[PATCH] sunxi: dram: h6: fix the unreliability related to the DDR3 sequence
patrick9876 at free.fr
patrick9876 at free.fr
Mon Jan 22 23:12:18 CET 2024
From: Patrick Lerda <patrick9876 at free.fr>
Indeed, the DDR3 has a non-zero probability to not be properly
initialized. This could be the PLL that is not locked or anything else.
When this happens and the code tests the correct board configuration,
the proper board configuration is not set. The board could end with
half the expected memory size, or u-boot could stall.
This change adds a loop to execute the DDR3 sequence again until the
stable state is reached.
My H6 TX6 board was prone to this issue. Once fixed with this change,
the same board can now handle 10000+ consecutive reboots properly.
Fixes: ec9cdaaa13d ("sunxi: dram: h6: Improve DDR3 config detection")
Signed-off-by: Patrick Lerda <patrick9876 at free.fr>
---
arch/arm/mach-sunxi/dram_sun50i_h6.c | 207 ++++++++++++++-------------
1 file changed, 111 insertions(+), 96 deletions(-)
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h6.c b/arch/arm/mach-sunxi/dram_sun50i_h6.c
index 62bc2a0231..462adb1c9e 100644
--- a/arch/arm/mach-sunxi/dram_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/dram_sun50i_h6.c
@@ -420,116 +420,131 @@ static bool mctl_channel_init(struct dram_para *para)
(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
struct sunxi_mctl_phy_reg * const mctl_phy =
(struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
- int i;
+ int i, j = 0;
u32 val;
- setbits_le32(&mctl_ctl->dfiupd[0], BIT(31) | BIT(30));
- setbits_le32(&mctl_ctl->zqctl[0], BIT(31) | BIT(30));
- writel(0x2f05, &mctl_ctl->sched[0]);
- setbits_le32(&mctl_ctl->rfshctl3, BIT(0));
- setbits_le32(&mctl_ctl->dfimisc, BIT(0));
- setbits_le32(&mctl_ctl->unk_0x00c, BIT(8));
- clrsetbits_le32(&mctl_phy->pgcr[1], 0x180, 0xc0);
- /* TODO: non-LPDDR3 types */
- clrsetbits_le32(&mctl_phy->pgcr[2], GENMASK(17, 0), ns_to_t(7800));
- clrbits_le32(&mctl_phy->pgcr[6], BIT(0));
- clrsetbits_le32(&mctl_phy->dxccr, 0xee0, 0x220);
- /* TODO: VT compensation */
- clrsetbits_le32(&mctl_phy->dsgcr, BIT(0), 0x440060);
- clrbits_le32(&mctl_phy->vtcr[1], BIT(1));
-
- for (i = 0; i < 4; i++)
- clrsetbits_le32(&mctl_phy->dx[i].gcr[0], 0xe00, 0x800);
- for (i = 0; i < 4; i++)
- clrsetbits_le32(&mctl_phy->dx[i].gcr[2], 0xffff, 0x5555);
- for (i = 0; i < 4; i++)
- clrsetbits_le32(&mctl_phy->dx[i].gcr[3], 0x3030, 0x1010);
-
- udelay(100);
+ do {
+ setbits_le32(&mctl_ctl->dfiupd[0], BIT(31) | BIT(30));
+ setbits_le32(&mctl_ctl->zqctl[0], BIT(31) | BIT(30));
+ writel(0x2f05, &mctl_ctl->sched[0]);
+ setbits_le32(&mctl_ctl->rfshctl3, BIT(0));
+ setbits_le32(&mctl_ctl->dfimisc, BIT(0));
+ setbits_le32(&mctl_ctl->unk_0x00c, BIT(8));
+ clrsetbits_le32(&mctl_phy->pgcr[1], 0x180, 0xc0);
+ /* TODO: non-LPDDR3 types */
+ clrsetbits_le32(&mctl_phy->pgcr[2], GENMASK(17, 0),
+ ns_to_t(7800));
+ clrbits_le32(&mctl_phy->pgcr[6], BIT(0));
+ clrsetbits_le32(&mctl_phy->dxccr, 0xee0, 0x220);
+ /* TODO: VT compensation */
+ clrsetbits_le32(&mctl_phy->dsgcr, BIT(0), 0x440060);
+ clrbits_le32(&mctl_phy->vtcr[1], BIT(1));
- if (para->ranks == 2)
- setbits_le32(&mctl_phy->dtcr[1], 0x30000);
- else
- clrsetbits_le32(&mctl_phy->dtcr[1], 0x30000, 0x10000);
+ for (i = 0; i < 4; i++)
+ clrsetbits_le32(&mctl_phy->dx[i].gcr[0], 0xe00, 0x800);
+ for (i = 0; i < 4; i++)
+ clrsetbits_le32(&mctl_phy->dx[i].gcr[2], 0xffff,
+ 0x5555);
+ for (i = 0; i < 4; i++)
+ clrsetbits_le32(&mctl_phy->dx[i].gcr[3], 0x3030,
+ 0x1010);
- if (sunxi_dram_is_lpddr(para->type))
- clrbits_le32(&mctl_phy->dtcr[1], BIT(1));
- if (para->ranks == 2) {
- writel(0x00010001, &mctl_phy->rankidr);
- writel(0x20000, &mctl_phy->odtcr);
- } else {
- writel(0x0, &mctl_phy->rankidr);
- writel(0x10000, &mctl_phy->odtcr);
- }
+ udelay(100);
- /* set bits [3:0] to 1? 0 not valid in ZynqMP d/s */
- if (para->type == SUNXI_DRAM_TYPE_LPDDR3)
- clrsetbits_le32(&mctl_phy->dtcr[0], 0xF0000000, 0x10000040);
- else
- clrsetbits_le32(&mctl_phy->dtcr[0], 0xF0000000, 0x10000000);
- if (para->clk <= 792) {
- if (para->clk <= 672) {
- if (para->clk <= 600)
- val = 0x300;
- else
- val = 0x400;
+ if (para->ranks == 2)
+ setbits_le32(&mctl_phy->dtcr[1], 0x30000);
+ else
+ clrsetbits_le32(&mctl_phy->dtcr[1], 0x30000, 0x10000);
+
+ if (sunxi_dram_is_lpddr(para->type))
+ clrbits_le32(&mctl_phy->dtcr[1], BIT(1));
+ if (para->ranks == 2) {
+ writel(0x00010001, &mctl_phy->rankidr);
+ writel(0x20000, &mctl_phy->odtcr);
} else {
- val = 0x500;
+ writel(0x0, &mctl_phy->rankidr);
+ writel(0x10000, &mctl_phy->odtcr);
}
- } else {
- val = 0x600;
- }
- /* FIXME: NOT REVIEWED YET */
- clrsetbits_le32(&mctl_phy->zq[0].zqcr, 0x700, val);
- clrsetbits_le32(&mctl_phy->zq[0].zqpr[0], 0xff,
- CONFIG_DRAM_ZQ & 0xff);
- clrbits_le32(&mctl_phy->zq[0].zqor[0], 0xfffff);
- setbits_le32(&mctl_phy->zq[0].zqor[0], (CONFIG_DRAM_ZQ >> 8) & 0xff);
- setbits_le32(&mctl_phy->zq[0].zqor[0], (CONFIG_DRAM_ZQ & 0xf00) - 0x100);
- setbits_le32(&mctl_phy->zq[0].zqor[0], (CONFIG_DRAM_ZQ & 0xff00) << 4);
- clrbits_le32(&mctl_phy->zq[1].zqpr[0], 0xfffff);
- setbits_le32(&mctl_phy->zq[1].zqpr[0], (CONFIG_DRAM_ZQ >> 16) & 0xff);
- setbits_le32(&mctl_phy->zq[1].zqpr[0], ((CONFIG_DRAM_ZQ >> 8) & 0xf00) - 0x100);
- setbits_le32(&mctl_phy->zq[1].zqpr[0], (CONFIG_DRAM_ZQ & 0xff0000) >> 4);
- if (para->type == SUNXI_DRAM_TYPE_LPDDR3) {
- for (i = 1; i < 14; i++)
- writel(0x06060606, &mctl_phy->acbdlr[i]);
- }
- val = PIR_ZCAL | PIR_DCAL | PIR_PHYRST | PIR_DRAMINIT | PIR_QSGATE |
- PIR_RDDSKW | PIR_WRDSKW | PIR_RDEYE | PIR_WREYE;
- if (para->type == SUNXI_DRAM_TYPE_DDR3)
- val |= PIR_DRAMRST | PIR_WL;
- mctl_phy_pir_init(val);
+ /* set bits [3:0] to 1? 0 not valid in ZynqMP d/s */
+ if (para->type == SUNXI_DRAM_TYPE_LPDDR3)
+ clrsetbits_le32(&mctl_phy->dtcr[0], 0xF0000000,
+ 0x10000040);
+ else
+ clrsetbits_le32(&mctl_phy->dtcr[0], 0xF0000000,
+ 0x10000000);
+ if (para->clk <= 792) {
+ if (para->clk <= 672) {
+ if (para->clk <= 600)
+ val = 0x300;
+ else
+ val = 0x400;
+ } else {
+ val = 0x500;
+ }
+ } else {
+ val = 0x600;
+ }
+ /* FIXME: NOT REVIEWED YET */
+ clrsetbits_le32(&mctl_phy->zq[0].zqcr, 0x700, val);
+ clrsetbits_le32(&mctl_phy->zq[0].zqpr[0], 0xff,
+ CONFIG_DRAM_ZQ & 0xff);
+ clrbits_le32(&mctl_phy->zq[0].zqor[0], 0xfffff);
+ setbits_le32(&mctl_phy->zq[0].zqor[0],
+ (CONFIG_DRAM_ZQ >> 8) & 0xff);
+ setbits_le32(&mctl_phy->zq[0].zqor[0],
+ (CONFIG_DRAM_ZQ & 0xf00) - 0x100);
+ setbits_le32(&mctl_phy->zq[0].zqor[0], (CONFIG_DRAM_ZQ & 0xff00)
+ << 4);
+ clrbits_le32(&mctl_phy->zq[1].zqpr[0], 0xfffff);
+ setbits_le32(&mctl_phy->zq[1].zqpr[0],
+ (CONFIG_DRAM_ZQ >> 16) & 0xff);
+ setbits_le32(&mctl_phy->zq[1].zqpr[0],
+ ((CONFIG_DRAM_ZQ >> 8) & 0xf00) - 0x100);
+ setbits_le32(&mctl_phy->zq[1].zqpr[0],
+ (CONFIG_DRAM_ZQ & 0xff0000) >> 4);
+ if (para->type == SUNXI_DRAM_TYPE_LPDDR3) {
+ for (i = 1; i < 14; i++)
+ writel(0x06060606, &mctl_phy->acbdlr[i]);
+ }
- /* TODO: DDR4 types ? */
- for (i = 0; i < 4; i++)
- writel(0x00000909, &mctl_phy->dx[i].gcr[5]);
+ val = PIR_ZCAL | PIR_DCAL | PIR_PHYRST | PIR_DRAMINIT |
+ PIR_QSGATE | PIR_RDDSKW | PIR_WRDSKW | PIR_RDEYE |
+ PIR_WREYE;
+ if (para->type == SUNXI_DRAM_TYPE_DDR3)
+ val |= PIR_DRAMRST | PIR_WL;
+ mctl_phy_pir_init(val);
- for (i = 0; i < 4; i++) {
- if (IS_ENABLED(CONFIG_DRAM_ODT_EN))
- val = 0x0;
- else
- val = 0xaaaa;
- clrsetbits_le32(&mctl_phy->dx[i].gcr[2], 0xffff, val);
+ /* TODO: DDR4 types ? */
+ for (i = 0; i < 4; i++)
+ writel(0x00000909, &mctl_phy->dx[i].gcr[5]);
- if (IS_ENABLED(CONFIG_DRAM_ODT_EN))
- val = 0x0;
- else
- val = 0x2020;
- clrsetbits_le32(&mctl_phy->dx[i].gcr[3], 0x3030, val);
- }
+ for (i = 0; i < 4; i++) {
+ if (IS_ENABLED(CONFIG_DRAM_ODT_EN))
+ val = 0x0;
+ else
+ val = 0xaaaa;
+ clrsetbits_le32(&mctl_phy->dx[i].gcr[2], 0xffff, val);
- mctl_bit_delay_set(para);
- udelay(1);
+ if (IS_ENABLED(CONFIG_DRAM_ODT_EN))
+ val = 0x0;
+ else
+ val = 0x2020;
+ clrsetbits_le32(&mctl_phy->dx[i].gcr[3], 0x3030, val);
+ }
- setbits_le32(&mctl_phy->pgcr[6], BIT(0));
- clrbits_le32(&mctl_phy->pgcr[6], 0xfff8);
- for (i = 0; i < 4; i++)
- clrbits_le32(&mctl_phy->dx[i].gcr[3], ~0x3ffff);
- udelay(10);
+ mctl_bit_delay_set(para);
+ udelay(1);
+
+ setbits_le32(&mctl_phy->pgcr[6], BIT(0));
+ clrbits_le32(&mctl_phy->pgcr[6], 0xfff8);
+ for (i = 0; i < 4; i++)
+ clrbits_le32(&mctl_phy->dx[i].gcr[3], ~0x3ffff);
+ udelay(10);
+ val = readl(&mctl_phy->pgsr[0]) & 0xff00000;
+ } while (val && j++ < 64);
- if (readl(&mctl_phy->pgsr[0]) & 0xff00000) {
+ if (val) {
/* Oops! There's something wrong! */
debug("PLL = %x\n", readl(0x3001010));
debug("DRAM PHY PGSR0 = %x\n", readl(&mctl_phy->pgsr[0]));
--
2.43.0
More information about the U-Boot
mailing list