[U-Boot] [linux-sunxi] [PATCH] sunxi: fix SID read on H3

Siarhei Siamashka siarhei.siamashka at gmail.com
Sat Dec 24 00:55:54 CET 2016


On Tue, 20 Dec 2016 02:03:36 +0800
Icenowy Zheng <icenowy at aosc.xyz> wrote:

> H3 SID controller has some bug, which makes the initial SID value at
> SUNXI_SID_BASE wrong when boot.
> 
> Change the SID retrieve code to call the SID Controller directly on H3,
> which can get the correct value, and also fix the SID value at
> SUNXI_SID_BASE, so that it can be used by further operations.
> 
> Signed-off-by: Icenowy Zheng <icenowy at aosc.xyz>
> ---
>  arch/arm/include/asm/arch-sunxi/cpu_sun4i.h |  1 +
>  arch/arm/mach-sunxi/cpu_info.c              | 44 +++++++++++++++++++++++++++++
>  2 files changed, 45 insertions(+)
> 
> diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
> index 7232f6d927..3c852224e6 100644
> --- a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
> +++ b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
> @@ -97,6 +97,7 @@
>  #if defined(CONFIG_MACH_SUN8I_A83T) || defined(CONFIG_MACH_SUN8I_H3) || \
>  defined(CONFIG_MACH_SUN50I)
>  /* SID address space starts at 0x01c1400, but e-fuse is at offset 0x200 */
> +#define SUNXI_SIDC_BASE			0x01c14000
>  #define SUNXI_SID_BASE			0x01c14200
>  #else
>  #define SUNXI_SID_BASE			0x01c23800
> diff --git a/arch/arm/mach-sunxi/cpu_info.c b/arch/arm/mach-sunxi/cpu_info.c
> index 76b6719d99..f1f6fd5ba4 100644
> --- a/arch/arm/mach-sunxi/cpu_info.c
> +++ b/arch/arm/mach-sunxi/cpu_info.c
> @@ -99,10 +99,54 @@ int print_cpuinfo(void)
>  }
>  #endif
>  
> +#ifdef CONFIG_MACH_SUN8I_H3
> +
> +#define SIDC_PRCTL 0x40
> +#define SIDC_RDKEY 0x60
> +
> +#define SIDC_OP_LOCK 0xAC
> +
> +uint32_t sun8i_efuse_read(uint32_t offset)
> +{
> +	uint32_t reg_val;
> +
> +	reg_val = readl(SUNXI_SIDC_BASE + SIDC_PRCTL);
> +	reg_val &= ~(((0x1ff) << 16) | 0x3);
> +	reg_val |= (offset << 16);
> +	writel(reg_val, SUNXI_SIDC_BASE + SIDC_PRCTL);

Normally clrsetbits_le32() is used for this kind of code in U-Boot.

> +
> +	reg_val &= ~(((0xff) << 8) | 0x3);
> +	reg_val |= (SIDC_OP_LOCK << 8) | 0x2;
> +	writel(reg_val, SUNXI_SIDC_BASE + SIDC_PRCTL);
> +
> +	while (readl(SUNXI_SIDC_BASE + SIDC_PRCTL) & 0x2);
> +
> +	reg_val &= ~(((0x1ff) << 16) | ((0xff) << 8) | 0x3);
> +	writel(reg_val, SUNXI_SIDC_BASE + SIDC_PRCTL);

Same here.

> +
> +	reg_val = readl(SUNXI_SIDC_BASE + SIDC_RDKEY);
> +	return reg_val;
> +}
> +#endif
> +
>  int sunxi_get_sid(unsigned int *sid)
>  {
>  #ifdef CONFIG_AXP221_POWER
>  	return axp_get_sid(sid);
> +#elif defined CONFIG_MACH_SUN8I_H3
> +	/*
> +	 * H3 SID controller has a bug, which makes the initial value of
> +	 * SUNXI_SID_BASE at boot wrong.
> +	 * Read the value directly from SID controller, in order to get
> +	 * the correct value, and also refresh the wrong value at
> +	 * SUNXI_SID_BASE.
> +	 */
> +	int i;
> +
> +	for (i = 0; i< 4; i++)
> +		sid[i] = sun8i_efuse_read(i * 4);
> +
> +	return 0;
>  #elif defined SUNXI_SID_BASE
>  	int i;
>  

Thanks for this workaround. This problem has buggered some people
since a while ago. It's good that you took time to investigate and
fix it.

-- 
Best regards,
Siarhei Siamashka


More information about the U-Boot mailing list