summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--arch/arm/include/asm/arch-fsl-layerscape/config.h22
-rw-r--r--arch/arm/include/asm/arch-fsl-layerscape/immap_lsch2.h3
-rw-r--r--arch/arm/include/asm/arch-fsl-layerscape/soc.h1
6 files changed, 150 insertions, 6 deletions
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
index 79e2dd66b0..dce1689e00 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 c10ccf9063..f289172c6c 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 04a2598006..62efa9097e 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
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/config.h b/arch/arm/include/asm/arch-fsl-layerscape/config.h
index 045825eb97..8c426af47e 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/config.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/config.h
@@ -163,6 +163,28 @@
/* Generic Interrupt Controller Definitions */
#define GICD_BASE 0x01401000
#define GICC_BASE 0x01402000
+#define GICH_BASE 0x01404000
+#define GICV_BASE 0x01406000
+#define GICD_SIZE 0x1000
+#define GICC_SIZE 0x2000
+#define GICH_SIZE 0x2000
+#define GICV_SIZE 0x2000
+#ifdef CONFIG_HAS_FEATURE_GIC64K_ALIGN
+#define GICD_BASE_64K 0x01410000
+#define GICC_BASE_64K 0x01420000
+#define GICH_BASE_64K 0x01440000
+#define GICV_BASE_64K 0x01460000
+#define GICD_SIZE_64K 0x10000
+#define GICC_SIZE_64K 0x20000
+#define GICH_SIZE_64K 0x20000
+#define GICV_SIZE_64K 0x20000
+#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_MAX_NUM_OF_SEC 1
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 6ace3daf01..8ad199f60a 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch2.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch2.h
@@ -361,7 +361,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;
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/soc.h b/arch/arm/include/asm/arch-fsl-layerscape/soc.h
index 9bafa6ddfd..426fe8ef86 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/soc.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/soc.h
@@ -59,6 +59,7 @@ struct cpu_type {
#define SVR_MAJ(svr) (((svr) >> 4) & 0xf)
#define SVR_MIN(svr) (((svr) >> 0) & 0xf)
+#define SVR_REV(svr) (((svr) >> 0) & 0xff)
#define SVR_SOC_VER(svr) (((svr) >> 8) & SVR_WO_E)
#define IS_E_PROCESSOR(svr) (!((svr >> 8) & 0x1))
#define IS_SVR_REV(svr, maj, min) \