2 * linux/arch/arm/mach-omap2/clock.c
4 * Copyright (C) 2005 Texas Instruments Inc.
5 * Richard Woodruff <r-woodruff2@ti.com>
8 * Cleaned up and modified to use omap shared clock framework by
9 * Tony Lindgren <tony@atomide.com>
11 * Based on omap1 clock.c, Copyright (C) 2004 - 2005 Nokia corporation
12 * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
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.
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/device.h>
21 #include <linux/list.h>
22 #include <linux/errno.h>
23 #include <linux/delay.h>
24 #include <linux/clk.h>
28 #include <asm/arch/clock.h>
29 #include <asm/arch/sram.h>
31 #include "prcm-regs.h"
35 //#define DOWN_VARIABLE_DPLL 1 /* Experimental */
37 static struct prcm_config
*curr_prcm_set
;
38 static u32 curr_perf_level
= PRCM_FULL_SPEED
;
39 static struct clk
*vclk
;
40 static struct clk
*sclk
;
42 /*-------------------------------------------------------------------------
43 * Omap2 specific clock functions
44 *-------------------------------------------------------------------------*/
46 /* Recalculate SYST_CLK */
47 static void omap2_sys_clk_recalc(struct clk
* clk
)
49 u32 div
= PRCM_CLKSRC_CTRL
;
50 div
&= (1 << 7) | (1 << 6); /* Test if ext clk divided by 1 or 2 */
51 div
>>= clk
->rate_offset
;
52 clk
->rate
= (clk
->parent
->rate
/ div
);
56 static u32
omap2_get_dpll_rate(struct clk
* tclk
)
59 int dpll_mult
, dpll_div
, amult
;
61 dpll_mult
= (CM_CLKSEL1_PLL
>> 12) & 0x03ff; /* 10 bits */
62 dpll_div
= (CM_CLKSEL1_PLL
>> 8) & 0x0f; /* 4 bits */
63 dpll_clk
= (long long)tclk
->parent
->rate
* dpll_mult
;
64 do_div(dpll_clk
, dpll_div
+ 1);
65 amult
= CM_CLKSEL2_PLL
& 0x3;
71 static void omap2_followparent_recalc(struct clk
*clk
)
73 followparent_recalc(clk
);
76 static void omap2_propagate_rate(struct clk
* clk
)
78 if (!(clk
->flags
& RATE_FIXED
))
79 clk
->rate
= clk
->parent
->rate
;
84 /* Enable an APLL if off */
85 static void omap2_clk_fixed_enable(struct clk
*clk
)
89 if (clk
->enable_bit
== 0xff) /* Parent will do it */
94 if ((cval
& (0x3 << clk
->enable_bit
)) == (0x3 << clk
->enable_bit
))
97 cval
&= ~(0x3 << clk
->enable_bit
);
98 cval
|= (0x3 << clk
->enable_bit
);
101 if (clk
== &apll96_ck
)
103 else if (clk
== &apll54_ck
)
106 while (!(CM_IDLEST_CKGEN
& cval
)) { /* Wait for lock */
114 /* Enables clock without considering parent dependencies or use count
115 * REVISIT: Maybe change this to use clk->enable like on omap1?
117 static int _omap2_clk_enable(struct clk
* clk
)
121 if (clk
->flags
& ALWAYS_ENABLED
)
124 if (unlikely(clk
->enable_reg
== 0)) {
125 printk(KERN_ERR
"clock.c: Enable for %s without enable code\n",
130 if (clk
->enable_reg
== (void __iomem
*)&CM_CLKEN_PLL
) {
131 omap2_clk_fixed_enable(clk
);
135 regval32
= __raw_readl(clk
->enable_reg
);
136 regval32
|= (1 << clk
->enable_bit
);
137 __raw_writel(regval32
, clk
->enable_reg
);
143 static void omap2_clk_fixed_disable(struct clk
*clk
)
147 if(clk
->enable_bit
== 0xff) /* let parent off do it */
151 cval
&= ~(0x3 << clk
->enable_bit
);
155 /* Disables clock without considering parent dependencies or use count */
156 static void _omap2_clk_disable(struct clk
*clk
)
160 if (clk
->enable_reg
== 0)
163 if (clk
->enable_reg
== (void __iomem
*)&CM_CLKEN_PLL
) {
164 omap2_clk_fixed_disable(clk
);
168 regval32
= __raw_readl(clk
->enable_reg
);
169 regval32
&= ~(1 << clk
->enable_bit
);
170 __raw_writel(regval32
, clk
->enable_reg
);
173 static int omap2_clk_enable(struct clk
*clk
)
177 if (clk
->usecount
++ == 0) {
178 if (likely((u32
)clk
->parent
))
179 ret
= omap2_clk_enable(clk
->parent
);
181 if (unlikely(ret
!= 0)) {
186 ret
= _omap2_clk_enable(clk
);
188 if (unlikely(ret
!= 0) && clk
->parent
) {
189 omap2_clk_disable(clk
->parent
);
197 static void omap2_clk_disable(struct clk
*clk
)
199 if (clk
->usecount
> 0 && !(--clk
->usecount
)) {
200 _omap2_clk_disable(clk
);
201 if (likely((u32
)clk
->parent
))
202 omap2_clk_disable(clk
->parent
);
207 * Uses the current prcm set to tell if a rate is valid.
208 * You can go slower, but not faster within a given rate set.
210 static u32
omap2_dpll_round_rate(unsigned long target_rate
)
214 if ((CM_CLKSEL2_PLL
& 0x3) == 1) { /* DPLL clockout */
215 high
= curr_prcm_set
->dpll_speed
* 2;
216 low
= curr_prcm_set
->dpll_speed
;
217 } else { /* DPLL clockout x 2 */
218 high
= curr_prcm_set
->dpll_speed
;
219 low
= curr_prcm_set
->dpll_speed
/ 2;
222 #ifdef DOWN_VARIABLE_DPLL
223 if (target_rate
> high
)
228 if (target_rate
> low
)
237 * Used for clocks that are part of CLKSEL_xyz governed clocks.
238 * REVISIT: Maybe change to use clk->enable() functions like on omap1?
240 static void omap2_clksel_recalc(struct clk
* clk
)
242 u32 fixed
= 0, div
= 0;
244 if (clk
== &dpll_ck
) {
245 clk
->rate
= omap2_get_dpll_rate(clk
);
250 if (clk
== &iva1_mpu_int_ifck
) {
255 if ((clk
== &dss1_fck
) && ((CM_CLKSEL1_CORE
& (0x1f << 8)) == 0)) {
256 clk
->rate
= sys_ck
.rate
;
261 div
= omap2_clksel_get_divisor(clk
);
267 if (unlikely(clk
->rate
== clk
->parent
->rate
/ div
))
269 clk
->rate
= clk
->parent
->rate
/ div
;
272 if (unlikely(clk
->flags
& RATE_PROPAGATES
))
277 * Finds best divider value in an array based on the source and target
278 * rates. The divider array must be sorted with smallest divider first.
280 static inline u32
omap2_divider_from_table(u32 size
, u32
*div_array
,
281 u32 src_rate
, u32 tgt_rate
)
285 if (div_array
== NULL
)
288 for (i
=0; i
< size
; i
++) {
289 test_rate
= src_rate
/ *div_array
;
290 if (test_rate
<= tgt_rate
)
295 return ~0; /* No acceptable divider */
299 * Find divisor for the given clock and target rate.
301 * Note that this will not work for clocks which are part of CONFIG_PARTICIPANT,
302 * they are only settable as part of virtual_prcm set.
304 static u32
omap2_clksel_round_rate(struct clk
*tclk
, u32 target_rate
,
307 u32 gfx_div
[] = {2, 3, 4};
308 u32 sysclkout_div
[] = {1, 2, 4, 8, 16};
309 u32 dss1_div
[] = {1, 2, 3, 4, 5, 6, 8, 9, 12, 16};
310 u32 vylnq_div
[] = {1, 2, 3, 4, 6, 8, 9, 12, 16, 18};
311 u32 best_div
= ~0, asize
= 0;
312 u32
*div_array
= NULL
;
314 switch (tclk
->flags
& SRC_RATE_SEL_MASK
) {
320 return omap2_dpll_round_rate(target_rate
);
321 case CM_SYSCLKOUT_SEL1
:
323 div_array
= sysclkout_div
;
326 if(tclk
== &dss1_fck
){
327 if(tclk
->parent
== &core_ck
){
329 div_array
= dss1_div
;
331 *new_div
= 0; /* fixed clk */
332 return(tclk
->parent
->rate
);
334 } else if((tclk
== &vlynq_fck
) && cpu_is_omap2420()){
335 if(tclk
->parent
== &core_ck
){
337 div_array
= vylnq_div
;
339 *new_div
= 0; /* fixed clk */
340 return(tclk
->parent
->rate
);
346 best_div
= omap2_divider_from_table(asize
, div_array
,
347 tclk
->parent
->rate
, target_rate
);
350 return best_div
; /* signal error */
354 return (tclk
->parent
->rate
/ best_div
);
357 /* Given a clock and a rate apply a clock specific rounding function */
358 static long omap2_clk_round_rate(struct clk
*clk
, unsigned long rate
)
363 if (clk
->flags
& RATE_FIXED
)
366 if (clk
->flags
& RATE_CKCTL
) {
367 valid_rate
= omap2_clksel_round_rate(clk
, rate
, &new_div
);
371 if (clk
->round_rate
!= 0)
372 return clk
->round_rate(clk
, rate
);
378 * Check the DLL lock state, and return tue if running in unlock mode.
379 * This is needed to compenste for the shifted DLL value in unlock mode.
381 static u32
omap2_dll_force_needed(void)
383 u32 dll_state
= SDRC_DLLA_CTRL
; /* dlla and dllb are a set */
385 if ((dll_state
& (1 << 2)) == (1 << 2))
391 static u32
omap2_reprogram_sdrc(u32 level
, u32 force
)
393 u32 slow_dll_ctrl
, fast_dll_ctrl
, m_type
;
394 u32 prev
= curr_perf_level
, flags
;
396 if ((curr_perf_level
== level
) && !force
)
399 m_type
= omap2_memory_get_type();
400 slow_dll_ctrl
= omap2_memory_get_slow_dll_ctrl();
401 fast_dll_ctrl
= omap2_memory_get_fast_dll_ctrl();
403 if (level
== PRCM_HALF_SPEED
) {
404 local_irq_save(flags
);
405 PRCM_VOLTSETUP
= 0xffff;
406 omap2_sram_reprogram_sdrc(PRCM_HALF_SPEED
,
407 slow_dll_ctrl
, m_type
);
408 curr_perf_level
= PRCM_HALF_SPEED
;
409 local_irq_restore(flags
);
411 if (level
== PRCM_FULL_SPEED
) {
412 local_irq_save(flags
);
413 PRCM_VOLTSETUP
= 0xffff;
414 omap2_sram_reprogram_sdrc(PRCM_FULL_SPEED
,
415 fast_dll_ctrl
, m_type
);
416 curr_perf_level
= PRCM_FULL_SPEED
;
417 local_irq_restore(flags
);
423 static int omap2_reprogram_dpll(struct clk
* clk
, unsigned long rate
)
425 u32 flags
, cur_rate
, low
, mult
, div
, valid_rate
, done_rate
;
427 struct prcm_config tmpset
;
430 local_irq_save(flags
);
431 cur_rate
= omap2_get_dpll_rate(&dpll_ck
);
432 mult
= CM_CLKSEL2_PLL
& 0x3;
434 if ((rate
== (cur_rate
/ 2)) && (mult
== 2)) {
435 omap2_reprogram_sdrc(PRCM_HALF_SPEED
, 1);
436 } else if ((rate
== (cur_rate
* 2)) && (mult
== 1)) {
437 omap2_reprogram_sdrc(PRCM_FULL_SPEED
, 1);
438 } else if (rate
!= cur_rate
) {
439 valid_rate
= omap2_dpll_round_rate(rate
);
440 if (valid_rate
!= rate
)
443 if ((CM_CLKSEL2_PLL
& 0x3) == 1)
444 low
= curr_prcm_set
->dpll_speed
;
446 low
= curr_prcm_set
->dpll_speed
/ 2;
448 tmpset
.cm_clksel1_pll
= CM_CLKSEL1_PLL
;
449 tmpset
.cm_clksel1_pll
&= ~(0x3FFF << 8);
450 div
= ((curr_prcm_set
->xtal_speed
/ 1000000) - 1);
451 tmpset
.cm_clksel2_pll
= CM_CLKSEL2_PLL
;
452 tmpset
.cm_clksel2_pll
&= ~0x3;
454 tmpset
.cm_clksel2_pll
|= 0x2;
455 mult
= ((rate
/ 2) / 1000000);
456 done_rate
= PRCM_FULL_SPEED
;
458 tmpset
.cm_clksel2_pll
|= 0x1;
459 mult
= (rate
/ 1000000);
460 done_rate
= PRCM_HALF_SPEED
;
462 tmpset
.cm_clksel1_pll
|= ((div
<< 8) | (mult
<< 12));
465 tmpset
.base_sdrc_rfr
= V24XX_SDRC_RFR_CTRL_BYPASS
;
467 if (rate
== curr_prcm_set
->xtal_speed
) /* If asking for 1-1 */
470 omap2_reprogram_sdrc(PRCM_FULL_SPEED
, 1); /* For init_mem */
472 /* Force dll lock mode */
473 omap2_set_prcm(tmpset
.cm_clksel1_pll
, tmpset
.base_sdrc_rfr
,
476 /* Errata: ret dll entry state */
477 omap2_init_memory_params(omap2_dll_force_needed());
478 omap2_reprogram_sdrc(done_rate
, 0);
480 omap2_clksel_recalc(&dpll_ck
);
484 local_irq_restore(flags
);
488 /* Just return the MPU speed */
489 static void omap2_mpu_recalc(struct clk
* clk
)
491 clk
->rate
= curr_prcm_set
->mpu_speed
;
495 * Look for a rate equal or less than the target rate given a configuration set.
497 * What's not entirely clear is "which" field represents the key field.
498 * Some might argue L3-DDR, others ARM, others IVA. This code is simple and
499 * just uses the ARM rates.
501 static long omap2_round_to_table_rate(struct clk
* clk
, unsigned long rate
)
503 struct prcm_config
* ptr
;
506 if (clk
!= &virt_prcm_set
)
509 highest_rate
= -EINVAL
;
511 for (ptr
= rate_table
; ptr
->mpu_speed
; ptr
++) {
512 if (ptr
->xtal_speed
!= sys_ck
.rate
)
515 highest_rate
= ptr
->mpu_speed
;
517 /* Can check only after xtal frequency check */
518 if (ptr
->mpu_speed
<= rate
)
525 * omap2_convert_field_to_div() - turn field value into integer divider
527 static u32
omap2_clksel_to_divisor(u32 div_sel
, u32 field_val
)
530 u32 clkout_array
[] = {1, 2, 4, 8, 16};
532 if ((div_sel
& SRC_RATE_SEL_MASK
) == CM_SYSCLKOUT_SEL1
) {
533 for (i
= 0; i
< 5; i
++) {
535 return clkout_array
[i
];
543 * Returns the CLKSEL divider register value
544 * REVISIT: This should be cleaned up to work nicely with void __iomem *
546 static u32
omap2_get_clksel(u32
*div_sel
, u32
*field_mask
,
550 u32 reg_val
, div_off
;
554 div_off
= clk
->rate_offset
;
556 switch ((*div_sel
& SRC_RATE_SEL_MASK
)) {
558 div_addr
= (u32
)&CM_CLKSEL_MPU
;
562 div_addr
= (u32
)&CM_CLKSEL_DSP
;
563 if (cpu_is_omap2420()) {
564 if ((div_off
== 0) || (div_off
== 8))
566 else if (div_off
== 5)
568 } else if (cpu_is_omap2430()) {
571 else if (div_off
== 5)
576 div_addr
= (u32
)&CM_CLKSEL_GFX
;
581 div_addr
= (u32
)&CM_CLKSEL_MDM
;
585 case CM_SYSCLKOUT_SEL1
:
586 div_addr
= (u32
)&PRCM_CLKOUT_CTRL
;
587 if ((div_off
== 3) || (div_off
= 11))
591 div_addr
= (u32
)&CM_CLKSEL1_CORE
;
595 case 15: /* vylnc-2420 */
609 if (unlikely(mask
== ~0))
614 if (unlikely(div_addr
== 0))
618 reg_val
= __raw_readl((void __iomem
*)div_addr
) & (mask
<< div_off
);
620 /* Normalize back to divider value */
627 * Return divider to be applied to parent clock.
630 static u32
omap2_clksel_get_divisor(struct clk
*clk
)
633 u32 div
, div_sel
, div_off
, field_mask
, field_val
;
635 /* isolate control register */
636 div_sel
= (SRC_RATE_SEL_MASK
& clk
->flags
);
638 div_off
= clk
->rate_offset
;
639 field_val
= omap2_get_clksel(&div_sel
, &field_mask
, clk
);
643 div_sel
= (SRC_RATE_SEL_MASK
& clk
->flags
);
644 div
= omap2_clksel_to_divisor(div_sel
, field_val
);
649 /* Set the clock rate for a clock source */
650 static int omap2_clk_set_rate(struct clk
*clk
, unsigned long rate
)
655 u32 div_sel
, div_off
, field_mask
, field_val
, reg_val
, validrate
;
658 if (!(clk
->flags
& CONFIG_PARTICIPANT
) && (clk
->flags
& RATE_CKCTL
)) {
660 return omap2_reprogram_dpll(clk
, rate
);
662 /* Isolate control register */
663 div_sel
= (SRC_RATE_SEL_MASK
& clk
->flags
);
664 div_off
= clk
->rate_offset
;
666 validrate
= omap2_clksel_round_rate(clk
, rate
, &new_div
);
667 if (validrate
!= rate
)
670 field_val
= omap2_get_clksel(&div_sel
, &field_mask
, clk
);
674 if (clk
->flags
& CM_SYSCLKOUT_SEL1
) {
695 reg
= (void __iomem
*)div_sel
;
697 reg_val
= __raw_readl(reg
);
698 reg_val
&= ~(field_mask
<< div_off
);
699 reg_val
|= (field_val
<< div_off
);
701 __raw_writel(reg_val
, reg
);
702 clk
->rate
= clk
->parent
->rate
/ field_val
;
704 if (clk
->flags
& DELAYED_APP
)
705 __raw_writel(0x1, (void __iomem
*)&PRCM_CLKCFG_CTRL
);
707 } else if (clk
->set_rate
!= 0)
708 ret
= clk
->set_rate(clk
, rate
);
710 if (unlikely(ret
== 0 && (clk
->flags
& RATE_PROPAGATES
)))
716 /* Converts encoded control register address into a full address */
717 static u32
omap2_get_src_field(u32
*type_to_addr
, u32 reg_offset
,
718 struct clk
*src_clk
, u32
*field_mask
)
720 u32 val
= ~0, src_reg_addr
= 0, mask
= 0;
722 /* Find target control register.*/
723 switch ((*type_to_addr
& SRC_RATE_SEL_MASK
)) {
725 src_reg_addr
= (u32
)&CM_CLKSEL1_CORE
;
726 if (reg_offset
== 13) { /* DSS2_fclk */
728 if (src_clk
== &sys_ck
)
730 if (src_clk
== &func_48m_ck
)
732 } else if (reg_offset
== 8) { /* DSS1_fclk */
734 if (src_clk
== &sys_ck
)
736 else if (src_clk
== &core_ck
) /* divided clock */
737 val
= 0x10; /* rate needs fixing */
738 } else if ((reg_offset
== 15) && cpu_is_omap2420()){ /*vlnyq*/
740 if(src_clk
== &func_96m_ck
)
742 else if (src_clk
== &core_ck
)
747 src_reg_addr
= (u32
)&CM_CLKSEL2_CORE
;
749 if (src_clk
== &func_32k_ck
)
751 if (src_clk
== &sys_ck
)
753 if (src_clk
== &alt_ck
)
757 src_reg_addr
= (u32
)&CM_CLKSEL_WKUP
;
759 if (src_clk
== &func_32k_ck
)
761 if (src_clk
== &sys_ck
)
763 if (src_clk
== &alt_ck
)
767 src_reg_addr
= (u32
)&CM_CLKSEL1_PLL
;
769 if (reg_offset
== 0x3) {
770 if (src_clk
== &apll96_ck
)
772 if (src_clk
== &alt_ck
)
775 else if (reg_offset
== 0x5) {
776 if (src_clk
== &apll54_ck
)
778 if (src_clk
== &alt_ck
)
783 src_reg_addr
= (u32
)&CM_CLKSEL2_PLL
;
785 if (src_clk
== &func_32k_ck
)
787 if (src_clk
== &dpll_ck
)
790 case CM_SYSCLKOUT_SEL1
:
791 src_reg_addr
= (u32
)&PRCM_CLKOUT_CTRL
;
793 if (src_clk
== &dpll_ck
)
795 if (src_clk
== &sys_ck
)
797 if (src_clk
== &func_96m_ck
)
799 if (src_clk
== &func_54m_ck
)
804 if (val
== ~0) /* Catch errors in offset */
807 *type_to_addr
= src_reg_addr
;
813 static int omap2_clk_set_parent(struct clk
*clk
, struct clk
*new_parent
)
816 u32 src_sel
, src_off
, field_val
, field_mask
, reg_val
, rate
;
819 if (unlikely(clk
->flags
& CONFIG_PARTICIPANT
))
822 if (clk
->flags
& SRC_SEL_MASK
) { /* On-chip SEL collection */
823 src_sel
= (SRC_RATE_SEL_MASK
& clk
->flags
);
824 src_off
= clk
->src_offset
;
827 goto set_parent_error
;
829 field_val
= omap2_get_src_field(&src_sel
, src_off
, new_parent
,
832 reg
= (void __iomem
*)src_sel
;
834 if (clk
->usecount
> 0)
835 _omap2_clk_disable(clk
);
837 /* Set new source value (previous dividers if any in effect) */
838 reg_val
= __raw_readl(reg
) & ~(field_mask
<< src_off
);
839 reg_val
|= (field_val
<< src_off
);
840 __raw_writel(reg_val
, reg
);
842 if (clk
->flags
& DELAYED_APP
)
843 __raw_writel(0x1, (void __iomem
*)&PRCM_CLKCFG_CTRL
);
845 if (clk
->usecount
> 0)
846 _omap2_clk_enable(clk
);
848 clk
->parent
= new_parent
;
850 /* SRC_RATE_SEL_MASK clocks follow their parents rates.*/
851 if ((new_parent
== &core_ck
) && (clk
== &dss1_fck
))
852 clk
->rate
= new_parent
->rate
/ 0x10;
854 clk
->rate
= new_parent
->rate
;
856 if (unlikely(clk
->flags
& RATE_PROPAGATES
))
861 clk
->parent
= new_parent
;
862 rate
= new_parent
->rate
;
863 omap2_clk_set_rate(clk
, rate
);
871 /* Sets basic clocks based on the specified rate */
872 static int omap2_select_table_rate(struct clk
* clk
, unsigned long rate
)
874 u32 flags
, cur_rate
, done_rate
, bypass
= 0;
876 struct prcm_config
*prcm
;
877 unsigned long found_speed
= 0;
879 if (clk
!= &virt_prcm_set
)
882 /* FIXME: Change cpu_is_omap2420() to cpu_is_omap242x() */
883 if (cpu_is_omap2420())
884 cpu_mask
= RATE_IN_242X
;
885 else if (cpu_is_omap2430())
886 cpu_mask
= RATE_IN_243X
;
888 for (prcm
= rate_table
; prcm
->mpu_speed
; prcm
++) {
889 if (!(prcm
->flags
& cpu_mask
))
892 if (prcm
->xtal_speed
!= sys_ck
.rate
)
895 if (prcm
->mpu_speed
<= rate
) {
896 found_speed
= prcm
->mpu_speed
;
902 printk(KERN_INFO
"Could not set MPU rate to %luMHz\n",
907 curr_prcm_set
= prcm
;
908 cur_rate
= omap2_get_dpll_rate(&dpll_ck
);
910 if (prcm
->dpll_speed
== cur_rate
/ 2) {
911 omap2_reprogram_sdrc(PRCM_HALF_SPEED
, 1);
912 } else if (prcm
->dpll_speed
== cur_rate
* 2) {
913 omap2_reprogram_sdrc(PRCM_FULL_SPEED
, 1);
914 } else if (prcm
->dpll_speed
!= cur_rate
) {
915 local_irq_save(flags
);
917 if (prcm
->dpll_speed
== prcm
->xtal_speed
)
920 if ((prcm
->cm_clksel2_pll
& 0x3) == 2)
921 done_rate
= PRCM_FULL_SPEED
;
923 done_rate
= PRCM_HALF_SPEED
;
926 CM_CLKSEL_MPU
= prcm
->cm_clksel_mpu
;
928 /* dsp + iva1 div(2420), iva2.1(2430) */
929 CM_CLKSEL_DSP
= prcm
->cm_clksel_dsp
;
931 CM_CLKSEL_GFX
= prcm
->cm_clksel_gfx
;
933 /* Major subsystem dividers */
934 CM_CLKSEL1_CORE
= prcm
->cm_clksel1_core
;
935 if (cpu_is_omap2430())
936 CM_CLKSEL_MDM
= prcm
->cm_clksel_mdm
;
938 /* x2 to enter init_mem */
939 omap2_reprogram_sdrc(PRCM_FULL_SPEED
, 1);
941 omap2_set_prcm(prcm
->cm_clksel1_pll
, prcm
->base_sdrc_rfr
,
944 omap2_init_memory_params(omap2_dll_force_needed());
945 omap2_reprogram_sdrc(done_rate
, 0);
947 local_irq_restore(flags
);
949 omap2_clksel_recalc(&dpll_ck
);
954 /*-------------------------------------------------------------------------
955 * Omap2 clock reset and init functions
956 *-------------------------------------------------------------------------*/
958 static struct clk_functions omap2_clk_functions
= {
959 .clk_enable
= omap2_clk_enable
,
960 .clk_disable
= omap2_clk_disable
,
961 .clk_round_rate
= omap2_clk_round_rate
,
962 .clk_set_rate
= omap2_clk_set_rate
,
963 .clk_set_parent
= omap2_clk_set_parent
,
966 static void __init
omap2_get_crystal_rate(struct clk
*osc
, struct clk
*sys
)
968 u32 div
, aplls
, sclk
= 13000000;
970 aplls
= CM_CLKSEL1_PLL
;
971 aplls
&= ((1 << 23) | (1 << 24) | (1 << 25));
972 aplls
>>= 23; /* Isolate field, 0,2,3 */
981 div
= PRCM_CLKSRC_CTRL
;
982 div
&= ((1 << 7) | (1 << 6));
983 div
>>= sys
->rate_offset
;
985 osc
->rate
= sclk
* div
;
990 * Set clocks for bypass mode for reboot to work.
992 void omap2_clk_prepare_for_reboot(void)
996 if (vclk
== NULL
|| sclk
== NULL
)
999 rate
= clk_get_rate(sclk
);
1000 clk_set_rate(vclk
, rate
);
1003 #ifdef CONFIG_OMAP_RESET_CLOCKS
1004 static void __init
omap2_disable_unused_clocks(void)
1009 list_for_each_entry(ck
, &clocks
, node
) {
1010 if (ck
->usecount
> 0 || (ck
->flags
& ALWAYS_ENABLED
) ||
1011 ck
->enable_reg
== 0)
1014 regval32
= __raw_readl(ck
->enable_reg
);
1015 if ((regval32
& (1 << ck
->enable_bit
)) == 0)
1018 printk(KERN_INFO
"Disabling unused clock \"%s\"\n", ck
->name
);
1019 _omap2_clk_disable(ck
);
1022 late_initcall(omap2_disable_unused_clocks
);
1026 * Switch the MPU rate if specified on cmdline.
1027 * We cannot do this early until cmdline is parsed.
1029 static int __init
omap2_clk_arch_init(void)
1034 if (omap2_select_table_rate(&virt_prcm_set
, mpurate
))
1035 printk(KERN_ERR
"Could not find matching MPU rate\n");
1037 propagate_rate(&osc_ck
); /* update main root fast */
1038 propagate_rate(&func_32k_ck
); /* update main root slow */
1040 printk(KERN_INFO
"Switched to new clocking rate (Crystal/DPLL/MPU): "
1041 "%ld.%01ld/%ld/%ld MHz\n",
1042 (sys_ck
.rate
/ 1000000), (sys_ck
.rate
/ 100000) % 10,
1043 (dpll_ck
.rate
/ 1000000), (mpu_ck
.rate
/ 1000000)) ;
1047 arch_initcall(omap2_clk_arch_init
);
1049 int __init
omap2_clk_init(void)
1051 struct prcm_config
*prcm
;
1055 clk_init(&omap2_clk_functions
);
1056 omap2_get_crystal_rate(&osc_ck
, &sys_ck
);
1058 for (clkp
= onchip_clks
; clkp
< onchip_clks
+ ARRAY_SIZE(onchip_clks
);
1061 if ((*clkp
)->flags
& CLOCK_IN_OMAP242X
&& cpu_is_omap2420()) {
1062 clk_register(*clkp
);
1066 if ((*clkp
)->flags
& CLOCK_IN_OMAP243X
&& cpu_is_omap2430()) {
1067 clk_register(*clkp
);
1072 /* Check the MPU rate set by bootloader */
1073 clkrate
= omap2_get_dpll_rate(&dpll_ck
);
1074 for (prcm
= rate_table
; prcm
->mpu_speed
; prcm
++) {
1075 if (prcm
->xtal_speed
!= sys_ck
.rate
)
1077 if (prcm
->dpll_speed
<= clkrate
)
1080 curr_prcm_set
= prcm
;
1082 propagate_rate(&osc_ck
); /* update main root fast */
1083 propagate_rate(&func_32k_ck
); /* update main root slow */
1085 printk(KERN_INFO
"Clocking rate (Crystal/DPLL/MPU): "
1086 "%ld.%01ld/%ld/%ld MHz\n",
1087 (sys_ck
.rate
/ 1000000), (sys_ck
.rate
/ 100000) % 10,
1088 (dpll_ck
.rate
/ 1000000), (mpu_ck
.rate
/ 1000000)) ;
1091 * Only enable those clocks we will need, let the drivers
1092 * enable other clocks as necessary
1094 clk_enable(&sync_32k_ick
);
1095 clk_enable(&omapctrl_ick
);
1096 if (cpu_is_omap2430())
1097 clk_enable(&sdrc_ick
);
1099 /* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
1100 vclk
= clk_get(NULL
, "virt_prcm_set");
1101 sclk
= clk_get(NULL
, "sys_ck");