public inbox for linux-omap@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] OMAP3: Dynamic Calculation of SDRC stall latency during DVFS
@ 2010-03-18  4:55 Pramod Gurav
  2010-03-18  4:55 ` [PATCH v4 1/2] OMAP3: SDRC: " Pramod Gurav
  0 siblings, 1 reply; 13+ messages in thread
From: Pramod Gurav @ 2010-03-18  4:55 UTC (permalink / raw)
  To: linux-omap; +Cc: Pramod Gurav

The patch has the changes to calculate the dpll3 clock stabilization delay 
dynamically. The SRAM delay is calibrated during bootup using the gptimers
and used while calculating the stabilization delay. By using the dynamic 
method the dependency on the type of cache being used is removed.

To calculate the dpll3 M2 clock stabilization delay dynamically and wait
time for L3 M2 clock stabilization are different for 3430 & 3630 and is as
follows:
3430: 4*REFCLK + 8*CLKOUTX2
3630: 2*SYS_CLK + 10*CLKOUTX2
REFCLK & CLKOUTX2 are derived from M, N, M2  and DPLL reference clock.

Incase of 3430 a 2usec and 3630 1usec buffer time is added for safety.

Below is the summery of the comments from the commumnity, those are addressed 
in this version of patch:
1. Change in ASM code to reduce overhead of a instruction
2. Replaced magic numbers with proper macros
3. Code style changes

Teerth Reddy (1):
  OMAP3: SDRC: Dynamic Calculation of SDRC stall latency during DVFS
Pramod Gurav (2):
  OMAP3630 SDRC: Change in DVFS Latency Formula for OMAP3630

 arch/arm/mach-omap2/clkt34xx_dpll3m2.c |   80 ++++++++++++++++++++++++++++----
 arch/arm/mach-omap2/clock34xx.h        |    2 +
 arch/arm/mach-omap2/clock3xxx.c        |    2 +-
 arch/arm/mach-omap2/clock3xxx.h        |    1 +
 arch/arm/mach-omap2/clock3xxx_data.c   |   13 +++++
 arch/arm/mach-omap2/sram34xx.S         |    8 +++
 arch/arm/plat-omap/include/plat/sram.h |    4 ++
 arch/arm/plat-omap/sram.c              |   51 ++++++++++++++++++++
 8 files changed, 150 insertions(+), 11 deletions(-)


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v4 1/2] OMAP3: SDRC: Dynamic Calculation of SDRC stall latency during DVFS
  2010-03-18  4:55 [PATCH 0/2] OMAP3: Dynamic Calculation of SDRC stall latency during DVFS Pramod Gurav
@ 2010-03-18  4:55 ` Pramod Gurav
  2010-03-18  4:55   ` [PATCH v2 2/2] OMAP3630 SDRC: Change in DVFS Latency Formula for OMAP3630 Pramod Gurav
                     ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Pramod Gurav @ 2010-03-18  4:55 UTC (permalink / raw)
  To: linux-omap; +Cc: Teerth Reddy, Pramod Gurav, Vishwanath Sripathy

From: Teerth Reddy <teerth@ti.com>

The patch has the changes to calculate the dpll3 clock stabilization
delay dynamically. The SRAM delay is calibrated during bootup using the
gptimers and used while calculating the stabilization delay. By using
the dynamic method the dependency on the type of cache being used is
removed.

The wait time for L3 clock stabilization is calculated using the formula
        = 4*REFCLK + 8*CLKOUTX2,
which uses the M, N and M2 read from the registers.
Since this gives slightly less value, 2us is added as buffer for safety.
This works fine for omap3.

Signed-off-by: Teerth Reddy <teerth@ti.com>
Signed-off-by: Pramod Gurav <pramod.gurav@ti.com>
Signed-off-by: Vishwanath Sripathy <vishwanath.bs@ti.com>

---
 arch/arm/mach-omap2/clkt34xx_dpll3m2.c |   54 +++++++++++++++++++++++++++-----
 arch/arm/mach-omap2/clock34xx.h        |    2 +
 arch/arm/mach-omap2/clock3xxx.c        |    2 +-
 arch/arm/mach-omap2/clock3xxx.h        |    1 +
 arch/arm/mach-omap2/clock3xxx_data.c   |   13 ++++++++
 arch/arm/mach-omap2/sram34xx.S         |    8 +++++
 arch/arm/plat-omap/include/plat/sram.h |    4 ++
 arch/arm/plat-omap/sram.c              |   51 ++++++++++++++++++++++++++++++
 8 files changed, 126 insertions(+), 9 deletions(-)

diff --git a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
index b2b1e37..29421b1 100644
--- a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
+++ b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
@@ -24,13 +24,21 @@
 #include <plat/clock.h>
 #include <plat/sram.h>
 #include <plat/sdrc.h>
+#include <plat/prcm.h>
 
 #include "clock.h"
 #include "clock3xxx.h"
 #include "clock34xx.h"
 #include "sdrc.h"
 
-#define CYCLES_PER_MHZ			1000000
+#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
 
 /*
  * CORE DPLL (DPLL3) M2 divider rate programming functions
@@ -56,6 +64,11 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
 	struct omap_sdrc_params *sdrc_cs0;
 	struct omap_sdrc_params *sdrc_cs1;
 	int ret;
+	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;
+	unsigned int delay_sram;
 
 	if (!clk || !rate)
 		return -EINVAL;
@@ -79,16 +92,41 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
 		unlock_dll = 1;
 	}
 
+	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_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();
+
 	/*
-	 * XXX This only needs to be done when the CPU frequency changes
+	 * Calculate the number of MPU cycles
+	 * to wait for SDRC to stabilize
 	 */
+
 	_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;
+
+	c = ((sdrc_clk_stab * _mpurate) / (delay_sram * 2));
+
+	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/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
index 628e8de..a9f2204 100644
--- a/arch/arm/mach-omap2/clock34xx.h
+++ b/arch/arm/mach-omap2/clock34xx.h
@@ -12,4 +12,6 @@ extern const struct clkops clkops_omap3430es2_ssi_wait;
 extern const struct clkops clkops_omap3430es2_hsotgusb_wait;
 extern const struct clkops clkops_omap3430es2_dss_usbhost_wait;
 
+unsigned int delay_sram_val(void);
+
 #endif
diff --git a/arch/arm/mach-omap2/clock3xxx.c b/arch/arm/mach-omap2/clock3xxx.c
index a447c4d..ce84a98 100644
--- a/arch/arm/mach-omap2/clock3xxx.c
+++ b/arch/arm/mach-omap2/clock3xxx.c
@@ -38,7 +38,7 @@
 #define DPLL5_FREQ_FOR_USBHOST		120000000
 
 /* needed by omap3_core_dpll_m2_set_rate() */
-struct clk *sdrc_ick_p, *arm_fck_p;
+struct clk *sdrc_ick_p, *arm_fck_p, *sys_ck_p;
 
 int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
 {
diff --git a/arch/arm/mach-omap2/clock3xxx.h b/arch/arm/mach-omap2/clock3xxx.h
index 8bbeeaf..475d0c7 100644
--- a/arch/arm/mach-omap2/clock3xxx.h
+++ b/arch/arm/mach-omap2/clock3xxx.h
@@ -15,6 +15,7 @@ void omap3_clk_lock_dpll5(void);
 
 extern struct clk *sdrc_ick_p;
 extern struct clk *arm_fck_p;
+extern struct clk *sys_ck_p;
 
 extern const struct clkops clkops_noncore_dpll_ops;
 
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index 57522de..280adff 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -22,6 +22,7 @@
 
 #include <plat/control.h>
 #include <plat/clkdev_omap.h>
+#include <plat/sram.h>
 
 #include "clock.h"
 #include "clock3xxx.h"
@@ -57,6 +58,8 @@
 static struct clk dpll1_fck;
 static struct clk dpll2_fck;
 
+static unsigned int delay_sram;
+
 /* PRM CLOCKS */
 
 /* According to timer32k.c, this is a 32768Hz clock, not a 32000Hz clock. */
@@ -3598,6 +3601,16 @@ int __init omap3xxx_clk_init(void)
 	/* Avoid sleeping during omap3_core_dpll_m2_set_rate() */
 	sdrc_ick_p = clk_get(NULL, "sdrc_ick");
 	arm_fck_p = clk_get(NULL, "arm_fck");
+	sys_ck_p = clk_get(NULL, "sys_ck");
+
+	/* Measure sram delay */
+	delay_sram = measure_sram_delay(10000);
+	pr_debug("SRAM delay: %d\n", delay_sram);
 
 	return 0;
 }
+
+unsigned int delay_sram_val(void)
+{
+	return delay_sram;
+}
diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S
index de99ba2..5a1631f 100644
--- a/arch/arm/mach-omap2/sram34xx.S
+++ b/arch/arm/mach-omap2/sram34xx.S
@@ -313,3 +313,11 @@ core_m2_mask_val:
 ENTRY(omap3_sram_configure_core_dpll_sz)
 	.word	. - omap3_sram_configure_core_dpll
 
+ENTRY(__sram_wait_delay)
+	subs    r0, r0, #1		@ loop till counter = 0
+	bne     __sram_wait_delay
+
+	mov     pc, lr
+
+ENTRY(__sram_wait_delay_sz)
+	.word   . - __sram_wait_delay
diff --git a/arch/arm/plat-omap/include/plat/sram.h b/arch/arm/plat-omap/include/plat/sram.h
index 16a1b45..dd294a8 100644
--- a/arch/arm/plat-omap/include/plat/sram.h
+++ b/arch/arm/plat-omap/include/plat/sram.h
@@ -69,6 +69,10 @@ extern u32 omap3_sram_configure_core_dpll(
 			u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1);
 extern unsigned long omap3_sram_configure_core_dpll_sz;
 
+extern unsigned int measure_sram_delay(unsigned int);
+extern void __sram_wait_delay(unsigned int);
+extern unsigned long __sram_wait_delay_sz;
+
 #ifdef CONFIG_PM
 extern void omap_push_sram_idle(void);
 #else
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 51f4dfb..a83d422 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -30,6 +30,9 @@
 #include <plat/cpu.h>
 #include <plat/vram.h>
 
+#include <linux/clk.h>
+#include <plat/dmtimer.h>
+#include <plat/io.h>
 #include <plat/control.h>
 
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
@@ -437,11 +440,59 @@ static inline int omap34xx_sram_init(void)
 }
 #endif
 
+#ifdef CONFIG_ARCH_OMAP3
+void (*_omap3_sram_delay)(unsigned int);
+unsigned int  measure_sram_delay(unsigned int loop)
+{
+	static struct omap_dm_timer *gpt;
+	unsigned long flags, diff = 0, gt_rate, mpurate;
+	unsigned int delay_sram, error_gain;
+	unsigned int start = 0, end = 0;
+
+	omap_dm_timer_init();
+	gpt = omap_dm_timer_request();
+	if (!gpt) {
+		pr_err("Could not get the gptimer\n");
+		return -1;
+	}
+
+	omap_dm_timer_set_source(gpt, OMAP_TIMER_SRC_SYS_CLK);
+
+	gt_rate = clk_get_rate(omap_dm_timer_get_fclk(gpt));
+	omap_dm_timer_set_load_start(gpt, 0, 0);
+
+	local_irq_save(flags);
+	start = omap_dm_timer_read_counter(gpt);
+	_omap3_sram_delay(loop);
+	end = omap_dm_timer_read_counter(gpt);
+	diff = end - start;
+	local_irq_restore(flags);
+
+	omap_dm_timer_stop(gpt);
+	omap_dm_timer_free(gpt);
+
+	mpurate = clk_get_rate(clk_get(NULL, "arm_fck"));
+
+	/* calculate the sram delay */
+	delay_sram = (((mpurate / gt_rate) * diff) / (loop * 2));
+
+	error_gain = mpurate / gt_rate;
+	delay_sram = delay_sram + error_gain;
+
+	return delay_sram;
+}
+#endif
+
 int __init omap_sram_init(void)
 {
 	omap_detect_sram();
 	omap_map_sram();
 
+#ifdef CONFIG_ARCH_OMAP3
+	_omap3_sram_delay = omap_sram_push(__sram_wait_delay,
+						__sram_wait_delay_sz);
+#endif
+
 	if (!(cpu_class_is_omap2()))
 		omap1_sram_init();
 	else if (cpu_is_omap242x())
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 2/2] OMAP3630 SDRC: Change in DVFS Latency Formula for OMAP3630
  2010-03-18  4:55 ` [PATCH v4 1/2] OMAP3: SDRC: " Pramod Gurav
@ 2010-03-18  4:55   ` Pramod Gurav
  2010-03-18  7:17     ` ambresh
  2010-03-18  6:17   ` [PATCH v4 1/2] OMAP3: SDRC: Dynamic Calculation of SDRC stall latency during DVFS G, Manjunath Kondaiah
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 13+ messages in thread
From: Pramod Gurav @ 2010-03-18  4:55 UTC (permalink / raw)
  To: linux-omap; +Cc: Pramod Gurav, Vishwanath Sripathy

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@ti.com>
Signed-off-by: Pramod Gurav <pramod.gurav@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));
+	}
 
 	pr_debug("m = %d, n = %d, m2 =%d\n", core_dpll_mul_m, core_dpll_div_n,
 						core_dpll_clkoutdiv_m2);
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* RE: [PATCH v4 1/2] OMAP3: SDRC: Dynamic Calculation of SDRC stall latency during DVFS
  2010-03-18  4:55 ` [PATCH v4 1/2] OMAP3: SDRC: " Pramod Gurav
  2010-03-18  4:55   ` [PATCH v2 2/2] OMAP3630 SDRC: Change in DVFS Latency Formula for OMAP3630 Pramod Gurav
@ 2010-03-18  6:17   ` G, Manjunath Kondaiah
  2010-03-18 14:48     ` Kevin Hilman
  2010-03-18  7:15   ` ambresh
  2010-03-18 15:09   ` Kevin Hilman
  3 siblings, 1 reply; 13+ messages in thread
From: G, Manjunath Kondaiah @ 2010-03-18  6:17 UTC (permalink / raw)
  To: Gurav , Pramod, linux-omap@vger.kernel.org
  Cc: Reddy, Teerth, Sripathy, Vishwanath




> -----Original Message-----
> From: linux-omap-owner@vger.kernel.org 
> [mailto:linux-omap-owner@vger.kernel.org] On Behalf Of Gurav , Pramod
> Sent: Thursday, March 18, 2010 10:26 AM
> To: linux-omap@vger.kernel.org
> Cc: Reddy, Teerth; Gurav , Pramod; Sripathy, Vishwanath
> Subject: [PATCH v4 1/2] OMAP3: SDRC: Dynamic Calculation of 
> SDRC stall latency during DVFS
> 
> From: Teerth Reddy <teerth@ti.com>
> 
> The patch has the changes to calculate the dpll3 clock stabilization
> delay dynamically. The SRAM delay is calibrated during bootup 
> using the
> gptimers and used while calculating the stabilization delay. By using
> the dynamic method the dependency on the type of cache being used is
> removed.
> 
> The wait time for L3 clock stabilization is calculated using 
> the formula
>         = 4*REFCLK + 8*CLKOUTX2,
> which uses the M, N and M2 read from the registers.
> Since this gives slightly less value, 2us is added as buffer 
> for safety.
> This works fine for omap3.
> 
> Signed-off-by: Teerth Reddy <teerth@ti.com>
> Signed-off-by: Pramod Gurav <pramod.gurav@ti.com>
> Signed-off-by: Vishwanath Sripathy <vishwanath.bs@ti.com>
> 
> ---
>  arch/arm/mach-omap2/clkt34xx_dpll3m2.c |   54 
> +++++++++++++++++++++++++++-----
>  arch/arm/mach-omap2/clock34xx.h        |    2 +
>  arch/arm/mach-omap2/clock3xxx.c        |    2 +-
>  arch/arm/mach-omap2/clock3xxx.h        |    1 +
>  arch/arm/mach-omap2/clock3xxx_data.c   |   13 ++++++++
>  arch/arm/mach-omap2/sram34xx.S         |    8 +++++
>  arch/arm/plat-omap/include/plat/sram.h |    4 ++
>  arch/arm/plat-omap/sram.c              |   51 
> ++++++++++++++++++++++++++++++
>  8 files changed, 126 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c 
> b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
> index b2b1e37..29421b1 100644
> --- a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
> +++ b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
> @@ -24,13 +24,21 @@
>  #include <plat/clock.h>
>  #include <plat/sram.h>
>  #include <plat/sdrc.h>
> +#include <plat/prcm.h>
>  
>  #include "clock.h"
>  #include "clock3xxx.h"
>  #include "clock34xx.h"
>  #include "sdrc.h"
>  
> -#define CYCLES_PER_MHZ			1000000
> +#define		CYCLES_PER_MHZ		1000000
> +
> +#define		DPLL_M_MASK		0x7ff
> +#define		DPLL_N_MASK		0x7f

Use one more tab

> +#define		DPLL_M2_MASK		0x1f
> +#define		SHIFT_DPLL_M		16
> +#define		SHIFT_DPLL_N		8
> +#define		SHIFT_DPLL_M2		27
>  
>  /*
>   * CORE DPLL (DPLL3) M2 divider rate programming functions
> @@ -56,6 +64,11 @@ int omap3_core_dpll_m2_set_rate(struct clk 
> *clk, unsigned long rate)
>  	struct omap_sdrc_params *sdrc_cs0;
>  	struct omap_sdrc_params *sdrc_cs1;
>  	int ret;
> +	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;
> +	unsigned int delay_sram;
>  
>  	if (!clk || !rate)
>  		return -EINVAL;
> @@ -79,16 +92,41 @@ int omap3_core_dpll_m2_set_rate(struct 
> clk *clk, unsigned long rate)
>  		unlock_dll = 1;
>  	}
>  
> +	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_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();
> +
>  	/*
> -	 * XXX This only needs to be done when the CPU frequency changes
> +	 * Calculate the number of MPU cycles
> +	 * to wait for SDRC to stabilize
>  	 */
> +
>  	_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;
> +
> +	c = ((sdrc_clk_stab * _mpurate) / (delay_sram * 2));
> +
> +	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/mach-omap2/clock34xx.h 
> b/arch/arm/mach-omap2/clock34xx.h
> index 628e8de..a9f2204 100644
> --- a/arch/arm/mach-omap2/clock34xx.h
> +++ b/arch/arm/mach-omap2/clock34xx.h
> @@ -12,4 +12,6 @@ extern const struct clkops 
> clkops_omap3430es2_ssi_wait;
>  extern const struct clkops clkops_omap3430es2_hsotgusb_wait;
>  extern const struct clkops clkops_omap3430es2_dss_usbhost_wait;
>  
> +unsigned int delay_sram_val(void);
> +
>  #endif
> diff --git a/arch/arm/mach-omap2/clock3xxx.c 
> b/arch/arm/mach-omap2/clock3xxx.c
> index a447c4d..ce84a98 100644
> --- a/arch/arm/mach-omap2/clock3xxx.c
> +++ b/arch/arm/mach-omap2/clock3xxx.c
> @@ -38,7 +38,7 @@
>  #define DPLL5_FREQ_FOR_USBHOST		120000000
>  
>  /* needed by omap3_core_dpll_m2_set_rate() */
> -struct clk *sdrc_ick_p, *arm_fck_p;
> +struct clk *sdrc_ick_p, *arm_fck_p, *sys_ck_p;
>  
>  int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
>  {
> diff --git a/arch/arm/mach-omap2/clock3xxx.h 
> b/arch/arm/mach-omap2/clock3xxx.h
> index 8bbeeaf..475d0c7 100644
> --- a/arch/arm/mach-omap2/clock3xxx.h
> +++ b/arch/arm/mach-omap2/clock3xxx.h
> @@ -15,6 +15,7 @@ void omap3_clk_lock_dpll5(void);
>  
>  extern struct clk *sdrc_ick_p;
>  extern struct clk *arm_fck_p;
> +extern struct clk *sys_ck_p;
>  
>  extern const struct clkops clkops_noncore_dpll_ops;
>  
> diff --git a/arch/arm/mach-omap2/clock3xxx_data.c 
> b/arch/arm/mach-omap2/clock3xxx_data.c
> index 57522de..280adff 100644
> --- a/arch/arm/mach-omap2/clock3xxx_data.c
> +++ b/arch/arm/mach-omap2/clock3xxx_data.c
> @@ -22,6 +22,7 @@
>  
>  #include <plat/control.h>
>  #include <plat/clkdev_omap.h>
> +#include <plat/sram.h>
>  
>  #include "clock.h"
>  #include "clock3xxx.h"
> @@ -57,6 +58,8 @@
>  static struct clk dpll1_fck;
>  static struct clk dpll2_fck;
>  
> +static unsigned int delay_sram;
> +
>  /* PRM CLOCKS */
>  
>  /* According to timer32k.c, this is a 32768Hz clock, not a 
> 32000Hz clock. */
> @@ -3598,6 +3601,16 @@ int __init omap3xxx_clk_init(void)
>  	/* Avoid sleeping during omap3_core_dpll_m2_set_rate() */
>  	sdrc_ick_p = clk_get(NULL, "sdrc_ick");
>  	arm_fck_p = clk_get(NULL, "arm_fck");
> +	sys_ck_p = clk_get(NULL, "sys_ck");
> +
> +	/* Measure sram delay */
> +	delay_sram = measure_sram_delay(10000);
> +	pr_debug("SRAM delay: %d\n", delay_sram);
>  
>  	return 0;
>  }
> +
> +unsigned int delay_sram_val(void)
> +{
> +	return delay_sram;
> +}
> diff --git a/arch/arm/mach-omap2/sram34xx.S 
> b/arch/arm/mach-omap2/sram34xx.S
> index de99ba2..5a1631f 100644
> --- a/arch/arm/mach-omap2/sram34xx.S
> +++ b/arch/arm/mach-omap2/sram34xx.S
> @@ -313,3 +313,11 @@ core_m2_mask_val:
>  ENTRY(omap3_sram_configure_core_dpll_sz)
>  	.word	. - omap3_sram_configure_core_dpll
>  
> +ENTRY(__sram_wait_delay)
> +	subs    r0, r0, #1		@ loop till counter = 0
> +	bne     __sram_wait_delay
> +
> +	mov     pc, lr
> +
> +ENTRY(__sram_wait_delay_sz)
> +	.word   . - __sram_wait_delay
> diff --git a/arch/arm/plat-omap/include/plat/sram.h 
> b/arch/arm/plat-omap/include/plat/sram.h
> index 16a1b45..dd294a8 100644
> --- a/arch/arm/plat-omap/include/plat/sram.h
> +++ b/arch/arm/plat-omap/include/plat/sram.h
> @@ -69,6 +69,10 @@ extern u32 omap3_sram_configure_core_dpll(
>  			u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1);
>  extern unsigned long omap3_sram_configure_core_dpll_sz;
>  
> +extern unsigned int measure_sram_delay(unsigned int);
> +extern void __sram_wait_delay(unsigned int);
> +extern unsigned long __sram_wait_delay_sz;
> +
>  #ifdef CONFIG_PM
>  extern void omap_push_sram_idle(void);
>  #else
> diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
> index 51f4dfb..a83d422 100644
> --- a/arch/arm/plat-omap/sram.c
> +++ b/arch/arm/plat-omap/sram.c
> @@ -30,6 +30,9 @@
>  #include <plat/cpu.h>
>  #include <plat/vram.h>
>  
> +#include <linux/clk.h>
> +#include <plat/dmtimer.h>
> +#include <plat/io.h>
>  #include <plat/control.h>
>  
>  #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
> @@ -437,11 +440,59 @@ static inline int omap34xx_sram_init(void)
>  }
>  #endif
>  
> +#ifdef CONFIG_ARCH_OMAP3
> +void (*_omap3_sram_delay)(unsigned int);
> +unsigned int  measure_sram_delay(unsigned int loop)
> +{
> +	static struct omap_dm_timer *gpt;
> +	unsigned long flags, diff = 0, gt_rate, mpurate;
> +	unsigned int delay_sram, error_gain;
> +	unsigned int start = 0, end = 0;
> +
> +	omap_dm_timer_init();
> +	gpt = omap_dm_timer_request();
> +	if (!gpt) {

Request timer API returns NULL on failure. 
Use   BUG_ON(gpt == NULL);

> +		pr_err("Could not get the gptimer\n");
> +		return -1;

If timer is not available, can we use fixed delay instead 
returning error.

> +	}
> +
> +	omap_dm_timer_set_source(gpt, OMAP_TIMER_SRC_SYS_CLK);
> +
> +	gt_rate = clk_get_rate(omap_dm_timer_get_fclk(gpt));
> +	omap_dm_timer_set_load_start(gpt, 0, 0);
> +
> +	local_irq_save(flags);
> +	start = omap_dm_timer_read_counter(gpt);
> +	_omap3_sram_delay(loop);
> +	end = omap_dm_timer_read_counter(gpt);
> +	diff = end - start;
> +	local_irq_restore(flags);
> +
> +	omap_dm_timer_stop(gpt);
> +	omap_dm_timer_free(gpt);
> +
> +	mpurate = clk_get_rate(clk_get(NULL, "arm_fck"));
> +
> +	/* calculate the sram delay */
> +	delay_sram = (((mpurate / gt_rate) * diff) / (loop * 2));
> +
> +	error_gain = mpurate / gt_rate;
> +	delay_sram = delay_sram + error_gain;
> +
> +	return delay_sram;
> +}
> +#endif
> +
>  int __init omap_sram_init(void)
>  {
>  	omap_detect_sram();
>  	omap_map_sram();
>  
> +#ifdef CONFIG_ARCH_OMAP3
> +	_omap3_sram_delay = omap_sram_push(__sram_wait_delay,
> +						__sram_wait_delay_sz);
> +#endif
> +
>  	if (!(cpu_class_is_omap2()))
>  		omap1_sram_init();
>  	else if (cpu_is_omap242x())
> -- 
> 1.5.6.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe 
> linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 1/2] OMAP3: SDRC: Dynamic Calculation of SDRC stall latency during DVFS
  2010-03-18  4:55 ` [PATCH v4 1/2] OMAP3: SDRC: " Pramod Gurav
  2010-03-18  4:55   ` [PATCH v2 2/2] OMAP3630 SDRC: Change in DVFS Latency Formula for OMAP3630 Pramod Gurav
  2010-03-18  6:17   ` [PATCH v4 1/2] OMAP3: SDRC: Dynamic Calculation of SDRC stall latency during DVFS G, Manjunath Kondaiah
@ 2010-03-18  7:15   ` ambresh
  2010-03-19 13:15     ` Sripathy, Vishwanath
  2010-03-18 15:09   ` Kevin Hilman
  3 siblings, 1 reply; 13+ messages in thread
From: ambresh @ 2010-03-18  7:15 UTC (permalink / raw)
  To: Gurav , Pramod
  Cc: linux-omap@vger.kernel.org, Reddy, Teerth, Sripathy, Vishwanath

Gurav , Pramod wrote:
> From: Teerth Reddy <teerth@ti.com>
> 
> The patch has the changes to calculate the dpll3 clock stabilization
> delay dynamically. The SRAM delay is calibrated during bootup using the
> gptimers and used while calculating the stabilization delay. By using
> the dynamic method the dependency on the type of cache being used is
> removed.
> 
> The wait time for L3 clock stabilization is calculated using the formula
>         = 4*REFCLK + 8*CLKOUTX2,
> which uses the M, N and M2 read from the registers.
> Since this gives slightly less value, 2us is added as buffer for safety.
> This works fine for omap3.
> 
> Signed-off-by: Teerth Reddy <teerth@ti.com>
> Signed-off-by: Pramod Gurav <pramod.gurav@ti.com>
> Signed-off-by: Vishwanath Sripathy <vishwanath.bs@ti.com>
> 
> ---
>  arch/arm/mach-omap2/clkt34xx_dpll3m2.c |   54 +++++++++++++++++++++++++++-----
>  arch/arm/mach-omap2/clock34xx.h        |    2 +
>  arch/arm/mach-omap2/clock3xxx.c        |    2 +-
>  arch/arm/mach-omap2/clock3xxx.h        |    1 +
>  arch/arm/mach-omap2/clock3xxx_data.c   |   13 ++++++++
>  arch/arm/mach-omap2/sram34xx.S         |    8 +++++
>  arch/arm/plat-omap/include/plat/sram.h |    4 ++
>  arch/arm/plat-omap/sram.c              |   51 ++++++++++++++++++++++++++++++
>  8 files changed, 126 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
> index b2b1e37..29421b1 100644
> --- a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
> +++ b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
> @@ -24,13 +24,21 @@
>  #include <plat/clock.h>
>  #include <plat/sram.h>
>  #include <plat/sdrc.h>
> +#include <plat/prcm.h>
>  
>  #include "clock.h"
>  #include "clock3xxx.h"
>  #include "clock34xx.h"
>  #include "sdrc.h"
>  
> -#define CYCLES_PER_MHZ			1000000
> +#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
>  
>  /*
>   * CORE DPLL (DPLL3) M2 divider rate programming functions
> @@ -56,6 +64,11 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
>  	struct omap_sdrc_params *sdrc_cs0;
>  	struct omap_sdrc_params *sdrc_cs1;
>  	int ret;
> +	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;
> +	unsigned int delay_sram;
>  
>  	if (!clk || !rate)
>  		return -EINVAL;
> @@ -79,16 +92,41 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
>  		unlock_dll = 1;
>  	}
>  
> +	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_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();
> +
>  	/*
> -	 * XXX This only needs to be done when the CPU frequency changes
> +	 * Calculate the number of MPU cycles
> +	 * to wait for SDRC to stabilize
>  	 */
> +
>  	_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;
> +
> +	c = ((sdrc_clk_stab * _mpurate) / (delay_sram * 2));
> +
> +	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/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
> index 628e8de..a9f2204 100644
> --- a/arch/arm/mach-omap2/clock34xx.h
> +++ b/arch/arm/mach-omap2/clock34xx.h
> @@ -12,4 +12,6 @@ extern const struct clkops clkops_omap3430es2_ssi_wait;
>  extern const struct clkops clkops_omap3430es2_hsotgusb_wait;
>  extern const struct clkops clkops_omap3430es2_dss_usbhost_wait;
>  
> +unsigned int delay_sram_val(void);
> +
>  #endif
> diff --git a/arch/arm/mach-omap2/clock3xxx.c b/arch/arm/mach-omap2/clock3xxx.c
> index a447c4d..ce84a98 100644
> --- a/arch/arm/mach-omap2/clock3xxx.c
> +++ b/arch/arm/mach-omap2/clock3xxx.c
> @@ -38,7 +38,7 @@
>  #define DPLL5_FREQ_FOR_USBHOST		120000000
>  
>  /* needed by omap3_core_dpll_m2_set_rate() */
> -struct clk *sdrc_ick_p, *arm_fck_p;
> +struct clk *sdrc_ick_p, *arm_fck_p, *sys_ck_p;
>  
>  int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
>  {
> diff --git a/arch/arm/mach-omap2/clock3xxx.h b/arch/arm/mach-omap2/clock3xxx.h
> index 8bbeeaf..475d0c7 100644
> --- a/arch/arm/mach-omap2/clock3xxx.h
> +++ b/arch/arm/mach-omap2/clock3xxx.h
> @@ -15,6 +15,7 @@ void omap3_clk_lock_dpll5(void);
>  
>  extern struct clk *sdrc_ick_p;
>  extern struct clk *arm_fck_p;
> +extern struct clk *sys_ck_p;
>  
>  extern const struct clkops clkops_noncore_dpll_ops;
>  
> diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
> index 57522de..280adff 100644
> --- a/arch/arm/mach-omap2/clock3xxx_data.c
> +++ b/arch/arm/mach-omap2/clock3xxx_data.c
> @@ -22,6 +22,7 @@
>  
>  #include <plat/control.h>
>  #include <plat/clkdev_omap.h>
> +#include <plat/sram.h>
>  
>  #include "clock.h"
>  #include "clock3xxx.h"
> @@ -57,6 +58,8 @@
>  static struct clk dpll1_fck;
>  static struct clk dpll2_fck;
>  
> +static unsigned int delay_sram;
> +
>  /* PRM CLOCKS */
>  
>  /* According to timer32k.c, this is a 32768Hz clock, not a 32000Hz clock. */
> @@ -3598,6 +3601,16 @@ int __init omap3xxx_clk_init(void)
>  	/* Avoid sleeping during omap3_core_dpll_m2_set_rate() */
>  	sdrc_ick_p = clk_get(NULL, "sdrc_ick");
>  	arm_fck_p = clk_get(NULL, "arm_fck");
> +	sys_ck_p = clk_get(NULL, "sys_ck");
> +
> +	/* Measure sram delay */
> +	delay_sram = measure_sram_delay(10000);
> +	pr_debug("SRAM delay: %d\n", delay_sram);
>  
>  	return 0;
>  }
> +
> +unsigned int delay_sram_val(void)
> +{
> +	return delay_sram;
> +}
> diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S
> index de99ba2..5a1631f 100644
> --- a/arch/arm/mach-omap2/sram34xx.S
> +++ b/arch/arm/mach-omap2/sram34xx.S
> @@ -313,3 +313,11 @@ core_m2_mask_val:
>  ENTRY(omap3_sram_configure_core_dpll_sz)
>  	.word	. - omap3_sram_configure_core_dpll
>  
> +ENTRY(__sram_wait_delay)
> +	subs    r0, r0, #1		@ loop till counter = 0
> +	bne     __sram_wait_delay
> +
> +	mov     pc, lr
> +
> +ENTRY(__sram_wait_delay_sz)
> +	.word   . - __sram_wait_delay
> diff --git a/arch/arm/plat-omap/include/plat/sram.h b/arch/arm/plat-omap/include/plat/sram.h
> index 16a1b45..dd294a8 100644
> --- a/arch/arm/plat-omap/include/plat/sram.h
> +++ b/arch/arm/plat-omap/include/plat/sram.h
> @@ -69,6 +69,10 @@ extern u32 omap3_sram_configure_core_dpll(
>  			u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1);
>  extern unsigned long omap3_sram_configure_core_dpll_sz;
>  
> +extern unsigned int measure_sram_delay(unsigned int);
> +extern void __sram_wait_delay(unsigned int);
> +extern unsigned long __sram_wait_delay_sz;
> +
>  #ifdef CONFIG_PM
>  extern void omap_push_sram_idle(void);
>  #else
> diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
> index 51f4dfb..a83d422 100644
> --- a/arch/arm/plat-omap/sram.c
> +++ b/arch/arm/plat-omap/sram.c
> @@ -30,6 +30,9 @@
>  #include <plat/cpu.h>
>  #include <plat/vram.h>
>  
> +#include <linux/clk.h>
> +#include <plat/dmtimer.h>
> +#include <plat/io.h>
>  #include <plat/control.h>
>  
>  #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
> @@ -437,11 +440,59 @@ static inline int omap34xx_sram_init(void)
>  }
>  #endif
>  
> +#ifdef CONFIG_ARCH_OMAP3
> +void (*_omap3_sram_delay)(unsigned int);
> +unsigned int  measure_sram_delay(unsigned int loop)
> +{
> +	static struct omap_dm_timer *gpt;
> +	unsigned long flags, diff = 0, gt_rate, mpurate;
> +	unsigned int delay_sram, error_gain;
> +	unsigned int start = 0, end = 0;
> +
> +	omap_dm_timer_init();
> +	gpt = omap_dm_timer_request();
> +	if (!gpt) {
> +		pr_err("Could not get the gptimer\n");
> +		return -1;
> +	}
> +
> +	omap_dm_timer_set_source(gpt, OMAP_TIMER_SRC_SYS_CLK);
> +
> +	gt_rate = clk_get_rate(omap_dm_timer_get_fclk(gpt));
> +	omap_dm_timer_set_load_start(gpt, 0, 0);
> +
> +	local_irq_save(flags);
> +	start = omap_dm_timer_read_counter(gpt);
> +	_omap3_sram_delay(loop);
> +	end = omap_dm_timer_read_counter(gpt);
> +	diff = end - start;
> +	local_irq_restore(flags);
> +
> +	omap_dm_timer_stop(gpt);
> +	omap_dm_timer_free(gpt);
> +
> +	mpurate = clk_get_rate(clk_get(NULL, "arm_fck"));
> +
> +	/* calculate the sram delay */
> +	delay_sram = (((mpurate / gt_rate) * diff) / (loop * 2));
> +
> +	error_gain = mpurate / gt_rate;
> +	delay_sram = delay_sram + error_gain;

Cosmetic changes:

         error_gain = mpurate / gt_rate;
         delay_sram = (error_gain * diff) / (loop);
         delay_sram += error_gain;

Thanks,
Ambresh

> +
> +	return delay_sram;
> +}
> +#endif
> +
>  int __init omap_sram_init(void)
>  {
>  	omap_detect_sram();
>  	omap_map_sram();
>  
> +#ifdef CONFIG_ARCH_OMAP3
> +	_omap3_sram_delay = omap_sram_push(__sram_wait_delay,
> +						__sram_wait_delay_sz);
> +#endif
> +
>  	if (!(cpu_class_is_omap2()))
>  		omap1_sram_init();
>  	else if (cpu_is_omap242x())


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 2/2] OMAP3630 SDRC: Change in DVFS Latency Formula for OMAP3630
  2010-03-18  4:55   ` [PATCH v2 2/2] OMAP3630 SDRC: Change in DVFS Latency Formula for OMAP3630 Pramod Gurav
@ 2010-03-18  7:17     ` ambresh
  2010-03-19 13:17       ` Sripathy, Vishwanath
  0 siblings, 1 reply; 13+ messages in thread
From: ambresh @ 2010-03-18  7:17 UTC (permalink / raw)
  To: Gurav , Pramod; +Cc: linux-omap@vger.kernel.org, Sripathy, Vishwanath

[-- Attachment #1: Type: text/plain, Size: 3995 bytes --]

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@ti.com>
> Signed-off-by: Pramod Gurav <pramod.gurav@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);


[-- Attachment #2: M2_stablization.patch --]
[-- Type: text/x-patch, Size: 4113 bytes --]

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;

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 1/2] OMAP3: SDRC: Dynamic Calculation of SDRC stall latency during DVFS
  2010-03-18  6:17   ` [PATCH v4 1/2] OMAP3: SDRC: Dynamic Calculation of SDRC stall latency during DVFS G, Manjunath Kondaiah
@ 2010-03-18 14:48     ` Kevin Hilman
  0 siblings, 0 replies; 13+ messages in thread
From: Kevin Hilman @ 2010-03-18 14:48 UTC (permalink / raw)
  To: G, Manjunath Kondaiah
  Cc: Gurav , Pramod, linux-omap@vger.kernel.org, Reddy, Teerth,
	Sripathy, Vishwanath

"G, Manjunath Kondaiah" <manjugk@ti.com> writes:

>> +#ifdef CONFIG_ARCH_OMAP3
>> +void (*_omap3_sram_delay)(unsigned int);
>> +unsigned int  measure_sram_delay(unsigned int loop)
>> +{
>> +	static struct omap_dm_timer *gpt;
>> +	unsigned long flags, diff = 0, gt_rate, mpurate;
>> +	unsigned int delay_sram, error_gain;
>> +	unsigned int start = 0, end = 0;
>> +
>> +	omap_dm_timer_init();
>> +	gpt = omap_dm_timer_request();
>> +	if (!gpt) {
>
> Request timer API returns NULL on failure. 
> Use   BUG_ON(gpt == NULL);

No.  BUG_ON() will panic the kernel and hang here.  There is no need
to crash the kernel for that.

Current aproach is fine, or if a more verbose warning is desired,
you can use if (WARN_ON(!gpt)) ... and drop the pr_err()

Kevin

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 1/2] OMAP3: SDRC: Dynamic Calculation of SDRC stall latency during DVFS
  2010-03-18  4:55 ` [PATCH v4 1/2] OMAP3: SDRC: " Pramod Gurav
                     ` (2 preceding siblings ...)
  2010-03-18  7:15   ` ambresh
@ 2010-03-18 15:09   ` Kevin Hilman
  3 siblings, 0 replies; 13+ messages in thread
From: Kevin Hilman @ 2010-03-18 15:09 UTC (permalink / raw)
  To: Pramod Gurav; +Cc: linux-omap, Teerth Reddy, Vishwanath Sripathy

Pramod Gurav <pramod.gurav@ti.com> writes:

> From: Teerth Reddy <teerth@ti.com>
>
> The patch has the changes to calculate the dpll3 clock stabilization
> delay dynamically. The SRAM delay is calibrated during bootup using the
> gptimers and used while calculating the stabilization delay. By using
> the dynamic method the dependency on the type of cache being used is
> removed.
>
> The wait time for L3 clock stabilization is calculated using the formula
>         = 4*REFCLK + 8*CLKOUTX2,
> which uses the M, N and M2 read from the registers.
> Since this gives slightly less value, 2us is added as buffer for safety.
> This works fine for omap3.
>
> Signed-off-by: Teerth Reddy <teerth@ti.com>
> Signed-off-by: Pramod Gurav <pramod.gurav@ti.com>
> Signed-off-by: Vishwanath Sripathy <vishwanath.bs@ti.com>

OK, I'm now OK with the GP timer usage in this version.  The rest will
need to be reviewed/merged by Paul.

Kevin

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: [PATCH v4 1/2] OMAP3: SDRC: Dynamic Calculation of SDRC stall latency during DVFS
  2010-03-18  7:15   ` ambresh
@ 2010-03-19 13:15     ` Sripathy, Vishwanath
  2010-03-21 13:24       ` ambresh
  0 siblings, 1 reply; 13+ messages in thread
From: Sripathy, Vishwanath @ 2010-03-19 13:15 UTC (permalink / raw)
  To: K, Ambresh, Gurav , Pramod; +Cc: linux-omap@vger.kernel.org, Reddy, Teerth



> -----Original Message-----
> From: K, Ambresh
> Sent: Thursday, March 18, 2010 12:46 PM
> To: Gurav , Pramod
> Cc: linux-omap@vger.kernel.org; Reddy, Teerth; Sripathy, Vishwanath
> Subject: Re: [PATCH v4 1/2] OMAP3: SDRC: Dynamic Calculation of SDRC stall
> latency during DVFS
> 
> Gurav , Pramod wrote:
> > From: Teerth Reddy <teerth@ti.com>
> >
> > The patch has the changes to calculate the dpll3 clock stabilization
> > delay dynamically. The SRAM delay is calibrated during bootup using the
> > gptimers and used while calculating the stabilization delay. By using
> > the dynamic method the dependency on the type of cache being used is
> > removed.
> >
> > The wait time for L3 clock stabilization is calculated using the formula
> >         = 4*REFCLK + 8*CLKOUTX2,
> > which uses the M, N and M2 read from the registers.
> > Since this gives slightly less value, 2us is added as buffer for safety.
> > This works fine for omap3.
> >
> > Signed-off-by: Teerth Reddy <teerth@ti.com>
> > Signed-off-by: Pramod Gurav <pramod.gurav@ti.com>
> > Signed-off-by: Vishwanath Sripathy <vishwanath.bs@ti.com>
> >
> > ---
> >  arch/arm/mach-omap2/clkt34xx_dpll3m2.c |   54
> +++++++++++++++++++++++++++-----
> >  arch/arm/mach-omap2/clock34xx.h        |    2 +
> >  arch/arm/mach-omap2/clock3xxx.c        |    2 +-
> >  arch/arm/mach-omap2/clock3xxx.h        |    1 +
> >  arch/arm/mach-omap2/clock3xxx_data.c   |   13 ++++++++
> >  arch/arm/mach-omap2/sram34xx.S         |    8 +++++
> >  arch/arm/plat-omap/include/plat/sram.h |    4 ++
> >  arch/arm/plat-omap/sram.c              |   51
> ++++++++++++++++++++++++++++++
> >  8 files changed, 126 insertions(+), 9 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c b/arch/arm/mach-
> omap2/clkt34xx_dpll3m2.c
> > index b2b1e37..29421b1 100644
> > --- a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
> > +++ b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
> > @@ -24,13 +24,21 @@
> >  #include <plat/clock.h>
> >  #include <plat/sram.h>
> >  #include <plat/sdrc.h>
> > +#include <plat/prcm.h>
> >
> >  #include "clock.h"
> >  #include "clock3xxx.h"
> >  #include "clock34xx.h"
> >  #include "sdrc.h"
> >
> > -#define CYCLES_PER_MHZ			1000000
> > +#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
> >
> >  /*
> >   * CORE DPLL (DPLL3) M2 divider rate programming functions
> > @@ -56,6 +64,11 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned
> long rate)
> >  	struct omap_sdrc_params *sdrc_cs0;
> >  	struct omap_sdrc_params *sdrc_cs1;
> >  	int ret;
> > +	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;
> > +	unsigned int delay_sram;
> >
> >  	if (!clk || !rate)
> >  		return -EINVAL;
> > @@ -79,16 +92,41 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned
> long rate)
> >  		unlock_dll = 1;
> >  	}
> >
> > +	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_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();
> > +
> >  	/*
> > -	 * XXX This only needs to be done when the CPU frequency changes
> > +	 * Calculate the number of MPU cycles
> > +	 * to wait for SDRC to stabilize
> >  	 */
> > +
> >  	_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;
> > +
> > +	c = ((sdrc_clk_stab * _mpurate) / (delay_sram * 2));
> > +
> > +	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/mach-omap2/clock34xx.h b/arch/arm/mach-
> omap2/clock34xx.h
> > index 628e8de..a9f2204 100644
> > --- a/arch/arm/mach-omap2/clock34xx.h
> > +++ b/arch/arm/mach-omap2/clock34xx.h
> > @@ -12,4 +12,6 @@ extern const struct clkops clkops_omap3430es2_ssi_wait;
> >  extern const struct clkops clkops_omap3430es2_hsotgusb_wait;
> >  extern const struct clkops clkops_omap3430es2_dss_usbhost_wait;
> >
> > +unsigned int delay_sram_val(void);
> > +
> >  #endif
> > diff --git a/arch/arm/mach-omap2/clock3xxx.c b/arch/arm/mach-
> omap2/clock3xxx.c
> > index a447c4d..ce84a98 100644
> > --- a/arch/arm/mach-omap2/clock3xxx.c
> > +++ b/arch/arm/mach-omap2/clock3xxx.c
> > @@ -38,7 +38,7 @@
> >  #define DPLL5_FREQ_FOR_USBHOST		120000000
> >
> >  /* needed by omap3_core_dpll_m2_set_rate() */
> > -struct clk *sdrc_ick_p, *arm_fck_p;
> > +struct clk *sdrc_ick_p, *arm_fck_p, *sys_ck_p;
> >
> >  int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
> >  {
> > diff --git a/arch/arm/mach-omap2/clock3xxx.h b/arch/arm/mach-
> omap2/clock3xxx.h
> > index 8bbeeaf..475d0c7 100644
> > --- a/arch/arm/mach-omap2/clock3xxx.h
> > +++ b/arch/arm/mach-omap2/clock3xxx.h
> > @@ -15,6 +15,7 @@ void omap3_clk_lock_dpll5(void);
> >
> >  extern struct clk *sdrc_ick_p;
> >  extern struct clk *arm_fck_p;
> > +extern struct clk *sys_ck_p;
> >
> >  extern const struct clkops clkops_noncore_dpll_ops;
> >
> > diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-
> omap2/clock3xxx_data.c
> > index 57522de..280adff 100644
> > --- a/arch/arm/mach-omap2/clock3xxx_data.c
> > +++ b/arch/arm/mach-omap2/clock3xxx_data.c
> > @@ -22,6 +22,7 @@
> >
> >  #include <plat/control.h>
> >  #include <plat/clkdev_omap.h>
> > +#include <plat/sram.h>
> >
> >  #include "clock.h"
> >  #include "clock3xxx.h"
> > @@ -57,6 +58,8 @@
> >  static struct clk dpll1_fck;
> >  static struct clk dpll2_fck;
> >
> > +static unsigned int delay_sram;
> > +
> >  /* PRM CLOCKS */
> >
> >  /* According to timer32k.c, this is a 32768Hz clock, not a 32000Hz clock. */
> > @@ -3598,6 +3601,16 @@ int __init omap3xxx_clk_init(void)
> >  	/* Avoid sleeping during omap3_core_dpll_m2_set_rate() */
> >  	sdrc_ick_p = clk_get(NULL, "sdrc_ick");
> >  	arm_fck_p = clk_get(NULL, "arm_fck");
> > +	sys_ck_p = clk_get(NULL, "sys_ck");
> > +
> > +	/* Measure sram delay */
> > +	delay_sram = measure_sram_delay(10000);
> > +	pr_debug("SRAM delay: %d\n", delay_sram);
> >
> >  	return 0;
> >  }
> > +
> > +unsigned int delay_sram_val(void)
> > +{
> > +	return delay_sram;
> > +}
> > diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-
> omap2/sram34xx.S
> > index de99ba2..5a1631f 100644
> > --- a/arch/arm/mach-omap2/sram34xx.S
> > +++ b/arch/arm/mach-omap2/sram34xx.S
> > @@ -313,3 +313,11 @@ core_m2_mask_val:
> >  ENTRY(omap3_sram_configure_core_dpll_sz)
> >  	.word	. - omap3_sram_configure_core_dpll
> >
> > +ENTRY(__sram_wait_delay)
> > +	subs    r0, r0, #1		@ loop till counter = 0
> > +	bne     __sram_wait_delay
> > +
> > +	mov     pc, lr
> > +
> > +ENTRY(__sram_wait_delay_sz)
> > +	.word   . - __sram_wait_delay
> > diff --git a/arch/arm/plat-omap/include/plat/sram.h b/arch/arm/plat-
> omap/include/plat/sram.h
> > index 16a1b45..dd294a8 100644
> > --- a/arch/arm/plat-omap/include/plat/sram.h
> > +++ b/arch/arm/plat-omap/include/plat/sram.h
> > @@ -69,6 +69,10 @@ extern u32 omap3_sram_configure_core_dpll(
> >  			u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1);
> >  extern unsigned long omap3_sram_configure_core_dpll_sz;
> >
> > +extern unsigned int measure_sram_delay(unsigned int);
> > +extern void __sram_wait_delay(unsigned int);
> > +extern unsigned long __sram_wait_delay_sz;
> > +
> >  #ifdef CONFIG_PM
> >  extern void omap_push_sram_idle(void);
> >  #else
> > diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
> > index 51f4dfb..a83d422 100644
> > --- a/arch/arm/plat-omap/sram.c
> > +++ b/arch/arm/plat-omap/sram.c
> > @@ -30,6 +30,9 @@
> >  #include <plat/cpu.h>
> >  #include <plat/vram.h>
> >
> > +#include <linux/clk.h>
> > +#include <plat/dmtimer.h>
> > +#include <plat/io.h>
> >  #include <plat/control.h>
> >
> >  #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
> > @@ -437,11 +440,59 @@ static inline int omap34xx_sram_init(void)
> >  }
> >  #endif
> >
> > +#ifdef CONFIG_ARCH_OMAP3
> > +void (*_omap3_sram_delay)(unsigned int);
> > +unsigned int  measure_sram_delay(unsigned int loop)
> > +{
> > +	static struct omap_dm_timer *gpt;
> > +	unsigned long flags, diff = 0, gt_rate, mpurate;
> > +	unsigned int delay_sram, error_gain;
> > +	unsigned int start = 0, end = 0;
> > +
> > +	omap_dm_timer_init();
> > +	gpt = omap_dm_timer_request();
> > +	if (!gpt) {
> > +		pr_err("Could not get the gptimer\n");
> > +		return -1;
> > +	}
> > +
> > +	omap_dm_timer_set_source(gpt, OMAP_TIMER_SRC_SYS_CLK);
> > +
> > +	gt_rate = clk_get_rate(omap_dm_timer_get_fclk(gpt));
> > +	omap_dm_timer_set_load_start(gpt, 0, 0);
> > +
> > +	local_irq_save(flags);
> > +	start = omap_dm_timer_read_counter(gpt);
> > +	_omap3_sram_delay(loop);
> > +	end = omap_dm_timer_read_counter(gpt);
> > +	diff = end - start;
> > +	local_irq_restore(flags);
> > +
> > +	omap_dm_timer_stop(gpt);
> > +	omap_dm_timer_free(gpt);
> > +
> > +	mpurate = clk_get_rate(clk_get(NULL, "arm_fck"));
> > +
> > +	/* calculate the sram delay */
> > +	delay_sram = (((mpurate / gt_rate) * diff) / (loop * 2));
> > +
> > +	error_gain = mpurate / gt_rate;
> > +	delay_sram = delay_sram + error_gain;
> 
> Cosmetic changes:
> 
>          error_gain = mpurate / gt_rate;
>          delay_sram = (error_gain * diff) / (loop);
>          delay_sram += error_gain;
> 
Why *2 is missing in your code? 2 is needed since the loop takes 2 arm cycles.

Regards
Vishwa
> Thanks,
> Ambresh
> 
> > +
> > +	return delay_sram;
> > +}
> > +#endif
> > +
> >  int __init omap_sram_init(void)
> >  {
> >  	omap_detect_sram();
> >  	omap_map_sram();
> >
> > +#ifdef CONFIG_ARCH_OMAP3
> > +	_omap3_sram_delay = omap_sram_push(__sram_wait_delay,
> > +						__sram_wait_delay_sz);
> > +#endif
> > +
> >  	if (!(cpu_class_is_omap2()))
> >  		omap1_sram_init();
> >  	else if (cpu_is_omap242x())


^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: [PATCH v2 2/2] OMAP3630 SDRC: Change in DVFS Latency Formula for OMAP3630
  2010-03-18  7:17     ` ambresh
@ 2010-03-19 13:17       ` Sripathy, Vishwanath
  2010-03-23  2:49         ` ambresh
  0 siblings, 1 reply; 13+ messages in thread
From: Sripathy, Vishwanath @ 2010-03-19 13:17 UTC (permalink / raw)
  To: K, Ambresh, Gurav , Pramod; +Cc: linux-omap@vger.kernel.org



> -----Original Message-----
> From: K, Ambresh
> Sent: Thursday, March 18, 2010 12:48 PM
> To: Gurav , Pramod
> Cc: linux-omap@vger.kernel.org; Sripathy, Vishwanath
> Subject: Re: [PATCH v2 2/2] OMAP3630 SDRC: Change in DVFS Latency Formula for
> OMAP3630
> 
> 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@ti.com>
> > Signed-off-by: Pramod Gurav <pramod.gurav@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).
> 
No, CLKOUTX2 is dependent on M2. Pls refer to table 3-45 (DPLL Operating Mode and Latency) in 3630 TRM Version D. 

Regards
Vishwa
> Thanks,
> Ambresh
> 
> >  	pr_debug("m = %d, n = %d, m2 =%d\n", core_dpll_mul_m, core_dpll_div_n,
> >  						core_dpll_clkoutdiv_m2);


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v4 1/2] OMAP3: SDRC: Dynamic Calculation of SDRC stall latency during DVFS
  2010-03-19 13:15     ` Sripathy, Vishwanath
@ 2010-03-21 13:24       ` ambresh
  0 siblings, 0 replies; 13+ messages in thread
From: ambresh @ 2010-03-21 13:24 UTC (permalink / raw)
  To: Sripathy, Vishwanath
  Cc: K, Ambresh, Gurav , Pramod, linux-omap@vger.kernel.org,
	Reddy, Teerth

Sripathy, Vishwanath wrote:
> 

>>> +	/* calculate the sram delay */
>>> +	delay_sram = (((mpurate / gt_rate) * diff) / (loop * 2));
>>> +
>>> +	error_gain = mpurate / gt_rate;
>>> +	delay_sram = delay_sram + error_gain;
>> Cosmetic changes:
>>
>>          error_gain = mpurate / gt_rate;
>>          delay_sram = (error_gain * diff) / (loop);
>>          delay_sram += error_gain;
>>
> Why *2 is missing in your code? 2 is needed since the loop takes 2 arm cycles.

its a typo, it should be (loop * 2).

BR,
Ambresh

> 
> Regards
> Vishwa
>> Thanks,
>> Ambresh
>>
>>> +
>>> +	return delay_sram;
>>> +}
>>> +#endif
>>> +
>>>  int __init omap_sram_init(void)
>>>  {
>>>  	omap_detect_sram();
>>>  	omap_map_sram();
>>>
>>> +#ifdef CONFIG_ARCH_OMAP3
>>> +	_omap3_sram_delay = omap_sram_push(__sram_wait_delay,
>>> +						__sram_wait_delay_sz);
>>> +#endif
>>> +
>>>  	if (!(cpu_class_is_omap2()))
>>>  		omap1_sram_init();
>>>  	else if (cpu_is_omap242x())
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 2/2] OMAP3630 SDRC: Change in DVFS Latency Formula for OMAP3630
  2010-03-19 13:17       ` Sripathy, Vishwanath
@ 2010-03-23  2:49         ` ambresh
  0 siblings, 0 replies; 13+ messages in thread
From: ambresh @ 2010-03-23  2:49 UTC (permalink / raw)
  To: Sripathy, Vishwanath
  Cc: K, Ambresh, Gurav , Pramod, linux-omap@vger.kernel.org

Sripathy, Vishwanath wrote:

>>>
>> -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).
>>
> No, CLKOUTX2 is dependent on M2. Pls refer to table 3-45 (DPLL Operating Mode and Latency) in 3630 TRM Version D. 
> 

Yes! Stabilization delay for CLKOUTx2 is dependent on M2.

Confusion prevailed because of the section 3.5.3.3.3.1 where clkoutx2 is 
not dependent on M2 factor. And moreover the formula used to calculate 
clkoutx2 in this case looks like the one used for computing clkout_M2X2 :)

Thanks,
Ambresh

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v4 1/2] OMAP3: SDRC: Dynamic Calculation of SDRC stall latency during DVFS
  2010-04-01 17:16 [PATCH V4 0/2] OMAP3: " Pramod Gurav
@ 2010-04-01 17:16 ` Pramod Gurav
  0 siblings, 0 replies; 13+ messages in thread
From: Pramod Gurav @ 2010-04-01 17:16 UTC (permalink / raw)
  To: linux-omap
  Cc: Teerth Reddy, Romit Dasgupta, Pramod Gurav, Vishwanath Sripathy,
	Ambresh K

From: Teerth Reddy <teerth@ti.com> 

The patch has the changes to calculate the dpll3 clock stabilization
delay dynamically. The SRAM delay is calibrated during bootup using the
gptimers and used while calculating the stabilization delay. By using
the dynamic method the dependency on the type of cache being used is
removed. Hence there is no need of loop based calculation.

The wait time for L3 clock stabilization is calculated using the formula
	= 4*REFCLK + 8*CLKOUTX2,
which uses the M, N and M2 read from the registers.
Since this gives slightly less value, 2us is added as buffer for safety.
This works fine for omap3.

Signed-off-by: Teerth Reddy <teerth@ti.com>
Signed-off-by: Romit Dasgupta <romit@ti.com>
Signed-off-by: Pramod Gurav <pramod.gurav@ti.com>
Signed-off-by: Vishwanath Sripathy <vishwanath.bs@ti.com>
Signed-off-by: Ambresh K <ambresh@ti.com>

---
 arch/arm/mach-omap2/clkt34xx_dpll3m2.c |   56 +++++++++++++++++++++++++------
 arch/arm/mach-omap2/clock34xx.h        |    2 +
 arch/arm/mach-omap2/clock3xxx.c        |    2 +-
 arch/arm/mach-omap2/clock3xxx.h        |    1 +
 arch/arm/mach-omap2/clock3xxx_data.c   |   13 +++++++
 arch/arm/mach-omap2/sram34xx.S         |    8 ++++
 arch/arm/plat-omap/include/plat/sram.h |    4 ++
 arch/arm/plat-omap/sram.c              |   51 +++++++++++++++++++++++++++++
 8 files changed, 125 insertions(+), 12 deletions(-)

diff --git a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
index b2b1e37..6ad18f2 100644
--- a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
+++ b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
@@ -24,13 +24,22 @@
 #include <plat/clock.h>
 #include <plat/sram.h>
 #include <plat/sdrc.h>
+#include <plat/prcm.h>
 
 #include "clock.h"
 #include "clock3xxx.h"
 #include "clock34xx.h"
 #include "sdrc.h"
 
-#define CYCLES_PER_MHZ			1000000
+#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		SCALING_FACTOR		10
 
 /*
  * CORE DPLL (DPLL3) M2 divider rate programming functions
@@ -51,10 +60,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 m, n, m2;
+	u32 sys_clk_rate, sdrc_clk_stab;
+	u32 refclk, clkoutx2, switch_latency;
 	struct omap_sdrc_params *sdrc_cs0;
 	struct omap_sdrc_params *sdrc_cs1;
+	unsigned long validrate, sdrcrate, _mpurate;
 	int ret;
 
 	if (!clk || !rate)
@@ -79,16 +92,37 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
 		unlock_dll = 1;
 	}
 
+	clk_sel_regval = __raw_readl(clk->clksel_reg);
+
+	/* Get the M, N and M2 values required for getting sdrc clk stab */
+	m = (clk_sel_regval >> SHIFT_DPLL_M) & DPLL_M_MASK;
+	n = (clk_sel_regval >> SHIFT_DPLL_N) & DPLL_N_MASK;
+	m2 = (clk_sel_regval >> SHIFT_DPLL_M2) & DPLL_M2_MASK;
+
+	sys_clk_rate = (sys_ck_p->rate) / CYCLES_PER_MHZ;
+
+	_mpurate = arm_fck_p->rate / CYCLES_PER_MHZ;
+
+	delay_sram = delay_sram_val();
+	sys_clk = (1 << SCALING_FACTOR) / sys_clk_rate;
+	clkoutx2 = (sys_clk * (n + 1) * m2) / (2 * m);
+
+	/* wait time for L3 clk stabilization = 4*REFCLK + 8*CLKOUTX2 */
+	refclk = (n + 1) * sys_clk;
+	switch_latency =  (4 * refclk) + (8 * clkoutx2);
+
+	/* Adding 2000 ns to sdrc clk stab */
+	sdrc_clk_stab =  switch_latency + 2000;
+
 	/*
-	 * XXX This only needs to be done when the CPU frequency changes
+	 * Calculate the number of MPU cycles
+	 * to wait for SDRC to stabilize
 	 */
-	_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;
+	c = ((sdrc_clk_stab * _mpurate) / (delay_sram * 2)) >> SCALING_FACTOR;
+
+	pr_debug("m = %d, n = %d, m2 =%d\n", m, n, 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/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
index 628e8de..a9f2204 100644
--- a/arch/arm/mach-omap2/clock34xx.h
+++ b/arch/arm/mach-omap2/clock34xx.h
@@ -12,4 +12,6 @@ extern const struct clkops clkops_omap3430es2_ssi_wait;
 extern const struct clkops clkops_omap3430es2_hsotgusb_wait;
 extern const struct clkops clkops_omap3430es2_dss_usbhost_wait;
 
+unsigned int delay_sram_val(void);
+
 #endif
diff --git a/arch/arm/mach-omap2/clock3xxx.c b/arch/arm/mach-omap2/clock3xxx.c
index a447c4d..ce84a98 100644
--- a/arch/arm/mach-omap2/clock3xxx.c
+++ b/arch/arm/mach-omap2/clock3xxx.c
@@ -38,7 +38,7 @@
 #define DPLL5_FREQ_FOR_USBHOST		120000000
 
 /* needed by omap3_core_dpll_m2_set_rate() */
-struct clk *sdrc_ick_p, *arm_fck_p;
+struct clk *sdrc_ick_p, *arm_fck_p, *sys_ck_p;
 
 int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
 {
diff --git a/arch/arm/mach-omap2/clock3xxx.h b/arch/arm/mach-omap2/clock3xxx.h
index 8bbeeaf..475d0c7 100644
--- a/arch/arm/mach-omap2/clock3xxx.h
+++ b/arch/arm/mach-omap2/clock3xxx.h
@@ -15,6 +15,7 @@ void omap3_clk_lock_dpll5(void);
 
 extern struct clk *sdrc_ick_p;
 extern struct clk *arm_fck_p;
+extern struct clk *sys_ck_p;
 
 extern const struct clkops clkops_noncore_dpll_ops;
 
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index 57522de..280adff 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -22,6 +22,7 @@
 
 #include <plat/control.h>
 #include <plat/clkdev_omap.h>
+#include <plat/sram.h>
 
 #include "clock.h"
 #include "clock3xxx.h"
@@ -57,6 +58,8 @@
 static struct clk dpll1_fck;
 static struct clk dpll2_fck;
 
+static unsigned int delay_sram;
+
 /* PRM CLOCKS */
 
 /* According to timer32k.c, this is a 32768Hz clock, not a 32000Hz clock. */
@@ -3598,6 +3601,16 @@ int __init omap3xxx_clk_init(void)
 	/* Avoid sleeping during omap3_core_dpll_m2_set_rate() */
 	sdrc_ick_p = clk_get(NULL, "sdrc_ick");
 	arm_fck_p = clk_get(NULL, "arm_fck");
+	sys_ck_p = clk_get(NULL, "sys_ck");
+
+	/* Measure sram delay */
+	delay_sram = measure_sram_delay(10000);
+	pr_debug("SRAM delay: %d\n", delay_sram);
 
 	return 0;
 }
+
+unsigned int delay_sram_val(void)
+{
+	return delay_sram;
+}
diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S
index de99ba2..5a1631f 100644
--- a/arch/arm/mach-omap2/sram34xx.S
+++ b/arch/arm/mach-omap2/sram34xx.S
@@ -313,3 +313,11 @@ core_m2_mask_val:
 ENTRY(omap3_sram_configure_core_dpll_sz)
 	.word	. - omap3_sram_configure_core_dpll
 
+ENTRY(__sram_wait_delay)
+	subs    r0, r0, #1		@ loop till counter = 0
+	bne     __sram_wait_delay
+
+	mov     pc, lr
+
+ENTRY(__sram_wait_delay_sz)
+	.word   . - __sram_wait_delay
diff --git a/arch/arm/plat-omap/include/plat/sram.h b/arch/arm/plat-omap/include/plat/sram.h
index 16a1b45..dd294a8 100644
--- a/arch/arm/plat-omap/include/plat/sram.h
+++ b/arch/arm/plat-omap/include/plat/sram.h
@@ -69,6 +69,10 @@ extern u32 omap3_sram_configure_core_dpll(
 			u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1);
 extern unsigned long omap3_sram_configure_core_dpll_sz;
 
+extern unsigned int measure_sram_delay(unsigned int);
+extern void __sram_wait_delay(unsigned int);
+extern unsigned long __sram_wait_delay_sz;
+
 #ifdef CONFIG_PM
 extern void omap_push_sram_idle(void);
 #else
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 51f4dfb..a890e5a 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -30,6 +30,9 @@
 #include <plat/cpu.h>
 #include <plat/vram.h>
 
+#include <linux/clk.h>
+#include <plat/dmtimer.h>
+#include <plat/io.h>
 #include <plat/control.h>
 
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
@@ -437,11 +440,59 @@ static inline int omap34xx_sram_init(void)
 }
 #endif
 
+#ifdef CONFIG_ARCH_OMAP3
+void (*_omap3_sram_delay)(unsigned int);
+unsigned int  measure_sram_delay(unsigned int loop)
+{
+	static struct omap_dm_timer *gpt;
+	unsigned long flags, diff = 0, gt_rate, mpurate;
+	unsigned int delay_sram, error_gain;
+	unsigned int start = 0, end = 0;
+
+	omap_dm_timer_init();
+	gpt = omap_dm_timer_request();
+	if (!gpt) {
+		pr_err("Could not get the gptimer\n");
+		return -1;
+	}
+
+	omap_dm_timer_set_source(gpt, OMAP_TIMER_SRC_SYS_CLK);
+
+	gt_rate = clk_get_rate(omap_dm_timer_get_fclk(gpt));
+	omap_dm_timer_set_load_start(gpt, 0, 0);
+
+	local_irq_save(flags);
+	start = omap_dm_timer_read_counter(gpt);
+	_omap3_sram_delay(loop);
+	end = omap_dm_timer_read_counter(gpt);
+	diff = end - start;
+	local_irq_restore(flags);
+
+	omap_dm_timer_stop(gpt);
+	omap_dm_timer_free(gpt);
+
+	mpurate = clk_get_rate(clk_get(NULL, "arm_fck"));
+
+	/* calculate the sram delay */
+	error_gain = mpurate / gt_rate;
+	delay_sram = ((error_gain * diff) / (loop * 2));
+
+	delay_sram += error_gain;
+
+	return delay_sram;
+}
+#endif
+
 int __init omap_sram_init(void)
 {
 	omap_detect_sram();
 	omap_map_sram();
 
+#ifdef CONFIG_ARCH_OMAP3
+	_omap3_sram_delay = omap_sram_push(__sram_wait_delay,
+						__sram_wait_delay_sz);
+#endif
+
 	if (!(cpu_class_is_omap2()))
 		omap1_sram_init();
 	else if (cpu_is_omap242x())
-- 
1.6.0.4


^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2010-04-01 11:39 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-03-18  4:55 [PATCH 0/2] OMAP3: Dynamic Calculation of SDRC stall latency during DVFS Pramod Gurav
2010-03-18  4:55 ` [PATCH v4 1/2] OMAP3: SDRC: " Pramod Gurav
2010-03-18  4:55   ` [PATCH v2 2/2] OMAP3630 SDRC: Change in DVFS Latency Formula for OMAP3630 Pramod Gurav
2010-03-18  7:17     ` ambresh
2010-03-19 13:17       ` Sripathy, Vishwanath
2010-03-23  2:49         ` ambresh
2010-03-18  6:17   ` [PATCH v4 1/2] OMAP3: SDRC: Dynamic Calculation of SDRC stall latency during DVFS G, Manjunath Kondaiah
2010-03-18 14:48     ` Kevin Hilman
2010-03-18  7:15   ` ambresh
2010-03-19 13:15     ` Sripathy, Vishwanath
2010-03-21 13:24       ` ambresh
2010-03-18 15:09   ` Kevin Hilman
  -- strict thread matches above, loose matches on Subject: below --
2010-04-01 17:16 [PATCH V4 0/2] OMAP3: " Pramod Gurav
2010-04-01 17:16 ` [PATCH v4 1/2] OMAP3: SDRC: " Pramod Gurav

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox