Merge "feat(fvp): define ns memory in the SPMC manifest" into integration
diff --git a/Makefile b/Makefile
index 892c2c9..7368ca5 100644
--- a/Makefile
+++ b/Makefile
@@ -1212,6 +1212,7 @@
         TWED_DELAY \
         ENABLE_FEAT_TWED \
         SVE_VECTOR_LEN \
+	IMPDEF_SYSREG_TRAP \
 )))
 
 ifdef KEY_SIZE
@@ -1343,6 +1344,7 @@
         TWED_DELAY \
         ENABLE_FEAT_TWED \
 	CONDITIONAL_CMO \
+	IMPDEF_SYSREG_TRAP \
 )))
 
 ifeq (${SANITIZE_UB},trap)
diff --git a/bl31/bl31_traps.c b/bl31/bl31_traps.c
index b12185d..2cfe14a 100644
--- a/bl31/bl31_traps.c
+++ b/bl31/bl31_traps.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2022, ARM Limited. All rights reserved.
+ * Copyright (c) 2023, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -11,13 +12,19 @@
 
 int handle_sysreg_trap(uint64_t esr_el3, cpu_context_t *ctx)
 {
-	switch (esr_el3 & ISS_SYSREG_OPCODE_MASK) {
+	uint64_t __unused opcode = esr_el3 & ISS_SYSREG_OPCODE_MASK;
+
 #if ENABLE_FEAT_RNG_TRAP
-	case ISS_SYSREG_OPCODE_RNDR:
-	case ISS_SYSREG_OPCODE_RNDRRS:
+	if ((opcode == ISS_SYSREG_OPCODE_RNDR) || (opcode == ISS_SYSREG_OPCODE_RNDRRS)) {
 		return plat_handle_rng_trap(esr_el3, ctx);
+	}
 #endif
-	default:
-		return TRAP_RET_UNHANDLED;
+
+#if IMPDEF_SYSREG_TRAP
+	if ((opcode & ISS_SYSREG_OPCODE_IMPDEF) == ISS_SYSREG_OPCODE_IMPDEF) {
+		return plat_handle_impdef_trap(esr_el3, ctx);
 	}
+#endif
+
+	return TRAP_RET_UNHANDLED;
 }
diff --git a/docs/components/secure-partition-manager.rst b/docs/components/secure-partition-manager.rst
index f0caf89..8dc1c61 100644
--- a/docs/components/secure-partition-manager.rst
+++ b/docs/components/secure-partition-manager.rst
@@ -1318,6 +1318,25 @@
        direct request to SP2 by invoking FFA_RUN.
   - 9) SPMC resumes the pre-empted vCPU of SP2.
 
+EL3 interrupt handling
+~~~~~~~~~~~~~~~~~~~~~~
+
+In GICv3 based systems, EL3 interrupts are configured as Group0 secure
+interrupts. Execution traps to SPMC when a Group0 interrupt triggers while an
+SP is running. Further, SPMC running at S-EL2 uses FFA_EL3_INTR_HANDLE ABI to
+request EL3 platform firmware to handle a pending Group0 interrupt.
+Similarly, SPMD registers a handler with interrupt management framework to
+delegate handling of Group0 interrupt to the platform if the interrupt triggers
+in normal world.
+
+ - Platform hook
+
+   - plat_spmd_handle_group0_interrupt
+
+     SPMD provides platform hook to handle Group0 secure interrupts. In the
+     current design, SPMD expects the platform not to delegate handling to the
+     NWd (such as through SDEI) while processing Group0 interrupts.
+
 Power management
 ----------------
 
@@ -1557,4 +1576,4 @@
 
 --------------
 
-*Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2020-2023, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/design_documents/measured_boot_poc.rst b/docs/design_documents/measured_boot_poc.rst
index 2e25057..7f73d7e 100644
--- a/docs/design_documents/measured_boot_poc.rst
+++ b/docs/design_documents/measured_boot_poc.rst
@@ -135,11 +135,11 @@
 
 (4) Now, you should be able to continue with step 5 in "`Get and build the solution`_"
     instructions. In order to enable support for Measured Boot, you need to
-    set the ``MEASURED_BOOT`` build option:
+    set the following build options:
 
     .. code:: shell
 
-       $ MEASURED_BOOT=y make -j `nproc`
+       $ MEASURED_BOOT=y MEASURED_BOOT_FTPM=y make -j `nproc`
 
     .. note::
        The build process will likely take a long time. It is strongly recommended to
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 2229591..2735f17 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -640,6 +640,10 @@
    translation library (xlat tables v2) must be used; version 1 of translation
    library is not supported.
 
+-  ``IMPDEF_SYSREG_TRAP``: Numeric value to enable the handling traps for
+   implementation defined system register accesses from lower ELs. Default
+   value is ``0``.
+
 -  ``INVERTED_MEMMAP``: memmap tool print by default lower addresses at the
    bottom, higher addresses at the top. This build flag can be set to '1' to
    invert this behavior. Lower addresses will be printed at the top and higher
diff --git a/docs/plat/allwinner.rst b/docs/plat/allwinner.rst
index 3e9ce51..8e967dc 100644
--- a/docs/plat/allwinner.rst
+++ b/docs/plat/allwinner.rst
@@ -23,6 +23,8 @@
 +------+-------------------+
 | H313 | sun50i_h616       |
 +------+-------------------+
+| T507 | sun50i_h616       |
++------+-------------------+
 | R329 | sun50i_r329       |
 +------+-------------------+
 
diff --git a/docs/plat/index.rst b/docs/plat/index.rst
index a4e2067..57c7303 100644
--- a/docs/plat/index.rst
+++ b/docs/plat/index.rst
@@ -76,7 +76,9 @@
 +----------------+----------------+--------------------+--------------------+
 |    tc0         |      Arm       |        2.8         |       3.0          |
 +----------------+----------------+--------------------+--------------------+
+|    rde1edge    |      Arm       |        2.9         |       3.1          |
++----------------+----------------+--------------------+--------------------+
 
 --------------
 
-*Copyright (c) 2019-2022, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2023, Arm Limited. All rights reserved.*
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index 25b55e8..1225a9f 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -2785,6 +2785,22 @@
 by the ``MPIDR`` (first argument). The generic code expects the platform to
 return PSCI_E_SUCCESS on success or PSCI_E_INTERN_FAIL for any failure.
 
+plat_psci_ops.pwr_domain_off_early() [optional]
+...............................................
+
+This optional function performs the platform specific actions to check if
+powering off the calling CPU and its higher parent power domain levels as
+indicated by the ``target_state`` (first argument) is possible or allowed.
+
+The ``target_state`` encodes the platform coordinated target local power states
+for the CPU power domain and its parent power domain levels.
+
+For this handler, the local power state for the CPU power domain will be a
+power down state where as it could be either power down, retention or run state
+for the higher power domain levels depending on the result of state
+coordination. The generic code expects PSCI_E_DENIED return code if the
+platform thinks that CPU_OFF should not proceed on the calling CPU.
+
 plat_psci_ops.pwr_domain_off()
 ..............................
 
@@ -3502,6 +3518,38 @@
 
 This function needs to be implemented by a platform if it enables FEAT_RNG_TRAP.
 
+Function : plat_handle_impdef_trap
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : uint64_t
+    Argument : cpu_context_t *
+    Return   : int
+
+This function is invoked by BL31's exception handler when there is a synchronous
+system register trap caused by access to the implementation defined registers.
+It allows platforms enabling ``IMPDEF_SYSREG_TRAP`` to emulate those system
+registers choosing to program bits of their choice.
+
+The first parameter (``uint64_t esr_el3``) contains the content of the ESR_EL3
+syndrome register, which encodes the instruction that was trapped.
+
+The second parameter (``cpu_context_t *ctx``) represents the CPU state in the
+lower exception level, at the time when the execution of the ``mrs`` instruction
+was trapped.
+
+The return value indicates how to proceed:
+
+-  When returning ``TRAP_RET_UNHANDLED`` (-1), the machine will panic.
+-  When returning ``TRAP_RET_REPEAT`` (0), the exception handler will return
+   to the same instruction, so its execution will be repeated.
+-  When returning ``TRAP_RET_CONTINUE`` (1), the exception handler will return
+   to the next instruction.
+
+This function needs to be implemented by a platform if it enables
+IMPDEF_SYSREG_TRAP.
+
 Build flags
 -----------
 
diff --git a/include/bl31/sync_handle.h b/include/bl31/sync_handle.h
index e211575..1ac4f98 100644
--- a/include/bl31/sync_handle.h
+++ b/include/bl31/sync_handle.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2022, ARM Limited. All rights reserved.
+ * Copyright (c) 2023, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,6 +17,7 @@
 #define ISS_SYSREG_DIRECTION_MASK	0x000001UL
 
 #define ISS_SYSREG_OPCODE_RNDR		0x30c808U
+#define ISS_SYSREG_OPCODE_IMPDEF	0x303c00U
 #define ISS_SYSREG_OPCODE_RNDRRS	0x32c808U
 
 #define TRAP_RET_UNHANDLED		-1
@@ -54,6 +56,7 @@
 int handle_sysreg_trap(uint64_t esr_el3, cpu_context_t *ctx);
 
 /* Prototypes for system register emulation handlers provided by platforms. */
+int plat_handle_impdef_trap(uint64_t esr_el3, cpu_context_t *ctx);
 int plat_handle_rng_trap(uint64_t esr_el3, cpu_context_t *ctx);
 
 #endif /* __ASSEMBLER__ */
diff --git a/include/lib/psci/psci.h b/include/lib/psci/psci.h
index 6d27b7b..4d7e58e 100644
--- a/include/lib/psci/psci.h
+++ b/include/lib/psci/psci.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2023, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -317,6 +318,7 @@
 	void (*cpu_standby)(plat_local_state_t cpu_state);
 	int (*pwr_domain_on)(u_register_t mpidr);
 	void (*pwr_domain_off)(const psci_power_state_t *target_state);
+	int (*pwr_domain_off_early)(const psci_power_state_t *target_state);
 	void (*pwr_domain_suspend_pwrdown_early)(
 				const psci_power_state_t *target_state);
 #if PSCI_OS_INIT_MODE
diff --git a/include/services/ffa_svc.h b/include/services/ffa_svc.h
index 8bc911a..64af437 100644
--- a/include/services/ffa_svc.h
+++ b/include/services/ffa_svc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -24,7 +24,7 @@
 
 /* The macros below are used to identify FFA calls from the SMC function ID */
 #define FFA_FNUM_MIN_VALUE	U(0x60)
-#define FFA_FNUM_MAX_VALUE	U(0x8B)
+#define FFA_FNUM_MAX_VALUE	U(0x8C)
 #define is_ffa_fid(fid) __extension__ ({		\
 	__typeof__(fid) _fid = (fid);			\
 	((GET_SMC_NUM(_fid) >= FFA_FNUM_MIN_VALUE) &&	\
@@ -118,6 +118,7 @@
 #define FFA_FNUM_MSG_SEND2			U(0x86)
 #define FFA_FNUM_SECONDARY_EP_REGISTER		U(0x87)
 #define FFA_FNUM_PARTITION_INFO_GET_REGS	U(0x8B)
+#define FFA_FNUM_EL3_INTR_HANDLE		U(0x8C)
 
 /* FFA SMC32 FIDs */
 #define FFA_ERROR		FFA_FID(SMC_32, FFA_FNUM_ERROR)
@@ -163,6 +164,7 @@
 #define FFA_MEM_FRAG_TX	FFA_FID(SMC_32, FFA_FNUM_MEM_FRAG_TX)
 #define FFA_SPM_ID_GET		FFA_FID(SMC_32, FFA_FNUM_SPM_ID_GET)
 #define FFA_NORMAL_WORLD_RESUME	FFA_FID(SMC_32, FFA_FNUM_NORMAL_WORLD_RESUME)
+#define FFA_EL3_INTR_HANDLE	FFA_FID(SMC_32, FFA_FNUM_EL3_INTR_HANDLE)
 
 /* FFA SMC64 FIDs */
 #define FFA_ERROR_SMC64		FFA_FID(SMC_64, FFA_FNUM_ERROR)
diff --git a/lib/cpus/aarch64/cortex_x1.S b/lib/cpus/aarch64/cortex_x1.S
index 9a7f666..de65365 100644
--- a/lib/cpus/aarch64/cortex_x1.S
+++ b/lib/cpus/aarch64/cortex_x1.S
@@ -37,7 +37,7 @@
 	bl	check_errata_1821534
 	cbz	x0, 1f
 	mrs	x1, CORTEX_X1_ACTLR2_EL1
-	orr	x1, x1, BIT(2)
+	orr	x1, x1, #BIT(2)
 	msr	CORTEX_X1_ACTLR2_EL1, x1
 	isb
 1:
@@ -64,7 +64,7 @@
 	bl	check_errata_1688305
 	cbz	x0, 1f
 	mrs	x0, CORTEX_X1_ACTLR2_EL1
-	orr	x0, x0, BIT(1)
+	orr	x0, x0, #BIT(1)
 	msr	CORTEX_X1_ACTLR2_EL1, x0
 	isb
 
@@ -92,7 +92,7 @@
 	bl	check_errata_1827429
 	cbz	x0, 1f
 	mrs	x0, CORTEX_X1_CPUECTLR_EL1
-	orr	x0, x0, BIT(53)
+	orr	x0, x0, #BIT(53)
 	msr	CORTEX_X1_CPUECTLR_EL1, x0
 	isb
 
diff --git a/lib/cpus/aarch64/runtime_errata.S b/lib/psci/aarch64/runtime_errata.S
similarity index 100%
rename from lib/cpus/aarch64/runtime_errata.S
rename to lib/psci/aarch64/runtime_errata.S
diff --git a/lib/psci/psci_lib.mk b/lib/psci/psci_lib.mk
index 6864202..c71580f 100644
--- a/lib/psci/psci_lib.mk
+++ b/lib/psci/psci_lib.mk
@@ -22,7 +22,7 @@
 
 ifeq (${ARCH}, aarch64)
 PSCI_LIB_SOURCES	+=	lib/el3_runtime/aarch64/context.S	\
-				lib/cpus/aarch64/runtime_errata.S
+				lib/psci/aarch64/runtime_errata.S
 endif
 
 ifeq (${USE_COHERENT_MEM}, 1)
diff --git a/lib/psci/psci_off.c b/lib/psci/psci_off.c
index 637adb9..9f36ac7 100644
--- a/lib/psci/psci_off.c
+++ b/lib/psci/psci_off.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2023, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -57,6 +58,19 @@
 	psci_set_power_off_state(&state_info);
 
 	/*
+	 * Call the platform provided early CPU_OFF handler to allow
+	 * platforms to perform any housekeeping activities before
+	 * actually powering the CPU off. PSCI_E_DENIED indicates that
+	 * the CPU off sequence should be aborted at this time.
+	 */
+	if (psci_plat_pm_ops->pwr_domain_off_early) {
+		rc = psci_plat_pm_ops->pwr_domain_off_early(&state_info);
+		if (rc == PSCI_E_DENIED) {
+			return rc;
+		}
+	}
+
+	/*
 	 * Get the parent nodes here, this is important to do before we
 	 * initiate the power down sequence as after that point the core may
 	 * have exited coherency and its cache may be disabled, any access to
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index 9ca6bdf..0c82a71 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -326,7 +326,10 @@
 
 $(eval OBJ := $(1)/$(patsubst %.c,%.o,$(notdir $(2))))
 $(eval DEP := $(patsubst %.o,%.d,$(OBJ)))
-$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) -DIMAGE_$(call uppercase,$(3)))
+
+$(eval BL_DEFINES := $($(call uppercase,$(3))_DEFINES))
+$(eval BL_INCLUDE_DIRS := $($(call uppercase,$(3))_INCLUDE_DIRS))
+$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) -DIMAGE_$(call uppercase,$(3)) $(addprefix -D,$(BL_DEFINES)) $(addprefix -I,$(BL_INCLUDE_DIRS)))
 $(eval BL_CFLAGS := $($(call uppercase,$(3))_CFLAGS))
 
 $(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs
@@ -346,7 +349,10 @@
 
 $(eval OBJ := $(1)/$(patsubst %.S,%.o,$(notdir $(2))))
 $(eval DEP := $(patsubst %.o,%.d,$(OBJ)))
-$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) -DIMAGE_$(call uppercase,$(3)))
+
+$(eval BL_DEFINES := $($(call uppercase,$(3))_DEFINES))
+$(eval BL_INCLUDE_DIRS := $($(call uppercase,$(3))_INCLUDE_DIRS))
+$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) -DIMAGE_$(call uppercase,$(3)) $(addprefix -D,$(BL_DEFINES)) $(addprefix -I,$(BL_INCLUDE_DIRS)))
 $(eval BL_ASFLAGS := $($(call uppercase,$(3))_ASFLAGS))
 
 $(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs
@@ -365,7 +371,10 @@
 define MAKE_LD
 
 $(eval DEP := $(1).d)
-$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) -DIMAGE_$(call uppercase,$(3)))
+
+$(eval BL_DEFINES := $($(call uppercase,$(3))_DEFINES))
+$(eval BL_INCLUDE_DIRS := $($(call uppercase,$(3))_INCLUDE_DIRS))
+$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) -DIMAGE_$(call uppercase,$(3)) $(addprefix -D,$(BL_DEFINES)) $(addprefix -I,$(BL_INCLUDE_DIRS)))
 
 $(1): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs
 	$$(ECHO) "  PP      $$<"
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 021893c..8ec16fa 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -243,6 +243,9 @@
 # operations.
 HW_ASSISTED_COHERENCY		:= 0
 
+# Flag to enable trapping of implementation defined sytem registers
+IMPDEF_SYSREG_TRAP		:= 0
+
 # Set the default algorithm for the generation of Trusted Board Boot keys
 KEY_ALG				:= rsa
 
diff --git a/plat/allwinner/common/include/sunxi_cpucfg_ncat.h b/plat/allwinner/common/include/sunxi_cpucfg_ncat.h
new file mode 100644
index 0000000..22828c2
--- /dev/null
+++ b/plat/allwinner/common/include/sunxi_cpucfg_ncat.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_CPUCFG_H
+#define SUNXI_CPUCFG_H
+
+#include <sunxi_mmap.h>
+
+/* c = cluster, n = core */
+#define SUNXI_CPUCFG_CLS_CTRL_REG0(c)	(SUNXI_CPUCFG_BASE + 0x0010 + (c) * 0x10)
+#define SUNXI_CPUCFG_CLS_CTRL_REG1(c)	(SUNXI_CPUCFG_BASE + 0x0014 + (c) * 0x10)
+#define SUNXI_CPUCFG_CACHE_CFG_REG	(SUNXI_CPUCFG_BASE + 0x0024)
+/* The T507 datasheet does not mention this register. */
+#define SUNXI_CPUCFG_DBG_REG0		(SUNXI_CPUCFG_BASE + 0x00c0)
+
+#define SUNXI_CPUCFG_RST_CTRL_REG(c)	(SUNXI_CPUCFG_BASE + 0x0000 + (c) * 4)
+#define SUNXI_CPUCFG_RVBAR_LO_REG(n)	(SUNXI_CPUCFG_BASE + 0x0040 + (n) * 8)
+#define SUNXI_CPUCFG_RVBAR_HI_REG(n)	(SUNXI_CPUCFG_BASE + 0x0044 + (n) * 8)
+
+#define SUNXI_C0_CPU_CTRL_REG(n)	(SUNXI_CPUCFG_BASE + 0x0060 + (n) * 4)
+
+#define SUNXI_CPU_CTRL_REG(n)		(SUNXI_CPUSUBSYS_BASE + 0x20 + (n) * 4)
+#define SUNXI_ALT_RVBAR_LO_REG(n)	(SUNXI_CPUSUBSYS_BASE + 0x40 + (n) * 8)
+#define SUNXI_ALT_RVBAR_HI_REG(n)	(SUNXI_CPUSUBSYS_BASE + 0x44 + (n) * 8)
+
+#define SUNXI_POWERON_RST_REG(c)	(SUNXI_R_CPUCFG_BASE + 0x0040 + (c) * 4)
+#define SUNXI_POWEROFF_GATING_REG(c)	(SUNXI_R_CPUCFG_BASE + 0x0044 + (c) * 4)
+#define SUNXI_CPU_POWER_CLAMP_REG(c, n)	(SUNXI_R_CPUCFG_BASE + 0x0050 + \
+					(c) * 0x10 + (n) * 4)
+#define SUNXI_CPU_UNK_REG(n)		(SUNXI_R_CPUCFG_BASE + 0x0070 + (n) * 4)
+
+#define SUNXI_CPUIDLE_EN_REG		(SUNXI_R_CPUCFG_BASE + 0x0100)
+#define SUNXI_CORE_CLOSE_REG		(SUNXI_R_CPUCFG_BASE + 0x0104)
+#define SUNXI_PWR_SW_DELAY_REG		(SUNXI_R_CPUCFG_BASE + 0x0140)
+#define SUNXI_CONFIG_DELAY_REG		(SUNXI_R_CPUCFG_BASE + 0x0144)
+
+#define SUNXI_AA64nAA32_REG		SUNXI_CPUCFG_CLS_CTRL_REG0
+#define SUNXI_AA64nAA32_OFFSET		24
+
+#endif /* SUNXI_CPUCFG_H */
diff --git a/plat/allwinner/common/include/sunxi_cpucfg_ncat2.h b/plat/allwinner/common/include/sunxi_cpucfg_ncat2.h
new file mode 100644
index 0000000..d4aec19
--- /dev/null
+++ b/plat/allwinner/common/include/sunxi_cpucfg_ncat2.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 Sipeed
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_CPUCFG_H
+#define SUNXI_CPUCFG_H
+
+#include <sunxi_mmap.h>
+
+/* c = cluster, n = core */
+#define SUNXI_CPUCFG_CLS_CTRL_REG0(c)	(SUNXI_C0_CPUXCFG_BASE + 0x0010)
+#define SUNXI_CPUCFG_CLS_CTRL_REG1(c)	(SUNXI_C0_CPUXCFG_BASE + 0x0014)
+#define SUNXI_CPUCFG_CACHE_CFG_REG	(SUNXI_C0_CPUXCFG_BASE + 0x0024)
+#define SUNXI_CPUCFG_DBG_REG0		(SUNXI_C0_CPUXCFG_BASE + 0x00c0)
+
+#define SUNXI_CPUCFG_RST_CTRL_REG(c)	(SUNXI_C0_CPUXCFG_BASE + 0x0000)
+#define SUNXI_CPUCFG_GEN_CTRL_REG0(c)	(SUNXI_CPUCFG_BASE + 0x0000)
+#define SUNXI_CPUCFG_RVBAR_LO_REG(n)	(SUNXI_CPUCFG_BASE + 0x0040 + (n) * 8)
+#define SUNXI_CPUCFG_RVBAR_HI_REG(n)	(SUNXI_CPUCFG_BASE + 0x0044 + (n) * 8)
+
+#define SUNXI_POWERON_RST_REG(c)	(SUNXI_R_CPUCFG_BASE + 0x0040 + (c) * 4)
+#define SUNXI_POWEROFF_GATING_REG(c)	(SUNXI_R_CPUCFG_BASE + 0x0044 + (c) * 4)
+#define SUNXI_CPU_POWER_CLAMP_REG(c, n)	(SUNXI_R_CPUCFG_BASE + 0x0050 + \
+					(c) * 0x10 + (n) * 4)
+
+#define SUNXI_AA64nAA32_REG		SUNXI_CPUCFG_GEN_CTRL_REG0
+#define SUNXI_AA64nAA32_OFFSET		4
+
+static inline bool sunxi_cpucfg_has_per_cluster_regs(void)
+{
+	return true;
+}
+
+#endif /* SUNXI_CPUCFG_H */
diff --git a/plat/allwinner/common/include/sunxi_def.h b/plat/allwinner/common/include/sunxi_def.h
index c17ef95..20f6c49 100644
--- a/plat/allwinner/common/include/sunxi_def.h
+++ b/plat/allwinner/common/include/sunxi_def.h
@@ -20,6 +20,7 @@
 #define SUNXI_SOC_H616			0x1823
 #define SUNXI_SOC_R329			0x1851
 
+#define SUNXI_VER_BITS_MASK		0xffU
 #define JEDEC_ALLWINNER_BKID		9U
 #define JEDEC_ALLWINNER_MFID		0x9eU
 
diff --git a/plat/allwinner/common/sunxi_common.c b/plat/allwinner/common/sunxi_common.c
index 092659c..62f4fcb 100644
--- a/plat/allwinner/common/sunxi_common.c
+++ b/plat/allwinner/common/sunxi_common.c
@@ -183,5 +183,5 @@
 {
 	uint32_t reg = mmio_read_32(SRAM_VER_REG);
 
-	return reg & GENMASK_32(7, 0);
+	return reg & SUNXI_VER_BITS_MASK;
 }
diff --git a/plat/allwinner/common/sunxi_cpu_ops.c b/plat/allwinner/common/sunxi_cpu_ops.c
index 46e7090..30841e2 100644
--- a/plat/allwinner/common/sunxi_cpu_ops.c
+++ b/plat/allwinner/common/sunxi_cpu_ops.c
@@ -19,6 +19,12 @@
 #include <sunxi_mmap.h>
 #include <sunxi_private.h>
 
+#ifndef SUNXI_C0_CPU_CTRL_REG
+#define SUNXI_C0_CPU_CTRL_REG(n)	0
+#define SUNXI_CPU_UNK_REG(n)		0
+#define SUNXI_CPU_CTRL_REG(n)		0
+#endif
+
 static void sunxi_cpu_disable_power(unsigned int cluster, unsigned int core)
 {
 	if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0xff)
@@ -53,15 +59,30 @@
 
 	VERBOSE("PSCI: Powering off cluster %d core %d\n", cluster, core);
 
-	/* Deassert DBGPWRDUP */
-	mmio_clrbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core));
-	/* Activate the core output clamps, but not for core 0. */
-	if (core != 0)
-		mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core));
-	/* Assert CPU power-on reset */
-	mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
-	/* Remove power from the CPU */
-	sunxi_cpu_disable_power(cluster, core);
+	if (sunxi_cpucfg_has_per_cluster_regs()) {
+		/* Deassert DBGPWRDUP */
+		mmio_clrbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core));
+		/* Activate the core output clamps, but not for core 0. */
+		if (core != 0) {
+			mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster),
+					BIT(core));
+		}
+		/* Assert CPU power-on reset */
+		mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
+		/* Remove power from the CPU */
+		sunxi_cpu_disable_power(cluster, core);
+	} else {
+		/* power down(?) debug core */
+		mmio_clrbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(8));
+		/* ??? Activate the core output clamps, but not for core 0 */
+		if (core != 0) {
+			mmio_setbits_32(SUNXI_CPU_UNK_REG(core), BIT(1));
+		}
+		/* ??? Assert CPU power-on reset ??? */
+		mmio_clrbits_32(SUNXI_CPU_UNK_REG(core), BIT(0));
+		/* Remove power from the CPU */
+		sunxi_cpu_disable_power(cluster, core);
+	}
 }
 
 void sunxi_cpu_on(u_register_t mpidr)
@@ -71,23 +92,45 @@
 
 	VERBOSE("PSCI: Powering on cluster %d core %d\n", cluster, core);
 
+	if (sunxi_cpucfg_has_per_cluster_regs()) {
+		/* Assert CPU core reset */
+		mmio_clrbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core));
+		/* Assert CPU power-on reset */
+		mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
+		/* Set CPU to start in AArch64 mode */
+		mmio_setbits_32(SUNXI_AA64nAA32_REG(cluster),
+				BIT(SUNXI_AA64nAA32_OFFSET + core));
+		/* Apply power to the CPU */
+		sunxi_cpu_enable_power(cluster, core);
+		/* Release the core output clamps */
+		mmio_clrbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core));
+		/* Deassert CPU power-on reset */
+		mmio_setbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
+		/* Deassert CPU core reset */
+		mmio_setbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core));
+		/* Assert DBGPWRDUP */
+		mmio_setbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core));
+	} else {
+		/* Assert CPU core reset */
+		mmio_clrbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(0));
+		/* ??? Assert CPU power-on reset ??? */
+		mmio_clrbits_32(SUNXI_CPU_UNK_REG(core), BIT(0));
+
+		/* Set CPU to start in AArch64 mode */
+		mmio_setbits_32(SUNXI_CPU_CTRL_REG(core), BIT(0));
+
+		/* Apply power to the CPU */
+		sunxi_cpu_enable_power(cluster, core);
+
-	/* Assert CPU core reset */
-	mmio_clrbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core));
-	/* Assert CPU power-on reset */
-	mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
-	/* Set CPU to start in AArch64 mode */
-	mmio_setbits_32(SUNXI_AA64nAA32_REG(cluster),
-			BIT(SUNXI_AA64nAA32_OFFSET + core));
-	/* Apply power to the CPU */
-	sunxi_cpu_enable_power(cluster, core);
-	/* Release the core output clamps */
-	mmio_clrbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core));
-	/* Deassert CPU power-on reset */
-	mmio_setbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
-	/* Deassert CPU core reset */
-	mmio_setbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core));
-	/* Assert DBGPWRDUP */
-	mmio_setbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core));
+		/* ??? Release the core output clamps ??? */
+		mmio_clrbits_32(SUNXI_CPU_UNK_REG(core), BIT(1));
+		/* ??? Deassert CPU power-on reset ??? */
+		mmio_setbits_32(SUNXI_CPU_UNK_REG(core), BIT(0));
+		/* Deassert CPU core reset */
+		mmio_setbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(0));
+		/* power up(?) debug core */
+		mmio_setbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(8));
+	}
 }
 
 void sunxi_cpu_power_off_others(void)
diff --git a/plat/allwinner/common/sunxi_pm.c b/plat/allwinner/common/sunxi_pm.c
index 3772b4a..ebc406b 100644
--- a/plat/allwinner/common/sunxi_pm.c
+++ b/plat/allwinner/common/sunxi_pm.c
@@ -25,6 +25,11 @@
 }
 #endif
 
+#ifndef SUNXI_ALT_RVBAR_LO_REG
+#define SUNXI_ALT_RVBAR_LO_REG(n)	0
+#define SUNXI_ALT_RVBAR_HI_REG(n)	0
+#endif
+
 int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint)
 {
 	/* The non-secure entry point must be in DRAM */
@@ -42,10 +47,17 @@
 
 	/* Program all CPU entry points. */
 	for (unsigned int cpu = 0; cpu < PLATFORM_CORE_COUNT; ++cpu) {
-		mmio_write_32(SUNXI_CPUCFG_RVBAR_LO_REG(cpu),
-			      sec_entrypoint & 0xffffffff);
-		mmio_write_32(SUNXI_CPUCFG_RVBAR_HI_REG(cpu),
-			      sec_entrypoint >> 32);
+		if (sunxi_cpucfg_has_per_cluster_regs()) {
+			mmio_write_32(SUNXI_CPUCFG_RVBAR_LO_REG(cpu),
+				      sec_entrypoint & 0xffffffff);
+			mmio_write_32(SUNXI_CPUCFG_RVBAR_HI_REG(cpu),
+				      sec_entrypoint >> 32);
+		} else {
+			mmio_write_32(SUNXI_ALT_RVBAR_LO_REG(cpu),
+				      sec_entrypoint & 0xffffffff);
+			mmio_write_32(SUNXI_ALT_RVBAR_HI_REG(cpu),
+				      sec_entrypoint >> 32);
+		}
 	}
 
 	if (sunxi_set_scpi_psci_ops(psci_ops) == 0) {
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h
index aed3585..ddd53ba 100644
--- a/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h
+++ b/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h
@@ -36,4 +36,9 @@
 #define SUNXI_AA64nAA32_REG		SUNXI_CPUCFG_CLS_CTRL_REG0
 #define SUNXI_AA64nAA32_OFFSET		24
 
+static inline bool sunxi_cpucfg_has_per_cluster_regs(void)
+{
+	return true;
+}
+
 #endif /* SUNXI_CPUCFG_H */
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h
index 5bfda5d..585c51b 100644
--- a/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h
+++ b/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h
@@ -1,35 +1,6 @@
-/*
- * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef SUNXI_CPUCFG_H
-#define SUNXI_CPUCFG_H
-
-#include <sunxi_mmap.h>
-
-/* c = cluster, n = core */
-#define SUNXI_CPUCFG_CLS_CTRL_REG0(c)	(SUNXI_CPUCFG_BASE + 0x0010 + (c) * 0x10)
-#define SUNXI_CPUCFG_CLS_CTRL_REG1(c)	(SUNXI_CPUCFG_BASE + 0x0014 + (c) * 0x10)
-#define SUNXI_CPUCFG_CACHE_CFG_REG	(SUNXI_CPUCFG_BASE + 0x0024)
-#define SUNXI_CPUCFG_DBG_REG0		(SUNXI_CPUCFG_BASE + 0x00c0)
-
-#define SUNXI_CPUCFG_RST_CTRL_REG(c)	(SUNXI_CPUCFG_BASE + 0x0000 + (c) * 4)
-#define SUNXI_CPUCFG_RVBAR_LO_REG(n)	(SUNXI_CPUCFG_BASE + 0x0040 + (n) * 8)
-#define SUNXI_CPUCFG_RVBAR_HI_REG(n)	(SUNXI_CPUCFG_BASE + 0x0044 + (n) * 8)
-
-#define SUNXI_POWERON_RST_REG(c)	(SUNXI_R_CPUCFG_BASE + 0x0040 + (c) * 4)
-#define SUNXI_POWEROFF_GATING_REG(c)	(SUNXI_R_CPUCFG_BASE + 0x0044 + (c) * 4)
-#define SUNXI_CPU_POWER_CLAMP_REG(c, n)	(SUNXI_R_CPUCFG_BASE + 0x0050 + \
-					(c) * 0x10 + (n) * 4)
-
-#define SUNXI_CPUIDLE_EN_REG		(SUNXI_R_CPUCFG_BASE + 0x0100)
-#define SUNXI_CORE_CLOSE_REG		(SUNXI_R_CPUCFG_BASE + 0x0104)
-#define SUNXI_PWR_SW_DELAY_REG		(SUNXI_R_CPUCFG_BASE + 0x0140)
-#define SUNXI_CONFIG_DELAY_REG		(SUNXI_R_CPUCFG_BASE + 0x0144)
-
-#define SUNXI_AA64nAA32_REG		SUNXI_CPUCFG_CLS_CTRL_REG0
-#define SUNXI_AA64nAA32_OFFSET		24
+#include <sunxi_cpucfg_ncat.h>
 
-#endif /* SUNXI_CPUCFG_H */
+static inline bool sunxi_cpucfg_has_per_cluster_regs(void)
+{
+	return true;
+}
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
index 58216d8..43133be 100644
--- a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
+++ b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
@@ -59,5 +59,6 @@
 #define SUNXI_R_RSB_BASE		0x07083000
 #define SUNXI_R_UART_BASE		0x07080000
 #define SUNXI_R_PIO_BASE		0x07022000
+#define SUNXI_CPUSUBSYS_BASE		0x08100000
 
 #endif /* SUNXI_MMAP_H */
diff --git a/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h
index dab663b..5c590e4 100644
--- a/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h
+++ b/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h
@@ -1,35 +1,8 @@
-/*
- * Copyright (c) 2017-2020, ARM Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
+#include <plat/common/platform.h>
 
-#ifndef SUNXI_CPUCFG_H
-#define SUNXI_CPUCFG_H
-
-#include <sunxi_mmap.h>
-
-/* c = cluster, n = core */
-#define SUNXI_CPUCFG_CLS_CTRL_REG0(c)	(SUNXI_CPUCFG_BASE + 0x0010 + (c) * 0x10)
-#define SUNXI_CPUCFG_CLS_CTRL_REG1(c)	(SUNXI_CPUCFG_BASE + 0x0014 + (c) * 0x10)
-#define SUNXI_CPUCFG_CACHE_CFG_REG	(SUNXI_CPUCFG_BASE + 0x0024)
-#define SUNXI_CPUCFG_DBG_REG0		(SUNXI_CPUCFG_BASE + 0x00c0)
-
-#define SUNXI_CPUCFG_RST_CTRL_REG(c)	(SUNXI_CPUCFG_BASE + 0x0000 + (c) * 4)
-#define SUNXI_CPUCFG_RVBAR_LO_REG(n)	(SUNXI_CPUCFG_BASE + 0x0040 + (n) * 8)
-#define SUNXI_CPUCFG_RVBAR_HI_REG(n)	(SUNXI_CPUCFG_BASE + 0x0044 + (n) * 8)
-
-#define SUNXI_POWERON_RST_REG(c)	(SUNXI_R_CPUCFG_BASE + 0x0040 + (c) * 4)
-#define SUNXI_POWEROFF_GATING_REG(c)	(SUNXI_R_CPUCFG_BASE + 0x0044 + (c) * 4)
-#define SUNXI_CPU_POWER_CLAMP_REG(c, n)	(SUNXI_R_CPUCFG_BASE + 0x0050 + \
-					(c) * 0x10 + (n) * 4)
-
-#define SUNXI_CPUIDLE_EN_REG		(SUNXI_R_CPUCFG_BASE + 0x0100)
-#define SUNXI_CORE_CLOSE_REG		(SUNXI_R_CPUCFG_BASE + 0x0104)
-#define SUNXI_PWR_SW_DELAY_REG		(SUNXI_R_CPUCFG_BASE + 0x0140)
-#define SUNXI_CONFIG_DELAY_REG		(SUNXI_R_CPUCFG_BASE + 0x0144)
-
-#define SUNXI_AA64nAA32_REG		SUNXI_CPUCFG_CLS_CTRL_REG0
-#define SUNXI_AA64nAA32_OFFSET		24
+#include <sunxi_cpucfg_ncat.h>
 
-#endif /* SUNXI_CPUCFG_H */
+static inline bool sunxi_cpucfg_has_per_cluster_regs(void)
+{
+	return (plat_get_soc_revision() != 2);
+}
diff --git a/plat/allwinner/sun50i_h616/include/sunxi_mmap.h b/plat/allwinner/sun50i_h616/include/sunxi_mmap.h
index 3b4f4a0..24a4ba8 100644
--- a/plat/allwinner/sun50i_h616/include/sunxi_mmap.h
+++ b/plat/allwinner/sun50i_h616/include/sunxi_mmap.h
@@ -41,6 +41,7 @@
 #define SUNXI_R_UART_BASE		0x07080000
 #define SUNXI_R_I2C_BASE		0x07081400
 #define SUNXI_R_RSB_BASE		0x07083000
+#define SUNXI_CPUSUBSYS_BASE		0x08100000
 #define SUNXI_CPUCFG_BASE		0x09010000
 
 #endif /* SUNXI_MMAP_H */
diff --git a/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h
index 9478f32..3c3530f 100644
--- a/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h
+++ b/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h
@@ -1,31 +1 @@
-/*
- * Copyright (c) 2021 Sipeed
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef SUNXI_CPUCFG_H
-#define SUNXI_CPUCFG_H
-
-#include <sunxi_mmap.h>
-
-/* c = cluster, n = core */
-#define SUNXI_CPUCFG_CLS_CTRL_REG0(c)	(SUNXI_C0_CPUXCFG_BASE + 0x0010)
-#define SUNXI_CPUCFG_CLS_CTRL_REG1(c)	(SUNXI_C0_CPUXCFG_BASE + 0x0014)
-#define SUNXI_CPUCFG_CACHE_CFG_REG	(SUNXI_C0_CPUXCFG_BASE + 0x0024)
-#define SUNXI_CPUCFG_DBG_REG0		(SUNXI_C0_CPUXCFG_BASE + 0x00c0)
-
-#define SUNXI_CPUCFG_RST_CTRL_REG(c)	(SUNXI_C0_CPUXCFG_BASE + 0x0000)
-#define SUNXI_CPUCFG_GEN_CTRL_REG0(c)	(SUNXI_CPUCFG_BASE + 0x0000)
-#define SUNXI_CPUCFG_RVBAR_LO_REG(n)	(SUNXI_CPUCFG_BASE + 0x0040 + (n) * 8)
-#define SUNXI_CPUCFG_RVBAR_HI_REG(n)	(SUNXI_CPUCFG_BASE + 0x0044 + (n) * 8)
-
-#define SUNXI_POWERON_RST_REG(c)	(SUNXI_R_CPUCFG_BASE + 0x0040 + (c) * 4)
-#define SUNXI_POWEROFF_GATING_REG(c)	(SUNXI_R_CPUCFG_BASE + 0x0044 + (c) * 4)
-#define SUNXI_CPU_POWER_CLAMP_REG(c, n)	(SUNXI_R_CPUCFG_BASE + 0x0050 + \
-					(c) * 0x10 + (n) * 4)
-
-#define SUNXI_AA64nAA32_REG		SUNXI_CPUCFG_GEN_CTRL_REG0
-#define SUNXI_AA64nAA32_OFFSET		4
-
-#endif /* SUNXI_CPUCFG_H */
+#include <sunxi_cpucfg_ncat2.h>
diff --git a/plat/arm/board/corstone1000/common/corstone1000_bl31_setup.c b/plat/arm/board/corstone1000/common/corstone1000_bl31_setup.c
new file mode 100644
index 0000000..b6765a6
--- /dev/null
+++ b/plat/arm/board/corstone1000/common/corstone1000_bl31_setup.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#if defined(SPD_spmd)
+/*
+ * A dummy implementation of the platform handler for Group0 secure interrupt.
+ */
+int plat_spmd_handle_group0_interrupt(uint32_t intid)
+{
+	(void)intid;
+	return -1;
+}
+#endif /*defined(SPD_spmd)*/
diff --git a/plat/arm/board/corstone1000/platform.mk b/plat/arm/board/corstone1000/platform.mk
index d891691..3edffe0 100644
--- a/plat/arm/board/corstone1000/platform.mk
+++ b/plat/arm/board/corstone1000/platform.mk
@@ -56,6 +56,7 @@
 			plat/arm/board/corstone1000/common/corstone1000_security.c		\
 			plat/arm/board/corstone1000/common/corstone1000_plat.c		\
 			plat/arm/board/corstone1000/common/corstone1000_pm.c		\
+			plat/arm/board/corstone1000/common/corstone1000_bl31_setup.c	\
 			${CORSTONE1000_CPU_LIBS}					\
 			${CORSTONE1000_GIC_SOURCES}
 
diff --git a/plat/arm/board/fvp/fvp_spmd.c b/plat/arm/board/fvp/fvp_spmd.c
new file mode 100644
index 0000000..8213e5e
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_spmd.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+int plat_spmd_handle_group0_interrupt(uint32_t intid)
+{
+	/*
+	 * As of now, there are no sources of Group0 secure interrupt enabled
+	 * for FVP.
+	 */
+	(void)intid;
+	return -1;
+}
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index af082ba..ea3f954 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -50,7 +50,8 @@
 	ENABLE_FEAT_RNG			:= 2
 	ENABLE_FEAT_TWED		:= 2
 	ENABLE_FEAT_GCS			:= 2
-ifeq (${ARCH},aarch64)
+ifeq (${ARCH}, aarch64)
+ifneq (${SPD}, spmd)
 ifeq (${SPM_MM}, 0)
 ifeq (${ENABLE_RME}, 0)
 ifeq (${CTX_INCLUDE_FPREGS}, 0)
@@ -61,6 +62,7 @@
 endif
 endif
 endif
+endif
 
 # enable unconditionally for all builds
 ifeq (${ARCH}, aarch64)
@@ -510,3 +512,7 @@
     endif
 BL31_SOURCES	+= plat/arm/board/fvp/aarch64/fvp_ea.c
 endif
+
+ifeq (${SPD},spmd)
+BL31_SOURCES	+=	plat/arm/board/fvp/fvp_spmd.c
+endif
diff --git a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
index 4941a4b..6809541 100644
--- a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
+++ b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
@@ -159,3 +159,14 @@
 	if ((plat_info.multichip_mode) && (plat_info.remote_ddr_size != 0))
 		remote_dmc_ecc_setup(plat_info.remote_ddr_size);
 }
+
+#if defined(SPD_spmd)
+/*
+ * A dummy implementation of the platform handler for Group0 secure interrupt.
+ */
+int plat_spmd_handle_group0_interrupt(uint32_t intid)
+{
+	(void)intid;
+	return -1;
+}
+#endif /*defined(SPD_spmd)*/
diff --git a/plat/arm/board/rde1edge/platform.mk b/plat/arm/board/rde1edge/platform.mk
index 0f9dd49..4a9a467 100644
--- a/plat/arm/board/rde1edge/platform.mk
+++ b/plat/arm/board/rde1edge/platform.mk
@@ -1,9 +1,12 @@
 #
-# Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2023, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+$(warning Platform ${PLAT} is deprecated. \
+  Some of the features might not work as expected)
+
 include plat/arm/css/sgi/sgi-common.mk
 
 RDE1EDGE_BASE		=	plat/arm/board/rde1edge
diff --git a/plat/arm/board/tc/include/tc_plat.h b/plat/arm/board/tc/include/tc_plat.h
index ba1831f..195366e 100644
--- a/plat/arm/board/tc/include/tc_plat.h
+++ b/plat/arm/board/tc/include/tc_plat.h
@@ -9,8 +9,10 @@
 
 void tc_bl31_common_platform_setup(void);
 
-#ifdef PLATFORM_TEST
+#ifdef PLATFORM_TEST_TFM_TESTSUITE
 void run_platform_tests(void);
+#endif
+#ifdef PLATFORM_TEST_NV_COUNTERS
 void nv_counter_test(void);
 #endif
 
diff --git a/plat/arm/board/tc/plat_fiptool.mk b/plat/arm/board/tc/plat_fiptool.mk
deleted file mode 100644
index 0e13556..0000000
--- a/plat/arm/board/tc/plat_fiptool.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# Copyright (c) 2021, NXP. All rights reserved.
-# Copyright (c) 2022, Arm Limited. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-# Name of the platform defined source file name,
-# which contains platform defined UUID entries populated
-# in the plat_def_toc_entries[].
-PLAT_DEF_UUID_CONFIG_FILE_NAME	:= plat_def_uuid_config
-
-PLAT_DEF_UUID_CONFIG_FILE_PATH := ../../plat/arm/board/tc
-
-PLAT_DEF_UUID := yes
-PLAT_DEF_UUID_OID_CONFIG_PATH := ../../plat/arm/board/tc
-
-
-INCLUDE_PATHS += -I${PLAT_DEF_UUID_OID_CONFIG_PATH} \
-		 -I./
-# Clean the stale object file.
-$(shell rm ${PLAT_DEF_UUID_CONFIG_FILE_PATH}/${PLAT_DEF_UUID_CONFIG_FILE_NAME}.o)
-
-ifeq (${PLAT_DEF_OID},yes)
-HOSTCCFLAGS += -DPLAT_DEF_OID
-endif
-
-ifeq (${PLAT_DEF_UUID},yes)
-HOSTCCFLAGS += -DPLAT_DEF_FIP_UUID
-PLAT_OBJECTS += ${PLAT_DEF_UUID_CONFIG_FILE_PATH}/${PLAT_DEF_UUID_CONFIG_FILE_NAME}.o
-endif
-
-OBJECTS += ${PLAT_OBJECTS}
diff --git a/plat/arm/board/tc/plat_tc_mbedtls_config.h b/plat/arm/board/tc/plat_tc_mbedtls_config.h
index d776b63..f0aa60b 100644
--- a/plat/arm/board/tc/plat_tc_mbedtls_config.h
+++ b/plat/arm/board/tc/plat_tc_mbedtls_config.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022, Arm Ltd. All rights reserved.
+ * Copyright (c) 2022-2023, Arm Ltd. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,8 +7,8 @@
 #ifndef PLAT_TC_MBEDTLS_CONFIG_H
 #define PLAT_TC_MBEDTLS_CONFIG_H
 
-#include <mbedtls_config.h>
 #include <export/lib/utils_def_exp.h>
+#include <mbedtls_config-3.h>
 
 #ifndef TF_MBEDTLS_HEAP_SIZE
 #error TF_MBEDTLS_HEAP_SIZE is not defined
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
index 7fdc4fd..63a9237 100644
--- a/plat/arm/board/tc/platform.mk
+++ b/plat/arm/board/tc/platform.mk
@@ -53,9 +53,6 @@
 # enable trace filter control registers access to NS by default
 ENABLE_TRF_FOR_NS               := 1
 
-# Enable RSS-required FIP UUIDs
-$(shell cp plat/arm/board/tc/plat_fiptool.mk ${PLAT_DIR})
-
 # Include GICv3 driver files
 include drivers/arm/gic/v3/gicv3.mk
 
@@ -209,7 +206,7 @@
 
     PLAT_INCLUDES	+=	-Iinclude/lib/psa
 
-    $(eval $(call add_define,PLATFORM_TEST))
+    $(eval $(call add_define,PLATFORM_TEST_NV_COUNTERS))
 else ifeq (${PLATFORM_TEST},tfm-testsuite)
     # Add this include as first, before arm_common.mk. This is necessary
     # because arm_common.mk builds Mbed TLS, and platform_test.mk can
diff --git a/plat/arm/board/tc/platform_test.mk b/plat/arm/board/tc/platform_test.mk
index 5cdbb86..e974855 100644
--- a/plat/arm/board/tc/platform_test.mk
+++ b/plat/arm/board/tc/platform_test.mk
@@ -76,5 +76,5 @@
     $(eval $(call add_define,MEASURED_BOOT_HASH_ALG))
     $(eval $(call add_define,DELEG_ATTEST_DUMP_TOKEN_AND_KEY))
 
-    $(eval $(call add_define,PLATFORM_TEST))
+    $(eval $(call add_define,PLATFORM_TEST_TFM_TESTSUITE))
 endif
diff --git a/plat/arm/board/tc/tc_bl31_setup.c b/plat/arm/board/tc/tc_bl31_setup.c
index 1c1e2fb..8ad1d30 100644
--- a/plat/arm/board/tc/tc_bl31_setup.c
+++ b/plat/arm/board/tc/tc_bl31_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2023, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2023, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -53,11 +53,11 @@
 {
 	arm_bl31_platform_setup();
 
-#ifdef PLATFORM_TEST
-#if PLATFORM_TEST == rss-nv-counters
+#if defined(PLATFORM_TEST_NV_COUNTERS) || defined(PLATFORM_TEST_TFM_TESTSUITE)
+#ifdef PLATFORM_TEST_NV_COUNTERS
 	nv_counter_test();
-#elif PLATFORM_TEST == tfm-testsuite
-	run_platform_tests()
+#elif PLATFORM_TEST_TFM_TESTSUITE
+	run_platform_tests();
 #endif
 	/* Suspend booting */
 	plat_error_handler(-1);
diff --git a/plat/hisilicon/hikey960/hikey960_bl31_setup.c b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
index 50751ee..1d7bc94 100644
--- a/plat/hisilicon/hikey960/hikey960_bl31_setup.c
+++ b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -245,6 +245,15 @@
 
 	return 0;
 }
+#elif defined(SPD_spmd) && (SPMD_SPM_AT_SEL2 == 1)
+/*
+ * A dummy implementation of the platform handler for Group0 secure interrupt.
+ */
+int plat_spmd_handle_group0_interrupt(uint32_t intid)
+{
+	(void)intid;
+	return -1;
+}
 #endif
 
 void bl31_plat_runtime_setup(void)
diff --git a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
index 6c8c4f0..72ecd54 100644
--- a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
+++ b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
@@ -125,15 +125,18 @@
 .endm
 
 	/* -----------------------------------------------------
-	 * unsigned int plat_is_my_cpu_primary(void);
+	 * bool plat_is_my_cpu_primary(void);
 	 *
 	 * This function checks if this is the Primary CPU
+	 *
+	 * Registers clobbered: x0, x1
 	 * -----------------------------------------------------
 	 */
 func plat_is_my_cpu_primary
 	mrs	x0, mpidr_el1
-	and	x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
-	cmp	x0, #TEGRA_PRIMARY_CPU
+	adr	x1, tegra_primary_cpu_mpid
+	ldr	x1, [x1]
+	cmp	x0, x1
 	cset	x0, eq
 	ret
 endfunc plat_is_my_cpu_primary
@@ -251,6 +254,14 @@
 	adr	x18, bl31_entrypoint
 	str	x18, [x17]
 
+	/* -----------------------------------
+	 * save the boot CPU MPID value
+	 * -----------------------------------
+	 */
+	mrs	x0, mpidr_el1
+	adr	x1, tegra_primary_cpu_mpid
+	str	x0, [x1]
+
 1:	cpu_init_common
 
 	ret
@@ -426,3 +437,10 @@
 	 */
 tegra_console_base:
 	.quad	0
+
+	/* --------------------------------------------------
+	 * MPID value for the boot CPU
+	 * --------------------------------------------------
+	 */
+tegra_primary_cpu_mpid:
+	.quad	0
diff --git a/plat/nvidia/tegra/common/tegra_bl31_setup.c b/plat/nvidia/tegra/common/tegra_bl31_setup.c
index 6a3eae0..050ef52 100644
--- a/plat/nvidia/tegra/common/tegra_bl31_setup.c
+++ b/plat/nvidia/tegra/common/tegra_bl31_setup.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2020-2023, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -92,21 +92,16 @@
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
-	struct tegra_bl31_params *arg_from_bl2 = (struct tegra_bl31_params *) arg0;
-	plat_params_from_bl2_t *plat_params = (plat_params_from_bl2_t *)arg1;
+	struct tegra_bl31_params *arg_from_bl2 = plat_get_bl31_params();
+	plat_params_from_bl2_t *plat_params = plat_get_bl31_plat_params();
 	int32_t ret;
 
 	/*
-	 * For RESET_TO_BL31 systems, BL31 is the first bootloader to run so
-	 * there's no argument to relay from a previous bootloader. Platforms
-	 * might use custom ways to get arguments.
+	 * Tegra platforms will receive boot parameters through custom
+	 * mechanisms. So, we ignore the input parameters.
 	 */
-	if (arg_from_bl2 == NULL) {
-		arg_from_bl2 = plat_get_bl31_params();
-	}
-	if (plat_params == NULL) {
-		plat_params = plat_get_bl31_plat_params();
-	}
+	(void)arg0;
+	(void)arg1;
 
 	/*
 	 * Copy BL3-3, BL3-2 entry point information.
diff --git a/plat/nvidia/tegra/common/tegra_pm.c b/plat/nvidia/tegra/common/tegra_pm.c
index ec34a85..8edb024 100644
--- a/plat/nvidia/tegra/common/tegra_pm.c
+++ b/plat/nvidia/tegra/common/tegra_pm.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2020-2023, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -92,6 +92,16 @@
 /*******************************************************************************
  * Handler called when a power domain is about to be turned off. The
  * target_state encodes the power state that each level should transition to.
+ * Return error if CPU off sequence is not allowed for the current core.
+ ******************************************************************************/
+static int tegra_pwr_domain_off_early(const psci_power_state_t *target_state)
+{
+	return tegra_soc_pwr_domain_off_early(target_state);
+}
+
+/*******************************************************************************
+ * Handler called when a power domain is about to be turned off. The
+ * target_state encodes the power state that each level should transition to.
  ******************************************************************************/
 static void tegra_pwr_domain_off(const psci_power_state_t *target_state)
 {
@@ -268,6 +278,7 @@
 static plat_psci_ops_t tegra_plat_psci_ops = {
 	.cpu_standby			= tegra_cpu_standby,
 	.pwr_domain_on			= tegra_pwr_domain_on,
+	.pwr_domain_off_early		= tegra_pwr_domain_off_early,
 	.pwr_domain_off			= tegra_pwr_domain_off,
 	.pwr_domain_suspend_pwrdown_early = tegra_pwr_domain_suspend_pwrdown_early,
 	.pwr_domain_suspend		= tegra_pwr_domain_suspend,
diff --git a/plat/nvidia/tegra/include/platform_def.h b/plat/nvidia/tegra/include/platform_def.h
index 84b3297..958a3f9 100644
--- a/plat/nvidia/tegra/include/platform_def.h
+++ b/plat/nvidia/tegra/include/platform_def.h
@@ -41,8 +41,6 @@
 #define PLATFORM_STACK_SIZE 		U(0x400)
 #endif
 
-#define TEGRA_PRIMARY_CPU		U(0x0)
-
 #define PLAT_MAX_PWR_LVL		MPIDR_AFFLVL2
 #define PLATFORM_CORE_COUNT		(PLATFORM_CLUSTER_COUNT * \
 					 PLATFORM_MAX_CPUS_PER_CLUSTER)
diff --git a/plat/nvidia/tegra/include/tegra_private.h b/plat/nvidia/tegra/include/tegra_private.h
index cc2ad86..71bea08 100644
--- a/plat/nvidia/tegra/include/tegra_private.h
+++ b/plat/nvidia/tegra/include/tegra_private.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2020-2023, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -98,6 +98,9 @@
 int32_t tegra_fiq_get_intr_context(void);
 void tegra_fiq_set_ns_entrypoint(uint64_t entrypoint);
 
+/* Declarations for tegra_helpers.S */
+bool plat_is_my_cpu_primary(void);
+
 /* Declarations for tegra_security.c */
 void tegra_security_setup(void);
 void tegra_security_setup_videomem(uintptr_t base, uint64_t size);
@@ -109,6 +112,7 @@
 int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state);
 int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state);
 int32_t tegra_soc_pwr_domain_on(u_register_t mpidr);
+int32_t tegra_soc_pwr_domain_off_early(const psci_power_state_t *target_state);
 int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state);
 int32_t tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state);
 int32_t tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state);
diff --git a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
index af4182e..8f88e28 100644
--- a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
@@ -433,6 +433,16 @@
 	return PSCI_E_SUCCESS;
 }
 
+int32_t tegra_soc_pwr_domain_off_early(const psci_power_state_t *target_state)
+{
+	/* Do not power off the boot CPU */
+	if (plat_is_my_cpu_primary()) {
+		return PSCI_E_DENIED;
+	}
+
+	return PSCI_E_SUCCESS;
+}
+
 int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
 {
 	uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & (uint64_t)MIDR_IMPL_MASK;
diff --git a/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
index 41a85ee..83d815a 100644
--- a/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
@@ -463,6 +463,16 @@
 	return PSCI_E_SUCCESS;
 }
 
+int32_t tegra_soc_pwr_domain_off_early(const psci_power_state_t *target_state)
+{
+	/* Do not power off the boot CPU */
+	if (plat_is_my_cpu_primary()) {
+		return PSCI_E_DENIED;
+	}
+
+	return PSCI_E_SUCCESS;
+}
+
 int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
 {
 	uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
diff --git a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
index 7f73ea5..2ec044c 100644
--- a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
@@ -575,6 +575,16 @@
 	return PSCI_E_SUCCESS;
 }
 
+int32_t tegra_soc_pwr_domain_off_early(const psci_power_state_t *target_state)
+{
+	/* Do not power off the boot CPU */
+	if (plat_is_my_cpu_primary()) {
+		return PSCI_E_DENIED;
+	}
+
+	return PSCI_E_SUCCESS;
+}
+
 int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
 {
 	tegra_fc_cpu_off(read_mpidr() & MPIDR_CPU_MASK);
diff --git a/plat/nxp/common/fip_handler/ddr_fip/ddr_fip_io.mk b/plat/nxp/common/fip_handler/ddr_fip/ddr_fip_io.mk
index 7d673ba..36c07b7 100644
--- a/plat/nxp/common/fip_handler/ddr_fip/ddr_fip_io.mk
+++ b/plat/nxp/common/fip_handler/ddr_fip/ddr_fip_io.mk
@@ -1,5 +1,6 @@
 #
 # Copyright 2020 NXP
+# Copyright (c) 2023, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -22,8 +23,6 @@
 
 DDR_FIP_IO_SOURCES	+= $(DDR_FIP_IO_STORAGE_PATH)/ddr_io_storage.c
 
-$(shell cp tools/nxp/plat_fiptool/plat_fiptool.mk ${PLAT_DIR})
-
 ifeq (${BL_COMM_DDR_FIP_IO_NEEDED},yes)
 BL_COMMON_SOURCES	+= ${DDR_FIP_IO_SOURCES}
 else
diff --git a/plat/nxp/common/fip_handler/fuse_fip/fuse.mk b/plat/nxp/common/fip_handler/fuse_fip/fuse.mk
index d8f5ae6..4e84d02 100644
--- a/plat/nxp/common/fip_handler/fuse_fip/fuse.mk
+++ b/plat/nxp/common/fip_handler/fuse_fip/fuse.mk
@@ -1,5 +1,6 @@
 #
 # Copyright 2018-2020 NXP
+# Copyright (c) 2023, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -29,8 +30,6 @@
 
 ifeq (${FUSE_PROV_FILE},)
 
-$(shell cp tools/nxp/plat_fiptool/plat_fiptool.mk ${PLAT_DIR})
-
 else
 ifeq (${TRUSTED_BOARD_BOOT},1)
 FUSE_PROV_FILE_SB = $(notdir ${FUSE_PROV_FILE})_prov.sb
diff --git a/plat/qemu/common/qemu_common.c b/plat/qemu/common/qemu_common.c
index 935ba7a..9aec213 100644
--- a/plat/qemu/common/qemu_common.c
+++ b/plat/qemu/common/qemu_common.c
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -162,3 +162,14 @@
 	return 0;
 }
 #endif
+
+#if defined(SPD_spmd) && (SPMD_SPM_AT_SEL2 == 1)
+/*
+ * A dummy implementation of the platform handler for Group0 secure interrupt.
+ */
+int plat_spmd_handle_group0_interrupt(uint32_t intid)
+{
+	(void)intid;
+	return -1;
+}
+#endif /*defined(SPD_spmd) && (SPMD_SPM_AT_SEL2 == 1)*/
diff --git a/plat/xilinx/common/include/plat_startup.h b/plat/xilinx/common/include/plat_startup.h
index ae9d52a..ed3946f 100644
--- a/plat/xilinx/common/include/plat_startup.h
+++ b/plat/xilinx/common/include/plat_startup.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
- * Copyright (C) 2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2023, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
diff --git a/plat/xilinx/versal/aarch64/versal_common.c b/plat/xilinx/versal/aarch64/versal_common.c
index 0c8ee1e..88da279 100644
--- a/plat/xilinx/versal/aarch64/versal_common.c
+++ b/plat/xilinx/versal/aarch64/versal_common.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved.
- * Copyright (C) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
diff --git a/plat/xilinx/versal_net/aarch64/versal_net_common.c b/plat/xilinx/versal_net/aarch64/versal_net_common.c
index 253c382..1a57330 100644
--- a/plat/xilinx/versal_net/aarch64/versal_net_common.c
+++ b/plat/xilinx/versal_net/aarch64/versal_net_common.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
- * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
diff --git a/plat/xilinx/versal_net/aarch64/versal_net_helpers.S b/plat/xilinx/versal_net/aarch64/versal_net_helpers.S
index bbd937b..e1e2317 100644
--- a/plat/xilinx/versal_net/aarch64/versal_net_helpers.S
+++ b/plat/xilinx/versal_net/aarch64/versal_net_helpers.S
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
- * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
diff --git a/plat/xilinx/versal_net/bl31_versal_net_setup.c b/plat/xilinx/versal_net/bl31_versal_net_setup.c
index 48be081..ae9dfe8 100644
--- a/plat/xilinx/versal_net/bl31_versal_net_setup.c
+++ b/plat/xilinx/versal_net/bl31_versal_net_setup.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
- * Copyright (C) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
diff --git a/plat/xilinx/versal_net/include/plat_ipi.h b/plat/xilinx/versal_net/include/plat_ipi.h
index 5ac611c..30c51b5 100644
--- a/plat/xilinx/versal_net/include/plat_ipi.h
+++ b/plat/xilinx/versal_net/include/plat_ipi.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2022, Xilinx, Inc. All rights reserved.
- * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
diff --git a/plat/xilinx/versal_net/include/plat_pm_common.h b/plat/xilinx/versal_net/include/plat_pm_common.h
index ad7b40f..6485df7 100644
--- a/plat/xilinx/versal_net/include/plat_pm_common.h
+++ b/plat/xilinx/versal_net/include/plat_pm_common.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2022, Xilinx, Inc. All rights reserved.
- * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
diff --git a/plat/xilinx/versal_net/include/versal_net_def.h b/plat/xilinx/versal_net/include/versal_net_def.h
index ec36e55..8fb71f9 100644
--- a/plat/xilinx/versal_net/include/versal_net_def.h
+++ b/plat/xilinx/versal_net/include/versal_net_def.h
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2021-2022, Xilinx, Inc. All rights reserved.
- * Copyright (C) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
diff --git a/plat/xilinx/versal_net/plat_psci_pm.c b/plat/xilinx/versal_net/plat_psci_pm.c
index 9d401a5..d39fc2e 100644
--- a/plat/xilinx/versal_net/plat_psci_pm.c
+++ b/plat/xilinx/versal_net/plat_psci_pm.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2022, Xilinx, Inc. All rights reserved.
- * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
diff --git a/plat/xilinx/versal_net/plat_topology.c b/plat/xilinx/versal_net/plat_topology.c
index c74faf2..ee756c4 100644
--- a/plat/xilinx/versal_net/plat_topology.c
+++ b/plat/xilinx/versal_net/plat_topology.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
- * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
diff --git a/plat/xilinx/versal_net/sip_svc_setup.c b/plat/xilinx/versal_net/sip_svc_setup.c
index cc8306e..f6240f3 100644
--- a/plat/xilinx/versal_net/sip_svc_setup.c
+++ b/plat/xilinx/versal_net/sip_svc_setup.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
- * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
diff --git a/plat/xilinx/versal_net/versal_net_gicv3.c b/plat/xilinx/versal_net/versal_net_gicv3.c
index e7d8e75..2fdef12 100644
--- a/plat/xilinx/versal_net/versal_net_gicv3.c
+++ b/plat/xilinx/versal_net/versal_net_gicv3.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
- * Copyright (C) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
diff --git a/plat/xilinx/versal_net/versal_net_ipi.c b/plat/xilinx/versal_net/versal_net_ipi.c
index 26ded89..cf897e3 100644
--- a/plat/xilinx/versal_net/versal_net_ipi.c
+++ b/plat/xilinx/versal_net/versal_net_ipi.c
@@ -1,6 +1,6 @@
 /*
- * Copyright (C) 2022, Xilinx, Inc. All rights reserved.
- * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
index 0e1899e..80b506b 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -249,6 +249,74 @@
 	SMC_RET0(&ctx->cpu_ctx);
 }
 
+/*******************************************************************************
+ * spmd_group0_interrupt_handler_nwd
+ * Group0 secure interrupt in the normal world are trapped to EL3. Delegate the
+ * handling of the interrupt to the platform handler, and return only upon
+ * successfully handling the Group0 interrupt.
+ ******************************************************************************/
+static uint64_t spmd_group0_interrupt_handler_nwd(uint32_t id,
+						  uint32_t flags,
+						  void *handle,
+						  void *cookie)
+{
+	uint32_t intid;
+
+	/* Sanity check the security state when the exception was generated. */
+	assert(get_interrupt_src_ss(flags) == NON_SECURE);
+
+	/* Sanity check the pointer to this cpu's context. */
+	assert(handle == cm_get_context(NON_SECURE));
+
+	assert(id == INTR_ID_UNAVAILABLE);
+
+	assert(plat_ic_get_pending_interrupt_type() == INTR_TYPE_EL3);
+
+	intid = plat_ic_get_pending_interrupt_id();
+
+	if (plat_spmd_handle_group0_interrupt(intid) < 0) {
+		ERROR("Group0 interrupt %u not handled\n", intid);
+		panic();
+	}
+
+	return 0U;
+}
+
+/*******************************************************************************
+ * spmd_handle_group0_intr_swd
+ * SPMC delegates handling of Group0 secure interrupt to EL3 firmware using
+ * FFA_EL3_INTR_HANDLE SMC call. Further, SPMD delegates the handling of the
+ * interrupt to the platform handler, and returns only upon successfully
+ * handling the Group0 interrupt.
+ ******************************************************************************/
+static uint64_t spmd_handle_group0_intr_swd(void *handle)
+{
+	uint32_t intid;
+
+	/* Sanity check the pointer to this cpu's context */
+	assert(handle == cm_get_context(SECURE));
+
+	assert(plat_ic_get_pending_interrupt_type() == INTR_TYPE_EL3);
+
+	intid = plat_ic_get_pending_interrupt_id();
+
+	/*
+	 * TODO: Currently due to a limitation in SPMD implementation, the
+	 * platform handler is expected to not delegate handling to NWd while
+	 * processing Group0 secure interrupt.
+	 */
+	if (plat_spmd_handle_group0_interrupt(intid) < 0) {
+		/* Group0 interrupt was not handled by the platform. */
+		ERROR("Group0 interrupt %u not handled\n", intid);
+		panic();
+	}
+
+	/* Return success. */
+	SMC_RET8(handle, FFA_SUCCESS_SMC32, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+		 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+		 FFA_PARAM_MBZ);
+}
+
 #if ENABLE_RME && SPMD_SPM_AT_SEL2 && !RESET_TO_BL31
 static int spmd_dynamic_map_mem(uintptr_t base_addr, size_t size,
 				 unsigned int attr, uintptr_t *align_addr,
@@ -492,6 +560,16 @@
 		panic();
 	}
 
+	/*
+	 * Register an interrupt handler routing Group0 interrupts to SPMD
+	 * while the NWd is running.
+	 */
+	rc = register_interrupt_type_handler(INTR_TYPE_EL3,
+					     spmd_group0_interrupt_handler_nwd,
+					     flags);
+	if (rc != 0) {
+		panic();
+	}
 	return 0;
 }
 
@@ -1089,6 +1167,12 @@
 					handle, flags);
 		break; /* Not reached */
 #endif
+	case FFA_EL3_INTR_HANDLE:
+		if (secure_origin) {
+			return spmd_handle_group0_intr_swd(handle);
+		} else {
+			return spmd_ffa_error_return(handle, FFA_ERROR_DENIED);
+		}
 	default:
 		WARN("SPM: Unsupported call 0x%08x\n", smc_fid);
 		return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
diff --git a/services/std_svc/spmd/spmd_private.h b/services/std_svc/spmd/spmd_private.h
index d21a622..ff6942e 100644
--- a/services/std_svc/spmd/spmd_private.h
+++ b/services/std_svc/spmd/spmd_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2023, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -93,6 +93,13 @@
 int spmd_pm_secondary_ep_register(uintptr_t entry_point);
 bool spmd_check_address_in_binary_image(uint64_t address);
 
+/*
+ * Platform hook in EL3 firmware to handle for Group0 secure interrupt.
+ * Return values:
+ *  0 = success
+ *  otherwise it returns a negative value
+ */
+int plat_spmd_handle_group0_interrupt(uint32_t id);
 #endif /* __ASSEMBLER__ */
 
 #endif /* SPMD_PRIVATE_H */
diff --git a/tools/fiptool/Makefile b/tools/fiptool/Makefile
index ac262cd..2ebee33 100644
--- a/tools/fiptool/Makefile
+++ b/tools/fiptool/Makefile
@@ -54,10 +54,13 @@
 ifneq (${PLAT},)
 TF_PLATFORM_ROOT	:=	../../plat/
 include ${MAKE_HELPERS_DIRECTORY}plat_helpers.mk
-PLAT_FIPTOOL_HELPER_MK := ${PLAT_DIR}/plat_fiptool.mk
+COMBINED_PATH_FRAG := plat_fiptool/
+PLAT_FIPTOOL_HELPER_MK := $(foreach path_frag,$(subst /, ,$(patsubst ../../plat/%/,%,${PLAT_DIR})),\
+			  $(eval COMBINED_PATH_FRAG := ${COMBINED_PATH_FRAG}/${path_frag})\
+			  $(wildcard ${COMBINED_PATH_FRAG}/plat_fiptool.mk))
 endif
 
-ifneq (,$(wildcard ${PLAT_FIPTOOL_HELPER_MK}))
+ifneq (,$(wildcard $(lastword ${PLAT_FIPTOOL_HELPER_MK})))
 include ${PLAT_FIPTOOL_HELPER_MK}
 endif
 
diff --git a/plat/arm/board/tc/plat_def_uuid_config.c b/tools/fiptool/plat_fiptool/arm/board/tc/plat_def_uuid_config.c
similarity index 100%
rename from plat/arm/board/tc/plat_def_uuid_config.c
rename to tools/fiptool/plat_fiptool/arm/board/tc/plat_def_uuid_config.c
diff --git a/tools/fiptool/plat_fiptool/arm/board/tc/plat_fiptool.mk b/tools/fiptool/plat_fiptool/arm/board/tc/plat_fiptool.mk
new file mode 100644
index 0000000..70ccfc5
--- /dev/null
+++ b/tools/fiptool/plat_fiptool/arm/board/tc/plat_fiptool.mk
@@ -0,0 +1,12 @@
+#
+# Copyright (c) 2021, NXP. All rights reserved.
+# Copyright (c) 2022-2023, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+INCLUDE_PATHS += -I./ \
+		 -I../../plat/arm/board/tc
+
+HOSTCCFLAGS += -DPLAT_DEF_FIP_UUID
+OBJECTS += plat_fiptool/arm/board/tc/plat_def_uuid_config.o
diff --git a/tools/nxp/plat_fiptool/plat_def_uuid_config.c b/tools/fiptool/plat_fiptool/nxp/plat_def_uuid_config.c
similarity index 100%
rename from tools/nxp/plat_fiptool/plat_def_uuid_config.c
rename to tools/fiptool/plat_fiptool/nxp/plat_def_uuid_config.c
diff --git a/tools/nxp/plat_fiptool/plat_fiptool.mk b/tools/fiptool/plat_fiptool/nxp/plat_fiptool.mk
similarity index 80%
rename from tools/nxp/plat_fiptool/plat_fiptool.mk
rename to tools/fiptool/plat_fiptool/nxp/plat_fiptool.mk
index ca2962a..6d7b07b 100644
--- a/tools/nxp/plat_fiptool/plat_fiptool.mk
+++ b/tools/fiptool/plat_fiptool/nxp/plat_fiptool.mk
@@ -1,5 +1,6 @@
 #
 # Copyright (c) 2021, NXP. All rights reserved.
+# Copyright (c) 2023, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -9,7 +10,7 @@
 # in the plat_def_toc_entries[].
 PLAT_DEF_UUID_CONFIG_FILE_NAME	:= plat_def_uuid_config
 
-PLAT_DEF_UUID_CONFIG_FILE_PATH := ../nxp/plat_fiptool
+PLAT_DEF_UUID_CONFIG_FILE_PATH := plat_fiptool/nxp/
 
 PLAT_DEF_OID := yes
 PLAT_DEF_UUID := yes
@@ -18,8 +19,6 @@
 
 INCLUDE_PATHS += -I${PLAT_DEF_UUID_OID_CONFIG_PATH} \
 		 -I./
-# Clean the stale object file.
-$(shell rm ${PLAT_DEF_UUID_CONFIG_FILE_PATH}/${PLAT_DEF_UUID_CONFIG_FILE_NAME}.o)
 
 ifeq (${PLAT_DEF_OID},yes)
 HOSTCCFLAGS += -DPLAT_DEF_OID
diff --git a/plat/st/stm32mp1/plat_def_uuid_config.c b/tools/fiptool/plat_fiptool/st/stm32mp1/plat_def_uuid_config.c
similarity index 100%
rename from plat/st/stm32mp1/plat_def_uuid_config.c
rename to tools/fiptool/plat_fiptool/st/stm32mp1/plat_def_uuid_config.c
diff --git a/plat/st/stm32mp1/plat_fiptool.mk b/tools/fiptool/plat_fiptool/st/stm32mp1/plat_fiptool.mk
similarity index 87%
rename from plat/st/stm32mp1/plat_fiptool.mk
rename to tools/fiptool/plat_fiptool/st/stm32mp1/plat_fiptool.mk
index 00570c2..1ba47c1 100644
--- a/plat/st/stm32mp1/plat_fiptool.mk
+++ b/tools/fiptool/plat_fiptool/st/stm32mp1/plat_fiptool.mk
@@ -16,7 +16,7 @@
 ifeq (${PLAT_DEF_UUID},yes)
 HOSTCCFLAGS += -DPLAT_DEF_FIP_UUID
 
-${PLAT_DEF_UUID_FILE_NAME}.o: ${PLAT_DIR}${PLAT_DEF_UUID_FILE_NAME}.c
+${PLAT_DEF_UUID_FILE_NAME}.o: plat_fiptool/st/stm32mp1/${PLAT_DEF_UUID_FILE_NAME}.c
 	${HOSTCC} -c ${CPPFLAGS} ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@
 
 PLAT_OBJECTS += ${PLAT_DEF_UUID_FILE_NAME}.o