[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