* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <asm/arch/clock.h>
#include <asm/arch/sram.h>
+#include <asm/arch/prcm.h>
-#include "prcm-regs.h"
-#include "memory.h"
#include "clock.h"
//#define DOWN_VARIABLE_DPLL 1 /* Experimental */
static struct prcm_config *curr_prcm_set;
+static struct memory_timings mem_timings;
static u32 curr_perf_level = PRCM_FULL_SPEED;
/*-------------------------------------------------------------------------
static u32 omap2_get_dpll_rate(struct clk * tclk)
{
- long long dpll_clk;
- int dpll_mult, dpll_div, amult;
+ int dpll_clk, dpll_mult, dpll_div, amult;
dpll_mult = (CM_CLKSEL1_PLL >> 12) & 0x03ff; /* 10 bits */
dpll_div = (CM_CLKSEL1_PLL >> 8) & 0x0f; /* 4 bits */
- dpll_clk = (long long)tclk->parent->rate * dpll_mult;
- do_div(dpll_clk, dpll_div + 1);
+ dpll_clk = (tclk->parent->rate * dpll_mult) / (dpll_div + 1);
amult = CM_CLKSEL2_PLL & 0x3;
dpll_clk *= amult;
return 0;
}
+static void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
+{
+ unsigned long dll_cnt;
+ u32 fast_dll = 0;
+
+ mem_timings.m_type = !((SDRC_MR_0 & 0x3) == 0x1); /* DDR = 1, SDR = 0 */
+
+ /* 2422 es2.05 and beyond has a single SIP DDR instead of 2 like others.
+ * In the case of 2422, its ok to use CS1 instead of CS0.
+ */
+
+#if 0 /* FIXME: Enable after 24xx cpu detection works */
+ ctype = get_cpu_type();
+ if (cpu_is_omap2422())
+ mem_timings.base_cs = 1;
+ else
+#endif
+ mem_timings.base_cs = 0;
+
+ if (mem_timings.m_type != M_DDR)
+ return;
+
+ /* With DDR we need to determine the low frequency DLL value */
+ if (((mem_timings.fast_dll_ctrl & (1 << 2)) == M_LOCK_CTRL))
+ mem_timings.dll_mode = M_UNLOCK;
+ else
+ mem_timings.dll_mode = M_LOCK;
+
+ if (mem_timings.base_cs == 0) {
+ fast_dll = SDRC_DLLA_CTRL;
+ dll_cnt = SDRC_DLLA_STATUS & 0xff00;
+ } else {
+ fast_dll = SDRC_DLLB_CTRL;
+ dll_cnt = SDRC_DLLB_STATUS & 0xff00;
+ }
+ if (force_lock_to_unlock_mode) {
+ fast_dll &= ~0xff00;
+ fast_dll |= dll_cnt; /* Current lock mode */
+ }
+ mem_timings.fast_dll_ctrl = fast_dll;
+
+ /* No disruptions, DDR will be offline & C-ABI not followed */
+ omap2_sram_ddr_init(&mem_timings.slow_dll_ctrl,
+ mem_timings.fast_dll_ctrl,
+ mem_timings.base_cs,
+ force_lock_to_unlock_mode);
+ mem_timings.slow_dll_ctrl &= 0xff00; /* Keep lock value */
+
+ /* Turn status into unlock ctrl */
+ mem_timings.slow_dll_ctrl |=
+ ((mem_timings.fast_dll_ctrl & 0xF) | (1 << 2));
+
+ /* 90 degree phase for anything below 133Mhz */
+ mem_timings.slow_dll_ctrl |= (1 << 1);
+}
+
static u32 omap2_reprogram_sdrc(u32 level, u32 force)
{
- u32 slow_dll_ctrl, fast_dll_ctrl, m_type;
u32 prev = curr_perf_level, flags;
if ((curr_perf_level == level) && !force)
return prev;
- m_type = omap2_memory_get_type();
- slow_dll_ctrl = omap2_memory_get_slow_dll_ctrl();
- fast_dll_ctrl = omap2_memory_get_fast_dll_ctrl();
-
if (level == PRCM_HALF_SPEED) {
local_irq_save(flags);
PRCM_VOLTSETUP = 0xffff;
omap2_sram_reprogram_sdrc(PRCM_HALF_SPEED,
- slow_dll_ctrl, m_type);
+ mem_timings.slow_dll_ctrl,
+ mem_timings.m_type);
curr_perf_level = PRCM_HALF_SPEED;
local_irq_restore(flags);
}
local_irq_save(flags);
PRCM_VOLTSETUP = 0xffff;
omap2_sram_reprogram_sdrc(PRCM_FULL_SPEED,
- fast_dll_ctrl, m_type);
+ mem_timings.fast_dll_ctrl,
+ mem_timings.m_type);
curr_perf_level = PRCM_FULL_SPEED;
local_irq_restore(flags);
}
case 13: /* dss2 */
mask = 0x1; break;
case 25: /* usb */
- mask = 0x7; break;
+ mask = 0xf; break;
}
}
/* Isolate control register */
div_sel = (SRC_RATE_SEL_MASK & clk->flags);
- div_off = clk->rate_offset;
+ div_off = clk->src_offset;
validrate = omap2_clksel_round_rate(clk, rate, &new_div);
- if (validrate != rate)
+ if(validrate != rate)
return(ret);
field_val = omap2_get_clksel(&div_sel, &field_mask, clk);
if (div_sel == 0)
return ret;
- if (clk->flags & CM_SYSCLKOUT_SEL1) {
- switch (new_div) {
- case 16:
- field_val = 4;
- break;
- case 8:
- field_val = 3;
- break;
- case 4:
- field_val = 2;
- break;
- case 2:
- field_val = 1;
- break;
- case 1:
- field_val = 0;
- break;
+ if(clk->flags & CM_SYSCLKOUT_SEL1){
+ switch(new_div){
+ case 16: field_val = 4; break;
+ case 8: field_val = 3; break;
+ case 4: field_val = 2; break;
+ case 2: field_val = 1; break;
+ case 1: field_val = 0; break;
}
- } else
+ }
+ else
field_val = new_div;
reg = (void __iomem *)div_sel;
val = 0x2;
break;
case CM_WKUP_SEL1:
- src_reg_addr = (u32)&CM_CLKSEL_WKUP;
+ src_reg_addr = (u32)&CM_CLKSEL2_CORE;
mask = 0x3;
if (src_clk == &func_32k_ck)
val = 0x0;
val = 0;
if (src_clk == &sys_ck)
val = 1;
- if (src_clk == &func_96m_ck)
- val = 2;
if (src_clk == &func_54m_ck)
+ val = 2;
+ if (src_clk == &func_96m_ck)
val = 3;
break;
}