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