diff options
author | Lokesh Vutla <lokeshvutla@ti.com> | 2013-12-10 15:02:22 +0530 |
---|---|---|
committer | Tom Rini <trini@ti.com> | 2013-12-18 21:14:44 -0500 |
commit | d3daba10f159cca7e9d24c6f154926a9b92c75e3 (patch) | |
tree | 34dee6df0d4914e66bc0bc9a3c652b20fc0e7eb7 /arch/arm/cpu/armv7/am33xx | |
parent | 965de8b91bddd1f5967240d1d44005719b09dd5e (diff) |
ARM: AM43xx: EPOS_EVM: Add support for LPDDR2
AM4372 EPOS EVM has 1GB LPDDR2(Part no: MT42L256M32D2LG-25 WT:A)
Adding LPDDR2 init sequence and register details for the same.
Below is the brief description of LPDDR2 init sequence:
-> Configure VTP
-> Configure DDR IO settings
-> Disable initialization and refreshes until EMIF registers are programmed.
-> Program Timing registers
-> Program PHY control and Temp alert and ZQ config registers.
-> Enable initialization and refreshes and configure SDRAM CONFIG register
-> Wait till initialization is complete and the configure MR registers.
Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
Diffstat (limited to 'arch/arm/cpu/armv7/am33xx')
-rw-r--r-- | arch/arm/cpu/armv7/am33xx/ddr.c | 117 | ||||
-rw-r--r-- | arch/arm/cpu/armv7/am33xx/emif4.c | 22 |
2 files changed, 138 insertions, 1 deletions
diff --git a/arch/arm/cpu/armv7/am33xx/ddr.c b/arch/arm/cpu/armv7/am33xx/ddr.c index 255f333b69..1abbb07c96 100644 --- a/arch/arm/cpu/armv7/am33xx/ddr.c +++ b/arch/arm/cpu/armv7/am33xx/ddr.c @@ -36,6 +36,71 @@ static struct ddr_data_regs *ddr_data_reg[2] = { static struct ddr_cmdtctrl *ioctrl_reg = { (struct ddr_cmdtctrl *)DDR_CONTROL_BASE_ADDR}; +static inline u32 get_mr(int nr, u32 cs, u32 mr_addr) +{ + u32 mr; + + mr_addr |= cs << EMIF_REG_CS_SHIFT; + writel(mr_addr, &emif_reg[nr]->emif_lpddr2_mode_reg_cfg); + + mr = readl(&emif_reg[nr]->emif_lpddr2_mode_reg_data); + debug("get_mr: EMIF1 cs %d mr %08x val 0x%x\n", cs, mr_addr, 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(int nr, u32 cs, u32 mr_addr, u32 mr_val) +{ + mr_addr |= cs << EMIF_REG_CS_SHIFT; + writel(mr_addr, &emif_reg[nr]->emif_lpddr2_mode_reg_cfg); + writel(mr_val, &emif_reg[nr]->emif_lpddr2_mode_reg_data); +} + +static void configure_mr(int nr, u32 cs) +{ + u32 mr_addr; + + while (get_mr(nr, cs, LPDDR2_MR0) & LPDDR2_MR0_DAI_MASK) + ; + set_mr(nr, cs, LPDDR2_MR10, 0x56); + + set_mr(nr, cs, LPDDR2_MR1, 0x43); + set_mr(nr, cs, LPDDR2_MR2, 0x2); + + mr_addr = LPDDR2_MR2 | EMIF_REG_REFRESH_EN_MASK; + set_mr(nr, cs, mr_addr, 0x2); +} + +/* + * Configure EMIF4D5 registers and MR registers + */ +void config_sdram_emif4d5(const struct emif_regs *regs, int nr) +{ + writel(0x0, &emif_reg[nr]->emif_pwr_mgmt_ctrl); + writel(0x0, &emif_reg[nr]->emif_pwr_mgmt_ctrl_shdw); + writel(0x1, &emif_reg[nr]->emif_iodft_tlgc); + writel(regs->zq_config, &emif_reg[nr]->emif_zq_config); + + writel(regs->temp_alert_config, &emif_reg[nr]->emif_temp_alert_config); + writel(regs->emif_rd_wr_lvl_rmp_win, + &emif_reg[nr]->emif_rd_wr_lvl_rmp_win); + writel(regs->emif_rd_wr_lvl_rmp_ctl, + &emif_reg[nr]->emif_rd_wr_lvl_rmp_ctl); + writel(regs->emif_rd_wr_lvl_ctl, &emif_reg[nr]->emif_rd_wr_lvl_ctl); + writel(regs->emif_rd_wr_exec_thresh, + &emif_reg[nr]->emif_rd_wr_exec_thresh); + + writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl); + writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config); + + configure_mr(nr, 0); + configure_mr(nr, 1); +} + /** * Configure SDRAM */ @@ -72,15 +137,67 @@ void set_sdram_timings(const struct emif_regs *regs, int nr) writel(regs->sdram_tim3, &emif_reg[nr]->emif_sdram_tim_3_shdw); } +void __weak emif_get_ext_phy_ctrl_const_regs(const u32 **regs, u32 *size) +{ +} + +/* + * Configure EXT PHY registers + */ +static void ext_phy_settings(const struct emif_regs *regs, int nr) +{ + u32 *ext_phy_ctrl_base = 0; + u32 *emif_ext_phy_ctrl_base = 0; + const u32 *ext_phy_ctrl_const_regs; + u32 i = 0; + u32 size; + + ext_phy_ctrl_base = (u32 *)&(regs->emif_ddr_ext_phy_ctrl_1); + emif_ext_phy_ctrl_base = + (u32 *)&(emif_reg[nr]->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 + */ + emif_get_ext_phy_ctrl_const_regs(&ext_phy_ctrl_const_regs, &size); + + if (!size) + return; + + for (i = 0; i < size; i++) { + writel(ext_phy_ctrl_const_regs[i], emif_ext_phy_ctrl_base++); + /* Update shadow registers */ + writel(ext_phy_ctrl_const_regs[i], emif_ext_phy_ctrl_base++); + } +} + /** * Configure DDR PHY */ void config_ddr_phy(const struct emif_regs *regs, int nr) { + /* + * disable initialization and refreshes for now until we + * finish programming EMIF regs. + */ + setbits_le32(&emif_reg[nr]->emif_sdram_ref_ctrl, + EMIF_REG_INITREF_DIS_MASK); + writel(regs->emif_ddr_phy_ctlr_1, &emif_reg[nr]->emif_ddr_phy_ctrl_1); writel(regs->emif_ddr_phy_ctlr_1, &emif_reg[nr]->emif_ddr_phy_ctrl_1_shdw); + + if (get_emif_rev((u32)emif_reg[nr]) == EMIF_4D5) + ext_phy_settings(regs, nr); } /** diff --git a/arch/arm/cpu/armv7/am33xx/emif4.c b/arch/arm/cpu/armv7/am33xx/emif4.c index adda650fe8..d28fceb75c 100644 --- a/arch/arm/cpu/armv7/am33xx/emif4.c +++ b/arch/arm/cpu/armv7/am33xx/emif4.c @@ -48,6 +48,11 @@ static struct vtp_reg *vtpreg[2] = { #ifdef CONFIG_AM33XX static struct ddr_ctrl *ddrctrl = (struct ddr_ctrl *)DDR_CTRL_ADDR; #endif +#ifdef CONFIG_AM43XX +static struct ddr_ctrl *ddrctrl = (struct ddr_ctrl *)DDR_CTRL_ADDR; +static struct cm_device_inst *cm_device = + (struct cm_device_inst *)CM_DEVICE_INST; +#endif #ifdef CONFIG_TI81XX void config_dmm(const struct dmm_lisa_map_regs *regs) @@ -104,9 +109,24 @@ void config_ddr(unsigned int pll, const struct ctrl_ioregs *ioregs, /* Set CKE to be controlled by EMIF/DDR PHY */ writel(DDR_CKE_CTRL_NORMAL, &ddrctrl->ddrckectrl); #endif +#ifdef CONFIG_AM43XX + writel(readl(&cm_device->cm_dll_ctrl) & ~0x1, &cm_device->cm_dll_ctrl); + while ((readl(&cm_device->cm_dll_ctrl) && CM_DLL_READYST) == 0) + ; + writel(0x0, &ddrctrl->ddrioctrl); + + config_io_ctrl(ioregs); + + /* Set CKE to be controlled by EMIF/DDR PHY */ + writel(DDR_CKE_CTRL_NORMAL, &ddrctrl->ddrckectrl); +#endif + /* Program EMIF instance */ config_ddr_phy(regs, nr); set_sdram_timings(regs, nr); - config_sdram(regs, nr); + if (get_emif_rev(EMIF1_BASE) == EMIF_4D5) + config_sdram_emif4d5(regs, nr); + else + config_sdram(regs, nr); } #endif |