Skip to content

Commit

Permalink
ARM: DRA7/OMAP5: EMIF: Add workaround for bug 0039
Browse files Browse the repository at this point in the history
When core power domain hits oswr, then DDR3 memories does not come back
while resuming. This is because when EMIF registers are lost, then the
controller takes care of copying the values from the shadow registers.
If the shadow registers are not updated with the right values, then this
results in incorrect settings while resuming. So updating the shadow registers
with the corresponding status registers here during the boot.

Signed-off-by: Sricharan R <[email protected]>
  • Loading branch information
Sricharanti authored and trini committed Dec 4, 2013
1 parent 6c70935 commit 54d022e
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 1 deletion.
42 changes: 42 additions & 0 deletions arch/arm/cpu/armv7/omap-common/emif-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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");
}
5 changes: 5 additions & 0 deletions arch/arm/cpu/armv7/omap4/sdram_elpida.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
68 changes: 68 additions & 0 deletions arch/arm/cpu/armv7/omap5/sdram.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
10 changes: 9 additions & 1 deletion arch/arm/include/asm/emif.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 (;;); })
Expand Down Expand Up @@ -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

0 comments on commit 54d022e

Please sign in to comment.