Merge "plat: imx8m: Fix the rdc memory region slot's offset" into integration
diff --git a/Makefile b/Makefile
index 5167d2e..39e8a00 100644
--- a/Makefile
+++ b/Makefile
@@ -207,9 +207,10 @@
 CPP			=	$(CC) -E $(TF_CFLAGS_$(ARCH))
 PP			=	$(CC) -E $(TF_CFLAGS_$(ARCH))
 else ifneq ($(findstring clang,$(notdir $(CC))),)
+CLANG_CCDIR		=	$(if $(filter-out ./,$(dir $(CC))),$(dir $(CC)),)
 TF_CFLAGS_aarch32	=	$(target32-directive) $(march32-directive)
 TF_CFLAGS_aarch64	=	-target aarch64-elf $(march64-directive)
-LD			=	ld.lld
+LD			=	$(CLANG_CCDIR)ld.lld
 ifeq (, $(shell which $(LD)))
 $(error "No $(LD) in PATH, make sure it is installed or set LD to a different linker")
 endif
@@ -418,11 +419,20 @@
         $(warning "SPD and EL3_PAYLOAD_BASE are incompatible build options.")
         $(warning "The SPD and its BL32 companion will be present but ignored.")
 endif
-        # We expect to locate an spd.mk under the specified SPD directory
-        SPD_MAKE	:=	$(wildcard services/spd/${SPD}/${SPD}.mk)
+	ifeq (${SPD},spmd)
+		# SPMD is located in std_svc directory
+		SPD_DIR := std_svc
+	else
+		# All other SPDs in spd directory
+		SPD_DIR := spd
+	endif
+
+	# We expect to locate an spd.mk under the specified SPD directory
+	SPD_MAKE	:=	$(wildcard services/${SPD_DIR}/${SPD}/${SPD}.mk)
+
 
         ifeq (${SPD_MAKE},)
-                $(error Error: No services/spd/${SPD}/${SPD}.mk located)
+                $(error Error: No services/${SPD_DIR}/${SPD}/${SPD}.mk located)
         endif
         $(info Including ${SPD_MAKE})
         include ${SPD_MAKE}
@@ -611,6 +621,12 @@
     endif
 endif
 
+ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1)
+    ifeq (${ALLOW_RO_XLAT_TABLES}, 1)
+        $(error "ALLOW_RO_XLAT_TABLES requires translation tables library v2")
+    endif
+endif
+
 ################################################################################
 # Process platform overrideable behaviour
 ################################################################################
@@ -691,6 +707,7 @@
 # Variables for use with sptool
 SPTOOLPATH		?=	tools/sptool
 SPTOOL			?=	${SPTOOLPATH}/sptool${BIN_EXT}
+SP_MK_GEN		?=	${SPTOOLPATH}/sp_mk_generator.py
 
 # Variables for use with ROMLIB
 ROMLIBPATH		?=	lib/romlib
@@ -737,6 +754,7 @@
 # Build options checks
 ################################################################################
 
+$(eval $(call assert_boolean,ALLOW_RO_XLAT_TABLES))
 $(eval $(call assert_boolean,COLD_BOOT_SINGLE_CPU))
 $(eval $(call assert_boolean,CREATE_KEYS))
 $(eval $(call assert_boolean,CTX_INCLUDE_AARCH32_REGS))
@@ -777,6 +795,7 @@
 $(eval $(call assert_boolean,TRUSTED_BOARD_BOOT))
 $(eval $(call assert_boolean,USE_COHERENT_MEM))
 $(eval $(call assert_boolean,USE_DEBUGFS))
+$(eval $(call assert_boolean,USE_FCONF_BASED_IO))
 $(eval $(call assert_boolean,USE_ROMLIB))
 $(eval $(call assert_boolean,USE_TBBR_DEFS))
 $(eval $(call assert_boolean,WARMBOOT_ENABLE_DCACHE_EARLY))
@@ -803,6 +822,7 @@
 # platform to overwrite the default options
 ################################################################################
 
+$(eval $(call add_define,ALLOW_RO_XLAT_TABLES))
 $(eval $(call add_define,ARM_ARCH_MAJOR))
 $(eval $(call add_define,ARM_ARCH_MINOR))
 $(eval $(call add_define,COLD_BOOT_SINGLE_CPU))
@@ -845,6 +865,7 @@
 $(eval $(call add_define,TRUSTED_BOARD_BOOT))
 $(eval $(call add_define,USE_COHERENT_MEM))
 $(eval $(call add_define,USE_DEBUGFS))
+$(eval $(call add_define,USE_FCONF_BASED_IO))
 $(eval $(call add_define,USE_ROMLIB))
 $(eval $(call add_define,USE_TBBR_DEFS))
 $(eval $(call add_define,WARMBOOT_ENABLE_DCACHE_EARLY))
@@ -877,11 +898,22 @@
 $(eval $(call add_define,USE_ARM_LINK))
 endif
 
+# Generate and include sp_gen.mk if SPD is spmd and SP_LAYOUT_FILE is defined
+ifdef SP_LAYOUT_FILE
+ifeq (${SPD},spmd)
+        -include $(BUILD_PLAT)/sp_gen.mk
+        FIP_DEPS += sp
+        NEED_SP_PKG := yes
+else
+        $(error "SP_LAYOUT_FILE will be used only if SPD=spmd")
+endif
+endif
+
 ################################################################################
 # Build targets
 ################################################################################
 
-.PHONY:	all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool sptool fip fwu_fip certtool dtbs memmap doc
+.PHONY:	all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool sptool fip sp fwu_fip certtool dtbs memmap doc
 .SUFFIXES:
 
 all: msg_start
@@ -959,6 +991,17 @@
     $(eval $(call MAKE_DTBS,$(BUILD_PLAT)/fdts,$(FDT_SOURCES)))
 endif
 
+# Add Secure Partition packages
+ifeq (${NEED_SP_PKG},yes)
+$(BUILD_PLAT)/sp_gen.mk: ${SP_MK_GEN} ${SP_LAYOUT_FILE} | ${BUILD_PLAT}
+	${Q}${PYTHON} "$<" "$@" $(filter-out $<,$^) $(BUILD_PLAT)
+sp: $(SPTOOL) $(DTBS) $(BUILD_PLAT)/sp_gen.mk
+	${Q}$(SPTOOL) $(SPTOOL_ARGS)
+	@${ECHO_BLANK_LINE}
+	@echo "Built SP Images successfully"
+	@${ECHO_BLANK_LINE}
+endif
+
 locate-checkpatch:
 ifndef CHECKPATCH
 	$(error "Please set CHECKPATCH to point to the Linux checkpatch.pl file, eg: CHECKPATCH=../linux/scripts/checkpatch.pl")
@@ -1120,6 +1163,7 @@
 	@echo "  distclean      Remove all build artifacts for all platforms"
 	@echo "  certtool       Build the Certificate generation tool"
 	@echo "  fiptool        Build the Firmware Image Package (FIP) creation tool"
+	@echo "  sp             Build the Secure Partition Packages"
 	@echo "  sptool         Build the Secure Partition Package creation tool"
 	@echo "  dtbs           Build the Device Tree Blobs (if required for the platform)"
 	@echo "  memmap         Print the memory map of the built binaries"
diff --git a/bl1/aarch64/bl1_context_mgmt.c b/bl1/aarch64/bl1_context_mgmt.c
index 8be8830..210c358 100644
--- a/bl1/aarch64/bl1_context_mgmt.c
+++ b/bl1/aarch64/bl1_context_mgmt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -69,7 +69,7 @@
 	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))
+	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. */
diff --git a/bl1/bl1.ld.S b/bl1/bl1.ld.S
index 877af8e..b20859b 100644
--- a/bl1/bl1.ld.S
+++ b/bl1/bl1.ld.S
@@ -65,8 +65,13 @@
          * No need to pad out the .rodata section to a page boundary. Next is
          * the .data section, which can mapped in ROM with the same memory
          * attributes as the .rodata section.
+         *
+         * Pad out to 16 bytes though as .data section needs to be 16 byte
+         * aligned and lld does not align the LMA to the aligment specified
+         * on the .data section.
          */
         __RODATA_END__ = .;
+         . = ALIGN(16);
     } >ROM
 #else
     ro . : {
@@ -92,6 +97,13 @@
 
         *(.vectors)
         __RO_END__ = .;
+
+        /*
+         * Pad out to 16 bytes as .data section needs to be 16 byte aligned and
+         * lld does not align the LMA to the aligment specified on the .data
+         * section.
+         */
+         . = ALIGN(16);
     } >ROM
 #endif
 
diff --git a/bl1/bl1_fwu.c b/bl1/bl1_fwu.c
index 48f08d2..42a3ded 100644
--- a/bl1/bl1_fwu.c
+++ b/bl1/bl1_fwu.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -55,11 +55,11 @@
 /*******************************************************************************
  * Top level handler for servicing FWU SMCs.
  ******************************************************************************/
-register_t bl1_fwu_smc_handler(unsigned int smc_fid,
-			register_t x1,
-			register_t x2,
-			register_t x3,
-			register_t x4,
+u_register_t bl1_fwu_smc_handler(unsigned int smc_fid,
+			u_register_t x1,
+			u_register_t x2,
+			u_register_t x3,
+			u_register_t x4,
 			void *cookie,
 			void *handle,
 			unsigned int flags)
@@ -76,7 +76,7 @@
 		SMC_RET1(handle, bl1_fwu_image_execute(x1, &handle, flags));
 
 	case FWU_SMC_IMAGE_RESUME:
-		SMC_RET1(handle, bl1_fwu_image_resume(x1, &handle, flags));
+		SMC_RET1(handle, bl1_fwu_image_resume((register_t)x1, &handle, flags));
 
 	case FWU_SMC_SEC_IMAGE_DONE:
 		SMC_RET1(handle, bl1_fwu_sec_image_done(&handle, flags));
diff --git a/bl1/bl1_main.c b/bl1/bl1_main.c
index cd6fe7d..e11ead6 100644
--- a/bl1/bl1_main.c
+++ b/bl1/bl1_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -26,7 +26,7 @@
 
 /* BL1 Service UUID */
 DEFINE_SVC_UUID2(bl1_svc_uid,
-	0xd46739fd, 0xcb72, 0x9a4d, 0xb5, 0x75,
+	U(0xd46739fd), 0xcb72, 0x9a4d, 0xb5, 0x75,
 	0x67, 0x15, 0xd6, 0xf4, 0xbb, 0x4a);
 
 static void bl1_load_bl2(void);
@@ -172,7 +172,7 @@
 
 	/* Get the image descriptor */
 	image_desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
-	assert(image_desc);
+	assert(image_desc != NULL);
 
 	/* Get the image info */
 	image_info = &image_desc->image_info;
@@ -226,11 +226,11 @@
 /*******************************************************************************
  * Top level handler for servicing BL1 SMCs.
  ******************************************************************************/
-register_t bl1_smc_handler(unsigned int smc_fid,
-	register_t x1,
-	register_t x2,
-	register_t x3,
-	register_t x4,
+u_register_t bl1_smc_handler(unsigned int smc_fid,
+	u_register_t x1,
+	u_register_t x2,
+	u_register_t x3,
+	u_register_t x4,
 	void *cookie,
 	void *handle,
 	unsigned int flags)
@@ -269,14 +269,14 @@
  * BL1 SMC wrapper.  This function is only used in AArch32 mode to ensure ABI
  * compliance when invoking bl1_smc_handler.
  ******************************************************************************/
-register_t bl1_smc_wrapper(uint32_t smc_fid,
+u_register_t bl1_smc_wrapper(uint32_t smc_fid,
 	void *cookie,
 	void *handle,
 	unsigned int flags)
 {
-	register_t x1, x2, x3, x4;
+	u_register_t x1, x2, x3, x4;
 
-	assert(handle);
+	assert(handle != NULL);
 
 	get_smc_params_from_ctx(handle, x1, x2, x3, x4);
 	return bl1_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags);
diff --git a/bl1/bl1_private.h b/bl1/bl1_private.h
index 927c7b8..2cfeeea 100644
--- a/bl1/bl1_private.h
+++ b/bl1/bl1_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,11 +19,11 @@
 
 void bl1_prepare_next_image(unsigned int image_id);
 
-register_t bl1_fwu_smc_handler(unsigned int smc_fid,
-		register_t x1,
-		register_t x2,
-		register_t x3,
-		register_t x4,
+u_register_t bl1_fwu_smc_handler(unsigned int smc_fid,
+		u_register_t x1,
+		u_register_t x2,
+		u_register_t x3,
+		u_register_t x4,
 		void *cookie,
 		void *handle,
 		unsigned int flags);
diff --git a/bl2/bl2.ld.S b/bl2/bl2.ld.S
index 6230562..c1338e2 100644
--- a/bl2/bl2.ld.S
+++ b/bl2/bl2.ld.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -46,6 +46,11 @@
         __RODATA_START__ = .;
         *(SORT_BY_ALIGNMENT(.rodata*))
 
+       . = ALIGN(8);
+        __FCONF_POPULATOR_START__ = .;
+        KEEP(*(.fconf_populator))
+        __FCONF_POPULATOR_END__ = .;
+
         /* Ensure 8-byte alignment for descriptors and ensure inclusion */
         . = ALIGN(8);
         __PARSER_LIB_DESCS_START__ = .;
@@ -62,6 +67,11 @@
         *(SORT_BY_ALIGNMENT(.text*))
         *(SORT_BY_ALIGNMENT(.rodata*))
 
+	. = ALIGN(8);
+         __FCONF_POPULATOR_START__ = .;
+         KEEP(*(.fconf_populator))
+         __FCONF_POPULATOR_END__ = .;
+
         /* Ensure 8-byte alignment for descriptors and ensure inclusion */
         . = ALIGN(8);
         __PARSER_LIB_DESCS_START__ = .;
diff --git a/bl2/bl2_image_load_v2.c b/bl2/bl2_image_load_v2.c
index 1fbdbab..81d4b2b 100644
--- a/bl2/bl2_image_load_v2.c
+++ b/bl2/bl2_image_load_v2.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -35,13 +35,13 @@
 	 * Get information about the images to load.
 	 */
 	bl2_load_info = plat_get_bl_image_load_info();
-	assert(bl2_load_info);
-	assert(bl2_load_info->head);
+	assert(bl2_load_info != NULL);
+	assert(bl2_load_info->head != NULL);
 	assert(bl2_load_info->h.type == PARAM_BL_LOAD_INFO);
 	assert(bl2_load_info->h.version >= VERSION_2);
 	bl2_node_info = bl2_load_info->head;
 
-	while (bl2_node_info) {
+	while (bl2_node_info != NULL) {
 		/*
 		 * Perform platform setup before loading the image,
 		 * if indicated in the image attributes AND if NOT
@@ -91,11 +91,11 @@
 	 * Get information to pass to the next image.
 	 */
 	bl2_to_next_bl_params = plat_get_next_bl_params();
-	assert(bl2_to_next_bl_params);
-	assert(bl2_to_next_bl_params->head);
+	assert(bl2_to_next_bl_params != NULL);
+	assert(bl2_to_next_bl_params->head != NULL);
 	assert(bl2_to_next_bl_params->h.type == PARAM_BL_PARAMS);
 	assert(bl2_to_next_bl_params->h.version >= VERSION_2);
-	assert(bl2_to_next_bl_params->head->ep_info);
+	assert(bl2_to_next_bl_params->head->ep_info != NULL);
 
 	/* Populate arg0 for the next BL image if not already provided */
 	if (bl2_to_next_bl_params->head->ep_info->args.arg0 == (u_register_t)0)
diff --git a/bl31/aarch64/crash_reporting.S b/bl31/aarch64/crash_reporting.S
index f2c1296..97db2a1 100644
--- a/bl31/aarch64/crash_reporting.S
+++ b/bl31/aarch64/crash_reporting.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -244,6 +244,11 @@
 	mrs	x0, tpidr_el3
 	/* report x30 first from the crash buf */
 	ldr	x4, [x0, #REGSZ * 7]
+
+#if ENABLE_PAUTH
+	/* Demangle address */
+	xpaci	x4
+#endif
 	bl	asm_print_hex
 	bl	asm_print_newline
 	/* Load the crash buf address */
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index 58909e8..0948e94 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -31,6 +31,7 @@
 				services/arm_arch_svc/arm_arch_svc_setup.c	\
 				services/std_svc/std_svc_setup.c		\
 				${PSCI_LIB_SOURCES}				\
+				${SPMD_SOURCES}					\
 				${SPM_SOURCES}
 
 
diff --git a/common/backtrace/backtrace.c b/common/backtrace/backtrace.c
index 506d4a4..907117f 100644
--- a/common/backtrace/backtrace.c
+++ b/common/backtrace/backtrace.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -37,47 +37,6 @@
 	uintptr_t return_addr;
 };
 
-/*
- * Strip the Pointer Authentication Code (PAC) from the address to retrieve the
- * original one.
- *
- * The PAC field is stored on the high bits of the address and defined as:
- * - PAC field = Xn[54:bottom_PAC_bit], when address tagging is used.
- * - PAC field = Xn[63:56, 54:bottom_PAC_bit], without address tagging.
- *
- * With bottom_PAC_bit = 64 - TCR_ELx.TnSZ
- */
-#if ENABLE_PAUTH
-static uintptr_t demangle_address(uintptr_t addr)
-{
-	unsigned int el, t0sz, bottom_pac_bit;
-	uint64_t tcr, pac_mask;
-
-	/*
-	 * Different virtual address space size can be defined for each EL.
-	 * Ensure that we use the proper one by reading the corresponding
-	 * TCR_ELx register.
-	 */
-	el = get_current_el();
-
-	if (el == 3U) {
-		tcr = read_tcr_el3();
-	} else if (el == 2U) {
-		tcr = read_tcr_el2();
-	} else {
-		tcr = read_tcr_el1();
-	}
-
-	/* T0SZ = TCR_ELx[5:0] */
-	t0sz = tcr & 0x1f;
-	bottom_pac_bit = 64 - t0sz;
-	pac_mask = (1ULL << bottom_pac_bit) - 1;
-
-	/* demangle the address with the computed mask */
-	return (addr & pac_mask);
-}
-#endif /* ENABLE_PAUTH */
-
 static const char *get_el_str(unsigned int el)
 {
 	if (el == 3U) {
@@ -104,9 +63,8 @@
 	 * stack contains a PAC. It must be stripped to retrieve the return
 	 * address.
 	 */
-	addr = demangle_address(addr);
+	xpaci(addr);
 #endif
-
 	if (el == 3U) {
 		ats1e3r(addr);
 	} else if (el == 2U) {
@@ -257,9 +215,8 @@
 		 * the stack contains a PAC. It must be stripped to retrieve the
 		 * return address.
 		 */
-		call_site = demangle_address(call_site);
+		xpaci(call_site);
 #endif
-
 		/*
 		 * If the address is invalid it means that the frame record is
 		 * probably corrupted.
diff --git a/common/bl_common.c b/common/bl_common.c
index b74225b..2fcb538 100644
--- a/common/bl_common.c
+++ b/common/bl_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
diff --git a/common/desc_image_load.c b/common/desc_image_load.c
index f2e8f60..0769226 100644
--- a/common/desc_image_load.c
+++ b/common/desc_image_load.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -215,6 +215,9 @@
 	bl_params_node_t *params_node;
 	unsigned int fw_config_id;
 	uintptr_t hw_config_base = 0, fw_config_base;
+#if defined(SPD_spmd)
+	uint32_t fw_config_size = 0;
+#endif
 	bl_mem_params_node_t *mem_params;
 
 	assert(bl2_to_next_bl_params != NULL);
@@ -249,10 +252,14 @@
 
 		if (fw_config_id != INVALID_IMAGE_ID) {
 			mem_params = get_bl_mem_params_node(fw_config_id);
-			if (mem_params != NULL)
+			if (mem_params != NULL) {
 				fw_config_base = mem_params->image_info.image_base;
+#if defined(SPD_spmd)
+				fw_config_size =
+					mem_params->image_info.image_size;
+#endif
+			}
 		}
-
 		/*
 		 * Pass hw and tb_fw config addresses to next images. NOTE - for
 		 * EL3 runtime images (BL31 for AArch64 and BL32 for AArch32),
@@ -273,6 +280,11 @@
 			if (params_node->ep_info->args.arg1 == 0U)
 				params_node->ep_info->args.arg1 =
 								hw_config_base;
+#if defined(SPD_spmd)
+			if (params_node->ep_info->args.arg2 == 0U)
+				params_node->ep_info->args.arg2 =
+								fw_config_size;
+#endif
 		}
 	}
 }
@@ -301,9 +313,9 @@
 			image_info_t *bl33_image_info;
 		} *v1 = (void *)(uintptr_t)param;
 		assert(v1->h.type == PARAM_BL31);
-		if (bl32_ep_info_out)
+		if (bl32_ep_info_out != NULL)
 			*bl32_ep_info_out = *v1->bl32_ep_info;
-		if (bl33_ep_info_out)
+		if (bl33_ep_info_out != NULL)
 			*bl33_ep_info_out = *v1->bl33_ep_info;
 		return;
 	}
@@ -311,12 +323,12 @@
 
 	assert(v2->h.version == PARAM_VERSION_2);
 	assert(v2->h.type == PARAM_BL_PARAMS);
-	for (node = v2->head; node; node = node->next_params_info) {
+	for (node = v2->head; node != NULL; node = node->next_params_info) {
 		if (node->image_id == BL32_IMAGE_ID)
-			if (bl32_ep_info_out)
+			if (bl32_ep_info_out != NULL)
 				*bl32_ep_info_out = *node->ep_info;
 		if (node->image_id == BL33_IMAGE_ID)
-			if (bl33_ep_info_out)
+			if (bl33_ep_info_out != NULL)
 				*bl33_ep_info_out = *node->ep_info;
 	}
 }
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index d9d7f84..802dafc 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -64,6 +64,14 @@
 :F: drivers/amlogic/g12a
 :F: plat/amlogic/g12a/
 
+Amlogic Meson A113D (AXG) platform port
+-----------------------------------------
+:M: Carlo Caione <ccaione@baylibre.com>
+:G: `carlocaione`_
+:F: docs/plat/meson-axg.rst
+:F: drivers/amlogic/axg
+:F: plat/amlogic/axg/
+
 Armv7-A architecture port
 -------------------------
 :M: Etienne Carriere <etienne.carriere@linaro.org>
diff --git a/docs/components/debugfs-design.rst b/docs/components/debugfs-design.rst
index 06916f3..8ce1ba6 100644
--- a/docs/components/debugfs-design.rst
+++ b/docs/components/debugfs-design.rst
@@ -15,8 +15,9 @@
 ------------------
 
 The core functionality lies in a virtual file system based on a 9p file server
-interface (`Notes on the Plan 9 Kernel Source`_). The implementation permits
-exposing virtual files, firmware drivers, and file blobs.
+interface (`Notes on the Plan 9 Kernel Source`_ and
+`Linux 9p remote filesystem protocol`_).
+The implementation permits exposing virtual files, firmware drivers, and file blobs.
 
 Namespace
 ~~~~~~~~~
@@ -77,10 +78,10 @@
 -------------
 
 The communication with the 9p layer in BL31 is made through an SMC conduit
-(`SMC Calling Convention PDD`_), using a specific SiP Function Id. An NS shared
-buffer is used to pass path string parameters, or e.g. to exchange data on a
-read operation. Refer to `ARM SiP Services`_ for a description of the SMC
-interface.
+(`SMC Calling Convention PDD`_), using a specific SiP Function Id. An NS
+shared buffer is used to pass path string parameters, or e.g. to exchange
+data on a read operation. Refer to `ARM SiP Services`_ for a description
+of the SMC interface.
 
 Security considerations
 -----------------------
@@ -114,17 +115,9 @@
 - a Linux kernel driver running at NS-EL1
 - a Linux userspace application through the kernel driver
 
-References
-----------
-
-.. [#] `SMC Calling Convention PDD`_
-.. [#] `Notes on the Plan 9 Kernel Source`_
-.. [#] `Linux 9p remote filesystem protocol`_
-.. [#] `ARM SiP Services`_
-
 --------------
 
-*Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.*
 
 .. _SMC Calling Convention PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/
 .. _Notes on the Plan 9 Kernel Source: http://lsub.org/who/nemo/9.pdf
diff --git a/docs/components/fconf.rst b/docs/components/fconf.rst
new file mode 100644
index 0000000..cec3ceb
--- /dev/null
+++ b/docs/components/fconf.rst
@@ -0,0 +1,85 @@
+Firmware Configuration Framework
+================================
+
+This document provides an overview of the |FCONF| framework.
+
+Introduction
+~~~~~~~~~~~~
+
+The Firmware CONfiguration Framework (|FCONF|) is an abstraction layer for
+platform specific data, allowing a "property" to be queried and a value
+retrieved without the requesting entity knowing what backing store is being used
+to hold the data.
+
+It is used to bridge new and old ways of providing platform-specific data.
+Today, information like the Chain of Trust is held within several, nested
+platform-defined tables. In the future, it may be provided as part of a device
+blob, along with the rest of the information about images to load.
+Introducing this abstraction layer will make migration easier and will preserve
+functionality for platforms that cannot / don't want to use device tree.
+
+Accessing properties
+~~~~~~~~~~~~~~~~~~~~
+
+Properties defined in the |FCONF| are grouped around namespaces and
+sub-namespaces: a.b.property.
+Examples namespace can be:
+
+- (|TBBR|) Chain of Trust data: tbbr.cot.trusted_boot_fw_cert
+- (|TBBR|) dynamic configuration info: tbbr.dyn_config.disable_auth
+- Arm io policies: arm.io_policies.bl2_image
+
+Properties can be accessed with the ``FCONF_GET_PROPERTY(a,b,property)`` macro.
+
+Defining properties
+~~~~~~~~~~~~~~~~~~~
+
+Properties composing the |FCONF| have to be stored in C structures. If another
+backing store is wanted to be used, the platform has to provide a ``populate()``
+function to fill the corresponding C structure.
+
+The ``populate()`` function must be registered to the |FCONF| framework with
+the ``FCONF_REGISTER_POPULATOR()`` macro. This ensures that the function would
+be called inside the generic ``fconf_populate()`` function during
+initialization.
+
+::
+
+    int fconf_populate_tbbr_dyn_config(uintptr_t config)
+    {
+        /* read dtb and fill tbbr_dyn_config struct */
+    }
+
+    FCONF_REGISTER_POPULATOR(fconf_populate_tbbr_dyn_config);
+
+Then, a wrapper has to be provided to match the ``FCONF_GET_PROPERTY()`` macro:
+
+::
+
+    /* generic getter */
+    #define FCONF_GET_PROPERTY(a,b,property)	a##__##b##_getter(property)
+
+    /* my specific getter */
+    #define tbbr__dyn_config_getter(id)	tbbr_dyn_config.id
+
+This second level wrapper can be used to remap the ``FCONF_GET_PROPERTY()`` to
+anything appropriate: structure, array, function, etc..
+
+Loading the property device tree
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``fconf_load_config()`` must be called to load the device tree containing
+the properties' values. This must be done after the io layer is initialized, as
+the |DTB| is stored on an external device (FIP).
+
+.. uml:: ../resources/diagrams/plantuml/fconf_bl1_load_config.puml
+
+Populating the properties
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Once a valid device tree is available, the ``fconf_populate(config)`` function
+can be used to fill the C data structure with the data from the config |DTB|.
+This function will call all the ``populate()`` callbacks which have been
+registered with ``FCONF_REGISTER_POPULATOR()``.
+
+.. uml:: ../resources/diagrams/plantuml/fconf_bl2_populate.puml
diff --git a/docs/components/index.rst b/docs/components/index.rst
index f1904c0..ae78b2b 100644
--- a/docs/components/index.rst
+++ b/docs/components/index.rst
@@ -8,7 +8,9 @@
 
    spd/index
    arm-sip-service
+   debugfs-design
    exception-handling
+   fconf
    firmware-update
    platform-interrupt-controller-API
    ras
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index f3096b4..258f73d 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -324,6 +324,13 @@
    as recommended in section "4.7 Non-Temporal Loads/Stores" of the
    `Cortex-A57 Software Optimization Guide`_.
 
+- ''A57_ENABLE_NON_CACHEABLE_LOAD_FWD'': This flag enables non-cacheable
+   streaming enhancement feature for Cortex-A57 CPUs. Platforms can set
+   this bit only if their memory system meets the requirement that cache
+   line fill requests from the Cortex-A57 processor are atomic. Each
+   Cortex-A57 based platform must make its own decision on whether to use
+   the optimization. This flag is disabled by default.
+
 -  ``NEOVERSE_N1_EXTERNAL_LLC``: This flag indicates that an external last
    level cache(LLC) is present in the system, and that the DataSource field
    on the master CHI interface indicates when data is returned from the LLC.
diff --git a/docs/design/firmware-design.rst b/docs/design/firmware-design.rst
index 5fc1335..d0d6ef6 100644
--- a/docs/design/firmware-design.rst
+++ b/docs/design/firmware-design.rst
@@ -2696,13 +2696,13 @@
 
 --------------
 
-*Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.*
 
 .. _Power State Coordination Interface PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf
 .. _SMCCC: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf
 .. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf
 .. _Power State Coordination Interface PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf
-.. _Arm ARM: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0487a.e/index.html
+.. _Arm ARM: https://developer.arm.com/docs/ddi0487/latest
 .. _SMC Calling Convention PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf
 .. _Trusted Board Boot Requirements CLIENT (TBBR-CLIENT) Armv8-A (ARM DEN0006D): https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a
 
diff --git a/docs/design/trusted-board-boot-build.rst b/docs/design/trusted-board-boot-build.rst
index 2025243..f5c8bc9 100644
--- a/docs/design/trusted-board-boot-build.rst
+++ b/docs/design/trusted-board-boot-build.rst
@@ -33,7 +33,7 @@
    -  ``GENERATE_COT=1``
 
    In the case of Arm platforms, the location of the ROTPK hash must also be
-   specified at build time. Two locations are currently supported (see
+   specified at build time. The following locations are currently supported (see
    ``ARM_ROTPK_LOCATION`` build option):
 
    -  ``ARM_ROTPK_LOCATION=regs``: the ROTPK hash is obtained from the Trusted
@@ -41,17 +41,16 @@
       registers are read-only. On FVP Base and Cortex models, the registers
       are read-only, but the value can be specified using the command line
       option ``bp.trusted_key_storage.public_key`` when launching the model.
-      On both Juno and FVP models, the default value corresponds to an
-      ECDSA-SECP256R1 public key hash, whose private part is not currently
-      available.
+      On Juno board, the default value corresponds to an ECDSA-SECP256R1 public
+      key hash, whose private part is not currently available.
 
-   -  ``ARM_ROTPK_LOCATION=devel_rsa``: use the ROTPK hash that is hardcoded
-      in the Arm platform port. The private/public RSA key pair may be
-      found in ``plat/arm/board/common/rotpk``.
+   -  ``ARM_ROTPK_LOCATION=devel_rsa``: use the default hash located in
+      plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin. Enforce generation
+      of the new hash if ROT_KEY is specified.
 
-   -  ``ARM_ROTPK_LOCATION=devel_ecdsa``: use the ROTPK hash that is hardcoded
-      in the Arm platform port. The private/public ECDSA key pair may be
-      found in ``plat/arm/board/common/rotpk``.
+   -  ``ARM_ROTPK_LOCATION=devel_ecdsa``: use the default hash located in
+      plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin. Enforce generation
+      of the new hash if ROT_KEY is specified.
 
    Example of command line using RSA development keys:
 
@@ -108,7 +107,7 @@
 
 --------------
 
-*Copyright (c) 2019, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
 
 .. _mbed TLS Repository: https://github.com/ARMmbed/mbedtls.git
 .. _mbed TLS Security Center: https://tls.mbed.org/security
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index e9747af..7ee34c9 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -189,7 +189,7 @@
    that is only required for the assertion and does not fit in the assertion
    itself.
 
--  ``ENABLE_BACKTRACE``: This option controls whether to enables backtrace
+-  ``ENABLE_BACKTRACE``: This option controls whether to enable backtrace
    dumps or not. It is supported in both AArch64 and AArch32. However, in
    AArch32 the format of the frame records are not defined in the AAPCS and they
    are defined by the implementation. This implementation of backtrace only
@@ -468,7 +468,8 @@
    entrypoint) or 1 (CPU reset to SP_MIN entrypoint). The default value is 0.
 
 -  ``ROT_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the
-   file that contains the ROT private key in PEM format. If ``SAVE_KEYS=1``, this
+   file that contains the ROT private key in PEM format and enforces public key
+   hash generation. If ``SAVE_KEYS=1``, this
    file name will be used to save the key.
 
 -  ``SAVE_KEYS``: This option is used when ``GENERATE_COT=1``. It tells the
@@ -521,6 +522,11 @@
 -  ``SPM_MM`` : Boolean option to enable the Management Mode (MM)-based Secure
    Partition Manager (SPM) implementation. The default value is ``0``.
 
+-  ``SP_LAYOUT_FILE``: Platform provided path to JSON file containing the
+   description of secure partitions. Build system will parse this file and
+   package all secure partition blobs in FIP. This file not necessarily be
+   part of TF-A tree. Only avaialbe when ``SPD=spmd``.
+
 -  ``SP_MIN_WITH_SECURE_FIQ``: Boolean flag to indicate the SP_MIN handles
    secure interrupts (caught through the FIQ line). Platforms can enable
    this directive if they need to handle such interruption. When enabled,
@@ -577,6 +583,11 @@
    exposing a virtual filesystem interface through BL31 as a SiP SMC function.
    Default is 0.
 
+-  ``USE_FCONF_BASED_IO``: This flag determines whether to use IO based on the
+   firmware configuration framework. This allows moving the io_policies into a
+   configuration device tree, instead of static structure in the code base.
+
+
 -  ``USE_ROMLIB``: This flag determines whether library at ROM will be used.
    This feature creates a library of functions to be placed in ROM and thus
    reduces SRAM usage. Refer to :ref:`Library at ROM` for further details. Default
diff --git a/docs/global_substitutions.txt b/docs/global_substitutions.txt
index 491b160..4dda1dc 100644
--- a/docs/global_substitutions.txt
+++ b/docs/global_substitutions.txt
@@ -6,11 +6,13 @@
 .. |COT| replace:: :term:`COT`
 .. |CSS| replace:: :term:`CSS`
 .. |CVE| replace:: :term:`CVE`
+.. |DTB| replace:: :term:`DTB`
 .. |DS-5| replace:: :term:`DS-5`
 .. |DSU| replace:: :term:`DSU`
 .. |DT| replace:: :term:`DT`
 .. |EL| replace:: :term:`EL`
 .. |EHF| replace:: :term:`EHF`
+.. |FCONF| replace:: :term:`FCONF`
 .. |FDT| replace:: :term:`FDT`
 .. |FIP| replace:: :term:`FIP`
 .. |FVP| replace:: :term:`FVP`
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 2f19df5..3da30b0 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -42,12 +42,18 @@
    DT
       Device Tree
 
+   DTB
+      Device Tree Blob
+
    EL
       Exception Level
 
    EHF
       Exception Handling Framework
 
+   FCONF
+      Firmware Configuration Framework
+
    FDT
       Flattened Device Tree
 
diff --git a/docs/perf/index.rst b/docs/perf/index.rst
index 0f49b48..1482b80 100644
--- a/docs/perf/index.rst
+++ b/docs/perf/index.rst
@@ -8,7 +8,8 @@
 
    psci-performance-juno
    tsp
+   performance-monitoring-unit
 
 --------------
 
-*Copyright (c) 2019, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/docs/perf/performance-monitoring-unit.rst b/docs/perf/performance-monitoring-unit.rst
new file mode 100644
index 0000000..5dd1af5
--- /dev/null
+++ b/docs/perf/performance-monitoring-unit.rst
@@ -0,0 +1,158 @@
+Performance Monitoring Unit
+===========================
+
+The Performance Monitoring Unit (PMU) allows recording of architectural and
+microarchitectural events for profiling purposes.
+
+This document gives an overview of the PMU counter configuration to assist with
+implementation and to complement the PMU security guidelines given in the
+:ref:`Secure Development Guidelines` document.
+
+.. note::
+   This section applies to Armv8-A implementations which have version 3
+   of the Performance Monitors Extension (PMUv3).
+
+PMU Counters
+------------
+
+The PMU makes 32 counters available at all privilege levels:
+
+-  31 programmable event counters: ``PMEVCNTR<n>``, where ``n`` is ``0`` to
+   ``30``.
+-  A dedicated cycle counter: ``PMCCNTR``.
+
+Architectural mappings
+~~~~~~~~~~~~~~~~~~~~~~
+
++--------------+---------+----------------------------+
+| Counters     | State   | System Register Name       |
++==============+=========+============================+
+|              | AArch64 | ``PMEVCNTR<n>_EL0[63*:0]`` |
+| Programmable +---------+----------------------------+
+|              | AArch32 | ``PMEVCNTR<n>[31:0]``      |
++--------------+---------+----------------------------+
+|              | AArch64 | ``PMCCNTR_EL0[63:0]``      |
+| Cycle        +---------+----------------------------+
+|              | AArch32 | ``PMCCNTR[63:0]``          |
++--------------+---------+----------------------------+
+
+.. note::
+   Bits [63:32] are only available if ARMv8.5-PMU is implemented. Refer to the
+   `Arm ARM`_ for a detailed description of ARMv8.5-PMU features.
+
+Configuring the PMU for counting events
+---------------------------------------
+
+Each programmable counter has an associated register, ``PMEVTYPER<n>`` which
+configures it. The cycle counter has the ``PMCCFILTR_EL0`` register, which has
+an identical function and bit field layout as ``PMEVTYPER<n>``. In addition,
+the counters are enabled (permitted to increment) via the ``PMCNTENSET`` and
+``PMCR`` registers. These can be accessed at all privilege levels.
+
+Architectural mappings
+~~~~~~~~~~~~~~~~~~~~~~
+
++-----------------------------+------------------------+
+| AArch64                     | AArch32                |
++=============================+========================+
+| ``PMEVTYPER<n>_EL0[63*:0]`` | ``PMEVTYPER<n>[31:0]`` |
++-----------------------------+------------------------+
+| ``PMCCFILTR_EL0[63*:0]``    | ``PMCCFILTR[31:0]``    |
++-----------------------------+------------------------+
+| ``PMCNTENSET_EL0[63*:0]``   | ``PMCNTENSET[31:0]``   |
++-----------------------------+------------------------+
+| ``PMCR_EL0[63*:0]``         | ``PMCR[31:0]``         |
++-----------------------------+------------------------+
+
+.. note::
+   Bits [63:32] are reserved.
+
+Relevant register fields
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+For ``PMEVTYPER<n>_EL0``/``PMEVTYPER<n>`` and ``PMCCFILTR_EL0/PMCCFILTR``, the
+most important fields are:
+
+-  ``P``:
+
+   -  Bit 31.
+   -  If set to ``0``, will increment the associated ``PMEVCNTR<n>`` at EL1.
+
+-  ``NSK``:
+
+   -  Bit 29.
+   -  If equal to the ``P`` bit it enables the associated ``PMEVCNTR<n>`` at
+      Non-secure EL1.
+   -  Reserved if EL3 not implemented.
+
+-  ``NSH``:
+
+   -  Bit 27.
+   -  If set to ``1``, will increment the associated ``PMEVCNTR<n>`` at EL2.
+   -  Reserved if EL2 not implemented.
+
+-  ``SH``:
+
+   -  Bit 24.
+   -  If different to the ``NSH`` bit it enables the associated ``PMEVCNTR<n>``
+      at Secure EL2.
+   -  Reserved if Secure EL2 not implemented.
+
+-  ``M``:
+
+   -  Bit 26.
+   -  If equal to the ``P`` bit it enables the associated ``PMEVCNTR<n>`` at
+      EL3.
+
+-  ``evtCount[15:10]``:
+
+   -  Extension to ``evtCount[9:0]``. Reserved unless ARMv8.1-PMU implemented.
+
+-  ``evtCount[9:0]``:
+
+   -  The event number that the associated ``PMEVCNTR<n>`` will count.
+
+For ``PMCNTENSET_EL0``/``PMCNTENSET``, the most important fields are:
+
+-  ``P[30:0]``:
+
+   -  Setting bit ``P[n]`` to ``1`` enables counter ``PMEVCNTR<n>``.
+   -  The effects of ``PMEVTYPER<n>`` are applied on top of this.
+      In other words, the counter will not increment at any privilege level or
+      security state unless it is enabled here.
+
+-  ``C``:
+
+   -  Bit 31.
+   -  If set to ``1`` enables the cycle counter ``PMCCNTR``.
+
+For ``PMCR``/``PMCR_EL0``, the most important fields are:
+
+-  ``DP``:
+
+   -  Bit 5.
+   -  If set to ``1`` it disables the cycle counter ``PMCCNTR`` where event
+      counting (by ``PMEVCNTR<n>``) is prohibited (e.g. EL2 and the Secure
+      world).
+   -  If set to ``0``, ``PMCCNTR`` will not be affected by this bit and
+      therefore will be able to count where the programmable counters are
+      prohibited.
+
+-  ``E``:
+
+   -  Bit 0.
+   -  Enables/disables counting altogether.
+   -  The effects of ``PMCNTENSET`` and ``PMCR.DP`` are applied on top of this.
+      In other words, if this bit is ``0`` then no counters will increment
+      regardless of how the other PMU system registers or bit fields are
+      configured.
+
+.. rubric:: References
+
+-  `Arm ARM`_
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.*
+
+.. _Arm ARM: https://developer.arm.com/docs/ddi0487/latest
diff --git a/docs/plat/arm/arm-build-options.rst b/docs/plat/arm/arm-build-options.rst
index d24ad23..9622de6 100644
--- a/docs/plat/arm/arm-build-options.rst
+++ b/docs/plat/arm/arm-build-options.rst
@@ -57,8 +57,7 @@
    ``ARM_ROTPK_LOCATION`` are:
 
    -  ``regs`` : return the ROTPK hash stored in the Trusted root-key storage
-      registers. The private key corresponding to this ROTPK hash is not
-      currently available.
+      registers.
    -  ``devel_rsa`` : return a development public key hash embedded in the BL1
       and BL2 binaries. This hash has been obtained from the RSA public key
       ``arm_rotpk_rsa.der``, located in ``plat/arm/board/common/rotpk``. To use
@@ -70,6 +69,12 @@
       use this option, ``arm_rotprivk_ecdsa.pem`` must be specified as
       ``ROT_KEY`` when creating the certificates.
 
+-  ``ARM_ROTPK_HASH``: used when ``ARM_ROTPK_LOCATION=devel_*``. Specifies the
+   location of the ROTPK hash. Not expected to be a build option. This defaults to
+   ``plat/arm/board/common/rotpk/*_sha256.bin`` depending on the specified algorithm.
+   Providing ``ROT_KEY`` enforces generation of the hash from the ``ROT_KEY`` and
+   overwrites the default hash file.
+
 -  ``ARM_TSP_RAM_LOCATION``: location of the TSP binary. Options:
 
    -  ``tsram`` : Trusted SRAM (default option when TBB is not enabled)
@@ -109,6 +114,11 @@
    management operations and for SCP RAM Firmware transfer. If this option
    is set to 1, then SCMI/SDS drivers will be used. Default is 0.
 
+ - ``CSS_SGI_CHIP_COUNT``: Configures the number of chips on a SGI/RD platform
+   which supports multi-chip operation. If ``CSS_SGI_CHIP_COUNT`` is set to any
+   valid value greater than 1, the platform code performs required configuration
+   to support multi-chip operation.
+
 --------------
 
-*Copyright (c) 2019, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/docs/plat/arm/fvp/index.rst b/docs/plat/arm/fvp/index.rst
index 37010e1..40e9661 100644
--- a/docs/plat/arm/fvp/index.rst
+++ b/docs/plat/arm/fvp/index.rst
@@ -277,15 +277,15 @@
     -C cluster0.NUM_CORES=4                                     \
     -C cluster1.NUM_CORES=4                                     \
     -C cache_state_modelled=1                                   \
-    -C cluster0.cpu0.RVBAR=0x04020000                           \
-    -C cluster0.cpu1.RVBAR=0x04020000                           \
-    -C cluster0.cpu2.RVBAR=0x04020000                           \
-    -C cluster0.cpu3.RVBAR=0x04020000                           \
-    -C cluster1.cpu0.RVBAR=0x04020000                           \
-    -C cluster1.cpu1.RVBAR=0x04020000                           \
-    -C cluster1.cpu2.RVBAR=0x04020000                           \
-    -C cluster1.cpu3.RVBAR=0x04020000                           \
-    --data cluster0.cpu0="<path-to>/bl31.bin"@0x04020000        \
+    -C cluster0.cpu0.RVBAR=0x04001000                           \
+    -C cluster0.cpu1.RVBAR=0x04001000                           \
+    -C cluster0.cpu2.RVBAR=0x04001000                           \
+    -C cluster0.cpu3.RVBAR=0x04001000                           \
+    -C cluster1.cpu0.RVBAR=0x04001000                           \
+    -C cluster1.cpu1.RVBAR=0x04001000                           \
+    -C cluster1.cpu2.RVBAR=0x04001000                           \
+    -C cluster1.cpu3.RVBAR=0x04001000                           \
+    --data cluster0.cpu0="<path-to>/bl31.bin"@0x04001000        \
     --data cluster0.cpu0="<path-to>/<patched-fdt>"@0x82000000   \
     --data cluster0.cpu0="<path-to>/<kernel-binary>"@0x80080000 \
     --data cluster0.cpu0="<path-to>/<ramdisk.img>"@0x84000000
diff --git a/docs/plat/meson-axg.rst b/docs/plat/meson-axg.rst
new file mode 100644
index 0000000..1e4b2c2
--- /dev/null
+++ b/docs/plat/meson-axg.rst
@@ -0,0 +1,27 @@
+Amlogic Meson A113D (AXG)
+===========================
+
+The Amlogic Meson A113D is a SoC with a quad core Arm Cortex-A53 running at
+~1.2GHz. It also contains a Cortex-M3 used as SCP.
+
+This port is a minimal implementation of BL31 capable of booting mainline U-Boot
+and Linux:
+
+- SCPI support.
+- Basic PSCI support (CPU_ON, CPU_OFF, SYSTEM_RESET, SYSTEM_OFF). Note that CPU0
+  can't be turned off, so there is a workaround to hide this from the caller.
+- GICv2 driver set up.
+- Basic SIP services (read efuse data, enable/disable JTAG).
+
+In order to build it:
+
+.. code:: shell
+
+    CROSS_COMPILE=aarch64-none-elf- make DEBUG=1 PLAT=axg [SPD=opteed]
+         [AML_USE_ATOS=1 when using ATOS as BL32]
+
+This port has been tested on a A113D board. After building it, follow the
+instructions in the `U-Boot repository`_, replacing the mentioned **bl31.img**
+by the one built from this port.
+
+.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/board/amlogic/s400/README
diff --git a/docs/process/security-hardening.rst b/docs/process/security-hardening.rst
index 43a5721..507046f 100644
--- a/docs/process/security-hardening.rst
+++ b/docs/process/security-hardening.rst
@@ -25,6 +25,99 @@
 many normal world requests (a *Denial of Service* or *DoS* attack). It should
 have a mechanism for throttling or ignoring normal world requests.
 
+Preventing Secure-world timing information leakage via PMU counters
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The Secure world needs to implement some defenses to prevent the Non-secure
+world from making it leak timing information. In general, higher privilege
+levels must defend from those below when the PMU is treated as an attack
+vector.
+
+Refer to the :ref:`Performance Monitoring Unit` guide for detailed information
+on the PMU registers.
+
+Timing leakage attacks from the Non-secure world
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Since the Non-secure world has access to the ``PMCR`` register, it can
+configure the PMU to increment counters at any exception level and in both
+Secure and Non-secure state. Thus, it attempts to leak timing information from
+the Secure world.
+
+Shown below is an example of such a configuration:
+
+-  ``PMEVTYPER0_EL0`` and ``PMCCFILTR_EL0``:
+
+   -  Set ``P`` to ``0``.
+   -  Set ``NSK`` to ``1``.
+   -  Set ``M`` to ``0``.
+   -  Set ``NSH`` to ``0``.
+   -  Set ``SH`` to ``1``.
+
+-  ``PMCNTENSET_EL0``:
+
+   -  Set ``P[0]`` to ``1``.
+   -  Set ``C`` to ``1``.
+
+-  ``PMCR_EL0``:
+
+   -  Set ``DP`` to ``0``.
+   -  Set ``E`` to ``1``.
+
+This configuration instructs ``PMEVCNTR0_EL0`` and ``PMCCNTR_EL0`` to increment
+at Secure EL1, Secure EL2 (if implemented) and EL3.
+
+Since the Non-secure world has fine-grained control over where (at which
+exception levels) it instructs counters to increment, obtaining event counts
+would allow it to carry out side-channel timing attacks against the Secure
+world. Examples include Spectre, Meltdown, as well as extracting secrets from
+cryptographic algorithms with data-dependent variations in their execution
+time.
+
+Secure world mitigation strategies
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``MDCR_EL3`` register allows EL3 to configure the PMU (among other things).
+The `Arm ARM`_ details all of the bit fields in this register, but for the PMU
+there are two bits which determine the permissions of the counters:
+
+-  ``SPME`` for the programmable counters.
+-  ``SCCD`` for the cycle counter.
+
+Depending on the implemented features, the Secure world can prohibit counting
+in AArch64 state via the following:
+
+-  ARMv8.2-Debug not implemented:
+
+   -  Prohibit general event counters and the cycle counter:
+      ``MDCR_EL3.SPME == 0 && PMCR_EL0.DP == 1 && !ExternalSecureNoninvasiveDebugEnabled()``.
+
+      -  ``MDCR_EL3.SPME`` resets to ``0``, so by default general events should
+         not be counted in the Secure world.
+      -  The ``PMCR_EL0.DP`` bit therefore needs to be set to ``1`` when EL3 is
+         entered and ``PMCR_EL0`` needs to be saved and restored in EL3.
+      -  ``ExternalSecureNoninvasiveDebugEnabled()`` is an authentication
+         interface which is implementation-defined unless ARMv8.4-Debug is
+         implemented. The `Arm ARM`_ has detailed information on this topic.
+
+   -  The only other way is to disable the ``PMCR_EL0.E`` bit upon entering
+      EL3, which disables counting altogether.
+
+-  ARMv8.2-Debug implemented:
+
+   -  Prohibit general event counters: ``MDCR_EL3.SPME == 0``.
+   -  Prohibit cycle counter: ``MDCR_EL3.SPME == 0 && PMCR_EL0.DP == 1``.
+      ``PMCR_EL0`` therefore needs to be saved and restored in EL3.
+
+-  ARMv8.5-PMU implemented:
+
+   -  Prohibit general event counters: as in ARMv8.2-Debug.
+   -  Prohibit cycle counter: ``MDCR_EL3.SCCD == 1``
+
+In Aarch32 execution state the ``MDCR_EL3`` alias is the ``SDCR`` register,
+which has some of the bit fields of ``MDCR_EL3``, most importantly the ``SPME``
+and ``SCCD`` bits.
+
 Build options
 -------------
 
@@ -71,6 +164,12 @@
   NB: The ``Werror`` flag is enabled by default in TF-A and can be disabled by
   setting the ``E`` build flag to 0.
 
+.. rubric:: References
+
+-  `Arm ARM`_
+
 --------------
 
 *Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
+
+.. _Arm ARM: https://developer.arm.com/docs/ddi0487/latest
diff --git a/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml b/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml
new file mode 100644
index 0000000..c36e544
--- /dev/null
+++ b/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml
@@ -0,0 +1,52 @@
+@startuml
+
+box "BL1 common code"
+	participant bl1_main
+	participant bl_common
+end box
+
+box "arm platform code" #LightBlue
+	participant fvp_bl1_setup
+	participant arm_bl1_setup
+	participant arm_io_storage
+end box
+
+box "platform common code"
+	participant plat_bl1_common
+	participant fconf
+end box
+
+bl1_main -> fvp_bl1_setup : bl1_platform_setup()
+fvp_bl1_setup -> arm_bl1_setup : arm_bl1_platform_setup()
+arm_bl1_setup -> arm_io_storage : plat_arm_io_setup()
+note over arm_io_storage : register and setup fip
+arm_bl1_setup -> fconf : fconf_load_config()
+activate fconf
+	note over fconf
+		create and populate an
+		image_desc_t for TB_FW_CONFIG
+	end note
+	fconf -> bl_common : load_auth_image(TB_FW_CONFIG_ID, &image_info)
+	activate bl_common
+	note over bl_common
+		load and auth image from fip
+		with info from plat_io_policy
+	end note
+	bl_common -> arm_io_storage
+	arm_io_storage -> fconf: FCONF_GET_PROPERTY(arm, arm_io_policies, tb_fw_cfg)
+	note over fconf: use staticaly defined policies in bl1
+	fconf <- bl_common : image_info
+	deactivate bl_common
+	note over fconf : get tb_fw_config_dtb from image_info
+	fconf -> plat_bl1_common : bl1_plat_get_image_desc(BL2_IMAGE_ID)
+	fconf <- plat_bl1_common : BL2_IMAGE_DESC
+	note over fconf
+		set ep_info.args.arg0 of BL2_IMAGE_DESC
+		to TB_FW_CONFIG base address
+	end note
+arm_bl1_setup <- fconf
+deactivate fconf
+
+== load & auth, prepare and jump to BL2 ==
+
+@enduml
diff --git a/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml b/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml
new file mode 100644
index 0000000..98a3ff1
--- /dev/null
+++ b/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml
@@ -0,0 +1,41 @@
+@startuml
+
+box "BL2 common code"
+	participant bl2_entrypoint
+	participant bl2_main
+end box
+
+box "platform common code"
+	participant fconf
+	participant fconf_tbbr_getter
+end box
+
+box "arm platform code" #LightBlue
+	participant arm_bl2_setup
+	participant arm_io_storage
+	participant arm_fconf_io
+end box
+
+== bl2 setup ==
+bl2_entrypoint -> bl2_main : bl2_setup()
+bl2_main -> arm_bl2_setup : bl2_early_platform_setup2(\n\t arg0, arg1, arg2, arg3)
+note over arm_bl2_setup
+	arg0 = tb_fw_config
+	arg1 = mem_layout
+end note
+arm_bl2_setup -> arm_bl2_setup : arm_bl2_early_platform_setup(\n\t tb_fw_config, mem_layout)
+activate arm_bl2_setup
+	arm_bl2_setup -> fconf: fconf_polulate(tb_fw_config)
+	activate fconf
+		fconf -> fconf_tbbr_getter: fconf_populate_tbbr_dyn_config(uintptr_t dtb)
+		note over fconf_tbbr_getter: read tbbr propeties from dtb
+		fconf -> arm_fconf_io: fconf_populate_arm_io_policies(uintptr_t dtb)
+		note over arm_fconf_io: read arm io propeties from dtb
+	deactivate fconf
+	arm_bl2_setup -> arm_io_storage : plat_arm_io_setup()
+	note over arm_io_storage: use populated properties
+deactivate arm_bl2_setup
+
+== bl2 main ==
+
+@enduml
diff --git a/drivers/amlogic/console/aarch64/meson_console.S b/drivers/amlogic/console/aarch64/meson_console.S
index e645cba..39c2545 100644
--- a/drivers/amlogic/console/aarch64/meson_console.S
+++ b/drivers/amlogic/console/aarch64/meson_console.S
@@ -46,14 +46,14 @@
 	/* -----------------------------------------------
 	 * int console_meson_register(uintptr_t base,
 	 *     uint32_t clk, uint32_t baud,
-	 *     console_meson_t *console);
+	 *     console_t *console);
 	 * Function to initialize and register a new MESON
 	 * console. Storage passed in for the console struct
 	 * *must* be persistent (i.e. not from the stack).
 	 * In: x0 - UART register base address
 	 *     w1 - UART clock in Hz
 	 *     w2 - Baud rate
-	 *     x3 - pointer to empty console_meson_t struct
+	 *     x3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : x0, x1, x2, x6, x7, x14
 	 * -----------------------------------------------
@@ -62,7 +62,7 @@
 	mov	x7, x30
 	mov	x6, x3
 	cbz	x6, register_fail
-	str	x0, [x6, #CONSOLE_T_MESON_BASE]
+	str	x0, [x6, #CONSOLE_T_BASE]
 
 	bl	console_meson_init
 	cbz	x0, register_fail
@@ -128,7 +128,7 @@
 endfunc console_meson_init
 
 	/* --------------------------------------------------------
-	 * int console_meson_putc(int c, console_meson_t *console)
+	 * int console_meson_putc(int c, console_t *console)
 	 * Function to output a character over the console. It
 	 * returns the character printed on success or -1 on error.
 	 * In : w0 - character to be printed
@@ -142,7 +142,7 @@
 	cmp	x1, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x1, [x1, #CONSOLE_T_MESON_BASE]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 	b	console_meson_core_putc
 endfunc console_meson_putc
 
@@ -179,7 +179,7 @@
 endfunc console_meson_core_putc
 
 	/* ---------------------------------------------
-	 * int console_meson_getc(console_meson_t *console)
+	 * int console_meson_getc(console_t *console)
 	 * Function to get a character from the console.
 	 * It returns the character grabbed on success
 	 * or -1 if no character is available.
@@ -193,7 +193,7 @@
 	cmp	x0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x0, [x0, #CONSOLE_T_MESON_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_meson_core_getc
 endfunc console_meson_getc
 
@@ -224,7 +224,7 @@
 endfunc console_meson_core_getc
 
 	/* ---------------------------------------------
-	 * int console_meson_flush(console_meson_t *console)
+	 * int console_meson_flush(console_t *console)
 	 * Function to force a write of all buffered
 	 * data that hasn't been output.
 	 * In : x0 - pointer to console_t structure
@@ -237,7 +237,7 @@
 	cmp	x0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x0, [x0, #CONSOLE_T_MESON_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_meson_core_flush
 endfunc console_meson_flush
 
diff --git a/drivers/arm/css/mhu/css_mhu_doorbell.c b/drivers/arm/css/mhu/css_mhu_doorbell.c
index 8858742..c51f3b1 100644
--- a/drivers/arm/css/mhu/css_mhu_doorbell.c
+++ b/drivers/arm/css/mhu/css_mhu_doorbell.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -20,11 +20,13 @@
 
 void mhuv2_ring_doorbell(struct scmi_channel_plat_info *plat_info)
 {
+	uintptr_t mhuv2_base = plat_info->db_reg_addr & MHU_V2_FRAME_BASE_MASK;
+
 	/* wake receiver */
-	MHU_V2_ACCESS_REQUEST(MHUV2_BASE_ADDR);
+	MHU_V2_ACCESS_REQUEST(mhuv2_base);
 
 	/* wait for receiver to acknowledge its ready */
-	while (MHU_V2_IS_ACCESS_READY(MHUV2_BASE_ADDR) == 0)
+	while (MHU_V2_IS_ACCESS_READY(mhuv2_base) == 0)
 		;
 
 	MHU_RING_DOORBELL(plat_info->db_reg_addr,
@@ -32,7 +34,7 @@
 			plat_info->db_preserve_mask);
 
 	/* clear the access request for the receiver */
-	MHU_V2_CLEAR_REQUEST(MHUV2_BASE_ADDR);
+	MHU_V2_CLEAR_REQUEST(mhuv2_base);
 
 	return;
 }
diff --git a/drivers/arm/css/scp/css_pm_scmi.c b/drivers/arm/css/scp/css_pm_scmi.c
index b945cda..097d2eb 100644
--- a/drivers/arm/css/scp/css_pm_scmi.c
+++ b/drivers/arm/css/scp/css_pm_scmi.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
  */
@@ -63,17 +63,45 @@
 } scmi_power_state_t;
 
 /*
- * The global handle for invoking the SCMI driver APIs after the driver
+ * The global handles for invoking the SCMI driver APIs after the driver
  * has been initialized.
  */
-static void *scmi_handle;
+static void *scmi_handles[PLAT_ARM_SCMI_CHANNEL_COUNT];
 
-/* The SCMI channel global object */
-static scmi_channel_t channel;
+/* The global SCMI channels array */
+static scmi_channel_t scmi_channels[PLAT_ARM_SCMI_CHANNEL_COUNT];
 
+/*
+ * Channel ID for the default SCMI channel.
+ * The default channel is used to issue SYSTEM level SCMI requests and is
+ * initialized to the channel which has the boot cpu as its resource.
+ */
+static uint32_t default_scmi_channel_id;
+
+/*
+ * TODO: Allow use of channel specific lock instead of using a single lock for
+ * all the channels.
+ */
 ARM_SCMI_INSTANTIATE_LOCK;
 
 /*
+ * Function to obtain the SCMI Domain ID and SCMI Channel number from the linear
+ * core position. The SCMI Channel number is encoded in the upper 16 bits and
+ * the Domain ID is encoded in the lower 16 bits in each entry of the mapping
+ * array exported by the platform.
+ */
+static void css_scp_core_pos_to_scmi_channel(unsigned int core_pos,
+		unsigned int *scmi_domain_id, unsigned int *scmi_channel_id)
+{
+	unsigned int composite_id;
+
+	composite_id = plat_css_core_pos_to_scmi_dmn_id_map[core_pos];
+
+	*scmi_channel_id = GET_SCMI_CHANNEL_ID(composite_id);
+	*scmi_domain_id = GET_SCMI_DOMAIN_ID(composite_id);
+}
+
+/*
  * Helper function to suspend a CPU power domain and its parent power domains
  * if applicable.
  */
@@ -87,10 +115,10 @@
 
 	/* Check if power down at system power domain level is requested */
 	if (css_system_pwr_state(target_state) == ARM_LOCAL_STATE_OFF) {
-		/* Issue SCMI command for SYSTEM_SUSPEND */
-		ret = scmi_sys_pwr_state_set(scmi_handle,
-				SCMI_SYS_PWR_FORCEFUL_REQ,
-				SCMI_SYS_PWR_SUSPEND);
+		/* Issue SCMI command for SYSTEM_SUSPEND on all SCMI channels */
+		ret = scmi_sys_pwr_state_set(
+				scmi_handles[default_scmi_channel_id],
+				SCMI_SYS_PWR_FORCEFUL_REQ, SCMI_SYS_PWR_SUSPEND);
 		if (ret != SCMI_E_SUCCESS) {
 			ERROR("SCMI system power domain suspend return 0x%x unexpected\n",
 					ret);
@@ -99,7 +127,7 @@
 		return;
 	}
 #if !HW_ASSISTED_COHERENCY
-	unsigned int lvl;
+	unsigned int lvl, channel_id, domain_id;
 	uint32_t scmi_pwr_state = 0;
 	/*
 	 * If we reach here, then assert that power down at system power domain
@@ -127,9 +155,10 @@
 
 	SCMI_SET_PWR_STATE_MAX_PWR_LVL(scmi_pwr_state, lvl - 1);
 
-	ret = scmi_pwr_state_set(scmi_handle,
-		plat_css_core_pos_to_scmi_dmn_id_map[plat_my_core_pos()],
-		scmi_pwr_state);
+	css_scp_core_pos_to_scmi_channel(plat_my_core_pos(),
+			&domain_id, &channel_id);
+	ret = scmi_pwr_state_set(scmi_handles[channel_id],
+		domain_id, scmi_pwr_state);
 
 	if (ret != SCMI_E_SUCCESS) {
 		ERROR("SCMI set power state command return 0x%x unexpected\n",
@@ -145,7 +174,7 @@
  */
 void css_scp_off(const struct psci_power_state *target_state)
 {
-	unsigned int lvl = 0;
+	unsigned int lvl = 0, channel_id, domain_id;
 	int ret;
 	uint32_t scmi_pwr_state = 0;
 
@@ -168,10 +197,10 @@
 
 	SCMI_SET_PWR_STATE_MAX_PWR_LVL(scmi_pwr_state, lvl - 1);
 
-	ret = scmi_pwr_state_set(scmi_handle,
-		plat_css_core_pos_to_scmi_dmn_id_map[plat_my_core_pos()],
-		scmi_pwr_state);
-
+	css_scp_core_pos_to_scmi_channel(plat_my_core_pos(),
+			&domain_id, &channel_id);
+	ret = scmi_pwr_state_set(scmi_handles[channel_id],
+		domain_id, scmi_pwr_state);
 	if (ret != SCMI_E_QUEUED && ret != SCMI_E_SUCCESS) {
 		ERROR("SCMI set power state command return 0x%x unexpected\n",
 				ret);
@@ -185,8 +214,8 @@
  */
 void css_scp_on(u_register_t mpidr)
 {
-	unsigned int lvl = 0;
-	int core_pos, ret;
+	unsigned int lvl = 0, channel_id, core_pos, domain_id;
+	int ret;
 	uint32_t scmi_pwr_state = 0;
 
 	for (; lvl <= PLAT_MAX_PWR_LVL; lvl++)
@@ -196,13 +225,12 @@
 	SCMI_SET_PWR_STATE_MAX_PWR_LVL(scmi_pwr_state, lvl - 1);
 
 	core_pos = plat_core_pos_by_mpidr(mpidr);
-	assert((core_pos >= 0) &&
-		(((unsigned int)core_pos) < PLATFORM_CORE_COUNT));
+	assert(core_pos >= 0 && (core_pos < PLATFORM_CORE_COUNT));
 
-	ret = scmi_pwr_state_set(scmi_handle,
-		plat_css_core_pos_to_scmi_dmn_id_map[core_pos],
-		scmi_pwr_state);
-
+	css_scp_core_pos_to_scmi_channel(core_pos, &domain_id,
+			&channel_id);
+	ret = scmi_pwr_state_set(scmi_handles[channel_id],
+		domain_id, scmi_pwr_state);
 	if (ret != SCMI_E_QUEUED && ret != SCMI_E_SUCCESS) {
 		ERROR("SCMI set power state command return 0x%x unexpected\n",
 				ret);
@@ -216,8 +244,9 @@
  */
 int css_scp_get_power_state(u_register_t mpidr, unsigned int power_level)
 {
-	int ret, cpu_idx;
+	int ret;
 	uint32_t scmi_pwr_state = 0, lvl_state;
+	unsigned int channel_id, cpu_idx, domain_id;
 
 	/* We don't support get power state at the system power domain level */
 	if ((power_level > PLAT_MAX_PWR_LVL) ||
@@ -230,9 +259,9 @@
 	cpu_idx = plat_core_pos_by_mpidr(mpidr);
 	assert(cpu_idx > -1);
 
-	ret = scmi_pwr_state_get(scmi_handle,
-		plat_css_core_pos_to_scmi_dmn_id_map[cpu_idx],
-		&scmi_pwr_state);
+	css_scp_core_pos_to_scmi_channel(cpu_idx, &domain_id, &channel_id);
+	ret = scmi_pwr_state_get(scmi_handles[channel_id],
+		domain_id, &scmi_pwr_state);
 
 	if (ret != SCMI_E_SUCCESS) {
 		WARN("SCMI get power state command return 0x%x unexpected\n",
@@ -271,7 +300,7 @@
 	 * Issue SCMI command. First issue a graceful
 	 * request and if that fails force the request.
 	 */
-	ret = scmi_sys_pwr_state_set(scmi_handle,
+	ret = scmi_sys_pwr_state_set(scmi_handles[default_scmi_channel_id],
 			SCMI_SYS_PWR_FORCEFUL_REQ,
 			state);
 
@@ -325,17 +354,28 @@
 
 void __init plat_arm_pwrc_setup(void)
 {
-	channel.info = plat_css_get_scmi_info();
-	channel.lock = ARM_SCMI_LOCK_GET_INSTANCE;
-	scmi_handle = scmi_init(&channel);
-	if (scmi_handle == NULL) {
-		ERROR("SCMI Initialization failed\n");
-		panic();
-	}
-	if (scmi_ap_core_init(&channel) < 0) {
-		ERROR("SCMI AP core protocol initialization failed\n");
-		panic();
+	unsigned int composite_id, idx;
+
+	for (idx = 0; idx < PLAT_ARM_SCMI_CHANNEL_COUNT; idx++) {
+		INFO("Initializing driver on Channel %d\n", idx);
+
+		scmi_channels[idx].info = plat_css_get_scmi_info(idx);
+		scmi_channels[idx].lock = ARM_SCMI_LOCK_GET_INSTANCE;
+		scmi_handles[idx] = scmi_init(&scmi_channels[idx]);
+
+		if (scmi_handles[idx] == NULL) {
+			ERROR("SCMI Initialization failed on channel %d\n", idx);
+			panic();
+		}
+
+		if (scmi_ap_core_init(&scmi_channels[idx]) < 0) {
+			ERROR("SCMI AP core protocol initialization failed\n");
+			panic();
+		}
 	}
+
+	composite_id = plat_css_core_pos_to_scmi_dmn_id_map[plat_my_core_pos()];
+	default_scmi_channel_id = GET_SCMI_CHANNEL_ID(composite_id);
 }
 
 /******************************************************************************
@@ -347,6 +387,7 @@
 {
 	uint32_t msg_attr;
 	int ret;
+	void *scmi_handle = scmi_handles[default_scmi_channel_id];
 
 	assert(scmi_handle);
 
@@ -411,14 +452,17 @@
 #if PROGRAMMABLE_RESET_ADDRESS
 void plat_arm_program_trusted_mailbox(uintptr_t address)
 {
-	int ret;
+	int ret, i;
 
-	assert(scmi_handle);
-	ret = scmi_ap_core_set_reset_addr(scmi_handle, address,
-		SCMI_AP_CORE_LOCK_ATTR);
-	if (ret != SCMI_E_SUCCESS) {
-		ERROR("CSS: Failed to program reset address: %d\n", ret);
-		panic();
+	for (i = 0; i < PLAT_ARM_SCMI_CHANNEL_COUNT; i++) {
+		assert(scmi_handles[i]);
+
+		ret = scmi_ap_core_set_reset_addr(scmi_handles[i], address,
+				SCMI_AP_CORE_LOCK_ATTR);
+		if (ret != SCMI_E_SUCCESS) {
+			ERROR("CSS: Failed to program reset address: %d\n", ret);
+			panic();
+		}
 	}
 }
 #endif
diff --git a/drivers/arm/css/scpi/css_scpi.c b/drivers/arm/css/scpi/css_scpi.c
index c56b7c4..416356b 100644
--- a/drivers/arm/css/scpi/css_scpi.c
+++ b/drivers/arm/css/scpi/css_scpi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -51,7 +51,7 @@
 	mhu_secure_message_send(SCPI_MHU_SLOT_ID);
 }
 
-static void scpi_secure_message_receive(scpi_cmd_t *cmd)
+static int scpi_secure_message_receive(scpi_cmd_t *cmd)
 {
 	uint32_t mhu_status;
 
@@ -63,7 +63,7 @@
 	if (mhu_status != (1 << SCPI_MHU_SLOT_ID)) {
 		ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n",
 			mhu_status);
-		panic();
+		return -1;
 	}
 
 	/*
@@ -74,6 +74,8 @@
 	dmbld();
 
 	memcpy(cmd, (void *) SCPI_SHARED_MEM_SCP_TO_AP, sizeof(*cmd));
+
+	return 0;
 }
 
 static void scpi_secure_message_end(void)
@@ -84,14 +86,19 @@
 int scpi_wait_ready(void)
 {
 	scpi_cmd_t scpi_cmd;
+	int rc;
 
 	VERBOSE("Waiting for SCP_READY command...\n");
 
 	/* Get a message from the SCP */
 	scpi_secure_message_start();
-	scpi_secure_message_receive(&scpi_cmd);
+	rc = scpi_secure_message_receive(&scpi_cmd);
 	scpi_secure_message_end();
 
+	/* If no message was received, don't send a response */
+	if (rc != 0)
+		return rc;
+
 	/* We are expecting 'SCP Ready', produce correct error if it's not */
 	scpi_status_t status = SCP_OK;
 	if (scpi_cmd.id != SCPI_CMD_SCP_READY) {
@@ -209,7 +216,8 @@
 	 * Send message and wait for SCP's response
 	 */
 	scpi_secure_message_send(0);
-	scpi_secure_message_receive(&response);
+	if (scpi_secure_message_receive(&response) != 0)
+		goto exit;
 
 	if (response.status != SCP_OK)
 		goto exit;
@@ -254,7 +262,9 @@
 	*payload_addr = system_state & 0xff;
 	scpi_secure_message_send(sizeof(*payload_addr));
 
-	scpi_secure_message_receive(&response);
+	/* If no response is received, fill in an error status */
+	if (scpi_secure_message_receive(&response) != 0)
+		response.status = SCP_E_TIMEOUT;
 
 	scpi_secure_message_end();
 
diff --git a/drivers/arm/pl011/aarch32/pl011_console.S b/drivers/arm/pl011/aarch32/pl011_console.S
index 05c8250..93045f0 100644
--- a/drivers/arm/pl011/aarch32/pl011_console.S
+++ b/drivers/arm/pl011/aarch32/pl011_console.S
@@ -91,14 +91,14 @@
 	/* -------------------------------------------------------
 	 * int console_pl011_register(uintptr_t baseaddr,
 	 *     uint32_t clock, uint32_t baud,
-	 *     console_pl011_t *console);
+	 *     console_t *console);
 	 * Function to initialize and register a new PL011
 	 * console. Storage passed in for the console struct
 	 * *must* be persistent (i.e. not from the stack).
 	 * In: r0 - UART register base address
 	 *     r1 - UART clock in Hz
 	 *     r2 - Baud rate
-	 *     r3 - pointer to empty console_pl011_t struct
+	 *     r3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : r0, r1, r2
 	 * -------------------------------------------------------
@@ -108,7 +108,7 @@
 	mov	r4, r3
 	cmp	r4, #0
 	beq	register_fail
-	str	r0, [r4, #CONSOLE_T_PL011_BASE]
+	str	r0, [r4, #CONSOLE_T_BASE]
 
 	bl console_pl011_core_init
 	cmp	r0, #0
@@ -159,7 +159,7 @@
 endfunc console_pl011_core_putc
 
 	/* --------------------------------------------------------
-	 * int console_pl011_putc(int c, console_pl011_t *console)
+	 * int console_pl011_putc(int c, console_t *console)
 	 * Function to output a character over the console. It
 	 * returns the character printed on success or -1 on error.
 	 * In: r0 - character to be printed
@@ -173,7 +173,7 @@
 	cmp	r1, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	r1, [r1, #CONSOLE_T_PL011_BASE]
+	ldr	r1, [r1, #CONSOLE_T_BASE]
 	b	console_pl011_core_putc
 endfunc console_pl011_putc
 
@@ -203,7 +203,7 @@
 endfunc console_pl011_core_getc
 
 	/* ------------------------------------------------
-	 * int console_pl011_getc(console_pl011_t *console)
+	 * int console_pl011_getc(console_t *console)
 	 * Function to get a character from the console.
 	 * It returns the character grabbed on success
 	 * or -1 if no character is available.
@@ -217,7 +217,7 @@
 	cmp	r0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	r0, [r0, #CONSOLE_T_PL011_BASE]
+	ldr	r0, [r0, #CONSOLE_T_BASE]
 	b	console_pl011_core_getc
 endfunc console_pl011_getc
 
@@ -248,7 +248,7 @@
 endfunc console_pl011_core_flush
 
 	/* ---------------------------------------------
-	 * int console_pl011_flush(console_pl011_t *console)
+	 * int console_pl011_flush(console_t *console)
 	 * Function to force a write of all buffered
 	 * data that hasn't been output.
 	 * In : r0 - pointer to console_t structure
@@ -261,6 +261,6 @@
 	cmp	r0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	r0, [r0, #CONSOLE_T_PL011_BASE]
+	ldr	r0, [r0, #CONSOLE_T_BASE]
 	b	console_pl011_core_flush
 endfunc console_pl011_flush
diff --git a/drivers/arm/pl011/aarch64/pl011_console.S b/drivers/arm/pl011/aarch64/pl011_console.S
index 04de99f..3a2a3cd 100644
--- a/drivers/arm/pl011/aarch64/pl011_console.S
+++ b/drivers/arm/pl011/aarch64/pl011_console.S
@@ -80,14 +80,14 @@
 	/* -----------------------------------------------
 	 * int console_pl011_register(uintptr_t baseaddr,
 	 *     uint32_t clock, uint32_t baud,
-	 *     console_pl011_t *console);
+	 *     console_t *console);
 	 * Function to initialize and register a new PL011
 	 * console. Storage passed in for the console struct
 	 * *must* be persistent (i.e. not from the stack).
 	 * In: x0 - UART register base address
 	 *     w1 - UART clock in Hz
 	 *     w2 - Baud rate
-	 *     x3 - pointer to empty console_pl011_t struct
+	 *     x3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : x0, x1, x2, x6, x7, x14
 	 * -----------------------------------------------
@@ -96,7 +96,7 @@
 	mov	x7, x30
 	mov	x6, x3
 	cbz	x6, register_fail
-	str	x0, [x6, #CONSOLE_T_PL011_BASE]
+	str	x0, [x6, #CONSOLE_T_BASE]
 
 	bl	console_pl011_core_init
 	cbz	x0, register_fail
@@ -143,7 +143,7 @@
 endfunc console_pl011_core_putc
 
 	/* --------------------------------------------------------
-	 * int console_pl011_putc(int c, console_pl011_t *console)
+	 * int console_pl011_putc(int c, console_t *console)
 	 * Function to output a character over the console. It
 	 * returns the character printed on success or -1 on error.
 	 * In : w0 - character to be printed
@@ -157,7 +157,7 @@
 	cmp	x1, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x1, [x1, #CONSOLE_T_PL011_BASE]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 	b	console_pl011_core_putc
 endfunc console_pl011_putc
 
@@ -189,7 +189,7 @@
 endfunc console_pl011_core_getc
 
 	/* ---------------------------------------------
-	 * int console_pl011_getc(console_pl011_t *console)
+	 * int console_pl011_getc(console_t *console)
 	 * Function to get a character from the console.
 	 * It returns the character grabbed on success
 	 * or -1 if no character is available.
@@ -203,7 +203,7 @@
 	cmp	x0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x0, [x0, #CONSOLE_T_PL011_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_pl011_core_getc
 endfunc console_pl011_getc
 
@@ -231,7 +231,7 @@
 endfunc console_pl011_core_flush
 
 	/* ---------------------------------------------
-	 * int console_pl011_flush(console_pl011_t *console)
+	 * int console_pl011_flush(console_t *console)
 	 * Function to force a write of all buffered
 	 * data that hasn't been output.
 	 * In : x0 - pointer to console_t structure
@@ -244,6 +244,6 @@
 	cmp	x0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x0, [x0, #CONSOLE_T_PL011_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_pl011_core_flush
 endfunc console_pl011_flush
diff --git a/drivers/auth/auth_mod.c b/drivers/auth/auth_mod.c
index 3fb2d1a..91ee1be 100644
--- a/drivers/auth/auth_mod.c
+++ b/drivers/auth/auth_mod.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, 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 <lib/fconf/fconf_tbbr_getter.h>
 #include <plat/common/platform.h>
 
 /* ASN.1 tags */
@@ -302,9 +303,8 @@
 	const auth_img_desc_t *img_desc = NULL;
 
 	assert(parent_id != NULL);
-
 	/* Get the image descriptor */
-	img_desc = cot_desc_ptr[img_id];
+	img_desc = FCONF_GET_PROPERTY(tbbr, cot, img_id);
 
 	/* Check if the image has no parent (ROT) */
 	if (img_desc->parent == NULL) {
@@ -353,7 +353,7 @@
 	int rc, i;
 
 	/* Get the image descriptor from the chain of trust */
-	img_desc = cot_desc_ptr[img_id];
+	img_desc = FCONF_GET_PROPERTY(tbbr, cot, img_id);
 
 	/* Ask the parser to check the image integrity */
 	rc = img_parser_check_integrity(img_desc->img_type, img_ptr, img_len);
diff --git a/drivers/auth/tbbr/tbbr_cot.c b/drivers/auth/tbbr/tbbr_cot.c
index 6dd4ae2..6f00b18 100644
--- a/drivers/auth/tbbr/tbbr_cot.c
+++ b/drivers/auth/tbbr/tbbr_cot.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,7 +18,12 @@
 
 
 /*
- * Maximum key and hash sizes (in DER format)
+ * Maximum key and hash sizes (in DER format).
+ *
+ * Both RSA and ECDSA keys may be used at the same time. In this case, the key
+ * buffers must be big enough to hold either. As RSA keys are bigger than ECDSA
+ * ones for all key sizes we support, they impose the minimum size of these
+ * buffers.
  */
 #if TF_MBEDTLS_USE_RSA
 #if TF_MBEDTLS_KEY_SIZE == 1024
@@ -32,11 +37,19 @@
 #else
 #error "Invalid value for TF_MBEDTLS_KEY_SIZE"
 #endif
-#else
-#define PK_DER_LEN			294
+#else /* Only using ECDSA keys. */
+#define PK_DER_LEN			91
 #endif
 
+#if TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA256
+#define HASH_DER_LEN			51
+#elif TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA384
+#define HASH_DER_LEN			67
+#elif TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA512
 #define HASH_DER_LEN			83
+#else
+#error "Invalid value for TF_MBEDTLS_HASH_ALG_ID"
+#endif
 
 /*
  * The platform must allocate buffers to store the authentication parameters
diff --git a/drivers/cadence/uart/aarch64/cdns_console.S b/drivers/cadence/uart/aarch64/cdns_console.S
index ecd0c47..8e5d6a1 100644
--- a/drivers/cadence/uart/aarch64/cdns_console.S
+++ b/drivers/cadence/uart/aarch64/cdns_console.S
@@ -56,14 +56,14 @@
 	/* -----------------------------------------------
 	 * int console_cdns_register(uintptr_t baseaddr,
 	 *     uint32_t clock, uint32_t baud,
-	 *     console_cdns_t *console);
+	 *     console_t *console);
 	 * Function to initialize and register a new CDNS
 	 * console. Storage passed in for the console struct
 	 * *must* be persistent (i.e. not from the stack).
 	 * In: x0 - UART register base address
 	 *     w1 - UART clock in Hz
 	 *     w2 - Baud rate
-	 *     x3 - pointer to empty console_16550_t struct
+	 *     x3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : x0, x1, x2, x6, x7, x14
 	 * -----------------------------------------------
@@ -72,7 +72,7 @@
 	mov	x7, x30
 	mov	x6, x3
 	cbz	x6, register_fail
-	str	x0, [x6, #CONSOLE_T_CDNS_BASE]
+	str	x0, [x6, #CONSOLE_T_BASE]
 
 	bl	console_cdns_core_init
 	cbz	x0, register_fail
@@ -119,7 +119,7 @@
 endfunc console_cdns_core_putc
 
 	/* --------------------------------------------------------
-	 * int console_cdns_putc(int c, console_cdns_t *cdns)
+	 * int console_cdns_putc(int c, console_t *cdns)
 	 * Function to output a character over the console. It
 	 * returns the character printed on success or -1 on error.
 	 * In : w0 - character to be printed
@@ -133,7 +133,7 @@
 	cmp	x1, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x1, [x1, #CONSOLE_T_CDNS_BASE]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 	b	console_cdns_core_putc
 endfunc console_cdns_putc
 
@@ -165,7 +165,7 @@
 endfunc console_cdns_core_getc
 
 	/* ---------------------------------------------
-	 * int console_cdns_getc(console_cdns_t *console)
+	 * int console_cdns_getc(console_t *console)
 	 * Function to get a character from the console.
 	 * It returns the character grabbed on success
 	 * or -1 if no character is available.
@@ -179,7 +179,7 @@
 	cmp	x0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x0, [x0, #CONSOLE_T_CDNS_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_cdns_core_getc
 endfunc console_cdns_getc
 
@@ -203,7 +203,7 @@
 endfunc console_cdns_core_flush
 
 	/* ---------------------------------------------
-	 * int console_cdns_flush(console_pl011_t *console)
+	 * int console_cdns_flush(console_t *console)
 	 * Function to force a write of all buffered
 	 * data that hasn't been output.
 	 * In : x0 - pointer to console_t structure
@@ -216,6 +216,6 @@
 	cmp	x0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x0, [x0, #CONSOLE_T_CDNS_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_cdns_core_flush
 endfunc console_cdns_flush
diff --git a/drivers/cfi/v2m/v2m_flash.c b/drivers/cfi/v2m/v2m_flash.c
index aadafbc..6690189 100644
--- a/drivers/cfi/v2m/v2m_flash.c
+++ b/drivers/cfi/v2m/v2m_flash.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -27,7 +27,7 @@
 #define DWS_WORD_LOCK_RETRIES		1000
 
 /* Helper macro to detect end of command */
-#define NOR_CMD_END (NOR_DWS | NOR_DWS << 16l)
+#define NOR_CMD_END (NOR_DWS | (NOR_DWS << 16l))
 
 /* Helper macros to access two flash banks in parallel */
 #define NOR_2X16(d)			((d << 16) | (d & 0xffff))
diff --git a/drivers/console/aarch32/skeleton_console.S b/drivers/console/aarch32/skeleton_console.S
index 45ad139..c594f7e 100644
--- a/drivers/console/aarch32/skeleton_console.S
+++ b/drivers/console/aarch32/skeleton_console.S
@@ -50,7 +50,7 @@
 	 * by later console callback (e.g. putc).
 	 * Example:
 	 */
-	str	r1, [r0, #CONSOLE_T_XXX_BASE]
+	str	r1, [r0, #CONSOLE_T_BASE]
 	str	r2, [r0, #CONSOLE_T_XXX_SOME_OTHER_VALUE]
 
 	/*
@@ -87,7 +87,7 @@
 	 * console_xxx_t structure pointed to by r1.
 	 * Example:
 	 */
-	ldr	r1, [r1, #CONSOLE_T_XXX_BASE]
+	ldr	r1, [r1, #CONSOLE_T_BASE]
 
 	/*
 	 * Write r0 to hardware.
@@ -125,7 +125,7 @@
 	 * console_xxx_t structure pointed to by r0.
 	 * Example:
 	 */
-	ldr	r1, [r0, #CONSOLE_T_XXX_BASE]
+	ldr	r1, [r0, #CONSOLE_T_BASE]
 
 	/*
 	 * Try to read character into r0 from hardware.
@@ -159,7 +159,7 @@
 	 * console_xxx_t structure pointed to by r0.
 	 * Example:
 	 */
-	ldr	r1, [r0, #CONSOLE_T_XXX_BASE]
+	ldr	r1, [r0, #CONSOLE_T_BASE]
 
 	/*
 	 * Flush all remaining output from hardware FIFOs. Do not return until
diff --git a/drivers/console/aarch64/skeleton_console.S b/drivers/console/aarch64/skeleton_console.S
index 957ed83..9a85867 100644
--- a/drivers/console/aarch64/skeleton_console.S
+++ b/drivers/console/aarch64/skeleton_console.S
@@ -50,7 +50,7 @@
 	 * by later console callback (e.g. putc).
 	 * Example:
 	 */
-	str	x1, [x0, #CONSOLE_T_XXX_BASE]
+	str	x1, [x0, #CONSOLE_T_BASE]
 	str	x2, [x0, #CONSOLE_T_XXX_SOME_OTHER_VALUE]
 
 	/*
@@ -87,7 +87,7 @@
 	 * console_xxx_t structure pointed to by x1.
 	 * Example:
 	 */
-	ldr	x1, [x1, #CONSOLE_T_XXX_BASE]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 
 	/*
 	 * Write w0 to hardware.
@@ -125,7 +125,7 @@
 	 * console_xxx_t structure pointed to by x0.
 	 * Example:
 	 */
-	ldr	x1, [x0, #CONSOLE_T_XXX_BASE]
+	ldr	x1, [x0, #CONSOLE_T_BASE]
 
 	/*
 	 * Try to read character into w0 from hardware.
@@ -159,7 +159,7 @@
 	 * console_xxx_t structure pointed to by x0.
 	 * Example:
 	 */
-	ldr	x1, [x0, #CONSOLE_T_XXX_BASE]
+	ldr	x1, [x0, #CONSOLE_T_BASE]
 
 	/*
 	 * Flush all remaining output from hardware FIFOs. Do not return until
diff --git a/drivers/console/multi_console.c b/drivers/console/multi_console.c
index 215f495..0665f20 100644
--- a/drivers/console/multi_console.c
+++ b/drivers/console/multi_console.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -90,7 +90,7 @@
 	console_t *console;
 
 	for (console = console_list; console != NULL; console = console->next)
-		if ((console->flags & console_state) && console->putc) {
+		if ((console->flags & console_state) && (console->putc != NULL)) {
 			int ret = do_putc(c, console);
 			if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err))
 				err = ret;
@@ -107,7 +107,7 @@
 	do {	/* Keep polling while at least one console works correctly. */
 		for (console = console_list; console != NULL;
 		     console = console->next)
-			if ((console->flags & console_state) && console->getc) {
+			if ((console->flags & console_state) && (console->getc != NULL)) {
 				int ret = console->getc(console);
 				if (ret >= 0)
 					return ret;
@@ -125,7 +125,7 @@
 	console_t *console;
 
 	for (console = console_list; console != NULL; console = console->next)
-		if ((console->flags & console_state) && console->flush) {
+		if ((console->flags & console_state) && (console->flush != NULL)) {
 			int ret = console->flush(console);
 			if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err))
 				err = ret;
diff --git a/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S b/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S
index fd04c2e..a4a7bf8 100644
--- a/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S
+++ b/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S
@@ -35,7 +35,7 @@
 	 * -----------------------------------------------
 	 */
 func console_cbmc_register
-	str	x0, [x1, #CONSOLE_T_CBMC_BASE]
+	str	x0, [x1, #CONSOLE_T_BASE]
 	ldr	w2, [x0]
 	str	w2, [x1, #CONSOLE_T_CBMC_SIZE]
 	mov	x0, x1
@@ -54,7 +54,7 @@
 	 */
 func console_cbmc_putc
 	ldr	w2, [x1, #CONSOLE_T_CBMC_SIZE]
-	ldr	x1, [x1, #CONSOLE_T_CBMC_BASE]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 	add	x1, x1, #8		/* keep address of body in x1 */
 
 	ldr	w16, [x1, #-4]		/* load cursor (one u32 before body) */
@@ -93,7 +93,7 @@
 func console_cbmc_flush
 	mov	x5, x30
 	ldr	x1, [x0, #CONSOLE_T_CBMC_SIZE]
-	ldr	x0, [x0, #CONSOLE_T_CBMC_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	add	x1, x1, #8		/* add size of console header */
 	bl	clean_dcache_range	/* (clobbers x2 and x3) */
 	mov	x0, #0
diff --git a/drivers/delay_timer/generic_delay_timer.c b/drivers/delay_timer/generic_delay_timer.c
index 3d0a11f..ca522e0 100644
--- a/drivers/delay_timer/generic_delay_timer.c
+++ b/drivers/delay_timer/generic_delay_timer.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,11 +13,9 @@
 #include <common/debug.h>
 #include <drivers/delay_timer.h>
 #include <drivers/generic_delay_timer.h>
+#include <lib/utils_def.h>
 #include <plat/common/platform.h>
 
-/* Ticks elapsed in one second by a signal of 1 MHz */
-#define MHZ_TICKS_PER_SEC 1000000
-
 static timer_ops_t ops;
 
 static uint32_t get_timer_value(void)
diff --git a/drivers/imx/uart/imx_uart.h b/drivers/imx/uart/imx_uart.h
index 4f6d3de..a133024 100644
--- a/drivers/imx/uart/imx_uart.h
+++ b/drivers/imx/uart/imx_uart.h
@@ -154,15 +154,10 @@
 
 #ifndef __ASSEMBLER__
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_imx_uart_t;
-
 int console_imx_uart_register(uintptr_t baseaddr,
 			      uint32_t clock,
 			      uint32_t baud,
-			      console_imx_uart_t *console);
+			      console_t *console);
 #endif /*__ASSEMBLER__*/
 
 #endif /* IMX_UART_H */
diff --git a/drivers/marvell/mochi/cp110_setup.c b/drivers/marvell/mochi/cp110_setup.c
index b4b4e0c..7186f98 100644
--- a/drivers/marvell/mochi/cp110_setup.c
+++ b/drivers/marvell/mochi/cp110_setup.c
@@ -303,7 +303,7 @@
 			      DOMAIN_SYSTEM_SHAREABLE);
 }
 
-static void amb_bridge_init(uintptr_t base)
+void cp110_amb_init(uintptr_t base)
 {
 	uint32_t reg;
 
@@ -399,7 +399,7 @@
 	cp110_stream_id_init(cp110_base, stream_id);
 
 	/* Open AMB bridge for comphy for CP0 & CP1*/
-	amb_bridge_init(cp110_base);
+	cp110_amb_init(cp110_base);
 
 	/* Reset RTC if needed */
 	cp110_rtc_init(cp110_base);
@@ -411,7 +411,7 @@
 #if PCI_EP_SUPPORT
 	INFO("%s: Initialize CPx - base = %lx\n", __func__, cp110_base);
 
-	amb_bridge_init(cp110_base);
+	cp110_amb_init(cp110_base);
 
 	/* Configure PCIe clock */
 	cp110_pcie_clk_cfg(cp110_base);
diff --git a/drivers/marvell/uart/a3700_console.S b/drivers/marvell/uart/a3700_console.S
index da1ce35..ecd494c 100644
--- a/drivers/marvell/uart/a3700_console.S
+++ b/drivers/marvell/uart/a3700_console.S
@@ -110,7 +110,7 @@
 	.globl console_a3700_register
 
 	/* -----------------------------------------------
-	 * int console_a3700_register(console_16550_t *console,
+	 * int console_a3700_register(console_t *console,
 		uintptr_t base, uint32_t clk, uint32_t baud)
 	 * Function to initialize and register a new a3700
 	 * console. Storage passed in for the console struct
@@ -118,7 +118,7 @@
 	 * In: x0 - UART register base address
 	 *     w1 - UART clock in Hz
 	 *     w2 - Baud rate
-	 *     x3 - pointer to empty console_a3700_t struct
+	 *     x3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : x0, x1, x2, x6, x7, x14
 	 * -----------------------------------------------
@@ -127,7 +127,7 @@
 	mov	x7, x30
 	mov	x6, x3
 	cbz	x6, register_fail
-	str	x0, [x6, #CONSOLE_T_A3700_BASE]
+	str	x0, [x6, #CONSOLE_T_BASE]
 
 	bl	console_a3700_core_init
 	cbz	x0, register_fail
@@ -178,7 +178,7 @@
 endfunc console_a3700_core_putc
 
 	/* --------------------------------------------------------
-	 * int console_a3700_putc(int c, console_a3700_t *console)
+	 * int console_a3700_putc(int c, console_t *console)
 	 * Function to output a character over the console. It
 	 * returns the character printed on success or -1 on error.
 	 * In : w0 - character to be printed
@@ -188,7 +188,7 @@
 	 * --------------------------------------------------------
 	 */
 func console_a3700_putc
-	ldr	x1, [x1, #CONSOLE_T_A3700_BASE]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 	b	console_a3700_core_putc
 endfunc console_a3700_putc
 
@@ -208,7 +208,7 @@
 endfunc console_a3700_core_getc
 
 	/* ---------------------------------------------
-	 * int console_a3700_getc(console_a3700_t *console)
+	 * int console_a3700_getc(console_t *console)
 	 * Function to get a character from the console.
 	 * It returns the character grabbed on success
 	 * or -1 on if no character is available.
@@ -218,7 +218,7 @@
 	 * ---------------------------------------------
 	 */
 func console_a3700_getc
-	ldr	x0, [x0, #CONSOLE_T_A3700_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_a3700_core_getc
 endfunc console_a3700_getc
 
@@ -237,7 +237,7 @@
 endfunc console_a3700_core_flush
 
 	/* ---------------------------------------------
-	 * int console_a3700_flush(console_a3700_t *console)
+	 * int console_a3700_flush(console_t *console)
 	 * Function to force a write of all buffered
 	 * data that hasn't been output.
 	 * In : x0 - pointer to console_t structure
@@ -246,7 +246,7 @@
 	 * ---------------------------------------------
 	 */
 func console_a3700_flush
-	ldr	x0, [x0, #CONSOLE_T_A3700_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_a3700_core_flush
 endfunc console_a3700_flush
 
diff --git a/drivers/renesas/rcar/board/board.c b/drivers/renesas/rcar/board/board.c
index df17802..cd194ff 100644
--- a/drivers/renesas/rcar/board/board.c
+++ b/drivers/renesas/rcar/board/board.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights
+ * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights
  * reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -33,7 +33,7 @@
 #define SXS_ID	{ 0x10U, 0xFFU, 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 SK_ID	{ 0x10U, 0xFFU, 0xFFU, 0xFFU, 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 }
 #define DR_ID	{ 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
diff --git a/drivers/renesas/rcar/console/rcar_console.S b/drivers/renesas/rcar/console/rcar_console.S
index 859efec..4d006b7 100644
--- a/drivers/renesas/rcar/console/rcar_console.S
+++ b/drivers/renesas/rcar/console/rcar_console.S
@@ -20,14 +20,14 @@
 	/* -----------------------------------------------
 	 * int console_rcar_register(
 	 *      uintptr_t base, uint32_t clk, uint32_t baud,
-	 *      console_rcar_t *console)
+	 *      console_t *console)
 	 * Function to initialize and register a new rcar
 	 * console. Storage passed in for the console struct
 	 * *must* be persistent (i.e. not from the stack).
 	 * In: x0 - UART register base address
 	 *     w1 - UART clock in Hz
 	 *     w2 - Baud rate
-	 *     x3 - pointer to empty console_rcar_t struct
+	 *     x3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : x0, x1, x2, x6, x7, x14
 	 * -----------------------------------------------
@@ -36,7 +36,7 @@
 	mov	x7, x30
 	mov	x6, x3
 	cbz	x6, register_fail
-	str	x0, [x6, #CONSOLE_T_RCAR_BASE]
+	str	x0, [x6, #CONSOLE_T_BASE]
 
 	bl	rcar_log_init
 	cbz	x0, register_fail
@@ -68,11 +68,11 @@
 endfunc console_rcar_init
 
 	/* --------------------------------------------------------
-	 * int console_rcar_putc(int c, console_rcar_t *console)
+	 * int console_rcar_putc(int c, console_t *console)
 	 * Function to output a character over the console. It
 	 * returns the character printed on success or -1 on error.
 	 * In : w0 - character to be printed
-	 *      x1 - pointer to console_rcar_t structure
+	 *      x1 - pointer to console_t structure
 	 * Out : return -1 on error else return character.
 	 * Clobber list : x2
 	 * --------------------------------------------------------
diff --git a/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram.c b/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram.c
index 1d6e83a..ac83c9a 100644
--- a/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram.c
+++ b/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, Renesas Electronics Corporation.
+ * Copyright (c) 2015-2020, Renesas Electronics Corporation.
  * All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -510,6 +510,14 @@
 	dsb_sev();
 }
 
+static void dbwait_loop(uint32_t wait_loop)
+{
+	uint32_t i;
+
+	for (i = 0; i < wait_loop; i++)
+		wait_dbcmd();
+}
+
 /* DDRPHY register access (raw) */
 static uint32_t reg_ddrphy_read(uint32_t phyno, uint32_t regadd)
 {
@@ -866,6 +874,7 @@
 	uint8_t WL;
 	uint8_t nwr;
 	uint8_t nrtp;
+	uint8_t odtlon;
 	uint8_t MR1;
 	uint8_t MR2;
 };
@@ -877,21 +886,21 @@
 #define JS1_MR2(f) (0x00 | ((f) << 3) | (f))
 const struct _jedec_spec1 js1[JS1_FREQ_TBL_NUM] = {
 	/* 533.333Mbps */
-	{  800,  6,  6,  4,  6,  8, JS1_MR1(0), JS1_MR2(0) | 0x40 },
+	{  800,  6,  6,  4,  6,  8, 0, JS1_MR1(0), JS1_MR2(0) | 0x40 },
 	/* 1066.666Mbps */
-	{ 1600, 10, 12,  8, 10,  8, JS1_MR1(1), JS1_MR2(1) | 0x40 },
+	{ 1600, 10, 12,  8, 10,  8, 0, JS1_MR1(1), JS1_MR2(1) | 0x40 },
 	/* 1600.000Mbps */
-	{ 2400, 14, 16, 12, 16,  8, JS1_MR1(2), JS1_MR2(2) | 0x40 },
+	{ 2400, 14, 16, 12, 16,  8, 6, JS1_MR1(2), JS1_MR2(2) | 0x40 },
 	/* 2133.333Mbps */
-	{ 3200, 20, 22, 10, 20,  8, JS1_MR1(3), JS1_MR2(3) },
+	{ 3200, 20, 22, 10, 20,  8, 4, JS1_MR1(3), JS1_MR2(3) },
 	/* 2666.666Mbps */
-	{ 4000, 24, 28, 12, 24, 10, JS1_MR1(4), JS1_MR2(4) },
+	{ 4000, 24, 28, 12, 24, 10, 4, JS1_MR1(4), JS1_MR2(4) },
 	/* 3200.000Mbps */
-	{ 4800, 28, 32, 14, 30, 12, JS1_MR1(5), JS1_MR2(5) },
+	{ 4800, 28, 32, 14, 30, 12, 6, JS1_MR1(5), JS1_MR2(5) },
 	/* 3733.333Mbps */
-	{ 5600, 32, 36, 16, 34, 14, JS1_MR1(6), JS1_MR2(6) },
+	{ 5600, 32, 36, 16, 34, 14, 6, JS1_MR1(6), JS1_MR2(6) },
 	/* 4266.666Mbps */
-	{ 6400, 36, 40, 18, 40, 16, JS1_MR1(7), JS1_MR2(7) }
+	{ 6400, 36, 40, 18, 40, 16, 8, JS1_MR1(7), JS1_MR2(7) }
 };
 
 struct _jedec_spec2 {
@@ -921,7 +930,8 @@
 #define js2_tzqcalns 19
 #define js2_tzqlat 20
 #define js2_tiedly 21
-#define JS2_TBLCNT 22
+#define js2_tODTon_min 22
+#define JS2_TBLCNT 23
 
 #define js2_trcpb (JS2_TBLCNT)
 #define js2_trcab (JS2_TBLCNT + 1)
@@ -954,7 +964,8 @@
 /*tMRD*/ {14000, 10},
 /*tZQCALns*/ {1000 * 10, 0},
 /*tZQLAT*/ {30000, 10},
-/*tIEdly*/ {12500, 0}
+/*tIEdly*/ {12500, 0},
+/*tODTon_min*/ {1500, 0}
 	 }, {
 /*tSR   */ {15000, 3},
 /*tXP   */ {7500, 3},
@@ -977,7 +988,8 @@
 /*tMRD*/ {14000, 10},
 /*tZQCALns*/ {1000 * 10, 0},
 /*tZQLAT*/ {30000, 10},
-/*tIEdly*/ {12500, 0}
+/*tIEdly*/ {12500, 0},
+/*tODTon_min*/ {1500, 0}
 	}
 };
 
@@ -1452,7 +1464,7 @@
 	if ((prr_product == PRR_PRODUCT_M3N) ||
 	    (prr_product == PRR_PRODUCT_V3H)) {
 		ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET,
-			      _reg_PHY_RDDATA_EN_OE_DLY, dataS);
+			      _reg_PHY_RDDATA_EN_OE_DLY, dataS - 2);
 	}
 	ddrtbl_setval(_cnf_DDR_PI_REGSET, _reg_PI_RDLAT_ADJ_F1, RL - dataS);
 
@@ -1498,9 +1510,10 @@
 
 	/* DDRPHY INT START */
 	if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
-		/*  non */
+		/* non */
 	} else {
 		regif_pll_wa();
+		dbwait_loop(5);
 	}
 
 	/* FREQ_SEL_MULTICAST & PER_CS_TRAINING_MULTICAST SET (for safety) */
@@ -2067,12 +2080,18 @@
 	/* DBTR9.TRDPR : tRTP */
 	mmio_write_32(DBSC_DBTR(9), js2[js2_trtp]);
 
-	/* DBTR10.TWR : nwr */
+	/* DBTR10.TWR : nWR */
 	mmio_write_32(DBSC_DBTR(10), js1[js1_ind].nwr);
 
-	/* DBTR11.TRDWR : RL + tDQSCK + BL/2 + Rounddown(tRPST) - WL + tWPRE */
+	/*
+	 * DBTR11.TRDWR : RL +  BL / 2 + Rounddown(tRPST) + PHY_ODTLoff -
+	 * 		  odtlon + tDQSCK - tODTon,min +
+	 * 		  PCB delay (out+in) + tPHY_ODToff
+	 */
 	mmio_write_32(DBSC_DBTR(11),
-		      RL + js2[js2_tdqsck] + (16 / 2) + 1 - WL + 2 + 2);
+		      RL + (16 / 2) + 1 + 2 - js1[js1_ind].odtlon +
+		      js2[js2_tdqsck] - js2[js2_tODTon_min] +
+		      _f_scale(ddr_mbps, ddr_mbpsdiv, 1300, 0));
 
 	/* DBTR12.TWRRD : WL + 1 + BL/2 + tWTR */
 	data_l = WL + 1 + (16 / 2) + js2[js2_twtr];
@@ -2338,10 +2357,23 @@
 		}
 	}
 	if ((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) {
+#if RCAR_DRAM_SPLIT == 2
+		if (board_cnf->phyvalid == 0x05) {
+			mmio_write_32(DBSC_DBTR(24),
+				      (rdlat_max << 24) + (rdlat_min << 16) +
+				      mmio_read_32(DBSC_DBTR(24)));
+		} else {
+			mmio_write_32(DBSC_DBTR(24),
+				      ((rdlat_max * 2 - rdlat_min + 4) << 24) +
+				      ((rdlat_min + 2) << 16) +
+				      mmio_read_32(DBSC_DBTR(24)));
+		}
+#else /*RCAR_DRAM_SPLIT == 2 */
 		mmio_write_32(DBSC_DBTR(24),
 			      ((rdlat_max * 2 - rdlat_min + 4) << 24) +
 			      ((rdlat_min + 2) << 16) +
 			      mmio_read_32(DBSC_DBTR(24)));
+#endif /*RCAR_DRAM_SPLIT == 2 */
 	} else {
 		mmio_write_32(DBSC_DBTR(24),
 			      ((rdlat_max + 2) << 24) +
@@ -2383,37 +2415,6 @@
 	mmio_write_32(DBSC_DBRFCNF1, 0x00080000 | (data_l & 0x0000ffff));
 	mmio_write_32(DBSC_DBRFCNF2, 0x00010000 | DBSC_REFINTS);
 
-#ifdef DDR_BACKUPMODE
-	if (ddr_backup == DRAM_BOOT_STATUS_WARM) {
-#ifdef DDR_BACKUPMODE_HALF	/* for Half channel(ch0,1 only) */
-		DEBUG(" DEBUG_MESS : DDR_BACKUPMODE_HALF ", 1);
-		send_dbcmd(0x08040001);
-		wait_dbcmd();
-		send_dbcmd(0x0A040001);
-		wait_dbcmd();
-		send_dbcmd(0x04040010);
-		wait_dbcmd();
-
-		if (prr_product == PRR_PRODUCT_H3) {
-			send_dbcmd(0x08140001);
-			wait_dbcmd();
-			send_dbcmd(0x0A140001);
-			wait_dbcmd();
-			send_dbcmd(0x04140010);
-			wait_dbcmd();
-		}
-#else /* DDR_BACKUPMODE_HALF                              //for All channels */
-		send_dbcmd(0x08840001);
-		wait_dbcmd();
-		send_dbcmd(0x0A840001);
-		wait_dbcmd();
-
-		send_dbcmd(0x04840010);
-		wait_dbcmd();
-#endif /* DDR_BACKUPMODE_HALF */
-	}
-#endif /* DDR_BACKUPMODE */
-
 #if RCAR_REWT_TRAINING != 0
 	/* Periodic-WriteDQ Training seeting */
 	if (((prr_product == PRR_PRODUCT_H3) &&
@@ -2422,12 +2423,7 @@
 	     (prr_cut == PRR_PRODUCT_10))) {
 		/* non : H3 Ver.1.x/M3-W Ver.1.0 not support */
 	} else {
-		/*
-		 * H3 Ver.2.0 or later/M3-W Ver.1.1 or
-		 * later/M3-N/V3H -> Periodic-WriteDQ Training seeting
-		 */
-
-		/* Periodic WriteDQ Training seeting */
+		/* H3 Ver.2.0 or later/M3-W Ver.1.1 or later/M3-N/V3H */
 		mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000000);
 
 		ddr_setval_ach_as(_reg_PHY_WDQLVL_PATT, 0x04);
@@ -2440,7 +2436,6 @@
 					     _reg_PI_WDQLVL_CS_MAP));
 		ddr_setval_ach(_reg_PI_LONG_COUNT_MASK, 0x1f);
 		ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x00);
-		ddr_setval_ach(_reg_PI_WDQLVL_INTERVAL, 0x0100);
 		ddr_setval_ach(_reg_PI_WDQLVL_ROTATE, 0x01);
 		ddr_setval_ach(_reg_PI_TREF_F0, 0x0000);
 		ddr_setval_ach(_reg_PI_TREF_F1, 0x0000);
@@ -2458,8 +2453,10 @@
 		mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000011);
 	}
 #endif /* RCAR_REWT_TRAINING */
-	/* periodic dram zqcal and phy ctrl update enable */
+	/* periodic dram zqcal enable */
 	mmio_write_32(DBSC_DBCALCNF, 0x01000010);
+
+	/* periodic phy ctrl update enable */
 	if (((prr_product == PRR_PRODUCT_H3) &&
 	     (prr_cut <= PRR_PRODUCT_11)) ||
 	    ((prr_product == PRR_PRODUCT_M3) &&
@@ -2477,7 +2474,36 @@
 #endif /* RCAR_DRAM_SPLIT == 2 */
 	}
 
+#ifdef DDR_BACKUPMODE
+	/* SRX */
+	if (ddr_backup == DRAM_BOOT_STATUS_WARM) {
+#ifdef DDR_BACKUPMODE_HALF		/* for Half channel(ch0, 1 only) */
+		NOTICE("BL2: [DEBUG_MESS] DDR_BACKUPMODE_HALF\n");
+		send_dbcmd(0x0A040001);
+		if (Prr_Product == PRR_PRODUCT_H3)
+			send_dbcmd(0x0A140001);
+#else /* DDR_BACKUPMODE_HALF */		/* for All channels */
+		send_dbcmd(0x0A840001);
+#endif /* DDR_BACKUPMODE_HALF */
+	}
+#endif /* DDR_BACKUPMODE */
+
+	/* set Auto Refresh */
 	mmio_write_32(DBSC_DBRFEN, 0x00000001);
+
+#if RCAR_REWT_TRAINING != 0
+	/* Periodic WriteDQ Traning */
+	if (((prr_product == PRR_PRODUCT_H3) &&
+	     (prr_cut <= PRR_PRODUCT_11)) ||
+	    ((prr_product == PRR_PRODUCT_M3) &&
+	     (prr_cut == PRR_PRODUCT_10))) {
+		/* non : H3 Ver.1.x/M3-W Ver.1.0 not support */
+	} else {
+		/* H3 Ver.2.0 or later/M3-W Ver.1.1 or later/M3-N/V3H */
+		ddr_setval_ach(_reg_PI_WDQLVL_INTERVAL, 0x0100);
+	}
+#endif /* RCAR_REWT_TRAINING */
+
 	/* dram access enable */
 	mmio_write_32(DBSC_DBACEN, 0x00000001);
 
@@ -3026,6 +3052,9 @@
 		return INITDRAM_ERR_O;
 	MSG_LF(__func__ ":5\n");
 
+	/* Dummy PDE */
+	send_dbcmd(0x08840000);
+
 	/* PDX */
 	send_dbcmd(0x08840001);
 
@@ -3477,10 +3506,13 @@
 {
 	uint32_t err, retry_cnt;
 	const uint32_t retry_max = 0x10;
-	uint32_t ch, ddr_csn, mr14_bkup[4][4];
+	uint32_t datal, ch, ddr_csn, mr14_bkup[4][4];
+
+	datal = RL + js2[js2_tdqsck] + (16 / 2) + 1 - WL + 2 + 2 + 19;
+	if ((mmio_read_32(DBSC_DBTR(11)) & 0xFF) > datal)
+		datal = mmio_read_32(DBSC_DBTR(11)) & 0xFF;
+	ddr_setval_ach(_reg_PI_TDFI_WDQLVL_RW, datal);
 
-	ddr_setval_ach(_reg_PI_TDFI_WDQLVL_RW,
-		       (mmio_read_32(DBSC_DBTR(11)) & 0xFF) + 19);
 	if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) ||
 	    (prr_product == PRR_PRODUCT_M3N) ||
 	    (prr_product == PRR_PRODUCT_V3H)) {
diff --git a/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram_config.c b/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram_config.c
index f8caade..de126de 100644
--- a/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram_config.c
+++ b/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram_config.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, Renesas Electronics Corporation.
+ * Copyright (c) 2015-2020, Renesas Electronics Corporation.
  * All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -1571,8 +1571,13 @@
 {
 	uint32_t md;
 
-	md = (mmio_read_32(RST_MODEMR) >> 17) & 0x5;
-	md = (md | (md >> 1)) & 0x3;
+	if (prr_product == PRR_PRODUCT_V3H) {
+		md = (mmio_read_32(RST_MODEMR) >> 19) & 0x1;
+		md = (md | (md << 1)) & 0x3; /* 0 or 3 */
+	} else {
+		md = (mmio_read_32(RST_MODEMR) >> 17) & 0x5;
+		md = (md | (md >> 1)) & 0x3;
+	}
 	switch (md) {
 	case 0x0:
 		*mbps = 3200;
@@ -1722,8 +1727,13 @@
 #endif
 		}
 	} else if (prr_product == PRR_PRODUCT_M3) {
-		/* RENESAS Starter Kit(M3-W/SIP 8Gbit 1rank) board */
-		brd = 3;
+		if (prr_cut >= PRR_PRODUCT_30) {
+			/* RENESAS Starter Kit (M3-W Ver.3.0/SIP) */
+			brd = 18;
+		} else {
+			/* RENESAS Starter Kit(M3-W/SIP 8Gbit 1rank) board */
+			brd = 3;
+		}
 	} else {
 		/* RENESAS Starter Kit(M3-N/SIP) board */
 		brd = 11;
diff --git a/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram_regdef.h b/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram_regdef.h
index 5047e5c..56363eb 100644
--- a/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram_regdef.h
+++ b/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram_regdef.h
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2015-2019, Renesas Electronics Corporation.
+ * Copyright (c) 2015-2020, Renesas Electronics Corporation.
  * All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#define RCAR_DDR_VERSION	"rev.0.37"
+#define RCAR_DDR_VERSION	"rev.0.40"
 #define DRAM_CH_CNT		0x04
 #define SLICE_CNT		0x04
 #define CS_CNT			0x02
@@ -22,7 +22,7 @@
 
 /* for ddr deisity setting */
 #define DBMEMCONF_REG(d3, row, bank, col, dw)	\
-	((d3) << 30 | ((row) << 24) | ((bank) << 16) | ((col) << 8) | (dw))
+	(((d3) << 30) | ((row) << 24) | ((bank) << 16) | ((col) << 8) | (dw))
 
 #define DBMEMCONF_REGD(density)		\
 	(DBMEMCONF_REG((density) % 2, ((density) + 1) / \
diff --git a/drivers/renesas/rcar/ddr/ddr_b/init_dram_tbl_m3n.h b/drivers/renesas/rcar/ddr/ddr_b/init_dram_tbl_m3n.h
index 8d80842..fb3032d 100644
--- a/drivers/renesas/rcar/ddr/ddr_b/init_dram_tbl_m3n.h
+++ b/drivers/renesas/rcar/ddr/ddr_b/init_dram_tbl_m3n.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, Renesas Electronics Corporation.
+ * Copyright (c) 2015-2020, Renesas Electronics Corporation.
  * All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -116,7 +116,7 @@
 	/*0859*/ 0x00000200,
 	/*085a*/ 0x00000004,
 	/*085b*/ 0x4041a151,
-	/*085c*/ 0x0141c0a0,
+	/*085c*/ 0x0141a0a0,
 	/*085d*/ 0x0000c0c0,
 	/*085e*/ 0x0e0c000e,
 	/*085f*/ 0x10001000,
diff --git a/drivers/renesas/rcar/scif/scif.S b/drivers/renesas/rcar/scif/scif.S
index 8309bb2..064aba4 100644
--- a/drivers/renesas/rcar/scif/scif.S
+++ b/drivers/renesas/rcar/scif/scif.S
@@ -126,14 +126,14 @@
 	/* -----------------------------------------------
 	 * int console_rcar_register(
 	 *      uintptr_t base, uint32_t clk, uint32_t baud,
-	 *      console_rcar_t *console)
+	 *      console_t *console)
 	 * Function to initialize and register a new rcar
 	 * console. Storage passed in for the console struct
 	 * *must* be persistent (i.e. not from the stack).
 	 * In: x0 - UART register base address
 	 *     w1 - UART clock in Hz
 	 *     w2 - Baud rate
-	 *     x3 - pointer to empty console_rcar_t struct
+	 *     x3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : x0, x1, x2, x6, x7, x14
 	 * -----------------------------------------------
@@ -142,7 +142,7 @@
 	mov	x7, x30
 	mov	x6, x3
 	cbz	x6, register_fail
-	str	x0, [x6, #CONSOLE_T_RCAR_BASE]
+	str	x0, [x6, #CONSOLE_T_BASE]
 
 	bl	console_rcar_init
 
diff --git a/drivers/st/uart/aarch32/stm32_console.S b/drivers/st/uart/aarch32/stm32_console.S
index ca3c1f6..0ed37d1 100644
--- a/drivers/st/uart/aarch32/stm32_console.S
+++ b/drivers/st/uart/aarch32/stm32_console.S
@@ -91,14 +91,14 @@
 	/* -------------------------------------------------------
 	 * int console_stm32_register(uintptr_t baseaddr,
 	 *     uint32_t clock, uint32_t baud,
-	 *     struct console_stm32 *console);
+	 *     console_t *console);
 	 * Function to initialize and register a new STM32
 	 * console. Storage passed in for the console struct
 	 * *must* be persistent (i.e. not from the stack).
 	 * In: r0 - UART register base address
 	 *     r1 - UART clock in Hz
 	 *     r2 - Baud rate
-	 *     r3 - pointer to empty console_stm32 struct
+	 *     r3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : r0, r1, r2
 	 * -------------------------------------------------------
@@ -108,7 +108,7 @@
 	mov	r4, r3
 	cmp	r4, #0
 	beq	register_fail
-	str	r0, [r4, #CONSOLE_T_STM32_BASE]
+	str	r0, [r4, #CONSOLE_T_BASE]
 
 	bl console_stm32_core_init
 	cmp	r0, #0
@@ -157,7 +157,7 @@
 endfunc console_stm32_core_putc
 
 	/* ------------------------------------------------------------
-	 * int console_stm32_putc(int c, struct console_stm32 *console)
+	 * int console_stm32_putc(int c, console_t *console)
 	 * Function to output a character over the console. It
 	 * returns the character printed on success or -1 on error.
 	 * In: r0 - character to be printed
@@ -171,7 +171,7 @@
 	cmp	r1, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	r1, [r1, #CONSOLE_T_STM32_BASE]
+	ldr	r1, [r1, #CONSOLE_T_BASE]
 	b	console_stm32_core_putc
 endfunc console_stm32_putc
 
@@ -219,7 +219,7 @@
 endfunc console_stm32_core_flush
 
 	/* ------------------------------------------------------
-	 * int console_stm32_flush(struct console_stm32 *console)
+	 * int console_stm32_flush(console_t *console)
 	 * Function to force a write of all buffered
 	 * data that hasn't been output.
 	 * In : r0 - pointer to console_t structure
@@ -232,6 +232,6 @@
 	cmp	r0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	r0, [r0, #CONSOLE_T_STM32_BASE]
+	ldr	r0, [r0, #CONSOLE_T_BASE]
 	b	console_stm32_core_flush
 endfunc console_stm32_flush
diff --git a/drivers/ti/uart/aarch32/16550_console.S b/drivers/ti/uart/aarch32/16550_console.S
index 5cd9b30..bc0b3ab 100644
--- a/drivers/ti/uart/aarch32/16550_console.S
+++ b/drivers/ti/uart/aarch32/16550_console.S
@@ -91,7 +91,7 @@
 	/* -------------------------------------------------------
 	 * int console_16550_register(uintptr_t baseaddr,
 	 *     uint32_t clock, uint32_t baud,
-	 *     console_16550_t *console);
+	 *     console_t *console);
 	 * Function to initialize and register a new 16550
 	 * console. Storage passed in for the console struct
 	 * *must* be persistent (i.e. not from the stack).
@@ -101,7 +101,7 @@
 	 * In: r0 - UART register base address
 	 *     r1 - UART clock in Hz
 	 *     r2 - Baud rate (ignored if r1 is 0)
-	 *     r3 - pointer to empty console_16550_t struct
+	 *     r3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : r0, r1, r2
 	 * -------------------------------------------------------
@@ -111,7 +111,7 @@
 	mov	r4, r3
 	cmp	r4, #0
 	beq	register_fail
-	str	r0, [r4, #CONSOLE_T_16550_BASE]
+	str	r0, [r4, #CONSOLE_T_BASE]
 
 	/* A clock rate of zero means to skip the initialisation. */
 	cmp	r1, #0
@@ -167,7 +167,7 @@
 endfunc console_16550_core_putc
 
 	/* --------------------------------------------------------
-	 * int console_16550_putc(int c, console_16550_t *console)
+	 * int console_16550_putc(int c, console_t *console)
 	 * Function to output a character over the console. It
 	 * returns the character printed on success or -1 on error.
 	 * In : r0 - character to be printed
@@ -181,7 +181,7 @@
 	cmp	r1, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	r1, [r1, #CONSOLE_T_16550_BASE]
+	ldr	r1, [r1, #CONSOLE_T_BASE]
 	b	console_16550_core_putc
 endfunc console_16550_putc
 
@@ -213,7 +213,7 @@
 endfunc console_16550_core_getc
 
 	/* ---------------------------------------------
-	 * int console_16550_getc(console_16550_t *console)
+	 * int console_16550_getc(console_t *console)
 	 * Function to get a character from the console.
 	 * It returns the character grabbed on success
 	 * or -1 on if no character is available.
@@ -227,7 +227,7 @@
 	cmp	r0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	r0, [r0, #CONSOLE_T_16550_BASE]
+	ldr	r0, [r0, #CONSOLE_T_BASE]
 	b	console_16550_core_getc
 endfunc console_16550_getc
 
@@ -257,7 +257,7 @@
 endfunc console_16550_core_flush
 
 	/* ---------------------------------------------
-	 * int console_16550_flush(console_pl011_t *console)
+	 * int console_16550_flush(console_t *console)
 	 * Function to force a write of all buffered
 	 * data that hasn't been output.
 	 * In : r0 - pointer to console_t structure
@@ -270,6 +270,6 @@
 	cmp	r0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	r0, [r0, #CONSOLE_T_16550_BASE]
+	ldr	r0, [r0, #CONSOLE_T_BASE]
 	b	console_16550_core_flush
 endfunc console_16550_flush
diff --git a/drivers/ti/uart/aarch64/16550_console.S b/drivers/ti/uart/aarch64/16550_console.S
index 80c1b86..0640227 100644
--- a/drivers/ti/uart/aarch64/16550_console.S
+++ b/drivers/ti/uart/aarch64/16550_console.S
@@ -88,7 +88,7 @@
 	/* -----------------------------------------------
 	 * int console_16550_register(uintptr_t baseaddr,
 	 *     uint32_t clock, uint32_t baud,
-	 *     console_16550_t *console);
+	 *     console_t *console);
 	 * Function to initialize and register a new 16550
 	 * console. Storage passed in for the console struct
 	 * *must* be persistent (i.e. not from the stack).
@@ -98,7 +98,7 @@
 	 * In: x0 - UART register base address
 	 *     w1 - UART clock in Hz
 	 *     w2 - Baud rate (ignored if w1 is 0)
-	 *     x3 - pointer to empty console_16550_t struct
+	 *     x3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : x0, x1, x2, x6, x7, x14
 	 * -----------------------------------------------
@@ -107,7 +107,7 @@
 	mov	x7, x30
 	mov	x6, x3
 	cbz	x6, register_fail
-	str	x0, [x6, #CONSOLE_T_16550_BASE]
+	str	x0, [x6, #CONSOLE_T_BASE]
 
 	/* A clock rate of zero means to skip the initialisation. */
 	cbz	w1, register_16550
@@ -161,7 +161,7 @@
 endfunc console_16550_core_putc
 
 	/* --------------------------------------------------------
-	 * int console_16550_putc(int c, console_16550_t *console)
+	 * int console_16550_putc(int c, console_t *console)
 	 * Function to output a character over the console. It
 	 * returns the character printed on success or -1 on error.
 	 * In : w0 - character to be printed
@@ -175,7 +175,7 @@
 	cmp	x1, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x1, [x1, #CONSOLE_T_16550_BASE]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 	b	console_16550_core_putc
 endfunc console_16550_putc
 
@@ -206,7 +206,7 @@
 endfunc console_16550_core_getc
 
 	/* ---------------------------------------------
-	 * int console_16550_getc(console_16550_t *console)
+	 * int console_16550_getc(console_t *console)
 	 * Function to get a character from the console.
 	 * It returns the character grabbed on success
 	 * or -1 on if no character is available.
@@ -220,7 +220,7 @@
 	cmp	x1, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x0, [x0, #CONSOLE_T_16550_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_16550_core_getc
 endfunc console_16550_getc
 
@@ -250,7 +250,7 @@
 endfunc console_16550_core_flush
 
 	/* ---------------------------------------------
-	 * int console_16550_flush(console_pl011_t *console)
+	 * int console_16550_flush(console_t *console)
 	 * Function to force a write of all buffered
 	 * data that hasn't been output.
 	 * In : x0 - pointer to console_t structure
@@ -263,6 +263,6 @@
 	cmp	x0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x0, [x0, #CONSOLE_T_16550_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_16550_core_flush
 endfunc console_16550_flush
diff --git a/fdts/corstone700.dts b/fdts/corstone700.dts
index 16cf412..c13d3b2 100644
--- a/fdts/corstone700.dts
+++ b/fdts/corstone700.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,9 +14,10 @@
 	#size-cells = <1>;
 
 	chosen {
-		bootargs = "console=ttyAMA0 root=/dev/vda2 rw loglevel=9";
-		linux,initrd-start = <0x02a00000>;
-		linux,initrd-end = <0x04000000>;
+		bootargs = "console=ttyAMA0 \
+		root=mtd:physmap-flash.0 \
+		ro \
+		loglevel=9";
 	};
 
 	cpus {
@@ -32,9 +33,9 @@
 
 	};
 
-	memory@2000000 {
+	memory@80000000 {
 		device_type = "memory";
-		reg = <0x02000000 0x02000000>;
+		reg = <0x80000000 0x80000000>;
 	};
 
 	gic: interrupt-controller@1c000000 {
@@ -68,14 +69,21 @@
 		clock-output-names = "smclk";
 	};
 
+	uartclk: uartclk {
+		/* UART clock - 32MHz */
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32000000>;
+		clock-output-names = "uartclk";
+	};
 
 	serial0: uart@1a510000 {
 		compatible = "arm,pl011", "arm,primecell";
 		reg = <0x1a510000 0x1000>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 19 4>;
-		clocks = <&refclk100mhz>, <&smbclk>;
-		clock-names = "apb_pclk", "smclk";
+		clocks = <&uartclk>, <&refclk100mhz>;
+		clock-names = "uartclk", "apb_pclk";
 	};
 
 	serial1: uart@1a520000 {
@@ -83,8 +91,8 @@
 		reg = <0x1a520000 0x1000>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 20 4>;
-		clocks = <&refclk100mhz>, <&smbclk>;
-		clock-names = "apb_pclk", "smclk";
+		clocks = <&uartclk>, <&refclk100mhz>;
+		clock-names = "uartclk", "apb_pclk";
 	};
 
 	timer {
diff --git a/fdts/fvp-base-gicv3-psci-common.dtsi b/fdts/fvp-base-gicv3-psci-common.dtsi
index 94ed67d..5b0470d 100644
--- a/fdts/fvp-base-gicv3-psci-common.dtsi
+++ b/fdts/fvp-base-gicv3-psci-common.dtsi
@@ -39,7 +39,7 @@
 		#address-cells = <2>;
 		#size-cells = <0>;
 
-		cpu-map {
+		CPU_MAP:cpu-map {
 			cluster0 {
 				core0 {
 					cpu = <&CPU0>;
diff --git a/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts b/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts
index 48269a0..daa2e66 100644
--- a/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts
+++ b/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts
@@ -6,7 +6,7 @@
 
 /dts-v1/;
 
-#include "fvp-base-gicv3-psci-common.dtsi"
+#include "fvp-base-gicv3-psci-dynamiq-common.dtsi"
 
 &CPU0 {
 	reg = <0x0 0x0>;
diff --git a/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi b/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi
new file mode 100644
index 0000000..f3f7684
--- /dev/null
+++ b/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+#include "fvp-base-gicv3-psci-common.dtsi"
+
+/* DynamIQ based designs have upto 8 CPUs in each cluster */
+
+&CPU_MAP {
+	cluster0 {
+		core0 {
+			cpu = <&CPU0>;
+		};
+		core1 {
+			cpu = <&CPU1>;
+		};
+		core2 {
+			cpu = <&CPU2>;
+		};
+		core3 {
+			cpu = <&CPU3>;
+		};
+		core4 {
+			cpu = <&CPU4>;
+		};
+		core5 {
+			cpu = <&CPU5>;
+		};
+		core6 {
+			cpu = <&CPU6>;
+		};
+		core7 {
+			cpu = <&CPU7>;
+		};
+	};
+};
diff --git a/fdts/fvp-base-gicv3-psci-dynamiq.dts b/fdts/fvp-base-gicv3-psci-dynamiq.dts
index 51c7aca..b8b0445 100644
--- a/fdts/fvp-base-gicv3-psci-dynamiq.dts
+++ b/fdts/fvp-base-gicv3-psci-dynamiq.dts
@@ -6,7 +6,7 @@
 
 /dts-v1/;
 
-#include "fvp-base-gicv3-psci-common.dtsi"
+#include "fvp-base-gicv3-psci-dynamiq-common.dtsi"
 
 &CPU0 {
 	reg = <0x0 0x0>;
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 1fcd0f9..1faddbe 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -597,6 +598,10 @@
 #define CNTP_CTL_IMASK_MASK     U(1)
 #define CNTP_CTL_ISTATUS_MASK   U(1)
 
+/* Physical timer control macros */
+#define CNTP_CTL_ENABLE_BIT	(U(1) << CNTP_CTL_ENABLE_SHIFT)
+#define CNTP_CTL_IMASK_BIT	(U(1) << CNTP_CTL_IMASK_SHIFT)
+
 /* Exception Syndrome register bits and bobs */
 #define ESR_EC_SHIFT			U(26)
 #define ESR_EC_MASK			U(0x3f)
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index c60f2e8..240c1fb 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -69,6 +69,13 @@
 	__asm__ (#_op);					\
 }
 
+/* Define function for system instruction with register parameter */
+#define DEFINE_SYSOP_PARAM_FUNC(_op)			\
+static inline void _op(uint64_t v)			\
+{							\
+	 __asm__ (#_op "  %0" : : "r" (v));		\
+}
+
 /* Define function for system instruction with type specifier */
 #define DEFINE_SYSOP_TYPE_FUNC(_op, _type)		\
 static inline void _op ## _type(void)			\
@@ -211,6 +218,11 @@
 DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s1e2r)
 DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s1e3r)
 
+/*******************************************************************************
+ * Strip Pointer Authentication Code
+ ******************************************************************************/
+DEFINE_SYSOP_PARAM_FUNC(xpaci)
+
 void flush_dcache_range(uintptr_t addr, size_t size);
 void clean_dcache_range(uintptr_t addr, size_t size);
 void inv_dcache_range(uintptr_t addr, size_t size);
diff --git a/include/bl1/bl1.h b/include/bl1/bl1.h
index d81f434..e6447f2 100644
--- a/include/bl1/bl1.h
+++ b/include/bl1/bl1.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -67,16 +67,16 @@
 
 struct entry_point_info;
 
-register_t bl1_smc_wrapper(uint32_t smc_fid,
+u_register_t bl1_smc_wrapper(uint32_t smc_fid,
 	void *cookie,
 	void *handle,
 	unsigned int flags);
 
-register_t bl1_smc_handler(unsigned int smc_fid,
-	register_t x1,
-	register_t x2,
-	register_t x3,
-	register_t x4,
+u_register_t bl1_smc_handler(unsigned int smc_fid,
+	u_register_t x1,
+	u_register_t x2,
+	u_register_t x3,
+	u_register_t x4,
 	void *cookie,
 	void *handle,
 	unsigned int flags);
diff --git a/include/drivers/amlogic/meson_console.h b/include/drivers/amlogic/meson_console.h
index 70e3b0b..8d52d79 100644
--- a/include/drivers/amlogic/meson_console.h
+++ b/include/drivers/amlogic/meson_console.h
@@ -9,17 +9,10 @@
 
 #include <drivers/console.h>
 
-#define CONSOLE_T_MESON_BASE	CONSOLE_T_DRVDATA
-
 #ifndef __ASSEMBLER__
 
 #include <stdint.h>
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_meson_t;
-
 /*
  * Initialize a new meson console instance and register it with the console
  * framework. The |console| pointer must point to storage that will be valid
@@ -30,7 +23,7 @@
  * order to make this function future-proof.
  */
 int console_meson_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			   console_meson_t *console);
+			   console_t *console);
 
 #endif /*__ASSEMBLER__*/
 
diff --git a/include/drivers/arm/css/css_mhu_doorbell.h b/include/drivers/arm/css/css_mhu_doorbell.h
index e6f7a1b..88302fd 100644
--- a/include/drivers/arm/css/css_mhu_doorbell.h
+++ b/include/drivers/arm/css/css_mhu_doorbell.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,13 +11,13 @@
 
 #include <lib/mmio.h>
 
-/* MHUv2 Base Address */
-#define MHUV2_BASE_ADDR		PLAT_MHUV2_BASE
+/* MHUv2 Frame Base Mask */
+#define MHU_V2_FRAME_BASE_MASK			UL(~0xFFF)
 
 /* MHUv2 Control Registers Offsets */
-#define MHU_V2_MSG_NO_CAP_OFFSET		0xF80
-#define MHU_V2_ACCESS_REQ_OFFSET		0xF88
-#define MHU_V2_ACCESS_READY_OFFSET		0xF8C
+#define MHU_V2_MSG_NO_CAP_OFFSET		UL(0xF80)
+#define MHU_V2_ACCESS_REQ_OFFSET		UL(0xF88)
+#define MHU_V2_ACCESS_READY_OFFSET		UL(0xF8C)
 
 #define SENDER_REG_STAT(_channel)	(0x20 * (_channel))
 #define SENDER_REG_SET(_channel)	((0x20 * (_channel)) + 0xC)
diff --git a/include/drivers/arm/css/scmi.h b/include/drivers/arm/css/scmi.h
index 1f8dc6c..e8a2863 100644
--- a/include/drivers/arm/css/scmi.h
+++ b/include/drivers/arm/css/scmi.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
  */
@@ -162,7 +162,7 @@
 int scmi_ap_core_get_reset_addr(void *p, uint64_t *reset_addr, uint32_t *attr);
 
 /* API to get the platform specific SCMI channel information. */
-scmi_channel_plat_info_t *plat_css_get_scmi_info(void);
+scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id);
 
 /* API to override default PSCI callbacks for platforms that support SCMI. */
 const plat_psci_ops_t *css_scmi_override_pm_ops(plat_psci_ops_t *ops);
diff --git a/include/drivers/arm/pl011.h b/include/drivers/arm/pl011.h
index 8733d19..ebc6643 100644
--- a/include/drivers/arm/pl011.h
+++ b/include/drivers/arm/pl011.h
@@ -81,17 +81,10 @@
 
 #endif /* !PL011_GENERIC_UART */
 
-#define CONSOLE_T_PL011_BASE	CONSOLE_T_DRVDATA
-
 #ifndef __ASSEMBLER__
 
 #include <stdint.h>
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_pl011_t;
-
 /*
  * Initialize a new PL011 console instance and register it with the console
  * framework. The |console| pointer must point to storage that will be valid
@@ -99,7 +92,7 @@
  * Its contents will be reinitialized from scratch.
  */
 int console_pl011_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			   console_pl011_t *console);
+			   console_t *console);
 
 #endif /*__ASSEMBLER__*/
 
diff --git a/include/drivers/cadence/cdns_uart.h b/include/drivers/cadence/cdns_uart.h
index 64a062c..46ba466 100644
--- a/include/drivers/cadence/cdns_uart.h
+++ b/include/drivers/cadence/cdns_uart.h
@@ -25,17 +25,10 @@
 #define R_UART_TX	0x30
 #define R_UART_RX	0x30
 
-#define CONSOLE_T_CDNS_BASE	CONSOLE_T_DRVDATA
-
 #ifndef __ASSEMBLER__
 
 #include <stdint.h>
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_cdns_t;
-
 /*
  * Initialize a new Cadence console instance and register it with the console
  * framework. The |console| pointer must point to storage that will be valid
@@ -43,7 +36,7 @@
  * Its contents will be reinitialized from scratch.
  */
 int console_cdns_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			  console_cdns_t *console);
+			  console_t *console);
 
 #endif /*__ASSEMBLER__*/
 
diff --git a/include/drivers/console.h b/include/drivers/console.h
index a4859d8..761816a 100644
--- a/include/drivers/console.h
+++ b/include/drivers/console.h
@@ -14,7 +14,8 @@
 #define CONSOLE_T_PUTC			(U(2) * REGSZ)
 #define CONSOLE_T_GETC			(U(3) * REGSZ)
 #define CONSOLE_T_FLUSH			(U(4) * REGSZ)
-#define CONSOLE_T_DRVDATA		(U(5) * REGSZ)
+#define CONSOLE_T_BASE			(U(5) * REGSZ)
+#define CONSOLE_T_DRVDATA		(U(6) * REGSZ)
 
 #define CONSOLE_FLAG_BOOT		(U(1) << 0)
 #define CONSOLE_FLAG_RUNTIME		(U(1) << 1)
@@ -43,6 +44,7 @@
 	int (*const putc)(int character, struct console *console);
 	int (*const getc)(struct console *console);
 	int (*const flush)(struct console *console);
+	uintptr_t base;
 	/* Additional private driver data may follow here. */
 } console_t;
 
diff --git a/include/drivers/coreboot/cbmem_console.h b/include/drivers/coreboot/cbmem_console.h
index 40c90e6..30b39f1 100644
--- a/include/drivers/coreboot/cbmem_console.h
+++ b/include/drivers/coreboot/cbmem_console.h
@@ -9,14 +9,12 @@
 
 #include <drivers/console.h>
 
-#define CONSOLE_T_CBMC_BASE	CONSOLE_T_DRVDATA
-#define CONSOLE_T_CBMC_SIZE	(CONSOLE_T_DRVDATA + REGSZ)
+#define CONSOLE_T_CBMC_SIZE	CONSOLE_T_DRVDATA
 
 #ifndef __ASSEMBLER__
 
 typedef struct {
 	console_t console;
-	uintptr_t base;
 	uint32_t size;
 } console_cbmc_t;
 
diff --git a/include/drivers/io/io_storage.h b/include/drivers/io/io_storage.h
index 0e6ffd6..a301ad5 100644
--- a/include/drivers/io/io_storage.h
+++ b/include/drivers/io/io_storage.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -53,7 +53,7 @@
 /* UUID specification - used to refer to data accessed using UUIDs (i.e. FIP
  * images) */
 typedef struct io_uuid_spec {
-	const uuid_t uuid;
+	uuid_t uuid;
 } io_uuid_spec_t;
 
 /* Block specification - used to refer to data on a device supporting
diff --git a/include/drivers/marvell/mochi/cp110_setup.h b/include/drivers/marvell/mochi/cp110_setup.h
index 3686257..f8cd26b 100644
--- a/include/drivers/marvell/mochi/cp110_setup.h
+++ b/include/drivers/marvell/mochi/cp110_setup.h
@@ -51,5 +51,6 @@
 
 void cp110_init(uintptr_t cp110_base, uint32_t stream_id);
 void cp110_ble_init(uintptr_t cp110_base);
+void cp110_amb_init(uintptr_t base);
 
 #endif /* CP110_SETUP_H */
diff --git a/include/drivers/marvell/uart/a3700_console.h b/include/drivers/marvell/uart/a3700_console.h
index 517f01a..5e3ab05 100644
--- a/include/drivers/marvell/uart/a3700_console.h
+++ b/include/drivers/marvell/uart/a3700_console.h
@@ -54,17 +54,10 @@
 #define UART_CTRL_TXFIFO_RESET	(1 << 15)
 #define UARTLSR_TXFIFOEMPTY	(1 << 6)
 
-#define CONSOLE_T_A3700_BASE	CONSOLE_T_DRVDATA
-
 #ifndef __ASSEMBLER__
 
 #include <stdint.h>
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_a3700_t;
-
 /*
  * Initialize a new a3700 console instance and register it with the console
  * framework. The |console| pointer must point to storage that will be valid
@@ -72,7 +65,7 @@
  * Its contents will be reinitialized from scratch.
  */
 int console_a3700_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			   console_a3700_t *console);
+			   console_t *console);
 
 #endif /*__ASSEMBLER__*/
 
diff --git a/include/drivers/renesas/rcar/console/console.h b/include/drivers/renesas/rcar/console/console.h
index 0e4ed8f..7d5b5d3 100644
--- a/include/drivers/renesas/rcar/console/console.h
+++ b/include/drivers/renesas/rcar/console/console.h
@@ -7,17 +7,10 @@
 #ifndef RCAR_PRINTF_H
 #define RCAR_PRINTF_H
 
-#define CONSOLE_T_RCAR_BASE	CONSOLE_T_DRVDATA
-
 #ifndef __ASSEMBLER__
 
 #include <stdint.h>
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_rcar_t;
-
 /*
  * Initialize a new rcar console instance and register it with the console
  * framework. The |console| pointer must point to storage that will be valid
@@ -25,7 +18,7 @@
  * Its contents will be reinitialized from scratch.
  */
 int console_rcar_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			  console_rcar_t *console);
+			  console_t *console);
 
 #endif /*__ASSEMBLER__*/
 
diff --git a/include/drivers/st/stm32_console.h b/include/drivers/st/stm32_console.h
index a2ad87c..8d9187d 100644
--- a/include/drivers/st/stm32_console.h
+++ b/include/drivers/st/stm32_console.h
@@ -9,17 +9,10 @@
 
 #include <drivers/console.h>
 
-#define CONSOLE_T_STM32_BASE	CONSOLE_T_DRVDATA
-
 #ifndef __ASSEMBLER__
 
 #include <stdint.h>
 
-struct console_stm32 {
-	console_t console;
-	uintptr_t base;
-};
-
 /*
  * Initialize a new STM32 console instance and register it with the console
  * framework. The |console| pointer must point to storage that will be valid
@@ -27,7 +20,7 @@
  * Its contents will be reinitialized from scratch.
  */
 int console_stm32_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			   struct console_stm32 *console);
+			   console_t *console);
 
 #endif /*__ASSEMBLER__*/
 
diff --git a/include/drivers/ti/uart/uart_16550.h b/include/drivers/ti/uart/uart_16550.h
index 2b95fa3..bddd997 100644
--- a/include/drivers/ti/uart/uart_16550.h
+++ b/include/drivers/ti/uart/uart_16550.h
@@ -71,17 +71,10 @@
 #define UARTLSR_RDR_BIT		(0)		/* Rx Data Ready Bit */
 #define UARTLSR_RDR		(1 << UARTLSR_RDR_BIT)	/* Rx Data Ready */
 
-#define CONSOLE_T_16550_BASE	CONSOLE_T_DRVDATA
-
 #ifndef __ASSEMBLER__
 
 #include <stdint.h>
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_16550_t;
-
 /*
  * Initialize a new 16550 console instance and register it with the console
  * framework. The |console| pointer must point to storage that will be valid
@@ -94,7 +87,7 @@
  * case as well.
  */
 int console_16550_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			   console_16550_t *console);
+			   console_t *console);
 
 #endif /*__ASSEMBLER__*/
 
diff --git a/include/lib/cpus/aarch64/cortex_a57.h b/include/lib/cpus/aarch64/cortex_a57.h
index 102ff60..dc40e31 100644
--- a/include/lib/cpus/aarch64/cortex_a57.h
+++ b/include/lib/cpus/aarch64/cortex_a57.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -54,6 +55,7 @@
 #define CORTEX_A57_CPUACTLR_EL1_FORCE_FPSCR_FLUSH	(ULL(1) << 38)
 #define CORTEX_A57_CPUACTLR_EL1_DIS_INSTR_PREFETCH	(ULL(1) << 32)
 #define CORTEX_A57_CPUACTLR_EL1_DIS_STREAMING		(ULL(3) << 27)
+#define CORTEX_A57_CPUACTLR_EL1_EN_NC_LOAD_FWD		(ULL(1) << 24)
 #define CORTEX_A57_CPUACTLR_EL1_DIS_L1_STREAMING	(ULL(3) << 25)
 #define CORTEX_A57_CPUACTLR_EL1_DIS_INDIRECT_PREDICTOR	(ULL(1) << 4)
 
diff --git a/include/lib/cpus/aarch64/cortex_klein.h b/include/lib/cpus/aarch64/cortex_klein.h
new file mode 100644
index 0000000..729b3bf
--- /dev/null
+++ b/include/lib/cpus/aarch64/cortex_klein.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CORTEX_KLEIN_H
+#define CORTEX_KLEIN_H
+
+#define CORTEX_KLEIN_MIDR					U(0x410FD460)
+
+/*******************************************************************************
+ * CPU Extended Control register specific definitions
+ ******************************************************************************/
+#define CORTEX_KLEIN_CPUECTLR_EL1				S3_0_C15_C1_4
+
+/*******************************************************************************
+ * CPU Power Control register specific definitions
+ ******************************************************************************/
+#define CORTEX_KLEIN_CPUPWRCTLR_EL1				S3_0_C15_C2_7
+#define CORTEX_KLEIN_CPUPWRCTLR_EL1_CORE_PWRDN_BIT		U(1)
+
+#endif /* CORTEX_KLEIN_H */
diff --git a/include/lib/cpus/aarch64/cortex_matterhorn.h b/include/lib/cpus/aarch64/cortex_matterhorn.h
new file mode 100644
index 0000000..0185533
--- /dev/null
+++ b/include/lib/cpus/aarch64/cortex_matterhorn.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CORTEX_MATTERHORN_H
+#define CORTEX_MATTERHORN_H
+
+#define CORTEX_MATTERHORN_MIDR					U(0x410FD470)
+
+/*******************************************************************************
+ * CPU Extended Control register specific definitions
+ ******************************************************************************/
+#define CORTEX_MATTERHORN_CPUECTLR_EL1				S3_0_C15_C1_4
+
+/*******************************************************************************
+ * CPU Power Control register specific definitions
+ ******************************************************************************/
+#define CORTEX_MATTERHORN_CPUPWRCTLR_EL1			S3_0_C15_C2_7
+#define CORTEX_MATTERHORN_CPUPWRCTLR_EL1_CORE_PWRDN_BIT		U(1)
+
+#endif /* CORTEX_MATTERHORN_H */
diff --git a/include/lib/el3_runtime/aarch32/context.h b/include/lib/el3_runtime/aarch32/context.h
index c5567c9..5604c8e 100644
--- a/include/lib/el3_runtime/aarch32/context.h
+++ b/include/lib/el3_runtime/aarch32/context.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -37,7 +37,7 @@
 #define WORD_SHIFT		U(2)
 #define DEFINE_REG_STRUCT(name, num_regs)	\
 	typedef struct name {			\
-		uint32_t _regs[num_regs];	\
+		uint32_t ctx_regs[num_regs];	\
 	}  __aligned(8) name##_t
 
 /* Constants to determine the size of individual context structures */
@@ -47,8 +47,8 @@
 
 #undef CTX_REG_ALL
 
-#define read_ctx_reg(ctx, offset)	((ctx)->_regs[offset >> WORD_SHIFT])
-#define write_ctx_reg(ctx, offset, val)	(((ctx)->_regs[offset >> WORD_SHIFT]) \
+#define read_ctx_reg(ctx, offset)	((ctx)->ctx_regs[offset >> WORD_SHIFT])
+#define write_ctx_reg(ctx, offset, val)	(((ctx)->ctx_regs[offset >> WORD_SHIFT]) \
 					 = val)
 typedef struct cpu_context {
 	regs_t regs_ctx;
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index 7a1f3a3..4158c02 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -230,7 +230,7 @@
 #define DWORD_SHIFT		U(3)
 #define DEFINE_REG_STRUCT(name, num_regs)	\
 	typedef struct name {			\
-		uint64_t _regs[num_regs];	\
+		uint64_t ctx_regs[num_regs];	\
 	}  __aligned(16) name##_t
 
 /* Constants to determine the size of individual context structures */
@@ -288,8 +288,8 @@
  * Macros to access members of any of the above structures using their
  * offsets
  */
-#define read_ctx_reg(ctx, offset)	((ctx)->_regs[(offset) >> DWORD_SHIFT])
-#define write_ctx_reg(ctx, offset, val)	(((ctx)->_regs[(offset) >> DWORD_SHIFT]) \
+#define read_ctx_reg(ctx, offset)	((ctx)->ctx_regs[(offset) >> DWORD_SHIFT])
+#define write_ctx_reg(ctx, offset, val)	(((ctx)->ctx_regs[(offset) >> DWORD_SHIFT]) \
 					 = (uint64_t) (val))
 
 /*
diff --git a/include/lib/fconf/fconf.h b/include/lib/fconf/fconf.h
new file mode 100644
index 0000000..f58ff57
--- /dev/null
+++ b/include/lib/fconf/fconf.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FCONF_H
+#define FCONF_H
+
+#include <stdint.h>
+
+/* Public API */
+#define FCONF_GET_PROPERTY(a, b, c)	a##__##b##_getter(c)
+
+#define FCONF_REGISTER_POPULATOR(name, callback)				\
+	__attribute__((used, section(".fconf_populator")))			\
+	const struct fconf_populator name##__populator = {			\
+		.info = #name,							\
+		.populate = callback						\
+	};
+
+/*
+ * Populator callback
+ *
+ * This structure are used by the fconf_populate function and should only be
+ * defined by the FCONF_REGISTER_POPULATOR macro.
+ */
+struct fconf_populator {
+	/* Description of the data loaded by the callback */
+	const char *info;
+
+	/* Callback used by fconf_populate function with a provided config dtb.
+	 * Return 0 on success, err_code < 0 otherwise.
+	 */
+	int (*populate)(uintptr_t config);
+};
+
+/* Load firmware configuration dtb */
+void fconf_load_config(void);
+
+/* Top level populate function
+ *
+ * This function takes a configuration dtb and calls all the registered
+ * populator callback with it.
+ *
+ *  Panic on error.
+ */
+void fconf_populate(uintptr_t config);
+
+/* FCONF specific getter */
+#define fconf__dtb_getter(prop)	fconf_dtb_info.prop
+
+/* Structure used to locally keep a reference to the config dtb. */
+struct fconf_dtb_info_t {
+	uintptr_t base_addr;
+	size_t size;
+};
+
+extern struct fconf_dtb_info_t fconf_dtb_info;
+
+#endif /* FCONF_H */
diff --git a/include/lib/fconf/fconf_dyn_cfg_getter.h b/include/lib/fconf/fconf_dyn_cfg_getter.h
new file mode 100644
index 0000000..0fda8c9
--- /dev/null
+++ b/include/lib/fconf/fconf_dyn_cfg_getter.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FCONF_DYN_CFG_GETTER_H
+#define FCONF_DYN_CFG_GETTER_H
+
+#include <lib/fconf/fconf.h>
+
+/* Dynamic configuration related getter */
+#define dyn_cfg__dtb_getter(id)	dyn_cfg_dtb_info_getter(id)
+
+struct dyn_cfg_dtb_info_t {
+	uintptr_t config_addr;
+	size_t config_max_size;
+	unsigned int config_id;
+};
+
+struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id);
+int fconf_populate_dtb_registry(uintptr_t config);
+
+#endif /* FCONF_DYN_CFG_GETTER_H */
diff --git a/include/lib/fconf/fconf_tbbr_getter.h b/include/lib/fconf/fconf_tbbr_getter.h
new file mode 100644
index 0000000..eddc0c4
--- /dev/null
+++ b/include/lib/fconf/fconf_tbbr_getter.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FCONF_TBBR_GETTER_H
+#define FCONF_TBBR_GETTER_H
+
+#include <lib/fconf/fconf.h>
+
+/* TBBR related getter */
+#define tbbr__cot_getter(id)	cot_desc_ptr[id]
+
+#define tbbr__dyn_config_getter(id)	tbbr_dyn_config.id
+
+struct tbbr_dyn_config_t {
+	uint32_t disable_auth;
+	void *mbedtls_heap_addr;
+	size_t mbedtls_heap_size;
+};
+
+extern struct tbbr_dyn_config_t tbbr_dyn_config;
+
+int fconf_populate_tbbr_dyn_config(uintptr_t config);
+
+#endif /* FCONF_TBBR_GETTER_H */
diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h
index 23f59bd..09ae399 100644
--- a/include/lib/utils_def.h
+++ b/include/lib/utils_def.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -157,4 +158,9 @@
 # define SPECULATION_SAFE_VALUE(var) var
 #endif
 
+/*
+ * Ticks elapsed in one second with a signal of 1 MHz
+ */
+#define MHZ_TICKS_PER_SEC	U(1000000)
+
 #endif /* UTILS_DEF_H */
diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h
index 0e09998..a80fab0 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-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -345,6 +345,16 @@
 				   size_t size, uint32_t attr);
 int xlat_change_mem_attributes(uintptr_t base_va, size_t size, uint32_t attr);
 
+#if PLAT_RO_XLAT_TABLES
+/*
+ * Change the memory attributes of the memory region encompassing the higher
+ * level translation tables to secure read-only data.
+ *
+ * Return 0 on success, a negative error code on error.
+ */
+int xlat_make_tables_readonly(void);
+#endif
+
 /*
  * Query the memory attributes of a memory page in a set of translation tables.
  *
diff --git a/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
index b17b71a..c88fa4d 100644
--- a/include/lib/xlat_tables/xlat_tables_v2_helpers.h
+++ b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -70,6 +70,9 @@
 	 */
 	uint64_t (*tables)[XLAT_TABLE_ENTRIES];
 	int tables_num;
+#if PLAT_RO_XLAT_TABLES
+	bool readonly_tables;
+#endif
 	/*
 	 * Keep track of how many regions are mapped in each table. The base
 	 * table can't be unmapped so it isn't needed to keep track of it.
@@ -122,6 +125,14 @@
 	/* do nothing */
 #endif /* PLAT_XLAT_TABLES_DYNAMIC */
 
+#if PLAT_RO_XLAT_TABLES
+#define XLAT_CTX_INIT_TABLE_ATTR()					\
+	.readonly_tables = false,
+#else
+#define XLAT_CTX_INIT_TABLE_ATTR()
+	/* do nothing */
+#endif
+
 #define REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count,		\
 			_xlat_tables_count, _virt_addr_space_size,	\
 			_phy_addr_space_size, _xlat_regime, _section_name)\
@@ -142,22 +153,63 @@
 	XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count)		\
 									\
 	static xlat_ctx_t _ctx_name##_xlat_ctx = {			\
-		.va_max_address = (_virt_addr_space_size) - 1UL,	\
 		.pa_max_address = (_phy_addr_space_size) - 1ULL,	\
+		.va_max_address = (_virt_addr_space_size) - 1UL,	\
 		.mmap = _ctx_name##_mmap,				\
 		.mmap_num = (_mmap_count),				\
-		.base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size),\
+		.tables = _ctx_name##_xlat_tables,			\
+		.tables_num = _xlat_tables_count,			\
+		 XLAT_CTX_INIT_TABLE_ATTR()				\
+		 XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name)			\
+		.next_table = 0,					\
 		.base_table = _ctx_name##_base_xlat_table,		\
 		.base_table_entries =					\
 			GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size),\
+		.max_pa = 0U,						\
+		.max_va = 0U,						\
+		.base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size),\
+		.initialized = false,					\
+		.xlat_regime = (_xlat_regime)				\
+	}
+
+#define REGISTER_XLAT_CONTEXT_RO_BASE_TABLE(_ctx_name, _mmap_count,	\
+			_xlat_tables_count, _virt_addr_space_size,	\
+			_phy_addr_space_size, _xlat_regime, _section_name)\
+	CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(_phy_addr_space_size),	\
+		assert_invalid_physical_addr_space_sizefor_##_ctx_name);\
+									\
+	static mmap_region_t _ctx_name##_mmap[_mmap_count + 1];		\
+									\
+	static uint64_t _ctx_name##_xlat_tables[_xlat_tables_count]	\
+		[XLAT_TABLE_ENTRIES]					\
+		__aligned(XLAT_TABLE_SIZE) __section(_section_name);	\
+									\
+	static uint64_t _ctx_name##_base_xlat_table			\
+		[GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)]	\
+		__aligned(GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)\
+			* sizeof(uint64_t))				\
+		__section(".rodata");					\
+									\
+	XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count)		\
+									\
+	static xlat_ctx_t _ctx_name##_xlat_ctx = {			\
+		.pa_max_address = (_phy_addr_space_size) - 1ULL,	\
+		.va_max_address = (_virt_addr_space_size) - 1UL,	\
+		.mmap = _ctx_name##_mmap,				\
+		.mmap_num = (_mmap_count),				\
 		.tables = _ctx_name##_xlat_tables,			\
 		.tables_num = _xlat_tables_count,			\
+		 XLAT_CTX_INIT_TABLE_ATTR()				\
 		 XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name)			\
-		.xlat_regime = (_xlat_regime),				\
+		.next_table = 0,					\
+		.base_table = _ctx_name##_base_xlat_table,		\
+		.base_table_entries =					\
+			GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size),\
 		.max_pa = 0U,						\
 		.max_va = 0U,						\
-		.next_table = 0,					\
+		.base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size),\
 		.initialized = false,					\
+		.xlat_regime = (_xlat_regime)				\
 	}
 
 #endif /*__ASSEMBLER__*/
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 5bd53f3..7df6b0d 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -18,6 +18,12 @@
  * Definitions common to all ARM standard platforms
  *****************************************************************************/
 
+/*
+ * Root of trust key hash lengths
+ */
+#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)
 
@@ -223,6 +229,14 @@
 						ARM_EL3_TZC_DRAM1_SIZE,	\
 						MT_MEMORY | MT_RW | MT_SECURE)
 
+#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)
+#endif
+
+
 /*
  * Mapping for the BL1 RW region. This mapping is needed by BL2 in order to
  * share the Mbed TLS heap. Since the heap is allocated inside BL1, it resides
@@ -471,6 +485,12 @@
 #  define BL32_BASE			(ARM_AP_TZC_DRAM1_BASE + ULL(0x200000))
 #  define BL32_LIMIT			(ARM_AP_TZC_DRAM1_BASE +	\
 						ARM_AP_TZC_DRAM1_SIZE)
+# elif defined(SPD_spmd)
+#  define TSP_SEC_MEM_BASE		(ARM_AP_TZC_DRAM1_BASE + ULL(0x200000))
+#  define TSP_SEC_MEM_SIZE		(ARM_AP_TZC_DRAM1_SIZE - ULL(0x200000))
+#  define BL32_BASE			PLAT_ARM_TRUSTED_DRAM_BASE
+#  define BL32_LIMIT			(PLAT_ARM_TRUSTED_DRAM_BASE	\
+						+ (UL(1) << 21))
 # elif ARM_BL31_IN_DRAM
 #  define TSP_SEC_MEM_BASE		(ARM_AP_TZC_DRAM1_BASE +	\
 						PLAT_ARM_MAX_BL31_SIZE)
@@ -505,12 +525,12 @@
 
 /*
  * BL32 is mandatory in AArch32. In AArch64, undefine BL32_BASE if there is no
- * SPD and no SPM, as they are the only ones that can be used as BL32.
+ * SPD and no SPM-MM, as they are the only ones that can be used as BL32.
  */
 #if defined(__aarch64__) && !JUNO_AARCH32_EL3_RUNTIME
 # if defined(SPD_none) && !SPM_MM
 #  undef BL32_BASE
-# endif /* defined(SPD_none) && !SPM_MM*/
+# endif /* defined(SPD_none) && !SPM_MM */
 #endif /* defined(__aarch64__) && !JUNO_AARCH32_EL3_RUNTIME */
 
 /*******************************************************************************
diff --git a/include/plat/arm/common/arm_dyn_cfg_helpers.h b/include/plat/arm/common/arm_dyn_cfg_helpers.h
index 3ad6d54..2dc94ab 100644
--- a/include/plat/arm/common/arm_dyn_cfg_helpers.h
+++ b/include/plat/arm/common/arm_dyn_cfg_helpers.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,12 +10,7 @@
 #include <stdint.h>
 
 /* Function declarations */
-int arm_dyn_get_config_load_info(void *dtb, int node, unsigned int config_id,
-		uint64_t *config_addr, uint32_t *config_size);
 int arm_dyn_tb_fw_cfg_init(void *dtb, int *node);
-int arm_dyn_get_disable_auth(void *dtb, int node, uint32_t *disable_auth);
-int arm_get_dtb_mbedtls_heap_info(void *dtb, void **heap_addr,
-	size_t *heap_size);
 int arm_set_dtb_mbedtls_heap_info(void *dtb, void *heap_addr,
 	size_t heap_size);
 
diff --git a/include/plat/arm/common/arm_fconf_getter.h b/include/plat/arm/common/arm_fconf_getter.h
new file mode 100644
index 0000000..28913a4
--- /dev/null
+++ b/include/plat/arm/common/arm_fconf_getter.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ARM_FCONF_GETTER
+#define ARM_FCONF_GETTER
+
+#include <lib/fconf/fconf.h>
+
+/* ARM io policies */
+#define arm__io_policies_getter(id)	&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_arm_io_policies(uintptr_t config);
+
+#endif /* ARM_FCONF_GETTER */
diff --git a/include/plat/arm/common/arm_fconf_io_storage.h b/include/plat/arm/common/arm_fconf_io_storage.h
new file mode 100644
index 0000000..02ee66c
--- /dev/null
+++ b/include/plat/arm/common/arm_fconf_io_storage.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef ARM_FCONF_IO_STORAGE_H
+#define ARM_FCONF_IO_STORAGE_H
+
+#include <stdint.h>
+
+/* IO devices handle */
+extern uintptr_t memmap_dev_handle;
+extern uintptr_t fip_dev_handle;
+
+/* Function declarations */
+int open_fip(const uintptr_t spec);
+int open_memmap(const uintptr_t spec);
+
+#endif /* ARM_FCONF_IO_STORAGE_H */
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 02feec7..862e73a 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -1,11 +1,12 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 #ifndef PLAT_ARM_H
 #define PLAT_ARM_H
 
+#include <stdbool.h>
 #include <stdint.h>
 
 #include <drivers/arm/tzc_common.h>
@@ -142,8 +143,13 @@
 #define STATE_SW_E_PARAM		(-2)
 #define STATE_SW_E_DENIED		(-3)
 
+/* plat_get_rotpk_info() flags */
+#define ARM_ROTPK_REGS_ID		1
+#define ARM_ROTPK_DEVEL_RSA_ID		2
+#define ARM_ROTPK_DEVEL_ECDSA_ID	3
+
 /* IO storage utility functions */
-void arm_io_setup(void);
+int arm_io_setup(void);
 
 /* Security utility functions */
 void arm_tzc400_setup(const arm_tzc_regions_info_t *tzc_regions);
@@ -217,11 +223,9 @@
 void arm_sp_min_plat_runtime_setup(void);
 
 /* FIP TOC validity check */
-int arm_io_is_toc_valid(void);
+bool arm_io_is_toc_valid(void);
 
 /* Utility functions for Dynamic Config */
-void arm_load_tb_fw_config(void);
-void arm_bl2_set_tb_cfg_addr(void *dtb);
 void arm_bl2_dyn_cfg_init(void);
 void arm_bl1_set_mbedtls_heap(void);
 int arm_get_mbedtls_heap(void **heap_addr, size_t *heap_size);
@@ -233,6 +237,11 @@
 void arm_free_init_memory(void);
 
 /*
+ * Make the higher level translation tables read-only
+ */
+void arm_xlat_make_tables_readonly(void);
+
+/*
  * Mandatory functions required in ARM standard platforms
  */
 unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr);
@@ -251,13 +260,21 @@
 void plat_arm_interconnect_enter_coherency(void);
 void plat_arm_interconnect_exit_coherency(void);
 void plat_arm_program_trusted_mailbox(uintptr_t address);
-int plat_arm_bl1_fwu_needed(void);
+bool plat_arm_bl1_fwu_needed(void);
 __dead2 void plat_arm_error_handler(int err);
 
 /*
- * Optional function in ARM standard platforms
+ * Optional functions in ARM standard platforms
  */
 void plat_arm_override_gicr_frames(const uintptr_t *plat_gicr_frames);
+int arm_get_rotpk_info(void **key_ptr, unsigned int *key_len,
+	unsigned int *flags);
+int arm_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len,
+	unsigned int *flags);
+int arm_get_rotpk_info_cc(void **key_ptr, unsigned int *key_len,
+	unsigned int *flags);
+int arm_get_rotpk_info_dev(void **key_ptr, unsigned int *key_len,
+	unsigned int *flags);
 
 #if ARM_PLAT_MT
 unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr);
diff --git a/include/plat/arm/css/common/css_def.h b/include/plat/arm/css/common/css_def.h
index 2adf11d..7b61484 100644
--- a/include/plat/arm/css/common/css_def.h
+++ b/include/plat/arm/css/common/css_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -29,6 +29,10 @@
 #define SID_REG_BASE			0x2a4a0000
 #define SID_SYSTEM_ID_OFFSET		0x40
 #define SID_SYSTEM_CFG_OFFSET		0x70
+#define SID_NODE_ID_OFFSET		0x60
+#define SID_CHIP_ID_MASK		0xFF
+#define SID_MULTI_CHIP_MODE_MASK	0x100
+#define SID_MULTI_CHIP_MODE_SHIFT	8
 
 /* The slave_bootsecure controls access to GPU, DMC and CS. */
 #define CSS_NIC400_SLAVE_BOOTSECURE	8
diff --git a/include/plat/arm/css/common/css_pm.h b/include/plat/arm/css/common/css_pm.h
index 93f8616..e5357f5 100644
--- a/include/plat/arm/css/common/css_pm.h
+++ b/include/plat/arm/css/common/css_pm.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -44,4 +44,15 @@
  */
 extern const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[];
 
+#define SCMI_DOMAIN_ID_MASK		U(0xFFFF)
+#define SCMI_CHANNEL_ID_MASK		U(0xFFFF)
+#define SCMI_CHANNEL_ID_SHIFT		U(16)
+
+#define SET_SCMI_CHANNEL_ID(n)		(((n) & SCMI_CHANNEL_ID_MASK) << \
+					 SCMI_CHANNEL_ID_SHIFT)
+#define SET_SCMI_DOMAIN_ID(n)		((n) & SCMI_DOMAIN_ID_MASK)
+#define GET_SCMI_CHANNEL_ID(n)		(((n) >> SCMI_CHANNEL_ID_SHIFT) & \
+					 SCMI_CHANNEL_ID_MASK)
+#define GET_SCMI_DOMAIN_ID(n)		((n) & SCMI_DOMAIN_ID_MASK)
+
 #endif /* CSS_PM_H */
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 332cfca..f5bd298 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,6 +10,9 @@
 #include <stdint.h>
 
 #include <lib/psci/psci.h>
+#if defined(SPD_spmd)
+ #include <services/spm_core_manifest.h>
+#endif
 
 /*******************************************************************************
  * Forward declarations
@@ -272,7 +275,11 @@
 int plat_spm_sp_rd_load(struct sp_res_desc *rd, const void *ptr, size_t size);
 int plat_spm_sp_get_next_address(void **sp_base, size_t *sp_size,
 				 void **rd_base, size_t *rd_size);
-
+#if defined(SPD_spmd)
+int plat_spm_core_manifest_load(spmc_manifest_sect_attribute_t *manifest,
+				const void *ptr,
+				size_t size);
+#endif
 /*******************************************************************************
  * Mandatory BL image load functions(may be overridden).
  ******************************************************************************/
diff --git a/include/services/arm_arch_svc.h b/include/services/arm_arch_svc.h
index 23c6f56..1cb2038 100644
--- a/include/services/arm_arch_svc.h
+++ b/include/services/arm_arch_svc.h
@@ -12,6 +12,4 @@
 #define SMCCC_ARCH_WORKAROUND_1		U(0x80008000)
 #define SMCCC_ARCH_WORKAROUND_2		U(0x80007FFF)
 
-#define SMCCC_ARCH_NOT_REQUIRED		-2
-
 #endif /* ARM_ARCH_SVC_H */
diff --git a/include/services/spci_svc.h b/include/services/spci_svc.h
new file mode 100644
index 0000000..49ba408
--- /dev/null
+++ b/include/services/spci_svc.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SPCI_SVC_H
+#define SPCI_SVC_H
+
+#include <lib/smccc.h>
+#include <lib/utils_def.h>
+#include <tools_share/uuid.h>
+
+/* SPCI error codes. */
+#define SPCI_ERROR_NOT_SUPPORTED	-1
+#define SPCI_ERROR_INVALID_PARAMETER	-2
+#define SPCI_ERROR_NO_MEMORY		-3
+#define SPCI_ERROR_BUSY			-4
+#define SPCI_ERROR_INTERRUPTED		-5
+#define SPCI_ERROR_DENIED		-6
+#define SPCI_ERROR_RETRY		-7
+
+/* The macros below are used to identify SPCI calls from the SMC function ID */
+#define SPCI_FNUM_MIN_VALUE	U(0x60)
+#define SPCI_FNUM_MAX_VALUE	U(0x7f)
+#define is_spci_fid(fid) __extension__ ({		\
+	__typeof__(fid) _fid = (fid);			\
+	((GET_SMC_NUM(_fid) >= SPCI_FNUM_MIN_VALUE) &&	\
+	 (GET_SMC_NUM(_fid) <= SPCI_FNUM_MAX_VALUE)); })
+
+/* SPCI_VERSION helpers */
+#define SPCI_VERSION_MAJOR		U(0)
+#define SPCI_VERSION_MAJOR_SHIFT	16
+#define SPCI_VERSION_MAJOR_MASK		U(0x7FFF)
+#define SPCI_VERSION_MINOR		U(9)
+#define SPCI_VERSION_MINOR_SHIFT	0
+#define SPCI_VERSION_MINOR_MASK		U(0xFFFF)
+
+#define MAKE_SPCI_VERSION(major, minor) \
+	((((major) & SPCI_VERSION_MAJOR_MASK) <<  SPCI_VERSION_MAJOR_SHIFT) | \
+	 (((minor) & SPCI_VERSION_MINOR_MASK) << SPCI_VERSION_MINOR_SHIFT))
+#define SPCI_VERSION_COMPILED		MAKE_SPCI_VERSION(SPCI_VERSION_MAJOR, \
+							  SPCI_VERSION_MINOR)
+
+/* SPCI_MSG_SEND helpers */
+#define SPCI_MSG_SEND_ATTRS_BLK_SHIFT	U(0)
+#define SPCI_MSG_SEND_ATTRS_BLK_MASK	U(0x1)
+#define SPCI_MSG_SEND_ATTRS_BLK		U(0)
+#define SPCI_MSG_SEND_ATTRS_BLK_NOT	U(1)
+#define SPCI_MSG_SEND_ATTRS(blk)		\
+	(((blk) & SPCI_MSG_SEND_ATTRS_BLK_MASK) \
+	<< SPCI_MSG_SEND_ATTRS_BLK_SHIFT)
+
+/* Get SPCI fastcall std FID from function number */
+#define SPCI_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))
+
+/* SPCI function numbers */
+#define SPCI_FNUM_ERROR			U(0x60)
+#define SPCI_FNUM_SUCCESS		U(0x61)
+#define SPCI_FNUM_INTERRUPT		U(0x62)
+#define SPCI_FNUM_VERSION		U(0x63)
+#define SPCI_FNUM_FEATURES		U(0x64)
+#define SPCI_FNUM_RX_RELEASE		U(0x65)
+#define SPCI_FNUM_RXTX_MAP		U(0x66)
+#define SPCI_FNUM_RXTX_UNMAP		U(0x67)
+#define SPCI_FNUM_PARTITION_INFO_GET	U(0x68)
+#define SPCI_FNUM_ID_GET		U(0x69)
+#define SPCI_FNUM_MSG_POLL		U(0x6A)
+#define SPCI_FNUM_MSG_WAIT		U(0x6B)
+#define SPCI_FNUM_MSG_YIELD		U(0x6C)
+#define SPCI_FNUM_MSG_RUN		U(0x6D)
+#define SPCI_FNUM_MSG_SEND		U(0x6E)
+#define SPCI_FNUM_MSG_SEND_DIRECT_REQ	U(0x6F)
+#define SPCI_FNUM_MSG_SEND_DIRECT_RESP	U(0x70)
+#define SPCI_FNUM_MEM_DONATE		U(0x71)
+#define SPCI_FNUM_MEM_LEND		U(0x72)
+#define SPCI_FNUM_MEM_SHARE		U(0x73)
+#define SPCI_FNUM_MEM_RETRIEVE_REQ	U(0x74)
+#define SPCI_FNUM_MEM_RETRIEVE_RESP	U(0x75)
+#define SPCI_FNUM_MEM_RELINQUISH	U(0x76)
+#define SPCI_FNUM_MEM_RECLAIM		U(0x77)
+
+/* SPCI SMC32 FIDs */
+#define SPCI_ERROR		SPCI_FID(SMC_32, SPCI_FNUM_ERROR)
+#define SPCI_SUCCESS_SMC32	SPCI_FID(SMC_32, SPCI_FNUM_SUCCESS)
+#define SPCI_INTERRUPT		SPCI_FID(SMC_32, SPCI_FNUM_INTERRUPT)
+#define SPCI_VERSION		SPCI_FID(SMC_32, SPCI_FNUM_VERSION)
+#define SPCI_FEATURES		SPCI_FID(SMC_32, SPCI_FNUM_FEATURES)
+#define SPCI_RX_RELEASE		SPCI_FID(SMC_32, SPCI_FNUM_RX_RELEASE)
+#define SPCI_RXTX_MAP_SMC32	SPCI_FID(SMC_32, SPCI_FNUM_RXTX_MAP)
+#define SPCI_RXTX_UNMAP		SPCI_FID(SMC_32, SPCI_FNUM_RXTX_UNMAP)
+#define SPCI_PARTITION_INFO_GET	SPCI_FID(SMC_32, SPCI_FNUM_PARTITION_INFO_GET)
+#define SPCI_ID_GET		SPCI_FID(SMC_32, SPCI_FNUM_ID_GET)
+#define SPCI_MSG_POLL		SPCI_FID(SMC_32, SPCI_FNUM_MSG_POLL)
+#define SPCI_MSG_WAIT		SPCI_FID(SMC_32, SPCI_FNUM_MSG_WAIT)
+#define SPCI_MSG_YIELD		SPCI_FID(SMC_32, SPCI_FNUM_MSG_YIELD)
+#define SPCI_MSG_RUN		SPCI_FID(SMC_32, SPCI_FNUM_MSG_RUN)
+#define SPCI_MSG_SEND		SPCI_FID(SMC_32, SPCI_FNUM_MSG_SEND)
+#define SPCI_MSG_SEND_DIRECT_REQ_SMC32 \
+	SPCI_FID(SMC_32, SPCI_FNUM_MSG_SEND_DIRECT_REQ)
+#define SPCI_MSG_SEND_DIRECT_RESP_SMC32	\
+	SPCI_FID(SMC_32, SPCI_FNUM_MSG_SEND_DIRECT_RESP)
+#define SPCI_MEM_DONATE_SMC32	SPCI_FID(SMC_32, SPCI_FNUM_MEM_DONATE)
+#define SPCI_MEM_LEND_SMC32	SPCI_FID(SMC_32, SPCI_FNUM_MEM_LEND)
+#define SPCI_MEM_SHARE_SMC32	SPCI_FID(SMC_32, SPCI_FNUM_MEM_SHARE)
+#define SPCI_MEM_RETRIEVE_REQ_SMC32 \
+	SPCI_FID(SMC_32, SPCI_FNUM_MEM_RETRIEVE_REQ)
+#define SPCI_MEM_RETRIEVE_RESP	SPCI_FID(SMC_32, SPCI_FNUM_MEM_RETRIEVE_RESP)
+#define SPCI_MEM_RELINQUISH	SPCI_FID(SMC_32, SPCI_FNUM_MEM_RELINQUISH)
+#define SPCI_MEM_RECLAIM	SPCI_FID(SMC_32, SPCI_FNUM_MEM_RECLAIM)
+
+/* SPCI SMC64 FIDs */
+#define SPCI_SUCCESS_SMC64	SPCI_FID(SMC_64, SPCI_FNUM_SUCCESS)
+#define SPCI_RXTX_MAP_SMC64	SPCI_FID(SMC_64, SPCI_FNUM_RXTX_MAP)
+#define SPCI_MSG_SEND_DIRECT_REQ_SMC64 \
+	SPCI_FID(SMC_64, SPCI_FNUM_MSG_SEND_DIRECT_REQ)
+#define SPCI_MSG_SEND_DIRECT_RESP_SMC64	\
+	SPCI_FID(SMC_64, SPCI_FNUM_MSG_SEND_DIRECT_RESP)
+#define SPCI_MEM_DONATE_SMC64	SPCI_FID(SMC_64, SPCI_FNUM_MEM_DONATE)
+#define SPCI_MEM_LEND_SMC64	SPCI_FID(SMC_64, SPCI_FNUM_MEM_LEND)
+#define SPCI_MEM_SHARE_SMC64	SPCI_FID(SMC_64, SPCI_FNUM_MEM_SHARE)
+#define SPCI_MEM_RETRIEVE_REQ_SMC64 \
+	SPCI_FID(SMC_64, SPCI_FNUM_MEM_RETRIEVE_REQ)
+
+/*
+ * Reserve a special value for traffic targeted to the Hypervisor or SPM.
+ */
+#define SPCI_TARGET_INFO_MBZ		U(0x0)
+
+/*
+ * Reserve a special value for MBZ parameters.
+ */
+#define SPCI_PARAM_MBZ			U(0x0)
+
+#endif /* SPCI_SVC_H */
diff --git a/include/services/spm_core_manifest.h b/include/services/spm_core_manifest.h
new file mode 100644
index 0000000..06ecc13
--- /dev/null
+++ b/include/services/spm_core_manifest.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SPMC_MANIFEST_H
+#define SPMC_MANIFEST_H
+
+#include <stdint.h>
+
+/*******************************************************************************
+ * Attribute Section
+ ******************************************************************************/
+
+typedef struct spm_core_manifest_sect_attribute {
+	/*
+	 * SPCI version (mandatory).
+	 */
+	uint32_t major_version;
+	uint32_t minor_version;
+
+	/*
+	 * Run-Time Exception Level (mandatory):
+	 * - 1: SEL1
+	 * - 2: SEL2
+	 */
+	uint32_t runtime_el;
+
+	/*
+	 * Run-Time Execution state (optional):
+	 * - 0: AArch64 (default)
+	 * - 1: AArch32
+	 */
+	uint32_t exec_state;
+
+	/*
+	 * Address of binary image containing SPM core in bytes (optional).
+	 */
+	uint64_t load_address;
+
+	/*
+	 * Offset from the base of the partition's binary image to the entry
+	 * point of the partition.
+	 */
+	uint64_t entrypoint;
+
+	/*
+	 * Size of binary image containing SPM core in bytes (mandatory).
+	 */
+	uint32_t binary_size;
+
+} spmc_manifest_sect_attribute_t;
+
+#endif /* SPMC_MANIFEST_H */
diff --git a/include/services/spmd_svc.h b/include/services/spmd_svc.h
new file mode 100644
index 0000000..6e4caf2
--- /dev/null
+++ b/include/services/spmd_svc.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SPMD_SVC_H
+#define SPMD_SVC_H
+
+#ifndef __ASSEMBLER__
+#include <services/spci_svc.h>
+#include <stdint.h>
+
+int32_t spmd_setup(void);
+uint64_t spmd_smc_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 /* SPMD_SVC_H */
diff --git a/include/tools_share/sptool.h b/include/tools_share/sptool.h
index 67a2cf0..53668e0 100644
--- a/include/tools_share/sptool.h
+++ b/include/tools_share/sptool.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,21 +9,17 @@
 
 #include <stdint.h>
 
-/* Header for a secure partition package. There is one per package. */
-struct sp_pkg_header {
-	uint64_t version;
-	uint64_t number_of_sp;
-};
+/* 4 Byte magic name "SPKG" */
+#define SECURE_PARTITION_MAGIC		0x474B5053
 
-/*
- * Entry descriptor in a secure partition package. Each entry comprises a
- * secure partition and its resource description.
- */
-struct sp_pkg_entry {
-	uint64_t sp_offset;
-	uint64_t sp_size;
-	uint64_t rd_offset;
-	uint64_t rd_size;
+/* Header for a secure partition package. */
+struct sp_pkg_header {
+	uint32_t magic;
+	uint32_t version;
+	uint32_t pm_offset;
+	uint32_t pm_size;
+	uint32_t img_offset;
+	uint32_t img_size;
 };
 
 #endif /* SPTOOL_H */
diff --git a/include/tools_share/uuid.h b/include/tools_share/uuid.h
index 7d00432..36be9ed 100644
--- a/include/tools_share/uuid.h
+++ b/include/tools_share/uuid.h
@@ -27,7 +27,7 @@
  */
 
 /*
- * Portions copyright (c) 2014, ARM Limited and Contributors.
+ * Portions copyright (c) 2014-2020, ARM Limited and Contributors.
  * All rights reserved.
  */
 
@@ -56,6 +56,11 @@
 	uint8_t		node[_UUID_NODE_LEN];
 };
 
+union uuid_helper_t {
+	struct uuid uuid_struct;
+	uint32_t word[4];
+};
+
 /* XXX namespace pollution? */
 typedef struct uuid uuid_t;
 
diff --git a/lib/aarch64/cache_helpers.S b/lib/aarch64/cache_helpers.S
index 9ef8ca7..de9c8e4 100644
--- a/lib/aarch64/cache_helpers.S
+++ b/lib/aarch64/cache_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -30,7 +30,7 @@
 	dc	\op, x0
 	add	x0, x0, x2
 	cmp	x0, x1
-	b.lo    loop_\op
+	b.lo	loop_\op
 	dsb	sy
 exit_loop_\op:
 	ret
@@ -140,7 +140,7 @@
 level_done:
 	add	x10, x10, #2		// increment cache number
 	cmp	x3, x10
-	b.hi    loop1
+	b.hi	loop1
 	msr	csselr_el1, xzr		// select cache level 0 in csselr
 	dsb	sy			// barrier to complete final cache operation
 	isb
diff --git a/lib/coreboot/coreboot_table.c b/lib/coreboot/coreboot_table.c
index 63bdc63..253fac2 100644
--- a/lib/coreboot/coreboot_table.c
+++ b/lib/coreboot/coreboot_table.c
@@ -75,7 +75,7 @@
 static void setup_cbmem_console(uintptr_t baseaddr)
 {
 	static console_cbmc_t console;
-	assert(!console.base);		/* should only have one CBMEM console */
+	assert(!console.console.base);	/* should only have one CBMEM console */
 
 	/* CBMEM console structure stores its size in first header field. */
 	uint32_t size = *(uint32_t *)baseaddr;
diff --git a/lib/cpus/aarch64/cortex_a57.S b/lib/cpus/aarch64/cortex_a57.S
index dd03c0f..3fee470 100644
--- a/lib/cpus/aarch64/cortex_a57.S
+++ b/lib/cpus/aarch64/cortex_a57.S
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -469,6 +470,17 @@
 	dsb	sy
 #endif
 
+#if A57_ENABLE_NONCACHEABLE_LOAD_FWD
+	/* ---------------------------------------------
+	 * Enable higher performance non-cacheable load
+	 * forwarding
+	 * ---------------------------------------------
+	 */
+	mrs	x0, CORTEX_A57_CPUACTLR_EL1
+	orr	x0, x0, #CORTEX_A57_CPUACTLR_EL1_EN_NC_LOAD_FWD
+	msr	CORTEX_A57_CPUACTLR_EL1, x0
+#endif
+
 	/* ---------------------------------------------
 	 * Enable the SMP bit.
 	 * ---------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_klein.S b/lib/cpus/aarch64/cortex_klein.S
new file mode 100644
index 0000000..d3a8ab4
--- /dev/null
+++ b/lib/cpus/aarch64/cortex_klein.S
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2020, 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_klein.h>
+#include <cpu_macros.S>
+#include <plat_macros.S>
+
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "Cortex Klein must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
+/* 64-bit only core */
+#if CTX_INCLUDE_AARCH32_REGS == 1
+#error "Cortex Klein supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
+#endif
+
+	/* ----------------------------------------------------
+	 * HW will do the cache maintenance while powering down
+	 * ----------------------------------------------------
+	 */
+func cortex_klein_core_pwr_dwn
+	/* ---------------------------------------------------
+	 * Enable CPU power down bit in power control register
+	 * ---------------------------------------------------
+	 */
+	mrs	x0, CORTEX_KLEIN_CPUPWRCTLR_EL1
+	orr	x0, x0, #CORTEX_KLEIN_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
+	msr	CORTEX_KLEIN_CPUPWRCTLR_EL1, x0
+	isb
+	ret
+endfunc cortex_klein_core_pwr_dwn
+
+	/*
+	 * Errata printing function for Cortex Klein. Must follow AAPCS.
+	 */
+#if REPORT_ERRATA
+func cortex_klein_errata_report
+	ret
+endfunc cortex_klein_errata_report
+#endif
+
+func cortex_klein_reset_func
+	/* Disable speculative loads */
+	msr	SSBS, xzr
+	isb
+	ret
+endfunc cortex_klein_reset_func
+
+	/* ---------------------------------------------
+	 * This function provides Cortex-Klein 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_klein_regs, "aS"
+cortex_klein_regs:  /* The ascii list of register names to be reported */
+	.asciz	"cpuectlr_el1", ""
+
+func cortex_klein_cpu_reg_dump
+	adr	x6, cortex_klein_regs
+	mrs	x8, CORTEX_KLEIN_CPUECTLR_EL1
+	ret
+endfunc cortex_klein_cpu_reg_dump
+
+declare_cpu_ops cortex_klein, CORTEX_KLEIN_MIDR, \
+	cortex_klein_reset_func, \
+	cortex_klein_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_matterhorn.S b/lib/cpus/aarch64/cortex_matterhorn.S
new file mode 100644
index 0000000..4156f3c
--- /dev/null
+++ b/lib/cpus/aarch64/cortex_matterhorn.S
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2020, 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_matterhorn.h>
+#include <cpu_macros.S>
+#include <plat_macros.S>
+
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "Cortex Matterhorn must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
+/* 64-bit only core */
+#if CTX_INCLUDE_AARCH32_REGS == 1
+#error "Cortex Matterhorn supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
+#endif
+
+	/* ----------------------------------------------------
+	 * HW will do the cache maintenance while powering down
+	 * ----------------------------------------------------
+	 */
+func cortex_matterhorn_core_pwr_dwn
+	/* ---------------------------------------------------
+	 * Enable CPU power down bit in power control register
+	 * ---------------------------------------------------
+	 */
+	mrs	x0, CORTEX_MATTERHORN_CPUPWRCTLR_EL1
+	orr	x0, x0, #CORTEX_MATTERHORN_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
+	msr	CORTEX_MATTERHORN_CPUPWRCTLR_EL1, x0
+	isb
+	ret
+endfunc cortex_matterhorn_core_pwr_dwn
+
+	/*
+	 * Errata printing function for Cortex Matterhorn. Must follow AAPCS.
+	 */
+#if REPORT_ERRATA
+func cortex_matterhorn_errata_report
+	ret
+endfunc cortex_matterhorn_errata_report
+#endif
+
+func cortex_matterhorn_reset_func
+	/* Disable speculative loads */
+	msr	SSBS, xzr
+	isb
+	ret
+endfunc cortex_matterhorn_reset_func
+
+	/* ---------------------------------------------
+	 * This function provides Cortex-Matterhorn 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_matterhorn_regs, "aS"
+cortex_matterhorn_regs:  /* The ascii list of register names to be reported */
+	.asciz	"cpuectlr_el1", ""
+
+func cortex_matterhorn_cpu_reg_dump
+	adr	x6, cortex_matterhorn_regs
+	mrs	x8, CORTEX_MATTERHORN_CPUECTLR_EL1
+	ret
+endfunc cortex_matterhorn_cpu_reg_dump
+
+declare_cpu_ops cortex_matterhorn, CORTEX_MATTERHORN_MIDR, \
+	cortex_matterhorn_reset_func, \
+	cortex_matterhorn_core_pwr_dwn
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index e3bfc2f..3c0c9cd 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -1,5 +1,6 @@
 #
 # Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -16,6 +17,10 @@
 # It is enabled by default.
 A57_DISABLE_NON_TEMPORAL_HINT	?=1
 
+# Flag to enable higher performance non-cacheable load forwarding.
+# It is disabled by default.
+A57_ENABLE_NONCACHEABLE_LOAD_FWD	?= 0
+
 WORKAROUND_CVE_2017_5715	?=1
 WORKAROUND_CVE_2018_3639	?=1
 DYNAMIC_WORKAROUND_CVE_2018_3639	?=0
@@ -24,6 +29,10 @@
 # By default internal
 NEOVERSE_N1_EXTERNAL_LLC	?=0
 
+# Process A57_ENABLE_NONCACHEABLE_LOAD_FWD flag
+$(eval $(call assert_boolean,A57_ENABLE_NONCACHEABLE_LOAD_FWD))
+$(eval $(call add_define,A57_ENABLE_NONCACHEABLE_LOAD_FWD))
+
 # Process SKIP_A57_L1_FLUSH_PWR_DWN flag
 $(eval $(call assert_boolean,SKIP_A57_L1_FLUSH_PWR_DWN))
 $(eval $(call add_define,SKIP_A57_L1_FLUSH_PWR_DWN))
diff --git a/lib/fconf/fconf.c b/lib/fconf/fconf.c
new file mode 100644
index 0000000..a6da56b
--- /dev/null
+++ b/lib/fconf/fconf.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <lib/fconf/fconf.h>
+#include <libfdt.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+struct fconf_dtb_info_t fconf_dtb_info;
+
+void fconf_load_config(void)
+{
+	int err;
+	/* fconf FW_CONFIG and TB_FW_CONFIG are currently the same DTB */
+	image_info_t arm_tb_fw_info = {
+		.h.type = (uint8_t)PARAM_IMAGE_BINARY,
+		.h.version = (uint8_t)VERSION_2,
+		.h.size = (uint16_t)sizeof(image_info_t),
+		.h.attr = 0,
+		.image_base = ARM_TB_FW_CONFIG_BASE,
+		.image_max_size = (uint32_t)
+				(ARM_TB_FW_CONFIG_LIMIT - ARM_TB_FW_CONFIG_BASE)
+	};
+
+	VERBOSE("FCONF: Loading FW_CONFIG\n");
+	err = load_auth_image(TB_FW_CONFIG_ID, &arm_tb_fw_info);
+	if (err != 0) {
+		/* Return if FW_CONFIG is not loaded */
+		VERBOSE("Failed to load FW_CONFIG\n");
+		return;
+	}
+
+	/* At this point we know that a DTB is indeed available */
+	fconf_dtb_info.base_addr = arm_tb_fw_info.image_base;
+	fconf_dtb_info.size = (size_t)arm_tb_fw_info.image_size;
+
+#if !BL2_AT_EL3
+	image_desc_t *desc;
+
+	/* The BL2 ep_info arg0 is modified to point to FW_CONFIG */
+	desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
+	assert(desc != NULL);
+	desc->ep_info.args.arg0 = arm_tb_fw_info.image_base;
+#endif
+
+	INFO("FCONF: FW_CONFIG loaded at address = 0x%lx\n", arm_tb_fw_info.image_base);
+}
+
+void fconf_populate(uintptr_t config)
+{
+	assert(config != 0UL);
+
+	/* Check if the pointer to DTB is correct */
+	if (fdt_check_header((void *)config) != 0) {
+		ERROR("FCONF: Invalid DTB file passed for FW_CONFIG\n");
+		panic();
+	}
+
+	INFO("FCONF: Reading firmware configuration file from: 0x%lx\n", config);
+
+	/* Go through all registered populate functions */
+	IMPORT_SYM(struct fconf_populator *, __FCONF_POPULATOR_START__, start);
+	IMPORT_SYM(struct fconf_populator *, __FCONF_POPULATOR_END__, end);
+	const struct fconf_populator *populator;
+
+	for (populator = start; populator != end; populator++) {
+		assert((populator->info != NULL) && (populator->populate != NULL));
+
+		INFO("FCONF: Reading firmware configuration information for: %s\n", populator->info);
+		if (populator->populate(config) != 0) {
+			/* TODO: handle property miss */
+			panic();
+		}
+	}
+
+	/* save local pointer to the config dtb */
+	fconf_dtb_info.base_addr = config;
+}
diff --git a/lib/fconf/fconf.mk b/lib/fconf/fconf.mk
new file mode 100644
index 0000000..7031969
--- /dev/null
+++ b/lib/fconf/fconf.mk
@@ -0,0 +1,12 @@
+#
+# Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Add Firmware Configuration files
+FCONF_SOURCES		:=	lib/fconf/fconf.c				\
+				lib/fconf/fconf_dyn_cfg_getter.c
+
+BL1_SOURCES		+=	${FCONF_SOURCES}
+BL2_SOURCES		+=	${FCONF_SOURCES}
diff --git a/lib/fconf/fconf_dyn_cfg_getter.c b/lib/fconf/fconf_dyn_cfg_getter.c
new file mode 100644
index 0000000..d313a56
--- /dev/null
+++ b/lib/fconf/fconf_dyn_cfg_getter.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <lib/object_pool.h>
+#include <libfdt.h>
+
+/* We currently use TB_FW, SOC_FW, TOS_FW, NS_fw and HW configs  */
+#define MAX_DTB_INFO	U(5)
+
+static struct dyn_cfg_dtb_info_t dtb_infos[MAX_DTB_INFO];
+static OBJECT_POOL_ARRAY(dtb_info_pool, dtb_infos);
+
+struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id)
+{
+	unsigned int index;
+	struct dyn_cfg_dtb_info_t *info;
+
+	/* Positions index to the proper config-id */
+	for (index = 0; index < MAX_DTB_INFO; index++) {
+		if (dtb_infos[index].config_id == config_id) {
+			info = &dtb_infos[index];
+			break;
+		}
+	}
+
+	if (index == MAX_DTB_INFO) {
+		WARN("FCONF: Invalid config id %u\n", config_id);
+		info = NULL;
+	}
+
+	return info;
+}
+
+int fconf_populate_dtb_registry(uintptr_t config)
+{
+	int rc;
+	int node, child;
+	struct dyn_cfg_dtb_info_t *dtb_info;
+
+	/* As libfdt use void *, we can't avoid this cast */
+	const void *dtb = (void *)config;
+
+	/* Find the node offset point to "arm,dyn_cfg-dtb_registry" compatible property */
+	const char *compatible_str = "arm,dyn_cfg-dtb_registry";
+	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;
+	}
+
+	fdt_for_each_subnode(child, dtb, node) {
+		dtb_info = pool_alloc(&dtb_info_pool);
+
+		/* Read configuration dtb information */
+		rc = fdtw_read_cells(dtb, child, "load-address", 2, &dtb_info->config_addr);
+		if (rc < 0) {
+			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
+			return rc;
+		}
+
+		rc = fdtw_read_cells(dtb, child, "max-size", 1, &dtb_info->config_max_size);
+		if (rc < 0) {
+			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
+			return rc;
+		}
+
+		rc = fdtw_read_cells(dtb, child, "id", 1, &dtb_info->config_id);
+		if (rc < 0) {
+			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
+			return rc;
+		}
+
+		VERBOSE("FCONF: dyn_cfg.dtb_registry cell found with:\n");
+		VERBOSE("\tload-address = %lx\n", dtb_info->config_addr);
+		VERBOSE("\tmax-size = 0x%zx\n", dtb_info->config_max_size);
+		VERBOSE("\tconfig-id = %u\n", dtb_info->config_id);
+	}
+
+	if ((child < 0) && (child != -FDT_ERR_NOTFOUND)) {
+		ERROR("%d: fdt_for_each_subnode(): %d\n", __LINE__, node);
+		return child;
+	}
+
+	return 0;
+}
+
+FCONF_REGISTER_POPULATOR(dyn_cfg, fconf_populate_dtb_registry);
diff --git a/lib/fconf/fconf_tbbr_getter.c b/lib/fconf/fconf_tbbr_getter.c
new file mode 100644
index 0000000..c6df9c8
--- /dev/null
+++ b/lib/fconf/fconf_tbbr_getter.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <lib/fconf/fconf_tbbr_getter.h>
+#include <libfdt.h>
+
+struct tbbr_dyn_config_t tbbr_dyn_config;
+
+int fconf_populate_tbbr_dyn_config(uintptr_t config)
+{
+	int err;
+	int node;
+
+	/* As libfdt use void *, we can't avoid this cast */
+	const void *dtb = (void *)config;
+
+	/* Assert the node offset point to "arm,tb_fw" compatible property */
+	const char *compatible_str = "arm,tb_fw";
+	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 disable_auth cell and read the value */
+	err = fdtw_read_cells(dtb, node, "disable_auth", 1, &tbbr_dyn_config.disable_auth);
+	if (err < 0) {
+		WARN("FCONF: Read cell failed for `disable_auth`\n");
+		return err;
+	}
+
+	/* Check if the value is boolean */
+	if ((tbbr_dyn_config.disable_auth != 0U) && (tbbr_dyn_config.disable_auth != 1U)) {
+		WARN("Invalid value for `disable_auth` cell %d\n", tbbr_dyn_config.disable_auth);
+		return -1;
+	}
+
+#if defined(DYN_DISABLE_AUTH)
+	if (tbbr_dyn_config.disable_auth == 1)
+		dyn_disable_auth();
+#endif
+
+	/* Retrieve the Mbed TLS heap details from the DTB */
+	err = fdtw_read_cells(dtb, node,
+		"mbedtls_heap_addr", 2, &tbbr_dyn_config.mbedtls_heap_addr);
+	if (err < 0) {
+		ERROR("FCONF: Read cell failed for mbedtls_heap\n");
+		return err;
+	}
+
+	err = fdtw_read_cells(dtb, node,
+		"mbedtls_heap_size", 1, &tbbr_dyn_config.mbedtls_heap_size);
+	if (err < 0) {
+		ERROR("FCONF: Read cell failed for mbedtls_heap\n");
+		return err;
+	}
+
+	VERBOSE("FCONF:tbbr.disable_auth cell found with value = %d\n",
+					tbbr_dyn_config.disable_auth);
+	VERBOSE("FCONF:tbbr.mbedtls_heap_addr cell found with value = %p\n",
+					tbbr_dyn_config.mbedtls_heap_addr);
+	VERBOSE("FCONF:tbbr.mbedtls_heap_size cell found with value = %zu\n",
+					tbbr_dyn_config.mbedtls_heap_size);
+
+	return 0;
+}
+
+FCONF_REGISTER_POPULATOR(tbbr, fconf_populate_tbbr_dyn_config);
diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c
index 5ab15c6..cced276 100644
--- a/lib/psci/psci_common.c
+++ b/lib/psci/psci_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -601,7 +601,7 @@
 	unsigned int level;
 
 	/* Unlock top down. No unlocking required for level 0. */
-	for (level = end_pwrlvl; level >= PSCI_CPU_PWR_LVL + 1U; level--) {
+	for (level = end_pwrlvl; level >= (PSCI_CPU_PWR_LVL + 1U); level--) {
 		parent_idx = parent_nodes[level - 1U];
 		psci_lock_release(&psci_non_cpu_pd_nodes[parent_idx]);
 	}
diff --git a/lib/utils/mem_region.c b/lib/utils/mem_region.c
index 08bccf6..6bd78ba 100644
--- a/lib/utils/mem_region.c
+++ b/lib/utils/mem_region.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -32,7 +32,7 @@
 {
 	size_t i;
 
-	assert(tbl);
+	assert(tbl != NULL);
 	assert(nregions > 0);
 
 	for (i = 0; i < nregions; i++) {
@@ -114,7 +114,7 @@
 	uintptr_t region_start, region_end, start, end;
 	size_t i;
 
-	assert(tbl);
+	assert(tbl != NULL);
 	assert(nbytes > 0);
 	assert(!check_uptr_overflow(addr, nbytes-1));
 
diff --git a/lib/xlat_tables_v2/ro_xlat_tables.mk b/lib/xlat_tables_v2/ro_xlat_tables.mk
new file mode 100644
index 0000000..7991e1a
--- /dev/null
+++ b/lib/xlat_tables_v2/ro_xlat_tables.mk
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2020, 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)
+    ifeq (${RESET_TO_SP_MIN},1)
+       $(error "RESET_TO_SP_MIN requires functionality from the dynamic \
+                translation library and is incompatible with \
+                ALLOW_RO_XLAT_TABLES.")
+    endif
+else # if AArch64
+    ifeq (${PLAT},tegra)
+        $(error "Tegra requires functionality from the dynamic translation \
+                 library and is incompatible with ALLOW_RO_XLAT_TABLES.")
+    endif
+    ifeq (${RESET_TO_BL31},1)
+        $(error "RESET_TO_BL31 requires functionality from the dynamic \
+                 translation library and is incompatible with \
+                 ALLOW_RO_XLAT_TABLES.")
+    endif
+    ifeq (${SPD},trusty)
+        $(error "Trusty requires functionality from the dynamic translation \
+                 library and is incompatible with ALLOW_RO_XLAT_TABLES.")
+    endif
+    ifeq (${SPM_MM},1)
+        $(error "SPM_MM requires functionality to change memory region \
+                 attributes, which is not possible once the translation tables \
+                 have been made read-only.")
+    endif
+endif
diff --git a/lib/xlat_tables_v2/xlat_tables.mk b/lib/xlat_tables_v2/xlat_tables.mk
index c946315..bcc3e68 100644
--- a/lib/xlat_tables_v2/xlat_tables.mk
+++ b/lib/xlat_tables_v2/xlat_tables.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2017-2018, 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,3 +13,7 @@
 
 XLAT_TABLES_LIB_V2	:=	1
 $(eval $(call add_define,XLAT_TABLES_LIB_V2))
+
+ifeq (${ALLOW_RO_XLAT_TABLES}, 1)
+    include lib/xlat_tables_v2/ro_xlat_tables.mk
+endif
diff --git a/lib/xlat_tables_v2/xlat_tables_context.c b/lib/xlat_tables_v2/xlat_tables_context.c
index f4b64b3..adca578 100644
--- a/lib/xlat_tables_v2/xlat_tables_context.c
+++ b/lib/xlat_tables_v2/xlat_tables_context.c
@@ -1,9 +1,10 @@
 /*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <arch_helpers.h>
 #include <assert.h>
 
 #include <platform_def.h>
@@ -24,8 +25,14 @@
  * Allocate and initialise the default translation context for the BL image
  * currently executing.
  */
+#if PLAT_RO_XLAT_TABLES
+REGISTER_XLAT_CONTEXT_RO_BASE_TABLE(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES,
+		PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE,
+		EL_REGIME_INVALID, "xlat_table");
+#else
 REGISTER_XLAT_CONTEXT(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES,
 		PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE);
+#endif
 
 void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, size_t size,
 		     unsigned int attr)
@@ -119,6 +126,75 @@
 	return xlat_change_mem_attributes_ctx(&tf_xlat_ctx, base_va, size, attr);
 }
 
+#if PLAT_RO_XLAT_TABLES
+/* Change the memory attributes of the descriptors which resolve the address
+ * range that belongs to the translation tables themselves, which are by default
+ * mapped as part of read-write data in the BL image's memory.
+ *
+ * Since the translation tables map themselves via these level 3 (page)
+ * descriptors, any change applied to them with the MMU on would introduce a
+ * chicken and egg problem because of the break-before-make sequence.
+ * Eventually, it would reach the descriptor that resolves the very table it
+ * belongs to and the invalidation (break step) would cause the subsequent write
+ * (make step) to it to generate an MMU fault. Therefore, the MMU is disabled
+ * before making the change.
+ *
+ * No assumption is made about what data this function needs, therefore all the
+ * caches are flushed in order to ensure coherency. A future optimization would
+ * be to only flush the required data to main memory.
+ */
+int xlat_make_tables_readonly(void)
+{
+	assert(tf_xlat_ctx.initialized == true);
+#ifdef __aarch64__
+	if (tf_xlat_ctx.xlat_regime == EL1_EL0_REGIME) {
+		disable_mmu_el1();
+	} else if (tf_xlat_ctx.xlat_regime == EL3_REGIME) {
+		disable_mmu_el3();
+	} else {
+		assert(tf_xlat_ctx.xlat_regime == EL2_REGIME);
+		return -1;
+	}
+
+	/* Flush all caches. */
+	dcsw_op_all(DCCISW);
+#else /* !__aarch64__ */
+	assert(tf_xlat_ctx.xlat_regime == EL1_EL0_REGIME);
+	/* On AArch32, we flush the caches before disabling the MMU. The reason
+	 * for this is that the dcsw_op_all AArch32 function pushes some
+	 * registers onto the stack under the assumption that it is writing to
+	 * cache, which is not true with the MMU off. This would result in the
+	 * stack becoming corrupted and a wrong/junk value for the LR being
+	 * restored at the end of the routine.
+	 */
+	dcsw_op_all(DC_OP_CISW);
+	disable_mmu_secure();
+#endif
+
+	int rc = xlat_change_mem_attributes_ctx(&tf_xlat_ctx,
+				(uintptr_t)tf_xlat_ctx.tables,
+				tf_xlat_ctx.tables_num * XLAT_TABLE_SIZE,
+				MT_RO_DATA | MT_SECURE);
+
+#ifdef __aarch64__
+	if (tf_xlat_ctx.xlat_regime == EL1_EL0_REGIME) {
+		enable_mmu_el1(0U);
+	} else {
+		assert(tf_xlat_ctx.xlat_regime == EL3_REGIME);
+		enable_mmu_el3(0U);
+	}
+#else /* !__aarch64__ */
+	enable_mmu_svc_mon(0U);
+#endif
+
+	if (rc == 0) {
+		tf_xlat_ctx.readonly_tables = true;
+	}
+
+	return rc;
+}
+#endif /* PLAT_RO_XLAT_TABLES */
+
 /*
  * If dynamic allocation of new regions is disabled then by the time we call the
  * function enabling the MMU, we'll have registered all the memory regions to
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index 1fa26cc..b6925d3 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -67,6 +67,17 @@
 $(if $(__numeric),$(error $(1) must be numeric))
 endef
 
+# CREATE_SEQ is a recursive function to create sequence of numbers from 1 to
+# $(2) and assign the sequence to $(1)
+define CREATE_SEQ
+$(if $(word $(2), $($(1))),\
+  $(eval $(1) += $(words $($(1))))\
+  $(eval $(1) := $(filter-out 0,$($(1)))),\
+  $(eval $(1) += $(words $($(1))))\
+  $(call CREATE_SEQ,$(1),$(2))\
+)
+endef
+
 # IMG_LINKERFILE defines the linker script corresponding to a BL stage
 #   $(1) = BL stage (2, 30, 31, 32, 33)
 define IMG_LINKERFILE
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index fff336c..60958a1 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -201,9 +201,19 @@
 # Build option to add debugfs support
 USE_DEBUGFS			:= 0
 
+# Build option to fconf based io
+USE_FCONF_BASED_IO		:= 0
+
 # Build option to choose whether Trusted Firmware uses library at ROM
 USE_ROMLIB			:= 0
 
+# Build option to choose whether the xlat tables of BL images can be read-only.
+# Note that this only serves as a higher level option to PLAT_RO_XLAT_TABLES,
+# which is the per BL-image option that actually enables the read-only tables
+# API. The reason for having this additional option is to have a common high
+# level makefile where we can check for incompatible features/build options.
+ALLOW_RO_XLAT_TABLES		:= 0
+
 # Chain of trust.
 COT				:= tbbr
 
diff --git a/plat/allwinner/common/include/platform_def.h b/plat/allwinner/common/include/platform_def.h
index 32a7c04..6f22744 100644
--- a/plat/allwinner/common/include/platform_def.h
+++ b/plat/allwinner/common/include/platform_def.h
@@ -13,7 +13,7 @@
 
 #include <sunxi_mmap.h>
 
-#define BL31_BASE			SUNXI_SRAM_A2_BASE
+#define BL31_BASE			(SUNXI_SRAM_A2_BASE + 0x4000)
 #define BL31_LIMIT			(SUNXI_SRAM_A2_BASE + SUNXI_SRAM_A2_SIZE)
 
 /* Overwrite U-Boot SPL, but reserve the first page for the SPL header. */
diff --git a/plat/allwinner/common/sunxi_bl31_setup.c b/plat/allwinner/common/sunxi_bl31_setup.c
index a24527c..e836a34 100644
--- a/plat/allwinner/common/sunxi_bl31_setup.c
+++ b/plat/allwinner/common/sunxi_bl31_setup.c
@@ -28,7 +28,7 @@
 static entry_point_info_t bl32_image_ep_info;
 static entry_point_info_t bl33_image_ep_info;
 
-static console_16550_t console;
+static console_t console;
 
 static const gicv2_driver_data_t sunxi_gic_data = {
 	.gicd_base = SUNXI_GICD_BASE,
diff --git a/plat/allwinner/common/sunxi_common.c b/plat/allwinner/common/sunxi_common.c
index 3759c28..45e4154 100644
--- a/plat/allwinner/common/sunxi_common.c
+++ b/plat/allwinner/common/sunxi_common.c
@@ -175,7 +175,7 @@
  */
 void sunxi_execute_arisc_code(uint32_t *code, size_t size, uint16_t param)
 {
-	uintptr_t arisc_reset_vec = SUNXI_SRAM_A2_BASE - 0x4000 + 0x100;
+	uintptr_t arisc_reset_vec = SUNXI_SRAM_A2_BASE + 0x100;
 
 	do {
 		bakery_lock_get(&arisc_lock);
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
index db44091..9d2542f 100644
--- a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
+++ b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,8 +14,8 @@
 #define SUNXI_SRAM_SIZE			0x00044000
 #define SUNXI_SRAM_A1_BASE		0x00010000
 #define SUNXI_SRAM_A1_SIZE		0x00008000
-#define SUNXI_SRAM_A2_BASE		0x00044000
-#define SUNXI_SRAM_A2_SIZE		0x00010000
+#define SUNXI_SRAM_A2_BASE		0x00040000
+#define SUNXI_SRAM_A2_SIZE		0x00014000
 #define SUNXI_SRAM_C_BASE		0x00018000
 #define SUNXI_SRAM_C_SIZE		0x0001c000
 #define SUNXI_DEV_BASE			0x01000000
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
index f36491a..0e204d0 100644
--- a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
+++ b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,8 +14,8 @@
 #define SUNXI_SRAM_SIZE			0x000f8000
 #define SUNXI_SRAM_A1_BASE		0x00020000
 #define SUNXI_SRAM_A1_SIZE		0x00008000
-#define SUNXI_SRAM_A2_BASE		0x00104000
-#define SUNXI_SRAM_A2_SIZE		0x00014000
+#define SUNXI_SRAM_A2_BASE		0x00100000
+#define SUNXI_SRAM_A2_SIZE		0x00018000
 #define SUNXI_SRAM_C_BASE		0x00028000
 #define SUNXI_SRAM_C_SIZE		0x0001e000
 #define SUNXI_DEV_BASE			0x01000000
diff --git a/plat/amlogic/axg/axg_bl31_setup.c b/plat/amlogic/axg/axg_bl31_setup.c
new file mode 100644
index 0000000..8cc9d69
--- /dev/null
+++ b/plat/amlogic/axg/axg_bl31_setup.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <common/bl_common.h>
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include "aml_private.h"
+
+/*
+ * Placeholder variables for copying the arguments that have been passed to
+ * BL31 from BL2.
+ */
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+static image_info_t bl30_image_info;
+static image_info_t bl301_image_info;
+
+/*******************************************************************************
+ * Return a pointer to the 'entry_point_info' structure of the next image for
+ * the security state specified. BL33 corresponds to the non-secure image type
+ * while BL32 corresponds to the secure image type. A NULL pointer is returned
+ * if the image does not exist.
+ ******************************************************************************/
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+	entry_point_info_t *next_image_info;
+
+	next_image_info = (type == NON_SECURE) ?
+			  &bl33_image_ep_info : &bl32_image_ep_info;
+
+	/* None of the images can have 0x0 as the entrypoint. */
+	if (next_image_info->pc != 0U)
+		return next_image_info;
+
+	return NULL;
+}
+
+/*******************************************************************************
+ * Perform any BL31 early platform setup. Here is an opportunity to copy
+ * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before
+ * they are lost (potentially). This needs to be done before the MMU is
+ * initialized so that the memory layout can be used while creating page
+ * tables. BL2 has flushed this information to memory, so we are guaranteed
+ * to pick up good data.
+ ******************************************************************************/
+struct axg_bl31_param {
+	param_header_t h;
+	image_info_t *bl31_image_info;
+	entry_point_info_t *bl32_ep_info;
+	image_info_t *bl32_image_info;
+	entry_point_info_t *bl33_ep_info;
+	image_info_t *bl33_image_info;
+	image_info_t *scp_image_info[];
+};
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				u_register_t arg2, u_register_t arg3)
+{
+	struct axg_bl31_param *from_bl2;
+
+	/* Initialize the console to provide early debug support */
+	aml_console_init();
+
+	from_bl2 = (struct axg_bl31_param *)arg0;
+
+	/* Check params passed from BL2 are not NULL. */
+	assert(from_bl2 != NULL);
+	assert(from_bl2->h.type == PARAM_BL31);
+	assert(from_bl2->h.version >= VERSION_1);
+
+	/*
+	 * Copy BL32 and BL33 entry point information. It is stored in Secure
+	 * RAM, in BL2's address space.
+	 */
+	bl32_image_ep_info = *from_bl2->bl32_ep_info;
+	bl33_image_ep_info = *from_bl2->bl33_ep_info;
+
+#if AML_USE_ATOS
+	/*
+	 * BL2 is unconditionally setting 0 (OPTEE_AARCH64) in arg0 even when
+	 * the BL32 image is 32bit (OPTEE_AARCH32). This is causing the boot to
+	 * hang when ATOS (32bit Amlogic BL32 binary-only TEE OS) is used.
+	 *
+	 * Hardcode to OPTEE_AARCH32 / MODE_RW_32.
+	 */
+	bl32_image_ep_info.args.arg0 = MODE_RW_32;
+#endif
+
+	if (bl33_image_ep_info.pc == 0U) {
+		ERROR("BL31: BL33 entrypoint not obtained from BL2\n");
+		panic();
+	}
+
+	bl30_image_info = *from_bl2->scp_image_info[0];
+	bl301_image_info = *from_bl2->scp_image_info[1];
+}
+
+void bl31_plat_arch_setup(void)
+{
+	aml_setup_page_tables();
+
+	enable_mmu_el3(0);
+}
+
+static inline bool axg_scp_ready(void)
+{
+	return AML_AO_RTI_SCP_IS_READY(mmio_read_32(AML_AO_RTI_SCP_STAT));
+}
+
+static inline void axg_scp_boot(void)
+{
+	aml_scpi_upload_scp_fw(bl30_image_info.image_base,
+			       bl30_image_info.image_size, 0);
+	aml_scpi_upload_scp_fw(bl301_image_info.image_base,
+			       bl301_image_info.image_size, 1);
+	while (!axg_scp_ready())
+		;
+}
+
+/*******************************************************************************
+ * GICv2 driver setup information
+ ******************************************************************************/
+static const interrupt_prop_t axg_interrupt_props[] = {
+	INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+	INTR_PROP_DESC(IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY,
+		       GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL)
+};
+
+static const gicv2_driver_data_t axg_gic_data = {
+	.gicd_base = AML_GICD_BASE,
+	.gicc_base = AML_GICC_BASE,
+	.interrupt_props = axg_interrupt_props,
+	.interrupt_props_num = ARRAY_SIZE(axg_interrupt_props)
+};
+
+void bl31_platform_setup(void)
+{
+	aml_mhu_secure_init();
+
+	gicv2_driver_init(&axg_gic_data);
+	gicv2_distif_init();
+	gicv2_pcpu_distif_init();
+	gicv2_cpuif_enable();
+
+	axg_scp_boot();
+}
diff --git a/plat/amlogic/axg/axg_common.c b/plat/amlogic/axg/axg_common.c
new file mode 100644
index 0000000..870daf4
--- /dev/null
+++ b/plat/amlogic/axg/axg_common.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <bl31/interrupt_mgmt.h>
+#include <common/bl_common.h>
+#include <common/ep_info.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <platform_def.h>
+#include <stdint.h>
+
+/*******************************************************************************
+ * Platform memory map regions
+ ******************************************************************************/
+#define MAP_NSDRAM0		MAP_REGION_FLAT(AML_NSDRAM0_BASE,		\
+						AML_NSDRAM0_SIZE,		\
+						MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_NS_SHARE_MEM	MAP_REGION_FLAT(AML_NS_SHARE_MEM_BASE,		\
+						AML_NS_SHARE_MEM_SIZE,		\
+						MT_MEMORY | MT_RW | MT_NS)
+
+#define MAP_SEC_SHARE_MEM	MAP_REGION_FLAT(AML_SEC_SHARE_MEM_BASE,		\
+						AML_SEC_SHARE_MEM_SIZE,		\
+						MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE0		MAP_REGION_FLAT(AML_SEC_DEVICE0_BASE,		\
+						AML_SEC_DEVICE0_SIZE,		\
+						MT_DEVICE | MT_RW)
+
+#define MAP_GIC_DEVICE		MAP_REGION_FLAT(AML_GIC_DEVICE_BASE,		\
+						AML_GIC_DEVICE_SIZE,		\
+						MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE1		MAP_REGION_FLAT(AML_SEC_DEVICE1_BASE,		\
+						AML_SEC_DEVICE1_SIZE,		\
+						MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_SEC_DEVICE2		MAP_REGION_FLAT(AML_SEC_DEVICE2_BASE,		\
+						AML_SEC_DEVICE2_SIZE,		\
+						MT_DEVICE | MT_RW | MT_SECURE)
+
+#define MAP_TZRAM		MAP_REGION_FLAT(AML_TZRAM_BASE,			\
+						AML_TZRAM_SIZE,			\
+						MT_DEVICE | MT_RW | MT_SECURE)
+
+static const mmap_region_t axg_mmap[] = {
+	MAP_NSDRAM0,
+	MAP_NS_SHARE_MEM,
+	MAP_SEC_SHARE_MEM,
+	MAP_SEC_DEVICE0,
+	MAP_GIC_DEVICE,
+	MAP_SEC_DEVICE1,
+	MAP_SEC_DEVICE2,
+	MAP_TZRAM,
+	{0}
+};
+
+/*******************************************************************************
+ * Per-image regions
+ ******************************************************************************/
+#define MAP_BL31	MAP_REGION_FLAT(BL31_BASE,					\
+					BL31_END - BL31_BASE,				\
+					MT_MEMORY | MT_RW | MT_SECURE)
+
+#define MAP_BL_CODE	MAP_REGION_FLAT(BL_CODE_BASE,					\
+					BL_CODE_END - BL_CODE_BASE,			\
+					MT_CODE | MT_SECURE)
+
+#define MAP_BL_RO_DATA	MAP_REGION_FLAT(BL_RO_DATA_BASE,				\
+					BL_RO_DATA_END - BL_RO_DATA_BASE,		\
+					MT_RO_DATA | MT_SECURE)
+
+#define MAP_BL_COHERENT	MAP_REGION_FLAT(BL_COHERENT_RAM_BASE,				\
+					BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, 	\
+					MT_DEVICE | MT_RW | MT_SECURE)
+
+/*******************************************************************************
+ * Function that sets up the translation tables.
+ ******************************************************************************/
+void aml_setup_page_tables(void)
+{
+#if IMAGE_BL31
+	const mmap_region_t axg_bl_mmap[] = {
+		MAP_BL31,
+		MAP_BL_CODE,
+		MAP_BL_RO_DATA,
+#if USE_COHERENT_MEM
+		MAP_BL_COHERENT,
+#endif
+		{0}
+	};
+#endif
+
+	mmap_add(axg_bl_mmap);
+
+	mmap_add(axg_mmap);
+
+	init_xlat_tables();
+}
+
+/*******************************************************************************
+ * Function that returns the system counter frequency
+ ******************************************************************************/
+unsigned int plat_get_syscnt_freq2(void)
+{
+	mmio_clrbits_32(AML_SYS_CPU_CFG7, PLAT_SYS_CPU_CFG7);
+	mmio_clrbits_32(AML_AO_TIMESTAMP_CNTL, PLAT_AO_TIMESTAMP_CNTL);
+
+	return AML_OSC24M_CLK_IN_HZ;
+}
diff --git a/plat/amlogic/axg/axg_def.h b/plat/amlogic/axg/axg_def.h
new file mode 100644
index 0000000..d90681a
--- /dev/null
+++ b/plat/amlogic/axg/axg_def.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef AXG_DEF_H
+#define AXG_DEF_H
+
+#include <lib/utils_def.h>
+
+/*******************************************************************************
+ * System oscillator
+ ******************************************************************************/
+#define AML_OSC24M_CLK_IN_HZ			ULL(24000000) /* 24 MHz */
+
+/*******************************************************************************
+ * Memory regions
+ ******************************************************************************/
+#define AML_NS_SHARE_MEM_BASE			UL(0x05000000)
+#define AML_NS_SHARE_MEM_SIZE			UL(0x00100000)
+
+#define AML_SEC_SHARE_MEM_BASE			UL(0x05200000)
+#define AML_SEC_SHARE_MEM_SIZE			UL(0x00100000)
+
+#define AML_GIC_DEVICE_BASE			UL(0xFFC00000)
+#define AML_GIC_DEVICE_SIZE			UL(0x00008000)
+
+#define AML_NSDRAM0_BASE			UL(0x01000000)
+#define AML_NSDRAM0_SIZE			UL(0x0F000000)
+
+#define BL31_BASE				UL(0x05100000)
+#define BL31_SIZE				UL(0x00100000)
+#define BL31_LIMIT				(BL31_BASE + BL31_SIZE)
+
+/* Shared memory used for SMC services */
+#define AML_SHARE_MEM_INPUT_BASE		UL(0x050FE000)
+#define AML_SHARE_MEM_OUTPUT_BASE		UL(0x050FF000)
+
+#define AML_SEC_DEVICE0_BASE			UL(0xFFD00000)
+#define AML_SEC_DEVICE0_SIZE			UL(0x00026000)
+
+#define AML_SEC_DEVICE1_BASE			UL(0xFF800000)
+#define AML_SEC_DEVICE1_SIZE			UL(0x0000A000)
+
+#define AML_SEC_DEVICE2_BASE			UL(0xFF620000)
+#define AML_SEC_DEVICE2_SIZE			UL(0x00028000)
+
+#define AML_TZRAM_BASE				UL(0xFFFC0000)
+#define AML_TZRAM_SIZE				UL(0x00020000)
+
+/* Mailboxes */
+#define AML_MHU_SECURE_SCP_TO_AP_PAYLOAD	UL(0xFFFD3800)
+#define AML_MHU_SECURE_AP_TO_SCP_PAYLOAD	UL(0xFFFD3A00)
+#define AML_PSCI_MAILBOX_BASE			UL(0xFFFD3F00)
+
+/*******************************************************************************
+ * GIC-400 and interrupt handling related constants
+ ******************************************************************************/
+#define AML_GICD_BASE				UL(0xFFC01000)
+#define AML_GICC_BASE				UL(0xFFC02000)
+
+#define IRQ_SEC_PHY_TIMER			29
+
+#define IRQ_SEC_SGI_0				8
+#define IRQ_SEC_SGI_1				9
+#define IRQ_SEC_SGI_2				10
+#define IRQ_SEC_SGI_3				11
+#define IRQ_SEC_SGI_4				12
+#define IRQ_SEC_SGI_5				13
+#define IRQ_SEC_SGI_6				14
+#define IRQ_SEC_SGI_7				15
+#define IRQ_SEC_SGI_8				16
+
+/*******************************************************************************
+ * UART definitions
+ ******************************************************************************/
+#define AML_UART0_AO_BASE			UL(0xFF803000)
+#define AML_UART0_AO_CLK_IN_HZ			AML_OSC24M_CLK_IN_HZ
+#define AML_UART_BAUDRATE			U(115200)
+
+/*******************************************************************************
+ * Memory-mapped I/O Registers
+ ******************************************************************************/
+#define AML_AO_TIMESTAMP_CNTL			UL(0xFF8000B4)
+
+#define AML_SYS_CPU_CFG7			UL(0xFF634664)
+
+#define AML_AO_RTI_STATUS_REG3			UL(0xFF80001C)
+#define AML_AO_RTI_SCP_STAT			UL(0xFF80023C)
+#define AML_AO_RTI_SCP_READY_OFF		U(0x14)
+#define AML_A0_RTI_SCP_READY_MASK		U(3)
+#define AML_AO_RTI_SCP_IS_READY(v)					\
+	((((v) >> AML_AO_RTI_SCP_READY_OFF) &				\
+	AML_A0_RTI_SCP_READY_MASK) == AML_A0_RTI_SCP_READY_MASK)
+
+#define AML_HIU_MAILBOX_SET_0			UL(0xFF63C404)
+#define AML_HIU_MAILBOX_STAT_0			UL(0xFF63C408)
+#define AML_HIU_MAILBOX_CLR_0			UL(0xFF63C40C)
+#define AML_HIU_MAILBOX_SET_3			UL(0xFF63C428)
+#define AML_HIU_MAILBOX_STAT_3			UL(0xFF63C42C)
+#define AML_HIU_MAILBOX_CLR_3			UL(0xFF63C430)
+
+#define AML_SHA_DMA_BASE			UL(0xFF63E000)
+#define AML_SHA_DMA_DESC			(AML_SHA_DMA_BASE + 0x08)
+#define AML_SHA_DMA_STATUS			(AML_SHA_DMA_BASE + 0x28)
+
+/*******************************************************************************
+ * System Monitor Call IDs and arguments
+ ******************************************************************************/
+#define AML_SM_GET_SHARE_MEM_INPUT_BASE		U(0x82000020)
+#define AML_SM_GET_SHARE_MEM_OUTPUT_BASE	U(0x82000021)
+
+#define AML_SM_EFUSE_READ			U(0x82000030)
+#define AML_SM_EFUSE_USER_MAX			U(0x82000033)
+
+#define AML_SM_JTAG_ON				U(0x82000040)
+#define AML_SM_JTAG_OFF				U(0x82000041)
+#define AML_SM_GET_CHIP_ID			U(0x82000044)
+
+#define AML_JTAG_STATE_ON			U(0)
+#define AML_JTAG_STATE_OFF			U(1)
+
+#define AML_JTAG_M3_AO				U(0)
+#define AML_JTAG_M3_EE				U(1)
+#define AML_JTAG_A53_AO				U(2)
+#define AML_JTAG_A53_EE				U(3)
+
+#endif /* AXG_DEF_H */
diff --git a/plat/amlogic/axg/axg_pm.c b/plat/amlogic/axg/axg_pm.c
new file mode 100644
index 0000000..e67f263
--- /dev/null
+++ b/plat/amlogic/axg/axg_pm.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/console.h>
+#include <errno.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+#include "aml_private.h"
+
+#define SCPI_POWER_ON		0
+#define SCPI_POWER_RETENTION	1
+#define SCPI_POWER_OFF		3
+
+#define SCPI_SYSTEM_SHUTDOWN	0
+#define SCPI_SYSTEM_REBOOT	1
+
+static uintptr_t axg_sec_entrypoint;
+
+static void axg_pm_set_reset_addr(u_register_t mpidr, uint64_t value)
+{
+	unsigned int core = plat_calc_core_pos(mpidr);
+	uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4);
+
+	mmio_write_64(cpu_mailbox_addr, value);
+}
+
+static void axg_pm_reset(u_register_t mpidr, uint32_t value)
+{
+	unsigned int core = plat_calc_core_pos(mpidr);
+	uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4) + 8;
+
+	mmio_write_32(cpu_mailbox_addr, value);
+}
+
+static void __dead2 axg_system_reset(void)
+{
+	u_register_t mpidr = read_mpidr_el1();
+	int ret;
+
+	INFO("BL31: PSCI_SYSTEM_RESET\n");
+
+	ret = aml_scpi_sys_power_state(SCPI_SYSTEM_REBOOT);
+	if (ret != 0) {
+		ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %i\n", ret);
+		panic();
+	}
+
+	axg_pm_reset(mpidr, 0);
+
+	wfi();
+
+	ERROR("BL31: PSCI_SYSTEM_RESET: Operation not handled\n");
+	panic();
+}
+
+static void __dead2 axg_system_off(void)
+{
+	u_register_t mpidr = read_mpidr_el1();
+	int ret;
+
+	INFO("BL31: PSCI_SYSTEM_OFF\n");
+
+	ret = aml_scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN);
+	if (ret != 0) {
+		ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %i\n", ret);
+		panic();
+	}
+
+	axg_pm_set_reset_addr(mpidr, 0);
+	axg_pm_reset(mpidr, 0);
+
+	dmbsy();
+	wfi();
+
+	ERROR("BL31: PSCI_SYSTEM_OFF: Operation not handled\n");
+	panic();
+}
+
+static int32_t axg_pwr_domain_on(u_register_t mpidr)
+{
+	axg_pm_set_reset_addr(mpidr, axg_sec_entrypoint);
+	aml_scpi_set_css_power_state(mpidr,
+				     SCPI_POWER_ON, SCPI_POWER_ON, SCPI_POWER_ON);
+	dmbsy();
+	sev();
+
+	return PSCI_E_SUCCESS;
+}
+
+static void axg_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+	assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+					PLAT_LOCAL_STATE_OFF);
+
+	gicv2_pcpu_distif_init();
+	gicv2_cpuif_enable();
+
+	axg_pm_set_reset_addr(read_mpidr_el1(), 0);
+}
+
+static void axg_pwr_domain_off(const psci_power_state_t *target_state)
+{
+	u_register_t mpidr = read_mpidr_el1();
+	uint32_t system_state = SCPI_POWER_ON;
+	uint32_t cluster_state = SCPI_POWER_ON;
+
+	assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+					PLAT_LOCAL_STATE_OFF);
+
+	axg_pm_reset(mpidr, -1);
+
+	gicv2_cpuif_disable();
+
+	if (target_state->pwr_domain_state[MPIDR_AFFLVL2] ==
+					PLAT_LOCAL_STATE_OFF)
+		system_state = SCPI_POWER_OFF;
+
+	if (target_state->pwr_domain_state[MPIDR_AFFLVL1] ==
+					PLAT_LOCAL_STATE_OFF)
+		cluster_state = SCPI_POWER_OFF;
+
+
+	aml_scpi_set_css_power_state(mpidr,
+				     SCPI_POWER_OFF, cluster_state,
+				     system_state);
+}
+
+static void __dead2 axg_pwr_domain_pwr_down_wfi(const psci_power_state_t
+						 *target_state)
+{
+	dsbsy();
+	axg_pm_reset(read_mpidr_el1(), 0);
+
+	for (;;)
+		wfi();
+}
+
+/*******************************************************************************
+ * Platform handlers and setup function.
+ ******************************************************************************/
+static const plat_psci_ops_t axg_ops = {
+	.pwr_domain_on			= axg_pwr_domain_on,
+	.pwr_domain_on_finish		= axg_pwr_domain_on_finish,
+	.pwr_domain_off			= axg_pwr_domain_off,
+	.pwr_domain_pwr_down_wfi	= axg_pwr_domain_pwr_down_wfi,
+	.system_off			= axg_system_off,
+	.system_reset			= axg_system_reset
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	axg_sec_entrypoint = sec_entrypoint;
+	*psci_ops = &axg_ops;
+	return 0;
+}
diff --git a/plat/amlogic/axg/include/platform_def.h b/plat/amlogic/axg/include/platform_def.h
new file mode 100644
index 0000000..a47cf73
--- /dev/null
+++ b/plat/amlogic/axg/include/platform_def.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <lib/utils_def.h>
+
+#include "../axg_def.h"
+
+#define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH		aarch64
+
+#define PLATFORM_STACK_SIZE		UL(0x1000)
+
+#define PLATFORM_MAX_CPUS_PER_CLUSTER	U(4)
+#define PLATFORM_CLUSTER_COUNT		U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT	PLATFORM_MAX_CPUS_PER_CLUSTER
+#define PLATFORM_CORE_COUNT		PLATFORM_CLUSTER0_CORE_COUNT
+
+#define AML_PRIMARY_CPU			U(0)
+
+#define PLAT_MAX_PWR_LVL		MPIDR_AFFLVL1
+#define PLAT_NUM_PWR_DOMAINS		(PLATFORM_CLUSTER_COUNT + \
+					 PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_RET_STATE		U(1)
+#define PLAT_MAX_OFF_STATE		U(2)
+
+#define PLAT_SYS_CPU_CFG7		(U(1) << 25)
+#define PLAT_AO_TIMESTAMP_CNTL		U(0x1ff)
+
+/* Local power state for power domains in Run state. */
+#define PLAT_LOCAL_STATE_RUN		U(0)
+/* Local power state for retention. Valid only for CPU power domains */
+#define PLAT_LOCAL_STATE_RET		U(1)
+/* Local power state for power-down. Valid for CPU and cluster power domains. */
+#define PLAT_LOCAL_STATE_OFF		U(2)
+
+/*
+ * Macros used to parse state information from State-ID if it is using the
+ * recommended encoding for State-ID.
+ */
+#define PLAT_LOCAL_PSTATE_WIDTH		U(4)
+#define PLAT_LOCAL_PSTATE_MASK		((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1)
+
+/*
+ * 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_SHIFT		U(6)
+#define CACHE_WRITEBACK_GRANULE		(U(1) << CACHE_WRITEBACK_SHIFT)
+
+/* Memory-related defines */
+#define PLAT_PHY_ADDR_SPACE_SIZE	(ULL(1) << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(ULL(1) << 32)
+
+#define MAX_MMAP_REGIONS		16
+#define MAX_XLAT_TABLES			8
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/amlogic/axg/platform.mk b/plat/amlogic/axg/platform.mk
new file mode 100644
index 0000000..3560b0c
--- /dev/null
+++ b/plat/amlogic/axg/platform.mk
@@ -0,0 +1,95 @@
+#
+# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include lib/xlat_tables_v2/xlat_tables.mk
+
+AML_PLAT		:=	plat/amlogic
+AML_PLAT_SOC		:=	${AML_PLAT}/${PLAT}
+AML_PLAT_COMMON		:=	${AML_PLAT}/common
+
+DOIMAGEPATH		?=	tools/amlogic
+DOIMAGETOOL		?=	${DOIMAGEPATH}/doimage
+
+PLAT_INCLUDES		:=	-Iinclude/drivers/amlogic/			\
+				-I${AML_PLAT_SOC}/include			\
+				-I${AML_PLAT_COMMON}/include
+
+GIC_SOURCES		:=	drivers/arm/gic/common/gic_common.c		\
+				drivers/arm/gic/v2/gicv2_main.c			\
+				drivers/arm/gic/v2/gicv2_helpers.c		\
+				plat/common/plat_gicv2.c
+
+BL31_SOURCES		+=	lib/cpus/aarch64/cortex_a53.S			\
+				plat/common/plat_psci_common.c			\
+				drivers/amlogic/console/aarch64/meson_console.S	\
+				${AML_PLAT_SOC}/${PLAT}_bl31_setup.c		\
+				${AML_PLAT_SOC}/${PLAT}_pm.c			\
+				${AML_PLAT_SOC}/${PLAT}_common.c		\
+				${AML_PLAT_COMMON}/aarch64/aml_helpers.S	\
+				${AML_PLAT_COMMON}/aml_efuse.c			\
+				${AML_PLAT_COMMON}/aml_mhu.c			\
+				${AML_PLAT_COMMON}/aml_scpi.c			\
+				${AML_PLAT_COMMON}/aml_sip_svc.c		\
+				${AML_PLAT_COMMON}/aml_thermal.c		\
+				${AML_PLAT_COMMON}/aml_topology.c		\
+				${AML_PLAT_COMMON}/aml_console.c		\
+				drivers/amlogic/crypto/sha_dma.c		\
+				${XLAT_TABLES_LIB_SRCS}				\
+				${GIC_SOURCES}
+
+# Tune compiler for Cortex-A53
+ifeq ($(notdir $(CC)),armclang)
+    TF_CFLAGS_aarch64	+=	-mcpu=cortex-a53
+else ifneq ($(findstring clang,$(notdir $(CC))),)
+    TF_CFLAGS_aarch64	+=	-mcpu=cortex-a53
+else
+    TF_CFLAGS_aarch64	+=	-mtune=cortex-a53
+endif
+
+# Build config flags
+# ------------------
+
+# Enable all errata workarounds for Cortex-A53
+ERRATA_A53_855873		:= 1
+ERRATA_A53_819472		:= 1
+ERRATA_A53_824069		:= 1
+ERRATA_A53_827319		:= 1
+
+WORKAROUND_CVE_2017_5715	:= 0
+
+# Have different sections for code and rodata
+SEPARATE_CODE_AND_RODATA	:= 1
+
+# Use Coherent memory
+USE_COHERENT_MEM		:= 1
+
+AML_USE_ATOS			:= 0
+$(eval $(call assert_boolean,AML_USE_ATOS))
+$(eval $(call add_define,AML_USE_ATOS))
+
+# Verify build config
+# -------------------
+
+ifneq (${RESET_TO_BL31}, 0)
+  $(error Error: ${PLAT} needs RESET_TO_BL31=0)
+endif
+
+ifeq (${ARCH},aarch32)
+  $(error Error: AArch32 not supported on ${PLAT})
+endif
+
+all: ${BUILD_PLAT}/bl31.img
+distclean realclean clean: cleanimage
+
+cleanimage:
+	${Q}${MAKE} -C ${DOIMAGEPATH} clean
+
+${DOIMAGETOOL}:
+	${Q}${MAKE} -C ${DOIMAGEPATH}
+
+${BUILD_PLAT}/bl31.img: ${BUILD_PLAT}/bl31.bin ${DOIMAGETOOL}
+	${DOIMAGETOOL} ${BUILD_PLAT}/bl31.bin ${BUILD_PLAT}/bl31.img
+
diff --git a/plat/amlogic/common/aml_console.c b/plat/amlogic/common/aml_console.c
index 352279b..e21d707 100644
--- a/plat/amlogic/common/aml_console.c
+++ b/plat/amlogic/common/aml_console.c
@@ -11,7 +11,7 @@
 /*******************************************************************************
  * Function that sets up the console
  ******************************************************************************/
-static console_meson_t aml_console;
+static console_t aml_console;
 
 void aml_console_init(void)
 {
@@ -28,6 +28,6 @@
 		panic();
 	}
 
-	console_set_scope(&aml_console.console,
+	console_set_scope(&aml_console,
 			  CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
 }
diff --git a/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts b/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts
new file mode 100644
index 0000000..2f2d265
--- /dev/null
+++ b/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "arm,dyn_cfg-dtb_registry";
+
+		/* tb_fw_config is temporarily contained in this dtb */
+		tb_fw-config {
+			load-address = <0x0 0x2001010>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+
+		hw-config {
+			load-address = <0x0 0x83000000>;
+			max-size = <0x01000000>;
+			id = <HW_CONFIG_ID>;
+		};
+	};
+
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+	};
+};
diff --git a/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts b/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts
deleted file mode 100644
index 7b3aa11..0000000
--- a/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/dts-v1/;
-
-/ {
-	/* Platform Config */
-	plat_arm_bl2 {
-		compatible = "arm,tb_fw";
-		hw_config_addr = <0x0 0x83000000>;
-		hw_config_max_size = <0x01000000>;
-		/* Disable authentication for development */
-		disable_auth = <0x0>;
-	};
-};
diff --git a/plat/arm/board/a5ds/platform.mk b/plat/arm/board/a5ds/platform.mk
index d42b2bf..7198842 100644
--- a/plat/arm/board/a5ds/platform.mk
+++ b/plat/arm/board/a5ds/platform.mk
@@ -1,9 +1,12 @@
 #
-# Copyright (c) 2019, Arm Limited. All rights reserved.
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+# Firmware Configuration Framework sources
+include lib/fconf/fconf.mk
+
 # Add `libfdt` and Arm common helpers required for Dynamic Config
 include lib/libfdt/libfdt.mk
 
@@ -67,7 +70,7 @@
 # Add the FDT_SOURCES and options for Dynamic Config (only for Unix env)
 ifdef UNIX_MK
 
-FVP_TB_FW_CONFIG	:=	${BUILD_PLAT}/fdts/a5ds_tb_fw_config.dtb
+FVP_TB_FW_CONFIG	:=	${BUILD_PLAT}/fdts/a5ds_fw_config.dtb
 
 # Add the TB_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${FVP_TB_FW_CONFIG},--tb-fw-config))
@@ -77,7 +80,7 @@
 # Add the HW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${FVP_HW_CONFIG},--hw-config))
 
-FDT_SOURCES		+=	plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts \
+FDT_SOURCES		+=	plat/arm/board/a5ds/fdts/a5ds_fw_config.dts \
 					${FVP_HW_CONFIG_DTS}
 endif
 
diff --git a/plat/arm/board/common/board_arm_trusted_boot.c b/plat/arm/board/common/board_arm_trusted_boot.c
index c71e932..3c19230 100644
--- a/plat/arm/board/common/board_arm_trusted_boot.c
+++ b/plat/arm/board/common/board_arm_trusted_boot.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,130 +8,61 @@
 #include <stdint.h>
 #include <string.h>
 
+#include <common/debug.h>
+#include <drivers/arm/cryptocell/cc_rotpk.h>
+#include <drivers/delay_timer.h>
 #include <lib/cassert.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/common_def.h>
 #include <plat/common/platform.h>
-#include <tools_share/tbbr_oid.h>
 #include <platform_def.h>
-
-/* SHA256 algorithm */
-#define SHA256_BYTES			32
-
-/* ROTPK locations */
-#define ARM_ROTPK_REGS_ID		1
-#define ARM_ROTPK_DEVEL_RSA_ID		2
-#define ARM_ROTPK_DEVEL_ECDSA_ID	3
+#include <tools_share/tbbr_oid.h>
 
-static const unsigned char rotpk_hash_hdr[] =		\
-		"\x30\x31\x30\x0D\x06\x09\x60\x86\x48"	\
-		"\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20";
-static const unsigned int rotpk_hash_hdr_len = sizeof(rotpk_hash_hdr) - 1;
-static unsigned char rotpk_hash_der[sizeof(rotpk_hash_hdr) - 1 + SHA256_BYTES];
 
-/* Use the cryptocell variants if Cryptocell is present */
 #if !ARM_CRYPTOCELL_INTEG
 #if !ARM_ROTPK_LOCATION_ID
   #error "ARM_ROTPK_LOCATION_ID not defined"
 #endif
+#endif
 
 /* Weak definition may be overridden in specific platform */
 #pragma weak plat_get_nv_ctr
 #pragma weak plat_set_nv_ctr
 
-#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID)
-static const unsigned char arm_devel_rotpk_hash[] =	\
-		"\xB0\xF3\x82\x09\x12\x97\xD8\x3A"	\
-		"\x37\x7A\x72\x47\x1B\xEC\x32\x73"	\
-		"\xE9\x92\x32\xE2\x49\x59\xF6\x5E"	\
-		"\x8B\x4A\x4A\x46\xD8\x22\x9A\xDA";
-#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
-static const unsigned char arm_devel_rotpk_hash[] =	\
-		"\x2E\x40\xBF\x6E\xF9\x12\xBB\x98"	\
-		"\x31\x71\x09\x0E\x1E\x15\x3D\x0B"	\
-		"\xFD\xD1\xCC\x69\x4A\x98\xEB\x8B"	\
-		"\xA0\xB0\x20\x86\x4E\x6C\x07\x17";
-#endif
+extern unsigned char arm_rotpk_header[], arm_rotpk_hash_end[];
+
+static unsigned char rotpk_hash_der[ARM_ROTPK_HEADER_LEN + ARM_ROTPK_HASH_LEN];
 
 /*
- * 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
- * }
+ * Return the ROTPK hash stored in dedicated registers.
  */
-int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+int arm_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len,
 			unsigned int *flags)
 {
 	uint8_t *dst;
+	uint32_t *src, tmp;
+	unsigned int words, i;
 
 	assert(key_ptr != NULL);
 	assert(key_len != NULL);
 	assert(flags != NULL);
 
 	/* Copy the DER header */
-	memcpy(rotpk_hash_der, rotpk_hash_hdr, rotpk_hash_hdr_len);
-	dst = (uint8_t *)&rotpk_hash_der[rotpk_hash_hdr_len];
 
-#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) \
-	|| (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
-	memcpy(dst, arm_devel_rotpk_hash, SHA256_BYTES);
-#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
-	uint32_t *src, tmp;
-	unsigned int words, i;
+	memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN);
+	dst = (uint8_t *)&rotpk_hash_der[ARM_ROTPK_HEADER_LEN];
 
-	/*
-	 * Append the hash from Trusted Root-Key Storage registers. The hash has
-	 * not been written linearly into the registers, so we have to do a bit
-	 * of byte swapping:
-	 *
-	 *     0x00    0x04    0x08    0x0C    0x10    0x14    0x18    0x1C
-	 * +---------------------------------------------------------------+
-	 * | Reg0  | Reg1  | Reg2  | Reg3  | Reg4  | Reg5  | Reg6  | Reg7  |
-	 * +---------------------------------------------------------------+
-	 *  | ...                    ... |   | ...                   ...  |
-	 *  |       +--------------------+   |                    +-------+
-	 *  |       |                        |                    |
-	 *  +----------------------------+   +----------------------------+
-	 *          |                    |                        |       |
-	 *  +-------+                    |   +--------------------+       |
-	 *  |                            |   |                            |
-	 *  v                            v   v                            v
-	 * +---------------------------------------------------------------+
-	 * |                               |                               |
-	 * +---------------------------------------------------------------+
-	 *  0                           15  16                           31
-	 *
-	 * Additionally, we have to access the registers in 32-bit words
-	 */
-	words = SHA256_BYTES >> 3;
+	words = ARM_ROTPK_HASH_LEN >> 2;
 
-	/* Swap bytes 0-15 (first four registers) */
 	src = (uint32_t *)TZ_PUB_KEY_HASH_BASE;
 	for (i = 0 ; i < words ; i++) {
 		tmp = src[words - 1 - i];
 		/* Words are read in little endian */
-		*dst++ = (uint8_t)((tmp >> 24) & 0xFF);
-		*dst++ = (uint8_t)((tmp >> 16) & 0xFF);
-		*dst++ = (uint8_t)((tmp >> 8) & 0xFF);
 		*dst++ = (uint8_t)(tmp & 0xFF);
-	}
-
-	/* Swap bytes 16-31 (last four registers) */
-	src = (uint32_t *)(TZ_PUB_KEY_HASH_BASE + SHA256_BYTES / 2);
-	for (i = 0 ; i < words ; i++) {
-		tmp = src[words - 1 - i];
-		*dst++ = (uint8_t)((tmp >> 24) & 0xFF);
-		*dst++ = (uint8_t)((tmp >> 16) & 0xFF);
 		*dst++ = (uint8_t)((tmp >> 8) & 0xFF);
-		*dst++ = (uint8_t)(tmp & 0xFF);
+		*dst++ = (uint8_t)((tmp >> 16) & 0xFF);
+		*dst++ = (uint8_t)((tmp >> 24) & 0xFF);
 	}
-#endif /* (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) \
-		  || (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID) */
 
 	*key_ptr = (void *)rotpk_hash_der;
 	*key_len = (unsigned int)sizeof(rotpk_hash_der);
@@ -139,6 +70,65 @@
 	return 0;
 }
 
+#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \
+    (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
+/*
+ * Return development ROTPK hash generated from ROT_KEY.
+ */
+int arm_get_rotpk_info_dev(void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+	*key_ptr = arm_rotpk_header;
+	*key_len = arm_rotpk_hash_end - arm_rotpk_header;
+	*flags = ROTPK_IS_HASH;
+	return 0;
+}
+#endif
+
+#if ARM_CRYPTOCELL_INTEG
+/*
+ * Return ROTPK hash from CryptoCell.
+ */
+int arm_get_rotpk_info_cc(void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+	unsigned char *dst;
+
+	assert(key_ptr != NULL);
+	assert(key_len != NULL);
+	assert(flags != NULL);
+
+	/* Copy the DER header */
+	memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN);
+	dst = &rotpk_hash_der[ARM_ROTPK_HEADER_LEN];
+	*key_ptr = rotpk_hash_der;
+	*key_len = sizeof(rotpk_hash_der);
+	return cc_get_rotpk_hash(dst, ARM_ROTPK_HASH_LEN, flags);
+}
+#endif
+
+/*
+ * Wraper function for most Arm platforms to get ROTPK hash.
+ */
+int arm_get_rotpk_info(void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+#if ARM_CRYPTOCELL_INTEG
+	return arm_get_rotpk_info_cc(key_ptr, key_len, flags);
+#else
+
+#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \
+    (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
+	return arm_get_rotpk_info_dev(key_ptr, key_len, flags);
+#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
+	return arm_get_rotpk_info_regs(key_ptr, key_len, flags);
+#else
+	return 1;
+#endif
+
+#endif /* ARM_CRYPTOCELL_INTEG */
+}
+
 /*
  * Return the non-volatile counter value stored in the platform. The cookie
  * will contain the OID of the counter in the certificate.
@@ -179,37 +169,3 @@
 {
 	return 1;
 }
-#else /* ARM_CRYPTOCELL_INTEG */
-
-#include <drivers/arm/cryptocell/cc_rotpk.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)
-{
-	unsigned char *dst;
-
-	assert(key_ptr != NULL);
-	assert(key_len != NULL);
-	assert(flags != NULL);
-
-	/* Copy the DER header */
-	memcpy(rotpk_hash_der, rotpk_hash_hdr, rotpk_hash_hdr_len);
-	dst = &rotpk_hash_der[rotpk_hash_hdr_len];
-	*key_ptr = rotpk_hash_der;
-	*key_len = sizeof(rotpk_hash_der);
-	return cc_get_rotpk_hash(dst, SHA256_BYTES, flags);
-}
-#endif /* ARM_CRYPTOCELL_INTEG */
diff --git a/plat/arm/board/common/board_common.mk b/plat/arm/board/common/board_common.mk
index b98dfd4..459156b 100644
--- a/plat/arm/board/common/board_common.mk
+++ b/plat/arm/board/common/board_common.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -12,31 +12,60 @@
 BL2_SOURCES		+=	drivers/cfi/v2m/v2m_flash.c
 
 ifneq (${TRUSTED_BOARD_BOOT},0)
-  ifneq (${ARM_CRYPTOCELL_INTEG}, 1)
-    # ROTPK hash location
-    ifeq (${ARM_ROTPK_LOCATION}, regs)
-        ARM_ROTPK_LOCATION_ID = ARM_ROTPK_REGS_ID
-    else ifeq (${ARM_ROTPK_LOCATION}, devel_rsa)
-        KEY_ALG := rsa
-        ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_RSA_ID
-    else ifeq (${ARM_ROTPK_LOCATION}, devel_ecdsa)
-        KEY_ALG := ecdsa
-        ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_ECDSA_ID
-    else
-        $(error "Unsupported ARM_ROTPK_LOCATION value")
-    endif
-    $(eval $(call add_define,ARM_ROTPK_LOCATION_ID))
+ifneq (${ARM_CRYPTOCELL_INTEG}, 1)
+# ROTPK hash location
+ifeq (${ARM_ROTPK_LOCATION}, regs)
+	ARM_ROTPK_LOCATION_ID = ARM_ROTPK_REGS_ID
+else ifeq (${ARM_ROTPK_LOCATION}, devel_rsa)
+	CRYPTO_ALG=rsa
+	ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_RSA_ID
+	ARM_ROTPK_HASH = plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin
+$(eval $(call add_define_val,ARM_ROTPK_HASH,'"$(ARM_ROTPK_HASH)"'))
+$(BUILD_PLAT)/bl2/arm_dev_rotpk.o : $(ARM_ROTPK_HASH)
+$(warning Development keys support for FVP is deprecated. Use `regs` \
+option instead)
+else ifeq (${ARM_ROTPK_LOCATION}, devel_ecdsa)
+	CRYPTO_ALG=ec
+	ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_ECDSA_ID
+	ARM_ROTPK_HASH = plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin
+$(eval $(call add_define_val,ARM_ROTPK_HASH,'"$(ARM_ROTPK_HASH)"'))
+$(BUILD_PLAT)/bl2/arm_dev_rotpk.o : $(ARM_ROTPK_HASH)
+$(warning Development keys support for FVP is deprecated. Use `regs` \
+option instead)
+else
+	$(error "Unsupported ARM_ROTPK_LOCATION value")
+endif
+
+$(eval $(call add_define,ARM_ROTPK_LOCATION_ID))
+
+# Force generation of the new hash if ROT_KEY is specified
+ifdef ROT_KEY
+	HASH_PREREQUISITES = $(ROT_KEY) FORCE
+FORCE:
+else
+	HASH_PREREQUISITES = $(ROT_KEY)
+endif
+
+$(ARM_ROTPK_HASH) : $(HASH_PREREQUISITES)
+ifndef ROT_KEY
+	$(error Cannot generate hash: no ROT_KEY defined)
+endif
+	openssl ${CRYPTO_ALG} -in $< -pubout -outform DER | openssl dgst \
+		-sha256 -binary > $@
+
+# Certificate NV-Counters. Use values corresponding to tied off values in
+# ARM development platforms
+TFW_NVCTR_VAL	?=	31
+NTFW_NVCTR_VAL	?=	223
+else
+# Certificate NV-Counters when CryptoCell is integrated. For development
+# platforms we set the counter to first valid value.
+TFW_NVCTR_VAL	?=	0
+NTFW_NVCTR_VAL	?=	0
+endif
+BL1_SOURCES		+=	plat/arm/board/common/board_arm_trusted_boot.c \
+				plat/arm/board/common/rotpk/arm_dev_rotpk.S
+BL2_SOURCES		+=	plat/arm/board/common/board_arm_trusted_boot.c \
+				plat/arm/board/common/rotpk/arm_dev_rotpk.S
 
-    # Certificate NV-Counters. Use values corresponding to tied off values in
-    # ARM development platforms
-    TFW_NVCTR_VAL	?=	31
-    NTFW_NVCTR_VAL	?=	223
-  else
-    # Certificate NV-Counters when CryptoCell is integrated. For development
-    # platforms we set the counter to first valid value.
-    TFW_NVCTR_VAL	?=	0
-    NTFW_NVCTR_VAL	?=	0
-  endif
-    BL1_SOURCES		+=	plat/arm/board/common/board_arm_trusted_boot.c
-    BL2_SOURCES		+=	plat/arm/board/common/board_arm_trusted_boot.c
 endif
diff --git a/plat/arm/board/common/rotpk/arm_dev_rotpk.S b/plat/arm/board/common/rotpk/arm_dev_rotpk.S
new file mode 100644
index 0000000..80f2192
--- /dev/null
+++ b/plat/arm/board/common/rotpk/arm_dev_rotpk.S
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "plat/arm/common/arm_def.h"
+
+	.global arm_rotpk_header
+	.global arm_rotpk_header_end
+	.section .rodata.arm_rotpk_hash, "a"
+
+arm_rotpk_header:
+	.byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
+	.byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+arm_rotpk_header_len:
+
+#ifdef ARM_ROTPK_HASH
+	.global arm_rotpk_hash_end
+	.incbin ARM_ROTPK_HASH
+arm_rotpk_hash_end:
+#endif
+
+.if ARM_ROTPK_HEADER_LEN != arm_rotpk_header_len - arm_rotpk_header
+.error "Invalid ROTPK header length."
+.endif
diff --git a/plat/arm/board/corstone700/corstone700_plat.c b/plat/arm/board/corstone700/corstone700_plat.c
index cee6fd6..e2ade70 100644
--- a/plat/arm/board/corstone700/corstone700_plat.c
+++ b/plat/arm/board/corstone700/corstone700_plat.c
@@ -1,10 +1,12 @@
 /*
- * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <common/bl_common.h>
+
+#include <mhu.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 #include <platform_def.h>
@@ -26,6 +28,7 @@
  */
 void __init plat_arm_pwrc_setup(void)
 {
+	mhu_secure_init();
 }
 
 unsigned int plat_get_syscnt_freq2(void)
diff --git a/plat/arm/board/corstone700/corstone700_stack_protector.c b/plat/arm/board/corstone700/corstone700_stack_protector.c
new file mode 100644
index 0000000..6fd09da
--- /dev/null
+++ b/plat/arm/board/corstone700/corstone700_stack_protector.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2020, 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 is returned */
+}
diff --git a/plat/arm/board/corstone700/corstone700_topology.c b/plat/arm/board/corstone700/corstone700_topology.c
index d9445e0..904f5ab 100644
--- a/plat/arm/board/corstone700/corstone700_topology.c
+++ b/plat/arm/board/corstone700/corstone700_topology.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,8 +8,8 @@
 #include <plat/common/platform.h>
 
 /* The Corstone700 power domain tree descriptor */
-static unsigned char corstone700_power_domain_tree_desc
-			[PLAT_ARM_CLUSTER_COUNT + 2];
+static unsigned char corstone700_power_domain_tree_desc[PLAT_ARM_CLUSTER_COUNT
+							+ 2];
 /*******************************************************************************
  * This function dynamically constructs the topology according to
  * CLUSTER_COUNT and returns it.
diff --git a/plat/arm/board/corstone700/drivers/mhu/mhu.c b/plat/arm/board/corstone700/drivers/mhu/mhu.c
new file mode 100644
index 0000000..2231d11
--- /dev/null
+++ b/plat/arm/board/corstone700/drivers/mhu/mhu.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+
+#include "mhu.h"
+#include <plat_arm.h>
+#include <platform_def.h>
+
+ARM_INSTANTIATE_LOCK;
+
+#pragma weak plat_arm_pwrc_setup
+
+/*
+ * Slot 31 is reserved because the MHU hardware uses this register bit to
+ * indicate a non-secure access attempt. The total number of available slots is
+ * therefore 31 [30:0].
+ */
+#define MHU_MAX_SLOT_ID		30
+
+void mhu_secure_message_start(uintptr_t address, unsigned int slot_id)
+{
+	unsigned int intr_stat_check;
+	uint64_t timeout_cnt;
+	volatile uint8_t expiration;
+
+	assert(slot_id <= MHU_MAX_SLOT_ID);
+	arm_lock_get();
+
+	/*
+	 * Make sure any previous command has finished
+	 * and polling timeout not expired
+	 */
+
+	timeout_cnt = timeout_init_us(MHU_POLL_INTR_STAT_TIMEOUT);
+
+	do {
+		intr_stat_check = (mmio_read_32(address + CPU_INTR_S_STAT) &
+						(1 << slot_id));
+
+		expiration = timeout_elapsed(timeout_cnt);
+
+	} while ((intr_stat_check != 0U) && (expiration == 0U));
+
+	/*
+	 * Note: No risk of timer overflows while waiting
+	 * for the timeout expiration.
+	 * According to Armv8 TRM: System counter roll-over
+	 * time of not less than 40 years
+	 */
+}
+
+void mhu_secure_message_send(uintptr_t address,
+				unsigned int slot_id,
+				unsigned int message)
+{
+	unsigned char access_ready;
+	uint64_t timeout_cnt;
+	volatile uint8_t expiration;
+
+	assert(slot_id <= MHU_MAX_SLOT_ID);
+	assert((mmio_read_32(address + CPU_INTR_S_STAT) &
+						(1 << slot_id)) == 0U);
+
+	MHU_V2_ACCESS_REQUEST(address);
+
+	timeout_cnt = timeout_init_us(MHU_POLL_INTR_STAT_TIMEOUT);
+
+	do {
+		access_ready = MHU_V2_IS_ACCESS_READY(address);
+		expiration = timeout_elapsed(timeout_cnt);
+
+	} while ((access_ready == 0U) && (expiration == 0U));
+
+	/*
+	 * Note: No risk of timer overflows while waiting
+	 * for the timeout expiration.
+	 * According to Armv8 TRM: System counter roll-over
+	 * time of not less than 40 years
+	 */
+
+	mmio_write_32(address + CPU_INTR_S_SET, message);
+}
+
+void mhu_secure_message_end(uintptr_t address, unsigned int slot_id)
+{
+	assert(slot_id <= MHU_MAX_SLOT_ID);
+	/*
+	 * Clear any response we got by writing one in the relevant slot bit to
+	 * the CLEAR register
+	 */
+	MHU_V2_CLEAR_REQUEST(address);
+
+	arm_lock_release();
+}
+
+void __init mhu_secure_init(void)
+{
+	arm_lock_init();
+
+	/*
+	 * The STAT register resets to zero. Ensure it is in the expected state,
+	 * as a stale or garbage value would make us think it's a message we've
+	 * already sent.
+	 */
+
+	assert(mmio_read_32(PLAT_SDK700_MHU0_SEND + CPU_INTR_S_STAT) == 0);
+}
diff --git a/plat/arm/board/corstone700/drivers/mhu/mhu.h b/plat/arm/board/corstone700/drivers/mhu/mhu.h
new file mode 100644
index 0000000..3808746
--- /dev/null
+++ b/plat/arm/board/corstone700/drivers/mhu/mhu.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MHU_H
+#define MHU_H
+
+#define MHU_POLL_INTR_STAT_TIMEOUT		50000 /*timeout value in us*/
+
+/* CPU MHU secure channel registers */
+#define CPU_INTR_S_STAT				0x00
+#define CPU_INTR_S_SET				0x0C
+
+/* MHUv2 Control Registers Offsets */
+#define MHU_V2_MSG_CFG_OFFSET			0xF80
+#define MHU_V2_ACCESS_REQ_OFFSET		0xF88
+#define MHU_V2_ACCESS_READY_OFFSET		0xF8C
+
+#define MHU_V2_ACCESS_REQUEST(addr)     \
+	mmio_write_32((addr) + MHU_V2_ACCESS_REQ_OFFSET, 0x1)
+
+#define MHU_V2_CLEAR_REQUEST(addr)      \
+	mmio_write_32((addr) + MHU_V2_ACCESS_REQ_OFFSET, 0x0)
+
+#define MHU_V2_IS_ACCESS_READY(addr)    \
+	(mmio_read_32((addr) + MHU_V2_ACCESS_READY_OFFSET) & 0x1)
+
+void mhu_secure_message_start(uintptr_t address, unsigned int slot_id);
+void mhu_secure_message_send(uintptr_t address,
+				unsigned int slot_id,
+				unsigned int message);
+void mhu_secure_message_end(uintptr_t address, unsigned int slot_id);
+void mhu_secure_init(void);
+
+#endif /* MHU_H */
diff --git a/plat/arm/board/corstone700/include/platform_def.h b/plat/arm/board/corstone700/include/platform_def.h
index 8dff3ec..0fb74e4 100644
--- a/plat/arm/board/corstone700/include/platform_def.h
+++ b/plat/arm/board/corstone700/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,20 +9,35 @@
 
 #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/common/common_def.h>
 
+/* 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		32000000
+#define V2M_IOFPGA_UART1_CLK_IN_HZ		32000000
+
 /* Core/Cluster/Thread counts for Corstone700 */
 #define CORSTONE700_CLUSTER_COUNT		U(1)
 #define CORSTONE700_MAX_CPUS_PER_CLUSTER	U(4)
 #define CORSTONE700_MAX_PE_PER_CPU		U(1)
-#define CORSTONE700_CORE_COUNT		(CORSTONE700_CLUSTER_COUNT *	\
-					CORSTONE700_MAX_CPUS_PER_CLUSTER * \
-					CORSTONE700_MAX_PE_PER_CPU)
-#define PLATFORM_CORE_COUNT		CORSTONE700_CORE_COUNT
+
 #define PLAT_ARM_CLUSTER_COUNT		CORSTONE700_CLUSTER_COUNT
 
+#define PLATFORM_CORE_COUNT		(PLAT_ARM_CLUSTER_COUNT *       \
+					CORSTONE700_MAX_CPUS_PER_CLUSTER *   \
+					CORSTONE700_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
@@ -85,8 +100,12 @@
 					ARM_BL_REGIONS)
 
 /* GIC related constants */
-#define PLAT_ARM_GICD_BASE			0x1C010000
-#define PLAT_ARM_GICC_BASE			0x1C02F000
+#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)
@@ -101,46 +120,46 @@
  * 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
+#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)
+#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)
+#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 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_TRUSTED_MAILBOX_BASE		ARM_TRUSTED_SRAM_BASE
+#define PLAT_ARM_NSTIMER_FRAME_ID		U(1)
 
-#define PLAT_ARM_NS_IMAGE_OFFSET	(ARM_DRAM1_BASE + UL(0x8000000))
+#define PLAT_ARM_NS_IMAGE_OFFSET		(ARM_DRAM1_BASE + UL(0x8000000))
 
-#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
-#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
+#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
+#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 PLAT_MAX_OFF_STATE			2
 
-#define PLATFORM_STACK_SIZE		UL(0x440)
+#define PLATFORM_STACK_SIZE			UL(0x440)
 
-#define ARM_MAP_SHARED_RAM		MAP_REGION_FLAT(		\
+#define ARM_MAP_SHARED_RAM			MAP_REGION_FLAT(	\
 						ARM_SHARED_RAM_BASE,	\
 						ARM_SHARED_RAM_SIZE,	\
 						MT_DEVICE | MT_RW | MT_SECURE)
@@ -170,21 +189,21 @@
 
 #define CORSTONE700_DEVICE_BASE		(0x1A000000)
 #define CORSTONE700_DEVICE_SIZE		(0x26000000)
-#define CORSTONE700_MAP_DEVICE	MAP_REGION_FLAT(			\
-					CORSTONE700_DEVICE_BASE,	\
-					CORSTONE700_DEVICE_SIZE,	\
-					MT_DEVICE | MT_RW | MT_SECURE)
+#define CORSTONE700_MAP_DEVICE		MAP_REGION_FLAT(		\
+						CORSTONE700_DEVICE_BASE,\
+						CORSTONE700_DEVICE_SIZE,\
+						MT_DEVICE | MT_RW | MT_SECURE)
 
-#define ARM_IRQ_SEC_PHY_TIMER		29
+#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 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
@@ -192,7 +211,7 @@
  * as Group 0 interrupts.
  */
 #define ARM_G1S_IRQ_PROPS(grp) \
-	INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,	\
+	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), \
@@ -217,11 +236,11 @@
  * as Group 0 interrupts.
  */
 #define PLAT_ARM_G1S_IRQ_PROPS(grp)	\
-	ARM_G1S_IRQ_PROPS(grp),	\
-	INTR_PROP_DESC(CORSTONE700_IRQ_TZ_WDOG,	\
-		GIC_HIGHEST_SEC_PRIORITY, (grp), GIC_INTR_CFG_LEVEL),	\
-	INTR_PROP_DESC(CORSTONE700_IRQ_SEC_SYS_TIMER,	\
-		GIC_HIGHEST_SEC_PRIORITY, (grp), GIC_INTR_CFG_LEVEL)	\
+	ARM_G1S_IRQ_PROPS(grp), \
+	INTR_PROP_DESC(CORSTONE700_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, \
+			(grp), GIC_INTR_CFG_LEVEL), \
+	INTR_PROP_DESC(CORSTONE700_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)
 
diff --git a/plat/arm/board/corstone700/platform.mk b/plat/arm/board/corstone700/platform.mk
index bff3589..a4d4f22 100644
--- a/plat/arm/board/corstone700/platform.mk
+++ b/plat/arm/board/corstone700/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -11,16 +11,19 @@
 				plat/arm/common/arm_common.c	\
 				lib/xlat_tables/aarch32/xlat_tables.c	\
 				lib/xlat_tables/xlat_tables_common.c	\
-				${CORSTONE700_CPU_LIBS}
+				${CORSTONE700_CPU_LIBS}	\
+				plat/arm/board/corstone700/drivers/mhu/mhu.c
 
-PLAT_INCLUDES		:=	-Iplat/arm/board/corstone700/include
+PLAT_INCLUDES		:=	-Iplat/arm/board/corstone700/include	\
+				-Iinclude/plat/arm/common	\
+				-Iplat/arm/board/corstone700/drivers/mhu
 
 NEED_BL32		:=	yes
 
-CORSTONE700_GIC_SOURCES      :=	drivers/arm/gic/common/gic_common.c     \
-				drivers/arm/gic/v2/gicv2_main.c         \
-				drivers/arm/gic/v2/gicv2_helpers.c      \
-				plat/common/plat_gicv2.c                \
+CORSTONE700_GIC_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
+				drivers/arm/gic/v2/gicv2_main.c		\
+				drivers/arm/gic/v2/gicv2_helpers.c	\
+				plat/common/plat_gicv2.c		\
 				plat/arm/common/arm_gicv2.c
 
 # BL1/BL2 Image not a part of the capsule Image for Corstone700
diff --git a/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk b/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk
index 57e1ec3..acee6c3 100644
--- a/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk
+++ b/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -15,4 +15,10 @@
 			plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c	\
 			${CORSTONE700_GIC_SOURCES}
 
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+	ifneq (${ENABLE_STACK_PROTECTOR},none)
+		BL32_SOURCES += plat/arm/board/corstone700/corstone700_stack_protector.c
+	endif
+endif
+
 include plat/arm/common/sp_min/arm_sp_min.mk
diff --git a/plat/arm/board/fvp/fdts/fvp_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_fw_config.dts
new file mode 100644
index 0000000..d0f6033
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_fw_config.dts
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "arm,dyn_cfg-dtb_registry";
+
+		/* tb_fw_config is temporarily contained on this dtb */
+		tb_fw-config {
+			load-address = <0x0 0x4001010>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+
+		hw-config {
+			load-address = <0x0 0x82000000>;
+			max-size = <0x01000000>;
+			id = <HW_CONFIG_ID>;
+		};
+
+		/*
+		 * Load SoC and TOS firmware configs at the base of
+		 * non shared SRAM. The runtime checks ensure we don't
+		 * overlap BL2, BL31 or BL32. The NT firmware config
+		 * is loaded at base of DRAM.
+		 */
+		soc_fw-config {
+			load-address = <0x0 0x04001000>;
+			max-size = <0x200>;
+			id = <SOC_FW_CONFIG_ID>;
+		};
+
+		tos_fw-config {
+			load-address = <0x0 0x04001200>;
+			max-size = <0x200>;
+			id = <TOS_FW_CONFIG_ID>;
+		};
+
+		nt_fw-config {
+			load-address = <0x0 0x80000000>;
+			max-size = <0x200>;
+			id = <NT_FW_CONFIG_ID>;
+		};
+	};
+
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+
+	arm-io_policies {
+		fip-handles {
+			compatible = "arm,io-fip-handle";
+			scp_bl2_uuid = <0x3dfd6697 0x49e8be89 0xa1785dae 0x13826040>;
+			bl31_uuid = <0x6d08d447 0x4698fe4c 0x5029959b 0x005abdcb>;
+			bl32_uuid = <0x89e1d005 0x4713dc53 0xa502b8d 0x383e7a4b>;
+			bl32_extra1_uuid = <0x9bc2700b 0x40785a2a 0x560a659f 0x88827382>;
+			bl32_extra2_uuid = <0xb17ba88e 0x4d3fa2cf 0xbbe7fd85 0xd92002a5>;
+			bl33_uuid = <0xa7eed0d6 0x4bd5eafc 0x34998297 0xe4b634f2>;
+			hw_cfg_uuid = <0xd9f1b808 0x4993cfc9 0xbc6f62a9 0xcc65726b>;
+			soc_fw_cfg_uuid = <0x4b817999 0x46fb7603 0x268d8e8c 0xe059787f>;
+			tos_fw_cfg_uuid = <0x1a7c2526 0x477fc6db 0xc4c4968d 0x218024b0>;
+			nt_fw_cfg_uuid = <0x1598da28 0x447ee893 0xaf1a66ac 0xf9501580>;
+			t_key_cert_uuid = <0x90e87e82 0x11e460f8 0x7a77b4a1 0x4cf9b421>;
+			scp_fw_key_uuid = <0xa1214202 0x11e460f8 0x3cf39b8d 0x14a0150e>;
+			soc_fw_key_uuid = <0xccbeb88a 0x11e460f9 0x48ebd09a 0xf8dcd822>;
+			tos_fw_key_cert_uuid = <0x3d67794 0x11e460fb 0x10b7dd85 0x4ee8c5b>;
+			nt_fw_key_cert_uuid = <0x2a83d58a 0x11e460fb 0x30dfaf8a 0x5998c4bb>;
+			scp_fw_content_cert_uuid = <0x046fbe44 0x11e4635e 0xd8738bb2 0x5696aeea>;
+			soc_fw_content_cert_uuid = <0x200cb2e2 0x11e4635e 0xccabe89c 0x66b62bf9>;
+			tos_fw_content_cert_uuid = <0x11449fa4 0x11e4635e 0x53f2887 0x3df32a72>;
+			nt_fw_content_cert_uuid = <0xf3c1c48e 0x11e4635d 0xee87a9a7 0xa73fb240>;
+		};
+	};
+};
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
new file mode 100644
index 0000000..e1c106f
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+/dts-v1/;
+
+/ {
+	compatible = "spci-core-manifest-1.0";
+
+	attribute {
+		maj_ver = <0x0>;
+		min_ver = <0x9>;
+		runtime_el = <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
deleted file mode 100644
index ce58938..0000000
--- a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/dts-v1/;
-
-/ {
-	/* Platform Config */
-	plat_arm_bl2 {
-		compatible = "arm,tb_fw";
-		hw_config_addr = <0x0 0x82000000>;
-		hw_config_max_size = <0x01000000>;
-		/* Disable authentication for development */
-		disable_auth = <0x0>;
-		/*
-		 * Load SoC and TOS firmware configs at the base of
-		 * non shared SRAM. The runtime checks ensure we don't
-		 * overlap BL2, BL31 or BL32. The NT firmware config
-		 * is loaded at base of DRAM.
-		 */
-		soc_fw_config_addr = <0x0 0x04001000>;
-		soc_fw_config_max_size = <0x200>;
-		tos_fw_config_addr = <0x0 0x04001200>;
-		tos_fw_config_max_size = <0x200>;
-		nt_fw_config_addr = <0x0 0x80000000>;
-		nt_fw_config_max_size = <0x200>;
-		/*
-		 * The following two entries are placeholders for Mbed TLS
-		 * heap information. The default values don't matter since
-		 * they will be overwritten by BL1.
-		 * In case of having shared Mbed TLS heap between BL1 and BL2,
-		 * BL1 will populate these two properties with the respective
-		 * info about the shared heap. This info will be available for
-		 * BL2 in order to locate and re-use the heap.
-		 */
-		mbedtls_heap_addr = <0x0 0x0>;
-		mbedtls_heap_size = <0x0>;
-	};
-};
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index ffaa93d..2c880fc 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -86,6 +86,9 @@
 #ifdef __aarch64__
 	ARM_MAP_DRAM2,
 #endif
+#if defined(SPD_spmd)
+	ARM_MAP_TRUSTED_DRAM,
+#endif
 #ifdef SPD_tspd
 	ARM_MAP_TSP_SEC_MEM,
 #endif
diff --git a/plat/arm/board/fvp/fvp_io_storage.c b/plat/arm/board/fvp/fvp_io_storage.c
index 9c4c1d5..109d321 100644
--- a/plat/arm/board/fvp/fvp_io_storage.c
+++ b/plat/arm/board/fvp/fvp_io_storage.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -120,18 +120,22 @@
 {
 	int io_result;
 
-	arm_io_setup();
+	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);
-	assert(io_result == 0);
+	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);
-	assert(io_result == 0);
-
-	/* Ignore improbable errors in release builds */
-	(void)io_result;
+	if (io_result < 0) {
+		panic();
+	}
 }
 
 /*
diff --git a/plat/arm/board/fvp/fvp_trusted_boot.c b/plat/arm/board/fvp/fvp_trusted_boot.c
index dc50764..a09b80e 100644
--- a/plat/arm/board/fvp/fvp_trusted_boot.c
+++ b/plat/arm/board/fvp/fvp_trusted_boot.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,12 +9,31 @@
 #include <string.h>
 
 #include <lib/mmio.h>
-
+#include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 #include <platform_def.h>
 #include <tools_share/tbbr_oid.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(key_ptr, key_len, flags);
+}
+
+/*
  * Store a new non-volatile counter value.
  *
  * On some FVP versions, the non-volatile counters are read-only so this
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index c2b7b98..bfe207a 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -116,12 +116,18 @@
 # define PLAT_ARM_MAX_BL2_SIZE	(UL(0x11000) - FVP_BL2_ROMLIB_OPTIMIZATION)
 #endif
 
+#if RESET_TO_BL31
+/* Size of Trusted SRAM - the first 4KB of shared memory */
+#define PLAT_ARM_MAX_BL31_SIZE		(PLAT_ARM_TRUSTED_SRAM_SIZE - \
+					 ARM_SHARED_RAM_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(0x3B000)
+#endif /* RESET_TO_BL31 */
 
 #ifndef __aarch64__
 /*
@@ -139,13 +145,13 @@
 # if TRUSTED_BOARD_BOOT
 #  define PLATFORM_STACK_SIZE		UL(0x1000)
 # else
-#  define PLATFORM_STACK_SIZE		UL(0x440)
+#  define PLATFORM_STACK_SIZE		UL(0x500)
 # endif
 #elif defined(IMAGE_BL2)
 # if TRUSTED_BOARD_BOOT
 #  define PLATFORM_STACK_SIZE		UL(0x1000)
 # else
-#  define PLATFORM_STACK_SIZE		UL(0x400)
+#  define PLATFORM_STACK_SIZE		UL(0x440)
 # endif
 #elif defined(IMAGE_BL2U)
 # define PLATFORM_STACK_SIZE		UL(0x400)
diff --git a/plat/arm/board/fvp/jmptbl.i b/plat/arm/board/fvp/jmptbl.i
index 6ccdd28..b1b9ed4 100644
--- a/plat/arm/board/fvp/jmptbl.i
+++ b/plat/arm/board/fvp/jmptbl.i
@@ -20,6 +20,8 @@
 fdt     fdt_check_header
 fdt     fdt_node_offset_by_compatible
 fdt     fdt_setprop_inplace_namelen_partial
+fdt     fdt_first_subnode
+fdt     fdt_next_subnode
 mbedtls mbedtls_asn1_get_alg
 mbedtls mbedtls_asn1_get_alg_null
 mbedtls mbedtls_asn1_get_bitstring_null
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 97a326c..05c11ce 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -10,6 +10,11 @@
 # Use the SP804 timer instead of the generic one
 FVP_USE_SP804_TIMER	:= 0
 
+# Use fconf based io for FVP
+ifeq ($(BL2_AT_EL3), 0)
+USE_FCONF_BASED_IO	:= 1
+endif
+
 # Default cluster count for FVP
 FVP_CLUSTER_COUNT	:= 2
 
@@ -117,6 +122,8 @@
 					lib/cpus/aarch64/neoverse_zeus.S	\
 					lib/cpus/aarch64/cortex_hercules.S	\
 					lib/cpus/aarch64/cortex_hercules_ae.S	\
+					lib/cpus/aarch64/cortex_klein.S	        \
+					lib/cpus/aarch64/cortex_matterhorn.S	\
 					lib/cpus/aarch64/cortex_a65.S		\
 					lib/cpus/aarch64/cortex_a65ae.S
 	endif
@@ -139,7 +146,6 @@
 				plat/arm/board/fvp/fvp_bl1_setup.c		\
 				plat/arm/board/fvp/fvp_err.c			\
 				plat/arm/board/fvp/fvp_io_storage.c		\
-				plat/arm/board/fvp/fvp_trusted_boot.c		\
 				${FVP_CPU_LIBS}					\
 				${FVP_INTERCONNECT_SOURCES}
 
@@ -158,7 +164,6 @@
 				plat/arm/board/fvp/fvp_bl2_setup.c		\
 				plat/arm/board/fvp/fvp_err.c			\
 				plat/arm/board/fvp/fvp_io_storage.c		\
-				plat/arm/board/fvp/fvp_trusted_boot.c		\
 				plat/arm/common/arm_nor_psci_mem_protect.c	\
 				${FVP_SECURITY_SOURCES}
 
@@ -207,12 +212,12 @@
 ifdef UNIX_MK
 FVP_HW_CONFIG_DTS	:=	fdts/${FVP_DT_PREFIX}.dts
 FDT_SOURCES		+=	$(addprefix plat/arm/board/fvp/fdts/,	\
-					${PLAT}_tb_fw_config.dts	\
+					${PLAT}_fw_config.dts		\
 					${PLAT}_soc_fw_config.dts	\
 					${PLAT}_nt_fw_config.dts	\
 				)
 
-FVP_TB_FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+FVP_TB_FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
 FVP_SOC_FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_soc_fw_config.dtb
 FVP_NT_FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb
 
@@ -224,6 +229,14 @@
 $(eval $(call TOOL_ADD_PAYLOAD,${FVP_TOS_FW_CONFIG},--tos-fw-config))
 endif
 
+ifeq (${SPD},spmd)
+FDT_SOURCES		+=	plat/arm/board/fvp/fdts/${PLAT}_spmc_manifest.dts
+FVP_TOS_FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_spmc_manifest.dtb
+
+# Add the TOS_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TOS_FW_CONFIG},--tos-fw-config))
+endif
+
 # Add the TB_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${FVP_TB_FW_CONFIG},--tb-fw-config))
 # Add the SOC_FW_CONFIG to FIP and specify the same to certtool
@@ -279,7 +292,7 @@
     ifeq (${RESET_TO_SP_MIN},1)
         BL32_CFLAGS	+=	-DPLAT_XLAT_TABLES_DYNAMIC=1
     endif
-else # if AArch64
+else # AArch64
     ifeq (${RESET_TO_BL31},1)
         BL31_CFLAGS	+=	-DPLAT_XLAT_TABLES_DYNAMIC=1
     endif
@@ -288,6 +301,17 @@
     endif
 endif
 
+ifeq (${ALLOW_RO_XLAT_TABLES}, 1)
+    ifeq (${ARCH},aarch32)
+        BL32_CFLAGS	+=	-DPLAT_RO_XLAT_TABLES=1
+    else # AArch64
+        BL31_CFLAGS	+=	-DPLAT_RO_XLAT_TABLES=1
+        ifeq (${SPD},tspd)
+            BL32_CFLAGS	+=	-DPLAT_RO_XLAT_TABLES=1
+        endif
+    endif
+endif
+
 ifeq (${USE_DEBUGFS},1)
     BL31_CFLAGS	+=	-DPLAT_XLAT_TABLES_DYNAMIC=1
 endif
@@ -302,8 +326,10 @@
 include plat/arm/board/common/board_common.mk
 include plat/arm/common/arm_common.mk
 
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES		+=	plat/arm/board/fvp/fvp_trusted_boot.c
+BL2_SOURCES		+=	plat/arm/board/fvp/fvp_trusted_boot.c
 # FVP being a development platform, enable capability to disable Authentication
 # dynamically if TRUSTED_BOARD_BOOT is set.
-ifeq (${TRUSTED_BOARD_BOOT}, 1)
-        DYN_DISABLE_AUTH	:=	1
+DYN_DISABLE_AUTH	:=	1
 endif
diff --git a/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts b/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts
new file mode 100644
index 0000000..147c8f3
--- /dev/null
+++ b/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "arm,dyn_cfg-dtb_registry";
+
+		/* tb_fw_config is temporarily contained on this dtb */
+		tb_fw-config {
+			load-address = <0x0 0x80001010>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+
+		hw-config {
+			load-address = <0x0 0x82000000>;
+			max-size = <0x01000000>;
+			id = <HW_CONFIG_ID>;
+		};
+	};
+
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+	};
+};
diff --git a/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts b/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts
deleted file mode 100644
index 9ab2d96..0000000
--- a/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (c) 2019, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/dts-v1/;
-
-/ {
-	/* Platform Config */
-	plat_arm_bl2 {
-		compatible = "arm,tb_fw";
-		hw_config_addr = <0x0 0x82000000>;
-		hw_config_max_size = <0x01000000>;
-		/* Disable authentication for development */
-		disable_auth = <0x0>;
-	};
-};
diff --git a/plat/arm/board/fvp_ve/platform.mk b/plat/arm/board/fvp_ve/platform.mk
index 4d21f4b..7883719 100644
--- a/plat/arm/board/fvp_ve/platform.mk
+++ b/plat/arm/board/fvp_ve/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2019, Arm Limited. All rights reserved.
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -72,9 +72,9 @@
 # Add the FDT_SOURCES and options for Dynamic Config (only for Unix env)
 ifdef UNIX_MK
 
-FDT_SOURCES		+=	plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts
+FDT_SOURCES		+=	plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts
 
-FVP_TB_FW_CONFIG	:=	${BUILD_PLAT}/fdts/fvp_ve_tb_fw_config.dtb
+FVP_TB_FW_CONFIG	:=	${BUILD_PLAT}/fdts/fvp_ve_fw_config.dtb
 
 # Add the TB_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${FVP_TB_FW_CONFIG},--tb-fw-config))
@@ -116,6 +116,9 @@
 	PLAT_BL_COMMON_SOURCES	+=	${XLAT_TABLES_LIB_SRCS}
 endif
 
+# Firmware Configuration Framework sources
+include lib/fconf/fconf.mk
+
 # Add `libfdt` and Arm common helpers required for Dynamic Config
 include lib/libfdt/libfdt.mk
 
diff --git a/plat/arm/board/juno/fdts/juno_fw_config.dts b/plat/arm/board/juno/fdts/juno_fw_config.dts
new file mode 100644
index 0000000..cab6f2b
--- /dev/null
+++ b/plat/arm/board/juno/fdts/juno_fw_config.dts
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "arm,dyn_cfg-dtb_registry";
+
+		/* tb_fw_config is temporarily contained on this dtb */
+		tb_fw-config {
+			load-address = <0x0 0x4001010>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+	};
+
+	tb_fw-config {
+		/* Platform Config */
+		compatible = "arm,tb_fw";
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+};
diff --git a/plat/arm/board/juno/fdts/juno_tb_fw_config.dts b/plat/arm/board/juno/fdts/juno_tb_fw_config.dts
deleted file mode 100644
index a8ab6c5..0000000
--- a/plat/arm/board/juno/fdts/juno_tb_fw_config.dts
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/dts-v1/;
-
-/ {
-	/* Platform Config */
-	compatible = "arm,tb_fw";
-	/* Disable authentication for development */
-	disable_auth = <0x0>;
-	/*
-	 * The following two entries are placeholders for Mbed TLS
-	 * heap information. The default values don't matter since
-	 * they will be overwritten by BL1.
-	 * In case of having shared Mbed TLS heap between BL1 and BL2,
-	 * BL1 will populate these two properties with the respective
-	 * info about the shared heap. This info will be available for
-	 * BL2 in order to locate and re-use the heap.
-	 */
-	mbedtls_heap_addr = <0x0 0x0>;
-	mbedtls_heap_size = <0x0>;
-};
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index 16bb33d..eddd7e5 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -224,7 +224,6 @@
 
 /* MHU related constants */
 #define PLAT_CSS_MHU_BASE		UL(0x2b1f0000)
-#define PLAT_MHUV2_BASE			PLAT_CSS_MHU_BASE
 
 /*
  * Base address of the first memory region used for communication between AP
@@ -301,4 +300,7 @@
 #define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
 #endif
 
+/* Number of SCMI channels on the platform */
+#define PLAT_ARM_SCMI_CHANNEL_COUNT	U(1)
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/juno/jmptbl.i b/plat/arm/board/juno/jmptbl.i
index 6ccdd28..b1b9ed4 100644
--- a/plat/arm/board/juno/jmptbl.i
+++ b/plat/arm/board/juno/jmptbl.i
@@ -20,6 +20,8 @@
 fdt     fdt_check_header
 fdt     fdt_node_offset_by_compatible
 fdt     fdt_setprop_inplace_namelen_partial
+fdt     fdt_first_subnode
+fdt     fdt_next_subnode
 mbedtls mbedtls_asn1_get_alg
 mbedtls mbedtls_asn1_get_alg_null
 mbedtls mbedtls_asn1_get_bitstring_null
diff --git a/plat/arm/board/juno/juno_bl1_setup.c b/plat/arm/board/juno/juno_bl1_setup.c
index 89398d6..25a27da 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-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -60,17 +60,13 @@
  * The following function checks if Firmware update is needed,
  * by checking if TOC in FIP image is valid or watchdog reset happened.
  ******************************************************************************/
-int plat_arm_bl1_fwu_needed(void)
+bool plat_arm_bl1_fwu_needed(void)
 {
 	const int32_t *nv_flags_ptr = (const int32_t *)V2M_SYS_NVFLAGS_ADDR;
 
 	/* Check if TOC is invalid or watchdog reset happened. */
-	if ((arm_io_is_toc_valid() != 1) ||
-		(((*nv_flags_ptr == -EAUTH) || (*nv_flags_ptr == -ENOENT))
-		&& is_watchdog_reset()))
-		return 1;
-
-	return 0;
+	return (!arm_io_is_toc_valid() || (((*nv_flags_ptr == -EAUTH) ||
+		(*nv_flags_ptr == -ENOENT)) && is_watchdog_reset()));
 }
 
 /*******************************************************************************
diff --git a/plat/arm/board/juno/juno_topology.c b/plat/arm/board/juno/juno_topology.c
index 052ab9f..075f512 100644
--- a/plat/arm/board/juno/juno_topology.c
+++ b/plat/arm/board/juno/juno_topology.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -20,7 +20,7 @@
 		.ring_doorbell = &mhu_ring_doorbell,
 };
 
-scmi_channel_plat_info_t *plat_css_get_scmi_info(void)
+scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id)
 {
 	return &juno_scmi_plat_info;
 }
diff --git a/plat/arm/board/juno/juno_trusted_boot.c b/plat/arm/board/juno/juno_trusted_boot.c
new file mode 100644
index 0000000..25a7470
--- /dev/null
+++ b/plat/arm/board/juno/juno_trusted_boot.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <drivers/arm/cryptocell/cc_rotpk.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/common_def.h>
+#include <plat/common/platform.h>
+
+#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
+
+static unsigned char rotpk_hash_der[ARM_ROTPK_HEADER_LEN + ARM_ROTPK_HASH_LEN];
+
+extern unsigned char arm_rotpk_header[];
+
+/*
+ * Return the ROTPK hash stored in the registers of Juno board.
+ */
+static int juno_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+	uint8_t *dst;
+	uint32_t *src, tmp;
+	unsigned int words, i;
+
+	assert(key_ptr != NULL);
+	assert(key_len != NULL);
+	assert(flags != NULL);
+
+	/* Copy the DER header */
+	memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN);
+	dst = (uint8_t *)&rotpk_hash_der[ARM_ROTPK_HEADER_LEN];
+
+
+	/*
+	 * Append the hash from Trusted Root-Key Storage registers. The hash has
+	 * not been written linearly into the registers, so we have to do a bit
+	 * of byte swapping:
+	 *
+	 *     0x00    0x04    0x08    0x0C    0x10    0x14    0x18    0x1C
+	 * +---------------------------------------------------------------+
+	 * | Reg0  | Reg1  | Reg2  | Reg3  | Reg4  | Reg5  | Reg6  | Reg7  |
+	 * +---------------------------------------------------------------+
+	 *  | ...                    ... |   | ...                   ...  |
+	 *  |       +--------------------+   |                    +-------+
+	 *  |       |                        |                    |
+	 *  +----------------------------+   +----------------------------+
+	 *          |                    |                        |       |
+	 *  +-------+                    |   +--------------------+       |
+	 *  |                            |   |                            |
+	 *  v                            v   v                            v
+	 * +---------------------------------------------------------------+
+	 * |                               |                               |
+	 * +---------------------------------------------------------------+
+	 *  0                           15  16                           31
+	 *
+	 * Additionally, we have to access the registers in 32-bit words
+	 */
+	words = ARM_ROTPK_HASH_LEN >> 3;
+
+	/* Swap bytes 0-15 (first four registers) */
+	src = (uint32_t *)TZ_PUB_KEY_HASH_BASE;
+	for (i = 0 ; i < words ; i++) {
+		tmp = src[words - 1 - i];
+		/* Words are read in little endian */
+		*dst++ = (uint8_t)((tmp >> 24) & 0xFF);
+		*dst++ = (uint8_t)((tmp >> 16) & 0xFF);
+		*dst++ = (uint8_t)((tmp >> 8) & 0xFF);
+		*dst++ = (uint8_t)(tmp & 0xFF);
+	}
+
+	/* Swap bytes 16-31 (last four registers) */
+	src = (uint32_t *)(TZ_PUB_KEY_HASH_BASE + ARM_ROTPK_HASH_LEN / 2);
+	for (i = 0 ; i < words ; i++) {
+		tmp = src[words - 1 - i];
+		*dst++ = (uint8_t)((tmp >> 24) & 0xFF);
+		*dst++ = (uint8_t)((tmp >> 16) & 0xFF);
+		*dst++ = (uint8_t)((tmp >> 8) & 0xFF);
+		*dst++ = (uint8_t)(tmp & 0xFF);
+	}
+
+	*key_ptr = (void *)rotpk_hash_der;
+	*key_len = (unsigned int)sizeof(rotpk_hash_der);
+	*flags = ROTPK_IS_HASH;
+	return 0;
+}
+
+#endif
+
+/*
+ * 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)
+{
+#if ARM_CRYPTOCELL_INTEG
+	return arm_get_rotpk_info_cc(key_ptr, key_len, flags);
+#else
+
+#if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \
+    (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
+	return arm_get_rotpk_info_dev(key_ptr, key_len, flags);
+#elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
+	return juno_get_rotpk_info_regs(key_ptr, key_len, flags);
+#else
+	return 1;
+#endif
+
+#endif /* ARM_CRYPTOCELL_INTEG */
+}
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index bd6bae5..f07c1b1 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -91,8 +91,13 @@
 BL1_SOURCES		+=	drivers/arm/css/sds/sds.c
 endif
 
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES		+=	plat/arm/board/juno/juno_trusted_boot.c
+BL2_SOURCES		+=	plat/arm/board/juno/juno_trusted_boot.c
 endif
 
+endif
+
 ifneq (${RESET_TO_BL31},0)
   $(error "Using BL31 as the reset vector is not supported on ${PLAT} platform. \
   Please set RESET_TO_BL31 to 0.")
@@ -150,9 +155,17 @@
     endif
 endif
 
+ifeq (${ALLOW_RO_XLAT_TABLES}, 1)
+    ifeq (${JUNO_AARCH32_EL3_RUNTIME}, 1)
+        BL32_CFLAGS	+=	-DPLAT_RO_XLAT_TABLES=1
+    else
+        BL31_CFLAGS	+=	-DPLAT_RO_XLAT_TABLES=1
+    endif
+endif
+
 # Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES		+=	plat/arm/board/juno/fdts/${PLAT}_tb_fw_config.dts
-TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+FDT_SOURCES		+=	plat/arm/board/juno/fdts/${PLAT}_fw_config.dts
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
 
 # Add the TB_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
diff --git a/plat/arm/board/n1sdp/include/platform_def.h b/plat/arm/board/n1sdp/include/platform_def.h
index 6a309e8..cc07852 100644
--- a/plat/arm/board/n1sdp/include/platform_def.h
+++ b/plat/arm/board/n1sdp/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -90,7 +90,6 @@
 
 #define PLAT_ARM_NSTIMER_FRAME_ID		0
 #define PLAT_CSS_MHU_BASE			0x45000000
-#define PLAT_MHUV2_BASE				PLAT_CSS_MHU_BASE
 #define PLAT_MAX_PWR_LVL			2
 
 #define PLAT_ARM_G1S_IRQS			ARM_G1S_IRQS,			\
@@ -144,4 +143,7 @@
 #define SBSA_SECURE_WDOG_BASE			UL(0x2A480000)
 #define SBSA_SECURE_WDOG_TIMEOUT		UL(100)
 
+/* Number of SCMI channels on the platform */
+#define PLAT_ARM_SCMI_CHANNEL_COUNT		U(1)
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
index b150b89..136287a 100644
--- a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
+++ b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -74,7 +74,7 @@
 	0
 };
 
-scmi_channel_plat_info_t *plat_css_get_scmi_info()
+scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id)
 {
 	return &n1sdp_scmi_plat_info;
 }
diff --git a/plat/arm/board/rddaniel/fdts/rddaniel_fw_config.dts b/plat/arm/board/rddaniel/fdts/rddaniel_fw_config.dts
new file mode 100644
index 0000000..81e4cc1
--- /dev/null
+++ b/plat/arm/board/rddaniel/fdts/rddaniel_fw_config.dts
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "arm,dyn_cfg-dtb_registry";
+
+		/* tb_fw_config is temporarily contained on this dtb */
+		tb_fw-config {
+			load-address = <0x0 0x4001010>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+
+		nt_fw-config {
+			load-address = <0x0 0xFEF00000>;
+			max-size = <0x0100000>;
+			id = <NT_FW_CONFIG_ID>;
+		};
+	};
+
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+};
diff --git a/plat/arm/board/rddaniel/fdts/rddaniel_nt_fw_config.dts b/plat/arm/board/rddaniel/fdts/rddaniel_nt_fw_config.dts
new file mode 100644
index 0000000..4d4580d
--- /dev/null
+++ b/plat/arm/board/rddaniel/fdts/rddaniel_nt_fw_config.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+	/* compatible string */
+	compatible = "arm,rd-daniel";
+
+	/*
+	 * Place holder for system-id node with default values. The
+	 * value of platform-id and config-id will be set to the
+	 * correct values during the BL2 stage of boot.
+	 */
+	system-id {
+		platform-id = <0x0>;
+		config-id = <0x0>;
+		multi-chip-mode = <0x0>;
+	};
+};
diff --git a/plat/arm/board/rddaniel/include/platform_def.h b/plat/arm/board/rddaniel/include/platform_def.h
new file mode 100644
index 0000000..5163602
--- /dev/null
+++ b/plat/arm/board/rddaniel/include/platform_def.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+
+#include <sgi_base_platform_def.h>
+
+#define PLAT_ARM_CLUSTER_COUNT		U(16)
+#define CSS_SGI_MAX_CPUS_PER_CLUSTER	U(1)
+#define CSS_SGI_MAX_PE_PER_CPU		U(1)
+
+#define PLAT_CSS_MHU_BASE		UL(0x45400000)
+#define PLAT_MHUV2_BASE			PLAT_CSS_MHU_BASE
+
+#define CSS_SYSTEM_PWR_DMN_LVL		ARM_PWR_LVL2
+#define PLAT_MAX_PWR_LVL		ARM_PWR_LVL1
+
+/*
+ * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
+ */
+#ifdef __aarch64__
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 42)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 42)
+#else
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
+#endif
+
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE		UL(0x30000000)
+#define PLAT_ARM_GICC_BASE		UL(0x2C000000)
+#define PLAT_ARM_GICR_BASE		UL(0x30140000)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/rddaniel/platform.mk b/plat/arm/board/rddaniel/platform.mk
new file mode 100644
index 0000000..c7e3c7d
--- /dev/null
+++ b/plat/arm/board/rddaniel/platform.mk
@@ -0,0 +1,43 @@
+# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include plat/arm/css/sgi/sgi-common.mk
+
+RDDANIEL_BASE		=	plat/arm/board/rddaniel
+
+PLAT_INCLUDES		+=	-I${RDDANIEL_BASE}/include/
+
+SGI_CPU_SOURCES		:=	lib/cpus/aarch64/neoverse_zeus.S
+
+BL1_SOURCES		+=	${SGI_CPU_SOURCES}			\
+				${RDDANIEL_BASE}/rddaniel_err.c
+
+BL2_SOURCES		+=	${RDDANIEL_BASE}/rddaniel_plat.c	\
+				${RDDANIEL_BASE}/rddaniel_security.c	\
+				${RDDANIEL_BASE}/rddaniel_err.c		\
+				lib/utils/mem_region.c			\
+				plat/arm/common/arm_nor_psci_mem_protect.c
+
+BL31_SOURCES		+=	${SGI_CPU_SOURCES}			\
+				${RDDANIEL_BASE}/rddaniel_plat.c	\
+				${RDDANIEL_BASE}/rddaniel_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		+=	${RDDANIEL_BASE}/fdts/${PLAT}_fw_config.dts
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
+
+FDT_SOURCES		+=	${RDDANIEL_BASE}/fdts/${PLAT}_nt_fw_config.dts
+NT_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb
+
+# Add the NT_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config))
+
+override CTX_INCLUDE_AARCH32_REGS	:= 0
diff --git a/plat/arm/board/rddaniel/rddaniel_err.c b/plat/arm/board/rddaniel/rddaniel_err.c
new file mode 100644
index 0000000..5e10942
--- /dev/null
+++ b/plat/arm/board/rddaniel/rddaniel_err.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * rddaniel error handler
+ */
+void __dead2 plat_arm_error_handler(int err)
+{
+	while (1) {
+		wfi();
+	}
+}
diff --git a/plat/arm/board/rddaniel/rddaniel_plat.c b/plat/arm/board/rddaniel/rddaniel_plat.c
new file mode 100644
index 0000000..ab5251e
--- /dev/null
+++ b/plat/arm/board/rddaniel/rddaniel_plat.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+#include <sgi_plat.h>
+
+unsigned int plat_arm_sgi_get_platform_id(void)
+{
+	return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET)
+				& SID_SYSTEM_ID_PART_NUM_MASK;
+}
+
+unsigned int plat_arm_sgi_get_config_id(void)
+{
+	return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET);
+}
+
+unsigned int plat_arm_sgi_get_multi_chip_mode(void)
+{
+	return (mmio_read_32(SID_REG_BASE + SID_NODE_ID_OFFSET) &
+			SID_MULTI_CHIP_MODE_MASK) >> SID_MULTI_CHIP_MODE_SHIFT;
+}
+
+void bl31_platform_setup(void)
+{
+	sgi_bl31_common_platform_setup();
+}
diff --git a/plat/arm/board/rddaniel/rddaniel_security.c b/plat/arm/board/rddaniel/rddaniel_security.c
new file mode 100644
index 0000000..6aa38c8
--- /dev/null
+++ b/plat/arm/board/rddaniel/rddaniel_security.c
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+/* Initialize the secure environment */
+void plat_arm_security_setup(void)
+{
+}
diff --git a/plat/arm/board/rddaniel/rddaniel_topology.c b/plat/arm/board/rddaniel/rddaniel_topology.c
new file mode 100644
index 0000000..55f5e04
--- /dev/null
+++ b/plat/arm/board/rddaniel/rddaniel_topology.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+#include <plat/arm/css/common/css_pm.h>
+
+/******************************************************************************
+ * The power domain tree descriptor.
+ ******************************************************************************/
+const unsigned char rd_daniel_pd_tree_desc[] = {
+	PLAT_ARM_CLUSTER_COUNT,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER
+};
+
+/*******************************************************************************
+ * This function returns the topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return rd_daniel_pd_tree_desc;
+}
+
+/*******************************************************************************
+ * The array mapping platform core position (implemented by plat_my_core_pos())
+ * to the SCMI power domain ID implemented by SCP.
+ ******************************************************************************/
+const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = {
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x4)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x8)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x9)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xA)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xB)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xC)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xD)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xE)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0xF))
+};
diff --git a/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts b/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts
new file mode 100644
index 0000000..2719ab4
--- /dev/null
+++ b/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "arm,dyn_cfg-dtb_registry";
+
+		/* tb_fw_config is temporarily contained on this dtb */
+		tb_fw-config {
+			load-address = <0x0 0x4001010>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+
+		nt_fw-config {
+			load-address = <0x0 0xFEF00000>;
+			max-size = <0x0100000>;
+			id = <NT_FW_CONFIG_ID>;
+		};
+	};
+
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+};
diff --git a/plat/arm/board/rde1edge/fdts/rde1edge_nt_fw_config.dts b/plat/arm/board/rde1edge/fdts/rde1edge_nt_fw_config.dts
index 4176921..0af821e 100644
--- a/plat/arm/board/rde1edge/fdts/rde1edge_nt_fw_config.dts
+++ b/plat/arm/board/rde1edge/fdts/rde1edge_nt_fw_config.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -17,6 +17,7 @@
 	system-id {
 		platform-id = <0x0>;
 		config-id = <0x0>;
+		multi-chip-mode = <0x0>;
 	};
 
 };
diff --git a/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts b/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts
deleted file mode 100644
index 766dc00..0000000
--- a/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/dts-v1/;
-
-/ {
-	/* Platform Config */
-	compatible = "arm,tb_fw";
-	nt_fw_config_addr = <0x0 0xFEF00000>;
-	nt_fw_config_max_size = <0x0100000>;
-	/*
-	 * The following two entries are placeholders for Mbed TLS
-	 * heap information. The default values don't matter since
-	 * they will be overwritten by BL1.
-	 * In case of having shared Mbed TLS heap between BL1 and BL2,
-	 * BL1 will populate these two properties with the respective
-	 * info about the shared heap. This info will be available for
-	 * BL2 in order to locate and re-use the heap.
-	 */
-	mbedtls_heap_addr = <0x0 0x0>;
-	mbedtls_heap_size = <0x0>;
-};
diff --git a/plat/arm/board/rde1edge/include/platform_def.h b/plat/arm/board/rde1edge/include/platform_def.h
index 2be3f88..3fb6409 100644
--- a/plat/arm/board/rde1edge/include/platform_def.h
+++ b/plat/arm/board/rde1edge/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,7 +16,6 @@
 #define CSS_SGI_MAX_PE_PER_CPU		U(2)
 
 #define PLAT_CSS_MHU_BASE		UL(0x45400000)
-#define PLAT_MHUV2_BASE			PLAT_CSS_MHU_BASE
 
 /* Base address of DMC-620 instances */
 #define RDE1EDGE_DMC620_BASE0		UL(0x4e000000)
@@ -37,4 +36,9 @@
 #define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
 #endif
 
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE		UL(0x30000000)
+#define PLAT_ARM_GICC_BASE		UL(0x2C000000)
+#define PLAT_ARM_GICR_BASE		UL(0x300C0000)
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/rde1edge/platform.mk b/plat/arm/board/rde1edge/platform.mk
index 43c37ff..1a4dd17 100644
--- a/plat/arm/board/rde1edge/platform.mk
+++ b/plat/arm/board/rde1edge/platform.mk
@@ -29,9 +29,14 @@
 				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES		+=	${RDE1EDGE_BASE}/rde1edge_trusted_boot.c
+BL2_SOURCES		+=	${RDE1EDGE_BASE}/rde1edge_trusted_boot.c
+endif
+
 # Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES		+=	${RDE1EDGE_BASE}/fdts/${PLAT}_tb_fw_config.dts
-TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+FDT_SOURCES		+=	${RDE1EDGE_BASE}/fdts/${PLAT}_fw_config.dts
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
 
 # Add the TB_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
@@ -42,4 +47,9 @@
 # Add the NT_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config))
 
+ifneq ($(CSS_SGI_CHIP_COUNT),1)
+ $(error  "Chip count for RDE1Edge should be 1, currently set to \
+   ${CSS_SGI_CHIP_COUNT}.")
+endif
+
 override CTX_INCLUDE_AARCH32_REGS	:= 0
diff --git a/plat/arm/board/rde1edge/rde1edge_plat.c b/plat/arm/board/rde1edge/rde1edge_plat.c
index a1b8d62..44d818a 100644
--- a/plat/arm/board/rde1edge/rde1edge_plat.c
+++ b/plat/arm/board/rde1edge/rde1edge_plat.c
@@ -1,10 +1,11 @@
 /*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <plat/common/platform.h>
+#include <sgi_plat.h>
 
 unsigned int plat_arm_sgi_get_platform_id(void)
 {
@@ -16,3 +17,13 @@
 {
 	return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET);
 }
+
+unsigned int plat_arm_sgi_get_multi_chip_mode(void)
+{
+	return 0;
+}
+
+void bl31_platform_setup(void)
+{
+	sgi_bl31_common_platform_setup();
+}
diff --git a/plat/arm/board/rde1edge/rde1edge_topology.c b/plat/arm/board/rde1edge/rde1edge_topology.c
index 0b56f20..a16283e 100644
--- a/plat/arm/board/rde1edge/rde1edge_topology.c
+++ b/plat/arm/board/rde1edge/rde1edge_topology.c
@@ -7,12 +7,15 @@
 #include <plat/arm/common/plat_arm.h>
 
 /******************************************************************************
- * The power domain tree descriptor.
+ * The power domain tree descriptor. RD-E1-Edge platform consists of two
+ * clusters with eight CPUs in each cluster. The CPUs are multi-threaded with
+ * two threads per CPU.
  ******************************************************************************/
 static const unsigned char rde1edge_pd_tree_desc[] = {
+	CSS_SGI_CHIP_COUNT,
 	PLAT_ARM_CLUSTER_COUNT,
-	CSS_SGI_MAX_CPUS_PER_CLUSTER,
-	CSS_SGI_MAX_CPUS_PER_CLUSTER
+	CSS_SGI_MAX_CPUS_PER_CLUSTER * CSS_SGI_MAX_PE_PER_CPU,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER * CSS_SGI_MAX_PE_PER_CPU
 };
 
 /******************************************************************************
diff --git a/plat/arm/board/rde1edge/rde1edge_trusted_boot.c b/plat/arm/board/rde1edge/rde1edge_trusted_boot.c
new file mode 100644
index 0000000..c271f7f
--- /dev/null
+++ b/plat/arm/board/rde1edge/rde1edge_trusted_boot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, Arm Limited. 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
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+	return arm_get_rotpk_info(key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts b/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts
new file mode 100644
index 0000000..ba74b75
--- /dev/null
+++ b/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/dts-v1/;
+/ {
+	dtb-registry {
+		compatible = "arm,dyn_cfg-dtb_registry";
+
+		/* tb_fw_config is temporarily contained on this dtb */
+		tb_fw-config {
+			load-address = <0x0 0x80001010>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+
+		nt_fw-config {
+			load-address = <0x0 0xFEF00000>;
+			max-size = <0x0100000>;
+			id = <NT_FW_CONFIG_ID>;
+		};
+	};
+
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+};
+
diff --git a/plat/arm/board/rdn1edge/fdts/rdn1edge_nt_fw_config.dts b/plat/arm/board/rdn1edge/fdts/rdn1edge_nt_fw_config.dts
index fff5874..68366c5 100644
--- a/plat/arm/board/rdn1edge/fdts/rdn1edge_nt_fw_config.dts
+++ b/plat/arm/board/rdn1edge/fdts/rdn1edge_nt_fw_config.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -17,5 +17,6 @@
 	system-id {
 		platform-id = <0x0>;
 		config-id = <0x0>;
+		multi-chip-mode = <0x0>;
 	};
 };
diff --git a/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts b/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts
deleted file mode 100644
index b14d7ad..0000000
--- a/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/dts-v1/;
-
-/ {
-	/* Platform Config */
-	compatible = "arm,tb_fw";
-	nt_fw_config_addr = <0x0 0xFEF00000>;
-	nt_fw_config_max_size = <0x0100000>;
-	/*
-	 * The following two entries are placeholders for Mbed TLS
-	 * heap information. The default values don't matter since
-	 * they will be overwritten by BL1.
-	 * In case of having shared Mbed TLS heap between BL1 and BL2,
-	 * BL1 will populate these two properties with the respective
-	 * info about the shared heap. This info will be available for
-	 * BL2 in order to locate and re-use the heap.
-	 */
-	mbedtls_heap_addr = <0x0 0x0>;
-	mbedtls_heap_size = <0x0>;
-};
diff --git a/plat/arm/board/rdn1edge/include/platform_def.h b/plat/arm/board/rdn1edge/include/platform_def.h
index c635faa..ab63e23 100644
--- a/plat/arm/board/rdn1edge/include/platform_def.h
+++ b/plat/arm/board/rdn1edge/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,7 +16,6 @@
 #define CSS_SGI_MAX_PE_PER_CPU		U(1)
 
 #define PLAT_CSS_MHU_BASE		UL(0x45400000)
-#define PLAT_MHUV2_BASE			PLAT_CSS_MHU_BASE
 
 /* Base address of DMC-620 instances */
 #define RDN1EDGE_DMC620_BASE0		UL(0x4e000000)
@@ -27,15 +26,23 @@
 
 #define PLAT_MAX_PWR_LVL		ARM_PWR_LVL1
 
+/* Virtual address used by dynamic mem_protect for chunk_base */
+#define PLAT_ARM_MEM_PROTEC_VA_FRAME	UL(0xc0000000)
+
 /*
  * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes
  */
 #ifdef __aarch64__
-#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 36)
-#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 36)
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 43)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 43)
 #else
 #define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
 #define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
 #endif
 
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE		UL(0x30000000)
+#define PLAT_ARM_GICC_BASE		UL(0x2C000000)
+#define PLAT_ARM_GICR_BASE		UL(0x300C0000)
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/rdn1edge/platform.mk b/plat/arm/board/rdn1edge/platform.mk
index ca1e95e..135676d 100644
--- a/plat/arm/board/rdn1edge/platform.mk
+++ b/plat/arm/board/rdn1edge/platform.mk
@@ -26,12 +26,21 @@
 				${RDN1EDGE_BASE}/rdn1edge_plat.c	\
 				${RDN1EDGE_BASE}/rdn1edge_topology.c	\
 				drivers/cfi/v2m/v2m_flash.c		\
+				drivers/arm/gic/v3/gic600_multichip.c	\
 				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES		+=	${RDN1EDGE_BASE}/rdn1edge_trusted_boot.c
+BL2_SOURCES		+=	${RDN1EDGE_BASE}/rdn1edge_trusted_boot.c
+endif
+
+# Enable dynamic addition of MMAP regions in BL31
+BL31_CFLAGS		+=	-DPLAT_XLAT_TABLES_DYNAMIC=1
+
 # Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES		+=	${RDN1EDGE_BASE}/fdts/${PLAT}_tb_fw_config.dts
-TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+FDT_SOURCES		+=	${RDN1EDGE_BASE}/fdts/${PLAT}_fw_config.dts
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
 
 # Add the TB_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
@@ -42,4 +51,10 @@
 # Add the NT_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config))
 
+$(eval $(call CREATE_SEQ,SEQ,2))
+ifneq ($(CSS_SGI_CHIP_COUNT),$(filter $(CSS_SGI_CHIP_COUNT),$(SEQ)))
+ $(error  "Chip count for RDN1Edge platform should be one of $(SEQ), currently \
+   set to ${CSS_SGI_CHIP_COUNT}.")
+endif
+
 override CTX_INCLUDE_AARCH32_REGS	:= 0
diff --git a/plat/arm/board/rdn1edge/rdn1edge_plat.c b/plat/arm/board/rdn1edge/rdn1edge_plat.c
index 3b7e5ee..f62c6f4 100644
--- a/plat/arm/board/rdn1edge/rdn1edge_plat.c
+++ b/plat/arm/board/rdn1edge/rdn1edge_plat.c
@@ -1,10 +1,44 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <common/debug.h>
+#include <drivers/arm/gic600_multichip.h>
+#include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
+#include <sgi_base_platform_def.h>
+#include <sgi_plat.h>
+
+#if defined(IMAGE_BL31)
+static const mmap_region_t rdn1edge_dynamic_mmap[] = {
+	ARM_MAP_SHARED_RAM_REMOTE_CHIP(1),
+	CSS_SGI_MAP_DEVICE_REMOTE_CHIP(1),
+	SOC_CSS_MAP_DEVICE_REMOTE_CHIP(1)
+};
+
+static struct gic600_multichip_data rdn1e1_multichip_data __init = {
+	.rt_owner_base = PLAT_ARM_GICD_BASE,
+	.rt_owner = 0,
+	.chip_count = CSS_SGI_CHIP_COUNT,
+	.chip_addrs = {
+		PLAT_ARM_GICD_BASE >> 16,
+		(PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1)) >> 16
+	},
+	.spi_ids = {
+		{32, 255},
+		{0, 0}
+	}
+};
+
+static uintptr_t rdn1e1_multichip_gicr_frames[] = {
+	PLAT_ARM_GICR_BASE,				/* Chip 0's GICR Base */
+	PLAT_ARM_GICR_BASE +
+		CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1),	/* Chip 1's GICR BASE */
+	UL(0)						/* Zero Termination */
+};
+#endif /* IMAGE_BL31 */
 
 unsigned int plat_arm_sgi_get_platform_id(void)
 {
@@ -16,3 +50,48 @@
 {
 	return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET);
 }
+
+unsigned int plat_arm_sgi_get_multi_chip_mode(void)
+{
+	return (mmio_read_32(SID_REG_BASE + SID_NODE_ID_OFFSET) &
+			SID_MULTI_CHIP_MODE_MASK) >> SID_MULTI_CHIP_MODE_SHIFT;
+}
+
+/*
+ * IMAGE_BL31 macro is added to build bl31_platform_setup function only for BL31
+ * because PLAT_XLAT_TABLES_DYNAMIC macro is set to build only for BL31 and not
+ * for other stages.
+ */
+#if defined(IMAGE_BL31)
+void bl31_platform_setup(void)
+{
+	int i, ret;
+
+	if (plat_arm_sgi_get_multi_chip_mode() == 0 && CSS_SGI_CHIP_COUNT > 1) {
+		ERROR("Chip Count is set to %d but multi-chip mode not enabled\n",
+				CSS_SGI_CHIP_COUNT);
+		panic();
+	} else if (plat_arm_sgi_get_multi_chip_mode() == 1 &&
+			CSS_SGI_CHIP_COUNT > 1) {
+		INFO("Enabling support for multi-chip in RD-N1-Edge\n");
+
+		for (i = 0; i < ARRAY_SIZE(rdn1edge_dynamic_mmap); i++) {
+			ret = mmap_add_dynamic_region(
+					rdn1edge_dynamic_mmap[i].base_pa,
+					rdn1edge_dynamic_mmap[i].base_va,
+					rdn1edge_dynamic_mmap[i].size,
+					rdn1edge_dynamic_mmap[i].attr
+					);
+			if (ret != 0) {
+				ERROR("Failed to add dynamic mmap entry\n");
+				panic();
+			}
+		}
+
+		plat_arm_override_gicr_frames(rdn1e1_multichip_gicr_frames);
+		gic600_multichip_init(&rdn1e1_multichip_data);
+	}
+
+	sgi_bl31_common_platform_setup();
+}
+#endif /* IMAGE_BL31 */
diff --git a/plat/arm/board/rdn1edge/rdn1edge_topology.c b/plat/arm/board/rdn1edge/rdn1edge_topology.c
index 687ae35..5bbea69 100644
--- a/plat/arm/board/rdn1edge/rdn1edge_topology.c
+++ b/plat/arm/board/rdn1edge/rdn1edge_topology.c
@@ -5,14 +5,19 @@
  */
 
 #include <plat/arm/common/plat_arm.h>
+#include <plat/arm/css/common/css_pm.h>
 
 /******************************************************************************
  * The power domain tree descriptor.
  ******************************************************************************/
 static const unsigned char rdn1edge_pd_tree_desc[] = {
-	PLAT_ARM_CLUSTER_COUNT,
+	(PLAT_ARM_CLUSTER_COUNT) * (CSS_SGI_CHIP_COUNT),
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+#if (CSS_SGI_CHIP_COUNT > 1)
 	CSS_SGI_MAX_CPUS_PER_CLUSTER,
 	CSS_SGI_MAX_CPUS_PER_CLUSTER
+#endif
 };
 
 /*******************************************************************************
@@ -28,5 +33,22 @@
  * to the SCMI power domain ID implemented by SCP.
  ******************************************************************************/
 const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = {
-	0, 1, 2, 3, 4, 5, 6, 7
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x4)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x5)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x6)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x7)),
+#if (CSS_SGI_CHIP_COUNT > 1)
+	(SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x0)),
+	(SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x1)),
+	(SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x2)),
+	(SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x3)),
+	(SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x4)),
+	(SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x5)),
+	(SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x6)),
+	(SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x7)),
+#endif
 };
diff --git a/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c b/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c
new file mode 100644
index 0000000..c271f7f
--- /dev/null
+++ b/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, Arm Limited. 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
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+	return arm_get_rotpk_info(key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts b/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts
new file mode 100644
index 0000000..605cc08
--- /dev/null
+++ b/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "arm,dyn_cfg-dtb_registry";
+
+		/* tb_fw_config is temporarily contained on this dtb */
+		tb_fw-config {
+			load-address = <0x0 0x4001010>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+
+		nt_fw-config {
+			load-address = <0x0 0xFEF00000>;
+			max-size = <0x0100000>;
+			id = <NT_FW_CONFIG_ID>;
+		};
+	};
+
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+};
diff --git a/plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts b/plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts
index 1e1ea14..260247a 100644
--- a/plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts
+++ b/plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -17,5 +17,6 @@
 	system-id {
 		platform-id = <0x0>;
 		config-id = <0x0>;
+		multi-chip-mode = <0x0>;
 	};
 };
diff --git a/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts b/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts
deleted file mode 100644
index b14d7ad..0000000
--- a/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/dts-v1/;
-
-/ {
-	/* Platform Config */
-	compatible = "arm,tb_fw";
-	nt_fw_config_addr = <0x0 0xFEF00000>;
-	nt_fw_config_max_size = <0x0100000>;
-	/*
-	 * The following two entries are placeholders for Mbed TLS
-	 * heap information. The default values don't matter since
-	 * they will be overwritten by BL1.
-	 * In case of having shared Mbed TLS heap between BL1 and BL2,
-	 * BL1 will populate these two properties with the respective
-	 * info about the shared heap. This info will be available for
-	 * BL2 in order to locate and re-use the heap.
-	 */
-	mbedtls_heap_addr = <0x0 0x0>;
-	mbedtls_heap_size = <0x0>;
-};
diff --git a/plat/arm/board/sgi575/include/platform_def.h b/plat/arm/board/sgi575/include/platform_def.h
index fd59e52..95986cf 100644
--- a/plat/arm/board/sgi575/include/platform_def.h
+++ b/plat/arm/board/sgi575/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,7 +16,6 @@
 #define CSS_SGI_MAX_PE_PER_CPU		U(1)
 
 #define PLAT_CSS_MHU_BASE		UL(0x45000000)
-#define PLAT_MHUV2_BASE			PLAT_CSS_MHU_BASE
 
 /* Base address of DMC-620 instances */
 #define SGI575_DMC620_BASE0		UL(0x4e000000)
@@ -38,4 +37,9 @@
 #define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
 #endif
 
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE		UL(0x30000000)
+#define PLAT_ARM_GICC_BASE		UL(0x2C000000)
+#define PLAT_ARM_GICR_BASE		UL(0x300C0000)
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/sgi575/platform.mk b/plat/arm/board/sgi575/platform.mk
index ce2717f..d91f829 100644
--- a/plat/arm/board/sgi575/platform.mk
+++ b/plat/arm/board/sgi575/platform.mk
@@ -29,9 +29,14 @@
 				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES		+=	${SGI575_BASE}/sgi575_trusted_boot.c
+BL2_SOURCES		+=	${SGI575_BASE}/sgi575_trusted_boot.c
+endif
+
 # Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES		+=	${SGI575_BASE}/fdts/${PLAT}_tb_fw_config.dts
-TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+FDT_SOURCES		+=	${SGI575_BASE}/fdts/${PLAT}_fw_config.dts
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
 
 # Add the TB_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
@@ -41,3 +46,8 @@
 
 # Add the NT_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config))
+
+ifneq ($(CSS_SGI_CHIP_COUNT),1)
+ $(error  "Chip count for SGI575 should be 1, currently set to \
+   ${CSS_SGI_CHIP_COUNT}.")
+endif
diff --git a/plat/arm/board/sgi575/sgi575_plat.c b/plat/arm/board/sgi575/sgi575_plat.c
index 0d3fd16..dc294e6 100644
--- a/plat/arm/board/sgi575/sgi575_plat.c
+++ b/plat/arm/board/sgi575/sgi575_plat.c
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <plat/common/platform.h>
-
+#include <sgi_plat.h>
 #include <sgi_variant.h>
 
 unsigned int plat_arm_sgi_get_platform_id(void)
@@ -18,3 +18,13 @@
 	return (mmio_read_32(SSC_VERSION) >> SSC_VERSION_CONFIG_SHIFT)
 			& SSC_VERSION_CONFIG_MASK;
 }
+
+unsigned int plat_arm_sgi_get_multi_chip_mode(void)
+{
+	return 0;
+}
+
+void bl31_platform_setup(void)
+{
+	sgi_bl31_common_platform_setup();
+}
diff --git a/plat/arm/board/sgi575/sgi575_trusted_boot.c b/plat/arm/board/sgi575/sgi575_trusted_boot.c
new file mode 100644
index 0000000..c271f7f
--- /dev/null
+++ b/plat/arm/board/sgi575/sgi575_trusted_boot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, Arm Limited. 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
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+	return arm_get_rotpk_info(key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts b/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts
new file mode 100644
index 0000000..a0d0ea9
--- /dev/null
+++ b/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "arm,dyn_cfg-dtb_registry";
+
+		/* tb_fw_config is temporarily contained on this dtb */
+		tb_fw-config {
+			load-address = <0x0 0x4001010>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+
+		hw-config {
+			load-address = <0x0 0x83000000>;
+			max-size = <0x01000000>;
+			id = <HW_CONFIG_ID>;
+		};
+	};
+
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+	};
+};
diff --git a/plat/arm/board/sgm775/fdts/sgm775_tb_fw_config.dts b/plat/arm/board/sgm775/fdts/sgm775_tb_fw_config.dts
deleted file mode 100644
index 9502549..0000000
--- a/plat/arm/board/sgm775/fdts/sgm775_tb_fw_config.dts
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/dts-v1/;
-
-/ {
-	/* Platform Config */
-	plat_arm_bl2 {
-		compatible = "arm,tb_fw";
-		hw_config_addr = <0x0 0x83000000>;
-		hw_config_max_size = <0x01000000>;
-	};
-};
diff --git a/plat/arm/board/sgm775/platform.mk b/plat/arm/board/sgm775/platform.mk
index 7a843c3..355b9ee 100644
--- a/plat/arm/board/sgm775/platform.mk
+++ b/plat/arm/board/sgm775/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,7 +8,7 @@
 
 SGM775_BASE= plat/arm/board/sgm775
 
-FDT_SOURCES += ${SGM775_BASE}/fdts/sgm775_tb_fw_config.dts
+FDT_SOURCES += ${SGM775_BASE}/fdts/sgm775_fw_config.dts
 
 PLAT_INCLUDES +=-I${SGM775_BASE}/include/
 
@@ -21,3 +21,8 @@
 BL31_SOURCES		+=	drivers/cfi/v2m/v2m_flash.c		\
 				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
+
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES		+=	${SGM775_BASE}/sgm775_trusted_boot.c
+BL2_SOURCES		+=	${SGM775_BASE}/sgm775_trusted_boot.c
+endif
diff --git a/plat/arm/board/sgm775/sgm775_trusted_boot.c b/plat/arm/board/sgm775/sgm775_trusted_boot.c
new file mode 100644
index 0000000..c271f7f
--- /dev/null
+++ b/plat/arm/board/sgm775/sgm775_trusted_boot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, Arm Limited. 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
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+	return arm_get_rotpk_info(key_ptr, key_len, flags);
+}
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index b19a7c3..c2f49c2 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,6 +11,7 @@
 #include <arch.h>
 #include <bl1/bl1.h>
 #include <common/bl_common.h>
+#include <lib/fconf/fconf.h>
 #include <lib/utils.h>
 #include <lib/xlat_tables/xlat_tables_compat.h>
 #include <plat/arm/common/plat_arm.h>
@@ -143,7 +144,10 @@
 {
 	/* Initialise the IO layer and register platform IO devices */
 	plat_arm_io_setup();
-	arm_load_tb_fw_config();
+
+	/* Load fw config */
+	fconf_load_config();
+
 #if TRUSTED_BOARD_BOOT
 	/* Share the Mbed TLS heap info with other images */
 	arm_bl1_set_mbedtls_heap();
@@ -184,9 +188,9 @@
  * On Arm platforms, the FWU process is triggered when the FIP image has
  * been tampered with.
  */
-int plat_arm_bl1_fwu_needed(void)
+bool plat_arm_bl1_fwu_needed(void)
 {
-	return (arm_io_is_toc_valid() != 1);
+	return !arm_io_is_toc_valid();
 }
 
 /*******************************************************************************
@@ -195,8 +199,5 @@
  ******************************************************************************/
 unsigned int bl1_plat_get_next_image_id(void)
 {
-	if (plat_arm_bl1_fwu_needed() != 0)
-		return NS_BL1U_IMAGE_ID;
-
-	return BL2_IMAGE_ID;
+	return plat_arm_bl1_fwu_needed() ? NS_BL1U_IMAGE_ID : BL2_IMAGE_ID;
 }
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index cdf87ca..dd39208 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,6 +14,7 @@
 #include <common/debug.h>
 #include <common/desc_image_load.h>
 #include <drivers/generic_delay_timer.h>
+#include <lib/fconf/fconf.h>
 #ifdef SPD_opteed
 #include <lib/optee_utils.h>
 #endif
@@ -58,11 +59,13 @@
 	/* Setup the BL2 memory layout */
 	bl2_tzram_layout = *mem_layout;
 
+	/* Fill the properties struct with the info from the config dtb */
+	if (tb_fw_config != 0U) {
+		fconf_populate(tb_fw_config);
+	}
+
 	/* Initialise the IO layer and register platform IO devices */
 	plat_arm_io_setup();
-
-	if (tb_fw_config != 0U)
-		arm_bl2_set_tb_cfg_addr((void *)tb_fw_config);
 }
 
 void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3)
@@ -150,7 +153,7 @@
 	bl_mem_params_node_t *pager_mem_params = NULL;
 	bl_mem_params_node_t *paged_mem_params = NULL;
 #endif
-	assert(bl_mem_params);
+	assert(bl_mem_params != NULL);
 
 	switch (image_id) {
 #ifdef __aarch64__
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index c135d7f..85535c1 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -256,9 +256,14 @@
 
 	/* Initialize the runtime console */
 	arm_console_runtime_init();
+
 #if RECLAIM_INIT_CODE
 	arm_free_init_memory();
 #endif
+
+#if PLAT_RO_XLAT_TABLES
+	arm_xlat_make_tables_readonly();
+#endif
 }
 
 #if RECLAIM_INIT_CODE
diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c
index d1e9620..d1eee08 100644
--- a/plat/arm/common/arm_common.c
+++ b/plat/arm/common/arm_common.c
@@ -25,6 +25,26 @@
  * conflicts with the definition in plat/common. */
 #pragma weak plat_get_syscnt_freq2
 
+/*******************************************************************************
+ * Changes the memory attributes for the region of mapped memory where the BL
+ * image's translation tables are located such that the tables will have
+ * read-only permissions.
+ ******************************************************************************/
+#if PLAT_RO_XLAT_TABLES
+void arm_xlat_make_tables_readonly(void)
+{
+	int rc = xlat_make_tables_readonly();
+
+	if (rc != 0) {
+		ERROR("Failed to make translation tables read-only at EL%u.\n",
+		      get_current_el());
+		panic();
+	}
+
+	INFO("Translation tables are now read-only at EL%u.\n",
+	     get_current_el());
+}
+#endif
 
 void arm_setup_romlib(void)
 {
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 9f4bc21..17058d1 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -177,12 +177,20 @@
 PLAT_BL_COMMON_SOURCES	+=	${XLAT_TABLES_LIB_SRCS}
 endif
 
+ifeq (${USE_FCONF_BASED_IO}, 0)
+ARM_IO_SOURCES		+=	plat/arm/common/arm_io_storage.c
+else
+ARM_IO_SOURCES		+=	plat/arm/common/arm_fconf_io_storage.c		\
+				plat/arm/common/fconf/arm_fconf_io.c
+endif
+
 BL1_SOURCES		+=	drivers/io/io_fip.c				\
 				drivers/io/io_memmap.c				\
 				drivers/io/io_storage.c				\
 				plat/arm/common/arm_bl1_setup.c			\
 				plat/arm/common/arm_err.c			\
-				plat/arm/common/arm_io_storage.c
+				${ARM_IO_SOURCES}
+
 ifdef EL3_PAYLOAD_BASE
 # Need the plat_arm_program_trusted_mailbox() function to release secondary CPUs from
 # their holding pen
@@ -196,7 +204,10 @@
 				drivers/io/io_storage.c				\
 				plat/arm/common/arm_bl2_setup.c			\
 				plat/arm/common/arm_err.c			\
-				plat/arm/common/arm_io_storage.c
+				${ARM_IO_SOURCES}
+
+# Firmware Configuration Framework sources
+include lib/fconf/fconf.mk
 
 # Add `libfdt` and Arm common helpers required for Dynamic Config
 include lib/libfdt/libfdt.mk
@@ -265,12 +276,20 @@
 				lib/extensions/pauth/pauth_helpers.S
 endif
 
+ifeq (${SPD},spmd)
+BL31_SOURCES		+=	plat/common/plat_spmd_manifest.c	\
+				common/fdt_wrappers.c			\
+				${LIBFDT_SRCS}
+
+endif
+
 ifneq (${TRUSTED_BOARD_BOOT},0)
 
     # Include common TBB sources
     AUTH_SOURCES	:=	drivers/auth/auth_mod.c				\
 				drivers/auth/crypto_mod.c			\
 				drivers/auth/img_parser_mod.c			\
+				lib/fconf/fconf_tbbr_getter.c
 
     # Include the selected chain of trust sources.
     ifeq (${COT},tbbr)
diff --git a/plat/arm/common/arm_console.c b/plat/arm/common/arm_console.c
index 123811d..0cac5d9 100644
--- a/plat/arm/common/arm_console.c
+++ b/plat/arm/common/arm_console.c
@@ -16,8 +16,8 @@
 /*******************************************************************************
  * Functions that set up the console
  ******************************************************************************/
-static console_pl011_t arm_boot_console;
-static console_pl011_t arm_runtime_console;
+static console_t arm_boot_console;
+static console_t arm_runtime_console;
 
 /* Initialize the console to provide early debug support */
 void __init arm_console_boot_init(void)
@@ -35,13 +35,13 @@
 		panic();
 	}
 
-	console_set_scope(&arm_boot_console.console, CONSOLE_FLAG_BOOT);
+	console_set_scope(&arm_boot_console, CONSOLE_FLAG_BOOT);
 }
 
 void arm_console_boot_end(void)
 {
 	(void)console_flush();
-	(void)console_unregister(&arm_boot_console.console);
+	(void)console_unregister(&arm_boot_console);
 }
 
 /* Initialize the runtime console */
@@ -54,7 +54,7 @@
 	if (rc == 0)
 		panic();
 
-	console_set_scope(&arm_runtime_console.console, CONSOLE_FLAG_RUNTIME);
+	console_set_scope(&arm_runtime_console, CONSOLE_FLAG_RUNTIME);
 }
 
 void arm_console_runtime_end(void)
diff --git a/plat/arm/common/arm_dyn_cfg.c b/plat/arm/common/arm_dyn_cfg.c
index e6c5a73..443d40f 100644
--- a/plat/arm/common/arm_dyn_cfg.c
+++ b/plat/arm/common/arm_dyn_cfg.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,13 +16,13 @@
 #if TRUSTED_BOARD_BOOT
 #include <drivers/auth/mbedtls/mbedtls_config.h>
 #endif
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <lib/fconf/fconf_tbbr_getter.h>
 #include <plat/arm/common/arm_dyn_cfg_helpers.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 
-/* Variable to store the address to TB_FW_CONFIG passed from BL1 */
-static void *tb_fw_cfg_dtb;
-
 #if TRUSTED_BOARD_BOOT
 
 static void *mbedtls_heap_addr;
@@ -57,20 +57,10 @@
 
 #elif defined(IMAGE_BL2)
 
-	int err;
-
 	/* If in BL2, retrieve the already allocated heap's info from DTB */
-	if (tb_fw_cfg_dtb != NULL) {
-		err = arm_get_dtb_mbedtls_heap_info(tb_fw_cfg_dtb, heap_addr,
-			heap_size);
-		if (err < 0) {
-			ERROR("BL2: unable to retrieve shared Mbed TLS heap information from DTB\n");
-			panic();
-		}
-	} else {
-		ERROR("BL2: DTB missing, cannot get Mbed TLS heap\n");
-		panic();
-	}
+	*heap_addr = FCONF_GET_PROPERTY(tbbr, dyn_config, mbedtls_heap_addr);
+	*heap_size = FCONF_GET_PROPERTY(tbbr, dyn_config, mbedtls_heap_size);
+
 #endif
 
 	return 0;
@@ -83,6 +73,7 @@
 void arm_bl1_set_mbedtls_heap(void)
 {
 	int err;
+	uintptr_t tb_fw_cfg_dtb;
 
 	/*
 	 * If tb_fw_cfg_dtb==NULL then DTB is not present for the current
@@ -96,8 +87,15 @@
 	 * information, we would need to call plat_get_mbedtls_heap to retrieve
 	 * the default heap's address and size.
 	 */
-	if ((tb_fw_cfg_dtb != NULL) && (mbedtls_heap_addr != NULL)) {
-		err = arm_set_dtb_mbedtls_heap_info(tb_fw_cfg_dtb,
+
+	/* fconf FW_CONFIG and TB_FW_CONFIG are currently the same DTB*/
+	tb_fw_cfg_dtb = FCONF_GET_PROPERTY(fconf, dtb, base_addr);
+
+	if ((tb_fw_cfg_dtb != 0UL) && (mbedtls_heap_addr != NULL)) {
+		/* As libfdt use void *, we can't avoid this cast */
+		void *dtb = (void *)tb_fw_cfg_dtb;
+
+		err = arm_set_dtb_mbedtls_heap_info(dtb,
 			mbedtls_heap_addr, mbedtls_heap_size);
 		if (err < 0) {
 			ERROR("BL1: unable to write shared Mbed TLS heap information to DTB\n");
@@ -108,111 +106,34 @@
 		 * images. It's critical because BL2 won't be able to proceed
 		 * without the heap info.
 		 */
-		flush_dcache_range((uintptr_t)tb_fw_cfg_dtb,
-			fdt_totalsize(tb_fw_cfg_dtb));
+		flush_dcache_range(tb_fw_cfg_dtb, fdt_totalsize(dtb));
 	}
 }
 
 #endif /* TRUSTED_BOARD_BOOT */
 
 /*
- * Helper function to load TB_FW_CONFIG and populate the load information to
- * arg0 of BL2 entrypoint info.
- */
-void arm_load_tb_fw_config(void)
-{
-	int err;
-	uintptr_t config_base = 0UL;
-	image_desc_t *desc;
-
-	image_desc_t arm_tb_fw_info = {
-		.image_id = TB_FW_CONFIG_ID,
-		SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
-				VERSION_2, image_info_t, 0),
-		.image_info.image_base = ARM_TB_FW_CONFIG_BASE,
-		.image_info.image_max_size =
-			ARM_TB_FW_CONFIG_LIMIT - ARM_TB_FW_CONFIG_BASE
-	};
-
-	VERBOSE("BL1: Loading TB_FW_CONFIG\n");
-	err = load_auth_image(TB_FW_CONFIG_ID, &arm_tb_fw_info.image_info);
-	if (err != 0) {
-		/* Return if TB_FW_CONFIG is not loaded */
-		VERBOSE("Failed to load TB_FW_CONFIG\n");
-		return;
-	}
-
-	/* At this point we know that a DTB is indeed available */
-	config_base = arm_tb_fw_info.image_info.image_base;
-	tb_fw_cfg_dtb = (void *)config_base;
-
-	/* The BL2 ep_info arg0 is modified to point to TB_FW_CONFIG */
-	desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
-	assert(desc != NULL);
-	desc->ep_info.args.arg0 = config_base;
-
-	INFO("BL1: TB_FW_CONFIG loaded at address = 0x%lx\n", config_base);
-
-#if TRUSTED_BOARD_BOOT && defined(DYN_DISABLE_AUTH)
-	int tb_fw_node;
-	uint32_t disable_auth = 0;
-
-	err = arm_dyn_tb_fw_cfg_init((void *)config_base, &tb_fw_node);
-	if (err < 0) {
-		ERROR("Invalid TB_FW_CONFIG loaded\n");
-		panic();
-	}
-
-	err = arm_dyn_get_disable_auth((void *)config_base, tb_fw_node, &disable_auth);
-	if (err < 0)
-		return;
-
-	if (disable_auth == 1)
-		dyn_disable_auth();
-#endif
-}
-
-/*
- * BL2 utility function to set the address of TB_FW_CONFIG passed from BL1.
- */
-void arm_bl2_set_tb_cfg_addr(void *dtb)
-{
-	assert(dtb != NULL);
-	tb_fw_cfg_dtb = dtb;
-}
-
-/*
  * BL2 utility function to initialize dynamic configuration specified by
  * TB_FW_CONFIG. Populate the bl_mem_params_node_t of other FW_CONFIGs if
  * specified in TB_FW_CONFIG.
  */
 void arm_bl2_dyn_cfg_init(void)
 {
-	int err = 0, tb_fw_node;
 	unsigned int i;
 	bl_mem_params_node_t *cfg_mem_params = NULL;
-	uint64_t image_base;
-	uint32_t image_size;
+	uintptr_t image_base;
+	size_t image_size;
 	const unsigned int config_ids[] = {
 			HW_CONFIG_ID,
 			SOC_FW_CONFIG_ID,
 			NT_FW_CONFIG_ID,
-#ifdef SPD_tspd
-			/* Currently tos_fw_config is only present for TSP */
+#if defined(SPD_tspd) || defined(SPD_spmd)
+			/* tos_fw_config is only present for TSPD/SPMD */
 			TOS_FW_CONFIG_ID
 #endif
 	};
 
-	if (tb_fw_cfg_dtb == NULL) {
-		VERBOSE("No TB_FW_CONFIG specified\n");
-		return;
-	}
-
-	err = arm_dyn_tb_fw_cfg_init(tb_fw_cfg_dtb, &tb_fw_node);
-	if (err < 0) {
-		ERROR("Invalid TB_FW_CONFIG passed from BL1\n");
-		panic();
-	}
+	const struct dyn_cfg_dtb_info_t *dtb_info;
 
 	/* Iterate through all the fw config IDs */
 	for (i = 0; i < ARRAY_SIZE(config_ids); i++) {
@@ -223,14 +144,16 @@
 			continue;
 		}
 
-		err = arm_dyn_get_config_load_info(tb_fw_cfg_dtb, tb_fw_node,
-				config_ids[i], &image_base, &image_size);
-		if (err < 0) {
+		dtb_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, config_ids[i]);
+		if (dtb_info == NULL) {
 			VERBOSE("Couldn't find config_id %d load info in TB_FW_CONFIG\n",
 					config_ids[i]);
 			continue;
 		}
 
+		image_base = dtb_info->config_addr;
+		image_size = dtb_info->config_max_size;
+
 		/*
 		 * Do some runtime checks on the load addresses of soc_fw_config,
 		 * tos_fw_config, nt_fw_config. This is not a comprehensive check
@@ -262,8 +185,8 @@
 		}
 
 
-		cfg_mem_params->image_info.image_base = (uintptr_t)image_base;
-		cfg_mem_params->image_info.image_max_size = image_size;
+		cfg_mem_params->image_info.image_base = image_base;
+		cfg_mem_params->image_info.image_max_size = (uint32_t)image_size;
 
 		/*
 		 * Remove the IMAGE_ATTRIB_SKIP_LOADING attribute from
@@ -271,16 +194,4 @@
 		 */
 		cfg_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING;
 	}
-
-#if TRUSTED_BOARD_BOOT && defined(DYN_DISABLE_AUTH)
-	uint32_t disable_auth = 0;
-
-	err = arm_dyn_get_disable_auth(tb_fw_cfg_dtb, tb_fw_node,
-					&disable_auth);
-	if (err < 0)
-		return;
-
-	if (disable_auth == 1)
-		dyn_disable_auth();
-#endif
 }
diff --git a/plat/arm/common/arm_dyn_cfg_helpers.c b/plat/arm/common/arm_dyn_cfg_helpers.c
index daf0f0a..909c4a6 100644
--- a/plat/arm/common/arm_dyn_cfg_helpers.c
+++ b/plat/arm/common/arm_dyn_cfg_helpers.c
@@ -15,128 +15,6 @@
 #define DTB_PROP_MBEDTLS_HEAP_ADDR "mbedtls_heap_addr"
 #define DTB_PROP_MBEDTLS_HEAP_SIZE "mbedtls_heap_size"
 
-typedef struct config_load_info_prop {
-	unsigned int config_id;
-	const char *config_addr;
-	const char *config_max_size;
-} config_load_info_prop_t;
-
-static const config_load_info_prop_t prop_names[] = {
-	{HW_CONFIG_ID, "hw_config_addr", "hw_config_max_size"},
-	{SOC_FW_CONFIG_ID, "soc_fw_config_addr", "soc_fw_config_max_size"},
-	{TOS_FW_CONFIG_ID, "tos_fw_config_addr", "tos_fw_config_max_size"},
-	{NT_FW_CONFIG_ID, "nt_fw_config_addr", "nt_fw_config_max_size"}
-};
-
-/*******************************************************************************
- * Helper to read the load information corresponding to the `config_id` in
- * TB_FW_CONFIG. This function expects the following properties to be defined :
- *	<config>_addr		size : 2 cells
- *	<config>_max_size	size : 1 cell
- *
- * Arguments:
- *	void *dtb		 - pointer to the TB_FW_CONFIG in memory
- *	int node		 - The node offset to appropriate node in the
- *					 DTB.
- *	unsigned int config_id	 - The configuration id
- *	uint64_t *config_addr	 - Returns the `config` load address if read
- *					 is successful.
- *	uint32_t *config_size	 - Returns the `config` size if read is
- *					 successful.
- *
- * Returns 0 on success and -1 on error.
- ******************************************************************************/
-int arm_dyn_get_config_load_info(void *dtb, int node, unsigned int config_id,
-		uint64_t *config_addr, uint32_t *config_size)
-{
-	int err;
-	unsigned int i;
-
-	assert(dtb != NULL);
-	assert(config_addr != NULL);
-	assert(config_size != NULL);
-
-	for (i = 0; i < ARRAY_SIZE(prop_names); i++) {
-		if (prop_names[i].config_id == config_id)
-			break;
-	}
-
-	if (i == ARRAY_SIZE(prop_names)) {
-		WARN("Invalid config id %d\n", config_id);
-		return -1;
-	}
-
-	/* Check if the pointer to DT is correct */
-	assert(fdt_check_header(dtb) == 0);
-
-	/* Assert the node offset point to "arm,tb_fw" compatible property */
-	assert(node == fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw"));
-
-	err = fdtw_read_cells(dtb, node, prop_names[i].config_addr, 2,
-				(void *) config_addr);
-	if (err < 0) {
-		WARN("Read cell failed for %s\n", prop_names[i].config_addr);
-		return -1;
-	}
-
-	err = fdtw_read_cells(dtb, node, prop_names[i].config_max_size, 1,
-				(void *) config_size);
-	if (err < 0) {
-		WARN("Read cell failed for %s\n", prop_names[i].config_max_size);
-		return -1;
-	}
-
-	VERBOSE("Dyn cfg: Read config_id %d load info from TB_FW_CONFIG 0x%llx 0x%x\n",
-				config_id, (unsigned long long)*config_addr, *config_size);
-
-	return 0;
-}
-
-/*******************************************************************************
- * Helper to read the `disable_auth` property in config DTB. This function
- * expects the following properties to be present in the config DTB.
- *	name : disable_auth		size : 1 cell
- *
- * Arguments:
- *	void *dtb		 - pointer to the TB_FW_CONFIG in memory
- *	int node		 - The node offset to appropriate node in the
- *				   DTB.
- *	uint64_t *disable_auth	 - The value of `disable_auth` property on
- *				   successful read. Must be 0 or 1.
- *
- * Returns 0 on success and -1 on error.
- ******************************************************************************/
-int arm_dyn_get_disable_auth(void *dtb, int node, uint32_t *disable_auth)
-{
-	int err;
-
-	assert(dtb != NULL);
-	assert(disable_auth != NULL);
-
-	/* Check if the pointer to DT is correct */
-	assert(fdt_check_header(dtb) == 0);
-
-	/* Assert the node offset point to "arm,tb_fw" compatible property */
-	assert(node == fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw"));
-
-	/* Locate the disable_auth cell and read the value */
-	err = fdtw_read_cells(dtb, node, "disable_auth", 1, disable_auth);
-	if (err < 0) {
-		WARN("Read cell failed for `disable_auth`\n");
-		return -1;
-	}
-
-	/* Check if the value is boolean */
-	if ((*disable_auth != 0U) && (*disable_auth != 1U)) {
-		WARN("Invalid value for `disable_auth` cell %d\n", *disable_auth);
-		return -1;
-	}
-
-	VERBOSE("Dyn cfg: `disable_auth` cell found with value = %d\n",
-					*disable_auth);
-	return 0;
-}
-
 /*******************************************************************************
  * Validate the tb_fw_config is a valid DTB file and returns the node offset
  * to "arm,tb_fw" property.
@@ -169,47 +47,6 @@
 }
 
 /*
- * Reads and returns the Mbed TLS shared heap information from the DTB.
- * This function is supposed to be called *only* when a DTB is present.
- * This function is supposed to be called only by BL2.
- *
- * Returns:
- *	0 = success
- *	-1 = error. In this case the values of heap_addr, heap_size should be
- *	    considered as garbage by the caller.
- */
-int arm_get_dtb_mbedtls_heap_info(void *dtb, void **heap_addr,
-	size_t *heap_size)
-{
-	int err, dtb_root;
-
-	/* Verify the DTB is valid and get the root node */
-	err = arm_dyn_tb_fw_cfg_init(dtb, &dtb_root);
-	if (err < 0) {
-		ERROR("Invalid TB_FW_CONFIG. Cannot retrieve Mbed TLS heap information from DTB\n");
-		return -1;
-	}
-
-	/* Retrieve the Mbed TLS heap details from the DTB */
-	err = fdtw_read_cells(dtb, dtb_root,
-		DTB_PROP_MBEDTLS_HEAP_ADDR, 2, heap_addr);
-	if (err < 0) {
-		ERROR("Error while reading %s from DTB\n",
-			DTB_PROP_MBEDTLS_HEAP_ADDR);
-		return -1;
-	}
-	err = fdtw_read_cells(dtb, dtb_root,
-		DTB_PROP_MBEDTLS_HEAP_SIZE, 1, heap_size);
-	if (err < 0) {
-		ERROR("Error while reading %s from DTB\n",
-			DTB_PROP_MBEDTLS_HEAP_SIZE);
-		return -1;
-	}
-	return 0;
-}
-
-
-/*
  * This function writes the Mbed TLS heap address and size in the DTB. When it
  * is called, it is guaranteed that a DTB is available. However it is not
  * guaranteed that the shared Mbed TLS heap implementation is used. Thus we
diff --git a/plat/arm/common/arm_fconf_io_storage.c b/plat/arm/common/arm_fconf_io_storage.c
new file mode 100644
index 0000000..341622a
--- /dev/null
+++ b/plat/arm/common/arm_fconf_io_storage.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited. 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_fip.h>
+#include <drivers/io/io_memmap.h>
+#include <drivers/io/io_storage.h>
+#include <lib/utils.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <plat/arm/common/arm_fconf_getter.h>
+#include <plat/arm/common/arm_fconf_io_storage.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+/* IO devices */
+static const io_dev_connector_t *fip_dev_con;
+uintptr_t fip_dev_handle;
+static const io_dev_connector_t *memmap_dev_con;
+uintptr_t memmap_dev_handle;
+
+/* Weak definitions may be overridden in specific ARM standard platform */
+#pragma weak plat_arm_io_setup
+#pragma weak plat_arm_get_alt_image_source
+
+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;
+}
+
+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;
+}
+
+int arm_io_setup(void)
+{
+	int io_result;
+
+	io_result = register_io_dev_fip(&fip_dev_con);
+	if (io_result < 0) {
+		return io_result;
+	}
+
+	io_result = register_io_dev_memmap(&memmap_dev_con);
+	if (io_result < 0) {
+		return io_result;
+	}
+
+	/* Open connections to devices and cache the handles */
+	io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
+				&fip_dev_handle);
+	if (io_result < 0) {
+		return io_result;
+	}
+
+	io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
+				&memmap_dev_handle);
+
+	return io_result;
+}
+
+void plat_arm_io_setup(void)
+{
+	int err;
+
+	err = arm_io_setup();
+	if (err < 0) {
+		panic();
+	}
+}
+
+int plat_arm_get_alt_image_source(
+	unsigned int image_id __unused,
+	uintptr_t *dev_handle __unused,
+	uintptr_t *image_spec __unused)
+{
+	/* By default do not try an alternative */
+	return -ENOENT;
+}
+
+/* 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 result;
+	const struct plat_io_policy *policy;
+
+	assert(image_id < MAX_NUMBER_IDS);
+
+	policy = FCONF_GET_PROPERTY(arm, io_policies, image_id);
+	result = policy->check(policy->image_spec);
+	if (result == 0) {
+		*image_spec = policy->image_spec;
+		*dev_handle = *(policy->dev_handle);
+	} else {
+		VERBOSE("Trying alternative IO\n");
+		result = plat_arm_get_alt_image_source(image_id, dev_handle,
+						       image_spec);
+	}
+
+	return result;
+}
+
+/*
+ * See if a Firmware Image Package is available,
+ * by checking if TOC is valid or not.
+ */
+bool arm_io_is_toc_valid(void)
+{
+	return (io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID) == 0);
+}
diff --git a/plat/arm/common/arm_io_storage.c b/plat/arm/common/arm_io_storage.c
index fc1eb49..f5d8a41 100644
--- a/plat/arm/common/arm_io_storage.c
+++ b/plat/arm/common/arm_io_storage.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -292,32 +292,41 @@
 }
 
 
-void arm_io_setup(void)
+int arm_io_setup(void)
 {
 	int io_result;
 
 	io_result = register_io_dev_fip(&fip_dev_con);
-	assert(io_result == 0);
+	if (io_result < 0) {
+		return io_result;
+	}
 
 	io_result = register_io_dev_memmap(&memmap_dev_con);
-	assert(io_result == 0);
+	if (io_result < 0) {
+		return io_result;
+	}
 
 	/* Open connections to devices and cache the handles */
 	io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
 				&fip_dev_handle);
-	assert(io_result == 0);
+	if (io_result < 0) {
+		return io_result;
+	}
 
 	io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
 				&memmap_dev_handle);
-	assert(io_result == 0);
 
-	/* Ignore improbable errors in release builds */
-	(void)io_result;
+	return io_result;
 }
 
 void plat_arm_io_setup(void)
 {
-	arm_io_setup();
+	int err;
+
+	err = arm_io_setup();
+	if (err < 0) {
+		panic();
+	}
 }
 
 int plat_arm_get_alt_image_source(
@@ -357,12 +366,8 @@
  * See if a Firmware Image Package is available,
  * by checking if TOC is valid or not.
  */
-int arm_io_is_toc_valid(void)
+bool arm_io_is_toc_valid(void)
 {
-	int result;
-
-	result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
-
-	return (result == 0);
+	return (io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID) == 0);
 }
 
diff --git a/plat/arm/common/fconf/arm_fconf_io.c b/plat/arm/common/fconf/arm_fconf_io.c
new file mode 100644
index 0000000..3c0586f
--- /dev/null
+++ b/plat/arm/common/fconf/arm_fconf_io.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. 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 <lib/object_pool.h>
+#include <libfdt.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <plat/arm/common/arm_fconf_getter.h>
+#include <plat/arm/common/arm_fconf_io_storage.h>
+#include <platform_def.h>
+
+const io_block_spec_t fip_block_spec = {
+	.offset = PLAT_ARM_FIP_BASE,
+	.length = PLAT_ARM_FIP_MAX_SIZE
+};
+
+const io_uuid_spec_t arm_uuid_spec[MAX_NUMBER_IDS] = {
+	[BL2_IMAGE_ID] = {UUID_TRUSTED_BOOT_FIRMWARE_BL2},
+	[TB_FW_CONFIG_ID] = {UUID_TB_FW_CONFIG},
+#if TRUSTED_BOARD_BOOT
+	[TRUSTED_BOOT_FW_CERT_ID] = {UUID_TRUSTED_BOOT_FW_CERT},
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+/* By default, ARM platforms load images from the FIP */
+struct plat_io_policy policies[MAX_NUMBER_IDS] = {
+	[FIP_IMAGE_ID] = {
+		&memmap_dev_handle,
+		(uintptr_t)&fip_block_spec,
+		open_memmap
+	},
+	[BL2_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&arm_uuid_spec[BL2_IMAGE_ID],
+		open_fip
+	},
+	[TB_FW_CONFIG_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&arm_uuid_spec[TB_FW_CONFIG_ID],
+		open_fip
+	},
+#if TRUSTED_BOARD_BOOT
+	[TRUSTED_BOOT_FW_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&arm_uuid_spec[TRUSTED_BOOT_FW_CERT_ID],
+		open_fip
+	},
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+#ifdef IMAGE_BL2
+
+#if TRUSTED_BOARD_BOOT
+#define FCONF_ARM_IO_UUID_NUMBER	19
+#else
+#define FCONF_ARM_IO_UUID_NUMBER	10
+#endif
+
+static io_uuid_spec_t fconf_arm_uuids[FCONF_ARM_IO_UUID_NUMBER];
+static OBJECT_POOL_ARRAY(fconf_arm_uuids_pool, fconf_arm_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_ARM_IO_UUID_NUMBER] = {
+	{SCP_BL2_IMAGE_ID, "scp_bl2_uuid"},
+	{BL31_IMAGE_ID, "bl31_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"},
+	{SOC_FW_CONFIG_ID, "soc_fw_cfg_uuid"},
+	{TOS_FW_CONFIG_ID, "tos_fw_cfg_uuid"},
+	{NT_FW_CONFIG_ID, "nt_fw_cfg_uuid"},
+#if TRUSTED_BOARD_BOOT
+	{TRUSTED_KEY_CERT_ID, "t_key_cert_uuid"},
+	{SCP_FW_KEY_CERT_ID, "scp_fw_key_uuid"},
+	{SOC_FW_KEY_CERT_ID, "soc_fw_key_uuid"},
+	{TRUSTED_OS_FW_KEY_CERT_ID, "tos_fw_key_cert_uuid"},
+	{NON_TRUSTED_FW_KEY_CERT_ID, "nt_fw_key_cert_uuid"},
+	{SCP_FW_CONTENT_CERT_ID, "scp_fw_content_cert_uuid"},
+	{SOC_FW_CONTENT_CERT_ID, "soc_fw_content_cert_uuid"},
+	{TRUSTED_OS_FW_CONTENT_CERT_ID, "tos_fw_content_cert_uuid"},
+	{NON_TRUSTED_FW_CONTENT_CERT_ID, "nt_fw_content_cert_uuid"},
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+int fconf_populate_arm_io_policies(uintptr_t config)
+{
+	int err, node;
+	unsigned int i;
+
+	union uuid_helper_t uuid_helper;
+	io_uuid_spec_t *uuid_ptr;
+
+	/* As libfdt uses void *, we can't avoid this cast */
+	const void *dtb = (void *)config;
+
+	/* Assert the node offset point to "arm,io-fip-handle" compatible property */
+	const char *compatible_str = "arm,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 = 0; i < FCONF_ARM_IO_UUID_NUMBER; i++) {
+		uuid_ptr = pool_alloc(&fconf_arm_uuids_pool);
+		err = fdtw_read_array(dtb, node, load_info[i].name, 4, &uuid_helper.word);
+		if (err < 0) {
+			WARN("FCONF: Read cell failed for %s\n", load_info[i].name);
+			return err;
+		}
+
+		VERBOSE("FCONF: arm-io_policies.%s cell found with value = 0x%x 0x%x 0x%x 0x%x\n",
+			load_info[i].name,
+			uuid_helper.word[0], uuid_helper.word[1],
+			uuid_helper.word[2], uuid_helper.word[3]);
+
+		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(arm_io, fconf_populate_arm_io_policies);
+
+#endif /* IMAGE_BL2 */
diff --git a/plat/arm/common/sp_min/arm_sp_min_setup.c b/plat/arm/common/sp_min/arm_sp_min_setup.c
index 0cc746b..cbbdfa2 100644
--- a/plat/arm/common/sp_min/arm_sp_min_setup.c
+++ b/plat/arm/common/sp_min/arm_sp_min_setup.c
@@ -167,6 +167,10 @@
 {
 	/* Initialize the runtime console */
 	arm_console_runtime_init();
+
+#if PLAT_RO_XLAT_TABLES
+	arm_xlat_make_tables_readonly();
+#endif
 }
 
 /*******************************************************************************
diff --git a/plat/arm/common/tsp/arm_tsp_setup.c b/plat/arm/common/tsp/arm_tsp_setup.c
index aefdf89..a4da8c3 100644
--- a/plat/arm/common/tsp/arm_tsp_setup.c
+++ b/plat/arm/common/tsp/arm_tsp_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -28,7 +28,7 @@
 /*******************************************************************************
  * Initialize the UART
  ******************************************************************************/
-static console_pl011_t arm_tsp_runtime_console;
+static console_t arm_tsp_runtime_console;
 
 void arm_tsp_early_platform_setup(void)
 {
@@ -43,7 +43,7 @@
 	if (rc == 0)
 		panic();
 
-	console_set_scope(&arm_tsp_runtime_console.console,
+	console_set_scope(&arm_tsp_runtime_console,
 			  CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
 }
 
@@ -79,4 +79,8 @@
 
 	setup_page_tables(bl_regions, plat_arm_get_mmap());
 	enable_mmu_el1(0);
+
+#if PLAT_RO_XLAT_TABLES
+	arm_xlat_make_tables_readonly();
+#endif
 }
diff --git a/plat/arm/css/sgi/aarch64/sgi_helper.S b/plat/arm/css/sgi/aarch64/sgi_helper.S
index b80903d..04bfb77 100644
--- a/plat/arm/css/sgi/aarch64/sgi_helper.S
+++ b/plat/arm/css/sgi/aarch64/sgi_helper.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,19 +18,22 @@
 	 * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
 	 *
 	 * Helper function to calculate the core position.
+	 * (ChipId * PLAT_ARM_CLUSTER_COUNT *
+	 *  CSS_SGI_MAX_CPUS_PER_CLUSTER * CSS_SGI_MAX_PE_PER_CPU) +
 	 * (ClusterId * CSS_SGI_MAX_CPUS_PER_CLUSTER * CSS_SGI_MAX_PE_PER_CPU) +
 	 * (CPUId * CSS_SGI_MAX_PE_PER_CPU) +
 	 * ThreadId
 	 *
 	 * which can be simplified as:
 	 *
-	 * ((ClusterId * CSS_SGI_MAX_CPUS_PER_CLUSTER + CPUId) *
-	 * CSS_SGI_MAX_PE_PER_CPU) + ThreadId
+	 * ((((ChipId * PLAT_ARM_CLUSTER_COUNT) + ClusterId) *
+	 *   CSS_SGI_MAX_CPUS_PER_CLUSTER) + CPUId) * CSS_SGI_MAX_PE_PER_CPU +
+	 * ThreadId
 	 * ------------------------------------------------------
 	 */
 
 func plat_arm_calc_core_pos
-	mov	x3, x0
+	mov	x4, x0
 
 	/*
 	 * The MT bit in MPIDR is always set for SGI platforms
@@ -38,15 +41,18 @@
 	 */
 
 	/* 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
+	ubfx    x0, x4, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx    x1, x4, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx    x2, x4, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx    x3, x4, #MPIDR_AFF3_SHIFT, #MPIDR_AFFINITY_BITS
 
 	/* Compute linear position */
+	mov     x4, #PLAT_ARM_CLUSTER_COUNT
+	madd    x2, x3, x4, x2
 	mov     x4, #CSS_SGI_MAX_CPUS_PER_CLUSTER
 	madd    x1, x2, x4, x1
-	mov     x5, #CSS_SGI_MAX_PE_PER_CPU
-	madd    x0, x1, x5, x0
+	mov     x4, #CSS_SGI_MAX_PE_PER_CPU
+	madd    x0, x1, x4, x0
 	ret
 endfunc plat_arm_calc_core_pos
 
diff --git a/plat/arm/css/sgi/include/sgi_base_platform_def.h b/plat/arm/css/sgi/include/sgi_base_platform_def.h
index e214573..4986378 100644
--- a/plat/arm/css/sgi/include/sgi_base_platform_def.h
+++ b/plat/arm/css/sgi/include/sgi_base_platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -17,12 +17,16 @@
 #include <plat/arm/soc/common/soc_css_def.h>
 #include <plat/common/common_def.h>
 
-#define PLATFORM_CORE_COUNT		(PLAT_ARM_CLUSTER_COUNT *	\
-					CSS_SGI_MAX_CPUS_PER_CLUSTER * \
+#define PLATFORM_CORE_COUNT		(CSS_SGI_CHIP_COUNT *		\
+					PLAT_ARM_CLUSTER_COUNT *	\
+					CSS_SGI_MAX_CPUS_PER_CLUSTER *	\
 					CSS_SGI_MAX_PE_PER_CPU)
 
 #define PLAT_ARM_TRUSTED_SRAM_SIZE	0x00040000	/* 256 KB */
 
+/* Remote chip address offset (4TB per chip) */
+#define CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n)	((ULL(1) << 42) * (n))
+
 /*
  * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
  * plat_arm_mmap array defined for each BL stage.
@@ -35,14 +39,14 @@
 #  define PLAT_SP_IMAGE_MAX_XLAT_TABLES	10
 # else
 #  define PLAT_ARM_MMAP_ENTRIES		8
-#  define MAX_XLAT_TABLES		5
+#  define MAX_XLAT_TABLES		8
 # endif
 #elif defined(IMAGE_BL32)
 # define PLAT_ARM_MMAP_ENTRIES		8
 # define MAX_XLAT_TABLES		5
 #elif !USE_ROMLIB
 # define PLAT_ARM_MMAP_ENTRIES		11
-# define MAX_XLAT_TABLES		5
+# define MAX_XLAT_TABLES		7
 #else
 # define PLAT_ARM_MMAP_ENTRIES		12
 # define MAX_XLAT_TABLES		6
@@ -129,10 +133,29 @@
 					CSS_SGI_DEVICE_SIZE,	\
 					MT_DEVICE | MT_RW | MT_SECURE)
 
-/* GIC related constants */
-#define PLAT_ARM_GICD_BASE		0x30000000
-#define PLAT_ARM_GICC_BASE		0x2C000000
-#define PLAT_ARM_GICR_BASE		0x300C0000
+#define ARM_MAP_SHARED_RAM_REMOTE_CHIP(n)					\
+			MAP_REGION_FLAT(					\
+				CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) +		\
+				ARM_SHARED_RAM_BASE,				\
+				ARM_SHARED_RAM_SIZE,				\
+				MT_MEMORY | MT_RW | MT_SECURE			\
+			)
+
+#define CSS_SGI_MAP_DEVICE_REMOTE_CHIP(n)					\
+			MAP_REGION_FLAT(					\
+				CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) +		\
+				CSS_SGI_DEVICE_BASE,				\
+				CSS_SGI_DEVICE_SIZE,				\
+				MT_DEVICE | MT_RW | MT_SECURE			\
+			)
+
+#define SOC_CSS_MAP_DEVICE_REMOTE_CHIP(n)					\
+			MAP_REGION_FLAT(					\
+				CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) +		\
+				SOC_CSS_DEVICE_BASE,				\
+				SOC_CSS_DEVICE_SIZE,				\
+				MT_DEVICE | MT_RW | MT_SECURE			\
+			)
 
 /* Map the secure region for access from S-EL0 */
 #define PLAT_ARM_SECURE_MAP_DEVICE	MAP_REGION_FLAT(	\
@@ -212,4 +235,7 @@
 #define SBSA_SECURE_WDOG_BASE		UL(0x2A480000)
 #define SBSA_SECURE_WDOG_TIMEOUT	UL(100)
 
+/* Number of SCMI channels on the platform */
+#define PLAT_ARM_SCMI_CHANNEL_COUNT	CSS_SGI_CHIP_COUNT
+
 #endif /* SGI_BASE_PLATFORM_DEF_H */
diff --git a/plat/arm/css/sgi/include/sgi_plat.h b/plat/arm/css/sgi/include/sgi_plat.h
new file mode 100644
index 0000000..a5fbded
--- /dev/null
+++ b/plat/arm/css/sgi/include/sgi_plat.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SGI_PLAT_H
+#define SGI_PLAT_H
+
+/* BL31 platform setup common to all SGI based platforms */
+void sgi_bl31_common_platform_setup(void);
+
+#endif /* SGI_PLAT_H */
diff --git a/plat/arm/css/sgi/include/sgi_variant.h b/plat/arm/css/sgi/include/sgi_variant.h
index c75f213..f4c5300 100644
--- a/plat/arm/css/sgi/include/sgi_variant.h
+++ b/plat/arm/css/sgi/include/sgi_variant.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,16 +8,21 @@
 #define SGI_VARIANT_H
 
 /* SSC_VERSION values for SGI575 */
-#define SGI575_SSC_VER_PART_NUM		0x0783
+#define SGI575_SSC_VER_PART_NUM			0x0783
 
 /* SID Version values for RD-N1E1-Edge */
 #define RD_N1E1_EDGE_SID_VER_PART_NUM		0x0786
 #define RD_E1_EDGE_CONFIG_ID			0x2
 
+/* SID Version values for RD-Daniel */
+#define RD_DANIEL_SID_VER_PART_NUM		0x078a
+
 /* Structure containing SGI platform variant information */
 typedef struct sgi_platform_info {
 	unsigned int platform_id;	/* Part Number of the platform */
 	unsigned int config_id;		/* Config Id of the platform */
+	unsigned int chip_id;		/* Chip Id or Node number */
+	unsigned int multi_chip_mode;	/* Multi-chip mode availability */
 } sgi_platform_info_t;
 
 extern sgi_platform_info_t sgi_plat_info;
@@ -28,4 +33,7 @@
 /* returns the configuration id of the platform */
 unsigned int plat_arm_sgi_get_config_id(void);
 
+/* returns true if operating in multi-chip configuration */
+unsigned int plat_arm_sgi_get_multi_chip_mode(void);
+
 #endif /* SGI_VARIANT_H */
diff --git a/plat/arm/css/sgi/sgi-common.mk b/plat/arm/css/sgi/sgi-common.mk
index 7160111..40a7fd8 100644
--- a/plat/arm/css/sgi/sgi-common.mk
+++ b/plat/arm/css/sgi/sgi-common.mk
@@ -16,6 +16,8 @@
 
 HANDLE_EA_EL3_FIRST		:=	0
 
+CSS_SGI_CHIP_COUNT		:=	1
+
 INTERCONNECT_SOURCES	:=	${CSS_ENT_BASE}/sgi_interconnect.c
 
 PLAT_INCLUDES		+=	-I${CSS_ENT_BASE}/include
@@ -52,6 +54,8 @@
 
 $(eval $(call add_define,SGI_PLAT))
 
+$(eval $(call add_define,CSS_SGI_CHIP_COUNT))
+
 override CSS_LOAD_SCP_IMAGES	:=	0
 override NEED_BL2U		:=	no
 override ARM_BL31_IN_DRAM	:=	1
diff --git a/plat/arm/css/sgi/sgi_bl31_setup.c b/plat/arm/css/sgi/sgi_bl31_setup.c
index ba050d5..fcb7e1f 100644
--- a/plat/arm/css/sgi/sgi_bl31_setup.c
+++ b/plat/arm/css/sgi/sgi_bl31_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -28,18 +28,57 @@
 		.ring_doorbell = &mhu_ring_doorbell,
 };
 
-static scmi_channel_plat_info_t rd_n1e1_edge_scmi_plat_info = {
+static scmi_channel_plat_info_t rd_n1e1_edge_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,
+	},
+	#if (CSS_SGI_CHIP_COUNT > 1)
+	{
+		.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE +
+			CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1),
+		.db_reg_addr = PLAT_CSS_MHU_BASE
+			+ CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1) + SENDER_REG_SET(0),
+		.db_preserve_mask = 0xfffffffe,
+		.db_modify_mask = 0x1,
+		.ring_doorbell = &mhuv2_ring_doorbell,
+	},
+	#endif
+	#if (CSS_SGI_CHIP_COUNT > 2)
+	{
+		.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE +
+			CSS_SGI_REMOTE_CHIP_MEM_OFFSET(2),
+		.db_reg_addr = PLAT_CSS_MHU_BASE +
+			CSS_SGI_REMOTE_CHIP_MEM_OFFSET(2) + SENDER_REG_SET(0),
+		.db_preserve_mask = 0xfffffffe,
+		.db_modify_mask = 0x1,
+		.ring_doorbell = &mhuv2_ring_doorbell,
+	},
+	#endif
+	#if (CSS_SGI_CHIP_COUNT > 3)
+	{
+		.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE +
+			CSS_SGI_REMOTE_CHIP_MEM_OFFSET(3),
+		.db_reg_addr = PLAT_CSS_MHU_BASE +
+			CSS_SGI_REMOTE_CHIP_MEM_OFFSET(3) + SENDER_REG_SET(0),
+		.db_preserve_mask = 0xfffffffe,
+		.db_modify_mask = 0x1,
+		.ring_doorbell = &mhuv2_ring_doorbell,
+	},
+	#endif
 };
 
-scmi_channel_plat_info_t *plat_css_get_scmi_info(void)
+scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id)
 {
-	if (sgi_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM)
-		return &rd_n1e1_edge_scmi_plat_info;
+	if (sgi_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM ||
+		sgi_plat_info.platform_id == RD_DANIEL_SID_VER_PART_NUM) {
+		if (channel_id >= sizeof(rd_n1e1_edge_scmi_plat_info))
+			panic();
+		return &rd_n1e1_edge_scmi_plat_info[channel_id];
+	}
 	else if (sgi_plat_info.platform_id == SGI575_SSC_VER_PART_NUM)
 		return &sgi575_scmi_plat_info;
 	else
@@ -51,11 +90,12 @@
 {
 	sgi_plat_info.platform_id = plat_arm_sgi_get_platform_id();
 	sgi_plat_info.config_id = plat_arm_sgi_get_config_id();
+	sgi_plat_info.multi_chip_mode = plat_arm_sgi_get_multi_chip_mode();
 
 	arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
 }
 
-void bl31_platform_setup(void)
+void sgi_bl31_common_platform_setup(void)
 {
 	arm_bl31_platform_setup();
 
@@ -66,9 +106,13 @@
 
 const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
 {
-	/* For RD-E1-Edge platform only CPU ON/OFF is supported */
-	if ((sgi_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM) &&
-	    (sgi_plat_info.config_id == RD_E1_EDGE_CONFIG_ID)) {
+	/*
+	 * For RD-E1-Edge and RD-Daniel platforms, only CPU power ON/OFF
+	 * PSCI platform callbacks are supported.
+	 */
+	if (((sgi_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM) &&
+	    (sgi_plat_info.config_id == RD_E1_EDGE_CONFIG_ID)) ||
+	    (sgi_plat_info.platform_id == RD_DANIEL_SID_VER_PART_NUM)) {
 		ops->cpu_standby = NULL;
 		ops->system_off = NULL;
 		ops->system_reset = NULL;
diff --git a/plat/arm/css/sgi/sgi_image_load.c b/plat/arm/css/sgi/sgi_image_load.c
index a2f10dc..09f3b72 100644
--- a/plat/arm/css/sgi/sgi_image_load.c
+++ b/plat/arm/css/sgi/sgi_image_load.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -62,6 +62,13 @@
 		return -1;
 	}
 
+	platcfg = plat_arm_sgi_get_multi_chip_mode();
+	err = fdt_setprop_u32(fdt, nodeoffset, "multi-chip-mode", platcfg);
+	if (err < 0) {
+		ERROR("Failed to set multi-chip-mode\n");
+		return -1;
+	}
+
 	flush_dcache_range((uintptr_t)fdt, mem_params->image_info.image_size);
 
 	return 0;
diff --git a/plat/arm/css/sgm/include/sgm_base_platform_def.h b/plat/arm/css/sgm/include/sgm_base_platform_def.h
index 24bbed5..90511ac 100644
--- a/plat/arm/css/sgm/include/sgm_base_platform_def.h
+++ b/plat/arm/css/sgm/include/sgm_base_platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -86,7 +86,6 @@
 
 /* MHU related constants */
 #define PLAT_CSS_MHU_BASE		0x2b1f0000
-#define PLAT_MHUV2_BASE			PLAT_CSS_MHU_BASE
 
 #define PLAT_ARM_TRUSTED_ROM_BASE	0x00000000
 #define PLAT_ARM_TRUSTED_ROM_SIZE	0x00080000
@@ -239,4 +238,7 @@
 /* System power domain level */
 #define CSS_SYSTEM_PWR_DMN_LVL		ARM_PWR_LVL2
 
+/* Number of SCMI channels on the platform */
+#define PLAT_ARM_SCMI_CHANNEL_COUNT	U(1)
+
 #endif /* SGM_BASE_PLATFORM_DEF_H */
diff --git a/plat/arm/css/sgm/sgm_bl31_setup.c b/plat/arm/css/sgm/sgm_bl31_setup.c
index 7e92ac8..907e9fd 100644
--- a/plat/arm/css/sgm/sgm_bl31_setup.c
+++ b/plat/arm/css/sgm/sgm_bl31_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -20,7 +20,7 @@
 		.ring_doorbell = &mhu_ring_doorbell,
 };
 
-scmi_channel_plat_info_t *plat_css_get_scmi_info()
+scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id)
 {
 	return &sgm775_scmi_plat_info;
 }
diff --git a/plat/common/plat_psci_common.c b/plat/common/plat_psci_common.c
index 80ed819..bed8890 100644
--- a/plat/common/plat_psci_common.c
+++ b/plat/common/plat_psci_common.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,6 +10,7 @@
 #include <arch.h>
 #include <lib/pmf/pmf.h>
 #include <lib/psci/psci.h>
+#include <lib/utils_def.h>
 #include <plat/common/platform.h>
 
 #if ENABLE_PSCI_STAT && ENABLE_PMF
@@ -16,9 +18,6 @@
 #pragma weak plat_psci_stat_accounting_stop
 #pragma weak plat_psci_stat_get_residency
 
-/* Ticks elapsed in one second by a signal of 1 MHz */
-#define MHZ_TICKS_PER_SEC 1000000U
-
 /* Maximum time-stamp value read from architectural counters */
 #ifdef __aarch64__
 #define MAX_TS	UINT64_MAX
diff --git a/plat/common/plat_spmd_manifest.c b/plat/common/plat_spmd_manifest.c
new file mode 100644
index 0000000..4c78979
--- /dev/null
+++ b/plat/common/plat_spmd_manifest.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <libfdt.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <errno.h>
+#include <platform_def.h>
+#include <services/spm_core_manifest.h>
+
+/*******************************************************************************
+ * Attribute section handler
+ ******************************************************************************/
+static int manifest_parse_attribute(spmc_manifest_sect_attribute_t *attr,
+				    const void *fdt,
+				    int node)
+{
+	int rc = 0;
+
+	assert(attr && fdt);
+
+	rc = fdtw_read_cells(fdt, node, "maj_ver", 1, &attr->major_version);
+	if (rc) {
+		ERROR("Missing SPCI major version in SPM core manifest.\n");
+		return -ENOENT;
+	}
+
+	rc = fdtw_read_cells(fdt, node, "min_ver", 1, &attr->minor_version);
+	if (rc) {
+		ERROR("Missing SPCI minor version in SPM core manifest.\n");
+		return -ENOENT;
+	}
+
+	rc = fdtw_read_cells(fdt, node, "runtime_el", 1, &attr->runtime_el);
+	if (rc) {
+		ERROR("Missing SPM core runtime EL in manifest.\n");
+		return -ENOENT;
+	}
+
+	rc = fdtw_read_cells(fdt, node, "exec_state", 1, &attr->exec_state);
+	if (rc)
+		NOTICE("Execution state not specified in SPM core manifest.\n");
+
+	rc = fdtw_read_cells(fdt, node, "binary_size", 1, &attr->binary_size);
+	if (rc)
+		NOTICE("Binary size not specified in SPM core manifest.\n");
+
+	rc = fdtw_read_cells(fdt, node, "load_address", 2, &attr->load_address);
+	if (rc)
+		NOTICE("Load address not specified in SPM core manifest.\n");
+
+	rc = fdtw_read_cells(fdt, node, "entrypoint", 2, &attr->entrypoint);
+	if (rc)
+		NOTICE("Entrypoint not specified in SPM core manifest.\n");
+
+	VERBOSE("SPM core manifest attribute section:\n");
+	VERBOSE("  version: %x.%x\n", attr->major_version, attr->minor_version);
+	VERBOSE("  runtime_el: 0x%x\n", attr->runtime_el);
+	VERBOSE("  binary_size: 0x%x\n", attr->binary_size);
+	VERBOSE("  load_address: 0x%llx\n", attr->load_address);
+	VERBOSE("  entrypoint: 0x%llx\n", attr->entrypoint);
+
+	return 0;
+}
+
+/*******************************************************************************
+ * Root node handler
+ ******************************************************************************/
+static int manifest_parse_root(spmc_manifest_sect_attribute_t *manifest,
+				const void *fdt,
+				int root)
+{
+	int node;
+	char *str;
+
+	str = "attribute";
+	node = fdt_subnode_offset_namelen(fdt, root, str, strlen(str));
+	if (node < 0) {
+		ERROR("Root node doesn't contain subnode '%s'\n", str);
+		return -ENOENT;
+	}
+
+	return manifest_parse_attribute(manifest, fdt, node);
+}
+
+/*******************************************************************************
+ * Platform handler to parse a SPM core manifest.
+ ******************************************************************************/
+int plat_spm_core_manifest_load(spmc_manifest_sect_attribute_t *manifest,
+				const void *ptr,
+				size_t size)
+{
+	int rc;
+	int root_node;
+
+	assert(manifest != NULL);
+	assert(ptr != NULL);
+
+	INFO("Reading SPM core manifest at address %p\n", ptr);
+
+	rc = fdt_check_header(ptr);
+	if (rc != 0) {
+		ERROR("Wrong format for SPM core manifest (%d).\n", rc);
+		return -EINVAL;
+	}
+
+	INFO("Reading SPM core manifest at address %p\n", ptr);
+
+	root_node = fdt_node_offset_by_compatible(ptr, -1,
+				"arm,spci-core-manifest-1.0");
+	if (root_node < 0) {
+		ERROR("Unrecognized SPM core manifest\n");
+		return -ENOENT;
+	}
+
+	INFO("Reading SPM core manifest at address %p\n", ptr);
+	return manifest_parse_root(manifest, ptr, root_node);
+}
diff --git a/plat/hisilicon/hikey/hikey_bl1_setup.c b/plat/hisilicon/hikey/hikey_bl1_setup.c
index a97d763..86e4fd6 100644
--- a/plat/hisilicon/hikey/hikey_bl1_setup.c
+++ b/plat/hisilicon/hikey/hikey_bl1_setup.c
@@ -26,7 +26,7 @@
 
 /* Data structure which holds the extents of the trusted RAM for BL1 */
 static meminfo_t bl1_tzram_layout;
-static console_pl011_t console;
+static console_t console;
 
 enum {
 	BOOT_NORMAL = 0,
diff --git a/plat/hisilicon/hikey/hikey_bl2_setup.c b/plat/hisilicon/hikey/hikey_bl2_setup.c
index 96136ec..feb7f8a 100644
--- a/plat/hisilicon/hikey/hikey_bl2_setup.c
+++ b/plat/hisilicon/hikey/hikey_bl2_setup.c
@@ -32,7 +32,7 @@
 #define BL2_RW_BASE		(BL_CODE_END)
 
 static meminfo_t bl2_el3_tzram_layout;
-static console_pl011_t console;
+static console_t console;
 
 enum {
 	BOOT_MODE_RECOVERY = 0,
diff --git a/plat/hisilicon/hikey/hikey_bl31_setup.c b/plat/hisilicon/hikey/hikey_bl31_setup.c
index 0326e9f..7d008e7 100644
--- a/plat/hisilicon/hikey/hikey_bl31_setup.c
+++ b/plat/hisilicon/hikey/hikey_bl31_setup.c
@@ -27,7 +27,7 @@
 
 static entry_point_info_t bl32_ep_info;
 static entry_point_info_t bl33_ep_info;
-static console_pl011_t console;
+static console_t console;
 
 /******************************************************************************
  * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
diff --git a/plat/hisilicon/hikey960/hikey960_bl1_setup.c b/plat/hisilicon/hikey960/hikey960_bl1_setup.c
index 4a7036c..0a2d062 100644
--- a/plat/hisilicon/hikey960/hikey960_bl1_setup.c
+++ b/plat/hisilicon/hikey960/hikey960_bl1_setup.c
@@ -41,7 +41,7 @@
 
 /* Data structure which holds the extents of the trusted RAM for BL1 */
 static meminfo_t bl1_tzram_layout;
-static console_pl011_t console;
+static console_t console;
 
 /******************************************************************************
  * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
diff --git a/plat/hisilicon/hikey960/hikey960_bl2_setup.c b/plat/hisilicon/hikey960/hikey960_bl2_setup.c
index 35d7692..c1c2a8c 100644
--- a/plat/hisilicon/hikey960/hikey960_bl2_setup.c
+++ b/plat/hisilicon/hikey960/hikey960_bl2_setup.c
@@ -32,7 +32,7 @@
 #define BL2_RW_BASE		(BL_CODE_END)
 
 static meminfo_t bl2_el3_tzram_layout;
-static console_pl011_t console;
+static console_t console;
 extern int load_lpm3(void);
 
 enum {
diff --git a/plat/hisilicon/hikey960/hikey960_bl31_setup.c b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
index 9383265..d3b4e4f 100644
--- a/plat/hisilicon/hikey960/hikey960_bl31_setup.c
+++ b/plat/hisilicon/hikey960/hikey960_bl31_setup.c
@@ -29,7 +29,7 @@
 
 static entry_point_info_t bl32_ep_info;
 static entry_point_info_t bl33_ep_info;
-static console_pl011_t console;
+static console_t console;
 
 /******************************************************************************
  * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0
diff --git a/plat/hisilicon/hikey960/hikey960_pm.c b/plat/hisilicon/hikey960/hikey960_pm.c
index ede893e..9f96fc3 100644
--- a/plat/hisilicon/hikey960/hikey960_pm.c
+++ b/plat/hisilicon/hikey960/hikey960_pm.c
@@ -33,7 +33,7 @@
 #define AXI_CONF_BASE		0x820
 
 static unsigned int uart_base;
-static console_pl011_t console;
+static console_t console;
 static uintptr_t hikey960_sec_entrypoint;
 
 static void hikey960_pwr_domain_standby(plat_local_state_t cpu_state)
diff --git a/plat/hisilicon/poplar/bl1_plat_setup.c b/plat/hisilicon/poplar/bl1_plat_setup.c
index 08ad67c..047ba62 100644
--- a/plat/hisilicon/poplar/bl1_plat_setup.c
+++ b/plat/hisilicon/poplar/bl1_plat_setup.c
@@ -28,7 +28,7 @@
 /* Data structure which holds the extents of the trusted RAM for BL1 */
 static meminfo_t bl1_tzram_layout;
 static meminfo_t bl2_tzram_layout;
-static console_pl011_t console;
+static console_t console;
 
 /*
  * Cannot use default weak implementation in bl1_main.c because BL1 RW data is
diff --git a/plat/hisilicon/poplar/bl2_plat_setup.c b/plat/hisilicon/poplar/bl2_plat_setup.c
index cc9d975..482935c 100644
--- a/plat/hisilicon/poplar/bl2_plat_setup.c
+++ b/plat/hisilicon/poplar/bl2_plat_setup.c
@@ -25,7 +25,7 @@
 #include "plat_private.h"
 
 static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
-static console_pl011_t console;
+static console_t console;
 
 /*******************************************************************************
  * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol.
diff --git a/plat/hisilicon/poplar/bl31_plat_setup.c b/plat/hisilicon/poplar/bl31_plat_setup.c
index 981ef37..a4e17ca 100644
--- a/plat/hisilicon/poplar/bl31_plat_setup.c
+++ b/plat/hisilicon/poplar/bl31_plat_setup.c
@@ -29,7 +29,7 @@
 
 static entry_point_info_t bl32_image_ep_info;
 static entry_point_info_t bl33_image_ep_info;
-static console_pl011_t console;
+static console_t console;
 
 static void hisi_tzpc_sec_init(void)
 {
diff --git a/plat/imx/common/include/imx8_lpuart.h b/plat/imx/common/include/imx8_lpuart.h
index 0ea284f..26470e0 100644
--- a/plat/imx/common/include/imx8_lpuart.h
+++ b/plat/imx/common/include/imx8_lpuart.h
@@ -54,13 +54,8 @@
 
 #include <stdint.h>
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_lpuart_t;
-
 int console_lpuart_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			   console_lpuart_t *console);
+			   console_t *console);
 #endif /*__ASSEMBLER__*/
 
 #endif /* IMX8_LPUART_H */
diff --git a/plat/imx/common/include/imx_uart.h b/plat/imx/common/include/imx_uart.h
index cc1b531..6c4d62f 100644
--- a/plat/imx/common/include/imx_uart.h
+++ b/plat/imx/common/include/imx_uart.h
@@ -11,13 +11,8 @@
 
 #ifndef __ASSEMBLER__
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_uart_t;
-
 int console_imx_uart_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			   console_uart_t *console);
+			      console_t *console);
 #endif /*__ASSEMBLER__*/
 
 #endif  /* IMX_UART_H */
diff --git a/plat/imx/imx7/common/imx7_bl2_el3_common.c b/plat/imx/imx7/common/imx7_bl2_el3_common.c
index a1e2aaf..7f156e3 100644
--- a/plat/imx/imx7/common/imx7_bl2_el3_common.c
+++ b/plat/imx/imx7/common/imx7_bl2_el3_common.c
@@ -150,7 +150,7 @@
 void bl2_el3_early_platform_setup(u_register_t arg1, u_register_t arg2,
 				  u_register_t arg3, u_register_t arg4)
 {
-	static console_imx_uart_t console;
+	static console_t console;
 	int console_scope = CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME;
 
 	/* Initialize common components */
@@ -170,7 +170,7 @@
 				  PLAT_IMX7_BOOT_UART_CLK_IN_HZ,
 				  PLAT_IMX7_CONSOLE_BAUDRATE,
 				  &console);
-	console_set_scope(&console.console, console_scope);
+	console_set_scope(&console, console_scope);
 
 	/* Open handles to persistent storage */
 	plat_imx7_io_setup();
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
index 4c5f4f0..40110d7 100644
--- a/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
+++ b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
@@ -97,7 +97,7 @@
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 		u_register_t arg2, u_register_t arg3)
 {
-	static console_uart_t console;
+	static console_t console;
 	int i;
 
 	/* Enable CSU NS access permission */
@@ -114,7 +114,7 @@
 	console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
 		IMX_CONSOLE_BAUDRATE, &console);
 	/* This console is only used for boot stage */
-	console_set_scope(&console.console, CONSOLE_FLAG_BOOT);
+	console_set_scope(&console, CONSOLE_FLAG_BOOT);
 
 	/*
 	 * tell BL3-1 where the non-secure software image is located
diff --git a/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c b/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
index a347389..05b5970 100644
--- a/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
+++ b/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
@@ -133,7 +133,7 @@
 	imx8m_caam_init();
 
 #if DEBUG_CONSOLE
-	static console_uart_t console;
+	static console_t console;
 
 	console_imx_uart_register(IMX_BOOT_UART_BASE, IMX_BOOT_UART_CLK_IN_HZ,
 		IMX_CONSOLE_BAUDRATE, &console);
diff --git a/plat/imx/imx8qm/imx8qm_bl31_setup.c b/plat/imx/imx8qm/imx8qm_bl31_setup.c
index 9232cbc..cffb140 100644
--- a/plat/imx/imx8qm/imx8qm_bl31_setup.c
+++ b/plat/imx/imx8qm/imx8qm_bl31_setup.c
@@ -295,7 +295,7 @@
 				u_register_t arg2, u_register_t arg3)
 {
 #if DEBUG_CONSOLE
-	static console_lpuart_t console;
+	static console_t console;
 #endif
 	if (sc_ipc_open(&ipc_handle, SC_IPC_BASE) != SC_ERR_NONE)
 		panic();
diff --git a/plat/imx/imx8qx/imx8qx_bl31_setup.c b/plat/imx/imx8qx/imx8qx_bl31_setup.c
index 58c82ce..97d2227 100644
--- a/plat/imx/imx8qx/imx8qx_bl31_setup.c
+++ b/plat/imx/imx8qx/imx8qx_bl31_setup.c
@@ -255,7 +255,7 @@
 				u_register_t arg2, u_register_t arg3)
 {
 #if DEBUG_CONSOLE
-	static console_lpuart_t console;
+	static console_t console;
 #endif
 	if (sc_ipc_open(&ipc_handle, SC_IPC_BASE) != SC_ERR_NONE)
 		panic();
diff --git a/plat/intel/soc/agilex/bl2_plat_setup.c b/plat/intel/soc/agilex/bl2_plat_setup.c
index 9587d48..468b356 100644
--- a/plat/intel/soc/agilex/bl2_plat_setup.c
+++ b/plat/intel/soc/agilex/bl2_plat_setup.c
@@ -46,12 +46,12 @@
 	{0},
 };
 
-boot_source_type boot_source;
+boot_source_type boot_source = BOOT_SOURCE;
 
 void bl2_el3_early_platform_setup(u_register_t x0, u_register_t x1,
 				u_register_t x2, u_register_t x4)
 {
-	static console_16550_t console;
+	static console_t console;
 	handoff reverse_handoff_ptr;
 
 	generic_delay_timer_init();
@@ -59,7 +59,6 @@
 	if (socfpga_get_handoff(&reverse_handoff_ptr))
 		return;
 	config_pinmux(&reverse_handoff_ptr);
-	boot_source = reverse_handoff_ptr.boot_source;
 	config_clkmgr_handoff(&reverse_handoff_ptr);
 
 	enable_nonsecure_access();
diff --git a/plat/intel/soc/agilex/bl31_plat_setup.c b/plat/intel/soc/agilex/bl31_plat_setup.c
index 13099b4..6f32aff 100644
--- a/plat/intel/soc/agilex/bl31_plat_setup.c
+++ b/plat/intel/soc/agilex/bl31_plat_setup.c
@@ -14,6 +14,7 @@
 #include <lib/mmio.h>
 #include <lib/xlat_tables/xlat_tables.h>
 
+#include "socfpga_mailbox.h"
 #include "socfpga_private.h"
 
 static entry_point_info_t bl32_image_ep_info;
@@ -36,7 +37,7 @@
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
-	static console_16550_t console;
+	static console_t console;
 
 	console_16550_register(PLAT_UART0_BASE, PLAT_UART_CLOCK, PLAT_BAUDRATE,
 		&console);
@@ -107,6 +108,8 @@
 	/* Signal secondary CPUs to jump to BL31 (BL2 = U-boot SPL) */
 	mmio_write_64(PLAT_CPU_RELEASE_ADDR,
 		(uint64_t)plat_secondary_cpus_bl31_entry);
+
+	mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL);
 }
 
 const mmap_region_t plat_agilex_mmap[] = {
diff --git a/plat/intel/soc/agilex/include/socfpga_plat_def.h b/plat/intel/soc/agilex/include/socfpga_plat_def.h
index b4e0921..6c9d81c 100644
--- a/plat/intel/soc/agilex/include/socfpga_plat_def.h
+++ b/plat/intel/soc/agilex/include/socfpga_plat_def.h
@@ -12,6 +12,7 @@
 
 /* Platform Setting */
 #define PLATFORM_MODEL				PLAT_SOCFPGA_AGILEX
+#define BOOT_SOURCE				BOOT_SOURCE_SDMMC
 
 /* Register Mapping */
 #define SOCFPGA_MMC_REG_BASE			0xff808000
diff --git a/plat/intel/soc/common/include/socfpga_handoff.h b/plat/intel/soc/common/include/socfpga_handoff.h
index 889d137..ba0f7f3 100644
--- a/plat/intel/soc/common/include/socfpga_handoff.h
+++ b/plat/intel/soc/common/include/socfpga_handoff.h
@@ -125,7 +125,6 @@
 	uint32_t	misc_magic;
 	uint32_t	misc_length;
 	uint32_t	_pad_0x618_0x620[2];
-	uint32_t	boot_source;
 } handoff;
 
 int verify_handoff_image(handoff *hoff_ptr, handoff *reverse_hoff_ptr);
diff --git a/plat/intel/soc/common/include/socfpga_mailbox.h b/plat/intel/soc/common/include/socfpga_mailbox.h
index c4b9e59..7d725b0 100644
--- a/plat/intel/soc/common/include/socfpga_mailbox.h
+++ b/plat/intel/soc/common/include/socfpga_mailbox.h
@@ -73,6 +73,29 @@
 /* Mailbox REBOOT commands */
 #define MBOX_CMD_REBOOT_HPS		71
 
+/* Mailbox RSU commands */
+#define MBOX_GET_SUBPARTITION_TABLE	90
+#define MBOX_RSU_STATUS			91
+#define MBOX_RSU_UPDATE			92
+
+/* Mailbox RSU macros */
+#define RSU_VERSION_ACMF		BIT(8)
+#define RSU_VERSION_ACMF_MASK		0xff00
+
+/* HPS stage notify command */
+#define MBOX_HPS_STAGE_NOTIFY		93
+
+/* Execution states for HPS_STAGE_NOTIFY */
+#define HPS_EXECUTION_STATE_FSBL	0
+#define HPS_EXECUTION_STATE_SSBL	1
+#define HPS_EXECUTION_STATE_OS		2
+
+/* Mailbox reconfiguration commands */
+#define MBOX_CONFIG_STATUS		4
+#define MBOX_RECONFIG			6
+#define MBOX_RECONFIG_DATA		8
+#define MBOX_RECONFIG_STATUS		9
+
 /* Generic error handling */
 #define MBOX_TIMEOUT			-2047
 #define MBOX_NO_RESPONSE		-2
@@ -98,28 +121,26 @@
 #define MBOX_CFGSTAT_STATE_ERROR_BOOT_INFO		0xf0000007
 #define MBOX_CFGSTAT_STATE_ERROR_QSPI_ERROR		0xf0000008
 
-/* Mailbox reconfiguration commands */
-#define MBOX_CONFIG_STATUS	4
-#define MBOX_RECONFIG		6
-#define MBOX_RECONFIG_DATA	8
-#define MBOX_RECONFIG_STATUS	9
-
-
 void mailbox_set_int(int interrupt_input);
 int mailbox_init(void);
 void mailbox_set_qspi_close(void);
 void mailbox_set_qspi_open(void);
 void mailbox_set_qspi_direct(void);
-int mailbox_send_cmd(int job_id, unsigned int cmd, uint32_t *args,
+int mailbox_send_cmd(int job_id, unsigned int cmd, uint64_t *args,
 			int len, int urgent, uint32_t *response, int resp_len);
-int mailbox_send_cmd_async(int job_id, unsigned int cmd, uint32_t *args,
+int mailbox_send_cmd_async(int job_id, unsigned int cmd, uint64_t *args,
 				int len, int urgent);
 int mailbox_read_response(int job_id, uint32_t *response, int resp_len);
 int mailbox_get_qspi_clock(void);
 void mailbox_reset_cold(void);
 void mailbox_clear_response(void);
 
-uint32_t intel_mailbox_get_config_status(uint32_t cmd);
+int intel_mailbox_get_config_status(uint32_t cmd);
 int intel_mailbox_is_fpga_not_ready(void);
 
+int mailbox_rsu_get_spt_offset(uint32_t *resp_buf, uint32_t resp_buf_len);
+int mailbox_rsu_status(uint32_t *resp_buf, uint32_t resp_buf_len);
+int mailbox_rsu_update(uint64_t *flash_offset);
+int mailbox_hps_stage_notify(uint64_t execution_stage);
+
 #endif /* SOCFPGA_MBOX_H */
diff --git a/plat/intel/soc/common/include/socfpga_sip_svc.h b/plat/intel/soc/common/include/socfpga_sip_svc.h
index 6bb41f3..2b1d983 100644
--- a/plat/intel/soc/common/include/socfpga_sip_svc.h
+++ b/plat/intel/soc/common/include/socfpga_sip_svc.h
@@ -28,6 +28,7 @@
 #define INTEL_SIP_LEGACY_SMC_ECC_DBE			0xC200000D
 #define INTEL_SIP_SMC_RSU_NOTIFY			0xC200000E
 #define INTEL_SIP_SMC_RSU_RETRY_COUNTER			0xC200000F
+#define INTEL_SIP_SMC_MBOX_SEND_CMD			0xC200001E
 
 /* FPGA config helpers */
 #define INTEL_SIP_SMC_FPGA_CONFIG_ADDR			0x400000
diff --git a/plat/intel/soc/common/soc/socfpga_mailbox.c b/plat/intel/soc/common/soc/socfpga_mailbox.c
index 8d7c1d6..8ce40a7 100644
--- a/plat/intel/soc/common/soc/socfpga_mailbox.c
+++ b/plat/intel/soc/common/soc/socfpga_mailbox.c
@@ -11,7 +11,7 @@
 #include "socfpga_mailbox.h"
 #include "socfpga_sip_svc.h"
 
-static int fill_mailbox_circular_buffer(uint32_t header_cmd, uint32_t *args,
+static int fill_mailbox_circular_buffer(uint32_t header_cmd, uint64_t *args,
 					int len)
 {
 	uint32_t cmd_free_offset;
@@ -167,7 +167,7 @@
 	}
 }
 
-int mailbox_send_cmd_async(int job_id, unsigned int cmd, uint32_t *args,
+int mailbox_send_cmd_async(int job_id, unsigned int cmd, uint64_t *args,
 			  int len, int urgent)
 {
 	if (urgent)
@@ -184,7 +184,7 @@
 	return 0;
 }
 
-int mailbox_send_cmd(int job_id, unsigned int cmd, uint32_t *args,
+int mailbox_send_cmd(int job_id, unsigned int cmd, uint64_t *args,
 			int len, int urgent, uint32_t *response, int resp_len)
 {
 	int status = 0;
@@ -252,7 +252,7 @@
 
 void mailbox_qspi_set_cs(int device_select)
 {
-	uint32_t cs_setting = device_select;
+	uint64_t cs_setting = device_select;
 
 	/* QSPI device select settings at 31:28 */
 	cs_setting = (cs_setting << 28);
@@ -267,6 +267,55 @@
 	mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_REBOOT_HPS, 0, 0, 0, NULL, 0);
 }
 
+int mailbox_rsu_get_spt_offset(uint32_t *resp_buf, uint32_t resp_buf_len)
+{
+	return mailbox_send_cmd(MBOX_JOB_ID, MBOX_GET_SUBPARTITION_TABLE,
+				NULL, 0, 0, (uint32_t *)resp_buf,
+				resp_buf_len);
+}
+
+struct rsu_status_info {
+	uint64_t current_image;
+	uint64_t fail_image;
+	uint32_t state;
+	uint32_t version;
+	uint32_t error_location;
+	uint32_t error_details;
+	uint32_t retry_counter;
+};
+
+int mailbox_rsu_status(uint32_t *resp_buf, uint32_t resp_buf_len)
+{
+	int ret;
+	struct rsu_status_info *info = (struct rsu_status_info *)resp_buf;
+
+	info->retry_counter = ~0;
+
+	ret = mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_STATUS, NULL, 0, 0,
+			       (uint32_t *)resp_buf, resp_buf_len);
+
+	if (ret < 0)
+		return ret;
+
+	if (info->retry_counter != ~0)
+		if (!(info->version & RSU_VERSION_ACMF_MASK))
+			info->version |= RSU_VERSION_ACMF;
+
+	return ret;
+}
+
+int mailbox_rsu_update(uint64_t *flash_offset)
+{
+	return mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_UPDATE,
+				flash_offset, 2, 0, NULL, 0);
+}
+
+int mailbox_hps_stage_notify(uint64_t execution_stage)
+{
+	return mailbox_send_cmd(MBOX_JOB_ID, MBOX_HPS_STAGE_NOTIFY,
+				&execution_stage, 1, 0, NULL, 0);
+}
+
 int mailbox_init(void)
 {
 	int status = 0;
@@ -287,10 +336,10 @@
 	return 0;
 }
 
-uint32_t intel_mailbox_get_config_status(uint32_t cmd)
+int intel_mailbox_get_config_status(uint32_t cmd)
 {
-	uint32_t status, res;
-	uint32_t response[6];
+	int status;
+	uint32_t res, response[6];
 
 	status = mailbox_send_cmd(1, cmd, NULL, 0, 0, response,
 		sizeof(response) / sizeof(response[0]));
diff --git a/plat/intel/soc/common/socfpga_psci.c b/plat/intel/soc/common/socfpga_psci.c
index d8a6c19..d48fb5d 100644
--- a/plat/intel/soc/common/socfpga_psci.c
+++ b/plat/intel/soc/common/socfpga_psci.c
@@ -130,9 +130,14 @@
 	panic();
 }
 
+extern uint64_t intel_rsu_update_address;
+
 static void __dead2 socfpga_system_reset(void)
 {
-	mailbox_reset_cold();
+	if (intel_rsu_update_address)
+		mailbox_rsu_update(&intel_rsu_update_address);
+	else
+		mailbox_reset_cold();
 
 	while (1)
 		wfi();
diff --git a/plat/intel/soc/common/socfpga_sip_svc.c b/plat/intel/soc/common/socfpga_sip_svc.c
index 41dae9e..1c3d45b 100644
--- a/plat/intel/soc/common/socfpga_sip_svc.c
+++ b/plat/intel/soc/common/socfpga_sip_svc.c
@@ -61,7 +61,7 @@
 
 static int intel_fpga_sdm_write_buffer(struct fpga_config_info *buffer)
 {
-	uint32_t args[3];
+	uint64_t args[3];
 
 	while (max_blocks > 0 && buffer->size > buffer->size_written) {
 		args[0] = (1<<8);
@@ -252,12 +252,16 @@
 	return true;
 }
 
-static bool is_address_in_ddr_range(uint64_t addr)
+static bool is_address_in_ddr_range(uint64_t addr, uint64_t size)
 {
-	if (addr >= DRAM_BASE && addr <= DRAM_BASE + DRAM_SIZE)
-		return true;
+	if (size > (UINT64_MAX - addr))
+		return false;
+	if (addr < BL31_LIMIT)
+		return false;
+	if (addr + size > DRAM_BASE + DRAM_SIZE)
+		return false;
 
-	return false;
+	return true;
 }
 
 static uint32_t intel_fpga_config_write(uint64_t mem, uint64_t size)
@@ -266,8 +270,7 @@
 
 	intel_fpga_sdm_write_all();
 
-	if (!is_address_in_ddr_range(mem) ||
-		!is_address_in_ddr_range(mem + size) ||
+	if (!is_address_in_ddr_range(mem, size) ||
 		is_fpga_config_buffer_full())
 		return INTEL_SIP_SMC_STATUS_REJECTED;
 
@@ -365,6 +368,66 @@
 	return INTEL_SIP_SMC_STATUS_ERROR;
 }
 
+/* Intel Remote System Update (RSU) services */
+uint64_t intel_rsu_update_address;
+
+static uint32_t intel_rsu_status(uint64_t *respbuf, uint32_t respbuf_sz)
+{
+	if (mailbox_rsu_status((uint32_t *)respbuf, respbuf_sz) < 0)
+		return INTEL_SIP_SMC_STATUS_ERROR;
+
+	return INTEL_SIP_SMC_STATUS_OK;
+}
+
+static uint32_t intel_rsu_update(uint64_t update_address)
+{
+	intel_rsu_update_address = update_address;
+	return INTEL_SIP_SMC_STATUS_OK;
+}
+
+static uint32_t intel_rsu_notify(uint64_t execution_stage)
+{
+	if (mailbox_hps_stage_notify(execution_stage) < 0)
+		return INTEL_SIP_SMC_STATUS_ERROR;
+
+	return INTEL_SIP_SMC_STATUS_OK;
+}
+
+static uint32_t intel_rsu_retry_counter(uint32_t *respbuf, uint32_t respbuf_sz,
+					uint32_t *ret_stat)
+{
+	if (mailbox_rsu_status((uint32_t *)respbuf, respbuf_sz) < 0)
+		return INTEL_SIP_SMC_STATUS_ERROR;
+
+	*ret_stat = respbuf[8];
+	return INTEL_SIP_SMC_STATUS_OK;
+}
+
+/* Mailbox services */
+static uint32_t intel_mbox_send_cmd(uint32_t cmd, uint64_t *args, int len,
+				    int urgent, uint32_t *response,
+				    int resp_len, int *mbox_status,
+				    int *len_in_resp)
+{
+	*len_in_resp = 0;
+	*mbox_status = 0;
+
+	if (!is_address_in_ddr_range((uint64_t)args, sizeof(uint32_t) * len))
+		return INTEL_SIP_SMC_STATUS_REJECTED;
+
+	int status = mailbox_send_cmd(MBOX_JOB_ID, cmd, args, len, urgent,
+				      response, resp_len);
+
+	if (status < 0) {
+		*mbox_status = -status;
+		return INTEL_SIP_SMC_STATUS_ERROR;
+	}
+
+	*mbox_status = 0;
+	*len_in_resp = status;
+	return INTEL_SIP_SMC_STATUS_OK;
+}
+
 /*
  * This function is responsible for handling all SiP calls from the NS world
  */
@@ -381,7 +444,10 @@
 	uint32_t val = 0;
 	uint32_t status = INTEL_SIP_SMC_STATUS_OK;
 	uint32_t completed_addr[3];
+	uint64_t rsu_respbuf[9];
 	uint32_t count = 0;
+	u_register_t x5, x6;
+	int mbox_status, len_in_resp;
 
 	switch (smc_fid) {
 	case SIP_SVC_UID:
@@ -446,6 +512,41 @@
 						 (uint32_t)x3, &val);
 		SMC_RET3(handle, status, val, x1);
 
+	case INTEL_SIP_SMC_RSU_STATUS:
+		status = intel_rsu_status(rsu_respbuf,
+					ARRAY_SIZE(rsu_respbuf));
+		if (status) {
+			SMC_RET1(handle, status);
+		} else {
+			SMC_RET4(handle, rsu_respbuf[0], rsu_respbuf[1],
+					rsu_respbuf[2], rsu_respbuf[3]);
+		}
+
+	case INTEL_SIP_SMC_RSU_UPDATE:
+		status = intel_rsu_update(x1);
+		SMC_RET1(handle, status);
+
+	case INTEL_SIP_SMC_RSU_NOTIFY:
+		status = intel_rsu_notify(x1);
+		SMC_RET1(handle, status);
+
+	case INTEL_SIP_SMC_RSU_RETRY_COUNTER:
+		status = intel_rsu_retry_counter((uint32_t *)rsu_respbuf,
+						ARRAY_SIZE(rsu_respbuf), &val);
+		if (status) {
+			SMC_RET1(handle, status);
+		} else {
+			SMC_RET2(handle, status, val);
+		}
+
+	case INTEL_SIP_SMC_MBOX_SEND_CMD:
+		x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
+		x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
+		status = intel_mbox_send_cmd(x1, (uint64_t *)x2, x3, x4,
+					     (uint32_t *)x5, x6, &mbox_status,
+					     &len_in_resp);
+		SMC_RET4(handle, status, mbox_status, x5, len_in_resp);
+
 	default:
 		return socfpga_sip_handler(smc_fid, x1, x2, x3, x4,
 			cookie, handle, flags);
diff --git a/plat/intel/soc/stratix10/bl2_plat_setup.c b/plat/intel/soc/stratix10/bl2_plat_setup.c
index 7d183db..d0c8e4c 100644
--- a/plat/intel/soc/stratix10/bl2_plat_setup.c
+++ b/plat/intel/soc/stratix10/bl2_plat_setup.c
@@ -45,12 +45,12 @@
 	{0},
 };
 
-boot_source_type boot_source;
+boot_source_type boot_source = BOOT_SOURCE;
 
 void bl2_el3_early_platform_setup(u_register_t x0, u_register_t x1,
 				u_register_t x2, u_register_t x4)
 {
-	static console_16550_t console;
+	static console_t console;
 	handoff reverse_handoff_ptr;
 
 	generic_delay_timer_init();
@@ -58,7 +58,6 @@
 	if (socfpga_get_handoff(&reverse_handoff_ptr))
 		return;
 	config_pinmux(&reverse_handoff_ptr);
-	boot_source = reverse_handoff_ptr.boot_source;
 
 	config_clkmgr_handoff(&reverse_handoff_ptr);
 	enable_nonsecure_access();
diff --git a/plat/intel/soc/stratix10/bl31_plat_setup.c b/plat/intel/soc/stratix10/bl31_plat_setup.c
index 29f57c4..5813c8f 100644
--- a/plat/intel/soc/stratix10/bl31_plat_setup.c
+++ b/plat/intel/soc/stratix10/bl31_plat_setup.c
@@ -16,6 +16,7 @@
 #include <plat/common/platform.h>
 #include <platform_def.h>
 
+#include "socfpga_mailbox.h"
 #include "socfpga_private.h"
 #include "socfpga_reset_manager.h"
 #include "socfpga_system_manager.h"
@@ -44,7 +45,7 @@
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
-	static console_16550_t console;
+	static console_t console;
 
 	console_16550_register(PLAT_UART0_BASE, PLAT_UART_CLOCK, PLAT_BAUDRATE,
 		&console);
@@ -115,6 +116,8 @@
 	/* Signal secondary CPUs to jump to BL31 (BL2 = U-boot SPL) */
 	mmio_write_64(PLAT_CPU_RELEASE_ADDR,
 		(uint64_t)plat_secondary_cpus_bl31_entry);
+
+	mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL);
 }
 
 const mmap_region_t plat_stratix10_mmap[] = {
diff --git a/plat/intel/soc/stratix10/include/socfpga_plat_def.h b/plat/intel/soc/stratix10/include/socfpga_plat_def.h
index 9dc5151..a2bd57b 100644
--- a/plat/intel/soc/stratix10/include/socfpga_plat_def.h
+++ b/plat/intel/soc/stratix10/include/socfpga_plat_def.h
@@ -10,7 +10,8 @@
 #include <platform_def.h>
 
 /* Platform Setting */
-#define PLATFORM_MODEL		PLAT_SOCFPGA_STRATIX10
+#define PLATFORM_MODEL				PLAT_SOCFPGA_STRATIX10
+#define BOOT_SOURCE				BOOT_SOURCE_SDMMC
 
 /* Register Mapping */
 #define SOCFPGA_MMC_REG_BASE                    0xff808000
diff --git a/plat/layerscape/common/aarch64/ls_console.S b/plat/layerscape/common/aarch64/ls_console.S
index f8948b4..c1bd3f7 100644
--- a/plat/layerscape/common/aarch64/ls_console.S
+++ b/plat/layerscape/common/aarch64/ls_console.S
@@ -81,7 +81,7 @@
 	.globl console_ls_16550_register
 
 	/* -----------------------------------------------
-	 * int console_ls_16550_register(console_ls_16550_t *console,
+	 * int console_ls_16550_register(console_t *console,
 	 *	uintptr_t base, uint32_t clk, uint32_t baud)
 	 * Function to initialize and register a new 16550
 	 * console. Storage passed in for the console struct
@@ -89,7 +89,7 @@
 	 * In: x0 - UART register base address
 	 *     w1 - UART clock in Hz
 	 *     w2 - Baud rate
-	 *     x3 - pointer to empty console_ls_16550_t struct
+	 *     x3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : x0, x1, x2, x6, x7, x14
 	 * -----------------------------------------------
@@ -98,7 +98,7 @@
 	mov	x7, x30
 	mov	x6, x3
 	cbz	x6, register_fail
-	str	x0, [x6, #CONSOLE_T_16550_BASE]
+	str	x0, [x6, #CONSOLE_T_BASE]
 
 	bl	console_ls_16550_core_init
 	cbz	x0, register_fail
@@ -150,7 +150,7 @@
 endfunc console_ls_16550_core_putc
 
 	/* --------------------------------------------------------
-	 * int console_16550_putc(int c, console_ls_16550_t *console)
+	 * int console_16550_putc(int c, console_t *console)
 	 * Function to output a character over the console. It
 	 * returns the character printed on success or -1 on error.
 	 * In : w0 - character to be printed
@@ -164,7 +164,7 @@
 	cmp	x1, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x1, [x1, #CONSOLE_T_16550_BASE]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 	b	console_ls_16550_core_putc
 endfunc console_ls_16550_putc
 
@@ -195,7 +195,7 @@
 endfunc console_ls_16550_core_getc
 
 	/* ---------------------------------------------
-	 * int console_ls_16550_getc(console_ls_16550_t *console)
+	 * int console_ls_16550_getc(console_t *console)
 	 * Function to get a character from the console.
 	 * It returns the character grabbed on success
 	 * or -1 on if no character is available.
@@ -209,7 +209,7 @@
 	cmp	x1, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x0, [x0, #CONSOLE_T_16550_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_ls_16550_core_getc
 endfunc console_ls_16550_getc
 
@@ -239,7 +239,7 @@
 endfunc console_ls_16550_core_flush
 
 	/* ---------------------------------------------
-	 * int console_ls_16550_flush(console_ls_16550_t *console)
+	 * int console_ls_16550_flush(console_t *console)
 	 * Function to force a write of all buffered
 	 * data that hasn't been output.
 	 * In : x0 - pointer to console_t structure
@@ -252,6 +252,6 @@
 	cmp	x0, #0
 	ASM_ASSERT(ne)
 #endif /* ENABLE_ASSERTIONS */
-	ldr	x0, [x0, #CONSOLE_T_16550_BASE]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 	b	console_ls_16550_core_flush
 endfunc console_ls_16550_flush
diff --git a/plat/layerscape/common/include/ls_16550.h b/plat/layerscape/common/include/ls_16550.h
index cb4514f..95a64ad 100644
--- a/plat/layerscape/common/include/ls_16550.h
+++ b/plat/layerscape/common/include/ls_16550.h
@@ -61,17 +61,10 @@
 #define UARTLSR_OVRF		(1 << 2)	/* Rx Overrun Error */
 #define UARTLSR_RDR		(1 << 2)	/* Rx Data Ready */
 
-#define CONSOLE_T_16550_BASE	CONSOLE_T_DRVDATA
-
 #ifndef __ASSEMBLER__
 
 #include <stdint.h>
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_ls_16550_t;
-
 /*
  * Initialize a new 16550 console instance and register it with the console
  * framework. The |console| pointer must point to storage that will be valid
@@ -79,7 +72,7 @@
  * Its contents will be reinitialized from scratch.
  */
 int console_ls_16550_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			   console_ls_16550_t *console);
+			      console_t *console);
 
 #endif /*__ASSEMBLER__*/
 
diff --git a/plat/layerscape/common/ls_bl1_setup.c b/plat/layerscape/common/ls_bl1_setup.c
index fff065e..fa69be2 100644
--- a/plat/layerscape/common/ls_bl1_setup.c
+++ b/plat/layerscape/common/ls_bl1_setup.c
@@ -23,7 +23,7 @@
  ******************************************************************************/
 void ls_bl1_early_platform_setup(void)
 {
-	static console_ls_16550_t console;
+	static console_t console;
 
 #if !LS1043_DISABLE_TRUSTED_WDOG
 	/* TODO: Enable watchdog */
diff --git a/plat/layerscape/common/ls_bl2_setup.c b/plat/layerscape/common/ls_bl2_setup.c
index 35f42e1..6ca66bd 100644
--- a/plat/layerscape/common/ls_bl2_setup.c
+++ b/plat/layerscape/common/ls_bl2_setup.c
@@ -23,7 +23,7 @@
  ******************************************************************************/
 void ls_bl2_early_platform_setup(meminfo_t *mem_layout)
 {
-	static console_ls_16550_t console;
+	static console_t console;
 
 	/* Initialize the console to provide early debug support */
 	console_ls_16550_register(LS_TF_UART_BASE, LS_TF_UART_CLOCK,
diff --git a/plat/layerscape/common/ls_bl31_setup.c b/plat/layerscape/common/ls_bl31_setup.c
index 03e5807..7a91aef 100644
--- a/plat/layerscape/common/ls_bl31_setup.c
+++ b/plat/layerscape/common/ls_bl31_setup.c
@@ -67,7 +67,7 @@
 void ls_bl31_early_platform_setup(void *from_bl2,
 				void *plat_params_from_bl2)
 {
-	static console_ls_16550_t console;
+	static console_t console;
 
 	/* Initialize the console to provide early debug support */
 	console_ls_16550_register(LS_TF_UART_BASE, LS_TF_UART_CLOCK,
@@ -182,7 +182,7 @@
  ******************************************************************************/
 void ls_bl31_plat_runtime_setup(void)
 {
-	static console_ls_16550_t console;
+	static console_t console;
 
 	/* Initialize the runtime console */
 	console_ls_16550_register(PLAT_LS1043_UART_BASE, PLAT_LS1043_UART_CLOCK,
diff --git a/plat/layerscape/common/tsp/ls_tsp_setup.c b/plat/layerscape/common/tsp/ls_tsp_setup.c
index f3b6027..969d0b8 100644
--- a/plat/layerscape/common/tsp/ls_tsp_setup.c
+++ b/plat/layerscape/common/tsp/ls_tsp_setup.c
@@ -30,7 +30,7 @@
  ******************************************************************************/
 void ls_tsp_early_platform_setup(void)
 {
-	static console_ls_16550_t console;
+	static console_t console;
 	/*
 	 * Initialize a different console than already in use to display
 	 * messages from TSP
diff --git a/plat/marvell/a8k/common/mss/mss_a8k.mk b/plat/marvell/a8k/common/mss/mss_a8k.mk
index 58f23d8..efd03c5 100644
--- a/plat/marvell/a8k/common/mss/mss_a8k.mk
+++ b/plat/marvell/a8k/common/mss/mss_a8k.mk
@@ -8,7 +8,8 @@
 PLAT_MARVELL		:=	plat/marvell
 A8K_MSS_SOURCE		:=	$(PLAT_MARVELL)/a8k/common/mss
 
-BL2_SOURCES		+=	$(A8K_MSS_SOURCE)/mss_bl2_setup.c
+BL2_SOURCES		+=	$(A8K_MSS_SOURCE)/mss_bl2_setup.c \
+				$(MARVELL_MOCHI_DRV)
 
 BL31_SOURCES		+=	$(A8K_MSS_SOURCE)/mss_pm_ipc.c
 
diff --git a/plat/marvell/a8k/common/mss/mss_bl2_setup.c b/plat/marvell/a8k/common/mss/mss_bl2_setup.c
index 728ee54..09b8446 100644
--- a/plat/marvell/a8k/common/mss/mss_bl2_setup.c
+++ b/plat/marvell/a8k/common/mss/mss_bl2_setup.c
@@ -74,6 +74,12 @@
 	/* Set the default target id to PIDI */
 	mmio_write_32(MVEBU_IO_WIN_BASE(MVEBU_AP0) + IOW_GCR_OFFSET, PIDI_TID);
 
+	/* Open AMB bridge required for MG access */
+	cp110_amb_init(MVEBU_CP_REGS_BASE(0));
+
+	if (CP_COUNT == 2)
+		cp110_amb_init(MVEBU_CP_REGS_BASE(1));
+
 	return 0;
 }
 
diff --git a/plat/marvell/common/marvell_console.c b/plat/marvell/common/marvell_console.c
index 22c5eb3..1716661 100644
--- a/plat/marvell/common/marvell_console.c
+++ b/plat/marvell/common/marvell_console.c
@@ -14,16 +14,15 @@
 
 #ifdef PLAT_a3700
 #include <drivers/marvell/uart/a3700_console.h>
-
-static console_a3700_t marvell_boot_console;
-static console_a3700_t marvell_runtime_console;
+#define console_marvell_register console_a3700_register
 #else
 #include <drivers/ti/uart/uart_16550.h>
-
-static console_16550_t marvell_boot_console;
-static console_16550_t marvell_runtime_console;
+#define console_marvell_register console_16550_register
 #endif
 
+static console_t marvell_boot_console;
+static console_t marvell_runtime_console;
+
 /*******************************************************************************
  * Functions that set up the console
  ******************************************************************************/
@@ -32,15 +31,10 @@
 void marvell_console_boot_init(void)
 {
 	int rc =
-#ifdef PLAT_a3700
-	console_a3700_register(
-#else
-	console_16550_register(
-#endif
-				PLAT_MARVELL_BOOT_UART_BASE,
-				PLAT_MARVELL_BOOT_UART_CLK_IN_HZ,
-				MARVELL_CONSOLE_BAUDRATE,
-				&marvell_boot_console);
+	console_marvell_register(PLAT_MARVELL_BOOT_UART_BASE,
+				 PLAT_MARVELL_BOOT_UART_CLK_IN_HZ,
+				 MARVELL_CONSOLE_BAUDRATE,
+				 &marvell_boot_console);
 	if (rc == 0) {
 		/*
 		 * The crash console doesn't use the multi console API, it uses
@@ -50,40 +44,33 @@
 		panic();
 	}
 
-	console_set_scope(&marvell_boot_console.console,
-			  CONSOLE_FLAG_BOOT);
+	console_set_scope(&marvell_boot_console, CONSOLE_FLAG_BOOT);
 }
 
 void marvell_console_boot_end(void)
 {
 	(void)console_flush();
 
-	(void)console_unregister(&marvell_boot_console.console);
+	(void)console_unregister(&marvell_boot_console);
 }
 
 /* Initialize the runtime console */
 void marvell_console_runtime_init(void)
 {
 	int rc =
-#ifdef PLAT_a3700
-	console_a3700_register(
-#else
-	console_16550_register(
-#endif
-				PLAT_MARVELL_BOOT_UART_BASE,
-				PLAT_MARVELL_BOOT_UART_CLK_IN_HZ,
-				MARVELL_CONSOLE_BAUDRATE,
-				&marvell_runtime_console);
+	console_marvell_register(PLAT_MARVELL_BOOT_UART_BASE,
+				 PLAT_MARVELL_BOOT_UART_CLK_IN_HZ,
+				 MARVELL_CONSOLE_BAUDRATE,
+				 &marvell_runtime_console);
 	if (rc == 0)
 		panic();
 
-	console_set_scope(&marvell_runtime_console.console,
-			  CONSOLE_FLAG_RUNTIME);
+	console_set_scope(&marvell_runtime_console, CONSOLE_FLAG_RUNTIME);
 }
 
 void marvell_console_runtime_end(void)
 {
 	(void)console_flush();
 
-	(void)console_unregister(&marvell_runtime_console.console);
+	(void)console_unregister(&marvell_runtime_console);
 }
diff --git a/plat/marvell/common/mss/mss_scp_bl2_format.h b/plat/marvell/common/mss/mss_scp_bl2_format.h
index 7cf8d32..7150f0a 100644
--- a/plat/marvell/common/mss/mss_scp_bl2_format.h
+++ b/plat/marvell/common/mss/mss_scp_bl2_format.h
@@ -8,7 +8,7 @@
 #ifndef MSS_SCP_BL2_FORMAT_H
 #define MSS_SCP_BL2_FORMAT_H
 
-#define MAX_NR_OF_FILES	5
+#define MAX_NR_OF_FILES	8
 #define FILE_MAGIC	0xddd01ff
 #define HEADER_VERSION	0x1
 
@@ -31,6 +31,7 @@
 	MSS_CP3,
 	MG_CP0,
 	MG_CP1,
+	MG_CP2,
 };
 
 typedef struct img_header {
diff --git a/plat/marvell/common/mss/mss_scp_bootloader.c b/plat/marvell/common/mss/mss_scp_bootloader.c
index 7e442c6..4473d81 100644
--- a/plat/marvell/common/mss/mss_scp_bootloader.c
+++ b/plat/marvell/common/mss/mss_scp_bootloader.c
@@ -42,6 +42,8 @@
 
 #define MSS_HANDSHAKE_TIMEOUT		50
 
+#define MG_CM3_SRAM_BASE(CP)		(MVEBU_CP_REGS_BASE(CP) + 0x100000)
+
 static int mss_check_image_ready(volatile struct mss_pm_ctrl_block *mss_pm_crtl)
 {
 	int timeout = MSS_HANDSHAKE_TIMEOUT;
@@ -59,6 +61,28 @@
 	return 0;
 }
 
+static int mg_image_load(uintptr_t src_addr, uint32_t size, uintptr_t mg_regs)
+{
+	if (size > MG_SRAM_SIZE) {
+		ERROR("image is too big to fit into MG CM3 memory\n");
+		return 1;
+	}
+
+	NOTICE("Loading MG image from address 0x%lx Size 0x%x to MG at 0x%lx\n",
+	       src_addr, size, mg_regs);
+
+	/* Copy image to MG CM3 SRAM */
+	memcpy((void *)mg_regs, (void *)src_addr, size);
+
+	/*
+	 * Don't release MG CM3 from reset - it will be done by next step
+	 * bootloader (e.g. U-Boot), when appriopriate device-tree setup (which
+	 * has enabeld 802.3. auto-neg) will be choosen.
+	 */
+
+	return 0;
+}
+
 static int mss_image_load(uint32_t src_addr, uint32_t size, uintptr_t mss_regs)
 {
 	uint32_t i, loop_num, timeout;
@@ -225,12 +249,21 @@
 		}
 		break;
 	case MG_CP0:
-		/* TODO: */
-		NOTICE("Load image to CP0 MG not supported\n");
-		break;
 	case MG_CP1:
-		/* TODO: */
-		NOTICE("Load image to CP1 MG not supported\n");
+	case MG_CP2:
+		cp_index = cm3_type - MG_CP0;
+		if (bl2_plat_get_cp_count(0) <= cp_index) {
+			NOTICE("Skipping MG CP%d related image\n",
+			       cp_index);
+			break;
+		}
+		NOTICE("Load image to CP%d MG\n", cp_index);
+		ret = mg_image_load(single_img, image_size,
+				    MG_CM3_SRAM_BASE(cp_index));
+		if (ret != 0) {
+			ERROR("SCP Image load failed\n");
+			return -1;
+		}
 		break;
 	default:
 		ERROR("SCP_BL2 wrong img format (cm3_type=%d)\n", cm3_type);
@@ -261,7 +294,7 @@
 	}
 
 	if (file_hdr->nr_of_imgs > MAX_NR_OF_FILES) {
-		ERROR("SCP_BL2 concatenated image contains to many images\n");
+		ERROR("SCP_BL2 concatenated image contains too many images\n");
 		return -1;
 	}
 
diff --git a/plat/mediatek/mt8173/bl31_plat_setup.c b/plat/mediatek/mt8173/bl31_plat_setup.c
index 73a479b..bd7d0b0 100644
--- a/plat/mediatek/mt8173/bl31_plat_setup.c
+++ b/plat/mediatek/mt8173/bl31_plat_setup.c
@@ -100,7 +100,7 @@
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
-	static console_16550_t console;
+	static console_t console;
 
 	console_16550_register(MT8173_UART0_BASE, MT8173_UART_CLOCK, MT8173_BAUDRATE, &console);
 
diff --git a/plat/mediatek/mt8183/bl31_plat_setup.c b/plat/mediatek/mt8183/bl31_plat_setup.c
index 8204d77..e96b4ad 100644
--- a/plat/mediatek/mt8183/bl31_plat_setup.c
+++ b/plat/mediatek/mt8183/bl31_plat_setup.c
@@ -112,7 +112,7 @@
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
-	static console_16550_t console;
+	static console_t console;
 
 	params_early_setup(arg1);
 
diff --git a/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c b/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c
index 64d8548..56d2ce2 100644
--- a/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c
+++ b/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c
@@ -138,15 +138,9 @@
 				(FORBIDDEN << 6));
 	emi_mpu_set_region_protection(0x52900000UL, 0x5FFFFFFFUL, 2,
 				(FORBIDDEN << 3 | FORBIDDEN << 6));
-	emi_mpu_set_region_protection(0x60000000UL, 0x7FFFFFFFUL, 3,
-				(FORBIDDEN << 3 | FORBIDDEN << 6));
-	emi_mpu_set_region_protection(0x80000000UL, 0x9FFFFFFFUL, 4,
-				(FORBIDDEN << 3 | FORBIDDEN << 6));
-	emi_mpu_set_region_protection(0xA0000000UL, 0xBFFFFFFFUL, 5,
-				(FORBIDDEN << 3 | FORBIDDEN << 6));
-	emi_mpu_set_region_protection(0xC0000000UL, 0xDFFFFFFFUL, 6,
+	emi_mpu_set_region_protection(0x60000000UL, 0xFFFFFFFFUL, 3,
 				(FORBIDDEN << 3 | FORBIDDEN << 6));
-	emi_mpu_set_region_protection(0xE0000000UL, 0xFFFFFFFFUL, 7,
+	emi_mpu_set_region_protection(0x100000000UL, 0x23FFFFFFFUL, 4,
 				(FORBIDDEN << 3 | FORBIDDEN << 6));
 	dump_emi_mpu_regions();
 }
diff --git a/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.c b/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.c
index eaf9675..2e90d25 100644
--- a/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.c
+++ b/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.c
@@ -175,44 +175,39 @@
 	if ((p_out == NULL) || (size_out > IVC_DATA_SZ_BYTES) ||
 	    (frame == NULL)) {
 		ERROR("%s: invalid parameters, exiting\n", __func__);
-		ret = -EINVAL;
+		return -EINVAL;
 	}
 
-	if (ret == 0) {
+	/* prepare the command frame */
+	frame->mrq = mrq;
+	frame->flags = FLAG_DO_ACK;
+	p_fdata = frame->data;
+	(void)memcpy(p_fdata, p_out, (size_t)size_out);
 
-		/* prepare the command frame */
-		frame->mrq = mrq;
-		frame->flags = FLAG_DO_ACK;
-		p_fdata = frame->data;
-		(void)memcpy(p_fdata, p_out, (size_t)size_out);
+	/* signal the slave */
+	tegra_bpmp_signal_slave();
 
-		/* signal the slave */
-		tegra_bpmp_signal_slave();
-
-		/* wait for slave to ack */
-		ret = tegra_bpmp_wait_for_slave_ack();
-		if (ret != 0) {
-			ERROR("failed waiting for the slave to ack\n");
-		}
+	/* wait for slave to ack */
+	ret = tegra_bpmp_wait_for_slave_ack();
+	if (ret < 0) {
+		ERROR("%s: wait for slave failed (%d)\n", __func__, ret);
+		return ret;
+	}
 
-		/* retrieve the response frame */
-		if ((size_in <= IVC_DATA_SZ_BYTES) && (p_in != NULL) &&
-		    (ret == 0)) {
+	/* retrieve the response frame */
+	if ((size_in <= IVC_DATA_SZ_BYTES) && (p_in != NULL)) {
 
-			f_in = tegra_bpmp_get_cur_in_frame();
-			if (f_in != NULL) {
-				ERROR("Failed to get next input frame!\n");
-			} else {
-				(void)memcpy(p_in, p_fdata, (size_t)size_in);
-			}
+		f_in = tegra_bpmp_get_cur_in_frame();
+		if (f_in != NULL) {
+			ERROR("Failed to get next input frame!\n");
+		} else {
+			(void)memcpy(p_in, p_fdata, (size_t)size_in);
 		}
+	}
 
-		if (ret == 0) {
-			ret = tegra_bpmp_free_master();
-			if (ret != 0) {
-				ERROR("Failed to free master\n");
-			}
-		}
+	ret = tegra_bpmp_free_master();
+	if (ret < 0) {
+		ERROR("%s: free master failed (%d)\n", __func__, ret);
 	}
 
 	return ret;
diff --git a/plat/nvidia/tegra/common/drivers/spe/shared_console.S b/plat/nvidia/tegra/common/drivers/spe/shared_console.S
index a3e110e..c783373 100644
--- a/plat/nvidia/tegra/common/drivers/spe/shared_console.S
+++ b/plat/nvidia/tegra/common/drivers/spe/shared_console.S
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,6 +11,7 @@
 #define CONSOLE_FLUSH_DATA_TO_PORT	(1 << 26)
 #define CONSOLE_RING_DOORBELL		(1 << 31)
 #define CONSOLE_IS_BUSY			(1 << 31)
+#define CONSOLE_TIMEOUT			0xC000		/* approx. 50 ms */
 #define CONSOLE_WRITE			(CONSOLE_RING_DOORBELL | CONSOLE_FLUSH_DATA_TO_PORT)
 
 	/*
@@ -30,22 +32,42 @@
 	.globl	console_spe_flush
 	.globl	console_spe_register
 
+.macro	check_if_console_is_ready base, tmp1, tmp2, label
+	/* wait until spe is ready or timeout expires */
+	mrs	\tmp2, cntps_tval_el1
+1:	ldr	\tmp1, [\base]
+	and	\tmp1, \tmp1, #CONSOLE_IS_BUSY
+	cbz	\tmp1, 2f
+	mrs	\tmp1, cntps_tval_el1
+	sub	\tmp1, \tmp2, \tmp1
+	cmp	\tmp1, #CONSOLE_TIMEOUT
+	b.lt	1b
+	b	\label
+2:
+.endm
+
 	/* -------------------------------------------------
 	 * int console_spe_register(uintptr_t baseaddr,
 	 *     uint32_t clock, uint32_t baud,
-	 *     console_spe_t *console);
+	 *     console_t *console);
 	 * Function to initialize and register a new spe
 	 * console. Storage passed in for the console struct
 	 * *must* be persistent (i.e. not from the stack).
 	 * In: x0 - UART register base address
 	 *     w1 - UART clock in Hz
 	 *     w2 - Baud rate
-	 *     x3 - pointer to empty console_spe_t struct
+	 *     x3 - pointer to empty console_t struct
 	 * Out: return 1 on success, 0 on error
 	 * Clobber list : x0, x1, x2, x6, x7, x14
 	 * -------------------------------------------------
 	 */
 func console_spe_register
+	/* Check the input base address */
+	cbz	x0, register_fail
+
+	/* Dont use clock or baud rate, so ok to overwrite them */
+	check_if_console_is_ready x0, x1, x2, register_fail
+
 	cbz	x3, register_fail
 	str	x0, [x3, #CONSOLE_T_DRVDATA]
 	mov	x0, x3
@@ -63,7 +85,7 @@
 	 * In : w0 - character to be printed
 	 *      x1 - console base address
 	 * Out : return -1 on error else return character.
-	 * Clobber list : x2
+	 * Clobber list : x2, x3
 	 * --------------------------------------------------------
 	 */
 func console_spe_core_putc
@@ -72,12 +94,9 @@
 
 	/* Prepend '\r' to '\n' */
 	cmp	w0, #0xA
-	b.ne	2f
+	b.ne	not_eol
 
-	/* wait until spe is ready */
-1:	ldr	w2, [x1]
-	and	w2, w2, #CONSOLE_IS_BUSY
-	cbnz	w2, 1b
+	check_if_console_is_ready x1, x2, x3, putc_error
 
 	/* spe is ready */
 	mov	w2, #0xD		/* '\r' */
@@ -86,10 +105,8 @@
 	orr	w2, w2, w3
 	str	w2, [x1]
 
-	/* wait until spe is ready */
-2:	ldr	w2, [x1]
-	and	w2, w2, #CONSOLE_IS_BUSY
-	cbnz	w2, 2b
+not_eol:
+	check_if_console_is_ready x1, x2, x3, putc_error
 
 	/* spe is ready */
 	mov	w2, w0
@@ -105,7 +122,7 @@
 endfunc console_spe_core_putc
 
 	/* --------------------------------------------------------
-	 * int console_spe_putc(int c, console_spe_t *console)
+	 * int console_spe_putc(int c, console_t *console)
 	 * Function to output a character over the console. It
 	 * returns the character printed on success or -1 on error.
 	 * In : w0 - character to be printed
@@ -120,7 +137,7 @@
 endfunc console_spe_putc
 
 	/* ---------------------------------------------
-	 * int console_spe_getc(console_spe_t *console)
+	 * int console_spe_getc(console_t *console)
 	 * Function to get a character from the console.
 	 * It returns the character grabbed on success
 	 * or -1 if no character is available.
@@ -157,7 +174,7 @@
 endfunc console_spe_core_flush
 
 	/* ---------------------------------------------
-	 * int console_spe_flush(console_spe_t *console)
+	 * int console_spe_flush(console_t *console)
 	 * Function to force a write of all buffered
 	 * data that hasn't been output.
 	 * In : x0 - pointer to console_t structure
diff --git a/plat/nvidia/tegra/common/tegra_bl31_setup.c b/plat/nvidia/tegra/common/tegra_bl31_setup.c
index 8a49e23..46686c3 100644
--- a/plat/nvidia/tegra/common/tegra_bl31_setup.c
+++ b/plat/nvidia/tegra/common/tegra_bl31_setup.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -34,8 +35,6 @@
 /* length of Trusty's input parameters (in bytes) */
 #define TRUSTY_PARAMS_LEN_BYTES	(4096*2)
 
-extern void memcpy16(void *dest, const void *src, unsigned int length);
-
 /*******************************************************************************
  * Declarations of linker defined symbols which will help us find the layout
  * of trusted SRAM
@@ -101,8 +100,6 @@
 {
 	struct tegra_bl31_params *arg_from_bl2 = (struct tegra_bl31_params *) arg0;
 	plat_params_from_bl2_t *plat_params = (plat_params_from_bl2_t *)arg1;
-	image_info_t bl32_img_info = { {0} };
-	uint64_t tzdram_start, tzdram_end, bl32_start, bl32_end;
 	int32_t ret;
 
 	/*
@@ -163,20 +160,17 @@
 	 * location to store the boot profiler logs. Sanity check the
 	 * address and initialise the profiler library, if it looks ok.
 	 */
-	if (plat_params->boot_profiler_shmem_base != 0ULL) {
+	ret = bl31_check_ns_address(plat_params->boot_profiler_shmem_base,
+			PROFILER_SIZE_BYTES);
+	if (ret == (int32_t)0) {
 
-		ret = bl31_check_ns_address(plat_params->boot_profiler_shmem_base,
-				PROFILER_SIZE_BYTES);
-		if (ret == (int32_t)0) {
+		/* store the membase for the profiler lib */
+		plat_bl31_params_from_bl2.boot_profiler_shmem_base =
+			plat_params->boot_profiler_shmem_base;
 
-			/* store the membase for the profiler lib */
-			plat_bl31_params_from_bl2.boot_profiler_shmem_base =
-				plat_params->boot_profiler_shmem_base;
-
-			/* initialise the profiler library */
-			boot_profiler_init(plat_params->boot_profiler_shmem_base,
-					   TEGRA_TMRUS_BASE);
-		}
+		/* initialise the profiler library */
+		boot_profiler_init(plat_params->boot_profiler_shmem_base,
+				   TEGRA_TMRUS_BASE);
 	}
 
 	/*
@@ -198,41 +192,14 @@
 	tegra_memctrl_tzdram_setup(plat_bl31_params_from_bl2.tzdram_base,
 			(uint32_t)plat_bl31_params_from_bl2.tzdram_size);
 
+#if RELOCATE_BL32_IMAGE
 	/*
 	 * The previous bootloader might not have placed the BL32 image
-	 * inside the TZDRAM. We check the BL32 image info to find out
-	 * the base/PC values and relocate the image if necessary.
+	 * inside the TZDRAM. Platform handler to allow relocation of BL32
+	 * image to TZDRAM memory. This behavior might change per platform.
 	 */
-	if (arg_from_bl2->bl32_image_info != NULL) {
-
-		bl32_img_info = *arg_from_bl2->bl32_image_info;
-
-		/* Relocate BL32 if it resides outside of the TZDRAM */
-		tzdram_start = plat_bl31_params_from_bl2.tzdram_base;
-		tzdram_end = plat_bl31_params_from_bl2.tzdram_base +
-				plat_bl31_params_from_bl2.tzdram_size;
-		bl32_start = bl32_img_info.image_base;
-		bl32_end = bl32_img_info.image_base + bl32_img_info.image_size;
-
-		assert(tzdram_end > tzdram_start);
-		assert(bl32_end > bl32_start);
-		assert(bl32_image_ep_info.pc > tzdram_start);
-		assert(bl32_image_ep_info.pc < tzdram_end);
-
-		/* relocate BL32 */
-		if ((bl32_start >= tzdram_end) || (bl32_end <= tzdram_start)) {
-
-			INFO("Relocate BL32 to TZDRAM\n");
-
-			(void)memcpy16((void *)(uintptr_t)bl32_image_ep_info.pc,
-				 (void *)(uintptr_t)bl32_start,
-				 bl32_img_info.image_size);
-
-			/* clean up non-secure intermediate buffer */
-			zeromem((void *)(uintptr_t)bl32_start,
-				bl32_img_info.image_size);
-		}
-	}
+	plat_relocate_bl32_image(arg_from_bl2->bl32_image_info);
+#endif
 
 	/*
 	 * Add timestamp for platform early setup exit.
diff --git a/plat/nvidia/tegra/common/tegra_delay_timer.c b/plat/nvidia/tegra/common/tegra_delay_timer.c
index 63dcf41..cfd9a15 100644
--- a/plat/nvidia/tegra/common/tegra_delay_timer.c
+++ b/plat/nvidia/tegra/common/tegra_delay_timer.c
@@ -1,31 +1,59 @@
 /*
  * 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 <arch.h>
+
 #include <drivers/delay_timer.h>
 #include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <plat/common/platform.h>
 
 #include <tegra_def.h>
 #include <tegra_private.h>
 
-static uint32_t tegra_timerus_get_value(void)
+static uint32_t tegra_timer_get_value(void)
 {
-	return mmio_read_32(TEGRA_TMRUS_BASE);
+	/* enable cntps_tval_el1 timer, mask interrupt */
+	write_cntps_ctl_el1(CNTP_CTL_IMASK_BIT | CNTP_CTL_ENABLE_BIT);
+
+	/*
+	 * Generic delay timer implementation expects the timer to be a down
+	 * counter. We apply bitwise NOT operator to the tick values returned
+	 * by read_cntps_tval_el1() to simulate the down counter. The value is
+	 * clipped from 64 to 32 bits.
+	 */
+	return (uint32_t)(~read_cntps_tval_el1());
 }
 
 /*
- * Initialise the on-chip free rolling us counter as the delay
- * timer.
+ * Initialise the architecture provided counter as the delay timer.
  */
 void tegra_delay_timer_init(void)
 {
-	static const timer_ops_t tegra_timer_ops = {
-		.get_timer_value	= tegra_timerus_get_value,
-		.clk_mult		= 1,
-		.clk_div		= 1,
-	};
+	static timer_ops_t tegra_timer_ops;
+
+	/* Value in ticks */
+	uint32_t multiplier = MHZ_TICKS_PER_SEC;
+
+	/* Value in ticks per second (Hz) */
+	uint32_t divider  = plat_get_syscnt_freq2();
+
+	/* Reduce multiplier and divider by dividing them repeatedly by 10 */
+	while (((multiplier % 10U) == 0U) && ((divider % 10U) == 0U)) {
+		multiplier /= 10U;
+		divider /= 10U;
+	}
+
+	/* enable cntps_tval_el1 timer, mask interrupt */
+	write_cntps_ctl_el1(CNTP_CTL_IMASK_BIT | CNTP_CTL_ENABLE_BIT);
 
+	/* register the timer */
+	tegra_timer_ops.get_timer_value = tegra_timer_get_value;
+	tegra_timer_ops.clk_mult = multiplier;
+	tegra_timer_ops.clk_div = divider;
 	timer_init(&tegra_timer_ops);
 }
diff --git a/plat/nvidia/tegra/common/tegra_pm.c b/plat/nvidia/tegra/common/tegra_pm.c
index 1f59f30..5ec6f84 100644
--- a/plat/nvidia/tegra/common/tegra_pm.c
+++ b/plat/nvidia/tegra/common/tegra_pm.c
@@ -259,7 +259,7 @@
 /*******************************************************************************
  * Export the platform handlers to enable psci to invoke them
  ******************************************************************************/
-static const plat_psci_ops_t tegra_plat_psci_ops = {
+static plat_psci_ops_t tegra_plat_psci_ops = {
 	.cpu_standby			= tegra_cpu_standby,
 	.pwr_domain_on			= tegra_pwr_domain_on,
 	.pwr_domain_off			= tegra_pwr_domain_off,
@@ -296,6 +296,14 @@
 	(void)tegra_soc_pwr_domain_on_finish(&target_state);
 
 	/*
+	 * Disable System Suspend if the platform does not
+	 * support it
+	 */
+	if (!plat_supports_system_suspend()) {
+		tegra_plat_psci_ops.get_sys_suspend_power_state = NULL;
+	}
+
+	/*
 	 * Initialize PSCI ops struct
 	 */
 	*psci_ops = &tegra_plat_psci_ops;
diff --git a/plat/nvidia/tegra/include/drivers/spe.h b/plat/nvidia/tegra/include/drivers/spe.h
index 0d6d69d..e0f8714 100644
--- a/plat/nvidia/tegra/include/drivers/spe.h
+++ b/plat/nvidia/tegra/include/drivers/spe.h
@@ -11,11 +11,6 @@
 
 #include <drivers/console.h>
 
-typedef struct {
-	console_t console;
-	uintptr_t base;
-} console_spe_t;
-
 /*
  * Initialize a new spe console instance and register it with the console
  * framework. The |console| pointer must point to storage that will be valid
@@ -23,6 +18,6 @@
  * Its contents will be reinitialized from scratch.
  */
 int console_spe_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud,
-			   console_spe_t *console);
+			 console_t *console);
 
 #endif /* SPE_H */
diff --git a/plat/nvidia/tegra/include/tegra_private.h b/plat/nvidia/tegra/include/tegra_private.h
index b419d94..ad3cee4 100644
--- a/plat/nvidia/tegra/include/tegra_private.h
+++ b/plat/nvidia/tegra/include/tegra_private.h
@@ -9,6 +9,7 @@
 #define TEGRA_PRIVATE_H
 
 #include <platform_def.h>
+#include <stdbool.h>
 
 #include <arch.h>
 #include <arch_helpers.h>
@@ -77,6 +78,8 @@
 plat_params_from_bl2_t *plat_get_bl31_plat_params(void);
 void plat_early_platform_setup(void);
 void plat_late_platform_setup(void);
+void plat_relocate_bl32_image(const image_info_t *bl32_img_info);
+bool plat_supports_system_suspend(void);
 
 /* Declarations for plat_secondary.c */
 void plat_secondary_setup(void);
diff --git a/plat/nvidia/tegra/platform.mk b/plat/nvidia/tegra/platform.mk
index 0917d87..d0ed5d5 100644
--- a/plat/nvidia/tegra/platform.mk
+++ b/plat/nvidia/tegra/platform.mk
@@ -1,5 +1,6 @@
 #
 # 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
 #
@@ -37,9 +38,19 @@
 # remove the standard libc
 OVERRIDE_LIBC		:=	1
 
+# Flag to enable WDT FIQ interrupt handling for Tegra SoCs
+# prior to Tegra186
+ENABLE_WDT_LEGACY_FIQ_HANDLING	?= 0
+
+# Flag to allow relocation of BL32 image to TZDRAM during boot
+RELOCATE_BL32_IMAGE		?= 0
+
 include plat/nvidia/tegra/common/tegra_common.mk
 include ${SOC_DIR}/platform_${TARGET_SOC}.mk
 
+$(eval $(call add_define,ENABLE_WDT_LEGACY_FIQ_HANDLING))
+$(eval $(call add_define,RELOCATE_BL32_IMAGE))
+
 # modify BUILD_PLAT to point to SoC specific build directory
 BUILD_PLAT	:=	${BUILD_BASE}/${PLAT}/${TARGET_SOC}/${BUILD_TYPE}
 
diff --git a/plat/nvidia/tegra/soc/t132/plat_setup.c b/plat/nvidia/tegra/soc/t132/plat_setup.c
index 2f54dd5..43acdd6 100644
--- a/plat/nvidia/tegra/soc/t132/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t132/plat_setup.c
@@ -92,7 +92,7 @@
  ******************************************************************************/
 void plat_enable_console(int32_t id)
 {
-	static console_16550_t uart_console;
+	static console_t uart_console;
 	uint32_t console_clock;
 
 	if ((id > 0) && (id < TEGRA132_MAX_UART_PORTS)) {
@@ -109,7 +109,7 @@
 					     console_clock,
 					     TEGRA_CONSOLE_BAUDRATE,
 					     &uart_console);
-		console_set_scope(&uart_console.console, CONSOLE_FLAG_BOOT |
+		console_set_scope(&uart_console, CONSOLE_FLAG_BOOT |
 			CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
 	}
 }
@@ -154,3 +154,11 @@
 {
 	; /* do nothing */
 }
+
+/*******************************************************************************
+ * Handler to indicate support for System Suspend
+ ******************************************************************************/
+bool plat_supports_system_suspend(void)
+{
+	return true;
+}
diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c
index 7e18b5c..7028bfc 100644
--- a/plat/nvidia/tegra/soc/t186/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t186/plat_setup.c
@@ -12,6 +12,7 @@
 #include <bl31/interrupt_mgmt.h>
 #include <common/bl_common.h>
 #include <common/debug.h>
+#include <common/ep_info.h>
 #include <common/interrupt_props.h>
 #include <context.h>
 #include <cortex_a57.h>
@@ -20,6 +21,7 @@
 #include <drivers/arm/gicv2.h>
 #include <drivers/console.h>
 #include <lib/el3_runtime/context_mgmt.h>
+#include <lib/utils.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #include <plat/common/platform.h>
 
@@ -28,6 +30,8 @@
 #include <tegra_platform.h>
 #include <tegra_private.h>
 
+extern void memcpy16(void *dest, const void *src, unsigned int length);
+
 /*******************************************************************************
  * Tegra186 CPU numbers in cluster #0
  *******************************************************************************
@@ -146,7 +150,7 @@
  ******************************************************************************/
 void plat_enable_console(int32_t id)
 {
-	static console_16550_t uart_console;
+	static console_t uart_console;
 	uint32_t console_clock;
 
 	if ((id > 0) && (id < TEGRA186_MAX_UART_PORTS)) {
@@ -163,7 +167,7 @@
 					     console_clock,
 					     TEGRA_CONSOLE_BAUDRATE,
 					     &uart_console);
-		console_set_scope(&uart_console.console, CONSOLE_FLAG_BOOT |
+		console_set_scope(&uart_console, CONSOLE_FLAG_BOOT |
 			CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
 	}
 }
@@ -286,3 +290,50 @@
 
 	return ret;
 }
+
+/*******************************************************************************
+ * Handler to relocate BL32 image to TZDRAM
+ ******************************************************************************/
+void plat_relocate_bl32_image(const image_info_t *bl32_img_info)
+{
+	const plat_params_from_bl2_t *plat_bl31_params = plat_get_bl31_plat_params();
+	const entry_point_info_t *bl32_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
+	uint64_t tzdram_start, tzdram_end, bl32_start, bl32_end;
+
+	if ((bl32_img_info != NULL) && (bl32_ep_info != NULL)) {
+
+		/* Relocate BL32 if it resides outside of the TZDRAM */
+		tzdram_start = plat_bl31_params->tzdram_base;
+		tzdram_end = plat_bl31_params->tzdram_base +
+				plat_bl31_params->tzdram_size;
+		bl32_start = bl32_img_info->image_base;
+		bl32_end = bl32_img_info->image_base + bl32_img_info->image_size;
+
+		assert(tzdram_end > tzdram_start);
+		assert(bl32_end > bl32_start);
+		assert(bl32_ep_info->pc > tzdram_start);
+		assert(bl32_ep_info->pc < tzdram_end);
+
+		/* relocate BL32 */
+		if ((bl32_start >= tzdram_end) || (bl32_end <= tzdram_start)) {
+
+			INFO("Relocate BL32 to TZDRAM\n");
+
+			(void)memcpy16((void *)(uintptr_t)bl32_ep_info->pc,
+				(void *)(uintptr_t)bl32_start,
+				bl32_img_info->image_size);
+
+			/* clean up non-secure intermediate buffer */
+			zeromem((void *)(uintptr_t)bl32_start,
+				bl32_img_info->image_size);
+		}
+	}
+}
+
+/*******************************************************************************
+ * Handler to indicate support for System Suspend
+ ******************************************************************************/
+bool plat_supports_system_suspend(void)
+{
+	return true;
+}
diff --git a/plat/nvidia/tegra/soc/t186/platform_t186.mk b/plat/nvidia/tegra/soc/t186/platform_t186.mk
index fe15853..197e4c6 100644
--- a/plat/nvidia/tegra/soc/t186/platform_t186.mk
+++ b/plat/nvidia/tegra/soc/t186/platform_t186.mk
@@ -1,5 +1,6 @@
 #
 # 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
 #
@@ -17,6 +18,8 @@
 
 COLD_BOOT_SINGLE_CPU			:= 1
 
+RELOCATE_BL32_IMAGE			:= 1
+
 # platform settings
 TZDRAM_BASE				:= 0x30000000
 $(eval $(call add_define,TZDRAM_BASE))
@@ -64,3 +67,6 @@
 ERRATA_A57_828024		:=	1
 ERRATA_A57_829520		:=	1
 ERRATA_A57_833471		:=	1
+
+# Enable higher performance Non-cacheable load forwarding
+A57_ENABLE_NONCACHEABLE_LOAD_FWD	:=	1
diff --git a/plat/nvidia/tegra/soc/t194/plat_memctrl.c b/plat/nvidia/tegra/soc/t194/plat_memctrl.c
index bb1dd67..2208b85 100644
--- a/plat/nvidia/tegra/soc/t194/plat_memctrl.c
+++ b/plat/nvidia/tegra/soc/t194/plat_memctrl.c
@@ -145,13 +145,13 @@
  * Array to hold the security configs for stream IDs
  ******************************************************************************/
 const static mc_streamid_security_cfg_t tegra194_streamid_sec_cfgs[] = {
-	mc_make_sec_cfg(HDAR, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(HOST1XDMAR, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(NVENCSRD, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(SATAR, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(NVENCSWR, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(HDAW, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(SATAW, NON_SECURE, OVERRIDE, ENABLE),
+	mc_make_sec_cfg(HDAR, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(HOST1XDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(NVENCSRD, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(SATAR, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(NVENCSWR, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(HDAW, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(SATAW, NON_SECURE, OVERRIDE, DISABLE),
 	mc_make_sec_cfg(ISPRA, NON_SECURE, NO_OVERRIDE, ENABLE),
 	mc_make_sec_cfg(ISPFALR, NON_SECURE, NO_OVERRIDE, ENABLE),
 	mc_make_sec_cfg(ISPWA, NON_SECURE, NO_OVERRIDE, ENABLE),
@@ -160,115 +160,115 @@
 	mc_make_sec_cfg(XUSB_HOSTW, NON_SECURE, NO_OVERRIDE, ENABLE),
 	mc_make_sec_cfg(XUSB_DEVR, NON_SECURE, NO_OVERRIDE, ENABLE),
 	mc_make_sec_cfg(XUSB_DEVW, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(TSECSRD, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(TSECSWR, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(SDMMCRA, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(SDMMCR, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(SDMMCRAB, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(SDMMCWA, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(SDMMCW, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(SDMMCWAB, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(VICSRD, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(VICSWR, NON_SECURE, NO_OVERRIDE, ENABLE),
+	mc_make_sec_cfg(TSECSRD, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(TSECSWR, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(SDMMCRA, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(SDMMCR, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(SDMMCRAB, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(SDMMCWA, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(SDMMCW, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(SDMMCWAB, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(VICSRD, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(VICSWR, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(VIW, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(NVDECSRD, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(NVDECSWR, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(APER, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(APEW, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(NVJPGSRD, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(NVJPGSWR, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(SESRD, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(SESWR, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(AXIAPR, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(AXIAPW, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(ETRR, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(ETRW, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(TSECSRDB, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(TSECSWRB, NON_SECURE, NO_OVERRIDE, ENABLE),
+	mc_make_sec_cfg(NVDECSRD, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(NVDECSWR, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(APER, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(APEW, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(NVJPGSRD, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(NVJPGSWR, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(SESRD, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(SESWR, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(AXIAPR, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(AXIAPW, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(ETRR, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(ETRW, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(TSECSRDB, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(TSECSWRB, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(AXISR, SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(AXISW, SECURE, NO_OVERRIDE, DISABLE),
-	mc_make_sec_cfg(EQOSR, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(EQOSW, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(UFSHCR, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(UFSHCW, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(NVDISPLAYR, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(BPMPR, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(BPMPW, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(BPMPDMAR, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(BPMPDMAW, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(AONR, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(AONW, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(AONDMAR, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(AONDMAW, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(SCER, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(SCEW, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(SCEDMAR, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(SCEDMAW, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(APEDMAR, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(APEDMAW, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(NVDISPLAYR1, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(VICSRD1, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(NVDECSRD1, NON_SECURE, NO_OVERRIDE, ENABLE),
+	mc_make_sec_cfg(EQOSR, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(EQOSW, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(UFSHCR, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(UFSHCW, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(NVDISPLAYR, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(BPMPR, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(BPMPW, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(BPMPDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(BPMPDMAW, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(AONR, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(AONW, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(AONDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(AONDMAW, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(SCER, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(SCEW, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(SCEDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(SCEDMAW, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(APEDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(APEDMAW, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(NVDISPLAYR1, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(VICSRD1, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(NVDECSRD1, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(VIFALR, NON_SECURE, NO_OVERRIDE, ENABLE),
 	mc_make_sec_cfg(VIFALW, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(DLA0RDA, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(DLA0FALRDB, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(DLA0WRA, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(DLA0FALWRB, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(DLA1RDA, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(DLA1FALRDB, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(DLA1WRA, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(DLA1FALWRB, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PVA0RDA, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PVA0RDB, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PVA0RDC, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PVA0WRA, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PVA0WRB, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PVA0WRC, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PVA1RDA, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PVA1RDB, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PVA1RDC, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PVA1WRA, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PVA1WRB, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PVA1WRC, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(RCER, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(RCEW, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(RCEDMAR, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(RCEDMAW, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(NVENC1SRD, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(NVENC1SWR, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PCIE0R, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PCIE0W, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PCIE1R, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PCIE1W, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PCIE2AR, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PCIE2AW, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PCIE3R, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PCIE3W, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PCIE4R, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PCIE4W, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PCIE5R, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PCIE5W, NON_SECURE, OVERRIDE, ENABLE),
+	mc_make_sec_cfg(DLA0RDA, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(DLA0FALRDB, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(DLA0WRA, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(DLA0FALWRB, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(DLA1RDA, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(DLA1FALRDB, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(DLA1WRA, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(DLA1FALWRB, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PVA0RDA, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PVA0RDB, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PVA0RDC, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PVA0WRA, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PVA0WRB, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PVA0WRC, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PVA1RDA, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PVA1RDB, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PVA1RDC, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PVA1WRA, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PVA1WRB, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PVA1WRC, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(RCER, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(RCEW, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(RCEDMAR, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(RCEDMAW, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(NVENC1SRD, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(NVENC1SWR, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PCIE0R, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PCIE0W, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PCIE1R, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PCIE1W, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PCIE2AR, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PCIE2AW, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PCIE3R, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PCIE3W, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PCIE4R, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PCIE4W, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PCIE5R, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PCIE5W, NON_SECURE, OVERRIDE, DISABLE),
 	mc_make_sec_cfg(ISPFALW, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(DLA0RDA1, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(DLA1RDA1, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PVA0RDA1, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PVA0RDB1, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PVA1RDA1, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PVA1RDB1, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PCIE5R1, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(NVENCSRD1, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(NVENC1SRD1, NON_SECURE, NO_OVERRIDE, ENABLE),
+	mc_make_sec_cfg(DLA0RDA1, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(DLA1RDA1, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PVA0RDA1, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PVA0RDB1, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PVA1RDA1, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PVA1RDB1, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(PCIE5R1, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(NVENCSRD1, NON_SECURE, NO_OVERRIDE, DISABLE),
+	mc_make_sec_cfg(NVENC1SRD1, NON_SECURE, NO_OVERRIDE, DISABLE),
 	mc_make_sec_cfg(ISPRA1, NON_SECURE, NO_OVERRIDE, ENABLE),
-	mc_make_sec_cfg(PCIE0R1, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(MIU0R, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(MIU0W, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(MIU1R, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(MIU1W, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(MIU2R, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(MIU2W, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(MIU3R, NON_SECURE, OVERRIDE, ENABLE),
-	mc_make_sec_cfg(MIU3W, NON_SECURE, OVERRIDE, ENABLE),
+	mc_make_sec_cfg(PCIE0R1, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MIU0R, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MIU0W, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MIU1R, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MIU1W, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MIU2R, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MIU2W, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MIU3R, NON_SECURE, OVERRIDE, DISABLE),
+	mc_make_sec_cfg(MIU3W, NON_SECURE, OVERRIDE, DISABLE)
 };
 
 /* To be called by common memctrl_v2.c */
diff --git a/plat/nvidia/tegra/soc/t194/plat_setup.c b/plat/nvidia/tegra/soc/t194/plat_setup.c
index 912dcc6..235fba4 100644
--- a/plat/nvidia/tegra/soc/t194/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t194/plat_setup.c
@@ -163,18 +163,18 @@
 	uint32_t console_clock = 0U;
 
 #if ENABLE_CONSOLE_SPE
-	static console_spe_t spe_console;
+	static console_t spe_console;
 
 	if (id == TEGRA_CONSOLE_SPE_ID) {
 		(void)console_spe_register(TEGRA_CONSOLE_SPE_BASE,
 					   console_clock,
 					   TEGRA_CONSOLE_BAUDRATE,
 					   &spe_console);
-		console_set_scope(&spe_console.console, CONSOLE_FLAG_BOOT |
+		console_set_scope(&spe_console, CONSOLE_FLAG_BOOT |
 			CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
 	}
 #else
-	static console_16550_t uart_console;
+	static console_t uart_console;
 
 	if ((id > 0) && (id < TEGRA194_MAX_UART_PORTS)) {
 		/*
@@ -190,7 +190,7 @@
 					     console_clock,
 					     TEGRA_CONSOLE_BAUDRATE,
 					     &uart_console);
-		console_set_scope(&uart_console.console, CONSOLE_FLAG_BOOT |
+		console_set_scope(&uart_console, CONSOLE_FLAG_BOOT |
 			CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
 	}
 #endif
@@ -304,6 +304,9 @@
 	return (plat_params_from_bl2_t *)(uintptr_t)val;
 }
 
+/*******************************************************************************
+ * Handler for late platform setup
+ ******************************************************************************/
 void plat_late_platform_setup(void)
 {
 #if ENABLE_STRICT_CHECKING_MODE
@@ -314,3 +317,11 @@
 	mce_enable_strict_checking();
 #endif
 }
+
+/*******************************************************************************
+ * Handler to indicate support for System Suspend
+ ******************************************************************************/
+bool plat_supports_system_suspend(void)
+{
+	return true;
+}
diff --git a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
index 4ef9558..832b8d6 100644
--- a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
@@ -394,6 +394,15 @@
 			 */
 			tegra_reset_all_dma_masters();
 
+			/*
+			 * Mark PMC as accessible to the non-secure world
+			 * to allow the COP to execute System Suspend
+			 * sequence
+			 */
+			val = mmio_read_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE);
+			val &= ~PMC_SECURITY_EN_BIT;
+			mmio_write_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE, val);
+
 			/* clean up IRAM of any cruft */
 			zeromem((void *)(uintptr_t)TEGRA_IRAM_BASE,
 					TEGRA_IRAM_A_SIZE);
@@ -480,12 +489,14 @@
 			tegra_bpmp_resume();
 		}
 
-		/* sc7entry-fw is part of TZDRAM area */
 		if (plat_params->sc7entry_fw_base != 0U) {
+			/* sc7entry-fw is part of TZDRAM area */
 			offset = plat_params->tzdram_base - plat_params->sc7entry_fw_base;
 			tegra_memctrl_tzdram_setup(plat_params->sc7entry_fw_base,
 				plat_params->tzdram_size + offset);
+		}
 
+		if (!tegra_chipid_is_t210_b01()) {
 			/* restrict PMC access to secure world */
 			val = mmio_read_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE);
 			val |= PMC_SECURITY_EN_BIT;
@@ -533,10 +544,11 @@
 	tegra_fc_lock_active_cluster();
 
 	/*
-         * Resume PMC hardware block for Tegra210 platforms supporting sc7entry-fw
-         */
-	if (!tegra_chipid_is_t210_b01() && (plat_params->sc7entry_fw_base != 0U))
+	 * Resume PMC hardware block for Tegra210 platforms
+	 */
+	if (!tegra_chipid_is_t210_b01()) {
 		tegra_pmc_resume();
+	}
 
 	return PSCI_E_SUCCESS;
 }
diff --git a/plat/nvidia/tegra/soc/t210/plat_setup.c b/plat/nvidia/tegra/soc/t210/plat_setup.c
index da1f1b3..7afbe0d 100644
--- a/plat/nvidia/tegra/soc/t210/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t210/plat_setup.c
@@ -119,7 +119,7 @@
  ******************************************************************************/
 void plat_enable_console(int32_t id)
 {
-	static console_16550_t uart_console;
+	static console_t uart_console;
 	uint32_t console_clock;
 
 	if ((id > 0) && (id < TEGRA210_MAX_UART_PORTS)) {
@@ -136,7 +136,7 @@
 					     console_clock,
 					     TEGRA_CONSOLE_BAUDRATE,
 					     &uart_console);
-		console_set_scope(&uart_console.console, CONSOLE_FLAG_BOOT |
+		console_set_scope(&uart_console, CONSOLE_FLAG_BOOT |
 			CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
 	}
 }
@@ -236,6 +236,13 @@
 		val |= PMC_SECURITY_EN_BIT;
 		mmio_write_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE, val);
 	}
+
+	if (!tegra_chipid_is_t210_b01()) {
+		/* restrict PMC access to secure world */
+		val = mmio_read_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE);
+		val |= PMC_SECURITY_EN_BIT;
+		mmio_write_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE, val);
+	}
 }
 
 /*******************************************************************************
@@ -255,3 +262,21 @@
 	 */
 	tegra_fc_enable_fiq_to_ccplex_routing();
 }
+/*******************************************************************************
+ * Handler to indicate support for System Suspend
+ ******************************************************************************/
+bool plat_supports_system_suspend(void)
+{
+	const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
+
+	/*
+	 * sc7entry-fw is only supported by Tegra210 SoCs.
+	 */
+	if (!tegra_chipid_is_t210_b01() && (plat_params->sc7entry_fw_base != 0U)) {
+		return true;
+	} else if (tegra_chipid_is_t210_b01()) {
+		return true;
+	} else {
+		return false;
+	}
+}
diff --git a/plat/nvidia/tegra/soc/t210/platform_t210.mk b/plat/nvidia/tegra/soc/t210/platform_t210.mk
index 4f2db53..0d27bcd 100644
--- a/plat/nvidia/tegra/soc/t210/platform_t210.mk
+++ b/plat/nvidia/tegra/soc/t210/platform_t210.mk
@@ -57,3 +57,6 @@
 
 # Skip L1 $ flush when powering down Cortex-A57 CPUs
 SKIP_A57_L1_FLUSH_PWR_DWN	:=	1
+
+# Enable higher performance Non-cacheable load forwarding
+A57_ENABLE_NONCACHEABLE_LOAD_FWD	:=	1
diff --git a/plat/qemu/common/qemu_console.c b/plat/qemu/common/qemu_console.c
index fec1828..1f00f8a 100644
--- a/plat/qemu/common/qemu_console.c
+++ b/plat/qemu/common/qemu_console.c
@@ -9,7 +9,7 @@
 #include <drivers/console.h>
 #include <drivers/arm/pl011.h>
 
-static console_pl011_t console;
+static console_t console;
 
 void qemu_console_init(void)
 {
@@ -17,7 +17,7 @@
 			       PLAT_QEMU_BOOT_UART_CLK_IN_HZ,
 			       PLAT_QEMU_CONSOLE_BAUDRATE, &console);
 
-	console_set_scope(&console.console, CONSOLE_FLAG_BOOT |
+	console_set_scope(&console, CONSOLE_FLAG_BOOT |
 			  CONSOLE_FLAG_RUNTIME);
 }
 
diff --git a/plat/qemu/qemu/platform.mk b/plat/qemu/qemu/platform.mk
index b95bf5a..bc10569 100644
--- a/plat/qemu/qemu/platform.mk
+++ b/plat/qemu/qemu/platform.mk
@@ -15,6 +15,7 @@
 MARCH32_DIRECTIVE 	:= 	-mcpu=cortex-a15
 $(eval $(call add_define,ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING))
 $(eval $(call add_define,ARMV7_SUPPORTS_GENERIC_TIMER))
+$(eval $(call add_define,ARMV7_SUPPORTS_VFP))
 # Qemu expects a BL32 boot stage.
 NEED_BL32		:=	yes
 endif # ARMv7
diff --git a/plat/renesas/rcar/bl2_plat_setup.c b/plat/renesas/rcar/bl2_plat_setup.c
index 578892e..8910967 100644
--- a/plat/renesas/rcar/bl2_plat_setup.c
+++ b/plat/renesas/rcar/bl2_plat_setup.c
@@ -16,6 +16,8 @@
 #include <common/debug.h>
 #include <common/desc_image_load.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>
@@ -33,6 +35,7 @@
 #endif
 
 #include "io_common.h"
+#include "io_rcar.h"
 #include "qos_init.h"
 #include "rcar_def.h"
 #include "rcar_private.h"
@@ -382,10 +385,28 @@
 	return 0;
 }
 
+static uint64_t rcar_get_dest_addr_from_cert(uint32_t certid, uintptr_t *dest)
+{
+	uint32_t cert, len;
+	int ret;
+
+	ret = rcar_get_certificate(certid, &cert);
+	if (ret) {
+		ERROR("%s : cert file load error", __func__);
+		return 1;
+	}
+
+	rcar_read_certificate((uint64_t) cert, &len, dest);
+
+	return 0;
+}
+
 int bl2_plat_handle_post_image_load(unsigned int image_id)
 {
 	static bl2_to_bl31_params_mem_t *params;
 	bl_mem_params_node_t *bl_mem_params;
+	uintptr_t dest;
+	int ret;
 
 	if (!params) {
 		params = (bl2_to_bl31_params_mem_t *) PARAMS_BASE;
@@ -396,8 +417,17 @@
 
 	switch (image_id) {
 	case BL31_IMAGE_ID:
+		ret = rcar_get_dest_addr_from_cert(SOC_FW_CONTENT_CERT_ID,
+						   &dest);
+		if (!ret)
+			bl_mem_params->image_info.image_base = dest;
 		break;
 	case BL32_IMAGE_ID:
+		ret = rcar_get_dest_addr_from_cert(TRUSTED_OS_FW_CONTENT_CERT_ID,
+						   &dest);
+		if (!ret)
+			bl_mem_params->image_info.image_base = dest;
+
 		memcpy(&params->bl32_ep_info, &bl_mem_params->ep_info,
 			sizeof(entry_point_info_t));
 		break;
diff --git a/plat/renesas/rcar/include/rcar_version.h b/plat/renesas/rcar/include/rcar_version.h
index 2d400e0..67cbd71 100644
--- a/plat/renesas/rcar/include/rcar_version.h
+++ b/plat/renesas/rcar/include/rcar_version.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,8 +9,8 @@
 
 #include <arch_helpers.h>
 
-#define VERSION_OF_RENESAS		"2.0.4"
-#define	VERSION_OF_RENESAS_MAXLEN	(128)
+#define VERSION_OF_RENESAS		"2.0.6"
+#define VERSION_OF_RENESAS_MAXLEN	128
 
 extern const uint8_t version_of_renesas[VERSION_OF_RENESAS_MAXLEN];
 
diff --git a/plat/renesas/rcar/rcar_common.c b/plat/renesas/rcar/rcar_common.c
index 4ea753f..dec7229 100644
--- a/plat/renesas/rcar/rcar_common.c
+++ b/plat/renesas/rcar/rcar_common.c
@@ -70,8 +70,8 @@
 
 #include <drivers/renesas/rcar/console/console.h>
 
-static console_rcar_t rcar_boot_console;
-static console_rcar_t rcar_runtime_console;
+static console_t rcar_boot_console;
+static console_t rcar_runtime_console;
 
 void rcar_console_boot_init(void)
 {
@@ -81,7 +81,7 @@
 	if (!ret)
 		panic();
 
-	console_set_scope(&rcar_boot_console.console, CONSOLE_FLAG_BOOT);
+	console_set_scope(&rcar_boot_console, CONSOLE_FLAG_BOOT);
 }
 
 void rcar_console_boot_end(void)
@@ -96,7 +96,7 @@
 	if (!ret)
 		panic();
 
-	console_set_scope(&rcar_boot_console.console, CONSOLE_FLAG_RUNTIME);
+	console_set_scope(&rcar_boot_console, CONSOLE_FLAG_RUNTIME);
 }
 
 void rcar_console_runtime_end(void)
diff --git a/plat/rockchip/common/bl31_plat_setup.c b/plat/rockchip/common/bl31_plat_setup.c
index c4a0359..98ef415 100644
--- a/plat/rockchip/common/bl31_plat_setup.c
+++ b/plat/rockchip/common/bl31_plat_setup.c
@@ -57,7 +57,7 @@
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
-	static console_16550_t console;
+	static console_t console;
 
 	params_early_setup(arg1);
 
diff --git a/plat/rockchip/common/drivers/parameter/ddr_parameter.h b/plat/rockchip/common/drivers/parameter/ddr_parameter.h
index 61349c4..25c93a1 100644
--- a/plat/rockchip/common/drivers/parameter/ddr_parameter.h
+++ b/plat/rockchip/common/drivers/parameter/ddr_parameter.h
@@ -35,8 +35,8 @@
 	uint64_t ns_top[DDR_REGION_NR_MAX];
 
 	uint32_t s_nr;
-	uint64_t s_base[DDR_REGION_NR_MAX];
-	uint64_t s_top[DDR_REGION_NR_MAX];
+	uint64_t s_base[DDR_REGION_NR_MAX + 1];
+	uint64_t s_top[DDR_REGION_NR_MAX + 1];
 };
 
 struct param_ddr_usage ddr_region_usage_parse(uint64_t addr, uint64_t max_mb);
diff --git a/plat/rockchip/common/sp_min_plat_setup.c b/plat/rockchip/common/sp_min_plat_setup.c
index 6d15075..0237b16 100644
--- a/plat/rockchip/common/sp_min_plat_setup.c
+++ b/plat/rockchip/common/sp_min_plat_setup.c
@@ -52,7 +52,7 @@
 void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				  u_register_t arg2, u_register_t arg3)
 {
-	static console_16550_t console;
+	static console_t console;
 
 	params_early_setup(arg1);
 
diff --git a/plat/rpi/common/rpi3_common.c b/plat/rpi/common/rpi3_common.c
index ff33694..27281f2 100644
--- a/plat/rpi/common/rpi3_common.c
+++ b/plat/rpi/common/rpi3_common.c
@@ -102,7 +102,7 @@
 /*******************************************************************************
  * Function that sets up the console
  ******************************************************************************/
-static console_16550_t rpi3_console;
+static console_t rpi3_console;
 
 void rpi3_console_init(unsigned int base_clk_rate)
 {
@@ -123,7 +123,7 @@
 		panic();
 	}
 
-	console_set_scope(&rpi3_console.console, console_scope);
+	console_set_scope(&rpi3_console, console_scope);
 }
 
 /*******************************************************************************
diff --git a/plat/socionext/synquacer/include/platform_def.h b/plat/socionext/synquacer/include/platform_def.h
index 7158bfa..b87ac3f 100644
--- a/plat/socionext/synquacer/include/platform_def.h
+++ b/plat/socionext/synquacer/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -80,7 +80,6 @@
 #define DRAMINFO_BASE			0x2E00FFC0
 
 #define PLAT_SQ_MHU_BASE		0x45000000
-#define PLAT_MHUV2_BASE			0xFFFFFFFF /* MHUV2 is not supported */
 
 #define PLAT_SQ_SCP_COM_SHARED_MEM_BASE		0x45400000
 #define SCPI_CMD_GET_DRAMINFO			0x1
diff --git a/plat/socionext/synquacer/sq_bl31_setup.c b/plat/socionext/synquacer/sq_bl31_setup.c
index b864021..9723ef9 100644
--- a/plat/socionext/synquacer/sq_bl31_setup.c
+++ b/plat/socionext/synquacer/sq_bl31_setup.c
@@ -16,7 +16,7 @@
 #include <lib/mmio.h>
 #include <sq_common.h>
 
-static console_pl011_t console;
+static console_t console;
 static entry_point_info_t bl32_image_ep_info;
 static entry_point_info_t bl33_image_ep_info;
 
@@ -69,8 +69,7 @@
 			       PLAT_SQ_BOOT_UART_CLK_IN_HZ,
 			       SQ_CONSOLE_BAUDRATE, &console);
 
-	console_set_scope(&console.console, CONSOLE_FLAG_BOOT |
-			  CONSOLE_FLAG_RUNTIME);
+	console_set_scope(&console, CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
 
 	/* There are no parameters from BL2 if BL31 is a reset vector */
 	assert(arg0 == 0U);
diff --git a/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c b/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c
index 4f58b68..091a6f7 100644
--- a/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c
+++ b/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c
@@ -4,16 +4,25 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <errno.h>
+
 #include <platform_def.h>
 
 #include <common/bl_common.h>
 #include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <plat/common/platform.h>
 
 #include "../uniphier.h"
 
+static unsigned int uniphier_soc = UNIPHIER_SOC_UNKNOWN;
+
 void tsp_early_platform_setup(void)
 {
-	uniphier_console_setup();
+	uniphier_soc = uniphier_get_soc_id();
+	if (uniphier_soc == UNIPHIER_SOC_UNKNOWN)
+		plat_error_handler(-ENOTSUP);
+
+	uniphier_console_setup(uniphier_soc);
 }
 
 void tsp_platform_setup(void)
@@ -22,6 +31,6 @@
 
 void tsp_plat_arch_setup(void)
 {
-	uniphier_mmap_setup();
+	uniphier_mmap_setup(uniphier_soc);
 	enable_mmu_el1(0);
 }
diff --git a/plat/socionext/uniphier/uniphier.h b/plat/socionext/uniphier/uniphier.h
index 729dc5c..ee520ad 100644
--- a/plat/socionext/uniphier/uniphier.h
+++ b/plat/socionext/uniphier/uniphier.h
@@ -25,7 +25,8 @@
 #define UNIPHIER_BOOT_DEVICE_EMMC	0
 #define UNIPHIER_BOOT_DEVICE_NAND	1
 #define UNIPHIER_BOOT_DEVICE_NOR	2
-#define UNIPHIER_BOOT_DEVICE_USB	3
+#define UNIPHIER_BOOT_DEVICE_SD		3
+#define UNIPHIER_BOOT_DEVICE_USB	4
 #define UNIPHIER_BOOT_DEVICE_RSV	0xffffffff
 
 unsigned int uniphier_get_boot_master(unsigned int soc);
@@ -34,11 +35,13 @@
 #define UNIPHIER_BOOT_MASTER_SCP	1
 #define UNIPHIER_BOOT_MASTER_EXT	2
 
-void uniphier_console_setup(void);
+void uniphier_console_setup(unsigned int soc);
 
 struct io_block_dev_spec;
-int uniphier_emmc_init(struct io_block_dev_spec **block_dev_spec);
-int uniphier_nand_init(struct io_block_dev_spec **block_dev_spec);
+int uniphier_emmc_init(unsigned int soc,
+		       struct io_block_dev_spec **block_dev_spec);
+int uniphier_nand_init(unsigned int soc,
+		       struct io_block_dev_spec **block_dev_spec);
 int uniphier_usb_init(unsigned int soc,
 		      struct io_block_dev_spec **block_dev_spec);
 
@@ -54,7 +57,7 @@
 void uniphier_scp_system_off(void);
 void uniphier_scp_system_reset(void);
 
-void uniphier_mmap_setup(void);
+void uniphier_mmap_setup(unsigned int soc);
 
 void uniphier_cci_init(unsigned int soc);
 void uniphier_cci_enable(void);
@@ -66,6 +69,8 @@
 void uniphier_gic_cpuif_disable(void);
 void uniphier_gic_pcpu_init(void);
 
+void uniphier_psci_init(unsigned int soc);
+
 unsigned int uniphier_calc_core_pos(u_register_t mpidr);
 
 #endif /* UNIPHIER_H */
diff --git a/plat/socionext/uniphier/uniphier_bl2_setup.c b/plat/socionext/uniphier/uniphier_bl2_setup.c
index 11d837c..7a7f786 100644
--- a/plat/socionext/uniphier/uniphier_bl2_setup.c
+++ b/plat/socionext/uniphier/uniphier_bl2_setup.c
@@ -25,39 +25,37 @@
 #define UNIPHIER_IMAGE_BUF_SIZE		0x00100000UL
 
 static uintptr_t uniphier_mem_base = UNIPHIER_MEM_BASE;
+static unsigned int uniphier_soc = UNIPHIER_SOC_UNKNOWN;
 static int uniphier_bl2_kick_scp;
 
 void bl2_el3_early_platform_setup(u_register_t x0, u_register_t x1,
 				  u_register_t x2, u_register_t x3)
 {
-	uniphier_console_setup();
+	uniphier_soc = uniphier_get_soc_id();
+	if (uniphier_soc == UNIPHIER_SOC_UNKNOWN)
+		plat_error_handler(-ENOTSUP);
+
+	uniphier_console_setup(uniphier_soc);
 }
 
 void bl2_el3_plat_arch_setup(void)
 {
-	unsigned int soc;
 	int skip_scp = 0;
 	int ret;
 
-	uniphier_mmap_setup();
+	uniphier_mmap_setup(uniphier_soc);
 	enable_mmu_el3(0);
 
 	/* add relocation offset (run-time-address - link-address) */
 	uniphier_mem_base += BL_CODE_BASE - BL2_BASE;
 
-	soc = uniphier_get_soc_id();
-	if (soc == UNIPHIER_SOC_UNKNOWN) {
-		ERROR("unsupported SoC\n");
-		plat_error_handler(-ENOTSUP);
-	}
-
-	ret = uniphier_io_setup(soc, uniphier_mem_base);
+	ret = uniphier_io_setup(uniphier_soc, uniphier_mem_base);
 	if (ret) {
 		ERROR("failed to setup io devices\n");
 		plat_error_handler(ret);
 	}
 
-	switch (uniphier_get_boot_master(soc)) {
+	switch (uniphier_get_boot_master(uniphier_soc)) {
 	case UNIPHIER_BOOT_MASTER_THIS:
 		INFO("Booting from this SoC\n");
 		skip_scp = 1;
diff --git a/plat/socionext/uniphier/uniphier_bl31_setup.c b/plat/socionext/uniphier/uniphier_bl31_setup.c
index 47f2378..f2f0b29 100644
--- a/plat/socionext/uniphier/uniphier_bl31_setup.c
+++ b/plat/socionext/uniphier/uniphier_bl31_setup.c
@@ -21,6 +21,7 @@
 
 static entry_point_info_t bl32_image_ep_info;
 static entry_point_info_t bl33_image_ep_info;
+static unsigned int uniphier_soc = UNIPHIER_SOC_UNKNOWN;
 
 entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
 {
@@ -37,7 +38,11 @@
 
 	bl_params_node_t *bl_params = ((bl_params_t *)from_bl2)->head;
 
-	uniphier_console_setup();
+	uniphier_soc = uniphier_get_soc_id();
+	if (uniphier_soc == UNIPHIER_SOC_UNKNOWN)
+		plat_error_handler(-ENOTSUP);
+
+	uniphier_console_setup(uniphier_soc);
 
 	while (bl_params) {
 		if (bl_params->image_id == BL32_IMAGE_ID)
@@ -53,32 +58,34 @@
 		panic();
 }
 
-#define UNIPHIER_SYS_CNTCTL_BASE	0x60E00000
+static const uintptr_t uniphier_cntctl_base[] = {
+	[UNIPHIER_SOC_LD11] = 0x60e00000,
+	[UNIPHIER_SOC_LD20] = 0x60e00000,
+	[UNIPHIER_SOC_PXS3] = 0x60e00000,
+};
 
 void bl31_platform_setup(void)
 {
-	unsigned int soc;
+	uintptr_t cntctl_base;
 
-	soc = uniphier_get_soc_id();
-	if (soc == UNIPHIER_SOC_UNKNOWN) {
-		ERROR("unsupported SoC\n");
-		plat_error_handler(-ENOTSUP);
-	}
-
-	uniphier_cci_init(soc);
+	uniphier_cci_init(uniphier_soc);
 	uniphier_cci_enable();
 
 	/* Initialize the GIC driver, cpu and distributor interfaces */
-	uniphier_gic_driver_init(soc);
+	uniphier_gic_driver_init(uniphier_soc);
 	uniphier_gic_init();
 
+	assert(uniphier_soc < ARRAY_SIZE(uniphier_cntctl_base));
+	cntctl_base = uniphier_cntctl_base[uniphier_soc];
+
 	/* Enable and initialize the System level generic timer */
-	mmio_write_32(UNIPHIER_SYS_CNTCTL_BASE + CNTCR_OFF,
-		      CNTCR_FCREQ(0U) | CNTCR_EN);
+	mmio_write_32(cntctl_base + CNTCR_OFF, CNTCR_FCREQ(0U) | CNTCR_EN);
+
+	uniphier_psci_init(uniphier_soc);
 }
 
 void bl31_plat_arch_setup(void)
 {
-	uniphier_mmap_setup();
+	uniphier_mmap_setup(uniphier_soc);
 	enable_mmu_el3(0);
 }
diff --git a/plat/socionext/uniphier/uniphier_boot_device.c b/plat/socionext/uniphier/uniphier_boot_device.c
index 462c085..36a9908 100644
--- a/plat/socionext/uniphier/uniphier_boot_device.c
+++ b/plat/socionext/uniphier/uniphier_boot_device.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 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,22 +13,29 @@
 
 #include "uniphier.h"
 
-#define UNIPHIER_PINMON0		0x5f900100
-#define UNIPHIER_PINMON2		0x5f900108
+#define UNIPHIER_PINMON0		0x0
+#define UNIPHIER_PINMON2		0x8
 
-static int uniphier_ld11_is_usb_boot(uint32_t pinmon)
+static const uintptr_t uniphier_pinmon_base[] = {
+	[UNIPHIER_SOC_LD11] = 0x5f900100,
+	[UNIPHIER_SOC_LD20] = 0x5f900100,
+	[UNIPHIER_SOC_PXS3] = 0x5f900100,
+};
+
+static bool uniphier_ld11_is_usb_boot(uint32_t pinmon)
 {
 	return !!(~pinmon & 0x00000080);
 }
 
-static int uniphier_ld20_is_usb_boot(uint32_t pinmon)
+static bool uniphier_ld20_is_usb_boot(uint32_t pinmon)
 {
 	return !!(~pinmon & 0x00000780);
 }
 
-static int uniphier_pxs3_is_usb_boot(uint32_t pinmon)
+static bool uniphier_pxs3_is_usb_boot(uint32_t pinmon)
 {
-	uint32_t pinmon2 = mmio_read_32(UNIPHIER_PINMON2);
+	uintptr_t pinmon_base = uniphier_pinmon_base[UNIPHIER_SOC_PXS3];
+	uint32_t pinmon2 = mmio_read_32(pinmon_base + UNIPHIER_PINMON2);
 
 	return !!(pinmon2 & BIT(31));
 }
@@ -106,20 +113,25 @@
 }
 
 struct uniphier_boot_device_info {
-	int (*is_usb_boot)(uint32_t pinmon);
+	bool have_boot_swap;
+	bool (*is_sd_boot)(uint32_t pinmon);
+	bool (*is_usb_boot)(uint32_t pinmon);
 	unsigned int (*get_boot_device)(uint32_t pinmon);
 };
 
 static const struct uniphier_boot_device_info uniphier_boot_device_info[] = {
 	[UNIPHIER_SOC_LD11] = {
+		.have_boot_swap = true,
 		.is_usb_boot = uniphier_ld11_is_usb_boot,
 		.get_boot_device = uniphier_ld11_get_boot_device,
 	},
 	[UNIPHIER_SOC_LD20] = {
+		.have_boot_swap = true,
 		.is_usb_boot = uniphier_ld20_is_usb_boot,
 		.get_boot_device = uniphier_ld11_get_boot_device,
 	},
 	[UNIPHIER_SOC_PXS3] = {
+		.have_boot_swap = true,
 		.is_usb_boot = uniphier_pxs3_is_usb_boot,
 		.get_boot_device = uniphier_pxs3_get_boot_device,
 	},
@@ -128,17 +140,24 @@
 unsigned int uniphier_get_boot_device(unsigned int soc)
 {
 	const struct uniphier_boot_device_info *info;
+	uintptr_t pinmon_base;
 	uint32_t pinmon;
 
 	assert(soc < ARRAY_SIZE(uniphier_boot_device_info));
 	info = &uniphier_boot_device_info[soc];
 
-	pinmon = mmio_read_32(UNIPHIER_PINMON0);
+	assert(soc < ARRAY_SIZE(uniphier_boot_device_info));
+	pinmon_base = uniphier_pinmon_base[soc];
+
+	pinmon = mmio_read_32(pinmon_base + UNIPHIER_PINMON0);
 
-	if (!(pinmon & BIT(29)))
+	if (info->have_boot_swap && !(pinmon & BIT(29)))
 		return UNIPHIER_BOOT_DEVICE_NOR;
 
-	if (info->is_usb_boot(pinmon))
+	if (info->is_sd_boot && info->is_sd_boot(pinmon))
+		return UNIPHIER_BOOT_DEVICE_SD;
+
+	if (info->is_usb_boot && info->is_usb_boot(pinmon))
 		return UNIPHIER_BOOT_DEVICE_USB;
 
 	return info->get_boot_device(pinmon);
@@ -155,7 +174,12 @@
 	assert(soc < ARRAY_SIZE(uniphier_have_onchip_scp));
 
 	if (uniphier_have_onchip_scp[soc]) {
-		if (mmio_read_32(UNIPHIER_PINMON0) & BIT(27))
+		uintptr_t pinmon_base;
+
+		assert(soc < ARRAY_SIZE(uniphier_boot_device_info));
+		pinmon_base = uniphier_pinmon_base[soc];
+
+		if (mmio_read_32(pinmon_base + UNIPHIER_PINMON0) & BIT(27))
 			return UNIPHIER_BOOT_MASTER_THIS;
 		else
 			return UNIPHIER_BOOT_MASTER_SCP;
diff --git a/plat/socionext/uniphier/uniphier_console.S b/plat/socionext/uniphier/uniphier_console.S
index 1113c6e..f3dde0c 100644
--- a/plat/socionext/uniphier/uniphier_console.S
+++ b/plat/socionext/uniphier/uniphier_console.S
@@ -17,7 +17,7 @@
  */
 	.globl	uniphier_console_putc
 func uniphier_console_putc
-	ldr	x1, [x1, #CONSOLE_T_DRVDATA]
+	ldr	x1, [x1, #CONSOLE_T_BASE]
 
 	/* Wait until the transmitter FIFO gets empty */
 0:	ldr	w2, [x1, #UNIPHIER_UART_LSR]
@@ -36,7 +36,7 @@
  */
 	.globl	uniphier_console_getc
 func uniphier_console_getc
-	ldr	x0, [x0, #CONSOLE_T_DRVDATA]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 
 	ldr	w1, [x0, #UNIPHIER_UART_LSR]
 	tbz	w1, #UNIPHIER_UART_LSR_DR_BIT, 0f
@@ -55,7 +55,7 @@
  */
 	.global uniphier_console_flush
 func uniphier_console_flush
-	ldr	x0, [x0, #CONSOLE_T_DRVDATA]
+	ldr	x0, [x0, #CONSOLE_T_BASE]
 
 	/* wait until the transmitter gets empty */
 0:	ldr	w1, [x0, #UNIPHIER_UART_LSR]
diff --git a/plat/socionext/uniphier/uniphier_console_setup.c b/plat/socionext/uniphier/uniphier_console_setup.c
index 64ee797..e2ae8bf 100644
--- a/plat/socionext/uniphier/uniphier_console_setup.c
+++ b/plat/socionext/uniphier/uniphier_console_setup.c
@@ -1,9 +1,11 @@
 /*
- * Copyright (c) 2019, Socionext Inc. All rights reserved.
+ * Copyright (c) 2019-2020, Socionext Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <assert.h>
+
 #include <drivers/console.h>
 #include <errno.h>
 #include <lib/mmio.h>
@@ -12,44 +14,46 @@
 #include "uniphier.h"
 #include "uniphier_console.h"
 
-#define UNIPHIER_UART_BASE	0x54006800
-#define UNIPHIER_UART_END	0x54006c00
 #define UNIPHIER_UART_OFFSET	0x100
-
-struct uniphier_console {
-	struct console console;
-	uintptr_t base;
-};
+#define UNIPHIER_UART_NR_PORTS	4
 
 /* These callbacks are implemented in assembly to use crash_console_helpers.S */
 int uniphier_console_putc(int character, struct console *console);
 int uniphier_console_getc(struct console *console);
 int uniphier_console_flush(struct console *console);
 
-static struct uniphier_console uniphier_console = {
-	.console = {
-		.flags = CONSOLE_FLAG_BOOT |
+static console_t uniphier_console = {
+	.flags = CONSOLE_FLAG_BOOT |
 #if DEBUG
-			 CONSOLE_FLAG_RUNTIME |
+		 CONSOLE_FLAG_RUNTIME |
 #endif
-			 CONSOLE_FLAG_CRASH |
-			 CONSOLE_FLAG_TRANSLATE_CRLF,
-		.putc = uniphier_console_putc,
-		.getc = uniphier_console_getc,
-		.flush = uniphier_console_flush,
-	},
+		 CONSOLE_FLAG_CRASH |
+		 CONSOLE_FLAG_TRANSLATE_CRLF,
+	.putc = uniphier_console_putc,
+	.getc = uniphier_console_getc,
+	.flush = uniphier_console_flush,
 };
 
+static const uintptr_t uniphier_uart_base[] = {
+	[UNIPHIER_SOC_LD11] = 0x54006800,
+	[UNIPHIER_SOC_LD20] = 0x54006800,
+	[UNIPHIER_SOC_PXS3] = 0x54006800,
+};
+
 /*
  * There are 4 UART ports available on this platform. By default, we want to
  * use the same one as used in the previous firmware stage.
  */
-static uintptr_t uniphier_console_get_base(void)
+static uintptr_t uniphier_console_get_base(unsigned int soc)
 {
-	uintptr_t base = UNIPHIER_UART_BASE;
+	uintptr_t base, end;
 	uint32_t div;
 
-	while (base < UNIPHIER_UART_END) {
+	assert(soc < ARRAY_SIZE(uniphier_uart_base));
+	base = uniphier_uart_base[soc];
+	end = base + UNIPHIER_UART_OFFSET * UNIPHIER_UART_NR_PORTS;
+
+	while (base < end) {
 		div = mmio_read_32(base + UNIPHIER_UART_DLR);
 		if (div)
 			return base;
@@ -66,16 +70,16 @@
 		      UNIPHIER_UART_LCR_WLEN8 << 8);
 }
 
-void uniphier_console_setup(void)
+void uniphier_console_setup(unsigned int soc)
 {
 	uintptr_t base;
 
-	base = uniphier_console_get_base();
+	base = uniphier_console_get_base(soc);
 	if (!base)
 		plat_error_handler(-EINVAL);
 
 	uniphier_console.base = base;
-	console_register(&uniphier_console.console);
+	console_register(&uniphier_console);
 
 	/*
 	 * The hardware might be still printing characters queued up in the
diff --git a/plat/socionext/uniphier/uniphier_emmc.c b/plat/socionext/uniphier/uniphier_emmc.c
index d666ba7..b3d23cb 100644
--- a/plat/socionext/uniphier/uniphier_emmc.c
+++ b/plat/socionext/uniphier/uniphier_emmc.c
@@ -87,7 +87,12 @@
 	unsigned int is_data;
 };
 
-static int uniphier_emmc_block_addressing;
+struct uniphier_emmc_host {
+	uintptr_t base;
+	bool is_block_addressing;
+};
+
+static struct uniphier_emmc_host uniphier_emmc_host;
 
 static int uniphier_emmc_send_cmd(uintptr_t host_base,
 				  struct uniphier_mmc_cmd *cmd)
@@ -157,7 +162,8 @@
 	return uniphier_emmc_send_cmd(host_base, &cmd);
 }
 
-static int uniphier_emmc_is_over_2gb(uintptr_t host_base)
+static int uniphier_emmc_check_device_size(uintptr_t host_base,
+					   bool *is_block_addressing)
 {
 	struct uniphier_mmc_cmd cmd = {0};
 	uint32_t csd40, csd72;	/* CSD[71:40], CSD[103:72] */
@@ -174,7 +180,10 @@
 	csd40 = mmio_read_32(host_base + SDHCI_RESPONSE + 4);
 	csd72 = mmio_read_32(host_base + SDHCI_RESPONSE + 8);
 
-	return !(~csd40 & 0xffc00380) && !(~csd72 & 0x3);
+	/* C_SIZE == 0xfff && C_SIZE_MULT == 0x7 ? */
+	*is_block_addressing = !(~csd40 & 0xffc00380) && !(~csd72 & 0x3);
+
+	return 0;
 }
 
 static int uniphier_emmc_load_image(uintptr_t host_base,
@@ -210,15 +219,15 @@
 
 static size_t uniphier_emmc_read(int lba, uintptr_t buf, size_t size)
 {
-	uintptr_t host_base = 0x5a000200;
 	int ret;
 
 	inv_dcache_range(buf, size);
 
-	if (!uniphier_emmc_block_addressing)
+	if (!uniphier_emmc_host.is_block_addressing)
 		lba *= 512;
 
-	ret = uniphier_emmc_load_image(host_base, lba, buf, size / 512);
+	ret = uniphier_emmc_load_image(uniphier_emmc_host.base,
+				       lba, buf, size / 512);
 
 	inv_dcache_range(buf, size);
 
@@ -232,10 +241,10 @@
 	.block_size = 512,
 };
 
-static int uniphier_emmc_hw_init(void)
+static int uniphier_emmc_hw_init(struct uniphier_emmc_host *host)
 {
-	uintptr_t host_base = 0x5a000200;
 	struct uniphier_mmc_cmd cmd = {0};
+	uintptr_t host_base = uniphier_emmc_host.base;
 	int ret;
 
 	/*
@@ -253,12 +262,11 @@
 	while (mmio_read_8(host_base + SDHCI_SOFTWARE_RESET))
 		;
 
-	ret = uniphier_emmc_is_over_2gb(host_base);
-	if (ret < 0)
+	ret = uniphier_emmc_check_device_size(host_base,
+				&uniphier_emmc_host.is_block_addressing);
+	if (ret)
 		return ret;
 
-	uniphier_emmc_block_addressing = ret;
-
 	cmd.cmdarg = UNIPHIER_EMMC_RCA << 16;
 
 	/* select card again */
@@ -274,11 +282,23 @@
 	return 0;
 }
 
+static const uintptr_t uniphier_emmc_base[] = {
+	[UNIPHIER_SOC_LD11] = 0x5a000200,
+	[UNIPHIER_SOC_LD20] = 0x5a000200,
+	[UNIPHIER_SOC_PXS3] = 0x5a000200,
+};
+
-int uniphier_emmc_init(struct io_block_dev_spec **block_dev_spec)
+int uniphier_emmc_init(unsigned int soc,
+		       struct io_block_dev_spec **block_dev_spec)
 {
 	int ret;
 
-	ret = uniphier_emmc_hw_init();
+	assert(soc < ARRAY_SIZE(uniphier_emmc_base));
+	uniphier_emmc_host.base = uniphier_emmc_base[soc];
+	if (uniphier_emmc_host.base == 0UL)
+		return -ENOTSUP;
+
+	ret = uniphier_emmc_hw_init(&uniphier_emmc_host);
 	if (ret)
 		return ret;
 
diff --git a/plat/socionext/uniphier/uniphier_io_storage.c b/plat/socionext/uniphier/uniphier_io_storage.c
index 89c8718..e89c835 100644
--- a/plat/socionext/uniphier/uniphier_io_storage.c
+++ b/plat/socionext/uniphier/uniphier_io_storage.c
@@ -23,7 +23,6 @@
 #define UNIPHIER_ROM_REGION_BASE	0x00000000ULL
 #define UNIPHIER_ROM_REGION_SIZE	0x10000000ULL
 
-#define UNIPHIER_OCM_REGION_BASE	0x30000000ULL
 #define UNIPHIER_OCM_REGION_SIZE	0x00040000ULL
 
 #define UNIPHIER_BLOCK_BUF_OFFSET	0x04200000UL
@@ -249,24 +248,24 @@
 	return io_dev_open(uniphier_fip_dev_con, 0, &uniphier_fip_dev_handle);
 }
 
-static int uniphier_io_emmc_setup(unsigned int soc_id, size_t buffer_offset)
+static int uniphier_io_emmc_setup(unsigned int soc, size_t buffer_offset)
 {
 	struct io_block_dev_spec *block_dev_spec;
 	int ret;
 
-	ret = uniphier_emmc_init(&block_dev_spec);
+	ret = uniphier_emmc_init(soc, &block_dev_spec);
 	if (ret)
 		return ret;
 
 	return uniphier_io_block_setup(0x20000, block_dev_spec, buffer_offset);
 }
 
-static int uniphier_io_nand_setup(unsigned int soc_id, size_t buffer_offset)
+static int uniphier_io_nand_setup(unsigned int soc, size_t buffer_offset)
 {
 	struct io_block_dev_spec *block_dev_spec;
 	int ret;
 
-	ret = uniphier_nand_init(&block_dev_spec);
+	ret = uniphier_nand_init(soc, &block_dev_spec);
 	if (ret)
 		return ret;
 
@@ -278,12 +277,20 @@
 	return uniphier_io_memmap_setup(0x70000);
 }
 
-static int uniphier_io_usb_setup(unsigned int soc_id, size_t buffer_offset)
+static const uintptr_t uniphier_ocm_base[] = {
+	[UNIPHIER_SOC_LD11] = 0x30000000,
+	[UNIPHIER_SOC_LD20] = 0x30000000,
+	[UNIPHIER_SOC_PXS3] = 0x30000000,
+};
+
+static int uniphier_io_rom_api_setup(unsigned int soc)
 {
-	struct io_block_dev_spec *block_dev_spec;
+	uintptr_t ocm_base;
 	int ret;
 
-	/* use ROM API for loading images from USB storage */
+	assert(soc < ARRAY_SIZE(uniphier_ocm_base));
+	ocm_base = uniphier_ocm_base[soc];
+
 	ret = mmap_add_dynamic_region(UNIPHIER_ROM_REGION_BASE,
 				      UNIPHIER_ROM_REGION_BASE,
 				      UNIPHIER_ROM_REGION_SIZE,
@@ -296,14 +303,26 @@
 	 * load functions provided by the ROM use this memory region as a work
 	 * area, but do not cater to cache coherency.
 	 */
-	ret = mmap_add_dynamic_region(UNIPHIER_OCM_REGION_BASE,
-				      UNIPHIER_OCM_REGION_BASE,
+	ret = mmap_add_dynamic_region(ocm_base, ocm_base,
 				      UNIPHIER_OCM_REGION_SIZE,
 				      MT_DEVICE | MT_RW | MT_SECURE);
 	if (ret)
 		return ret;
 
+	return 0;
+}
+
+static int uniphier_io_usb_setup(unsigned int soc, size_t buffer_offset)
+{
+	struct io_block_dev_spec *block_dev_spec;
+	int ret;
+
+	/* use ROM API for loading images from USB storage */
+	ret = uniphier_io_rom_api_setup(soc);
+	if (ret)
+		return ret;
+
-	ret = uniphier_usb_init(soc_id, &block_dev_spec);
+	ret = uniphier_usb_init(soc, &block_dev_spec);
 	if (ret)
 		return ret;
 
diff --git a/plat/socionext/uniphier/uniphier_nand.c b/plat/socionext/uniphier/uniphier_nand.c
index 3925177..71cb96c 100644
--- a/plat/socionext/uniphier/uniphier_nand.c
+++ b/plat/socionext/uniphier/uniphier_nand.c
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <assert.h>
 #include <stdint.h>
 
 #include <platform_def.h>
@@ -237,8 +238,7 @@
 	for (i = 0; i < ARRAY_SIZE(nand->bbt); i++)
 		nand->bbt[i] = UNIPHIER_NAND_BBT_UNKNOWN;
 
-	nand->host_base = 0x68000000;
-	nand->reg_base = 0x68100000;
+	nand->reg_base = nand->host_base + 0x100000;
 
 	nand->pages_per_block =
 			mmio_read_32(nand->reg_base + DENALI_PAGES_PER_BLOCK);
@@ -255,10 +255,22 @@
 	return 0;
 }
 
-int uniphier_nand_init(struct io_block_dev_spec **block_dev_spec)
+static const uintptr_t uniphier_nand_base[] = {
+	[UNIPHIER_SOC_LD11] = 0x68000000,
+	[UNIPHIER_SOC_LD20] = 0x68000000,
+	[UNIPHIER_SOC_PXS3] = 0x68000000,
+};
+
+int uniphier_nand_init(unsigned int soc,
+		       struct io_block_dev_spec **block_dev_spec)
 {
 	int ret;
 
+	assert(soc < ARRAY_SIZE(uniphier_nand_base));
+	uniphier_nand.host_base = uniphier_nand_base[soc];
+	if (!uniphier_nand.host_base)
+		return -ENOTSUP;
+
 	ret = uniphier_nand_hw_init(&uniphier_nand);
 	if (ret)
 		return ret;
diff --git a/plat/socionext/uniphier/uniphier_psci.c b/plat/socionext/uniphier/uniphier_psci.c
index 2acc874..a371705 100644
--- a/plat/socionext/uniphier/uniphier_psci.c
+++ b/plat/socionext/uniphier/uniphier_psci.c
@@ -1,9 +1,11 @@
 /*
- * 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
  */
 
+#include <assert.h>
+
 #include <arch_helpers.h>
 #include <common/debug.h>
 #include <errno.h>
@@ -12,15 +14,18 @@
 
 #include "uniphier.h"
 
-#define UNIPHIER_ROM_RSV0		0x59801200
+#define UNIPHIER_ROM_RSV0		0x0
 
-#define UNIPHIER_SLFRSTSEL		0x61843010
+#define UNIPHIER_SLFRSTSEL		0x10
 #define   UNIPHIER_SLFRSTSEL_MASK		GENMASK(1, 0)
-#define UNIPHIER_SLFRSTCTL		0x61843014
+#define UNIPHIER_SLFRSTCTL		0x14
 #define   UNIPHIER_SLFRSTCTL_RST		BIT(0)
 
 #define MPIDR_AFFINITY_INVALID		((u_register_t)-1)
 
+static uintptr_t uniphier_rom_rsv_base;
+static uintptr_t uniphier_slfrst_base;
+
 uintptr_t uniphier_sec_entrypoint;
 
 void uniphier_warmboot_entrypoint(void);
@@ -34,7 +39,7 @@
 	flush_dcache_range((uint64_t)&uniphier_holding_pen_release,
 			   sizeof(uniphier_holding_pen_release));
 
-	mmio_write_64(UNIPHIER_ROM_RSV0,
+	mmio_write_64(uniphier_rom_rsv_base + UNIPHIER_ROM_RSV0,
 		      (uint64_t)&uniphier_warmboot_entrypoint);
 	sev();
 
@@ -71,8 +76,10 @@
 
 static void uniphier_self_system_reset(void)
 {
-	mmio_clrbits_32(UNIPHIER_SLFRSTSEL, UNIPHIER_SLFRSTSEL_MASK);
-	mmio_setbits_32(UNIPHIER_SLFRSTCTL, UNIPHIER_SLFRSTCTL_RST);
+	mmio_clrbits_32(uniphier_slfrst_base + UNIPHIER_SLFRSTSEL,
+			UNIPHIER_SLFRSTSEL_MASK);
+	mmio_setbits_32(uniphier_slfrst_base + UNIPHIER_SLFRSTCTL,
+			UNIPHIER_SLFRSTCTL_RST);
 }
 
 static void __dead2 uniphier_psci_system_off(void)
@@ -114,13 +121,40 @@
 int plat_setup_psci_ops(uintptr_t sec_entrypoint,
 			const struct plat_psci_ops **psci_ops)
 {
-	unsigned int soc;
+	uniphier_sec_entrypoint = sec_entrypoint;
+	flush_dcache_range((uint64_t)&uniphier_sec_entrypoint,
+			   sizeof(uniphier_sec_entrypoint));
 
-	soc = uniphier_get_soc_id();
-	if (soc == UNIPHIER_SOC_UNKNOWN) {
-		ERROR("unsupported SoC\n");
-		return -ENOTSUP;
-	}
+	*psci_ops = &uniphier_psci_ops;
+
+	return 0;
+}
+
+struct uniphier_psci_ctrl_base {
+	uintptr_t rom_rsv_base;
+	uintptr_t slfrst_base;
+};
+
+static const struct uniphier_psci_ctrl_base uniphier_psci_ctrl_base[] = {
+	[UNIPHIER_SOC_LD11] = {
+		.rom_rsv_base = 0x59801200,
+		.slfrst_base = 0x61843000,
+	},
+	[UNIPHIER_SOC_LD20] = {
+		.rom_rsv_base = 0x59801200,
+		.slfrst_base = 0x61843000,
+	},
+	[UNIPHIER_SOC_PXS3] = {
+		.rom_rsv_base = 0x59801200,
+		.slfrst_base = 0x61843000,
+	},
+};
+
+void uniphier_psci_init(unsigned int soc)
+{
+	assert(soc < ARRAY_SIZE(uniphier_psci_ctrl_base));
+	uniphier_rom_rsv_base = uniphier_psci_ctrl_base[soc].rom_rsv_base;
+	uniphier_slfrst_base = uniphier_psci_ctrl_base[soc].slfrst_base;
 
 	if (uniphier_get_boot_master(soc) == UNIPHIER_BOOT_MASTER_SCP) {
 		uniphier_psci_scp_mode = uniphier_scp_is_running();
@@ -130,12 +164,4 @@
 		if (uniphier_psci_scp_mode)
 			uniphier_scp_open_com();
 	}
-
-	uniphier_sec_entrypoint = sec_entrypoint;
-	flush_dcache_range((uint64_t)&uniphier_sec_entrypoint,
-			   sizeof(uniphier_sec_entrypoint));
-
-	*psci_ops = &uniphier_psci_ops;
-
-	return 0;
 }
diff --git a/plat/socionext/uniphier/uniphier_xlat_setup.c b/plat/socionext/uniphier/uniphier_xlat_setup.c
index 18d2f9e..66c7834 100644
--- a/plat/socionext/uniphier/uniphier_xlat_setup.c
+++ b/plat/socionext/uniphier/uniphier_xlat_setup.c
@@ -4,15 +4,36 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <assert.h>
+
 #include <platform_def.h>
 
 #include <common/debug.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
 
+#include "uniphier.h"
+
-#define UNIPHIER_REG_REGION_BASE	0x50000000ULL
-#define UNIPHIER_REG_REGION_SIZE	0x20000000ULL
+struct uniphier_reg_region {
+	uintptr_t base;
+	size_t size;
+};
 
-void uniphier_mmap_setup(void)
+static const struct uniphier_reg_region uniphier_reg_region[] = {
+	[UNIPHIER_SOC_LD11] = {
+		.base = 0x50000000UL,
+		.size = 0x20000000UL,
+	},
+	[UNIPHIER_SOC_LD20] = {
+		.base = 0x50000000UL,
+		.size = 0x20000000UL,
+	},
+	[UNIPHIER_SOC_PXS3] = {
+		.base = 0x50000000UL,
+		.size = 0x20000000UL,
+	},
+};
+
+void uniphier_mmap_setup(unsigned int soc)
 {
 	VERBOSE("Trusted RAM seen by this BL image: %p - %p\n",
 		(void *)BL_CODE_BASE, (void *)BL_END);
@@ -35,8 +56,10 @@
 			MT_DEVICE | MT_RW | MT_SECURE);
 
 	/* register region */
-	mmap_add_region(UNIPHIER_REG_REGION_BASE, UNIPHIER_REG_REGION_BASE,
-			UNIPHIER_REG_REGION_SIZE,
+	assert(soc < ARRAY_SIZE(uniphier_reg_region));
+	mmap_add_region(uniphier_reg_region[soc].base,
+			uniphier_reg_region[soc].base,
+			uniphier_reg_region[soc].size,
 			MT_DEVICE | MT_RW | MT_SECURE);
 
 	init_xlat_tables();
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index d9e29b4..024dbe0 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -31,7 +31,7 @@
 #include <stm32mp1_context.h>
 #include <stm32mp1_dbgmcu.h>
 
-static struct console_stm32 console;
+static console_t console;
 static struct stm32mp_auth_ops stm32mp1_auth_ops;
 
 static void print_reset_reason(void)
@@ -273,7 +273,7 @@
 		panic();
 	}
 
-	console_set_scope(&console.console, CONSOLE_FLAG_BOOT |
+	console_set_scope(&console, CONSOLE_FLAG_BOOT |
 			  CONSOLE_FLAG_CRASH | CONSOLE_FLAG_TRANSLATE_CRLF);
 
 	stm32mp_print_cpuinfo();
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
index e10dfbf..4e74c27 100644
--- a/plat/st/stm32mp1/sp_min/sp_min_setup.c
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
@@ -35,7 +35,7 @@
  ******************************************************************************/
 static entry_point_info_t bl33_image_ep_info;
 
-static struct console_stm32 console;
+static console_t console;
 
 /*******************************************************************************
  * Interrupt handler for FIQ (secure IRQ)
@@ -142,7 +142,7 @@
 #ifdef DEBUG
 		console_flags |= CONSOLE_FLAG_RUNTIME;
 #endif
-		console_set_scope(&console.console, console_flags);
+		console_set_scope(&console, console_flags);
 	}
 }
 
diff --git a/plat/ti/k3/common/k3_console.c b/plat/ti/k3/common/k3_console.c
index ba0ddac..8c44c17 100644
--- a/plat/ti/k3/common/k3_console.c
+++ b/plat/ti/k3/common/k3_console.c
@@ -13,7 +13,7 @@
 
 void bl31_console_setup(void)
 {
-	static console_16550_t console;
+	static console_t console;
 
 	/* Initialize the console to provide early debug support */
 	console_16550_register(K3_USART_BASE, K3_USART_CLK_SPEED,
diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c
index a5cf05e..03b7fbb 100644
--- a/plat/xilinx/versal/bl31_versal_setup.c
+++ b/plat/xilinx/versal/bl31_versal_setup.c
@@ -22,7 +22,7 @@
 
 static entry_point_info_t bl32_image_ep_info;
 static entry_point_info_t bl33_image_ep_info;
-static console_pl011_t versal_runtime_console;
+static console_t versal_runtime_console;
 
 /*
  * Return a pointer to the 'entry_point_info' structure of the next image for
@@ -71,7 +71,7 @@
 	if (rc == 0)
 		panic();
 
-	console_set_scope(&versal_runtime_console.console, CONSOLE_FLAG_BOOT |
+	console_set_scope(&versal_runtime_console, CONSOLE_FLAG_BOOT |
 			  CONSOLE_FLAG_RUNTIME);
 
 	/* Initialize the platform config for future decision making */
diff --git a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
index 6e0e811..b6d8770 100644
--- a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
+++ b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
@@ -62,12 +62,12 @@
 {
 	uint64_t atf_handoff_addr;
 	/* Register the console to provide early debug support */
-	static console_cdns_t bl31_boot_console;
+	static console_t bl31_boot_console;
 	(void)console_cdns_register(ZYNQMP_UART_BASE,
 				       zynqmp_get_uart_clk(),
 				       ZYNQMP_UART_BAUDRATE,
 				       &bl31_boot_console);
-	console_set_scope(&bl31_boot_console.console,
+	console_set_scope(&bl31_boot_console,
 			  CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_BOOT);
 
 	/* Initialize the platform config for future decision making */
diff --git a/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
index 7f0ac74..5e770f7 100644
--- a/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
+++ b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
@@ -21,12 +21,12 @@
 	 * Register a different console than already in use to display
 	 * messages from TSP
 	 */
-	static console_cdns_t tsp_boot_console;
+	static console_t tsp_boot_console;
 	(void)console_cdns_register(ZYNQMP_UART_BASE,
 				       zynqmp_get_uart_clk(),
 				       ZYNQMP_UART_BAUDRATE,
 				       &tsp_boot_console);
-	console_set_scope(&tsp_boot_console.console,
+	console_set_scope(&tsp_boot_console,
 			  CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_BOOT);
 
 	/* Initialize the platform config for future decision making */
diff --git a/services/arm_arch_svc/arm_arch_svc_setup.c b/services/arm_arch_svc/arm_arch_svc_setup.c
index 1fc7827..6dac56e 100644
--- a/services/arm_arch_svc/arm_arch_svc_setup.c
+++ b/services/arm_arch_svc/arm_arch_svc_setup.c
@@ -66,7 +66,7 @@
 		return 0;
 #else
 		/* Either the CPUs are unaffected or permanently mitigated */
-		return SMCCC_ARCH_NOT_REQUIRED;
+		return SMC_ARCH_CALL_NOT_REQUIRED;
 #endif
 	}
 #endif
diff --git a/services/spd/trusty/generic-arm64-smcall.c b/services/spd/trusty/generic-arm64-smcall.c
index dfc3e71..5c3a628 100644
--- a/services/spd/trusty/generic-arm64-smcall.c
+++ b/services/spd/trusty/generic-arm64-smcall.c
@@ -12,6 +12,22 @@
 
 #include "generic-arm64-smcall.h"
 
+#ifndef PLAT_ARM_GICD_BASE
+#ifdef GICD_BASE
+#define PLAT_ARM_GICD_BASE GICD_BASE
+#define PLAT_ARM_GICC_BASE GICC_BASE
+#ifdef GICR_BASE
+#define PLAT_ARM_GICR_BASE GICR_BASE
+#endif
+#else
+#error PLAT_ARM_GICD_BASE or GICD_BASE must be defined
+#endif
+#endif
+
+#ifndef PLAT_ARM_GICR_BASE
+#define PLAT_ARM_GICR_BASE SMC_UNK
+#endif
+
 int trusty_disable_serial_debug;
 
 struct dputc_state {
@@ -48,12 +64,15 @@
 static uint64_t trusty_get_reg_base(uint32_t reg)
 {
 	switch (reg) {
-	case 0:
+	case SMC_GET_GIC_BASE_GICD:
 		return PLAT_ARM_GICD_BASE;
 
-	case 1:
+	case SMC_GET_GIC_BASE_GICC:
 		return PLAT_ARM_GICC_BASE;
 
+	case SMC_GET_GIC_BASE_GICR:
+		return PLAT_ARM_GICR_BASE;
+
 	default:
 		NOTICE("%s(0x%x) unknown reg\n", __func__, reg);
 		return SMC_UNK;
diff --git a/services/spd/trusty/generic-arm64-smcall.h b/services/spd/trusty/generic-arm64-smcall.h
index 06efc72..ac03469 100644
--- a/services/spd/trusty/generic-arm64-smcall.h
+++ b/services/spd/trusty/generic-arm64-smcall.h
@@ -23,5 +23,6 @@
  */
 #define SMC_GET_GIC_BASE_GICD	0
 #define SMC_GET_GIC_BASE_GICC	1
+#define SMC_GET_GIC_BASE_GICR	2
 #define SMC_FC_GET_REG_BASE	SMC_FASTCALL_NR(SMC_ENTITY_PLATFORM_MONITOR, 0x1)
 #define SMC_FC64_GET_REG_BASE	SMC_FASTCALL64_NR(SMC_ENTITY_PLATFORM_MONITOR, 0x1)
diff --git a/services/spd/trusty/trusty.c b/services/spd/trusty/trusty.c
index d6c092c..092ffa8 100644
--- a/services/spd/trusty/trusty.c
+++ b/services/spd/trusty/trusty.c
@@ -390,6 +390,10 @@
 
 void plat_trusty_set_boot_args(aapcs64_params_t *args);
 
+#if !defined(TSP_SEC_MEM_SIZE) && defined(BL32_MEM_SIZE)
+#define TSP_SEC_MEM_SIZE BL32_MEM_SIZE
+#endif
+
 #ifdef TSP_SEC_MEM_SIZE
 #pragma weak plat_trusty_set_boot_args
 void plat_trusty_set_boot_args(aapcs64_params_t *args)
diff --git a/services/spd/tspd/tspd_main.c b/services/spd/tspd/tspd_main.c
index f206724..b0cbf62 100644
--- a/services/spd/tspd/tspd_main.c
+++ b/services/spd/tspd/tspd_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -126,7 +126,7 @@
 	 * interrupt handling.
 	 */
 	if (get_yield_smc_active_flag(tsp_ctx->state)) {
-		tsp_ctx->saved_spsr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx,
+		tsp_ctx->saved_spsr_el3 = (uint32_t)SMC_GET_EL3(&tsp_ctx->cpu_ctx,
 						      CTX_SPSR_EL3);
 		tsp_ctx->saved_elr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx,
 						     CTX_ELR_EL3);
diff --git a/services/std_svc/spmd/aarch64/spmd_helpers.S b/services/std_svc/spmd/aarch64/spmd_helpers.S
new file mode 100644
index 0000000..d7bffca
--- /dev/null
+++ b/services/std_svc/spmd/aarch64/spmd_helpers.S
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include "../spmd_private.h"
+
+	.global spmd_spm_core_enter
+	.global spmd_spm_core_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 spmd_spm_core_enter
+	/* Make space for the registers that we're going to save */
+	mov	x3, sp
+	str	x3, [x0, #0]
+	sub	sp, sp, #SPMD_C_RT_CTX_SIZE
+
+	/* Save callee-saved registers on to the stack */
+	stp	x19, x20, [sp, #SPMD_C_RT_CTX_X19]
+	stp	x21, x22, [sp, #SPMD_C_RT_CTX_X21]
+	stp	x23, x24, [sp, #SPMD_C_RT_CTX_X23]
+	stp	x25, x26, [sp, #SPMD_C_RT_CTX_X25]
+	stp	x27, x28, [sp, #SPMD_C_RT_CTX_X27]
+	stp	x29, x30, [sp, #SPMD_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 spmd_spm_core_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 spmd_spm_core_exit
+	/* Restore the previous stack */
+	mov	sp, x0
+
+	/* Restore callee-saved registers on to the stack */
+	ldp	x19, x20, [x0, #(SPMD_C_RT_CTX_X19 - SPMD_C_RT_CTX_SIZE)]
+	ldp	x21, x22, [x0, #(SPMD_C_RT_CTX_X21 - SPMD_C_RT_CTX_SIZE)]
+	ldp	x23, x24, [x0, #(SPMD_C_RT_CTX_X23 - SPMD_C_RT_CTX_SIZE)]
+	ldp	x25, x26, [x0, #(SPMD_C_RT_CTX_X25 - SPMD_C_RT_CTX_SIZE)]
+	ldp	x27, x28, [x0, #(SPMD_C_RT_CTX_X27 - SPMD_C_RT_CTX_SIZE)]
+	ldp	x29, x30, [x0, #(SPMD_C_RT_CTX_X29 - SPMD_C_RT_CTX_SIZE)]
+
+	/* ---------------------------------------------------------------------
+	 * This should take us back to the instruction after the call to the
+	 * last spm_secure_partition_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 spmd_spm_core_exit
diff --git a/services/std_svc/spmd/spmd.mk b/services/std_svc/spmd/spmd.mk
new file mode 100644
index 0000000..38d43f1
--- /dev/null
+++ b/services/std_svc/spmd/spmd.mk
@@ -0,0 +1,21 @@
+#
+# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ifneq (${ARCH},aarch64)
+        $(error "Error: SPMD is only supported on aarch64.")
+endif
+
+SPMD_SOURCES	+=	$(addprefix services/std_svc/spmd/,	\
+			${ARCH}/spmd_helpers.S			\
+			spmd_main.c)
+
+# Let the top-level Makefile know that we intend to include a BL32 image
+NEED_BL32		:=	yes
+
+# Enable dynamic memory mapping
+# The SPMD component maps the SPMC DTB within BL31 virtual space.
+PLAT_XLAT_TABLES_DYNAMIC :=	1
+$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC))
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
new file mode 100644
index 0000000..677f639
--- /dev/null
+++ b/services/std_svc/spmd/spmd_main.c
@@ -0,0 +1,487 @@
+/*
+ * Copyright (c) 2020, 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 <bl31/bl31.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/smccc.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/spci_svc.h>
+#include <services/spmd_svc.h>
+#include <smccc_helpers.h>
+#include "spmd_private.h"
+
+/*******************************************************************************
+ * SPM Core context information.
+ ******************************************************************************/
+spmd_spm_core_context_t spm_core_context[PLATFORM_CORE_COUNT];
+
+/*******************************************************************************
+ * SPM Core attribute information read from its manifest.
+ ******************************************************************************/
+spmc_manifest_sect_attribute_t spmc_attrs;
+
+/*******************************************************************************
+ * This function takes an SP context pointer and performs a synchronous entry
+ * into it.
+ ******************************************************************************/
+uint64_t spmd_spm_core_sync_entry(spmd_spm_core_context_t *spmc_ctx)
+{
+	uint64_t rc;
+
+	assert(spmc_ctx != NULL);
+
+	cm_set_context(&(spmc_ctx->cpu_ctx), SECURE);
+
+	/* Restore the context assigned above */
+	cm_el1_sysregs_context_restore(SECURE);
+	cm_set_next_eret_context(SECURE);
+
+	/* Invalidate TLBs at EL1. */
+	tlbivmalle1();
+	dsbish();
+
+	/* Enter Secure Partition */
+	rc = spmd_spm_core_enter(&spmc_ctx->c_rt_ctx);
+
+	/* Save secure state */
+	cm_el1_sysregs_context_save(SECURE);
+
+	return rc;
+}
+
+/*******************************************************************************
+ * This function returns to the place where spm_sp_synchronous_entry() was
+ * called originally.
+ ******************************************************************************/
+__dead2 void spmd_spm_core_sync_exit(uint64_t rc)
+{
+	spmd_spm_core_context_t *ctx = &spm_core_context[plat_my_core_pos()];
+
+	/* Get context of the SP in use by this CPU. */
+	assert(cm_get_context(SECURE) == &(ctx->cpu_ctx));
+
+	/*
+	 * The SPMD must have initiated the original request through a
+	 * synchronous entry into SPMC. Jump back to the original C runtime
+	 * context with the value of rc in x0;
+	 */
+	spmd_spm_core_exit(ctx->c_rt_ctx, rc);
+
+	panic();
+}
+
+/*******************************************************************************
+ * Jump to the SPM core for the first time.
+ ******************************************************************************/
+static int32_t spmd_init(void)
+{
+	uint64_t rc = 0;
+	spmd_spm_core_context_t *ctx = &spm_core_context[plat_my_core_pos()];
+
+	INFO("SPM Core init start.\n");
+	ctx->state = SPMC_STATE_RESET;
+
+	rc = spmd_spm_core_sync_entry(ctx);
+	if (rc) {
+		ERROR("SPMC initialisation failed 0x%llx\n", rc);
+		panic();
+	}
+
+	ctx->state = SPMC_STATE_IDLE;
+	INFO("SPM Core init end.\n");
+
+	return 1;
+}
+
+/*******************************************************************************
+ * Initialize context of SPM core.
+ ******************************************************************************/
+int32_t spmd_setup(void)
+{
+	int rc;
+	void *rd_base;
+	size_t rd_size;
+	entry_point_info_t *spmc_ep_info;
+	uintptr_t rd_base_align;
+	uintptr_t rd_size_align;
+	uint32_t ep_attr;
+
+	spmc_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
+	if (!spmc_ep_info) {
+		WARN("No SPM core image provided by BL2 boot loader, Booting "
+		     "device without SP initialization. SMC`s destined for SPM "
+		     "core will return SMC_UNK\n");
+		return 1;
+	}
+
+	/* Under no circumstances will this parameter be 0 */
+	assert(spmc_ep_info->pc != 0U);
+
+	/*
+	 * Check if BL32 ep_info has a reference to 'tos_fw_config'. This will
+	 * be used as a manifest for the SPM core at the next lower EL/mode.
+	 */
+	if (spmc_ep_info->args.arg0 == 0U || spmc_ep_info->args.arg2 == 0U) {
+		ERROR("Invalid or absent SPM core manifest\n");
+		panic();
+	}
+
+	/* Obtain whereabouts of SPM core manifest */
+	rd_base = (void *) spmc_ep_info->args.arg0;
+	rd_size = spmc_ep_info->args.arg2;
+
+	rd_base_align = page_align((uintptr_t) rd_base, DOWN);
+	rd_size_align = page_align((uintptr_t) rd_size, UP);
+
+	/* Map the manifest in the SPMD translation regime first */
+	VERBOSE("SPM core manifest base : 0x%lx\n", rd_base_align);
+	VERBOSE("SPM core manifest size : 0x%lx\n", rd_size_align);
+	rc = mmap_add_dynamic_region((unsigned long long) rd_base_align,
+				     (uintptr_t) rd_base_align,
+				     rd_size_align,
+				     MT_RO_DATA);
+	if (rc < 0) {
+		ERROR("Error while mapping SPM core manifest (%d).\n", rc);
+		panic();
+	}
+
+	/* Load the SPM core manifest */
+	rc = plat_spm_core_manifest_load(&spmc_attrs, rd_base, rd_size);
+	if (rc < 0) {
+		WARN("No or invalid SPM core manifest image provided by BL2 "
+		     "boot loader. ");
+		goto error;
+	}
+
+	/*
+	 * Ensure that the SPM core version is compatible with the SPM
+	 * dispatcher version
+	 */
+	if ((spmc_attrs.major_version != SPCI_VERSION_MAJOR) ||
+	    (spmc_attrs.minor_version > SPCI_VERSION_MINOR)) {
+		WARN("Unsupported SPCI version (%x.%x) specified in SPM core "
+		     "manifest image provided by BL2 boot loader.\n",
+		     spmc_attrs.major_version, spmc_attrs.minor_version);
+		goto error;
+	}
+
+	INFO("SPCI version (%x.%x).\n", spmc_attrs.major_version,
+	     spmc_attrs.minor_version);
+
+	/* Validate the SPM core runtime EL */
+	if ((spmc_attrs.runtime_el != MODE_EL1) &&
+	    (spmc_attrs.runtime_el != MODE_EL2)) {
+		WARN("Unsupported SPM core run time EL%x specified in "
+		     "manifest image provided by BL2 boot loader.\n",
+		     spmc_attrs.runtime_el);
+		goto error;
+	}
+
+	INFO("SPM core run time EL%x.\n", spmc_attrs.runtime_el);
+
+	/* Validate the SPM core execution state */
+	if ((spmc_attrs.exec_state != MODE_RW_64) &&
+	    (spmc_attrs.exec_state != MODE_RW_32)) {
+		WARN("Unsupported SPM core execution state %x specified in "
+		     "manifest image provided by BL2 boot loader.\n",
+		     spmc_attrs.exec_state);
+		goto error;
+	}
+
+	INFO("SPM core execution state %x.\n", spmc_attrs.exec_state);
+
+	/* Ensure manifest has not requested S-EL2 in AArch32 state */
+	if ((spmc_attrs.exec_state == MODE_RW_32) &&
+	    (spmc_attrs.runtime_el == MODE_EL2)) {
+		WARN("Invalid combination of SPM core execution state (%x) "
+		     "and run time EL (%x).\n", spmc_attrs.exec_state,
+		     spmc_attrs.runtime_el);
+		goto error;
+	}
+
+	/*
+	 * Check if S-EL2 is supported on this system if S-EL2
+	 * is required for SPM
+	 */
+	if (spmc_attrs.runtime_el == MODE_EL2) {
+		uint64_t sel2 = read_id_aa64pfr0_el1();
+
+		sel2 >>= ID_AA64PFR0_SEL2_SHIFT;
+		sel2 &= ID_AA64PFR0_SEL2_MASK;
+
+		if (!sel2) {
+			WARN("SPM core run time EL: S-EL%x is not supported "
+			     "but specified in manifest image provided by "
+			     "BL2 boot loader.\n", spmc_attrs.runtime_el);
+			goto error;
+		}
+	}
+
+	/* Initialise an entrypoint to set up the CPU context */
+	ep_attr = SECURE | EP_ST_ENABLE;
+	if (read_sctlr_el3() & SCTLR_EE_BIT)
+		ep_attr |= EP_EE_BIG;
+	SET_PARAM_HEAD(spmc_ep_info, PARAM_EP, VERSION_1, ep_attr);
+	assert(spmc_ep_info->pc == BL32_BASE);
+
+	/*
+	 * Populate SPSR for SPM core based upon validated parameters from the
+	 * manifest
+	 */
+	if (spmc_attrs.exec_state == MODE_RW_32) {
+		spmc_ep_info->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
+						 SPSR_E_LITTLE,
+						 DAIF_FIQ_BIT |
+						 DAIF_IRQ_BIT |
+						 DAIF_ABT_BIT);
+	} else {
+		spmc_ep_info->spsr = SPSR_64(spmc_attrs.runtime_el,
+					     MODE_SP_ELX,
+					     DISABLE_ALL_EXCEPTIONS);
+	}
+
+	/* Initialise SPM core context with this entry point information */
+	cm_setup_context(&(spm_core_context[plat_my_core_pos()].cpu_ctx),
+			 spmc_ep_info);
+
+	INFO("SPM core setup done.\n");
+
+	/* Register init function for deferred init.  */
+	bl31_register_bl32_init(&spmd_init);
+
+	return 0;
+
+error:
+	WARN("Booting device without SPM initialization. "
+	     "SPCI SMCs destined for SPM core will return "
+	     "ENOTSUPPORTED\n");
+
+	rc = mmap_remove_dynamic_region(rd_base_align, rd_size_align);
+	if (rc < 0) {
+		ERROR("Error while unmapping SPM core manifest (%d).\n",
+		      rc);
+		panic();
+	}
+
+	return 1;
+}
+
+/*******************************************************************************
+ * This function handles all SMCs in the range reserved for SPCI. Each call is
+ * either forwarded to the other security state or handled by the SPM dispatcher
+ ******************************************************************************/
+uint64_t spmd_smc_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 in_sstate;
+	uint32_t out_sstate;
+	int32_t ret;
+	spmd_spm_core_context_t *ctx = &spm_core_context[plat_my_core_pos()];
+
+	/* Determine which security state this SMC originated from */
+	if (is_caller_secure(flags)) {
+		in_sstate = SECURE;
+		out_sstate = NON_SECURE;
+	} else {
+		in_sstate = NON_SECURE;
+		out_sstate = SECURE;
+	}
+
+	INFO("SPM: 0x%x, 0x%llx, 0x%llx, 0x%llx, 0x%llx, "
+	     "0x%llx, 0x%llx, 0x%llx\n",
+	     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));
+
+	switch (smc_fid) {
+	case SPCI_ERROR:
+		/*
+		 * Check if this is the first invocation of this interface on
+		 * this CPU. If so, then indicate that the SPM core initialised
+		 * unsuccessfully.
+		 */
+		if ((in_sstate == SECURE) && (ctx->state == SPMC_STATE_RESET))
+			spmd_spm_core_sync_exit(x2);
+
+		/* Save incoming security state */
+		cm_el1_sysregs_context_save(in_sstate);
+
+		/* Restore outgoing security state */
+		cm_el1_sysregs_context_restore(out_sstate);
+		cm_set_next_eret_context(out_sstate);
+
+		SMC_RET8(cm_get_context(out_sstate), 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));
+		break; /* not reached */
+
+	case SPCI_VERSION:
+		/*
+		 * TODO: This is an optimization that the version information
+		 * provided by the SPM core manifest is returned by the SPM
+		 * dispatcher. It might be a better idea to simply forward this
+		 * call to the SPM core and wash our hands completely.
+		 */
+		ret = MAKE_SPCI_VERSION(spmc_attrs.major_version,
+					spmc_attrs.minor_version);
+		SMC_RET8(handle, SPCI_SUCCESS_SMC32, SPCI_TARGET_INFO_MBZ, ret,
+			 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
+			 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ);
+		break; /* not reached */
+
+	case SPCI_FEATURES:
+		/*
+		 * This is an optional interface. Do the minimal checks and
+		 * forward to SPM core which will handle it if implemented.
+		 */
+
+		/*
+		 * Check if w1 holds a valid SPCI fid. This is an
+		 * optimization.
+		 */
+		if (!is_spci_fid(x1))
+			SMC_RET8(handle, SPCI_ERROR,
+				 SPCI_TARGET_INFO_MBZ, SPCI_ERROR_NOT_SUPPORTED,
+				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
+				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ);
+
+		/* Forward SMC from Normal world to the SPM core */
+		if (in_sstate == NON_SECURE) {
+			/* Save incoming security state */
+			cm_el1_sysregs_context_save(in_sstate);
+
+			/* Restore outgoing security state */
+			cm_el1_sysregs_context_restore(out_sstate);
+			cm_set_next_eret_context(out_sstate);
+
+			SMC_RET8(cm_get_context(out_sstate), 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));
+		} else {
+			/*
+			 * Return success if call was from secure world i.e. all
+			 * SPCI functions are supported. This is essentially a
+			 * nop.
+			 */
+			SMC_RET8(handle, SPCI_SUCCESS_SMC32, 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));
+		}
+		break; /* not reached */
+
+	case SPCI_RX_RELEASE:
+	case SPCI_RXTX_MAP_SMC32:
+	case SPCI_RXTX_MAP_SMC64:
+	case SPCI_RXTX_UNMAP:
+	case SPCI_MSG_RUN:
+		/* This interface must be invoked only by the Normal world */
+		if (in_sstate == SECURE) {
+			SMC_RET8(handle, SPCI_ERROR,
+				 SPCI_TARGET_INFO_MBZ, SPCI_ERROR_NOT_SUPPORTED,
+				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
+				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ);
+		}
+
+		/* Fall through to forward the call to the other world */
+
+	case SPCI_PARTITION_INFO_GET:
+	case SPCI_MSG_SEND:
+	case SPCI_MSG_SEND_DIRECT_REQ_SMC32:
+	case SPCI_MSG_SEND_DIRECT_REQ_SMC64:
+	case SPCI_MSG_SEND_DIRECT_RESP_SMC32:
+	case SPCI_MSG_SEND_DIRECT_RESP_SMC64:
+	case SPCI_MEM_DONATE_SMC32:
+	case SPCI_MEM_DONATE_SMC64:
+	case SPCI_MEM_LEND_SMC32:
+	case SPCI_MEM_LEND_SMC64:
+	case SPCI_MEM_SHARE_SMC32:
+	case SPCI_MEM_SHARE_SMC64:
+	case SPCI_MEM_RETRIEVE_REQ_SMC32:
+	case SPCI_MEM_RETRIEVE_REQ_SMC64:
+	case SPCI_MEM_RETRIEVE_RESP:
+	case SPCI_MEM_RELINQUISH:
+	case SPCI_MEM_RECLAIM:
+	case SPCI_SUCCESS_SMC32:
+	case SPCI_SUCCESS_SMC64:
+		/*
+		 * TODO: Assume that no requests originate from EL3 at the
+		 * moment. This will change if a SP service is required in
+		 * response to secure interrupts targeted to EL3. Until then
+		 * simply forward the call to the Normal world.
+		 */
+
+		/* Save incoming security state */
+		cm_el1_sysregs_context_save(in_sstate);
+
+		/* Restore outgoing security state */
+		cm_el1_sysregs_context_restore(out_sstate);
+		cm_set_next_eret_context(out_sstate);
+
+		SMC_RET8(cm_get_context(out_sstate), 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));
+		break; /* not reached */
+
+	case SPCI_MSG_WAIT:
+		/*
+		 * Check if this is the first invocation of this interface on
+		 * this CPU from the Secure world. If so, then indicate that the
+		 * SPM core initialised successfully.
+		 */
+		if ((in_sstate == SECURE) && (ctx->state == SPMC_STATE_RESET)) {
+			spmd_spm_core_sync_exit(0);
+		}
+
+		/* Intentional fall-through */
+
+	case SPCI_MSG_YIELD:
+		/* This interface must be invoked only by the Secure world */
+		if (in_sstate == NON_SECURE) {
+			SMC_RET8(handle, SPCI_ERROR,
+				 SPCI_TARGET_INFO_MBZ, SPCI_ERROR_NOT_SUPPORTED,
+				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
+				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ);
+		}
+
+		/* Save incoming security state */
+		cm_el1_sysregs_context_save(in_sstate);
+
+		/* Restore outgoing security state */
+		cm_el1_sysregs_context_restore(out_sstate);
+		cm_set_next_eret_context(out_sstate);
+
+		SMC_RET8(cm_get_context(out_sstate), 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));
+		break; /* not reached */
+
+	default:
+		WARN("SPM: Unsupported call 0x%08x\n", smc_fid);
+		SMC_RET8(handle, SPCI_ERROR,
+			 SPCI_TARGET_INFO_MBZ, SPCI_ERROR_NOT_SUPPORTED,
+			 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
+			 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ);
+	}
+}
diff --git a/services/std_svc/spmd/spmd_private.h b/services/std_svc/spmd/spmd_private.h
new file mode 100644
index 0000000..61b479a
--- /dev/null
+++ b/services/std_svc/spmd/spmd_private.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SPMD_PRIVATE_H
+#define SPMD_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 SPMD_C_RT_CTX_X19		0x0
+#define SPMD_C_RT_CTX_X20		0x8
+#define SPMD_C_RT_CTX_X21		0x10
+#define SPMD_C_RT_CTX_X22		0x18
+#define SPMD_C_RT_CTX_X23		0x20
+#define SPMD_C_RT_CTX_X24		0x28
+#define SPMD_C_RT_CTX_X25		0x30
+#define SPMD_C_RT_CTX_X26		0x38
+#define SPMD_C_RT_CTX_X27		0x40
+#define SPMD_C_RT_CTX_X28		0x48
+#define SPMD_C_RT_CTX_X29		0x50
+#define SPMD_C_RT_CTX_X30		0x58
+
+#define SPMD_C_RT_CTX_SIZE		0x60
+#define SPMD_C_RT_CTX_ENTRIES		(SPMD_C_RT_CTX_SIZE >> DWORD_SHIFT)
+
+#ifndef __ASSEMBLER__
+#include <services/spci_svc.h>
+#include <stdint.h>
+
+/*
+ * Convert a function no. in a FID to a bit position. All function nos. are
+ * between 0 and 0x1f
+ */
+#define SPCI_FNO_TO_BIT_POS(_fid)	(1 << ((_fid) & U(0x1f)))
+
+typedef enum spmc_state {
+	SPMC_STATE_RESET = 0,
+	SPMC_STATE_IDLE
+} spmc_state_t;
+
+/*
+ * Data structure used by the SPM dispatcher (SPMD) in EL3 to track context of
+ * the SPM core (SPMC) at the next lower EL.
+ */
+typedef struct spmd_spm_core_context {
+	uint64_t c_rt_ctx;
+	cpu_context_t cpu_ctx;
+	spmc_state_t state;
+} spmd_spm_core_context_t;
+
+/*
+ * Data structure used by the SPM dispatcher (SPMD) in EL3 to track sequence of
+ * SPCI calls from lower ELs.
+ *
+ * next_smc_bit_map: Per-cpu bit map of SMCs from each world that are expected
+ *                   next.
+ */
+typedef struct spmd_spci_context {
+	uint32_t next_smc_bit_map[2];
+} spmd_spci_context_t;
+
+/* Functions used to enter/exit a Secure Partition synchronously */
+uint64_t spmd_spm_core_sync_entry(spmd_spm_core_context_t *ctx);
+__dead2 void spmd_spm_core_sync_exit(uint64_t rc);
+
+/* Assembly helpers */
+uint64_t spmd_spm_core_enter(uint64_t *c_rt_ctx);
+void __dead2 spmd_spm_core_exit(uint64_t c_rt_ctx, uint64_t ret);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* SPMD_PRIVATE_H */
diff --git a/services/std_svc/std_svc_setup.c b/services/std_svc/std_svc_setup.c
index 7787a2f..895fd29 100644
--- a/services/std_svc/std_svc_setup.c
+++ b/services/std_svc/std_svc_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,6 +15,7 @@
 #include <lib/runtime_instr.h>
 #include <services/sdei.h>
 #include <services/spm_mm_svc.h>
+#include <services/spmd_svc.h>
 #include <services/std_svc.h>
 #include <smccc_helpers.h>
 #include <tools_share/uuid.h>
@@ -51,6 +52,12 @@
 	}
 #endif
 
+#if defined(SPD_spmd)
+	if (spmd_setup() != 0) {
+		ret = 1;
+	}
+#endif
+
 #if SDEI_SUPPORT
 	/* SDEI initialisation */
 	sdei_init();
@@ -114,6 +121,17 @@
 	}
 #endif
 
+#if defined(SPD_spmd)
+	/*
+	 * Dispatch SPCI calls to the SPCI SMC handler implemented by the SPM
+	 * dispatcher and return its return value
+	 */
+	if (is_spci_fid(smc_fid)) {
+		return spmd_smc_handler(smc_fid, x1, x2, x3, x4, cookie,
+					handle, flags);
+	}
+#endif
+
 #if SDEI_SUPPORT
 	if (is_sdei_fid(smc_fid)) {
 		return sdei_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle,
diff --git a/tools/sptool/sp_mk_generator.py b/tools/sptool/sp_mk_generator.py
new file mode 100755
index 0000000..6b6fa19
--- /dev/null
+++ b/tools/sptool/sp_mk_generator.py
@@ -0,0 +1,100 @@
+#!/usr/bin/python3
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+"""
+This script is invoked by Make system and generates secure partition makefile.
+It expects platform provided secure partition layout file which contains list
+of Secure Partition Images and Partition manifests(PM).
+Layout file can exist outside of TF-A tree and the paths of Image and PM files
+must be relative to it.
+
+This script parses the layout file and generates a make file which updates
+FDT_SOURCES, FIP_ARGS and SPTOOL_ARGS which are used in later build steps.
+This script also gets SP "uuid" from parsing its PM and converting it to a
+standard format.
+
+param1: Generated mk file "sp_gen.mk"
+param2: "SP_LAYOUT_FILE", json file containing platform provided information
+param3: plat out directory
+
+Generated "sp_gen.mk" file contains triplet of following information for each
+Secure Partition entry
+    FDT_SOURCES +=  sp1.dts
+    SPTOOL_ARGS += -i sp1.bin:sp1.dtb -o sp1.pkg
+    FIP_ARGS += --blob uuid=XXXXX-XXX...,file=sp1.pkg
+
+A typical SP_LAYOUT_FILE file will look like
+{
+        "SP1" : {
+                "image": "sp1.bin",
+                "pm": "test/sp1.dts"
+        },
+
+        "SP2" : {
+                "image": "sp2.bin",
+                "pm": "test/sp2.dts"
+        }
+
+        ...
+}
+
+"""
+
+import getopt
+import json
+import os
+import re
+import sys
+import uuid
+
+with open(sys.argv[2],'r') as in_file:
+    data = json.load(in_file)
+json_file = os.path.abspath(sys.argv[2])
+json_dir = os.path.dirname(json_file)
+gen_file = sys.argv[1]
+out_dir = sys.argv[3][2:]
+dtb_dir = out_dir + "/fdts/"
+print(dtb_dir)
+
+with open(gen_file, 'w') as out_file:
+    for key in data.keys():
+
+        """
+        Append FDT_SOURCES
+        """
+        dts = os.path.join(json_dir, data[key]['pm'])
+        dtb = dtb_dir + os.path.basename(data[key]['pm'][:-1] + "b")
+        out_file.write("FDT_SOURCES += " + dts + "\n")
+
+        """
+        Update SPTOOL_ARGS
+        """
+        dst = out_dir + "/" + key + ".pkg"
+        src = [ json_dir + "/" + data[key]['image'] , dtb  ]
+        out_file.write("SPTOOL_ARGS += -i " + ":".join(src) + " -o " + dst + "\n")
+
+        """
+        Extract uuid from partition manifest
+        """
+        pm_file = open(dts)
+        key = "uuid"
+
+        for line in pm_file:
+            if key in line:
+                uuid_hex = re.findall(r'\<(.+?)\>', line)[0];
+
+        # 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)
+
+        """
+        Append FIP_ARGS
+        """
+        out_file.write("FIP_ARGS += --blob uuid=" + uuid_std + ",file=" + dst + "\n")
+        out_file.write("\n")
diff --git a/tools/sptool/sptool.c b/tools/sptool/sptool.c
index a33b664..38baa2c 100644
--- a/tools/sptool/sptool.c
+++ b/tools/sptool/sptool.c
@@ -1,10 +1,11 @@
 /*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <stdarg.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -16,25 +17,26 @@
 #define PAGE_SIZE		4096
 
 /*
- * Linked list of entries describing entries in the secure
- * partition package.
+ * Entry describing Secure Partition package.
  */
-struct sp_entry_info {
+struct sp_pkg_info {
 	/* Location of the files in the host's RAM. */
-	void *sp_data, *rd_data;
+	void *img_data, *pm_data;
 
 	/* Size of the files. */
-	uint64_t sp_size, rd_size;
+	uint32_t img_size, pm_size;
 
 	/* Location of the binary files inside the package output file */
-	uint64_t sp_offset, rd_offset;
-
-	struct sp_entry_info *next;
+	uint32_t img_offset, pm_offset;
 };
 
-static struct sp_entry_info *sp_info_head;
-
-static uint64_t sp_count;
+/*
+ * List of input provided by user
+ */
+struct arg_list {
+	char *usr_input;
+	struct arg_list *next;
+};
 
 /* Align an address to a power-of-two boundary. */
 static unsigned int align_to(unsigned int address, unsigned int boundary)
@@ -89,34 +91,69 @@
 	}
 }
 
-static void cleanup(void)
+/*
+ * Free SP package structure
+ */
+static void cleanup(struct sp_pkg_info *sp)
 {
-	struct sp_entry_info *sp = sp_info_head;
 
-	while (sp != NULL) {
-		struct sp_entry_info *next = sp->next;
-
-		if (sp->sp_data != NULL)
-			free(sp->sp_data);
+	if (sp != NULL) {
+		if (sp->img_data != NULL) {
+			free(sp->img_data);
+		}
 
-		if (sp->rd_data != NULL)
-			free(sp->rd_data);
+		if (sp->pm_data != NULL) {
+			free(sp->pm_data);
+		}
 
 		free(sp);
 
-		sp = next;
 	}
+}
 
-	sp_count = 0;
-	sp_info_head = NULL;
+/*
+ * Free argument list structure
+ */
+static void freelist(struct arg_list *head)
+{
+	struct arg_list *tmp;
+
+	while (head != NULL) {
+		tmp = head;
+		head = head->next;
+		free(tmp);
+	}
 }
 
 /*
+ * Append user inputs in argument list structure
+ */
+static void append_user_input(struct arg_list **head, char *args)
+{
+	struct arg_list *tmp = *head;
+
+	if (tmp == NULL) {
+		tmp = xzalloc(sizeof(struct arg_list),
+				"Failed to allocate arg_list struct");
+		tmp->usr_input = args;
+		*head = tmp;
+	} else {
+		while (tmp->next != NULL) {
+			tmp = tmp->next;
+		}
+		tmp->next = xzalloc(sizeof(struct arg_list),
+				"Failed to allocate arg_list struct");
+		tmp = tmp->next;
+		tmp->usr_input = args;
+	}
+}
+
+/*
  * Allocate a buffer big enough to store the content of the specified file and
  * load the file into it. Fill 'size' with the file size. Exit the program on
  * error.
  */
-static void load_file(const char *path, void **ptr, uint64_t *size)
+static void load_file(const char *path, void **ptr, uint32_t *size)
 {
 	FILE *f = fopen(path, "rb");
 	if (f == NULL) {
@@ -147,59 +184,40 @@
 	fclose(f);
 }
 
-static void load_sp_rd(char *path)
+/*
+ * Parse the string containing input payloads and fill in the
+ * SP Package data structure.
+ */
+static void load_sp_pm(char *path, struct sp_pkg_info **sp_out)
 {
+	struct sp_pkg_info *sp_pkg;
+
 	char *split_mark = strstr(path, ":");
 
 	*split_mark = '\0';
 
 	char *sp_path = path;
-	char *rd_path = split_mark + 1;
-
-	struct sp_entry_info *sp;
-
-	if (sp_info_head == NULL) {
-		sp_info_head = xzalloc(sizeof(struct sp_entry_info),
-			"Failed to allocate sp_entry_info struct");
-
-		sp = sp_info_head;
-	} else {
-		sp = sp_info_head;
-
-		while (sp->next != NULL) {
-			sp = sp->next;
-		}
-
-		sp->next = xzalloc(sizeof(struct sp_entry_info),
-			"Failed to allocate sp_entry_info struct");
+	char *pm_path = split_mark + 1;
 
-		sp = sp->next;
-	}
+	sp_pkg = xzalloc(sizeof(struct sp_pkg_info),
+		"Failed to allocate sp_pkg_info struct");
 
-	load_file(sp_path, &sp->sp_data, &sp->sp_size);
-	printf("Loaded image file %s (%lu bytes)\n", sp_path, sp->sp_size);
+	load_file(pm_path, &sp_pkg->pm_data, &sp_pkg->pm_size);
+	printf("\nLoaded SP Manifest file %s (%u bytes)\n", pm_path, sp_pkg->pm_size);
 
-	load_file(rd_path, &sp->rd_data, &sp->rd_size);
-	printf("Loaded RD file %s (%lu bytes)\n", rd_path, sp->rd_size);
+	load_file(sp_path, &sp_pkg->img_data, &sp_pkg->img_size);
+	printf("Loaded SP Image file %s (%u bytes)\n", sp_path, sp_pkg->img_size);
 
-	sp_count++;
+	*sp_out = sp_pkg;
 }
 
-static void output_write(const char *path)
+/*
+ * Write SP package data structure into output file.
+ */
+static void output_write(const char *path, struct sp_pkg_info *sp, bool header)
 {
-	struct sp_entry_info *sp;
-
-	if (sp_count == 0) {
-		fprintf(stderr, "error: At least one SP must be provided.\n");
-		exit(1);
-	}
-
-	/* The layout of the structs is specified in the header file sptool.h */
-
-	printf("Writing %lu partitions to output file.\n", sp_count);
-
-	unsigned int header_size = (sizeof(struct sp_pkg_header) * 8)
-				 + (sizeof(struct sp_pkg_entry) * 8 * sp_count);
+	struct sp_pkg_header sp_header_info;
+	unsigned int file_ptr = 0;
 
 	FILE *f = fopen(path, "wb");
 	if (f == NULL) {
@@ -207,70 +225,46 @@
 		exit(1);
 	}
 
-	unsigned int file_ptr = align_to(header_size, PAGE_SIZE);
-
-	/* First, save all partition images aligned to page boundaries */
-
-	sp = sp_info_head;
-
-	for (uint64_t i = 0; i < sp_count; i++) {
-		xfseek(f, file_ptr, SEEK_SET);
-
-		printf("Writing image %lu to offset 0x%x (0x%lx bytes)\n",
-		       i, file_ptr, sp->sp_size);
-
-		sp->sp_offset = file_ptr;
-		xfwrite(sp->sp_data, sp->sp_size, f);
-		file_ptr = align_to(file_ptr + sp->sp_size, PAGE_SIZE);
-		sp = sp->next;
+	/* Reserve Header size */
+	if (header) {
+		file_ptr = sizeof(struct sp_pkg_header);
 	}
 
-	/* Now, save resource description blobs aligned to 8 bytes */
+	/* Save partition manifest */
+	xfseek(f, file_ptr, SEEK_SET);
+	printf("Writing SP Manifest at offset 0x%x (%u bytes)\n",
+	       file_ptr, sp->pm_size);
 
-	sp = sp_info_head;
+	sp->pm_offset = file_ptr;
+	xfwrite(sp->pm_data, sp->pm_size, f);
 
-	for (uint64_t i = 0; i < sp_count; i++) {
-		xfseek(f, file_ptr, SEEK_SET);
+	/* Save partition image aligned to Page size */
+	file_ptr = align_to((sp->pm_offset + sp->pm_size), PAGE_SIZE);
+	xfseek(f, file_ptr, SEEK_SET);
+	printf("Writing SP Image at offset 0x%x (%u bytes)\n",
+	       file_ptr, sp->img_size);
 
-		printf("Writing RD blob %lu to offset 0x%x (0x%lx bytes)\n",
-		       i, file_ptr, sp->rd_size);
+	sp->img_offset = file_ptr;
+	xfwrite(sp->img_data, sp->img_size, f);
 
-		sp->rd_offset = file_ptr;
-		xfwrite(sp->rd_data, sp->rd_size, f);
-		file_ptr = align_to(file_ptr + sp->rd_size, 8);
-		sp = sp->next;
-	}
-
-	/* Finally, write header */
-
-	uint64_t version = 0x1;
-	uint64_t sp_num = sp_count;
-
-	xfseek(f, 0, SEEK_SET);
+	/* Finally, write header, if needed */
+	if (header) {
+		sp_header_info.magic = SECURE_PARTITION_MAGIC;
+		sp_header_info.version = 0x1;
+		sp_header_info.img_offset = sp->img_offset;
+		sp_header_info.img_size = sp->img_size;
+		sp_header_info.pm_offset = sp->pm_offset;
+		sp_header_info.pm_size = sp->pm_size;
 
-	xfwrite(&version, sizeof(uint64_t), f);
-	xfwrite(&sp_num, sizeof(uint64_t), f);
+		xfseek(f, 0, SEEK_SET);
 
-	sp = sp_info_head;
+		printf("Writing package header\n");
 
-	for (unsigned int i = 0; i < sp_count; i++) {
-
-		uint64_t sp_offset, sp_size, rd_offset, rd_size;
-
-		sp_offset = sp->sp_offset;
-		sp_size = align_to(sp->sp_size, PAGE_SIZE);
-		rd_offset = sp->rd_offset;
-		rd_size = sp->rd_size;
-
-		xfwrite(&sp_offset, sizeof(uint64_t), f);
-		xfwrite(&sp_size, sizeof(uint64_t), f);
-		xfwrite(&rd_offset, sizeof(uint64_t), f);
-		xfwrite(&rd_size, sizeof(uint64_t), f);
-
-		sp = sp->next;
+		xfwrite(&sp_header_info, sizeof(struct sp_pkg_header), f);
 	}
 
 	/* All information has been written now */
+	printf("\nsptool: Built Secure Partition blob %s\n", path);
 
 	fclose(f);
 }
@@ -286,30 +280,51 @@
 #endif
 	printf(" [<args>]\n\n");
 
-	printf("This tool takes as inputs several image binary files and the\n"
-	       "resource description blobs as input and generates a package\n"
-	       "file that contains them.\n\n");
+	printf("This tool takes as input set of image binary files and the\n"
+	       "partition manifest blobs as input and generates set of\n"
+	       "output package files\n"
+	       "Usage example: sptool -i sp1.bin:sp1.dtb -o sp1.pkg\n"
+	       "                      -i sp2.bin:sp2.dtb -o sp2.pkg ...\n\n");
 	printf("Commands supported:\n");
 	printf("  -o <path>            Set output file path.\n");
-	printf("  -i <sp_path:rd_path> Add Secure Partition image and Resource\n"
-	       "                       Description blob (specified in two paths\n"
+	printf("  -i <sp_path:pm_path> Add Secure Partition image and\n"
+	       "                       Manifest blob (specified in two paths\n"
 	       "                       separated by a colon).\n");
+	printf("  -n                   Generate package without header\n");
 	printf("  -h                   Show this message.\n");
 	exit(1);
 }
 
 int main(int argc, char *argv[])
 {
+	struct sp_pkg_info *sp_pkg = NULL;
+	struct arg_list *in_head = NULL;
+	struct arg_list *out_head = NULL;
+	struct arg_list *in_list = NULL;
+	struct arg_list *out_list = NULL;
+	unsigned int match_counter = 0;
+	bool need_header = true;
+
 	int ch;
-	const char *outname = NULL;
 
-	while ((ch = getopt(argc, argv, "hi:o:")) != -1) {
+	if (argc <= 1) {
+		fprintf(stderr, "error: File paths must be provided.\n\n");
+		usage();
+		return 1;
+	}
+
+	while ((ch = getopt(argc, argv, "hni:o:")) != -1) {
 		switch (ch) {
 		case 'i':
-			load_sp_rd(optarg);
+			append_user_input(&in_head, optarg);
+			match_counter++;
 			break;
 		case 'o':
-			outname = optarg;
+			append_user_input(&out_head, optarg);
+			match_counter--;
+			break;
+		case 'n':
+			need_header = false;
 			break;
 		case 'h':
 		default:
@@ -317,18 +332,29 @@
 		}
 	}
 
-	argc -= optind;
-	argv += optind;
-
-	if (outname == NULL) {
-		fprintf(stderr, "error: An output file path must be provided.\n\n");
+	if (match_counter) {
+		fprintf(stderr, "error: Input/Output count mismatch.\n\n");
+		freelist(in_head);
+		freelist(out_head);
 		usage();
 		return 1;
 	}
 
-	output_write(outname);
+	in_list = in_head;
+	out_list = out_head;
+	while (in_list != NULL) {
+		load_sp_pm(in_list->usr_input, &sp_pkg);
+		output_write(out_list->usr_input, sp_pkg, need_header);
+		in_list = in_list->next;
+		out_list = out_list->next;
+	}
+
+	argc -= optind;
+	argv += optind;
 
-	cleanup();
+	cleanup(sp_pkg);
+	freelist(in_head);
+	freelist(out_head);
 
 	return 0;
 }