[U-Boot] [PATCH v4 1/2] armv8/ls1043a: fixup GIC offset according to SVR and SCFG_GIC400_ALIGN[GIC_ADDR_BIT]
Wenbin Song
wenbin.song at nxp.com
Wed Oct 26 12:39:45 CEST 2016
Hi: york
Best Regards
Wenbin Song
> -----Original Message-----
> From: york sun
> Sent: Wednesday, October 26, 2016 4:35 AM
> To: Wenbin Song <wenbin.song at nxp.com>; albert.u.boot at aribaud.net;
> Mingkai Hu <mingkai.hu at nxp.com>; u-boot at lists.denx.de
> Subject: Re: [PATCH v4 1/2] armv8/ls1043a: fixup GIC offset according to SVR
> and SCFG_GIC400_ALIGN[GIC_ADDR_BIT]
>
> >
> > Overriding the weekly smp_kick_all_cpus, the new impletment is able to
> > detect GIC offset.
>
> I think you meant "weak" here. :)
[wenbin] sorry, this is my carelessness.
>
> >
> > The default GIC offset in kernel device tree is using 64K alignment,
> > it need to be fixed if 4K alignment is detected.
>
> The "default" offset in device tree is also created by us, isn't it? I am not against
> you fixing it. Don't you want to check the alignment first? If the device tree has
> 4K alignment but you run on rev 1.1, do you want to use 64K alignment?
[wenbin] Yes, I will modify them.
>
> >
> > +
> > + if (val == REV1_1) {
>
> This is problematic. How about for future SoCs, or other than LS1043A?
> Can we just check GIC_ADDR_BIT?
>
[wenbin] it is not clear about the future revise ,including whether has the new revise, whether the new revise supports GIC 4K alignment and how to detect it.
So I could only suppose the future revise is as same as rev1.1.
Therefore, I will modify it to " if (val != REV1_0) {" in next version.
> > + val = scfg_in32(&scfg->gic_align) & (0x01 << GIC_ADDR_BIT);
> > + if (!val)
> > + return;
> > + }
> > +
> > + offset = fdt_subnode_offset(blob, 0, "interrupt-controller at 1400000");
> > + if (offset < 0) {
> > + printf("WARNING: fdt_subnode_offset can't find
> node %s: %s\n",
> > + "interrupt-controller at 1400000", fdt_strerror(offset));
> > + return;
> > + }
> > +
> > + reg[0] = cpu_to_fdt64(GICD_BASE_4K);
> > + reg[1] = cpu_to_fdt64(GICD_SIZE_4K);
> > + reg[2] = cpu_to_fdt64(GICC_BASE_4K);
> > + reg[3] = cpu_to_fdt64(GICC_SIZE_4K);
> > + reg[4] = cpu_to_fdt64(GICH_BASE_4K);
> > + reg[5] = cpu_to_fdt64(GICH_SIZE_4K);
> > + reg[6] = cpu_to_fdt64(GICV_BASE_4K);
> > + reg[7] = cpu_to_fdt64(GICV_SIZE_4K);
> > +
> > + err = fdt_setprop(blob, offset, "reg", reg, sizeof(reg));
> > + if (err < 0) {
> > + printf("WARNING: fdt_setprop can't set %s from
> node %s: %s\n",
> > + "reg", "interrupt-controller at 1400000",
> > + fdt_strerror(err));
> > + return;
> > + }
> > +
> > + return;
> > +}
> > +#endif
> > +
> > void ft_cpu_setup(void *blob, bd_t *bd) { #ifdef CONFIG_FSL_LSCH2
> > @@ -170,4 +216,7 @@ void ft_cpu_setup(void *blob, bd_t *bd) #endif
> > fsl_fdt_disable_usb(blob);
> >
> > +#ifdef CONFIG_HAS_FEATURE_GIC4K_ALIGN
> > + fdt_fixup_gic(blob);
> > +#endif
> > }
> > diff --git a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
> > b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
> > index 5d0b7a4..e2b8698 100644
> > --- a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
> > +++ b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
> > @@ -14,6 +14,48 @@
> > #include <asm/arch/mp.h>
> > #endif
> >
> > +#ifdef CONFIG_HAS_FEATURE_GIC4K_ALIGN
> > +
> > +/* fixup GIC offset
> > +* For LS1043a rev1.0, GIC base address align with 4k.
> > +* For LS1043a rev1.1, if DCFG_GIC400_ALIGN[GIC_ADDR_BIT]
> > +* is set, GIC base address align with 4K, or else align
> > +* with 64k.
> > +* output:
> > +* x0: the base address of GICD
> > +* x1: the base address of GICC
> > +*/
> > +ENTRY(fix_gic_offset)
> > + ldr x0, =GICD_BASE
> > + ldr x1, =GICC_BASE
> > + ldr x3, =DCFG_CCSR_SVR
> > + ldr w3, [x3]
> > + rev w3, w3
> > + ands w3, w3, #0xff
> > + cmp w3, #REV1_0
> > + b.eq 1f
> > + ldr x3, =SCFG_GIC400_ALIGN
> > + ldr w3, [x3]
> > + rev w3, w3
> > + tbnz w3, #GIC_ADDR_BIT, 1f
> > + ret
> > +1:
> > + ldr x0, =GICD_BASE_4K
> > + ldr x1, =GICC_BASE_4K
> > + ret
> > +ENDPROC(fix_gic_offset)
>
> The more I read it, the more I think the function name should be called
> get_gic_offset. You are not fixing it, the return value is the correct gic offset.
[wenbin] ok, it will be modified
>
> > +
> > +ENTRY(smp_kick_all_cpus)
> > + /* Kick secondary cpus up by SGI 0 interrupt */
> > + mov x29, lr /* Save LR */
> > + bl fix_gic_offset
> > + bl gic_kick_secondary_cpus
> > + mov lr, x29 /* Restore LR */
> > + ret
> > +ENDPROC(smp_kick_all_cpus)
>
> Another way to do this is to implement a weak get_gic_offset function in
> start.S to return GICD_BASE. You can implement another function here to
> return correct offset. If you want to replace smp_kick_all_cpus, you may want
> to keep the #if condition to check CONFIG_GICV2 or CONFIG_GICV3, in case
> we need to debug without GIC.
[wenbin] hi, Could you explain what's the mean of "debug without GIC" ?
The HAS_FEATURE_GIC4K_ALIGN is a feature(or, to be more exact, it is a bug for ls1043a rev1.0 silicon ) only belonging to ls1043a.
So if ARCH_LS1043A is selected , the CONFIG_GICV2 will be selected, too.
>
> > +
> > +#endif
> > +
> > ENTRY(lowlevel_init)
> > mov x29, lr /* Save LR */
> >
> > @@ -105,15 +147,23 @@ ENTRY(lowlevel_init)
> > /* Initialize GIC Secure Bank Status */
> > #if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
> > branch_if_slave x0, 1f
> > +#ifdef CONFIG_HAS_FEATURE_GIC4K_ALIGN
> > + bl fix_gic_offset
> > +#else
> > ldr x0, =GICD_BASE
> > +#endif
>
> If you use get_gic_offset, you can get rid of this #ifdef.
[Wenbin] I will modify the get_gic_offset as a general function for fsl-layerscape.
>
> > bl gic_init_secure
> > 1:
> > #ifdef CONFIG_GICV3
> > ldr x0, =GICR_BASE
> > bl gic_init_secure_percpu
> > #elif defined(CONFIG_GICV2)
> > +#ifdef CONFIG_HAS_FEATURE_GIC4K_ALIGN
> > +#define GICD_BASE_4K 0x01401000
> > +#define GICC_BASE_4K 0x01402000
> > +#define GICH_BASE_4K 0x01404000
> > +#define GICV_BASE_4K 0x01406000
>
> Are you using space instead of tab here?
[wenbin] ok, it will be modified.
>
> > +#define GICD_SIZE_4K 0x1000
> > +#define GICC_SIZE_4K 0x2000
> > +#define GICH_SIZE_4K 0x2000
> > +#define GICV_SIZE_4K 0x2000
> > +#endif
>
> This is a bit odd. You have rev 1.0 first, which uses 4K alignment. Yet
> you have kernel device tree using 64K alignment. How did it work before?
>
> Now you have rev 1.1, you make 64K as default, and replace it with 4K if
> a bit is set, or rev 1.0 SoC is detected. You are not changing anything
> actually, but to return the correct offset for the three situations,
> i.e. rev 1.0 SoC, rev 1.1 SoC with the bit cleared, rev 1.1 SoC with bit
> set.
>
> The only "fix" part in this patch is to fixup device tree. I suggest you
> read the device tree to determine which alignment you have there, and
> update accordingly, for both 4K and 64K alignment. I don't think you
> presumption of 64K will stand.
>
[Wenbin]
Yes, I will modify them.
> If GIC_ADDR_BIT is always set for SoCs with 4K alignment, you can get
> rid of the Kconfig option.
[Wenbin]
The GIC_ADDR_BIT is set or cleaned by PBI command. It is added on rev1.1 silicon.
> York
More information about the U-Boot
mailing list