X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=arch%2Farm%2Fcpu%2Farmv7%2Fomap-common%2Femif-common.c;h=f5b22f6a783626590f06123050437e8d3ad14b21;hb=0d3f732fd2ba679b4498541f075d1b1bdbea3935;hp=88253cf8ce3e5bf1128d70f08d22bacdfddb09b4;hpb=86021143a3081bd62d85abcc48135a0babc0096a;p=platform%2Fkernel%2Fu-boot.git diff --git a/arch/arm/cpu/armv7/omap-common/emif-common.c b/arch/arm/cpu/armv7/omap-common/emif-common.c index 88253cf..f5b22f6 100644 --- a/arch/arm/cpu/armv7/omap-common/emif-common.c +++ b/arch/arm/cpu/armv7/omap-common/emif-common.c @@ -6,28 +6,12 @@ * * Aneesh V * - * 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 #include -#include +#include #include #include #include @@ -66,7 +50,6 @@ inline u32 emif_num(u32 base) return 0; } - static inline u32 get_mr(u32 base, u32 cs, u32 mr_addr) { u32 mr; @@ -110,11 +93,13 @@ void emif_reset_phy(u32 base) static void do_lpddr2_init(u32 base, u32 cs) { u32 mr_addr; + const struct lpddr2_mr_regs *mr_regs; + get_lpddr2_mr_regs(&mr_regs); /* Wait till device auto initialization is complete */ while (get_mr(base, cs, LPDDR2_MR0) & LPDDR2_MR0_DAI_MASK) ; - set_mr(base, cs, LPDDR2_MR10, MR10_ZQ_ZQINIT); + set_mr(base, cs, LPDDR2_MR10, mr_regs->mr10); /* * tZQINIT = 1 us * Enough loops assuming a maximum of 2GHz @@ -122,22 +107,18 @@ static void do_lpddr2_init(u32 base, u32 cs) sdelay(2000); - if (omap_revision() >= OMAP5430_ES1_0) - set_mr(base, cs, LPDDR2_MR1, MR1_BL_8_BT_SEQ_WRAP_EN_NWR_8); - else - set_mr(base, cs, LPDDR2_MR1, MR1_BL_8_BT_SEQ_WRAP_EN_NWR_3); - - set_mr(base, cs, LPDDR2_MR16, MR16_REF_FULL_ARRAY); + set_mr(base, cs, LPDDR2_MR1, mr_regs->mr1); + set_mr(base, cs, LPDDR2_MR16, mr_regs->mr16); /* * Enable refresh along with writing MR2 * Encoding of RL in MR2 is (RL - 2) */ mr_addr = LPDDR2_MR2 | EMIF_REG_REFRESH_EN_MASK; - set_mr(base, cs, mr_addr, RL_FINAL - 2); + set_mr(base, cs, mr_addr, mr_regs->mr2); - if (omap_revision() >= OMAP5430_ES1_0) - set_mr(base, cs, LPDDR2_MR3, 0x1); + if (mr_regs->mr3 > 0) + set_mr(base, cs, LPDDR2_MR3, mr_regs->mr3); } static void lpddr2_init(u32 base, const struct emif_regs *regs) @@ -158,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); @@ -198,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) { @@ -210,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; @@ -221,88 +202,196 @@ 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; - u32 *ext_phy_ctrl_base = 0; - u32 *emif_ext_phy_ctrl_base = 0; - u32 i = 0; + /* 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"); /* - * 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 + * Update slave ratios in EXT_PHY_CTRLx registers + * as per HW leveling output */ - writel(regs->sdram_config_init, &emif->emif_sdram_config); + update_hwleveling_output(base, regs); +} - writel(regs->emif_ddr_phy_ctlr_1_init, &emif->emif_ddr_phy_ctrl_1); +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(regs->ref_ctrl, &emif->emif_sdram_ref_ctrl); + 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); - 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); + 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); - /* 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++); - } + 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); /* - * external phy 6-24 registers do not change with - * ddr frequency + * 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 */ - 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++); - } + 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->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 @@ -667,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 */ @@ -1052,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 @@ -1078,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 (omap_revision() != OMAP5432_ES1_0) + 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); @@ -1096,9 +1195,6 @@ void emif_post_init_config(u32 base) struct emif_reg_struct *emif = (struct emif_reg_struct *)base; u32 omap_rev = omap_revision(); - if (omap_rev == OMAP5430_ES1_0) - return; - /* reset phy on ES2.0 */ if (omap_rev == OMAP4430_ES2_0) emif_reset_phy(base); @@ -1123,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) @@ -1187,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 = @@ -1206,7 +1305,7 @@ void dmm_init(u32 base) writel(lisa_map_regs->dmm_lisa_map_0, &hw_lisa_map_regs->dmm_lisa_map_0); - if (omap_revision() >= OMAP4460_ES1_0) { + if (lisa_map_regs->is_ma_present) { hw_lisa_map_regs = (struct dmm_lisa_map_regs *)MA_BASE; @@ -1235,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); } /* @@ -1264,7 +1400,8 @@ void dmm_init(u32 base) void sdram_init(void) { u32 in_sdram, size_prog, size_detect; - u32 omap_rev = omap_revision(); + 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"); @@ -1274,11 +1411,11 @@ void sdram_init(void) in_sdram = running_from_sdram(); debug("in_sdram = %d\n", in_sdram); - if (!(in_sdram || warm_reset())) { - if (omap_rev != OMAP5432_ES1_0) - bypass_dpll(&prcm->cm_clkmode_dpll_core); - else - writel(CM_DLL_CTRL_NO_OVERRIDE, &prcm->cm_dll_ctrl); + if (!in_sdram) { + if ((sdram_type == EMIF_SDRAM_TYPE_LPDDR2) && !warm_reset()) + bypass_dpll((*prcm)->cm_clkmode_dpll_core); + else if (sdram_type == EMIF_SDRAM_TYPE_DDR3) + writel(CM_DLL_CTRL_NO_OVERRIDE, (*prcm)->cm_dll_ctrl); } if (!in_sdram) @@ -1298,7 +1435,7 @@ void sdram_init(void) } /* for the shadow registers to take effect */ - if (omap_rev != OMAP5432_ES1_0) + if (sdram_type == EMIF_SDRAM_TYPE_LPDDR2) freq_update_core(); /* Do some testing after the init */ @@ -1319,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("<