ARM: uniphier: add PH1-LD20 SoC support
This is the first ARMv8 SoC from Socionext Inc.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
diff --git a/arch/arm/mach-uniphier/arm64/Makefile b/arch/arm/mach-uniphier/arm64/Makefile
new file mode 100644
index 0000000..5ed030a
--- /dev/null
+++ b/arch/arm/mach-uniphier/arm64/Makefile
@@ -0,0 +1,10 @@
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+ifdef CONFIG_SPL_BUILD
+obj-y += timer.o
+else
+obj-y += mem_map.o smp.o smp_kick_cpus.o
+obj-$(CONFIG_ARCH_UNIPHIER_LD20) += arm-cci500.o
+endif
diff --git a/arch/arm/mach-uniphier/arm64/arm-cci500.c b/arch/arm/mach-uniphier/arm64/arm-cci500.c
new file mode 100644
index 0000000..607f96a
--- /dev/null
+++ b/arch/arm/mach-uniphier/arm64/arm-cci500.c
@@ -0,0 +1,41 @@
+/*
+ * Initialization of ARM Corelink CCI-500 Cache Coherency Interconnect
+ *
+ * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <mapmem.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+
+#define CCI500_BASE 0x5FD00000
+#define CCI500_SLAVE_OFFSET 0x1000
+
+#define CCI500_SNOOP_CTRL
+#define CCI500_SNOOP_CTRL_EN_DVM BIT(1)
+#define CCI500_SNOOP_CTRL_EN_SNOOP BIT(0)
+
+void cci500_init(unsigned int nr_slaves)
+{
+ unsigned long slave_base = CCI500_BASE + CCI500_SLAVE_OFFSET;
+ int i;
+
+ for (i = 0; i < nr_slaves; i++) {
+ void __iomem *base;
+ u32 tmp;
+
+ base = map_sysmem(slave_base, SZ_4K);
+
+ tmp = readl(base);
+ tmp |= CCI500_SNOOP_CTRL_EN_DVM | CCI500_SNOOP_CTRL_EN_SNOOP;
+ writel(tmp, base);
+
+ unmap_sysmem(base);
+
+ slave_base += CCI500_SLAVE_OFFSET;
+ }
+}
diff --git a/arch/arm/mach-uniphier/arm64/mem_map.c b/arch/arm/mach-uniphier/arm64/mem_map.c
new file mode 100644
index 0000000..74ef919
--- /dev/null
+++ b/arch/arm/mach-uniphier/arm64/mem_map.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <linux/types.h>
+#include <asm/armv8/mmu.h>
+
+static struct mm_region uniphier_mem_map[] = {
+ {
+ .base = 0x00000000,
+ .size = 0x80000000,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+ PTE_BLOCK_NON_SHARE |
+ PTE_BLOCK_PXN | PTE_BLOCK_UXN
+ },
+ {
+ .base = 0x80000000,
+ .size = 0xc0000000,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE
+ },
+ { /* sentinel */ }
+};
+
+struct mm_region *mem_map = uniphier_mem_map;
diff --git a/arch/arm/mach-uniphier/arm64/smp.S b/arch/arm/mach-uniphier/arm64/smp.S
new file mode 100644
index 0000000..9348ec9
--- /dev/null
+++ b/arch/arm/mach-uniphier/arm64/smp.S
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <linux/linkage.h>
+
+ENTRY(uniphier_smp_setup)
+ mrs x0, s3_1_c15_c2_1 /* CPUECTLR_EL1 */
+ orr x0, x0, #(1 << 6) /* SMPEN */
+ msr s3_1_c15_c2_1, x0
+ ret
+ENDPROC(uniphier_smp_setup)
+
+ENTRY(uniphier_secondary_startup)
+ bl uniphier_smp_setup
+ b _start
+ENDPROC(uniphier_secondary_startup)
diff --git a/arch/arm/mach-uniphier/arm64/smp_kick_cpus.c b/arch/arm/mach-uniphier/arm64/smp_kick_cpus.c
new file mode 100644
index 0000000..64412e0
--- /dev/null
+++ b/arch/arm/mach-uniphier/arm64/smp_kick_cpus.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <mapmem.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+
+#define UNIPHIER_SMPCTRL_ROM_RSV0 0x59801200
+
+void uniphier_smp_setup(void);
+void uniphier_secondary_startup(void);
+
+void uniphier_smp_kick_all_cpus(void)
+{
+ void __iomem *rom_boot_rsv0;
+
+ rom_boot_rsv0 = map_sysmem(UNIPHIER_SMPCTRL_ROM_RSV0, SZ_8);
+
+ writeq((u64)uniphier_secondary_startup, rom_boot_rsv0);
+ readq(rom_boot_rsv0); /* relax */
+
+ unmap_sysmem(rom_boot_rsv0);
+
+ uniphier_smp_setup();
+
+ asm("sev"); /* Bring up all secondary CPUs from Boot ROM into U-Boot */
+}
diff --git a/arch/arm/mach-uniphier/arm64/timer.c b/arch/arm/mach-uniphier/arm64/timer.c
new file mode 100644
index 0000000..4beab9d
--- /dev/null
+++ b/arch/arm/mach-uniphier/arm64/timer.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <mapmem.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/sizes.h>
+
+#define CNT_CONTROL_BASE 0x60E00000
+
+#define CNTCR 0x000
+#define CNTCR_EN BIT(0)
+
+/* setup ARMv8 Generic Timer */
+int timer_init(void)
+{
+ void __iomem *base;
+ u32 tmp;
+
+ base = map_sysmem(CNT_CONTROL_BASE, SZ_4K);
+
+ /*
+ * Note:
+ * In a system that implements both Secure and Non-secure states,
+ * this register is only writable in Secure state.
+ */
+ tmp = readl(base + CNTCR);
+ tmp |= CNTCR_EN;
+ writel(tmp, base + CNTCR);
+
+ unmap_sysmem(base);
+
+ return 0;
+}