1 /* 2 * (C) Copyright 2015, Freescale Semiconductor, Inc. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <asm/io.h> 8 #include <asm/arch/imx-regs.h> 9 #include <asm/arch/mc_cgm_regs.h> 10 #include <asm/arch/mc_me_regs.h> 11 #include <asm/arch/clock.h> 12 13 /* 14 * Select the clock reference for required pll. 15 * pll - ARM_PLL, PERIPH_PLL, ENET_PLL, DDR_PLL, VIDEO_PLL. 16 * refclk_freq - input referece clock frequency (FXOSC - 40 MHZ, FIRC - 48 MHZ) 17 */ 18 static int select_pll_source_clk(enum pll_type pll, u32 refclk_freq) 19 { 20 u32 clk_src; 21 u32 pll_idx; 22 volatile struct src *src = (struct src *)SRC_SOC_BASE_ADDR; 23 24 /* select the pll clock source */ 25 switch (refclk_freq) { 26 case FIRC_CLK_FREQ: 27 clk_src = SRC_GPR1_FIRC_CLK_SOURCE; 28 break; 29 case XOSC_CLK_FREQ: 30 clk_src = SRC_GPR1_XOSC_CLK_SOURCE; 31 break; 32 default: 33 /* The clock frequency for the source clock is unknown */ 34 return -1; 35 } 36 /* 37 * The hardware definition is not uniform, it has to calculate again 38 * the recurrence formula. 39 */ 40 switch (pll) { 41 case PERIPH_PLL: 42 pll_idx = 3; 43 break; 44 case ENET_PLL: 45 pll_idx = 1; 46 break; 47 case DDR_PLL: 48 pll_idx = 2;; 49 break; 50 default: 51 pll_idx = pll; 52 } 53 54 writel(readl(&src->gpr1) | SRC_GPR1_PLL_SOURCE(pll_idx, clk_src), 55 &src->gpr1); 56 57 return 0; 58 } 59 60 static void entry_to_target_mode(u32 mode) 61 { 62 writel(mode | MC_ME_MCTL_KEY, MC_ME_MCTL); 63 writel(mode | MC_ME_MCTL_INVERTEDKEY, MC_ME_MCTL); 64 while ((readl(MC_ME_GS) & MC_ME_GS_S_MTRANS) != 0x00000000) ; 65 } 66 67 /* 68 * Program the pll according to the input parameters. 69 * pll - ARM_PLL, PERIPH_PLL, ENET_PLL, DDR_PLL, VIDEO_PLL. 70 * refclk_freq - input reference clock frequency (FXOSC - 40 MHZ, FIRC - 48 MHZ) 71 * freq - expected output frequency for PHY0 72 * freq1 - expected output frequency for PHY1 73 * dfs_nr - number of DFS modules for current PLL 74 * dfs - array with the activation dfs field, mfn and mfi 75 * plldv_prediv - divider of clkfreq_ref 76 * plldv_mfd - loop multiplication factor divider 77 * pllfd_mfn - numerator loop multiplication factor divider 78 * Please consult the PLLDIG chapter of platform manual 79 * before to use this function. 80 *) 81 */ 82 static int program_pll(enum pll_type pll, u32 refclk_freq, u32 freq0, u32 freq1, 83 u32 dfs_nr, u32 dfs[][DFS_PARAMS_Nr], u32 plldv_prediv, 84 u32 plldv_mfd, u32 pllfd_mfn) 85 { 86 u32 i, rfdphi1, rfdphi, dfs_on = 0, fvco; 87 88 /* 89 * This formula is from platform reference manual (Rev. 1, 6/2015), PLLDIG chapter. 90 */ 91 fvco = 92 (refclk_freq / plldv_prediv) * (plldv_mfd + 93 pllfd_mfn / (float)20480); 94 95 /* 96 * VCO should have value in [ PLL_MIN_FREQ, PLL_MAX_FREQ ]. Please consult 97 * the platform DataSheet in order to determine the allowed values. 98 */ 99 100 if (fvco < PLL_MIN_FREQ || fvco > PLL_MAX_FREQ) { 101 return -1; 102 } 103 104 if (select_pll_source_clk(pll, refclk_freq) < 0) { 105 return -1; 106 } 107 108 rfdphi = fvco / freq0; 109 110 rfdphi1 = (freq1 == 0) ? 0 : fvco / freq1; 111 112 writel(PLLDIG_PLLDV_RFDPHI1_SET(rfdphi1) | 113 PLLDIG_PLLDV_RFDPHI_SET(rfdphi) | 114 PLLDIG_PLLDV_PREDIV_SET(plldv_prediv) | 115 PLLDIG_PLLDV_MFD(plldv_mfd), PLLDIG_PLLDV(pll)); 116 117 writel(readl(PLLDIG_PLLFD(pll)) | PLLDIG_PLLFD_MFN_SET(pllfd_mfn) | 118 PLLDIG_PLLFD_SMDEN, PLLDIG_PLLFD(pll)); 119 120 /* switch on the pll in current mode */ 121 writel(readl(MC_ME_RUNn_MC(0)) | MC_ME_RUNMODE_MC_PLL(pll), 122 MC_ME_RUNn_MC(0)); 123 124 entry_to_target_mode(MC_ME_MCTL_RUN0); 125 126 /* Only ARM_PLL, ENET_PLL and DDR_PLL */ 127 if ((pll == ARM_PLL) || (pll == ENET_PLL) || (pll == DDR_PLL)) { 128 /* DFS clk enable programming */ 129 writel(DFS_CTRL_DLL_RESET, DFS_CTRL(pll)); 130 131 writel(DFS_DLLPRG1_CPICTRL_SET(0x5) | 132 DFS_DLLPRG1_VSETTLCTRL_SET(0x1) | 133 DFS_DLLPRG1_CALBYPEN_SET(0x0) | 134 DFS_DLLPRG1_DACIN_SET(0x1) | DFS_DLLPRG1_LCKWT_SET(0x0) | 135 DFS_DLLPRG1_V2IGC_SET(0x5), DFS_DLLPRG1(pll)); 136 137 for (i = 0; i < dfs_nr; i++) { 138 if (dfs[i][0]) { 139 writel(DFS_DVPORTn_MFI_SET(dfs[i][2]) | 140 DFS_DVPORTn_MFN_SET(dfs[i][1]), 141 DFS_DVPORTn(pll, i)); 142 dfs_on |= (dfs[i][0] << i); 143 } 144 } 145 146 writel(readl(DFS_CTRL(pll)) & ~DFS_CTRL_DLL_RESET, 147 DFS_CTRL(pll)); 148 writel(readl(DFS_PORTRESET(pll)) & 149 ~DFS_PORTRESET_PORTRESET_SET(dfs_on), 150 DFS_PORTRESET(pll)); 151 while ((readl(DFS_PORTSR(pll)) & dfs_on) != dfs_on) ; 152 } 153 154 entry_to_target_mode(MC_ME_MCTL_RUN0); 155 156 return 0; 157 158 } 159 160 static void aux_source_clk_config(uintptr_t cgm_addr, u8 ac, u32 source) 161 { 162 /* select the clock source */ 163 writel(MC_CGM_ACn_SEL_SET(source), CGM_ACn_SC(cgm_addr, ac)); 164 } 165 166 static void aux_div_clk_config(uintptr_t cgm_addr, u8 ac, u8 dc, u32 divider) 167 { 168 /* set the divider */ 169 writel(MC_CGM_ACn_DCm_DE | MC_CGM_ACn_DCm_PREDIV(divider), 170 CGM_ACn_DCm(cgm_addr, ac, dc)); 171 } 172 173 static void setup_sys_clocks(void) 174 { 175 176 /* set ARM PLL DFS 1 as SYSCLK */ 177 writel((readl(MC_ME_RUNn_MC(0)) & ~MC_ME_RUNMODE_MC_SYSCLK_MASK) | 178 MC_ME_RUNMODE_MC_SYSCLK(0x2), MC_ME_RUNn_MC(0)); 179 180 entry_to_target_mode(MC_ME_MCTL_RUN0); 181 182 /* select sysclks ARMPLL, ARMPLLDFS2, ARMPLLDFS3 */ 183 writel(MC_ME_RUNMODE_SEC_CC_I_SYSCLK 184 (0x2, 185 MC_ME_RUNMODE_SEC_CC_I_SYSCLK1_OFFSET) | 186 MC_ME_RUNMODE_SEC_CC_I_SYSCLK(0x2, 187 MC_ME_RUNMODE_SEC_CC_I_SYSCLK2_OFFSET) 188 | MC_ME_RUNMODE_SEC_CC_I_SYSCLK(0x2, 189 MC_ME_RUNMODE_SEC_CC_I_SYSCLK3_OFFSET), 190 MC_ME_RUNn_SEC_CC_I(0)); 191 192 /* setup the sys clock divider for CORE_CLK (1000MHz) */ 193 writel(MC_CGM_SC_DCn_DE | MC_CGM_SC_DCn_PREDIV(0x0), 194 CGM_SC_DCn(MC_CGM1_BASE_ADDR, 0)); 195 196 /* setup the sys clock divider for CORE2_CLK (500MHz) */ 197 writel(MC_CGM_SC_DCn_DE | MC_CGM_SC_DCn_PREDIV(0x1), 198 CGM_SC_DCn(MC_CGM1_BASE_ADDR, 1)); 199 /* setup the sys clock divider for SYS3_CLK (266 MHz) */ 200 writel(MC_CGM_SC_DCn_DE | MC_CGM_SC_DCn_PREDIV(0x0), 201 CGM_SC_DCn(MC_CGM0_BASE_ADDR, 0)); 202 203 /* setup the sys clock divider for SYS6_CLK (133 Mhz) */ 204 writel(MC_CGM_SC_DCn_DE | MC_CGM_SC_DCn_PREDIV(0x1), 205 CGM_SC_DCn(MC_CGM0_BASE_ADDR, 1)); 206 207 entry_to_target_mode(MC_ME_MCTL_RUN0); 208 209 } 210 211 static void setup_aux_clocks(void) 212 { 213 /* 214 * setup the aux clock divider for PERI_CLK 215 * (source: PERIPH_PLL_PHI_0/5, PERI_CLK - 80 MHz) 216 */ 217 aux_source_clk_config(MC_CGM0_BASE_ADDR, 5, MC_CGM_ACn_SEL_PERPLLDIVX); 218 aux_div_clk_config(MC_CGM0_BASE_ADDR, 5, 0, 4); 219 220 /* setup the aux clock divider for LIN_CLK (40MHz) */ 221 aux_source_clk_config(MC_CGM0_BASE_ADDR, 3, MC_CGM_ACn_SEL_PERPLLDIVX); 222 aux_div_clk_config(MC_CGM0_BASE_ADDR, 3, 0, 1); 223 224 /* setup the aux clock divider for ENET_TIME_CLK (50MHz) */ 225 aux_source_clk_config(MC_CGM0_BASE_ADDR, 7, MC_CGM_ACn_SEL_ENETPLL); 226 aux_div_clk_config(MC_CGM0_BASE_ADDR, 7, 1, 9); 227 228 /* setup the aux clock divider for ENET_CLK (50MHz) */ 229 aux_source_clk_config(MC_CGM2_BASE_ADDR, 2, MC_CGM_ACn_SEL_ENETPLL); 230 aux_div_clk_config(MC_CGM2_BASE_ADDR, 2, 0, 9); 231 232 /* setup the aux clock divider for SDHC_CLK (50 MHz). */ 233 aux_source_clk_config(MC_CGM0_BASE_ADDR, 15, MC_CGM_ACn_SEL_ENETPLL); 234 aux_div_clk_config(MC_CGM0_BASE_ADDR, 15, 0, 9); 235 236 /* setup the aux clock divider for DDR_CLK (533MHz) and APEX_SYS_CLK (266MHz) */ 237 aux_source_clk_config(MC_CGM0_BASE_ADDR, 8, MC_CGM_ACn_SEL_DDRPLL); 238 aux_div_clk_config(MC_CGM0_BASE_ADDR, 8, 0, 0); 239 /* setup the aux clock divider for DDR4_CLK (133,25MHz) */ 240 aux_div_clk_config(MC_CGM0_BASE_ADDR, 8, 1, 3); 241 242 entry_to_target_mode(MC_ME_MCTL_RUN0); 243 244 } 245 246 static void enable_modules_clock(void) 247 { 248 /* PIT0 */ 249 writeb(MC_ME_PCTLn_RUNPCm(0), MC_ME_PCTL58); 250 /* PIT1 */ 251 writeb(MC_ME_PCTLn_RUNPCm(0), MC_ME_PCTL170); 252 /* LINFLEX0 */ 253 writeb(MC_ME_PCTLn_RUNPCm(0), MC_ME_PCTL83); 254 /* LINFLEX1 */ 255 writeb(MC_ME_PCTLn_RUNPCm(0), MC_ME_PCTL188); 256 /* ENET */ 257 writeb(MC_ME_PCTLn_RUNPCm(0), MC_ME_PCTL50); 258 /* SDHC */ 259 writeb(MC_ME_PCTLn_RUNPCm(0), MC_ME_PCTL93); 260 /* IIC0 */ 261 writeb(MC_ME_PCTLn_RUNPCm(0), MC_ME_PCTL81); 262 /* IIC1 */ 263 writeb(MC_ME_PCTLn_RUNPCm(0), MC_ME_PCTL184); 264 /* IIC2 */ 265 writeb(MC_ME_PCTLn_RUNPCm(0), MC_ME_PCTL186); 266 /* MMDC0 */ 267 writeb(MC_ME_PCTLn_RUNPCm(0), MC_ME_PCTL54); 268 /* MMDC1 */ 269 writeb(MC_ME_PCTLn_RUNPCm(0), MC_ME_PCTL162); 270 271 entry_to_target_mode(MC_ME_MCTL_RUN0); 272 } 273 274 void clock_init(void) 275 { 276 unsigned int arm_dfs[ARM_PLL_PHI1_DFS_Nr][DFS_PARAMS_Nr] = { 277 {ARM_PLL_PHI1_DFS1_EN, ARM_PLL_PHI1_DFS1_MFN, 278 ARM_PLL_PHI1_DFS1_MFI}, 279 {ARM_PLL_PHI1_DFS2_EN, ARM_PLL_PHI1_DFS2_MFN, 280 ARM_PLL_PHI1_DFS2_MFI}, 281 {ARM_PLL_PHI1_DFS3_EN, ARM_PLL_PHI1_DFS3_MFN, 282 ARM_PLL_PHI1_DFS3_MFI} 283 }; 284 285 unsigned int enet_dfs[ENET_PLL_PHI1_DFS_Nr][DFS_PARAMS_Nr] = { 286 {ENET_PLL_PHI1_DFS1_EN, ENET_PLL_PHI1_DFS1_MFN, 287 ENET_PLL_PHI1_DFS1_MFI}, 288 {ENET_PLL_PHI1_DFS2_EN, ENET_PLL_PHI1_DFS2_MFN, 289 ENET_PLL_PHI1_DFS2_MFI}, 290 {ENET_PLL_PHI1_DFS3_EN, ENET_PLL_PHI1_DFS3_MFN, 291 ENET_PLL_PHI1_DFS3_MFI}, 292 {ENET_PLL_PHI1_DFS4_EN, ENET_PLL_PHI1_DFS4_MFN, 293 ENET_PLL_PHI1_DFS4_MFI} 294 }; 295 296 unsigned int ddr_dfs[DDR_PLL_PHI1_DFS_Nr][DFS_PARAMS_Nr] = { 297 {DDR_PLL_PHI1_DFS1_EN, DDR_PLL_PHI1_DFS1_MFN, 298 DDR_PLL_PHI1_DFS1_MFI}, 299 {DDR_PLL_PHI1_DFS2_EN, DDR_PLL_PHI1_DFS2_MFN, 300 DDR_PLL_PHI1_DFS2_MFI}, 301 {DDR_PLL_PHI1_DFS3_EN, DDR_PLL_PHI1_DFS3_MFN, 302 DDR_PLL_PHI1_DFS3_MFI} 303 }; 304 305 writel(MC_ME_RUN_PCn_DRUN | MC_ME_RUN_PCn_RUN0 | MC_ME_RUN_PCn_RUN1 | 306 MC_ME_RUN_PCn_RUN2 | MC_ME_RUN_PCn_RUN3, MC_ME_RUN_PCn(0)); 307 308 /* turn on FXOSC */ 309 writel(MC_ME_RUNMODE_MC_MVRON | MC_ME_RUNMODE_MC_XOSCON | 310 MC_ME_RUNMODE_MC_FIRCON | MC_ME_RUNMODE_MC_SYSCLK(0x1), 311 MC_ME_RUNn_MC(0)); 312 313 entry_to_target_mode(MC_ME_MCTL_RUN0); 314 315 program_pll(ARM_PLL, XOSC_CLK_FREQ, ARM_PLL_PHI0_FREQ, 316 ARM_PLL_PHI1_FREQ, ARM_PLL_PHI1_DFS_Nr, arm_dfs, 317 ARM_PLL_PLLDV_PREDIV, ARM_PLL_PLLDV_MFD, ARM_PLL_PLLDV_MFN); 318 319 setup_sys_clocks(); 320 321 program_pll(PERIPH_PLL, XOSC_CLK_FREQ, PERIPH_PLL_PHI0_FREQ, 322 PERIPH_PLL_PHI1_FREQ, PERIPH_PLL_PHI1_DFS_Nr, NULL, 323 PERIPH_PLL_PLLDV_PREDIV, PERIPH_PLL_PLLDV_MFD, 324 PERIPH_PLL_PLLDV_MFN); 325 326 program_pll(ENET_PLL, XOSC_CLK_FREQ, ENET_PLL_PHI0_FREQ, 327 ENET_PLL_PHI1_FREQ, ENET_PLL_PHI1_DFS_Nr, enet_dfs, 328 ENET_PLL_PLLDV_PREDIV, ENET_PLL_PLLDV_MFD, 329 ENET_PLL_PLLDV_MFN); 330 331 program_pll(DDR_PLL, XOSC_CLK_FREQ, DDR_PLL_PHI0_FREQ, 332 DDR_PLL_PHI1_FREQ, DDR_PLL_PHI1_DFS_Nr, ddr_dfs, 333 DDR_PLL_PLLDV_PREDIV, DDR_PLL_PLLDV_MFD, DDR_PLL_PLLDV_MFN); 334 335 program_pll(VIDEO_PLL, XOSC_CLK_FREQ, VIDEO_PLL_PHI0_FREQ, 336 VIDEO_PLL_PHI1_FREQ, VIDEO_PLL_PHI1_DFS_Nr, NULL, 337 VIDEO_PLL_PLLDV_PREDIV, VIDEO_PLL_PLLDV_MFD, 338 VIDEO_PLL_PLLDV_MFN); 339 340 setup_aux_clocks(); 341 342 enable_modules_clock(); 343 344 } 345