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;