aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/clock24xx.c
diff options
context:
space:
mode:
authorPaul Walmsley <paul@pwsan.com>2008-07-03 05:24:46 -0400
committerTony Lindgren <tony@atomide.com>2008-07-03 05:24:46 -0400
commit88b8ba90570067178d32c654ad95786041e86e86 (patch)
treec2ce719334f9fbbde2500b990bc1cc295226334a /arch/arm/mach-omap2/clock24xx.c
parent542313cc98e72d026d2df86f515699dfaface460 (diff)
ARM: OMAP2: Clock: New OMAP2/3 DPLL rate rounding algorithm
This patch adds a new rate rounding algorithm for DPLL clocks on the OMAP2/3 architecture. For a desired DPLL target rate, there may be several multiplier/divider (M, N) values which will generate a sufficiently close rate. Lower N values result in greater power economy. However, lower N values can cause the difference between the rounded rate and the target rate ("rate error") to be larger than it would be with a higher N. This can cause downstream devices to run more slowly than they otherwise would. This DPLL rate rounding algorithm: - attempts to find the lowest possible N (DPLL divider) to reach the target_rate (since, according to Richard Woodruff <r-woodruff@ti.com>, lower N values save more power than higher N values). - allows developers to set an upper bound on the error between the rounded rate and the desired target rate ("rate tolerance"), so an appropriate balance between rate fidelity and power savings can be set. This maximum rate error tolerance is set via omap2_set_dpll_rate_tolerance(). - never returns a rounded rate higher than the target rate. The rate rounding algorithm caches the last rounded M, N, and rate computation to avoid rounding the rate twice for each clk_set_rate() call. (This patch does not yet implement set_rate for DPLLs; that follows in a future patch.) The algorithm trades execution speed for rate accuracy. It will find the (M, N) set that results in the least rate error, within a specified rate tolerance. It does this by evaluating each divider setting - on OMAP3, this involves 128 steps. Another approach to DPLL rate rounding would be to bail out as soon as a valid rate is found within the rate tolerance, which would trade rate accuracy for execution speed. Alternate implementations welcome. This code is not yet used by the OMAP24XX DPLL clock, since it is currently defined as a composite clock, fusing the DPLL M,N and the M2 output divider. This patch also renames the existing OMAP24xx DPLL programming functions to highlight that they program both the DPLL and the DPLL's output multiplier. 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.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
index ece32d8acba4..aa567876651d 100644
--- a/arch/arm/mach-omap2/clock24xx.c
+++ b/arch/arm/mach-omap2/clock24xx.c
@@ -154,7 +154,7 @@ static void omap2_clk_fixed_disable(struct clk *clk)
154 * Uses the current prcm set to tell if a rate is valid. 154 * Uses the current prcm set to tell if a rate is valid.
155 * You can go slower, but not faster within a given rate set. 155 * You can go slower, but not faster within a given rate set.
156 */ 156 */
157static u32 omap2_dpll_round_rate(unsigned long target_rate) 157long omap2_dpllcore_round_rate(unsigned long target_rate)
158{ 158{
159 u32 high, low, core_clk_src; 159 u32 high, low, core_clk_src;
160 160
@@ -183,14 +183,14 @@ static u32 omap2_dpll_round_rate(unsigned long target_rate)
183 183
184} 184}
185 185
186static void omap2_dpll_recalc(struct clk *clk) 186static void omap2_dpllcore_recalc(struct clk *clk)
187{ 187{
188 clk->rate = omap2_get_dpll_rate_24xx(clk); 188 clk->rate = omap2_get_dpll_rate_24xx(clk);
189 189
190 propagate_rate(clk); 190 propagate_rate(clk);
191} 191}
192 192
193static int omap2_reprogram_dpll(struct clk *clk, unsigned long rate) 193static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
194{ 194{
195 u32 cur_rate, low, mult, div, valid_rate, done_rate; 195 u32 cur_rate, low, mult, div, valid_rate, done_rate;
196 u32 bypass = 0; 196 u32 bypass = 0;
@@ -209,7 +209,7 @@ static int omap2_reprogram_dpll(struct clk *clk, unsigned long rate)
209 } else if ((rate == (cur_rate * 2)) && (mult == 1)) { 209 } else if ((rate == (cur_rate * 2)) && (mult == 1)) {
210 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1); 210 omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
211 } else if (rate != cur_rate) { 211 } else if (rate != cur_rate) {
212 valid_rate = omap2_dpll_round_rate(rate); 212 valid_rate = omap2_dpllcore_round_rate(rate);
213 if (valid_rate != rate) 213 if (valid_rate != rate)
214 goto dpll_exit; 214 goto dpll_exit;
215 215
@@ -256,7 +256,7 @@ static int omap2_reprogram_dpll(struct clk *clk, unsigned long rate)
256 omap2_init_memory_params(omap2_dll_force_needed()); 256 omap2_init_memory_params(omap2_dll_force_needed());
257 omap2_reprogram_sdrc(done_rate, 0); 257 omap2_reprogram_sdrc(done_rate, 0);
258 } 258 }
259 omap2_dpll_recalc(&dpll_ck); 259 omap2_dpllcore_recalc(&dpll_ck);
260 ret = 0; 260 ret = 0;
261 261
262dpll_exit: 262dpll_exit:
@@ -383,7 +383,7 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
383 383
384 local_irq_restore(flags); 384 local_irq_restore(flags);
385 } 385 }
386 omap2_dpll_recalc(&dpll_ck); 386 omap2_dpllcore_recalc(&dpll_ck);
387 387
388 return 0; 388 return 0;
389} 389}