aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/clock24xx.c
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2008-03-18 04:35:15 -0400
committerTony Lindgren <tony@atomide.com>2008-04-14 13:29:38 -0400
commit6b8858a972a0eff1dc1ab77b0fd9fc25387c217c (patch)
treea34e94f4d372670c5125e8f490c85e9364d222df /arch/arm/mach-omap2/clock24xx.c
parent543d93781a3c744017594d0721c4c1814a26bcce (diff)
ARM: OMAP2: Change 24xx to use shared clock code and new reg access
This patch changes 24xx to use shared clock code and new register access. Note that patch adds some temporary OLD_CK defines to keep patch more readable. These temporary defines will be removed in the next patch. Also not all clocks are changed in this patch to limit the size. Also, the patch fixes few incorrect clock defines in clock24xx.h. Signed-off-by: Paul Walmsley <paul@pwsan.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm/mach-omap2/clock24xx.c')
-rw-r--r--arch/arm/mach-omap2/clock24xx.c319
1 files changed, 202 insertions, 117 deletions
diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
index 5c24781f6d9b..c3ccac1b7218 100644
--- a/arch/arm/mach-omap2/clock24xx.c
+++ b/arch/arm/mach-omap2/clock24xx.c
@@ -15,6 +15,8 @@
15 * it under the terms of the GNU General Public License version 2 as 15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation. 16 * published by the Free Software Foundation.
17 */ 17 */
18#undef DEBUG
19
18#include <linux/module.h> 20#include <linux/module.h>
19#include <linux/kernel.h> 21#include <linux/kernel.h>
20#include <linux/device.h> 22#include <linux/device.h>
@@ -23,29 +25,64 @@
23#include <linux/delay.h> 25#include <linux/delay.h>
24#include <linux/clk.h> 26#include <linux/clk.h>
25 27
26#include <asm/io.h> 28#include <linux/io.h>
29#include <linux/cpufreq.h>
27 30
28#include <asm/arch/clock.h> 31#include <asm/arch/clock.h>
29#include <asm/arch/sram.h> 32#include <asm/arch/sram.h>
30#include <asm/div64.h> 33#include <asm/div64.h>
34#include <asm/bitops.h>
31 35
32#include "prcm-regs.h"
33#include "memory.h" 36#include "memory.h"
37#include "clock.h"
34#include "clock24xx.h" 38#include "clock24xx.h"
39#include "prm.h"
40#include "prm-regbits-24xx.h"
41#include "cm.h"
42#include "cm-regbits-24xx.h"
35 43
36#undef DEBUG 44/* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */
45#define EN_APLL_STOPPED 0
46#define EN_APLL_LOCKED 3
37 47
38//#define DOWN_VARIABLE_DPLL 1 /* Experimental */ 48/* CM_CLKSEL1_PLL.APLLS_CLKIN options (24XX) */
49#define APLLS_CLKIN_19_2MHZ 0
50#define APLLS_CLKIN_13MHZ 2
51#define APLLS_CLKIN_12MHZ 3
52
53/* #define DOWN_VARIABLE_DPLL 1 */ /* Experimental */
39 54
40static struct prcm_config *curr_prcm_set; 55static struct prcm_config *curr_prcm_set;
41static u32 curr_perf_level = PRCM_FULL_SPEED;
42static struct clk *vclk; 56static struct clk *vclk;
43static struct clk *sclk; 57static struct clk *sclk;
44 58
45/*------------------------------------------------------------------------- 59/*-------------------------------------------------------------------------
46 * Omap2 specific clock functions 60 * Omap24xx specific clock functions
47 *-------------------------------------------------------------------------*/ 61 *-------------------------------------------------------------------------*/
48 62
63static int omap2_enable_osc_ck(struct clk *clk)
64{
65 u32 pcc;
66
67 pcc = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL);
68
69 __raw_writel(pcc & ~OMAP_AUTOEXTCLKMODE_MASK,
70 OMAP24XX_PRCM_CLKSRC_CTRL);
71
72 return 0;
73}
74
75static void omap2_disable_osc_ck(struct clk *clk)
76{
77 u32 pcc;
78
79 pcc = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL);
80
81 __raw_writel(pcc | OMAP_AUTOEXTCLKMODE_MASK,
82 OMAP24XX_PRCM_CLKSRC_CTRL);
83}
84
85#ifdef OLD_CK
49/* Recalculate SYST_CLK */ 86/* Recalculate SYST_CLK */
50static void omap2_sys_clk_recalc(struct clk * clk) 87static void omap2_sys_clk_recalc(struct clk * clk)
51{ 88{
@@ -55,17 +92,18 @@ static void omap2_sys_clk_recalc(struct clk * clk)
55 clk->rate = (clk->parent->rate / div); 92 clk->rate = (clk->parent->rate / div);
56 propagate_rate(clk); 93 propagate_rate(clk);
57} 94}
95#endif /* OLD_CK */
58 96
59static u32 omap2_get_dpll_rate(struct clk * tclk) 97/* This actually returns the rate of core_ck, not dpll_ck. */
98static u32 omap2_get_dpll_rate_24xx(struct clk *tclk)
60{ 99{
61 long long dpll_clk; 100 long long dpll_clk;
62 int dpll_mult, dpll_div, amult; 101 u8 amult;
102
103 dpll_clk = omap2_get_dpll_rate(tclk);
63 104
64 dpll_mult = (CM_CLKSEL1_PLL >> 12) & 0x03ff; /* 10 bits */ 105 amult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
65 dpll_div = (CM_CLKSEL1_PLL >> 8) & 0x0f; /* 4 bits */ 106 amult &= OMAP24XX_CORE_CLK_SRC_MASK;
66 dpll_clk = (long long)tclk->parent->rate * dpll_mult;
67 do_div(dpll_clk, dpll_div + 1);
68 amult = CM_CLKSEL2_PLL & 0x3;
69 dpll_clk *= amult; 107 dpll_clk *= amult;
70 108
71 return dpll_clk; 109 return dpll_clk;
@@ -84,6 +122,7 @@ static void omap2_propagate_rate(struct clk * clk)
84 propagate_rate(clk); 122 propagate_rate(clk);
85} 123}
86 124
125#ifdef OLD_CK
87static void omap2_set_osc_ck(int enable) 126static void omap2_set_osc_ck(int enable)
88{ 127{
89 if (enable) 128 if (enable)
@@ -91,39 +130,40 @@ static void omap2_set_osc_ck(int enable)
91 else 130 else
92 PRCM_CLKSRC_CTRL |= 0x3 << 3; 131 PRCM_CLKSRC_CTRL |= 0x3 << 3;
93} 132}
133#endif /* OLD_CK */
94 134
95/* Enable an APLL if off */ 135/* Enable an APLL if off */
96static void omap2_clk_fixed_enable(struct clk *clk) 136static int omap2_clk_fixed_enable(struct clk *clk)
97{ 137{
98 u32 cval, i=0; 138 u32 cval, apll_mask;
99 139
100 if (clk->enable_bit == 0xff) /* Parent will do it */ 140 apll_mask = EN_APLL_LOCKED << clk->enable_bit;
101 return;
102 141
103 cval = CM_CLKEN_PLL; 142 cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
104 143
105 if ((cval & (0x3 << clk->enable_bit)) == (0x3 << clk->enable_bit)) 144 if ((cval & apll_mask) == apll_mask)
106 return; 145 return 0; /* apll already enabled */
107 146
108 cval &= ~(0x3 << clk->enable_bit); 147 cval &= ~apll_mask;
109 cval |= (0x3 << clk->enable_bit); 148 cval |= apll_mask;
110 CM_CLKEN_PLL = cval; 149 cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
111 150
112 if (clk == &apll96_ck) 151 if (clk == &apll96_ck)
113 cval = (1 << 8); 152 cval = OMAP24XX_ST_96M_APLL;
114 else if (clk == &apll54_ck) 153 else if (clk == &apll54_ck)
115 cval = (1 << 6); 154 cval = OMAP24XX_ST_54M_APLL;
116 155
117 while (!(CM_IDLEST_CKGEN & cval)) { /* Wait for lock */ 156 omap2_wait_clock_ready(OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), cval,
118 ++i; 157 clk->name);
119 udelay(1); 158
120 if (i == 100000) { 159 /*
121 printk(KERN_ERR "Clock %s didn't lock\n", clk->name); 160 * REVISIT: Should we return an error code if omap2_wait_clock_ready()
122 break; 161 * fails?
123 } 162 */
124 } 163 return 0;
125} 164}
126 165
166#ifdef OLD_CK
127static void omap2_clk_wait_ready(struct clk *clk) 167static void omap2_clk_wait_ready(struct clk *clk)
128{ 168{
129 unsigned long reg, other_reg, st_reg; 169 unsigned long reg, other_reg, st_reg;
@@ -199,20 +239,19 @@ static int _omap2_clk_enable(struct clk * clk)
199 239
200 return 0; 240 return 0;
201} 241}
242#endif /* OLD_CK */
202 243
203/* Stop APLL */ 244/* Stop APLL */
204static void omap2_clk_fixed_disable(struct clk *clk) 245static void omap2_clk_fixed_disable(struct clk *clk)
205{ 246{
206 u32 cval; 247 u32 cval;
207 248
208 if(clk->enable_bit == 0xff) /* let parent off do it */ 249 cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
209 return; 250 cval &= ~(EN_APLL_LOCKED << clk->enable_bit);
210 251 cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
211 cval = CM_CLKEN_PLL;
212 cval &= ~(0x3 << clk->enable_bit);
213 CM_CLKEN_PLL = cval;
214} 252}
215 253
254#ifdef OLD_CK
216/* Disables clock without considering parent dependencies or use count */ 255/* Disables clock without considering parent dependencies or use count */
217static void _omap2_clk_disable(struct clk *clk) 256static void _omap2_clk_disable(struct clk *clk)
218{ 257{
@@ -269,6 +308,7 @@ static void omap2_clk_disable(struct clk *clk)
269 omap2_clk_disable(clk->parent); 308 omap2_clk_disable(clk->parent);
270 } 309 }
271} 310}
311#endif /* OLD_CK */
272 312
273/* 313/*
274 * Uses the current prcm set to tell if a rate is valid. 314 * Uses the current prcm set to tell if a rate is valid.
@@ -276,9 +316,12 @@ static void omap2_clk_disable(struct clk *clk)
276 */ 316 */
277static u32 omap2_dpll_round_rate(unsigned long target_rate) 317static u32 omap2_dpll_round_rate(unsigned long target_rate)
278{ 318{
279 u32 high, low; 319 u32 high, low, core_clk_src;
280 320
281 if ((CM_CLKSEL2_PLL & 0x3) == 1) { /* DPLL clockout */ 321 core_clk_src = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
322 core_clk_src &= OMAP24XX_CORE_CLK_SRC_MASK;
323
324 if (core_clk_src == CORE_CLK_SRC_DPLL) { /* DPLL clockout */
282 high = curr_prcm_set->dpll_speed * 2; 325 high = curr_prcm_set->dpll_speed * 2;
283 low = curr_prcm_set->dpll_speed; 326 low = curr_prcm_set->dpll_speed;
284 } else { /* DPLL clockout x 2 */ 327 } else { /* DPLL clockout x 2 */
@@ -300,6 +343,7 @@ static u32 omap2_dpll_round_rate(unsigned long target_rate)
300 343
301} 344}
302 345
346#ifdef OLD_CK
303/* 347/*
304 * Used for clocks that are part of CLKSEL_xyz governed clocks. 348 * Used for clocks that are part of CLKSEL_xyz governed clocks.
305 * REVISIT: Maybe change to use clk->enable() functions like on omap1? 349 * REVISIT: Maybe change to use clk->enable() functions like on omap1?
@@ -486,55 +530,72 @@ static u32 omap2_reprogram_sdrc(u32 level, u32 force)
486 530
487 return prev; 531 return prev;
488} 532}
533#endif /* OLD_CK */
534
535static void omap2_dpll_recalc(struct clk *clk)
536{
537 clk->rate = omap2_get_dpll_rate_24xx(clk);
538
539 propagate_rate(clk);
540}
489 541
490static int omap2_reprogram_dpll(struct clk * clk, unsigned long rate) 542static int omap2_reprogram_dpll(struct clk *clk, unsigned long rate)
491{ 543{
492 u32 flags, cur_rate, low, mult, div, valid_rate, done_rate; 544 u32 cur_rate, low, mult, div, valid_rate, done_rate;
493 u32 bypass = 0; 545 u32 bypass = 0;
494 struct prcm_config tmpset; 546 struct prcm_config tmpset;
547 const struct dpll_data *dd;
548 unsigned long flags;
495 int ret = -EINVAL; 549 int ret = -EINVAL;
496 550
497 local_irq_save(flags); 551 local_irq_save(flags);
498 cur_rate = omap2_get_dpll_rate(&dpll_ck); 552 cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
499 mult = CM_CLKSEL2_PLL & 0x3; 553 mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
554 mult &= OMAP24XX_CORE_CLK_SRC_MASK;
500 555
501 if ((rate == (cur_rate / 2)) && (mult == 2)) { 556 if ((rate == (cur_rate / 2)) && (mult == 2)) {
502 omap2_reprogram_sdrc(PRCM_HALF_SPEED, 1); 557 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
503 } else if ((rate == (cur_rate * 2)) && (mult == 1)) { 558 } else if ((rate == (cur_rate * 2)) && (mult == 1)) {
504 omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1); 559 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
505 } else if (rate != cur_rate) { 560 } else if (rate != cur_rate) {
506 valid_rate = omap2_dpll_round_rate(rate); 561 valid_rate = omap2_dpll_round_rate(rate);
507 if (valid_rate != rate) 562 if (valid_rate != rate)
508 goto dpll_exit; 563 goto dpll_exit;
509 564
510 if ((CM_CLKSEL2_PLL & 0x3) == 1) 565 if (mult == 1)
511 low = curr_prcm_set->dpll_speed; 566 low = curr_prcm_set->dpll_speed;
512 else 567 else
513 low = curr_prcm_set->dpll_speed / 2; 568 low = curr_prcm_set->dpll_speed / 2;
514 569
515 tmpset.cm_clksel1_pll = CM_CLKSEL1_PLL; 570 dd = clk->dpll_data;
516 tmpset.cm_clksel1_pll &= ~(0x3FFF << 8); 571 if (!dd)
572 goto dpll_exit;
573
574 tmpset.cm_clksel1_pll = __raw_readl(dd->mult_div1_reg);
575 tmpset.cm_clksel1_pll &= ~(dd->mult_mask |
576 dd->div1_mask);
517 div = ((curr_prcm_set->xtal_speed / 1000000) - 1); 577 div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
518 tmpset.cm_clksel2_pll = CM_CLKSEL2_PLL; 578 tmpset.cm_clksel2_pll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
519 tmpset.cm_clksel2_pll &= ~0x3; 579 tmpset.cm_clksel2_pll &= ~OMAP24XX_CORE_CLK_SRC_MASK;
520 if (rate > low) { 580 if (rate > low) {
521 tmpset.cm_clksel2_pll |= 0x2; 581 tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL_X2;
522 mult = ((rate / 2) / 1000000); 582 mult = ((rate / 2) / 1000000);
523 done_rate = PRCM_FULL_SPEED; 583 done_rate = CORE_CLK_SRC_DPLL_X2;
524 } else { 584 } else {
525 tmpset.cm_clksel2_pll |= 0x1; 585 tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL;
526 mult = (rate / 1000000); 586 mult = (rate / 1000000);
527 done_rate = PRCM_HALF_SPEED; 587 done_rate = CORE_CLK_SRC_DPLL;
528 } 588 }
529 tmpset.cm_clksel1_pll |= ((div << 8) | (mult << 12)); 589 tmpset.cm_clksel1_pll |= (div << __ffs(dd->mult_mask));
590 tmpset.cm_clksel1_pll |= (mult << __ffs(dd->div1_mask));
530 591
531 /* Worst case */ 592 /* Worst case */
532 tmpset.base_sdrc_rfr = V24XX_SDRC_RFR_CTRL_BYPASS; 593 tmpset.base_sdrc_rfr = SDRC_RFR_CTRL_BYPASS;
533 594
534 if (rate == curr_prcm_set->xtal_speed) /* If asking for 1-1 */ 595 if (rate == curr_prcm_set->xtal_speed) /* If asking for 1-1 */
535 bypass = 1; 596 bypass = 1;
536 597
537 omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1); /* For init_mem */ 598 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1); /* For init_mem */
538 599
539 /* Force dll lock mode */ 600 /* Force dll lock mode */
540 omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr, 601 omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr,
@@ -544,7 +605,7 @@ static int omap2_reprogram_dpll(struct clk * clk, unsigned long rate)
544 omap2_init_memory_params(omap2_dll_force_needed()); 605 omap2_init_memory_params(omap2_dll_force_needed());
545 omap2_reprogram_sdrc(done_rate, 0); 606 omap2_reprogram_sdrc(done_rate, 0);
546 } 607 }
547 omap2_clksel_recalc(&dpll_ck); 608 omap2_dpll_recalc(&dpll_ck);
548 ret = 0; 609 ret = 0;
549 610
550dpll_exit: 611dpll_exit:
@@ -552,8 +613,13 @@ dpll_exit:
552 return(ret); 613 return(ret);
553} 614}
554 615
555/* Just return the MPU speed */ 616/**
556static void omap2_mpu_recalc(struct clk * clk) 617 * omap2_table_mpu_recalc - just return the MPU speed
618 * @clk: virt_prcm_set struct clk
619 *
620 * Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
621 */
622static void omap2_table_mpu_recalc(struct clk *clk)
557{ 623{
558 clk->rate = curr_prcm_set->mpu_speed; 624 clk->rate = curr_prcm_set->mpu_speed;
559} 625}
@@ -565,9 +631,9 @@ static void omap2_mpu_recalc(struct clk * clk)
565 * Some might argue L3-DDR, others ARM, others IVA. This code is simple and 631 * Some might argue L3-DDR, others ARM, others IVA. This code is simple and
566 * just uses the ARM rates. 632 * just uses the ARM rates.
567 */ 633 */
568static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate) 634static long omap2_round_to_table_rate(struct clk *clk, unsigned long rate)
569{ 635{
570 struct prcm_config * ptr; 636 struct prcm_config *ptr;
571 long highest_rate; 637 long highest_rate;
572 638
573 if (clk != &virt_prcm_set) 639 if (clk != &virt_prcm_set)
@@ -576,6 +642,8 @@ static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate)
576 highest_rate = -EINVAL; 642 highest_rate = -EINVAL;
577 643
578 for (ptr = rate_table; ptr->mpu_speed; ptr++) { 644 for (ptr = rate_table; ptr->mpu_speed; ptr++) {
645 if (!(ptr->flags & cpu_mask))
646 continue;
579 if (ptr->xtal_speed != sys_ck.rate) 647 if (ptr->xtal_speed != sys_ck.rate)
580 continue; 648 continue;
581 649
@@ -588,6 +656,7 @@ static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate)
588 return highest_rate; 656 return highest_rate;
589} 657}
590 658
659#ifdef OLD_CK
591/* 660/*
592 * omap2_convert_field_to_div() - turn field value into integer divider 661 * omap2_convert_field_to_div() - turn field value into integer divider
593 */ 662 */
@@ -938,24 +1007,19 @@ static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
938 set_parent_error: 1007 set_parent_error:
939 return ret; 1008 return ret;
940} 1009}
1010#endif /* OLD_CK */
941 1011
942/* Sets basic clocks based on the specified rate */ 1012/* Sets basic clocks based on the specified rate */
943static int omap2_select_table_rate(struct clk * clk, unsigned long rate) 1013static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
944{ 1014{
945 u32 flags, cur_rate, done_rate, bypass = 0; 1015 u32 cur_rate, done_rate, bypass = 0, tmp;
946 u8 cpu_mask = 0;
947 struct prcm_config *prcm; 1016 struct prcm_config *prcm;
948 unsigned long found_speed = 0; 1017 unsigned long found_speed = 0;
1018 unsigned long flags;
949 1019
950 if (clk != &virt_prcm_set) 1020 if (clk != &virt_prcm_set)
951 return -EINVAL; 1021 return -EINVAL;
952 1022
953 /* FIXME: Change cpu_is_omap2420() to cpu_is_omap242x() */
954 if (cpu_is_omap2420())
955 cpu_mask = RATE_IN_242X;
956 else if (cpu_is_omap2430())
957 cpu_mask = RATE_IN_243X;
958
959 for (prcm = rate_table; prcm->mpu_speed; prcm++) { 1023 for (prcm = rate_table; prcm->mpu_speed; prcm++) {
960 if (!(prcm->flags & cpu_mask)) 1024 if (!(prcm->flags & cpu_mask))
961 continue; 1025 continue;
@@ -976,38 +1040,42 @@ static int omap2_select_table_rate(struct clk * clk, unsigned long rate)
976 } 1040 }
977 1041
978 curr_prcm_set = prcm; 1042 curr_prcm_set = prcm;
979 cur_rate = omap2_get_dpll_rate(&dpll_ck); 1043 cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck);
980 1044
981 if (prcm->dpll_speed == cur_rate / 2) { 1045 if (prcm->dpll_speed == cur_rate / 2) {
982 omap2_reprogram_sdrc(PRCM_HALF_SPEED, 1); 1046 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL, 1);
983 } else if (prcm->dpll_speed == cur_rate * 2) { 1047 } else if (prcm->dpll_speed == cur_rate * 2) {
984 omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1); 1048 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
985 } else if (prcm->dpll_speed != cur_rate) { 1049 } else if (prcm->dpll_speed != cur_rate) {
986 local_irq_save(flags); 1050 local_irq_save(flags);
987 1051
988 if (prcm->dpll_speed == prcm->xtal_speed) 1052 if (prcm->dpll_speed == prcm->xtal_speed)
989 bypass = 1; 1053 bypass = 1;
990 1054
991 if ((prcm->cm_clksel2_pll & 0x3) == 2) 1055 if ((prcm->cm_clksel2_pll & OMAP24XX_CORE_CLK_SRC_MASK) ==
992 done_rate = PRCM_FULL_SPEED; 1056 CORE_CLK_SRC_DPLL_X2)
1057 done_rate = CORE_CLK_SRC_DPLL_X2;
993 else 1058 else
994 done_rate = PRCM_HALF_SPEED; 1059 done_rate = CORE_CLK_SRC_DPLL;
995 1060
996 /* MPU divider */ 1061 /* MPU divider */
997 CM_CLKSEL_MPU = prcm->cm_clksel_mpu; 1062 cm_write_mod_reg(prcm->cm_clksel_mpu, MPU_MOD, CM_CLKSEL);
998 1063
999 /* dsp + iva1 div(2420), iva2.1(2430) */ 1064 /* dsp + iva1 div(2420), iva2.1(2430) */
1000 CM_CLKSEL_DSP = prcm->cm_clksel_dsp; 1065 cm_write_mod_reg(prcm->cm_clksel_dsp,
1066 OMAP24XX_DSP_MOD, CM_CLKSEL);
1001 1067
1002 CM_CLKSEL_GFX = prcm->cm_clksel_gfx; 1068 cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL);
1003 1069
1004 /* Major subsystem dividers */ 1070 /* Major subsystem dividers */
1005 CM_CLKSEL1_CORE = prcm->cm_clksel1_core; 1071 tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK;
1072 cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD, CM_CLKSEL1);
1006 if (cpu_is_omap2430()) 1073 if (cpu_is_omap2430())
1007 CM_CLKSEL_MDM = prcm->cm_clksel_mdm; 1074 cm_write_mod_reg(prcm->cm_clksel_mdm,
1075 OMAP2430_MDM_MOD, CM_CLKSEL);
1008 1076
1009 /* x2 to enter init_mem */ 1077 /* x2 to enter init_mem */
1010 omap2_reprogram_sdrc(PRCM_FULL_SPEED, 1); 1078 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
1011 1079
1012 omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr, 1080 omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
1013 bypass); 1081 bypass);
@@ -1017,7 +1085,7 @@ static int omap2_select_table_rate(struct clk * clk, unsigned long rate)
1017 1085
1018 local_irq_restore(flags); 1086 local_irq_restore(flags);
1019 } 1087 }
1020 omap2_clksel_recalc(&dpll_ck); 1088 omap2_dpll_recalc(&dpll_ck);
1021 1089
1022 return 0; 1090 return 0;
1023} 1091}
@@ -1051,27 +1119,45 @@ static struct clk_functions omap2_clk_functions = {
1051 .clk_disable_unused = omap2_clk_disable_unused, 1119 .clk_disable_unused = omap2_clk_disable_unused,
1052}; 1120};
1053 1121
1054static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys) 1122static u32 omap2_get_apll_clkin(void)
1055{ 1123{
1056 u32 div, aplls, sclk = 13000000; 1124 u32 aplls, sclk = 0;
1057 1125
1058 aplls = CM_CLKSEL1_PLL; 1126 aplls = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
1059 aplls &= ((1 << 23) | (1 << 24) | (1 << 25)); 1127 aplls &= OMAP24XX_APLLS_CLKIN_MASK;
1060 aplls >>= 23; /* Isolate field, 0,2,3 */ 1128 aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT;
1061 1129
1062 if (aplls == 0) 1130 if (aplls == APLLS_CLKIN_19_2MHZ)
1063 sclk = 19200000; 1131 sclk = 19200000;
1064 else if (aplls == 2) 1132 else if (aplls == APLLS_CLKIN_13MHZ)
1065 sclk = 13000000; 1133 sclk = 13000000;
1066 else if (aplls == 3) 1134 else if (aplls == APLLS_CLKIN_12MHZ)
1067 sclk = 12000000; 1135 sclk = 12000000;
1068 1136
1069 div = PRCM_CLKSRC_CTRL; 1137 return sclk;
1070 div &= ((1 << 7) | (1 << 6)); 1138}
1071 div >>= sys->rate_offset; 1139
1140static u32 omap2_get_sysclkdiv(void)
1141{
1142 u32 div;
1143
1144 div = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL);
1145 div &= OMAP_SYSCLKDIV_MASK;
1146 div >>= OMAP_SYSCLKDIV_SHIFT;
1072 1147
1073 osc->rate = sclk * div; 1148 return div;
1074 sys->rate = sclk; 1149}
1150
1151static void omap2_osc_clk_recalc(struct clk *clk)
1152{
1153 clk->rate = omap2_get_apll_clkin() * omap2_get_sysclkdiv();
1154 propagate_rate(clk);
1155}
1156
1157static void omap2_sys_clk_recalc(struct clk *clk)
1158{
1159 clk->rate = clk->parent->rate / omap2_get_sysclkdiv();
1160 propagate_rate(clk);
1075} 1161}
1076 1162
1077/* 1163/*
@@ -1100,8 +1186,7 @@ static int __init omap2_clk_arch_init(void)
1100 if (omap2_select_table_rate(&virt_prcm_set, mpurate)) 1186 if (omap2_select_table_rate(&virt_prcm_set, mpurate))
1101 printk(KERN_ERR "Could not find matching MPU rate\n"); 1187 printk(KERN_ERR "Could not find matching MPU rate\n");
1102 1188
1103 propagate_rate(&osc_ck); /* update main root fast */ 1189 recalculate_root_clocks();
1104 propagate_rate(&func_32k_ck); /* update main root slow */
1105 1190
1106 printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL/MPU): " 1191 printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL/MPU): "
1107 "%ld.%01ld/%ld/%ld MHz\n", 1192 "%ld.%01ld/%ld/%ld MHz\n",
@@ -1115,13 +1200,21 @@ arch_initcall(omap2_clk_arch_init);
1115int __init omap2_clk_init(void) 1200int __init omap2_clk_init(void)
1116{ 1201{
1117 struct prcm_config *prcm; 1202 struct prcm_config *prcm;
1118 struct clk ** clkp; 1203 struct clk **clkp;
1119 u32 clkrate; 1204 u32 clkrate;
1120 1205
1206 if (cpu_is_omap242x())
1207 cpu_mask = RATE_IN_242X;
1208 else if (cpu_is_omap2430())
1209 cpu_mask = RATE_IN_243X;
1210
1121 clk_init(&omap2_clk_functions); 1211 clk_init(&omap2_clk_functions);
1122 omap2_get_crystal_rate(&osc_ck, &sys_ck);
1123 1212
1124 for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks); 1213 omap2_osc_clk_recalc(&osc_ck);
1214 omap2_sys_clk_recalc(&sys_ck);
1215
1216 for (clkp = onchip_24xx_clks;
1217 clkp < onchip_24xx_clks + ARRAY_SIZE(onchip_24xx_clks);
1125 clkp++) { 1218 clkp++) {
1126 1219
1127 if ((*clkp)->flags & CLOCK_IN_OMAP242X && cpu_is_omap2420()) { 1220 if ((*clkp)->flags & CLOCK_IN_OMAP242X && cpu_is_omap2420()) {
@@ -1136,8 +1229,10 @@ int __init omap2_clk_init(void)
1136 } 1229 }
1137 1230
1138 /* Check the MPU rate set by bootloader */ 1231 /* Check the MPU rate set by bootloader */
1139 clkrate = omap2_get_dpll_rate(&dpll_ck); 1232 clkrate = omap2_get_dpll_rate_24xx(&dpll_ck);
1140 for (prcm = rate_table; prcm->mpu_speed; prcm++) { 1233 for (prcm = rate_table; prcm->mpu_speed; prcm++) {
1234 if (!(prcm->flags & cpu_mask))
1235 continue;
1141 if (prcm->xtal_speed != sys_ck.rate) 1236 if (prcm->xtal_speed != sys_ck.rate)
1142 continue; 1237 continue;
1143 if (prcm->dpll_speed <= clkrate) 1238 if (prcm->dpll_speed <= clkrate)
@@ -1145,8 +1240,7 @@ int __init omap2_clk_init(void)
1145 } 1240 }
1146 curr_prcm_set = prcm; 1241 curr_prcm_set = prcm;
1147 1242
1148 propagate_rate(&osc_ck); /* update main root fast */ 1243 recalculate_root_clocks();
1149 propagate_rate(&func_32k_ck); /* update main root slow */
1150 1244
1151 printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): " 1245 printk(KERN_INFO "Clocking rate (Crystal/DPLL/MPU): "
1152 "%ld.%01ld/%ld/%ld MHz\n", 1246 "%ld.%01ld/%ld/%ld MHz\n",
@@ -1157,16 +1251,7 @@ int __init omap2_clk_init(void)
1157 * Only enable those clocks we will need, let the drivers 1251 * Only enable those clocks we will need, let the drivers
1158 * enable other clocks as necessary 1252 * enable other clocks as necessary
1159 */ 1253 */
1160 clk_enable(&sync_32k_ick); 1254 clk_enable_init_clocks();
1161 clk_enable(&omapctrl_ick);
1162
1163 /* Force the APLLs always active. The clocks are idled
1164 * automatically by hardware. */
1165 clk_enable(&apll96_ck);
1166 clk_enable(&apll54_ck);
1167
1168 if (cpu_is_omap2430())
1169 clk_enable(&sdrc_ick);
1170 1255
1171 /* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */ 1256 /* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
1172 vclk = clk_get(NULL, "virt_prcm_set"); 1257 vclk = clk_get(NULL, "virt_prcm_set");