]> git.sur5r.net Git - u-boot/blobdiff - arch/arm/cpu/armv7/omap-common/emif-common.c
Merge branch 'master' of git://git.denx.de/u-boot
[u-boot] / arch / arm / cpu / armv7 / omap-common / emif-common.c
index 846511d03bded902feee0414028da15f88cfd123..88253cf8ce3e5bf1128d70f08d22bacdfddb09b4 100644 (file)
 #include <asm/arch/sys_proto.h>
 #include <asm/omap_common.h>
 #include <asm/utils.h>
+#include <linux/compiler.h>
+
+static int emif1_enabled = -1, emif2_enabled = -1;
+
+void set_lpmode_selfrefresh(u32 base)
+{
+       struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
+       u32 reg;
+
+       reg = readl(&emif->emif_pwr_mgmt_ctrl);
+       reg &= ~EMIF_REG_LP_MODE_MASK;
+       reg |= LP_MODE_SELF_REFRESH << EMIF_REG_LP_MODE_SHIFT;
+       reg &= ~EMIF_REG_SR_TIM_MASK;
+       writel(reg, &emif->emif_pwr_mgmt_ctrl);
+
+       /* dummy read for the new SR_TIM to be loaded */
+       readl(&emif->emif_pwr_mgmt_ctrl);
+}
+
+void force_emif_self_refresh()
+{
+       set_lpmode_selfrefresh(EMIF1_BASE);
+       set_lpmode_selfrefresh(EMIF2_BASE);
+}
 
 inline u32 emif_num(u32 base)
 {
@@ -56,7 +80,12 @@ static inline u32 get_mr(u32 base, u32 cs, u32 mr_addr)
                mr = readl(&emif->emif_lpddr2_mode_reg_data);
        debug("get_mr: EMIF%d cs %d mr %08x val 0x%x\n", emif_num(base),
              cs, mr_addr, mr);
-       return mr;
+       if (((mr & 0x0000ff00) >>  8) == (mr & 0xff) &&
+           ((mr & 0x00ff0000) >> 16) == (mr & 0xff) &&
+           ((mr & 0xff000000) >> 24) == (mr & 0xff))
+               return mr & 0xff;
+       else
+               return mr;
 }
 
 static inline void set_mr(u32 base, u32 cs, u32 mr_addr, u32 mr_val)
@@ -114,9 +143,6 @@ static void do_lpddr2_init(u32 base, u32 cs)
 static void lpddr2_init(u32 base, const struct emif_regs *regs)
 {
        struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
-       u32 *ext_phy_ctrl_base = 0;
-       u32 *emif_ext_phy_ctrl_base = 0;
-       u32 i = 0;
 
        /* Not NVM */
        clrbits_le32(&emif->emif_lpddr2_nvm_config, EMIF_REG_CS1NVMEN_MASK);
@@ -134,29 +160,7 @@ static void lpddr2_init(u32 base, const struct emif_regs *regs)
        writel(regs->sdram_config_init, &emif->emif_sdram_config);
        writel(regs->emif_ddr_phy_ctlr_1, &emif->emif_ddr_phy_ctrl_1);
 
-       ext_phy_ctrl_base = (u32 *) &(regs->emif_ddr_ext_phy_ctrl_1);
-       emif_ext_phy_ctrl_base = (u32 *) &(emif->emif_ddr_ext_phy_ctrl_1);
-
-       if (omap_revision() >= OMAP5430_ES1_0) {
-               /* Configure external phy control timing registers */
-               for (i = 0; i < EMIF_EXT_PHY_CTRL_TIMING_REG; i++) {
-                       writel(*ext_phy_ctrl_base, emif_ext_phy_ctrl_base++);
-                       /* Update shadow registers */
-                       writel(*ext_phy_ctrl_base++, emif_ext_phy_ctrl_base++);
-               }
-
-               /*
-                * external phy 6-24 registers do not change with
-                * ddr frequency
-                */
-               for (i = 0; i < EMIF_EXT_PHY_CTRL_CONST_REG; i++) {
-                       writel(ext_phy_ctrl_const_base[i],
-                                               emif_ext_phy_ctrl_base++);
-                       /* Update shadow registers */
-                       writel(ext_phy_ctrl_const_base[i],
-                                               emif_ext_phy_ctrl_base++);
-               }
-       }
+       do_ext_phy_settings(base, regs);
 
        do_lpddr2_init(base, CS0);
        if (regs->sdram_config & EMIF_REG_EBANK_MASK)
@@ -168,6 +172,10 @@ static void lpddr2_init(u32 base, const struct emif_regs *regs)
        /* Enable refresh now */
        clrbits_le32(&emif->emif_sdram_ref_ctrl, EMIF_REG_INITREF_DIS_MASK);
 
+       }
+
+__weak void do_ext_phy_settings(u32 base, const struct emif_regs *regs)
+{
 }
 
 void emif_update_timings(u32 base, const struct emif_regs *regs)
@@ -921,7 +929,7 @@ static u8 is_lpddr2_sdram_present(u32 base, u32 cs,
        }
 
        mr = get_mr(base, cs, LPDDR2_MR5);
-       if (mr >= 0xFF) {
+       if (mr > 0xFF) {
                /* Mode register value bigger than 8 bit */
                return 0;
        }
@@ -990,7 +998,7 @@ struct lpddr2_device_details *emif_get_device_details(u32 emif_nr, u8 cs,
                return NULL;
 
        /* Do the minimum init for mode register accesses */
-       if (!running_from_sdram()) {
+       if (!(running_from_sdram() || warm_reset())) {
                phy = get_ddr_phy_ctrl_1(get_sys_clk_freq() / 2, RL_BOOT);
                writel(phy, &emif->emif_ddr_phy_ctrl_1);
        }
@@ -1070,7 +1078,7 @@ static void do_sdram_init(u32 base)
         * Changing the timing registers in EMIF can happen(going from one
         * OPP to another)
         */
-       if (!in_sdram) {
+       if (!(in_sdram || warm_reset())) {
                if (omap_revision() != OMAP5432_ES1_0)
                        lpddr2_init(base, regs);
                else
@@ -1103,6 +1111,7 @@ void emif_post_init_config(u32 base)
 void dmm_init(u32 base)
 {
        const struct dmm_lisa_map_regs *lisa_map_regs;
+       u32 i, section, valid;
 
 #ifdef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS
        emif_get_dmm_regs(&lisa_map_regs);
@@ -1210,6 +1219,29 @@ void dmm_init(u32 base)
                writel(lisa_map_regs->dmm_lisa_map_0,
                        &hw_lisa_map_regs->dmm_lisa_map_0);
        }
+
+       /*
+        * EMIF should be configured only when
+        * memory is mapped on it. Using emif1_enabled
+        * and emif2_enabled variables for this.
+        */
+       emif1_enabled = 0;
+       emif2_enabled = 0;
+       for (i = 0; i < 4; i++) {
+               section = __raw_readl(DMM_BASE + i*4);
+               valid = (section & EMIF_SDRC_MAP_MASK) >>
+                       (EMIF_SDRC_MAP_SHIFT);
+               if (valid == 3) {
+                       emif1_enabled = 1;
+                       emif2_enabled = 1;
+                       break;
+               } else if (valid == 1) {
+                       emif1_enabled = 1;
+               } else if (valid == 2) {
+                       emif2_enabled = 1;
+               }
+       }
+
 }
 
 /*
@@ -1232,6 +1264,7 @@ void dmm_init(u32 base)
 void sdram_init(void)
 {
        u32 in_sdram, size_prog, size_detect;
+       u32 omap_rev = omap_revision();
 
        debug(">>sdram_init()\n");
 
@@ -1241,21 +1274,32 @@ void sdram_init(void)
        in_sdram = running_from_sdram();
        debug("in_sdram = %d\n", in_sdram);
 
+       if (!(in_sdram || warm_reset())) {
+               if (omap_rev != OMAP5432_ES1_0)
+                       bypass_dpll(&prcm->cm_clkmode_dpll_core);
+               else
+                       writel(CM_DLL_CTRL_NO_OVERRIDE, &prcm->cm_dll_ctrl);
+       }
+
        if (!in_sdram)
-               bypass_dpll(&prcm->cm_clkmode_dpll_core);
+               dmm_init(DMM_BASE);
 
+       if (emif1_enabled)
+               do_sdram_init(EMIF1_BASE);
 
-       do_sdram_init(EMIF1_BASE);
-       do_sdram_init(EMIF2_BASE);
+       if (emif2_enabled)
+               do_sdram_init(EMIF2_BASE);
 
-       if (!in_sdram) {
-               dmm_init(DMM_BASE);
-               emif_post_init_config(EMIF1_BASE);
-               emif_post_init_config(EMIF2_BASE);
+       if (!(in_sdram || warm_reset())) {
+               if (emif1_enabled)
+                       emif_post_init_config(EMIF1_BASE);
+               if (emif2_enabled)
+                       emif_post_init_config(EMIF2_BASE);
        }
 
        /* for the shadow registers to take effect */
-       freq_update_core();
+       if (omap_rev != OMAP5432_ES1_0)
+               freq_update_core();
 
        /* Do some testing after the init */
        if (!in_sdram) {