summaryrefslogtreecommitdiffstats
path: root/plat/arm/board/n1sdp
diff options
context:
space:
mode:
Diffstat (limited to 'plat/arm/board/n1sdp')
-rw-r--r--plat/arm/board/n1sdp/aarch64/n1sdp_helper.S78
-rw-r--r--plat/arm/board/n1sdp/fdts/n1sdp_fw_config.dts29
-rw-r--r--plat/arm/board/n1sdp/fdts/n1sdp_nt_fw_config.dts23
-rw-r--r--plat/arm/board/n1sdp/fdts/n1sdp_optee_spmc_manifest.dts30
-rw-r--r--plat/arm/board/n1sdp/fdts/n1sdp_tb_fw_config.dts27
-rw-r--r--plat/arm/board/n1sdp/include/plat_macros.S24
-rw-r--r--plat/arm/board/n1sdp/include/platform_def.h251
-rw-r--r--plat/arm/board/n1sdp/n1sdp_bl1_setup.c19
-rw-r--r--plat/arm/board/n1sdp/n1sdp_bl2_setup.c89
-rw-r--r--plat/arm/board/n1sdp/n1sdp_bl31_setup.c161
-rw-r--r--plat/arm/board/n1sdp/n1sdp_def.h52
-rw-r--r--plat/arm/board/n1sdp/n1sdp_err.c17
-rw-r--r--plat/arm/board/n1sdp/n1sdp_image_load.c143
-rw-r--r--plat/arm/board/n1sdp/n1sdp_interconnect.c33
-rw-r--r--plat/arm/board/n1sdp/n1sdp_plat.c73
-rw-r--r--plat/arm/board/n1sdp/n1sdp_security.c12
-rw-r--r--plat/arm/board/n1sdp/n1sdp_topology.c59
-rw-r--r--plat/arm/board/n1sdp/n1sdp_trusted_boot.c54
-rw-r--r--plat/arm/board/n1sdp/platform.mk111
19 files changed, 1285 insertions, 0 deletions
diff --git a/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S b/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S
new file mode 100644
index 0000000..3da55b6
--- /dev/null
+++ b/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <neoverse_n1.h>
+#include <cpu_macros.S>
+#include <platform_def.h>
+
+ .globl plat_arm_calc_core_pos
+ .globl plat_reset_handler
+
+ /* -----------------------------------------------------
+ * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
+ *
+ * Helper function to calculate the core position.
+ * ((ChipId * N1SDP_MAX_CLUSTERS_PER_CHIP + ClusterId) *
+ * N1SDP_MAX_CPUS_PER_CLUSTER * N1SDP_MAX_PE_PER_CPU) +
+ * (CPUId * N1SDP_MAX_PE_PER_CPU) + ThreadId
+ *
+ * which can be simplified as:
+ *
+ * (((ChipId * N1SDP_MAX_CLUSTERS_PER_CHIP + ClusterId) *
+ * N1SDP_MAX_CPUS_PER_CLUSTER + CPUId) * N1SDP_MAX_PE_PER_CPU) +
+ * ThreadId
+ * ------------------------------------------------------
+ */
+
+func plat_arm_calc_core_pos
+ mov x4, x0
+
+ /*
+ * The MT bit in MPIDR is always set for n1sdp and the
+ * affinity level 0 corresponds to thread affinity level.
+ */
+
+ /* Extract individual affinity fields from MPIDR */
+ ubfx x0, x4, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x1, x4, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x2, x4, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x3, x4, #MPIDR_AFF3_SHIFT, #MPIDR_AFFINITY_BITS
+
+ /* Compute linear position */
+ mov x4, #N1SDP_MAX_CLUSTERS_PER_CHIP
+ madd x2, x3, x4, x2
+ mov x4, #N1SDP_MAX_CPUS_PER_CLUSTER
+ madd x1, x2, x4, x1
+ mov x4, #N1SDP_MAX_PE_PER_CPU
+ madd x0, x1, x4, x0
+ ret
+endfunc plat_arm_calc_core_pos
+
+ /* -----------------------------------------------------
+ * void plat_reset_handler(void);
+ *
+ * Determine the CPU MIDR and disable power down bit for
+ * that CPU.
+ * -----------------------------------------------------
+ */
+
+func plat_reset_handler
+ jump_if_cpu_midr NEOVERSE_N1_MIDR, N1
+ ret
+
+ /* -----------------------------------------------------
+ * Disable CPU power down bit in power control register
+ * -----------------------------------------------------
+ */
+N1:
+ mrs x0, NEOVERSE_N1_CPUPWRCTLR_EL1
+ bic x0, x0, #NEOVERSE_N1_CORE_PWRDN_EN_MASK
+ msr NEOVERSE_N1_CPUPWRCTLR_EL1, x0
+ isb
+ ret
+endfunc plat_reset_handler
diff --git a/plat/arm/board/n1sdp/fdts/n1sdp_fw_config.dts b/plat/arm/board/n1sdp/fdts/n1sdp_fw_config.dts
new file mode 100644
index 0000000..700b900
--- /dev/null
+++ b/plat/arm/board/n1sdp/fdts/n1sdp_fw_config.dts
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/tbbr/tbbr_img_def.h>
+
+/dts-v1/;
+/ {
+ dtb-registry {
+ compatible = "fconf,dyn_cfg-dtb_registry";
+ tb_fw-config {
+ load-address = <0x0 0x4001300>;
+ max-size = <0x200>;
+ id = <TB_FW_CONFIG_ID>;
+ };
+ tos_fw-config {
+ load-address = <0x0 0x4001600>;
+ max-size = <0x1000>;
+ id = <TOS_FW_CONFIG_ID>;
+ };
+ nt_fw-config {
+ load-address = <0x0 0xFEF00000>;
+ max-size = <0x0100000>;
+ id = <NT_FW_CONFIG_ID>;
+ };
+ };
+};
diff --git a/plat/arm/board/n1sdp/fdts/n1sdp_nt_fw_config.dts b/plat/arm/board/n1sdp/fdts/n1sdp_nt_fw_config.dts
new file mode 100644
index 0000000..da5e04d
--- /dev/null
+++ b/plat/arm/board/n1sdp/fdts/n1sdp_nt_fw_config.dts
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+ /* compatible string */
+ compatible = "arm,n1sdp";
+
+ /*
+ * Place holder for platform-info node with default values.
+ * The values will be set to the correct values during
+ * the BL2 stage of boot.
+ */
+ platform-info {
+ multichip-mode = <0x0>;
+ secondary-chip-count = <0x0>;
+ local-ddr-size = <0x0>;
+ remote-ddr-size = <0x0>;
+ };
+}; \ No newline at end of file
diff --git a/plat/arm/board/n1sdp/fdts/n1sdp_optee_spmc_manifest.dts b/plat/arm/board/n1sdp/fdts/n1sdp_optee_spmc_manifest.dts
new file mode 100644
index 0000000..ed87080
--- /dev/null
+++ b/plat/arm/board/n1sdp/fdts/n1sdp_optee_spmc_manifest.dts
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2022 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+/dts-v1/;
+
+/ {
+ compatible = "arm,ffa-core-manifest-1.0";
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ /*
+ * BL32 image details needed by SPMC
+ *
+ * Note:
+ * binary_size: size of BL32 + TOS_FW_CONFIG
+ */
+
+ attribute {
+ spmc_id = <0x8000>;
+ maj_ver = <0x1>;
+ min_ver = <0x0>;
+ exec_state = <0x0>;
+ load_address = <0x0 0x08000000>;
+ entrypoint = <0x0 0x08000000>;
+ binary_size = <0x2000000>;
+ };
+
+};
diff --git a/plat/arm/board/n1sdp/fdts/n1sdp_tb_fw_config.dts b/plat/arm/board/n1sdp/fdts/n1sdp_tb_fw_config.dts
new file mode 100644
index 0000000..e5ffba3
--- /dev/null
+++ b/plat/arm/board/n1sdp/fdts/n1sdp_tb_fw_config.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+ tb_fw-config {
+ compatible = "arm,tb_fw";
+
+ /* Disable authentication for development */
+ disable_auth = <0x0>;
+
+ /*
+ * The following two entries are placeholders for Mbed TLS
+ * heap information. The default values don't matter since
+ * they will be overwritten by BL1.
+ * In case of having shared Mbed TLS heap between BL1 and BL2,
+ * BL1 will populate these two properties with the respective
+ * info about the shared heap. This info will be available for
+ * BL2 in order to locate and re-use the heap.
+ */
+ mbedtls_heap_addr = <0x0 0x0>;
+ mbedtls_heap_size = <0x0>;
+ };
+};
diff --git a/plat/arm/board/n1sdp/include/plat_macros.S b/plat/arm/board/n1sdp/include/plat_macros.S
new file mode 100644
index 0000000..521bcc3
--- /dev/null
+++ b/plat/arm/board/n1sdp/include/plat_macros.S
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <css_macros.S>
+
+/* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant platform registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ *
+ * There are currently no platform specific regs
+ * to print.
+ * ---------------------------------------------
+ */
+ .macro plat_crash_print_regs
+ .endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/arm/board/n1sdp/include/platform_def.h b/plat/arm/board/n1sdp/include/platform_def.h
new file mode 100644
index 0000000..b3799a7
--- /dev/null
+++ b/plat/arm/board/n1sdp/include/platform_def.h
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <plat/arm/board/common/v2m_def.h>
+#include <plat/arm/common/arm_def.h>
+#include <plat/arm/css/common/css_def.h>
+
+/* UART related constants */
+#define PLAT_ARM_BOOT_UART_BASE 0x2A400000
+#define PLAT_ARM_BOOT_UART_CLK_IN_HZ 50000000
+
+/* IOFPGA UART0 */
+#define PLAT_ARM_RUN_UART_BASE 0x1C090000
+#define PLAT_ARM_RUN_UART_CLK_IN_HZ 24000000
+
+#define PLAT_ARM_SP_MIN_RUN_UART_BASE 0x2A410000
+#define PLAT_ARM_SP_MIN_RUN_UART_CLK_IN_HZ 50000000
+
+#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE
+#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ
+
+#define PLAT_ARM_DRAM2_BASE ULL(0x8080000000)
+#define PLAT_ARM_DRAM2_SIZE ULL(0xF80000000)
+
+#define MAX_IO_DEVICES U(3)
+#define MAX_IO_HANDLES U(4)
+
+#define PLAT_ARM_FLASH_IMAGE_BASE 0x18200000
+#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE 0x00800000
+
+#define PLAT_ARM_NVM_BASE 0x18200000
+#define PLAT_ARM_NVM_SIZE 0x00800000
+
+#if defined NS_BL1U_BASE
+# undef NS_BL1U_BASE
+# define NS_BL1U_BASE (PLAT_ARM_NVM_BASE + UL(0x00800000))
+#endif
+
+/* Non-volatile counters */
+#define SOC_TRUSTED_NVCTR_BASE 0x7fe70000
+#define TFW_NVCTR_BASE (SOC_TRUSTED_NVCTR_BASE)
+#define TFW_NVCTR_SIZE U(4)
+#define NTFW_CTR_BASE (SOC_TRUSTED_NVCTR_BASE + 0x0004)
+#define NTFW_CTR_SIZE U(4)
+
+/* N1SDP remote chip at 4 TB offset */
+#define PLAT_ARM_REMOTE_CHIP_OFFSET (ULL(1) << 42)
+
+#define N1SDP_REMOTE_DRAM1_BASE ARM_DRAM1_BASE + \
+ PLAT_ARM_REMOTE_CHIP_OFFSET
+#define N1SDP_REMOTE_DRAM1_SIZE ARM_DRAM1_SIZE
+
+#define N1SDP_REMOTE_DRAM2_BASE PLAT_ARM_DRAM2_BASE + \
+ PLAT_ARM_REMOTE_CHIP_OFFSET
+#define N1SDP_REMOTE_DRAM2_SIZE PLAT_ARM_DRAM2_SIZE
+
+/*
+ * N1SDP platform supports RDIMMs with ECC capability. To use the ECC
+ * capability, the entire DDR memory space has to be zeroed out before
+ * enabling the ECC bits in DMC620. To access the complete DDR memory
+ * along with remote chip's DDR memory, which is at 4 TB offset, physical
+ * and virtual address space limits are extended to 43-bits.
+ */
+#ifdef __aarch64__
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 43)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 43)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+#endif
+
+#if CSS_USE_SCMI_SDS_DRIVER
+#define N1SDP_SCMI_PAYLOAD_BASE 0x45400000
+#else
+#define PLAT_CSS_SCP_COM_SHARED_MEM_BASE 0x45400000
+#endif
+
+/*
+ * Trusted SRAM in N1SDP is 512 KB but only the bottom 384 KB
+ * is used for trusted board boot flow. The top 128 KB is used
+ * to load AP-BL1 image.
+ */
+#define PLAT_ARM_TRUSTED_SRAM_SIZE 0x00060000 /* 384 KB */
+
+/*
+ * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
+ * plus a little space for growth.
+ */
+#define PLAT_ARM_MAX_BL1_RW_SIZE 0xC000
+
+/*
+ * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page
+ */
+
+#if USE_ROMLIB
+# define PLAT_ARM_MAX_ROMLIB_RW_SIZE 0x1000
+# define PLAT_ARM_MAX_ROMLIB_RO_SIZE 0xe000
+#else
+# define PLAT_ARM_MAX_ROMLIB_RW_SIZE U(0)
+# define PLAT_ARM_MAX_ROMLIB_RO_SIZE U(0)
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
+ * little space for growth.
+ */
+#if TRUSTED_BOARD_BOOT
+# define PLAT_ARM_MAX_BL2_SIZE 0x22000
+#else
+# define PLAT_ARM_MAX_BL2_SIZE 0x14000
+#endif
+
+#define PLAT_ARM_MAX_BL31_SIZE UL(0x40000)
+
+#define PLAT_ARM_SPMC_BASE U(0x08000000)
+#define PLAT_ARM_SPMC_SIZE UL(0x02000000) /* 32 MB */
+
+
+/*******************************************************************************
+ * N1SDP topology related constants
+ ******************************************************************************/
+#define N1SDP_MAX_CPUS_PER_CLUSTER U(2)
+#define PLAT_ARM_CLUSTER_COUNT U(2)
+#define PLAT_N1SDP_CHIP_COUNT U(2)
+#define N1SDP_MAX_CLUSTERS_PER_CHIP U(2)
+#define N1SDP_MAX_PE_PER_CPU U(1)
+
+#define PLATFORM_CORE_COUNT (PLAT_N1SDP_CHIP_COUNT * \
+ PLAT_ARM_CLUSTER_COUNT * \
+ N1SDP_MAX_CPUS_PER_CLUSTER * \
+ N1SDP_MAX_PE_PER_CPU)
+
+/* System power domain level */
+#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL3
+
+/*
+ * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
+ * plat_arm_mmap array defined for each BL stage.
+ */
+
+#ifdef IMAGE_BL1
+# define PLAT_ARM_MMAP_ENTRIES U(6)
+# define MAX_XLAT_TABLES U(5)
+#endif
+
+#ifdef IMAGE_BL2
+# define PLAT_ARM_MMAP_ENTRIES U(11)
+# define MAX_XLAT_TABLES U(10)
+#endif
+
+#ifdef IMAGE_BL31
+# define PLAT_ARM_MMAP_ENTRIES U(12)
+# define MAX_XLAT_TABLES U(12)
+#endif
+
+/*
+ * Size of cacheable stacks
+ */
+#if defined(IMAGE_BL1)
+# if TRUSTED_BOARD_BOOT
+# define PLATFORM_STACK_SIZE 0x1000
+# else
+# define PLATFORM_STACK_SIZE 0x440
+# endif
+#elif defined(IMAGE_BL2)
+# if TRUSTED_BOARD_BOOT
+# define PLATFORM_STACK_SIZE 0x1000
+# else
+# define PLATFORM_STACK_SIZE 0x400
+# endif
+#elif defined(IMAGE_BL2U)
+# define PLATFORM_STACK_SIZE 0x400
+#elif defined(IMAGE_BL31)
+# if SPM_MM
+# define PLATFORM_STACK_SIZE 0x500
+# else
+# define PLATFORM_STACK_SIZE 0x400
+# endif
+#elif defined(IMAGE_BL32)
+# define PLATFORM_STACK_SIZE 0x440
+#endif
+
+#define PLAT_ARM_NSTIMER_FRAME_ID 0
+#define PLAT_CSS_MHU_BASE 0x45000000
+#define PLAT_MAX_PWR_LVL 2
+
+#define PLAT_ARM_G1S_IRQS ARM_G1S_IRQS, \
+ CSS_IRQ_MHU
+#define PLAT_ARM_G0_IRQS ARM_G0_IRQS
+
+#define PLAT_ARM_G1S_IRQ_PROPS(grp) CSS_G1S_IRQ_PROPS(grp)
+#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp)
+
+
+#define N1SDP_DEVICE_BASE ULL(0x08000000)
+#define N1SDP_DEVICE_SIZE ULL(0x48000000)
+#define N1SDP_REMOTE_DEVICE_BASE N1SDP_DEVICE_BASE + \
+ PLAT_ARM_REMOTE_CHIP_OFFSET
+#define N1SDP_REMOTE_DEVICE_SIZE N1SDP_DEVICE_SIZE
+
+/* Real base is 0x0. Changed to load BL1 at this address */
+# define PLAT_ARM_TRUSTED_ROM_BASE 0x04060000
+# define PLAT_ARM_TRUSTED_ROM_SIZE 0x00020000 /* 128KB */
+
+#define N1SDP_MAP_DEVICE MAP_REGION_FLAT( \
+ N1SDP_DEVICE_BASE, \
+ N1SDP_DEVICE_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define ARM_MAP_DRAM1 MAP_REGION_FLAT( \
+ ARM_DRAM1_BASE, \
+ ARM_DRAM1_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define N1SDP_MAP_REMOTE_DEVICE MAP_REGION_FLAT( \
+ N1SDP_REMOTE_DEVICE_BASE, \
+ N1SDP_REMOTE_DEVICE_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define N1SDP_MAP_REMOTE_DRAM1 MAP_REGION_FLAT( \
+ N1SDP_REMOTE_DRAM1_BASE, \
+ N1SDP_REMOTE_DRAM1_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+#define N1SDP_MAP_REMOTE_DRAM2 MAP_REGION_FLAT( \
+ N1SDP_REMOTE_DRAM2_BASE, \
+ N1SDP_REMOTE_DRAM2_SIZE, \
+ MT_MEMORY | MT_RW | MT_NS)
+
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE 0x30000000
+#define PLAT_ARM_GICC_BASE 0x2C000000
+#define PLAT_ARM_GICR_BASE 0x300C0000
+
+/* Platform ID address */
+#define SSC_VERSION (SSC_REG_BASE + SSC_VERSION_OFFSET)
+
+/* Secure Watchdog Constants */
+#define SBSA_SECURE_WDOG_BASE UL(0x2A480000)
+#define SBSA_SECURE_WDOG_TIMEOUT UL(100)
+
+/* Number of SCMI channels on the platform */
+#define PLAT_ARM_SCMI_CHANNEL_COUNT U(1)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/n1sdp/n1sdp_bl1_setup.c b/plat/arm/board/n1sdp/n1sdp_bl1_setup.c
new file mode 100644
index 0000000..ed93222
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_bl1_setup.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * Perform any BL1 specific platform actions.
+ ******************************************************************************/
+
+void soc_css_init_nic400(void)
+{
+}
+
+void soc_css_init_pcie(void)
+{
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_bl2_setup.c b/plat/arm/board/n1sdp/n1sdp_bl2_setup.c
new file mode 100644
index 0000000..5f8af9f
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_bl2_setup.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/arm/css/sds.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+
+#include "n1sdp_def.h"
+#include <plat/arm/common/plat_arm.h>
+
+struct n1sdp_plat_info {
+ bool multichip_mode;
+ uint8_t secondary_count;
+ uint8_t local_ddr_size;
+ uint8_t remote_ddr_size;
+} __packed;
+
+/*
+ * N1SDP platform supports RDIMMs with ECC capability. To use the ECC
+ * capability, the entire DDR memory space has to be zeroed out before
+ * enabling the ECC bits in DMC620. Zeroing out several gigabytes of
+ * memory from SCP is quite time consuming so the following function
+ * is added to zero out the DDR memory from application processor which is
+ * much faster compared to SCP.
+ */
+
+void dmc_ecc_setup(uint8_t ddr_size_gb)
+{
+ uint64_t dram2_size;
+
+ dram2_size = (ddr_size_gb * 1024UL * 1024UL * 1024UL) -
+ ARM_DRAM1_SIZE;
+
+ INFO("Zeroing DDR memories\n");
+ zero_normalmem((void *)ARM_DRAM1_BASE, ARM_DRAM1_SIZE);
+ flush_dcache_range(ARM_DRAM1_BASE, ARM_DRAM1_SIZE);
+ zero_normalmem((void *)ARM_DRAM2_BASE, dram2_size);
+ flush_dcache_range(ARM_DRAM2_BASE, dram2_size);
+
+ INFO("Enabling ECC on DMCs\n");
+ /* Set DMCs to CONFIG state before writing ERR0CTLR0 register */
+ mmio_write_32(N1SDP_DMC0_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_CONFIG);
+ mmio_write_32(N1SDP_DMC1_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_CONFIG);
+
+ /* Enable ECC in DMCs */
+ mmio_setbits_32(N1SDP_DMC0_ERR0CTLR0_REG, N1SDP_DMC_ERR0CTLR0_ECC_EN);
+ mmio_setbits_32(N1SDP_DMC1_ERR0CTLR0_REG, N1SDP_DMC_ERR0CTLR0_ECC_EN);
+
+ /* Set DMCs to READY state */
+ mmio_write_32(N1SDP_DMC0_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY);
+ mmio_write_32(N1SDP_DMC1_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY);
+}
+
+void bl2_platform_setup(void)
+{
+ int ret;
+ struct n1sdp_plat_info plat_info;
+
+ ret = sds_init();
+ if (ret != SDS_OK) {
+ ERROR("SDS initialization failed\n");
+ panic();
+ }
+
+ ret = sds_struct_read(N1SDP_SDS_PLATFORM_INFO_STRUCT_ID,
+ N1SDP_SDS_PLATFORM_INFO_OFFSET,
+ &plat_info,
+ N1SDP_SDS_PLATFORM_INFO_SIZE,
+ SDS_ACCESS_MODE_NON_CACHED);
+ if (ret != SDS_OK) {
+ ERROR("Error getting platform info from SDS\n");
+ panic();
+ }
+ /* Validate plat_info SDS */
+ if ((plat_info.local_ddr_size == 0)
+ || (plat_info.local_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB)
+ || (plat_info.remote_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB)
+ || (plat_info.secondary_count > N1SDP_MAX_SECONDARY_COUNT)) {
+ ERROR("platform info SDS is corrupted\n");
+ panic();
+ }
+
+ dmc_ecc_setup(plat_info.local_ddr_size);
+ arm_bl2_platform_setup();
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
new file mode 100644
index 0000000..5e897fe
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/arm/css/css_mhu_doorbell.h>
+#include <drivers/arm/css/scmi.h>
+#include <drivers/arm/css/sds.h>
+#include <drivers/arm/gic600_multichip.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <plat/arm/common/plat_arm.h>
+
+#include "n1sdp_def.h"
+#include <platform_def.h>
+
+/*
+ * Platform information structure stored in SDS.
+ * This structure holds information about platform's DDR
+ * size which will be used to zero out the memory before
+ * enabling the ECC capability as well as information
+ * about multichip setup
+ * - multichip mode
+ * - secondary_count
+ * - Local DDR size in GB, DDR memory in master board
+ * - Remote DDR size in GB, DDR memory in secondary board
+ */
+struct n1sdp_plat_info {
+ bool multichip_mode;
+ uint8_t secondary_count;
+ uint8_t local_ddr_size;
+ uint8_t remote_ddr_size;
+} __packed;
+
+static scmi_channel_plat_info_t n1sdp_scmi_plat_info = {
+ .scmi_mbx_mem = N1SDP_SCMI_PAYLOAD_BASE,
+ .db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF,
+ .db_preserve_mask = 0xfffffffe,
+ .db_modify_mask = 0x1,
+ .ring_doorbell = &mhu_ring_doorbell
+};
+
+static struct gic600_multichip_data n1sdp_multichip_data __init = {
+ .rt_owner_base = PLAT_ARM_GICD_BASE,
+ .rt_owner = 0,
+ .chip_count = 1,
+ .chip_addrs = {
+ PLAT_ARM_GICD_BASE >> 16,
+ PLAT_ARM_GICD_BASE >> 16
+ },
+ .spi_ids = {
+ {32, 479},
+ {512, 959}
+ }
+};
+
+static uintptr_t n1sdp_multichip_gicr_frames[3] = {
+ PLAT_ARM_GICR_BASE,
+ PLAT_ARM_GICR_BASE + PLAT_ARM_REMOTE_CHIP_OFFSET,
+ 0
+};
+
+scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id)
+{
+ return &n1sdp_scmi_plat_info;
+}
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+ return css_scmi_override_pm_ops(ops);
+}
+
+/*
+ * N1SDP platform supports RDIMMs with ECC capability. To use the ECC
+ * capability, the entire DDR memory space has to be zeroed out before
+ * enabling the ECC bits in DMC620. Zeroing out several gigabytes of
+ * memory from SCP is quite time consuming so the following function
+ * is added to zero out the DDR memory from application processor which is
+ * much faster compared to SCP. Local DDR memory is zeroed out during BL2
+ * stage. If remote chip is connected, it's DDR memory is zeroed out here.
+ */
+
+void remote_dmc_ecc_setup(uint8_t remote_ddr_size)
+{
+ uint64_t remote_dram2_size;
+
+ remote_dram2_size = (remote_ddr_size * 1024UL * 1024UL * 1024UL) -
+ N1SDP_REMOTE_DRAM1_SIZE;
+ /* multichip setup */
+ INFO("Zeroing remote DDR memories\n");
+ zero_normalmem((void *)N1SDP_REMOTE_DRAM1_BASE,
+ N1SDP_REMOTE_DRAM1_SIZE);
+ flush_dcache_range(N1SDP_REMOTE_DRAM1_BASE, N1SDP_REMOTE_DRAM1_SIZE);
+ zero_normalmem((void *)N1SDP_REMOTE_DRAM2_BASE, remote_dram2_size);
+ flush_dcache_range(N1SDP_REMOTE_DRAM2_BASE, remote_dram2_size);
+
+ INFO("Enabling ECC on remote DMCs\n");
+ /* Set DMCs to CONFIG state before writing ERR0CTLR0 register */
+ mmio_write_32(N1SDP_REMOTE_DMC0_MEMC_CMD_REG,
+ N1SDP_DMC_MEMC_CMD_CONFIG);
+ mmio_write_32(N1SDP_REMOTE_DMC1_MEMC_CMD_REG,
+ N1SDP_DMC_MEMC_CMD_CONFIG);
+
+ /* Enable ECC in DMCs */
+ mmio_setbits_32(N1SDP_REMOTE_DMC0_ERR0CTLR0_REG,
+ N1SDP_DMC_ERR0CTLR0_ECC_EN);
+ mmio_setbits_32(N1SDP_REMOTE_DMC1_ERR0CTLR0_REG,
+ N1SDP_DMC_ERR0CTLR0_ECC_EN);
+
+ /* Set DMCs to READY state */
+ mmio_write_32(N1SDP_REMOTE_DMC0_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY);
+ mmio_write_32(N1SDP_REMOTE_DMC1_MEMC_CMD_REG, N1SDP_DMC_MEMC_CMD_READY);
+}
+
+void n1sdp_bl31_multichip_setup(void)
+{
+ plat_arm_override_gicr_frames(n1sdp_multichip_gicr_frames);
+ gic600_multichip_init(&n1sdp_multichip_data);
+}
+
+void bl31_platform_setup(void)
+{
+ int ret;
+ struct n1sdp_plat_info plat_info;
+
+ ret = sds_init();
+ if (ret != SDS_OK) {
+ ERROR("SDS initialization failed\n");
+ panic();
+ }
+
+ ret = sds_struct_read(N1SDP_SDS_PLATFORM_INFO_STRUCT_ID,
+ N1SDP_SDS_PLATFORM_INFO_OFFSET,
+ &plat_info,
+ N1SDP_SDS_PLATFORM_INFO_SIZE,
+ SDS_ACCESS_MODE_NON_CACHED);
+ if (ret != SDS_OK) {
+ ERROR("Error getting platform info from SDS\n");
+ panic();
+ }
+ /* Validate plat_info SDS */
+ if ((plat_info.local_ddr_size == 0)
+ || (plat_info.local_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB)
+ || (plat_info.remote_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB)
+ || (plat_info.secondary_count > N1SDP_MAX_SECONDARY_COUNT)) {
+ ERROR("platform info SDS is corrupted\n");
+ panic();
+ }
+
+ if (plat_info.multichip_mode) {
+ n1sdp_multichip_data.chip_count = plat_info.secondary_count + 1;
+ n1sdp_bl31_multichip_setup();
+ }
+ arm_bl31_platform_setup();
+
+ /* Check if remote memory is present */
+ if ((plat_info.multichip_mode) && (plat_info.remote_ddr_size != 0))
+ remote_dmc_ecc_setup(plat_info.remote_ddr_size);
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_def.h b/plat/arm/board/n1sdp/n1sdp_def.h
new file mode 100644
index 0000000..ffa6a03
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_def.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef N1SDP_DEF_H
+#define N1SDP_DEF_H
+
+/* Non-secure SRAM MMU mapping */
+#define N1SDP_NS_SRAM_BASE (0x06000000)
+#define N1SDP_NS_SRAM_SIZE (0x00010000)
+#define N1SDP_MAP_NS_SRAM MAP_REGION_FLAT( \
+ N1SDP_NS_SRAM_BASE, \
+ N1SDP_NS_SRAM_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+/* SDS Platform information defines */
+#define N1SDP_SDS_PLATFORM_INFO_STRUCT_ID 8
+#define N1SDP_SDS_PLATFORM_INFO_OFFSET 0
+#define N1SDP_SDS_PLATFORM_INFO_SIZE 4
+#define N1SDP_MAX_DDR_CAPACITY_GB 64
+#define N1SDP_MAX_SECONDARY_COUNT 16
+
+/* DMC memory command registers */
+#define N1SDP_DMC0_MEMC_CMD_REG 0x4E000008
+#define N1SDP_DMC1_MEMC_CMD_REG 0x4E100008
+
+/* DMC ERR0CTLR0 registers */
+#define N1SDP_DMC0_ERR0CTLR0_REG 0x4E000708
+#define N1SDP_DMC1_ERR0CTLR0_REG 0x4E100708
+
+/* Remote DMC memory command registers */
+#define N1SDP_REMOTE_DMC0_MEMC_CMD_REG PLAT_ARM_REMOTE_CHIP_OFFSET +\
+ N1SDP_DMC0_MEMC_CMD_REG
+#define N1SDP_REMOTE_DMC1_MEMC_CMD_REG PLAT_ARM_REMOTE_CHIP_OFFSET +\
+ N1SDP_DMC1_MEMC_CMD_REG
+
+/* Remote DMC ERR0CTLR0 registers */
+#define N1SDP_REMOTE_DMC0_ERR0CTLR0_REG PLAT_ARM_REMOTE_CHIP_OFFSET +\
+ N1SDP_DMC0_ERR0CTLR0_REG
+#define N1SDP_REMOTE_DMC1_ERR0CTLR0_REG PLAT_ARM_REMOTE_CHIP_OFFSET +\
+ N1SDP_DMC1_ERR0CTLR0_REG
+
+/* DMC memory commands */
+#define N1SDP_DMC_MEMC_CMD_CONFIG 0
+#define N1SDP_DMC_MEMC_CMD_READY 3
+
+/* DMC ECC enable bit in ERR0CTLR0 register */
+#define N1SDP_DMC_ERR0CTLR0_ECC_EN 0x1
+
+#endif /* N1SDP_DEF_H */
diff --git a/plat/arm/board/n1sdp/n1sdp_err.c b/plat/arm/board/n1sdp/n1sdp_err.c
new file mode 100644
index 0000000..629e76a
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_err.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * n1sdp error handler
+ */
+void __dead2 plat_arm_error_handler(int err)
+{
+ while (true) {
+ wfi();
+ }
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_image_load.c b/plat/arm/board/n1sdp/n1sdp_image_load.c
new file mode 100644
index 0000000..6c3528c
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_image_load.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/arm/css/sds.h>
+#include <libfdt.h>
+#include <plat/common/platform.h>
+
+#include "n1sdp_def.h"
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Platform information structure stored in SDS.
+ * This structure holds information about platform's DDR
+ * size which will be used to zero out the memory before
+ * enabling the ECC capability as well as information
+ * about multichip setup
+ * - multichip mode
+ * - secondary_count
+ * - Local DDR size in GB, DDR memory in master board
+ * - Remote DDR size in GB, DDR memory in secondary board
+ */
+struct n1sdp_plat_info {
+ bool multichip_mode;
+ uint8_t secondary_count;
+ uint8_t local_ddr_size;
+ uint8_t remote_ddr_size;
+} __packed;
+
+/*******************************************************************************
+ * This function inserts Platform information via device tree nodes as,
+ * platform-info {
+ * multichip-mode = <0x0>;
+ * secondary-chip-count = <0x0>;
+ * local-ddr-size = <0x0>;
+ * remote-ddr-size = <0x0>;
+ * };
+ ******************************************************************************/
+static int plat_n1sdp_append_config_node(struct n1sdp_plat_info *plat_info)
+{
+ bl_mem_params_node_t *mem_params;
+ void *fdt;
+ int nodeoffset, err;
+
+ mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID);
+ if (mem_params == NULL) {
+ ERROR("NT_FW CONFIG base address is NULL\n");
+ return -1;
+ }
+
+ fdt = (void *)(mem_params->image_info.image_base);
+
+ /* Check the validity of the fdt */
+ if (fdt_check_header(fdt) != 0) {
+ ERROR("Invalid NT_FW_CONFIG DTB passed\n");
+ return -1;
+ }
+
+ nodeoffset = fdt_subnode_offset(fdt, 0, "platform-info");
+ if (nodeoffset < 0) {
+ ERROR("NT_FW_CONFIG: Failed to get platform-info node offset\n");
+ return -1;
+ }
+
+ err = fdt_setprop_u32(fdt, nodeoffset, "multichip-mode",
+ plat_info->multichip_mode);
+ if (err < 0) {
+ ERROR("NT_FW_CONFIG: Failed to set multichip-mode\n");
+ return -1;
+ }
+
+ err = fdt_setprop_u32(fdt, nodeoffset, "secondary-chip-count",
+ plat_info->secondary_count);
+ if (err < 0) {
+ ERROR("NT_FW_CONFIG: Failed to set secondary-chip-count\n");
+ return -1;
+ }
+
+ err = fdt_setprop_u32(fdt, nodeoffset, "local-ddr-size",
+ plat_info->local_ddr_size);
+ if (err < 0) {
+ ERROR("NT_FW_CONFIG: Failed to set local-ddr-size\n");
+ return -1;
+ }
+
+ err = fdt_setprop_u32(fdt, nodeoffset, "remote-ddr-size",
+ plat_info->remote_ddr_size);
+ if (err < 0) {
+ ERROR("NT_FW_CONFIG: Failed to set remote-ddr-size\n");
+ return -1;
+ }
+
+ flush_dcache_range((uintptr_t)fdt, mem_params->image_info.image_size);
+
+ return 0;
+}
+
+/*******************************************************************************
+ * This function returns the list of executable images.
+ ******************************************************************************/
+bl_params_t *plat_get_next_bl_params(void)
+{
+ int ret;
+ struct n1sdp_plat_info plat_info;
+
+ ret = sds_init();
+ if (ret != SDS_OK) {
+ ERROR("SDS initialization failed. ret:%d\n", ret);
+ panic();
+ }
+
+ ret = sds_struct_read(N1SDP_SDS_PLATFORM_INFO_STRUCT_ID,
+ N1SDP_SDS_PLATFORM_INFO_OFFSET,
+ &plat_info,
+ N1SDP_SDS_PLATFORM_INFO_SIZE,
+ SDS_ACCESS_MODE_NON_CACHED);
+ if (ret != SDS_OK) {
+ ERROR("Error getting platform info from SDS. ret:%d\n", ret);
+ panic();
+ }
+
+ /* Validate plat_info SDS */
+ if ((plat_info.local_ddr_size == 0U)
+ || (plat_info.local_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB)
+ || (plat_info.remote_ddr_size > N1SDP_MAX_DDR_CAPACITY_GB)
+ || (plat_info.secondary_count > N1SDP_MAX_SECONDARY_COUNT)
+ ){
+ ERROR("platform info SDS is corrupted\n");
+ panic();
+ }
+
+ ret = plat_n1sdp_append_config_node(&plat_info);
+ if (ret != 0) {
+ panic();
+ }
+
+ return arm_get_next_bl_params();
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_interconnect.c b/plat/arm/board/n1sdp/n1sdp_interconnect.c
new file mode 100644
index 0000000..908f41c
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_interconnect.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+/*
+ * For N1SDP which support FCM (with automatic interconnect enter/exit),
+ * we should not do anything in these interface functions.
+ * They are used to override the weak functions in cci drivers.
+ */
+
+/******************************************************************************
+ * Helper function to initialize ARM interconnect driver.
+ *****************************************************************************/
+void plat_arm_interconnect_init(void)
+{
+}
+
+/******************************************************************************
+ * Helper function to place current master into coherency
+ *****************************************************************************/
+void plat_arm_interconnect_enter_coherency(void)
+{
+}
+
+/******************************************************************************
+ * Helper function to remove current master from coherency
+ *****************************************************************************/
+void plat_arm_interconnect_exit_coherency(void)
+{
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_plat.c b/plat/arm/board/n1sdp/n1sdp_plat.c
new file mode 100644
index 0000000..502268c
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_plat.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <drivers/arm/sbsa.h>
+#include <plat/arm/common/plat_arm.h>
+
+#include "n1sdp_def.h"
+
+/*
+ * Table of regions to map using the MMU.
+ * Replace or extend the below regions as required
+ */
+
+#if IMAGE_BL1
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ N1SDP_MAP_DEVICE,
+ N1SDP_MAP_NS_SRAM,
+ ARM_MAP_DRAM1,
+ {0}
+};
+#endif
+
+#if IMAGE_BL2
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ N1SDP_MAP_DEVICE,
+ N1SDP_MAP_NS_SRAM,
+ ARM_MAP_DRAM1,
+ ARM_MAP_DRAM2,
+#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3
+ ARM_MAP_BL1_RW,
+#endif
+ {0}
+};
+#endif
+
+#if IMAGE_BL31
+const mmap_region_t plat_arm_mmap[] = {
+ ARM_MAP_SHARED_RAM,
+ N1SDP_MAP_DEVICE,
+ N1SDP_MAP_NS_SRAM,
+ N1SDP_MAP_REMOTE_DEVICE,
+ N1SDP_MAP_REMOTE_DRAM1,
+ N1SDP_MAP_REMOTE_DRAM2,
+ {0}
+};
+#endif
+
+#if TRUSTED_BOARD_BOOT
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+ assert(heap_addr != NULL);
+ assert(heap_size != NULL);
+
+ return arm_get_mbedtls_heap(heap_addr, heap_size);
+}
+#endif
+
+void plat_arm_secure_wdt_start(void)
+{
+ sbsa_wdog_start(SBSA_SECURE_WDOG_BASE, SBSA_SECURE_WDOG_TIMEOUT);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+ sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE);
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_security.c b/plat/arm/board/n1sdp/n1sdp_security.c
new file mode 100644
index 0000000..d2a187b
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_security.c
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * TZC programming is currently not done.
+ */
+void plat_arm_security_setup(void)
+{
+}
diff --git a/plat/arm/board/n1sdp/n1sdp_topology.c b/plat/arm/board/n1sdp/n1sdp_topology.c
new file mode 100644
index 0000000..5c2db71
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_topology.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/* Topology */
+typedef struct n1sdp_topology {
+ const unsigned char *power_tree;
+ unsigned int plat_cluster_core_count;
+} n1sdp_topology_t;
+
+/*
+ * 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[] = {
+ PLAT_N1SDP_CHIP_COUNT,
+ PLAT_ARM_CLUSTER_COUNT,
+ PLAT_ARM_CLUSTER_COUNT,
+ N1SDP_MAX_CPUS_PER_CLUSTER,
+ N1SDP_MAX_CPUS_PER_CLUSTER,
+ N1SDP_MAX_CPUS_PER_CLUSTER,
+ N1SDP_MAX_CPUS_PER_CLUSTER
+};
+
+/* Topology configuration for n1sdp */
+const n1sdp_topology_t n1sdp_topology = {
+ .power_tree = n1sdp_pd_tree_desc,
+ .plat_cluster_core_count = N1SDP_MAX_CPUS_PER_CLUSTER
+};
+
+/*******************************************************************************
+ * This function returns the topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+ return n1sdp_topology.power_tree;
+}
+
+/*******************************************************************************
+ * This function returns the core count within the cluster corresponding to
+ * `mpidr`.
+ ******************************************************************************/
+unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr)
+{
+ return n1sdp_topology.plat_cluster_core_count;
+}
+
+/*******************************************************************************
+ * The array mapping platform core position (implemented by plat_my_core_pos())
+ * to the SCMI power domain ID implemented by SCP.
+ ******************************************************************************/
+const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[PLATFORM_CORE_COUNT] = {
+ 0, 1, 2, 3, 4, 5, 6, 7};
diff --git a/plat/arm/board/n1sdp/n1sdp_trusted_boot.c b/plat/arm/board/n1sdp/n1sdp_trusted_boot.c
new file mode 100644
index 0000000..c7dc47f
--- /dev/null
+++ b/plat/arm/board/n1sdp/n1sdp_trusted_boot.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Return the non-volatile counter value stored in the platform. The cookie
+ * will contain the OID of the counter in the certificate.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ *nv_ctr = N1SDP_FW_NVCTR_VAL;
+ return 0;
+}
+
+/*
+ * Store a new non-volatile counter value. By default on ARM development
+ * platforms, the non-volatile counters are RO and cannot be modified. We expect
+ * the values in the certificates to always match the RO values so that this
+ * function is never called.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ return 1;
+}
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
+
diff --git a/plat/arm/board/n1sdp/platform.mk b/plat/arm/board/n1sdp/platform.mk
new file mode 100644
index 0000000..9c0cc02
--- /dev/null
+++ b/plat/arm/board/n1sdp/platform.mk
@@ -0,0 +1,111 @@
+#
+# Copyright (c) 2018-2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+
+N1SDP_BASE := plat/arm/board/n1sdp
+
+INTERCONNECT_SOURCES := ${N1SDP_BASE}/n1sdp_interconnect.c
+
+PLAT_INCLUDES := -I${N1SDP_BASE}/include
+
+
+N1SDP_CPU_SOURCES := lib/cpus/aarch64/neoverse_n1.S
+
+# GIC-600 configuration
+GICV3_SUPPORT_GIC600 := 1
+GICV3_IMPL_GIC600_MULTICHIP := 1
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+N1SDP_GIC_SOURCES := ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ plat/arm/common/arm_gicv3.c \
+
+PLAT_BL_COMMON_SOURCES := ${N1SDP_BASE}/n1sdp_plat.c \
+ ${N1SDP_BASE}/aarch64/n1sdp_helper.S
+
+BL1_SOURCES := ${N1SDP_CPU_SOURCES} \
+ ${INTERCONNECT_SOURCES} \
+ ${N1SDP_BASE}/n1sdp_err.c \
+ ${N1SDP_BASE}/n1sdp_trusted_boot.c \
+ ${N1SDP_BASE}/n1sdp_bl1_setup.c \
+ drivers/arm/sbsa/sbsa.c
+
+BL2_SOURCES := ${N1SDP_BASE}/n1sdp_security.c \
+ ${N1SDP_BASE}/n1sdp_err.c \
+ ${N1SDP_BASE}/n1sdp_trusted_boot.c \
+ lib/utils/mem_region.c \
+ ${N1SDP_BASE}/n1sdp_bl2_setup.c \
+ ${N1SDP_BASE}/n1sdp_image_load.c \
+ drivers/arm/css/sds/sds.c
+
+BL31_SOURCES := ${N1SDP_CPU_SOURCES} \
+ ${INTERCONNECT_SOURCES} \
+ ${N1SDP_GIC_SOURCES} \
+ ${N1SDP_BASE}/n1sdp_bl31_setup.c \
+ ${N1SDP_BASE}/n1sdp_topology.c \
+ ${N1SDP_BASE}/n1sdp_security.c \
+ drivers/arm/css/sds/sds.c
+
+FDT_SOURCES += fdts/${PLAT}-single-chip.dts \
+ fdts/${PLAT}-multi-chip.dts \
+ ${N1SDP_BASE}/fdts/n1sdp_fw_config.dts \
+ ${N1SDP_BASE}/fdts/n1sdp_tb_fw_config.dts \
+ ${N1SDP_BASE}/fdts/n1sdp_nt_fw_config.dts
+
+FW_CONFIG := ${BUILD_PLAT}/fdts/n1sdp_fw_config.dtb
+TB_FW_CONFIG := ${BUILD_PLAT}/fdts/n1sdp_tb_fw_config.dtb
+NT_FW_CONFIG := ${BUILD_PLAT}/fdts/n1sdp_nt_fw_config.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG}))
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG}))
+# Add the NT_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config,${NT_FW_CONFIG}))
+
+N1SDP_SPMC_MANIFEST_DTS := ${N1SDP_BASE}/fdts/${PLAT}_optee_spmc_manifest.dts
+FDT_SOURCES += ${N1SDP_SPMC_MANIFEST_DTS}
+N1SDP_TOS_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_optee_spmc_manifest.dtb
+
+# Add the TOS_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${N1SDP_TOS_FW_CONFIG},--tos-fw-config,${N1SDP_TOS_FW_CONFIG}))
+
+# Setting to 0 as no NVCTR in N1SDP
+N1SDP_FW_NVCTR_VAL := 0
+TFW_NVCTR_VAL := ${N1SDP_FW_NVCTR_VAL}
+NTFW_NVCTR_VAL := ${N1SDP_FW_NVCTR_VAL}
+
+# Add N1SDP_FW_NVCTR_VAL
+$(eval $(call add_define,N1SDP_FW_NVCTR_VAL))
+
+# TF-A not required to load the SCP Images
+override CSS_LOAD_SCP_IMAGES := 0
+
+override NEED_BL2U := no
+
+# 32 bit mode not supported
+override CTX_INCLUDE_AARCH32_REGS := 0
+
+override ARM_PLAT_MT := 1
+
+# Select SCMI/SDS drivers instead of SCPI/BOM driver for communicating with the
+# SCP during power management operations and for SCP RAM Firmware transfer.
+CSS_USE_SCMI_SDS_DRIVER := 1
+
+# System coherency is managed in hardware
+HW_ASSISTED_COHERENCY := 1
+
+# When building for systems with hardware-assisted coherency, there's no need to
+# use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too.
+USE_COHERENT_MEM := 0
+
+# Enable the flag since N1SDP has a system level cache
+NEOVERSE_Nx_EXTERNAL_LLC := 1
+include plat/arm/common/arm_common.mk
+include plat/arm/css/common/css_common.mk
+include plat/arm/board/common/board_common.mk