1 /* 2 * linux/arch/arm/mach-omap2/clock.c 3 * 4 * Copyright (C) 2005 Texas Instruments Inc. 5 * Richard Woodruff <r-woodruff2@ti.com> 6 * Created for OMAP2. 7 * 8 * Cleaned up and modified to use omap shared clock framework by 9 * Tony Lindgren <tony@atomide.com> 10 * 11 * Based on omap1 clock.c, Copyright (C) 2004 - 2005 Nokia corporation 12 * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> 13 * 14 * This program is free software; you can redistribute it and/or modify 15 * it under the terms of the GNU General Public License version 2 as 16 * published by the Free Software Foundation. 17 */ 18 #include <linux/config.h> 19 #include <linux/module.h> 20 #include <linux/kernel.h> 21 #include <linux/device.h> 22 #include <linux/list.h> 23 #include <linux/errno.h> 24 #include <linux/delay.h> 25 #include <linux/clk.h> 26 27 #include <asm/io.h> 28 29 #include <asm/arch/clock.h> 30 #include <asm/arch/sram.h> 31 32 #include "prcm-regs.h" 33 #include "memory.h" 34 #include "clock.h" 35 36 //#define DOWN_VARIABLE_DPLL 1 /* Experimental */ 37 38 static struct prcm_config *curr_prcm_set; 39 static u32 curr_perf_level = PRCM_FULL_SPEED; 40 41 /*------------------------------------------------------------------------- 42 * Omap2 specific clock functions 43 *-------------------------------------------------------------------------*/ 44 45 /* Recalculate SYST_CLK */ 46 static void omap2_sys_clk_recalc(struct clk * clk) 47 { 48 u32 div = PRCM_CLKSRC_CTRL; 49 div &= (1 << 7) | (1 << 6); /* Test if ext clk divided by 1 or 2 */ 50 div >>= clk->rate_offset; 51 clk->rate = (clk->parent->rate / div); 52 propagate_rate(clk); 53 } 54 55 static u32 omap2_get_dpll_rate(struct clk * tclk) 56 { 57 long long dpll_clk; 58 int dpll_mult, dpll_div, amult; 59 60 dpll_mult = (CM_CLKSEL1_PLL >> 12) & 0x03ff; /* 10 bits */ 61 dpll_div = (CM_CLKSEL1_PLL >> 8) & 0x0f; /* 4 bits */ 62 dpll_clk = (long long)tclk->parent->rate * dpll_mult; 63 do_div(dpll_clk, dpll_div + 1); 64 amult = CM_CLKSEL2_PLL & 0x3; 65 dpll_clk *= amult; 66 67 return dpll_clk; 68 } 69 70 static void omap2_followparent_recalc(struct clk *clk) 71 { 72 followparent_recalc(clk); 73 } 74 75 static void omap2_propagate_rate(struct clk * clk) 76 { 77 if (!(clk->flags & RATE_FIXED)) 78 clk->rate = clk->parent->rate; 79 80 propagate_rate(clk); 81 } 82 83 /* Enable an APLL if off */ 84 static void omap2_clk_fixed_enable(struct clk *clk) 85 { 86 u32 cval, i=0; 87 88 if (clk->enable_bit == 0xff) /* Parent will do it */ 89 return; 90 91 cval = CM_CLKEN_PLL; 92 93 if ((cval & (0x3 << clk->enable_bit)) == (0x3 << clk->enable_bit)) 94 return; 95 96 cval &= ~(0x3 << clk->enable_bit); 97 cval |= (0x3 << clk->enable_bit); 98 CM_CLKEN_PLL = cval; 99 100 if (clk == &apll96_ck) 101 cval = (1 << 8); 102 else if (clk == &apll54_ck) 103 cval = (1 << 6); 104 105 while (!CM_IDLEST_CKGEN & cval) { /* Wait for lock */ 106 ++i; 107 udelay(1); 108 if (i == 100000) 109 break; 110 } 111 } 112 113 /* Enables clock without considering parent dependencies or use count 114 * REVISIT: Maybe change this to use clk->enable like on omap1? 115 */ 116 static int _omap2_clk_enable(struct clk * clk) 117 { 118 u32 regval32; 119 120 if (clk->flags & ALWAYS_ENABLED) 121 return 0; 122 123 if (unlikely(clk->enable_reg == 0)) { 124 printk(KERN_ERR "clock.c: Enable for %s without enable code\n", 125 clk->name); 126 return 0; 127 } 128 129 if (clk->enable_reg == (void __iomem *)&CM_CLKEN_PLL) { 130 omap2_clk_fixed_enable(clk); 131 return 0; 132 } 133 134 regval32 = __raw_readl(clk->enable_reg); 135 regval32 |= (1 << clk->enable_bit); 136 __raw_writel(regval32, clk->enable_reg); 137 138 return 0; 139 } 140 141 /* Stop APLL */ 142 static void omap2_clk_fixed_disable(struct clk *clk) 143 { 144 u32 cval; 145 146 if(clk->enable_bit == 0xff) /* let parent off do it */ 147 return; 148 149 cval = CM_CLKEN_PLL; 150 cval &= ~(0x3 << clk->enable_bit); 151 CM_CLKEN_PLL = cval; 152 } 153 154 /* Disables clock without considering parent dependencies or use count */ 155 static void _omap2_clk_disable(struct clk *clk) 156 { 157 u32 regval32; 158 159 if (clk->enable_reg == 0) 160 return; 161 162 if (clk->enable_reg == (void __iomem *)&CM_CLKEN_PLL) { 163 omap2_clk_fixed_disable(clk); 164 return; 165 } 166 167 regval32 = __raw_readl(clk->enable_reg); 168 regval32 &= ~(1 << clk->enable_bit); 169 __raw_writel(regval32, clk->enable_reg); 170 } 171 172 static int omap2_clk_enable(struct clk *clk) 173 { 174 int ret = 0; 175 176 if (clk->usecount++ == 0) { 177 if (likely((u32)clk->parent)) 178 ret = omap2_clk_enable(clk->parent); 179 180 if (unlikely(ret != 0)) { 181 clk->usecount--; 182 return ret; 183 } 184 185 ret = _omap2_clk_enable(clk); 186 187 if (unlikely(ret != 0) && clk->parent) { 188 omap2_clk_disable(clk->parent); 189 clk->usecount--; 190 } 191 } 192 193 return ret; 194 } 195 196 static void omap2_clk_disable(struct clk *clk) 197 { 198 if (clk->usecount > 0 && !(--clk->usecount)) { 199 _omap2_clk_disable(clk); 200 if (likely((u32)clk->parent)) 201 omap2_clk_disable(clk->parent); 202 } 203 } 204 205 /* 206 * Uses the current prcm set to tell if a rate is valid. 207 * You can go slower, but not faster within a given rate set. 208 */ 209 static u32 omap2_dpll_round_rate(unsigned long target_rate) 210 { 211 u32 high, low; 212 213 if ((CM_CLKSEL2_PLL & 0x3) == 1) { /* DPLL clockout */ 214 high = curr_prcm_set->dpll_speed * 2; 215 low = curr_prcm_set->dpll_speed; 216 } else { /* DPLL clockout x 2 */ 217 high = curr_prcm_set->dpll_speed; 218 low = curr_prcm_set->dpll_speed / 2; 219 } 220 221 #ifdef DOWN_VARIABLE_DPLL 222 if (target_rate > high) 223 return high; 224 else 225 return target_rate; 226 #else 227 if (target_rate > low) 228 return high; 229 else 230 return low; 231 #endif 232 233 } 234 235 /* 236 * Used for clocks that are part of CLKSEL_xyz governed clocks. 237 * REVISIT: Maybe change to use clk->enable() functions like on omap1? 238 */ 239 static void omap2_clksel_recalc(struct clk * clk) 240 { 241 u32 fixed = 0, div = 0; 242 243 if (clk == &dpll_ck) { 244 clk->rate = omap2_get_dpll_rate(clk); 245 fixed = 1; 246 div = 0; 247 } 248 249 if (clk == &iva1_mpu_int_ifck) { 250 div = 2; 251 fixed = 1; 252 } 253 254 if ((clk == &dss1_fck) && ((CM_CLKSEL1_CORE & (0x1f << 8)) == 0)) { 255 clk->rate = sys_ck.rate; 256 return; 257 } 258 259 if (!fixed) { 260 div = omap2_clksel_get_divisor(clk); 261 if (div == 0) 262 return; 263 } 264 265 if (div != 0) { 266 if (unlikely(clk->rate == clk->parent->rate / div)) 267 return; 268 clk->rate = clk->parent->rate / div; 269 } 270 271 if (unlikely(clk->flags & RATE_PROPAGATES)) 272 propagate_rate(clk); 273 } 274 275 /* 276 * Finds best divider value in an array based on the source and target 277 * rates. The divider array must be sorted with smallest divider first. 278 */ 279 static inline u32 omap2_divider_from_table(u32 size, u32 *div_array, 280 u32 src_rate, u32 tgt_rate) 281 { 282 int i, test_rate; 283 284 if (div_array == NULL) 285 return ~1; 286 287 for (i=0; i < size; i++) { 288 test_rate = src_rate / *div_array; 289 if (test_rate <= tgt_rate) 290 return *div_array; 291 ++div_array; 292 } 293 294 return ~0; /* No acceptable divider */ 295 } 296 297 /* 298 * Find divisor for the given clock and target rate. 299 * 300 * Note that this will not work for clocks which are part of CONFIG_PARTICIPANT, 301 * they are only settable as part of virtual_prcm set. 302 */ 303 static u32 omap2_clksel_round_rate(struct clk *tclk, u32 target_rate, 304 u32 *new_div) 305 { 306 u32 gfx_div[] = {2, 3, 4}; 307 u32 sysclkout_div[] = {1, 2, 4, 8, 16}; 308 u32 dss1_div[] = {1, 2, 3, 4, 5, 6, 8, 9, 12, 16}; 309 u32 vylnq_div[] = {1, 2, 3, 4, 6, 8, 9, 12, 16, 18}; 310 u32 best_div = ~0, asize = 0; 311 u32 *div_array = NULL; 312 313 switch (tclk->flags & SRC_RATE_SEL_MASK) { 314 case CM_GFX_SEL1: 315 asize = 3; 316 div_array = gfx_div; 317 break; 318 case CM_PLL_SEL1: 319 return omap2_dpll_round_rate(target_rate); 320 case CM_SYSCLKOUT_SEL1: 321 asize = 5; 322 div_array = sysclkout_div; 323 break; 324 case CM_CORE_SEL1: 325 if(tclk == &dss1_fck){ 326 if(tclk->parent == &core_ck){ 327 asize = 10; 328 div_array = dss1_div; 329 } else { 330 *new_div = 0; /* fixed clk */ 331 return(tclk->parent->rate); 332 } 333 } else if((tclk == &vlynq_fck) && cpu_is_omap2420()){ 334 if(tclk->parent == &core_ck){ 335 asize = 10; 336 div_array = vylnq_div; 337 } else { 338 *new_div = 0; /* fixed clk */ 339 return(tclk->parent->rate); 340 } 341 } 342 break; 343 } 344 345 best_div = omap2_divider_from_table(asize, div_array, 346 tclk->parent->rate, target_rate); 347 if (best_div == ~0){ 348 *new_div = 1; 349 return best_div; /* signal error */ 350 } 351 352 *new_div = best_div; 353 return (tclk->parent->rate / best_div); 354 } 355 356 /* Given a clock and a rate apply a clock specific rounding function */ 357 static long omap2_clk_round_rate(struct clk *clk, unsigned long rate) 358 { 359 u32 new_div = 0; 360 int valid_rate; 361 362 if (clk->flags & RATE_FIXED) 363 return clk->rate; 364 365 if (clk->flags & RATE_CKCTL) { 366 valid_rate = omap2_clksel_round_rate(clk, rate, &new_div); 367 return valid_rate; 368 } 369 370 if (clk->round_rate != 0) 371 return clk->round_rate(clk, rate); 372 373 return clk->rate; 374 } 375 376 /* 377 * Check the DLL lock state, and return tue if running in unlock mode. 378 * This is needed to compenste for the shifted DLL value in unlock mode. 379 */ 380 static u32 omap2_dll_force_needed(void) 381 { 382 u32 dll_state = SDRC_DLLA_CTRL; /* dlla and dllb are a set */ 383 384 if ((dll_state & (1 << 2)) == (1 << 2)) 385 return 1; 386 else 387 return 0; 388 } 389 390 static u32 omap2_reprogram_sdrc(u32 level, u32 force) 391 { 392 u32 slow_dll_ctrl, fast_dll_ctrl, m_type; 393 u32 prev = curr_perf_level, flags; 394 395 if ((curr_perf_level == level) && !force) 396 return prev; 397 398 m_type = omap2_memory_get_type(); 399 slow_dll_ctrl = omap2_memory_get_slow_dll_ctrl(); 400 fast_dll_ctrl = omap2_memory_get_fast_dll_ctrl(); 401 402 if (level == PRCM_HALF_SPEED) { 403 local_irq_save(flags); 404 PRCM_VOLTSETUP = 0xffff; 405 omap2_sram_reprogram_sdrc(PRCM_HALF_SPEED, 406 slow_dll_ctrl, m_type); 407 curr_perf_level = PRCM_HALF_SPEED; 408 local_irq_restore(flags); 409 } 410 if (level == PRCM_FULL_SPEED) { 411 local_irq_save(flags); 412 PRCM_VOLTSETUP = 0xffff; 413 omap2_sram_reprogram_sdrc(PRCM_FULL_SPEED, 414 fast_dll_ctrl, m_type); 415 curr_perf_level = PRCM_FULL_SPEED; 416 local_irq_restore(flags); 417 } 418 419 return prev; 420 } 421 422 static int omap2_reprogram_dpll(struct clk * clk, unsigned long rate) 423 { 424 u32 flags, cur_rate, low, mult, div, valid_rate, done_rate; 425 u32 bypass = 0; 426 struct prcm_config tmpset; 427 int ret = -EINVAL; 428 429 local_irq_save(flags); 430 cur_rate = omap2_get_dpll_rate(&dpll_ck); 431 mult = CM_CLKSEL2_PLL & 0x3; 432 433 if ((rate == (cur_rate / 2)) && (mult == 2)) { 434 omap2_reprogram_sdrc(PRCM_HALF_SPEED, 1); 435 } else if ((rate == (cur_rate * 2)) && (mult == 1)) { 436 omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1); 437 } else if (rate != cur_rate) { 438 valid_rate = omap2_dpll_round_rate(rate); 439 if (valid_rate != rate) 440 goto dpll_exit; 441 442 if ((CM_CLKSEL2_PLL & 0x3) == 1) 443 low = curr_prcm_set->dpll_speed; 444 else 445 low = curr_prcm_set->dpll_speed / 2; 446 447 tmpset.cm_clksel1_pll = CM_CLKSEL1_PLL; 448 tmpset.cm_clksel1_pll &= ~(0x3FFF << 8); 449 div = ((curr_prcm_set->xtal_speed / 1000000) - 1); 450 tmpset.cm_clksel2_pll = CM_CLKSEL2_PLL; 451 tmpset.cm_clksel2_pll &= ~0x3; 452 if (rate > low) { 453 tmpset.cm_clksel2_pll |= 0x2; 454 mult = ((rate / 2) / 1000000); 455 done_rate = PRCM_FULL_SPEED; 456 } else { 457 tmpset.cm_clksel2_pll |= 0x1; 458 mult = (rate / 1000000); 459 done_rate = PRCM_HALF_SPEED; 460 } 461 tmpset.cm_clksel1_pll |= ((div << 8) | (mult << 12)); 462 463 /* Worst case */ 464 tmpset.base_sdrc_rfr = V24XX_SDRC_RFR_CTRL_BYPASS; 465 466 if (rate == curr_prcm_set->xtal_speed) /* If asking for 1-1 */ 467 bypass = 1; 468 469 omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1); /* For init_mem */ 470 471 /* Force dll lock mode */ 472 omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr, 473 bypass); 474 475 /* Errata: ret dll entry state */ 476 omap2_init_memory_params(omap2_dll_force_needed()); 477 omap2_reprogram_sdrc(done_rate, 0); 478 } 479 omap2_clksel_recalc(&dpll_ck); 480 ret = 0; 481 482 dpll_exit: 483 local_irq_restore(flags); 484 return(ret); 485 } 486 487 /* Just return the MPU speed */ 488 static void omap2_mpu_recalc(struct clk * clk) 489 { 490 clk->rate = curr_prcm_set->mpu_speed; 491 } 492 493 /* 494 * Look for a rate equal or less than the target rate given a configuration set. 495 * 496 * What's not entirely clear is "which" field represents the key field. 497 * Some might argue L3-DDR, others ARM, others IVA. This code is simple and 498 * just uses the ARM rates. 499 */ 500 static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate) 501 { 502 struct prcm_config * ptr; 503 long highest_rate; 504 505 if (clk != &virt_prcm_set) 506 return -EINVAL; 507 508 highest_rate = -EINVAL; 509 510 for (ptr = rate_table; ptr->mpu_speed; ptr++) { 511 if (ptr->xtal_speed != sys_ck.rate) 512 continue; 513 514 highest_rate = ptr->mpu_speed; 515 516 /* Can check only after xtal frequency check */ 517 if (ptr->mpu_speed <= rate) 518 break; 519 } 520 return highest_rate; 521 } 522 523 /* 524 * omap2_convert_field_to_div() - turn field value into integer divider 525 */ 526 static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val) 527 { 528 u32 i; 529 u32 clkout_array[] = {1, 2, 4, 8, 16}; 530 531 if ((div_sel & SRC_RATE_SEL_MASK) == CM_SYSCLKOUT_SEL1) { 532 for (i = 0; i < 5; i++) { 533 if (field_val == i) 534 return clkout_array[i]; 535 } 536 return ~0; 537 } else 538 return field_val; 539 } 540 541 /* 542 * Returns the CLKSEL divider register value 543 * REVISIT: This should be cleaned up to work nicely with void __iomem * 544 */ 545 static u32 omap2_get_clksel(u32 *div_sel, u32 *field_mask, 546 struct clk *clk) 547 { 548 int ret = ~0; 549 u32 reg_val, div_off; 550 u32 div_addr = 0; 551 u32 mask = ~0; 552 553 div_off = clk->rate_offset; 554 555 switch ((*div_sel & SRC_RATE_SEL_MASK)) { 556 case CM_MPU_SEL1: 557 div_addr = (u32)&CM_CLKSEL_MPU; 558 mask = 0x1f; 559 break; 560 case CM_DSP_SEL1: 561 div_addr = (u32)&CM_CLKSEL_DSP; 562 if (cpu_is_omap2420()) { 563 if ((div_off == 0) || (div_off == 8)) 564 mask = 0x1f; 565 else if (div_off == 5) 566 mask = 0x3; 567 } else if (cpu_is_omap2430()) { 568 if (div_off == 0) 569 mask = 0x1f; 570 else if (div_off == 5) 571 mask = 0x3; 572 } 573 break; 574 case CM_GFX_SEL1: 575 div_addr = (u32)&CM_CLKSEL_GFX; 576 if (div_off == 0) 577 mask = 0x7; 578 break; 579 case CM_MODEM_SEL1: 580 div_addr = (u32)&CM_CLKSEL_MDM; 581 if (div_off == 0) 582 mask = 0xf; 583 break; 584 case CM_SYSCLKOUT_SEL1: 585 div_addr = (u32)&PRCM_CLKOUT_CTRL; 586 if ((div_off == 3) || (div_off = 11)) 587 mask= 0x3; 588 break; 589 case CM_CORE_SEL1: 590 div_addr = (u32)&CM_CLKSEL1_CORE; 591 switch (div_off) { 592 case 0: /* l3 */ 593 case 8: /* dss1 */ 594 case 15: /* vylnc-2420 */ 595 case 20: /* ssi */ 596 mask = 0x1f; break; 597 case 5: /* l4 */ 598 mask = 0x3; break; 599 case 13: /* dss2 */ 600 mask = 0x1; break; 601 case 25: /* usb */ 602 mask = 0x7; break; 603 } 604 } 605 606 *field_mask = mask; 607 608 if (unlikely(mask == ~0)) 609 div_addr = 0; 610 611 *div_sel = div_addr; 612 613 if (unlikely(div_addr == 0)) 614 return ret; 615 616 /* Isolate field */ 617 reg_val = __raw_readl((void __iomem *)div_addr) & (mask << div_off); 618 619 /* Normalize back to divider value */ 620 reg_val >>= div_off; 621 622 return reg_val; 623 } 624 625 /* 626 * Return divider to be applied to parent clock. 627 * Return 0 on error. 628 */ 629 static u32 omap2_clksel_get_divisor(struct clk *clk) 630 { 631 int ret = 0; 632 u32 div, div_sel, div_off, field_mask, field_val; 633 634 /* isolate control register */ 635 div_sel = (SRC_RATE_SEL_MASK & clk->flags); 636 637 div_off = clk->rate_offset; 638 field_val = omap2_get_clksel(&div_sel, &field_mask, clk); 639 if (div_sel == 0) 640 return ret; 641 642 div_sel = (SRC_RATE_SEL_MASK & clk->flags); 643 div = omap2_clksel_to_divisor(div_sel, field_val); 644 645 return div; 646 } 647 648 /* Set the clock rate for a clock source */ 649 static int omap2_clk_set_rate(struct clk *clk, unsigned long rate) 650 651 { 652 int ret = -EINVAL; 653 void __iomem * reg; 654 u32 div_sel, div_off, field_mask, field_val, reg_val, validrate; 655 u32 new_div = 0; 656 657 if (!(clk->flags & CONFIG_PARTICIPANT) && (clk->flags & RATE_CKCTL)) { 658 if (clk == &dpll_ck) 659 return omap2_reprogram_dpll(clk, rate); 660 661 /* Isolate control register */ 662 div_sel = (SRC_RATE_SEL_MASK & clk->flags); 663 div_off = clk->src_offset; 664 665 validrate = omap2_clksel_round_rate(clk, rate, &new_div); 666 if(validrate != rate) 667 return(ret); 668 669 field_val = omap2_get_clksel(&div_sel, &field_mask, clk); 670 if (div_sel == 0) 671 return ret; 672 673 if(clk->flags & CM_SYSCLKOUT_SEL1){ 674 switch(new_div){ 675 case 16: field_val = 4; break; 676 case 8: field_val = 3; break; 677 case 4: field_val = 2; break; 678 case 2: field_val = 1; break; 679 case 1: field_val = 0; break; 680 } 681 } 682 else 683 field_val = new_div; 684 685 reg = (void __iomem *)div_sel; 686 687 reg_val = __raw_readl(reg); 688 reg_val &= ~(field_mask << div_off); 689 reg_val |= (field_val << div_off); 690 691 __raw_writel(reg_val, reg); 692 clk->rate = clk->parent->rate / field_val; 693 694 if (clk->flags & DELAYED_APP) 695 __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL); 696 ret = 0; 697 } else if (clk->set_rate != 0) 698 ret = clk->set_rate(clk, rate); 699 700 if (unlikely(ret == 0 && (clk->flags & RATE_PROPAGATES))) 701 propagate_rate(clk); 702 703 return ret; 704 } 705 706 /* Converts encoded control register address into a full address */ 707 static u32 omap2_get_src_field(u32 *type_to_addr, u32 reg_offset, 708 struct clk *src_clk, u32 *field_mask) 709 { 710 u32 val = ~0, src_reg_addr = 0, mask = 0; 711 712 /* Find target control register.*/ 713 switch ((*type_to_addr & SRC_RATE_SEL_MASK)) { 714 case CM_CORE_SEL1: 715 src_reg_addr = (u32)&CM_CLKSEL1_CORE; 716 if (reg_offset == 13) { /* DSS2_fclk */ 717 mask = 0x1; 718 if (src_clk == &sys_ck) 719 val = 0; 720 if (src_clk == &func_48m_ck) 721 val = 1; 722 } else if (reg_offset == 8) { /* DSS1_fclk */ 723 mask = 0x1f; 724 if (src_clk == &sys_ck) 725 val = 0; 726 else if (src_clk == &core_ck) /* divided clock */ 727 val = 0x10; /* rate needs fixing */ 728 } else if ((reg_offset == 15) && cpu_is_omap2420()){ /*vlnyq*/ 729 mask = 0x1F; 730 if(src_clk == &func_96m_ck) 731 val = 0; 732 else if (src_clk == &core_ck) 733 val = 0x10; 734 } 735 break; 736 case CM_CORE_SEL2: 737 src_reg_addr = (u32)&CM_CLKSEL2_CORE; 738 mask = 0x3; 739 if (src_clk == &func_32k_ck) 740 val = 0x0; 741 if (src_clk == &sys_ck) 742 val = 0x1; 743 if (src_clk == &alt_ck) 744 val = 0x2; 745 break; 746 case CM_WKUP_SEL1: 747 src_reg_addr = (u32)&CM_CLKSEL2_CORE; 748 mask = 0x3; 749 if (src_clk == &func_32k_ck) 750 val = 0x0; 751 if (src_clk == &sys_ck) 752 val = 0x1; 753 if (src_clk == &alt_ck) 754 val = 0x2; 755 break; 756 case CM_PLL_SEL1: 757 src_reg_addr = (u32)&CM_CLKSEL1_PLL; 758 mask = 0x1; 759 if (reg_offset == 0x3) { 760 if (src_clk == &apll96_ck) 761 val = 0; 762 if (src_clk == &alt_ck) 763 val = 1; 764 } 765 else if (reg_offset == 0x5) { 766 if (src_clk == &apll54_ck) 767 val = 0; 768 if (src_clk == &alt_ck) 769 val = 1; 770 } 771 break; 772 case CM_PLL_SEL2: 773 src_reg_addr = (u32)&CM_CLKSEL2_PLL; 774 mask = 0x3; 775 if (src_clk == &func_32k_ck) 776 val = 0x0; 777 if (src_clk == &dpll_ck) 778 val = 0x2; 779 break; 780 case CM_SYSCLKOUT_SEL1: 781 src_reg_addr = (u32)&PRCM_CLKOUT_CTRL; 782 mask = 0x3; 783 if (src_clk == &dpll_ck) 784 val = 0; 785 if (src_clk == &sys_ck) 786 val = 1; 787 if (src_clk == &func_54m_ck) 788 val = 2; 789 if (src_clk == &func_96m_ck) 790 val = 3; 791 break; 792 } 793 794 if (val == ~0) /* Catch errors in offset */ 795 *type_to_addr = 0; 796 else 797 *type_to_addr = src_reg_addr; 798 *field_mask = mask; 799 800 return val; 801 } 802 803 static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) 804 { 805 void __iomem * reg; 806 u32 src_sel, src_off, field_val, field_mask, reg_val, rate; 807 int ret = -EINVAL; 808 809 if (unlikely(clk->flags & CONFIG_PARTICIPANT)) 810 return ret; 811 812 if (clk->flags & SRC_SEL_MASK) { /* On-chip SEL collection */ 813 src_sel = (SRC_RATE_SEL_MASK & clk->flags); 814 src_off = clk->src_offset; 815 816 if (src_sel == 0) 817 goto set_parent_error; 818 819 field_val = omap2_get_src_field(&src_sel, src_off, new_parent, 820 &field_mask); 821 822 reg = (void __iomem *)src_sel; 823 824 if (clk->usecount > 0) 825 _omap2_clk_disable(clk); 826 827 /* Set new source value (previous dividers if any in effect) */ 828 reg_val = __raw_readl(reg) & ~(field_mask << src_off); 829 reg_val |= (field_val << src_off); 830 __raw_writel(reg_val, reg); 831 832 if (clk->flags & DELAYED_APP) 833 __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL); 834 835 if (clk->usecount > 0) 836 _omap2_clk_enable(clk); 837 838 clk->parent = new_parent; 839 840 /* SRC_RATE_SEL_MASK clocks follow their parents rates.*/ 841 if ((new_parent == &core_ck) && (clk == &dss1_fck)) 842 clk->rate = new_parent->rate / 0x10; 843 else 844 clk->rate = new_parent->rate; 845 846 if (unlikely(clk->flags & RATE_PROPAGATES)) 847 propagate_rate(clk); 848 849 return 0; 850 } else { 851 clk->parent = new_parent; 852 rate = new_parent->rate; 853 omap2_clk_set_rate(clk, rate); 854 ret = 0; 855 } 856 857 set_parent_error: 858 return ret; 859 } 860 861 /* Sets basic clocks based on the specified rate */ 862 static int omap2_select_table_rate(struct clk * clk, unsigned long rate) 863 { 864 u32 flags, cur_rate, done_rate, bypass = 0; 865 u8 cpu_mask = 0; 866 struct prcm_config *prcm; 867 unsigned long found_speed = 0; 868 869 if (clk != &virt_prcm_set) 870 return -EINVAL; 871 872 /* FIXME: Change cpu_is_omap2420() to cpu_is_omap242x() */ 873 if (cpu_is_omap2420()) 874 cpu_mask = RATE_IN_242X; 875 else if (cpu_is_omap2430()) 876 cpu_mask = RATE_IN_243X; 877 878 for (prcm = rate_table; prcm->mpu_speed; prcm++) { 879 if (!(prcm->flags & cpu_mask)) 880 continue; 881 882 if (prcm->xtal_speed != sys_ck.rate) 883 continue; 884 885 if (prcm->mpu_speed <= rate) { 886 found_speed = prcm->mpu_speed; 887 break; 888 } 889 } 890 891 if (!found_speed) { 892 printk(KERN_INFO "Could not set MPU rate to %luMHz\n", 893 rate / 1000000); 894 return -EINVAL; 895 } 896 897 curr_prcm_set = prcm; 898 cur_rate = omap2_get_dpll_rate(&dpll_ck); 899 900 if (prcm->dpll_speed == cur_rate / 2) { 901 omap2_reprogram_sdrc(PRCM_HALF_SPEED, 1); 902 } else if (prcm->dpll_speed == cur_rate * 2) { 903 omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1); 904 } else if (prcm->dpll_speed != cur_rate) { 905 local_irq_save(flags); 906 907 if (prcm->dpll_speed == prcm->xtal_speed) 908 bypass = 1; 909 910 if ((prcm->cm_clksel2_pll & 0x3) == 2) 911 done_rate = PRCM_FULL_SPEED; 912 else 913 done_rate = PRCM_HALF_SPEED; 914 915 /* MPU divider */ 916 CM_CLKSEL_MPU = prcm->cm_clksel_mpu; 917 918 /* dsp + iva1 div(2420), iva2.1(2430) */ 919 CM_CLKSEL_DSP = prcm->cm_clksel_dsp; 920 921 CM_CLKSEL_GFX = prcm->cm_clksel_gfx; 922 923 /* Major subsystem dividers */ 924 CM_CLKSEL1_CORE = prcm->cm_clksel1_core; 925 if (cpu_is_omap2430()) 926 CM_CLKSEL_MDM = prcm->cm_clksel_mdm; 927 928 /* x2 to enter init_mem */ 929 omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1); 930 931 omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr, 932 bypass); 933 934 omap2_init_memory_params(omap2_dll_force_needed()); 935 omap2_reprogram_sdrc(done_rate, 0); 936 937 local_irq_restore(flags); 938 } 939 omap2_clksel_recalc(&dpll_ck); 940 941 return 0; 942 } 943 944 /*------------------------------------------------------------------------- 945 * Omap2 clock reset and init functions 946 *-------------------------------------------------------------------------*/ 947 948 static struct clk_functions omap2_clk_functions = { 949 .clk_enable = omap2_clk_enable, 950 .clk_disable = omap2_clk_disable, 951 .clk_round_rate = omap2_clk_round_rate, 952 .clk_set_rate = omap2_clk_set_rate, 953 .clk_set_parent = omap2_clk_set_parent, 954 }; 955 956 static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys) 957 { 958 u32 div, aplls, sclk = 13000000; 959 960 aplls = CM_CLKSEL1_PLL; 961 aplls &= ((1 << 23) | (1 << 24) | (1 << 25)); 962 aplls >>= 23; /* Isolate field, 0,2,3 */ 963 964 if (aplls == 0) 965 sclk = 19200000; 966 else if (aplls == 2) 967 sclk = 13000000; 968 else if (aplls == 3) 969 sclk = 12000000; 970 971 div = PRCM_CLKSRC_CTRL; 972 div &= ((1 << 7) | (1 << 6)); 973 div >>= sys->rate_offset; 974 975 osc->rate = sclk * div; 976 sys->rate = sclk; 977 } 978 979 #ifdef CONFIG_OMAP_RESET_CLOCKS 980 static void __init omap2_disable_unused_clocks(void) 981 { 982 struct clk *ck; 983 u32 regval32; 984 985 list_for_each_entry(ck, &clocks, node) { 986 if (ck->usecount > 0 || (ck->flags & ALWAYS_ENABLED) || 987 ck->enable_reg == 0) 988 continue; 989 990 regval32 = __raw_readl(ck->enable_reg); 991 if ((regval32 & (1 << ck->enable_bit)) == 0) 992 continue; 993 994 printk(KERN_INFO "Disabling unused clock \"%s\"\n", ck->name); 995 _omap2_clk_disable(ck); 996 } 997 } 998 late_initcall(omap2_disable_unused_clocks); 999 #endif 1000 1001 /* 1002 * Switch the MPU rate if specified on cmdline. 1003 * We cannot do this early until cmdline is parsed. 1004 */ 1005 static int __init omap2_clk_arch_init(void) 1006 { 1007 if (!mpurate) 1008 return -EINVAL; 1009 1010 if (omap2_select_table_rate(&virt_prcm_set, mpurate)) 1011 printk(KERN_ERR "Could not find matching MPU rate\n"); 1012 1013 propagate_rate(&osc_ck); /* update main root fast */ 1014 propagate_rate(&func_32k_ck); /* update main root slow */ 1015 1016 printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL/MPU): " 1017 "%ld.%01ld/%ld/%ld MHz\n", 1018 (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10, 1019 (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ; 1020 1021 return 0; 1022 } 1023 arch_initcall(omap2_clk_arch_init); 1024 1025 int __init omap2_clk_init(void) 1026 { 1027 struct prcm_config *prcm; 1028 struct clk ** clkp; 1029 u32 clkrate; 1030 1031 clk_init(&omap2_clk_functions); 1032 omap2_get_crystal_rate(&osc_ck, &sys_ck); 1033 1034 for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks); 1035 clkp++) { 1036 1037 if ((*clkp)->flags & CLOCK_IN_OMAP242X && cpu_is_omap2420()) { 1038 clk_register(*clkp); 1039 continue; 1040 } 1041 1042 if ((*clkp)->flags & CLOCK_IN_OMAP243X && cpu_is_omap2430()) { 1043 clk_register(*clkp); 1044 continue; 1045 } 1046 } 1047 1048 /* Check the MPU rate set by bootloader */ 1049 clkrate = omap2_get_dpll_rate(&dpll_ck); 1050 for (prcm = rate_table; prcm->mpu_speed; prcm++) { 1051 if (prcm->xtal_speed != sys_ck.rate) 1052 continue; 1053 if (prcm->dpll_speed <= clkrate) 1054 break; 1055 } 1056 curr_prcm_set = prcm; 1057 1058 propagate_rate(&osc_ck); /* update main root fast */ 1059 propagate_rate(&func_32k_ck); /* update main root slow */ 1060 1061 printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): " 1062 "%ld.%01ld/%ld/%ld MHz\n", 1063 (sys_ck.rate / 1000000), (sys_ck.rate / 100000) % 10, 1064 (dpll_ck.rate / 1000000), (mpu_ck.rate / 1000000)) ; 1065 1066 /* 1067 * Only enable those clocks we will need, let the drivers 1068 * enable other clocks as necessary 1069 */ 1070 clk_enable(&sync_32k_ick); 1071 clk_enable(&omapctrl_ick); 1072 if (cpu_is_omap2430()) 1073 clk_enable(&sdrc_ick); 1074 1075 return 0; 1076 } 1077