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