arm: nuvoton: Add support for Nuvoton NPCM845 BMC

Add basic support for the Nuvoton NPCM845 EVB (Arbel).

Signed-off-by: Jim Liu <JJLIU0@nuvoton.com>
diff --git a/arch/arm/mach-npcm/Kconfig b/arch/arm/mach-npcm/Kconfig
index cf5043d..7f2f9ac 100644
--- a/arch/arm/mach-npcm/Kconfig
+++ b/arch/arm/mach-npcm/Kconfig
@@ -19,8 +19,16 @@
 	  General support for NPCM7xx BMC (Poleg).
 	  Nuvoton NPCM7xx BMC is based on the Cortex A9.
 
+config ARCH_NPCM8XX
+	bool "Support Nuvoton NPCM8xx SoC"
+	select ARM64
+	help
+	  General support for NPCM8xx BMC (Arbel).
+	  Nuvoton NPCM8xx BMC is based on the Cortex A35.
+
 endchoice
 
 source "arch/arm/mach-npcm/npcm7xx/Kconfig"
+source "arch/arm/mach-npcm/npcm8xx/Kconfig"
 
 endif
diff --git a/arch/arm/mach-npcm/Makefile b/arch/arm/mach-npcm/Makefile
index 8a1572b..b448329 100644
--- a/arch/arm/mach-npcm/Makefile
+++ b/arch/arm/mach-npcm/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_ARCH_NPCM7xx) += npcm7xx/
+obj-$(CONFIG_ARCH_NPCM8XX) += npcm8xx/
diff --git a/arch/arm/mach-npcm/npcm8xx/Kconfig b/arch/arm/mach-npcm/npcm8xx/Kconfig
new file mode 100644
index 0000000..5f4a050
--- /dev/null
+++ b/arch/arm/mach-npcm/npcm8xx/Kconfig
@@ -0,0 +1,18 @@
+if ARCH_NPCM8XX
+
+config SYS_CPU
+	default "armv8"
+
+config SYS_SOC
+	default "npcm8xx"
+
+config TARGET_ARBEL_EVB
+	bool "Arbel Evaluation Board"
+	help
+	  ARBEL_EVB is Nuvoton evaluation board for NPCM845 SoC,
+	  supports general functions of Basebase Management Controller
+	  (BMC).
+
+source "board/nuvoton/arbel_evb/Kconfig"
+
+endif
diff --git a/arch/arm/mach-npcm/npcm8xx/Makefile b/arch/arm/mach-npcm/npcm8xx/Makefile
new file mode 100644
index 0000000..6c080e1
--- /dev/null
+++ b/arch/arm/mach-npcm/npcm8xx/Makefile
@@ -0,0 +1 @@
+obj-y += cpu.o reset.o
diff --git a/arch/arm/mach-npcm/npcm8xx/cpu.c b/arch/arm/mach-npcm/npcm8xx/cpu.c
new file mode 100644
index 0000000..2d839cf
--- /dev/null
+++ b/arch/arm/mach-npcm/npcm8xx/cpu.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2022 Nuvoton Technology Corp.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/arch/gcr.h>
+#include <asm/armv8/mmu.h>
+
+#define SYSCNT_CTRL_BASE_ADDR   0xF07FC000
+#define SC_CNTCR_ENABLE		BIT(0)
+#define SC_CNTCR_HDBG		BIT(1)
+#define SC_CNTCR_FREQ0		BIT(8)
+#define SC_CNTCR_FREQ1		BIT(9)
+
+/* System Counter register map */
+struct sctr_regs {
+	u32 cntcr;
+	u32 cntsr;
+	u32 cntcv1;
+	u32 cntcv2;
+	u32 resv1[4];
+	u32 cntfid0;
+	u32 cntfid1;
+	u32 cntfid2;
+	u32 resv2[1001];
+	u32 counterid[1];
+};
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int print_cpuinfo(void)
+{
+	struct npcm_gcr *gcr = (struct npcm_gcr *)NPCM_GCR_BA;
+	unsigned int val;
+	unsigned long mpidr_val;
+
+	asm volatile("mrs %0, mpidr_el1" : "=r" (mpidr_val));
+
+	val = readl(&gcr->mdlr);
+
+	printf("CPU-%lu: ", mpidr_val & 0x3);
+
+	switch (val) {
+	case ARBEL_NPCM845:
+		printf("NPCM845 ");
+		break;
+	case ARBEL_NPCM830:
+		printf("NPCM830 ");
+		break;
+	case ARBEL_NPCM810:
+		printf("NPCM810 ");
+		break;
+	default:
+		printf("NPCM8XX ");
+		break;
+	}
+
+	val = readl(&gcr->pdid);
+	switch (val) {
+	case ARBEL_Z1:
+		printf("Z1 @ ");
+		break;
+	case ARBEL_A1:
+		printf("A1 @ ");
+		break;
+	default:
+		printf("Unknown\n");
+		break;
+	}
+
+	return 0;
+}
+
+int arch_cpu_init(void)
+{
+	if (!IS_ENABLED(CONFIG_SYS_DCACHE_OFF)) {
+		/* Enable cache to speed up system running */
+		if (get_sctlr() & CR_M)
+			return 0;
+
+		icache_enable();
+		__asm_invalidate_dcache_all();
+		__asm_invalidate_tlb_all();
+		set_sctlr(get_sctlr() | CR_C);
+	}
+
+	return 0;
+}
+
+static struct mm_region npcm_mem_map[1 + CONFIG_NR_DRAM_BANKS + 1] = {
+	{
+		/* DRAM */
+		.phys = 0x0UL,
+		.virt = 0x0UL,
+		.size = 0x80000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_INNER_SHARE
+	},
+	{
+		.phys = 0x80000000UL,
+		.virt = 0x80000000UL,
+		.size = 0x80000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	},
+	{
+		/* List terminator */
+		0,
+	}
+};
+
+struct mm_region *mem_map = npcm_mem_map;
+
+int timer_init(void)
+{
+	struct sctr_regs *sctr = (struct sctr_regs *)SYSCNT_CTRL_BASE_ADDR;
+	u32 cntfrq_el0;
+
+	/* Enable system counter */
+	__asm__ __volatile__("mrs %0, CNTFRQ_EL0\n\t" : "=r" (cntfrq_el0) : : "memory");
+	writel(cntfrq_el0, &sctr->cntfid0);
+	clrsetbits_le32(&sctr->cntcr, SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1,
+			SC_CNTCR_ENABLE | SC_CNTCR_HDBG);
+
+	gd->arch.tbl = 0;
+	gd->arch.tbu = 0;
+
+	return 0;
+}
diff --git a/arch/arm/mach-npcm/npcm8xx/reset.c b/arch/arm/mach-npcm/npcm8xx/reset.c
new file mode 100644
index 0000000..6954e6c
--- /dev/null
+++ b/arch/arm/mach-npcm/npcm8xx/reset.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2022 Nuvoton Technology Corp.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/gcr.h>
+#include <asm/arch/rst.h>
+
+void reset_cpu(void)
+{
+	/* Generate a watchdog0 reset */
+	writel(WTCR_WTR | WTCR_WTRE | WTCR_WTE, WTCR0_REG);
+
+	while (1)
+		;
+}
+
+void reset_misc(void)
+{
+	struct npcm_gcr *gcr = (struct npcm_gcr *)NPCM_GCR_BA;
+
+	clrbits_le32(&gcr->intcr2, INTCR2_WDC);
+}
+
+int npcm_get_reset_status(void)
+{
+	struct npcm_gcr *gcr = (struct npcm_gcr *)NPCM_GCR_BA;
+	u32 val;
+
+	val = readl(&gcr->ressr);
+	if (!val)
+		val = readl(&gcr->intcr2);
+
+	return val & RST_STS_MASK;
+}