The LS1043A rev1.1 silicon supports two types of GIC offset: 4K alignment
and 64K alignment. The bit SCFG_GIC400_ALIGN[GIC_ADDR_BIT] is used to choose
which offset will be used. If GIC_ADDR_BIT bit is set, 4K alignment is used,
or else 64K alignment is used. The rev1.0 silicon only supports the CIG offset
with 4K alignment.

GIC offset is decided by SVR and GIC_ADDR_BIT bit.

Overriding the weak smp_kick_all_cpus, the new impletment is able to detect
GIC offset.

Signed-off-by: Wenbin Song <wenbin.s...@nxp.com>
Signed-off-by: Mingkai Hu <mingkai...@nxp.com>
---
Changes in v5:
        Replace fix_gic_off with get_gic_off.
        Add #if condition to check CONFIG_GICV2 and CONFIG_GICV3 on 
smp_kick_all_cpus.
        Fixup gic node with 64K alignment when running on rev1.1 with 
GIC_ADDR_BIT cleared. 
---
 arch/arm/cpu/armv8/fsl-layerscape/Kconfig          |  4 ++
 arch/arm/cpu/armv8/fsl-layerscape/fdt.c            | 62 ++++++++++++++++++++++
 arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S       | 57 ++++++++++++++++++--
 arch/arm/include/asm/arch-fsl-layerscape/config.h  | 26 ++++++++-
 .../include/asm/arch-fsl-layerscape/immap_lsch2.h  |  3 +-
 5 files changed, 145 insertions(+), 7 deletions(-)

diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig 
b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
index 94ec8d5..f415868 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
@@ -135,4 +135,8 @@ config SYS_FSL_DDR4
        help
          Enable Freescale DDR4 controller.
 
+config HAS_FEATURE_GIC4K_ALIGN
+       bool
+       default y if ARCH_LS1043A
+
 endmenu
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c 
b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
index 1a8321b..e90adb0 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
@@ -126,6 +126,65 @@ void fsl_fdt_disable_usb(void *blob)
        }
 }
 
+#ifdef CONFIG_HAS_FEATURE_GIC4K_ALIGN
+static void fdt_fixup_gic(void *blob)
+{
+       int offset, err;
+       u64 reg[8];
+       struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
+       unsigned int rev;
+       struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
+       int align_4k = 1;
+
+       rev = gur_in32(&gur->svr) & 0xff;
+
+       if (rev > REV1_0) {
+               rev = scfg_in32(&scfg->gic_align) & (0x01 << GIC_ADDR_BIT);
+               if (!rev)
+                       align_4k = 0;
+       }
+
+       offset = fdt_subnode_offset(blob, 0, "interrupt-controller@1400000");
+       if (offset < 0) {
+               printf("WARNING: fdt_subnode_offset can't find node %s: %s\n",
+                      "interrupt-controller@1400000", fdt_strerror(offset));
+               return;
+       }
+
+       /* Fixup gic node align with 4K */
+       if (align_4k) {
+               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);
+       } else {
+       /* Fixup gic node align with 64K */
+               reg[0] = cpu_to_fdt64(GICD_BASE);
+               reg[1] = cpu_to_fdt64(GICD_SIZE);
+               reg[2] = cpu_to_fdt64(GICC_BASE);
+               reg[3] = cpu_to_fdt64(GICC_SIZE);
+               reg[4] = cpu_to_fdt64(GICH_BASE);
+               reg[5] = cpu_to_fdt64(GICH_SIZE);
+               reg[6] = cpu_to_fdt64(GICV_BASE);
+               reg[7] = cpu_to_fdt64(GICV_SIZE);
+       }
+
+       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@1400000",
+                      fdt_strerror(err));
+               return;
+       }
+
+       return;
+}
+#endif
+
 void ft_cpu_setup(void *blob, bd_t *bd)
 {
 #ifdef CONFIG_FSL_LSCH2
@@ -170,4 +229,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..d50096c 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
+++ b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
@@ -14,6 +14,55 @@
 #include <asm/arch/mp.h>
 #endif
 
+
+/* Get 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:
+*   for GICv2:
+*      x0-> the base address of GICD
+*      x1-> the base address of GICC
+*   for GICv3:
+*       x0-> the base address of GICD
+*/
+ENTRY(get_gic_offset)
+       ldr     x0, =GICD_BASE
+#ifdef CONFIG_GICV2
+       ldr     x1, =GICC_BASE
+#endif
+#ifdef CONFIG_HAS_FEATURE_GIC4K_ALIGN
+       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
+#endif
+       ret
+ENDPROC(get_gic_offset)
+
+ENTRY(smp_kick_all_cpus)
+       /* Kick secondary cpus up by SGI 0 interrupt */
+#if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
+       mov     x29, lr                 /* Save LR */
+       bl      get_gic_offset
+       bl      gic_kick_secondary_cpus
+       mov     lr, x29                 /* Restore LR */
+#endif
+       ret
+ENDPROC(smp_kick_all_cpus)
+
+
 ENTRY(lowlevel_init)
        mov     x29, lr                 /* Save LR */
 
@@ -105,15 +154,14 @@ ENTRY(lowlevel_init)
        /* Initialize GIC Secure Bank Status */
 #if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
        branch_if_slave x0, 1f
-       ldr     x0, =GICD_BASE
+       bl      get_gic_offset
        bl      gic_init_secure
 1:
 #ifdef CONFIG_GICV3
        ldr     x0, =GICR_BASE
        bl      gic_init_secure_percpu
 #elif defined(CONFIG_GICV2)
-       ldr     x0, =GICD_BASE
-       ldr     x1, =GICC_BASE
+       bl      get_gic_offset
        bl      gic_init_secure_percpu
 #endif
 #endif
@@ -335,7 +383,8 @@ ENTRY(secondary_boot_func)
 #if defined(CONFIG_GICV3)
        gic_wait_for_interrupt_m x0
 #elif defined(CONFIG_GICV2)
-        ldr     x0, =GICC_BASE
+       bl      get_gic_offset
+       mov     x0, x1
         gic_wait_for_interrupt_m x0, w1
 #endif
 
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/config.h 
b/arch/arm/include/asm/arch-fsl-layerscape/config.h
index 4201e0f..35f67dd 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/config.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/config.h
@@ -172,8 +172,30 @@
 #define SMMU_BASE              0x09000000
 
 /* Generic Interrupt Controller Definitions */
-#define GICD_BASE              0x01401000
-#define GICC_BASE              0x01402000
+#define GICD_BASE              0x01410000
+#define GICC_BASE              0x01420000
+#define GICH_BASE              0x01440000
+#define GICV_BASE              0x01460000
+#define GICD_SIZE              0x10000
+#define GICC_SIZE              0x20000
+#define GICH_SIZE              0x20000
+#define GICV_SIZE              0x20000
+#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
+#define GICD_SIZE_4K           0x1000
+#define GICC_SIZE_4K           0x2000
+#define GICH_SIZE_4K           0x2000
+#define GICV_SIZE_4K           0x2000
+#endif
+
+#define DCFG_CCSR_SVR          0x1ee00a4
+#define REV1_0                 0x10
+#define REV1_1                 0x11
+#define GIC_ADDR_BIT           31
+#define SCFG_GIC400_ALIGN      0x1570188
 
 #define CONFIG_SYS_FSL_ERRATUM_A008850
 #define CONFIG_SYS_FSL_ERRATUM_A009663
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch2.h 
b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch2.h
index d88543d..1dfef53 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch2.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch2.h
@@ -359,7 +359,8 @@ struct ccsr_scfg {
        u32 qspi_cfg;
        u8 res_160[0x180-0x160];
        u32 dmamcr;
-       u8 res_184[0x18c-0x184];
+       u8 res_184[0x188-0x184];
+       u32 gic_align;
        u32 debug_icid;
        u8 res_190[0x1a4-0x190];
        u32 snpcnfgcr;
-- 
2.1.0.27.g96db324

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to