@@ -56,9 +56,18 @@
*/
#define DPLL5_FREQ_FOR_USBHOST 120000000
+/*
+ * SDRC_TIME_STABILIZE: Time for SDRC to stabilize in us
+ * TO DO: Use formula to calculate across all platforms
+ */
+#define SDRC_TIME_STABILIZE 6
+
/* needed by omap3_core_dpll_m2_set_rate() */
struct clk *sdrc_ick_p, *arm_fck_p;
+/* SRAM delay required for sdrc clk stab delay calculation */
+unsigned int delay_sram;
+
/**
* omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI
* @clk: struct clk * being enabled
@@ -215,16 +224,10 @@ 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
- */
+ /* 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_TIME_STABILIZE * _mpurate) / (delay_sram * 2));
pr_debug("clock: changing CORE DPLL rate from %lu to %lu\n", clk->rate,
validrate);
@@ -21,4 +21,6 @@ extern const struct clkops clkops_omap3430es2_hsotgusb_wait;
extern const struct clkops clkops_omap3430es2_dss_usbhost_wait;
extern const struct clkops clkops_noncore_dpll_ops;
+extern unsigned int delay_sram;
+
#endif
@@ -22,6 +22,7 @@
#include <plat/control.h>
#include <plat/clkdev_omap.h>
+#include <plat/sram.h>
#include "clock.h"
#include "clock34xx.h"
@@ -3285,5 +3286,8 @@ int __init omap2_clk_init(void)
sdrc_ick_p = clk_get(NULL, "sdrc_ick");
arm_fck_p = clk_get(NULL, "arm_fck");
+ /* Measure sram delay */
+ delay_sram = measure_sram_delay(10000);
+ pr_debug("SRAM delay: %d\n", delay_sram);
return 0;
}
@@ -68,6 +68,10 @@
/* CM_CLKSEL1_PLL bit settings */
#define CORE_DPLL_CLKOUT_DIV_SHIFT 0x1b
+#define GPTIMER10_TCRR_PHY 0x48086028
+
+#define GPTIMER10_TCRR OMAP2_L4_IO_ADDRESS(GPTIMER10_TCRR_PHY)
+
/*
* omap3_sram_configure_core_dpll - change DPLL3 M2 divider
*
@@ -313,3 +317,24 @@ core_m2_mask_val:
ENTRY(omap3_sram_configure_core_dpll_sz)
.word . - omap3_sram_configure_core_dpll
+ENTRY(__sram_wait_delay)
+ stmfd sp!, {r1-r12, lr} @ store regs to stack
+ ldr r2, gptimer10_counter
+ ldr r3, [r2]
+
+loop1:
+ subs r0, r0, #1
+ bne loop1
+
+ isb
+ ldr r4, [r2]
+ subs r5, r4, r3
+
+ mov r0, r5 @ return value
+ ldmfd sp!, {r1-r12, pc} @ restore regs and return
+
+gptimer10_counter:
+ .word GPTIMER10_TCRR
+
+ENTRY(__sram_wait_delay_sz)
+ .word . - __sram_wait_delay
@@ -69,6 +69,11 @@ 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 u32 __sram_wait_delay(unsigned int);
+extern unsigned long __sram_wait_delay_sz;
+
#ifdef CONFIG_PM
extern void omap_push_sram_idle(void);
#else
@@ -30,6 +30,9 @@
#include <plat/cpu.h>
#include <plat/vram.h>
+#include <linux/clk.h>
+#include <plat/dmtimer.h>
+
#include <plat/control.h>
#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
@@ -437,11 +440,51 @@ static inline int omap34xx_sram_init(void)
}
#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+unsigned long (*_omap3_sram_delay)(unsigned long);
+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;
+
+ omap_dm_timer_init();
+ gpt = omap_dm_timer_request_specific(10);
+ if (!gpt)
+ pr_err("Could not get the gptimer\n");
+ 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);
+ diff = _omap3_sram_delay(loop);
+ 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/1000000) / (gt_rate/1000000)) * diff) / 20000);
+
+ error_gain = ((mpurate/1000000) / (gt_rate/1000000));
+ delay_sram = delay_sram + error_gain;
+
+ return delay_sram;
+}
+#endif
+
int __init omap_sram_init(void)
{
omap_detect_sram();
omap_map_sram();
+ _omap3_sram_delay = omap_sram_push(__sram_wait_delay,
+ __sram_wait_delay_sz);
+
if (!(cpu_class_is_omap2()))
omap1_sram_init();
else if (cpu_is_omap242x())