X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Farm%2Fmach-omap2%2Fclock.c;fp=arch%2Farm%2Fmach-omap2%2Fclock.c;h=180f675c9064094d1fb95486b5bdfbad8c1d8f8c;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=d1b648a4efbfde4ad325e1f136fab6d226fb2789;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index d1b648a4e..180f675c9 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -15,6 +15,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include #include #include #include @@ -27,14 +28,14 @@ #include #include +#include -#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; /*------------------------------------------------------------------------- @@ -53,13 +54,11 @@ static void omap2_sys_clk_recalc(struct clk * clk) 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; @@ -386,23 +385,75 @@ static u32 omap2_dll_force_needed(void) 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); } @@ -410,7 +461,8 @@ static u32 omap2_reprogram_sdrc(u32 level, u32 force) 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); } @@ -598,7 +650,7 @@ static u32 omap2_get_clksel(u32 *div_sel, u32 *field_mask, case 13: /* dss2 */ mask = 0x1; break; case 25: /* usb */ - mask = 0x7; break; + mask = 0xf; break; } } @@ -659,35 +711,26 @@ static int omap2_clk_set_rate(struct clk *clk, unsigned long rate) /* 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; @@ -752,7 +795,7 @@ static u32 omap2_get_src_field(u32 *type_to_addr, u32 reg_offset, 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; @@ -792,9 +835,9 @@ static u32 omap2_get_src_field(u32 *type_to_addr, u32 reg_offset, 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; }