ARM: DRA7: DDR3: Add support for HW leveling
authorLokesh Vutla <lokeshvutla@ti.com>
Wed, 3 Jun 2015 09:13:21 +0000 (14:43 +0530)
committerTom Rini <trini@konsulko.com>
Fri, 12 Jun 2015 16:43:06 +0000 (12:43 -0400)
DRA7 EMIF supports Full leveling for DDR3.
Adding support for the Full leveling sequence.

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
Reviewed-by: Tom Rini <trini@konsulko.com>
arch/arm/cpu/armv7/omap-common/emif-common.c
arch/arm/cpu/armv7/omap5/sdram.c
arch/arm/include/asm/emif.h
board/ti/beagle_x15/board.c

index c01a98f71958e67df5674f4330d463ffa1512a32..3ee4695ea31755486be60441c00417e676fbfccb 100644 (file)
@@ -242,13 +242,122 @@ static void omap5_ddr3_leveling(u32 base, const struct emif_regs *regs)
               __udelay(130);
 }
 
-static void ddr3_leveling(u32 base, const struct emif_regs *regs)
+static void update_hwleveling_output(u32 base, const struct emif_regs *regs)
 {
-       if (is_omap54xx())
-               omap5_ddr3_leveling(base, 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 ddr3_init(u32 base, const struct emif_regs *regs)
+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_SHIFT,
+                       EMIF_REG_INITREF_DIS_SHIFT);
+
+       /* 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_SHIFT);
+
+       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;
 
@@ -269,25 +378,20 @@ static void ddr3_init(u32 base, const struct emif_regs *regs)
 
        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->ref_ctrl_final, &emif->emif_sdram_ref_ctrl);
-               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);
-       }
+       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
@@ -1075,7 +1179,7 @@ static void do_sdram_init(u32 base)
        if (warm_reset() && (emif_sdram_type() == EMIF_SDRAM_TYPE_DDR3)) {
                set_lpmode_selfrefresh(base);
                emif_reset_phy(base);
-               ddr3_leveling(base, regs);
+               omap5_ddr3_leveling(base, regs);
        }
 
        /* Write to the shadow registers */
index 5f8daa1ee1e7a749f9de90c47857a9f29a39a8d8..2e2385286c3d8dda71088254bd5d24f2a25eec11 100644 (file)
@@ -421,8 +421,14 @@ const u32 ddr3_ext_phy_ctrl_const_base_es2[] = {
        0x0
 };
 
+/* Ext phy ctrl 1-35 regs */
 const u32
 dra_ddr3_ext_phy_ctrl_const_base_es1_emif1[] = {
+       0x10040100,
+       0x00910091,
+       0x00950095,
+       0x009B009B,
+       0x009E009E,
        0x00980098,
        0x00340034,
        0x00350035,
@@ -441,7 +447,7 @@ dra_ddr3_ext_phy_ctrl_const_base_es1_emif1[] = {
        0x00500050,
        0x00000000,
        0x00600020,
-       0x40010080,
+       0x40011080,
        0x08102040,
        0x0,
        0x0,
@@ -450,8 +456,14 @@ dra_ddr3_ext_phy_ctrl_const_base_es1_emif1[] = {
        0x0
 };
 
+/* Ext phy ctrl 1-35 regs */
 const u32
 dra_ddr3_ext_phy_ctrl_const_base_es1_emif2[] = {
+       0x10040100,
+       0x00910091,
+       0x00950095,
+       0x009B009B,
+       0x009E009E,
        0x00980098,
        0x00330033,
        0x00330033,
@@ -470,7 +482,7 @@ dra_ddr3_ext_phy_ctrl_const_base_es1_emif2[] = {
        0x00500050,
        0x00000000,
        0x00600020,
-       0x40010080,
+       0x40011080,
        0x08102040,
        0x0,
        0x0,
@@ -479,8 +491,14 @@ dra_ddr3_ext_phy_ctrl_const_base_es1_emif2[] = {
        0x0
 };
 
+/* Ext phy ctrl 1-35 regs */
 const u32
 dra_ddr3_ext_phy_ctrl_const_base_666MHz[] = {
+       0x10040100,
+       0x00A400A4,
+       0x00A900A9,
+       0x00B000B0,
+       0x00B000B0,
        0x00A400A4,
        0x00390039,
        0x00320032,
@@ -562,7 +580,7 @@ void get_lpddr2_mr_regs(const struct lpddr2_mr_regs **regs)
        *regs = &mr_regs;
 }
 
-void do_ext_phy_settings(u32 base, const struct emif_regs *regs)
+static void do_ext_phy_settings_omap5(u32 base, const struct emif_regs *regs)
 {
        u32 *ext_phy_ctrl_base = 0;
        u32 *emif_ext_phy_ctrl_base = 0;
@@ -601,6 +619,58 @@ void do_ext_phy_settings(u32 base, const struct emif_regs *regs)
        }
 }
 
+static void do_ext_phy_settings_dra7(u32 base, const struct emif_regs *regs)
+{
+       struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
+       u32 *emif_ext_phy_ctrl_base = 0;
+       u32 emif_nr;
+       const u32 *ext_phy_ctrl_const_regs;
+       u32 i, hw_leveling, size;
+
+       emif_nr = (base == EMIF1_BASE) ? 1 : 2;
+
+       hw_leveling = regs->emif_rd_wr_lvl_rmp_ctl >> EMIF_REG_RDWRLVL_EN_SHIFT;
+
+       emif_ext_phy_ctrl_base = (u32 *)&(emif->emif_ddr_ext_phy_ctrl_1);
+
+       emif_get_ext_phy_ctrl_const_regs(emif_nr,
+                                        &ext_phy_ctrl_const_regs, &size);
+
+       writel(ext_phy_ctrl_const_regs[0], &emif_ext_phy_ctrl_base[0]);
+       writel(ext_phy_ctrl_const_regs[0], &emif_ext_phy_ctrl_base[1]);
+
+       if (!hw_leveling) {
+               /*
+                * Copy the predefined PHY register values
+                * in case of sw leveling
+                */
+               for (i = 1; i < 25; i++) {
+                       writel(ext_phy_ctrl_const_regs[i],
+                              &emif_ext_phy_ctrl_base[i * 2]);
+                       writel(ext_phy_ctrl_const_regs[i],
+                              &emif_ext_phy_ctrl_base[i * 2 + 1]);
+               }
+       } else {
+               /*
+                * Write the init value for HW levling to occur
+                */
+               for (i = 21; i < 35; i++) {
+                       writel(ext_phy_ctrl_const_regs[i],
+                              &emif_ext_phy_ctrl_base[i * 2]);
+                       writel(ext_phy_ctrl_const_regs[i],
+                              &emif_ext_phy_ctrl_base[i * 2 + 1]);
+               }
+       }
+}
+
+void do_ext_phy_settings(u32 base, const struct emif_regs *regs)
+{
+       if (is_omap54xx())
+               do_ext_phy_settings_omap5(base, regs);
+       else
+               do_ext_phy_settings_dra7(base, regs);
+}
+
 #ifndef CONFIG_SYS_DEFAULT_LPDDR2_TIMINGS
 static const struct lpddr2_ac_timings timings_jedec_532_mhz = {
        .max_freq       = 532000000,
index 7a545ea01a7c3f661867696f9c88c80fd3386dae..a97d2fd4eade83e3bdcccb9ffa81d2841d55adf7 100644 (file)
@@ -44,6 +44,8 @@
 #define EMIF_REG_DUAL_CLK_MODE_MASK                    (1 << 30)
 #define EMIF_REG_FAST_INIT_SHIFT                       29
 #define EMIF_REG_FAST_INIT_MASK                        (1 << 29)
+#define EMIF_REG_LEVLING_TO_SHIFT              4
+#define EMIF_REG_LEVELING_TO_MASK              (7 << 4)
 #define EMIF_REG_PHY_DLL_READY_SHIFT           2
 #define EMIF_REG_PHY_DLL_READY_MASK                    (1 << 2)
 
 #define EMIF_REG_RDWRLVLINC_RMP_WIN_SHIFT      0
 #define EMIF_REG_RDWRLVLINC_RMP_WIN_MASK       (0x1FFF << 0)
 
+/* EMIF_PHY_CTRL_36 */
+#define EMIF_REG_PHY_FIFO_WE_IN_MISALINED_CLR  (1 << 8)
+
+#define PHY_RDDQS_RATIO_REGS           5
+#define PHY_FIFO_WE_SLAVE_RATIO_REGS   5
+#define PHY_REG_WR_DQ_SLAVE_RATIO_REGS 10
+
 /*Leveling Fields */
 #define DDR3_WR_LVL_INT                0x73
 #define DDR3_RD_LVL_INT                0x33
index ffcd53185bf270d0faeb133f9c83054231254379..b32d0909c4552c905839faa61d027363e2a44255 100644 (file)
@@ -68,7 +68,13 @@ static const struct emif_regs beagle_x15_emif1_ddr3_532mhz_emif_regs = {
        .emif_rd_wr_exec_thresh = 0x00000305
 };
 
+/* Ext phy ctrl regs 1-35 */
 static const u32 beagle_x15_emif1_ddr3_ext_phy_ctrl_const_regs[] = {
+       0x10040100,
+       0x00740074,
+       0x00780078,
+       0x007c007c,
+       0x007b007b,
        0x00800080,
        0x00360036,
        0x00340034,
@@ -90,7 +96,7 @@ static const u32 beagle_x15_emif1_ddr3_ext_phy_ctrl_const_regs[] = {
 
        0x00000000,
        0x00600020,
-       0x40010080,
+       0x40011080,
        0x08102040,
 
        0x00400040,
@@ -126,6 +132,11 @@ static const struct emif_regs beagle_x15_emif2_ddr3_532mhz_emif_regs = {
 };
 
 static const u32 beagle_x15_emif2_ddr3_ext_phy_ctrl_const_regs[] = {
+       0x10040100,
+       0x00820082,
+       0x008b008b,
+       0x00800080,
+       0x007e007e,
        0x00800080,
        0x00370037,
        0x00390039,
@@ -145,7 +156,7 @@ static const u32 beagle_x15_emif2_ddr3_ext_phy_ctrl_const_regs[] = {
 
        0x00000000,
        0x00600020,
-       0x40010080,
+       0x40011080,
        0x08102040,
 
        0x00400040,