]> git.karo-electronics.de Git - karo-tx-uboot.git/blobdiff - arch/arm/cpu/armv7/omap-common/emif-common.c
ARM: DRA7: emif: Fix disabling/enabling of refreshes
[karo-tx-uboot.git] / arch / arm / cpu / armv7 / omap-common / emif-common.c
index 9eb1279d4112699d93c9ca511d267b7af1aaeeba..bf7bf262c7f6dec7f8f440b4c6b0974825379c59 100644 (file)
@@ -6,28 +6,12 @@
  *
  * 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>
@@ -66,20 +50,6 @@ inline u32 emif_num(u32 base)
                return 0;
 }
 
-/*
- * Get SDRAM type connected to EMIF.
- * Assuming similar SDRAM parts are connected to both EMIF's
- * which is typically the case. So it is sufficient to get
- * SDRAM type from EMIF1.
- */
-u32 emif_sdram_type()
-{
-       struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
-
-       return (readl(&emif->emif_sdram_config) &
-               EMIF_REG_SDRAM_TYPE_MASK) >> EMIF_REG_SDRAM_TYPE_SHIFT;
-}
-
 static inline u32 get_mr(u32 base, u32 cs, u32 mr_addr)
 {
        u32 mr;
@@ -169,7 +139,7 @@ static void lpddr2_init(u32 base, const struct emif_regs *regs)
         * un-locked frequency & default RL
         */
        writel(regs->sdram_config_init, &emif->emif_sdram_config);
-       writel(regs->emif_ddr_phy_ctlr_1, &emif->emif_ddr_phy_ctrl_1);
+       writel(regs->emif_ddr_phy_ctlr_1_init, &emif->emif_ddr_phy_ctrl_1);
 
        do_ext_phy_settings(base, regs);
 
@@ -209,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) {
@@ -221,7 +191,7 @@ void emif_update_timings(u32 base, const struct emif_regs *regs)
        }
 }
 
-static void ddr3_leveling(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;
 
@@ -232,49 +202,173 @@ static void ddr3_leveling(u32 base, const struct emif_regs *regs)
 
        /*
         * 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.
+        * 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);
+       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);
+              & 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);
+             __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);
+       /*
+        * 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);
+              __udelay(130);
 }
 
-static void ddr3_init(u32 base, const struct emif_regs *regs)
+static void update_hwleveling_output(u32 base, const struct emif_regs *regs)
+{
+       struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
+       u32 *emif_ext_phy_ctrl_reg, *emif_phy_status;
+       u32 reg, i;
+
+       emif_phy_status = (u32 *)&emif->emif_ddr_phy_status[7];
+
+       /* Update PHY_REG_RDDQS_RATIO */
+       emif_ext_phy_ctrl_reg = (u32 *)&emif->emif_ddr_ext_phy_ctrl_7;
+       for (i = 0; i < PHY_RDDQS_RATIO_REGS; i++) {
+               reg = readl(emif_phy_status++);
+               writel(reg, emif_ext_phy_ctrl_reg++);
+               writel(reg, emif_ext_phy_ctrl_reg++);
+       }
+
+       /* Update PHY_REG_FIFO_WE_SLAVE_RATIO */
+       emif_ext_phy_ctrl_reg = (u32 *)&emif->emif_ddr_ext_phy_ctrl_2;
+       for (i = 0; i < PHY_FIFO_WE_SLAVE_RATIO_REGS; i++) {
+               reg = readl(emif_phy_status++);
+               writel(reg, emif_ext_phy_ctrl_reg++);
+               writel(reg, emif_ext_phy_ctrl_reg++);
+       }
+
+       /* Update PHY_REG_WR_DQ/DQS_SLAVE_RATIO */
+       emif_ext_phy_ctrl_reg = (u32 *)&emif->emif_ddr_ext_phy_ctrl_12;
+       for (i = 0; i < PHY_REG_WR_DQ_SLAVE_RATIO_REGS; i++) {
+               reg = readl(emif_phy_status++);
+               writel(reg, emif_ext_phy_ctrl_reg++);
+               writel(reg, emif_ext_phy_ctrl_reg++);
+       }
+
+       /* Disable 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);
+       writel(0x0, &emif->emif_rd_wr_lvl_rmp_ctl);
+}
+
+static void dra7_ddr3_leveling(u32 base, const struct emif_regs *regs)
+{
+       struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
+
+       /* Clear Error Status */
+       clrsetbits_le32(&emif->emif_ddr_ext_phy_ctrl_36,
+                       EMIF_REG_PHY_FIFO_WE_IN_MISALINED_CLR,
+                       EMIF_REG_PHY_FIFO_WE_IN_MISALINED_CLR);
+
+       clrsetbits_le32(&emif->emif_ddr_ext_phy_ctrl_36_shdw,
+                       EMIF_REG_PHY_FIFO_WE_IN_MISALINED_CLR,
+                       EMIF_REG_PHY_FIFO_WE_IN_MISALINED_CLR);
+
+       /* Disable refreshed before leveling */
+       clrsetbits_le32(&emif->emif_sdram_ref_ctrl, EMIF_REG_INITREF_DIS_MASK,
+                       EMIF_REG_INITREF_DIS_MASK);
+
+       /* Start Full leveling */
+       writel(DDR3_FULL_LVL, &emif->emif_rd_wr_lvl_ctl);
+
+       __udelay(300);
+
+       /* Check for leveling timeout */
+       if (readl(&emif->emif_status) & EMIF_REG_LEVELING_TO_MASK) {
+               printf("Leveling timeout on EMIF%d\n", emif_num(base));
+               return;
+       }
+
+       /* Enable refreshes after leveling */
+       clrbits_le32(&emif->emif_sdram_ref_ctrl, EMIF_REG_INITREF_DIS_MASK);
+
+       debug("HW leveling success\n");
+       /*
+        * Update slave ratios in EXT_PHY_CTRLx registers
+        * as per HW leveling output
+        */
+       update_hwleveling_output(base, regs);
+}
+
+static void dra7_ddr3_init(u32 base, const struct emif_regs *regs)
+{
+       struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
+
+       if (warm_reset())
+               emif_reset_phy(base);
+       do_ext_phy_settings(base, regs);
+
+       writel(regs->ref_ctrl | EMIF_REG_INITREF_DIS_MASK,
+              &emif->emif_sdram_ref_ctrl);
+       /* 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(EMIF_L3_CONFIG_VAL_SYS_10_MPU_5_LL_0, &emif->emif_l3_config);
+       writel(regs->read_idle_ctrl, &emif->emif_read_idlectrl);
+       writel(regs->zq_config, &emif->emif_zq_config);
+       writel(regs->temp_alert_config, &emif->emif_temp_alert_config);
+       writel(regs->emif_rd_wr_lvl_rmp_ctl, &emif->emif_rd_wr_lvl_rmp_ctl);
+       writel(regs->emif_rd_wr_lvl_ctl, &emif->emif_rd_wr_lvl_ctl);
+
+       writel(regs->emif_ddr_phy_ctlr_1_init, &emif->emif_ddr_phy_ctrl_1);
+       writel(regs->emif_rd_wr_exec_thresh, &emif->emif_rd_wr_exec_thresh);
+
+       writel(regs->ref_ctrl, &emif->emif_sdram_ref_ctrl);
+
+       writel(regs->sdram_config2, &emif->emif_lpddr2_nvm_config);
+       writel(regs->sdram_config_init, &emif->emif_sdram_config);
+
+       __udelay(1000);
+
+       writel(regs->ref_ctrl_final, &emif->emif_sdram_ref_ctrl);
+
+       if (regs->emif_rd_wr_lvl_rmp_ctl & EMIF_REG_RDWRLVL_EN_MASK)
+               dra7_ddr3_leveling(base, regs);
+}
+
+static void omap5_ddr3_init(u32 base, const struct emif_regs *regs)
 {
        struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
 
+       writel(regs->ref_ctrl, &emif->emif_sdram_ref_ctrl);
+       writel(regs->sdram_config_init, &emif->emif_sdram_config);
        /*
         * 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->sdram_config_init, &emif->emif_sdram_config);
-
        writel(regs->emif_ddr_phy_ctlr_1_init, &emif->emif_ddr_phy_ctrl_1);
 
        /* Update timing registers */
@@ -282,15 +376,22 @@ static void ddr3_init(u32 base, const struct emif_regs *regs)
        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);
 
+       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);
+       omap5_ddr3_leveling(base, regs);
+}
 
-       ddr3_leveling(base, regs);
+static void ddr3_init(u32 base, const struct emif_regs *regs)
+{
+       if (is_omap54xx())
+               omap5_ddr3_init(base, regs);
+       else
+               dra7_ddr3_init(base, regs);
 }
 
 #ifndef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS
@@ -655,20 +756,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 */
@@ -1040,13 +1148,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
@@ -1066,12 +1170,19 @@ static void do_sdram_init(u32 base)
         * Changing the timing registers in EMIF can happen(going from one
         * OPP to another)
         */
-       if (!(in_sdram || warm_reset())) {
-               if (emif_sdram_type() == EMIF_SDRAM_TYPE_LPDDR2)
+       if (!in_sdram && (!warm_reset() || is_dra7xx())) {
+               if (emif_sdram_type(regs->sdram_config) ==
+                   EMIF_SDRAM_TYPE_LPDDR2)
                        lpddr2_init(base, regs);
                else
                        ddr3_init(base, regs);
        }
+       if (warm_reset() && (emif_sdram_type(regs->sdram_config) ==
+           EMIF_SDRAM_TYPE_DDR3) && !is_dra7xx()) {
+               set_lpmode_selfrefresh(base);
+               emif_reset_phy(base);
+               omap5_ddr3_leveling(base, regs);
+       }
 
        /* Write to the shadow registers */
        emif_update_timings(base, regs);
@@ -1108,8 +1219,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)
@@ -1172,6 +1283,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 =
@@ -1220,13 +1334,50 @@ void dmm_init(u32 base)
                        emif1_enabled = 1;
                        emif2_enabled = 1;
                        break;
-               } else if (valid == 1) {
+               }
+
+               if (valid == 1)
                        emif1_enabled = 1;
-               } else if (valid == 2) {
+
+               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);
 }
 
 /*
@@ -1249,7 +1400,8 @@ void dmm_init(u32 base)
 void sdram_init(void)
 {
        u32 in_sdram, size_prog, size_detect;
-       u32 sdram_type = emif_sdram_type();
+       struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
+       u32 sdram_type = emif_sdram_type(emif->emif_sdram_config);
 
        debug(">>sdram_init()\n");
 
@@ -1259,10 +1411,10 @@ void sdram_init(void)
        in_sdram = running_from_sdram();
        debug("in_sdram = %d\n", in_sdram);
 
-       if (!(in_sdram || warm_reset())) {
-               if (sdram_type == EMIF_SDRAM_TYPE_LPDDR2)
+       if (!in_sdram) {
+               if ((sdram_type == EMIF_SDRAM_TYPE_LPDDR2) && !warm_reset())
                        bypass_dpll((*prcm)->cm_clkmode_dpll_core);
-               else
+               else if (sdram_type == EMIF_SDRAM_TYPE_DDR3)
                        writel(CM_DLL_CTRL_NO_OVERRIDE, (*prcm)->cm_dll_ctrl);
        }
 
@@ -1304,5 +1456,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");
 }