plat(n1sdp): initial commit of N1SDP platform port

This patch allows TFTF to run on N1SDP in a limited manner and is still in
development, some tests are disabled using the file
plat/arm/n1sdp/tests_to_skip.txt.

The major known issue now is with PSCI commands waking up and powering
down cores, and SGIs do not wake up powered off cores.

Build command: "make CROSS_COMPILE=aarch64-none-elf- PLAT=n1sdp tftf"

To run TFTF on N1SDP, copy tftf.bin to the /SOFTWARE directory on the SD
card and edit the images.txt file to load tftf.bin instead of uefi.bin.

Signed-off-by: John Powell <john.powell@arm.com>
Change-Id: I897ba665306413c594544d6a231555475e7c8111
diff --git a/plat/arm/n1sdp/aarch64/plat_helpers.S b/plat/arm/n1sdp/aarch64/plat_helpers.S
new file mode 100644
index 0000000..d0c6347
--- /dev/null
+++ b/plat/arm/n1sdp/aarch64/plat_helpers.S
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <drivers/arm/pl011.h>
+#include <platform_def.h>
+
+	.globl	platform_get_core_pos
+	.globl	plat_crash_console_init
+	.globl	plat_crash_console_putc
+	.globl	plat_crash_console_flush
+
+/*----------------------------------------------------------------------
+ * unsigned int platform_get_core_pos(unsigned long mpid)
+ *
+ * Function to calculate the core position on N1SDP platforms.
+ *
+ * (ClusterId * N1SDP_MAX_CPUS_PER_CLUSTER * N1SDP_MAX_PE_PER_CPU) +
+ * (CPUId * N1SDP_MAX_PE_PER_CPU) +
+ * ThreadId
+ *
+ * which can be simplified as:
+ *
+ * ((ClusterId * N1SDP_MAX_CPUS_PER_CLUSTER + CPUId) * N1SDP_MAX_PE_PER_CPU)
+ * + ThreadId
+ * ---------------------------------------------------------------------
+ */
+func platform_get_core_pos
+	/*
+	 * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
+	 * look as if in a multi-threaded implementation.
+	 */
+	tst	x0, #MPIDR_MT_MASK
+	lsl	x3, x0, #MPIDR_AFFINITY_BITS
+	csel	x3, x3, x0, eq
+
+	/* Extract individual affinity fields from MPIDR */
+	ubfx	x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+
+	/* Compute linear position */
+	mov	x3, #N1SDP_MAX_CPUS_PER_CLUSTER
+	madd	x1, x2, x3, x1
+	mov	x3, #N1SDP_MAX_PE_PER_CPU
+	madd	x0, x1, x3, x0
+	ret
+endfunc platform_get_core_pos
+
+/* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0 - x4
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+	mov_imm	x0, PLAT_ARM_UART_BASE
+	mov_imm	x1, PLAT_ARM_UART_CLK_IN_HZ
+	mov_imm	x2, PL011_BAUDRATE
+	b	console_core_init
+endfunc plat_crash_console_init
+
+/* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+	mov_imm	x1, PLAT_ARM_UART_BASE
+	b	console_core_putc
+endfunc plat_crash_console_putc
+
+/* ---------------------------------------------
+ * int plat_crash_console_flush()
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * Out : return -1 on error else return 0.
+ * Clobber list : x0 - x1
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+	mov_imm	x1, PLAT_ARM_UART_BASE
+	b	console_core_flush
+endfunc plat_crash_console_flush
diff --git a/plat/arm/n1sdp/include/platform_def.h b/plat/arm/n1sdp/include/platform_def.h
new file mode 100644
index 0000000..71409fc
--- /dev/null
+++ b/plat/arm/n1sdp/include/platform_def.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <arch.h>
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+/* Platform binary types for linking */
+#define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH		aarch64
+
+#define N1SDP_CLUSTER_COUNT		2
+#define N1SDP_MAX_CPUS_PER_CLUSTER	2
+#define N1SDP_MAX_PE_PER_CPU		1
+
+/*******************************************************************************
+ * Run-time address of the TFTF image.
+ * It has to match the location where the Trusted Firmware-A loads the BL33
+ * image.
+ ******************************************************************************/
+#define TFTF_BASE			0xE0000000
+
+#define N1SDP_DRAM1_BASE		0x80000000
+#define N1SDP_DRAM1_SIZE		0x80000000
+#define DRAM_BASE			N1SDP_DRAM1_BASE
+
+/*
+ * TF-A reserves DRAM space 0xFD000000 - 0xFEFFFFFF for Trusted DRAM
+ * TF-A reserves DRAM space 0xFF000000 - 0xFFFFFFFF for TZC
+ */
+#define ARM_TZC_DRAM1_SIZE		0x00200000 /* 2MB */
+#define ARM_TRUSTED_DRAM1_SIZE		0x0E000000 /* 16MB */
+
+#define DRAM_SIZE			(N1SDP_DRAM1_SIZE	-	\
+					 ARM_TRUSTED_DRAM1_SIZE -	\
+					 ARM_TZC_DRAM1_SIZE)
+
+/* REFCLK CNTControl, Generic Timer. Secure Access only. */
+#define SYS_CNT_CONTROL_BASE		0x2a430000
+/* REFCLK CNTRead, Generic Timer. */
+#define SYS_CNT_READ_BASE		0x2a800000
+/* AP_REFCLK CNTBase1, Generic Timer. */
+#define SYS_CNT_BASE1			0x2A830000
+
+/* Base address of non-trusted watchdog (SP805) */
+#define SP805_WDOG_BASE			0x1C0F0000
+
+/* Base address of trusted watchdog (SP805) */
+#define SP805_TWDOG_BASE		0x2A480000
+#define IRQ_TWDOG_INTID			86
+
+/* Base address and size of external NVM flash */
+#define FLASH_BASE			0x08000000
+
+#define NOR_FLASH_BLOCK_SIZE		0x40000		/* 256KB */
+#define FLASH_SIZE			0x4000000	/* 64MB */
+
+/*
+ * If you want to use DRAM for non-volatile memory then the first 128MB
+ * can be used. However for tests that involve power resets this is not
+ * suitable since the state will be lost.
+ */
+#define TFTF_NVM_OFFSET			0x0
+#define TFTF_NVM_SIZE			0x8000000	/* 128 MB */
+
+/* Sub-system Peripherals */
+#define N1SDP_DEVICE0_BASE		0x08000000
+#define N1SDP_DEVICE0_SIZE		0x48000000
+
+/* N1SDP remote chip at 4 TB offset */
+#define PLAT_ARM_REMOTE_CHIP_OFFSET             (ULL(1) << 42)
+
+/* Following covers remote n1sdp */
+#define N1SDP_DEVICE1_BASE		(N1SDP_DEVICE0_BASE + PLAT_ARM_REMOTE_CHIP_OFFSET)
+#define N1SDP_DEVICE1_SIZE		N1SDP_DEVICE0_SIZE
+
+/* GIC-600 & interrupt handling related constants */
+#define N1SDP_GICD_BASE			0x30000000
+#define N1SDP_GICR_BASE			0x300C0000
+#define N1SDP_GICC_BASE			0x2C000000
+
+/* SoC's PL011 UART0 related constants */
+#define PL011_UART0_BASE		0x2A400000
+#define PL011_UART0_CLK_IN_HZ		50000000
+
+/*
+ * SoC's PL011 UART1 related constants (duplicated from UART0 since AP UART1
+ * isn't accessible on N1SDP)
+ */
+#define PL011_UART1_BASE		0x2A400000
+#define PL011_UART1_CLK_IN_HZ		50000000
+
+#define PLAT_ARM_UART_BASE		PL011_UART0_BASE
+#define PLAT_ARM_UART_CLK_IN_HZ		PL011_UART0_CLK_IN_HZ
+
+/* Size of cacheable stacks */
+#define PLATFORM_STACK_SIZE		0x1400
+
+/* Size of coherent stacks */
+#define PCPU_DV_MEM_STACK_SIZE		0x600
+
+#define PLATFORM_CORE_COUNT		(N1SDP_CLUSTER_COUNT * N1SDP_MAX_CPUS_PER_CLUSTER)
+#define PLATFORM_NUM_AFFS		(N1SDP_CLUSTER_COUNT + PLATFORM_CORE_COUNT)
+#define PLATFORM_MAX_AFFLVL		MPIDR_AFFLVL1
+
+#define PLAT_MAX_PWR_LEVEL		PLATFORM_MAX_AFFLVL
+#define PLAT_MAX_PWR_STATES_PER_LVL	2
+
+/* I/O Storage NOR flash device */
+#define MAX_IO_DEVICES			1
+#define MAX_IO_HANDLES			1
+
+/* Local state bit width for each level in the state-ID field of power state */
+#define PLAT_LOCAL_PSTATE_WIDTH		4
+
+/* Platform specific page table and MMU setup constants */
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ull << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ull << 36)
+
+#if IMAGE_CACTUS
+#define MAX_XLAT_TABLES			6
+#else
+#define MAX_XLAT_TABLES			5
+#endif
+#define MAX_MMAP_REGIONS		16
+
+/*******************************************************************************
+ * Used to align variables on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT  		 6
+#define CACHE_WRITEBACK_GRANULE		 (1 << CACHE_WRITEBACK_SHIFT)
+
+/* Non-Secure Software Generated Interupts IDs */
+#define IRQ_NS_SGI_0			0
+#define IRQ_NS_SGI_7			7
+
+/*
+ * AP UART1 interrupt is considered as the maximum SPI.
+ * MAX_SPI_ID = MIN_SPI_ID + PLAT_MAX_SPI_OFFSET_ID = 96
+ */
+#define PLAT_MAX_SPI_OFFSET_ID		64
+
+/* AP_REFCLK Generic Timer, Non-secure. */
+#define IRQ_CNTPSIRQ1			92
+
+/* Per-CPU Hypervisor Timer Interrupt ID */
+#define IRQ_PCPU_HP_TIMER		26
+
+/* Times(in ms) used by test code for completion of different events */
+#define PLAT_SUSPEND_ENTRY_TIME         0x100
+#define PLAT_SUSPEND_ENTRY_EXIT_TIME    0x200
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/n1sdp/n1sdp_mem_prot.c b/plat/arm/n1sdp/n1sdp_mem_prot.c
new file mode 100644
index 0000000..1ee602d
--- /dev/null
+++ b/plat/arm/n1sdp/n1sdp_mem_prot.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform.h>
+
+#define N1SDP_DRAM1_NS_START	(TFTF_BASE + 0x4000000)
+#define N1SDP_DRAM1_NS_SIZE	0x10000000
+
+static const mem_region_t n1sdp_ram_ranges[] = {
+	{ N1SDP_DRAM1_NS_START, N1SDP_DRAM1_NS_SIZE }
+};
+
+const mem_region_t *plat_get_prot_regions(int *nelem)
+{
+	*nelem = ARRAY_SIZE(n1sdp_ram_ranges);
+	return n1sdp_ram_ranges;
+}
diff --git a/plat/arm/n1sdp/n1sdp_pwr_state.c b/plat/arm/n1sdp/n1sdp_pwr_state.c
new file mode 100644
index 0000000..fcee7c4
--- /dev/null
+++ b/plat/arm/n1sdp/n1sdp_pwr_state.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform.h>
+#include <psci.h>
+
+/* State IDs for local power states on SGI platforms. */
+#define N1SDP_PS_RUN_STATE_ID		0 /* Valid for CPUs and Clusters */
+#define N1SDP_PS_RETENTION_STATE_ID	1 /* Valid for only CPUs */
+#define N1SDP_PS_OFF_STATE_ID		2 /* Valid for CPUs and Clusters */
+
+/* Suspend depth definitions for each power state */
+#define N1SDP_PS_RUN_DEPTH		0
+#define N1SDP_PS_RETENTION_DEPTH		1
+#define N1SDP_PS_OFF_DEPTH		2
+
+/* The state property array with details of idle state possible for the core */
+static const plat_state_prop_t core_state_prop[] = {
+	{N1SDP_PS_RETENTION_DEPTH, N1SDP_PS_RETENTION_STATE_ID, PSTATE_TYPE_STANDBY},
+	{N1SDP_PS_OFF_DEPTH, N1SDP_PS_OFF_STATE_ID, PSTATE_TYPE_POWERDOWN},
+	{0}
+};
+
+/* The state property array with details of idle state possible for the cluster */
+static const plat_state_prop_t cluster_state_prop[] = {
+	{N1SDP_PS_OFF_DEPTH, N1SDP_PS_OFF_STATE_ID, PSTATE_TYPE_POWERDOWN},
+	{0}
+};
+
+const plat_state_prop_t *plat_get_state_prop(unsigned int level)
+{
+	switch (level) {
+	case MPIDR_AFFLVL0:
+		return core_state_prop;
+	case MPIDR_AFFLVL1:
+		return cluster_state_prop;
+	default:
+		return NULL;
+	}
+}
diff --git a/plat/arm/n1sdp/n1sdp_topology.c b/plat/arm/n1sdp/n1sdp_topology.c
new file mode 100644
index 0000000..40750ce
--- /dev/null
+++ b/plat/arm/n1sdp/n1sdp_topology.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <plat_topology.h>
+#include <tftf_lib.h>
+
+static const struct {
+	unsigned int cluster_id;
+	unsigned int cpu_id;
+} n1sdp_cores[] = {
+	/* N1SDP has 2 clusters with 2 cores each */
+	{ 0, 0 },
+	{ 0, 1 },
+	{ 1, 0 },
+	{ 1, 1 },
+};
+
+/*
+ * The power domain tree descriptor. The cluster power domains are
+ * arranged so that when the PSCI generic code creates the power domain tree,
+ * the indices of the CPU power domain nodes it allocates match the linear
+ * indices returned by plat_core_pos_by_mpidr().
+ */
+const unsigned char n1sdp_pd_tree_desc[] = {
+	/* Number of root nodes */
+	N1SDP_CLUSTER_COUNT,
+	/* Number of children for the 1st node */
+	N1SDP_MAX_CPUS_PER_CLUSTER,
+	/* Number of children for the 2nd node */
+	N1SDP_MAX_CPUS_PER_CLUSTER
+};
+
+const unsigned char *tftf_plat_get_pwr_domain_tree_desc(void)
+{
+	return n1sdp_pd_tree_desc;
+}
+
+uint64_t tftf_plat_get_mpidr(unsigned int core_pos)
+{
+	uint64_t mpid;
+
+	assert(core_pos < PLATFORM_CORE_COUNT);
+
+	mpid = (uint64_t)make_mpid(n1sdp_cores[core_pos].cluster_id,
+				   n1sdp_cores[core_pos].cpu_id);
+
+	return mpid;
+}
diff --git a/plat/arm/n1sdp/plat_setup.c b/plat/arm/n1sdp/plat_setup.c
new file mode 100644
index 0000000..1c04c26
--- /dev/null
+++ b/plat/arm/n1sdp/plat_setup.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/arm_gic.h>
+#include <xlat_tables_v2.h>
+
+static const mmap_region_t mmap[] = {
+	MAP_REGION_FLAT(N1SDP_DEVICE0_BASE, N1SDP_DEVICE0_SIZE,
+			MT_DEVICE | MT_RW | MT_NS),
+	/*MAP_REGION_FLAT(N1SDP_DEVICE1_BASE, N1SDP_DEVICE1_SIZE,
+			MT_DEVICE | MT_RW | MT_NS),*/
+	MAP_REGION_FLAT(DRAM_BASE, TFTF_BASE - DRAM_BASE,
+			MT_MEMORY | MT_RW | MT_NS),
+	{0}
+};
+
+const mmap_region_t *tftf_platform_get_mmap(void)
+{
+	return mmap;
+}
+
+void plat_arm_gic_init(void)
+{
+	arm_gic_init(N1SDP_GICC_BASE, N1SDP_GICD_BASE, N1SDP_GICR_BASE);
+}
diff --git a/plat/arm/n1sdp/platform.mk b/plat/arm/n1sdp/platform.mk
new file mode 100644
index 0000000..39c33ab
--- /dev/null
+++ b/plat/arm/n1sdp/platform.mk
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+N1SDP_MAX_PE_PER_CPU	:= 1
+
+$(eval $(call add_define,TFTF_DEFINES,N1SDP_MAX_PE_PER_CPU))
+$(eval $(call add_define,NS_BL1U_DEFINES,N1SDP_MAX_PE_PER_CPU))
+$(eval $(call add_define,NS_BL2U_DEFINES,N1SDP_MAX_PE_PER_CPU))
+
+PLAT_INCLUDES	+=	-Iplat/arm/n1sdp/include/
+
+PLAT_SOURCES	:=	drivers/arm/gic/arm_gic_v2v3.c		\
+			drivers/arm/gic/gic_v2.c		\
+			drivers/arm/gic/gic_v3.c		\
+			drivers/arm/sp805/sp805.c		\
+			drivers/arm/timer/private_timer.c	\
+			drivers/arm/timer/system_timer.c	\
+			plat/arm/n1sdp/${ARCH}/plat_helpers.S	\
+			plat/arm/n1sdp/plat_setup.c		\
+			plat/arm/n1sdp/n1sdp_mem_prot.c		\
+			plat/arm/n1sdp/n1sdp_pwr_state.c		\
+			plat/arm/n1sdp/n1sdp_topology.c
+
+CACTUS_SOURCES	+=	plat/arm/n1sdp/${ARCH}/plat_helpers.S
+IVY_SOURCES	+=	plat/arm/n1sdp/${ARCH}/plat_helpers.S
+
+PLAT_TESTS_SKIP_LIST	:=	plat/arm/n1sdp/tests_to_skip.txt
+
+ifeq (${USE_NVM},1)
+$(error "USE_NVM is not supported on N1SDP platforms")
+endif
+
+$(warning "TFTF on N1SDP is still in development and there may be issues")
+
+include plat/arm/common/arm_common.mk
diff --git a/plat/arm/n1sdp/tests_to_skip.txt b/plat/arm/n1sdp/tests_to_skip.txt
new file mode 100644
index 0000000..21417e0
--- /dev/null
+++ b/plat/arm/n1sdp/tests_to_skip.txt
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Disable SMMUv3 tests
+SMMUv3 tests
+
+# PSCI is enabled but not tested
+PSCI STAT/Stats test cases after system suspend
+PSCI System Suspend Validation
+
+# Disable FF-A Interrupt tests as TWDOG is not supported by TC platform
+FF-A Interrupt
+
+# The following tests were disabled to make TFTF successfully run on N1SDP
+#
+# There is an issue where issuing an SGI to a powered off core will not wake it up
+#
+# Most of these tests should work but something is likely wrong with the plat
+# files in TFTF, since the port was done purely to test the spectre workaround
+# performance impact. Once that was done no further work was done on the port.
+
+Timer framework Validation/Target timer to a power down cpu
+Timer framework Validation/Test scenario where multiple CPUs call same timeout
+Timer framework Validation/Stress test the timer framework
+PSCI Affinity Info/Affinity info level0 powerdown
+PSCI CPU Suspend
+PSCI STAT/for valid composite state CPU suspend