linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / arch / arm / mach-omap2 / clock.c
index d1b648a..180f675 100644 (file)
@@ -15,6 +15,7 @@
  * 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;
 
 /*-------------------------------------------------------------------------
@@ -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;
        }