diff --git a/arch/arm/cpu/armv7/omap-common/emif-common.c b/arch/arm/cpu/armv7/omap-common/emif-common.c index 389feda7166af3d0e8c39dbae072e5bd7e0c53e7..846511d03bded902feee0414028da15f88cfd123 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 @@ 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) { 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 @@ void emif_update_timings(u32 base, const struct emif_regs *regs) } } +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 @@ 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) { + 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 187e93887b673aef636fbee7fed80c946d3bdea1..2c34e48f42854ae8227b29adf2dc5f39459fd8c4 100644 --- a/arch/arm/cpu/armv7/omap4/hwinit.c +++ b/arch/arm/cpu/armv7/omap4/hwinit.c @@ -118,6 +118,11 @@ void do_io_settings(void) } #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 df0b76050db28cfadf9ba5923152177411852f5a..d0c3ff70218d9a51c2cd5d79a183a889073a61f3 100644 --- a/arch/arm/cpu/armv7/omap5/hwinit.c +++ b/arch/arm/cpu/armv7/omap5/hwinit.c @@ -35,6 +35,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -203,6 +204,20 @@ void do_io_settings(void) } #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 5d2649e121be10b3c8b9b8358ad9af9cf9c14e4a..c2ad877ab2458656229ccc6ab8475e13fdedd271 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 T_den; extern u32 *const emif_sizes; #endif - +void config_data_eye_leveling_samples(u32 emif_base); #endif