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;
+}