Merge "fix(plat/qemu): reboot/shutdown with low to high gpio" into integration
diff --git a/Makefile b/Makefile
index 4dbc2be..ec6f885 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -129,6 +129,23 @@
         $(error Unknown BRANCH_PROTECTION value ${BRANCH_PROTECTION})
 endif
 
+# FEAT_RME
+ifeq (${ENABLE_RME},1)
+# RME doesn't support PIE
+ifneq (${ENABLE_PIE},0)
+        $(error ENABLE_RME does not support PIE)
+endif
+# RME requires AARCH64
+ifneq (${ARCH},aarch64)
+        $(error ENABLE_RME requires AArch64)
+endif
+# RME requires el2 context to be saved for now.
+CTX_INCLUDE_EL2_REGS := 1
+CTX_INCLUDE_AARCH32_REGS := 0
+ARM_ARCH_MAJOR := 8
+ARM_ARCH_MINOR := 6
+endif
+
 # USE_SPINLOCK_CAS requires AArch64 build
 ifeq (${USE_SPINLOCK_CAS},1)
 ifneq (${ARCH},aarch64)
@@ -525,6 +542,14 @@
         ifeq ($(TS_SP_FW_CONFIG),1)
             DTC_CPPFLAGS	+=	-DTS_SP_FW_CONFIG
         endif
+
+        ifneq ($(ARM_BL2_SP_LIST_DTS),)
+            DTC_CPPFLAGS += -DARM_BL2_SP_LIST_DTS=$(ARM_BL2_SP_LIST_DTS)
+        endif
+
+        ifneq ($(SP_LAYOUT_FILE),)
+            BL2_ENABLE_SP_LOAD := 1
+        endif
     else
         # All other SPDs in spd directory
         SPD_DIR := spd
@@ -551,6 +576,18 @@
 endif
 
 ################################################################################
+# Include rmmd Makefile if RME is enabled
+################################################################################
+
+ifneq (${ENABLE_RME},0)
+ifneq (${ARCH},aarch64)
+	$(error ENABLE_RME requires AArch64)
+endif
+include services/std_svc/rmmd/rmmd.mk
+$(warning "RME is an experimental feature")
+endif
+
+################################################################################
 # Include the platform specific Makefile after the SPD Makefile (the platform
 # makefile may use all previous definitions in this file)
 ################################################################################
@@ -746,6 +783,10 @@
     endif
 endif
 
+ifeq ($(PSA_FWU_SUPPORT),1)
+    $(info PSA_FWU_SUPPORT is an experimental feature)
+endif
+
 ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1)
     ifeq (${ALLOW_RO_XLAT_TABLES}, 1)
         $(error "ALLOW_RO_XLAT_TABLES requires translation tables library v2")
@@ -764,10 +805,16 @@
 # Process platform overrideable behaviour
 ################################################################################
 
+ifdef BL1_SOURCES
+NEED_BL1 := yes
+endif
+
-# Using BL2 implies that a BL33 image also needs to be supplied for the FIP and
-# Certificate generation tools. This flag can be overridden by the platform.
 ifdef BL2_SOURCES
-        ifdef EL3_PAYLOAD_BASE
+	NEED_BL2 := yes
+
+	# Using BL2 implies that a BL33 image also needs to be supplied for the FIP and
+	# Certificate generation tools. This flag can be overridden by the platform.
+	ifdef EL3_PAYLOAD_BASE
                 # If booting an EL3 payload there is no need for a BL33 image
                 # in the FIP file.
                 NEED_BL33		:=	no
@@ -782,6 +829,10 @@
         endif
 endif
 
+ifdef BL2U_SOURCES
+NEED_BL2U := yes
+endif
+
 # If SCP_BL2 is given, we always want FIP to include it.
 ifdef SCP_BL2
         NEED_SCP_BL2		:=	yes
@@ -819,6 +870,10 @@
 FIP_ARGS += --align ${FIP_ALIGN}
 endif
 
+ifdef FDT_SOURCES
+NEED_FDT := yes
+endif
+
 ################################################################################
 # Include libraries' Makefile that are used in all BL
 ################################################################################
@@ -862,30 +917,22 @@
 ################################################################################
 # Include BL specific makefiles
 ################################################################################
-ifdef BL1_SOURCES
-NEED_BL1 := yes
+
+ifeq (${NEED_BL1},yes)
 include bl1/bl1.mk
 endif
 
-ifdef BL2_SOURCES
-NEED_BL2 := yes
+ifeq (${NEED_BL2},yes)
 include bl2/bl2.mk
 endif
 
-ifdef BL2U_SOURCES
-NEED_BL2U := yes
+ifeq (${NEED_BL2U},yes)
 include bl2u/bl2u.mk
 endif
 
 ifeq (${NEED_BL31},yes)
-ifdef BL31_SOURCES
 include bl31/bl31.mk
 endif
-endif
-
-ifdef FDT_SOURCES
-NEED_FDT := yes
-endif
 
 ################################################################################
 # Build options checks
@@ -894,6 +941,7 @@
 $(eval $(call assert_booleans,\
     $(sort \
         ALLOW_RO_XLAT_TABLES \
+        BL2_ENABLE_SP_LOAD \
         COLD_BOOT_SINGLE_CPU \
         CREATE_KEYS \
         CTX_INCLUDE_AARCH32_REGS \
@@ -913,6 +961,7 @@
         ENABLE_PIE \
         ENABLE_PMF \
         ENABLE_PSCI_STAT \
+        ENABLE_RME \
         ENABLE_RUNTIME_INSTRUMENTATION \
         ENABLE_SPE_FOR_LOWER_ELS \
         ENABLE_SVE_FOR_NS \
@@ -959,6 +1008,11 @@
         USE_SP804_TIMER \
         ENABLE_FEAT_RNG \
         ENABLE_FEAT_SB \
+        PSA_FWU_SUPPORT \
+        ENABLE_TRBE_FOR_NS \
+        ENABLE_SYS_REG_TRACE_FOR_NS \
+        ENABLE_TRF_FOR_NS \
+        ENABLE_FEAT_HCX \
 )))
 
 $(eval $(call assert_numerics,\
@@ -967,6 +1021,8 @@
         ARM_ARCH_MINOR \
         BRANCH_PROTECTION \
         FW_ENC_STATUS \
+        NR_OF_FW_BANKS \
+        NR_OF_IMAGES_IN_FW_BANK \
 )))
 
 ifdef KEY_SIZE
@@ -988,6 +1044,7 @@
         ALLOW_RO_XLAT_TABLES \
         ARM_ARCH_MAJOR \
         ARM_ARCH_MINOR \
+        BL2_ENABLE_SP_LOAD \
         COLD_BOOT_SINGLE_CPU \
         CTX_INCLUDE_AARCH32_REGS \
         CTX_INCLUDE_FPREGS \
@@ -1007,6 +1064,7 @@
         ENABLE_PIE \
         ENABLE_PMF \
         ENABLE_PSCI_STAT \
+        ENABLE_RME \
         ENABLE_RUNTIME_INSTRUMENTATION \
         ENABLE_SPE_FOR_LOWER_ELS \
         ENABLE_SVE_FOR_NS \
@@ -1054,6 +1112,13 @@
         USE_SP804_TIMER \
         ENABLE_FEAT_RNG \
         ENABLE_FEAT_SB \
+        NR_OF_FW_BANKS \
+        NR_OF_IMAGES_IN_FW_BANK \
+        PSA_FWU_SUPPORT \
+        ENABLE_TRBE_FOR_NS \
+        ENABLE_SYS_REG_TRACE_FOR_NS \
+        ENABLE_TRF_FOR_NS \
+        ENABLE_FEAT_HCX \
 )))
 
 ifeq (${SANITIZE_UB},trap)
@@ -1083,9 +1148,6 @@
 # Generate and include sp_gen.mk if SPD is spmd and SP_LAYOUT_FILE is defined
 ifeq (${SPD},spmd)
 ifdef SP_LAYOUT_FILE
-        ifeq (${SPMD_SPM_AT_SEL2},0)
-            $(error "SPMD with SPM at S-EL1 does not require SP_LAYOUT_FILE")
-        endif
         -include $(BUILD_PLAT)/sp_gen.mk
         FIP_DEPS += sp
         CRT_DEPS += sp
@@ -1123,7 +1185,7 @@
 
 # Expand build macros for the different images
 ifeq (${NEED_BL1},yes)
-$(eval $(call MAKE_BL,1))
+$(eval $(call MAKE_BL,bl1))
 endif
 
 ifeq (${NEED_BL2},yes)
@@ -1132,7 +1194,7 @@
 endif
 
 $(if ${BL2}, $(eval $(call TOOL_ADD_IMG,bl2,--${FIP_BL2_ARGS})),\
-	$(eval $(call MAKE_BL,2,${FIP_BL2_ARGS})))
+	$(eval $(call MAKE_BL,bl2,${FIP_BL2_ARGS})))
 endif
 
 ifeq (${NEED_SCP_BL2},yes)
@@ -1145,10 +1207,10 @@
 BL31_SOURCES := $(sort ${BL31_SOURCES})
 ifneq (${DECRYPTION_SUPPORT},none)
 $(if ${BL31}, $(eval $(call TOOL_ADD_IMG,bl31,--soc-fw,,$(ENCRYPT_BL31))),\
-	$(eval $(call MAKE_BL,31,soc-fw,,$(ENCRYPT_BL31))))
+	$(eval $(call MAKE_BL,bl31,soc-fw,,$(ENCRYPT_BL31))))
 else
 $(if ${BL31}, $(eval $(call TOOL_ADD_IMG,bl31,--soc-fw)),\
-	$(eval $(call MAKE_BL,31,soc-fw)))
+	$(eval $(call MAKE_BL,bl31,soc-fw)))
 endif
 endif
 
@@ -1161,14 +1223,25 @@
 BUILD_BL32 := $(if $(BL32),,$(if $(BL32_SOURCES),1))
 
 ifneq (${DECRYPTION_SUPPORT},none)
-$(if ${BUILD_BL32}, $(eval $(call MAKE_BL,32,tos-fw,,$(ENCRYPT_BL32))),\
+$(if ${BUILD_BL32}, $(eval $(call MAKE_BL,bl32,tos-fw,,$(ENCRYPT_BL32))),\
 	$(eval $(call TOOL_ADD_IMG,bl32,--tos-fw,,$(ENCRYPT_BL32))))
 else
-$(if ${BUILD_BL32}, $(eval $(call MAKE_BL,32,tos-fw)),\
+$(if ${BUILD_BL32}, $(eval $(call MAKE_BL,bl32,tos-fw)),\
 	$(eval $(call TOOL_ADD_IMG,bl32,--tos-fw)))
 endif
 endif
 
+# If RMM image is needed but RMM is not defined, Test Realm Payload (TRP)
+# needs to be built from RMM_SOURCES.
+ifeq (${NEED_RMM},yes)
+# Sort RMM source files to remove duplicates
+RMM_SOURCES := $(sort ${RMM_SOURCES})
+BUILD_RMM := $(if $(RMM),,$(if $(RMM_SOURCES),1))
+
+$(if ${BUILD_RMM}, $(eval $(call MAKE_BL,rmm,rmm-fw)),\
+         $(eval $(call TOOL_ADD_IMG,rmm,--rmm-fw)))
+endif
+
 # Add the BL33 image if required by the platform
 ifeq (${NEED_BL33},yes)
 $(eval $(call TOOL_ADD_IMG,bl33,--nt-fw))
@@ -1176,7 +1249,7 @@
 
 ifeq (${NEED_BL2U},yes)
 $(if ${BL2U}, $(eval $(call TOOL_ADD_IMG,bl2u,--ap-fwu-cfg,FWU_)),\
-	$(eval $(call MAKE_BL,2u,ap-fwu-cfg,FWU_)))
+	$(eval $(call MAKE_BL,bl2u,ap-fwu-cfg,FWU_)))
 endif
 
 # Expand build macros for the different images
diff --git a/bl1/aarch64/bl1_context_mgmt.c b/bl1/aarch64/bl1_context_mgmt.c
index 2a8d58e..b9a7e5b 100644
--- a/bl1/aarch64/bl1_context_mgmt.c
+++ b/bl1/aarch64/bl1_context_mgmt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,6 +16,7 @@
 
 /* Following contains the cpu context pointers. */
 static void *bl1_cpu_context_ptr[2];
+entry_point_info_t *bl2_ep_info;
 
 
 void *cm_get_context(uint32_t security_state)
@@ -30,6 +31,40 @@
 	bl1_cpu_context_ptr[security_state] = context;
 }
 
+#if ENABLE_RME
+/*******************************************************************************
+ * This function prepares the entry point information to run BL2 in Root world,
+ * i.e. EL3, for the case when FEAT_RME is enabled.
+ ******************************************************************************/
+void bl1_prepare_next_image(unsigned int image_id)
+{
+	image_desc_t *bl2_desc;
+
+	assert(image_id == BL2_IMAGE_ID);
+
+	/* Get the image descriptor. */
+	bl2_desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
+	assert(bl2_desc != NULL);
+
+	/* Get the entry point info. */
+	bl2_ep_info = &bl2_desc->ep_info;
+
+	bl2_ep_info->spsr = (uint32_t)SPSR_64(MODE_EL3, MODE_SP_ELX,
+						DISABLE_ALL_EXCEPTIONS);
+
+	/*
+	 * Flush cache since bl2_ep_info is accessed after MMU is disabled
+	 * before jumping to BL2.
+	 */
+	flush_dcache_range((uintptr_t)bl2_ep_info, sizeof(entry_point_info_t));
+
+	/* Indicate that image is in execution state. */
+	bl2_desc->state = IMAGE_STATE_EXECUTED;
+
+	/* Print debug info and flush the console before running BL2. */
+	print_entry_point_info(bl2_ep_info);
+}
+#else
 /*******************************************************************************
  * This function prepares the context for Secure/Normal world images.
  * Normal world images are transitioned to EL2(if supported) else EL1.
@@ -93,3 +128,4 @@
 
 	print_entry_point_info(next_bl_ep);
 }
+#endif /* ENABLE_RME */
diff --git a/bl1/aarch64/bl1_entrypoint.S b/bl1/aarch64/bl1_entrypoint.S
index 00f2718..f61c060 100644
--- a/bl1/aarch64/bl1_entrypoint.S
+++ b/bl1/aarch64/bl1_entrypoint.S
@@ -1,13 +1,15 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <arch.h>
+#include <common/bl_common.h>
 #include <el3_common_macros.S>
 
 	.globl	bl1_entrypoint
+	.globl	bl1_run_bl2_in_root
 
 
 	/* -----------------------------------------------------
@@ -66,5 +68,41 @@
 	 * Do the transition to next boot image.
 	 * --------------------------------------------------
 	 */
+#if ENABLE_RME
+	b	bl1_run_bl2_in_root
+#else
 	b	el3_exit
+#endif
 endfunc bl1_entrypoint
+
+	/* -----------------------------------------------------
+	 * void bl1_run_bl2_in_root();
+	 * This function runs BL2 in root/EL3 when RME is enabled.
+	 * -----------------------------------------------------
+	 */
+
+func bl1_run_bl2_in_root
+	/* read bl2_ep_info */
+	adrp	x20, bl2_ep_info
+	add	x20, x20, :lo12:bl2_ep_info
+	ldr	x20, [x20]
+
+	/* ---------------------------------------------
+	 * MMU needs to be disabled because BL2 executes
+	 * in EL3. It will initialize the address space
+	 * according to its own requirements.
+	 * ---------------------------------------------
+	 */
+	bl	disable_mmu_icache_el3
+	tlbi	alle3
+
+	ldp	x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET]
+	msr	elr_el3, x0
+	msr	spsr_el3, x1
+
+	ldp	x6, x7, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x30)]
+	ldp	x4, x5, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x20)]
+	ldp	x2, x3, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x10)]
+	ldp	x0, x1, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x0)]
+	exception_return
+endfunc bl1_run_bl2_in_root
diff --git a/bl1/bl1.mk b/bl1/bl1.mk
index d11b4ab..9f63fd5 100644
--- a/bl1/bl1.mk
+++ b/bl1/bl1.mk
@@ -1,14 +1,14 @@
 #
-# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
-BL1_SOURCES		+=	bl1/bl1_main.c				\
-				bl1/${ARCH}/bl1_arch_setup.c		\
+BL1_SOURCES		+=	bl1/${ARCH}/bl1_arch_setup.c		\
 				bl1/${ARCH}/bl1_context_mgmt.c		\
 				bl1/${ARCH}/bl1_entrypoint.S		\
 				bl1/${ARCH}/bl1_exceptions.S		\
+				bl1/bl1_main.c				\
 				lib/cpus/${ARCH}/cpu_helpers.S		\
 				lib/cpus/errata_report.c		\
 				lib/el3_runtime/${ARCH}/context_mgmt.c	\
diff --git a/bl1/bl1_private.h b/bl1/bl1_private.h
index 2cfeeea..e119ba7 100644
--- a/bl1/bl1_private.h
+++ b/bl1/bl1_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,6 +11,8 @@
 
 #include <common/bl_common.h>
 
+extern entry_point_info_t *bl2_ep_info;
+
 /******************************************
  * Function prototypes
  *****************************************/
@@ -18,6 +20,7 @@
 void bl1_arch_next_el_setup(void);
 
 void bl1_prepare_next_image(unsigned int image_id);
+void bl1_run_bl2_in_root(void);
 
 u_register_t bl1_fwu_smc_handler(unsigned int smc_fid,
 		u_register_t x1,
diff --git a/bl2/aarch32/bl2_el3_entrypoint.S b/bl2/aarch32/bl2_el3_entrypoint.S
index 7e85551..40154aa 100644
--- a/bl2/aarch32/bl2_el3_entrypoint.S
+++ b/bl2/aarch32/bl2_el3_entrypoint.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,7 +10,6 @@
 #include <el3_common_macros.S>
 
 	.globl	bl2_entrypoint
-	.globl	bl2_run_next_image
 
 
 func bl2_entrypoint
@@ -56,37 +55,3 @@
 	no_ret	plat_panic_handler
 
 endfunc bl2_entrypoint
-
-func bl2_run_next_image
-	mov	r8,r0
-
-	/*
-	 * MMU needs to be disabled because both BL2 and BL32 execute
-	 * in PL1, and therefore share the same address space.
-	 * BL32 will initialize the address space according to its
-	 * own requirement.
-	 */
-	bl	disable_mmu_icache_secure
-	stcopr	r0, TLBIALL
-	dsb	sy
-	isb
-	mov	r0, r8
-	bl	bl2_el3_plat_prepare_exit
-
-	/*
-	 * Extract PC and SPSR based on struct `entry_point_info_t`
-	 * and load it in LR and SPSR registers respectively.
-	 */
-	ldr	lr, [r8, #ENTRY_POINT_INFO_PC_OFFSET]
-	ldr	r1, [r8, #(ENTRY_POINT_INFO_PC_OFFSET + 4)]
-	msr	spsr_xc, r1
-
-	/* Some BL32 stages expect lr_svc to provide the BL33 entry address */
-	cps	#MODE32_svc
-	ldr	lr, [r8, #ENTRY_POINT_INFO_LR_SVC_OFFSET]
-	cps	#MODE32_mon
-
-	add	r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET
-	ldm	r8, {r0, r1, r2, r3}
-	exception_return
-endfunc bl2_run_next_image
diff --git a/bl2/aarch32/bl2_run_next_image.S b/bl2/aarch32/bl2_run_next_image.S
new file mode 100644
index 0000000..0b3554e
--- /dev/null
+++ b/bl2/aarch32/bl2_run_next_image.S
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+
+	.globl	bl2_run_next_image
+
+
+func bl2_run_next_image
+	mov	r8,r0
+
+	/*
+	 * MMU needs to be disabled because both BL2 and BL32 execute
+	 * in PL1, and therefore share the same address space.
+	 * BL32 will initialize the address space according to its
+	 * own requirement.
+	 */
+	bl	disable_mmu_icache_secure
+	stcopr	r0, TLBIALL
+	dsb	sy
+	isb
+	mov	r0, r8
+	bl	bl2_el3_plat_prepare_exit
+
+	/*
+	 * Extract PC and SPSR based on struct `entry_point_info_t`
+	 * and load it in LR and SPSR registers respectively.
+	 */
+	ldr	lr, [r8, #ENTRY_POINT_INFO_PC_OFFSET]
+	ldr	r1, [r8, #(ENTRY_POINT_INFO_PC_OFFSET + 4)]
+	msr	spsr_xc, r1
+
+	/* Some BL32 stages expect lr_svc to provide the BL33 entry address */
+	cps	#MODE32_svc
+	ldr	lr, [r8, #ENTRY_POINT_INFO_LR_SVC_OFFSET]
+	cps	#MODE32_mon
+
+	add	r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET
+	ldm	r8, {r0, r1, r2, r3}
+	exception_return
+endfunc bl2_run_next_image
diff --git a/bl2/aarch64/bl2_el3_entrypoint.S b/bl2/aarch64/bl2_el3_entrypoint.S
index 4eab39c..45bac7d 100644
--- a/bl2/aarch64/bl2_el3_entrypoint.S
+++ b/bl2/aarch64/bl2_el3_entrypoint.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,8 +12,6 @@
 #include <el3_common_macros.S>
 
 	.globl	bl2_entrypoint
-	.globl	bl2_el3_run_image
-	.globl	bl2_run_next_image
 
 #if BL2_IN_XIP_MEM
 #define FIXUP_SIZE	0
@@ -72,36 +70,3 @@
 	 */
 	no_ret	plat_panic_handler
 endfunc bl2_entrypoint
-
-func bl2_run_next_image
-	mov	x20,x0
-	/* ---------------------------------------------
-	 * MMU needs to be disabled because both BL2 and BL31 execute
-	 * in EL3, and therefore share the same address space.
-	 * BL31 will initialize the address space according to its
-	 * own requirement.
-	 * ---------------------------------------------
-	 */
-	bl	disable_mmu_icache_el3
-	tlbi	alle3
-	bl	bl2_el3_plat_prepare_exit
-
-#if ENABLE_PAUTH
-	/* ---------------------------------------------
-	 * Disable pointer authentication before jumping
-	 * to next boot image.
-	 * ---------------------------------------------
-	 */
-	bl	pauth_disable_el3
-#endif /* ENABLE_PAUTH */
-
-	ldp	x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET]
-	msr	elr_el3, x0
-	msr	spsr_el3, x1
-
-	ldp	x6, x7, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x30)]
-	ldp	x4, x5, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x20)]
-	ldp	x2, x3, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x10)]
-	ldp	x0, x1, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x0)]
-	exception_return
-endfunc bl2_run_next_image
diff --git a/bl2/aarch64/bl2_rme_entrypoint.S b/bl2/aarch64/bl2_rme_entrypoint.S
new file mode 100644
index 0000000..076e326
--- /dev/null
+++ b/bl2/aarch64/bl2_rme_entrypoint.S
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <el3_common_macros.S>
+
+	.globl	bl2_entrypoint
+
+
+func bl2_entrypoint
+	/* Save arguments x0-x3 from previous Boot loader */
+	mov	x20, x0
+	mov	x21, x1
+	mov	x22, x2
+	mov	x23, x3
+
+	el3_entrypoint_common                                   \
+		_init_sctlr=0                                   \
+		_warm_boot_mailbox=0                            \
+		_secondary_cold_boot=0                          \
+		_init_memory=0                                  \
+		_init_c_runtime=1                               \
+		_exception_vectors=bl2_el3_exceptions           \
+		_pie_fixup_size=0
+
+	/* ---------------------------------------------
+	 * Restore parameters of boot rom
+	 * ---------------------------------------------
+	 */
+	mov	x0, x20
+	mov	x1, x21
+	mov	x2, x22
+	mov	x3, x23
+
+	/* ---------------------------------------------
+	 * Perform BL2 setup
+	 * ---------------------------------------------
+	 */
+	bl	bl2_setup
+
+#if ENABLE_PAUTH
+	/* ---------------------------------------------
+	 * Program APIAKey_EL1 and enable pointer authentication.
+	 * ---------------------------------------------
+	 */
+	bl	pauth_init_enable_el3
+#endif /* ENABLE_PAUTH */
+
+	/* ---------------------------------------------
+	 * Jump to main function.
+	 * ---------------------------------------------
+	 */
+	bl	bl2_main
+
+	/* ---------------------------------------------
+	 * Should never reach this point.
+	 * ---------------------------------------------
+	 */
+	no_ret	plat_panic_handler
+endfunc bl2_entrypoint
diff --git a/bl2/aarch64/bl2_run_next_image.S b/bl2/aarch64/bl2_run_next_image.S
new file mode 100644
index 0000000..f0a8be8
--- /dev/null
+++ b/bl2/aarch64/bl2_run_next_image.S
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+
+	.globl	bl2_run_next_image
+
+
+func bl2_run_next_image
+	mov	x20,x0
+	/* ---------------------------------------------
+	 * MMU needs to be disabled because both BL2 and BL31 execute
+	 * in EL3, and therefore share the same address space.
+	 * BL31 will initialize the address space according to its
+	 * own requirement.
+	 * ---------------------------------------------
+	 */
+	bl	disable_mmu_icache_el3
+	tlbi	alle3
+	bl	bl2_el3_plat_prepare_exit
+
+#if ENABLE_PAUTH
+	/* ---------------------------------------------
+	 * Disable pointer authentication before jumping
+	 * to next boot image.
+	 * ---------------------------------------------
+	 */
+	bl	pauth_disable_el3
+#endif /* ENABLE_PAUTH */
+
+	ldp	x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET]
+	msr	elr_el3, x0
+	msr	spsr_el3, x1
+
+	ldp	x6, x7, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x30)]
+	ldp	x4, x5, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x20)]
+	ldp	x2, x3, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x10)]
+	ldp	x0, x1, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x0)]
+	exception_return
+endfunc bl2_run_next_image
diff --git a/bl2/bl2.ld.S b/bl2/bl2.ld.S
index 37849c3..d332ec0 100644
--- a/bl2/bl2.ld.S
+++ b/bl2/bl2.ld.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -25,7 +25,11 @@
 #if SEPARATE_CODE_AND_RODATA
     .text . : {
         __TEXT_START__ = .;
+#if ENABLE_RME
+        *bl2_rme_entrypoint.o(.text*)
+#else /* ENABLE_RME */
         *bl2_entrypoint.o(.text*)
+#endif /* ENABLE_RME */
         *(SORT_BY_ALIGNMENT(.text*))
         *(.vectors)
         . = ALIGN(PAGE_SIZE);
diff --git a/bl2/bl2.mk b/bl2/bl2.mk
index 735e7e0..7a973e5 100644
--- a/bl2/bl2.mk
+++ b/bl2/bl2.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -15,13 +15,26 @@
 BL2_SOURCES		+=	common/aarch64/early_exceptions.S
 endif
 
-ifeq (${BL2_AT_EL3},0)
+ifeq (${ENABLE_RME},1)
+# Using RME, run BL2 at EL3
+include lib/gpt_rme/gpt_rme.mk
+
+BL2_SOURCES		+=      bl2/${ARCH}/bl2_rme_entrypoint.S	\
+				bl2/${ARCH}/bl2_el3_exceptions.S	\
+				bl2/${ARCH}/bl2_run_next_image.S	\
+				${GPT_LIB_SRCS}
+BL2_LINKERFILE		:=	bl2/bl2.ld.S
+
+else ifeq (${BL2_AT_EL3},0)
+# Normal operation, no RME, no BL2 at EL3
 BL2_SOURCES		+=	bl2/${ARCH}/bl2_entrypoint.S
 BL2_LINKERFILE		:=	bl2/bl2.ld.S
 
 else
+# BL2 at EL3, no RME
 BL2_SOURCES		+=	bl2/${ARCH}/bl2_el3_entrypoint.S	\
 				bl2/${ARCH}/bl2_el3_exceptions.S	\
+				bl2/${ARCH}/bl2_run_next_image.S        \
 				lib/cpus/${ARCH}/cpu_helpers.S		\
 				lib/cpus/errata_report.c
 
diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c
index 203e1d4..197c057 100644
--- a/bl2/bl2_main.c
+++ b/bl2/bl2_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,6 +14,7 @@
 #include <common/debug.h>
 #include <drivers/auth/auth_mod.h>
 #include <drivers/console.h>
+#include <drivers/fwu/fwu.h>
 #if MEASURED_BOOT
 #include <drivers/measured_boot/measured_boot.h>
 #endif
@@ -28,18 +29,18 @@
 #define NEXT_IMAGE	"BL32"
 #endif
 
-#if !BL2_AT_EL3
+#if BL2_AT_EL3
 /*******************************************************************************
- * Setup function for BL2.
+ * Setup function for BL2 when BL2_AT_EL3=1
  ******************************************************************************/
-void bl2_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2,
-	       u_register_t arg3)
+void bl2_el3_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2,
+		   u_register_t arg3)
 {
 	/* Perform early platform-specific setup */
-	bl2_early_platform_setup2(arg0, arg1, arg2, arg3);
+	bl2_el3_early_platform_setup(arg0, arg1, arg2, arg3);
 
 	/* Perform late platform-specific setup */
-	bl2_plat_arch_setup();
+	bl2_el3_plat_arch_setup();
 
 #if CTX_INCLUDE_PAUTH_REGS
 	/*
@@ -49,19 +50,18 @@
 	assert(is_armv8_3_pauth_present());
 #endif /* CTX_INCLUDE_PAUTH_REGS */
 }
-
-#else /* if BL2_AT_EL3 */
+#else /* BL2_AT_EL3 */
 /*******************************************************************************
- * Setup function for BL2 when BL2_AT_EL3=1.
+ * Setup function for BL2 when BL2_AT_EL3=0
  ******************************************************************************/
-void bl2_el3_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2,
-		   u_register_t arg3)
+void bl2_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2,
+	       u_register_t arg3)
 {
 	/* Perform early platform-specific setup */
-	bl2_el3_early_platform_setup(arg0, arg1, arg2, arg3);
+	bl2_early_platform_setup2(arg0, arg1, arg2, arg3);
 
 	/* Perform late platform-specific setup */
-	bl2_el3_plat_arch_setup();
+	bl2_plat_arch_setup();
 
 #if CTX_INCLUDE_PAUTH_REGS
 	/*
@@ -88,6 +88,10 @@
 	/* Perform remaining generic architectural setup in S-EL1 */
 	bl2_arch_setup();
 
+#if PSA_FWU_SUPPORT
+	fwu_init();
+#endif /* PSA_FWU_SUPPORT */
+
 #if TRUSTED_BOARD_BOOT
 	/* Initialize authentication module */
 	auth_mod_init();
@@ -110,7 +114,7 @@
 	measured_boot_finish();
 #endif /* MEASURED_BOOT */
 
-#if !BL2_AT_EL3
+#if !BL2_AT_EL3 && !ENABLE_RME
 #ifndef __aarch64__
 	/*
 	 * For AArch32 state BL1 and BL2 share the MMU setup.
@@ -135,7 +139,7 @@
 	 * be passed to next BL image as an argument.
 	 */
 	smc(BL1_SMC_RUN_IMAGE, (unsigned long)next_bl_ep_info, 0, 0, 0, 0, 0, 0);
-#else /* if BL2_AT_EL3 */
+#else /* if BL2_AT_EL3 || ENABLE_RME */
 	NOTICE("BL2: Booting " NEXT_IMAGE "\n");
 	print_entry_point_info(next_bl_ep_info);
 	console_flush();
@@ -148,5 +152,5 @@
 #endif /* ENABLE_PAUTH */
 
 	bl2_run_next_image(next_bl_ep_info);
-#endif /* BL2_AT_EL3 */
+#endif /* BL2_AT_EL3 && ENABLE_RME */
 }
diff --git a/bl31/aarch64/bl31_entrypoint.S b/bl31/aarch64/bl31_entrypoint.S
index 2d672dd..ed05864 100644
--- a/bl31/aarch64/bl31_entrypoint.S
+++ b/bl31/aarch64/bl31_entrypoint.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -195,6 +195,19 @@
 #endif
 	bl	bl31_plat_enable_mmu
 
+#if ENABLE_RME
+	/*
+	 * At warm boot GPT data structures have already been initialized in RAM
+	 * but the sysregs for this CPU need to be initialized. Note that the GPT
+	 * accesses are controlled attributes in GPCCR and do not depend on the
+	 * SCR_EL3.C bit.
+	 */
+	bl	gpt_enable
+	cbz	x0, 1f
+	no_ret plat_panic_handler
+1:
+#endif
+
 #if ENABLE_PAUTH
 	/* --------------------------------------------------------------------
 	 * Program APIAKey_EL1 and enable pointer authentication
diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S
index 51eb2bd..0d0a12d 100644
--- a/bl31/aarch64/runtime_exceptions.S
+++ b/bl31/aarch64/runtime_exceptions.S
@@ -500,6 +500,21 @@
 	stp	x16, x17, [x6, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
 	str	x18, [x6, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
 
+	/* Clear flag register */
+	mov	x7, xzr
+
+#if ENABLE_RME
+	/* Copy SCR_EL3.NSE bit to the flag to indicate caller's security */
+	ubfx	x7, x18, #SCR_NSE_SHIFT, 1
+
+	/*
+	 * Shift copied SCR_EL3.NSE bit by 5 to create space for
+	 * SCR_EL3.NS bit. Bit 5 of the flag correspondes to
+	 * the SCR_EL3.NSE bit.
+	 */
+	lsl	x7, x7, #5
+#endif /* ENABLE_RME */
+
 	/* Copy SCR_EL3.NS bit to the flag to indicate caller's security */
 	bfi	x7, x18, #0, #1
 
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index 1fdf545..106d410 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -90,6 +90,18 @@
 BL31_SOURCES		+=	lib/extensions/mpam/mpam.c
 endif
 
+ifeq (${ENABLE_TRBE_FOR_NS},1)
+BL31_SOURCES		+=	lib/extensions/trbe/trbe.c
+endif
+
+ifeq (${ENABLE_SYS_REG_TRACE_FOR_NS},1)
+BL31_SOURCES		+=      lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c
+endif
+
+ifeq (${ENABLE_TRF_FOR_NS},1)
+BL31_SOURCES		+=	lib/extensions/trf/aarch64/trf.c
+endif
+
 ifeq (${WORKAROUND_CVE_2017_5715},1)
 BL31_SOURCES		+=	lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S	\
 				lib/cpus/aarch64/wa_cve_2017_5715_mmu.S
@@ -99,6 +111,13 @@
 BL31_SOURCES		+=	services/std_svc/pci_svc.c
 endif
 
+ifeq (${ENABLE_RME},1)
+include lib/gpt_rme/gpt_rme.mk
+
+BL31_SOURCES		+=	${GPT_LIB_SRCS}					\
+				${RMMD_SOURCES}
+endif
+
 BL31_LINKERFILE		:=	bl31/bl31.ld.S
 
 # Flag used to indicate if Crash reporting via console should be included
diff --git a/bl31/bl31_context_mgmt.c b/bl31/bl31_context_mgmt.c
index 9175ee3..34f69ad 100644
--- a/bl31/bl31_context_mgmt.c
+++ b/bl31/bl31_context_mgmt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,9 +19,9 @@
  ******************************************************************************/
 void *cm_get_context(uint32_t security_state)
 {
-	assert(security_state <= NON_SECURE);
+	assert(sec_state_is_valid(security_state));
 
-	return get_cpu_data(cpu_context[security_state]);
+	return get_cpu_data(cpu_context[get_cpu_context_index(security_state)]);
 }
 
 /*******************************************************************************
@@ -30,9 +30,10 @@
  ******************************************************************************/
 void cm_set_context(void *context, uint32_t security_state)
 {
-	assert(security_state <= NON_SECURE);
+	assert(sec_state_is_valid(security_state));
 
-	set_cpu_data(cpu_context[security_state], context);
+	set_cpu_data(cpu_context[get_cpu_context_index(security_state)],
+			context);
 }
 
 /*******************************************************************************
@@ -46,7 +47,8 @@
 {
 	assert(sec_state_is_valid(security_state));
 
-	return get_cpu_data_by_index(cpu_idx, cpu_context[security_state]);
+	return get_cpu_data_by_index(cpu_idx,
+			cpu_context[get_cpu_context_index(security_state)]);
 }
 
 /*******************************************************************************
@@ -58,5 +60,7 @@
 {
 	assert(sec_state_is_valid(security_state));
 
-	set_cpu_data_by_index(cpu_idx, cpu_context[security_state], context);
+	set_cpu_data_by_index(cpu_idx,
+			cpu_context[get_cpu_context_index(security_state)],
+			context);
 }
diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c
index 44bf32c..9ac10e2 100644
--- a/bl31/bl31_main.c
+++ b/bl31/bl31_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -35,6 +35,13 @@
  ******************************************************************************/
 static int32_t (*bl32_init)(void);
 
+/*****************************************************************************
+ * Function used to initialise RMM if RME is enabled
+ *****************************************************************************/
+#if ENABLE_RME
+static int32_t (*rmm_init)(void);
+#endif
+
 /*******************************************************************************
  * Variable to indicate whether next image to execute after BL31 is BL33
  * (non-secure & default) or BL32 (secure).
@@ -85,6 +92,15 @@
 	/* Perform late platform-specific setup */
 	bl31_plat_arch_setup();
 
+#if ENABLE_FEAT_HCX
+	/*
+	 * Assert that FEAT_HCX is supported on this system, without this check
+	 * an exception would occur during context save/restore if enabled but
+	 * not supported.
+	 */
+	assert(is_feat_hcx_present());
+#endif /* ENABLE_FEAT_HCX */
+
 #if CTX_INCLUDE_PAUTH_REGS
 	/*
 	 * Assert that the ARMv8.3-PAuth registers are present or an access
@@ -130,12 +146,15 @@
 
 	/*
 	 * All the cold boot actions on the primary cpu are done. We now need to
-	 * decide which is the next image (BL32 or BL33) and how to execute it.
+	 * decide which is the next image and how to execute it.
 	 * If the SPD runtime service is present, it would want to pass control
 	 * to BL32 first in S-EL1. In that case, SPD would have registered a
 	 * function to initialize bl32 where it takes responsibility of entering
-	 * S-EL1 and returning control back to bl31_main. Once this is done we
-	 * can prepare entry into BL33 as normal.
+	 * S-EL1 and returning control back to bl31_main. Similarly, if RME is
+	 * enabled and a function is registered to initialize RMM, control is
+	 * transferred to RMM in R-EL2. After RMM initialization, control is
+	 * returned back to bl31_main. Once this is done we can prepare entry
+	 * into BL33 as normal.
 	 */
 
 	/*
@@ -146,9 +165,27 @@
 
 		int32_t rc = (*bl32_init)();
 
-		if (rc == 0)
+		if (rc == 0) {
 			WARN("BL31: BL32 initialization failed\n");
+		}
 	}
+
+	/*
+	 * If RME is enabled and init hook is registered, initialize RMM
+	 * in R-EL2.
+	 */
+#if ENABLE_RME
+	if (rmm_init != NULL) {
+		INFO("BL31: Initializing RMM\n");
+
+		int32_t rc = (*rmm_init)();
+
+		if (rc == 0) {
+			WARN("BL31: RMM initialization failed\n");
+		}
+	}
+#endif
+
 	/*
 	 * We are ready to enter the next EL. Prepare entry into the image
 	 * corresponding to the desired security state after the next ERET.
@@ -227,3 +264,14 @@
 {
 	bl32_init = func;
 }
+
+#if ENABLE_RME
+/*******************************************************************************
+ * This function initializes the pointer to RMM init function. This is expected
+ * to be called by the RMMD after it finishes all its initialization
+ ******************************************************************************/
+void bl31_register_rmm_init(int32_t (*func)(void))
+{
+	rmm_init = func;
+}
+#endif
diff --git a/bl32/sp_min/sp_min.mk b/bl32/sp_min/sp_min.mk
index 8b5eddd..6339cf8 100644
--- a/bl32/sp_min/sp_min.mk
+++ b/bl32/sp_min/sp_min.mk
@@ -42,6 +42,14 @@
 				services/std_svc/trng/trng_entropy_pool.c
 endif
 
+ifeq (${ENABLE_SYS_REG_TRACE_FOR_NS},1)
+BL32_SOURCES		+=	lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c
+endif
+
+ifeq (${ENABLE_TRF_FOR_NS},1)
+BL32_SOURCES		+=	lib/extensions/trf/aarch32/trf.c
+endif
+
 BL32_LINKERFILE	:=	bl32/sp_min/sp_min.ld.S
 
 # Include the platform-specific SP_MIN Makefile
diff --git a/common/bl_common.c b/common/bl_common.c
index f17afcb..a7e2816 100644
--- a/common/bl_common.c
+++ b/common/bl_common.c
@@ -239,9 +239,18 @@
 {
 	int err;
 
+/*
+ * All firmware banks should be part of the same non-volatile storage as per
+ * PSA FWU specification, hence don't check for any alternate boot source
+ * when PSA FWU is enabled.
+ */
+#if PSA_FWU_SUPPORT
+	err = load_auth_image_internal(image_id, image_data);
+#else
 	do {
 		err = load_auth_image_internal(image_id, image_data);
 	} while ((err != 0) && (plat_try_next_boot_source() != 0));
+#endif /* PSA_FWU_SUPPORT */
 
 	return err;
 }
diff --git a/common/hw_crc32.c b/common/tf_crc32.c
similarity index 86%
rename from common/hw_crc32.c
rename to common/tf_crc32.c
index a8731da..b33d36e 100644
--- a/common/hw_crc32.c
+++ b/common/tf_crc32.c
@@ -9,8 +9,9 @@
 
 #include <arm_acle.h>
 #include <common/debug.h>
+#include <common/tf_crc32.h>
 
-/* hw_crc32 - compute CRC using Arm intrinsic function
+/* compute CRC using Arm intrinsic function
  *
  * This function is useful for the platforms with the CPU ARMv8.0
  * (with CRC instructions supported), and onwards.
@@ -23,7 +24,7 @@
  *
  * Return calculated CRC value
  */
-uint32_t hw_crc32(uint32_t crc, const unsigned char *buf, size_t size)
+uint32_t tf_crc32(uint32_t crc, const unsigned char *buf, size_t size)
 {
 	assert(buf != NULL);
 
diff --git a/common/tf_log.c b/common/tf_log.c
index 08d3cf4..68f1be4 100644
--- a/common/tf_log.c
+++ b/common/tf_log.c
@@ -49,6 +49,20 @@
 	va_end(args);
 }
 
+void tf_log_newline(const char log_fmt[2])
+{
+	unsigned int log_level = log_fmt[0];
+
+	/* Verify that log_level is one of LOG_MARKER_* macro defined in debug.h */
+	assert((log_level > 0U) && (log_level <= LOG_LEVEL_VERBOSE));
+	assert((log_level % 10U) == 0U);
+
+	if (log_level > max_log_level)
+		return;
+
+	putchar('\n');
+}
+
 /*
  * The helper function to set the log level dynamically by platform. The
  * maximum log level is determined by `LOG_LEVEL` build flag at compile time
diff --git a/common/uuid.c b/common/uuid.c
index dd3c7b0..ac6db50 100644
--- a/common/uuid.c
+++ b/common/uuid.c
@@ -73,6 +73,7 @@
 int read_uuid(uint8_t *dest, char *uuid)
 {
 	int err;
+	uint8_t *dest_start = dest;
 
 	/* Check that we have enough characters */
 	if (strnlen(uuid, UUID_STRING_LENGTH) != UUID_STRING_LENGTH) {
@@ -124,7 +125,7 @@
 	if (err < 0) {
 		WARN("Error parsing UUID\n");
 		/* Clear the buffer on error */
-		memset((void *)dest, '\0', UUID_BYTES_LENGTH * sizeof(uint8_t));
+		memset((void *)dest_start, '\0', UUID_BYTES_LENGTH * sizeof(uint8_t));
 		return -EINVAL;
 	}
 
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index d014fbd..7db81fc 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -109,6 +109,16 @@
 :|G|: `john-powell-arm`_
 :|F|: bl31/ehf.c
 
+Realm Management Extension (RME)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:|M|: Bipin Ravi <bipin.ravi@arm.com>
+:|G|: `bipinravi-arm`_
+:|M|: Mark Dykes <mark.dykes@arm.com>
+:|G|: `mardyk01`_
+:|M|: John Powell <John.Powell@arm.com>
+:|G|: `john-powell-arm`_
+:|M|: Zelalem Aweke <Zelalem.Aweke@arm.com>
+:|G|: `zelalem-aweke`_
 
 Drivers, Libraries and Framework Code
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -399,6 +409,7 @@
 :|G|: `vishnu-banavath`_
 :|F|: plat/arm/board/corstone700
 :|F|: plat/arm/board/a5ds
+:|F|: plat/arm/board/diphda
 
 Arm Reference Design platform ports
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -414,13 +425,13 @@
 :|F|: plat/arm/board/rdv1mc/
 :|F|: plat/arm/board/sgi575/
 
-Arm Total Compute(tc0) platform port
+Arm Total Compute platform port
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 :|M|: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
 :|G|: `arugan02`_
 :|M|: Usama Arif <usama.arif@arm.com>
 :|G|: `uarif1`_
-:|F|: plat/arm/board/tc0
+:|F|: plat/arm/board/tc
 
 HiSilicon HiKey and HiKey960 platform ports
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -493,8 +504,8 @@
 
 NXP i.MX 8 platform port
 ^^^^^^^^^^^^^^^^^^^^^^^^
-:|M|: Anson Huang <Anson.Huang@nxp.com>
-:|G|: `Anson-Huang`_
+:|M|: Peng Fan <peng.fan@nxp.com>
+:|G|: `MrVan`_
 :|F|: docs/plat/imx8.rst
 :|F|: plat/imx/
 
@@ -534,7 +545,10 @@
 ^^^^^^^^^^^^^^^^^
 :|M|: Saurabh Gorecha <sgorecha@codeaurora.org>
 :|G|: `sgorecha`_
-:|M|: Debasish Mandal <dmandal@codeaurora.org>
+:|M|: Lachit Patel <lpatel@codeaurora.org>
+:|G|: `lachitp`_
+:|M|: Sreevyshanavi Kare <skare@codeaurora.org>
+:|G|: `sreekare`_
 :|M|: QTI TF Maintainers <qti.trustedfirmware.maintainers@codeaurora.org>
 :|F|: docs/plat/qti.rst
 :|F|: plat/qti/
@@ -594,6 +608,8 @@
 :|G|: `rockchip-linux`_
 :|M|: Heiko Stuebner <heiko@sntech.de>
 :|G|: `mmind`_
+:|M|: Julius Werner <jwerner@chromium.org>
+:|G|: `jwerner-chromium`_
 :|F|: plat/rockchip/
 
 STM32MP1 platform port
@@ -729,6 +745,7 @@
 .. _jenswi-linaro: https://github.com/jenswi-linaro
 .. _jwerner-chromium: https://github.com/jwerner-chromium
 .. _kostapr: https://github.com/kostapr
+.. _lachitp: https://github.com/lachitp
 .. _ldts: https://github.com/ldts
 .. _marex: https://github.com/marex
 .. _masahir0y: https://github.com/masahir0y
@@ -747,6 +764,7 @@
 .. _shawnguo2: https://github.com/shawnguo2
 .. _smaeul: https://github.com/smaeul
 .. _soby-mathew: https://github.com/soby-mathew
+.. _sreekare: https://github.com/sreekare
 .. _thloh85-intel: https://github.com/thloh85-intel
 .. _thomas-arm: https://github.com/thomas-arm
 .. _TonyXie06: https://github.com/TonyXie06
diff --git a/docs/about/release-information.rst b/docs/about/release-information.rst
index 3e8dd91..b65571d 100644
--- a/docs/about/release-information.rst
+++ b/docs/about/release-information.rst
@@ -46,7 +46,7 @@
 +-----------------+---------------------------+------------------------------+
 | v2.5            | 3rd week of May '21       | 5th week of Apr '21          |
 +-----------------+---------------------------+------------------------------+
-| v2.6            | 4th week of Oct '21       | 1st week of Oct '21          |
+| v2.6            | 4th week of Nov '21       | 2nd week of Nov '21          |
 +-----------------+---------------------------+------------------------------+
 
 Removal of Deprecated Interfaces
diff --git a/docs/components/ffa-manifest-binding.rst b/docs/components/ffa-manifest-binding.rst
index 9e3919d..df2985c 100644
--- a/docs/components/ffa-manifest-binding.rst
+++ b/docs/components/ffa-manifest-binding.rst
@@ -106,14 +106,17 @@
      The "compatible" must be the string "arm,ffa-manifest-rx_tx-buffer".
 
 - messaging-method [mandatory]
-   - value type: <u32>
-   - Specifies which messaging methods are supported by the partition:
+   - value type: <u8>
+   - Specifies which messaging methods are supported by the partition, set bit
+     means the feature is supported, clear bit - not supported:
+
+      - Bit[0]: partition can receive direct requests if set
+      - Bit[1]: partition can send direct requests if set
+      - Bit[2]: partition can send and receive indirect messages
 
-      - 0x0: direct messaging method
-      - 0x1: indirect messaging method
-      - 0x2: both direct and indirect messaging methods
-      - 0x3: direct messaging method with managed exit support
-      - 0x4: both messaging methods with managed exit support
+- managed-exit
+   - value type: <empty>
+   - Specifies if managed exit is supported.
 
 - has-primary-scheduler
    - value type: <empty>
diff --git a/docs/components/index.rst b/docs/components/index.rst
index 2409f96..f349d8d 100644
--- a/docs/components/index.rst
+++ b/docs/components/index.rst
@@ -22,3 +22,4 @@
    ffa-manifest-binding
    xlat-tables-lib-v2-design
    cot-binding
+   realm-management-extension
diff --git a/docs/components/realm-management-extension.rst b/docs/components/realm-management-extension.rst
new file mode 100644
index 0000000..5c580f3
--- /dev/null
+++ b/docs/components/realm-management-extension.rst
@@ -0,0 +1,194 @@
+
+Realm Management Extension (RME)
+====================================
+
+FEAT_RME (or RME for short) is an Armv9-A extension and is one component of the
+`Arm Confidential Compute Architecture (Arm CCA)`_. TF-A supports RME starting
+from version 2.6. This document provides instructions on how to build and run
+TF-A with RME.
+
+Building and running TF-A with RME
+------------------------------------
+
+This section describes how you can build and run TF-A with RME enabled.
+We assume you have all the :ref:`Prerequisites` to build TF-A.
+
+To enable RME, you need to set the ENABLE_RME build flag when building
+TF-A. Currently, this feature is only supported for the FVP platform.
+
+The following instructions show you how to build and run TF-A with RME
+for two scenarios: TF-A with TF-A Tests, and four-world execution with
+Hafnium and TF-A Tests. The instructions assume you have already obtained
+TF-A. You can use the following command to clone TF-A.
+
+.. code:: shell
+
+ git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
+
+To run the tests, you need an FVP model. You can download a model that supports
+RME from the `Arm Architecture Models website`_. Please select the
+*Base RevC AEM FVP* model. After extracting the downloaded file, you should be able to
+find the *FVP_Base_RevC-2xAEMvA* binary. The instructions below have been tested
+with model version 11.15 revision 18.
+
+.. note::
+
+ ENABLE_RME build option is currently experimental.
+
+Building TF-A with TF-A Tests
+********************************************
+Use the following instructions to build TF-A with `TF-A Tests`_ as the
+non-secure payload (BL33).
+
+**1. Obtain and build TF-A Tests**
+
+.. code:: shell
+
+ git clone https://git.trustedfirmware.org/TF-A/tf-a-tests.git
+ cd tf-a-tests
+ make CROSS_COMPILE=aarch64-none-elf- PLAT=fvp DEBUG=1
+
+This produces a TF-A Tests binary (*tftf.bin*) in the *build/fvp/debug* directory.
+
+**2. Build TF-A**
+
+.. code:: shell
+
+ cd trusted-firmware-a
+ make CROSS_COMPILE=aarch64-none-elf- \
+ PLAT=fvp \
+ ENABLE_RME=1 \
+ FVP_HW_CONFIG_DTS=fdts/fvp-base-gicv3-psci-1t.dts \
+ DEBUG=1 \
+ BL33=<path/to/tftf.bin> \
+ all fip
+
+This produces *bl1.bin* and *fip.bin* binaries in the *build/fvp/debug* directory.
+The above command also builds a Test Realm Payload (TRP), which is a small test
+payload that implements Realm Monitor Management (RMM) functionalities and runs
+in the realm world (R-EL2). The TRP binary is packaged in *fip.bin*.
+
+Four-world execution with Hafnium and TF-A Tests
+****************************************************
+Four-world execution involves software components at each security state: root,
+secure, realm and non-secure. This section describes how to build TF-A
+with four-world support. We use TF-A as the root firmware, `Hafnium`_ as the
+secure component, TRP as the realm-world firmware and TF-A Tests as the
+non-secure payload.
+
+Before building TF-A, you first need to build the other software components.
+You can find instructions on how to get and build TF-A Tests above.
+
+**1. Obtain and build Hafnium**
+
+.. code:: shell
+
+ git clone --recurse-submodules https://git.trustedfirmware.org/hafnium/hafnium.git
+ cd hafnium
+ make PROJECT=reference
+
+The Hafnium binary should be located at
+*out/reference/secure_aem_v8a_fvp_clang/hafnium.bin*
+
+**2. Build TF-A**
+
+Build TF-A with RME as well as SPM enabled.
+
+.. code:: shell
+
+ make CROSS_COMPILE=aarch64-none-elf- \
+ PLAT=fvp \
+ ENABLE_RME=1 \
+ FVP_HW_CONFIG_DTS=fdts/fvp-base-gicv3-psci-1t.dts \
+ SPD=spmd \
+ SPMD_SPM_AT_SEL2=1 \
+ BRANCH_PROTECTION=1 \
+ CTX_INCLUDE_PAUTH_REGS=1 \
+ DEBUG=1 \
+ SP_LAYOUT_FILE=<path/to/tf-a-tests>/build/fvp/debug/sp_layout.json> \
+ BL32=<path/to/hafnium.bin> \
+ BL33=<path/to/tftf.bin> \
+ all fip
+
+Running the tests
+*********************
+Use the following command to run the tests on FVP. TF-A Tests should boot
+and run the default tests including RME tests.
+
+.. code:: shell
+
+ FVP_Base_RevC-2xAEMvA \
+ -C bp.flashloader0.fname=<path/to/fip.bin> \
+ -C bp.secureflashloader.fname=<path/to/bl1.bin> \
+ -C bp.refcounter.non_arch_start_at_default=1 \
+ -C bp.refcounter.use_real_time=0 \
+ -C bp.ve_sysregs.exit_on_shutdown=1 \
+ -C cache_state_modelled=1 \
+ -C cluster0.NUM_CORES=4 \
+ -C cluster0.PA_SIZE=48 \
+ -C cluster0.ecv_support_level=2 \
+ -C cluster0.gicv3.cpuintf-mmap-access-level=2 \
+ -C cluster0.gicv3.without-DS-support=1 \
+ -C cluster0.gicv4.mask-virtual-interrupt=1 \
+ -C cluster0.has_arm_v8-6=1 \
+ -C cluster0.has_branch_target_exception=1 \
+ -C cluster0.has_rme=1 \
+ -C cluster0.has_rndr=1 \
+ -C cluster0.has_amu=1 \
+ -C cluster0.has_v8_7_pmu_extension=2 \
+ -C cluster0.max_32bit_el=-1 \
+ -C cluster0.restriction_on_speculative_execution=2 \
+ -C cluster0.restriction_on_speculative_execution_aarch32=2 \
+ -C cluster1.NUM_CORES=4 \
+ -C cluster1.PA_SIZE=48 \
+ -C cluster1.ecv_support_level=2 \
+ -C cluster1.gicv3.cpuintf-mmap-access-level=2 \
+ -C cluster1.gicv3.without-DS-support=1 \
+ -C cluster1.gicv4.mask-virtual-interrupt=1 \
+ -C cluster1.has_arm_v8-6=1 \
+ -C cluster1.has_branch_target_exception=1 \
+ -C cluster1.has_rme=1 \
+ -C cluster1.has_rndr=1 \
+ -C cluster1.has_amu=1 \
+ -C cluster1.has_v8_7_pmu_extension=2 \
+ -C cluster1.max_32bit_el=-1 \
+ -C cluster1.restriction_on_speculative_execution=2 \
+ -C cluster1.restriction_on_speculative_execution_aarch32=2 \
+ -C pci.pci_smmuv3.mmu.SMMU_AIDR=2 \
+ -C pci.pci_smmuv3.mmu.SMMU_IDR0=0x0046123B \
+ -C pci.pci_smmuv3.mmu.SMMU_IDR1=0x00600002 \
+ -C pci.pci_smmuv3.mmu.SMMU_IDR3=0x1714 \
+ -C pci.pci_smmuv3.mmu.SMMU_IDR5=0xFFFF0475 \
+ -C pci.pci_smmuv3.mmu.SMMU_S_IDR1=0xA0000002 \
+ -C pci.pci_smmuv3.mmu.SMMU_S_IDR2=0 \
+ -C pci.pci_smmuv3.mmu.SMMU_S_IDR3=0 \
+ -C bp.pl011_uart0.out_file=uart0.log \
+ -C bp.pl011_uart1.out_file=uart1.log \
+ -C bp.pl011_uart2.out_file=uart2.log \
+ -C pctl.startup=0.0.0.0 \
+ -Q 1000 \
+ "$@"
+
+The bottom of the output from *uart0* should look something like the following.
+
+.. code-block:: shell
+
+ ...
+
+ > Test suite 'FF-A Interrupt'
+                                                                Passed
+ > Test suite 'SMMUv3 tests'
+                                                                Passed
+ > Test suite 'PMU Leakage'
+                                                                Passed
+ > Test suite 'DebugFS'
+                                                                Passed
+ > Test suite 'Realm payload tests'
+                                                                Passed
+ ...
+
+
+.. _Arm Confidential Compute Architecture (Arm CCA): https://www.arm.com/why-arm/architecture/security-features/arm-confidential-compute-architecture
+.. _Arm Architecture Models website: https://developer.arm.com/tools-and-software/simulation-models/fixed-virtual-platforms/arm-ecosystem-models
+.. _TF-A Tests: https://trustedfirmware-a-tests.readthedocs.io/en/latest
+.. _Hafnium: https://www.trustedfirmware.org/projects/hafnium
diff --git a/docs/components/secure-partition-manager.rst b/docs/components/secure-partition-manager.rst
index a5e7e8e..fa51fe0 100644
--- a/docs/components/secure-partition-manager.rst
+++ b/docs/components/secure-partition-manager.rst
@@ -6,59 +6,59 @@
 Acronyms
 ========
 
-+--------+-----------------------------------+
-| CoT    | Chain of Trust                    |
-+--------+-----------------------------------+
-| DMA    | Direct Memory Access              |
-+--------+-----------------------------------+
-| DTB    | Device Tree Blob                  |
-+--------+-----------------------------------+
-| DTS    | Device Tree Source                |
-+--------+-----------------------------------+
-| EC     | Execution Context                 |
-+--------+-----------------------------------+
-| FIP    | Firmware Image Package            |
-+--------+-----------------------------------+
-| FF-A   | Firmware Framework for Armv8-A    |
-+--------+-----------------------------------+
-| IPA    | Intermediate Physical Address     |
-+--------+-----------------------------------+
-| NWd    | Normal World                      |
-+--------+-----------------------------------+
-| ODM    | Original Design Manufacturer      |
-+--------+-----------------------------------+
-| OEM    | Original Equipment Manufacturer   |
-+--------+-----------------------------------+
-| PA     | Physical Address                  |
-+--------+-----------------------------------+
-| PE     | Processing Element                |
-+--------+-----------------------------------+
-| PM     | Power Management                  |
-+--------+-----------------------------------+
-| PVM    | Primary VM                        |
-+--------+-----------------------------------+
-| SMMU   | System Memory Management Unit     |
-+--------+-----------------------------------+
-| SP     | Secure Partition                  |
-+--------+-----------------------------------+
-| SPD    | Secure Payload Dispatcher         |
-+--------+-----------------------------------+
-| SPM    | Secure Partition Manager          |
-+--------+-----------------------------------+
-| SPMC   | SPM Core                          |
-+--------+-----------------------------------+
-| SPMD   | SPM Dispatcher                    |
-+--------+-----------------------------------+
-| SiP    | Silicon Provider                  |
-+--------+-----------------------------------+
-| SWd    | Secure World                      |
-+--------+-----------------------------------+
-| TLV    | Tag-Length-Value                  |
-+--------+-----------------------------------+
-| TOS    | Trusted Operating System          |
-+--------+-----------------------------------+
-| VM     | Virtual Machine                   |
-+--------+-----------------------------------+
++--------+--------------------------------------+
+| CoT    | Chain of Trust                       |
++--------+--------------------------------------+
+| DMA    | Direct Memory Access                 |
++--------+--------------------------------------+
+| DTB    | Device Tree Blob                     |
++--------+--------------------------------------+
+| DTS    | Device Tree Source                   |
++--------+--------------------------------------+
+| EC     | Execution Context                    |
++--------+--------------------------------------+
+| FIP    | Firmware Image Package               |
++--------+--------------------------------------+
+| FF-A   | Firmware Framework for Arm A-profile |
++--------+--------------------------------------+
+| IPA    | Intermediate Physical Address        |
++--------+--------------------------------------+
+| NWd    | Normal World                         |
++--------+--------------------------------------+
+| ODM    | Original Design Manufacturer         |
++--------+--------------------------------------+
+| OEM    | Original Equipment Manufacturer      |
++--------+--------------------------------------+
+| PA     | Physical Address                     |
++--------+--------------------------------------+
+| PE     | Processing Element                   |
++--------+--------------------------------------+
+| PM     | Power Management                     |
++--------+--------------------------------------+
+| PVM    | Primary VM                           |
++--------+--------------------------------------+
+| SMMU   | System Memory Management Unit        |
++--------+--------------------------------------+
+| SP     | Secure Partition                     |
++--------+--------------------------------------+
+| SPD    | Secure Payload Dispatcher            |
++--------+--------------------------------------+
+| SPM    | Secure Partition Manager             |
++--------+--------------------------------------+
+| SPMC   | SPM Core                             |
++--------+--------------------------------------+
+| SPMD   | SPM Dispatcher                       |
++--------+--------------------------------------+
+| SiP    | Silicon Provider                     |
++--------+--------------------------------------+
+| SWd    | Secure World                         |
++--------+--------------------------------------+
+| TLV    | Tag-Length-Value                     |
++--------+--------------------------------------+
+| TOS    | Trusted Operating System             |
++--------+--------------------------------------+
+| VM     | Virtual Machine                      |
++--------+--------------------------------------+
 
 Foreword
 ========
@@ -414,13 +414,17 @@
 
 The SPMC is loaded by BL2 as the BL32 image.
 
-The SPMC manifest is loaded by BL2 as the ``TOS_FW_CONFIG`` image.
+The SPMC manifest is loaded by BL2 as the ``TOS_FW_CONFIG`` image `[9]`_.
 
 BL2 passes the SPMC manifest address to BL31 through a register.
 
 At boot time, the SPMD in BL31 runs from the primary core, initializes the core
-contexts and launches the SPMC (BL32) passing the SPMC manifest address through
-a register.
+contexts and launches the SPMC (BL32) passing the following information through
+registers:
+
+- X0 holds the ``TOS_FW_CONFIG`` physical address (or SPMC manifest blob).
+- X1 holds the ``HW_CONFIG`` physical address.
+- X4 holds the currently running core linear id.
 
 Loading of SPs
 ~~~~~~~~~~~~~~
@@ -920,7 +924,7 @@
 
 .. _[1]:
 
-[1] `Arm Firmware Framework for Armv8-A <https://developer.arm.com/docs/den0077/latest>`__
+[1] `Arm Firmware Framework for Arm A-profile <https://developer.arm.com/docs/den0077/latest>`__
 
 .. _[2]:
 
@@ -951,6 +955,10 @@
 
 [8] https://lists.trustedfirmware.org/pipermail/tf-a/2020-February/000296.html
 
+.. _[9]:
+
+[9] https://trustedfirmware-a.readthedocs.io/en/latest/design/firmware-design.html#dynamic-configuration-during-cold-boot
+
 --------------
 
 *Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/components/xlat-tables-lib-v2-design.rst b/docs/components/xlat-tables-lib-v2-design.rst
index af5151f..cac32f5 100644
--- a/docs/components/xlat-tables-lib-v2-design.rst
+++ b/docs/components/xlat-tables-lib-v2-design.rst
@@ -10,7 +10,7 @@
 More specifically, some use cases that this library aims to support are:
 
 #. Statically allocate translation tables and populate them (at run-time) based
-   on a description of the memory layout. The memory layout is typically
+   upon a description of the memory layout. The memory layout is typically
    provided by the platform port as a list of memory regions;
 
 #. Support for generating translation tables pertaining to a different
@@ -26,22 +26,28 @@
 #. Support for changing memory attributes of memory regions at run-time.
 
 
-About version 1 and version 2
------------------------------
+About version 1, version 2 and MPU libraries
+--------------------------------------------
 
 This document focuses on version 2 of the library, whose sources are available
 in the ``lib/xlat_tables_v2`` directory. Version 1 of the library can still be
 found in ``lib/xlat_tables`` directory but it is less flexible and doesn't
-support dynamic mapping. Although potential bug fixes will be applied to both
-versions, future features enhancements will focus on version 2 and might not be
-back-ported to version 1. Therefore, it is recommended to use version 2,
-especially for new platform ports.
+support dynamic mapping. ``lib/xlat_mpu``, which configures Arm's MPU
+equivalently, is also addressed here. The ``lib/xlat_mpu`` is experimental,
+meaning that its API may change. It currently strives for consistency and
+code-reuse with xlat_tables_v2.  Future versions may be more MPU-specific (e.g.,
+removing all mentions of virtual addresses). Although potential bug fixes will
+be applied to all versions of the xlat_* libs, future feature enhancements will
+focus on version 2 and might not be back-ported to version 1 and MPU versions.
+Therefore, it is recommended to use version 2, especially for new platform
+ports (unless the platform uses an MPU).
 
-However, please note that version 2 is still in active development and is not
-considered stable yet. Hence, compatibility breaks might be introduced.
+However, please note that version 2 and the MPU version are still in active
+development and is not considered stable yet. Hence, compatibility breaks might
+be introduced.
 
 From this point onwards, this document will implicitly refer to version 2 of the
-library.
+library, unless stated otherwise.
 
 
 Design concepts and interfaces
@@ -102,6 +108,16 @@
 library will choose the mapping granularity for this region as it sees fit (more
 details can be found in `The memory mapping algorithm`_ section below).
 
+The MPU library also uses ``struct mmap_region`` to specify translations, but
+the MPU's translations are limited to specification of valid addresses and
+access permissions.  If the requested virtual and physical addresses mismatch
+the system will panic. Being register-based for deterministic memory-reference
+timing, the MPU hardware does not involve memory-resident translation tables.
+
+Currently, the MPU library is also limited to MPU translation at EL2 with no
+MMU translation at other ELs.  These limitations, however, are expected to be
+overcome in future library versions.
+
 Translation Context
 ~~~~~~~~~~~~~~~~~~~
 
@@ -215,7 +231,8 @@
 The ``MAP_REGION()`` and ``MAP_REGION_FLAT()`` macros do not allow specifying a
 mapping granularity, which leaves the library implementation free to choose
 it. However, in cases where a specific granularity is required, the
-``MAP_REGION2()`` macro might be used instead.
+``MAP_REGION2()`` macro might be used instead. Using ``MAP_REGION_FLAT()`` only
+to define regions for the MPU library is strongly recommended.
 
 As explained earlier in this document, when the dynamic mapping feature is
 disabled, there is no notion of dynamic regions. Conceptually, there are only
@@ -374,6 +391,9 @@
 refer to the comments in the source code of the core module for more details
 about the sorting algorithm in use.
 
+This mapping algorithm does not apply to the MPU library, since the MPU hardware
+directly maps regions by "base" and "limit" (bottom and top) addresses.
+
 TLB maintenance operations
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -390,6 +410,11 @@
 is deferred to the ``enable_mmu*()`` family of functions, just before the MMU is
 turned on.
 
+Regarding enabling and disabling memory management, for the MPU library, to
+reduce confusion, calls to enable or disable the MPU use ``mpu`` in their names
+in place of ``mmu``. For example, the ``enable_mmu_el2()`` call is changed to
+``enable_mpu_el2()``.
+
 TLB invalidation is not required when adding dynamic regions either. Dynamic
 regions are not allowed to overlap existing memory region. Therefore, if the
 dynamic mapping request is deemed legitimate, it automatically concerns memory
@@ -412,6 +437,6 @@
 
 --------------
 
-*Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.*
 
 .. |Alignment Example| image:: ../resources/diagrams/xlat_align.png
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index ab638fb..eebeaa2 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -281,6 +281,23 @@
 -  ``ERRATA_A78_1821534``: This applies errata 1821534 workaround to Cortex-A78
    CPU. This needs to be enabled for revisions r0p0 and r1p0.
 
+-  ``ERRATA_A78_1952683``: This applies errata 1952683 workaround to Cortex-A78
+   CPU. This needs to be enabled for revision r0p0, it is fixed in r1p0.
+
+-  ``ERRATA_A78_2132060``: This applies errata 2132060 workaround to Cortex-A78
+   CPU. This needs to be enabled for revisions r0p0, r1p0, r1p1, and r1p2. It
+   is still open.
+
+For Cortex-A78 AE, the following errata build flags are defined :
+
+- ``ERRATA_A78_AE_1941500`` : This applies errata 1941500 workaround to Cortex-A78
+   AE CPU. This needs to be enabled for revisions r0p0 and r0p1. This erratum is
+   still open.
+
+- ``ERRATA_A78_AE_1951502`` : This applies errata 1951502 workaround to Cortex-A78
+  AE CPU. This needs to be enabled for revisions r0p0 and r0p1. This erratum is
+  still open.
+
 For Neoverse N1, the following errata build flags are defined :
 
 -  ``ERRATA_N1_1073348``: This applies errata 1073348 workaround to Neoverse-N1
@@ -323,6 +340,88 @@
    CPU. This needs to be enabled for revisions r3p0, r3p1, r4p0, and r4p1, for
    revisions r0p0, r1p0, and r2p0 there is no workaround.
 
+For Neoverse N2, the following errata build flags are defined :
+
+-  ``ERRATA_N2_2002655``: This applies errata 2002655 workaround to Neoverse-N2
+   CPU. This needs to be enabled for revision r0p0 of the CPU, it is still open.
+
+For Neoverse V1, the following errata build flags are defined :
+
+-  ``ERRATA_V1_1774420``: This applies errata 1774420 workaround to Neoverse-V1
+   CPU. This needs to be enabled only for revisions r0p0 and r1p0, it is fixed
+   in r1p1.
+
+-  ``ERRATA_V1_1791573``: This applies errata 1791573 workaround to Neoverse-V1
+   CPU. This needs to be enabled only for revisions r0p0 and r1p0, it is fixed
+   in r1p1.
+
+-  ``ERRATA_V1_1852267``: This applies errata 1852267 workaround to Neoverse-V1
+   CPU. This needs to be enabled only for revisions r0p0 and r1p0, it is fixed
+   in r1p1.
+
+-  ``ERRATA_V1_1925756``: This applies errata 1925756 workaround to Neoverse-V1
+   CPU. This needs to be enabled for r0p0, r1p0, and r1p1, it is still open.
+
+-  ``ERRATA_V1_1940577``: This applies errata 1940577 workaround to Neoverse-V1
+   CPU. This needs to be enabled only for revision r1p0 and r1p1 of the
+   CPU.
+
+-  ``ERRATA_V1_1966096``: This applies errata 1966096 workaround to Neoverse-V1
+   CPU. This needs to be enabled for revisions r1p0 and r1p1 of the CPU, the
+   issue is present in r0p0 as well but there is no workaround for that
+   revision.  It is still open.
+
+-  ``ERRATA_V1_2139242``: This applies errata 2139242 workaround to Neoverse-V1
+   CPU. This needs to be enabled for revisions r0p0, r1p0, and r1p1 of the
+   CPU.  It is still open.
+
+-  ``ERRATA_V1_2108267``: This applies errata 2108267 workaround to Neoverse-V1
+   CPU. This needs to be enabled for revisions r0p0, r1p0, and r1p1 of the CPU.
+   It is still open.
+
+For Cortex-A710, the following errata build flags are defined :
+
+-  ``ERRATA_A710_1987031``: This applies errata 1987031 workaround to
+   Cortex-A710 CPU. This needs to be enabled only for revisions r0p0, r1p0 and
+   r2p0 of the CPU. It is still open.
+
+-  ``ERRATA_A710_2081180``: This applies errata 2081180 workaround to
+   Cortex-A710 CPU. This needs to be enabled only for revisions r0p0, r1p0 and
+   r2p0 of the CPU. It is still open.
+
+-  ``ERRATA_A710_2055002``: This applies errata 2055002 workaround to
+   Cortex-A710 CPU. This needs to be enabled for revisions r1p0, r2p0 of the CPU
+   and is still open.
+
+-  ``ERRATA_A710_2017096``: This applies errata 2017096 workaround to
+   Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0
+   of the CPU and is still open.
+
+-  ``ERRATA_A710_2083908``: This applies errata 2083908 workaround to
+   Cortex-A710 CPU. This needs to be enabled for revision r2p0 of the CPU and
+   is still open.
+
+-  ``ERRATA_A710_2058056``: This applies errata 2058056 workaround to
+   Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0
+   of the CPU and is still open.
+
+For Neoverse N2, the following errata build flags are defined :
+
+-  ``ERRATA_N2_2067956``: This applies errata 2067956 workaround to Neoverse-N2
+   CPU. This needs to be enabled for revision r0p0 of the CPU and is still open.
+
+-  ``ERRATA_N2_2025414``: This applies errata 2025414 workaround to Neoverse-N2
+   CPU. This needs to be enabled for revision r0p0 of the CPU and is still open.
+
+-  ``ERRATA_N2_2189731``: This applies errata 2189731 workaround to Neoverse-N2
+   CPU. This needs to be enabled for revision r0p0 of the CPU and is still open.
+
+-  ``ERRATA_N2_2138956``: This applies errata 2138956 workaround to Neoverse-N2
+   CPU. This needs to be enabled for revision r0p0 of the CPU and is still open.
+
+-  ``ERRATA_N2_2138953``: This applies errata 2138953 workaround to Neoverse-N2
+   CPU. This needs to be enabled for revision r0p0 of the CPU and is still open.
+
 DSU Errata Workarounds
 ----------------------
 
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 86618e4..1259881 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -55,6 +55,9 @@
 -  ``BL2_AT_EL3``: This is an optional build option that enables the use of
    BL2 at EL3 execution level.
 
+-  ``BL2_ENABLE_SP_LOAD``: Boolean option to enable loading SP packages from the
+   FIP. Automatically enabled if ``SP_LAYOUT_FILE`` is provided.
+
 -  ``BL2_IN_XIP_MEM``: In some use-cases BL2 will be stored in eXecute In Place
    (XIP) memory, like BL1. In these use-cases, it is necessary to initialize
    the RW sections in RAM, while leaving the RO sections in place. This option
@@ -235,6 +238,10 @@
    builds, but this behaviour can be overridden in each platform's Makefile or
    in the build command line.
 
+-  ``ENABLE_FEAT_HCX``: This option sets the bit SCR_EL3.HXEn in EL3 to allow
+   access to HCRX_EL2 (extended hypervisor control register) from EL2 as well as
+   adding HCRX_EL2 to the EL2 context save/restore operations.
+
 -  ``ENABLE_LTO``: Boolean option to enable Link Time Optimization (LTO)
    support in GCC for TF-A. This option is currently only supported for
    AArch64. Default is 0.
@@ -264,6 +271,10 @@
    be enabled. If ``ENABLE_PMF`` is set, the residency statistics are tracked in
    software.
 
+- ``ENABLE_RME``: Boolean option to enable support for the ARMv9 Realm
+   Management Extension. Default value is 0. This is currently an experimental
+   feature.
+
 -  ``ENABLE_RUNTIME_INSTRUMENTATION``: Boolean option to enable runtime
    instrumentation which injects timestamp collection points into TF-A to
    allow runtime performance to be measured. Currently, only PSCI is
@@ -775,6 +786,21 @@
   functions that wait for an arbitrary time length (udelay and mdelay). The
   default value is 0.
 
+- ``ENABLE_TRBE_FOR_NS``: This flag is used to enable access of trace buffer
+  control registers from NS ELs, NS-EL2 or NS-EL1(when NS-EL2 is implemented
+  but unused) when FEAT_TRBE is implemented. TRBE is an optional architectural
+  feature for AArch64. The default is 0 and it is automatically disabled when
+  the target architecture is AArch32.
+
+- ``ENABLE_SYS_REG_TRACE_FOR_NS``: Boolean option to enable trace system
+  registers access from NS ELs, NS-EL2 or NS-EL1 (when NS-EL2 is implemented
+  but unused). This feature is available if trace unit such as ETMv4.x, and
+  ETE(extending ETM feature) is implemented. This flag is disabled by default.
+
+- ``ENABLE_TRF_FOR_NS``: Boolean option to enable trace filter control registers
+  access from NS ELs, NS-EL2 or NS-EL1 (when NS-EL2 is implemented but unused),
+  if FEAT_TRF is implemented. This flag is disabled by default.
+
 GICv3 driver options
 --------------------
 
@@ -790,6 +816,11 @@
    GIC-600, so is safe to select even for a GIC500 implementation.
    This option defaults to 0.
 
+- ``GICV3_SUPPORT_GIC600AE_FMU``: Add support for the Fault Management Unit
+   for GIC-600 AE. Enabling this option will introduce support to initialize
+   the FMU. Platforms should call the init function during boot to enable the
+   FMU and its safety mechanisms. This option defaults to 0.
+
 -  ``GICV3_IMPL_GIC600_MULTICHIP``: Selects GIC-600 variant with multichip
    functionality. This option defaults to 0
 
@@ -860,9 +891,31 @@
     # Resume execution
     continue
 
+Firmware update options
+-----------------------
+
+-  ``NR_OF_FW_BANKS``: Define the number of firmware banks. This flag is used
+   in defining the firmware update metadata structure. This flag is by default
+   set to '2'.
+
+-  ``NR_OF_IMAGES_IN_FW_BANK``: Define the number of firmware images in each
+   firmware bank. Each firmware bank must have the same number of images as per
+   the `PSA FW update specification`_.
+   This flag is used in defining the firmware update metadata structure. This
+   flag is by default set to '1'.
+
+-  ``PSA_FWU_SUPPORT``: Enable the firmware update mechanism as per the
+   `PSA FW update specification`_. The default value is 0, and this is an
+   experimental feature.
+   PSA firmware update implementation has some limitations, such as BL2 is
+   not part of the protocol-updatable images, if BL2 needs to be updated, then
+   it should be done through another platform-defined mechanism, and it assumes
+   that the platform's hardware supports CRC32 instructions.
+
 --------------
 
 *Copyright (c) 2019-2021, Arm Limited. All rights reserved.*
 
 .. _DEN0115: https://developer.arm.com/docs/den0115/latest
+.. _PSA FW update specification: https://developer.arm.com/documentation/den0118/a/
 
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index 906daf8..54754fe 100644
--- a/docs/getting_started/porting-guide.rst
+++ b/docs/getting_started/porting-guide.rst
@@ -894,6 +894,54 @@
 Note that this API depends on ``DECRYPTION_SUPPORT`` build flag which is
 marked as experimental.
 
+Function : plat_fwu_set_images_source() [when PSA_FWU_SUPPORT == 1]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : struct fwu_metadata *metadata
+    Return   : void
+
+This function is mandatory when PSA_FWU_SUPPORT is enabled.
+It provides a means to retrieve image specification (offset in
+non-volatile storage and length) of active/updated images using the passed
+FWU metadata, and update I/O policies of active/updated images using retrieved
+image specification information.
+Further I/O layer operations such as I/O open, I/O read, etc. on these
+images rely on this function call.
+
+In Arm platforms, this function is used to set an I/O policy of the FIP image,
+container of all active/updated secure and non-secure images.
+
+Function : plat_fwu_set_metadata_image_source() [when PSA_FWU_SUPPORT == 1]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : unsigned int image_id, uintptr_t *dev_handle,
+               uintptr_t *image_spec
+    Return   : int
+
+This function is mandatory when PSA_FWU_SUPPORT is enabled. It is
+responsible for setting up the platform I/O policy of the requested metadata
+image (either FWU_METADATA_IMAGE_ID or BKUP_FWU_METADATA_IMAGE_ID) that will
+be used to load this image from the platform's non-volatile storage.
+
+FWU metadata can not be always stored as a raw image in non-volatile storage
+to define its image specification (offset in non-volatile storage and length)
+statically in I/O policy.
+For example, the FWU metadata image is stored as a partition inside the GUID
+partition table image. Its specification is defined in the partition table
+that needs to be parsed dynamically.
+This function provides a means to retrieve such dynamic information to set
+the I/O policy of the FWU metadata image.
+Further I/O layer operations such as I/O open, I/O read, etc. on FWU metadata
+image relies on this function call.
+
+It returns '0' on success, otherwise a negative error value on error.
+Alongside, returns device handle and image specification from the I/O policy
+of the requested FWU metadata image.
+
 Common optional modifications
 -----------------------------
 
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 54820e4..f4912f5 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -60,8 +60,8 @@
    FDT
       Flattened Device Tree
 
-   FFA
-      Firmware Framework for A-class processors
+   FF-A
+      Firmware Framework for Arm A-profile
 
    FIP
       Firmware Image Package
diff --git a/docs/index.rst b/docs/index.rst
index 29e5839..edc2535 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -30,6 +30,7 @@
 -  `SMC Calling Convention`_
 -  `System Control and Management Interface (SCMI)`_
 -  `Software Delegated Exception Interface (SDEI)`_
+-  `PSA FW update specification`_
 
 Where possible, the code is designed for reuse or porting to other Armv7-A and
 Armv8-A model and hardware platforms.
@@ -92,3 +93,4 @@
 .. _System Control and Management Interface (SCMI): http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/DEN0056A_System_Control_and_Management_Interface.pdf
 .. _Software Delegated Exception Interface (SDEI): http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf
 .. _SMC Calling Convention: https://developer.arm.com/docs/den0028/latest
+.. _PSA FW update specification: https://developer.arm.com/documentation/den0118/a/
diff --git a/docs/plat/arm/arm-build-options.rst b/docs/plat/arm/arm-build-options.rst
index d4fa98d..339ebbe 100644
--- a/docs/plat/arm/arm-build-options.rst
+++ b/docs/plat/arm/arm-build-options.rst
@@ -100,12 +100,15 @@
 -  ``ARM_SPMC_MANIFEST_DTS`` : path to an alternate manifest file used as the
    SPMC Core manifest. Valid when ``SPD=spmd`` is selected.
 
+-  ``ARM_BL2_SP_LIST_DTS``: Path to DTS file snippet to override the hardcoded
+   SP nodes in tb_fw_config.
+
 -  ``OPTEE_SP_FW_CONFIG``: DTC build flag to include OP-TEE as SP in tb_fw_config
    device tree. This flag is defined only when ``ARM_SPMC_MANIFEST_DTS`` manifest
    file name contains pattern optee_sp.
 
 -  ``TS_SP_FW_CONFIG``: DTC build flag to include Trusted Services (Crypto and
-   secure-storage) as SP in tb_fw_config device tree.
+   internal-trusted-storage) as SP in tb_fw_config device tree.
 
 -  ``ARM_GPT_SUPPORT``: Enable GPT parser to get the entry address and length of
    the various partitions present in the GPT image. This support is available
diff --git a/docs/plat/arm/diphda/index.rst b/docs/plat/arm/diphda/index.rst
new file mode 100644
index 0000000..27afda4
--- /dev/null
+++ b/docs/plat/arm/diphda/index.rst
@@ -0,0 +1,61 @@
+Diphda Platform
+==========================
+
+Some of the features of the Diphda platform referenced in TF-A include:
+
+- Cortex-A35 application processor (64-bit mode)
+- Secure Enclave
+- GIC-400
+- Trusted Board Boot
+
+Boot Sequence
+-------------
+
+The board boot relies on CoT (chain of trust). The trusted-firmware-a
+BL2 is extracted from the FIP and verified by the Secure Enclave
+processor. BL2 verification relies on the signature area at the
+beginning of the BL2 image. This area is needed by the SecureEnclave
+bootloader.
+
+Then, the application processor is released from reset and starts by
+executing BL2.
+
+BL2 performs the actions described in the trusted-firmware-a TBB design
+document.
+
+Build Procedure (TF-A only)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+-  Obtain AArch64 ELF bare-metal target `toolchain <https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads>`_.
+   Set the CROSS_COMPILE environment variable to point to the toolchain folder.
+
+-  Build TF-A:
+
+   .. code:: shell
+
+      make LD=aarch64-none-elf-ld \
+      CC=aarch64-none-elf-gcc \
+      V=1 \
+      BUILD_BASE=<path to the build folder> \
+      PLAT=diphda \
+      SPD=spmd \
+      SPMD_SPM_AT_SEL2=0 \
+      DEBUG=1 \
+      MBEDTLS_DIR=mbedtls \
+      OPENSSL_DIR=<path to openssl usr folder> \
+      RUNTIME_SYSROOT=<path to the sysroot> \
+      ARCH=aarch64 \
+      TARGET_PLATFORM=<fpga or fvp> \
+      ENABLE_PIE=1 \
+      BL2_AT_EL3=1 \
+      CREATE_KEYS=1 \
+      GENERATE_COT=1 \
+      TRUSTED_BOARD_BOOT=1 \
+      COT=tbbr \
+      ARM_ROTPK_LOCATION=devel_rsa \
+      ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \
+      BL32=<path to optee binary> \
+      BL33=<path to u-boot binary> \
+      bl2
+
+*Copyright (c) 2021, Arm Limited. All rights reserved.*
diff --git a/docs/plat/arm/fvp/index.rst b/docs/plat/arm/fvp/index.rst
index 710043e..d41982f 100644
--- a/docs/plat/arm/fvp/index.rst
+++ b/docs/plat/arm/fvp/index.rst
@@ -12,7 +12,7 @@
 (64-bit host machine only).
 
 .. note::
-   The FVP models used are Version 11.14 Build 21, unless otherwise stated.
+   The FVP models used are Version 11.15 Build 14, unless otherwise stated.
 
 -  ``FVP_Base_AEMvA``
 -  ``FVP_Base_AEMv8A-AEMv8A``
@@ -39,7 +39,7 @@
 -  ``FVP_Base_Cortex-A76AEx8``
 -  ``FVP_Base_Cortex-A77x4``
 -  ``FVP_Base_Cortex-A78x4``
--  ``FVP_Base_Matterhornx4``
+-  ``FVP_Base_Cortex-A710x4``
 -  ``FVP_Morello``         (Version 0.10 build 542)
 -  ``FVP_Base_Neoverse-E1x1``
 -  ``FVP_Base_Neoverse-E1x2``
diff --git a/docs/plat/arm/fvp_r/index.rst b/docs/plat/arm/fvp_r/index.rst
new file mode 100644
index 0000000..8af16ba
--- /dev/null
+++ b/docs/plat/arm/fvp_r/index.rst
@@ -0,0 +1,46 @@
+ARM V8-R64 Fixed Virtual Platform (FVP)
+=======================================
+
+Some of the features of Armv8-R AArch64 FVP platform referenced in Trusted
+Boot R-class include:
+
+- Secure World Support Only
+- EL2 as Maximum EL support (No EL3)
+- MPU Support only at EL2
+- MPU or MMU Support at EL0/EL1
+- AArch64 Support Only
+- Trusted Board Boot
+
+Further information on v8-R64 FVP is available at `info <https://developer.arm.com/documentation/ddi0600/latest/>`_
+
+Boot Sequence
+-------------
+
+BL1 –> BL33
+
+The execution begins from BL1 which loads the BL33 image, a boot-wrapped (bootloader + Operating System)
+Operating System, from FIP to DRAM.
+
+Build Procedure
+~~~~~~~~~~~~~~~
+
+-  Obtain arm `toolchain <https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads>`_.
+   Set the CROSS_COMPILE environment variable to point to the toolchain folder.
+
+-  Build TF-A:
+
+   .. code:: shell
+
+      make PLAT=fvp_r BL33=<path_to_os.bin> all fip
+
+   Enable TBBR by adding the following options to the make command:
+
+   .. code:: shell
+
+      MBEDTLS_DIR=<path_to_mbedtls_directory>  \
+      TRUSTED_BOARD_BOOT=1 \
+      GENERATE_COT=1 \
+      ARM_ROTPK_LOCATION=devel_rsa  \
+      ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem
+
+*Copyright (c) 2021, Arm Limited. All rights reserved.*
diff --git a/docs/plat/arm/index.rst b/docs/plat/arm/index.rst
index f72992b..f262dc0 100644
--- a/docs/plat/arm/index.rst
+++ b/docs/plat/arm/index.rst
@@ -7,11 +7,13 @@
 
    juno/index
    fvp/index
+   fvp_r/index
    fvp-ve/index
-   tc0/index
+   tc/index
    arm_fpga/index
    arm-build-options
    morello/index
+   diphda/index
 
 This chapter holds documentation related to Arm's development platforms,
 including both software models (FVPs) and hardware development boards
@@ -19,4 +21,4 @@
 
 --------------
 
-*Copyright (c) 2019, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2021, Arm Limited. All rights reserved.*
diff --git a/docs/plat/arm/tc0/index.rst b/docs/plat/arm/tc/index.rst
similarity index 73%
rename from docs/plat/arm/tc0/index.rst
rename to docs/plat/arm/tc/index.rst
index 34d1f13..20d3e56 100644
--- a/docs/plat/arm/tc0/index.rst
+++ b/docs/plat/arm/tc/index.rst
@@ -1,7 +1,7 @@
-TC0 Total Compute Platform
+TC Total Compute Platform
 ==========================
 
-Some of the features of TC0 platform referenced in TF-A include:
+Some of the features of TC platform referenced in TF-A include:
 
 - A `System Control Processor <https://github.com/ARM-software/SCP-firmware>`_
   to abstract power and system management tasks away from application
@@ -13,6 +13,12 @@
 - SCMI
 - MHUv2
 
+Currently, the main difference between TC0 (TARGET_PLATFORM=0) and TC1
+(TARGET_PLATFORM=1) platforms w.r.t to TF-A is the CPUs supported. TC0 has
+support for Cortex A510, Cortex A710 and Cortex X2, while TC1 has support for
+Cortex A510, Cortex Makalu and Cortex Makalu ELP Arm CPUs.
+
+
 Boot Sequence
 -------------
 
@@ -34,8 +40,8 @@
 
    .. code:: shell
 
-      make PLAT=tc0 BL33=<path_to_uboot.bin> \
-      SCP_BL2=<path_to_scp_ramfw.bin>  all fip
+      make PLAT=tc BL33=<path_to_uboot.bin> \
+      SCP_BL2=<path_to_scp_ramfw.bin> TARGET_PLATFORM={0,1} all fip
 
    Enable TBBR by adding the following options to the make command:
 
@@ -47,4 +53,4 @@
       ARM_ROTPK_LOCATION=devel_rsa  \
       ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem
 
-*Copyright (c) 2020, Arm Limited. All rights reserved.*
+*Copyright (c) 2020-2021, Arm Limited. All rights reserved.*
diff --git a/docs/plat/deprecated.rst b/docs/plat/deprecated.rst
index 203ae00..7cc4258 100644
--- a/docs/plat/deprecated.rst
+++ b/docs/plat/deprecated.rst
@@ -16,3 +16,5 @@
 +================+================+====================+====================+
 |    sgm775      |      Arm       |        2.5         |       2.7          |
 +----------------+----------------+--------------------+--------------------+
+|    mt6795      |      MTK       |        2.5         |       2.7          |
++----------------+----------------+--------------------+--------------------+
diff --git a/docs/plat/index.rst b/docs/plat/index.rst
index 4dc9ecd..5848005 100644
--- a/docs/plat/index.rst
+++ b/docs/plat/index.rst
@@ -27,6 +27,7 @@
    imx8
    imx8m
    ls1043a
+   nxp/index
    poplar
    qemu
    qemu-sbsa
diff --git a/docs/plat/marvell/armada/build.rst b/docs/plat/marvell/armada/build.rst
index c9f5e82..b125144 100644
--- a/docs/plat/marvell/armada/build.rst
+++ b/docs/plat/marvell/armada/build.rst
@@ -62,6 +62,7 @@
             - a80x0_mcbin  - MacchiatoBin
             - a80x0_puzzle - IEI Puzzle-M801
             - t9130        - CN913x
+            - t9130_cex7_eval - CN913x CEx7 Evaluation Board
 
 - DEBUG
 
@@ -98,50 +99,26 @@
         There is no reason to enable this feature if OP-TEE OS built with CFG_WITH_PAGER=n.
         Only set LLC_SRAM=1 if OP-TEE OS is built with CFG_WITH_PAGER=y.
 
-- CM3_SYSTEM_RESET
-
-        For Armada37x0 only, when ``CM3_SYSTEM_RESET=1``, the Cortex-M3 secure coprocessor will
-        be used for system reset.
-        TF-A will send command 0x0009 with a magic value via the rWTM mailbox interface to the
-        Cortex-M3 secure coprocessor.
-        The firmware running in the coprocessor must either implement this functionality or
-        ignore the 0x0009 command (which is true for the firmware from A3700-utils-marvell
-        repository). If this option is enabled but the firmware does not support this command,
-        an error message will be printed prior trying to reboot via the usual way.
-
-        This option is needed on Turris MOX as a workaround to a HW bug which causes reset to
-        sometime hang the board.
-
-- A3720_DB_PM_WAKEUP_SRC
-
-        For Armada 3720 Develpment Board only, when ``A3720_DB_PM_WAKEUP_SRC=1``,
-        TF-A will setup PM wake up src configuration. This option is disabled by default.
-
 - MARVELL_SECURE_BOOT
 
         Build trusted(=1)/non trusted(=0) image, default is non trusted.
-
-- BLE_PATH
-
-        Points to BLE (Binary ROM extension) sources folder.
-        Only required for A7K/8K/CN913x builds.
-        The parameter is optional, its default value is ``plat/marvell/armada/a8k/common/ble``.
+        This parameter is used only for ``mrvl_flash`` and ``mrvl_uart`` targets.
 
 - MV_DDR_PATH
 
-        For A7K/8K/CN913x, use this parameter to point to mv_ddr driver sources to allow BLE build. For A37x0,
-        it is used for ddr_tool build.
+        This parameter is required for ``mrvl_flash`` and ``mrvl_uart`` targets.
+        For A7K/8K/CN913x it is used for BLE build and for Armada37x0 it used
+        for ddr_tool build.
 
-        Usage example: MV_DDR_PATH=path/to/mv_ddr
+        Specify path to the full checkout of Marvell mv-ddr-marvell git
+        repository. Checkout must contain also .git subdirectory because
+        mv-ddr build process calls git commands.
 
-        The parameter is optional for A7K/8K/CN913x, when this parameter is not set, the mv_ddr
-        sources are expected to be located at: drivers/marvell/mv_ddr. However, the parameter
-        is necessary for A37x0.
+        Do not remove any parts of git checkout becuase build process and other
+        applications need them for correct building and version determination.
 
-        For the mv_ddr source location, check the section "Tools and external components installation"
 
-        If MV_DDR_PATH source code is a git snapshot then provide path to the full git
-        repository (including .git subdir) because mv_ddr build process calls git commands.
+CN913x specific build options:
 
 - CP_NUM
 
@@ -151,9 +128,79 @@
         family (PLAT=t9130), which can have external CPs connected to the MCI ports. Valid
         values with CP_NUM are in a range of 1 to 3.
 
+
+A7K/8K/CN913x specific build options:
+
+- BLE_PATH
+
+        Points to BLE (Binary ROM extension) sources folder.
+        The parameter is optional, its default value is ``plat/marvell/armada/a8k/common/ble``
+        which uses TF-A in-tree BLE implementation.
+
+- MSS_SUPPORT
+
+        When ``MSS_SUPPORT=1``, then TF-A includes support for Management SubSystem (MSS).
+        When enabled it is required to specify path to the MSS firmware image via ``SCP_BL2``
+        option.
+
+        This option is by default enabled.
+
+- SCP_BL2
+
+        Specify path to the MSS fimware image binary which will run on Cortex-M3 coprocessor.
+        It is available in Marvell binaries-marvell git repository. Required when ``MSS_SUPPORT=1``.
+
+
+Armada37x0 specific build options:
+
+- HANDLE_EA_EL3_FIRST
+
+        When ``HANDLE_EA_EL3_FIRST=1``, External Aborts and SError Interrupts will be always trapped
+        in TF-A. TF-A in this case enables dirty hack / workaround for a bug found in U-Boot and
+        Linux kernel PCIe controller driver pci-aardvark.c, traps and then masks SError interrupt
+        caused by AXI SLVERR on external access (syndrome 0xbf000002).
+
+        Otherwise when ``HANDLE_EA_EL3_FIRST=0``, these exceptions will be trapped in the current
+        exception level (or in EL1 if the current exception level is EL0). So exceptions caused by
+        U-Boot will be trapped in U-Boot, exceptions caused by Linux kernel (or user applications)
+        will be trapped in Linux kernel.
+
+        Mentioned bug in pci-aardvark.c driver is fixed in U-Boot version v2021.07 and Linux kernel
+        version v5.13 (workarounded since Linux kernel version 5.9) and also backported in Linux
+        kernel stable releases since versions v5.12.13, v5.10.46, v5.4.128, v4.19.198, v4.14.240.
+
+        If target system has already patched version of U-Boot and Linux kernel then it is strongly
+        recommended to not enable this workaround as it disallows propagating of all External Aborts
+        to running Linux kernel and makes correctable errors as fatal aborts.
+
+        This option is now disabled by default. In past this option was enabled by default in
+        TF-A versions v2.2, v2.3, v2.4 and v2.5.
+
+- CM3_SYSTEM_RESET
+
+        When ``CM3_SYSTEM_RESET=1``, the Cortex-M3 secure coprocessor will be used for system reset.
+
+        TF-A will send command 0x0009 with a magic value via the rWTM mailbox interface to the
+        Cortex-M3 secure coprocessor.
+        The firmware running in the coprocessor must either implement this functionality or
+        ignore the 0x0009 command (which is true for the firmware from A3700-utils-marvell
+        repository). If this option is enabled but the firmware does not support this command,
+        an error message will be printed prior trying to reboot via the usual way.
+
+        This option is needed on Turris MOX as a workaround to a HW bug which causes reset to
+        sometime hang the board.
+
+- A3720_DB_PM_WAKEUP_SRC
+
+        For Armada 3720 Development Board only, when ``A3720_DB_PM_WAKEUP_SRC=1``,
+        TF-A will setup PM wake up src configuration. This option is disabled by default.
+
+
+Armada37x0 specific build options for ``mrvl_flash`` and ``mrvl_uart`` targets:
+
 - DDR_TOPOLOGY
 
-        For Armada37x0 only, the DDR topology map index/name, default is 0.
+        The DDR topology map index/name, default is 0.
 
         Supported Options:
             -    0 - DDR3 1CS 512MB (DB-88F3720-DDR3-Modular, EspressoBin V3-V5)
@@ -168,7 +215,7 @@
 
 - CLOCKSPRESET
 
-        For Armada37x0 only, the clock tree configuration preset including CPU and DDR frequency,
+        The clock tree configuration preset including CPU and DDR frequency,
         default is CPU_800_DDR_800.
 
             - CPU_600_DDR_600  - CPU at 600 MHz, DDR at 600 MHz
@@ -185,7 +232,7 @@
 
 - BOOTDEV
 
-        For Armada37x0 only, the flash boot device, default is ``SPINOR``.
+        The flash boot device, default is ``SPINOR``.
 
         Currently, Armada37x0 only supports ``SPINOR``, ``SPINAND``, ``EMMCNORM`` and ``SATA``:
 
@@ -204,7 +251,7 @@
 
 - PARTNUM
 
-        For Armada37x0 only, the boot partition number, default is 0.
+        The boot partition number, default is 0.
 
         To boot from eMMC, the value should be aligned with the parameter in
         U-Boot with name of ``CONFIG_SYS_MMC_ENV_PART``, whose value by default is
@@ -213,7 +260,7 @@
 
 - WTMI_IMG
 
-        For Armada37x0 only, the path of the binary can point to an image which
+        The path of the binary can point to an image which
         does nothing, an image which supports EFUSE or a customized CM3 firmware
         binary. The default image is ``fuse.bin`` that built from sources in WTP
         folder, which is the next option. If the default image is OK, then this
@@ -236,16 +283,19 @@
 
 - WTP
 
-        For Armada37x0 only, use this parameter to point to wtptools source code
-        directory, which can be found as a3700_utils.zip in the release. Usage
-        example: ``WTP=/path/to/a3700_utils``
+        Specify path to the full checkout of Marvell A3700-utils-marvell git
+        repository. Checkout must contain also .git subdirectory because WTP
+        build process calls git commands.
 
-        If WTP source code is a git snapshot then provide path to the full git
-        repository (including .git subdir) because WTP build process calls git commands.
+        WTP build process uses also Marvell mv-ddr-marvell git repository
+        specified in MV_DDR_PATH option.
+
+        Do not remove any parts of git checkout becuase build process and other
+        applications need them for correct building and version determination.
 
 - CRYPTOPP_PATH
 
-        For Armada37x0 only, use this parameter to point to Crypto++ source code
+        Use this parameter to point to Crypto++ source code
         directory. If this option is specified then Crypto++ source code in
         CRYPTOPP_PATH directory will be automatically compiled. Crypto++ library
         is required for building WTP image tool. Either CRYPTOPP_PATH or
@@ -253,12 +303,12 @@
 
 - CRYPTOPP_LIBDIR
 
-        For Armada37x0 only, use this parameter to point to the directory with
+        Use this parameter to point to the directory with
         compiled Crypto++ library. By default it points to the CRYPTOPP_PATH.
 
 - CRYPTOPP_INCDIR
 
-        For Armada37x0 only, use this parameter to point to the directory with
+        Use this parameter to point to the directory with
         header files of Crypto++ library. By default it points to the CRYPTOPP_PATH.
 
 
@@ -354,8 +404,8 @@
 Tools and external components installation
 ------------------------------------------
 
-Armada37x0 Builds require installation of 3 components
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Armada37x0 Builds require installation of additional components
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 (1) ARM cross compiler capable of building images for the service CPU (CM3).
     This component is usually included in the Linux host packages.
@@ -388,10 +438,19 @@
 
     https://github.com/weidai11/cryptopp.git
 
-Armada70x0 and Armada80x0 Builds require installation of an additional component
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+(5) Optional CZ.NIC's Armada 3720 Secure Firmware:
+
+    https://gitlab.nic.cz/turris/mox-boot-builder.git
+
+Armada70x0, Armada80x0 and CN913x Builds require installation of additional components
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 (1) DDR initialization library sources (mv_ddr) available at the following repository
     (use the "master" branch):
 
     https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git
+
+(2) MSS Management SubSystem Firmware available at the following repository
+    (use the "binaries-marvell-armada-SDK10.0.1.0" branch):
+
+    https://github.com/MarvellEmbeddedProcessors/binaries-marvell.git
diff --git a/docs/plat/nvidia-tegra.rst b/docs/plat/nvidia-tegra.rst
index 02ff38b..391c7c8 100644
--- a/docs/plat/nvidia-tegra.rst
+++ b/docs/plat/nvidia-tegra.rst
@@ -19,7 +19,7 @@
 multi-processing (HMP) solution designed to optimize performance and
 efficiency.
 
-T186 has Dual NVIDIA Denver 2 ARM® CPU cores, plus Quad ARM Cortex®-A57 cores,
+T186 has Dual NVIDIA Denver2 ARM® CPU cores, plus Quad ARM Cortex®-A57 cores,
 in a coherent multiprocessor configuration. The Denver 2 and Cortex-A57 cores
 support ARMv8, executing both 64-bit Aarch64 code, and 32-bit Aarch32 code
 including legacy ARMv7 applications. The Denver 2 processors each have 128 KB
@@ -29,20 +29,6 @@
 high speed coherency fabric connects these two processor complexes and allows
 heterogeneous multi-processing with all six cores if required.
 
--  .. rubric:: T210
-      :name: t210
-
-T210 has Quad Arm® Cortex®-A57 cores in a switched configuration with a
-companion set of quad Arm Cortex-A53 cores. The Cortex-A57 and A53 cores
-support Armv8-A, executing both 64-bit Aarch64 code, and 32-bit Aarch32 code
-including legacy Armv7-A applications. The Cortex-A57 processors each have
-48 KB Instruction and 32 KB Data Level 1 caches; and have a 2 MB shared
-Level 2 unified cache. The Cortex-A53 processors each have 32 KB Instruction
-and 32 KB Data Level 1 caches; and have a 512 KB shared Level 2 unified cache.
-
--  .. rubric:: T132
-      :name: t132
-
 Denver is NVIDIA's own custom-designed, 64-bit, dual-core CPU which is
 fully Armv8-A architecture compatible. Each of the two Denver cores
 implements a 7-way superscalar microarchitecture (up to 7 concurrent
@@ -68,6 +54,17 @@
 to extensive power-gating and dynamic voltage and clock scaling based on
 workloads.
 
+-  .. rubric:: T210
+      :name: t210
+
+T210 has Quad Arm® Cortex®-A57 cores in a switched configuration with a
+companion set of quad Arm Cortex-A53 cores. The Cortex-A57 and A53 cores
+support Armv8-A, executing both 64-bit Aarch64 code, and 32-bit Aarch32 code
+including legacy Armv7-A applications. The Cortex-A57 processors each have
+48 KB Instruction and 32 KB Data Level 1 caches; and have a 2 MB shared
+Level 2 unified cache. The Cortex-A53 processors each have 32 KB Instruction
+and 32 KB Data Level 1 caches; and have a 512 KB shared Level 2 unified cache.
+
 Directory structure
 -------------------
 
@@ -89,7 +86,6 @@
 
 These are the supported Trusted OS' by Tegra platforms.
 
-- Tegra132: TLK
 - Tegra210: TLK and Trusty
 - Tegra186: Trusty
 - Tegra194: Trusty
@@ -110,7 +106,7 @@
 .. code:: shell
 
     CROSS_COMPILE=<path-to-aarch64-gcc>/bin/aarch64-none-elf- make PLAT=tegra \
-    TARGET_SOC=<target-soc e.g. t194|t186|t210|t132> SPD=<dispatcher e.g. trusty|tlkd>
+    TARGET_SOC=<target-soc e.g. t194|t186|t210> SPD=<dispatcher e.g. trusty|tlkd>
     bl31
 
 Platforms wanting to use different TZDRAM\_BASE, can add ``TZDRAM_BASE=<value>``
diff --git a/docs/plat/nxp/index.rst b/docs/plat/nxp/index.rst
new file mode 100644
index 0000000..8546887
--- /dev/null
+++ b/docs/plat/nxp/index.rst
@@ -0,0 +1,17 @@
+NXP Reference Development Platforms
+===================================
+
+.. toctree::
+   :maxdepth: 1
+   :caption: Contents
+
+   nxp-layerscape
+   nxp-ls-fuse-prov
+   nxp-ls-tbbr
+
+This chapter holds documentation related to NXP reference development platforms.
+It includes details on image flashing, fuse provisioning and trusted board boot-up.
+
+--------------
+
+*Copyright (c) 2021, NXP Limited. All rights reserved.*
diff --git a/docs/plat/nxp/nxp-layerscape.rst b/docs/plat/nxp/nxp-layerscape.rst
new file mode 100644
index 0000000..9a470e6
--- /dev/null
+++ b/docs/plat/nxp/nxp-layerscape.rst
@@ -0,0 +1,301 @@
+NXP SoCs - Overview
+=====================
+.. section-numbering::
+    :suffix: .
+
+The QorIQ family of ARM based SoCs that are supported on TF-A are:
+
+1. LX2160A
+
+- SoC Overview:
+
+The LX2160A multicore processor, the highest-performance member of the
+Layerscape family, combines FinFET process technology's low power and
+sixteen Arm® Cortex®-A72 cores with datapath acceleration optimized for
+L2/3 packet processing, together with security offload, robust traffic
+management and quality of service.
+
+Details about LX2160A can be found at `lx2160a`_.
+
+- LX2160ARDB Board:
+
+The LX2160A reference design board provides a comprehensive platform
+that enables design and evaluation of the LX2160A or LX2162A processors. It
+comes preloaded with a board support package (BSP) based on a standard Linux
+kernel.
+
+Board details can be fetched from the link: `lx2160ardb`_.
+
+2. LS1028A
+
+- SoC Overview:
+
+The Layerscape LS1028A applications processor for industrial and
+automotive includes a time-sensitive networking (TSN) -enabled Ethernet
+switch and Ethernet controllers to support converged IT and OT networks.
+Two powerful 64-bit Arm®v8 cores support real-time processing for
+industrial control and virtual machines for edge computing in the IoT.
+The integrated GPU and LCD controller enable Human-Machine Interface
+(HMI) systems with next-generation interfaces.
+
+Details about LS1028A can be found at `ls1028a`_.
+
+- LS1028ARDB Boards:
+
+The LS1028A reference design board (RDB) is a computing, evaluation,
+and development platform that supports industrial IoT applications, human
+machine interface solutions, and industrial networking.
+
+Details about LS1028A RDB board can be found at `ls1028ardb`_.
+
+Table of supported boot-modes by each platform & platform that needs FIP-DDR:
+-----------------------------------------------------------------------------
+
++---------------------+---------------------------------------------------------------------+-----------------+
+|                     |                            BOOT_MODE                                |                 |
+|       PLAT          +-------+--------+-------+-------+-------+-------------+--------------+ fip_ddr_needed  |
+|                     |  sd   |  qspi  |  nor  | nand  | emmc  | flexspi_nor | flexspi_nand |                 |
++=====================+=======+========+=======+=======+=======+=============+==============+=================+
+|     lx2160ardb      |  yes  |        |       |       |  yes  |   yes       |              |       yes       |
++---------------------+-------+--------+-------+-------+-------+-------------+--------------+-----------------+
+|     ls1028ardb      |  yes  |        |       |       |  yes  |   yes       |              |       no        |
++---------------------+-------+--------+-------+-------+-------+-------------+--------------+-----------------+
+
+
+Boot Sequence
+-------------
+::
+
++                           Secure World        |     Normal World
++ EL0                                           |
++                                               |
++ EL1                           BL32(Tee OS)    |     kernel
++                                ^ |            |       ^
++                                | |            |       |
++ EL2                            | |            |     BL33(u-boot)
++                                | |            |      ^
++                                | v            |     /
++ EL3        BootROM --> BL2 --> BL31 ---------------/
++
+
+Boot Sequence with FIP-DDR
+--------------------------
+::
+
++                           Secure World        |     Normal World
++ EL0                                           |
++                                               |
++ EL1               fip-ddr     BL32(Tee OS)    |     kernel
++                     ^ |         ^ |           |       ^
++                     | |         | |           |       |
++ EL2                 | |         | |           |     BL33(u-boot)
++                     | |         | |           |      ^
++                     | v         | v           |     /
++ EL3     BootROM --> BL2 -----> BL31 ---------------/
++
+
+DDR Memory Layout
+--------------------------
+
+NXP Platforms divide DRAM into banks:
+
+- DRAM0 Bank:  Maximum size of this bank is fixed to 2GB, DRAM0 size is defined in platform_def.h if it is less than 2GB.
+
+- DRAM1 ~ DRAMn Bank:  Greater than 2GB belongs to DRAM1 and following banks, and size of DRAMn Bank varies for one platform to others.
+
+The following diagram is default DRAM0 memory layout in which secure memory is at top of DRAM0.
+
+::
+
+  high  +---------------------------------------------+
+        |                                             |
+        |   Secure EL1 Payload Shared Memory (2 MB)   |
+        |                                             |
+        +---------------------------------------------+
+        |                                             |
+        |            Secure Memory (64 MB)            |
+        |                                             |
+        +---------------------------------------------+
+        |                                             |
+        |             Non Secure Memory               |
+        |                                             |
+  low   +---------------------------------------------+
+
+How to build
+=============
+
+Code Locations
+--------------
+
+-  OP-TEE:
+   `link <https://source.codeaurora.org/external/qoriq/qoriq-components/optee_os>`__
+
+-  U-Boot:
+   `link <https://source.codeaurora.org/external/qoriq/qoriq-components/u-boot>`__
+
+-  RCW:
+   `link <https://source.codeaurora.org/external/qoriq/qoriq-components/rcw>`__
+
+-  ddr-phy-binary: Required by platforms that need fip-ddr.
+   `link <https:://github.com/NXP/ddr-phy-binary>`__
+
+-  cst: Required for TBBR.
+   `link <https:://source.codeaurora.org/external/qoriq/qoriq-components/cst>`__
+
+Build Procedure
+---------------
+
+-  Fetch all the above repositories into local host.
+
+-  Prepare AARCH64 toolchain and set the environment variable "CROSS_COMPILE".
+
+   .. code:: shell
+
+       export CROSS_COMPILE=.../bin/aarch64-linux-gnu-
+
+-  Build RCW. Refer README from the respective cloned folder for more details.
+
+-  Build u-boot and OPTee firstly, and get binary images: u-boot.bin and tee.bin.
+   For u-boot you can use the <platform>_tfa_defconfig for build.
+
+-  Copy/clone the repo "ddr-phy-binary" to the tfa directory for platform needing ddr-fip.
+
+-  Below are the steps to build TF-A images for the supported platforms.
+
+Compilation steps without BL32
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+BUILD BL2:
+
+-To compile
+   .. code:: shell
+
+       make PLAT=$PLAT \
+       BOOT_MODE=<platform_supported_boot_mode> \
+       RCW=$RCW_BIN \
+       pbl
+
+BUILD FIP:
+
+   .. code:: shell
+
+       make PLAT=$PLAT \
+       BOOT_MODE=<platform_supported_boot_mode> \
+       RCW=$RCW_BIN \
+       BL33=$UBOOT_SECURE_BIN \
+       pbl \
+       fip
+
+Compilation steps with BL32
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+BUILD BL2:
+
+-To compile
+   .. code:: shell
+
+       make PLAT=$PLAT \
+       BOOT_MODE=<platform_supported_boot_mode> \
+       RCW=$RCW_BIN \
+       BL32=$TEE_BIN SPD=opteed\
+       pbl
+
+BUILD FIP:
+
+   .. code:: shell
+
+       make PLAT=$PLAT \
+       BOOT_MODE=<platform_supported_boot_mode> \
+       RCW=$RCW_BIN \
+       BL32=$TEE_BIN SPD=opteed\
+       BL33=$UBOOT_SECURE_BIN \
+       pbl \
+       fip
+
+
+BUILD fip-ddr (Mandatory for certain platforms, refer table above):
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+-To compile additional fip-ddr for selected platforms(Refer above table if the platform needs fip-ddr).
+   .. code:: shell
+
+	make PLAT=<platform_name> fip-ddr
+
+
+Deploy ATF Images
+=================
+
+Note: The size in the standard uboot commands for copy to nor, qspi, nand or sd
+should be modified based on the binary size of the image to be copied.
+
+-  Deploy ATF images on flexspi-Nor flash Alt Bank from U-Boot prompt.
+   --  Commands to flash images for bl2_xxx.pbl and fip.bin.
+
+   .. code:: shell
+
+        tftp 82000000  $path/bl2_flexspi_nor.pbl;
+        i2c mw 66 50 20;sf probe 0:0; sf erase 0 +$filesize; sf write 0x82000000 0x0 $filesize;
+
+        tftp 82000000  $path/fip.bin;
+        i2c mw 66 50 20;sf probe 0:0; sf erase 0x100000 +$filesize; sf write 0x82000000 0x100000 $filesize;
+
+   --  Next step is valid for platform where FIP-DDR is needed.
+
+   .. code:: shell
+
+        tftp 82000000  $path/ddr_fip.bin;
+        i2c mw 66 50 20;sf probe 0:0; sf erase 0x800000 +$filesize; sf write 0x82000000 0x800000 $filesize;
+
+   --  Then reset to alternate bank to boot up ATF.
+
+   .. code:: shell
+
+        qixisreset altbank;
+
+-  Deploy ATF images on SD/eMMC from U-Boot prompt.
+   -- file_size_in_block_sizeof_512 = (Size_of_bytes_tftp / 512)
+
+   .. code:: shell
+
+        mmc dev <idx>; (idx = 1 for eMMC; idx = 0 for SD)
+
+        tftp 82000000  $path/bl2_<sd>_or_<emmc>.pbl;
+        mmc write 82000000 8 <file_size_in_block_sizeof_512>;
+
+        tftp 82000000  $path/fip.bin;
+        mmc write 82000000 0x800 <file_size_in_block_sizeof_512>;
+
+    --  Next step is valid for platform that needs FIP-DDR.
+
+   .. code:: shell
+
+        tftp 82000000  $path/ddr_fip.bin;
+        mmc write 82000000 0x4000 <file_size_in_block_sizeof_512>;
+
+   --  Then reset to sd/emmc to boot up ATF from sd/emmc as boot-source.
+
+   .. code:: shell
+
+        qixisreset <sd or emmc>;
+
+Trusted Board Boot:
+===================
+
+For TBBR, the binary name changes:
+
++-------------+--------------------------+---------+-------------------+
+|  Boot Type  |           BL2            |   FIP   |      FIP-DDR      |
++=============+==========================+=========+===================+
+| Normal Boot |  bl2_<boot_mode>.pbl     | fip.bin | ddr_fip.bin       |
++-------------+--------------------------+---------+-------------------+
+| TBBR Boot   |  bl2_<boot_mode>_sec.pbl | fip.bin | ddr_fip_sec.bin   |
++-------------+--------------------------+---------+-------------------+
+
+Refer `nxp-ls-tbbr.rst`_ for detailed user steps.
+
+
+.. _lx2160a: https://www.nxp.com/products/processors-and-microcontrollers/arm-processors/layerscape-processors/layerscape-lx2160a-lx2120a-lx2080a-processors:LX2160A
+.. _lx2160ardb: https://www.nxp.com/products/processors-and-microcontrollers/arm-processors/layerscape-communication-process/layerscape-lx2160a-multicore-communications-processor:LX2160A
+.. _ls1028a: https://www.nxp.com/products/processors-and-microcontrollers/arm-processors/layerscape-processors/layerscape-1028a-applications-processor:LS1028A
+.. _ls1028ardb: https://www.nxp.com/design/qoriq-developer-resources/layerscape-ls1028a-reference-design-board:LS1028ARDB
+.. _nxp-ls-tbbr.rst: ./nxp-ls-tbbr.rst
diff --git a/docs/plat/nxp/nxp-ls-fuse-prov.rst b/docs/plat/nxp/nxp-ls-fuse-prov.rst
new file mode 100644
index 0000000..64e1c6f
--- /dev/null
+++ b/docs/plat/nxp/nxp-ls-fuse-prov.rst
@@ -0,0 +1,271 @@
+
+Steps to blow fuses on NXP LS SoC:
+==================================
+
+
+- Enable POVDD
+  -- Refer board GSG(Getting Started Guide) for the steps to enable POVDD.
+  -- Once the POVDD is enabled, make sure to set variable POVDD_ENABLE := yes, in the platform.mk.
+
++---+-----------------+-----------+------------+-----------------+-----------------------------+
+|   |   Platform      |  Jumper   |  Switch    | LED to Verify   |  Through GPIO Pin (=number) |
++===+=================+===========+============+=================+=============================+
+| 1.| lx2160ardb      |  J9       |            |                 |             no              |
++---+-----------------+-----------+------------+-----------------+-----------------------------+
+| 2.| lx2160aqds      |  J35      |            |                 |             no              |
++---+-----------------+-----------+------------+-----------------+-----------------------------+
+| 3.| lx2162aqds      |  J35      | SW9[4] = 1 |    D15          |             no              |
++---+-----------------+-----------+------------+-----------------+-----------------------------+
+
+- SFP registers to be written to:
+
++---+----------------------------------+----------------------+----------------------+
+|   |   Platform                       |   OTPMKR0..OTPMKR7   |   SRKHR0..SRKHR7     |
++===+==================================+======================+======================+
+| 1.| lx2160ardb/lx2160aqds/lx2162aqds | 0x1e80234..0x1e80250 | 0x1e80254..0x1e80270 |
++---+----------------------------------+----------------------+----------------------+
+
+- At U-Boot prompt, verify that SNVS register - HPSR, whether OTPMK was written, already:
+
++---+----------------------------------+-------------------------------------------+---------------+
+|   |   Platform                       |           OTPMK_ZERO_BIT(=value)          | SNVS_HPSR_REG |
++===+==================================+===========================================+===============+
+| 1.| lx2160ardb/lx2160aqds/lx2162aqds | 27 (= 1 means not blown, =0 means blown)  | 0x01E90014    |
++---+----------------------------------+-------------------------------------------+---------------+
+
+From u-boot prompt:
+
+  --  Check for the OTPMK.
+   .. code:: shell
+
+        md $SNVS_HPSR_REG
+
+      Command Output:
+          01e90014: 88000900
+
+          In case it is read as 00000000, then read this register using jtag (in development mode only through CW tap).
+                       +0       +4       +8       +C
+          [0x01E90014] 88000900
+
+          Note: OTPMK_ZERO_BIT is 1, indicating that the OTPMK is not blown.
+
+  --  Check for the SRK Hash.
+   .. code:: shell
+
+        md $SRKHR0 0x10
+
+      Command Output:
+          01e80254: 00000000 00000000 00000000 00000000    ................
+          01e80264: 00000000 00000000 00000000 00000000    ................
+
+          Note: Zero means that SRK hash is not blown.
+
+- If not blown, then from the U-Boot prompt, using following commands:
+  --  Provision the OTPMK.
+
+   .. code:: shell
+
+        mw.l $OTPMKR0  <OTMPKR_0_32Bit_val>
+        mw.l $OTPMKR1  <OTMPKR_1_32Bit_val>
+        mw.l $OTPMKR2  <OTMPKR_2_32Bit_val>
+        mw.l $OTPMKR3  <OTMPKR_3_32Bit_val>
+        mw.l $OTPMKR4  <OTMPKR_4_32Bit_val>
+        mw.l $OTPMKR5  <OTMPKR_5_32Bit_val>
+        mw.l $OTPMKR6  <OTMPKR_6_32Bit_val>
+        mw.l $OTPMKR7  <OTMPKR_7_32Bit_val>
+
+  --  Provision the SRK Hash.
+
+   .. code:: shell
+
+        mw.l $SRKHR0  <SRKHR_0_32Bit_val>
+        mw.l $SRKHR1  <SRKHR_1_32Bit_val>
+        mw.l $SRKHR2  <SRKHR_2_32Bit_val>
+        mw.l $SRKHR3  <SRKHR_3_32Bit_val>
+        mw.l $SRKHR4  <SRKHR_4_32Bit_val>
+        mw.l $SRKHR5  <SRKHR_5_32Bit_val>
+        mw.l $SRKHR6  <SRKHR_6_32Bit_val>
+        mw.l $SRKHR7  <SRKHR_7_32Bit_val>
+
+      Note: SRK Hash should be carefully written keeping in mind the SFP Block Endianness.
+
+- At U-Boot prompt, verify that SNVS registers for OTPMK are correctly written:
+
+  --  Check for the OTPMK.
+   .. code:: shell
+
+        md $SNVS_HPSR_REG
+
+      Command Output:
+          01e90014: 80000900
+
+          OTPMK_ZERO_BIT is zero, indicating that the OTPMK is blown.
+
+          Note: In case it is read as 00000000, then read this register using jtag (in development mode only through CW tap).
+
+   .. code:: shell
+
+        md $OTPMKR0 0x10
+
+      Command Output:
+          01e80234: ffffffff ffffffff ffffffff ffffffff    ................
+          01e80244: ffffffff ffffffff ffffffff ffffffff    ................
+
+          Note: OTPMK will never be visible in plain.
+
+  --  Check for the SRK Hash. For example, if following SRK hash is written:
+
+       SFP SRKHR0 = fdc2fed4
+       SFP SRKHR1 = 317f569e
+       SFP SRKHR2 = 1828425c
+       SFP SRKHR3 = e87b5cfd
+       SFP SRKHR4 = 34beab8f
+       SFP SRKHR5 = df792a70
+       SFP SRKHR6 = 2dff85e1
+       SFP SRKHR7 = 32a29687,
+
+       then following would be the value on dumping SRK hash.
+
+   .. code:: shell
+
+        md $SRKHR0 0x10
+
+      Command Output:
+          01e80254: d4fec2fd 9e567f31 5c422818 fd5c7be8    ....1.V..(B\.{\.
+          01e80264: 8fabbe34 702a79df e185ff2d 8796a232    4....y*p-...2...
+
+          Note: SRK Hash is visible in plain based on the SFP Block Endianness.
+
+- Caution: Donot proceed to the next step, until you are sure that OTPMK and SRKH are correctly blown from above steps.
+  -- After the next step, there is no turning back.
+  -- Fuses will be burnt, which cannot be undo.
+
+- Write SFP_INGR[INST] with the PROGFB(0x2) instruction to blow the fuses.
+  -- User need to save the SRK key pair and OTPMK Key forever, to continue using this board.
+
++---+----------------------------------+-------------------------------------------+-----------+
+|   |   Platform                       | SFP_INGR_REG | SFP_WRITE_DATE_FRM_MIRROR_REG_TO_FUSE  |
++===+==================================+=======================================================+
+| 1.| lx2160ardb/lx2160aqds/lx2162aqds | 0x01E80020   |    0x2                                 |
++---+----------------------------------+--------------+----------------------------------------+
+
+   .. code:: shell
+
+        md $SFP_INGR_REG  $SFP_WRITE_DATE_FRM_MIRROR_REG_TO_FUSE
+
+- On reset, if the SFP register were read from u-boot, it will show the following:
+  --  Check for the OTPMK.
+
+   .. code:: shell
+
+        md $SNVS_HPSR_REG
+
+      Command Output:
+          01e90014: 80000900
+
+          In case it is read as 00000000, then read this register using jtag (in development mode only through CW tap).
+                       +0       +4       +8       +C
+          [0x01E90014] 80000900
+
+          Note: OTPMK_ZERO_BIT is zero, indicating that the OTPMK is blown.
+
+   .. code:: shell
+
+        md $OTPMKR0 0x10
+
+      Command Output:
+          01e80234: ffffffff ffffffff ffffffff ffffffff    ................
+          01e80244: ffffffff ffffffff ffffffff ffffffff    ................
+
+          Note: OTPMK will never be visible in plain.
+
+  -- SRK Hash
+
+   .. code:: shell
+
+        md $SRKHR0 0x10
+
+      Command Output:
+          01e80254: d4fec2fd 9e567f31 5c422818 fd5c7be8    ....1.V..(B\.{\.
+          01e80264: 8fabbe34 702a79df e185ff2d 8796a232    4....y*p-...2...
+
+          Note: SRK Hash is visible in plain based on the SFP Block Endianness.
+
+Second method to do the fuse provsioning:
+=========================================
+
+This method is used for quick way to provision fuses.
+Typically used by those who needs to provision number of boards.
+
+- Enable POVDD:
+  -- Refer the table above to enable POVDD.
+
+     Note: If GPIO Pin supports enabling POVDD, it can be done through the below input_fuse_file.
+
+  -- Once the POVDD is enabled, make sure to set variable POVDD_ENABLE := yes, in the platform.mk.
+
+- User need to populate the "input_fuse_file", corresponding to the platform for:
+
+  -- OTPMK
+  -- SRKH
+
+  Table of fuse provisioning input file for every supported platform:
+
++---+----------------------------------+-----------------------------------------------------------------+
+|   |   Platform                       |                        FUSE_PROV_FILE                           |
++===+==================================+=================================================================+
+| 1.| lx2160ardb/lx2160aqds/lx2162aqds | ${CST_DIR}/input_files/gen_fusescr/ls2088_1088/input_fuse_file  |
++---+----------------------------------+--------------+--------------------------------------------------+
+
+- Create the TF-A binary with FUSE_PROG=1.
+
+   .. code:: shell
+
+        make PLAT=$PLAT FUSE_PROG=1\
+          BOOT_MODE=<platform_supported_boot_mode> \
+          RCW=$RCW_BIN \
+          BL32=$TEE_BIN SPD=opteed\
+          BL33=$UBOOT_SECURE_BIN \
+          pbl \
+          fip \
+          fip_fuse \
+          FUSE_PROV_FILE=../../apps/security/cst/input_files/gen_fusescr/ls2088_1088/input_fuse_file
+
+- Deployment:
+  -- Refer the nxp-layerscape.rst for deploying TF-A images.
+  -- Deploying fip_fuse.bin:
+
+       For Flexspi-Nor:
+
+   .. code:: shell
+
+        tftp 82000000  $path/fuse_fip.bin;
+        i2c mw 66 50 20;sf probe 0:0; sf erase 0x880000 +$filesize; sf write 0x82000000 0x880000 $filesize;
+
+      For SD or eMMC [file_size_in_block_sizeof_512 = (Size_of_bytes_tftp / 512)]:
+
+   .. code:: shell
+
+        tftp 82000000  $path/fuse_fip.bin;
+        mmc write 82000000 0x4408 <file_size_in_block_sizeof_512>;
+
+- Valiation:
+
++---+----------------------------------+---------------------------------------------------+
+|   |   Platform                       |    Error_Register        | Error_Register_Address |
++===+==================================+===================================================+
+| 1.| lx2160ardb/lx2160aqds/lx2162aqds | DCFG scratch 4 register  |     0x01EE020C         |
++---+----------------------------------+---------------------------------------------------+
+
+   At the U-Boot prompt, check DCFG scratch 4 register for any error.
+
+   .. code:: shell
+
+        md $Error_Register_Address 1
+
+      Command Ouput:
+          01ee020c: 00000000
+
+      Note:
+       - 0x00000000 shows no error, then fuse provisioning is successful.
+       - For non-zero value, refer the code header file ".../drivers/nxp/sfp/sfp_error_codes.h"
diff --git a/docs/plat/nxp/nxp-ls-tbbr.rst b/docs/plat/nxp/nxp-ls-tbbr.rst
new file mode 100644
index 0000000..43e15f7
--- /dev/null
+++ b/docs/plat/nxp/nxp-ls-tbbr.rst
@@ -0,0 +1,210 @@
+
+--------------
+NXP Platforms:
+--------------
+TRUSTED_BOARD_BOOT option can be enabled by specifying TRUSTED_BOARD_BOOT=1 on command line during make.
+
+
+
+Bare-Minimum Preparation to run  TBBR on NXP Platforms:
+=======================================================
+- OTPMK(One Time Programable Key) needs to be burnt in fuses.
+  -- It is the 256 bit key that stores a secret value used by the NXP SEC 4.0 IP in Trusted or Secure mode.
+
+     Note: It is primarily for the purpose of decrypting additional secrets stored in system non-volatile memory.
+
+  -- NXP CST tool gives an option to generate it.
+
+   Use the below command from directory 'cst', with correct options.
+
+   .. code:: shell
+
+     ./gen_otpmk_drbg
+
+- SRKH (Super Root Key Hash) needs to be burnt in fuses.
+  -- It is the 256 bit hash of the list of the public keys of the SRK key pair.
+  -- NXP CST tool gives an option to generate the RSA key pair and its hash.
+
+   Use the below command from directory 'cst', with correct options.
+
+   .. code:: shell
+
+     ./gen_keys
+
+Refer fuse frovisioning readme 'nxp-ls-fuse-prov.rst' for steps to blow these keys.
+
+
+
+Two options are provided for TRUSTED_BOARD_BOOT:
+================================================
+
+-------------------------------------------------------------------------
+Option 1: CoT using X 509 certificates
+-------------------------------------------------------------------------
+
+- This CoT is as provided by ARM.
+
+- To use this option user needs to specify mbedtld dir path in MBEDTLS_DIR.
+
+- To generate CSF header, path of CST repository needs to be specified as CST_DIR
+
+- CSF header is embedded to each of the BL2 image.
+
+- GENERATE_COT=1 adds the tool 'cert_create' to the build environment to generate:
+  -- X509 Certificates as (.crt) files.
+  -- X509 Pem key file as (.pem) files.
+
+- SAVE_KEYS=1 saves the keys and certificates, if GENERATE_COT=1.
+  -- For this to work, file name for cert and keys are provided as part of  compilation or build command.
+
+     --- default file names will be used, incase not provided as part compilation or build command.
+     --- default folder 'BUILD_PLAT' will be used to store them.
+
+- ROTPK for x.509 certificates is generated and embedded in bl2.bin and
+  verified as part of CoT by Boot ROM during secure boot.
+
+- Compilation steps:
+
+All Images
+   .. code:: shell
+
+       make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 MBEDTLS_DIR=$MBEDTLS_PATH CST_DIR=$CST_DIR_PATH \
+       BOOT_MODE=<platform_supported_boot_mode> \
+       RCW=$RCW_BIN \
+       BL32=$TEE_BIN SPD=opteed\
+       BL33=$UBOOT_SECURE_BIN \
+       pbl \
+       fip
+
+Additional FIP_DDR Image (For NXP platforms like lx2160a)
+   .. code:: shell
+
+       make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 MBEDTLS_DIR=$MBEDTLS_PATH fip_ddr
+
+      Note: make target 'fip_ddr' should never be combine with other make target 'fip', 'pbl' & 'bl2'.
+
+-------------------------------------------------------------------------
+Option 2: CoT using NXP CSF headers.
+-------------------------------------------------------------------------
+
+- This option is automatically selected when TRUSTED_BOARD_BOOT is set but MBEDTLS_DIR path is not specified.
+
+- CSF header is embedded to each of the BL31, BL32 and  BL33 image.
+
+- To generate CSF header, path of CST repository needs to be specified as CST_DIR
+
+- Default input files for CSF header generation is added in this repo.
+
+- Default input file requires user to generate RSA key pair named
+  -- srk.pri, and
+  -- srk.pub, and add them in ATF repo.
+  -- These keys can be generated using gen_keys tool of CST.
+
+- To change the input file , user can use the options BL33_INPUT_FILE, BL32_INPUT_FILE, BL31_INPUT_FILE
+
+- There are 2 paths in secure boot flow :
+  -- Development Mode (sb_en in RCW = 1, SFP->OSPR, ITS = 0)
+
+     --- In this flow , even on ROTPK comparison failure, flow would continue.
+     --- However SNVS is transitioned to non-secure state
+
+  -- Production mode (SFP->OSPR, ITS = 1)
+
+     --- Any failure is fatal failure
+
+- Compilation steps:
+
+All Images
+   .. code:: shell
+
+       make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 CST_DIR=$CST_DIR_PATH \
+       BOOT_MODE=<platform_supported_boot_mode> \
+       RCW=$RCW_BIN \
+       BL32=$TEE_BIN SPD=opteed\
+       BL33=$UBOOT_SECURE_BIN \
+       pbl \
+       fip
+
+Additional FIP_DDR Image (For NXP platforms like lx2160a)
+   .. code:: shell
+
+       make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 CST_DIR=$CST_DIR_PATH fip_ddr
+
+- Compilation Steps with build option for generic image processing filters to prepend CSF header:
+  --  Generic image processing filters to prepend CSF header
+
+      BL32_INPUT_FILE = < file name>
+      BL33_INPUT_FILE = <file name>
+
+   .. code:: shell
+
+       make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 CST_DIR=$CST_DIR_PATH \
+       BOOT_MODE=<platform_supported_boot_mode> \
+       RCW=$RCW_BIN \
+       BL32=$TEE_BIN SPD=opteed\
+       BL33=$UBOOT_SECURE_BIN \
+       BL33_INPUT_FILE = <ip file> \
+       BL32_INPUT_FILE = <ip_file> \
+       BL31_INPUT_FILE = <ip file> \
+       pbl \
+       fip
+
+
+Deploy ATF Images
+=================
+Same steps as mentioned in the readme "nxp-layerscape.rst".
+
+
+
+Verification to check if Secure state is achieved:
+==================================================
+
++---+----------------+-----------------+------------------------+----------------------------------+-------------------------------+
+|   |   Platform     |  SNVS_HPSR_REG  | SYS_SECURE_BIT(=value) | SYSTEM_SECURE_CONFIG_BIT(=value) | SSM_STATE                     |
++===+================+=================+========================+==================================+===============================+
+| 1.| lx2160ardb  or |    0x01E90014   | 15                     | 14-12                            | 11-8                          |
+|   | lx2160aqds  or |                 | ( = 1, BootROM Booted) | ( = 010 means Intent to Secure,  | (=1111 means secure boot)     |
+|   | lx2162aqds     |                 |                        | ( = 000 Unsecure)                | (=1011 means Non-secure Boot) |
++---+----------------+-----------------+------------------------+----------------------------------+-------------------------------+
+
+- Production mode (SFP->OSPR, ITS = 1)
+  -- Linux prompt will successfully come. if the TBBR is successful.
+
+     --- Else, Linux boot will be successful.
+
+  -- For secure-boot status, read SNVS Register $SNVS_HPSR_REG from u-boot prompt:
+
+   .. code:: shell
+
+        md $SNVS_HPSR_REG
+
+      Command Output:
+          1e90014: 8000AF00
+
+          In case it is read as 00000000, then read this register using jtag (in development mode only through CW tap).
+                       +0       +4       +8       +C
+          [0x01E90014] 8000AF00
+
+
+- Development Mode (sb_en in RCW = 1, SFP->OSPR, ITS = 0)
+  -- Refer the SoC specific table to read the register to interpret whether the secure boot is achieved or not.
+  -- Using JTAG (in development environment only, using CW tap):
+
+     --- For secure-boot status, read SNVS Register $SNVS_HPSR_REG
+
+   .. code:: shell
+
+        ccs::display_regs 86 0x01E90014 4 0 1
+
+      Command Output:
+          Using the SAP chain position number 86, following is the output.
+
+                       +0       +4       +8       +C
+          [0x01E90014] 8000AF00
+
+          Note: Chain position number will vary from one SoC to other SoC.
+
+- Interpretation of the value:
+
+  -- 0xA indicates BootROM booted, with intent to secure.
+  -- 0xF = secure boot, as SSM_STATE.
diff --git a/docs/plat/qti.rst b/docs/plat/qti.rst
index 814e672..1d483e7 100644
--- a/docs/plat/qti.rst
+++ b/docs/plat/qti.rst
@@ -1,8 +1,8 @@
 Qualcomm Technologies, Inc.
 ===========================
 
-Trusted Firmware-A (TF-A) implements the EL3 firmware layer for QTI SC7180.
-
+Trusted Firmware-A (TF-A) implements the EL3 firmware layer for QTI SC7180,
+SC7280.
 
 Boot Trace
 -------------
@@ -38,4 +38,6 @@
 added to satisfy compilation.
 
 QTISELIB for SC7180 is available at
-`link <https://review.coreboot.org/cgit/qc_blobs.git/plain/sc7180/qtiseclib/libqtisec.a>`__
+`link <https://github.com/coreboot/qc_blobs/blob/master/sc7180/qtiseclib/libqtisec.a?raw=true>`__
+QTISELIB for SC7280 is available at
+`link <https://github.com/coreboot/qc_blobs/blob/master/sc7280/qtiseclib/libqtisec.a?raw=true>`__
diff --git a/docs/plat/stm32mp1.rst b/docs/plat/stm32mp1.rst
index 0ef2923..17f7a86 100644
--- a/docs/plat/stm32mp1.rst
+++ b/docs/plat/stm32mp1.rst
@@ -37,6 +37,17 @@
 for ROM code is able to load this image.
 Tool stm32image can be used to prepend this header to the generated TF-A binary.
 
+Boot with FIP
+~~~~~~~~~~~~~
+The use of FIP is now the recommended way to boot STM32MP1 platform.
+Only BL2 (with STM32 header) is loaded by ROM code. The other binaries are
+inside the FIP binary: BL32 (SP_min or OP-TEE), U-Boot and their respective
+device tree blobs.
+
+STM32IMAGE bootchain
+~~~~~~~~~~~~~~~~~~~~
+Although still supported, this way of booting is not recommended.
+Pease use FIP instead.
 At compilation step, BL2, BL32 and DTB file are linked together in a single
 binary. The stm32image tool is also generated and the header is added to TF-A
 binary. This binary file with header is named tf-a-stm32mp157c-ev1.stm32.
@@ -55,15 +66,17 @@
                |       ...       |
                |                 |
     0x2FFC0000 +-----------------+ \
-               |                 | |
+               |     BL32 DTB    | |
+    0x2FFC5000 +-----------------+ |
+               |       BL32      | |
+    0x2FFDF000 +-----------------+ |
                |       ...       | |
-               |                 | |
-    0x2FFD8000 +-----------------+ |
-               |    TF-A DTB     | | Embedded SRAM
-    0x2FFDC000 +-----------------+ |
+    0x2FFE3000 +-----------------+ |
+               |     BL2 DTB     | | Embedded SRAM
+    0x2FFEA000 +-----------------+ |
                |       BL2       | |
-    0x2FFEF000 +-----------------+ |
-               |       BL32      | |
+    0x2FFFF000 +-----------------+ |
+               |  SCMI mailbox   | |
     0x30000000 +-----------------+ /
                |                 |
                |       ...       |
@@ -102,23 +115,110 @@
 - ``STM32MP_SPI_NAND``
 - ``STM32MP_SPI_NOR``
 
-To build with SP_min and support for all bootable devices:
+Boot with FIP
+~~~~~~~~~~~~~
+You need to build BL2, BL32 (SP_min or OP-TEE) and BL33 (U-Boot) before building FIP binary.
+
+U-Boot
+______
 
 .. code:: bash
 
-    make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=sp_min STM32MP_SDMMC=1 STM32MP_EMMC=1 STM32MP_RAW_NAND=1 STM32MP_SPI_NAND=1
-    STM32MP_SPI_NOR=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb
     cd <u-boot_directory>
     make stm32mp15_trusted_defconfig
     make DEVICE_TREE=stm32mp157c-ev1 all
 
-To build TF-A with OP-TEE support for all bootable devices:
+OP-TEE (optional)
+_________________
 
 .. code:: bash
 
-    make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=optee STM32MP_SDMMC=1 STM32MP_EMMC=1 STM32MP_RAW_NAND=1 STM32MP_SPI_NAND=1 STM32MP_SPI_NOR=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb
     cd <optee_directory>
-    make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm PLATFORM=stm32mp1 CFG_EMBED_DTB_SOURCE_FILE=stm32mp157c-ev1.dts
+    make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm PLATFORM=stm32mp1 \
+        CFG_EMBED_DTB_SOURCE_FILE=stm32mp157c-ev1.dts
+
+
+TF-A BL32 (SP_min)
+__________________
+If you choose not to use OP-TEE, you can use TF-A SP_min.
+To build TF-A BL32, and its device tree file:
+
+.. code:: bash
+
+    make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \
+        AARCH32_SP=sp_min DTB_FILE_NAME=stm32mp157c-ev1.dtb bl32 dtbs
+
+TF-A BL2
+________
+To build TF-A BL2 with its STM32 header for SD-card boot:
+
+.. code:: bash
+
+    make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \
+        DTB_FILE_NAME=stm32mp157c-ev1.dtb STM32MP_SDMMC=1
+
+For other boot devices, you have to replace STM32MP_SDMMC in the previous command
+with the desired device flag.
+
+This BL2 is independent of the BL32 used (SP_min or OP-TEE)
+
+
+FIP
+___
+With BL32 SP_min:
+
+.. code:: bash
+
+    make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \
+        AARCH32_SP=sp_min \
+        DTB_FILE_NAME=stm32mp157c-ev1.dtb \
+        BL33=<u-boot_directory>/u-boot-nodtb.bin \
+        BL33_CFG=<u-boot_directory>/u-boot.dtb \
+        fip
+
+With OP-TEE:
+
+.. code:: bash
+
+    make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \
+        DTB_FILE_NAME=stm32mp157c-ev1.dtb \
+        BL33=<u-boot_directory>/u-boot-nodtb.bin \
+        BL33_CFG=<u-boot_directory>/u-boot.dtb \
+        BL32=<optee_directory>/tee-header_v2.bin \
+        BL32_EXTRA1=<optee_directory>/tee-pager_v2.bin
+        BL32_EXTRA2=<optee_directory>/tee-pageable_v2.bin
+        fip
+
+
+STM32IMAGE bootchain
+~~~~~~~~~~~~~~~~~~~~
+You need to add the following flag to the make command:
+``STM32MP_USE_STM32IMAGE=1``
+
+To build with SP_min and support for SD-card boot:
+
+.. code:: bash
+
+    make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \
+        AARCH32_SP=sp_min STM32MP_SDMMC=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb \
+        STM32MP_USE_STM32IMAGE=1
+
+    cd <u-boot_directory>
+    make stm32mp15_trusted_defconfig
+    make DEVICE_TREE=stm32mp157c-ev1 all
+
+To build TF-A with OP-TEE support for SD-card boot:
+
+.. code:: bash
+
+    make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \
+        AARCH32_SP=optee STM32MP_SDMMC=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb \
+        STM32MP_USE_STM32IMAGE=1
+
+    cd <optee_directory>
+    make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm PLATFORM=stm32mp1 \
+        CFG_EMBED_DTB_SOURCE_FILE=stm32mp157c-ev1.dts
+
     cd <u-boot_directory>
     make stm32mp15_trusted_defconfig
     make DEVICE_TREE=stm32mp157c-ev1 all
@@ -132,7 +232,19 @@
 Populate SD-card
 ----------------
 
+Boot with FIP
+~~~~~~~~~~~~~
+The SD-card has to be formatted with GPT.
+It should contain at least those partitions:
+
+- fsbl: to copy the tf-a-stm32mp157c-ev1.stm32 binary (BL2)
+- fip: which contains the FIP binary
+
+Usually, two copies of fsbl are used (fsbl1 and fsbl2) instead of one partition fsbl.
+
-The SD-card has to be formated with GPT.
+STM32IMAGE bootchain
+~~~~~~~~~~~~~~~~~~~~
+The SD-card has to be formatted with GPT.
 It should contain at least those partitions:
 
 - fsbl: to copy the tf-a-stm32mp157c-ev1.stm32 binary
diff --git a/docs/plat/xilinx-versal.rst b/docs/plat/xilinx-versal.rst
index 3d4c4a4..d65b048 100644
--- a/docs/plat/xilinx-versal.rst
+++ b/docs/plat/xilinx-versal.rst
@@ -24,6 +24,11 @@
 make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal bl31 VERSAL_CONSOLE=dcc
 ```
 
+To build TF-A with Straight-Line Speculation(SLS)
+```bash
+make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal bl31 HARDEN_SLS_ALL=1
+```
+
 Xilinx Versal platform specific build options
 ---------------------------------------------
 
diff --git a/docs/process/contributing.rst b/docs/process/contributing.rst
index c91903a..aa050da 100644
--- a/docs/process/contributing.rst
+++ b/docs/process/contributing.rst
@@ -209,6 +209,65 @@
       revert your patches and ask you to resubmit a reworked version of them or
       they may ask you to provide a fix-up patch.
 
+Add Build Configurations
+------------------------
+
+-  TF-A uses Jenkins tool for Continuous Integration and testing activities.
+   Various CI Jobs are deployed which run tests on every patch before being
+   merged. So each of your patches go through a series of checks before they
+   get merged on to the master branch.
+
+-  ``Coverity Scan analysis`` is one of the tests we perform on our source code
+   at regular intervals. We maintain a build script ``tf-cov-make`` which contains the
+   build configurations of various platforms in order to cover the entire source
+   code being analysed by Coverity.
+
+-  When you submit your patches for review containing new source files, please
+   ensure to include them for the ``Coverity Scan analysis`` by adding the
+   respective build configurations in the ``tf-cov-make`` build script.
+
+-  In this section you find the details on how to append your new build
+   configurations for Coverity Scan analysis:
+
+#. We maintain a separate repository named `tf-a-ci-scripts repository`_
+   for placing all the test scripts which will be executed by the CI Jobs.
+
+#. In this repository, ``tf-cov-make`` script is located at
+   ``tf-a-ci-scripts/script/tf-coverity/tf-cov-make``
+
+#. Edit `tf-cov-make`_ script by appending all the possible build configurations with
+   the specific ``build-flags`` relevant to your platform, so that newly added
+   source files get built and analysed by Coverity.
+
+#. For better understanding follow the below specified examples listed in the
+   ``tf-cov-make`` script.
+
+.. code:: shell
+
+    Example 1:
+    #Intel
+    make PLAT=stratix10 $(common_flags) all
+    make PLAT=agilex $(common_flags) all
+
+-  In the above example there are two different SoCs ``stratix`` and ``agilex``
+   under the Intel platform and the build configurations has been added suitably
+   to include most of their source files.
+
+.. code:: shell
+
+    Example 2:
+    #Hikey
+    make PLAT=hikey $(common_flags) ${TBB_OPTIONS} ENABLE_PMF=1 all
+    make PLAT=hikey960 $(common_flags) ${TBB_OPTIONS} all
+    make PLAT=poplar $(common_flags) all
+
+-  In this case for ``Hikey`` boards additional ``build-flags`` has been included
+   along with the ``commom_flags`` to cover most of the files relevant to it.
+
+-  Similar to this you can still find many other different build configurations
+   of various other platforms listed in the ``tf-cov-make`` script. Kindly refer
+   them and append your build configurations respectively.
+
 Binary Components
 -----------------
 
@@ -228,7 +287,7 @@
 
 --------------
 
-*Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.*
 
 .. _Conventional Commits: https://www.conventionalcommits.org/en/v1.0.0
 .. _developer.trustedfirmware.org: https://developer.trustedfirmware.org
@@ -243,3 +302,5 @@
 .. _Trusted Firmware binary repository: https://review.trustedfirmware.org/admin/repos/tf-binaries
 .. _tf-binaries-readme: https://git.trustedfirmware.org/tf-binaries.git/tree/readme.rst
 .. _TF-A mailing list: https://lists.trustedfirmware.org/mailman/listinfo/tf-a
+.. _tf-a-ci-scripts repository: https://git.trustedfirmware.org/ci/tf-a-ci-scripts.git/
+.. _tf-cov-make: https://git.trustedfirmware.org/ci/tf-a-ci-scripts.git/tree/script/tf-coverity/tf-cov-make
diff --git a/docs/resources/diagrams/plantuml/spm_dfd.puml b/docs/resources/diagrams/plantuml/spm_dfd.puml
new file mode 100644
index 0000000..ad4996e
--- /dev/null
+++ b/docs/resources/diagrams/plantuml/spm_dfd.puml
@@ -0,0 +1,82 @@
+/'
+ ' Copyright (c) 2021, Arm Limited. All rights reserved.
+ '
+ ' SPDX-License-Identifier: BSD-3-Clause
+ '/
+
+/'
+TF-A SPMC Data Flow Diagram
+'/
+
+@startuml
+digraph tfa_dfd {
+
+    # Allow arrows to end on cluster boundaries
+    compound=true
+
+    # Default settings for edges and nodes
+    edge [minlen=2 color="#8c1b07"]
+    node [fillcolor="#ffb866" style=filled shape=box fixedsize=true width=1.6 height=0.7]
+
+    # Nodes outside of the trust boundary
+    nsec [label="NS Client"]
+    ddr  [label="External memory (DDR)"]
+
+    # Trust boundary cluster
+    subgraph cluster_trusted {
+        graph [style=dashed color="#f22430"]
+
+        # HW IPs cluster
+        subgraph cluster_ip {
+            label ="Hardware IPs";
+            graph [style=filled color="#000000" fillcolor="#ffd29e"]
+
+            rank="same"
+            gic [label="GIC" width=1.2 height=0.5]
+            smmu [label="SMMU" width=1.2 height=0.5]
+            uart [label="UART" width=1.2 height=0.5]
+	    pe [label="PE" width=1.2 height=0.5]
+        }
+
+        # TF-A cluster
+        subgraph cluster_tfa {
+            label ="EL3 monitor";
+            graph [style=filled color="#000000" fillcolor="#faf9cd"]
+
+            bl31 [label="BL31" fillcolor="#ddffb3"];
+            spmd [label="SPMD" fillcolor="#ddffb3" height=1]
+        }
+
+        # SPMC cluster
+        subgraph cluster_spmc {
+            label ="SPMC";
+            graph [style=filled color="#000000" fillcolor="#faf9cd"]
+
+            spmc [label="SPMC" fillcolor="#ddffb3" height=1]
+        }
+	bl2 [label="BL2" width=1.2 height=0.5]
+    }
+
+    # Secure Partitions cluster
+    subgraph cluster_sp {
+        label ="Secure Partitions";
+        graph [style=filled color="#000000" fillcolor="#faf9cd"]
+
+        sp1 [label="SP1" fillcolor="#ddffb3" height=1]
+        sp2 [label="SP2" fillcolor="#ddffb3" height=1]
+        spn [label="SP..." fillcolor="#ddffb3" height=1]
+    }
+
+    # Interactions between nodes
+    sp1 -> spmc [dir="both" label="DF1"]
+    spmc -> spmd [dir="both" label="DF2"]
+    spmd -> nsec [dir="both" label="DF3"]
+    sp1 -> sp2 [dir="both" label="DF4"]
+    spmc -> smmu [lhead=cluster_spmc label="DF5"]
+    bl2 -> spmc [lhead=cluster_spmc label="DF6"]
+    bl2 -> spn [lhead=cluster_spmc label="DF6"]
+    sp1 -> ddr [dir="both"  label="DF7"]
+    spmc -> ddr [dir="both"  label="DF7"]
+}
+
+@enduml
diff --git a/docs/resources/diagrams/spm-threat-model-trust-boundaries.png b/docs/resources/diagrams/spm-threat-model-trust-boundaries.png
new file mode 100644
index 0000000..58898c5
--- /dev/null
+++ b/docs/resources/diagrams/spm-threat-model-trust-boundaries.png
Binary files differ
diff --git a/docs/threat_model/index.rst b/docs/threat_model/index.rst
index e8f09b9..b5ede69 100644
--- a/docs/threat_model/index.rst
+++ b/docs/threat_model/index.rst
@@ -1,5 +1,12 @@
 Threat Model
-=============
+============
+
+Threat modeling is an important part of Secure Development Lifecycle (SDL)
+that helps us identify potential threats and mitigations affecting a system.
+
+In the next sections, we first give a description of the target of evaluation
+using a data flow diagram. Then we provide a list of threats we have identified
+based on the data flow diagram and potential threat mitigations.
 
 .. toctree::
    :maxdepth: 1
@@ -7,6 +14,7 @@
    :numbered:
 
    threat_model
+   threat_model_spm
 
 --------------
 
diff --git a/docs/threat_model/threat_model.rst b/docs/threat_model/threat_model.rst
index 9cee104..9f26487 100644
--- a/docs/threat_model/threat_model.rst
+++ b/docs/threat_model/threat_model.rst
@@ -1,13 +1,10 @@
-*****************
-Introduction
-*****************
-Threat modeling is an important part of Secure Development Lifecycle (SDL)
-that helps us identify potential threats and mitigations affecting a system.
+Generic threat model
+********************
 
-This document provides a generic threat model for TF-A firmware. In the
-next sections, we first give a description of the target of evaluation
-using a data flow diagram. Then we provide a list of threats we have
-identified based on the data flow diagram and potential threat mitigations.
+************************
+Introduction
+************************
+This document provides a generic threat model for TF-A firmware.
 
 ************************
 Target of Evaluation
@@ -781,4 +778,4 @@
 .. _Trusted Board Boot (TBB): https://trustedfirmware-a.readthedocs.io/en/latest/design/trusted-board-boot.html
 .. _TF-A error handling policy: https://trustedfirmware-a.readthedocs.io/en/latest/process/coding-guidelines.html#error-handling-and-robustness
 .. _Secure Development Guidelines: https://trustedfirmware-a.readthedocs.io/en/latest/process/security-hardening.html#secure-development-guidelines
-.. _Trusted Firmware-A Tests: https://git.trustedfirmware.org/TF-A/tf-a-tests.git/about/
\ No newline at end of file
+.. _Trusted Firmware-A Tests: https://git.trustedfirmware.org/TF-A/tf-a-tests.git/about/
diff --git a/docs/threat_model/threat_model_spm.rst b/docs/threat_model/threat_model_spm.rst
new file mode 100644
index 0000000..82f9916
--- /dev/null
+++ b/docs/threat_model/threat_model_spm.rst
@@ -0,0 +1,617 @@
+SPMC threat model
+*****************
+
+************************
+Introduction
+************************
+This document provides a threat model for the TF-A `Secure Partition Manager`_
+(SPM) implementation or more generally the S-EL2 reference firmware running on
+systems implementing the FEAT_SEL2 (formerly Armv8.4 Secure EL2) architecture
+extension. The SPM implementation is based on the `Arm Firmware Framework for
+Arm A-profile`_ specification.
+
+In brief, the broad FF-A specification and S-EL2 firmware implementation
+provide:
+
+- Isolation of mutually mistrusting SW components, or endpoints in the FF-A
+  terminology.
+- Distinct sandboxes in the secure world called secure partitions. This permits
+  isolation of services from multiple vendors.
+- A standard protocol for communication and memory sharing between FF-A
+  endpoints.
+- Mutual isolation of the normal world and the secure world (e.g. a Trusted OS
+  is prevented to map an arbitrary NS physical memory region such as the kernel
+  or the Hypervisor).
+
+************************
+Target of Evaluation
+************************
+In this threat model, the target of evaluation is the S-EL2 firmware or the
+``Secure Partition Manager Core`` component (SPMC).
+The monitor and SPMD at EL3 are covered by the `Generic TF-A threat model`_.
+
+The scope for this threat model is:
+
+- The TF-A implementation for the S-EL2 SPMC based on the Hafnium hypervisor
+  running in the secure world of TrustZone (at S-EL2 exception level).
+  The threat model is not related to the normal world Hypervisor or VMs.
+  The S-EL1 SPMC solution is not covered.
+- The implementation complies with the FF-A v1.0 specification.
+- Secure partitions are statically provisioned at boot time.
+- Focus on the run-time part of the life-cycle (no specific emphasis on boot
+  time, factory firmware provisioning, firmware udpate etc.)
+- Not covering advanced or invasive physical attacks such as decapsulation,
+  FIB etc.
+- Assumes secure boot or in particular TF-A trusted boot (TBBR or dual CoT) is
+  enabled. An attacker cannot boot arbitrary images that are not approved by the
+  SiP or platform providers.
+
+Data Flow Diagram
+======================
+Figure 1 shows a high-level data flow diagram for the SPM split into an SPMD
+component at EL3 and an SPMC component at S-EL2. The SPMD mostly acts as a
+relayer/pass-through between the normal world and the secure world. It is
+assumed to expose small attack surface.
+
+A description of each diagram element is given in Table 1. In the diagram, the
+red broken lines indicate trust boundaries.
+
+Components outside of the broken lines are considered untrusted.
+
+.. uml:: ../resources/diagrams/plantuml/spm_dfd.puml
+  :caption: Figure 1: SPMC Data Flow Diagram
+
+.. table:: Table 1: SPMC Data Flow Diagram Description
+
+  +---------------------+--------------------------------------------------------+
+  | Diagram Element     | Description                                            |
+  +=====================+========================================================+
+  | ``DF1``             | SP to SPMC communication. FF-A function invocation or  |
+  |                     | implementation-defined Hypervisor call.                |
+  +---------------------+--------------------------------------------------------+
+  | ``DF2``             | SPMC to SPMD FF-A call.                                |
+  +---------------------+--------------------------------------------------------+
+  | ``DF3``             | SPMD to NS forwarding.                                 |
+  +---------------------+--------------------------------------------------------+
+  | ``DF4``             | SP to SP FF-A direct message request/response.         |
+  |                     | Note as a matter of simplifying the diagram            |
+  |                     | the SP to SP communication happens through the SPMC    |
+  |                     | (SP1 performs a direct message request to the          |
+  |                     | SPMC targeting SP2 as destination. And similarly for   |
+  |                     | the direct message response from SP2 to SP1).          |
+  +---------------------+--------------------------------------------------------+
+  | ``DF5``             | HW control.                                            |
+  +---------------------+--------------------------------------------------------+
+  | ``DF6``             | Bootloader image loading.                              |
+  +---------------------+--------------------------------------------------------+
+  | ``DF7``             | External memory access.                                |
+  +---------------------+--------------------------------------------------------+
+
+*********************
+Threat Analysis
+*********************
+
+This threat model follows a similar methodology to the `Generic TF-A threat model`_.
+The following sections define:
+
+- Trust boundaries
+- Assets
+- Theat agents
+- Threat types
+
+Trust boundaries
+============================
+
+- Normal world is untrusted.
+- Secure world and normal world are separate trust boundaries.
+- EL3 monitor, SPMD and SPMC are trusted.
+- Bootloaders (in particular BL1/BL2 if using TF-A) and run-time BL31 are
+  implicitely trusted by the usage of secure boot.
+- EL3 monitor, SPMD, SPMC do not trust SPs.
+
+.. figure:: ../resources/diagrams/spm-threat-model-trust-boundaries.png
+
+    Figure 2: Trust boundaries
+
+Assets
+============================
+
+The following assets are identified:
+
+- SPMC state.
+- SP state.
+- Information exchange between endpoints (partition messages).
+- SPMC secrets (e.g. pointer authentication key when enabled)
+- SP secrets (e.g. application keys).
+- Scheduling cycles.
+- Shared memory.
+
+Threat Agents
+============================
+
+The following threat agents are identified:
+
+- NS-Endpoint identifies a non-secure endpoint: normal world client at NS-EL2
+  (Hypervisor) or NS-EL1 (VM or OS kernel).
+- S-Endpoint identifies a secure endpoint typically a secure partition.
+- Hardware attacks (non-invasive) requiring a physical access to the device,
+  such as bus probing or DRAM stress.
+
+Threat types
+============================
+
+The following threat categories as exposed in the `Generic TF-A threat model`_
+are re-used:
+
+- Spoofing
+- Tampering
+- Repudiation
+- Information disclosure
+- Denial of service
+- Elevation of privileges
+
+Similarly this threat model re-uses the same threat risk ratings. The risk
+analysis is evaluated based on the environment being ``Server`` or ``Mobile``.
+
+Threat Assessment
+============================
+
+The following threats are identified by applying STRIDE analysis on each diagram
+element of the data flow diagram.
+
++------------------------+----------------------------------------------------+
+| ID                     | 01                                                 |
++========================+====================================================+
+| ``Threat``             | **An endpoint impersonates the sender or receiver  |
+|                        | FF-A ID in a direct request/response invocation.** |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF1, DF2, DF3, DF4                                 |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMD, SPMC                                         |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | SP state                                           |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | NS-Endpoint, S-Endpoint                            |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Spoofing                                           |
++------------------------+------------------+-----------------+---------------+
+| ``Application``        |   ``Server``     |   ``Mobile``    |               |
++------------------------+------------------++----------------+---------------+
+| ``Impact``             | Critical(5)      | Critical(5)     |               |
++------------------------+------------------++----------------+---------------+
+| ``Likelihood``         | Critical(5)      | Critical(5)     |               |
++------------------------+------------------++----------------+---------------+
+| ``Total Risk Rating``  | Critical(25)     | Critical(25)    |               |
++------------------------+------------------+-----------------+---------------+
+| ``Mitigations``        | The TF-A SPMC does not mitigate this threat.       |
+|                        | The guidance below is left for a system integrator |
+|                        | to implemented as necessary.                       |
+|                        | The SPMC must enforce checks in the direct message |
+|                        | request/response interfaces such an endpoint cannot|
+|                        | spoof the origin and destination worlds (e.g. a NWd|
+|                        | originated message directed to the SWd cannot use a|
+|                        | SWd ID as the sender ID).                          |
+|                        | Additionally a software component residing in the  |
+|                        | SPMC can be added for the purpose of direct        |
+|                        | request/response filtering.                        |
+|                        | It can be configured with the list of known IDs    |
+|                        | and about which interaction can occur between one  |
+|                        | and another endpoint (e.g. which NWd endpoint ID   |
+|                        | sends a direct request to which SWd endpoint ID).  |
+|                        | This component checks the sender/receiver fields   |
+|                        | for a legitimate communication between endpoints.  |
+|                        | A similar component can exist in the OS kernel     |
+|                        | driver, or Hypervisor although it remains untrusted|
+|                        | by the SPMD/SPMC.                                  |
++------------------------+----------------------------------------------------+
+
++------------------------+----------------------------------------------------+
+| ID                     | 02                                                 |
++========================+====================================================+
+| ``Threat``             | **Tampering with memory shared between an endpoint |
+|                        | and the SPMC.**                                    |
+|                        | A malicious endpoint may attempt tampering with its|
+|                        | RX/TX buffer contents while the SPMC is processing |
+|                        | it (TOCTOU).                                       |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF1, DF3, DF4, DF7                                 |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMC                                               |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | Shared memory, Information exchange                |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | NS-Endpoint, S-Endpoint                            |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Tampering                                          |
++------------------------+------------------+-----------------+---------------+
+| ``Application``        |   ``Server``     |   ``Mobile``    |               |
++------------------------+------------------+-----------------+---------------+
+| ``Impact``             | High (4)         | High (4)        |               |
++------------------------+------------------+-----------------+---------------+
+| ``Likelihood``         | High (4)         | High (4)        |               |
++------------------------+------------------+-----------------+---------------+
+| ``Total Risk Rating``  | High (16)        | High (16)       |               |
++------------------------+------------------+-----------------+---------------+
+| ``Mitigations``        | In context of FF-A v1.0 this is the case of sharing|
+|                        | the RX/TX buffer pair and usage in the             |
+|                        | PARTITION_INFO_GET or mem sharing primitives.      |
+|                        | The SPMC must copy the contents of the TX buffer   |
+|                        | to an internal temporary buffer before processing  |
+|                        | its contents. The SPMC must implement hardened     |
+|                        | input validation on data transmitted through the TX|
+|                        | buffer by an untrusted endpoint.                   |
+|                        | The TF-A SPMC mitigates this threat by enforcing   |
+|                        | checks on data transmitted through RX/TX buffers.  |
++------------------------+----------------------------------------------------+
+
++------------------------+----------------------------------------------------+
+| ID                     | 03                                                 |
++========================+====================================================+
+| ``Threat``             | **An endpoint may tamper with its own state or the |
+|                        | state of another endpoint.**                       |
+|                        | A malicious endpoint may attempt violating:        |
+|                        | - its own or another SP state by using an unusual  |
+|                        | combination (or out-of-order) FF-A function        |
+|                        | invocations.                                       |
+|                        | This can also be an endpoint emitting              |
+|                        | FF-A function invocations to another endpoint while|
+|                        | the latter in not in a state to receive it (e.g. a |
+|                        | SP sends a direct request to the normal world early|
+|                        | while the normal world is not booted yet).         |
+|                        | - the SPMC state itself by employing unexpected    |
+|                        | transitions in FF-A memory sharing, direct requests|
+|                        | and responses, or handling of interrupts.          |
+|                        | This can be led by random stimuli injection or     |
+|                        | fuzzing.                                           |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF1, DF2, DF3, DF4                                 |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMD, SPMC                                         |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | SP state, SPMC state                               |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | NS-Endpoint, S-Endpoint                            |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Tampering                                          |
++------------------------+------------------+-----------------+---------------+
+| ``Application``        |   ``Server``     |   ``Mobile``    |               |
++------------------------+------------------+-----------------+---------------+
+| ``Impact``             | High (4)         | High (4)        |               |
++------------------------+------------------+-----------------+---------------+
+| ``Likelihood``         | Medium (3)       | Medium (3)      |               |
++------------------------+------------------+-----------------+---------------+
+| ``Total Risk Rating``  | High (12)        | High (12)       |               |
++------------------------+------------------+-----------------+---------------+
+| ``Mitigations``        | The SPMC may be vulnerable to invalid state        |
+|                        | transitions for itself or while handling an SP     |
+|                        | state. The FF-A v1.1 specification provides a      |
+|                        | guidance on those state transitions (run-time      |
+|                        | model). The TF-A SPMC will be hardened in future   |
+|                        | releases to follow this guidance.                  |
+|                        | Additionally The TF-A SPMC mitigates the threat by |
+|                        | runs of the Arm `FF-A ACS`_ compliance test suite. |
++------------------------+----------------------------------------------------+
+
++------------------------+----------------------------------------------------+
+| ID                     | 04                                                 |
++========================+====================================================+
+| ``Threat``             | *An attacker may attempt injecting errors by the   |
+|                        | use of external DRAM stress techniques.**          |
+|                        | A malicious agent may attempt toggling an SP       |
+|                        | Stage-2 MMU descriptor bit within the page tables  |
+|                        | that the SPMC manages. This can happen in Rowhammer|
+|                        | types of attack.                                   |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF7                                                |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMC                                               |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | SP or SPMC state                                   |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | Hardware attack                                    |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Tampering                                          |
++------------------------+------------------+---------------+-----------------+
+| ``Application``        |   ``Server``     |  ``Mobile``   |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Impact``             | High (4)         | High (4)	    |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Likelihood``         | Low (2)          | Medium (3)    |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Total Risk Rating``  | Medium (8)       | High (12)	    |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Mitigations``        | The TF-A SPMC does not provide mitigations to this |
+|                        | type of attack. It can be addressed by the use of  |
+|                        | dedicated HW circuity or hardening at the chipset  |
+|                        | or platform level left to the integrator.          |
++------------------------+----------------------------------------------------+
+
++------------------------+----------------------------------------------------+
+| ID                     | 05                                                 |
++========================+====================================================+
+| ``Threat``             | **Protection of the SPMC from a DMA capable device |
+|                        | upstream to an SMMU.**                             |
+|                        | A device may attempt to tamper with the internal   |
+|                        | SPMC code/data sections.                           |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF5                                                |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMC                                               |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | SPMC or SP state                                   |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | NS-Endpoint, S-Endpoint                            |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Tampering, Elevation of privileges                 |
++------------------------+------------------+---------------+-----------------+
+| ``Application``        |   ``Server``     |  ``Mobile``   |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Impact``             | High (4)         | High (4)      |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Likelihood``         | Medium (3)       | Medium (3)    |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Total Risk Rating``  | High (12)        | High (12)     |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Mitigations``        | A platform may prefer assigning boot time,         |
+|                        | statically alocated memory regions through the SMMU|
+|                        | configuration and page tables. The FF-A v1.1       |
+|                        | specification provisions this capability through   |
+|                        | static DMA isolation.                              |
+|                        | The TF-A SPMC does not mitigate this threat.       |
+|                        | It will adopt the static DMA isolation approach in |
+|                        | a future release.                                  |
++------------------------+----------------------------------------------------+
+
++------------------------+----------------------------------------------------+
+| ID                     | 06                                                 |
++========================+====================================================+
+| ``Threat``             | **Replay fragments of past communication between   |
+|                        | endpoints.**                                       |
+|                        | A malicious endpoint may replay a message exchange |
+|                        | that occured between two legitimate endpoint as    |
+|                        | a matter of triggering a malfunction or extracting |
+|                        | secrets from the receiving endpoint. In particular |
+|                        | the memory sharing operation with fragmented       |
+|                        | messages between an endpoint and the SPMC may be   |
+|                        | replayed by a malicious agent as a matter of       |
+|                        | getting access or gaining permissions to a memory  |
+|                        | region which does not belong to this agent.        |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF2, DF3                                           |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMC                                               |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | Information exchange                               |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | NS-Endpoint, S-Endpoint                            |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Repdudiation                                       |
++------------------------+------------------+---------------+-----------------+
+| ``Application``        |   ``Server``     |  ``Mobile``   |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Impact``             | Medium (3)       | Medium (3)    |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Likelihood``         | High (4)         | High (4)	    |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Total Risk Rating``  | High (12)        | High (12)     |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Mitigations``        | The TF-A SPMC does not mitigate this threat.       |
++------------------------+----------------------------------------------------+
+
++------------------------+----------------------------------------------------+
+| ID                     | 07                                                 |
++========================+====================================================+
+| ``Threat``             | **A malicious endpoint may attempt to extract data |
+|                        | or state information by the use of invalid or      |
+|                        | incorrect input arguments.**                       |
+|                        | Lack of input parameter validation or side effects |
+|                        | of maliciously forged input parameters might affect|
+|                        | the SPMC.                                          |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF1, DF2, DF3, DF4                                 |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMD, SPMC                                         |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | SP secrets, SPMC secrets, SP state, SPMC state     |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | NS-Endpoint, S-Endpoint                            |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Information discolure                              |
++------------------------+------------------+---------------+-----------------+
+| ``Application``        |   ``Server``     |  ``Mobile``   |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Impact``             | High (4)         | High (4)      |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Likelihood``         | Medium (3)       | Medium (3)    |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Total Risk Rating``  | High (12)        | High (12)     |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Mitigations``        | Secure Partitions must follow security standards   |
+|                        | and best practises as a way to mitigate the risk   |
+|                        | of common vulnerabilities to be exploited.         |
+|                        | The use of software (canaries) or hardware         |
+|                        | hardening techniques (XN, WXN, BTI, pointer        |
+|                        | authentication, MTE) helps detecting and stopping  |
+|                        | an exploitation early.                             |
+|                        | The TF-A SPMC mitigates this threat by implementing|
+|                        | stack protector, pointer authentication, BTI, XN,  |
+|                        | WXN, security hardening techniques.                |
++------------------------+----------------------------------------------------+
+
++------------------------+----------------------------------------------------+
+| ID                     | 08                                                 |
++========================+====================================================+
+| ``Threat``             | **A malicious endpoint may forge a direct message  |
+|                        | request such that it reveals the internal state of |
+|                        | another endpoint through the direct message        |
+|                        | response.**                                        |
+|                        | The secure partition or SPMC replies to a partition|
+|                        | message by a direct message response with          |
+|                        | information which may reveal its internal state    |
+|                        | (.e.g. partition message response outside of       |
+|                        | allowed bounds).                                   |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF1, DF2, DF3, DF4                                 |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMC                                               |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | SPMC or SP state                                   |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | NS-Endpoint, S-Endpoint                            |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Information discolure                              |
++------------------------+------------------+---------------+-----------------+
+| ``Application``        |   ``Server``     |  ``Mobile``   |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Impact``             | Medium (3)       | Medium (3)    |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Likelihood``         | Low (2)          | Low (2)	    |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Total Risk Rating``  | Medium (6)       | Medium (6)    |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Mitigations``        | For the specific case of direct requests targetting|
+|                        | the SPMC, the latter is hardened to prevent        |
+|                        | its internal state or the state of an SP to be     |
+|                        | revealed through a direct message response.        |
+|                        | Further FF-A v1.1 guidance about run time models   |
+|                        | and partition states will be implemented in future |
+|                        | TF-A SPMC releases.                                |
++------------------------+----------------------------------------------------+
+
++------------------------+----------------------------------------------------+
+| ID                     | 09                                                 |
++========================+====================================================+
+| ``Threat``             | **Probing the FF-A communication between           |
+|                        | endpoints.**                                       |
+|                        | SPMC and SPs are typically loaded to external      |
+|                        | memory (protected by a TrustZone memory            |
+|                        | controller). A malicious agent may use non invasive|
+|                        | methods to probe the external memory bus and       |
+|                        | extract the traffic between an SP and the SPMC or  |
+|                        | among SPs when shared buffers are held in external |
+|                        | memory.                                            |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF7                                                |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMC                                               |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | SP/SPMC state, SP/SPMC secrets                     |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | Hardware attack                                    |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Information disclosure                             |
++------------------------+------------------+-----------------+---------------+
+| ``Application``        |   ``Server``     |   ``Mobile``    |               |
++------------------------+------------------+-----------------+---------------+
+| ``Impact``             | Medium (3)       | Medium (3)      |               |
++------------------------+------------------+-----------------+---------------+
+| ``Likelihood``         | Low (2)          | Medium (3)      |               |
++------------------------+------------------+-----------------+---------------+
+| ``Total Risk Rating``  | Medium (6)       | Medium (9)      |               |
++------------------------+------------------+-----------------+---------------+
+| ``Mitigations``        | It is expected the platform or chipset provides    |
+|                        | guarantees in protecting the DRAM contents.        |
+|                        | The TF-A SPMC does not mitigate this class of      |
+|                        | attack and this is left to the integrator.         |
++------------------------+----------------------------------------------------+
+
++------------------------+----------------------------------------------------+
+| ID                     | 10                                                 |
++========================+====================================================+
+| ``Threat``             | **A malicious agent may attempt revealing the SPMC |
+|                        | state or secrets by the use of software-based cache|
+|                        | side-channel attack techniques.**                  |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF7                                                |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMC                                               |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | SP or SPMC state                                   |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | NS-Endpoint, S-Endpoint                            |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Information disclosure                             |
++------------------------+------------------+-----------------+---------------+
+| ``Application``        |   ``Server``     |   ``Mobile``    |               |
++------------------------+------------------+-----------------+---------------+
+| ``Impact``             | Medium (3)       | Medium (3)      |               |
++------------------------+------------------+-----------------+---------------+
+| ``Likelihood``         | Low (2)          | Low (2)         |               |
++------------------------+------------------+-----------------+---------------+
+| ``Total Risk Rating``  | Medium (6)       | Medium (6)      |               |
++------------------------+------------------+-----------------+---------------+
+| ``Mitigations``        | From an integration perspective it is assumed      |
+|                        | platforms consuming the SPMC component at S-EL2    |
+|                        | (hence implementing the Armv8.4 FEAT_SEL2          |
+|                        | architecture extension) implement mitigations to   |
+|                        | Spectre, Meltdown or other cache timing            |
+|                        | side-channel type of attacks.                      |
+|                        | The TF-A SPMC implements one mitigation (barrier   |
+|                        | preventing speculation past exeception returns).   |
+|                        | The SPMC may be hardened further with SW           |
+|                        | mitigations (e.g. speculation barriers) for the    |
+|                        | cases not covered in HW. Usage of hardened         |
+|                        | compilers and appropriate options, code inspection |
+|                        | are recommended ways to mitigate Spectre types of  |
+|                        | attacks. For non-hardened cores, the usage of      |
+|                        | techniques such a kernel page table isolation can  |
+|                        | help mitigating Meltdown type of attacks.          |
++------------------------+----------------------------------------------------+
+
++------------------------+----------------------------------------------------+
+| ID                     | 11                                                 |
++========================+====================================================+
+| ``Threat``             | **A malicious endpoint may attempt flooding the    |
+|                        | SPMC with requests targetting a service within an  |
+|                        | endpoint such that it denies another endpoint to   |
+|                        | access this service.**                             |
+|                        | Similarly, the malicious endpoint may target a     |
+|                        | a service within an endpoint such that the latter  |
+|                        | is unable to request services from another         |
+|                        | endpoint.                                          |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF1, DF2, DF3, DF4                                 |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMC                                               |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | SPMC state                                         |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | NS-Endpoint, S-Endpoint                            |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Denial of service                                  |
++------------------------+------------------+-----------------+---------------+
+| ``Application``        |   ``Server``     |   ``Mobile``    |               |
++------------------------+------------------+-----------------+---------------+
+| ``Impact``             | Medium (3)       | Medium (3)      |               |
++------------------------+------------------+-----------------+---------------+
+| ``Likelihood``         | Medium (3)       | Medium (3)      |               |
++------------------------+------------------+-----------------+---------------+
+| ``Total Risk Rating``  | Medium (9)       | Medium (9)      |               |
++------------------------+------------------+-----------------+---------------+
+| ``Mitigations``        | The TF-A SPMC does not mitigate this threat.       |
+|                        | Bounding the time for operations to complete can   |
+|                        | be achieved by the usage of a trusted watchdog.    |
+|                        | Other quality of service monitoring can be achieved|
+|                        | in the SPMC such as counting a number of operations|
+|                        | in a limited timeframe.                            |
++------------------------+----------------------------------------------------+
+
+--------------
+
+*Copyright (c) 2021, Arm Limited. All rights reserved.*
+
+.. _Arm Firmware Framework for Arm A-profile: https://developer.arm.com/docs/den0077/latest
+.. _Secure Partition Manager: ../components/secure-partition-manager.html
+.. _Generic TF-A threat model: ./threat_model.html#threat-analysis
+.. _FF-A ACS: https://github.com/ARM-software/ff-a-acs/releases
diff --git a/drivers/arm/ethosn/ethosn_smc.c b/drivers/arm/ethosn/ethosn_smc.c
index 299d07c..60364cd 100644
--- a/drivers/arm/ethosn/ethosn_smc.c
+++ b/drivers/arm/ethosn/ethosn_smc.c
@@ -14,11 +14,10 @@
 #include <lib/mmio.h>
 #include <plat/arm/common/fconf_ethosn_getter.h>
 
-/* Arm Ethos-N NPU (NPU) status */
-#define ETHOSN_STATUS \
-	FCONF_GET_PROPERTY(hw_config, ethosn_config, status)
-
-/* Number of NPU cores available */
+/*
+ * Number of Arm Ethos-N NPU (NPU) cores available for a
+ * particular parent device
+ */
 #define ETHOSN_NUM_CORES \
 	FCONF_GET_PROPERTY(hw_config, ethosn_config, num_cores)
 
@@ -51,6 +50,17 @@
 #define SEC_SYSCTRL0_SOFT_RESET		U(3U << 29)
 #define SEC_SYSCTRL0_HARD_RESET		U(1U << 31)
 
+static bool ethosn_is_core_addr_valid(uintptr_t core_addr)
+{
+	for (uint32_t core_idx = 0U; core_idx < ETHOSN_NUM_CORES; core_idx++) {
+		if (ETHOSN_CORE_ADDR(core_idx) == core_addr) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
 static void ethosn_delegate_to_ns(uintptr_t core_addr)
 {
 	mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SECCTLR_REG),
@@ -66,9 +76,9 @@
 			SEC_DEL_ADDR_EXT_VAL);
 }
 
-static int ethosn_is_sec(void)
+static int ethosn_is_sec(uintptr_t core_addr)
 {
-	if ((mmio_read_32(ETHOSN_CORE_SEC_REG(ETHOSN_CORE_ADDR(0), SEC_DEL_REG))
+	if ((mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG))
 		& SEC_DEL_EXCC_MASK) != 0U) {
 		return 0;
 	}
@@ -101,7 +111,7 @@
 }
 
 uintptr_t ethosn_smc_handler(uint32_t smc_fid,
-			     u_register_t core_idx,
+			     u_register_t core_addr,
 			     u_register_t x2,
 			     u_register_t x3,
 			     u_register_t x4,
@@ -109,8 +119,8 @@
 			     void *handle,
 			     u_register_t flags)
 {
-	uintptr_t core_addr;
 	int hard_reset = 0;
+	const uint32_t fid = smc_fid & FUNCID_NUM_MASK;
 
 	/* Only SiP fast calls are expected */
 	if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) ||
@@ -120,7 +130,7 @@
 
 	/* Truncate parameters to 32-bits for SMC32 */
 	if (GET_SMC_CC(smc_fid) == SMC_32) {
-		core_idx &= 0xFFFFFFFF;
+		core_addr &= 0xFFFFFFFF;
 		x2 &= 0xFFFFFFFF;
 		x3 &= 0xFFFFFFFF;
 		x4 &= 0xFFFFFFFF;
@@ -130,33 +140,29 @@
 		SMC_RET1(handle, SMC_UNK);
 	}
 
-	if (ETHOSN_STATUS == ETHOSN_STATUS_DISABLED) {
-		WARN("ETHOSN: Arm Ethos-N NPU not available\n");
-		SMC_RET1(handle, ETHOSN_NOT_SUPPORTED);
-	}
-
-	switch (smc_fid & FUNCID_NUM_MASK) {
+	/* Commands that do not require a valid core address */
+	switch (fid) {
 	case ETHOSN_FNUM_VERSION:
 		SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR);
+	}
+
+	if (!ethosn_is_core_addr_valid(core_addr)) {
+		WARN("ETHOSN: Unknown core address given to SMC call.\n");
+		SMC_RET1(handle, ETHOSN_UNKNOWN_CORE_ADDRESS);
+	}
+
+	/* Commands that require a valid addr */
+	switch (fid) {
 	case ETHOSN_FNUM_IS_SEC:
-		SMC_RET1(handle, ethosn_is_sec());
+		SMC_RET1(handle, ethosn_is_sec(core_addr));
 	case ETHOSN_FNUM_HARD_RESET:
 		hard_reset = 1;
 		/* Fallthrough */
 	case ETHOSN_FNUM_SOFT_RESET:
-		if (core_idx >= ETHOSN_NUM_CORES) {
-			WARN("ETHOSN: core index out of range\n");
-			SMC_RET1(handle, ETHOSN_CORE_IDX_OUT_OF_RANGE);
-		}
-
-		core_addr = ETHOSN_CORE_ADDR(core_idx);
-
 		if (!ethosn_reset(core_addr, hard_reset)) {
 			SMC_RET1(handle, ETHOSN_FAILURE);
 		}
-
 		ethosn_delegate_to_ns(core_addr);
-
 		SMC_RET1(handle, ETHOSN_SUCCESS);
 	default:
 		SMC_RET1(handle, SMC_UNK);
diff --git a/drivers/arm/gic/v3/gic-x00.c b/drivers/arm/gic/v3/gic-x00.c
index 6e106ba..aaef485 100644
--- a/drivers/arm/gic/v3/gic-x00.c
+++ b/drivers/arm/gic/v3/gic-x00.c
@@ -16,15 +16,13 @@
 #include <assert.h>
 
 #include <arch_helpers.h>
+#include <drivers/arm/arm_gicv3_common.h>
 #include <drivers/arm/gicv3.h>
 
 #include "gicv3_private.h"
 
 /* GIC-600 specific register offsets */
 #define GICR_PWRR			0x24U
-#define IIDR_MODEL_ARM_GIC_600		U(0x0200043b)
-#define IIDR_MODEL_ARM_GIC_600AE	U(0x0300043b)
-#define IIDR_MODEL_ARM_GIC_CLAYTON	U(0x0400043b)
 
 /* GICR_PWRR fields */
 #define PWRR_RDPD_SHIFT			0
@@ -46,7 +44,7 @@
 
 #if GICV3_SUPPORT_GIC600
 
-/* GIC-600/Clayton specific accessor functions */
+/* GIC-600/700 specific accessor functions */
 static void gicr_write_pwrr(uintptr_t base, unsigned int val)
 {
 	mmio_write_32(base + GICR_PWRR, val);
@@ -123,12 +121,12 @@
 	uint32_t reg = mmio_read_32(gicr_base + GICR_IIDR);
 
 	/*
-	 * The Arm GIC-600 and GIC-Clayton models have their redistributors
+	 * The Arm GIC-600 and GIC-700 models have their redistributors
 	 * powered down at reset.
 	 */
 	return (((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) ||
 		((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600AE) ||
-		((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_CLAYTON));
+		((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_700));
 }
 
 #endif	/* GICV3_SUPPORT_GIC600 */
diff --git a/drivers/arm/gic/v3/gic600_multichip.c b/drivers/arm/gic/v3/gic600_multichip.c
index ca7c43b..fd3d8c2 100644
--- a/drivers/arm/gic/v3/gic600_multichip.c
+++ b/drivers/arm/gic/v3/gic600_multichip.c
@@ -11,6 +11,7 @@
 #include <assert.h>
 
 #include <common/debug.h>
+#include <drivers/arm/arm_gicv3_common.h>
 #include <drivers/arm/gic600_multichip.h>
 #include <drivers/arm/gicv3.h>
 
@@ -73,6 +74,7 @@
 				unsigned int spi_id_max)
 {
 	unsigned int spi_block_min, spi_blocks;
+	unsigned int gicd_iidr_val = gicd_read_iidr(base);
 	uint64_t chipr_n_val;
 
 	/*
@@ -100,8 +102,24 @@
 	spi_block_min = SPI_BLOCK_MIN_VALUE(spi_id_min);
 	spi_blocks    = SPI_BLOCKS_VALUE(spi_id_min, spi_id_max);
 
-	chipr_n_val = (GICD_CHIPR_VALUE(chip_addr, spi_block_min, spi_blocks)) |
-		GICD_CHIPRx_SOCKET_STATE;
+	switch ((gicd_iidr_val & IIDR_MODEL_MASK)) {
+	case IIDR_MODEL_ARM_GIC_600:
+		chipr_n_val = GICD_CHIPR_VALUE_GIC_600(chip_addr,
+						       spi_block_min,
+						       spi_blocks);
+		break;
+	case IIDR_MODEL_ARM_GIC_700:
+		chipr_n_val = GICD_CHIPR_VALUE_GIC_700(chip_addr,
+						       spi_block_min,
+						       spi_blocks);
+		break;
+	default:
+		ERROR("Unsupported GIC model 0x%x for multichip setup.\n",
+		      gicd_iidr_val);
+		panic();
+		break;
+	}
+	chipr_n_val |= GICD_CHIPRx_SOCKET_STATE;
 
 	/*
 	 * Wait for DCHIPR.PUP to be zero before commencing writes to
diff --git a/drivers/arm/gic/v3/gic600_multichip_private.h b/drivers/arm/gic/v3/gic600_multichip_private.h
index fe4134c..5d1ff6a 100644
--- a/drivers/arm/gic/v3/gic600_multichip_private.h
+++ b/drivers/arm/gic/v3/gic600_multichip_private.h
@@ -27,17 +27,11 @@
 #define GICD_CHIPSR_RTS_SHIFT		4
 #define GICD_DCHIPR_RT_OWNER_SHIFT	4
 
-/*
- * If GIC v4 extension is enabled, then use SPI macros specific to GIC-Clayton.
- * Other shifts and mask remains same between GIC-600 and GIC-Clayton.
- */
-#if GIC_ENABLE_V4_EXTN
-#define GICD_CHIPRx_SPI_BLOCK_MIN_SHIFT	9
-#define GICD_CHIPRx_SPI_BLOCKS_SHIFT	3
-#else
-#define GICD_CHIPRx_SPI_BLOCK_MIN_SHIFT	10
-#define GICD_CHIPRx_SPI_BLOCKS_SHIFT	5
-#endif
+/* Other shifts and masks remain the same between GIC-600 and GIC-700. */
+#define GIC_700_SPI_BLOCK_MIN_SHIFT	9
+#define GIC_700_SPI_BLOCKS_SHIFT	3
+#define GIC_600_SPI_BLOCK_MIN_SHIFT	10
+#define GIC_600_SPI_BLOCKS_SHIFT	5
 
 #define GICD_CHIPSR_RTS_STATE_DISCONNECTED	U(0)
 #define GICD_CHIPSR_RTS_STATE_UPDATING		U(1)
@@ -59,10 +53,14 @@
 #define SPI_BLOCKS_VALUE(spi_id_min, spi_id_max) \
 			(((spi_id_max) - (spi_id_min) + 1) / \
 			GIC600_SPI_ID_MIN)
-#define GICD_CHIPR_VALUE(chip_addr, spi_block_min, spi_blocks) \
+#define GICD_CHIPR_VALUE_GIC_700(chip_addr, spi_block_min, spi_blocks) \
+			(((chip_addr) << GICD_CHIPRx_ADDR_SHIFT) | \
+			((spi_block_min) << GIC_700_SPI_BLOCK_MIN_SHIFT) | \
+			((spi_blocks) << GIC_700_SPI_BLOCKS_SHIFT))
+#define GICD_CHIPR_VALUE_GIC_600(chip_addr, spi_block_min, spi_blocks) \
 			(((chip_addr) << GICD_CHIPRx_ADDR_SHIFT) | \
-			((spi_block_min) << GICD_CHIPRx_SPI_BLOCK_MIN_SHIFT) | \
-			((spi_blocks) << GICD_CHIPRx_SPI_BLOCKS_SHIFT))
+			((spi_block_min) << GIC_600_SPI_BLOCK_MIN_SHIFT) | \
+			((spi_blocks) << GIC_600_SPI_BLOCKS_SHIFT))
 
 /*
  * Multichip data assertion macros
diff --git a/drivers/arm/gic/v3/gic600ae_fmu.c b/drivers/arm/gic/v3/gic600ae_fmu.c
new file mode 100644
index 0000000..13979fa
--- /dev/null
+++ b/drivers/arm/gic/v3/gic600ae_fmu.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Driver for GIC-600AE Fault Management Unit
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/gic600ae_fmu.h>
+#include <drivers/arm/gicv3.h>
+
+/* GIC-600 AE FMU specific register offsets */
+
+/* GIC-600 AE FMU specific macros */
+#define FMU_ERRIDR_NUM			U(44)
+#define FMU_ERRIDR_NUM_MASK		U(0xFFFF)
+
+/* Safety mechanisms for GICD block */
+static char *gicd_sm_info[] = {
+	"Reserved",
+	"GICD dual lockstep error",
+	"GICD AXI4 slave interface error",
+	"GICD-PPI AXI4-Stream interface error",
+	"GICD-ITS AXI4-Stream interface error",
+	"GICD-SPI-Collator AXI4-Stream interface error",
+	"GICD AXI4 master interface error",
+	"SPI RAM DED error",
+	"SGI RAM DED error",
+	"Reserved",
+	"LPI RAM DED error",
+	"GICD-remote-GICD AXI4-Stream interface error",
+	"GICD Q-Channel interface error",
+	"GICD P-Channel interface error",
+	"SPI RAM address decode error",
+	"SGI RAM address decode error",
+	"Reserved",
+	"LPI RAM address decode error",
+	"FMU dual lockstep error",
+	"FMU ping ACK error",
+	"FMU APB parity error",
+	"GICD-Wake AXI4-Stream interface error",
+	"GICD PageOffset or Chip ID error",
+	"MBIST REQ error",
+	"SPI RAM SEC error",
+	"SGI RAM SEC error",
+	"Reserved",
+	"LPI RAM SEC error",
+	"User custom SM0 error",
+	"User custom SM1 error",
+	"GICD-ITS Monolithic switch error",
+	"GICD-ITS Q-Channel interface error",
+	"GICD-ITS Monolithic interface error",
+	"GICD FMU ClkGate override"
+};
+
+/* Safety mechanisms for PPI block */
+static char *ppi_sm_info[] = {
+	"Reserved",
+	"PPI dual lockstep error",
+	"PPI-GICD AXI4-Stream interface error",
+	"PPI-CPU-IF AXI4-Stream interface error",
+	"PPI Q-Channel interface error",
+	"PPI RAM DED error",
+	"PPI RAM address decode error",
+	"PPI RAM SEC error",
+	"PPI User0 SM",
+	"PPI User1 SM",
+	"MBIST REQ error",
+	"PPI interrupt parity protection error",
+	"PPI FMU ClkGate override"
+};
+
+/* Safety mechanisms for ITS block */
+static char *its_sm_info[] = {
+	"Reserved",
+	"ITS dual lockstep error",
+	"ITS-GICD AXI4-Stream interface error",
+	"ITS AXI4 slave interface error",
+	"ITS AXI4 master interface error",
+	"ITS Q-Channel interface error",
+	"ITS RAM DED error",
+	"ITS RAM address decode error",
+	"Bypass ACE switch error",
+	"ITS RAM SEC error",
+	"ITS User0 SM",
+	"ITS User1 SM",
+	"ITS-GICD Monolithic interface error",
+	"MBIST REQ error",
+	"ITS FMU ClkGate override"
+};
+
+/* Safety mechanisms for SPI Collator block */
+static char *spicol_sm_info[] = {
+	"Reserved",
+	"SPI Collator dual lockstep error",
+	"SPI-Collator-GICD AXI4-Stream interface error",
+	"SPI Collator Q-Channel interface error",
+	"SPI Collator Q-Channel clock error",
+	"SPI interrupt parity error"
+};
+
+/* Safety mechanisms for Wake Request block */
+static char *wkrqst_sm_info[] = {
+	"Reserved",
+	"Wake dual lockstep error",
+	"Wake-GICD AXI4-Stream interface error"
+};
+
+/*
+ * Initialization sequence for the FMU
+ *
+ * 1. enable error detection for error records that are passed in the blk_present_mask
+ * 2. enable MBIST REQ and FMU Clk Gate override safety mechanisms for error records
+ *    that are present on the platform
+ *
+ * The platforms are expected to pass `errctlr_ce_en` and `errctlr_ue_en`.
+ */
+void gic600_fmu_init(uint64_t base, uint64_t blk_present_mask,
+		     bool errctlr_ce_en, bool errctlr_ue_en)
+{
+	unsigned int num_blk = gic_fmu_read_erridr(base) & FMU_ERRIDR_NUM_MASK;
+	uint64_t errctlr;
+	uint32_t smen;
+
+	INFO("GIC600-AE FMU supports %d error records\n", num_blk);
+
+	assert(num_blk == FMU_ERRIDR_NUM);
+
+	/* sanitize block present mask */
+	blk_present_mask &= FMU_BLK_PRESENT_MASK;
+
+	/* Enable error detection for all error records */
+	for (unsigned int i = 0U; i < num_blk; i++) {
+
+		/* Skip next steps if the block is not present */
+		if ((blk_present_mask & BIT(i)) == 0U) {
+			continue;
+		}
+
+		/* Read the error record control register */
+		errctlr = gic_fmu_read_errctlr(base, i);
+
+		/* Enable error reporting and logging, if it is disabled */
+		if ((errctlr & FMU_ERRCTLR_ED_BIT) == 0U) {
+			errctlr |= FMU_ERRCTLR_ED_BIT;
+		}
+
+		/* Enable client provided ERRCTLR settings */
+		errctlr |= (errctlr_ce_en ? (FMU_ERRCTLR_CI_BIT | FMU_ERRCTLR_CE_EN_BIT) : 0);
+		errctlr |= (errctlr_ue_en ? FMU_ERRCTLR_UI_BIT : 0U);
+
+		gic_fmu_write_errctlr(base, i, errctlr);
+	}
+
+	/*
+	 * Enable MBIST REQ error and FMU CLK gate override safety mechanisms for
+	 * all blocks
+	 *
+	 * GICD, SMID 23 and SMID 33
+	 * PPI, SMID 10 and SMID 12
+	 * ITS, SMID 13 and SMID 14
+	 */
+	if ((blk_present_mask & BIT(FMU_BLK_GICD)) != 0U) {
+		smen = (GICD_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
+			(FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT);
+		gic_fmu_write_smen(base, smen);
+
+		smen = (GICD_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
+			(FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT);
+		gic_fmu_write_smen(base, smen);
+	}
+
+	for (unsigned int i = FMU_BLK_PPI0; i < FMU_BLK_PPI31; i++) {
+		if ((blk_present_mask & BIT(i)) != 0U) {
+			smen = (PPI_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
+				(i << FMU_SMEN_BLK_SHIFT);
+			gic_fmu_write_smen(base, smen);
+
+			smen = (PPI_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
+				(i << FMU_SMEN_BLK_SHIFT);
+			gic_fmu_write_smen(base, smen);
+		}
+	}
+
+	for (unsigned int i = FMU_BLK_ITS0; i < FMU_BLK_ITS7; i++) {
+		if ((blk_present_mask & BIT(i)) != 0U) {
+			smen = (ITS_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
+				(i << FMU_SMEN_BLK_SHIFT);
+			gic_fmu_write_smen(base, smen);
+
+			smen = (ITS_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
+				(i << FMU_SMEN_BLK_SHIFT);
+			gic_fmu_write_smen(base, smen);
+		}
+	}
+}
+
+/*
+ * This function enable the GICD background ping engine. The GICD sends ping
+ * messages to each remote GIC block, and expects a PING_ACK back within the
+ * specified timeout. Pings need to be enabled after programming the timeout
+ * value.
+ */
+void gic600_fmu_enable_ping(uint64_t base, uint64_t blk_present_mask,
+		unsigned int timeout_val, unsigned int interval_diff)
+{
+	/*
+	 * Populate the PING Mask to skip a specific block while generating
+	 * background ping messages and enable the ping mechanism.
+	 */
+	gic_fmu_write_pingmask(base, ~blk_present_mask);
+	gic_fmu_write_pingctlr(base, (interval_diff << FMU_PINGCTLR_INTDIFF_SHIFT) |
+		(timeout_val << FMU_PINGCTLR_TIMEOUTVAL_SHIFT) | FMU_PINGCTLR_EN_BIT);
+}
+
+/* Print the safety mechanism description for a given block */
+void gic600_fmu_print_sm_info(uint64_t base, unsigned int blk, unsigned int smid)
+{
+	if (blk == FMU_BLK_GICD && smid <= FMU_SMID_GICD_MAX) {
+		INFO("GICD, SMID %d: %s\n", smid, gicd_sm_info[smid]);
+	}
+
+	if (blk == FMU_BLK_SPICOL && smid <= FMU_SMID_SPICOL_MAX) {
+		INFO("SPI Collator, SMID %d: %s\n", smid, spicol_sm_info[smid]);
+	}
+
+	if (blk == FMU_BLK_WAKERQ && (smid <= FMU_SMID_WAKERQ_MAX)) {
+		INFO("Wake Request, SMID %d: %s\n", smid, wkrqst_sm_info[smid]);
+	}
+
+	if (((blk >= FMU_BLK_ITS0) && (blk <= FMU_BLK_ITS7)) && (smid <= FMU_SMID_ITS_MAX)) {
+		INFO("ITS, SMID %d: %s\n", smid, its_sm_info[smid]);
+	}
+
+	if (((blk >= FMU_BLK_PPI0) && (blk <= FMU_BLK_PPI31)) && (smid <= FMU_SMID_PPI_MAX)) {
+		INFO("PPI, SMID %d: %s\n", smid, ppi_sm_info[smid]);
+	}
+}
diff --git a/drivers/arm/gic/v3/gic600ae_fmu_helpers.c b/drivers/arm/gic/v3/gic600ae_fmu_helpers.c
new file mode 100644
index 0000000..84f7292
--- /dev/null
+++ b/drivers/arm/gic/v3/gic600ae_fmu_helpers.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <drivers/arm/gic600ae_fmu.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#define GICFMU_IDLE_TIMEOUT_US		U(2000000)
+
+/* Macro to write 32-bit FMU registers */
+#define GIC_FMU_WRITE_32(base, reg, val) \
+	do { \
+		/* \
+		 * This register receives the unlock key that is required for \
+		 * writes to FMU registers to be successful. \
+		 */ \
+		mmio_write_32(base + GICFMU_KEY, 0xBE); \
+		/* Perform the actual write */ \
+		mmio_write_32((base) + (reg), (val)); \
+	} while (false)
+
+/* Macro to write 64-bit FMU registers */
+#define GIC_FMU_WRITE_64(base, reg, n, val) \
+	do { \
+		/* \
+		 * This register receives the unlock key that is required for \
+		 * writes to FMU registers to be successful. \
+		 */ \
+		mmio_write_32(base + GICFMU_KEY, 0xBE); \
+		/* \
+		 * APB bus is 32-bit wide; so split the 64-bit write into \
+		 * two 32-bit writes \
+		 */ \
+		mmio_write_32((base) + reg##_LO + (n * 64), (val)); \
+		mmio_write_32((base) + reg##_HI + (n * 64), (val)); \
+	} while (false)
+
+/* Helper function to wait until FMU is ready to accept the next command */
+static void wait_until_fmu_is_idle(uintptr_t base)
+{
+	uint64_t timeout_ref = timeout_init_us(GICFMU_IDLE_TIMEOUT_US);
+	uint64_t status;
+
+	/* wait until status is 'busy' */
+	do {
+		status = (gic_fmu_read_status(base) & BIT(0));
+
+		if (timeout_elapsed(timeout_ref)) {
+			ERROR("GIC600 AE FMU is not responding\n");
+			panic();
+		}
+	} while (status == U(0));
+}
+
+#define GIC_FMU_WRITE_ON_IDLE_32(base, reg, val) \
+	do { \
+		/* Wait until FMU is ready */ \
+		wait_until_fmu_is_idle(base); \
+		/* Actual register write */ \
+		GIC_FMU_WRITE_32(base, reg, val); \
+		/* Wait until FMU is ready */ \
+		wait_until_fmu_is_idle(base); \
+	} while (false)
+
+#define GIC_FMU_WRITE_ON_IDLE_64(base, reg, n, val) \
+	do { \
+		/* Wait until FMU is ready */ \
+		wait_until_fmu_is_idle(base); \
+		/* Actual register write */ \
+		GIC_FMU_WRITE_64(base, reg, n, val); \
+		/* Wait until FMU is ready */ \
+		wait_until_fmu_is_idle(base); \
+	} while (false)
+
+/*******************************************************************************
+ * GIC FMU functions for accessing the Fault Management Unit registers
+ ******************************************************************************/
+
+/*
+ * Accessors to read the Error Record Feature Register bits corresponding
+ * to an error record 'n'
+ */
+uint64_t gic_fmu_read_errfr(uintptr_t base, unsigned int n)
+{
+	/*
+	 * APB bus is 32-bit wide; so split the 64-bit read into
+	 * two 32-bit reads
+	 */
+	uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRFR_LO + n * 64U);
+
+	reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRFR_HI + n * 64U) << 32);
+	return reg_val;
+}
+
+/*
+ * Accessors to read the Error Record Control Register bits corresponding
+ * to an error record 'n'
+ */
+uint64_t gic_fmu_read_errctlr(uintptr_t base, unsigned int n)
+{
+	/*
+	 * APB bus is 32-bit wide; so split the 64-bit read into
+	 * two 32-bit reads
+	 */
+	uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRCTLR_LO + n * 64U);
+
+	reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRCTLR_HI + n * 64U) << 32);
+	return reg_val;
+}
+
+/*
+ * Accessors to read the Error Record Primary Status Register bits
+ * corresponding to an error record 'n'
+ */
+uint64_t gic_fmu_read_errstatus(uintptr_t base, unsigned int n)
+{
+	/*
+	 * APB bus is 32-bit wide; so split the 64-bit read into
+	 * two 32-bit reads
+	 */
+	uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRSTATUS_LO + n * 64U);
+
+	reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRSTATUS_HI + n * 64U) << 32);
+	return reg_val;
+}
+
+/*
+ * Accessors to read the Error Group Status Register
+ */
+uint64_t gic_fmu_read_errgsr(uintptr_t base)
+{
+	/*
+	 * APB bus is 32-bit wide; so split the 64-bit read into
+	 * two 32-bit reads
+	 */
+	uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRGSR_LO);
+
+	reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRGSR_HI) << 32);
+	return reg_val;
+}
+
+/*
+ * Accessors to read the Ping Control Register
+ */
+uint32_t gic_fmu_read_pingctlr(uintptr_t base)
+{
+	return mmio_read_32(base + GICFMU_PINGCTLR);
+}
+
+/*
+ * Accessors to read the Ping Now Register
+ */
+uint32_t gic_fmu_read_pingnow(uintptr_t base)
+{
+	return mmio_read_32(base + GICFMU_PINGNOW);
+}
+
+/*
+ * Accessors to read the Ping Mask Register
+ */
+uint64_t gic_fmu_read_pingmask(uintptr_t base)
+{
+	/*
+	 * APB bus is 32-bit wide; so split the 64-bit read into
+	 * two 32-bit reads
+	 */
+	uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_PINGMASK_LO);
+
+	reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_PINGMASK_HI) << 32);
+	return reg_val;
+}
+
+/*
+ * Accessors to read the FMU Status Register
+ */
+uint32_t gic_fmu_read_status(uintptr_t base)
+{
+	return mmio_read_32(base + GICFMU_STATUS);
+}
+
+/*
+ * Accessors to read the Error Record ID Register
+ */
+uint32_t gic_fmu_read_erridr(uintptr_t base)
+{
+	return mmio_read_32(base + GICFMU_ERRIDR);
+}
+
+/*
+ * Accessors to write a 64 bit value to the Error Record Control Register
+ */
+void gic_fmu_write_errctlr(uintptr_t base, unsigned int n, uint64_t val)
+{
+	GIC_FMU_WRITE_64(base, GICFMU_ERRCTLR, n, val);
+}
+
+/*
+ * Accessors to write a 64 bit value to the Error Record Primary Status
+ * Register
+ */
+void gic_fmu_write_errstatus(uintptr_t base, unsigned int n, uint64_t val)
+{
+	/* Wait until FMU is ready before writing */
+	GIC_FMU_WRITE_ON_IDLE_64(base, GICFMU_ERRSTATUS, n, val);
+}
+
+/*
+ * Accessors to write a 32 bit value to the Ping Control Register
+ */
+void gic_fmu_write_pingctlr(uintptr_t base, uint32_t val)
+{
+	GIC_FMU_WRITE_32(base, GICFMU_PINGCTLR, val);
+}
+
+/*
+ * Accessors to write a 32 bit value to the Ping Now Register
+ */
+void gic_fmu_write_pingnow(uintptr_t base, uint32_t val)
+{
+	/* Wait until FMU is ready before writing */
+	GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_PINGNOW, val);
+}
+
+/*
+ * Accessors to write a 32 bit value to the Safety Mechanism Enable Register
+ */
+void gic_fmu_write_smen(uintptr_t base, uint32_t val)
+{
+	/* Wait until FMU is ready before writing */
+	GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_SMEN, val);
+}
+
+/*
+ * Accessors to write a 32 bit value to the Safety Mechanism Inject Error
+ * Register
+ */
+void gic_fmu_write_sminjerr(uintptr_t base, uint32_t val)
+{
+	/* Wait until FMU is ready before writing */
+	GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_SMINJERR, val);
+}
+
+/*
+ * Accessors to write a 64 bit value to the Ping Mask Register
+ */
+void gic_fmu_write_pingmask(uintptr_t base, uint64_t val)
+{
+	GIC_FMU_WRITE_64(base, GICFMU_PINGMASK, 0, val);
+}
diff --git a/drivers/arm/gic/v3/gicv3.mk b/drivers/arm/gic/v3/gicv3.mk
index a2fc16f..d7e3536 100644
--- a/drivers/arm/gic/v3/gicv3.mk
+++ b/drivers/arm/gic/v3/gicv3.mk
@@ -1,11 +1,13 @@
 #
 # Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
 # Default configuration values
 GICV3_SUPPORT_GIC600		?=	0
+GICV3_SUPPORT_GIC600AE_FMU	?=	0
 GICV3_IMPL_GIC600_MULTICHIP	?=	0
 GICV3_OVERRIDE_DISTIF_PWR_OPS	?=	0
 GIC_ENABLE_V4_EXTN		?=	0
@@ -16,6 +18,11 @@
 			drivers/arm/gic/v3/gicdv3_helpers.c	\
 			drivers/arm/gic/v3/gicrv3_helpers.c
 
+ifeq (${GICV3_SUPPORT_GIC600AE_FMU}, 1)
+GICV3_SOURCES	+=	drivers/arm/gic/v3/gic600ae_fmu.c	\
+			drivers/arm/gic/v3/gic600ae_fmu_helpers.c
+endif
+
 ifeq (${GICV3_OVERRIDE_DISTIF_PWR_OPS}, 0)
 GICV3_SOURCES	+=	drivers/arm/gic/v3/arm_gicv3_common.c
 endif
@@ -29,6 +36,10 @@
 $(eval $(call assert_boolean,GICV3_SUPPORT_GIC600))
 $(eval $(call add_define,GICV3_SUPPORT_GIC600))
 
+# Set GIC-600AE FMU support
+$(eval $(call assert_boolean,GICV3_SUPPORT_GIC600AE_FMU))
+$(eval $(call add_define,GICV3_SUPPORT_GIC600AE_FMU))
+
 # Set GICv4 extension
 $(eval $(call assert_boolean,GIC_ENABLE_V4_EXTN))
 $(eval $(call add_define,GIC_ENABLE_V4_EXTN))
diff --git a/drivers/arm/gic/v3/gicv3_helpers.c b/drivers/arm/gic/v3/gicv3_helpers.c
index a0f44e9..d752013 100644
--- a/drivers/arm/gic/v3/gicv3_helpers.c
+++ b/drivers/arm/gic/v3/gicv3_helpers.c
@@ -86,8 +86,7 @@
 		if (proc_num < rdistif_num) {
 			rdistif_base_addrs[proc_num] = rdistif_base;
 		}
-
-		rdistif_base += (1U << GICR_PCPUBASE_SHIFT);
+		rdistif_base += gicv3_redist_size(typer_val);
 	} while ((typer_val & TYPER_LAST_BIT) == 0U);
 }
 
@@ -383,11 +382,13 @@
 	uintptr_t rdistif_base = gicr_frame;
 	unsigned int count;
 
-	for (count = 1; count < PLATFORM_CORE_COUNT; count++) {
-		if ((gicr_read_typer(rdistif_base) & TYPER_LAST_BIT) != 0U) {
+	for (count = 1U; count < PLATFORM_CORE_COUNT; count++) {
+		uint64_t typer_val = gicr_read_typer(rdistif_base);
+
+		if ((typer_val & TYPER_LAST_BIT) != 0U) {
 			break;
 		}
-		rdistif_base += (1U << GICR_PCPUBASE_SHIFT);
+		rdistif_base += gicv3_redist_size(typer_val);
 	}
 
 	return count;
diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c
index 668416c..53a8fae 100644
--- a/drivers/arm/gic/v3/gicv3_main.c
+++ b/drivers/arm/gic/v3/gicv3_main.c
@@ -123,13 +123,7 @@
 	gic_version &= PIDR2_ARCH_REV_MASK;
 
 	/* Check GIC version */
-#if GIC_ENABLE_V4_EXTN
-	assert(gic_version == ARCH_REV_GICV4);
-
-	/* GICv4 supports Direct Virtual LPI injection */
-	assert((gicd_read_typer(plat_driver_data->gicd_base)
-					& TYPER_DVIS) != 0);
-#else
+#if !GIC_ENABLE_V4_EXTN
 	assert(gic_version == ARCH_REV_GICV3);
 #endif
 	/*
@@ -332,6 +326,8 @@
 	write_icc_igrpen1_el3(read_icc_igrpen1_el3() |
 				IGRPEN1_EL3_ENABLE_G1S_BIT);
 	isb();
+	/* Add DSB to ensure visibility of System register writes */
+	dsb();
 }
 
 /*******************************************************************************
@@ -363,6 +359,8 @@
 
 	/* Synchronise accesses to group enable registers */
 	isb();
+	/* Add DSB to ensure visibility of System register writes */
+	dsb();
 
 	/* Mark the connected core as asleep */
 	gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
@@ -1294,7 +1292,7 @@
 			gicr_frame_found = true;
 			break;
 		}
-		rdistif_base += (uintptr_t)(ULL(1) << GICR_PCPUBASE_SHIFT);
+		rdistif_base += gicv3_redist_size(typer_val);
 	} while ((typer_val & TYPER_LAST_BIT) == 0U);
 
 	if (!gicr_frame_found) {
diff --git a/drivers/arm/tzc/tzc400.c b/drivers/arm/tzc/tzc400.c
index 9fc1578..e4fc8c9 100644
--- a/drivers/arm/tzc/tzc400.c
+++ b/drivers/arm/tzc/tzc400.c
@@ -68,6 +68,7 @@
 DEFINE_TZC_COMMON_WRITE_REGION_TOP(400, 400)
 DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(400, 400)
 DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(400, 400)
+DEFINE_TZC_COMMON_UPDATE_FILTERS(400, 400)
 DEFINE_TZC_COMMON_CONFIGURE_REGION0(400)
 DEFINE_TZC_COMMON_CONFIGURE_REGION(400)
 
@@ -271,6 +272,15 @@
 						sec_attr, nsaid_permissions);
 }
 
+void tzc400_update_filters(unsigned int region, unsigned int filters)
+{
+	/* Do range checks on filters and regions. */
+	assert(((filters >> tzc400.num_filters) == 0U) &&
+	       (region < tzc400.num_regions));
+
+	_tzc400_update_filters(tzc400.base, region, tzc400.num_filters, filters);
+}
+
 void tzc400_enable_filters(void)
 {
 	unsigned int state;
@@ -281,6 +291,11 @@
 	for (filter = 0U; filter < tzc400.num_filters; filter++) {
 		state = _tzc400_get_gate_keeper(tzc400.base, filter);
 		if (state != 0U) {
+			/* Filter 0 is special and cannot be disabled.
+			 * So here we allow it being already enabled. */
+			if (filter == 0U) {
+				continue;
+			}
 			/*
 			 * The TZC filter is already configured. Changing the
 			 * programmer's view in an active system can cause
@@ -302,14 +317,17 @@
 void tzc400_disable_filters(void)
 {
 	unsigned int filter;
+	unsigned int state;
+	unsigned int start = 0U;
 
 	assert(tzc400.base != 0U);
 
-	/*
-	 * We don't do the same state check as above as the Gatekeepers are
-	 * disabled after reset.
-	 */
-	for (filter = 0; filter < tzc400.num_filters; filter++)
+	/* Filter 0 is special and cannot be disabled. */
+	state = _tzc400_get_gate_keeper(tzc400.base, 0);
+	if (state != 0U) {
+		start++;
+	}
+	for (filter = start; filter < tzc400.num_filters; filter++)
 		_tzc400_set_gate_keeper(tzc400.base, filter, 0);
 }
 
diff --git a/drivers/arm/tzc/tzc_common_private.h b/drivers/arm/tzc/tzc_common_private.h
index 1d99077..2090944 100644
--- a/drivers/arm/tzc/tzc_common_private.h
+++ b/drivers/arm/tzc/tzc_common_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -90,6 +90,27 @@
 	}
 
 /*
+ * It is used to modify the filters status for a defined region.
+ */
+#define DEFINE_TZC_COMMON_UPDATE_FILTERS(fn_name, macro_name)		\
+	static inline void _tzc##fn_name##_update_filters(		\
+						uintptr_t base,		\
+						unsigned int region_no,	\
+						unsigned int nbfilters, \
+						unsigned int filters)	\
+	{								\
+		uint32_t filters_mask = GENMASK(nbfilters - 1U, 0);	\
+									\
+		mmio_clrsetbits_32(base +				\
+			TZC_REGION_OFFSET(				\
+				TZC_##macro_name##_REGION_SIZE,		\
+				region_no) +				\
+			TZC_##macro_name##_REGION_ATTR_0_OFFSET,	\
+			filters_mask << TZC_REGION_ATTR_F_EN_SHIFT,	\
+			filters << TZC_REGION_ATTR_F_EN_SHIFT);		\
+	}
+
+/*
  * It is used to program region 0 ATTRIBUTES and ACCESS register.
  */
 #define DEFINE_TZC_COMMON_CONFIGURE_REGION0(fn_name)			\
diff --git a/drivers/auth/auth_mod.c b/drivers/auth/auth_mod.c
index c7f84af..917ee4a 100644
--- a/drivers/auth/auth_mod.c
+++ b/drivers/auth/auth_mod.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,6 +16,7 @@
 #include <drivers/auth/auth_mod.h>
 #include <drivers/auth/crypto_mod.h>
 #include <drivers/auth/img_parser_mod.h>
+#include <drivers/fwu/fwu.h>
 #include <lib/fconf/fconf_tbbr_getter.h>
 #include <plat/common/platform.h>
 
@@ -242,6 +243,7 @@
 	unsigned int data_len, len, i;
 	unsigned int plat_nv_ctr;
 	int rc = 0;
+	bool is_trial_run = false;
 
 	/* Get the counter value from current image. The AM expects the IPM
 	 * to return the counter value as a DER encoded integer */
@@ -284,7 +286,10 @@
 		/* Invalid NV-counter */
 		return 1;
 	} else if (*cert_nv_ctr > plat_nv_ctr) {
-		*need_nv_ctr_upgrade = true;
+#if PSA_FWU_SUPPORT && IMAGE_BL2
+		is_trial_run = fwu_is_trial_run_state();
+#endif /* PSA_FWU_SUPPORT && IMAGE_BL2 */
+		*need_nv_ctr_upgrade = !is_trial_run;
 	}
 
 	return 0;
diff --git a/drivers/auth/tbbr/tbbr_cot_bl1_r64.c b/drivers/auth/tbbr/tbbr_cot_bl1_r64.c
new file mode 100644
index 0000000..e8e017c
--- /dev/null
+++ b/drivers/auth/tbbr/tbbr_cot_bl1_r64.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <drivers/auth/auth_mod.h>
+#include <drivers/auth/mbedtls/mbedtls_config.h>
+#include <drivers/auth/tbbr_cot_common.h>
+
+#if USE_TBBR_DEFS
+#include <tools_share/tbbr_oid.h>
+#else
+#include <platform_oid.h>
+#endif
+#include <platform_def.h>
+
+
+static unsigned char trusted_world_pk_buf[PK_DER_LEN];
+static unsigned char non_trusted_world_pk_buf[PK_DER_LEN];
+static unsigned char content_pk_buf[PK_DER_LEN];
+static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN];
+
+static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID);
+static auth_param_type_desc_t trusted_world_pk = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_PUB_KEY, TRUSTED_WORLD_PK_OID);
+static auth_param_type_desc_t non_trusted_world_pk = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_PUB_KEY, NON_TRUSTED_WORLD_PK_OID);
+static auth_param_type_desc_t nt_fw_content_pk = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_PUB_KEY, NON_TRUSTED_FW_CONTENT_CERT_PK_OID);
+static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID);
+static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID);
+/*
+ * Trusted key certificate
+ */
+static const auth_img_desc_t trusted_key_cert = {
+	.img_id = TRUSTED_KEY_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = NULL,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &subject_pk,
+				.sig = &sig,
+				.alg = &sig_alg,
+				.data = &raw_data
+			}
+		},
+		[1] = {
+			.type = AUTH_METHOD_NV_CTR,
+			.param.nv_ctr = {
+				.cert_nv_ctr = &trusted_nv_ctr,
+				.plat_nv_ctr = &trusted_nv_ctr
+			}
+		}
+	},
+	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &trusted_world_pk,
+			.data = {
+				.ptr = (void *)trusted_world_pk_buf,
+				.len = (unsigned int)PK_DER_LEN
+			}
+		},
+		[1] = {
+			.type_desc = &non_trusted_world_pk,
+			.data = {
+				.ptr = (void *)non_trusted_world_pk_buf,
+				.len = (unsigned int)PK_DER_LEN
+			}
+		}
+	}
+};
+/*
+ * Non-Trusted Firmware
+ */
+static const auth_img_desc_t non_trusted_fw_key_cert = {
+	.img_id = NON_TRUSTED_FW_KEY_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = &trusted_key_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &non_trusted_world_pk,
+				.sig = &sig,
+				.alg = &sig_alg,
+				.data = &raw_data
+			}
+		},
+		[1] = {
+			.type = AUTH_METHOD_NV_CTR,
+			.param.nv_ctr = {
+				.cert_nv_ctr = &non_trusted_nv_ctr,
+				.plat_nv_ctr = &non_trusted_nv_ctr
+			}
+		}
+	},
+	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &nt_fw_content_pk,
+			.data = {
+				.ptr = (void *)content_pk_buf,
+				.len = (unsigned int)PK_DER_LEN
+			}
+		}
+	}
+};
+static const auth_img_desc_t non_trusted_fw_content_cert = {
+	.img_id = NON_TRUSTED_FW_CONTENT_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = &non_trusted_fw_key_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &nt_fw_content_pk,
+				.sig = &sig,
+				.alg = &sig_alg,
+				.data = &raw_data
+			}
+		},
+		[1] = {
+			.type = AUTH_METHOD_NV_CTR,
+			.param.nv_ctr = {
+				.cert_nv_ctr = &non_trusted_nv_ctr,
+				.plat_nv_ctr = &non_trusted_nv_ctr
+			}
+		}
+	},
+	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &nt_world_bl_hash,
+			.data = {
+				.ptr = (void *)nt_world_bl_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[1] = {
+			.type_desc = &nt_fw_config_hash,
+			.data = {
+				.ptr = (void *)nt_fw_config_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		}
+	}
+};
+static const auth_img_desc_t bl33_image = {
+	.img_id = BL33_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &non_trusted_fw_content_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &nt_world_bl_hash
+			}
+		}
+	}
+};
+
+static const auth_img_desc_t * const cot_desc[] = {
+	[TRUSTED_KEY_CERT_ID]			=	&trusted_key_cert,
+	[NON_TRUSTED_FW_KEY_CERT_ID]		=	&non_trusted_fw_key_cert,
+	[NON_TRUSTED_FW_CONTENT_CERT_ID]	=	&non_trusted_fw_content_cert,
+	[BL33_IMAGE_ID]				=	&bl33_image,
+};
+
+/* Register the CoT in the authentication module */
+REGISTER_COT(cot_desc);
diff --git a/drivers/fwu/fwu.c b/drivers/fwu/fwu.c
new file mode 100644
index 0000000..7cb4c29
--- /dev/null
+++ b/drivers/fwu/fwu.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/tf_crc32.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/fwu/fwu.h>
+#include <drivers/fwu/fwu_metadata.h>
+#include <drivers/io/io_storage.h>
+
+#include <plat/common/platform.h>
+
+/*
+ * Assert that crc_32 is the first member of fwu_metadata structure.
+ * It avoids accessing data outside of the metadata structure during
+ * CRC32 computation if the crc_32 field gets moved due the structure
+ * member(s) addition in the future.
+ */
+CASSERT((offsetof(struct fwu_metadata, crc_32) == 0),
+	crc_32_must_be_first_member_of_structure);
+
+static struct fwu_metadata metadata;
+static bool is_fwu_initialized;
+
+/*******************************************************************************
+ * Compute CRC32 of the FWU metadata, and check it against the CRC32 value
+ * present in the FWU metadata.
+ *
+ * return -1 on error, otherwise 0
+ ******************************************************************************/
+static int fwu_metadata_crc_check(void)
+{
+	unsigned char *data = (unsigned char *)&metadata;
+
+	uint32_t calc_crc = tf_crc32(0U, data + sizeof(metadata.crc_32),
+				     (sizeof(metadata) -
+				      sizeof(metadata.crc_32)));
+
+	if (metadata.crc_32 != calc_crc) {
+		return -1;
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+ * Check the sanity of FWU metadata.
+ *
+ * return -1 on error, otherwise 0
+ ******************************************************************************/
+static int fwu_metadata_sanity_check(void)
+{
+	/* ToDo: add more conditions for sanity check */
+	if ((metadata.active_index >= NR_OF_FW_BANKS) ||
+	    (metadata.previous_active_index >= NR_OF_FW_BANKS)) {
+		return -1;
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+ * Verify and load specified FWU metadata image to local FWU metadata structure.
+ *
+ * @image_id: FWU metadata image id (either FWU_METADATA_IMAGE_ID or
+ *				     BKUP_FWU_METADATA_IMAGE_ID)
+ *
+ * return a negative value on error, otherwise 0
+ ******************************************************************************/
+static int fwu_metadata_load(unsigned int image_id)
+{
+	int result;
+	uintptr_t dev_handle, image_handle, image_spec;
+	size_t bytes_read;
+
+	assert((image_id == FWU_METADATA_IMAGE_ID) ||
+	       (image_id == BKUP_FWU_METADATA_IMAGE_ID));
+
+	result = plat_fwu_set_metadata_image_source(image_id,
+						    &dev_handle,
+						    &image_spec);
+	if (result != 0) {
+		WARN("Failed to set reference to image id=%u (%i)\n",
+		     image_id, result);
+		return result;
+	}
+
+	result = io_open(dev_handle, image_spec, &image_handle);
+	if (result != 0) {
+		WARN("Failed to load image id id=%u (%i)\n",
+		     image_id, result);
+		return result;
+	}
+
+	result = io_read(image_handle, (uintptr_t)&metadata,
+			 sizeof(struct fwu_metadata), &bytes_read);
+
+	if (result != 0) {
+		WARN("Failed to read image id=%u (%i)\n", image_id, result);
+		goto exit;
+	}
+
+	if (sizeof(struct fwu_metadata) != bytes_read) {
+		/* return -1 in case of partial/no read */
+		result = -1;
+		WARN("Read bytes (%zu) instead of expected (%zu) bytes\n",
+		     bytes_read, sizeof(struct fwu_metadata));
+		goto exit;
+	}
+
+	/* sanity check on loaded parameters */
+	result = fwu_metadata_sanity_check();
+	if (result != 0) {
+		WARN("Sanity %s\n", "check failed on FWU metadata");
+		goto exit;
+	}
+
+	/* CRC check on loaded parameters */
+	result = fwu_metadata_crc_check();
+	if (result != 0) {
+		WARN("CRC %s\n", "check failed on FWU metadata");
+	}
+
+exit:
+	(void)io_close(image_handle);
+
+	return result;
+}
+
+/*******************************************************************************
+ * The system runs in the trial run state if any of the images in the active
+ * firmware bank has not been accepted yet.
+ *
+ * Returns true if the system is running in the trial state.
+ ******************************************************************************/
+bool fwu_is_trial_run_state(void)
+{
+	bool trial_run = false;
+
+	assert(is_fwu_initialized == true);
+
+	for (unsigned int i = 0U; i < NR_OF_IMAGES_IN_FW_BANK; i++) {
+		struct fwu_image_entry *entry = &metadata.img_entry[i];
+		struct fwu_image_properties *img_props =
+			&entry->img_props[metadata.active_index];
+		if (img_props->accepted == 0) {
+			trial_run = true;
+			break;
+		}
+	}
+
+	return trial_run;
+}
+
+/*******************************************************************************
+ * Load verified copy of FWU metadata image kept in the platform NV storage
+ * into local FWU metadata structure.
+ * Also, update platform I/O policies with the offset address and length of
+ * firmware-updated images kept in the platform NV storage.
+ ******************************************************************************/
+void fwu_init(void)
+{
+	/* Load FWU metadata which will be used to load the images in the
+	 * active bank as per PSA FWU specification
+	 */
+	int result = fwu_metadata_load(FWU_METADATA_IMAGE_ID);
+
+	if (result != 0) {
+		WARN("loading of FWU-Metadata failed, "
+		     "using Bkup-FWU-Metadata\n");
+
+		result = fwu_metadata_load(BKUP_FWU_METADATA_IMAGE_ID);
+		if (result != 0) {
+			ERROR("loading of Bkup-FWU-Metadata failed\n");
+			panic();
+		}
+	}
+
+	plat_fwu_set_images_source(&metadata);
+
+	is_fwu_initialized = true;
+}
diff --git a/drivers/fwu/fwu.mk b/drivers/fwu/fwu.mk
new file mode 100644
index 0000000..f4452e0
--- /dev/null
+++ b/drivers/fwu/fwu.mk
@@ -0,0 +1,11 @@
+#
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+FWU_SRC_DIR	:= drivers/fwu/
+
+FWU_SRCS	:= ${FWU_SRC_DIR}fwu.c
+
+BL2_SOURCES	+= ${FWU_SRCS}
diff --git a/drivers/io/io_mtd.c b/drivers/io/io_mtd.c
index 7575fa2..ba8cecd 100644
--- a/drivers/io/io_mtd.c
+++ b/drivers/io/io_mtd.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,8 +18,9 @@
 typedef struct {
 	io_mtd_dev_spec_t	*dev_spec;
 	uintptr_t		base;
-	unsigned long long	offset;		/* Offset in bytes */
-	unsigned long long	size;	/* Size of device in bytes */
+	unsigned long long	pos;		/* Offset in bytes */
+	unsigned long long	size;		/* Size of device in bytes */
+	unsigned long long	extra_offset;	/* Extra offset in bytes */
 } mtd_dev_state_t;
 
 io_type_t device_type_mtd(void);
@@ -110,16 +111,47 @@
 	return 0;
 }
 
+static int mtd_add_extra_offset(mtd_dev_state_t *cur, size_t *extra_offset)
+{
+	io_mtd_ops_t *ops = &cur->dev_spec->ops;
+	int ret;
+
+	if (ops->seek == NULL) {
+		return 0;
+	}
+
+	ret = ops->seek(cur->base, cur->pos, extra_offset);
+	if (ret != 0) {
+		ERROR("%s: Seek error %d\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 static int mtd_open(io_dev_info_t *dev_info, const uintptr_t spec,
 		    io_entity_t *entity)
 {
 	mtd_dev_state_t *cur;
+	io_block_spec_t *region;
+	size_t extra_offset = 0U;
+	int ret;
 
 	assert((dev_info->info != 0UL) && (entity->info == 0UL));
 
+	region = (io_block_spec_t *)spec;
 	cur = (mtd_dev_state_t *)dev_info->info;
 	entity->info = (uintptr_t)cur;
-	cur->offset = 0U;
+	cur->base = region->offset;
+	cur->pos = 0U;
+	cur->extra_offset = 0U;
+
+	ret = mtd_add_extra_offset(cur, &extra_offset);
+	if (ret != 0) {
+		return ret;
+	}
+
+	cur->base += extra_offset;
 
 	return 0;
 }
@@ -128,6 +160,8 @@
 static int mtd_seek(io_entity_t *entity, int mode, signed long long offset)
 {
 	mtd_dev_state_t *cur;
+	size_t extra_offset = 0U;
+	int ret;
 
 	assert((entity->info != (uintptr_t)NULL) && (offset >= 0));
 
@@ -140,22 +174,29 @@
 			return -EINVAL;
 		}
 
-		cur->offset = offset;
+		cur->pos = offset;
 		break;
 	case IO_SEEK_CUR:
-		if (((cur->offset + (unsigned long long)offset) >=
+		if (((cur->base + cur->pos + (unsigned long long)offset) >=
 		     cur->size) ||
-		    ((cur->offset + (unsigned long long)offset) <
-		     cur->offset)) {
+		    ((cur->base + cur->pos + (unsigned long long)offset) <
+		     cur->base + cur->pos)) {
 			return -EINVAL;
 		}
 
-		cur->offset += (unsigned long long)offset;
+		cur->pos += (unsigned long long)offset;
 		break;
 	default:
 		return -EINVAL;
 	}
 
+	ret = mtd_add_extra_offset(cur, &extra_offset);
+	if (ret != 0) {
+		return ret;
+	}
+
+	cur->extra_offset = extra_offset;
+
 	return 0;
 }
 
@@ -174,18 +215,19 @@
 	assert(ops->read != NULL);
 
 	VERBOSE("Read at %llx into %lx, length %zi\n",
-		cur->offset, buffer, length);
-	if ((cur->offset + length) > cur->dev_spec->device_size) {
+		cur->base + cur->pos, buffer, length);
+	if ((cur->base + cur->pos + length) > cur->dev_spec->device_size) {
 		return -EINVAL;
 	}
 
-	ret = ops->read(cur->offset, buffer, length, out_length);
+	ret = ops->read(cur->base + cur->pos + cur->extra_offset, buffer,
+			length, out_length);
 	if (ret < 0) {
 		return ret;
 	}
 
 	assert(*out_length == length);
-	cur->offset += *out_length;
+	cur->pos += *out_length;
 
 	return 0;
 }
diff --git a/drivers/marvell/comphy/comphy-cp110.h b/drivers/marvell/comphy/comphy-cp110.h
index 9b10619..af5c715 100644
--- a/drivers/marvell/comphy/comphy-cp110.h
+++ b/drivers/marvell/comphy/comphy-cp110.h
@@ -54,7 +54,7 @@
 #define COMMON_SELECTOR_PIPE_COMPHY_USBH	0x1
 #define COMMON_SELECTOR_PIPE_COMPHY_USBD	0x2
 
-/* SGMII/HS-SGMII/SFI/RXAUI */
+/* SGMII/Base-X/SFI/RXAUI */
 #define COMMON_SELECTOR_COMPHY0_1_2_NETWORK	0x1
 #define COMMON_SELECTOR_COMPHY3_RXAUI		0x1
 #define COMMON_SELECTOR_COMPHY3_SGMII		0x2
diff --git a/drivers/marvell/comphy/phy-comphy-3700.c b/drivers/marvell/comphy/phy-comphy-3700.c
index 7377e5e..0ad14a8 100644
--- a/drivers/marvell/comphy/phy-comphy-3700.c
+++ b/drivers/marvell/comphy/phy-comphy-3700.c
@@ -118,7 +118,7 @@
 };
 
 /* PHY selector configures with corresponding modes */
-static void mvebu_a3700_comphy_set_phy_selector(uint8_t comphy_index,
+static int mvebu_a3700_comphy_set_phy_selector(uint8_t comphy_index,
 						uint32_t comphy_mode)
 {
 	uint32_t reg;
@@ -135,7 +135,7 @@
 		break;
 
 	case (COMPHY_SGMII_MODE):
-	case (COMPHY_HS_SGMII_MODE):
+	case (COMPHY_2500BASEX_MODE):
 		if (comphy_index == COMPHY_LANE0)
 			reg &= ~COMPHY_SELECTOR_USB3_GBE1_SEL_BIT;
 		else if (comphy_index == COMPHY_LANE1)
@@ -168,9 +168,10 @@
 	}
 
 	mmio_write_32(MVEBU_COMPHY_REG_BASE + COMPHY_SELECTOR_PHY_REG, reg);
-	return;
+	return 0;
 error:
 	ERROR("COMPHY[%d] mode[%d] is invalid\n", comphy_index, mode);
+	return -EINVAL;
 }
 
 /*
@@ -183,7 +184,7 @@
  * with COMPHY_USB3D_MODE or COMPHY_USB3H_MODE. (The usb3 phy initialization
  * code does not differentiate between these modes.)
  * Also it returns COMPHY_SGMII_MODE even if the phy was configures with
- * COMPHY_HS_SGMII_MODE. (The sgmii phy initialization code does differentiate
+ * COMPHY_2500BASEX_MODE. (The sgmii phy initialization code does differentiate
  * between these modes, but it is irrelevant when powering the phy off.)
  */
 static int mvebu_a3700_comphy_get_mode(uint8_t comphy_index)
@@ -214,7 +215,7 @@
 
 /* It is only used for SATA and USB3 on comphy lane2. */
 static void comphy_set_indirect(uintptr_t addr, uint32_t offset, uint16_t data,
-				uint16_t mask, int mode)
+				uint16_t mask, bool is_sata)
 {
 	/*
 	 * When Lane 2 PHY is for USB3, access the PHY registers
@@ -224,27 +225,38 @@
 	 * within the SATA Host Controller registers, Lane 2 base register
 	 * offset is 0x200
 	 */
-	if (mode == COMPHY_UNUSED)
-		return;
-
-	if (mode == COMPHY_SATA_MODE)
+	if (is_sata) {
 		mmio_write_32(addr + COMPHY_LANE2_INDIR_ADDR_OFFSET, offset);
-	else
+	} else {
 		mmio_write_32(addr + COMPHY_LANE2_INDIR_ADDR_OFFSET,
 			      offset + USB3PHY_LANE2_REG_BASE_OFFSET);
+	}
 
 	reg_set(addr + COMPHY_LANE2_INDIR_DATA_OFFSET, data, mask);
 }
 
+/* It is only used for SATA on comphy lane2. */
+static void comphy_sata_set_indirect(uintptr_t addr, uint32_t reg_offset,
+				     uint16_t data, uint16_t mask)
+{
+	comphy_set_indirect(addr, reg_offset, data, mask, true);
+}
+
+/* It is only used for USB3 indirect access on comphy lane2. */
+static void comphy_usb3_set_indirect(uintptr_t addr, uint32_t reg_offset,
+				     uint16_t data, uint16_t mask)
+{
+	comphy_set_indirect(addr, reg_offset, data, mask, false);
+}
+
-/* It is only used USB3 direct access not on comphy lane2. */
+/* It is only used for USB3 direct access not on comphy lane2. */
 static void comphy_usb3_set_direct(uintptr_t addr, uint32_t reg_offset,
-				   uint16_t data, uint16_t mask, int mode)
+				   uint16_t data, uint16_t mask)
 {
 	reg_set16((reg_offset * PHY_SHFT(USB3) + addr), data, mask);
 }
 
-static void comphy_sgmii_phy_init(uint32_t comphy_index, uint32_t mode,
-				  uintptr_t sd_ip_addr)
+static void comphy_sgmii_phy_init(uintptr_t sd_ip_addr, bool is_1gbps)
 {
 	const int fix_arr_sz = ARRAY_SIZE(sgmii_phy_init_fix);
 	int addr, fix_idx;
@@ -259,8 +271,7 @@
 		 * comparison to 3.125 Gbps values. These register values are
 		 * stored in "sgmii_phy_init_fix" array.
 		 */
-		if ((mode != COMPHY_SGMII_MODE) &&
-		    (sgmii_phy_init_fix[fix_idx].addr == addr)) {
+		if (!is_1gbps && sgmii_phy_init_fix[fix_idx].addr == addr) {
 			/* Use new value */
 			val = sgmii_phy_init_fix[fix_idx].value;
 			if (fix_idx < fix_arr_sz)
@@ -276,21 +287,22 @@
 static int mvebu_a3700_comphy_sata_power_on(uint8_t comphy_index,
 					    uint32_t comphy_mode)
 {
-	int ret = 0;
+	int ret;
 	uint32_t offset, data = 0, ref_clk;
 	uintptr_t comphy_indir_regs = COMPHY_INDIRECT_REG;
-	int mode = COMPHY_GET_MODE(comphy_mode);
 	int invert = COMPHY_GET_POLARITY_INVERT(comphy_mode);
 
 	debug_enter();
 
 	/* Configure phy selector for SATA */
-	mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode);
+	ret = mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode);
+	if (ret) {
+		return ret;
+	}
 
 	/* Clear phy isolation mode to make it work in normal mode */
 	offset =  COMPHY_ISOLATION_CTRL_REG + SATAPHY_LANE2_REG_BASE_OFFSET;
-	comphy_set_indirect(comphy_indir_regs, offset, 0, PHY_ISOLATE_MODE,
-			    mode);
+	comphy_sata_set_indirect(comphy_indir_regs, offset, 0, PHY_ISOLATE_MODE);
 
 	/* 0. Check the Polarity invert bits */
 	if (invert & COMPHY_POLARITY_TXD_INVERT)
@@ -299,13 +311,13 @@
 		data |= RXD_INVERT_BIT;
 
 	offset = COMPHY_SYNC_PATTERN_REG + SATAPHY_LANE2_REG_BASE_OFFSET;
-	comphy_set_indirect(comphy_indir_regs, offset, data, TXD_INVERT_BIT |
-			    RXD_INVERT_BIT, mode);
+	comphy_sata_set_indirect(comphy_indir_regs, offset, data, TXD_INVERT_BIT |
+				 RXD_INVERT_BIT);
 
 	/* 1. Select 40-bit data width width */
 	offset = COMPHY_LOOPBACK_REG0 + SATAPHY_LANE2_REG_BASE_OFFSET;
-	comphy_set_indirect(comphy_indir_regs, offset, DATA_WIDTH_40BIT,
-			    SEL_DATA_WIDTH_MASK, mode);
+	comphy_sata_set_indirect(comphy_indir_regs, offset, DATA_WIDTH_40BIT,
+				 SEL_DATA_WIDTH_MASK);
 
 	/* 2. Select reference clock(25M) and PHY mode (SATA) */
 	offset = COMPHY_POWER_PLL_CTRL + SATAPHY_LANE2_REG_BASE_OFFSET;
@@ -314,17 +326,17 @@
 	else
 		ref_clk = REF_CLOCK_SPEED_25M;
 
-	comphy_set_indirect(comphy_indir_regs, offset, ref_clk | PHY_MODE_SATA,
-			    REF_FREF_SEL_MASK | PHY_MODE_MASK, mode);
+	comphy_sata_set_indirect(comphy_indir_regs, offset, ref_clk | PHY_MODE_SATA,
+				 REF_FREF_SEL_MASK | PHY_MODE_MASK);
 
 	/* 3. Use maximum PLL rate (no power save) */
 	offset = COMPHY_KVCO_CAL_CTRL + SATAPHY_LANE2_REG_BASE_OFFSET;
-	comphy_set_indirect(comphy_indir_regs, offset, USE_MAX_PLL_RATE_BIT,
-			    USE_MAX_PLL_RATE_BIT, mode);
+	comphy_sata_set_indirect(comphy_indir_regs, offset, USE_MAX_PLL_RATE_BIT,
+				 USE_MAX_PLL_RATE_BIT);
 
 	/* 4. Reset reserved bit */
-	comphy_set_indirect(comphy_indir_regs, COMPHY_RESERVED_REG, 0,
-			    PHYCTRL_FRM_PIN_BIT, mode);
+	comphy_sata_set_indirect(comphy_indir_regs, COMPHY_RESERVED_REG, 0,
+				 PHYCTRL_FRM_PIN_BIT);
 
 	/* 5. Set vendor-specific configuration (It is done in sata driver) */
 	/* XXX: in U-Boot below sequence was executed in this place, in Linux
@@ -346,17 +358,21 @@
 				   COMPHY_LANE2_INDIR_DATA_OFFSET,
 				   PLL_READY_TX_BIT, PLL_READY_TX_BIT,
 				   COMPHY_PLL_TIMEOUT, REG_32BIT);
+	if (ret) {
+		return -ETIMEDOUT;
+	}
 
 	debug_exit();
 
-	return ret;
+	return 0;
 }
 
 static int mvebu_a3700_comphy_sgmii_power_on(uint8_t comphy_index,
 					     uint32_t comphy_mode)
 {
-	int ret = 0;
-	uint32_t mask, data, offset;
+	int ret;
+	uint32_t mask, data;
+	uintptr_t offset;
 	uintptr_t sd_ip_addr;
 	int mode = COMPHY_GET_MODE(comphy_mode);
 	int invert = COMPHY_GET_POLARITY_INVERT(comphy_mode);
@@ -364,7 +380,10 @@
 	debug_enter();
 
 	/* Set selector */
-	mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode);
+	ret = mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode);
+	if (ret) {
+		return ret;
+	}
 
 	/* Serdes IP Base address
 	 * COMPHY Lane0 -- USB3/GBE1
@@ -401,8 +420,8 @@
 		/* SGMII 1G, SerDes speed 1.25G */
 		data |= SD_SPEED_1_25_G << GEN_RX_SEL_OFFSET;
 		data |= SD_SPEED_1_25_G << GEN_TX_SEL_OFFSET;
-	} else if (mode == COMPHY_HS_SGMII_MODE) {
-		/* HS SGMII (2.5G), SerDes speed 3.125G */
+	} else if (mode == COMPHY_2500BASEX_MODE) {
+		/* 2500Base-X, SerDes speed 3.125G */
 		data |= SD_SPEED_2_5_G << GEN_RX_SEL_OFFSET;
 		data |= SD_SPEED_2_5_G << GEN_TX_SEL_OFFSET;
 	} else {
@@ -479,9 +498,9 @@
 	 * 25 MHz the default values stored in PHY registers are OK.
 	 */
 	debug("Running C-DPI phy init %s mode\n",
-	      mode == COMPHY_HS_SGMII_MODE ? "2G5" : "1G");
+	      mode == COMPHY_2500BASEX_MODE ? "2G5" : "1G");
 	if (get_ref_clk() == 40)
-		comphy_sgmii_phy_init(comphy_index, mode, sd_ip_addr);
+		comphy_sgmii_phy_init(sd_ip_addr, mode != COMPHY_2500BASEX_MODE);
 
 	/*
 	 * 14. [Simulation Only] should not be used for real chip.
@@ -525,8 +544,10 @@
 				   PHY_PLL_READY_TX_BIT | PHY_PLL_READY_RX_BIT,
 				   PHY_PLL_READY_TX_BIT | PHY_PLL_READY_RX_BIT,
 				   COMPHY_PLL_TIMEOUT, REG_32BIT);
-	if (ret)
+	if (ret) {
 		ERROR("Failed to lock PLL for SGMII PHY %d\n", comphy_index);
+		return -ETIMEDOUT;
+	}
 
 	/*
 	 * 19. Set COMPHY input port PIN_TX_IDLE=0
@@ -549,26 +570,29 @@
 				   PHY_PLL_READY_TX_BIT | PHY_PLL_READY_RX_BIT,
 				   PHY_PLL_READY_TX_BIT | PHY_PLL_READY_RX_BIT,
 				   COMPHY_PLL_TIMEOUT, REG_32BIT);
-	if (ret)
+	if (ret) {
 		ERROR("Failed to lock PLL for SGMII PHY %d\n", comphy_index);
-
+		return -ETIMEDOUT;
+	}
 
 	ret = polling_with_timeout(MVEBU_COMPHY_REG_BASE +
 				   COMPHY_PHY_STATUS_OFFSET(comphy_index),
 				   PHY_RX_INIT_DONE_BIT, PHY_RX_INIT_DONE_BIT,
 				   COMPHY_PLL_TIMEOUT, REG_32BIT);
-	if (ret)
+	if (ret) {
 		ERROR("Failed to init RX of SGMII PHY %d\n", comphy_index);
+		return -ETIMEDOUT;
+	}
 
 	debug_exit();
 
-	return ret;
+	return 0;
 }
 
 static int mvebu_a3700_comphy_sgmii_power_off(uint8_t comphy_index)
 {
-	int ret = 0;
-	uint32_t mask, data, offset;
+	uintptr_t offset;
+	uint32_t mask, data;
 
 	debug_enter();
 
@@ -579,28 +603,31 @@
 
 	debug_exit();
 
-	return ret;
+	return 0;
 }
 
 static int mvebu_a3700_comphy_usb3_power_on(uint8_t comphy_index,
 					    uint32_t comphy_mode)
 {
-	int ret = 0;
+	int ret;
 	uintptr_t reg_base = 0;
-	uint32_t mask, data, addr, cfg, ref_clk;
+	uintptr_t addr;
+	uint32_t mask, data, cfg, ref_clk;
 	void (*usb3_reg_set)(uintptr_t addr, uint32_t reg_offset, uint16_t data,
-			     uint16_t mask, int mode);
-	int mode = COMPHY_GET_MODE(comphy_mode);
+			     uint16_t mask);
 	int invert = COMPHY_GET_POLARITY_INVERT(comphy_mode);
 
 	debug_enter();
 
 	/* Set phy seclector */
-	mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode);
+	ret = mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode);
+	if (ret) {
+		return ret;
+	}
 
 	/* Set usb3 reg access func, Lane2 is indirect access */
 	if (comphy_index == COMPHY_LANE2) {
-		usb3_reg_set = &comphy_set_indirect;
+		usb3_reg_set = &comphy_usb3_set_indirect;
 		reg_base = COMPHY_INDIRECT_REG;
 	} else {
 		/* Get the direct access register resource and map */
@@ -619,7 +646,7 @@
 	mask = PRD_TXDEEMPH0_MASK | PRD_TXMARGIN_MASK | PRD_TXSWING_MASK |
 		CFG_TX_ALIGN_POS_MASK;
 	usb3_reg_set(reg_base, COMPHY_REG_LANE_CFG0_ADDR, PRD_TXDEEMPH0_MASK,
-		     mask, mode);
+		     mask);
 
 	/*
 	 * 2. Set BIT0: enable transmitter in high impedance mode
@@ -631,20 +658,20 @@
 	mask = PRD_TXDEEMPH1_MASK | TX_DET_RX_MODE | GEN2_TX_DATA_DLY_MASK |
 		TX_ELEC_IDLE_MODE_EN;
 	data = TX_DET_RX_MODE | GEN2_TX_DATA_DLY_DEFT | TX_ELEC_IDLE_MODE_EN;
-	usb3_reg_set(reg_base, COMPHY_REG_LANE_CFG1_ADDR, data, mask, mode);
+	usb3_reg_set(reg_base, COMPHY_REG_LANE_CFG1_ADDR, data, mask);
 
 	/*
 	 * 3. Set Spread Spectrum Clock Enabled
 	 */
 	usb3_reg_set(reg_base, COMPHY_REG_LANE_CFG4_ADDR,
-		     SPREAD_SPECTRUM_CLK_EN, SPREAD_SPECTRUM_CLK_EN, mode);
+		     SPREAD_SPECTRUM_CLK_EN, SPREAD_SPECTRUM_CLK_EN);
 
 	/*
 	 * 4. Set Override Margining Controls From the MAC:
 	 *    Use margining signals from lane configuration
 	 */
 	usb3_reg_set(reg_base, COMPHY_REG_TEST_MODE_CTRL_ADDR,
-		     MODE_MARGIN_OVERRIDE, REG_16_BIT_MASK, mode);
+		     MODE_MARGIN_OVERRIDE, REG_16_BIT_MASK);
 
 	/*
 	 * 5. Set Lane-to-Lane Bundle Clock Sampling Period = per PCLK cycles
@@ -652,13 +679,13 @@
 	 */
 	usb3_reg_set(reg_base, COMPHY_REG_GLOB_CLK_SRC_LO_ADDR, 0x0,
 		     (MODE_CLK_SRC | BUNDLE_PERIOD_SEL | BUNDLE_PERIOD_SCALE |
-		      BUNDLE_SAMPLE_CTRL | PLL_READY_DLY), mode);
+		      BUNDLE_SAMPLE_CTRL | PLL_READY_DLY));
 
 	/*
 	 * 6. Set G2 Spread Spectrum Clock Amplitude at 4K
 	 */
 	usb3_reg_set(reg_base, COMPHY_REG_GEN2_SET_2,
-		     G2_TX_SSC_AMP_VALUE_20, G2_TX_SSC_AMP_MASK, mode);
+		     G2_TX_SSC_AMP_VALUE_20, G2_TX_SSC_AMP_MASK);
 
 	/*
 	 * 7. Unset G3 Spread Spectrum Clock Amplitude
@@ -667,7 +694,7 @@
 	mask = G3_TX_SSC_AMP_MASK | G3_VREG_RXTX_MAS_ISET_MASK |
 		RSVD_PH03FH_6_0_MASK;
 	usb3_reg_set(reg_base, COMPHY_REG_GEN2_SET_3,
-		     G3_VREG_RXTX_MAS_ISET_60U, mask, mode);
+		     G3_VREG_RXTX_MAS_ISET_60U, mask);
 
 	/*
 	 * 8. Check crystal jumper setting and program the Power and PLL Control
@@ -688,39 +715,37 @@
 		REF_FREF_SEL_MASK;
 	data = PU_IVREF_BIT | PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT |
 		PU_TX_INTP_BIT | PU_DFE_BIT | PHY_MODE_USB3 | ref_clk;
-	usb3_reg_set(reg_base, COMPHY_POWER_PLL_CTRL, data,  mask, mode);
+	usb3_reg_set(reg_base, COMPHY_POWER_PLL_CTRL, data,  mask);
 
 	mask = CFG_PM_OSCCLK_WAIT_MASK | CFG_PM_RXDEN_WAIT_MASK |
 		CFG_PM_RXDLOZ_WAIT_MASK;
 	data = CFG_PM_RXDEN_WAIT_1_UNIT  | cfg;
-	usb3_reg_set(reg_base, COMPHY_REG_PWR_MGM_TIM1_ADDR, data, mask, mode);
+	usb3_reg_set(reg_base, COMPHY_REG_PWR_MGM_TIM1_ADDR, data, mask);
 
 	/*
 	 * 9. Enable idle sync
 	 */
 	data = UNIT_CTRL_DEFAULT_VALUE | IDLE_SYNC_EN;
-	usb3_reg_set(reg_base, COMPHY_REG_UNIT_CTRL_ADDR, data, REG_16_BIT_MASK,
-		     mode);
+	usb3_reg_set(reg_base, COMPHY_REG_UNIT_CTRL_ADDR, data, REG_16_BIT_MASK);
 
 	/*
 	 * 10. Enable the output of 500M clock
 	 */
 	data = MISC_REG0_DEFAULT_VALUE | CLK500M_EN;
-	usb3_reg_set(reg_base, COMPHY_MISC_REG0_ADDR, data, REG_16_BIT_MASK,
-		     mode);
+	usb3_reg_set(reg_base, COMPHY_MISC_REG0_ADDR, data, REG_16_BIT_MASK);
 
 	/*
 	 * 11. Set 20-bit data width
 	 */
 	usb3_reg_set(reg_base, COMPHY_LOOPBACK_REG0, DATA_WIDTH_20BIT,
-		     REG_16_BIT_MASK, mode);
+		     REG_16_BIT_MASK);
 
 	/*
 	 * 12. Override Speed_PLL value and use MAC PLL
 	 */
 	usb3_reg_set(reg_base, COMPHY_KVCO_CAL_CTRL,
 		     (SPEED_PLL_VALUE_16 | USE_MAX_PLL_RATE_BIT),
-		     REG_16_BIT_MASK, mode);
+		     REG_16_BIT_MASK);
 
 	/*
 	 * 13. Check the Polarity invert bit
@@ -733,27 +758,26 @@
 		data |= RXD_INVERT_BIT;
 	}
 	mask = TXD_INVERT_BIT | RXD_INVERT_BIT;
-	usb3_reg_set(reg_base, COMPHY_SYNC_PATTERN_REG, data, mask, mode);
+	usb3_reg_set(reg_base, COMPHY_SYNC_PATTERN_REG, data, mask);
 
 	/*
 	 * 14. Set max speed generation to USB3.0 5Gbps
 	 */
 	usb3_reg_set(reg_base, COMPHY_SYNC_MASK_GEN_REG, PHY_GEN_USB3_5G,
-		     PHY_GEN_MAX_MASK, mode);
+		     PHY_GEN_MAX_MASK);
 
 	/*
 	 * 15. Set capacitor value for FFE gain peaking to 0xF
 	 */
 	usb3_reg_set(reg_base, COMPHY_REG_GEN3_SETTINGS_3,
-		     COMPHY_GEN_FFE_CAP_SEL_VALUE, COMPHY_GEN_FFE_CAP_SEL_MASK,
-		     mode);
+		     COMPHY_GEN_FFE_CAP_SEL_VALUE, COMPHY_GEN_FFE_CAP_SEL_MASK);
 
 	/*
 	 * 16. Release SW reset
 	 */
 	data = MODE_CORE_CLK_FREQ_SEL | MODE_PIPE_WIDTH_32 | MODE_REFDIV_BY_4;
 	usb3_reg_set(reg_base, COMPHY_REG_GLOB_PHY_CTRL0_ADDR, data,
-		     REG_16_BIT_MASK, mode);
+		     REG_16_BIT_MASK);
 
 	/* Wait for > 55 us to allow PCLK be enabled */
 	udelay(PLL_SET_DELAY_US);
@@ -771,12 +795,14 @@
 					   TXDCLK_PCLK_EN, TXDCLK_PCLK_EN,
 					   COMPHY_PLL_TIMEOUT, REG_16BIT);
 	}
-	if (ret)
+	if (ret) {
 		ERROR("Failed to lock USB3 PLL\n");
+		return -ETIMEDOUT;
+	}
 
 	debug_exit();
 
-	return ret;
+	return 0;
 }
 
 static int mvebu_a3700_comphy_pcie_power_on(uint8_t comphy_index,
@@ -862,12 +888,14 @@
 	ret = polling_with_timeout(LANE_STATUS1_ADDR(PCIE) + COMPHY_SD_ADDR,
 				   TXDCLK_PCLK_EN, TXDCLK_PCLK_EN,
 				   COMPHY_PLL_TIMEOUT, REG_16BIT);
-	if (ret)
+	if (ret) {
 		ERROR("Failed to lock PCIE PLL\n");
+		return -ETIMEDOUT;
+	}
 
 	debug_exit();
 
-	return ret;
+	return 0;
 }
 
 int mvebu_3700_comphy_power_on(uint8_t comphy_index, uint32_t comphy_mode)
@@ -883,7 +911,7 @@
 						       comphy_mode);
 		break;
 	case(COMPHY_SGMII_MODE):
-	case(COMPHY_HS_SGMII_MODE):
+	case(COMPHY_2500BASEX_MODE):
 		ret = mvebu_a3700_comphy_sgmii_power_on(comphy_index,
 							comphy_mode);
 		break;
@@ -919,23 +947,22 @@
 	return 0;
 }
 
-static int mvebu_a3700_comphy_sata_power_off(uint32_t comphy_mode)
+static int mvebu_a3700_comphy_sata_power_off(void)
 {
 	uintptr_t comphy_indir_regs = COMPHY_INDIRECT_REG;
-	int mode = COMPHY_GET_MODE(comphy_mode);
 	uint32_t offset;
 
 	debug_enter();
 
 	/* Set phy isolation mode */
 	offset = COMPHY_ISOLATION_CTRL_REG + SATAPHY_LANE2_REG_BASE_OFFSET;
-	comphy_set_indirect(comphy_indir_regs, offset, PHY_ISOLATE_MODE,
-			    PHY_ISOLATE_MODE, mode);
+	comphy_sata_set_indirect(comphy_indir_regs, offset, PHY_ISOLATE_MODE,
+				 PHY_ISOLATE_MODE);
 
 	/* Power off PLL, Tx, Rx */
 	offset = COMPHY_POWER_PLL_CTRL + SATAPHY_LANE2_REG_BASE_OFFSET;
-	comphy_set_indirect(comphy_indir_regs, offset, 0,
-			    PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT, mode);
+	comphy_sata_set_indirect(comphy_indir_regs, offset, 0,
+				 PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT);
 
 	debug_exit();
 
@@ -960,7 +987,7 @@
 
 	switch (mode) {
 	case(COMPHY_SGMII_MODE):
-	case(COMPHY_HS_SGMII_MODE):
+	case(COMPHY_2500BASEX_MODE):
 		err = mvebu_a3700_comphy_sgmii_power_off(comphy_index);
 		break;
 	case (COMPHY_USB3_MODE):
@@ -968,7 +995,7 @@
 		err = mvebu_a3700_comphy_usb3_power_off();
 		break;
 	case (COMPHY_SATA_MODE):
-		err = mvebu_a3700_comphy_sata_power_off(comphy_mode);
+		err = mvebu_a3700_comphy_sata_power_off();
 		break;
 
 	default:
diff --git a/drivers/marvell/comphy/phy-comphy-common.h b/drivers/marvell/comphy/phy-comphy-common.h
index e3b430a..c599437 100644
--- a/drivers/marvell/comphy/phy-comphy-common.h
+++ b/drivers/marvell/comphy/phy-comphy-common.h
@@ -87,7 +87,7 @@
 
 #define COMPHY_SATA_MODE	0x1
 #define COMPHY_SGMII_MODE	0x2	/* SGMII 1G */
-#define COMPHY_HS_SGMII_MODE	0x3	/* SGMII 2.5G */
+#define COMPHY_2500BASEX_MODE	0x3	/* 2500Base-X */
 #define COMPHY_USB3H_MODE	0x4
 #define COMPHY_USB3D_MODE	0x5
 #define COMPHY_PCIE_MODE	0x6
diff --git a/drivers/marvell/comphy/phy-comphy-cp110.c b/drivers/marvell/comphy/phy-comphy-cp110.c
index 86f4c77..e7cde75 100644
--- a/drivers/marvell/comphy/phy-comphy-cp110.c
+++ b/drivers/marvell/comphy/phy-comphy-cp110.c
@@ -30,7 +30,7 @@
 /* COMPHY speed macro */
 #define COMPHY_SPEED_1_25G		0 /* SGMII 1G */
 #define COMPHY_SPEED_2_5G		1
-#define COMPHY_SPEED_3_125G		2 /* SGMII 2.5G */
+#define COMPHY_SPEED_3_125G		2 /* 2500Base-X */
 #define COMPHY_SPEED_5G			3
 #define COMPHY_SPEED_5_15625G		4 /* XFI 5G */
 #define COMPHY_SPEED_6G			5
@@ -191,7 +191,7 @@
 		case(3):
 			/* For comphy 3:
 			 * 0x1 = RXAUI_Lane1
-			 * 0x2 = SGMII/HS-SGMII Port1
+			 * 0x2 = SGMII/Base-X Port1
 			 */
 			if (mode == COMPHY_RXAUI_MODE)
 				reg |= COMMON_SELECTOR_COMPHY3_RXAUI <<
@@ -202,20 +202,20 @@
 			break;
 		case(4):
 			 /* For comphy 4:
-			  * 0x1 = SGMII/HS-SGMII Port1, XFI1/SFI1
-			  * 0x2 = SGMII/HS-SGMII Port0: XFI0/SFI0, RXAUI_Lane0
+			  * 0x1 = SGMII/Base-X Port1, XFI1/SFI1
+			  * 0x2 = SGMII/Base-X Port0: XFI0/SFI0, RXAUI_Lane0
 			  *
-			  * We want to check if SGMII1/HS_SGMII1 is the
+			  * We want to check if SGMII1 is the
 			  * requested mode in order to determine which value
 			  * should be set (all other modes use the same value)
 			  * so we need to strip the mode, and check the ID
-			  * because we might handle SGMII0/HS_SGMII0 too.
+			  * because we might handle SGMII0 too.
 			  */
 			  /* TODO: need to distinguish between CP110 and CP115
 			   * as SFI1/XFI1 available only for CP115.
 			   */
 			if ((mode == COMPHY_SGMII_MODE ||
-			     mode == COMPHY_HS_SGMII_MODE ||
+			     mode == COMPHY_2500BASEX_MODE ||
 			     mode == COMPHY_SFI_MODE ||
 			     mode == COMPHY_XFI_MODE ||
 			     mode == COMPHY_AP_MODE)
@@ -228,7 +228,7 @@
 			break;
 		case(5):
 			/* For comphy 5:
-			 * 0x1 = SGMII/HS-SGMII Port2
+			 * 0x1 = SGMII/Base-X Port2
 			 * 0x2 = RXAUI Lane1
 			 */
 			if (mode == COMPHY_RXAUI_MODE)
@@ -713,7 +713,7 @@
 		data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
 		data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
 	} else if (sgmii_speed == COMPHY_SPEED_3_125G) {
-		/* HS SGMII (2.5G), SerDes speed 3.125G */
+		/* 2500Base-X, SerDes speed 3.125G */
 		data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
 		data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
 	} else {
@@ -1730,11 +1730,13 @@
 				HPIPE_LANE_STATUS1_REG;
 			data = HPIPE_LANE_STATUS1_PCLK_EN_MASK;
 			mask = data;
-			ret = polling_with_timeout(addr, data, mask,
+			data = polling_with_timeout(addr, data, mask,
 						   PLL_LOCK_TIMEOUT,
 						   REG_32BIT);
-			if (ret)
+			if (data) {
 				ERROR("Failed to lock PCIE PLL\n");
+				ret = -ETIMEDOUT;
+			}
 		}
 	}
 
@@ -2343,7 +2345,7 @@
 
 	switch (mode) {
 	case (COMPHY_SGMII_MODE):
-	case (COMPHY_HS_SGMII_MODE):
+	case (COMPHY_2500BASEX_MODE):
 	case (COMPHY_XFI_MODE):
 	case (COMPHY_SFI_MODE):
 	case (COMPHY_RXAUI_MODE):
@@ -2378,7 +2380,7 @@
 						       comphy_mode);
 		break;
 	case(COMPHY_SGMII_MODE):
-	case(COMPHY_HS_SGMII_MODE):
+	case(COMPHY_2500BASEX_MODE):
 		err = mvebu_cp110_comphy_sgmii_power_on(comphy_base,
 							comphy_index,
 							comphy_mode);
diff --git a/drivers/mtd/nand/core.c b/drivers/mtd/nand/core.c
index 44b001e..9f0331a 100644
--- a/drivers/mtd/nand/core.c
+++ b/drivers/mtd/nand/core.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -112,6 +112,47 @@
 	return 0;
 }
 
+int nand_seek_bb(uintptr_t base, unsigned int offset, size_t *extra_offset)
+{
+	unsigned int block;
+	unsigned int offset_block;
+	unsigned int max_block;
+	int is_bad;
+	size_t count_bb = 0U;
+
+	block = base / nand_dev.block_size;
+
+	if (offset != 0U) {
+		offset_block = (base + offset - 1U) / nand_dev.block_size;
+	} else {
+		offset_block = block;
+	}
+
+	max_block = nand_dev.size / nand_dev.block_size;
+
+	while (block <= offset_block) {
+		if (offset_block >= max_block) {
+			return -EIO;
+		}
+
+		is_bad = nand_dev.mtd_block_is_bad(block);
+		if (is_bad < 0) {
+			return is_bad;
+		}
+
+		if (is_bad == 1) {
+			count_bb++;
+			offset_block++;
+		}
+
+		block++;
+	}
+
+	*extra_offset = count_bb * nand_dev.block_size;
+
+	return 0;
+}
+
 struct nand_device *get_nand_device(void)
 {
 	return &nand_dev;
diff --git a/drivers/mtd/nand/spi_nand.c b/drivers/mtd/nand/spi_nand.c
index d01a119..abb524d 100644
--- a/drivers/mtd/nand/spi_nand.c
+++ b/drivers/mtd/nand/spi_nand.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019,  STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2021,  STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -286,6 +286,10 @@
 		return -EINVAL;
 	}
 
+	assert((spinand_dev.nand_dev->page_size != 0U) &&
+	       (spinand_dev.nand_dev->block_size != 0U) &&
+	       (spinand_dev.nand_dev->size != 0U));
+
 	ret = spi_nand_reset();
 	if (ret != 0) {
 		return ret;
@@ -301,12 +305,12 @@
 		return ret;
 	}
 
-	ret = spi_nand_quad_enable(id[0]);
+	ret = spi_nand_quad_enable(id[1]);
 	if (ret != 0) {
 		return ret;
 	}
 
-	VERBOSE("SPI_NAND Detected ID 0x%x 0x%x\n", id[0], id[1]);
+	VERBOSE("SPI_NAND Detected ID 0x%x\n", id[1]);
 
 	VERBOSE("Page size %i, Block size %i, size %lli\n",
 		spinand_dev.nand_dev->page_size,
diff --git a/drivers/nxp/auth/csf_hdr_parser/csf_hdr.mk b/drivers/nxp/auth/csf_hdr_parser/csf_hdr.mk
index d518dbb..1af51f8 100644
--- a/drivers/nxp/auth/csf_hdr_parser/csf_hdr.mk
+++ b/drivers/nxp/auth/csf_hdr_parser/csf_hdr.mk
@@ -1,5 +1,5 @@
 #
-# Copyright 2020 NXP
+# Copyright 2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -9,7 +9,7 @@
 
 CSF_HDR_SOURCES	+=  $(PLAT_DRIVERS_PATH)/auth/csf_hdr_parser/plat_img_parser.c
 
-PLAT_INCLUDES	+= -I$(PLAT_DRIVERS_PATH)/auth/csf_hdr_parser/
+PLAT_INCLUDES	+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/auth/csf_hdr_parser/
 
 $(eval $(call add_define, CSF_HEADER_PREPENDED))
 
diff --git a/drivers/nxp/console/console.mk b/drivers/nxp/console/console.mk
index 22d1336..6174650 100644
--- a/drivers/nxp/console/console.mk
+++ b/drivers/nxp/console/console.mk
@@ -14,7 +14,7 @@
 
 ADD_CONSOLE		:= 1
 
-PLAT_INCLUDES		+=	-I$(PLAT_DRIVERS_PATH)/console
+PLAT_INCLUDES		+=	-I$(PLAT_DRIVERS_INCLUDE_PATH)/console
 
 ifeq ($(CONSOLE), NS16550)
 NXP_CONSOLE		:=	NS16550
diff --git a/drivers/nxp/crypto/caam/caam.mk b/drivers/nxp/crypto/caam/caam.mk
index 548c7b1..f929f53 100644
--- a/drivers/nxp/crypto/caam/caam.mk
+++ b/drivers/nxp/crypto/caam/caam.mk
@@ -1,5 +1,5 @@
 #
-# Copyright 2020 NXP
+# Copyright 2020-2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,11 +8,10 @@
 ifeq (${ADD_CAAM},)
 
 ADD_CAAM		:= 1
-CAAM_DRIVER_PATH	:= drivers/nxp/crypto/caam
 
-CAAM_DRIVER_SOURCES	+=  $(wildcard $(CAAM_DRIVER_PATH)/src/*.c)
+CAAM_DRIVER_SOURCES	+=  $(wildcard $(PLAT_DRIVERS_PATH)/crypto/caam/src/*.c)
 
-PLAT_INCLUDES		+= -I$(CAAM_DRIVER_PATH)/include
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/crypto/caam
 
 ifeq (${BL_COMM_CRYPTO_NEEDED},yes)
 BL_COMMON_SOURCES	+= ${CAAM_DRIVER_SOURCES}
diff --git a/drivers/nxp/csu/csu.mk b/drivers/nxp/csu/csu.mk
index ebdf674..bc16035 100644
--- a/drivers/nxp/csu/csu.mk
+++ b/drivers/nxp/csu/csu.mk
@@ -1,5 +1,5 @@
 #
-# Copyright 2020 NXP
+# Copyright 2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,11 +8,9 @@
 
 CSU_ADDED		:= 1
 
-CSU_DRIVERS_PATH	:=  ${PLAT_DRIVERS_PATH}/csu
-
-PLAT_INCLUDES		+= -I$(CSU_DRIVERS_PATH)
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/csu
 
-CSU_SOURCES		+= $(CSU_DRIVERS_PATH)/csu.c
+CSU_SOURCES		+= $(PLAT_DRIVERS_PATH)/csu/csu.c
 
 ifeq (${BL_COMM_CSU_NEEDED},yes)
 BL_COMMON_SOURCES	+= ${CSU_SOURCES}
diff --git a/drivers/nxp/dcfg/dcfg.c b/drivers/nxp/dcfg/dcfg.c
index 2e813e7..a988c5d 100644
--- a/drivers/nxp/dcfg/dcfg.c
+++ b/drivers/nxp/dcfg/dcfg.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 NXP
+ * Copyright 2020-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -43,20 +43,12 @@
 
 	reg = gur_in32(dcfg_init_info->g_nxp_dcfg_addr + DCFG_SVR_OFFSET);
 
-	soc_info.mfr_id = (reg & SVR_MFR_ID_MASK) >> SVR_MFR_ID_SHIFT;
-#if defined(CONFIG_CHASSIS_3_2)
-	soc_info.family = (reg & SVR_FAMILY_MASK) >> SVR_FAMILY_SHIFT;
-	soc_info.dev_id = (reg & SVR_DEV_ID_MASK) >> SVR_DEV_ID_SHIFT;
-#endif
+	soc_info.svr_reg.val = reg;
+
 	/* zero means SEC enabled. */
 	soc_info.sec_enabled =
 		(((reg & SVR_SEC_MASK) >> SVR_SEC_SHIFT) == 0) ? true : false;
 
-	soc_info.personality = (reg & SVR_PERSONALITY_MASK)
-				>> SVR_PERSONALITY_SHIFT;
-	soc_info.maj_ver = (reg & SVR_MAJ_VER_MASK) >> SVR_MAJ_VER_SHIFT;
-	soc_info.min_ver = reg & SVR_MIN_VER_MASK;
-
 	soc_info.is_populated = true;
 	return (const soc_info_t *) &soc_info;
 }
diff --git a/drivers/nxp/dcfg/dcfg.mk b/drivers/nxp/dcfg/dcfg.mk
index 61d1850..206595f 100644
--- a/drivers/nxp/dcfg/dcfg.mk
+++ b/drivers/nxp/dcfg/dcfg.mk
@@ -1,5 +1,5 @@
 #
-# Copyright 2020 NXP
+# Copyright 2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,11 +8,9 @@
 
 ADD_DCFG		:= 1
 
-DCFG_DRIVERS_PATH	:=  ${PLAT_DRIVERS_PATH}/dcfg
-
-PLAT_INCLUDES		+= -I$(DCFG_DRIVERS_PATH)
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/dcfg
 
-DCFG_SOURCES		+= $(DCFG_DRIVERS_PATH)/dcfg.c
+DCFG_SOURCES		+= $(PLAT_DRIVERS_PATH)/dcfg/dcfg.c
 
 ifeq (${BL_COMM_DCFG_NEEDED},yes)
 BL_COMMON_SOURCES	+= ${DCFG_SOURCES}
diff --git a/drivers/nxp/ddr/fsl-mmdc/ddr.mk b/drivers/nxp/ddr/fsl-mmdc/ddr.mk
index e6cc7c1..afccb62 100644
--- a/drivers/nxp/ddr/fsl-mmdc/ddr.mk
+++ b/drivers/nxp/ddr/fsl-mmdc/ddr.mk
@@ -9,11 +9,11 @@
 
 DDR_DRIVERS_PATH	:=	drivers/nxp/ddr
 
-DDR_CNTLR_SOURCES	:=	${DDR_DRIVERS_PATH}/fsl-mmdc/fsl_mmdc.c \
-				${DDR_DRIVERS_PATH}/nxp-ddr/utility.c	\
-				${DDR_DRIVERS_PATH}/nxp-ddr/ddr.c	\
-				${DDR_DRIVERS_PATH}/nxp-ddr/ddrc.c
+DDR_CNTLR_SOURCES	:=	${PLAT_DRIVERS_PATH}/ddr/fsl-mmdc/fsl_mmdc.c \
+				${PLAT_DRIVERS_PATH}/ddr/nxp-ddr/utility.c	\
+				${PLAT_DRIVERS_PATH}/ddr/nxp-ddr/ddr.c	\
+				${PLAT_DRIVERS_PATH}/ddr/nxp-ddr/ddrc.c
 
-PLAT_INCLUDES		+=	-I$(DDR_DRIVERS_PATH)/include	\
-				-I$(DDR_DRIVERS_PATH)/fsl-mmdc
+PLAT_INCLUDES		+=	-I$(PLAT_DRIVERS_INCLUDE_PATH)/ddr	\
+				-I$(PLAT_DRIVERS_INCLUDE_PATH)/ddr/fsl-mmdc
 #------------------------------------------------
diff --git a/drivers/nxp/ddr/nxp-ddr/ddr.mk b/drivers/nxp/ddr/nxp-ddr/ddr.mk
index 866c092..6bdd947 100644
--- a/drivers/nxp/ddr/nxp-ddr/ddr.mk
+++ b/drivers/nxp/ddr/nxp-ddr/ddr.mk
@@ -4,8 +4,6 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
-DDR_DRIVERS_PATH	:= ${PLAT_DRIVERS_PATH}/ddr
-
 ifeq ($(PLAT_DDR_PHY), PHY_GEN2)
 $(eval $(call add_define, PHY_GEN2))
 PLAT_DDR_PHY_DIR		:= phy-gen2
@@ -68,12 +66,11 @@
 $(eval $(call add_define, DEBUG_DDR_INPUT_CONFIG))
 endif
 
-DDR_CNTLR_SOURCES	:= $(DDR_DRIVERS_PATH)/nxp-ddr/ddr.c \
-			   $(DDR_DRIVERS_PATH)/nxp-ddr/ddrc.c \
-			   $(DDR_DRIVERS_PATH)/nxp-ddr/dimm.c \
-			   $(DDR_DRIVERS_PATH)/nxp-ddr/regs.c \
-			   $(DDR_DRIVERS_PATH)/nxp-ddr/utility.c \
-			   $(DDR_DRIVERS_PATH)/$(PLAT_DDR_PHY_DIR)/phy.c
+DDR_CNTLR_SOURCES	:= $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/ddr.c \
+			   $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/ddrc.c \
+			   $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/dimm.c \
+			   $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/regs.c \
+			   $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/utility.c \
+			   $(PLAT_DRIVERS_PATH)/ddr/$(PLAT_DDR_PHY_DIR)/phy.c
 
-PLAT_INCLUDES		+= -I$(DDR_DRIVERS_PATH)/nxp-ddr \
-			   -I$(DDR_DRIVERS_PATH)/include
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/ddr
diff --git a/drivers/nxp/ddr/phy-gen2/phy.c b/drivers/nxp/ddr/phy-gen2/phy.c
index 97de1ae..9c84b00 100644
--- a/drivers/nxp/ddr/phy-gen2/phy.c
+++ b/drivers/nxp/ddr/phy-gen2/phy.c
@@ -672,7 +672,7 @@
 
 #ifdef DDR_PLL_FIX
 	soc_info = get_soc_info();
-	if (soc_info->maj_ver == 1) {
+	if (soc_info->svr_reg.bf.maj_ver == 1) {
 		ps_count[0] = 0x520; /* seq0bdly0 */
 		ps_count[1] = 0xa41; /* seq0bdly1 */
 		ps_count[2] = 0x668a; /* seq0bdly2 */
@@ -1093,8 +1093,8 @@
 
 #ifdef ERRATA_DDR_A011396
 	/* Only apply to DDRC 5.05.00 */
-	soc_info = get_soc_info(NXP_DCFG_ADDR);
-	if ((soc_info->maj_ver == 1U) && (ip_rev == U(0x50500))) {
+	soc_info = get_soc_info();
+	if ((soc_info->svr_reg.bf.maj_ver == 1U) && (ip_rev == U(0x50500))) {
 		phy_io_write16(phy,
 				t_master | csr_dfi_rd_data_cs_dest_map_addr,
 				0U);
@@ -1890,8 +1890,8 @@
 		prog_pll_ctrl2(phy, input);
 #ifdef DDR_PLL_FIX
 		soc_info = get_soc_info();
-		debug("SOC_SI_REV = %x\n", soc_info->maj_ver);
-		if (soc_info->maj_ver == 1) {
+		debug("SOC_SI_REV = %x\n", soc_info->svr_reg.bf.maj_ver);
+		if (soc_info->svr_reg.bf.maj_ver == 1) {
 			prog_pll_pwr_dn(phy, input);
 
 			/*Enable FFE aka TxEqualizationMode for rev1 SI*/
@@ -2601,8 +2601,8 @@
 		}
 
 #ifdef NXP_APPLY_MAX_CDD
-		soc_info = get_soc_info(NXP_DCFG_ADDR);
-		if (soc_info->maj_ver == 2) {
+		soc_info = get_soc_info();
+		if (soc_info->svr_reg.bf.maj_ver == 2) {
 			tcfg0 = regs->timing_cfg[0];
 			tcfg4 = regs->timing_cfg[4];
 			rank = findrank(conf->cs_in_use);
diff --git a/drivers/nxp/drivers.mk b/drivers/nxp/drivers.mk
index c6d5541..c2db363 100644
--- a/drivers/nxp/drivers.mk
+++ b/drivers/nxp/drivers.mk
@@ -1,5 +1,5 @@
 #
-# Copyright 2020 NXP
+# Copyright 2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,7 +8,8 @@
 ###############################################################################
 
 
-PLAT_DRIVERS_PATH	:=	drivers/nxp
+PLAT_DRIVERS_PATH		:=	drivers/nxp
+PLAT_DRIVERS_INCLUDE_PATH	:=	include/drivers/nxp
 
 ifeq (${SMMU_NEEDED},yes)
 PLAT_INCLUDES	+= -Iinclude/drivers/nxp/smmu/
diff --git a/drivers/nxp/gic/gic.mk b/drivers/nxp/gic/gic.mk
index 68091e8..d75e071 100644
--- a/drivers/nxp/gic/gic.mk
+++ b/drivers/nxp/gic/gic.mk
@@ -17,7 +17,7 @@
 GIC_SOURCES		+=	${PLAT_DRIVERS_PATH}/gic/ls_gicv2.c	\
 				plat/common/plat_gicv2.c
 
-PLAT_INCLUDES		+=	-I${PLAT_DRIVERS_PATH}/gic/include/gicv2
+PLAT_INCLUDES		+=	-I${PLAT_DRIVERS_INCLUDE_PATH}/gic/gicv2
 else
 ifeq ($(GIC), GIC500)
 include drivers/arm/gic/v3/gicv3.mk
@@ -25,7 +25,7 @@
 GIC_SOURCES		+=	${PLAT_DRIVERS_PATH}/gic/ls_gicv3.c	\
 				plat/common/plat_gicv3.c
 
-PLAT_INCLUDES		+=	-I${PLAT_DRIVERS_PATH}/gic/include/gicv3
+PLAT_INCLUDES		+=	-I${PLAT_DRIVERS_INCLUDE_PATH}/gic/gicv3
 else
     $(error -> GIC type not set!)
 endif
diff --git a/drivers/nxp/gpio/gpio.mk b/drivers/nxp/gpio/gpio.mk
index 157c60a..74f0dc4 100644
--- a/drivers/nxp/gpio/gpio.mk
+++ b/drivers/nxp/gpio/gpio.mk
@@ -9,11 +9,9 @@
 
 GPIO_ADDED		:= 1
 
-GPIO_DRIVERS_PATH	:=  drivers/nxp/gpio
-
-PLAT_INCLUDES		+=  -I$(GPIO_DRIVERS_PATH)
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/gpio
 
-GPIO_SOURCES		:= $(GPIO_DRIVERS_PATH)/nxp_gpio.c
+GPIO_SOURCES		:= $(PLAT_DRIVERS_PATH)/gpio/nxp_gpio.c
 
 ifeq (${BL_COMM_GPIO_NEEDED},yes)
 BL_COMMON_SOURCES	+= ${GPIO_SOURCES}
diff --git a/drivers/nxp/i2c/i2c.mk b/drivers/nxp/i2c/i2c.mk
index ae89115..716e14a 100644
--- a/drivers/nxp/i2c/i2c.mk
+++ b/drivers/nxp/i2c/i2c.mk
@@ -1,5 +1,5 @@
 #
-# Copyright 2020 NXP
+# Copyright 2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -7,10 +7,10 @@
 ifeq (${ADD_I2C},)
 
 ADD_I2C			:= 1
-I2C_DRIVERS_PATH        := ${PLAT_DRIVERS_PATH}/i2c
+
+I2C_SOURCES		+= $(PLAT_DRIVERS_PATH)/i2c/i2c.c
 
-I2C_SOURCES		+= $(I2C_DRIVERS_PATH)/i2c.c
-PLAT_INCLUDES		+= -I$(I2C_DRIVERS_PATH)
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/i2c
 
 ifeq (${BL_COMM_I2C_NEEDED},yes)
 BL_COMMON_SOURCES	+= ${I2C_SOURCES}
diff --git a/drivers/nxp/interconnect/interconnect.mk b/drivers/nxp/interconnect/interconnect.mk
index 81e3fa9..aa51be4 100644
--- a/drivers/nxp/interconnect/interconnect.mk
+++ b/drivers/nxp/interconnect/interconnect.mk
@@ -1,4 +1,4 @@
-# Copyright 2020 NXP
+# Copyright 2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -12,7 +12,7 @@
 ifeq (${ADD_INTERCONNECT},)
 
 ADD_INTERCONNECT	:= 1
-PLAT_INCLUDES		+= -I${PLAT_DRIVERS_PATH}/interconnect
+PLAT_INCLUDES		+= -I${PLAT_DRIVERS_INCLUDE_PATH}/interconnect
 
 ifeq (, $(filter $(INTERCONNECT), CCI400 CCN502 CCN504 CCN508))
     $(error -> Interconnect type not set!)
diff --git a/drivers/nxp/pmu/pmu.mk b/drivers/nxp/pmu/pmu.mk
index 56b0422..8d2ef07 100644
--- a/drivers/nxp/pmu/pmu.mk
+++ b/drivers/nxp/pmu/pmu.mk
@@ -8,11 +8,9 @@
 
 PMU_ADDED		:= 1
 
-PMU_DRIVERS_PATH	:=  ${PLAT_DRIVERS_PATH}/pmu
-
-PLAT_INCLUDES		+= -I$(PMU_DRIVERS_PATH)
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/pmu
 
-PMU_SOURCES		+= $(PMU_DRIVERS_PATH)/pmu.c
+PMU_SOURCES		+= $(PLAT_DRIVERS_PATH)/pmu/pmu.c
 
 ifeq (${BL_COMM_PMU_NEEDED},yes)
 BL_COMMON_SOURCES	+= ${PMU_SOURCES}
diff --git a/drivers/nxp/qspi/qspi.mk b/drivers/nxp/qspi/qspi.mk
index 3e2c735..b83dee2 100644
--- a/drivers/nxp/qspi/qspi.mk
+++ b/drivers/nxp/qspi/qspi.mk
@@ -1,5 +1,5 @@
 #
-# Copyright 2020 NXP
+# Copyright 2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,11 +8,9 @@
 
 QSPI_ADDED		:= 1
 
-QSPI_DRIVERS_PATH	:=  ${PLAT_DRIVERS_PATH}/qspi
-
-QSPI_SOURCES		:=  $(QSPI_DRIVERS_PATH)/qspi.c
+QSPI_SOURCES		:= $(PLAT_DRIVERS_PATH)/qspi/qspi.c
 
-PLAT_INCLUDES		+= -I$(QSPI_DRIVERS_PATH)
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_PATH)/qspi
 
 ifeq (${BL_COMM_QSPI_NEEDED},yes)
 BL_COMMON_SOURCES	+= ${QSPI_SOURCES}
diff --git a/drivers/nxp/sd/sd_mmc.mk b/drivers/nxp/sd/sd_mmc.mk
index af91b1f..c83b1bd 100644
--- a/drivers/nxp/sd/sd_mmc.mk
+++ b/drivers/nxp/sd/sd_mmc.mk
@@ -1,5 +1,5 @@
 #
-# Copyright 2020 NXP
+# Copyright 2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,12 +8,10 @@
 
 ADD_SD_MMC	:= 1
 
-SD_DRIVERS_PATH		:=  ${PLAT_DRIVERS_PATH}/sd
-
-SD_MMC_BOOT_SOURCES	+= ${SD_DRIVERS_PATH}/sd_mmc.c \
+SD_MMC_BOOT_SOURCES	+= ${PLAT_DRIVERS_PATH}/sd/sd_mmc.c \
 			   drivers/io/io_block.c
 
-PLAT_INCLUDES		+= -I$(SD_DRIVERS_PATH)
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/sd
 
 ifeq (${BL_COMM_SD_MMC_NEEDED},yes)
 BL_COMMON_SOURCES	+= ${SD_MMC_BOOT_SOURCES}
diff --git a/drivers/nxp/sec_mon/sec_mon.mk b/drivers/nxp/sec_mon/sec_mon.mk
index 51e3e86..aaac53f 100644
--- a/drivers/nxp/sec_mon/sec_mon.mk
+++ b/drivers/nxp/sec_mon/sec_mon.mk
@@ -8,11 +8,9 @@
 
 ADD_SNVS		:= 1
 
-SNVS_DRIVERS_PATH	:= ${PLAT_DRIVERS_PATH}/sec_mon
-
-PLAT_INCLUDES		+= -I$(SNVS_DRIVERS_PATH)
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/sec_mon
 
-SNVS_SOURCES		+= $(SNVS_DRIVERS_PATH)/snvs.c
+SNVS_SOURCES		+= $(PLAT_DRIVERS_PATH)/sec_mon/snvs.c
 
 ifeq (${BL_COMM_SNVS_NEEDED},yes)
 BL_COMMON_SOURCES	+= ${SNVS_SOURCES}
diff --git a/drivers/nxp/sfp/sfp.mk b/drivers/nxp/sfp/sfp.mk
index 2546dc2..de708c5 100644
--- a/drivers/nxp/sfp/sfp.mk
+++ b/drivers/nxp/sfp/sfp.mk
@@ -1,5 +1,5 @@
 #
-# Copyright 2020 NXP
+# Copyright 2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -9,14 +9,12 @@
 SFP_ADDED		:= 1
 $(eval $(call add_define, NXP_SFP_ENABLED))
 
-SFP_DRIVERS_PATH	:=  ${PLAT_DRIVERS_PATH}/sfp
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/sfp
 
-PLAT_INCLUDES		+= -I$(SFP_DRIVERS_PATH)
-
-SFP_SOURCES		+= $(SFP_DRIVERS_PATH)/sfp.c
+SFP_SOURCES		+= $(PLAT_DRIVERS_PATH)/sfp/sfp.c
 
 ifeq (${FUSE_PROG}, 1)
-SFP_BL2_SOURCES		+= $(SFP_DRIVERS_PATH)/fuse_prov.c
+SFP_BL2_SOURCES		+= $(PLAT_DRIVERS_PATH)/sfp/fuse_prov.c
 endif
 
 ifeq (${BL_COMM_SFP_NEEDED},yes)
diff --git a/drivers/nxp/timer/timer.mk b/drivers/nxp/timer/timer.mk
index b9e298f..d658d19 100644
--- a/drivers/nxp/timer/timer.mk
+++ b/drivers/nxp/timer/timer.mk
@@ -8,10 +8,8 @@
 
 ADD_TIMER		:= 1
 
-TIMER_DRIVERS_PATH	:=  ${PLAT_DRIVERS_PATH}/timer
-
-PLAT_INCLUDES		+= -I$(TIMER_DRIVERS_PATH)
-TIMER_SOURCES	+= drivers/delay_timer/delay_timer.c	\
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/timer
+TIMER_SOURCES		+= drivers/delay_timer/delay_timer.c	\
 			   $(PLAT_DRIVERS_PATH)/timer/nxp_timer.c
 
 ifeq (${BL_COMM_TIMER_NEEDED},yes)
diff --git a/drivers/nxp/tzc/tzc.mk b/drivers/nxp/tzc/tzc.mk
index 830d78e..3fba28f 100644
--- a/drivers/nxp/tzc/tzc.mk
+++ b/drivers/nxp/tzc/tzc.mk
@@ -8,13 +8,11 @@
 
 ADD_TZASC		:= 1
 
-TZASC_DRIVERS_PATH	:=  ${PLAT_DRIVERS_PATH}/tzc
-
-PLAT_INCLUDES		+= -I$(TZASC_DRIVERS_PATH)
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/tzc
 
 ifeq ($(TZC_ID), TZC400)
 TZASC_SOURCES		+= drivers/arm/tzc/tzc400.c\
-			   $(TZASC_DRIVERS_PATH)/plat_tzc400.c
+			   $(PLAT_DRIVERS_PATH)/tzc/plat_tzc400.c
 else ifeq ($(TZC_ID), NONE)
     $(info -> No TZC present on platform)
 else
diff --git a/drivers/renesas/common/common.c b/drivers/renesas/common/common.c
index 9b7c1eb..a0aa480 100644
--- a/drivers/renesas/common/common.c
+++ b/drivers/renesas/common/common.c
@@ -1,11 +1,12 @@
 /*
- * Copyright (c) 2018-2020, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2018-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <lib/mmio.h>
 
+#include "cpg_registers.h"
 #include "rcar_private.h"
 
 #if IMAGE_BL31
@@ -16,7 +17,7 @@
 {
 	uint32_t value = regval;
 
-	mmio_write_32((uintptr_t) RCAR_CPGWPR, ~value);
+	mmio_write_32(CPG_CPGWPR, ~value);
 	mmio_write_32(regadr, value);
 }
 
diff --git a/drivers/renesas/common/console/rcar_console.S b/drivers/renesas/common/console/rcar_console.S
index 29baa67..b683d7b 100644
--- a/drivers/renesas/common/console/rcar_console.S
+++ b/drivers/renesas/common/console/rcar_console.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2018-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -63,7 +63,7 @@
 	 * ---------------------------------------------
 	 */
 func console_rcar_init
-	mov	w0, #0
+	mov	w0, #1
 	ret
 endfunc console_rcar_init
 
diff --git a/drivers/renesas/common/ddr/ddr_a/ddr_init_d3.c b/drivers/renesas/common/ddr/ddr_a/ddr_init_d3.c
index a49510e..f0113f1 100644
--- a/drivers/renesas/common/ddr/ddr_a/ddr_init_d3.c
+++ b/drivers/renesas/common/ddr/ddr_a/ddr_init_d3.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, Renesas Electronics Corporation.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation.
  * All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -11,7 +11,11 @@
 #include "rcar_def.h"
 #include "../ddr_regs.h"
 
-#define RCAR_DDR_VERSION	"rev.0.01"
+#define RCAR_DDR_VERSION	"rev.0.02"
+
+/* Average periodic refresh interval[ns]. Support 3900,7800 */
+#define REFRESH_RATE  3900
+
 
 #if RCAR_LSI != RCAR_D3
 #error "Don't have DDR initialize routine."
@@ -44,7 +48,7 @@
 	mmio_write_32(DBSC_DBTR16, 0x09210507);
 	mmio_write_32(DBSC_DBTR17, 0x040E0000);
 	mmio_write_32(DBSC_DBTR18, 0x00000200);
-	mmio_write_32(DBSC_DBTR19, 0x012B004B);
+	mmio_write_32(DBSC_DBTR19, 0x0129004B);
 	mmio_write_32(DBSC_DBTR20, 0x020000FB);
 	mmio_write_32(DBSC_DBTR21, 0x00040004);
 	mmio_write_32(DBSC_DBBL, 0x00000000);
@@ -54,8 +58,8 @@
 	mmio_write_32(DBSC_DBDFICNT_0, 0x00000010);
 	mmio_write_32(DBSC_DBBCAMDIS, 0x00000001);
 	mmio_write_32(DBSC_DBSCHRW1, 0x00000046);
-	mmio_write_32(DBSC_SCFCTST0, 0x0D020D04);
-	mmio_write_32(DBSC_SCFCTST1, 0x0306040C);
+	mmio_write_32(DBSC_SCFCTST0, 0x0C050B03);
+	mmio_write_32(DBSC_SCFCTST1, 0x0305030C);
 
 	mmio_write_32(DBSC_DBPDLK_0, 0x0000A55A);
 	mmio_write_32(DBSC_DBCMD, 0x01000001);
@@ -101,7 +105,9 @@
 		;
 
 	mmio_write_32(DBSC_DBPDRGA_0, 0x00000004);
-	mmio_write_32(DBSC_DBPDRGD_0, 0x0A206F89);
+	mmio_write_32(DBSC_DBPDRGD_0,
+		(uint32_t) (REFRESH_RATE * 928 / 125) - 400
+			+ 0x0A300000);
 	mmio_write_32(DBSC_DBPDRGA_0, 0x00000022);
 	mmio_write_32(DBSC_DBPDRGD_0, 0x1000040B);
 	mmio_write_32(DBSC_DBPDRGA_0, 0x00000023);
@@ -117,7 +123,11 @@
 	mmio_write_32(DBSC_DBPDRGA_0, 0x00000028);
 	mmio_write_32(DBSC_DBPDRGD_0, 0x00000046);
 	mmio_write_32(DBSC_DBPDRGA_0, 0x00000029);
-	mmio_write_32(DBSC_DBPDRGD_0, 0x000000A0);
+	if (REFRESH_RATE > 3900) {
+		mmio_write_32(DBSC_DBPDRGD_0, 0x00000020);
+	} else {
+		mmio_write_32(DBSC_DBPDRGD_0, 0x000000A0);
+	}
 	mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C);
 	mmio_write_32(DBSC_DBPDRGD_0, 0x81003047);
 	mmio_write_32(DBSC_DBPDRGA_0, 0x00000020);
@@ -225,8 +235,10 @@
 
 	mmio_write_32(DBSC_DBPDRGA_0, 0x000000AF);
 	r2 = mmio_read_32(DBSC_DBPDRGD_0);
+	mmio_write_32(DBSC_DBPDRGA_0, 0x000000AF);
 	mmio_write_32(DBSC_DBPDRGD_0, ((r2 + 0x1) & 0xFF) | (r2 & 0xFFFFFF00));
 	mmio_write_32(DBSC_DBPDRGA_0, 0x000000CF);
+	mmio_write_32(DBSC_DBPDRGA_0, 0x000000CF);
 	r2 = mmio_read_32(DBSC_DBPDRGD_0);
 	mmio_write_32(DBSC_DBPDRGD_0, ((r2 + 0x1) & 0xFF) | (r2 & 0xFFFFFF00));
 
@@ -296,8 +308,10 @@
 	mmio_write_32(DBSC_DBPDRGD_0, 0x0024643E);
 
 	mmio_write_32(DBSC_DBBUS0CNF1, 0x00000010);
-	mmio_write_32(DBSC_DBCALCNF, 0x0100401B);
-	mmio_write_32(DBSC_DBRFCNF1, 0x00080E23);
+	mmio_write_32(DBSC_DBCALCNF,
+		(uint32_t) (64000000 / REFRESH_RATE) + 0x01000000);
+	mmio_write_32(DBSC_DBRFCNF1,
+		(uint32_t) (REFRESH_RATE * 116 / 125) + 0x00080000);
 	mmio_write_32(DBSC_DBRFCNF2, 0x00010000);
 	mmio_write_32(DBSC_DBDFICUPDCNF, 0x40100001);
 	mmio_write_32(DBSC_DBRFEN, 0x00000001);
@@ -346,6 +360,19 @@
 {
 	uint32_t i, r2, r3, r5, r6, r7, r12;
 
+	mmio_write_32(CPG_CPGWPR, 0x5A5AFFFF);
+	mmio_write_32(CPG_CPGWPCR, 0xA5A50000);
+
+	mmio_write_32(CPG_SRCR4, 0x20000000);
+
+	mmio_write_32(0xE61500DC, 0xe2200000);
+	while (!(mmio_read_32(CPG_PLLECR) & BIT(11)))
+		;
+
+	mmio_write_32(CPG_SRSTCLR4, 0x20000000);
+
+	mmio_write_32(CPG_CPGWPCR, 0xA5A50001);
+
 	mmio_write_32(DBSC_DBSYSCNT0, 0x00001234);
 	mmio_write_32(DBSC_DBKIND, 0x00000007);
 	mmio_write_32(DBSC_DBMEMCONF_0_0, 0x0f030a01);
@@ -363,14 +390,14 @@
 	mmio_write_32(DBSC_DBTR10, 0x0000000C);
 	mmio_write_32(DBSC_DBTR11, 0x0000000A);
 	mmio_write_32(DBSC_DBTR12, 0x00120012);
-	mmio_write_32(DBSC_DBTR13, 0x000000D0);
+	mmio_write_32(DBSC_DBTR13, 0x000000CE);
 	mmio_write_32(DBSC_DBTR14, 0x00140005);
 	mmio_write_32(DBSC_DBTR15, 0x00050004);
 	mmio_write_32(DBSC_DBTR16, 0x071F0305);
 	mmio_write_32(DBSC_DBTR17, 0x040C0000);
 	mmio_write_32(DBSC_DBTR18, 0x00000200);
 	mmio_write_32(DBSC_DBTR19, 0x01000040);
-	mmio_write_32(DBSC_DBTR20, 0x020000D8);
+	mmio_write_32(DBSC_DBTR20, 0x020000D6);
 	mmio_write_32(DBSC_DBTR21, 0x00040004);
 	mmio_write_32(DBSC_DBBL, 0x00000000);
 	mmio_write_32(DBSC_DBODT0, 0x00000001);
@@ -379,8 +406,8 @@
 	mmio_write_32(DBSC_DBDFICNT_0, 0x00000010);
 	mmio_write_32(DBSC_DBBCAMDIS, 0x00000001);
 	mmio_write_32(DBSC_DBSCHRW1, 0x00000046);
-	mmio_write_32(DBSC_SCFCTST0, 0x0D020C04);
-	mmio_write_32(DBSC_SCFCTST1, 0x0305040C);
+	mmio_write_32(DBSC_SCFCTST0, 0x0D050B03);
+	mmio_write_32(DBSC_SCFCTST1, 0x0306030C);
 
 	mmio_write_32(DBSC_DBPDLK_0, 0x0000A55A);
 	mmio_write_32(DBSC_DBCMD, 0x01000001);
@@ -426,13 +453,14 @@
 		;
 
 	mmio_write_32(DBSC_DBPDRGA_0, 0x00000004);
-	mmio_write_32(DBSC_DBPDRGD_0, 0x08C05FF0);
+	mmio_write_32(DBSC_DBPDRGD_0,
+		(uint32_t) (REFRESH_RATE * 792 / 125) - 400 + 0x08B00000);
 	mmio_write_32(DBSC_DBPDRGA_0, 0x00000022);
 	mmio_write_32(DBSC_DBPDRGD_0, 0x1000040B);
 	mmio_write_32(DBSC_DBPDRGA_0, 0x00000023);
 	mmio_write_32(DBSC_DBPDRGD_0, 0x2D9C0B66);
 	mmio_write_32(DBSC_DBPDRGA_0, 0x00000024);
-	mmio_write_32(DBSC_DBPDRGD_0, 0x2A88C400);
+	mmio_write_32(DBSC_DBPDRGD_0, 0x2A88B400);
 	mmio_write_32(DBSC_DBPDRGA_0, 0x00000025);
 	mmio_write_32(DBSC_DBPDRGD_0, 0x30005200);
 	mmio_write_32(DBSC_DBPDRGA_0, 0x00000026);
@@ -442,7 +470,11 @@
 	mmio_write_32(DBSC_DBPDRGA_0, 0x00000028);
 	mmio_write_32(DBSC_DBPDRGD_0, 0x00000046);
 	mmio_write_32(DBSC_DBPDRGA_0, 0x00000029);
-	mmio_write_32(DBSC_DBPDRGD_0, 0x00000098);
+	if (REFRESH_RATE > 3900) {
+		mmio_write_32(DBSC_DBPDRGD_0, 0x00000018);
+	} else {
+		mmio_write_32(DBSC_DBPDRGD_0, 0x00000098);
+	}
 	mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C);
 	mmio_write_32(DBSC_DBPDRGD_0, 0x81003047);
 	mmio_write_32(DBSC_DBPDRGA_0, 0x00000020);
@@ -549,9 +581,11 @@
 
 	mmio_write_32(DBSC_DBPDRGA_0, 0x000000AF);
 	r2 = mmio_read_32(DBSC_DBPDRGD_0);
+	mmio_write_32(DBSC_DBPDRGA_0, 0x000000AF);
 	mmio_write_32(DBSC_DBPDRGD_0, ((r2 + 0x1) & 0xFF) | (r2 & 0xFFFFFF00));
 	mmio_write_32(DBSC_DBPDRGA_0, 0x000000CF);
 	r2 = mmio_read_32(DBSC_DBPDRGD_0);
+	mmio_write_32(DBSC_DBPDRGA_0, 0x000000CF);
 	mmio_write_32(DBSC_DBPDRGD_0, ((r2 + 0x1) & 0xFF) | (r2 & 0xFFFFFF00));
 
 	mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0);
@@ -620,8 +654,10 @@
 	mmio_write_32(DBSC_DBPDRGD_0, 0x0024643E);
 
 	mmio_write_32(DBSC_DBBUS0CNF1, 0x00000010);
-	mmio_write_32(DBSC_DBCALCNF, 0x0100401B);
-	mmio_write_32(DBSC_DBRFCNF1, 0x00080C30);
+	mmio_write_32(DBSC_DBCALCNF,
+		(uint32_t) (64000000 / REFRESH_RATE) + 0x01000000);
+	mmio_write_32(DBSC_DBRFCNF1,
+		(uint32_t) (REFRESH_RATE * 99 / 125) + 0x00080000);
 	mmio_write_32(DBSC_DBRFCNF2, 0x00010000);
 	mmio_write_32(DBSC_DBDFICUPDCNF, 0x40100001);
 	mmio_write_32(DBSC_DBRFEN, 0x00000001);
@@ -693,7 +729,7 @@
 		ddr_mbps = 1600;
 	}
 
-	NOTICE("BL2: DDR%d\n", ddr_mbps);
+	NOTICE("BL2: DDR%d(%s)\n", ddr_mbps, RCAR_DDR_VERSION);
 
 	return 0;
 }
diff --git a/drivers/renesas/common/ddr/ddr_b/boot_init_dram.c b/drivers/renesas/common/ddr/ddr_b/boot_init_dram.c
index aa3bc24..8d002de 100644
--- a/drivers/renesas/common/ddr/ddr_b/boot_init_dram.c
+++ b/drivers/renesas/common/ddr/ddr_b/boot_init_dram.c
@@ -4147,7 +4147,13 @@
 	}
 
 	/* THCTR Bit6: PONM=0 , Bit0: THSST=0   */
-	data_l = mmio_read_32(THS1_THCTR) & 0xFFFFFFBE;
+	data_l = mmio_read_32(THS1_THCTR);
+	if (data_l & 0x00000040U) {
+		data_l = data_l & 0xFFFFFFBEU;
+	} else {
+		data_l = data_l | BIT(1);
+	}
+
 	mmio_write_32(THS1_THCTR, data_l);
 
 	/* Judge product and cut */
diff --git a/drivers/renesas/common/ddr/ddr_b/boot_init_dram_config.c b/drivers/renesas/common/ddr/ddr_b/boot_init_dram_config.c
index 45b6b08..bbb0200 100644
--- a/drivers/renesas/common/ddr/ddr_b/boot_init_dram_config.c
+++ b/drivers/renesas/common/ddr/ddr_b/boot_init_dram_config.c
@@ -12,6 +12,9 @@
 #if (RZG_SOC == 1)
 #define BOARDNUM 4
 #else
+
+#include <board.h>
+
 #define BOARDNUM 22
 #endif /* RZG_SOC == 1 */
 #define BOARD_JUDGE_AUTO
@@ -1967,6 +1970,44 @@
 }
 #endif /* RZG_SOC == 1 */
 
+#if (RZG_SOC == 0) && (RCAR_DRAM_LPDDR4_MEMCONF != 0)
+static uint32_t ddr_rank_judge(void)
+{
+	uint32_t brd;
+
+#if (RCAR_DRAM_MEMRANK == 0)
+	int32_t ret;
+	uint32_t type = 0U;
+	uint32_t rev = 0U;
+
+	brd = 99U;
+	ret = rcar_get_board_type(&type, &rev);
+	if ((ret == 0) && (rev != 0xFFU)) {
+		if (type == (uint32_t)BOARD_SALVATOR_XS) {
+			if (rev == 0x11U) {
+				brd = 14U;
+			} else {
+				brd = 8U;
+			}
+		} else if (type == (uint32_t)BOARD_STARTER_KIT_PRE) {
+			if (rev == 0x21U) {
+				brd = 14U;
+			} else {
+				brd = 8U;
+			}
+		}
+	}
+#elif (RCAR_DRAM_MEMRANK == 1)
+	brd = 14U;
+#elif (RCAR_DRAM_MEMRANK == 2)
+	brd = 8U;
+#else
+#error Invalid value was set to RCAR_DRAM_MEMRANK
+#endif /* (RCAR_DRAM_MEMRANK == 0) */
+	return brd;
+}
+#endif /* (RCAR_DRAM_LPDDR4_MEMCONF != 0) */
+
 static uint32_t _board_judge(void)
 {
 	uint32_t brd;
@@ -1985,7 +2026,7 @@
 #if (RCAR_DRAM_LPDDR4_MEMCONF == 0)
 			brd = 7;
 #else
-			brd = 8;
+			brd = ddr_rank_judge();
 #endif
 		}
 	} else if (prr_product == PRR_PRODUCT_M3) {
@@ -2039,7 +2080,7 @@
 #if (RCAR_DRAM_LPDDR4_MEMCONF == 0)
 				brd = 7;
 #else
-				brd = 8;
+				brd = ddr_rank_judge();
 #endif
 			}
 		} else if (prr_product == PRR_PRODUCT_M3N) {
diff --git a/drivers/renesas/common/ddr/ddr_b/boot_init_dram_regdef.h b/drivers/renesas/common/ddr/ddr_b/boot_init_dram_regdef.h
index 56363eb..3cb1975 100644
--- a/drivers/renesas/common/ddr/ddr_b/boot_init_dram_regdef.h
+++ b/drivers/renesas/common/ddr/ddr_b/boot_init_dram_regdef.h
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2015-2020, Renesas Electronics Corporation.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation.
  * All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#define RCAR_DDR_VERSION	"rev.0.40"
+#define RCAR_DDR_VERSION	"rev.0.41"
 #define DRAM_CH_CNT		0x04
 #define SLICE_CNT		0x04
 #define CS_CNT			0x02
diff --git a/drivers/renesas/common/emmc/emmc_init.c b/drivers/renesas/common/emmc/emmc_init.c
index 354aa3c..c0ec600 100644
--- a/drivers/renesas/common/emmc/emmc_init.c
+++ b/drivers/renesas/common/emmc/emmc_init.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,6 +14,7 @@
 #include "emmc_registers.h"
 #include "emmc_def.h"
 #include "rcar_private.h"
+#include "cpg_registers.h"
 
 st_mmc_base mmc_drv_obj;
 
@@ -87,11 +88,11 @@
 	SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR);	/* all interrupt disable */
 	SETR_32(SD_CLK_CTRL, 0x00000000U);	/* MMC clock stop */
 
-	dataL = mmio_read_32(CPG_SMSTPCR3);
+	dataL = mmio_read_32(SMSTPCR3);
 	if ((dataL & CPG_MSTP_MMC) == 0U) {
 		dataL |= (CPG_MSTP_MMC);
 		mmio_write_32(CPG_CPGWPR, (~dataL));
-		mmio_write_32(CPG_SMSTPCR3, dataL);
+		mmio_write_32(SMSTPCR3, dataL);
 	}
 
 	return result;
@@ -100,7 +101,7 @@
 static EMMC_ERROR_CODE emmc_dev_init(void)
 {
 	/* Enable clock supply to eMMC. */
-	mstpcr_write(CPG_SMSTPCR3, CPG_MSTPSR3, CPG_MSTP_MMC);
+	mstpcr_write(SMSTPCR3, CPG_MSTPSR3, CPG_MSTP_MMC);
 
 	/* Set SD clock */
 	mmio_write_32(CPG_CPGWPR, ~((uint32_t) (BIT9 | BIT0)));	/* SD phy 200MHz */
diff --git a/drivers/renesas/common/emmc/emmc_registers.h b/drivers/renesas/common/emmc/emmc_registers.h
index 7fae5e4..67d285d 100644
--- a/drivers/renesas/common/emmc/emmc_registers.h
+++ b/drivers/renesas/common/emmc/emmc_registers.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -50,19 +50,6 @@
 #define BIT30	(0x40000000U)
 #define BIT31	(0x80000000U)
 
-/* Clock Pulse Generator (CPG) registers */
-#define CPG_BASE	(0xE6150000U)
-/* Module stop status register 3 */
-#define CPG_MSTPSR3	(CPG_BASE + 0x0048U)
-/* System module stop control register 3 */
-#define CPG_SMSTPCR3	(CPG_BASE + 0x013CU)
-/* SDHI2 clock frequency control register */
-#define CPG_SD2CKCR	(CPG_BASE + 0x0268U)
-/* SDHI3 clock frequency control register */
-#define CPG_SD3CKCR	(CPG_BASE + 0x026CU)
-/* CPG Write Protect Register */
-#define CPG_CPGWPR	(CPG_BASE + 0x0900U)
-
 #if USE_MMC_CH == MMC_CH0
 #define CPG_SDxCKCR		(CPG_SD2CKCR)	/* SDHI2/MMC0 */
 #else /* USE_MMC_CH == MMC_CH0 */
diff --git a/drivers/renesas/common/iic_dvfs/iic_dvfs.c b/drivers/renesas/common/iic_dvfs/iic_dvfs.c
index e1c9a5b..bf80697 100644
--- a/drivers/renesas/common/iic_dvfs/iic_dvfs.c
+++ b/drivers/renesas/common/iic_dvfs/iic_dvfs.c
@@ -517,7 +517,7 @@
 	uint32_t err = 0U;
 
 	mstpcr_write(SCMSTPCR9, CPG_MSTPSR9, CPG_BIT_SMSTPCR9_DVFS);
-	mmio_write_8(IIC_DVFS_REG_ICCR, 0U);
+	mmio_write_8(IIC_DVFS_REG_ICCR, 1U);
 again:
 	switch (state) {
 	case DVFS_START:
@@ -557,7 +557,7 @@
 	uint32_t err = 0U;
 
 	mstpcr_write(SCMSTPCR9, CPG_MSTPSR9, CPG_BIT_SMSTPCR9_DVFS);
-	mmio_write_8(IIC_DVFS_REG_ICCR, 0U);
+	mmio_write_8(IIC_DVFS_REG_ICCR, 1U);
 again:
 	switch (state) {
 	case DVFS_START:
diff --git a/drivers/renesas/common/io/io_rcar.c b/drivers/renesas/common/io/io_rcar.c
index c3e8319..17d7aaa 100644
--- a/drivers/renesas/common/io/io_rcar.c
+++ b/drivers/renesas/common/io/io_rcar.c
@@ -151,6 +151,9 @@
 	return -EINVAL;
 }
 
+#define MFISBTSTSR			(0xE6260604U)
+#define MFISBTSTSR_BOOT_PARTITION	(0x00000010U)
+
 static int32_t file_to_offset(const int32_t name, uintptr_t *offset,
 			      uint32_t *cert, uint32_t *no_load,
 			      uintptr_t *partition)
@@ -169,6 +172,9 @@
 		}
 
 		*offset = rcar_image_header[addr];
+
+		if (mmio_read_32(MFISBTSTSR) & MFISBTSTSR_BOOT_PARTITION)
+			*offset += 0x800000;
 		*cert = RCAR_CERT_SIZE;
 		*cert *= RCAR_ATTR_GET_CERTOFF(name_offset[i].attr);
 		*cert += RCAR_SDRAM_certESS;
diff --git a/drivers/renesas/common/pwrc/pwrc.c b/drivers/renesas/common/pwrc/pwrc.c
index c0f015f..4ebf049 100644
--- a/drivers/renesas/common/pwrc/pwrc.c
+++ b/drivers/renesas/common/pwrc/pwrc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -20,6 +20,7 @@
 #include "pwrc.h"
 #include "rcar_def.h"
 #include "rcar_private.h"
+#include "cpg_registers.h"
 
 /*
  * Someday there will be a generic power controller api. At the moment each
@@ -43,6 +44,7 @@
 #define CPU_PWR_OFF				(0x00000003U)
 #define RCAR_PSTR_MASK				(0x00000003U)
 #define ST_ALL_STANDBY				(0x00003333U)
+#define SYSCEXTMASK_EXTMSK0			(0x00000001U)
 /* Suspend to ram	*/
 #define DBSC4_REG_BASE				(0xE6790000U)
 #define DBSC4_REG_DBSYSCNT0			(DBSC4_REG_BASE + 0x0100U)
@@ -190,6 +192,8 @@
 {
 	uintptr_t reg_pwrsr, reg_cpumcr, reg_pwron, reg_pwrer;
 	uint32_t c, sysc_reg_bit;
+	uint32_t lsi_product;
+	uint32_t lsi_cut;
 
 	c = rcar_pwrc_get_mpidr_cluster(mpidr);
 	reg_cpumcr = IS_CA57(c) ? RCAR_CA57CPUCMCR : RCAR_CA53CPUCMCR;
@@ -204,6 +208,17 @@
 	if (mmio_read_32(reg_cpumcr) != 0)
 		mmio_write_32(reg_cpumcr, 0);
 
+	lsi_product = mmio_read_32((uintptr_t)RCAR_PRR);
+	lsi_cut = lsi_product & PRR_CUT_MASK;
+	lsi_product &= PRR_PRODUCT_MASK;
+
+	if ((lsi_product == PRR_PRODUCT_M3 && lsi_cut >= PRR_PRODUCT_30) ||
+	    lsi_product == PRR_PRODUCT_H3 ||
+	    lsi_product == PRR_PRODUCT_M3N ||
+	    lsi_product == PRR_PRODUCT_E3) {
+		mmio_setbits_32(RCAR_SYSCEXTMASK, SYSCEXTMASK_EXTMSK0);
+	}
+
 	mmio_setbits_32(RCAR_SYSCIER, sysc_reg_bit);
 	mmio_setbits_32(RCAR_SYSCIMR, sysc_reg_bit);
 
@@ -215,7 +230,15 @@
 
 	while ((mmio_read_32(RCAR_SYSCISR) & sysc_reg_bit) == 0)
 		;
-	mmio_write_32(RCAR_SYSCISR, sysc_reg_bit);
+	mmio_write_32(RCAR_SYSCISCR, sysc_reg_bit);
+
+	if ((lsi_product == PRR_PRODUCT_M3 && lsi_cut >= PRR_PRODUCT_30) ||
+	    lsi_product == PRR_PRODUCT_H3 ||
+	    lsi_product == PRR_PRODUCT_M3N ||
+	    lsi_product == PRR_PRODUCT_E3) {
+		mmio_clrbits_32(RCAR_SYSCEXTMASK, SYSCEXTMASK_EXTMSK0);
+	}
+
 	while ((mmio_read_32(reg_pwrsr) & STATUS_PWRUP) == 0)
 		;
 }
@@ -238,7 +261,7 @@
 	scu_power_up(mpidr);
 	cpu = mpidr & MPIDR_CPU_MASK;
 	on_data = 1 << cpu;
-	mmio_write_32(RCAR_CPGWPR, ~on_data);
+	mmio_write_32(CPG_CPGWPR, ~on_data);
 	mmio_write_32(on_reg, on_data);
 	mmio_write_32(res_reg, res_data & (~(1 << (3 - cpu))));
 
@@ -260,7 +283,7 @@
 	if (read_mpidr_el1() != mpidr)
 		panic();
 
-	mmio_write_32(RCAR_CPGWPR, ~CPU_PWR_OFF);
+	mmio_write_32(CPG_CPGWPR, ~CPU_PWR_OFF);
 	mmio_write_32(reg + cpu * 0x0010, CPU_PWR_OFF);
 
 	rcar_lock_release();
diff --git a/drivers/renesas/common/scif/scif.S b/drivers/renesas/common/scif/scif.S
index beb8dd8..72b5b4b 100644
--- a/drivers/renesas/common/scif/scif.S
+++ b/drivers/renesas/common/scif/scif.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -79,7 +79,7 @@
 					 SCSMR_STOP_1 +		\
 					 SCSMR_CKS_DIV1)
 #define SCBRR_115200BPS		(17)
-#define SCBRR_115200BPSON	(16)
+#define SCBRR_115200BPS_D3_SSCG	(16)
 #define SCBRR_115200BPS_E3_SSCG	(15)
 #define SCBRR_230400BPS		(8)
 
@@ -216,26 +216,38 @@
 	and	w1, w1, #PRR_PRODUCT_MASK
 	mov	w2, #PRR_PRODUCT_D3
 	cmp	w1, w2
-	beq	4f
+	beq	5f
 	and	w1, w1, #PRR_PRODUCT_MASK
 	mov	w2, #PRR_PRODUCT_E3
 	cmp	w1, w2
-	bne	5f
+	bne	4f
 
+	/* When SSCG(MD12) on (E3) */
 	ldr	x1, =RST_MODEMR
 	ldr	w1, [x1]
 	and	w1, w1, #MODEMR_MD12
 	mov	w2, #MODEMR_MD12
 	cmp	w1, w2
-	bne	5f
+	bne	4f
 
+	/* When SSCG(MD12) on (E3) */
 	mov	w1, #SCBRR_115200BPS_E3_SSCG
 	b	2f
 5:
-	mov	w1, #SCBRR_115200BPS
+	/* In case of D3 */
+	ldr	x1, =RST_MODEMR
+	ldr	w1, [x1]
+	and	w1, w1, #MODEMR_MD12
+	mov	w2, #MODEMR_MD12
+	cmp	w1, w2
+	bne	4f
+
+	/* When SSCG(MD12) on (D3) */
+	mov	w1, #SCBRR_115200BPS_D3_SSCG
 	b	2f
 4:
-	mov	w1, #SCBRR_115200BPSON
+	/* In case of H3/M3/M3N or when SSCG(MD12) is off in E3/D3 */
+	mov	w1, #SCBRR_115200BPS
 	b	2f
 3:
 	mov	w1, #SCBRR_230400BPS
diff --git a/drivers/renesas/common/watchdog/swdt.c b/drivers/renesas/common/watchdog/swdt.c
index 1a351ca..29ef6f4 100644
--- a/drivers/renesas/common/watchdog/swdt.c
+++ b/drivers/renesas/common/watchdog/swdt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -78,7 +78,7 @@
 void rcar_swdt_init(void)
 {
 	uint32_t rmsk, sr;
-#if (RCAR_LSI != RCAR_E3) && (RCAR_LSI != RZ_G2E)
+#if (RCAR_LSI != RCAR_E3) && (RCAR_LSI != RCAR_D3) && (RCAR_LSI != RZ_G2E)
 	uint32_t reg, val, product_cut, chk_data;
 
 	reg = mmio_read_32(RCAR_PRR);
@@ -96,6 +96,8 @@
 
 #if (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RZ_G2E)
 	mmio_write_32(SWDT_WTCNT, WTCNT_UPPER_BYTE | WTCNT_COUNT_7p81k);
+#elif (RCAR_LSI == RCAR_D3)
+	mmio_write_32(SWDT_WTCNT, WTCNT_UPPER_BYTE | WTCNT_COUNT_8p13k);
 #else
 	val = WTCNT_UPPER_BYTE;
 
diff --git a/drivers/renesas/rcar/board/board.c b/drivers/renesas/rcar/board/board.c
index cd194ff..dbbaed6 100644
--- a/drivers/renesas/rcar/board/board.c
+++ b/drivers/renesas/rcar/board/board.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights
  * reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -30,9 +30,9 @@
 #define BOARD_CODE_SHIFT	(0x03)
 #define BOARD_ID_UNKNOWN	(0xFF)
 
-#define SXS_ID	{ 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
+#define SXS_ID	{ 0x10U, 0x11U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
 #define SX_ID	{ 0x10U, 0x11U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
-#define SKP_ID	{ 0x10U, 0x10U, 0x20U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
+#define SKP_ID	{ 0x10U, 0x10U, 0x20U, 0x21U, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
 #define SK_ID	{ 0x10U, 0x30U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
 #define EB4_ID	{ 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
 #define EB_ID	{ 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
diff --git a/drivers/scmi-msg/common.h b/drivers/scmi-msg/common.h
index ef5953b..62f3087 100644
--- a/drivers/scmi-msg/common.h
+++ b/drivers/scmi-msg/common.h
@@ -13,6 +13,7 @@
 
 #include "base.h"
 #include "clock.h"
+#include "power_domain.h"
 #include "reset_domain.h"
 
 #define SCMI_VERSION			0x20000U
@@ -111,6 +112,13 @@
 scmi_msg_handler_t scmi_msg_get_rstd_handler(struct scmi_msg *msg);
 
 /*
+ * scmi_msg_get_pd_handler - Return a handler for a power domain message
+ * @msg - message to process
+ * Return a function handler for the message or NULL
+ */
+scmi_msg_handler_t scmi_msg_get_pd_handler(struct scmi_msg *msg);
+
+/*
  * Process Read, process and write response for input SCMI message
  *
  * @msg: SCMI message context
diff --git a/drivers/scmi-msg/entry.c b/drivers/scmi-msg/entry.c
index ea3efa2..3537fbe 100644
--- a/drivers/scmi-msg/entry.c
+++ b/drivers/scmi-msg/entry.c
@@ -11,6 +11,31 @@
 
 #include "common.h"
 
+#pragma weak scmi_msg_get_clock_handler
+#pragma weak scmi_msg_get_rstd_handler
+#pragma weak scmi_msg_get_pd_handler
+#pragma weak scmi_msg_get_voltage_handler
+
+scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg __unused)
+{
+	return NULL;
+}
+
+scmi_msg_handler_t scmi_msg_get_rstd_handler(struct scmi_msg *msg __unused)
+{
+	return NULL;
+}
+
+scmi_msg_handler_t scmi_msg_get_pd_handler(struct scmi_msg *msg __unused)
+{
+	return NULL;
+}
+
+scmi_msg_handler_t scmi_msg_get_voltage_handler(struct scmi_msg *msg __unused)
+{
+	return NULL;
+}
+
 void scmi_status_response(struct scmi_msg *msg, int32_t status)
 {
 	assert(msg->out && msg->out_size >= sizeof(int32_t));
@@ -47,6 +72,9 @@
 	case SCMI_PROTOCOL_ID_RESET_DOMAIN:
 		handler = scmi_msg_get_rstd_handler(msg);
 		break;
+	case SCMI_PROTOCOL_ID_POWER_DOMAIN:
+		handler = scmi_msg_get_pd_handler(msg);
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/scmi-msg/power_domain.c b/drivers/scmi-msg/power_domain.c
new file mode 100644
index 0000000..c4e1289
--- /dev/null
+++ b/drivers/scmi-msg/power_domain.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Linaro Limited
+ */
+#include <cdefs.h>
+#include <string.h>
+
+#include <drivers/scmi-msg.h>
+#include <drivers/scmi.h>
+#include <lib/utils_def.h>
+
+#include "common.h"
+
+#pragma weak plat_scmi_pd_count
+#pragma weak plat_scmi_pd_get_name
+#pragma weak plat_scmi_pd_get_state
+#pragma weak plat_scmi_pd_set_state
+#pragma weak plat_scmi_pd_statistics
+#pragma weak plat_scmi_pd_get_attributes
+
+static bool message_id_is_supported(size_t message_id);
+
+size_t plat_scmi_pd_count(unsigned int agent_id __unused)
+{
+	return 0U;
+}
+
+const char *plat_scmi_pd_get_name(unsigned int agent_id __unused,
+				  unsigned int pd_id __unused)
+{
+	return NULL;
+}
+
+unsigned int plat_scmi_pd_statistics(unsigned int agent_id __unused,
+				     unsigned long *pd_id __unused)
+{
+	return 0U;
+}
+
+unsigned int plat_scmi_pd_get_attributes(unsigned int agent_id __unused,
+					 unsigned int pd_id __unused)
+{
+	return 0U;
+}
+
+unsigned int plat_scmi_pd_get_state(unsigned int agent_id __unused,
+				    unsigned int pd_id __unused)
+{
+	return 0U;
+}
+
+int32_t plat_scmi_pd_set_state(unsigned int agent_id __unused,
+			       unsigned int flags __unused,
+			       unsigned int pd_id __unused,
+			       unsigned int state __unused)
+{
+	return SCMI_NOT_SUPPORTED;
+}
+
+static void report_version(struct scmi_msg *msg)
+{
+	struct scmi_protocol_version_p2a return_values = {
+		.status = SCMI_SUCCESS,
+		.version = SCMI_PROTOCOL_VERSION_PD,
+	};
+
+	if (msg->in_size != 0) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void report_attributes(struct scmi_msg *msg)
+{
+	unsigned long addr = 0UL;
+	unsigned int len;
+
+	struct scmi_protocol_attributes_p2a_pd return_values = {
+		.status = SCMI_SUCCESS,
+	};
+
+	if (msg->in_size != 0) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	return_values.attributes = plat_scmi_pd_count(msg->agent_id);
+	len = plat_scmi_pd_statistics(msg->agent_id, &addr);
+	if (len != 0U) {
+		return_values.statistics_addr_low = (unsigned int)addr;
+		return_values.statistics_addr_high = (uint32_t)(addr >> 32);
+		return_values.statistics_len = len;
+	}
+
+	scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void report_message_attributes(struct scmi_msg *msg)
+{
+	struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in;
+	struct scmi_protocol_message_attributes_p2a return_values = {
+		.status = SCMI_SUCCESS,
+		/* For this protocol, attributes shall be zero */
+		.attributes = 0U,
+	};
+
+	if (msg->in_size != sizeof(*in_args)) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	if (!message_id_is_supported(in_args->message_id)) {
+		scmi_status_response(msg, SCMI_NOT_FOUND);
+		return;
+	}
+
+	scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void scmi_pd_attributes(struct scmi_msg *msg)
+{
+	const struct scmi_pd_attributes_a2p *in_args = (void *)msg->in;
+	struct scmi_pd_attributes_p2a return_values = {
+		.status = SCMI_SUCCESS,
+	};
+	const char *name = NULL;
+	unsigned int pd_id = 0U;
+
+	if (msg->in_size != sizeof(*in_args)) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	pd_id = SPECULATION_SAFE_VALUE(in_args->pd_id);
+
+	if (pd_id >= plat_scmi_pd_count(msg->agent_id)) {
+		scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
+		return;
+	}
+
+	name = plat_scmi_pd_get_name(msg->agent_id, pd_id);
+	if (name == NULL) {
+		scmi_status_response(msg, SCMI_NOT_FOUND);
+		return;
+	}
+
+	COPY_NAME_IDENTIFIER(return_values.pd_name, name);
+
+	return_values.attributes = plat_scmi_pd_get_attributes(msg->agent_id, pd_id);
+
+	scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void scmi_pd_state_get(struct scmi_msg *msg)
+{
+	const struct scmi_pd_state_get_a2p *in_args = (void *)msg->in;
+	unsigned int state = 0U;
+	struct scmi_pd_state_get_p2a return_values = {
+		.status = SCMI_SUCCESS,
+	};
+	unsigned int pd_id = 0U;
+
+	if (msg->in_size != sizeof(*in_args)) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	pd_id = SPECULATION_SAFE_VALUE(in_args->pd_id);
+
+	if (pd_id >= plat_scmi_pd_count(msg->agent_id)) {
+		scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
+		return;
+	}
+
+	state = plat_scmi_pd_get_state(msg->agent_id, pd_id);
+
+	return_values.power_state = state;
+
+	scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void scmi_pd_state_set(struct scmi_msg *msg)
+{
+	const struct scmi_pd_state_set_a2p *in_args = (void *)msg->in;
+	unsigned int flags = 0U;
+	int32_t status = 0;
+	unsigned int pd_id = 0U;
+	unsigned int state = 0U;
+
+	if (msg->in_size != sizeof(*in_args)) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	pd_id = SPECULATION_SAFE_VALUE(in_args->pd_id);
+
+	if (pd_id >= plat_scmi_pd_count(msg->agent_id)) {
+		scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
+		return;
+	}
+
+	flags = SPECULATION_SAFE_VALUE(in_args->flags);
+	state = SPECULATION_SAFE_VALUE(in_args->power_state);
+
+	status = plat_scmi_pd_set_state(msg->agent_id, flags, pd_id, state);
+
+	scmi_status_response(msg, status);
+}
+
+static const scmi_msg_handler_t scmi_pd_handler_table[] = {
+	[SCMI_PROTOCOL_VERSION] = report_version,
+	[SCMI_PROTOCOL_ATTRIBUTES] = report_attributes,
+	[SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes,
+	[SCMI_PD_ATTRIBUTES] = scmi_pd_attributes,
+	[SCMI_PD_STATE_SET] = scmi_pd_state_set,
+	[SCMI_PD_STATE_GET] = scmi_pd_state_get,
+};
+
+static bool message_id_is_supported(size_t message_id)
+{
+	return (message_id < ARRAY_SIZE(scmi_pd_handler_table)) &&
+	       (scmi_pd_handler_table[message_id] != NULL);
+}
+
+scmi_msg_handler_t scmi_msg_get_pd_handler(struct scmi_msg *msg)
+{
+	const size_t array_size = ARRAY_SIZE(scmi_pd_handler_table);
+	unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id);
+
+	if (message_id >= array_size) {
+		VERBOSE("pd handle not found %u", msg->message_id);
+		return NULL;
+	}
+
+	return scmi_pd_handler_table[message_id];
+}
diff --git a/drivers/scmi-msg/power_domain.h b/drivers/scmi-msg/power_domain.h
new file mode 100644
index 0000000..48551fd
--- /dev/null
+++ b/drivers/scmi-msg/power_domain.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright 2021 NXP
+ */
+
+#ifndef SCMI_MSG_PD_H
+#define SCMI_MSG_PD_H
+
+#include <stdint.h>
+
+#include <lib/utils_def.h>
+
+#define SCMI_PROTOCOL_VERSION_PD	0x21000U
+
+/*
+ * Identifiers of the SCMI POWER DOMAIN Protocol commands
+ */
+enum scmi_pd_command_id {
+	SCMI_PD_ATTRIBUTES = 0x003,
+	SCMI_PD_STATE_SET = 0x004,
+	SCMI_PD_STATE_GET = 0x005,
+};
+
+/* Protocol attributes */
+struct scmi_pd_attributes_a2p {
+	uint32_t pd_id;
+};
+
+struct scmi_protocol_attributes_p2a_pd {
+	int32_t status;
+	uint32_t attributes;
+	uint32_t statistics_addr_low;
+	uint32_t statistics_addr_high;
+	uint32_t statistics_len;
+};
+
+#define SCMI_PD_NAME_LENGTH_MAX	16U
+
+struct scmi_pd_attributes_p2a {
+	int32_t status;
+	uint32_t attributes;
+	char pd_name[SCMI_PD_NAME_LENGTH_MAX];
+};
+
+/*
+ * Power Domain State Get
+ */
+
+struct scmi_pd_state_get_a2p {
+	uint32_t pd_id;
+};
+
+struct scmi_pd_state_get_p2a {
+	int32_t status;
+	uint32_t power_state;
+};
+
+/*
+ * Power domain State Set
+ */
+
+struct scmi_pd_state_set_a2p {
+	uint32_t flags;
+	uint32_t pd_id;
+	uint32_t power_state;
+};
+
+struct scmi_pd_state_set_p2a {
+	int32_t status;
+};
+
+#endif /* SCMI_MSG_PD_H */
diff --git a/drivers/scmi-msg/smt.c b/drivers/scmi-msg/smt.c
index b08ee06..9b079c7 100644
--- a/drivers/scmi-msg/smt.c
+++ b/drivers/scmi-msg/smt.c
@@ -44,12 +44,12 @@
 	assert_scmi_message_max_length_fits_in_smt_buffer_slot);
 
 /* Flag set in smt_header::status when SMT does not contain pending message */
-#define SMT_STATUS_FREE			BIT(0)
+#define SMT_STATUS_FREE			BIT_32(0)
 /* Flag set in smt_header::status when SMT reports an error */
-#define SMT_STATUS_ERROR		BIT(1)
+#define SMT_STATUS_ERROR		BIT_32(1)
 
 /* Flag set in smt_header::flags when SMT uses interrupts */
-#define SMT_FLAG_INTR_ENABLED		BIT(1)
+#define SMT_FLAG_INTR_ENABLED		BIT_32(1)
 
 /* Bit fields packed in smt_header::message_header */
 #define SMT_MSG_ID_MASK			GENMASK_32(7, 0)
@@ -133,7 +133,7 @@
 			  sizeof(smt_hdr->message_header);
 
 	if (in_payload_size > SCMI_PLAYLOAD_MAX) {
-		VERBOSE("SCMI payload too big %u", in_payload_size);
+		VERBOSE("SCMI payload too big %zu", in_payload_size);
 		goto out;
 	}
 
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
index 6ada96a..80b6408 100644
--- a/drivers/st/clk/stm32mp1_clk.c
+++ b/drivers/st/clk/stm32mp1_clk.c
@@ -56,6 +56,7 @@
 	_HSI_KER = NB_OSC,
 	_HSE_KER,
 	_HSE_KER_DIV2,
+	_HSE_RTC,
 	_CSI_KER,
 	_PLL1_P,
 	_PLL1_Q,
@@ -107,7 +108,7 @@
 	_USBPHY_SEL,
 	_USBO_SEL,
 	_MPU_SEL,
-	_PER_SEL,
+	_CKPER_SEL,
 	_RTC_SEL,
 	_PARENT_SEL_NB,
 	_UNKNOWN_SEL = 0xff,
@@ -125,6 +126,7 @@
 	[_HSI_KER] = CK_HSI,
 	[_HSE_KER] = CK_HSE,
 	[_HSE_KER_DIV2] = CK_HSE_DIV2,
+	[_HSE_RTC] = _UNKNOWN_ID,
 	[_CSI_KER] = CK_CSI,
 	[_PLL1_P] = PLL1_P,
 	[_PLL1_Q] = PLL1_Q,
@@ -490,7 +492,7 @@
 };
 
 static const uint8_t rtc_parents[] = {
-	_UNKNOWN_ID, _LSE, _LSI, _HSE
+	_UNKNOWN_ID, _LSE, _LSI, _HSE_RTC
 };
 
 static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
@@ -502,7 +504,7 @@
 	_CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents),
 	_CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents),
 	_CLK_PARENT_SEL(MPU, RCC_MPCKSELR, mpu_parents),
-	_CLK_PARENT_SEL(PER, RCC_CPERCKSELR, per_parents),
+	_CLK_PARENT_SEL(CKPER, RCC_CPERCKSELR, per_parents),
 	_CLK_PARENT_SEL(RTC, RCC_BDCR, rtc_parents),
 	_CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents),
 	_CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents),
@@ -587,6 +589,7 @@
 	[_HSI_KER] = "HSI_KER",
 	[_HSE_KER] = "HSE_KER",
 	[_HSE_KER_DIV2] = "HSE_KER_DIV2",
+	[_HSE_RTC] = "HSE_RTC",
 	[_CSI_KER] = "CSI_KER",
 	[_PLL1_P] = "PLL1_P",
 	[_PLL1_Q] = "PLL1_Q",
@@ -969,6 +972,10 @@
 	case _HSE_KER_DIV2:
 		clock = stm32mp1_clk_get_fixed(_HSE) >> 1;
 		break;
+	case _HSE_RTC:
+		clock = stm32mp1_clk_get_fixed(_HSE);
+		clock /= (mmio_read_32(rcc_base + RCC_RTCDIVR) & RCC_DIVR_DIV_MASK) + 1U;
+		break;
 	case _LSI:
 		clock = stm32mp1_clk_get_fixed(_LSI);
 		break;
@@ -1652,7 +1659,7 @@
 	    (clksrc != (uint32_t)CLK_RTC_DISABLED)) {
 		mmio_clrsetbits_32(address,
 				   RCC_BDCR_RTCSRC_MASK,
-				   clksrc << RCC_BDCR_RTCSRC_SHIFT);
+				   (clksrc & RCC_SELR_SRC_MASK) << RCC_BDCR_RTCSRC_SHIFT);
 
 		mmio_setbits_32(address, RCC_BDCR_RTCCKEN);
 	}
@@ -2152,6 +2159,7 @@
 	case _HSE:
 	case _HSE_KER:
 	case _HSE_KER_DIV2:
+	case _HSE_RTC:
 	case _LSE:
 		break;
 
@@ -2210,6 +2218,7 @@
 		DDRC2, DDRC2LP,
 		DDRCAPB, DDRPHYCAPB, DDRPHYCAPBLP,
 		DDRPHYC, DDRPHYCLP,
+		RTCAPB,
 		TZC1, TZC2,
 		TZPC,
 		STGEN_K,
@@ -2218,10 +2227,6 @@
 	for (idx = 0U; idx < ARRAY_SIZE(secure_enable); idx++) {
 		stm32mp_clk_enable(secure_enable[idx]);
 	}
-
-	if (!stm32mp_is_single_core()) {
-		stm32mp1_clk_enable_secure(RTCAPB);
-	}
 }
 
 int stm32mp1_clk_probe(void)
diff --git a/drivers/st/clk/stm32mp_clkfunc.c b/drivers/st/clk/stm32mp_clkfunc.c
index 8333f6d..2101171 100644
--- a/drivers/st/clk/stm32mp_clkfunc.c
+++ b/drivers/st/clk/stm32mp_clkfunc.c
@@ -161,7 +161,7 @@
  * @param fdt: Device tree reference
  * @return: Node offset or a negative value on error
  */
-int fdt_get_rcc_node(void *fdt)
+static int fdt_get_rcc_node(void *fdt)
 {
 	return fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT);
 }
diff --git a/drivers/st/uart/aarch32/stm32_console.S b/drivers/st/uart/aarch32/stm32_console.S
index 686b18b..2b8879a 100644
--- a/drivers/st/uart/aarch32/stm32_console.S
+++ b/drivers/st/uart/aarch32/stm32_console.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -45,7 +45,12 @@
 	/* Check the input base address */
 	cmp	r0, #0
 	beq	core_init_fail
-#if defined(IMAGE_BL2)
+#if !defined(IMAGE_BL2)
+	/* Skip UART initialization if it is already enabled */
+	ldr	r3, [r0, #USART_CR1]
+	ands	r3, r3, #USART_CR1_UE
+	bne	1f
+#endif /* IMAGE_BL2 */
 	/* Check baud rate and uart clock for sanity */
 	cmp	r1, #0
 	beq	core_init_fail
@@ -78,7 +83,7 @@
 	ldr	r3, [r0, #USART_ISR]
 	tst	r3, #USART_ISR_TEACK
 	beq	teack_loop
-#endif /* IMAGE_BL2 */
+1:
 	mov	r0, #1
 	bx	lr
 core_init_fail:
diff --git a/fdts/fvp-base-gicv3-psci-common.dtsi b/fdts/fvp-base-gicv3-psci-common.dtsi
index b6753de..3cb613f 100644
--- a/fdts/fvp-base-gicv3-psci-common.dtsi
+++ b/fdts/fvp-base-gicv3-psci-common.dtsi
@@ -24,7 +24,11 @@
 	#address-cells = <2>;
 	#size-cells = <2>;
 
-	chosen { };
+#if (ENABLE_RME == 1)
+	chosen { bootargs = "mem=1G console=ttyAMA0 earlycon=pl011,0x1c090000 root=/dev/vda ip=on";};
+#else
+	chosen {};
+#endif
 
 	aliases {
 		serial0 = &v2m_serial0;
@@ -135,8 +139,13 @@
 
 	memory@80000000 {
 		device_type = "memory";
+#if (ENABLE_RME == 1)
+		reg = <0x00000000 0x80000000 0 0x7C000000>,
+		      <0x00000008 0x80000000 0 0x80000000>;
+#else
 		reg = <0x00000000 0x80000000 0 0x7F000000>,
 		      <0x00000008 0x80000000 0 0x80000000>;
+#endif
 	};
 
 	gic: interrupt-controller@2f000000 {
diff --git a/fdts/juno-ethosn.dtsi b/fdts/juno-ethosn.dtsi
index 87ab378..e2f3355 100644
--- a/fdts/juno-ethosn.dtsi
+++ b/fdts/juno-ethosn.dtsi
@@ -4,19 +4,21 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+/*
+ * For examples of multi-core and multi-device NPU, refer to the examples given in the
+ * Arm Ethos-N NPU driver stack.
+ * https://github.com/ARM-software/ethos-n-driver-stack
+ */
+
 / {
 	#address-cells = <2>;
 	#size-cells = <2>;
 
-	ethosn: ethosn@6f300000 {
+	ethosn0: ethosn@6f300000 {
 		compatible = "ethosn";
 		reg = <0 0x6f300000 0 0x00100000>;
 		status = "okay";
 
-		/*
-		 * Single-core NPU. For multi-core NPU, additional core nodes
-		 * and reg values must be added.
-		 */
 		core0 {
 			compatible = "ethosn-core";
 			status = "okay";
diff --git a/fdts/stm32mp15-bl2.dtsi b/fdts/stm32mp15-bl2.dtsi
new file mode 100644
index 0000000..da95b25
--- /dev/null
+++ b/fdts/stm32mp15-bl2.dtsi
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2020-2021 - All Rights Reserved
+ */
+
+/ {
+	cpus {
+		/delete-node/ cpu@1;
+	};
+
+	/delete-node/ psci;
+
+	soc {
+		/delete-node/ timer@40006000;
+		/delete-node/ timer@44006000;
+		/delete-node/ pwr_mcu@50001014;
+		/delete-node/ cryp@54001000;
+		/delete-node/ rng@54003000;
+		/delete-node/ spi@5c001000;
+		/delete-node/ rtc@5c004000;
+		/delete-node/ etzpc@5c007000;
+		/delete-node/ stgen@5c008000;
+		/delete-node/ i2c@5c009000;
+		/delete-node/ tamp@5c00a000;
+
+		pin-controller@50002000 {
+			/delete-node/ rtc-out2-rmp-pins-0;
+		};
+	};
+
+#if !STM32MP_USE_STM32IMAGE
+	/*
+	 * UUID's here are UUID RFC 4122 compliant meaning fieds are stored in
+	 * network order (big endian)
+	 */
+
+	st-io_policies {
+		fip-handles {
+			compatible = "st,io-fip-handle";
+			fw_cfg_uuid = "5807e16a-8459-47be-8ed5-648e8dddab0e";
+			bl32_uuid = "05d0e189-53dc-1347-8d2b-500a4b7a3e38";
+			bl32_extra1_uuid = "0b70c29b-2a5a-7840-9f65-0a5682738288";
+			bl32_extra2_uuid = "8ea87bb1-cfa2-3f4d-85fd-e7bba50220d9";
+			bl33_uuid = "d6d0eea7-fcea-d54b-9782-9934f234b6e4";
+			hw_cfg_uuid = "08b8f1d9-c9cf-9349-a962-6fbc6b7265cc";
+			tos_fw_cfg_uuid = "26257c1a-dbc6-7f47-8d96-c4c4b0248021";
+			nt_fw_cfg_uuid = "28da9815-93e8-7e44-ac66-1aaf801550f9";
+		};
+	};
+#endif /* !STM32MP_USE_STM32IMAGE */
+};
diff --git a/fdts/stm32mp15-bl32.dtsi b/fdts/stm32mp15-bl32.dtsi
new file mode 100644
index 0000000..f005d56
--- /dev/null
+++ b/fdts/stm32mp15-bl32.dtsi
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2020-2021 - All Rights Reserved
+ */
+
+/ {
+	aliases {
+		/delete-property/ mmc0;
+		/delete-property/ mmc1;
+	};
+
+	cpus {
+		/delete-node/ cpu@1;
+	};
+
+	/delete-node/ psci;
+
+	soc {
+		/delete-node/ usb-otg@49000000;
+		/delete-node/ hash@54002000;
+		/delete-node/ memory-controller@58002000;
+		/delete-node/ spi@58003000;
+		/delete-node/ sdmmc@58005000;
+		/delete-node/ sdmmc@58007000;
+		/delete-node/ usbphyc@5a006000;
+		/delete-node/ spi@5c001000;
+		/delete-node/ stgen@5c008000;
+		/delete-node/ i2c@5c009000;
+
+		pin-controller@50002000 {
+			/delete-node/ fmc-0;
+			/delete-node/ qspi-clk-0;
+			/delete-node/ qspi-bk1-0;
+			/delete-node/ qspi-bk2-0;
+			/delete-node/ sdmmc1-b4-0;
+			/delete-node/ sdmmc1-dir-0;
+			/delete-node/ sdmmc2-b4-0;
+			/delete-node/ sdmmc2-b4-1;
+			/delete-node/ sdmmc2-d47-0;
+			/delete-node/ usbotg_hs-0;
+			/delete-node/ usbotg-fs-dp-dm-0;
+		};
+	};
+};
diff --git a/fdts/stm32mp15-fw-config.dtsi b/fdts/stm32mp15-fw-config.dtsi
new file mode 100644
index 0000000..8aece28
--- /dev/null
+++ b/fdts/stm32mp15-fw-config.dtsi
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common/tbbr/tbbr_img_def.h>
+#include <dt-bindings/soc/stm32mp15-tzc400.h>
+
+#include <platform_def.h>
+
+#ifndef DDR_SIZE
+#error "DDR_SIZE is not defined"
+#endif
+
+#define DDR_NS_BASE	STM32MP_DDR_BASE
+#ifdef AARCH32_SP_OPTEE
+/* OP-TEE reserved shared memory: located at DDR top */
+#define DDR_SHARE_SIZE	STM32MP_DDR_SHMEM_SIZE
+#define DDR_SHARE_BASE	(STM32MP_DDR_BASE + (DDR_SIZE - DDR_SHARE_SIZE))
+/* OP-TEE secure memory: located right below OP-TEE reserved shared memory */
+#define DDR_SEC_SIZE	STM32MP_DDR_S_SIZE
+#define DDR_SEC_BASE	(DDR_SHARE_BASE - DDR_SEC_SIZE)
+#define DDR_NS_SIZE	(DDR_SEC_BASE - DDR_NS_BASE)
+#else /* !AARCH32_SP_OPTEE */
+#define DDR_NS_SIZE	DDR_SIZE
+#endif /* AARCH32_SP_OPTEE */
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "fconf,dyn_cfg-dtb_registry";
+
+		hw-config {
+			load-address = <0x0 STM32MP_HW_CONFIG_BASE>;
+			max-size = <STM32MP_HW_CONFIG_MAX_SIZE>;
+			id = <HW_CONFIG_ID>;
+		};
+
+		nt_fw {
+			load-address = <0x0 STM32MP_BL33_BASE>;
+			max-size = <STM32MP_BL33_MAX_SIZE>;
+			id = <BL33_IMAGE_ID>;
+		};
+
+#ifdef AARCH32_SP_OPTEE
+		tos_fw {
+			load-address = <0x0 STM32MP_OPTEE_BASE>;
+			max-size = <STM32MP_OPTEE_SIZE>;
+			id = <BL32_IMAGE_ID>;
+		};
+#else
+		tos_fw {
+			load-address = <0x0 STM32MP_BL32_BASE>;
+			max-size = <STM32MP_BL32_SIZE>;
+			id = <BL32_IMAGE_ID>;
+		};
+
+		tos_fw-config {
+			load-address = <0x0 STM32MP_BL32_DTB_BASE>;
+			max-size = <STM32MP_BL32_DTB_SIZE>;
+			id = <TOS_FW_CONFIG_ID>;
+		};
+#endif
+	};
+
+	st-mem-firewall {
+		compatible = "st,mem-firewall";
+#ifdef AARCH32_SP_OPTEE
+		memory-ranges = <
+			DDR_NS_BASE DDR_NS_SIZE TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR
+			DDR_SEC_BASE DDR_SEC_SIZE TZC_REGION_S_RDWR 0
+			DDR_SHARE_BASE DDR_SHARE_SIZE TZC_REGION_S_NONE
+			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID)>;
+#else
+		memory-ranges = <
+			DDR_NS_BASE DDR_NS_SIZE TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR>;
+#endif
+	};
+};
diff --git a/fdts/stm32mp157a-avenger96-fw-config.dts b/fdts/stm32mp157a-avenger96-fw-config.dts
new file mode 100644
index 0000000..2abbe50
--- /dev/null
+++ b/fdts/stm32mp157a-avenger96-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157a-dk1-fw-config.dts b/fdts/stm32mp157a-dk1-fw-config.dts
new file mode 100644
index 0000000..83116d1
--- /dev/null
+++ b/fdts/stm32mp157a-dk1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x20000000 /* 512MB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157a-ed1-fw-config.dts b/fdts/stm32mp157a-ed1-fw-config.dts
new file mode 100644
index 0000000..2abbe50
--- /dev/null
+++ b/fdts/stm32mp157a-ed1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157a-ev1-fw-config.dts b/fdts/stm32mp157a-ev1-fw-config.dts
new file mode 100644
index 0000000..2abbe50
--- /dev/null
+++ b/fdts/stm32mp157a-ev1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157c-dk2-fw-config.dts b/fdts/stm32mp157c-dk2-fw-config.dts
new file mode 100644
index 0000000..83116d1
--- /dev/null
+++ b/fdts/stm32mp157c-dk2-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x20000000 /* 512MB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157c-ed1-fw-config.dts b/fdts/stm32mp157c-ed1-fw-config.dts
new file mode 100644
index 0000000..2abbe50
--- /dev/null
+++ b/fdts/stm32mp157c-ed1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157c-ev1-fw-config.dts b/fdts/stm32mp157c-ev1-fw-config.dts
new file mode 100644
index 0000000..2abbe50
--- /dev/null
+++ b/fdts/stm32mp157c-ev1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157c-lxa-mc1-fw-config.dts b/fdts/stm32mp157c-lxa-mc1-fw-config.dts
new file mode 100644
index 0000000..9ee09e9
--- /dev/null
+++ b/fdts/stm32mp157c-lxa-mc1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x20000000 /* 512MB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157c-odyssey-fw-config.dts b/fdts/stm32mp157c-odyssey-fw-config.dts
new file mode 100644
index 0000000..9ee09e9
--- /dev/null
+++ b/fdts/stm32mp157c-odyssey-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x20000000 /* 512MB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157d-dk1-fw-config.dts b/fdts/stm32mp157d-dk1-fw-config.dts
new file mode 100644
index 0000000..83116d1
--- /dev/null
+++ b/fdts/stm32mp157d-dk1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x20000000 /* 512MB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157d-ed1-fw-config.dts b/fdts/stm32mp157d-ed1-fw-config.dts
new file mode 100644
index 0000000..2abbe50
--- /dev/null
+++ b/fdts/stm32mp157d-ed1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157d-ev1-fw-config.dts b/fdts/stm32mp157d-ev1-fw-config.dts
new file mode 100644
index 0000000..2abbe50
--- /dev/null
+++ b/fdts/stm32mp157d-ev1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157f-dk2-fw-config.dts b/fdts/stm32mp157f-dk2-fw-config.dts
new file mode 100644
index 0000000..83116d1
--- /dev/null
+++ b/fdts/stm32mp157f-dk2-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x20000000 /* 512MB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157f-ed1-fw-config.dts b/fdts/stm32mp157f-ed1-fw-config.dts
new file mode 100644
index 0000000..2abbe50
--- /dev/null
+++ b/fdts/stm32mp157f-ed1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157f-ev1-fw-config.dts b/fdts/stm32mp157f-ev1-fw-config.dts
new file mode 100644
index 0000000..2abbe50
--- /dev/null
+++ b/fdts/stm32mp157f-ev1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/tc0.dts b/fdts/tc.dts
similarity index 99%
rename from fdts/tc0.dts
rename to fdts/tc.dts
index 9051b7b..f66d556 100644
--- a/fdts/tc0.dts
+++ b/fdts/tc.dts
@@ -7,7 +7,7 @@
 /dts-v1/;
 
 / {
-	compatible = "arm,tc0";
+	compatible = "arm,tc";
 	interrupt-parent = <&gic>;
 	#address-cells = <2>;
 	#size-cells = <2>;
diff --git a/include/arch/aarch32/arch.h b/include/arch/aarch32/arch.h
index 54ec009..7221b62 100644
--- a/include/arch/aarch32/arch.h
+++ b/include/arch/aarch32/arch.h
@@ -102,6 +102,16 @@
 /* CSSELR definitions */
 #define LEVEL_SHIFT		U(1)
 
+/* ID_DFR0_EL1 definitions */
+#define ID_DFR0_COPTRC_SHIFT		U(12)
+#define ID_DFR0_COPTRC_MASK		U(0xf)
+#define ID_DFR0_COPTRC_SUPPORTED	U(1)
+#define ID_DFR0_COPTRC_LENGTH		U(4)
+#define ID_DFR0_TRACEFILT_SHIFT		U(28)
+#define ID_DFR0_TRACEFILT_MASK		U(0xf)
+#define ID_DFR0_TRACEFILT_SUPPORTED	U(1)
+#define ID_DFR0_TRACEFILT_LENGTH	U(4)
+
 /* ID_DFR1_EL1 definitions */
 #define ID_DFR1_MTPMU_SHIFT	U(0)
 #define ID_DFR1_MTPMU_MASK	U(0xf)
@@ -173,6 +183,7 @@
 #define SDCR_SPD_DISABLE	U(0x2)
 #define SDCR_SPD_ENABLE		U(0x3)
 #define SDCR_SCCD_BIT		(U(1) << 23)
+#define SDCR_TTRF_BIT		(U(1) << 19)
 #define SDCR_SPME_BIT		(U(1) << 17)
 #define SDCR_RESET_VAL		U(0x0)
 #define SDCR_MTPME_BIT		(U(1) << 28)
@@ -516,6 +527,7 @@
 #define CTR		p15, 0, c0, c0, 1
 #define CNTFRQ		p15, 0, c14, c0, 0
 #define ID_MMFR4	p15, 0, c0, c2, 6
+#define ID_DFR0		p15, 0, c0, c1, 2
 #define ID_DFR1		p15, 0, c0, c3, 5
 #define ID_PFR0		p15, 0, c0, c1, 0
 #define ID_PFR1		p15, 0, c0, c1, 1
diff --git a/include/arch/aarch32/arch_helpers.h b/include/arch/aarch32/arch_helpers.h
index 726baf5..0330989 100644
--- a/include/arch/aarch32/arch_helpers.h
+++ b/include/arch/aarch32/arch_helpers.h
@@ -217,6 +217,7 @@
 DEFINE_COPROCR_READ_FUNC(mpidr, MPIDR)
 DEFINE_COPROCR_READ_FUNC(midr, MIDR)
 DEFINE_COPROCR_READ_FUNC(id_mmfr4, ID_MMFR4)
+DEFINE_COPROCR_READ_FUNC(id_dfr0, ID_DFR0)
 DEFINE_COPROCR_READ_FUNC(id_pfr0, ID_PFR0)
 DEFINE_COPROCR_READ_FUNC(id_pfr1, ID_PFR1)
 DEFINE_COPROCR_READ_FUNC(isr, ISR)
@@ -282,6 +283,7 @@
 DEFINE_COPROCR_RW_FUNCS_64(icc_sgi0r_el1, ICC_SGI0R_EL1_64)
 DEFINE_COPROCR_WRITE_FUNC_64(icc_sgi1r, ICC_SGI1R_EL1_64)
 
+DEFINE_COPROCR_RW_FUNCS(sdcr, SDCR)
 DEFINE_COPROCR_RW_FUNCS(hdcr, HDCR)
 DEFINE_COPROCR_RW_FUNCS(cnthp_ctl, CNTHP_CTL)
 DEFINE_COPROCR_READ_FUNC(pmcr, PMCR)
diff --git a/include/arch/aarch32/el3_common_macros.S b/include/arch/aarch32/el3_common_macros.S
index 7fff4c7..65f9a8e 100644
--- a/include/arch/aarch32/el3_common_macros.S
+++ b/include/arch/aarch32/el3_common_macros.S
@@ -63,11 +63,23 @@
 	 *  cp11 field is ignored, but is set to same value as cp10. The cp10
 	 *  field is set to allow access to Advanced SIMD and floating point
 	 *  features from both Security states.
+	 *
+	 * NSACR.NSTRCDIS: When system register trace implemented, Set to one
+	 *  so that NS System register accesses to all implemented trace
+	 *  registers are disabled.
+	 *  When system register trace is not implemented, this bit is RES0 and
+	 *  hence set to zero.
 	 * ---------------------------------------------------------------------
 	 */
 	ldcopr	r0, NSACR
 	and	r0, r0, #NSACR_IMP_DEF_MASK
 	orr	r0, r0, #(NSACR_RESET_VAL | NSACR_ENABLE_FP_ACCESS)
+	ldcopr	r1, ID_DFR0
+	ubfx	r1, r1, #ID_DFR0_COPTRC_SHIFT, #ID_DFR0_COPTRC_LENGTH
+	cmp	r1, #ID_DFR0_COPTRC_SUPPORTED
+	bne	1f
+	orr	r0, r0, #NSTRCDIS_BIT
+1:
 	stcopr	r0, NSACR
 	isb
 
@@ -119,9 +131,22 @@
 	 *  in Secure state. This bit is RES0 in versions of the architecture
 	 *  earlier than ARMv8.5, setting it to 1 doesn't have any effect on
 	 *  them.
+	 *
+	 * SDCR.TTRF: Set to one so that access to trace filter control
+	 *  registers in non-monitor mode generate Monitor trap exception,
+	 *  unless the access generates a higher priority exception when
+	 *  trace filter control(FEAT_TRF) is implemented.
+	 *  When FEAT_TRF is not implemented, this bit is RES0.
 	 * ---------------------------------------------------------------------
 	 */
-	ldr	r0, =(SDCR_RESET_VAL | SDCR_SPD(SDCR_SPD_DISABLE) | SDCR_SCCD_BIT)
+	ldr	r0, =((SDCR_RESET_VAL | SDCR_SPD(SDCR_SPD_DISABLE) | \
+		      SDCR_SCCD_BIT) & ~SDCR_TTRF_BIT)
+	ldcopr	r1, ID_DFR0
+	ubfx	r1, r1, #ID_DFR0_TRACEFILT_SHIFT, #ID_DFR0_TRACEFILT_LENGTH
+	cmp	r1, #ID_DFR0_TRACEFILT_SUPPORTED
+	bne	1f
+	orr	r0, r0, #SDCR_TTRF_BIT
+1:
 	stcopr	r0, SDCR
 
 	/* ---------------------------------------------------------------------
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 3383a3b..74bc8cb 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -182,16 +182,36 @@
 #define ID_AA64PFR0_CSV2_SHIFT	U(56)
 #define ID_AA64PFR0_CSV2_MASK	ULL(0xf)
 #define ID_AA64PFR0_CSV2_LENGTH	U(4)
+#define ID_AA64PFR0_FEAT_RME_SHIFT		U(52)
+#define ID_AA64PFR0_FEAT_RME_MASK		ULL(0xf)
+#define ID_AA64PFR0_FEAT_RME_LENGTH		U(4)
+#define ID_AA64PFR0_FEAT_RME_NOT_SUPPORTED	U(0)
+#define ID_AA64PFR0_FEAT_RME_V1			U(1)
 
 /* Exception level handling */
 #define EL_IMPL_NONE		ULL(0)
 #define EL_IMPL_A64ONLY		ULL(1)
 #define EL_IMPL_A64_A32		ULL(2)
 
+/* ID_AA64DFR0_EL1.TraceVer definitions */
+#define ID_AA64DFR0_TRACEVER_SHIFT	U(4)
+#define ID_AA64DFR0_TRACEVER_MASK	ULL(0xf)
+#define ID_AA64DFR0_TRACEVER_SUPPORTED	ULL(1)
+#define ID_AA64DFR0_TRACEVER_LENGTH	U(4)
+#define ID_AA64DFR0_TRACEFILT_SHIFT	U(40)
+#define ID_AA64DFR0_TRACEFILT_MASK	U(0xf)
+#define ID_AA64DFR0_TRACEFILT_SUPPORTED	U(1)
+#define ID_AA64DFR0_TRACEFILT_LENGTH	U(4)
+
 /* ID_AA64DFR0_EL1.PMS definitions (for ARMv8.2+) */
 #define ID_AA64DFR0_PMS_SHIFT	U(32)
 #define ID_AA64DFR0_PMS_MASK	ULL(0xf)
 
+/* ID_AA64DFR0_EL1.TraceBuffer definitions */
+#define ID_AA64DFR0_TRACEBUFFER_SHIFT		U(44)
+#define ID_AA64DFR0_TRACEBUFFER_MASK		ULL(0xf)
+#define ID_AA64DFR0_TRACEBUFFER_SUPPORTED	ULL(1)
+
 /* ID_AA64DFR0_EL1.MTPMU definitions (for ARMv8.6+) */
 #define ID_AA64DFR0_MTPMU_SHIFT		U(48)
 #define ID_AA64DFR0_MTPMU_MASK		ULL(0xf)
@@ -263,6 +283,14 @@
 #define ID_AA64MMFR1_EL1_PAN2_SUPPORTED		ULL(0x2)
 #define ID_AA64MMFR1_EL1_PAN3_SUPPORTED		ULL(0x3)
 
+#define ID_AA64MMFR1_EL1_VHE_SHIFT		U(8)
+#define ID_AA64MMFR1_EL1_VHE_MASK		ULL(0xf)
+
+#define ID_AA64MMFR1_EL1_HCX_SHIFT              U(40)
+#define ID_AA64MMFR1_EL1_HCX_MASK               ULL(0xf)
+#define ID_AA64MMFR1_EL1_HCX_SUPPORTED          ULL(0x1)
+#define ID_AA64MMFR1_EL1_HCX_NOT_SUPPORTED      ULL(0x0)
+
 /* ID_AA64MMFR2_EL1 definitions */
 #define ID_AA64MMFR2_EL1		S3_0_C0_C7_2
 
@@ -390,7 +418,8 @@
 
 #define SCTLR_ATA0_BIT		(ULL(1) << 42)
 #define SCTLR_ATA_BIT		(ULL(1) << 43)
-#define SCTLR_DSSBS_BIT		(ULL(1) << 44)
+#define SCTLR_DSSBS_SHIFT	U(44)
+#define SCTLR_DSSBS_BIT		(ULL(1) << SCTLR_DSSBS_SHIFT)
 #define SCTLR_TWEDEn_BIT	(ULL(1) << 45)
 #define SCTLR_TWEDEL_SHIFT	U(46)
 #define SCTLR_TWEDEL_MASK	ULL(0xf)
@@ -408,13 +437,18 @@
 
 /* SCR definitions */
 #define SCR_RES1_BITS		((U(1) << 4) | (U(1) << 5))
+#define SCR_NSE_SHIFT		U(62)
+#define SCR_NSE_BIT		(ULL(1) << SCR_NSE_SHIFT)
+#define SCR_GPF_BIT		(UL(1) << 48)
 #define SCR_TWEDEL_SHIFT	U(30)
 #define SCR_TWEDEL_MASK		ULL(0xf)
+#define SCR_HXEn_BIT            (UL(1) << 38)
 #define SCR_AMVOFFEN_BIT	(UL(1) << 35)
 #define SCR_TWEDEn_BIT		(UL(1) << 29)
 #define SCR_ECVEN_BIT		(UL(1) << 28)
 #define SCR_FGTEN_BIT		(UL(1) << 27)
 #define SCR_ATA_BIT		(UL(1) << 26)
+#define SCR_EnSCXT_BIT		(UL(1) << 25)
 #define SCR_FIEN_BIT		(UL(1) << 21)
 #define SCR_EEL2_BIT		(UL(1) << 18)
 #define SCR_API_BIT		(UL(1) << 17)
@@ -438,6 +472,9 @@
 #define MDCR_EnPMSN_BIT		(ULL(1) << 36)
 #define MDCR_MPMX_BIT		(ULL(1) << 35)
 #define MDCR_MCCD_BIT		(ULL(1) << 34)
+#define MDCR_NSTB(x)		((x) << 24)
+#define MDCR_NSTB_EL1		ULL(0x3)
+#define MDCR_NSTBE		(ULL(1) << 26)
 #define MDCR_MTPME_BIT		(ULL(1) << 28)
 #define MDCR_TDCC_BIT		(ULL(1) << 27)
 #define MDCR_SCCD_BIT		(ULL(1) << 23)
@@ -461,6 +498,8 @@
 /* MDCR_EL2 definitions */
 #define MDCR_EL2_MTPME		(U(1) << 28)
 #define MDCR_EL2_HLP		(U(1) << 26)
+#define MDCR_EL2_E2TB(x)	((x) << 24)
+#define MDCR_EL2_E2TB_EL1	U(0x3)
 #define MDCR_EL2_HCCD		(U(1) << 23)
 #define MDCR_EL2_TTRF		(U(1) << 19)
 #define MDCR_EL2_HPMD		(U(1) << 17)
@@ -492,13 +531,18 @@
 #define VTTBR_BADDR_SHIFT	U(0)
 
 /* HCR definitions */
+#define HCR_RESET_VAL		ULL(0x0)
 #define HCR_AMVOFFEN_BIT	(ULL(1) << 51)
+#define HCR_TEA_BIT		(ULL(1) << 47)
 #define HCR_API_BIT		(ULL(1) << 41)
 #define HCR_APK_BIT		(ULL(1) << 40)
 #define HCR_E2H_BIT		(ULL(1) << 34)
+#define HCR_HCD_BIT		(ULL(1) << 29)
 #define HCR_TGE_BIT		(ULL(1) << 27)
 #define HCR_RW_SHIFT		U(31)
 #define HCR_RW_BIT		(ULL(1) << HCR_RW_SHIFT)
+#define HCR_TWE_BIT		(ULL(1) << 14)
+#define HCR_TWI_BIT		(ULL(1) << 13)
 #define HCR_AMO_BIT		(ULL(1) << 5)
 #define HCR_IMO_BIT		(ULL(1) << 4)
 #define HCR_FMO_BIT		(ULL(1) << 3)
@@ -541,6 +585,10 @@
 #define CPTR_EL2_TZ_BIT		(U(1) << 8)
 #define CPTR_EL2_RESET_VAL	CPTR_EL2_RES1
 
+/* VTCR_EL2 definitions */
+#define VTCR_RESET_VAL         U(0x0)
+#define VTCR_EL2_MSA           (U(1) << 31)
+
 /* CPSR/SPSR definitions */
 #define DAIF_FIQ_BIT		(U(1) << 0)
 #define DAIF_IRQ_BIT		(U(1) << 1)
@@ -566,12 +614,21 @@
 #define SPSR_M_MASK		U(0x1)
 #define SPSR_M_AARCH64		U(0x0)
 #define SPSR_M_AARCH32		U(0x1)
+#define SPSR_M_EL2H		U(0x9)
 
 #define SPSR_EL_SHIFT		U(2)
 #define SPSR_EL_WIDTH		U(2)
 
+#define SPSR_SSBS_SHIFT_AARCH64 U(12)
+#define SPSR_SSBS_BIT_AARCH64	(ULL(1) << SPSR_SSBS_SHIFT_AARCH64)
+#define SPSR_SSBS_SHIFT_AARCH32 U(23)
+#define SPSR_SSBS_BIT_AARCH32	(ULL(1) << SPSR_SSBS_SHIFT_AARCH32)
+
+#define SPSR_PAN_BIT		BIT_64(22)
+
-#define SPSR_SSBS_BIT_AARCH64	BIT_64(12)
-#define SPSR_SSBS_BIT_AARCH32	BIT_64(23)
+#define SPSR_DIT_BIT		BIT(24)
+
+#define SPSR_TCO_BIT_AARCH64	BIT_64(25)
 
 #define DISABLE_ALL_EXCEPTIONS \
 		(DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT | DAIF_DBG_BIT)
@@ -1050,6 +1107,12 @@
 #define AMEVCNTVOFF1F_EL2	S3_4_C13_C11_7
 
 /*******************************************************************************
+ * Realm management extension register definitions
+ ******************************************************************************/
+#define GPCCR_EL3			S3_6_C2_C1_6
+#define GPTBR_EL3			S3_6_C2_C1_4
+
+/*******************************************************************************
  * RAS system registers
  ******************************************************************************/
 #define DISR_EL1		S3_0_C12_C1_1
@@ -1112,6 +1175,16 @@
 #define GCR_EL1			S3_0_C1_C0_6
 
 /*******************************************************************************
+ * FEAT_HCX - Extended Hypervisor Configuration Register
+ ******************************************************************************/
+#define HCRX_EL2                S3_4_C1_C2_2
+#define HCRX_EL2_FGTnXS_BIT     (UL(1) << 4)
+#define HCRX_EL2_FnXS_BIT       (UL(1) << 3)
+#define HCRX_EL2_EnASR_BIT      (UL(1) << 2)
+#define HCRX_EL2_EnALS_BIT      (UL(1) << 1)
+#define HCRX_EL2_EnAS0_BIT      (UL(1) << 0)
+
+/*******************************************************************************
  * Definitions for DynamicIQ Shared Unit registers
  ******************************************************************************/
 #define CLUSTERPWRDN_EL1	S3_0_c15_c3_6
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index 47a797a..46cd1c9 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -17,6 +17,18 @@
 	return true;
 }
 
+static inline bool is_armv8_1_pan_present(void)
+{
+	return ((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_PAN_SHIFT) &
+		ID_AA64MMFR1_EL1_PAN_MASK) != 0U;
+}
+
+static inline bool is_armv8_1_vhe_present(void)
+{
+	return ((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_VHE_SHIFT) &
+		ID_AA64MMFR1_EL1_VHE_MASK) != 0U;
+}
+
 static inline bool is_armv8_2_ttcnp_present(void)
 {
 	return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_CNP_SHIFT) &
@@ -105,4 +117,21 @@
 		ID_AA64PFR1_MPAM_FRAC_SHIFT) & ID_AA64PFR1_MPAM_FRAC_MASK));
 }
 
+static inline bool is_feat_hcx_present(void)
+{
+	return (((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_HCX_SHIFT) &
+		ID_AA64MMFR1_EL1_HCX_MASK) == ID_AA64MMFR1_EL1_HCX_SUPPORTED);
+}
+
+static inline unsigned int get_armv9_2_feat_rme_support(void)
+{
+	/*
+	 * Return the RME version, zero if not supported.  This function can be
+	 * used as both an integer value for the RME version or compared to zero
+	 * to detect RME presence.
+	 */
+	return (unsigned int)(read_id_aa64pfr0_el1() >>
+		ID_AA64PFR0_FEAT_RME_SHIFT) & ID_AA64PFR0_FEAT_RME_MASK;
+}
+
 #endif /* ARCH_FEATURES_H */
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index a41b325..cae05dc 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -233,8 +233,10 @@
 
 void disable_mmu_el1(void);
 void disable_mmu_el3(void);
+void disable_mpu_el2(void);
 void disable_mmu_icache_el1(void);
 void disable_mmu_icache_el3(void);
+void disable_mpu_icache_el2(void);
 
 /*******************************************************************************
  * Misc. accessor prototypes
@@ -440,6 +442,8 @@
 DEFINE_SYSREG_READ_FUNC(cntpct_el0)
 DEFINE_SYSREG_RW_FUNCS(cnthctl_el2)
 
+DEFINE_SYSREG_RW_FUNCS(vtcr_el2)
+
 #define get_cntp_ctl_enable(x)  (((x) >> CNTP_CTL_ENABLE_SHIFT) & \
 					CNTP_CTL_ENABLE_MASK)
 #define get_cntp_ctl_imask(x)   (((x) >> CNTP_CTL_IMASK_SHIFT) & \
@@ -532,9 +536,16 @@
 DEFINE_SYSREG_READ_FUNC(rndr)
 DEFINE_SYSREG_READ_FUNC(rndrrs)
 
+/* FEAT_HCX Register */
+DEFINE_RENAME_SYSREG_RW_FUNCS(hcrx_el2, HCRX_EL2)
+
 /* DynamIQ Shared Unit power management */
 DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpwrdn_el1, CLUSTERPWRDN_EL1)
 
+/* Armv9.2 RME Registers */
+DEFINE_RENAME_SYSREG_RW_FUNCS(gptbr_el3, GPTBR_EL3)
+DEFINE_RENAME_SYSREG_RW_FUNCS(gpccr_el3, GPCCR_EL3)
+
 #define IS_IN_EL(x) \
 	(GET_EL(read_CurrentEl()) == MODE_EL##x)
 
@@ -578,7 +589,28 @@
 	}
 }
 
+/*
+ * TLBIPAALLOS instruction
+ * (TLB Inivalidate GPT Information by PA,
+ * All Entries, Outer Shareable)
+ */
+static inline void tlbipaallos(void)
+{
+	__asm__("SYS #6,c8,c1,#4");
+}
+
+/*
+ * Invalidate cached copies of GPT entries
+ * from TLBs by physical address
+ *
+ * @pa: the starting address for the range
+ *      of invalidation
+ * @size: size of the range of invalidation
+ */
+void gpt_tlbi_by_pa(uint64_t pa, size_t size);
+
+
-/* Previously defined accesor functions with incomplete register names  */
+/* Previously defined accessor functions with incomplete register names  */
 
 #define read_current_el()	read_CurrentEl()
 
diff --git a/include/arch/aarch64/asm_macros.S b/include/arch/aarch64/asm_macros.S
index 464c05b..7706cd8 100644
--- a/include/arch/aarch64/asm_macros.S
+++ b/include/arch/aarch64/asm_macros.S
@@ -10,10 +10,6 @@
 #include <common/asm_macros_common.S>
 #include <lib/spinlock.h>
 
-#if ENABLE_BTI && !ARM_ARCH_AT_LEAST(8, 5)
-#error Branch Target Identification requires ARM_ARCH_MINOR >= 5
-#endif
-
 /*
  * TLBI instruction with type specifier that implements the workaround for
  * errata 813419 of Cortex-A57 or errata 1286807 of Cortex-A76.
diff --git a/include/arch/aarch64/el2_common_macros.S b/include/arch/aarch64/el2_common_macros.S
new file mode 100644
index 0000000..c57a1ec
--- /dev/null
+++ b/include/arch/aarch64/el2_common_macros.S
@@ -0,0 +1,448 @@
+/*
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EL2_COMMON_MACROS_S
+#define EL2_COMMON_MACROS_S
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <context.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+
+#include <platform_def.h>
+
+	/*
+	 * Helper macro to initialise system registers at EL2.
+	 */
+	.macro el2_arch_init_common
+
+	/* ---------------------------------------------------------------------
+	 * SCTLR_EL2 has already been initialised - read current value before
+	 * modifying.
+	 *
+	 * SCTLR_EL2.I: Enable the instruction cache.
+	 *
+	 * SCTLR_EL2.SA: Enable Stack Alignment check. A SP alignment fault
+	 *  exception is generated if a load or store instruction executed at
+	 *  EL2 uses the SP as the base address and the SP is not aligned to a
+	 *  16-byte boundary.
+	 *
+	 * SCTLR_EL2.A: Enable Alignment fault checking. All instructions that
+	 *  load or store one or more registers have an alignment check that the
+	 *  address being accessed is aligned to the size of the data element(s)
+	 *  being accessed.
+	 * ---------------------------------------------------------------------
+	 */
+	mov	x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
+	mrs	x0, sctlr_el2
+	orr	x0, x0, x1
+	msr	sctlr_el2, x0
+	isb
+
+	/* ---------------------------------------------------------------------
+	 * Initialise HCR_EL2, setting all fields rather than relying on HW.
+	 * All fields are architecturally UNKNOWN on reset. The following fields
+	 * do not change during the TF lifetime. The remaining fields are set to
+	 * zero here but are updated ahead of transitioning to a lower EL in the
+	 * function cm_init_context_common().
+	 *
+	 * HCR_EL2.TWE: Set to zero so that execution of WFE instructions at
+	 *  EL2, EL1 and EL0 are not trapped to EL2.
+	 *
+	 * HCR_EL2.TWI: Set to zero so that execution of WFI instructions at
+	 *  EL2, EL1 and EL0 are not trapped to EL2.
+	 *
+	 * HCR_EL2.HCD: Set to zero to enable HVC calls at EL1 and above,
+	 *  from both Security states and both Execution states.
+	 *
+	 * HCR_EL2.TEA: Set to one to route External Aborts and SError
+	 * Interrupts to EL2 when executing at any EL.
+	 *
+	 * HCR_EL2.{API,APK}: For Armv8.3 pointer authentication feature,
+	 * disable traps to EL2 when accessing key registers or using
+	 * pointer authentication instructions from lower ELs.
+	 * ---------------------------------------------------------------------
+	 */
+	mov_imm	x0, ((HCR_RESET_VAL | HCR_TEA_BIT) \
+			& ~(HCR_TWE_BIT | HCR_TWI_BIT | HCR_HCD_BIT))
+#if CTX_INCLUDE_PAUTH_REGS
+	/*
+	 * If the pointer authentication registers are saved during world
+	 * switches, enable pointer authentication everywhere, as it is safe to
+	 * do so.
+	 */
+	orr	x0, x0, #(HCR_API_BIT | HCR_APK_BIT)
+#endif  /* CTX_INCLUDE_PAUTH_REGS */
+	msr	hcr_el2, x0
+
+	/* ---------------------------------------------------------------------
+	 * Initialise MDCR_EL2, setting all fields rather than relying on
+	 * hw. Some fields are architecturally UNKNOWN on reset.
+	 *
+	 * MDCR_EL2.SDD: Set to one to disable AArch64 Secure self-hosted
+	 *  debug. Debug exceptions, other than Breakpoint Instruction
+	 *  exceptions, are disabled from all ELs in Secure state.
+	 *
+	 * MDCR_EL2.TDOSA: Set to zero so that EL2 and EL2 System register
+	 *  access to the powerdown debug registers do not trap to EL2.
+	 *
+	 * MDCR_EL2.TDA: Set to zero to allow EL0, EL1 and EL2 access to the
+	 *  debug registers, other than those registers that are controlled by
+	 *  MDCR_EL2.TDOSA.
+	 *
+	 * MDCR_EL2.TPM: Set to zero so that EL0, EL1, and EL2 System
+	 *  register accesses to all Performance Monitors registers do not trap
+	 *  to EL2.
+	 *
+	 * MDCR_EL2.SCCD: Set to one so that cycle counting by PMCCNTR_EL0
+	 *  is prohibited in Secure state. This bit is RES0 in versions of the
+	 *  architecture with FEAT_PMUv3p5 not implemented, setting it to 1
+	 *  doesn't have any effect on them.
+	 *
+	 * MDCR_EL2.MCCD: Set to one so that cycle counting by PMCCNTR_EL0
+	 *  is prohibited in EL2. This bit is RES0 in versions of the
+	 *  architecture with FEAT_PMUv3p7 not implemented, setting it to 1
+	 *  doesn't have any effect on them.
+	 *
+	 * MDCR_EL2.SPME: Set to zero so that event counting by the program-
+	 *  mable counters PMEVCNTR<n>_EL0 is prohibited in Secure state. If
+	 *  ARMv8.2 Debug is not implemented this bit does not have any effect
+	 *  on the counters unless there is support for the implementation
+	 *  defined authentication interface
+	 *  ExternalSecureNoninvasiveDebugEnabled().
+	 * ---------------------------------------------------------------------
+	 */
+	mov_imm	x0, ((MDCR_EL2_RESET_VAL | MDCR_SDD_BIT | \
+		      MDCR_SPD32(MDCR_SPD32_DISABLE) | MDCR_SCCD_BIT | \
+		      MDCR_MCCD_BIT) & ~(MDCR_SPME_BIT | MDCR_TDOSA_BIT | \
+		      MDCR_TDA_BIT | MDCR_TPM_BIT))
+
+	msr	mdcr_el2, x0
+
+	/* ---------------------------------------------------------------------
+	 * Initialise PMCR_EL0 setting all fields rather than relying
+	 * on hw. Some fields are architecturally UNKNOWN on reset.
+	 *
+	 * PMCR_EL0.LP: Set to one so that event counter overflow, that
+	 *  is recorded in PMOVSCLR_EL0[0-30], occurs on the increment
+	 *  that changes PMEVCNTR<n>_EL0[63] from 1 to 0, when ARMv8.5-PMU
+	 *  is implemented. This bit is RES0 in versions of the architecture
+	 *  earlier than ARMv8.5, setting it to 1 doesn't have any effect
+	 *  on them.
+	 *
+	 * PMCR_EL0.LC: Set to one so that cycle counter overflow, that
+	 *  is recorded in PMOVSCLR_EL0[31], occurs on the increment
+	 *  that changes PMCCNTR_EL0[63] from 1 to 0.
+	 *
+	 * PMCR_EL0.DP: Set to one so that the cycle counter,
+	 *  PMCCNTR_EL0 does not count when event counting is prohibited.
+	 *
+	 * PMCR_EL0.X: Set to zero to disable export of events.
+	 *
+	 * PMCR_EL0.D: Set to zero so that, when enabled, PMCCNTR_EL0
+	 *  counts on every clock cycle.
+	 * ---------------------------------------------------------------------
+	 */
+	mov_imm	x0, ((PMCR_EL0_RESET_VAL | PMCR_EL0_LP_BIT | \
+		      PMCR_EL0_LC_BIT | PMCR_EL0_DP_BIT) & \
+		    ~(PMCR_EL0_X_BIT | PMCR_EL0_D_BIT))
+
+	msr	pmcr_el0, x0
+
+	/* ---------------------------------------------------------------------
+	 * Enable External Aborts and SError Interrupts now that the exception
+	 * vectors have been setup.
+	 * ---------------------------------------------------------------------
+	 */
+	msr	daifclr, #DAIF_ABT_BIT
+
+	/* ---------------------------------------------------------------------
+	 * Initialise CPTR_EL2, setting all fields rather than relying on hw.
+	 * All fields are architecturally UNKNOWN on reset.
+	 *
+	 * CPTR_EL2.TCPAC: Set to zero so that any accesses to CPACR_EL1 do
+	 * not trap to EL2.
+	 *
+	 * CPTR_EL2.TTA: Set to zero so that System register accesses to the
+	 *  trace registers do not trap to EL2.
+	 *
+	 * CPTR_EL2.TFP: Set to zero so that accesses to the V- or Z- registers
+	 *  by Advanced SIMD, floating-point or SVE instructions (if implemented)
+	 *  do not trap to EL2.
+	 */
+
+	mov_imm x0, (CPTR_EL2_RESET_VAL & ~(TCPAC_BIT | TTA_BIT | TFP_BIT))
+	msr	cptr_el2, x0
+
+	/*
+	 * If Data Independent Timing (DIT) functionality is implemented,
+	 * always enable DIT in EL2
+	 */
+	mrs	x0, id_aa64pfr0_el1
+	ubfx	x0, x0, #ID_AA64PFR0_DIT_SHIFT, #ID_AA64PFR0_DIT_LENGTH
+	cmp	x0, #ID_AA64PFR0_DIT_SUPPORTED
+	bne	1f
+	mov	x0, #DIT_BIT
+	msr	DIT, x0
+1:
+	.endm
+
+/* -----------------------------------------------------------------------------
+ * This is the super set of actions that need to be performed during a cold boot
+ * or a warm boot in EL2. This code is shared by BL1 and BL31.
+ *
+ * This macro will always perform reset handling, architectural initialisations
+ * and stack setup. The rest of the actions are optional because they might not
+ * be needed, depending on the context in which this macro is called. This is
+ * why this macro is parameterised ; each parameter allows to enable/disable
+ * some actions.
+ *
+ *  _init_sctlr:
+ *	Whether the macro needs to initialise SCTLR_EL2, including configuring
+ *      the endianness of data accesses.
+ *
+ *  _warm_boot_mailbox:
+ *	Whether the macro needs to detect the type of boot (cold/warm). The
+ *	detection is based on the platform entrypoint address : if it is zero
+ *	then it is a cold boot, otherwise it is a warm boot. In the latter case,
+ *	this macro jumps on the platform entrypoint address.
+ *
+ *  _secondary_cold_boot:
+ *	Whether the macro needs to identify the CPU that is calling it: primary
+ *	CPU or secondary CPU. The primary CPU will be allowed to carry on with
+ *	the platform initialisations, while the secondaries will be put in a
+ *	platform-specific state in the meantime.
+ *
+ *	If the caller knows this macro will only be called by the primary CPU
+ *	then this parameter can be defined to 0 to skip this step.
+ *
+ * _init_memory:
+ *	Whether the macro needs to initialise the memory.
+ *
+ * _init_c_runtime:
+ *	Whether the macro needs to initialise the C runtime environment.
+ *
+ * _exception_vectors:
+ *	Address of the exception vectors to program in the VBAR_EL2 register.
+ *
+ * _pie_fixup_size:
+ *	Size of memory region to fixup Global Descriptor Table (GDT).
+ *
+ *	A non-zero value is expected when firmware needs GDT to be fixed-up.
+ *
+ * -----------------------------------------------------------------------------
+ */
+	.macro el2_entrypoint_common					\
+		_init_sctlr, _warm_boot_mailbox, _secondary_cold_boot,	\
+		_init_memory, _init_c_runtime, _exception_vectors,	\
+		_pie_fixup_size
+
+	.if \_init_sctlr
+		/* -------------------------------------------------------------
+		 * This is the initialisation of SCTLR_EL2 and so must ensure
+		 * that all fields are explicitly set rather than relying on hw.
+		 * Some fields reset to an IMPLEMENTATION DEFINED value and
+		 * others are architecturally UNKNOWN on reset.
+		 *
+		 * SCTLR.EE: Set the CPU endianness before doing anything that
+		 *  might involve memory reads or writes. Set to zero to select
+		 *  Little Endian.
+		 *
+		 * SCTLR_EL2.WXN: For the EL2 translation regime, this field can
+		 *  force all memory regions that are writeable to be treated as
+		 *  XN (Execute-never). Set to zero so that this control has no
+		 *  effect on memory access permissions.
+		 *
+		 * SCTLR_EL2.SA: Set to zero to disable Stack Alignment check.
+		 *
+		 * SCTLR_EL2.A: Set to zero to disable Alignment fault checking.
+		 *
+		 * SCTLR.DSSBS: Set to zero to disable speculation store bypass
+		 *  safe behaviour upon exception entry to EL2.
+		 * -------------------------------------------------------------
+		 */
+		mov_imm	x0, (SCTLR_RESET_VAL & ~(SCTLR_EE_BIT | SCTLR_WXN_BIT \
+				| SCTLR_SA_BIT | SCTLR_A_BIT | SCTLR_DSSBS_BIT))
+		msr	sctlr_el2, x0
+		isb
+	.endif /* _init_sctlr */
+
+#if DISABLE_MTPMU
+		bl	mtpmu_disable
+#endif
+
+	.if \_warm_boot_mailbox
+		/* -------------------------------------------------------------
+		 * This code will be executed for both warm and cold resets.
+		 * Now is the time to distinguish between the two.
+		 * Query the platform entrypoint address and if it is not zero
+		 * then it means it is a warm boot so jump to this address.
+		 * -------------------------------------------------------------
+		 */
+		bl	plat_get_my_entrypoint
+		cbz	x0, do_cold_boot
+		br	x0
+
+	do_cold_boot:
+	.endif /* _warm_boot_mailbox */
+
+	.if \_pie_fixup_size
+#if ENABLE_PIE
+		/*
+		 * ------------------------------------------------------------
+		 * If PIE is enabled fixup the Global descriptor Table only
+		 * once during primary core cold boot path.
+		 *
+		 * Compile time base address, required for fixup, is calculated
+		 * using "pie_fixup" label present within first page.
+		 * ------------------------------------------------------------
+		 */
+	pie_fixup:
+		ldr	x0, =pie_fixup
+		and	x0, x0, #~(PAGE_SIZE_MASK)
+		mov_imm	x1, \_pie_fixup_size
+		add	x1, x1, x0
+		bl	fixup_gdt_reloc
+#endif /* ENABLE_PIE */
+	.endif /* _pie_fixup_size */
+
+	/* ---------------------------------------------------------------------
+	 * Set the exception vectors.
+	 * ---------------------------------------------------------------------
+	 */
+	adr	x0, \_exception_vectors
+	msr	vbar_el2, x0
+	isb
+
+	/* ---------------------------------------------------------------------
+	 * It is a cold boot.
+	 * Perform any processor specific actions upon reset e.g. cache, TLB
+	 * invalidations etc.
+	 * ---------------------------------------------------------------------
+	 */
+	bl	reset_handler
+
+	el2_arch_init_common
+
+	.if \_secondary_cold_boot
+		/* -------------------------------------------------------------
+		 * Check if this is a primary or secondary CPU cold boot.
+		 * The primary CPU will set up the platform while the
+		 * secondaries are placed in a platform-specific state until the
+		 * primary CPU performs the necessary actions to bring them out
+		 * of that state and allows entry into the OS.
+		 * -------------------------------------------------------------
+		 */
+		bl	plat_is_my_cpu_primary
+		cbnz	w0, do_primary_cold_boot
+
+		/* This is a cold boot on a secondary CPU */
+		bl	plat_secondary_cold_boot_setup
+		/* plat_secondary_cold_boot_setup() is not supposed to return */
+		bl	el2_panic
+	do_primary_cold_boot:
+	.endif /* _secondary_cold_boot */
+
+	/* ---------------------------------------------------------------------
+	 * Initialize memory now. Secondary CPU initialization won't get to this
+	 * point.
+	 * ---------------------------------------------------------------------
+	 */
+
+	.if \_init_memory
+		bl	platform_mem_init
+	.endif /* _init_memory */
+
+	/* ---------------------------------------------------------------------
+	 * Init C runtime environment:
+	 *   - Zero-initialise the NOBITS sections. There are 2 of them:
+	 *       - the .bss section;
+	 *       - the coherent memory section (if any).
+	 *   - Relocate the data section from ROM to RAM, if required.
+	 * ---------------------------------------------------------------------
+	 */
+	.if \_init_c_runtime
+		adrp	x0, __BSS_START__
+		add	x0, x0, :lo12:__BSS_START__
+
+		adrp	x1, __BSS_END__
+		add	x1, x1, :lo12:__BSS_END__
+		sub	x1, x1, x0
+		bl	zeromem
+
+#if defined(IMAGE_BL1) || (defined(IMAGE_BL2) && BL2_AT_EL3 && BL2_IN_XIP_MEM)
+		adrp	x0, __DATA_RAM_START__
+		add	x0, x0, :lo12:__DATA_RAM_START__
+		adrp	x1, __DATA_ROM_START__
+		add	x1, x1, :lo12:__DATA_ROM_START__
+		adrp	x2, __DATA_RAM_END__
+		add	x2, x2, :lo12:__DATA_RAM_END__
+		sub	x2, x2, x0
+		bl	memcpy16
+#endif
+	.endif /* _init_c_runtime */
+
+	/* ---------------------------------------------------------------------
+	 * Use SP_EL0 for the C runtime stack.
+	 * ---------------------------------------------------------------------
+	 */
+	msr	spsel, #0
+
+	/* ---------------------------------------------------------------------
+	 * Allocate a stack whose memory will be marked as Normal-IS-WBWA when
+	 * the MMU is enabled. There is no risk of reading stale stack memory
+	 * after enabling the MMU as only the primary CPU is running at the
+	 * moment.
+	 * ---------------------------------------------------------------------
+	 */
+	bl	plat_set_my_stack
+
+#if STACK_PROTECTOR_ENABLED
+	.if \_init_c_runtime
+	bl	update_stack_protector_canary
+	.endif /* _init_c_runtime */
+#endif
+	.endm
+
+	.macro	apply_at_speculative_wa
+#if ERRATA_SPECULATIVE_AT
+	/*
+	 * Explicitly save x30 so as to free up a register and to enable
+	 * branching and also, save x29 which will be used in the called
+	 * function
+	 */
+	stp	x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29]
+	bl	save_and_update_ptw_el1_sys_regs
+	ldp	x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29]
+#endif
+	.endm
+
+	.macro	restore_ptw_el1_sys_regs
+#if ERRATA_SPECULATIVE_AT
+	/* -----------------------------------------------------------
+	 * In case of ERRATA_SPECULATIVE_AT, must follow below order
+	 * to ensure that page table walk is not enabled until
+	 * restoration of all EL1 system registers. TCR_EL1 register
+	 * should be updated at the end which restores previous page
+	 * table walk setting of stage1 i.e.(TCR_EL1.EPDx) bits. ISB
+	 * ensures that CPU does below steps in order.
+	 *
+	 * 1. Ensure all other system registers are written before
+	 *    updating SCTLR_EL1 using ISB.
+	 * 2. Restore SCTLR_EL1 register.
+	 * 3. Ensure SCTLR_EL1 written successfully using ISB.
+	 * 4. Restore TCR_EL1 register.
+	 * -----------------------------------------------------------
+	 */
+	isb
+	ldp	x28, x29, [sp, #CTX_EL1_SYSREGS_OFFSET + CTX_SCTLR_EL1]
+	msr	sctlr_el1, x28
+	isb
+	msr	tcr_el1, x29
+#endif
+	.endm
+
+#endif /* EL2_COMMON_MACROS_S */
diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S
index 9734335..7d6a963 100644
--- a/include/arch/aarch64/el3_common_macros.S
+++ b/include/arch/aarch64/el3_common_macros.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -88,6 +88,13 @@
 	 */
 	orr	x0, x0, #(SCR_API_BIT | SCR_APK_BIT)
 #endif
+#if ENABLE_RME
+	/*
+	 * TODO: Settting the EEL2 bit to allow EL3 access to secure only registers
+	 * in context management. This will need to be refactored.
+	 */
+	orr	x0, x0, #SCR_EEL2_BIT
+#endif
 	msr	scr_el3, x0
 
 	/* ---------------------------------------------------------------------
@@ -126,13 +133,31 @@
 	 *  Debug is not implemented this bit does not have any effect on the
 	 *  counters unless there is support for the implementation defined
 	 *  authentication interface ExternalSecureNoninvasiveDebugEnabled().
+	 *
+	 * MDCR_EL3.NSTB, MDCR_EL3.NSTBE: Set to zero so that Trace Buffer
+	 *  owning security state is Secure state. If FEAT_TRBE is implemented,
+	 *  accesses to Trace Buffer control registers at EL2 and EL1 in any
+	 *  security state generates trap exceptions to EL3.
+	 *  If FEAT_TRBE is not implemented, these bits are RES0.
+	 *
+	 * MDCR_EL3.TTRF: Set to one so that access to trace filter control
+	 *  registers in non-monitor mode generate EL3 trap exception,
+	 *  unless the access generates a higher priority exception when trace
+	 *  filter control(FEAT_TRF) is implemented.
+	 *  When FEAT_TRF is not implemented, this bit is RES0.
 	 * ---------------------------------------------------------------------
 	 */
 	mov_imm	x0, ((MDCR_EL3_RESET_VAL | MDCR_SDD_BIT | \
 		      MDCR_SPD32(MDCR_SPD32_DISABLE) | MDCR_SCCD_BIT | \
 		      MDCR_MCCD_BIT) & ~(MDCR_SPME_BIT | MDCR_TDOSA_BIT | \
-		      MDCR_TDA_BIT | MDCR_TPM_BIT))
+		      MDCR_TDA_BIT | MDCR_TPM_BIT | MDCR_NSTB(MDCR_NSTB_EL1) | \
+		      MDCR_NSTBE | MDCR_TTRF_BIT))
 
+	mrs	x1, id_aa64dfr0_el1
+	ubfx	x1, x1, #ID_AA64DFR0_TRACEFILT_SHIFT, #ID_AA64DFR0_TRACEFILT_LENGTH
+	cbz	x1, 1f
+	orr	x0, x0, #MDCR_TTRF_BIT
+1:
 	msr	mdcr_el3, x0
 
 	/* ---------------------------------------------------------------------
@@ -179,6 +204,12 @@
 	 * CPTR_EL3.TCPAC: Set to zero so that any accesses to CPACR_EL1,
 	 *  CPTR_EL2, CPACR, or HCPTR do not trap to EL3.
 	 *
+	 * CPTR_EL3.TTA: Set to one so that accesses to the trace system
+	 *  registers trap to EL3 from all exception levels and security
+	 *  states when system register trace is implemented.
+	 *  When system register trace is not implemented, this bit is RES0 and
+	 *  hence set to zero.
+	 *
 	 * CPTR_EL3.TTA: Set to zero so that System register accesses to the
 	 *  trace registers do not trap to EL3.
 	 *
@@ -194,6 +225,11 @@
 	 */
 
 	mov_imm x0, (CPTR_EL3_RESET_VAL & ~(TCPAC_BIT | TTA_BIT | TFP_BIT))
+	mrs	x1, id_aa64dfr0_el1
+	ubfx	x1, x1, #ID_AA64DFR0_TRACEVER_SHIFT, #ID_AA64DFR0_TRACEVER_LENGTH
+	cbz	x1, 1f
+	orr	x0, x0, #TTA_BIT
+1:
 	msr	cptr_el3, x0
 
 	/*
@@ -336,6 +372,7 @@
 	msr	vbar_el3, x0
 	isb
 
+#if !(defined(IMAGE_BL2) && ENABLE_RME)
 	/* ---------------------------------------------------------------------
 	 * It is a cold boot.
 	 * Perform any processor specific actions upon reset e.g. cache, TLB
@@ -343,6 +380,7 @@
 	 * ---------------------------------------------------------------------
 	 */
 	bl	reset_handler
+#endif
 
 	el3_arch_init_common
 
@@ -385,7 +423,8 @@
 	 * ---------------------------------------------------------------------
 	 */
 	.if \_init_c_runtime
-#if defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3 && BL2_INV_DCACHE)
+#if defined(IMAGE_BL31) || (defined(IMAGE_BL2) && \
+	((BL2_AT_EL3 && BL2_INV_DCACHE) || ENABLE_RME))
 		/* -------------------------------------------------------------
 		 * Invalidate the RW memory used by the BL31 image. This
 		 * includes the data and NOBITS sections. This is done to
diff --git a/include/bl31/bl31.h b/include/bl31/bl31.h
index 3deb0a5..1d58ef9 100644
--- a/include/bl31/bl31.h
+++ b/include/bl31/bl31.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,6 +19,7 @@
 uint32_t bl31_get_next_image_type(void);
 void bl31_prepare_next_image_entry(void);
 void bl31_register_bl32_init(int32_t (*func)(void));
+void bl31_register_rmm_init(int32_t (*func)(void));
 void bl31_warm_entrypoint(void);
 void bl31_main(void);
 void bl31_lib_init(void);
diff --git a/include/common/bl_common.h b/include/common/bl_common.h
index 77fb1f6..8cb4990 100644
--- a/include/common/bl_common.h
+++ b/include/common/bl_common.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -106,6 +106,10 @@
 IMPORT_SYM(uintptr_t, __RO_START__,		BL_CODE_BASE);
 IMPORT_SYM(uintptr_t, __RO_END__,		BL_CODE_END);
 #endif
+#if SEPARATE_NOBITS_REGION
+IMPORT_SYM(uintptr_t, __NOBITS_START__,		BL_NOBITS_BASE);
+IMPORT_SYM(uintptr_t, __NOBITS_END__,		BL_NOBITS_END);
+#endif
 IMPORT_SYM(uintptr_t, __RW_END__,		BL_END);
 
 #if defined(IMAGE_BL1)
@@ -122,6 +126,8 @@
 IMPORT_SYM(uintptr_t, __BL31_END__,		BL31_END);
 #elif defined(IMAGE_BL32)
 IMPORT_SYM(uintptr_t, __BL32_END__,		BL32_END);
+#elif defined(IMAGE_RMM)
+IMPORT_SYM(uintptr_t, __RMM_END__,		RMM_END);
 #endif /* IMAGE_BLX */
 
 /* The following symbols are only exported from the BL2 at EL3 linker script. */
diff --git a/include/common/debug.h b/include/common/debug.h
index ed0e8bf..a7ca0d7 100644
--- a/include/common/debug.h
+++ b/include/common/debug.h
@@ -61,8 +61,10 @@
 
 #if LOG_LEVEL >= LOG_LEVEL_ERROR
 # define ERROR(...)	tf_log(LOG_MARKER_ERROR __VA_ARGS__)
+# define ERROR_NL()	tf_log_newline(LOG_MARKER_ERROR)
 #else
 # define ERROR(...)	no_tf_log(LOG_MARKER_ERROR __VA_ARGS__)
+# define ERROR_NL()
 #endif
 
 #if LOG_LEVEL >= LOG_LEVEL_NOTICE
@@ -109,6 +111,7 @@
 void __dead2 __stack_chk_fail(void);
 
 void tf_log(const char *fmt, ...) __printflike(1, 2);
+void tf_log_newline(const char log_fmt[2]);
 void tf_log_set_max_level(unsigned int log_level);
 
 #endif /* __ASSEMBLER__ */
diff --git a/include/common/ep_info.h b/include/common/ep_info.h
index 4bfa1fa..771572c 100644
--- a/include/common/ep_info.h
+++ b/include/common/ep_info.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,14 +18,21 @@
 
 #define SECURE		EP_SECURE
 #define NON_SECURE	EP_NON_SECURE
+#define REALM		EP_REALM
+#if ENABLE_RME
+#define sec_state_is_valid(s)	(((s) == SECURE) ||	\
+				((s) == NON_SECURE) ||	\
+				((s) == REALM))
+#else
 #define sec_state_is_valid(s) (((s) == SECURE) || ((s) == NON_SECURE))
+#endif
 
 #define PARAM_EP_SECURITY_MASK	EP_SECURITY_MASK
 
 #define NON_EXECUTABLE	EP_NON_EXECUTABLE
 #define EXECUTABLE	EP_EXECUTABLE
 
-/* Secure or Non-secure image */
+/* Get/set security state of an image */
 #define GET_SECURITY_STATE(x) ((x) & EP_SECURITY_MASK)
 #define SET_SECURITY_STATE(x, security) \
 			((x) = ((x) & ~EP_SECURITY_MASK) | (security))
diff --git a/include/common/fdt_wrappers.h b/include/common/fdt_wrappers.h
index e8b3933..98e7a3e 100644
--- a/include/common/fdt_wrappers.h
+++ b/include/common/fdt_wrappers.h
@@ -48,4 +48,9 @@
 	return fdt32_to_cpu(dtb_header[1]);
 }
 
+#define fdt_for_each_compatible_node(dtb, node, compatible_str)       \
+for (node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);   \
+     node >= 0;                                                       \
+     node = fdt_node_offset_by_compatible(dtb, node, compatible_str))
+
 #endif /* FDT_WRAPPERS_H */
diff --git a/include/common/hw_crc32.h b/include/common/tf_crc32.h
similarity index 62%
rename from include/common/hw_crc32.h
rename to include/common/tf_crc32.h
index 0d14d57..38c56a5 100644
--- a/include/common/hw_crc32.h
+++ b/include/common/tf_crc32.h
@@ -4,13 +4,13 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef HW_CRC32_H
-#define HW_CRC32_H
+#ifndef TF_CRC32_H
+#define TF_CRC32_H
 
 #include <stddef.h>
 #include <stdint.h>
 
 /* compute CRC using Arm intrinsic function */
-uint32_t hw_crc32(uint32_t crc, const unsigned char *buf, size_t size);
+uint32_t tf_crc32(uint32_t crc, const unsigned char *buf, size_t size);
 
-#endif /* HW_CRC32_H */
+#endif /* TF_CRC32_H */
diff --git a/include/drivers/arm/arm_gicv3_common.h b/include/drivers/arm/arm_gicv3_common.h
index b88b59f..e5df311 100644
--- a/include/drivers/arm/arm_gicv3_common.h
+++ b/include/drivers/arm/arm_gicv3_common.h
@@ -17,4 +17,8 @@
 #define WAKER_SL_BIT		(1U << WAKER_SL_SHIFT)
 #define WAKER_QSC_BIT		(1U << WAKER_QSC_SHIFT)
 
+#define IIDR_MODEL_ARM_GIC_600		U(0x0200043b)
+#define IIDR_MODEL_ARM_GIC_600AE	U(0x0300043b)
+#define IIDR_MODEL_ARM_GIC_700		U(0x0400043b)
+
 #endif /* ARM_GICV3_COMMON_H */
diff --git a/include/drivers/arm/ethosn.h b/include/drivers/arm/ethosn.h
index 6de2abb..9310733 100644
--- a/include/drivers/arm/ethosn.h
+++ b/include/drivers/arm/ethosn.h
@@ -38,8 +38,8 @@
 #define is_ethosn_fid(_fid) (((_fid) & ETHOSN_FID_MASK) == ETHOSN_FID_VALUE)
 
 /* Service version  */
-#define ETHOSN_VERSION_MAJOR U(0)
-#define ETHOSN_VERSION_MINOR U(1)
+#define ETHOSN_VERSION_MAJOR U(1)
+#define ETHOSN_VERSION_MINOR U(0)
 
 /* Return codes for function calls */
 #define ETHOSN_SUCCESS			 0
@@ -47,10 +47,10 @@
 /* -2 Reserved for NOT_REQUIRED */
 /* -3 Reserved for INVALID_PARAMETER */
 #define ETHOSN_FAILURE			-4
-#define ETHOSN_CORE_IDX_OUT_OF_RANGE	-5
+#define ETHOSN_UNKNOWN_CORE_ADDRESS	-5
 
 uintptr_t ethosn_smc_handler(uint32_t smc_fid,
-			     u_register_t core_idx,
+			     u_register_t core_addr,
 			     u_register_t x2,
 			     u_register_t x3,
 			     u_register_t x4,
diff --git a/include/drivers/arm/gic600ae_fmu.h b/include/drivers/arm/gic600ae_fmu.h
new file mode 100644
index 0000000..691ffc7
--- /dev/null
+++ b/include/drivers/arm/gic600ae_fmu.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GIC600AE_FMU_H
+#define GIC600AE_FMU_H
+
+/*******************************************************************************
+ * GIC600-AE FMU register offsets and constants
+ ******************************************************************************/
+#define GICFMU_ERRFR_LO		U(0x000)
+#define GICFMU_ERRFR_HI		U(0x004)
+#define GICFMU_ERRCTLR_LO	U(0x008)
+#define GICFMU_ERRCTLR_HI	U(0x00C)
+#define GICFMU_ERRSTATUS_LO	U(0x010)
+#define GICFMU_ERRSTATUS_HI	U(0x014)
+#define GICFMU_ERRGSR_LO	U(0xE00)
+#define GICFMU_ERRGSR_HI	U(0xE04)
+#define GICFMU_KEY		U(0xEA0)
+#define GICFMU_PINGCTLR		U(0xEA4)
+#define GICFMU_PINGNOW		U(0xEA8)
+#define GICFMU_SMEN		U(0xEB0)
+#define GICFMU_SMINJERR		U(0xEB4)
+#define GICFMU_PINGMASK_LO	U(0xEC0)
+#define GICFMU_PINGMASK_HI	U(0xEC4)
+#define GICFMU_STATUS		U(0xF00)
+#define GICFMU_ERRIDR		U(0xFC8)
+
+/* ERRCTLR bits */
+#define FMU_ERRCTLR_ED_BIT	BIT(0)
+#define FMU_ERRCTLR_CE_EN_BIT	BIT(1)
+#define FMU_ERRCTLR_UI_BIT	BIT(2)
+#define FMU_ERRCTLR_CI_BIT	BIT(3)
+
+/* SMEN constants */
+#define FMU_SMEN_BLK_SHIFT	U(8)
+#define FMU_SMEN_SMID_SHIFT	U(24)
+
+/* Error record IDs */
+#define FMU_BLK_GICD		U(0)
+#define FMU_BLK_SPICOL		U(1)
+#define FMU_BLK_WAKERQ		U(2)
+#define FMU_BLK_ITS0		U(4)
+#define FMU_BLK_ITS1		U(5)
+#define FMU_BLK_ITS2		U(6)
+#define FMU_BLK_ITS3		U(7)
+#define FMU_BLK_ITS4		U(8)
+#define FMU_BLK_ITS5		U(9)
+#define FMU_BLK_ITS6		U(10)
+#define FMU_BLK_ITS7		U(11)
+#define FMU_BLK_PPI0		U(12)
+#define FMU_BLK_PPI1		U(13)
+#define FMU_BLK_PPI2		U(14)
+#define FMU_BLK_PPI3		U(15)
+#define FMU_BLK_PPI4		U(16)
+#define FMU_BLK_PPI5		U(17)
+#define FMU_BLK_PPI6		U(18)
+#define FMU_BLK_PPI7		U(19)
+#define FMU_BLK_PPI8		U(20)
+#define FMU_BLK_PPI9		U(21)
+#define FMU_BLK_PPI10		U(22)
+#define FMU_BLK_PPI11		U(23)
+#define FMU_BLK_PPI12		U(24)
+#define FMU_BLK_PPI13		U(25)
+#define FMU_BLK_PPI14		U(26)
+#define FMU_BLK_PPI15		U(27)
+#define FMU_BLK_PPI16		U(28)
+#define FMU_BLK_PPI17		U(29)
+#define FMU_BLK_PPI18		U(30)
+#define FMU_BLK_PPI19		U(31)
+#define FMU_BLK_PPI20		U(32)
+#define FMU_BLK_PPI21		U(33)
+#define FMU_BLK_PPI22		U(34)
+#define FMU_BLK_PPI23		U(35)
+#define FMU_BLK_PPI24		U(36)
+#define FMU_BLK_PPI25		U(37)
+#define FMU_BLK_PPI26		U(38)
+#define FMU_BLK_PPI27		U(39)
+#define FMU_BLK_PPI28		U(40)
+#define FMU_BLK_PPI29		U(41)
+#define FMU_BLK_PPI30		U(42)
+#define FMU_BLK_PPI31		U(43)
+#define FMU_BLK_PRESENT_MASK	U(0xFFFFFFFFFFF)
+
+/* Safety Mechamism limit */
+#define FMU_SMID_GICD_MAX	U(33)
+#define FMU_SMID_SPICOL_MAX	U(5)
+#define FMU_SMID_WAKERQ_MAX	U(2)
+#define FMU_SMID_ITS_MAX	U(14)
+#define FMU_SMID_PPI_MAX	U(12)
+
+/* MBIST Safety Mechanism ID */
+#define GICD_MBIST_REQ_ERROR	U(23)
+#define GICD_FMU_CLKGATE_ERROR	U(33)
+#define PPI_MBIST_REQ_ERROR	U(10)
+#define PPI_FMU_CLKGATE_ERROR	U(12)
+#define ITS_MBIST_REQ_ERROR	U(13)
+#define ITS_FMU_CLKGATE_ERROR	U(14)
+
+/* ERRSTATUS bits */
+#define FMU_ERRSTATUS_V_BIT	BIT(30)
+#define FMU_ERRSTATUS_UE_BIT	BIT(29)
+#define FMU_ERRSTATUS_OV_BIT	BIT(27)
+#define FMU_ERRSTATUS_CE_BITS	(BIT(25) | BIT(24))
+#define FMU_ERRSTATUS_CLEAR	(FMU_ERRSTATUS_V_BIT | FMU_ERRSTATUS_UE_BIT | \
+				 FMU_ERRSTATUS_OV_BIT | FMU_ERRSTATUS_CE_BITS)
+
+/* PINGCTLR constants */
+#define FMU_PINGCTLR_INTDIFF_SHIFT	U(16)
+#define FMU_PINGCTLR_TIMEOUTVAL_SHIFT	U(4)
+#define FMU_PINGCTLR_EN_BIT		BIT(0)
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+
+/*******************************************************************************
+ * GIC600 FMU EL3 driver API
+ ******************************************************************************/
+uint64_t gic_fmu_read_errfr(uintptr_t base, unsigned int n);
+uint64_t gic_fmu_read_errctlr(uintptr_t base, unsigned int n);
+uint64_t gic_fmu_read_errstatus(uintptr_t base, unsigned int n);
+uint64_t gic_fmu_read_errgsr(uintptr_t base);
+uint32_t gic_fmu_read_pingctlr(uintptr_t base);
+uint32_t gic_fmu_read_pingnow(uintptr_t base);
+uint64_t gic_fmu_read_pingmask(uintptr_t base);
+uint32_t gic_fmu_read_status(uintptr_t base);
+uint32_t gic_fmu_read_erridr(uintptr_t base);
+void gic_fmu_write_errctlr(uintptr_t base, unsigned int n, uint64_t val);
+void gic_fmu_write_errstatus(uintptr_t base, unsigned int n, uint64_t val);
+void gic_fmu_write_pingctlr(uintptr_t base, uint32_t val);
+void gic_fmu_write_pingnow(uintptr_t base, uint32_t val);
+void gic_fmu_write_smen(uintptr_t base, uint32_t val);
+void gic_fmu_write_sminjerr(uintptr_t base, uint32_t val);
+void gic_fmu_write_pingmask(uintptr_t base, uint64_t val);
+
+void gic600_fmu_init(uint64_t base, uint64_t blk_present_mask, bool errctlr_ce_en, bool errctlr_ue_en);
+void gic600_fmu_enable_ping(uint64_t base, uint64_t blk_present_mask,
+		unsigned int timeout_val, unsigned int interval_diff);
+void gic600_fmu_print_sm_info(uint64_t base, unsigned int blk, unsigned int smid);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* GIC600AE_FMU_H */
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index d8ac4cb..fa8946b 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.h
@@ -153,11 +153,8 @@
 /*******************************************************************************
  * Common GIC Redistributor interface registers & constants
  ******************************************************************************/
-#if GIC_ENABLE_V4_EXTN
-#define GICR_PCPUBASE_SHIFT	0x12
-#else
-#define GICR_PCPUBASE_SHIFT	0x11
-#endif
+#define GICR_V4_PCPUBASE_SHIFT	0x12
+#define GICR_V3_PCPUBASE_SHIFT	0x11
 #define GICR_SGIBASE_OFFSET	U(65536)	/* 64 KB */
 #define GICR_CTLR		U(0x0)
 #define GICR_IIDR		U(0x04)
@@ -212,12 +209,14 @@
 #define TYPER_AFF_VAL_SHIFT	32
 #define TYPER_PROC_NUM_SHIFT	8
 #define TYPER_LAST_SHIFT	4
+#define TYPER_VLPI_SHIFT	1
 
 #define TYPER_AFF_VAL_MASK	U(0xffffffff)
 #define TYPER_PROC_NUM_MASK	U(0xffff)
 #define TYPER_LAST_MASK		U(0x1)
 
 #define TYPER_LAST_BIT		BIT_32(TYPER_LAST_SHIFT)
+#define TYPER_VLPI_BIT		BIT_32(TYPER_VLPI_SHIFT)
 
 #define TYPER_PPI_NUM_SHIFT	U(27)
 #define TYPER_PPI_NUM_MASK	U(0x1f)
@@ -312,6 +311,19 @@
 #include <drivers/arm/gic_common.h>
 #include <lib/utils_def.h>
 
+static inline uintptr_t gicv3_redist_size(uint64_t typer_val)
+{
+#if GIC_ENABLE_V4_EXTN
+	if ((typer_val & TYPER_VLPI_BIT) != 0U) {
+		return 1U << GICR_V4_PCPUBASE_SHIFT;
+	} else {
+		return 1U << GICR_V3_PCPUBASE_SHIFT;
+	}
+#else
+	return 1U << GICR_V3_PCPUBASE_SHIFT;
+#endif
+}
+
 static inline bool gicv3_is_intr_id_special_identifier(unsigned int id)
 {
 	return (id >= PENDING_G1S_INTID) && (id <= GIC_SPURIOUS_INTERRUPT);
diff --git a/include/drivers/arm/tzc400.h b/include/drivers/arm/tzc400.h
index 5f8a48f..765c130 100644
--- a/include/drivers/arm/tzc400.h
+++ b/include/drivers/arm/tzc400.h
@@ -109,6 +109,7 @@
 			  unsigned long long region_top,
 			  unsigned int sec_attr,
 			  unsigned int nsaid_permissions);
+void tzc400_update_filters(unsigned int region, unsigned int filters);
 void tzc400_set_action(unsigned int action);
 void tzc400_enable_filters(void);
 void tzc400_disable_filters(void);
diff --git a/include/drivers/fwu/fwu.h b/include/drivers/fwu/fwu.h
new file mode 100644
index 0000000..ae06da9
--- /dev/null
+++ b/include/drivers/fwu/fwu.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FWU_H
+#define FWU_H
+
+#include <stdbool.h>
+
+void fwu_init(void);
+bool fwu_is_trial_run_state(void);
+
+#endif /* FWU_H */
diff --git a/include/drivers/fwu/fwu_metadata.h b/include/drivers/fwu/fwu_metadata.h
new file mode 100644
index 0000000..2e88de5
--- /dev/null
+++ b/include/drivers/fwu/fwu_metadata.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * FWU metadata information as per the specification section 4.1:
+ * https://developer.arm.com/documentation/den0118/a/
+ *
+ */
+
+#ifndef FWU_METADATA_H
+#define FWU_METADATA_H
+
+#include <stdint.h>
+#include <tools_share/uuid.h>
+
+/* Properties of image in a bank */
+struct fwu_image_properties {
+
+	/* UUID of the image in this bank */
+	uuid_t img_uuid;
+
+	/* [0]: bit describing the image acceptance status –
+	 *      1 means the image is accepted
+	 * [31:1]: MBZ
+	 */
+	uint32_t accepted;
+
+	/* reserved (MBZ) */
+	uint32_t reserved;
+
+} __packed;
+
+/* Image entry information */
+struct fwu_image_entry {
+
+	/* UUID identifying the image type */
+	uuid_t img_type_uuid;
+
+	/* UUID of the storage volume where the image is located */
+	uuid_t location_uuid;
+
+	/* Properties of images with img_type_uuid in the different FW banks */
+	struct fwu_image_properties img_props[NR_OF_FW_BANKS];
+
+} __packed;
+
+/*
+ * FWU metadata filled by the updater and consumed by TF-A for
+ * various purposes as below:
+ * 1. Get active FW bank.
+ * 2. Rollback to previous working FW bank.
+ * 3. Get properties of all images present in all banks.
+ */
+struct fwu_metadata {
+
+	/* Metadata CRC value */
+	uint32_t crc_32;
+
+	/* Metadata version */
+	uint32_t version;
+
+	/* Bank index with which device boots */
+	uint32_t active_index;
+
+	/* Previous bank index with which device booted successfully */
+	uint32_t previous_active_index;
+
+	/* Image entry information */
+	struct fwu_image_entry img_entry[NR_OF_IMAGES_IN_FW_BANK];
+
+} __packed;
+
+#endif /* FWU_METADATA_H */
diff --git a/include/drivers/io/io_mtd.h b/include/drivers/io/io_mtd.h
index 1395ff6..2b5d9b1 100644
--- a/include/drivers/io/io_mtd.h
+++ b/include/drivers/io/io_mtd.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -44,11 +44,22 @@
 	 * Return 0 on success, a negative error code otherwise.
 	 */
 	int (*write)(unsigned int offset, uintptr_t buffer, size_t length);
+
+	/*
+	 * Look for an offset to be added to the given offset.
+	 *
+	 * @base: Base address of the area.
+	 * @offset: Offset in bytes to start read operation.
+	 * @extra_offset: [out] Offset to be added to the previous offset.
+	 * Return 0 on success, a negative error code otherwise.
+	 */
+	int (*seek)(uintptr_t base, unsigned int offset, size_t *extra_offset);
 } io_mtd_ops_t;
 
 typedef struct io_mtd_dev_spec {
 	unsigned long long device_size;
 	unsigned int erase_size;
+	size_t offset;
 	io_mtd_ops_t ops;
 } io_mtd_dev_spec_t;
 
diff --git a/include/drivers/measured_boot/measured_boot.h b/include/drivers/measured_boot/measured_boot.h
index f8769ab..05be4a9 100644
--- a/include/drivers/measured_boot/measured_boot.h
+++ b/include/drivers/measured_boot/measured_boot.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,9 +11,6 @@
 
 #include <drivers/measured_boot/event_log.h>
 
-/* Platform specific table of image IDs, names and PCRs */
-extern const image_data_t images_data[];
-
 /* Functions' declarations */
 void measured_boot_init(void);
 void measured_boot_finish(void);
diff --git a/include/drivers/nand.h b/include/drivers/nand.h
index 1dbb008..1b78ad4 100644
--- a/include/drivers/nand.h
+++ b/include/drivers/nand.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -46,6 +46,16 @@
 	      size_t *length_read);
 
 /*
+ * Look for an extra offset to be added in case of bad blocks
+ *
+ * @base: Base address of the area
+ * @offset: Byte offset to read from in device
+ * @extra_offset: [out] Extra offset to be added if bad blocks are found
+ * Return: 0 on success, a negative errno on failure
+ */
+int nand_seek_bb(uintptr_t base, unsigned int offset, size_t *extra_offset);
+
+/*
  * Get NAND device instance
  *
  * Return: NAND device instance reference
diff --git a/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h b/include/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h
similarity index 98%
rename from drivers/nxp/auth/csf_hdr_parser/csf_hdr.h
rename to include/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h
index eaead76..ae56d3b 100644
--- a/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h
+++ b/include/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017-2020 NXP
+ * Copyright 2017-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/console/plat_console.h b/include/drivers/nxp/console/plat_console.h
similarity index 100%
rename from drivers/nxp/console/plat_console.h
rename to include/drivers/nxp/console/plat_console.h
diff --git a/drivers/nxp/crypto/caam/include/caam.h b/include/drivers/nxp/crypto/caam/caam.h
similarity index 97%
rename from drivers/nxp/crypto/caam/include/caam.h
rename to include/drivers/nxp/crypto/caam/caam.h
index 580e133..4984b54 100644
--- a/drivers/nxp/crypto/caam/include/caam.h
+++ b/include/drivers/nxp/crypto/caam/caam.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017-2020 NXP
+ * Copyright 2017-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/crypto/caam/include/caam_io.h b/include/drivers/nxp/crypto/caam/caam_io.h
similarity index 97%
rename from drivers/nxp/crypto/caam/include/caam_io.h
rename to include/drivers/nxp/crypto/caam/caam_io.h
index 4fdb04d..b68f836 100644
--- a/drivers/nxp/crypto/caam/include/caam_io.h
+++ b/include/drivers/nxp/crypto/caam/caam_io.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2020 NXP
+ * Copyright 2018-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/crypto/caam/include/hash.h b/include/drivers/nxp/crypto/caam/hash.h
similarity index 98%
rename from drivers/nxp/crypto/caam/include/hash.h
rename to include/drivers/nxp/crypto/caam/hash.h
index 946087d..9136dca 100644
--- a/drivers/nxp/crypto/caam/include/hash.h
+++ b/include/drivers/nxp/crypto/caam/hash.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017-2020 NXP
+ * Copyright 2017-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/crypto/caam/include/jobdesc.h b/include/drivers/nxp/crypto/caam/jobdesc.h
similarity index 97%
rename from drivers/nxp/crypto/caam/include/jobdesc.h
rename to include/drivers/nxp/crypto/caam/jobdesc.h
index 5921f7b..efef228 100644
--- a/drivers/nxp/crypto/caam/include/jobdesc.h
+++ b/include/drivers/nxp/crypto/caam/jobdesc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017-2020 NXP
+ * Copyright 2017-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/crypto/caam/include/jr_driver_config.h b/include/drivers/nxp/crypto/caam/jr_driver_config.h
similarity index 99%
rename from drivers/nxp/crypto/caam/include/jr_driver_config.h
rename to include/drivers/nxp/crypto/caam/jr_driver_config.h
index f25c42e..1b3c447 100644
--- a/drivers/nxp/crypto/caam/include/jr_driver_config.h
+++ b/include/drivers/nxp/crypto/caam/jr_driver_config.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017-2020 NXP
+ * Copyright 2017-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/crypto/caam/include/rsa.h b/include/drivers/nxp/crypto/caam/rsa.h
similarity index 96%
rename from drivers/nxp/crypto/caam/include/rsa.h
rename to include/drivers/nxp/crypto/caam/rsa.h
index bd5dc71..dd9ecdc 100644
--- a/drivers/nxp/crypto/caam/include/rsa.h
+++ b/include/drivers/nxp/crypto/caam/rsa.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017-2020 NXP
+ * Copyright 2017-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/crypto/caam/include/sec_hw_specific.h b/include/drivers/nxp/crypto/caam/sec_hw_specific.h
similarity index 99%
rename from drivers/nxp/crypto/caam/include/sec_hw_specific.h
rename to include/drivers/nxp/crypto/caam/sec_hw_specific.h
index a82a1a0..a4fc022 100644
--- a/drivers/nxp/crypto/caam/include/sec_hw_specific.h
+++ b/include/drivers/nxp/crypto/caam/sec_hw_specific.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017-2020 NXP
+ * Copyright 2017-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/crypto/caam/include/sec_jr_driver.h b/include/drivers/nxp/crypto/caam/sec_jr_driver.h
similarity index 99%
rename from drivers/nxp/crypto/caam/include/sec_jr_driver.h
rename to include/drivers/nxp/crypto/caam/sec_jr_driver.h
index 1381eab..57e0fa0 100644
--- a/drivers/nxp/crypto/caam/include/sec_jr_driver.h
+++ b/include/drivers/nxp/crypto/caam/sec_jr_driver.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017-2020 NXP
+ * Copyright 2017-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/csu/csu.h b/include/drivers/nxp/csu/csu.h
similarity index 96%
rename from drivers/nxp/csu/csu.h
rename to include/drivers/nxp/csu/csu.h
index 9f82feb..3a43e45 100644
--- a/drivers/nxp/csu/csu.h
+++ b/include/drivers/nxp/csu/csu.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 NXP
+ * Copyright 2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/dcfg/dcfg.h b/include/drivers/nxp/dcfg/dcfg.h
similarity index 71%
rename from drivers/nxp/dcfg/dcfg.h
rename to include/drivers/nxp/dcfg/dcfg.h
index 161e295..524450a 100644
--- a/drivers/nxp/dcfg/dcfg.h
+++ b/include/drivers/nxp/dcfg/dcfg.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2020 NXP
+ * Copyright 2018-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -27,23 +27,41 @@
 #endif
 
 typedef struct {
-	bool is_populated;
-	uint8_t mfr_id;
-#if defined(CONFIG_CHASSIS_3_2)
-	uint8_t family;
-	uint8_t dev_id;
+	union {
+		uint32_t val;
+		struct {
+			uint32_t min_ver:4;
+			uint32_t maj_ver:4;
+#if defined(CONFIG_CHASSIS_3) || defined(CONFIG_CHASSIS_3_2)
+			uint32_t personality:6;
+			uint32_t rsv1:2;
+#elif defined(CONFIG_CHASSIS_2)
+			uint32_t personality:8;
+
 #endif
-	uint8_t personality;
+#if defined(CONFIG_CHASSIS_3) || defined(CONFIG_CHASSIS_3_2)
+			uint32_t dev_id:6;
+			uint32_t rsv2:2;
+			uint32_t family:4;
+#elif defined(CONFIG_CHASSIS_2)
+			uint32_t dev_id:12;
+#endif
+			uint32_t mfr_id;
+		} __packed bf;
+		struct {
+			uint32_t maj_min:8;
+			uint32_t version; /* SoC version without major and minor info */
+		} __packed bf_ver;
+	} __packed svr_reg;
 	bool sec_enabled;
-	uint8_t maj_ver;
-	uint8_t min_ver;
+	bool is_populated;
 } soc_info_t;
 
 typedef struct {
 	bool is_populated;
 	uint8_t ocram_present;
 	uint8_t ddrc1_present;
-#if defined(CONFIG_CHASSIS_3_2)
+#if defined(CONFIG_CHASSIS_3) || defined(CONFIG_CHASSIS_3_2)
 	uint8_t ddrc2_present;
 #endif
 } devdisr5_info_t;
diff --git a/drivers/nxp/dcfg/dcfg_lsch2.h b/include/drivers/nxp/dcfg/dcfg_lsch2.h
similarity index 90%
rename from drivers/nxp/dcfg/dcfg_lsch2.h
rename to include/drivers/nxp/dcfg/dcfg_lsch2.h
index c021aa1..1e56729 100644
--- a/drivers/nxp/dcfg/dcfg_lsch2.h
+++ b/include/drivers/nxp/dcfg/dcfg_lsch2.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 NXP
+ * Copyright 2020-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -34,12 +34,10 @@
 
 #define SVR_MFR_ID_MASK			0xF0000000
 #define SVR_MFR_ID_SHIFT		28
-#define SVR_FAMILY_MASK			0xF000000
-#define SVR_FAMILY_SHIFT		24
-#define SVR_DEV_ID_MASK			0x3F0000
+#define SVR_DEV_ID_MASK			0xFFF0000
 #define SVR_DEV_ID_SHIFT		16
-#define SVR_PERSONALITY_MASK		0x3E00
-#define SVR_PERSONALITY_SHIFT		9
+#define SVR_PERSONALITY_MASK		0xFF00
+#define SVR_PERSONALITY_SHIFT		8
 #define SVR_SEC_MASK			0x100
 #define SVR_SEC_SHIFT			8
 #define SVR_MAJ_VER_MASK		0xF0
diff --git a/drivers/nxp/dcfg/dcfg_lsch3.h b/include/drivers/nxp/dcfg/dcfg_lsch3.h
similarity index 95%
rename from drivers/nxp/dcfg/dcfg_lsch3.h
rename to include/drivers/nxp/dcfg/dcfg_lsch3.h
index 8144542..cde86fe 100644
--- a/drivers/nxp/dcfg/dcfg_lsch3.h
+++ b/include/drivers/nxp/dcfg/dcfg_lsch3.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 NXP
+ * Copyright 2020-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -74,4 +74,7 @@
 #define DCFG_BOOTLOCPTRH_OFFSET			0x404
 #define DCFG_COREDISABLEDSR_OFFSET		0x990
 
+/* Reset module bit field */
+#define RSTCR_RESET_REQ         0x2
+
 #endif /*	DCFG_LSCH3_H	*/
diff --git a/drivers/nxp/dcfg/scfg.h b/include/drivers/nxp/dcfg/scfg.h
similarity index 98%
rename from drivers/nxp/dcfg/scfg.h
rename to include/drivers/nxp/dcfg/scfg.h
index 81df9a6..b6e3df5 100644
--- a/drivers/nxp/dcfg/scfg.h
+++ b/include/drivers/nxp/dcfg/scfg.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 NXP
+ * Copyright 2020-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/ddr/include/ddr.h b/include/drivers/nxp/ddr/ddr.h
similarity index 100%
rename from drivers/nxp/ddr/include/ddr.h
rename to include/drivers/nxp/ddr/ddr.h
diff --git a/drivers/nxp/ddr/include/ddr_io.h b/include/drivers/nxp/ddr/ddr_io.h
similarity index 100%
rename from drivers/nxp/ddr/include/ddr_io.h
rename to include/drivers/nxp/ddr/ddr_io.h
diff --git a/drivers/nxp/ddr/include/dimm.h b/include/drivers/nxp/ddr/dimm.h
similarity index 100%
rename from drivers/nxp/ddr/include/dimm.h
rename to include/drivers/nxp/ddr/dimm.h
diff --git a/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h b/include/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h
similarity index 100%
rename from drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h
rename to include/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h
diff --git a/drivers/nxp/ddr/include/immap.h b/include/drivers/nxp/ddr/immap.h
similarity index 100%
rename from drivers/nxp/ddr/include/immap.h
rename to include/drivers/nxp/ddr/immap.h
diff --git a/drivers/nxp/ddr/include/opts.h b/include/drivers/nxp/ddr/opts.h
similarity index 100%
rename from drivers/nxp/ddr/include/opts.h
rename to include/drivers/nxp/ddr/opts.h
diff --git a/drivers/nxp/ddr/include/regs.h b/include/drivers/nxp/ddr/regs.h
similarity index 100%
rename from drivers/nxp/ddr/include/regs.h
rename to include/drivers/nxp/ddr/regs.h
diff --git a/drivers/nxp/ddr/include/utility.h b/include/drivers/nxp/ddr/utility.h
similarity index 100%
rename from drivers/nxp/ddr/include/utility.h
rename to include/drivers/nxp/ddr/utility.h
diff --git a/include/drivers/nxp/flexspi/flash_info.h b/include/drivers/nxp/flexspi/flash_info.h
index 6df79c9..d0ffc86 100644
--- a/include/drivers/nxp/flexspi/flash_info.h
+++ b/include/drivers/nxp/flexspi/flash_info.h
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: BSD-3-Clause
 /*
- *  Copyright 2020 NXP
+ *  Copyright 2020-2021 NXP
  */
 
 /**
@@ -12,6 +12,7 @@
 
 #define SZ_16M_BYTES			0x1000000U
 
+/* Start of "if defined(CONFIG_MT25QU512A)" */
 #if defined(CONFIG_MT25QU512A)
 #define F_SECTOR_64K			0x10000U
 #define F_PAGE_256			0x100U
@@ -22,6 +23,9 @@
 #define F_SECTOR_ERASE_SZ		F_SECTOR_4K
 #endif
 
+/* End of "if defined(CONFIG_MT25QU512A)" */
+
+/* Start of "if defined(CONFIG_MX25U25645G)" */
 #elif defined(CONFIG_MX25U25645G)
 #define F_SECTOR_64K			0x10000U
 #define F_PAGE_256			0x100U
@@ -32,6 +36,9 @@
 #define F_SECTOR_ERASE_SZ		F_SECTOR_4K
 #endif
 
+/* End of "if defined(CONFIG_MX25U25645G)" */
+
+/* Start of "if defined(CONFIG_MX25U51245G)" */
 #elif defined(CONFIG_MX25U51245G)
 #define F_SECTOR_64K			0x10000U
 #define F_PAGE_256			0x100U
@@ -42,6 +49,9 @@
 #define F_SECTOR_ERASE_SZ		F_SECTOR_4K
 #endif
 
+/* End of "if defined(CONFIG_MX25U51245G)" */
+
+/* Start of "if defined(CONFIG_MT35XU512A)" */
 #elif defined(CONFIG_MT35XU512A)
 #define F_SECTOR_128K			0x20000U
 #define F_SECTOR_32K			0x8000U
@@ -52,10 +62,28 @@
 #ifdef CONFIG_FSPI_4K_ERASE
 #define F_SECTOR_ERASE_SZ		F_SECTOR_4K
 #endif
-
+/* If Warm boot is enabled for the platform,
+ * count of arm instruction N-OP(s) to mark
+ * the completion of write operation to flash;
+ * varies from one flash to other.
+ */
 #ifdef NXP_WARM_BOOT
 #define FLASH_WR_COMP_WAIT_BY_NOP_COUNT	0x20000
 #endif
 
+/* End of "if defined(CONFIG_MT35XU512A)" */
+
+/* Start of #elif defined(CONFIG_MT35XU02G) */
+#elif defined(CONFIG_MT35XU02G)
+#define F_SECTOR_128K			0x20000U
+#define F_PAGE_256			0x100U
+#define F_SECTOR_4K			0x1000U
+#define F_FLASH_SIZE_BYTES		0x10000000U
+#define F_SECTOR_ERASE_SZ		F_SECTOR_128K
+#ifdef CONFIG_FSPI_4K_ERASE
+#define F_SECTOR_ERASE_SZ		F_SECTOR_4K
 #endif
+
+#endif /* End of #elif defined(CONFIG_MT35XU02G) */
+
 #endif /* FLASH_INFO_H */
diff --git a/drivers/nxp/gic/include/gicv2/plat_gic.h b/include/drivers/nxp/gic/gicv2/plat_gic.h
similarity index 100%
rename from drivers/nxp/gic/include/gicv2/plat_gic.h
rename to include/drivers/nxp/gic/gicv2/plat_gic.h
diff --git a/drivers/nxp/gic/include/gicv3/plat_gic.h b/include/drivers/nxp/gic/gicv3/plat_gic.h
similarity index 100%
rename from drivers/nxp/gic/include/gicv3/plat_gic.h
rename to include/drivers/nxp/gic/gicv3/plat_gic.h
diff --git a/drivers/nxp/gpio/nxp_gpio.h b/include/drivers/nxp/gpio/nxp_gpio.h
similarity index 100%
rename from drivers/nxp/gpio/nxp_gpio.h
rename to include/drivers/nxp/gpio/nxp_gpio.h
diff --git a/drivers/nxp/i2c/i2c.h b/include/drivers/nxp/i2c/i2c.h
similarity index 97%
rename from drivers/nxp/i2c/i2c.h
rename to include/drivers/nxp/i2c/i2c.h
index 925bbc0..85e6eb4 100644
--- a/drivers/nxp/i2c/i2c.h
+++ b/include/drivers/nxp/i2c/i2c.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2020 NXP
+ * Copyright 2016-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/interconnect/ls_interconnect.h b/include/drivers/nxp/interconnect/ls_interconnect.h
similarity index 92%
rename from drivers/nxp/interconnect/ls_interconnect.h
rename to include/drivers/nxp/interconnect/ls_interconnect.h
index 26787fb..777089c 100644
--- a/drivers/nxp/interconnect/ls_interconnect.h
+++ b/include/drivers/nxp/interconnect/ls_interconnect.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 NXP
+ * Copyright 2020-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/pmu/pmu.h b/include/drivers/nxp/pmu/pmu.h
similarity index 100%
rename from drivers/nxp/pmu/pmu.h
rename to include/drivers/nxp/pmu/pmu.h
diff --git a/drivers/nxp/qspi/qspi.h b/include/drivers/nxp/qspi/qspi.h
similarity index 100%
rename from drivers/nxp/qspi/qspi.h
rename to include/drivers/nxp/qspi/qspi.h
diff --git a/drivers/nxp/sd/sd_mmc.h b/include/drivers/nxp/sd/sd_mmc.h
similarity index 99%
rename from drivers/nxp/sd/sd_mmc.h
rename to include/drivers/nxp/sd/sd_mmc.h
index 29ad328..32b41f1 100644
--- a/drivers/nxp/sd/sd_mmc.h
+++ b/include/drivers/nxp/sd/sd_mmc.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2015, 2016 Freescale Semiconductor, Inc.
- * Copyright 2017-2020 NXP
+ * Copyright 2017-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/sec_mon/snvs.h b/include/drivers/nxp/sec_mon/snvs.h
similarity index 100%
rename from drivers/nxp/sec_mon/snvs.h
rename to include/drivers/nxp/sec_mon/snvs.h
diff --git a/drivers/nxp/sfp/fuse_prov.h b/include/drivers/nxp/sfp/fuse_prov.h
similarity index 100%
rename from drivers/nxp/sfp/fuse_prov.h
rename to include/drivers/nxp/sfp/fuse_prov.h
diff --git a/drivers/nxp/sfp/sfp.h b/include/drivers/nxp/sfp/sfp.h
similarity index 100%
rename from drivers/nxp/sfp/sfp.h
rename to include/drivers/nxp/sfp/sfp.h
diff --git a/drivers/nxp/sfp/sfp_error_codes.h b/include/drivers/nxp/sfp/sfp_error_codes.h
similarity index 100%
rename from drivers/nxp/sfp/sfp_error_codes.h
rename to include/drivers/nxp/sfp/sfp_error_codes.h
diff --git a/drivers/nxp/timer/nxp_timer.h b/include/drivers/nxp/timer/nxp_timer.h
similarity index 100%
rename from drivers/nxp/timer/nxp_timer.h
rename to include/drivers/nxp/timer/nxp_timer.h
diff --git a/drivers/nxp/tzc/plat_tzc400.h b/include/drivers/nxp/tzc/plat_tzc400.h
similarity index 100%
rename from drivers/nxp/tzc/plat_tzc400.h
rename to include/drivers/nxp/tzc/plat_tzc400.h
diff --git a/include/drivers/st/stm32mp1_rcc.h b/include/drivers/st/stm32mp1_rcc.h
index 2ffc3b2..14f93fd 100644
--- a/include/drivers/st/stm32mp1_rcc.h
+++ b/include/drivers/st/stm32mp1_rcc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2015-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,508 +9,1158 @@
 
 #include <lib/utils_def.h>
 
-#define RCC_TZCR			U(0x00)
-#define RCC_OCENSETR			U(0x0C)
-#define RCC_OCENCLRR			U(0x10)
-#define RCC_HSICFGR			U(0x18)
-#define RCC_CSICFGR			U(0x1C)
-#define RCC_MPCKSELR			U(0x20)
-#define RCC_ASSCKSELR			U(0x24)
-#define RCC_RCK12SELR			U(0x28)
-#define RCC_MPCKDIVR			U(0x2C)
-#define RCC_AXIDIVR			U(0x30)
-#define RCC_APB4DIVR			U(0x3C)
-#define RCC_APB5DIVR			U(0x40)
-#define RCC_RTCDIVR			U(0x44)
-#define RCC_MSSCKSELR			U(0x48)
-#define RCC_PLL1CR			U(0x80)
-#define RCC_PLL1CFGR1			U(0x84)
-#define RCC_PLL1CFGR2			U(0x88)
-#define RCC_PLL1FRACR			U(0x8C)
-#define RCC_PLL1CSGR			U(0x90)
-#define RCC_PLL2CR			U(0x94)
-#define RCC_PLL2CFGR1			U(0x98)
-#define RCC_PLL2CFGR2			U(0x9C)
-#define RCC_PLL2FRACR			U(0xA0)
-#define RCC_PLL2CSGR			U(0xA4)
-#define RCC_I2C46CKSELR			U(0xC0)
-#define RCC_SPI6CKSELR			U(0xC4)
-#define RCC_UART1CKSELR			U(0xC8)
-#define RCC_RNG1CKSELR			U(0xCC)
-#define RCC_CPERCKSELR			U(0xD0)
-#define RCC_STGENCKSELR			U(0xD4)
-#define RCC_DDRITFCR			U(0xD8)
-#define RCC_MP_BOOTCR			U(0x100)
-#define RCC_MP_SREQSETR			U(0x104)
-#define RCC_MP_SREQCLRR			U(0x108)
-#define RCC_MP_GCR			U(0x10C)
-#define RCC_MP_APRSTCR			U(0x110)
-#define RCC_MP_APRSTSR			U(0x114)
-#define RCC_BDCR			U(0x140)
-#define RCC_RDLSICR			U(0x144)
-#define RCC_APB4RSTSETR			U(0x180)
-#define RCC_APB4RSTCLRR			U(0x184)
-#define RCC_APB5RSTSETR			U(0x188)
-#define RCC_APB5RSTCLRR			U(0x18C)
-#define RCC_AHB5RSTSETR			U(0x190)
-#define RCC_AHB5RSTCLRR			U(0x194)
-#define RCC_AHB6RSTSETR			U(0x198)
-#define RCC_AHB6RSTCLRR			U(0x19C)
-#define RCC_TZAHB6RSTSETR		U(0x1A0)
-#define RCC_TZAHB6RSTCLRR		U(0x1A4)
-#define RCC_MP_APB4ENSETR		U(0x200)
-#define RCC_MP_APB4ENCLRR		U(0x204)
-#define RCC_MP_APB5ENSETR		U(0x208)
-#define RCC_MP_APB5ENCLRR		U(0x20C)
-#define RCC_MP_AHB5ENSETR		U(0x210)
-#define RCC_MP_AHB5ENCLRR		U(0x214)
-#define RCC_MP_AHB6ENSETR		U(0x218)
-#define RCC_MP_AHB6ENCLRR		U(0x21C)
-#define RCC_MP_TZAHB6ENSETR		U(0x220)
-#define RCC_MP_TZAHB6ENCLRR		U(0x224)
-#define RCC_MC_APB4ENSETR		U(0x280)
-#define RCC_MC_APB4ENCLRR		U(0x284)
-#define RCC_MC_APB5ENSETR		U(0x288)
-#define RCC_MC_APB5ENCLRR		U(0x28C)
-#define RCC_MC_AHB5ENSETR		U(0x290)
-#define RCC_MC_AHB5ENCLRR		U(0x294)
-#define RCC_MC_AHB6ENSETR		U(0x298)
-#define RCC_MC_AHB6ENCLRR		U(0x29C)
-#define RCC_MP_APB4LPENSETR		U(0x300)
-#define RCC_MP_APB4LPENCLRR		U(0x304)
-#define RCC_MP_APB5LPENSETR		U(0x308)
-#define RCC_MP_APB5LPENCLRR		U(0x30C)
-#define RCC_MP_AHB5LPENSETR		U(0x310)
-#define RCC_MP_AHB5LPENCLRR		U(0x314)
-#define RCC_MP_AHB6LPENSETR		U(0x318)
-#define RCC_MP_AHB6LPENCLRR		U(0x31C)
-#define RCC_MP_TZAHB6LPENSETR		U(0x320)
-#define RCC_MP_TZAHB6LPENCLRR		U(0x324)
-#define RCC_MC_APB4LPENSETR		U(0x380)
-#define RCC_MC_APB4LPENCLRR		U(0x384)
-#define RCC_MC_APB5LPENSETR		U(0x388)
-#define RCC_MC_APB5LPENCLRR		U(0x38C)
-#define RCC_MC_AHB5LPENSETR		U(0x390)
-#define RCC_MC_AHB5LPENCLRR		U(0x394)
-#define RCC_MC_AHB6LPENSETR		U(0x398)
-#define RCC_MC_AHB6LPENCLRR		U(0x39C)
-#define RCC_BR_RSTSCLRR			U(0x400)
-#define RCC_MP_GRSTCSETR		U(0x404)
-#define RCC_MP_RSTSCLRR			U(0x408)
-#define RCC_MP_IWDGFZSETR		U(0x40C)
-#define RCC_MP_IWDGFZCLRR		U(0x410)
-#define RCC_MP_CIER			U(0x414)
-#define RCC_MP_CIFR			U(0x418)
-#define RCC_PWRLPDLYCR			U(0x41C)
-#define RCC_MP_RSTSSETR			U(0x420)
-#define RCC_MCO1CFGR			U(0x800)
-#define RCC_MCO2CFGR			U(0x804)
-#define RCC_OCRDYR			U(0x808)
-#define RCC_DBGCFGR			U(0x80C)
-#define RCC_RCK3SELR			U(0x820)
-#define RCC_RCK4SELR			U(0x824)
-#define RCC_TIMG1PRER			U(0x828)
-#define RCC_TIMG2PRER			U(0x82C)
-#define RCC_MCUDIVR			U(0x830)
-#define RCC_APB1DIVR			U(0x834)
-#define RCC_APB2DIVR			U(0x838)
-#define RCC_APB3DIVR			U(0x83C)
-#define RCC_PLL3CR			U(0x880)
-#define RCC_PLL3CFGR1			U(0x884)
-#define RCC_PLL3CFGR2			U(0x888)
-#define RCC_PLL3FRACR			U(0x88C)
-#define RCC_PLL3CSGR			U(0x890)
-#define RCC_PLL4CR			U(0x894)
-#define RCC_PLL4CFGR1			U(0x898)
-#define RCC_PLL4CFGR2			U(0x89C)
-#define RCC_PLL4FRACR			U(0x8A0)
-#define RCC_PLL4CSGR			U(0x8A4)
-#define RCC_I2C12CKSELR			U(0x8C0)
-#define RCC_I2C35CKSELR			U(0x8C4)
-#define RCC_SAI1CKSELR			U(0x8C8)
-#define RCC_SAI2CKSELR			U(0x8CC)
-#define RCC_SAI3CKSELR			U(0x8D0)
-#define RCC_SAI4CKSELR			U(0x8D4)
-#define RCC_SPI2S1CKSELR		U(0x8D8)
-#define RCC_SPI2S23CKSELR		U(0x8DC)
-#define RCC_SPI45CKSELR			U(0x8E0)
-#define RCC_UART6CKSELR			U(0x8E4)
-#define RCC_UART24CKSELR		U(0x8E8)
-#define RCC_UART35CKSELR		U(0x8EC)
-#define RCC_UART78CKSELR		U(0x8F0)
-#define RCC_SDMMC12CKSELR		U(0x8F4)
-#define RCC_SDMMC3CKSELR		U(0x8F8)
-#define RCC_ETHCKSELR			U(0x8FC)
-#define RCC_QSPICKSELR			U(0x900)
-#define RCC_FMCCKSELR			U(0x904)
-#define RCC_FDCANCKSELR			U(0x90C)
-#define RCC_SPDIFCKSELR			U(0x914)
-#define RCC_CECCKSELR			U(0x918)
-#define RCC_USBCKSELR			U(0x91C)
-#define RCC_RNG2CKSELR			U(0x920)
-#define RCC_DSICKSELR			U(0x924)
-#define RCC_ADCCKSELR			U(0x928)
-#define RCC_LPTIM45CKSELR		U(0x92C)
-#define RCC_LPTIM23CKSELR		U(0x930)
-#define RCC_LPTIM1CKSELR		U(0x934)
-#define RCC_APB1RSTSETR			U(0x980)
-#define RCC_APB1RSTCLRR			U(0x984)
-#define RCC_APB2RSTSETR			U(0x988)
-#define RCC_APB2RSTCLRR			U(0x98C)
-#define RCC_APB3RSTSETR			U(0x990)
-#define RCC_APB3RSTCLRR			U(0x994)
-#define RCC_AHB2RSTSETR			U(0x998)
-#define RCC_AHB2RSTCLRR			U(0x99C)
-#define RCC_AHB3RSTSETR			U(0x9A0)
-#define RCC_AHB3RSTCLRR			U(0x9A4)
-#define RCC_AHB4RSTSETR			U(0x9A8)
-#define RCC_AHB4RSTCLRR			U(0x9AC)
-#define RCC_MP_APB1ENSETR		U(0xA00)
-#define RCC_MP_APB1ENCLRR		U(0xA04)
-#define RCC_MP_APB2ENSETR		U(0xA08)
-#define RCC_MP_APB2ENCLRR		U(0xA0C)
-#define RCC_MP_APB3ENSETR		U(0xA10)
-#define RCC_MP_APB3ENCLRR		U(0xA14)
-#define RCC_MP_AHB2ENSETR		U(0xA18)
-#define RCC_MP_AHB2ENCLRR		U(0xA1C)
-#define RCC_MP_AHB3ENSETR		U(0xA20)
-#define RCC_MP_AHB3ENCLRR		U(0xA24)
-#define RCC_MP_AHB4ENSETR		U(0xA28)
-#define RCC_MP_AHB4ENCLRR		U(0xA2C)
-#define RCC_MP_MLAHBENSETR		U(0xA38)
-#define RCC_MP_MLAHBENCLRR		U(0xA3C)
-#define RCC_MC_APB1ENSETR		U(0xA80)
-#define RCC_MC_APB1ENCLRR		U(0xA84)
-#define RCC_MC_APB2ENSETR		U(0xA88)
-#define RCC_MC_APB2ENCLRR		U(0xA8C)
-#define RCC_MC_APB3ENSETR		U(0xA90)
-#define RCC_MC_APB3ENCLRR		U(0xA94)
-#define RCC_MC_AHB2ENSETR		U(0xA98)
-#define RCC_MC_AHB2ENCLRR		U(0xA9C)
-#define RCC_MC_AHB3ENSETR		U(0xAA0)
-#define RCC_MC_AHB3ENCLRR		U(0xAA4)
-#define RCC_MC_AHB4ENSETR		U(0xAA8)
-#define RCC_MC_AHB4ENCLRR		U(0xAAC)
-#define RCC_MC_AXIMENSETR		U(0xAB0)
-#define RCC_MC_AXIMENCLRR		U(0xAB4)
-#define RCC_MC_MLAHBENSETR		U(0xAB8)
-#define RCC_MC_MLAHBENCLRR		U(0xABC)
-#define RCC_MP_APB1LPENSETR		U(0xB00)
-#define RCC_MP_APB1LPENCLRR		U(0xB04)
-#define RCC_MP_APB2LPENSETR		U(0xB08)
-#define RCC_MP_APB2LPENCLRR		U(0xB0C)
-#define RCC_MP_APB3LPENSETR		U(0xB10)
-#define RCC_MP_APB3LPENCLRR		U(0xB14)
-#define RCC_MP_AHB2LPENSETR		U(0xB18)
-#define RCC_MP_AHB2LPENCLRR		U(0xB1C)
-#define RCC_MP_AHB3LPENSETR		U(0xB20)
-#define RCC_MP_AHB3LPENCLRR		U(0xB24)
-#define RCC_MP_AHB4LPENSETR		U(0xB28)
-#define RCC_MP_AHB4LPENCLRR		U(0xB2C)
-#define RCC_MP_AXIMLPENSETR		U(0xB30)
-#define RCC_MP_AXIMLPENCLRR		U(0xB34)
-#define RCC_MP_MLAHBLPENSETR		U(0xB38)
-#define RCC_MP_MLAHBLPENCLRR		U(0xB3C)
-#define RCC_MC_APB1LPENSETR		U(0xB80)
-#define RCC_MC_APB1LPENCLRR		U(0xB84)
-#define RCC_MC_APB2LPENSETR		U(0xB88)
-#define RCC_MC_APB2LPENCLRR		U(0xB8C)
-#define RCC_MC_APB3LPENSETR		U(0xB90)
-#define RCC_MC_APB3LPENCLRR		U(0xB94)
-#define RCC_MC_AHB2LPENSETR		U(0xB98)
-#define RCC_MC_AHB2LPENCLRR		U(0xB9C)
-#define RCC_MC_AHB3LPENSETR		U(0xBA0)
-#define RCC_MC_AHB3LPENCLRR		U(0xBA4)
-#define RCC_MC_AHB4LPENSETR		U(0xBA8)
-#define RCC_MC_AHB4LPENCLRR		U(0xBAC)
-#define RCC_MC_AXIMLPENSETR		U(0xBB0)
-#define RCC_MC_AXIMLPENCLRR		U(0xBB4)
-#define RCC_MC_MLAHBLPENSETR		U(0xBB8)
-#define RCC_MC_MLAHBLPENCLRR		U(0xBBC)
-#define RCC_MC_RSTSCLRR			U(0xC00)
-#define RCC_MC_CIER			U(0xC14)
-#define RCC_MC_CIFR			U(0xC18)
-#define RCC_VERR			U(0xFF4)
-#define RCC_IDR				U(0xFF8)
-#define RCC_SIDR			U(0xFFC)
+#define RCC_TZCR				U(0x00)
+#define RCC_OCENSETR				U(0x0C)
+#define RCC_OCENCLRR				U(0x10)
+#define RCC_HSICFGR				U(0x18)
+#define RCC_CSICFGR				U(0x1C)
+#define RCC_MPCKSELR				U(0x20)
+#define RCC_ASSCKSELR				U(0x24)
+#define RCC_RCK12SELR				U(0x28)
+#define RCC_MPCKDIVR				U(0x2C)
+#define RCC_AXIDIVR				U(0x30)
+#define RCC_APB4DIVR				U(0x3C)
+#define RCC_APB5DIVR				U(0x40)
+#define RCC_RTCDIVR				U(0x44)
+#define RCC_MSSCKSELR				U(0x48)
+#define RCC_PLL1CR				U(0x80)
+#define RCC_PLL1CFGR1				U(0x84)
+#define RCC_PLL1CFGR2				U(0x88)
+#define RCC_PLL1FRACR				U(0x8C)
+#define RCC_PLL1CSGR				U(0x90)
+#define RCC_PLL2CR				U(0x94)
+#define RCC_PLL2CFGR1				U(0x98)
+#define RCC_PLL2CFGR2				U(0x9C)
+#define RCC_PLL2FRACR				U(0xA0)
+#define RCC_PLL2CSGR				U(0xA4)
+#define RCC_I2C46CKSELR				U(0xC0)
+#define RCC_SPI6CKSELR				U(0xC4)
+#define RCC_UART1CKSELR				U(0xC8)
+#define RCC_RNG1CKSELR				U(0xCC)
+#define RCC_CPERCKSELR				U(0xD0)
+#define RCC_STGENCKSELR				U(0xD4)
+#define RCC_DDRITFCR				U(0xD8)
+#define RCC_MP_BOOTCR				U(0x100)
+#define RCC_MP_SREQSETR				U(0x104)
+#define RCC_MP_SREQCLRR				U(0x108)
+#define RCC_MP_GCR				U(0x10C)
+#define RCC_MP_APRSTCR				U(0x110)
+#define RCC_MP_APRSTSR				U(0x114)
+#define RCC_BDCR				U(0x140)
+#define RCC_RDLSICR				U(0x144)
+#define RCC_APB4RSTSETR				U(0x180)
+#define RCC_APB4RSTCLRR				U(0x184)
+#define RCC_APB5RSTSETR				U(0x188)
+#define RCC_APB5RSTCLRR				U(0x18C)
+#define RCC_AHB5RSTSETR				U(0x190)
+#define RCC_AHB5RSTCLRR				U(0x194)
+#define RCC_AHB6RSTSETR				U(0x198)
+#define RCC_AHB6RSTCLRR				U(0x19C)
+#define RCC_TZAHB6RSTSETR			U(0x1A0)
+#define RCC_TZAHB6RSTCLRR			U(0x1A4)
+#define RCC_MP_APB4ENSETR			U(0x200)
+#define RCC_MP_APB4ENCLRR			U(0x204)
+#define RCC_MP_APB5ENSETR			U(0x208)
+#define RCC_MP_APB5ENCLRR			U(0x20C)
+#define RCC_MP_AHB5ENSETR			U(0x210)
+#define RCC_MP_AHB5ENCLRR			U(0x214)
+#define RCC_MP_AHB6ENSETR			U(0x218)
+#define RCC_MP_AHB6ENCLRR			U(0x21C)
+#define RCC_MP_TZAHB6ENSETR			U(0x220)
+#define RCC_MP_TZAHB6ENCLRR			U(0x224)
+#define RCC_MC_APB4ENSETR			U(0x280)
+#define RCC_MC_APB4ENCLRR			U(0x284)
+#define RCC_MC_APB5ENSETR			U(0x288)
+#define RCC_MC_APB5ENCLRR			U(0x28C)
+#define RCC_MC_AHB5ENSETR			U(0x290)
+#define RCC_MC_AHB5ENCLRR			U(0x294)
+#define RCC_MC_AHB6ENSETR			U(0x298)
+#define RCC_MC_AHB6ENCLRR			U(0x29C)
+#define RCC_MP_APB4LPENSETR			U(0x300)
+#define RCC_MP_APB4LPENCLRR			U(0x304)
+#define RCC_MP_APB5LPENSETR			U(0x308)
+#define RCC_MP_APB5LPENCLRR			U(0x30C)
+#define RCC_MP_AHB5LPENSETR			U(0x310)
+#define RCC_MP_AHB5LPENCLRR			U(0x314)
+#define RCC_MP_AHB6LPENSETR			U(0x318)
+#define RCC_MP_AHB6LPENCLRR			U(0x31C)
+#define RCC_MP_TZAHB6LPENSETR			U(0x320)
+#define RCC_MP_TZAHB6LPENCLRR			U(0x324)
+#define RCC_MC_APB4LPENSETR			U(0x380)
+#define RCC_MC_APB4LPENCLRR			U(0x384)
+#define RCC_MC_APB5LPENSETR			U(0x388)
+#define RCC_MC_APB5LPENCLRR			U(0x38C)
+#define RCC_MC_AHB5LPENSETR			U(0x390)
+#define RCC_MC_AHB5LPENCLRR			U(0x394)
+#define RCC_MC_AHB6LPENSETR			U(0x398)
+#define RCC_MC_AHB6LPENCLRR			U(0x39C)
+#define RCC_BR_RSTSCLRR				U(0x400)
+#define RCC_MP_GRSTCSETR			U(0x404)
+#define RCC_MP_RSTSCLRR				U(0x408)
+#define RCC_MP_IWDGFZSETR			U(0x40C)
+#define RCC_MP_IWDGFZCLRR			U(0x410)
+#define RCC_MP_CIER				U(0x414)
+#define RCC_MP_CIFR				U(0x418)
+#define RCC_PWRLPDLYCR				U(0x41C)
+#define RCC_MP_RSTSSETR				U(0x420)
+#define RCC_MCO1CFGR				U(0x800)
+#define RCC_MCO2CFGR				U(0x804)
+#define RCC_OCRDYR				U(0x808)
+#define RCC_DBGCFGR				U(0x80C)
+#define RCC_RCK3SELR				U(0x820)
+#define RCC_RCK4SELR				U(0x824)
+#define RCC_TIMG1PRER				U(0x828)
+#define RCC_TIMG2PRER				U(0x82C)
+#define RCC_MCUDIVR				U(0x830)
+#define RCC_APB1DIVR				U(0x834)
+#define RCC_APB2DIVR				U(0x838)
+#define RCC_APB3DIVR				U(0x83C)
+#define RCC_PLL3CR				U(0x880)
+#define RCC_PLL3CFGR1				U(0x884)
+#define RCC_PLL3CFGR2				U(0x888)
+#define RCC_PLL3FRACR				U(0x88C)
+#define RCC_PLL3CSGR				U(0x890)
+#define RCC_PLL4CR				U(0x894)
+#define RCC_PLL4CFGR1				U(0x898)
+#define RCC_PLL4CFGR2				U(0x89C)
+#define RCC_PLL4FRACR				U(0x8A0)
+#define RCC_PLL4CSGR				U(0x8A4)
+#define RCC_I2C12CKSELR				U(0x8C0)
+#define RCC_I2C35CKSELR				U(0x8C4)
+#define RCC_SAI1CKSELR				U(0x8C8)
+#define RCC_SAI2CKSELR				U(0x8CC)
+#define RCC_SAI3CKSELR				U(0x8D0)
+#define RCC_SAI4CKSELR				U(0x8D4)
+#define RCC_SPI2S1CKSELR			U(0x8D8)
+#define RCC_SPI2S23CKSELR			U(0x8DC)
+#define RCC_SPI45CKSELR				U(0x8E0)
+#define RCC_UART6CKSELR				U(0x8E4)
+#define RCC_UART24CKSELR			U(0x8E8)
+#define RCC_UART35CKSELR			U(0x8EC)
+#define RCC_UART78CKSELR			U(0x8F0)
+#define RCC_SDMMC12CKSELR			U(0x8F4)
+#define RCC_SDMMC3CKSELR			U(0x8F8)
+#define RCC_ETHCKSELR				U(0x8FC)
+#define RCC_QSPICKSELR				U(0x900)
+#define RCC_FMCCKSELR				U(0x904)
+#define RCC_FDCANCKSELR				U(0x90C)
+#define RCC_SPDIFCKSELR				U(0x914)
+#define RCC_CECCKSELR				U(0x918)
+#define RCC_USBCKSELR				U(0x91C)
+#define RCC_RNG2CKSELR				U(0x920)
+#define RCC_DSICKSELR				U(0x924)
+#define RCC_ADCCKSELR				U(0x928)
+#define RCC_LPTIM45CKSELR			U(0x92C)
+#define RCC_LPTIM23CKSELR			U(0x930)
+#define RCC_LPTIM1CKSELR			U(0x934)
+#define RCC_APB1RSTSETR				U(0x980)
+#define RCC_APB1RSTCLRR				U(0x984)
+#define RCC_APB2RSTSETR				U(0x988)
+#define RCC_APB2RSTCLRR				U(0x98C)
+#define RCC_APB3RSTSETR				U(0x990)
+#define RCC_APB3RSTCLRR				U(0x994)
+#define RCC_AHB2RSTSETR				U(0x998)
+#define RCC_AHB2RSTCLRR				U(0x99C)
+#define RCC_AHB3RSTSETR				U(0x9A0)
+#define RCC_AHB3RSTCLRR				U(0x9A4)
+#define RCC_AHB4RSTSETR				U(0x9A8)
+#define RCC_AHB4RSTCLRR				U(0x9AC)
+#define RCC_MP_APB1ENSETR			U(0xA00)
+#define RCC_MP_APB1ENCLRR			U(0xA04)
+#define RCC_MP_APB2ENSETR			U(0xA08)
+#define RCC_MP_APB2ENCLRR			U(0xA0C)
+#define RCC_MP_APB3ENSETR			U(0xA10)
+#define RCC_MP_APB3ENCLRR			U(0xA14)
+#define RCC_MP_AHB2ENSETR			U(0xA18)
+#define RCC_MP_AHB2ENCLRR			U(0xA1C)
+#define RCC_MP_AHB3ENSETR			U(0xA20)
+#define RCC_MP_AHB3ENCLRR			U(0xA24)
+#define RCC_MP_AHB4ENSETR			U(0xA28)
+#define RCC_MP_AHB4ENCLRR			U(0xA2C)
+#define RCC_MP_MLAHBENSETR			U(0xA38)
+#define RCC_MP_MLAHBENCLRR			U(0xA3C)
+#define RCC_MC_APB1ENSETR			U(0xA80)
+#define RCC_MC_APB1ENCLRR			U(0xA84)
+#define RCC_MC_APB2ENSETR			U(0xA88)
+#define RCC_MC_APB2ENCLRR			U(0xA8C)
+#define RCC_MC_APB3ENSETR			U(0xA90)
+#define RCC_MC_APB3ENCLRR			U(0xA94)
+#define RCC_MC_AHB2ENSETR			U(0xA98)
+#define RCC_MC_AHB2ENCLRR			U(0xA9C)
+#define RCC_MC_AHB3ENSETR			U(0xAA0)
+#define RCC_MC_AHB3ENCLRR			U(0xAA4)
+#define RCC_MC_AHB4ENSETR			U(0xAA8)
+#define RCC_MC_AHB4ENCLRR			U(0xAAC)
+#define RCC_MC_AXIMENSETR			U(0xAB0)
+#define RCC_MC_AXIMENCLRR			U(0xAB4)
+#define RCC_MC_MLAHBENSETR			U(0xAB8)
+#define RCC_MC_MLAHBENCLRR			U(0xABC)
+#define RCC_MP_APB1LPENSETR			U(0xB00)
+#define RCC_MP_APB1LPENCLRR			U(0xB04)
+#define RCC_MP_APB2LPENSETR			U(0xB08)
+#define RCC_MP_APB2LPENCLRR			U(0xB0C)
+#define RCC_MP_APB3LPENSETR			U(0xB10)
+#define RCC_MP_APB3LPENCLRR			U(0xB14)
+#define RCC_MP_AHB2LPENSETR			U(0xB18)
+#define RCC_MP_AHB2LPENCLRR			U(0xB1C)
+#define RCC_MP_AHB3LPENSETR			U(0xB20)
+#define RCC_MP_AHB3LPENCLRR			U(0xB24)
+#define RCC_MP_AHB4LPENSETR			U(0xB28)
+#define RCC_MP_AHB4LPENCLRR			U(0xB2C)
+#define RCC_MP_AXIMLPENSETR			U(0xB30)
+#define RCC_MP_AXIMLPENCLRR			U(0xB34)
+#define RCC_MP_MLAHBLPENSETR			U(0xB38)
+#define RCC_MP_MLAHBLPENCLRR			U(0xB3C)
+#define RCC_MC_APB1LPENSETR			U(0xB80)
+#define RCC_MC_APB1LPENCLRR			U(0xB84)
+#define RCC_MC_APB2LPENSETR			U(0xB88)
+#define RCC_MC_APB2LPENCLRR			U(0xB8C)
+#define RCC_MC_APB3LPENSETR			U(0xB90)
+#define RCC_MC_APB3LPENCLRR			U(0xB94)
+#define RCC_MC_AHB2LPENSETR			U(0xB98)
+#define RCC_MC_AHB2LPENCLRR			U(0xB9C)
+#define RCC_MC_AHB3LPENSETR			U(0xBA0)
+#define RCC_MC_AHB3LPENCLRR			U(0xBA4)
+#define RCC_MC_AHB4LPENSETR			U(0xBA8)
+#define RCC_MC_AHB4LPENCLRR			U(0xBAC)
+#define RCC_MC_AXIMLPENSETR			U(0xBB0)
+#define RCC_MC_AXIMLPENCLRR			U(0xBB4)
+#define RCC_MC_MLAHBLPENSETR			U(0xBB8)
+#define RCC_MC_MLAHBLPENCLRR			U(0xBBC)
+#define RCC_MC_RSTSCLRR				U(0xC00)
+#define RCC_MC_CIER				U(0xC14)
+#define RCC_MC_CIFR				U(0xC18)
+#define RCC_VERR				U(0xFF4)
+#define RCC_IDR					U(0xFF8)
+#define RCC_SIDR				U(0xFFC)
 
-#define RCC_OFFSET_MASK			GENMASK(11, 0)
+/* RCC_TZCR register fields */
+#define RCC_TZCR_TZEN				BIT(0)
+#define RCC_TZCR_MCKPROT			BIT(1)
 
-/* Values for RCC_TZCR register */
-#define RCC_TZCR_TZEN			BIT(0)
-#define RCC_TZCR_MCKPROT		BIT(1)
+/* RCC_OCENSETR register fields */
+#define RCC_OCENSETR_HSION			BIT(0)
+#define RCC_OCENSETR_HSIKERON			BIT(1)
+#define RCC_OCENSETR_CSION			BIT(4)
+#define RCC_OCENSETR_CSIKERON			BIT(5)
+#define RCC_OCENSETR_DIGBYP			BIT(7)
+#define RCC_OCENSETR_HSEON			BIT(8)
+#define RCC_OCENSETR_HSEKERON			BIT(9)
+#define RCC_OCENSETR_HSEBYP			BIT(10)
+#define RCC_OCENSETR_HSECSSON			BIT(11)
 
-/* Used for most of RCC_<x>SELR registers */
-#define RCC_SELR_SRC_MASK		GENMASK(2, 0)
-#define RCC_SELR_REFCLK_SRC_MASK	GENMASK(1, 0)
-#define RCC_SELR_SRCRDY			BIT(31)
+/* RCC_OCENCLRR register fields */
+#define RCC_OCENCLRR_HSION			BIT(0)
+#define RCC_OCENCLRR_HSIKERON			BIT(1)
+#define RCC_OCENCLRR_CSION			BIT(4)
+#define RCC_OCENCLRR_CSIKERON			BIT(5)
+#define RCC_OCENCLRR_DIGBYP			BIT(7)
+#define RCC_OCENCLRR_HSEON			BIT(8)
+#define RCC_OCENCLRR_HSEKERON			BIT(9)
+#define RCC_OCENCLRR_HSEBYP			BIT(10)
 
-/* Values of RCC_MPCKSELR register */
-#define RCC_MPCKSELR_HSI		0x00000000
-#define RCC_MPCKSELR_HSE		0x00000001
-#define RCC_MPCKSELR_PLL		0x00000002
-#define RCC_MPCKSELR_PLL_MPUDIV		0x00000003
-#define RCC_MPCKSELR_MPUSRC_MASK	GENMASK(1, 0)
-#define RCC_MPCKSELR_MPUSRC_SHIFT	0
+/* RCC_HSICFGR register fields */
+#define RCC_HSICFGR_HSIDIV_MASK			GENMASK(1, 0)
+#define RCC_HSICFGR_HSIDIV_SHIFT		0
+#define RCC_HSICFGR_HSITRIM_MASK		GENMASK(14, 8)
+#define RCC_HSICFGR_HSITRIM_SHIFT		8
+#define RCC_HSICFGR_HSICAL_MASK			GENMASK(24, 16)
+#define RCC_HSICFGR_HSICAL_SHIFT		16
+#define RCC_HSICFGR_HSICAL_TEMP_MASK		GENMASK(27, 25)
 
-/* Values of RCC_ASSCKSELR register */
-#define RCC_ASSCKSELR_HSI		0x00000000
-#define RCC_ASSCKSELR_HSE		0x00000001
-#define RCC_ASSCKSELR_PLL		0x00000002
+/* RCC_CSICFGR register fields */
+#define RCC_CSICFGR_CSITRIM_MASK		GENMASK(12, 8)
+#define RCC_CSICFGR_CSITRIM_SHIFT		8
+#define RCC_CSICFGR_CSICAL_MASK			GENMASK(23, 16)
+#define RCC_CSICFGR_CSICAL_SHIFT		16
 
-/* Values of RCC_MSSCKSELR register */
-#define RCC_MSSCKSELR_HSI		0x00000000
-#define RCC_MSSCKSELR_HSE		0x00000001
-#define RCC_MSSCKSELR_CSI		0x00000002
-#define RCC_MSSCKSELR_PLL		0x00000003
+/* RCC_MPCKSELR register fields */
+#define RCC_MPCKSELR_HSI			0x00000000
+#define RCC_MPCKSELR_HSE			0x00000001
+#define RCC_MPCKSELR_PLL			0x00000002
+#define RCC_MPCKSELR_PLL_MPUDIV			0x00000003
+#define RCC_MPCKSELR_MPUSRC_MASK		GENMASK(1, 0)
+#define RCC_MPCKSELR_MPUSRC_SHIFT		0
+#define RCC_MPCKSELR_MPUSRCRDY			BIT(31)
 
-/* Values of RCC_CPERCKSELR register */
-#define RCC_CPERCKSELR_HSI		0x00000000
-#define RCC_CPERCKSELR_CSI		0x00000001
-#define RCC_CPERCKSELR_HSE		0x00000002
-#define RCC_CPERCKSELR_PERSRC_MASK	GENMASK(1, 0)
-#define RCC_CPERCKSELR_PERSRC_SHIFT	0
+/* RCC_ASSCKSELR register fields */
+#define RCC_ASSCKSELR_HSI			0x00000000
+#define RCC_ASSCKSELR_HSE			0x00000001
+#define RCC_ASSCKSELR_PLL			0x00000002
+#define RCC_ASSCKSELR_AXISSRC_MASK		GENMASK(2, 0)
+#define RCC_ASSCKSELR_AXISSRC_SHIFT		0
+#define RCC_ASSCKSELR_AXISSRCRDY		BIT(31)
 
-/* Used for most of DIVR register: max div for RTC */
-#define RCC_DIVR_DIV_MASK		GENMASK(5, 0)
-#define RCC_DIVR_DIVRDY			BIT(31)
+/* RCC_RCK12SELR register fields */
+#define RCC_RCK12SELR_PLL12SRC_MASK		GENMASK(1, 0)
+#define RCC_RCK12SELR_PLL12SRC_SHIFT		0
+#define RCC_RCK12SELR_PLL12SRCRDY		BIT(31)
 
-/* Masks for specific DIVR registers */
-#define RCC_APBXDIV_MASK		GENMASK(2, 0)
-#define RCC_MPUDIV_MASK			GENMASK(2, 0)
-#define RCC_AXIDIV_MASK			GENMASK(2, 0)
-#define RCC_MCUDIV_MASK			GENMASK(3, 0)
+/* RCC_MPCKDIVR register fields */
+#define RCC_MPCKDIVR_MPUDIV_MASK		GENMASK(2, 0)
+#define RCC_MPCKDIVR_MPUDIV_SHIFT		0
+#define RCC_MPCKDIVR_MPUDIVRDY			BIT(31)
 
-/* Used for TIMER Prescaler */
-#define RCC_TIMGXPRER_TIMGXPRE		BIT(0)
+/* RCC_AXIDIVR register fields */
+#define RCC_AXIDIVR_AXIDIV_MASK			GENMASK(2, 0)
+#define RCC_AXIDIVR_AXIDIV_SHIFT		0
+#define RCC_AXIDIVR_AXIDIVRDY			BIT(31)
 
-/* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */
-#define RCC_MP_ENCLRR_OFFSET		U(4)
+/* RCC_APB4DIVR register fields */
+#define RCC_APB4DIVR_APB4DIV_MASK		GENMASK(2, 0)
+#define RCC_APB4DIVR_APB4DIV_SHIFT		0
+#define RCC_APB4DIVR_APB4DIVRDY			BIT(31)
 
-/* Offset between RCC_xxxRSTSETR and RCC_xxxRSTCLRR registers */
-#define RCC_RSTCLRR_OFFSET		U(4)
+/* RCC_APB5DIVR register fields */
+#define RCC_APB5DIVR_APB5DIV_MASK		GENMASK(2, 0)
+#define RCC_APB5DIVR_APB5DIV_SHIFT		0
+#define RCC_APB5DIVR_APB5DIVRDY			BIT(31)
 
-/* Fields of RCC_BDCR register */
-#define RCC_BDCR_LSEON			BIT(0)
-#define RCC_BDCR_LSEBYP			BIT(1)
-#define RCC_BDCR_LSERDY			BIT(2)
-#define RCC_BDCR_DIGBYP			BIT(3)
-#define RCC_BDCR_LSEDRV_MASK		GENMASK(5, 4)
-#define RCC_BDCR_LSEDRV_SHIFT		4
-#define RCC_BDCR_LSECSSON		BIT(8)
-#define RCC_BDCR_RTCCKEN		BIT(20)
-#define RCC_BDCR_RTCSRC_MASK		GENMASK(17, 16)
-#define RCC_BDCR_RTCSRC_SHIFT		16
-#define RCC_BDCR_VSWRST			BIT(31)
+/* RCC_RTCDIVR register fields */
+#define RCC_RTCDIVR_RTCDIV_MASK			GENMASK(5, 0)
+#define RCC_RTCDIVR_RTCDIV_SHIFT		0
 
-/* Fields of RCC_RDLSICR register */
-#define RCC_RDLSICR_LSION		BIT(0)
-#define RCC_RDLSICR_LSIRDY		BIT(1)
+/* RCC_MSSCKSELR register fields */
+#define RCC_MSSCKSELR_HSI			0x00000000
+#define RCC_MSSCKSELR_HSE			0x00000001
+#define RCC_MSSCKSELR_CSI			0x00000002
+#define RCC_MSSCKSELR_PLL			0x00000003
+#define RCC_MSSCKSELR_MCUSSRC_MASK		GENMASK(1, 0)
+#define RCC_MSSCKSELR_MCUSSRC_SHIFT		0
+#define RCC_MSSCKSELR_MCUSSRCRDY		BIT(31)
 
-/* Used for all RCC_PLL<n>CR registers */
-#define RCC_PLLNCR_PLLON		BIT(0)
-#define RCC_PLLNCR_PLLRDY		BIT(1)
-#define RCC_PLLNCR_SSCG_CTRL		BIT(2)
-#define RCC_PLLNCR_DIVPEN		BIT(4)
-#define RCC_PLLNCR_DIVQEN		BIT(5)
-#define RCC_PLLNCR_DIVREN		BIT(6)
-#define RCC_PLLNCR_DIVEN_SHIFT		4
+/* RCC_PLL1CR register fields */
+#define RCC_PLL1CR_PLLON			BIT(0)
+#define RCC_PLL1CR_PLL1RDY			BIT(1)
+#define RCC_PLL1CR_SSCG_CTRL			BIT(2)
+#define RCC_PLL1CR_DIVPEN			BIT(4)
+#define RCC_PLL1CR_DIVQEN			BIT(5)
+#define RCC_PLL1CR_DIVREN			BIT(6)
 
-/* Used for all RCC_PLL<n>CFGR1 registers */
-#define RCC_PLLNCFGR1_DIVM_SHIFT	16
-#define RCC_PLLNCFGR1_DIVM_MASK		GENMASK(21, 16)
-#define RCC_PLLNCFGR1_DIVN_SHIFT	0
-#define RCC_PLLNCFGR1_DIVN_MASK		GENMASK(8, 0)
-/* Only for PLL3 and PLL4 */
-#define RCC_PLLNCFGR1_IFRGE_SHIFT	24
-#define RCC_PLLNCFGR1_IFRGE_MASK	GENMASK(25, 24)
+/* RCC_PLL1CFGR1 register fields */
+#define RCC_PLL1CFGR1_DIVN_MASK			GENMASK(8, 0)
+#define RCC_PLL1CFGR1_DIVN_SHIFT		0
+#define RCC_PLL1CFGR1_DIVM1_MASK		GENMASK(21, 16)
+#define RCC_PLL1CFGR1_DIVM1_SHIFT		16
 
-/* Used for all RCC_PLL<n>CFGR2 registers */
-#define RCC_PLLNCFGR2_DIVX_MASK		GENMASK(6, 0)
-#define RCC_PLLNCFGR2_DIVP_SHIFT	0
-#define RCC_PLLNCFGR2_DIVP_MASK		GENMASK(6, 0)
-#define RCC_PLLNCFGR2_DIVQ_SHIFT	8
-#define RCC_PLLNCFGR2_DIVQ_MASK		GENMASK(14, 8)
-#define RCC_PLLNCFGR2_DIVR_SHIFT	16
-#define RCC_PLLNCFGR2_DIVR_MASK		GENMASK(22, 16)
+/* RCC_PLL1CFGR2 register fields */
+#define RCC_PLL1CFGR2_DIVP_MASK			GENMASK(6, 0)
+#define RCC_PLL1CFGR2_DIVP_SHIFT		0
+#define RCC_PLL1CFGR2_DIVQ_MASK			GENMASK(14, 8)
+#define RCC_PLL1CFGR2_DIVQ_SHIFT		8
+#define RCC_PLL1CFGR2_DIVR_MASK			GENMASK(22, 16)
+#define RCC_PLL1CFGR2_DIVR_SHIFT		16
 
-/* Used for all RCC_PLL<n>FRACR registers */
-#define RCC_PLLNFRACR_FRACV_SHIFT	3
-#define RCC_PLLNFRACR_FRACV_MASK	GENMASK(15, 3)
-#define RCC_PLLNFRACR_FRACLE		BIT(16)
+/* RCC_PLL1FRACR register fields */
+#define RCC_PLL1FRACR_FRACV_MASK		GENMASK(15, 3)
+#define RCC_PLL1FRACR_FRACV_SHIFT		3
+#define RCC_PLL1FRACR_FRACLE			BIT(16)
 
-/* Used for all RCC_PLL<n>CSGR registers */
-#define RCC_PLLNCSGR_INC_STEP_SHIFT	16
-#define RCC_PLLNCSGR_INC_STEP_MASK	GENMASK(30, 16)
-#define RCC_PLLNCSGR_MOD_PER_SHIFT	0
-#define RCC_PLLNCSGR_MOD_PER_MASK	GENMASK(12, 0)
-#define RCC_PLLNCSGR_SSCG_MODE_SHIFT	15
-#define RCC_PLLNCSGR_SSCG_MODE_MASK	BIT(15)
+/* RCC_PLL1CSGR register fields */
+#define RCC_PLL1CSGR_MOD_PER_MASK		GENMASK(12, 0)
+#define RCC_PLL1CSGR_MOD_PER_SHIFT		0
+#define RCC_PLL1CSGR_TPDFN_DIS			BIT(13)
+#define RCC_PLL1CSGR_RPDFN_DIS			BIT(14)
+#define RCC_PLL1CSGR_SSCG_MODE			BIT(15)
+#define RCC_PLL1CSGR_INC_STEP_MASK		GENMASK(30, 16)
+#define RCC_PLL1CSGR_INC_STEP_SHIFT		16
 
-/* Used for RCC_OCENSETR and RCC_OCENCLRR registers */
-#define RCC_OCENR_HSION			BIT(0)
-#define RCC_OCENR_HSIKERON		BIT(1)
-#define RCC_OCENR_CSION			BIT(4)
-#define RCC_OCENR_CSIKERON		BIT(5)
-#define RCC_OCENR_DIGBYP		BIT(7)
-#define RCC_OCENR_HSEON			BIT(8)
-#define RCC_OCENR_HSEKERON		BIT(9)
-#define RCC_OCENR_HSEBYP		BIT(10)
-#define RCC_OCENR_HSECSSON		BIT(11)
+/* RCC_PLL2CR register fields */
+#define RCC_PLL2CR_PLLON			BIT(0)
+#define RCC_PLL2CR_PLL2RDY			BIT(1)
+#define RCC_PLL2CR_SSCG_CTRL			BIT(2)
+#define RCC_PLL2CR_DIVPEN			BIT(4)
+#define RCC_PLL2CR_DIVQEN			BIT(5)
+#define RCC_PLL2CR_DIVREN			BIT(6)
 
-/* Fields of RCC_OCRDYR register */
-#define RCC_OCRDYR_HSIRDY		BIT(0)
-#define RCC_OCRDYR_HSIDIVRDY		BIT(2)
-#define RCC_OCRDYR_CSIRDY		BIT(4)
-#define RCC_OCRDYR_HSERDY		BIT(8)
+/* RCC_PLL2CFGR1 register fields */
+#define RCC_PLL2CFGR1_DIVN_MASK			GENMASK(8, 0)
+#define RCC_PLL2CFGR1_DIVN_SHIFT		0
+#define RCC_PLL2CFGR1_DIVM2_MASK		GENMASK(21, 16)
+#define RCC_PLL2CFGR1_DIVM2_SHIFT		16
 
-/* Fields of RCC_DDRITFCR register */
-#define RCC_DDRITFCR_DDRC1EN		BIT(0)
-#define RCC_DDRITFCR_DDRC1LPEN		BIT(1)
-#define RCC_DDRITFCR_DDRC2EN		BIT(2)
-#define RCC_DDRITFCR_DDRC2LPEN		BIT(3)
-#define RCC_DDRITFCR_DDRPHYCEN		BIT(4)
-#define RCC_DDRITFCR_DDRPHYCLPEN	BIT(5)
-#define RCC_DDRITFCR_DDRCAPBEN		BIT(6)
-#define RCC_DDRITFCR_DDRCAPBLPEN	BIT(7)
-#define RCC_DDRITFCR_AXIDCGEN		BIT(8)
-#define RCC_DDRITFCR_DDRPHYCAPBEN	BIT(9)
-#define RCC_DDRITFCR_DDRPHYCAPBLPEN	BIT(10)
-#define RCC_DDRITFCR_DDRCAPBRST		BIT(14)
-#define RCC_DDRITFCR_DDRCAXIRST		BIT(15)
-#define RCC_DDRITFCR_DDRCORERST		BIT(16)
-#define RCC_DDRITFCR_DPHYAPBRST		BIT(17)
-#define RCC_DDRITFCR_DPHYRST		BIT(18)
-#define RCC_DDRITFCR_DPHYCTLRST		BIT(19)
-#define RCC_DDRITFCR_DDRCKMOD_MASK	GENMASK(22, 20)
-#define RCC_DDRITFCR_DDRCKMOD_SHIFT	20
-#define RCC_DDRITFCR_DDRCKMOD_SSR	0
-#define RCC_DDRITFCR_DDRCKMOD_ASR1	BIT(20)
-#define RCC_DDRITFCR_DDRCKMOD_HSR1	BIT(21)
-#define RCC_DDRITFCR_GSKPCTRL		BIT(24)
+/* RCC_PLL2CFGR2 register fields */
+#define RCC_PLL2CFGR2_DIVP_MASK			GENMASK(6, 0)
+#define RCC_PLL2CFGR2_DIVP_SHIFT		0
+#define RCC_PLL2CFGR2_DIVQ_MASK			GENMASK(14, 8)
+#define RCC_PLL2CFGR2_DIVQ_SHIFT		8
+#define RCC_PLL2CFGR2_DIVR_MASK			GENMASK(22, 16)
+#define RCC_PLL2CFGR2_DIVR_SHIFT		16
 
-/* Fields of RCC_HSICFGR register */
-#define RCC_HSICFGR_HSIDIV_MASK		GENMASK(1, 0)
-#define RCC_HSICFGR_HSITRIM_SHIFT	8
-#define RCC_HSICFGR_HSITRIM_MASK	GENMASK(14, 8)
-#define RCC_HSICFGR_HSICAL_SHIFT	16
-#define RCC_HSICFGR_HSICAL_MASK		GENMASK(27, 16)
+/* RCC_PLL2FRACR register fields */
+#define RCC_PLL2FRACR_FRACV_MASK		GENMASK(15, 3)
+#define RCC_PLL2FRACR_FRACV_SHIFT		3
+#define RCC_PLL2FRACR_FRACLE			BIT(16)
 
-/* Fields of RCC_CSICFGR register */
-#define RCC_CSICFGR_CSITRIM_SHIFT	8
-#define RCC_CSICFGR_CSITRIM_MASK	GENMASK(12, 8)
-#define RCC_CSICFGR_CSICAL_SHIFT	16
-#define RCC_CSICFGR_CSICAL_MASK		GENMASK(23, 16)
+/* RCC_PLL2CSGR register fields */
+#define RCC_PLL2CSGR_MOD_PER_MASK		GENMASK(12, 0)
+#define RCC_PLL2CSGR_MOD_PER_SHIFT		0
+#define RCC_PLL2CSGR_TPDFN_DIS			BIT(13)
+#define RCC_PLL2CSGR_RPDFN_DIS			BIT(14)
+#define RCC_PLL2CSGR_SSCG_MODE			BIT(15)
+#define RCC_PLL2CSGR_INC_STEP_MASK		GENMASK(30, 16)
+#define RCC_PLL2CSGR_INC_STEP_SHIFT		16
 
-/* Used for RCC_MCO related operations */
-#define RCC_MCOCFG_MCOON		BIT(12)
-#define RCC_MCOCFG_MCODIV_MASK		GENMASK(7, 4)
-#define RCC_MCOCFG_MCODIV_SHIFT		4
-#define RCC_MCOCFG_MCOSRC_MASK		GENMASK(2, 0)
+/* RCC_I2C46CKSELR register fields */
+#define RCC_I2C46CKSELR_I2C46SRC_MASK		GENMASK(2, 0)
+#define RCC_I2C46CKSELR_I2C46SRC_SHIFT		0
 
-/* Fields of RCC_DBGCFGR register */
-#define RCC_DBGCFGR_DBGCKEN		BIT(8)
+/* RCC_SPI6CKSELR register fields */
+#define RCC_SPI6CKSELR_SPI6SRC_MASK		GENMASK(2, 0)
+#define RCC_SPI6CKSELR_SPI6SRC_SHIFT		0
 
-/* RCC register fields for reset reasons */
-#define RCC_MP_RSTSCLRR_PORRSTF		BIT(0)
-#define RCC_MP_RSTSCLRR_BORRSTF		BIT(1)
-#define RCC_MP_RSTSCLRR_PADRSTF		BIT(2)
-#define RCC_MP_RSTSCLRR_HCSSRSTF	BIT(3)
-#define RCC_MP_RSTSCLRR_VCORERSTF	BIT(4)
-#define RCC_MP_RSTSCLRR_MPSYSRSTF	BIT(6)
-#define RCC_MP_RSTSCLRR_MCSYSRSTF	BIT(7)
-#define RCC_MP_RSTSCLRR_IWDG1RSTF	BIT(8)
-#define RCC_MP_RSTSCLRR_IWDG2RSTF	BIT(9)
-#define RCC_MP_RSTSCLRR_STDBYRSTF	BIT(11)
-#define RCC_MP_RSTSCLRR_CSTDBYRSTF	BIT(12)
-#define RCC_MP_RSTSCLRR_MPUP0RSTF	BIT(13)
-#define RCC_MP_RSTSCLRR_MPUP1RSTF	BIT(14)
+/* RCC_UART1CKSELR register fields */
+#define RCC_UART1CKSELR_UART1SRC_MASK		GENMASK(2, 0)
+#define RCC_UART1CKSELR_UART1SRC_SHIFT		0
 
-/* Global Reset Register */
-#define RCC_MP_GRSTCSETR_MPSYSRST	BIT(0)
-#define RCC_MP_GRSTCSETR_MCURST		BIT(1)
-#define RCC_MP_GRSTCSETR_MPUP0RST	BIT(4)
-#define RCC_MP_GRSTCSETR_MPUP1RST	BIT(5)
+/* RCC_RNG1CKSELR register fields */
+#define RCC_RNG1CKSELR_RNG1SRC_MASK		GENMASK(1, 0)
+#define RCC_RNG1CKSELR_RNG1SRC_SHIFT		0
 
-/* Clock Source Interrupt Flag Register */
-#define RCC_MP_CIFR_MASK		U(0x110F1F)
-#define RCC_MP_CIFR_LSIRDYF		BIT(0)
-#define RCC_MP_CIFR_LSERDYF		BIT(1)
-#define RCC_MP_CIFR_HSIRDYF		BIT(2)
-#define RCC_MP_CIFR_HSERDYF		BIT(3)
-#define RCC_MP_CIFR_CSIRDYF		BIT(4)
-#define RCC_MP_CIFR_PLL1DYF		BIT(8)
-#define RCC_MP_CIFR_PLL2DYF		BIT(9)
-#define RCC_MP_CIFR_PLL3DYF		BIT(10)
-#define RCC_MP_CIFR_PLL4DYF		BIT(11)
-#define RCC_MP_CIFR_WKUPF		BIT(20)
+/* RCC_CPERCKSELR register fields */
+#define RCC_CPERCKSELR_HSI			0x00000000
+#define RCC_CPERCKSELR_CSI			0x00000001
+#define RCC_CPERCKSELR_HSE			0x00000002
+#define RCC_CPERCKSELR_CKPERSRC_MASK		GENMASK(1, 0)
+#define RCC_CPERCKSELR_CKPERSRC_SHIFT		0
 
-/* Stop Request Set Register */
-#define RCC_MP_SREQSETR_STPREQ_P0	BIT(0)
-#define RCC_MP_SREQSETR_STPREQ_P1	BIT(1)
+/* RCC_STGENCKSELR register fields */
+#define RCC_STGENCKSELR_STGENSRC_MASK		GENMASK(1, 0)
+#define RCC_STGENCKSELR_STGENSRC_SHIFT		0
 
-/* Stop Request Clear Register */
-#define RCC_MP_SREQCLRR_STPREQ_P0	BIT(0)
-#define RCC_MP_SREQCLRR_STPREQ_P1	BIT(1)
+/* RCC_DDRITFCR register fields */
+#define RCC_DDRITFCR_DDRC1EN			BIT(0)
+#define RCC_DDRITFCR_DDRC1LPEN			BIT(1)
+#define RCC_DDRITFCR_DDRC2EN			BIT(2)
+#define RCC_DDRITFCR_DDRC2LPEN			BIT(3)
+#define RCC_DDRITFCR_DDRPHYCEN			BIT(4)
+#define RCC_DDRITFCR_DDRPHYCLPEN		BIT(5)
+#define RCC_DDRITFCR_DDRCAPBEN			BIT(6)
+#define RCC_DDRITFCR_DDRCAPBLPEN		BIT(7)
+#define RCC_DDRITFCR_AXIDCGEN			BIT(8)
+#define RCC_DDRITFCR_DDRPHYCAPBEN		BIT(9)
+#define RCC_DDRITFCR_DDRPHYCAPBLPEN		BIT(10)
+#define RCC_DDRITFCR_KERDCG_DLY_MASK		GENMASK(13, 11)
+#define RCC_DDRITFCR_KERDCG_DLY_SHIFT		11
+#define RCC_DDRITFCR_DDRCAPBRST			BIT(14)
+#define RCC_DDRITFCR_DDRCAXIRST			BIT(15)
+#define RCC_DDRITFCR_DDRCORERST			BIT(16)
+#define RCC_DDRITFCR_DPHYAPBRST			BIT(17)
+#define RCC_DDRITFCR_DPHYRST			BIT(18)
+#define RCC_DDRITFCR_DPHYCTLRST			BIT(19)
+#define RCC_DDRITFCR_DDRCKMOD_MASK		GENMASK(22, 20)
+#define RCC_DDRITFCR_DDRCKMOD_SHIFT		20
+#define RCC_DDRITFCR_DDRCKMOD_SSR		0
+#define RCC_DDRITFCR_DDRCKMOD_ASR1		BIT(20)
+#define RCC_DDRITFCR_DDRCKMOD_HSR1		BIT(21)
+#define RCC_DDRITFCR_GSKPMOD			BIT(23)
+#define RCC_DDRITFCR_GSKPCTRL			BIT(24)
+#define RCC_DDRITFCR_DFILP_WIDTH_MASK		GENMASK(27, 25)
+#define RCC_DDRITFCR_DFILP_WIDTH_SHIFT		25
+#define RCC_DDRITFCR_GSKP_DUR_MASK		GENMASK(31, 28)
+#define RCC_DDRITFCR_GSKP_DUR_SHIFT		28
 
-/* Values of RCC_UART24CKSELR register */
-#define RCC_UART24CKSELR_HSI		0x00000002
+/* RCC_MP_BOOTCR register fields */
+#define RCC_MP_BOOTCR_MCU_BEN			BIT(0)
+#define RCC_MP_BOOTCR_MPU_BEN			BIT(1)
 
-/* Values of RCC_MP_APB1ENSETR register */
-#define RCC_MP_APB1ENSETR_UART4EN	BIT(16)
+/* RCC_MP_SREQSETR register fields */
+#define RCC_MP_SREQSETR_STPREQ_P0		BIT(0)
+#define RCC_MP_SREQSETR_STPREQ_P1		BIT(1)
 
-/* Values of RCC_MP_APB5ENSETR register */
-#define RCC_MP_APB5ENSETR_SPI6EN	BIT(0)
-#define RCC_MP_APB5ENSETR_I2C4EN	BIT(2)
-#define RCC_MP_APB5ENSETR_I2C6EN	BIT(3)
-#define RCC_MP_APB5ENSETR_USART1EN	BIT(4)
-#define RCC_MP_APB5ENSETR_RTCAPBEN	BIT(8)
-#define RCC_MP_APB5ENSETR_IWDG1APBEN	BIT(15)
+/* RCC_MP_SREQCLRR register fields */
+#define RCC_MP_SREQCLRR_STPREQ_P0		BIT(0)
+#define RCC_MP_SREQCLRR_STPREQ_P1		BIT(1)
 
-/* Values of RCC_MP_AHB4ENSETR register */
-#define RCC_MP_AHB4ENSETR_GPIOGEN	BIT(6)
-#define RCC_MP_AHB4ENSETR_GPIOHEN	BIT(7)
+/* RCC_MP_GCR register fields */
+#define RCC_MP_GCR_BOOT_MCU			BIT(0)
 
-/* Values of RCC_MP_AHB5ENSETR register */
-#define RCC_MP_AHB5ENSETR_GPIOZEN	BIT(0)
-#define RCC_MP_AHB5ENSETR_CRYP1EN	BIT(4)
-#define RCC_MP_AHB5ENSETR_HASH1EN	BIT(5)
-#define RCC_MP_AHB5ENSETR_RNG1EN	BIT(6)
+/* RCC_MP_APRSTCR register fields */
+#define RCC_MP_APRSTCR_RDCTLEN			BIT(0)
+#define RCC_MP_APRSTCR_RSTTO_MASK		GENMASK(14, 8)
+#define RCC_MP_APRSTCR_RSTTO_SHIFT		8
 
-/* Values of RCC_MP_IWDGFZSETR register */
-#define RCC_MP_IWDGFZSETR_IWDG1		BIT(0)
-#define RCC_MP_IWDGFZSETR_IWDG2		BIT(1)
+/* RCC_MP_APRSTSR register fields */
+#define RCC_MP_APRSTSR_RSTTOV_MASK		GENMASK(14, 8)
+#define RCC_MP_APRSTSR_RSTTOV_SHIFT		8
 
-/* Values of RCC_PWRLPDLYCR register */
-#define RCC_PWRLPDLYCR_PWRLP_DLY_MASK	GENMASK(21, 0)
+/* RCC_BDCR register fields */
+#define RCC_BDCR_LSEON				BIT(0)
+#define RCC_BDCR_LSEBYP				BIT(1)
+#define RCC_BDCR_LSERDY				BIT(2)
+#define RCC_BDCR_DIGBYP				BIT(3)
+#define RCC_BDCR_LSEDRV_MASK			GENMASK(5, 4)
+#define RCC_BDCR_LSEDRV_SHIFT			4
+#define RCC_BDCR_LSECSSON			BIT(8)
+#define RCC_BDCR_LSECSSD			BIT(9)
+#define RCC_BDCR_RTCSRC_MASK			GENMASK(17, 16)
+#define RCC_BDCR_RTCSRC_SHIFT			16
+#define RCC_BDCR_RTCCKEN			BIT(20)
+#define RCC_BDCR_VSWRST				BIT(31)
 
-/* RCC_ASSCKSELR register fields */
-#define RCC_ASSCKSELR_AXISSRC_MASK		GENMASK(2, 0)
-#define RCC_ASSCKSELR_AXISSRC_SHIFT		0
+/* RCC_RDLSICR register fields */
+#define RCC_RDLSICR_LSION			BIT(0)
+#define RCC_RDLSICR_LSIRDY			BIT(1)
+#define RCC_RDLSICR_MRD_MASK			GENMASK(20, 16)
+#define RCC_RDLSICR_MRD_SHIFT			16
+#define RCC_RDLSICR_EADLY_MASK			GENMASK(26, 24)
+#define RCC_RDLSICR_EADLY_SHIFT			24
+#define RCC_RDLSICR_SPARE_MASK			GENMASK(31, 27)
+#define RCC_RDLSICR_SPARE_SHIFT			27
 
-/* RCC_MSSCKSELR register fields */
-#define RCC_MSSCKSELR_MCUSSRC_MASK		GENMASK(1, 0)
-#define RCC_MSSCKSELR_MCUSSRC_SHIFT		0
+/* RCC_APB4RSTSETR register fields */
+#define RCC_APB4RSTSETR_LTDCRST			BIT(0)
+#define RCC_APB4RSTSETR_DSIRST			BIT(4)
+#define RCC_APB4RSTSETR_DDRPERFMRST		BIT(8)
+#define RCC_APB4RSTSETR_USBPHYRST		BIT(16)
 
-/* RCC_I2C46CKSELR register fields */
-#define RCC_I2C46CKSELR_I2C46SRC_MASK		GENMASK(2, 0)
-#define RCC_I2C46CKSELR_I2C46SRC_SHIFT		0
+/* RCC_APB4RSTCLRR register fields */
+#define RCC_APB4RSTCLRR_LTDCRST			BIT(0)
+#define RCC_APB4RSTCLRR_DSIRST			BIT(4)
+#define RCC_APB4RSTCLRR_DDRPERFMRST		BIT(8)
+#define RCC_APB4RSTCLRR_USBPHYRST		BIT(16)
 
-/* RCC_SPI6CKSELR register fields */
-#define RCC_SPI6CKSELR_SPI6SRC_MASK		GENMASK(2, 0)
-#define RCC_SPI6CKSELR_SPI6SRC_SHIFT		0
+/* RCC_APB5RSTSETR register fields */
+#define RCC_APB5RSTSETR_SPI6RST			BIT(0)
+#define RCC_APB5RSTSETR_I2C4RST			BIT(2)
+#define RCC_APB5RSTSETR_I2C6RST			BIT(3)
+#define RCC_APB5RSTSETR_USART1RST		BIT(4)
+#define RCC_APB5RSTSETR_STGENRST		BIT(20)
 
-/* RCC_UART1CKSELR register fields */
-#define RCC_UART1CKSELR_UART1SRC_MASK		GENMASK(2, 0)
-#define RCC_UART1CKSELR_UART1SRC_SHIFT		0
+/* RCC_APB5RSTCLRR register fields */
+#define RCC_APB5RSTCLRR_SPI6RST			BIT(0)
+#define RCC_APB5RSTCLRR_I2C4RST			BIT(2)
+#define RCC_APB5RSTCLRR_I2C6RST			BIT(3)
+#define RCC_APB5RSTCLRR_USART1RST		BIT(4)
+#define RCC_APB5RSTCLRR_STGENRST		BIT(20)
 
-/* RCC_RNG1CKSELR register fields */
-#define RCC_RNG1CKSELR_RNG1SRC_MASK		GENMASK(1, 0)
-#define RCC_RNG1CKSELR_RNG1SRC_SHIFT		0
+/* RCC_AHB5RSTSETR register fields */
+#define RCC_AHB5RSTSETR_GPIOZRST		BIT(0)
+#define RCC_AHB5RSTSETR_CRYP1RST		BIT(4)
+#define RCC_AHB5RSTSETR_HASH1RST		BIT(5)
+#define RCC_AHB5RSTSETR_RNG1RST			BIT(6)
+#define RCC_AHB5RSTSETR_AXIMCRST		BIT(16)
 
-/* RCC_STGENCKSELR register fields */
-#define RCC_STGENCKSELR_STGENSRC_MASK		GENMASK(1, 0)
-#define RCC_STGENCKSELR_STGENSRC_SHIFT		0
+/* RCC_AHB5RSTCLRR register fields */
+#define RCC_AHB5RSTCLRR_GPIOZRST		BIT(0)
+#define RCC_AHB5RSTCLRR_CRYP1RST		BIT(4)
+#define RCC_AHB5RSTCLRR_HASH1RST		BIT(5)
+#define RCC_AHB5RSTCLRR_RNG1RST			BIT(6)
+#define RCC_AHB5RSTCLRR_AXIMCRST		BIT(16)
+
+/* RCC_AHB6RSTSETR register fields */
+#define RCC_AHB6RSTSETR_GPURST			BIT(5)
+#define RCC_AHB6RSTSETR_ETHMACRST		BIT(10)
+#define RCC_AHB6RSTSETR_FMCRST			BIT(12)
+#define RCC_AHB6RSTSETR_QSPIRST			BIT(14)
+#define RCC_AHB6RSTSETR_SDMMC1RST		BIT(16)
+#define RCC_AHB6RSTSETR_SDMMC2RST		BIT(17)
+#define RCC_AHB6RSTSETR_CRC1RST			BIT(20)
+#define RCC_AHB6RSTSETR_USBHRST			BIT(24)
+
+/* RCC_AHB6RSTCLRR register fields */
+#define RCC_AHB6RSTCLRR_ETHMACRST		BIT(10)
+#define RCC_AHB6RSTCLRR_FMCRST			BIT(12)
+#define RCC_AHB6RSTCLRR_QSPIRST			BIT(14)
+#define RCC_AHB6RSTCLRR_SDMMC1RST		BIT(16)
+#define RCC_AHB6RSTCLRR_SDMMC2RST		BIT(17)
+#define RCC_AHB6RSTCLRR_CRC1RST			BIT(20)
+#define RCC_AHB6RSTCLRR_USBHRST			BIT(24)
+
+/* RCC_TZAHB6RSTSETR register fields */
+#define RCC_TZAHB6RSTSETR_MDMARST		BIT(0)
+
+/* RCC_TZAHB6RSTCLRR register fields */
+#define RCC_TZAHB6RSTCLRR_MDMARST		BIT(0)
+
+/* RCC_MP_APB4ENSETR register fields */
+#define RCC_MP_APB4ENSETR_LTDCEN		BIT(0)
+#define RCC_MP_APB4ENSETR_DSIEN			BIT(4)
+#define RCC_MP_APB4ENSETR_DDRPERFMEN		BIT(8)
+#define RCC_MP_APB4ENSETR_IWDG2APBEN		BIT(15)
+#define RCC_MP_APB4ENSETR_USBPHYEN		BIT(16)
+#define RCC_MP_APB4ENSETR_STGENROEN		BIT(20)
+
+/* RCC_MP_APB4ENCLRR register fields */
+#define RCC_MP_APB4ENCLRR_LTDCEN		BIT(0)
+#define RCC_MP_APB4ENCLRR_DSIEN			BIT(4)
+#define RCC_MP_APB4ENCLRR_DDRPERFMEN		BIT(8)
+#define RCC_MP_APB4ENCLRR_IWDG2APBEN		BIT(15)
+#define RCC_MP_APB4ENCLRR_USBPHYEN		BIT(16)
+#define RCC_MP_APB4ENCLRR_STGENROEN		BIT(20)
+
+/* RCC_MP_APB5ENSETR register fields */
+#define RCC_MP_APB5ENSETR_SPI6EN		BIT(0)
+#define RCC_MP_APB5ENSETR_I2C4EN		BIT(2)
+#define RCC_MP_APB5ENSETR_I2C6EN		BIT(3)
+#define RCC_MP_APB5ENSETR_USART1EN		BIT(4)
+#define RCC_MP_APB5ENSETR_RTCAPBEN		BIT(8)
+#define RCC_MP_APB5ENSETR_TZC1EN		BIT(11)
+#define RCC_MP_APB5ENSETR_TZC2EN		BIT(12)
+#define RCC_MP_APB5ENSETR_TZPCEN		BIT(13)
+#define RCC_MP_APB5ENSETR_IWDG1APBEN		BIT(15)
+#define RCC_MP_APB5ENSETR_BSECEN		BIT(16)
+#define RCC_MP_APB5ENSETR_STGENEN		BIT(20)
+
+/* RCC_MP_APB5ENCLRR register fields */
+#define RCC_MP_APB5ENCLRR_SPI6EN		BIT(0)
+#define RCC_MP_APB5ENCLRR_I2C4EN		BIT(2)
+#define RCC_MP_APB5ENCLRR_I2C6EN		BIT(3)
+#define RCC_MP_APB5ENCLRR_USART1EN		BIT(4)
+#define RCC_MP_APB5ENCLRR_RTCAPBEN		BIT(8)
+#define RCC_MP_APB5ENCLRR_TZC1EN		BIT(11)
+#define RCC_MP_APB5ENCLRR_TZC2EN		BIT(12)
+#define RCC_MP_APB5ENCLRR_TZPCEN		BIT(13)
+#define RCC_MP_APB5ENCLRR_IWDG1APBEN		BIT(15)
+#define RCC_MP_APB5ENCLRR_BSECEN		BIT(16)
+#define RCC_MP_APB5ENCLRR_STGENEN		BIT(20)
+
+/* RCC_MP_AHB5ENSETR register fields */
+#define RCC_MP_AHB5ENSETR_GPIOZEN		BIT(0)
+#define RCC_MP_AHB5ENSETR_CRYP1EN		BIT(4)
+#define RCC_MP_AHB5ENSETR_HASH1EN		BIT(5)
+#define RCC_MP_AHB5ENSETR_RNG1EN		BIT(6)
+#define RCC_MP_AHB5ENSETR_BKPSRAMEN		BIT(8)
+#define RCC_MP_AHB5ENSETR_AXIMCEN		BIT(16)
+
+/* RCC_MP_AHB5ENCLRR register fields */
+#define RCC_MP_AHB5ENCLRR_GPIOZEN		BIT(0)
+#define RCC_MP_AHB5ENCLRR_CRYP1EN		BIT(4)
+#define RCC_MP_AHB5ENCLRR_HASH1EN		BIT(5)
+#define RCC_MP_AHB5ENCLRR_RNG1EN		BIT(6)
+#define RCC_MP_AHB5ENCLRR_BKPSRAMEN		BIT(8)
+#define RCC_MP_AHB5ENCLRR_AXIMCEN		BIT(16)
+
+/* RCC_MP_AHB6ENSETR register fields */
+#define RCC_MP_AHB6ENSETR_MDMAEN		BIT(0)
+#define RCC_MP_AHB6ENSETR_GPUEN			BIT(5)
+#define RCC_MP_AHB6ENSETR_ETHCKEN		BIT(7)
+#define RCC_MP_AHB6ENSETR_ETHTXEN		BIT(8)
+#define RCC_MP_AHB6ENSETR_ETHRXEN		BIT(9)
+#define RCC_MP_AHB6ENSETR_ETHMACEN		BIT(10)
+#define RCC_MP_AHB6ENSETR_FMCEN			BIT(12)
+#define RCC_MP_AHB6ENSETR_QSPIEN		BIT(14)
+#define RCC_MP_AHB6ENSETR_SDMMC1EN		BIT(16)
+#define RCC_MP_AHB6ENSETR_SDMMC2EN		BIT(17)
+#define RCC_MP_AHB6ENSETR_CRC1EN		BIT(20)
+#define RCC_MP_AHB6ENSETR_USBHEN		BIT(24)
+
+/* RCC_MP_AHB6ENCLRR register fields */
+#define RCC_MP_AHB6ENCLRR_MDMAEN		BIT(0)
+#define RCC_MP_AHB6ENCLRR_GPUEN			BIT(5)
+#define RCC_MP_AHB6ENCLRR_ETHCKEN		BIT(7)
+#define RCC_MP_AHB6ENCLRR_ETHTXEN		BIT(8)
+#define RCC_MP_AHB6ENCLRR_ETHRXEN		BIT(9)
+#define RCC_MP_AHB6ENCLRR_ETHMACEN		BIT(10)
+#define RCC_MP_AHB6ENCLRR_FMCEN			BIT(12)
+#define RCC_MP_AHB6ENCLRR_QSPIEN		BIT(14)
+#define RCC_MP_AHB6ENCLRR_SDMMC1EN		BIT(16)
+#define RCC_MP_AHB6ENCLRR_SDMMC2EN		BIT(17)
+#define RCC_MP_AHB6ENCLRR_CRC1EN		BIT(20)
+#define RCC_MP_AHB6ENCLRR_USBHEN		BIT(24)
+
+/* RCC_MP_TZAHB6ENSETR register fields */
+#define RCC_MP_TZAHB6ENSETR_MDMAEN		BIT(0)
+
+/* RCC_MP_TZAHB6ENCLRR register fields */
+#define RCC_MP_TZAHB6ENCLRR_MDMAEN		BIT(0)
+
+/* RCC_MC_APB4ENSETR register fields */
+#define RCC_MC_APB4ENSETR_LTDCEN		BIT(0)
+#define RCC_MC_APB4ENSETR_DSIEN			BIT(4)
+#define RCC_MC_APB4ENSETR_DDRPERFMEN		BIT(8)
+#define RCC_MC_APB4ENSETR_USBPHYEN		BIT(16)
+#define RCC_MC_APB4ENSETR_STGENROEN		BIT(20)
+
+/* RCC_MC_APB4ENCLRR register fields */
+#define RCC_MC_APB4ENCLRR_LTDCEN		BIT(0)
+#define RCC_MC_APB4ENCLRR_DSIEN			BIT(4)
+#define RCC_MC_APB4ENCLRR_DDRPERFMEN		BIT(8)
+#define RCC_MC_APB4ENCLRR_USBPHYEN		BIT(16)
+#define RCC_MC_APB4ENCLRR_STGENROEN		BIT(20)
+
+/* RCC_MC_APB5ENSETR register fields */
+#define RCC_MC_APB5ENSETR_SPI6EN		BIT(0)
+#define RCC_MC_APB5ENSETR_I2C4EN		BIT(2)
+#define RCC_MC_APB5ENSETR_I2C6EN		BIT(3)
+#define RCC_MC_APB5ENSETR_USART1EN		BIT(4)
+#define RCC_MC_APB5ENSETR_RTCAPBEN		BIT(8)
+#define RCC_MC_APB5ENSETR_TZC1EN		BIT(11)
+#define RCC_MC_APB5ENSETR_TZC2EN		BIT(12)
+#define RCC_MC_APB5ENSETR_TZPCEN		BIT(13)
+#define RCC_MC_APB5ENSETR_BSECEN		BIT(16)
+#define RCC_MC_APB5ENSETR_STGENEN		BIT(20)
+
+/* RCC_MC_APB5ENCLRR register fields */
+#define RCC_MC_APB5ENCLRR_SPI6EN		BIT(0)
+#define RCC_MC_APB5ENCLRR_I2C4EN		BIT(2)
+#define RCC_MC_APB5ENCLRR_I2C6EN		BIT(3)
+#define RCC_MC_APB5ENCLRR_USART1EN		BIT(4)
+#define RCC_MC_APB5ENCLRR_RTCAPBEN		BIT(8)
+#define RCC_MC_APB5ENCLRR_TZC1EN		BIT(11)
+#define RCC_MC_APB5ENCLRR_TZC2EN		BIT(12)
+#define RCC_MC_APB5ENCLRR_TZPCEN		BIT(13)
+#define RCC_MC_APB5ENCLRR_BSECEN		BIT(16)
+#define RCC_MC_APB5ENCLRR_STGENEN		BIT(20)
+
+/* RCC_MC_AHB5ENSETR register fields */
+#define RCC_MC_AHB5ENSETR_GPIOZEN		BIT(0)
+#define RCC_MC_AHB5ENSETR_CRYP1EN		BIT(4)
+#define RCC_MC_AHB5ENSETR_HASH1EN		BIT(5)
+#define RCC_MC_AHB5ENSETR_RNG1EN		BIT(6)
+#define RCC_MC_AHB5ENSETR_BKPSRAMEN		BIT(8)
+
+/* RCC_MC_AHB5ENCLRR register fields */
+#define RCC_MC_AHB5ENCLRR_GPIOZEN		BIT(0)
+#define RCC_MC_AHB5ENCLRR_CRYP1EN		BIT(4)
+#define RCC_MC_AHB5ENCLRR_HASH1EN		BIT(5)
+#define RCC_MC_AHB5ENCLRR_RNG1EN		BIT(6)
+#define RCC_MC_AHB5ENCLRR_BKPSRAMEN		BIT(8)
+
+/* RCC_MC_AHB6ENSETR register fields */
+#define RCC_MC_AHB6ENSETR_MDMAEN		BIT(0)
+#define RCC_MC_AHB6ENSETR_GPUEN			BIT(5)
+#define RCC_MC_AHB6ENSETR_ETHCKEN		BIT(7)
+#define RCC_MC_AHB6ENSETR_ETHTXEN		BIT(8)
+#define RCC_MC_AHB6ENSETR_ETHRXEN		BIT(9)
+#define RCC_MC_AHB6ENSETR_ETHMACEN		BIT(10)
+#define RCC_MC_AHB6ENSETR_FMCEN			BIT(12)
+#define RCC_MC_AHB6ENSETR_QSPIEN		BIT(14)
+#define RCC_MC_AHB6ENSETR_SDMMC1EN		BIT(16)
+#define RCC_MC_AHB6ENSETR_SDMMC2EN		BIT(17)
+#define RCC_MC_AHB6ENSETR_CRC1EN		BIT(20)
+#define RCC_MC_AHB6ENSETR_USBHEN		BIT(24)
+
+/* RCC_MC_AHB6ENCLRR register fields */
+#define RCC_MC_AHB6ENCLRR_MDMAEN		BIT(0)
+#define RCC_MC_AHB6ENCLRR_GPUEN			BIT(5)
+#define RCC_MC_AHB6ENCLRR_ETHCKEN		BIT(7)
+#define RCC_MC_AHB6ENCLRR_ETHTXEN		BIT(8)
+#define RCC_MC_AHB6ENCLRR_ETHRXEN		BIT(9)
+#define RCC_MC_AHB6ENCLRR_ETHMACEN		BIT(10)
+#define RCC_MC_AHB6ENCLRR_FMCEN			BIT(12)
+#define RCC_MC_AHB6ENCLRR_QSPIEN		BIT(14)
+#define RCC_MC_AHB6ENCLRR_SDMMC1EN		BIT(16)
+#define RCC_MC_AHB6ENCLRR_SDMMC2EN		BIT(17)
+#define RCC_MC_AHB6ENCLRR_CRC1EN		BIT(20)
+#define RCC_MC_AHB6ENCLRR_USBHEN		BIT(24)
+
+/* RCC_MP_APB4LPENSETR register fields */
+#define RCC_MP_APB4LPENSETR_LTDCLPEN		BIT(0)
+#define RCC_MP_APB4LPENSETR_DSILPEN		BIT(4)
+#define RCC_MP_APB4LPENSETR_DDRPERFMLPEN	BIT(8)
+#define RCC_MP_APB4LPENSETR_IWDG2APBLPEN	BIT(15)
+#define RCC_MP_APB4LPENSETR_USBPHYLPEN		BIT(16)
+#define RCC_MP_APB4LPENSETR_STGENROLPEN		BIT(20)
+#define RCC_MP_APB4LPENSETR_STGENROSTPEN	BIT(21)
+
+/* RCC_MP_APB4LPENCLRR register fields */
+#define RCC_MP_APB4LPENCLRR_LTDCLPEN		BIT(0)
+#define RCC_MP_APB4LPENCLRR_DSILPEN		BIT(4)
+#define RCC_MP_APB4LPENCLRR_DDRPERFMLPEN	BIT(8)
+#define RCC_MP_APB4LPENCLRR_IWDG2APBLPEN	BIT(15)
+#define RCC_MP_APB4LPENCLRR_USBPHYLPEN		BIT(16)
+#define RCC_MP_APB4LPENCLRR_STGENROLPEN		BIT(20)
+#define RCC_MP_APB4LPENCLRR_STGENROSTPEN	BIT(21)
+
+/* RCC_MP_APB5LPENSETR register fields */
+#define RCC_MP_APB5LPENSETR_SPI6LPEN		BIT(0)
+#define RCC_MP_APB5LPENSETR_I2C4LPEN		BIT(2)
+#define RCC_MP_APB5LPENSETR_I2C6LPEN		BIT(3)
+#define RCC_MP_APB5LPENSETR_USART1LPEN		BIT(4)
+#define RCC_MP_APB5LPENSETR_RTCAPBLPEN		BIT(8)
+#define RCC_MP_APB5LPENSETR_TZC1LPEN		BIT(11)
+#define RCC_MP_APB5LPENSETR_TZC2LPEN		BIT(12)
+#define RCC_MP_APB5LPENSETR_TZPCLPEN		BIT(13)
+#define RCC_MP_APB5LPENSETR_IWDG1APBLPEN	BIT(15)
+#define RCC_MP_APB5LPENSETR_BSECLPEN		BIT(16)
+#define RCC_MP_APB5LPENSETR_STGENLPEN		BIT(20)
+#define RCC_MP_APB5LPENSETR_STGENSTPEN		BIT(21)
+
+/* RCC_MP_APB5LPENCLRR register fields */
+#define RCC_MP_APB5LPENCLRR_SPI6LPEN		BIT(0)
+#define RCC_MP_APB5LPENCLRR_I2C4LPEN		BIT(2)
+#define RCC_MP_APB5LPENCLRR_I2C6LPEN		BIT(3)
+#define RCC_MP_APB5LPENCLRR_USART1LPEN		BIT(4)
+#define RCC_MP_APB5LPENCLRR_RTCAPBLPEN		BIT(8)
+#define RCC_MP_APB5LPENCLRR_TZC1LPEN		BIT(11)
+#define RCC_MP_APB5LPENCLRR_TZC2LPEN		BIT(12)
+#define RCC_MP_APB5LPENCLRR_TZPCLPEN		BIT(13)
+#define RCC_MP_APB5LPENCLRR_IWDG1APBLPEN	BIT(15)
+#define RCC_MP_APB5LPENCLRR_BSECLPEN		BIT(16)
+#define RCC_MP_APB5LPENCLRR_STGENLPEN		BIT(20)
+#define RCC_MP_APB5LPENCLRR_STGENSTPEN		BIT(21)
+
+/* RCC_MP_AHB5LPENSETR register fields */
+#define RCC_MP_AHB5LPENSETR_GPIOZLPEN		BIT(0)
+#define RCC_MP_AHB5LPENSETR_CRYP1LPEN		BIT(4)
+#define RCC_MP_AHB5LPENSETR_HASH1LPEN		BIT(5)
+#define RCC_MP_AHB5LPENSETR_RNG1LPEN		BIT(6)
+#define RCC_MP_AHB5LPENSETR_BKPSRAMLPEN		BIT(8)
+
+/* RCC_MP_AHB5LPENCLRR register fields */
+#define RCC_MP_AHB5LPENCLRR_GPIOZLPEN		BIT(0)
+#define RCC_MP_AHB5LPENCLRR_CRYP1LPEN		BIT(4)
+#define RCC_MP_AHB5LPENCLRR_HASH1LPEN		BIT(5)
+#define RCC_MP_AHB5LPENCLRR_RNG1LPEN		BIT(6)
+#define RCC_MP_AHB5LPENCLRR_BKPSRAMLPEN		BIT(8)
+
+/* RCC_MP_AHB6LPENSETR register fields */
+#define RCC_MP_AHB6LPENSETR_MDMALPEN		BIT(0)
+#define RCC_MP_AHB6LPENSETR_GPULPEN		BIT(5)
+#define RCC_MP_AHB6LPENSETR_ETHCKLPEN		BIT(7)
+#define RCC_MP_AHB6LPENSETR_ETHTXLPEN		BIT(8)
+#define RCC_MP_AHB6LPENSETR_ETHRXLPEN		BIT(9)
+#define RCC_MP_AHB6LPENSETR_ETHMACLPEN		BIT(10)
+#define RCC_MP_AHB6LPENSETR_ETHSTPEN		BIT(11)
+#define RCC_MP_AHB6LPENSETR_FMCLPEN		BIT(12)
+#define RCC_MP_AHB6LPENSETR_QSPILPEN		BIT(14)
+#define RCC_MP_AHB6LPENSETR_SDMMC1LPEN		BIT(16)
+#define RCC_MP_AHB6LPENSETR_SDMMC2LPEN		BIT(17)
+#define RCC_MP_AHB6LPENSETR_CRC1LPEN		BIT(20)
+#define RCC_MP_AHB6LPENSETR_USBHLPEN		BIT(24)
+
+/* RCC_MP_AHB6LPENCLRR register fields */
+#define RCC_MP_AHB6LPENCLRR_MDMALPEN		BIT(0)
+#define RCC_MP_AHB6LPENCLRR_GPULPEN		BIT(5)
+#define RCC_MP_AHB6LPENCLRR_ETHCKLPEN		BIT(7)
+#define RCC_MP_AHB6LPENCLRR_ETHTXLPEN		BIT(8)
+#define RCC_MP_AHB6LPENCLRR_ETHRXLPEN		BIT(9)
+#define RCC_MP_AHB6LPENCLRR_ETHMACLPEN		BIT(10)
+#define RCC_MP_AHB6LPENCLRR_ETHSTPEN		BIT(11)
+#define RCC_MP_AHB6LPENCLRR_FMCLPEN		BIT(12)
+#define RCC_MP_AHB6LPENCLRR_QSPILPEN		BIT(14)
+#define RCC_MP_AHB6LPENCLRR_SDMMC1LPEN		BIT(16)
+#define RCC_MP_AHB6LPENCLRR_SDMMC2LPEN		BIT(17)
+#define RCC_MP_AHB6LPENCLRR_CRC1LPEN		BIT(20)
+#define RCC_MP_AHB6LPENCLRR_USBHLPEN		BIT(24)
+
+/* RCC_MP_TZAHB6LPENSETR register fields */
+#define RCC_MP_TZAHB6LPENSETR_MDMALPEN		BIT(0)
+
+/* RCC_MP_TZAHB6LPENCLRR register fields */
+#define RCC_MP_TZAHB6LPENCLRR_MDMALPEN		BIT(0)
+
+/* RCC_MC_APB4LPENSETR register fields */
+#define RCC_MC_APB4LPENSETR_LTDCLPEN		BIT(0)
+#define RCC_MC_APB4LPENSETR_DSILPEN		BIT(4)
+#define RCC_MC_APB4LPENSETR_DDRPERFMLPEN	BIT(8)
+#define RCC_MC_APB4LPENSETR_USBPHYLPEN		BIT(16)
+#define RCC_MC_APB4LPENSETR_STGENROLPEN		BIT(20)
+#define RCC_MC_APB4LPENSETR_STGENROSTPEN	BIT(21)
+
+/* RCC_MC_APB4LPENCLRR register fields */
+#define RCC_MC_APB4LPENCLRR_LTDCLPEN		BIT(0)
+#define RCC_MC_APB4LPENCLRR_DSILPEN		BIT(4)
+#define RCC_MC_APB4LPENCLRR_DDRPERFMLPEN	BIT(8)
+#define RCC_MC_APB4LPENCLRR_USBPHYLPEN		BIT(16)
+#define RCC_MC_APB4LPENCLRR_STGENROLPEN		BIT(20)
+#define RCC_MC_APB4LPENCLRR_STGENROSTPEN	BIT(21)
+
+/* RCC_MC_APB5LPENSETR register fields */
+#define RCC_MC_APB5LPENSETR_SPI6LPEN		BIT(0)
+#define RCC_MC_APB5LPENSETR_I2C4LPEN		BIT(2)
+#define RCC_MC_APB5LPENSETR_I2C6LPEN		BIT(3)
+#define RCC_MC_APB5LPENSETR_USART1LPEN		BIT(4)
+#define RCC_MC_APB5LPENSETR_RTCAPBLPEN		BIT(8)
+#define RCC_MC_APB5LPENSETR_TZC1LPEN		BIT(11)
+#define RCC_MC_APB5LPENSETR_TZC2LPEN		BIT(12)
+#define RCC_MC_APB5LPENSETR_TZPCLPEN		BIT(13)
+#define RCC_MC_APB5LPENSETR_BSECLPEN		BIT(16)
+#define RCC_MC_APB5LPENSETR_STGENLPEN		BIT(20)
+#define RCC_MC_APB5LPENSETR_STGENSTPEN		BIT(21)
+
+/* RCC_MC_APB5LPENCLRR register fields */
+#define RCC_MC_APB5LPENCLRR_SPI6LPEN		BIT(0)
+#define RCC_MC_APB5LPENCLRR_I2C4LPEN		BIT(2)
+#define RCC_MC_APB5LPENCLRR_I2C6LPEN		BIT(3)
+#define RCC_MC_APB5LPENCLRR_USART1LPEN		BIT(4)
+#define RCC_MC_APB5LPENCLRR_RTCAPBLPEN		BIT(8)
+#define RCC_MC_APB5LPENCLRR_TZC1LPEN		BIT(11)
+#define RCC_MC_APB5LPENCLRR_TZC2LPEN		BIT(12)
+#define RCC_MC_APB5LPENCLRR_TZPCLPEN		BIT(13)
+#define RCC_MC_APB5LPENCLRR_BSECLPEN		BIT(16)
+#define RCC_MC_APB5LPENCLRR_STGENLPEN		BIT(20)
+#define RCC_MC_APB5LPENCLRR_STGENSTPEN		BIT(21)
+
+/* RCC_MC_AHB5LPENSETR register fields */
+#define RCC_MC_AHB5LPENSETR_GPIOZLPEN		BIT(0)
+#define RCC_MC_AHB5LPENSETR_CRYP1LPEN		BIT(4)
+#define RCC_MC_AHB5LPENSETR_HASH1LPEN		BIT(5)
+#define RCC_MC_AHB5LPENSETR_RNG1LPEN		BIT(6)
+#define RCC_MC_AHB5LPENSETR_BKPSRAMLPEN		BIT(8)
+
+/* RCC_MC_AHB5LPENCLRR register fields */
+#define RCC_MC_AHB5LPENCLRR_GPIOZLPEN		BIT(0)
+#define RCC_MC_AHB5LPENCLRR_CRYP1LPEN		BIT(4)
+#define RCC_MC_AHB5LPENCLRR_HASH1LPEN		BIT(5)
+#define RCC_MC_AHB5LPENCLRR_RNG1LPEN		BIT(6)
+#define RCC_MC_AHB5LPENCLRR_BKPSRAMLPEN		BIT(8)
+
+/* RCC_MC_AHB6LPENSETR register fields */
+#define RCC_MC_AHB6LPENSETR_MDMALPEN		BIT(0)
+#define RCC_MC_AHB6LPENSETR_GPULPEN		BIT(5)
+#define RCC_MC_AHB6LPENSETR_ETHCKLPEN		BIT(7)
+#define RCC_MC_AHB6LPENSETR_ETHTXLPEN		BIT(8)
+#define RCC_MC_AHB6LPENSETR_ETHRXLPEN		BIT(9)
+#define RCC_MC_AHB6LPENSETR_ETHMACLPEN		BIT(10)
+#define RCC_MC_AHB6LPENSETR_ETHSTPEN		BIT(11)
+#define RCC_MC_AHB6LPENSETR_FMCLPEN		BIT(12)
+#define RCC_MC_AHB6LPENSETR_QSPILPEN		BIT(14)
+#define RCC_MC_AHB6LPENSETR_SDMMC1LPEN		BIT(16)
+#define RCC_MC_AHB6LPENSETR_SDMMC2LPEN		BIT(17)
+#define RCC_MC_AHB6LPENSETR_CRC1LPEN		BIT(20)
+#define RCC_MC_AHB6LPENSETR_USBHLPEN		BIT(24)
+
+/* RCC_MC_AHB6LPENCLRR register fields */
+#define RCC_MC_AHB6LPENCLRR_MDMALPEN		BIT(0)
+#define RCC_MC_AHB6LPENCLRR_GPULPEN		BIT(5)
+#define RCC_MC_AHB6LPENCLRR_ETHCKLPEN		BIT(7)
+#define RCC_MC_AHB6LPENCLRR_ETHTXLPEN		BIT(8)
+#define RCC_MC_AHB6LPENCLRR_ETHRXLPEN		BIT(9)
+#define RCC_MC_AHB6LPENCLRR_ETHMACLPEN		BIT(10)
+#define RCC_MC_AHB6LPENCLRR_ETHSTPEN		BIT(11)
+#define RCC_MC_AHB6LPENCLRR_FMCLPEN		BIT(12)
+#define RCC_MC_AHB6LPENCLRR_QSPILPEN		BIT(14)
+#define RCC_MC_AHB6LPENCLRR_SDMMC1LPEN		BIT(16)
+#define RCC_MC_AHB6LPENCLRR_SDMMC2LPEN		BIT(17)
+#define RCC_MC_AHB6LPENCLRR_CRC1LPEN		BIT(20)
+#define RCC_MC_AHB6LPENCLRR_USBHLPEN		BIT(24)
+
+/* RCC_BR_RSTSCLRR register fields */
+#define RCC_BR_RSTSCLRR_PORRSTF			BIT(0)
+#define RCC_BR_RSTSCLRR_BORRSTF			BIT(1)
+#define RCC_BR_RSTSCLRR_PADRSTF			BIT(2)
+#define RCC_BR_RSTSCLRR_HCSSRSTF		BIT(3)
+#define RCC_BR_RSTSCLRR_VCORERSTF		BIT(4)
+#define RCC_BR_RSTSCLRR_MPSYSRSTF		BIT(6)
+#define RCC_BR_RSTSCLRR_MCSYSRSTF		BIT(7)
+#define RCC_BR_RSTSCLRR_IWDG1RSTF		BIT(8)
+#define RCC_BR_RSTSCLRR_IWDG2RSTF		BIT(9)
+#define RCC_BR_RSTSCLRR_MPUP0RSTF		BIT(13)
+#define RCC_BR_RSTSCLRR_MPUP1RSTF		BIT(14)
+
+/* RCC_MP_GRSTCSETR register fields */
+#define RCC_MP_GRSTCSETR_MPSYSRST		BIT(0)
+#define RCC_MP_GRSTCSETR_MCURST			BIT(1)
+#define RCC_MP_GRSTCSETR_MPUP0RST		BIT(4)
+#define RCC_MP_GRSTCSETR_MPUP1RST		BIT(5)
+
+/* RCC_MP_RSTSCLRR register fields */
+#define RCC_MP_RSTSCLRR_PORRSTF			BIT(0)
+#define RCC_MP_RSTSCLRR_BORRSTF			BIT(1)
+#define RCC_MP_RSTSCLRR_PADRSTF			BIT(2)
+#define RCC_MP_RSTSCLRR_HCSSRSTF		BIT(3)
+#define RCC_MP_RSTSCLRR_VCORERSTF		BIT(4)
+#define RCC_MP_RSTSCLRR_MPSYSRSTF		BIT(6)
+#define RCC_MP_RSTSCLRR_MCSYSRSTF		BIT(7)
+#define RCC_MP_RSTSCLRR_IWDG1RSTF		BIT(8)
+#define RCC_MP_RSTSCLRR_IWDG2RSTF		BIT(9)
+#define RCC_MP_RSTSCLRR_STDBYRSTF		BIT(11)
+#define RCC_MP_RSTSCLRR_CSTDBYRSTF		BIT(12)
+#define RCC_MP_RSTSCLRR_MPUP0RSTF		BIT(13)
+#define RCC_MP_RSTSCLRR_MPUP1RSTF		BIT(14)
+#define RCC_MP_RSTSCLRR_SPARE			BIT(15)
+
+/* RCC_MP_IWDGFZSETR register fields */
+#define RCC_MP_IWDGFZSETR_FZ_IWDG1		BIT(0)
+#define RCC_MP_IWDGFZSETR_FZ_IWDG2		BIT(1)
+
+/* RCC_MP_IWDGFZCLRR register fields */
+#define RCC_MP_IWDGFZCLRR_FZ_IWDG1		BIT(0)
+#define RCC_MP_IWDGFZCLRR_FZ_IWDG2		BIT(1)
+
+/* RCC_MP_CIER register fields */
+#define RCC_MP_CIER_LSIRDYIE			BIT(0)
+#define RCC_MP_CIER_LSERDYIE			BIT(1)
+#define RCC_MP_CIER_HSIRDYIE			BIT(2)
+#define RCC_MP_CIER_HSERDYIE			BIT(3)
+#define RCC_MP_CIER_CSIRDYIE			BIT(4)
+#define RCC_MP_CIER_PLL1DYIE			BIT(8)
+#define RCC_MP_CIER_PLL2DYIE			BIT(9)
+#define RCC_MP_CIER_PLL3DYIE			BIT(10)
+#define RCC_MP_CIER_PLL4DYIE			BIT(11)
+#define RCC_MP_CIER_LSECSSIE			BIT(16)
+#define RCC_MP_CIER_WKUPIE			BIT(20)
+
+/* RCC_MP_CIFR register fields */
+#define RCC_MP_CIFR_MASK			U(0x110F1F)
+#define RCC_MP_CIFR_LSIRDYF			BIT(0)
+#define RCC_MP_CIFR_LSERDYF			BIT(1)
+#define RCC_MP_CIFR_HSIRDYF			BIT(2)
+#define RCC_MP_CIFR_HSERDYF			BIT(3)
+#define RCC_MP_CIFR_CSIRDYF			BIT(4)
+#define RCC_MP_CIFR_PLL1DYF			BIT(8)
+#define RCC_MP_CIFR_PLL2DYF			BIT(9)
+#define RCC_MP_CIFR_PLL3DYF			BIT(10)
+#define RCC_MP_CIFR_PLL4DYF			BIT(11)
+#define RCC_MP_CIFR_LSECSSF			BIT(16)
+#define RCC_MP_CIFR_WKUPF			BIT(20)
+
+/* RCC_PWRLPDLYCR register fields */
+#define RCC_PWRLPDLYCR_PWRLP_DLY_MASK		GENMASK(21, 0)
+#define RCC_PWRLPDLYCR_PWRLP_DLY_SHIFT		0
+#define RCC_PWRLPDLYCR_MCTMPSKP			BIT(24)
+
+/* RCC_MP_RSTSSETR register fields */
+#define RCC_MP_RSTSSETR_PORRSTF			BIT(0)
+#define RCC_MP_RSTSSETR_BORRSTF			BIT(1)
+#define RCC_MP_RSTSSETR_PADRSTF			BIT(2)
+#define RCC_MP_RSTSSETR_HCSSRSTF		BIT(3)
+#define RCC_MP_RSTSSETR_VCORERSTF		BIT(4)
+#define RCC_MP_RSTSSETR_MPSYSRSTF		BIT(6)
+#define RCC_MP_RSTSSETR_MCSYSRSTF		BIT(7)
+#define RCC_MP_RSTSSETR_IWDG1RSTF		BIT(8)
+#define RCC_MP_RSTSSETR_IWDG2RSTF		BIT(9)
+#define RCC_MP_RSTSSETR_STDBYRSTF		BIT(11)
+#define RCC_MP_RSTSSETR_CSTDBYRSTF		BIT(12)
+#define RCC_MP_RSTSSETR_MPUP0RSTF		BIT(13)
+#define RCC_MP_RSTSSETR_MPUP1RSTF		BIT(14)
+#define RCC_MP_RSTSSETR_SPARE			BIT(15)
+
+/* RCC_MCO1CFGR register fields */
+#define RCC_MCO1CFGR_MCO1SEL_MASK		GENMASK(2, 0)
+#define RCC_MCO1CFGR_MCO1SEL_SHIFT		0
+#define RCC_MCO1CFGR_MCO1DIV_MASK		GENMASK(7, 4)
+#define RCC_MCO1CFGR_MCO1DIV_SHIFT		4
+#define RCC_MCO1CFGR_MCO1ON			BIT(12)
+
+/* RCC_MCO2CFGR register fields */
+#define RCC_MCO2CFGR_MCO2SEL_MASK		GENMASK(2, 0)
+#define RCC_MCO2CFGR_MCO2SEL_SHIFT		0
+#define RCC_MCO2CFGR_MCO2DIV_MASK		GENMASK(7, 4)
+#define RCC_MCO2CFGR_MCO2DIV_SHIFT		4
+#define RCC_MCO2CFGR_MCO2ON			BIT(12)
+
+/* RCC_OCRDYR register fields */
+#define RCC_OCRDYR_HSIRDY			BIT(0)
+#define RCC_OCRDYR_HSIDIVRDY			BIT(2)
+#define RCC_OCRDYR_CSIRDY			BIT(4)
+#define RCC_OCRDYR_HSERDY			BIT(8)
+#define RCC_OCRDYR_MPUCKRDY			BIT(23)
+#define RCC_OCRDYR_AXICKRDY			BIT(24)
+#define RCC_OCRDYR_CKREST			BIT(25)
+
+/* RCC_DBGCFGR register fields */
+#define RCC_DBGCFGR_TRACEDIV_MASK		GENMASK(2, 0)
+#define RCC_DBGCFGR_TRACEDIV_SHIFT		0
+#define RCC_DBGCFGR_DBGCKEN			BIT(8)
+#define RCC_DBGCFGR_TRACECKEN			BIT(9)
+#define RCC_DBGCFGR_DBGRST			BIT(12)
+
+/* RCC_RCK3SELR register fields */
+#define RCC_RCK3SELR_PLL3SRC_MASK		GENMASK(1, 0)
+#define RCC_RCK3SELR_PLL3SRC_SHIFT		0
+#define RCC_RCK3SELR_PLL3SRCRDY			BIT(31)
+
+/* RCC_RCK4SELR register fields */
+#define RCC_RCK4SELR_PLL4SRC_MASK		GENMASK(1, 0)
+#define RCC_RCK4SELR_PLL4SRC_SHIFT		0
+#define RCC_RCK4SELR_PLL4SRCRDY			BIT(31)
+
+/* RCC_TIMG1PRER register fields */
+#define RCC_TIMG1PRER_TIMG1PRE			BIT(0)
+#define RCC_TIMG1PRER_TIMG1PRERDY		BIT(31)
+
+/* RCC_TIMG2PRER register fields */
+#define RCC_TIMG2PRER_TIMG2PRE			BIT(0)
+#define RCC_TIMG2PRER_TIMG2PRERDY		BIT(31)
+
+/* RCC_MCUDIVR register fields */
+#define RCC_MCUDIVR_MCUDIV_MASK			GENMASK(3, 0)
+#define RCC_MCUDIVR_MCUDIV_SHIFT		0
+#define RCC_MCUDIVR_MCUDIVRDY			BIT(31)
+
+/* RCC_APB1DIVR register fields */
+#define RCC_APB1DIVR_APB1DIV_MASK		GENMASK(2, 0)
+#define RCC_APB1DIVR_APB1DIV_SHIFT		0
+#define RCC_APB1DIVR_APB1DIVRDY			BIT(31)
+
+/* RCC_APB2DIVR register fields */
+#define RCC_APB2DIVR_APB2DIV_MASK		GENMASK(2, 0)
+#define RCC_APB2DIVR_APB2DIV_SHIFT		0
+#define RCC_APB2DIVR_APB2DIVRDY			BIT(31)
+
+/* RCC_APB3DIVR register fields */
+#define RCC_APB3DIVR_APB3DIV_MASK		GENMASK(2, 0)
+#define RCC_APB3DIVR_APB3DIV_SHIFT		0
+#define RCC_APB3DIVR_APB3DIVRDY			BIT(31)
+
+/* RCC_PLL3CR register fields */
+#define RCC_PLL3CR_PLLON			BIT(0)
+#define RCC_PLL3CR_PLL3RDY			BIT(1)
+#define RCC_PLL3CR_SSCG_CTRL			BIT(2)
+#define RCC_PLL3CR_DIVPEN			BIT(4)
+#define RCC_PLL3CR_DIVQEN			BIT(5)
+#define RCC_PLL3CR_DIVREN			BIT(6)
+
+/* RCC_PLL3CFGR1 register fields */
+#define RCC_PLL3CFGR1_DIVN_MASK			GENMASK(8, 0)
+#define RCC_PLL3CFGR1_DIVN_SHIFT		0
+#define RCC_PLL3CFGR1_DIVM3_MASK		GENMASK(21, 16)
+#define RCC_PLL3CFGR1_DIVM3_SHIFT		16
+#define RCC_PLL3CFGR1_IFRGE_MASK		GENMASK(25, 24)
+#define RCC_PLL3CFGR1_IFRGE_SHIFT		24
+
+/* RCC_PLL3CFGR2 register fields */
+#define RCC_PLL3CFGR2_DIVP_MASK			GENMASK(6, 0)
+#define RCC_PLL3CFGR2_DIVP_SHIFT		0
+#define RCC_PLL3CFGR2_DIVQ_MASK			GENMASK(14, 8)
+#define RCC_PLL3CFGR2_DIVQ_SHIFT		8
+#define RCC_PLL3CFGR2_DIVR_MASK			GENMASK(22, 16)
+#define RCC_PLL3CFGR2_DIVR_SHIFT		16
+
+/* RCC_PLL3FRACR register fields */
+#define RCC_PLL3FRACR_FRACV_MASK		GENMASK(15, 3)
+#define RCC_PLL3FRACR_FRACV_SHIFT		3
+#define RCC_PLL3FRACR_FRACLE			BIT(16)
+
+/* RCC_PLL3CSGR register fields */
+#define RCC_PLL3CSGR_MOD_PER_MASK		GENMASK(12, 0)
+#define RCC_PLL3CSGR_MOD_PER_SHIFT		0
+#define RCC_PLL3CSGR_TPDFN_DIS			BIT(13)
+#define RCC_PLL3CSGR_RPDFN_DIS			BIT(14)
+#define RCC_PLL3CSGR_SSCG_MODE			BIT(15)
+#define RCC_PLL3CSGR_INC_STEP_MASK		GENMASK(30, 16)
+#define RCC_PLL3CSGR_INC_STEP_SHIFT		16
+
+/* RCC_PLL4CR register fields */
+#define RCC_PLL4CR_PLLON			BIT(0)
+#define RCC_PLL4CR_PLL4RDY			BIT(1)
+#define RCC_PLL4CR_SSCG_CTRL			BIT(2)
+#define RCC_PLL4CR_DIVPEN			BIT(4)
+#define RCC_PLL4CR_DIVQEN			BIT(5)
+#define RCC_PLL4CR_DIVREN			BIT(6)
+
+/* RCC_PLL4CFGR1 register fields */
+#define RCC_PLL4CFGR1_DIVN_MASK			GENMASK(8, 0)
+#define RCC_PLL4CFGR1_DIVN_SHIFT		0
+#define RCC_PLL4CFGR1_DIVM4_MASK		GENMASK(21, 16)
+#define RCC_PLL4CFGR1_DIVM4_SHIFT		16
+#define RCC_PLL4CFGR1_IFRGE_MASK		GENMASK(25, 24)
+#define RCC_PLL4CFGR1_IFRGE_SHIFT		24
+
+/* RCC_PLL4CFGR2 register fields */
+#define RCC_PLL4CFGR2_DIVP_MASK			GENMASK(6, 0)
+#define RCC_PLL4CFGR2_DIVP_SHIFT		0
+#define RCC_PLL4CFGR2_DIVQ_MASK			GENMASK(14, 8)
+#define RCC_PLL4CFGR2_DIVQ_SHIFT		8
+#define RCC_PLL4CFGR2_DIVR_MASK			GENMASK(22, 16)
+#define RCC_PLL4CFGR2_DIVR_SHIFT		16
+
+/* RCC_PLL4FRACR register fields */
+#define RCC_PLL4FRACR_FRACV_MASK		GENMASK(15, 3)
+#define RCC_PLL4FRACR_FRACV_SHIFT		3
+#define RCC_PLL4FRACR_FRACLE			BIT(16)
+
+/* RCC_PLL4CSGR register fields */
+#define RCC_PLL4CSGR_MOD_PER_MASK		GENMASK(12, 0)
+#define RCC_PLL4CSGR_MOD_PER_SHIFT		0
+#define RCC_PLL4CSGR_TPDFN_DIS			BIT(13)
+#define RCC_PLL4CSGR_RPDFN_DIS			BIT(14)
+#define RCC_PLL4CSGR_SSCG_MODE			BIT(15)
+#define RCC_PLL4CSGR_INC_STEP_MASK		GENMASK(30, 16)
+#define RCC_PLL4CSGR_INC_STEP_SHIFT		16
 
 /* RCC_I2C12CKSELR register fields */
 #define RCC_I2C12CKSELR_I2C12SRC_MASK		GENMASK(2, 0)
@@ -520,11 +1170,40 @@
 #define RCC_I2C35CKSELR_I2C35SRC_MASK		GENMASK(2, 0)
 #define RCC_I2C35CKSELR_I2C35SRC_SHIFT		0
 
+/* RCC_SAI1CKSELR register fields */
+#define RCC_SAI1CKSELR_SAI1SRC_MASK		GENMASK(2, 0)
+#define RCC_SAI1CKSELR_SAI1SRC_SHIFT		0
+
+/* RCC_SAI2CKSELR register fields */
+#define RCC_SAI2CKSELR_SAI2SRC_MASK		GENMASK(2, 0)
+#define RCC_SAI2CKSELR_SAI2SRC_SHIFT		0
+
+/* RCC_SAI3CKSELR register fields */
+#define RCC_SAI3CKSELR_SAI3SRC_MASK		GENMASK(2, 0)
+#define RCC_SAI3CKSELR_SAI3SRC_SHIFT		0
+
+/* RCC_SAI4CKSELR register fields */
+#define RCC_SAI4CKSELR_SAI4SRC_MASK		GENMASK(2, 0)
+#define RCC_SAI4CKSELR_SAI4SRC_SHIFT		0
+
+/* RCC_SPI2S1CKSELR register fields */
+#define RCC_SPI2S1CKSELR_SPI1SRC_MASK		GENMASK(2, 0)
+#define RCC_SPI2S1CKSELR_SPI1SRC_SHIFT		0
+
+/* RCC_SPI2S23CKSELR register fields */
+#define RCC_SPI2S23CKSELR_SPI23SRC_MASK		GENMASK(2, 0)
+#define RCC_SPI2S23CKSELR_SPI23SRC_SHIFT	0
+
+/* RCC_SPI45CKSELR register fields */
+#define RCC_SPI45CKSELR_SPI45SRC_MASK		GENMASK(2, 0)
+#define RCC_SPI45CKSELR_SPI45SRC_SHIFT		0
+
 /* RCC_UART6CKSELR register fields */
 #define RCC_UART6CKSELR_UART6SRC_MASK		GENMASK(2, 0)
 #define RCC_UART6CKSELR_UART6SRC_SHIFT		0
 
 /* RCC_UART24CKSELR register fields */
+#define RCC_UART24CKSELR_HSI			0x00000002
 #define RCC_UART24CKSELR_UART24SRC_MASK		GENMASK(2, 0)
 #define RCC_UART24CKSELR_UART24SRC_SHIFT	0
 
@@ -547,6 +1226,8 @@
 /* RCC_ETHCKSELR register fields */
 #define RCC_ETHCKSELR_ETHSRC_MASK		GENMASK(1, 0)
 #define RCC_ETHCKSELR_ETHSRC_SHIFT		0
+#define RCC_ETHCKSELR_ETHPTPDIV_MASK		GENMASK(7, 4)
+#define RCC_ETHCKSELR_ETHPTPDIV_SHIFT		4
 
 /* RCC_QSPICKSELR register fields */
 #define RCC_QSPICKSELR_QSPISRC_MASK		GENMASK(1, 0)
@@ -556,10 +1237,1092 @@
 #define RCC_FMCCKSELR_FMCSRC_MASK		GENMASK(1, 0)
 #define RCC_FMCCKSELR_FMCSRC_SHIFT		0
 
+/* RCC_FDCANCKSELR register fields */
+#define RCC_FDCANCKSELR_FDCANSRC_MASK		GENMASK(1, 0)
+#define RCC_FDCANCKSELR_FDCANSRC_SHIFT		0
+
+/* RCC_SPDIFCKSELR register fields */
+#define RCC_SPDIFCKSELR_SPDIFSRC_MASK		GENMASK(1, 0)
+#define RCC_SPDIFCKSELR_SPDIFSRC_SHIFT		0
+
+/* RCC_CECCKSELR register fields */
+#define RCC_CECCKSELR_CECSRC_MASK		GENMASK(1, 0)
+#define RCC_CECCKSELR_CECSRC_SHIFT		0
+
 /* RCC_USBCKSELR register fields */
 #define RCC_USBCKSELR_USBPHYSRC_MASK		GENMASK(1, 0)
 #define RCC_USBCKSELR_USBPHYSRC_SHIFT		0
+#define RCC_USBCKSELR_USBOSRC			BIT(4)
 #define RCC_USBCKSELR_USBOSRC_MASK		BIT(4)
 #define RCC_USBCKSELR_USBOSRC_SHIFT		4
 
+/* RCC_RNG2CKSELR register fields */
+#define RCC_RNG2CKSELR_RNG2SRC_MASK		GENMASK(1, 0)
+#define RCC_RNG2CKSELR_RNG2SRC_SHIFT		0
+
+/* RCC_DSICKSELR register fields */
+#define RCC_DSICKSELR_DSISRC			BIT(0)
+
+/* RCC_ADCCKSELR register fields */
+#define RCC_ADCCKSELR_ADCSRC_MASK		GENMASK(1, 0)
+#define RCC_ADCCKSELR_ADCSRC_SHIFT		0
+
+/* RCC_LPTIM45CKSELR register fields */
+#define RCC_LPTIM45CKSELR_LPTIM45SRC_MASK	GENMASK(2, 0)
+#define RCC_LPTIM45CKSELR_LPTIM45SRC_SHIFT	0
+
+/* RCC_LPTIM23CKSELR register fields */
+#define RCC_LPTIM23CKSELR_LPTIM23SRC_MASK	GENMASK(2, 0)
+#define RCC_LPTIM23CKSELR_LPTIM23SRC_SHIFT	0
+
+/* RCC_LPTIM1CKSELR register fields */
+#define RCC_LPTIM1CKSELR_LPTIM1SRC_MASK		GENMASK(2, 0)
+#define RCC_LPTIM1CKSELR_LPTIM1SRC_SHIFT	0
+
+/* RCC_APB1RSTSETR register fields */
+#define RCC_APB1RSTSETR_TIM2RST			BIT(0)
+#define RCC_APB1RSTSETR_TIM3RST			BIT(1)
+#define RCC_APB1RSTSETR_TIM4RST			BIT(2)
+#define RCC_APB1RSTSETR_TIM5RST			BIT(3)
+#define RCC_APB1RSTSETR_TIM6RST			BIT(4)
+#define RCC_APB1RSTSETR_TIM7RST			BIT(5)
+#define RCC_APB1RSTSETR_TIM12RST		BIT(6)
+#define RCC_APB1RSTSETR_TIM13RST		BIT(7)
+#define RCC_APB1RSTSETR_TIM14RST		BIT(8)
+#define RCC_APB1RSTSETR_LPTIM1RST		BIT(9)
+#define RCC_APB1RSTSETR_SPI2RST			BIT(11)
+#define RCC_APB1RSTSETR_SPI3RST			BIT(12)
+#define RCC_APB1RSTSETR_USART2RST		BIT(14)
+#define RCC_APB1RSTSETR_USART3RST		BIT(15)
+#define RCC_APB1RSTSETR_UART4RST		BIT(16)
+#define RCC_APB1RSTSETR_UART5RST		BIT(17)
+#define RCC_APB1RSTSETR_UART7RST		BIT(18)
+#define RCC_APB1RSTSETR_UART8RST		BIT(19)
+#define RCC_APB1RSTSETR_I2C1RST			BIT(21)
+#define RCC_APB1RSTSETR_I2C2RST			BIT(22)
+#define RCC_APB1RSTSETR_I2C3RST			BIT(23)
+#define RCC_APB1RSTSETR_I2C5RST			BIT(24)
+#define RCC_APB1RSTSETR_SPDIFRST		BIT(26)
+#define RCC_APB1RSTSETR_CECRST			BIT(27)
+#define RCC_APB1RSTSETR_DAC12RST		BIT(29)
+#define RCC_APB1RSTSETR_MDIOSRST		BIT(31)
+
+/* RCC_APB1RSTCLRR register fields */
+#define RCC_APB1RSTCLRR_TIM2RST			BIT(0)
+#define RCC_APB1RSTCLRR_TIM3RST			BIT(1)
+#define RCC_APB1RSTCLRR_TIM4RST			BIT(2)
+#define RCC_APB1RSTCLRR_TIM5RST			BIT(3)
+#define RCC_APB1RSTCLRR_TIM6RST			BIT(4)
+#define RCC_APB1RSTCLRR_TIM7RST			BIT(5)
+#define RCC_APB1RSTCLRR_TIM12RST		BIT(6)
+#define RCC_APB1RSTCLRR_TIM13RST		BIT(7)
+#define RCC_APB1RSTCLRR_TIM14RST		BIT(8)
+#define RCC_APB1RSTCLRR_LPTIM1RST		BIT(9)
+#define RCC_APB1RSTCLRR_SPI2RST			BIT(11)
+#define RCC_APB1RSTCLRR_SPI3RST			BIT(12)
+#define RCC_APB1RSTCLRR_USART2RST		BIT(14)
+#define RCC_APB1RSTCLRR_USART3RST		BIT(15)
+#define RCC_APB1RSTCLRR_UART4RST		BIT(16)
+#define RCC_APB1RSTCLRR_UART5RST		BIT(17)
+#define RCC_APB1RSTCLRR_UART7RST		BIT(18)
+#define RCC_APB1RSTCLRR_UART8RST		BIT(19)
+#define RCC_APB1RSTCLRR_I2C1RST			BIT(21)
+#define RCC_APB1RSTCLRR_I2C2RST			BIT(22)
+#define RCC_APB1RSTCLRR_I2C3RST			BIT(23)
+#define RCC_APB1RSTCLRR_I2C5RST			BIT(24)
+#define RCC_APB1RSTCLRR_SPDIFRST		BIT(26)
+#define RCC_APB1RSTCLRR_CECRST			BIT(27)
+#define RCC_APB1RSTCLRR_DAC12RST		BIT(29)
+#define RCC_APB1RSTCLRR_MDIOSRST		BIT(31)
+
+/* RCC_APB2RSTSETR register fields */
+#define RCC_APB2RSTSETR_TIM1RST			BIT(0)
+#define RCC_APB2RSTSETR_TIM8RST			BIT(1)
+#define RCC_APB2RSTSETR_TIM15RST		BIT(2)
+#define RCC_APB2RSTSETR_TIM16RST		BIT(3)
+#define RCC_APB2RSTSETR_TIM17RST		BIT(4)
+#define RCC_APB2RSTSETR_SPI1RST			BIT(8)
+#define RCC_APB2RSTSETR_SPI4RST			BIT(9)
+#define RCC_APB2RSTSETR_SPI5RST			BIT(10)
+#define RCC_APB2RSTSETR_USART6RST		BIT(13)
+#define RCC_APB2RSTSETR_SAI1RST			BIT(16)
+#define RCC_APB2RSTSETR_SAI2RST			BIT(17)
+#define RCC_APB2RSTSETR_SAI3RST			BIT(18)
+#define RCC_APB2RSTSETR_DFSDMRST		BIT(20)
+#define RCC_APB2RSTSETR_FDCANRST		BIT(24)
+
+/* RCC_APB2RSTCLRR register fields */
+#define RCC_APB2RSTCLRR_TIM1RST			BIT(0)
+#define RCC_APB2RSTCLRR_TIM8RST			BIT(1)
+#define RCC_APB2RSTCLRR_TIM15RST		BIT(2)
+#define RCC_APB2RSTCLRR_TIM16RST		BIT(3)
+#define RCC_APB2RSTCLRR_TIM17RST		BIT(4)
+#define RCC_APB2RSTCLRR_SPI1RST			BIT(8)
+#define RCC_APB2RSTCLRR_SPI4RST			BIT(9)
+#define RCC_APB2RSTCLRR_SPI5RST			BIT(10)
+#define RCC_APB2RSTCLRR_USART6RST		BIT(13)
+#define RCC_APB2RSTCLRR_SAI1RST			BIT(16)
+#define RCC_APB2RSTCLRR_SAI2RST			BIT(17)
+#define RCC_APB2RSTCLRR_SAI3RST			BIT(18)
+#define RCC_APB2RSTCLRR_DFSDMRST		BIT(20)
+#define RCC_APB2RSTCLRR_FDCANRST		BIT(24)
+
+/* RCC_APB3RSTSETR register fields */
+#define RCC_APB3RSTSETR_LPTIM2RST		BIT(0)
+#define RCC_APB3RSTSETR_LPTIM3RST		BIT(1)
+#define RCC_APB3RSTSETR_LPTIM4RST		BIT(2)
+#define RCC_APB3RSTSETR_LPTIM5RST		BIT(3)
+#define RCC_APB3RSTSETR_SAI4RST			BIT(8)
+#define RCC_APB3RSTSETR_SYSCFGRST		BIT(11)
+#define RCC_APB3RSTSETR_VREFRST			BIT(13)
+#define RCC_APB3RSTSETR_TMPSENSRST		BIT(16)
+#define RCC_APB3RSTSETR_PMBCTRLRST		BIT(17)
+
+/* RCC_APB3RSTCLRR register fields */
+#define RCC_APB3RSTCLRR_LPTIM2RST		BIT(0)
+#define RCC_APB3RSTCLRR_LPTIM3RST		BIT(1)
+#define RCC_APB3RSTCLRR_LPTIM4RST		BIT(2)
+#define RCC_APB3RSTCLRR_LPTIM5RST		BIT(3)
+#define RCC_APB3RSTCLRR_SAI4RST			BIT(8)
+#define RCC_APB3RSTCLRR_SYSCFGRST		BIT(11)
+#define RCC_APB3RSTCLRR_VREFRST			BIT(13)
+#define RCC_APB3RSTCLRR_TMPSENSRST		BIT(16)
+#define RCC_APB3RSTCLRR_PMBCTRLRST		BIT(17)
+
+/* RCC_AHB2RSTSETR register fields */
+#define RCC_AHB2RSTSETR_DMA1RST			BIT(0)
+#define RCC_AHB2RSTSETR_DMA2RST			BIT(1)
+#define RCC_AHB2RSTSETR_DMAMUXRST		BIT(2)
+#define RCC_AHB2RSTSETR_ADC12RST		BIT(5)
+#define RCC_AHB2RSTSETR_USBORST			BIT(8)
+#define RCC_AHB2RSTSETR_SDMMC3RST		BIT(16)
+
+/* RCC_AHB2RSTCLRR register fields */
+#define RCC_AHB2RSTCLRR_DMA1RST			BIT(0)
+#define RCC_AHB2RSTCLRR_DMA2RST			BIT(1)
+#define RCC_AHB2RSTCLRR_DMAMUXRST		BIT(2)
+#define RCC_AHB2RSTCLRR_ADC12RST		BIT(5)
+#define RCC_AHB2RSTCLRR_USBORST			BIT(8)
+#define RCC_AHB2RSTCLRR_SDMMC3RST		BIT(16)
+
+/* RCC_AHB3RSTSETR register fields */
+#define RCC_AHB3RSTSETR_DCMIRST			BIT(0)
+#define RCC_AHB3RSTSETR_CRYP2RST		BIT(4)
+#define RCC_AHB3RSTSETR_HASH2RST		BIT(5)
+#define RCC_AHB3RSTSETR_RNG2RST			BIT(6)
+#define RCC_AHB3RSTSETR_CRC2RST			BIT(7)
+#define RCC_AHB3RSTSETR_HSEMRST			BIT(11)
+#define RCC_AHB3RSTSETR_IPCCRST			BIT(12)
+
+/* RCC_AHB3RSTCLRR register fields */
+#define RCC_AHB3RSTCLRR_DCMIRST			BIT(0)
+#define RCC_AHB3RSTCLRR_CRYP2RST		BIT(4)
+#define RCC_AHB3RSTCLRR_HASH2RST		BIT(5)
+#define RCC_AHB3RSTCLRR_RNG2RST			BIT(6)
+#define RCC_AHB3RSTCLRR_CRC2RST			BIT(7)
+#define RCC_AHB3RSTCLRR_HSEMRST			BIT(11)
+#define RCC_AHB3RSTCLRR_IPCCRST			BIT(12)
+
+/* RCC_AHB4RSTSETR register fields */
+#define RCC_AHB4RSTSETR_GPIOARST		BIT(0)
+#define RCC_AHB4RSTSETR_GPIOBRST		BIT(1)
+#define RCC_AHB4RSTSETR_GPIOCRST		BIT(2)
+#define RCC_AHB4RSTSETR_GPIODRST		BIT(3)
+#define RCC_AHB4RSTSETR_GPIOERST		BIT(4)
+#define RCC_AHB4RSTSETR_GPIOFRST		BIT(5)
+#define RCC_AHB4RSTSETR_GPIOGRST		BIT(6)
+#define RCC_AHB4RSTSETR_GPIOHRST		BIT(7)
+#define RCC_AHB4RSTSETR_GPIOIRST		BIT(8)
+#define RCC_AHB4RSTSETR_GPIOJRST		BIT(9)
+#define RCC_AHB4RSTSETR_GPIOKRST		BIT(10)
+
+/* RCC_AHB4RSTCLRR register fields */
+#define RCC_AHB4RSTCLRR_GPIOARST		BIT(0)
+#define RCC_AHB4RSTCLRR_GPIOBRST		BIT(1)
+#define RCC_AHB4RSTCLRR_GPIOCRST		BIT(2)
+#define RCC_AHB4RSTCLRR_GPIODRST		BIT(3)
+#define RCC_AHB4RSTCLRR_GPIOERST		BIT(4)
+#define RCC_AHB4RSTCLRR_GPIOFRST		BIT(5)
+#define RCC_AHB4RSTCLRR_GPIOGRST		BIT(6)
+#define RCC_AHB4RSTCLRR_GPIOHRST		BIT(7)
+#define RCC_AHB4RSTCLRR_GPIOIRST		BIT(8)
+#define RCC_AHB4RSTCLRR_GPIOJRST		BIT(9)
+#define RCC_AHB4RSTCLRR_GPIOKRST		BIT(10)
+
+/* RCC_MP_APB1ENSETR register fields */
+#define RCC_MP_APB1ENSETR_TIM2EN		BIT(0)
+#define RCC_MP_APB1ENSETR_TIM3EN		BIT(1)
+#define RCC_MP_APB1ENSETR_TIM4EN		BIT(2)
+#define RCC_MP_APB1ENSETR_TIM5EN		BIT(3)
+#define RCC_MP_APB1ENSETR_TIM6EN		BIT(4)
+#define RCC_MP_APB1ENSETR_TIM7EN		BIT(5)
+#define RCC_MP_APB1ENSETR_TIM12EN		BIT(6)
+#define RCC_MP_APB1ENSETR_TIM13EN		BIT(7)
+#define RCC_MP_APB1ENSETR_TIM14EN		BIT(8)
+#define RCC_MP_APB1ENSETR_LPTIM1EN		BIT(9)
+#define RCC_MP_APB1ENSETR_SPI2EN		BIT(11)
+#define RCC_MP_APB1ENSETR_SPI3EN		BIT(12)
+#define RCC_MP_APB1ENSETR_USART2EN		BIT(14)
+#define RCC_MP_APB1ENSETR_USART3EN		BIT(15)
+#define RCC_MP_APB1ENSETR_UART4EN		BIT(16)
+#define RCC_MP_APB1ENSETR_UART5EN		BIT(17)
+#define RCC_MP_APB1ENSETR_UART7EN		BIT(18)
+#define RCC_MP_APB1ENSETR_UART8EN		BIT(19)
+#define RCC_MP_APB1ENSETR_I2C1EN		BIT(21)
+#define RCC_MP_APB1ENSETR_I2C2EN		BIT(22)
+#define RCC_MP_APB1ENSETR_I2C3EN		BIT(23)
+#define RCC_MP_APB1ENSETR_I2C5EN		BIT(24)
+#define RCC_MP_APB1ENSETR_SPDIFEN		BIT(26)
+#define RCC_MP_APB1ENSETR_CECEN			BIT(27)
+#define RCC_MP_APB1ENSETR_DAC12EN		BIT(29)
+#define RCC_MP_APB1ENSETR_MDIOSEN		BIT(31)
+
+/* RCC_MP_APB1ENCLRR register fields */
+#define RCC_MP_APB1ENCLRR_TIM2EN		BIT(0)
+#define RCC_MP_APB1ENCLRR_TIM3EN		BIT(1)
+#define RCC_MP_APB1ENCLRR_TIM4EN		BIT(2)
+#define RCC_MP_APB1ENCLRR_TIM5EN		BIT(3)
+#define RCC_MP_APB1ENCLRR_TIM6EN		BIT(4)
+#define RCC_MP_APB1ENCLRR_TIM7EN		BIT(5)
+#define RCC_MP_APB1ENCLRR_TIM12EN		BIT(6)
+#define RCC_MP_APB1ENCLRR_TIM13EN		BIT(7)
+#define RCC_MP_APB1ENCLRR_TIM14EN		BIT(8)
+#define RCC_MP_APB1ENCLRR_LPTIM1EN		BIT(9)
+#define RCC_MP_APB1ENCLRR_SPI2EN		BIT(11)
+#define RCC_MP_APB1ENCLRR_SPI3EN		BIT(12)
+#define RCC_MP_APB1ENCLRR_USART2EN		BIT(14)
+#define RCC_MP_APB1ENCLRR_USART3EN		BIT(15)
+#define RCC_MP_APB1ENCLRR_UART4EN		BIT(16)
+#define RCC_MP_APB1ENCLRR_UART5EN		BIT(17)
+#define RCC_MP_APB1ENCLRR_UART7EN		BIT(18)
+#define RCC_MP_APB1ENCLRR_UART8EN		BIT(19)
+#define RCC_MP_APB1ENCLRR_I2C1EN		BIT(21)
+#define RCC_MP_APB1ENCLRR_I2C2EN		BIT(22)
+#define RCC_MP_APB1ENCLRR_I2C3EN		BIT(23)
+#define RCC_MP_APB1ENCLRR_I2C5EN		BIT(24)
+#define RCC_MP_APB1ENCLRR_SPDIFEN		BIT(26)
+#define RCC_MP_APB1ENCLRR_CECEN			BIT(27)
+#define RCC_MP_APB1ENCLRR_DAC12EN		BIT(29)
+#define RCC_MP_APB1ENCLRR_MDIOSEN		BIT(31)
+
+/* RCC_MP_APB2ENSETR register fields */
+#define RCC_MP_APB2ENSETR_TIM1EN		BIT(0)
+#define RCC_MP_APB2ENSETR_TIM8EN		BIT(1)
+#define RCC_MP_APB2ENSETR_TIM15EN		BIT(2)
+#define RCC_MP_APB2ENSETR_TIM16EN		BIT(3)
+#define RCC_MP_APB2ENSETR_TIM17EN		BIT(4)
+#define RCC_MP_APB2ENSETR_SPI1EN		BIT(8)
+#define RCC_MP_APB2ENSETR_SPI4EN		BIT(9)
+#define RCC_MP_APB2ENSETR_SPI5EN		BIT(10)
+#define RCC_MP_APB2ENSETR_USART6EN		BIT(13)
+#define RCC_MP_APB2ENSETR_SAI1EN		BIT(16)
+#define RCC_MP_APB2ENSETR_SAI2EN		BIT(17)
+#define RCC_MP_APB2ENSETR_SAI3EN		BIT(18)
+#define RCC_MP_APB2ENSETR_DFSDMEN		BIT(20)
+#define RCC_MP_APB2ENSETR_ADFSDMEN		BIT(21)
+#define RCC_MP_APB2ENSETR_FDCANEN		BIT(24)
+
+/* RCC_MP_APB2ENCLRR register fields */
+#define RCC_MP_APB2ENCLRR_TIM1EN		BIT(0)
+#define RCC_MP_APB2ENCLRR_TIM8EN		BIT(1)
+#define RCC_MP_APB2ENCLRR_TIM15EN		BIT(2)
+#define RCC_MP_APB2ENCLRR_TIM16EN		BIT(3)
+#define RCC_MP_APB2ENCLRR_TIM17EN		BIT(4)
+#define RCC_MP_APB2ENCLRR_SPI1EN		BIT(8)
+#define RCC_MP_APB2ENCLRR_SPI4EN		BIT(9)
+#define RCC_MP_APB2ENCLRR_SPI5EN		BIT(10)
+#define RCC_MP_APB2ENCLRR_USART6EN		BIT(13)
+#define RCC_MP_APB2ENCLRR_SAI1EN		BIT(16)
+#define RCC_MP_APB2ENCLRR_SAI2EN		BIT(17)
+#define RCC_MP_APB2ENCLRR_SAI3EN		BIT(18)
+#define RCC_MP_APB2ENCLRR_DFSDMEN		BIT(20)
+#define RCC_MP_APB2ENCLRR_ADFSDMEN		BIT(21)
+#define RCC_MP_APB2ENCLRR_FDCANEN		BIT(24)
+
+/* RCC_MP_APB3ENSETR register fields */
+#define RCC_MP_APB3ENSETR_LPTIM2EN		BIT(0)
+#define RCC_MP_APB3ENSETR_LPTIM3EN		BIT(1)
+#define RCC_MP_APB3ENSETR_LPTIM4EN		BIT(2)
+#define RCC_MP_APB3ENSETR_LPTIM5EN		BIT(3)
+#define RCC_MP_APB3ENSETR_SAI4EN		BIT(8)
+#define RCC_MP_APB3ENSETR_SYSCFGEN		BIT(11)
+#define RCC_MP_APB3ENSETR_VREFEN		BIT(13)
+#define RCC_MP_APB3ENSETR_TMPSENSEN		BIT(16)
+#define RCC_MP_APB3ENSETR_PMBCTRLEN		BIT(17)
+#define RCC_MP_APB3ENSETR_HDPEN			BIT(20)
+
+/* RCC_MP_APB3ENCLRR register fields */
+#define RCC_MP_APB3ENCLRR_LPTIM2EN		BIT(0)
+#define RCC_MP_APB3ENCLRR_LPTIM3EN		BIT(1)
+#define RCC_MP_APB3ENCLRR_LPTIM4EN		BIT(2)
+#define RCC_MP_APB3ENCLRR_LPTIM5EN		BIT(3)
+#define RCC_MP_APB3ENCLRR_SAI4EN		BIT(8)
+#define RCC_MP_APB3ENCLRR_SYSCFGEN		BIT(11)
+#define RCC_MP_APB3ENCLRR_VREFEN		BIT(13)
+#define RCC_MP_APB3ENCLRR_TMPSENSEN		BIT(16)
+#define RCC_MP_APB3ENCLRR_PMBCTRLEN		BIT(17)
+#define RCC_MP_APB3ENCLRR_HDPEN			BIT(20)
+
+/* RCC_MP_AHB2ENSETR register fields */
+#define RCC_MP_AHB2ENSETR_DMA1EN		BIT(0)
+#define RCC_MP_AHB2ENSETR_DMA2EN		BIT(1)
+#define RCC_MP_AHB2ENSETR_DMAMUXEN		BIT(2)
+#define RCC_MP_AHB2ENSETR_ADC12EN		BIT(5)
+#define RCC_MP_AHB2ENSETR_USBOEN		BIT(8)
+#define RCC_MP_AHB2ENSETR_SDMMC3EN		BIT(16)
+
+/* RCC_MP_AHB2ENCLRR register fields */
+#define RCC_MP_AHB2ENCLRR_DMA1EN		BIT(0)
+#define RCC_MP_AHB2ENCLRR_DMA2EN		BIT(1)
+#define RCC_MP_AHB2ENCLRR_DMAMUXEN		BIT(2)
+#define RCC_MP_AHB2ENCLRR_ADC12EN		BIT(5)
+#define RCC_MP_AHB2ENCLRR_USBOEN		BIT(8)
+#define RCC_MP_AHB2ENCLRR_SDMMC3EN		BIT(16)
+
+/* RCC_MP_AHB3ENSETR register fields */
+#define RCC_MP_AHB3ENSETR_DCMIEN		BIT(0)
+#define RCC_MP_AHB3ENSETR_CRYP2EN		BIT(4)
+#define RCC_MP_AHB3ENSETR_HASH2EN		BIT(5)
+#define RCC_MP_AHB3ENSETR_RNG2EN		BIT(6)
+#define RCC_MP_AHB3ENSETR_CRC2EN		BIT(7)
+#define RCC_MP_AHB3ENSETR_HSEMEN		BIT(11)
+#define RCC_MP_AHB3ENSETR_IPCCEN		BIT(12)
+
+/* RCC_MP_AHB3ENCLRR register fields */
+#define RCC_MP_AHB3ENCLRR_DCMIEN		BIT(0)
+#define RCC_MP_AHB3ENCLRR_CRYP2EN		BIT(4)
+#define RCC_MP_AHB3ENCLRR_HASH2EN		BIT(5)
+#define RCC_MP_AHB3ENCLRR_RNG2EN		BIT(6)
+#define RCC_MP_AHB3ENCLRR_CRC2EN		BIT(7)
+#define RCC_MP_AHB3ENCLRR_HSEMEN		BIT(11)
+#define RCC_MP_AHB3ENCLRR_IPCCEN		BIT(12)
+
+/* RCC_MP_AHB4ENSETR register fields */
+#define RCC_MP_AHB4ENSETR_GPIOAEN		BIT(0)
+#define RCC_MP_AHB4ENSETR_GPIOBEN		BIT(1)
+#define RCC_MP_AHB4ENSETR_GPIOCEN		BIT(2)
+#define RCC_MP_AHB4ENSETR_GPIODEN		BIT(3)
+#define RCC_MP_AHB4ENSETR_GPIOEEN		BIT(4)
+#define RCC_MP_AHB4ENSETR_GPIOFEN		BIT(5)
+#define RCC_MP_AHB4ENSETR_GPIOGEN		BIT(6)
+#define RCC_MP_AHB4ENSETR_GPIOHEN		BIT(7)
+#define RCC_MP_AHB4ENSETR_GPIOIEN		BIT(8)
+#define RCC_MP_AHB4ENSETR_GPIOJEN		BIT(9)
+#define RCC_MP_AHB4ENSETR_GPIOKEN		BIT(10)
+
+/* RCC_MP_AHB4ENCLRR register fields */
+#define RCC_MP_AHB4ENCLRR_GPIOAEN		BIT(0)
+#define RCC_MP_AHB4ENCLRR_GPIOBEN		BIT(1)
+#define RCC_MP_AHB4ENCLRR_GPIOCEN		BIT(2)
+#define RCC_MP_AHB4ENCLRR_GPIODEN		BIT(3)
+#define RCC_MP_AHB4ENCLRR_GPIOEEN		BIT(4)
+#define RCC_MP_AHB4ENCLRR_GPIOFEN		BIT(5)
+#define RCC_MP_AHB4ENCLRR_GPIOGEN		BIT(6)
+#define RCC_MP_AHB4ENCLRR_GPIOHEN		BIT(7)
+#define RCC_MP_AHB4ENCLRR_GPIOIEN		BIT(8)
+#define RCC_MP_AHB4ENCLRR_GPIOJEN		BIT(9)
+#define RCC_MP_AHB4ENCLRR_GPIOKEN		BIT(10)
+
+/* RCC_MP_MLAHBENSETR register fields */
+#define RCC_MP_MLAHBENSETR_RETRAMEN		BIT(4)
+
+/* RCC_MP_MLAHBENCLRR register fields */
+#define RCC_MP_MLAHBENCLRR_RETRAMEN		BIT(4)
+
+/* RCC_MC_APB1ENSETR register fields */
+#define RCC_MC_APB1ENSETR_TIM2EN		BIT(0)
+#define RCC_MC_APB1ENSETR_TIM3EN		BIT(1)
+#define RCC_MC_APB1ENSETR_TIM4EN		BIT(2)
+#define RCC_MC_APB1ENSETR_TIM5EN		BIT(3)
+#define RCC_MC_APB1ENSETR_TIM6EN		BIT(4)
+#define RCC_MC_APB1ENSETR_TIM7EN		BIT(5)
+#define RCC_MC_APB1ENSETR_TIM12EN		BIT(6)
+#define RCC_MC_APB1ENSETR_TIM13EN		BIT(7)
+#define RCC_MC_APB1ENSETR_TIM14EN		BIT(8)
+#define RCC_MC_APB1ENSETR_LPTIM1EN		BIT(9)
+#define RCC_MC_APB1ENSETR_SPI2EN		BIT(11)
+#define RCC_MC_APB1ENSETR_SPI3EN		BIT(12)
+#define RCC_MC_APB1ENSETR_USART2EN		BIT(14)
+#define RCC_MC_APB1ENSETR_USART3EN		BIT(15)
+#define RCC_MC_APB1ENSETR_UART4EN		BIT(16)
+#define RCC_MC_APB1ENSETR_UART5EN		BIT(17)
+#define RCC_MC_APB1ENSETR_UART7EN		BIT(18)
+#define RCC_MC_APB1ENSETR_UART8EN		BIT(19)
+#define RCC_MC_APB1ENSETR_I2C1EN		BIT(21)
+#define RCC_MC_APB1ENSETR_I2C2EN		BIT(22)
+#define RCC_MC_APB1ENSETR_I2C3EN		BIT(23)
+#define RCC_MC_APB1ENSETR_I2C5EN		BIT(24)
+#define RCC_MC_APB1ENSETR_SPDIFEN		BIT(26)
+#define RCC_MC_APB1ENSETR_CECEN			BIT(27)
+#define RCC_MC_APB1ENSETR_WWDG1EN		BIT(28)
+#define RCC_MC_APB1ENSETR_DAC12EN		BIT(29)
+#define RCC_MC_APB1ENSETR_MDIOSEN		BIT(31)
+
+/* RCC_MC_APB1ENCLRR register fields */
+#define RCC_MC_APB1ENCLRR_TIM2EN		BIT(0)
+#define RCC_MC_APB1ENCLRR_TIM3EN		BIT(1)
+#define RCC_MC_APB1ENCLRR_TIM4EN		BIT(2)
+#define RCC_MC_APB1ENCLRR_TIM5EN		BIT(3)
+#define RCC_MC_APB1ENCLRR_TIM6EN		BIT(4)
+#define RCC_MC_APB1ENCLRR_TIM7EN		BIT(5)
+#define RCC_MC_APB1ENCLRR_TIM12EN		BIT(6)
+#define RCC_MC_APB1ENCLRR_TIM13EN		BIT(7)
+#define RCC_MC_APB1ENCLRR_TIM14EN		BIT(8)
+#define RCC_MC_APB1ENCLRR_LPTIM1EN		BIT(9)
+#define RCC_MC_APB1ENCLRR_SPI2EN		BIT(11)
+#define RCC_MC_APB1ENCLRR_SPI3EN		BIT(12)
+#define RCC_MC_APB1ENCLRR_USART2EN		BIT(14)
+#define RCC_MC_APB1ENCLRR_USART3EN		BIT(15)
+#define RCC_MC_APB1ENCLRR_UART4EN		BIT(16)
+#define RCC_MC_APB1ENCLRR_UART5EN		BIT(17)
+#define RCC_MC_APB1ENCLRR_UART7EN		BIT(18)
+#define RCC_MC_APB1ENCLRR_UART8EN		BIT(19)
+#define RCC_MC_APB1ENCLRR_I2C1EN		BIT(21)
+#define RCC_MC_APB1ENCLRR_I2C2EN		BIT(22)
+#define RCC_MC_APB1ENCLRR_I2C3EN		BIT(23)
+#define RCC_MC_APB1ENCLRR_I2C5EN		BIT(24)
+#define RCC_MC_APB1ENCLRR_SPDIFEN		BIT(26)
+#define RCC_MC_APB1ENCLRR_CECEN			BIT(27)
+#define RCC_MC_APB1ENCLRR_DAC12EN		BIT(29)
+#define RCC_MC_APB1ENCLRR_MDIOSEN		BIT(31)
+
+/* RCC_MC_APB2ENSETR register fields */
+#define RCC_MC_APB2ENSETR_TIM1EN		BIT(0)
+#define RCC_MC_APB2ENSETR_TIM8EN		BIT(1)
+#define RCC_MC_APB2ENSETR_TIM15EN		BIT(2)
+#define RCC_MC_APB2ENSETR_TIM16EN		BIT(3)
+#define RCC_MC_APB2ENSETR_TIM17EN		BIT(4)
+#define RCC_MC_APB2ENSETR_SPI1EN		BIT(8)
+#define RCC_MC_APB2ENSETR_SPI4EN		BIT(9)
+#define RCC_MC_APB2ENSETR_SPI5EN		BIT(10)
+#define RCC_MC_APB2ENSETR_USART6EN		BIT(13)
+#define RCC_MC_APB2ENSETR_SAI1EN		BIT(16)
+#define RCC_MC_APB2ENSETR_SAI2EN		BIT(17)
+#define RCC_MC_APB2ENSETR_SAI3EN		BIT(18)
+#define RCC_MC_APB2ENSETR_DFSDMEN		BIT(20)
+#define RCC_MC_APB2ENSETR_ADFSDMEN		BIT(21)
+#define RCC_MC_APB2ENSETR_FDCANEN		BIT(24)
+
+/* RCC_MC_APB2ENCLRR register fields */
+#define RCC_MC_APB2ENCLRR_TIM1EN		BIT(0)
+#define RCC_MC_APB2ENCLRR_TIM8EN		BIT(1)
+#define RCC_MC_APB2ENCLRR_TIM15EN		BIT(2)
+#define RCC_MC_APB2ENCLRR_TIM16EN		BIT(3)
+#define RCC_MC_APB2ENCLRR_TIM17EN		BIT(4)
+#define RCC_MC_APB2ENCLRR_SPI1EN		BIT(8)
+#define RCC_MC_APB2ENCLRR_SPI4EN		BIT(9)
+#define RCC_MC_APB2ENCLRR_SPI5EN		BIT(10)
+#define RCC_MC_APB2ENCLRR_USART6EN		BIT(13)
+#define RCC_MC_APB2ENCLRR_SAI1EN		BIT(16)
+#define RCC_MC_APB2ENCLRR_SAI2EN		BIT(17)
+#define RCC_MC_APB2ENCLRR_SAI3EN		BIT(18)
+#define RCC_MC_APB2ENCLRR_DFSDMEN		BIT(20)
+#define RCC_MC_APB2ENCLRR_ADFSDMEN		BIT(21)
+#define RCC_MC_APB2ENCLRR_FDCANEN		BIT(24)
+
+/* RCC_MC_APB3ENSETR register fields */
+#define RCC_MC_APB3ENSETR_LPTIM2EN		BIT(0)
+#define RCC_MC_APB3ENSETR_LPTIM3EN		BIT(1)
+#define RCC_MC_APB3ENSETR_LPTIM4EN		BIT(2)
+#define RCC_MC_APB3ENSETR_LPTIM5EN		BIT(3)
+#define RCC_MC_APB3ENSETR_SAI4EN		BIT(8)
+#define RCC_MC_APB3ENSETR_SYSCFGEN		BIT(11)
+#define RCC_MC_APB3ENSETR_VREFEN		BIT(13)
+#define RCC_MC_APB3ENSETR_TMPSENSEN		BIT(16)
+#define RCC_MC_APB3ENSETR_PMBCTRLEN		BIT(17)
+#define RCC_MC_APB3ENSETR_HDPEN			BIT(20)
+
+/* RCC_MC_APB3ENCLRR register fields */
+#define RCC_MC_APB3ENCLRR_LPTIM2EN		BIT(0)
+#define RCC_MC_APB3ENCLRR_LPTIM3EN		BIT(1)
+#define RCC_MC_APB3ENCLRR_LPTIM4EN		BIT(2)
+#define RCC_MC_APB3ENCLRR_LPTIM5EN		BIT(3)
+#define RCC_MC_APB3ENCLRR_SAI4EN		BIT(8)
+#define RCC_MC_APB3ENCLRR_SYSCFGEN		BIT(11)
+#define RCC_MC_APB3ENCLRR_VREFEN		BIT(13)
+#define RCC_MC_APB3ENCLRR_TMPSENSEN		BIT(16)
+#define RCC_MC_APB3ENCLRR_PMBCTRLEN		BIT(17)
+#define RCC_MC_APB3ENCLRR_HDPEN			BIT(20)
+
+/* RCC_MC_AHB2ENSETR register fields */
+#define RCC_MC_AHB2ENSETR_DMA1EN		BIT(0)
+#define RCC_MC_AHB2ENSETR_DMA2EN		BIT(1)
+#define RCC_MC_AHB2ENSETR_DMAMUXEN		BIT(2)
+#define RCC_MC_AHB2ENSETR_ADC12EN		BIT(5)
+#define RCC_MC_AHB2ENSETR_USBOEN		BIT(8)
+#define RCC_MC_AHB2ENSETR_SDMMC3EN		BIT(16)
+
+/* RCC_MC_AHB2ENCLRR register fields */
+#define RCC_MC_AHB2ENCLRR_DMA1EN		BIT(0)
+#define RCC_MC_AHB2ENCLRR_DMA2EN		BIT(1)
+#define RCC_MC_AHB2ENCLRR_DMAMUXEN		BIT(2)
+#define RCC_MC_AHB2ENCLRR_ADC12EN		BIT(5)
+#define RCC_MC_AHB2ENCLRR_USBOEN		BIT(8)
+#define RCC_MC_AHB2ENCLRR_SDMMC3EN		BIT(16)
+
+/* RCC_MC_AHB3ENSETR register fields */
+#define RCC_MC_AHB3ENSETR_DCMIEN		BIT(0)
+#define RCC_MC_AHB3ENSETR_CRYP2EN		BIT(4)
+#define RCC_MC_AHB3ENSETR_HASH2EN		BIT(5)
+#define RCC_MC_AHB3ENSETR_RNG2EN		BIT(6)
+#define RCC_MC_AHB3ENSETR_CRC2EN		BIT(7)
+#define RCC_MC_AHB3ENSETR_HSEMEN		BIT(11)
+#define RCC_MC_AHB3ENSETR_IPCCEN		BIT(12)
+
+/* RCC_MC_AHB3ENCLRR register fields */
+#define RCC_MC_AHB3ENCLRR_DCMIEN		BIT(0)
+#define RCC_MC_AHB3ENCLRR_CRYP2EN		BIT(4)
+#define RCC_MC_AHB3ENCLRR_HASH2EN		BIT(5)
+#define RCC_MC_AHB3ENCLRR_RNG2EN		BIT(6)
+#define RCC_MC_AHB3ENCLRR_CRC2EN		BIT(7)
+#define RCC_MC_AHB3ENCLRR_HSEMEN		BIT(11)
+#define RCC_MC_AHB3ENCLRR_IPCCEN		BIT(12)
+
+/* RCC_MC_AHB4ENSETR register fields */
+#define RCC_MC_AHB4ENSETR_GPIOAEN		BIT(0)
+#define RCC_MC_AHB4ENSETR_GPIOBEN		BIT(1)
+#define RCC_MC_AHB4ENSETR_GPIOCEN		BIT(2)
+#define RCC_MC_AHB4ENSETR_GPIODEN		BIT(3)
+#define RCC_MC_AHB4ENSETR_GPIOEEN		BIT(4)
+#define RCC_MC_AHB4ENSETR_GPIOFEN		BIT(5)
+#define RCC_MC_AHB4ENSETR_GPIOGEN		BIT(6)
+#define RCC_MC_AHB4ENSETR_GPIOHEN		BIT(7)
+#define RCC_MC_AHB4ENSETR_GPIOIEN		BIT(8)
+#define RCC_MC_AHB4ENSETR_GPIOJEN		BIT(9)
+#define RCC_MC_AHB4ENSETR_GPIOKEN		BIT(10)
+
+/* RCC_MC_AHB4ENCLRR register fields */
+#define RCC_MC_AHB4ENCLRR_GPIOAEN		BIT(0)
+#define RCC_MC_AHB4ENCLRR_GPIOBEN		BIT(1)
+#define RCC_MC_AHB4ENCLRR_GPIOCEN		BIT(2)
+#define RCC_MC_AHB4ENCLRR_GPIODEN		BIT(3)
+#define RCC_MC_AHB4ENCLRR_GPIOEEN		BIT(4)
+#define RCC_MC_AHB4ENCLRR_GPIOFEN		BIT(5)
+#define RCC_MC_AHB4ENCLRR_GPIOGEN		BIT(6)
+#define RCC_MC_AHB4ENCLRR_GPIOHEN		BIT(7)
+#define RCC_MC_AHB4ENCLRR_GPIOIEN		BIT(8)
+#define RCC_MC_AHB4ENCLRR_GPIOJEN		BIT(9)
+#define RCC_MC_AHB4ENCLRR_GPIOKEN		BIT(10)
+
+/* RCC_MC_AXIMENSETR register fields */
+#define RCC_MC_AXIMENSETR_SYSRAMEN		BIT(0)
+
+/* RCC_MC_AXIMENCLRR register fields */
+#define RCC_MC_AXIMENCLRR_SYSRAMEN		BIT(0)
+
+/* RCC_MC_MLAHBENSETR register fields */
+#define RCC_MC_MLAHBENSETR_RETRAMEN		BIT(4)
+
+/* RCC_MC_MLAHBENCLRR register fields */
+#define RCC_MC_MLAHBENCLRR_RETRAMEN		BIT(4)
+
+/* RCC_MP_APB1LPENSETR register fields */
+#define RCC_MP_APB1LPENSETR_TIM2LPEN		BIT(0)
+#define RCC_MP_APB1LPENSETR_TIM3LPEN		BIT(1)
+#define RCC_MP_APB1LPENSETR_TIM4LPEN		BIT(2)
+#define RCC_MP_APB1LPENSETR_TIM5LPEN		BIT(3)
+#define RCC_MP_APB1LPENSETR_TIM6LPEN		BIT(4)
+#define RCC_MP_APB1LPENSETR_TIM7LPEN		BIT(5)
+#define RCC_MP_APB1LPENSETR_TIM12LPEN		BIT(6)
+#define RCC_MP_APB1LPENSETR_TIM13LPEN		BIT(7)
+#define RCC_MP_APB1LPENSETR_TIM14LPEN		BIT(8)
+#define RCC_MP_APB1LPENSETR_LPTIM1LPEN		BIT(9)
+#define RCC_MP_APB1LPENSETR_SPI2LPEN		BIT(11)
+#define RCC_MP_APB1LPENSETR_SPI3LPEN		BIT(12)
+#define RCC_MP_APB1LPENSETR_USART2LPEN		BIT(14)
+#define RCC_MP_APB1LPENSETR_USART3LPEN		BIT(15)
+#define RCC_MP_APB1LPENSETR_UART4LPEN		BIT(16)
+#define RCC_MP_APB1LPENSETR_UART5LPEN		BIT(17)
+#define RCC_MP_APB1LPENSETR_UART7LPEN		BIT(18)
+#define RCC_MP_APB1LPENSETR_UART8LPEN		BIT(19)
+#define RCC_MP_APB1LPENSETR_I2C1LPEN		BIT(21)
+#define RCC_MP_APB1LPENSETR_I2C2LPEN		BIT(22)
+#define RCC_MP_APB1LPENSETR_I2C3LPEN		BIT(23)
+#define RCC_MP_APB1LPENSETR_I2C5LPEN		BIT(24)
+#define RCC_MP_APB1LPENSETR_SPDIFLPEN		BIT(26)
+#define RCC_MP_APB1LPENSETR_CECLPEN		BIT(27)
+#define RCC_MP_APB1LPENSETR_DAC12LPEN		BIT(29)
+#define RCC_MP_APB1LPENSETR_MDIOSLPEN		BIT(31)
+
+/* RCC_MP_APB1LPENCLRR register fields */
+#define RCC_MP_APB1LPENCLRR_TIM2LPEN		BIT(0)
+#define RCC_MP_APB1LPENCLRR_TIM3LPEN		BIT(1)
+#define RCC_MP_APB1LPENCLRR_TIM4LPEN		BIT(2)
+#define RCC_MP_APB1LPENCLRR_TIM5LPEN		BIT(3)
+#define RCC_MP_APB1LPENCLRR_TIM6LPEN		BIT(4)
+#define RCC_MP_APB1LPENCLRR_TIM7LPEN		BIT(5)
+#define RCC_MP_APB1LPENCLRR_TIM12LPEN		BIT(6)
+#define RCC_MP_APB1LPENCLRR_TIM13LPEN		BIT(7)
+#define RCC_MP_APB1LPENCLRR_TIM14LPEN		BIT(8)
+#define RCC_MP_APB1LPENCLRR_LPTIM1LPEN		BIT(9)
+#define RCC_MP_APB1LPENCLRR_SPI2LPEN		BIT(11)
+#define RCC_MP_APB1LPENCLRR_SPI3LPEN		BIT(12)
+#define RCC_MP_APB1LPENCLRR_USART2LPEN		BIT(14)
+#define RCC_MP_APB1LPENCLRR_USART3LPEN		BIT(15)
+#define RCC_MP_APB1LPENCLRR_UART4LPEN		BIT(16)
+#define RCC_MP_APB1LPENCLRR_UART5LPEN		BIT(17)
+#define RCC_MP_APB1LPENCLRR_UART7LPEN		BIT(18)
+#define RCC_MP_APB1LPENCLRR_UART8LPEN		BIT(19)
+#define RCC_MP_APB1LPENCLRR_I2C1LPEN		BIT(21)
+#define RCC_MP_APB1LPENCLRR_I2C2LPEN		BIT(22)
+#define RCC_MP_APB1LPENCLRR_I2C3LPEN		BIT(23)
+#define RCC_MP_APB1LPENCLRR_I2C5LPEN		BIT(24)
+#define RCC_MP_APB1LPENCLRR_SPDIFLPEN		BIT(26)
+#define RCC_MP_APB1LPENCLRR_CECLPEN		BIT(27)
+#define RCC_MP_APB1LPENCLRR_DAC12LPEN		BIT(29)
+#define RCC_MP_APB1LPENCLRR_MDIOSLPEN		BIT(31)
+
+/* RCC_MP_APB2LPENSETR register fields */
+#define RCC_MP_APB2LPENSETR_TIM1LPEN		BIT(0)
+#define RCC_MP_APB2LPENSETR_TIM8LPEN		BIT(1)
+#define RCC_MP_APB2LPENSETR_TIM15LPEN		BIT(2)
+#define RCC_MP_APB2LPENSETR_TIM16LPEN		BIT(3)
+#define RCC_MP_APB2LPENSETR_TIM17LPEN		BIT(4)
+#define RCC_MP_APB2LPENSETR_SPI1LPEN		BIT(8)
+#define RCC_MP_APB2LPENSETR_SPI4LPEN		BIT(9)
+#define RCC_MP_APB2LPENSETR_SPI5LPEN		BIT(10)
+#define RCC_MP_APB2LPENSETR_USART6LPEN		BIT(13)
+#define RCC_MP_APB2LPENSETR_SAI1LPEN		BIT(16)
+#define RCC_MP_APB2LPENSETR_SAI2LPEN		BIT(17)
+#define RCC_MP_APB2LPENSETR_SAI3LPEN		BIT(18)
+#define RCC_MP_APB2LPENSETR_DFSDMLPEN		BIT(20)
+#define RCC_MP_APB2LPENSETR_ADFSDMLPEN		BIT(21)
+#define RCC_MP_APB2LPENSETR_FDCANLPEN		BIT(24)
+
+/* RCC_MP_APB2LPENCLRR register fields */
+#define RCC_MP_APB2LPENCLRR_TIM1LPEN		BIT(0)
+#define RCC_MP_APB2LPENCLRR_TIM8LPEN		BIT(1)
+#define RCC_MP_APB2LPENCLRR_TIM15LPEN		BIT(2)
+#define RCC_MP_APB2LPENCLRR_TIM16LPEN		BIT(3)
+#define RCC_MP_APB2LPENCLRR_TIM17LPEN		BIT(4)
+#define RCC_MP_APB2LPENCLRR_SPI1LPEN		BIT(8)
+#define RCC_MP_APB2LPENCLRR_SPI4LPEN		BIT(9)
+#define RCC_MP_APB2LPENCLRR_SPI5LPEN		BIT(10)
+#define RCC_MP_APB2LPENCLRR_USART6LPEN		BIT(13)
+#define RCC_MP_APB2LPENCLRR_SAI1LPEN		BIT(16)
+#define RCC_MP_APB2LPENCLRR_SAI2LPEN		BIT(17)
+#define RCC_MP_APB2LPENCLRR_SAI3LPEN		BIT(18)
+#define RCC_MP_APB2LPENCLRR_DFSDMLPEN		BIT(20)
+#define RCC_MP_APB2LPENCLRR_ADFSDMLPEN		BIT(21)
+#define RCC_MP_APB2LPENCLRR_FDCANLPEN		BIT(24)
+
+/* RCC_MP_APB3LPENSETR register fields */
+#define RCC_MP_APB3LPENSETR_LPTIM2LPEN		BIT(0)
+#define RCC_MP_APB3LPENSETR_LPTIM3LPEN		BIT(1)
+#define RCC_MP_APB3LPENSETR_LPTIM4LPEN		BIT(2)
+#define RCC_MP_APB3LPENSETR_LPTIM5LPEN		BIT(3)
+#define RCC_MP_APB3LPENSETR_SAI4LPEN		BIT(8)
+#define RCC_MP_APB3LPENSETR_SYSCFGLPEN		BIT(11)
+#define RCC_MP_APB3LPENSETR_VREFLPEN		BIT(13)
+#define RCC_MP_APB3LPENSETR_TMPSENSLPEN		BIT(16)
+#define RCC_MP_APB3LPENSETR_PMBCTRLLPEN		BIT(17)
+
+/* RCC_MP_APB3LPENCLRR register fields */
+#define RCC_MP_APB3LPENCLRR_LPTIM2LPEN		BIT(0)
+#define RCC_MP_APB3LPENCLRR_LPTIM3LPEN		BIT(1)
+#define RCC_MP_APB3LPENCLRR_LPTIM4LPEN		BIT(2)
+#define RCC_MP_APB3LPENCLRR_LPTIM5LPEN		BIT(3)
+#define RCC_MP_APB3LPENCLRR_SAI4LPEN		BIT(8)
+#define RCC_MP_APB3LPENCLRR_SYSCFGLPEN		BIT(11)
+#define RCC_MP_APB3LPENCLRR_VREFLPEN		BIT(13)
+#define RCC_MP_APB3LPENCLRR_TMPSENSLPEN		BIT(16)
+#define RCC_MP_APB3LPENCLRR_PMBCTRLLPEN		BIT(17)
+
+/* RCC_MP_AHB2LPENSETR register fields */
+#define RCC_MP_AHB2LPENSETR_DMA1LPEN		BIT(0)
+#define RCC_MP_AHB2LPENSETR_DMA2LPEN		BIT(1)
+#define RCC_MP_AHB2LPENSETR_DMAMUXLPEN		BIT(2)
+#define RCC_MP_AHB2LPENSETR_ADC12LPEN		BIT(5)
+#define RCC_MP_AHB2LPENSETR_USBOLPEN		BIT(8)
+#define RCC_MP_AHB2LPENSETR_SDMMC3LPEN		BIT(16)
+
+/* RCC_MP_AHB2LPENCLRR register fields */
+#define RCC_MP_AHB2LPENCLRR_DMA1LPEN		BIT(0)
+#define RCC_MP_AHB2LPENCLRR_DMA2LPEN		BIT(1)
+#define RCC_MP_AHB2LPENCLRR_DMAMUXLPEN		BIT(2)
+#define RCC_MP_AHB2LPENCLRR_ADC12LPEN		BIT(5)
+#define RCC_MP_AHB2LPENCLRR_USBOLPEN		BIT(8)
+#define RCC_MP_AHB2LPENCLRR_SDMMC3LPEN		BIT(16)
+
+/* RCC_MP_AHB3LPENSETR register fields */
+#define RCC_MP_AHB3LPENSETR_DCMILPEN		BIT(0)
+#define RCC_MP_AHB3LPENSETR_CRYP2LPEN		BIT(4)
+#define RCC_MP_AHB3LPENSETR_HASH2LPEN		BIT(5)
+#define RCC_MP_AHB3LPENSETR_RNG2LPEN		BIT(6)
+#define RCC_MP_AHB3LPENSETR_CRC2LPEN		BIT(7)
+#define RCC_MP_AHB3LPENSETR_HSEMLPEN		BIT(11)
+#define RCC_MP_AHB3LPENSETR_IPCCLPEN		BIT(12)
+
+/* RCC_MP_AHB3LPENCLRR register fields */
+#define RCC_MP_AHB3LPENCLRR_DCMILPEN		BIT(0)
+#define RCC_MP_AHB3LPENCLRR_CRYP2LPEN		BIT(4)
+#define RCC_MP_AHB3LPENCLRR_HASH2LPEN		BIT(5)
+#define RCC_MP_AHB3LPENCLRR_RNG2LPEN		BIT(6)
+#define RCC_MP_AHB3LPENCLRR_CRC2LPEN		BIT(7)
+#define RCC_MP_AHB3LPENCLRR_HSEMLPEN		BIT(11)
+#define RCC_MP_AHB3LPENCLRR_IPCCLPEN		BIT(12)
+
+/* RCC_MP_AHB4LPENSETR register fields */
+#define RCC_MP_AHB4LPENSETR_GPIOALPEN		BIT(0)
+#define RCC_MP_AHB4LPENSETR_GPIOBLPEN		BIT(1)
+#define RCC_MP_AHB4LPENSETR_GPIOCLPEN		BIT(2)
+#define RCC_MP_AHB4LPENSETR_GPIODLPEN		BIT(3)
+#define RCC_MP_AHB4LPENSETR_GPIOELPEN		BIT(4)
+#define RCC_MP_AHB4LPENSETR_GPIOFLPEN		BIT(5)
+#define RCC_MP_AHB4LPENSETR_GPIOGLPEN		BIT(6)
+#define RCC_MP_AHB4LPENSETR_GPIOHLPEN		BIT(7)
+#define RCC_MP_AHB4LPENSETR_GPIOILPEN		BIT(8)
+#define RCC_MP_AHB4LPENSETR_GPIOJLPEN		BIT(9)
+#define RCC_MP_AHB4LPENSETR_GPIOKLPEN		BIT(10)
+
+/* RCC_MP_AHB4LPENCLRR register fields */
+#define RCC_MP_AHB4LPENCLRR_GPIOALPEN		BIT(0)
+#define RCC_MP_AHB4LPENCLRR_GPIOBLPEN		BIT(1)
+#define RCC_MP_AHB4LPENCLRR_GPIOCLPEN		BIT(2)
+#define RCC_MP_AHB4LPENCLRR_GPIODLPEN		BIT(3)
+#define RCC_MP_AHB4LPENCLRR_GPIOELPEN		BIT(4)
+#define RCC_MP_AHB4LPENCLRR_GPIOFLPEN		BIT(5)
+#define RCC_MP_AHB4LPENCLRR_GPIOGLPEN		BIT(6)
+#define RCC_MP_AHB4LPENCLRR_GPIOHLPEN		BIT(7)
+#define RCC_MP_AHB4LPENCLRR_GPIOILPEN		BIT(8)
+#define RCC_MP_AHB4LPENCLRR_GPIOJLPEN		BIT(9)
+#define RCC_MP_AHB4LPENCLRR_GPIOKLPEN		BIT(10)
+
+/* RCC_MP_AXIMLPENSETR register fields */
+#define RCC_MP_AXIMLPENSETR_SYSRAMLPEN		BIT(0)
+
+/* RCC_MP_AXIMLPENCLRR register fields */
+#define RCC_MP_AXIMLPENCLRR_SYSRAMLPEN		BIT(0)
+
+/* RCC_MP_MLAHBLPENSETR register fields */
+#define RCC_MP_MLAHBLPENSETR_SRAM1LPEN		BIT(0)
+#define RCC_MP_MLAHBLPENSETR_SRAM2LPEN		BIT(1)
+#define RCC_MP_MLAHBLPENSETR_SRAM34LPEN		BIT(2)
+#define RCC_MP_MLAHBLPENSETR_RETRAMLPEN		BIT(4)
+
+/* RCC_MP_MLAHBLPENCLRR register fields */
+#define RCC_MP_MLAHBLPENCLRR_SRAM1LPEN		BIT(0)
+#define RCC_MP_MLAHBLPENCLRR_SRAM2LPEN		BIT(1)
+#define RCC_MP_MLAHBLPENCLRR_SRAM34LPEN		BIT(2)
+#define RCC_MP_MLAHBLPENCLRR_RETRAMLPEN		BIT(4)
+
+/* RCC_MC_APB1LPENSETR register fields */
+#define RCC_MC_APB1LPENSETR_TIM2LPEN		BIT(0)
+#define RCC_MC_APB1LPENSETR_TIM3LPEN		BIT(1)
+#define RCC_MC_APB1LPENSETR_TIM4LPEN		BIT(2)
+#define RCC_MC_APB1LPENSETR_TIM5LPEN		BIT(3)
+#define RCC_MC_APB1LPENSETR_TIM6LPEN		BIT(4)
+#define RCC_MC_APB1LPENSETR_TIM7LPEN		BIT(5)
+#define RCC_MC_APB1LPENSETR_TIM12LPEN		BIT(6)
+#define RCC_MC_APB1LPENSETR_TIM13LPEN		BIT(7)
+#define RCC_MC_APB1LPENSETR_TIM14LPEN		BIT(8)
+#define RCC_MC_APB1LPENSETR_LPTIM1LPEN		BIT(9)
+#define RCC_MC_APB1LPENSETR_SPI2LPEN		BIT(11)
+#define RCC_MC_APB1LPENSETR_SPI3LPEN		BIT(12)
+#define RCC_MC_APB1LPENSETR_USART2LPEN		BIT(14)
+#define RCC_MC_APB1LPENSETR_USART3LPEN		BIT(15)
+#define RCC_MC_APB1LPENSETR_UART4LPEN		BIT(16)
+#define RCC_MC_APB1LPENSETR_UART5LPEN		BIT(17)
+#define RCC_MC_APB1LPENSETR_UART7LPEN		BIT(18)
+#define RCC_MC_APB1LPENSETR_UART8LPEN		BIT(19)
+#define RCC_MC_APB1LPENSETR_I2C1LPEN		BIT(21)
+#define RCC_MC_APB1LPENSETR_I2C2LPEN		BIT(22)
+#define RCC_MC_APB1LPENSETR_I2C3LPEN		BIT(23)
+#define RCC_MC_APB1LPENSETR_I2C5LPEN		BIT(24)
+#define RCC_MC_APB1LPENSETR_SPDIFLPEN		BIT(26)
+#define RCC_MC_APB1LPENSETR_CECLPEN		BIT(27)
+#define RCC_MC_APB1LPENSETR_WWDG1LPEN		BIT(28)
+#define RCC_MC_APB1LPENSETR_DAC12LPEN		BIT(29)
+#define RCC_MC_APB1LPENSETR_MDIOSLPEN		BIT(31)
+
+/* RCC_MC_APB1LPENCLRR register fields */
+#define RCC_MC_APB1LPENCLRR_TIM2LPEN		BIT(0)
+#define RCC_MC_APB1LPENCLRR_TIM3LPEN		BIT(1)
+#define RCC_MC_APB1LPENCLRR_TIM4LPEN		BIT(2)
+#define RCC_MC_APB1LPENCLRR_TIM5LPEN		BIT(3)
+#define RCC_MC_APB1LPENCLRR_TIM6LPEN		BIT(4)
+#define RCC_MC_APB1LPENCLRR_TIM7LPEN		BIT(5)
+#define RCC_MC_APB1LPENCLRR_TIM12LPEN		BIT(6)
+#define RCC_MC_APB1LPENCLRR_TIM13LPEN		BIT(7)
+#define RCC_MC_APB1LPENCLRR_TIM14LPEN		BIT(8)
+#define RCC_MC_APB1LPENCLRR_LPTIM1LPEN		BIT(9)
+#define RCC_MC_APB1LPENCLRR_SPI2LPEN		BIT(11)
+#define RCC_MC_APB1LPENCLRR_SPI3LPEN		BIT(12)
+#define RCC_MC_APB1LPENCLRR_USART2LPEN		BIT(14)
+#define RCC_MC_APB1LPENCLRR_USART3LPEN		BIT(15)
+#define RCC_MC_APB1LPENCLRR_UART4LPEN		BIT(16)
+#define RCC_MC_APB1LPENCLRR_UART5LPEN		BIT(17)
+#define RCC_MC_APB1LPENCLRR_UART7LPEN		BIT(18)
+#define RCC_MC_APB1LPENCLRR_UART8LPEN		BIT(19)
+#define RCC_MC_APB1LPENCLRR_I2C1LPEN		BIT(21)
+#define RCC_MC_APB1LPENCLRR_I2C2LPEN		BIT(22)
+#define RCC_MC_APB1LPENCLRR_I2C3LPEN		BIT(23)
+#define RCC_MC_APB1LPENCLRR_I2C5LPEN		BIT(24)
+#define RCC_MC_APB1LPENCLRR_SPDIFLPEN		BIT(26)
+#define RCC_MC_APB1LPENCLRR_CECLPEN		BIT(27)
+#define RCC_MC_APB1LPENCLRR_WWDG1LPEN		BIT(28)
+#define RCC_MC_APB1LPENCLRR_DAC12LPEN		BIT(29)
+#define RCC_MC_APB1LPENCLRR_MDIOSLPEN		BIT(31)
+
+/* RCC_MC_APB2LPENSETR register fields */
+#define RCC_MC_APB2LPENSETR_TIM1LPEN		BIT(0)
+#define RCC_MC_APB2LPENSETR_TIM8LPEN		BIT(1)
+#define RCC_MC_APB2LPENSETR_TIM15LPEN		BIT(2)
+#define RCC_MC_APB2LPENSETR_TIM16LPEN		BIT(3)
+#define RCC_MC_APB2LPENSETR_TIM17LPEN		BIT(4)
+#define RCC_MC_APB2LPENSETR_SPI1LPEN		BIT(8)
+#define RCC_MC_APB2LPENSETR_SPI4LPEN		BIT(9)
+#define RCC_MC_APB2LPENSETR_SPI5LPEN		BIT(10)
+#define RCC_MC_APB2LPENSETR_USART6LPEN		BIT(13)
+#define RCC_MC_APB2LPENSETR_SAI1LPEN		BIT(16)
+#define RCC_MC_APB2LPENSETR_SAI2LPEN		BIT(17)
+#define RCC_MC_APB2LPENSETR_SAI3LPEN		BIT(18)
+#define RCC_MC_APB2LPENSETR_DFSDMLPEN		BIT(20)
+#define RCC_MC_APB2LPENSETR_ADFSDMLPEN		BIT(21)
+#define RCC_MC_APB2LPENSETR_FDCANLPEN		BIT(24)
+
+/* RCC_MC_APB2LPENCLRR register fields */
+#define RCC_MC_APB2LPENCLRR_TIM1LPEN		BIT(0)
+#define RCC_MC_APB2LPENCLRR_TIM8LPEN		BIT(1)
+#define RCC_MC_APB2LPENCLRR_TIM15LPEN		BIT(2)
+#define RCC_MC_APB2LPENCLRR_TIM16LPEN		BIT(3)
+#define RCC_MC_APB2LPENCLRR_TIM17LPEN		BIT(4)
+#define RCC_MC_APB2LPENCLRR_SPI1LPEN		BIT(8)
+#define RCC_MC_APB2LPENCLRR_SPI4LPEN		BIT(9)
+#define RCC_MC_APB2LPENCLRR_SPI5LPEN		BIT(10)
+#define RCC_MC_APB2LPENCLRR_USART6LPEN		BIT(13)
+#define RCC_MC_APB2LPENCLRR_SAI1LPEN		BIT(16)
+#define RCC_MC_APB2LPENCLRR_SAI2LPEN		BIT(17)
+#define RCC_MC_APB2LPENCLRR_SAI3LPEN		BIT(18)
+#define RCC_MC_APB2LPENCLRR_DFSDMLPEN		BIT(20)
+#define RCC_MC_APB2LPENCLRR_ADFSDMLPEN		BIT(21)
+#define RCC_MC_APB2LPENCLRR_FDCANLPEN		BIT(24)
+
+/* RCC_MC_APB3LPENSETR register fields */
+#define RCC_MC_APB3LPENSETR_LPTIM2LPEN		BIT(0)
+#define RCC_MC_APB3LPENSETR_LPTIM3LPEN		BIT(1)
+#define RCC_MC_APB3LPENSETR_LPTIM4LPEN		BIT(2)
+#define RCC_MC_APB3LPENSETR_LPTIM5LPEN		BIT(3)
+#define RCC_MC_APB3LPENSETR_SAI4LPEN		BIT(8)
+#define RCC_MC_APB3LPENSETR_SYSCFGLPEN		BIT(11)
+#define RCC_MC_APB3LPENSETR_VREFLPEN		BIT(13)
+#define RCC_MC_APB3LPENSETR_TMPSENSLPEN		BIT(16)
+#define RCC_MC_APB3LPENSETR_PMBCTRLLPEN		BIT(17)
+
+/* RCC_MC_APB3LPENCLRR register fields */
+#define RCC_MC_APB3LPENCLRR_LPTIM2LPEN		BIT(0)
+#define RCC_MC_APB3LPENCLRR_LPTIM3LPEN		BIT(1)
+#define RCC_MC_APB3LPENCLRR_LPTIM4LPEN		BIT(2)
+#define RCC_MC_APB3LPENCLRR_LPTIM5LPEN		BIT(3)
+#define RCC_MC_APB3LPENCLRR_SAI4LPEN		BIT(8)
+#define RCC_MC_APB3LPENCLRR_SYSCFGLPEN		BIT(11)
+#define RCC_MC_APB3LPENCLRR_VREFLPEN		BIT(13)
+#define RCC_MC_APB3LPENCLRR_TMPSENSLPEN		BIT(16)
+#define RCC_MC_APB3LPENCLRR_PMBCTRLLPEN		BIT(17)
+
+/* RCC_MC_AHB2LPENSETR register fields */
+#define RCC_MC_AHB2LPENSETR_DMA1LPEN		BIT(0)
+#define RCC_MC_AHB2LPENSETR_DMA2LPEN		BIT(1)
+#define RCC_MC_AHB2LPENSETR_DMAMUXLPEN		BIT(2)
+#define RCC_MC_AHB2LPENSETR_ADC12LPEN		BIT(5)
+#define RCC_MC_AHB2LPENSETR_USBOLPEN		BIT(8)
+#define RCC_MC_AHB2LPENSETR_SDMMC3LPEN		BIT(16)
+
+/* RCC_MC_AHB2LPENCLRR register fields */
+#define RCC_MC_AHB2LPENCLRR_DMA1LPEN		BIT(0)
+#define RCC_MC_AHB2LPENCLRR_DMA2LPEN		BIT(1)
+#define RCC_MC_AHB2LPENCLRR_DMAMUXLPEN		BIT(2)
+#define RCC_MC_AHB2LPENCLRR_ADC12LPEN		BIT(5)
+#define RCC_MC_AHB2LPENCLRR_USBOLPEN		BIT(8)
+#define RCC_MC_AHB2LPENCLRR_SDMMC3LPEN		BIT(16)
+
+/* RCC_MC_AHB3LPENSETR register fields */
+#define RCC_MC_AHB3LPENSETR_DCMILPEN		BIT(0)
+#define RCC_MC_AHB3LPENSETR_CRYP2LPEN		BIT(4)
+#define RCC_MC_AHB3LPENSETR_HASH2LPEN		BIT(5)
+#define RCC_MC_AHB3LPENSETR_RNG2LPEN		BIT(6)
+#define RCC_MC_AHB3LPENSETR_CRC2LPEN		BIT(7)
+#define RCC_MC_AHB3LPENSETR_HSEMLPEN		BIT(11)
+#define RCC_MC_AHB3LPENSETR_IPCCLPEN		BIT(12)
+
+/* RCC_MC_AHB3LPENCLRR register fields */
+#define RCC_MC_AHB3LPENCLRR_DCMILPEN		BIT(0)
+#define RCC_MC_AHB3LPENCLRR_CRYP2LPEN		BIT(4)
+#define RCC_MC_AHB3LPENCLRR_HASH2LPEN		BIT(5)
+#define RCC_MC_AHB3LPENCLRR_RNG2LPEN		BIT(6)
+#define RCC_MC_AHB3LPENCLRR_CRC2LPEN		BIT(7)
+#define RCC_MC_AHB3LPENCLRR_HSEMLPEN		BIT(11)
+#define RCC_MC_AHB3LPENCLRR_IPCCLPEN		BIT(12)
+
+/* RCC_MC_AHB4LPENSETR register fields */
+#define RCC_MC_AHB4LPENSETR_GPIOALPEN		BIT(0)
+#define RCC_MC_AHB4LPENSETR_GPIOBLPEN		BIT(1)
+#define RCC_MC_AHB4LPENSETR_GPIOCLPEN		BIT(2)
+#define RCC_MC_AHB4LPENSETR_GPIODLPEN		BIT(3)
+#define RCC_MC_AHB4LPENSETR_GPIOELPEN		BIT(4)
+#define RCC_MC_AHB4LPENSETR_GPIOFLPEN		BIT(5)
+#define RCC_MC_AHB4LPENSETR_GPIOGLPEN		BIT(6)
+#define RCC_MC_AHB4LPENSETR_GPIOHLPEN		BIT(7)
+#define RCC_MC_AHB4LPENSETR_GPIOILPEN		BIT(8)
+#define RCC_MC_AHB4LPENSETR_GPIOJLPEN		BIT(9)
+#define RCC_MC_AHB4LPENSETR_GPIOKLPEN		BIT(10)
+
+/* RCC_MC_AHB4LPENCLRR register fields */
+#define RCC_MC_AHB4LPENCLRR_GPIOALPEN		BIT(0)
+#define RCC_MC_AHB4LPENCLRR_GPIOBLPEN		BIT(1)
+#define RCC_MC_AHB4LPENCLRR_GPIOCLPEN		BIT(2)
+#define RCC_MC_AHB4LPENCLRR_GPIODLPEN		BIT(3)
+#define RCC_MC_AHB4LPENCLRR_GPIOELPEN		BIT(4)
+#define RCC_MC_AHB4LPENCLRR_GPIOFLPEN		BIT(5)
+#define RCC_MC_AHB4LPENCLRR_GPIOGLPEN		BIT(6)
+#define RCC_MC_AHB4LPENCLRR_GPIOHLPEN		BIT(7)
+#define RCC_MC_AHB4LPENCLRR_GPIOILPEN		BIT(8)
+#define RCC_MC_AHB4LPENCLRR_GPIOJLPEN		BIT(9)
+#define RCC_MC_AHB4LPENCLRR_GPIOKLPEN		BIT(10)
+
+/* RCC_MC_AXIMLPENSETR register fields */
+#define RCC_MC_AXIMLPENSETR_SYSRAMLPEN		BIT(0)
+
+/* RCC_MC_AXIMLPENCLRR register fields */
+#define RCC_MC_AXIMLPENCLRR_SYSRAMLPEN		BIT(0)
+
+/* RCC_MC_MLAHBLPENSETR register fields */
+#define RCC_MC_MLAHBLPENSETR_SRAM1LPEN		BIT(0)
+#define RCC_MC_MLAHBLPENSETR_SRAM2LPEN		BIT(1)
+#define RCC_MC_MLAHBLPENSETR_SRAM34LPEN		BIT(2)
+#define RCC_MC_MLAHBLPENSETR_RETRAMLPEN		BIT(4)
+
+/* RCC_MC_MLAHBLPENCLRR register fields */
+#define RCC_MC_MLAHBLPENCLRR_SRAM1LPEN		BIT(0)
+#define RCC_MC_MLAHBLPENCLRR_SRAM2LPEN		BIT(1)
+#define RCC_MC_MLAHBLPENCLRR_SRAM34LPEN		BIT(2)
+#define RCC_MC_MLAHBLPENCLRR_RETRAMLPEN		BIT(4)
+
+/* RCC_MC_RSTSCLRR register fields */
+#define RCC_MC_RSTSCLRR_PORRSTF			BIT(0)
+#define RCC_MC_RSTSCLRR_BORRSTF			BIT(1)
+#define RCC_MC_RSTSCLRR_PADRSTF			BIT(2)
+#define RCC_MC_RSTSCLRR_HCSSRSTF		BIT(3)
+#define RCC_MC_RSTSCLRR_VCORERSTF		BIT(4)
+#define RCC_MC_RSTSCLRR_MCURSTF			BIT(5)
+#define RCC_MC_RSTSCLRR_MPSYSRSTF		BIT(6)
+#define RCC_MC_RSTSCLRR_MCSYSRSTF		BIT(7)
+#define RCC_MC_RSTSCLRR_IWDG1RSTF		BIT(8)
+#define RCC_MC_RSTSCLRR_IWDG2RSTF		BIT(9)
+#define RCC_MC_RSTSCLRR_WWDG1RSTF		BIT(10)
+
+/* RCC_MC_CIER register fields */
+#define RCC_MC_CIER_LSIRDYIE			BIT(0)
+#define RCC_MC_CIER_LSERDYIE			BIT(1)
+#define RCC_MC_CIER_HSIRDYIE			BIT(2)
+#define RCC_MC_CIER_HSERDYIE			BIT(3)
+#define RCC_MC_CIER_CSIRDYIE			BIT(4)
+#define RCC_MC_CIER_PLL1DYIE			BIT(8)
+#define RCC_MC_CIER_PLL2DYIE			BIT(9)
+#define RCC_MC_CIER_PLL3DYIE			BIT(10)
+#define RCC_MC_CIER_PLL4DYIE			BIT(11)
+#define RCC_MC_CIER_LSECSSIE			BIT(16)
+#define RCC_MC_CIER_WKUPIE			BIT(20)
+
+/* RCC_MC_CIFR register fields */
+#define RCC_MC_CIFR_LSIRDYF			BIT(0)
+#define RCC_MC_CIFR_LSERDYF			BIT(1)
+#define RCC_MC_CIFR_HSIRDYF			BIT(2)
+#define RCC_MC_CIFR_HSERDYF			BIT(3)
+#define RCC_MC_CIFR_CSIRDYF			BIT(4)
+#define RCC_MC_CIFR_PLL1DYF			BIT(8)
+#define RCC_MC_CIFR_PLL2DYF			BIT(9)
+#define RCC_MC_CIFR_PLL3DYF			BIT(10)
+#define RCC_MC_CIFR_PLL4DYF			BIT(11)
+#define RCC_MC_CIFR_LSECSSF			BIT(16)
+#define RCC_MC_CIFR_WKUPF			BIT(20)
+
+/* RCC_VERR register fields */
+#define RCC_VERR_MINREV_MASK			GENMASK(3, 0)
+#define RCC_VERR_MINREV_SHIFT			0
+#define RCC_VERR_MAJREV_MASK			GENMASK(7, 4)
+#define RCC_VERR_MAJREV_SHIFT			4
+
+/* Used for RCC_OCENSETR and RCC_OCENCLRR registers */
+#define RCC_OCENR_HSION				BIT(0)
+#define RCC_OCENR_HSIKERON			BIT(1)
+#define RCC_OCENR_CSION				BIT(4)
+#define RCC_OCENR_CSIKERON			BIT(5)
+#define RCC_OCENR_DIGBYP			BIT(7)
+#define RCC_OCENR_HSEON				BIT(8)
+#define RCC_OCENR_HSEKERON			BIT(9)
+#define RCC_OCENR_HSEBYP			BIT(10)
+#define RCC_OCENR_HSECSSON			BIT(11)
+
+/* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */
+#define RCC_MP_ENCLRR_OFFSET			U(4)
+
+/* Offset between RCC_xxxRSTSETR and RCC_xxxRSTCLRR registers */
+#define RCC_RSTCLRR_OFFSET			U(4)
+
+/* Used for most of DIVR register: max div for RTC */
+#define RCC_DIVR_DIV_MASK			GENMASK(5, 0)
+#define RCC_DIVR_DIVRDY				BIT(31)
+
+/* Masks for specific DIVR registers */
+#define RCC_APBXDIV_MASK			GENMASK(2, 0)
+#define RCC_MPUDIV_MASK				GENMASK(2, 0)
+#define RCC_AXIDIV_MASK				GENMASK(2, 0)
+#define RCC_MCUDIV_MASK				GENMASK(3, 0)
+
+/* Used for most of RCC_<x>SELR registers */
+#define RCC_SELR_SRC_MASK			GENMASK(2, 0)
+#define RCC_SELR_REFCLK_SRC_MASK		GENMASK(1, 0)
+#define RCC_SELR_SRCRDY				BIT(31)
+
+/* Used for all RCC_PLL<n>CR registers */
+#define RCC_PLLNCR_PLLON			BIT(0)
+#define RCC_PLLNCR_PLLRDY			BIT(1)
+#define RCC_PLLNCR_SSCG_CTRL			BIT(2)
+#define RCC_PLLNCR_DIVPEN			BIT(4)
+#define RCC_PLLNCR_DIVQEN			BIT(5)
+#define RCC_PLLNCR_DIVREN			BIT(6)
+#define RCC_PLLNCR_DIVEN_SHIFT			4
+
+/* Used for all RCC_PLL<n>CFGR1 registers */
+#define RCC_PLLNCFGR1_DIVM_MASK			GENMASK(21, 16)
+#define RCC_PLLNCFGR1_DIVM_SHIFT		16
+#define RCC_PLLNCFGR1_DIVN_MASK			GENMASK(8, 0)
+#define RCC_PLLNCFGR1_DIVN_SHIFT		0
+
+/* Only for PLL3 and PLL4 */
+#define RCC_PLLNCFGR1_IFRGE_MASK		GENMASK(25, 24)
+#define RCC_PLLNCFGR1_IFRGE_SHIFT		24
+
+/* Used for all RCC_PLL<n>CFGR2 registers */
+#define RCC_PLLNCFGR2_DIVX_MASK			GENMASK(6, 0)
+#define RCC_PLLNCFGR2_DIVP_MASK			GENMASK(6, 0)
+#define RCC_PLLNCFGR2_DIVP_SHIFT		0
+#define RCC_PLLNCFGR2_DIVQ_MASK			GENMASK(14, 8)
+#define RCC_PLLNCFGR2_DIVQ_SHIFT		8
+#define RCC_PLLNCFGR2_DIVR_MASK			GENMASK(22, 16)
+#define RCC_PLLNCFGR2_DIVR_SHIFT		16
+
+/* Used for all RCC_PLL<n>FRACR registers */
+#define RCC_PLLNFRACR_FRACV_SHIFT		3
+#define RCC_PLLNFRACR_FRACV_MASK		GENMASK(15, 3)
+#define RCC_PLLNFRACR_FRACLE			BIT(16)
+
+/* Used for all RCC_PLL<n>CSGR registers */
+#define RCC_PLLNCSGR_INC_STEP_SHIFT		16
+#define RCC_PLLNCSGR_INC_STEP_MASK		GENMASK(30, 16)
+#define RCC_PLLNCSGR_MOD_PER_SHIFT		0
+#define RCC_PLLNCSGR_MOD_PER_MASK		GENMASK(12, 0)
+#define RCC_PLLNCSGR_SSCG_MODE_SHIFT		15
+#define RCC_PLLNCSGR_SSCG_MODE_MASK		BIT(15)
+
+/* Used for TIMER Prescaler */
+#define RCC_TIMGXPRER_TIMGXPRE			BIT(0)
+
+/* Used for RCC_MCO related operations */
+#define RCC_MCOCFG_MCOON			BIT(12)
+#define RCC_MCOCFG_MCODIV_MASK			GENMASK(7, 4)
+#define RCC_MCOCFG_MCODIV_SHIFT			4
+#define RCC_MCOCFG_MCOSRC_MASK			GENMASK(2, 0)
+
 #endif /* STM32MP1_RCC_H */
diff --git a/include/drivers/st/stm32mp_clkfunc.h b/include/drivers/st/stm32mp_clkfunc.h
index c7e0b6e..c3329cc 100644
--- a/include/drivers/st/stm32mp_clkfunc.h
+++ b/include/drivers/st/stm32mp_clkfunc.h
@@ -19,7 +19,6 @@
 				     const char *prop_name,
 				     uint32_t dflt_value);
 
-int fdt_get_rcc_node(void *fdt);
 int fdt_rcc_read_uint32_array(const char *prop_name, uint32_t count,
 			      uint32_t *array);
 int fdt_rcc_subnode_offset(const char *name);
diff --git a/include/dt-bindings/soc/stm32mp15-tzc400.h b/include/dt-bindings/soc/stm32mp15-tzc400.h
new file mode 100644
index 0000000..54cd902
--- /dev/null
+++ b/include/dt-bindings/soc/stm32mp15-tzc400.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (C) 2021, STMicroelectronics - All Rights Reserved
+ */
+
+#ifndef _DT_BINDINGS_STM32MP15_TZC400_H
+#define _DT_BINDINGS_STM32MP15_TZC400_H
+
+#include <drivers/arm/tzc_common.h>
+
+#define STM32MP1_TZC_A7_ID		U(0)
+#define STM32MP1_TZC_M4_ID		U(1)
+#define STM32MP1_TZC_LCD_ID		U(3)
+#define STM32MP1_TZC_GPU_ID		U(4)
+#define STM32MP1_TZC_MDMA_ID		U(5)
+#define STM32MP1_TZC_DMA_ID		U(6)
+#define STM32MP1_TZC_USB_HOST_ID	U(7)
+#define STM32MP1_TZC_USB_OTG_ID		U(8)
+#define STM32MP1_TZC_SDMMC_ID		U(9)
+#define STM32MP1_TZC_ETH_ID		U(10)
+#define STM32MP1_TZC_DAP_ID		U(15)
+
+#define TZC_REGION_NSEC_ALL_ACCESS_RDWR \
+	(TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_M4_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID))
+
+#endif /* _DT_BINDINGS_STM32MP15_TZC400_H */
diff --git a/include/export/common/ep_info_exp.h b/include/export/common/ep_info_exp.h
index 9d2969f..a5bd10a 100644
--- a/include/export/common/ep_info_exp.h
+++ b/include/export/common/ep_info_exp.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -24,11 +24,23 @@
 #define ENTRY_POINT_INFO_ARGS_OFFSET	U(0x14)
 #endif
 
-/* Security state of the image. */
-#define EP_SECURITY_MASK	UL(0x1)
+/*
+ * Security state of the image. Bit 0 and
+ * bit 5 are used to determine the security
+ * state of the image as follows:
+ *
+ * ---------------------------------
+ *  Bit 5 | Bit 0 | Security state
+ * ---------------------------------
+ *   0        0      EP_SECURE
+ *   0        1      EP_NON_SECURE
+ *   1        1      EP_REALM
+ */
+#define EP_SECURITY_MASK	UL(0x21)
 #define EP_SECURITY_SHIFT	UL(0)
 #define EP_SECURE		UL(0x0)
 #define EP_NON_SECURE		UL(0x1)
+#define EP_REALM		UL(0x21)
 
 /* Endianness of the image. */
 #define EP_EE_MASK		U(0x2)
diff --git a/include/export/common/tbbr/tbbr_img_def_exp.h b/include/export/common/tbbr/tbbr_img_def_exp.h
index 18f0125..98544c0 100644
--- a/include/export/common/tbbr/tbbr_img_def_exp.h
+++ b/include/export/common/tbbr/tbbr_img_def_exp.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -91,7 +91,20 @@
 /* FW_CONFIG */
 #define FW_CONFIG_ID			U(31)
 
+/*
+ * Primary FWU metadata image ID
+ */
+#define FWU_METADATA_IMAGE_ID		U(32)
+
+/*
+ * Backup FWU metadata image ID
+ */
+#define BKUP_FWU_METADATA_IMAGE_ID	U(33)
+
+/* Realm Monitor Manager (RMM) */
+#define RMM_IMAGE_ID			U(34)
+
 /* Max Images */
-#define MAX_IMAGE_IDS			U(32)
+#define MAX_IMAGE_IDS			U(35)
 
 #endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_TBBR_TBBR_IMG_DEF_EXP_H */
diff --git a/include/lib/cpus/aarch64/cortex_a710.h b/include/lib/cpus/aarch64/cortex_a710.h
index 44c540c..d2bc146 100644
--- a/include/lib/cpus/aarch64/cortex_a710.h
+++ b/include/lib/cpus/aarch64/cortex_a710.h
@@ -13,6 +13,7 @@
  * CPU Extended Control register specific definitions
  ******************************************************************************/
 #define CORTEX_A710_CPUECTLR_EL1				S3_0_C15_C1_4
+#define CORTEX_A710_CPUECTLR_EL1_PFSTIDIS_BIT			(ULL(1) << 8)
 
 /*******************************************************************************
  * CPU Power Control register specific definitions
@@ -20,4 +21,24 @@
 #define CORTEX_A710_CPUPWRCTLR_EL1				S3_0_C15_C2_7
 #define CORTEX_A710_CPUPWRCTLR_EL1_CORE_PWRDN_BIT		U(1)
 
+/*******************************************************************************
+ * CPU Auxiliary Control register specific definitions.
+ ******************************************************************************/
+#define CORTEX_A710_CPUACTLR_EL1 				S3_0_C15_C1_0
+#define CORTEX_A710_CPUACTLR_EL1_BIT_46				(ULL(1) << 46)
+
+/*******************************************************************************
+ * CPU Auxiliary Control register specific definitions.
+ ******************************************************************************/
+#define CORTEX_A710_CPUACTLR5_EL1				S3_0_C15_C8_0
+#define CORTEX_A710_CPUACTLR5_EL1_BIT_13			(ULL(1) << 13)
+
+/*******************************************************************************
+ * CPU Auxiliary Control register specific definitions.
+ ******************************************************************************/
+#define CORTEX_A710_CPUECTLR2_EL1				S3_0_C15_C1_5
+#define CORTEX_A710_CPUECTLR2_EL1_PF_MODE_CNSRV			ULL(9)
+#define CPUECTLR2_EL1_PF_MODE_LSB				U(11)
+#define CPUECTLR2_EL1_PF_MODE_WIDTH				U(4)
+
 #endif /* CORTEX_A710_H */
diff --git a/include/lib/cpus/aarch64/cortex_a78.h b/include/lib/cpus/aarch64/cortex_a78.h
index 4bc49f3..42b0833 100644
--- a/include/lib/cpus/aarch64/cortex_a78.h
+++ b/include/lib/cpus/aarch64/cortex_a78.h
@@ -16,6 +16,9 @@
  ******************************************************************************/
 #define CORTEX_A78_CPUECTLR_EL1				S3_0_C15_C1_4
 #define CORTEX_A78_CPUECTLR_EL1_BIT_8			(ULL(1) << 8)
+#define CORTEX_A78_CPUECTLR_EL1_PF_MODE_CNSRV		ULL(3)
+#define CPUECTLR_EL1_PF_MODE_LSB				U(6)
+#define CPUECTLR_EL1_PF_MODE_WIDTH				U(2)
 
 /*******************************************************************************
  * CPU Power Control register specific definitions
diff --git a/include/lib/cpus/aarch64/cortex_a78_ae.h b/include/lib/cpus/aarch64/cortex_a78_ae.h
index 24ae7ee..0c8adcf 100644
--- a/include/lib/cpus/aarch64/cortex_a78_ae.h
+++ b/include/lib/cpus/aarch64/cortex_a78_ae.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,4 +12,10 @@
 
 #define CORTEX_A78_AE_MIDR U(0x410FD420)
 
+/*******************************************************************************
+ * CPU Extended Control register specific definitions.
+ ******************************************************************************/
+#define CORTEX_A78_AE_CPUECTLR_EL1			CORTEX_A78_CPUECTLR_EL1
+#define CORTEX_A78_AE_CPUECTLR_EL1_BIT_8		CORTEX_A78_CPUECTLR_EL1_BIT_8
+
 #endif /* CORTEX_A78_AE_H */
diff --git a/include/lib/cpus/aarch64/cortex_demeter.h b/include/lib/cpus/aarch64/cortex_demeter.h
new file mode 100644
index 0000000..9dd0987
--- /dev/null
+++ b/include/lib/cpus/aarch64/cortex_demeter.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CORTEX_DEMETER_H
+#define CORTEX_DEMETER_H
+
+#define CORTEX_DEMETER_MIDR				U(0x410FD4F0)
+
+/*******************************************************************************
+ * CPU Extended Control register specific definitions
+ ******************************************************************************/
+#define CORTEX_DEMETER_CPUECTLR_EL1			S3_0_C15_C1_4
+
+/*******************************************************************************
+ * CPU Power Control register specific definitions
+ ******************************************************************************/
+#define CORTEX_DEMETER_CPUPWRCTLR_EL1			S3_0_C15_C2_7
+#define CORTEX_DEMETER_CPUPWRCTLR_EL1_CORE_PWRDN_BIT	U(1)
+
+#endif /* CORTEX_DEMETER_H */
diff --git a/include/lib/cpus/aarch64/cortex_hayes.h b/include/lib/cpus/aarch64/cortex_hayes.h
new file mode 100644
index 0000000..82022e9
--- /dev/null
+++ b/include/lib/cpus/aarch64/cortex_hayes.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CORTEX_HAYES_H
+#define CORTEX_HAYES_H
+
+#define CORTEX_HAYES_MIDR					U(0x410FD800)
+
+/*******************************************************************************
+ * CPU Extended Control register specific definitions
+ ******************************************************************************/
+#define CORTEX_HAYES_CPUECTLR_EL1				S3_0_C15_C1_4
+
+/*******************************************************************************
+ * CPU Power Control register specific definitions
+ ******************************************************************************/
+#define CORTEX_HAYES_CPUPWRCTLR_EL1				S3_0_C15_C2_7
+#define CORTEX_HAYES_CPUPWRCTLR_EL1_CORE_PWRDN_BIT		U(1)
+
+#endif /* CORTEX_HAYES_H */
diff --git a/include/lib/cpus/aarch64/neoverse_n2.h b/include/lib/cpus/aarch64/neoverse_n2.h
index 7cbd8c1..f414cb5 100644
--- a/include/lib/cpus/aarch64/neoverse_n2.h
+++ b/include/lib/cpus/aarch64/neoverse_n2.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,24 +8,45 @@
 #define NEOVERSE_N2_H
 
 /* Neoverse N2 ID register for revision r0p0 */
-#define NEOVERSE_N2_MIDR			U(0x410FD490)
+#define NEOVERSE_N2_MIDR				U(0x410FD490)
 
 /*******************************************************************************
  * CPU Power control register
  ******************************************************************************/
-#define NEOVERSE_N2_CPUPWRCTLR_EL1		S3_0_C15_C2_7
-#define NEOVERSE_N2_CORE_PWRDN_EN_BIT		(ULL(1) << 0)
+#define NEOVERSE_N2_CPUPWRCTLR_EL1			S3_0_C15_C2_7
+#define NEOVERSE_N2_CORE_PWRDN_EN_BIT			(ULL(1) << 0)
 
 /*******************************************************************************
  * CPU Extended Control register specific definitions.
  ******************************************************************************/
-#define NEOVERSE_N2_CPUECTLR_EL1		S3_0_C15_C1_4
-#define NEOVERSE_N2_CPUECTLR_EL1_EXTLLC_BIT	(ULL(1) << 0)
+#define NEOVERSE_N2_CPUECTLR_EL1			S3_0_C15_C1_4
+#define NEOVERSE_N2_CPUECTLR_EL1_EXTLLC_BIT		(ULL(1) << 0)
+#define NEOVERSE_N2_CPUECTLR_EL1_PFSTIDIS_BIT		(ULL(1) << 8)
 
 /*******************************************************************************
  * CPU Auxiliary Control register specific definitions.
  ******************************************************************************/
-#define NEOVERSE_N2_CPUACTLR2_EL1		S3_0_C15_C1_1
-#define NEOVERSE_N2_CPUACTLR2_EL1_BIT_2		(ULL(1) << 2)
+#define NEOVERSE_N2_CPUACTLR_EL1			S3_0_C15_C1_0
+#define NEOVERSE_N2_CPUACTLR_EL1_BIT_46			(ULL(1) << 46)
+
+/*******************************************************************************
+ * CPU Auxiliary Control register 2 specific definitions.
+ ******************************************************************************/
+#define NEOVERSE_N2_CPUACTLR2_EL1			S3_0_C15_C1_1
+#define NEOVERSE_N2_CPUACTLR2_EL1_BIT_2			(ULL(1) << 2)
+
+/*******************************************************************************
+ * CPU Auxiliary Control register 5 specific definitions.
+ ******************************************************************************/
+#define NEOVERSE_N2_CPUACTLR5_EL1			S3_0_C15_C8_0
+#define NEOVERSE_N2_CPUACTLR5_EL1_BIT_44		(ULL(1) << 44)
+
+/*******************************************************************************
+ * CPU Auxiliary Control register specific definitions.
+ ******************************************************************************/
+#define NEOVERSE_N2_CPUECTLR2_EL1			S3_0_C15_C1_5
+#define NEOVERSE_N2_CPUECTLR2_EL1_PF_MODE_CNSRV		ULL(9)
+#define CPUECTLR2_EL1_PF_MODE_LSB			U(11)
+#define CPUECTLR2_EL1_PF_MODE_WIDTH			U(4)
 
 #endif /* NEOVERSE_N2_H */
diff --git a/include/lib/cpus/aarch64/neoverse_v1.h b/include/lib/cpus/aarch64/neoverse_v1.h
index 650eb4d..e43c907 100644
--- a/include/lib/cpus/aarch64/neoverse_v1.h
+++ b/include/lib/cpus/aarch64/neoverse_v1.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ * Copyright (c) 2019-2021, ARM Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,6 +13,11 @@
  * CPU Extended Control register specific definitions.
  ******************************************************************************/
 #define NEOVERSE_V1_CPUECTLR_EL1				S3_0_C15_C1_4
+#define NEOVERSE_V1_CPUECTLR_EL1_BIT_8				(ULL(1) << 8)
+#define NEOVERSE_V1_CPUECTLR_EL1_BIT_53				(ULL(1) << 53)
+#define NEOVERSE_V1_CPUECTLR_EL1_PF_MODE_CNSRV			ULL(3)
+#define CPUECTLR_EL1_PF_MODE_LSB				U(6)
+#define CPUECTLR_EL1_PF_MODE_WIDTH				U(2)
 
 /*******************************************************************************
  * CPU Power Control register specific definitions
@@ -20,4 +25,11 @@
 #define NEOVERSE_V1_CPUPWRCTLR_EL1				S3_0_C15_C2_7
 #define NEOVERSE_V1_CPUPWRCTLR_EL1_CORE_PWRDN_BIT		U(1)
 
+/*******************************************************************************
+ * CPU Auxiliary Control register specific definitions.
+ ******************************************************************************/
+#define NEOVERSE_V1_ACTLR2_EL1					S3_0_C15_C1_1
+#define NEOVERSE_V1_ACTLR2_EL1_BIT_2				(ULL(1) << 2)
+#define NEOVERSE_V1_ACTLR2_EL1_BIT_28				(ULL(1) << 28)
+
 #endif /* NEOVERSE_V1_H */
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index d449a65..698e208 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -228,6 +228,10 @@
 
 // Starting with Armv8.5
 #define CTX_SCXTNUM_EL2		U(0x1e0)
+
+// Register for FEAT_HCX
+#define CTX_HCRX_EL2            U(0x1e8)
+
 /* Align to the next 16 byte boundary */
 #define CTX_EL2_SYSREGS_END	U(0x1f0)
 
@@ -401,13 +405,12 @@
 					 = (uint64_t) (val))
 
 /*
- * Top-level context structure which is used by EL3 firmware to
- * preserve the state of a core at EL1 in one of the two security
- * states and save enough EL3 meta data to be able to return to that
- * EL and security state. The context management library will be used
- * to ensure that SP_EL3 always points to an instance of this
- * structure at exception entry and exit. Each instance will
- * correspond to either the secure or the non-secure state.
+ * Top-level context structure which is used by EL3 firmware to preserve
+ * the state of a core at the next lower EL in a given security state and
+ * save enough EL3 meta data to be able to return to that EL and security
+ * state. The context management library will be used to ensure that
+ * SP_EL3 always points to an instance of this structure at exception
+ * entry and exit.
  */
 typedef struct cpu_context {
 	gp_regs_t gpregs_ctx;
diff --git a/include/lib/el3_runtime/cpu_data.h b/include/lib/el3_runtime/cpu_data.h
index 5426135..2c7b619 100644
--- a/include/lib/el3_runtime/cpu_data.h
+++ b/include/lib/el3_runtime/cpu_data.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,16 +19,25 @@
 /* 8-bytes aligned size of psci_cpu_data structure */
 #define PSCI_CPU_DATA_SIZE_ALIGNED	((PSCI_CPU_DATA_SIZE + 7) & ~7)
 
+#if ENABLE_RME
+/* Size of cpu_context array */
+#define CPU_DATA_CONTEXT_NUM		3
 /* Offset of cpu_ops_ptr, size 8 bytes */
+#define CPU_DATA_CPU_OPS_PTR		0x18
+#else /* ENABLE_RME */
+#define CPU_DATA_CONTEXT_NUM		2
 #define CPU_DATA_CPU_OPS_PTR		0x10
+#endif /* ENABLE_RME */
 
 #if ENABLE_PAUTH
 /* 8-bytes aligned offset of apiakey[2], size 16 bytes */
-#define	CPU_DATA_APIAKEY_OFFSET		(0x18 + PSCI_CPU_DATA_SIZE_ALIGNED)
-#define CPU_DATA_CRASH_BUF_OFFSET	(CPU_DATA_APIAKEY_OFFSET + 0x10)
-#else
-#define CPU_DATA_CRASH_BUF_OFFSET	(0x18 + PSCI_CPU_DATA_SIZE_ALIGNED)
-#endif	/* ENABLE_PAUTH */
+#define	CPU_DATA_APIAKEY_OFFSET		(0x8 + PSCI_CPU_DATA_SIZE_ALIGNED \
+					     + CPU_DATA_CPU_OPS_PTR)
+#define CPU_DATA_CRASH_BUF_OFFSET	(0x10 + CPU_DATA_APIAKEY_OFFSET)
+#else /* ENABLE_PAUTH */
+#define CPU_DATA_CRASH_BUF_OFFSET	(0x8 + PSCI_CPU_DATA_SIZE_ALIGNED \
+					     + CPU_DATA_CPU_OPS_PTR)
+#endif /* ENABLE_PAUTH */
 
 /* need enough space in crash buffer to save 8 registers */
 #define CPU_DATA_CRASH_BUF_SIZE		64
@@ -65,11 +74,14 @@
 
 #ifndef __ASSEMBLER__
 
+#include <assert.h>
+#include <stdint.h>
+
 #include <arch_helpers.h>
 #include <lib/cassert.h>
 #include <lib/psci/psci.h>
+
 #include <platform_def.h>
-#include <stdint.h>
 
 /* Offsets for the cpu_data structure */
 #define CPU_DATA_PSCI_LOCK_OFFSET	__builtin_offsetof\
@@ -80,27 +92,34 @@
 		(cpu_data_t, platform_cpu_data)
 #endif
 
+typedef enum context_pas {
+	CPU_CONTEXT_SECURE = 0,
+	CPU_CONTEXT_NS,
+#if ENABLE_RME
+	CPU_CONTEXT_REALM,
+#endif
+	CPU_CONTEXT_NUM
+} context_pas_t;
+
 /*******************************************************************************
  * Function & variable prototypes
  ******************************************************************************/
 
 /*******************************************************************************
  * Cache of frequently used per-cpu data:
- *   Pointers to non-secure and secure security state contexts
+ *   Pointers to non-secure, realm, and secure security state contexts
  *   Address of the crash stack
  * It is aligned to the cache line boundary to allow efficient concurrent
  * manipulation of these pointers on different cpus
  *
- * TODO: Add other commonly used variables to this (tf_issues#90)
- *
  * The data structure and the _cpu_data accessors should not be used directly
  * by components that have per-cpu members. The member access macros should be
  * used for this.
  ******************************************************************************/
 typedef struct cpu_data {
 #ifdef __aarch64__
-	void *cpu_context[2];
-#endif
+	void *cpu_context[CPU_DATA_CONTEXT_NUM];
+#endif /* __aarch64__ */
 	uintptr_t cpu_ops_ptr;
 	struct psci_cpu_data psci_svc_cpu_data;
 #if ENABLE_PAUTH
@@ -122,10 +141,15 @@
 
 extern cpu_data_t percpu_data[PLATFORM_CORE_COUNT];
 
+#ifdef __aarch64__
+CASSERT(CPU_DATA_CONTEXT_NUM == CPU_CONTEXT_NUM,
+		assert_cpu_data_context_num_mismatch);
+#endif
+
 #if ENABLE_PAUTH
 CASSERT(CPU_DATA_APIAKEY_OFFSET == __builtin_offsetof
 	(cpu_data_t, apiakey),
-	assert_cpu_data_crash_stack_offset_mismatch);
+	assert_cpu_data_pauth_stack_offset_mismatch);
 #endif
 
 #if CRASH_REPORTING
@@ -160,6 +184,31 @@
 struct cpu_data *_cpu_data(void);
 #endif
 
+/*
+ * Returns the index of the cpu_context array for the given security state.
+ * All accesses to cpu_context should be through this helper to make sure
+ * an access is not out-of-bounds. The function assumes security_state is
+ * valid.
+ */
+static inline context_pas_t get_cpu_context_index(uint32_t security_state)
+{
+	if (security_state == SECURE) {
+		return CPU_CONTEXT_SECURE;
+	} else {
+#if ENABLE_RME
+		if (security_state == NON_SECURE) {
+			return CPU_CONTEXT_NS;
+		} else {
+			assert(security_state == REALM);
+			return CPU_CONTEXT_REALM;
+		}
+#else
+		assert(security_state == NON_SECURE);
+		return CPU_CONTEXT_NS;
+#endif
+	}
+}
+
 /**************************************************************************
  * APIs for initialising and accessing per-cpu data
  *************************************************************************/
diff --git a/include/lib/extensions/amu.h b/include/lib/extensions/amu.h
index 3a70e4f..3a254c9 100644
--- a/include/lib/extensions/amu.h
+++ b/include/lib/extensions/amu.h
@@ -13,6 +13,7 @@
 #include <lib/cassert.h>
 #include <lib/utils_def.h>
 
+#include <context.h>
 #include <platform_def.h>
 
 /* All group 0 counters */
@@ -80,7 +81,11 @@
 };
 
 unsigned int amu_get_version(void);
+#if __aarch64__
+void amu_enable(bool el2_unused, cpu_context_t *ctx);
+#else
 void amu_enable(bool el2_unused);
+#endif
 
 /* Group 0 configuration helpers */
 uint64_t amu_group0_cnt_read(unsigned int idx);
diff --git a/include/lib/extensions/mpam.h b/include/lib/extensions/mpam.h
index ac8c00a..414adcb 100644
--- a/include/lib/extensions/mpam.h
+++ b/include/lib/extensions/mpam.h
@@ -9,7 +9,6 @@
 
 #include <stdbool.h>
 
-bool mpam_supported(void);
 void mpam_enable(bool el2_unused);
 
 #endif /* MPAM_H */
diff --git a/include/lib/extensions/sys_reg_trace.h b/include/lib/extensions/sys_reg_trace.h
new file mode 100644
index 0000000..74470fe
--- /dev/null
+++ b/include/lib/extensions/sys_reg_trace.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SYS_REG_TRACE_H
+#define SYS_REG_TRACE_H
+
+#include <context.h>
+
+#if __aarch64__
+void sys_reg_trace_enable(cpu_context_t *context);
+#else
+void sys_reg_trace_enable(void);
+#endif /* __aarch64__ */
+
+#endif /* SYS_REG_TRACE_H */
diff --git a/include/lib/extensions/trbe.h b/include/lib/extensions/trbe.h
new file mode 100644
index 0000000..1753ab6
--- /dev/null
+++ b/include/lib/extensions/trbe.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TRBE_H
+#define TRBE_H
+
+void trbe_enable(void);
+
+#endif /* TRBE_H */
diff --git a/include/lib/extensions/trf.h b/include/lib/extensions/trf.h
new file mode 100644
index 0000000..18f17f3
--- /dev/null
+++ b/include/lib/extensions/trf.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TRF_H
+#define TRF_H
+
+void trf_enable(void);
+
+#endif /* TRF_H */
diff --git a/include/lib/gpt_rme/gpt_rme.h b/include/lib/gpt_rme/gpt_rme.h
new file mode 100644
index 0000000..379b915
--- /dev/null
+++ b/include/lib/gpt_rme/gpt_rme.h
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPT_RME_H
+#define GPT_RME_H
+
+#include <stdint.h>
+
+#include <arch.h>
+
+/******************************************************************************/
+/* GPT helper macros and definitions                                          */
+/******************************************************************************/
+
+/*
+ * Structure for specifying a mapping range and it's properties. This should not
+ * be manually initialized, using the MAP_GPT_REGION_x macros is recommended as
+ * to avoid potential incompatibilities in the future.
+ */
+typedef struct pas_region {
+	uintptr_t	base_pa;	/* Base address for PAS. */
+	size_t		size;		/* Size of the PAS. */
+	unsigned int	attrs;		/* PAS GPI and entry type. */
+} pas_region_t;
+
+/* GPT GPI definitions */
+#define GPT_GPI_NO_ACCESS		U(0x0)
+#define GPT_GPI_SECURE			U(0x8)
+#define GPT_GPI_NS			U(0x9)
+#define GPT_GPI_ROOT			U(0xA)
+#define GPT_GPI_REALM			U(0xB)
+#define GPT_GPI_ANY			U(0xF)
+#define GPT_GPI_VAL_MASK		UL(0xF)
+
+/* PAS attribute GPI definitions. */
+#define GPT_PAS_ATTR_GPI_SHIFT		U(0)
+#define GPT_PAS_ATTR_GPI_MASK		U(0xF)
+#define GPT_PAS_ATTR_GPI(_attrs)	(((_attrs)			\
+					>> GPT_PAS_ATTR_GPI_SHIFT)	\
+					& GPT_PAS_ATTR_GPI_MASK)
+
+/* PAS attribute mapping type definitions */
+#define GPT_PAS_ATTR_MAP_TYPE_BLOCK	U(0x0)
+#define GPT_PAS_ATTR_MAP_TYPE_GRANULE	U(0x1)
+#define GPT_PAS_ATTR_MAP_TYPE_SHIFT	U(4)
+#define GPT_PAS_ATTR_MAP_TYPE_MASK	U(0x1)
+#define GPT_PAS_ATTR_MAP_TYPE(_attrs)	(((_attrs)			\
+					>> GPT_PAS_ATTR_MAP_TYPE_SHIFT)	\
+					& GPT_PAS_ATTR_MAP_TYPE_MASK)
+
+/*
+ * Macro to initialize the attributes field in the pas_region_t structure.
+ * [31:5] Reserved
+ * [4]    Mapping type (GPT_PAS_ATTR_MAP_TYPE_x definitions)
+ * [3:0]  PAS GPI type (GPT_GPI_x definitions)
+ */
+#define GPT_PAS_ATTR(_type, _gpi)					\
+	((((_type) & GPT_PAS_ATTR_MAP_TYPE_MASK)			\
+	  << GPT_PAS_ATTR_MAP_TYPE_SHIFT) |				\
+	(((_gpi) & GPT_PAS_ATTR_GPI_MASK)				\
+	 << GPT_PAS_ATTR_GPI_SHIFT))
+
+/*
+ * Macro to create a GPT entry for this PAS range as a block descriptor. If this
+ * region does not fit the requirements for a block descriptor then GPT
+ * initialization will fail.
+ */
+#define GPT_MAP_REGION_BLOCK(_pa, _sz, _gpi)				\
+	{								\
+		.base_pa = (_pa),					\
+		.size = (_sz),						\
+		.attrs = GPT_PAS_ATTR(GPT_PAS_ATTR_MAP_TYPE_BLOCK, (_gpi)), \
+	}
+
+/*
+ * Macro to create a GPT entry for this PAS range as a table descriptor. If this
+ * region does not fit the requirements for a table descriptor then GPT
+ * initialization will fail.
+ */
+#define GPT_MAP_REGION_GRANULE(_pa, _sz, _gpi)				\
+	{								\
+		.base_pa = (_pa),					\
+		.size = (_sz),						\
+		.attrs = GPT_PAS_ATTR(GPT_PAS_ATTR_MAP_TYPE_GRANULE, (_gpi)), \
+	}
+
+/******************************************************************************/
+/* GPT register field definitions                                             */
+/******************************************************************************/
+
+/*
+ * Least significant address bits protected by each entry in level 0 GPT. This
+ * field is read-only.
+ */
+#define GPCCR_L0GPTSZ_SHIFT	U(20)
+#define GPCCR_L0GPTSZ_MASK	U(0xF)
+
+typedef enum {
+	GPCCR_L0GPTSZ_30BITS	= U(0x0),
+	GPCCR_L0GPTSZ_34BITS	= U(0x4),
+	GPCCR_L0GPTSZ_36BITS	= U(0x6),
+	GPCCR_L0GPTSZ_39BITS	= U(0x9)
+} gpccr_l0gptsz_e;
+
+/* Granule protection check priority bit definitions */
+#define GPCCR_GPCP_SHIFT	U(17)
+#define GPCCR_GPCP_BIT		(ULL(1) << GPCCR_EL3_GPCP_SHIFT)
+
+/* Granule protection check bit definitions */
+#define GPCCR_GPC_SHIFT		U(16)
+#define GPCCR_GPC_BIT		(ULL(1) << GPCCR_GPC_SHIFT)
+
+/* Physical granule size bit definitions */
+#define GPCCR_PGS_SHIFT		U(14)
+#define GPCCR_PGS_MASK		U(0x3)
+#define SET_GPCCR_PGS(x)	(((x) & GPCCR_PGS_MASK) << GPCCR_PGS_SHIFT)
+
+typedef enum {
+	GPCCR_PGS_4K		= U(0x0),
+	GPCCR_PGS_64K		= U(0x1),
+	GPCCR_PGS_16K		= U(0x2)
+} gpccr_pgs_e;
+
+/* GPT fetch shareability attribute bit definitions */
+#define GPCCR_SH_SHIFT		U(12)
+#define GPCCR_SH_MASK		U(0x3)
+#define SET_GPCCR_SH(x)		(((x) & GPCCR_SH_MASK) << GPCCR_SH_SHIFT)
+
+typedef enum {
+	GPCCR_SH_NS		= U(0x0),
+	GPCCR_SH_OS		= U(0x2),
+	GPCCR_SH_IS		= U(0x3)
+} gpccr_sh_e;
+
+/* GPT fetch outer cacheability attribute bit definitions */
+#define GPCCR_ORGN_SHIFT	U(10)
+#define GPCCR_ORGN_MASK		U(0x3)
+#define SET_GPCCR_ORGN(x)	(((x) & GPCCR_ORGN_MASK) << GPCCR_ORGN_SHIFT)
+
+typedef enum {
+	GPCCR_ORGN_NC		= U(0x0),
+	GPCCR_ORGN_WB_RA_WA	= U(0x1),
+	GPCCR_ORGN_WT_RA_NWA	= U(0x2),
+	GPCCR_ORGN_WB_RA_NWA	= U(0x3)
+} gpccr_orgn_e;
+
+/* GPT fetch inner cacheability attribute bit definitions */
+#define GPCCR_IRGN_SHIFT	U(8)
+#define GPCCR_IRGN_MASK		U(0x3)
+#define SET_GPCCR_IRGN(x)	(((x) & GPCCR_IRGN_MASK) << GPCCR_IRGN_SHIFT)
+
+typedef enum {
+	GPCCR_IRGN_NC		= U(0x0),
+	GPCCR_IRGN_WB_RA_WA	= U(0x1),
+	GPCCR_IRGN_WT_RA_NWA	= U(0x2),
+	GPCCR_IRGN_WB_RA_NWA	= U(0x3)
+} gpccr_irgn_e;
+
+/* Protected physical address size bit definitions */
+#define GPCCR_PPS_SHIFT		U(0)
+#define GPCCR_PPS_MASK		U(0x7)
+#define SET_GPCCR_PPS(x)	(((x) & GPCCR_PPS_MASK) << GPCCR_PPS_SHIFT)
+
+typedef enum {
+	GPCCR_PPS_4GB		= U(0x0),
+	GPCCR_PPS_64GB		= U(0x1),
+	GPCCR_PPS_1TB		= U(0x2),
+	GPCCR_PPS_4TB		= U(0x3),
+	GPCCR_PPS_16TB		= U(0x4),
+	GPCCR_PPS_256TB		= U(0x5),
+	GPCCR_PPS_4PB		= U(0x6)
+} gpccr_pps_e;
+
+/* Base Address for the GPT bit definitions */
+#define GPTBR_BADDR_SHIFT	U(0)
+#define GPTBR_BADDR_VAL_SHIFT	U(12)
+#define GPTBR_BADDR_MASK	ULL(0xffffffffff)
+
+/******************************************************************************/
+/* GPT public APIs                                                            */
+/******************************************************************************/
+
+/*
+ * Public API that initializes the entire protected space to GPT_GPI_ANY using
+ * the L0 tables (block descriptors).  Ideally, this function is invoked prior
+ * to DDR discovery and initialization.  The MMU must be initialized before
+ * calling this function.
+ *
+ * Parameters
+ *   pps		PPS value to use for table generation
+ *   l0_mem_base	Base address of L0 tables in memory.
+ *   l0_mem_size	Total size of memory available for L0 tables.
+ *
+ * Return
+ *   Negative Linux error code in the event of a failure, 0 for success.
+ */
+int gpt_init_l0_tables(gpccr_pps_e pps,
+		       uintptr_t l0_mem_base,
+		       size_t l0_mem_size);
+
+/*
+ * Public API that carves out PAS regions from the L0 tables and builds any L1
+ * tables that are needed.  This function ideally is run after DDR discovery and
+ * initialization.  The L0 tables must have already been initialized to GPI_ANY
+ * when this function is called.
+ *
+ * Parameters
+ *   pgs		PGS value to use for table generation.
+ *   l1_mem_base	Base address of memory used for L1 tables.
+ *   l1_mem_size	Total size of memory available for L1 tables.
+ *   *pas_regions	Pointer to PAS regions structure array.
+ *   pas_count		Total number of PAS regions.
+ *
+ * Return
+ *   Negative Linux error code in the event of a failure, 0 for success.
+ */
+int gpt_init_pas_l1_tables(gpccr_pgs_e pgs,
+			   uintptr_t l1_mem_base,
+			   size_t l1_mem_size,
+			   pas_region_t *pas_regions,
+			   unsigned int pas_count);
+
+/*
+ * Public API to initialize the runtime gpt_config structure based on the values
+ * present in the GPTBR_EL3 and GPCCR_EL3 registers. GPT initialization
+ * typically happens in a bootloader stage prior to setting up the EL3 runtime
+ * environment for the granule transition service so this function detects the
+ * initialization from a previous stage. Granule protection checks must be
+ * enabled already or this function will return an error.
+ *
+ * Return
+ *   Negative Linux error code in the event of a failure, 0 for success.
+ */
+int gpt_runtime_init(void);
+
+/*
+ * Public API to enable granule protection checks once the tables have all been
+ * initialized.  This function is called at first initialization and then again
+ * later during warm boots of CPU cores.
+ *
+ * Return
+ *   Negative Linux error code in the event of a failure, 0 for success.
+ */
+int gpt_enable(void);
+
+/*
+ * Public API to disable granule protection checks.
+ */
+void gpt_disable(void);
+
+/*
+ * This function is the core of the granule transition service. When a granule
+ * transition request occurs it is routed to this function where the request is
+ * validated then fulfilled if possible.
+ *
+ * TODO: implement support for transitioning multiple granules at once.
+ *
+ * Parameters
+ *   base: Base address of the region to transition, must be aligned to granule
+ *         size.
+ *   size: Size of region to transition, must be aligned to granule size.
+ *   src_sec_state: Security state of the caller.
+ *   target_pas: Target PAS of the specified memory region.
+ *
+ * Return
+ *    Negative Linux error code in the event of a failure, 0 for success.
+ */
+int gpt_transition_pas(uint64_t base,
+		       size_t size,
+		       unsigned int src_sec_state,
+		       unsigned int target_pas);
+
+#endif /* GPT_RME_H */
diff --git a/include/lib/optee_utils.h b/include/lib/optee_utils.h
index 6067caf..06378eb 100644
--- a/include/lib/optee_utils.h
+++ b/include/lib/optee_utils.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,8 +7,12 @@
 #ifndef OPTEE_UTILS_H
 #define OPTEE_UTILS_H
 
+#include <stdbool.h>
+
 #include <common/bl_common.h>
 
+bool optee_header_is_valid(uintptr_t header_base);
+
 int parse_optee_header(entry_point_info_t *header_ep,
 	image_info_t *pager_image_info,
 	image_info_t *paged_image_info);
diff --git a/include/lib/smccc.h b/include/lib/smccc.h
index deaeb1d..1a39f24 100644
--- a/include/lib/smccc.h
+++ b/include/lib/smccc.h
@@ -108,9 +108,24 @@
 #define SMC_ARCH_CALL_NOT_REQUIRED	-2
 #define SMC_ARCH_CALL_INVAL_PARAM	-3
 
-/* Various flags passed to SMC handlers */
+/*
+ * Various flags passed to SMC handlers
+ *
+ * Bit 5 and bit 0 of the flag are used to
+ * determine the source security state as
+ * follows:
+ * ---------------------------------
+ *  Bit 5 | Bit 0 | Security state
+ * ---------------------------------
+ *   0        0      SMC_FROM_SECURE
+ *   0        1      SMC_FROM_NON_SECURE
+ *   1        1      SMC_FROM_REALM
+ */
+
 #define SMC_FROM_SECURE		(U(0) << 0)
 #define SMC_FROM_NON_SECURE	(U(1) << 0)
+#define SMC_FROM_REALM		U(0x21)
+#define SMC_FROM_MASK		U(0x21)
 
 #ifndef __ASSEMBLER__
 
@@ -118,8 +133,18 @@
 
 #include <lib/cassert.h>
 
+#if ENABLE_RME
+#define is_caller_non_secure(_f)	(((_f) & SMC_FROM_MASK) \
+					  == SMC_FROM_NON_SECURE)
+#define is_caller_secure(_f)		(((_f) & SMC_FROM_MASK) \
+					  == SMC_FROM_SECURE)
+#define is_caller_realm(_f)		(((_f) & SMC_FROM_MASK) \
+					  == SMC_FROM_REALM)
+#define caller_sec_state(_f)		((_f) & SMC_FROM_MASK)
+#else /* ENABLE_RME */
 #define is_caller_non_secure(_f)	(((_f) & SMC_FROM_NON_SECURE) != U(0))
 #define is_caller_secure(_f)		(!is_caller_non_secure(_f))
+#endif /* ENABLE_RME */
 
 /* The macro below is used to identify a Standard Service SMC call */
 #define is_std_svc_call(_fid)		(GET_SMC_OEN(_fid) == OEN_STD_START)
diff --git a/include/lib/xlat_mpu/xlat_mpu.h b/include/lib/xlat_mpu/xlat_mpu.h
new file mode 100644
index 0000000..252b92c
--- /dev/null
+++ b/include/lib/xlat_mpu/xlat_mpu.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef XLAT_MPU_H
+#define XLAT_MPU_H
+
+#ifndef __ASSEMBLER__
+
+#include <lib/cassert.h>
+
+#define XLAT_TABLES_LIB_V2	1
+
+void enable_mpu_el2(unsigned int flags);
+void enable_mpu_direct_el2(unsigned int flags);
+
+/*
+ * Function to wipe clean and disable all MPU regions.  This function expects
+ * that the MPU has already been turned off, and caching concerns addressed,
+ * but it nevertheless also explicitly turns off the MPU.
+ */
+void clear_all_mpu_regions(void);
+
+#endif /* __ASSEMBLER__ */
+#endif /* XLAT_MPU_H */
diff --git a/include/lib/xlat_tables/xlat_tables.h b/include/lib/xlat_tables/xlat_tables.h
index 082bb5e..a156969 100644
--- a/include/lib/xlat_tables/xlat_tables.h
+++ b/include/lib/xlat_tables/xlat_tables.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -72,6 +72,13 @@
 #define MT_CODE			(MT_MEMORY | MT_RO | MT_EXECUTE)
 #define MT_RO_DATA		(MT_MEMORY | MT_RO | MT_EXECUTE_NEVER)
 
+/* Memory type for EL3 regions */
+#if ENABLE_RME
+#error FEAT_RME requires version 2 of the Translation Tables Library
+#else
+#define EL3_PAS			MT_SECURE
+#endif
+
 /*
  * Structure for specifying a single region of memory.
  */
diff --git a/include/lib/xlat_tables/xlat_tables_defs.h b/include/lib/xlat_tables/xlat_tables_defs.h
index 579d8d8..2d0949b 100644
--- a/include/lib/xlat_tables/xlat_tables_defs.h
+++ b/include/lib/xlat_tables/xlat_tables_defs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -142,6 +142,7 @@
 #define AP_NO_ACCESS_UNPRIVILEGED	(AP1_NO_ACCESS_UNPRIVILEGED << 4)
 #define AP_ONE_VA_RANGE_RES1		(AP1_RES1 << 4)
 #define NS				(U(0x1) << 3)
+#define EL3_S1_NSE			(U(0x1) << 9)
 #define ATTR_NON_CACHEABLE_INDEX	ULL(0x2)
 #define ATTR_DEVICE_INDEX		ULL(0x1)
 #define ATTR_IWBWA_OWBWA_NTR_INDEX	ULL(0x0)
diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h
index 359b983..69ad027 100644
--- a/include/lib/xlat_tables/xlat_tables_v2.h
+++ b/include/lib/xlat_tables/xlat_tables_v2.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -60,17 +60,22 @@
 #define MT_TYPE(_attr)		((_attr) & MT_TYPE_MASK)
 /* Access permissions (RO/RW) */
 #define MT_PERM_SHIFT		U(3)
-/* Security state (SECURE/NS) */
-#define MT_SEC_SHIFT		U(4)
+
+/* Physical address space (SECURE/NS/Root/Realm) */
+#define	MT_PAS_SHIFT		U(4)
+#define MT_PAS_MASK		(U(3) << MT_PAS_SHIFT)
+#define MT_PAS(_attr)		((_attr) & MT_PAS_MASK)
+
 /* Access permissions for instruction execution (EXECUTE/EXECUTE_NEVER) */
-#define MT_EXECUTE_SHIFT	U(5)
+#define MT_EXECUTE_SHIFT	U(6)
 /* In the EL1&0 translation regime, User (EL0) or Privileged (EL1). */
-#define MT_USER_SHIFT		U(6)
+#define MT_USER_SHIFT		U(7)
 
 /* Shareability attribute for the memory region */
-#define MT_SHAREABILITY_SHIFT	U(7)
+#define MT_SHAREABILITY_SHIFT	U(8)
 #define MT_SHAREABILITY_MASK	(U(3) << MT_SHAREABILITY_SHIFT)
 #define MT_SHAREABILITY(_attr)	((_attr) & MT_SHAREABILITY_MASK)
+
 /* All other bits are reserved */
 
 /*
@@ -91,8 +96,10 @@
 #define MT_RO			(U(0) << MT_PERM_SHIFT)
 #define MT_RW			(U(1) << MT_PERM_SHIFT)
 
-#define MT_SECURE		(U(0) << MT_SEC_SHIFT)
-#define MT_NS			(U(1) << MT_SEC_SHIFT)
+#define MT_SECURE		(U(0) << MT_PAS_SHIFT)
+#define MT_NS			(U(1) << MT_PAS_SHIFT)
+#define MT_ROOT			(U(2) << MT_PAS_SHIFT)
+#define MT_REALM		(U(3) << MT_PAS_SHIFT)
 
 /*
  * Access permissions for instruction execution are only relevant for normal
@@ -149,6 +156,13 @@
 #define EL3_REGIME		3
 #define EL_REGIME_INVALID	-1
 
+/* Memory type for EL3 regions. With RME, EL3 is in ROOT PAS */
+#if ENABLE_RME
+#define EL3_PAS			MT_ROOT
+#else
+#define EL3_PAS			MT_SECURE
+#endif /* ENABLE_RME */
+
 /*
  * Declare the translation context type.
  * Its definition is private.
diff --git a/include/plat/arm/board/common/v2m_def.h b/include/plat/arm/board/common/v2m_def.h
index 6a6979c..cb11dac 100644
--- a/include/plat/arm/board/common/v2m_def.h
+++ b/include/plat/arm/board/common/v2m_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,6 +8,13 @@
 
 #include <lib/utils_def.h>
 
+/* Base address of all V2M */
+#ifdef PLAT_V2M_OFFSET
+#define V2M_OFFSET			PLAT_V2M_OFFSET
+#else
+#define V2M_OFFSET			UL(0)
+#endif
+
 /* V2M motherboard system registers & offsets */
 #define V2M_SYSREGS_BASE		UL(0x1c010000)
 #define V2M_SYS_ID			UL(0x0)
@@ -69,18 +76,18 @@
 
 
 /* NOR Flash */
-#define V2M_FLASH0_BASE			UL(0x08000000)
+#define V2M_FLASH0_BASE			(V2M_OFFSET + UL(0x08000000))
 #define V2M_FLASH0_SIZE			UL(0x04000000)
-#define V2M_FLASH_BLOCK_SIZE		UL(0x00040000)	/* 256 KB */
+#define V2M_FLASH_BLOCK_SIZE		UL(0x00040000) /* 256 KB */
 
-#define V2M_IOFPGA_BASE			UL(0x1c000000)
+#define V2M_IOFPGA_BASE			(V2M_OFFSET + UL(0x1c000000))
 #define V2M_IOFPGA_SIZE			UL(0x03000000)
 
 /* PL011 UART related constants */
-#define V2M_IOFPGA_UART0_BASE		UL(0x1c090000)
-#define V2M_IOFPGA_UART1_BASE		UL(0x1c0a0000)
-#define V2M_IOFPGA_UART2_BASE		UL(0x1c0b0000)
-#define V2M_IOFPGA_UART3_BASE		UL(0x1c0c0000)
+#define V2M_IOFPGA_UART0_BASE		(V2M_OFFSET + UL(0x1c090000))
+#define V2M_IOFPGA_UART1_BASE		(V2M_OFFSET + UL(0x1c0a0000))
+#define V2M_IOFPGA_UART2_BASE		(V2M_OFFSET + UL(0x1c0b0000))
+#define V2M_IOFPGA_UART3_BASE		(V2M_OFFSET + UL(0x1c0c0000))
 
 #define V2M_IOFPGA_UART0_CLK_IN_HZ	24000000
 #define V2M_IOFPGA_UART1_CLK_IN_HZ	24000000
@@ -88,11 +95,11 @@
 #define V2M_IOFPGA_UART3_CLK_IN_HZ	24000000
 
 /* SP804 timer related constants */
-#define V2M_SP804_TIMER0_BASE		UL(0x1C110000)
-#define V2M_SP804_TIMER1_BASE		UL(0x1C120000)
+#define V2M_SP804_TIMER0_BASE		(V2M_OFFSET + UL(0x1C110000))
+#define V2M_SP804_TIMER1_BASE		(V2M_OFFSET + UL(0x1C120000))
 
 /* SP810 controller */
-#define V2M_SP810_BASE			UL(0x1c020000)
+#define V2M_SP810_BASE			(V2M_OFFSET + UL(0x1c020000))
 #define V2M_SP810_CTRL_TIM0_SEL		BIT_32(15)
 #define V2M_SP810_CTRL_TIM1_SEL		BIT_32(17)
 #define V2M_SP810_CTRL_TIM2_SEL		BIT_32(19)
diff --git a/include/plat/arm/board/fvp_r/fvp_r_bl1.h b/include/plat/arm/board/fvp_r/fvp_r_bl1.h
new file mode 100644
index 0000000..0b41e67
--- /dev/null
+++ b/include/plat/arm/board/fvp_r/fvp_r_bl1.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FVP_R_BL1_H
+#define FVP_R_BL1_H
+
+void bl1_load_bl33(void);
+void bl1_transfer_bl33(void);
+
+#endif /* FVP_R_BL1_H */
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index ae80628..1993cb4 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -58,8 +58,12 @@
 #define ARM_TRUSTED_DRAM_ID		1
 #define ARM_DRAM_ID			2
 
-/* The first 4KB of Trusted SRAM are used as shared memory */
+#ifdef PLAT_ARM_TRUSTED_SRAM_BASE
+#define ARM_TRUSTED_SRAM_BASE		PLAT_ARM_TRUSTED_SRAM_BASE
+#else
 #define ARM_TRUSTED_SRAM_BASE		UL(0x04000000)
+#endif /* PLAT_ARM_TRUSTED_SRAM_BASE */
+
 #define ARM_SHARED_RAM_BASE		ARM_TRUSTED_SRAM_BASE
 #define ARM_SHARED_RAM_SIZE		UL(0x00001000)	/* 4 KB */
 
@@ -70,38 +74,84 @@
 					 ARM_SHARED_RAM_SIZE)
 
 /*
- * The top 16MB of DRAM1 is configured as secure access only using the TZC
+ * The top 16MB (or 64MB if RME is enabled) of DRAM1 is configured as
+ * follows:
  *   - SCP TZC DRAM: If present, DRAM reserved for SCP use
+ *   - L1 GPT DRAM: Reserved for L1 GPT if RME is enabled
+ *   - REALM DRAM: Reserved for Realm world if RME is enabled
  *   - AP TZC DRAM: The remaining TZC secured DRAM reserved for AP use
+ *
+ *              RME enabled(64MB)                RME not enabled(16MB)
+ *              --------------------             -------------------
+ *              |                  |             |                 |
+ *              |  AP TZC (~28MB)  |             |  AP TZC (~14MB) |
+ *              --------------------             -------------------
+ *              |                  |             |                 |
+ *              |  REALM (32MB)    |             |  EL3 TZC (2MB)  |
+ *              --------------------             -------------------
+ *              |                  |             |                 |
+ *              |  EL3 TZC (3MB)   |             |    SCP TZC      |
+ *              --------------------  0xFFFF_FFFF-------------------
+ *              | L1 GPT + SCP TZC |
+ *              |       (~1MB)     |
+ *  0xFFFF_FFFF --------------------
+ */
+#if ENABLE_RME
+#define ARM_TZC_DRAM1_SIZE              UL(0x04000000) /* 64MB */
+/*
+ * Define a region within the TZC secured DRAM for use by EL3 runtime
+ * firmware. This region is meant to be NOLOAD and will not be zero
+ * initialized. Data sections with the attribute `arm_el3_tzc_dram` will be
+ * placed here. 3MB region is reserved if RME is enabled, 2MB otherwise.
  */
-#define ARM_TZC_DRAM1_SIZE		UL(0x01000000)
+#define ARM_EL3_TZC_DRAM1_SIZE		UL(0x00300000) /* 3MB */
+#define ARM_L1_GPT_SIZE			UL(0x00100000) /* 1MB */
+#define ARM_REALM_SIZE			UL(0x02000000) /* 32MB */
+#else
+#define ARM_TZC_DRAM1_SIZE		UL(0x01000000) /* 16MB */
+#define ARM_EL3_TZC_DRAM1_SIZE		UL(0x00200000) /* 2MB */
+#define ARM_L1_GPT_SIZE			UL(0)
+#define ARM_REALM_SIZE			UL(0)
+#endif /* ENABLE_RME */
 
 #define ARM_SCP_TZC_DRAM1_BASE		(ARM_DRAM1_BASE +		\
-					 ARM_DRAM1_SIZE -		\
-					 ARM_SCP_TZC_DRAM1_SIZE)
+					ARM_DRAM1_SIZE -		\
+					(ARM_SCP_TZC_DRAM1_SIZE +	\
+					ARM_L1_GPT_SIZE))
 #define ARM_SCP_TZC_DRAM1_SIZE		PLAT_ARM_SCP_TZC_DRAM1_SIZE
 #define ARM_SCP_TZC_DRAM1_END		(ARM_SCP_TZC_DRAM1_BASE +	\
-					 ARM_SCP_TZC_DRAM1_SIZE - 1U)
+					ARM_SCP_TZC_DRAM1_SIZE - 1U)
+#if ENABLE_RME
+#define ARM_L1_GPT_ADDR_BASE		(ARM_DRAM1_BASE +		\
+					ARM_DRAM1_SIZE -		\
+					ARM_L1_GPT_SIZE)
+#define ARM_L1_GPT_END			(ARM_L1_GPT_ADDR_BASE +		\
+					ARM_L1_GPT_SIZE - 1U)
 
-/*
- * Define a 2MB region within the TZC secured DRAM for use by EL3 runtime
- * firmware. This region is meant to be NOLOAD and will not be zero
- * initialized. Data sections with the attribute `arm_el3_tzc_dram` will be
- * placed here.
- */
-#define ARM_EL3_TZC_DRAM1_BASE		(ARM_SCP_TZC_DRAM1_BASE - ARM_EL3_TZC_DRAM1_SIZE)
-#define ARM_EL3_TZC_DRAM1_SIZE		UL(0x00200000) /* 2 MB */
+#define ARM_REALM_BASE			(ARM_DRAM1_BASE +		\
+					ARM_DRAM1_SIZE -		\
+					(ARM_SCP_TZC_DRAM1_SIZE +	\
+					ARM_EL3_TZC_DRAM1_SIZE +	\
+					ARM_REALM_SIZE +		\
+					ARM_L1_GPT_SIZE))
+#define ARM_REALM_END                   (ARM_REALM_BASE + ARM_REALM_SIZE - 1U)
+#endif /* ENABLE_RME */
+
+#define ARM_EL3_TZC_DRAM1_BASE		(ARM_SCP_TZC_DRAM1_BASE -	\
+					ARM_EL3_TZC_DRAM1_SIZE)
 #define ARM_EL3_TZC_DRAM1_END		(ARM_EL3_TZC_DRAM1_BASE +	\
 					ARM_EL3_TZC_DRAM1_SIZE - 1U)
 
 #define ARM_AP_TZC_DRAM1_BASE		(ARM_DRAM1_BASE +		\
-					 ARM_DRAM1_SIZE -		\
-					 ARM_TZC_DRAM1_SIZE)
+					ARM_DRAM1_SIZE -		\
+					ARM_TZC_DRAM1_SIZE)
 #define ARM_AP_TZC_DRAM1_SIZE		(ARM_TZC_DRAM1_SIZE -		\
-					 (ARM_SCP_TZC_DRAM1_SIZE +	\
-					 ARM_EL3_TZC_DRAM1_SIZE))
+					(ARM_SCP_TZC_DRAM1_SIZE +	\
+					ARM_EL3_TZC_DRAM1_SIZE +	\
+					ARM_REALM_SIZE +		\
+					ARM_L1_GPT_SIZE))
 #define ARM_AP_TZC_DRAM1_END		(ARM_AP_TZC_DRAM1_BASE +	\
-					 ARM_AP_TZC_DRAM1_SIZE - 1U)
+					ARM_AP_TZC_DRAM1_SIZE - 1U)
 
 /* Define the Access permissions for Secure peripherals to NS_DRAM */
 #if ARM_CRYPTOCELL_INTEG
@@ -149,8 +199,12 @@
 					 ARM_TZC_DRAM1_SIZE)
 #define ARM_NS_DRAM1_END		(ARM_NS_DRAM1_BASE +		\
 					 ARM_NS_DRAM1_SIZE - 1U)
-
+#ifdef PLAT_ARM_DRAM1_BASE
+#define ARM_DRAM1_BASE			PLAT_ARM_DRAM1_BASE
+#else
 #define ARM_DRAM1_BASE			ULL(0x80000000)
+#endif /* PLAT_ARM_DRAM1_BASE */
+
 #define ARM_DRAM1_SIZE			ULL(0x80000000)
 #define ARM_DRAM1_END			(ARM_DRAM1_BASE +		\
 					 ARM_DRAM1_SIZE - 1U)
@@ -198,45 +252,58 @@
 	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \
 			GIC_INTR_CFG_EDGE)
 
-#define ARM_MAP_SHARED_RAM		MAP_REGION_FLAT(		\
-						ARM_SHARED_RAM_BASE,	\
-						ARM_SHARED_RAM_SIZE,	\
-						MT_DEVICE | MT_RW | MT_SECURE)
+#define ARM_MAP_SHARED_RAM	MAP_REGION_FLAT(			\
+					ARM_SHARED_RAM_BASE,		\
+					ARM_SHARED_RAM_SIZE,		\
+					MT_DEVICE | MT_RW | EL3_PAS)
 
-#define ARM_MAP_NS_DRAM1		MAP_REGION_FLAT(		\
-						ARM_NS_DRAM1_BASE,	\
-						ARM_NS_DRAM1_SIZE,	\
-						MT_MEMORY | MT_RW | MT_NS)
+#define ARM_MAP_NS_DRAM1	MAP_REGION_FLAT(			\
+					ARM_NS_DRAM1_BASE,		\
+					ARM_NS_DRAM1_SIZE,		\
+					MT_MEMORY | MT_RW | MT_NS)
 
-#define ARM_MAP_DRAM2			MAP_REGION_FLAT(		\
-						ARM_DRAM2_BASE,		\
-						ARM_DRAM2_SIZE,		\
-						MT_MEMORY | MT_RW | MT_NS)
+#define ARM_MAP_DRAM2		MAP_REGION_FLAT(			\
+					ARM_DRAM2_BASE,			\
+					ARM_DRAM2_SIZE,			\
+					MT_MEMORY | MT_RW | MT_NS)
 
-#define ARM_MAP_TSP_SEC_MEM		MAP_REGION_FLAT(		\
-						TSP_SEC_MEM_BASE,	\
-						TSP_SEC_MEM_SIZE,	\
-						MT_MEMORY | MT_RW | MT_SECURE)
+#define ARM_MAP_TSP_SEC_MEM	MAP_REGION_FLAT(			\
+					TSP_SEC_MEM_BASE,		\
+					TSP_SEC_MEM_SIZE,		\
+					MT_MEMORY | MT_RW | MT_SECURE)
 
 #if ARM_BL31_IN_DRAM
-#define ARM_MAP_BL31_SEC_DRAM		MAP_REGION_FLAT(		\
-						BL31_BASE,		\
-						PLAT_ARM_MAX_BL31_SIZE,	\
-						MT_MEMORY | MT_RW | MT_SECURE)
+#define ARM_MAP_BL31_SEC_DRAM	MAP_REGION_FLAT(			\
+					BL31_BASE,			\
+					PLAT_ARM_MAX_BL31_SIZE,		\
+					MT_MEMORY | MT_RW | MT_SECURE)
 #endif
 
-#define ARM_MAP_EL3_TZC_DRAM		MAP_REGION_FLAT(			\
-						ARM_EL3_TZC_DRAM1_BASE,	\
-						ARM_EL3_TZC_DRAM1_SIZE,	\
-						MT_MEMORY | MT_RW | MT_SECURE)
+#define ARM_MAP_EL3_TZC_DRAM	MAP_REGION_FLAT(			\
+					ARM_EL3_TZC_DRAM1_BASE,		\
+					ARM_EL3_TZC_DRAM1_SIZE,		\
+					MT_MEMORY | MT_RW | EL3_PAS)
 
 #if defined(SPD_spmd)
-#define ARM_MAP_TRUSTED_DRAM		MAP_REGION_FLAT(		    \
-						PLAT_ARM_TRUSTED_DRAM_BASE, \
-						PLAT_ARM_TRUSTED_DRAM_SIZE, \
-						MT_MEMORY | MT_RW | MT_SECURE)
+#define ARM_MAP_TRUSTED_DRAM	MAP_REGION_FLAT(			\
+					PLAT_ARM_TRUSTED_DRAM_BASE,	\
+					PLAT_ARM_TRUSTED_DRAM_SIZE,	\
+					MT_MEMORY | MT_RW | MT_SECURE)
 #endif
 
+#if ENABLE_RME
+#define ARM_MAP_RMM_DRAM	MAP_REGION_FLAT(			\
+					PLAT_ARM_RMM_BASE,		\
+					PLAT_ARM_RMM_SIZE,		\
+					MT_MEMORY | MT_RW | MT_REALM)
+
+
+#define ARM_MAP_GPT_L1_DRAM	MAP_REGION_FLAT(			\
+					ARM_L1_GPT_ADDR_BASE,		\
+					ARM_L1_GPT_SIZE,		\
+					MT_MEMORY | MT_RW | EL3_PAS)
+
+#endif /* ENABLE_RME */
 
 /*
  * Mapping for the BL1 RW region. This mapping is needed by BL2 in order to
@@ -247,7 +314,7 @@
 #define ARM_MAP_BL1_RW		MAP_REGION_FLAT(	\
 					BL1_RW_BASE,	\
 					BL1_RW_LIMIT - BL1_RW_BASE, \
-					MT_MEMORY | MT_RW | MT_SECURE)
+					MT_MEMORY | MT_RW | EL3_PAS)
 
 /*
  * If SEPARATE_CODE_AND_RODATA=1 we define a region for each section
@@ -257,35 +324,35 @@
 #define ARM_MAP_BL_RO			MAP_REGION_FLAT(			\
 						BL_CODE_BASE,			\
 						BL_CODE_END - BL_CODE_BASE,	\
-						MT_CODE | MT_SECURE),		\
+						MT_CODE | EL3_PAS),		\
 					MAP_REGION_FLAT(			\
 						BL_RO_DATA_BASE,		\
 						BL_RO_DATA_END			\
 							- BL_RO_DATA_BASE,	\
-						MT_RO_DATA | MT_SECURE)
+						MT_RO_DATA | EL3_PAS)
 #else
 #define ARM_MAP_BL_RO			MAP_REGION_FLAT(			\
 						BL_CODE_BASE,			\
 						BL_CODE_END - BL_CODE_BASE,	\
-						MT_CODE | MT_SECURE)
+						MT_CODE | EL3_PAS)
 #endif
 #if USE_COHERENT_MEM
 #define ARM_MAP_BL_COHERENT_RAM		MAP_REGION_FLAT(			\
 						BL_COHERENT_RAM_BASE,		\
 						BL_COHERENT_RAM_END		\
 							- BL_COHERENT_RAM_BASE, \
-						MT_DEVICE | MT_RW | MT_SECURE)
+						MT_DEVICE | MT_RW | EL3_PAS)
 #endif
 #if USE_ROMLIB
 #define ARM_MAP_ROMLIB_CODE		MAP_REGION_FLAT(			\
 						ROMLIB_RO_BASE,			\
 						ROMLIB_RO_LIMIT	- ROMLIB_RO_BASE,\
-						MT_CODE | MT_SECURE)
+						MT_CODE | EL3_PAS)
 
 #define ARM_MAP_ROMLIB_DATA		MAP_REGION_FLAT(			\
 						ROMLIB_RW_BASE,			\
 						ROMLIB_RW_END	- ROMLIB_RW_BASE,\
-						MT_MEMORY | MT_RW | MT_SECURE)
+						MT_MEMORY | MT_RW | EL3_PAS)
 #endif
 
 /*
@@ -300,7 +367,15 @@
 #define ARM_MAP_BL_CONFIG_REGION	MAP_REGION_FLAT(ARM_BL_RAM_BASE,	\
 						(ARM_FW_CONFIGS_LIMIT		\
 							- ARM_BL_RAM_BASE),	\
-						MT_MEMORY | MT_RW | MT_SECURE)
+						MT_MEMORY | MT_RW | EL3_PAS)
+/*
+ * Map L0_GPT with read and write permissions
+ */
+#if ENABLE_RME
+#define ARM_MAP_L0_GPT_REGION		MAP_REGION_FLAT(ARM_L0_GPT_ADDR_BASE,	\
+						ARM_L0_GPT_SIZE,		\
+						MT_MEMORY | MT_RW | MT_ROOT)
+#endif
 
 /*
  * The max number of regions like RO(code), coherent and data required by
@@ -312,16 +387,44 @@
 					 ARM_BL_REGIONS)
 
 /* Memory mapped Generic timer interfaces  */
+#ifdef PLAT_ARM_SYS_CNTCTL_BASE
+#define ARM_SYS_CNTCTL_BASE		PLAT_ARM_SYS_CNTCTL_BASE
+#else
 #define ARM_SYS_CNTCTL_BASE		UL(0x2a430000)
+#endif
+
+#ifdef PLAT_ARM_SYS_CNTREAD_BASE
+#define ARM_SYS_CNTREAD_BASE		PLAT_ARM_SYS_CNTREAD_BASE
+#else
 #define ARM_SYS_CNTREAD_BASE		UL(0x2a800000)
+#endif
+
+#ifdef PLAT_ARM_SYS_TIMCTL_BASE
+#define ARM_SYS_TIMCTL_BASE		PLAT_ARM_SYS_TIMCTL_BASE
+#else
 #define ARM_SYS_TIMCTL_BASE		UL(0x2a810000)
+#endif
+
+#ifdef PLAT_ARM_SYS_CNT_BASE_S
+#define ARM_SYS_CNT_BASE_S		PLAT_ARM_SYS_CNT_BASE_S
+#else
 #define ARM_SYS_CNT_BASE_S		UL(0x2a820000)
+#endif
+
+#ifdef PLAT_ARM_SYS_CNT_BASE_NS
+#define ARM_SYS_CNT_BASE_NS		PLAT_ARM_SYS_CNT_BASE_NS
+#else
 #define ARM_SYS_CNT_BASE_NS		UL(0x2a830000)
+#endif
 
 #define ARM_CONSOLE_BAUDRATE		115200
 
 /* Trusted Watchdog constants */
+#ifdef PLAT_ARM_SP805_TWDG_BASE
+#define ARM_SP805_TWDG_BASE		PLAT_ARM_SP805_TWDG_BASE
+#else
 #define ARM_SP805_TWDG_BASE		UL(0x2a490000)
+#endif
 #define ARM_SP805_TWDG_CLK_HZ		32768
 /* The TBBR document specifies a watchdog timeout of 256 seconds. SP805
  * asserts reset after two consecutive countdowns (2 x 128 = 256 sec) */
@@ -373,15 +476,32 @@
  */
 #define ARM_FW_CONFIGS_LIMIT		(ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
 
+#if ENABLE_RME
+/*
+ * Store the L0 GPT on Trusted SRAM next to firmware
+ * configuration memory, 4KB aligned.
+ */
+#define ARM_L0_GPT_SIZE			(PAGE_SIZE)
+#define ARM_L0_GPT_ADDR_BASE		(ARM_FW_CONFIGS_LIMIT)
+#define ARM_L0_GPT_LIMIT		(ARM_L0_GPT_ADDR_BASE + ARM_L0_GPT_SIZE)
+#else
+#define ARM_L0_GPT_SIZE			U(0)
+#endif
+
 /*******************************************************************************
  * BL1 specific defines.
  * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of
  * addresses.
  ******************************************************************************/
 #define BL1_RO_BASE			PLAT_ARM_TRUSTED_ROM_BASE
+#ifdef PLAT_BL1_RO_LIMIT
+#define BL1_RO_LIMIT			PLAT_BL1_RO_LIMIT
+#else
 #define BL1_RO_LIMIT			(PLAT_ARM_TRUSTED_ROM_BASE	\
 					 + (PLAT_ARM_TRUSTED_ROM_SIZE - \
 					    PLAT_ARM_MAX_ROMLIB_RO_SIZE))
+#endif
+
 /*
  * Put BL1 RW at the top of the Trusted SRAM.
  */
@@ -460,6 +580,14 @@
 #endif
 #endif
 
+/******************************************************************************
+ * RMM specific defines
+ *****************************************************************************/
+#if ENABLE_RME
+#define RMM_BASE			(ARM_REALM_BASE)
+#define RMM_LIMIT			(RMM_BASE + ARM_REALM_SIZE)
+#endif
+
 #if !defined(__aarch64__) || JUNO_AARCH32_EL3_RUNTIME
 /*******************************************************************************
  * BL32 specific defines for EL3 runtime in AArch32 mode
diff --git a/include/plat/arm/common/arm_pas_def.h b/include/plat/arm/common/arm_pas_def.h
new file mode 100644
index 0000000..4fee41b
--- /dev/null
+++ b/include/plat/arm/common/arm_pas_def.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef ARM_PAS_DEF_H
+#define ARM_PAS_DEF_H
+
+#include <lib/gpt_rme/gpt_rme.h>
+#include <plat/arm/common/arm_def.h>
+
+/*****************************************************************************
+ * PAS regions used to initialize the Granule Protection Table (GPT)
+ ****************************************************************************/
+
+/*
+ * The PA space is initially mapped in the GPT as follows:
+ *
+ * ============================================================================
+ * Base Addr| Size        |L? GPT|PAS   |Content                 |Comment
+ * ============================================================================
+ * 0GB      | 1GB         |L0 GPT|ANY   |TBROM (EL3 code)        |Fixed mapping
+ *          |             |      |      |TSRAM (EL3 data)        |
+ *          |             |      |      |IO (incl.UARTs & GIC)   |
+ * ----------------------------------------------------------------------------
+ * 1GB      | 1GB         |L0 GPT|ANY   |IO                      |Fixed mapping
+ * ----------------------------------------------------------------------------
+ * 2GB      | 1GB         |L1 GPT|NS    |DRAM (NS Kernel)        |Use T.Descrip
+ * ----------------------------------------------------------------------------
+ * 3GB      |1GB-64MB     |L1 GPT|NS    |DRAM (NS Kernel)        |Use T.Descrip
+ * ----------------------------------------------------------------------------
+ * 4GB-64MB |64MB-32MB    |      |      |                        |
+ *          | -4MB        |L1 GPT|SECURE|DRAM TZC                |Use T.Descrip
+ * ----------------------------------------------------------------------------
+ * 4GB-32MB |             |      |      |                        |
+ * -3MB-1MB |32MB         |L1 GPT|REALM |RMM                     |Use T.Descrip
+ * ----------------------------------------------------------------------------
+ * 4GB-3MB  |             |      |      |                        |
+ * -1MB     |3MB          |L1 GPT|ROOT  |EL3 DRAM data           |Use T.Descrip
+ * ----------------------------------------------------------------------------
+ * 4GB-1MB  |1MB          |L1 GPT|ROOT  |DRAM (L1 GPTs, SCP TZC) |Fixed mapping
+ * ============================================================================
+ *
+ * - 4KB of L0 GPT reside in TSRAM, on top of the CONFIG section.
+ * - ~1MB of L1 GPTs reside at the top of DRAM1 (TZC area).
+ * - The first 1GB region has GPT_GPI_ANY and, therefore, is not protected by
+ *   the GPT.
+ * - The DRAM TZC area is split into three regions: the L1 GPT region and
+ *   3MB of region below that are defined as GPT_GPI_ROOT, 32MB Realm region
+ *   below that is defined as GPT_GPI_REALM and the rest of it is defined as
+ *   GPT_GPI_SECURE.
+ */
+
+/* TODO: This might not be the best way to map the PAS */
+
+/* Device memory 0 to 2GB */
+#define ARM_PAS_1_BASE			(U(0))
+#define ARM_PAS_1_SIZE			((ULL(1)<<31)) /* 2GB */
+
+/* NS memory 2GB to (end - 64MB) */
+#define ARM_PAS_2_BASE			(ARM_PAS_1_BASE + ARM_PAS_1_SIZE)
+#define ARM_PAS_2_SIZE			(ARM_NS_DRAM1_SIZE)
+
+/* Secure TZC region */
+#define ARM_PAS_3_BASE			(ARM_AP_TZC_DRAM1_BASE)
+#define ARM_PAS_3_SIZE			(ARM_AP_TZC_DRAM1_SIZE)
+
+#define ARM_PAS_GPI_ANY			MAP_GPT_REGION(ARM_PAS_1_BASE, \
+						       ARM_PAS_1_SIZE, \
+						       GPT_GPI_ANY)
+#define	ARM_PAS_KERNEL			GPT_MAP_REGION_GRANULE(ARM_PAS_2_BASE, \
+							       ARM_PAS_2_SIZE, \
+							       GPT_GPI_NS)
+
+#define ARM_PAS_SECURE			GPT_MAP_REGION_GRANULE(ARM_PAS_3_BASE, \
+							       ARM_PAS_3_SIZE, \
+							       GPT_GPI_SECURE)
+
+#define ARM_PAS_REALM			GPT_MAP_REGION_GRANULE(ARM_REALM_BASE, \
+							       ARM_REALM_SIZE, \
+							       GPT_GPI_REALM)
+
+#define ARM_PAS_EL3_DRAM		GPT_MAP_REGION_GRANULE(ARM_EL3_TZC_DRAM1_BASE, \
+							       ARM_EL3_TZC_DRAM1_SIZE, \
+							       GPT_GPI_ROOT)
+
+#define	ARM_PAS_GPTS			GPT_MAP_REGION_GRANULE(ARM_L1_GPT_ADDR_BASE, \
+							       ARM_L1_GPT_SIZE, \
+							       GPT_GPI_ROOT)
+
+/* GPT Configuration options */
+#define PLATFORM_L0GPTSZ		GPCCR_L0GPTSZ_30BITS
+
+#endif /* ARM_PAS_DEF_H */
diff --git a/include/plat/arm/common/fconf_ethosn_getter.h b/include/plat/arm/common/fconf_ethosn_getter.h
index 0fd1f02..fcdc31f 100644
--- a/include/plat/arm/common/fconf_ethosn_getter.h
+++ b/include/plat/arm/common/fconf_ethosn_getter.h
@@ -14,7 +14,7 @@
 #define hw_config__ethosn_config_getter(prop) ethosn_config.prop
 #define hw_config__ethosn_core_addr_getter(idx) __extension__ ({	\
 	assert(idx < ethosn_config.num_cores);				\
-	ethosn_config.core_addr[idx];					\
+	ethosn_config.core[idx].addr;					\
 })
 
 #define ETHOSN_STATUS_DISABLED U(0)
@@ -22,10 +22,13 @@
 
 #define ETHOSN_CORE_NUM_MAX U(64)
 
+struct ethosn_core_t {
+	uint64_t addr;
+};
+
 struct ethosn_config_t {
-	uint8_t status;
 	uint32_t num_cores;
-	uint64_t core_addr[ETHOSN_CORE_NUM_MAX];
+	struct ethosn_core_t core[ETHOSN_CORE_NUM_MAX];
 };
 
 int fconf_populate_arm_ethosn(uintptr_t config);
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 846c9a4..1500ed3 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -41,7 +41,7 @@
  ******************************************************************************/
 #if SPM_MM
 #define ARM_TZC_REGIONS_DEF						\
-	{ARM_AP_TZC_DRAM1_BASE, ARM_EL3_TZC_DRAM1_END,			\
+	{ARM_AP_TZC_DRAM1_BASE, ARM_EL3_TZC_DRAM1_END + ARM_L1_GPT_SIZE,\
 		TZC_REGION_S_RDWR, 0},					\
 	{ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \
 		PLAT_ARM_TZC_NS_DEV_ACCESS}, 				\
@@ -51,9 +51,20 @@
 		PLAT_SP_IMAGE_NS_BUF_SIZE) - 1, TZC_REGION_S_NONE,	\
 		PLAT_ARM_TZC_NS_DEV_ACCESS}
 
+#elif ENABLE_RME
+#define ARM_TZC_REGIONS_DEF						    \
+	{ARM_AP_TZC_DRAM1_BASE, ARM_AP_TZC_DRAM1_END, TZC_REGION_S_RDWR, 0},\
+	{ARM_EL3_TZC_DRAM1_BASE, ARM_L1_GPT_END, TZC_REGION_S_RDWR, 0},	    \
+	{ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS,	    \
+		PLAT_ARM_TZC_NS_DEV_ACCESS},				    \
+	{ARM_REALM_BASE, ARM_REALM_END, ARM_TZC_NS_DRAM_S_ACCESS,	    \
+		PLAT_ARM_TZC_NS_DEV_ACCESS},				    \
+	{ARM_DRAM2_BASE, ARM_DRAM2_END, ARM_TZC_NS_DRAM_S_ACCESS,	    \
+		PLAT_ARM_TZC_NS_DEV_ACCESS}
+
 #else
 #define ARM_TZC_REGIONS_DEF						\
-	{ARM_AP_TZC_DRAM1_BASE, ARM_EL3_TZC_DRAM1_END,			\
+	{ARM_AP_TZC_DRAM1_BASE, ARM_EL3_TZC_DRAM1_END + ARM_L1_GPT_SIZE,\
 		TZC_REGION_S_RDWR, 0},					\
 	{ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \
 		PLAT_ARM_TZC_NS_DEV_ACCESS},	 			\
@@ -153,7 +164,9 @@
 int arm_io_setup(void);
 
 /* Set image specification in IO block policy */
-int arm_set_image_source(unsigned int image_id, const char *part_name);
+int arm_set_image_source(unsigned int image_id, const char *part_name,
+			 uintptr_t *dev_handle, uintptr_t *image_spec);
+void arm_set_fip_addr(uint32_t active_fw_bank_idx);
 
 /* Security utility functions */
 void arm_tzc400_setup(uintptr_t tzc_base,
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 1def86e..434835e 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -16,6 +16,7 @@
 #if TRNG_SUPPORT
 #include "plat_trng.h"
 #endif
+#include <drivers/fwu/fwu_metadata.h>
 
 /*******************************************************************************
  * Forward declarations
@@ -140,6 +141,8 @@
 void plat_sdei_handle_masked_trigger(uint64_t mpidr, unsigned int intr);
 #endif
 
+void plat_default_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
+		void *handle, uint64_t flags);
 void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
 		void *handle, uint64_t flags);
 
@@ -349,4 +352,12 @@
  */
 int32_t plat_is_smccc_feature_available(u_register_t fid);
 
+/*******************************************************************************
+ * FWU platform specific functions
+ ******************************************************************************/
+int plat_fwu_set_metadata_image_source(unsigned int image_id,
+				       uintptr_t *dev_handle,
+				       uintptr_t *image_spec);
+void plat_fwu_set_images_source(struct fwu_metadata *metadata);
+
 #endif /* PLATFORM_H */
diff --git a/include/services/ffa_svc.h b/include/services/ffa_svc.h
index 5b39c42..85ff703 100644
--- a/include/services/ffa_svc.h
+++ b/include/services/ffa_svc.h
@@ -22,7 +22,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(0x85)
+#define FFA_FNUM_MAX_VALUE	U(0x87)
 #define is_ffa_fid(fid) __extension__ ({		\
 	__typeof__(fid) _fid = (fid);			\
 	((GET_SMC_NUM(_fid) >= FFA_FNUM_MIN_VALUE) &&	\
@@ -32,7 +32,7 @@
 #define FFA_VERSION_MAJOR		U(1)
 #define FFA_VERSION_MAJOR_SHIFT		16
 #define FFA_VERSION_MAJOR_MASK		U(0x7FFF)
-#define FFA_VERSION_MINOR		U(0)
+#define FFA_VERSION_MINOR		U(1)
 #define FFA_VERSION_MINOR_SHIFT		0
 #define FFA_VERSION_MINOR_MASK		U(0xFFFF)
 #define FFA_VERSION_BIT31_MASK 		U(0x1u << 31)
@@ -61,32 +61,44 @@
 		 ((func_num) << FUNCID_NUM_SHIFT))
 
 /* FFA function numbers */
-#define FFA_FNUM_ERROR			U(0x60)
-#define FFA_FNUM_SUCCESS		U(0x61)
-#define FFA_FNUM_INTERRUPT		U(0x62)
-#define FFA_FNUM_VERSION		U(0x63)
-#define FFA_FNUM_FEATURES		U(0x64)
-#define FFA_FNUM_RX_RELEASE		U(0x65)
-#define FFA_FNUM_RXTX_MAP		U(0x66)
-#define FFA_FNUM_RXTX_UNMAP		U(0x67)
-#define FFA_FNUM_PARTITION_INFO_GET	U(0x68)
-#define FFA_FNUM_ID_GET			U(0x69)
-#define FFA_FNUM_MSG_POLL		U(0x6A)
-#define FFA_FNUM_MSG_WAIT		U(0x6B)
-#define FFA_FNUM_MSG_YIELD		U(0x6C)
-#define FFA_FNUM_MSG_RUN		U(0x6D)
-#define FFA_FNUM_MSG_SEND		U(0x6E)
-#define FFA_FNUM_MSG_SEND_DIRECT_REQ	U(0x6F)
-#define FFA_FNUM_MSG_SEND_DIRECT_RESP	U(0x70)
-#define FFA_FNUM_MEM_DONATE		U(0x71)
-#define FFA_FNUM_MEM_LEND		U(0x72)
-#define FFA_FNUM_MEM_SHARE		U(0x73)
-#define FFA_FNUM_MEM_RETRIEVE_REQ	U(0x74)
-#define FFA_FNUM_MEM_RETRIEVE_RESP	U(0x75)
-#define FFA_FNUM_MEM_RELINQUISH	U(0x76)
-#define FFA_FNUM_MEM_RECLAIM		U(0x77)
-#define FFA_FNUM_SECONDARY_EP_REGISTER	U(0x84)
-#define FFA_FNUM_SPM_ID_GET		U(0x85)
+#define FFA_FNUM_ERROR				U(0x60)
+#define FFA_FNUM_SUCCESS			U(0x61)
+#define FFA_FNUM_INTERRUPT			U(0x62)
+#define FFA_FNUM_VERSION			U(0x63)
+#define FFA_FNUM_FEATURES			U(0x64)
+#define FFA_FNUM_RX_RELEASE			U(0x65)
+#define FFA_FNUM_RXTX_MAP			U(0x66)
+#define FFA_FNUM_RXTX_UNMAP			U(0x67)
+#define FFA_FNUM_PARTITION_INFO_GET		U(0x68)
+#define FFA_FNUM_ID_GET				U(0x69)
+#define FFA_FNUM_MSG_POLL			U(0x6A) /* Legacy FF-A v1.0 */
+#define FFA_FNUM_MSG_WAIT			U(0x6B)
+#define FFA_FNUM_MSG_YIELD			U(0x6C)
+#define FFA_FNUM_MSG_RUN			U(0x6D)
+#define FFA_FNUM_MSG_SEND			U(0x6E) /* Legacy FF-A v1.0 */
+#define FFA_FNUM_MSG_SEND_DIRECT_REQ		U(0x6F)
+#define FFA_FNUM_MSG_SEND_DIRECT_RESP		U(0x70)
+#define FFA_FNUM_MEM_DONATE			U(0x71)
+#define FFA_FNUM_MEM_LEND			U(0x72)
+#define FFA_FNUM_MEM_SHARE			U(0x73)
+#define FFA_FNUM_MEM_RETRIEVE_REQ		U(0x74)
+#define FFA_FNUM_MEM_RETRIEVE_RESP		U(0x75)
+#define FFA_FNUM_MEM_RELINQUISH			U(0x76)
+#define FFA_FNUM_MEM_RECLAIM			U(0x77)
+#define FFA_FNUM_NORMAL_WORLD_RESUME		U(0x7C)
+
+/* FF-A v1.1 */
+#define FFA_FNUM_NOTIFICATION_BITMAP_CREATE	U(0x7D)
+#define FFA_FNUM_NOTIFICATION_BITMAP_DESTROY	U(0x7E)
+#define FFA_FNUM_NOTIFICATION_BIND		U(0x7F)
+#define FFA_FNUM_NOTIFICATION_UNBIND		U(0x80)
+#define FFA_FNUM_NOTIFICATION_SET		U(0x81)
+#define FFA_FNUM_NOTIFICATION_GET		U(0x82)
+#define FFA_FNUM_NOTIFICATION_INFO_GET		U(0x83)
+#define FFA_FNUM_RX_ACQUIRE			U(0x84)
+#define FFA_FNUM_SPM_ID_GET			U(0x85)
+#define FFA_FNUM_MSG_SEND2			U(0x86)
+#define FFA_FNUM_SECONDARY_EP_REGISTER		U(0x87)
 
 /* FFA SMC32 FIDs */
 #define FFA_ERROR		FFA_FID(SMC_32, FFA_FNUM_ERROR)
@@ -116,6 +128,16 @@
 #define FFA_MEM_RETRIEVE_RESP	FFA_FID(SMC_32, FFA_FNUM_MEM_RETRIEVE_RESP)
 #define FFA_MEM_RELINQUISH	FFA_FID(SMC_32, FFA_FNUM_MEM_RELINQUISH)
 #define FFA_MEM_RECLAIM	FFA_FID(SMC_32, FFA_FNUM_MEM_RECLAIM)
+#define FFA_NOTIFICATION_BITMAP_CREATE	\
+	FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_BITMAP_CREATE)
+#define FFA_NOTIFICATION_BITMAP_DESTROY	\
+	FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_BITMAP_DESTROY)
+#define FFA_NOTIFICATION_BIND	FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_BIND)
+#define FFA_NOTIFICATION_UNBIND FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_UNBIND)
+#define FFA_NOTIFICATION_SET 	FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_SET)
+#define FFA_NOTIFICATION_GET 	FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_GET)
+#define FFA_NOTIFICATION_INFO_GET \
+	FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_INFO_GET)
 #define FFA_SPM_ID_GET		FFA_FID(SMC_32, FFA_FNUM_SPM_ID_GET)
 
 /* FFA SMC64 FIDs */
@@ -133,6 +155,8 @@
 	FFA_FID(SMC_64, FFA_FNUM_MEM_RETRIEVE_REQ)
 #define FFA_SECONDARY_EP_REGISTER_SMC64 \
 	FFA_FID(SMC_64, FFA_FNUM_SECONDARY_EP_REGISTER)
+#define FFA_NOTIFICATION_INFO_GET_SMC64 \
+	FFA_FID(SMC_64, FFA_FNUM_NOTIFICATION_INFO_GET)
 
 /*
  * Reserve a special value for traffic targeted to the Hypervisor or SPM.
diff --git a/include/services/gtsi_svc.h b/include/services/gtsi_svc.h
new file mode 100644
index 0000000..cb942ed
--- /dev/null
+++ b/include/services/gtsi_svc.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GTSI_SVC_H
+#define GTSI_SVC_H
+
+/* GTSI error codes. */
+#define GTSI_SUCCESS			0
+#define GTSI_ERROR_NOT_SUPPORTED	-1
+#define GTSI_ERROR_INVALID_ADDRESS	-2
+#define GTSI_ERROR_INVALID_PAS		-3
+
+/* The macros below are used to identify GTSI calls from the SMC function ID */
+#define GTSI_FNUM_MIN_VALUE	U(0x100)
+#define GTSI_FNUM_MAX_VALUE	U(0x101)
+#define is_gtsi_fid(fid) __extension__ ({		\
+	__typeof__(fid) _fid = (fid);			\
+	((GET_SMC_NUM(_fid) >= GTSI_FNUM_MIN_VALUE) &&	\
+	 (GET_SMC_NUM(_fid) <= GTSI_FNUM_MAX_VALUE)); })
+
+/* Get GTSI fastcall std FID from function number */
+#define GTSI_FID(smc_cc, func_num)			\
+	((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT)	|	\
+	 ((smc_cc) << FUNCID_CC_SHIFT)		|	\
+	 (OEN_STD_START << FUNCID_OEN_SHIFT)	|	\
+	 ((func_num) << FUNCID_NUM_SHIFT))
+
+#define GRAN_TRANS_TO_REALM_FNUM	U(0x100)
+#define GRAN_TRANS_TO_NS_FNUM		U(0x101)
+
+#define SMC_ASC_MARK_REALM	GTSI_FID(SMC_64, GRAN_TRANS_TO_REALM_FNUM)
+#define SMC_ASC_MARK_NONSECURE	GTSI_FID(SMC_64, GRAN_TRANS_TO_NS_FNUM)
+
+#define GRAN_TRANS_RET_BAD_ADDR		-2
+#define GRAN_TRANS_RET_BAD_PAS		-3
+
+#endif /* GTSI_SVC_H */
diff --git a/include/services/rmi_svc.h b/include/services/rmi_svc.h
new file mode 100644
index 0000000..9106f08
--- /dev/null
+++ b/include/services/rmi_svc.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RMI_SVC_H
+#define RMI_SVC_H
+
+#include <lib/smccc.h>
+#include <lib/utils_def.h>
+
+/* RMI error codes. */
+#define RMI_SUCCESS			0
+#define RMI_ERROR_NOT_SUPPORTED		-1
+#define RMI_ERROR_INVALID_ADDRESS	-2
+#define RMI_ERROR_INVALID_PAS		-3
+
+/* The macros below are used to identify RMI calls from the SMC function ID */
+#define RMI_FNUM_MIN_VALUE	U(0x00)
+#define RMI_FNUM_MAX_VALUE	U(0x20)
+#define is_rmi_fid(fid) __extension__ ({		\
+	__typeof__(fid) _fid = (fid);			\
+	((GET_SMC_NUM(_fid) >= RMI_FNUM_MIN_VALUE) &&	\
+	 (GET_SMC_NUM(_fid) <= RMI_FNUM_MAX_VALUE) &&	\
+	 (GET_SMC_TYPE(_fid) == SMC_TYPE_FAST)	   &&	\
+	 (GET_SMC_CC(_fid) == SMC_64)              &&	\
+	 (GET_SMC_OEN(_fid) == OEN_ARM_START)      &&	\
+	 ((_fid & 0x00FE0000) == 0U)); })
+
+/* Get RMI fastcall std FID from function number */
+#define RMI_FID(smc_cc, func_num)			\
+	((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT)	|	\
+	((smc_cc) << FUNCID_CC_SHIFT)		|	\
+	(OEN_ARM_START << FUNCID_OEN_SHIFT)	|	\
+	((func_num) << FUNCID_NUM_SHIFT))
+
+/*
+ * SMC_RMM_INIT_COMPLETE is the only function in the RMI that originates from
+ * the Realm world and is handled by the RMMD. The remaining functions are
+ * always invoked by the Normal world, forwarded by RMMD and handled by the
+ * RMM
+ */
+#define RMI_FNUM_REQ_COMPLETE		U(0x10)
+#define RMI_FNUM_VERSION_REQ		U(0x00)
+
+#define RMI_FNUM_GRAN_NS_REALM		U(0x01)
+#define RMI_FNUM_GRAN_REALM_NS		U(0x10)
+
+/* RMI SMC64 FIDs handled by the RMMD */
+#define RMI_RMM_REQ_COMPLETE		RMI_FID(SMC_64, RMI_FNUM_REQ_COMPLETE)
+#define RMI_RMM_REQ_VERSION		RMI_FID(SMC_64, RMI_FNUM_VERSION_REQ)
+
+#define RMI_RMM_GRANULE_DELEGATE	RMI_FID(SMC_64, RMI_FNUM_GRAN_NS_REALM)
+#define RMI_RMM_GRANULE_UNDELEGATE	RMI_FID(SMC_64, RMI_FNUM_GRAN_REALM_NS)
+
+
+#define RMI_ABI_VERSION_GET_MAJOR(_version) ((_version) >> 16)
+#define RMI_ABI_VERSION_GET_MINOR(_version) ((_version) & 0xFFFF)
+
+/* Reserve a special value for MBZ parameters. */
+#define RMI_PARAM_MBZ			U(0x0)
+
+#endif /* RMI_SVC_H */
diff --git a/include/services/rmmd_svc.h b/include/services/rmmd_svc.h
new file mode 100644
index 0000000..132973b
--- /dev/null
+++ b/include/services/rmmd_svc.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RMMD_SVC_H
+#define RMMD_SVC_H
+
+#ifndef __ASSEMBLER__
+#include <stdint.h>
+
+int rmmd_setup(void);
+uint64_t rmmd_rmi_handler(uint32_t smc_fid,
+		uint64_t x1,
+		uint64_t x2,
+		uint64_t x3,
+		uint64_t x4,
+		void *cookie,
+		void *handle,
+		uint64_t flags);
+
+uint64_t rmmd_gtsi_handler(uint32_t smc_fid,
+		uint64_t x1,
+		uint64_t x2,
+		uint64_t x3,
+		uint64_t x4,
+		void *cookie,
+		void *handle,
+		uint64_t flags);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* RMMD_SVC_H */
diff --git a/include/services/trp/platform_trp.h b/include/services/trp/platform_trp.h
new file mode 100644
index 0000000..b34da85
--- /dev/null
+++ b/include/services/trp/platform_trp.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_TRP_H
+#define PLATFORM_TRP_H
+
+/*******************************************************************************
+ * Mandatory TRP functions (only if platform contains a TRP)
+ ******************************************************************************/
+void trp_early_platform_setup(void);
+
+#endif /* PLATFORM_TRP_H */
diff --git a/include/tools_share/firmware_image_package.h b/include/tools_share/firmware_image_package.h
index dc65cc6..bd5b14b 100644
--- a/include/tools_share/firmware_image_package.h
+++ b/include/tools_share/firmware_image_package.h
@@ -38,6 +38,8 @@
 	{{0x8e,  0xa8, 0x7b, 0xb1}, {0xcf, 0xa2}, {0x3f, 0x4d}, 0x85, 0xfd, {0xe7, 0xbb, 0xa5, 0x02, 0x20, 0xd9} }
 #define UUID_NON_TRUSTED_FIRMWARE_BL33 \
 	{{0xd6,  0xd0, 0xee, 0xa7}, {0xfc, 0xea}, {0xd5, 0x4b}, 0x97, 0x82, {0x99, 0x34, 0xf2, 0x34, 0xb6, 0xe4} }
+#define UUID_REALM_MONITOR_MGMT_FIRMWARE \
+	{{0x6c,  0x07, 0x62, 0xa6}, {0x12, 0xf2}, {0x4b, 0x56}, 0x92, 0xcb, {0xba, 0x8f, 0x63, 0x36, 0x06, 0xd9} }
 /* Key certificates */
 #define UUID_ROT_KEY_CERT \
 	{{0x86,  0x2d, 0x1d, 0x72}, {0xf8, 0x60}, {0xe4, 0x11}, 0x92, 0x0b, {0x8b, 0xe7, 0x62, 0x16, 0x0f, 0x24} }
diff --git a/lib/aarch64/misc_helpers.S b/lib/aarch64/misc_helpers.S
index b6f6c9d..6e4d1fc 100644
--- a/lib/aarch64/misc_helpers.S
+++ b/lib/aarch64/misc_helpers.S
@@ -15,6 +15,7 @@
 	.globl	zero_normalmem
 	.globl	zeromem
 	.globl	memcpy16
+	.globl	gpt_tlbi_by_pa
 
 	.globl	disable_mmu_el1
 	.globl	disable_mmu_el3
@@ -162,7 +163,8 @@
 	 * Check for M bit (MMU enabled) of the current SCTLR_EL(1|3)
 	 * register value and panic if the MMU is disabled.
 	 */
-#if defined(IMAGE_BL1) || defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3)
+#if defined(IMAGE_BL1) || defined(IMAGE_BL31) || (defined(IMAGE_BL2) && \
+	(BL2_AT_EL3 || ENABLE_RME))
 	mrs	tmp1, sctlr_el3
 #else
 	mrs	tmp1, sctlr_el1
@@ -592,3 +594,20 @@
 	b.lo	1b
 	ret
 endfunc fixup_gdt_reloc
+
+/*
+ * TODO: Currently only supports size of 4KB,
+ * support other sizes as well.
+ */
+func gpt_tlbi_by_pa
+#if ENABLE_ASSERTIONS
+	cmp	x1, #PAGE_SIZE_4KB
+	ASM_ASSERT(eq)
+	tst	x0, #(PAGE_SIZE_MASK)
+	ASM_ASSERT(eq)
+#endif
+	lsr	x0, x0, #FOUR_KB_SHIFT	/* 4KB size encoding is zero */
+	sys	#6, c8, c4, #3, x0 	/* TLBI RPAOS, <Xt> */
+	dsb	sy
+	ret
+endfunc gpt_tlbi_by_pa
diff --git a/lib/cpus/aarch64/cortex_a710.S b/lib/cpus/aarch64/cortex_a710.S
index 4f979f8..7d7fbd8 100644
--- a/lib/cpus/aarch64/cortex_a710.S
+++ b/lib/cpus/aarch64/cortex_a710.S
@@ -21,6 +21,201 @@
 #error "Cortex A710 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+/* --------------------------------------------------
+ * Errata Workaround for Cortex-A710 Erratum 1987031.
+ * This applies to revision r0p0, r1p0 and r2p0 of Cortex-A710. It is still
+ * open.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_a710_1987031_wa
+	/* Check revision. */
+	mov	x17, x30
+	bl	check_errata_1987031
+	cbz	x0, 1f
+
+	/* Apply instruction patching sequence */
+	ldr x0,=0x6
+	msr S3_6_c15_c8_0,x0
+	ldr x0,=0xF3A08002
+	msr S3_6_c15_c8_2,x0
+	ldr x0,=0xFFF0F7FE
+	msr S3_6_c15_c8_3,x0
+	ldr x0,=0x40000001003ff
+	msr S3_6_c15_c8_1,x0
+	ldr x0,=0x7
+	msr S3_6_c15_c8_0,x0
+	ldr x0,=0xBF200000
+	msr S3_6_c15_c8_2,x0
+	ldr x0,=0xFFEF0000
+	msr S3_6_c15_c8_3,x0
+	ldr x0,=0x40000001003f3
+	msr S3_6_c15_c8_1,x0
+	isb
+1:
+	ret	x17
+endfunc errata_a710_1987031_wa
+
+func check_errata_1987031
+	/* Applies to r0p0, r1p0 and r2p0 */
+	mov	x1, #0x20
+	b	cpu_rev_var_ls
+endfunc check_errata_1987031
+
+/* --------------------------------------------------
+ * Errata Workaround for Cortex-A710 Erratum 2081180.
+ * This applies to revision r0p0, r1p0 and r2p0 of Cortex-A710.
+ * It is still open.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_a710_2081180_wa
+	/* Check revision. */
+	mov	x17, x30
+	bl	check_errata_2081180
+	cbz	x0, 1f
+
+	/* Apply instruction patching sequence */
+	ldr	x0,=0x3
+	msr	S3_6_c15_c8_0,x0
+	ldr	x0,=0xF3A08002
+	msr	S3_6_c15_c8_2,x0
+	ldr	x0,=0xFFF0F7FE
+	msr	S3_6_c15_c8_3,x0
+	ldr	x0,=0x10002001003FF
+	msr	S3_6_c15_c8_1,x0
+	ldr	x0,=0x4
+	msr	S3_6_c15_c8_0,x0
+	ldr	x0,=0xBF200000
+	msr	S3_6_c15_c8_2,x0
+	ldr	x0,=0xFFEF0000
+	msr	S3_6_c15_c8_3,x0
+	ldr	x0,=0x10002001003F3
+	msr	S3_6_c15_c8_1,x0
+	isb
+1:
+	ret	x17
+endfunc errata_a710_2081180_wa
+
+func check_errata_2081180
+	/* Applies to r0p0, r1p0 and r2p0 */
+	mov	x1, #0x20
+	b	cpu_rev_var_ls
+endfunc check_errata_2081180
+
+/* ---------------------------------------------------------------------
+ * Errata Workaround for Cortex-A710 Erratum 2055002.
+ * This applies to revision r1p0, r2p0 of Cortex-A710 and is still open.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * ---------------------------------------------------------------------
+ */
+func errata_a710_2055002_wa
+	/* Compare x0 against revision r2p0 */
+	mov	x17, x30
+	bl	check_errata_2055002
+	cbz	x0, 1f
+	mrs	x1, CORTEX_A710_CPUACTLR_EL1
+	orr	x1, x1, CORTEX_A710_CPUACTLR_EL1_BIT_46
+	msr	CORTEX_A710_CPUACTLR_EL1, x1
+1:
+	ret	x17
+endfunc errata_a710_2055002_wa
+
+func check_errata_2055002
+	/* Applies to r1p0, r2p0 */
+	mov	x1, #0x20
+	b	cpu_rev_var_ls
+endfunc check_errata_2055002
+
+/* -------------------------------------------------------------
+ * Errata Workaround for Cortex-A710 Erratum 2017096.
+ * This applies to revisions r0p0, r1p0 and r2p0 of Cortex-A710.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * -------------------------------------------------------------
+ */
+func errata_a710_2017096_wa
+	/* Compare x0 against revision r0p0 to r2p0 */
+	mov     x17, x30
+	bl      check_errata_2017096
+	cbz     x0, 1f
+	mrs     x1, CORTEX_A710_CPUECTLR_EL1
+	orr     x1, x1, CORTEX_A710_CPUECTLR_EL1_PFSTIDIS_BIT
+	msr     CORTEX_A710_CPUECTLR_EL1, x1
+
+1:
+	ret     x17
+endfunc errata_a710_2017096_wa
+
+func check_errata_2017096
+	/* Applies to r0p0, r1p0, r2p0 */
+	mov     x1, #0x20
+	b       cpu_rev_var_ls
+endfunc check_errata_2017096
+
+
+/* ---------------------------------------------------------------------
+ * Errata Workaround for Cortex-A710 Erratum 2083908.
+ * This applies to revision r2p0 of Cortex-A710 and is still open.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * ---------------------------------------------------------------------
+ */
+func errata_a710_2083908_wa
+	/* Compare x0 against revision r2p0 */
+	mov	x17, x30
+	bl	check_errata_2083908
+	cbz	x0, 1f
+	mrs	x1, CORTEX_A710_CPUACTLR5_EL1
+	orr	x1, x1, CORTEX_A710_CPUACTLR5_EL1_BIT_13
+	msr	CORTEX_A710_CPUACTLR5_EL1, x1
+1:
+	ret	x17
+endfunc errata_a710_2083908_wa
+
+func check_errata_2083908
+	/* Applies to r2p0 */
+	mov	x1, #CPU_REV(2, 0)
+	mov	x2, #CPU_REV(2, 0)
+	b	cpu_rev_var_range
+endfunc check_errata_2083908
+
+/* ---------------------------------------------------------------------
+ * Errata Workaround for Cortex-A710 Erratum 2058056.
+ * This applies to revisions r0p0, r1p0 and r2p0 of Cortex-A710 and is still
+ * open.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * ---------------------------------------------------------------------
+ */
+func errata_a710_2058056_wa
+	/* Compare x0 against revision r2p0 */
+	mov	x17, x30
+	bl	check_errata_2058056
+	cbz	x0, 1f
+	mrs	x1, CORTEX_A710_CPUECTLR2_EL1
+	mov	x0, #CORTEX_A710_CPUECTLR2_EL1_PF_MODE_CNSRV
+	bfi	x1, x0, #CPUECTLR2_EL1_PF_MODE_LSB, #CPUECTLR2_EL1_PF_MODE_WIDTH
+	msr	CORTEX_A710_CPUECTLR2_EL1, x1
+1:
+	ret	x17
+endfunc errata_a710_2058056_wa
+
+func check_errata_2058056
+	/* Applies to r0p0, r1p0 and r2p0 */
+	mov	x1, #0x20
+	b	cpu_rev_var_ls
+endfunc check_errata_2058056
+
 	/* ----------------------------------------------------
 	 * HW will do the cache maintenance while powering down
 	 * ----------------------------------------------------
@@ -37,20 +232,72 @@
 	ret
 endfunc cortex_a710_core_pwr_dwn
 
+#if REPORT_ERRATA
 	/*
-	 * Errata printing function for Cortex A710. Must follow AAPCS.
+	 * Errata printing function for Cortex-A710. Must follow AAPCS.
 	 */
-#if REPORT_ERRATA
 func cortex_a710_errata_report
+	stp	x8, x30, [sp, #-16]!
+
+	bl	cpu_get_rev_var
+	mov	x8, x0
+
+	/*
+	 * Report all errata. The revision-variant information is passed to
+	 * checking functions of each errata.
+	 */
+	report_errata ERRATA_A710_1987031, cortex_a710, 1987031
+	report_errata ERRATA_A710_2081180, cortex_a710, 2081180
+	report_errata ERRATA_A710_2055002, cortex_a710, 2055002
+	report_errata ERRATA_A710_2017096, cortex_a710, 2017096
+	report_errata ERRATA_A710_2083908, cortex_a710, 2083908
+	report_errata ERRATA_A710_2058056, cortex_a710, 2058056
+
+	ldp	x8, x30, [sp], #16
 	ret
 endfunc cortex_a710_errata_report
 #endif
 
 func cortex_a710_reset_func
+	mov	x19, x30
+
 	/* Disable speculative loads */
 	msr	SSBS, xzr
+
+	bl	cpu_get_rev_var
+	mov	x18, x0
+
+#if ERRATA_A710_1987031
+	mov	x0, x18
+	bl	errata_a710_1987031_wa
+#endif
+
+#if ERRATA_A710_2081180
+	mov	x0, x18
+	bl	errata_a710_2081180_wa
+#endif
+
+#if ERRATA_A710_2055002
+	mov	x0, x18
+	bl	errata_a710_2055002_wa
+#endif
+
+#if ERRATA_A710_2017096
+	mov	x0, x18
+	bl	errata_a710_2017096_wa
+#endif
+
+#if ERRATA_A710_2083908
+	mov	x0, x18
+	bl	errata_a710_2083908_wa
+#endif
+
+#if ERRATA_A710_2058056
+	mov	x0, x18
+	bl	errata_a710_2058056_wa
+#endif
 	isb
-	ret
+	ret	x19
 endfunc cortex_a710_reset_func
 
 	/* ---------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a78.S b/lib/cpus/aarch64/cortex_a78.S
index 8c5a45a..4e8a228 100644
--- a/lib/cpus/aarch64/cortex_a78.S
+++ b/lib/cpus/aarch64/cortex_a78.S
@@ -154,6 +154,79 @@
 	b	cpu_rev_var_ls
 endfunc check_errata_1821534
 
+/* --------------------------------------------------
+ * Errata Workaround for Cortex A78 Errata 1952683.
+ * This applies to revision r0p0.
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_a78_1952683_wa
+	/* Check revision. */
+	mov	x17, x30
+	bl	check_errata_1952683
+	cbz	x0, 1f
+
+	ldr	x0,=0x5
+	msr	S3_6_c15_c8_0,x0
+	ldr	x0,=0xEEE10A10
+	msr	S3_6_c15_c8_2,x0
+	ldr	x0,=0xFFEF0FFF
+	msr	S3_6_c15_c8_3,x0
+	ldr	x0,=0x0010F000
+	msr	S3_6_c15_c8_4,x0
+	ldr	x0,=0x0010F000
+	msr	S3_6_c15_c8_5,x0
+	ldr	x0,=0x40000080023ff
+	msr	S3_6_c15_c8_1,x0
+	ldr	x0,=0x6
+	msr	S3_6_c15_c8_0,x0
+	ldr	x0,=0xEE640F34
+	msr	S3_6_c15_c8_2,x0
+	ldr	x0,=0xFFEF0FFF
+	msr	S3_6_c15_c8_3,x0
+	ldr	x0,=0x40000080023ff
+	msr	S3_6_c15_c8_1,x0
+	isb
+1:
+	ret	x17
+endfunc errata_a78_1952683_wa
+
+func check_errata_1952683
+	/* Applies to r0p0 only */
+	mov	x1, #0x00
+	b	cpu_rev_var_ls
+endfunc check_errata_1952683
+
+/* --------------------------------------------------
+ * Errata Workaround for Cortex A78 Errata 2132060.
+ * This applies to revisions r0p0, r1p0, r1p1, and r1p2.
+ * It is still open.
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x1, x17
+ * --------------------------------------------------
+ */
+func errata_a78_2132060_wa
+	/* Check revision. */
+	mov	x17, x30
+	bl	check_errata_2132060
+	cbz	x0, 1f
+
+	/* Apply the workaround. */
+	mrs	x1, CORTEX_A78_CPUECTLR_EL1
+	mov	x0, #CORTEX_A78_CPUECTLR_EL1_PF_MODE_CNSRV
+	bfi	x1, x0, #CPUECTLR_EL1_PF_MODE_LSB, #CPUECTLR_EL1_PF_MODE_WIDTH
+	msr	CORTEX_A78_CPUECTLR_EL1, x1
+1:
+	ret	x17
+endfunc errata_a78_2132060_wa
+
+func check_errata_2132060
+	/* Applies to r0p0, r0p1, r1p1, and r1p2 */
+	mov	x1, #0x12
+	b	cpu_rev_var_ls
+endfunc check_errata_2132060
+
 	/* -------------------------------------------------
 	 * The CPU Ops reset function for Cortex-A78
 	 * -------------------------------------------------
@@ -183,6 +256,16 @@
 	bl	errata_a78_1821534_wa
 #endif
 
+#if ERRATA_A78_1952683
+	mov	x0, x18
+	bl	errata_a78_1952683_wa
+#endif
+
+#if ERRATA_A78_2132060
+	mov	x0, x18
+	bl	errata_a78_2132060_wa
+#endif
+
 #if ENABLE_AMU
 	/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
 	mrs	x0, actlr_el3
@@ -241,6 +324,8 @@
 	report_errata ERRATA_A78_1941498, cortex_a78, 1941498
 	report_errata ERRATA_A78_1951500, cortex_a78, 1951500
 	report_errata ERRATA_A78_1821534, cortex_a78, 1821534
+	report_errata ERRATA_A78_1952683, cortex_a78, 1952683
+	report_errata ERRATA_A78_2132060, cortex_a78, 2132060
 
 	ldp	x8, x30, [sp], #16
 	ret
diff --git a/lib/cpus/aarch64/cortex_a78_ae.S b/lib/cpus/aarch64/cortex_a78_ae.S
index 9aff9ac..421c174 100644
--- a/lib/cpus/aarch64/cortex_a78_ae.S
+++ b/lib/cpus/aarch64/cortex_a78_ae.S
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,12 +17,108 @@
 #error "cortex_a78_ae must be compiled with HW_ASSISTED_COHERENCY enabled"
 #endif
 
+/* --------------------------------------------------
+ * Errata Workaround for A78 AE Erratum 1941500.
+ * This applies to revisions r0p0 and r0p1 of A78 AE.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_a78_ae_1941500_wa
+	/* Compare x0 against revisions r0p0 - r0p1 */
+	mov	x17, x30
+	bl	check_errata_1941500
+	cbz	x0, 1f
+
+	/* Set bit 8 in ECTLR_EL1 */
+	mrs	x0, CORTEX_A78_AE_CPUECTLR_EL1
+	bic	x0, x0, #CORTEX_A78_AE_CPUECTLR_EL1_BIT_8
+	msr	CORTEX_A78_AE_CPUECTLR_EL1, x0
+	isb
+1:
+	ret	x17
+endfunc errata_a78_ae_1941500_wa
+
+func check_errata_1941500
+	/* Applies to revisions r0p0 and r0p1. */
+	mov	x1, #CPU_REV(0, 0)
+	mov	x2, #CPU_REV(0, 1)
+	b	cpu_rev_var_range
+endfunc check_errata_1941500
+
+/* --------------------------------------------------
+ * Errata Workaround for A78 AE Erratum 1951502.
+ * This applies to revisions r0p0 and r0p1 of A78 AE.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_a78_ae_1951502_wa
+	/* Compare x0 against revisions r0p0 - r0p1 */
+	mov	x17, x30
+	bl	check_errata_1951502
+	cbz	x0, 1f
+
+	msr	S3_6_c15_c8_0, xzr
+	ldr	x0, =0x10E3900002
+	msr	S3_6_c15_c8_2, x0
+	ldr	x0, =0x10FFF00083
+	msr	S3_6_c15_c8_3, x0
+	ldr	x0, =0x2001003FF
+	msr	S3_6_c15_c8_1, x0
+
+	mov	x0, #1
+	msr	S3_6_c15_c8_0, x0
+	ldr	x0, =0x10E3800082
+	msr	S3_6_c15_c8_2, x0
+	ldr	x0, =0x10FFF00083
+	msr	S3_6_c15_c8_3, x0
+	ldr	x0, =0x2001003FF
+	msr	S3_6_c15_c8_1, x0
+
+	mov	x0, #2
+	msr	S3_6_c15_c8_0, x0
+	ldr	x0, =0x10E3800200
+	msr	S3_6_c15_c8_2, x0
+	ldr	x0, =0x10FFF003E0
+	msr	S3_6_c15_c8_3, x0
+	ldr	x0, =0x2001003FF
+	msr	S3_6_c15_c8_1, x0
+
+	isb
+1:
+	ret	x17
+endfunc errata_a78_ae_1951502_wa
+
+func check_errata_1951502
+	/* Applies to revisions r0p0 and r0p1. */
+	mov	x1, #CPU_REV(0, 0)
+	mov	x2, #CPU_REV(0, 1)
+	b	cpu_rev_var_range
+endfunc check_errata_1951502
+
 	/* -------------------------------------------------
 	 * The CPU Ops reset function for Cortex-A78-AE
 	 * -------------------------------------------------
 	 */
-#if ENABLE_AMU
 func cortex_a78_ae_reset_func
+	mov	x19, x30
+	bl	cpu_get_rev_var
+	mov	x18, x0
+
+#if ERRATA_A78_AE_1941500
+	mov	x0, x18
+	bl	errata_a78_ae_1941500_wa
+#endif
+
+#if ERRATA_A78_AE_1951502
+	mov	x0, x18
+	bl	errata_a78_ae_1951502_wa
+#endif
+
+#if ENABLE_AMU
 	/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
 	mrs	x0, actlr_el3
 	bic	x0, x0, #CORTEX_A78_ACTLR_TAM_BIT
@@ -39,11 +136,12 @@
 	/* Enable group1 counters */
 	mov	x0, #CORTEX_A78_AMU_GROUP1_MASK
 	msr	CPUAMCNTENSET1_EL0, x0
+#endif
+
 	isb
 
-	ret
+	ret	x19
 endfunc cortex_a78_ae_reset_func
-#endif
 
 	/* -------------------------------------------------------
 	 * HW will do the cache maintenance while powering down
@@ -66,6 +164,19 @@
 	 */
 #if REPORT_ERRATA
 func cortex_a78_ae_errata_report
+	stp	x8, x30, [sp, #-16]!
+
+	bl	cpu_get_rev_var
+	mov	x8, x0
+
+	/*
+	 * Report all errata. The revision-variant information is passed to
+	 * checking functions of each errata.
+	 */
+	report_errata ERRATA_A78_AE_1941500, cortex_a78_ae, 1941500
+	report_errata ERRATA_A78_AE_1951502, cortex_a78_ae, 1951502
+
+	ldp	x8, x30, [sp], #16
 	ret
 endfunc cortex_a78_ae_errata_report
 #endif
@@ -89,12 +200,6 @@
 	ret
 endfunc cortex_a78_ae_cpu_reg_dump
 
-#if ENABLE_AMU
-#define A78_AE_RESET_FUNC cortex_a78_ae_reset_func
-#else
-#define A78_AE_RESET_FUNC CPU_NO_RESET_FUNC
-#endif
-
 declare_cpu_ops cortex_a78_ae, CORTEX_A78_AE_MIDR, \
-	A78_AE_RESET_FUNC, \
+	cortex_a78_ae_reset_func, \
 	cortex_a78_ae_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_demeter.S b/lib/cpus/aarch64/cortex_demeter.S
new file mode 100644
index 0000000..9ad8b86
--- /dev/null
+++ b/lib/cpus/aarch64/cortex_demeter.S
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <cortex_demeter.h>
+#include <cpu_macros.S>
+#include <plat_macros.S>
+
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "Cortex Demeter must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
+/* 64-bit only core */
+#if CTX_INCLUDE_AARCH32_REGS == 1
+#error "Cortex Demeter supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
+#endif
+
+	/* ----------------------------------------------------
+	 * HW will do the cache maintenance while powering down
+	 * ----------------------------------------------------
+	 */
+func cortex_demeter_core_pwr_dwn
+	/* ---------------------------------------------------
+	 * Enable CPU power down bit in power control register
+	 * ---------------------------------------------------
+	 */
+	mrs	x0, CORTEX_DEMETER_CPUPWRCTLR_EL1
+	orr	x0, x0, #CORTEX_DEMETER_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
+	msr	CORTEX_DEMETER_CPUPWRCTLR_EL1, x0
+	isb
+	ret
+endfunc cortex_demeter_core_pwr_dwn
+
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Cortex Demeter. Must follow AAPCS.
+ */
+func cortex_demeter_errata_report
+	ret
+endfunc cortex_demeter_errata_report
+#endif
+
+func cortex_demeter_reset_func
+	/* Disable speculative loads */
+	msr	SSBS, xzr
+	isb
+	ret
+endfunc cortex_demeter_reset_func
+
+	/* ---------------------------------------------
+	 * This function provides Cortex Demeter-
+	 * specific register information for crash
+	 * reporting. It needs to return with x6
+	 * pointing to a list of register names in ascii
+	 * and x8 - x15 having values of registers to be
+	 * reported.
+	 * ---------------------------------------------
+	 */
+.section .rodata.cortex_demeter_regs, "aS"
+cortex_demeter_regs:  /* The ascii list of register names to be reported */
+	.asciz	"cpuectlr_el1", ""
+
+func cortex_demeter_cpu_reg_dump
+	adr	x6, cortex_demeter_regs
+	mrs	x8, CORTEX_DEMETER_CPUECTLR_EL1
+	ret
+endfunc cortex_demeter_cpu_reg_dump
+
+declare_cpu_ops cortex_demeter, CORTEX_DEMETER_MIDR, \
+	cortex_demeter_reset_func, \
+	cortex_demeter_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_hayes.S b/lib/cpus/aarch64/cortex_hayes.S
new file mode 100644
index 0000000..445a691
--- /dev/null
+++ b/lib/cpus/aarch64/cortex_hayes.S
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <cortex_hayes.h>
+#include <cpu_macros.S>
+#include <plat_macros.S>
+
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "Cortex Hayes must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
+/* 64-bit only core */
+#if CTX_INCLUDE_AARCH32_REGS == 1
+#error "Cortex Hayes supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
+#endif
+
+	/* ----------------------------------------------------
+	 * HW will do the cache maintenance while powering down
+	 * ----------------------------------------------------
+	 */
+func cortex_hayes_core_pwr_dwn
+	/* ---------------------------------------------------
+	 * Enable CPU power down bit in power control register
+	 * ---------------------------------------------------
+	 */
+	mrs	x0, CORTEX_HAYES_CPUPWRCTLR_EL1
+	orr	x0, x0, #CORTEX_HAYES_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
+	msr	CORTEX_HAYES_CPUPWRCTLR_EL1, x0
+	isb
+	ret
+endfunc cortex_hayes_core_pwr_dwn
+
+	/*
+	 * Errata printing function for Cortex Hayes. Must follow AAPCS.
+	 */
+#if REPORT_ERRATA
+func cortex_hayes_errata_report
+	ret
+endfunc cortex_hayes_errata_report
+#endif
+
+func cortex_hayes_reset_func
+	/* Disable speculative loads */
+	msr	SSBS, xzr
+	isb
+	ret
+endfunc cortex_hayes_reset_func
+
+	/* ---------------------------------------------
+	 * This function provides Cortex Hayes specific
+	 * register information for crash reporting.
+	 * It needs to return with x6 pointing to
+	 * a list of register names in ascii and
+	 * x8 - x15 having values of registers to be
+	 * reported.
+	 * ---------------------------------------------
+	 */
+.section .rodata.cortex_hayes_regs, "aS"
+cortex_hayes_regs:  /* The ascii list of register names to be reported */
+	.asciz	"cpuectlr_el1", ""
+
+func cortex_hayes_cpu_reg_dump
+	adr	x6, cortex_hayes_regs
+	mrs	x8, CORTEX_HAYES_CPUECTLR_EL1
+	ret
+endfunc cortex_hayes_cpu_reg_dump
+
+declare_cpu_ops cortex_hayes, CORTEX_HAYES_MIDR, \
+	cortex_hayes_reset_func, \
+	cortex_hayes_core_pwr_dwn
diff --git a/lib/cpus/aarch64/neoverse_n2.S b/lib/cpus/aarch64/neoverse_n2.S
index 8d646cb..330cc59 100644
--- a/lib/cpus/aarch64/neoverse_n2.S
+++ b/lib/cpus/aarch64/neoverse_n2.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,11 +19,206 @@
 #error "Neoverse-N2 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
-	/* -------------------------------------------------
+/* --------------------------------------------------
+ * Errata Workaround for Neoverse N2 Erratum 2002655.
+ * This applies to revision r0p0 of Neoverse N2. it is still open.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_n2_2002655_wa
+	/* Check revision. */
+	mov	x17, x30
+	bl	check_errata_2002655
+	cbz	x0, 1f
+
+	/* Apply instruction patching sequence */
+	ldr x0,=0x6
+	msr S3_6_c15_c8_0,x0
+	ldr x0,=0xF3A08002
+	msr S3_6_c15_c8_2,x0
+	ldr x0,=0xFFF0F7FE
+	msr S3_6_c15_c8_3,x0
+	ldr x0,=0x40000001003ff
+	msr S3_6_c15_c8_1,x0
+	ldr x0,=0x7
+	msr S3_6_c15_c8_0,x0
+	ldr x0,=0xBF200000
+	msr S3_6_c15_c8_2,x0
+	ldr x0,=0xFFEF0000
+	msr S3_6_c15_c8_3,x0
+	ldr x0,=0x40000001003f3
+	msr S3_6_c15_c8_1,x0
+	isb
+1:
+	ret	x17
+endfunc errata_n2_2002655_wa
+
+func check_errata_2002655
+	/* Applies to r0p0 */
+	mov	x1, #0x00
+	b	cpu_rev_var_ls
+endfunc check_errata_2002655
+
+/* ---------------------------------------------------------------
+ * Errata Workaround for Neoverse N2 Erratum 2067956.
+ * This applies to revision r0p0 of Neoverse N2 and is still open.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * ---------------------------------------------------------------
+ */
+func errata_n2_2067956_wa
+	/* Compare x0 against revision r0p0 */
+	mov	x17, x30
+	bl	check_errata_2067956
+	cbz	x0, 1f
+	mrs	x1, NEOVERSE_N2_CPUACTLR_EL1
+	orr	x1, x1, NEOVERSE_N2_CPUACTLR_EL1_BIT_46
+	msr	NEOVERSE_N2_CPUACTLR_EL1, x1
+1:
+	ret	x17
+endfunc errata_n2_2067956_wa
+
+func check_errata_2067956
+	/* Applies to r0p0 */
+	mov	x1, #0x00
+	b	cpu_rev_var_ls
+endfunc check_errata_2067956
+
+/* ---------------------------------------------------------------
+ * Errata Workaround for Neoverse N2 Erratum 2025414.
+ * This applies to revision r0p0 of Neoverse N2 and is still open.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * ---------------------------------------------------------------
+ */
+func errata_n2_2025414_wa
+	/* Compare x0 against revision r0p0 */
+	mov     x17, x30
+	bl      check_errata_2025414
+	cbz     x0, 1f
+	mrs     x1, NEOVERSE_N2_CPUECTLR_EL1
+	orr     x1, x1, NEOVERSE_N2_CPUECTLR_EL1_PFSTIDIS_BIT
+	msr     NEOVERSE_N2_CPUECTLR_EL1, x1
+
+1:
+	ret     x17
+endfunc errata_n2_2025414_wa
+
+func check_errata_2025414
+	/* Applies to r0p0 */
+	mov     x1, #0x00
+	b       cpu_rev_var_ls
+endfunc check_errata_2025414
+
+/* ---------------------------------------------------------------
+ * Errata Workaround for Neoverse N2 Erratum 2189731.
+ * This applies to revision r0p0 of Neoverse N2 and is still open.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * ---------------------------------------------------------------
+ */
+func errata_n2_2189731_wa
+	/* Compare x0 against revision r0p0 */
+	mov     x17, x30
+	bl      check_errata_2189731
+	cbz     x0, 1f
+	mrs     x1, NEOVERSE_N2_CPUACTLR5_EL1
+	orr     x1, x1, NEOVERSE_N2_CPUACTLR5_EL1_BIT_44
+	msr     NEOVERSE_N2_CPUACTLR5_EL1, x1
+
+1:
+	ret     x17
+endfunc errata_n2_2189731_wa
+
+func check_errata_2189731
+	/* Applies to r0p0 */
+	mov     x1, #0x00
+	b       cpu_rev_var_ls
+endfunc check_errata_2189731
+
+/* --------------------------------------------------
+ * Errata Workaround for Neoverse N2 Erratum 2138956.
+ * This applies to revision r0p0 of Neoverse N2. it is still open.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_n2_2138956_wa
+	/* Check revision. */
+	mov	x17, x30
+	bl	check_errata_2138956
+	cbz	x0, 1f
+
+	/* Apply instruction patching sequence */
+	ldr	x0,=0x3
+	msr	S3_6_c15_c8_0,x0
+	ldr	x0,=0xF3A08002
+	msr	S3_6_c15_c8_2,x0
+	ldr	x0,=0xFFF0F7FE
+	msr	S3_6_c15_c8_3,x0
+	ldr	x0,=0x10002001003FF
+	msr	S3_6_c15_c8_1,x0
+	ldr	x0,=0x4
+	msr	S3_6_c15_c8_0,x0
+	ldr	x0,=0xBF200000
+	msr	S3_6_c15_c8_2,x0
+	ldr	x0,=0xFFEF0000
+	msr	S3_6_c15_c8_3,x0
+	ldr	x0,=0x10002001003F3
+	msr	S3_6_c15_c8_1,x0
+	isb
+1:
+	ret	x17
+endfunc errata_n2_2138956_wa
+
+func check_errata_2138956
+	/* Applies to r0p0 */
+	mov	x1, #0x00
+	b	cpu_rev_var_ls
+endfunc check_errata_2138956
+
+/* --------------------------------------------------
+ * Errata Workaround for Neoverse N2 Erratum 2138953.
+ * This applies to revision r0p0 of Neoverse N2. it is still open.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x1, x17
+ * --------------------------------------------------
+ */
+func errata_n2_2138953_wa
+	/* Check revision. */
+	mov	x17, x30
+	bl	check_errata_2138953
+	cbz	x0, 1f
+
+	/* Apply instruction patching sequence */
+	mrs	x1, NEOVERSE_N2_CPUECTLR2_EL1
+	mov	x0, #NEOVERSE_N2_CPUECTLR2_EL1_PF_MODE_CNSRV
+	bfi	x1, x0, #CPUECTLR2_EL1_PF_MODE_LSB, #CPUECTLR2_EL1_PF_MODE_WIDTH
+	msr	NEOVERSE_N2_CPUECTLR2_EL1, x1
+1:
+	ret	x17
+endfunc errata_n2_2138953_wa
+
+func check_errata_2138953
+	/* Applies to r0p0 */
+	mov	x1, #0x00
+	b	cpu_rev_var_ls
+endfunc check_errata_2138953
+
+	/* -------------------------------------------
 	 * The CPU Ops reset function for Neoverse N2.
-	 * -------------------------------------------------
+	 * -------------------------------------------
 	 */
 func neoverse_n2_reset_func
+	mov	x19, x30
+
 	/* Check if the PE implements SSBS */
 	mrs	x0, id_aa64pfr1_el1
 	tst	x0, #(ID_AA64PFR1_EL1_SSBS_MASK << ID_AA64PFR1_EL1_SSBS_SHIFT)
@@ -37,6 +232,32 @@
 	orr	x0, x0, #NEOVERSE_N2_CPUACTLR2_EL1_BIT_2
 	msr	NEOVERSE_N2_CPUACTLR2_EL1, x0
 
+#if ERRATA_N2_2067956
+	mov	x0, x18
+	bl	errata_n2_2067956_wa
+#endif
+
+#if ERRATA_N2_2025414
+	mov     x0, x18
+	bl      errata_n2_2025414_wa
+#endif
+
+#if ERRATA_N2_2189731
+	mov     x0, x18
+	bl      errata_n2_2189731_wa
+#endif
+
+
+#if ERRATA_N2_2138956
+	mov	x0, x18
+	bl	errata_n2_2138956_wa
+#endif
+
+#if ERRATA_N2_2138953
+	mov	x0, x18
+	bl	errata_n2_2138953_wa
+#endif
+
 #if ENABLE_AMU
 	/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
 	mrs	x0, cptr_el3
@@ -53,20 +274,28 @@
 
 #if NEOVERSE_Nx_EXTERNAL_LLC
 	/* Some systems may have External LLC, core needs to be made aware */
-	mrs     x0, NEOVERSE_N2_CPUECTLR_EL1
-	orr     x0, x0, NEOVERSE_N2_CPUECTLR_EL1_EXTLLC_BIT
-	msr     NEOVERSE_N2_CPUECTLR_EL1, x0
+	mrs	x0, NEOVERSE_N2_CPUECTLR_EL1
+	orr	x0, x0, NEOVERSE_N2_CPUECTLR_EL1_EXTLLC_BIT
+	msr	NEOVERSE_N2_CPUECTLR_EL1, x0
+#endif
+
+	bl	cpu_get_rev_var
+	mov	x18, x0
+
+#if ERRATA_N2_2002655
+	mov	x0, x18
+	bl	errata_n2_2002655_wa
 #endif
 
 	isb
-	ret
+	ret	x19
 endfunc neoverse_n2_reset_func
 
 func neoverse_n2_core_pwr_dwn
-	/* ---------------------------------------------
+	/* ---------------------------------------------------
 	 * Enable CPU power down bit in power control register
 	 * No need to do cache maintenance here.
-	 * ---------------------------------------------
+	 * ---------------------------------------------------
 	 */
 	mrs	x0, NEOVERSE_N2_CPUPWRCTLR_EL1
 	orr	x0, x0, #NEOVERSE_N2_CORE_PWRDN_EN_BIT
@@ -80,7 +309,23 @@
  * Errata printing function for Neoverse N2 cores. Must follow AAPCS.
  */
 func neoverse_n2_errata_report
-	/* No errata reported for Neoverse N2 cores */
+	stp	x8, x30, [sp, #-16]!
+
+	bl	cpu_get_rev_var
+	mov	x8, x0
+
+	/*
+	 * Report all errata. The revision-variant information is passed to
+	 * checking functions of each errata.
+	 */
+	report_errata ERRATA_N2_2002655, neoverse_n2, 2002655
+	report_errata ERRATA_N2_2067956, neoverse_n2, 2067956
+	report_errata ERRATA_N2_2025414, neoverse_n2, 2025414
+	report_errata ERRATA_N2_2189731, neoverse_n2, 2189731
+	report_errata ERRATA_N2_2138956, neoverse_n2, 2138956
+	report_errata ERRATA_N2_2138953, neoverse_n2, 2138953
+
+	ldp	x8, x30, [sp], #16
 	ret
 endfunc neoverse_n2_errata_report
 #endif
diff --git a/lib/cpus/aarch64/neoverse_v1.S b/lib/cpus/aarch64/neoverse_v1.S
index 7336294..200f67d 100644
--- a/lib/cpus/aarch64/neoverse_v1.S
+++ b/lib/cpus/aarch64/neoverse_v1.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,6 +21,273 @@
 #error "Neoverse-V1 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+	/* --------------------------------------------------
+	 * Errata Workaround for Neoverse V1 Errata #1774420.
+	 * This applies to revisions r0p0 and r1p0, fixed in r1p1.
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * --------------------------------------------------
+	 */
+func errata_neoverse_v1_1774420_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_1774420
+	cbz	x0, 1f
+
+	/* Set bit 53 in CPUECTLR_EL1 */
+	mrs     x1, NEOVERSE_V1_CPUECTLR_EL1
+	orr	x1, x1, #NEOVERSE_V1_CPUECTLR_EL1_BIT_53
+	msr     NEOVERSE_V1_CPUECTLR_EL1, x1
+	isb
+1:
+	ret	x17
+endfunc errata_neoverse_v1_1774420_wa
+
+func check_errata_1774420
+	/* Applies to r0p0 and r1p0. */
+	mov	x1, #0x10
+	b	cpu_rev_var_ls
+endfunc check_errata_1774420
+
+	/* --------------------------------------------------
+	 * Errata Workaround for Neoverse V1 Errata #1791573.
+	 * This applies to revisions r0p0 and r1p0, fixed in r1p1.
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * --------------------------------------------------
+	 */
+func errata_neoverse_v1_1791573_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_1791573
+	cbz	x0, 1f
+
+	/* Set bit 2 in ACTLR2_EL1 */
+	mrs	x1, NEOVERSE_V1_ACTLR2_EL1
+	orr	x1, x1, #NEOVERSE_V1_ACTLR2_EL1_BIT_2
+	msr	NEOVERSE_V1_ACTLR2_EL1, x1
+	isb
+1:
+	ret	x17
+endfunc errata_neoverse_v1_1791573_wa
+
+func check_errata_1791573
+	/* Applies to r0p0 and r1p0. */
+	mov	x1, #0x10
+	b	cpu_rev_var_ls
+endfunc check_errata_1791573
+
+	/* --------------------------------------------------
+	 * Errata Workaround for Neoverse V1 Errata #1852267.
+	 * This applies to revisions r0p0 and r1p0, fixed in r1p1.
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * --------------------------------------------------
+	 */
+func errata_neoverse_v1_1852267_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_1852267
+	cbz	x0, 1f
+
+	/* Set bit 28 in ACTLR2_EL1 */
+	mrs	x1, NEOVERSE_V1_ACTLR2_EL1
+	orr	x1, x1, #NEOVERSE_V1_ACTLR2_EL1_BIT_28
+	msr	NEOVERSE_V1_ACTLR2_EL1, x1
+	isb
+1:
+	ret	x17
+endfunc errata_neoverse_v1_1852267_wa
+
+func check_errata_1852267
+	/* Applies to r0p0 and r1p0. */
+	mov	x1, #0x10
+	b	cpu_rev_var_ls
+endfunc check_errata_1852267
+
+	/* --------------------------------------------------
+	 * Errata Workaround for Neoverse V1 Errata #1925756.
+	 * This applies to revisions <= r1p1.
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * --------------------------------------------------
+	 */
+func errata_neoverse_v1_1925756_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_1925756
+	cbz	x0, 1f
+
+	/* Set bit 8 in CPUECTLR_EL1 */
+	mrs	x1, NEOVERSE_V1_CPUECTLR_EL1
+	orr	x1, x1, #NEOVERSE_V1_CPUECTLR_EL1_BIT_8
+	msr	NEOVERSE_V1_CPUECTLR_EL1, x1
+	isb
+1:
+	ret	x17
+endfunc errata_neoverse_v1_1925756_wa
+
+func check_errata_1925756
+	/* Applies to <= r1p1. */
+	mov	x1, #0x11
+	b	cpu_rev_var_ls
+endfunc check_errata_1925756
+
+	/* --------------------------------------------------
+	 * Errata Workaround for Neoverse V1 Erratum #1940577
+	 * This applies to revisions r1p0 - r1p1 and is open.
+	 * It also exists in r0p0 but there is no fix in that
+	 * revision.
+	 * Inputs:
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * --------------------------------------------------
+	 */
+func errata_neoverse_v1_1940577_wa
+	/* Compare x0 against revisions r1p0 - r1p1 */
+	mov	x17, x30
+	bl	check_errata_1940577
+	cbz	x0, 1f
+
+	mov	x0, #0
+	msr	S3_6_C15_C8_0, x0
+	ldr	x0, =0x10E3900002
+	msr	S3_6_C15_C8_2, x0
+	ldr	x0, =0x10FFF00083
+	msr	S3_6_C15_C8_3, x0
+	ldr	x0, =0x2001003FF
+	msr	S3_6_C15_C8_1, x0
+
+	mov	x0, #1
+	msr	S3_6_C15_C8_0, x0
+	ldr	x0, =0x10E3800082
+	msr	S3_6_C15_C8_2, x0
+	ldr	x0, =0x10FFF00083
+	msr	S3_6_C15_C8_3, x0
+	ldr	x0, =0x2001003FF
+	msr	S3_6_C15_C8_1, x0
+
+	mov	x0, #2
+	msr	S3_6_C15_C8_0, x0
+	ldr	x0, =0x10E3800200
+	msr	S3_6_C15_C8_2, x0
+	ldr	x0, =0x10FFF003E0
+	msr	S3_6_C15_C8_3, x0
+	ldr	x0, =0x2001003FF
+	msr	S3_6_C15_C8_1, x0
+
+	isb
+1:
+	ret	x17
+endfunc errata_neoverse_v1_1940577_wa
+
+func check_errata_1940577
+	/* Applies to revisions r1p0 - r1p1. */
+	mov	x1, #0x10
+	mov	x2, #0x11
+	b	cpu_rev_var_range
+endfunc check_errata_1940577
+
+	/* --------------------------------------------------
+	 * Errata Workaround for Neoverse V1 Errata #1966096
+	 * This applies to revisions r1p0 - r1p1 and is open.
+	 * It also exists in r0p0 but there is no workaround
+	 * for that revision.
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * --------------------------------------------------
+	 */
+func errata_neoverse_v1_1966096_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_1966096
+	cbz	x0, 1f
+
+	/* Apply the workaround. */
+	mov	x0, #0x3
+	msr	S3_6_C15_C8_0, x0
+	ldr	x0, =0xEE010F12
+	msr	S3_6_C15_C8_2, x0
+	ldr	x0, =0xFFFF0FFF
+	msr	S3_6_C15_C8_3, x0
+	ldr	x0, =0x80000000003FF
+	msr	S3_6_C15_C8_1, x0
+	isb
+
+1:
+	ret	x17
+endfunc errata_neoverse_v1_1966096_wa
+
+func check_errata_1966096
+	mov	x1, #0x10
+	mov	x2, #0x11
+	b	cpu_rev_var_range
+endfunc check_errata_1966096
+
+	/* --------------------------------------------------
+	 * Errata Workaround for Neoverse V1 Errata #2139242.
+	 * This applies to revisions r0p0, r1p0, and r1p1, it
+	 * is still open.
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * --------------------------------------------------
+	 */
+func errata_neoverse_v1_2139242_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_2139242
+	cbz	x0, 1f
+
+	/* Apply the workaround. */
+	mov	x0, #0x3
+	msr	S3_6_C15_C8_0, x0
+	ldr	x0, =0xEE720F14
+	msr	S3_6_C15_C8_2, x0
+	ldr	x0, =0xFFFF0FDF
+	msr	S3_6_C15_C8_3, x0
+	ldr	x0, =0x40000005003FF
+	msr	S3_6_C15_C8_1, x0
+	isb
+
+1:
+	ret	x17
+endfunc errata_neoverse_v1_2139242_wa
+
+func check_errata_2139242
+	/* Applies to r0p0, r1p0, r1p1 */
+	mov	x1, #0x11
+	b	cpu_rev_var_ls
+endfunc check_errata_2139242
+
+	/* --------------------------------------------------
+	 * Errata Workaround for Neoverse V1 Errata #2108267.
+	 * This applies to revisions r0p0, r1p0, and r1p1, it
+	 * is still open.
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x1, x17
+	 * --------------------------------------------------
+	 */
+func errata_neoverse_v1_2108267_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_2108267
+	cbz	x0, 1f
+
+	/* Apply the workaround. */
+	mrs	x1, NEOVERSE_V1_CPUECTLR_EL1
+	mov	x0, #NEOVERSE_V1_CPUECTLR_EL1_PF_MODE_CNSRV
+	bfi	x1, x0, #CPUECTLR_EL1_PF_MODE_LSB, #CPUECTLR_EL1_PF_MODE_WIDTH
+	msr	NEOVERSE_V1_CPUECTLR_EL1, x1
+1:
+	ret	x17
+endfunc errata_neoverse_v1_2108267_wa
+
+func check_errata_2108267
+	/* Applies to r0p0, r1p0, r1p1 */
+	mov	x1, #0x11
+	b	cpu_rev_var_ls
+endfunc check_errata_2108267
+
 	/* ---------------------------------------------
 	 * HW will do the cache maintenance while powering down
 	 * ---------------------------------------------
@@ -42,6 +309,25 @@
 	 */
 #if REPORT_ERRATA
 func neoverse_v1_errata_report
+	stp	x8, x30, [sp, #-16]!
+
+	bl	cpu_get_rev_var
+	mov	x8, x0
+
+	/*
+	 * Report all errata. The revision-variant information is passed to
+	 * checking functions of each errata.
+	 */
+	report_errata ERRATA_V1_1774420, neoverse_v1, 1774420
+	report_errata ERRATA_V1_1791573, neoverse_v1, 1791573
+	report_errata ERRATA_V1_1852267, neoverse_v1, 1852267
+	report_errata ERRATA_V1_1925756, neoverse_v1, 1925756
+	report_errata ERRATA_V1_1940577, neoverse_v1, 1940577
+	report_errata ERRATA_V1_1966096, neoverse_v1, 1966096
+	report_errata ERRATA_V1_2139242, neoverse_v1, 2139242
+	report_errata ERRATA_V1_2108267, neoverse_v1, 2108267
+
+	ldp	x8, x30, [sp], #16
 	ret
 endfunc neoverse_v1_errata_report
 #endif
@@ -51,8 +337,48 @@
 
 	/* Disable speculative loads */
 	msr	SSBS, xzr
-
 	isb
+
+#if ERRATA_V1_1774420
+	mov	x0, x18
+	bl	errata_neoverse_v1_1774420_wa
+#endif
+
+#if ERRATA_V1_1791573
+	mov	x0, x18
+	bl	errata_neoverse_v1_1791573_wa
+#endif
+
+#if ERRATA_V1_1852267
+	mov	x0, x18
+	bl	errata_neoverse_v1_1852267_wa
+#endif
+
+#if ERRATA_V1_1925756
+	mov	x0, x18
+	bl	errata_neoverse_v1_1925756_wa
+#endif
+
+#if ERRATA_V1_1940577
+	mov	x0, x18
+	bl	errata_neoverse_v1_1940577_wa
+#endif
+
+#if ERRATA_V1_1966096
+	mov	x0, x18
+	bl	errata_neoverse_v1_1966096_wa
+#endif
+
+#if ERRATA_V1_2139242
+	mov	x0, x18
+	bl	errata_neoverse_v1_2139242_wa
+#endif
+
+#if ERRATA_V1_2108267
+	mov	x0, x18
+	bl	errata_neoverse_v1_2108267_wa
+#endif
+
 	ret	x19
 endfunc neoverse_v1_reset_func
 
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index b1747af..138f7a5 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -1,6 +1,6 @@
 #
 # Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved.
-# Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+# Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -311,10 +311,26 @@
 # well but there is no workaround for that revision.
 ERRATA_A78_1951500	?=0
 
+# Flag to apply erratum 1941500 workaround during reset. This erratum applies
+# to revisions r0p0 and r0p1 of the A78 AE cpu. It is still open.
+ERRATA_A78_AE_1941500	?=0
+
+# Flag to apply erratum 1951502 workaround during reset. This erratum applies
+# to revisions r0p0 and r0p1 of the A78 AE cpu. It is still open.
+ERRATA_A78_AE_1951502	?=0
+
 # Flag to apply erratum 1821534 workaround during reset. This erratum applies
 # to revisions r0p0 and r1p0 of the A78 cpu.
 ERRATA_A78_1821534	?=0
 
+# Flag to apply erratum 1952683 workaround during reset. This erratum applies
+# to revision r0p0 of the A78 cpu and was fixed in the revision r1p0.
+ERRATA_A78_1952683	?=0
+
+# Flag to apply erratum 2132060 workaround during reset. This erratum applies
+# to revisions r0p0, r1p0, r1p1, and r1p2 of the A78 cpu. It is still open.
+ERRATA_A78_2132060	?=0
+
 # Flag to apply T32 CLREX workaround during reset. This erratum applies
 # only to r0p0 and r1p0 of the Neoverse N1 cpu.
 ERRATA_N1_1043202	?=0
@@ -372,6 +388,87 @@
 # exists in revisions r0p0, r1p0, and r2p0 as well but there is no workaround.
 ERRATA_N1_1946160	?=0
 
+# Flag to apply erratum 2002655 workaround during reset. This erratum applies
+# to revisions r0p0 of the Neoverse-N2 cpu, it is still open.
+ERRATA_N2_2002655	?=0
+
+# Flag to apply erratum 1774420 workaround during reset.  This erratum applies
+# to revisions r0p0 and r1p0 of the Neoverse V1 core, and was fixed in r1p1.
+ERRATA_V1_1774420	?=0
+
+# Flag to apply erratum 1791573 workaround during reset.  This erratum applies
+# to revisions r0p0 and r1p0 of the Neoverse V1 core, and was fixed in r1p1.
+ERRATA_V1_1791573	?=0
+
+# Flag to apply erratum 1852267 workaround during reset.  This erratum applies
+# to revisions r0p0 and r1p0 of the Neoverse V1 core, and was fixed in r1p1.
+ERRATA_V1_1852267	?=0
+
+# Flag to apply erratum 1925756 workaround during reset.  This needs to be
+# enabled for r0p0, r1p0, and r1p1 of the Neoverse V1 core, it is still open.
+ERRATA_V1_1925756	?=0
+
+# Flag to apply erratum 1940577 workaround during reset. This erratum applies
+# to revisions r1p0 and r1p1 of the Neoverse V1 cpu.
+ERRATA_V1_1940577	?=0
+
+# Flag to apply erratum 1966096 workaround during reset. This erratum applies
+# to revisions r1p0 and r1p1 of the Neoverse V1 CPU and is open.  This issue
+# exists in r0p0 as well but there is no workaround for that revision.
+ERRATA_V1_1966096	?=0
+
+# Flag to apply erratum 2139242 workaround during reset. This erratum applies
+# to revisions r0p0, r1p0, and r1p1 of the Neoverse V1 cpu and is still open.
+ERRATA_V1_2139242	?=0
+
+# Flag to apply erratum 2108267 workaround during reset. This erratum applies
+# to revisions r0p0, r1p0, and r1p1 of the Neoverse V1 cpu and is still open.
+ERRATA_V1_2108267	?=0
+
+# Flag to apply erratum 1987031 workaround during reset. This erratum applies
+# to revisions r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is still open.
+ERRATA_A710_1987031	?=0
+
+# Flag to apply erratum 2081180 workaround during reset. This erratum applies
+# to revisions r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is still open.
+ERRATA_A710_2081180	?=0
+
+# Flag to apply erratum 2083908 workaround during reset. This erratum applies
+# to revision r2p0 of the Cortex-A710 cpu and is still open.
+ERRATA_A710_2083908	?=0
+
+# Flag to apply erratum 2058056 workaround during reset. This erratum applies
+# to revisions r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is still open.
+ERRATA_A710_2058056	?=0
+
+# Flag to apply erratum 2067956 workaround during reset. This erratum applies
+# to revision r0p0 of the Neoverse N2 cpu and is still open.
+ERRATA_N2_2067956	?=0
+
+# Flag to apply erratum 2025414 workaround during reset. This erratum applies
+# to revision r0p0 of the Neoverse N2 cpu and is still open.
+ERRATA_N2_2025414	?=0
+
+# Flag to apply erratum 2189731 workaround during reset. This erratum applies
+# to revision r0p0 of the Neoverse N2 cpu and is still open.
+ERRATA_N2_2189731	?=0
+
+# Flag to apply erratum 2138956 workaround during reset. This erratum applies
+# to revision r0p0 of the Neoverse N2 cpu and is still open.
+ERRATA_N2_2138956	?=0
+
+# Flag to apply erratum 2138953 workaround during reset. This erratum applies
+# to revision r0p0 of the Neoverse N2 cpu and is still open.
+ERRATA_N2_2138953	?=0
+
+# Flag to apply erratum 2055002 workaround during reset. This erratum applies
+# to revision r1p0, r2p0 of the Cortex-A710 cpu and is still open.
+ERRATA_A710_2055002	?=0
+
+# Flag to apply erratum 2017096 workaround during reset. This erratum applies
+# to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is still open.
+ERRATA_A710_2017096	?=0
+
 # Flag to apply DSU erratum 798953. This erratum applies to DSUs revision r0p0.
 # Applying the workaround results in higher DSU power consumption on idle.
 ERRATA_DSU_798953	?=0
@@ -617,10 +714,26 @@
 $(eval $(call assert_boolean,ERRATA_A78_1951500))
 $(eval $(call add_define,ERRATA_A78_1951500))
 
+# Process ERRATA_A78_AE_1941500 flag
+$(eval $(call assert_boolean,ERRATA_A78_AE_1941500))
+$(eval $(call add_define,ERRATA_A78_AE_1941500))
+
+# Process ERRATA_A78_AE_1951502 flag
+$(eval $(call assert_boolean,ERRATA_A78_AE_1951502))
+$(eval $(call add_define,ERRATA_A78_AE_1951502))
+
 # Process ERRATA_A78_1821534 flag
 $(eval $(call assert_boolean,ERRATA_A78_1821534))
 $(eval $(call add_define,ERRATA_A78_1821534))
 
+# Process ERRATA_A78_1952683 flag
+$(eval $(call assert_boolean,ERRATA_A78_1952683))
+$(eval $(call add_define,ERRATA_A78_1952683))
+
+# Process ERRATA_A78_2132060 flag
+$(eval $(call assert_boolean,ERRATA_A78_2132060))
+$(eval $(call add_define,ERRATA_A78_2132060))
+
 # Process ERRATA_N1_1043202 flag
 $(eval $(call assert_boolean,ERRATA_N1_1043202))
 $(eval $(call add_define,ERRATA_N1_1043202))
@@ -677,6 +790,86 @@
 $(eval $(call assert_boolean,ERRATA_N1_1946160))
 $(eval $(call add_define,ERRATA_N1_1946160))
 
+# Process ERRATA_N2_2002655 flag
+$(eval $(call assert_boolean,ERRATA_N2_2002655))
+$(eval $(call add_define,ERRATA_N2_2002655))
+
+# Process ERRATA_V1_1774420 flag
+$(eval $(call assert_boolean,ERRATA_V1_1774420))
+$(eval $(call add_define,ERRATA_V1_1774420))
+
+# Process ERRATA_V1_1791573 flag
+$(eval $(call assert_boolean,ERRATA_V1_1791573))
+$(eval $(call add_define,ERRATA_V1_1791573))
+
+# Process ERRATA_V1_1852267 flag
+$(eval $(call assert_boolean,ERRATA_V1_1852267))
+$(eval $(call add_define,ERRATA_V1_1852267))
+
+# Process ERRATA_V1_1925756 flag
+$(eval $(call assert_boolean,ERRATA_V1_1925756))
+$(eval $(call add_define,ERRATA_V1_1925756))
+
+# Process ERRATA_V1_1940577 flag
+$(eval $(call assert_boolean,ERRATA_V1_1940577))
+$(eval $(call add_define,ERRATA_V1_1940577))
+
+# Process ERRATA_V1_1966096 flag
+$(eval $(call assert_boolean,ERRATA_V1_1966096))
+$(eval $(call add_define,ERRATA_V1_1966096))
+
+# Process ERRATA_V1_2139242 flag
+$(eval $(call assert_boolean,ERRATA_V1_2139242))
+$(eval $(call add_define,ERRATA_V1_2139242))
+
+# Process ERRATA_V1_2108267 flag
+$(eval $(call assert_boolean,ERRATA_V1_2108267))
+$(eval $(call add_define,ERRATA_V1_2108267))
+
+# Process ERRATA_A710_1987031 flag
+$(eval $(call assert_boolean,ERRATA_A710_1987031))
+$(eval $(call add_define,ERRATA_A710_1987031))
+
+# Process ERRATA_A710_2081180 flag
+$(eval $(call assert_boolean,ERRATA_A710_2081180))
+$(eval $(call add_define,ERRATA_A710_2081180))
+
+# Process ERRATA_A710_2083908 flag
+$(eval $(call assert_boolean,ERRATA_A710_2083908))
+$(eval $(call add_define,ERRATA_A710_2083908))
+
+# Process ERRATA_A710_2058056 flag
+$(eval $(call assert_boolean,ERRATA_A710_2058056))
+$(eval $(call add_define,ERRATA_A710_2058056))
+
+# Process ERRATA_N2_2067956 flag
+$(eval $(call assert_boolean,ERRATA_N2_2067956))
+$(eval $(call add_define,ERRATA_N2_2067956))
+
+# Process ERRATA_N2_2025414 flag
+$(eval $(call assert_boolean,ERRATA_N2_2025414))
+$(eval $(call add_define,ERRATA_N2_2025414))
+
+# Process ERRATA_N2_2189731 flag
+$(eval $(call assert_boolean,ERRATA_N2_2189731))
+$(eval $(call add_define,ERRATA_N2_2189731))
+
+# Process ERRATA_N2_2138956 flag
+$(eval $(call assert_boolean,ERRATA_N2_2138956))
+$(eval $(call add_define,ERRATA_N2_2138956))
+
+# Process ERRATA_N2_2138953 flag
+$(eval $(call assert_boolean,ERRATA_N2_2138953))
+$(eval $(call add_define,ERRATA_N2_2138953))
+
+# Process ERRATA_A710_2055002 flag
+$(eval $(call assert_boolean,ERRATA_A710_2055002))
+$(eval $(call add_define,ERRATA_A710_2055002))
+
+# Process ERRATA_A710_2017096 flag
+$(eval $(call assert_boolean,ERRATA_A710_2017096))
+$(eval $(call add_define,ERRATA_A710_2017096))
+
 # Process ERRATA_DSU_798953 flag
 $(eval $(call assert_boolean,ERRATA_DSU_798953))
 $(eval $(call add_define,ERRATA_DSU_798953))
diff --git a/lib/el3_runtime/aarch32/context_mgmt.c b/lib/el3_runtime/aarch32/context_mgmt.c
index 81d793b..3ef378c 100644
--- a/lib/el3_runtime/aarch32/context_mgmt.c
+++ b/lib/el3_runtime/aarch32/context_mgmt.c
@@ -16,6 +16,8 @@
 #include <context.h>
 #include <lib/el3_runtime/context_mgmt.h>
 #include <lib/extensions/amu.h>
+#include <lib/extensions/sys_reg_trace.h>
+#include <lib/extensions/trf.h>
 #include <lib/utils.h>
 
 /*******************************************************************************
@@ -136,6 +138,14 @@
 #if ENABLE_AMU
 	amu_enable(el2_unused);
 #endif
+
+#if ENABLE_SYS_REG_TRACE_FOR_NS
+	sys_reg_trace_enable();
+#endif /* ENABLE_SYS_REG_TRACE_FOR_NS */
+
+#if ENABLE_TRF_FOR_NS
+	trf_enable();
+#endif /* ENABLE_TRF_FOR_NS */
 #endif
 }
 
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index d610fd4..e270ad0 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -193,6 +193,11 @@
 	str	x13, [x0, #CTX_SCXTNUM_EL2]
 #endif
 
+#if ENABLE_FEAT_HCX
+	mrs	x14, hcrx_el2
+	str	x14, [x0, #CTX_HCRX_EL2]
+#endif
+
 	ret
 endfunc el2_sysregs_context_save
 
@@ -362,6 +367,11 @@
 	msr	scxtnum_el2, x13
 #endif
 
+#if ENABLE_FEAT_HCX
+	ldr	x14, [x0, #CTX_HCRX_EL2]
+	msr	hcrx_el2, x14
+#endif
+
 	ret
 endfunc el2_sysregs_context_restore
 
@@ -903,16 +913,11 @@
 
 #if IMAGE_BL31
 	/* ----------------------------------------------------------
-	 * Restore CPTR_EL3, ZCR_EL3 for SVE support.
-	 * If SVE is not supported - skip the restoration.
+	 * Restore CPTR_EL3.
 	 * ZCR is only restored if SVE is supported and enabled.
 	 * Synchronization is required before zcr_el3 is addressed.
 	 * ----------------------------------------------------------
 	 */
-	mrs	x17, id_aa64pfr0_el1
-	ubfx	x17, x17, ID_AA64PFR0_SVE_SHIFT, ID_AA64PFR0_SVE_LENGTH
-	cbz	x17, sve_not_enabled
-
 	ldp	x19, x20, [sp, #CTX_EL3STATE_OFFSET + CTX_CPTR_EL3]
 	msr	cptr_el3, x19
 
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 7a25151..0ec7e7e 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -22,9 +22,13 @@
 #include <lib/extensions/mpam.h>
 #include <lib/extensions/spe.h>
 #include <lib/extensions/sve.h>
+#include <lib/extensions/sys_reg_trace.h>
+#include <lib/extensions/trbe.h>
+#include <lib/extensions/trf.h>
 #include <lib/extensions/twed.h>
 #include <lib/utils.h>
 
+static void enable_extensions_secure(cpu_context_t *ctx);
 
 /*******************************************************************************
  * Context management library initialisation routine. This library is used by
@@ -89,24 +93,49 @@
 	scr_el3 = read_scr();
 	scr_el3 &= ~(SCR_NS_BIT | SCR_RW_BIT | SCR_FIQ_BIT | SCR_IRQ_BIT |
 			SCR_ST_BIT | SCR_HCE_BIT);
+
+#if ENABLE_RME
+	/* When RME support is enabled, clear the NSE bit as well. */
+	scr_el3 &= ~SCR_NSE_BIT;
+#endif /* ENABLE_RME */
+
 	/*
 	 * SCR_NS: Set the security state of the next EL.
 	 */
-	if (security_state != SECURE)
+	if (security_state == NON_SECURE) {
 		scr_el3 |= SCR_NS_BIT;
+	}
+
+#if ENABLE_RME
+	/* Check for realm state if RME support enabled. */
+	if (security_state == REALM) {
+		scr_el3 |= SCR_NS_BIT | SCR_NSE_BIT | SCR_EnSCXT_BIT;
+	}
+#endif /* ENABLE_RME */
+
 	/*
 	 * SCR_EL3.RW: Set the execution state, AArch32 or AArch64, for next
 	 *  Exception level as specified by SPSR.
 	 */
-	if (GET_RW(ep->spsr) == MODE_RW_64)
+	if (GET_RW(ep->spsr) == MODE_RW_64) {
 		scr_el3 |= SCR_RW_BIT;
+	}
 	/*
 	 * SCR_EL3.ST: Traps Secure EL1 accesses to the Counter-timer Physical
 	 *  Secure timer registers to EL3, from AArch64 state only, if specified
 	 *  by the entrypoint attributes.
 	 */
-	if (EP_GET_ST(ep->h.attr) != 0U)
+	if (EP_GET_ST(ep->h.attr) != 0U) {
 		scr_el3 |= SCR_ST_BIT;
+	}
+
+	/*
+	 * If FEAT_HCX is enabled, enable access to HCRX_EL2 by setting
+	 * SCR_EL3.HXEn.
+	 */
+#if ENABLE_FEAT_HCX
+	scr_el3 |= SCR_HXEn_BIT;
+#endif
 
 #if RAS_TRAP_LOWER_EL_ERR_ACCESS
 	/*
@@ -140,8 +169,9 @@
 	 * If the Secure world wants to use pointer authentication,
 	 * CTX_INCLUDE_PAUTH_REGS must be set to 1.
 	 */
-	if (security_state == NON_SECURE)
+	if (security_state == NON_SECURE) {
 		scr_el3 |= SCR_API_BIT | SCR_APK_BIT;
+	}
 #endif /* !CTX_INCLUDE_PAUTH_REGS */
 
 #if !CTX_INCLUDE_MTE_REGS || ENABLE_ASSERTIONS
@@ -176,21 +206,21 @@
 	/*
 	 * SCR_EL3.IRQ, SCR_EL3.FIQ: Enable the physical FIQ and IRQ routing as
 	 *  indicated by the interrupt routing model for BL31.
+	 *
+	 * TODO: The interrupt routing model code is not updated for REALM
+	 * state. Use the default values of IRQ = FIQ = 0 for REALM security
+	 * state for now.
 	 */
-	scr_el3 |= get_scr_el3_from_routing_model(security_state);
-
-#if ENABLE_SVE_FOR_NS
-	if (security_state == NON_SECURE) {
-		sve_enable(ctx);
+	if (security_state != REALM) {
+		scr_el3 |= get_scr_el3_from_routing_model(security_state);
 	}
 #endif
-#if ENABLE_SVE_FOR_SWD
+
+	/* Save the initialized value of CPTR_EL3 register */
+	write_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3, read_cptr_el3());
 	if (security_state == SECURE) {
-		sve_enable(ctx);
+		enable_extensions_secure(ctx);
 	}
-#endif
-
-#endif
 
 	/*
 	 * SCR_EL3.HCE: Enable HVC instructions if next execution state is
@@ -250,9 +280,9 @@
 	 *  required by PSCI specification)
 	 */
 	sctlr_elx = (EP_GET_EE(ep->h.attr) != 0U) ? SCTLR_EE_BIT : 0U;
-	if (GET_RW(ep->spsr) == MODE_RW_64)
+	if (GET_RW(ep->spsr) == MODE_RW_64) {
 		sctlr_elx |= SCTLR_EL1_RES1;
-	else {
+	} else {
 		/*
 		 * If the target execution state is AArch32 then the following
 		 * fields need to be set.
@@ -335,7 +365,7 @@
  * When EL2 is implemented but unused `el2_unused` is non-zero, otherwise
  * it is zero.
  ******************************************************************************/
-static void enable_extensions_nonsecure(bool el2_unused)
+static void enable_extensions_nonsecure(bool el2_unused, cpu_context_t *ctx)
 {
 #if IMAGE_BL31
 #if ENABLE_SPE_FOR_LOWER_ELS
@@ -343,12 +373,41 @@
 #endif
 
 #if ENABLE_AMU
-	amu_enable(el2_unused);
+	amu_enable(el2_unused, ctx);
+#endif
+
+#if ENABLE_SVE_FOR_NS
+	sve_enable(ctx);
 #endif
 
 #if ENABLE_MPAM_FOR_LOWER_ELS
 	mpam_enable(el2_unused);
 #endif
+
+#if ENABLE_TRBE_FOR_NS
+	trbe_enable();
+#endif /* ENABLE_TRBE_FOR_NS */
+
+#if ENABLE_SYS_REG_TRACE_FOR_NS
+	sys_reg_trace_enable(ctx);
+#endif /* ENABLE_SYS_REG_TRACE_FOR_NS */
+
+#if ENABLE_TRF_FOR_NS
+	trf_enable();
+#endif /* ENABLE_TRF_FOR_NS */
+
+#endif
+}
+
+/*******************************************************************************
+ * Enable architecture extensions on first entry to Secure world.
+ ******************************************************************************/
+static void enable_extensions_secure(cpu_context_t *ctx)
+{
+#if IMAGE_BL31
+#if ENABLE_SVE_FOR_SWD
+	sve_enable(ctx);
+#endif
 #endif
 }
 
@@ -378,7 +437,8 @@
 }
 
 /*******************************************************************************
- * Prepare the CPU system registers for first entry into secure or normal world
+ * Prepare the CPU system registers for first entry into realm, secure, or
+ * normal world.
  *
  * If execution is requested to EL2 or hyp mode, SCTLR_EL2 is initialized
  * If execution is requested to non-secure EL1 or svc mode, and the CPU supports
@@ -446,6 +506,8 @@
 			 * CPTR_EL2.TTA: Set to zero so that Non-secure System
 			 *  register accesses to the trace registers from both
 			 *  Execution states do not trap to EL2.
+			 *  If PE trace unit System registers are not implemented
+			 *  then this bit is reserved, and must be set to zero.
 			 *
 			 * CPTR_EL2.TFP: Set to zero so that Non-secure accesses
 			 *  to SIMD and floating-point functionality from both
@@ -460,7 +522,7 @@
 			 * architecturally UNKNOWN on reset and are set to zero
 			 * except for field(s) listed below.
 			 *
-			 * CNTHCTL_EL2.EL1PCEN: Set to one to disable traps to
+			 * CNTHCTL_EL2.EL1PTEN: Set to one to disable traps to
 			 *  Hyp mode of Non-secure EL0 and EL1 accesses to the
 			 *  physical timer registers.
 			 *
@@ -554,6 +616,11 @@
 			 *
 			 * MDCR_EL2.HPMN: Set to value of PMCR_EL0.N which is the
 			 *  architecturally-defined reset value.
+			 *
+			 * MDCR_EL2.E2TB: Set to zero so that the trace Buffer
+			 *  owning exception level is NS-EL1 and, tracing is
+			 *  prohibited at NS-EL2. These bits are RES0 when
+			 *  FEAT_TRBE is not implemented.
 			 */
 			mdcr_el2 = ((MDCR_EL2_RESET_VAL | MDCR_EL2_HLP |
 				     MDCR_EL2_HPMD) |
@@ -563,7 +630,8 @@
 				     MDCR_EL2_TDRA_BIT | MDCR_EL2_TDOSA_BIT |
 				     MDCR_EL2_TDA_BIT | MDCR_EL2_TDE_BIT |
 				     MDCR_EL2_HPME_BIT | MDCR_EL2_TPM_BIT |
-				     MDCR_EL2_TPMCR_BIT);
+				     MDCR_EL2_TPMCR_BIT |
+				     MDCR_EL2_E2TB(MDCR_EL2_E2TB_EL1));
 
 			write_mdcr_el2(mdcr_el2);
 
@@ -586,7 +654,7 @@
 			write_cnthp_ctl_el2(CNTHP_CTL_RESET_VAL &
 						~(CNTHP_CTL_ENABLE_BIT));
 		}
-		enable_extensions_nonsecure(el2_unused);
+		enable_extensions_nonsecure(el2_unused, ctx);
 	}
 
 	cm_el1_sysregs_context_restore(security_state);
@@ -602,10 +670,10 @@
 	u_register_t scr_el3 = read_scr();
 
 	/*
-	 * Always save the non-secure EL2 context, only save the
+	 * Always save the non-secure and realm EL2 context, only save the
 	 * S-EL2 context if S-EL2 is enabled.
 	 */
-	if ((security_state == NON_SECURE) ||
+	if ((security_state != SECURE) ||
 	    ((security_state == SECURE) && ((scr_el3 & SCR_EEL2_BIT) != 0U))) {
 		cpu_context_t *ctx;
 
@@ -624,10 +692,10 @@
 	u_register_t scr_el3 = read_scr();
 
 	/*
-	 * Always restore the non-secure EL2 context, only restore the
+	 * Always restore the non-secure and realm EL2 context, only restore the
 	 * S-EL2 context if S-EL2 is enabled.
 	 */
-	if ((security_state == NON_SECURE) ||
+	if ((security_state != SECURE) ||
 	    ((security_state == SECURE) && ((scr_el3 & SCR_EEL2_BIT) != 0U))) {
 		cpu_context_t *ctx;
 
diff --git a/lib/extensions/amu/aarch64/amu.c b/lib/extensions/amu/aarch64/amu.c
index 24c3737..295c0d5 100644
--- a/lib/extensions/amu/aarch64/amu.c
+++ b/lib/extensions/amu/aarch64/amu.c
@@ -46,7 +46,7 @@
  * Enable counters. This function is meant to be invoked
  * by the context management library before exiting from EL3.
  */
-void amu_enable(bool el2_unused)
+void amu_enable(bool el2_unused, cpu_context_t *ctx)
 {
 	uint64_t v;
 	unsigned int amu_version = amu_get_version();
@@ -88,12 +88,13 @@
 	}
 
 	/*
-	 * CPTR_EL3.TAM: Set to zero so that any accesses to
+	 * Retrieve and update the CPTR_EL3 value from the context mentioned
+	 * in 'ctx'. Set CPTR_EL3.TAM to zero so that any accesses to
 	 * the Activity Monitor registers do not trap to EL3.
 	 */
-	v = read_cptr_el3();
+	v = read_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3);
 	v &= ~TAM_BIT;
-	write_cptr_el3(v);
+	write_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3, v);
 
 	/* Enable group 0 counters */
 	write_amcntenset0_el0(AMU_GROUP0_COUNTERS_MASK);
diff --git a/lib/extensions/sve/sve.c b/lib/extensions/sve/sve.c
index 7043cc2..2702c30 100644
--- a/lib/extensions/sve/sve.c
+++ b/lib/extensions/sve/sve.c
@@ -27,11 +27,13 @@
 
 void sve_enable(cpu_context_t *context)
 {
+	u_register_t cptr_el3;
+
 	if (!sve_supported()) {
 		return;
 	}
 
-	u_register_t cptr_el3 = read_cptr_el3();
+	cptr_el3 = read_ctx_reg(get_el3state_ctx(context), CTX_CPTR_EL3);
 
 	/* Enable access to SVE functionality for all ELs. */
 	cptr_el3 = (cptr_el3 | CPTR_EZ_BIT) & ~(TFP_BIT);
diff --git a/lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c b/lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c
new file mode 100644
index 0000000..89b8029
--- /dev/null
+++ b/lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <lib/extensions/sys_reg_trace.h>
+
+static bool sys_reg_trace_supported(void)
+{
+	uint32_t features;
+
+	features = read_id_dfr0() >> ID_DFR0_COPTRC_SHIFT;
+	return ((features & ID_DFR0_COPTRC_MASK) ==
+		ID_DFR0_COPTRC_SUPPORTED);
+}
+
+void sys_reg_trace_enable(void)
+{
+	uint32_t val;
+
+	if (sys_reg_trace_supported()) {
+		/*
+		 * NSACR.NSTRCDIS = b0
+		 * enable NS system register access to implemented trace
+		 * registers.
+		 */
+		val = read_nsacr();
+		val &= ~NSTRCDIS_BIT;
+		write_nsacr(val);
+	}
+}
diff --git a/lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c b/lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c
new file mode 100644
index 0000000..960d698
--- /dev/null
+++ b/lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <lib/extensions/sys_reg_trace.h>
+
+static bool sys_reg_trace_supported(void)
+{
+	uint64_t features;
+
+	features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEVER_SHIFT;
+	return ((features & ID_AA64DFR0_TRACEVER_MASK) ==
+		ID_AA64DFR0_TRACEVER_SUPPORTED);
+}
+
+void sys_reg_trace_enable(cpu_context_t *ctx)
+{
+	uint64_t val;
+
+	if (sys_reg_trace_supported()) {
+		/* Retrieve CPTR_EL3 value from the given context 'ctx',
+		 * and update CPTR_EL3.TTA bit to 0.
+		 * This function is called while switching context to NS to
+		 * allow system trace register access to NS-EL2 and NS-EL1
+		 * when NS-EL2 is implemented but not used.
+		 */
+		val = read_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3);
+		val &= ~TTA_BIT;
+		write_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3, val);
+	}
+}
diff --git a/lib/extensions/trbe/trbe.c b/lib/extensions/trbe/trbe.c
new file mode 100644
index 0000000..9f754d5
--- /dev/null
+++ b/lib/extensions/trbe/trbe.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <lib/el3_runtime/pubsub.h>
+#include <lib/extensions/trbe.h>
+
+static void tsb_csync(void)
+{
+	/*
+	 * The assembler does not yet understand the tsb csync mnemonic
+	 * so use the equivalent hint instruction.
+	 */
+	__asm__ volatile("hint #18");
+}
+
+static bool trbe_supported(void)
+{
+	uint64_t features;
+
+	features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEBUFFER_SHIFT;
+	return ((features & ID_AA64DFR0_TRACEBUFFER_MASK) ==
+		ID_AA64DFR0_TRACEBUFFER_SUPPORTED);
+}
+
+void trbe_enable(void)
+{
+	uint64_t val;
+
+	if (trbe_supported()) {
+		/*
+		 * MDCR_EL3.NSTB = 0b11
+		 * Allow access of trace buffer control registers from NS-EL1
+		 * and NS-EL2, tracing is prohibited in Secure and Realm state
+		 * (if implemented).
+		 */
+		val = read_mdcr_el3();
+		val |= MDCR_NSTB(MDCR_NSTB_EL1);
+		write_mdcr_el3(val);
+	}
+}
+
+static void *trbe_drain_trace_buffers_hook(const void *arg __unused)
+{
+	if (trbe_supported()) {
+		/*
+		 * Before switching from normal world to secure world
+		 * the trace buffers need to be drained out to memory. This is
+		 * required to avoid an invalid memory access when TTBR is switched
+		 * for entry to S-EL1.
+		 */
+		tsb_csync();
+		dsbnsh();
+	}
+
+	return (void *)0;
+}
+
+SUBSCRIBE_TO_EVENT(cm_entering_secure_world, trbe_drain_trace_buffers_hook);
diff --git a/lib/extensions/trf/aarch32/trf.c b/lib/extensions/trf/aarch32/trf.c
new file mode 100644
index 0000000..834092d
--- /dev/null
+++ b/lib/extensions/trf/aarch32/trf.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <lib/extensions/trf.h>
+
+static bool trf_supported(void)
+{
+	uint32_t features;
+
+	features = read_id_dfr0() >> ID_DFR0_TRACEFILT_SHIFT;
+	return ((features & ID_DFR0_TRACEFILT_MASK) ==
+		ID_DFR0_TRACEFILT_SUPPORTED);
+}
+
+void trf_enable(void)
+{
+	uint32_t val;
+
+	if (trf_supported()) {
+		/*
+		 * Allow access of trace filter control registers from
+		 * non-monitor mode
+		 */
+		val = read_sdcr();
+		val &= ~SDCR_TTRF_BIT;
+		write_sdcr(val);
+	}
+}
diff --git a/lib/extensions/trf/aarch64/trf.c b/lib/extensions/trf/aarch64/trf.c
new file mode 100644
index 0000000..1da5dce
--- /dev/null
+++ b/lib/extensions/trf/aarch64/trf.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <lib/extensions/trf.h>
+
+static bool trf_supported(void)
+{
+	uint64_t features;
+
+	features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEFILT_SHIFT;
+	return ((features & ID_AA64DFR0_TRACEFILT_MASK) ==
+		ID_AA64DFR0_TRACEFILT_SUPPORTED);
+}
+
+void trf_enable(void)
+{
+	uint64_t val;
+
+	if (trf_supported()) {
+		/*
+		 * MDCR_EL3.TTRF = b0
+		 * Allow access of trace filter control registers from NS-EL2
+		 * and NS-EL1 when NS-EL2 is implemented but not used
+		 */
+		val = read_mdcr_el3();
+		val &= ~MDCR_TTRF_BIT;
+		write_mdcr_el3(val);
+	}
+}
diff --git a/lib/gpt_rme/gpt_rme.c b/lib/gpt_rme/gpt_rme.c
new file mode 100644
index 0000000..1f90e64
--- /dev/null
+++ b/lib/gpt_rme/gpt_rme.c
@@ -0,0 +1,1112 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include "gpt_rme_private.h"
+#include <lib/gpt_rme/gpt_rme.h>
+#include <lib/smccc.h>
+#include <lib/spinlock.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#if !ENABLE_RME
+#error "ENABLE_RME must be enabled to use the GPT library."
+#endif
+
+/*
+ * Lookup T from PPS
+ *
+ *   PPS    Size    T
+ *   0b000  4GB     32
+ *   0b001  64GB    36
+ *   0b010  1TB     40
+ *   0b011  4TB     42
+ *   0b100  16TB    44
+ *   0b101  256TB   48
+ *   0b110  4PB     52
+ *
+ * See section 15.1.27 of the RME specification.
+ */
+static const gpt_t_val_e gpt_t_lookup[] = {PPS_4GB_T, PPS_64GB_T,
+					   PPS_1TB_T, PPS_4TB_T,
+					   PPS_16TB_T, PPS_256TB_T,
+					   PPS_4PB_T};
+
+/*
+ * Lookup P from PGS
+ *
+ *   PGS    Size    P
+ *   0b00   4KB     12
+ *   0b10   16KB    14
+ *   0b01   64KB    16
+ *
+ * Note that pgs=0b10 is 16KB and pgs=0b01 is 64KB, this is not a typo.
+ *
+ * See section 15.1.27 of the RME specification.
+ */
+static const gpt_p_val_e gpt_p_lookup[] = {PGS_4KB_P, PGS_64KB_P, PGS_16KB_P};
+
+/*
+ * This structure contains GPT configuration data.
+ */
+typedef struct {
+	uintptr_t plat_gpt_l0_base;
+	gpccr_pps_e pps;
+	gpt_t_val_e t;
+	gpccr_pgs_e pgs;
+	gpt_p_val_e p;
+} gpt_config_t;
+
+static gpt_config_t gpt_config;
+
+/* These variables are used during initialization of the L1 tables. */
+static unsigned int gpt_next_l1_tbl_idx;
+static uintptr_t gpt_l1_tbl;
+
+/*
+ * This function checks to see if a GPI value is valid.
+ *
+ * These are valid GPI values.
+ *   GPT_GPI_NO_ACCESS   U(0x0)
+ *   GPT_GPI_SECURE      U(0x8)
+ *   GPT_GPI_NS          U(0x9)
+ *   GPT_GPI_ROOT        U(0xA)
+ *   GPT_GPI_REALM       U(0xB)
+ *   GPT_GPI_ANY         U(0xF)
+ *
+ * Parameters
+ *   gpi		GPI to check for validity.
+ *
+ * Return
+ *   true for a valid GPI, false for an invalid one.
+ */
+static bool gpt_is_gpi_valid(unsigned int gpi)
+{
+	if ((gpi == GPT_GPI_NO_ACCESS) || (gpi == GPT_GPI_ANY) ||
+	    ((gpi >= GPT_GPI_SECURE) && (gpi <= GPT_GPI_REALM))) {
+		return true;
+	} else {
+		return false;
+	}
+}
+
+/*
+ * This function checks to see if two PAS regions overlap.
+ *
+ * Parameters
+ *   base_1: base address of first PAS
+ *   size_1: size of first PAS
+ *   base_2: base address of second PAS
+ *   size_2: size of second PAS
+ *
+ * Return
+ *   True if PAS regions overlap, false if they do not.
+ */
+static bool gpt_check_pas_overlap(uintptr_t base_1, size_t size_1,
+				  uintptr_t base_2, size_t size_2)
+{
+	if (((base_1 + size_1) > base_2) && ((base_2 + size_2) > base_1)) {
+		return true;
+	} else {
+		return false;
+	}
+}
+
+/*
+ * This helper function checks to see if a PAS region from index 0 to
+ * (pas_idx - 1) occupies the L0 region at index l0_idx in the L0 table.
+ *
+ * Parameters
+ *   l0_idx:      Index of the L0 entry to check
+ *   pas_regions: PAS region array
+ *   pas_idx:     Upper bound of the PAS array index.
+ *
+ * Return
+ *   True if a PAS region occupies the L0 region in question, false if not.
+ */
+static bool gpt_does_previous_pas_exist_here(unsigned int l0_idx,
+					     pas_region_t *pas_regions,
+					     unsigned int pas_idx)
+{
+	/* Iterate over PAS regions up to pas_idx. */
+	for (unsigned int i = 0U; i < pas_idx; i++) {
+		if (gpt_check_pas_overlap((GPT_L0GPTSZ_ACTUAL_SIZE * l0_idx),
+		    GPT_L0GPTSZ_ACTUAL_SIZE,
+		    pas_regions[i].base_pa, pas_regions[i].size)) {
+			return true;
+		}
+	}
+	return false;
+}
+
+/*
+ * This function iterates over all of the PAS regions and checks them to ensure
+ * proper alignment of base and size, that the GPI is valid, and that no regions
+ * overlap. As a part of the overlap checks, this function checks existing L0
+ * mappings against the new PAS regions in the event that gpt_init_pas_l1_tables
+ * is called multiple times to place L1 tables in different areas of memory. It
+ * also counts the number of L1 tables needed and returns it on success.
+ *
+ * Parameters
+ *   *pas_regions	Pointer to array of PAS region structures.
+ *   pas_region_cnt	Total number of PAS regions in the array.
+ *
+ * Return
+ *   Negative Linux error code in the event of a failure, number of L1 regions
+ *   required when successful.
+ */
+static int gpt_validate_pas_mappings(pas_region_t *pas_regions,
+				     unsigned int pas_region_cnt)
+{
+	unsigned int idx;
+	unsigned int l1_cnt = 0U;
+	unsigned int pas_l1_cnt;
+	uint64_t *l0_desc = (uint64_t *)gpt_config.plat_gpt_l0_base;
+
+	assert(pas_regions != NULL);
+	assert(pas_region_cnt != 0U);
+
+	for (idx = 0U; idx < pas_region_cnt; idx++) {
+		/* Check for arithmetic overflow in region. */
+		if ((ULONG_MAX - pas_regions[idx].base_pa) <
+		    pas_regions[idx].size) {
+			ERROR("[GPT] Address overflow in PAS[%u]!\n", idx);
+			return -EOVERFLOW;
+		}
+
+		/* Initial checks for PAS validity. */
+		if (((pas_regions[idx].base_pa + pas_regions[idx].size) >
+		    GPT_PPS_ACTUAL_SIZE(gpt_config.t)) ||
+		    !gpt_is_gpi_valid(GPT_PAS_ATTR_GPI(pas_regions[idx].attrs))) {
+			ERROR("[GPT] PAS[%u] is invalid!\n", idx);
+			return -EFAULT;
+		}
+
+		/*
+		 * Make sure this PAS does not overlap with another one. We
+		 * start from idx + 1 instead of 0 since prior PAS mappings will
+		 * have already checked themselves against this one.
+		 */
+		for (unsigned int i = idx + 1; i < pas_region_cnt; i++) {
+			if (gpt_check_pas_overlap(pas_regions[idx].base_pa,
+			    pas_regions[idx].size,
+			    pas_regions[i].base_pa,
+			    pas_regions[i].size)) {
+				ERROR("[GPT] PAS[%u] overlaps with PAS[%u]\n",
+					i, idx);
+				return -EFAULT;
+			}
+		}
+
+		/*
+		 * Since this function can be called multiple times with
+		 * separate L1 tables we need to check the existing L0 mapping
+		 * to see if this PAS would fall into one that has already been
+		 * initialized.
+		 */
+		for (unsigned int i = GPT_L0_IDX(pas_regions[idx].base_pa);
+		     i <= GPT_L0_IDX(pas_regions[idx].base_pa + pas_regions[idx].size - 1);
+		     i++) {
+			if ((GPT_L0_TYPE(l0_desc[i]) == GPT_L0_TYPE_BLK_DESC) &&
+			    (GPT_L0_BLKD_GPI(l0_desc[i]) == GPT_GPI_ANY)) {
+				/* This descriptor is unused so continue. */
+				continue;
+			}
+
+			/*
+			 * This descriptor has been initialized in a previous
+			 * call to this function so cannot be initialized again.
+			 */
+			ERROR("[GPT] PAS[%u] overlaps with previous L0[%d]!\n",
+			      idx, i);
+			return -EFAULT;
+		}
+
+		/* Check for block mapping (L0) type. */
+		if (GPT_PAS_ATTR_MAP_TYPE(pas_regions[idx].attrs) ==
+		    GPT_PAS_ATTR_MAP_TYPE_BLOCK) {
+			/* Make sure base and size are block-aligned. */
+			if (!GPT_IS_L0_ALIGNED(pas_regions[idx].base_pa) ||
+			    !GPT_IS_L0_ALIGNED(pas_regions[idx].size)) {
+				ERROR("[GPT] PAS[%u] is not block-aligned!\n",
+				      idx);
+				return -EFAULT;
+			}
+
+			continue;
+		}
+
+		/* Check for granule mapping (L1) type. */
+		if (GPT_PAS_ATTR_MAP_TYPE(pas_regions[idx].attrs) ==
+		    GPT_PAS_ATTR_MAP_TYPE_GRANULE) {
+			/* Make sure base and size are granule-aligned. */
+			if (!GPT_IS_L1_ALIGNED(gpt_config.p, pas_regions[idx].base_pa) ||
+			    !GPT_IS_L1_ALIGNED(gpt_config.p, pas_regions[idx].size)) {
+				ERROR("[GPT] PAS[%u] is not granule-aligned!\n",
+				      idx);
+				return -EFAULT;
+			}
+
+			/* Find how many L1 tables this PAS occupies. */
+			pas_l1_cnt = (GPT_L0_IDX(pas_regions[idx].base_pa +
+				     pas_regions[idx].size - 1) -
+				     GPT_L0_IDX(pas_regions[idx].base_pa) + 1);
+
+			/*
+			 * This creates a situation where, if multiple PAS
+			 * regions occupy the same table descriptor, we can get
+			 * an artificially high total L1 table count. The way we
+			 * handle this is by checking each PAS against those
+			 * before it in the array, and if they both occupy the
+			 * same PAS we subtract from pas_l1_cnt and only the
+			 * first PAS in the array gets to count it.
+			 */
+
+			/*
+			 * If L1 count is greater than 1 we know the start and
+			 * end PAs are in different L0 regions so we must check
+			 * both for overlap against other PAS.
+			 */
+			if (pas_l1_cnt > 1) {
+				if (gpt_does_previous_pas_exist_here(
+				    GPT_L0_IDX(pas_regions[idx].base_pa +
+				    pas_regions[idx].size - 1),
+				    pas_regions, idx)) {
+					pas_l1_cnt = pas_l1_cnt - 1;
+				}
+			}
+
+			if (gpt_does_previous_pas_exist_here(
+			    GPT_L0_IDX(pas_regions[idx].base_pa),
+			    pas_regions, idx)) {
+				pas_l1_cnt = pas_l1_cnt - 1;
+			}
+
+			l1_cnt += pas_l1_cnt;
+			continue;
+		}
+
+		/* If execution reaches this point, mapping type is invalid. */
+		ERROR("[GPT] PAS[%u] has invalid mapping type 0x%x.\n", idx,
+		      GPT_PAS_ATTR_MAP_TYPE(pas_regions[idx].attrs));
+		return -EINVAL;
+	}
+
+	return l1_cnt;
+}
+
+/*
+ * This function validates L0 initialization parameters.
+ *
+ * Parameters
+ *   l0_mem_base	Base address of memory used for L0 tables.
+ *   l1_mem_size	Size of memory available for L0 tables.
+ *
+ * Return
+ *   Negative Linux error code in the event of a failure, 0 for success.
+ */
+static int gpt_validate_l0_params(gpccr_pps_e pps, uintptr_t l0_mem_base,
+				  size_t l0_mem_size)
+{
+	size_t l0_alignment;
+
+	/*
+	 * Make sure PPS is valid and then store it since macros need this value
+	 * to work.
+	 */
+	if (pps > GPT_PPS_MAX) {
+		ERROR("[GPT] Invalid PPS: 0x%x\n", pps);
+		return -EINVAL;
+	}
+	gpt_config.pps = pps;
+	gpt_config.t = gpt_t_lookup[pps];
+
+	/* Alignment must be the greater of 4k or l0 table size. */
+	l0_alignment = PAGE_SIZE_4KB;
+	if (l0_alignment < GPT_L0_TABLE_SIZE(gpt_config.t)) {
+		l0_alignment = GPT_L0_TABLE_SIZE(gpt_config.t);
+	}
+
+	/* Check base address. */
+	if ((l0_mem_base == 0U) || ((l0_mem_base & (l0_alignment - 1)) != 0U)) {
+		ERROR("[GPT] Invalid L0 base address: 0x%lx\n", l0_mem_base);
+		return -EFAULT;
+	}
+
+	/* Check size. */
+	if (l0_mem_size < GPT_L0_TABLE_SIZE(gpt_config.t)) {
+		ERROR("[GPT] Inadequate L0 memory: need 0x%lx, have 0x%lx)\n",
+		      GPT_L0_TABLE_SIZE(gpt_config.t),
+		      l0_mem_size);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/*
+ * In the event that L1 tables are needed, this function validates
+ * the L1 table generation parameters.
+ *
+ * Parameters
+ *   l1_mem_base	Base address of memory used for L1 table allocation.
+ *   l1_mem_size	Total size of memory available for L1 tables.
+ *   l1_gpt_cnt		Number of L1 tables needed.
+ *
+ * Return
+ *   Negative Linux error code in the event of a failure, 0 for success.
+ */
+static int gpt_validate_l1_params(uintptr_t l1_mem_base, size_t l1_mem_size,
+				  unsigned int l1_gpt_cnt)
+{
+	size_t l1_gpt_mem_sz;
+
+	/* Check if the granularity is supported */
+	if (!xlat_arch_is_granule_size_supported(
+	    GPT_PGS_ACTUAL_SIZE(gpt_config.p))) {
+		return -EPERM;
+	}
+
+	/* Make sure L1 tables are aligned to their size. */
+	if ((l1_mem_base & (GPT_L1_TABLE_SIZE(gpt_config.p) - 1)) != 0U) {
+		ERROR("[GPT] Unaligned L1 GPT base address: 0x%lx\n",
+		      l1_mem_base);
+		return -EFAULT;
+	}
+
+	/* Get total memory needed for L1 tables. */
+	l1_gpt_mem_sz = l1_gpt_cnt * GPT_L1_TABLE_SIZE(gpt_config.p);
+
+	/* Check for overflow. */
+	if ((l1_gpt_mem_sz / GPT_L1_TABLE_SIZE(gpt_config.p)) != l1_gpt_cnt) {
+		ERROR("[GPT] Overflow calculating L1 memory size.\n");
+		return -ENOMEM;
+	}
+
+	/* Make sure enough space was supplied. */
+	if (l1_mem_size < l1_gpt_mem_sz) {
+		ERROR("[GPT] Inadequate memory for L1 GPTs. ");
+		ERROR("      Expected 0x%lx bytes. Got 0x%lx bytes\n",
+		      l1_gpt_mem_sz, l1_mem_size);
+		return -ENOMEM;
+	}
+
+	VERBOSE("[GPT] Requested 0x%lx bytes for L1 GPTs.\n", l1_gpt_mem_sz);
+	return 0;
+}
+
+/*
+ * This function initializes L0 block descriptors (regions that cannot be
+ * transitioned at the granule level) according to the provided PAS.
+ *
+ * Parameters
+ *   *pas		Pointer to the structure defining the PAS region to
+ *			initialize.
+ */
+static void gpt_generate_l0_blk_desc(pas_region_t *pas)
+{
+	uint64_t gpt_desc;
+	unsigned int end_idx;
+	unsigned int idx;
+	uint64_t *l0_gpt_arr;
+
+	assert(gpt_config.plat_gpt_l0_base != 0U);
+	assert(pas != NULL);
+
+	/*
+	 * Checking of PAS parameters has already been done in
+	 * gpt_validate_pas_mappings so no need to check the same things again.
+	 */
+
+	l0_gpt_arr = (uint64_t *)gpt_config.plat_gpt_l0_base;
+
+	/* Create the GPT Block descriptor for this PAS region */
+	gpt_desc = GPT_L0_BLK_DESC(GPT_PAS_ATTR_GPI(pas->attrs));
+
+	/* Start index of this region in L0 GPTs */
+	idx = pas->base_pa >> GPT_L0_IDX_SHIFT;
+
+	/*
+	 * Determine number of L0 GPT descriptors covered by
+	 * this PAS region and use the count to populate these
+	 * descriptors.
+	 */
+	end_idx = (pas->base_pa + pas->size) >> GPT_L0_IDX_SHIFT;
+
+	/* Generate the needed block descriptors. */
+	for (; idx < end_idx; idx++) {
+		l0_gpt_arr[idx] = gpt_desc;
+		VERBOSE("[GPT] L0 entry (BLOCK) index %u [%p]: GPI = 0x%llx (0x%llx)\n",
+			idx, &l0_gpt_arr[idx],
+			(gpt_desc >> GPT_L0_BLK_DESC_GPI_SHIFT) &
+			GPT_L0_BLK_DESC_GPI_MASK, l0_gpt_arr[idx]);
+	}
+}
+
+/*
+ * Helper function to determine if the end physical address lies in the same L0
+ * region as the current physical address. If true, the end physical address is
+ * returned else, the start address of the next region is returned.
+ *
+ * Parameters
+ *   cur_pa		Physical address of the current PA in the loop through
+ *			the range.
+ *   end_pa		Physical address of the end PA in a PAS range.
+ *
+ * Return
+ *   The PA of the end of the current range.
+ */
+static uintptr_t gpt_get_l1_end_pa(uintptr_t cur_pa, uintptr_t end_pa)
+{
+	uintptr_t cur_idx;
+	uintptr_t end_idx;
+
+	cur_idx = cur_pa >> GPT_L0_IDX_SHIFT;
+	end_idx = end_pa >> GPT_L0_IDX_SHIFT;
+
+	assert(cur_idx <= end_idx);
+
+	if (cur_idx == end_idx) {
+		return end_pa;
+	}
+
+	return (cur_idx + 1U) << GPT_L0_IDX_SHIFT;
+}
+
+/*
+ * Helper function to fill out GPI entries in a single L1 table. This function
+ * fills out entire L1 descriptors at a time to save memory writes.
+ *
+ * Parameters
+ *   gpi		GPI to set this range to
+ *   l1			Pointer to L1 table to fill out
+ *   first		Address of first granule in range.
+ *   last		Address of last granule in range (inclusive).
+ */
+static void gpt_fill_l1_tbl(uint64_t gpi, uint64_t *l1, uintptr_t first,
+			    uintptr_t last)
+{
+	uint64_t gpi_field = GPT_BUILD_L1_DESC(gpi);
+	uint64_t gpi_mask = 0xFFFFFFFFFFFFFFFF;
+
+	assert(first <= last);
+	assert((first & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) == 0U);
+	assert((last & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) == 0U);
+	assert(GPT_L0_IDX(first) == GPT_L0_IDX(last));
+	assert(l1 != NULL);
+
+	/* Shift the mask if we're starting in the middle of an L1 entry. */
+	gpi_mask = gpi_mask << (GPT_L1_GPI_IDX(gpt_config.p, first) << 2);
+
+	/* Fill out each L1 entry for this region. */
+	for (unsigned int i = GPT_L1_IDX(gpt_config.p, first);
+	     i <= GPT_L1_IDX(gpt_config.p, last); i++) {
+		/* Account for stopping in the middle of an L1 entry. */
+		if (i == GPT_L1_IDX(gpt_config.p, last)) {
+			gpi_mask &= (gpi_mask >> ((15 -
+				    GPT_L1_GPI_IDX(gpt_config.p, last)) << 2));
+		}
+
+		/* Write GPI values. */
+		assert((l1[i] & gpi_mask) ==
+		       (GPT_BUILD_L1_DESC(GPT_GPI_ANY) & gpi_mask));
+		l1[i] = (l1[i] & ~gpi_mask) | (gpi_mask & gpi_field);
+
+		/* Reset mask. */
+		gpi_mask = 0xFFFFFFFFFFFFFFFF;
+	}
+}
+
+/*
+ * This function finds the next available unused L1 table and initializes all
+ * granules descriptor entries to GPI_ANY. This ensures that there are no chunks
+ * of GPI_NO_ACCESS (0b0000) memory floating around in the system in the
+ * event that a PAS region stops midway through an L1 table, thus guaranteeing
+ * that all memory not explicitly assigned is GPI_ANY. This function does not
+ * check for overflow conditions, that should be done by the caller.
+ *
+ * Return
+ *   Pointer to the next available L1 table.
+ */
+static uint64_t *gpt_get_new_l1_tbl(void)
+{
+	/* Retrieve the next L1 table. */
+	uint64_t *l1 = (uint64_t *)((uint64_t)(gpt_l1_tbl) +
+		       (GPT_L1_TABLE_SIZE(gpt_config.p) *
+		       gpt_next_l1_tbl_idx));
+
+	/* Increment L1 counter. */
+	gpt_next_l1_tbl_idx++;
+
+	/* Initialize all GPIs to GPT_GPI_ANY */
+	for (unsigned int i = 0U; i < GPT_L1_ENTRY_COUNT(gpt_config.p); i++) {
+		l1[i] = GPT_BUILD_L1_DESC(GPT_GPI_ANY);
+	}
+
+	return l1;
+}
+
+/*
+ * When L1 tables are needed, this function creates the necessary L0 table
+ * descriptors and fills out the L1 table entries according to the supplied
+ * PAS range.
+ *
+ * Parameters
+ *   *pas		Pointer to the structure defining the PAS region.
+ */
+static void gpt_generate_l0_tbl_desc(pas_region_t *pas)
+{
+	uintptr_t end_pa;
+	uintptr_t cur_pa;
+	uintptr_t last_gran_pa;
+	uint64_t *l0_gpt_base;
+	uint64_t *l1_gpt_arr;
+	unsigned int l0_idx;
+
+	assert(gpt_config.plat_gpt_l0_base != 0U);
+	assert(pas != NULL);
+
+	/*
+	 * Checking of PAS parameters has already been done in
+	 * gpt_validate_pas_mappings so no need to check the same things again.
+	 */
+
+	end_pa = pas->base_pa + pas->size;
+	l0_gpt_base = (uint64_t *)gpt_config.plat_gpt_l0_base;
+
+	/* We start working from the granule at base PA */
+	cur_pa = pas->base_pa;
+
+	/* Iterate over each L0 region in this memory range. */
+	for (l0_idx = GPT_L0_IDX(pas->base_pa);
+	     l0_idx <= GPT_L0_IDX(end_pa - 1U);
+	     l0_idx++) {
+
+		/*
+		 * See if the L0 entry is already a table descriptor or if we
+		 * need to create one.
+		 */
+		if (GPT_L0_TYPE(l0_gpt_base[l0_idx]) == GPT_L0_TYPE_TBL_DESC) {
+			/* Get the L1 array from the L0 entry. */
+			l1_gpt_arr = GPT_L0_TBLD_ADDR(l0_gpt_base[l0_idx]);
+		} else {
+			/* Get a new L1 table from the L1 memory space. */
+			l1_gpt_arr = gpt_get_new_l1_tbl();
+
+			/* Fill out the L0 descriptor and flush it. */
+			l0_gpt_base[l0_idx] = GPT_L0_TBL_DESC(l1_gpt_arr);
+		}
+
+		VERBOSE("[GPT] L0 entry (TABLE) index %u [%p] ==> L1 Addr 0x%llx (0x%llx)\n",
+			l0_idx, &l0_gpt_base[l0_idx],
+			(unsigned long long)(l1_gpt_arr),
+			l0_gpt_base[l0_idx]);
+
+		/*
+		 * Determine the PA of the last granule in this L0 descriptor.
+		 */
+		last_gran_pa = gpt_get_l1_end_pa(cur_pa, end_pa) -
+			       GPT_PGS_ACTUAL_SIZE(gpt_config.p);
+
+		/*
+		 * Fill up L1 GPT entries between these two addresses. This
+		 * function needs the addresses of the first granule and last
+		 * granule in the range.
+		 */
+		gpt_fill_l1_tbl(GPT_PAS_ATTR_GPI(pas->attrs), l1_gpt_arr,
+				cur_pa, last_gran_pa);
+
+		/* Advance cur_pa to first granule in next L0 region. */
+		cur_pa = gpt_get_l1_end_pa(cur_pa, end_pa);
+	}
+}
+
+/*
+ * This function flushes a range of L0 descriptors used by a given PAS region
+ * array. There is a chance that some unmodified L0 descriptors would be flushed
+ * in the case that there are "holes" in an array of PAS regions but overall
+ * this should be faster than individually flushing each modified L0 descriptor
+ * as they are created.
+ *
+ * Parameters
+ *   *pas		Pointer to an array of PAS regions.
+ *   pas_count		Number of entries in the PAS array.
+ */
+static void flush_l0_for_pas_array(pas_region_t *pas, unsigned int pas_count)
+{
+	unsigned int idx;
+	unsigned int start_idx;
+	unsigned int end_idx;
+	uint64_t *l0 = (uint64_t *)gpt_config.plat_gpt_l0_base;
+
+	assert(pas != NULL);
+	assert(pas_count > 0);
+
+	/* Initial start and end values. */
+	start_idx = GPT_L0_IDX(pas[0].base_pa);
+	end_idx = GPT_L0_IDX(pas[0].base_pa + pas[0].size - 1);
+
+	/* Find lowest and highest L0 indices used in this PAS array. */
+	for (idx = 1; idx < pas_count; idx++) {
+		if (GPT_L0_IDX(pas[idx].base_pa) < start_idx) {
+			start_idx = GPT_L0_IDX(pas[idx].base_pa);
+		}
+		if (GPT_L0_IDX(pas[idx].base_pa + pas[idx].size - 1) > end_idx) {
+			end_idx = GPT_L0_IDX(pas[idx].base_pa + pas[idx].size - 1);
+		}
+	}
+
+	/*
+	 * Flush all covered L0 descriptors, add 1 because we need to include
+	 * the end index value.
+	 */
+	flush_dcache_range((uintptr_t)&l0[start_idx],
+			   ((end_idx + 1) - start_idx) * sizeof(uint64_t));
+}
+
+/*
+ * Public API to enable granule protection checks once the tables have all been
+ * initialized. This function is called at first initialization and then again
+ * later during warm boots of CPU cores.
+ *
+ * Return
+ *   Negative Linux error code in the event of a failure, 0 for success.
+ */
+int gpt_enable(void)
+{
+	u_register_t gpccr_el3;
+
+	/*
+	 * Granule tables must be initialised before enabling
+	 * granule protection.
+	 */
+	if (gpt_config.plat_gpt_l0_base == 0U) {
+		ERROR("[GPT] Tables have not been initialized!\n");
+		return -EPERM;
+	}
+
+	/* Invalidate any stale TLB entries */
+	tlbipaallos();
+	dsb();
+
+	/* Write the base address of the L0 tables into GPTBR */
+	write_gptbr_el3(((gpt_config.plat_gpt_l0_base >> GPTBR_BADDR_VAL_SHIFT)
+			>> GPTBR_BADDR_SHIFT) & GPTBR_BADDR_MASK);
+
+	/* GPCCR_EL3.PPS */
+	gpccr_el3 = SET_GPCCR_PPS(gpt_config.pps);
+
+	/* GPCCR_EL3.PGS */
+	gpccr_el3 |= SET_GPCCR_PGS(gpt_config.pgs);
+
+	/* Set shareability attribute to Outher Shareable */
+	gpccr_el3 |= SET_GPCCR_SH(GPCCR_SH_OS);
+
+	/* Outer and Inner cacheability set to Normal memory, WB, RA, WA. */
+	gpccr_el3 |= SET_GPCCR_ORGN(GPCCR_ORGN_WB_RA_WA);
+	gpccr_el3 |= SET_GPCCR_IRGN(GPCCR_IRGN_WB_RA_WA);
+
+	/* Enable GPT */
+	gpccr_el3 |= GPCCR_GPC_BIT;
+
+	/* TODO: Configure GPCCR_EL3_GPCP for Fault control. */
+	write_gpccr_el3(gpccr_el3);
+	tlbipaallos();
+	dsb();
+	isb();
+
+	return 0;
+}
+
+/*
+ * Public API to disable granule protection checks.
+ */
+void gpt_disable(void)
+{
+	u_register_t gpccr_el3 = read_gpccr_el3();
+
+	write_gpccr_el3(gpccr_el3 & ~GPCCR_GPC_BIT);
+	dsbsy();
+	isb();
+}
+
+/*
+ * Public API that initializes the entire protected space to GPT_GPI_ANY using
+ * the L0 tables (block descriptors). Ideally, this function is invoked prior
+ * to DDR discovery and initialization. The MMU must be initialized before
+ * calling this function.
+ *
+ * Parameters
+ *   pps		PPS value to use for table generation
+ *   l0_mem_base	Base address of L0 tables in memory.
+ *   l0_mem_size	Total size of memory available for L0 tables.
+ *
+ * Return
+ *   Negative Linux error code in the event of a failure, 0 for success.
+ */
+int gpt_init_l0_tables(unsigned int pps, uintptr_t l0_mem_base,
+		       size_t l0_mem_size)
+{
+	int ret;
+	uint64_t gpt_desc;
+
+	/* Ensure that MMU and caches are enabled. */
+	assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
+
+	/* Validate other parameters. */
+	ret = gpt_validate_l0_params(pps, l0_mem_base, l0_mem_size);
+	if (ret < 0) {
+		return ret;
+	}
+
+	/* Create the descriptor to initialize L0 entries with. */
+	gpt_desc = GPT_L0_BLK_DESC(GPT_GPI_ANY);
+
+	/* Iterate through all L0 entries */
+	for (unsigned int i = 0U; i < GPT_L0_REGION_COUNT(gpt_config.t); i++) {
+		((uint64_t *)l0_mem_base)[i] = gpt_desc;
+	}
+
+	/* Flush updated L0 tables to memory. */
+	flush_dcache_range((uintptr_t)l0_mem_base,
+			   (size_t)GPT_L0_TABLE_SIZE(gpt_config.t));
+
+	/* Stash the L0 base address once initial setup is complete. */
+	gpt_config.plat_gpt_l0_base = l0_mem_base;
+
+	return 0;
+}
+
+/*
+ * Public API that carves out PAS regions from the L0 tables and builds any L1
+ * tables that are needed. This function ideally is run after DDR discovery and
+ * initialization. The L0 tables must have already been initialized to GPI_ANY
+ * when this function is called.
+ *
+ * This function can be called multiple times with different L1 memory ranges
+ * and PAS regions if it is desirable to place L1 tables in different locations
+ * in memory. (ex: you have multiple DDR banks and want to place the L1 tables
+ * in the DDR bank that they control)
+ *
+ * Parameters
+ *   pgs		PGS value to use for table generation.
+ *   l1_mem_base	Base address of memory used for L1 tables.
+ *   l1_mem_size	Total size of memory available for L1 tables.
+ *   *pas_regions	Pointer to PAS regions structure array.
+ *   pas_count		Total number of PAS regions.
+ *
+ * Return
+ *   Negative Linux error code in the event of a failure, 0 for success.
+ */
+int gpt_init_pas_l1_tables(gpccr_pgs_e pgs, uintptr_t l1_mem_base,
+			   size_t l1_mem_size, pas_region_t *pas_regions,
+			   unsigned int pas_count)
+{
+	int ret;
+	int l1_gpt_cnt;
+
+	/* Ensure that MMU and caches are enabled. */
+	assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
+
+	/* PGS is needed for gpt_validate_pas_mappings so check it now. */
+	if (pgs > GPT_PGS_MAX) {
+		ERROR("[GPT] Invalid PGS: 0x%x\n", pgs);
+		return -EINVAL;
+	}
+	gpt_config.pgs = pgs;
+	gpt_config.p = gpt_p_lookup[pgs];
+
+	/* Make sure L0 tables have been initialized. */
+	if (gpt_config.plat_gpt_l0_base == 0U) {
+		ERROR("[GPT] L0 tables must be initialized first!\n");
+		return -EPERM;
+	}
+
+	/* Check if L1 GPTs are required and how many. */
+	l1_gpt_cnt = gpt_validate_pas_mappings(pas_regions, pas_count);
+	if (l1_gpt_cnt < 0) {
+		return l1_gpt_cnt;
+	}
+
+	VERBOSE("[GPT] %u L1 GPTs requested.\n", l1_gpt_cnt);
+
+	/* If L1 tables are needed then validate the L1 parameters. */
+	if (l1_gpt_cnt > 0) {
+		ret = gpt_validate_l1_params(l1_mem_base, l1_mem_size,
+		      l1_gpt_cnt);
+		if (ret < 0) {
+			return ret;
+		}
+
+		/* Set up parameters for L1 table generation. */
+		gpt_l1_tbl = l1_mem_base;
+		gpt_next_l1_tbl_idx = 0U;
+	}
+
+	INFO("[GPT] Boot Configuration\n");
+	INFO("  PPS/T:     0x%x/%u\n", gpt_config.pps, gpt_config.t);
+	INFO("  PGS/P:     0x%x/%u\n", gpt_config.pgs, gpt_config.p);
+	INFO("  L0GPTSZ/S: 0x%x/%u\n", GPT_L0GPTSZ, GPT_S_VAL);
+	INFO("  PAS count: 0x%x\n", pas_count);
+	INFO("  L0 base:   0x%lx\n", gpt_config.plat_gpt_l0_base);
+
+	/* Generate the tables in memory. */
+	for (unsigned int idx = 0U; idx < pas_count; idx++) {
+		INFO("[GPT] PAS[%u]: base 0x%lx, size 0x%lx, GPI 0x%x, type 0x%x\n",
+		     idx, pas_regions[idx].base_pa, pas_regions[idx].size,
+		     GPT_PAS_ATTR_GPI(pas_regions[idx].attrs),
+		     GPT_PAS_ATTR_MAP_TYPE(pas_regions[idx].attrs));
+
+		/* Check if a block or table descriptor is required */
+		if (GPT_PAS_ATTR_MAP_TYPE(pas_regions[idx].attrs) ==
+		    GPT_PAS_ATTR_MAP_TYPE_BLOCK) {
+			gpt_generate_l0_blk_desc(&pas_regions[idx]);
+
+		} else {
+			gpt_generate_l0_tbl_desc(&pas_regions[idx]);
+		}
+	}
+
+	/* Flush modified L0 tables. */
+	flush_l0_for_pas_array(pas_regions, pas_count);
+
+	/* Flush L1 tables if needed. */
+	if (l1_gpt_cnt > 0) {
+		flush_dcache_range(l1_mem_base,
+				   GPT_L1_TABLE_SIZE(gpt_config.p) *
+				   l1_gpt_cnt);
+	}
+
+	/* Make sure that all the entries are written to the memory. */
+	dsbishst();
+
+	return 0;
+}
+
+/*
+ * Public API to initialize the runtime gpt_config structure based on the values
+ * present in the GPTBR_EL3 and GPCCR_EL3 registers. GPT initialization
+ * typically happens in a bootloader stage prior to setting up the EL3 runtime
+ * environment for the granule transition service so this function detects the
+ * initialization from a previous stage. Granule protection checks must be
+ * enabled already or this function will return an error.
+ *
+ * Return
+ *   Negative Linux error code in the event of a failure, 0 for success.
+ */
+int gpt_runtime_init(void)
+{
+	u_register_t reg;
+
+	/* Ensure that MMU and caches are enabled. */
+	assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
+
+	/* Ensure GPC are already enabled. */
+	if ((read_gpccr_el3() & GPCCR_GPC_BIT) == 0U) {
+		ERROR("[GPT] Granule protection checks are not enabled!\n");
+		return -EPERM;
+	}
+
+	/*
+	 * Read the L0 table address from GPTBR, we don't need the L1 base
+	 * address since those are included in the L0 tables as needed.
+	 */
+	reg = read_gptbr_el3();
+	gpt_config.plat_gpt_l0_base = ((reg >> GPTBR_BADDR_SHIFT) &
+				      GPTBR_BADDR_MASK) <<
+				      GPTBR_BADDR_VAL_SHIFT;
+
+	/* Read GPCCR to get PGS and PPS values. */
+	reg = read_gpccr_el3();
+	gpt_config.pps = (reg >> GPCCR_PPS_SHIFT) & GPCCR_PPS_MASK;
+	gpt_config.t = gpt_t_lookup[gpt_config.pps];
+	gpt_config.pgs = (reg >> GPCCR_PGS_SHIFT) & GPCCR_PGS_MASK;
+	gpt_config.p = gpt_p_lookup[gpt_config.pgs];
+
+	VERBOSE("[GPT] Runtime Configuration\n");
+	VERBOSE("  PPS/T:     0x%x/%u\n", gpt_config.pps, gpt_config.t);
+	VERBOSE("  PGS/P:     0x%x/%u\n", gpt_config.pgs, gpt_config.p);
+	VERBOSE("  L0GPTSZ/S: 0x%x/%u\n", GPT_L0GPTSZ, GPT_S_VAL);
+	VERBOSE("  L0 base:   0x%lx\n", gpt_config.plat_gpt_l0_base);
+
+	return 0;
+}
+
+/*
+ * The L1 descriptors are protected by a spinlock to ensure that multiple
+ * CPUs do not attempt to change the descriptors at once. In the future it
+ * would be better to have separate spinlocks for each L1 descriptor.
+ */
+static spinlock_t gpt_lock;
+
+/*
+ * Check if caller is allowed to transition a PAS.
+ *
+ * - Secure world caller can only request S <-> NS transitions on a
+ *   granule that is already in either S or NS PAS.
+ *
+ * - Realm world caller can only request R <-> NS transitions on a
+ *   granule that is already in either R or NS PAS.
+ *
+ * Parameters
+ *   src_sec_state	Security state of the caller.
+ *   current_gpi	Current GPI of the granule.
+ *   target_gpi		Requested new GPI for the granule.
+ *
+ * Return
+ *   Negative Linux error code in the event of a failure, 0 for success.
+ */
+static int gpt_check_transition_gpi(unsigned int src_sec_state,
+				    unsigned int current_gpi,
+				    unsigned int target_gpi)
+{
+	unsigned int check_gpi;
+
+	/* Cannot transition a granule to the state it is already in. */
+	if (current_gpi == target_gpi) {
+		return -EINVAL;
+	}
+
+	/* Check security state, only secure and realm can transition. */
+	if (src_sec_state == SMC_FROM_REALM) {
+		check_gpi = GPT_GPI_REALM;
+	} else if (src_sec_state == SMC_FROM_SECURE) {
+		check_gpi = GPT_GPI_SECURE;
+	} else {
+		return -EINVAL;
+	}
+
+	/* Make sure security state is allowed to make the transition. */
+	if ((target_gpi != check_gpi) && (target_gpi != GPT_GPI_NS)) {
+		return -EINVAL;
+	}
+	if ((current_gpi != check_gpi) && (current_gpi != GPT_GPI_NS)) {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * This function is the core of the granule transition service. When a granule
+ * transition request occurs it is routed to this function where the request is
+ * validated then fulfilled if possible.
+ *
+ * TODO: implement support for transitioning multiple granules at once.
+ *
+ * Parameters
+ *   base		Base address of the region to transition, must be
+ *			aligned to granule size.
+ *   size		Size of region to transition, must be aligned to granule
+ *			size.
+ *   src_sec_state	Security state of the caller.
+ *   target_pas		Target PAS of the specified memory region.
+ *
+ * Return
+ *    Negative Linux error code in the event of a failure, 0 for success.
+ */
+int gpt_transition_pas(uint64_t base, size_t size, unsigned int src_sec_state,
+	unsigned int target_pas)
+{
+	int idx;
+	unsigned int gpi_shift;
+	unsigned int gpi;
+	uint64_t gpt_l0_desc;
+	uint64_t gpt_l1_desc;
+	uint64_t *gpt_l1_addr;
+	uint64_t *gpt_l0_base;
+
+	/* Ensure that the tables have been set up before taking requests. */
+	assert(gpt_config.plat_gpt_l0_base != 0U);
+
+	/* Check for address range overflow. */
+	if ((ULONG_MAX - base) < size) {
+		VERBOSE("[GPT] Transition request address overflow!\n");
+		VERBOSE("      Base=0x%llx\n", base);
+		VERBOSE("      Size=0x%lx\n", size);
+		return -EINVAL;
+	}
+
+	/* Make sure base and size are valid. */
+	if (((base & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) != 0U) ||
+	    ((size & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) != 0U) ||
+	    (size == 0U) ||
+	    ((base + size) >= GPT_PPS_ACTUAL_SIZE(gpt_config.t))) {
+		VERBOSE("[GPT] Invalid granule transition address range!\n");
+		VERBOSE("      Base=0x%llx\n", base);
+		VERBOSE("      Size=0x%lx\n", size);
+		return -EINVAL;
+	}
+
+	/* See if this is a single granule transition or a range of granules. */
+	if (size != GPT_PGS_ACTUAL_SIZE(gpt_config.p)) {
+		/*
+		 * TODO: Add support for transitioning multiple granules with a
+		 * single call to this function.
+		 */
+		panic();
+	}
+
+	/* Get the L0 descriptor and make sure it is for a table. */
+	gpt_l0_base = (uint64_t *)gpt_config.plat_gpt_l0_base;
+	gpt_l0_desc = gpt_l0_base[GPT_L0_IDX(base)];
+	if (GPT_L0_TYPE(gpt_l0_desc) != GPT_L0_TYPE_TBL_DESC) {
+		VERBOSE("[GPT] Granule is not covered by a table descriptor!\n");
+		VERBOSE("      Base=0x%llx\n", base);
+		return -EINVAL;
+	}
+
+	/* Get the table index and GPI shift from PA. */
+	gpt_l1_addr = GPT_L0_TBLD_ADDR(gpt_l0_desc);
+	idx = GPT_L1_IDX(gpt_config.p, base);
+	gpi_shift = GPT_L1_GPI_IDX(gpt_config.p, base) << 2;
+
+	/*
+	 * Access to L1 tables is controlled by a global lock to ensure
+	 * that no more than one CPU is allowed to make changes at any
+	 * given time.
+	 */
+	spin_lock(&gpt_lock);
+	gpt_l1_desc = gpt_l1_addr[idx];
+	gpi = (gpt_l1_desc >> gpi_shift) & GPT_L1_GRAN_DESC_GPI_MASK;
+
+	/* Make sure caller state and source/target PAS are allowed. */
+	if (gpt_check_transition_gpi(src_sec_state, gpi, target_pas) < 0) {
+		spin_unlock(&gpt_lock);
+			VERBOSE("[GPT] Invalid caller state and PAS combo!\n");
+		VERBOSE("      Caller: %u, Current GPI: %u, Target GPI: %u\n",
+			src_sec_state, gpi, target_pas);
+		return -EPERM;
+	}
+
+	/* Clear existing GPI encoding and transition granule. */
+	gpt_l1_desc &= ~(GPT_L1_GRAN_DESC_GPI_MASK << gpi_shift);
+	gpt_l1_desc |= ((uint64_t)target_pas << gpi_shift);
+	gpt_l1_addr[idx] = gpt_l1_desc;
+
+	/* Ensure that the write operation happens before the unlock. */
+	dmbishst();
+
+	/* Unlock access to the L1 tables. */
+	spin_unlock(&gpt_lock);
+
+	/* Cache maintenance. */
+	clean_dcache_range((uintptr_t)&gpt_l1_addr[idx],
+			   sizeof(uint64_t));
+	gpt_tlbi_by_pa(base, GPT_PGS_ACTUAL_SIZE(gpt_config.p));
+	dsbishst();
+
+	VERBOSE("[GPT] Granule 0x%llx, GPI 0x%x->0x%x\n", base, gpi,
+		target_pas);
+
+	return 0;
+}
diff --git a/lib/gpt_rme/gpt_rme.mk b/lib/gpt_rme/gpt_rme.mk
new file mode 100644
index 0000000..60176f4
--- /dev/null
+++ b/lib/gpt_rme/gpt_rme.mk
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+GPT_LIB_SRCS	:=	$(addprefix lib/gpt_rme/,        \
+			gpt_rme.c)
diff --git a/lib/gpt_rme/gpt_rme_private.h b/lib/gpt_rme/gpt_rme_private.h
new file mode 100644
index 0000000..5770bf7
--- /dev/null
+++ b/lib/gpt_rme/gpt_rme_private.h
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPT_RME_PRIVATE_H
+#define GPT_RME_PRIVATE_H
+
+#include <arch.h>
+#include <lib/gpt_rme/gpt_rme.h>
+#include <lib/utils_def.h>
+
+/******************************************************************************/
+/* GPT descriptor definitions                                                 */
+/******************************************************************************/
+
+/* GPT level 0 descriptor bit definitions. */
+#define GPT_L0_TYPE_MASK		UL(0xF)
+#define GPT_L0_TYPE_SHIFT		U(0)
+
+/* For now, we don't support contiguous descriptors, only table and block. */
+#define GPT_L0_TYPE_TBL_DESC		UL(0x3)
+#define GPT_L0_TYPE_BLK_DESC		UL(0x1)
+
+#define GPT_L0_TBL_DESC_L1ADDR_MASK	UL(0xFFFFFFFFFF)
+#define GPT_L0_TBL_DESC_L1ADDR_SHIFT	U(12)
+
+#define GPT_L0_BLK_DESC_GPI_MASK	UL(0xF)
+#define GPT_L0_BLK_DESC_GPI_SHIFT	U(4)
+
+/* GPT level 1 descriptor bit definitions */
+#define GPT_L1_GRAN_DESC_GPI_MASK	UL(0xF)
+
+/*
+ * This macro fills out every GPI entry in a granules descriptor to the same
+ * value.
+ */
+#define GPT_BUILD_L1_DESC(_gpi)		(((uint64_t)(_gpi) << 4*0) | \
+					 ((uint64_t)(_gpi) << 4*1) | \
+					 ((uint64_t)(_gpi) << 4*2) | \
+					 ((uint64_t)(_gpi) << 4*3) | \
+					 ((uint64_t)(_gpi) << 4*4) | \
+					 ((uint64_t)(_gpi) << 4*5) | \
+					 ((uint64_t)(_gpi) << 4*6) | \
+					 ((uint64_t)(_gpi) << 4*7) | \
+					 ((uint64_t)(_gpi) << 4*8) | \
+					 ((uint64_t)(_gpi) << 4*9) | \
+					 ((uint64_t)(_gpi) << 4*10) | \
+					 ((uint64_t)(_gpi) << 4*11) | \
+					 ((uint64_t)(_gpi) << 4*12) | \
+					 ((uint64_t)(_gpi) << 4*13) | \
+					 ((uint64_t)(_gpi) << 4*14) | \
+					 ((uint64_t)(_gpi) << 4*15))
+
+/******************************************************************************/
+/* GPT platform configuration                                                 */
+/******************************************************************************/
+
+/* This value comes from GPCCR_EL3 so no externally supplied definition. */
+#define GPT_L0GPTSZ		((unsigned int)((read_gpccr_el3() >> \
+				GPCCR_L0GPTSZ_SHIFT) & GPCCR_L0GPTSZ_MASK))
+
+/* The "S" value is directly related to L0GPTSZ */
+#define GPT_S_VAL		(GPT_L0GPTSZ + 30U)
+
+/*
+ * Map PPS values to T values.
+ *
+ *   PPS    Size    T
+ *   0b000  4GB     32
+ *   0b001  64GB    36
+ *   0b010  1TB     40
+ *   0b011  4TB     42
+ *   0b100  16TB    44
+ *   0b101  256TB   48
+ *   0b110  4PB     52
+ *
+ * See section 15.1.27 of the RME specification.
+ */
+typedef enum {
+	PPS_4GB_T =	32U,
+	PPS_64GB_T =	36U,
+	PPS_1TB_T =	40U,
+	PPS_4TB_T =	42U,
+	PPS_16TB_T =	44U,
+	PPS_256TB_T =	48U,
+	PPS_4PB_T =	52U
+} gpt_t_val_e;
+
+/*
+ * Map PGS values to P values.
+ *
+ *   PGS    Size    P
+ *   0b00   4KB     12
+ *   0b10   16KB    14
+ *   0b01   64KB    16
+ *
+ * Note that pgs=0b10 is 16KB and pgs=0b01 is 64KB, this is not a typo.
+ *
+ * See section 15.1.27 of the RME specification.
+ */
+typedef enum {
+	PGS_4KB_P =	12U,
+	PGS_16KB_P =	14U,
+	PGS_64KB_P =	16U
+} gpt_p_val_e;
+
+/* Max valid value for PGS. */
+#define GPT_PGS_MAX			(2U)
+
+/* Max valid value for PPS. */
+#define GPT_PPS_MAX			(6U)
+
+/******************************************************************************/
+/* L0 address attribute macros                                                */
+/******************************************************************************/
+
+/*
+ * If S is greater than or equal to T then there is a single L0 region covering
+ * the entire protected space so there is no L0 index, so the width (and the
+ * derivative mask value) are both zero.  If we don't specifically handle this
+ * special case we'll get a negative width value which does not make sense and
+ * could cause a lot of problems.
+ */
+#define GPT_L0_IDX_WIDTH(_t)		(((_t) > GPT_S_VAL) ? \
+					((_t) - GPT_S_VAL) : (0U))
+
+/* Bit shift for the L0 index field in a PA. */
+#define GPT_L0_IDX_SHIFT		(GPT_S_VAL)
+
+/* Mask for the L0 index field, must be shifted. */
+#define GPT_L0_IDX_MASK(_t)		(0xFFFFFFFFFFFFFFFFUL >> \
+					(64U - (GPT_L0_IDX_WIDTH(_t))))
+
+/* Total number of L0 regions. */
+#define GPT_L0_REGION_COUNT(_t)		((GPT_L0_IDX_MASK(_t)) + 1U)
+
+/* Total size of each GPT L0 region in bytes. */
+#define GPT_L0_REGION_SIZE		(1UL << (GPT_L0_IDX_SHIFT))
+
+/* Total size in bytes of the whole L0 table. */
+#define GPT_L0_TABLE_SIZE(_t)		((GPT_L0_REGION_COUNT(_t)) << 3U)
+
+/******************************************************************************/
+/* L1 address attribute macros                                                */
+/******************************************************************************/
+
+/* Width of the L1 index field. */
+#define GPT_L1_IDX_WIDTH(_p)		((GPT_S_VAL - 1U) - ((_p) + 3U))
+
+/* Bit shift for the L1 index field. */
+#define GPT_L1_IDX_SHIFT(_p)		((_p) + 4U)
+
+/* Mask for the L1 index field, must be shifted. */
+#define GPT_L1_IDX_MASK(_p)		(0xFFFFFFFFFFFFFFFFUL >> \
+					(64U - (GPT_L1_IDX_WIDTH(_p))))
+
+/* Bit shift for the index of the L1 GPI in a PA. */
+#define GPT_L1_GPI_IDX_SHIFT(_p)	(_p)
+
+/* Mask for the index of the L1 GPI in a PA. */
+#define GPT_L1_GPI_IDX_MASK		(0xF)
+
+/* Total number of entries in each L1 table. */
+#define GPT_L1_ENTRY_COUNT(_p)		((GPT_L1_IDX_MASK(_p)) + 1U)
+
+/* Total size in bytes of each L1 table. */
+#define GPT_L1_TABLE_SIZE(_p)		((GPT_L1_ENTRY_COUNT(_p)) << 3U)
+
+/******************************************************************************/
+/* General helper macros                                                      */
+/******************************************************************************/
+
+/* Protected space actual size in bytes. */
+#define GPT_PPS_ACTUAL_SIZE(_t)	(1UL << (_t))
+
+/* Granule actual size in bytes. */
+#define GPT_PGS_ACTUAL_SIZE(_p)	(1UL << (_p))
+
+/* L0 GPT region size in bytes. */
+#define GPT_L0GPTSZ_ACTUAL_SIZE	(1UL << GPT_S_VAL)
+
+/* Get the index of the L0 entry from a physical address. */
+#define GPT_L0_IDX(_pa)		((_pa) >> GPT_L0_IDX_SHIFT)
+
+/*
+ * This definition is used to determine if a physical address lies on an L0
+ * region boundary.
+ */
+#define GPT_IS_L0_ALIGNED(_pa)	(((_pa) & (GPT_L0_REGION_SIZE - U(1))) == U(0))
+
+/* Get the type field from an L0 descriptor. */
+#define GPT_L0_TYPE(_desc)	(((_desc) >> GPT_L0_TYPE_SHIFT) & \
+				GPT_L0_TYPE_MASK)
+
+/* Create an L0 block descriptor. */
+#define GPT_L0_BLK_DESC(_gpi)	(GPT_L0_TYPE_BLK_DESC | \
+				(((_gpi) & GPT_L0_BLK_DESC_GPI_MASK) << \
+				GPT_L0_BLK_DESC_GPI_SHIFT))
+
+/* Create an L0 table descriptor with an L1 table address. */
+#define GPT_L0_TBL_DESC(_pa)	(GPT_L0_TYPE_TBL_DESC | ((uint64_t)(_pa) & \
+				(GPT_L0_TBL_DESC_L1ADDR_MASK << \
+				GPT_L0_TBL_DESC_L1ADDR_SHIFT)))
+
+/* Get the GPI from an L0 block descriptor. */
+#define GPT_L0_BLKD_GPI(_desc)	(((_desc) >> GPT_L0_BLK_DESC_GPI_SHIFT) & \
+				GPT_L0_BLK_DESC_GPI_MASK)
+
+/* Get the L1 address from an L0 table descriptor. */
+#define GPT_L0_TBLD_ADDR(_desc)	((uint64_t *)(((_desc) & \
+				(GPT_L0_TBL_DESC_L1ADDR_MASK << \
+				GPT_L0_TBL_DESC_L1ADDR_SHIFT))))
+
+/* Get the index into the L1 table from a physical address. */
+#define GPT_L1_IDX(_p, _pa)	(((_pa) >> GPT_L1_IDX_SHIFT(_p)) & \
+				GPT_L1_IDX_MASK(_p))
+
+/* Get the index of the GPI within an L1 table entry from a physical address. */
+#define GPT_L1_GPI_IDX(_p, _pa)	(((_pa) >> GPT_L1_GPI_IDX_SHIFT(_p)) & \
+				GPT_L1_GPI_IDX_MASK)
+
+/* Determine if an address is granule-aligned. */
+#define GPT_IS_L1_ALIGNED(_p, _pa) (((_pa) & (GPT_PGS_ACTUAL_SIZE(_p) - U(1))) \
+				   == U(0))
+
+#endif /* GPT_RME_PRIVATE_H */
diff --git a/lib/optee/optee_utils.c b/lib/optee/optee_utils.c
index 0ad1082..d090b38 100644
--- a/lib/optee/optee_utils.c
+++ b/lib/optee/optee_utils.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -47,25 +47,24 @@
 
 /*******************************************************************************
  * Check if it is a valid tee header
- * Return 1 if valid
- * Return 0 if invalid
+ * Return true if valid
+ * Return false if invalid
  ******************************************************************************/
-static inline int tee_validate_header(optee_header_t *header)
+static bool tee_validate_header(optee_header_t *header)
 {
-	int valid = 0;
-
 	if ((header->magic == TEE_MAGIC_NUM_OPTEE) &&
 		(header->version == 2u) &&
 		(header->nb_images > 0u) &&
 		(header->nb_images <= OPTEE_MAX_NUM_IMAGES)) {
-		valid = 1;
+		return true;
 	}
 
-	else {
-		WARN("Not a known TEE, use default loading options.\n");
-	}
+	return false;
+}
 
-	return valid;
+bool optee_header_is_valid(uintptr_t header_base)
+{
+	return tee_validate_header((optee_header_t *)header_base);
 }
 
 /*******************************************************************************
diff --git a/lib/xlat_mpu/aarch64/enable_mpu.S b/lib/xlat_mpu/aarch64/enable_mpu.S
new file mode 100644
index 0000000..3791f2d
--- /dev/null
+++ b/lib/xlat_mpu/aarch64/enable_mpu.S
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <platform_def.h>
+
+	.global	enable_mpu_direct_el2
+
+	/* void enable_mmu_direct_el2(unsigned int flags) */
+func enable_mpu_direct_el2
+#if ENABLE_ASSERTIONS
+	mrs	x1, sctlr_el2
+	tst	x1, #SCTLR_M_BIT
+	ASM_ASSERT(eq)
+#endif
+	mov	x7, x0
+	adrp	x0, mmu_cfg_params
+	add	x0, x0, :lo12:mmu_cfg_params
+
+	/* (MAIRs are already set up) */
+
+	/* TCR */
+	ldr	x2, [x0, #(MMU_CFG_TCR << 3)]
+	msr	tcr_el2, x2
+
+	/*
+	 * Ensure all translation table writes have drained into memory, the TLB
+	 * invalidation is complete, and translation register writes are
+	 * committed before enabling the MMU
+	 */
+	dsb	ish
+	isb
+
+	/* Set and clear required fields of SCTLR */
+	mrs	x4, sctlr_el2
+	mov_imm	x5, SCTLR_WXN_BIT | SCTLR_C_BIT | SCTLR_M_BIT
+	orr	x4, x4, x5
+
+	/* Additionally, amend SCTLR fields based on flags */
+	bic	x5, x4, #SCTLR_C_BIT
+	tst	x7, #DISABLE_DCACHE
+	csel	x4, x5, x4, ne
+
+	msr	sctlr_el2, x4
+	isb
+
+	ret
+endfunc enable_mpu_direct_el2
diff --git a/lib/xlat_mpu/aarch64/xlat_mpu_arch.c b/lib/xlat_mpu/aarch64/xlat_mpu_arch.c
new file mode 100644
index 0000000..5068eb8
--- /dev/null
+++ b/lib/xlat_mpu/aarch64/xlat_mpu_arch.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "../xlat_mpu_private.h"
+#include <arch.h>
+#include <arch_features.h>
+#include <lib/cassert.h>
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include <fvp_r_arch_helpers.h>
+
+#warning "xlat_mpu library is currently experimental and its API may change in future."
+
+#if ENABLE_ASSERTIONS
+/*
+ * Return minimum virtual address space size supported by the architecture
+ */
+uintptr_t xlat_get_min_virt_addr_space_size(void)
+{
+	uintptr_t ret;
+
+	if (is_armv8_4_ttst_present()) {
+		ret = MIN_VIRT_ADDR_SPACE_SIZE_TTST;
+	} else {
+		ret = MIN_VIRT_ADDR_SPACE_SIZE;
+	}
+	return ret;
+}
+#endif /* ENABLE_ASSERTIONS*/
+
+bool is_mpu_enabled_ctx(const xlat_ctx_t *ctx)
+{
+	if (ctx->xlat_regime == EL1_EL0_REGIME) {
+		assert(xlat_arch_current_el() >= 1U);
+		return (read_sctlr_el1() & SCTLR_M_BIT) != 0U;
+	} else {
+		assert(xlat_arch_current_el() >= 2U);
+		return (read_sctlr_el2() & SCTLR_M_BIT) != 0U;
+	}
+}
+
+bool is_dcache_enabled(void)
+{
+	unsigned int el = get_current_el();
+
+	if (el == 1U) {
+		return (read_sctlr_el1() & SCTLR_C_BIT) != 0U;
+	} else {  /* must be EL2 */
+		return (read_sctlr_el2() & SCTLR_C_BIT) != 0U;
+	}
+}
+
+unsigned int xlat_arch_current_el(void)
+{
+	unsigned int el = (unsigned int)GET_EL(read_CurrentEl());
+
+	assert(el > 0U);
+
+	return el;
+}
+
diff --git a/lib/xlat_mpu/ro_xlat_mpu.mk b/lib/xlat_mpu/ro_xlat_mpu.mk
new file mode 100644
index 0000000..23f1d46
--- /dev/null
+++ b/lib/xlat_mpu/ro_xlat_mpu.mk
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2021, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ifeq (${USE_DEBUGFS}, 1)
+    $(error "Debugfs requires functionality from the dynamic translation \
+             library and is incompatible with ALLOW_RO_XLAT_TABLES.")
+endif
+
+ifeq (${ARCH},aarch32)
+    $(error "The xlat_mpu library does not currently support AArch32.")
+endif
diff --git a/lib/xlat_mpu/xlat_mpu.mk b/lib/xlat_mpu/xlat_mpu.mk
new file mode 100644
index 0000000..041b91c
--- /dev/null
+++ b/lib/xlat_mpu/xlat_mpu.mk
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+XLAT_MPU_LIB_V1_SRCS	:=	$(addprefix lib/xlat_mpu/,		\
+				${ARCH}/enable_mpu.S			\
+				${ARCH}/xlat_mpu_arch.c			\
+				xlat_mpu_context.c			\
+				xlat_mpu_core.c				\
+				xlat_mpu_utils.c)
+
+XLAT_MPU_LIB_V1	:=	1
+$(eval $(call add_define,XLAT_MPU_LIB_V1))
+
+ifeq (${ALLOW_XLAT_MPU}, 1)
+    include lib/xlat_mpu_v2/ro_xlat_mpu.mk
+endif
diff --git a/lib/xlat_mpu/xlat_mpu_context.c b/lib/xlat_mpu/xlat_mpu_context.c
new file mode 100644
index 0000000..28c463b
--- /dev/null
+++ b/lib/xlat_mpu/xlat_mpu_context.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+
+#include "lib/xlat_mpu/xlat_mpu.h"
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include "xlat_mpu_private.h"
+
+#include <fvp_r_arch_helpers.h>
+#include <platform_def.h>
+
+#warning "xlat_mpu library is currently experimental and its API may change in future."
+
+
+/*
+ * MMU configuration register values for the active translation context. Used
+ * from the MMU assembly helpers.
+ */
+uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
+
+/*
+ * Allocate and initialise the default translation context for the BL image
+ * currently executing.
+ */
+REGISTER_XLAT_CONTEXT(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES,
+			PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE);
+
+void mmap_add(const mmap_region_t *mm)
+{
+	mmap_add_ctx(&tf_xlat_ctx, mm);
+}
+
+void __init init_xlat_tables(void)
+{
+	assert(tf_xlat_ctx.xlat_regime == EL_REGIME_INVALID);
+
+	unsigned int current_el = xlat_arch_current_el();
+
+	if (current_el == 1U) {
+		tf_xlat_ctx.xlat_regime = EL1_EL0_REGIME;
+	} else {
+		assert(current_el == 2U);
+		tf_xlat_ctx.xlat_regime = EL2_REGIME;
+	}
+	/* Note:  If EL3 is supported in future v8-R64, add EL3 assignment */
+	init_xlat_tables_ctx(&tf_xlat_ctx);
+}
+
+int xlat_get_mem_attributes(uintptr_t base_va, uint32_t *attr)
+{
+	return xlat_get_mem_attributes_ctx(&tf_xlat_ctx, base_va, attr);
+}
+
+void enable_mpu_el2(unsigned int flags)
+{
+	/* EL2 is strictly MPU on v8-R64, so no need for setup_mpu_cfg() */
+	enable_mpu_direct_el2(flags);
+}
diff --git a/lib/xlat_mpu/xlat_mpu_core.c b/lib/xlat_mpu/xlat_mpu_core.c
new file mode 100644
index 0000000..6b4b0c2
--- /dev/null
+++ b/lib/xlat_mpu/xlat_mpu_core.c
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <arch_features.h>
+#include <common/debug.h>
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include "xlat_mpu_private.h"
+
+#include <fvp_r_arch_helpers.h>
+#include <platform_def.h>
+
+#warning "xlat_mpu library is currently experimental and its API may change in future."
+
+
+/* Helper function that cleans the data cache only if it is enabled. */
+static inline __attribute__((unused))
+	void xlat_clean_dcache_range(uintptr_t addr, size_t size)
+{
+	if (is_dcache_enabled()) {
+		clean_dcache_range(addr, size);
+	}
+}
+
+
+
+/* Calculate region-attributes byte for PRBAR part of MPU-region descriptor: */
+uint64_t prbar_attr_value(uint32_t attr)
+{
+	uint64_t retValue = UL(0);
+	uint64_t extract;  /* temp var holding bit extracted from attr */
+
+	/* Extract and stuff SH: */
+	extract = (uint64_t) ((attr >> MT_SHAREABILITY_SHIFT)
+				& MT_SHAREABILITY_MASK);
+	retValue |= (extract << PRBAR_SH_SHIFT);
+
+	/* Extract and stuff AP: */
+	extract = (uint64_t) ((attr >> MT_PERM_SHIFT) & MT_PERM_MASK);
+	if (extract == 0U) {
+		retValue |= (UL(2) << PRBAR_AP_SHIFT);
+	} else /* extract == 1 */ {
+		retValue |= (UL(0) << PRBAR_AP_SHIFT);
+	}
+
+	/* Extract and stuff XN: */
+	extract = (uint64_t) ((attr >> MT_EXECUTE_SHIFT) & MT_EXECUTE_MASK);
+	retValue |= (extract << PRBAR_XN_SHIFT);
+	/* However, also don't execute in peripheral space: */
+	extract = (uint64_t) ((attr >> MT_TYPE_SHIFT) & MT_TYPE_MASK);
+	if (extract == 0U) {
+		retValue |= (UL(1) << PRBAR_XN_SHIFT);
+	}
+	return retValue;
+}
+
+/* Calculate region-attributes byte for PRLAR part of MPU-region descriptor: */
+uint64_t prlar_attr_value(uint32_t attr)
+{
+	uint64_t retValue = UL(0);
+	uint64_t extract;  /* temp var holding bit extracted from attr */
+
+	/* Extract and stuff AttrIndx: */
+	extract = (uint64_t) ((attr >> MT_TYPE_SHIFT)
+				& MT_TYPE_MASK);
+	switch (extract) {
+	case UL(0):
+		retValue |= (UL(1) << PRLAR_ATTR_SHIFT);
+		break;
+	case UL(2):
+		/* 0, so OR in nothing */
+		break;
+	case UL(3):
+		retValue |= (UL(2) << PRLAR_ATTR_SHIFT);
+		break;
+	default:
+		retValue |= (extract << PRLAR_ATTR_SHIFT);
+		break;
+	}
+
+	/* Stuff EN: */
+	retValue |= (UL(1) << PRLAR_EN_SHIFT);
+
+	/* Force NS to 0 (Secure);  v8-R64 only supports Secure: */
+	extract = ~(1U << PRLAR_NS_SHIFT);
+	retValue &= extract;
+
+	return retValue;
+}
+
+/*
+ * Function that writes an MPU "translation" into the MPU registers. If not
+ * possible (e.g., if no more MPU regions available) boot is aborted.
+ */
+static void mpu_map_region(mmap_region_t *mm)
+{
+	uint64_t prenr_el2_value = 0UL;
+	uint64_t prbar_attrs = 0UL;
+	uint64_t prlar_attrs = 0UL;
+	int region_to_use = 0;
+
+	/* If all MPU regions in use, then abort boot: */
+	prenr_el2_value = read_prenr_el2();
+	assert(prenr_el2_value != 0xffffffff);
+
+	/* Find and select first-available MPU region (PRENR has an enable bit
+	 * for each MPU region, 1 for in-use or 0 for unused):
+	 */
+	for (region_to_use = 0;  region_to_use < N_MPU_REGIONS;
+	     region_to_use++) {
+		if (((prenr_el2_value >> region_to_use) & 1) == 0) {
+			break;
+		}
+	}
+	write_prselr_el2((uint64_t) (region_to_use));
+	isb();
+
+	/* Set base and limit addresses: */
+	write_prbar_el2(mm->base_pa & PRBAR_PRLAR_ADDR_MASK);
+	write_prlar_el2((mm->base_pa + mm->size - 1UL)
+			& PRBAR_PRLAR_ADDR_MASK);
+	dsbsy();
+	isb();
+
+	/* Set attributes: */
+	prbar_attrs = prbar_attr_value(mm->attr);
+	write_prbar_el2(read_prbar_el2() | prbar_attrs);
+	prlar_attrs = prlar_attr_value(mm->attr);
+	write_prlar_el2(read_prlar_el2() | prlar_attrs);
+	dsbsy();
+	isb();
+
+	/* Mark this MPU region as used: */
+	prenr_el2_value |= (1 << region_to_use);
+	write_prenr_el2(prenr_el2_value);
+	isb();
+}
+
+/*
+ * Function that verifies that a region can be mapped.
+ * Returns:
+ *        0: Success, the mapping is allowed.
+ *   EINVAL: Invalid values were used as arguments.
+ *   ERANGE: The memory limits were surpassed.
+ *   ENOMEM: There is not enough memory in the mmap array.
+ *    EPERM: Region overlaps another one in an invalid way.
+ */
+static int mmap_add_region_check(const xlat_ctx_t *ctx, const mmap_region_t *mm)
+{
+	unsigned long long base_pa = mm->base_pa;
+	uintptr_t base_va = mm->base_va;
+	size_t size = mm->size;
+
+	unsigned long long end_pa = base_pa + size - 1U;
+	uintptr_t end_va = base_va + size - 1U;
+
+	if (base_pa != base_va) {
+		return -EINVAL;  /* MPU does not perform address translation */
+	}
+	if ((base_pa % 64ULL) != 0ULL) {
+		return -EINVAL;  /* MPU requires 64-byte alignment */
+	}
+	/* Check for overflows */
+	if ((base_pa > end_pa) || (base_va > end_va)) {
+		return -ERANGE;
+	}
+	if (end_pa > ctx->pa_max_address) {
+		return -ERANGE;
+	}
+	/* Check that there is space in the ctx->mmap array */
+	if (ctx->mmap[ctx->mmap_num - 1].size != 0U) {
+		return -ENOMEM;
+	}
+	/* Check for PAs and VAs overlaps with all other regions */
+	for (const mmap_region_t *mm_cursor = ctx->mmap;
+	     mm_cursor->size != 0U; ++mm_cursor) {
+
+		uintptr_t mm_cursor_end_va =
+			mm_cursor->base_va + mm_cursor->size - 1U;
+
+		/*
+		 * Check if one of the regions is completely inside the other
+		 * one.
+		 */
+		bool fully_overlapped_va =
+			((base_va >= mm_cursor->base_va) &&
+					(end_va <= mm_cursor_end_va)) ||
+			((mm_cursor->base_va >= base_va) &&
+						(mm_cursor_end_va <= end_va));
+
+		/*
+		 * Full VA overlaps are only allowed if both regions are
+		 * identity mapped (zero offset) or have the same VA to PA
+		 * offset. Also, make sure that it's not the exact same area.
+		 * This can only be done with static regions.
+		 */
+		if (fully_overlapped_va) {
+
+#if PLAT_XLAT_TABLES_DYNAMIC
+			if (((mm->attr & MT_DYNAMIC) != 0U) ||
+			    ((mm_cursor->attr & MT_DYNAMIC) != 0U)) {
+				return -EPERM;
+			}
+#endif /* PLAT_XLAT_TABLES_DYNAMIC */
+			if ((mm_cursor->base_va - mm_cursor->base_pa)
+					!= (base_va - base_pa)) {
+				return -EPERM;
+			}
+			if ((base_va == mm_cursor->base_va) &&
+					(size == mm_cursor->size)) {
+				return -EPERM;
+			}
+		} else {
+			/*
+			 * If the regions do not have fully overlapping VAs,
+			 * then they must have fully separated VAs and PAs.
+			 * Partial overlaps are not allowed
+			 */
+
+			unsigned long long mm_cursor_end_pa =
+				     mm_cursor->base_pa + mm_cursor->size - 1U;
+
+			bool separated_pa = (end_pa < mm_cursor->base_pa) ||
+				(base_pa > mm_cursor_end_pa);
+			bool separated_va = (end_va < mm_cursor->base_va) ||
+				(base_va > mm_cursor_end_va);
+
+			if (!separated_va || !separated_pa) {
+				return -EPERM;
+			}
+		}
+	}
+
+	return 0;
+}
+
+void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm)
+{
+	mmap_region_t *mm_cursor = ctx->mmap, *mm_destination;
+	const mmap_region_t *mm_end = ctx->mmap + ctx->mmap_num;
+	const mmap_region_t *mm_last;
+	unsigned long long end_pa = mm->base_pa + mm->size - 1U;
+	uintptr_t end_va = mm->base_va + mm->size - 1U;
+	int ret;
+
+	/* Ignore empty regions */
+	if (mm->size == 0U) {
+		return;
+	}
+
+	/* Static regions must be added before initializing the xlat tables. */
+	assert(!ctx->initialized);
+
+	ret = mmap_add_region_check(ctx, mm);
+	if (ret != 0) {
+		ERROR("mmap_add_region_check() failed. error %d\n", ret);
+		assert(false);
+		return;
+	}
+
+	/*
+	 * Find the last entry marker in the mmap
+	 */
+	mm_last = ctx->mmap;
+	while ((mm_last->size != 0U) && (mm_last < mm_end)) {
+		++mm_last;
+	}
+
+	/*
+	 * Check if we have enough space in the memory mapping table.
+	 * This shouldn't happen as we have checked in mmap_add_region_check
+	 * that there is free space.
+	 */
+	assert(mm_last->size == 0U);
+
+	/* Make room for new region by moving other regions up by one place */
+	mm_destination = mm_cursor + 1;
+	(void)memmove(mm_destination, mm_cursor,
+		(uintptr_t)mm_last - (uintptr_t)mm_cursor);
+
+	/*
+	 * Check we haven't lost the empty sentinel from the end of the array.
+	 * This shouldn't happen as we have checked in mmap_add_region_check
+	 * that there is free space.
+	 */
+	assert(mm_end->size == 0U);
+
+	*mm_cursor = *mm;
+
+	if (end_pa > ctx->max_pa) {
+		ctx->max_pa = end_pa;
+	}
+	if (end_va > ctx->max_va) {
+		ctx->max_va = end_va;
+	}
+}
+
+void mmap_add_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm)
+{
+	const mmap_region_t *mm_cursor = mm;
+
+	while (mm_cursor->granularity != 0U) {
+		mmap_add_region_ctx(ctx, mm_cursor);
+		mm_cursor++;
+	}
+}
+
+void __init init_xlat_tables_ctx(xlat_ctx_t *ctx)
+{
+	uint64_t mair = UL(0);
+
+	assert(ctx != NULL);
+	assert(!ctx->initialized);
+	assert((ctx->xlat_regime == EL2_REGIME) ||
+		(ctx->xlat_regime == EL1_EL0_REGIME));
+	/* Note:  Add EL3_REGIME if EL3 is supported in future v8-R64 cores. */
+	assert(!is_mpu_enabled_ctx(ctx));
+
+	mmap_region_t *mm = ctx->mmap;
+
+	assert(ctx->va_max_address >=
+		(xlat_get_min_virt_addr_space_size() - 1U));
+	assert(ctx->va_max_address <= (MAX_VIRT_ADDR_SPACE_SIZE - 1U));
+	assert(IS_POWER_OF_TWO(ctx->va_max_address + 1U));
+
+	xlat_mmap_print(mm);
+
+	/* All tables must be zeroed before mapping any region. */
+
+	for (unsigned int i = 0U; i < ctx->base_table_entries; i++)
+		ctx->base_table[i] = INVALID_DESC;
+
+	/* Also mark all MPU regions as invalid in the MPU hardware itself: */
+	write_prenr_el2(0);
+		/* Sufficient for current, max-32-region implementations. */
+	dsbsy();
+	isb();
+	while (mm->size != 0U) {
+		if (read_prenr_el2() == ALL_MPU_EL2_REGIONS_USED) {
+			ERROR("Not enough MPU regions to map region:\n"
+				" VA:0x%lx  PA:0x%llx  size:0x%zx  attr:0x%x\n",
+				mm->base_va, mm->base_pa, mm->size, mm->attr);
+			panic();
+		} else {
+#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY)
+			xlat_clean_dcache_range((uintptr_t)mm->base_va,
+				mm->size);
+#endif
+			mpu_map_region(mm);
+		}
+		mm++;
+	}
+
+	ctx->initialized = true;
+
+	xlat_tables_print(ctx);
+
+	/* Set attributes in the right indices of the MAIR */
+	mair = MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX);
+	mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR,
+			ATTR_IWBWA_OWBWA_NTR_INDEX);
+	mair |= MAIR_ATTR_SET(ATTR_NON_CACHEABLE,
+			ATTR_NON_CACHEABLE_INDEX);
+	write_mair_el2(mair);
+	dsbsy();
+	isb();
+}
+
+/*
+ * Function to wipe clean and disable all MPU regions.  This function expects
+ * that the MPU has already been turned off, and caching concerns addressed,
+ * but it nevertheless also explicitly turns off the MPU.
+ */
+void clear_all_mpu_regions(void)
+{
+	uint64_t sctlr_el2_value = 0UL;
+	uint64_t region_n = 0UL;
+
+	/*
+	 * MPU should already be disabled, but explicitly disable it
+	 * nevertheless:
+	 */
+	sctlr_el2_value = read_sctlr_el2() & ~(1UL);
+	write_sctlr_el2(sctlr_el2_value);
+
+	/* Disable all regions: */
+	write_prenr_el2(0UL);
+
+	/* Sequence through all regions, zeroing them out and turning off: */
+	for (region_n = 0UL;  region_n < N_MPU_REGIONS;  region_n++) {
+		write_prselr_el2(region_n);
+		isb();
+		write_prbar_el2((uint64_t) 0);
+		write_prlar_el2((uint64_t) 0);
+		dsbsy();
+		isb();
+	}
+}
diff --git a/lib/xlat_mpu/xlat_mpu_private.h b/lib/xlat_mpu/xlat_mpu_private.h
new file mode 100644
index 0000000..e0e479d
--- /dev/null
+++ b/lib/xlat_mpu/xlat_mpu_private.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef XLAT_MPU_PRIVATE_H
+#define XLAT_MPU_PRIVATE_H
+
+#include <stdbool.h>
+
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include <platform_def.h>
+
+#if PLAT_XLAT_TABLES_DYNAMIC
+/*
+ * Private shifts and masks to access fields of an mmap attribute
+ */
+/* Dynamic or static */
+#define MT_DYN_SHIFT		U(31)
+
+/*
+ * Memory mapping private attributes
+ *
+ * Private attributes not exposed in the public header.
+ */
+
+#endif /* PLAT_XLAT_TABLES_DYNAMIC */
+
+/* Calculate region-attributes byte for PRBAR part of MPU-region descriptor: */
+uint64_t prbar_attr_value(uint32_t attr);
+/* Calculate region-attributes byte for PRLAR part of MPU-region descriptor: */
+uint64_t prlar_attr_value(uint32_t attr);
+/* Calculates the attr value for a given PRBAR and PRLAR entry value: */
+uint32_t region_attr(uint64_t prbar_attr, uint64_t prlar_attr);
+
+#define PRBAR_PRLAR_ADDR_MASK	UL(0xffffffffffc0)
+	/* mask for PRBAR & PRLAR MPU-region field */
+/* MPU region attribute bit fields: */
+#define PRBAR_SH_SHIFT		UL(4)
+#define PRBAR_SH_MASK		UL(0x3)
+#define PRBAR_AP_SHIFT		UL(2)
+#define PRBAR_AP_MASK		UL(0x3)
+#define PRBAR_XN_SHIFT		UL(1)
+#define PRBAR_XN_MASK		UL(0x3)
+#define PRLAR_NS_SHIFT		UL(4)
+#define PRLAR_NS_MASK		UL(0x3)
+#define PRBAR_ATTR_SHIFT	UL(0)
+#define PRBAR_ATTR_MASK		UL(0x3f)
+#define PRLAR_ATTR_SHIFT	UL(1)
+#define PRLAR_ATTR_MASK		UL(0x7)
+#define PRLAR_EN_SHIFT		UL(0)
+#define PRLAR_EN_MASK		UL(0x1)
+/* Aspects of the source attributes not defined elsewhere: */
+#define MT_PERM_MASK		UL(0x1)
+#define MT_SEC_MASK		UL(0x1)
+#define MT_EXECUTE_MASK		UL(0x3)
+#define MT_TYPE_SHIFT		UL(0)
+
+extern uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
+
+/*
+ * Return the execute-never mask that will prevent instruction fetch at the
+ * given translation regime.
+ */
+uint64_t xlat_arch_regime_get_xn_desc(int xlat_regime);
+
+/* Print VA, PA, size and attributes of all regions in the mmap array. */
+void xlat_mmap_print(const mmap_region_t *mmap);
+
+/*
+ * Print the current state of the translation tables by reading them from
+ * memory.
+ */
+void xlat_tables_print(xlat_ctx_t *ctx);
+
+/*
+ * Returns a block/page table descriptor for the given level and attributes.
+ */
+uint64_t xlat_desc(const xlat_ctx_t *ctx, uint32_t attr,
+		   unsigned long long addr_pa, unsigned int level);
+
+/*
+ * Architecture-specific initialization code.
+ */
+
+/* Returns the current Exception Level. The returned EL must be 1 or higher. */
+unsigned int xlat_arch_current_el(void);
+
+/*
+ * Returns true if the MMU of the translation regime managed by the given
+ * xlat_ctx_t is enabled, false otherwise.
+ */
+bool is_mpu_enabled_ctx(const xlat_ctx_t *ctx);
+
+/*
+ * Returns minimum virtual address space size supported by the architecture
+ */
+uintptr_t xlat_get_min_virt_addr_space_size(void);
+
+#endif /* XLAT_MPU_PRIVATE_H */
diff --git a/lib/xlat_mpu/xlat_mpu_utils.c b/lib/xlat_mpu/xlat_mpu_utils.c
new file mode 100644
index 0000000..f305632
--- /dev/null
+++ b/lib/xlat_mpu/xlat_mpu_utils.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include <common/debug.h>
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include "xlat_mpu_private.h"
+
+#include <fvp_r_arch_helpers.h>
+#include <platform_def.h>
+
+#warning "xlat_mpu library is currently experimental and its API may change in future."
+
+
+#if LOG_LEVEL < LOG_LEVEL_VERBOSE
+
+void xlat_mmap_print(__unused const mmap_region_t *mmap)
+{
+	/* Empty */
+}
+
+void xlat_tables_print(__unused xlat_ctx_t *ctx)
+{
+	/* Empty */
+}
+
+#else /* if LOG_LEVEL >= LOG_LEVEL_VERBOSE */
+
+static const char *invalid_descriptors_ommited =
+		"%s(%d invalid descriptors omitted)\n";
+
+void xlat_tables_print(xlat_ctx_t *ctx)
+{
+	const char *xlat_regime_str;
+	int used_page_tables;
+
+	if (ctx->xlat_regime == EL1_EL0_REGIME) {
+		xlat_regime_str = "1&0";
+	} else if (ctx->xlat_regime == EL2_REGIME) {
+		xlat_regime_str = "2";
+	} else {
+		assert(ctx->xlat_regime == EL3_REGIME);
+		xlat_regime_str = "3";
+		/* If no EL3 and EL3 tables generated, then need to know. */
+	}
+	VERBOSE("Translation tables state:\n");
+	VERBOSE("  Xlat regime:     EL%s\n", xlat_regime_str);
+	VERBOSE("  Max allowed PA:  0x%llx\n", ctx->pa_max_address);
+	VERBOSE("  Max allowed VA:  0x%lx\n", ctx->va_max_address);
+	VERBOSE("  Max mapped PA:   0x%llx\n", ctx->max_pa);
+	VERBOSE("  Max mapped VA:   0x%lx\n", ctx->max_va);
+
+	VERBOSE("  Initial lookup level: %u\n", ctx->base_level);
+	VERBOSE("  Entries @initial lookup level: %u\n",
+		ctx->base_table_entries);
+
+	xlat_tables_print_internal(ctx, 0U, ctx->base_table,
+				   ctx->base_table_entries, ctx->base_level);
+}
+
+#endif /* LOG_LEVEL >= LOG_LEVEL_VERBOSE */
diff --git a/lib/xlat_tables/aarch64/xlat_tables.c b/lib/xlat_tables/aarch64/xlat_tables.c
index c86412c..dc167e3 100644
--- a/lib/xlat_tables/aarch64/xlat_tables.c
+++ b/lib/xlat_tables/aarch64/xlat_tables.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -147,7 +147,7 @@
  *			exception level
  ******************************************************************************/
 #define DEFINE_ENABLE_MMU_EL(_el, _tcr_extra, _tlbi_fct)		\
-	void enable_mmu_el##_el(unsigned int flags)				\
+	void enable_mmu_el##_el(unsigned int flags)			\
 	{								\
 		uint64_t mair, tcr, ttbr;				\
 		uint32_t sctlr;						\
diff --git a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
index b69c670..a1a44af 100644
--- a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -39,6 +39,23 @@
 	return PAGE_SIZE_4KB;
 }
 
+/*
+ * Determine the physical address space encoded in the 'attr' parameter.
+ *
+ * The physical address will fall into one of two spaces; secure or
+ * nonsecure.
+ */
+uint32_t xlat_arch_get_pas(uint32_t attr)
+{
+	uint32_t pas = MT_PAS(attr);
+
+	if (pas == MT_NS) {
+		return LOWER_ATTRS(NS);
+	} else { /* MT_SECURE */
+		return 0U;
+	}
+}
+
 #if ENABLE_ASSERTIONS
 unsigned long long xlat_arch_get_max_supported_pa(void)
 {
@@ -203,8 +220,6 @@
 
 		assert(virtual_addr_space_size >=
 			xlat_get_min_virt_addr_space_size());
-		assert(virtual_addr_space_size <=
-			MAX_VIRT_ADDR_SPACE_SIZE);
 		assert(IS_POWER_OF_TWO(virtual_addr_space_size));
 
 		/*
diff --git a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
index 3832b07..719110a 100644
--- a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -53,6 +53,33 @@
 	}
 }
 
+/*
+ * Determine the physical address space encoded in the 'attr' parameter.
+ *
+ * The physical address will fall into one of four spaces; secure,
+ * nonsecure, root, or realm if RME is enabled, or one of two spaces;
+ * secure and nonsecure otherwise.
+ */
+uint32_t xlat_arch_get_pas(uint32_t attr)
+{
+	uint32_t pas = MT_PAS(attr);
+
+	switch (pas) {
+#if ENABLE_RME
+	/* TTD.NSE = 1 and TTD.NS = 1 for Realm PAS */
+	case MT_REALM:
+		return LOWER_ATTRS(EL3_S1_NSE | NS);
+	/* TTD.NSE = 1 and TTD.NS = 0 for Root PAS */
+	case MT_ROOT:
+		return LOWER_ATTRS(EL3_S1_NSE);
+#endif
+	case MT_NS:
+		return LOWER_ATTRS(NS);
+	default: /* MT_SECURE */
+		return 0U;
+	}
+}
+
 unsigned long long tcr_physical_addr_size_bits(unsigned long long max_addr)
 {
 	/* Physical address can't exceed 48 bits */
diff --git a/lib/xlat_tables_v2/xlat_tables_core.c b/lib/xlat_tables_v2/xlat_tables_core.c
index bb6d184..de57184 100644
--- a/lib/xlat_tables_v2/xlat_tables_core.c
+++ b/lib/xlat_tables_v2/xlat_tables_core.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -125,11 +125,14 @@
 	 * faults aren't managed.
 	 */
 	desc |= LOWER_ATTRS(ACCESS_FLAG);
+
+	/* Determine the physical address space this region belongs to. */
+	desc |= xlat_arch_get_pas(attr);
+
 	/*
-	 * Deduce other fields of the descriptor based on the MT_NS and MT_RW
-	 * memory region attributes.
+	 * Deduce other fields of the descriptor based on the MT_RW memory
+	 * region attributes.
 	 */
-	desc |= ((attr & MT_NS) != 0U) ? LOWER_ATTRS(NS) : 0U;
 	desc |= ((attr & MT_RW) != 0U) ? LOWER_ATTRS(AP_RW) : LOWER_ATTRS(AP_RO);
 
 	/*
diff --git a/lib/xlat_tables_v2/xlat_tables_private.h b/lib/xlat_tables_v2/xlat_tables_private.h
index 863470c..42c9a43 100644
--- a/lib/xlat_tables_v2/xlat_tables_private.h
+++ b/lib/xlat_tables_v2/xlat_tables_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -40,6 +40,9 @@
 
 extern uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
 
+/* Determine the physical address space encoded in the 'attr' parameter. */
+uint32_t xlat_arch_get_pas(uint32_t attr);
+
 /*
  * Return the execute-never mask that will prevent instruction fetch at the
  * given translation regime.
diff --git a/lib/xlat_tables_v2/xlat_tables_utils.c b/lib/xlat_tables_v2/xlat_tables_utils.c
index 9fae7e9..df17386 100644
--- a/lib/xlat_tables_v2/xlat_tables_utils.c
+++ b/lib/xlat_tables_v2/xlat_tables_utils.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -95,7 +95,23 @@
 			  ? "-USER" : "-PRIV");
 	}
 
+#if ENABLE_RME
+	switch (desc & LOWER_ATTRS(EL3_S1_NSE | NS)) {
+	case 0ULL:
+		printf("-S");
+		break;
+	case LOWER_ATTRS(NS):
+		printf("-NS");
+		break;
+	case LOWER_ATTRS(EL3_S1_NSE):
+		printf("-RT");
+		break;
+	default: /* LOWER_ATTRS(EL3_S1_NSE | NS) */
+		printf("-RL");
+	}
+#else
 	printf(((LOWER_ATTRS(NS) & desc) != 0ULL) ? "-NS" : "-S");
+#endif
 
 #ifdef __aarch64__
 	/* Check Guarded Page bit */
diff --git a/lib/zlib/tf_gunzip.c b/lib/zlib/tf_gunzip.c
index fd56dfc..3ac80bc 100644
--- a/lib/zlib/tf_gunzip.c
+++ b/lib/zlib/tf_gunzip.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,6 +9,7 @@
 #include <string.h>
 
 #include <common/debug.h>
+#include <common/tf_crc32.h>
 #include <lib/utils.h>
 #include <tf_gunzip.h>
 
@@ -100,3 +101,15 @@
 
 	return ret;
 }
+
+/* Wrapper function to calculate CRC
+ * @crc: previous accumulated CRC
+ * @buf: buffer base address
+ * @size: size of the buffer
+ *
+ * Return calculated CRC32 value
+ */
+uint32_t tf_crc32(uint32_t crc, const unsigned char *buf, size_t size)
+{
+	return (uint32_t)crc32((unsigned long)crc, buf, size);
+}
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index 8655028..12aaee6 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -98,41 +98,41 @@
 endef
 
 # IMG_LINKERFILE defines the linker script corresponding to a BL stage
-#   $(1) = BL stage (1, 2, 2u, 31, 32)
+#   $(1) = BL stage
 define IMG_LINKERFILE
-    ${BUILD_DIR}/bl$(1).ld
+    ${BUILD_DIR}/$(1).ld
 endef
 
 # IMG_MAPFILE defines the output file describing the memory map corresponding
 # to a BL stage
-#   $(1) = BL stage (1, 2, 2u, 31, 32)
+#   $(1) = BL stage
 define IMG_MAPFILE
-    ${BUILD_DIR}/bl$(1).map
+    ${BUILD_DIR}/$(1).map
 endef
 
 # IMG_ELF defines the elf file corresponding to a BL stage
-#   $(1) = BL stage (1, 2, 2u, 31, 32)
+#   $(1) = BL stage
 define IMG_ELF
-    ${BUILD_DIR}/bl$(1).elf
+    ${BUILD_DIR}/$(1).elf
 endef
 
 # IMG_DUMP defines the symbols dump file corresponding to a BL stage
-#   $(1) = BL stage (1, 2, 2u, 31, 32)
+#   $(1) = BL stage
 define IMG_DUMP
-    ${BUILD_DIR}/bl$(1).dump
+    ${BUILD_DIR}/$(1).dump
 endef
 
 # IMG_BIN defines the default image file corresponding to a BL stage
-#   $(1) = BL stage (1, 2, 2u, 31, 32)
+#   $(1) = BL stage
 define IMG_BIN
-    ${BUILD_PLAT}/bl$(1).bin
+    ${BUILD_PLAT}/$(1).bin
 endef
 
 # IMG_ENC_BIN defines the default encrypted image file corresponding to a
 # BL stage
-#   $(1) = BL stage (2, 30, 31, 32, 33)
+#   $(1) = BL stage
 define IMG_ENC_BIN
-    ${BUILD_PLAT}/bl$(1)_enc.bin
+    ${BUILD_PLAT}/$(1)_enc.bin
 endef
 
 # ENCRYPT_FW invokes enctool to encrypt firmware binary
@@ -294,15 +294,15 @@
 # MAKE_C builds a C source file and generates the dependency file
 #   $(1) = output directory
 #   $(2) = source file (%.c)
-#   $(3) = BL stage (1, 2, 2u, 31, 32)
+#   $(3) = BL stage
 define MAKE_C
 
 $(eval OBJ := $(1)/$(patsubst %.c,%.o,$(notdir $(2))))
 $(eval DEP := $(patsubst %.o,%.d,$(OBJ)))
-$(eval BL_CPPFLAGS := $(BL$(call uppercase,$(3))_CPPFLAGS) -DIMAGE_BL$(call uppercase,$(3)))
-$(eval BL_CFLAGS := $(BL$(call uppercase,$(3))_CFLAGS))
+$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) -DIMAGE_$(call uppercase,$(3)))
+$(eval BL_CFLAGS := $($(call uppercase,$(3))_CFLAGS))
 
-$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | bl$(3)_dirs
+$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs
 	$$(ECHO) "  CC      $$<"
 	$$(Q)$$(CC) $$(LTO_CFLAGS) $$(TF_CFLAGS) $$(CFLAGS) $(BL_CPPFLAGS) $(BL_CFLAGS) $(MAKE_DEP) -c $$< -o $$@
 
@@ -314,15 +314,15 @@
 # MAKE_S builds an assembly source file and generates the dependency file
 #   $(1) = output directory
 #   $(2) = assembly file (%.S)
-#   $(3) = BL stage (1, 2, 2u, 31, 32)
+#   $(3) = BL stage
 define MAKE_S
 
 $(eval OBJ := $(1)/$(patsubst %.S,%.o,$(notdir $(2))))
 $(eval DEP := $(patsubst %.o,%.d,$(OBJ)))
-$(eval BL_CPPFLAGS := $(BL$(call uppercase,$(3))_CPPFLAGS) -DIMAGE_BL$(call uppercase,$(3)))
-$(eval BL_ASFLAGS := $(BL$(call uppercase,$(3))_ASFLAGS))
+$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) -DIMAGE_$(call uppercase,$(3)))
+$(eval BL_ASFLAGS := $($(call uppercase,$(3))_ASFLAGS))
 
-$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | bl$(3)_dirs
+$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs
 	$$(ECHO) "  AS      $$<"
 	$$(Q)$$(AS) $$(ASFLAGS) $(BL_CPPFLAGS) $(BL_ASFLAGS) $(MAKE_DEP) -c $$< -o $$@
 
@@ -334,13 +334,13 @@
 # MAKE_LD generate the linker script using the C preprocessor
 #   $(1) = output linker script
 #   $(2) = input template
-#   $(3) = BL stage (1, 2, 2u, 31, 32)
+#   $(3) = BL stage
 define MAKE_LD
 
 $(eval DEP := $(1).d)
-$(eval BL_CPPFLAGS := $(BL$(call uppercase,$(3))_CPPFLAGS) -DIMAGE_BL$(call uppercase,$(3)))
+$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) -DIMAGE_$(call uppercase,$(3)))
 
-$(1): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | bl$(3)_dirs
+$(1): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs
 	$$(ECHO) "  PP      $$<"
 	$$(Q)$$(CPP) $$(CPPFLAGS) $(BL_CPPFLAGS) $(TF_CFLAGS_$(ARCH)) -P -x assembler-with-cpp -D__LINKER__ $(MAKE_DEP) -o $$@ $$<
 
@@ -368,7 +368,7 @@
 # MAKE_OBJS builds both C and assembly source files
 #   $(1) = output directory
 #   $(2) = list of source files (both C and assembly)
-#   $(3) = BL stage (1, 2, 2u, 31, 32)
+#   $(3) = BL stage
 define MAKE_OBJS
         $(eval C_OBJS := $(filter %.c,$(2)))
         $(eval REMAIN := $(filter-out %.c,$(2)))
@@ -445,13 +445,13 @@
 
 # MAKE_BL macro defines the targets and options to build each BL image.
 # Arguments:
-#   $(1) = BL stage (1, 2, 2u, 31, 32)
+#   $(1) = BL stage
 #   $(2) = FIP command line option (if empty, image will not be included in the FIP)
 #   $(3) = FIP prefix (optional) (if FWU_, target is fwu_fip instead of fip)
 #   $(4) = BL encryption flag (optional) (0, 1)
 define MAKE_BL
-        $(eval BUILD_DIR  := ${BUILD_PLAT}/bl$(1))
-        $(eval BL_SOURCES := $(BL$(call uppercase,$(1))_SOURCES))
+        $(eval BUILD_DIR  := ${BUILD_PLAT}/$(1))
+        $(eval BL_SOURCES := $($(call uppercase,$(1))_SOURCES))
         $(eval SOURCES    := $(BL_SOURCES) $(BL_COMMON_SOURCES) $(PLAT_BL_COMMON_SOURCES))
         $(eval OBJS       := $(addprefix $(BUILD_DIR)/,$(call SOURCES_TO_OBJS,$(SOURCES))))
         $(eval LINKERFILE := $(call IMG_LINKERFILE,$(1)))
@@ -460,8 +460,8 @@
         $(eval DUMP       := $(call IMG_DUMP,$(1)))
         $(eval BIN        := $(call IMG_BIN,$(1)))
         $(eval ENC_BIN    := $(call IMG_ENC_BIN,$(1)))
-        $(eval BL_LINKERFILE := $(BL$(call uppercase,$(1))_LINKERFILE))
-        $(eval BL_LIBS    := $(BL$(call uppercase,$(1))_LIBS))
+        $(eval BL_LINKERFILE := $($(call uppercase,$(1))_LINKERFILE))
+        $(eval BL_LIBS    := $($(call uppercase,$(1))_LIBS))
         # We use sort only to get a list of unique object directory names.
         # ordering is not relevant but sort removes duplicates.
         $(eval TEMP_OBJ_DIRS := $(sort $(dir ${OBJS} ${LINKERFILE})))
@@ -475,21 +475,21 @@
 
 $(eval $(foreach objd,${OBJ_DIRS},$(call MAKE_PREREQ_DIR,${objd},${BUILD_DIR})))
 
-.PHONY : bl${1}_dirs
+.PHONY : ${1}_dirs
 
 # We use order-only prerequisites to ensure that directories are created,
 # but do not cause re-builds every time a file is written.
-bl${1}_dirs: | ${OBJ_DIRS}
+${1}_dirs: | ${OBJ_DIRS}
 
 $(eval $(call MAKE_OBJS,$(BUILD_DIR),$(SOURCES),$(1)))
 $(eval $(call MAKE_LD,$(LINKERFILE),$(BL_LINKERFILE),$(1)))
-$(eval BL_LDFLAGS := $(BL$(call uppercase,$(1))_LDFLAGS))
+$(eval BL_LDFLAGS := $($(call uppercase,$(1))_LDFLAGS))
 
 ifeq ($(USE_ROMLIB),1)
 $(ELF): romlib.bin
 endif
 
-$(ELF): $(OBJS) $(LINKERFILE) | bl$(1)_dirs libraries $(BL_LIBS)
+$(ELF): $(OBJS) $(LINKERFILE) | $(1)_dirs libraries $(BL_LIBS)
 	$$(ECHO) "  LD      $$@"
 ifdef MAKE_BUILD_STRINGS
 	$(call MAKE_BUILD_STRINGS, $(BUILD_DIR)/build_message.o)
@@ -499,10 +499,10 @@
 		$$(CC) $$(TF_CFLAGS) $$(CFLAGS) -xc -c - -o $(BUILD_DIR)/build_message.o
 endif
 ifneq ($(findstring armlink,$(notdir $(LD))),)
-	$$(Q)$$(LD) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) $(BL_LDFLAGS) --entry=bl${1}_entrypoint \
+	$$(Q)$$(LD) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) $(BL_LDFLAGS) --entry=${1}_entrypoint \
 		--predefine="-D__LINKER__=$(__LINKER__)" \
 		--predefine="-DTF_CFLAGS=$(TF_CFLAGS)" \
-		--map --list="$(MAPFILE)" --scatter=${PLAT_DIR}/scat/bl${1}.scat \
+		--map --list="$(MAPFILE)" --scatter=${PLAT_DIR}/scat/${1}.scat \
 		$(LDPATHS) $(LIBWRAPPER) $(LDLIBS) $(BL_LIBS) \
 		$(BUILD_DIR)/build_message.o $(OBJS)
 else ifneq ($(findstring gcc,$(notdir $(LD))),)
@@ -531,21 +531,21 @@
 	@echo "Built $$@ successfully"
 	@${ECHO_BLANK_LINE}
 
-.PHONY: bl$(1)
+.PHONY: $(1)
 ifeq ($(DISABLE_BIN_GENERATION),1)
-bl$(1): $(ELF) $(DUMP)
+$(1): $(ELF) $(DUMP)
 else
-bl$(1): $(BIN) $(DUMP)
+$(1): $(BIN) $(DUMP)
 endif
 
-all: bl$(1)
+all: $(1)
 
 ifeq ($(4),1)
 $(call ENCRYPT_FW,$(BIN),$(ENC_BIN))
-$(if $(2),$(call TOOL_ADD_IMG_PAYLOAD,bl$(1),$(BIN),--$(2),$(ENC_BIN),$(3), \
+$(if $(2),$(call TOOL_ADD_IMG_PAYLOAD,$(1),$(BIN),--$(2),$(ENC_BIN),$(3), \
 		$(ENC_BIN)))
 else
-$(if $(2),$(call TOOL_ADD_IMG_PAYLOAD,bl$(1),$(BIN),--$(2),$(BIN),$(3)))
+$(if $(2),$(call TOOL_ADD_IMG_PAYLOAD,$(1),$(BIN),--$(2),$(BIN),$(3)))
 endif
 
 endef
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index b2d1ee2..819c536 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016-2021, ARM Limited. All rights reserved.
+# Copyright (c) 2016-2021, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -32,6 +32,9 @@
 # Execute BL2 at EL3
 BL2_AT_EL3			:= 0
 
+# Only use SP packages if SP layout JSON is defined
+BL2_ENABLE_SP_LOAD		:= 0
+
 # BL2 image is stored in XIP memory, for now, this option is only supported
 # when BL2_AT_EL3 is 1.
 BL2_IN_XIP_MEM			:= 0
@@ -102,6 +105,9 @@
 # Flag to enable PSCI STATs functionality
 ENABLE_PSCI_STAT		:= 0
 
+# Flag to enable Realm Management Extension (FEAT_RME)
+ENABLE_RME			:= 0
+
 # Flag to enable runtime instrumentation using PMF
 ENABLE_RUNTIME_INSTRUMENTATION	:= 0
 
@@ -121,6 +127,9 @@
 # Use BRANCH_PROTECTION to enable PAUTH.
 ENABLE_PAUTH			:= 0
 
+# Flag to enable access to the HCRX_EL2 register by setting SCR_EL3.HXEn.
+ENABLE_FEAT_HCX                 := 0
+
 # By default BL31 encryption disabled
 ENCRYPT_BL31			:= 0
 
@@ -344,3 +353,35 @@
 
 # Build option to use the SP804 timer instead of the generic one
 USE_SP804_TIMER			:= 0
+
+# Build option to define number of firmware banks, used in firmware update
+# metadata structure.
+NR_OF_FW_BANKS			:= 2
+
+# Build option to define number of images in firmware bank, used in firmware
+# update metadata structure.
+NR_OF_IMAGES_IN_FW_BANK		:= 1
+
+# Disable Firmware update support by default
+PSA_FWU_SUPPORT			:= 0
+
+# By default, disable access of trace buffer control registers from NS
+# lower ELs  i.e. NS-EL2, or NS-EL1 if NS-EL2 implemented but unused
+# if FEAT_TRBE is implemented.
+# Note FEAT_TRBE is only supported on AArch64 - therefore do not enable in
+# AArch32.
+ifneq (${ARCH},aarch32)
+    ENABLE_TRBE_FOR_NS		:= 0
+else
+    override ENABLE_TRBE_FOR_NS	:= 0
+endif
+
+# By default, disable access of trace system registers from NS lower
+# ELs  i.e. NS-EL2, or NS-EL1 if NS-EL2 implemented but unused if
+# system register trace is implemented.
+ENABLE_SYS_REG_TRACE_FOR_NS	:= 0
+
+# By default, disable trace filter control registers access to NS
+# lower ELs, i.e. NS-EL2, or NS-EL1 if NS-EL2 implemented but unused
+# if FEAT_TRF is implemented.
+ENABLE_TRF_FOR_NS		:= 0
diff --git a/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk
index f7cced4..0a280b4 100644
--- a/make_helpers/tbbr/tbbr_tools.mk
+++ b/make_helpers/tbbr/tbbr_tools.mk
@@ -11,6 +11,7 @@
 # Expected environment:
 #
 #   BUILD_PLAT: output directory
+#   NEED_BL2: indicates whether BL2 is needed by the platform
 #   NEED_BL32: indicates whether BL32 is needed by the platform
 #   BL2: image filename (optional). Default is IMG_BIN(2) (see macro IMG_BIN)
 #   SCP_BL2: image filename (optional). Default is IMG_BIN(30)
@@ -67,9 +68,11 @@
 
 
 # Add the BL2 CoT (image cert)
+ifeq (${NEED_BL2},yes)
 ifeq (${BL2_AT_EL3}, 0)
 $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert))
 endif
+endif
 
 # Add the SCP_BL2 CoT (key cert + img cert)
 ifneq (${SCP_BL2},)
diff --git a/package-lock.json b/package-lock.json
index 46d8bf3..61caf57 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1561,9 +1561,9 @@
       "dev": true
     },
     "path-parse": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
-      "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
       "dev": true
     },
     "path-type": {
diff --git a/plat/allwinner/common/include/platform_def.h b/plat/allwinner/common/include/platform_def.h
index 4893368..49951e0 100644
--- a/plat/allwinner/common/include/platform_def.h
+++ b/plat/allwinner/common/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,9 +13,6 @@
 
 #include <sunxi_mmap.h>
 
-/* The SCP firmware is allocated the last 16KiB of SRAM A2. */
-#define SUNXI_SCP_SIZE			0x4000
-
 #ifdef SUNXI_BL31_IN_DRAM
 
 #define BL31_BASE			SUNXI_DRAM_BASE
@@ -28,10 +25,10 @@
 
 #else	/* !SUNXI_BL31_IN_DRAM */
 
-#define BL31_BASE			(SUNXI_SRAM_A2_BASE + 0x4000)
+#define BL31_BASE			(SUNXI_SRAM_A2_BASE + \
+					 SUNXI_SRAM_A2_BL31_OFFSET)
 #define BL31_LIMIT			(SUNXI_SRAM_A2_BASE + \
 					 SUNXI_SRAM_A2_SIZE - SUNXI_SCP_SIZE)
-#define SUNXI_SCP_BASE			BL31_LIMIT
 
 /* Overwrite U-Boot SPL, but reserve the first page for the SPL header. */
 #define BL31_NOBITS_BASE		(SUNXI_SRAM_A1_BASE + 0x1000)
@@ -39,12 +36,14 @@
 
 #define MAX_XLAT_TABLES			1
 #define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 28)
-#define SUNXI_BL33_VIRT_BASE		(SUNXI_DRAM_VIRT_BASE + SUNXI_DRAM_SEC_SIZE)
 
-#endif /* SUNXI_BL31_IN_DRAM */
+#define SUNXI_BL33_VIRT_BASE		SUNXI_DRAM_VIRT_BASE
 
-/* How much memory to reserve as secure for BL32, if configured */
-#define SUNXI_DRAM_SEC_SIZE		(32U << 20)
+/* The SCP firmware is allocated the last 16KiB of SRAM A2. */
+#define SUNXI_SCP_BASE			BL31_LIMIT
+#define SUNXI_SCP_SIZE			0x4000
+
+#endif /* SUNXI_BL31_IN_DRAM */
 
 /* How much DRAM to map (to map BL33, for fetching the DTB from U-Boot) */
 #define SUNXI_DRAM_MAP_SIZE		(64U << 20)
@@ -52,7 +51,8 @@
 #define CACHE_WRITEBACK_SHIFT		6
 #define CACHE_WRITEBACK_GRANULE		(1 << CACHE_WRITEBACK_SHIFT)
 
-#define MAX_MMAP_REGIONS		(3 + PLATFORM_MMAP_REGIONS)
+#define MAX_STATIC_MMAP_REGIONS		3
+#define MAX_MMAP_REGIONS		(5 + MAX_STATIC_MMAP_REGIONS)
 
 #define PLAT_CSS_SCP_COM_SHARED_MEM_BASE \
 	(SUNXI_SRAM_A2_BASE + SUNXI_SRAM_A2_SIZE - 0x200)
@@ -72,7 +72,6 @@
 #define PLATFORM_CORE_COUNT		(PLATFORM_CLUSTER_COUNT * \
 					 PLATFORM_MAX_CPUS_PER_CLUSTER)
 #define PLATFORM_MAX_CPUS_PER_CLUSTER	U(4)
-#define PLATFORM_MMAP_REGIONS		5
 #define PLATFORM_STACK_SIZE		(0x1000 / PLATFORM_CORE_COUNT)
 
 #ifndef SPD_none
diff --git a/plat/allwinner/common/include/sunxi_def.h b/plat/allwinner/common/include/sunxi_def.h
index f036816..ec50887 100644
--- a/plat/allwinner/common/include/sunxi_def.h
+++ b/plat/allwinner/common/include/sunxi_def.h
@@ -18,5 +18,6 @@
 #define SUNXI_SOC_H5			0x1718
 #define SUNXI_SOC_H6			0x1728
 #define SUNXI_SOC_H616			0x1823
+#define SUNXI_SOC_R329			0x1851
 
 #endif /* SUNXI_DEF_H */
diff --git a/plat/allwinner/common/sunxi_bl31_setup.c b/plat/allwinner/common/sunxi_bl31_setup.c
index 72bfbd9..14049e8 100644
--- a/plat/allwinner/common/sunxi_bl31_setup.c
+++ b/plat/allwinner/common/sunxi_bl31_setup.c
@@ -128,6 +128,9 @@
 	case SUNXI_SOC_H616:
 		soc_name = "H616";
 		break;
+	case SUNXI_SOC_R329:
+		soc_name = "R329";
+		break;
 	default:
 		soc_name = "unknown";
 		break;
diff --git a/plat/allwinner/common/sunxi_common.c b/plat/allwinner/common/sunxi_common.c
index d47d360..82410b1 100644
--- a/plat/allwinner/common/sunxi_common.c
+++ b/plat/allwinner/common/sunxi_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,17 +14,11 @@
 #include <sunxi_mmap.h>
 #include <sunxi_private.h>
 
-static const mmap_region_t sunxi_mmap[PLATFORM_MMAP_REGIONS + 1] = {
+static const mmap_region_t sunxi_mmap[MAX_STATIC_MMAP_REGIONS + 1] = {
 	MAP_REGION_FLAT(SUNXI_SRAM_BASE, SUNXI_SRAM_SIZE,
-			MT_RW_DATA | MT_SECURE),
-#ifdef SUNXI_SCP_BASE
-	MAP_REGION_FLAT(SUNXI_SCP_BASE, SUNXI_SCP_SIZE,
 			MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER),
-#endif
 	MAP_REGION_FLAT(SUNXI_DEV_BASE, SUNXI_DEV_SIZE,
 			MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER),
-	MAP_REGION(SUNXI_DRAM_BASE, SUNXI_DRAM_VIRT_BASE, SUNXI_DRAM_SEC_SIZE,
-		   MT_RW_DATA | MT_SECURE),
 	MAP_REGION(PRELOADED_BL33_BASE, SUNXI_BL33_VIRT_BASE,
 		   SUNXI_DRAM_MAP_SIZE, MT_RW_DATA | MT_NS),
 	{},
@@ -40,12 +34,24 @@
 	mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
 			BL_CODE_END - BL_CODE_BASE,
 			MT_CODE | MT_SECURE);
+	mmap_add_region(BL_CODE_END, BL_CODE_END,
+			BL_END - BL_CODE_END,
+			MT_RW_DATA | MT_SECURE);
+#if SEPARATE_CODE_AND_RODATA
 	mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE,
 			BL_RO_DATA_END - BL_RO_DATA_BASE,
 			MT_RO_DATA | MT_SECURE);
+#endif
+#if SEPARATE_NOBITS_REGION
+	mmap_add_region(BL_NOBITS_BASE, BL_NOBITS_BASE,
+			BL_NOBITS_END - BL_NOBITS_BASE,
+			MT_RW_DATA | MT_SECURE);
+#endif
+#if USE_COHERENT_MEM
 	mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
 			BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
 			MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER);
+#endif
 
 	mmap_add(sunxi_mmap);
 	init_xlat_tables();
diff --git a/plat/allwinner/common/sunxi_cpu_ops.c b/plat/allwinner/common/sunxi_cpu_ops.c
index 420b507..46e7090 100644
--- a/plat/allwinner/common/sunxi_cpu_ops.c
+++ b/plat/allwinner/common/sunxi_cpu_ops.c
@@ -42,6 +42,7 @@
 	mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xe0);
 	mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x80);
 	mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x00);
+	udelay(1);
 }
 
 /* We can't turn ourself off like this, but it works for other cores. */
@@ -75,7 +76,8 @@
 	/* 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_CPUCFG_CLS_CTRL_REG0(cluster), BIT(24 + core));
+	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 */
diff --git a/plat/allwinner/common/sunxi_scpi_pm.c b/plat/allwinner/common/sunxi_scpi_pm.c
index 74763ef..eb37daa 100644
--- a/plat/allwinner/common/sunxi_scpi_pm.c
+++ b/plat/allwinner/common/sunxi_scpi_pm.c
@@ -212,7 +212,6 @@
 		uint32_t offset = SUNXI_SCP_BASE - vector;
 
 		mmio_write_32(vector, offset >> 2);
-		clean_dcache_range(vector, sizeof(uint32_t));
 	}
 
 	/* Take the SCP out of reset. */
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h
index c3eeadb..aed3585 100644
--- a/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h
+++ b/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h
@@ -33,4 +33,7 @@
 #define SUNXI_R_CPUCFG_SS_ENTRY_REG	(SUNXI_R_CPUCFG_BASE + 0x01a8)
 #define SUNXI_R_CPUCFG_HP_FLAG_REG	(SUNXI_R_CPUCFG_BASE + 0x01ac)
 
+#define SUNXI_AA64nAA32_REG		SUNXI_CPUCFG_CLS_CTRL_REG0
+#define SUNXI_AA64nAA32_OFFSET		24
+
 #endif /* SUNXI_CPUCFG_H */
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
index 6c847d3..6d10921 100644
--- a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
+++ b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
@@ -15,6 +15,7 @@
 #define SUNXI_SRAM_A1_BASE		0x00010000
 #define SUNXI_SRAM_A1_SIZE		0x00008000
 #define SUNXI_SRAM_A2_BASE		0x00040000
+#define SUNXI_SRAM_A2_BL31_OFFSET	0x00004000
 #define SUNXI_SRAM_A2_SIZE		0x00014000
 #define SUNXI_SRAM_C_BASE		0x00018000
 #define SUNXI_SRAM_C_SIZE		0x0001c000
diff --git a/plat/allwinner/sun50i_a64/sunxi_power.c b/plat/allwinner/sun50i_a64/sunxi_power.c
index 0fdb62d..a35b9dd 100644
--- a/plat/allwinner/sun50i_a64/sunxi_power.c
+++ b/plat/allwinner/sun50i_a64/sunxi_power.c
@@ -244,7 +244,6 @@
 	 * in instruction granularity (32 bits).
 	 */
 	mmio_write_32(arisc_reset_vec, ((uintptr_t)code - arisc_reset_vec) / 4);
-	clean_dcache_range(arisc_reset_vec, 4);
 
 	/* De-assert the arisc reset line to let it run. */
 	mmio_setbits_32(SUNXI_R_CPUCFG_BASE, BIT(0));
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h
index a2b94af..5bfda5d 100644
--- a/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h
+++ b/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h
@@ -29,4 +29,7 @@
 #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/sun50i_h6/include/sunxi_mmap.h b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
index 2d7b098..58216d8 100644
--- a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
+++ b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
@@ -15,6 +15,7 @@
 #define SUNXI_SRAM_A1_BASE		0x00020000
 #define SUNXI_SRAM_A1_SIZE		0x00008000
 #define SUNXI_SRAM_A2_BASE		0x00100000
+#define SUNXI_SRAM_A2_BL31_OFFSET	0x00004000
 #define SUNXI_SRAM_A2_SIZE		0x00018000
 #define SUNXI_SRAM_C_BASE		0x00028000
 #define SUNXI_SRAM_C_SIZE		0x0001e000
diff --git a/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h
index a637554..dab663b 100644
--- a/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h
+++ b/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h
@@ -29,4 +29,7 @@
 #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/sun50i_r329/include/sunxi_ccu.h b/plat/allwinner/sun50i_r329/include/sunxi_ccu.h
new file mode 100644
index 0000000..0e6b543
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/include/sunxi_ccu.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2021 Sipeed
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_CCU_H
+#define SUNXI_CCU_H
+
+#define SUNXI_CCU_SEC_SWITCH_REG	(SUNXI_CCU_BASE + 0x0f00)
+
+#define SUNXI_R_PRCM_SEC_SWITCH_REG	(SUNXI_R_PRCM_BASE + 0x0290)
+
+#endif /* SUNXI_CCU_H */
diff --git a/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h
new file mode 100644
index 0000000..9478f32
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h
@@ -0,0 +1,31 @@
+/*
+ * 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 */
diff --git a/plat/allwinner/sun50i_r329/include/sunxi_mmap.h b/plat/allwinner/sun50i_r329/include/sunxi_mmap.h
new file mode 100644
index 0000000..a4469b5
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/include/sunxi_mmap.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_MMAP_H
+#define SUNXI_MMAP_H
+
+/* Memory regions */
+#define SUNXI_ROM_BASE			0x00000000
+#define SUNXI_ROM_SIZE			0x00010000
+/*
+ * In fact all SRAM from 0x100000 is SRAM A2. However as it's too big for
+ * firmware, and the user manual gives a tip on a 2*64K/27*64K partition,
+ * only use the first 2*64K for firmwares now, with the SPL using the first
+ * 64K and BL3-1 using the second one.
+ *
+ * Only the used 2*64K SRAM is defined here, to prevent a gaint translation
+ * table to be generated.
+ */
+#define SUNXI_SRAM_BASE			0x00100000
+#define SUNXI_SRAM_SIZE			0x00020000
+#define SUNXI_SRAM_A1_BASE		0x00100000
+#define SUNXI_SRAM_A1_SIZE		0x00010000
+#define SUNXI_SRAM_A2_BASE		0x00110000
+#define SUNXI_SRAM_A2_BL31_OFFSET	0x00000000
+#define SUNXI_SRAM_A2_SIZE		0x00010000
+#define SUNXI_DEV_BASE			0x01000000
+#define SUNXI_DEV_SIZE			0x09000000
+#define SUNXI_DRAM_BASE			0x40000000
+#define SUNXI_DRAM_VIRT_BASE		0x0a000000
+
+/* Memory-mapped devices */
+#define SUNXI_WDOG_BASE			0x020000a0
+#define SUNXI_R_WDOG_BASE		SUNXI_WDOG_BASE
+#define SUNXI_PIO_BASE			0x02000400
+#define SUNXI_SPC_BASE			0x02000800
+#define SUNXI_CCU_BASE			0x02001000
+#define SUNXI_UART0_BASE		0x02500000
+#define SUNXI_SYSCON_BASE		0x03000000
+#define SUNXI_DMA_BASE			0x03002000
+#define SUNXI_SID_BASE			0x03006000
+#define SUNXI_GICD_BASE			0x03021000
+#define SUNXI_GICC_BASE			0x03022000
+#define SUNXI_SPI0_BASE			0x04025000
+#define SUNXI_R_CPUCFG_BASE		0x07000400
+#define SUNXI_R_PRCM_BASE		0x07010000
+#define SUNXI_R_PIO_BASE		0x07022000
+#define SUNXI_R_UART_BASE		0x07080000
+#define SUNXI_R_I2C_BASE		0x07081400
+#define SUNXI_CPUCFG_BASE		0x08100000
+#define SUNXI_C0_CPUXCFG_BASE		0x09010000
+
+#endif /* SUNXI_MMAP_H */
diff --git a/plat/allwinner/sun50i_r329/include/sunxi_spc.h b/plat/allwinner/sun50i_r329/include/sunxi_spc.h
new file mode 100644
index 0000000..2c87bca
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/include/sunxi_spc.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2021 Sipeed
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_SPC_H
+#define SUNXI_SPC_H
+
+/* Get by REing stock ATF and checking initialization loop boundary */
+#define SUNXI_SPC_NUM_PORTS		11
+
+#define SUNXI_SPC_DECPORT_STA_REG(p)	(SUNXI_SPC_BASE + 0x0000 + 0x10 * (p))
+#define SUNXI_SPC_DECPORT_SET_REG(p)	(SUNXI_SPC_BASE + 0x0004 + 0x10 * (p))
+#define SUNXI_SPC_DECPORT_CLR_REG(p)	(SUNXI_SPC_BASE + 0x0008 + 0x10 * (p))
+
+#endif /* SUNXI_SPC_H */
diff --git a/plat/allwinner/sun50i_r329/platform.mk b/plat/allwinner/sun50i_r329/platform.mk
new file mode 100644
index 0000000..05d7cde
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/platform.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2021 Sipeed
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Without a management processor there is no SCPI support.
+SUNXI_PSCI_USE_SCPI	:=	0
+SUNXI_PSCI_USE_NATIVE	:=	1
+
+# The differences between the platforms are covered by the include files.
+include plat/allwinner/common/allwinner-common.mk
+
+# the above could be overwritten on the command line
+ifeq (${SUNXI_PSCI_USE_SCPI}, 1)
+    $(error "R329 does not support SCPI PSCI ops")
+endif
+
+# Put NOBITS memory in the first 64K of SRAM A2, overwriting U-Boot's SPL.
+SEPARATE_NOBITS_REGION	:=	1
diff --git a/plat/allwinner/sun50i_r329/sunxi_power.c b/plat/allwinner/sun50i_r329/sunxi_power.c
new file mode 100644
index 0000000..96a24d5
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/sunxi_power.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Sipeed
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <sunxi_mmap.h>
+#include <sunxi_cpucfg.h>
+#include <sunxi_private.h>
+
+int sunxi_pmic_setup(uint16_t socid, const void *fdt)
+{
+	/* Currently known hardware has no PMIC */
+
+	return 0;
+}
+
+void sunxi_power_down(void)
+{
+}
+
+void sunxi_cpu_power_off_self(void)
+{
+	/* TODO: It's still unknown whether CPUIDLE exists on R329 */
+}
diff --git a/plat/arm/board/arm_fpga/build_axf.ld.S b/plat/arm/board/arm_fpga/build_axf.ld.S
index d7cd008..b4bc7d8 100644
--- a/plat/arm/board/arm_fpga/build_axf.ld.S
+++ b/plat/arm/board/arm_fpga/build_axf.ld.S
@@ -17,6 +17,7 @@
 
 INPUT(./bl31/bl31.elf)
 INPUT(./rom_trampoline.o)
+INPUT(./kernel_trampoline.o)
 
 TARGET(binary)
 INPUT(./fdts/arm_fpga.dtb)
@@ -33,7 +34,6 @@
 	.bl31 (BL31_BASE): {
 		ASSERT(. == ALIGN(PAGE_SIZE), "BL31_BASE is not page aligned");
 		*bl31.elf(.text* .data* .rodata* ro* .bss*)
-		*bl31.elf(.stack)
 	}
 
 	.dtb (FPGA_PRELOADED_DTB_BASE): {
@@ -41,6 +41,12 @@
 		*arm_fpga.dtb
 	}
 
+	.kern_tramp (PRELOADED_BL33_BASE): {
+		*kernel_trampoline.o(.text*)
+		KEEP(*(.kern_tramp))
+	}
+
+	/DISCARD/ : { *(stacks) }
 	/DISCARD/ : { *(.debug_*) }
 	/DISCARD/ : { *(.note*) }
 	/DISCARD/ : { *(.comment*) }
diff --git a/plat/arm/board/arm_fpga/fpga_bl31_setup.c b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
index a5f5ea0..2b5ca4a 100644
--- a/plat/arm/board/arm_fpga/fpga_bl31_setup.c
+++ b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
@@ -144,6 +144,12 @@
 		panic();
 	}
 
+	/* Reserve memory used by Trusted Firmware. */
+	if (fdt_add_reserved_memory(fdt, "tf-a@80000000", BL31_BASE,
+				    BL31_LIMIT - BL31_BASE)) {
+		WARN("Failed to add reserved memory node to DT\n");
+	}
+
 	/* Check for the command line signature. */
 	if (!strncmp(cmdline, "CMD:", 4)) {
 		int chosen;
@@ -218,7 +224,7 @@
 			INFO("Adjusting GICR DT region to cover %u cores\n",
 			      nr_cores);
 			err = fdt_adjust_gic_redist(fdt, nr_cores,
-						    1U << GICR_PCPUBASE_SHIFT);
+						    fpga_get_redist_size());
 			if (err < 0) {
 				ERROR("Error %d fixing up GIC DT node\n", err);
 			}
diff --git a/plat/arm/board/arm_fpga/fpga_gicv3.c b/plat/arm/board/arm_fpga/fpga_gicv3.c
index bfc116b..4a97beb 100644
--- a/plat/arm/board/arm_fpga/fpga_gicv3.c
+++ b/plat/arm/board/arm_fpga/fpga_gicv3.c
@@ -8,6 +8,7 @@
 #include <common/fdt_wrappers.h>
 #include <drivers/arm/gicv3.h>
 #include <drivers/arm/gic_common.h>
+#include <lib/mmio.h>
 #include <libfdt.h>
 
 #include <platform_def.h>
@@ -82,3 +83,11 @@
 {
 	return gicv3_rdistif_get_number_frames(fpga_gicv3_driver_data.gicr_base);
 }
+
+uintptr_t fpga_get_redist_size(void)
+{
+	uint64_t typer_val = mmio_read_64(fpga_gicv3_driver_data.gicr_base +
+					  GICR_TYPER);
+
+	return gicv3_redist_size(typer_val);
+}
diff --git a/plat/arm/board/arm_fpga/fpga_private.h b/plat/arm/board/arm_fpga/fpga_private.h
index 1ca241f..cc809c4 100644
--- a/plat/arm/board/arm_fpga/fpga_private.h
+++ b/plat/arm/board/arm_fpga/fpga_private.h
@@ -25,6 +25,7 @@
 void fpga_pwr_gic_off(void);
 unsigned int plat_fpga_calc_core_pos(uint32_t mpid);
 unsigned int fpga_get_nr_gic_cores(void);
+uintptr_t fpga_get_redist_size(void);
 
 #endif /* __ASSEMBLER__ */
 
diff --git a/plat/arm/board/arm_fpga/include/platform_def.h b/plat/arm/board/arm_fpga/include/platform_def.h
index 411b936..2350d87 100644
--- a/plat/arm/board/arm_fpga/include/platform_def.h
+++ b/plat/arm/board/arm_fpga/include/platform_def.h
@@ -30,7 +30,7 @@
 
 #if !ENABLE_PIE
 #define BL31_BASE			UL(0x80000000)
-#define BL31_LIMIT			UL(0x80100000)
+#define BL31_LIMIT			UL(0x80070000)
 #else
 #define BL31_BASE			UL(0x0)
 #define BL31_LIMIT			UL(0x01000000)
diff --git a/plat/arm/board/arm_fpga/kernel_trampoline.S b/plat/arm/board/arm_fpga/kernel_trampoline.S
new file mode 100644
index 0000000..f4c08ef
--- /dev/null
+++ b/plat/arm/board/arm_fpga/kernel_trampoline.S
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * The traditional arm64 Linux kernel load address is 512KiB from the
+ * beginning of DRAM, caused by this having been the default value of the
+ * kernel's CONFIG_TEXT_OFFSET Kconfig value.
+ * However kernel version 5.8 changed the default offset (into a 2MB page)
+ * to 0, so TF-A's default assumption is no longer true. Fortunately the
+ * kernel got more relaxed about this offset at the same time, so it
+ * tolerates the wrong offset, but issues a warning:
+ * [Firmware Bug]: Kernel image misaligned at boot, please fix your bootloader!
+ *
+ * We cannot easily change the load address offset in TF-A to be 2MiB, because
+ * this would break older kernels - and they are not as forgiving in this
+ * respect.
+ *
+ * But we can allow users to load the kernel at the right offset, and
+ * offer this trampoline here to transition to this new load address.
+ * Any older kernels, or newer kernels misloaded, will overwrite this code
+ * here, so it does no harm in this case.
+ */
+
+#include <asm_macros.S>
+#include <common/bl_common.ld.h>
+
+.text
+.global _tramp_start
+
+_tramp_start:
+	adr	x4, _tramp_start
+	orr	x4, x4, #0x1fffff
+	add	x4, x4, #1			/* align up to 2MB */
+	br	x4
diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk
index f1fd777..901fabf 100644
--- a/plat/arm/board/arm_fpga/platform.mk
+++ b/plat/arm/board/arm_fpga/platform.mk
@@ -32,6 +32,8 @@
 FPGA_PRELOADED_CMD_LINE := 0x1000
 $(eval $(call add_define,FPGA_PRELOADED_CMD_LINE))
 
+ENABLE_AMU		:=	1
+
 # Treating this as a memory-constrained port for now
 USE_COHERENT_MEM	:=	0
 
@@ -87,6 +89,8 @@
 # Allow detection of GIC-600
 GICV3_SUPPORT_GIC600	:=	1
 
+GIC_ENABLE_V4_EXTN	:=	1
+
 # Include GICv3 driver files
 include drivers/arm/gic/v3/gicv3.mk
 
@@ -113,11 +117,12 @@
 				${FPGA_CPU_LIBS}				\
 				${FPGA_GIC_SOURCES}
 
-$(eval $(call MAKE_S,$(BUILD_PLAT),plat/arm/board/arm_fpga/rom_trampoline.S,31))
-$(eval $(call MAKE_LD,$(BUILD_PLAT)/build_axf.ld,plat/arm/board/arm_fpga/build_axf.ld.S,31))
+$(eval $(call MAKE_S,$(BUILD_PLAT),plat/arm/board/arm_fpga/rom_trampoline.S,bl31))
+$(eval $(call MAKE_S,$(BUILD_PLAT),plat/arm/board/arm_fpga/kernel_trampoline.S,bl31))
+$(eval $(call MAKE_LD,$(BUILD_PLAT)/build_axf.ld,plat/arm/board/arm_fpga/build_axf.ld.S,bl31))
 
-bl31.axf: bl31 dtbs ${BUILD_PLAT}/rom_trampoline.o ${BUILD_PLAT}/build_axf.ld
+bl31.axf: bl31 dtbs ${BUILD_PLAT}/rom_trampoline.o ${BUILD_PLAT}/kernel_trampoline.o ${BUILD_PLAT}/build_axf.ld
 	$(ECHO) "  LD      $@"
-	$(Q)$(LD) -T ${BUILD_PLAT}/build_axf.ld -L ${BUILD_PLAT} --strip-debug -o ${BUILD_PLAT}/bl31.axf
+	$(Q)$(LD) -T ${BUILD_PLAT}/build_axf.ld -L ${BUILD_PLAT} --strip-debug -s -n -o ${BUILD_PLAT}/bl31.axf
 
 all: bl31.axf
diff --git a/plat/arm/board/common/rotpk/arm_dev_rotpk.S b/plat/arm/board/common/rotpk/arm_dev_rotpk.S
index 80f2192..38f91fe 100644
--- a/plat/arm/board/common/rotpk/arm_dev_rotpk.S
+++ b/plat/arm/board/common/rotpk/arm_dev_rotpk.S
@@ -1,10 +1,17 @@
 /*
- * Copyright (c) 2020, ARM Limited. All rights reserved.
+ * Copyright (c) 2021, ARM Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+/* diphda platform provides custom values for the macros defined in
+ * arm_def.h , so only platform_def.h needs to be included
+ */
+#if !defined(TARGET_PLATFORM_FVP) && !defined(TARGET_PLATFORM_FPGA)
 #include "plat/arm/common/arm_def.h"
+#else
+#include <platform_def.h>
+#endif
 
 	.global arm_rotpk_header
 	.global arm_rotpk_header_end
diff --git a/plat/arm/board/diphda/common/diphda_bl2_mem_params_desc.c b/plat/arm/board/diphda/common/diphda_bl2_mem_params_desc.c
new file mode 100644
index 0000000..916c868
--- /dev/null
+++ b/plat/arm/board/diphda/common/diphda_bl2_mem_params_desc.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/desc_image_load.h>
+
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+
+	/* Fill BL31 related information */
+	{
+		.image_id = BL31_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+			VERSION_2, entry_point_info_t,
+			SECURE | EXECUTABLE | EP_FIRST_EXE),
+		.ep_info.pc = BL31_BASE,
+		.ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+			DISABLE_ALL_EXCEPTIONS),
+			.ep_info.args.arg3 = ARM_BL31_PLAT_PARAM_VAL,
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+			VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP),
+		.image_info.image_base = BL31_BASE,
+		.image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+
+		.next_handoff_image_id = BL32_IMAGE_ID,
+	},
+
+	/* Fill BL32 related information */
+	{
+		.image_id = BL32_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+			VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),
+		.ep_info.pc = BL32_BASE,
+			.ep_info.args.arg0 = DIPHDA_TOS_FW_CONFIG_BASE,
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+			VERSION_2, image_info_t, 0),
+		.image_info.image_base = BL32_BASE,
+		.image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+		.next_handoff_image_id = BL33_IMAGE_ID,
+	},
+
+	/* Fill TOS_FW_CONFIG related information */
+	{
+		.image_id = TOS_FW_CONFIG_ID,
+		.image_info.image_base = DIPHDA_TOS_FW_CONFIG_BASE,
+		.image_info.image_max_size = DIPHDA_TOS_FW_CONFIG_LIMIT - \
+			DIPHDA_TOS_FW_CONFIG_BASE,
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+			VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+		VERSION_2, image_info_t, 0),
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+
+	/* Fill BL33 related information */
+	{
+		.image_id = BL33_IMAGE_ID,
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+			VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE),
+		.ep_info.pc = PLAT_ARM_NS_IMAGE_BASE,
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+			VERSION_2, image_info_t, 0),
+		.image_info.image_base = PLAT_ARM_NS_IMAGE_BASE,
+		.image_info.image_max_size = ARM_DRAM1_BASE + ARM_DRAM1_SIZE
+			- PLAT_ARM_NS_IMAGE_BASE,
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/arm/board/tc0/tc0_err.c b/plat/arm/board/diphda/common/diphda_err.c
similarity index 62%
copy from plat/arm/board/tc0/tc0_err.c
copy to plat/arm/board/diphda/common/diphda_err.c
index 83f2e9f..89a3b82 100644
--- a/plat/arm/board/tc0/tc0_err.c
+++ b/plat/arm/board/diphda/common/diphda_err.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,11 +7,11 @@
 #include <plat/arm/common/plat_arm.h>
 
 /*
- * tc0 error handler
+ * diphda error handler
  */
 void __dead2 plat_arm_error_handler(int err)
 {
-	while (true) {
+	while (1) {
 		wfi();
 	}
 }
diff --git a/plat/arm/board/diphda/common/diphda_helpers.S b/plat/arm/board/diphda/common/diphda_helpers.S
new file mode 100644
index 0000000..c9d2a88
--- /dev/null
+++ b/plat/arm/board/diphda/common/diphda_helpers.S
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+	.globl	plat_secondary_cold_boot_setup
+	.globl	plat_get_my_entrypoint
+	.globl	plat_is_my_cpu_primary
+	.globl	plat_arm_calc_core_pos
+
+	/* --------------------------------------------------------------------
+	 * void plat_secondary_cold_boot_setup (void);
+	 *
+	 * For AArch32, cold-booting secondary CPUs is not yet
+	 * implemented and they panic.
+	 * --------------------------------------------------------------------
+	 */
+func plat_secondary_cold_boot_setup
+cb_panic:
+	b	cb_panic
+endfunc plat_secondary_cold_boot_setup
+
+	/* ---------------------------------------------------------------------
+	 * unsigned long plat_get_my_entrypoint (void);
+	 *
+	 * Main job of this routine is to distinguish between a cold and warm
+	 * boot. On diphda, this information can be queried from the power
+	 * controller. The Power Control SYS Status Register (PSYSR) indicates
+	 * the wake-up reason for the CPU.
+	 *
+	 * For a cold boot, return 0.
+	 * For a warm boot, Not yet supported.
+	 *
+	 * TODO: PSYSR is a common register and should be
+	 * 	accessed using locks. Since it is not possible
+	 * 	to use locks immediately after a cold reset
+	 * 	we are relying on the fact that after a cold
+	 * 	reset all cpus will read the same WK field
+	 * ---------------------------------------------------------------------
+	 */
+func plat_get_my_entrypoint
+	/* TODO support warm boot */
+	/* Cold reset */
+	mov	x0, #0
+	ret
+endfunc plat_get_my_entrypoint
+
+	/* -----------------------------------------------------
+	 * unsigned int plat_is_my_cpu_primary (void);
+	 *
+	 * Find out whether the current CPU is the primary
+	 * CPU.
+	 * -----------------------------------------------------
+	 */
+func plat_is_my_cpu_primary
+	mrs	x0, mpidr_el1
+	mov_imm	x1, MPIDR_AFFINITY_MASK
+	and	x0, x0, x1
+	cmp	x0, #DIPHDA_PRIMARY_CPU
+	cset	w0, eq
+	ret
+endfunc plat_is_my_cpu_primary
diff --git a/plat/arm/board/diphda/common/diphda_plat.c b/plat/arm/board/diphda/common/diphda_plat.c
new file mode 100644
index 0000000..28d15a5
--- /dev/null
+++ b/plat/arm/board/diphda/common/diphda_plat.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/bl_common.h>
+
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+/*
+ * Table of regions to map using the MMU.
+ * Replace or extend the below regions as required
+ */
+
+const mmap_region_t plat_arm_mmap[] = {
+	ARM_MAP_SHARED_RAM,
+	ARM_MAP_NS_SHARED_RAM,
+	ARM_MAP_NS_DRAM1,
+	DIPHDA_MAP_DEVICE,
+	DIPHDA_EXTERNAL_FLASH,
+	{0}
+};
+
+/* diphda only has one always-on power domain and there
+ * is no power control present
+ */
+void __init plat_arm_pwrc_setup(void)
+{
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	/* Returning the Generic Timer Frequency */
+	return SYS_COUNTER_FREQ_IN_TICKS;
+}
+
+
+/*
+ * 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)
+{
+}
+
+/*
+ * This function is invoked during Mbed TLS library initialisation to get a heap
+ * The function simply returns the default allocated heap.
+ */
+
+#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
diff --git a/plat/arm/board/diphda/common/diphda_pm.c b/plat/arm/board/diphda/common/diphda_pm.c
new file mode 100644
index 0000000..12b322e
--- /dev/null
+++ b/plat/arm/board/diphda/common/diphda_pm.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/psci/psci.h>
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
+ * platform layer will take care of registering the handlers with PSCI.
+ ******************************************************************************/
+plat_psci_ops_t plat_arm_psci_pm_ops = {
+	/* dummy struct */
+	.validate_ns_entrypoint = NULL
+};
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+	return ops;
+}
diff --git a/plat/arm/board/diphda/common/diphda_security.c b/plat/arm/board/diphda/common/diphda_security.c
new file mode 100644
index 0000000..bf172af
--- /dev/null
+++ b/plat/arm/board/diphda/common/diphda_security.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * We assume that all security programming is done by the primary core.
+ */
+void plat_arm_security_setup(void)
+{
+	/*
+	 * If the platform had additional peripheral specific security
+	 * configurations, those would be configured here.
+	 */
+}
diff --git a/plat/arm/board/diphda/common/diphda_stack_protector.c b/plat/arm/board/diphda/common/diphda_stack_protector.c
new file mode 100644
index 0000000..6228b63
--- /dev/null
+++ b/plat/arm/board/diphda/common/diphda_stack_protector.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <plat/common/platform.h>
+
+static uint32_t plat_generate_random_number(void)
+{
+	uintptr_t return_addr = (uintptr_t)__builtin_return_address(0U);
+	uintptr_t frame_addr = (uintptr_t)__builtin_frame_address(0U);
+	uint64_t cntpct = read_cntpct_el0();
+
+	/* Generate 32-bit pattern: saving the 2 least significant bytes
+	 * in random_lo and random_hi
+	 */
+	uint16_t random_lo = (uint16_t)(
+			(((uint64_t)return_addr) << 13) ^ frame_addr ^ cntpct
+			);
+
+	uint16_t random_hi = (uint16_t)(
+			(((uint64_t)frame_addr) << 15) ^ return_addr ^ cntpct
+			);
+
+	return (((uint32_t)random_hi) << 16) | random_lo;
+}
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+	return  plat_generate_random_number(); /* a 32-bit pattern returned */
+}
diff --git a/plat/arm/board/diphda/common/diphda_topology.c b/plat/arm/board/diphda/common/diphda_topology.c
new file mode 100644
index 0000000..9dfd05d
--- /dev/null
+++ b/plat/arm/board/diphda/common/diphda_topology.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+/* The diphda power domain tree descriptor */
+static unsigned char diphda_power_domain_tree_desc[PLAT_ARM_CLUSTER_COUNT
+							+ 2];
+/*******************************************************************************
+ * This function dynamically constructs the topology according to
+ * CLUSTER_COUNT and returns it.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	int i;
+
+	/*
+	 * The highest level is the system level. The next level is constituted
+	 * by clusters and then cores in clusters.
+	 */
+	diphda_power_domain_tree_desc[0] = 1;
+	diphda_power_domain_tree_desc[1] = PLAT_ARM_CLUSTER_COUNT;
+
+	for (i = 0; i < PLAT_ARM_CLUSTER_COUNT; i++)
+		diphda_power_domain_tree_desc[i + 2] = PLATFORM_CORE_COUNT;
+
+	return diphda_power_domain_tree_desc;
+}
+
+/******************************************************************************
+ * This function implements a part of the critical interface between the PSCI
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is
+ * returned in case the MPIDR is invalid.
+ *****************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+	return plat_arm_calc_core_pos(mpidr);
+}
diff --git a/plat/arm/board/diphda/common/diphda_trusted_boot.c b/plat/arm/board/diphda/common/diphda_trusted_boot.c
new file mode 100644
index 0000000..ddb41fa
--- /dev/null
+++ b/plat/arm/board/diphda/common/diphda_trusted_boot.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * 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
+ * }
+ *
+ * The function returns 0 on success. Any other value is treated as error by the
+ * Trusted Board Boot. The function also reports extra information related
+ * to the ROTPK in the flags parameter: ROTPK_IS_HASH, ROTPK_NOT_DEPLOYED.
+ *
+ * Refer to the TF-A porting-guide document for more details.
+ */
+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);
+}
+
+/*
+ * STUB overriding the non-volatile counter reading.
+ * NV counters are not implemented at this stage of development.
+ * Return: 0 = success
+ */
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+    *nv_ctr = DIPHDA_FW_NVCTR_VAL;
+    return 0;
+}
+
+/*
+ * STUB overriding the non-volatile counter updating.
+ * NV counters are not implemented at this stage of development.
+ * Return: 0 = success
+ */
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+    return 0;
+}
diff --git a/plat/arm/board/diphda/common/fdts/diphda_spmc_manifest.dts b/plat/arm/board/diphda/common/fdts/diphda_spmc_manifest.dts
new file mode 100644
index 0000000..536bdc3
--- /dev/null
+++ b/plat/arm/board/diphda/common/fdts/diphda_spmc_manifest.dts
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021, 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 = <0x1>;
+		exec_state = <0x0>;
+		load_address = <0x0 0x2002000>;
+		entrypoint = <0x0 0x2002000>;
+		binary_size = <0xae000>;
+	};
+
+};
diff --git a/plat/arm/board/diphda/common/include/platform_def.h b/plat/arm/board/diphda/common/include/platform_def.h
new file mode 100644
index 0000000..37fd71b
--- /dev/null
+++ b/plat/arm/board/diphda/common/include/platform_def.h
@@ -0,0 +1,416 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <common/tbbr/tbbr_img_def.h>
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+#include <plat/arm/board/common/v2m_def.h>
+#include <plat/arm/common/arm_spm_def.h>
+#include <plat/arm/common/smccc_def.h>
+#include <plat/common/common_def.h>
+#include <plat/arm/soc/common/soc_css_def.h>
+
+#define ARM_ROTPK_HEADER_LEN			19
+#define ARM_ROTPK_HASH_LEN			32
+
+/* Special value used to verify platform parameters from BL2 to BL31 */
+#define ARM_BL31_PLAT_PARAM_VAL		ULL(0x0f1e2d3c4b5a6978)
+
+/* PL011 UART related constants */
+#ifdef V2M_IOFPGA_UART0_CLK_IN_HZ
+#undef V2M_IOFPGA_UART0_CLK_IN_HZ
+#endif
+
+#ifdef V2M_IOFPGA_UART1_CLK_IN_HZ
+#undef V2M_IOFPGA_UART1_CLK_IN_HZ
+#endif
+
+#define V2M_IOFPGA_UART0_CLK_IN_HZ		50000000
+#define V2M_IOFPGA_UART1_CLK_IN_HZ		50000000
+
+/* Core/Cluster/Thread counts for diphda */
+#define DIPHDA_CLUSTER_COUNT			U(1)
+#define DIPHDA_MAX_CPUS_PER_CLUSTER		U(4)
+#define DIPHDA_MAX_PE_PER_CPU			U(1)
+#define DIPHDA_PRIMARY_CPU			U(0)
+
+#define PLAT_ARM_CLUSTER_COUNT		DIPHDA_CLUSTER_COUNT
+
+#define PLATFORM_CORE_COUNT			(PLAT_ARM_CLUSTER_COUNT *      \
+						DIPHDA_MAX_CPUS_PER_CLUSTER *  \
+						DIPHDA_MAX_PE_PER_CPU)
+
+/* UART related constants */
+#define PLAT_ARM_BOOT_UART_BASE		0x1a510000
+#define PLAT_ARM_BOOT_UART_CLK_IN_HZ		V2M_IOFPGA_UART0_CLK_IN_HZ
+#define PLAT_ARM_RUN_UART_BASE		0x1a520000
+#define PLAT_ARM_RUN_UART_CLK_IN_HZ		V2M_IOFPGA_UART1_CLK_IN_HZ
+#define ARM_CONSOLE_BAUDRATE			115200
+#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
+
+/* Memory related constants */
+
+/* SRAM (CVM) memory layout
+ *
+ * <ARM_TRUSTED_SRAM_BASE>
+ *
+ *         partition size: sizeof(meminfo_t) = 16 bytes
+ *
+ *         content: memory info area used by the next BL
+ *
+ * <ARM_FW_CONFIG_BASE>
+ *
+ *         partition size: 4080 bytes
+ *
+ * <ARM_BL2_MEM_DESC_BASE>
+ *
+ *         partition size: 4 KB
+ *
+ *         content:
+ *
+ *             Area where BL2 copies the images descriptors
+ *
+ * <ARM_BL_RAM_BASE> = <BL32_BASE>
+ *
+ *         partition size: 688 KB
+ *
+ *         content:
+ *
+ *             BL32 (optee-os)
+ *
+ * <DIPHDA_TOS_FW_CONFIG_BASE> = 0x20ae000
+ *
+ *         partition size: 8 KB
+ *
+ *         content:
+ *
+ *             BL32 config (TOS_FW_CONFIG)
+ *
+ * <BL31_BASE>
+ *
+ *         partition size: 140 KB
+ *
+ *         content:
+ *
+ *             BL31
+ *
+ * <BL2_SIGNATURE_BASE>
+ *
+ *     partition size: 4 KB
+ *
+ *     content:
+ *
+ *         MCUBOOT data needed to verify TF-A BL2
+ *
+ * <BL2_BASE>
+ *
+ *     partition size: 176 KB
+ *
+ *         content:
+ *
+ *             BL2
+ *
+ * <ARM_NS_SHARED_RAM_BASE> = <ARM_TRUSTED_SRAM_BASE> + 1 MB
+ *
+ *         partition size: 3 MB
+ *
+ *         content:
+ *
+ *             BL33 (u-boot)
+ */
+
+/* DDR memory */
+#define ARM_DRAM1_BASE			UL(0x80000000)
+#define ARM_DRAM1_SIZE			UL(0x80000000)
+#define ARM_DRAM1_END				(ARM_DRAM1_BASE +	\
+						ARM_DRAM1_SIZE - 1)
+
+/* DRAM1 and DRAM2 are the same for diphda */
+#define ARM_DRAM2_BASE			ARM_DRAM1_BASE
+#define ARM_DRAM2_SIZE			ARM_DRAM1_SIZE
+#define ARM_DRAM2_END				ARM_DRAM1_END
+
+#define ARM_NS_DRAM1_BASE			ARM_DRAM1_BASE
+#define ARM_NS_DRAM1_SIZE			ARM_DRAM1_SIZE
+#define ARM_NS_DRAM1_END			(ARM_NS_DRAM1_BASE +	\
+						ARM_NS_DRAM1_SIZE - 1)
+
+/* The first 8 KB of Trusted SRAM are used as shared memory */
+#define ARM_TRUSTED_SRAM_BASE			UL(0x02000000)
+#define ARM_SHARED_RAM_SIZE			UL(0x00002000)  /* 8 KB */
+#define ARM_SHARED_RAM_BASE			ARM_TRUSTED_SRAM_BASE
+
+/* The remaining Trusted SRAM is used to load the BL images */
+
+#define PLAT_ARM_TRUSTED_SRAM_SIZE		UL(0x00100000)  /* 1 MB */
+
+#define PLAT_ARM_MAX_BL2_SIZE			UL(0x0002d000)  /* 180 KB */
+
+#define PLAT_ARM_MAX_BL31_SIZE		UL(0x00023000)  /* 140 KB */
+
+#define ARM_BL_RAM_BASE			(ARM_SHARED_RAM_BASE +	\
+						ARM_SHARED_RAM_SIZE)
+#define ARM_BL_RAM_SIZE			(PLAT_ARM_TRUSTED_SRAM_SIZE -	\
+						ARM_SHARED_RAM_SIZE)
+
+#define BL2_SIGNATURE_SIZE			UL(0x00001000)  /* 4 KB */
+#define BL2_SIGNATURE_BASE			(BL2_LIMIT - \
+						PLAT_ARM_MAX_BL2_SIZE)
+#define BL2_BASE				(BL2_LIMIT - \
+						PLAT_ARM_MAX_BL2_SIZE + \
+						BL2_SIGNATURE_SIZE)
+#define BL2_LIMIT				(ARM_BL_RAM_BASE + \
+						ARM_BL_RAM_SIZE)
+
+#define BL31_BASE				(BL2_SIGNATURE_BASE - \
+						PLAT_ARM_MAX_BL31_SIZE)
+#define BL31_LIMIT				BL2_SIGNATURE_BASE
+
+#define DIPHDA_TOS_FW_CONFIG_BASE		(BL31_BASE - \
+						DIPHDA_TOS_FW_CONFIG_SIZE)
+#define DIPHDA_TOS_FW_CONFIG_SIZE		UL(0x00002000)  /* 8 KB */
+#define DIPHDA_TOS_FW_CONFIG_LIMIT		BL31_BASE
+
+#define BL32_BASE				ARM_BL_RAM_BASE
+#define PLAT_ARM_MAX_BL32_SIZE		(DIPHDA_TOS_FW_CONFIG_BASE - \
+						BL32_BASE)     /* 688 KB */
+#define BL32_LIMIT				(BL32_BASE + \
+						PLAT_ARM_MAX_BL32_SIZE)
+
+/* SPD_spmd settings */
+
+#define PLAT_ARM_SPMC_BASE			BL32_BASE
+#define PLAT_ARM_SPMC_SIZE			PLAT_ARM_MAX_BL32_SIZE
+
+/* NS memory */
+
+/* The last 3 MB of the SRAM is allocated to the non secure area */
+#define ARM_NS_SHARED_RAM_BASE		(ARM_TRUSTED_SRAM_BASE + \
+						PLAT_ARM_TRUSTED_SRAM_SIZE)
+#define ARM_NS_SHARED_RAM_SIZE		UL(0x00300000)  /* 3 MB */
+
+/* end of the definition of SRAM memory layout */
+
+/* NOR Flash */
+
+#define PLAT_ARM_FIP_BASE			UL(0x08131000)
+#define PLAT_ARM_FIP_MAX_SIZE			UL(0x1ff000)  /* 1.996 MB */
+
+#define PLAT_ARM_NVM_BASE			V2M_FLASH0_BASE
+#define PLAT_ARM_NVM_SIZE			UL(0x02000000)  /* 32 MB */
+
+#define PLAT_ARM_FLASH_IMAGE_BASE		PLAT_ARM_FIP_BASE
+#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE		PLAT_ARM_FIP_MAX_SIZE
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_GRANULE		(U(1) << ARM_CACHE_WRITEBACK_SHIFT)
+#define ARM_CACHE_WRITEBACK_SHIFT		6
+
+/*
+ * Define FW_CONFIG area base and limit. Leave enough space for BL2 meminfo.
+ * FW_CONFIG is intended to host the device tree. Currently, This area is not
+ * used because diphda platform doesn't use a device tree at TF-A level.
+ */
+#define ARM_FW_CONFIG_BASE			(ARM_SHARED_RAM_BASE \
+						+ sizeof(meminfo_t))
+#define ARM_FW_CONFIG_LIMIT			(ARM_SHARED_RAM_BASE \
+						+ (ARM_SHARED_RAM_SIZE >> 1))
+
+/*
+ * Boot parameters passed from BL2 to BL31/BL32 are stored here
+ */
+#define ARM_BL2_MEM_DESC_BASE			ARM_FW_CONFIG_LIMIT
+#define ARM_BL2_MEM_DESC_LIMIT		ARM_BL_RAM_BASE
+
+/*
+ * The max number of regions like RO(code), coherent and data required by
+ * different BL stages which need to be mapped in the MMU.
+ */
+#define ARM_BL_REGIONS			3
+#define PLAT_ARM_MMAP_ENTRIES			8
+#define MAX_XLAT_TABLES			5
+#define MAX_MMAP_REGIONS			(PLAT_ARM_MMAP_ENTRIES + \
+						ARM_BL_REGIONS)
+#define MAX_IO_DEVICES			2
+#define MAX_IO_HANDLES			3
+#define MAX_IO_BLOCK_DEVICES			1
+
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE			0x1C010000
+#define PLAT_ARM_GICC_BASE			0x1C02F000
+
+/* MHUv2 Secure Channel receiver and sender */
+#define PLAT_SDK700_MHU0_SEND			0x1B800000
+#define PLAT_SDK700_MHU0_RECV			0x1B810000
+
+/* Timer/watchdog related constants */
+#define ARM_SYS_CNTCTL_BASE			UL(0x1a200000)
+#define ARM_SYS_CNTREAD_BASE			UL(0x1a210000)
+#define ARM_SYS_TIMCTL_BASE			UL(0x1a220000)
+
+#define SYS_COUNTER_FREQ_IN_TICKS	UL(50000000) /* 50MHz */
+
+#define DIPHDA_IRQ_TZ_WDOG			32
+#define DIPHDA_IRQ_SEC_SYS_TIMER		34
+
+#define PLAT_MAX_PWR_LVL			2
+/*
+ * Macros mapping the MPIDR Affinity levels to ARM Platform Power levels. The
+ * power levels have a 1:1 mapping with the MPIDR affinity levels.
+ */
+#define ARM_PWR_LVL0				MPIDR_AFFLVL0
+#define ARM_PWR_LVL1				MPIDR_AFFLVL1
+#define ARM_PWR_LVL2				MPIDR_AFFLVL2
+
+/*
+ *  Macros for local power states in ARM platforms encoded by State-ID field
+ *  within the power-state parameter.
+ */
+/* Local power state for power domains in Run state. */
+#define ARM_LOCAL_STATE_RUN			U(0)
+/* Local power state for retention. Valid only for CPU power domains */
+#define ARM_LOCAL_STATE_RET			U(1)
+/* Local power state for OFF/power-down. Valid for CPU and cluster
+ * power domains
+ */
+#define ARM_LOCAL_STATE_OFF			U(2)
+
+#define PLAT_ARM_TRUSTED_MAILBOX_BASE		ARM_TRUSTED_SRAM_BASE
+#define PLAT_ARM_NSTIMER_FRAME_ID		U(1)
+
+#define PLAT_ARM_NS_IMAGE_BASE		(ARM_NS_SHARED_RAM_BASE)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE		(1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE		(1ULL << 32)
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * ID will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE			1
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE			2
+
+#define PLATFORM_STACK_SIZE			UL(0x440)
+
+#define DIPHDA_EXTERNAL_FLASH			MAP_REGION_FLAT(	\
+						PLAT_ARM_NVM_BASE,	\
+						PLAT_ARM_NVM_SIZE,	\
+						MT_DEVICE | MT_RO | MT_SECURE)
+
+#define ARM_MAP_SHARED_RAM			MAP_REGION_FLAT(	\
+						ARM_SHARED_RAM_BASE,	\
+						ARM_SHARED_RAM_SIZE,	\
+						MT_MEMORY | MT_RW | MT_SECURE)
+
+#define ARM_MAP_NS_SHARED_RAM			MAP_REGION_FLAT(	\
+						ARM_NS_SHARED_RAM_BASE, \
+						ARM_NS_SHARED_RAM_SIZE, \
+						MT_MEMORY | MT_RW | MT_NS)
+
+#define ARM_MAP_NS_DRAM1			MAP_REGION_FLAT(	\
+						ARM_NS_DRAM1_BASE,	\
+						ARM_NS_DRAM1_SIZE,	\
+						MT_MEMORY | MT_RW | MT_NS)
+
+#define ARM_MAP_BL_RO				MAP_REGION_FLAT(	\
+						BL_CODE_BASE,		\
+						BL_CODE_END		\
+							- BL_CODE_BASE, \
+						MT_CODE | MT_SECURE),	\
+						MAP_REGION_FLAT(	\
+						BL_RO_DATA_BASE,	\
+						BL_RO_DATA_END	\
+						- BL_RO_DATA_BASE,	\
+						MT_RO_DATA | MT_SECURE)
+#if USE_COHERENT_MEM
+#define ARM_MAP_BL_COHERENT_RAM		MAP_REGION_FLAT(	\
+						BL_COHERENT_RAM_BASE,	\
+						BL_COHERENT_RAM_END	\
+						- BL_COHERENT_RAM_BASE, \
+						MT_DEVICE | MT_RW | MT_SECURE)
+#endif
+
+/*
+ * Map the region for the optional device tree configuration with read and
+ * write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION		MAP_REGION_FLAT(	\
+						ARM_FW_CONFIG_BASE,	\
+						(ARM_FW_CONFIG_LIMIT-   \
+						ARM_FW_CONFIG_BASE),   \
+						MT_MEMORY | MT_RW | MT_SECURE)
+
+#define DIPHDA_DEVICE_BASE			(0x1A000000)
+#define DIPHDA_DEVICE_SIZE			(0x26000000)
+#define DIPHDA_MAP_DEVICE			MAP_REGION_FLAT(	\
+						DIPHDA_DEVICE_BASE,	\
+						DIPHDA_DEVICE_SIZE,	\
+						MT_DEVICE | MT_RW | MT_SECURE)
+
+#define ARM_IRQ_SEC_PHY_TIMER			29
+
+#define ARM_IRQ_SEC_SGI_0			8
+#define ARM_IRQ_SEC_SGI_1			9
+#define ARM_IRQ_SEC_SGI_2			10
+#define ARM_IRQ_SEC_SGI_3			11
+#define ARM_IRQ_SEC_SGI_4			12
+#define ARM_IRQ_SEC_SGI_5			13
+#define ARM_IRQ_SEC_SGI_6			14
+#define ARM_IRQ_SEC_SGI_7			15
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define ARM_G1S_IRQ_PROPS(grp) \
+	INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \
+		(grp), GIC_INTR_CFG_LEVEL), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY,	\
+		(grp), GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY,	\
+		(grp), GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY,	\
+		(grp), GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY,	\
+		(grp), GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY,	\
+		(grp), GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY,	\
+		(grp), GIC_INTR_CFG_EDGE)
+
+#define ARM_G0_IRQ_PROPS(grp) \
+	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \
+		GIC_INTR_CFG_EDGE)
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_ARM_G1S_IRQ_PROPS(grp)	\
+	ARM_G1S_IRQ_PROPS(grp), \
+	INTR_PROP_DESC(DIPHDA_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, \
+		(grp), GIC_INTR_CFG_LEVEL), \
+	INTR_PROP_DESC(DIPHDA_IRQ_SEC_SYS_TIMER, \
+		GIC_HIGHEST_SEC_PRIORITY, (grp), GIC_INTR_CFG_LEVEL)
+
+#define PLAT_ARM_G0_IRQ_PROPS(grp)	ARM_G0_IRQ_PROPS(grp)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/diphda/include/plat_macros.S b/plat/arm/board/diphda/include/plat_macros.S
new file mode 100644
index 0000000..4de8f95
--- /dev/null
+++ b/plat/arm/board/diphda/include/plat_macros.S
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2021, 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.
+ * ---------------------------------------------
+ */
+	.macro plat_crash_print_regs
+	css_print_gic_regs
+	.endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/arm/board/diphda/platform.mk b/plat/arm/board/diphda/platform.mk
new file mode 100644
index 0000000..8b89cee
--- /dev/null
+++ b/plat/arm/board/diphda/platform.mk
@@ -0,0 +1,83 @@
+#
+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Making sure the diphda platform type is specified
+ifeq ($(filter ${TARGET_PLATFORM}, fpga fvp),)
+	$(error TARGET_PLATFORM must be fpga or fvp)
+endif
+
+DIPHDA_CPU_LIBS	+=lib/cpus/aarch64/cortex_a35.S
+
+PLAT_INCLUDES		:=	-Iplat/arm/board/diphda/common/include	\
+				-Iplat/arm/board/diphda/include		\
+				-Iinclude/plat/arm/common			\
+				-Iinclude/plat/arm/css/common/aarch64
+
+
+DIPHDA_FW_NVCTR_VAL	:=	255
+TFW_NVCTR_VAL		:=	${DIPHDA_FW_NVCTR_VAL}
+NTFW_NVCTR_VAL		:=	${DIPHDA_FW_NVCTR_VAL}
+
+override NEED_BL1	:=	no
+
+override NEED_BL2	:=	yes
+FIP_BL2_ARGS := tb-fw
+
+override NEED_BL2U	:=	no
+override NEED_BL31	:=	yes
+NEED_BL32		:=	yes
+override NEED_BL33	:=	yes
+
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+DIPHDA_GIC_SOURCES	:=	${GICV2_SOURCES}			\
+				plat/common/plat_gicv2.c		\
+				plat/arm/common/arm_gicv2.c
+
+
+BL2_SOURCES		+=	plat/arm/board/diphda/common/diphda_security.c		\
+				plat/arm/board/diphda/common/diphda_err.c		\
+				plat/arm/board/diphda/common/diphda_trusted_boot.c	\
+				lib/utils/mem_region.c					\
+				plat/arm/board/diphda/common/diphda_helpers.S		\
+				plat/arm/board/diphda/common/diphda_plat.c		\
+				plat/arm/board/diphda/common/diphda_bl2_mem_params_desc.c \
+				${DIPHDA_CPU_LIBS}					\
+
+
+BL31_SOURCES	+=	drivers/cfi/v2m/v2m_flash.c				\
+			lib/utils/mem_region.c					\
+			plat/arm/board/diphda/common/diphda_helpers.S		\
+			plat/arm/board/diphda/common/diphda_topology.c		\
+			plat/arm/board/diphda/common/diphda_security.c		\
+			plat/arm/board/diphda/common/diphda_plat.c		\
+			plat/arm/board/diphda/common/diphda_pm.c		\
+			${DIPHDA_CPU_LIBS}					\
+			${DIPHDA_GIC_SOURCES}
+
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+	ifneq (${ENABLE_STACK_PROTECTOR},none)
+		DIPHDA_SECURITY_SOURCES := plat/arm/board/diphda/common/diphda_stack_protector.c
+		BL2_SOURCES += ${DIPHDA_SECURITY_SOURCES}
+		BL31_SOURCES += ${DIPHDA_SECURITY_SOURCES}
+	endif
+endif
+
+FDT_SOURCES		+=	plat/arm/board/diphda/common/fdts/diphda_spmc_manifest.dts
+DIPHDA_TOS_FW_CONFIG	:=	${BUILD_PLAT}/fdts/diphda_spmc_manifest.dtb
+
+# Add the SPMC manifest to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${DIPHDA_TOS_FW_CONFIG},--tos-fw-config,${DIPHDA_TOS_FW_CONFIG}))
+
+# Adding TARGET_PLATFORM as a GCC define (-D option)
+$(eval $(call add_define,TARGET_PLATFORM_$(call uppercase,${TARGET_PLATFORM})))
+
+# Adding DIPHDA_FW_NVCTR_VAL as a GCC define (-D option)
+$(eval $(call add_define,DIPHDA_FW_NVCTR_VAL))
+
+include plat/arm/common/arm_common.mk
+include plat/arm/board/common/board_common.mk
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
index 67e5504..21a6073 100644
--- a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
@@ -20,7 +20,7 @@
 	attribute {
 		spmc_id = <0x8000>;
 		maj_ver = <0x1>;
-		min_ver = <0x0>;
+		min_ver = <0x1>;
 		exec_state = <0x0>;
 		load_address = <0x0 0x6000000>;
 		entrypoint = <0x0 0x6000000>;
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts
index 088179b..041dade 100644
--- a/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts
@@ -20,7 +20,7 @@
 	attribute {
 		spmc_id = <0x8000>;
 		maj_ver = <0x1>;
-		min_ver = <0x0>;
+		min_ver = <0x1>;
 		exec_state = <0x0>;
 		load_address = <0x0 0x6000000>;
 		entrypoint = <0x0 0x6000000>;
diff --git a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
index 62ab27c..08d3c32 100644
--- a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
@@ -4,6 +4,8 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <lib/libc/cdefs.h>
+
 /dts-v1/;
 
 / {
@@ -74,6 +76,10 @@
 
 	secure-partitions {
 		compatible = "arm,sp";
+
+#ifdef ARM_BL2_SP_LIST_DTS
+	#include __XSTRING(ARM_BL2_SP_LIST_DTS)
+#else
 #ifdef OPTEE_SP_FW_CONFIG
 		op-tee {
 			uuid = "486178e0-e7f8-11e3-bc5e-0002a5d5c51b";
@@ -104,6 +110,7 @@
 			owner = "Plat";
 		};
 #endif
+#endif /* ARM_BL2_SP_LIST_DTS */
 	};
 
 #if COT_DESC_IN_DTB
diff --git a/plat/arm/board/fvp/fdts/optee_sp_manifest.dts b/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
index 928d0d3..551efe6 100644
--- a/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
+++ b/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -16,7 +16,7 @@
 	/* Properties */
 	description = "op-tee";
 	ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */
-	uuid = <0x486178e0 0xe7f811e3 0xbc5e0002 0xa5d5c51b>;
+	uuid = <0xe0786148 0xe311f8e7 0x02005ebc 0x1bc5d5a5>;
 	id = <1>;
 	execution-ctx-count = <8>;
 	exception-level = <2>; /* S-EL1 */
@@ -25,8 +25,9 @@
 	entrypoint-offset = <0x1000>;
 	xlat-granule = <0>; /* 4KiB */
 	boot-order = <0>;
-	messaging-method = <0>; /* Direct messaging only */
-	run-time-model = <1>; /* Run to completion */
+	messaging-method = <0x3>; /* Direct request/response supported. */
+	managed-exit;
+	run-time-model = <1>; /* SP pre-emptible. */
 
 	/* Boot protocol */
 	gp-register-num = <0x0>;
diff --git a/plat/arm/board/fvp/fvp_bl1_setup.c b/plat/arm/board/fvp/fvp_bl1_setup.c
index e713bbc..06ee037 100644
--- a/plat/arm/board/fvp/fvp_bl1_setup.c
+++ b/plat/arm/board/fvp/fvp_bl1_setup.c
@@ -1,15 +1,17 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <assert.h>
+#include <errno.h>
 
 #include <bl1/bl1.h>
 #include <common/tbbr/tbbr_img_def.h>
 #include <drivers/arm/smmu_v3.h>
 #include <drivers/arm/sp805.h>
+#include <lib/mmio.h>
 #include <plat/arm/common/arm_config.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/arm/common/arm_def.h>
@@ -61,6 +63,12 @@
 
 __dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved)
 {
+	uint32_t nv_flags = mmio_read_32(V2M_SYS_NVFLAGS_ADDR);
+
+	/* Clear the NV flags register. */
+	mmio_write_32((V2M_SYSREGS_BASE + V2M_SYS_NVFLAGSCLR),
+		      nv_flags);
+
 	/* Setup the watchdog to reset the system as soon as possible */
 	sp805_refresh(ARM_SP805_TWDG_BASE, 1U);
 
@@ -124,3 +132,15 @@
 	return 0;
 }
 #endif /* MEASURED_BOOT */
+
+/*******************************************************************************
+ * The following function checks if Firmware update is needed by checking error
+ * reported in NV flag.
+ ******************************************************************************/
+bool plat_arm_bl1_fwu_needed(void)
+{
+	int32_t nv_flags = (int32_t)mmio_read_32(V2M_SYS_NVFLAGS_ADDR);
+
+	/* if image load/authentication failed */
+	return ((nv_flags == -EAUTH) || (nv_flags == -ENOENT));
+}
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index fe0903b..e7a28ac 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -72,14 +72,11 @@
  * Table of memory regions for various BL stages to map using the MMU.
  * This doesn't include Trusted SRAM as setup_page_tables() already takes care
  * of mapping it.
- *
- * The flash needs to be mapped as writable in order to erase the FIP's Table of
- * Contents in case of unrecoverable error (see plat_error_handler()).
  */
 #ifdef IMAGE_BL1
 const mmap_region_t plat_arm_mmap[] = {
 	ARM_MAP_SHARED_RAM,
-	V2M_MAP_FLASH0_RW,
+	V2M_MAP_FLASH0_RO,
 	V2M_MAP_IOFPGA,
 	MAP_DEVICE0,
 #if FVP_INTERCONNECT_DRIVER == FVP_CCN
@@ -110,6 +107,10 @@
 #if defined(SPD_spmd)
 	ARM_MAP_TRUSTED_DRAM,
 #endif
+#if ENABLE_RME
+	ARM_MAP_RMM_DRAM,
+	ARM_MAP_GPT_L1_DRAM,
+#endif /* ENABLE_RME */
 #ifdef SPD_tspd
 	ARM_MAP_TSP_SEC_MEM,
 #endif
@@ -162,6 +163,9 @@
 #endif
 	/* Required by fconf APIs to read HW_CONFIG dtb loaded into DRAM */
 	ARM_DTB_DRAM_NS,
+#if ENABLE_RME
+	ARM_MAP_GPT_L1_DRAM,
+#endif
 	{0}
 };
 
@@ -194,6 +198,15 @@
 };
 #endif
 
+#ifdef IMAGE_RMM
+const mmap_region_t plat_arm_mmap[] = {
+	V2M_MAP_IOFPGA,
+	MAP_DEVICE0,
+	MAP_DEVICE1,
+	{0}
+};
+#endif
+
 ARM_CASSERT_MMAP
 
 #if FVP_INTERCONNECT_DRIVER != FVP_CCN
diff --git a/plat/arm/board/fvp/fvp_err.c b/plat/arm/board/fvp/fvp_err.c
index 2928b3a..1f9f0dd 100644
--- a/plat/arm/board/fvp/fvp_err.c
+++ b/plat/arm/board/fvp/fvp_err.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,6 +9,7 @@
 #include <common/debug.h>
 #include <drivers/arm/sp805.h>
 #include <drivers/cfi/v2m_flash.h>
+#include <lib/mmio.h>
 #include <plat/arm/common/plat_arm.h>
 #include <platform_def.h>
 
@@ -17,25 +18,8 @@
  */
 __dead2 void plat_arm_error_handler(int err)
 {
-	int ret;
-
-	switch (err) {
-	case -ENOENT:
-	case -EAUTH:
-		/* Image load or authentication error. Erase the ToC */
-		INFO("Erasing FIP ToC from flash...\n");
-		(void)nor_unlock(PLAT_ARM_FLASH_IMAGE_BASE);
-		ret = nor_word_program(PLAT_ARM_FLASH_IMAGE_BASE, 0);
-		if (ret != 0) {
-			ERROR("Cannot erase ToC\n");
-		} else {
-			INFO("Done\n");
-		}
-		break;
-	default:
-		/* Unexpected error */
-		break;
-	}
+	/* Propagate the err code in the NV-flags register */
+	mmio_write_32(V2M_SYS_NVFLAGS_ADDR, (uint32_t)err);
 
 	console_flush();
 
diff --git a/plat/arm/board/fvp/fvp_io_storage.c b/plat/arm/board/fvp/fvp_io_storage.c
index 109d321..4eef51c 100644
--- a/plat/arm/board/fvp/fvp_io_storage.c
+++ b/plat/arm/board/fvp/fvp_io_storage.c
@@ -20,6 +20,10 @@
 #define BL32_IMAGE_NAME			"bl32.bin"
 #define BL33_IMAGE_NAME			"bl33.bin"
 #define TB_FW_CONFIG_NAME		"fvp_tb_fw_config.dtb"
+#define SOC_FW_CONFIG_NAME		"fvp_soc_fw_config.dtb"
+#define TOS_FW_CONFIG_NAME		"fvp_tsp_fw_config.dtb"
+#define NT_FW_CONFIG_NAME		"fvp_nt_fw_config.dtb"
+#define FW_CONFIG_NAME			"fvp_fw_config.dtb"
 #define HW_CONFIG_NAME			"hw_config.dtb"
 
 #if TRUSTED_BOARD_BOOT
@@ -58,6 +62,22 @@
 		.path = TB_FW_CONFIG_NAME,
 		.mode = FOPEN_MODE_RB
 	},
+	[SOC_FW_CONFIG_ID] = {
+		.path = SOC_FW_CONFIG_NAME,
+		.mode = FOPEN_MODE_RB
+	},
+	[TOS_FW_CONFIG_ID] = {
+		.path = TOS_FW_CONFIG_NAME,
+		.mode = FOPEN_MODE_RB
+	},
+	[NT_FW_CONFIG_ID] = {
+		.path = NT_FW_CONFIG_NAME,
+		.mode = FOPEN_MODE_RB
+	},
+	[FW_CONFIG_ID] = {
+		.path = FW_CONFIG_NAME,
+		.mode = FOPEN_MODE_RB
+	},
 	[HW_CONFIG_ID] = {
 		.path = HW_CONFIG_NAME,
 		.mode = FOPEN_MODE_RB
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index 333d892..6b9d618 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -138,21 +138,37 @@
 	fvp_pwrc_clr_wen(mpidr);
 }
 
-
 /*******************************************************************************
  * FVP handler called when a CPU is about to enter standby.
  ******************************************************************************/
 static void fvp_cpu_standby(plat_local_state_t cpu_state)
 {
+	u_register_t scr = read_scr_el3();
 
 	assert(cpu_state == ARM_LOCAL_STATE_RET);
 
 	/*
+	 * Enable the Non-secure interrupt to wake the CPU.
+	 * In GICv3 affinity routing mode, the Non-secure Group 1 interrupts
+	 * use Physical FIQ at EL3 whereas in GICv2, Physical IRQ is used.
+	 * Enabling both the bits works for both GICv2 mode and GICv3 affinity
+	 * routing mode.
+	 */
+	write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
+	isb();
+
+	/*
-	 * Enter standby state
-	 * dsb is good practice before using wfi to enter low power states
+	 * Enter standby state.
+	 * dsb is good practice before using wfi to enter low power states.
 	 */
 	dsb();
 	wfi();
+
+	/*
+	 * Restore SCR_EL3 to the original value, synchronisation of SCR_EL3
+	 * is done by eret in el3_exit() to save some execution cycles.
+	 */
+	write_scr_el3(scr);
 }
 
 /*******************************************************************************
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 8b25a54..96574e5 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -43,6 +43,11 @@
 #define PLAT_ARM_TRUSTED_DRAM_BASE	UL(0x06000000)
 #define PLAT_ARM_TRUSTED_DRAM_SIZE	UL(0x02000000)	/* 32 MB */
 
+#if ENABLE_RME
+#define PLAT_ARM_RMM_BASE		(RMM_BASE)
+#define PLAT_ARM_RMM_SIZE		(RMM_LIMIT - RMM_BASE)
+#endif
+
 /*
  * Max size of SPMC is 2MB for fvp. With SPMD enabled this value corresponds to
  * max size of BL32 image.
@@ -61,12 +66,13 @@
 #define PLAT_ARM_DRAM2_BASE		ULL(0x880000000)
 #define PLAT_ARM_DRAM2_SIZE		UL(0x80000000)
 
-#define PLAT_HW_CONFIG_DTB_BASE		ULL(0x82000000)
-#define PLAT_HW_CONFIG_DTB_SIZE		ULL(0x8000)
+/* Range of kernel DTB load address */
+#define FVP_DTB_DRAM_MAP_START		ULL(0x82000000)
+#define FVP_DTB_DRAM_MAP_SIZE		ULL(0x02000000)	/* 32 MB */
 
 #define ARM_DTB_DRAM_NS			MAP_REGION_FLAT(		\
-					PLAT_HW_CONFIG_DTB_BASE,	\
-					PLAT_HW_CONFIG_DTB_SIZE,	\
+					FVP_DTB_DRAM_MAP_START,		\
+					FVP_DTB_DRAM_MAP_SIZE,		\
 					MT_MEMORY | MT_RO | MT_NS)
 /*
  * Load address of BL33 for this platform port
@@ -80,15 +86,27 @@
 #if defined(IMAGE_BL31)
 # if SPM_MM
 #  define PLAT_ARM_MMAP_ENTRIES		10
-#  define MAX_XLAT_TABLES		9
+#  if ENABLE_RME
+#   define MAX_XLAT_TABLES		10
+#  else
+#   define MAX_XLAT_TABLES		9
+# endif
 #  define PLAT_SP_IMAGE_MMAP_REGIONS	30
 #  define PLAT_SP_IMAGE_MAX_XLAT_TABLES	10
 # else
 #  define PLAT_ARM_MMAP_ENTRIES		9
 #  if USE_DEBUGFS
-#   define MAX_XLAT_TABLES		8
+#   if ENABLE_RME
+#    define MAX_XLAT_TABLES		9
+#   else
+#    define MAX_XLAT_TABLES		8
+#   endif
 #  else
-#   define MAX_XLAT_TABLES		7
+#   if ENABLE_RME
+#    define MAX_XLAT_TABLES		8
+#   else
+#    define MAX_XLAT_TABLES		7
+#   endif
 #  endif
 # endif
 #elif defined(IMAGE_BL32)
@@ -137,16 +155,17 @@
 #endif
 
 #if RESET_TO_BL31
-/* Size of Trusted SRAM - the first 4KB of shared memory */
+/* Size of Trusted SRAM - the first 4KB of shared memory - GPT L0 Tables */
 #define PLAT_ARM_MAX_BL31_SIZE		(PLAT_ARM_TRUSTED_SRAM_SIZE - \
-					 ARM_SHARED_RAM_SIZE)
+					 ARM_SHARED_RAM_SIZE - \
+					 ARM_L0_GPT_SIZE)
 #else
 /*
  * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is
  * calculated using the current BL31 PROGBITS debug size plus the sizes of
  * BL2 and BL1-RW
  */
-#define PLAT_ARM_MAX_BL31_SIZE		UL(0x3D000)
+#define PLAT_ARM_MAX_BL31_SIZE		(UL(0x3D000) - ARM_L0_GPT_SIZE)
 #endif /* RESET_TO_BL31 */
 
 #ifndef __aarch64__
@@ -177,7 +196,7 @@
 # if TRUSTED_BOARD_BOOT
 #  define PLATFORM_STACK_SIZE		UL(0x1000)
 # else
-#  define PLATFORM_STACK_SIZE		UL(0x440)
+#  define PLATFORM_STACK_SIZE		UL(0x600)
 # endif
 #elif defined(IMAGE_BL2U)
 # define PLATFORM_STACK_SIZE		UL(0x400)
@@ -185,6 +204,8 @@
 #  define PLATFORM_STACK_SIZE		UL(0x800)
 #elif defined(IMAGE_BL32)
 # define PLATFORM_STACK_SIZE		UL(0x440)
+#elif defined(IMAGE_RMM)
+# define PLATFORM_STACK_SIZE		UL(0x440)
 #endif
 
 #define MAX_IO_DEVICES			3
@@ -222,6 +243,9 @@
 #define PLAT_ARM_TSP_UART_BASE		V2M_IOFPGA_UART2_BASE
 #define PLAT_ARM_TSP_UART_CLK_IN_HZ	V2M_IOFPGA_UART2_CLK_IN_HZ
 
+#define PLAT_ARM_TRP_UART_BASE		V2M_IOFPGA_UART3_BASE
+#define PLAT_ARM_TRP_UART_CLK_IN_HZ	V2M_IOFPGA_UART3_CLK_IN_HZ
+
 #define PLAT_FVP_SMMUV3_BASE		UL(0x2b400000)
 
 /* CCI related constants */
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 10258ad..b375146 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -135,9 +135,11 @@
 					lib/cpus/aarch64/cortex_a710.S	\
 					lib/cpus/aarch64/cortex_makalu.S	\
 					lib/cpus/aarch64/cortex_makalu_elp_arm.S \
+					lib/cpus/aarch64/cortex_demeter.S	\
 					lib/cpus/aarch64/cortex_a65.S		\
 					lib/cpus/aarch64/cortex_a65ae.S		\
-					lib/cpus/aarch64/cortex_a78c.S
+					lib/cpus/aarch64/cortex_a78c.S		\
+					lib/cpus/aarch64/cortex_hayes.S
 	endif
 	# AArch64/AArch32 cores
 	FVP_CPU_LIBS	+=	lib/cpus/aarch64/cortex_a55.S		\
@@ -184,6 +186,10 @@
 BL2_SOURCES		+=	plat/arm/common/fconf/fconf_nv_cntr_getter.c
 endif
 
+ifeq (${ENABLE_RME},1)
+BL2_SOURCES		+=	plat/arm/board/fvp/aarch64/fvp_helpers.S
+endif
+
 ifeq (${BL2_AT_EL3},1)
 BL2_SOURCES		+=	plat/arm/board/fvp/${ARCH}/fvp_helpers.S	\
 				plat/arm/board/fvp/fvp_bl2_el3_setup.c		\
@@ -377,3 +383,12 @@
 # dynamically if TRUSTED_BOARD_BOOT is set.
 DYN_DISABLE_AUTH	:=	1
 endif
+
+# enable trace buffer control registers access to NS by default
+ENABLE_TRBE_FOR_NS		:= 1
+
+# enable trace system registers access to NS by default
+ENABLE_SYS_REG_TRACE_FOR_NS	:= 1
+
+# enable trace filter control registers access to NS by default
+ENABLE_TRF_FOR_NS		:= 1
diff --git a/plat/arm/board/fvp/trp/trp-fvp.mk b/plat/arm/board/fvp/trp/trp-fvp.mk
new file mode 100644
index 0000000..a450541
--- /dev/null
+++ b/plat/arm/board/fvp/trp/trp-fvp.mk
@@ -0,0 +1,12 @@
+#
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# TRP source files specific to FVP platform
+
+RMM_SOURCES		+=	plat/arm/board/fvp/aarch64/fvp_helpers.S
+
+include plat/arm/common/trp/arm_trp.mk
+
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c b/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c
new file mode 100644
index 0000000..ae6af6c
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "../../../../bl1/bl1_private.h"
+#include <arch.h>
+
+#include <fvp_r_arch_helpers.h>
+
+/*******************************************************************************
+ * Function that does the first bit of architectural setup that affects
+ * execution in the non-secure address space.
+ ******************************************************************************/
+void bl1_arch_setup(void)
+{
+	/* v8-R64 does not include SCRs. */
+}
+
+/*******************************************************************************
+ * Set the Secure EL1 required architectural state
+ ******************************************************************************/
+void bl1_arch_next_el_setup(void)
+{
+	u_register_t next_sctlr;
+
+	/* Use the same endianness than the current BL */
+	next_sctlr = (read_sctlr_el2() & SCTLR_EE_BIT);
+
+	/* Set SCTLR Secure EL1 */
+	next_sctlr |= SCTLR_EL1_RES1;
+
+	write_sctlr_el1(next_sctlr);
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_context_mgmt.c b/plat/arm/board/fvp_r/fvp_r_bl1_context_mgmt.c
new file mode 100644
index 0000000..c6544b4
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_context_mgmt.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include "../../../../bl1/bl1_private.h"
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <context.h>
+#include <lib/el3_runtime/context_mgmt.h>
+
+#include <plat/common/platform.h>
+
+
+void cm_prepare_el2_exit(void);
+
+/* Following contains the cpu context pointers. */
+static void *bl1_cpu_context_ptr[2];
+
+void *cm_get_context(uint32_t security_state)
+{
+	assert(sec_state_is_valid(security_state));
+	return bl1_cpu_context_ptr[security_state];
+}
+
+void cm_set_context(void *context, uint32_t security_state)
+{
+	assert(sec_state_is_valid(security_state));
+	bl1_cpu_context_ptr[security_state] = context;
+}
+
+/*******************************************************************************
+ * This function prepares the context for Secure/Normal world images.
+ * Normal world images are transitioned to EL2(if supported) else EL1.
+ ******************************************************************************/
+void bl1_prepare_next_image(unsigned int image_id)
+{
+	/*
+	 * Following array will be used for context management.
+	 * There are 2 instances, for the Secure and Non-Secure contexts.
+	 */
+	static cpu_context_t bl1_cpu_context[2];
+
+	unsigned int security_state, mode = MODE_EL1;
+	image_desc_t *desc;
+	entry_point_info_t *next_bl_ep;
+
+#if CTX_INCLUDE_AARCH32_REGS
+	/*
+	 * Ensure that the build flag to save AArch32 system registers in CPU
+	 * context is not set for AArch64-only platforms.
+	 */
+	if (el_implemented(1) == EL_IMPL_A64ONLY) {
+		ERROR("EL1 supports AArch64-only. Please set build flag %s",
+				"CTX_INCLUDE_AARCH32_REGS = 0\n");
+		panic();
+	}
+#endif
+
+	/* Get the image descriptor. */
+	desc = bl1_plat_get_image_desc(image_id);
+	assert(desc != NULL);
+
+	/* Get the entry point info. */
+	next_bl_ep = &desc->ep_info;
+
+	/* Get the image security state. */
+	security_state = GET_SECURITY_STATE(next_bl_ep->h.attr);
+
+	/* Setup the Secure/Non-Secure context if not done already. */
+	if (cm_get_context(security_state) == NULL) {
+		cm_set_context(&bl1_cpu_context[security_state], security_state);
+	}
+	/* Prepare the SPSR for the next BL image. */
+	next_bl_ep->spsr = (uint32_t)SPSR_64((uint64_t) mode,
+		(uint64_t)MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+
+	/* Allow platform to make change */
+	bl1_plat_set_ep_info(image_id, next_bl_ep);
+
+	/* Prepare context for the next EL */
+	cm_prepare_el2_exit();
+
+	/* Indicate that image is in execution state. */
+	desc->state = IMAGE_STATE_EXECUTED;
+
+	print_entry_point_info(next_bl_ep);
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S b/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S
new file mode 100644
index 0000000..19a685c
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <el2_common_macros.S>
+#include <lib/xlat_mpu/xlat_mpu.h>
+
+	.globl	bl1_entrypoint
+	.globl	bl1_run_next_image
+
+
+	/* -----------------------------------------------------
+	 * bl1_entrypoint() is the entry point into the trusted
+	 * firmware code when a cpu is released from warm or
+	 * cold reset.
+	 * -----------------------------------------------------
+	 */
+
+func bl1_entrypoint
+	/* ---------------------------------------------------------------------
+	 * If the reset address is programmable then bl1_entrypoint() is
+	 * executed only on the cold boot path. Therefore, we can skip the warm
+	 * boot mailbox mechanism.
+	 * ---------------------------------------------------------------------
+	 */
+	el2_entrypoint_common					\
+		_init_sctlr=1					\
+		_warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS	\
+		_secondary_cold_boot=!COLD_BOOT_SINGLE_CPU	\
+		_init_memory=1					\
+		_init_c_runtime=1				\
+		_exception_vectors=bl1_exceptions		\
+		_pie_fixup_size=0
+
+	/* --------------------------------------------------------------------
+	 * Perform BL1 setup
+	 * --------------------------------------------------------------------
+	 */
+	bl	bl1_setup
+
+#if ENABLE_PAUTH
+	/* --------------------------------------------------------------------
+	 * Program APIAKey_EL1 and enable pointer authentication.
+	 * --------------------------------------------------------------------
+	 */
+	bl	pauth_init_enable_el2
+#endif /* ENABLE_PAUTH */
+
+	/* --------------------------------------------------------------------
+	 * Initialize platform and jump to our c-entry point
+	 * for this type of reset.
+	 * --------------------------------------------------------------------
+	 */
+	bl	bl1_main
+
+	/* ---------------------------------------------
+	 * Should never reach this point.
+	 * ---------------------------------------------
+	 */
+	no_ret	plat_panic_handler
+endfunc bl1_entrypoint
+
+func bl1_run_next_image
+	mov	x20,x0
+
+	/* ---------------------------------------------
+	 * MPU needs to be disabled because both BL1 and BL33 execute
+	 * in EL2, and therefore share the same address space.
+	 * BL33 will initialize the address space according to its
+	 * own requirement.
+	 * ---------------------------------------------
+	 */
+	bl	disable_mpu_icache_el2
+
+	/* ---------------------------------------------
+	 * Wipe clean and disable all MPU regions.  This function expects
+	 * that the MPU has already been turned off, and caching concerns
+	 * addressed, but it also explicitly turns off the MPU.
+	 * ---------------------------------------------
+	 */
+	bl	clear_all_mpu_regions
+
+#if ENABLE_PAUTH
+	/* ---------------------------------------------
+	 * Disable pointer authentication before jumping
+	 * to next boot image.
+	 * ---------------------------------------------
+	 */
+	bl	pauth_disable_el2
+#endif /* ENABLE_PAUTH */
+
+	/* --------------------------------------------------
+	 * Do the transition to next boot image.
+	 * --------------------------------------------------
+	 */
+	ldp	x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET]
+	msr	elr_el2, x0
+	msr	spsr_el2, x1
+
+	ldp	x6, x7, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x30)]
+	ldp	x4, x5, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x20)]
+	ldp	x2, x3, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x10)]
+	ldp	x0, x1, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x0)]
+	exception_return
+endfunc bl1_run_next_image
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S b/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S
new file mode 100644
index 0000000..43c2e01
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl1/bl1.h>
+#include <common/bl_common.h>
+#include <context.h>
+
+/* -----------------------------------------------------------------------------
+ * File contains an EL2 equivalent of the EL3 vector table from:
+ * 	.../bl1/aarch64/bl1_exceptions.S
+ * -----------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------
+ * Very simple stackless exception handlers used by BL1.
+ * -----------------------------------------------------------------------------
+ */
+	.globl	bl1_exceptions
+
+vector_base bl1_exceptions
+
+	/* -----------------------------------------------------
+	 * Current EL with SP0 : 0x0 - 0x200
+	 * -----------------------------------------------------
+	 */
+vector_entry SynchronousExceptionSP0
+	mov	x0, #SYNC_EXCEPTION_SP_EL0
+	bl	plat_report_exception
+	no_ret	plat_panic_handler
+end_vector_entry SynchronousExceptionSP0
+
+vector_entry IrqSP0
+	mov	x0, #IRQ_SP_EL0
+	bl	plat_report_exception
+	no_ret	plat_panic_handler
+end_vector_entry IrqSP0
+
+vector_entry FiqSP0
+	mov	x0, #FIQ_SP_EL0
+	bl	plat_report_exception
+	no_ret	plat_panic_handler
+end_vector_entry FiqSP0
+
+vector_entry SErrorSP0
+	mov	x0, #SERROR_SP_EL0
+	bl	plat_report_exception
+	no_ret	plat_panic_handler
+end_vector_entry SErrorSP0
+
+	/* -----------------------------------------------------
+	 * Current EL with SPx: 0x200 - 0x400
+	 * -----------------------------------------------------
+	 */
+vector_entry SynchronousExceptionSPx
+	mov	x0, #SYNC_EXCEPTION_SP_ELX
+	bl	plat_report_exception
+	no_ret	plat_panic_handler
+end_vector_entry SynchronousExceptionSPx
+
+vector_entry IrqSPx
+	mov	x0, #IRQ_SP_ELX
+	bl	plat_report_exception
+	no_ret	plat_panic_handler
+end_vector_entry IrqSPx
+
+vector_entry FiqSPx
+	mov	x0, #FIQ_SP_ELX
+	bl	plat_report_exception
+	no_ret	plat_panic_handler
+end_vector_entry FiqSPx
+
+vector_entry SErrorSPx
+	mov	x0, #SERROR_SP_ELX
+	bl	plat_report_exception
+	no_ret	plat_panic_handler
+end_vector_entry SErrorSPx
+
+	/* -----------------------------------------------------
+	 * Lower EL using AArch64 : 0x400 - 0x600
+	 * -----------------------------------------------------
+	 */
+vector_entry SynchronousExceptionA64
+	/* The current v8-R64 implementation does not support conduit calls */
+	b	el2_panic
+end_vector_entry SynchronousExceptionA64
+
+vector_entry IrqA64
+	mov	x0, #IRQ_AARCH64
+	bl	plat_report_exception
+	no_ret	plat_panic_handler
+end_vector_entry IrqA64
+
+vector_entry FiqA64
+	mov	x0, #FIQ_AARCH64
+	bl	plat_report_exception
+	no_ret	plat_panic_handler
+end_vector_entry FiqA64
+
+vector_entry SErrorA64
+	mov	x0, #SERROR_AARCH64
+	bl	plat_report_exception
+	no_ret	plat_panic_handler
+end_vector_entry SErrorA64
+
+
+unexpected_sync_exception:
+	mov	x0, #SYNC_EXCEPTION_AARCH64
+	bl	plat_report_exception
+	no_ret	plat_panic_handler
+
+	/* -----------------------------------------------------
+	 * Save Secure/Normal world context and jump to
+	 * BL1 SMC handler.
+	 * -----------------------------------------------------
+	 */
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_main.c b/plat/arm/board/fvp_r/fvp_r_bl1_main.c
new file mode 100644
index 0000000..2fd0e97
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_main.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include "../../../../bl1/bl1_private.h"
+#include <arch.h>
+#include <arch_features.h>
+#include <arch_helpers.h>
+#include <bl1/bl1.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/auth/auth_mod.h>
+#include <drivers/console.h>
+#include <lib/cpus/errata_report.h>
+#include <lib/utils.h>
+#include <smccc_helpers.h>
+#include <tools_share/uuid.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+
+void bl1_run_next_image(const struct entry_point_info *bl_ep_info);
+
+/*******************************************************************************
+ * Function to perform late architectural and platform specific initialization.
+ * It also queries the platform to load and run next BL image. Only called
+ * by the primary cpu after a cold boot.
+ ******************************************************************************/
+void bl1_transfer_bl33(void)
+{
+	unsigned int image_id;
+
+	/* Get the image id of next image to load and run. */
+	image_id = bl1_plat_get_next_image_id();
+
+#if ENABLE_PAUTH
+	/*
+	 * Disable pointer authentication before running next boot image
+	 */
+	pauth_disable_el2();
+#endif /* ENABLE_PAUTH */
+
+#if !ARM_DISABLE_TRUSTED_WDOG
+	/* Disable watchdog before leaving BL1 */
+	plat_arm_secure_wdt_stop();
+#endif
+
+	bl1_run_next_image(&bl1_plat_get_image_desc(image_id)->ep_info);
+}
+
+/*******************************************************************************
+ * This function locates and loads the BL33 raw binary image in the trusted SRAM.
+ * Called by the primary cpu after a cold boot.
+ * TODO: Add support for alternative image load mechanism e.g using virtio/elf
+ * loader etc.
+ ******************************************************************************/
+void bl1_load_bl33(void)
+{
+	image_desc_t *desc;
+	image_info_t *info;
+	int err;
+
+	/* Get the image descriptor */
+	desc = bl1_plat_get_image_desc(BL33_IMAGE_ID);
+	assert(desc != NULL);
+
+	/* Get the image info */
+	info = &desc->image_info;
+	INFO("BL1: Loading BL33\n");
+
+	err = bl1_plat_handle_pre_image_load(BL33_IMAGE_ID);
+	if (err != 0) {
+		ERROR("Failure in pre image load handling of BL33 (%d)\n", err);
+		plat_error_handler(err);
+	}
+
+	err = load_auth_image(BL33_IMAGE_ID, info);
+	if (err != 0) {
+		ERROR("Failed to load BL33 firmware.\n");
+		plat_error_handler(err);
+	}
+
+	/* Allow platform to handle image information. */
+	err = bl1_plat_handle_post_image_load(BL33_IMAGE_ID);
+	if (err != 0) {
+		ERROR("Failure in post image load handling of BL33 (%d)\n", err);
+		plat_error_handler(err);
+	}
+
+	NOTICE("BL1: Booting BL33\n");
+}
+
+static void bl1_load_bl2(void);
+
+#if ENABLE_PAUTH
+uint64_t bl1_apiakey[2];
+#endif
+
+/*******************************************************************************
+ * Helper utility to calculate the BL2 memory layout taking into consideration
+ * the BL1 RW data assuming that it is at the top of the memory layout.
+ ******************************************************************************/
+void bl1_calc_bl2_mem_layout(const meminfo_t *bl1_mem_layout,
+			meminfo_t *bl2_mem_layout)
+{
+	assert(bl1_mem_layout != NULL);
+	assert(bl2_mem_layout != NULL);
+
+	/*
+	 * Remove BL1 RW data from the scope of memory visible to BL2.
+	 * This is assuming BL1 RW data is at the top of bl1_mem_layout.
+	 */
+	assert(bl1_mem_layout->total_base < BL1_RW_BASE);
+	bl2_mem_layout->total_base = bl1_mem_layout->total_base;
+	bl2_mem_layout->total_size = BL1_RW_BASE - bl1_mem_layout->total_base;
+
+	flush_dcache_range((uintptr_t)bl2_mem_layout, sizeof(meminfo_t));
+}
+
+/*******************************************************************************
+ * Setup function for BL1.
+ ******************************************************************************/
+void bl1_setup(void)
+{
+	/* Perform early platform-specific setup */
+	bl1_early_platform_setup();
+
+	/* Perform late platform-specific setup */
+	bl1_plat_arch_setup();
+
+#if CTX_INCLUDE_PAUTH_REGS
+	/*
+	 * Assert that the ARMv8.3-PAuth registers are present or an access
+	 * fault will be triggered when they are being saved or restored.
+	 */
+	assert(is_armv8_3_pauth_present());
+#endif /* CTX_INCLUDE_PAUTH_REGS */
+}
+
+/*******************************************************************************
+ * Function to perform late architectural and platform specific initialization.
+ * It also queries the platform to load and run next BL image. Only called
+ * by the primary cpu after a cold boot.
+ ******************************************************************************/
+void bl1_main(void)
+{
+	unsigned int image_id;
+
+	/* Announce our arrival */
+	NOTICE(FIRMWARE_WELCOME_STR);
+	NOTICE("BL1: %s\n", version_string);
+	NOTICE("BL1: %s\n", build_message);
+
+	INFO("BL1: RAM %p - %p\n", (void *)BL1_RAM_BASE, (void *)BL1_RAM_LIMIT);
+
+	print_errata_status();
+
+#if ENABLE_ASSERTIONS
+	u_register_t val;
+	/*
+	 * Ensure that MMU/Caches and coherency are turned on
+	 */
+	val = read_sctlr_el2();
+
+	assert((val & SCTLR_M_BIT) != 0U);
+	assert((val & SCTLR_C_BIT) != 0U);
+	assert((val & SCTLR_I_BIT) != 0U);
+	/*
+	 * Check that Cache Writeback Granule (CWG) in CTR_EL0 matches the
+	 * provided platform value
+	 */
+	val = (read_ctr_el0() >> CTR_CWG_SHIFT) & CTR_CWG_MASK;
+	/*
+	 * If CWG is zero, then no CWG information is available but we can
+	 * at least check the platform value is less than the architectural
+	 * maximum.
+	 */
+	if (val != 0) {
+		assert(SIZE_FROM_LOG2_WORDS(val) == CACHE_WRITEBACK_GRANULE);
+	} else {
+		assert(MAX_CACHE_LINE_SIZE >= CACHE_WRITEBACK_GRANULE);
+	}
+#endif /* ENABLE_ASSERTIONS */
+
+	/* Perform remaining generic architectural setup from ELmax */
+	bl1_arch_setup();
+
+#if TRUSTED_BOARD_BOOT
+	/* Initialize authentication module */
+	auth_mod_init();
+#endif /* TRUSTED_BOARD_BOOT */
+
+	/* Perform platform setup in BL1. */
+	bl1_platform_setup();
+
+#if ENABLE_PAUTH
+	/* Store APIAKey_EL1 key */
+	bl1_apiakey[0] = read_apiakeylo_el1();
+	bl1_apiakey[1] = read_apiakeyhi_el1();
+#endif /* ENABLE_PAUTH */
+
+	/* Get the image id of next image to load and run. */
+	image_id = bl1_plat_get_next_image_id();
+
+	/*
+	 * We currently interpret any image id other than
+	 * BL2_IMAGE_ID as the start of firmware update.
+	 */
+	if (image_id == BL2_IMAGE_ID) {
+		bl1_load_bl2();
+	} else if (image_id == BL33_IMAGE_ID) {
+		bl1_load_bl33();
+	} else {
+		NOTICE("BL1-FWU: *******FWU Process Started*******\n");
+	}
+
+	bl1_prepare_next_image(image_id);
+
+	console_flush();
+
+	bl1_transfer_bl33();
+}
+
+/*******************************************************************************
+ * This function locates and loads the BL2 raw binary image in the trusted SRAM.
+ * Called by the primary cpu after a cold boot.
+ * TODO: Add support for alternative image load mechanism e.g using virtio/elf
+ * loader etc.
+ ******************************************************************************/
+static void bl1_load_bl2(void)
+{
+	image_desc_t *desc;
+	image_info_t *info;
+	int err;
+
+	/* Get the image descriptor */
+	desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
+	assert(desc != NULL);
+
+	/* Get the image info */
+	info = &desc->image_info;
+	INFO("BL1: Loading BL2\n");
+
+	err = bl1_plat_handle_pre_image_load(BL2_IMAGE_ID);
+	if (err != 0) {
+		ERROR("Failure in pre image load handling of BL2 (%d)\n", err);
+		plat_error_handler(err);
+	}
+
+	err = load_auth_image(BL2_IMAGE_ID, info);
+	if (err != 0) {
+		ERROR("Failed to load BL2 firmware.\n");
+		plat_error_handler(err);
+	}
+
+	/* Allow platform to handle image information. */
+	err = bl1_plat_handle_post_image_load(BL2_IMAGE_ID);
+	if (err != 0) {
+		ERROR("Failure in post image load handling of BL2 (%d)\n", err);
+		plat_error_handler(err);
+	}
+
+	NOTICE("BL1: Booting BL2\n");
+}
+
+/*******************************************************************************
+ * Function called just before handing over to the next BL to inform the user
+ * about the boot progress. In debug mode, also print details about the BL
+ * image's execution context.
+ ******************************************************************************/
+void bl1_print_next_bl_ep_info(const entry_point_info_t *bl_ep_info)
+{
+	NOTICE("BL1: Booting BL31\n");
+	print_entry_point_info(bl_ep_info);
+}
+
+#if SPIN_ON_BL1_EXIT
+void print_debug_loop_message(void)
+{
+	NOTICE("BL1: Debug loop, spinning forever\n");
+	NOTICE("BL1: Please connect the debugger to continue\n");
+}
+#endif
+
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_setup.c b/plat/arm/board/fvp_r/fvp_r_bl1_setup.c
new file mode 100644
index 0000000..3f3fd5e
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_setup.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Use the xlat_tables_v2 data structures: */
+#define XLAT_TABLES_LIB_V2	1
+
+#include <assert.h>
+
+#include <bl1/bl1.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/arm/sp805.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <lib/xlat_mpu/xlat_mpu.h>
+
+#include "fvp_r_private.h"
+#include <plat/arm/common/arm_config.h>
+#include <plat/arm/common/arm_def.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#define MAP_BL1_TOTAL		MAP_REGION_FLAT(			\
+					bl1_tzram_layout.total_base,	\
+					bl1_tzram_layout.total_size,	\
+					MT_MEMORY | MT_RW | MT_SECURE)
+/*
+ * If SEPARATE_CODE_AND_RODATA=1 we define a region for each section
+ * otherwise one region is defined containing both
+ */
+#if SEPARATE_CODE_AND_RODATA
+#define MAP_BL1_RO		MAP_REGION_FLAT(			\
+					BL_CODE_BASE,			\
+					BL1_CODE_END - BL_CODE_BASE,	\
+					MT_CODE | MT_SECURE),		\
+				MAP_REGION_FLAT(			\
+					BL1_RO_DATA_BASE,		\
+					BL1_RO_DATA_END			\
+						- BL_RO_DATA_BASE,	\
+					MT_RO_DATA | MT_SECURE)
+#else
+#define MAP_BL1_RO		MAP_REGION_FLAT(			\
+					BL_CODE_BASE,			\
+					BL1_CODE_END - BL_CODE_BASE,	\
+					MT_CODE | MT_SECURE)
+#endif
+
+/* Data structure which holds the extents of the trusted SRAM for BL1*/
+static meminfo_t bl1_tzram_layout;
+
+struct meminfo *bl1_plat_sec_mem_layout(void)
+{
+	return &bl1_tzram_layout;
+}
+
+void arm_bl1_early_platform_setup(void)
+{
+
+#if !ARM_DISABLE_TRUSTED_WDOG
+	/* Enable watchdog */
+	plat_arm_secure_wdt_start();
+#endif
+
+	/* Initialize the console to provide early debug support */
+	arm_console_boot_init();
+
+	/* Allow BL1 to see the whole Trusted RAM */
+	bl1_tzram_layout.total_base = ARM_BL_RAM_BASE;
+	bl1_tzram_layout.total_size = ARM_BL_RAM_SIZE;
+}
+
+/* Boolean variable to hold condition whether firmware update needed or not */
+static bool is_fwu_needed;
+
+/*******************************************************************************
+ * Perform any BL1 specific platform actions.
+ ******************************************************************************/
+void bl1_early_platform_setup(void)
+{
+	arm_bl1_early_platform_setup();
+
+	/* Initialize the platform config for future decision making */
+	fvp_config_setup();
+
+	/*
+	 * Initialize Interconnect for this cluster during cold boot.
+	 * No need for locks as no other CPU is active.
+	 */
+	fvp_interconnect_init();
+	/*
+	 * Enable coherency in Interconnect for the primary CPU's cluster.
+	 */
+	fvp_interconnect_enable();
+}
+
+void arm_bl1_plat_arch_setup(void)
+{
+	const mmap_region_t bl_regions[] = {
+		MAP_BL1_TOTAL,
+		MAP_BL1_RO,
+#if USE_ROMLIB
+		ARM_MAP_ROMLIB_CODE,
+		ARM_MAP_ROMLIB_DATA,
+#endif
+#if ARM_CRYPTOCELL_INTEG
+		ARM_MAP_BL_COHERENT_RAM,
+#endif
+		/* DRAM1_region: */
+		MAP_REGION_FLAT(					\
+			PLAT_ARM_DRAM1_BASE,				\
+			PLAT_ARM_DRAM1_SIZE,				\
+			MT_MEMORY | MT_SECURE | MT_EXECUTE		\
+			| MT_RW | MT_NON_CACHEABLE),
+		/* NULL terminator: */
+		{0}
+	};
+
+	setup_page_tables(bl_regions, plat_arm_get_mmap());
+	enable_mpu_el2(0);
+
+	arm_setup_romlib();
+}
+
+void plat_arm_secure_wdt_start(void)
+{
+	sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+	sp805_stop(ARM_SP805_TWDG_BASE);
+}
+
+/*
+ * Perform the platform specific architecture setup shared between
+ * ARM standard platforms.
+ */
+void arm_bl1_platform_setup(void)
+{
+	image_desc_t *desc;
+	uint32_t fw_config_max_size;
+
+	/* Initialise the IO layer and register platform IO devices */
+	plat_arm_io_setup();
+
+	/* Check if we need FWU before further processing */
+	is_fwu_needed = plat_arm_bl1_fwu_needed();
+	if (is_fwu_needed) {
+		ERROR("Skip platform setup as FWU detected\n");
+		return;
+	}
+
+	/* Set global DTB info for fixed fw_config information */
+	fw_config_max_size = ARM_FW_CONFIG_LIMIT - ARM_FW_CONFIG_BASE;
+	set_config_info(ARM_FW_CONFIG_BASE, fw_config_max_size, FW_CONFIG_ID);
+
+	desc = bl1_plat_get_image_desc(BL33_IMAGE_ID);
+	assert(desc != NULL);
+
+	/*
+	 * Allow access to the System counter timer module and program
+	 * counter frequency for non secure images during FWU
+	 */
+#ifdef ARM_SYS_TIMCTL_BASE
+	arm_configure_sys_timer();
+#endif
+#if (ARM_ARCH_MAJOR > 7) || defined(ARMV7_SUPPORTS_GENERIC_TIMER)
+	write_cntfrq_el0(plat_get_syscnt_freq2());
+#endif
+}
+
+void bl1_platform_setup(void)
+{
+	arm_bl1_platform_setup();
+
+	/* Initialize System level generic or SP804 timer */
+	fvp_timer_init();
+}
+
+__dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved)
+{
+	/* Setup the watchdog to reset the system as soon as possible */
+	sp805_refresh(ARM_SP805_TWDG_BASE, 1U);
+
+	while (true) {
+		wfi();
+	}
+}
+
+unsigned int bl1_plat_get_next_image_id(void)
+{
+	return  is_fwu_needed ? NS_BL1U_IMAGE_ID : BL33_IMAGE_ID;
+}
+
+/*
+ * Returns BL33 image details.
+ */
+struct image_desc *bl1_plat_get_image_desc(unsigned int image_id)
+{
+	static image_desc_t bl33_img_desc = BL33_IMAGE_DESC;
+
+	return &bl33_img_desc;
+}
+
+/*
+ * This function populates the default arguments to BL33.
+ * The BL33 memory layout structure is allocated and the
+ * calculated layout is populated in arg1 to BL33.
+ */
+int bl1_plat_handle_post_image_load(unsigned int image_id)
+{
+	meminfo_t *bl33_secram_layout;
+	meminfo_t *bl1_secram_layout;
+	image_desc_t *image_desc;
+	entry_point_info_t *ep_info;
+
+	if (image_id != BL33_IMAGE_ID) {
+		return 0;
+	}
+	/* Get the image descriptor */
+	image_desc = bl1_plat_get_image_desc(BL33_IMAGE_ID);
+	assert(image_desc != NULL);
+
+	/* Get the entry point info */
+	ep_info = &image_desc->ep_info;
+
+	/* Find out how much free trusted ram remains after BL1 load */
+	bl1_secram_layout = bl1_plat_sec_mem_layout();
+
+	/*
+	 * Create a new layout of memory for BL33 as seen by BL1 i.e.
+	 * tell it the amount of total and free memory available.
+	 * This layout is created at the first free address visible
+	 * to BL33. BL33 will read the memory layout before using its
+	 * memory for other purposes.
+	 */
+	bl33_secram_layout = (meminfo_t *) bl1_secram_layout->total_base;
+
+	bl1_calc_bl2_mem_layout(bl1_secram_layout, bl33_secram_layout);
+
+	ep_info->args.arg1 = (uintptr_t)bl33_secram_layout;
+
+	VERBOSE("BL1: BL3 memory layout address = %p\n",
+		(void *) bl33_secram_layout);
+	return 0;
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_common.c b/plat/arm/board/fvp_r/fvp_r_common.c
new file mode 100644
index 0000000..bce943d
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_common.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* This uses xlat_mpu, but tables are set up using V2 mmap_region_t */
+#define XLAT_TABLES_LIB_V2	1
+
+#include <assert.h>
+#include <common/debug.h>
+
+#include <drivers/arm/cci.h>
+#include <drivers/arm/ccn.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/sp804_delay_timer.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/smccc.h>
+#include <lib/xlat_tables/xlat_tables_compat.h>
+#include <services/arm_arch_svc.h>
+
+#include "fvp_r_private.h"
+#include <plat/arm/common/arm_config.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+
+/* Defines for GIC Driver build time selection */
+#define FVP_R_GICV3		2
+
+/*******************************************************************************
+ * arm_config holds the characteristics of the differences between the FVP_R
+ * platforms. It will be populated during cold boot at each boot stage by the
+ * primary before enabling the MPU (to allow interconnect configuration) &
+ * used thereafter. Each BL will have its own copy to allow independent
+ * operation.
+ ******************************************************************************/
+arm_config_t arm_config;
+
+#define MAP_DEVICE0	MAP_REGION_FLAT(DEVICE0_BASE,			\
+					DEVICE0_SIZE,			\
+					MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_DEVICE1	MAP_REGION_FLAT(DEVICE1_BASE,			\
+					DEVICE1_SIZE,			\
+					MT_DEVICE | MT_RW | MT_SECURE)
+
+/*
+ * Need to be mapped with write permissions in order to set a new non-volatile
+ * counter value.
+ */
+#define MAP_DEVICE2	MAP_REGION_FLAT(DEVICE2_BASE,			\
+					DEVICE2_SIZE,			\
+					MT_DEVICE | MT_RW | MT_SECURE)
+
+/*
+ * Table of memory regions for various BL stages to map using the MPU.
+ * This doesn't include Trusted SRAM as setup_page_tables() already takes care
+ * of mapping it.
+ *
+ * The flash needs to be mapped as writable in order to erase the FIP's Table of
+ * Contents in case of unrecoverable error (see plat_error_handler()).
+ */
+#ifdef IMAGE_BL1
+const mmap_region_t plat_arm_mmap[] = {
+	ARM_MAP_SHARED_RAM,
+	V2M_MAP_FLASH0_RW,
+	V2M_MAP_IOFPGA,
+	MAP_DEVICE0,
+	MAP_DEVICE1,
+#if TRUSTED_BOARD_BOOT
+	/* To access the Root of Trust Public Key registers. */
+	MAP_DEVICE2,
+#endif
+	{0}
+};
+#endif
+
+ARM_CASSERT_MMAP
+
+#if FVP_R_INTERCONNECT_DRIVER != FVP_R_CCN
+static const int fvp_cci400_map[] = {
+	PLAT_FVP_R_CCI400_CLUS0_SL_PORT,
+	PLAT_FVP_R_CCI400_CLUS1_SL_PORT,
+};
+
+static const int fvp_cci5xx_map[] = {
+	PLAT_FVP_R_CCI5XX_CLUS0_SL_PORT,
+	PLAT_FVP_R_CCI5XX_CLUS1_SL_PORT,
+};
+
+static unsigned int get_interconnect_master(void)
+{
+	unsigned int master;
+	u_register_t mpidr;
+
+	mpidr = read_mpidr_el1();
+	master = ((arm_config.flags & ARM_CONFIG_FVP_SHIFTED_AFF) != 0U) ?
+		MPIDR_AFFLVL2_VAL(mpidr) : MPIDR_AFFLVL1_VAL(mpidr);
+
+	assert(master < FVP_R_CLUSTER_COUNT);
+	return master;
+}
+#endif
+
+/*******************************************************************************
+ * Initialize the platform config for future decision making
+ ******************************************************************************/
+void __init fvp_config_setup(void)
+{
+	unsigned int rev, hbi, bld, arch, sys_id;
+
+	arm_config.flags |= ARM_CONFIG_BASE_MMAP;
+	sys_id = mmio_read_32(V2M_FVP_R_SYSREGS_BASE + V2M_SYS_ID);
+	rev = (sys_id >> V2M_SYS_ID_REV_SHIFT) & V2M_SYS_ID_REV_MASK;
+	hbi = (sys_id >> V2M_SYS_ID_HBI_SHIFT) & V2M_SYS_ID_HBI_MASK;
+	bld = (sys_id >> V2M_SYS_ID_BLD_SHIFT) & V2M_SYS_ID_BLD_MASK;
+	arch = (sys_id >> V2M_SYS_ID_ARCH_SHIFT) & V2M_SYS_ID_ARCH_MASK;
+
+	if (arch != ARCH_MODEL) {
+		ERROR("This firmware is for FVP_R models\n");
+		panic();
+	}
+
+	/*
+	 * The build field in the SYS_ID tells which variant of the GIC
+	 * memory is implemented by the model.
+	 */
+	switch (bld) {
+	case BLD_GIC_VE_MMAP:
+		ERROR("Legacy Versatile Express memory map for GIC %s",
+				"peripheral is not supported\n");
+		panic();
+		break;
+	case BLD_GIC_A53A57_MMAP:
+		break;
+	default:
+		ERROR("Unsupported board build %x\n", bld);
+		panic();
+	}
+
+	/*
+	 * The hbi field in the SYS_ID is 0x020 for the Base FVP_R & 0x010
+	 * for the Foundation FVP_R.
+	 */
+	switch (hbi) {
+	case HBI_FOUNDATION_FVP_R:
+		arm_config.flags = 0;
+
+		/*
+		 * Check for supported revisions of Foundation FVP_R
+		 * Allow future revisions to run but emit warning diagnostic
+		 */
+		switch (rev) {
+		case REV_FOUNDATION_FVP_R_V2_0:
+		case REV_FOUNDATION_FVP_R_V2_1:
+		case REV_FOUNDATION_FVP_R_v9_1:
+		case REV_FOUNDATION_FVP_R_v9_6:
+			break;
+		default:
+			WARN("Unrecognized Foundation FVP_R revision %x\n", rev);
+			break;
+		}
+		break;
+	case HBI_BASE_FVP_R:
+		arm_config.flags |= (ARM_CONFIG_BASE_MMAP | ARM_CONFIG_HAS_TZC);
+
+		/*
+		 * Check for supported revisions
+		 * Allow future revisions to run but emit warning diagnostic
+		 */
+		switch (rev) {
+		case REV_BASE_FVP_R_V0:
+			arm_config.flags |= ARM_CONFIG_FVP_HAS_CCI400;
+			break;
+		default:
+			WARN("Unrecognized Base FVP_R revision %x\n", rev);
+			break;
+		}
+		break;
+	default:
+		ERROR("Unsupported board HBI number 0x%x\n", hbi);
+		panic();
+	}
+
+	/*
+	 * We assume that the presence of MT bit, and therefore shifted
+	 * affinities, is uniform across the platform: either all CPUs, or no
+	 * CPUs implement it.
+	 */
+	if ((read_mpidr_el1() & MPIDR_MT_MASK) != 0U) {
+		arm_config.flags |= ARM_CONFIG_FVP_SHIFTED_AFF;
+	}
+}
+
+
+void __init fvp_interconnect_init(void)
+{
+#if FVP_R_INTERCONNECT_DRIVER == FVP_R_CCN
+	if (ccn_get_part0_id(PLAT_ARM_CCN_BASE) != CCN_502_PART0_ID) {
+		ERROR("Unrecognized CCN variant detected. Only CCN-502 is supported");
+		panic();
+	}
+
+	plat_arm_interconnect_init();
+#else
+	uintptr_t cci_base = 0U;
+	const int *cci_map = NULL;
+	unsigned int map_size = 0U;
+
+	/* Initialize the right interconnect */
+	if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI5XX) != 0U) {
+		cci_base = PLAT_FVP_R_CCI5XX_BASE;
+		cci_map = fvp_cci5xx_map;
+		map_size = ARRAY_SIZE(fvp_cci5xx_map);
+	} else if ((arm_config.flags & ARM_CONFIG_FVP_HAS_CCI400) != 0U) {
+		cci_base = PLAT_FVP_R_CCI400_BASE;
+		cci_map = fvp_cci400_map;
+		map_size = ARRAY_SIZE(fvp_cci400_map);
+	} else {
+		return;
+	}
+
+	assert(cci_base != 0U);
+	assert(cci_map != NULL);
+	cci_init(cci_base, cci_map, map_size);
+#endif
+}
+
+void fvp_interconnect_enable(void)
+{
+#if FVP_R_INTERCONNECT_DRIVER == FVP_R_CCN
+	plat_arm_interconnect_enter_coherency();
+#else
+	unsigned int master;
+
+	if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 |
+				 ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) {
+		master = get_interconnect_master();
+		cci_enable_snoop_dvm_reqs(master);
+	}
+#endif
+}
+
+void fvp_interconnect_disable(void)
+{
+#if FVP_R_INTERCONNECT_DRIVER == FVP_R_CCN
+	plat_arm_interconnect_exit_coherency();
+#else
+	unsigned int master;
+
+	if ((arm_config.flags & (ARM_CONFIG_FVP_HAS_CCI400 |
+				 ARM_CONFIG_FVP_HAS_CCI5XX)) != 0U) {
+		master = get_interconnect_master();
+		cci_disable_snoop_dvm_reqs(master);
+	}
+#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 fvp_timer_init(void)
+{
+#if USE_SP804_TIMER
+	/* Enable the clock override for SP804 timer 0, which means that no
+	 * clock dividers are applied and the raw (35MHz) clock will be used.
+	 */
+	mmio_write_32(V2M_SP810_BASE, FVP_R_SP810_CTRL_TIM0_OV);
+
+	/* Initialize delay timer driver using SP804 dual timer 0 */
+	sp804_timer_init(V2M_SP804_TIMER0_BASE,
+			SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV);
+#else
+	generic_delay_timer_init();
+
+	/* Enable System level generic timer */
+	mmio_write_32(ARM_SYS_CNTCTL_BASE + CNTCR_OFF,
+			CNTCR_FCREQ(0U) | CNTCR_EN);
+#endif /* USE_SP804_TIMER */
+}
+
+/* Get SOC version */
+int32_t plat_get_soc_version(void)
+{
+	return (int32_t)
+		((ARM_SOC_IDENTIFICATION_CODE << ARM_SOC_IDENTIFICATION_SHIFT)
+		 | (ARM_SOC_CONTINUATION_CODE << ARM_SOC_CONTINUATION_SHIFT)
+		 | FVP_R_SOC_ID);
+}
+
+/* Get SOC revision */
+int32_t plat_get_soc_revision(void)
+{
+	unsigned int sys_id;
+
+	sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID);
+	return (int32_t)((sys_id >> V2M_SYS_ID_REV_SHIFT) &
+			V2M_SYS_ID_REV_MASK);
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_context.S b/plat/arm/board/fvp_r/fvp_r_context.S
new file mode 100644
index 0000000..2746c2e
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_context.S
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+
+	.global	el2_exit
+
+/* ------------------------------------------------------------------
+ * The mechanism, from el3_exit, is not used in this v8-R64 implementation.
+ * ------------------------------------------------------------------
+ */
+func el2_exit
+	exception_return
+endfunc el2_exit
diff --git a/plat/arm/board/fvp_r/fvp_r_context_mgmt.c b/plat/arm/board/fvp_r/fvp_r_context_mgmt.c
new file mode 100644
index 0000000..d172d2d
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_context_mgmt.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+
+/************************************************************
+ * For R-class everything is in secure world.
+ * Prepare the CPU system registers for first entry into EL1
+ ************************************************************/
+void cm_prepare_el2_exit(void)
+{
+	uint64_t hcr_el2 = 0U;
+
+	/*
+	 * The use of ARMv8.3 pointer authentication (PAuth) is governed
+	 * by fields in HCR_EL2, which trigger a 'trap to EL2' if not
+	 * enabled. This register initialized at boot up, update PAuth
+	 * bits.
+	 *
+	 * HCR_API_BIT: Set to one to disable traps to EL2 if lower ELs
+	 * access PAuth registers
+	 *
+	 * HCR_APK_BIT: Set to one to disable traps to EL2 if lower ELs
+	 * access PAuth instructions
+	 */
+	hcr_el2 = read_hcr_el2();
+	write_hcr_el2(hcr_el2 | HCR_API_BIT | HCR_APK_BIT);
+
+	/*
+	 * Initialise CNTHCTL_EL2. All fields are architecturally UNKNOWN
+	 * on reset and are set to zero except for field(s) listed below.
+	 *
+	 * CNTHCTL_EL2.EL1PCEN: Set to one to disable traps to EL2
+	 * if lower ELs accesses to the physical timer registers.
+	 *
+	 * CNTHCTL_EL2.EL1PCTEN: Set to one to disable traps to EL2
+	 * if lower ELs access to the physical counter registers.
+	 */
+	write_cnthctl_el2(CNTHCTL_RESET_VAL | EL1PCEN_BIT | EL1PCTEN_BIT);
+
+	/*
+	 * On Armv8-R, the EL1&0 memory system architecture is configurable
+	 * as a VMSA or PMSA. All the fields architecturally UNKNOWN on reset
+	* and are set to zero except for field listed below.
+	*
+	* VCTR_EL2.MSA: Set to one to ensure the VMSA is enabled so that
+	* rich OS can boot.
+	*/
+	write_vtcr_el2(VTCR_RESET_VAL | VTCR_EL2_MSA);
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_debug.S b/plat/arm/board/fvp_r/fvp_r_debug.S
new file mode 100644
index 0000000..8db1b09
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_debug.S
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/debug.h>
+
+	.globl el2_panic
+
+	/***********************************************************
+	 * The common implementation of do_panic for all BL stages
+	 ***********************************************************/
+
+.section .rodata.panic_str, "aS"
+	panic_msg: .asciz "PANIC at PC : 0x"
+
+/*
+ * el2_panic will be redefined by the
+ * crash reporting mechanism (if enabled)
+ */
+el2_panic:
+	mov	x6, x30
+	bl	plat_crash_console_init
+
+	/* Check if the console is initialized */
+	cbz	x0, _panic_handler
+
+	/* The console is initialized */
+	adr	x4, panic_msg
+	bl	asm_print_str
+	mov	x4, x6
+
+	/* The panic location is lr -4 */
+	sub	x4, x4, #4
+	bl	asm_print_hex
+
+	bl	plat_crash_console_flush
+
+_panic_handler:
+	/* Pass to plat_panic_handler the address from where el2_panic was
+	 * called, not the address of the call from el2_panic. */
+	mov	x30, x6
+	b	plat_panic_handler
diff --git a/plat/arm/board/fvp_r/fvp_r_def.h b/plat/arm/board/fvp_r/fvp_r_def.h
new file mode 100644
index 0000000..b9f6989
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_def.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FVP_R_DEF_H
+#define FVP_R_DEF_H
+
+#include <lib/utils_def.h>
+
+#ifndef FVP_R_CLUSTER_COUNT
+#error "FVP_R_CLUSTER_COUNT is not set in makefile"
+#endif
+
+#ifndef FVP_R_MAX_CPUS_PER_CLUSTER
+#error "FVP_R_MAX_CPUS_PER_CLUSTER is not set in makefile"
+#endif
+
+#ifndef FVP_R_MAX_PE_PER_CPU
+#error "FVP_R_MAX_PE_PER_CPU is not set in makefile"
+#endif
+
+#define FVP_R_PRIMARY_CPU			0x0
+
+/* Defines for the Interconnect build selection */
+#define FVP_R_CCI			1
+#define FVP_R_CCN			2
+
+/******************************************************************************
+ * Definition of platform soc id
+ *****************************************************************************/
+#define FVP_R_SOC_ID      0
+
+/*******************************************************************************
+ * FVP_R memory map related constants
+ ******************************************************************************/
+
+#define FLASH1_BASE			UL(0x8c000000)
+#define FLASH1_SIZE			UL(0x04000000)
+
+#define PSRAM_BASE			UL(0x94000000)
+#define PSRAM_SIZE			UL(0x04000000)
+
+#define VRAM_BASE			UL(0x98000000)
+#define VRAM_SIZE			UL(0x02000000)
+
+/* Aggregate of all devices in the first GB */
+#define DEVICE0_BASE			UL(0xa0000000)
+#define DEVICE0_SIZE			UL(0x0c200000)
+
+/*
+ *  In case of FVP_R models with CCN, the CCN register space overlaps into
+ *  the NSRAM area.
+ */
+#define DEVICE1_BASE			UL(0xae000000)
+#define DEVICE1_SIZE			UL(0x1A00000)
+
+#define NSRAM_BASE			UL(0xae000000)
+#define NSRAM_SIZE			UL(0x10000)
+/* Devices in the second GB */
+#define DEVICE2_BASE			UL(0xffe00000)
+#define DEVICE2_SIZE			UL(0x00200000)
+
+#define PCIE_EXP_BASE			UL(0xc0000000)
+#define TZRNG_BASE			UL(0x7fe60000)
+
+/* Non-volatile counters */
+#define TRUSTED_NVCTR_BASE		UL(0xffe70000)
+#define TFW_NVCTR_BASE			(TRUSTED_NVCTR_BASE + UL(0x0000))
+#define TFW_NVCTR_SIZE			UL(4)
+#define NTFW_CTR_BASE			(TRUSTED_NVCTR_BASE + UL(0x0004))
+#define NTFW_CTR_SIZE			UL(4)
+
+/* Keys */
+#define SOC_KEYS_BASE			UL(0xffe80000)
+#define TZ_PUB_KEY_HASH_BASE		(SOC_KEYS_BASE + UL(0x0000))
+#define TZ_PUB_KEY_HASH_SIZE		UL(32)
+#define HU_KEY_BASE			(SOC_KEYS_BASE + UL(0x0020))
+#define HU_KEY_SIZE			UL(16)
+#define END_KEY_BASE			(SOC_KEYS_BASE + UL(0x0044))
+#define END_KEY_SIZE			UL(32)
+
+/* Constants to distinguish FVP_R type */
+#define HBI_BASE_FVP_R			U(0x020)
+#define REV_BASE_FVP_R_V0		U(0x0)
+#define REV_BASE_FVP_R_REVC		U(0x2)
+
+#define HBI_FOUNDATION_FVP_R		U(0x010)
+#define REV_FOUNDATION_FVP_R_V2_0	U(0x0)
+#define REV_FOUNDATION_FVP_R_V2_1	U(0x1)
+#define REV_FOUNDATION_FVP_R_v9_1	U(0x2)
+#define REV_FOUNDATION_FVP_R_v9_6	U(0x3)
+
+#define BLD_GIC_VE_MMAP			U(0x0)
+#define BLD_GIC_A53A57_MMAP		U(0x1)
+
+#define ARCH_MODEL			U(0x1)
+
+/* FVP_R Power controller base address*/
+#define PWRC_BASE			UL(0x1c100000)
+
+/* FVP_R SP804 timer frequency is 35 MHz*/
+#define SP804_TIMER_CLKMULT		1
+#define SP804_TIMER_CLKDIV		35
+
+/* SP810 controller. FVP_R specific flags */
+#define FVP_R_SP810_CTRL_TIM0_OV		BIT_32(16)
+#define FVP_R_SP810_CTRL_TIM1_OV		BIT_32(18)
+#define FVP_R_SP810_CTRL_TIM2_OV		BIT_32(20)
+#define FVP_R_SP810_CTRL_TIM3_OV		BIT_32(22)
+
+#endif /* FVP_R_DEF_H */
diff --git a/plat/arm/board/fvp_r/fvp_r_err.c b/plat/arm/board/fvp_r/fvp_r_err.c
new file mode 100644
index 0000000..7ee752b
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_err.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <common/debug.h>
+#include <drivers/arm/sp805.h>
+#include <drivers/cfi/v2m_flash.h>
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+/*
+ * FVP_R error handler
+ */
+__dead2 void plat_arm_error_handler(int err)
+{
+	int ret;
+
+	switch (err) {
+	case -ENOENT:
+	case -EAUTH:
+		/* Image load or authentication error. Erase the ToC */
+		INFO("Erasing FIP ToC from flash...\n");
+		(void)nor_unlock(PLAT_ARM_FLASH_IMAGE_BASE);
+		ret = nor_word_program(PLAT_ARM_FLASH_IMAGE_BASE, 0);
+		if (ret != 0) {
+			ERROR("Cannot erase ToC\n");
+		} else {
+			INFO("Done\n");
+		}
+		break;
+	default:
+		/* Unexpected error */
+		break;
+	}
+
+	(void)console_flush();
+
+	/* Setup the watchdog to reset the system as soon as possible */
+	sp805_refresh(ARM_SP805_TWDG_BASE, 1U);
+
+	while (true) {
+		wfi();
+	}
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_helpers.S b/plat/arm/board/fvp_r/fvp_r_helpers.S
new file mode 100644
index 0000000..f7a04d8
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_helpers.S
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <drivers/arm/fvp/fvp_pwrc.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/arm/gicv3.h>
+
+#include <platform_def.h>
+
+
+	.globl	plat_secondary_cold_boot_setup
+	.globl	plat_get_my_entrypoint
+	.globl	plat_is_my_cpu_primary
+	.globl	plat_arm_calc_core_pos
+
+	/* -----------------------------------------------------
+	 * void plat_secondary_cold_boot_setup (void);
+	 *
+	 * This function performs any platform specific actions
+	 * needed for a secondary cpu after a cold reset e.g
+	 * mark the cpu's presence, mechanism to place it in a
+	 * holding pen etc.
+	 * TODO: Should we read the PSYS register to make sure
+	 * that the request has gone through.
+	 * -----------------------------------------------------
+	 */
+func plat_secondary_cold_boot_setup
+	/* ---------------------------------------------
+	 * Power down this cpu.
+	 * TODO: Do we need to worry about powering the
+	 * cluster down as well here? That will need
+	 * locks which we won't have unless an elf-
+	 * loader zeroes out the zi section.
+	 * ---------------------------------------------
+	 */
+	mrs	x0, mpidr_el1
+	mov_imm	x1, PWRC_BASE
+	str	w0, [x1, #PPOFFR_OFF]
+
+	/* ---------------------------------------------
+	 * There is no sane reason to come out of this
+	 * wfi so panic if we do. This cpu will be pow-
+	 * ered on and reset by the cpu_on pm api
+	 * ---------------------------------------------
+	 */
+	dsb	sy
+	wfi
+	no_ret	plat_panic_handler
+endfunc plat_secondary_cold_boot_setup
+
+	/* ---------------------------------------------------------------------
+	 * uintptr_t plat_get_my_entrypoint (void);
+	 *
+	 * Main job of this routine is to distinguish between a cold and warm
+	 * boot. On FVP_R, this information can be queried from the power
+	 * controller. The Power Control SYS Status Register (PSYSR) indicates
+	 * the wake-up reason for the CPU.
+	 *
+	 * For a cold boot, return 0.
+	 * For a warm boot, read the mailbox and return the address it contains.
+	 *
+	 * TODO: PSYSR is a common register and should be
+	 * 	accessed using locks. Since it is not possible
+	 * 	to use locks immediately after a cold reset
+	 * 	we are relying on the fact that after a cold
+	 * 	reset all cpus will read the same WK field
+	 * ---------------------------------------------------------------------
+	 */
+func plat_get_my_entrypoint
+	/* ---------------------------------------------------------------------
+	 * When bit PSYSR.WK indicates either "Wake by PPONR" or "Wake by GIC
+	 * WakeRequest signal" then it is a warm boot.
+	 * ---------------------------------------------------------------------
+	 */
+	mrs	x2, mpidr_el1
+	mov_imm	x1, PWRC_BASE
+	str	w2, [x1, #PSYSR_OFF]
+	ldr	w2, [x1, #PSYSR_OFF]
+	ubfx	w2, w2, #PSYSR_WK_SHIFT, #PSYSR_WK_WIDTH
+	cmp	w2, #WKUP_PPONR
+	beq	warm_reset
+	cmp	w2, #WKUP_GICREQ
+	beq	warm_reset
+
+	/* Cold reset */
+	mov	x0, #0
+	ret
+
+warm_reset:
+	/* ---------------------------------------------------------------------
+	 * A mailbox is maintained in the trusted SRAM. It is flushed out of the
+	 * caches after every update using normal memory so it is safe to read
+	 * it here with SO attributes.
+	 * ---------------------------------------------------------------------
+	 */
+	mov_imm	x0, PLAT_ARM_TRUSTED_MAILBOX_BASE
+	ldr	x0, [x0]
+	cbz	x0, _panic_handler
+	ret
+
+	/* ---------------------------------------------------------------------
+	 * The power controller indicates this is a warm reset but the mailbox
+	 * is empty. This should never happen!
+	 * ---------------------------------------------------------------------
+	 */
+_panic_handler:
+	no_ret	plat_panic_handler
+endfunc plat_get_my_entrypoint
+
+	/* -----------------------------------------------------
+	 * unsigned int plat_is_my_cpu_primary (void);
+	 *
+	 * Find out whether the current cpu is the primary
+	 * cpu.
+	 * -----------------------------------------------------
+	 */
+func plat_is_my_cpu_primary
+	mrs	x0, mpidr_el1
+	mov_imm	x1, MPIDR_AFFINITY_MASK
+	and	x0, x0, x1
+	cmp	x0, #FVP_R_PRIMARY_CPU
+	cset	w0, eq
+	ret
+endfunc plat_is_my_cpu_primary
+
+	/* ---------------------------------------------------------------------
+	 * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
+	 *
+	 * Function to calculate the core position on FVP_R.
+	 *
+	 * (ClusterId * FVP_R_MAX_CPUS_PER_CLUSTER * FVP_R_MAX_PE_PER_CPU) +
+	 * (CPUId * FVP_R_MAX_PE_PER_CPU) +
+	 * ThreadId
+	 *
+	 * which can be simplified as:
+	 *
+	 * ((ClusterId * FVP_R_MAX_CPUS_PER_CLUSTER + CPUId) * FVP_R_MAX_PE_PER_CPU)
+	 * + ThreadId
+	 * ---------------------------------------------------------------------
+	 */
+func plat_arm_calc_core_pos
+	/*
+	 * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
+	 * look as if in a multi-threaded implementation.
+	 */
+	tst	x0, #MPIDR_MT_MASK
+	lsl	x3, x0, #MPIDR_AFFINITY_BITS
+	csel	x3, x3, x0, eq
+
+	/* Extract individual affinity fields from MPIDR */
+	ubfx	x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+
+	/* Compute linear position */
+	mov	x4, #FVP_R_MAX_CPUS_PER_CLUSTER
+	madd	x1, x2, x4, x1
+	mov	x5, #FVP_R_MAX_PE_PER_CPU
+	madd	x0, x1, x5, x0
+	ret
+endfunc plat_arm_calc_core_pos
diff --git a/plat/arm/board/fvp_r/fvp_r_io_storage.c b/plat/arm/board/fvp_r/fvp_r_io_storage.c
new file mode 100644
index 0000000..3b44828
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_io_storage.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_semihosting.h>
+#include <drivers/io/io_storage.h>
+#include <lib/semihosting.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/common_def.h>
+
+/* Semihosting filenames */
+#define BL33_IMAGE_NAME			"bl33.bin"
+
+#if TRUSTED_BOARD_BOOT
+#define TRUSTED_KEY_CERT_NAME		"trusted_key.crt"
+#define NT_FW_KEY_CERT_NAME		"nt_fw_key.crt"
+#define NT_FW_CONTENT_CERT_NAME		"nt_fw_content.crt"
+#endif /* TRUSTED_BOARD_BOOT */
+
+/* IO devices */
+static const io_dev_connector_t *sh_dev_con;
+static uintptr_t sh_dev_handle;
+
+static const io_file_spec_t sh_file_spec[] = {
+	[BL33_IMAGE_ID] = {
+		.path = BL33_IMAGE_NAME,
+		.mode = FOPEN_MODE_RB
+	},
+#if TRUSTED_BOARD_BOOT
+	[TRUSTED_KEY_CERT_ID] = {
+		.path = TRUSTED_KEY_CERT_NAME,
+		.mode = FOPEN_MODE_RB
+	},
+	[NON_TRUSTED_FW_KEY_CERT_ID] = {
+		.path = NT_FW_KEY_CERT_NAME,
+		.mode = FOPEN_MODE_RB
+	},
+	[NON_TRUSTED_FW_CONTENT_CERT_ID] = {
+		.path = NT_FW_CONTENT_CERT_NAME,
+		.mode = FOPEN_MODE_RB
+	},
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+
+static int open_semihosting(const uintptr_t spec)
+{
+	int result;
+	uintptr_t local_image_handle;
+
+	/* See if the file exists on semi-hosting.*/
+	result = io_dev_init(sh_dev_handle, (uintptr_t)NULL);
+	if (result == 0) {
+		result = io_open(sh_dev_handle, spec, &local_image_handle);
+		if (result == 0) {
+			VERBOSE("Using Semi-hosting IO\n");
+			io_close(local_image_handle);
+		}
+	}
+	return result;
+}
+
+void plat_arm_io_setup(void)
+{
+	int io_result;
+
+	io_result = arm_io_setup();
+	if (io_result < 0) {
+		panic();
+	}
+
+	/* Register the additional IO devices on this platform */
+	io_result = register_io_dev_sh(&sh_dev_con);
+	if (io_result < 0) {
+		panic();
+	}
+
+	/* Open connections to devices and cache the handles */
+	io_result = io_dev_open(sh_dev_con, (uintptr_t)NULL, &sh_dev_handle);
+	if (io_result < 0) {
+		panic();
+	}
+}
+
+/*
+ * FVP_R provides semihosting as an alternative to load images
+ */
+int plat_arm_get_alt_image_source(unsigned int image_id, uintptr_t *dev_handle,
+				  uintptr_t *image_spec)
+{
+	int result = open_semihosting((const uintptr_t)&sh_file_spec[image_id]);
+
+	if (result == 0) {
+		*dev_handle = sh_dev_handle;
+		*image_spec = (uintptr_t)&sh_file_spec[image_id];
+	}
+
+	return result;
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_misc_helpers.S b/plat/arm/board/fvp_r/fvp_r_misc_helpers.S
new file mode 100644
index 0000000..67ad164
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_misc_helpers.S
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+
+	.globl	disable_mpu_el2
+	.globl	disable_mpu_icache_el2
+
+/* ---------------------------------------------------------------------------
+ * Disable the MPU at EL2.
+ * ---------------------------------------------------------------------------
+ */
+
+func disable_mpu_el2
+	mov	x1, #(SCTLR_M_BIT | SCTLR_C_BIT)
+do_disable_mpu_el2:
+	mrs	x0, sctlr_el2
+	bic	x0, x0, x1
+	msr	sctlr_el2, x0
+	isb	/* ensure MMU is off */
+	dsb	sy
+	ret
+endfunc disable_mpu_el2
+
+
+func disable_mpu_icache_el2
+	mov	x1, #(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT)
+	b	do_disable_mpu_el2
+endfunc disable_mpu_icache_el2
diff --git a/plat/arm/board/fvp_r/fvp_r_pauth_helpers.S b/plat/arm/board/fvp_r/fvp_r_pauth_helpers.S
new file mode 100644
index 0000000..7e6bc3d
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_pauth_helpers.S
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <lib/el3_runtime/cpu_data.h>
+
+	.global	pauth_init_enable_el2
+	.global	pauth_disable_el2
+
+/* -------------------------------------------------------------
+ * File contains EL2 versions of EL3 funcs in:
+ * 	.../lib/extensions/pauth/pauth_helpers.S
+ * -------------------------------------------------------------
+ */
+
+/* -------------------------------------------------------------
+ * Program APIAKey_EL1 and enable pointer authentication in EL2
+ * -------------------------------------------------------------
+ */
+func pauth_init_enable_el2
+	stp	x29, x30, [sp, #-16]!
+
+	/* Initialize platform key */
+	bl	plat_init_apkey
+
+	/* Program instruction key A used by the Trusted Firmware */
+	msr	APIAKeyLo_EL1, x0
+	msr	APIAKeyHi_EL1, x1
+
+	/* Enable pointer authentication */
+	mrs	x0, sctlr_el2
+	orr	x0, x0, #SCTLR_EnIA_BIT
+
+#if ENABLE_BTI
+	 /* Enable PAC branch type compatibility */
+	bic	x0, x0, #SCTLR_BT_BIT
+#endif
+	msr	sctlr_el2, x0
+	isb
+
+	ldp	x29, x30, [sp], #16
+	ret
+endfunc pauth_init_enable_el2
+
+/* -------------------------------------------------------------
+ * Disable pointer authentication in EL2
+ * -------------------------------------------------------------
+ */
+func pauth_disable_el2
+	mrs	x0, sctlr_el2
+	bic	x0, x0, #SCTLR_EnIA_BIT
+	msr	sctlr_el2, x0
+	isb
+	ret
+endfunc pauth_disable_el2
diff --git a/plat/arm/board/fvp_r/fvp_r_private.h b/plat/arm/board/fvp_r/fvp_r_private.h
new file mode 100644
index 0000000..48f6e89
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_private.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FVP_R_PRIVATE_H
+#define FVP_R_PRIVATE_H
+
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+
+void fvp_config_setup(void);
+
+void fvp_interconnect_init(void);
+void fvp_interconnect_enable(void);
+void fvp_interconnect_disable(void);
+void fvp_timer_init(void);
+
+#endif /* FVP_R_PRIVATE_H */
diff --git a/plat/arm/board/fvp_r/fvp_r_stack_protector.c b/plat/arm/board/fvp_r/fvp_r_stack_protector.c
new file mode 100644
index 0000000..69b6312
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_stack_protector.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <fvp_r_arch_helpers.h>
+#include <plat/common/platform.h>
+
+#define RANDOM_CANARY_VALUE ((u_register_t) 8092347823957523895ULL)
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+	/*
+	 * Ideally, a random number should be returned instead of the
+	 * combination of a timer's value and a compile-time constant. As the
+	 * FVP_R does not have any random number generator, this is better than
+	 * nothing but not necessarily really secure.
+	 */
+	return RANDOM_CANARY_VALUE ^ read_cntpct_el0();
+}
+
diff --git a/plat/arm/board/fvp_r/fvp_r_trusted_boot.c b/plat/arm/board/fvp_r/fvp_r_trusted_boot.c
new file mode 100644
index 0000000..de0b28f
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_trusted_boot.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <lib/fconf/fconf.h>
+#include <lib/mmio.h>
+#include <tools_share/tbbr_oid.h>
+
+#include <plat/arm/common/fconf_nv_cntr_getter.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+
+/*
+ * 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);
+}
+
+/*
+ * Store a new non-volatile counter value.
+ *
+ * On some FVP_R versions, the non-volatile counters are read-only so this
+ * function will always fail.
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+	const char *oid;
+	uintptr_t nv_ctr_addr;
+
+	assert(cookie != NULL);
+
+	oid = (const char *)cookie;
+	if (strcmp(oid, TRUSTED_FW_NVCOUNTER_OID) == 0) {
+		nv_ctr_addr = FCONF_GET_PROPERTY(cot, nv_cntr_addr,
+						TRUSTED_NV_CTR_ID);
+	} else if (strcmp(oid, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) {
+		nv_ctr_addr = FCONF_GET_PROPERTY(cot, nv_cntr_addr,
+						NON_TRUSTED_NV_CTR_ID);
+	} else {
+		return 1;
+	}
+
+	mmio_write_32(nv_ctr_addr, nv_ctr);
+
+	/*
+	 * If the FVP_R models a locked counter then its value cannot be updated
+	 * and the above write operation has been silently ignored.
+	 */
+	return (mmio_read_32(nv_ctr_addr) == nv_ctr) ? 0 : 1;
+}
diff --git a/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h b/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h
new file mode 100644
index 0000000..92bf484
--- /dev/null
+++ b/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FVP_R_ARCH_HELPERS_H
+#define FVP_R_ARCH_HELPERS_H
+
+#include <arch_helpers.h>
+
+/*******************************************************************************
+ * MPU register definitions
+ ******************************************************************************/
+#define MPUIR_EL2		S3_4_C0_C0_4
+#define PRBAR_EL2		S3_4_C6_C8_0
+#define PRLAR_EL2		S3_4_C6_C8_1
+#define PRSELR_EL2		S3_4_C6_C2_1
+#define PRENR_EL2		S3_4_C6_C1_1
+
+/* v8-R64 MPU registers */
+DEFINE_RENAME_SYSREG_RW_FUNCS(mpuir_el2, MPUIR_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(prenr_el2, PRENR_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(prselr_el2, PRSELR_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(prbar_el2, PRBAR_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(prlar_el2, PRLAR_EL2)
+
+#endif /* FVP_R_ARCH_HELPERS_H */
diff --git a/plat/arm/board/fvp_r/include/plat.ld.S b/plat/arm/board/fvp_r/include/plat.ld.S
new file mode 100644
index 0000000..e91a5a0
--- /dev/null
+++ b/plat/arm/board/fvp_r/include/plat.ld.S
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_LD_S
+#define PLAT_LD_S
+
+#include <plat/arm/common/arm_tzc_dram.ld.S>
+
+#endif /* PLAT_LD_S */
diff --git a/plat/arm/board/fvp_r/include/platform_def.h b/plat/arm/board/fvp_r/include/platform_def.h
new file mode 100644
index 0000000..4a6b441
--- /dev/null
+++ b/plat/arm/board/fvp_r/include/platform_def.h
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FVP_R_PLATFORM_DEF_H
+#define FVP_R_PLATFORM_DEF_H
+
+#define PLAT_V2M_OFFSET			0x80000000
+
+#define BL33_IMAGE_DESC {				\
+	.image_id = BL33_IMAGE_ID,			\
+	SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,	\
+		VERSION_2, image_info_t, 0),		\
+	.image_info.image_base = PLAT_ARM_DRAM1_BASE + 0x1000,		\
+	.image_info.image_max_size = UL(0x3ffff000), \
+	SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,	\
+		VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),\
+	.ep_info.pc = PLAT_ARM_DRAM1_BASE + 0x1000,				\
+	.ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS),	\
+}
+
+#include "../fvp_r_def.h"
+#include <drivers/arm/tzc400.h>
+#include <lib/utils_def.h>
+#include <plat/arm/board/common/v2m_def.h>
+
+/* These are referenced by arm_def.h #included next, so #define first. */
+#define PLAT_ARM_TRUSTED_ROM_BASE	UL(0x80000000)
+#define PLAT_ARM_TRUSTED_SRAM_BASE	UL(0x84000000)
+#define PLAT_ARM_TRUSTED_DRAM_BASE	UL(0x86000000)
+#define PLAT_ARM_DRAM1_BASE		ULL(0x0)
+#define PLAT_ARM_DRAM2_BASE		ULL(0x080000000)
+
+#define PLAT_HW_CONFIG_DTB_BASE		ULL(0x12000000)
+#define PLAT_ARM_SYS_CNTCTL_BASE	UL(0xaa430000)
+#define PLAT_ARM_SYS_CNTREAD_BASE	UL(0xaa800000)
+#define PLAT_ARM_SYS_TIMCTL_BASE	UL(0xaa810000)
+#define PLAT_ARM_SYS_CNT_BASE_S		UL(0xaa820000)
+#define PLAT_ARM_SYS_CNT_BASE_NS	UL(0xaa830000)
+#define PLAT_ARM_SP805_TWDG_BASE	UL(0xaa490000)
+
+#include <plat/arm/common/arm_def.h>
+#include <plat/common/common_def.h>
+
+
+/* Required to create plat_regions: */
+#define MIN_LVL_BLOCK_DESC	U(1)
+
+/* Required platform porting definitions */
+#define PLATFORM_CORE_COUNT  (U(FVP_R_CLUSTER_COUNT) * \
+			      U(FVP_R_MAX_CPUS_PER_CLUSTER) * \
+			      U(FVP_R_MAX_PE_PER_CPU))
+
+#define PLAT_NUM_PWR_DOMAINS (U(FVP_R_CLUSTER_COUNT) + \
+			      PLATFORM_CORE_COUNT + U(1))
+
+#define PLAT_MAX_PWR_LVL		ARM_PWR_LVL2
+
+/*
+ * Other platform porting definitions are provided by included headers
+ */
+
+/*
+ * Required ARM standard platform porting definitions
+ */
+#define PLAT_ARM_CLUSTER_COUNT		U(FVP_R_CLUSTER_COUNT)
+#define PLAT_ARM_DRAM1_SIZE		ULL(0x7fffffff)
+#define PLAT_ARM_TRUSTED_SRAM_SIZE	UL(0x00040000)	/* 256 KB */
+#define PLAT_ARM_TRUSTED_ROM_SIZE	UL(0x04000000)	/* 64 MB */
+#define PLAT_ARM_TRUSTED_DRAM_SIZE	UL(0x02000000)	/* 32 MB */
+
+/* These two are defined thus in arm_def.h, but doesn't seem to see it... */
+#define PLAT_BL1_RO_LIMIT               (BL1_RO_BASE \
+					+ PLAT_ARM_TRUSTED_ROM_SIZE)
+
+#define PLAT_ARM_SYS_CNTCTL_BASE	UL(0xaa430000)
+#define PLAT_ARM_SYS_CNTREAD_BASE	UL(0xaa800000)
+#define PLAT_ARM_SYS_TIMCTL_BASE	UL(0xaa810000)
+#define PLAT_ARM_SYS_CNT_BASE_S		UL(0xaa820000)
+#define PLAT_ARM_SYS_CNT_BASE_NS	UL(0xaa830000)
+#define PLAT_ARM_SP805_TWDG_BASE	UL(0xaa490000)
+
+/* virtual address used by dynamic mem_protect for chunk_base */
+#define PLAT_ARM_MEM_PROTEC_VA_FRAME	UL(0xc0000000)
+
+/* No SCP in FVP_R */
+#define PLAT_ARM_SCP_TZC_DRAM1_SIZE	UL(0x0)
+
+#define PLAT_ARM_DRAM2_SIZE		UL(0x80000000)
+
+#define PLAT_HW_CONFIG_DTB_SIZE		ULL(0x8000)
+
+#define ARM_DTB_DRAM_NS			MAP_REGION_FLAT(		\
+					PLAT_HW_CONFIG_DTB_BASE,	\
+					PLAT_HW_CONFIG_DTB_SIZE,	\
+					MT_MEMORY | MT_RO | MT_NS)
+
+#define V2M_FVP_R_SYSREGS_BASE		UL(0x9c010000)
+
+/*
+ * Load address of BL33 for this platform port,
+ * U-Boot specifically must be loaded at a 4K aligned address.
+ */
+#define PLAT_ARM_NS_IMAGE_BASE		(PLAT_ARM_DRAM1_BASE + 0x1000)
+
+/*
+ * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
+ * plat_arm_mmap array defined for each BL stage.
+ */
+#if !USE_ROMLIB
+# define PLAT_ARM_MMAP_ENTRIES		11
+# define MAX_XLAT_TABLES		5
+#else
+# define PLAT_ARM_MMAP_ENTRIES		12
+# define MAX_XLAT_TABLES		6
+#endif
+# define N_MPU_REGIONS			16  /* number of MPU regions */
+# define ALL_MPU_EL2_REGIONS_USED	0xffffffff
+	/* this is the PRENR_EL2 value if all MPU regions are in use */
+
+/*
+ * 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	UL(0xB000)
+
+/*
+ * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page
+ */
+
+#if USE_ROMLIB
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE	UL(0x1000)
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE	UL(0xe000)
+#define FVP_R_BL2_ROMLIB_OPTIMIZATION UL(0x6000)
+#else
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE	UL(0)
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE	UL(0)
+#define FVP_R_BL2_ROMLIB_OPTIMIZATION UL(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
+#if COT_DESC_IN_DTB
+# define PLAT_ARM_MAX_BL2_SIZE	(UL(0x1E000) - FVP_R_BL2_ROMLIB_OPTIMIZATION)
+#else
+# define PLAT_ARM_MAX_BL2_SIZE	(UL(0x1D000) - FVP_R_BL2_ROMLIB_OPTIMIZATION)
+#endif
+#else
+# define PLAT_ARM_MAX_BL2_SIZE	(UL(0x13000) - FVP_R_BL2_ROMLIB_OPTIMIZATION)
+#endif
+
+/*
+ * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is
+ * calculated using the current BL31 PROGBITS debug size plus the sizes of
+ * BL2 and BL1-RW
+ */
+#define PLAT_ARM_MAX_BL31_SIZE		UL(0x3D000)
+
+/*
+ * Size of cacheable stacks
+ */
+#if defined(IMAGE_BL1)
+# if TRUSTED_BOARD_BOOT
+#  define PLATFORM_STACK_SIZE		UL(0x1000)
+# else
+#  define PLATFORM_STACK_SIZE		UL(0x500)
+# endif
+#endif
+
+#define MAX_IO_DEVICES			3
+#define MAX_IO_HANDLES			4
+
+/*
+ * These nominally reserve the last block of flash for PSCI MEM PROTECT flag,
+ * but no PSCI in FVP_R platform, so reserve nothing:
+ */
+#define PLAT_ARM_FLASH_IMAGE_BASE	(PLAT_ARM_DRAM1_BASE + UL(0x40000000))
+#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE	(PLAT_ARM_DRAM1_SIZE - UL(0x40000000))
+
+#define PLAT_ARM_NVM_BASE		V2M_FLASH0_BASE
+#define PLAT_ARM_NVM_SIZE		(V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+/*
+ * PL011 related constants
+ */
+#define PLAT_ARM_BOOT_UART_BASE		V2M_IOFPGA_UART0_BASE
+#define PLAT_ARM_BOOT_UART_CLK_IN_HZ	V2M_IOFPGA_UART0_CLK_IN_HZ
+
+#define PLAT_ARM_RUN_UART_BASE		V2M_IOFPGA_UART1_BASE
+#define PLAT_ARM_RUN_UART_CLK_IN_HZ	V2M_IOFPGA_UART1_CLK_IN_HZ
+
+#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_TSP_UART_BASE		V2M_IOFPGA_UART2_BASE
+#define PLAT_ARM_TSP_UART_CLK_IN_HZ	V2M_IOFPGA_UART2_CLK_IN_HZ
+
+/* CCI related constants */
+#define PLAT_FVP_R_CCI400_BASE		UL(0xac090000)
+#define PLAT_FVP_R_CCI400_CLUS0_SL_PORT	3
+#define PLAT_FVP_R_CCI400_CLUS1_SL_PORT	4
+
+/* CCI-500/CCI-550 on Base platform */
+#define PLAT_FVP_R_CCI5XX_BASE		UL(0xaa000000)
+#define PLAT_FVP_R_CCI5XX_CLUS0_SL_PORT	5
+#define PLAT_FVP_R_CCI5XX_CLUS1_SL_PORT	6
+
+/* CCN related constants. Only CCN 502 is currently supported */
+#define PLAT_ARM_CCN_BASE		UL(0xae000000)
+#define PLAT_ARM_CLUSTER_TO_CCN_ID_MAP	1, 5, 7, 11
+
+/* System timer related constants */
+#define PLAT_ARM_NSTIMER_FRAME_ID	U(1)
+
+/* Mailbox base address */
+#define PLAT_ARM_TRUSTED_MAILBOX_BASE	ARM_TRUSTED_SRAM_BASE
+
+
+/* TrustZone controller related constants
+ *
+ * Currently only filters 0 and 2 are connected on Base FVP_R.
+ * Filter 0 : CPU clusters (no access to DRAM by default)
+ * Filter 1 : not connected
+ * Filter 2 : LCDs (access to VRAM allowed by default)
+ * Filter 3 : not connected
+ * Programming unconnected filters will have no effect at the
+ * moment. These filter could, however, be connected in future.
+ * So care should be taken not to configure the unused filters.
+ *
+ * Allow only non-secure access to all DRAM to supported devices.
+ * Give access to the CPUs and Virtio. Some devices
+ * would normally use the default ID so allow that too.
+ */
+#define PLAT_ARM_TZC_BASE		UL(0xaa4a0000)
+#define PLAT_ARM_TZC_FILTERS		TZC_400_REGION_ATTR_FILTER_BIT(0)
+
+#define PLAT_ARM_TZC_NS_DEV_ACCESS	(				\
+		TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_DEFAULT)	|	\
+		TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_PCI)		|	\
+		TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_AP)		|	\
+		TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_VIRTIO)	|	\
+		TZC_REGION_ACCESS_RDWR(FVP_R_NSAID_VIRTIO_OLD))
+
+/*
+ * GIC related constants to cater for both GICv2 and GICv3 instances of an
+ * FVP_R. They could be overridden at runtime in case the FVP_R implements the
+ * legacy VE memory map.
+ */
+#define PLAT_ARM_GICD_BASE		BASE_GICD_BASE
+#define PLAT_ARM_GICR_BASE		BASE_GICR_BASE
+#define PLAT_ARM_GICC_BASE		BASE_GICC_BASE
+
+#define PLAT_ARM_SP_IMAGE_STACK_BASE	(PLAT_SP_IMAGE_NS_BUF_BASE +	\
+					 PLAT_SP_IMAGE_NS_BUF_SIZE)
+
+#define PLAT_SP_PRI			PLAT_RAS_PRI
+
+/*
+ * Physical and virtual address space limits for MPU in AARCH64 & AARCH32 modes
+ */
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 36)
+
+#define ARM_SOC_CONTINUATION_SHIFT	U(24)
+#define ARM_SOC_IDENTIFICATION_SHIFT	U(16)
+
+#endif /* FVP_R_PLATFORM_DEF_H */
diff --git a/plat/arm/board/fvp_r/platform.mk b/plat/arm/board/fvp_r/platform.mk
new file mode 100644
index 0000000..8f5878f
--- /dev/null
+++ b/plat/arm/board/fvp_r/platform.mk
@@ -0,0 +1,146 @@
+#
+# Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Only aarch64 ARCH supported for FVP_R
+ARCH	:= aarch64
+
+# Override to exclude BL2, BL2U, BL31, and BL33 for FVP_R
+override NEED_BL2	:= no
+override NEED_BL2U	:= no
+override NEED_BL31	:= no
+NEED_BL32		:= no
+
+override CTX_INCLUDE_AARCH32_REGS	:=	0
+
+# Default cluster count for FVP_R
+FVP_R_CLUSTER_COUNT	:= 2
+
+# Default number of CPUs per cluster on FVP_R
+FVP_R_MAX_CPUS_PER_CLUSTER	:= 4
+
+# Default number of threads per CPU on FVP_R
+FVP_R_MAX_PE_PER_CPU	:= 1
+
+# Use MPU-based memory management:
+XLAT_MPU_LIB_V1		:=	1
+
+# Pass FVP_R_CLUSTER_COUNT to the build system.
+$(eval $(call add_define,FVP_R_CLUSTER_COUNT))
+
+# Pass FVP_R_MAX_CPUS_PER_CLUSTER to the build system.
+$(eval $(call add_define,FVP_R_MAX_CPUS_PER_CLUSTER))
+
+# Pass FVP_R_MAX_PE_PER_CPU to the build system.
+$(eval $(call add_define,FVP_R_MAX_PE_PER_CPU))
+
+# Sanity check the cluster count and if FVP_R_CLUSTER_COUNT <= 2,
+# choose the CCI driver , else the CCN driver
+ifeq ($(FVP_R_CLUSTER_COUNT), 0)
+$(error "Incorrect cluster count specified for FVP_R port")
+else ifeq ($(FVP_R_CLUSTER_COUNT),$(filter $(FVP_R_CLUSTER_COUNT),1 2))
+FVP_R_INTERCONNECT_DRIVER := FVP_R_CCI
+else
+FVP_R_INTERCONNECT_DRIVER := FVP_R_CCN
+endif
+
+$(eval $(call add_define,FVP_R_INTERCONNECT_DRIVER))
+
+ifeq (${FVP_R_INTERCONNECT_DRIVER}, FVP_R_CCI)
+FVP_R_INTERCONNECT_SOURCES	:= 	drivers/arm/cci/cci.c
+else ifeq (${FVP_R_INTERCONNECT_DRIVER}, FVP_R_CCN)
+FVP_R_INTERCONNECT_SOURCES	:= 	drivers/arm/ccn/ccn.c		\
+					plat/arm/common/arm_ccn.c
+else
+$(error "Incorrect CCN driver chosen on FVP_R port")
+endif
+
+include plat/arm/board/common/board_common.mk
+include plat/arm/common/arm_common.mk
+
+PLAT_INCLUDES		:=	-Iplat/arm/board/fvp_r/include
+
+FVP_R_BL_COMMON_SOURCES	:=	plat/arm/board/fvp_r/fvp_r_common.c		\
+				plat/arm/board/fvp_r/fvp_r_context_mgmt.c	\
+				plat/arm/board/fvp_r/fvp_r_context.S		\
+				plat/arm/board/fvp_r/fvp_r_debug.S		\
+				plat/arm/board/fvp_r/fvp_r_err.c		\
+				plat/arm/board/fvp_r/fvp_r_helpers.S		\
+				plat/arm/board/fvp_r/fvp_r_misc_helpers.S	\
+				plat/arm/board/fvp_r/fvp_r_pauth_helpers.S
+
+FVP_R_BL1_SOURCES	:=	plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c	\
+				plat/arm/board/fvp_r/fvp_r_bl1_setup.c		\
+				plat/arm/board/fvp_r/fvp_r_io_storage.c		\
+				plat/arm/board/fvp_r/fvp_r_bl1_context_mgmt.c	\
+				plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S	\
+				plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S	\
+				plat/arm/board/fvp_r/fvp_r_bl1_main.c
+
+FVP_R_CPU_LIBS		:=	lib/cpus/${ARCH}/aem_generic.S
+
+FVP_R_DYNC_CFG_SOURCES	:=	common/fdt_wrappers.c				\
+				common/uuid.c					\
+				plat/arm/common/arm_dyn_cfg.c			\
+				plat/arm/common/arm_dyn_cfg_helpers.c
+
+ifeq (${TRUSTED_BOARD_BOOT},1)
+FVP_R_AUTH_SOURCES	:=	drivers/auth/auth_mod.c				\
+				drivers/auth/crypto_mod.c			\
+				drivers/auth/img_parser_mod.c			\
+				lib/fconf/fconf_tbbr_getter.c			\
+				bl1/tbbr/tbbr_img_desc.c			\
+				plat/arm/common/arm_bl1_fwu.c			\
+				plat/common/tbbr/plat_tbbr.c			\
+				drivers/auth/tbbr/tbbr_cot_bl1_r64.c		\
+				drivers/auth/tbbr/tbbr_cot_common.c		\
+				plat/arm/board/common/board_arm_trusted_boot.c	\
+				plat/arm/board/common/rotpk/arm_dev_rotpk.S	\
+				plat/arm/board/fvp_r/fvp_r_trusted_boot.c
+
+FVP_R_BL1_SOURCES	+=	${MBEDTLS_SOURCES}				\
+				${FVP_R_AUTH_SOURCES}
+endif
+
+ifeq (${USE_SP804_TIMER},1)
+FVP_R_BL_COMMON_SOURCES		+=	drivers/arm/sp804/sp804_delay_timer.c
+else
+FVP_R_BL_COMMON_SOURCES		+=	drivers/delay_timer/generic_delay_timer.c
+endif
+
+# Enable Activity Monitor Unit extensions by default
+ENABLE_AMU			:=	1
+
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+FVP_R_BL_COMMON_SOURCES	+=	plat/arm/board/fvp_r/fvp_r_stack_protector.c
+endif
+
+override BL1_SOURCES	:=	drivers/arm/sp805/sp805.c			\
+				drivers/cfi/v2m/v2m_flash.c			\
+				drivers/delay_timer/delay_timer.c		\
+				drivers/io/io_fip.c				\
+				drivers/io/io_memmap.c				\
+				drivers/io/io_storage.c				\
+				drivers/io/io_semihosting.c			\
+				lib/cpus/aarch64/cpu_helpers.S			\
+				lib/cpus/errata_report.c			\
+				lib/cpus/aarch64/dsu_helpers.S			\
+				lib/el3_runtime/aarch64/context.S		\
+				lib/el3_runtime/aarch64/context_mgmt.c		\
+				lib/fconf/fconf.c				\
+				lib/fconf/fconf_dyn_cfg_getter.c		\
+				lib/semihosting/semihosting.c			\
+				lib/semihosting/${ARCH}/semihosting_call.S	\
+				plat/arm/common/arm_bl1_setup.c			\
+				plat/arm/common/arm_err.c			\
+				plat/arm/common/arm_io_storage.c		\
+				plat/arm/common/fconf/arm_fconf_io.c		\
+				plat/common/plat_bl1_common.c			\
+				plat/common/aarch64/platform_up_stack.S		\
+				${FVP_R_BL1_SOURCES}				\
+				${FVP_R_BL_COMMON_SOURCES}			\
+				${FVP_R_CPU_LIBS}				\
+				${FVP_R_DYNC_CFG_SOURCES}			\
+				${FVP_R_INTERCONNECT_SOURCES}
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index 5299a7b..d61ba5d 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -53,12 +53,13 @@
 #define PLAT_ARM_DRAM2_BASE		ULL(0x880000000)
 #define PLAT_ARM_DRAM2_SIZE		ULL(0x180000000)
 
-#define PLAT_HW_CONFIG_DTB_BASE		ULL(0x82000000)
-#define PLAT_HW_CONFIG_DTB_SIZE		ULL(0x00008000) /* 32KB */
+/* Range of kernel DTB load address */
+#define JUNO_DTB_DRAM_MAP_START		ULL(0x82000000)
+#define JUNO_DTB_DRAM_MAP_SIZE		ULL(0x00008000) /* 32KB */
 
 #define ARM_DTB_DRAM_NS			MAP_REGION_FLAT(		\
-					PLAT_HW_CONFIG_DTB_BASE,	\
-					PLAT_HW_CONFIG_DTB_SIZE,	\
+					JUNO_DTB_DRAM_MAP_START,	\
+					JUNO_DTB_DRAM_MAP_SIZE,		\
 					MT_MEMORY | MT_RO | MT_NS)
 
 /* virtual address used by dynamic mem_protect for chunk_base */
diff --git a/plat/arm/board/juno/juno_bl1_setup.c b/plat/arm/board/juno/juno_bl1_setup.c
index 2234055..a9d5cc3 100644
--- a/plat/arm/board/juno/juno_bl1_setup.c
+++ b/plat/arm/board/juno/juno_bl1_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -62,11 +62,11 @@
  ******************************************************************************/
 bool plat_arm_bl1_fwu_needed(void)
 {
-	const int32_t *nv_flags_ptr = (const int32_t *)V2M_SYS_NVFLAGS_ADDR;
+	int32_t nv_flags = (int32_t)mmio_read_32(V2M_SYS_NVFLAGS_ADDR);
 
 	/* Check if TOC is invalid or watchdog reset happened. */
-	return (!arm_io_is_toc_valid() || (((*nv_flags_ptr == -EAUTH) ||
-		(*nv_flags_ptr == -ENOENT)) && is_watchdog_reset()));
+	return (!arm_io_is_toc_valid() || (((nv_flags == -EAUTH) ||
+		(nv_flags == -ENOENT)) && is_watchdog_reset()));
 }
 
 /*******************************************************************************
@@ -86,13 +86,11 @@
  ******************************************************************************/
 __dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved)
 {
-	unsigned int *nv_flags_clr = (unsigned int *)
-			(V2M_SYSREGS_BASE + V2M_SYS_NVFLAGSCLR);
-	unsigned int *nv_flags_ptr = (unsigned int *)
-			(V2M_SYSREGS_BASE + V2M_SYS_NVFLAGS);
+	uint32_t nv_flags = mmio_read_32(V2M_SYS_NVFLAGS_ADDR);
 
 	/* Clear the NV flags register. */
-	*nv_flags_clr = *nv_flags_ptr;
+	mmio_write_32((V2M_SYSREGS_BASE + V2M_SYS_NVFLAGSCLR),
+		      nv_flags);
 
 	/* Setup the watchdog to reset the system as soon as possible */
 	sp805_refresh(ARM_SP805_TWDG_BASE, 1U);
diff --git a/plat/arm/board/juno/juno_err.c b/plat/arm/board/juno/juno_err.c
index 60699cc..02d751e 100644
--- a/plat/arm/board/juno/juno_err.c
+++ b/plat/arm/board/juno/juno_err.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,10 +16,8 @@
  */
 void __dead2 plat_arm_error_handler(int err)
 {
-	uint32_t *flags_ptr = (uint32_t *)V2M_SYS_NVFLAGS_ADDR;
-
 	/* Propagate the err code in the NV-flags register */
-	*flags_ptr = err;
+	mmio_write_32(V2M_SYS_NVFLAGS_ADDR, (uint32_t)err);
 
 	/* Setup the watchdog to reset the system as soon as possible */
 	sp805_refresh(ARM_SP805_TWDG_BASE, 1U);
diff --git a/plat/arm/board/rdn2/include/platform_def.h b/plat/arm/board/rdn2/include/platform_def.h
index 30a0c5c..194814f 100644
--- a/plat/arm/board/rdn2/include/platform_def.h
+++ b/plat/arm/board/rdn2/include/platform_def.h
@@ -44,6 +44,8 @@
 #define TZC_NSAID_ALL_AP		U(0)
 #define TZC_NSAID_PCI			U(1)
 #define TZC_NSAID_HDLCD0		U(2)
+#define TZC_NSAID_DMA			U(5)
+#define TZC_NSAID_DMA2			U(8)
 #define TZC_NSAID_CLCD			U(7)
 #define TZC_NSAID_AP			U(9)
 #define TZC_NSAID_VIRTIO		U(15)
@@ -52,6 +54,8 @@
 		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_ALL_AP)) | \
 		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_HDLCD0)) | \
 		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_PCI))    | \
+		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_DMA))    | \
+		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_DMA2))   | \
 		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_AP))     | \
 		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_CLCD))   | \
 		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_VIRTIO))
diff --git a/plat/arm/board/rdn2/platform.mk b/plat/arm/board/rdn2/platform.mk
index 794f897..5b24c32 100644
--- a/plat/arm/board/rdn2/platform.mk
+++ b/plat/arm/board/rdn2/platform.mk
@@ -3,7 +3,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
-# RD-N2 platform uses GIC-Clayton which is based on GICv4.1
+# RD-N2 platform uses GIC-700 which is based on GICv4.1
 GIC_ENABLE_V4_EXTN	:=	1
 
 include plat/arm/css/sgi/sgi-common.mk
diff --git a/plat/arm/board/rdv1/platform.mk b/plat/arm/board/rdv1/platform.mk
index 1ae85de..11f5212 100644
--- a/plat/arm/board/rdv1/platform.mk
+++ b/plat/arm/board/rdv1/platform.mk
@@ -3,7 +3,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
-# RD-V1 platform uses GIC-Clayton which is based on GICv4.1
+# RD-V1 platform uses GIC-700 which is based on GICv4.1
 GIC_ENABLE_V4_EXTN	:=	1
 
 include plat/arm/css/sgi/sgi-common.mk
diff --git a/plat/arm/board/tc0/fdts/tc0_fw_config.dts b/plat/arm/board/tc/fdts/tc_fw_config.dts
similarity index 84%
rename from plat/arm/board/tc0/fdts/tc0_fw_config.dts
rename to plat/arm/board/tc/fdts/tc_fw_config.dts
index 4b6abd4..a84c7f8 100644
--- a/plat/arm/board/tc0/fdts/tc0_fw_config.dts
+++ b/plat/arm/board/tc/fdts/tc_fw_config.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -26,7 +26,7 @@
 
 		hw-config {
 			load-address = <0x0 0x83000000>;
-			max-size = <0x01000000>;
+			max-size = <0x8000>;
 			id = <HW_CONFIG_ID>;
 		};
 	};
diff --git a/plat/arm/board/tc0/fdts/tc0_spmc_manifest.dts b/plat/arm/board/tc/fdts/tc_spmc_manifest.dts
similarity index 97%
rename from plat/arm/board/tc0/fdts/tc0_spmc_manifest.dts
rename to plat/arm/board/tc/fdts/tc_spmc_manifest.dts
index 44c7008..a8592f6 100644
--- a/plat/arm/board/tc0/fdts/tc0_spmc_manifest.dts
+++ b/plat/arm/board/tc/fdts/tc_spmc_manifest.dts
@@ -13,7 +13,7 @@
 	attribute {
 		spmc_id = <0x8000>;
 		maj_ver = <0x1>;
-		min_ver = <0x0>;
+		min_ver = <0x1>;
 		exec_state = <0x0>;
 		load_address = <0x0 0xfd000000>;
 		entrypoint = <0x0 0xfd000000>;
@@ -110,7 +110,7 @@
 		};
 	};
 
-	/* 32MB of TC0_TZC_DRAM1_BASE */
+	/* 32MB of TC_TZC_DRAM1_BASE */
 	memory@fd000000 {
 		device_type = "memory";
 		reg = <0x0 0xfd000000 0x2000000>;
diff --git a/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts b/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts
similarity index 92%
rename from plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts
rename to plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts
index 0830d5c..92e2ddd 100644
--- a/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts
+++ b/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,7 +13,7 @@
 	attribute {
 		spmc_id = <0x8000>;
 		maj_ver = <0x1>;
-		min_ver = <0x0>;
+		min_ver = <0x1>;
 		exec_state = <0x0>;
 		load_address = <0x0 0xfd000000>;
 		entrypoint = <0x0 0xfd000000>;
@@ -36,7 +36,7 @@
 #ifdef TS_SP_FW_CONFIG
 		vm2 {
 			is_ffa_partition;
-			debug_name = "secure-storage";
+			debug_name = "internal-trusted-storage";
 			load_address = <0xfee00000>;
 			vcpu_count = <1>;
 			mem_size = <2097152>; /* 2MB TZC DRAM */
@@ -116,7 +116,7 @@
 		};
 	};
 
-	/* 32MB of TC0_TZC_DRAM1_BASE */
+	/* 32MB of TC_TZC_DRAM1_BASE */
 	memory@fd000000 {
 		device_type = "memory";
 		reg = <0x0 0xfd000000 0x2000000>;
diff --git a/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts b/plat/arm/board/tc/fdts/tc_tb_fw_config.dts
similarity index 89%
rename from plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts
rename to plat/arm/board/tc/fdts/tc_tb_fw_config.dts
index 28ed7ae..af80550 100644
--- a/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts
+++ b/plat/arm/board/tc/fdts/tc_tb_fw_config.dts
@@ -4,6 +4,8 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <lib/libc/cdefs.h>
+
 /dts-v1/;
 
 / {
@@ -27,8 +29,11 @@
 
 	secure-partitions {
 		compatible = "arm,sp";
+#ifdef ARM_BL2_SP_LIST_DTS
+	#include __XSTRING(ARM_BL2_SP_LIST_DTS)
+#else
 #ifdef TS_SP_FW_CONFIG
-		secure-storage {
+		internal-trusted-storage {
 		       uuid = "dc1eef48-b17a-4ccf-ac8b-dfcff7711b14";
 		       load-address = <0xfee00000>;
 		};
@@ -60,5 +65,6 @@
 			load-address = <0xfe200000>;
 		};
 #endif
+#endif /* ARM_BL2_SP_LIST_DTS */
 	};
 };
diff --git a/plat/arm/board/tc0/include/plat_macros.S b/plat/arm/board/tc/include/plat_macros.S
similarity index 100%
rename from plat/arm/board/tc0/include/plat_macros.S
rename to plat/arm/board/tc/include/plat_macros.S
diff --git a/plat/arm/board/tc0/include/platform_def.h b/plat/arm/board/tc/include/platform_def.h
similarity index 80%
rename from plat/arm/board/tc0/include/platform_def.h
rename to plat/arm/board/tc/include/platform_def.h
index b169d77..ccabced 100644
--- a/plat/arm/board/tc0/include/platform_def.h
+++ b/plat/arm/board/tc/include/platform_def.h
@@ -29,38 +29,46 @@
  *   - BL32_BASE when SPD_spmd is enabled
  *   - Region to load Trusted OS
  */
-#define TC0_TZC_DRAM1_BASE		(ARM_AP_TZC_DRAM1_BASE -	\
-					 TC0_TZC_DRAM1_SIZE)
-#define TC0_TZC_DRAM1_SIZE		UL(0x02000000)	/* 32 MB */
-#define TC0_TZC_DRAM1_END		(TC0_TZC_DRAM1_BASE +		\
-					 TC0_TZC_DRAM1_SIZE - 1)
+#define TC_TZC_DRAM1_BASE		(ARM_AP_TZC_DRAM1_BASE -	\
+					 TC_TZC_DRAM1_SIZE)
+#define TC_TZC_DRAM1_SIZE		UL(0x02000000)	/* 32 MB */
+#define TC_TZC_DRAM1_END		(TC_TZC_DRAM1_BASE +		\
+					 TC_TZC_DRAM1_SIZE - 1)
 
-#define TC0_NS_DRAM1_BASE		ARM_DRAM1_BASE
-#define TC0_NS_DRAM1_SIZE		(ARM_DRAM1_SIZE -		\
+#define TC_NS_DRAM1_BASE		ARM_DRAM1_BASE
+#define TC_NS_DRAM1_SIZE		(ARM_DRAM1_SIZE -		\
 					 ARM_TZC_DRAM1_SIZE -		\
-					 TC0_TZC_DRAM1_SIZE)
-#define TC0_NS_DRAM1_END		(TC0_NS_DRAM1_BASE +		\
-					 TC0_NS_DRAM1_SIZE - 1)
+					 TC_TZC_DRAM1_SIZE)
+#define TC_NS_DRAM1_END		(TC_NS_DRAM1_BASE +		\
+					 TC_NS_DRAM1_SIZE - 1)
 
 /*
- * Mappings for TC0 DRAM1 (non-secure) and TC0 TZC DRAM1 (secure)
+ * Mappings for TC DRAM1 (non-secure) and TC TZC DRAM1 (secure)
  */
-#define TC0_MAP_NS_DRAM1		MAP_REGION_FLAT(		\
-						TC0_NS_DRAM1_BASE,	\
-						TC0_NS_DRAM1_SIZE,	\
+#define TC_MAP_NS_DRAM1		MAP_REGION_FLAT(		\
+						TC_NS_DRAM1_BASE,	\
+						TC_NS_DRAM1_SIZE,	\
 						MT_MEMORY | MT_RW | MT_NS)
 
 
-#define TC0_MAP_TZC_DRAM1		MAP_REGION_FLAT(		\
-						TC0_TZC_DRAM1_BASE,	\
-						TC0_TZC_DRAM1_SIZE,	\
+#define TC_MAP_TZC_DRAM1		MAP_REGION_FLAT(		\
+						TC_TZC_DRAM1_BASE,	\
+						TC_TZC_DRAM1_SIZE,	\
 						MT_MEMORY | MT_RW | MT_SECURE)
+
+#define PLAT_HW_CONFIG_DTB_BASE	ULL(0x83000000)
+#define PLAT_HW_CONFIG_DTB_SIZE	ULL(0x8000)
+
+#define PLAT_DTB_DRAM_NS MAP_REGION_FLAT(	\
+					PLAT_HW_CONFIG_DTB_BASE,	\
+					PLAT_HW_CONFIG_DTB_SIZE,	\
+					MT_MEMORY | MT_RO | MT_NS)
 /*
- * Max size of SPMC is 2MB for tc0. With SPMD enabled this value corresponds to
+ * Max size of SPMC is 2MB for tc. With SPMD enabled this value corresponds to
  * max size of BL32 image.
  */
 #if defined(SPD_spmd)
-#define PLAT_ARM_SPMC_BASE		TC0_TZC_DRAM1_BASE
+#define PLAT_ARM_SPMC_BASE		TC_TZC_DRAM1_BASE
 #define PLAT_ARM_SPMC_SIZE		UL(0x200000)  /* 2 MB */
 #endif
 
@@ -122,7 +130,7 @@
  * calculated using the current BL31 PROGBITS debug size plus the sizes of
  * BL2 and BL1-RW
  */
-#define PLAT_ARM_MAX_BL31_SIZE		0x3B000
+#define PLAT_ARM_MAX_BL31_SIZE		0x3F000
 
 /*
  * Size of cacheable stacks
@@ -152,18 +160,18 @@
 #endif
 
 
-#define TC0_DEVICE_BASE			0x21000000
-#define TC0_DEVICE_SIZE			0x5f000000
+#define TC_DEVICE_BASE			0x21000000
+#define TC_DEVICE_SIZE			0x5f000000
 
-// TC0_MAP_DEVICE covers different peripherals
+// TC_MAP_DEVICE covers different peripherals
 // available to the platform
-#define TC0_MAP_DEVICE	MAP_REGION_FLAT(		\
-					TC0_DEVICE_BASE,	\
-					TC0_DEVICE_SIZE,	\
+#define TC_MAP_DEVICE	MAP_REGION_FLAT(		\
+					TC_DEVICE_BASE,	\
+					TC_DEVICE_SIZE,	\
 					MT_DEVICE | MT_RW | MT_SECURE)
 
 
-#define TC0_FLASH0_RO	MAP_REGION_FLAT(V2M_FLASH0_BASE,\
+#define TC_FLASH0_RO	MAP_REGION_FLAT(V2M_FLASH0_BASE,\
 						V2M_FLASH0_SIZE,	\
 						MT_DEVICE | MT_RO | MT_SECURE)
 
@@ -250,14 +258,14 @@
 		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_DEFAULT))
 
 /*
- * The first region below, TC0_TZC_DRAM1_BASE (0xfd000000) to
+ * The first region below, TC_TZC_DRAM1_BASE (0xfd000000) to
  * ARM_SCP_TZC_DRAM1_END (0xffffffff) will mark the last 48 MB of DRAM as
  * secure. The second region gives non secure access to rest of DRAM.
  */
-#define TC0_TZC_REGIONS_DEF						\
-	{TC0_TZC_DRAM1_BASE, ARM_SCP_TZC_DRAM1_END,			\
+#define TC_TZC_REGIONS_DEF						\
+	{TC_TZC_DRAM1_BASE, ARM_SCP_TZC_DRAM1_END,			\
 		TZC_REGION_S_RDWR, PLAT_ARM_TZC_NS_DEV_ACCESS},		\
-	{TC0_NS_DRAM1_BASE, TC0_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \
+	{TC_NS_DRAM1_BASE, TC_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \
 		PLAT_ARM_TZC_NS_DEV_ACCESS}
 
 /* virtual address used by dynamic mem_protect for chunk_base */
diff --git a/plat/arm/board/tc0/include/tc0_helpers.S b/plat/arm/board/tc/include/tc_helpers.S
similarity index 96%
rename from plat/arm/board/tc0/include/tc0_helpers.S
rename to plat/arm/board/tc/include/tc_helpers.S
index 90623a2..5f54856 100644
--- a/plat/arm/board/tc0/include/tc0_helpers.S
+++ b/plat/arm/board/tc/include/tc_helpers.S
@@ -15,7 +15,7 @@
 	/* ---------------------------------------------------------------------
 	 * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
 	 *
-	 * Function to calculate the core position on TC0.
+	 * Function to calculate the core position on TC.
 	 *
 	 * (ClusterId * PLAT_MAX_CPUS_PER_CLUSTER * PLAT_MAX_PE_PER_CPU) +
 	 * (CPUId * PLAT_MAX_PE_PER_CPU) +
diff --git a/plat/arm/board/tc/include/tc_plat.h b/plat/arm/board/tc/include/tc_plat.h
new file mode 100644
index 0000000..28c0308
--- /dev/null
+++ b/plat/arm/board/tc/include/tc_plat.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TC_PLAT_H
+#define TC_PLAT_H
+
+void tc_bl31_common_platform_setup(void);
+
+#endif /* TC_PLAT_H */
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
new file mode 100644
index 0000000..7ebf639
--- /dev/null
+++ b/plat/arm/board/tc/platform.mk
@@ -0,0 +1,144 @@
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ifeq ($(filter ${TARGET_PLATFORM}, 0 1),)
+        $(error TARGET_PLATFORM must be 0 or 1)
+endif
+
+CSS_LOAD_SCP_IMAGES	:=	1
+
+CSS_USE_SCMI_SDS_DRIVER	:=	1
+
+RAS_EXTENSION		:=	0
+
+SDEI_SUPPORT		:=	0
+
+EL3_EXCEPTION_HANDLING	:=	0
+
+HANDLE_EA_EL3_FIRST	:=	0
+
+# 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
+
+GIC_ENABLE_V4_EXTN	:=      1
+
+# GIC-600 configuration
+GICV3_SUPPORT_GIC600	:=	1
+
+# Enable SVE
+ENABLE_SVE_FOR_NS	:=	1
+ENABLE_SVE_FOR_SWD	:=	1
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+ENT_GIC_SOURCES		:=	${GICV3_SOURCES}		\
+				plat/common/plat_gicv3.c	\
+				plat/arm/common/arm_gicv3.c
+
+override NEED_BL2U	:=	no
+
+override ARM_PLAT_MT	:=	1
+
+TC_BASE	=	plat/arm/board/tc
+
+PLAT_INCLUDES		+=	-I${TC_BASE}/include/
+
+# Common CPU libraries
+TC_CPU_SOURCES	:=	lib/cpus/aarch64/cortex_a510.S
+
+# CPU libraries for TARGET_PLATFORM=0
+ifeq (${TARGET_PLATFORM}, 0)
+TC_CPU_SOURCES	+=	lib/cpus/aarch64/cortex_a710.S \
+			lib/cpus/aarch64/cortex_x2.S
+endif
+
+# CPU libraries for TARGET_PLATFORM=1
+ifeq (${TARGET_PLATFORM}, 1)
+TC_CPU_SOURCES	+=	lib/cpus/aarch64/cortex_makalu.S \
+			lib/cpus/aarch64/cortex_makalu_elp_arm.S
+endif
+
+INTERCONNECT_SOURCES	:=	${TC_BASE}/tc_interconnect.c
+
+PLAT_BL_COMMON_SOURCES	+=	${TC_BASE}/tc_plat.c	\
+				${TC_BASE}/include/tc_helpers.S
+
+BL1_SOURCES		+=	${INTERCONNECT_SOURCES}	\
+				${TC_CPU_SOURCES}	\
+				${TC_BASE}/tc_trusted_boot.c	\
+				${TC_BASE}/tc_err.c	\
+				drivers/arm/sbsa/sbsa.c
+
+
+BL2_SOURCES		+=	${TC_BASE}/tc_security.c	\
+				${TC_BASE}/tc_err.c		\
+				${TC_BASE}/tc_trusted_boot.c		\
+				${TC_BASE}/tc_bl2_setup.c		\
+				lib/utils/mem_region.c			\
+				drivers/arm/tzc/tzc400.c		\
+				plat/arm/common/arm_tzc400.c		\
+				plat/arm/common/arm_nor_psci_mem_protect.c
+
+BL31_SOURCES		+=	${INTERCONNECT_SOURCES}	\
+				${TC_CPU_SOURCES}	\
+				${ENT_GIC_SOURCES}			\
+				${TC_BASE}/tc_bl31_setup.c	\
+				${TC_BASE}/tc_topology.c	\
+				common/fdt_wrappers.c			\
+				lib/fconf/fconf.c			\
+				lib/fconf/fconf_dyn_cfg_getter.c	\
+				drivers/cfi/v2m/v2m_flash.c		\
+				lib/utils/mem_region.c			\
+				plat/arm/common/arm_nor_psci_mem_protect.c
+
+# Add the FDT_SOURCES and options for Dynamic Config
+FDT_SOURCES		+=	${TC_BASE}/fdts/${PLAT}_fw_config.dts	\
+				${TC_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_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}))
+
+ifeq (${SPD},spmd)
+ifeq ($(ARM_SPMC_MANIFEST_DTS),)
+ARM_SPMC_MANIFEST_DTS	:=	${TC_BASE}/fdts/${PLAT}_spmc_manifest.dts
+endif
+
+FDT_SOURCES		+=	${ARM_SPMC_MANIFEST_DTS}
+TC_TOS_FW_CONFIG	:=	${BUILD_PLAT}/fdts/$(notdir $(basename ${ARM_SPMC_MANIFEST_DTS})).dtb
+
+# Add the TOS_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TC_TOS_FW_CONFIG},--tos-fw-config,${TC_TOS_FW_CONFIG}))
+endif
+
+#Device tree
+TC_HW_CONFIG_DTS	:=	fdts/tc.dts
+TC_HW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}.dtb
+FDT_SOURCES		+=	${TC_HW_CONFIG_DTS}
+$(eval TC_HW_CONFIG	:=	${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(TC_HW_CONFIG_DTS)))
+
+# Add the HW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TC_HW_CONFIG},--hw-config,${TC_HW_CONFIG}))
+
+override CTX_INCLUDE_AARCH32_REGS	:= 0
+
+override CTX_INCLUDE_PAUTH_REGS	:= 1
+
+override ENABLE_SPE_FOR_LOWER_ELS	:= 0
+
+override ENABLE_AMU := 1
+
+include plat/arm/common/arm_common.mk
+include plat/arm/css/common/css_common.mk
+include plat/arm/soc/common/soc_css.mk
+include plat/arm/board/common/board_common.mk
diff --git a/plat/arm/board/tc/tc_bl2_setup.c b/plat/arm/board/tc/tc_bl2_setup.c
new file mode 100644
index 0000000..74ef569
--- /dev/null
+++ b/plat/arm/board/tc/tc_bl2_setup.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * This function returns the list of executable images
+ ******************************************************************************/
+struct bl_params *plat_get_next_bl_params(void)
+{
+	struct bl_params *arm_bl_params = arm_get_next_bl_params();
+
+	const struct dyn_cfg_dtb_info_t *fw_config_info;
+	bl_mem_params_node_t *param_node;
+	uintptr_t fw_config_base = 0U;
+	entry_point_info_t *ep_info;
+
+	/* Get BL31 image node */
+	param_node = get_bl_mem_params_node(BL31_IMAGE_ID);
+	assert(param_node != NULL);
+
+	/* Get fw_config load address */
+	fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID);
+	assert(fw_config_info != NULL);
+
+	fw_config_base = fw_config_info->config_addr;
+	assert(fw_config_base != 0U);
+
+	/*
+	 * Get the entry point info of BL31 image and override
+	 * arg1 of entry point info with fw_config base address
+	 */
+	ep_info = &param_node->ep_info;
+	ep_info->args.arg1 = (uint32_t)fw_config_base;
+
+	return arm_bl_params;
+}
diff --git a/plat/arm/board/tc/tc_bl31_setup.c b/plat/arm/board/tc/tc_bl31_setup.c
new file mode 100644
index 0000000..0523ef8
--- /dev/null
+++ b/plat/arm/board/tc/tc_bl31_setup.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <libfdt.h>
+#include <tc_plat.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/css/css_mhu_doorbell.h>
+#include <drivers/arm/css/scmi.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+static scmi_channel_plat_info_t tc_scmi_plat_info[] = {
+	{
+		.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
+		.db_reg_addr = PLAT_CSS_MHU_BASE + SENDER_REG_SET(0),
+		.db_preserve_mask = 0xfffffffe,
+		.db_modify_mask = 0x1,
+		.ring_doorbell = &mhuv2_ring_doorbell,
+	}
+};
+
+void bl31_platform_setup(void)
+{
+	tc_bl31_common_platform_setup();
+}
+
+scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id)
+{
+
+	return &tc_scmi_plat_info[channel_id];
+
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				u_register_t arg2, u_register_t arg3)
+{
+	arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
+
+	/* Fill the properties struct with the info from the config dtb */
+	fconf_populate("FW_CONFIG", arg1);
+}
+
+void tc_bl31_common_platform_setup(void)
+{
+	arm_bl31_platform_setup();
+}
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+	return css_scmi_override_pm_ops(ops);
+}
+
+void __init bl31_plat_arch_setup(void)
+{
+	arm_bl31_plat_arch_setup();
+
+	/* HW_CONFIG was also loaded by BL2 */
+	const struct dyn_cfg_dtb_info_t *hw_config_info;
+
+	hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID);
+	assert(hw_config_info != NULL);
+
+	fconf_populate("HW_CONFIG", hw_config_info->config_addr);
+}
diff --git a/plat/arm/board/tc0/tc0_err.c b/plat/arm/board/tc/tc_err.c
similarity index 91%
rename from plat/arm/board/tc0/tc0_err.c
rename to plat/arm/board/tc/tc_err.c
index 83f2e9f..9ed7e92 100644
--- a/plat/arm/board/tc0/tc0_err.c
+++ b/plat/arm/board/tc/tc_err.c
@@ -7,7 +7,7 @@
 #include <plat/arm/common/plat_arm.h>
 
 /*
- * tc0 error handler
+ * tc error handler
  */
 void __dead2 plat_arm_error_handler(int err)
 {
diff --git a/plat/arm/board/tc0/tc0_interconnect.c b/plat/arm/board/tc/tc_interconnect.c
similarity index 100%
rename from plat/arm/board/tc0/tc0_interconnect.c
rename to plat/arm/board/tc/tc_interconnect.c
diff --git a/plat/arm/board/tc0/tc0_plat.c b/plat/arm/board/tc/tc_plat.c
similarity index 93%
rename from plat/arm/board/tc0/tc0_plat.c
rename to plat/arm/board/tc/tc_plat.c
index b5698c0..a9668e1 100644
--- a/plat/arm/board/tc0/tc0_plat.c
+++ b/plat/arm/board/tc/tc_plat.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -28,19 +28,19 @@
 #if IMAGE_BL1
 const mmap_region_t plat_arm_mmap[] = {
 	ARM_MAP_SHARED_RAM,
-	TC0_FLASH0_RO,
-	TC0_MAP_DEVICE,
+	TC_FLASH0_RO,
+	TC_MAP_DEVICE,
 	{0}
 };
 #endif
 #if IMAGE_BL2
 const mmap_region_t plat_arm_mmap[] = {
 	ARM_MAP_SHARED_RAM,
-	TC0_FLASH0_RO,
-	TC0_MAP_DEVICE,
-	TC0_MAP_NS_DRAM1,
+	TC_FLASH0_RO,
+	TC_MAP_DEVICE,
+	TC_MAP_NS_DRAM1,
 #if defined(SPD_spmd)
-	TC0_MAP_TZC_DRAM1,
+	TC_MAP_TZC_DRAM1,
 #endif
 #if ARM_BL31_IN_DRAM
 	ARM_MAP_BL31_SEC_DRAM,
@@ -62,7 +62,8 @@
 const mmap_region_t plat_arm_mmap[] = {
 	ARM_MAP_SHARED_RAM,
 	V2M_MAP_IOFPGA,
-	TC0_MAP_DEVICE,
+	TC_MAP_DEVICE,
+	PLAT_DTB_DRAM_NS,
 #if SPM_MM
 	ARM_SPM_BUF_EL3_MMAP,
 #endif
diff --git a/plat/arm/board/tc0/tc0_security.c b/plat/arm/board/tc/tc_security.c
similarity index 94%
rename from plat/arm/board/tc0/tc0_security.c
rename to plat/arm/board/tc/tc_security.c
index f543762..6a34501 100644
--- a/plat/arm/board/tc0/tc0_security.c
+++ b/plat/arm/board/tc/tc_security.c
@@ -8,7 +8,7 @@
 #include <platform_def.h>
 
 static const arm_tzc_regions_info_t tzc_regions[] = {
-	TC0_TZC_REGIONS_DEF,
+	TC_TZC_REGIONS_DEF,
 	{}
 };
 
diff --git a/plat/arm/board/tc0/tc0_topology.c b/plat/arm/board/tc/tc_topology.c
similarity index 96%
rename from plat/arm/board/tc0/tc0_topology.c
rename to plat/arm/board/tc/tc_topology.c
index 8cfc3b5..9e18da6 100644
--- a/plat/arm/board/tc0/tc0_topology.c
+++ b/plat/arm/board/tc/tc_topology.c
@@ -10,7 +10,7 @@
 /******************************************************************************
  * The power domain tree descriptor.
  ******************************************************************************/
-const unsigned char tc0_pd_tree_desc[] = {
+const unsigned char tc_pd_tree_desc[] = {
 	PLAT_ARM_CLUSTER_COUNT,
 	PLAT_MAX_CPUS_PER_CLUSTER,
 };
@@ -20,7 +20,7 @@
  ******************************************************************************/
 const unsigned char *plat_get_power_domain_tree_desc(void)
 {
-	return tc0_pd_tree_desc;
+	return tc_pd_tree_desc;
 }
 
 /*******************************************************************************
diff --git a/plat/arm/board/tc0/tc0_trusted_boot.c b/plat/arm/board/tc/tc_trusted_boot.c
similarity index 100%
rename from plat/arm/board/tc0/tc0_trusted_boot.c
rename to plat/arm/board/tc/tc_trusted_boot.c
diff --git a/plat/arm/board/tc0/include/tc0_plat.h b/plat/arm/board/tc0/include/tc0_plat.h
deleted file mode 100644
index f0cb431..0000000
--- a/plat/arm/board/tc0/include/tc0_plat.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef tc0_bl31_common_platform_setup_PLAT_H
-#define tc0_bl31_common_platform_setup_PLAT_H
-
-void tc0_bl31_common_platform_setup(void);
-
-#endif /* tc0_bl31_common_platform_setup_PLAT_H */
diff --git a/plat/arm/board/tc0/platform.mk b/plat/arm/board/tc0/platform.mk
deleted file mode 100644
index 814ccd3..0000000
--- a/plat/arm/board/tc0/platform.mk
+++ /dev/null
@@ -1,120 +0,0 @@
-# Copyright (c) 2020-2021, Arm Limited. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-CSS_LOAD_SCP_IMAGES	:=	1
-
-CSS_USE_SCMI_SDS_DRIVER	:=	1
-
-RAS_EXTENSION		:=	0
-
-SDEI_SUPPORT		:=	0
-
-EL3_EXCEPTION_HANDLING	:=	0
-
-HANDLE_EA_EL3_FIRST	:=	0
-
-# 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
-
-GIC_ENABLE_V4_EXTN	:=      1
-
-# GIC-600 configuration
-GICV3_SUPPORT_GIC600	:=	1
-
-
-# Include GICv3 driver files
-include drivers/arm/gic/v3/gicv3.mk
-
-ENT_GIC_SOURCES		:=	${GICV3_SOURCES}		\
-				plat/common/plat_gicv3.c	\
-				plat/arm/common/arm_gicv3.c
-
-override NEED_BL2U	:=	no
-
-override ARM_PLAT_MT	:=	1
-
-TC0_BASE	=	plat/arm/board/tc0
-
-PLAT_INCLUDES		+=	-I${TC0_BASE}/include/
-
-TC0_CPU_SOURCES	:=	lib/cpus/aarch64/cortex_a510.S         \
-			lib/cpus/aarch64/cortex_a710.S \
-			lib/cpus/aarch64/cortex_x2.S
-
-INTERCONNECT_SOURCES	:=	${TC0_BASE}/tc0_interconnect.c
-
-PLAT_BL_COMMON_SOURCES	+=	${TC0_BASE}/tc0_plat.c	\
-				${TC0_BASE}/include/tc0_helpers.S
-
-BL1_SOURCES		+=	${INTERCONNECT_SOURCES}	\
-				${TC0_CPU_SOURCES}	\
-				${TC0_BASE}/tc0_trusted_boot.c	\
-				${TC0_BASE}/tc0_err.c	\
-				drivers/arm/sbsa/sbsa.c
-
-
-BL2_SOURCES		+=	${TC0_BASE}/tc0_security.c	\
-				${TC0_BASE}/tc0_err.c		\
-				${TC0_BASE}/tc0_trusted_boot.c		\
-				lib/utils/mem_region.c			\
-				drivers/arm/tzc/tzc400.c		\
-				plat/arm/common/arm_tzc400.c		\
-				plat/arm/common/arm_nor_psci_mem_protect.c
-
-BL31_SOURCES		+=	${INTERCONNECT_SOURCES}	\
-				${TC0_CPU_SOURCES}	\
-				${ENT_GIC_SOURCES}			\
-				${TC0_BASE}/tc0_bl31_setup.c	\
-				${TC0_BASE}/tc0_topology.c	\
-				drivers/cfi/v2m/v2m_flash.c		\
-				lib/utils/mem_region.c			\
-				plat/arm/common/arm_nor_psci_mem_protect.c
-
-# Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES		+=	${TC0_BASE}/fdts/${PLAT}_fw_config.dts	\
-				${TC0_BASE}/fdts/${PLAT}_tb_fw_config.dts
-FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
-TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_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}))
-
-ifeq (${SPD},spmd)
-ifeq ($(ARM_SPMC_MANIFEST_DTS),)
-ARM_SPMC_MANIFEST_DTS	:=	${TC0_BASE}/fdts/${PLAT}_spmc_manifest.dts
-endif
-
-FDT_SOURCES		+=	${ARM_SPMC_MANIFEST_DTS}
-TC0_TOS_FW_CONFIG	:=	${BUILD_PLAT}/fdts/$(notdir $(basename ${ARM_SPMC_MANIFEST_DTS})).dtb
-
-# Add the TOS_FW_CONFIG to FIP and specify the same to certtool
-$(eval $(call TOOL_ADD_PAYLOAD,${TC0_TOS_FW_CONFIG},--tos-fw-config,${TC0_TOS_FW_CONFIG}))
-endif
-
-#Device tree
-TC0_HW_CONFIG_DTS	:=	fdts/tc0.dts
-TC0_HW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}.dtb
-FDT_SOURCES		+=	${TC0_HW_CONFIG_DTS}
-$(eval TC0_HW_CONFIG	:=	${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(TC0_HW_CONFIG_DTS)))
-
-# Add the HW_CONFIG to FIP and specify the same to certtool
-$(eval $(call TOOL_ADD_PAYLOAD,${TC0_HW_CONFIG},--hw-config,${TC0_HW_CONFIG}))
-
-override CTX_INCLUDE_AARCH32_REGS	:= 0
-
-override CTX_INCLUDE_PAUTH_REGS	:= 1
-
-override ENABLE_SPE_FOR_LOWER_ELS	:= 0
-
-include plat/arm/common/arm_common.mk
-include plat/arm/css/common/css_common.mk
-include plat/arm/soc/common/soc_css.mk
-include plat/arm/board/common/board_common.mk
diff --git a/plat/arm/board/tc0/tc0_bl31_setup.c b/plat/arm/board/tc0/tc0_bl31_setup.c
deleted file mode 100644
index b91b11c..0000000
--- a/plat/arm/board/tc0/tc0_bl31_setup.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-
-#include <libfdt.h>
-#include <tc0_plat.h>
-
-#include <common/bl_common.h>
-#include <common/debug.h>
-#include <drivers/arm/css/css_mhu_doorbell.h>
-#include <drivers/arm/css/scmi.h>
-#include <plat/arm/common/plat_arm.h>
-#include <plat/common/platform.h>
-
-static scmi_channel_plat_info_t tc0_scmi_plat_info[] = {
-	{
-		.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
-		.db_reg_addr = PLAT_CSS_MHU_BASE + SENDER_REG_SET(0),
-		.db_preserve_mask = 0xfffffffe,
-		.db_modify_mask = 0x1,
-		.ring_doorbell = &mhuv2_ring_doorbell,
-	}
-};
-
-void bl31_platform_setup(void)
-{
-	tc0_bl31_common_platform_setup();
-}
-
-scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id)
-{
-
-	return &tc0_scmi_plat_info[channel_id];
-
-}
-
-void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
-				u_register_t arg2, u_register_t arg3)
-{
-	arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
-}
-
-void tc0_bl31_common_platform_setup(void)
-{
-	arm_bl31_platform_setup();
-}
-
-const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
-{
-	return css_scmi_override_pm_ops(ops);
-}
diff --git a/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c b/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c
index 6a8943d..0666e57 100644
--- a/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c
+++ b/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -75,8 +75,10 @@
 	    .image_info.image_base = BL31_BASE,
 	    .image_info.image_max_size = BL31_LIMIT - BL31_BASE,
 
-# ifdef BL32_BASE
+# if defined(BL32_BASE)
 	    .next_handoff_image_id = BL32_IMAGE_ID,
+# elif ENABLE_RME
+	    .next_handoff_image_id = RMM_IMAGE_ID,
 # else
 	    .next_handoff_image_id = BL33_IMAGE_ID,
 # endif
@@ -99,6 +101,22 @@
 		    VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
 	    .next_handoff_image_id = INVALID_IMAGE_ID,
     },
+
+# if ENABLE_RME
+	/* Fill RMM related information */
+    {
+	    .image_id = RMM_IMAGE_ID,
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+		    VERSION_2, entry_point_info_t, EP_REALM | EXECUTABLE),
+	    .ep_info.pc = RMM_BASE,
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, 0),
+	    .image_info.image_base = RMM_BASE,
+	    .image_info.image_max_size = RMM_LIMIT - RMM_BASE,
+	    .next_handoff_image_id = BL33_IMAGE_ID,
+    },
+# endif
+
 # ifdef BL32_BASE
 	/* Fill BL32 related information */
     {
@@ -113,7 +131,11 @@
 	    .image_info.image_base = BL32_BASE,
 	    .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
 
+# if ENABLE_RME
+	    .next_handoff_image_id = RMM_IMAGE_ID,
+# else
 	    .next_handoff_image_id = BL33_IMAGE_ID,
+# endif
     },
 
 	/*
diff --git a/plat/arm/common/arm_bl1_fwu.c b/plat/arm/common/arm_bl1_fwu.c
index 124c1af..ce2c356 100644
--- a/plat/arm/common/arm_bl1_fwu.c
+++ b/plat/arm/common/arm_bl1_fwu.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,6 +16,8 @@
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 
+#pragma weak bl1_plat_get_image_desc
+
 /* Struct to keep track of usable memory */
 typedef struct bl1_mem_info {
 	uintptr_t mem_base;
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index 4b2a062..320bb82 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -22,14 +22,17 @@
 #pragma weak bl1_early_platform_setup
 #pragma weak bl1_plat_arch_setup
 #pragma weak bl1_plat_sec_mem_layout
+#pragma weak arm_bl1_early_platform_setup
 #pragma weak bl1_plat_prepare_exit
 #pragma weak bl1_plat_get_next_image_id
 #pragma weak plat_arm_bl1_fwu_needed
+#pragma weak arm_bl1_plat_arch_setup
+#pragma weak arm_bl1_platform_setup
 
 #define MAP_BL1_TOTAL		MAP_REGION_FLAT(			\
 					bl1_tzram_layout.total_base,	\
 					bl1_tzram_layout.total_size,	\
-					MT_MEMORY | MT_RW | MT_SECURE)
+					MT_MEMORY | MT_RW | EL3_PAS)
 /*
  * If SEPARATE_CODE_AND_RODATA=1 we define a region for each section
  * otherwise one region is defined containing both
@@ -38,17 +41,17 @@
 #define MAP_BL1_RO		MAP_REGION_FLAT(			\
 					BL_CODE_BASE,			\
 					BL1_CODE_END - BL_CODE_BASE,	\
-					MT_CODE | MT_SECURE),		\
+					MT_CODE | EL3_PAS),		\
 				MAP_REGION_FLAT(			\
 					BL1_RO_DATA_BASE,		\
 					BL1_RO_DATA_END			\
 						- BL_RO_DATA_BASE,	\
-					MT_RO_DATA | MT_SECURE)
+					MT_RO_DATA | EL3_PAS)
 #else
 #define MAP_BL1_RO		MAP_REGION_FLAT(			\
 					BL_CODE_BASE,			\
 					BL1_CODE_END - BL_CODE_BASE,	\
-					MT_CODE | MT_SECURE)
+					MT_CODE | EL3_PAS)
 #endif
 
 /* Data structure which holds the extents of the trusted SRAM for BL1*/
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 63ed9fe..2871b1b 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -9,6 +9,7 @@
 
 #include <platform_def.h>
 
+#include <arch_features.h>
 #include <arch_helpers.h>
 #include <common/bl_common.h>
 #include <common/debug.h>
@@ -17,10 +18,16 @@
 #include <drivers/partition/partition.h>
 #include <lib/fconf/fconf.h>
 #include <lib/fconf/fconf_dyn_cfg_getter.h>
+#if ENABLE_RME
+#include <lib/gpt_rme/gpt_rme.h>
+#endif /* ENABLE_RME */
 #ifdef SPD_opteed
 #include <lib/optee_utils.h>
 #endif
 #include <lib/utils.h>
+#if ENABLE_RME
+#include <plat/arm/common/arm_pas_def.h>
+#endif /* ENABLE_RME */
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 
@@ -45,11 +52,17 @@
 #pragma weak bl2_plat_get_hash
 #endif
 
+#if ENABLE_RME
 #define MAP_BL2_TOTAL		MAP_REGION_FLAT(			\
 					bl2_tzram_layout.total_base,	\
 					bl2_tzram_layout.total_size,	\
+					MT_MEMORY | MT_RW | MT_ROOT)
+#else
+#define MAP_BL2_TOTAL		MAP_REGION_FLAT(			\
+					bl2_tzram_layout.total_base,	\
+					bl2_tzram_layout.total_size,	\
 					MT_MEMORY | MT_RW | MT_SECURE)
-
+#endif /* ENABLE_RME */
 
 #pragma weak arm_bl2_plat_handle_post_image_load
 
@@ -94,13 +107,10 @@
 {
 	arm_bl2_dyn_cfg_init();
 
-#if ARM_GPT_SUPPORT
-	int result = arm_set_image_source(FIP_IMAGE_ID, "FIP_A");
-
-	if (result != 0) {
-		panic();
-	}
-#endif /* ARM_GPT_SUPPORT */
+#if ARM_GPT_SUPPORT && !PSA_FWU_SUPPORT
+	/* Always use the FIP from bank 0 */
+	arm_set_fip_addr(0U);
+#endif /* ARM_GPT_SUPPORT && !PSA_FWU_SUPPORT */
 }
 
 /*
@@ -108,8 +118,10 @@
  */
 void arm_bl2_platform_setup(void)
 {
+#if !ENABLE_RME
 	/* Initialize the secure environment */
 	plat_arm_security_setup();
+#endif
 
 #if defined(PLAT_ARM_MEM_PROT_ADDR)
 	arm_nor_psci_do_static_mem_protect();
@@ -121,9 +133,54 @@
 	arm_bl2_platform_setup();
 }
 
+#if ENABLE_RME
+
+static void arm_bl2_plat_gpt_setup(void)
+{
+	/*
+	 * The GPT library might modify the gpt regions structure to optimize
+	 * the layout, so the array cannot be constant.
+	 */
+	pas_region_t pas_regions[] = {
+		ARM_PAS_KERNEL,
+		ARM_PAS_SECURE,
+		ARM_PAS_REALM,
+		ARM_PAS_EL3_DRAM,
+		ARM_PAS_GPTS
+	};
+
+	/* Initialize entire protected space to GPT_GPI_ANY. */
+	if (gpt_init_l0_tables(GPCCR_PPS_4GB, ARM_L0_GPT_ADDR_BASE,
+		ARM_L0_GPT_SIZE) < 0) {
+		ERROR("gpt_init_l0_tables() failed!\n");
+		panic();
+	}
+
+	/* Carve out defined PAS ranges. */
+	if (gpt_init_pas_l1_tables(GPCCR_PGS_4K,
+				   ARM_L1_GPT_ADDR_BASE,
+				   ARM_L1_GPT_SIZE,
+				   pas_regions,
+				   (unsigned int)(sizeof(pas_regions) /
+				   sizeof(pas_region_t))) < 0) {
+		ERROR("gpt_init_pas_l1_tables() failed!\n");
+		panic();
+	}
+
+	INFO("Enabling Granule Protection Checks\n");
+	if (gpt_enable() < 0) {
+		ERROR("gpt_enable() failed!\n");
+		panic();
+	}
+}
+
+#endif /* ENABLE_RME */
+
 /*******************************************************************************
- * Perform the very early platform specific architectural setup here. At the
- * moment this is only initializes the mmu in a quick and dirty way.
+ * Perform the very early platform specific architectural setup here.
+ * When RME is enabled the secure environment is initialised before
+ * initialising and enabling Granule Protection.
+ * This function initialises the MMU in a quick and dirty way.
  ******************************************************************************/
 void arm_bl2_plat_arch_setup(void)
 {
@@ -146,13 +203,29 @@
 		ARM_MAP_BL_COHERENT_RAM,
 #endif
 		ARM_MAP_BL_CONFIG_REGION,
+#if ENABLE_RME
+		ARM_MAP_L0_GPT_REGION,
+#endif
 		{0}
 	};
 
+#if ENABLE_RME
+	/* Initialise the secure environment */
+	plat_arm_security_setup();
+#endif
 	setup_page_tables(bl_regions, plat_arm_get_mmap());
 
 #ifdef __aarch64__
+#if ENABLE_RME
+	/* BL2 runs in EL3 when RME enabled. */
+	assert(get_armv9_2_feat_rme_support() != 0U);
+	enable_mmu_el3(0);
+
+	/* Initialise and enable granule protection after MMU. */
+	arm_bl2_plat_gpt_setup();
+#else
 	enable_mmu_el1(0);
+#endif
 #else
 	enable_mmu_svc_mon(0);
 #endif
@@ -236,7 +309,7 @@
  ******************************************************************************/
 int arm_bl2_plat_handle_post_image_load(unsigned int image_id)
 {
-#if defined(SPD_spmd) && SPMD_SPM_AT_SEL2
+#if defined(SPD_spmd) && BL2_ENABLE_SP_LOAD
 	/* For Secure Partitions we don't need post processing */
 	if ((image_id >= (MAX_NUMBER_IDS - MAX_SP_IDS)) &&
 		(image_id < MAX_NUMBER_IDS)) {
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index b819888..6472590 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,6 +13,9 @@
 #include <drivers/console.h>
 #include <lib/debugfs.h>
 #include <lib/extensions/ras.h>
+#if ENABLE_RME
+#include <lib/gpt_rme/gpt_rme.h>
+#endif
 #include <lib/mmio.h>
 #include <lib/xlat_tables/xlat_tables_compat.h>
 #include <plat/arm/common/plat_arm.h>
@@ -25,6 +28,9 @@
  */
 static entry_point_info_t bl32_image_ep_info;
 static entry_point_info_t bl33_image_ep_info;
+#if ENABLE_RME
+static entry_point_info_t rmm_image_ep_info;
+#endif
 
 #if !RESET_TO_BL31
 /*
@@ -43,7 +49,7 @@
 #define MAP_BL31_TOTAL		MAP_REGION_FLAT(			\
 					BL31_START,			\
 					BL31_END - BL31_START,		\
-					MT_MEMORY | MT_RW | MT_SECURE)
+					MT_MEMORY | MT_RW | EL3_PAS)
 #if RECLAIM_INIT_CODE
 IMPORT_SYM(unsigned long, __INIT_CODE_START__, BL_INIT_CODE_BASE);
 IMPORT_SYM(unsigned long, __INIT_CODE_END__, BL_CODE_END_UNALIGNED);
@@ -58,7 +64,7 @@
 					BL_INIT_CODE_BASE,		\
 					BL_INIT_CODE_END		\
 						- BL_INIT_CODE_BASE,	\
-					MT_CODE | MT_SECURE)
+					MT_CODE | EL3_PAS)
 #endif
 
 #if SEPARATE_NOBITS_REGION
@@ -66,7 +72,7 @@
 					BL31_NOBITS_BASE,		\
 					BL31_NOBITS_LIMIT 		\
 						- BL31_NOBITS_BASE,	\
-					MT_MEMORY | MT_RW | MT_SECURE)
+					MT_MEMORY | MT_RW | EL3_PAS)
 
 #endif
 /*******************************************************************************
@@ -80,8 +86,18 @@
 	entry_point_info_t *next_image_info;
 
 	assert(sec_state_is_valid(type));
-	next_image_info = (type == NON_SECURE)
-			? &bl33_image_ep_info : &bl32_image_ep_info;
+	if (type == NON_SECURE) {
+		next_image_info = &bl33_image_ep_info;
+	}
+#if ENABLE_RME
+	else if (type == REALM) {
+		next_image_info = &rmm_image_ep_info;
+	}
+#endif
+	else {
+		next_image_info = &bl32_image_ep_info;
+	}
+
 	/*
 	 * None of the images on the ARM development platforms can have 0x0
 	 * as the entrypoint
@@ -169,21 +185,31 @@
 	bl_params_node_t *bl_params = params_from_bl2->head;
 
 	/*
-	 * Copy BL33 and BL32 (if present), entry point information.
+	 * Copy BL33, BL32 and RMM (if present), entry point information.
 	 * They are stored in Secure RAM, in BL2's address space.
 	 */
 	while (bl_params != NULL) {
-		if (bl_params->image_id == BL32_IMAGE_ID)
+		if (bl_params->image_id == BL32_IMAGE_ID) {
 			bl32_image_ep_info = *bl_params->ep_info;
-
-		if (bl_params->image_id == BL33_IMAGE_ID)
+		}
+#if ENABLE_RME
+		else if (bl_params->image_id == RMM_IMAGE_ID) {
+			rmm_image_ep_info = *bl_params->ep_info;
+		}
+#endif
+		else if (bl_params->image_id == BL33_IMAGE_ID) {
 			bl33_image_ep_info = *bl_params->ep_info;
+		}
 
 		bl_params = bl_params->next_params_info;
 	}
 
 	if (bl33_image_ep_info.pc == 0U)
 		panic();
+#if ENABLE_RME
+	if (rmm_image_ep_info.pc == 0U)
+		panic();
+#endif
 #endif /* RESET_TO_BL31 */
 
 # if ARM_LINUX_KERNEL_AS_BL33
@@ -193,7 +219,11 @@
 	 * tree blob (DTB) in x0, while x1-x3 are reserved for future use and
 	 * must be 0.
 	 */
+#if RESET_TO_BL31
 	bl33_image_ep_info.args.arg0 = (u_register_t)ARM_PRELOADED_DTB_BASE;
+#else
+	bl33_image_ep_info.args.arg0 = (u_register_t)hw_config;
+#endif
 	bl33_image_ep_info.args.arg1 = 0U;
 	bl33_image_ep_info.args.arg2 = 0U;
 	bl33_image_ep_info.args.arg3 = 0U;
@@ -355,6 +385,9 @@
 {
 	const mmap_region_t bl_regions[] = {
 		MAP_BL31_TOTAL,
+#if ENABLE_RME
+		ARM_MAP_L0_GPT_REGION,
+#endif
 #if RECLAIM_INIT_CODE
 		MAP_BL_INIT_CODE,
 #endif
@@ -376,6 +409,19 @@
 
 	enable_mmu_el3(0);
 
+#if ENABLE_RME
+	/*
+	 * Initialise Granule Protection library and enable GPC for the primary
+	 * processor. The tables have already been initialized by a previous BL
+	 * stage, so there is no need to provide any PAS here. This function
+	 * sets up pointers to those tables.
+	 */
+	if (gpt_runtime_init() < 0) {
+		ERROR("gpt_runtime_init() failed!\n");
+		panic();
+	}
+#endif /* ENABLE_RME */
+
 	arm_setup_romlib();
 }
 
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index f1e4cf5..f82392c 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -52,9 +52,10 @@
 $(eval $(call add_define,ARM_RECOM_STATE_ID_ENC))
 
 # Process ARM_DISABLE_TRUSTED_WDOG flag
-# By default, Trusted Watchdog is always enabled unless SPIN_ON_BL1_EXIT is set
+# By default, Trusted Watchdog is always enabled unless
+# SPIN_ON_BL1_EXIT or ENABLE_RME is set
 ARM_DISABLE_TRUSTED_WDOG	:=	0
-ifeq (${SPIN_ON_BL1_EXIT}, 1)
+ifneq ($(filter 1,${SPIN_ON_BL1_EXIT} ${ENABLE_RME}),)
 ARM_DISABLE_TRUSTED_WDOG	:=	1
 endif
 $(eval $(call assert_boolean,ARM_DISABLE_TRUSTED_WDOG))
@@ -94,10 +95,13 @@
   ifndef PRELOADED_BL33_BASE
     $(error "PRELOADED_BL33_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used.")
   endif
-  ifndef ARM_PRELOADED_DTB_BASE
-    $(error "ARM_PRELOADED_DTB_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used.")
+  ifeq (${RESET_TO_BL31},1)
+    ifndef ARM_PRELOADED_DTB_BASE
+      $(error "ARM_PRELOADED_DTB_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is
+       used with RESET_TO_BL31.")
+    endif
+    $(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
   endif
-  $(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
 endif
 
 # Arm Ethos-N NPU SiP service
@@ -185,6 +189,18 @@
   BL2_CPPFLAGS += -march=armv8-a+crc
 endif
 
+ifeq ($(PSA_FWU_SUPPORT),1)
+    # GPT support is recommended as per PSA FWU specification hence
+    # PSA FWU implementation is tightly coupled with GPT support,
+    # and it does not support other formats.
+    ifneq ($(ARM_GPT_SUPPORT),1)
+      $(error For PSA_FWU_SUPPORT, ARM_GPT_SUPPORT must be enabled)
+    endif
+    FWU_MK := drivers/fwu/fwu.mk
+    $(info Including ${FWU_MK})
+    include ${FWU_MK}
+endif
+
 ifeq (${ARCH}, aarch64)
 PLAT_INCLUDES		+=	-Iinclude/plat/arm/common/aarch64
 endif
@@ -194,18 +210,22 @@
 				plat/arm/common/arm_console.c
 
 ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1)
-PLAT_BL_COMMON_SOURCES	+=	lib/xlat_tables/xlat_tables_common.c		\
+PLAT_BL_COMMON_SOURCES 	+=	lib/xlat_tables/xlat_tables_common.c	      \
 				lib/xlat_tables/${ARCH}/xlat_tables.c
 else
+ifeq (${XLAT_MPU_LIB_V1}, 1)
+include lib/xlat_mpu/xlat_mpu.mk
+PLAT_BL_COMMON_SOURCES	+=	${XLAT_MPU_LIB_V1_SRCS}
+else
 include lib/xlat_tables_v2/xlat_tables.mk
-
-PLAT_BL_COMMON_SOURCES	+=	${XLAT_TABLES_LIB_SRCS}
+PLAT_BL_COMMON_SOURCES	+=      ${XLAT_TABLES_LIB_SRCS}
+endif
 endif
 
 ARM_IO_SOURCES		+=	plat/arm/common/arm_io_storage.c		\
 				plat/arm/common/fconf/arm_fconf_io.c
 ifeq (${SPD},spmd)
-    ifeq (${SPMD_SPM_AT_SEL2},1)
+    ifeq (${BL2_ENABLE_SP_LOAD},1)
          ARM_IO_SOURCES		+=	plat/arm/common/fconf/arm_fconf_sp.c
     endif
 endif
@@ -230,7 +250,7 @@
 				drivers/io/io_storage.c				\
 				plat/arm/common/arm_bl2_setup.c			\
 				plat/arm/common/arm_err.c			\
-				common/hw_crc32.c				\
+				common/tf_crc32.c				\
 				${ARM_IO_SOURCES}
 
 # Firmware Configuration Framework sources
@@ -256,8 +276,10 @@
 ifeq (${JUNO_AARCH32_EL3_RUNTIME},1)
 BL2_SOURCES		+=	plat/arm/common/aarch32/arm_bl2_mem_params_desc.c
 else
+ifeq ($(filter ${TARGET_PLATFORM}, fpga fvp),)
 BL2_SOURCES		+=	plat/arm/common/${ARCH}/arm_bl2_mem_params_desc.c
 endif
+endif
 BL2_SOURCES		+=	plat/arm/common/arm_image_load.c		\
 				common/desc_image_load.c
 ifeq (${SPD},opteed)
@@ -337,7 +359,7 @@
 
     # Include the selected chain of trust sources.
     ifeq (${COT},tbbr)
-	BL1_SOURCES     +=      drivers/auth/tbbr/tbbr_cot_common.c		\
+            BL1_SOURCES	+=	drivers/auth/tbbr/tbbr_cot_common.c		\
 				drivers/auth/tbbr/tbbr_cot_bl1.c
         ifneq (${COT_DESC_IN_DTB},0)
             BL2_SOURCES	+=	lib/fconf/fconf_cot_getter.c
diff --git a/plat/arm/common/arm_image_load.c b/plat/arm/common/arm_image_load.c
index ebf6dff..c411c6c 100644
--- a/plat/arm/common/arm_image_load.c
+++ b/plat/arm/common/arm_image_load.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -32,7 +32,7 @@
 		next_bl_params_cpy_ptr);
 }
 
-#if defined(SPD_spmd) && SPMD_SPM_AT_SEL2
+#if defined(SPD_spmd) && BL2_ENABLE_SP_LOAD
 /*******************************************************************************
  * This function appends Secure Partitions to list of loadable images.
  ******************************************************************************/
@@ -76,7 +76,7 @@
  ******************************************************************************/
 struct bl_load_info *plat_get_bl_image_load_info(void)
 {
-#if defined(SPD_spmd) && SPMD_SPM_AT_SEL2
+#if defined(SPD_spmd) && BL2_ENABLE_SP_LOAD
 	bl_load_info_t *bl_load_info;
 
 	bl_load_info = get_bl_load_info_from_mem_params_desc();
diff --git a/plat/arm/common/arm_io_storage.c b/plat/arm/common/arm_io_storage.c
index c5d913e..387086a 100644
--- a/plat/arm/common/arm_io_storage.c
+++ b/plat/arm/common/arm_io_storage.c
@@ -5,6 +5,7 @@
  */
 
 #include <common/debug.h>
+#include <drivers/fwu/fwu_metadata.h>
 #include <drivers/io/io_driver.h>
 #include <drivers/io/io_fip.h>
 #include <drivers/io/io_memmap.h>
@@ -24,6 +25,13 @@
 static const io_dev_connector_t *memmap_dev_con;
 uintptr_t memmap_dev_handle;
 
+#if ARM_GPT_SUPPORT
+/* fip partition names */
+static const char * const fip_part_names[] = {"FIP_A", "FIP_B"};
+CASSERT(sizeof(fip_part_names)/sizeof(char *) == NR_OF_FW_BANKS,
+	assert_fip_partition_names_missing);
+#endif /* ARM_GPT_SUPPORT */
+
 /* Weak definitions may be overridden in specific ARM standard platform */
 #pragma weak plat_arm_io_setup
 #pragma weak plat_arm_get_alt_image_source
@@ -139,17 +147,20 @@
 }
 
 #if ARM_GPT_SUPPORT
-/**********************************************************************
- * arm_set_image_source: Set image specification in IO policy
+/******************************************************************************
+ * Retrieve partition entry details such as offset and length, and set these
+ * details in the I/O policy of the requested image.
  *
- * @image_id: id of the image whose specification to be set
+ * @image_id: image id whose I/O policy to be updated
  *
- * @part_name: name of the partition that to be read for entry details
+ * @part_name: partition name whose details to be retrieved
  *
- * set the entry and offset details of partition in global IO policy
- * of the image
- *********************************************************************/
-int arm_set_image_source(unsigned int image_id, const char *part_name)
+ * Returns 0 on success, error otherwise
+ * Alongside, returns device handle and image specification of requested
+ * image.
+ ******************************************************************************/
+int arm_set_image_source(unsigned int image_id, const char *part_name,
+			 uintptr_t *dev_handle, uintptr_t *image_spec)
 {
 	const partition_entry_t *entry = get_partition_entry(part_name);
 
@@ -158,19 +169,82 @@
 		return -ENOENT;
 	}
 
-	const struct plat_io_policy *policy = FCONF_GET_PROPERTY(arm,
-								 io_policies,
-								 image_id);
+	struct plat_io_policy *policy = FCONF_GET_PROPERTY(arm,
+							   io_policies,
+							   image_id);
 
 	assert(policy != NULL);
 	assert(policy->image_spec != 0UL);
 
+	io_block_spec_t *spec = (io_block_spec_t *)policy->image_spec;
 	/* set offset and length of the image */
-	io_block_spec_t *image_spec = (io_block_spec_t *)policy->image_spec;
+	spec->offset = PLAT_ARM_FLASH_IMAGE_BASE + entry->start;
+	spec->length = entry->length;
 
-	image_spec->offset = PLAT_ARM_FLASH_IMAGE_BASE + entry->start;
-	image_spec->length = entry->length;
+	*dev_handle = *(policy->dev_handle);
+	*image_spec = policy->image_spec;
 
 	return 0;
 }
+
+/*******************************************************************************
+ * Set the source offset and length of the FIP image in its I/O policy.
+ *
+ * @active_fw_bank_idx: active firmware bank index gathered from FWU metadata.
+ ******************************************************************************/
+void arm_set_fip_addr(uint32_t active_fw_bank_idx)
+{
+	uintptr_t dev_handle __unused;
+	uintptr_t image_spec __unused;
+
+	assert(active_fw_bank_idx < NR_OF_FW_BANKS);
+
+	INFO("Booting with partition %s\n", fip_part_names[active_fw_bank_idx]);
+
+	int result = arm_set_image_source(FIP_IMAGE_ID,
+					  fip_part_names[active_fw_bank_idx],
+					  &dev_handle,
+					  &image_spec);
+	if (result != 0) {
+		panic();
+	}
+}
+#endif /* ARM_GPT_SUPPORT */
+
+#if PSA_FWU_SUPPORT
+/*******************************************************************************
+ * Read the FIP partition of the GPT image corresponding to the active firmware
+ * bank to get its offset and length, and update these details in the I/O policy
+ * of the FIP image.
+ ******************************************************************************/
+void plat_fwu_set_images_source(struct fwu_metadata *metadata)
+{
+	arm_set_fip_addr(metadata->active_index);
+}
+
+/*******************************************************************************
+ * Read the requested FWU metadata partition of the GPT image to get its offset
+ * and length, and update these details in the I/O policy of the requested FWU
+ * metadata image.
+ ******************************************************************************/
+int plat_fwu_set_metadata_image_source(unsigned int image_id,
+				       uintptr_t *dev_handle,
+				       uintptr_t *image_spec)
+{
+	int result = -1;
+
+	if (image_id == FWU_METADATA_IMAGE_ID) {
+		result = arm_set_image_source(FWU_METADATA_IMAGE_ID,
+					      "FWU-Metadata",
+					      dev_handle,
+					      image_spec);
+	} else if (image_id == BKUP_FWU_METADATA_IMAGE_ID) {
+		result = arm_set_image_source(BKUP_FWU_METADATA_IMAGE_ID,
+					      "Bkup-FWU-Metadata",
+					      dev_handle,
+					      image_spec);
+	}
+
+	return result;
+}
-#endif
+#endif /* PSA_FWU_SUPPORT */
diff --git a/plat/arm/common/fconf/arm_fconf_io.c b/plat/arm/common/fconf/arm_fconf_io.c
index 8e4469f..aea2f38 100644
--- a/plat/arm/common/fconf/arm_fconf_io.c
+++ b/plat/arm/common/fconf/arm_fconf_io.c
@@ -18,6 +18,11 @@
 #include <plat/arm/common/arm_fconf_io_storage.h>
 #include <platform_def.h>
 
+#if PSA_FWU_SUPPORT
+/* metadata entry details */
+static io_block_spec_t fwu_metadata_spec;
+#endif /* PSA_FWU_SUPPORT */
+
 io_block_spec_t fip_block_spec = {
 /*
  * This is fixed FIP address used by BL1, BL2 loads partition table
@@ -62,6 +67,7 @@
 	[SOC_FW_CONFIG_ID] = {UUID_SOC_FW_CONFIG},
 	[TOS_FW_CONFIG_ID] = {UUID_TOS_FW_CONFIG},
 	[NT_FW_CONFIG_ID] = {UUID_NT_FW_CONFIG},
+	[RMM_IMAGE_ID] = {UUID_REALM_MONITOR_MGMT_FIRMWARE},
 #endif /* ARM_IO_IN_DTB */
 #if TRUSTED_BOARD_BOOT
 	[TRUSTED_BOOT_FW_CERT_ID] = {UUID_TRUSTED_BOOT_FW_CERT},
@@ -92,6 +98,20 @@
 		open_memmap
 	},
 #endif /* ARM_GPT_SUPPORT */
+#if PSA_FWU_SUPPORT
+	[FWU_METADATA_IMAGE_ID] = {
+		&memmap_dev_handle,
+		/* filled runtime from partition information */
+		(uintptr_t)&fwu_metadata_spec,
+		open_memmap
+	},
+	[BKUP_FWU_METADATA_IMAGE_ID] = {
+		&memmap_dev_handle,
+		/* filled runtime from partition information */
+		(uintptr_t)&fwu_metadata_spec,
+		open_memmap
+	},
+#endif /* PSA_FWU_SUPPORT */
 	[FIP_IMAGE_ID] = {
 		&memmap_dev_handle,
 		(uintptr_t)&fip_block_spec,
@@ -143,6 +163,11 @@
 		(uintptr_t)&arm_uuid_spec[BL33_IMAGE_ID],
 		open_fip
 	},
+	[RMM_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&arm_uuid_spec[RMM_IMAGE_ID],
+		open_fip
+	},
 	[HW_CONFIG_ID] = {
 		&fip_dev_handle,
 		(uintptr_t)&arm_uuid_spec[HW_CONFIG_ID],
diff --git a/plat/arm/common/fconf/fconf_ethosn_getter.c b/plat/arm/common/fconf/fconf_ethosn_getter.c
index 1ba9f3a..0af1a20 100644
--- a/plat/arm/common/fconf/fconf_ethosn_getter.c
+++ b/plat/arm/common/fconf/fconf_ethosn_getter.c
@@ -12,7 +12,7 @@
 #include <libfdt.h>
 #include <plat/arm/common/fconf_ethosn_getter.h>
 
-struct ethosn_config_t ethosn_config;
+struct ethosn_config_t ethosn_config = {.num_cores = 0};
 
 static uint8_t fdt_node_get_status(const void *fdt, int node)
 {
@@ -33,74 +33,86 @@
 int fconf_populate_ethosn_config(uintptr_t config)
 {
 	int ethosn_node;
-	int sub_node;
-	uint8_t ethosn_status;
-	uint32_t core_count = 0U;
-	uint32_t core_addr_idx = 0U;
 	const void *hw_conf_dtb = (const void *)config;
 
 	/* Find offset to node with 'ethosn' compatible property */
-	ethosn_node = fdt_node_offset_by_compatible(hw_conf_dtb, -1, "ethosn");
-	if (ethosn_node < 0) {
-		ERROR("FCONF: Can't find 'ethosn' compatible node in dtb\n");
-		return ethosn_node;
-	}
-
-	/* If the Arm Ethos-N NPU is disabled the core check can be skipped */
-	ethosn_status = fdt_node_get_status(hw_conf_dtb, ethosn_node);
-	if (ethosn_status == ETHOSN_STATUS_DISABLED) {
-		return 0;
-	}
+	INFO("Probing Arm Ethos-N NPU\n");
+	uint32_t total_core_count = 0U;
 
-	fdt_for_each_subnode(sub_node, hw_conf_dtb, ethosn_node) {
-		int err;
-		uintptr_t addr;
-		uint8_t status;
+	fdt_for_each_compatible_node(hw_conf_dtb, ethosn_node, "ethosn") {
+		int sub_node;
+		uint8_t ethosn_status;
+		uint32_t device_core_count = 0U;
 
-		/* Check that the sub node is "ethosn-core" compatible */
-		if (fdt_node_check_compatible(hw_conf_dtb, sub_node,
-					      "ethosn-core") != 0) {
-			/* Ignore incompatible sub node */
+		/* If the Arm Ethos-N NPU is disabled the core check can be skipped */
+		ethosn_status = fdt_node_get_status(hw_conf_dtb, ethosn_node);
+		if (ethosn_status == ETHOSN_STATUS_DISABLED) {
 			continue;
 		}
 
-		/* Including disabled cores */
-		if (core_addr_idx >= ETHOSN_CORE_NUM_MAX) {
-			ERROR("FCONF: Reached max number of Arm Ethos-N NPU cores\n");
-			return -1;
-		}
+		fdt_for_each_subnode(sub_node, hw_conf_dtb, ethosn_node) {
+			int err;
+			uintptr_t core_addr;
+			uint8_t core_status;
 
-		status = fdt_node_get_status(hw_conf_dtb, ethosn_node);
-		if (status == ETHOSN_STATUS_DISABLED) {
-			++core_addr_idx;
-			continue;
+			if (total_core_count >= ETHOSN_CORE_NUM_MAX) {
+				ERROR("FCONF: Reached max number of Arm Ethos-N NPU cores\n");
+				return -FDT_ERR_BADSTRUCTURE;
+			}
+
+			/* Check that the sub node is "ethosn-core" compatible */
+			if (fdt_node_check_compatible(hw_conf_dtb,
+						      sub_node,
+						      "ethosn-core") != 0) {
+				/* Ignore incompatible sub node */
+				continue;
+			}
+
+			core_status = fdt_node_get_status(hw_conf_dtb, sub_node);
+			if (core_status == ETHOSN_STATUS_DISABLED) {
+				continue;
+			}
+
+			err = fdt_get_reg_props_by_index(hw_conf_dtb,
+							 ethosn_node,
+							 device_core_count,
+							 &core_addr,
+							 NULL);
+			if (err < 0) {
+				ERROR(
+				"FCONF: Failed to read reg property for Arm Ethos-N NPU core %u\n",
+						device_core_count);
+				return err;
+			}
+
+			INFO("NPU core probed at address 0x%lx\n", core_addr);
+			ethosn_config.core[total_core_count].addr = core_addr;
+			total_core_count++;
+			device_core_count++;
 		}
 
-		err = fdt_get_reg_props_by_index(hw_conf_dtb, ethosn_node,
-						 core_addr_idx, &addr, NULL);
-		if (err < 0) {
-			ERROR("FCONF: Failed to read reg property for Arm Ethos-N NPU core %u\n",
-			      core_addr_idx);
-			return err;
+		if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) {
+			ERROR("FCONF: Failed to parse sub nodes\n");
+			return -FDT_ERR_BADSTRUCTURE;
 		}
 
-		ethosn_config.core_addr[core_count++] = addr;
-		++core_addr_idx;
+		if (device_core_count == 0U) {
+			ERROR(
+			"FCONF: Enabled Arm Ethos-N NPU device must have at least one enabled core\n");
+			return -FDT_ERR_BADSTRUCTURE;
+		}
 	}
 
-	if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) {
-		ERROR("FCONF: Failed to parse sub nodes\n");
-		return sub_node;
+	if (total_core_count == 0U) {
+		ERROR("FCONF: Can't find 'ethosn' compatible node in dtb\n");
+		return -FDT_ERR_BADSTRUCTURE;
 	}
 
-	/* The Arm Ethos-N NPU can't be used if no cores were found */
-	if (core_count == 0) {
-		ERROR("FCONF: No Arm Ethos-N NPU cores found\n");
-		return -1;
-	}
+	ethosn_config.num_cores = total_core_count;
 
-	ethosn_config.num_cores = core_count;
-	ethosn_config.status = ethosn_status;
+	INFO("%d NPU core%s probed\n",
+	     ethosn_config.num_cores,
+	     ethosn_config.num_cores > 1 ? "s" : "");
 
 	return 0;
 }
diff --git a/plat/arm/common/trp/arm_trp.mk b/plat/arm/common/trp/arm_trp.mk
new file mode 100644
index 0000000..997111f
--- /dev/null
+++ b/plat/arm/common/trp/arm_trp.mk
@@ -0,0 +1,10 @@
+#
+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# TRP source files common to ARM standard platforms
+RMM_SOURCES		+=	plat/arm/common/trp/arm_trp_setup.c	\
+				plat/arm/common/arm_topology.c		\
+				plat/common/aarch64/platform_mp_stack.S
diff --git a/plat/arm/common/trp/arm_trp_setup.c b/plat/arm/common/trp/arm_trp_setup.c
new file mode 100644
index 0000000..8e48293
--- /dev/null
+++ b/plat/arm/common/trp/arm_trp_setup.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/console.h>
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Initialize the UART
+ ******************************************************************************/
+static console_t arm_trp_runtime_console;
+
+void arm_trp_early_platform_setup(void)
+{
+	/*
+	 * Initialize a different console than already in use to display
+	 * messages from trp
+	 */
+	int rc = console_pl011_register(PLAT_ARM_TRP_UART_BASE,
+					PLAT_ARM_TRP_UART_CLK_IN_HZ,
+					ARM_CONSOLE_BAUDRATE,
+					&arm_trp_runtime_console);
+	if (rc == 0) {
+		panic();
+	}
+
+	console_set_scope(&arm_trp_runtime_console,
+			  CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
+}
+
+void trp_early_platform_setup(void)
+{
+	arm_trp_early_platform_setup();
+}
diff --git a/plat/arm/css/sgi/aarch64/sgi_helper.S b/plat/arm/css/sgi/aarch64/sgi_helper.S
index 04bfb77..ced59e8 100644
--- a/plat/arm/css/sgi/aarch64/sgi_helper.S
+++ b/plat/arm/css/sgi/aarch64/sgi_helper.S
@@ -9,6 +9,8 @@
 #include <platform_def.h>
 #include <cortex_a75.h>
 #include <neoverse_n1.h>
+#include <neoverse_v1.h>
+#include <neoverse_n2.h>
 #include <cpu_macros.S>
 
 	.globl	plat_arm_calc_core_pos
@@ -66,6 +68,8 @@
 func plat_reset_handler
 	jump_if_cpu_midr CORTEX_A75_MIDR, A75
 	jump_if_cpu_midr NEOVERSE_N1_MIDR, N1
+	jump_if_cpu_midr NEOVERSE_V1_MIDR, V1
+	jump_if_cpu_midr NEOVERSE_N2_MIDR, N2
 	ret
 
 	/* -----------------------------------------------------
@@ -85,4 +89,18 @@
 	msr	NEOVERSE_N1_CPUPWRCTLR_EL1, x0
 	isb
 	ret
+
+V1:
+	mrs	x0, NEOVERSE_V1_CPUPWRCTLR_EL1
+	bic	x0, x0, #NEOVERSE_V1_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
+	msr	NEOVERSE_V1_CPUPWRCTLR_EL1, x0
+	isb
+	ret
+
+N2:
+	mrs	x0, NEOVERSE_N2_CPUPWRCTLR_EL1
+	bic	x0, x0, #NEOVERSE_N2_CORE_PWRDN_EN_BIT
+	msr	NEOVERSE_N2_CPUPWRCTLR_EL1, x0
+	isb
+	ret
 endfunc plat_reset_handler
diff --git a/plat/arm/css/sgi/include/sgi_ras.h b/plat/arm/css/sgi/include/sgi_ras.h
index 4b8a0d1..e69a684 100644
--- a/plat/arm/css/sgi/include/sgi_ras.h
+++ b/plat/arm/css/sgi/include/sgi_ras.h
@@ -7,16 +7,11 @@
 #ifndef SGI_RAS_H
 #define SGI_RAS_H
 
-/* Platform specific SMC FID's used for DMC-620 RAS error handling */
-#define SP_DMC_ERROR_OVERFLOW_EVENT_AARCH64	0xC4000043
-#define SP_DMC_ERROR_ECC_EVENT_AARCH64		0xC4000044
-
 /*
  * Mapping the RAS interrupt with SDEI event number and the event
  * id used with Standalone MM code
  */
 struct sgi_ras_ev_map {
-	int ras_ev_num;		/* RAS Event number */
 	int sdei_ev_num;	/* SDEI Event number */
 	int intr;		/* Physical intr number */
 };
diff --git a/plat/arm/css/sgi/sgi_ras.c b/plat/arm/css/sgi/sgi_ras.c
index a04972d..4f03ac4 100644
--- a/plat/arm/css/sgi/sgi_ras.c
+++ b/plat/arm/css/sgi/sgi_ras.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -20,44 +20,51 @@
 static int sgi_ras_intr_handler(const struct err_record_info *err_rec,
 				int probe_data,
 				const struct err_handler_data *const data);
-struct efi_guid {
-	uint32_t	data1;
-	uint16_t	data2;
-	uint16_t	data3;
-	uint8_t		data4[8];
-};
-
 typedef struct mm_communicate_header {
 	struct efi_guid	header_guid;
 	size_t		message_len;
 	uint8_t		data[8];
 } mm_communicate_header_t;
 
+/*
+ * GUID to indicate that the MM communication message is intended for DMC-620
+ * MM driver.
+ */
+const struct efi_guid dmc620_ecc_event_guid = {
+	0x5ef0afd5, 0xe01a, 0x4c30,
+	{0x86, 0x19, 0x45, 0x46, 0x26, 0x91, 0x80, 0x98}
+};
+
 struct sgi_ras_ev_map sgi575_ras_map[] = {
 
-	/* DMC620 error overflow interrupt*/
-	{SP_DMC_ERROR_OVERFLOW_EVENT_AARCH64, SGI_SDEI_DS_EVENT_1, 33},
+	/* DMC 0 error ECC error interrupt*/
+	{SGI_SDEI_DS_EVENT_0, 35},
 
-	/* DMC620 error ECC error interrupt*/
-	{SP_DMC_ERROR_ECC_EVENT_AARCH64, SGI_SDEI_DS_EVENT_0, 35},
+	/* DMC 1 error ECC error interrupt*/
+	{SGI_SDEI_DS_EVENT_1, 39},
 };
 
 #define SGI575_RAS_MAP_SIZE	ARRAY_SIZE(sgi575_ras_map)
 
 struct err_record_info sgi_err_records[] = {
 	{
+		/* DMC 0 error record info */
 		.handler = &sgi_ras_intr_handler,
+		.aux_data = (void *)0,
+	}, {
+		/* DMC 1 error record info */
+		.handler = &sgi_ras_intr_handler,
+		.aux_data = (void *)1,
 	},
 };
 
 struct ras_interrupt sgi_ras_interrupts[] = {
 	{
-		.intr_number = 33,
-		.err_record = &sgi_err_records[0],
-	},
-	{
 		.intr_number = 35,
 		.err_record = &sgi_err_records[0],
+	}, {
+		.intr_number = 39,
+		.err_record = &sgi_err_records[1],
 	}
 };
 
@@ -138,9 +145,10 @@
 	 */
 	header = (void *) PLAT_SPM_BUF_BASE;
 	memset(header, 0, sizeof(*header));
-	memcpy(&header->data, &ras_map->ras_ev_num,
-	       sizeof(ras_map->ras_ev_num));
-	header->message_len = 4;
+	memcpy(&header->data, &err_rec->aux_data, sizeof(err_rec->aux_data));
+	header->message_len = sizeof(err_rec->aux_data);
+	memcpy(&header->header_guid, (void *) &dmc620_ecc_event_guid,
+			sizeof(const struct efi_guid));
 
 	spm_mm_sp_call(MM_COMMUNICATE_AARCH64, (uint64_t)header, 0,
 		       plat_my_core_pos());
diff --git a/plat/common/aarch64/plat_common.c b/plat/common/aarch64/plat_common.c
index ba4c366..345fec3 100644
--- a/plat/common/aarch64/plat_common.c
+++ b/plat/common/aarch64/plat_common.c
@@ -28,7 +28,7 @@
 #pragma weak plat_sdei_validate_entry_point
 #endif
 
-#pragma weak plat_ea_handler
+#pragma weak plat_ea_handler = plat_default_ea_handler
 
 void bl31_plat_runtime_setup(void)
 {
@@ -79,7 +79,7 @@
 #endif /* !ENABLE_BACKTRACE */
 
 /* RAS functions common to AArch64 ARM platforms */
-void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
+void plat_default_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
 		void *handle, uint64_t flags)
 {
 #if RAS_EXTENSION
@@ -90,6 +90,7 @@
 #endif
 	unsigned int level = (unsigned int)GET_EL(read_spsr_el3());
 
+	ERROR_NL();
 	ERROR("Unhandled External Abort received on 0x%lx from %s\n",
 		read_mpidr_el1(), get_el_str(level));
 	ERROR("exception reason=%u syndrome=0x%llx\n", ea_reason, syndrome);
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_io_storage.c b/plat/imx/common/imx_io_storage.c
similarity index 93%
rename from plat/imx/imx8m/imx8mm/imx8mm_io_storage.c
rename to plat/imx/common/imx_io_storage.c
index ff6687e..bb35662 100644
--- a/plat/imx/imx8m/imx8mm/imx8mm_io_storage.c
+++ b/plat/imx/common/imx_io_storage.c
@@ -6,10 +6,10 @@
 
 #include <assert.h>
 
+#include <common/debug.h>
 #include <drivers/io/io_block.h>
 #include <drivers/io/io_driver.h>
 #include <drivers/io/io_fip.h>
-#include <drivers/io/io_driver.h>
 #include <drivers/io/io_memmap.h>
 #include <drivers/mmc.h>
 #include <lib/utils_def.h>
@@ -21,21 +21,21 @@
 static const io_dev_connector_t *fip_dev_con;
 static uintptr_t fip_dev_handle;
 
-#ifndef IMX8MM_FIP_MMAP
+#ifndef IMX_FIP_MMAP
 static const io_dev_connector_t *mmc_dev_con;
 static uintptr_t mmc_dev_handle;
 
 static const io_block_spec_t mmc_fip_spec = {
-	.offset = IMX8MM_FIP_MMC_BASE,
-	.length = IMX8MM_FIP_SIZE
+	.offset = IMX_FIP_MMC_BASE,
+	.length = IMX_FIP_SIZE
 };
 
 static const io_block_dev_spec_t mmc_dev_spec = {
 	/* It's used as temp buffer in block driver. */
 	.buffer		= {
-		.offset	= IMX8MM_FIP_BASE,
+		.offset	= IMX_FIP_BASE,
 		/* do we need a new value? */
-		.length = IMX8MM_FIP_SIZE
+		.length = IMX_FIP_SIZE
 	},
 	.ops		= {
 		.read	= mmc_read_blocks,
@@ -51,8 +51,8 @@
 static uintptr_t memmap_dev_handle;
 
 static const io_block_spec_t fip_block_spec = {
-	.offset = IMX8MM_FIP_BASE,
-	.length = IMX8MM_FIP_SIZE
+	.offset = IMX_FIP_BASE,
+	.length = IMX_FIP_SIZE
 };
 static int open_memmap(const uintptr_t spec);
 #endif
@@ -113,6 +113,7 @@
 };
 #endif /* TRUSTED_BOARD_BOOT */
 
+/* TODO: this structure is replicated multiple times. rationalize it ! */
 struct plat_io_policy {
 	uintptr_t *dev_handle;
 	uintptr_t image_spec;
@@ -120,7 +121,7 @@
 };
 
 static const struct plat_io_policy policies[] = {
-#ifndef IMX8MM_FIP_MMAP
+#ifndef IMX_FIP_MMAP
 	[FIP_IMAGE_ID] = {
 		&mmc_dev_handle,
 		(uintptr_t)&mmc_fip_spec,
@@ -219,7 +220,7 @@
 	return result;
 }
 
-#ifndef IMX8MM_FIP_MMAP
+#ifndef IMX_FIP_MMAP
 static int open_mmc(const uintptr_t spec)
 {
 	int result;
@@ -270,11 +271,11 @@
 	return result;
 }
 
-void plat_imx8mm_io_setup(void)
+void plat_imx_io_setup(void)
 {
 	int result __unused;
 
-#ifndef IMX8MM_FIP_MMAP
+#ifndef IMX_FIP_MMAP
 	result = register_io_dev_block(&mmc_dev_con);
 	assert(result == 0);
 
diff --git a/plat/imx/imx7/common/imx7.mk b/plat/imx/imx7/common/imx7.mk
index 3a95772..fdde9a9 100644
--- a/plat/imx/imx7/common/imx7.mk
+++ b/plat/imx/imx7/common/imx7.mk
@@ -16,6 +16,7 @@
 				-Iplat/imx/imx7/include			\
 				-Idrivers/imx/timer			\
 				-Idrivers/imx/usdhc			\
+				-Iinclude/common/tbbr
 
 # Translation tables library
 include lib/xlat_tables_v2/xlat_tables.mk
@@ -46,7 +47,7 @@
 				plat/imx/imx7/common/imx7_bl2_el3_common.c	\
 				plat/imx/imx7/common/imx7_helpers.S		\
 				plat/imx/imx7/common/imx7_image_load.c		\
-				plat/imx/imx7/common/imx7_io_storage.c		\
+				plat/imx/common/imx_io_storage.c		\
 				plat/imx/common/aarch32/imx_uart_console.S	\
 				${XLAT_TABLES_LIB_SRCS}
 
diff --git a/plat/imx/imx7/common/imx7_bl2_el3_common.c b/plat/imx/imx7/common/imx7_bl2_el3_common.c
index 7f156e3..4e5028c 100644
--- a/plat/imx/imx7/common/imx7_bl2_el3_common.c
+++ b/plat/imx/imx7/common/imx7_bl2_el3_common.c
@@ -173,7 +173,7 @@
 	console_set_scope(&console, console_scope);
 
 	/* Open handles to persistent storage */
-	plat_imx7_io_setup();
+	plat_imx_io_setup();
 
 	/* Setup higher-level functionality CAAM, RTC etc */
 	imx_caam_init();
@@ -183,7 +183,7 @@
 	VERBOSE("\tOPTEE       0x%08x-0x%08x\n", IMX7_OPTEE_BASE, IMX7_OPTEE_LIMIT);
 	VERBOSE("\tATF/BL2     0x%08x-0x%08x\n", BL2_RAM_BASE, BL2_RAM_LIMIT);
 	VERBOSE("\tSHRAM       0x%08x-0x%08x\n", SHARED_RAM_BASE, SHARED_RAM_LIMIT);
-	VERBOSE("\tFIP         0x%08x-0x%08x\n", IMX7_FIP_BASE, IMX7_FIP_LIMIT);
+	VERBOSE("\tFIP         0x%08x-0x%08x\n", IMX_FIP_BASE, IMX_FIP_LIMIT);
 	VERBOSE("\tDTB-OVERLAY 0x%08x-0x%08x\n", IMX7_DTB_OVERLAY_BASE, IMX7_DTB_OVERLAY_LIMIT);
 	VERBOSE("\tDTB         0x%08x-0x%08x\n", IMX7_DTB_BASE, IMX7_DTB_LIMIT);
 	VERBOSE("\tUBOOT/BL33  0x%08x-0x%08x\n", IMX7_UBOOT_BASE, IMX7_UBOOT_LIMIT);
diff --git a/plat/imx/imx7/common/imx7_io_storage.c b/plat/imx/imx7/common/imx7_io_storage.c
deleted file mode 100644
index 977181d..0000000
--- a/plat/imx/imx7/common/imx7_io_storage.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-
-#include <platform_def.h>
-
-#include <common/debug.h>
-#include <drivers/io/io_block.h>
-#include <drivers/io/io_driver.h>
-#include <drivers/io/io_fip.h>
-#include <drivers/io/io_memmap.h>
-#include <drivers/mmc.h>
-#include <tools_share/firmware_image_package.h>
-
-static const io_dev_connector_t *fip_dev_con;
-static uintptr_t fip_dev_handle;
-
-#ifndef IMX7_FIP_MMAP
-static const io_dev_connector_t *mmc_dev_con;
-static uintptr_t mmc_dev_handle;
-
-static const io_block_spec_t mmc_fip_spec = {
-	.offset = IMX7_FIP_MMC_BASE,
-	.length = IMX7_FIP_SIZE
-};
-
-static const io_block_dev_spec_t mmc_dev_spec = {
-	/* It's used as temp buffer in block driver. */
-	.buffer		= {
-		.offset	= IMX7_FIP_BASE,
-		/* do we need a new value? */
-		.length = IMX7_FIP_SIZE
-	},
-	.ops		= {
-		.read	= mmc_read_blocks,
-		.write	= mmc_write_blocks,
-	},
-	.block_size	= MMC_BLOCK_SIZE,
-};
-
-static int open_mmc(const uintptr_t spec);
-
-#else
-static const io_dev_connector_t *memmap_dev_con;
-static uintptr_t memmap_dev_handle;
-
-static const io_block_spec_t fip_block_spec = {
-	.offset = IMX7_FIP_BASE,
-	.length = IMX7_FIP_SIZE
-};
-static int open_memmap(const uintptr_t spec);
-#endif
-static int open_fip(const uintptr_t spec);
-
-static const io_uuid_spec_t bl32_uuid_spec = {
-	.uuid = UUID_SECURE_PAYLOAD_BL32,
-};
-
-static const io_uuid_spec_t bl32_extra1_uuid_spec = {
-	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
-};
-
-static const io_uuid_spec_t bl32_extra2_uuid_spec = {
-	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
-};
-
-static const io_uuid_spec_t bl33_uuid_spec = {
-	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
-};
-
-#if TRUSTED_BOARD_BOOT
-static const io_uuid_spec_t tb_fw_cert_uuid_spec = {
-	.uuid = UUID_TRUSTED_BOOT_FW_CERT,
-};
-
-static const io_uuid_spec_t trusted_key_cert_uuid_spec = {
-	.uuid = UUID_TRUSTED_KEY_CERT,
-};
-
-static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = {
-	.uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
-};
-
-static const io_uuid_spec_t tos_fw_cert_uuid_spec = {
-	.uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
-};
-
-static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = {
-	.uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
-};
-
-static const io_uuid_spec_t nt_fw_cert_uuid_spec = {
-	.uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT,
-};
-#endif /* TRUSTED_BOARD_BOOT */
-
-/* TODO: this structure is replicated multiple times. rationalize it ! */
-struct plat_io_policy {
-	uintptr_t *dev_handle;
-	uintptr_t image_spec;
-	int (*check)(const uintptr_t spec);
-};
-
-static const struct plat_io_policy policies[] = {
-#ifndef IMX7_FIP_MMAP
-	[FIP_IMAGE_ID] = {
-		&mmc_dev_handle,
-		(uintptr_t)&mmc_fip_spec,
-		open_mmc
-	},
-#else
-	[FIP_IMAGE_ID] = {
-		&memmap_dev_handle,
-		(uintptr_t)&fip_block_spec,
-		open_memmap
-	},
-#endif
-	[BL32_IMAGE_ID] = {
-		&fip_dev_handle,
-		(uintptr_t)&bl32_uuid_spec,
-		open_fip
-	},
-	[BL32_EXTRA1_IMAGE_ID] = {
-		&fip_dev_handle,
-		(uintptr_t)&bl32_extra1_uuid_spec,
-		open_fip
-	},
-	[BL32_EXTRA2_IMAGE_ID] = {
-		&fip_dev_handle,
-		(uintptr_t)&bl32_extra2_uuid_spec,
-		open_fip
-	},
-	[BL33_IMAGE_ID] = {
-		&fip_dev_handle,
-		(uintptr_t)&bl33_uuid_spec,
-		open_fip
-	},
-#if TRUSTED_BOARD_BOOT
-	[TRUSTED_BOOT_FW_CERT_ID] = {
-		&fip_dev_handle,
-		(uintptr_t)&tb_fw_cert_uuid_spec,
-		open_fip
-	},
-	[TRUSTED_KEY_CERT_ID] = {
-		&fip_dev_handle,
-		(uintptr_t)&trusted_key_cert_uuid_spec,
-		open_fip
-	},
-	[TRUSTED_OS_FW_KEY_CERT_ID] = {
-		&fip_dev_handle,
-		(uintptr_t)&tos_fw_key_cert_uuid_spec,
-		open_fip
-	},
-	[NON_TRUSTED_FW_KEY_CERT_ID] = {
-		&fip_dev_handle,
-		(uintptr_t)&nt_fw_key_cert_uuid_spec,
-		open_fip
-	},
-	[TRUSTED_OS_FW_CONTENT_CERT_ID] = {
-		&fip_dev_handle,
-		(uintptr_t)&tos_fw_cert_uuid_spec,
-		open_fip
-	},
-	[NON_TRUSTED_FW_CONTENT_CERT_ID] = {
-		&fip_dev_handle,
-		(uintptr_t)&nt_fw_cert_uuid_spec,
-		open_fip
-	},
-#endif /* TRUSTED_BOARD_BOOT */
-};
-
-static int open_fip(const uintptr_t spec)
-{
-	int result;
-	uintptr_t local_image_handle;
-
-	/* See if a Firmware Image Package is available */
-	result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
-	if (result == 0) {
-		result = io_open(fip_dev_handle, spec, &local_image_handle);
-		if (result == 0) {
-			VERBOSE("Using FIP\n");
-			io_close(local_image_handle);
-		}
-	}
-	return result;
-}
-
-#ifndef IMX7_FIP_MMAP
-static int open_mmc(const uintptr_t spec)
-{
-	int result;
-	uintptr_t local_handle;
-
-	result = io_dev_init(mmc_dev_handle, (uintptr_t)NULL);
-	if (result == 0) {
-		result = io_open(mmc_dev_handle, spec, &local_handle);
-		if (result == 0)
-			io_close(local_handle);
-	}
-	return result;
-}
-#else
-static int open_memmap(const uintptr_t spec)
-{
-	int result;
-	uintptr_t local_image_handle;
-
-	result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
-	if (result == 0) {
-		result = io_open(memmap_dev_handle, spec, &local_image_handle);
-		if (result == 0) {
-			VERBOSE("Using Memmap\n");
-			io_close(local_image_handle);
-		}
-	}
-	return result;
-}
-#endif
-
-int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
-			  uintptr_t *image_spec)
-{
-	int result;
-	const struct plat_io_policy *policy;
-
-	assert(image_id < ARRAY_SIZE(policies));
-
-	policy = &policies[image_id];
-	result = policy->check(policy->image_spec);
-	assert(result == 0);
-
-	*image_spec = policy->image_spec;
-	*dev_handle = *policy->dev_handle;
-
-	return result;
-}
-
-void plat_imx7_io_setup(void)
-{
-	int result __unused;
-
-#ifndef IMX7_FIP_MMAP
-	result = register_io_dev_block(&mmc_dev_con);
-	assert(result == 0);
-
-	result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_dev_spec,
-			     &mmc_dev_handle);
-	assert(result == 0);
-
-#else
-	result = register_io_dev_memmap(&memmap_dev_con);
-	assert(result == 0);
-
-	result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
-			     &memmap_dev_handle);
-	assert(result == 0);
-
-#endif
-	result = register_io_dev_fip(&fip_dev_con);
-	assert(result == 0);
-
-	result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
-			     &fip_dev_handle);
-	assert(result == 0);
-}
diff --git a/plat/imx/imx7/include/imx7_def.h b/plat/imx/imx7/include/imx7_def.h
index 77a8ca3..d92a2d1 100644
--- a/plat/imx/imx7/include/imx7_def.h
+++ b/plat/imx/imx7/include/imx7_def.h
@@ -13,7 +13,7 @@
 /*******************************************************************************
  * Function and variable prototypes
  ******************************************************************************/
-void plat_imx7_io_setup(void);
+void plat_imx_io_setup(void);
 void imx7_platform_setup(u_register_t arg1, u_register_t arg2,
 			 u_register_t arg3, u_register_t arg4);
 
diff --git a/plat/imx/imx7/picopi/include/platform_def.h b/plat/imx/imx7/picopi/include/platform_def.h
index 141571c..5f2975d 100644
--- a/plat/imx/imx7/picopi/include/platform_def.h
+++ b/plat/imx/imx7/picopi/include/platform_def.h
@@ -92,12 +92,12 @@
 #define IMX7_UBOOT_LIMIT		(IMX7_UBOOT_BASE + IMX7_UBOOT_SIZE)
 
 /* Define FIP image absolute location 0x80000000 - 0x80100000 */
-#define IMX7_FIP_SIZE			0x00100000
-#define IMX7_FIP_BASE			(DRAM_BASE)
-#define IMX7_FIP_LIMIT			(IMX7_FIP_BASE + IMX7_FIP_SIZE)
+#define IMX_FIP_SIZE			0x00100000
+#define IMX_FIP_BASE			(DRAM_BASE)
+#define IMX_FIP_LIMIT			(IMX_FIP_BASE + IMX_FIP_SIZE)
 
 /* Define FIP image location at 1MB offset */
-#define IMX7_FIP_MMC_BASE		(1024 * 1024)
+#define IMX_FIP_MMC_BASE		(1024 * 1024)
 
 /* Define the absolute location of DTB 0x83000000 - 0x83100000 */
 #define IMX7_DTB_SIZE			0x00100000
diff --git a/plat/imx/imx7/picopi/picopi_bl2_el3_setup.c b/plat/imx/imx7/picopi/picopi_bl2_el3_setup.c
index 3cf5c36..2df96ae 100644
--- a/plat/imx/imx7/picopi/picopi_bl2_el3_setup.c
+++ b/plat/imx/imx7/picopi/picopi_bl2_el3_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -43,6 +43,8 @@
 	 IOMUXC_SW_PAD_CTL_PAD_SD3_SLEW_SLOW         | \
 	 IOMUXC_SW_PAD_CTL_PAD_SD3_DSE_3_X6)
 
+static struct mmc_device_info mmc_info;
+
 static void picopi_setup_pinmux(void)
 {
 	/* Configure UART5 TX */
@@ -93,14 +95,13 @@
 static void picopi_usdhc_setup(void)
 {
 	imx_usdhc_params_t params;
-	struct mmc_device_info info;
 
 	zeromem(&params, sizeof(imx_usdhc_params_t));
 	params.reg_base = PLAT_PICOPI_BOOT_MMC_BASE;
 	params.clk_rate = 25000000;
 	params.bus_width = MMC_BUS_WIDTH_8;
-	info.mmc_dev_type = MMC_IS_EMMC;
-	imx_usdhc_init(&params, &info);
+	mmc_info.mmc_dev_type = MMC_IS_EMMC;
+	imx_usdhc_init(&params, &mmc_info);
 }
 
 static void picopi_setup_usb_clocks(void)
diff --git a/plat/imx/imx7/warp7/include/platform_def.h b/plat/imx/imx7/warp7/include/platform_def.h
index 4afcb54..683e50d 100644
--- a/plat/imx/imx7/warp7/include/platform_def.h
+++ b/plat/imx/imx7/warp7/include/platform_def.h
@@ -94,12 +94,12 @@
 #define IMX7_UBOOT_LIMIT		(IMX7_UBOOT_BASE + IMX7_UBOOT_SIZE)
 
 /* Define FIP image absolute location 0x80000000 - 0x80100000 */
-#define IMX7_FIP_SIZE			0x00100000
-#define IMX7_FIP_BASE			(DRAM_BASE)
-#define IMX7_FIP_LIMIT			(IMX7_FIP_BASE + IMX7_FIP_SIZE)
+#define IMX_FIP_SIZE			0x00100000
+#define IMX_FIP_BASE			(DRAM_BASE)
+#define IMX_FIP_LIMIT			(IMX_FIP_BASE + IMX_FIP_SIZE)
 
 /* Define FIP image location at 1MB offset */
-#define IMX7_FIP_MMC_BASE		(1024 * 1024)
+#define IMX_FIP_MMC_BASE		(1024 * 1024)
 
 /* Define the absolute location of DTB 0x83000000 - 0x83100000 */
 #define IMX7_DTB_SIZE			0x00100000
diff --git a/plat/imx/imx7/warp7/warp7_bl2_el3_setup.c b/plat/imx/imx7/warp7/warp7_bl2_el3_setup.c
index 935a411..ec13ade 100644
--- a/plat/imx/imx7/warp7/warp7_bl2_el3_setup.c
+++ b/plat/imx/imx7/warp7/warp7_bl2_el3_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -69,6 +69,8 @@
 	 IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_HYS_EN		| \
 	 IOMUXC_SW_PAD_CTL_PAD_ECSPI1_SCLK_DSE_1_X4)
 
+static struct mmc_device_info mmc_info;
+
 static void warp7_setup_pinmux(void)
 {
 	/* Configure UART1 TX */
@@ -99,14 +101,13 @@
 static void warp7_usdhc_setup(void)
 {
 	imx_usdhc_params_t params;
-	struct mmc_device_info info;
 
 	zeromem(&params, sizeof(imx_usdhc_params_t));
 	params.reg_base = PLAT_WARP7_BOOT_MMC_BASE;
 	params.clk_rate = 25000000;
 	params.bus_width = MMC_BUS_WIDTH_8;
-	info.mmc_dev_type = MMC_IS_EMMC;
-	imx_usdhc_init(&params, &info);
+	mmc_info.mmc_dev_type = MMC_IS_EMMC;
+	imx_usdhc_init(&params, &mmc_info);
 }
 
 static void warp7_setup_usb_clocks(void)
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_image_load.c b/plat/imx/imx8m/imx8m_image_load.c
similarity index 100%
rename from plat/imx/imx8m/imx8mm/imx8mm_image_load.c
rename to plat/imx/imx8m/imx8m_image_load.c
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c b/plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c
index 937774c..c39dd93 100644
--- a/plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c
+++ b/plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c
@@ -88,7 +88,7 @@
 	imx8mm_usdhc_setup();
 
 	/* Open handles to a FIP image */
-	plat_imx8mm_io_setup();
+	plat_imx_io_setup();
 }
 
 void bl2_el3_plat_arch_setup(void)
diff --git a/plat/imx/imx8m/imx8mm/include/imx8mm_private.h b/plat/imx/imx8m/imx8mm/include/imx8mm_private.h
index 52d13f0..5e0ef97 100644
--- a/plat/imx/imx8m/imx8mm/include/imx8mm_private.h
+++ b/plat/imx/imx8m/imx8mm/include/imx8mm_private.h
@@ -10,6 +10,6 @@
 /*******************************************************************************
  * Function and variable prototypes
  ******************************************************************************/
-void plat_imx8mm_io_setup(void);
+void plat_imx_io_setup(void);
 
 #endif /* IMX8MM_PRIVATE_H */
diff --git a/plat/imx/imx8m/imx8mm/include/platform_def.h b/plat/imx/imx8m/imx8mm/include/platform_def.h
index f8efa56..e86938b 100644
--- a/plat/imx/imx8m/imx8mm/include/platform_def.h
+++ b/plat/imx/imx8m/imx8mm/include/platform_def.h
@@ -41,12 +41,12 @@
 #define BL2_LIMIT			U(0x940000)
 #define BL31_BASE			U(0x900000)
 #define BL31_LIMIT			U(0x920000)
-#define IMX8MM_FIP_BASE			U(0x40310000)
-#define IMX8MM_FIP_SIZE			U(0x000200000)
-#define IMX8MM_FIP_LIMIT		U(FIP_BASE + FIP_SIZE)
+#define IMX_FIP_BASE			U(0x40310000)
+#define IMX_FIP_SIZE			U(0x000300000)
+#define IMX_FIP_LIMIT			U(FIP_BASE + FIP_SIZE)
 
 /* Define FIP image location on eMMC */
-#define IMX8MM_FIP_MMC_BASE		U(0x100000)
+#define IMX_FIP_MMC_BASE		U(0x100000)
 
 #define PLAT_IMX8MM_BOOT_MMC_BASE	U(0x30B50000) /* SD */
 #else
@@ -56,7 +56,7 @@
 
 /* non-secure uboot base */
 #define PLAT_NS_IMAGE_OFFSET		U(0x40200000)
-#define PLAT_NS_IMAGE_SIZE		U(0x00100000)
+#define PLAT_NS_IMAGE_SIZE		U(0x00200000)
 
 /* GICv3 base address */
 #define PLAT_GICD_BASE			U(0x38800000)
diff --git a/plat/imx/imx8m/imx8mm/platform.mk b/plat/imx/imx8m/imx8mm/platform.mk
index 1863233..ac5a809 100644
--- a/plat/imx/imx8m/imx8mm/platform.mk
+++ b/plat/imx/imx8m/imx8mm/platform.mk
@@ -63,8 +63,8 @@
 				drivers/io/io_storage.c				\
 				drivers/imx/usdhc/imx_usdhc.c			\
 				plat/imx/imx8m/imx8mm/imx8mm_bl2_mem_params_desc.c	\
-				plat/imx/imx8m/imx8mm/imx8mm_io_storage.c		\
-				plat/imx/imx8m/imx8mm/imx8mm_image_load.c		\
+				plat/imx/common/imx_io_storage.c		\
+				plat/imx/imx8m/imx8m_image_load.c		\
 				lib/optee/optee_utils.c
 endif
 
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c b/plat/imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c
new file mode 100644
index 0000000..08cbeeb
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <context.h>
+#include <drivers/arm/tzc380.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/mmc.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+#include <lib/optee_utils.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include <imx8m_caam.h>
+#include "imx8mp_private.h"
+#include <imx_aipstz.h>
+#include <imx_rdc.h>
+#include <imx_uart.h>
+#include <plat/common/platform.h>
+#include <plat_imx8.h>
+#include <platform_def.h>
+
+
+static const struct aipstz_cfg aipstz[] = {
+	{IMX_AIPSTZ1, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{IMX_AIPSTZ2, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{IMX_AIPSTZ3, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{IMX_AIPSTZ4, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{0},
+};
+
+void bl2_el3_early_platform_setup(u_register_t arg0, u_register_t arg1,
+		u_register_t arg2, u_register_t arg3)
+{
+	static console_t console;
+	unsigned int i;
+
+	/* Enable CSU NS access permission */
+	for (i = 0U; i < 64; i++) {
+		mmio_write_32(IMX_CSU_BASE + i * 4, 0x00ff00ff);
+	}
+
+	imx_aipstz_init(aipstz);
+
+	console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
+		IMX_CONSOLE_BAUDRATE, &console);
+
+	generic_delay_timer_init();
+
+	/* select the CKIL source to 32K OSC */
+	mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_MISC_CTL, 0x1);
+
+	/* Open handles to a FIP image */
+	plat_imx_io_setup();
+}
+
+void bl2_el3_plat_arch_setup(void)
+{
+}
+
+void bl2_platform_setup(void)
+{
+}
+
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+	int err = 0;
+	bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+	bl_mem_params_node_t *pager_mem_params = NULL;
+	bl_mem_params_node_t *paged_mem_params = NULL;
+
+	assert(bl_mem_params);
+
+	switch (image_id) {
+	case BL32_IMAGE_ID:
+		pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+		assert(pager_mem_params);
+
+		paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+		assert(paged_mem_params);
+
+		err = parse_optee_header(&bl_mem_params->ep_info,
+					 &pager_mem_params->image_info,
+					 &paged_mem_params->image_info);
+		if (err != 0) {
+			WARN("OPTEE header parse error.\n");
+		}
+
+		break;
+	default:
+		/* Do nothing in default case */
+		break;
+	}
+
+	return err;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return COUNTER_FREQUENCY;
+}
+
+void bl2_plat_runtime_setup(void)
+{
+	return;
+}
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_bl2_mem_params_desc.c b/plat/imx/imx8m/imx8mp/imx8mp_bl2_mem_params_desc.c
new file mode 100644
index 0000000..f2f6808
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/imx8mp_bl2_mem_params_desc.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+	{
+		.image_id = BL31_IMAGE_ID,
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+				      entry_point_info_t,
+				      SECURE | EXECUTABLE | EP_FIRST_EXE),
+		.ep_info.pc = BL31_BASE,
+		.ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX,
+					DISABLE_ALL_EXCEPTIONS),
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_PLAT_SETUP),
+		.image_info.image_base = BL31_BASE,
+		.image_info.image_max_size = BL31_LIMIT - BL31_BASE,
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+	{
+		.image_id = BL32_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+				      entry_point_info_t,
+				      SECURE | EXECUTABLE),
+		.ep_info.pc = BL32_BASE,
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
+				      image_info_t, 0),
+
+		.image_info.image_base = BL32_BASE,
+		.image_info.image_max_size = BL32_SIZE,
+
+		.next_handoff_image_id = BL33_IMAGE_ID,
+	},
+	{
+		.image_id = BL32_EXTRA1_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+				      entry_point_info_t,
+				      SECURE | NON_EXECUTABLE),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2,
+				      image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+		.image_info.image_base = BL32_BASE,
+		.image_info.image_max_size =  BL32_SIZE,
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+	{
+		/* This is a zero sized image so we don't set base or size */
+		.image_id = BL32_EXTRA2_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | NON_EXECUTABLE),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+	{
+		.image_id = BL33_IMAGE_ID,
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
+				      entry_point_info_t,
+				      NON_SECURE | EXECUTABLE),
+		# ifdef PRELOADED_BL33_BASE
+			.ep_info.pc = PLAT_NS_IMAGE_OFFSET,
+
+			SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+					      VERSION_2, image_info_t,
+					      IMAGE_ATTRIB_SKIP_LOADING),
+		# else
+			.ep_info.pc = PLAT_NS_IMAGE_OFFSET,
+
+			SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+					      VERSION_2, image_info_t, 0),
+			.image_info.image_base = PLAT_NS_IMAGE_OFFSET,
+			.image_info.image_max_size = PLAT_NS_IMAGE_SIZE,
+		# endif /* PRELOADED_BL33_BASE */
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	}
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs);
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_rotpk.S b/plat/imx/imx8m/imx8mp/imx8mp_rotpk.S
new file mode 100644
index 0000000..a4c7ce1
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/imx8mp_rotpk.S
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+	.global imx8mp_rotpk_hash
+	.global imx8mp_rotpk_hash_end
+imx8mp_rotpk_hash:
+	/* DER header */
+	.byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
+	.byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+	/* SHA256 */
+	.incbin ROTPK_HASH
+imx8mp_rotpk_hash_end:
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_trusted_boot.c b/plat/imx/imx8m/imx8mp/imx8mp_trusted_boot.c
new file mode 100644
index 0000000..5d1a6c2
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/imx8mp_trusted_boot.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+
+extern char imx8mp_rotpk_hash[], imx8mp_rotpk_hash_end[];
+
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+	*key_ptr = imx8mp_rotpk_hash;
+	*key_len = imx8mp_rotpk_hash_end - imx8mp_rotpk_hash;
+	*flags = ROTPK_IS_HASH;
+
+	return 0;
+}
+
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+	*nv_ctr = 0;
+
+	return 0;
+}
+
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+	return 1;
+}
+
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+	return get_mbedtls_heap_helper(heap_addr, heap_size);
+}
diff --git a/plat/imx/imx8m/imx8mp/include/imx8mp_private.h b/plat/imx/imx8m/imx8mp/include/imx8mp_private.h
new file mode 100644
index 0000000..0a02334
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/include/imx8mp_private.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX8MP_PRIVATE_H
+#define IMX8MP_PRIVATE_H
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void plat_imx_io_setup(void);
+
+#endif /* IMX8MP_PRIVATE_H */
diff --git a/plat/imx/imx8m/imx8mp/include/platform_def.h b/plat/imx/imx8m/imx8mp/include/platform_def.h
index 832bed1..14b7ea0 100644
--- a/plat/imx/imx8m/imx8mp/include/platform_def.h
+++ b/plat/imx/imx8m/imx8mp/include/platform_def.h
@@ -6,6 +6,7 @@
 #ifndef PLATFORM_DEF_H
 #define PLATFORM_DEF_H
 
+#include <common/tbbr/tbbr_img_def.h>
 #include <lib/utils_def.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
 
@@ -34,8 +35,23 @@
 #define PLAT_WAIT_RET_STATE		U(1)
 #define PLAT_STOP_OFF_STATE		U(3)
 
+#if defined(NEED_BL2)
+#define BL2_BASE			U(0x960000)
+#define BL2_LIMIT			U(0x980000)
+#define BL31_BASE			U(0x940000)
+#define BL31_LIMIT			U(0x960000)
+#define IMX_FIP_BASE			U(0x40310000)
+#define IMX_FIP_SIZE			U(0x000300000)
+#define IMX_FIP_LIMIT			U(FIP_BASE + FIP_SIZE)
+
+/* Define FIP image location on eMMC */
+#define IMX_FIP_MMC_BASE		U(0x100000)
+
+#define PLAT_IMX8MP_BOOT_MMC_BASE	U(0x30B50000) /* SD */
+#else
 #define BL31_BASE			U(0x960000)
 #define BL31_LIMIT			U(0x980000)
+#endif
 
 #define PLAT_PRI_BITS			U(3)
 #define PLAT_SDEI_CRITICAL_PRI		0x10
@@ -44,6 +60,7 @@
 
 /* non-secure uboot base */
 #define PLAT_NS_IMAGE_OFFSET		U(0x40200000)
+#define PLAT_NS_IMAGE_SIZE		U(0x00200000)
 
 /* GICv3 base address */
 #define PLAT_GICD_BASE			U(0x38800000)
@@ -150,6 +167,10 @@
 
 #define IMX_WDOG_B_RESET
 
+#define MAX_IO_HANDLES			3U
+#define MAX_IO_DEVICES			2U
+#define MAX_IO_BLOCK_DEVICES		1U
+
 #define GIC_MAP		MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW)
 #define AIPS_MAP	MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW) /* AIPS map */
 #define OCRAM_S_MAP	MAP_REGION_FLAT(OCRAM_S_BASE, OCRAM_S_SIZE, MT_MEMORY | MT_RW) /* OCRAM_S */
diff --git a/plat/imx/imx8m/imx8mp/platform.mk b/plat/imx/imx8m/imx8mp/platform.mk
index 6be2f98..823b5d6 100644
--- a/plat/imx/imx8m/imx8mp/platform.mk
+++ b/plat/imx/imx8m/imx8mp/platform.mk
@@ -6,7 +6,9 @@
 
 PLAT_INCLUDES		:=	-Iplat/imx/common/include		\
 				-Iplat/imx/imx8m/include		\
-				-Iplat/imx/imx8m/imx8mp/include
+				-Iplat/imx/imx8m/imx8mp/include		\
+				-Idrivers/imx/usdhc			\
+				-Iinclude/common/tbbr
 # Translation tables library
 include lib/xlat_tables_v2/xlat_tables.mk
 
@@ -40,6 +42,96 @@
 				${IMX_GIC_SOURCES}				\
 				${XLAT_TABLES_LIB_SRCS}
 
+ifeq (${NEED_BL2},yes)
+BL2_SOURCES		+=	common/desc_image_load.c			\
+				plat/imx/common/imx8_helpers.S			\
+				plat/imx/common/imx_uart_console.S		\
+				plat/imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c	\
+				plat/imx/imx8m/imx8mp/gpc.c			\
+				plat/imx/imx8m/imx_aipstz.c			\
+				plat/imx/imx8m/imx_rdc.c			\
+				plat/imx/imx8m/imx8m_caam.c			\
+				plat/common/plat_psci_common.c			\
+				lib/cpus/aarch64/cortex_a53.S			\
+				drivers/arm/tzc/tzc380.c			\
+				drivers/delay_timer/delay_timer.c		\
+				drivers/delay_timer/generic_delay_timer.c	\
+				${PLAT_GIC_SOURCES}				\
+				${PLAT_DRAM_SOURCES}				\
+				${XLAT_TABLES_LIB_SRCS}				\
+				drivers/mmc/mmc.c				\
+				drivers/io/io_block.c				\
+				drivers/io/io_fip.c				\
+				drivers/io/io_memmap.c				\
+				drivers/io/io_storage.c				\
+				drivers/imx/usdhc/imx_usdhc.c			\
+				plat/imx/imx8m/imx8mp/imx8mp_bl2_mem_params_desc.c	\
+				plat/imx/common/imx_io_storage.c		\
+				plat/imx/imx8m/imx8m_image_load.c		\
+				lib/optee/optee_utils.c
+endif
+
+# Add the build options to pack BLx images and kernel device tree
+# in the FIP if the platform requires.
+ifneq ($(BL2),)
+RESET_TO_BL31		:=	0
+$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert))
+endif
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2))
+endif
+ifneq ($(HW_CONFIG),)
+$(eval $(call TOOL_ADD_IMG,HW_CONFIG,--hw-config))
+endif
+
+ifeq (${NEED_BL2},yes)
+$(eval $(call add_define,NEED_BL2))
+LOAD_IMAGE_V2		:=	1
+# Non-TF Boot ROM
+BL2_AT_EL3		:=	1
+endif
+
+ifneq (${TRUSTED_BOARD_BOOT},0)
+
+include drivers/auth/mbedtls/mbedtls_crypto.mk
+include drivers/auth/mbedtls/mbedtls_x509.mk
+
+AUTH_SOURCES	:=	drivers/auth/auth_mod.c			\
+			drivers/auth/crypto_mod.c		\
+			drivers/auth/img_parser_mod.c		\
+			drivers/auth/tbbr/tbbr_cot_common.c     \
+			drivers/auth/tbbr/tbbr_cot_bl2.c
+
+BL2_SOURCES		+=	${AUTH_SOURCES}					\
+				plat/common/tbbr/plat_tbbr.c			\
+				plat/imx/imx8m/imx8mp/imx8mp_trusted_boot.c	\
+				plat/imx/imx8m/imx8mp/imx8mp_rotpk.S
+
+ROT_KEY             = $(BUILD_PLAT)/rot_key.pem
+ROTPK_HASH          = $(BUILD_PLAT)/rotpk_sha256.bin
+
+$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
+$(eval $(call MAKE_LIB_DIRS))
+
+$(BUILD_PLAT)/bl2/imx8mp_rotpk.o: $(ROTPK_HASH)
+
+certificates: $(ROT_KEY)
+
+$(ROT_KEY): | $(BUILD_PLAT)
+	@echo "  OPENSSL $@"
+	@if [ ! -f $(ROT_KEY) ]; then \
+		openssl genrsa 2048 > $@ 2>/dev/null; \
+	fi
+
+$(ROTPK_HASH): $(ROT_KEY)
+	@echo "  OPENSSL $@"
+	$(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\
+	openssl dgst -sha256 -binary > $@ 2>/dev/null
+endif
+
 USE_COHERENT_MEM	:=	1
 RESET_TO_BL31		:=	1
 A53_DISABLE_NON_TEMPORAL_HINT := 0
diff --git a/plat/marvell/armada/a3k/common/a3700_common.mk b/plat/marvell/armada/a3k/common/a3700_common.mk
index 7d95e48..9550452 100644
--- a/plat/marvell/armada/a3k/common/a3700_common.mk
+++ b/plat/marvell/armada/a3k/common/a3700_common.mk
@@ -13,7 +13,7 @@
 PLAT_COMMON_BASE		:= $(PLAT_FAMILY_BASE)/common
 MARVELL_DRV_BASE		:= drivers/marvell
 MARVELL_COMMON_BASE		:= $(MARVELL_PLAT_BASE)/common
-HANDLE_EA_EL3_FIRST		:= 1
+ERRATA_A53_1530924		:= 1
 
 include plat/marvell/marvell.mk
 
@@ -53,7 +53,6 @@
 				$(PLAT_COMMON_BASE)/dram_win.c		\
 				$(PLAT_COMMON_BASE)/io_addr_dec.c	\
 				$(PLAT_COMMON_BASE)/marvell_plat_config.c     \
-				$(PLAT_COMMON_BASE)/a3700_ea.c		\
 				$(PLAT_FAMILY_BASE)/$(PLAT)/plat_bl31_setup.c \
 				$(MARVELL_COMMON_BASE)/marvell_cci.c	\
 				$(MARVELL_COMMON_BASE)/marvell_ddr_info.c	\
@@ -63,6 +62,10 @@
 				$(PLAT_COMMON_BASE)/a3700_sip_svc.c	\
 				$(MARVELL_DRV)
 
+ifeq ($(HANDLE_EA_EL3_FIRST),1)
+BL31_SOURCES		+=	$(PLAT_COMMON_BASE)/a3700_ea.c
+endif
+
 ifeq ($(CM3_SYSTEM_RESET),1)
 BL31_SOURCES		+=	$(PLAT_COMMON_BASE)/cm3_system_reset.c
 endif
@@ -74,44 +77,45 @@
 ifdef WTP
 
 $(if $(wildcard $(value WTP)/*),,$(error "'WTP=$(value WTP)' was specified, but '$(value WTP)' directory does not exist"))
-$(if $(shell test -s "$(value WTP)/branch.txt" || git -C $(value WTP) rev-parse --show-cdup 2>&1),$(error "'WTP=$(value WTP)' was specified, but '$(value WTP)' does not contain valid Marvell a3700_utils release tarball nor git repository"))
+$(if $(shell git -C $(value WTP) rev-parse --show-cdup 2>&1),$(error "'WTP=$(value WTP)' was specified, but '$(value WTP)' does not contain valid A3700-utils-marvell git repository"))
 
-DOIMAGEPATH	:= $(WTP)
-DOIMAGETOOL	:= $(DOIMAGEPATH)/wtptp/src/TBB_Linux/release/TBB_linux
+TBB		:= $(WTP)/wtptp/src/TBB_Linux/release/TBB_linux
 
 BUILD_UART	:= uart-images
 UART_IMAGE	:= $(BUILD_UART).tgz.bin
 
 ifeq ($(MARVELL_SECURE_BOOT),1)
-DOIMAGE_CFG	:= $(BUILD_PLAT)/atf-tim.txt
-DOIMAGEUART_CFG	:= $(BUILD_PLAT)/$(BUILD_UART)/atf-tim.txt
-IMAGESPATH	:= $(DOIMAGEPATH)/tim/trusted
-TIMNCFG		:= $(BUILD_PLAT)/atf-timN.txt
-TIMNUARTCFG	:= $(BUILD_PLAT)/$(BUILD_UART)/atf-timN.txt
-TIMNSIG		:= $(IMAGESPATH)/timnsign.txt
-TIM2IMGARGS	:= -i $(DOIMAGE_CFG) -n $(TIMNCFG)
-TIMN_IMAGE	:= $$(grep "Image Filename:" -m 1 $(TIMNCFG) | cut -c 17-)
+TIM_CFG		:= $(BUILD_PLAT)/atf-tim.txt
+TIM_UART_CFG	:= $(BUILD_PLAT)/$(BUILD_UART)/atf-tim.txt
+IMAGESPATH	:= $(WTP)/tim/trusted
+TIMN_CFG	:= $(BUILD_PLAT)/atf-timN.txt
+TIMN_UART_CFG	:= $(BUILD_PLAT)/$(BUILD_UART)/atf-timN.txt
+TIMN_SIG	:= $(IMAGESPATH)/timnsign.txt
+TIM2IMGARGS	:= -i $(TIM_CFG) -n $(TIMN_CFG)
+TIMN_UART_IMAGE	:= $$(grep "Image Filename:" -m 1 $(TIMN_UART_CFG) | cut -c 17-)
 else #MARVELL_SECURE_BOOT
-DOIMAGE_CFG	:= $(BUILD_PLAT)/atf-ntim.txt
-DOIMAGEUART_CFG	:= $(BUILD_PLAT)/$(BUILD_UART)/atf-ntim.txt
-IMAGESPATH	:= $(DOIMAGEPATH)/tim/untrusted
-TIM2IMGARGS	:= -i $(DOIMAGE_CFG)
+TIM_CFG		:= $(BUILD_PLAT)/atf-ntim.txt
+TIM_UART_CFG	:= $(BUILD_PLAT)/$(BUILD_UART)/atf-ntim.txt
+IMAGESPATH	:= $(WTP)/tim/untrusted
+TIM2IMGARGS	:= -i $(TIM_CFG)
 endif #MARVELL_SECURE_BOOT
 
+TIM_UART_IMAGE	:= $$(grep "Image Filename:" -m 1 $(TIM_UART_CFG) | cut -c 17-)
+
-TIMBUILD	:= $(DOIMAGEPATH)/script/buildtim.sh
-TIM2IMG		:= $(DOIMAGEPATH)/script/tim2img.pl
-TIMDDRTOOL	:= $(DOIMAGEPATH)/tim/ddr/ddr_tool
+TIMBUILD	:= $(WTP)/script/buildtim.sh
+TIM2IMG		:= $(WTP)/script/tim2img.pl
+TIMDDRTOOL	:= $(WTP)/tim/ddr/ddr_tool
 
 $(TIMBUILD): $(TIMDDRTOOL)
 
 # WTMI_IMG is used to specify the customized RTOS image running over
 # Service CPU (CM3 processor). By the default, it points to a
 # baremetal binary of fuse programming in A3700_utils.
-WTMI_IMG	:= $(DOIMAGEPATH)/wtmi/fuse/build/fuse.bin
+WTMI_IMG	:= $(WTP)/wtmi/fuse/build/fuse.bin
 
 # WTMI_MULTI_IMG is composed of CM3 RTOS image (WTMI_IMG)
 # and sys-init image.
-WTMI_MULTI_IMG		:= $(DOIMAGEPATH)/wtmi/build/wtmi.bin
+WTMI_MULTI_IMG		:= $(WTP)/wtmi/build/wtmi.bin
 
 WTMI_ENC_IMG		:= wtmi-enc.bin
 
@@ -124,16 +128,21 @@
 BOOTDEV			?= SPINOR
 PARTNUM			?= 0
 
-TIM_IMAGE		:= $$(grep "Image Filename:" -m 1 $(DOIMAGE_CFG) | cut -c 17-)
-TIMBLDARGS		:= $(MARVELL_SECURE_BOOT) $(BOOTDEV) $(IMAGESPATH) $(DOIMAGEPATH) $(CLOCKSPRESET) \
-				$(DDR_TOPOLOGY) $(PARTNUM) $(DEBUG) $(DOIMAGE_CFG) $(TIMNCFG) $(TIMNSIG) 1
-TIMBLDUARTARGS		:= $(MARVELL_SECURE_BOOT) UART $(IMAGESPATH) $(DOIMAGEPATH) $(CLOCKSPRESET) \
-				$(DDR_TOPOLOGY) 0 0 $(DOIMAGEUART_CFG) $(TIMNUARTCFG) $(TIMNSIG) 0
+TIMBLDARGS		:= $(MARVELL_SECURE_BOOT) $(BOOTDEV) $(IMAGESPATH) $(WTP) $(CLOCKSPRESET) \
+				$(DDR_TOPOLOGY) $(PARTNUM) $(DEBUG) $(TIM_CFG) $(TIMN_CFG) $(TIMN_SIG) 1
+TIMBLDUARTARGS		:= $(MARVELL_SECURE_BOOT) UART $(IMAGESPATH) $(WTP) $(CLOCKSPRESET) \
+				$(DDR_TOPOLOGY) 0 0 $(TIM_UART_CFG) $(TIMN_UART_CFG) $(TIMN_SIG) 0
+
+UART_IMAGES		:= $(BUILD_UART)/$(TIM_UART_IMAGE)
+ifeq ($(MARVELL_SECURE_BOOT),1)
+UART_IMAGES		+= $(BUILD_UART)/$(TIMN_UART_IMAGE)
+endif
+UART_IMAGES		+= $(BUILD_UART)/wtmi_h.bin $(BUILD_UART)/boot-image_h.bin
 
 CRYPTOPP_LIBDIR		?= $(CRYPTOPP_PATH)
 CRYPTOPP_INCDIR		?= $(CRYPTOPP_PATH)
 
-$(DOIMAGETOOL): FORCE
+$(TBB): FORCE
 	$(if $(CRYPTOPP_LIBDIR),,$(error "Platform '$(PLAT)' for WTP image tool requires CRYPTOPP_PATH or CRYPTOPP_LIBDIR. Please set CRYPTOPP_PATH or CRYPTOPP_LIBDIR to point to the right directory"))
 	$(if $(CRYPTOPP_INCDIR),,$(error "Platform '$(PLAT)' for WTP image tool requires CRYPTOPP_PATH or CRYPTOPP_INCDIR. Please set CRYPTOPP_PATH or CRYPTOPP_INCDIR to point to the right directory"))
 	$(if $(wildcard $(CRYPTOPP_LIBDIR)/*),,$(error "Either 'CRYPTOPP_PATH' or 'CRYPTOPP_LIB' was set to '$(CRYPTOPP_LIBDIR)', but '$(CRYPTOPP_LIBDIR)' does not exist"))
@@ -141,10 +150,10 @@
 ifdef CRYPTOPP_PATH
 	$(Q)$(MAKE) --no-print-directory -C $(CRYPTOPP_PATH) -f GNUmakefile
 endif
-	$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH)/wtptp/src/TBB_Linux -f TBB_linux.mak LIBDIR=$(CRYPTOPP_LIBDIR) INCDIR=$(CRYPTOPP_INCDIR)
+	$(Q)$(MAKE) --no-print-directory -C $(WTP)/wtptp/src/TBB_Linux -f TBB_linux.mak LIBDIR=$(CRYPTOPP_LIBDIR) INCDIR=$(CRYPTOPP_INCDIR)
 
 $(WTMI_MULTI_IMG): FORCE
-	$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH) WTMI_IMG=$(WTMI_IMG) DDR_TOPOLOGY=$(DDR_TOPOLOGY) CLOCKSPRESET=$(CLOCKSPRESET) WTMI
+	$(Q)$(MAKE) --no-print-directory -C $(WTP) WTMI_IMG=$(WTMI_IMG) DDR_TOPOLOGY=$(DDR_TOPOLOGY) CLOCKSPRESET=$(CLOCKSPRESET) WTMI
 
 $(BUILD_PLAT)/wtmi.bin: $(WTMI_MULTI_IMG)
 	$(Q)cp -a $(WTMI_MULTI_IMG) $(BUILD_PLAT)/wtmi.bin
@@ -152,40 +161,40 @@
 $(TIMDDRTOOL): FORCE
 	$(if $(value MV_DDR_PATH),,$(error "Platform '${PLAT}' for ddr tool requires MV_DDR_PATH. Please set MV_DDR_PATH to point to the right directory"))
 	$(if $(wildcard $(value MV_DDR_PATH)/*),,$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' directory does not exist"))
-	$(if $(shell test -s "$(value MV_DDR_PATH)/branch.txt" || git -C $(value MV_DDR_PATH) rev-parse --show-cdup 2>&1),$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' does not contain valid Marvell mv_ddr release tarball nor git repository"))
-	$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH) MV_DDR_PATH=$(MV_DDR_PATH) DDR_TOPOLOGY=$(DDR_TOPOLOGY) mv_ddr
+	$(if $(shell git -C $(value MV_DDR_PATH) rev-parse --show-cdup 2>&1),$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' does not contain valid mv-ddr-marvell git repository"))
+	$(Q)$(MAKE) --no-print-directory -C $(WTP) MV_DDR_PATH=$(MV_DDR_PATH) DDR_TOPOLOGY=$(DDR_TOPOLOGY) mv_ddr
 
-$(BUILD_PLAT)/$(UART_IMAGE): $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/wtmi.bin $(DOIMAGETOOL) $(TIMBUILD) $(TIMDDRTOOL)
+$(BUILD_PLAT)/$(UART_IMAGE): $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/wtmi.bin $(TBB) $(TIMBUILD) $(TIMDDRTOOL)
 	@$(ECHO_BLANK_LINE)
 	@echo "Building uart images"
 	$(Q)mkdir -p $(BUILD_PLAT)/$(BUILD_UART)
 	$(Q)cp -a $(BUILD_PLAT)/wtmi.bin $(BUILD_PLAT)/$(BUILD_UART)/wtmi.bin
 	$(Q)cp -a $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/$(BUILD_UART)/$(BOOT_IMAGE)
 	$(Q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(TIMBUILD) $(TIMBLDUARTARGS)
-	$(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(DOIMAGEUART_CFG)
-	$(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(DOIMAGEUART_CFG)
+	$(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIM_UART_CFG)
+	$(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIM_UART_CFG)
 ifeq ($(MARVELL_SECURE_BOOT),1)
-	$(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIMNUARTCFG)
-	$(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIMNUARTCFG)
+	$(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIMN_UART_CFG)
+	$(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIMN_UART_CFG)
 endif
-	$(Q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(DOIMAGETOOL) -r $(DOIMAGEUART_CFG) -v -D
+	$(Q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(TBB) -r $(TIM_UART_CFG) -v -D
 ifeq ($(MARVELL_SECURE_BOOT),1)
-	$(Q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(DOIMAGETOOL) -r $(TIMNUARTCFG)
+	$(Q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(TBB) -r $(TIMN_UART_CFG)
 endif
-	$(Q)tar czf $(BUILD_PLAT)/$(UART_IMAGE) -C $(BUILD_PLAT) $(BUILD_UART)/$(TIM_IMAGE) $(BUILD_UART)/wtmi_h.bin $(BUILD_UART)/boot-image_h.bin
+	$(Q)tar czf $(BUILD_PLAT)/$(UART_IMAGE) -C $(BUILD_PLAT) $(UART_IMAGES)
 	@$(ECHO_BLANK_LINE)
 	@echo "Built $@ successfully"
 	@$(ECHO_BLANK_LINE)
 
-$(BUILD_PLAT)/$(FLASH_IMAGE): $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/wtmi.bin $(DOIMAGETOOL) $(TIMBUILD) $(TIMDDRTOOL) $(TIM2IMG)
+$(BUILD_PLAT)/$(FLASH_IMAGE): $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/wtmi.bin $(TBB) $(TIMBUILD) $(TIMDDRTOOL) $(TIM2IMG)
 	@$(ECHO_BLANK_LINE)
 	@echo "Building flash image"
 	$(Q)cd $(BUILD_PLAT) && $(TIMBUILD) $(TIMBLDARGS)
-	$(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(DOIMAGE_CFG)
-	$(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(DOIMAGE_CFG)
+	$(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIM_CFG)
+	$(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIM_CFG)
 ifeq ($(MARVELL_SECURE_BOOT),1)
-	$(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIMNCFG)
-	$(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIMNCFG)
+	$(Q)sed -i 's|WTMI_IMG|wtmi.bin|1' $(TIMN_CFG)
+	$(Q)sed -i 's|BOOT_IMAGE|$(BOOT_IMAGE)|1' $(TIMN_CFG)
 	@$(ECHO_BLANK_LINE)
 	@echo "=======================================================";
 	@echo "  Secure boot. Encrypting wtmi and boot-image";
@@ -203,11 +212,11 @@
 	-K `cat $(IMAGESPATH)/aes-256.txt` -nosalt \
 	-iv `cat $(IMAGESPATH)/iv.txt` -p
 endif
-	$(Q)cd $(BUILD_PLAT) && $(DOIMAGETOOL) -r $(DOIMAGE_CFG) -v -D
+	$(Q)cd $(BUILD_PLAT) && $(TBB) -r $(TIM_CFG) -v -D
 ifeq ($(MARVELL_SECURE_BOOT),1)
-	$(Q)cd $(BUILD_PLAT) && $(DOIMAGETOOL) -r $(TIMNCFG)
-	$(Q)sed -i 's|wtmi.bin|$(WTMI_ENC_IMG)|1' $(TIMNCFG)
-	$(Q)sed -i 's|$(BOOT_IMAGE)|$(BOOT_ENC_IMAGE)|1' $(TIMNCFG)
+	$(Q)cd $(BUILD_PLAT) && $(TBB) -r $(TIMN_CFG)
+	$(Q)sed -i 's|wtmi.bin|$(WTMI_ENC_IMG)|1' $(TIMN_CFG)
+	$(Q)sed -i 's|$(BOOT_IMAGE)|$(BOOT_ENC_IMAGE)|1' $(TIMN_CFG)
 endif
 	$(Q)cd $(BUILD_PLAT) && $(TIM2IMG) $(TIM2IMGARGS) -o $(BUILD_PLAT)/$(FLASH_IMAGE)
 	@$(ECHO_BLANK_LINE)
@@ -218,8 +227,8 @@
 
 .PHONY: mrvl_clean
 mrvl_clean:
-	-$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH) MV_DDR_PATH=$(MV_DDR_PATH) clean
-	-$(Q)$(MAKE) --no-print-directory -C $(DOIMAGEPATH)/wtptp/src/TBB_Linux -f TBB_linux.mak clean
+	-$(Q)$(MAKE) --no-print-directory -C $(WTP) MV_DDR_PATH=$(MV_DDR_PATH) clean
+	-$(Q)$(MAKE) --no-print-directory -C $(WTP)/wtptp/src/TBB_Linux -f TBB_linux.mak clean
 ifdef CRYPTOPP_PATH
 	-$(Q)$(MAKE) --no-print-directory -C $(CRYPTOPP_PATH) -f GNUmakefile clean
 endif
diff --git a/plat/marvell/armada/a3k/common/a3700_ea.c b/plat/marvell/armada/a3k/common/a3700_ea.c
index dd46beb..4a58fc6 100644
--- a/plat/marvell/armada/a3k/common/a3700_ea.c
+++ b/plat/marvell/armada/a3k/common/a3700_ea.c
@@ -7,17 +7,80 @@
 #include <common/bl_common.h>
 #include <common/debug.h>
 #include <arch_helpers.h>
+#include <plat/common/platform.h>
+#include <bl31/ea_handle.h>
 
-#define ADVK_SERROR_SYNDROME 0xbf000002
+#define A53_SERR_INT_AXI_SLVERR_ON_EXTERNAL_ACCESS 0xbf000002
 
+#if !ENABLE_BACKTRACE
+static const char *get_el_str(unsigned int el)
+{
+	if (el == MODE_EL3) {
+		return "EL3";
+	} else if (el == MODE_EL2) {
+		return "EL2";
+	}
+	return "S-EL1";
+}
+#endif /* !ENABLE_BACKTRACE */
+
+/*
+ * This source file with custom plat_ea_handler function is compiled only when
+ * building TF-A with compile option HANDLE_EA_EL3_FIRST=1
+ */
 void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
 		void *handle, uint64_t flags)
 {
-	if (syndrome != ADVK_SERROR_SYNDROME) {
-		ERROR("Unhandled External Abort received on 0x%lx at EL3!\n",
-			read_mpidr_el1());
-		ERROR(" exception reason=%u syndrome=0x%llx\n", ea_reason,
-				syndrome);
-		panic();
+	unsigned int level = (unsigned int)GET_EL(read_spsr_el3());
+
+	/*
+	 * Asynchronous External Abort with syndrome 0xbf000002 on Cortex A53
+	 * core means SError interrupt caused by AXI SLVERR on external access.
+	 *
+	 * In most cases this indicates a bug in U-Boot or Linux kernel driver
+	 * pci-aardvark.c which implements access to A3700 PCIe config space.
+	 * Driver does not wait for PCIe PIO transfer completion and try to
+	 * start a new PCIe PIO transfer while previous has not finished yet.
+	 * A3700 PCIe controller in this case sends SLVERR via AXI which results
+	 * in a fatal Asynchronous SError interrupt on Cortex A53 CPU.
+	 *
+	 * Following patches fix that bug in U-Boot and Linux kernel drivers:
+	 * https://source.denx.de/u-boot/u-boot/-/commit/eccbd4ad8e4e182638eafbfb87ac139c04f24a01
+	 * https://git.kernel.org/stable/c/f18139966d072dab8e4398c95ce955a9742e04f7
+	 *
+	 * As a hacky workaround for unpatched U-Boot and Linux kernel drivers
+	 * ignore all asynchronous aborts with that syndrome value received on
+	 * CPU from level lower than EL3.
+	 *
+	 * Because these aborts are delivered on CPU asynchronously, they are
+	 * imprecise and we cannot check the real reason of abort and neither
+	 * who and why sent this abort. We expect that on A3700 it is always
+	 * PCIe controller.
+	 *
+	 * Hence ignoring all aborts with this syndrome value is just a giant
+	 * hack that we need only because of bugs in old U-Boot and Linux kernel
+	 * versions and because it was decided that TF-A would implement this
+	 * hack for U-Boot and Linux kernel it in this way. New patched U-Boot
+	 * and kernel versions do not need it anymore.
+	 *
+	 * Links to discussion about this workaround:
+	 * https://lore.kernel.org/linux-pci/20190316161243.29517-1-repk@triplefau.lt/
+	 * https://lore.kernel.org/linux-pci/971be151d24312cc533989a64bd454b4@www.loen.fr/
+	 * https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/1541
+	 */
+	if (level < MODE_EL3 && ea_reason == ERROR_EA_ASYNC &&
+	    syndrome == A53_SERR_INT_AXI_SLVERR_ON_EXTERNAL_ACCESS) {
+		ERROR_NL();
+		ERROR("Ignoring Asynchronous External Abort with"
+		     " syndrome 0x%llx received on 0x%lx from %s\n",
+		     syndrome, read_mpidr_el1(), get_el_str(level));
+		ERROR("SError interrupt: AXI SLVERR on external access\n");
+		ERROR("This indicates a bug in pci-aardvark.c driver\n");
+		ERROR("Please update U-Boot/Linux to the latest version\n");
+		ERROR_NL();
+		console_flush();
+		return;
 	}
+
+	plat_default_ea_handler(ea_reason, syndrome, cookie, handle, flags);
 }
diff --git a/plat/marvell/armada/a3k/common/io_addr_dec.c b/plat/marvell/armada/a3k/common/io_addr_dec.c
index b27633c..fea7f81 100644
--- a/plat/marvell/armada/a3k/common/io_addr_dec.c
+++ b/plat/marvell/armada/a3k/common/io_addr_dec.c
@@ -67,17 +67,14 @@
 	mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base,
 		      win_id, dec_win->win_offset), ctrl);
 
-	INFO("set_io_addr_dec %d result: ctrl(0x%x) base(0x%x)",
+	INFO("set_io_addr_dec %d result: ctrl(0x%x) base(0x%x) remap(0x%x)\n",
 	     win_id, mmio_read_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base,
 	     win_id, dec_win->win_offset)),
 	     mmio_read_32(MVEBU_DEC_WIN_BASE_REG(dec_win->dec_reg_base,
-			  win_id, dec_win->win_offset)));
-	if (win_id < dec_win->max_remap)
-		INFO(" remap(%x)\n",
-		     mmio_read_32(MVEBU_DEC_WIN_REMAP_REG(dec_win->dec_reg_base,
-		     win_id, dec_win->win_offset)));
-	else
-		INFO("\n");
+			  win_id, dec_win->win_offset)),
+	     (win_id < dec_win->max_remap) ?
+		mmio_read_32(MVEBU_DEC_WIN_REMAP_REG(dec_win->dec_reg_base,
+			     win_id, dec_win->win_offset)) : 0);
 }
 
 /* Set io decode window */
@@ -167,12 +164,11 @@
 			ERROR("Failed to set IO address decode\n");
 			return -1;
 		}
-		INFO("Set IO decode window successfully, base(0x%x)",
-		     io_dec_win->dec_reg_base);
-		INFO(" win_attr(%x) max_dram_win(%d) max_remap(%d)",
+		INFO("Set IO decode window successfully, base(0x%x)"
+		     " win_attr(%x) max_dram_win(%d) max_remap(%d)"
+		     " win_offset(%d)\n", io_dec_win->dec_reg_base,
 		     io_dec_win->win_attr, io_dec_win->max_dram_win,
-		     io_dec_win->max_remap);
-		INFO(" win_offset(%d)\n", io_dec_win->win_offset);
+		     io_dec_win->max_remap, io_dec_win->win_offset);
 	}
 
 	return 0;
diff --git a/plat/marvell/armada/a8k/common/a8k_common.mk b/plat/marvell/armada/a8k/common/a8k_common.mk
index 90883f2..9474d08 100644
--- a/plat/marvell/armada/a8k/common/a8k_common.mk
+++ b/plat/marvell/armada/a8k/common/a8k_common.mk
@@ -80,16 +80,19 @@
 				drivers/arm/gic/v2/gicv2_helpers.c	\
 				plat/common/plat_gicv2.c
 
-PLAT_INCLUDES		:=	-I$(BOARD_DIR)				\
+PLAT_INCLUDES		+=	-I$(BOARD_DIR)				\
 				-I$(BOARD_DIR)/board			\
+				-I$(CURDIR)/drivers/marvell		\
 				-I$(PLAT_COMMON_BASE)/include		\
 				-I$(PLAT_INCLUDE_BASE)/common
 
 PLAT_BL_COMMON_SOURCES	:=	$(PLAT_COMMON_BASE)/aarch64/a8k_common.c \
 				drivers/ti/uart/aarch64/16550_console.S
 
+ifndef BLE_PORTING_SOURCES
 BLE_PORTING_SOURCES	:=	$(BOARD_DIR)/board/dram_port.c \
 				$(BOARD_DIR)/board/marvell_plat_config.c
+endif
 
 MARVELL_MOCHI_DRV	+=	$(MARVELL_DRV_BASE)/mochi/cp110_setup.c
 
@@ -124,7 +127,9 @@
 MARVELL_DRV		+=	$(MARVELL_DRV_BASE)/mg_conf_cm3/mg_conf_cm3.c
 endif
 
+ifndef BL31_PORTING_SOURCES
 BL31_PORTING_SOURCES	:=	$(BOARD_DIR)/board/marvell_plat_config.c
+endif
 
 ifeq ($(SYSTEM_POWER_SUPPORT),1)
 BL31_PORTING_SOURCES	+=	$(BOARD_DIR)/board/system_power.c
@@ -161,7 +166,7 @@
 BLE_PATH	?=  $(PLAT_COMMON_BASE)/ble
 
 include ${BLE_PATH}/ble.mk
-$(eval $(call MAKE_BL,e))
+$(eval $(call MAKE_BL,ble))
 
 clean realclean distclean: mrvl_clean
 
diff --git a/plat/marvell/armada/a8k/common/ble/ble.mk b/plat/marvell/armada/a8k/common/ble/ble.mk
index d6d72c1..87e2ce0 100644
--- a/plat/marvell/armada/a8k/common/ble/ble.mk
+++ b/plat/marvell/armada/a8k/common/ble/ble.mk
@@ -3,8 +3,6 @@
 # SPDX-License-Identifier:     BSD-3-Clause
 # https://spdx.org/licenses
 
-MV_DDR_PATH		?=	drivers/marvell/mv_ddr
-
 MV_DDR_LIB		=	$(BUILD_PLAT)/ble/mv_ddr_lib.a
 LIBC_LIB		=	$(BUILD_PLAT)/lib/libc.a
 BLE_LIBS		=	$(MV_DDR_LIB) $(LIBC_LIB)
@@ -18,14 +16,19 @@
 				$(PLAT_MARVELL)/common/plat_delay_timer.c	\
 				$(PLAT_MARVELL)/common/marvell_console.c
 
-PLAT_INCLUDES		+= 	-I$(MV_DDR_PATH)				\
-				-I$(CURDIR)/include				\
+MV_DDR_INCLUDES		:=	-I$(CURDIR)/include				\
 				-I$(CURDIR)/include/arch/aarch64		\
 				-I$(CURDIR)/include/lib/libc			\
-				-I$(CURDIR)/include/lib/libc/aarch64		\
-				-I$(CURDIR)/drivers/marvell
+				-I$(CURDIR)/include/lib/libc/aarch64
 
 BLE_LINKERFILE		:=	$(BLE_PATH)/ble.ld.S
 
+BLE_OBJS := $(addprefix $(BUILD_PLAT)/ble/,$(call SOURCES_TO_OBJS,$(BLE_SOURCES)))
+$(BLE_OBJS): PLAT_INCLUDES += -I$(MV_DDR_PATH)
+$(BLE_OBJS): $(MV_DDR_LIB)
+
 $(MV_DDR_LIB): FORCE
-	@+make -C $(MV_DDR_PATH) --no-print-directory PLAT_INCLUDES="$(PLAT_INCLUDES)" PLATFORM=$(PLAT) ARCH=AARCH64 OBJ_DIR=$(BUILD_PLAT)/ble
+	$(if $(value MV_DDR_PATH),,$(error "Platform '$(PLAT)' for BLE requires MV_DDR_PATH. Please set MV_DDR_PATH to point to the right directory"))
+	$(if $(wildcard $(value MV_DDR_PATH)/*),,$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' directory does not exist"))
+	$(if $(shell git -C $(value MV_DDR_PATH) rev-parse --show-cdup 2>&1),$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' does not contain valid mv-ddr-marvell git repository"))
+	@+make -C $(MV_DDR_PATH) --no-print-directory PLAT_INCLUDES="$(MV_DDR_INCLUDES)" PLATFORM=$(PLAT) ARCH=AARCH64 OBJ_DIR=$(BUILD_PLAT)/ble
diff --git a/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c b/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c
new file mode 100644
index 0000000..5bae8eb
--- /dev/null
+++ b/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ * Copyright (C) 2021 Semihalf.
+ *
+ * SPDX-License-Identifier:	BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <armada_common.h>
+#include <mvebu_def.h>
+
+/*
+ * If bootrom is currently at BLE there's no need to include the memory
+ * maps structure at this point
+ */
+#ifndef IMAGE_BLE
+
+/*****************************************************************************
+ * AMB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win amb_memory_map_cp0[] = {
+	/* CP0 SPI1 CS0 Direct Mode access */
+	{0xef00,	0x1000000,	AMB_SPI1_CS0_ID},
+};
+
+struct addr_map_win amb_memory_map_cp1[] = {
+	/* CP1 SPI1 CS0 Direct Mode access */
+	{0xe800,	0x1000000,	AMB_SPI1_CS0_ID},
+};
+
+int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size,
+			       uintptr_t base)
+{
+	switch (base) {
+	case MVEBU_CP_REGS_BASE(0):
+		*win = amb_memory_map_cp0;
+		*size = ARRAY_SIZE(amb_memory_map_cp0);
+		return 0;
+	case MVEBU_CP_REGS_BASE(1):
+		*win = amb_memory_map_cp1;
+		*size = ARRAY_SIZE(amb_memory_map_cp1);
+		return 0;
+	case MVEBU_CP_REGS_BASE(2):
+	default:
+		*size = 0;
+		*win = 0;
+		return 1;
+	}
+}
+#endif
+
+/*****************************************************************************
+ * IO WIN Configuration
+ *****************************************************************************
+ */
+struct addr_map_win io_win_memory_map[] = {
+#if (CP_COUNT > 1)
+	/* SB (MCi0) internal regs */
+	{0x00000000f4000000,		0x2000000,	MCI_0_TID},
+	/* SB (MCi0) PCIe0-2 on CP1 */
+	{0x00000000e2000000,		0x7000000,	MCI_0_TID},
+	/*
+	 * Due to lack of sufficient number of IO windows registers,
+	 * below CP1 PCIE configuration must be performed in the
+	 * later firmware stages. It should replace the MCI 0 indirect
+	 * window, which becomes no longer needed.
+	 */
+	/* {0x0000000890000000,		0x30000000,	MCI_0_TID}, */
+#if (CP_COUNT > 2)
+	/* SB (MCi1) internal regs */
+	{0x00000000f6000000,		0x2000000,	MCI_1_TID},
+	/* SB (MCi1) PCIe0-2 on CP2 */
+	{0x00000000e9000000,		0x6000000,	MCI_1_TID},
+	/*
+	 * Due to lack of sufficient number of IO windows registers,
+	 * below CP2 PCIE configuration must be performed in the
+	 * later firmware stages. It should replace the MCI 1 indirect
+	 * window, which becomes no longer needed.
+	 */
+	/* {0x00000008c0000000,		0x30000000,	MCI_1_TID}, */
+#endif
+#endif
+#ifndef IMAGE_BLE
+	/* MCI 0 indirect window */
+	{MVEBU_MCI_REG_BASE_REMAP(0),	0x100000,	MCI_0_TID},
+	/* MCI 1 indirect window */
+	{MVEBU_MCI_REG_BASE_REMAP(1),	0x100000,	MCI_1_TID},
+#endif
+};
+
+/* Global Control Register - window default target */
+uint32_t marvell_get_io_win_gcr_target(int ap_index)
+{
+	/*
+	 * PIDI == iMCIP AP to SB internal MoChi connection.
+	 * In other words CP0
+	 */
+	return PIDI_TID;
+}
+
+int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win,
+				  uint32_t *size)
+{
+	*win = io_win_memory_map;
+	if (*win == NULL)
+		*size = 0;
+	else
+		*size = ARRAY_SIZE(io_win_memory_map);
+
+	return 0;
+}
+
+#ifndef IMAGE_BLE
+/*****************************************************************************
+ * IOB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win iob_memory_map_cp0[] = {
+	/* SPI1_CS0 (RUNIT) window */
+	{0x00000000ef000000,	0x1000000,	RUNIT_TID},
+	/* PEX2_X1 window */
+	{0x00000000e1000000,	0x1000000,	PEX2_TID},
+	/* PEX1_X1 window */
+	{0x00000000e0000000,	0x1000000,	PEX1_TID},
+	/* PEX0_X4 window */
+	{0x00000000c0000000,	0x20000000,	PEX0_TID},
+	{0x0000000800000000,	0x90000000,	PEX0_TID},
+};
+
+struct addr_map_win iob_memory_map_cp1[] = {
+	/* SPI1_CS0 (RUNIT) window */
+	{0x00000000e8000000,	0x1000000,	RUNIT_TID},
+	/* PEX2_X1 window */
+	{0x00000000e6000000,	0x2000000,	PEX2_TID},
+	{0x00000008b0000000,	0x10000000,	PEX2_TID},
+	/* PEX1_X1 window */
+	{0x00000000e4000000,	0x2000000,	PEX1_TID},
+	{0x00000008a0000000,	0x10000000,	PEX1_TID},
+	/* PEX0_X2 window */
+	{0x00000000e2000000,	0x2000000,	PEX0_TID},
+	{0x0000000890000000,	0x10000000,	PEX0_TID},
+};
+
+struct addr_map_win iob_memory_map_cp2[] = {
+
+	/* PEX2_X1 window */
+	{0x00000000ed000000,	0x2000000,	PEX2_TID},
+	{0x00000008e0000000,	0x10000000,	PEX2_TID},
+	/* PEX1_X1 window */
+	{0x00000000eb000000,	0x2000000,	PEX1_TID},
+	{0x00000008d0000000,	0x10000000,	PEX1_TID},
+	/* PEX0_X1 window */
+	{0x00000000e9000000,	0x2000000,	PEX0_TID},
+	{0x00000008c0000000,	0x10000000,	PEX0_TID},
+};
+
+int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size,
+			       uintptr_t base)
+{
+	switch (base) {
+	case MVEBU_CP_REGS_BASE(0):
+		*win = iob_memory_map_cp0;
+		*size = ARRAY_SIZE(iob_memory_map_cp0);
+		return 0;
+	case MVEBU_CP_REGS_BASE(1):
+		*win = iob_memory_map_cp1;
+		*size = ARRAY_SIZE(iob_memory_map_cp1);
+		return 0;
+	case MVEBU_CP_REGS_BASE(2):
+		*win = iob_memory_map_cp2;
+		*size = ARRAY_SIZE(iob_memory_map_cp2);
+		return 0;
+	default:
+		*size = 0;
+		*win = 0;
+		return 1;
+	}
+}
+#endif
+
+/*****************************************************************************
+ * CCU Configuration
+ *****************************************************************************
+ */
+struct addr_map_win ccu_memory_map[] = {	/* IO window */
+#ifdef IMAGE_BLE
+	{0x00000000f2000000,	0x6000000,	IO_0_TID}, /* IO window */
+#else
+#if LLC_SRAM
+	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
+#endif
+	{0x00000000f2000000,	0xe000000,	IO_0_TID}, /* IO window */
+	{0x00000000c0000000,	0x30000000,	IO_0_TID}, /* IO window */
+	{0x0000000800000000,	0x100000000,    IO_0_TID}, /* IO window */
+	{0x0000002000000000,	0x70e000000,	IO_0_TID}, /* IO for CV-OS */
+#endif
+};
+
+uint32_t marvell_get_ccu_gcr_target(int ap)
+{
+	return DRAM_0_TID;
+}
+
+int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win,
+			       uint32_t *size)
+{
+	*win = ccu_memory_map;
+	*size = ARRAY_SIZE(ccu_memory_map);
+
+	return 0;
+}
+
+#ifdef IMAGE_BLE
+/*****************************************************************************
+ * SKIP IMAGE Configuration
+ *****************************************************************************
+ */
+void *plat_get_skip_image_data(void)
+{
+	/* No recovery button on CN-9130 board? */
+	return NULL;
+}
+#endif
diff --git a/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/platform.mk b/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/platform.mk
new file mode 100644
index 0000000..ee55455
--- /dev/null
+++ b/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/platform.mk
@@ -0,0 +1,33 @@
+#
+# Copyright (C) 2018 Marvell International Ltd.
+# Copyright (C) 2021 Semihalf.
+#
+# SPDX-License-Identifier:	BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+PCI_EP_SUPPORT		:=	0
+
+CP_NUM			:=	1
+$(eval $(call add_define,CP_NUM))
+
+DOIMAGE_SEC     	:=	tools/doimage/secure/sec_img_7K.cfg
+
+MARVELL_MOCHI_DRV	:=	drivers/marvell/mochi/ap807_setup.c
+
+BOARD_DIR		:=	$(shell dirname $(lastword $(MAKEFILE_LIST)))
+
+#
+# CN913X CEx7 Evaluation Board shares the DRAM connectivity
+# and SerDes settings with the CN913X DB - reuse relevant
+# board-specific files.
+#
+T9130_DIR		:=	$(BOARD_DIR)/../t9130
+PLAT_INCLUDES		:=	-I$(T9130_DIR)				\
+				-I$(T9130_DIR)/board
+BLE_PORTING_SOURCES	:=	$(T9130_DIR)/board/dram_port.c		\
+				$(BOARD_DIR)/board/marvell_plat_config.c
+
+include plat/marvell/armada/a8k/common/a8k_common.mk
+
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/mediatek/common/mtk_cirq.c b/plat/mediatek/common/mtk_cirq.c
index de37986..9cf7144 100644
--- a/plat/mediatek/common/mtk_cirq.c
+++ b/plat/mediatek/common/mtk_cirq.c
@@ -541,11 +541,9 @@
 
 void mt_cirq_sw_reset(void)
 {
-#ifdef CIRQ_NEED_SW_RESET
 	uint32_t st;
 
 	st = mmio_read_32(CIRQ_CON);
 	st |= (CIRQ_SW_RESET << CIRQ_CON_SW_RST_BITS);
 	mmio_write_32(CIRQ_CON, st);
-#endif
 }
diff --git a/plat/mediatek/mt8183/drivers/sspm/sspm.c b/plat/mediatek/mt8183/drivers/sspm/sspm.c
index 3917638..6e76124 100644
--- a/plat/mediatek/mt8183/drivers/sspm/sspm.c
+++ b/plat/mediatek/mt8183/drivers/sspm/sspm.c
@@ -149,7 +149,7 @@
 
 	while (sspm_ipi_recv_non_blocking(IPI_ID_PLATFORM,
 					  &ipi_data,
-					  sizeof(ipi_data))
+					  sizeof(ipi_data) / sizeof(uint32_t))
 					  && count) {
 		mdelay(100);
 		count--;
diff --git a/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c b/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c
new file mode 100644
index 0000000..69c395e
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mtk_sip_svc.h>
+#include <plat_dfd.h>
+
+static bool dfd_enabled;
+static uint64_t dfd_base_addr;
+static uint64_t dfd_chain_length;
+static uint64_t dfd_cache_dump;
+
+static void dfd_setup(uint64_t base_addr, uint64_t chain_length,
+		      uint64_t cache_dump)
+{
+	/* bit[0]: rg_rw_dfd_internal_dump_en -> 1 */
+	/* bit[2]: rg_rw_dfd_clock_stop_en -> 1 */
+	sync_writel(DFD_INTERNAL_CTL, 0x5);
+
+	/* bit[13]: xreset_b_update_disable */
+	mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 13);
+
+	/*
+	 * bit[10:3]: DFD trigger selection mask
+	 * bit[3]: rg_rw_dfd_trigger_sel[0] = 1(enable wdt trigger)
+	 * bit[4]: rg_rw_dfd_trigger_sel[1] = 1(enable HW trigger)
+	 * bit[5]: rg_rw_dfd_trigger_sel[2] = 1(enable SW trigger)
+	 * bit[6]: rg_rw_dfd_trigger_sel[3] = 1(enable SW non-security trigger)
+	 * bit[7]: rg_rw_dfd_trigger_sel[4] = 1(enable timer trigger)
+	 */
+	mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 3);
+
+	/* bit[20:19]: rg_dfd_armpll_div_mux_sel switch to PLL2 for DFD */
+	mmio_setbits_32(DFD_INTERNAL_CTL, 0x3 << 19);
+
+	/*
+	 * bit[0]: rg_rw_dfd_auto_power_on = 1
+	 * bit[2:1]: rg_rw_dfd_auto_power_on_dely = 1(10us)
+	 * bit[4:2]: rg_rw_dfd_power_on_wait_time = 1(20us)
+	 */
+	mmio_write_32(DFD_INTERNAL_PWR_ON, 0xB);
+
+	/* longest scan chain length */
+	mmio_write_32(DFD_CHAIN_LENGTH0, chain_length);
+
+	/* bit[1:0]: rg_rw_dfd_shift_clock_ratio */
+	mmio_write_32(DFD_INTERNAL_SHIFT_CLK_RATIO, 0x0);
+
+	/* rg_dfd_test_so_over_64 */
+	mmio_write_32(DFD_INTERNAL_TEST_SO_OVER_64, 0x1);
+
+	/* DFD3.0 */
+	mmio_write_32(DFD_TEST_SI_0, DFD_TEST_SI_0_CACHE_DIS_VAL);
+	mmio_write_32(DFD_TEST_SI_1, DFD_TEST_SI_1_VAL);
+	mmio_write_32(DFD_TEST_SI_2, DFD_TEST_SI_2_VAL);
+	mmio_write_32(DFD_TEST_SI_3, DFD_TEST_SI_3_VAL);
+
+	/* for iLDO feature */
+	sync_writel(DFD_POWER_CTL, 0xF9);
+
+	/* set base address */
+	mmio_write_32(DFD_O_SET_BASEADDR_REG, base_addr >> 24);
+
+	/*
+	 * disable sleep protect of DFD
+	 * 10001220[8]: protect_en_reg[8]
+	 * 10001a3c[2]: infra_mcu_pwr_ctl_mask[2]
+	 */
+	mmio_clrbits_32(DFD_O_PROTECT_EN_REG, 1 << 8);
+	mmio_clrbits_32(DFD_O_INTRF_MCU_PWR_CTL_MASK, 1 << 2);
+
+	/* clean DFD trigger status */
+	sync_writel(DFD_CLEAN_STATUS, 0x1);
+	sync_writel(DFD_CLEAN_STATUS, 0x0);
+
+	/* DFD-3.0 */
+	sync_writel(DFD_V30_CTL, 0x1);
+
+	/* setup global variables for suspend and resume */
+	dfd_enabled = true;
+	dfd_base_addr = base_addr;
+	dfd_chain_length = chain_length;
+	dfd_cache_dump = cache_dump;
+
+	if ((cache_dump & DFD_CACHE_DUMP_ENABLE) != 0UL) {
+		/* DFD3.5 */
+		mmio_write_32(DFD_TEST_SI_0, DFD_TEST_SI_0_CACHE_EN_VAL);
+		sync_writel(DFD_V35_ENALBE, 0x1);
+		sync_writel(DFD_V35_TAP_NUMBER, 0xB);
+		sync_writel(DFD_V35_TAP_EN, DFD_V35_TAP_EN_VAL);
+		sync_writel(DFD_V35_SEQ0_0, DFD_V35_SEQ0_0_VAL);
+
+		if (cache_dump & DFD_PARITY_ERR_TRIGGER) {
+			sync_writel(DFD_HW_TRIGGER_MASK, 0xC);
+			mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 4);
+		}
+	}
+	dsbsy();
+}
+
+void dfd_resume(void)
+{
+	if (dfd_enabled == true) {
+		dfd_setup(dfd_base_addr, dfd_chain_length, dfd_cache_dump);
+	}
+}
+
+uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1,
+			    uint64_t arg2, uint64_t arg3)
+{
+	uint64_t ret = 0L;
+
+	switch (arg0) {
+	case PLAT_MTK_DFD_SETUP_MAGIC:
+		dfd_setup(arg1, arg2, arg3);
+		break;
+	case PLAT_MTK_DFD_READ_MAGIC:
+		/* only allow to access DFD register base + 0x200 */
+		if (arg1 <= 0x200) {
+			ret = mmio_read_32(MISC1_CFG_BASE + arg1);
+		}
+		break;
+	case PLAT_MTK_DFD_WRITE_MAGIC:
+		/* only allow to access DFD register base + 0x200 */
+		if (arg1 <= 0x200) {
+			sync_writel(MISC1_CFG_BASE + arg1, arg2);
+		}
+		break;
+	default:
+		ret = MTK_SIP_E_INVALID_PARAM;
+		break;
+	}
+
+	return ret;
+}
diff --git a/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h b/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h
new file mode 100644
index 0000000..7f0f4b5
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DFD_H
+#define PLAT_DFD_H
+
+#include <arch_helpers.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#define sync_writel(addr, val)	do { mmio_write_32((addr), (val)); \
+				dsbsy(); \
+				} while (0)
+
+#define PLAT_MTK_DFD_SETUP_MAGIC		(0x99716150)
+#define PLAT_MTK_DFD_READ_MAGIC			(0x99716151)
+#define PLAT_MTK_DFD_WRITE_MAGIC		(0x99716152)
+
+#define MCU_BIU_BASE				(MCUCFG_BASE)
+#define MISC1_CFG_BASE				(MCU_BIU_BASE + 0xE040)
+#define DFD_INTERNAL_CTL			(MISC1_CFG_BASE + 0x00)
+#define DFD_INTERNAL_PWR_ON			(MISC1_CFG_BASE + 0x08)
+#define DFD_CHAIN_LENGTH0			(MISC1_CFG_BASE + 0x0C)
+#define DFD_INTERNAL_SHIFT_CLK_RATIO		(MISC1_CFG_BASE + 0x10)
+#define DFD_CHAIN_LENGTH1			(MISC1_CFG_BASE + 0x1C)
+#define DFD_CHAIN_LENGTH2			(MISC1_CFG_BASE + 0x20)
+#define DFD_CHAIN_LENGTH3			(MISC1_CFG_BASE + 0x24)
+#define DFD_INTERNAL_TEST_SO_0			(MISC1_CFG_BASE + 0x28)
+#define DFD_INTERNAL_NUM_OF_TEST_SO_GROUP	(MISC1_CFG_BASE + 0x30)
+#define DFD_INTERNAL_TEST_SO_OVER_64		(MISC1_CFG_BASE + 0x34)
+#define DFD_V30_CTL				(MISC1_CFG_BASE + 0x48)
+#define DFD_V30_BASE_ADDR			(MISC1_CFG_BASE + 0x4C)
+#define DFD_POWER_CTL				(MISC1_CFG_BASE + 0x50)
+#define DFD_TEST_SI_0				(MISC1_CFG_BASE + 0x58)
+#define DFD_TEST_SI_1				(MISC1_CFG_BASE + 0x5C)
+#define DFD_CLEAN_STATUS			(MISC1_CFG_BASE + 0x60)
+#define DFD_TEST_SI_2				(MISC1_CFG_BASE + 0x1D8)
+#define DFD_TEST_SI_3				(MISC1_CFG_BASE + 0x1DC)
+#define DFD_HW_TRIGGER_MASK			(MISC1_CFG_BASE + 0xBC)
+
+#define DFD_V35_ENALBE				(MCU_BIU_BASE + 0xE0A8)
+#define DFD_V35_TAP_NUMBER			(MCU_BIU_BASE + 0xE0AC)
+#define DFD_V35_TAP_EN				(MCU_BIU_BASE + 0xE0B0)
+#define DFD_V35_CTL				(MCU_BIU_BASE + 0xE0B4)
+#define DFD_V35_SEQ0_0				(MCU_BIU_BASE + 0xE0C0)
+#define DFD_V35_SEQ0_1				(MCU_BIU_BASE + 0xE0C4)
+
+#define DFD_O_PROTECT_EN_REG			(0x10001220)
+#define DFD_O_INTRF_MCU_PWR_CTL_MASK		(0x10001A3C)
+#define DFD_O_SET_BASEADDR_REG			(0x10043034)
+
+#define DFD_CACHE_DUMP_ENABLE			1U
+#define DFD_PARITY_ERR_TRIGGER			2U
+
+#define DFD_TEST_SI_0_CACHE_DIS_VAL		(0x1E000202)
+#define DFD_TEST_SI_0_CACHE_EN_VAL		(0x1E000002)
+#define DFD_TEST_SI_1_VAL			(0x20408100)
+#define DFD_TEST_SI_2_VAL			(0x10101000)
+#define DFD_TEST_SI_3_VAL			(0x00000010)
+#define	DFD_V35_TAP_EN_VAL			(0x43FF)
+#define	DFD_V35_SEQ0_0_VAL			(0x63668820)
+
+void dfd_resume(void);
+uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1,
+			    uint64_t arg2, uint64_t arg3);
+
+#endif /* PLAT_DFD_H */
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.c b/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.c
index 307862d..2d67fdf 100644
--- a/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.c
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.c
@@ -143,6 +143,11 @@
 		blocked |= SPM_COND_CHECK_BLOCKED_PLL;
 	}
 
+	if (is_system_suspend && (blocked != 0U)) {
+		INFO("suspend: %s total blocked = 0x%08x\n",
+		     dest->name, blocked);
+	}
+
 	return blocked;
 }
 
diff --git a/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.h b/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.h
index ba13fe3..91ebdd9 100644
--- a/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.h
+++ b/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.h
@@ -23,20 +23,11 @@
 	PLAT_SPM_COND_MAX,
 };
 
-enum PLAT_SPM_COND_PLL {
-	PLAT_SPM_COND_PLL_UNIVPLL = 0,
-	PLAT_SPM_COND_PLL_MFGPLL,
-	PLAT_SPM_COND_PLL_MSDCPLL,
-	PLAT_SPM_COND_PLL_TVDPLL,
-	PLAT_SPM_COND_PLL_MMPLL,
-	PLAT_SPM_COND_PLL_MAX,
-};
-
-#define PLL_BIT_MFGPLL	(PLAT_SPM_COND_PLL_MFGPLL)
-#define PLL_BIT_MMPLL	(PLAT_SPM_COND_PLL_MMPLL)
-#define PLL_BIT_UNIVPLL	(PLAT_SPM_COND_PLL_UNIVPLL)
-#define PLL_BIT_MSDCPLL	(PLAT_SPM_COND_PLL_MSDCPLL)
-#define PLL_BIT_TVDPLL	(PLAT_SPM_COND_PLL_TVDPLL)
+#define PLL_BIT_UNIVPLL	BIT(0)
+#define PLL_BIT_MFGPLL	BIT(1)
+#define PLL_BIT_MSDCPLL	BIT(2)
+#define PLL_BIT_TVDPLL	BIT(3)
+#define PLL_BIT_MMPLL	BIT(4)
 
 /* Definition about SPM_COND_CHECK_BLOCKED
  * bit [00 ~ 15]: cg blocking index
diff --git a/plat/mediatek/mt8192/include/plat_sip_calls.h b/plat/mediatek/mt8192/include/plat_sip_calls.h
index 0e42322..f68a4ea 100644
--- a/plat/mediatek/mt8192/include/plat_sip_calls.h
+++ b/plat/mediatek/mt8192/include/plat_sip_calls.h
@@ -10,6 +10,10 @@
 /*******************************************************************************
  * Plat SiP function constants
  ******************************************************************************/
-#define MTK_PLAT_SIP_NUM_CALLS    0
+#define MTK_PLAT_SIP_NUM_CALLS    2
+
+/* DFD */
+#define MTK_SIP_KERNEL_DFD_AARCH32		0x82000205
+#define MTK_SIP_KERNEL_DFD_AARCH64		0xC2000205
 
 #endif /* PLAT_SIP_CALLS_H */
diff --git a/plat/mediatek/mt8192/plat_pm.c b/plat/mediatek/mt8192/plat_pm.c
index 6dfb6c9..018e418 100644
--- a/plat/mediatek/mt8192/plat_pm.c
+++ b/plat/mediatek/mt8192/plat_pm.c
@@ -17,6 +17,7 @@
 #include <mtk_ptp3_common.h>
 #include <mtspmc.h>
 #include <plat/common/platform.h>
+#include <plat_dfd.h>
 #include <plat_mtk_lpm.h>
 #include <plat_params.h>
 #include <plat_pm.h>
@@ -168,6 +169,8 @@
 	mt_gic_distif_restore();
 	gic_sgi_restore_all();
 
+	dfd_resume();
+
 	plat_mt_pm_invoke_no_check(pwr_mcusys_on_finished, cpu, state);
 }
 
diff --git a/plat/mediatek/mt8192/plat_sip_calls.c b/plat/mediatek/mt8192/plat_sip_calls.c
index f567f02..353faf8 100644
--- a/plat/mediatek/mt8192/plat_sip_calls.c
+++ b/plat/mediatek/mt8192/plat_sip_calls.c
@@ -9,6 +9,7 @@
 #include <mtk_apusys.h>
 #include <mtk_sip_svc.h>
 #include <mt_spm_vcorefs.h>
+#include <plat_dfd.h>
 #include "plat_sip_calls.h"
 
 uintptr_t mediatek_plat_sip_handler(uint32_t smc_fid,
@@ -34,6 +35,11 @@
 		ret = apusys_kernel_ctrl(x1, x2, x3, x4, &rnd_val0);
 		SMC_RET2(handle, ret, rnd_val0);
 		break;
+	case MTK_SIP_KERNEL_DFD_AARCH32:
+	case MTK_SIP_KERNEL_DFD_AARCH64:
+		ret = dfd_smc_dispatcher(x1, x2, x3, x4);
+		SMC_RET1(handle, ret);
+		break;
 	default:
 		ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
 		break;
diff --git a/plat/mediatek/mt8192/platform.mk b/plat/mediatek/mt8192/platform.mk
index 7761a55..cbdaadd 100644
--- a/plat/mediatek/mt8192/platform.mk
+++ b/plat/mediatek/mt8192/platform.mk
@@ -19,6 +19,7 @@
                  -I${MTK_PLAT_SOC}/drivers/apusys/                \
                  -I${MTK_PLAT_SOC}/drivers/dcm                    \
                  -I${MTK_PLAT_SOC}/drivers/devapc                 \
+                 -I${MTK_PLAT_SOC}/drivers/dfd                    \
                  -I${MTK_PLAT_SOC}/drivers/emi_mpu/               \
                  -I${MTK_PLAT_SOC}/drivers/gpio/                  \
                  -I${MTK_PLAT_SOC}/drivers/mcdi/                  \
@@ -68,6 +69,7 @@
                    ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c                 \
                    ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c           \
                    ${MTK_PLAT_SOC}/drivers/devapc/devapc.c               \
+                   ${MTK_PLAT_SOC}/drivers/dfd/plat_dfd.c                \
                    ${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c             \
                    ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c                 \
                    ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm.c              \
diff --git a/plat/mediatek/mt8195/bl31_plat_setup.c b/plat/mediatek/mt8195/bl31_plat_setup.c
index 39c1918..dff6670 100644
--- a/plat/mediatek/mt8195/bl31_plat_setup.c
+++ b/plat/mediatek/mt8195/bl31_plat_setup.c
@@ -16,9 +16,11 @@
 #include <lib/coreboot.h>
 
 /* Platform Includes */
+#include <emi_mpu.h>
 #include <mt_gic_v3.h>
 #include <mt_spm.h>
 #include <mt_timer.h>
+#include <mtk_dcm.h>
 #include <mtgpio.h>
 #include <plat_params.h>
 #include <plat_private.h>
@@ -84,6 +86,14 @@
  ******************************************************************************/
 void bl31_platform_setup(void)
 {
+	/* Set dcm on */
+	if (!dcm_set_default()) {
+		ERROR("Failed to set default dcm on!!\n");
+	}
+
+	/* Initialize EMI MPU */
+	emi_mpu_init();
+
 	/* Initialize the GIC driver, CPU and distributor interfaces */
 	mt_gic_driver_init();
 	mt_gic_init();
diff --git a/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.c b/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.c
new file mode 100644
index 0000000..aed0833
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <mtk_dcm.h>
+#include <mtk_dcm_utils.h>
+
+static void dcm_armcore(bool mode)
+{
+	dcm_mp_cpusys_top_bus_pll_div_dcm(mode);
+	dcm_mp_cpusys_top_cpu_pll_div_0_dcm(mode);
+	dcm_mp_cpusys_top_cpu_pll_div_1_dcm(mode);
+}
+
+static void dcm_mcusys(bool on)
+{
+	dcm_mp_cpusys_top_adb_dcm(on);
+	dcm_mp_cpusys_top_apb_dcm(on);
+	dcm_mp_cpusys_top_cpubiu_dcm(on);
+	dcm_mp_cpusys_top_misc_dcm(on);
+	dcm_mp_cpusys_top_mp0_qdcm(on);
+	dcm_cpccfg_reg_emi_wfifo(on);
+	dcm_mp_cpusys_top_last_cor_idle_dcm(on);
+}
+
+static void dcm_stall(bool on)
+{
+	dcm_mp_cpusys_top_core_stall_dcm(on);
+	dcm_mp_cpusys_top_fcm_stall_dcm(on);
+}
+
+static bool check_dcm_state(void)
+{
+	bool ret = true;
+
+	ret &= dcm_mp_cpusys_top_bus_pll_div_dcm_is_on();
+	ret &= dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on();
+	ret &= dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on();
+
+	ret &= dcm_mp_cpusys_top_adb_dcm_is_on();
+	ret &= dcm_mp_cpusys_top_apb_dcm_is_on();
+	ret &= dcm_mp_cpusys_top_cpubiu_dcm_is_on();
+	ret &= dcm_mp_cpusys_top_misc_dcm_is_on();
+	ret &= dcm_mp_cpusys_top_mp0_qdcm_is_on();
+	ret &= dcm_cpccfg_reg_emi_wfifo_is_on();
+	ret &= dcm_mp_cpusys_top_last_cor_idle_dcm_is_on();
+
+	ret &= dcm_mp_cpusys_top_core_stall_dcm_is_on();
+	ret &= dcm_mp_cpusys_top_fcm_stall_dcm_is_on();
+
+	return ret;
+}
+
+bool dcm_set_default(void)
+{
+	dcm_armcore(true);
+	dcm_mcusys(true);
+	dcm_stall(true);
+
+	return check_dcm_state();
+}
diff --git a/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.h b/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.h
new file mode 100644
index 0000000..cb65b85
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_DCM_H
+#define MTK_DCM_H
+
+#include <stdbool.h>
+
+bool dcm_set_default(void);
+
+#endif /* #ifndef MTK_DCM_H */
diff --git a/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.c b/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.c
new file mode 100644
index 0000000..a1a3720
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.c
@@ -0,0 +1,483 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <mtk_dcm_utils.h>
+
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_MASK (BIT(17))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_MASK (BIT(15) | \
+			BIT(16) | \
+			BIT(17) | \
+			BIT(18) | \
+			BIT(21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG2_MASK (BIT(15) | \
+			BIT(16) | \
+			BIT(17) | \
+			BIT(18))
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_ON (BIT(17))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_ON (BIT(15) | \
+			BIT(16) | \
+			BIT(17) | \
+			BIT(18) | \
+			BIT(21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG2_ON (BIT(15) | \
+			BIT(16) | \
+			BIT(17) | \
+			BIT(18))
+#define MP_CPUSYS_TOP_ADB_DCM_REG0_OFF ((0x0 << 17))
+#define MP_CPUSYS_TOP_ADB_DCM_REG1_OFF ((0x0 << 15) | \
+			(0x0 << 16) | \
+			(0x0 << 17) | \
+			(0x0 << 18) | \
+			(0x0 << 21))
+#define MP_CPUSYS_TOP_ADB_DCM_REG2_OFF ((0x0 << 15) | \
+			(0x0 << 16) | \
+			(0x0 << 17) | \
+			(0x0 << 18))
+
+bool dcm_mp_cpusys_top_adb_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG0) &
+		MP_CPUSYS_TOP_ADB_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG0_ON);
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4) &
+		MP_CPUSYS_TOP_ADB_DCM_REG1_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG1_ON);
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0) &
+		MP_CPUSYS_TOP_ADB_DCM_REG2_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_ADB_DCM_REG2_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_adb_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_adb_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG0,
+			MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_ADB_DCM_REG0_ON);
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4,
+			MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
+			MP_CPUSYS_TOP_ADB_DCM_REG1_ON);
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+			MP_CPUSYS_TOP_ADB_DCM_REG2_MASK,
+			MP_CPUSYS_TOP_ADB_DCM_REG2_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_adb_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG0,
+			MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_ADB_DCM_REG0_OFF);
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4,
+			MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
+			MP_CPUSYS_TOP_ADB_DCM_REG1_OFF);
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+			MP_CPUSYS_TOP_ADB_DCM_REG2_MASK,
+			MP_CPUSYS_TOP_ADB_DCM_REG2_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_APB_DCM_REG0_MASK (BIT(5))
+#define MP_CPUSYS_TOP_APB_DCM_REG1_MASK (BIT(8))
+#define MP_CPUSYS_TOP_APB_DCM_REG2_MASK (BIT(16))
+#define MP_CPUSYS_TOP_APB_DCM_REG0_ON (BIT(5))
+#define MP_CPUSYS_TOP_APB_DCM_REG1_ON (BIT(8))
+#define MP_CPUSYS_TOP_APB_DCM_REG2_ON (BIT(16))
+#define MP_CPUSYS_TOP_APB_DCM_REG0_OFF ((0x0 << 5))
+#define MP_CPUSYS_TOP_APB_DCM_REG1_OFF ((0x0 << 8))
+#define MP_CPUSYS_TOP_APB_DCM_REG2_OFF ((0x0 << 16))
+
+bool dcm_mp_cpusys_top_apb_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0) &
+		MP_CPUSYS_TOP_APB_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_APB_DCM_REG0_ON);
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0) &
+		MP_CPUSYS_TOP_APB_DCM_REG1_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_APB_DCM_REG1_ON);
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG0) &
+		MP_CPUSYS_TOP_APB_DCM_REG2_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_APB_DCM_REG2_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_apb_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_apb_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+			MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_APB_DCM_REG0_ON);
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+			MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
+			MP_CPUSYS_TOP_APB_DCM_REG1_ON);
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
+			MP_CPUSYS_TOP_APB_DCM_REG2_MASK,
+			MP_CPUSYS_TOP_APB_DCM_REG2_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_apb_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+			MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_APB_DCM_REG0_OFF);
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
+			MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
+			MP_CPUSYS_TOP_APB_DCM_REG1_OFF);
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
+			MP_CPUSYS_TOP_APB_DCM_REG2_MASK,
+			MP_CPUSYS_TOP_APB_DCM_REG2_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK (BIT(11) | \
+			BIT(24) | \
+			BIT(25))
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON (BIT(11) | \
+			BIT(24) | \
+			BIT(25))
+#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF ((0x0 << 11) | \
+			(0x0 << 24) | \
+			(0x0 << 25))
+
+bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG) &
+		MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_bus_pll_div_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
+			MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_bus_pll_div_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
+			MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK (BIT(0))
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON (BIT(0))
+#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF ((0x0 << 0))
+
+bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG7) &
+		MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_core_stall_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_core_stall_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
+			MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_core_stall_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
+			MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK ((0xffff << 0))
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON ((0xffff << 0))
+#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF ((0x0 << 0))
+
+bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_MCSIC_DCM0) &
+		MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_cpubiu_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_cpubiu_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSIC_DCM0,
+			MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpubiu_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSIC_DCM0,
+			MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK (BIT(24) | \
+			BIT(25))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON (BIT(24) | \
+			BIT(25))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF ((0x0 << 24) | \
+			(0x0 << 25))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0) &
+		MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK (BIT(24) | \
+			BIT(25))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON (BIT(24) | \
+			BIT(25))
+#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF ((0x0 << 24) | \
+			(0x0 << 25))
+
+bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1) &
+		MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK (BIT(4))
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON (BIT(4))
+#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF ((0x0 << 4))
+
+bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG7) &
+		MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_fcm_stall_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_fcm_stall_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
+			MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_fcm_stall_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
+			MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK ((0x1U << 31))
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON ((0x1U << 31))
+#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF ((0x0U << 31))
+
+bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG) &
+		MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_last_cor_idle_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
+			MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_last_cor_idle_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
+			MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_MASK (BIT(1) | \
+			BIT(4))
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_ON (BIT(1) | \
+			BIT(4))
+#define MP_CPUSYS_TOP_MISC_DCM_REG0_OFF ((0x0 << 1) | \
+			(0x0 << 4))
+
+bool dcm_mp_cpusys_top_misc_dcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0) &
+		MP_CPUSYS_TOP_MISC_DCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_MISC_DCM_REG0_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_misc_dcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_misc_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+			MP_CPUSYS_TOP_MISC_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_MISC_DCM_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_misc_dcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+			MP_CPUSYS_TOP_MISC_DCM_REG0_MASK,
+			MP_CPUSYS_TOP_MISC_DCM_REG0_OFF);
+	}
+}
+
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK (BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK (BIT(0) | \
+			BIT(1) | \
+			BIT(2) | \
+			BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_ON (BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG1_ON (BIT(0) | \
+			BIT(1) | \
+			BIT(2) | \
+			BIT(3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF ((0x0 << 3))
+#define MP_CPUSYS_TOP_MP0_QDCM_REG1_OFF ((0x0 << 0) | \
+			(0x0 << 1) | \
+			(0x0 << 2) | \
+			(0x0 << 3))
+
+bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0) &
+		MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_MP0_QDCM_REG0_ON);
+	ret &= ((mmio_read_32(MP_CPUSYS_TOP_MP0_DCM_CFG0) &
+		MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK) ==
+		(unsigned int) MP_CPUSYS_TOP_MP0_QDCM_REG1_ON);
+
+	return ret;
+}
+
+void dcm_mp_cpusys_top_mp0_qdcm(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'mp_cpusys_top_mp0_qdcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+			MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
+			MP_CPUSYS_TOP_MP0_QDCM_REG0_ON);
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
+			MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK,
+			MP_CPUSYS_TOP_MP0_QDCM_REG1_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'mp_cpusys_top_mp0_qdcm'" */
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
+			MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
+			MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF);
+		mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
+			MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK,
+			MP_CPUSYS_TOP_MP0_QDCM_REG1_OFF);
+	}
+}
+
+#define CPCCFG_REG_EMI_WFIFO_REG0_MASK (BIT(0) | \
+			BIT(1) | \
+			BIT(2) | \
+			BIT(3))
+#define CPCCFG_REG_EMI_WFIFO_REG0_ON (BIT(0) | \
+			BIT(1) | \
+			BIT(2) | \
+			BIT(3))
+#define CPCCFG_REG_EMI_WFIFO_REG0_OFF ((0x0 << 0) | \
+			(0x0 << 1) | \
+			(0x0 << 2) | \
+			(0x0 << 3))
+
+bool dcm_cpccfg_reg_emi_wfifo_is_on(void)
+{
+	bool ret = true;
+
+	ret &= ((mmio_read_32(CPCCFG_REG_EMI_WFIFO) &
+		CPCCFG_REG_EMI_WFIFO_REG0_MASK) ==
+		(unsigned int) CPCCFG_REG_EMI_WFIFO_REG0_ON);
+
+	return ret;
+}
+
+void dcm_cpccfg_reg_emi_wfifo(bool on)
+{
+	if (on) {
+		/* TINFO = "Turn ON DCM 'cpccfg_reg_emi_wfifo'" */
+		mmio_clrsetbits_32(CPCCFG_REG_EMI_WFIFO,
+			CPCCFG_REG_EMI_WFIFO_REG0_MASK,
+			CPCCFG_REG_EMI_WFIFO_REG0_ON);
+	} else {
+		/* TINFO = "Turn OFF DCM 'cpccfg_reg_emi_wfifo'" */
+		mmio_clrsetbits_32(CPCCFG_REG_EMI_WFIFO,
+			CPCCFG_REG_EMI_WFIFO_REG0_MASK,
+			CPCCFG_REG_EMI_WFIFO_REG0_OFF);
+	}
+}
diff --git a/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.h b/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.h
new file mode 100644
index 0000000..e5743af
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MTK_DCM_UTILS_H
+#define MTK_DCM_UTILS_H
+
+#include <stdbool.h>
+
+#include <mtk_dcm.h>
+#include <platform_def.h>
+
+/* Base */
+#define MP_CPUSYS_TOP_BASE	(MCUCFG_BASE + 0x8000)
+#define CPCCFG_REG_BASE		(MCUCFG_BASE + 0xA800)
+
+/* Register Definition */
+#define MP_CPUSYS_TOP_CPU_PLLDIV_CFG0 (MP_CPUSYS_TOP_BASE + 0x22a0)
+#define MP_CPUSYS_TOP_CPU_PLLDIV_CFG1 (MP_CPUSYS_TOP_BASE + 0x22a4)
+#define MP_CPUSYS_TOP_BUS_PLLDIV_CFG (MP_CPUSYS_TOP_BASE + 0x22e0)
+#define MP_CPUSYS_TOP_MCSIC_DCM0 (MP_CPUSYS_TOP_BASE + 0x2440)
+#define MP_CPUSYS_TOP_MP_ADB_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x2500)
+#define MP_CPUSYS_TOP_MP_ADB_DCM_CFG4 (MP_CPUSYS_TOP_BASE + 0x2510)
+#define MP_CPUSYS_TOP_MP_MISC_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x2518)
+#define MP_CPUSYS_TOP_MCUSYS_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x25c0)
+#define CPCCFG_REG_EMI_WFIFO (CPCCFG_REG_BASE + 0x100)
+#define MP_CPUSYS_TOP_MP0_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x4880)
+#define MP_CPUSYS_TOP_MP0_DCM_CFG7 (MP_CPUSYS_TOP_BASE + 0x489c)
+
+/* MP_CPUSYS_TOP */
+bool dcm_mp_cpusys_top_adb_dcm_is_on(void);
+void dcm_mp_cpusys_top_adb_dcm(bool on);
+bool dcm_mp_cpusys_top_apb_dcm_is_on(void);
+void dcm_mp_cpusys_top_apb_dcm(bool on);
+bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void);
+void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on);
+bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void);
+void dcm_mp_cpusys_top_core_stall_dcm(bool on);
+bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpubiu_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on);
+bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void);
+void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on);
+bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void);
+void dcm_mp_cpusys_top_fcm_stall_dcm(bool on);
+bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void);
+void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on);
+bool dcm_mp_cpusys_top_misc_dcm_is_on(void);
+void dcm_mp_cpusys_top_misc_dcm(bool on);
+bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void);
+void dcm_mp_cpusys_top_mp0_qdcm(bool on);
+/* CPCCFG_REG */
+bool dcm_cpccfg_reg_emi_wfifo_is_on(void);
+void dcm_cpccfg_reg_emi_wfifo(bool on);
+
+#endif
diff --git a/plat/mediatek/mt8195/drivers/dfd/plat_dfd.c b/plat/mediatek/mt8195/drivers/dfd/plat_dfd.c
new file mode 100644
index 0000000..c083318
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/dfd/plat_dfd.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mtk_sip_svc.h>
+#include <plat_dfd.h>
+
+static bool dfd_enabled;
+static uint64_t dfd_base_addr;
+static uint64_t dfd_chain_length;
+static uint64_t dfd_cache_dump;
+
+static void dfd_setup(uint64_t base_addr, uint64_t chain_length,
+		      uint64_t cache_dump)
+{
+	mmio_write_32(MTK_WDT_LATCH_CTL2, MTK_WDT_LATCH_CTL2_VAL);
+	mmio_write_32(MTK_WDT_INTERVAL, MTK_WDT_INTERVAL_VAL);
+	mmio_write_32(MTK_DRM_LATCH_CTL2, MTK_DRM_LATCH_CTL2_VAL);
+	mmio_write_32(MTK_DRM_LATCH_CTL1, MTK_DRM_LATCH_CTL1_VAL);
+
+	/* Bit[2] = 0 (default=1), disable dfd apb bus protect_en */
+	mmio_clrbits_32(DFD_O_INTRF_MCU_PWR_CTL_MASK, 0x1 << 2);
+
+	/* Bit[0] : enable?mcusys_vproc?external_off?dfd?trigger -> 1 */
+	mmio_setbits_32(DFD_V50_GROUP_0_63_DIFF, 0x1);
+
+	/* bit[0]: rg_rw_dfd_internal_dump_en -> 1 */
+	/* bit[2]: rg_rw_dfd_clock_stop_en -> 1 */
+	sync_writel(DFD_INTERNAL_CTL, 0x5);
+
+	/* bit[13]: xreset_b_update_disable */
+	mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 13);
+
+	/*
+	 * bit[10:3]: DFD trigger selection mask
+	 * bit[3]: rg_rw_dfd_trigger_sel[0] = 1(enable wdt trigger)
+	 * bit[4]: rg_rw_dfd_trigger_sel[1] = 1(enable HW trigger)
+	 * bit[5]: rg_rw_dfd_trigger_sel[2] = 1(enable SW trigger)
+	 * bit[6]: rg_rw_dfd_trigger_sel[3] = 1(enable SW non-security trigger)
+	 * bit[7]: rg_rw_dfd_trigger_sel[4] = 1(enable timer trigger)
+	 */
+	mmio_setbits_32(DFD_INTERNAL_CTL, 0x1F << 3);
+
+	/*
+	 * bit[9]  : rg_rw_dfd_trigger_sel[6] = 1(cpu_eb_sw_dfd_trigger)
+	 * bit[10] : rg_rw_dfd_trigger_sel[7] = 1(cpu_eb_wdt_dfd_trigger)
+	 */
+	mmio_setbits_32(DFD_INTERNAL_CTL, 0x3 << 9);
+
+	/* bit[20:19]: rg_dfd_armpll_div_mux_sel switch to PLL2 for DFD */
+	mmio_setbits_32(DFD_INTERNAL_CTL, 0x3 << 19);
+
+	/*
+	 * bit[0]: rg_rw_dfd_auto_power_on = 1
+	 * bit[2:1]: rg_rw_dfd_auto_power_on_dely = 1(10us)
+	 * bit[4:2]: rg_rw_dfd_power_on_wait_time = 1(20us)
+	 */
+	mmio_write_32(DFD_INTERNAL_PWR_ON, 0xB);
+
+	/* longest scan chain length */
+	mmio_write_32(DFD_CHAIN_LENGTH0, chain_length);
+
+	/* bit[1:0]: rg_rw_dfd_shift_clock_ratio */
+	mmio_write_32(DFD_INTERNAL_SHIFT_CLK_RATIO, 0x0);
+
+	/* rg_dfd_test_so_over_64 */
+	mmio_write_32(DFD_INTERNAL_TEST_SO_OVER_64, 0x1);
+
+	/* DFD3.0 */
+	mmio_write_32(DFD_TEST_SI_0, 0x0);
+	mmio_write_32(DFD_TEST_SI_1, 0x0);
+	mmio_write_32(DFD_TEST_SI_2, 0x0);
+	mmio_write_32(DFD_TEST_SI_3, 0x0);
+
+	/* for iLDO feature */
+	sync_writel(DFD_POWER_CTL, 0xF9);
+
+	/* read offset */
+	sync_writel(DFD_READ_ADDR, DFD_READ_ADDR_VAL);
+
+	/* for DFD-3.0 setup */
+	sync_writel(DFD_V30_CTL, 0xD);
+
+	/* set base address */
+	mmio_write_32(DFD_O_SET_BASEADDR_REG, base_addr >> 24);
+	mmio_write_32(DFD_O_REG_0, 0);
+
+	/* setup global variables for suspend and resume */
+	dfd_enabled = true;
+	dfd_base_addr = base_addr;
+	dfd_chain_length = chain_length;
+	dfd_cache_dump = cache_dump;
+
+	if ((cache_dump & DFD_CACHE_DUMP_ENABLE) != 0UL) {
+		mmio_write_32(MTK_DRM_LATCH_CTL2, MTK_DRM_LATCH_CTL2_CACHE_VAL);
+		sync_writel(DFD_V35_ENABLE, 0x1);
+		sync_writel(DFD_V35_TAP_NUMBER, 0xB);
+		sync_writel(DFD_V35_TAP_EN, DFD_V35_TAP_EN_VAL);
+		sync_writel(DFD_V35_SEQ0_0, DFD_V35_SEQ0_0_VAL);
+
+		/* Cache dump only mode */
+		sync_writel(DFD_V35_CTL, 0x1);
+		mmio_write_32(DFD_INTERNAL_NUM_OF_TEST_SO_GROUP, 0xF);
+		mmio_write_32(DFD_CHAIN_LENGTH0, DFD_CHAIN_LENGTH_VAL);
+		mmio_write_32(DFD_CHAIN_LENGTH1, DFD_CHAIN_LENGTH_VAL);
+		mmio_write_32(DFD_CHAIN_LENGTH2, DFD_CHAIN_LENGTH_VAL);
+		mmio_write_32(DFD_CHAIN_LENGTH3, DFD_CHAIN_LENGTH_VAL);
+
+		if ((cache_dump & DFD_PARITY_ERR_TRIGGER) != 0UL) {
+			sync_writel(DFD_HW_TRIGGER_MASK, 0xC);
+			mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 4);
+		}
+	}
+	dsbsy();
+}
+
+void dfd_resume(void)
+{
+	if (dfd_enabled == true) {
+		dfd_setup(dfd_base_addr, dfd_chain_length, dfd_cache_dump);
+	}
+}
+
+uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1,
+			    uint64_t arg2, uint64_t arg3)
+{
+	uint64_t ret = 0L;
+
+	switch (arg0) {
+	case PLAT_MTK_DFD_SETUP_MAGIC:
+		INFO("[%s] DFD setup call from kernel\n", __func__);
+		dfd_setup(arg1, arg2, arg3);
+		break;
+	case PLAT_MTK_DFD_READ_MAGIC:
+		/* only allow to access DFD register base + 0x200 */
+		if (arg1 <= 0x200) {
+			ret = mmio_read_32(MISC1_CFG_BASE + arg1);
+		}
+		break;
+	case PLAT_MTK_DFD_WRITE_MAGIC:
+		/* only allow to access DFD register base + 0x200 */
+		if (arg1 <= 0x200) {
+			sync_writel(MISC1_CFG_BASE + arg1, arg2);
+		}
+		break;
+	default:
+		ret = MTK_SIP_E_INVALID_PARAM;
+		break;
+	}
+
+	return ret;
+}
diff --git a/plat/mediatek/mt8195/drivers/dfd/plat_dfd.h b/plat/mediatek/mt8195/drivers/dfd/plat_dfd.h
new file mode 100644
index 0000000..2a7e979
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/dfd/plat_dfd.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DFD_H
+#define PLAT_DFD_H
+
+#include <arch_helpers.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#define sync_writel(addr, val)	do { mmio_write_32((addr), (val)); \
+				dsbsy(); \
+				} while (0)
+
+#define PLAT_MTK_DFD_SETUP_MAGIC		(0x99716150)
+#define PLAT_MTK_DFD_READ_MAGIC			(0x99716151)
+#define PLAT_MTK_DFD_WRITE_MAGIC		(0x99716152)
+
+#define MTK_DRM_LATCH_CTL1                      (DRM_BASE + 0x40)
+#define MTK_DRM_LATCH_CTL2			(DRM_BASE + 0x44)
+
+#define MTK_WDT_BASE				(RGU_BASE)
+#define MTK_WDT_INTERVAL			(MTK_WDT_BASE + 0x10)
+#define MTK_WDT_LATCH_CTL2			(MTK_WDT_BASE + 0x48)
+
+#define MCU_BIU_BASE				(MCUCFG_BASE)
+#define MISC1_CFG_BASE				(MCU_BIU_BASE + 0xE040)
+#define DFD_INTERNAL_CTL			(MISC1_CFG_BASE + 0x00)
+#define DFD_INTERNAL_PWR_ON			(MISC1_CFG_BASE + 0x08)
+#define DFD_CHAIN_LENGTH0			(MISC1_CFG_BASE + 0x0C)
+#define DFD_INTERNAL_SHIFT_CLK_RATIO		(MISC1_CFG_BASE + 0x10)
+#define DFD_CHAIN_LENGTH1			(MISC1_CFG_BASE + 0x1C)
+#define DFD_CHAIN_LENGTH2			(MISC1_CFG_BASE + 0x20)
+#define DFD_CHAIN_LENGTH3			(MISC1_CFG_BASE + 0x24)
+#define DFD_INTERNAL_TEST_SO_0			(MISC1_CFG_BASE + 0x28)
+#define DFD_INTERNAL_NUM_OF_TEST_SO_GROUP	(MISC1_CFG_BASE + 0x30)
+#define DFD_INTERNAL_TEST_SO_OVER_64		(MISC1_CFG_BASE + 0x34)
+#define DFD_INTERNAL_SW_NS_TRIGGER		(MISC1_CFG_BASE + 0x3c)
+#define DFD_V30_CTL				(MISC1_CFG_BASE + 0x48)
+#define DFD_V30_BASE_ADDR			(MISC1_CFG_BASE + 0x4C)
+#define DFD_POWER_CTL				(MISC1_CFG_BASE + 0x50)
+#define DFD_TEST_SI_0				(MISC1_CFG_BASE + 0x58)
+#define DFD_TEST_SI_1				(MISC1_CFG_BASE + 0x5C)
+#define DFD_CLEAN_STATUS			(MISC1_CFG_BASE + 0x60)
+#define DFD_TEST_SI_2				(MISC1_CFG_BASE + 0x1D8)
+#define DFD_TEST_SI_3				(MISC1_CFG_BASE + 0x1DC)
+#define DFD_READ_ADDR				(MISC1_CFG_BASE + 0x1E8)
+#define DFD_HW_TRIGGER_MASK			(MISC1_CFG_BASE + 0xBC)
+
+#define DFD_V35_ENABLE				(MCU_BIU_BASE + 0xE0A8)
+#define DFD_V35_TAP_NUMBER			(MCU_BIU_BASE + 0xE0AC)
+#define DFD_V35_TAP_EN				(MCU_BIU_BASE + 0xE0B0)
+#define DFD_V35_CTL				(MCU_BIU_BASE + 0xE0B4)
+#define DFD_V35_SEQ0_0				(MCU_BIU_BASE + 0xE0C0)
+#define DFD_V35_SEQ0_1				(MCU_BIU_BASE + 0xE0C4)
+#define DFD_V50_GROUP_0_63_DIFF			(MCU_BIU_BASE + 0xE2AC)
+
+#define DFD_O_PROTECT_EN_REG			(0x10001220)
+#define DFD_O_INTRF_MCU_PWR_CTL_MASK		(0x10001A3C)
+#define DFD_O_SET_BASEADDR_REG			(0x10043000)
+#define DFD_O_REG_0				(0x10001390)
+
+#define DFD_CACHE_DUMP_ENABLE			1U
+#define DFD_PARITY_ERR_TRIGGER			2U
+
+#define	DFD_V35_TAP_EN_VAL			(0x43FF)
+#define	DFD_V35_SEQ0_0_VAL			(0x63668820)
+#define DFD_READ_ADDR_VAL			(0x40000008)
+#define DFD_CHAIN_LENGTH_VAL			(0xFFFFFFFF)
+
+#define MTK_WDT_LATCH_CTL2_VAL			(0x9507FFFF)
+#define MTK_WDT_INTERVAL_VAL			(0x6600000A)
+#define MTK_DRM_LATCH_CTL2_VAL			(0x950600C8)
+#define MTK_DRM_LATCH_CTL2_CACHE_VAL		(0x95065DC0)
+
+#define MTK_DRM_LATCH_CTL1_VAL			(0x95000013)
+
+void dfd_resume(void);
+uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1,
+			    uint64_t arg2, uint64_t arg3);
+
+#endif /* PLAT_DFD_H */
diff --git a/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c b/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c
new file mode 100644
index 0000000..4330b77
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <emi_mpu.h>
+
+#if ENABLE_EMI_MPU_SW_LOCK
+static unsigned char region_lock_state[EMI_MPU_REGION_NUM];
+#endif
+
+#define EMI_MPU_START_MASK		(0x00FFFFFF)
+#define EMI_MPU_END_MASK		(0x00FFFFFF)
+#define EMI_MPU_APC_SW_LOCK_MASK	(0x00FFFFFF)
+#define EMI_MPU_APC_HW_LOCK_MASK	(0x80FFFFFF)
+
+static int _emi_mpu_set_protection(unsigned int start, unsigned int end,
+					unsigned int apc)
+{
+	unsigned int dgroup;
+	unsigned int region;
+
+	region = (start >> 24) & 0xFF;
+	start &= EMI_MPU_START_MASK;
+	dgroup = (end >> 24) & 0xFF;
+	end &= EMI_MPU_END_MASK;
+
+	if  ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) {
+		WARN("invalid region, domain\n");
+		return -1;
+	}
+
+#if ENABLE_EMI_MPU_SW_LOCK
+	if (region_lock_state[region] == 1) {
+		WARN("invalid region\n");
+		return -1;
+	}
+
+	if ((dgroup == 0) && ((apc >> 31) & 0x1)) {
+		region_lock_state[region] = 1;
+	}
+
+	apc &= EMI_MPU_APC_SW_LOCK_MASK;
+#else
+	apc &= EMI_MPU_APC_HW_LOCK_MASK;
+#endif
+
+	if ((start >= DRAM_OFFSET) && (end >= start)) {
+		start -= DRAM_OFFSET;
+		end -= DRAM_OFFSET;
+	} else {
+		WARN("invalid range\n");
+		return -1;
+	}
+
+	mmio_write_32(EMI_MPU_SA(region), start);
+	mmio_write_32(EMI_MPU_EA(region), end);
+	mmio_write_32(EMI_MPU_APC(region, dgroup), apc);
+
+#if defined(SUB_EMI_MPU_BASE)
+	mmio_write_32(SUB_EMI_MPU_SA(region), start);
+	mmio_write_32(SUB_EMI_MPU_EA(region), end);
+	mmio_write_32(SUB_EMI_MPU_APC(region, dgroup), apc);
+#endif
+	return 1;
+}
+
+int emi_mpu_set_protection(struct emi_region_info_t *region_info)
+{
+	unsigned int start, end;
+	int i;
+
+	if (region_info->region >= EMI_MPU_REGION_NUM) {
+		WARN("invalid region\n");
+		return -1;
+	}
+
+	start = (unsigned int)(region_info->start >> EMI_MPU_ALIGN_BITS) |
+		(region_info->region << 24);
+
+	for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) {
+		end = (unsigned int)(region_info->end >> EMI_MPU_ALIGN_BITS) |
+			(i << 24);
+		_emi_mpu_set_protection(start, end, region_info->apc[i]);
+	}
+
+	return 0;
+}
+
+void emi_mpu_init(void)
+{
+	/* TODO: more setting for EMI MPU. */
+}
diff --git a/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.h b/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.h
new file mode 100644
index 0000000..415146e
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EMI_MPU_H
+#define EMI_MPU_H
+
+#include <platform_def.h>
+
+#define ENABLE_EMI_MPU_SW_LOCK		1
+
+#define EMI_MPU_CTRL			(EMI_MPU_BASE + 0x000)
+#define EMI_MPU_DBG			(EMI_MPU_BASE + 0x004)
+#define EMI_MPU_SA0			(EMI_MPU_BASE + 0x100)
+#define EMI_MPU_EA0			(EMI_MPU_BASE + 0x200)
+#define EMI_MPU_SA(region)		(EMI_MPU_SA0 + (region * 4))
+#define EMI_MPU_EA(region)		(EMI_MPU_EA0 + (region * 4))
+#define EMI_MPU_APC0			(EMI_MPU_BASE + 0x300)
+#define EMI_MPU_APC(region, dgroup)	(EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100))
+#define EMI_MPU_CTRL_D0			(EMI_MPU_BASE + 0x800)
+#define EMI_MPU_CTRL_D(domain)		(EMI_MPU_CTRL_D0 + (domain * 4))
+#define EMI_RG_MASK_D0			(EMI_MPU_BASE + 0x900)
+#define EMI_RG_MASK_D(domain)		(EMI_RG_MASK_D0 + (domain * 4))
+#define EMI_MPU_START			(0x000)
+#define EMI_MPU_END			(0x93C)
+
+#define SUB_EMI_MPU_CTRL		(SUB_EMI_MPU_BASE + 0x000)
+#define SUB_EMI_MPU_DBG			(SUB_EMI_MPU_BASE + 0x004)
+#define SUB_EMI_MPU_SA0			(SUB_EMI_MPU_BASE + 0x100)
+#define SUB_EMI_MPU_EA0			(SUB_EMI_MPU_BASE + 0x200)
+#define SUB_EMI_MPU_SA(region)		(SUB_EMI_MPU_SA0 + (region * 4))
+#define SUB_EMI_MPU_EA(region)		(SUB_EMI_MPU_EA0 + (region * 4))
+#define SUB_EMI_MPU_APC0		(SUB_EMI_MPU_BASE + 0x300)
+#define SUB_EMI_MPU_APC(region, dgroup)	(SUB_EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100))
+#define SUB_EMI_MPU_CTRL_D0		(SUB_EMI_MPU_BASE + 0x800)
+#define SUB_EMI_MPU_CTRL_D(domain)	(SUB_EMI_MPU_CTRL_D0 + (domain * 4))
+#define SUB_EMI_RG_MASK_D0		(SUB_EMI_MPU_BASE + 0x900)
+#define SUB_EMI_RG_MASK_D(domain)	(SUB_EMI_RG_MASK_D0 + (domain * 4))
+
+#define EMI_MPU_DOMAIN_NUM		(16)
+#define EMI_MPU_REGION_NUM		(32)
+#define EMI_MPU_ALIGN_BITS		(16)
+#define DRAM_OFFSET			(0x40000000 >> EMI_MPU_ALIGN_BITS)
+
+#define NO_PROTECTION			0
+#define SEC_RW				1
+#define SEC_RW_NSEC_R			2
+#define SEC_RW_NSEC_W			3
+#define SEC_R_NSEC_R			4
+#define FORBIDDEN			5
+#define SEC_R_NSEC_RW			6
+
+#define LOCK				1
+#define UNLOCK				0
+
+#define EMI_MPU_DGROUP_NUM		(EMI_MPU_DOMAIN_NUM / 8)
+
+#if (EMI_MPU_DGROUP_NUM == 1)
+#define SET_ACCESS_PERMISSION(apc_ary, lock, d7, d6, d5, d4, d3, d2, d1, d0) \
+do { \
+	apc_ary[1] = 0; \
+	apc_ary[0] = \
+		(((unsigned int)  d7) << 21) | (((unsigned int)  d6) << 18) | \
+		(((unsigned int)  d5) << 15) | (((unsigned int)  d4) << 12) | \
+		(((unsigned int)  d3) <<  9) | (((unsigned int)  d2) <<  6) | \
+		(((unsigned int)  d1) <<  3) |  ((unsigned int)  d0) | \
+		((unsigned int) lock << 31); \
+} while (0)
+#elif (EMI_MPU_DGROUP_NUM == 2)
+#define SET_ACCESS_PERMISSION(apc_ary, lock, d15, d14, d13, d12, d11, d10, \
+				d9, d8, d7, d6, d5, d4, d3, d2, d1, d0) \
+do { \
+	apc_ary[1] = \
+		(((unsigned int) d15) << 21) | (((unsigned int) d14) << 18) | \
+		(((unsigned int) d13) << 15) | (((unsigned int) d12) << 12) | \
+		(((unsigned int) d11) <<  9) | (((unsigned int) d10) <<  6) | \
+		(((unsigned int)  d9) <<  3) |  ((unsigned int)  d8); \
+	apc_ary[0] = \
+		(((unsigned int)  d7) << 21) | (((unsigned int)  d6) << 18) | \
+		(((unsigned int)  d5) << 15) | (((unsigned int)  d4) << 12) | \
+		(((unsigned int)  d3) <<  9) | (((unsigned int)  d2) <<  6) | \
+		(((unsigned int)  d1) <<  3) |  ((unsigned int)  d0) | \
+		((unsigned int) lock << 31); \
+} while (0)
+#endif
+
+struct emi_region_info_t {
+	unsigned long long start;
+	unsigned long long end;
+	unsigned int region;
+	unsigned int apc[EMI_MPU_DGROUP_NUM];
+};
+
+void emi_mpu_init(void);
+
+#endif
diff --git a/plat/mediatek/mt8195/drivers/spm/build.mk b/plat/mediatek/mt8195/drivers/spm/build.mk
index d1ee092..28b2d07 100644
--- a/plat/mediatek/mt8195/drivers/spm/build.mk
+++ b/plat/mediatek/mt8195/drivers/spm/build.mk
@@ -30,7 +30,8 @@
 	${CUR_SPM_FOLDER}/constraints/mt_spm_rc_syspll.c	\
 	${CUR_SPM_FOLDER}/mt_spm_cond.c				\
 	${CUR_SPM_FOLDER}/mt_spm_suspend.c			\
-	${CUR_SPM_FOLDER}/mt_spm_idle.c
+	${CUR_SPM_FOLDER}/mt_spm_idle.c				\
+	${CUR_SPM_FOLDER}/mt_spm_vcorefs.c
 
 ifeq (${MT_SPM_FEATURE_SUPPORT}, no)
 PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_SPM_UNSUPPORT
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.c b/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.c
new file mode 100644
index 0000000..6a85b5c
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.c
@@ -0,0 +1,526 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <stddef.h>
+#include <string.h>
+#include <common/debug.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <mt_spm.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_pmic_wrap.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_vcorefs.h>
+#include <mtk_plat_common.h>
+#include <mtk_sip_svc.h>
+#include <platform_def.h>
+
+#define VCORE_MAX_OPP 4
+#define DRAM_MAX_OPP 7
+
+static bool spm_dvfs_init_done;
+static bool dvfs_enable_done;
+static int vcore_opp_0_uv = 750000;
+static int vcore_opp_1_uv = 650000;
+static int vcore_opp_2_uv = 600000;
+static int vcore_opp_3_uv = 550000;
+
+static struct reg_config dvfsrc_init_configs[] = {
+	{ DVFSRC_HRT_REQ_UNIT,       0x0000001E },
+	{ DVFSRC_DEBOUNCE_TIME,      0x19651965 },
+	{ DVFSRC_TIMEOUT_NEXTREQ,    0x00000015 },
+	{ DVFSRC_LEVEL_MASK,         0x000EE000 },
+	{ DVFSRC_DDR_QOS0,           0x00000019 },
+	{ DVFSRC_DDR_QOS1,           0x00000026 },
+	{ DVFSRC_DDR_QOS2,           0x00000033 },
+	{ DVFSRC_DDR_QOS3,           0x0000003B },
+	{ DVFSRC_DDR_QOS4,           0x0000004C },
+	{ DVFSRC_DDR_QOS5,           0x00000066 },
+	{ DVFSRC_DDR_QOS6,           0x00660066 },
+	{ DVFSRC_LEVEL_LABEL_0_1,    0x50436053 },
+	{ DVFSRC_LEVEL_LABEL_2_3,    0x40335042 },
+	{ DVFSRC_LEVEL_LABEL_4_5,    0x40314032 },
+	{ DVFSRC_LEVEL_LABEL_6_7,    0x30223023 },
+	{ DVFSRC_LEVEL_LABEL_8_9,    0x20133021 },
+	{ DVFSRC_LEVEL_LABEL_10_11,  0x20112012 },
+	{ DVFSRC_LEVEL_LABEL_12_13,  0x10032010 },
+	{ DVFSRC_LEVEL_LABEL_14_15,  0x10011002 },
+	{ DVFSRC_LEVEL_LABEL_16_17,  0x00131000 },
+	{ DVFSRC_LEVEL_LABEL_18_19,  0x00110012 },
+	{ DVFSRC_LEVEL_LABEL_20_21,  0x00000010 },
+	{ DVFSRC_MD_LATENCY_IMPROVE, 0x00000040 },
+	{ DVFSRC_DDR_REQUEST,        0x00004321 },
+	{ DVFSRC_DDR_REQUEST3,       0x00000065 },
+	{ DVFSRC_DDR_ADD_REQUEST,    0x66543210 },
+	{ DVFSRC_HRT_REQUEST,        0x66654321 },
+	{ DVFSRC_DDR_REQUEST5,       0x54321000 },
+	{ DVFSRC_DDR_REQUEST7,       0x66000000 },
+	{ DVFSRC_VCORE_USER_REQ,     0x00010A29 },
+	{ DVFSRC_HRT_HIGH_3,         0x18A618A6 },
+	{ DVFSRC_HRT_HIGH_2,         0x18A61183 },
+	{ DVFSRC_HRT_HIGH_1,         0x0D690B80 },
+	{ DVFSRC_HRT_HIGH,           0x070804B0 },
+	{ DVFSRC_HRT_LOW_3,          0x18A518A5 },
+	{ DVFSRC_HRT_LOW_2,          0x18A51182 },
+	{ DVFSRC_HRT_LOW_1,          0x0D680B7F },
+	{ DVFSRC_HRT_LOW,            0x070704AF },
+	{ DVFSRC_BASIC_CONTROL_3,    0x00000006 },
+	{ DVFSRC_INT_EN,             0x00000002 },
+	{ DVFSRC_QOS_EN,             0x0000407C },
+	{ DVFSRC_HRT_BW_BASE,        0x00000004 },
+	{ DVFSRC_PCIE_VCORE_REQ,     0x65908101 },
+	{ DVFSRC_CURRENT_FORCE,      0x00000001 },
+	{ DVFSRC_BASIC_CONTROL,      0x6698444B },
+	{ DVFSRC_BASIC_CONTROL,      0x6698054B },
+	{ DVFSRC_CURRENT_FORCE,      0x00000000 },
+};
+
+static struct pwr_ctrl vcorefs_ctrl = {
+	.wake_src		= R12_REG_CPU_WAKEUP,
+
+	/* default VCORE DVFS is disabled */
+	.pcm_flags = (SPM_FLAG_RUN_COMMON_SCENARIO |
+			SPM_FLAG_DISABLE_VCORE_DVS | SPM_FLAG_DISABLE_VCORE_DFS),
+
+	/* SPM_AP_STANDBY_CON */
+	/* [0] */
+	.reg_wfi_op = 0,
+	/* [1] */
+	.reg_wfi_type = 0,
+	/* [2] */
+	.reg_mp0_cputop_idle_mask = 0,
+	/* [3] */
+	.reg_mp1_cputop_idle_mask = 0,
+	/* [4] */
+	.reg_mcusys_idle_mask = 0,
+	/* [25] */
+	.reg_md_apsrc_1_sel = 0,
+	/* [26] */
+	.reg_md_apsrc_0_sel = 0,
+	/* [29] */
+	.reg_conn_apsrc_sel = 0,
+
+	/* SPM_SRC_REQ */
+	/* [0] */
+	.reg_spm_apsrc_req = 0,
+	/* [1] */
+	.reg_spm_f26m_req = 0,
+	/* [3] */
+	.reg_spm_infra_req = 0,
+	/* [4] */
+	.reg_spm_vrf18_req = 0,
+	/* [7] FIXME: default disable HW Auto S1*/
+	.reg_spm_ddr_en_req = 1,
+	/* [8] */
+	.reg_spm_dvfs_req = 0,
+	/* [9] */
+	.reg_spm_sw_mailbox_req = 0,
+	/* [10] */
+	.reg_spm_sspm_mailbox_req = 0,
+	/* [11] */
+	.reg_spm_adsp_mailbox_req = 0,
+	/* [12] */
+	.reg_spm_scp_mailbox_req = 0,
+
+	/* SPM_SRC_MASK */
+	/* [0] */
+	.reg_sspm_srcclkena_0_mask_b = 1,
+	/* [1] */
+	.reg_sspm_infra_req_0_mask_b = 1,
+	/* [2] */
+	.reg_sspm_apsrc_req_0_mask_b = 1,
+	/* [3] */
+	.reg_sspm_vrf18_req_0_mask_b = 1,
+	/* [4] */
+	.reg_sspm_ddr_en_0_mask_b = 1,
+	/* [5] */
+	.reg_scp_srcclkena_mask_b = 1,
+	/* [6] */
+	.reg_scp_infra_req_mask_b = 1,
+	/* [7] */
+	.reg_scp_apsrc_req_mask_b = 1,
+	/* [8] */
+	.reg_scp_vrf18_req_mask_b = 1,
+	/* [9] */
+	.reg_scp_ddr_en_mask_b = 1,
+	/* [10] */
+	.reg_audio_dsp_srcclkena_mask_b = 1,
+	/* [11] */
+	.reg_audio_dsp_infra_req_mask_b = 1,
+	/* [12] */
+	.reg_audio_dsp_apsrc_req_mask_b = 1,
+	/* [13] */
+	.reg_audio_dsp_vrf18_req_mask_b = 1,
+	/* [14] */
+	.reg_audio_dsp_ddr_en_mask_b = 1,
+	/* [15] */
+	.reg_apu_srcclkena_mask_b = 1,
+	/* [16] */
+	.reg_apu_infra_req_mask_b = 1,
+	/* [17] */
+	.reg_apu_apsrc_req_mask_b = 1,
+	/* [18] */
+	.reg_apu_vrf18_req_mask_b = 1,
+	/* [19] */
+	.reg_apu_ddr_en_mask_b = 1,
+	/* [20] */
+	.reg_cpueb_srcclkena_mask_b = 1,
+	/* [21] */
+	.reg_cpueb_infra_req_mask_b = 1,
+	/* [22] */
+	.reg_cpueb_apsrc_req_mask_b = 1,
+	/* [23] */
+	.reg_cpueb_vrf18_req_mask_b = 1,
+	/* [24] */
+	.reg_cpueb_ddr_en_mask_b = 1,
+	/* [25] */
+	.reg_bak_psri_srcclkena_mask_b = 0,
+	/* [26] */
+	.reg_bak_psri_infra_req_mask_b = 0,
+	/* [27] */
+	.reg_bak_psri_apsrc_req_mask_b = 0,
+	/* [28] */
+	.reg_bak_psri_vrf18_req_mask_b = 0,
+	/* [29] */
+	.reg_bak_psri_ddr_en_mask_b = 0,
+
+	/* SPM_SRC2_MASK */
+	/* [0] */
+	.reg_msdc0_srcclkena_mask_b = 1,
+	/* [1] */
+	.reg_msdc0_infra_req_mask_b = 1,
+	/* [2] */
+	.reg_msdc0_apsrc_req_mask_b = 1,
+	/* [3] */
+	.reg_msdc0_vrf18_req_mask_b = 1,
+	/* [4] */
+	.reg_msdc0_ddr_en_mask_b = 1,
+	/* [5] */
+	.reg_msdc1_srcclkena_mask_b = 1,
+	/* [6] */
+	.reg_msdc1_infra_req_mask_b = 1,
+	/* [7] */
+	.reg_msdc1_apsrc_req_mask_b = 1,
+	/* [8] */
+	.reg_msdc1_vrf18_req_mask_b = 1,
+	/* [9] */
+	.reg_msdc1_ddr_en_mask_b = 1,
+	/* [10] */
+	.reg_msdc2_srcclkena_mask_b = 1,
+	/* [11] */
+	.reg_msdc2_infra_req_mask_b = 1,
+	/* [12] */
+	.reg_msdc2_apsrc_req_mask_b = 1,
+	/* [13] */
+	.reg_msdc2_vrf18_req_mask_b = 1,
+	/* [14] */
+	.reg_msdc2_ddr_en_mask_b = 1,
+	/* [15] */
+	.reg_ufs_srcclkena_mask_b = 1,
+	/* [16] */
+	.reg_ufs_infra_req_mask_b = 1,
+	/* [17] */
+	.reg_ufs_apsrc_req_mask_b = 1,
+	/* [18] */
+	.reg_ufs_vrf18_req_mask_b = 1,
+	/* [19] */
+	.reg_ufs_ddr_en_mask_b = 1,
+	/* [20] */
+	.reg_usb_srcclkena_mask_b = 1,
+	/* [21] */
+	.reg_usb_infra_req_mask_b = 1,
+	/* [22] */
+	.reg_usb_apsrc_req_mask_b = 1,
+	/* [23] */
+	.reg_usb_vrf18_req_mask_b = 1,
+	/* [24] */
+	.reg_usb_ddr_en_mask_b = 1,
+	/* [25] */
+	.reg_pextp_p0_srcclkena_mask_b = 1,
+	/* [26] */
+	.reg_pextp_p0_infra_req_mask_b = 1,
+	/* [27] */
+	.reg_pextp_p0_apsrc_req_mask_b = 1,
+	/* [28] */
+	.reg_pextp_p0_vrf18_req_mask_b = 1,
+	/* [29] */
+	.reg_pextp_p0_ddr_en_mask_b = 1,
+
+	/* SPM_SRC3_MASK */
+	/* [0] */
+	.reg_pextp_p1_srcclkena_mask_b = 1,
+	/* [1] */
+	.reg_pextp_p1_infra_req_mask_b = 1,
+	/* [2] */
+	.reg_pextp_p1_apsrc_req_mask_b = 1,
+	/* [3] */
+	.reg_pextp_p1_vrf18_req_mask_b = 1,
+	/* [4] */
+	.reg_pextp_p1_ddr_en_mask_b = 1,
+	/* [5] */
+	.reg_gce0_infra_req_mask_b = 1,
+	/* [6] */
+	.reg_gce0_apsrc_req_mask_b = 1,
+	/* [7] */
+	.reg_gce0_vrf18_req_mask_b = 1,
+	/* [8] */
+	.reg_gce0_ddr_en_mask_b = 1,
+	/* [9] */
+	.reg_gce1_infra_req_mask_b = 1,
+	/* [10] */
+	.reg_gce1_apsrc_req_mask_b = 1,
+	/* [11] */
+	.reg_gce1_vrf18_req_mask_b = 1,
+	/* [12] */
+	.reg_gce1_ddr_en_mask_b = 1,
+	/* [13] */
+	.reg_spm_srcclkena_reserved_mask_b = 1,
+	/* [14] */
+	.reg_spm_infra_req_reserved_mask_b = 1,
+	/* [15] */
+	.reg_spm_apsrc_req_reserved_mask_b = 1,
+	/* [16] */
+	.reg_spm_vrf18_req_reserved_mask_b = 1,
+	/* [17] */
+	.reg_spm_ddr_en_reserved_mask_b = 1,
+	/* [18] */
+	.reg_disp0_apsrc_req_mask_b = 1,
+	/* [19] */
+	.reg_disp0_ddr_en_mask_b = 1,
+	/* [20] */
+	.reg_disp1_apsrc_req_mask_b = 1,
+	/* [21] */
+	.reg_disp1_ddr_en_mask_b = 1,
+	/* [22] */
+	.reg_disp2_apsrc_req_mask_b = 1,
+	/* [23] */
+	.reg_disp2_ddr_en_mask_b = 1,
+	/* [24] */
+	.reg_disp3_apsrc_req_mask_b = 1,
+	/* [25] */
+	.reg_disp3_ddr_en_mask_b = 1,
+	/* [26] */
+	.reg_infrasys_apsrc_req_mask_b = 0,
+	/* [27] */
+	.reg_infrasys_ddr_en_mask_b = 1,
+
+	/* [28] */
+	.reg_cg_check_srcclkena_mask_b = 1,
+	/* [29] */
+	.reg_cg_check_apsrc_req_mask_b = 1,
+	/* [30] */
+	.reg_cg_check_vrf18_req_mask_b = 1,
+	/* [31] */
+	.reg_cg_check_ddr_en_mask_b = 1,
+
+	/* SPM_SRC4_MASK */
+	/* [8:0] */
+	.reg_mcusys_merge_apsrc_req_mask_b = 0x11,
+	/* [17:9] */
+	.reg_mcusys_merge_ddr_en_mask_b = 0x11,
+	/* [19:18] */
+	.reg_dramc_md32_infra_req_mask_b = 0,
+	/* [21:20] */
+	.reg_dramc_md32_vrf18_req_mask_b = 0,
+	/* [23:22] */
+	.reg_dramc_md32_ddr_en_mask_b = 0,
+	/* [24] */
+	.reg_dvfsrc_event_trigger_mask_b = 1,
+
+	/* SPM_WAKEUP_EVENT_MASK2 */
+	/* [3:0] */
+	.reg_sc_sw2spm_wakeup_mask_b = 0,
+	/* [4] */
+	.reg_sc_adsp2spm_wakeup_mask_b = 0,
+	/* [8:5] */
+	.reg_sc_sspm2spm_wakeup_mask_b = 0,
+	/* [9] */
+	.reg_sc_scp2spm_wakeup_mask_b = 0,
+	/* [10] */
+	.reg_csyspwrup_ack_mask = 0,
+	/* [11] */
+	.reg_csyspwrup_req_mask = 1,
+
+	/* SPM_WAKEUP_EVENT_MASK */
+	/* [31:0] */
+	.reg_wakeup_event_mask = 0xEFFFFFFF,
+
+	/* SPM_WAKEUP_EVENT_EXT_MASK */
+	/* [31:0] */
+	.reg_ext_wakeup_event_mask = 0xFFFFFFFF,
+};
+
+struct spm_lp_scen __spm_vcorefs = {
+	.pwrctrl	= &vcorefs_ctrl,
+};
+
+static void spm_vcorefs_pwarp_cmd(uint64_t cmd, uint64_t val)
+{
+	if (cmd < NR_IDX_ALL) {
+		mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_ALLINONE, cmd, val);
+	} else {
+		INFO("cmd out of range!\n");
+	}
+}
+
+void spm_dvfsfw_init(uint64_t boot_up_opp, uint64_t dram_issue)
+{
+	if (spm_dvfs_init_done == false) {
+		mmio_write_32(SPM_DVFS_MISC, (mmio_read_32(SPM_DVFS_MISC) &
+				~(SPM_DVFS_FORCE_ENABLE_LSB)) | (SPM_DVFSRC_ENABLE_LSB));
+
+		mmio_write_32(SPM_DVFS_LEVEL, 0x00000001);
+		mmio_write_32(SPM_DVS_DFS_LEVEL, 0x00010001);
+
+		spm_dvfs_init_done = true;
+	}
+}
+
+void __spm_sync_vcore_dvfs_power_control(struct pwr_ctrl *dest_pwr_ctrl,
+						const struct pwr_ctrl *src_pwr_ctrl)
+{
+	uint32_t dvfs_mask = SPM_FLAG_DISABLE_VCORE_DVS |
+			     SPM_FLAG_DISABLE_VCORE_DFS |
+			     SPM_FLAG_ENABLE_VOLTAGE_BIN;
+
+	dest_pwr_ctrl->pcm_flags = (dest_pwr_ctrl->pcm_flags & (~dvfs_mask)) |
+					(src_pwr_ctrl->pcm_flags & dvfs_mask);
+
+	if (dest_pwr_ctrl->pcm_flags_cust) {
+		dest_pwr_ctrl->pcm_flags_cust = (dest_pwr_ctrl->pcm_flags_cust & (~dvfs_mask)) |
+						(src_pwr_ctrl->pcm_flags & dvfs_mask);
+	}
+}
+
+void spm_go_to_vcorefs(uint64_t spm_flags)
+{
+	__spm_set_power_control(__spm_vcorefs.pwrctrl);
+	__spm_set_wakeup_event(__spm_vcorefs.pwrctrl);
+	__spm_set_pcm_flags(__spm_vcorefs.pwrctrl);
+	__spm_send_cpu_wakeup_event();
+}
+
+uint64_t spm_vcorefs_args(uint64_t x1, uint64_t x2, uint64_t x3)
+{
+	uint64_t ret = 0U;
+	uint64_t cmd = x1;
+	uint64_t spm_flags;
+
+	switch (cmd) {
+	case VCOREFS_SMC_CMD_0:
+		spm_dvfsfw_init(x2, x3);
+		break;
+	case VCOREFS_SMC_CMD_1:
+		spm_flags = SPM_FLAG_RUN_COMMON_SCENARIO;
+		if (x2 & SPM_FLAG_DISABLE_VCORE_DVS)
+			spm_flags |= SPM_FLAG_DISABLE_VCORE_DVS;
+		if (x2 & SPM_FLAG_DISABLE_VCORE_DFS)
+			spm_flags |= SPM_FLAG_DISABLE_VCORE_DFS;
+		spm_go_to_vcorefs(spm_flags);
+		break;
+	case VCOREFS_SMC_CMD_3:
+		spm_vcorefs_pwarp_cmd(x2, x3);
+		break;
+	case VCOREFS_SMC_CMD_2:
+	case VCOREFS_SMC_CMD_4:
+	case VCOREFS_SMC_CMD_5:
+	case VCOREFS_SMC_CMD_7:
+	default:
+		break;
+	}
+	return ret;
+}
+
+static void dvfsrc_init(void)
+{
+	int i;
+	int count = ARRAY_SIZE(dvfsrc_init_configs);
+
+	if (dvfs_enable_done == false) {
+		for (i = 0; i < count; i++) {
+			mmio_write_32(dvfsrc_init_configs[i].offset,
+				dvfsrc_init_configs[i].val);
+		}
+
+		mmio_write_32(DVFSRC_QOS_EN, 0x0011007C);
+
+		dvfs_enable_done = true;
+	}
+}
+
+static void spm_vcorefs_vcore_setting(uint64_t flag)
+{
+	spm_vcorefs_pwarp_cmd(3, __vcore_uv_to_pmic(vcore_opp_3_uv));
+	spm_vcorefs_pwarp_cmd(2, __vcore_uv_to_pmic(vcore_opp_2_uv));
+	spm_vcorefs_pwarp_cmd(1, __vcore_uv_to_pmic(vcore_opp_1_uv));
+	spm_vcorefs_pwarp_cmd(0, __vcore_uv_to_pmic(vcore_opp_0_uv));
+}
+
+int spm_vcorefs_get_vcore(unsigned int gear)
+{
+	int ret_val;
+
+	switch (gear) {
+	case 3:
+		ret_val = vcore_opp_0_uv;
+		break;
+	case 2:
+		ret_val = vcore_opp_1_uv;
+		break;
+	case 1:
+		ret_val = vcore_opp_2_uv;
+		break;
+	case 0:
+	default:
+		ret_val = vcore_opp_3_uv;
+		break;
+	}
+	return ret_val;
+}
+
+uint64_t spm_vcorefs_v2_args(u_register_t x1, u_register_t x2, u_register_t x3, u_register_t *x4)
+{
+	uint64_t ret = 0U;
+	uint64_t cmd = x1;
+	uint64_t spm_flags;
+
+	switch (cmd) {
+	case VCOREFS_SMC_CMD_INIT:
+		/* vcore_dvfs init + kick */
+		spm_dvfsfw_init(0, 0);
+		spm_vcorefs_vcore_setting(x3 & 0xF);
+		spm_flags = SPM_FLAG_RUN_COMMON_SCENARIO;
+		if (x2 & 0x1) {
+			spm_flags |= SPM_FLAG_DISABLE_VCORE_DVS;
+		}
+		if (x2 & 0x2) {
+			spm_flags |= SPM_FLAG_DISABLE_VCORE_DFS;
+		}
+		spm_go_to_vcorefs(spm_flags);
+		dvfsrc_init();
+		*x4 = 0U;
+		break;
+	case VCOREFS_SMC_CMD_OPP_TYPE:
+		/* get dram type */
+		*x4 = 0U;
+		break;
+	case VCOREFS_SMC_CMD_FW_TYPE:
+		*x4 = 0U;
+		break;
+	case VCOREFS_SMC_CMD_GET_UV:
+		*x4 = spm_vcorefs_get_vcore(x2);
+		break;
+	case VCOREFS_SMC_CMD_GET_NUM_V:
+		*x4 = VCORE_MAX_OPP;
+		break;
+	case VCOREFS_SMC_CMD_GET_NUM_F:
+		*x4 = DRAM_MAX_OPP;
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.h b/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.h
new file mode 100644
index 0000000..b08fcce
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.h
@@ -0,0 +1,328 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef __MT_SPM_VCOREFS__H__
+#define __MT_SPM_VCOREFS__H__
+
+int spm_vcorefs_get_vcore(unsigned int gear);
+uint64_t spm_vcorefs_v2_args(u_register_t x1, u_register_t x2, u_register_t x3,
+			     u_register_t *x4);
+
+enum vcorefs_smc_cmd {
+	VCOREFS_SMC_CMD_0 = 0,
+	VCOREFS_SMC_CMD_1,
+	VCOREFS_SMC_CMD_2,
+	VCOREFS_SMC_CMD_3,
+	VCOREFS_SMC_CMD_4,
+	/* check spmfw status */
+	VCOREFS_SMC_CMD_5,
+
+	/* get spmfw type */
+	VCOREFS_SMC_CMD_6,
+
+	/* get spm reg status */
+	VCOREFS_SMC_CMD_7,
+
+	NUM_VCOREFS_SMC_CMD,
+};
+
+enum vcorefs_smc_cmd_new {
+	VCOREFS_SMC_CMD_INIT = 0,
+	VCOREFS_SMC_CMD_KICK = 1,
+	VCOREFS_SMC_CMD_OPP_TYPE = 2,
+	VCOREFS_SMC_CMD_FW_TYPE = 3,
+	VCOREFS_SMC_CMD_GET_UV = 4,
+	VCOREFS_SMC_CMD_GET_FREQ = 5,
+	VCOREFS_SMC_CMD_GET_NUM_V = 6,
+	VCOREFS_SMC_CMD_GET_NUM_F = 7,
+	VCOREFS_SMC_CMD_FB_ACTION = 8,
+	/*chip specific setting */
+	VCOREFS_SMC_CMD_SET_FREQ = 16,
+	VCOREFS_SMC_CMD_SET_EFUSE = 17,
+	VCOREFS_SMC_CMD_GET_EFUSE = 18,
+	VCOREFS_SMC_CMD_DVFS_HOPPING = 19,
+	VCOREFS_SMC_CMD_DVFS_HOPPING_STATE = 20,
+};
+
+enum dvfsrc_channel {
+	DVFSRC_CHANNEL_1 = 1,
+	DVFSRC_CHANNEL_2,
+	DVFSRC_CHANNEL_3,
+	DVFSRC_CHANNEL_4,
+	NUM_DVFSRC_CHANNEL,
+};
+
+#define _VCORE_BASE_UV		400000
+#define _VCORE_STEP_UV		6250
+
+/* PMIC */
+#define __vcore_pmic_to_uv(pmic)	\
+	(((pmic) * _VCORE_STEP_UV) + _VCORE_BASE_UV)
+
+#define __vcore_uv_to_pmic(uv)	/* pmic >= uv */	\
+	((((uv) - _VCORE_BASE_UV) + (_VCORE_STEP_UV - 1)) / _VCORE_STEP_UV)
+
+struct reg_config {
+	uint32_t offset;
+	uint32_t val;
+};
+
+#define DVFSRC_BASIC_CONTROL             (DVFSRC_BASE + 0x0)
+#define DVFSRC_SW_REQ1                   (DVFSRC_BASE + 0x4)
+#define DVFSRC_SW_REQ2                   (DVFSRC_BASE + 0x8)
+#define DVFSRC_SW_REQ3                   (DVFSRC_BASE + 0xC)
+#define DVFSRC_SW_REQ4                   (DVFSRC_BASE + 0x10)
+#define DVFSRC_SW_REQ5                   (DVFSRC_BASE + 0x14)
+#define DVFSRC_SW_REQ6                   (DVFSRC_BASE + 0x18)
+#define DVFSRC_SW_REQ7                   (DVFSRC_BASE + 0x1C)
+#define DVFSRC_SW_REQ8                   (DVFSRC_BASE + 0x20)
+#define DVFSRC_EMI_REQUEST               (DVFSRC_BASE + 0x24)
+#define DVFSRC_EMI_REQUEST2              (DVFSRC_BASE + 0x28)
+#define DVFSRC_EMI_REQUEST3              (DVFSRC_BASE + 0x2C)
+#define DVFSRC_EMI_REQUEST4              (DVFSRC_BASE + 0x30)
+#define DVFSRC_EMI_REQUEST5              (DVFSRC_BASE + 0x34)
+#define DVFSRC_EMI_REQUEST6              (DVFSRC_BASE + 0x38)
+#define DVFSRC_EMI_HRT                   (DVFSRC_BASE + 0x3C)
+#define DVFSRC_EMI_HRT2                  (DVFSRC_BASE + 0x40)
+#define DVFSRC_EMI_HRT3                  (DVFSRC_BASE + 0x44)
+#define DVFSRC_EMI_QOS0                  (DVFSRC_BASE + 0x48)
+#define DVFSRC_EMI_QOS1                  (DVFSRC_BASE + 0x4C)
+#define DVFSRC_EMI_QOS2                  (DVFSRC_BASE + 0x50)
+#define DVFSRC_EMI_MD2SPM0               (DVFSRC_BASE + 0x54)
+#define DVFSRC_EMI_MD2SPM1               (DVFSRC_BASE + 0x58)
+#define DVFSRC_EMI_MD2SPM2               (DVFSRC_BASE + 0x5C)
+#define DVFSRC_EMI_MD2SPM0_T             (DVFSRC_BASE + 0x60)
+#define DVFSRC_EMI_MD2SPM1_T             (DVFSRC_BASE + 0x64)
+#define DVFSRC_EMI_MD2SPM2_T             (DVFSRC_BASE + 0x68)
+#define DVFSRC_VCORE_REQUEST             (DVFSRC_BASE + 0x6C)
+#define DVFSRC_VCORE_REQUEST2            (DVFSRC_BASE + 0x70)
+#define DVFSRC_VCORE_REQUEST3            (DVFSRC_BASE + 0x74)
+#define DVFSRC_VCORE_REQUEST4            (DVFSRC_BASE + 0x78)
+#define DVFSRC_VCORE_HRT                 (DVFSRC_BASE + 0x7C)
+#define DVFSRC_VCORE_HRT2                (DVFSRC_BASE + 0x80)
+#define DVFSRC_VCORE_HRT3                (DVFSRC_BASE + 0x84)
+#define DVFSRC_VCORE_QOS0                (DVFSRC_BASE + 0x88)
+#define DVFSRC_VCORE_QOS1                (DVFSRC_BASE + 0x8C)
+#define DVFSRC_VCORE_QOS2                (DVFSRC_BASE + 0x90)
+#define DVFSRC_VCORE_MD2SPM0             (DVFSRC_BASE + 0x94)
+#define DVFSRC_VCORE_MD2SPM1             (DVFSRC_BASE + 0x98)
+#define DVFSRC_VCORE_MD2SPM2             (DVFSRC_BASE + 0x9C)
+#define DVFSRC_VCORE_MD2SPM0_T           (DVFSRC_BASE + 0xA0)
+#define DVFSRC_VCORE_MD2SPM1_T           (DVFSRC_BASE + 0xA4)
+#define DVFSRC_VCORE_MD2SPM2_T           (DVFSRC_BASE + 0xA8)
+#define DVFSRC_MD_VSRAM_REMAP            (DVFSRC_BASE + 0xBC)
+#define DVFSRC_HALT_SW_CONTROL           (DVFSRC_BASE + 0xC0)
+#define DVFSRC_INT                       (DVFSRC_BASE + 0xC4)
+#define DVFSRC_INT_EN                    (DVFSRC_BASE + 0xC8)
+#define DVFSRC_INT_CLR                   (DVFSRC_BASE + 0xCC)
+#define DVFSRC_BW_MON_WINDOW             (DVFSRC_BASE + 0xD0)
+#define DVFSRC_BW_MON_THRES_1            (DVFSRC_BASE + 0xD4)
+#define DVFSRC_BW_MON_THRES_2            (DVFSRC_BASE + 0xD8)
+#define DVFSRC_MD_TURBO                  (DVFSRC_BASE + 0xDC)
+#define DVFSRC_PCIE_VCORE_REQ            (DVFSRC_BASE + 0xE0)
+#define DVFSRC_VCORE_USER_REQ            (DVFSRC_BASE + 0xE4)
+#define DVFSRC_DEBOUNCE_FOUR             (DVFSRC_BASE + 0xF0)
+#define DVFSRC_DEBOUNCE_RISE_FALL        (DVFSRC_BASE + 0xF4)
+#define DVFSRC_TIMEOUT_NEXTREQ           (DVFSRC_BASE + 0xF8)
+#define DVFSRC_LEVEL_LABEL_0_1           (DVFSRC_BASE + 0x100)
+#define DVFSRC_LEVEL_LABEL_2_3           (DVFSRC_BASE + 0x104)
+#define DVFSRC_LEVEL_LABEL_4_5           (DVFSRC_BASE + 0x108)
+#define DVFSRC_LEVEL_LABEL_6_7           (DVFSRC_BASE + 0x10C)
+#define DVFSRC_LEVEL_LABEL_8_9           (DVFSRC_BASE + 0x110)
+#define DVFSRC_LEVEL_LABEL_10_11         (DVFSRC_BASE + 0x114)
+#define DVFSRC_LEVEL_LABEL_12_13         (DVFSRC_BASE + 0x118)
+#define DVFSRC_LEVEL_LABEL_14_15         (DVFSRC_BASE + 0x11C)
+#define DVFSRC_MM_BW_0                   (DVFSRC_BASE + 0x200)
+#define DVFSRC_MM_BW_1                   (DVFSRC_BASE + 0x204)
+#define DVFSRC_MM_BW_2                   (DVFSRC_BASE + 0x208)
+#define DVFSRC_MM_BW_3                   (DVFSRC_BASE + 0x20C)
+#define DVFSRC_MM_BW_4                   (DVFSRC_BASE + 0x210)
+#define DVFSRC_MM_BW_5                   (DVFSRC_BASE + 0x214)
+#define DVFSRC_MM_BW_6                   (DVFSRC_BASE + 0x218)
+#define DVFSRC_MM_BW_7                   (DVFSRC_BASE + 0x21C)
+#define DVFSRC_MM_BW_8                   (DVFSRC_BASE + 0x220)
+#define DVFSRC_MM_BW_9                   (DVFSRC_BASE + 0x224)
+#define DVFSRC_MM_BW_10                  (DVFSRC_BASE + 0x228)
+#define DVFSRC_MM_BW_11                  (DVFSRC_BASE + 0x22C)
+#define DVFSRC_MM_BW_12                  (DVFSRC_BASE + 0x230)
+#define DVFSRC_MM_BW_13                  (DVFSRC_BASE + 0x234)
+#define DVFSRC_MM_BW_14                  (DVFSRC_BASE + 0x238)
+#define DVFSRC_MM_BW_15                  (DVFSRC_BASE + 0x23C)
+#define DVFSRC_MD_BW_0                   (DVFSRC_BASE + 0x240)
+#define DVFSRC_MD_BW_1                   (DVFSRC_BASE + 0x244)
+#define DVFSRC_MD_BW_2                   (DVFSRC_BASE + 0x248)
+#define DVFSRC_MD_BW_3                   (DVFSRC_BASE + 0x24C)
+#define DVFSRC_MD_BW_4                   (DVFSRC_BASE + 0x250)
+#define DVFSRC_MD_BW_5                   (DVFSRC_BASE + 0x254)
+#define DVFSRC_MD_BW_6                   (DVFSRC_BASE + 0x258)
+#define DVFSRC_MD_BW_7                   (DVFSRC_BASE + 0x25C)
+#define DVFSRC_SW_BW_0                   (DVFSRC_BASE + 0x260)
+#define DVFSRC_SW_BW_1                   (DVFSRC_BASE + 0x264)
+#define DVFSRC_SW_BW_2                   (DVFSRC_BASE + 0x268)
+#define DVFSRC_SW_BW_3                   (DVFSRC_BASE + 0x26C)
+#define DVFSRC_SW_BW_4                   (DVFSRC_BASE + 0x270)
+#define DVFSRC_SW_BW_5                   (DVFSRC_BASE + 0x274)
+#define DVFSRC_SW_BW_6                   (DVFSRC_BASE + 0x278)
+#define DVFSRC_QOS_EN                    (DVFSRC_BASE + 0x280)
+#define DVFSRC_MD_BW_URG                 (DVFSRC_BASE + 0x284)
+#define DVFSRC_ISP_HRT                   (DVFSRC_BASE + 0x290)
+#define DVFSRC_HRT_BW_BASE               (DVFSRC_BASE + 0x294)
+#define DVFSRC_SEC_SW_REQ                (DVFSRC_BASE + 0x304)
+#define DVFSRC_EMI_MON_DEBOUNCE_TIME     (DVFSRC_BASE + 0x308)
+#define DVFSRC_MD_LATENCY_IMPROVE        (DVFSRC_BASE + 0x30C)
+#define DVFSRC_BASIC_CONTROL_3           (DVFSRC_BASE + 0x310)
+#define DVFSRC_DEBOUNCE_TIME             (DVFSRC_BASE + 0x314)
+#define DVFSRC_LEVEL_MASK                (DVFSRC_BASE + 0x318)
+#define DVFSRC_DEFAULT_OPP               (DVFSRC_BASE + 0x31C)
+#define DVFSRC_95MD_SCEN_EMI0            (DVFSRC_BASE + 0x500)
+#define DVFSRC_95MD_SCEN_EMI1            (DVFSRC_BASE + 0x504)
+#define DVFSRC_95MD_SCEN_EMI2            (DVFSRC_BASE + 0x508)
+#define DVFSRC_95MD_SCEN_EMI3            (DVFSRC_BASE + 0x50C)
+#define DVFSRC_95MD_SCEN_EMI0_T          (DVFSRC_BASE + 0x510)
+#define DVFSRC_95MD_SCEN_EMI1_T          (DVFSRC_BASE + 0x514)
+#define DVFSRC_95MD_SCEN_EMI2_T          (DVFSRC_BASE + 0x518)
+#define DVFSRC_95MD_SCEN_EMI3_T          (DVFSRC_BASE + 0x51C)
+#define DVFSRC_95MD_SCEN_EMI4            (DVFSRC_BASE + 0x520)
+#define DVFSRC_95MD_SCEN_BW0             (DVFSRC_BASE + 0x524)
+#define DVFSRC_95MD_SCEN_BW1             (DVFSRC_BASE + 0x528)
+#define DVFSRC_95MD_SCEN_BW2             (DVFSRC_BASE + 0x52C)
+#define DVFSRC_95MD_SCEN_BW3             (DVFSRC_BASE + 0x530)
+#define DVFSRC_95MD_SCEN_BW0_T           (DVFSRC_BASE + 0x534)
+#define DVFSRC_95MD_SCEN_BW1_T           (DVFSRC_BASE + 0x538)
+#define DVFSRC_95MD_SCEN_BW2_T           (DVFSRC_BASE + 0x53C)
+#define DVFSRC_95MD_SCEN_BW3_T           (DVFSRC_BASE + 0x540)
+#define DVFSRC_95MD_SCEN_BW4             (DVFSRC_BASE + 0x544)
+#define DVFSRC_MD_LEVEL_SW_REG           (DVFSRC_BASE + 0x548)
+#define DVFSRC_RSRV_0                    (DVFSRC_BASE + 0x600)
+#define DVFSRC_RSRV_1                    (DVFSRC_BASE + 0x604)
+#define DVFSRC_RSRV_2                    (DVFSRC_BASE + 0x608)
+#define DVFSRC_RSRV_3                    (DVFSRC_BASE + 0x60C)
+#define DVFSRC_RSRV_4                    (DVFSRC_BASE + 0x610)
+#define DVFSRC_RSRV_5                    (DVFSRC_BASE + 0x614)
+#define DVFSRC_SPM_RESEND                (DVFSRC_BASE + 0x630)
+#define DVFSRC_DEBUG_STA_0               (DVFSRC_BASE + 0x700)
+#define DVFSRC_DEBUG_STA_1               (DVFSRC_BASE + 0x704)
+#define DVFSRC_DEBUG_STA_2               (DVFSRC_BASE + 0x708)
+#define DVFSRC_DEBUG_STA_3               (DVFSRC_BASE + 0x70C)
+#define DVFSRC_DEBUG_STA_4               (DVFSRC_BASE + 0x710)
+#define DVFSRC_DEBUG_STA_5               (DVFSRC_BASE + 0x714)
+#define DVFSRC_EMI_REQUEST7              (DVFSRC_BASE + 0x800)
+#define DVFSRC_EMI_HRT_1                 (DVFSRC_BASE + 0x804)
+#define DVFSRC_EMI_HRT2_1                (DVFSRC_BASE + 0x808)
+#define DVFSRC_EMI_HRT3_1                (DVFSRC_BASE + 0x80C)
+#define DVFSRC_EMI_QOS3                  (DVFSRC_BASE + 0x810)
+#define DVFSRC_EMI_QOS4                  (DVFSRC_BASE + 0x814)
+#define DVFSRC_DDR_REQUEST               (DVFSRC_BASE + 0xA00)
+#define DVFSRC_DDR_REQUEST2              (DVFSRC_BASE + 0xA04)
+#define DVFSRC_DDR_REQUEST3              (DVFSRC_BASE + 0xA08)
+#define DVFSRC_DDR_REQUEST4              (DVFSRC_BASE + 0xA0C)
+#define DVFSRC_DDR_REQUEST5              (DVFSRC_BASE + 0xA10)
+#define DVFSRC_DDR_REQUEST6              (DVFSRC_BASE + 0xA14)
+#define DVFSRC_DDR_REQUEST7              (DVFSRC_BASE + 0xA18)
+#define DVFSRC_DDR_HRT                   (DVFSRC_BASE + 0xA1C)
+#define DVFSRC_DDR_HRT2                  (DVFSRC_BASE + 0xA20)
+#define DVFSRC_DDR_HRT3                  (DVFSRC_BASE + 0xA24)
+#define DVFSRC_DDR_HRT_1                 (DVFSRC_BASE + 0xA28)
+#define DVFSRC_DDR_HRT2_1                (DVFSRC_BASE + 0xA2C)
+#define DVFSRC_DDR_HRT3_1                (DVFSRC_BASE + 0xA30)
+#define DVFSRC_DDR_QOS0                  (DVFSRC_BASE + 0xA34)
+#define DVFSRC_DDR_QOS1                  (DVFSRC_BASE + 0xA38)
+#define DVFSRC_DDR_QOS2                  (DVFSRC_BASE + 0xA3C)
+#define DVFSRC_DDR_QOS3                  (DVFSRC_BASE + 0xA40)
+#define DVFSRC_DDR_QOS4                  (DVFSRC_BASE + 0xA44)
+#define DVFSRC_DDR_MD2SPM0               (DVFSRC_BASE + 0xA48)
+#define DVFSRC_DDR_MD2SPM1               (DVFSRC_BASE + 0xA4C)
+#define DVFSRC_DDR_MD2SPM2               (DVFSRC_BASE + 0xA50)
+#define DVFSRC_DDR_MD2SPM0_T             (DVFSRC_BASE + 0xA54)
+#define DVFSRC_DDR_MD2SPM1_T             (DVFSRC_BASE + 0xA58)
+#define DVFSRC_DDR_MD2SPM2_T             (DVFSRC_BASE + 0xA5C)
+#define DVFSRC_HRT_REQ_UNIT              (DVFSRC_BASE + 0xA60)
+#define DVSFRC_HRT_REQ_MD_URG            (DVFSRC_BASE + 0xA64)
+#define DVFSRC_HRT_REQ_MD_BW_0           (DVFSRC_BASE + 0xA68)
+#define DVFSRC_HRT_REQ_MD_BW_1           (DVFSRC_BASE + 0xA6C)
+#define DVFSRC_HRT_REQ_MD_BW_2           (DVFSRC_BASE + 0xA70)
+#define DVFSRC_HRT_REQ_MD_BW_3           (DVFSRC_BASE + 0xA74)
+#define DVFSRC_HRT_REQ_MD_BW_4           (DVFSRC_BASE + 0xA78)
+#define DVFSRC_HRT_REQ_MD_BW_5           (DVFSRC_BASE + 0xA7C)
+#define DVFSRC_HRT_REQ_MD_BW_6           (DVFSRC_BASE + 0xA80)
+#define DVFSRC_HRT_REQ_MD_BW_7           (DVFSRC_BASE + 0xA84)
+#define DVFSRC_HRT1_REQ_MD_BW_0          (DVFSRC_BASE + 0xA88)
+#define DVFSRC_HRT1_REQ_MD_BW_1          (DVFSRC_BASE + 0xA8C)
+#define DVFSRC_HRT1_REQ_MD_BW_2          (DVFSRC_BASE + 0xA90)
+#define DVFSRC_HRT1_REQ_MD_BW_3          (DVFSRC_BASE + 0xA94)
+#define DVFSRC_HRT1_REQ_MD_BW_4          (DVFSRC_BASE + 0xA98)
+#define DVFSRC_HRT1_REQ_MD_BW_5          (DVFSRC_BASE + 0xA9C)
+#define DVFSRC_HRT1_REQ_MD_BW_6          (DVFSRC_BASE + 0xAA0)
+#define DVFSRC_HRT1_REQ_MD_BW_7          (DVFSRC_BASE + 0xAA4)
+#define DVFSRC_HRT_REQ_MD_BW_8           (DVFSRC_BASE + 0xAA8)
+#define DVFSRC_HRT_REQ_MD_BW_9           (DVFSRC_BASE + 0xAAC)
+#define DVFSRC_HRT_REQ_MD_BW_10          (DVFSRC_BASE + 0xAB0)
+#define DVFSRC_HRT1_REQ_MD_BW_8          (DVFSRC_BASE + 0xAB4)
+#define DVFSRC_HRT1_REQ_MD_BW_9          (DVFSRC_BASE + 0xAB8)
+#define DVFSRC_HRT1_REQ_MD_BW_10         (DVFSRC_BASE + 0xABC)
+#define DVFSRC_HRT_REQ_BW_SW_REG         (DVFSRC_BASE + 0xAC0)
+#define DVFSRC_HRT_REQUEST               (DVFSRC_BASE + 0xAC4)
+#define DVFSRC_HRT_HIGH_2                (DVFSRC_BASE + 0xAC8)
+#define DVFSRC_HRT_HIGH_1                (DVFSRC_BASE + 0xACC)
+#define DVFSRC_HRT_HIGH                  (DVFSRC_BASE + 0xAD0)
+#define DVFSRC_HRT_LOW_2                 (DVFSRC_BASE + 0xAD4)
+#define DVFSRC_HRT_LOW_1                 (DVFSRC_BASE + 0xAD8)
+#define DVFSRC_HRT_LOW                   (DVFSRC_BASE + 0xADC)
+#define DVFSRC_DDR_ADD_REQUEST           (DVFSRC_BASE + 0xAE0)
+#define DVFSRC_LAST                      (DVFSRC_BASE + 0xAE4)
+#define DVFSRC_LAST_L                    (DVFSRC_BASE + 0xAE8)
+#define DVFSRC_MD_SCENARIO               (DVFSRC_BASE + 0xAEC)
+#define DVFSRC_RECORD_0_0                (DVFSRC_BASE + 0xAF0)
+#define DVFSRC_RECORD_0_1                (DVFSRC_BASE + 0xAF4)
+#define DVFSRC_RECORD_0_2                (DVFSRC_BASE + 0xAF8)
+#define DVFSRC_RECORD_0_3                (DVFSRC_BASE + 0xAFC)
+#define DVFSRC_RECORD_0_4                (DVFSRC_BASE + 0xB00)
+#define DVFSRC_RECORD_0_5                (DVFSRC_BASE + 0xB04)
+#define DVFSRC_RECORD_0_6                (DVFSRC_BASE + 0xB08)
+#define DVFSRC_RECORD_0_7                (DVFSRC_BASE + 0xB0C)
+#define DVFSRC_RECORD_0_L_0              (DVFSRC_BASE + 0xBF0)
+#define DVFSRC_RECORD_0_L_1              (DVFSRC_BASE + 0xBF4)
+#define DVFSRC_RECORD_0_L_2              (DVFSRC_BASE + 0xBF8)
+#define DVFSRC_RECORD_0_L_3              (DVFSRC_BASE + 0xBFC)
+#define DVFSRC_RECORD_0_L_4              (DVFSRC_BASE + 0xC00)
+#define DVFSRC_RECORD_0_L_5              (DVFSRC_BASE + 0xC04)
+#define DVFSRC_RECORD_0_L_6              (DVFSRC_BASE + 0xC08)
+#define DVFSRC_RECORD_0_L_7              (DVFSRC_BASE + 0xC0C)
+#define DVFSRC_EMI_REQUEST8              (DVFSRC_BASE + 0xCF0)
+#define DVFSRC_DDR_REQUEST8              (DVFSRC_BASE + 0xCF4)
+#define DVFSRC_EMI_HRT_2                 (DVFSRC_BASE + 0xCF8)
+#define DVFSRC_EMI_HRT2_2                (DVFSRC_BASE + 0xCFC)
+#define DVFSRC_EMI_HRT3_2                (DVFSRC_BASE + 0xD00)
+#define DVFSRC_EMI_QOS5                  (DVFSRC_BASE + 0xD04)
+#define DVFSRC_EMI_QOS6                  (DVFSRC_BASE + 0xD08)
+#define DVFSRC_DDR_HRT_2                 (DVFSRC_BASE + 0xD0C)
+#define DVFSRC_DDR_HRT2_2                (DVFSRC_BASE + 0xD10)
+#define DVFSRC_DDR_HRT3_2                (DVFSRC_BASE + 0xD14)
+#define DVFSRC_DDR_QOS5                  (DVFSRC_BASE + 0xD18)
+#define DVFSRC_DDR_QOS6                  (DVFSRC_BASE + 0xD1C)
+#define DVFSRC_VCORE_REQUEST5            (DVFSRC_BASE + 0xD20)
+#define DVFSRC_VCORE_HRT_1               (DVFSRC_BASE + 0xD24)
+#define DVFSRC_VCORE_HRT2_1              (DVFSRC_BASE + 0xD28)
+#define DVFSRC_VCORE_HRT3_1              (DVFSRC_BASE + 0xD2C)
+#define DVFSRC_VCORE_QOS3                (DVFSRC_BASE + 0xD30)
+#define DVFSRC_VCORE_QOS4                (DVFSRC_BASE + 0xD34)
+#define DVFSRC_HRT_HIGH_3                (DVFSRC_BASE + 0xD38)
+#define DVFSRC_HRT_LOW_3                 (DVFSRC_BASE + 0xD3C)
+#define DVFSRC_BASIC_CONTROL_2           (DVFSRC_BASE + 0xD40)
+#define DVFSRC_CURRENT_LEVEL             (DVFSRC_BASE + 0xD44)
+#define DVFSRC_TARGET_LEVEL              (DVFSRC_BASE + 0xD48)
+#define DVFSRC_LEVEL_LABEL_16_17         (DVFSRC_BASE + 0xD4C)
+#define DVFSRC_LEVEL_LABEL_18_19         (DVFSRC_BASE + 0xD50)
+#define DVFSRC_LEVEL_LABEL_20_21         (DVFSRC_BASE + 0xD54)
+#define DVFSRC_LEVEL_LABEL_22_23         (DVFSRC_BASE + 0xD58)
+#define DVFSRC_LEVEL_LABEL_24_25         (DVFSRC_BASE + 0xD5C)
+#define DVFSRC_LEVEL_LABEL_26_27         (DVFSRC_BASE + 0xD60)
+#define DVFSRC_LEVEL_LABEL_28_29         (DVFSRC_BASE + 0xD64)
+#define DVFSRC_LEVEL_LABEL_30_31         (DVFSRC_BASE + 0xD68)
+#define DVFSRC_CURRENT_FORCE             (DVFSRC_BASE + 0xD6C)
+#define DVFSRC_TARGET_FORCE              (DVFSRC_BASE + 0xD70)
+#define DVFSRC_EMI_ADD_REQUEST           (DVFSRC_BASE + 0xD74)
+
+#endif /* __MT_SPM_VCOREFS__H__ */
diff --git a/plat/mediatek/mt8195/include/plat_sip_calls.h b/plat/mediatek/mt8195/include/plat_sip_calls.h
index 181aec0..ce25c6f 100644
--- a/plat/mediatek/mt8195/include/plat_sip_calls.h
+++ b/plat/mediatek/mt8195/include/plat_sip_calls.h
@@ -10,7 +10,11 @@
 /*******************************************************************************
  * Plat SiP function constants
  ******************************************************************************/
-#define MTK_PLAT_SIP_NUM_CALLS    2
+#define MTK_PLAT_SIP_NUM_CALLS    4
+
+/* DFD */
+#define MTK_SIP_KERNEL_DFD_AARCH32	0x82000205
+#define MTK_SIP_KERNEL_DFD_AARCH64	0xC2000205
 
 /* DP/eDP */
 #define MTK_SIP_DP_CONTROL_AARCH32	0x82000523
diff --git a/plat/mediatek/mt8195/include/platform_def.h b/plat/mediatek/mt8195/include/platform_def.h
index b84e73f..68301d6 100644
--- a/plat/mediatek/mt8195/include/platform_def.h
+++ b/plat/mediatek/mt8195/include/platform_def.h
@@ -24,13 +24,16 @@
 #define TOPCKGEN_BASE           (IO_PHYS + 0x00000000)
 #define INFRACFG_AO_BASE        (IO_PHYS + 0x00001000)
 #define SPM_BASE		(IO_PHYS + 0x00006000)
+#define RGU_BASE		(IO_PHYS + 0x00007000)
 #define APMIXEDSYS              (IO_PHYS + 0x0000C000)
+#define DRM_BASE		(IO_PHYS + 0x0000D000)
 #define SSPM_MBOX_BASE          (IO_PHYS + 0x00480000)
 #define PERICFG_AO_BASE         (IO_PHYS + 0x01003000)
 #define VPPSYS0_BASE            (IO_PHYS + 0x04000000)
 #define VPPSYS1_BASE            (IO_PHYS + 0x04f00000)
 #define VDOSYS0_BASE            (IO_PHYS + 0x0C01A000)
 #define VDOSYS1_BASE            (IO_PHYS + 0x0C100000)
+#define DVFSRC_BASE             (IO_PHYS + 0x00012000)
 
 /*******************************************************************************
  * DP/eDP related constants
@@ -65,6 +68,12 @@
 #define PMIC_WRAP_BASE			(IO_PHYS + 0x00024000)
 
 /*******************************************************************************
+ * EMI MPU related constants
+ ******************************************************************************/
+#define EMI_MPU_BASE		(IO_PHYS + 0x00226000)
+#define SUB_EMI_MPU_BASE	(IO_PHYS + 0x00225000)
+
+/*******************************************************************************
  * System counter frequency related constants
  ******************************************************************************/
 #define SYS_COUNTER_FREQ_IN_TICKS	13000000
diff --git a/plat/mediatek/mt8195/plat_pm.c b/plat/mediatek/mt8195/plat_pm.c
index 2beeb02..b77ab27 100644
--- a/plat/mediatek/mt8195/plat_pm.c
+++ b/plat/mediatek/mt8195/plat_pm.c
@@ -17,6 +17,7 @@
 #include <mtk_ptp3_common.h>
 #include <mtspmc.h>
 #include <plat/common/platform.h>
+#include <plat_dfd.h>
 #include <plat_mtk_lpm.h>
 #include <plat_params.h>
 #include <plat_pm.h>
@@ -166,6 +167,8 @@
 	mt_gic_distif_restore();
 	gic_sgi_restore_all();
 
+	dfd_resume();
+
 	plat_mt_pm_invoke_no_check(pwr_mcusys_on_finished, cpu, state);
 }
 
diff --git a/plat/mediatek/mt8195/plat_sip_calls.c b/plat/mediatek/mt8195/plat_sip_calls.c
index 99e1eb3..ddc7502 100644
--- a/plat/mediatek/mt8195/plat_sip_calls.c
+++ b/plat/mediatek/mt8195/plat_sip_calls.c
@@ -7,7 +7,10 @@
 #include <common/debug.h>
 #include <common/runtime_svc.h>
 #include <mt_dp.h>
+#include <mt_spm.h>
+#include <mt_spm_vcorefs.h>
 #include <mtk_sip_svc.h>
+#include <plat_dfd.h>
 #include "plat_sip_calls.h"
 
 uintptr_t mediatek_plat_sip_handler(uint32_t smc_fid,
@@ -28,6 +31,16 @@
 		ret = dp_secure_handler(x1, x2, &ret_val);
 		SMC_RET2(handle, ret, ret_val);
 		break;
+	case MTK_SIP_VCORE_CONTROL_ARCH32:
+	case MTK_SIP_VCORE_CONTROL_ARCH64:
+		ret = spm_vcorefs_v2_args(x1, x2, x3, &x4);
+		SMC_RET2(handle, ret, x4);
+		break;
+	case MTK_SIP_KERNEL_DFD_AARCH32:
+	case MTK_SIP_KERNEL_DFD_AARCH64:
+		ret = dfd_smc_dispatcher(x1, x2, x3, x4);
+		SMC_RET1(handle, ret);
+		break;
 	default:
 		ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
 		break;
diff --git a/plat/mediatek/mt8195/platform.mk b/plat/mediatek/mt8195/platform.mk
index 481e9ad..ef7ff81 100644
--- a/plat/mediatek/mt8195/platform.mk
+++ b/plat/mediatek/mt8195/platform.mk
@@ -14,7 +14,10 @@
                  -I${MTK_PLAT}/common/drivers/timer/              \
                  -I${MTK_PLAT}/common/drivers/uart/               \
                  -I${MTK_PLAT}/common/lpm/                        \
-                 -I${MTK_PLAT_SOC}/drivers/dp/                  \
+                 -I${MTK_PLAT_SOC}/drivers/dcm                    \
+                 -I${MTK_PLAT_SOC}/drivers/dfd                    \
+                 -I${MTK_PLAT_SOC}/drivers/dp/                    \
+                 -I${MTK_PLAT_SOC}/drivers/emi_mpu/               \
                  -I${MTK_PLAT_SOC}/drivers/gpio/                  \
                  -I${MTK_PLAT_SOC}/drivers/mcdi/                  \
                  -I${MTK_PLAT_SOC}/drivers/pmic/                  \
@@ -56,7 +59,11 @@
                 ${MTK_PLAT_SOC}/aarch64/platform_common.c             \
                 ${MTK_PLAT_SOC}/aarch64/plat_helpers.S                \
                 ${MTK_PLAT_SOC}/bl31_plat_setup.c                     \
+                ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c                 \
+                ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c           \
+                ${MTK_PLAT_SOC}/drivers/dfd/plat_dfd.c                \
                 ${MTK_PLAT_SOC}/drivers/dp/mt_dp.c                    \
+                ${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c             \
                 ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c                 \
                 ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm.c              \
                 ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm_cpc.c          \
diff --git a/plat/nvidia/tegra/common/tegra_platform.c b/plat/nvidia/tegra/common/tegra_platform.c
index 3894b74..f3aa3ea 100644
--- a/plat/nvidia/tegra/common/tegra_platform.c
+++ b/plat/nvidia/tegra/common/tegra_platform.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -82,13 +82,6 @@
 	return (tegra_get_chipid() >> PRE_SI_PLATFORM_SHIFT) & PRE_SI_PLATFORM_MASK;
 }
 
-bool tegra_chipid_is_t132(void)
-{
-	uint32_t chip_id = ((tegra_get_chipid() >> CHIP_ID_SHIFT) & CHIP_ID_MASK);
-
-	return (chip_id == TEGRA_CHIPID_TEGRA13);
-}
-
 bool tegra_chipid_is_t186(void)
 {
 	uint32_t chip_id = (tegra_get_chipid() >> CHIP_ID_SHIFT) & CHIP_ID_MASK;
diff --git a/plat/nvidia/tegra/include/t132/tegra_def.h b/plat/nvidia/tegra/include/t132/tegra_def.h
deleted file mode 100644
index 6b87655..0000000
--- a/plat/nvidia/tegra/include/t132/tegra_def.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef TEGRA_DEF_H
-#define TEGRA_DEF_H
-
-#include <lib/utils_def.h>
-
-/*******************************************************************************
- * Platform BL31 specific defines.
- ******************************************************************************/
-#define BL31_SIZE			U(0x40000)
-
-/*******************************************************************************
- * This value is used by the PSCI implementation during the `SYSTEM_SUSPEND`
- * call as the `state-id` field in the 'power state' parameter.
- ******************************************************************************/
-#define PSTATE_ID_SOC_POWERDN	U(0xD)
-
-/*******************************************************************************
- * Platform power states (used by PSCI framework)
- *
- * - PLAT_MAX_RET_STATE should be less than lowest PSTATE_ID
- * - PLAT_MAX_OFF_STATE should be greater than the highest PSTATE_ID
- ******************************************************************************/
-#define PLAT_MAX_RET_STATE		U(1)
-#define PLAT_MAX_OFF_STATE		(PSTATE_ID_SOC_POWERDN + U(1))
-
-/*******************************************************************************
- * Chip specific page table and MMU setup constants
- ******************************************************************************/
-#define PLAT_PHY_ADDR_SPACE_SIZE	(ULL(1) << 35)
-#define PLAT_VIRT_ADDR_SPACE_SIZE	(ULL(1) << 35)
-
-/*******************************************************************************
- * GIC memory map
- ******************************************************************************/
-#define TEGRA_GICD_BASE			U(0x50041000)
-#define TEGRA_GICC_BASE			U(0x50042000)
-
-/*******************************************************************************
- * Tegra micro-seconds timer constants
- ******************************************************************************/
-#define TEGRA_TMRUS_BASE		U(0x60005010)
-#define TEGRA_TMRUS_SIZE		U(0x1000)
-
-/*******************************************************************************
- * Tegra Clock and Reset Controller constants
- ******************************************************************************/
-#define TEGRA_CAR_RESET_BASE		U(0x60006000)
-#define TEGRA_GPU_RESET_REG_OFFSET	U(0x28C)
-#define TEGRA_GPU_RESET_GPU_SET_OFFSET	U(0x290)
-#define  GPU_RESET_BIT			(U(1) << 24)
-#define  GPU_SET_BIT			(U(1) << 24)
-
-/*******************************************************************************
- * Tegra Flow Controller constants
- ******************************************************************************/
-#define TEGRA_FLOWCTRL_BASE		U(0x60007000)
-
-/*******************************************************************************
- * Tegra Secure Boot Controller constants
- ******************************************************************************/
-#define TEGRA_SB_BASE			U(0x6000C200)
-
-/*******************************************************************************
- * Tegra Exception Vectors constants
- ******************************************************************************/
-#define TEGRA_EVP_BASE			U(0x6000F000)
-
-/*******************************************************************************
- * Tegra Miscellaneous register constants
- ******************************************************************************/
-#define TEGRA_MISC_BASE			U(0x70000000)
-#define  HARDWARE_REVISION_OFFSET	U(0x804)
-
-/*******************************************************************************
- * Tegra UART controller base addresses
- ******************************************************************************/
-#define TEGRA_UARTA_BASE		U(0x70006000)
-#define TEGRA_UARTB_BASE		U(0x70006040)
-#define TEGRA_UARTC_BASE		U(0x70006200)
-#define TEGRA_UARTD_BASE		U(0x70006300)
-#define TEGRA_UARTE_BASE		U(0x70006400)
-
-/*******************************************************************************
- * Tegra Power Mgmt Controller constants
- ******************************************************************************/
-#define TEGRA_PMC_BASE			U(0x7000E400)
-
-/*******************************************************************************
- * Tegra Memory Controller constants
- ******************************************************************************/
-#define TEGRA_MC_BASE			U(0x70019000)
-
-/* Memory Controller Interrupt Status */
-#define MC_INTSTATUS			0x00U
-
-/* TZDRAM carveout configuration registers */
-#define MC_SECURITY_CFG0_0		U(0x70)
-#define MC_SECURITY_CFG1_0		U(0x74)
-#define MC_SECURITY_CFG3_0		U(0x9BC)
-
-/* Video Memory carveout configuration registers */
-#define MC_VIDEO_PROTECT_BASE_HI	U(0x978)
-#define MC_VIDEO_PROTECT_BASE_LO	U(0x648)
-#define MC_VIDEO_PROTECT_SIZE_MB	U(0x64c)
-#define MC_VIDEO_PROTECT_REG_CTRL	U(0x650)
-#define MC_VIDEO_PROTECT_WRITE_ACCESS_ENABLED	U(3)
-
-/*******************************************************************************
- * Tegra TZRAM constants
- ******************************************************************************/
-#define TEGRA_TZRAM_BASE		U(0x7C010000)
-#define TEGRA_TZRAM_SIZE		U(0x10000)
-
-/*******************************************************************************
- * Tegra DRAM memory base address
- ******************************************************************************/
-#define TEGRA_DRAM_BASE			ULL(0x80000000)
-#define TEGRA_DRAM_END			ULL(0x27FFFFFFF)
-
-#endif /* TEGRA_DEF_H */
diff --git a/plat/nvidia/tegra/include/tegra_platform.h b/plat/nvidia/tegra/include/tegra_platform.h
index b8297fd..ab51dfe 100644
--- a/plat/nvidia/tegra/include/tegra_platform.h
+++ b/plat/nvidia/tegra/include/tegra_platform.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -49,7 +49,6 @@
 /*
  * Tegra chip ID identifiers
  */
-bool tegra_chipid_is_t132(void);
 bool tegra_chipid_is_t186(void);
 bool tegra_chipid_is_t210(void);
 bool tegra_chipid_is_t210_b01(void);
diff --git a/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c
deleted file mode 100644
index 0e2edf0..0000000
--- a/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-
-#include <platform_def.h>
-
-#include <arch.h>
-#include <arch_helpers.h>
-#include <common/debug.h>
-#include <drivers/delay_timer.h>
-#include <denver.h>
-#include <lib/mmio.h>
-#include <lib/psci/psci.h>
-
-#include <flowctrl.h>
-#include <pmc.h>
-#include <tegra_def.h>
-#include <tegra_private.h>
-
-/*
- * Register used to clear CPU reset signals. Each CPU has two reset
- * signals: CPU reset (3:0) and Core reset (19:16)
- */
-#define CPU_CMPLX_RESET_CLR		0x344
-#define CPU_CORE_RESET_MASK		0x10001
-
-/* Clock and Reset controller registers for system clock's settings */
-#define SCLK_RATE			0x30
-#define SCLK_BURST_POLICY		0x28
-#define SCLK_BURST_POLICY_DEFAULT	0x10000000
-
-static int cpu_powergate_mask[PLATFORM_MAX_CPUS_PER_CLUSTER];
-
-plat_local_state_t tegra_soc_get_target_pwr_state(uint32_t lvl,
-					     const plat_local_state_t *states,
-					     uint32_t ncpu)
-{
-	plat_local_state_t target = PLAT_MAX_OFF_STATE, temp;
-	uint32_t num_cpu = ncpu;
-	const plat_local_state_t *local_state = states;
-
-	(void)lvl;
-
-	assert(ncpu != 0U);
-
-	do {
-		temp = *local_state;
-		if ((temp < target)) {
-			target = temp;
-		}
-		--num_cpu;
-		local_state++;
-	} while (num_cpu != 0U);
-
-	return target;
-}
-
-int32_t tegra_soc_validate_power_state(unsigned int power_state,
-					psci_power_state_t *req_state)
-{
-	int state_id = psci_get_pstate_id(power_state);
-	int cpu = read_mpidr() & MPIDR_CPU_MASK;
-
-	/*
-	 * Sanity check the requested state id, power level and CPU number.
-	 * Currently T132 only supports SYSTEM_SUSPEND on last standing CPU
-	 * i.e. CPU 0
-	 */
-	if ((state_id != PSTATE_ID_SOC_POWERDN) || (cpu != 0)) {
-		ERROR("unsupported state id @ power level\n");
-		return PSCI_E_INVALID_PARAMS;
-	}
-
-	/* Set lower power states to PLAT_MAX_OFF_STATE */
-	for (uint32_t i = MPIDR_AFFLVL0; i < PLAT_MAX_PWR_LVL; i++)
-		req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
-
-	/* Set the SYSTEM_SUSPEND state-id */
-	req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] =
-		PSTATE_ID_SOC_POWERDN;
-
-	return PSCI_E_SUCCESS;
-}
-
-int tegra_soc_pwr_domain_on(u_register_t mpidr)
-{
-	int cpu = mpidr & MPIDR_CPU_MASK;
-	uint32_t mask = CPU_CORE_RESET_MASK << cpu;
-
-	if (cpu_powergate_mask[cpu] == 0) {
-
-		/* Deassert CPU reset signals */
-		mmio_write_32(TEGRA_CAR_RESET_BASE + CPU_CMPLX_RESET_CLR, mask);
-
-		/* Power on CPU using PMC */
-		tegra_pmc_cpu_on(cpu);
-
-		/* Fill in the CPU powergate mask */
-		cpu_powergate_mask[cpu] = 1;
-
-	} else {
-		/* Power on CPU using Flow Controller */
-		tegra_fc_cpu_on(cpu);
-	}
-
-	return PSCI_E_SUCCESS;
-}
-
-int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
-{
-	/*
-	 * Lock scratch registers which hold the CPU vectors
-	 */
-	tegra_pmc_lock_cpu_vectors();
-
-	return PSCI_E_SUCCESS;
-}
-
-int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
-{
-	uint64_t val;
-
-	tegra_fc_cpu_off(read_mpidr() & MPIDR_CPU_MASK);
-
-	/* Disable DCO operations */
-	denver_disable_dco();
-
-	/* Power down the CPU */
-	val = read_actlr_el1() & ~ACTLR_EL1_PMSTATE_MASK;
-	write_actlr_el1(val | DENVER_CPU_STATE_POWER_DOWN);
-
-	return PSCI_E_SUCCESS;
-}
-
-int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state)
-{
-	(void)cpu_state;
-	return PSCI_E_SUCCESS;
-}
-
-int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
-{
-	uint64_t val;
-
-#if ENABLE_ASSERTIONS
-	int cpu = read_mpidr() & MPIDR_CPU_MASK;
-
-	/* SYSTEM_SUSPEND only on CPU0 */
-	assert(cpu == 0);
-#endif
-
-	/* Allow restarting CPU #1 using PMC on suspend exit */
-	cpu_powergate_mask[1] = 0;
-
-	/* Program FC to enter suspend state */
-	tegra_fc_cpu_powerdn(read_mpidr());
-
-	/* Disable DCO operations */
-	denver_disable_dco();
-
-	/* Program the suspend state ID */
-	val = read_actlr_el1() & ~ACTLR_EL1_PMSTATE_MASK;
-	write_actlr_el1(val | target_state->pwr_domain_state[PLAT_MAX_PWR_LVL]);
-
-	return PSCI_E_SUCCESS;
-}
-
-int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state)
-{
-	return PSCI_E_NOT_SUPPORTED;
-}
-
-int tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)
-{
-	return PSCI_E_SUCCESS;
-}
-
-int tegra_soc_prepare_system_reset(void)
-{
-	/*
-	 * Set System Clock (SCLK) to POR default so that the clock source
-	 * for the PMC APB clock would not be changed due to system reset.
-	 */
-	mmio_write_32((uintptr_t)TEGRA_CAR_RESET_BASE + SCLK_BURST_POLICY,
-		       SCLK_BURST_POLICY_DEFAULT);
-	mmio_write_32((uintptr_t)TEGRA_CAR_RESET_BASE + SCLK_RATE, 0);
-
-	/* Wait 1 ms to make sure clock source/device logic is stabilized. */
-	mdelay(1);
-
-	/*
-	 * Program the PMC in order to restart the system.
-	 */
-	tegra_pmc_system_reset();
-
-	return PSCI_E_SUCCESS;
-}
-
-__dead2 void tegra_soc_prepare_system_off(void)
-{
-	ERROR("Tegra System Off: operation not handled.\n");
-	panic();
-}
diff --git a/plat/nvidia/tegra/soc/t132/plat_secondary.c b/plat/nvidia/tegra/soc/t132/plat_secondary.c
deleted file mode 100644
index f46ad3b..0000000
--- a/plat/nvidia/tegra/soc/t132/plat_secondary.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-
-#include <arch_helpers.h>
-#include <common/debug.h>
-#include <denver.h>
-#include <lib/mmio.h>
-#include <lib/psci/psci.h>
-#include <plat/common/platform.h>
-
-#include <pmc.h>
-#include <tegra_def.h>
-
-#define SB_CSR				0x0
-#define  SB_CSR_NS_RST_VEC_WR_DIS	(1 << 1)
-
-/* AARCH64 CPU reset vector */
-#define SB_AA64_RESET_LOW		0x30	/* width = 31:0 */
-#define SB_AA64_RESET_HI		0x34	/* width = 11:0 */
-
-/* AARCH32 CPU reset vector */
-#define EVP_CPU_RESET_VECTOR		0x100
-
-extern void tegra_secure_entrypoint(void);
-
-/*
- * For T132, CPUs reset to AARCH32, so the reset vector is first
- * armv8_trampoline which does a warm reset to AARCH64 and starts
- * execution at the address in SB_AA64_RESET_LOW/SB_AA64_RESET_HI.
- */
-__aligned(8) const uint32_t armv8_trampoline[] = {
-	0xE3A00003,		/* mov	r0, #3 */
-	0xEE0C0F50,		/* mcr	p15, 0, r0, c12, c0, 2 */
-	0xEAFFFFFE,		/* b	. */
-};
-
-/*******************************************************************************
- * Setup secondary CPU vectors
- ******************************************************************************/
-void plat_secondary_setup(void)
-{
-	uint32_t val;
-	uint64_t reset_addr = (uint64_t)tegra_secure_entrypoint;
-
-	/*
-	 * For T132, CPUs reset to AARCH32, so the reset vector is first
-	 * armv8_trampoline, which does a warm reset to AARCH64 and starts
-	 * execution at the address in SCRATCH34/SCRATCH35.
-	 */
-	INFO("Setting up T132 CPU boot\n");
-
-	/* initial AARCH32 reset address */
-	tegra_pmc_write_32(PMC_SECURE_SCRATCH22,
-		(unsigned long)&armv8_trampoline);
-
-	/* set AARCH32 exception vector (read to flush) */
-	mmio_write_32(TEGRA_EVP_BASE + EVP_CPU_RESET_VECTOR,
-		(unsigned long)&armv8_trampoline);
-	val = mmio_read_32(TEGRA_EVP_BASE + EVP_CPU_RESET_VECTOR);
-
-	/* setup secondary CPU vector */
-	mmio_write_32(TEGRA_SB_BASE + SB_AA64_RESET_LOW,
-			(reset_addr & 0xFFFFFFFF) | 1);
-	val = reset_addr >> 32;
-	mmio_write_32(TEGRA_SB_BASE + SB_AA64_RESET_HI, val & 0x7FF);
-
-	/* configure PMC */
-	tegra_pmc_cpu_setup(reset_addr);
-	tegra_pmc_lock_cpu_vectors();
-}
diff --git a/plat/nvidia/tegra/soc/t132/plat_setup.c b/plat/nvidia/tegra/soc/t132/plat_setup.c
deleted file mode 100644
index 49e8b5d..0000000
--- a/plat/nvidia/tegra/soc/t132/plat_setup.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <arch_helpers.h>
-#include <assert.h>
-#include <common/bl_common.h>
-#include <drivers/console.h>
-#include <lib/xlat_tables/xlat_tables_v2.h>
-#include <memctrl.h>
-#include <plat/common/platform.h>
-#include <tegra_def.h>
-#include <tegra_platform.h>
-#include <tegra_private.h>
-
-/* sets of MMIO ranges setup */
-#define MMIO_RANGE_0_ADDR	0x50000000
-#define MMIO_RANGE_1_ADDR	0x60000000
-#define MMIO_RANGE_2_ADDR	0x70000000
-#define MMIO_RANGE_SIZE		0x200000
-
-/*
- * Table of regions to map using the MMU.
- */
-static const mmap_region_t tegra_mmap[] = {
-	MAP_REGION_FLAT(MMIO_RANGE_0_ADDR, MMIO_RANGE_SIZE,
-			MT_DEVICE | MT_RW | MT_SECURE),
-	MAP_REGION_FLAT(MMIO_RANGE_1_ADDR, MMIO_RANGE_SIZE,
-			MT_DEVICE | MT_RW | MT_SECURE),
-	MAP_REGION_FLAT(MMIO_RANGE_2_ADDR, MMIO_RANGE_SIZE,
-			MT_DEVICE | MT_RW | MT_SECURE),
-	{0}
-};
-
-/*******************************************************************************
- * Set up the pagetables as per the platform memory map & initialize the MMU
- ******************************************************************************/
-const mmap_region_t *plat_get_mmio_map(void)
-{
-	/* MMIO space */
-	return tegra_mmap;
-}
-
-/*******************************************************************************
- * The Tegra power domain tree has a single system level power domain i.e. a
- * single root node. The first entry in the power domain descriptor specifies
- * the number of power domains at the highest power level.
- *******************************************************************************
- */
-const unsigned char tegra_power_domain_tree_desc[] = {
-	/* No of root nodes */
-	1,
-	/* No of clusters */
-	PLATFORM_CLUSTER_COUNT,
-	/* No of CPU cores */
-	PLATFORM_CORE_COUNT,
-};
-
-/*******************************************************************************
- * This function returns the Tegra default topology tree information.
- ******************************************************************************/
-const unsigned char *plat_get_power_domain_tree_desc(void)
-{
-	return tegra_power_domain_tree_desc;
-}
-
-unsigned int plat_get_syscnt_freq2(void)
-{
-	return 12000000;
-}
-
-/*******************************************************************************
- * Maximum supported UART controllers
- ******************************************************************************/
-#define TEGRA132_MAX_UART_PORTS		5
-
-/*******************************************************************************
- * This variable holds the UART port base addresses
- ******************************************************************************/
-static uint32_t tegra132_uart_addresses[TEGRA132_MAX_UART_PORTS + 1] = {
-	0,	/* undefined - treated as an error case */
-	TEGRA_UARTA_BASE,
-	TEGRA_UARTB_BASE,
-	TEGRA_UARTC_BASE,
-	TEGRA_UARTD_BASE,
-	TEGRA_UARTE_BASE,
-};
-
-/*******************************************************************************
- * Enable console corresponding to the console ID
- ******************************************************************************/
-void plat_enable_console(int32_t id)
-{
-	static console_t uart_console;
-	uint32_t console_clock;
-
-	if ((id > 0) && (id < TEGRA132_MAX_UART_PORTS)) {
-		/*
-		 * Reference clock used by the FPGAs is a lot slower.
-		 */
-		if (tegra_platform_is_fpga()) {
-			console_clock = TEGRA_BOOT_UART_CLK_13_MHZ;
-		} else {
-			console_clock = TEGRA_BOOT_UART_CLK_408_MHZ;
-		}
-
-		(void)console_16550_register(tegra132_uart_addresses[id],
-					     console_clock,
-					     TEGRA_CONSOLE_BAUDRATE,
-					     &uart_console);
-		console_set_scope(&uart_console, CONSOLE_FLAG_BOOT |
-			CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
-	}
-}
-
-/*******************************************************************************
- * Initialize the GIC and SGIs
- ******************************************************************************/
-void plat_gic_setup(void)
-{
-	tegra_gic_setup(NULL, 0);
-	tegra_gic_init();
-}
-
-/*******************************************************************************
- * Return pointer to the BL31 params from previous bootloader
- ******************************************************************************/
-struct tegra_bl31_params *plat_get_bl31_params(void)
-{
-	return NULL;
-}
-
-/*******************************************************************************
- * Return pointer to the BL31 platform params from previous bootloader
- ******************************************************************************/
-plat_params_from_bl2_t *plat_get_bl31_plat_params(void)
-{
-	return NULL;
-}
-
-/*******************************************************************************
- * Handler for early platform setup
- ******************************************************************************/
-void plat_early_platform_setup(void)
-{
-	plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
-
-	/* Verify chip id is t132 */
-	assert(tegra_chipid_is_t132());
-
-	/*
-	 * Do initial security configuration to allow DRAM/device access.
-	 */
-	tegra_memctrl_tzdram_setup(plat_params->tzdram_base,
-			(uint32_t)plat_params->tzdram_size);
-}
-
-/*******************************************************************************
- * Handler for late platform setup
- ******************************************************************************/
-void plat_late_platform_setup(void)
-{
-	; /* do nothing */
-}
-
-/*******************************************************************************
- * Handler to indicate support for System Suspend
- ******************************************************************************/
-bool plat_supports_system_suspend(void)
-{
-	return true;
-}
-
-/*******************************************************************************
- * Platform specific runtime setup.
- ******************************************************************************/
-void plat_runtime_setup(void)
-{
-	/*
-	 * During cold boot, it is observed that the arbitration
-	 * bit is set in the Memory controller leading to false
-	 * error interrupts in the non-secure world. To avoid
-	 * this, clean the interrupt status register before
-	 * booting into the non-secure world
-	 */
-	tegra_memctrl_clear_pending_interrupts();
-
-	/*
-	 * During boot, USB3 and flash media (SDMMC/SATA) devices need
-	 * access to IRAM. Because these clients connect to the MC and
-	 * do not have a direct path to the IRAM, the MC implements AHB
-	 * redirection during boot to allow path to IRAM. In this mode
-	 * accesses to a programmed memory address aperture are directed
-	 * to the AHB bus, allowing access to the IRAM. This mode must be
-	 * disabled before we jump to the non-secure world.
-	 */
-	tegra_memctrl_disable_ahb_redirection();
-}
diff --git a/plat/nvidia/tegra/soc/t132/plat_sip_calls.c b/plat/nvidia/tegra/soc/t132/plat_sip_calls.c
deleted file mode 100644
index 90c6bb2..0000000
--- a/plat/nvidia/tegra/soc/t132/plat_sip_calls.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-#include <errno.h>
-
-#include <arch.h>
-#include <arch_helpers.h>
-#include <common/bl_common.h>
-#include <common/debug.h>
-#include <lib/el3_runtime/context_mgmt.h>
-
-#include <tegra_private.h>
-
-#define NS_SWITCH_AARCH32	1
-#define SCR_RW_BITPOS		__builtin_ctz(SCR_RW_BIT)
-
-/*******************************************************************************
- * Tegra132 SiP SMCs
- ******************************************************************************/
-#define TEGRA_SIP_AARCH_SWITCH			0x82000004
-
-/*******************************************************************************
- * SPSR settings for AARCH32/AARCH64 modes
- ******************************************************************************/
-#define SPSR32		SPSR_MODE32(MODE32_svc, SPSR_T_ARM, SPSR_E_LITTLE, \
-			DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT)
-#define SPSR64		SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS)
-
-/*******************************************************************************
- * This function is responsible for handling all T132 SiP calls
- ******************************************************************************/
-int plat_sip_handler(uint32_t smc_fid,
-		     uint64_t x1,
-		     uint64_t x2,
-		     uint64_t x3,
-		     uint64_t x4,
-		     const void *cookie,
-		     void *handle,
-		     uint64_t flags)
-{
-	switch (smc_fid) {
-
-	case TEGRA_SIP_AARCH_SWITCH:
-
-		/* clean up the high bits */
-		x1 = (uint32_t)x1;
-		x2 = (uint32_t)x2;
-
-		if (!x1 || x2 > NS_SWITCH_AARCH32) {
-			ERROR("%s: invalid parameters\n", __func__);
-			return -EINVAL;
-		}
-
-		/* x1 = ns entry point */
-		cm_set_elr_spsr_el3(NON_SECURE, x1,
-			(x2 == NS_SWITCH_AARCH32) ? SPSR32 : SPSR64);
-
-		/* switch NS world mode */
-		cm_write_scr_el3_bit(NON_SECURE, SCR_RW_BITPOS, !x2);
-
-		INFO("CPU switched to AARCH%s mode\n",
-			(x2 == NS_SWITCH_AARCH32) ? "32" : "64");
-		return 0;
-
-	default:
-		ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
-		break;
-	}
-
-	return -ENOTSUP;
-}
diff --git a/plat/nvidia/tegra/soc/t132/platform_t132.mk b/plat/nvidia/tegra/soc/t132/platform_t132.mk
deleted file mode 100644
index 9534c07..0000000
--- a/plat/nvidia/tegra/soc/t132/platform_t132.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
-# Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-TZDRAM_BASE			:= 0xF5C00000
-$(eval $(call add_define,TZDRAM_BASE))
-
-PLATFORM_CLUSTER_COUNT		:= 1
-$(eval $(call add_define,PLATFORM_CLUSTER_COUNT))
-
-PLATFORM_MAX_CPUS_PER_CLUSTER	:= 2
-$(eval $(call add_define,PLATFORM_MAX_CPUS_PER_CLUSTER))
-
-MAX_XLAT_TABLES			:= 3
-$(eval $(call add_define,MAX_XLAT_TABLES))
-
-MAX_MMAP_REGIONS		:= 8
-$(eval $(call add_define,MAX_MMAP_REGIONS))
-
-# platform files
-PLAT_INCLUDES		+=	-Iplat/nvidia/tegra/include/t132
-
-BL31_SOURCES		+=	${TEGRA_GICv2_SOURCES}			\
-				drivers/ti/uart/aarch64/16550_console.S	\
-				lib/cpus/aarch64/denver.S		\
-				${TEGRA_DRIVERS}/flowctrl/flowctrl.c	\
-				${TEGRA_DRIVERS}/memctrl/memctrl_v1.c	\
-				${TEGRA_DRIVERS}/pmc/pmc.c		\
-				${SOC_DIR}/plat_psci_handlers.c		\
-				${SOC_DIR}/plat_sip_calls.c		\
-				${SOC_DIR}/plat_setup.c			\
-				${SOC_DIR}/plat_secondary.c
diff --git a/plat/nvidia/tegra/soc/t194/plat_ras.c b/plat/nvidia/tegra/soc/t194/plat_ras.c
index 0c4c6fa..a322403 100644
--- a/plat/nvidia/tegra/soc/t194/plat_ras.c
+++ b/plat/nvidia/tegra/soc/t194/plat_ras.c
@@ -493,9 +493,6 @@
 #if RAS_EXTENSION
 	tegra194_ea_handler(ea_reason, syndrome, cookie, handle, flags);
 #else
-	ERROR("Unhandled External Abort received on 0x%llx at EL3!\n",
-			read_mpidr_el1());
-	ERROR(" exception reason=%u syndrome=0x%lx\n", ea_reason, syndrome);
-	panic();
+	plat_default_ea_handler(ea_reason, syndrome, cookie, handle, flags);
 #endif
 }
diff --git a/plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h b/plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h
index 08300b0..0a4228b 100644
--- a/plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h
+++ b/plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h
@@ -23,6 +23,9 @@
 /* MMU 500 soc.c*/
 #define NXP_SMMU_ADDR			0x05000000
 
+/* CCI400 base address */
+#define NXP_CCI_ADDR			0x04090000
+
 #define NXP_SNVS_ADDR			0x01E90000
 
 #define NXP_DCFG_ADDR			0x01E00000
@@ -81,4 +84,5 @@
 #define NXP_CCN_HNI_ADDR		0x04080000
 #define NXP_CCN_HN_F_0_ADDR		0x04200000
 
+#define NXP_EPU_ADDR			0x700060000
 #endif	/*	SOC_DEFAULT_BASE_ADDR_H		*/
diff --git a/plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h b/plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h
index cdc823a..8de516e 100644
--- a/plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h
+++ b/plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h
@@ -39,6 +39,10 @@
 
 #endif /* NXP_RESET_ADDR */
 
+/* secmon register offsets and bitfields */
+#define SECMON_HPCOMR_OFFSET	0x4
+#define SECMON_HPCOMR_NPSWAEN	0x80000000
+
 /* Secure-Register-File register offsets and bit masks */
 #ifdef NXP_RST_ADDR
 /* Register Offset */
diff --git a/plat/nxp/common/include/default/plat_default_def.h b/plat/nxp/common/include/default/plat_default_def.h
index dd5dfe0..43320bb 100644
--- a/plat/nxp/common/include/default/plat_default_def.h
+++ b/plat/nxp/common/include/default/plat_default_def.h
@@ -40,8 +40,12 @@
 #define NXP_NS_DRAM_ADDR	NXP_DRAM0_ADDR
 #endif
 
-/* 64M is reserved for Secure memory
- */
+/* 1 MB is reserved for dma of sd */
+#ifndef NXP_SD_BLOCK_BUF_SIZE
+#define NXP_SD_BLOCK_BUF_SIZE	(1 * 1024 * 1024)
+#endif
+
+/* 64MB is reserved for Secure memory */
 #ifndef NXP_SECURE_DRAM_SIZE
 #define NXP_SECURE_DRAM_SIZE	(64 * 1024 * 1024)
 #endif
@@ -57,18 +61,22 @@
 				(NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE))
 #endif
 
+#ifndef NXP_SD_BLOCK_BUF_ADDR
+#define NXP_SD_BLOCK_BUF_ADDR	(NXP_NS_DRAM_ADDR)
+#endif
+
 #ifndef NXP_SECURE_DRAM_ADDR
 #ifdef TEST_BL31
 #define NXP_SECURE_DRAM_ADDR 0
 #else
 #define NXP_SECURE_DRAM_ADDR	(NXP_NS_DRAM_ADDR + PLAT_DEF_DRAM0_SIZE - \
-				(NXP_SECURE_DRAM_SIZE  + NXP_SP_SHRD_DRAM_SIZE))
+				(NXP_SECURE_DRAM_SIZE + NXP_SP_SHRD_DRAM_SIZE))
 #endif
 #endif
 
 #ifndef NXP_SP_SHRD_DRAM_ADDR
-#define NXP_SP_SHRD_DRAM_ADDR	(NXP_NS_DRAM_ADDR + PLAT_DEF_DRAM0_SIZE \
-				- NXP_SP_SHRD_DRAM_SIZE)
+#define NXP_SP_SHRD_DRAM_ADDR	(NXP_NS_DRAM_ADDR + PLAT_DEF_DRAM0_SIZE - \
+				NXP_SP_SHRD_DRAM_SIZE)
 #endif
 
 #ifndef BL31_BASE
diff --git a/plat/nxp/common/psci/aarch64/psci_utils.S b/plat/nxp/common/psci/aarch64/psci_utils.S
index ea2abbf..ec69aea 100644
--- a/plat/nxp/common/psci/aarch64/psci_utils.S
+++ b/plat/nxp/common/psci/aarch64/psci_utils.S
@@ -1,6 +1,6 @@
 
 /*
- * Copyright 2018-2020 NXP
+ * Copyright 2018-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -234,7 +234,7 @@
 	msr DAIFSet, #0xF
 
 	/* read cpuectlr and save current value */
-	mrs   x4, CORTEX_A72_ECTLR_EL1
+	mrs   x4, CPUECTLR_EL1
 	mov   x1, #CPUECTLR_DATA
 	mov   x2, x4
 	mov   x0, x10
@@ -242,7 +242,7 @@
 
 	/* remove the core from coherency */
 	bic   x4, x4, #CPUECTLR_SMPEN_MASK
-	msr   CORTEX_A72_ECTLR_EL1, x4
+	msr   CPUECTLR_EL1, x4
 
 	/* save scr_el3 */
 	mov  x0, x10
@@ -339,7 +339,7 @@
 	mov   x1, #CPUECTLR_DATA
 	bl    _getCoreData
 	orr   x0, x0, #CPUECTLR_SMPEN_MASK
-	msr   CORTEX_A72_ECTLR_EL1, x0
+	msr   CPUECTLR_EL1, x0
 
 	/* x4 = core mask */
 
@@ -563,7 +563,7 @@
 	/* save cpuectlr */
 	mov  x0, x6
 	mov  x1, #CPUECTLR_DATA
-	mrs  x2, CORTEX_A72_ECTLR_EL1
+	mrs  x2, CPUECTLR_EL1
 	bl   _setCoreData
 
 	/* x6 = core mask */
@@ -640,7 +640,7 @@
 	bl   _getCoreData
 	/* make sure smp is set */
 	orr  x0, x0, #CPUECTLR_SMPEN_MASK
-	msr  CORTEX_A72_ECTLR_EL1, x0
+	msr  CPUECTLR_EL1, x0
 
 	/* x5 = core mask */
 
@@ -780,13 +780,13 @@
 	/* save cpuectlr */
 	mov  x0, x6
 	mov  x1, #CPUECTLR_DATA
-	mrs  x2, CORTEX_A72_ECTLR_EL1
+	mrs  x2, CPUECTLR_EL1
 	mov  x4, x2
 	bl   _setCoreData
 
 	/* remove core from coherency */
 	bic   x4, x4, #CPUECTLR_SMPEN_MASK
-	msr   CORTEX_A72_ECTLR_EL1, x4
+	msr   CPUECTLR_EL1, x4
 
 	/* x6 = core mask */
 
@@ -844,7 +844,7 @@
 	bl   _getCoreData
 	/* make sure smp is set */
 	orr  x0, x0, #CPUECTLR_SMPEN_MASK
-	msr  CORTEX_A72_ECTLR_EL1, x0
+	msr  CPUECTLR_EL1, x0
 
 	/* x4 = core mask */
 
@@ -985,13 +985,13 @@
 	/* save cpuectlr */
 	mov  x0, x6
 	mov  x1, #CPUECTLR_DATA
-	mrs  x2, CORTEX_A72_ECTLR_EL1
+	mrs  x2, CPUECTLR_EL1
 	mov  x4, x2
 	bl   _setCoreData
 
 	/* remove core from coherency */
 	bic   x4, x4, #CPUECTLR_SMPEN_MASK
-	msr   CORTEX_A72_ECTLR_EL1, x4
+	msr   CPUECTLR_EL1, x4
 
 	/* x6 = core mask */
 
@@ -1071,7 +1071,7 @@
 
 	/* make sure smp is set */
 	orr  x0, x0, #CPUECTLR_SMPEN_MASK
-	msr  CORTEX_A72_ECTLR_EL1, x0
+	msr  CPUECTLR_EL1, x0
 
 	/* x4 = core mask */
 
diff --git a/plat/nxp/common/psci/include/plat_psci.h b/plat/nxp/common/psci/include/plat_psci.h
index 97d4c97..7fc48fb 100644
--- a/plat/nxp/common/psci/include/plat_psci.h
+++ b/plat/nxp/common/psci/include/plat_psci.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2020 NXP
+ * Copyright 2018-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -7,6 +7,8 @@
 
 #ifndef PLAT_PSCI_H
 #define PLAT_PSCI_H
+#include <cortex_a53.h>
+#include <cortex_a72.h>
 
  /* core abort current op */
 #define CORE_ABORT_OP     0x1
@@ -55,6 +57,7 @@
 #define  CPUECTLR_RET_SET       0x2
 #define  CPUECTLR_TIMER_MASK    0x7
 #define  CPUECTLR_TIMER_8TICKS  0x2
+#define  CPUECTLR_TIMER_2TICKS  0x1
 #define  SCR_IRQ_MASK           0x2
 #define  SCR_FIQ_MASK           0x4
 
@@ -62,18 +65,53 @@
  *   value == 0x0, the soc code does not support this feature
  *   value != 0x0, the soc code supports this feature
  */
+#ifndef SOC_CORE_RELEASE
 #define SOC_CORE_RELEASE      0x1
+#endif
+
+#ifndef SOC_CORE_RESTART
 #define SOC_CORE_RESTART      0x1
+#endif
+
+#ifndef SOC_CORE_OFF
 #define SOC_CORE_OFF          0x1
+#endif
+
+#ifndef SOC_CORE_STANDBY
 #define SOC_CORE_STANDBY      0x1
+#endif
+
+#ifndef SOC_CORE_PWR_DWN
 #define SOC_CORE_PWR_DWN      0x1
+#endif
+
+#ifndef SOC_CLUSTER_STANDBY
 #define SOC_CLUSTER_STANDBY   0x1
+#endif
+
+#ifndef SOC_CLUSTER_PWR_DWN
 #define SOC_CLUSTER_PWR_DWN   0x1
+#endif
+
+#ifndef SOC_SYSTEM_STANDBY
 #define SOC_SYSTEM_STANDBY    0x1
+#endif
+
+#ifndef SOC_SYSTEM_PWR_DWN
 #define SOC_SYSTEM_PWR_DWN    0x1
+#endif
+
+#ifndef SOC_SYSTEM_OFF
 #define SOC_SYSTEM_OFF        0x1
+#endif
+
+#ifndef SOC_SYSTEM_RESET
 #define SOC_SYSTEM_RESET      0x1
+#endif
+
+#ifndef SOC_SYSTEM_RESET2
 #define SOC_SYSTEM_RESET2     0x1
+#endif
 
 #ifndef __ASSEMBLER__
 
diff --git a/plat/nxp/common/setup/core.mk b/plat/nxp/common/setup/core.mk
index 9b81f2d..82ce30e 100644
--- a/plat/nxp/common/setup/core.mk
+++ b/plat/nxp/common/setup/core.mk
@@ -1,4 +1,4 @@
-# Copyright 2018-2020 NXP
+# Copyright 2018-2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -11,9 +11,11 @@
 
 CPU_LIBS		:=	lib/cpus/${ARCH}/aem_generic.S
 
-ifeq (,$(filter $(CORE_TYPE),a53 a55 a57 a72 a75))
+ifeq (,$(filter $(CORE_TYPE),a53 a72))
 $(error "CORE_TYPE not specified or incorrect")
 else
+UPPER_CORE_TYPE=$(shell echo $(CORE_TYPE) | tr a-z A-Z)
+$(eval $(call add_define_val,CPUECTLR_EL1,CORTEX_$(UPPER_CORE_TYPE)_ECTLR_EL1))
 CPU_LIBS		+=	lib/cpus/${ARCH}/cortex_$(CORE_TYPE).S
 endif
 
diff --git a/plat/nxp/common/setup/include/plat_common.h b/plat/nxp/common/setup/include/plat_common.h
index 18d36ca..97a9cb7 100644
--- a/plat/nxp/common/setup/include/plat_common.h
+++ b/plat/nxp/common/setup/include/plat_common.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2020 NXP
+ * Copyright 2018-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -10,7 +10,9 @@
 
 #include <stdbool.h>
 
+#include <dcfg.h>
 #include <lib/el3_runtime/cpu_data.h>
+
 #include <platform_def.h>
 
 #ifdef IMAGE_BL31
@@ -129,18 +131,19 @@
 #endif
 );
 
-
 /* Structure to define SoC personality */
 struct soc_type {
 	char name[10];
-	uint32_t personality;
-	uint32_t num_clusters;
-	uint32_t cores_per_cluster;
+	uint32_t version;
+	uint8_t num_clusters;
+	uint8_t cores_per_cluster;
 };
+void get_cluster_info(const struct soc_type *soc_list, uint8_t ps_count,
+		uint8_t *num_clusters, uint8_t *cores_per_cluster);
 
 #define SOC_ENTRY(n, v, ncl, nc) {	\
 		.name = #n,		\
-		.personality = SVR_##v,	\
+		.version = SVR_##v,	\
 		.num_clusters = (ncl),	\
 		.cores_per_cluster = (nc)}
 
diff --git a/plat/nxp/common/setup/ls_common.c b/plat/nxp/common/setup/ls_common.c
index a6946e1..e7ae060 100644
--- a/plat/nxp/common/setup/ls_common.c
+++ b/plat/nxp/common/setup/ls_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2020 NXP
+ * Copyright 2018-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -238,3 +238,27 @@
 {
 	return plat_ls_mmap;
 }
+
+/*
+ * This function get the number of clusters and cores count per cluster
+ * in the SoC.
+ */
+void get_cluster_info(const struct soc_type *soc_list, uint8_t ps_count,
+		uint8_t *num_clusters, uint8_t *cores_per_cluster)
+{
+	const soc_info_t *soc_info = get_soc_info();
+	*num_clusters = NUMBER_OF_CLUSTERS;
+	*cores_per_cluster = CORES_PER_CLUSTER;
+	unsigned int i;
+
+	for (i = 0U; i < ps_count; i++) {
+		if (soc_list[i].version == soc_info->svr_reg.bf_ver.version) {
+			*num_clusters = soc_list[i].num_clusters;
+			*cores_per_cluster = soc_list[i].cores_per_cluster;
+			break;
+		}
+	}
+
+	VERBOSE("NUM of cluster = 0x%x, Cores per cluster = 0x%x\n",
+			*num_clusters, *cores_per_cluster);
+}
diff --git a/plat/nxp/common/soc_errata/errata.c b/plat/nxp/common/soc_errata/errata.c
new file mode 100644
index 0000000..fb1818a
--- /dev/null
+++ b/plat/nxp/common/soc_errata/errata.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <common/debug.h>
+
+#include "errata_list.h"
+
+void soc_errata(void)
+{
+#ifdef ERRATA_SOC_A050426
+	INFO("SoC workaround for Errata A050426 was applied\n");
+	erratum_a050426();
+#endif
+	/*
+	 * The following DDR Erratas workaround are implemented in DDR driver,
+	 * but print information here.
+	 */
+#if ERRATA_DDR_A011396
+	INFO("SoC workaround for DDR Errata A011396 was applied\n");
+#endif
+#if ERRATA_DDR_A050450
+	INFO("SoC workaround for DDR Errata A050450 was applied\n");
+#endif
+}
diff --git a/plat/nxp/common/soc_errata/errata.h b/plat/nxp/common/soc_errata/errata.h
new file mode 100644
index 0000000..b543b4b
--- /dev/null
+++ b/plat/nxp/common/soc_errata/errata.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2020-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef ERRATA_H
+#define ERRATA_H
+
+void soc_errata(void);
+
+#endif /* ERRATA_H */
diff --git a/plat/nxp/common/soc_errata/errata.mk b/plat/nxp/common/soc_errata/errata.mk
new file mode 100644
index 0000000..2942615
--- /dev/null
+++ b/plat/nxp/common/soc_errata/errata.mk
@@ -0,0 +1,23 @@
+#
+# Copyright 2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# Platform Errata Build flags.
+# These should be enabled by the platform if the erratum workaround needs to be
+# applied.
+
+ERRATA := \
+  ERRATA_SOC_A050426
+
+define enable_errata
+  $(1) ?= 0
+  ifeq ($$($(1)),1)
+    $$(eval $$(call add_define,$(1)))
+    BL2_SOURCES += $(PLAT_COMMON_PATH)/soc_errata/errata_a$(shell echo $(1)|awk -F '_A' '{print $$NF}').c
+  endif
+endef
+
+$(foreach e,$(ERRATA),$(eval $(call enable_errata,$(strip $(e)))))
+
+BL2_SOURCES += $(PLAT_COMMON_PATH)/soc_errata/errata.c
diff --git a/plat/nxp/soc-lx2160a/erratas_soc.c b/plat/nxp/common/soc_errata/errata_a050426.c
similarity index 98%
rename from plat/nxp/soc-lx2160a/erratas_soc.c
rename to plat/nxp/common/soc_errata/errata_a050426.c
index 8f3aa9f..13a0000 100644
--- a/plat/nxp/soc-lx2160a/erratas_soc.c
+++ b/plat/nxp/common/soc_errata/errata_a050426.c
@@ -7,7 +7,6 @@
 
 #include <mmio.h>
 
-#ifdef ERRATA_SOC_A050426
 void erratum_a050426(void)
 {
 	uint32_t i, val3, val4;
@@ -411,8 +410,6 @@
 	}
 
 	/* Disable BIST */
-
 	mmio_write_32(0x700117E60, val3);
 	mmio_write_32(0x700117E90, val4);
 }
-#endif
diff --git a/plat/nxp/common/soc_errata/errata_list.h b/plat/nxp/common/soc_errata/errata_list.h
new file mode 100644
index 0000000..74d2315
--- /dev/null
+++ b/plat/nxp/common/soc_errata/errata_list.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef ERRATA_LIST_H
+#define ERRATA_LIST_H
+
+#ifdef ERRATA_SOC_A050426
+void erratum_a050426(void);
+#endif
+
+#endif /* ERRATA_LIST_H */
diff --git a/plat/nxp/soc-ls1028a/aarch64/ls1028a.S b/plat/nxp/soc-ls1028a/aarch64/ls1028a.S
new file mode 100644
index 0000000..404c39e
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/aarch64/ls1028a.S
@@ -0,0 +1,1387 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+	.section .text, "ax"
+
+#include <asm_macros.S>
+
+#include <lib/psci/psci.h>
+#include <nxp_timer.h>
+#include <plat_gic.h>
+#include <pmu.h>
+
+#include <bl31_data.h>
+#include <plat_psci.h>
+#include <platform_def.h>
+
+	.global soc_init_lowlevel
+	.global soc_init_percpu
+	.global _set_platform_security
+	.global _soc_set_start_addr
+
+	.global _soc_core_release
+	.global _soc_ck_disabled
+	.global _soc_core_restart
+	.global _soc_core_prep_off
+	.global _soc_core_entr_off
+	.global _soc_core_exit_off
+	.global _soc_sys_reset
+	.global _soc_sys_off
+	.global _soc_core_prep_stdby
+	.global _soc_core_entr_stdby
+	.global _soc_core_exit_stdby
+	.global _soc_core_prep_pwrdn
+	.global _soc_core_entr_pwrdn
+	.global _soc_core_exit_pwrdn
+	.global _soc_clstr_prep_stdby
+	.global _soc_clstr_exit_stdby
+	.global _soc_clstr_prep_pwrdn
+	.global _soc_clstr_exit_pwrdn
+	.global _soc_sys_prep_stdby
+	.global _soc_sys_exit_stdby
+	.global _soc_sys_prep_pwrdn
+	.global _soc_sys_pwrdn_wfi
+	.global _soc_sys_exit_pwrdn
+
+	.equ TZPCDECPROT_0_SET_BASE, 0x02200804
+	.equ TZPCDECPROT_1_SET_BASE, 0x02200810
+	.equ TZPCDECPROT_2_SET_BASE, 0x0220081C
+
+	.equ TZASC_REGION_ATTRIBUTES_0_0, 0x01100110
+
+/*
+ * This function initialize the soc.
+ * in: void
+ * out: void
+ * uses x0 - x11
+ */
+func soc_init_lowlevel
+	/*
+	 * Called from C, so save the non-volatile regs
+	 * save these as pairs of registers to maintain the
+	 * required 16-byte alignment on the stack
+	 */
+	stp	x4,  x5,  [sp, #-16]!
+	stp	x6,  x7,  [sp, #-16]!
+	stp	x8,  x9,  [sp, #-16]!
+	stp	x10, x11, [sp, #-16]!
+	stp	x12, x13, [sp, #-16]!
+	stp	x18, x30, [sp, #-16]!
+
+	/*
+	 * Make sure the personality has been established by releasing cores
+	 * that are marked "to-be-disabled" from reset
+	 */
+	bl	release_disabled  /* 0-8 */
+
+	/* Set SCRATCHRW7 to 0x0 */
+	ldr	x0, =DCFG_SCRATCHRW7_OFFSET
+	mov	x1, xzr
+	bl	_write_reg_dcfg
+
+	/* Restore the aarch32/64 non-volatile registers */
+	ldp	x18, x30, [sp], #16
+	ldp	x12, x13, [sp], #16
+	ldp	x10, x11, [sp], #16
+	ldp	x8,  x9,  [sp], #16
+	ldp	x6,  x7,  [sp], #16
+	ldp	x4,  x5,  [sp], #16
+	ret
+endfunc soc_init_lowlevel
+
+/*
+ * void soc_init_percpu(void)
+ *
+ * This function performs any soc-specific initialization that is needed on
+ * a per-core basis
+ * in:  none
+ * out: none
+ * uses x0 - x3
+ */
+func soc_init_percpu
+	stp	x4,  x30,  [sp, #-16]!
+
+	bl	plat_my_core_mask
+	mov	x2, x0
+
+	/* x2 = core mask */
+
+	/* see if this core is marked for prefetch disable */
+	mov	x0, #PREFETCH_DIS_OFFSET
+	bl	_get_global_data  /* 0-1 */
+	tst	x0, x2
+	b.eq	1f
+	bl	_disable_ldstr_pfetch_A72  /* 0 */
+1:
+	mov	x0, #NXP_PMU_ADDR
+	bl	enable_timer_base_to_cluster
+
+	ldp	x4,  x30,  [sp], #16
+	ret
+endfunc soc_init_percpu
+
+/*
+ * This function determines if a core is disabled via COREDISABLEDSR
+ * in:  w0  = core_mask_lsb
+ * out: w0  = 0, core not disabled
+ *      w0 != 0, core disabled
+ * uses x0, x1
+ */
+func _soc_ck_disabled
+	/* get base addr of dcfg block */
+	ldr	x1, =NXP_DCFG_ADDR
+
+	/* read COREDISABLEDSR */
+	ldr	w1, [x1, #DCFG_COREDISABLEDSR_OFFSET]
+
+	/* test core bit */
+	and	w0, w1, w0
+
+	ret
+endfunc _soc_ck_disabled
+
+/*
+ * This function sets the security mechanisms in the SoC to implement the
+ * Platform Security Policy
+ */
+func _set_platform_security
+	mov	x3, x30
+
+#if (!SUPPRESS_TZC)
+	/* initialize the tzpc */
+	bl	init_tzpc
+#endif
+
+#if (!SUPPRESS_SEC)
+	/* initialize secmon */
+	bl	initSecMon
+#endif
+
+	mov	x30, x3
+	ret
+endfunc _set_platform_security
+
+/*
+ * Part of CPU_ON
+ *
+ * This function releases a secondary core from reset
+ * in:   x0 = core_mask_lsb
+ * out:  none
+ * uses: x0 - x3
+ */
+_soc_core_release:
+	mov	x3, x30
+
+	/*
+	 * Write to CORE_HOLD to tell the bootrom that we want this core
+	 * to run
+	 */
+	ldr	x1, =NXP_SEC_REGFILE_ADDR
+	str	w0, [x1, #CORE_HOLD_OFFSET]
+
+	/* Read-modify-write BRRL to release core */
+	mov	x1, #NXP_RESET_ADDR
+	ldr	w2, [x1, #BRR_OFFSET]
+	orr	w2, w2, w0
+	str	w2, [x1, #BRR_OFFSET]
+	dsb	sy
+	isb
+
+	/* Send event */
+	sev
+	isb
+
+	mov	x30, x3
+	ret
+
+/*
+ * This function writes a 64-bit address to bootlocptrh/l
+ * in:  x0, 64-bit address to write to BOOTLOCPTRL/H
+ * uses x0, x1, x2
+ */
+func _soc_set_start_addr
+	/* Get the 64-bit base address of the dcfg block */
+	ldr	x2, =NXP_DCFG_ADDR
+
+	/* Write the 32-bit BOOTLOCPTRL register */
+	mov	x1, x0
+	str	w1, [x2, #DCFG_BOOTLOCPTRL_OFFSET]
+
+	/* Write the 32-bit BOOTLOCPTRH register */
+	lsr	x1, x0, #32
+	str	w1, [x2, #DCFG_BOOTLOCPTRH_OFFSET]
+	ret
+endfunc _soc_set_start_addr
+
+/*
+ * Part of CPU_ON
+ *
+ * This function restarts a core shutdown via _soc_core_entr_off
+ * in:  x0 = core mask lsb (of the target cpu)
+ * out: x0 == 0, on success
+ *      x0 != 0, on failure
+ * uses x0 - x6
+ */
+_soc_core_restart:
+	mov	x6, x30
+	mov	x4, x0
+
+	/* pgm GICD_CTLR - enable secure grp0  */
+	mov	x5, #NXP_GICD_ADDR
+	ldr	w2, [x5, #GICD_CTLR_OFFSET]
+	orr	w2, w2, #GICD_CTLR_EN_GRP_0
+	str	w2, [x5, #GICD_CTLR_OFFSET]
+	dsb	sy
+	isb
+
+	/* Poll on RWP til write completes */
+4:
+	ldr	w2, [x5, #GICD_CTLR_OFFSET]
+	tst	w2, #GICD_CTLR_RWP
+	b.ne	4b
+
+	/*
+	 * x4 = core mask lsb
+	 * x5 = gicd base addr
+	 */
+
+	mov	x0, x4
+	bl	get_mpidr_value
+
+	/* Generate target list bit */
+	and	x1, x0, #MPIDR_AFFINITY0_MASK
+	mov	x2, #1
+	lsl	x2, x2, x1
+
+	/* Get the affinity1 field */
+	and	x1, x0, #MPIDR_AFFINITY1_MASK
+	lsl	x1, x1, #8
+	orr	x2, x2, x1
+
+	/* Insert the INTID for SGI15 */
+	orr	x2, x2, #ICC_SGI0R_EL1_INTID
+
+	/* Fire the SGI */
+	msr	ICC_SGI0R_EL1, x2
+	dsb	sy
+	isb
+
+	/* Load '0' on success */
+	mov	x0, xzr
+
+	mov	x30, x6
+	ret
+
+/*
+ * Part of CPU_OFF
+ *
+ * This function programs SoC & GIC registers in preparation for shutting down
+ * the core
+ * in:  x0 = core mask lsb
+ * out: none
+ * uses x0 - x7
+ */
+_soc_core_prep_off:
+	mov	x8, x30
+	mov	x7, x0
+
+	/* x7 = core mask lsb */
+
+	mrs	x1, CPUECTLR_EL1
+
+	/* Set smp and disable L2 snoops in cpuectlr */
+	orr	x1, x1, #CPUECTLR_SMPEN_EN
+	orr	x1, x1, #CPUECTLR_DISABLE_TWALK_PREFETCH
+	bic	x1, x1, #CPUECTLR_INS_PREFETCH_MASK
+	bic	x1, x1, #CPUECTLR_DAT_PREFETCH_MASK
+
+	/* Set retention control in cpuectlr */
+	bic	x1, x1, #CPUECTLR_TIMER_MASK
+	orr	x1, x1, #CPUECTLR_TIMER_2TICKS
+	msr	CPUECTLR_EL1, x1
+
+	/* Get redistributor rd base addr for this core */
+	mov	x0, x7
+	bl	get_gic_rd_base
+	mov	x6, x0
+
+	/* Get redistributor sgi base addr for this core */
+	mov	x0, x7
+	bl	get_gic_sgi_base
+	mov	x5, x0
+
+	/*
+	 * x5 = gicr sgi base addr
+	 * x6 = gicr rd  base addr
+	 * x7 = core mask lsb
+	 */
+
+	/* Disable SGI 15 at redistributor - GICR_ICENABLER0 */
+	mov	w3, #GICR_ICENABLER0_SGI15
+	str	w3, [x5, #GICR_ICENABLER0_OFFSET]
+2:
+	/* Poll on rwp bit in GICR_CTLR */
+	ldr	w4, [x6, #GICR_CTLR_OFFSET]
+	tst	w4, #GICR_CTLR_RWP
+	b.ne	2b
+
+	/* Disable GRP1 interrupts at cpu interface */
+	msr	ICC_IGRPEN1_EL3, xzr
+
+	/* Disable GRP0 ints at cpu interface */
+	msr	ICC_IGRPEN0_EL1, xzr
+
+	/* Program the redistributor - poll on GICR_CTLR.RWP as needed */
+
+	/* Define SGI 15 as Grp0 - GICR_IGROUPR0 */
+	ldr	w4, [x5, #GICR_IGROUPR0_OFFSET]
+	bic	w4, w4, #GICR_IGROUPR0_SGI15
+	str	w4, [x5, #GICR_IGROUPR0_OFFSET]
+
+	/* Define SGI 15 as Grp0 - GICR_IGRPMODR0 */
+	ldr	w3, [x5, #GICR_IGRPMODR0_OFFSET]
+	bic	w3, w3, #GICR_IGRPMODR0_SGI15
+	str	w3, [x5, #GICR_IGRPMODR0_OFFSET]
+
+	/* Set priority of SGI 15 to highest (0x0) - GICR_IPRIORITYR3 */
+	ldr	w4, [x5, #GICR_IPRIORITYR3_OFFSET]
+	bic	w4, w4, #GICR_IPRIORITYR3_SGI15_MASK
+	str	w4, [x5, #GICR_IPRIORITYR3_OFFSET]
+
+	/* Enable SGI 15 at redistributor - GICR_ISENABLER0 */
+	mov	w3, #GICR_ISENABLER0_SGI15
+	str	w3, [x5, #GICR_ISENABLER0_OFFSET]
+	dsb	sy
+	isb
+3:
+	/* Poll on rwp bit in GICR_CTLR */
+	ldr	w4, [x6, #GICR_CTLR_OFFSET]
+	tst	w4, #GICR_CTLR_RWP
+	b.ne	3b
+
+	/* Quiesce the debug interfaces */
+	mrs	x3, osdlr_el1
+	orr	x3, x3, #OSDLR_EL1_DLK_LOCK
+	msr	osdlr_el1, x3
+	isb
+
+	/* Enable grp0 ints */
+	mov	x3, #ICC_IGRPEN0_EL1_EN
+	msr	ICC_IGRPEN0_EL1, x3
+
+	/*
+	 * x5 = gicr sgi base addr
+	 * x6 = gicr rd  base addr
+	 * x7 = core mask lsb
+	 */
+
+	/* Clear any pending interrupts */
+	mvn	w1, wzr
+	str	w1, [x5, #GICR_ICPENDR0_OFFSET]
+
+	/* Make sure system counter is enabled */
+	ldr	x3, =NXP_TIMER_ADDR
+	ldr	w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
+	tst	w0, #SYS_COUNTER_CNTCR_EN
+	b.ne	4f
+	orr	w0, w0, #SYS_COUNTER_CNTCR_EN
+	str	w0, [x3, #SYS_COUNTER_CNTCR_OFFSET]
+4:
+	/* Enable the core timer and mask timer interrupt */
+	mov	x1, #CNTP_CTL_EL0_EN
+	orr	x1, x1, #CNTP_CTL_EL0_IMASK
+	msr	cntp_ctl_el0, x1
+
+	isb
+	mov	x30, x8
+	ret
+
+/*
+ * Part of CPU_OFF
+ *
+ * This function performs the final steps to shutdown the core
+ * in:  x0 = core mask lsb
+ * out: none
+ * uses x0 - x5
+ */
+_soc_core_entr_off:
+	mov	x5, x30
+	mov	x4, x0
+
+	/* x4 = core mask */
+1:
+	/* Enter low-power state by executing wfi */
+	wfi
+
+	/* See if SGI15 woke us up */
+	mrs	x2, ICC_IAR0_EL1
+	mov	x3, #ICC_IAR0_EL1_SGI15
+	cmp	x2, x3
+	b.ne	1b
+
+	/* Deactivate the int */
+	msr	ICC_EOIR0_EL1, x2
+
+	/* x4 = core mask */
+2:
+	/* Check if core has been turned on */
+	mov	x0, x4
+	bl	_getCoreState
+
+	/* x0 = core state */
+
+	cmp	x0, #CORE_WAKEUP
+	b.ne	1b
+
+	/* If we get here, then we have exited the wfi */
+	mov	x30, x5
+	ret
+
+/*
+ * Part of CPU_OFF
+ *
+ * This function starts the process of starting a core back up
+ * in:  x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5, x6
+ */
+_soc_core_exit_off:
+	mov	x6, x30
+	mov	x5, x0
+
+	/* Disable forwarding of GRP0 ints at cpu interface */
+	msr	ICC_IGRPEN0_EL1, xzr
+
+	/* Get redistributor sgi base addr for this core */
+	mov	x0, x5
+	bl	get_gic_sgi_base
+	mov	x4, x0
+
+	/* x4 = gicr sgi base addr */
+	/* x5 = core mask */
+
+	/* Disable SGI 15 at redistributor - GICR_ICENABLER0 */
+	mov	w1, #GICR_ICENABLER0_SGI15
+	str	w1, [x4, #GICR_ICENABLER0_OFFSET]
+
+	/* Get redistributor rd base addr for this core */
+	mov	x0, x5
+	bl	get_gic_rd_base
+	mov	x4, x0
+
+	/* x4 = gicr rd  base addr */
+2:
+	/* Poll on rwp bit in GICR_CTLR */
+	ldr	w2, [x4, #GICR_CTLR_OFFSET]
+	tst	w2, #GICR_CTLR_RWP
+	b.ne	2b
+
+	/* x4 = gicr rd  base addr */
+
+	/* Unlock the debug interfaces */
+	mrs	x3, osdlr_el1
+	bic	x3, x3, #OSDLR_EL1_DLK_LOCK
+	msr	osdlr_el1, x3
+	isb
+
+	dsb	sy
+	isb
+	mov	x30, x6
+	ret
+
+/*
+ * This function requests a reset of the entire SOC
+ * in:  none
+ * out: none
+ * uses: x0, x1, x2, x3, x4, x5, x6
+ */
+_soc_sys_reset:
+	mov	x3, x30
+
+	/* Make sure the mask is cleared in the reset request mask register */
+	mov	x0, #RST_RSTRQMR1_OFFSET
+	mov	w1, wzr
+	bl	_write_reg_reset
+
+	/* Set the reset request */
+	mov	x4, #RST_RSTCR_OFFSET
+	mov	x0, x4
+	mov	w1, #RSTCR_RESET_REQ
+	bl	_write_reg_reset
+
+	/* x4 = RST_RSTCR_OFFSET */
+
+	/*
+	 * Just in case this address range is mapped as cacheable,
+	 * flush the write out of the dcaches
+	 */
+	mov	x2, #NXP_RESET_ADDR
+	add	x2, x2, x4
+	dc	cvac, x2
+	dsb	st
+	isb
+
+	/* This function does not return */
+1:
+	wfi
+	b	1b
+
+/*
+ * Part of SYSTEM_OFF
+ *
+ * This function turns off the SoC clocks
+ * Note: this function is not intended to return, and the only allowable
+ *       recovery is POR
+ * in:  none
+ * out: none
+ * uses x0, x1, x2, x3
+ */
+_soc_sys_off:
+	/*
+	 * Disable sec, spi and flexspi
+	 * TBD - Check if eNETC needs to be disabled
+	 */
+	ldr	x2, =NXP_DCFG_ADDR
+	ldr	x0, =DCFG_DEVDISR1_OFFSET
+	ldr	w1, =DCFG_DEVDISR1_SEC
+	str	w1, [x2, x0]
+	ldr	x0, =DCFG_DEVDISR4_OFFSET
+	ldr	w1, =DCFG_DEVDISR4_SPI_QSPI
+	str	w1, [x2, x0]
+
+	/* Set TPMWAKEMR0 */
+	ldr	x0, =TPMWAKEMR0_ADDR
+	mov	w1, #0x1
+	str	w1, [x0]
+
+	/* Disable icache, dcache, mmu @ EL1 */
+	mov	x1, #SCTLR_I_C_M_MASK
+	mrs	x0, sctlr_el1
+	bic	x0, x0, x1
+	msr	sctlr_el1, x0
+
+	/* Disable L2 prefetches */
+	mrs	x0, CPUECTLR_EL1
+	orr	x0, x0, #CPUECTLR_SMPEN_EN
+	bic	x0, x0, #CPUECTLR_TIMER_MASK
+	orr	x0, x0, #CPUECTLR_TIMER_2TICKS
+	msr	CPUECTLR_EL1, x0
+	dsb	sy
+	isb
+
+	/* Disable CCI snoop domain */
+	ldr	x0, =NXP_CCI_ADDR
+	mov	w1, #0x1
+	str	w1, [x0]
+
+	bl	get_pmu_idle_core_mask
+
+	/* x3 = pmu base addr */
+	mov	x3, #NXP_PMU_ADDR
+4:
+	ldr	w1, [x3, #PMU_PCPW20SR_OFFSET]
+	cmp	w1, w0
+	b.ne	4b
+
+	bl	get_pmu_idle_cluster_mask
+	mov	x3, #NXP_PMU_ADDR
+	str	w0, [x3, #PMU_CLAINACTSETR_OFFSET]
+
+	bl	get_pmu_idle_core_mask
+	mov	x3, #NXP_PMU_ADDR
+1:
+	ldr	w1, [x3, #PMU_PCPW20SR_OFFSET]
+	cmp	w1, w0
+	b.ne	1b
+
+	bl	get_pmu_flush_cluster_mask
+	mov	x3, #NXP_PMU_ADDR
+	str	w0, [x3, #PMU_CLL2FLUSHSETR_OFFSET]
+2:
+	ldr	w1, [x3, #PMU_CLL2FLUSHSR_OFFSET]
+	cmp	w1, w0
+	b.ne	2b
+
+	str	w0, [x3, #PMU_CLSL2FLUSHCLRR_OFFSET]
+
+	str	w0, [x3, #PMU_CLSINACTSETR_OFFSET]
+
+	mov	x2, #DAIF_SET_MASK
+	mrs	x1, spsr_el1
+	orr	x1, x1, x2
+	msr	spsr_el1, x1
+
+	mrs	x1, spsr_el2
+	orr	x1, x1, x2
+	msr	spsr_el2, x1
+
+	/* Force the debug interface to be quiescent */
+	mrs	x0, osdlr_el1
+	orr	x0, x0, #0x1
+	msr	osdlr_el1, x0
+
+	/* Invalidate all TLB entries at all 3 exception levels */
+	tlbi	alle1
+	tlbi	alle2
+	tlbi	alle3
+
+	/* x3 = pmu base addr */
+
+	/* Request lpm20 */
+	ldr	x0, =PMU_POWMGTCSR_OFFSET
+	ldr	w1, =PMU_POWMGTCSR_VAL
+	str	w1, [x3, x0]
+	isb
+	dsb	sy
+5:
+	wfe
+	b.eq	5b
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs SoC-specific programming prior to standby
+ * in:  x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+_soc_core_prep_stdby:
+	/* Clear CPUECTLR_EL1[2:0] */
+	mrs	x1, CPUECTLR_EL1
+	bic	x1, x1, #CPUECTLR_TIMER_MASK
+	msr	CPUECTLR_EL1, x1
+
+	ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function puts the calling core into standby state
+ * in:  x0 = core mask lsb
+ * out: none
+ * uses x0
+ */
+_soc_core_entr_stdby:
+	/* X0 = core mask lsb */
+	dsb	sy
+	isb
+	wfi
+
+	ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs any SoC-specific cleanup after standby state
+ * in:  x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+_soc_core_exit_stdby:
+	ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs SoC-specific programming prior to power-down
+ * in:  x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2
+ */
+_soc_core_prep_pwrdn:
+	/* Make sure system counter is enabled */
+	ldr	x2, =NXP_TIMER_ADDR
+	ldr	w0, [x2, #SYS_COUNTER_CNTCR_OFFSET]
+	tst	w0, #SYS_COUNTER_CNTCR_EN
+	b.ne	1f
+	orr	w0, w0, #SYS_COUNTER_CNTCR_EN
+	str	w0, [x2, #SYS_COUNTER_CNTCR_OFFSET]
+1:
+	/*
+	 * Enable dynamic retention control (CPUECTLR[2:0])
+	 * Set the SMPEN bit (CPUECTLR[6])
+	 */
+	mrs	x1, CPUECTLR_EL1
+	bic	x1, x1, #CPUECTLR_RET_MASK
+	orr	x1, x1, #CPUECTLR_TIMER_2TICKS
+	orr	x1, x1, #CPUECTLR_SMPEN_EN
+	msr	CPUECTLR_EL1, x1
+
+	isb
+	ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function puts the calling core into a power-down state
+ * in:  x0 = core mask lsb
+ * out: none
+ * uses x0
+ */
+_soc_core_entr_pwrdn:
+	/* X0 = core mask lsb */
+	dsb	sy
+	isb
+	wfi
+
+	ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs any SoC-specific cleanup after power-down state
+ * in:  x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+_soc_core_exit_pwrdn:
+	ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs SoC-specific programming prior to standby
+ * in:  x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+_soc_clstr_prep_stdby:
+	/* Clear CPUECTLR_EL1[2:0] */
+	mrs	x1, CPUECTLR_EL1
+	bic	x1, x1, #CPUECTLR_TIMER_MASK
+	msr	CPUECTLR_EL1, x1
+
+	ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs any SoC-specific cleanup after standby state
+ * in:  x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+_soc_clstr_exit_stdby:
+	ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs SoC-specific programming prior to power-down
+ * in:  x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2
+ */
+_soc_clstr_prep_pwrdn:
+	/* Make sure system counter is enabled */
+	ldr	x2, =NXP_TIMER_ADDR
+	ldr	w0, [x2, #SYS_COUNTER_CNTCR_OFFSET]
+	tst	w0, #SYS_COUNTER_CNTCR_EN
+	b.ne	1f
+	orr	w0, w0, #SYS_COUNTER_CNTCR_EN
+	str	w0, [x2, #SYS_COUNTER_CNTCR_OFFSET]
+1:
+	/*
+	 * Enable dynamic retention control (CPUECTLR[2:0])
+	 * Set the SMPEN bit (CPUECTLR[6])
+	 */
+	mrs	x1, CPUECTLR_EL1
+	bic	x1, x1, #CPUECTLR_RET_MASK
+	orr	x1, x1, #CPUECTLR_TIMER_2TICKS
+	orr	x1, x1, #CPUECTLR_SMPEN_EN
+	msr	CPUECTLR_EL1, x1
+
+	isb
+	ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs any SoC-specific cleanup after power-down state
+ * in:  x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+_soc_clstr_exit_pwrdn:
+	ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs SoC-specific programming prior to standby
+ * in:  x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+_soc_sys_prep_stdby:
+	/* Clear CPUECTLR_EL1[2:0] */
+	mrs	x1, CPUECTLR_EL1
+	bic	x1, x1, #CPUECTLR_TIMER_MASK
+	msr	CPUECTLR_EL1, x1
+
+	ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs any SoC-specific cleanup after standby state
+ * in:  x0 = core mask lsb
+ * out: none
+ * uses none
+ */
+_soc_sys_exit_stdby:
+	ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs SoC-specific programming prior to
+ * suspend-to-power-down
+ * in:  x0 = core mask lsb
+ * out: none
+ * uses x0, x1, x2, x3, x4
+ */
+_soc_sys_prep_pwrdn:
+	/* Set retention control */
+	mrs	x0, CPUECTLR_EL1
+	bic	x0, x0, #CPUECTLR_TIMER_MASK
+	orr	x0, x0, #CPUECTLR_TIMER_2TICKS
+	orr	x0, x0, #CPUECTLR_SMPEN_EN
+	msr	CPUECTLR_EL1, x0
+	dsb	sy
+	isb
+	ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function puts the calling core, and potentially the soc, into a
+ * low-power state
+ * in:  x0 = core mask lsb
+ * out: x0 = 0, success
+ *      x0 < 0, failure
+ * uses x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x13, x14, x15,
+ *      x16, x17, x18
+ */
+_soc_sys_pwrdn_wfi:
+	mov	x18, x30
+
+	mov	x3, #NXP_PMU_ADDR
+
+	/* x3 = pmu base addr */
+
+	/* Backup epu registers to stack */
+	ldr	x2, =NXP_EPU_ADDR
+	ldr	w4, [x2, #EPU_EPIMCR10_OFFSET]
+	ldr	w5, [x2, #EPU_EPCCR10_OFFSET]
+	ldr	w6, [x2, #EPU_EPCTR10_OFFSET]
+	ldr	w7, [x2, #EPU_EPGCR_OFFSET]
+	stp	x4,  x5,  [sp, #-16]!
+	stp	x6,  x7,  [sp, #-16]!
+
+	/*
+	 * x2 = epu base addr
+	 * x3 = pmu base addr
+	 */
+
+	/* Set up EPU event to receive the wake signal from PMU */
+	mov	w4, #EPU_EPIMCR10_VAL
+	mov	w5, #EPU_EPCCR10_VAL
+	mov	w6, #EPU_EPCTR10_VAL
+	mov	w7, #EPU_EPGCR_VAL
+	str	w4, [x2, #EPU_EPIMCR10_OFFSET]
+	str	w5, [x2, #EPU_EPCCR10_OFFSET]
+	str	w6, [x2, #EPU_EPCTR10_OFFSET]
+	str	w7, [x2, #EPU_EPGCR_OFFSET]
+
+	ldr	x2, =NXP_GICD_ADDR
+
+	/*
+	 * x2 = gicd base addr
+	 * x3 = pmu base addr
+	 */
+
+	/* Backup flextimer/mmc/usb interrupt router */
+	ldr	x0, =GICD_IROUTER60_OFFSET
+	ldr	x1, =GICD_IROUTER76_OFFSET
+	ldr	w4, [x2, x0]
+	ldr	w5, [x2, x1]
+	ldr	x0, =GICD_IROUTER112_OFFSET
+	ldr	x1, =GICD_IROUTER113_OFFSET
+	ldr	w6, [x2, x0]
+	ldr	w7, [x2, x1]
+	stp	x4,  x5,  [sp, #-16]!
+	stp	x6,  x7,  [sp, #-16]!
+
+	/*
+	 * x2 = gicd base addr
+	 * x3 = pmu base addr
+	 * x0 = GICD_IROUTER112_OFFSET
+	 * x1 = GICD_IROUTER113_OFFSET
+	 */
+
+	/* Re-route interrupt to cluster 1 */
+	ldr	w4, =GICD_IROUTER_VALUE
+	str	w4, [x2, x0]
+	str	w4, [x2, x1]
+	ldr	x0, =GICD_IROUTER60_OFFSET
+	ldr	x1, =GICD_IROUTER76_OFFSET
+	str	w4, [x2, x0]
+	str	w4, [x2, x1]
+	dsb	sy
+	isb
+
+	/* x3 = pmu base addr */
+
+	/* Disable sec, Check for eNETC, spi and qspi */
+	ldr	x2, =NXP_DCFG_ADDR
+	ldr	x0, =DCFG_DEVDISR1_OFFSET
+	ldr	w1, =DCFG_DEVDISR1_SEC
+	str	w1, [x2, x0]
+
+	ldr	x0, =DCFG_DEVDISR4_OFFSET
+	ldr	w1, =DCFG_DEVDISR4_SPI_QSPI
+	str	w1, [x2, x0]
+
+	/* x3 = pmu base addr */
+
+	/* Set TPMWAKEMR0 */
+	ldr	x0, =TPMWAKEMR0_ADDR
+	mov	w1, #0x1
+	str	w1, [x0]
+
+	/* Disable CCI snoop domain */
+	ldr	x0, =NXP_CCI_ADDR
+	mov	w1, #0x1
+	str	w1, [x0]
+
+	/* Setup retention control */
+	mrs	x0, CPUECTLR_EL1
+	orr	x0, x0, #CPUECTLR_SMPEN_EN
+	orr	x0, x0, #CPUECTLR_TIMER_2TICKS
+	msr	CPUECTLR_EL1, x0
+	dsb	sy
+	isb
+
+	bl	get_pmu_idle_core_mask
+	mov	x3, #NXP_PMU_ADDR
+8:
+	ldr	w1, [x3, #PMU_PCPW20SR_OFFSET]
+	cmp	w1, w0
+	b.ne	8b
+
+	/* x3 = NXP_PMU_ADDR */
+	/* 1 cluster SoC */
+
+	bl	get_pmu_idle_cluster_mask
+	mov	x3, #NXP_PMU_ADDR
+
+	str	w0, [x3, #PMU_CLAINACTSETR_OFFSET]
+
+	bl	get_pmu_idle_core_mask
+	/* x3 = NXP_PMU_ADDR */
+	mov	x3, #NXP_PMU_ADDR
+1:
+	ldr	w1, [x3, #PMU_PCPW20SR_OFFSET]
+	cmp	w1, w0
+	b.ne	1b
+
+	/* x3 = NXP_PMU_ADDR */
+	bl	get_pmu_flush_cluster_mask
+	mov	x3, #NXP_PMU_ADDR
+
+	str	w0, [x3, #PMU_CLL2FLUSHSETR_OFFSET]
+
+	/* x3 = NXP_PMU_ADDR */
+2:
+	ldr	w1, [x3, #PMU_CLL2FLUSHSR_OFFSET]
+	cmp	w1, w0
+	b.ne	2b
+
+	/* x3 = NXP_PMU_ADDR */
+
+	str	w0, [x3, #PMU_CLSL2FLUSHCLRR_OFFSET]
+
+	str	w0, [x3, #PMU_CLSINACTSETR_OFFSET]
+
+	/* Force the debug interface to be quiescent */
+	mrs	x0, osdlr_el1
+	orr	x0, x0, #0x1
+	msr	osdlr_el1, x0
+
+	/*
+	 * Enable the WakeRequest signal
+	 * x3 is cpu mask starting from cpu1 to cpu0
+	 */
+	bl	get_tot_num_cores
+	sub	x0, x0, #1
+	mov	x3, #0x1
+	lsl	x3, x3, x0
+2:
+	mov	x0, x3
+	bl	get_gic_rd_base  // 0-2
+	ldr	w1, [x0, #GICR_WAKER_OFFSET]
+	orr	w1, w1, #GICR_WAKER_SLEEP_BIT
+	str	w1, [x0, #GICR_WAKER_OFFSET]
+1:
+	ldr	w1, [x0, #GICR_WAKER_OFFSET]
+	cmp	w1, #GICR_WAKER_ASLEEP
+	b.ne	1b
+
+	lsr	x3, x3, #1
+	cbnz	x3, 2b
+
+	/* Invalidate all TLB entries at all 3 exception levels */
+	tlbi	alle1
+	tlbi	alle2
+	tlbi	alle3
+
+	/* Request lpm20 */
+	mov	x3, #NXP_PMU_ADDR
+	ldr	x0, =PMU_POWMGTCSR_OFFSET
+	ldr	w1, =PMU_POWMGTCSR_VAL
+	str	w1, [x3, x0]
+
+	ldr	x5, =NXP_EPU_ADDR
+4:
+	wfe
+	ldr	w1, [x5, #EPU_EPCTR10_OFFSET]
+	cmp	w1, #0
+	b.eq	4b
+
+	/* x3 = NXP_PMU_ADDR */
+
+	bl	get_pmu_idle_cluster_mask
+	mov	x3, NXP_PMU_ADDR
+
+	/* Re-enable the GPP ACP */
+	str	w0, [x3, #PMU_CLAINACTCLRR_OFFSET]
+	str	w0, [x3, #PMU_CLSINACTCLRR_OFFSET]
+
+	/* x3 = NXP_PMU_ADDR */
+3:
+	ldr	w1, [x3, #PMU_CLAINACTSETR_OFFSET]
+	cbnz	w1, 3b
+4:
+	ldr	w1, [x3, #PMU_CLSINACTSETR_OFFSET]
+	cbnz	w1, 4b
+
+	/*
+	 * Enable the WakeRequest signal on cpu 0-1
+	 * x3 is cpu mask starting from cpu1
+	 */
+	bl	get_tot_num_cores
+	sub	x0, x0, #1
+	mov	x3, #0x1
+	lsl	x3, x3, x0
+2:
+	mov	x0, x3
+	bl	get_gic_rd_base  // 0-2
+	ldr	w1, [x0, #GICR_WAKER_OFFSET]
+	bic	w1, w1, #GICR_WAKER_SLEEP_BIT
+	str	w1, [x0, #GICR_WAKER_OFFSET]
+1:
+	ldr	w1, [x0, #GICR_WAKER_OFFSET]
+	cbnz	w1, 1b
+
+	lsr	x3, x3, #1
+	cbnz	x3, 2b
+
+	/* Enable CCI snoop domain */
+	ldr	x0, =NXP_CCI_ADDR
+	str	wzr, [x0]
+	dsb	sy
+	isb
+
+	ldr	x3, =NXP_EPU_ADDR
+
+	/* x3 = epu base addr */
+
+	/* Enable sec, enetc, spi and qspi */
+	ldr	x2, =NXP_DCFG_ADDR
+	str	wzr, [x2, #DCFG_DEVDISR1_OFFSET]
+	str	wzr, [x2, #DCFG_DEVDISR2_OFFSET]
+	str	wzr, [x2, #DCFG_DEVDISR4_OFFSET]
+
+	/* Restore flextimer/mmc/usb interrupt router */
+	ldr	x3, =NXP_GICD_ADDR
+	ldp	x0, x2, [sp], #16
+	ldr	x1, =GICD_IROUTER113_OFFSET
+	str	w2, [x3, x1]
+	ldr	x1, =GICD_IROUTER112_OFFSET
+	str	w0, [x3, x1]
+	ldp	x0, x2, [sp], #16
+	ldr	x1, =GICD_IROUTER76_OFFSET
+	str	w2, [x3, x1]
+	ldr	x1, =GICD_IROUTER60_OFFSET
+	str	w0, [x3, x1]
+
+	/* Restore EPU registers */
+	ldr	x3, =NXP_EPU_ADDR
+	ldp	x0, x2, [sp], #16
+	str	w2, [x3, #EPU_EPGCR_OFFSET]
+	str	w0, [x3, #EPU_EPCTR10_OFFSET]
+	ldp	x2, x1, [sp], #16
+	str	w1, [x3, #EPU_EPCCR10_OFFSET]
+	str	w2, [x3, #EPU_EPIMCR10_OFFSET]
+
+	dsb	sy
+	isb
+	mov	x30, x18
+	ret
+
+/*
+ * Part of CPU_SUSPEND
+ *
+ * This function performs any SoC-specific cleanup after power-down
+ * in:  x0 = core mask lsb
+ * out: none
+ * uses x0, x1
+ */
+_soc_sys_exit_pwrdn:
+	/* Enable stack alignment checking */
+	mrs	x1, SCTLR_EL1
+	orr	x1, x1, #0x4
+	msr	SCTLR_EL1, x1
+
+	/* Enable debug interface */
+	mrs	x1, osdlr_el1
+	bic	x1, x1, #OSDLR_EL1_DLK_LOCK
+	msr	osdlr_el1, x1
+
+	/* Enable i-cache */
+	mrs	x1, SCTLR_EL3
+	orr	x1, x1, #SCTLR_I_MASK
+	msr	SCTLR_EL3, x1
+
+	isb
+	ret
+
+/*
+ * This function setc up the TrustZone Address Space Controller (TZASC)
+ * in:  none
+ * out: none
+ * uses x0, x1
+ */
+init_tzpc:
+	/* Set Non Secure access for all devices protected via TZPC */
+	ldr	x1, =TZPCDECPROT_0_SET_BASE   /* decode Protection-0 Set Reg */
+	mov	w0, #0xFF		      /* set decode region to NS, Bits[7:0] */
+	str	w0, [x1]
+
+	ldr	x1, =TZPCDECPROT_1_SET_BASE   /* decode Protection-1 Set Reg */
+	mov	w0, #0xFF		      /* set decode region to NS, Bits[7:0] */
+	str	w0, [x1]
+
+	ldr	x1, =TZPCDECPROT_2_SET_BASE   /* decode Protection-2 Set Reg */
+	mov	w0, #0xFF		      /* set decode region to NS, Bits[7:0] */
+	str	w0, [x1]
+
+	 /* entire SRAM as NS */
+	ldr	x1, =NXP_OCRAM_TZPC_ADDR      /* secure RAM region size Reg */
+	mov	w0, #0x00000000		      /* 0x00000000 = no secure region */
+	str	w0, [x1]
+
+	ret
+
+/*
+ * This function performs any needed initialization on SecMon for
+ * boot services
+ */
+initSecMon:
+	/* Read the register hpcomr */
+	ldr	x1, =NXP_SNVS_ADDR
+	ldr	w0, [x1, #SECMON_HPCOMR_OFFSET]
+	/* Turn off secure access for the privileged registers */
+	orr	w0, w0, #SECMON_HPCOMR_NPSWAEN
+	/* Write back */
+	str	w0, [x1, #SECMON_HPCOMR_OFFSET]
+
+	ret
+
+/*
+ * This function checks to see if cores which are to be disabled have been
+ * released from reset - if not, it releases them
+ * in:  none
+ * out: none
+ * uses x0, x1, x2, x3, x4, x5, x6, x7, x8
+ */
+release_disabled:
+	stp	x18, x30, [sp, #-16]!
+
+	/*
+	 * Get the number of cpus on this device
+	 * Calling the below c function.
+	 * No need to Callee saved registers x9-x15,
+	 * as these registers are not used by the callee
+	 * prior to calling the below C-routine.
+	 */
+	bl	get_tot_num_cores
+	mov	x6, x0
+
+	/* Read COREDISABLESR */
+	mov	x0, #NXP_DCFG_ADDR
+	ldr	w4, [x0, #DCFG_COREDISABLEDSR_OFFSET]
+
+	mov	x0, #NXP_RESET_ADDR
+	ldr	w5, [x0, #BRR_OFFSET]
+
+	/* Load the core mask for the first core */
+	mov	x7, #1
+
+	/*
+	 * x4 = COREDISABLESR
+	 * x5 = BRR
+	 * x6 = loop count
+	 * x7 = core mask bit
+	 */
+2:
+	/* Check if the core is to be disabled */
+	tst	x4, x7
+	b.eq	1f
+
+	/* See if disabled cores have already been released from reset */
+	tst	x5, x7
+	b.ne	1f
+
+	/* If core has not been released, then release it (0-3) */
+	mov	x0, x7
+	bl	_soc_core_release
+
+	/* Record the core state in the data area (0-3) */
+	mov	x0, x7
+	mov	x1, #CORE_DISABLED
+	bl	_setCoreState
+1:
+	/* Decrement the counter */
+	subs	x6, x6, #1
+	b.le	3f
+	/* Shift the core mask to the next core */
+	lsl	x7, x7, #1
+	/* Continue */
+	b	2b
+3:
+	ldp	x18, x30, [sp], #16
+	ret
+
+/*
+ * Write a register in the DCFG block
+ * in:  x0 = offset
+ * in:  w1 = value to write
+ * uses x0, x1, x2
+ */
+_write_reg_dcfg:
+	ldr	x2, =NXP_DCFG_ADDR
+	str	w1, [x2, x0]
+	ret
+
+/*
+ * Read a register in the DCFG block
+ * in:  x0 = offset
+ * out: w0 = value read
+ * uses x0, x1, x2
+ */
+_read_reg_dcfg:
+	ldr	x2, =NXP_DCFG_ADDR
+	ldr	w1, [x2, x0]
+	mov	w0, w1
+	ret
+
+/*
+ * This function returns an mpidr value for a core, given a core_mask_lsb
+ * in:  x0 = core mask lsb
+ * out: x0 = affinity2:affinity1:affinity0, where affinity is 8-bits
+ * uses x0, x1
+ */
+get_mpidr_value:
+	/* Convert a core mask to an SoC core number */
+	clz	w0, w0
+	mov	w1, #31
+	sub	w0, w1, w0
+
+	/* Get the mpidr core number from the SoC core number */
+	mov	w1, wzr
+	tst	x0, #1
+	b.eq	1f
+	orr	w1, w1, #1
+1:
+	/* Extract the cluster number */
+	lsr	w0, w0, #1
+	orr	w0, w1, w0, lsl #8
+
+	ret
+
+/*
+ * This function returns the redistributor base address for the core specified
+ * in x1
+ * in:  x0 - core mask lsb of specified core
+ * out: x0 = redistributor rd base address for specified core
+ * uses x0, x1, x2
+ */
+get_gic_rd_base:
+	/* Get the 0-based core number */
+	clz	w1, w0
+	mov	w2, #0x20
+	sub	w2, w2, w1
+	sub	w2, w2, #1
+
+	/* x2 = core number / loop counter */
+	ldr	x0, =NXP_GICR_ADDR
+	mov	x1, #GIC_RD_OFFSET
+2:
+	cbz	x2, 1f
+	add	x0, x0, x1
+	sub	x2, x2, #1
+	b	2b
+1:
+	ret
+
+/*
+ * This function returns the redistributor base address for the core specified
+ * in x1
+ * in:  x0 - core mask lsb of specified core
+ * out: x0 = redistributor sgi base address for specified core
+ * uses x0, x1, x2
+ */
+get_gic_sgi_base:
+	/* Get the 0-based core number */
+	clz	w1, w0
+	mov	w2, #0x20
+	sub	w2, w2, w1
+	sub	w2, w2, #1
+
+	/* x2 = core number / loop counter */
+	ldr	x0, =NXP_GICR_SGI_ADDR
+	mov	x1, #GIC_SGI_OFFSET
+2:
+	cbz	x2, 1f
+	add	x0, x0, x1
+	sub	x2, x2, #1
+	b	2b
+1:
+	ret
+
+/*
+ * Write a register in the RESET block
+ * in:  x0 = offset
+ * in:  w1 = value to write
+ * uses x0, x1, x2
+ */
+_write_reg_reset:
+	ldr	x2, =NXP_RESET_ADDR
+	str	w1, [x2, x0]
+	ret
+
+/*
+ * Read a register in the RESET block
+ * in:  x0 = offset
+ * out: w0 = value read
+ * uses x0, x1
+ */
+_read_reg_reset:
+	ldr	x1, =NXP_RESET_ADDR
+	ldr	w0, [x1, x0]
+	ret
diff --git a/plat/nxp/soc-ls1028a/aarch64/ls1028a_helpers.S b/plat/nxp/soc-ls1028a/aarch64/ls1028a_helpers.S
new file mode 100644
index 0000000..ec67529
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/aarch64/ls1028a_helpers.S
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+#include <platform_def.h>
+
+.globl	plat_secondary_cold_boot_setup
+.globl	plat_is_my_cpu_primary
+.globl	plat_reset_handler
+.globl  platform_mem_init
+
+func platform_mem1_init
+	ret
+endfunc platform_mem1_init
+
+func platform_mem_init
+	ret
+endfunc	platform_mem_init
+
+func apply_platform_errata
+	ret
+endfunc apply_platform_errata
+
+func plat_reset_handler
+	mov	x29, x30
+	bl	apply_platform_errata
+
+#if defined(IMAGE_BL31)
+	ldr	x0, =POLICY_SMMU_PAGESZ_64K
+	cbz	x0, 1f
+	/* Set the SMMU page size in the sACR register */
+	bl	_set_smmu_pagesz_64
+#endif
+1:
+	mov	x30, x29
+	ret
+endfunc plat_reset_handler
+
+/*
+ * void plat_secondary_cold_boot_setup (void);
+ *
+ * This function performs any platform specific actions
+ * needed for a secondary cpu after a cold reset e.g
+ * mark the cpu's presence, mechanism to place it in a
+ * holding pen etc.
+ */
+func plat_secondary_cold_boot_setup
+	/* ls1028a does not do cold boot for secondary CPU */
+cb_panic:
+	b	cb_panic
+endfunc plat_secondary_cold_boot_setup
+
+/*
+ * unsigned int plat_is_my_cpu_primary (void);
+ *
+ * Find out whether the current cpu is the primary
+ * cpu.
+ */
+func plat_is_my_cpu_primary
+	mrs	x0, mpidr_el1
+	and	x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+	cmp	x0, 0x0
+	cset	w0, eq
+	ret
+endfunc plat_is_my_cpu_primary
diff --git a/plat/nxp/soc-ls1028a/include/soc.h b/plat/nxp/soc-ls1028a/include/soc.h
new file mode 100644
index 0000000..b1d044a
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/include/soc.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOC_H
+#define	SOC_H
+
+/* Chassis specific defines - common across SoC's of a particular platform */
+#include <dcfg_lsch3.h>
+#include <soc_default_base_addr.h>
+#include <soc_default_helper_macros.h>
+
+/*
+ * SVR Definition of LS1028A
+ * (not include major and minor rev)
+ * These info is listed in Table B-6. DCFG differences
+ * between LS1028A and LS1027A of LS1028ARM(Reference Manual)
+ */
+#define SVR_LS1017AN		0x870B25
+#define SVR_LS1017AE		0x870B24
+#define SVR_LS1018AN		0x870B21
+#define SVR_LS1018AE		0x870B20
+#define SVR_LS1027AN		0x870B05
+#define SVR_LS1027AE		0x870B04
+#define SVR_LS1028AN		0x870B01
+#define SVR_LS1028AE		0x870B00
+
+/* Number of cores in platform */
+#define PLATFORM_CORE_COUNT		2
+#define NUMBER_OF_CLUSTERS		1
+#define CORES_PER_CLUSTER		2
+
+/* Set to 0 if the clusters are not symmetrical */
+#define SYMMETRICAL_CLUSTERS		1
+
+#define NUM_DRAM_REGIONS		3
+
+#define	NXP_DRAM0_ADDR			0x80000000
+#define NXP_DRAM0_MAX_SIZE		0x80000000	/* 2GB */
+
+#define NXP_DRAM1_ADDR			0x2080000000
+#define NXP_DRAM1_MAX_SIZE		0x1F80000000	/* 126G */
+
+#define NXP_DRAM2_ADDR			0x6000000000
+#define NXP_DRAM2_MAX_SIZE		0x2000000000	/* 128G */
+
+/* DRAM0 Size defined in platform_def.h */
+#define	NXP_DRAM0_SIZE			PLAT_DEF_DRAM0_SIZE
+
+/* CCSR space memory Map  */
+#undef NXP_UART_ADDR
+#define NXP_UART_ADDR			0x021C0500
+
+#undef NXP_UART1_ADDR
+#define NXP_UART1_ADDR			0x021C0600
+
+#undef NXP_WDOG1_TZ_ADDR
+#define NXP_WDOG1_TZ_ADDR		0x023C0000
+
+#undef NXP_GICR_ADDR
+#define NXP_GICR_ADDR			0x06040000
+
+#undef NXP_GICR_SGI_ADDR
+#define NXP_GICR_SGI_ADDR		0x06050000
+
+/* EPU register offsets and values */
+#define EPU_EPGCR_OFFSET              0x0
+#define EPU_EPIMCR10_OFFSET           0x128
+#define EPU_EPCTR10_OFFSET            0xa28
+#define EPU_EPCCR10_OFFSET            0x828
+#define EPU_EPCCR10_VAL               0xb2800000
+#define EPU_EPIMCR10_VAL              0xba000000
+#define EPU_EPCTR10_VAL               0x0
+#define EPU_EPGCR_VAL                 (1 << 31)
+
+/* PORSR1 */
+#define PORSR1_RCW_MASK		0x07800000
+#define PORSR1_RCW_SHIFT	23
+
+#define SDHC1_VAL		0x8
+#define SDHC2_VAL		0x9
+#define I2C1_VAL		0xa
+#define FLEXSPI_NAND2K_VAL	0xc
+#define FLEXSPI_NAND4K_VAL	0xd
+#define FLEXSPI_NOR		0xf
+
+/*
+ * Required LS standard platform porting definitions
+ * for CCI-400
+ */
+#define NXP_CCI_CLUSTER0_SL_IFACE_IX	4
+
+/* Defines required for using XLAT tables from ARM common code */
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ull << 40)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ull << 40)
+
+/* Clock Divisors */
+#define NXP_PLATFORM_CLK_DIVIDER	1
+#define NXP_UART_CLK_DIVIDER		2
+
+/* dcfg register offsets and values */
+#define DCFG_DEVDISR2_ENETC		(1 << 31)
+
+#define MPIDR_AFFINITY0_MASK		0x00FF
+#define MPIDR_AFFINITY1_MASK		0xFF00
+#define CPUECTLR_DISABLE_TWALK_PREFETCH	0x4000000000
+#define CPUECTLR_INS_PREFETCH_MASK	0x1800000000
+#define CPUECTLR_DAT_PREFETCH_MASK	0x0300000000
+#define OSDLR_EL1_DLK_LOCK		0x1
+#define CNTP_CTL_EL0_EN			0x1
+#define CNTP_CTL_EL0_IMASK		0x2
+
+#define SYSTEM_PWR_DOMAINS	1
+#define PLAT_NUM_PWR_DOMAINS	(PLATFORM_CORE_COUNT + \
+				 NUMBER_OF_CLUSTERS  + \
+				 SYSTEM_PWR_DOMAINS)
+
+/* Power state coordination occurs at the system level */
+#define PLAT_PD_COORD_LVL	MPIDR_AFFLVL2
+#define PLAT_MAX_PWR_LVL	PLAT_PD_COORD_LVL
+
+/* Local power state for power domains in Run state */
+#define LS_LOCAL_STATE_RUN	PSCI_LOCAL_STATE_RUN
+
+/* define retention state */
+#define PLAT_MAX_RET_STATE	(PSCI_LOCAL_STATE_RUN + 1)
+#define LS_LOCAL_STATE_RET	PLAT_MAX_RET_STATE
+
+/* define power-down state */
+#define PLAT_MAX_OFF_STATE	(PLAT_MAX_RET_STATE + 1)
+#define LS_LOCAL_STATE_OFF	PLAT_MAX_OFF_STATE
+
+/* One cache line needed for bakery locks on ARM platforms */
+#define PLAT_PERCPU_BAKERY_LOCK_SIZE	(1 * CACHE_WRITEBACK_GRANULE)
+
+#ifndef __ASSEMBLER__
+/* CCI slave interfaces */
+static const int cci_map[] = {
+	NXP_CCI_CLUSTER0_SL_IFACE_IX,
+};
+void soc_init_lowlevel(void);
+void soc_init_percpu(void);
+void _soc_set_start_addr(unsigned long addr);
+void _set_platform_security(void);
+#endif
+
+#endif /* SOC_H */
diff --git a/plat/nxp/soc-ls1028a/ls1028ardb/ddr_init.c b/plat/nxp/soc-ls1028a/ls1028ardb/ddr_init.c
new file mode 100644
index 0000000..d82be51
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/ls1028ardb/ddr_init.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <string.h>
+
+#include <common/debug.h>
+#include <ddr.h>
+#include <lib/utils.h>
+
+#include <platform_def.h>
+
+#ifdef CONFIG_STATIC_DDR
+const struct ddr_cfg_regs static_1600 = {
+	.cs[0].config = U(0x80040422),
+	.cs[0].bnds = U(0xFF),
+	.sdram_cfg[0] = U(0xE50C0004),
+	.sdram_cfg[1] = U(0x401100),
+	.timing_cfg[0] = U(0x91550018),
+	.timing_cfg[1] = U(0xBAB40C42),
+	.timing_cfg[2] = U(0x48C111),
+	.timing_cfg[3] = U(0x1111000),
+	.timing_cfg[4] = U(0x2),
+	.timing_cfg[5] = U(0x3401400),
+	.timing_cfg[7] = U(0x23300000),
+	.timing_cfg[8] = U(0x2114600),
+	.sdram_mode[0] = U(0x3010210),
+	.sdram_mode[9] = U(0x4000000),
+	.sdram_mode[8] = U(0x500),
+	.sdram_mode[2] = U(0x10210),
+	.sdram_mode[10] = U(0x400),
+	.sdram_mode[11] = U(0x4000000),
+	.sdram_mode[4] = U(0x10210),
+	.sdram_mode[12] = U(0x400),
+	.sdram_mode[13] = U(0x4000000),
+	.sdram_mode[6] = U(0x10210),
+	.sdram_mode[14] = U(0x400),
+	.sdram_mode[15] = U(0x4000000),
+	.interval = U(0x18600618),
+	.data_init = U(0xdeadbeef),
+	.zq_cntl = U(0x8A090705),
+	.clk_cntl = U(0x2000000),
+	.cdr[0] = U(0x80040000),
+	.cdr[1] = U(0xA181),
+	.wrlvl_cntl[0] = U(0x8675F605),
+	.wrlvl_cntl[1] = U(0x6070700),
+	.wrlvl_cntl[2] = U(0x0000008),
+	.dq_map[0] = U(0x5b65b658),
+	.dq_map[1] = U(0xd96d8000),
+	.dq_map[2] = U(0),
+	.dq_map[3] = U(0x1600000),
+	.debug[28] = U(0x00700046),
+};
+
+unsigned long long board_static_ddr(struct ddr_info *priv)
+{
+	memcpy(&priv->ddr_reg, &static_1600, sizeof(static_1600));
+	return ULL(0x100000000);
+}
+
+#else
+
+static const struct rc_timing rcz[] = {
+	{1600, 8, 5},
+	{}
+};
+
+static const struct board_timing ram[] = {
+	{0x1f, rcz, 0x1020200, 0x00000003},
+};
+
+int ddr_board_options(struct ddr_info *priv)
+{
+	int ret;
+	struct memctl_opt *popts = &priv->opt;
+
+	ret = cal_board_params(priv, ram, ARRAY_SIZE(ram));
+	if (ret != 0) {
+		return ret;
+	}
+
+	popts->bstopre = U(0x40); /* precharge value */
+	popts->half_strength_drive_en = 1;
+	popts->cpo_sample = U(0x46);
+	popts->ddr_cdr1 = DDR_CDR1_DHC_EN |
+			  DDR_CDR1_ODT(DDR_CDR_ODT_80ohm);
+	popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) |
+			  DDR_CDR2_VREF_OVRD(70); /* Vref = 70% */
+
+	popts->addr_hash = 1; /* address hashing */
+	return 0;
+}
+
+/* DDR model number:  MT40A1G8SA-075:E */
+struct dimm_params ddr_raw_timing = {
+	.n_ranks = U(1),
+	.rank_density = ULL(4294967296),
+	.capacity = ULL(4294967296),
+	.primary_sdram_width = U(32),
+	.ec_sdram_width = U(4),
+	.rdimm = U(0),
+	.mirrored_dimm = U(0),
+	.n_row_addr = U(16),
+	.n_col_addr = U(10),
+	.bank_group_bits = U(2),
+	.edc_config = U(2),
+	.burst_lengths_bitmask = U(0x0c),
+	.tckmin_x_ps = 750,
+	.tckmax_ps = 1900,
+	.caslat_x = U(0x0001FFE00),
+	.taa_ps = 13500,
+	.trcd_ps = 13500,
+	.trp_ps = 13500,
+	.tras_ps = 32000,
+	.trc_ps = 45500,
+	.twr_ps = 15000,
+	.trfc1_ps = 350000,
+	.trfc2_ps = 260000,
+	.trfc4_ps = 160000,
+	.tfaw_ps = 21000,
+	.trrds_ps = 3000,
+	.trrdl_ps = 4900,
+	.tccdl_ps = 5000,
+	.refresh_rate_ps = U(7800000),
+	.dq_mapping[0] = U(0x16),
+	.dq_mapping[1] = U(0x36),
+	.dq_mapping[2] = U(0x16),
+	.dq_mapping[3] = U(0x36),
+	.dq_mapping[4] = U(0x16),
+	.dq_mapping[5] = U(0x36),
+	.dq_mapping[6] = U(0x16),
+	.dq_mapping[7] = U(0x36),
+	.dq_mapping[8] = U(0x16),
+	.dq_mapping[9] = U(0x0),
+	.dq_mapping[10] = U(0x0),
+	.dq_mapping[11] = U(0x0),
+	.dq_mapping[12] = U(0x0),
+	.dq_mapping[13] = U(0x0),
+	.dq_mapping[14] = U(0x0),
+	.dq_mapping[15] = U(0x0),
+	.dq_mapping[16] = U(0x0),
+	.dq_mapping[17] = U(0x0),
+	.dq_mapping_ors = U(0),
+	.rc = U(0x1f),
+};
+
+int ddr_get_ddr_params(struct dimm_params *pdimm,
+			    struct ddr_conf *conf)
+{
+	static const char dimm_model[] = "Fixed DDR on board";
+
+	conf->dimm_in_use[0] = 1;
+	memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params));
+	memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1);
+
+	return 1;
+}
+#endif
+
+int64_t init_ddr(void)
+{
+	struct ddr_info info;
+	struct sysinfo sys;
+	int64_t dram_size;
+
+	zeromem(&sys, sizeof(sys));
+	get_clocks(&sys);
+	debug("platform clock %lu\n", sys.freq_platform);
+	debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0);
+
+	zeromem(&info, sizeof(struct ddr_info));
+	info.num_ctlrs = 1;
+	info.dimm_on_ctlr = 1;
+	info.clk = get_ddr_freq(&sys, 0);
+	info.ddr[0] = (void *)NXP_DDR_ADDR;
+
+	dram_size = dram_init(&info);
+
+	if (dram_size < 0) {
+		ERROR("DDR init failed.\n");
+	}
+
+	return dram_size;
+}
diff --git a/plat/nxp/soc-ls1028a/ls1028ardb/plat_def.h b/plat/nxp/soc-ls1028a/ls1028ardb/plat_def.h
new file mode 100644
index 0000000..63c0219
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/ls1028ardb/plat_def.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DEF_H
+#define PLAT_DEF_H
+
+#include <arch.h>
+#include <cortex_a72.h>
+/*
+ * Required without TBBR.
+ * To include the defines for DDR PHY
+ * Images.
+ */
+#include <tbbr_img_def.h>
+
+#include <policy.h>
+#include <soc.h>
+
+
+#define NXP_SYSCLK_FREQ		100000000
+#define NXP_DDRCLK_FREQ		100000000
+
+/* UART related definition */
+#define NXP_CONSOLE_ADDR	NXP_UART_ADDR
+#define NXP_CONSOLE_BAUDRATE	115200
+
+#define NXP_SPD_EEPROM0		0x51
+
+/* Size of cacheable stacks */
+#if defined(IMAGE_BL2)
+#if defined(TRUSTED_BOARD_BOOT)
+#define PLATFORM_STACK_SIZE	0x2000
+#else
+#define PLATFORM_STACK_SIZE	0x1000
+#endif
+#elif defined(IMAGE_BL31)
+#define PLATFORM_STACK_SIZE	0x1000
+#endif
+
+/* SD block buffer */
+#define NXP_SD_BLOCK_BUF_SIZE	(0xC000)
+
+#ifdef SD_BOOT
+#define BL2_LIMIT		(NXP_OCRAM_ADDR + NXP_OCRAM_SIZE \
+				- NXP_SD_BLOCK_BUF_SIZE)
+#else
+#define BL2_LIMIT		(NXP_OCRAM_ADDR + NXP_OCRAM_SIZE)
+#endif
+#define BL2_TEXT_LIMIT		(BL2_LIMIT)
+
+/* IO defines as needed by IO driver framework */
+#define MAX_IO_DEVICES		4
+#define MAX_IO_BLOCK_DEVICES	1
+#define MAX_IO_HANDLES		4
+
+#define BL31_WDOG_SEC		89
+
+/*
+ * Define properties of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+#define PLAT_LS_G1S_IRQ_PROPS(grp) \
+	INTR_PROP_DESC(BL32_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE)
+
+/* SGI 15 and Secure watchdog interrupts assigned to Group 0 */
+#define PLAT_LS_G0_IRQ_PROPS(grp)	\
+	INTR_PROP_DESC(BL31_WDOG_SEC, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_EDGE), \
+	INTR_PROP_DESC(15, GIC_HIGHEST_SEC_PRIORITY, grp, \
+			GIC_INTR_CFG_LEVEL)
+#endif /* PLAT_DEF_H */
diff --git a/plat/nxp/soc-ls1028a/ls1028ardb/platform.c b/plat/nxp/soc-ls1028a/ls1028ardb/platform.c
new file mode 100644
index 0000000..65d508c
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/ls1028ardb/platform.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2020-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat_common.h>
+
+#pragma weak board_enable_povdd
+#pragma weak board_disable_povdd
+
+bool board_enable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+	return true;
+#else
+	return false;
+#endif
+}
+
+bool board_disable_povdd(void)
+{
+#ifdef CONFIG_POVDD_ENABLE
+	return true;
+#else
+	return false;
+#endif
+}
diff --git a/plat/nxp/soc-ls1028a/ls1028ardb/platform.mk b/plat/nxp/soc-ls1028a/ls1028ardb/platform.mk
new file mode 100644
index 0000000..c455000
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/ls1028ardb/platform.mk
@@ -0,0 +1,33 @@
+#
+# Copyright 2020-2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Board-specific build parameters
+BOOT_MODE	?=	flexspi_nor
+BOARD		:=	ls1028ardb
+POVDD_ENABLE	:=	no
+WARM_BOOT	:=	no
+
+# DDR build parameters
+NUM_OF_DDRC		:=	1
+CONFIG_DDR_NODIMM	:=	1
+DDR_ECC_EN		:=	yes
+
+# On-board flash
+FLASH_TYPE	:=	MT35XU02G
+XSPI_FLASH_SZ	:=	0x10000000
+
+BL2_SOURCES	+=	${BOARD_PATH}/ddr_init.c \
+			${BOARD_PATH}/platform.c
+
+SUPPORTED_BOOT_MODE	:=	flexspi_nor	\
+				sd		\
+				emmc
+
+# Add platform board build info
+include plat/nxp/common/plat_make_helper/plat_common_def.mk
+
+# Add SoC build info
+include plat/nxp/soc-ls1028a/soc.mk
diff --git a/plat/nxp/soc-ls1028a/ls1028ardb/platform_def.h b/plat/nxp/soc-ls1028a/ls1028ardb/platform_def.h
new file mode 100644
index 0000000..bbad293
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/ls1028ardb/platform_def.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <plat_def.h>
+#include <plat_default_def.h>
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/nxp/soc-ls1028a/ls1028ardb/policy.h b/plat/nxp/soc-ls1028a/ls1028ardb/policy.h
new file mode 100644
index 0000000..67a8b45
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/ls1028ardb/policy.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2020-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef POLICY_H
+#define	POLICY_H
+
+/*
+ * Set this to 0x0 to leave the default SMMU page size in sACR
+ * Set this to 0x1 to change the SMMU page size to 64K
+ */
+#define POLICY_SMMU_PAGESZ_64K 0x1
+
+#endif /* POLICY_H */
diff --git a/plat/nxp/soc-ls1028a/soc.c b/plat/nxp/soc-ls1028a/soc.c
new file mode 100644
index 0000000..4f67154
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/soc.c
@@ -0,0 +1,420 @@
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <endian.h>
+
+#include <arch.h>
+#include <caam.h>
+#include <cassert.h>
+#include <cci.h>
+#include <common/debug.h>
+#include <dcfg.h>
+#include <i2c.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <ls_interconnect.h>
+#include <mmio.h>
+#if TRUSTED_BOARD_BOOT
+#include <nxp_smmu.h>
+#endif
+#include <nxp_timer.h>
+#ifdef CONFIG_OCRAM_ECC_EN
+#include <ocram.h>
+#endif
+#include <plat_console.h>
+#include <plat_gic.h>
+#include <plat_tzc400.h>
+#include <pmu.h>
+#include <scfg.h>
+#if defined(NXP_SFP_ENABLED)
+#include <sfp.h>
+#endif
+
+#include <errata.h>
+#include "plat_common.h"
+#include "platform_def.h"
+#include "soc.h"
+
+static dcfg_init_info_t dcfg_init_data = {
+	.g_nxp_dcfg_addr = NXP_DCFG_ADDR,
+	.nxp_sysclk_freq = NXP_SYSCLK_FREQ,
+	.nxp_ddrclk_freq = NXP_DDRCLK_FREQ,
+	.nxp_plat_clk_divider = NXP_PLATFORM_CLK_DIVIDER,
+};
+
+static struct soc_type soc_list[] =  {
+	SOC_ENTRY(LS1017AN, LS1017AN, 1, 1),
+	SOC_ENTRY(LS1017AE, LS1017AE, 1, 1),
+	SOC_ENTRY(LS1018AN, LS1018AN, 1, 1),
+	SOC_ENTRY(LS1018AE, LS1018AE, 1, 1),
+	SOC_ENTRY(LS1027AN, LS1027AN, 1, 2),
+	SOC_ENTRY(LS1027AE, LS1027AE, 1, 2),
+	SOC_ENTRY(LS1028AN, LS1028AN, 1, 2),
+	SOC_ENTRY(LS1028AE, LS1028AE, 1, 2),
+};
+
+CASSERT(NUMBER_OF_CLUSTERS && NUMBER_OF_CLUSTERS <= 256,
+	assert_invalid_ls1028a_cluster_count);
+
+/*
+ * Function returns the base counter frequency
+ * after reading the first entry at CNTFID0 (0x20 offset).
+ *
+ * Function is used by:
+ *   1. ARM common code for PSCI management.
+ *   2. ARM Generic Timer init.
+ *
+ */
+unsigned int plat_get_syscnt_freq2(void)
+{
+	unsigned int counter_base_frequency;
+	/*
+	 * Below register specifies the base frequency of the system counter.
+	 * As per NXP Board Manuals:
+	 * The system counter always works with SYS_REF_CLK/4 frequency clock.
+	 */
+	counter_base_frequency = mmio_read_32(NXP_TIMER_ADDR + CNTFID_OFF);
+
+	return counter_base_frequency;
+}
+
+#ifdef IMAGE_BL2
+void soc_preload_setup(void)
+{
+}
+
+void soc_early_init(void)
+{
+	uint8_t num_clusters, cores_per_cluster;
+
+#ifdef CONFIG_OCRAM_ECC_EN
+	ocram_init(NXP_OCRAM_ADDR, NXP_OCRAM_SIZE);
+#endif
+	dcfg_init(&dcfg_init_data);
+	enable_timer_base_to_cluster(NXP_PMU_ADDR);
+	enable_core_tb(NXP_PMU_ADDR);
+	dram_regions_info_t *dram_regions_info = get_dram_regions_info();
+
+#ifdef POLICY_FUSE_PROVISION
+	gpio_init(&gpio_init_data);
+	sec_init(NXP_CAAM_ADDR);
+#endif
+
+#if LOG_LEVEL > 0
+	/* Initialize the console to provide early debug support */
+	plat_console_init(NXP_CONSOLE_ADDR,
+				NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE);
+#endif
+	enum  boot_device dev = get_boot_dev();
+	/*
+	 * Mark the buffer for SD in OCRAM as non secure.
+	 * The buffer is assumed to be at end of OCRAM for
+	 * the logic below to calculate TZPC programming
+	 */
+	if (dev == BOOT_DEVICE_EMMC || dev == BOOT_DEVICE_SDHC2_EMMC) {
+		/*
+		 * Calculate the region in OCRAM which is secure
+		 * The buffer for SD needs to be marked non-secure
+		 * to allow SD to do DMA operations on it
+		 */
+		uint32_t secure_region = (NXP_OCRAM_SIZE - NXP_SD_BLOCK_BUF_SIZE);
+		uint32_t mask = secure_region/TZPC_BLOCK_SIZE;
+
+		mmio_write_32(NXP_OCRAM_TZPC_ADDR, mask);
+
+		/* Add the entry for buffer in MMU Table */
+		mmap_add_region(NXP_SD_BLOCK_BUF_ADDR, NXP_SD_BLOCK_BUF_ADDR,
+				NXP_SD_BLOCK_BUF_SIZE, MT_DEVICE | MT_RW | MT_NS);
+	}
+
+#if TRUSTED_BOARD_BOOT
+	uint32_t mode;
+
+	sfp_init(NXP_SFP_ADDR);
+
+	/*
+	 * For secure boot disable SMMU.
+	 * Later when platform security policy comes in picture,
+	 * this might get modified based on the policy
+	 */
+	if (check_boot_mode_secure(&mode) == true) {
+		bypass_smmu(NXP_SMMU_ADDR);
+	}
+
+	/*
+	 * For Mbedtls currently crypto is not supported via CAAM
+	 * enable it when that support is there. In tbbr.mk
+	 * the CAAM_INTEG is set as 0.
+	 */
+#ifndef MBEDTLS_X509
+	/* Initialize the crypto accelerator if enabled */
+	if (is_sec_enabled()) {
+		sec_init(NXP_CAAM_ADDR);
+	} else {
+		INFO("SEC is disabled.\n");
+	}
+#endif
+#endif
+
+	/* Set eDDRTQ for DDR performance */
+	scfg_setbits32((void *)(NXP_SCFG_ADDR + 0x210), 0x1f1f1f1f);
+
+	soc_errata();
+
+	/*
+	 * Initialize Interconnect for this cluster during cold boot.
+	 * No need for locks as no other CPU is active.
+	 */
+	cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map));
+
+	/*
+	 * Enable Interconnect coherency for the primary CPU's cluster.
+	 */
+	get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+	plat_ls_interconnect_enter_coherency(num_clusters);
+
+	delay_timer_init(NXP_TIMER_ADDR);
+	i2c_init(NXP_I2C_ADDR);
+	dram_regions_info->total_dram_size = init_ddr();
+}
+
+void soc_bl2_prepare_exit(void)
+{
+#if defined(NXP_SFP_ENABLED) && defined(DISABLE_FUSE_WRITE)
+	set_sfp_wr_disable();
+#endif
+}
+
+/*
+ * This function returns the boot device based on RCW_SRC
+ */
+enum boot_device get_boot_dev(void)
+{
+	enum boot_device src = BOOT_DEVICE_NONE;
+	uint32_t porsr1;
+	uint32_t rcw_src;
+
+	porsr1 = read_reg_porsr1();
+
+	rcw_src = (porsr1 & PORSR1_RCW_MASK) >> PORSR1_RCW_SHIFT;
+	switch (rcw_src) {
+	case FLEXSPI_NOR:
+		src = BOOT_DEVICE_FLEXSPI_NOR;
+		INFO("RCW BOOT SRC is FLEXSPI NOR\n");
+		break;
+	case FLEXSPI_NAND2K_VAL:
+	case FLEXSPI_NAND4K_VAL:
+		INFO("RCW BOOT SRC is FLEXSPI NAND\n");
+		src = BOOT_DEVICE_FLEXSPI_NAND;
+		break;
+	case SDHC1_VAL:
+		src = BOOT_DEVICE_EMMC;
+		INFO("RCW BOOT SRC is SD\n");
+		break;
+	case SDHC2_VAL:
+		src = BOOT_DEVICE_SDHC2_EMMC;
+		INFO("RCW BOOT SRC is EMMC\n");
+		break;
+	default:
+		break;
+	}
+
+	return src;
+}
+
+/*
+ * This function sets up access permissions on memory regions
+ ****************************************************************************/
+void soc_mem_access(void)
+{
+	dram_regions_info_t *info_dram_regions = get_dram_regions_info();
+	struct tzc400_reg tzc400_reg_list[MAX_NUM_TZC_REGION];
+	int dram_idx = 0;
+	/* index 0 is reserved for region-0 */
+	int index = 1;
+
+	for (dram_idx = 0; dram_idx < info_dram_regions->num_dram_regions;
+	     dram_idx++) {
+		if (info_dram_regions->region[dram_idx].size == 0) {
+			ERROR("DDR init failure, or");
+			ERROR("DRAM regions not populated correctly.\n");
+			break;
+		}
+
+		index = populate_tzc400_reg_list(tzc400_reg_list,
+				dram_idx, index,
+				info_dram_regions->region[dram_idx].addr,
+				info_dram_regions->region[dram_idx].size,
+				NXP_SECURE_DRAM_SIZE, NXP_SP_SHRD_DRAM_SIZE);
+	}
+
+	mem_access_setup(NXP_TZC_ADDR, index, tzc400_reg_list);
+}
+
+#else
+
+static unsigned char _power_domain_tree_desc[NUMBER_OF_CLUSTERS + 2];
+/*
+ * This function dynamically constructs the topology according to
+ *  SoC Flavor and returns it.
+ */
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	uint8_t num_clusters, cores_per_cluster;
+	unsigned int i;
+
+	get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+	/*
+	 * The highest level is the system level. The next level is constituted
+	 * by clusters and then cores in clusters.
+	 */
+	_power_domain_tree_desc[0] = 1;
+	_power_domain_tree_desc[1] = num_clusters;
+
+	for (i = 0; i < _power_domain_tree_desc[1]; i++)
+		_power_domain_tree_desc[i + 2] = cores_per_cluster;
+
+	return _power_domain_tree_desc;
+}
+
+/*
+ * This function returns the core count within the cluster corresponding to
+ * `mpidr`.
+ */
+unsigned int plat_ls_get_cluster_core_count(u_register_t mpidr)
+{
+	uint8_t num_clusters, cores_per_cluster;
+
+	get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+	return num_clusters;
+}
+
+void soc_early_platform_setup2(void)
+{
+	dcfg_init(&dcfg_init_data);
+	/* Initialize system level generic timer for Socs */
+	delay_timer_init(NXP_TIMER_ADDR);
+
+#if LOG_LEVEL > 0
+	/* Initialize the console to provide early debug support */
+	plat_console_init(NXP_CONSOLE_ADDR,
+				NXP_UART_CLK_DIVIDER, NXP_CONSOLE_BAUDRATE);
+#endif
+}
+
+void soc_platform_setup(void)
+{
+	/* Initialize the GIC driver, cpu and distributor interfaces */
+	static uintptr_t target_mask_array[PLATFORM_CORE_COUNT];
+	static interrupt_prop_t ls_interrupt_props[] = {
+		PLAT_LS_G1S_IRQ_PROPS(INTR_GROUP1S),
+		PLAT_LS_G0_IRQ_PROPS(INTR_GROUP0)
+	};
+
+	plat_ls_gic_driver_init(NXP_GICD_ADDR, NXP_GICR_ADDR,
+				PLATFORM_CORE_COUNT,
+				ls_interrupt_props,
+				ARRAY_SIZE(ls_interrupt_props),
+				target_mask_array,
+				plat_core_pos);
+
+	plat_ls_gic_init();
+	enable_init_timer();
+}
+
+/* This function initializes the soc from the BL31 module */
+void soc_init(void)
+{
+	uint8_t num_clusters, cores_per_cluster;
+
+	get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+
+	/* Low-level init of the soc */
+	soc_init_lowlevel();
+	_init_global_data();
+	soc_init_percpu();
+	_initialize_psci();
+
+	/*
+	 * Initialize Interconnect for this cluster during cold boot.
+	 * No need for locks as no other CPU is active.
+	 */
+	cci_init(NXP_CCI_ADDR, cci_map, ARRAY_SIZE(cci_map));
+
+	/* Enable Interconnect coherency for the primary CPU's cluster. */
+	plat_ls_interconnect_enter_coherency(num_clusters);
+
+	/* Set platform security policies */
+	_set_platform_security();
+
+	/* Init SEC Engine which will be used by SiP */
+	if (is_sec_enabled()) {
+		sec_init(NXP_CAAM_ADDR);
+	} else {
+		INFO("SEC is disabled.\n");
+	}
+}
+
+#ifdef NXP_WDOG_RESTART
+static uint64_t wdog_interrupt_handler(uint32_t id, uint32_t flags,
+					  void *handle, void *cookie)
+{
+	uint8_t data = WDOG_RESET_FLAG;
+
+	wr_nv_app_data(WDT_RESET_FLAG_OFFSET,
+			(uint8_t *)&data, sizeof(data));
+
+	mmio_write_32(NXP_RST_ADDR + RSTCNTL_OFFSET, SW_RST_REQ_INIT);
+
+	return 0;
+}
+#endif
+
+void soc_runtime_setup(void)
+{
+#ifdef NXP_WDOG_RESTART
+	request_intr_type_el3(BL31_NS_WDOG_WS1, wdog_interrupt_handler);
+#endif
+}
+
+/* This function returns the total number of cores in the SoC. */
+unsigned int get_tot_num_cores(void)
+{
+	uint8_t num_clusters, cores_per_cluster;
+
+	get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+	return (num_clusters * cores_per_cluster);
+}
+
+/* This function returns the PMU IDLE Cluster mask. */
+unsigned int get_pmu_idle_cluster_mask(void)
+{
+	uint8_t num_clusters, cores_per_cluster;
+
+	get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+	return ((1 << num_clusters) - 2);
+}
+
+/* This function returns the PMU Flush Cluster mask. */
+unsigned int get_pmu_flush_cluster_mask(void)
+{
+	uint8_t num_clusters, cores_per_cluster;
+
+	get_cluster_info(soc_list, ARRAY_SIZE(soc_list), &num_clusters, &cores_per_cluster);
+	return ((1 << num_clusters) - 2);
+}
+
+/* This function returns the PMU idle core mask. */
+unsigned int get_pmu_idle_core_mask(void)
+{
+	return ((1 << get_tot_num_cores()) - 2);
+}
+
+/* Function to return the SoC SYS CLK */
+unsigned int get_sys_clk(void)
+{
+	return NXP_SYSCLK_FREQ;
+}
+#endif
diff --git a/plat/nxp/soc-ls1028a/soc.def b/plat/nxp/soc-ls1028a/soc.def
new file mode 100644
index 0000000..e133982
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/soc.def
@@ -0,0 +1,95 @@
+#
+# Copyright 2018-2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+#------------------------------------------------------------------------------
+#
+# This file contains the basic architecture definitions that drive the build
+#
+# -----------------------------------------------------------------------------
+
+CORE_TYPE	:=	a72
+
+CACHE_LINE	:=	6
+
+# Set to GIC400 or GIC500
+GIC		:=	GIC500
+
+# Set to CCI400 or CCN504 or CCN508
+INTERCONNECT	:=	CCI400
+
+# Layerscape chassis level - set to 3=LSCH3 or 2=LSCH2
+CHASSIS		:=	3_2
+
+# TZC used is TZC380 or TZC400
+TZC_ID		:=	TZC400
+
+# CONSOLE is NS16550 or PL011
+CONSOLE		:=	NS16550
+
+# DDR PHY generation to be used
+PLAT_DDR_PHY	:=	PHY_GEN1
+
+PHYS_SYS	:=	64
+
+# Max Size of CSF header. Required to define BL2 TEXT LIMIT in soc.def
+# Input to CST create_hdr_esbc tool
+CSF_HDR_SZ	:=	0x3000
+
+# In IMAGE_BL2, compile time flag for handling Cache coherency
+# with CAAM for BL2 running from OCRAM
+SEC_MEM_NON_COHERENT	:=	yes
+
+# OCRAM MAP for BL2
+# Before BL2
+# 0x18000000 - 0x18009fff -> Used by ROM code
+# 0x1800a000 - 0x1800dfff -> CSF header for BL2
+# For FlexSFlexSPI boot
+# 0x1800e000 - 0x18040000 -> Reserved for BL2 binary
+# For SD boot
+# 0x1800e000 - 0x18030000 -> Reserved for BL2 binary
+# 0x18030000 - 0x18040000 -> Reserved for SD buffer
+OCRAM_START_ADDR	:=	0x18000000
+OCRAM_SIZE		:=	0x40000
+
+# Area of OCRAM reserved by ROM code
+NXP_ROM_RSVD	:=	0xa000
+
+# Location of BL2 on OCRAM
+BL2_BASE_ADDR	:=	$(shell echo $$(( $(OCRAM_START_ADDR) + $(NXP_ROM_RSVD) + $(CSF_HDR_SZ) )))
+
+# Covert to HEX to be used by create_pbl.mk
+BL2_BASE	:=	$(shell echo "0x"$$(echo "obase=16; ${BL2_BASE_ADDR}" | bc))
+
+# BL2_HDR_LOC is at  (BL2_BASE + NXP_ROM_RSVD)
+# This value BL2_HDR_LOC + CSF_HDR_SZ should not
+# overalp with BL2_BASE
+# Input to CST create_hdr_isbc tool
+BL2_HDR_LOC	:=	0x1800A000
+
+# SoC ERRATAS to be enabled
+ERRATA_SOC_A008850	:=	1
+
+ERRATA_DDR_A009803	:=	1
+ERRATA_DDR_A009942	:=	1
+ERRATA_DDR_A010165	:=	1
+
+# Enable dynamic memory mapping
+PLAT_XLAT_TABLES_DYNAMIC	:=	1
+
+# Define Endianness of each module
+NXP_GUR_ENDIANNESS	:=	LE
+NXP_DDR_ENDIANNESS	:=	LE
+NXP_SEC_ENDIANNESS	:=	LE
+NXP_SFP_ENDIANNESS	:=	LE
+NXP_SNVS_ENDIANNESS	:=	LE
+NXP_ESDHC_ENDIANNESS	:=	LE
+NXP_QSPI_ENDIANNESS	:=	LE
+NXP_FSPI_ENDIANNESS	:=	LE
+
+NXP_SFP_VER		:=	3_4
+
+# OCRAM ECC Enabled
+OCRAM_ECC_EN		:=	yes
diff --git a/plat/nxp/soc-ls1028a/soc.mk b/plat/nxp/soc-ls1028a/soc.mk
new file mode 100644
index 0000000..92d8e98
--- /dev/null
+++ b/plat/nxp/soc-ls1028a/soc.mk
@@ -0,0 +1,113 @@
+#
+# Copyright 2020-2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# SoC-specific build parameters
+SOC			:=	ls1028a
+PLAT_PATH		:=	plat/nxp
+PLAT_COMMON_PATH	:=	plat/nxp/common
+PLAT_DRIVERS_PATH	:=	drivers/nxp
+PLAT_SOC_PATH		:=	${PLAT_PATH}/soc-${SOC}
+BOARD_PATH		:=	${PLAT_SOC_PATH}/${BOARD}
+
+# Get SoC-specific definitions
+include ${PLAT_SOC_PATH}/soc.def
+include ${PLAT_COMMON_PATH}/plat_make_helper/soc_common_def.mk
+include ${PLAT_COMMON_PATH}/plat_make_helper/plat_build_macros.mk
+
+ifeq (${TRUSTED_BOARD_BOOT},1)
+$(eval $(call SET_NXP_MAKE_FLAG,SMMU_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,SFP_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL2))
+SECURE_BOOT := yes
+endif
+$(eval $(call SET_NXP_MAKE_FLAG,CRYPTO_NEEDED,BL_COMM))
+
+$(eval $(call SET_NXP_MAKE_FLAG,DCFG_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,TIMER_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,INTERCONNECT_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,GIC_NEEDED,BL31))
+$(eval $(call SET_NXP_MAKE_FLAG,CONSOLE_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,PMU_NEEDED,BL_COMM))
+$(eval $(call SET_NXP_MAKE_FLAG,DDR_DRIVER_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,TZASC_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,I2C_NEEDED,BL2))
+$(eval $(call SET_NXP_MAKE_FLAG,IMG_LOADR_NEEDED,BL2))
+
+# Selecting PSCI & SIP_SVC support
+$(eval $(call SET_NXP_MAKE_FLAG,PSCI_NEEDED,BL31))
+$(eval $(call SET_NXP_MAKE_FLAG,SIPSVC_NEEDED,BL31))
+
+PLAT_INCLUDES		+=	-I${PLAT_COMMON_PATH}/include/default\
+				-I${BOARD_PATH}\
+				-I${PLAT_COMMON_PATH}/include/default/ch_${CHASSIS}\
+				-I${PLAT_SOC_PATH}/include\
+				-I${PLAT_COMMON_PATH}/soc_errata
+
+ifeq (${SECURE_BOOT},yes)
+include ${PLAT_COMMON_PATH}/tbbr/tbbr.mk
+endif
+
+ifeq ($(WARM_BOOT),yes)
+include ${PLAT_COMMON_PATH}/warm_reset/warm_reset.mk
+endif
+
+ifeq (${NXP_NV_SW_MAINT_LAST_EXEC_DATA}, yes)
+include ${PLAT_COMMON_PATH}/nv_storage/nv_storage.mk
+endif
+
+ifeq (${PSCI_NEEDED}, yes)
+include ${PLAT_COMMON_PATH}/psci/psci.mk
+endif
+
+ifeq (${SIPSVC_NEEDED}, yes)
+include ${PLAT_COMMON_PATH}/sip_svc/sipsvc.mk
+endif
+
+ifeq (${DDR_FIP_IO_NEEDED}, yes)
+include ${PLAT_COMMON_PATH}/fip_handler/ddr_fip/ddr_fip_io.mk
+endif
+
+# For fuse-fip & fuse-programming
+ifeq (${FUSE_PROG}, 1)
+include ${PLAT_COMMON_PATH}/fip_handler/fuse_fip/fuse.mk
+endif
+
+ifeq (${IMG_LOADR_NEEDED},yes)
+include $(PLAT_COMMON_PATH)/img_loadr/img_loadr.mk
+endif
+
+# Adding source files for the above selected drivers.
+include ${PLAT_DRIVERS_PATH}/drivers.mk
+
+# Adding SoC specific files
+include ${PLAT_COMMON_PATH}/soc_errata/errata.mk
+
+PLAT_INCLUDES		+=	${NV_STORAGE_INCLUDES}\
+				${WARM_RST_INCLUDES}
+
+BL31_SOURCES		+=	${PLAT_SOC_PATH}/$(ARCH)/${SOC}.S\
+				${WARM_RST_BL31_SOURCES}\
+				${PSCI_SOURCES}\
+				${SIPSVC_SOURCES}\
+				${PLAT_COMMON_PATH}/$(ARCH)/bl31_data.S
+
+PLAT_BL_COMMON_SOURCES	+=	${PLAT_COMMON_PATH}/$(ARCH)/ls_helpers.S\
+				${PLAT_SOC_PATH}/aarch64/${SOC}_helpers.S\
+				${NV_STORAGE_SOURCES}\
+				${WARM_RST_BL_COMM_SOURCES}\
+				${PLAT_SOC_PATH}/soc.c
+
+ifeq (${TEST_BL31}, 1)
+BL31_SOURCES	+=	${PLAT_SOC_PATH}/$(ARCH)/bootmain64.S \
+			${PLAT_SOC_PATH}/$(ARCH)/nonboot64.S
+endif
+
+BL2_SOURCES		+=	${DDR_CNTLR_SOURCES}\
+				${TBBR_SOURCES}\
+				${FUSE_SOURCES}
+
+# Adding TFA setup files
+include ${PLAT_PATH}/common/setup/common.mk
diff --git a/plat/nxp/soc-lx2160a/erratas_soc.mk b/plat/nxp/soc-lx2160a/erratas_soc.mk
deleted file mode 100644
index 07bed03..0000000
--- a/plat/nxp/soc-lx2160a/erratas_soc.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Copyright 2020 NXP
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-# Platform Errata Build flags.
-# These should be enabled by the platform if the erratum workaround needs to be
-# applied.
-
-# Flag to apply erratum 50426 workaround during reset.
-ERRATA_SOC_A050426	?= 0
-
-# Process ERRATA_SOC_A050426 flag
-ifeq (${ERRATA_SOC_A050426}, 1)
-INCL_SOC_ERRATA_SOURCES	:= yes
-$(eval $(call add_define,ERRATA_SOC_A050426))
-endif
-
-ifeq (${INCL_SOC_ERRATA_SOURCES},yes)
-BL2_SOURCES	+= 	${PLAT_SOC_PATH}/erratas_soc.c
-endif
diff --git a/plat/nxp/soc-lx2160a/include/errata.h b/plat/nxp/soc-lx2160a/include/errata.h
deleted file mode 100644
index 937824a..0000000
--- a/plat/nxp/soc-lx2160a/include/errata.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright 2020 NXP
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef ERRATA_H
-#define ERRATA_H
-
-#ifdef ERRATA_SOC_A050426
-void erratum_a050426(void);
-#endif
-
-#endif /* ERRATA_H */
diff --git a/plat/nxp/soc-lx2160a/include/soc.h b/plat/nxp/soc-lx2160a/include/soc.h
index bd23620..7cc4a03 100644
--- a/plat/nxp/soc-lx2160a/include/soc.h
+++ b/plat/nxp/soc-lx2160a/include/soc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2020 NXP
+ * Copyright 2018-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -52,11 +52,10 @@
 #define FLEXSPI_NOR		0xf
 /* End: Macros used by soc.c: get_boot_dev */
 
-/* bits */
-/* SVR Definition */
-#define SVR_LX2160A		0x04
-#define SVR_LX2120A		0x14
-#define SVR_LX2080A		0x05
+/* SVR Definition (not include major and minor rev) */
+#define SVR_LX2160A		0x873601
+#define SVR_LX2120A		0x873621
+#define SVR_LX2080A		0x873603
 
 /* Number of cores in platform */
 /* Used by common code for array initialization */
diff --git a/plat/nxp/soc-lx2160a/soc.c b/plat/nxp/soc-lx2160a/soc.c
index e0a2fe9..2209fda 100644
--- a/plat/nxp/soc-lx2160a/soc.c
+++ b/plat/nxp/soc-lx2160a/soc.c
@@ -82,28 +82,6 @@
 	.master_to_rn_id_map = master_to_rn_id_map
 };
 
-/*******************************************************************************
- * This function returns the number of clusters in the SoC
- ******************************************************************************/
-static unsigned int get_num_cluster(void)
-{
-	const soc_info_t *soc_info = get_soc_info();
-	uint32_t num_clusters = NUMBER_OF_CLUSTERS;
-	unsigned int i;
-
-	for (i = 0U; i < ARRAY_SIZE(soc_list); i++) {
-		if (soc_list[i].personality == soc_info->personality) {
-			num_clusters = soc_list[i].num_clusters;
-			break;
-		}
-	}
-
-	VERBOSE("NUM of cluster = 0x%x\n", num_clusters);
-
-	return num_clusters;
-}
-
-
 /******************************************************************************
  * Function returns the base counter frequency
  * after reading the first entry at CNTFID0 (0x20 offset).
@@ -142,8 +120,10 @@
 static void soc_interconnect_config(void)
 {
 	unsigned long long val = 0x0U;
+	uint8_t num_clusters, cores_per_cluster;
 
-	uint32_t num_clusters = get_num_cluster();
+	get_cluster_info(soc_list, ARRAY_SIZE(soc_list),
+			&num_clusters, &cores_per_cluster);
 
 	if (num_clusters == 6U) {
 		ccn_init(&plat_six_cluster_ccn_desc);
@@ -271,9 +251,7 @@
 				MT_DEVICE | MT_RW | MT_NS);
 	}
 
-#ifdef ERRATA_SOC_A050426
-	erratum_a050426();
-#endif
+	soc_errata();
 
 #if (TRUSTED_BOARD_BOOT) || defined(POLICY_FUSE_PROVISION)
 	sfp_init(NXP_SFP_ADDR);
@@ -466,7 +444,12 @@
  ******************************************************************************/
 void soc_init(void)
 {
-	 /* low-level init of the soc */
+	uint8_t num_clusters, cores_per_cluster;
+
+	get_cluster_info(soc_list, ARRAY_SIZE(soc_list),
+			&num_clusters, &cores_per_cluster);
+
+	/* low-level init of the soc */
 	soc_init_start();
 	soc_init_percpu();
 	_init_global_data();
@@ -478,8 +461,6 @@
 		panic();
 	}
 
-	uint32_t num_clusters = get_num_cluster();
-
 	if (num_clusters == 6U) {
 		ccn_init(&plat_six_cluster_ccn_desc);
 	} else {
diff --git a/plat/nxp/soc-lx2160a/soc.def b/plat/nxp/soc-lx2160a/soc.def
index bd0dd15..24d1d13 100644
--- a/plat/nxp/soc-lx2160a/soc.def
+++ b/plat/nxp/soc-lx2160a/soc.def
@@ -91,7 +91,7 @@
 # Location of BL2 on OCRAM
 BL2_BASE_ADDR	:=	$(shell echo $$(( $(OCRAM_START_ADDR) + $(NXP_ROM_RSVD) + $(CSF_HDR_SZ) )))
 # Covert to HEX to be used by create_pbl.mk
-BL2_BASE	:=	$$(echo "obase=16; ${BL2_BASE_ADDR}" | bc)
+BL2_BASE	:=	$(shell echo "0x"$$(echo "obase=16; ${BL2_BASE_ADDR}" | bc))
 
 # BL2_HDR_LOC is at  (OCRAM_ADDR + NXP_ROM_RSVD)
 # This value BL2_HDR_LOC + CSF_HDR_SZ should not overalp with BL2_BASE
@@ -107,95 +107,5 @@
 # SoC Errata
 ERRATA_SOC_A050426	:= 1
 
-ifneq (${CACHE_LINE},)
-$(eval $(call add_define_val,PLATFORM_CACHE_LINE_SHIFT,${CACHE_LINE}))
-$(eval CACHE_WRITEBACK_GRANULE=$(shell echo $$((1 << $(CACHE_LINE)))))
-$(eval $(call add_define_val,CACHE_WRITEBACK_GRANULE,$(CACHE_WRITEBACK_GRANULE)))
-endif
-
-ifneq (${INTERCONNECT},)
-$(eval $(call add_define,NXP_HAS_CCN508))
-endif
-
-ifneq (${CHASSIS},)
-$(eval $(call add_define,CONFIG_CHASSIS_${CHASSIS}))
-endif
-
-ifneq (${PLAT_DDR_PHY},)
-$(eval $(call add_define,NXP_DDR_${PLAT_DDR_PHY}))
-endif
-
-ifneq (${PHYS_SYS},)
-$(eval $(call add_define,CONFIG_PHYS_64BIT))
-endif
-
-ifneq (${CSF_HDR_SZ},)
-$(eval $(call add_define_val,CSF_HDR_SZ,${CSF_HDR_SZ}))
-endif
-
-ifneq (${OCRAM_START_ADDR},)
-$(eval $(call add_define_val,NXP_OCRAM_ADDR,${OCRAM_START_ADDR}))
-endif
-
-ifneq (${OCRAM_SIZE},)
-$(eval $(call add_define_val,NXP_OCRAM_SIZE,${OCRAM_SIZE}))
-endif
-
-ifneq (${NXP_ROM_RSVD},)
-$(eval $(call add_define_val,NXP_ROM_RSVD,${NXP_ROM_RSVD}))
-endif
-
-ifneq (${BL2_BASE_ADDR},)
-$(eval $(call add_define_val,BL2_BASE,${BL2_BASE_ADDR}))
-endif
-
-ifeq (${SEC_MEM_NON_COHERENT},yes)
-$(eval $(call add_define,SEC_MEM_NON_COHERENT))
-endif
-
-ifneq (${NXP_ESDHC_ENDIANNESS},)
-$(eval $(call add_define,NXP_ESDHC_${NXP_ESDHC_ENDIANNESS}))
-endif
-
-ifneq (${NXP_SFP_VER},)
-$(eval $(call add_define,NXP_SFP_VER_${NXP_SFP_VER}))
-endif
-
-ifneq (${NXP_SFP_ENDIANNESS},)
-$(eval $(call add_define,NXP_SFP_${NXP_SFP_ENDIANNESS}))
-endif
-
-ifneq (${NXP_GPIO_ENDIANNESS},)
-$(eval $(call add_define,NXP_GPIO_${NXP_GPIO_ENDIANNESS}))
-endif
-
-ifneq (${NXP_SNVS_ENDIANNESS},)
-$(eval $(call add_define,NXP_SNVS_${NXP_SNVS_ENDIANNESS}))
-endif
-
-ifneq (${NXP_GUR_ENDIANNESS},)
-$(eval $(call add_define,NXP_GUR_${NXP_GUR_ENDIANNESS}))
-endif
-
-ifneq (${NXP_FSPI_ENDIANNESS},)
-$(eval $(call add_define,NXP_FSPI_${NXP_FSPI_ENDIANNESS}))
-endif
-
 # enable dynamic memory mapping
 PLAT_XLAT_TABLES_DYNAMIC :=	1
-
-ifneq (${NXP_SEC_ENDIANNESS},)
-$(eval $(call add_define,NXP_SEC_${NXP_SEC_ENDIANNESS}))
-endif
-
-ifneq (${NXP_DDR_ENDIANNESS},)
-$(eval $(call add_define,NXP_DDR_${NXP_DDR_ENDIANNESS}))
-endif
-
-ifneq (${NXP_DDR_INTLV_256B},)
-$(eval $(call add_define,NXP_DDR_INTLV_256B))
-endif
-
-ifneq (${PLAT_XLAT_TABLES_DYNAMIC},)
-$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC))
-endif
diff --git a/plat/nxp/soc-lx2160a/soc.mk b/plat/nxp/soc-lx2160a/soc.mk
index b9649b4..75a3af2 100644
--- a/plat/nxp/soc-lx2160a/soc.mk
+++ b/plat/nxp/soc-lx2160a/soc.mk
@@ -15,7 +15,7 @@
 
  # get SoC-specific defnitions
 include ${PLAT_SOC_PATH}/soc.def
-
+include ${PLAT_COMMON_PATH}/plat_make_helper/soc_common_def.mk
 include ${PLAT_COMMON_PATH}/plat_make_helper/plat_build_macros.mk
 
  # SoC-specific
@@ -99,7 +99,8 @@
 PLAT_INCLUDES		+=	-I${PLAT_COMMON_PATH}/include/default\
 				-I${BOARD_PATH}\
 				-I${PLAT_COMMON_PATH}/include/default/ch_${CHASSIS}\
-				-I${PLAT_SOC_PATH}/include
+				-I${PLAT_SOC_PATH}/include\
+				-I${PLAT_COMMON_PATH}/soc_errata
 
 ifeq (${SECURE_BOOT},yes)
 include ${PLAT_COMMON_PATH}/tbbr/tbbr.mk
@@ -138,7 +139,7 @@
 include ${PLAT_DRIVERS_PATH}/drivers.mk
 
  # Adding SoC specific files
-include ${PLAT_SOC_PATH}/erratas_soc.mk
+include ${PLAT_COMMON_PATH}/soc_errata/errata.mk
 
 PLAT_INCLUDES		+=	${NV_STORAGE_INCLUDES}\
 				${WARM_RST_INCLUDES}
diff --git a/plat/qemu/qemu/include/platform_def.h b/plat/qemu/qemu/include/platform_def.h
index fbcaa63..c02eff9 100644
--- a/plat/qemu/qemu/include/platform_def.h
+++ b/plat/qemu/qemu/include/platform_def.h
@@ -80,8 +80,8 @@
 #define SEC_ROM_BASE			0x00000000
 #define SEC_ROM_SIZE			0x00020000
 
-#define NS_DRAM0_BASE			0x40000000
-#define NS_DRAM0_SIZE			0x3de00000
+#define NS_DRAM0_BASE			ULL(0x40000000)
+#define NS_DRAM0_SIZE			ULL(0xc0000000)
 
 #define SEC_SRAM_BASE			0x0e000000
 #define SEC_SRAM_SIZE			0x00060000
diff --git a/plat/qti/common/inc/qti_cpu.h b/plat/qti/common/inc/qti_cpu.h
index 3eda02b..3316f7b 100644
--- a/plat/qti/common/inc/qti_cpu.h
+++ b/plat/qti/common/inc/qti_cpu.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,4 +13,10 @@
 /* KRYO-4xx Silver MIDR */
 #define QTI_KRYO4_SILVER_MIDR	0x517F805D
 
+/* KRYO-6xx Gold MIDR */
+#define QTI_KRYO6_GOLD_MIDR	0x412FD410
+
+/* KRYO-6xx Silver MIDR */
+#define QTI_KRYO6_SILVER_MIDR	0x412FD050
+
 #endif /* QTI_CPU_H */
diff --git a/plat/qti/common/src/aarch64/qti_kryo6_gold.S b/plat/qti/common/src/aarch64/qti_kryo6_gold.S
new file mode 100644
index 0000000..db1a304
--- /dev/null
+++ b/plat/qti/common/src/aarch64/qti_kryo6_gold.S
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <cpu_macros.S>
+
+#include <plat_macros.S>
+#include <qti_cpu.h>
+
+	.p2align 3
+
+/* -------------------------------------------------
+ * The CPU Ops reset function for Kryo-3 Gold
+ * -------------------------------------------------
+ */
+func qti_kryo6_gold_reset_func
+#if IMAGE_BL31 && WORKAROUND_CVE_2017_5715
+	adr	x0, wa_cve_2017_5715_bpiall_vbar
+	msr	vbar_el3, x0
+	isb
+#endif
+
+	mov	x19, x30
+
+	bl	qtiseclib_kryo6_gold_reset_asm
+
+	ret	x19
+
+endfunc qti_kryo6_gold_reset_func
+
+/* ----------------------------------------------------
+ * The CPU Ops core power down function for Kryo-3 Gold
+ * ----------------------------------------------------
+ */
+func qti_kryo6_gold_core_pwr_dwn
+	ret
+endfunc qti_kryo6_gold_core_pwr_dwn
+
+/* -------------------------------------------------------
+ * The CPU Ops cluster power down function for Kryo-3 Gold
+ * -------------------------------------------------------
+ */
+func qti_kryo6_gold_cluster_pwr_dwn
+	ret
+endfunc qti_kryo6_gold_cluster_pwr_dwn
+
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Kryo4 Gold. Must follow AAPCS.
+ */
+func qti_kryo6_gold_errata_report
+	/* TODO : Need to add support. Required only for debug bl31 image.*/
+	ret
+endfunc qti_kryo6_gold_errata_report
+#endif
+
+/* ---------------------------------------------
+ * This function provides kryo4_gold specific
+ * register information for crash reporting.
+ * It needs to return with x6 pointing to
+ * a list of register names in ASCII and
+ * x8 - x15 having values of registers to be
+ * reported.
+ * ---------------------------------------------
+ */
+.section .rodata.qti_kryo4_gold_regs, "aS"
+qti_kryo6_gold_regs:  /* The ASCII list of register names to be reported */
+	.asciz	""
+
+func qti_kryo6_gold_cpu_reg_dump
+	adr	x6, qti_kryo6_gold_regs
+	ret
+endfunc qti_kryo6_gold_cpu_reg_dump
+
+declare_cpu_ops	qti_kryo6_gold, QTI_KRYO6_GOLD_MIDR,	\
+		qti_kryo6_gold_reset_func,		\
+		qti_kryo6_gold_core_pwr_dwn,	\
+		qti_kryo6_gold_cluster_pwr_dwn
diff --git a/plat/qti/common/src/aarch64/qti_kryo6_silver.S b/plat/qti/common/src/aarch64/qti_kryo6_silver.S
new file mode 100644
index 0000000..2d189f2
--- /dev/null
+++ b/plat/qti/common/src/aarch64/qti_kryo6_silver.S
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <cpu_macros.S>
+
+#include <plat_macros.S>
+#include <qti_cpu.h>
+
+	.p2align 3
+
+/* -------------------------------------------------
+ * The CPU Ops reset function for Kryo-3 Silver
+ * -------------------------------------------------
+ */
+func qti_kryo6_silver_reset_func
+	mov	x19, x30
+
+	bl	qtiseclib_kryo6_silver_reset_asm
+
+	ret	x19
+
+endfunc qti_kryo6_silver_reset_func
+
+/* ------------------------------------------------------
+ * The CPU Ops core power down function for Kryo-3 Silver
+ * ------------------------------------------------------
+ */
+func qti_kryo6_silver_core_pwr_dwn
+	ret
+endfunc qti_kryo6_silver_core_pwr_dwn
+
+/* ---------------------------------------------------------
+ * The CPU Ops cluster power down function for Kryo-3 Silver
+ * ---------------------------------------------------------
+ */
+func qti_kryo6_silver_cluster_pwr_dwn
+	ret
+endfunc qti_kryo6_silver_cluster_pwr_dwn
+
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Kryo4 Silver. Must follow AAPCS.
+ */
+func qti_kryo6_silver_errata_report
+	/* TODO : Need to add support. Required only for debug bl31 image.*/
+	ret
+endfunc qti_kryo6_silver_errata_report
+#endif
+
+
+/* ---------------------------------------------
+ * This function provides kryo4_silver specific
+ * register information for crash reporting.
+ * It needs to return with x6 pointing to
+ * a list of register names in ASCII and
+ * x8 - x15 having values of registers to be
+ * reported.
+ * ---------------------------------------------
+ */
+.section .rodata.qti_kryo4_silver_regs, "aS"
+qti_kryo6_silver_regs:  /* The ASCII list of register names to be reported */
+	.asciz	""
+
+func qti_kryo6_silver_cpu_reg_dump
+	adr	x6, qti_kryo6_silver_regs
+	ret
+endfunc qti_kryo6_silver_cpu_reg_dump
+
+
+declare_cpu_ops	qti_kryo6_silver, QTI_KRYO6_SILVER_MIDR,	\
+		qti_kryo6_silver_reset_func,		\
+		qti_kryo6_silver_core_pwr_dwn,		\
+		qti_kryo6_silver_cluster_pwr_dwn
diff --git a/plat/qti/common/src/qti_gic_v3.c b/plat/qti/common/src/qti_gic_v3.c
index a5e0ae7..f00267a 100644
--- a/plat/qti/common/src/qti_gic_v3.c
+++ b/plat/qti/common/src/qti_gic_v3.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -72,6 +72,16 @@
 	INTR_PROP_DESC(QTISECLIB_INT_ID_MMSS_NOC_ERROR,
 		       GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
 		       GIC_INTR_CFG_EDGE),
+#ifdef QTISECLIB_INT_ID_LPASS_AGNOC_ERROR
+	INTR_PROP_DESC(QTISECLIB_INT_ID_LPASS_AGNOC_ERROR, GIC_HIGHEST_SEC_PRIORITY,
+		       INTR_GROUP0,
+		       GIC_INTR_CFG_EDGE),
+#endif
+#ifdef QTISECLIB_INT_ID_NSP_NOC_ERROR
+	INTR_PROP_DESC(QTISECLIB_INT_ID_NSP_NOC_ERROR, GIC_HIGHEST_SEC_PRIORITY,
+		       INTR_GROUP0,
+		       GIC_INTR_CFG_EDGE),
+#endif
 };
 
 const gicv3_driver_data_t qti_gic_data = {
diff --git a/plat/qti/common/src/qti_syscall.c b/plat/qti/common/src/qti_syscall.c
index a7601b6..d8e5be9 100644
--- a/plat/qti/common/src/qti_syscall.c
+++ b/plat/qti/common/src/qti_syscall.c
@@ -21,6 +21,7 @@
 #include <qti_plat.h>
 #include <qti_secure_io_cfg.h>
 #include <qtiseclib_interface.h>
+
 /*
  * SIP service - SMC function IDs for SiP Service queries
  *
@@ -29,7 +30,7 @@
 #define	QTI_SIP_SVC_UID_ID				U(0x0200ff01)
 /*							0x8200ff02 is reserved*/
 #define	QTI_SIP_SVC_VERSION_ID				U(0x0200ff03)
-
+#define QTI_SIP_SVC_AVAILABLE_ID			U(0x02000601)
 /*
  * Syscall's to allow Non Secure world accessing peripheral/IO memory
  * those are secure/proteced BUT not required to be secure.
@@ -83,6 +84,22 @@
 	return false;
 }
 
+static bool qti_check_syscall_availability(u_register_t smc_fid)
+{
+	switch (smc_fid) {
+	case QTI_SIP_SVC_CALL_COUNT_ID:
+	case QTI_SIP_SVC_UID_ID:
+	case QTI_SIP_SVC_VERSION_ID:
+	case QTI_SIP_SVC_AVAILABLE_ID:
+	case QTI_SIP_SVC_SECURE_IO_READ_ID:
+	case QTI_SIP_SVC_SECURE_IO_WRITE_ID:
+	case QTI_SIP_SVC_MEM_ASSIGN_ID:
+		return true;
+	default:
+		return false;
+	}
+}
+
 bool qti_mem_assign_validate_param(memprot_info_t *mem_info,
 				   u_register_t u_num_mappings,
 				   uint32_t *source_vm_list,
@@ -315,6 +332,18 @@
 				 QTI_SIP_SVC_VERSION_MINOR);
 			break;
 		}
+	case QTI_SIP_SVC_AVAILABLE_ID:
+		{
+			if (x1 != 1) {
+				SMC_RET1(handle, QTI_SIP_INVALID_PARAM);
+			}
+			if (qti_check_syscall_availability(x2) == true) {
+				SMC_RET2(handle, QTI_SIP_SUCCESS, 1);
+			} else {
+				SMC_RET2(handle, QTI_SIP_SUCCESS, 0);
+			}
+			break;
+		}
 	case QTI_SIP_SVC_SECURE_IO_READ_ID:
 		{
 			if ((x1 == QTI_SIP_SVC_SECURE_IO_READ_PARAM_ID) &&
diff --git a/plat/qti/qtiseclib/inc/qtiseclib_interface.h b/plat/qti/qtiseclib/inc/qtiseclib_interface.h
index 315bd6b..babed1b 100644
--- a/plat/qti/qtiseclib/inc/qtiseclib_interface.h
+++ b/plat/qti/qtiseclib/inc/qtiseclib_interface.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -50,6 +50,14 @@
 void qtiseclib_kryo4_gold_reset_asm(void);
 
 /*
+ * Execute CPU (Kryo46 gold) specific reset handler / system initialization.
+ * This takes care of executing required CPU errata's.
+ *
+ * Clobbers: x0 - x16
+ */
+void qtiseclib_kryo6_gold_reset_asm(void);
+
+/*
  * Execute CPU (Kryo4 silver) specific reset handler / system initialization.
  * This takes care of executing required CPU errata's.
  *
@@ -58,6 +66,14 @@
 void qtiseclib_kryo4_silver_reset_asm(void);
 
 /*
+ * Execute CPU (Kryo6 silver) specific reset handler / system initialization.
+ * This takes care of executing required CPU errata's.
+ *
+ * Clobbers: x0 - x16
+ */
+void qtiseclib_kryo6_silver_reset_asm(void);
+
+/*
  * C Api's
  */
 void qtiseclib_bl31_platform_setup(void);
diff --git a/plat/qti/qtiseclib/inc/sc7280/qtiseclib_defs_plat.h b/plat/qti/qtiseclib/inc/sc7280/qtiseclib_defs_plat.h
new file mode 100644
index 0000000..b3d309f
--- /dev/null
+++ b/plat/qti/qtiseclib/inc/sc7280/qtiseclib_defs_plat.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __QTISECLIB_DEFS_PLAT_H__
+#define __QTISECLIB_DEFS_PLAT_H__
+
+#define QTISECLIB_PLAT_CLUSTER_COUNT	1
+#define QTISECLIB_PLAT_CORE_COUNT	8
+
+#define BL31_BASE						0xC0000000
+#define BL31_SIZE						0x00100000
+
+/*----------------------------------------------------------------------------*/
+/* AOP CMD DB  address space for mapping */
+/*----------------------------------------------------------------------------*/
+#define QTI_AOP_CMD_DB_BASE			0x80860000
+#define QTI_AOP_CMD_DB_SIZE			0x00020000
+
+/* Chipset specific secure interrupt number/ID defs. */
+#define QTISECLIB_INT_ID_SEC_WDOG_BARK			(0x204)
+#define QTISECLIB_INT_ID_NON_SEC_WDOG_BITE		(0x21)
+
+#define QTISECLIB_INT_ID_VMIDMT_ERR_CLT_SEC		(0xE6)
+#define QTISECLIB_INT_ID_VMIDMT_ERR_CLT_NONSEC		(0xE7)
+#define QTISECLIB_INT_ID_VMIDMT_ERR_CFG_SEC		(0xE8)
+#define QTISECLIB_INT_ID_VMIDMT_ERR_CFG_NONSEC		(0xE9)
+
+#define QTISECLIB_INT_ID_XPU_SEC			(0xE3)
+#define QTISECLIB_INT_ID_XPU_NON_SEC			(0xE4)
+
+//NOC INterrupt
+#define QTISECLIB_INT_ID_A1_NOC_ERROR			(0xC9)
+#define QTISECLIB_INT_ID_A2_NOC_ERROR			(0xEA)
+#define QTISECLIB_INT_ID_CONFIG_NOC_ERROR		(0xE2)
+#define QTISECLIB_INT_ID_DC_NOC_ERROR			(0x122)
+#define QTISECLIB_INT_ID_MEM_NOC_ERROR			(0x6C)
+#define QTISECLIB_INT_ID_SYSTEM_NOC_ERROR		(0xC8)
+#define QTISECLIB_INT_ID_MMSS_NOC_ERROR			(0xBA)
+#define QTISECLIB_INT_ID_LPASS_AGNOC_ERROR		(0x143)
+#define QTISECLIB_INT_ID_NSP_NOC_ERROR			(0x1CE)
+
+#endif /* __QTISECLIB_DEFS_PLAT_H__ */
diff --git a/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c b/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c
index bb552c6..c4cd259 100644
--- a/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c
+++ b/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c
@@ -132,6 +132,10 @@
 	void *ctx;
 
 	ctx = cm_get_context(NON_SECURE);
+	if (ctx) {
+		/* nothing to be done w/o ns context */
+		return;
+	}
 
 	qti_ns_ctx->spsr_el3 =
 	    read_ctx_reg(get_el3state_ctx(ctx), CTX_SPSR_EL3);
diff --git a/plat/qti/sc7280/inc/platform_def.h b/plat/qti/sc7280/inc/platform_def.h
new file mode 100644
index 0000000..660cb33
--- /dev/null
+++ b/plat/qti/sc7280/inc/platform_def.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+/* Enable the dynamic translation tables library. */
+#define PLAT_XLAT_TABLES_DYNAMIC	1
+
+#include <common_def.h>
+
+#include <qti_board_def.h>
+#include <qtiseclib_defs_plat.h>
+
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*
+ * MPIDR_PRIMARY_CPU
+ * You just need to have the correct core_affinity_val i.e. [7:0]
+ * and cluster_affinity_val i.e. [15:8]
+ * the other bits will be ignored
+ */
+/*----------------------------------------------------------------------------*/
+#define MPIDR_PRIMARY_CPU	0x0000
+/*----------------------------------------------------------------------------*/
+
+#define QTI_PWR_LVL0		MPIDR_AFFLVL0
+#define QTI_PWR_LVL1		MPIDR_AFFLVL1
+#define QTI_PWR_LVL2		MPIDR_AFFLVL2
+#define QTI_PWR_LVL3		MPIDR_AFFLVL3
+
+/*
+ *  Macros for local power states encoded by State-ID field
+ *  within the power-state parameter.
+ */
+/* Local power state for power domains in Run state. */
+#define QTI_LOCAL_STATE_RUN	0
+/*
+ * Local power state for clock-gating. Valid only for CPU and not cluster power
+ * domains
+ */
+#define QTI_LOCAL_STATE_STB	1
+/*
+ * Local power state for retention. Valid for CPU and cluster power
+ * domains
+ */
+#define QTI_LOCAL_STATE_RET	2
+/*
+ * Local power state for OFF/power down. Valid for CPU, cluster, RSC and PDC
+ * power domains
+ */
+#define QTI_LOCAL_STATE_OFF	3
+/*
+ * Local power state for DEEPOFF/power rail down. Valid for CPU, cluster and RSC
+ * power domains
+ */
+#define QTI_LOCAL_STATE_DEEPOFF	4
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE	QTI_LOCAL_STATE_RET
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE	QTI_LOCAL_STATE_DEEPOFF
+
+/******************************************************************************
+ * Required platform porting definitions common to all ARM standard platforms
+ *****************************************************************************/
+
+/*
+ * Platform specific page table and MMU setup constants.
+ */
+#define MAX_MMAP_REGIONS	(PLAT_QTI_MMAP_ENTRIES)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ull << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ull << 36)
+
+#define ARM_CACHE_WRITEBACK_SHIFT	6
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_GRANULE		(1 << ARM_CACHE_WRITEBACK_SHIFT)
+
+/*
+ * One cache line needed for bakery locks on ARM platforms
+ */
+#define PLAT_PERCPU_BAKERY_LOCK_SIZE	(1 * CACHE_WRITEBACK_GRANULE)
+
+/*----------------------------------------------------------------------------*/
+/* PSCI power domain topology definitions */
+/*----------------------------------------------------------------------------*/
+/* One domain each to represent RSC and PDC level */
+#define PLAT_PDC_COUNT			1
+#define PLAT_RSC_COUNT			1
+
+/* There is one top-level FCM cluster */
+#define PLAT_CLUSTER_COUNT		1
+
+/* No. of cores in the FCM cluster */
+#define PLAT_CLUSTER0_CORE_COUNT	8
+
+#define PLATFORM_CORE_COUNT		(PLAT_CLUSTER0_CORE_COUNT)
+
+#define PLAT_NUM_PWR_DOMAINS		(PLAT_PDC_COUNT +\
+					PLAT_RSC_COUNT	+\
+					PLAT_CLUSTER_COUNT	+\
+					PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_PWR_LVL		3
+
+/*****************************************************************************/
+/* Memory mapped Generic timer interfaces  */
+/*****************************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/* GIC-600 constants */
+/*----------------------------------------------------------------------------*/
+#define BASE_GICD_BASE		0x17A00000
+#define BASE_GICR_BASE		0x17A60000
+#define BASE_GICC_BASE		0x0
+#define BASE_GICH_BASE		0x0
+#define BASE_GICV_BASE		0x0
+
+#define QTI_GICD_BASE		BASE_GICD_BASE
+#define QTI_GICR_BASE		BASE_GICR_BASE
+#define QTI_GICC_BASE		BASE_GICC_BASE
+
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* UART related constants. */
+/*----------------------------------------------------------------------------*/
+/* BASE ADDRESS OF DIFFERENT REGISTER SPACES IN HW */
+#define GENI4_CFG				0x0
+#define GENI4_IMAGE_REGS			0x100
+#define GENI4_DATA				0x600
+
+/* COMMON STATUS/CONFIGURATION REGISTERS AND MASKS */
+#define GENI_STATUS_REG				(GENI4_CFG + 0x00000040)
+#define GENI_STATUS_M_GENI_CMD_ACTIVE_MASK	(0x1)
+#define UART_TX_TRANS_LEN_REG			(GENI4_IMAGE_REGS + 0x00000170)
+/* MASTER/TX ENGINE REGISTERS */
+#define GENI_M_CMD0_REG				(GENI4_DATA + 0x00000000)
+/* FIFO, STATUS REGISTERS AND MASKS */
+#define GENI_TX_FIFOn_REG			(GENI4_DATA + 0x00000100)
+
+#define GENI_M_CMD_TX				(0x08000000)
+
+/*----------------------------------------------------------------------------*/
+/* Device address space for mapping. Excluding starting 4K */
+/*----------------------------------------------------------------------------*/
+#define QTI_DEVICE_BASE				0x1000
+#define QTI_DEVICE_SIZE				(0x80000000 - QTI_DEVICE_BASE)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL31 at DDR as per memory map. BL31_BASE is calculated using the
+ * current BL31 debug size plus a little space for growth.
+ */
+#define BL31_LIMIT				(BL31_BASE + BL31_SIZE)
+
+/*----------------------------------------------------------------------------*/
+/* AOSS registers */
+/*----------------------------------------------------------------------------*/
+#define QTI_PS_HOLD_REG				0x0C264000
+/*----------------------------------------------------------------------------*/
+/* AOP CMD DB  address space for mapping */
+/*----------------------------------------------------------------------------*/
+#define QTI_AOP_CMD_DB_BASE			0x80860000
+#define QTI_AOP_CMD_DB_SIZE			0x00020000
+/*----------------------------------------------------------------------------*/
+/* SOC hw version register */
+/*----------------------------------------------------------------------------*/
+#define QTI_SOC_VERSION				U(0x7280)
+#define QTI_SOC_VERSION_MASK			U(0xFFFF)
+#define QTI_SOC_REVISION_REG			0x1FC8000
+#define QTI_SOC_REVISION_MASK			U(0xFFFF)
+/*----------------------------------------------------------------------------*/
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/qti/sc7280/inc/qti_rng_io.h b/plat/qti/sc7280/inc/qti_rng_io.h
new file mode 100644
index 0000000..0f41fd6
--- /dev/null
+++ b/plat/qti/sc7280/inc/qti_rng_io.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef QTI_RNG_IO_H
+#define QTI_RNG_IO_H
+
+#define SEC_PRNG_STATUS			0x10D1004
+#define SEC_PRNG_STATUS_DATA_AVAIL_BMSK	0x1
+#define SEC_PRNG_DATA_OUT		0x10D1000
+
+
+#endif /* QTI_RNG_IO_H */
+
diff --git a/plat/qti/sc7280/inc/qti_secure_io_cfg.h b/plat/qti/sc7280/inc/qti_secure_io_cfg.h
new file mode 100644
index 0000000..058c5b5
--- /dev/null
+++ b/plat/qti/sc7280/inc/qti_secure_io_cfg.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef QTI_SECURE_IO_CFG_H
+#define QTI_SECURE_IO_CFG_H
+
+#include <stdint.h>
+
+/*
+ * List of peripheral/IO memory areas that are protected from
+ * non-secure world but not required to be secure.
+ */
+
+#define APPS_SMMU_TBU_PWR_STATUS		0x15002204
+#define APPS_SMMU_CUSTOM_CFG			0x15002300
+#define APPS_SMMU_STATS_SYNC_INV_TBU_ACK	0x150025DC
+#define APPS_SMMU_SAFE_SEC_CFG			0x15002648
+#define APPS_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR	0x15002670
+
+static const uintptr_t qti_secure_io_allowed_regs[] = {
+	APPS_SMMU_TBU_PWR_STATUS,
+	APPS_SMMU_CUSTOM_CFG,
+	APPS_SMMU_STATS_SYNC_INV_TBU_ACK,
+	APPS_SMMU_SAFE_SEC_CFG,
+	APPS_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR,
+};
+
+#endif /* QTI_SECURE_IO_CFG_H */
diff --git a/plat/qti/sc7280/platform.mk b/plat/qti/sc7280/platform.mk
new file mode 100644
index 0000000..6e26781
--- /dev/null
+++ b/plat/qti/sc7280/platform.mk
@@ -0,0 +1,119 @@
+#
+# Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Make for SC7280 QTI platform.
+
+QTI_PLAT_PATH		:=	plat/qti
+CHIPSET			:=	${PLAT}
+
+# Turn On Separate code & data.
+SEPARATE_CODE_AND_RODATA	:=	1
+USE_COHERENT_MEM		:=	1
+WARMBOOT_ENABLE_DCACHE_EARLY	:=	1
+
+# Disable the PSCI platform compatibility layer
+ENABLE_PLAT_COMPAT		:=	0
+
+# Enable PSCI v1.0 extended state ID format
+PSCI_EXTENDED_STATE_ID	:=  1
+ARM_RECOM_STATE_ID_ENC  :=  1
+
+COLD_BOOT_SINGLE_CPU		:=	1
+PROGRAMMABLE_RESET_ADDRESS	:=	1
+
+RESET_TO_BL31			:=	0
+
+MULTI_CONSOLE_API		:=	1
+
+QTI_SDI_BUILD := 0
+$(eval $(call assert_boolean,QTI_SDI_BUILD))
+$(eval $(call add_define,QTI_SDI_BUILD))
+
+#disable CTX_INCLUDE_AARCH32_REGS to support sc7280 gold cores
+override CTX_INCLUDE_AARCH32_REGS	:=	0
+WORKAROUND_CVE_2017_5715		:=      0
+DYNAMIC_WORKAROUND_CVE_2018_3639	:=      1
+# Enable stack protector.
+ENABLE_STACK_PROTECTOR := strong
+
+
+QTI_EXTERNAL_INCLUDES	:=	-I${QTI_PLAT_PATH}/${CHIPSET}/inc			\
+				-I${QTI_PLAT_PATH}/common/inc				\
+				-I${QTI_PLAT_PATH}/common/inc/$(ARCH)			\
+				-I${QTI_PLAT_PATH}/qtiseclib/inc			\
+				-I${QTI_PLAT_PATH}/qtiseclib/inc/${CHIPSET}			\
+
+QTI_BL31_SOURCES	:=	$(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_helpers.S	\
+				$(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_kryo6_silver.S	\
+				$(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_kryo6_gold.S	\
+				$(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_uart_console.S	\
+				$(QTI_PLAT_PATH)/common/src/pm8998.c			\
+				$(QTI_PLAT_PATH)/common/src/qti_stack_protector.c	\
+				$(QTI_PLAT_PATH)/common/src/qti_common.c		\
+				$(QTI_PLAT_PATH)/common/src/qti_bl31_setup.c		\
+				$(QTI_PLAT_PATH)/common/src/qti_gic_v3.c		\
+				$(QTI_PLAT_PATH)/common/src/qti_interrupt_svc.c		\
+				$(QTI_PLAT_PATH)/common/src/qti_syscall.c		\
+				$(QTI_PLAT_PATH)/common/src/qti_topology.c		\
+				$(QTI_PLAT_PATH)/common/src/qti_pm.c			\
+				$(QTI_PLAT_PATH)/common/src/qti_rng.c			\
+				$(QTI_PLAT_PATH)/common/src/spmi_arb.c			\
+				$(QTI_PLAT_PATH)/qtiseclib/src/qtiseclib_cb_interface.c	\
+
+
+PLAT_INCLUDES		:=	-Iinclude/plat/common/					\
+
+PLAT_INCLUDES		+=	${QTI_EXTERNAL_INCLUDES}
+
+include lib/xlat_tables_v2/xlat_tables.mk
+PLAT_BL_COMMON_SOURCES	+=	${XLAT_TABLES_LIB_SRCS}					\
+				plat/common/aarch64/crash_console_helpers.S    \
+				common/desc_image_load.c			\
+				lib/bl_aux_params/bl_aux_params.c		\
+
+include lib/coreboot/coreboot.mk
+
+#PSCI Sources.
+PSCI_SOURCES		:=	plat/common/plat_psci_common.c				\
+
+# GIC-600 configuration
+GICV3_SUPPORT_GIC600	:=	1
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+#Timer sources
+TIMER_SOURCES		:=	drivers/delay_timer/generic_delay_timer.c	\
+				drivers/delay_timer/delay_timer.c		\
+
+#GIC sources.
+GIC_SOURCES		:=	plat/common/plat_gicv3.c			\
+				${GICV3_SOURCES}				\
+
+BL31_SOURCES		+=	${QTI_BL31_SOURCES}					\
+				${PSCI_SOURCES}						\
+				${GIC_SOURCES}						\
+				${TIMER_SOURCES}					\
+
+LIB_QTI_PATH	:=	${QTI_PLAT_PATH}/qtiseclib/lib/${CHIPSET}
+
+
+# Override this on the command line to point to the qtiseclib library which
+# will be available in coreboot.org
+QTISECLIB_PATH ?=
+
+ifeq ($(QTISECLIB_PATH),)
+# if No lib then use stub implementation for qtiseclib interface
+$(warning QTISECLIB_PATH is not provided while building, using stub implementation. \
+		Please refer docs/plat/qti.rst for more details \
+		THIS FIRMWARE WILL NOT BOOT!)
+BL31_SOURCES	+=	plat/qti/qtiseclib/src/qtiseclib_interface_stub.c
+else
+# use library provided by QTISECLIB_PATH
+LDFLAGS += -L $(dir $(QTISECLIB_PATH))
+LDLIBS += -l$(patsubst lib%.a,%,$(notdir $(QTISECLIB_PATH)))
+endif
+
diff --git a/plat/renesas/common/aarch64/plat_helpers.S b/plat/renesas/common/aarch64/plat_helpers.S
index ec21f25..21c3bed 100644
--- a/plat/renesas/common/aarch64/plat_helpers.S
+++ b/plat/renesas/common/aarch64/plat_helpers.S
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -284,7 +284,11 @@
 	str	x3, [sp, #-16]!
 	str	x4, [sp, #-16]!
 	str	x5, [sp, #-16]!
+	str	x6, [sp, #-16]!
+	str	x7, [sp, #-16]!
 	bl	console_rcar_putc
+	ldr	x7, [sp], #16
+	ldr	x6, [sp], #16
 	ldr	x5, [sp], #16
 	ldr	x4, [sp], #16
 	ldr	x3, [sp], #16
diff --git a/plat/renesas/common/bl2_cpg_init.c b/plat/renesas/common/bl2_cpg_init.c
index ba8e53b..a545f71 100644
--- a/plat/renesas/common/bl2_cpg_init.c
+++ b/plat/renesas/common/bl2_cpg_init.c
@@ -40,7 +40,6 @@
 #endif
 
 #if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_D3)
-static void bl2_realtime_cpg_init_d3(void);
 static void bl2_system_cpg_init_d3(void);
 #endif
 
@@ -140,7 +139,7 @@
 	cpg_write(SMSTPCR1, 0xFFFFFFFFU);
 	cpg_write(SMSTPCR2, 0x040E2FDCU);
 	cpg_write(SMSTPCR3, 0xFFFFFBDFU);
-	cpg_write(SMSTPCR4, 0x80000004U);
+	cpg_write(SMSTPCR4, 0x80000000U | (mmio_read_32(SMSTPCR4) & 0x4));
 	cpg_write(SMSTPCR5, 0xC3FFFFFFU);
 	cpg_write(SMSTPCR6, 0xFFFFFFFFU);
 	cpg_write(SMSTPCR7, 0xFFFFFFFFU);
@@ -176,7 +175,7 @@
 	cpg_write(SMSTPCR1, 0xFFFFFFFFU);
 	cpg_write(SMSTPCR2, 0x040E2FDCU);
 	cpg_write(SMSTPCR3, 0xFFFFFBDFU);
-	cpg_write(SMSTPCR4, 0x80000004U);
+	cpg_write(SMSTPCR4, 0x80000000U | (mmio_read_32(SMSTPCR4) & 0x4));
 	cpg_write(SMSTPCR5, 0xC3FFFFFFU);
 	cpg_write(SMSTPCR6, 0xFFFFFFFFU);
 	cpg_write(SMSTPCR7, 0xFFFFFFFFU);
@@ -212,7 +211,7 @@
 	cpg_write(SMSTPCR1, 0xFFFFFFFFU);
 	cpg_write(SMSTPCR2, 0x040E2FDCU);
 	cpg_write(SMSTPCR3, 0xFFFFFBDFU);
-	cpg_write(SMSTPCR4, 0x80000004U);
+	cpg_write(SMSTPCR4, 0x80000000U | (mmio_read_32(SMSTPCR4) & 0x4));
 	cpg_write(SMSTPCR5, 0xC3FFFFFFU);
 	cpg_write(SMSTPCR6, 0xFFFFFFFFU);
 	cpg_write(SMSTPCR7, 0xFFFFFFFFU);
@@ -246,7 +245,7 @@
 	cpg_write(SMSTPCR1, 0xFFFFFFFFU);
 	cpg_write(SMSTPCR2, 0x340E2FDCU);
 	cpg_write(SMSTPCR3, 0xFFFFFBDFU);
-	cpg_write(SMSTPCR4, 0x80000004U);
+	cpg_write(SMSTPCR4, 0x80000000U | (mmio_read_32(SMSTPCR4) & 0x4));
 	cpg_write(SMSTPCR5, 0xC3FFFFFFU);
 	cpg_write(SMSTPCR6, 0xFFFFFFFFU);
 	cpg_write(SMSTPCR7, 0xFFFFFFFFU);
@@ -280,7 +279,7 @@
 	cpg_write(SMSTPCR1, 0xFFFFFFFFU);
 	cpg_write(SMSTPCR2, 0x000E2FDCU);
 	cpg_write(SMSTPCR3, 0xFFFFFBDFU);
-	cpg_write(SMSTPCR4, 0x80000004U);
+	cpg_write(SMSTPCR4, 0x80000000U | (mmio_read_32(SMSTPCR4) & 0x4));
 	cpg_write(SMSTPCR5, 0xC3FFFFFFU);
 	cpg_write(SMSTPCR6, 0xFFFFFFFFU);
 	cpg_write(SMSTPCR7, 0xFFFFFFFFU);
@@ -292,23 +291,6 @@
 #endif
 
 #if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_D3)
-static void bl2_realtime_cpg_init_d3(void)
-{
-	/* Realtime Module Stop Control Registers */
-	cpg_write(RMSTPCR0, 0x00010000U);
-	cpg_write(RMSTPCR1, 0xFFFFFFFFU);
-	cpg_write(RMSTPCR2, 0x00060FDCU);
-	cpg_write(RMSTPCR3, 0xFFFFFFDFU);
-	cpg_write(RMSTPCR4, 0x80000184U);
-	cpg_write(RMSTPCR5, 0x83FFFFFFU);
-	cpg_write(RMSTPCR6, 0xFFFFFFFFU);
-	cpg_write(RMSTPCR7, 0xFFFFFFFFU);
-	cpg_write(RMSTPCR8, 0x00F1FFF7U);
-	cpg_write(RMSTPCR9, 0xF3F5E016U);
-	cpg_write(RMSTPCR10, 0xFFFEFFE0U);
-	cpg_write(RMSTPCR11, 0x000000B7U);
-}
-
 static void bl2_system_cpg_init_d3(void)
 {
 	/* System Module Stop Control Registers */
@@ -316,7 +298,7 @@
 	cpg_write(SMSTPCR1, 0xFFFFFFFFU);
 	cpg_write(SMSTPCR2, 0x00060FDCU);
 	cpg_write(SMSTPCR3, 0xFFFFFBDFU);
-	cpg_write(SMSTPCR4, 0x00000084U);
+	cpg_write(SMSTPCR4, 0x00000080U | (mmio_read_32(SMSTPCR4) & 0x4));
 	cpg_write(SMSTPCR5, 0x83FFFFFFU);
 	cpg_write(SMSTPCR6, 0xFFFFFFFFU);
 	cpg_write(SMSTPCR7, 0xFFFFFFFFU);
@@ -356,7 +338,7 @@
 			bl2_realtime_cpg_init_e3();
 			break;
 		case PRR_PRODUCT_D3:
-			bl2_realtime_cpg_init_d3();
+			/* no need */
 			break;
 		default:
 			panic();
@@ -373,7 +355,7 @@
 #elif RCAR_LSI == RCAR_E3 || RCAR_LSI == RZ_G2E
 		bl2_realtime_cpg_init_e3();
 #elif RCAR_LSI == RCAR_D3
-		bl2_realtime_cpg_init_d3();
+		/* no need */
 #else
 #error "Don't have CPG initialize routine(unknown)."
 #endif
diff --git a/plat/renesas/common/bl2_secure_setting.c b/plat/renesas/common/bl2_secure_setting.c
index 095d1f6..2f8b001 100644
--- a/plat/renesas/common/bl2_secure_setting.c
+++ b/plat/renesas/common/bl2_secure_setting.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -49,10 +49,10 @@
 	/*
 	 * Bit13: SCEG PKA (secure APB) slave ports
 	 *        0: registers accessed from secure resource only
-	 *        1: Reserved[R-Car E3]
+	 *        1: Reserved[R-Car E3/D3]
 	 * Bit12: SCEG PKA (public APB) slave ports
 	 *	  0: registers accessed from secure resource only
-	 *	  1: Reserved[R-Car E3]
+	 *	  1: Reserved[R-Car E3/D3]
 	 * Bit10: SCEG Secure Core slave ports
 	 *	  0: registers accessed from secure resource only
 	 */
@@ -152,14 +152,14 @@
 	 * Security group 1 attribute setting for slave ports 6
 	 * Bit13: SCEG PKA (secure APB) slave ports
 	 *	  SecurityGroup3
-	 *	  Reserved[R-Car E3]
+	 *	  Reserved[R-Car E3/D3]
 	 * Bit12: SCEG PKA (public APB) slave ports
 	 *	  SecurityGroup3
-	 *	  Reserved[R-Car E3]
+	 *	  Reserved[R-Car E3/D3]
 	 * Bit10: SCEG Secure Core slave ports
 	 *	  SecurityGroup3
 	 */
-#if RCAR_LSI == RCAR_E3
+#if RCAR_LSI == RCAR_E3 || RCAR_LSI == RCAR_D3
 	{ SEC_GRP0COND6, 0x00000400U },
 	{ SEC_GRP1COND6, 0x00000400U },
 #else /* RCAR_LSI == RCAR_E3 */
diff --git a/plat/renesas/common/common.mk b/plat/renesas/common/common.mk
index fafce98..0d88d65 100644
--- a/plat/renesas/common/common.mk
+++ b/plat/renesas/common/common.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2018-2020, Renesas Electronics Corporation. All rights reserved.
+# Copyright (c) 2018-2021, Renesas Electronics Corporation. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -65,10 +65,12 @@
 ERRATA_A53_835769  := 1
 ERRATA_A53_843419  := 1
 ERRATA_A53_855873  := 1
+ERRATA_A53_1530924 := 1
 
 # Enable workarounds for selected Cortex-A57 erratas.
 ERRATA_A57_859972  := 1
 ERRATA_A57_813419  := 1
+ERRATA_A57_1319537 := 1
 
 PLAT_INCLUDES	:=	-Iplat/renesas/common/include/registers	\
 			-Iplat/renesas/common/include		\
@@ -77,9 +79,8 @@
 PLAT_BL_COMMON_SOURCES	:=	drivers/renesas/common/iic_dvfs/iic_dvfs.c \
 				plat/renesas/common/rcar_common.c
 
-RCAR_GIC_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
-				drivers/arm/gic/v2/gicv2_main.c		\
-				drivers/arm/gic/v2/gicv2_helpers.c	\
+include drivers/arm/gic/v2/gicv2.mk
+RCAR_GIC_SOURCES	:=	${GICV2_SOURCES} \
 				plat/common/plat_gicv2.c
 
 BL2_SOURCES	+=	${RCAR_GIC_SOURCES}				\
diff --git a/plat/renesas/common/include/platform_def.h b/plat/renesas/common/include/platform_def.h
index 7378714..1213a3c 100644
--- a/plat/renesas/common/include/platform_def.h
+++ b/plat/renesas/common/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -144,14 +144,15 @@
  ******************************************************************************/
 #ifndef SPD_NONE
 #define BL32_BASE		U(0x44100000)
-#define BL32_LIMIT		(BL32_BASE + U(0x100000))
+#define BL32_LIMIT		(BL32_BASE + U(0x200000))
 #endif
 
 /*******************************************************************************
  * BL33
  ******************************************************************************/
 #define BL33_BASE		DRAM1_NS_BASE
-
+#define BL33_COMP_SIZE		U(0x200000)
+#define BL33_COMP_BASE		(BL33_BASE - BL33_COMP_SIZE)
 
 /*******************************************************************************
  * Platform specific page table and MMU setup constants
diff --git a/plat/renesas/common/include/rcar_def.h b/plat/renesas/common/include/rcar_def.h
index 6c5b295..2cd26ed 100644
--- a/plat/renesas/common/include/rcar_def.h
+++ b/plat/renesas/common/include/rcar_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -120,7 +120,6 @@
 /* Timer control */
 #define RCAR_CNTC_BASE		U(0xE6080000)
 /* Reset */
-#define RCAR_CPGWPR		U(0xE6150900)	/* CPG write protect    */
 #define RCAR_MODEMR		U(0xE6160060)	/* Mode pin             */
 #define RCAR_CA57RESCNT		U(0xE6160040)	/* Reset control A57    */
 #define RCAR_CA53RESCNT		U(0xE6160044)	/* Reset control A53    */
@@ -149,9 +148,13 @@
 #define RCAR_PWRER5		U(0xE61801D4)	/* shutoff/resume error */
 #define RCAR_SYSCISR		U(0xE6180004)	/* Interrupt status     */
 #define RCAR_SYSCISCR		U(0xE6180008)	/* Interrupt stat clear */
+#define RCAR_SYSCEXTMASK	U(0xE61802F8)	/* External Request Mask */
+						/* H3/H3-N, M3 v3.0, M3-N, E3 */
 /* Product register */
 #define RCAR_PRR			U(0xFFF00044)
 #define RCAR_M3_CUT_VER11		U(0x00000010)	/* M3 Ver.1.1/Ver.1.2 */
+#define RCAR_D3_CUT_VER10		U(0x00000000)	/* D3 Ver.1.0 */
+#define RCAR_D3_CUT_VER11		U(0x00000010)	/* D3 Ver.1.1 */
 #define RCAR_MAJOR_MASK			U(0x000000F0)
 #define RCAR_MINOR_MASK			U(0x0000000F)
 #define PRR_PRODUCT_SHIFT		U(8)
diff --git a/plat/renesas/common/include/rcar_version.h b/plat/renesas/common/include/rcar_version.h
index 67cbd71..173111d 100644
--- a/plat/renesas/common/include/rcar_version.h
+++ b/plat/renesas/common/include/rcar_version.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,7 +9,7 @@
 
 #include <arch_helpers.h>
 
-#define VERSION_OF_RENESAS		"2.0.6"
+#define VERSION_OF_RENESAS		"3.0.0"
 #define VERSION_OF_RENESAS_MAXLEN	128
 
 extern const uint8_t version_of_renesas[VERSION_OF_RENESAS_MAXLEN];
diff --git a/plat/renesas/common/include/registers/cpg_registers.h b/plat/renesas/common/include/registers/cpg_registers.h
index 0d698d9..5d2bb9e 100644
--- a/plat/renesas/common/include/registers/cpg_registers.h
+++ b/plat/renesas/common/include/registers/cpg_registers.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,6 +16,8 @@
 #define CPG_SRCR2	(CPG_BASE + 0x00B0U)
 /* CPG module stop status 2 */
 #define CPG_MSTPSR2	(CPG_BASE + 0x0040U)
+/* CPG module stop status 2 */
+#define CPG_MSTPSR3	(CPG_BASE + 0x0048U)
 /* CPG write protect */
 #define CPG_CPGWPR	(CPG_BASE + 0x0900U)
 /* CPG write protect control */
@@ -24,6 +26,10 @@
 #define CPG_SMSTPCR9    (CPG_BASE + 0x0994U)
 /* CPG module stop status 9 */
 #define CPG_MSTPSR9     (CPG_BASE + 0x09A4U)
+/* SDHI2 clock frequency control register */
+#define	CPG_SD2CKCR	(CPG_BASE + 0x0268U)
+/* SDHI3 clock frequency control register */
+#define CPG_SD3CKCR	(CPG_BASE + 0x026CU)
 
 /* CPG (SECURITY) registers */
 
diff --git a/plat/renesas/common/rcar_common.c b/plat/renesas/common/rcar_common.c
index dec7229..df4c30c 100644
--- a/plat/renesas/common/rcar_common.c
+++ b/plat/renesas/common/rcar_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2019-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,9 +12,8 @@
 #include <plat/common/platform.h>
 
 #include <lib/mmio.h>
+#include <cpg_registers.h>
 
-#define CPG_BASE		0xE6150000
-#define CPG_MSTPSR3		0x0048
 #define MSTP318			(1 << 18)
 #define MSTP319			(1 << 19)
 #define PMSR			0x5c
@@ -31,7 +30,7 @@
 	int ret = 0;
 
 	/* Test if PCIECx is enabled */
-	cpg = mmio_read_32(CPG_BASE + CPG_MSTPSR3);
+	cpg = mmio_read_32(CPG_MSTPSR3);
 	if (cpg & (MSTP318 << !controller))
 		return ret;
 
@@ -61,11 +60,7 @@
 	if (fixed)
 		return;
 
-	ERROR("Unhandled External Abort received on 0x%lx at EL3!\n",
-			read_mpidr_el1());
-	ERROR(" exception reason=%u syndrome=0x%llx\n", ea_reason, syndrome);
-
-	panic();
+	plat_default_ea_handler(ea_reason, syndrome, cookie, handle, flags);
 }
 
 #include <drivers/renesas/rcar/console/console.h>
diff --git a/plat/renesas/rcar/bl2_plat_setup.c b/plat/renesas/rcar/bl2_plat_setup.c
index add2a4f..e07b96f 100644
--- a/plat/renesas/rcar/bl2_plat_setup.c
+++ b/plat/renesas/rcar/bl2_plat_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2018-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,12 +15,16 @@
 #include <common/bl_common.h>
 #include <common/debug.h>
 #include <common/desc_image_load.h>
+#include <common/image_decompress.h>
 #include <drivers/console.h>
 #include <drivers/io/io_driver.h>
 #include <drivers/io/io_storage.h>
 #include <lib/mmio.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 #include <plat/common/platform.h>
+#if RCAR_GEN3_BL33_GZIP == 1
+#include <tf_gunzip.h>
+#endif
 
 #include "avs_driver.h"
 #include "boot_init_dram.h"
@@ -259,9 +263,6 @@
 	if (product == PRR_PRODUCT_H3 && PRR_PRODUCT_20 > cut)
 		goto tlb;
 
-	if (product == PRR_PRODUCT_D3)
-		goto tlb;
-
 	/* Disable MFIS write protection */
 	mmio_write_32(MFISWPCNTR, MFISWPCNTR_PASSWORD | 1);
 
@@ -357,16 +358,29 @@
 #endif
 }
 
+#if RCAR_GEN3_BL33_GZIP == 1
+void bl2_plat_preload_setup(void)
+{
+	image_decompress_init(BL33_COMP_BASE, BL33_COMP_SIZE, gunzip);
+}
+#endif
+
 int bl2_plat_handle_pre_image_load(unsigned int image_id)
 {
 	u_register_t *boot_kind = (void *) BOOT_KIND_BASE;
 	bl_mem_params_node_t *bl_mem_params;
 
+	bl_mem_params = get_bl_mem_params_node(image_id);
+
+#if RCAR_GEN3_BL33_GZIP == 1
+	if (image_id == BL33_IMAGE_ID) {
+		image_decompress_prepare(&bl_mem_params->image_info);
+	}
+#endif
+
 	if (image_id != BL31_IMAGE_ID)
 		return 0;
 
-	bl_mem_params = get_bl_mem_params_node(image_id);
-
 	if (is_ddr_backup_mode() == RCAR_COLD_BOOT)
 		goto cold_boot;
 
@@ -433,6 +447,19 @@
 			sizeof(entry_point_info_t));
 		break;
 	case BL33_IMAGE_ID:
+#if RCAR_GEN3_BL33_GZIP == 1
+		if ((mmio_read_32(BL33_COMP_BASE) & 0xffff) == 0x8b1f) {
+			/* decompress gzip-compressed image */
+			ret = image_decompress(&bl_mem_params->image_info);
+			if (ret != 0) {
+				return ret;
+			}
+		} else {
+			/* plain image, copy it in place */
+			memcpy((void *)BL33_BASE, (void *)BL33_COMP_BASE,
+				bl_mem_params->image_info.image_size);
+		}
+#endif
 		memcpy(&params->bl33_ep_info, &bl_mem_params->ep_info,
 			sizeof(entry_point_info_t));
 		break;
@@ -535,12 +562,75 @@
 	}
 }
 
-static void bl2_advertise_dram_entries(uint64_t dram_config[8])
+static void bl2_add_rpc_node(void)
+{
+#if (RCAR_RPC_HYPERFLASH_LOCKED == 0)
+	int ret, node;
+
+	node = ret = fdt_add_subnode(fdt, 0, "soc");
+	if (ret < 0) {
+		goto err;
+	}
+
+	node = ret = fdt_add_subnode(fdt, node, "rpc@ee200000");
+	if (ret < 0) {
+		goto err;
+	}
+
+	ret = fdt_setprop_string(fdt, node, "status", "okay");
+	if (ret < 0) {
+		goto err;
+	}
+
+	return;
+err:
+	NOTICE("BL2: Cannot add RPC node to FDT (ret=%i)\n", ret);
+	panic();
+#endif
+}
+
+static void bl2_add_dram_entry(uint64_t start, uint64_t size)
 {
 	char nodename[32] = { 0 };
-	uint64_t start, size;
 	uint64_t fdtsize;
-	int ret, node, chan;
+	int ret, node;
+
+	fdtsize = cpu_to_fdt64(size);
+
+	snprintf(nodename, sizeof(nodename), "memory@");
+	unsigned_num_print(start, 16, nodename + strlen(nodename));
+	node = ret = fdt_add_subnode(fdt, 0, nodename);
+	if (ret < 0) {
+		goto err;
+	}
+
+	ret = fdt_setprop_string(fdt, node, "device_type", "memory");
+	if (ret < 0) {
+		goto err;
+	}
+
+	ret = fdt_setprop_u64(fdt, node, "reg", start);
+	if (ret < 0) {
+		goto err;
+	}
+
+	ret = fdt_appendprop(fdt, node, "reg", &fdtsize,
+			     sizeof(fdtsize));
+	if (ret < 0) {
+		goto err;
+	}
+
+	return;
+err:
+	NOTICE("BL2: Cannot add memory node [%llx - %llx] to FDT (ret=%i)\n",
+		start, start + size - 1, ret);
+	panic();
+}
+
+static void bl2_advertise_dram_entries(uint64_t dram_config[8])
+{
+	uint64_t start, size, size32;
+	int chan;
 
 	for (chan = 0; chan < 4; chan++) {
 		start = dram_config[2 * chan];
@@ -568,39 +658,43 @@
 
 		/*
 		 * Channel 0 is mapped in 32bit space and the first
-		 * 128 MiB are reserved
+		 * 128 MiB are reserved and the maximum size is 2GiB.
 		 */
 		if (chan == 0) {
-			start = 0x48000000;
-			size -= 0x8000000;
-		}
+			/* Limit the 32bit entry to 2 GiB - 128 MiB */
+			size32 = size - 0x8000000U;
+			if (size32 >= 0x78000000U) {
+				size32 = 0x78000000U;
+			}
 
-		fdtsize = cpu_to_fdt64(size);
+			/* Emit 32bit entry, up to 2 GiB - 128 MiB long. */
+			bl2_add_dram_entry(0x48000000, size32);
 
-		snprintf(nodename, sizeof(nodename), "memory@");
-		unsigned_num_print(start, 16, nodename + strlen(nodename));
-		node = ret = fdt_add_subnode(fdt, 0, nodename);
-		if (ret < 0)
-			goto err;
+			/*
+			 * If channel 0 is less than 2 GiB long, the
+			 * entire memory fits into the 32bit space entry,
+			 * so move on to the next channel.
+			 */
+			if (size <= 0x80000000U) {
+				continue;
+			}
 
-		ret = fdt_setprop_string(fdt, node, "device_type", "memory");
-		if (ret < 0)
-			goto err;
-
-		ret = fdt_setprop_u64(fdt, node, "reg", start);
-		if (ret < 0)
-			goto err;
+			/*
+			 * If channel 0 is more than 2 GiB long, emit
+			 * another entry which covers the rest of the
+			 * memory in channel 0, in the 64bit space.
+			 *
+			 * Start of this new entry is at 2 GiB offset
+			 * from the beginning of the 64bit channel 0
+			 * address, size is 2 GiB shorter than total
+			 * size of the channel.
+			 */
+			start += 0x80000000U;
+			size -= 0x80000000U;
+		}
 
-		ret = fdt_appendprop(fdt, node, "reg", &fdtsize,
-				     sizeof(fdtsize));
-		if (ret < 0)
-			goto err;
+		bl2_add_dram_entry(start, size);
 	}
-
-	return;
-err:
-	NOTICE("BL2: Cannot add memory node to FDT (ret=%i)\n", ret);
-	panic();
 }
 
 static void bl2_advertise_dram_size(uint32_t product)
@@ -611,6 +705,7 @@
 		[4] = 0x600000000ULL,
 		[6] = 0x700000000ULL,
 	};
+	uint32_t cut = mmio_read_32(RCAR_PRR) & PRR_CUT_MASK;
 
 	switch (product) {
 	case PRR_PRODUCT_H3:
@@ -636,20 +731,31 @@
 		break;
 
 	case PRR_PRODUCT_M3:
+		if (cut < PRR_PRODUCT_30) {
 #if (RCAR_GEN3_ULCB == 1)
-		/* 2GB(1GBx2 2ch split) */
-		dram_config[1] = 0x40000000ULL;
-		dram_config[5] = 0x40000000ULL;
+			/* 2GB(1GBx2 2ch split) */
+			dram_config[1] = 0x40000000ULL;
+			dram_config[5] = 0x40000000ULL;
 #else
-		/* 4GB(2GBx2 2ch split) */
-		dram_config[1] = 0x80000000ULL;
-		dram_config[5] = 0x80000000ULL;
+			/* 4GB(2GBx2 2ch split) */
+			dram_config[1] = 0x80000000ULL;
+			dram_config[5] = 0x80000000ULL;
 #endif
+		} else {
+			/* 8GB(2GBx4 2ch split) */
+			dram_config[1] = 0x100000000ULL;
+			dram_config[5] = 0x100000000ULL;
+		}
 		break;
 
 	case PRR_PRODUCT_M3N:
+#if (RCAR_DRAM_LPDDR4_MEMCONF == 2)
+		/* 4GB(4GBx1) */
+		dram_config[1] = 0x100000000ULL;
+#elif (RCAR_DRAM_LPDDR4_MEMCONF == 1)
 		/* 2GB(1GBx2) */
 		dram_config[1] = 0x80000000ULL;
+#endif
 		break;
 
 	case PRR_PRODUCT_V3M:
@@ -795,6 +901,14 @@
 				str,
 				(reg & RCAR_MINOR_MASK) + RCAR_M3_MINOR_OFFSET);
 		}
+	} else if (product == PRR_PRODUCT_D3) {
+		if (RCAR_D3_CUT_VER10 == (reg & PRR_CUT_MASK)) {
+			NOTICE("BL2: PRR is R-Car %s Ver.1.0\n", str);
+		} else  if (RCAR_D3_CUT_VER11 == (reg & PRR_CUT_MASK)) {
+			NOTICE("BL2: PRR is R-Car %s Ver.1.1\n", str);
+		} else {
+			NOTICE("BL2: PRR is R-Car %s Ver.X.X\n", str);
+		}
 	} else {
 		major = (reg & RCAR_MAJOR_MASK) >> RCAR_MAJOR_SHIFT;
 		major = major + RCAR_MAJOR_OFFSET;
@@ -802,7 +916,7 @@
 		NOTICE("BL2: PRR is R-Car %s Ver.%d.%d\n", str, major, minor);
 	}
 
-	if (product == PRR_PRODUCT_E3) {
+	if (PRR_PRODUCT_E3 == product || PRR_PRODUCT_D3 == product) {
 		reg = mmio_read_32(RCAR_MODEMR);
 		sscg = reg & RCAR_SSCG_MASK;
 		str = sscg == RCAR_SSCG_ENABLE ? sscg_on : sscg_off;
@@ -866,10 +980,6 @@
 		str = boot_emmc25x1;
 		break;
 	case MODEMR_BOOT_DEV_EMMC_50X8:
-#if RCAR_LSI == RCAR_D3
-		ERROR("BL2: Failed to Initialize. eMMC is not supported.\n");
-		panic();
-#endif
 		str = boot_emmc50x8;
 		break;
 	default:
@@ -935,6 +1045,9 @@
 	/* Add platform compatible string */
 	bl2_populate_compatible_string(fdt);
 
+	/* Enable RPC if unlocked */
+	bl2_add_rpc_node();
+
 	/* Print DRAM layout */
 	bl2_advertise_dram_size(product);
 
diff --git a/plat/renesas/rcar/platform.mk b/plat/renesas/rcar/platform.mk
index 7a7a56c..670d499 100644
--- a/plat/renesas/rcar/platform.mk
+++ b/plat/renesas/rcar/platform.mk
@@ -245,6 +245,12 @@
 endif
 $(eval $(call add_define,RCAR_DRAM_LPDDR4_MEMCONF))
 
+# Process RCAR_DRAM_MEMRANK flag
+ifndef RCAR_DRAM_MEMRANK
+RCAR_DRAM_MEMRANK :=0
+endif
+$(eval $(call add_define,RCAR_DRAM_MEMRANK))
+
 # Process RCAR_DRAM_DDR3L_MEMCONF flag
 ifndef RCAR_DRAM_DDR3L_MEMCONF
 RCAR_DRAM_DDR3L_MEMCONF :=1
@@ -280,6 +286,11 @@
 endif
 $(eval $(call add_define,RCAR_SYSTEM_RESET_KEEPON_DDR))
 
+ifndef RCAR_GEN3_BL33_GZIP
+RCAR_GEN3_BL33_GZIP := 0
+endif
+$(eval $(call add_define,RCAR_GEN3_BL33_GZIP))
+
 # RCAR_SYSTEM_RESET_KEEPON_DDR requires power control of PMIC etc.
 # When executing SYSTEM_SUSPEND other than Salvator-X, Salvator-XS and Ebisu,
 # processing equivalent to that implemented in PMIC_ROHM_BD9571 is necessary.
@@ -315,6 +326,13 @@
 BL2_SOURCES	+=	plat/renesas/rcar/bl2_plat_setup.c	\
 			drivers/renesas/rcar/board/board.c
 
+ifeq (${RCAR_GEN3_BL33_GZIP},1)
+include lib/zlib/zlib.mk
+
+BL2_SOURCES	+=	common/image_decompress.c               \
+			$(ZLIB_SOURCES)
+endif
+
 ifeq (${RCAR_GEN3_ULCB},1)
 BL31_SOURCES		+=	drivers/renesas/rcar/cpld/ulcb_cpld.c
 endif
diff --git a/plat/rockchip/rk3399/drivers/dram/dram.h b/plat/rockchip/rk3399/drivers/dram/dram.h
index 0eb12cf..5572b16 100644
--- a/plat/rockchip/rk3399/drivers/dram/dram.h
+++ b/plat/rockchip/rk3399/drivers/dram/dram.h
@@ -149,7 +149,7 @@
 	uint32_t rx_cal_dqs[2][4];
 };
 
-extern __sramdata struct rk3399_sdram_params sdram_config;
+extern struct rk3399_sdram_params sdram_config;
 
 void dram_init(void);
 
diff --git a/plat/rockchip/rk3399/drivers/dram/suspend.c b/plat/rockchip/rk3399/drivers/dram/suspend.c
index 7f9fad1..a8b1c32 100644
--- a/plat/rockchip/rk3399/drivers/dram/suspend.c
+++ b/plat/rockchip/rk3399/drivers/dram/suspend.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -49,6 +49,7 @@
 
 __pmusramdata uint32_t dpll_data[PLL_CON_COUNT];
 __pmusramdata uint32_t cru_clksel_con6;
+__pmusramdata uint8_t pmu_enable_watchdog0;
 
 /*
  * Copy @num registers from @src to @dst
@@ -562,8 +563,14 @@
 
 	/* LPDDR4 f2 cann't do training, all training will fail */
 	for (ch = 0; ch < ch_count; ch++) {
-		mmio_clrsetbits_32(PHY_REG(ch, 896), (0x3 << 8) | 1,
-				   fn << 8);
+		/*
+		 * Without this disabled for LPDDR4 we end up writing 0's
+		 * in place of real data in an interesting pattern.
+		 */
+		if (sdram_params->dramtype != LPDDR4) {
+			mmio_clrsetbits_32(PHY_REG(ch, 896), (0x3 << 8) | 1,
+					fn << 8);
+		}
 
 		/* data_training failed */
 		if (data_training(ch, sdram_params, PI_FULL_TRAINING))
@@ -748,13 +755,44 @@
 	phy_regs->phy896[0] &= ~(0x3 << 8);
 }
 
+__pmusramfunc void phy_dll_bypass_set(uint32_t ch, uint32_t freq)
+{
+	if (freq <= (125 * 1000 * 1000)) {
+		/* Set master mode to SW for slices*/
+		mmio_setbits_32(PHY_REG(ch, 86), 3 << 10);
+		mmio_setbits_32(PHY_REG(ch, 214), 3 << 10);
+		mmio_setbits_32(PHY_REG(ch, 342), 3 << 10);
+		mmio_setbits_32(PHY_REG(ch, 470), 3 << 10);
+		/* Set master mode to SW for address slices*/
+		mmio_setbits_32(PHY_REG(ch, 547), 3 << 18);
+		mmio_setbits_32(PHY_REG(ch, 675), 3 << 18);
+		mmio_setbits_32(PHY_REG(ch, 803), 3 << 18);
+	} else {
+		/* Clear SW master mode for slices*/
+		mmio_clrbits_32(PHY_REG(ch, 86), 3 << 10);
+		mmio_clrbits_32(PHY_REG(ch, 214), 3 << 10);
+		mmio_clrbits_32(PHY_REG(ch, 342), 3 << 10);
+		mmio_clrbits_32(PHY_REG(ch, 470), 3 << 10);
+		/* Clear SW master mode for address slices*/
+		mmio_clrbits_32(PHY_REG(ch, 547), 3 << 18);
+		mmio_clrbits_32(PHY_REG(ch, 675), 3 << 18);
+		mmio_clrbits_32(PHY_REG(ch, 803), 3 << 18);
+	}
+}
+
 __pmusramfunc void dmc_resume(void)
 {
 	struct rk3399_sdram_params *sdram_params = &sdram_config;
 	uint32_t channel_mask = 0;
 	uint32_t channel;
 
-	pmusram_enable_watchdog();
+	/*
+	 * We can't turn off the watchdog, so if we have not turned it on before
+	 * we should not turn it on here.
+	 */
+	if ((pmu_enable_watchdog0 & 0x1) == 0x1) {
+		pmusram_enable_watchdog();
+	}
 	pmu_sgrf_rst_hld_release();
 	restore_pmu_rsthold();
 	sram_secure_timer_init();
@@ -772,6 +810,13 @@
 retry:
 	for (channel = 0; channel < sdram_params->num_channels; channel++) {
 		phy_pctrl_reset(channel);
+		/*
+		 * Without this, LPDDR4 will write 0's in place of real data
+		 * in a strange pattern.
+		 */
+		if (sdram_params->dramtype == LPDDR4) {
+			phy_dll_bypass_set(channel, sdram_params->ddr_freq);
+		}
 		pctl_cfg(channel, sdram_params);
 	}
 
@@ -788,8 +833,12 @@
 		if (sdram_params->dramtype == LPDDR3)
 			sram_udelay(10);
 
-		/* If traning fail, retry to do it again. */
-		if (data_training(channel, sdram_params, PI_FULL_TRAINING))
+		/*
+		 * Training here will always fail for LPDDR4, so skip it
+		 * If traning fail, retry to do it again.
+		 */
+		if (sdram_params->dramtype != LPDDR4 &&
+		    data_training(channel, sdram_params, PI_FULL_TRAINING))
 			goto retry;
 
 		set_ddrconfig(sdram_params, channel,
diff --git a/plat/rockchip/rk3399/drivers/dram/suspend.h b/plat/rockchip/rk3399/drivers/dram/suspend.h
index b99a926..1389944 100644
--- a/plat/rockchip/rk3399/drivers/dram/suspend.h
+++ b/plat/rockchip/rk3399/drivers/dram/suspend.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,6 +7,7 @@
 #ifndef SUSPEND_H
 #define SUSPEND_H
 
+#include <stdint.h>
 #include <dram.h>
 
 #define KHz (1000)
@@ -22,5 +23,6 @@
 
 void dmc_suspend(void);
 __pmusramfunc void dmc_resume(void);
+extern __pmusramdata uint8_t pmu_enable_watchdog0;
 
 #endif /* SUSPEND_H */
diff --git a/plat/rockchip/rk3399/drivers/pmu/pmu.c b/plat/rockchip/rk3399/drivers/pmu/pmu.c
index faee678..3084c4f 100644
--- a/plat/rockchip/rk3399/drivers/pmu/pmu.c
+++ b/plat/rockchip/rk3399/drivers/pmu/pmu.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -1324,6 +1324,7 @@
 		store_wdt0[i] = mmio_read_32(WDT0_BASE + i * 4);
 		store_wdt1[i] = mmio_read_32(WDT1_BASE + i * 4);
 	}
+	pmu_enable_watchdog0 = (uint8_t) store_wdt0[0] & 0x1;
 }
 
 void wdt_register_restore(void)
diff --git a/plat/rpi/rpi4/platform.mk b/plat/rpi/rpi4/platform.mk
index 99d51fb..528eb1d 100644
--- a/plat/rpi/rpi4/platform.mk
+++ b/plat/rpi/rpi4/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -86,6 +86,9 @@
 # Use normal memory mapping for ROM, FIP, SRAM and DRAM
 RPI3_USE_UEFI_MAP		:= 0
 
+# SMCCC PCI support (should be enabled for ACPI builds)
+SMC_PCI_SUPPORT            	:= 0
+
 # Process platform flags
 # ----------------------
 
@@ -96,6 +99,7 @@
 endif
 $(eval $(call add_define,RPI3_RUNTIME_UART))
 $(eval $(call add_define,RPI3_USE_UEFI_MAP))
+$(eval $(call add_define,SMC_PCI_SUPPORT))
 
 ifeq (${ARCH},aarch32)
   $(error Error: AArch32 not supported on rpi4)
@@ -105,3 +109,8 @@
 PLAT_BL_COMMON_SOURCES	+=	drivers/rpi3/rng/rpi3_rng.c		\
 				plat/rpi/common/rpi3_stack_protector.c
 endif
+
+ifeq ($(SMC_PCI_SUPPORT), 1)
+BL31_SOURCES            +=      plat/rpi/rpi4/rpi4_pci_svc.c
+endif
+
diff --git a/plat/rpi/rpi4/rpi4_bl31_setup.c b/plat/rpi/rpi4/rpi4_bl31_setup.c
index cfacd1f..5259859 100644
--- a/plat/rpi/rpi4/rpi4_bl31_setup.c
+++ b/plat/rpi/rpi4/rpi4_bl31_setup.c
@@ -201,6 +201,44 @@
 	enable_mmu_el3(0);
 }
 
+/*
+ * Remove the FDT /memreserve/ entry that covers the region at the very
+ * beginning of memory (if that exists). This is where the secondaries
+ * originally spin, but we pull them out there.
+ * Having overlapping /reserved-memory and /memreserve/ regions confuses
+ * the Linux kernel, so we need to get rid of this one.
+ */
+static void remove_spintable_memreserve(void *dtb)
+{
+	uint64_t addr, size;
+	int regions = fdt_num_mem_rsv(dtb);
+	int i;
+
+	for (i = 0; i < regions; i++) {
+		if (fdt_get_mem_rsv(dtb, i, &addr, &size) != 0) {
+			return;
+		}
+		if (size == 0U) {
+			return;
+		}
+		/* We only look for the region at the beginning of DRAM. */
+		if (addr != 0U) {
+			continue;
+		}
+		/*
+		 * Currently the region in the existing DTs is exactly 4K
+		 * in size. Should this value ever change, there is probably
+		 * a reason for that, so inform the user about this.
+		 */
+		if (size == 4096U) {
+			fdt_del_mem_rsv(dtb, i);
+			return;
+		}
+		WARN("Keeping unknown /memreserve/ region at 0, size: %lld\n",
+		     size);
+	}
+}
+
 static void rpi4_prepare_dtb(void)
 {
 	void *dtb = (void *)rpi4_get_dtb_address();
@@ -227,7 +265,11 @@
 		return;
 	}
 
-	/* Reserve memory used by Trusted Firmware. */
+	/*
+	 * Remove the original reserved region (used for the spintable), and
+	 * replace it with a region describing the whole of Trusted Firmware.
+	 */
+	remove_spintable_memreserve(dtb);
 	if (fdt_add_reserved_memory(dtb, "atf@0", 0, 0x80000))
 		WARN("Failed to add reserved memory nodes to DT.\n");
 
diff --git a/plat/rpi/rpi4/rpi4_pci_svc.c b/plat/rpi/rpi4/rpi4_pci_svc.c
new file mode 100644
index 0000000..7d1ca5c
--- /dev/null
+++ b/plat/rpi/rpi4/rpi4_pci_svc.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * The RPi4 has a single nonstandard PCI config region. It is broken into two
+ * pieces, the root port config registers and a window to a single device's
+ * config space which can move between devices. There isn't (yet) an
+ * authoritative public document on this since the available BCM2711 reference
+ * notes that there is a PCIe root port in the memory map but doesn't describe
+ * it. Given that it's not ECAM compliant yet reasonably simple, it makes for
+ * an excellent example of the PCI SMCCC interface.
+ *
+ * The PCI SMCCC interface is described in DEN0115 availabe from:
+ * https://developer.arm.com/documentation/den0115/latest
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/pmf/pmf.h>
+#include <lib/runtime_instr.h>
+#include <services/pci_svc.h>
+#include <services/sdei.h>
+#include <services/std_svc.h>
+#include <smccc_helpers.h>
+
+#include <lib/mmio.h>
+
+static spinlock_t pci_lock;
+
+#define PCIE_REG_BASE		U(RPI_IO_BASE + 0x01500000)
+#define PCIE_MISC_PCIE_STATUS	0x4068
+#define PCIE_EXT_CFG_INDEX	0x9000
+/* A small window pointing at the ECAM of the device selected by CFG_INDEX */
+#define PCIE_EXT_CFG_DATA	0x8000
+#define INVALID_PCI_ADDR	0xFFFFFFFF
+
+#define	PCIE_EXT_BUS_SHIFT	20
+#define	PCIE_EXT_DEV_SHIFT	15
+#define	PCIE_EXT_FUN_SHIFT	12
+
+
+static uint64_t pci_segment_lib_get_base(uint32_t address, uint32_t offset)
+{
+	uint64_t	base;
+	uint32_t	bus, dev, fun;
+	uint32_t	status;
+
+	base = PCIE_REG_BASE;
+
+	offset &= PCI_OFFSET_MASK;  /* Pick off the 4k register offset */
+
+	/* The root port is at the base of the PCIe register space */
+	if (address != 0U) {
+		/*
+		 * The current device must be at CFG_DATA, a 4K window mapped,
+		 * via CFG_INDEX, to the device we are accessing. At the same
+		 * time we must avoid accesses to certain areas of the cfg
+		 * space via CFG_DATA. Detect those accesses and report that
+		 * the address is invalid.
+		 */
+		base += PCIE_EXT_CFG_DATA;
+		bus = PCI_ADDR_BUS(address);
+		dev = PCI_ADDR_DEV(address);
+		fun = PCI_ADDR_FUN(address);
+		address = (bus << PCIE_EXT_BUS_SHIFT) |
+			  (dev << PCIE_EXT_DEV_SHIFT) |
+			  (fun << PCIE_EXT_FUN_SHIFT);
+
+		/* Allow only dev = 0 on root port and bus 1 */
+		if ((bus < 2U) && (dev > 0U)) {
+			return INVALID_PCI_ADDR;
+		}
+
+		/* Assure link up before reading bus 1 */
+		status = mmio_read_32(PCIE_REG_BASE + PCIE_MISC_PCIE_STATUS);
+		if ((status & 0x30) != 0x30) {
+			return INVALID_PCI_ADDR;
+		}
+
+		/* Adjust which device the CFG_DATA window is pointing at */
+		mmio_write_32(PCIE_REG_BASE + PCIE_EXT_CFG_INDEX, address);
+	}
+	return base + offset;
+}
+
+/**
+ * pci_read_config() - Performs a config space read at addr
+ * @addr: 32-bit, segment, BDF of requested function encoded per DEN0115
+ * @off:  register offset of function described by @addr to read
+ * @sz:	  size of read (8,16,32) bits.
+ * @val:  returned zero extended value read from config space
+ *
+ * sz bits of PCI config space is read at addr:offset, and the value
+ * is returned in val. Invalid segment/offset values return failure.
+ * Reads to valid functions that don't exist return INVALID_PCI_ADDR
+ * as is specified by PCI for requests that aren't completed by EPs.
+ * The boilerplate in pci_svc.c tends to do basic segment, off
+ * and sz validation. This routine should avoid duplicating those
+ * checks.
+ *
+ * This function maps directly to the PCI_READ function in DEN0115
+ * where detailed requirements may be found.
+ *
+ * Return: SMC_PCI_CALL_SUCCESS with val set
+ *	   SMC_PCI_CALL_INVAL_PARAM, on parameter error
+ */
+uint32_t pci_read_config(uint32_t addr, uint32_t off, uint32_t sz, uint32_t *val)
+{
+	uint32_t ret = SMC_PCI_CALL_SUCCESS;
+	uint64_t base;
+
+	spin_lock(&pci_lock);
+	base = pci_segment_lib_get_base(addr, off);
+
+	if (base == INVALID_PCI_ADDR) {
+		*val = base;
+	} else {
+		switch (sz) {
+		case SMC_PCI_SZ_8BIT:
+			*val = mmio_read_8(base);
+			break;
+		case SMC_PCI_SZ_16BIT:
+			*val = mmio_read_16(base);
+			break;
+		case SMC_PCI_SZ_32BIT:
+			*val = mmio_read_32(base);
+			break;
+		default: /* should be unreachable */
+			*val = 0;
+			ret = SMC_PCI_CALL_INVAL_PARAM;
+		}
+	}
+	spin_unlock(&pci_lock);
+	return ret;
+}
+
+/**
+ * pci_write_config() - Performs a config space write at addr
+ * @addr: 32-bit, segment, BDF of requested function encoded per DEN0115
+ * @off:  register offset of function described by @addr to write
+ * @sz:	  size of write (8,16,32) bits.
+ * @val:  value to be written
+ *
+ * sz bits of PCI config space is written at addr:offset. Invalid
+ * segment/BDF values return failure. Writes to valid functions
+ * without valid EPs are ignored, as is specified by PCI.
+ * The boilerplate in pci_svc.c tends to do basic segment, off
+ * and sz validation, so it shouldn't need to be repeated here.
+ *
+ * This function maps directly to the PCI_WRITE function in DEN0115
+ * where detailed requirements may be found.
+ *
+ * Return: SMC_PCI_CALL_SUCCESS
+ *	   SMC_PCI_CALL_INVAL_PARAM, on parameter error
+ */
+uint32_t pci_write_config(uint32_t addr, uint32_t off, uint32_t sz, uint32_t val)
+{
+	uint32_t ret = SMC_PCI_CALL_SUCCESS;
+	uint64_t base;
+
+	spin_lock(&pci_lock);
+	base = pci_segment_lib_get_base(addr, off);
+
+	if (base != INVALID_PCI_ADDR) {
+		switch (sz) {
+		case SMC_PCI_SZ_8BIT:
+			mmio_write_8(base, val);
+			break;
+		case SMC_PCI_SZ_16BIT:
+			mmio_write_16(base, val);
+			break;
+		case SMC_PCI_SZ_32BIT:
+			mmio_write_32(base, val);
+			break;
+		default: /* should be unreachable */
+			ret = SMC_PCI_CALL_INVAL_PARAM;
+		}
+	}
+	spin_unlock(&pci_lock);
+	return ret;
+}
+
+/**
+ * pci_get_bus_for_seg() - returns the start->end bus range for a segment
+ * @seg:  segment being queried
+ * @bus_range:	returned bus begin + (end << 8)
+ * @nseg: returns next segment in this machine or 0 for end
+ *
+ * pci_get_bus_for_seg is called to check if a given segment is
+ * valid on this machine. If it is valid, then its bus ranges are
+ * returned along with the next valid segment on the machine. If
+ * this is the last segment, then nseg must be 0.
+ *
+ * This function maps directly to the PCI_GET_SEG_INFO function
+ * in DEN0115 where detailed requirements may be found.
+ *
+ * Return: SMC_PCI_CALL_SUCCESS, and appropriate bus_range and nseg
+ *	   SMC_PCI_CALL_NOT_IMPL, if the segment is invalid
+ */
+uint32_t pci_get_bus_for_seg(uint32_t seg, uint32_t *bus_range, uint32_t *nseg)
+{
+	uint32_t ret = SMC_PCI_CALL_SUCCESS;
+	*nseg = 0U; /* only a single segment */
+	if (seg == 0U) {
+		*bus_range = 0xFF00; /* start 0, end 255 */
+	} else {
+		*bus_range = 0U;
+		ret = SMC_PCI_CALL_NOT_IMPL;
+	}
+	return ret;
+}
diff --git a/plat/socionext/synquacer/sq_psci.c b/plat/socionext/synquacer/sq_psci.c
index 0c97fcf..4168df9 100644
--- a/plat/socionext/synquacer/sq_psci.c
+++ b/plat/socionext/synquacer/sq_psci.c
@@ -97,6 +97,14 @@
 void sq_pwr_domain_off(const psci_power_state_t *target_state)
 {
 #if SQ_USE_SCMI_DRIVER
+	/* Prevent interrupts from spuriously waking up this cpu */
+	sq_gic_cpuif_disable();
+
+	/* Cluster is to be turned off, so disable coherency */
+	if (SQ_CLUSTER_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF) {
+		plat_sq_interconnect_exit_coherency();
+	}
+
 	sq_scmi_off(target_state);
 #else
 	sq_power_down_common(target_state);
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
index e603267..7e76083 100644
--- a/plat/st/common/bl2_io_storage.c
+++ b/plat/st/common/bl2_io_storage.c
@@ -7,13 +7,12 @@
 #include <assert.h>
 #include <string.h>
 
-#include <platform_def.h>
-
 #include <arch_helpers.h>
 #include <common/debug.h>
+#include <common/desc_image_load.h>
 #include <drivers/io/io_block.h>
 #include <drivers/io/io_driver.h>
-#include <drivers/io/io_dummy.h>
+#include <drivers/io/io_fip.h>
 #include <drivers/io/io_mtd.h>
 #include <drivers/io/io_storage.h>
 #include <drivers/mmc.h>
@@ -22,34 +21,30 @@
 #include <drivers/spi_nand.h>
 #include <drivers/spi_nor.h>
 #include <drivers/st/io_mmc.h>
-#include <drivers/st/io_stm32image.h>
 #include <drivers/st/stm32_fmc2_nand.h>
 #include <drivers/st/stm32_qspi.h>
 #include <drivers/st/stm32_sdmmc2.h>
+#include <lib/fconf/fconf.h>
 #include <lib/mmio.h>
 #include <lib/utils.h>
 #include <plat/common/platform.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <platform_def.h>
+#include <stm32mp_fconf_getter.h>
 
 /* IO devices */
-#ifndef AARCH32_SP_OPTEE
-static const io_dev_connector_t *dummy_dev_con;
-static uintptr_t dummy_dev_handle;
-static uintptr_t dummy_dev_spec;
-#endif
+uintptr_t fip_dev_handle;
+uintptr_t storage_dev_handle;
 
-static uintptr_t image_dev_handle;
-static uintptr_t storage_dev_handle;
+static const io_dev_connector_t *fip_dev_con;
 
 #if STM32MP_SDMMC || STM32MP_EMMC
 static struct mmc_device_info mmc_info;
-static io_block_spec_t gpt_block_spec = {
-	.offset = 0,
-	.length = 34 * MMC_BLOCK_SIZE, /* Size of GPT table */
-};
 
 static uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE);
 
-static const io_block_dev_spec_t mmc_block_dev_spec = {
+static io_block_dev_spec_t mmc_block_dev_spec = {
 	/* It's used as temp buffer in block driver */
 	.buffer = {
 		.offset = (size_t)&block_buffer,
@@ -62,30 +57,6 @@
 	.block_size = MMC_BLOCK_SIZE,
 };
 
-#if STM32MP_EMMC_BOOT
-static io_block_spec_t emmc_boot_ssbl_block_spec = {
-	.offset = PLAT_EMMC_BOOT_SSBL_OFFSET,
-	.length = MMC_BLOCK_SIZE, /* We are interested only in first 4 bytes */
-};
-
-static const io_block_dev_spec_t mmc_block_dev_boot_part_spec = {
-	/* It's used as temp buffer in block driver */
-	.buffer = {
-		.offset = (size_t)&block_buffer,
-		.length = MMC_BLOCK_SIZE,
-	},
-	.ops = {
-		.read = mmc_boot_part_read_blocks,
-		.write = NULL,
-	},
-	.block_size = MMC_BLOCK_SIZE,
-};
-#endif
-
-static struct io_mmc_dev_spec mmc_device_spec = {
-	.use_boot_part = false,
-};
-
 static const io_dev_connector_t *mmc_dev_con;
 #endif /* STM32MP_SDMMC || STM32MP_EMMC */
 
@@ -103,6 +74,7 @@
 	.ops = {
 		.init = nand_raw_init,
 		.read = nand_read,
+		.seek = nand_seek_bb
 	},
 };
 
@@ -114,6 +86,7 @@
 	.ops = {
 		.init = spi_nand_init,
 		.read = nand_read,
+		.seek = nand_seek_bb
 	},
 };
 #endif
@@ -122,176 +95,21 @@
 static const io_dev_connector_t *spi_dev_con;
 #endif
 
-#ifdef AARCH32_SP_OPTEE
-static const struct stm32image_part_info optee_header_partition_spec = {
-	.name = OPTEE_HEADER_IMAGE_NAME,
-	.binary_type = OPTEE_HEADER_BINARY_TYPE,
-};
-
-static const struct stm32image_part_info optee_core_partition_spec = {
-	.name = OPTEE_CORE_IMAGE_NAME,
-	.binary_type = OPTEE_CORE_BINARY_TYPE,
-};
-
-static const struct stm32image_part_info optee_paged_partition_spec = {
-	.name = OPTEE_PAGED_IMAGE_NAME,
-	.binary_type = OPTEE_PAGED_BINARY_TYPE,
-};
-#else
-static const io_block_spec_t bl32_block_spec = {
-	.offset = BL32_BASE,
-	.length = STM32MP_BL32_SIZE
-};
-#endif
-
-static const struct stm32image_part_info bl33_partition_spec = {
-	.name = BL33_IMAGE_NAME,
-	.binary_type = BL33_BINARY_TYPE,
-};
-
-enum {
-	IMG_IDX_BL33,
-#ifdef AARCH32_SP_OPTEE
-	IMG_IDX_OPTEE_HEADER,
-	IMG_IDX_OPTEE_CORE,
-	IMG_IDX_OPTEE_PAGED,
-#endif
-	IMG_IDX_NUM
-};
-
-static struct stm32image_device_info stm32image_dev_info_spec __unused = {
-	.lba_size = MMC_BLOCK_SIZE,
-	.part_info[IMG_IDX_BL33] = {
-		.name = BL33_IMAGE_NAME,
-		.binary_type = BL33_BINARY_TYPE,
-	},
-#ifdef AARCH32_SP_OPTEE
-	.part_info[IMG_IDX_OPTEE_HEADER] = {
-		.name = OPTEE_HEADER_IMAGE_NAME,
-		.binary_type = OPTEE_HEADER_BINARY_TYPE,
-	},
-	.part_info[IMG_IDX_OPTEE_CORE] = {
-		.name = OPTEE_CORE_IMAGE_NAME,
-		.binary_type = OPTEE_CORE_BINARY_TYPE,
-	},
-	.part_info[IMG_IDX_OPTEE_PAGED] = {
-		.name = OPTEE_PAGED_IMAGE_NAME,
-		.binary_type = OPTEE_PAGED_BINARY_TYPE,
-	},
-#endif
-};
-
-static io_block_spec_t stm32image_block_spec = {
-	.offset = 0,
-	.length = 0,
+io_block_spec_t image_block_spec = {
+	.offset = 0U,
+	.length = 0U,
 };
 
-static const io_dev_connector_t *stm32image_dev_con __unused;
-
-#ifndef AARCH32_SP_OPTEE
-static int open_dummy(const uintptr_t spec);
-#endif
-static int open_image(const uintptr_t spec);
-static int open_storage(const uintptr_t spec);
-
-struct plat_io_policy {
-	uintptr_t *dev_handle;
-	uintptr_t image_spec;
-	int (*check)(const uintptr_t spec);
-};
-
-static const struct plat_io_policy policies[] = {
-#ifdef AARCH32_SP_OPTEE
-	[BL32_IMAGE_ID] = {
-		.dev_handle = &image_dev_handle,
-		.image_spec = (uintptr_t)&optee_header_partition_spec,
-		.check = open_image
-	},
-	[BL32_EXTRA1_IMAGE_ID] = {
-		.dev_handle = &image_dev_handle,
-		.image_spec = (uintptr_t)&optee_core_partition_spec,
-		.check = open_image
-	},
-	[BL32_EXTRA2_IMAGE_ID] = {
-		.dev_handle = &image_dev_handle,
-		.image_spec = (uintptr_t)&optee_paged_partition_spec,
-		.check = open_image
-	},
-#else
-	[BL32_IMAGE_ID] = {
-		.dev_handle = &dummy_dev_handle,
-		.image_spec = (uintptr_t)&bl32_block_spec,
-		.check = open_dummy
-	},
-#endif
-	[BL33_IMAGE_ID] = {
-		.dev_handle = &image_dev_handle,
-		.image_spec = (uintptr_t)&bl33_partition_spec,
-		.check = open_image
-	},
-#if STM32MP_SDMMC || STM32MP_EMMC
-	[GPT_IMAGE_ID] = {
-		.dev_handle = &storage_dev_handle,
-		.image_spec = (uintptr_t)&gpt_block_spec,
-		.check = open_storage
-	},
-#endif
-	[STM32_IMAGE_ID] = {
-		.dev_handle = &storage_dev_handle,
-		.image_spec = (uintptr_t)&stm32image_block_spec,
-		.check = open_storage
-	}
-};
-
-#ifndef AARCH32_SP_OPTEE
-static int open_dummy(const uintptr_t spec)
-{
-	return io_dev_init(dummy_dev_handle, 0);
-}
-#endif
-
-static int open_image(const uintptr_t spec)
+int open_fip(const uintptr_t spec)
 {
-	return io_dev_init(image_dev_handle, 0);
+	return io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
 }
 
-static int open_storage(const uintptr_t spec)
+int open_storage(const uintptr_t spec)
 {
 	return io_dev_init(storage_dev_handle, 0);
 }
 
-#if STM32MP_EMMC_BOOT
-static uint32_t get_boot_part_ssbl_header(void)
-{
-	uint32_t magic = 0;
-	int io_result;
-	size_t bytes_read;
-
-	io_result = register_io_dev_block(&mmc_dev_con);
-	if (io_result != 0) {
-		panic();
-	}
-
-	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_boot_part_spec,
-				&storage_dev_handle);
-	assert(io_result == 0);
-
-	io_result = io_open(storage_dev_handle, (uintptr_t) &emmc_boot_ssbl_block_spec,
-			    &image_dev_handle);
-	assert(io_result == 0);
-
-	io_result = io_read(image_dev_handle, (uintptr_t) &magic, sizeof(magic),
-			    &bytes_read);
-	assert(io_result == 0);
-	assert(bytes_read == sizeof(magic));
-
-	io_result = io_dev_close(storage_dev_handle);
-	assert(io_result == 0);
-
-	return magic;
-}
-#endif
-
 static void print_boot_device(boot_api_context_t *boot_context)
 {
 	switch (boot_context->boot_interface_selected) {
@@ -311,7 +129,8 @@
 		INFO("Using SPI NAND\n");
 		break;
 	default:
-		ERROR("Boot interface not found\n");
+		ERROR("Boot interface %u not found\n",
+		      boot_context->boot_interface_selected);
 		panic();
 		break;
 	}
@@ -321,29 +140,12 @@
 	}
 }
 
-static void stm32image_io_setup(void)
-{
-	int io_result __unused;
-
-	io_result = register_io_dev_stm32image(&stm32image_dev_con);
-	assert(io_result == 0);
-
-	io_result = io_dev_open(stm32image_dev_con,
-				(uintptr_t)&stm32image_dev_info_spec,
-				&image_dev_handle);
-	assert(io_result == 0);
-}
-
 #if STM32MP_SDMMC || STM32MP_EMMC
 static void boot_mmc(enum mmc_device_type mmc_dev_type,
 		     uint16_t boot_interface_instance)
 {
 	int io_result __unused;
-	uint8_t idx;
-	struct stm32image_part_info *part;
 	struct stm32_sdmmc2_params params;
-	const partition_entry_t *entry __unused;
-	uint32_t magic __unused;
 
 	zeromem(&params, sizeof(struct stm32_sdmmc2_params));
 
@@ -375,26 +177,6 @@
 		panic();
 	}
 
-	stm32image_dev_info_spec.device_size =
-		stm32_sdmmc2_mmc_get_device_size();
-
-#if STM32MP_EMMC_BOOT
-	magic = get_boot_part_ssbl_header();
-
-	if (magic == BOOT_API_IMAGE_HEADER_MAGIC_NB) {
-		VERBOSE("%s, header found, jump to emmc load\n", __func__);
-		idx = IMG_IDX_BL33;
-		part = &stm32image_dev_info_spec.part_info[idx];
-		part->part_offset = PLAT_EMMC_BOOT_SSBL_OFFSET;
-		part->bkp_offset = 0U;
-		mmc_device_spec.use_boot_part = true;
-
-		goto emmc_boot;
-	} else {
-		WARN("%s: Can't find STM32 header on a boot partition\n", __func__);
-	}
-#endif
-
 	/* Open MMC as a block device to read GPT table */
 	io_result = register_io_dev_block(&mmc_dev_con);
 	if (io_result != 0) {
@@ -404,37 +186,6 @@
 	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_spec,
 				&storage_dev_handle);
 	assert(io_result == 0);
-
-	partition_init(GPT_IMAGE_ID);
-
-	io_result = io_dev_close(storage_dev_handle);
-	assert(io_result == 0);
-
-	for (idx = 0U; idx < IMG_IDX_NUM; idx++) {
-		part = &stm32image_dev_info_spec.part_info[idx];
-		entry = get_partition_entry(part->name);
-		if (entry == NULL) {
-			ERROR("Partition %s not found\n", part->name);
-			panic();
-		}
-
-		part->part_offset = entry->start;
-		part->bkp_offset = 0U;
-	}
-
-#if STM32MP_EMMC_BOOT
-emmc_boot:
-#endif
-	/*
-	 * Re-open MMC with io_mmc, for better perfs compared to
-	 * io_block.
-	 */
-	io_result = register_io_dev_mmc(&mmc_dev_con);
-	assert(io_result == 0);
-
-	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_device_spec,
-				&storage_dev_handle);
-	assert(io_result == 0);
 }
 #endif /* STM32MP_SDMMC || STM32MP_EMMC */
 
@@ -442,8 +193,6 @@
 static void boot_spi_nor(boot_api_context_t *boot_context)
 {
 	int io_result __unused;
-	uint8_t idx;
-	struct stm32image_part_info *part;
 
 	io_result = stm32_qspi_init();
 	assert(io_result == 0);
@@ -456,30 +205,6 @@
 				(uintptr_t)&spi_nor_dev_spec,
 				&storage_dev_handle);
 	assert(io_result == 0);
-
-	stm32image_dev_info_spec.device_size = spi_nor_dev_spec.device_size;
-
-	idx = IMG_IDX_BL33;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NOR_BL33_OFFSET;
-	part->bkp_offset = 0U;
-
-#ifdef AARCH32_SP_OPTEE
-	idx = IMG_IDX_OPTEE_HEADER;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NOR_TEEH_OFFSET;
-	part->bkp_offset = 0U;
-
-	idx = IMG_IDX_OPTEE_PAGED;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NOR_TEED_OFFSET;
-	part->bkp_offset = 0U;
-
-	idx = IMG_IDX_OPTEE_CORE;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NOR_TEEX_OFFSET;
-	part->bkp_offset = 0U;
-#endif
 }
 #endif /* STM32MP_SPI_NOR */
 
@@ -487,8 +212,6 @@
 static void boot_fmc2_nand(boot_api_context_t *boot_context)
 {
 	int io_result __unused;
-	uint8_t idx;
-	struct stm32image_part_info *part;
 
 	io_result = stm32_fmc2_init();
 	assert(io_result == 0);
@@ -501,30 +224,6 @@
 	io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec,
 				&storage_dev_handle);
 	assert(io_result == 0);
-
-	stm32image_dev_info_spec.device_size = nand_dev_spec.device_size;
-
-	idx = IMG_IDX_BL33;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_BL33_OFFSET;
-	part->bkp_offset = nand_dev_spec.erase_size;
-
-#ifdef AARCH32_SP_OPTEE
-	idx = IMG_IDX_OPTEE_HEADER;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_TEEH_OFFSET;
-	part->bkp_offset = nand_dev_spec.erase_size;
-
-	idx = IMG_IDX_OPTEE_PAGED;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_TEED_OFFSET;
-	part->bkp_offset = nand_dev_spec.erase_size;
-
-	idx = IMG_IDX_OPTEE_CORE;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_TEEX_OFFSET;
-	part->bkp_offset = nand_dev_spec.erase_size;
-#endif
 }
 #endif /* STM32MP_RAW_NAND */
 
@@ -532,8 +231,6 @@
 static void boot_spi_nand(boot_api_context_t *boot_context)
 {
 	int io_result __unused;
-	uint8_t idx;
-	struct stm32image_part_info *part;
 
 	io_result = stm32_qspi_init();
 	assert(io_result == 0);
@@ -546,31 +243,6 @@
 				(uintptr_t)&spi_nand_dev_spec,
 				&storage_dev_handle);
 	assert(io_result == 0);
-
-	stm32image_dev_info_spec.device_size =
-		spi_nand_dev_spec.device_size;
-
-	idx = IMG_IDX_BL33;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_BL33_OFFSET;
-	part->bkp_offset = spi_nand_dev_spec.erase_size;
-
-#ifdef AARCH32_SP_OPTEE
-	idx = IMG_IDX_OPTEE_HEADER;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_TEEH_OFFSET;
-	part->bkp_offset = spi_nand_dev_spec.erase_size;
-
-	idx = IMG_IDX_OPTEE_PAGED;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_TEED_OFFSET;
-	part->bkp_offset = spi_nand_dev_spec.erase_size;
-
-	idx = IMG_IDX_OPTEE_CORE;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_TEEX_OFFSET;
-	part->bkp_offset = spi_nand_dev_spec.erase_size;
-#endif
 }
 #endif /* STM32MP_SPI_NAND */
 
@@ -584,53 +256,45 @@
 
 	if ((boot_context->boot_partition_used_toboot == 1U) ||
 	    (boot_context->boot_partition_used_toboot == 2U)) {
-		INFO("Boot used partition fsbl%d\n",
+		INFO("Boot used partition fsbl%u\n",
 		     boot_context->boot_partition_used_toboot);
 	}
 
-#ifndef AARCH32_SP_OPTEE
-	io_result = register_io_dev_dummy(&dummy_dev_con);
+	io_result = register_io_dev_fip(&fip_dev_con);
 	assert(io_result == 0);
 
-	io_result = io_dev_open(dummy_dev_con, dummy_dev_spec,
-				&dummy_dev_handle);
-	assert(io_result == 0);
-#endif
+	io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
+				&fip_dev_handle);
 
 	switch (boot_context->boot_interface_selected) {
 #if STM32MP_SDMMC
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
 		dmbsy();
 		boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance);
-		stm32image_io_setup();
 		break;
 #endif
 #if STM32MP_EMMC
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
 		dmbsy();
 		boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance);
-		stm32image_io_setup();
 		break;
 #endif
 #if STM32MP_SPI_NOR
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
 		dmbsy();
 		boot_spi_nor(boot_context);
-		stm32image_io_setup();
 		break;
 #endif
 #if STM32MP_RAW_NAND
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
 		dmbsy();
 		boot_fmc2_nand(boot_context);
-		stm32image_io_setup();
 		break;
 #endif
 #if STM32MP_SPI_NAND
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
 		dmbsy();
 		boot_spi_nand(boot_context);
-		stm32image_io_setup();
 		break;
 #endif
 
@@ -642,6 +306,65 @@
 	}
 }
 
+int bl2_plat_handle_pre_image_load(unsigned int image_id)
+{
+	static bool gpt_init_done __unused;
+	uint16_t boot_itf = stm32mp_get_boot_itf_selected();
+
+	switch (boot_itf) {
+#if STM32MP_SDMMC || STM32MP_EMMC
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
+		if (!gpt_init_done) {
+			const partition_entry_t *entry;
+
+			partition_init(GPT_IMAGE_ID);
+			entry = get_partition_entry(FIP_IMAGE_NAME);
+			if (entry == NULL) {
+				ERROR("Could NOT find the %s partition!\n",
+				      FIP_IMAGE_NAME);
+				return -ENOENT;
+			}
+
+			image_block_spec.offset = entry->start;
+			image_block_spec.length = entry->length;
+
+			gpt_init_done = true;
+		} else {
+			bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+
+			mmc_block_dev_spec.buffer.offset = bl_mem_params->image_info.image_base;
+			mmc_block_dev_spec.buffer.length = bl_mem_params->image_info.image_max_size;
+		}
+
+		break;
+#endif
+
+#if STM32MP_RAW_NAND || STM32MP_SPI_NAND
+#if STM32MP_RAW_NAND
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
+#endif
+#if STM32MP_SPI_NAND
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
+#endif
+		image_block_spec.offset = STM32MP_NAND_FIP_OFFSET;
+		break;
+#endif
+
+#if STM32MP_SPI_NOR
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
+		image_block_spec.offset = STM32MP_NOR_FIP_OFFSET;
+		break;
+#endif
+
+	default:
+		ERROR("FIP Not found\n");
+		panic();
+	}
+
+	return 0;
+}
+
 /*
  * Return an IO device handle and specification which can be used to access
  * an image. Use this to enforce platform load policy.
@@ -652,9 +375,7 @@
 	int rc;
 	const struct plat_io_policy *policy;
 
-	assert(image_id < ARRAY_SIZE(policies));
-
-	policy = &policies[image_id];
+	policy = FCONF_GET_PROPERTY(stm32mp, io_policies, image_id);
 	rc = policy->check(policy->image_spec);
 	if (rc == 0) {
 		*image_spec = policy->image_spec;
diff --git a/plat/st/common/bl2_stm32_io_storage.c b/plat/st/common/bl2_stm32_io_storage.c
new file mode 100644
index 0000000..2d68a50
--- /dev/null
+++ b/plat/st/common/bl2_stm32_io_storage.c
@@ -0,0 +1,665 @@
+/*
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/io/io_block.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_dummy.h>
+#include <drivers/io/io_mtd.h>
+#include <drivers/io/io_storage.h>
+#include <drivers/mmc.h>
+#include <drivers/partition/partition.h>
+#include <drivers/raw_nand.h>
+#include <drivers/spi_nand.h>
+#include <drivers/spi_nor.h>
+#include <drivers/st/io_mmc.h>
+#include <drivers/st/io_stm32image.h>
+#include <drivers/st/stm32_fmc2_nand.h>
+#include <drivers/st/stm32_qspi.h>
+#include <drivers/st/stm32_sdmmc2.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+/* IO devices */
+#ifndef AARCH32_SP_OPTEE
+static const io_dev_connector_t *dummy_dev_con;
+static uintptr_t dummy_dev_handle;
+static uintptr_t dummy_dev_spec;
+#endif
+
+static uintptr_t image_dev_handle;
+static uintptr_t storage_dev_handle;
+
+#if STM32MP_SDMMC || STM32MP_EMMC
+static struct mmc_device_info mmc_info;
+static io_block_spec_t gpt_block_spec = {
+	.offset = 0U,
+	.length = 34U * MMC_BLOCK_SIZE, /* Size of GPT table */
+};
+
+static uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE);
+
+static const io_block_dev_spec_t mmc_block_dev_spec = {
+	/* It's used as temp buffer in block driver */
+	.buffer = {
+		.offset = (size_t)&block_buffer,
+		.length = MMC_BLOCK_SIZE,
+	},
+	.ops = {
+		.read = mmc_read_blocks,
+		.write = NULL,
+	},
+	.block_size = MMC_BLOCK_SIZE,
+};
+
+#if STM32MP_EMMC_BOOT
+static io_block_spec_t emmc_boot_ssbl_block_spec = {
+	.offset = PLAT_EMMC_BOOT_SSBL_OFFSET,
+	.length = MMC_BLOCK_SIZE, /* We are interested only in first 4 bytes */
+};
+
+static const io_block_dev_spec_t mmc_block_dev_boot_part_spec = {
+	/* It's used as temp buffer in block driver */
+	.buffer = {
+		.offset = (size_t)&block_buffer,
+		.length = MMC_BLOCK_SIZE,
+	},
+	.ops = {
+		.read = mmc_boot_part_read_blocks,
+		.write = NULL,
+	},
+	.block_size = MMC_BLOCK_SIZE,
+};
+#endif
+
+static struct io_mmc_dev_spec mmc_device_spec = {
+	.use_boot_part = false,
+};
+
+static const io_dev_connector_t *mmc_dev_con;
+#endif /* STM32MP_SDMMC || STM32MP_EMMC */
+
+#if STM32MP_SPI_NOR
+static io_mtd_dev_spec_t spi_nor_dev_spec = {
+	.ops = {
+		.init = spi_nor_init,
+		.read = spi_nor_read,
+	},
+};
+#endif
+
+#if STM32MP_RAW_NAND
+static io_mtd_dev_spec_t nand_dev_spec = {
+	.ops = {
+		.init = nand_raw_init,
+		.read = nand_read,
+	},
+};
+
+static const io_dev_connector_t *nand_dev_con;
+#endif
+
+#if STM32MP_SPI_NAND
+static io_mtd_dev_spec_t spi_nand_dev_spec = {
+	.ops = {
+		.init = spi_nand_init,
+		.read = nand_read,
+	},
+};
+#endif
+
+#if STM32MP_SPI_NAND || STM32MP_SPI_NOR
+static const io_dev_connector_t *spi_dev_con;
+#endif
+
+#ifdef AARCH32_SP_OPTEE
+static const struct stm32image_part_info optee_header_partition_spec = {
+	.name = OPTEE_HEADER_IMAGE_NAME,
+	.binary_type = OPTEE_HEADER_BINARY_TYPE,
+};
+
+static const struct stm32image_part_info optee_core_partition_spec = {
+	.name = OPTEE_CORE_IMAGE_NAME,
+	.binary_type = OPTEE_CORE_BINARY_TYPE,
+};
+
+static const struct stm32image_part_info optee_paged_partition_spec = {
+	.name = OPTEE_PAGED_IMAGE_NAME,
+	.binary_type = OPTEE_PAGED_BINARY_TYPE,
+};
+#else
+static const io_block_spec_t bl32_block_spec = {
+	.offset = BL32_BASE,
+	.length = STM32MP_BL32_SIZE
+};
+#endif
+
+static const struct stm32image_part_info bl33_partition_spec = {
+	.name = BL33_IMAGE_NAME,
+	.binary_type = BL33_BINARY_TYPE,
+};
+
+enum {
+	IMG_IDX_BL33,
+#ifdef AARCH32_SP_OPTEE
+	IMG_IDX_OPTEE_HEADER,
+	IMG_IDX_OPTEE_CORE,
+	IMG_IDX_OPTEE_PAGED,
+#endif
+	IMG_IDX_NUM
+};
+
+static struct stm32image_device_info stm32image_dev_info_spec __unused = {
+	.lba_size = MMC_BLOCK_SIZE,
+	.part_info[IMG_IDX_BL33] = {
+		.name = BL33_IMAGE_NAME,
+		.binary_type = BL33_BINARY_TYPE,
+	},
+#ifdef AARCH32_SP_OPTEE
+	.part_info[IMG_IDX_OPTEE_HEADER] = {
+		.name = OPTEE_HEADER_IMAGE_NAME,
+		.binary_type = OPTEE_HEADER_BINARY_TYPE,
+	},
+	.part_info[IMG_IDX_OPTEE_CORE] = {
+		.name = OPTEE_CORE_IMAGE_NAME,
+		.binary_type = OPTEE_CORE_BINARY_TYPE,
+	},
+	.part_info[IMG_IDX_OPTEE_PAGED] = {
+		.name = OPTEE_PAGED_IMAGE_NAME,
+		.binary_type = OPTEE_PAGED_BINARY_TYPE,
+	},
+#endif
+};
+
+static io_block_spec_t stm32image_block_spec = {
+	.offset = 0U,
+	.length = 0U,
+};
+
+static const io_dev_connector_t *stm32image_dev_con __unused;
+
+#ifndef AARCH32_SP_OPTEE
+static int open_dummy(const uintptr_t spec);
+#endif
+static int open_image(const uintptr_t spec);
+static int open_storage(const uintptr_t spec);
+
+struct plat_io_policy {
+	uintptr_t *dev_handle;
+	uintptr_t image_spec;
+	int (*check)(const uintptr_t spec);
+};
+
+static const struct plat_io_policy policies[] = {
+#ifdef AARCH32_SP_OPTEE
+	[BL32_IMAGE_ID] = {
+		.dev_handle = &image_dev_handle,
+		.image_spec = (uintptr_t)&optee_header_partition_spec,
+		.check = open_image
+	},
+	[BL32_EXTRA1_IMAGE_ID] = {
+		.dev_handle = &image_dev_handle,
+		.image_spec = (uintptr_t)&optee_core_partition_spec,
+		.check = open_image
+	},
+	[BL32_EXTRA2_IMAGE_ID] = {
+		.dev_handle = &image_dev_handle,
+		.image_spec = (uintptr_t)&optee_paged_partition_spec,
+		.check = open_image
+	},
+#else
+	[BL32_IMAGE_ID] = {
+		.dev_handle = &dummy_dev_handle,
+		.image_spec = (uintptr_t)&bl32_block_spec,
+		.check = open_dummy
+	},
+#endif
+	[BL33_IMAGE_ID] = {
+		.dev_handle = &image_dev_handle,
+		.image_spec = (uintptr_t)&bl33_partition_spec,
+		.check = open_image
+	},
+#if STM32MP_SDMMC || STM32MP_EMMC
+	[GPT_IMAGE_ID] = {
+		.dev_handle = &storage_dev_handle,
+		.image_spec = (uintptr_t)&gpt_block_spec,
+		.check = open_storage
+	},
+#endif
+	[STM32_IMAGE_ID] = {
+		.dev_handle = &storage_dev_handle,
+		.image_spec = (uintptr_t)&stm32image_block_spec,
+		.check = open_storage
+	}
+};
+
+#ifndef AARCH32_SP_OPTEE
+static int open_dummy(const uintptr_t spec)
+{
+	return io_dev_init(dummy_dev_handle, 0);
+}
+#endif
+
+static int open_image(const uintptr_t spec)
+{
+	return io_dev_init(image_dev_handle, 0);
+}
+
+static int open_storage(const uintptr_t spec)
+{
+	return io_dev_init(storage_dev_handle, 0);
+}
+
+#if STM32MP_EMMC_BOOT
+static uint32_t get_boot_part_ssbl_header(void)
+{
+	uint32_t magic = 0U;
+	int io_result;
+	size_t bytes_read;
+
+	io_result = register_io_dev_block(&mmc_dev_con);
+	if (io_result != 0) {
+		panic();
+	}
+
+	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_boot_part_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
+
+	io_result = io_open(storage_dev_handle, (uintptr_t)&emmc_boot_ssbl_block_spec,
+			    &image_dev_handle);
+	assert(io_result == 0);
+
+	io_result = io_read(image_dev_handle, (uintptr_t)&magic, sizeof(magic),
+			    &bytes_read);
+	assert(io_result == 0);
+	assert(bytes_read == sizeof(magic));
+
+	io_result = io_dev_close(storage_dev_handle);
+	assert(io_result == 0);
+
+	return magic;
+}
+#endif
+
+static void print_boot_device(boot_api_context_t *boot_context)
+{
+	switch (boot_context->boot_interface_selected) {
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
+		INFO("Using SDMMC\n");
+		break;
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
+		INFO("Using EMMC\n");
+		break;
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
+		INFO("Using QSPI NOR\n");
+		break;
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
+		INFO("Using FMC NAND\n");
+		break;
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
+		INFO("Using SPI NAND\n");
+		break;
+	default:
+		ERROR("Boot interface not found\n");
+		panic();
+		break;
+	}
+
+	if (boot_context->boot_interface_instance != 0U) {
+		INFO("  Instance %d\n", boot_context->boot_interface_instance);
+	}
+}
+
+static void stm32image_io_setup(void)
+{
+	int io_result __unused;
+
+	io_result = register_io_dev_stm32image(&stm32image_dev_con);
+	assert(io_result == 0);
+
+	io_result = io_dev_open(stm32image_dev_con,
+				(uintptr_t)&stm32image_dev_info_spec,
+				&image_dev_handle);
+	assert(io_result == 0);
+}
+
+#if STM32MP_SDMMC || STM32MP_EMMC
+static void boot_mmc(enum mmc_device_type mmc_dev_type,
+		     uint16_t boot_interface_instance)
+{
+	int io_result __unused;
+	uint8_t idx;
+	struct stm32image_part_info *part;
+	struct stm32_sdmmc2_params params;
+	const partition_entry_t *entry __unused;
+	uint32_t magic __unused;
+
+	zeromem(&params, sizeof(struct stm32_sdmmc2_params));
+
+	mmc_info.mmc_dev_type = mmc_dev_type;
+
+	switch (boot_interface_instance) {
+	case 1:
+		params.reg_base = STM32MP_SDMMC1_BASE;
+		break;
+	case 2:
+		params.reg_base = STM32MP_SDMMC2_BASE;
+		break;
+	case 3:
+		params.reg_base = STM32MP_SDMMC3_BASE;
+		break;
+	default:
+		WARN("SDMMC instance not found, using default\n");
+		if (mmc_dev_type == MMC_IS_SD) {
+			params.reg_base = STM32MP_SDMMC1_BASE;
+		} else {
+			params.reg_base = STM32MP_SDMMC2_BASE;
+		}
+		break;
+	}
+
+	params.device_info = &mmc_info;
+	if (stm32_sdmmc2_mmc_init(&params) != 0) {
+		ERROR("SDMMC%u init failed\n", boot_interface_instance);
+		panic();
+	}
+
+	stm32image_dev_info_spec.device_size =
+		stm32_sdmmc2_mmc_get_device_size();
+
+#if STM32MP_EMMC_BOOT
+	magic = get_boot_part_ssbl_header();
+
+	if (magic == BOOT_API_IMAGE_HEADER_MAGIC_NB) {
+		VERBOSE("%s, header found, jump to emmc load\n", __func__);
+		idx = IMG_IDX_BL33;
+		part = &stm32image_dev_info_spec.part_info[idx];
+		part->part_offset = PLAT_EMMC_BOOT_SSBL_OFFSET;
+		part->bkp_offset = 0U;
+		mmc_device_spec.use_boot_part = true;
+
+		goto emmc_boot;
+	} else {
+		WARN("%s: Can't find STM32 header on a boot partition\n", __func__);
+	}
+#endif
+
+	/* Open MMC as a block device to read GPT table */
+	io_result = register_io_dev_block(&mmc_dev_con);
+	if (io_result != 0) {
+		panic();
+	}
+
+	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
+
+	partition_init(GPT_IMAGE_ID);
+
+	io_result = io_dev_close(storage_dev_handle);
+	assert(io_result == 0);
+
+	for (idx = 0U; idx < IMG_IDX_NUM; idx++) {
+		part = &stm32image_dev_info_spec.part_info[idx];
+		entry = get_partition_entry(part->name);
+		if (entry == NULL) {
+			ERROR("Partition %s not found\n", part->name);
+			panic();
+		}
+
+		part->part_offset = entry->start;
+		part->bkp_offset = 0U;
+	}
+
+#if STM32MP_EMMC_BOOT
+emmc_boot:
+#endif
+	/*
+	 * Re-open MMC with io_mmc, for better perfs compared to
+	 * io_block.
+	 */
+	io_result = register_io_dev_mmc(&mmc_dev_con);
+	assert(io_result == 0);
+
+	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_device_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
+}
+#endif /* STM32MP_SDMMC || STM32MP_EMMC */
+
+#if STM32MP_SPI_NOR
+static void boot_spi_nor(boot_api_context_t *boot_context)
+{
+	int io_result __unused;
+	uint8_t idx;
+	struct stm32image_part_info *part;
+
+	io_result = stm32_qspi_init();
+	assert(io_result == 0);
+
+	io_result = register_io_dev_mtd(&spi_dev_con);
+	assert(io_result == 0);
+
+	/* Open connections to device */
+	io_result = io_dev_open(spi_dev_con,
+				(uintptr_t)&spi_nor_dev_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
+
+	stm32image_dev_info_spec.device_size = spi_nor_dev_spec.device_size;
+
+	idx = IMG_IDX_BL33;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NOR_BL33_OFFSET;
+	part->bkp_offset = 0U;
+
+#ifdef AARCH32_SP_OPTEE
+	idx = IMG_IDX_OPTEE_HEADER;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NOR_TEEH_OFFSET;
+	part->bkp_offset = 0U;
+
+	idx = IMG_IDX_OPTEE_PAGED;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NOR_TEED_OFFSET;
+	part->bkp_offset = 0U;
+
+	idx = IMG_IDX_OPTEE_CORE;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NOR_TEEX_OFFSET;
+	part->bkp_offset = 0U;
+#endif
+}
+#endif /* STM32MP_SPI_NOR */
+
+#if STM32MP_RAW_NAND
+static void boot_fmc2_nand(boot_api_context_t *boot_context)
+{
+	int io_result __unused;
+	uint8_t idx;
+	struct stm32image_part_info *part;
+
+	io_result = stm32_fmc2_init();
+	assert(io_result == 0);
+
+	/* Register the IO device on this platform */
+	io_result = register_io_dev_mtd(&nand_dev_con);
+	assert(io_result == 0);
+
+	/* Open connections to device */
+	io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
+
+	stm32image_dev_info_spec.device_size = nand_dev_spec.device_size;
+
+	idx = IMG_IDX_BL33;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_BL33_OFFSET;
+	part->bkp_offset = nand_dev_spec.erase_size;
+
+#ifdef AARCH32_SP_OPTEE
+	idx = IMG_IDX_OPTEE_HEADER;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_TEEH_OFFSET;
+	part->bkp_offset = nand_dev_spec.erase_size;
+
+	idx = IMG_IDX_OPTEE_PAGED;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_TEED_OFFSET;
+	part->bkp_offset = nand_dev_spec.erase_size;
+
+	idx = IMG_IDX_OPTEE_CORE;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_TEEX_OFFSET;
+	part->bkp_offset = nand_dev_spec.erase_size;
+#endif
+}
+#endif /* STM32MP_RAW_NAND */
+
+#if STM32MP_SPI_NAND
+static void boot_spi_nand(boot_api_context_t *boot_context)
+{
+	int io_result __unused;
+	uint8_t idx;
+	struct stm32image_part_info *part;
+
+	io_result = stm32_qspi_init();
+	assert(io_result == 0);
+
+	io_result = register_io_dev_mtd(&spi_dev_con);
+	assert(io_result == 0);
+
+	/* Open connections to device */
+	io_result = io_dev_open(spi_dev_con,
+				(uintptr_t)&spi_nand_dev_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
+
+	stm32image_dev_info_spec.device_size =
+		spi_nand_dev_spec.device_size;
+
+	idx = IMG_IDX_BL33;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_BL33_OFFSET;
+	part->bkp_offset = spi_nand_dev_spec.erase_size;
+
+#ifdef AARCH32_SP_OPTEE
+	idx = IMG_IDX_OPTEE_HEADER;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_TEEH_OFFSET;
+	part->bkp_offset = spi_nand_dev_spec.erase_size;
+
+	idx = IMG_IDX_OPTEE_PAGED;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_TEED_OFFSET;
+	part->bkp_offset = spi_nand_dev_spec.erase_size;
+
+	idx = IMG_IDX_OPTEE_CORE;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_TEEX_OFFSET;
+	part->bkp_offset = spi_nand_dev_spec.erase_size;
+#endif
+}
+#endif /* STM32MP_SPI_NAND */
+
+void stm32mp_io_setup(void)
+{
+	int io_result __unused;
+	boot_api_context_t *boot_context =
+		(boot_api_context_t *)stm32mp_get_boot_ctx_address();
+
+	print_boot_device(boot_context);
+
+	if ((boot_context->boot_partition_used_toboot == 1U) ||
+	    (boot_context->boot_partition_used_toboot == 2U)) {
+		INFO("Boot used partition fsbl%u\n",
+		     boot_context->boot_partition_used_toboot);
+	}
+
+#ifndef AARCH32_SP_OPTEE
+	io_result = register_io_dev_dummy(&dummy_dev_con);
+	assert(io_result == 0);
+
+	io_result = io_dev_open(dummy_dev_con, dummy_dev_spec,
+				&dummy_dev_handle);
+	assert(io_result == 0);
+#endif
+
+	switch (boot_context->boot_interface_selected) {
+#if STM32MP_SDMMC
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
+		dmbsy();
+		boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance);
+		stm32image_io_setup();
+		break;
+#endif
+#if STM32MP_EMMC
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
+		dmbsy();
+		boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance);
+		stm32image_io_setup();
+		break;
+#endif
+#if STM32MP_SPI_NOR
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
+		dmbsy();
+		boot_spi_nor(boot_context);
+		stm32image_io_setup();
+		break;
+#endif
+#if STM32MP_RAW_NAND
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
+		dmbsy();
+		boot_fmc2_nand(boot_context);
+		stm32image_io_setup();
+		break;
+#endif
+#if STM32MP_SPI_NAND
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
+		dmbsy();
+		boot_spi_nand(boot_context);
+		stm32image_io_setup();
+		break;
+#endif
+
+	default:
+		ERROR("Boot interface %d not supported\n",
+		      boot_context->boot_interface_selected);
+		panic();
+		break;
+	}
+}
+
+/*
+ * Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy.
+ */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+			  uintptr_t *image_spec)
+{
+	int rc;
+	const struct plat_io_policy *policy;
+
+	assert(image_id < ARRAY_SIZE(policies));
+
+	policy = &policies[image_id];
+	rc = policy->check(policy->image_spec);
+	if (rc == 0) {
+		*image_spec = policy->image_spec;
+		*dev_handle = *(policy->dev_handle);
+	}
+
+	return rc;
+}
diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h
index 42d3487..8a5fe48 100644
--- a/plat/st/common/include/stm32mp_common.h
+++ b/plat/st/common/include/stm32mp_common.h
@@ -17,6 +17,7 @@
 /* Functions to save and get boot context address given by ROM code */
 void stm32mp_save_boot_ctx_address(uintptr_t address);
 uintptr_t stm32mp_get_boot_ctx_address(void);
+uint16_t stm32mp_get_boot_itf_selected(void);
 
 bool stm32mp_is_single_core(void);
 bool stm32mp_is_closed_device(void);
@@ -94,6 +95,7 @@
 /* Initialise the IO layer and register platform IO devices */
 void stm32mp_io_setup(void);
 
+#if STM32MP_USE_STM32IMAGE
 /*
  * Check that the STM32 header of a .stm32 binary image is valid
  * @param header: pointer to the stm32 image header
@@ -101,6 +103,7 @@
  * @return: 0 on success, negative value in case of error
  */
 int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer);
+#endif /* STM32MP_USE_STM32IMAGE */
 
 /* Functions to map DDR in MMU with non-cacheable attribute, and unmap it */
 int stm32mp_map_ddr_non_cacheable(void);
diff --git a/plat/st/common/include/stm32mp_fconf_getter.h b/plat/st/common/include/stm32mp_fconf_getter.h
new file mode 100644
index 0000000..3a8bb11
--- /dev/null
+++ b/plat/st/common/include/stm32mp_fconf_getter.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP_FCONF_GETTER
+#define STM32MP_FCONF_GETTER
+
+#include <assert.h>
+
+#include <lib/fconf/fconf.h>
+
+/* IO policies */
+#define stm32mp__io_policies_getter(id) __extension__ ({	\
+	assert((id) < MAX_NUMBER_IDS);				\
+	&policies[id];						\
+})
+
+struct plat_io_policy {
+	uintptr_t *dev_handle;
+	uintptr_t image_spec;
+	int (*check)(const uintptr_t spec);
+};
+
+extern struct plat_io_policy policies[];
+int fconf_populate_stm32mp_io_policies(uintptr_t config);
+
+#endif /* STM32MP_FCONF_GETTER */
diff --git a/plat/st/common/include/stm32mp_io_storage.h b/plat/st/common/include/stm32mp_io_storage.h
new file mode 100644
index 0000000..989c890
--- /dev/null
+++ b/plat/st/common/include/stm32mp_io_storage.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef STM32MP_IO_STORAGE_H
+#define STM32MP_IO_STORAGE_H
+
+#include <stdint.h>
+
+#include <drivers/io/io_storage.h>
+
+/* IO devices handle */
+extern uintptr_t storage_dev_handle;
+extern uintptr_t fip_dev_handle;
+
+extern io_block_spec_t image_block_spec;
+
+/* Function declarations */
+int open_fip(const uintptr_t spec);
+int open_storage(const uintptr_t spec);
+
+#endif /* STM32MP_IO_STORAGE_H */
diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c
index d3de1e1..17ac145 100644
--- a/plat/st/common/stm32mp_common.c
+++ b/plat/st/common/stm32mp_common.c
@@ -28,10 +28,14 @@
 }
 
 static uintptr_t boot_ctx_address;
+static uint16_t boot_itf_selected;
 
 void stm32mp_save_boot_ctx_address(uintptr_t address)
 {
+	boot_api_context_t *boot_context = (boot_api_context_t *)address;
+
 	boot_ctx_address = address;
+	boot_itf_selected = boot_context->boot_interface_selected;
 }
 
 uintptr_t stm32mp_get_boot_ctx_address(void)
@@ -39,6 +43,11 @@
 	return boot_ctx_address;
 }
 
+uint16_t stm32mp_get_boot_itf_selected(void)
+{
+	return boot_itf_selected;
+}
+
 uintptr_t stm32mp_ddrctrl_base(void)
 {
 	return DDRCTRL_BASE;
@@ -67,6 +76,7 @@
 	return (read_sctlr() & c_m_bits) == c_m_bits;
 }
 
+#if STM32MP_USE_STM32IMAGE
 int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer)
 {
 	uint32_t i;
@@ -100,12 +110,13 @@
 
 	return 0;
 }
+#endif /* STM32MP_USE_STM32IMAGE */
 
 int stm32mp_map_ddr_non_cacheable(void)
 {
 	return  mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE,
 					STM32MP_DDR_MAX_SIZE,
-					MT_NON_CACHEABLE | MT_RW | MT_NS);
+					MT_NON_CACHEABLE | MT_RW | MT_SECURE);
 }
 
 int stm32mp_unmap_ddr(void)
diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c
index 6465c10..0b35646 100644
--- a/plat/st/common/stm32mp_dt.c
+++ b/plat/st/common/stm32mp_dt.c
@@ -209,15 +209,24 @@
  ******************************************************************************/
 uint32_t dt_get_ddr_size(void)
 {
+	static uint32_t size;
 	int node;
 
+	if (size != 0U) {
+		return size;
+	}
+
 	node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
 	if (node < 0) {
 		INFO("%s: Cannot read DDR node in DT\n", __func__);
 		return 0;
 	}
 
-	return fdt_read_uint32_default(fdt, node, "st,mem-size", 0);
+	size = fdt_read_uint32_default(fdt, node, "st,mem-size", 0U);
+
+	flush_dcache_range((uintptr_t)&size, sizeof(uint32_t));
+
+	return size;
 }
 
 /*******************************************************************************
diff --git a/plat/st/common/stm32mp_fconf_io.c b/plat/st/common/stm32mp_fconf_io.c
new file mode 100644
index 0000000..aa8cd54
--- /dev/null
+++ b/plat/st/common/stm32mp_fconf_io.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <drivers/io/io_storage.h>
+#include <drivers/mmc.h>
+#include <lib/fconf/fconf.h>
+#include <lib/object_pool.h>
+#include <libfdt.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <platform_def.h>
+#include <stm32mp_fconf_getter.h>
+#include <stm32mp_io_storage.h>
+
+#if STM32MP_SDMMC || STM32MP_EMMC
+static io_block_spec_t gpt_block_spec = {
+	.offset = 0U,
+	.length = 34U * MMC_BLOCK_SIZE, /* Size of GPT table */
+};
+#endif
+
+/* By default, STM32 platforms load images from the FIP */
+struct plat_io_policy policies[MAX_NUMBER_IDS] = {
+	[FIP_IMAGE_ID] = {
+		&storage_dev_handle,
+		(uintptr_t)&image_block_spec,
+		open_storage
+	},
+#if STM32MP_SDMMC || STM32MP_EMMC
+	[GPT_IMAGE_ID] = {
+		&storage_dev_handle,
+		(uintptr_t)&gpt_block_spec,
+		open_storage
+	},
+#endif
+};
+
+#define FCONF_ST_IO_UUID_NUMBER	U(8)
+
+static io_uuid_spec_t fconf_stm32mp_uuids[FCONF_ST_IO_UUID_NUMBER];
+static OBJECT_POOL_ARRAY(fconf_stm32mp_uuids_pool, fconf_stm32mp_uuids);
+
+struct policies_load_info {
+	unsigned int image_id;
+	const char *name;
+};
+
+/* image id to property name table */
+static const struct policies_load_info load_info[FCONF_ST_IO_UUID_NUMBER] = {
+	{FW_CONFIG_ID, "fw_cfg_uuid"},
+	{BL32_IMAGE_ID, "bl32_uuid"},
+	{BL32_EXTRA1_IMAGE_ID, "bl32_extra1_uuid"},
+	{BL32_EXTRA2_IMAGE_ID, "bl32_extra2_uuid"},
+	{BL33_IMAGE_ID, "bl33_uuid"},
+	{HW_CONFIG_ID, "hw_cfg_uuid"},
+	{TOS_FW_CONFIG_ID, "tos_fw_cfg_uuid"},
+	{NT_FW_CONFIG_ID, "nt_fw_cfg_uuid"},
+};
+
+int fconf_populate_stm32mp_io_policies(uintptr_t config)
+{
+	int node;
+	unsigned int i;
+
+	/* As libfdt uses void *, we can't avoid this cast */
+	const void *dtb = (void *)config;
+
+	/* Assert the node offset point to "st,io-fip-handle" compatible property */
+	const char *compatible_str = "st,io-fip-handle";
+
+	node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+	if (node < 0) {
+		ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str);
+		return node;
+	}
+
+	/* Locate the uuid cells and read the value for all the load info uuid */
+	for (i = 0U; i < FCONF_ST_IO_UUID_NUMBER; i++) {
+		union uuid_helper_t uuid_helper;
+		io_uuid_spec_t *uuid_ptr;
+		int err;
+
+		uuid_ptr = pool_alloc(&fconf_stm32mp_uuids_pool);
+		err = fdtw_read_uuid(dtb, node, load_info[i].name, 16,
+				     (uint8_t *)&uuid_helper);
+		if (err < 0) {
+			WARN("FCONF: Read cell failed for %s\n", load_info[i].name);
+			return err;
+		}
+
+		VERBOSE("FCONF: stm32mp-io_policies.%s cell found with value = "
+			"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
+			load_info[i].name,
+			uuid_helper.uuid_struct.time_low[0], uuid_helper.uuid_struct.time_low[1],
+			uuid_helper.uuid_struct.time_low[2], uuid_helper.uuid_struct.time_low[3],
+			uuid_helper.uuid_struct.time_mid[0], uuid_helper.uuid_struct.time_mid[1],
+			uuid_helper.uuid_struct.time_hi_and_version[0],
+			uuid_helper.uuid_struct.time_hi_and_version[1],
+			uuid_helper.uuid_struct.clock_seq_hi_and_reserved,
+			uuid_helper.uuid_struct.clock_seq_low,
+			uuid_helper.uuid_struct.node[0], uuid_helper.uuid_struct.node[1],
+			uuid_helper.uuid_struct.node[2], uuid_helper.uuid_struct.node[3],
+			uuid_helper.uuid_struct.node[4], uuid_helper.uuid_struct.node[5]);
+
+		uuid_ptr->uuid = uuid_helper.uuid_struct;
+		policies[load_info[i].image_id].image_spec = (uintptr_t)uuid_ptr;
+		policies[load_info[i].image_id].dev_handle = &fip_dev_handle;
+		policies[load_info[i].image_id].check = open_fip;
+	}
+
+	return 0;
+}
+
+FCONF_REGISTER_POPULATOR(TB_FW, stm32mp_io, fconf_populate_stm32mp_io_policies);
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index 91073b8..e87c529 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -5,6 +5,7 @@
  */
 
 #include <assert.h>
+#include <errno.h>
 #include <string.h>
 
 #include <platform_def.h>
@@ -15,6 +16,7 @@
 #include <common/desc_image_load.h>
 #include <drivers/delay_timer.h>
 #include <drivers/generic_delay_timer.h>
+#include <drivers/mmc.h>
 #include <drivers/st/bsec.h>
 #include <drivers/st/stm32_console.h>
 #include <drivers/st/stm32_iwdg.h>
@@ -23,6 +25,8 @@
 #include <drivers/st/stm32mp1_clk.h>
 #include <drivers/st/stm32mp1_pwr.h>
 #include <drivers/st/stm32mp1_ram.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
 #include <lib/mmio.h>
 #include <lib/optee_utils.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
@@ -132,7 +136,6 @@
 void bl2_platform_setup(void)
 {
 	int ret;
-	uint32_t ddr_ns_size;
 
 	if (dt_pmic_status() > 0) {
 		initialize_pmic();
@@ -144,29 +147,21 @@
 		panic();
 	}
 
-	ddr_ns_size = stm32mp_get_ddr_ns_size();
-	assert(ddr_ns_size > 0U);
-
-	/* Map non secure DDR for BL33 load, now with cacheable attribute */
+	/* Map DDR for binary load, now with cacheable attribute */
 	ret = mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE,
-				      ddr_ns_size, MT_MEMORY | MT_RW | MT_NS);
-	assert(ret == 0);
+				      STM32MP_DDR_MAX_SIZE, MT_MEMORY | MT_RW | MT_SECURE);
+	if (ret < 0) {
+		ERROR("DDR mapping: error %d\n", ret);
+		panic();
+	}
 
+#if STM32MP_USE_STM32IMAGE
 #ifdef AARCH32_SP_OPTEE
 	INFO("BL2 runs OP-TEE setup\n");
-
-	/* Map secure DDR for OP-TEE paged area */
-	ret = mmap_add_dynamic_region(STM32MP_DDR_BASE + ddr_ns_size,
-				      STM32MP_DDR_BASE + ddr_ns_size,
-				      STM32MP_DDR_S_SIZE,
-				      MT_MEMORY | MT_RW | MT_SECURE);
-	assert(ret == 0);
-
-	/* Initialize tzc400 after DDR initialization */
-	stm32mp1_security_setup();
 #else
 	INFO("BL2 runs SP_MIN setup\n");
 #endif
+#endif /* STM32MP_USE_STM32IMAGE */
 }
 
 void bl2_el3_plat_arch_setup(void)
@@ -184,11 +179,19 @@
 			BL_CODE_END - BL_CODE_BASE,
 			MT_CODE | MT_SECURE);
 
+#if STM32MP_USE_STM32IMAGE
 #ifdef AARCH32_SP_OPTEE
 	mmap_add_region(STM32MP_OPTEE_BASE, STM32MP_OPTEE_BASE,
 			STM32MP_OPTEE_SIZE,
 			MT_MEMORY | MT_RW | MT_SECURE);
+#else
+	/* Prevent corruption of preloaded BL32 */
+	mmap_add_region(BL32_BASE, BL32_BASE,
+			BL32_LIMIT - BL32_BASE,
+			MT_RO_DATA | MT_SECURE);
 #endif
+#endif /* STM32MP_USE_STM32IMAGE */
+
 	/* Prevent corruption of preloaded Device Tree */
 	mmap_add_region(DTB_BASE, DTB_BASE,
 			DTB_LIMIT - DTB_BASE,
@@ -327,10 +330,13 @@
 
 	print_reset_reason();
 
+#if !STM32MP_USE_STM32IMAGE
+	fconf_populate("TB_FW", STM32MP_DTB_BASE);
+#endif /* !STM32MP_USE_STM32IMAGE */
+
 	stm32mp_io_setup();
 }
 
-#if defined(AARCH32_SP_OPTEE)
 /*******************************************************************************
  * This function can be used by the platforms to update/use image
  * information for given `image_id`.
@@ -340,44 +346,119 @@
 	int err = 0;
 	bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
 	bl_mem_params_node_t *bl32_mem_params;
-	bl_mem_params_node_t *pager_mem_params;
-	bl_mem_params_node_t *paged_mem_params;
+	bl_mem_params_node_t *pager_mem_params __unused;
+	bl_mem_params_node_t *paged_mem_params __unused;
+#if !STM32MP_USE_STM32IMAGE
+	const struct dyn_cfg_dtb_info_t *config_info;
+	bl_mem_params_node_t *tos_fw_mem_params;
+	unsigned int i;
+	unsigned long long ddr_top __unused;
+	const unsigned int image_ids[] = {
+		BL32_IMAGE_ID,
+		BL33_IMAGE_ID,
+		HW_CONFIG_ID,
+		TOS_FW_CONFIG_ID,
+	};
+#endif /* !STM32MP_USE_STM32IMAGE */
 
 	assert(bl_mem_params != NULL);
 
 	switch (image_id) {
-	case BL32_IMAGE_ID:
-		bl_mem_params->ep_info.pc =
-					bl_mem_params->image_info.image_base;
+#if !STM32MP_USE_STM32IMAGE
+	case FW_CONFIG_ID:
+		/* Set global DTB info for fixed fw_config information */
+		set_config_info(STM32MP_FW_CONFIG_BASE, STM32MP_FW_CONFIG_MAX_SIZE, FW_CONFIG_ID);
+		fconf_populate("FW_CONFIG", STM32MP_FW_CONFIG_BASE);
+
+		/* Iterate through all the fw config IDs */
+		for (i = 0U; i < ARRAY_SIZE(image_ids); i++) {
+			bl_mem_params = get_bl_mem_params_node(image_ids[i]);
+			assert(bl_mem_params != NULL);
+
+			config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, image_ids[i]);
+			if (config_info == NULL) {
+				continue;
+			}
+
+			bl_mem_params->image_info.image_base = config_info->config_addr;
+			bl_mem_params->image_info.image_max_size = config_info->config_max_size;
+
+			bl_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING;
+
+			switch (image_ids[i]) {
+			case BL32_IMAGE_ID:
+				bl_mem_params->ep_info.pc = config_info->config_addr;
+
+				/* In case of OPTEE, initialize address space with tos_fw addr */
+				pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+				pager_mem_params->image_info.image_base = config_info->config_addr;
+				pager_mem_params->image_info.image_max_size =
+					config_info->config_max_size;
 
-		pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
-		assert(pager_mem_params != NULL);
-		pager_mem_params->image_info.image_base = STM32MP_OPTEE_BASE;
-		pager_mem_params->image_info.image_max_size =
-			STM32MP_OPTEE_SIZE;
+				/* Init base and size for pager if exist */
+				paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+				paged_mem_params->image_info.image_base = STM32MP_DDR_BASE +
+					(dt_get_ddr_size() - STM32MP_DDR_S_SIZE -
+					 STM32MP_DDR_SHMEM_SIZE);
+				paged_mem_params->image_info.image_max_size = STM32MP_DDR_S_SIZE;
+				break;
 
-		paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
-		assert(paged_mem_params != NULL);
-		paged_mem_params->image_info.image_base = STM32MP_DDR_BASE +
-			stm32mp_get_ddr_ns_size();
-		paged_mem_params->image_info.image_max_size =
-			STM32MP_DDR_S_SIZE;
+			case BL33_IMAGE_ID:
+				bl_mem_params->ep_info.pc = config_info->config_addr;
+				break;
 
-		err = parse_optee_header(&bl_mem_params->ep_info,
-					 &pager_mem_params->image_info,
-					 &paged_mem_params->image_info);
-		if (err) {
-			ERROR("OPTEE header parse error.\n");
-			panic();
+			case HW_CONFIG_ID:
+			case TOS_FW_CONFIG_ID:
+				break;
+
+			default:
+				return -EINVAL;
+			}
 		}
+		break;
+#endif /* !STM32MP_USE_STM32IMAGE */
+
+	case BL32_IMAGE_ID:
+		if (optee_header_is_valid(bl_mem_params->image_info.image_base)) {
+			/* BL32 is OP-TEE header */
+			bl_mem_params->ep_info.pc = bl_mem_params->image_info.image_base;
+			pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+			paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+			assert((pager_mem_params != NULL) && (paged_mem_params != NULL));
+
+#if STM32MP_USE_STM32IMAGE && defined(AARCH32_SP_OPTEE)
+			/* Set OP-TEE extra image load areas at run-time */
+			pager_mem_params->image_info.image_base = STM32MP_OPTEE_BASE;
+			pager_mem_params->image_info.image_max_size = STM32MP_OPTEE_SIZE;
 
-		/* Set optee boot info from parsed header data */
-		bl_mem_params->ep_info.pc =
-				pager_mem_params->image_info.image_base;
-		bl_mem_params->ep_info.args.arg0 =
-				paged_mem_params->image_info.image_base;
-		bl_mem_params->ep_info.args.arg1 = 0; /* Unused */
-		bl_mem_params->ep_info.args.arg2 = 0; /* No DT supported */
+			paged_mem_params->image_info.image_base = STM32MP_DDR_BASE +
+								  dt_get_ddr_size() -
+								  STM32MP_DDR_S_SIZE -
+								  STM32MP_DDR_SHMEM_SIZE;
+			paged_mem_params->image_info.image_max_size = STM32MP_DDR_S_SIZE;
+#endif /* STM32MP_USE_STM32IMAGE && defined(AARCH32_SP_OPTEE) */
+
+			err = parse_optee_header(&bl_mem_params->ep_info,
+						 &pager_mem_params->image_info,
+						 &paged_mem_params->image_info);
+			if (err) {
+				ERROR("OPTEE header parse error.\n");
+				panic();
+			}
+
+			/* Set optee boot info from parsed header data */
+			bl_mem_params->ep_info.args.arg0 = paged_mem_params->image_info.image_base;
+			bl_mem_params->ep_info.args.arg1 = 0; /* Unused */
+			bl_mem_params->ep_info.args.arg2 = 0; /* No DT supported */
+		} else {
+#if !STM32MP_USE_STM32IMAGE
+			bl_mem_params->ep_info.pc = bl_mem_params->image_info.image_base;
+			tos_fw_mem_params = get_bl_mem_params_node(TOS_FW_CONFIG_ID);
+			bl_mem_params->image_info.image_max_size +=
+				tos_fw_mem_params->image_info.image_max_size;
+#endif /* !STM32MP_USE_STM32IMAGE */
+			bl_mem_params->ep_info.args.arg0 = 0;
+		}
 		break;
 
 	case BL33_IMAGE_ID:
@@ -391,6 +472,23 @@
 		break;
 	}
 
+#if STM32MP_SDMMC || STM32MP_EMMC
+	/*
+	 * Invalidate remaining data read from MMC but not flushed by load_image_flush().
+	 * We take the worst case which is 2 MMC blocks.
+	 */
+	if ((image_id != FW_CONFIG_ID) &&
+	    ((bl_mem_params->image_info.h.attr & IMAGE_ATTRIB_SKIP_LOADING) == 0U)) {
+		inv_dcache_range(bl_mem_params->image_info.image_base +
+				 bl_mem_params->image_info.image_size,
+				 2U * MMC_BLOCK_SIZE);
+	}
+#endif /* STM32MP_SDMMC || STM32MP_EMMC */
+
 	return err;
 }
-#endif
+
+void bl2_el3_plat_prepare_exit(void)
+{
+	stm32mp1_security_setup();
+}
diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h
index 2d7d369..8a065bf 100644
--- a/plat/st/stm32mp1/include/platform_def.h
+++ b/plat/st/stm32mp1/include/platform_def.h
@@ -25,6 +25,7 @@
 #define PLATFORM_STACK_SIZE		0xC00
 #endif
 
+#if STM32MP_USE_STM32IMAGE
 #ifdef AARCH32_SP_OPTEE
 #define OPTEE_HEADER_IMAGE_NAME		"teeh"
 #define OPTEE_CORE_IMAGE_NAME		"teex"
@@ -37,6 +38,9 @@
 /* SSBL = second stage boot loader */
 #define BL33_IMAGE_NAME			"ssbl"
 #define BL33_BINARY_TYPE		U(0x0)
+#else /* STM32MP_USE_STM32IMAGE */
+#define FIP_IMAGE_NAME			"fip"
+#endif /* STM32MP_USE_STM32IMAGE */
 
 #define STM32MP_PRIMARY_CPU		U(0x0)
 #define STM32MP_SECONDARY_CPU		U(0x1)
@@ -67,7 +71,7 @@
 /*******************************************************************************
  * BL32 specific defines.
  ******************************************************************************/
-#ifndef AARCH32_SP_OPTEE
+#if STM32MP_USE_STM32IMAGE || defined(IMAGE_BL32)
 #if ENABLE_PIE
 #define BL32_BASE			0
 #define BL32_LIMIT			STM32MP_BL32_SIZE
@@ -76,7 +80,7 @@
 #define BL32_LIMIT			(STM32MP_BL32_BASE + \
 					 STM32MP_BL32_SIZE)
 #endif
-#endif
+#endif /* STM32MP_USE_STM32IMAGE || defined(IMAGE_BL32) */
 
 /*******************************************************************************
  * BL33 specific defines.
diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h
index b6cb91e..729d233 100644
--- a/plat/st/stm32mp1/include/stm32mp1_private.h
+++ b/plat/st/stm32mp1/include/stm32mp1_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,7 +21,9 @@
 void stm32mp1_syscfg_enable_io_compensation(void);
 void stm32mp1_syscfg_disable_io_compensation(void);
 
+#if STM32MP_USE_STM32IMAGE
 uint32_t stm32mp_get_ddr_ns_size(void);
+#endif /* STM32MP_USE_STM32IMAGE */
 
 void stm32mp1_init_scmi_server(void);
 #endif /* STM32MP1_PRIVATE_H */
diff --git a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
index 984c6ba..7963c4a 100644
--- a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
+++ b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
@@ -4,12 +4,12 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <platform_def.h>
-
 #include <common/bl_common.h>
 #include <common/desc_image_load.h>
 #include <plat/common/platform.h>
 
+#include <platform_def.h>
+
 /*******************************************************************************
  * Following descriptor provides BL image/ep information that gets used
  * by BL2 to load the images and also subset of this information is
@@ -19,6 +19,22 @@
  * the next executable image id.
  ******************************************************************************/
 static bl_mem_params_node_t bl2_mem_params_descs[] = {
+	/* Fill FW_CONFIG related information if it exists */
+	{
+		.image_id = FW_CONFIG_ID,
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | NON_EXECUTABLE),
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_PLAT_SETUP),
+
+		.image_info.image_base = STM32MP_FW_CONFIG_BASE,
+		.image_info.image_max_size = STM32MP_FW_CONFIG_MAX_SIZE,
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+
 	/* Fill BL32 related information */
 	{
 		.image_id = BL32_IMAGE_ID,
@@ -27,28 +43,17 @@
 				      VERSION_2, entry_point_info_t,
 				      SECURE | EXECUTABLE | EP_FIRST_EXE),
 
-#if !defined(AARCH32_SP_OPTEE)
-		.ep_info.pc = STM32MP_BL32_BASE,
-#endif
 		.ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
 					    SPSR_E_LITTLE,
 					    DISABLE_ALL_EXCEPTIONS),
 
 		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
 				      VERSION_2, image_info_t,
-				      IMAGE_ATTRIB_PLAT_SETUP),
-#if defined(AARCH32_SP_OPTEE)
-		/* optee header is loaded in SYSRAM above BL2 */
-		.image_info.image_base = STM32MP_OPTEE_BASE,
-		.image_info.image_max_size = STM32MP_OPTEE_SIZE,
-#else
-		.image_info.image_base = STM32MP_BL32_BASE,
-		.image_info.image_max_size = STM32MP_BL32_SIZE,
-#endif
+				      IMAGE_ATTRIB_SKIP_LOADING),
+
 		.next_handoff_image_id = BL33_IMAGE_ID,
 	},
 
-#if defined(AARCH32_SP_OPTEE)
 	/* Fill BL32 external 1 image related information */
 	{
 		.image_id = BL32_EXTRA1_IMAGE_ID,
@@ -77,7 +82,32 @@
 
 		.next_handoff_image_id = INVALID_IMAGE_ID,
 	},
-#endif /* AARCH32_SP_OPTEE */
+
+	/* Fill HW_CONFIG related information if it exists */
+	{
+		.image_id = HW_CONFIG_ID,
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+				      VERSION_2, entry_point_info_t,
+				      NON_SECURE | NON_EXECUTABLE),
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+
+	/* Fill TOS_FW_CONFIG related information if it exists */
+	{
+		.image_id = TOS_FW_CONFIG_ID,
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | NON_EXECUTABLE),
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
 
 	/* Fill BL33 related information */
 	{
@@ -87,17 +117,13 @@
 				      VERSION_2, entry_point_info_t,
 				      NON_SECURE | EXECUTABLE),
 
-		.ep_info.pc = PLAT_STM32MP_NS_IMAGE_OFFSET,
 		.ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
 					    SPSR_E_LITTLE,
 					    DISABLE_ALL_EXCEPTIONS),
 
 		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
-				      VERSION_2, image_info_t, 0),
-
-		.image_info.image_base = PLAT_STM32MP_NS_IMAGE_OFFSET,
-		.image_info.image_max_size = STM32MP_DDR_MAX_SIZE -
-			(PLAT_STM32MP_NS_IMAGE_OFFSET - STM32MP_DDR_BASE),
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
 
 		.next_handoff_image_id = INVALID_IMAGE_ID,
 	}
diff --git a/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c b/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c
new file mode 100644
index 0000000..4fce55a
--- /dev/null
+++ b/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+	/* Fill BL32 related information */
+	{
+		.image_id = BL32_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | EXECUTABLE | EP_FIRST_EXE),
+
+		/* Updated at runtime if OP-TEE is loaded */
+		.ep_info.pc = STM32MP_BL32_BASE,
+
+		.ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
+					    SPSR_E_LITTLE,
+					    DISABLE_ALL_EXCEPTIONS),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_PLAT_SETUP),
+
+		/* Updated at runtime if OP-TEE is loaded */
+		.image_info.image_base = STM32MP_BL32_BASE,
+		.image_info.image_max_size = STM32MP_BL32_SIZE,
+
+		.next_handoff_image_id = BL33_IMAGE_ID,
+	},
+
+#if defined(AARCH32_SP_OPTEE)
+	/* Fill BL32 external 1 image related information */
+	{
+		.image_id = BL32_EXTRA1_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | NON_EXECUTABLE),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+	/* Fill BL32 external 2 image related information */
+	{
+		.image_id = BL32_EXTRA2_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | NON_EXECUTABLE),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+#endif /* AARCH32_SP_OPTEE */
+
+	/* Fill BL33 related information */
+	{
+		.image_id = BL33_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      NON_SECURE | EXECUTABLE),
+
+		.ep_info.pc = PLAT_STM32MP_NS_IMAGE_OFFSET,
+		.ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
+					    SPSR_E_LITTLE,
+					    DISABLE_ALL_EXCEPTIONS),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t, 0U),
+
+		.image_info.image_base = PLAT_STM32MP_NS_IMAGE_OFFSET,
+		.image_info.image_max_size = STM32MP_DDR_MAX_SIZE -
+			(PLAT_STM32MP_NS_IMAGE_OFFSET - STM32MP_DDR_BASE),
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	}
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/st/stm32mp1/plat_image_load.c b/plat/st/stm32mp1/plat_image_load.c
index 6d7af74..36a3a1c 100644
--- a/plat/st/stm32mp1/plat_image_load.c
+++ b/plat/st/stm32mp1/plat_image_load.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -23,12 +23,14 @@
  ******************************************************************************/
 bl_load_info_t *plat_get_bl_image_load_info(void)
 {
+#if STM32MP_USE_STM32IMAGE
 	bl_mem_params_node_t *bl33 = get_bl_mem_params_node(BL33_IMAGE_ID);
 	uint32_t ddr_ns_size = stm32mp_get_ddr_ns_size();
 
 	/* Max size is non-secure DDR end address minus image_base */
 	bl33->image_info.image_max_size = STM32MP_DDR_BASE + ddr_ns_size -
 					  bl33->image_info.image_base;
+#endif /* STM32MP_USE_STM32IMAGE */
 
 	return get_bl_load_info_from_mem_params_desc();
 }
@@ -38,5 +40,9 @@
  ******************************************************************************/
 bl_params_t *plat_get_next_bl_params(void)
 {
-	return get_next_bl_params_from_mem_params_desc();
+	bl_params_t *bl_params = get_next_bl_params_from_mem_params_desc();
+
+	populate_next_bl_params_config(bl_params);
+
+	return bl_params;
 }
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index 1693135..1c2c9f0 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -9,7 +9,14 @@
 BL2_AT_EL3		:=	1
 USE_COHERENT_MEM	:=	0
 
+# Allow TF-A to concatenate BL2 & BL32 binaries in a single file,
+# share DTB file between BL2 and BL32
+# If it is set to 0, then FIP is used
+STM32MP_USE_STM32IMAGE	?=	0
+
+ifneq ($(STM32MP_USE_STM32IMAGE),1)
 ENABLE_PIE		:=	1
+endif
 
 STM32_TF_VERSION	?=	0
 
@@ -29,8 +36,10 @@
 STM32_BL33_PARTS_NUM		:=	1
 ifeq ($(AARCH32_SP),optee)
 STM32_RUNTIME_PARTS_NUM		:=	3
-else
+else ifeq ($(STM32MP_USE_STM32IMAGE),1)
 STM32_RUNTIME_PARTS_NUM		:=	0
+else
+STM32_RUNTIME_PARTS_NUM		:=	1
 endif
 PLAT_PARTITION_MAX_ENTRIES	:=	$(shell echo $$(($(STM32_TF_A_COPIES) + \
 							 $(STM32_BL33_PARTS_NUM) + \
@@ -46,7 +55,22 @@
 
 # Device tree
 DTB_FILE_NAME		?=	stm32mp157c-ev1.dtb
+ifeq ($(STM32MP_USE_STM32IMAGE),1)
+ifeq ($(AARCH32_SP),optee)
+BL2_DTSI		:=	stm32mp15-bl2.dtsi
+FDT_SOURCES		:=	$(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME)))
+else
 FDT_SOURCES		:=	$(addprefix fdts/, $(patsubst %.dtb,%.dts,$(DTB_FILE_NAME)))
+endif
+else
+BL2_DTSI		:=	stm32mp15-bl2.dtsi
+FDT_SOURCES		:=	$(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME)))
+ifeq ($(AARCH32_SP),sp_min)
+BL32_DTSI		:=	stm32mp15-bl32.dtsi
+FDT_SOURCES		+=	$(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dts,$(DTB_FILE_NAME)))
+endif
+endif
+DTC_CPPFLAGS		+=	${INCLUDES}
 DTC_FLAGS		+=	-Wno-unit_address_vs_reg
 
 # Macros and rules to build TF binary
@@ -66,6 +90,33 @@
 STM32IMAGE		?= ${STM32IMAGEPATH}/stm32image${BIN_EXT}
 STM32IMAGE_SRC		:= ${STM32IMAGEPATH}/stm32image.c
 
+ifneq (${STM32MP_USE_STM32IMAGE},1)
+FIP_DEPS		+=	dtbs
+STM32MP_HW_CONFIG	:=	${BL33_CFG}
+STM32MP_FW_CONFIG_NAME	:=	$(patsubst %.dtb,%-fw-config.dtb,$(DTB_FILE_NAME))
+STM32MP_FW_CONFIG	:=	${BUILD_PLAT}/fdts/$(STM32MP_FW_CONFIG_NAME)
+ifneq (${AARCH32_SP},none)
+FDT_SOURCES		+=	$(addprefix fdts/, $(patsubst %.dtb,%.dts,$(STM32MP_FW_CONFIG_NAME)))
+endif
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_FW_CONFIG},--fw-config))
+# Add the HW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_HW_CONFIG},--hw-config))
+ifeq ($(AARCH32_SP),sp_min)
+STM32MP_TOS_FW_CONFIG	:= $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dtb,$(DTB_FILE_NAME)))
+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_TOS_FW_CONFIG},--tos-fw-config))
+else
+# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
+# in the FIP if the platform requires.
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2))
+endif
+endif
+endif
+
 # Enable flags for C files
 $(eval $(call assert_booleans,\
 	$(sort \
@@ -76,6 +127,7 @@
 		STM32MP_SPI_NOR \
 		STM32MP_EMMC_BOOT \
 		PLAT_XLAT_TABLES_DYNAMIC \
+		STM32MP_USE_STM32IMAGE \
 )))
 
 $(eval $(call assert_numerics,\
@@ -95,6 +147,7 @@
 		PLAT_XLAT_TABLES_DYNAMIC \
 		STM32_TF_A_COPIES \
 		PLAT_PARTITION_MAX_ENTRIES \
+		STM32MP_USE_STM32IMAGE \
 )))
 
 # Include paths and source files
@@ -104,6 +157,7 @@
 include lib/libfdt/libfdt.mk
 
 PLAT_BL_COMMON_SOURCES	:=	common/fdt_wrappers.c					\
+				common/uuid.c						\
 				plat/st/common/stm32mp_common.c				\
 				plat/st/stm32mp1/stm32mp1_private.c
 
@@ -135,17 +189,29 @@
 				plat/st/stm32mp1/stm32mp1_context.c			\
 				plat/st/stm32mp1/stm32mp1_dbgmcu.c			\
 				plat/st/stm32mp1/stm32mp1_helper.S			\
-				plat/st/stm32mp1/stm32mp1_security.c			\
 				plat/st/stm32mp1/stm32mp1_syscfg.c
 
+ifneq (${STM32MP_USE_STM32IMAGE},1)
+BL2_SOURCES		+=	drivers/io/io_fip.c					\
+				lib/fconf/fconf.c					\
+				lib/fconf/fconf_dyn_cfg_getter.c			\
+				plat/st/common/bl2_io_storage.c				\
+				plat/st/common/stm32mp_fconf_io.c			\
+				plat/st/stm32mp1/plat_bl2_mem_params_desc.c		\
+				plat/st/stm32mp1/stm32mp1_fconf_firewall.c
+else
+BL2_SOURCES		+=	drivers/io/io_dummy.c					\
+				drivers/st/io/io_stm32image.c				\
+				plat/st/common/bl2_stm32_io_storage.c			\
+				plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c	\
+				plat/st/stm32mp1/stm32mp1_security.c
+endif
+
 BL2_SOURCES		+=	drivers/io/io_block.c					\
-				drivers/io/io_dummy.c					\
 				drivers/io/io_mtd.c					\
 				drivers/io/io_storage.c					\
 				drivers/st/crypto/stm32_hash.c				\
-				drivers/st/io/io_stm32image.c				\
 				plat/st/common/stm32mp_auth.c				\
-				plat/st/common/bl2_io_storage.c				\
 				plat/st/stm32mp1/bl2_plat_setup.c
 
 ifneq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC}),)
@@ -187,12 +253,9 @@
 				drivers/st/ddr/stm32mp1_ram.c
 
 BL2_SOURCES		+=	common/desc_image_load.c				\
-				plat/st/stm32mp1/plat_bl2_mem_params_desc.c		\
 				plat/st/stm32mp1/plat_image_load.c
 
-ifeq ($(AARCH32_SP),optee)
 BL2_SOURCES		+=	lib/optee/optee_utils.c
-endif
 
 # Compilation rules
 .PHONY: check_dtc_version stm32image clean_stm32image check_boot_device
@@ -230,12 +293,35 @@
 		false; \
 	fi
 
-
+ifeq ($(STM32MP_USE_STM32IMAGE)-$(AARCH32_SP),1-sp_min)
 ${BUILD_PLAT}/stm32mp1-%.o: ${BUILD_PLAT}/fdts/%.dtb plat/st/stm32mp1/stm32mp1.S bl2 ${BL32_DEP}
 	@echo "  AS      stm32mp1.S"
 	${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \
 		-DDTB_BIN_PATH=\"$<\" \
+		-c $(word 2,$^) -o $@
+else
+# Create DTB file for BL2
+${BUILD_PLAT}/fdts/%-bl2.dts: fdts/%.dts fdts/${BL2_DTSI} | ${BUILD_PLAT} fdt_dirs
+	@echo '#include "$(patsubst fdts/%,%,$<)"' > $@
+	@echo '#include "${BL2_DTSI}"' >> $@
+
+${BUILD_PLAT}/fdts/%-bl2.dtb: ${BUILD_PLAT}/fdts/%-bl2.dts
+
+ifeq ($(AARCH32_SP),sp_min)
+# Create DTB file for BL32
+${BUILD_PLAT}/fdts/%-bl32.dts: fdts/%.dts fdts/${BL32_DTSI} | ${BUILD_PLAT} fdt_dirs
+	@echo '#include "$(patsubst fdts/%,%,$<)"' > $@
+	@echo '#include "${BL32_DTSI}"' >> $@
+
+${BUILD_PLAT}/fdts/%-bl32.dtb: ${BUILD_PLAT}/fdts/%-bl32.dts
+endif
+
+${BUILD_PLAT}/stm32mp1-%.o: ${BUILD_PLAT}/fdts/%-bl2.dtb plat/st/stm32mp1/stm32mp1.S bl2
+	@echo "  AS      stm32mp1.S"
+	${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \
+		-DDTB_BIN_PATH=\"$<\" \
 		-c plat/st/stm32mp1/stm32mp1.S -o $@
+endif
 
 $(eval $(call MAKE_LD,${STM32_TF_LINKERFILE},plat/st/stm32mp1/stm32mp1.ld.S,2))
 
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
index 334f914..1495e02 100644
--- a/plat/st/stm32mp1/sp_min/sp_min_setup.c
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
@@ -45,6 +45,7 @@
 {
 	switch (id & INT_ID_MASK) {
 	case STM32MP1_IRQ_TZC400:
+		tzc400_init(STM32MP1_TZC_BASE);
 		(void)tzc400_it_handler();
 		panic();
 		break;
@@ -117,6 +118,11 @@
 	struct dt_node_info dt_uart_info;
 	int result;
 	bl_params_t *params_from_bl2 = (bl_params_t *)arg0;
+#if STM32MP_USE_STM32IMAGE
+	uintptr_t dt_addr = STM32MP_DTB_BASE;
+#else
+	uintptr_t dt_addr = arg1;
+#endif
 
 	/* Imprecise aborts can be masked in NonSecure */
 	write_scr(read_scr() | SCR_AW_BIT);
@@ -140,13 +146,23 @@
 	while (bl_params != NULL) {
 		if (bl_params->image_id == BL33_IMAGE_ID) {
 			bl33_image_ep_info = *bl_params->ep_info;
+			/*
+			 *  Check if hw_configuration is given to BL32 and
+			 *  share it to BL33.
+			 */
+			if (arg2 != 0U) {
+				bl33_image_ep_info.args.arg0 = 0U;
+				bl33_image_ep_info.args.arg1 = 0U;
+				bl33_image_ep_info.args.arg2 = arg2;
+			}
+
 			break;
 		}
 
 		bl_params = bl_params->next_params_info;
 	}
 
-	if (dt_open_and_check(STM32MP_DTB_BASE) < 0) {
+	if (dt_open_and_check(dt_addr) < 0) {
 		panic();
 	}
 
@@ -185,9 +201,6 @@
  ******************************************************************************/
 void sp_min_platform_setup(void)
 {
-	/* Initialize tzc400 after DDR initialization */
-	stm32mp1_security_setup();
-
 	generic_delay_timer_init();
 
 	stm32mp1_gic_init();
diff --git a/plat/st/stm32mp1/stm32mp1.S b/plat/st/stm32mp1/stm32mp1.S
index 7255fe5..85caa0a 100644
--- a/plat/st/stm32mp1/stm32mp1.S
+++ b/plat/st/stm32mp1/stm32mp1.S
@@ -1,13 +1,15 @@
 /*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#if STM32MP_USE_STM32IMAGE
 #ifdef BL32_BIN_PATH
 .section .bl32_image
 .incbin BL32_BIN_PATH
 #endif
+#endif /* STM32MP_USE_STM32IMAGE */
 
 .section .bl2_image
 .incbin BL2_BIN_PATH
diff --git a/plat/st/stm32mp1/stm32mp1.ld.S b/plat/st/stm32mp1/stm32mp1.ld.S
index b347bad..945de99 100644
--- a/plat/st/stm32mp1/stm32mp1.ld.S
+++ b/plat/st/stm32mp1/stm32mp1.ld.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -43,7 +43,11 @@
          * The strongest and only alignment contraint is MMU 4K page.
          * Indeed as images below will be removed, 4K pages will be re-used.
          */
+#if STM32MP_USE_STM32IMAGE
         . = ( STM32MP_DTB_BASE - STM32MP_BINARY_BASE );
+#else
+        . = ( STM32MP_BL2_DTB_BASE - STM32MP_BINARY_BASE );
+#endif /* STM32MP_USE_STM32IMAGE */
         __DTB_IMAGE_START__ = .;
         *(.dtb_image*)
         __DTB_IMAGE_END__ = .;
@@ -58,7 +62,7 @@
         *(.bl2_image*)
         __BL2_IMAGE_END__ = .;
 
-#ifndef AARCH32_SP_OPTEE
+#if STM32MP_USE_STM32IMAGE && !defined(AARCH32_SP_OPTEE)
         /*
          * bl32 will be settled by bl2.
          * The strongest and only alignment constraint is 8 words to simplify
@@ -68,7 +72,7 @@
         __BL32_IMAGE_START__ = .;
         *(.bl32_image*)
         __BL32_IMAGE_END__ = .;
-#endif
+#endif /* STM32MP_USE_STM32IMAGE && !defined(AARCH32_SP_OPTEE) */
 
         __DATA_END__ = .;
     } >RAM
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index 155d63d..469c2d9 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -28,6 +28,12 @@
 #include <stm32mp1_shared_resources.h>
 #endif
 
+#if !STM32MP_USE_STM32IMAGE
+#include "stm32mp1_fip_def.h"
+#else /* STM32MP_USE_STM32IMAGE */
+#include "stm32mp1_stm32image_def.h"
+#endif /* STM32MP_USE_STM32IMAGE */
+
 /*******************************************************************************
  * CHIP ID
  ******************************************************************************/
@@ -81,13 +87,6 @@
 /* DDR configuration */
 #define STM32MP_DDR_BASE		U(0xC0000000)
 #define STM32MP_DDR_MAX_SIZE		U(0x40000000)	/* Max 1GB */
-#ifdef AARCH32_SP_OPTEE
-#define STM32MP_DDR_S_SIZE		U(0x01E00000)	/* 30 MB */
-#define STM32MP_DDR_SHMEM_SIZE		U(0x00200000)	/* 2 MB */
-#else
-#define STM32MP_DDR_S_SIZE		U(0)
-#define STM32MP_DDR_SHMEM_SIZE		U(0)
-#endif
 
 /* DDR power initializations */
 #ifndef __ASSEMBLER__
@@ -111,26 +110,6 @@
 					 (STM32MP_PARAM_LOAD_SIZE +	\
 					  STM32MP_HEADER_SIZE))
 
-#ifdef AARCH32_SP_OPTEE
-#define STM32MP_BL32_SIZE		U(0)
-
-#define STM32MP_OPTEE_BASE		STM32MP_SEC_SYSRAM_BASE
-
-#define STM32MP_OPTEE_SIZE		(STM32MP_DTB_BASE -  \
-					 STM32MP_OPTEE_BASE)
-#else
-#define STM32MP_BL32_SIZE		U(0x00012000)	/* 72 KB for BL32 */
-#endif
-
-#define STM32MP_BL32_BASE		(STM32MP_SEC_SYSRAM_BASE + \
-					 STM32MP_SEC_SYSRAM_SIZE - \
-					 STM32MP_BL32_SIZE)
-
-#define STM32MP_BL2_SIZE		U(0x0001A000)	/* 100 KB for BL2 */
-
-#define STM32MP_BL2_BASE		(STM32MP_BL32_BASE - \
-					 STM32MP_BL2_SIZE)
-
 /* BL2 and BL32/sp_min require 4 tables */
 #define MAX_XLAT_TABLES			U(4)		/* 16 KB for mapping */
 
@@ -141,39 +120,14 @@
 #if defined(IMAGE_BL2)
   #define MAX_MMAP_REGIONS		11
 #endif
-#if defined(IMAGE_BL32)
-  #define MAX_MMAP_REGIONS		6
-#endif
-
-/* DTB initialization value */
-#define STM32MP_DTB_SIZE		U(0x00005000)	/* 20 KB for DTB */
-
-#define STM32MP_DTB_BASE		(STM32MP_BL2_BASE - \
-					 STM32MP_DTB_SIZE)
 
 #define STM32MP_BL33_BASE		(STM32MP_DDR_BASE + U(0x100000))
+#define STM32MP_BL33_MAX_SIZE		U(0x400000)
 
 /* Define maximum page size for NAND devices */
 #define PLATFORM_MTD_MAX_PAGE_SIZE	U(0x1000)
 
 /*******************************************************************************
- * STM32MP1 RAW partition offset for MTD devices
- ******************************************************************************/
-#define STM32MP_NOR_BL33_OFFSET		U(0x00080000)
-#ifdef AARCH32_SP_OPTEE
-#define STM32MP_NOR_TEEH_OFFSET		U(0x00280000)
-#define STM32MP_NOR_TEED_OFFSET		U(0x002C0000)
-#define STM32MP_NOR_TEEX_OFFSET		U(0x00300000)
-#endif
-
-#define STM32MP_NAND_BL33_OFFSET	U(0x00200000)
-#ifdef AARCH32_SP_OPTEE
-#define STM32MP_NAND_TEEH_OFFSET	U(0x00600000)
-#define STM32MP_NAND_TEED_OFFSET	U(0x00680000)
-#define STM32MP_NAND_TEEX_OFFSET	U(0x00700000)
-#endif
-
-/*******************************************************************************
  * STM32MP1 device/io map related constants (used for MMU)
  ******************************************************************************/
 #define STM32MP1_DEVICE1_BASE		U(0x40000000)
@@ -251,6 +205,8 @@
 #define DEBUG_UART_TX_CLKSRC		RCC_UART24CKSELR_HSI
 #define DEBUG_UART_TX_EN_REG		RCC_MP_APB1ENSETR
 #define DEBUG_UART_TX_EN		RCC_MP_APB1ENSETR_UART4EN
+#define DEBUG_UART_RST_REG		RCC_APB1RSTSETR
+#define DEBUG_UART_RST_BIT		RCC_APB1RSTSETR_UART4RST
 
 /*******************************************************************************
  * STM32MP1 ETZPC
@@ -355,18 +311,6 @@
  ******************************************************************************/
 #define STM32MP1_TZC_BASE		U(0x5C006000)
 
-#define STM32MP1_TZC_A7_ID		U(0)
-#define STM32MP1_TZC_M4_ID		U(1)
-#define STM32MP1_TZC_LCD_ID		U(3)
-#define STM32MP1_TZC_GPU_ID		U(4)
-#define STM32MP1_TZC_MDMA_ID		U(5)
-#define STM32MP1_TZC_DMA_ID		U(6)
-#define STM32MP1_TZC_USB_HOST_ID	U(7)
-#define STM32MP1_TZC_USB_OTG_ID		U(8)
-#define STM32MP1_TZC_SDMMC_ID		U(9)
-#define STM32MP1_TZC_ETH_ID		U(10)
-#define STM32MP1_TZC_DAP_ID		U(15)
-
 #define STM32MP1_FILTER_BIT_ALL		(TZC_400_REGION_ATTR_FILTER_BIT(0) | \
 					 TZC_400_REGION_ATTR_FILTER_BIT(1))
 
diff --git a/plat/st/stm32mp1/stm32mp1_fconf_firewall.c b/plat/st/stm32mp1/stm32mp1_fconf_firewall.c
new file mode 100644
index 0000000..caf9ff1
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_fconf_firewall.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <drivers/arm/tzc400.h>
+#include <drivers/st/stm32mp1_clk.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <lib/fconf/fconf.h>
+#include <lib/object_pool.h>
+#include <libfdt.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <platform_def.h>
+#include <stm32mp_fconf_getter.h>
+
+#define STM32MP_REGION_PARAMS	4
+#define STM32MP_MAX_REGIONS	8
+#define FORCE_SEC_REGION	BIT(31)
+
+static uint32_t nb_regions;
+
+struct dt_id_attr {
+	fdt32_t id_attr[STM32MP_MAX_REGIONS];
+};
+
+void stm32mp1_arch_security_setup(void)
+{
+	stm32mp_clk_enable(TZC1);
+	stm32mp_clk_enable(TZC2);
+
+	tzc400_init(STM32MP1_TZC_BASE);
+	tzc400_disable_filters();
+
+	/*
+	 * Region 0 set to cover all DRAM at 0xC000_0000
+	 * Only secure access is granted in read/write.
+	 */
+	tzc400_configure_region0(TZC_REGION_S_RDWR, 0);
+
+	tzc400_set_action(TZC_ACTION_ERR);
+	tzc400_enable_filters();
+}
+
+void stm32mp1_security_setup(void)
+{
+	uint8_t i;
+
+	assert(nb_regions > 0U);
+
+	tzc400_init(STM32MP1_TZC_BASE);
+	tzc400_disable_filters();
+
+	/*
+	 * Region 0 set to cover all DRAM at 0xC000_0000
+	 * No access is allowed.
+	 */
+	tzc400_configure_region0(TZC_REGION_S_NONE, 0);
+
+	for (i = 1U; i <= nb_regions; i++) {
+		tzc400_update_filters(i, STM32MP1_FILTER_BIT_ALL);
+	}
+
+	tzc400_set_action(TZC_ACTION_INT);
+	tzc400_enable_filters();
+}
+
+static int fconf_populate_stm32mp1_firewall(uintptr_t config)
+{
+	int node, len;
+	unsigned int i;
+	const struct dt_id_attr *conf_list;
+	const void *dtb = (const void *)config;
+
+	/* Assert the node offset point to "st,mem-firewall" compatible property */
+	const char *compatible_str = "st,mem-firewall";
+
+	node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+	if (node < 0) {
+		ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str);
+		return node;
+	}
+
+	conf_list = (const struct dt_id_attr *)fdt_getprop(dtb, node, "memory-ranges", &len);
+	if (conf_list == NULL) {
+		WARN("FCONF: Read cell failed for %s\n", "memory-ranges");
+		return -1;
+	}
+
+	/* Locate the memory cells and read all values */
+	for (i = 0U; i < (unsigned int)(len / (sizeof(uint32_t) * STM32MP_REGION_PARAMS)); i++) {
+		uint32_t base;
+		uint32_t size;
+		uint32_t sec_attr;
+		uint32_t nsaid;
+
+		base = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS]);
+		size = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 1]);
+		sec_attr = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 2]);
+		nsaid = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 3]);
+
+		VERBOSE("FCONF: stm32mp1-firewall cell found with value = 0x%x 0x%x 0x%x 0x%x\n",
+			base, size, sec_attr, nsaid);
+
+		nb_regions++;
+
+		/* Configure region but keep disabled for secure access for BL2 load */
+		tzc400_configure_region(0U, nb_regions, (unsigned long long)base,
+					(unsigned long long)base + size - 1ULL, sec_attr, nsaid);
+	}
+
+	/* Force flush as the value will be used cache off */
+	flush_dcache_range((uintptr_t)&nb_regions, sizeof(uint32_t));
+
+	return 0;
+}
+
+FCONF_REGISTER_POPULATOR(FW_CONFIG, stm32mp1_firewall, fconf_populate_stm32mp1_firewall);
diff --git a/plat/st/stm32mp1/stm32mp1_fip_def.h b/plat/st/stm32mp1/stm32mp1_fip_def.h
new file mode 100644
index 0000000..d8561dc
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_fip_def.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_FIP_DEF_H
+#define STM32MP1_FIP_DEF_H
+
+#define STM32MP_DDR_S_SIZE		U(0x01E00000)	/* 30 MB */
+#define STM32MP_DDR_SHMEM_SIZE		U(0x00200000)	/* 2 MB */
+
+#define STM32MP_BL2_SIZE		U(0x0001B000)	/* 108 KB for BL2 */
+#define STM32MP_BL2_DTB_SIZE		U(0x00006000)	/* 24 KB for DTB */
+#define STM32MP_BL32_SIZE		U(0x00019000)	/* 100 KB for BL32 */
+#define STM32MP_BL32_DTB_SIZE		U(0x00005000)	/* 20 KB for DTB */
+#define STM32MP_FW_CONFIG_MAX_SIZE	PAGE_SIZE	/* 4 KB for FCONF DTB */
+#define STM32MP_HW_CONFIG_MAX_SIZE	U(0x40000)	/* 256 KB for HW config DTB */
+
+#define STM32MP_BL2_BASE		(STM32MP_SEC_SYSRAM_BASE + \
+					 STM32MP_SEC_SYSRAM_SIZE - \
+					 STM32MP_BL2_SIZE)
+
+#define STM32MP_BL2_DTB_BASE		(STM32MP_BL2_BASE - \
+					 STM32MP_BL2_DTB_SIZE)
+
+#define STM32MP_BL32_DTB_BASE		STM32MP_SYSRAM_BASE
+
+#define STM32MP_BL32_BASE		(STM32MP_BL32_DTB_BASE + \
+					 STM32MP_BL32_DTB_SIZE)
+
+
+#if defined(IMAGE_BL2)
+#define STM32MP_DTB_SIZE		STM32MP_BL2_DTB_SIZE
+#define STM32MP_DTB_BASE		STM32MP_BL2_DTB_BASE
+#endif
+#if defined(IMAGE_BL32)
+#define STM32MP_DTB_SIZE		STM32MP_BL32_DTB_SIZE
+#define STM32MP_DTB_BASE		STM32MP_BL32_DTB_BASE
+#endif
+
+#ifdef AARCH32_SP_OPTEE
+#define STM32MP_OPTEE_BASE		STM32MP_SEC_SYSRAM_BASE
+
+#define STM32MP_OPTEE_SIZE		(STM32MP_BL2_DTB_BASE -  \
+					 STM32MP_OPTEE_BASE)
+#endif
+
+#define STM32MP_FW_CONFIG_BASE		(STM32MP_SYSRAM_BASE + \
+					 STM32MP_SYSRAM_SIZE - \
+					 PAGE_SIZE)
+#define STM32MP_HW_CONFIG_BASE		(STM32MP_BL33_BASE + \
+					STM32MP_BL33_MAX_SIZE)
+
+/*
+ * MAX_MMAP_REGIONS is usually:
+ * BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup
+ */
+#if defined(IMAGE_BL32)
+#define MAX_MMAP_REGIONS		10
+#endif
+
+/*******************************************************************************
+ * STM32MP1 RAW partition offset for MTD devices
+ ******************************************************************************/
+#define STM32MP_NOR_FIP_OFFSET		U(0x00080000)
+#define STM32MP_NAND_FIP_OFFSET		U(0x00200000)
+
+#endif /* STM32MP1_FIP_DEF_H */
diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S
index 84e9e8d..cac9752 100644
--- a/plat/st/stm32mp1/stm32mp1_helper.S
+++ b/plat/st/stm32mp1/stm32mp1_helper.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -148,6 +148,19 @@
 	 * ---------------------------------------------
 	 */
 func plat_crash_console_init
+	/* Reset UART peripheral */
+	ldr	r1, =(RCC_BASE + DEBUG_UART_RST_REG)
+	ldr	r2, =DEBUG_UART_RST_BIT
+	str	r2, [r1]
+1:
+	ldr	r0, [r1]
+	ands	r2, r0, r2
+	beq	1b
+	str	r2, [r1, #4] /* RSTCLR register */
+2:
+	ldr	r0, [r1]
+	ands	r2, r0, r2
+	bne	2b
 	/* Enable GPIOs for UART TX */
 	ldr	r1, =(RCC_BASE + DEBUG_UART_TX_GPIO_BANK_CLK_REG)
 	ldr	r2, [r1]
diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c
index 1af0075..e4065c1 100644
--- a/plat/st/stm32mp1/stm32mp1_private.c
+++ b/plat/st/stm32mp1/stm32mp1_private.c
@@ -452,6 +452,7 @@
 }
 #endif
 
+#if STM32MP_USE_STM32IMAGE
 /* Get the non-secure DDR size */
 uint32_t stm32mp_get_ddr_ns_size(void)
 {
@@ -472,3 +473,4 @@
 
 	return ddr_ns_size;
 }
+#endif /* STM32MP_USE_STM32IMAGE */
diff --git a/plat/st/stm32mp1/stm32mp1_security.c b/plat/st/stm32mp1/stm32mp1_security.c
index 195b3a5..19ef4f0 100644
--- a/plat/st/stm32mp1/stm32mp1_security.c
+++ b/plat/st/stm32mp1/stm32mp1_security.c
@@ -12,20 +12,47 @@
 #include <drivers/arm/tzc400.h>
 #include <drivers/st/stm32mp1_clk.h>
 #include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/soc/stm32mp15-tzc400.h>
 #include <lib/mmio.h>
 
-#define TZC_REGION_NSEC_ALL_ACCESS_RDWR \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) | \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) | \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) | \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_M4_ID) | \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) | \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) | \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) | \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) | \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) | \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID)
+static unsigned int region_nb;
+
+static void init_tzc400_begin(unsigned int region0_attr)
+{
+	tzc400_init(STM32MP1_TZC_BASE);
+	tzc400_disable_filters();
+
+	/* Region 0 set to cover all DRAM at 0xC000_0000 */
+	tzc400_configure_region0(region0_attr, 0);
+
+	region_nb = 1U;
+}
+
+static void init_tzc400_end(unsigned int action)
+{
+	tzc400_set_action(action);
+	tzc400_enable_filters();
+}
+
+static void tzc400_add_region(unsigned long long region_base,
+			      unsigned long long region_top, bool sec)
+{
+	unsigned int sec_attr;
+	unsigned int nsaid_permissions;
+
+	if (sec) {
+		sec_attr = TZC_REGION_S_RDWR;
+		nsaid_permissions = 0;
+	} else {
+		sec_attr = TZC_REGION_S_NONE;
+		nsaid_permissions = TZC_REGION_NSEC_ALL_ACCESS_RDWR;
+	}
+
+	tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, region_nb, region_base,
+				region_top, sec_attr, nsaid_permissions);
+
+	region_nb++;
+}
 
 /*******************************************************************************
  * Initialize the TrustZone Controller. Configure Region 0 with Secure RW access
@@ -38,10 +65,9 @@
 	unsigned long long ddr_ns_size =
 		(unsigned long long)stm32mp_get_ddr_ns_size();
 	unsigned long long ddr_ns_top = ddr_base + (ddr_ns_size - 1U);
-
-	tzc400_init(STM32MP1_TZC_BASE);
+	unsigned long long ddr_top __unused;
 
-	tzc400_disable_filters();
+	init_tzc400_begin(TZC_REGION_S_NONE);
 
 	/*
 	 * Region 1 set to cover all non-secure DRAM at 0xC000_0000. Apply the
@@ -49,35 +75,28 @@
 	 */
 	region_base = ddr_base;
 	region_top = ddr_ns_top;
-	tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1,
-				region_base,
-				region_top,
-				TZC_REGION_S_NONE,
-				TZC_REGION_NSEC_ALL_ACCESS_RDWR);
+	tzc400_add_region(region_base, region_top, false);
 
 #ifdef AARCH32_SP_OPTEE
 	/* Region 2 set to cover all secure DRAM. */
 	region_base = region_top + 1U;
 	region_top += STM32MP_DDR_S_SIZE;
-	tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 2,
-				region_base,
-				region_top,
-				TZC_REGION_S_RDWR,
-				0);
+	tzc400_add_region(region_base, region_top, true);
 
-	/* Region 3 set to cover non-secure shared memory DRAM. */
-	region_base = region_top + 1U;
-	region_top += STM32MP_DDR_SHMEM_SIZE;
-	tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 3,
-				region_base,
-				region_top,
-				TZC_REGION_S_NONE,
-				TZC_REGION_NSEC_ALL_ACCESS_RDWR);
+	ddr_top = STM32MP_DDR_BASE + dt_get_ddr_size() - 1U;
+	if (region_top < ddr_top) {
+		/* Region 3 set to cover non-secure memory DRAM after BL32. */
+		region_base = region_top + 1U;
+		region_top = ddr_top;
+		tzc400_add_region(region_base, region_top, false);
+	}
 #endif
 
-	tzc400_set_action(TZC_ACTION_INT);
-
-	tzc400_enable_filters();
+	/*
+	 * Raise an interrupt (secure FIQ) if a NS device tries to access
+	 * secure memory
+	 */
+	init_tzc400_end(TZC_ACTION_INT);
 }
 
 /*******************************************************************************
@@ -90,23 +109,11 @@
 	stm32mp_clk_enable(TZC1);
 	stm32mp_clk_enable(TZC2);
 
-	tzc400_init(STM32MP1_TZC_BASE);
-
-	tzc400_disable_filters();
-
-	/* Region 1 set to cover Non-Secure DRAM at 0xC000_0000 */
-	tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1,
-				STM32MP_DDR_BASE,
-				STM32MP_DDR_BASE +
-				(STM32MP_DDR_MAX_SIZE - 1U),
-				TZC_REGION_S_NONE,
-				TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) |
-				TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID));
+	/* Region 0 set to cover all DRAM secure at 0xC000_0000 */
+	init_tzc400_begin(TZC_REGION_S_RDWR);
 
 	/* Raise an exception if a NS device tries to access secure memory */
-	tzc400_set_action(TZC_ACTION_ERR);
-
-	tzc400_enable_filters();
+	init_tzc400_end(TZC_ACTION_ERR);
 }
 
 /*******************************************************************************
diff --git a/plat/st/stm32mp1/stm32mp1_stm32image_def.h b/plat/st/stm32mp1/stm32mp1_stm32image_def.h
new file mode 100644
index 0000000..8efa342
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_stm32image_def.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_STM32IMAGE_DEF_H
+#define STM32MP1_STM32IMAGE_DEF_H
+
+#ifdef AARCH32_SP_OPTEE
+#define STM32MP_DDR_S_SIZE		U(0x01E00000)	/* 30 MB */
+#define STM32MP_DDR_SHMEM_SIZE		U(0x00200000)	/* 2 MB */
+#else
+#define STM32MP_DDR_S_SIZE		U(0)
+#define STM32MP_DDR_SHMEM_SIZE		U(0)
+#endif
+
+#define STM32MP_BL2_SIZE		U(0x0001C000)	/* 112 KB for BL2 */
+#define STM32MP_DTB_SIZE		U(0x00006000)	/* 24 KB for DTB */
+
+#ifdef AARCH32_SP_OPTEE
+#define STM32MP_BL32_BASE		STM32MP_SEC_SYSRAM_BASE
+
+#define STM32MP_BL2_BASE		(STM32MP_SEC_SYSRAM_BASE + \
+					 STM32MP_SEC_SYSRAM_SIZE - \
+					 STM32MP_BL2_SIZE)
+
+/* OP-TEE loads from SYSRAM base to BL2 DTB start address */
+#define STM32MP_OPTEE_BASE		STM32MP_BL32_BASE
+#define STM32MP_OPTEE_SIZE		(STM32MP_SEC_SYSRAM_SIZE -  \
+					 STM32MP_BL2_SIZE - STM32MP_DTB_SIZE)
+#define STM32MP_BL32_SIZE		STM32MP_OPTEE_SIZE
+#else /* AARCH32_SP_OPTEE */
+#define STM32MP_BL32_SIZE		U(0x00019000)	/* 96 KB for BL32 */
+
+#define STM32MP_BL32_BASE		(STM32MP_SEC_SYSRAM_BASE + \
+					 STM32MP_SEC_SYSRAM_SIZE - \
+					 STM32MP_BL32_SIZE)
+
+#define STM32MP_BL2_BASE		(STM32MP_BL32_BASE - \
+					 STM32MP_BL2_SIZE)
+#endif /* AARCH32_SP_OPTEE */
+
+/* DTB initialization value */
+#define STM32MP_DTB_BASE		(STM32MP_BL2_BASE -	\
+					 STM32MP_DTB_SIZE)
+
+/*
+ * MAX_MMAP_REGIONS is usually:
+ * BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup
+ */
+#if defined(IMAGE_BL32)
+#define MAX_MMAP_REGIONS		6
+#endif
+
+/*******************************************************************************
+ * STM32MP1 RAW partition offset for MTD devices
+ ******************************************************************************/
+#define STM32MP_NOR_BL33_OFFSET		U(0x00080000)
+#ifdef AARCH32_SP_OPTEE
+#define STM32MP_NOR_TEEH_OFFSET		U(0x00280000)
+#define STM32MP_NOR_TEED_OFFSET		U(0x002C0000)
+#define STM32MP_NOR_TEEX_OFFSET		U(0x00300000)
+#endif
+
+#define STM32MP_NAND_BL33_OFFSET	U(0x00200000)
+#ifdef AARCH32_SP_OPTEE
+#define STM32MP_NAND_TEEH_OFFSET	U(0x00600000)
+#define STM32MP_NAND_TEED_OFFSET	U(0x00680000)
+#define STM32MP_NAND_TEEX_OFFSET	U(0x00700000)
+#endif
+
+#endif /* STM32MP1_STM32IMAGE_DEF_H */
diff --git a/plat/xilinx/common/include/ipi.h b/plat/xilinx/common/include/ipi.h
index 9c1d0f2..483902e 100644
--- a/plat/xilinx/common/include/ipi.h
+++ b/plat/xilinx/common/include/ipi.h
@@ -63,7 +63,7 @@
 int ipi_mb_enquire_status(uint32_t local, uint32_t remote);
 
 /* Trigger notification on the IPI mailbox */
-int ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking);
+void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking);
 
 /* Ack IPI mailbox notification */
 void ipi_mb_ack(uint32_t local, uint32_t remote);
diff --git a/plat/xilinx/common/ipi.c b/plat/xilinx/common/ipi.c
index ca4146e..0b8020b 100644
--- a/plat/xilinx/common/ipi.c
+++ b/plat/xilinx/common/ipi.c
@@ -13,7 +13,6 @@
 
 #include <common/debug.h>
 #include <common/runtime_svc.h>
-#include <drivers/delay_timer.h>
 #include <lib/bakery_lock.h>
 #include <lib/mmio.h>
 
@@ -39,9 +38,6 @@
 /* IPI register bit mask */
 #define IPI_BIT_MASK(I) (ipi_table[(I)].ipi_bit_mask)
 
-/* IPI Timeout */
-#define TIMEOUT_COUNT_US	U(0x4000)
-
 /* IPI configuration table */
 const static struct ipi_config *ipi_table;
 
@@ -160,30 +156,21 @@
  * @remote - remote IPI ID
  * @is_blocking - if to trigger the notification in blocking mode or not.
  *
- * return - 0 - Success or Error incase of timeout
  * It sets the remote bit in the IPI agent trigger register.
  *
  */
-int ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking)
+void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking)
 {
 	uint32_t status;
-	const unsigned int timeout_count = TIMEOUT_COUNT_US;
-	uint64_t timeout;
 
 	mmio_write_32(IPI_REG_BASE(local) + IPI_TRIG_OFFSET,
 		      IPI_BIT_MASK(remote));
 	if (is_blocking) {
-		timeout = timeout_init_us(timeout_count);
 		do {
 			status = mmio_read_32(IPI_REG_BASE(local) +
 					      IPI_OBR_OFFSET);
-			if (timeout_elapsed(timeout)) {
-				return -ETIMEDOUT;
-			}
 		} while (status & IPI_BIT_MASK(remote));
 	}
-
-	return 0;
 }
 
 /* ipi_mb_ack() - Ack IPI mailbox notification from the other end
diff --git a/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c b/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c
index cd5d830..f531158 100644
--- a/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c
+++ b/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c
@@ -107,8 +107,8 @@
 		uint32_t is_blocking;
 
 		is_blocking = (x3 & IPI_SMC_NOTIFY_BLOCK_MASK) ? 1 : 0;
-		ret = ipi_mb_notify(ipi_local_id, ipi_remote_id, is_blocking);
-		SMC_RET1(handle, ret);
+		ipi_mb_notify(ipi_local_id, ipi_remote_id, is_blocking);
+		SMC_RET1(handle, 0);
 	}
 	case IPI_MAILBOX_ACK:
 	{
diff --git a/plat/xilinx/common/pm_service/pm_ipi.c b/plat/xilinx/common/pm_service/pm_ipi.c
index 7b5bd02..7b2c8ec 100644
--- a/plat/xilinx/common/pm_service/pm_ipi.c
+++ b/plat/xilinx/common/pm_service/pm_ipi.c
@@ -55,7 +55,6 @@
 					     uint32_t payload[PAYLOAD_ARG_CNT],
 					     uint32_t is_blocking)
 {
-	int status;
 	unsigned int offset = 0;
 	uintptr_t buffer_base = proc->ipi->buffer_base +
 					IPI_BUFFER_TARGET_REMOTE_OFFSET +
@@ -71,13 +70,10 @@
 	}
 
 	/* Generate IPI to remote processor */
-	status = ipi_mb_notify(proc->ipi->local_ipi_id, proc->ipi->remote_ipi_id,
+	ipi_mb_notify(proc->ipi->local_ipi_id, proc->ipi->remote_ipi_id,
 		      is_blocking);
-	if (status == 0) {
-		return PM_RET_SUCCESS;
-	}
 
-	return PM_RET_ERROR_TIMEOUT;
+	return PM_RET_SUCCESS;
 }
 
 /**
diff --git a/plat/xilinx/versal/platform.mk b/plat/xilinx/versal/platform.mk
index a0b317f..a8b2c94 100644
--- a/plat/xilinx/versal/platform.mk
+++ b/plat/xilinx/versal/platform.mk
@@ -9,6 +9,7 @@
 override RESET_TO_BL31 := 1
 PL011_GENERIC_UART := 1
 IPI_CRC_CHECK := 0
+HARDEN_SLS_ALL := 0
 
 ifdef VERSAL_ATF_MEM_BASE
     $(eval $(call add_define,VERSAL_ATF_MEM_BASE))
@@ -87,3 +88,7 @@
 				plat/xilinx/versal/pm_service/pm_svc_main.c	\
 				plat/xilinx/versal/pm_service/pm_api_sys.c	\
 				plat/xilinx/versal/pm_service/pm_client.c
+
+ifeq ($(HARDEN_SLS_ALL), 1)
+TF_CFLAGS_aarch64      +=      -mharden-sls=all
+endif
diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c
index 15fe187..912835a 100644
--- a/plat/xilinx/versal/pm_service/pm_api_sys.c
+++ b/plat/xilinx/versal/pm_service/pm_api_sys.c
@@ -173,7 +173,7 @@
 	/* Send request to the PLM */
 	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_ABORT_SUSPEND,
 			 reason, primary_proc->node_id);
-	return pm_ipi_send(primary_proc, payload);
+	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
 }
 
 /**
@@ -909,7 +909,7 @@
 
 	PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_SET_WAKEUP_SOURCE,
 			 target, wkup_device, enable);
-	return pm_ipi_send(primary_proc, payload);
+	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
 }
 
 /**
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
index f165fb0..9c5af88 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
@@ -677,6 +677,10 @@
 	case IOCTL_AFI:
 		ret = pm_ioctl_afi(arg1, arg2);
 		break;
+	case IOCTL_SET_FEATURE_CONFIG:
+	case IOCTL_GET_FEATURE_CONFIG:
+		ret = pm_feature_config(ioctl_id, arg1, arg2, value);
+		break;
 	default:
 		ret = PM_RET_ERROR_NOTSUPPORTED;
 		break;
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h
index 337f732..f18dc00 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h
@@ -15,28 +15,43 @@
 
 //ioctl id
 enum {
-	IOCTL_GET_RPU_OPER_MODE,
-	IOCTL_SET_RPU_OPER_MODE,
-	IOCTL_RPU_BOOT_ADDR_CONFIG,
-	IOCTL_TCM_COMB_CONFIG,
-	IOCTL_SET_TAPDELAY_BYPASS,
-	IOCTL_SET_SGMII_MODE,
-	IOCTL_SD_DLL_RESET,
-	IOCTL_SET_SD_TAPDELAY,
+	IOCTL_GET_RPU_OPER_MODE = 0,
+	IOCTL_SET_RPU_OPER_MODE = 1,
+	IOCTL_RPU_BOOT_ADDR_CONFIG = 2,
+	IOCTL_TCM_COMB_CONFIG = 3,
+	IOCTL_SET_TAPDELAY_BYPASS = 4,
+	IOCTL_SET_SGMII_MODE = 5,
+	IOCTL_SD_DLL_RESET = 6,
+	IOCTL_SET_SD_TAPDELAY = 7,
 	 /* Ioctl for clock driver */
-	IOCTL_SET_PLL_FRAC_MODE,
-	IOCTL_GET_PLL_FRAC_MODE,
-	IOCTL_SET_PLL_FRAC_DATA,
-	IOCTL_GET_PLL_FRAC_DATA,
-	IOCTL_WRITE_GGS,
-	IOCTL_READ_GGS,
-	IOCTL_WRITE_PGGS,
-	IOCTL_READ_PGGS,
+	IOCTL_SET_PLL_FRAC_MODE = 8,
+	IOCTL_GET_PLL_FRAC_MODE = 9,
+	IOCTL_SET_PLL_FRAC_DATA = 10,
+	IOCTL_GET_PLL_FRAC_DATA = 11,
+	IOCTL_WRITE_GGS = 12,
+	IOCTL_READ_GGS = 13,
+	IOCTL_WRITE_PGGS = 14,
+	IOCTL_READ_PGGS = 15,
 	/* IOCTL for ULPI reset */
-	IOCTL_ULPI_RESET,
+	IOCTL_ULPI_RESET = 16,
 	/* Set healthy bit value */
-	IOCTL_SET_BOOT_HEALTH_STATUS,
-	IOCTL_AFI,
+	IOCTL_SET_BOOT_HEALTH_STATUS = 17,
+	IOCTL_AFI = 18,
+	/* Probe counter read/write */
+	IOCTL_PROBE_COUNTER_READ = 19,
+	IOCTL_PROBE_COUNTER_WRITE = 20,
+	IOCTL_OSPI_MUX_SELECT = 21,
+	/* IOCTL for USB power request */
+	IOCTL_USB_SET_STATE = 22,
+	/* IOCTL to get last reset reason */
+	IOCTL_GET_LAST_RESET_REASON = 23,
+	/* AI engine NPI ISR clear */
+	IOCTL_AIE_ISR_CLEAR = 24,
+	/* Register SGI to ATF */
+	IOCTL_REGISTER_SGI = 25,
+	/* Runtime feature configuration */
+	IOCTL_SET_FEATURE_CONFIG = 26,
+	IOCTL_GET_FEATURE_CONFIG = 27,
 };
 
 //RPU operation mode
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
index 9a53408..5d9408c 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
@@ -209,7 +209,7 @@
 	/* TODO: allow passing the node ID of the affected CPU */
 	PM_PACK_PAYLOAD3(payload, PM_ABORT_SUSPEND, reason,
 			 primary_proc->node_id);
-	return pm_ipi_send(primary_proc, payload);
+	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
 }
 
 /**
@@ -228,7 +228,7 @@
 
 	PM_PACK_PAYLOAD4(payload, PM_SET_WAKEUP_SOURCE, target, wkup_node,
 			 enable);
-	return pm_ipi_send(primary_proc, payload);
+	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
 }
 
 /**
@@ -316,7 +316,7 @@
 	uint32_t payload[PAYLOAD_ARG_CNT];
 
 	PM_PACK_PAYLOAD2(payload, PM_RELEASE_NODE, nid);
-	return pm_ipi_send(primary_proc, payload);
+	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
 }
 
 /**
@@ -332,7 +332,7 @@
 	uint32_t payload[PAYLOAD_ARG_CNT];
 
 	PM_PACK_PAYLOAD3(payload, PM_SET_MAX_LATENCY, nid, latency);
-	return pm_ipi_send(primary_proc, payload);
+	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
 }
 
 /* Miscellaneous API functions */
@@ -461,7 +461,7 @@
 
 	/* Send request to the PMU */
 	PM_PACK_PAYLOAD3(payload, PM_RESET_ASSERT, reset, assert);
-	return pm_ipi_send(primary_proc, payload);
+	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
 }
 
 /**
@@ -1648,3 +1648,36 @@
 	EM_PACK_PAYLOAD1(payload, EM_SEND_ERRORS);
 	return pm_ipi_send_sync(primary_proc, payload, value, 1);
 }
+
+/**
+ * pm_feature_config() - feature configuration at runtime
+ *
+ * This function is used to send IPI request to PMUFW to configure feature
+ * at runtime. The feature can be enable or disable as well as the feature
+ * can be configure at runtime using an IOCTL call.
+ *
+ * @ioctl_id	The ioctl id for the feature configuration
+ * @config_id	The config id of the feature to be configured
+ * @value	The value to be configured
+ * @response	Return to reference pointer
+ *
+ * @return      Returns 0 on success or error value on failure
+ */
+enum pm_ret_status pm_feature_config(unsigned int ioctl_id,
+				     unsigned int config_id,
+				     unsigned int value,
+				     unsigned int *response)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD5(payload, PM_IOCTL, 0, ioctl_id, config_id, value);
+
+	if (ioctl_id == IOCTL_GET_FEATURE_CONFIG) {
+		return pm_ipi_send_sync(primary_proc, payload, response, 1);
+	} else if (ioctl_id == IOCTL_SET_FEATURE_CONFIG) {
+		return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+	} else {
+		return PM_RET_ERROR_ARGS;
+	}
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
index b0c2652..ca07cef 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
@@ -202,4 +202,9 @@
 enum pm_ret_status em_remove_action(unsigned int *value);
 enum pm_ret_status em_send_errors(unsigned int *value);
 
+enum pm_ret_status pm_feature_config(unsigned int ioctl_id,
+				     unsigned int config_id,
+				     unsigned int value,
+				     unsigned int *response);
+
 #endif /* PM_API_SYS_H */
diff --git a/services/arm_arch_svc/arm_arch_svc_setup.c b/services/arm_arch_svc/arm_arch_svc_setup.c
index 37bfc62..1d4423c 100644
--- a/services/arm_arch_svc/arm_arch_svc_setup.c
+++ b/services/arm_arch_svc/arm_arch_svc_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,9 +11,19 @@
 #include <lib/cpus/wa_cve_2018_3639.h>
 #include <lib/smccc.h>
 #include <services/arm_arch_svc.h>
+#include <services/rmi_svc.h>
+#include <services/rmmd_svc.h>
 #include <smccc_helpers.h>
 #include <plat/common/platform.h>
 
+#if ENABLE_RME
+/* Setup Arm architecture Services */
+static int32_t arm_arch_svc_setup(void)
+{
+	return rmmd_setup();
+}
+#endif
+
 static int32_t smccc_version(void)
 {
 	return MAKE_SMCCC_VERSION(SMCCC_MAJOR_VERSION, SMCCC_MINOR_VERSION);
@@ -133,6 +143,16 @@
 		SMC_RET0(handle);
 #endif
 	default:
+#if ENABLE_RME
+		/*
+		 * RMI functions are allocated from the Arch service range. Call
+		 * the RMM dispatcher to handle RMI calls.
+		 */
+		if (is_rmi_fid(smc_fid)) {
+			return rmmd_rmi_handler(smc_fid, x1, x2, x3, x4, cookie,
+						handle, flags);
+		}
+#endif
 		WARN("Unimplemented Arm Architecture Service Call: 0x%x \n",
 			smc_fid);
 		SMC_RET1(handle, SMC_UNK);
@@ -145,6 +165,10 @@
 		OEN_ARM_START,
 		OEN_ARM_END,
 		SMC_TYPE_FAST,
+#if ENABLE_RME
+		arm_arch_svc_setup,
+#else
 		NULL,
+#endif
 		arm_arch_svc_smc_handler
 );
diff --git a/services/std_svc/rmmd/aarch64/rmmd_helpers.S b/services/std_svc/rmmd/aarch64/rmmd_helpers.S
new file mode 100644
index 0000000..6229baf
--- /dev/null
+++ b/services/std_svc/rmmd/aarch64/rmmd_helpers.S
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "../rmmd_private.h"
+#include <asm_macros.S>
+
+	.global rmmd_rmm_enter
+	.global rmmd_rmm_exit
+
+	/* ---------------------------------------------------------------------
+	 * This function is called with SP_EL0 as stack. Here we stash our EL3
+	 * callee-saved registers on to the stack as a part of saving the C
+	 * runtime and enter the secure payload.
+	 * 'x0' contains a pointer to the memory where the address of the C
+	 *  runtime context is to be saved.
+	 * ---------------------------------------------------------------------
+	 */
+func rmmd_rmm_enter
+	/* Make space for the registers that we're going to save */
+	mov	x3, sp
+	str	x3, [x0, #0]
+	sub	sp, sp, #RMMD_C_RT_CTX_SIZE
+
+	/* Save callee-saved registers on to the stack */
+	stp	x19, x20, [sp, #RMMD_C_RT_CTX_X19]
+	stp	x21, x22, [sp, #RMMD_C_RT_CTX_X21]
+	stp	x23, x24, [sp, #RMMD_C_RT_CTX_X23]
+	stp	x25, x26, [sp, #RMMD_C_RT_CTX_X25]
+	stp	x27, x28, [sp, #RMMD_C_RT_CTX_X27]
+	stp	x29, x30, [sp, #RMMD_C_RT_CTX_X29]
+
+	/* ---------------------------------------------------------------------
+	 * Everything is setup now. el3_exit() will use the secure context to
+	 * restore to the general purpose and EL3 system registers to ERET
+	 * into the secure payload.
+	 * ---------------------------------------------------------------------
+	 */
+	b	el3_exit
+endfunc rmmd_rmm_enter
+
+	/* ---------------------------------------------------------------------
+	 * This function is called with 'x0' pointing to a C runtime context.
+	 * It restores the saved registers and jumps to that runtime with 'x0'
+	 * as the new SP register. This destroys the C runtime context that had
+	 * been built on the stack below the saved context by the caller. Later
+	 * the second parameter 'x1' is passed as a return value to the caller.
+	 * ---------------------------------------------------------------------
+	 */
+func rmmd_rmm_exit
+	/* Restore the previous stack */
+	mov	sp, x0
+
+	/* Restore callee-saved registers on to the stack */
+	ldp	x19, x20, [x0, #(RMMD_C_RT_CTX_X19 - RMMD_C_RT_CTX_SIZE)]
+	ldp	x21, x22, [x0, #(RMMD_C_RT_CTX_X21 - RMMD_C_RT_CTX_SIZE)]
+	ldp	x23, x24, [x0, #(RMMD_C_RT_CTX_X23 - RMMD_C_RT_CTX_SIZE)]
+	ldp	x25, x26, [x0, #(RMMD_C_RT_CTX_X25 - RMMD_C_RT_CTX_SIZE)]
+	ldp	x27, x28, [x0, #(RMMD_C_RT_CTX_X27 - RMMD_C_RT_CTX_SIZE)]
+	ldp	x29, x30, [x0, #(RMMD_C_RT_CTX_X29 - RMMD_C_RT_CTX_SIZE)]
+
+	/* ---------------------------------------------------------------------
+	 * This should take us back to the instruction after the call to the
+	 * last rmmd_rmm_enter().* Place the second parameter to x0
+	 * so that the caller will see it as a return value from the original
+	 * entry call.
+	 * ---------------------------------------------------------------------
+	 */
+	mov	x0, x1
+	ret
+endfunc rmmd_rmm_exit
diff --git a/services/std_svc/rmmd/rmmd.mk b/services/std_svc/rmmd/rmmd.mk
new file mode 100644
index 0000000..bac0a9f
--- /dev/null
+++ b/services/std_svc/rmmd/rmmd.mk
@@ -0,0 +1,18 @@
+#
+# Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ifneq (${ARCH},aarch64)
+        $(error "Error: RMMD is only supported on aarch64.")
+endif
+
+include services/std_svc/rmmd/trp/trp.mk
+
+RMMD_SOURCES	+=	$(addprefix services/std_svc/rmmd/,	\
+			${ARCH}/rmmd_helpers.S			\
+			rmmd_main.c)
+
+# Let the top-level Makefile know that we intend to include RMM image
+NEED_RMM	:=	yes
diff --git a/services/std_svc/rmmd/rmmd_initial_context.h b/services/std_svc/rmmd/rmmd_initial_context.h
new file mode 100644
index 0000000..d7a743d
--- /dev/null
+++ b/services/std_svc/rmmd/rmmd_initial_context.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RMMD_INITIAL_CONTEXT_H
+#define RMMD_INITIAL_CONTEXT_H
+
+#include <arch.h>
+
+/*
+ * SPSR_EL2
+ *   M=0x9 (0b1001 EL2h)
+ *   M[4]=0
+ *   DAIF=0xF Exceptions masked on entry.
+ *   BTYPE=0  BTI not yet supported.
+ *   SSBS=0   Not yet supported.
+ *   IL=0     Not an illegal exception return.
+ *   SS=0     Not single stepping.
+ *   PAN=1    RMM shouldn't access realm memory.
+ *   UAO=0
+ *   DIT=0
+ *   TCO=0
+ *   NZCV=0
+ */
+#define REALM_SPSR_EL2		(					\
+					SPSR_M_EL2H			| \
+					(0xF << SPSR_DAIF_SHIFT)	| \
+					SPSR_PAN_BIT			\
+				)
+
+#endif /* RMMD_INITIAL_CONTEXT_H */
diff --git a/services/std_svc/rmmd/rmmd_main.c b/services/std_svc/rmmd/rmmd_main.c
new file mode 100644
index 0000000..dacd150
--- /dev/null
+++ b/services/std_svc/rmmd/rmmd_main.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <arch_features.h>
+#include <bl31/bl31.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <context.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/el3_runtime/pubsub.h>
+#include <lib/gpt_rme/gpt_rme.h>
+
+#include <lib/spinlock.h>
+#include <lib/utils.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/common_def.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <services/gtsi_svc.h>
+#include <services/rmi_svc.h>
+#include <services/rmmd_svc.h>
+#include <smccc_helpers.h>
+#include "rmmd_initial_context.h"
+#include "rmmd_private.h"
+
+/*******************************************************************************
+ * RMM context information.
+ ******************************************************************************/
+rmmd_rmm_context_t rmm_context[PLATFORM_CORE_COUNT];
+
+/*******************************************************************************
+ * RMM entry point information. Discovered on the primary core and reused
+ * on secondary cores.
+ ******************************************************************************/
+static entry_point_info_t *rmm_ep_info;
+
+/*******************************************************************************
+ * Static function declaration.
+ ******************************************************************************/
+static int32_t rmm_init(void);
+static uint64_t rmmd_smc_forward(uint32_t smc_fid, uint32_t src_sec_state,
+					uint32_t dst_sec_state, uint64_t x1,
+					uint64_t x2, uint64_t x3, uint64_t x4,
+					void *handle);
+
+/*******************************************************************************
+ * This function takes an RMM context pointer and performs a synchronous entry
+ * into it.
+ ******************************************************************************/
+uint64_t rmmd_rmm_sync_entry(rmmd_rmm_context_t *rmm_ctx)
+{
+	uint64_t rc;
+
+	assert(rmm_ctx != NULL);
+
+	cm_set_context(&(rmm_ctx->cpu_ctx), REALM);
+
+	/* Save the current el1/el2 context before loading realm context. */
+	cm_el1_sysregs_context_save(NON_SECURE);
+	cm_el2_sysregs_context_save(NON_SECURE);
+
+	/* Restore the realm context assigned above */
+	cm_el1_sysregs_context_restore(REALM);
+	cm_el2_sysregs_context_restore(REALM);
+	cm_set_next_eret_context(REALM);
+
+	/* Enter RMM */
+	rc = rmmd_rmm_enter(&rmm_ctx->c_rt_ctx);
+
+	/* Save realm context */
+	cm_el1_sysregs_context_save(REALM);
+	cm_el2_sysregs_context_save(REALM);
+
+	/* Restore the el1/el2 context again. */
+	cm_el1_sysregs_context_restore(NON_SECURE);
+	cm_el2_sysregs_context_restore(NON_SECURE);
+
+	return rc;
+}
+
+/*******************************************************************************
+ * This function returns to the place where rmmd_rmm_sync_entry() was
+ * called originally.
+ ******************************************************************************/
+__dead2 void rmmd_rmm_sync_exit(uint64_t rc)
+{
+	rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()];
+
+	/* Get context of the RMM in use by this CPU. */
+	assert(cm_get_context(REALM) == &(ctx->cpu_ctx));
+
+	/*
+	 * The RMMD must have initiated the original request through a
+	 * synchronous entry into RMM. Jump back to the original C runtime
+	 * context with the value of rc in x0;
+	 */
+	rmmd_rmm_exit(ctx->c_rt_ctx, rc);
+
+	panic();
+}
+
+static void rmm_el2_context_init(el2_sysregs_t *regs)
+{
+	regs->ctx_regs[CTX_SPSR_EL2 >> 3] = REALM_SPSR_EL2;
+	regs->ctx_regs[CTX_SCTLR_EL2 >> 3] = SCTLR_EL2_RES1;
+}
+
+/*******************************************************************************
+ * Jump to the RMM for the first time.
+ ******************************************************************************/
+static int32_t rmm_init(void)
+{
+
+	uint64_t rc;
+
+	rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()];
+
+	INFO("RMM init start.\n");
+	ctx->state = RMM_STATE_RESET;
+
+	/* Initialize RMM EL2 context. */
+	rmm_el2_context_init(&ctx->cpu_ctx.el2_sysregs_ctx);
+
+	rc = rmmd_rmm_sync_entry(ctx);
+	if (rc != 0ULL) {
+		ERROR("RMM initialisation failed 0x%llx\n", rc);
+		panic();
+	}
+
+	ctx->state = RMM_STATE_IDLE;
+	INFO("RMM init end.\n");
+
+	return 1;
+}
+
+/*******************************************************************************
+ * Load and read RMM manifest, setup RMM.
+ ******************************************************************************/
+int rmmd_setup(void)
+{
+	uint32_t ep_attr;
+	unsigned int linear_id = plat_my_core_pos();
+	rmmd_rmm_context_t *rmm_ctx = &rmm_context[linear_id];
+
+	/* Make sure RME is supported. */
+	assert(get_armv9_2_feat_rme_support() != 0U);
+
+	rmm_ep_info = bl31_plat_get_next_image_ep_info(REALM);
+	if (rmm_ep_info == NULL) {
+		WARN("No RMM image provided by BL2 boot loader, Booting "
+		     "device without RMM initialization. SMCs destined for "
+		     "RMM will return SMC_UNK\n");
+		return -ENOENT;
+	}
+
+	/* Under no circumstances will this parameter be 0 */
+	assert(rmm_ep_info->pc == RMM_BASE);
+
+	/* Initialise an entrypoint to set up the CPU context */
+	ep_attr = EP_REALM;
+	if ((read_sctlr_el3() & SCTLR_EE_BIT) != 0U) {
+		ep_attr |= EP_EE_BIG;
+	}
+
+	SET_PARAM_HEAD(rmm_ep_info, PARAM_EP, VERSION_1, ep_attr);
+	rmm_ep_info->spsr = SPSR_64(MODE_EL2,
+					MODE_SP_ELX,
+					DISABLE_ALL_EXCEPTIONS);
+
+	/* Initialise RMM context with this entry point information */
+	cm_setup_context(&rmm_ctx->cpu_ctx, rmm_ep_info);
+
+	INFO("RMM setup done.\n");
+
+	/* Register init function for deferred init.  */
+	bl31_register_rmm_init(&rmm_init);
+
+	return 0;
+}
+
+/*******************************************************************************
+ * Forward SMC to the other security state
+ ******************************************************************************/
+static uint64_t	rmmd_smc_forward(uint32_t smc_fid, uint32_t src_sec_state,
+					uint32_t dst_sec_state, uint64_t x1,
+					uint64_t x2, uint64_t x3, uint64_t x4,
+					void *handle)
+{
+	/* Save incoming security state */
+	cm_el1_sysregs_context_save(src_sec_state);
+	cm_el2_sysregs_context_save(src_sec_state);
+
+	/* Restore outgoing security state */
+	cm_el1_sysregs_context_restore(dst_sec_state);
+	cm_el2_sysregs_context_restore(dst_sec_state);
+	cm_set_next_eret_context(dst_sec_state);
+
+	SMC_RET8(cm_get_context(dst_sec_state), smc_fid, x1, x2, x3, x4,
+			SMC_GET_GP(handle, CTX_GPREG_X5),
+			SMC_GET_GP(handle, CTX_GPREG_X6),
+			SMC_GET_GP(handle, CTX_GPREG_X7));
+}
+
+/*******************************************************************************
+ * This function handles all SMCs in the range reserved for RMI. Each call is
+ * either forwarded to the other security state or handled by the RMM dispatcher
+ ******************************************************************************/
+uint64_t rmmd_rmi_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2,
+				uint64_t x3, uint64_t x4, void *cookie,
+				void *handle, uint64_t flags)
+{
+	rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()];
+	uint32_t src_sec_state;
+
+	/* Determine which security state this SMC originated from */
+	src_sec_state = caller_sec_state(flags);
+
+	/* RMI must not be invoked by the Secure world */
+	if (src_sec_state == SMC_FROM_SECURE) {
+		WARN("RMM: RMI invoked by secure world.\n");
+		SMC_RET1(handle, SMC_UNK);
+	}
+
+	/*
+	 * Forward an RMI call from the Normal world to the Realm world as it
+	 * is.
+	 */
+	if (src_sec_state == SMC_FROM_NON_SECURE) {
+		VERBOSE("RMM: RMI call from non-secure world.\n");
+		return rmmd_smc_forward(smc_fid, NON_SECURE, REALM,
+					x1, x2, x3, x4, handle);
+	}
+
+	assert(src_sec_state == SMC_FROM_REALM);
+
+	switch (smc_fid) {
+	case RMI_RMM_REQ_COMPLETE:
+		if (ctx->state == RMM_STATE_RESET) {
+			VERBOSE("RMM: running rmmd_rmm_sync_exit\n");
+			rmmd_rmm_sync_exit(x1);
+		}
+
+		return rmmd_smc_forward(x1, REALM, NON_SECURE,
+					x2, x3, x4, 0, handle);
+
+	default:
+		WARN("RMM: Unsupported RMM call 0x%08x\n", smc_fid);
+		SMC_RET1(handle, SMC_UNK);
+	}
+}
+
+/*******************************************************************************
+ * This cpu has been turned on. Enter RMM to initialise R-EL2.  Entry into RMM
+ * is done after initialising minimal architectural state that guarantees safe
+ * execution.
+ ******************************************************************************/
+static void *rmmd_cpu_on_finish_handler(const void *arg)
+{
+	int32_t rc;
+	uint32_t linear_id = plat_my_core_pos();
+	rmmd_rmm_context_t *ctx = &rmm_context[linear_id];
+
+	ctx->state = RMM_STATE_RESET;
+
+	/* Initialise RMM context with this entry point information */
+	cm_setup_context(&ctx->cpu_ctx, rmm_ep_info);
+
+	/* Initialize RMM EL2 context. */
+	rmm_el2_context_init(&ctx->cpu_ctx.el2_sysregs_ctx);
+
+	rc = rmmd_rmm_sync_entry(ctx);
+	if (rc != 0) {
+		ERROR("RMM initialisation failed (%d) on CPU%d\n", rc,
+		      linear_id);
+		panic();
+	}
+
+	ctx->state = RMM_STATE_IDLE;
+	return NULL;
+}
+
+/* Subscribe to PSCI CPU on to initialize RMM on secondary */
+SUBSCRIBE_TO_EVENT(psci_cpu_on_finish, rmmd_cpu_on_finish_handler);
+
+static int gtsi_transition_granule(uint64_t pa,
+					unsigned int src_sec_state,
+					unsigned int target_pas)
+{
+	int ret;
+
+	ret = gpt_transition_pas(pa, PAGE_SIZE_4KB, src_sec_state, target_pas);
+
+	/* Convert TF-A error codes into GTSI error codes */
+	if (ret == -EINVAL) {
+		ERROR("[GTSI] Transition failed: invalid %s\n", "address");
+		ERROR("       PA: 0x%llx, SRC: %d, PAS: %d\n", pa,
+		      src_sec_state, target_pas);
+		ret = GRAN_TRANS_RET_BAD_ADDR;
+	} else if (ret == -EPERM) {
+		ERROR("[GTSI] Transition failed: invalid %s\n", "caller/PAS");
+		ERROR("       PA: 0x%llx, SRC: %d, PAS: %d\n", pa,
+		      src_sec_state, target_pas);
+		ret = GRAN_TRANS_RET_BAD_PAS;
+	}
+
+	return ret;
+}
+
+/*******************************************************************************
+ * This function handles all SMCs in the range reserved for GTF.
+ ******************************************************************************/
+uint64_t rmmd_gtsi_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2,
+				uint64_t x3, uint64_t x4, void *cookie,
+				void *handle, uint64_t flags)
+{
+	uint32_t src_sec_state;
+
+	/* Determine which security state this SMC originated from */
+	src_sec_state = caller_sec_state(flags);
+
+	if (src_sec_state != SMC_FROM_REALM) {
+		WARN("RMM: GTF call originated from secure or normal world\n");
+		SMC_RET1(handle, SMC_UNK);
+	}
+
+	switch (smc_fid) {
+	case SMC_ASC_MARK_REALM:
+		SMC_RET1(handle, gtsi_transition_granule(x1, SMC_FROM_REALM,
+								GPT_GPI_REALM));
+	case SMC_ASC_MARK_NONSECURE:
+		SMC_RET1(handle, gtsi_transition_granule(x1, SMC_FROM_REALM,
+								GPT_GPI_NS));
+	default:
+		WARN("RMM: Unsupported GTF call 0x%08x\n", smc_fid);
+		SMC_RET1(handle, SMC_UNK);
+	}
+}
diff --git a/services/std_svc/rmmd/rmmd_private.h b/services/std_svc/rmmd/rmmd_private.h
new file mode 100644
index 0000000..d170bcd
--- /dev/null
+++ b/services/std_svc/rmmd/rmmd_private.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RMMD_PRIVATE_H
+#define RMMD_PRIVATE_H
+
+#include <context.h>
+
+/*******************************************************************************
+ * Constants that allow assembler code to preserve callee-saved registers of the
+ * C runtime context while performing a security state switch.
+ ******************************************************************************/
+#define RMMD_C_RT_CTX_X19		0x0
+#define RMMD_C_RT_CTX_X20		0x8
+#define RMMD_C_RT_CTX_X21		0x10
+#define RMMD_C_RT_CTX_X22		0x18
+#define RMMD_C_RT_CTX_X23		0x20
+#define RMMD_C_RT_CTX_X24		0x28
+#define RMMD_C_RT_CTX_X25		0x30
+#define RMMD_C_RT_CTX_X26		0x38
+#define RMMD_C_RT_CTX_X27		0x40
+#define RMMD_C_RT_CTX_X28		0x48
+#define RMMD_C_RT_CTX_X29		0x50
+#define RMMD_C_RT_CTX_X30		0x58
+
+#define RMMD_C_RT_CTX_SIZE		0x60
+#define RMMD_C_RT_CTX_ENTRIES		(RMMD_C_RT_CTX_SIZE >> DWORD_SHIFT)
+
+#ifndef __ASSEMBLER__
+#include <stdint.h>
+#include <services/rmi_svc.h>
+
+typedef enum rmm_state {
+	RMM_STATE_RESET = 0,
+	RMM_STATE_IDLE
+} rmm_state_t;
+
+/*
+ * Data structure used by the RMM dispatcher (RMMD) in EL3 to track context of
+ * the RMM at R-EL2.
+ */
+typedef struct rmmd_rmm_context {
+	uint64_t c_rt_ctx;
+	cpu_context_t cpu_ctx;
+	rmm_state_t state;
+} rmmd_rmm_context_t;
+
+/* Functions used to enter/exit the RMM synchronously */
+uint64_t rmmd_rmm_sync_entry(rmmd_rmm_context_t *ctx);
+__dead2 void rmmd_rmm_sync_exit(uint64_t rc);
+
+/* Assembly helpers */
+uint64_t rmmd_rmm_enter(uint64_t *c_rt_ctx);
+void __dead2 rmmd_rmm_exit(uint64_t c_rt_ctx, uint64_t ret);
+
+/* Reference to PM ops for the RMMD */
+extern const spd_pm_ops_t rmmd_pm;
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* RMMD_PRIVATE_H */
diff --git a/services/std_svc/rmmd/trp/linker.lds b/services/std_svc/rmmd/trp/linker.lds
new file mode 100644
index 0000000..2b7f383
--- /dev/null
+++ b/services/std_svc/rmmd/trp/linker.lds
@@ -0,0 +1,71 @@
+/*
+ * (C) COPYRIGHT 2021 Arm Limited or its affiliates.
+ * ALL RIGHTS RESERVED
+ */
+
+#include <common/bl_common.ld.h>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+
+/* Mapped using 4K pages, requires us to align different sections with
+ * different property at the same granularity. */
+PAGE_SIZE_4K = 4096;
+
+OUTPUT_FORMAT("elf64-littleaarch64")
+OUTPUT_ARCH(aarch64)
+ENTRY(trp_head)
+
+MEMORY {
+	RAM (rwx): ORIGIN = RMM_BASE, LENGTH = RMM_LIMIT - RMM_BASE
+}
+
+
+SECTIONS
+{
+	. = RMM_BASE;
+
+	.text : {
+		*(.head.text)
+		. = ALIGN(8);
+		*(.text*)
+	} >RAM
+
+	. = ALIGN(PAGE_SIZE_4K);
+
+	.rodata : {
+		*(.rodata*)
+	} >RAM
+
+	. = ALIGN(PAGE_SIZE_4K);
+
+	 __RW_START__ = . ;
+
+	.data : {
+		*(.data*)
+	} >RAM
+
+	.bss (NOLOAD) : {
+		__BSS_START__ = .;
+		*(.bss*)
+		__BSS_END__ = .;
+	} >RAM
+	__BSS_SIZE__ = SIZEOF(.bss);
+
+
+	STACK_SECTION >RAM
+
+
+	/*
+	* Define a linker symbol to mark the end of the RW memory area for this
+	* image.
+	*/
+	__RW_END__ = .;
+	__RMM_END__ = .;
+
+
+	/DISCARD/ : { *(.dynstr*) }
+	/DISCARD/ : { *(.dynamic*) }
+	/DISCARD/ : { *(.plt*) }
+	/DISCARD/ : { *(.interp*) }
+	/DISCARD/ : { *(.gnu*) }
+	/DISCARD/ : { *(.note*) }
+}
diff --git a/services/std_svc/rmmd/trp/trp.mk b/services/std_svc/rmmd/trp/trp.mk
new file mode 100644
index 0000000..a4f6e03
--- /dev/null
+++ b/services/std_svc/rmmd/trp/trp.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2021 Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+RMM_SOURCES		+=	services/std_svc/rmmd/trp/trp_entry.S	\
+				services/std_svc/rmmd/trp/trp_main.c
+
+RMM_LINKERFILE		:=	services/std_svc/rmmd/trp/linker.lds
+
+# Include the platform-specific TRP Makefile
+# If no platform-specific TRP Makefile exists, it means TRP is not supported
+# on this platform.
+TRP_PLAT_MAKEFILE := $(wildcard ${PLAT_DIR}/trp/trp-${PLAT}.mk)
+ifeq (,${TRP_PLAT_MAKEFILE})
+  $(error TRP is not supported on platform ${PLAT})
+else
+  include ${TRP_PLAT_MAKEFILE}
+endif
diff --git a/services/std_svc/rmmd/trp/trp_entry.S b/services/std_svc/rmmd/trp/trp_entry.S
new file mode 100644
index 0000000..23b48fb
--- /dev/null
+++ b/services/std_svc/rmmd/trp/trp_entry.S
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <services/gtsi_svc.h>
+#include <services/rmi_svc.h>
+#include "trp_private.h"
+
+.global trp_head
+.global trp_smc
+
+.section ".head.text", "ax"
+
+	/* ---------------------------------------------
+	 * Populate the params in x0-x7 from the pointer
+	 * to the smc args structure in x0.
+	 * ---------------------------------------------
+	 */
+	.macro restore_args_call_smc
+	ldp	x6, x7, [x0, #TRP_ARG6]
+	ldp	x4, x5, [x0, #TRP_ARG4]
+	ldp	x2, x3, [x0, #TRP_ARG2]
+	ldp	x0, x1, [x0, #TRP_ARG0]
+	smc	#0
+	.endm
+
+	/* ---------------------------------------------
+	 * Entry point for TRP
+	 * ---------------------------------------------
+	 */
+trp_head:
+	bl	plat_set_my_stack
+	bl	plat_is_my_cpu_primary
+	cbz	x0, trp_secondary_cpu_entry
+
+	/* ---------------------------------------------
+	 * Zero out BSS section
+	 * ---------------------------------------------
+	 */
+	ldr	x0, =__BSS_START__
+	ldr	x1, =__BSS_SIZE__
+	bl	zeromem
+
+	bl	trp_setup
+
+	bl	trp_main
+trp_secondary_cpu_entry:
+	mov_imm	x0, RMI_RMM_REQ_COMPLETE
+	mov	x1, xzr
+	smc	#0
+	b	trp_handler
+
+	/* ---------------------------------------------
+	 *   Direct SMC call to BL31 service provided by
+	 *   RMM Dispatcher
+	 * ---------------------------------------------
+	 */
+func trp_smc
+	restore_args_call_smc
+	ret
+endfunc trp_smc
+
+	/* ---------------------------------------------
+	 * RMI call handler
+	 * ---------------------------------------------
+	 */
+func trp_handler
+	bl	trp_rmi_handler
+	restore_args_call_smc
+	b	trp_handler
+endfunc trp_handler
diff --git a/services/std_svc/rmmd/trp/trp_main.c b/services/std_svc/rmmd/trp/trp_main.c
new file mode 100644
index 0000000..2ab9ecc
--- /dev/null
+++ b/services/std_svc/rmmd/trp/trp_main.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+#include <common/debug.h>
+#include <plat/common/platform.h>
+#include <services/gtsi_svc.h>
+#include <services/rmi_svc.h>
+#include <services/trp/platform_trp.h>
+
+#include <platform_def.h>
+#include "trp_private.h"
+
+/*******************************************************************************
+ * Per cpu data structure to populate parameters for an SMC in C code and use
+ * a pointer to this structure in assembler code to populate x0-x7
+ ******************************************************************************/
+static trp_args_t trp_smc_args[PLATFORM_CORE_COUNT];
+
+/*******************************************************************************
+ * Set the arguments for SMC call
+ ******************************************************************************/
+static trp_args_t *set_smc_args(uint64_t arg0,
+				uint64_t arg1,
+				uint64_t arg2,
+				uint64_t arg3,
+				uint64_t arg4,
+				uint64_t arg5,
+				uint64_t arg6,
+				uint64_t arg7)
+{
+	uint32_t linear_id;
+	trp_args_t *pcpu_smc_args;
+
+	/*
+	 * Return to Secure Monitor by raising an SMC. The results of the
+	 * service are passed as an arguments to the SMC
+	 */
+	linear_id = plat_my_core_pos();
+	pcpu_smc_args = &trp_smc_args[linear_id];
+	write_trp_arg(pcpu_smc_args, TRP_ARG0, arg0);
+	write_trp_arg(pcpu_smc_args, TRP_ARG1, arg1);
+	write_trp_arg(pcpu_smc_args, TRP_ARG2, arg2);
+	write_trp_arg(pcpu_smc_args, TRP_ARG3, arg3);
+	write_trp_arg(pcpu_smc_args, TRP_ARG4, arg4);
+	write_trp_arg(pcpu_smc_args, TRP_ARG5, arg5);
+	write_trp_arg(pcpu_smc_args, TRP_ARG6, arg6);
+	write_trp_arg(pcpu_smc_args, TRP_ARG7, arg7);
+
+	return pcpu_smc_args;
+}
+
+/*******************************************************************************
+ * Setup function for TRP.
+ ******************************************************************************/
+void trp_setup(void)
+{
+	/* Perform early platform-specific setup */
+	trp_early_platform_setup();
+}
+
+/* Main function for TRP */
+void trp_main(void)
+{
+	NOTICE("TRP: %s\n", version_string);
+	NOTICE("TRP: %s\n", build_message);
+	INFO("TRP: Memory base : 0x%lx\n", (unsigned long)RMM_BASE);
+	INFO("TRP: Total size : 0x%lx bytes\n", (unsigned long)(RMM_END
+								- RMM_BASE));
+}
+
+/*******************************************************************************
+ * Returning RMI version back to Normal World
+ ******************************************************************************/
+static trp_args_t *trp_ret_rmi_version(void)
+{
+	VERBOSE("RMM version is %u.%u\n", RMI_ABI_VERSION_MAJOR,
+					  RMI_ABI_VERSION_MINOR);
+	return set_smc_args(RMI_RMM_REQ_COMPLETE, RMI_ABI_VERSION,
+			    0, 0, 0, 0, 0, 0);
+}
+
+/*******************************************************************************
+ * Transitioning granule of NON-SECURE type to REALM type
+ ******************************************************************************/
+static trp_args_t *trp_asc_mark_realm(unsigned long long x1)
+{
+	unsigned long long ret;
+
+	VERBOSE("Delegating granule 0x%llx\n", x1);
+	ret = trp_smc(set_smc_args(SMC_ASC_MARK_REALM, x1, 0, 0, 0, 0, 0, 0));
+
+	if (ret != 0ULL) {
+		ERROR("Granule transition from NON-SECURE type to REALM type "
+			"failed 0x%llx\n", ret);
+	}
+	return set_smc_args(RMI_RMM_REQ_COMPLETE, ret, 0, 0, 0, 0, 0, 0);
+}
+
+/*******************************************************************************
+ * Transitioning granule of REALM type to NON-SECURE type
+ ******************************************************************************/
+static trp_args_t *trp_asc_mark_nonsecure(unsigned long long x1)
+{
+	unsigned long long ret;
+
+	VERBOSE("Undelegating granule 0x%llx\n", x1);
+	ret = trp_smc(set_smc_args(SMC_ASC_MARK_NONSECURE, x1, 0, 0, 0, 0, 0, 0));
+
+	if (ret != 0ULL) {
+		ERROR("Granule transition from REALM type to NON-SECURE type "
+			"failed 0x%llx\n", ret);
+	}
+	return set_smc_args(RMI_RMM_REQ_COMPLETE, ret, 0, 0, 0, 0, 0, 0);
+}
+
+/*******************************************************************************
+ * Main RMI SMC handler function
+ ******************************************************************************/
+trp_args_t *trp_rmi_handler(unsigned long fid, unsigned long long x1)
+{
+	switch (fid) {
+	case RMI_RMM_REQ_VERSION:
+		return trp_ret_rmi_version();
+	case RMI_RMM_GRANULE_DELEGATE:
+		return trp_asc_mark_realm(x1);
+	case RMI_RMM_GRANULE_UNDELEGATE:
+		return trp_asc_mark_nonsecure(x1);
+	default:
+		ERROR("Invalid SMC code to %s, FID %lu\n", __func__, fid);
+	}
+	return set_smc_args(SMC_UNK, 0, 0, 0, 0, 0, 0, 0);
+}
diff --git a/services/std_svc/rmmd/trp/trp_private.h b/services/std_svc/rmmd/trp/trp_private.h
new file mode 100644
index 0000000..9231390
--- /dev/null
+++ b/services/std_svc/rmmd/trp/trp_private.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TRP_PRIVATE_H
+#define TRP_PRIVATE_H
+
+/* Definitions to help the assembler access the SMC/ERET args structure */
+#define TRP_ARGS_SIZE		TRP_ARGS_END
+#define TRP_ARG0		0x0
+#define TRP_ARG1		0x8
+#define TRP_ARG2		0x10
+#define TRP_ARG3		0x18
+#define TRP_ARG4		0x20
+#define TRP_ARG5		0x28
+#define TRP_ARG6		0x30
+#define TRP_ARG7		0x38
+#define TRP_ARGS_END		0x40
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+/* Data structure to hold SMC arguments */
+typedef struct trp_args {
+	uint64_t regs[TRP_ARGS_END >> 3];
+} __aligned(CACHE_WRITEBACK_GRANULE) trp_args_t;
+
+#define write_trp_arg(args, offset, val) (((args)->regs[offset >> 3])	\
+					 = val)
+
+/* Definitions for RMI VERSION */
+#define RMI_ABI_VERSION_MAJOR		U(0x0)
+#define RMI_ABI_VERSION_MINOR		U(0x0)
+#define RMI_ABI_VERSION			((RMI_ABI_VERSION_MAJOR << 16) | \
+					RMI_ABI_VERSION_MINOR)
+
+/* Helper to issue SMC calls to BL31 */
+uint64_t trp_smc(trp_args_t *);
+
+/* The main function to executed only by Primary CPU */
+void trp_main(void);
+
+/* Setup TRP. Executed only by Primary CPU */
+void trp_setup(void);
+
+#endif /* __ASSEMBLER__ */
+#endif /* TRP_PRIVATE_H */
diff --git a/services/std_svc/sdei/sdei_intr_mgmt.c b/services/std_svc/sdei/sdei_intr_mgmt.c
index fa1d3d2..5d176c2 100644
--- a/services/std_svc/sdei/sdei_intr_mgmt.c
+++ b/services/std_svc/sdei/sdei_intr_mgmt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,6 +8,7 @@
 #include <string.h>
 
 #include <arch_helpers.h>
+#include <arch_features.h>
 #include <bl31/ehf.h>
 #include <bl31/interrupt_mgmt.h>
 #include <common/bl_common.h>
@@ -232,6 +233,77 @@
 }
 
 /*
+ * Prepare for ERET:
+ * - Set the ELR to the registered handler address
+ * - Set the SPSR register as described in the SDEI documentation and
+ *   the AArch64.TakeException() pseudocode function in
+ *   ARM DDI 0487F.c page J1-7635
+ */
+
+static void sdei_set_elr_spsr(sdei_entry_t *se, sdei_dispatch_context_t *disp_ctx)
+{
+	unsigned int client_el = sdei_client_el();
+	u_register_t sdei_spsr = SPSR_64(client_el, MODE_SP_ELX,
+					DISABLE_ALL_EXCEPTIONS);
+
+	u_register_t interrupted_pstate = disp_ctx->spsr_el3;
+
+	/* Check the SPAN bit in the client el SCTLR */
+	u_register_t client_el_sctlr;
+
+	if (client_el == MODE_EL2) {
+		client_el_sctlr = read_sctlr_el2();
+	} else {
+		client_el_sctlr = read_sctlr_el1();
+	}
+
+	/*
+	 * Check whether to force the PAN bit or use the value in the
+	 * interrupted EL according to the check described in
+	 * TakeException. Since the client can only be Non-Secure
+	 * EL2 or El1 some of the conditions in ElIsInHost() we know
+	 * will always be True.
+	 * When the client_el is EL2 we know that there will be a SPAN
+	 * bit in SCTLR_EL2 as we have already checked for the condition
+	 * HCR_EL2.E2H = 1 and HCR_EL2.TGE = 1
+	 */
+	u_register_t hcr_el2 = read_hcr();
+	bool el_is_in_host = is_armv8_1_vhe_present() &&
+			     (hcr_el2 & HCR_TGE_BIT) &&
+			     (hcr_el2 & HCR_E2H_BIT);
+
+	if (is_armv8_1_pan_present() &&
+	    ((client_el == MODE_EL1) ||
+		(client_el == MODE_EL2 && el_is_in_host)) &&
+	    ((client_el_sctlr & SCTLR_SPAN_BIT) == 0U)) {
+		sdei_spsr |=  SPSR_PAN_BIT;
+	} else {
+		sdei_spsr |= (interrupted_pstate & SPSR_PAN_BIT);
+	}
+
+	/* If SSBS is implemented, take the value from the client el SCTLR */
+	u_register_t ssbs_enabled = (read_id_aa64pfr1_el1()
+					>> ID_AA64PFR1_EL1_SSBS_SHIFT)
+					& ID_AA64PFR1_EL1_SSBS_MASK;
+	if (ssbs_enabled != SSBS_UNAVAILABLE) {
+		u_register_t  ssbs_bit = ((client_el_sctlr & SCTLR_DSSBS_BIT)
+						>> SCTLR_DSSBS_SHIFT)
+						<< SPSR_SSBS_SHIFT_AARCH64;
+		sdei_spsr |= ssbs_bit;
+	}
+
+	/* If MTE is implemented in the client el set the TCO bit */
+	if (get_armv8_5_mte_support() >= MTE_IMPLEMENTED_ELX) {
+		sdei_spsr |= SPSR_TCO_BIT_AARCH64;
+	}
+
+	/* Take the DIT field from the pstate of the interrupted el */
+	sdei_spsr |= (interrupted_pstate & SPSR_DIT_BIT);
+
+	cm_set_elr_spsr_el3(NON_SECURE, (uintptr_t) se->ep, sdei_spsr);
+}
+
+/*
  * Populate the Non-secure context so that the next ERET will dispatch to the
  * SDEI client.
  */
@@ -256,15 +328,8 @@
 	SMC_SET_GP(ctx, CTX_GPREG_X2, disp_ctx->elr_el3);
 	SMC_SET_GP(ctx, CTX_GPREG_X3, disp_ctx->spsr_el3);
 
-	/*
-	 * Prepare for ERET:
-	 *
-	 * - Set PC to the registered handler address
-	 * - Set SPSR to jump to client EL with exceptions masked
-	 */
-	cm_set_elr_spsr_el3(NON_SECURE, (uintptr_t) se->ep,
-			SPSR_64(sdei_client_el(), MODE_SP_ELX,
-				DISABLE_ALL_EXCEPTIONS));
+	/* Setup the elr and spsr register to prepare for ERET */
+	sdei_set_elr_spsr(se, disp_ctx);
 
 #if DYNAMIC_WORKAROUND_CVE_2018_3639
 	cve_2018_3639_t *tgt_cve_2018_3639;
@@ -571,15 +636,15 @@
 	if (!can_sdei_state_trans(se, DO_DISPATCH))
 		return -1;
 
-	/* Activate the priority corresponding to the event being dispatched */
-	ehf_activate_priority(sdei_event_priority(map));
-
 	/*
 	 * Prepare for NS dispatch by restoring the Non-secure context and
 	 * marking that as active.
 	 */
 	ns_ctx = restore_and_resume_ns_context();
 
+	/* Activate the priority corresponding to the event being dispatched */
+	ehf_activate_priority(sdei_event_priority(map));
+
 	/* Dispatch event synchronously */
 	setup_ns_dispatch(map, se, ns_ctx, &dispatch_jmp);
 	begin_sdei_synchronous_dispatch(&dispatch_jmp);
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
index dda127f..6de5feb 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -65,14 +65,6 @@
 }
 
 /*******************************************************************************
- * SPM Core entry point information get helper.
- ******************************************************************************/
-entry_point_info_t *spmd_spmc_ep_info_get(void)
-{
-	return spmc_ep_info;
-}
-
-/*******************************************************************************
  * SPM Core ID getter.
  ******************************************************************************/
 uint16_t spmd_spmc_id_get(void)
@@ -156,18 +148,11 @@
 {
 	spmd_spm_core_context_t *ctx = spmd_get_context();
 	uint64_t rc;
-	unsigned int linear_id = plat_my_core_pos();
-	unsigned int core_id;
 
 	VERBOSE("SPM Core init start.\n");
-	ctx->state = SPMC_STATE_ON_PENDING;
 
-	/* Set the SPMC context state on other CPUs to OFF */
-	for (core_id = 0U; core_id < PLATFORM_CORE_COUNT; core_id++) {
-		if (core_id != linear_id) {
-			spm_core_context[core_id].state = SPMC_STATE_OFF;
-		}
-	}
+	/* Primary boot core enters the SPMC for initialization. */
+	ctx->state = SPMC_STATE_ON_PENDING;
 
 	rc = spmd_spm_core_sync_entry(ctx);
 	if (rc != 0ULL) {
@@ -187,7 +172,8 @@
  ******************************************************************************/
 static int spmd_spmc_init(void *pm_addr)
 {
-	spmd_spm_core_context_t *spm_ctx = spmd_get_context();
+	cpu_context_t *cpu_ctx;
+	unsigned int core_id;
 	uint32_t ep_attr;
 	int rc;
 
@@ -280,13 +266,21 @@
 					     DISABLE_ALL_EXCEPTIONS);
 	}
 
-	/* Initialise SPM Core context with this entry point information */
-	cm_setup_context(&spm_ctx->cpu_ctx, spmc_ep_info);
+	/* Set an initial SPMC context state for all cores. */
+	for (core_id = 0U; core_id < PLATFORM_CORE_COUNT; core_id++) {
+		spm_core_context[core_id].state = SPMC_STATE_OFF;
 
-	/* Reuse PSCI affinity states to mark this SPMC context as off */
-	spm_ctx->state = AFF_STATE_OFF;
+		/* Setup an initial cpu context for the SPMC. */
+		cpu_ctx = &spm_core_context[core_id].cpu_ctx;
+		cm_setup_context(cpu_ctx, spmc_ep_info);
 
-	INFO("SPM Core setup done.\n");
+		/*
+		 * Pass the core linear ID to the SPMC through x4.
+		 * (TF-A implementation defined behavior helping
+		 * a legacy TOS migration to adopt FF-A).
+		 */
+		write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X4, core_id);
+	}
 
 	/* Register power management hooks with PSCI */
 	psci_register_spd_pm_hook(&spmd_pm);
@@ -294,6 +288,8 @@
 	/* Register init function for deferred init. */
 	bl31_register_bl32_init(&spmd_init);
 
+	INFO("SPM Core setup done.\n");
+
 	return 0;
 }
 
@@ -620,9 +616,19 @@
 	case FFA_RXTX_MAP_SMC64:
 	case FFA_RXTX_UNMAP:
 	case FFA_PARTITION_INFO_GET:
+#if MAKE_FFA_VERSION(1, 1) <= FFA_VERSION_COMPILED
+	case FFA_NOTIFICATION_BITMAP_CREATE:
+	case FFA_NOTIFICATION_BITMAP_DESTROY:
+	case FFA_NOTIFICATION_BIND:
+	case FFA_NOTIFICATION_UNBIND:
+	case FFA_NOTIFICATION_SET:
+	case FFA_NOTIFICATION_GET:
+	case FFA_NOTIFICATION_INFO_GET:
+	case FFA_NOTIFICATION_INFO_GET_SMC64:
+#endif
 		/*
-		 * Should not be allowed to forward FFA_PARTITION_INFO_GET
-		 * from Secure world to Normal world
+		 * Above calls should not be forwarded from Secure world to
+		 * Normal world.
 		 *
 		 * Fall through to forward the call to the other world
 		 */
diff --git a/services/std_svc/spmd/spmd_pm.c b/services/std_svc/spmd/spmd_pm.c
index 074609c..ac962ea 100644
--- a/services/std_svc/spmd/spmd_pm.c
+++ b/services/std_svc/spmd/spmd_pm.c
@@ -75,14 +75,14 @@
  ******************************************************************************/
 static void spmd_cpu_on_finish_handler(u_register_t unused)
 {
-	entry_point_info_t *spmc_ep_info = spmd_spmc_ep_info_get();
 	spmd_spm_core_context_t *ctx = spmd_get_context();
 	unsigned int linear_id = plat_my_core_pos();
+	el3_state_t *el3_state;
+	uintptr_t entry_point;
 	uint64_t rc;
 
 	assert(ctx != NULL);
 	assert(ctx->state != SPMC_STATE_ON);
-	assert(spmc_ep_info != NULL);
 
 	spin_lock(&g_spmd_pm.lock);
 
@@ -92,14 +92,20 @@
 	 * primary core address for booting secondary cores.
 	 */
 	if (g_spmd_pm.secondary_ep_locked == true) {
-		spmc_ep_info->pc = g_spmd_pm.secondary_ep;
+		/*
+		 * The CPU context has already been initialized at boot time
+		 * (in spmd_spmc_init by a call to cm_setup_context). Adjust
+		 * below the target core entry point based on the address
+		 * passed to by FFA_SECONDARY_EP_REGISTER.
+		 */
+		entry_point = g_spmd_pm.secondary_ep;
+		el3_state = get_el3state_ctx(&ctx->cpu_ctx);
+		write_ctx_reg(el3_state, CTX_ELR_EL3, entry_point);
 	}
 
 	spin_unlock(&g_spmd_pm.lock);
 
-	cm_setup_context(&ctx->cpu_ctx, spmc_ep_info);
-
-	/* Mark CPU as initiating ON operation */
+	/* Mark CPU as initiating ON operation. */
 	ctx->state = SPMC_STATE_ON_PENDING;
 
 	rc = spmd_spm_core_sync_entry(ctx);
diff --git a/services/std_svc/std_svc_setup.c b/services/std_svc/std_svc_setup.c
index 1917d0a..39db429 100644
--- a/services/std_svc/std_svc_setup.c
+++ b/services/std_svc/std_svc_setup.c
@@ -13,7 +13,9 @@
 #include <lib/pmf/pmf.h>
 #include <lib/psci/psci.h>
 #include <lib/runtime_instr.h>
+#include <services/gtsi_svc.h>
 #include <services/pci_svc.h>
+#include <services/rmmd_svc.h>
 #include <services/sdei.h>
 #include <services/spm_mm_svc.h>
 #include <services/spmd_svc.h>
@@ -158,6 +160,16 @@
 				flags);
 	}
 #endif
+#if ENABLE_RME
+	/*
+	 * Granule transition service interface functions (GTSI) are allocated
+	 * from the Std service range. Call the RMM dispatcher to handle calls.
+	 */
+	if (is_gtsi_fid(smc_fid)) {
+		return rmmd_gtsi_handler(smc_fid, x1, x2, x3, x4, cookie,
+						handle, flags);
+	}
+#endif
 
 #if SMC_PCI_SUPPORT
 	if (is_pci_fid(smc_fid)) {
diff --git a/tools/fiptool/tbbr_config.c b/tools/fiptool/tbbr_config.c
index c1e5217..4998bb2 100644
--- a/tools/fiptool/tbbr_config.c
+++ b/tools/fiptool/tbbr_config.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -67,6 +67,11 @@
 		.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
 		.cmdline_name = "nt-fw"
 	},
+	{
+		.name = "Realm Monitor Management Firmware",
+		.uuid = UUID_REALM_MONITOR_MGMT_FIRMWARE,
+		.cmdline_name = "rmm-fw"
+	},
 	/* Dynamic Configs */
 	{
 		.name = "FW_CONFIG",
diff --git a/tools/renesas/rcar_layout_create/sa6.c b/tools/renesas/rcar_layout_create/sa6.c
index fa828b9..8fafdad 100644
--- a/tools/renesas/rcar_layout_create/sa6.c
+++ b/tools/renesas/rcar_layout_create/sa6.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -96,7 +96,7 @@
 #define RCAR_BL32DST_ADDRESS		(0x44100000U)
 #define RCAR_BL32DST_ADDRESSH		(0x00000000U)
 /* Destination size for BL32 */
-#define RCAR_BL32DST_SIZE		(0x00040000U)
+#define RCAR_BL32DST_SIZE		(0x00080000U)
 /* Destination address for BL33 */
 #define RCAR_BL33DST_ADDRESS		(0x50000000U)
 #define RCAR_BL33DST_ADDRESSH		(0x00000000U)
diff --git a/tools/sptool/sp_mk_generator.py b/tools/sptool/sp_mk_generator.py
index a37e702..f983ff3 100755
--- a/tools/sptool/sp_mk_generator.py
+++ b/tools/sptool/sp_mk_generator.py
@@ -1,5 +1,5 @@
 #!/usr/bin/python3
-# Copyright (c) 2020, Arm Limited. All rights reserved.
+# Copyright (c) 2020-2021, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 
@@ -110,24 +110,36 @@
         Extract uuid from partition manifest
         """
         pm_file = open(dts)
-        uuid_key = "uuid"
-
         for line in pm_file:
-            if uuid_key in line:
-                uuid_hex = re.findall(r'\<(.+?)\>', line)[0];
+            if "uuid" in line:
+                # re.findall returns a list of string tuples.
+                # uuid_hex is the first item in this list representing the four
+                # uuid hex integers from the manifest uuid field. The heading
+                # '0x' of the hexadecimal representation is stripped out.
+                # e.g. uuid = <0x1e67b5b4 0xe14f904a 0x13fb1fb8 0xcbdae1da>;
+                # uuid_hex = ('1e67b5b4', 'e14f904a', '13fb1fb8', 'cbdae1da')
+                uuid_hex = re.findall(r'0x([0-9a-f]+) 0x([0-9a-f]+) 0x([0-9a-f]+) 0x([0-9a-f]+)', line)[0];
+
+        # uuid_hex is a list of four hex string values
+        if len(uuid_hex) != 4:
+            print("ERROR: malformed UUID")
+            exit(-1)
 
-        # PM has uuid in format 0xABC... 0x... 0x... 0x...
-        # Get rid of '0x' and spaces and convert to string of hex digits
-        uuid_hex = uuid_hex.replace('0x','').replace(' ','')
-        # make UUID from a string of hex digits
-        uuid_std = uuid.UUID(uuid_hex)
-        # convert UUID to a string of hex digits in standard form
-        uuid_std = str(uuid_std)
+        # The uuid field in SP manifest is the little endian representation
+        # mapped to arguments as described in SMCCC section 5.3.
+        # Convert each unsigned integer value to a big endian representation
+        # required by fiptool.
+        y=list(map(bytearray.fromhex, uuid_hex))
+        z=(int.from_bytes(y[0], byteorder='little', signed=False),
+        int.from_bytes(y[1], byteorder='little', signed=False),
+        int.from_bytes(y[2], byteorder='little', signed=False),
+        int.from_bytes(y[3], byteorder='little', signed=False))
+        uuid_std = uuid.UUID(f'{z[0]:04x}{z[1]:04x}{z[2]:04x}{z[3]:04x}')
 
         """
         Append FIP_ARGS
         """
-        out_file.write("FIP_ARGS += --blob uuid=" + uuid_std + ",file=" + dst + "\n")
+        out_file.write("FIP_ARGS += --blob uuid=" + str(uuid_std) + ",file=" + dst + "\n")
 
         """
         Append CRT_ARGS