From: Patrick Lerda <patrick9...@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 <patrick9...@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

Reply via email to