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.bs@xxxxxx>
Signed-off-by: Pramod Gurav <pramod.gurav@xxxxxx>
---
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;