diff options
| -rw-r--r-- | arch/arm/cpu/armv7/omap-common/emif-common.c | 42 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/omap4/sdram_elpida.c | 5 | ||||
| -rw-r--r-- | arch/arm/cpu/armv7/omap5/sdram.c | 68 | ||||
| -rw-r--r-- | arch/arm/include/asm/emif.h | 10 | 
4 files changed, 124 insertions, 1 deletions
| diff --git a/arch/arm/cpu/armv7/omap-common/emif-common.c b/arch/arm/cpu/armv7/omap-common/emif-common.c index dc1ea1d96..5a3f2858c 100644 --- a/arch/arm/cpu/armv7/omap-common/emif-common.c +++ b/arch/arm/cpu/armv7/omap-common/emif-common.c @@ -1286,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: @@ -1361,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");  } diff --git a/arch/arm/cpu/armv7/omap4/sdram_elpida.c b/arch/arm/cpu/armv7/omap4/sdram_elpida.c index e4c831637..811e7764c 100644 --- a/arch/arm/cpu/armv7/omap4/sdram_elpida.c +++ b/arch/arm/cpu/armv7/omap4/sdram_elpida.c @@ -321,3 +321,8 @@ void get_lpddr2_mr_regs(const struct lpddr2_mr_regs **regs)  {  	*regs = &mr_regs;  } + +__weak const struct read_write_regs *get_bug_regs(u32 *iterations) +{ +	return 0; +} diff --git a/arch/arm/cpu/armv7/omap5/sdram.c b/arch/arm/cpu/armv7/omap5/sdram.c index 2aae3efb7..2e1870609 100644 --- a/arch/arm/cpu/armv7/omap5/sdram.c +++ b/arch/arm/cpu/armv7/omap5/sdram.c @@ -569,6 +569,74 @@ static const struct lpddr2_device_timings dev_4G_S4_timings = {  	.min_tck	= &min_tck,  }; +/* + * List of status registers to be controlled back to control registers + * after initial leveling + * readreg, writereg + */ +const struct read_write_regs omap5_bug_00339_regs[] = { +	{ 8,  5 }, +	{ 9,  6 }, +	{ 10, 7 }, +	{ 14, 8 }, +	{ 15, 9 }, +	{ 16, 10 }, +	{ 11, 2 }, +	{ 12, 3 }, +	{ 13, 4 }, +	{ 17, 11 }, +	{ 18, 12 }, +	{ 19, 13 }, +}; + +const struct read_write_regs dra_bug_00339_regs[] = { +	{ 7,  7 }, +	{ 8,  8 }, +	{ 9,  9 }, +	{ 10, 10 }, +	{ 11, 11 }, +	{ 12, 2 }, +	{ 13, 3 }, +	{ 14, 4 }, +	{ 15, 5 }, +	{ 16, 6 }, +	{ 17, 12 }, +	{ 18, 13 }, +	{ 19, 14 }, +	{ 20, 15 }, +	{ 21, 16 }, +	{ 22, 17 }, +	{ 23, 18 }, +	{ 24, 19 }, +	{ 25, 20 }, +	{ 26, 21} +}; + +const struct read_write_regs *get_bug_regs(u32 *iterations) +{ +	const struct read_write_regs *bug_00339_regs_ptr = NULL; + +	switch (omap_revision()) { +	case OMAP5430_ES1_0: +	case OMAP5430_ES2_0: +	case OMAP5432_ES1_0: +	case OMAP5432_ES2_0: +		bug_00339_regs_ptr = omap5_bug_00339_regs; +		*iterations = sizeof(omap5_bug_00339_regs)/ +			     sizeof(omap5_bug_00339_regs[0]); +		break; +	case DRA752_ES1_0: +		bug_00339_regs_ptr = dra_bug_00339_regs; +		*iterations = sizeof(dra_bug_00339_regs)/ +			     sizeof(dra_bug_00339_regs[0]); +		break; +	default: +		printf("\n Error: UnKnown SOC"); +	} + +	return bug_00339_regs_ptr; +} +  void emif_get_device_timings_sdp(u32 emif_nr,  		const struct lpddr2_device_timings **cs0_device_timings,  		const struct lpddr2_device_timings **cs1_device_timings) diff --git a/arch/arm/include/asm/emif.h b/arch/arm/include/asm/emif.h index c12beea0c..d9d521a51 100644 --- a/arch/arm/include/asm/emif.h +++ b/arch/arm/include/asm/emif.h @@ -640,7 +640,9 @@ struct emif_reg_struct {  	u32 emif_ddr_phy_ctrl_2;  	u32 padding7[12];  	u32 emif_rd_wr_exec_thresh; -	u32 padding8[55]; +	u32 padding8[7]; +	u32 emif_ddr_phy_status[21]; +	u32 padding9[27];  	u32 emif_ddr_ext_phy_ctrl_1;  	u32 emif_ddr_ext_phy_ctrl_1_shdw;  	u32 emif_ddr_ext_phy_ctrl_2; @@ -1141,6 +1143,11 @@ struct lpddr2_mr_regs {  	s8 mr16;  }; +struct read_write_regs { +	u32 read_reg; +	u32 write_reg; +}; +  /* assert macros */  #if defined(DEBUG)  #define emif_assert(c)	({ if (!(c)) for (;;); }) @@ -1169,4 +1176,5 @@ extern u32 *const T_den;  void config_data_eye_leveling_samples(u32 emif_base);  u32 emif_sdram_type(void); +const struct read_write_regs *get_bug_regs(u32 *iterations);  #endif |