OMAP5: EMIF: Add support for DDR3 device
In OMAP5432 EMIF controlller supports DDR3 device.
This patch adds support for ddr3 device intialization and configuration.
Initialization sequence is done as specified in JEDEC specs.
This also adds support for ddr3 leveling.
Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
diff --git a/arch/arm/cpu/armv7/omap-common/emif-common.c b/arch/arm/cpu/armv7/omap-common/emif-common.c
index 389feda..846511d 100644
--- a/arch/arm/cpu/armv7/omap-common/emif-common.c
+++ b/arch/arm/cpu/armv7/omap-common/emif-common.c
@@ -190,7 +190,7 @@
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) {
writel(EMIF_L3_CONFIG_VAL_SYS_10_MPU_5_LL_0,
&emif->emif_l3_config);
} else if (omap_revision() >= OMAP4460_ES1_0) {
@@ -202,6 +202,101 @@
}
}
+static void 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_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;
+
+ /*
+ * 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 */
+ 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);
+
+ 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);
+
+ /* 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(ddr3_ext_phy_ctrl_const_base[i],
+ emif_ext_phy_ctrl_base++);
+ /* Update shadow registers */
+ writel(ddr3_ext_phy_ctrl_const_base[i],
+ emif_ext_phy_ctrl_base++);
+ }
+
+ /* 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))
@@ -975,8 +1070,12 @@
* Changing the timing registers in EMIF can happen(going from one
* OPP to another)
*/
- if (!in_sdram)
- lpddr2_init(base, regs);
+ if (!in_sdram) {
+ if (omap_revision() != OMAP5432_ES1_0)
+ lpddr2_init(base, regs);
+ else
+ ddr3_init(base, regs);
+ }
/* Write to the shadow registers */
emif_update_timings(base, regs);
diff --git a/arch/arm/cpu/armv7/omap4/hwinit.c b/arch/arm/cpu/armv7/omap4/hwinit.c
index 187e938..2c34e48 100644
--- a/arch/arm/cpu/armv7/omap4/hwinit.c
+++ b/arch/arm/cpu/armv7/omap4/hwinit.c
@@ -118,6 +118,11 @@
}
#endif
+/* dummy fuction for omap4 */
+void config_data_eye_leveling_samples(u32 emif_base)
+{
+}
+
void init_omap_revision(void)
{
/*
diff --git a/arch/arm/cpu/armv7/omap5/hwinit.c b/arch/arm/cpu/armv7/omap5/hwinit.c
index df0b760..d0c3ff7 100644
--- a/arch/arm/cpu/armv7/omap5/hwinit.c
+++ b/arch/arm/cpu/armv7/omap5/hwinit.c
@@ -35,6 +35,7 @@
#include <asm/sizes.h>
#include <asm/utils.h>
#include <asm/arch/gpio.h>
+#include <asm/emif.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -203,6 +204,20 @@
}
#endif
+void config_data_eye_leveling_samples(u32 emif_base)
+{
+ struct omap_sys_ctrl_regs *ioregs_base =
+ (struct omap_sys_ctrl_regs *) SYSCTRL_GENERAL_CORE_BASE;
+
+ /*EMIF_SDRAM_CONFIG_EXT-Read data eye leveling no of samples =4*/
+ if (emif_base == EMIF1_BASE)
+ writel(SDRAM_CONFIG_EXT_RD_LVL_4_SAMPLES,
+ &(ioregs_base->control_emif1_sdram_config_ext));
+ else if (emif_base == EMIF2_BASE)
+ writel(SDRAM_CONFIG_EXT_RD_LVL_4_SAMPLES,
+ &(ioregs_base->control_emif2_sdram_config_ext));
+}
+
void init_omap_revision(void)
{
/*
diff --git a/arch/arm/include/asm/emif.h b/arch/arm/include/asm/emif.h
index 5d2649e..c2ad877 100644
--- a/arch/arm/include/asm/emif.h
+++ b/arch/arm/include/asm/emif.h
@@ -471,6 +471,49 @@
#define EMIF_REG_DDR_PHY_CTRL_2_SHIFT 0
#define EMIF_REG_DDR_PHY_CTRL_2_MASK (0xffffffff << 0)
+/*EMIF_READ_WRITE_LEVELING_CONTROL*/
+#define EMIF_REG_RDWRLVLFULL_START_SHIFT 31
+#define EMIF_REG_RDWRLVLFULL_START_MASK (1 << 31)
+#define EMIF_REG_RDWRLVLINC_PRE_SHIFT 24
+#define EMIF_REG_RDWRLVLINC_PRE_MASK (0x7F << 24)
+#define EMIF_REG_RDLVLINC_INT_SHIFT 16
+#define EMIF_REG_RDLVLINC_INT_MASK (0xFF << 16)
+#define EMIF_REG_RDLVLGATEINC_INT_SHIFT 8
+#define EMIF_REG_RDLVLGATEINC_INT_MASK (0xFF << 8)
+#define EMIF_REG_WRLVLINC_INT_SHIFT 0
+#define EMIF_REG_WRLVLINC_INT_MASK (0xFF << 0)
+
+/*EMIF_READ_WRITE_LEVELING_RAMP_CONTROL*/
+#define EMIF_REG_RDWRLVL_EN_SHIFT 31
+#define EMIF_REG_RDWRLVL_EN_MASK (1 << 31)
+#define EMIF_REG_RDWRLVLINC_RMP_PRE_SHIFT 24
+#define EMIF_REG_RDWRLVLINC_RMP_PRE_MASK (0x7F << 24)
+#define EMIF_REG_RDLVLINC_RMP_INT_SHIFT 16
+#define EMIF_REG_RDLVLINC_RMP_INT_MASK (0xFF << 16)
+#define EMIF_REG_RDLVLGATEINC_RMP_INT_SHIFT 8
+#define EMIF_REG_RDLVLGATEINC_RMP_INT_MASK (0xFF << 8)
+#define EMIF_REG_WRLVLINC_RMP_INT_SHIFT 0
+#define EMIF_REG_WRLVLINC_RMP_INT_MASK (0xFF << 0)
+
+/*EMIF_READ_WRITE_LEVELING_RAMP_WINDOW*/
+#define EMIF_REG_RDWRLVLINC_RMP_WIN_SHIFT 0
+#define EMIF_REG_RDWRLVLINC_RMP_WIN_MASK (0x1FFF << 0)
+
+/*Leveling Fields */
+#define DDR3_WR_LVL_INT 0x73
+#define DDR3_RD_LVL_INT 0x33
+#define DDR3_RD_LVL_GATE_INT 0x59
+#define RD_RW_LVL_INC_PRE 0x0
+#define DDR3_FULL_LVL (1 << EMIF_REG_RDWRLVL_EN_SHIFT)
+
+#define DDR3_INC_LVL ((DDR3_WR_LVL_INT << EMIF_REG_WRLVLINC_INT_SHIFT) \
+ | (DDR3_RD_LVL_GATE_INT << EMIF_REG_RDLVLGATEINC_INT_SHIFT) \
+ | (DDR3_RD_LVL_INT << EMIF_REG_RDLVLINC_RMP_INT_SHIFT) \
+ | (RD_RW_LVL_INC_PRE << EMIF_REG_RDWRLVLINC_RMP_PRE_SHIFT))
+
+#define SDRAM_CONFIG_EXT_RD_LVL_11_SAMPLES 0x0000C1A7
+#define SDRAM_CONFIG_EXT_RD_LVL_4_SAMPLES 0x000001A7
+
/* DMM */
#define DMM_BASE 0x4E000040
@@ -1104,5 +1147,5 @@
extern u32 *const emif_sizes;
#endif
-
+void config_data_eye_leveling_samples(u32 emif_base);
#endif