]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - arch/arm/cpu/armv7/omap-common/emif-common.c
Merge branch 'master' of git://git.denx.de/u-boot-arc
[karo-tx-uboot.git] / arch / arm / cpu / armv7 / omap-common / emif-common.c
index 62678ff5d30739ce6dc0a4fdb5ea398acc3d31ea..c8e9bc86e588c8dc3e54e255af7cabbabf7b6618 100644 (file)
@@ -6,31 +6,39 @@
  *
  * Aneesh V <aneesh@ti.com>
  *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
 #include <asm/emif.h>
-#include <asm/arch/clocks.h>
+#include <asm/arch/clock.h>
 #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)
 {
@@ -42,7 +50,6 @@ inline u32 emif_num(u32 base)
                return 0;
 }
 
-
 static inline u32 get_mr(u32 base, u32 cs, u32 mr_addr)
 {
        u32 mr;
@@ -56,7 +63,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)
@@ -81,24 +93,32 @@ void emif_reset_phy(u32 base)
 static void do_lpddr2_init(u32 base, u32 cs)
 {
        u32 mr_addr;
+       const struct lpddr2_mr_regs *mr_regs;
 
+       get_lpddr2_mr_regs(&mr_regs);
        /* Wait till device auto initialization is complete */
        while (get_mr(base, cs, LPDDR2_MR0) & LPDDR2_MR0_DAI_MASK)
                ;
-       set_mr(base, cs, LPDDR2_MR10, MR10_ZQ_ZQINIT);
+       set_mr(base, cs, LPDDR2_MR10, mr_regs->mr10);
        /*
         * tZQINIT = 1 us
         * Enough loops assuming a maximum of 2GHz
         */
+
        sdelay(2000);
-       set_mr(base, cs, LPDDR2_MR1, MR1_BL_8_BT_SEQ_WRAP_EN_NWR_3);
-       set_mr(base, cs, LPDDR2_MR16, MR16_REF_FULL_ARRAY);
+
+       set_mr(base, cs, LPDDR2_MR1, mr_regs->mr1);
+       set_mr(base, cs, LPDDR2_MR16, mr_regs->mr16);
+
        /*
         * Enable refresh along with writing MR2
         * Encoding of RL in MR2 is (RL - 2)
         */
        mr_addr = LPDDR2_MR2 | EMIF_REG_REFRESH_EN_MASK;
-       set_mr(base, cs, mr_addr, RL_FINAL - 2);
+       set_mr(base, cs, mr_addr, mr_regs->mr2);
+
+       if (mr_regs->mr3 > 0)
+               set_mr(base, cs, LPDDR2_MR3, mr_regs->mr3);
 }
 
 static void lpddr2_init(u32 base, const struct emif_regs *regs)
@@ -121,6 +141,8 @@ 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_init, &emif->emif_ddr_phy_ctrl_1);
 
+       do_ext_phy_settings(base, regs);
+
        do_lpddr2_init(base, CS0);
        if (regs->sdram_config & EMIF_REG_EBANK_MASK)
                do_lpddr2_init(base, CS1);
@@ -131,6 +153,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)
@@ -153,7 +179,7 @@ void emif_update_timings(u32 base, const struct emif_regs *regs)
        writel(regs->temp_alert_config, &emif->emif_temp_alert_config);
        writel(regs->emif_ddr_phy_ctlr_1, &emif->emif_ddr_phy_ctrl_1_shdw);
 
-       if (omap_revision() == OMAP5430_ES1_0) {
+       if ((omap_revision() >= OMAP5430_ES1_0) || is_dra7xx()) {
                writel(EMIF_L3_CONFIG_VAL_SYS_10_MPU_5_LL_0,
                        &emif->emif_l3_config);
        } else if (omap_revision() >= OMAP4460_ES1_0) {
@@ -165,6 +191,103 @@ void emif_update_timings(u32 base, const struct emif_regs *regs)
        }
 }
 
+static void omap5_ddr3_leveling(u32 base, const struct emif_regs *regs)
+{
+       struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
+
+       /* keep sdram in self-refresh */
+       writel(((LP_MODE_SELF_REFRESH << EMIF_REG_LP_MODE_SHIFT)
+               & EMIF_REG_LP_MODE_MASK), &emif->emif_pwr_mgmt_ctrl);
+       __udelay(130);
+
+       /*
+        * Set invert_clkout (if activated)--DDR_PHYCTRL_1
+        * Invert clock adds an additional half cycle delay on the
+        * command interface.  The additional half cycle, is usually
+        * meant to enable leveling in the situation that DQS is later
+        * than CK on the board.It also helps provide some additional
+        * margin for leveling.
+        */
+       writel(regs->emif_ddr_phy_ctlr_1,
+              &emif->emif_ddr_phy_ctrl_1);
+
+       writel(regs->emif_ddr_phy_ctlr_1,
+              &emif->emif_ddr_phy_ctrl_1_shdw);
+       __udelay(130);
+
+       writel(((LP_MODE_DISABLE << EMIF_REG_LP_MODE_SHIFT)
+              & EMIF_REG_LP_MODE_MASK), &emif->emif_pwr_mgmt_ctrl);
+
+       /* Launch Full leveling */
+       writel(DDR3_FULL_LVL, &emif->emif_rd_wr_lvl_ctl);
+
+       /* Wait till full leveling is complete */
+       readl(&emif->emif_rd_wr_lvl_ctl);
+             __udelay(130);
+
+       /* Read data eye leveling no of samples */
+       config_data_eye_leveling_samples(base);
+
+       /*
+        * Launch 8 incremental WR_LVL- to compensate for
+        * PHY limitation.
+        */
+       writel(0x2 << EMIF_REG_WRLVLINC_INT_SHIFT,
+              &emif->emif_rd_wr_lvl_ctl);
+
+       __udelay(130);
+
+       /* Launch Incremental leveling */
+       writel(DDR3_INC_LVL, &emif->emif_rd_wr_lvl_ctl);
+              __udelay(130);
+}
+
+static void ddr3_leveling(u32 base, const struct emif_regs *regs)
+{
+       if (is_omap54xx())
+               omap5_ddr3_leveling(base, regs);
+}
+
+static void ddr3_init(u32 base, const struct emif_regs *regs)
+{
+       struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
+
+       /*
+        * Set SDRAM_CONFIG and PHY control registers to locked frequency
+        * and RL =7. As the default values of the Mode Registers are not
+        * defined, contents of mode Registers must be fully initialized.
+        * H/W takes care of this initialization
+        */
+       writel(regs->emif_ddr_phy_ctlr_1_init, &emif->emif_ddr_phy_ctrl_1);
+
+       /* Update timing registers */
+       writel(regs->sdram_tim1, &emif->emif_sdram_tim_1);
+       writel(regs->sdram_tim2, &emif->emif_sdram_tim_2);
+       writel(regs->sdram_tim3, &emif->emif_sdram_tim_3);
+
+       writel(regs->ref_ctrl, &emif->emif_sdram_ref_ctrl);
+       writel(regs->read_idle_ctrl, &emif->emif_read_idlectrl);
+
+       /*
+        * The same sequence should work on OMAP5432 as well. But strange that
+        * it is not working
+        */
+       if (is_dra7xx()) {
+               do_ext_phy_settings(base, regs);
+               writel(regs->sdram_config2, &emif->emif_lpddr2_nvm_config);
+               writel(regs->sdram_config_init, &emif->emif_sdram_config);
+       } else {
+               writel(regs->sdram_config2, &emif->emif_lpddr2_nvm_config);
+               writel(regs->sdram_config_init, &emif->emif_sdram_config);
+               do_ext_phy_settings(base, regs);
+       }
+
+       /* enable leveling */
+       writel(regs->emif_rd_wr_lvl_rmp_ctl, &emif->emif_rd_wr_lvl_rmp_ctl);
+
+       ddr3_leveling(base, regs);
+}
+
 #ifndef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS
 #define print_timing_reg(reg) debug(#reg" - 0x%08x\n", (reg))
 
@@ -527,20 +650,27 @@ static u32 get_ddr_phy_ctrl_1(u32 freq, u8 RL)
        return phy;
 }
 
-static u32 get_emif_mem_size(struct emif_device_details *devices)
+static u32 get_emif_mem_size(u32 base)
 {
        u32 size_mbytes = 0, temp;
+       struct emif_device_details dev_details;
+       struct lpddr2_device_details cs0_dev_details, cs1_dev_details;
+       u32 emif_nr = emif_num(base);
 
-       if (!devices)
-               return 0;
+       emif_reset_phy(base);
+       dev_details.cs0_device_details = emif_get_device_details(emif_nr, CS0,
+                                               &cs0_dev_details);
+       dev_details.cs1_device_details = emif_get_device_details(emif_nr, CS1,
+                                               &cs1_dev_details);
+       emif_reset_phy(base);
 
-       if (devices->cs0_device_details) {
-               temp = devices->cs0_device_details->density;
+       if (dev_details.cs0_device_details) {
+               temp = dev_details.cs0_device_details->density;
                size_mbytes += lpddr2_density_2_size_in_mbytes[temp];
        }
 
-       if (devices->cs1_device_details) {
-               temp = devices->cs1_device_details->density;
+       if (dev_details.cs1_device_details) {
+               temp = dev_details.cs1_device_details->density;
                size_mbytes += lpddr2_density_2_size_in_mbytes[temp];
        }
        /* convert to bytes */
@@ -789,7 +919,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;
        }
@@ -858,7 +988,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);
        }
@@ -912,13 +1042,9 @@ static void do_sdram_init(u32 base)
        /* Return if no devices on this EMIF */
        if (!dev_details.cs0_device_details &&
            !dev_details.cs1_device_details) {
-               emif_sizes[emif_nr - 1] = 0;
                return;
        }
 
-       if (!in_sdram)
-               emif_sizes[emif_nr - 1] = get_emif_mem_size(&dev_details);
-
        /*
         * Get device timings:
         * - Default timings specified by JESD209-2 if
@@ -938,8 +1064,17 @@ static void do_sdram_init(u32 base)
         * Changing the timing registers in EMIF can happen(going from one
         * OPP to another)
         */
-       if (!in_sdram)
-               lpddr2_init(base, regs);
+       if (!(in_sdram || warm_reset())) {
+               if (emif_sdram_type() == EMIF_SDRAM_TYPE_LPDDR2)
+                       lpddr2_init(base, regs);
+               else
+                       ddr3_init(base, regs);
+       }
+       if (warm_reset() && (emif_sdram_type() == EMIF_SDRAM_TYPE_DDR3)) {
+               set_lpmode_selfrefresh(base);
+               emif_reset_phy(base);
+               ddr3_leveling(base, regs);
+       }
 
        /* Write to the shadow registers */
        emif_update_timings(base, regs);
@@ -952,9 +1087,6 @@ void emif_post_init_config(u32 base)
        struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
        u32 omap_rev = omap_revision();
 
-       if (omap_rev == OMAP5430_ES1_0)
-               return;
-
        /* reset phy on ES2.0 */
        if (omap_rev == OMAP4430_ES2_0)
                emif_reset_phy(base);
@@ -967,6 +1099,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);
@@ -978,8 +1111,8 @@ void dmm_init(u32 base)
        mapped_size = 0;
        section_cnt = 3;
        sys_addr = CONFIG_SYS_SDRAM_BASE;
-       emif1_size = emif_sizes[0];
-       emif2_size = emif_sizes[1];
+       emif1_size = get_emif_mem_size(EMIF1_BASE);
+       emif2_size = get_emif_mem_size(EMIF2_BASE);
        debug("emif1_size 0x%x emif2_size 0x%x\n", emif1_size, emif2_size);
 
        if (!emif1_size && !emif2_size)
@@ -1042,6 +1175,9 @@ void dmm_init(u32 base)
        /* TRAP for invalid TILER mappings in section 0 */
        lis_map_regs_calculated.dmm_lisa_map_0 = DMM_LISA_MAP_0_INVAL_ADDR_TRAP;
 
+       if (omap_revision() >= OMAP4460_ES1_0)
+               lis_map_regs_calculated.is_ma_present = 1;
+
        lisa_map_regs = &lis_map_regs_calculated;
 #endif
        struct dmm_lisa_map_regs *hw_lisa_map_regs =
@@ -1061,7 +1197,7 @@ void dmm_init(u32 base)
        writel(lisa_map_regs->dmm_lisa_map_0,
                &hw_lisa_map_regs->dmm_lisa_map_0);
 
-       if (omap_revision() >= OMAP4460_ES1_0) {
+       if (lisa_map_regs->is_ma_present) {
                hw_lisa_map_regs =
                    (struct dmm_lisa_map_regs *)MA_BASE;
 
@@ -1074,6 +1210,65 @@ 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;
+               }
+       }
+
+}
+
+static void do_bug0039_workaround(u32 base)
+{
+       u32 val, i, clkctrl;
+       struct emif_reg_struct *emif_base = (struct emif_reg_struct *)base;
+       const struct read_write_regs *bug_00339_regs;
+       u32 iterations;
+       u32 *phy_status_base = &emif_base->emif_ddr_phy_status[0];
+       u32 *phy_ctrl_base = &emif_base->emif_ddr_ext_phy_ctrl_1;
+
+       if (is_dra7xx())
+               phy_status_base++;
+
+       bug_00339_regs = get_bug_regs(&iterations);
+
+       /* Put EMIF in to idle */
+       clkctrl = __raw_readl((*prcm)->cm_memif_clkstctrl);
+       __raw_writel(0x0, (*prcm)->cm_memif_clkstctrl);
+
+       /* Copy the phy status registers in to phy ctrl shadow registers */
+       for (i = 0; i < iterations; i++) {
+               val = __raw_readl(phy_status_base +
+                                 bug_00339_regs[i].read_reg - 1);
+
+               __raw_writel(val, phy_ctrl_base +
+                            ((bug_00339_regs[i].write_reg - 1) << 1));
+
+               __raw_writel(val, phy_ctrl_base +
+                            (bug_00339_regs[i].write_reg << 1) - 1);
+       }
+
+       /* Disable leveling */
+       writel(0x0, &emif_base->emif_rd_wr_lvl_rmp_ctl);
+
+       __raw_writel(clkctrl,  (*prcm)->cm_memif_clkstctrl);
 }
 
 /*
@@ -1096,6 +1291,7 @@ void dmm_init(u32 base)
 void sdram_init(void)
 {
        u32 in_sdram, size_prog, size_detect;
+       u32 sdram_type = emif_sdram_type();
 
        debug(">>sdram_init()\n");
 
@@ -1105,25 +1301,39 @@ void sdram_init(void)
        in_sdram = running_from_sdram();
        debug("in_sdram = %d\n", in_sdram);
 
+       if (!in_sdram) {
+               if ((sdram_type == EMIF_SDRAM_TYPE_LPDDR2) && !warm_reset())
+                       bypass_dpll((*prcm)->cm_clkmode_dpll_core);
+               else if (sdram_type == EMIF_SDRAM_TYPE_DDR3)
+                       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 (sdram_type == EMIF_SDRAM_TYPE_LPDDR2)
+               freq_update_core();
 
        /* Do some testing after the init */
        if (!in_sdram) {
                size_prog = omap_sdram_size();
+               size_prog = log_2_n_round_down(size_prog);
+               size_prog = (1 << size_prog);
+
                size_detect = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE,
                                                size_prog);
                /* Compare with the size programmed */
@@ -1136,5 +1346,13 @@ void sdram_init(void)
                        debug("get_ram_size() successful");
        }
 
+       if (sdram_type == EMIF_SDRAM_TYPE_DDR3 &&
+           (!in_sdram && !warm_reset()) && (!is_dra7xx())) {
+               if (emif1_enabled)
+                       do_bug0039_workaround(EMIF1_BASE);
+               if (emif2_enabled)
+                       do_bug0039_workaround(EMIF2_BASE);
+       }
+
        debug("<<sdram_init()\n");
 }