H3 seems to have a silicon bug breaking the impedance calibration.
This is currently worked around in software by multiple steps
combining the results to replace the wrong values.

Revision A chips need a different workaround, which is present in
the vendor bootloader too, but got overlooked in lack of
information and affected boards till now.
This commit adds a simplified version without correction factor,
which would be 1.00 for all known boards anyway.

Signed-off-by: Jens Kuske <jensku...@gmail.com>
---

Hi,

This has been tested by an Armbian user:
http://forum.armbian.com/index.php/topic/872-beelink-x2-with-armbian-possible/?p=16061

It looks like only few boards have revision A chips, probably only
non-development boards, otherwise we would have found this earlier.
The idea that these are different chip revision is based on:
https://github.com/igorpecovnik/linux/blob/sun8i/arch/arm/mach-sunxi/sunxi-chip.c#L341

Regards,
Jens

---
 arch/arm/mach-sunxi/dram_sun8i_h3.c | 64 +++++++++++++++++++++++++------------
 1 file changed, 43 insertions(+), 21 deletions(-)

diff --git a/arch/arm/mach-sunxi/dram_sun8i_h3.c 
b/arch/arm/mach-sunxi/dram_sun8i_h3.c
index 2020d75..b08b8e6 100644
--- a/arch/arm/mach-sunxi/dram_sun8i_h3.c
+++ b/arch/arm/mach-sunxi/dram_sun8i_h3.c
@@ -217,35 +217,57 @@ static void mctl_zq_calibration(struct dram_para *para)
        struct sunxi_mctl_ctl_reg * const mctl_ctl =
                        (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
 
-       int i;
-       u16 zq_val[6];
-       u8 val;
+       if ((readl(SUNXI_SRAMC_BASE + 0x24) & 0xff) == 0 &&
+           (readl(SUNXI_SRAMC_BASE + 0xf0) & 0x1) == 0) {
+               u32 reg_val;
 
-       writel(0x0a0a0a0a, &mctl_ctl->zqdr[2]);
-
-       for (i = 0; i < 6; i++) {
-               u8 zq = (CONFIG_DRAM_ZQ >> (i * 4)) & 0xf;
-
-               writel((zq << 20) | (zq << 16) | (zq << 12) |
-                               (zq << 8) | (zq << 4) | (zq << 0),
-                               &mctl_ctl->zqcr);
+               clrsetbits_le32(&mctl_ctl->zqcr, 0xffff,
+                               CONFIG_DRAM_ZQ & 0xffff);
 
                writel(PIR_CLRSR, &mctl_ctl->pir);
                mctl_phy_init(PIR_ZCAL);
 
-               zq_val[i] = readl(&mctl_ctl->zqdr[0]) & 0xff;
-               writel(REPEAT_BYTE(zq_val[i]), &mctl_ctl->zqdr[2]);
+               reg_val = readl(&mctl_ctl->zqdr[0]);
+               reg_val &= (0x1f << 16) | (0x1f << 0);
+               reg_val |= reg_val << 8;
+               writel(reg_val, &mctl_ctl->zqdr[0]);
 
-               writel(PIR_CLRSR, &mctl_ctl->pir);
-               mctl_phy_init(PIR_ZCAL);
+               reg_val = readl(&mctl_ctl->zqdr[1]);
+               reg_val &= (0x1f << 16) | (0x1f << 0);
+               reg_val |= reg_val << 8;
+               writel(reg_val, &mctl_ctl->zqdr[1]);
+               writel(reg_val, &mctl_ctl->zqdr[2]);
+       } else {
+               int i;
+               u16 zq_val[6];
+               u8 val;
 
-               val = readl(&mctl_ctl->zqdr[0]) >> 24;
-               zq_val[i] |= bin_to_mgray(mgray_to_bin(val) - 1) << 8;
-       }
+               writel(0x0a0a0a0a, &mctl_ctl->zqdr[2]);
+
+               for (i = 0; i < 6; i++) {
+                       u8 zq = (CONFIG_DRAM_ZQ >> (i * 4)) & 0xf;
+
+                       writel((zq << 20) | (zq << 16) | (zq << 12) |
+                                       (zq << 8) | (zq << 4) | (zq << 0),
+                                       &mctl_ctl->zqcr);
 
-       writel((zq_val[1] << 16) | zq_val[0], &mctl_ctl->zqdr[0]);
-       writel((zq_val[3] << 16) | zq_val[2], &mctl_ctl->zqdr[1]);
-       writel((zq_val[5] << 16) | zq_val[4], &mctl_ctl->zqdr[2]);
+                       writel(PIR_CLRSR, &mctl_ctl->pir);
+                       mctl_phy_init(PIR_ZCAL);
+
+                       zq_val[i] = readl(&mctl_ctl->zqdr[0]) & 0xff;
+                       writel(REPEAT_BYTE(zq_val[i]), &mctl_ctl->zqdr[2]);
+
+                       writel(PIR_CLRSR, &mctl_ctl->pir);
+                       mctl_phy_init(PIR_ZCAL);
+
+                       val = readl(&mctl_ctl->zqdr[0]) >> 24;
+                       zq_val[i] |= bin_to_mgray(mgray_to_bin(val) - 1) << 8;
+               }
+
+               writel((zq_val[1] << 16) | zq_val[0], &mctl_ctl->zqdr[0]);
+               writel((zq_val[3] << 16) | zq_val[2], &mctl_ctl->zqdr[1]);
+               writel((zq_val[5] << 16) | zq_val[4], &mctl_ctl->zqdr[2]);
+       }
 }
 
 static void mctl_set_cr(struct dram_para *para)
-- 
2.10.0

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to