summaryrefslogtreecommitdiff
path: root/arch/arm/cpu/armv8
diff options
context:
space:
mode:
authorWenbin Song <wenbin.song@nxp.com>2017-01-17 18:31:15 +0800
committerYork Sun <york.sun@nxp.com>2017-01-18 09:29:21 -0800
commitfa18ed76589a684fc9ba14b68d7b917b1bea16cf (patch)
treee04efffdb1fe39b70fb1ba88deb9c53d444b9661 /arch/arm/cpu/armv8
parent435cca167149d19a9740806f63a3f58388280507 (diff)
armv8/ls1043a: fixup GIC offset for ls1043a rev1
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. The LS1043A rev1.0 silicon only supports the CIG offset with 4K alignment. If GIC_ADDR_BIT bit is set, 4K alignment is used, or else 64K alignment is used. 64K alignment is the default setting. Overriding the weak smp_kick_all_cpus, the new impletment is able to detect GIC offset. The default GIC offset in kernel device tree is using 4K alignment, it need to be fixed if 64K alignment is detected. Signed-off-by: Wenbin Song <wenbin.song@nxp.com> Signed-off-by: Mingkai Hu <mingkai.hu@nxp.com> Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@nxp.com> Reviewed-by: York Sun <york.sun@nxp.com>
Diffstat (limited to 'arch/arm/cpu/armv8')
-rw-r--r--arch/arm/cpu/armv8/fsl-layerscape/Kconfig5
-rw-r--r--arch/arm/cpu/armv8/fsl-layerscape/fdt.c64
-rw-r--r--arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S61
3 files changed, 125 insertions, 5 deletions
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
index 79e2dd66b05..dce1689e005 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
@@ -90,6 +90,11 @@ config FSL_PCIE_COMPAT
This compatible is used to find pci controller node in Kernel DT
to complete fixup.
+config HAS_FEATURE_GIC64K_ALIGN
+ bool
+ default y if ARCH_LS1043A
+
+
menu "Layerscape PPA"
config FSL_LS_PPA
bool "FSL Layerscape PPA firmware support"
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
index c10ccf9063a..f289172c6c5 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fdt.c
@@ -133,6 +133,67 @@ void fsl_fdt_disable_usb(void *blob)
}
}
+#ifdef CONFIG_HAS_FEATURE_GIC64K_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 val;
+ struct ccsr_scfg __iomem *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
+ int align_64k = 0;
+
+ val = gur_in32(&gur->svr);
+
+ if (SVR_SOC_VER(val) != SVR_LS1043A) {
+ align_64k = 1;
+ } else if (SVR_REV(val) != REV1_0) {
+ val = scfg_in32(&scfg->gic_align) & (0x01 << GIC_ADDR_BIT);
+ if (!val)
+ align_64k = 1;
+ }
+
+ 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 64K */
+ if (align_64k) {
+ reg[0] = cpu_to_fdt64(GICD_BASE_64K);
+ reg[1] = cpu_to_fdt64(GICD_SIZE_64K);
+ reg[2] = cpu_to_fdt64(GICC_BASE_64K);
+ reg[3] = cpu_to_fdt64(GICC_SIZE_64K);
+ reg[4] = cpu_to_fdt64(GICH_BASE_64K);
+ reg[5] = cpu_to_fdt64(GICH_SIZE_64K);
+ reg[6] = cpu_to_fdt64(GICV_BASE_64K);
+ reg[7] = cpu_to_fdt64(GICV_SIZE_64K);
+ } else {
+ /* Fixup gic node align with default */
+ 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
@@ -177,4 +238,7 @@ void ft_cpu_setup(void *blob, bd_t *bd)
#endif
fsl_fdt_disable_usb(blob);
+#ifdef CONFIG_HAS_FEATURE_GIC64K_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 04a25980065..62efa9097e5 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
+++ b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
@@ -10,15 +10,66 @@
#include <linux/linkage.h>
#include <asm/gic.h>
#include <asm/macro.h>
+#include <asm/arch-fsl-layerscape/soc.h>
#ifdef CONFIG_MP
#include <asm/arch/mp.h>
#endif
#ifdef CONFIG_FSL_LSCH3
#include <asm/arch-fsl-layerscape/immap_lsch3.h>
-#include <asm/arch-fsl-layerscape/soc.h>
#endif
#include <asm/u-boot.h>
+/* 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:
+* x0: the base address of GICD
+* x1: the base address of GICC
+*/
+ENTRY(get_gic_offset)
+ ldr x0, =GICD_BASE
+#ifdef CONFIG_GICV2
+ ldr x1, =GICC_BASE
+#endif
+#ifdef CONFIG_HAS_FEATURE_GIC64K_ALIGN
+ ldr x2, =DCFG_CCSR_SVR
+ ldr w2, [x2]
+ rev w2, w2
+ mov w3, w2
+ ands w3, w3, #SVR_WO_E << 8
+ mov w4, #SVR_LS1043A << 8
+ cmp w3, w4
+ b.ne 1f
+ ands w2, w2, #0xff
+ cmp w2, #REV1_0
+ b.eq 1f
+ ldr x2, =SCFG_GIC400_ALIGN
+ ldr w2, [x2]
+ rev w2, w2
+ tbnz w2, #GIC_ADDR_BIT, 1f
+ ldr x0, =GICD_BASE_64K
+#ifdef CONFIG_GICV2
+ ldr x1, =GICC_BASE_64K
+#endif
+1:
+#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 */
@@ -130,15 +181,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
@@ -413,7 +463,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