diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2009-02-19 08:29:22 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-02-19 12:28:30 -0500 |
commit | c0bf31320dea2cbcbab1f53ee15a8520f762409b (patch) | |
tree | 1b4fbb4396da448eb116f2bee8b58030b63cfe3b /arch/arm/mach-omap2/clock24xx.c | |
parent | 8b9dbc16d4f5786c6c930ab028722e3ed7e4285b (diff) |
[ARM] omap: add support for bypassing DPLLs
This roughly corresponds with OMAP commits: 7d06c48, 3241b19,
88b5d9b, 18a5500, 9c909ac, 5c6497b, 8b1f0bd, 2ac1da8.
For both OMAP2 and OMAP3, we note the reference and bypass clocks in
the DPLL data structure. Whenever we modify the DPLL rate, we first
ensure that both the reference and bypass clocks are enabled. Then,
we decide whether to use the reference and DPLL, or the bypass clock
if the desired rate is identical to the bypass rate, and program the
DPLL appropriately. Finally, we update the clock's parent, and then
disable the unused clocks.
This keeps the parents correctly balanced, and more importantly ensures
that the bypass clock is running whenever we reprogram the DPLL. This
is especially important because the procedure for reprogramming the DPLL
involves switching to the bypass clock.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-omap2/clock24xx.c')
-rw-r--r-- | arch/arm/mach-omap2/clock24xx.c | 39 |
1 files changed, 26 insertions, 13 deletions
diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index f2b74e9b7d8d..1e839c5a28c5 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c | |||
@@ -236,19 +236,32 @@ static struct clk *sclk; | |||
236 | * Omap24xx specific clock functions | 236 | * Omap24xx specific clock functions |
237 | *-------------------------------------------------------------------------*/ | 237 | *-------------------------------------------------------------------------*/ |
238 | 238 | ||
239 | /* This actually returns the rate of core_ck, not dpll_ck. */ | 239 | /** |
240 | static u32 omap2_get_dpll_rate_24xx(struct clk *tclk) | 240 | * omap2xxx_clk_get_core_rate - return the CORE_CLK rate |
241 | * @clk: pointer to the combined dpll_ck + core_ck (currently "dpll_ck") | ||
242 | * | ||
243 | * Returns the CORE_CLK rate. CORE_CLK can have one of three rate | ||
244 | * sources on OMAP2xxx: the DPLL CLKOUT rate, DPLL CLKOUTX2, or 32KHz | ||
245 | * (the latter is unusual). This currently should be called with | ||
246 | * struct clk *dpll_ck, which is a composite clock of dpll_ck and | ||
247 | * core_ck. | ||
248 | */ | ||
249 | static unsigned long omap2xxx_clk_get_core_rate(struct clk *clk) | ||
241 | { | 250 | { |
242 | long long dpll_clk; | 251 | long long core_clk; |
243 | u8 amult; | 252 | u32 v; |
244 | 253 | ||
245 | dpll_clk = omap2_get_dpll_rate(tclk); | 254 | core_clk = omap2_get_dpll_rate(clk); |
246 | 255 | ||
247 | amult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2); | 256 | v = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2); |
248 | amult &= OMAP24XX_CORE_CLK_SRC_MASK; | 257 | v &= OMAP24XX_CORE_CLK_SRC_MASK; |
249 | dpll_clk *= amult; | 258 | |
259 | if (v == CORE_CLK_SRC_32K) | ||
260 | core_clk = 32768; | ||
261 | else | ||
262 | core_clk *= v; | ||
250 | 263 | ||
251 | return dpll_clk; | 264 | return core_clk; |
252 | } | 265 | } |
253 | 266 | ||
254 | static int omap2_enable_osc_ck(struct clk *clk) | 267 | static int omap2_enable_osc_ck(struct clk *clk) |
@@ -371,7 +384,7 @@ static long omap2_dpllcore_round_rate(unsigned long target_rate) | |||
371 | 384 | ||
372 | static unsigned long omap2_dpllcore_recalc(struct clk *clk) | 385 | static unsigned long omap2_dpllcore_recalc(struct clk *clk) |
373 | { | 386 | { |
374 | return omap2_get_dpll_rate_24xx(clk); | 387 | return omap2xxx_clk_get_core_rate(clk); |
375 | } | 388 | } |
376 | 389 | ||
377 | static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate) | 390 | static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate) |
@@ -381,7 +394,7 @@ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate) | |||
381 | struct prcm_config tmpset; | 394 | struct prcm_config tmpset; |
382 | const struct dpll_data *dd; | 395 | const struct dpll_data *dd; |
383 | 396 | ||
384 | cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck); | 397 | cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck); |
385 | mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2); | 398 | mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2); |
386 | mult &= OMAP24XX_CORE_CLK_SRC_MASK; | 399 | mult &= OMAP24XX_CORE_CLK_SRC_MASK; |
387 | 400 | ||
@@ -516,7 +529,7 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate) | |||
516 | } | 529 | } |
517 | 530 | ||
518 | curr_prcm_set = prcm; | 531 | curr_prcm_set = prcm; |
519 | cur_rate = omap2_get_dpll_rate_24xx(&dpll_ck); | 532 | cur_rate = omap2xxx_clk_get_core_rate(&dpll_ck); |
520 | 533 | ||
521 | if (prcm->dpll_speed == cur_rate / 2) { | 534 | if (prcm->dpll_speed == cur_rate / 2) { |
522 | omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1); | 535 | omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1); |
@@ -728,7 +741,7 @@ int __init omap2_clk_init(void) | |||
728 | } | 741 | } |
729 | 742 | ||
730 | /* Check the MPU rate set by bootloader */ | 743 | /* Check the MPU rate set by bootloader */ |
731 | clkrate = omap2_get_dpll_rate_24xx(&dpll_ck); | 744 | clkrate = omap2xxx_clk_get_core_rate(&dpll_ck); |
732 | for (prcm = rate_table; prcm->mpu_speed; prcm++) { | 745 | for (prcm = rate_table; prcm->mpu_speed; prcm++) { |
733 | if (!(prcm->flags & cpu_mask)) | 746 | if (!(prcm->flags & cpu_mask)) |
734 | continue; | 747 | continue; |