diff options
author | Paul Walmsley <paul@pwsan.com> | 2009-01-28 12:27:42 -0700 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-02-08 17:50:40 +0000 |
commit | 0eafd4725cf5d828e76e474b8991a228bbdd3f2b (patch) | |
tree | 797186618cb16d1ddb3f42a1ac9c9d4f84bdc7c1 /arch/arm/mach-omap2 | |
parent | 87246b7567f7d1951bfcea29875523ef435c0ebf (diff) |
[ARM] OMAP3 clock: add omap3_core_dpll_m2_set_rate()
Add the omap3_core_dpll_m2_set_rate() function to the OMAP3 clock code,
which calls into the SRAM function omap3_sram_configure_core_dpll() to
change the CORE DPLL M2 divider. (SRAM code is necessary since rate changes
on clocks upstream from the SDRC can glitch SDRAM accesses.)
Use this function for the set_rate function pointer in the dpll3_m2_ck
struct clk. With this function in place, PM/OPP code should be able to
alter SDRAM speed via code similar to:
clk_set_rate(&dpll3_m2_ck, target_rate).
linux-omap source commit is 7f8b2b0f4fe52238c67d79dedcd2794dcef4dddd.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r-- | arch/arm/mach-omap2/clock34xx.c | 65 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock34xx.h | 9 |
2 files changed, 69 insertions, 5 deletions
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 52385b1506e0..1ad0a1359cb8 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -634,6 +634,71 @@ static int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate) return omap3_noncore_dpll_set_rate(clk, rate); } + +/* + * CORE DPLL (DPLL3) rate programming functions + * + * These call into SRAM code to do the actual CM writes, since the SDRAM + * is clocked from DPLL3. + */ + +/** + * omap3_core_dpll_m2_set_rate - set CORE DPLL M2 divider + * @clk: struct clk * of DPLL to set + * @rate: rounded target rate + * + * Program the DPLL M2 divider with the rounded target rate. Returns + * -EINVAL upon error, or 0 upon success. + */ +static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate) +{ + u32 new_div = 0; + unsigned long validrate, sdrcrate; + struct omap_sdrc_params *sp; + + if (!clk || !rate) + return -EINVAL; + + if (clk != &dpll3_m2_ck) + return -EINVAL; + + if (rate == clk->rate) + return 0; + + validrate = omap2_clksel_round_rate_div(clk, rate, &new_div); + if (validrate != rate) + return -EINVAL; + + sdrcrate = sdrc_ick.rate; + if (rate > clk->rate) + sdrcrate <<= ((rate / clk->rate) - 1); + else + sdrcrate >>= ((clk->rate / rate) - 1); + + sp = omap2_sdrc_get_params(sdrcrate); + if (!sp) + return -EINVAL; + + pr_info("clock: changing CORE DPLL rate from %lu to %lu\n", clk->rate, + validrate); + pr_info("clock: SDRC timing params used: %08x %08x %08x\n", + sp->rfr_ctrl, sp->actim_ctrla, sp->actim_ctrlb); + + /* REVISIT: SRAM code doesn't support other M2 divisors yet */ + WARN_ON(new_div != 1 && new_div != 2); + + /* REVISIT: Add SDRC_MR changing to this code also */ + local_irq_disable(); + omap3_configure_core_dpll(sp->rfr_ctrl, sp->actim_ctrla, + sp->actim_ctrlb, new_div); + local_irq_enable(); + + omap2_clksel_recalc(clk); + + return 0; +} + + static const struct clkops clkops_noncore_dpll_ops = { .enable = &omap3_noncore_dpll_enable, .disable = &omap3_noncore_dpll_disable, diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index aadd296c05a2..681acf0427c1 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -34,6 +34,7 @@ static void omap3_dpll_deny_idle(struct clk *clk); static u32 omap3_dpll_autoidle_read(struct clk *clk); static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate); static int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate); +static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate); /* Maximum DPLL multiplier, divider values for OMAP3 */ #define OMAP3_MAX_DPLL_MULT 2048 @@ -471,11 +472,7 @@ static const struct clksel div31_dpll3m2_clksel[] = { { .parent = NULL } }; -/* - * DPLL3 output M2 - * REVISIT: This DPLL output divider must be changed in SRAM, so until - * that code is ready, this should remain a 'read-only' clksel clock. - */ +/* DPLL3 output M2 - primary control point for CORE speed */ static struct clk dpll3_m2_ck = { .name = "dpll3_m2_ck", .ops = &clkops_null, @@ -486,6 +483,8 @@ static struct clk dpll3_m2_ck = { .clksel = div31_dpll3m2_clksel, .flags = RATE_PROPAGATES, .clkdm_name = "dpll3_clkdm", + .round_rate = &omap2_clksel_round_rate, + .set_rate = &omap3_core_dpll_m2_set_rate, .recalc = &omap2_clksel_recalc, }; |