2 * linux/arch/arm/mach-omap2/clock.c
4 * Copyright (C) 2005-2008 Texas Instruments, Inc.
5 * Copyright (C) 2004-2008 Nokia Corporation
8 * Richard Woodruff <r-woodruff2@ti.com>
11 * Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
12 * Gordon McNutt and RidgeRun, Inc.
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.
20 #include <linux/module.h>
21 #include <linux/kernel.h>
22 #include <linux/device.h>
23 #include <linux/list.h>
24 #include <linux/errno.h>
25 #include <linux/delay.h>
26 #include <linux/clk.h>
28 #include <linux/cpufreq.h>
29 #include <linux/bitops.h>
31 #include <mach/common.h>
32 #include <mach/clock.h>
33 #include <mach/sram.h>
34 #include <asm/div64.h>
36 #include <mach/sdrc.h>
38 #include "clock24xx.h"
40 #include "prm-regbits-24xx.h"
42 #include "cm-regbits-24xx.h"
44 /* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */
45 #define EN_APLL_STOPPED 0
46 #define EN_APLL_LOCKED 3
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
53 /* #define DOWN_VARIABLE_DPLL 1 */ /* Experimental */
55 static struct prcm_config
*curr_prcm_set
;
56 static struct clk
*vclk
;
57 static struct clk
*sclk
;
59 /*-------------------------------------------------------------------------
60 * Omap24xx specific clock functions
61 *-------------------------------------------------------------------------*/
64 * omap2xxx_clk_get_core_rate - return the CORE_CLK rate
65 * @clk: pointer to the combined dpll_ck + core_ck (currently "dpll_ck")
66 * @parent_rate: rate of the parent of the dpll_ck
68 * Returns the CORE_CLK rate. CORE_CLK can have one of three rate
69 * sources on OMAP2xxx: the DPLL CLKOUT rate, DPLL CLKOUTX2, or 32KHz
70 * (the latter is unusual). This currently should be called with
71 * struct clk *dpll_ck, which is a composite clock of dpll_ck and
74 static u32
omap2xxx_clk_get_core_rate(struct clk
*clk
,
75 unsigned long parent_rate
)
80 core_clk
= omap2_get_dpll_rate(clk
, parent_rate
);
82 v
= cm_read_mod_reg(PLL_MOD
, CM_CLKSEL2
);
83 v
&= OMAP24XX_CORE_CLK_SRC_MASK
;
85 if (v
== CORE_CLK_SRC_32K
)
93 static unsigned long omap2xxx_clk_find_oppset_by_mpurate(unsigned long mpu_speed
,
94 struct prcm_config
**prcm
)
96 unsigned long found_speed
= 0;
97 struct prcm_config
*p
;
101 for (p
= rate_table
; p
->mpu_speed
; p
++) {
102 if (!(p
->flags
& cpu_mask
))
105 if (p
->xtal_speed
!= sys_ck
.rate
)
108 if (p
->mpu_speed
<= mpu_speed
) {
109 found_speed
= p
->mpu_speed
;
117 static int omap2_enable_osc_ck(struct clk
*clk
)
119 prm_rmw_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK
, 0,
120 OMAP24XX_GR_MOD
, OMAP24XX_PRCM_CLKSRC_CTRL_OFFSET
);
125 static void omap2_disable_osc_ck(struct clk
*clk
)
127 prm_rmw_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK
, OMAP_AUTOEXTCLKMODE_MASK
,
128 OMAP24XX_GR_MOD
, OMAP24XX_PRCM_CLKSRC_CTRL_OFFSET
);
131 /* Enable an APLL if off */
132 static int omap2_clk_fixed_enable(struct clk
*clk
)
136 apll_mask
= EN_APLL_LOCKED
<< clk
->enable_bit
;
138 cval
= cm_read_mod_reg(PLL_MOD
, CM_CLKEN
);
140 if ((cval
& apll_mask
) == apll_mask
)
141 return 0; /* apll already enabled */
145 cm_write_mod_reg(cval
, PLL_MOD
, CM_CLKEN
);
147 if (clk
== &apll96_ck
)
148 cval
= OMAP24XX_ST_96M_APLL
;
149 else if (clk
== &apll54_ck
)
150 cval
= OMAP24XX_ST_54M_APLL
;
152 omap2_wait_clock_ready(PLL_MOD
, CM_IDLEST
, cval
, clk
->name
);
155 * REVISIT: Should we return an error code if omap2_wait_clock_ready()
162 static void omap2_clk_fixed_disable(struct clk
*clk
)
166 cval
= cm_read_mod_reg(PLL_MOD
, CM_CLKEN
);
167 cval
&= ~(EN_APLL_LOCKED
<< clk
->enable_bit
);
168 cm_write_mod_reg(cval
, PLL_MOD
, CM_CLKEN
);
172 * Uses the current prcm set to tell if a rate is valid.
173 * You can go slower, but not faster within a given rate set.
175 static long omap2_dpllcore_round_rate(unsigned long target_rate
)
177 u32 high
, low
, core_clk_src
;
179 core_clk_src
= cm_read_mod_reg(PLL_MOD
, CM_CLKSEL2
);
180 core_clk_src
&= OMAP24XX_CORE_CLK_SRC_MASK
;
182 if (core_clk_src
== CORE_CLK_SRC_DPLL
) { /* DPLL clockout */
183 high
= curr_prcm_set
->dpll_speed
* 2;
184 low
= curr_prcm_set
->dpll_speed
;
185 } else { /* DPLL clockout x 2 */
186 high
= curr_prcm_set
->dpll_speed
;
187 low
= curr_prcm_set
->dpll_speed
/ 2;
190 #ifdef DOWN_VARIABLE_DPLL
191 if (target_rate
> high
)
196 if (target_rate
> low
)
204 static void omap2_dpllcore_recalc(struct clk
*clk
, unsigned long parent_rate
,
209 rate
= omap2xxx_clk_get_core_rate(clk
, parent_rate
);
211 if (rate_storage
== CURRENT_RATE
)
213 else if (rate_storage
== TEMP_RATE
)
214 clk
->temp_rate
= rate
;
217 static int omap2_reprogram_dpllcore(struct clk
*clk
, unsigned long rate
)
219 u32 cur_rate
, low
, mult
, div
, valid_rate
, done_rate
;
221 struct prcm_config tmpset
;
222 const struct dpll_data
*dd
;
224 cur_rate
= omap2xxx_clk_get_core_rate(&dpll_ck
, dpll_ck
.parent
->rate
);
225 mult
= cm_read_mod_reg(PLL_MOD
, CM_CLKSEL2
);
226 mult
&= OMAP24XX_CORE_CLK_SRC_MASK
;
228 if ((rate
== (cur_rate
/ 2)) && (mult
== 2)) {
229 omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL
, 1);
230 } else if ((rate
== (cur_rate
* 2)) && (mult
== 1)) {
231 omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2
, 1);
232 } else if (rate
!= cur_rate
) {
233 valid_rate
= omap2_dpllcore_round_rate(rate
);
234 if (valid_rate
!= rate
)
238 low
= curr_prcm_set
->dpll_speed
;
240 low
= curr_prcm_set
->dpll_speed
/ 2;
246 tmpset
.cm_clksel1_pll
= cm_read_mod_reg(clk
->prcm_mod
,
248 tmpset
.cm_clksel1_pll
&= ~(dd
->mult_mask
|
250 div
= ((curr_prcm_set
->xtal_speed
/ 1000000) - 1);
251 tmpset
.cm_clksel2_pll
= cm_read_mod_reg(PLL_MOD
, CM_CLKSEL2
);
252 tmpset
.cm_clksel2_pll
&= ~OMAP24XX_CORE_CLK_SRC_MASK
;
254 tmpset
.cm_clksel2_pll
|= CORE_CLK_SRC_DPLL_X2
;
255 mult
= ((rate
/ 2) / 1000000);
256 done_rate
= CORE_CLK_SRC_DPLL_X2
;
258 tmpset
.cm_clksel2_pll
|= CORE_CLK_SRC_DPLL
;
259 mult
= (rate
/ 1000000);
260 done_rate
= CORE_CLK_SRC_DPLL
;
262 tmpset
.cm_clksel1_pll
|= (div
<< __ffs(dd
->mult_mask
));
263 tmpset
.cm_clksel1_pll
|= (mult
<< __ffs(dd
->div1_mask
));
266 tmpset
.base_sdrc_rfr
= SDRC_RFR_CTRL_BYPASS
;
268 if (rate
== curr_prcm_set
->xtal_speed
) /* If asking for 1-1 */
271 /* For omap2xxx_sdrc_init_params() */
272 omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2
, 1);
274 /* Force dll lock mode */
275 omap2_set_prcm(tmpset
.cm_clksel1_pll
, tmpset
.base_sdrc_rfr
,
278 /* Errata: ret dll entry state */
279 omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
280 omap2xxx_sdrc_reprogram(done_rate
, 0);
287 * omap2_table_mpu_recalc - just return the MPU speed
288 * @clk: virt_prcm_set struct clk
290 * Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
292 static void omap2_table_mpu_recalc(struct clk
*clk
, unsigned long parent_rate
,
295 struct prcm_config
*prcm
;
296 unsigned long mpurate
;
298 mpurate
= omap2xxx_clk_find_oppset_by_mpurate(parent_rate
, &prcm
);
300 if (rate_storage
== CURRENT_RATE
)
302 else if (rate_storage
== TEMP_RATE
)
303 clk
->temp_rate
= mpurate
;
307 * Look for a rate equal or less than the target rate given a configuration set.
309 * What's not entirely clear is "which" field represents the key field.
310 * Some might argue L3-DDR, others ARM, others IVA. This code is simple and
311 * just uses the ARM rates.
313 static long omap2_round_to_table_rate(struct clk
*clk
, unsigned long rate
)
315 struct prcm_config
*ptr
;
318 if (clk
!= &virt_prcm_set
)
321 highest_rate
= -EINVAL
;
323 for (ptr
= rate_table
; ptr
->mpu_speed
; ptr
++) {
324 if (!(ptr
->flags
& cpu_mask
))
326 if (ptr
->xtal_speed
!= sys_ck
.rate
)
329 highest_rate
= ptr
->mpu_speed
;
331 /* Can check only after xtal frequency check */
332 if (ptr
->mpu_speed
<= rate
)
338 /* Sets basic clocks based on the specified rate */
339 static int omap2_select_table_rate(struct clk
*clk
, unsigned long rate
)
341 u32 cur_rate
, done_rate
, bypass
= 0, tmp
;
342 struct prcm_config
*prcm
;
343 unsigned long flags
, found_speed
;
345 if (clk
!= &virt_prcm_set
)
348 found_speed
= omap2xxx_clk_find_oppset_by_mpurate(rate
, &prcm
);
350 printk(KERN_INFO
"Could not set MPU rate to %luMHz\n",
355 curr_prcm_set
= prcm
;
356 cur_rate
= omap2xxx_clk_get_core_rate(&dpll_ck
, dpll_ck
.parent
->rate
);
358 if (prcm
->dpll_speed
== cur_rate
/ 2) {
359 omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL
, 1);
360 } else if (prcm
->dpll_speed
== cur_rate
* 2) {
361 omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2
, 1);
362 } else if (prcm
->dpll_speed
!= cur_rate
) {
363 local_irq_save(flags
);
365 if (prcm
->dpll_speed
== prcm
->xtal_speed
)
368 if ((prcm
->cm_clksel2_pll
& OMAP24XX_CORE_CLK_SRC_MASK
) ==
369 CORE_CLK_SRC_DPLL_X2
)
370 done_rate
= CORE_CLK_SRC_DPLL_X2
;
372 done_rate
= CORE_CLK_SRC_DPLL
;
375 cm_write_mod_reg(prcm
->cm_clksel_mpu
, MPU_MOD
, CM_CLKSEL
);
377 /* dsp + iva1 div(2420), iva2.1(2430) */
378 cm_write_mod_reg(prcm
->cm_clksel_dsp
,
379 OMAP24XX_DSP_MOD
, CM_CLKSEL
);
381 cm_write_mod_reg(prcm
->cm_clksel_gfx
, GFX_MOD
, CM_CLKSEL
);
383 /* Major subsystem dividers */
384 tmp
= cm_read_mod_reg(CORE_MOD
, CM_CLKSEL1
) & OMAP24XX_CLKSEL_DSS2_MASK
;
385 cm_write_mod_reg(prcm
->cm_clksel1_core
| tmp
, CORE_MOD
,
388 if (cpu_is_omap2430())
389 cm_write_mod_reg(prcm
->cm_clksel_mdm
,
390 OMAP2430_MDM_MOD
, CM_CLKSEL
);
392 /* x2 to enter omap2xxx_sdrc_init_params() */
393 omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2
, 1);
395 omap2_set_prcm(prcm
->cm_clksel1_pll
, prcm
->base_sdrc_rfr
,
398 omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
399 omap2xxx_sdrc_reprogram(done_rate
, 0);
401 local_irq_restore(flags
);
407 #ifdef CONFIG_CPU_FREQ
409 * Walk PRCM rate table and fillout cpufreq freq_table
411 static struct cpufreq_frequency_table freq_table
[ARRAY_SIZE(rate_table
)];
413 void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table
**table
)
415 struct prcm_config
*prcm
;
418 for (prcm
= rate_table
; prcm
->mpu_speed
; prcm
++) {
419 if (!(prcm
->flags
& cpu_mask
))
421 if (prcm
->xtal_speed
!= sys_ck
.rate
)
424 /* don't put bypass rates in table */
425 if (prcm
->dpll_speed
== prcm
->xtal_speed
)
428 freq_table
[i
].index
= i
;
429 freq_table
[i
].frequency
= prcm
->mpu_speed
/ 1000;
434 printk(KERN_WARNING
"%s: failed to initialize frequency "
435 "table\n", __func__
);
439 freq_table
[i
].index
= i
;
440 freq_table
[i
].frequency
= CPUFREQ_TABLE_END
;
442 *table
= &freq_table
[0];
446 static struct clk_functions omap2_clk_functions
= {
447 .clk_register
= omap2_clk_register
,
448 .clk_enable
= omap2_clk_enable
,
449 .clk_disable
= omap2_clk_disable
,
450 .clk_round_rate
= omap2_clk_round_rate
,
451 .clk_set_rate
= omap2_clk_set_rate
,
452 .clk_set_parent
= omap2_clk_set_parent
,
453 .clk_get_parent
= omap2_clk_get_parent
,
454 .clk_disable_unused
= omap2_clk_disable_unused
,
455 #ifdef CONFIG_CPU_FREQ
456 .clk_init_cpufreq_table
= omap2_clk_init_cpufreq_table
,
460 static u32
omap2_get_apll_clkin(void)
462 u32 aplls
, srate
= 0;
464 aplls
= cm_read_mod_reg(PLL_MOD
, CM_CLKSEL1
);
465 aplls
&= OMAP24XX_APLLS_CLKIN_MASK
;
466 aplls
>>= OMAP24XX_APLLS_CLKIN_SHIFT
;
468 if (aplls
== APLLS_CLKIN_19_2MHZ
)
470 else if (aplls
== APLLS_CLKIN_13MHZ
)
472 else if (aplls
== APLLS_CLKIN_12MHZ
)
478 static u32
omap2_get_sysclkdiv(void)
482 div
= prm_read_mod_reg(OMAP24XX_GR_MOD
,
483 OMAP24XX_PRCM_CLKSRC_CTRL_OFFSET
);
484 div
&= OMAP_SYSCLKDIV_MASK
;
485 div
>>= OMAP_SYSCLKDIV_SHIFT
;
490 static void omap2_osc_clk_recalc(struct clk
*clk
, unsigned long parent_rate
,
495 /* XXX osc_ck on 2xxx currently is parentless */
496 rate
= omap2_get_apll_clkin() * omap2_get_sysclkdiv();
498 if (rate_storage
== CURRENT_RATE
)
500 else if (rate_storage
== TEMP_RATE
)
501 clk
->temp_rate
= rate
;
504 static void omap2_sys_clk_recalc(struct clk
*clk
, unsigned long parent_rate
,
509 rate
= parent_rate
/ omap2_get_sysclkdiv();
511 if (rate_storage
== CURRENT_RATE
)
513 else if (rate_storage
== TEMP_RATE
)
514 clk
->temp_rate
= rate
;
518 * Set clocks for bypass mode for reboot to work.
520 void omap2_clk_prepare_for_reboot(void)
524 if (vclk
== NULL
|| sclk
== NULL
)
527 rate
= clk_get_rate(sclk
);
528 clk_set_rate(vclk
, rate
);
532 * Switch the MPU rate if specified on cmdline.
533 * We cannot do this early until cmdline is parsed.
535 static int __init
omap2_clk_arch_init(void)
540 if (clk_set_rate(&virt_prcm_set
, mpurate
))
541 printk(KERN_ERR
"Could not find matching MPU rate\n");
543 recalculate_root_clocks();
545 printk(KERN_INFO
"Switched to new clocking rate (Crystal/DPLL/MPU): "
546 "%ld.%01ld/%ld/%ld MHz\n",
547 (sys_ck
.rate
/ 1000000), (sys_ck
.rate
/ 100000) % 10,
548 (dpll_ck
.rate
/ 1000000), (mpu_ck
.rate
/ 1000000)) ;
552 arch_initcall(omap2_clk_arch_init
);
554 int __init
omap2_clk_init(void)
556 struct prcm_config
*prcm
;
560 if (cpu_is_omap242x())
561 cpu_mask
= RATE_IN_242X
;
562 else if (cpu_is_omap2430())
563 cpu_mask
= RATE_IN_243X
;
565 clk_init(&omap2_clk_functions
);
567 omap2_osc_clk_recalc(&osc_ck
, 0, CURRENT_RATE
);
568 omap2_sys_clk_recalc(&sys_ck
, sys_ck
.parent
->rate
, CURRENT_RATE
);
570 for (clkp
= onchip_24xx_clks
;
571 clkp
< onchip_24xx_clks
+ ARRAY_SIZE(onchip_24xx_clks
);
574 if ((*clkp
)->flags
& CLOCK_IN_OMAP242X
&& cpu_is_omap2420()) {
579 if ((*clkp
)->flags
& CLOCK_IN_OMAP243X
&& cpu_is_omap2430()) {
585 /* Check the MPU rate set by bootloader */
586 clkrate
= omap2xxx_clk_get_core_rate(&dpll_ck
, dpll_ck
.parent
->rate
);
587 for (prcm
= rate_table
; prcm
->mpu_speed
; prcm
++) {
588 if (!(prcm
->flags
& cpu_mask
))
590 if (prcm
->xtal_speed
!= sys_ck
.rate
)
592 if (prcm
->dpll_speed
<= clkrate
)
595 curr_prcm_set
= prcm
;
597 recalculate_root_clocks();
599 printk(KERN_INFO
"Clocking rate (Crystal/DPLL/MPU): "
600 "%ld.%01ld/%ld/%ld MHz\n",
601 (sys_ck
.rate
/ 1000000), (sys_ck
.rate
/ 100000) % 10,
602 (dpll_ck
.rate
/ 1000000), (mpu_ck
.rate
/ 1000000)) ;
605 * Only enable those clocks we will need, let the drivers
606 * enable other clocks as necessary
608 clk_enable_init_clocks();
610 /* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */
611 vclk
= clk_get(NULL
, "virt_prcm_set");
612 sclk
= clk_get(NULL
, "sys_ck");