[U-Boot] [PATCH] sunxi: Fix H3 DRAM impedance calibration on rev. A chips

Hans de Goede hdegoede at redhat.com
Mon Oct 10 10:09:38 CEST 2016


Hi,

On 21-09-16 20:08, Jens Kuske wrote:
> 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 <jenskuske at gmail.com>

Thank you for the patch. I've applied this patch to my local
tree and it will be part of the pull-request I'm about to send
out.

Regards,

Hans




> ---
>
> 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)
>


More information about the U-Boot mailing list