From b62ed03b96c3fe56282feebf5de7a73ada2014e2 Mon Sep 17 00:00:00 2001 From: ThomasKaiser Date: Wed, 21 Sep 2016 17:59:39 +0200 Subject: [PATCH] H3 Rev A impedance calibration fix --- config/sources/pine64.conf | 2 +- .../fix-h3-rev3-dram-calibration.patch | 106 ++++++++++++++++++ .../fix-h3-rev3-dram-calibration.patch | 106 ++++++++++++++++++ 3 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 patch/u-boot/u-boot-default/fix-h3-rev3-dram-calibration.patch create mode 100644 patch/u-boot/u-boot-dev/fix-h3-rev3-dram-calibration.patch diff --git a/config/sources/pine64.conf b/config/sources/pine64.conf index b3fdaf79b..88b8cdf6b 100644 --- a/config/sources/pine64.conf +++ b/config/sources/pine64.conf @@ -19,7 +19,7 @@ case $BRANCH in KERNELSOURCE='https://github.com/apritzel/linux.git' KERNELBRANCH='branch:a64-v5' KERNELDIR='linux-pine64-dev' - GOVERNOR=ondemand + GOVERNOR=schedutil UBOOT_FILES="u-boot-with-spl.bin" ;; esac diff --git a/patch/u-boot/u-boot-default/fix-h3-rev3-dram-calibration.patch b/patch/u-boot/u-boot-default/fix-h3-rev3-dram-calibration.patch new file mode 100644 index 000000000..54c51de2a --- /dev/null +++ b/patch/u-boot/u-boot-default/fix-h3-rev3-dram-calibration.patch @@ -0,0 +1,106 @@ +From f0b3ecefb7241c565b6400d2da11fc5c49b570ff Mon Sep 17 00:00:00 2001 +From: Jens Kuske +Date: Wed, 21 Sep 2016 16:08:43 +0200 +Subject: [PATCH] sunxi: Fix H3 DRAM impedance calibration on rev. A chips + +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 +--- + arch/arm/mach-sunxi/dram_sun8i_h3.c | 67 +++++++++++++++++++++++++------------ + 1 file changed, 46 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..b23a46c 100644 +--- a/arch/arm/mach-sunxi/dram_sun8i_h3.c ++++ b/arch/arm/mach-sunxi/dram_sun8i_h3.c +@@ -217,35 +217,60 @@ 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]); +- +- writel(PIR_CLRSR, &mctl_ctl->pir); +- mctl_phy_init(PIR_ZCAL); ++ 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]); + +- val = readl(&mctl_ctl->zqdr[0]) >> 24; +- zq_val[i] |= bin_to_mgray(mgray_to_bin(val) - 1) << 8; ++ 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; ++ ++ writel(0x0a0a0a0a, &mctl_ctl->zqdr[2]); ++ ++ for (i = 0; i < 6; i++) { ++ u8 zq = (CONFIG_DRAM_ZQ >> (i * 4)) & 0xf; + +- 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((zq << 20) | (zq << 16) | (zq << 12) | ++ (zq << 8) | (zq << 4) | (zq << 0), ++ &mctl_ctl->zqcr); ++ ++ 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) diff --git a/patch/u-boot/u-boot-dev/fix-h3-rev3-dram-calibration.patch b/patch/u-boot/u-boot-dev/fix-h3-rev3-dram-calibration.patch new file mode 100644 index 000000000..54c51de2a --- /dev/null +++ b/patch/u-boot/u-boot-dev/fix-h3-rev3-dram-calibration.patch @@ -0,0 +1,106 @@ +From f0b3ecefb7241c565b6400d2da11fc5c49b570ff Mon Sep 17 00:00:00 2001 +From: Jens Kuske +Date: Wed, 21 Sep 2016 16:08:43 +0200 +Subject: [PATCH] sunxi: Fix H3 DRAM impedance calibration on rev. A chips + +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 +--- + arch/arm/mach-sunxi/dram_sun8i_h3.c | 67 +++++++++++++++++++++++++------------ + 1 file changed, 46 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..b23a46c 100644 +--- a/arch/arm/mach-sunxi/dram_sun8i_h3.c ++++ b/arch/arm/mach-sunxi/dram_sun8i_h3.c +@@ -217,35 +217,60 @@ 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]); +- +- writel(PIR_CLRSR, &mctl_ctl->pir); +- mctl_phy_init(PIR_ZCAL); ++ 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]); + +- val = readl(&mctl_ctl->zqdr[0]) >> 24; +- zq_val[i] |= bin_to_mgray(mgray_to_bin(val) - 1) << 8; ++ 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; ++ ++ writel(0x0a0a0a0a, &mctl_ctl->zqdr[2]); ++ ++ for (i = 0; i < 6; i++) { ++ u8 zq = (CONFIG_DRAM_ZQ >> (i * 4)) & 0xf; + +- 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((zq << 20) | (zq << 16) | (zq << 12) | ++ (zq << 8) | (zq << 4) | (zq << 0), ++ &mctl_ctl->zqcr); ++ ++ 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)