ambresh
Thu, 18 Mar 2010 00:18:11 -0700
Gurav , Pramod wrote:
This patch uses new formula to derive the dpll3 clock Stabilization delay during DVFS for OMAP3630. The formula used is : Latency = 2 * SYS_CLK + 10 * CLKOUTX2 1usec buffer time is added for safety. Signed-off-by: Vishwanath Sripathy <vishwanath...@ti.com> Signed-off-by: Pramod Gurav <pramod.gu...@ti.com> --- arch/arm/mach-omap2/clkt34xx_dpll3m2.c | 60 ++++++++++++++++++++++---------- 1 files changed, 41 insertions(+), 19 deletions(-) diff --git a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c index 29421b1..58979ec 100644 --- a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c +++ b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c @@ -40,6 +40,9 @@ #define SHIFT_DPLL_N 8 #define SHIFT_DPLL_M2 27+#define AVOID_TRUNC_1000 1000+#define AVOID_TRUNC_100 100 + /* * CORE DPLL (DPLL3) M2 divider rate programming functions * @@ -67,7 +70,7 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate) u32 clk_sel_regval; u32 core_dpll_mul_m, core_dpll_div_n, core_dpll_clkoutdiv_m2; u32 sys_clk_rate, sdrc_clk_stab; - u32 refclk, clkoutx2, switch_latency; + u32 refclk, clkoutx2, switch_latency, dpll_lock_freq; unsigned int delay_sram;if (!clk || !rate)@@ -100,28 +103,47 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate) core_dpll_clkoutdiv_m2 = (clk_sel_regval >> SHIFT_DPLL_M2) & DPLL_M2_MASK; sys_clk_rate = clk_get_rate(sys_ck_p); - sys_clk_rate = sys_clk_rate / CYCLES_PER_MHZ;- /* wait time for L3 clk stabilization = 4*REFCLK + 8*CLKOUTX2 */- refclk = (4 * (core_dpll_div_n + 1)) / sys_clk_rate; - clkoutx2 = ((core_dpll_div_n + 1) * core_dpll_clkoutdiv_m2) / - (sys_clk_rate * core_dpll_mul_m * 2); - switch_latency = refclk + 8 * clkoutx2; - - /* Adding 2us to sdrc clk stab */ - sdrc_clk_stab = switch_latency + 2; - - delay_sram = delay_sram_val(); - - /* - * Calculate the number of MPU cycles - * to wait for SDRC to stabilize - */ - _mpurate = arm_fck_p->rate / CYCLES_PER_MHZ; + delay_sram = delay_sram_val();- c = ((sdrc_clk_stab * _mpurate) / (delay_sram * 2));+ if (cpu_is_omap3630()) { + /* + * wait time for L3 clk stabilization = + * 2*SYS_CLK + 10*CLKOUTX2 + */ + /* + * To avoid truncation of floating values, AVOID_TRUNC_1000 & + * AVOID_TRUNC_100 are multiplied and divided appropriately + */ + refclk = 2 * (AVOID_TRUNC_1000 / sys_clk_rate); + dpll_lock_freq = (AVOID_TRUNC_1000 * AVOID_TRUNC_100 * + (core_dpll_div_n + 1))/ + (2 * sys_clk_rate * core_dpll_mul_m); + clkoutx2 = 10 * (dpll_lock_freq * core_dpll_clkoutdiv_m2) / + AVOID_TRUNC_100; + switch_latency = refclk + clkoutx2; + + /* Adding 1000 nano seconds to sdrc clk stab */ + sdrc_clk_stab = switch_latency + 1000; + c = ((sdrc_clk_stab * _mpurate) / + (delay_sram * 2 * AVOID_TRUNC_1000)); + } else { + /* wait time for L3 clk stabilization = 4*REFCLK + 8*CLKOUTX2 */ + refclk = (4 * (core_dpll_div_n + 1)) / sys_clk_rate; + clkoutx2 = ((core_dpll_div_n + 1) * core_dpll_clkoutdiv_m2) / + (sys_clk_rate * core_dpll_mul_m * 2); + switch_latency = refclk + 8 * clkoutx2; + + /* Adding 2us to sdrc clk stab */ + sdrc_clk_stab = switch_latency + 2; + /* + * Calculate the number of MPU cycles to wait for + * SDRC to stabilize + */ + c = ((sdrc_clk_stab * _mpurate) / (delay_sram * 2)); + }
-PFA,- Attached patch provides further optimized 3630 & 3430 path for calculating M2 stablization delay.
- The formula used to compute clkoutx2, is actually calculating for clkoutm2x2 according to trm clkoutx2 = (Fref * 2 * M)/ (N + 1).
(Thanks to Eduardo for pointing this). Thanks, Ambresh
pr_debug("m = %d, n = %d, m2 =%d\n", core_dpll_mul_m, core_dpll_div_n,
core_dpll_clkoutdiv_m2);
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index 02ab136..83125a1 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -47,6 +47,16 @@
#define CYCLES_PER_MHZ 1000000
+#define DPLL_M_MASK 0x7ff
+#define DPLL_N_MASK 0x7f
+#define DPLL_M2_MASK 0x1f
+#define SHIFT_DPLL_M 16
+#define SHIFT_DPLL_N 8
+#define SHIFT_DPLL_M2 27
+
+#define AVOID_TRUNC_1000 1000
+#define AVOID_TRUNC_100 100
+
/*
* DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
* that are sourced by DPLL5, and both of these require this clock
@@ -203,7 +213,7 @@ int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
/*
- * CORE DPLL (DPLL3) rate programming functions
+ * CORE DPLL (DPLL3) M2 divider rate programming functions
*
* These call into SRAM code to do the actual CM writes, since the SDRAM
* is clocked from DPLL3.
@@ -221,10 +231,14 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
{
u32 new_div = 0;
u32 unlock_dll = 0;
- u32 c;
- unsigned long validrate, sdrcrate, _mpurate;
+ u32 c, delay_sram;
+ u32 clk_sel_regval, sys_clk;
+ u32 core_dpll_mul_m, core_dpll_div_n, core_dpll_clkoutdiv_m2;
+ u32 sys_clk_rate, sdrc_clk_stab;
+ u32 refclk, clkoutx2, switch_latency, dpll_lock_freq;
struct omap_sdrc_params *sdrc_cs0;
struct omap_sdrc_params *sdrc_cs1;
+ unsigned long validrate, sdrcrate, _mpurate;
int ret;
if (!clk || !rate)
@@ -249,16 +263,52 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
unlock_dll = 1;
}
- /*
- * XXX This only needs to be done when the CPU frequency changes
- */
+ clk_sel_regval = __raw_readl(clk->clksel_reg);
+
+ /* Get the M, N and M2 values required for getting sdrc clk stab */
+ core_dpll_mul_m = (clk_sel_regval >> SHIFT_DPLL_M) & DPLL_M_MASK;
+ core_dpll_div_n = (clk_sel_regval >> SHIFT_DPLL_N) & DPLL_N_MASK;
+ core_dpll_clkoutdiv_m2 = (clk_sel_regval >> SHIFT_DPLL_M2) &
+ DPLL_M2_MASK;
+
+ /* sys_ck rate */
+ sys_clk_rate = sys_ck_p->rate;
+ sys_clk_rate = sys_clk_rate / CYCLES_PER_MHZ;
_mpurate = arm_fck_p->rate / CYCLES_PER_MHZ;
- c = (_mpurate << SDRC_MPURATE_SCALE) >> SDRC_MPURATE_BASE_SHIFT;
- c += 1; /* for safety */
- c *= SDRC_MPURATE_LOOPS;
- c >>= SDRC_MPURATE_SCALE;
- if (c == 0)
- c = 1;
+
+ delay_sram = delay_sram_val();
+
+ sys_clk = AVOID_TRUNC_1000 / sys_clk_rate;
+ /* To avoid truncation of floating values, AVOID_TRUNC_1000 &
+ * AVOID_TRUNC_100 are multiplied and divided appropriately
+ */
+ dpll_lock_freq = ((AVOID_TRUNC_1000 * AVOID_TRUNC_100) *
+ (core_dpll_div_n + 1)) /
+ (2 * sys_clk_rate * core_dpll_mul_m);
+
+ clkoutx2 = dpll_lock_freq / AVOID_TRUNC_100;
+
+ if (cpu_is_omap3630()) {
+ /*
+ * wait time for L3 clk stabilization = 2*SYS_CLK + 10*CLKOUTX2
+ */
+ switch_latency = (2 * sys_clk) + (8 * clkoutx2);
+ /* Adding 1000 nano seconds to sdrc clk stab */
+ sdrc_clk_stab = switch_latency + 1000;
+ } else {
+ /* wait time for L3 clk stabilization = 4*REFCLK + 8*CLKOUTX2*/
+ refclk = (core_dpll_div_n + 1) * sys_clk;
+ switch_latency = (4 * refclk) + (8 * clkoutx2);
+ /* Adding 2000ns to sdrc clk stab */
+ sdrc_clk_stab = switch_latency + 2000;
+ }
+ c = ((sdrc_clk_stab * _mpurate) /
+ (delay_sram * 2 * AVOID_TRUNC_1000));
+
+ pr_debug("m = %d, n = %d, m2 =%d\n", core_dpll_mul_m, core_dpll_div_n,
+ core_dpll_clkoutdiv_m2);
+ pr_debug("switch_latency = %d, sys_clk_rate = %d, cycles = %d\n",
+ switch_latency, sys_clk_rate, c);
pr_debug("clock: changing CORE DPLL rate from %lu to %lu\n", clk->rate,
validrate);
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 74ae936..79584b0 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -458,7 +458,7 @@ unsigned int measure_sram_delay(unsigned int loop)
/* calculate the sram delay */
error_gain = mpurate / gt_rate;
- delay_sram = (error_gain * diff) / (loop * 2);
+ delay_sram = (error_gain * diff) / (loop);
delay_sram += error_gain;
return delay_sram;