diff options
Diffstat (limited to 'arch/arm/cpu/armv7/omap-common/emif-common.c')
| -rw-r--r-- | arch/arm/cpu/armv7/omap-common/emif-common.c | 142 | 
1 files changed, 113 insertions, 29 deletions
| diff --git a/arch/arm/cpu/armv7/omap-common/emif-common.c b/arch/arm/cpu/armv7/omap-common/emif-common.c index b0e1caa35..5a3f2858c 100644 --- a/arch/arm/cpu/armv7/omap-common/emif-common.c +++ b/arch/arm/cpu/armv7/omap-common/emif-common.c @@ -206,7 +206,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; @@ -217,47 +217,86 @@ 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_sw_leveling(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; -	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); +	u32 fifo_reg; + +	fifo_reg = readl(&emif->emif_ddr_fifo_misaligned_clear_1); +	writel(fifo_reg | 0x00000100, +	       &emif->emif_ddr_fifo_misaligned_clear_1); + +	fifo_reg = readl(&emif->emif_ddr_fifo_misaligned_clear_2); +	writel(fifo_reg | 0x00000100, +	       &emif->emif_ddr_fifo_misaligned_clear_2); + +	/* 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); -	writel(regs->emif_rd_wr_lvl_ctl, &emif->emif_rd_wr_lvl_ctl); -	writel(regs->sdram_config, &emif->emif_sdram_config); +	/* +	 * Disable leveling. This is because if leveling is kept +	 * enabled, then PHY triggers a false leveling during +	 * EMIF-idle scenario which results in wrong delay +	 * values getting updated. After this the EMIF becomes +	 * unaccessible. So disable it after the first time +	 */ +	writel(0x0, &emif->emif_rd_wr_lvl_rmp_ctl); +} + +static void ddr3_leveling(u32 base, const struct emif_regs *regs) +{ +	if (is_omap54xx()) +		omap5_ddr3_leveling(base, regs); +	else +		dra7_ddr3_leveling(base, regs);  }  static void ddr3_init(u32 base, const struct emif_regs *regs) @@ -270,9 +309,6 @@ static void ddr3_init(u32 base, const struct emif_regs *regs)  	 * defined, contents of mode Registers must be fully initialized.  	 * H/W takes care of this initialization  	 */ -	writel(regs->sdram_config2, &emif->emif_lpddr2_nvm_config); -	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 */ @@ -283,15 +319,24 @@ static void ddr3_init(u32 base, const struct emif_regs *regs)  	writel(regs->ref_ctrl, &emif->emif_sdram_ref_ctrl);  	writel(regs->read_idle_ctrl, &emif->emif_read_idlectrl); -	do_ext_phy_settings(base, regs); +	/* +	 * The same sequence should work on OMAP5432 as well. But strange that +	 * it is not working +	 */ +	if (omap_revision() == DRA752_ES1_0) { +		do_ext_phy_settings(base, regs); +		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); +	}  	/* enable leveling */  	writel(regs->emif_rd_wr_lvl_rmp_ctl, &emif->emif_rd_wr_lvl_rmp_ctl); -	if (omap_revision() == DRA752_ES1_0) -		ddr3_sw_leveling(base, regs); -	else -		ddr3_leveling(base, regs); +	ddr3_leveling(base, regs);  }  #ifndef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS @@ -1079,10 +1124,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); -		if (omap_revision() == DRA752_ES1_0) -			ddr3_sw_leveling(base, regs); -		else -			ddr3_leveling(base, regs); +		ddr3_leveling(base, regs);  	}  	/* Write to the shadow registers */ @@ -1244,6 +1286,42 @@ void dmm_init(u32 base)  } +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); +} +  /*   * SDRAM initialization:   * SDRAM initialization has two parts: @@ -1319,5 +1397,11 @@ void sdram_init(void)  			debug("get_ram_size() successful");  	} +	if (sdram_type == EMIF_SDRAM_TYPE_DDR3 && +	    (!in_sdram && !warm_reset())) { +		do_bug0039_workaround(EMIF1_BASE); +		do_bug0039_workaround(EMIF2_BASE); +	} +  	debug("<<sdram_init()\n");  } |