1 /* 2 * Freescale i.MX23/i.MX28 clock setup code 3 * 4 * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> 5 * on behalf of DENX Software Engineering GmbH 6 * 7 * Based on code from LTIB: 8 * Copyright (C) 2010 Freescale Semiconductor, Inc. 9 * 10 * SPDX-License-Identifier: GPL-2.0+ 11 */ 12 13 #include <common.h> 14 #include <asm/errno.h> 15 #include <asm/io.h> 16 #include <asm/arch/clock.h> 17 #include <asm/arch/imx-regs.h> 18 19 /* 20 * The PLL frequency is 480MHz and XTAL frequency is 24MHz 21 * iMX23: datasheet section 4.2 22 * iMX28: datasheet section 10.2 23 */ 24 #define PLL_FREQ_KHZ 480000 25 #define PLL_FREQ_COEF 18 26 #define XTAL_FREQ_KHZ 24000 27 28 #define PLL_FREQ_MHZ (PLL_FREQ_KHZ / 1000) 29 #define XTAL_FREQ_MHZ (XTAL_FREQ_KHZ / 1000) 30 31 #if defined(CONFIG_MX23) 32 #define MXC_SSPCLK_MAX MXC_SSPCLK0 33 #elif defined(CONFIG_MX28) 34 #define MXC_SSPCLK_MAX MXC_SSPCLK3 35 #endif 36 37 static uint32_t mxs_get_pclk(void) 38 { 39 struct mxs_clkctrl_regs *clkctrl_regs = 40 (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; 41 42 uint32_t clkctrl, clkseq, div; 43 uint8_t clkfrac, frac; 44 45 clkctrl = readl(&clkctrl_regs->hw_clkctrl_cpu); 46 47 /* No support of fractional divider calculation */ 48 if (clkctrl & 49 (CLKCTRL_CPU_DIV_XTAL_FRAC_EN | CLKCTRL_CPU_DIV_CPU_FRAC_EN)) { 50 return 0; 51 } 52 53 clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq); 54 55 /* XTAL Path */ 56 if (clkseq & CLKCTRL_CLKSEQ_BYPASS_CPU) { 57 div = (clkctrl & CLKCTRL_CPU_DIV_XTAL_MASK) >> 58 CLKCTRL_CPU_DIV_XTAL_OFFSET; 59 return XTAL_FREQ_MHZ / div; 60 } 61 62 /* REF Path */ 63 clkfrac = readb(&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_CPU]); 64 frac = clkfrac & CLKCTRL_FRAC_FRAC_MASK; 65 div = clkctrl & CLKCTRL_CPU_DIV_CPU_MASK; 66 return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div; 67 } 68 69 static uint32_t mxs_get_hclk(void) 70 { 71 struct mxs_clkctrl_regs *clkctrl_regs = 72 (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; 73 74 uint32_t div; 75 uint32_t clkctrl; 76 77 clkctrl = readl(&clkctrl_regs->hw_clkctrl_hbus); 78 79 /* No support of fractional divider calculation */ 80 if (clkctrl & CLKCTRL_HBUS_DIV_FRAC_EN) 81 return 0; 82 83 div = clkctrl & CLKCTRL_HBUS_DIV_MASK; 84 return mxs_get_pclk() / div; 85 } 86 87 static uint32_t mxs_get_emiclk(void) 88 { 89 struct mxs_clkctrl_regs *clkctrl_regs = 90 (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; 91 92 uint32_t clkctrl, clkseq, div; 93 uint8_t clkfrac, frac; 94 95 clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq); 96 clkctrl = readl(&clkctrl_regs->hw_clkctrl_emi); 97 98 /* XTAL Path */ 99 if (clkseq & CLKCTRL_CLKSEQ_BYPASS_EMI) { 100 div = (clkctrl & CLKCTRL_EMI_DIV_XTAL_MASK) >> 101 CLKCTRL_EMI_DIV_XTAL_OFFSET; 102 return XTAL_FREQ_MHZ / div; 103 } 104 105 /* REF Path */ 106 clkfrac = readb(&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_EMI]); 107 frac = clkfrac & CLKCTRL_FRAC_FRAC_MASK; 108 div = clkctrl & CLKCTRL_EMI_DIV_EMI_MASK; 109 return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div; 110 } 111 112 static uint32_t mxs_get_gpmiclk(void) 113 { 114 struct mxs_clkctrl_regs *clkctrl_regs = 115 (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; 116 #if defined(CONFIG_MX23) 117 uint8_t *reg = 118 &clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_CPU]; 119 #elif defined(CONFIG_MX28) 120 uint8_t *reg = 121 &clkctrl_regs->hw_clkctrl_frac1[CLKCTRL_FRAC1_GPMI]; 122 #endif 123 uint32_t clkctrl, clkseq, div; 124 uint8_t clkfrac, frac; 125 126 clkseq = readl(&clkctrl_regs->hw_clkctrl_clkseq); 127 clkctrl = readl(&clkctrl_regs->hw_clkctrl_gpmi); 128 129 /* XTAL Path */ 130 if (clkseq & CLKCTRL_CLKSEQ_BYPASS_GPMI) { 131 div = clkctrl & CLKCTRL_GPMI_DIV_MASK; 132 return XTAL_FREQ_MHZ / div; 133 } 134 135 /* REF Path */ 136 clkfrac = readb(reg); 137 frac = clkfrac & CLKCTRL_FRAC_FRAC_MASK; 138 div = clkctrl & CLKCTRL_GPMI_DIV_MASK; 139 return (PLL_FREQ_MHZ * PLL_FREQ_COEF / frac) / div; 140 } 141 142 /* 143 * Set IO clock frequency, in kHz 144 */ 145 void mxs_set_ioclk(enum mxs_ioclock io, uint32_t freq) 146 { 147 struct mxs_clkctrl_regs *clkctrl_regs = 148 (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; 149 uint32_t div; 150 int io_reg; 151 152 if (freq == 0) 153 return; 154 155 if ((io < MXC_IOCLK0) || (io > MXC_IOCLK1)) 156 return; 157 158 div = (PLL_FREQ_KHZ * PLL_FREQ_COEF) / freq; 159 160 if (div < 18) 161 div = 18; 162 163 if (div > 35) 164 div = 35; 165 166 io_reg = CLKCTRL_FRAC0_IO0 - io; /* Register order is reversed */ 167 writeb(CLKCTRL_FRAC_CLKGATE, 168 &clkctrl_regs->hw_clkctrl_frac0_set[io_reg]); 169 writeb(CLKCTRL_FRAC_CLKGATE | (div & CLKCTRL_FRAC_FRAC_MASK), 170 &clkctrl_regs->hw_clkctrl_frac0[io_reg]); 171 writeb(CLKCTRL_FRAC_CLKGATE, 172 &clkctrl_regs->hw_clkctrl_frac0_clr[io_reg]); 173 } 174 175 /* 176 * Get IO clock, returns IO clock in kHz 177 */ 178 static uint32_t mxs_get_ioclk(enum mxs_ioclock io) 179 { 180 struct mxs_clkctrl_regs *clkctrl_regs = 181 (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; 182 uint8_t ret; 183 int io_reg; 184 185 if ((io < MXC_IOCLK0) || (io > MXC_IOCLK1)) 186 return 0; 187 188 io_reg = CLKCTRL_FRAC0_IO0 - io; /* Register order is reversed */ 189 190 ret = readb(&clkctrl_regs->hw_clkctrl_frac0[io_reg]) & 191 CLKCTRL_FRAC_FRAC_MASK; 192 193 return (PLL_FREQ_KHZ * PLL_FREQ_COEF) / ret; 194 } 195 196 /* 197 * Configure SSP clock frequency, in kHz 198 */ 199 void mxs_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal) 200 { 201 struct mxs_clkctrl_regs *clkctrl_regs = 202 (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; 203 uint32_t clk, clkreg; 204 205 if (ssp > MXC_SSPCLK_MAX) 206 return; 207 208 clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) + 209 (ssp * sizeof(struct mxs_register_32)); 210 211 clrbits_le32(clkreg, CLKCTRL_SSP_CLKGATE); 212 while (readl(clkreg) & CLKCTRL_SSP_CLKGATE) 213 ; 214 215 if (xtal) 216 clk = XTAL_FREQ_KHZ; 217 else 218 clk = mxs_get_ioclk(ssp >> 1); 219 220 if (freq > clk) 221 return; 222 223 /* Calculate the divider and cap it if necessary */ 224 clk /= freq; 225 if (clk > CLKCTRL_SSP_DIV_MASK) 226 clk = CLKCTRL_SSP_DIV_MASK; 227 228 clrsetbits_le32(clkreg, CLKCTRL_SSP_DIV_MASK, clk); 229 while (readl(clkreg) & CLKCTRL_SSP_BUSY) 230 ; 231 232 if (xtal) 233 writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp, 234 &clkctrl_regs->hw_clkctrl_clkseq_set); 235 else 236 writel(CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp, 237 &clkctrl_regs->hw_clkctrl_clkseq_clr); 238 } 239 240 /* 241 * Return SSP frequency, in kHz 242 */ 243 static uint32_t mxs_get_sspclk(enum mxs_sspclock ssp) 244 { 245 struct mxs_clkctrl_regs *clkctrl_regs = 246 (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; 247 uint32_t clkreg; 248 uint32_t clk, tmp; 249 250 if (ssp > MXC_SSPCLK_MAX) 251 return 0; 252 253 tmp = readl(&clkctrl_regs->hw_clkctrl_clkseq); 254 if (tmp & (CLKCTRL_CLKSEQ_BYPASS_SSP0 << ssp)) 255 return XTAL_FREQ_KHZ; 256 257 clkreg = (uint32_t)(&clkctrl_regs->hw_clkctrl_ssp0) + 258 (ssp * sizeof(struct mxs_register_32)); 259 260 tmp = readl(clkreg) & CLKCTRL_SSP_DIV_MASK; 261 262 if (tmp == 0) 263 return 0; 264 265 clk = mxs_get_ioclk(ssp >> 1); 266 267 return clk / tmp; 268 } 269 270 /* 271 * Set SSP/MMC bus frequency, in kHz) 272 */ 273 void mxs_set_ssp_busclock(unsigned int bus, uint32_t freq) 274 { 275 struct mxs_ssp_regs *ssp_regs; 276 const enum mxs_sspclock clk = mxs_ssp_clock_by_bus(bus); 277 const uint32_t sspclk = mxs_get_sspclk(clk); 278 uint32_t reg; 279 uint32_t divide, rate, tgtclk; 280 281 ssp_regs = mxs_ssp_regs_by_bus(bus); 282 283 /* 284 * SSP bit rate = SSPCLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)), 285 * CLOCK_DIVIDE has to be an even value from 2 to 254, and 286 * CLOCK_RATE could be any integer from 0 to 255. 287 */ 288 for (divide = 2; divide < 254; divide += 2) { 289 rate = sspclk / freq / divide; 290 if (rate <= 256) 291 break; 292 } 293 294 tgtclk = sspclk / divide / rate; 295 while (tgtclk > freq) { 296 rate++; 297 tgtclk = sspclk / divide / rate; 298 } 299 if (rate > 256) 300 rate = 256; 301 302 /* Always set timeout the maximum */ 303 reg = SSP_TIMING_TIMEOUT_MASK | 304 (divide << SSP_TIMING_CLOCK_DIVIDE_OFFSET) | 305 ((rate - 1) << SSP_TIMING_CLOCK_RATE_OFFSET); 306 writel(reg, &ssp_regs->hw_ssp_timing); 307 308 debug("SPI%d: Set freq rate to %d KHz (requested %d KHz)\n", 309 bus, tgtclk, freq); 310 } 311 312 void mxs_set_lcdclk(uint32_t freq) 313 { 314 struct mxs_clkctrl_regs *clkctrl_regs = 315 (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; 316 uint32_t fp, x, k_rest, k_best, x_best, tk; 317 int32_t k_best_l = 999, k_best_t = 0, x_best_l = 0xff, x_best_t = 0xff; 318 319 if (freq == 0) 320 return; 321 322 #if defined(CONFIG_MX23) 323 writel(CLKCTRL_CLKSEQ_BYPASS_PIX, &clkctrl_regs->hw_clkctrl_clkseq_clr); 324 #elif defined(CONFIG_MX28) 325 writel(CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF, &clkctrl_regs->hw_clkctrl_clkseq_clr); 326 #endif 327 328 /* 329 * / 18 \ 1 1 330 * freq kHz = | 480000000 Hz * -- | * --- * ------ 331 * \ x / k 1000 332 * 333 * 480000000 Hz 18 334 * ------------ * -- 335 * freq kHz x 336 * k = ------------------- 337 * 1000 338 */ 339 340 fp = ((PLL_FREQ_KHZ * 1000) / freq) * 18; 341 342 for (x = 18; x <= 35; x++) { 343 tk = fp / x; 344 if ((tk / 1000 == 0) || (tk / 1000 > 255)) 345 continue; 346 347 k_rest = tk % 1000; 348 349 if (k_rest < (k_best_l % 1000)) { 350 k_best_l = tk; 351 x_best_l = x; 352 } 353 354 if (k_rest > (k_best_t % 1000)) { 355 k_best_t = tk; 356 x_best_t = x; 357 } 358 } 359 360 if (1000 - (k_best_t % 1000) > (k_best_l % 1000)) { 361 k_best = k_best_l; 362 x_best = x_best_l; 363 } else { 364 k_best = k_best_t; 365 x_best = x_best_t; 366 } 367 368 k_best /= 1000; 369 370 #if defined(CONFIG_MX23) 371 writeb(CLKCTRL_FRAC_CLKGATE, 372 &clkctrl_regs->hw_clkctrl_frac0_set[CLKCTRL_FRAC0_PIX]); 373 writeb(CLKCTRL_FRAC_CLKGATE | (x_best & CLKCTRL_FRAC_FRAC_MASK), 374 &clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_PIX]); 375 writeb(CLKCTRL_FRAC_CLKGATE, 376 &clkctrl_regs->hw_clkctrl_frac0_clr[CLKCTRL_FRAC0_PIX]); 377 378 writel(CLKCTRL_PIX_CLKGATE, 379 &clkctrl_regs->hw_clkctrl_pix_set); 380 clrsetbits_le32(&clkctrl_regs->hw_clkctrl_pix, 381 CLKCTRL_PIX_DIV_MASK | CLKCTRL_PIX_CLKGATE, 382 k_best << CLKCTRL_PIX_DIV_OFFSET); 383 384 while (readl(&clkctrl_regs->hw_clkctrl_pix) & CLKCTRL_PIX_BUSY) 385 ; 386 #elif defined(CONFIG_MX28) 387 writeb(CLKCTRL_FRAC_CLKGATE, 388 &clkctrl_regs->hw_clkctrl_frac1_set[CLKCTRL_FRAC1_PIX]); 389 writeb(CLKCTRL_FRAC_CLKGATE | (x_best & CLKCTRL_FRAC_FRAC_MASK), 390 &clkctrl_regs->hw_clkctrl_frac1[CLKCTRL_FRAC1_PIX]); 391 writeb(CLKCTRL_FRAC_CLKGATE, 392 &clkctrl_regs->hw_clkctrl_frac1_clr[CLKCTRL_FRAC1_PIX]); 393 394 writel(CLKCTRL_DIS_LCDIF_CLKGATE, 395 &clkctrl_regs->hw_clkctrl_lcdif_set); 396 clrsetbits_le32(&clkctrl_regs->hw_clkctrl_lcdif, 397 CLKCTRL_DIS_LCDIF_DIV_MASK | CLKCTRL_DIS_LCDIF_CLKGATE, 398 k_best << CLKCTRL_DIS_LCDIF_DIV_OFFSET); 399 400 while (readl(&clkctrl_regs->hw_clkctrl_lcdif) & CLKCTRL_DIS_LCDIF_BUSY) 401 ; 402 #endif 403 } 404 405 uint32_t mxc_get_clock(enum mxc_clock clk) 406 { 407 switch (clk) { 408 case MXC_ARM_CLK: 409 return mxs_get_pclk() * 1000000; 410 case MXC_GPMI_CLK: 411 return mxs_get_gpmiclk() * 1000000; 412 case MXC_AHB_CLK: 413 case MXC_IPG_CLK: 414 return mxs_get_hclk() * 1000000; 415 case MXC_EMI_CLK: 416 return mxs_get_emiclk(); 417 case MXC_IO0_CLK: 418 return mxs_get_ioclk(MXC_IOCLK0); 419 case MXC_IO1_CLK: 420 return mxs_get_ioclk(MXC_IOCLK1); 421 case MXC_XTAL_CLK: 422 return XTAL_FREQ_KHZ * 1000; 423 case MXC_SSP0_CLK: 424 return mxs_get_sspclk(MXC_SSPCLK0); 425 #ifdef CONFIG_MX28 426 case MXC_SSP1_CLK: 427 return mxs_get_sspclk(MXC_SSPCLK1); 428 case MXC_SSP2_CLK: 429 return mxs_get_sspclk(MXC_SSPCLK2); 430 case MXC_SSP3_CLK: 431 return mxs_get_sspclk(MXC_SSPCLK3); 432 #endif 433 } 434 435 return 0; 436 } 437