Merge "sc7180 platform support" into integration
diff --git a/Makefile b/Makefile
index 2f53cdf..f4589d9 100644
--- a/Makefile
+++ b/Makefile
@@ -121,6 +121,10 @@
 	# Extend the signing to include leaf functions
 	BP_OPTION := pac-ret+leaf
 	ENABLE_PAUTH := 1
+else ifeq (${BRANCH_PROTECTION},4)
+	# Turn on branch target identification mechanism
+	BP_OPTION := bti
+	ENABLE_BTI := 1
 else
         $(error Unknown BRANCH_PROTECTION value ${BRANCH_PROTECTION})
 endif
@@ -193,10 +197,8 @@
 
 # Memory tagging is supported in architecture Armv8.5-A AArch64 and onwards
 ifeq ($(ARCH), aarch64)
-ifeq ($(shell test $(ARM_ARCH_MAJOR) -gt 8; echo $$?),0)
-mem_tag_arch_support	= 	yes
-else ifeq ($(shell test $(ARM_ARCH_MAJOR) -eq 8 -a $(ARM_ARCH_MINOR) -ge 5; \
-	   echo $$?),0)
+# Check if revision is greater than or equal to 8.5
+ifeq "8.5" "$(word 1, $(sort 8.5 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))"
 mem_tag_arch_support	= 	yes
 endif
 endif
@@ -449,8 +451,10 @@
 
 include ${MAKE_HELPERS_DIRECTORY}plat_helpers.mk
 
-BUILD_BASE		:=	./build
-BUILD_PLAT		:=	${BUILD_BASE}/${PLAT}/${BUILD_TYPE}
+ifeq (${BUILD_BASE},)
+     BUILD_BASE		:=	./build
+endif
+BUILD_PLAT		:=	$(abspath ${BUILD_BASE})/${PLAT}/${BUILD_TYPE}
 
 SPDS			:=	$(sort $(filter-out none, $(patsubst services/spd/%,%,$(wildcard services/spd/*))))
 
@@ -482,6 +486,10 @@
                 $(error SPMD with SPM at S-EL2 requires CTX_INCLUDE_EL2_REGS option)
             endif
         endif
+
+        ifeq ($(findstring optee_sp,$(ARM_SPMC_MANIFEST_DTS)),optee_sp)
+            DTC_CPPFLAGS	+=	-DOPTEE_SP_FW_CONFIG
+        endif
     else
         # All other SPDs in spd directory
         SPD_DIR := spd
@@ -657,6 +665,10 @@
 	SDEI_SUPPORT is enabled")
 endif
 
+ifeq ($(COT_DESC_IN_DTB),1)
+    $(info CoT in device tree is an experimental feature)
+endif
+
 # If pointer authentication is used in the firmware, make sure that all the
 # registers associated to it are also saved and restored.
 # Not doing it would leak the value of the keys used by EL3 to EL1 and S-EL1.
@@ -889,6 +901,7 @@
 $(eval $(call assert_boolean,USE_DEBUGFS))
 $(eval $(call assert_boolean,ARM_IO_IN_DTB))
 $(eval $(call assert_boolean,SDEI_IN_FCONF))
+$(eval $(call assert_boolean,SEC_INT_DESC_IN_FCONF))
 $(eval $(call assert_boolean,USE_ROMLIB))
 $(eval $(call assert_boolean,USE_TBBR_DEFS))
 $(eval $(call assert_boolean,WARMBOOT_ENABLE_DCACHE_EARLY))
@@ -899,6 +912,8 @@
 $(eval $(call assert_boolean,ENCRYPT_BL31))
 $(eval $(call assert_boolean,ENCRYPT_BL32))
 $(eval $(call assert_boolean,ERRATA_SPECULATIVE_AT))
+$(eval $(call assert_boolean,RAS_TRAP_LOWER_EL_ERR_ACCESS))
+$(eval $(call assert_boolean,COT_DESC_IN_DTB))
 
 $(eval $(call assert_numeric,ARM_ARCH_MAJOR))
 $(eval $(call assert_numeric,ARM_ARCH_MINOR))
@@ -969,6 +984,7 @@
 $(eval $(call add_define,USE_DEBUGFS))
 $(eval $(call add_define,ARM_IO_IN_DTB))
 $(eval $(call add_define,SDEI_IN_FCONF))
+$(eval $(call add_define,SEC_INT_DESC_IN_FCONF))
 $(eval $(call add_define,USE_ROMLIB))
 $(eval $(call add_define,USE_TBBR_DEFS))
 $(eval $(call add_define,WARMBOOT_ENABLE_DCACHE_EARLY))
@@ -977,6 +993,8 @@
 $(eval $(call add_define,BL2_INV_DCACHE))
 $(eval $(call add_define,USE_SPINLOCK_CAS))
 $(eval $(call add_define,ERRATA_SPECULATIVE_AT))
+$(eval $(call add_define,RAS_TRAP_LOWER_EL_ERR_ACCESS))
+$(eval $(call add_define,COT_DESC_IN_DTB))
 
 ifeq (${SANITIZE_UB},trap)
         $(eval $(call add_define,MONITOR_TRAPS))
@@ -1010,6 +1028,7 @@
         endif
         -include $(BUILD_PLAT)/sp_gen.mk
         FIP_DEPS += sp
+        CRT_DEPS += sp
         NEED_SP_PKG := yes
 else
         ifeq (${SPMD_SPM_AT_SEL2},1)
@@ -1188,7 +1207,7 @@
 
 .PHONY: ${CRTTOOL}
 ${CRTTOOL}:
-	${Q}${MAKE} PLAT=${PLAT} USE_TBBR_DEFS=${USE_TBBR_DEFS} COT=${COT} --no-print-directory -C ${CRTTOOLPATH}
+	${Q}${MAKE} PLAT=${PLAT} USE_TBBR_DEFS=${USE_TBBR_DEFS} COT=${COT} OPENSSL_DIR=${OPENSSL_DIR} --no-print-directory -C ${CRTTOOLPATH}
 	@${ECHO_BLANK_LINE}
 	@echo "Built $@ successfully"
 	@${ECHO_BLANK_LINE}
@@ -1254,7 +1273,7 @@
 
 .PHONY: ${ENCTOOL}
 ${ENCTOOL}:
-	${Q}${MAKE} PLAT=${PLAT} BUILD_INFO=0 --no-print-directory -C ${ENCTOOLPATH}
+	${Q}${MAKE} PLAT=${PLAT} BUILD_INFO=0 OPENSSL_DIR=${OPENSSL_DIR} --no-print-directory -C ${ENCTOOLPATH}
 	@${ECHO_BLANK_LINE}
 	@echo "Built $@ successfully"
 	@${ECHO_BLANK_LINE}
diff --git a/bl2/bl2_el3.ld.S b/bl2/bl2_el3.ld.S
index 8c45d98..bc1794c 100644
--- a/bl2/bl2_el3.ld.S
+++ b/bl2/bl2_el3.ld.S
@@ -105,17 +105,7 @@
     __DATA_RAM_START__ = __DATA_START__;
     __DATA_RAM_END__ = __DATA_END__;
 
-    /*
-     * .rela.dyn needs to come after .data for the read-elf utility to parse
-     * this section correctly. Ensure 8-byte alignment so that the fields of
-     * RELA data structure are aligned.
-     */
-    . = ALIGN(8);
-    __RELA_START__ = .;
-    .rela.dyn . : {
-    } >RAM
-    __RELA_END__ = .;
-
+    RELA_SECTION >RAM
     STACK_SECTION >RAM
     BSS_SECTION >RAM
     XLAT_TABLE_SECTION >RAM
diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c
index 802c174..203e1d4 100644
--- a/bl2/bl2_main.c
+++ b/bl2/bl2_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
  */
@@ -14,6 +14,9 @@
 #include <common/debug.h>
 #include <drivers/auth/auth_mod.h>
 #include <drivers/console.h>
+#if MEASURED_BOOT
+#include <drivers/measured_boot/measured_boot.h>
+#endif
 #include <lib/extensions/pauth.h>
 #include <plat/common/platform.h>
 
@@ -88,14 +91,25 @@
 #if TRUSTED_BOARD_BOOT
 	/* Initialize authentication module */
 	auth_mod_init();
+
+#if MEASURED_BOOT
+	/* Initialize measured boot module */
+	measured_boot_init();
+
+#endif /* MEASURED_BOOT */
 #endif /* TRUSTED_BOARD_BOOT */
 
-	/* initialize boot source */
+	/* Initialize boot source */
 	bl2_plat_preload_setup();
 
 	/* Load the subsequent bootloader images. */
 	next_bl_ep_info = bl2_load_images();
 
+#if MEASURED_BOOT
+	/* Finalize measured boot */
+	measured_boot_finish();
+#endif /* MEASURED_BOOT */
+
 #if !BL2_AT_EL3
 #ifndef __aarch64__
 	/*
diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S
index 11e86a3..5026500 100644
--- a/bl31/bl31.ld.S
+++ b/bl31/bl31.ld.S
@@ -115,17 +115,7 @@
     __RW_START__ = . ;
 
     DATA_SECTION >RAM
-
-    /*
-     * .rela.dyn needs to come after .data for the read-elf utility to parse
-     * this section correctly. Ensure 8-byte alignment so that the fields of
-     * RELA data structure are aligned.
-     */
-    . = ALIGN(8);
-    __RELA_START__ = .;
-    .rela.dyn . : {
-    } >RAM
-    __RELA_END__ = .;
+    RELA_SECTION >RAM
 
 #ifdef BL31_PROGBITS_LIMIT
     ASSERT(. <= BL31_PROGBITS_LIMIT, "BL31 progbits has exceeded its limit.")
diff --git a/bl32/tsp/tsp.ld.S b/bl32/tsp/tsp.ld.S
index bdcd2cf..d86ae55 100644
--- a/bl32/tsp/tsp.ld.S
+++ b/bl32/tsp/tsp.ld.S
@@ -71,17 +71,7 @@
     __RW_START__ = . ;
 
     DATA_SECTION >RAM
-
-    /*
-     * .rela.dyn needs to come after .data for the read-elf utility to parse
-     * this section correctly. Ensure 8-byte alignment so that the fields of
-     * RELA data structure are aligned.
-     */
-    . = ALIGN(8);
-    __RELA_START__ = .;
-    .rela.dyn . : {
-    } >RAM
-    __RELA_END__ = .;
+    RELA_SECTION >RAM
 
 #ifdef TSP_PROGBITS_LIMIT
     ASSERT(. <= TSP_PROGBITS_LIMIT, "TSP progbits has exceeded its limit.")
diff --git a/common/fdt_wrappers.c b/common/fdt_wrappers.c
index 1901a20..5aad14e 100644
--- a/common/fdt_wrappers.c
+++ b/common/fdt_wrappers.c
@@ -341,3 +341,199 @@
 
 	return fdt_path_offset(dtb, path);
 }
+
+
+/*******************************************************************************
+ * Only devices which are direct children of root node use CPU address domain.
+ * All other devices use addresses that are local to the device node and cannot
+ * directly used by CPU. Device tree provides an address translation mechanism
+ * through "ranges" property which provides mappings from local address space to
+ * parent address space. Since a device could be a child of a child node to the
+ * root node, there can be more than one level of address translation needed to
+ * map the device local address space to CPU address space.
+ * fdtw_translate_address() API performs address translation of a local address
+ * to a global address with help of various helper functions.
+ ******************************************************************************/
+
+static bool fdtw_xlat_hit(const uint32_t *value, int child_addr_size,
+		int parent_addr_size, int range_size, uint64_t base_address,
+		uint64_t *translated_addr)
+{
+	uint64_t local_address, parent_address, addr_range;
+
+	local_address = fdt_read_prop_cells(value, child_addr_size);
+	parent_address = fdt_read_prop_cells(value + child_addr_size,
+				parent_addr_size);
+	addr_range = fdt_read_prop_cells(value + child_addr_size +
+				parent_addr_size,
+				range_size);
+	VERBOSE("DT: Address %llx mapped to %llx with range %llx\n",
+		local_address, parent_address, addr_range);
+
+	/* Perform range check */
+	if ((base_address < local_address) ||
+		(base_address >= local_address + addr_range)) {
+		return false;
+	}
+
+	/* Found hit for the addr range that needs to be translated */
+	*translated_addr = parent_address + (base_address - local_address);
+	VERBOSE("DT: child address %llx mapped to %llx in parent bus\n",
+			local_address, parent_address);
+	return true;
+}
+
+#define ILLEGAL_ADDR	ULL(~0)
+
+static uint64_t fdtw_search_all_xlat_entries(const void *dtb,
+				const struct fdt_property *ranges_prop,
+				int local_bus, uint64_t base_address)
+{
+	uint64_t translated_addr;
+	const uint32_t *next_entry;
+	int parent_bus_node, nxlat_entries, length;
+	int self_addr_cells, parent_addr_cells, self_size_cells, ncells_xlat;
+
+	/*
+	 * The number of cells in one translation entry in ranges is the sum of
+	 * the following values:
+	 * self#address-cells + parent#address-cells + self#size-cells
+	 * Ex: the iofpga ranges property has one translation entry with 4 cells
+	 * They represent iofpga#addr-cells + motherboard#addr-cells + iofpga#size-cells
+	 *              = 1                 + 2                      + 1
+	 */
+
+	parent_bus_node = fdt_parent_offset(dtb, local_bus);
+	self_addr_cells = fdt_address_cells(dtb, local_bus);
+	self_size_cells = fdt_size_cells(dtb, local_bus);
+	parent_addr_cells = fdt_address_cells(dtb, parent_bus_node);
+
+	/* Number of cells per translation entry i.e., mapping */
+	ncells_xlat = self_addr_cells + parent_addr_cells + self_size_cells;
+
+	assert(ncells_xlat > 0);
+
+	/*
+	 * Find the number of translations(mappings) specified in the current
+	 * `ranges` property. Note that length represents number of bytes and
+	 * is stored in big endian mode.
+	 */
+	length = fdt32_to_cpu(ranges_prop->len);
+	nxlat_entries = (length/sizeof(uint32_t))/ncells_xlat;
+
+	assert(nxlat_entries > 0);
+
+	next_entry = (const uint32_t *)ranges_prop->data;
+
+	/* Iterate over the entries in the "ranges" */
+	for (int i = 0; i < nxlat_entries; i++) {
+		if (fdtw_xlat_hit(next_entry, self_addr_cells,
+				parent_addr_cells, self_size_cells, base_address,
+				&translated_addr)){
+			return translated_addr;
+		}
+		next_entry = next_entry + ncells_xlat;
+	}
+
+	INFO("DT: No translation found for address %llx in node %s\n",
+		base_address, fdt_get_name(dtb, local_bus, NULL));
+	return ILLEGAL_ADDR;
+}
+
+
+/*******************************************************************************
+ * address mapping needs to be done recursively starting from current node to
+ * root node through all intermediate parent nodes.
+ * Sample device tree is shown here:
+
+smb@0,0 {
+	compatible = "simple-bus";
+
+	#address-cells = <2>;
+	#size-cells = <1>;
+	ranges = <0 0 0 0x08000000 0x04000000>,
+		 <1 0 0 0x14000000 0x04000000>,
+		 <2 0 0 0x18000000 0x04000000>,
+		 <3 0 0 0x1c000000 0x04000000>,
+		 <4 0 0 0x0c000000 0x04000000>,
+		 <5 0 0 0x10000000 0x04000000>;
+
+	motherboard {
+		arm,v2m-memory-map = "rs1";
+		compatible = "arm,vexpress,v2m-p1", "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges;
+
+		iofpga@3,00000000 {
+			compatible = "arm,amba-bus", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 3 0 0x200000>;
+			v2m_serial1: uart@a0000 {
+				compatible = "arm,pl011", "arm,primecell";
+				reg = <0x0a0000 0x1000>;
+				interrupts = <0 6 4>;
+				clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+				clock-names = "uartclk", "apb_pclk";
+		};
+	};
+};
+
+ * As seen above, there are 3 levels of address translations needed. An empty
+ * `ranges` property denotes identity mapping (as seen in `motherboard` node).
+ * Each ranges property can map a set of child addresses to parent bus. Hence
+ * there can be more than 1 (translation) entry in the ranges property as seen
+ * in the `smb` node which has 6 translation entries.
+ ******************************************************************************/
+
+/* Recursive implementation */
+uint64_t fdtw_translate_address(const void *dtb, int node,
+				uint64_t base_address)
+{
+	int length, local_bus_node;
+	const char *node_name;
+	uint64_t global_address;
+
+	local_bus_node = fdt_parent_offset(dtb, node);
+	node_name = fdt_get_name(dtb, local_bus_node, NULL);
+
+	/*
+	 * In the example given above, starting from the leaf node:
+	 * uart@a000 represents the current node
+	 * iofpga@3,00000000 represents the local bus
+	 * motherboard represents the parent bus
+	 */
+
+	/* Read the ranges property */
+	const struct fdt_property *property = fdt_get_property(dtb,
+					local_bus_node, "ranges", &length);
+
+	if (property == NULL) {
+		if (local_bus_node == 0) {
+			/*
+			 * root node doesn't have range property as addresses
+			 * are in CPU address space.
+			 */
+			return base_address;
+		}
+		INFO("DT: Couldn't find ranges property in node %s\n",
+			node_name);
+		return ILLEGAL_ADDR;
+	} else if (length == 0) {
+		/* empty ranges indicates identity map to parent bus */
+		return fdtw_translate_address(dtb, local_bus_node, base_address);
+	}
+
+	VERBOSE("DT: Translation lookup in node %s at offset %d\n", node_name,
+		local_bus_node);
+	global_address = fdtw_search_all_xlat_entries(dtb, property,
+				local_bus_node, base_address);
+
+	if (global_address == ILLEGAL_ADDR) {
+		return ILLEGAL_ADDR;
+	}
+
+	/* Translate the local device address recursively */
+	return fdtw_translate_address(dtb, local_bus_node, global_address);
+}
diff --git a/docs/about/features.rst b/docs/about/features.rst
index 7c73952..964cb25 100644
--- a/docs/about/features.rst
+++ b/docs/about/features.rst
@@ -108,8 +108,8 @@
 
 -  Refinements to Position Independent Executable (PIE) support.
 
--  Continued support for the draft SPCI specification, to enable the use of
-   secure partition management in the secure world.
+-  Continued support for the PSA FF-A v1.0 (formally known as SPCI) specification, to enable the
+   use of secure partition management in the secure world.
 
 -  Documentation enhancements.
 
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index d6fafe4..a628704 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -21,7 +21,7 @@
 :G: `soby-mathew`_
 :M: Sandrine Bailleux <sandrine.bailleux@arm.com>
 :G: `sandrine-bailleux-arm`_
-:M: Alexei Fedorov <alexei.fedorov@arm.com>
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
 :G: `AlexeiFedorov`_
 :M: Manish Pandey <manish.pandey2@arm.com>
 :G: `manish-pandey-arm`_
@@ -33,6 +33,18 @@
 :G: `bipinravi-arm`_
 :M: Joanna Farley <joanna.farley@arm.com>
 :G: `joannafarley-arm`_
+:M: Julius Werner <jwerner@chromium.org>
+:G: `jwerner-chromium`_
+:M: Varun Wadekar <vwadekar@nvidia.com>
+:G: `vwadekar`_
+:M: Andre Przywara <andre.przywara@arm.com>
+:G: `Andre-ARM`_
+:M: Lauren Wehrmeister <Lauren.Wehrmeister@arm.com>
+:G: `laurenw-arm`_
+:M: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
+:G: `madhukar-Arm`_
+:M: Raghu Krishnamurthy <raghu.ncstate@icloud.com>
+:G: `raghuncstate`_
 
 
 .. _code owners:
@@ -43,14 +55,57 @@
 Core Code
 ~~~~~~~~~
 
-.. note::
-   This section is incomplete right now.
-
 Armv7-A architecture port
 ^^^^^^^^^^^^^^^^^^^^^^^^^
 :M: Etienne Carriere <etienne.carriere@linaro.org>
 :G: `etienne-lms`_
 
+Build Definitions for CMake Build System
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:M: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
+:G: `javieralso-arm`_
+:M: Jack Bond-Preston <Jack.Bond-Preston@arm.com>
+:G: `jackbondpreston-arm`_
+:F: /
+
+Software Delegated Exception Interface (SDEI)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:M: Mark Dykes <mark.dykes@arm.com>
+:G: `mardyk01`_
+:M: John Powell <John.Powell@arm.com>
+:G: `john-powell-arm`_
+:F: services/std_svc/sdei/
+
+Trusted Boot
+^^^^^^^^^^^^
+:M: Sandrine Bailleux <sandrine.bailleux@arm.com>
+:G: `sandrine-bailleux-arm`_
+:M: Manish Pandey <manish.pandey2@arm.com>
+:G: `manish-pandey-arm`_
+:M: Manish Badarkhe <manish.badarkhe@arm.com>
+:G: `ManishVB-Arm`_
+:F: drivers/auth/
+
+Secure Partition Manager (SPM)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:M: Olivier Deprez <olivier.deprez@arm.com>
+:G: `odeprez`_
+:M: Manish Pandey <manish.pandey2@arm.com>
+:G: `manish-pandey-arm`_
+:M: Maksims Svecovs <maksims.svecovs@arm.com>
+:G: `max-shvetsov`_
+:M: Joao Alves <Joao.Alves@arm.com>
+:G: `J-Alves`_
+:F: services/std_svc/spm\*
+
+Exception Handling Framework (EHF)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:M: Manish Badarkhe <manish.badarkhe@arm.com>
+:G: `ManishVB-Arm`_
+:M: John Powell <John.Powell@arm.com>
+:G: `john-powell-arm`_
+:F: bl31/ehf.c
+
 
 Drivers, Libraries and Framework Code
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -84,6 +139,161 @@
 :F: include/drivers/ufs.h
 :F: include/drivers/synopsys/dw_mmc.h
 
+Power State Coordination Interface (PSCI)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:M: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
+:G: `javieralso-arm`_
+:M: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
+:G: `madhukar-Arm`_
+:M: Lauren Wehrmeister <Lauren.Wehrmeister@arm.com>
+:G: `laurenw-arm`_
+:M: Zelalem Aweke <Zelalem.Aweke@arm.com>
+:G: `zelalem-aweke`_
+:F: lib/psci/
+
+DebugFS
+^^^^^^^
+:M: Olivier Deprez <olivier.deprez@arm.com>
+:G: `odeprez`_
+:F: lib/debugfs/
+
+Firmware Configuration Framework (FCONF)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:M: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
+:G: `madhukar-Arm`_
+:M: Manish Badarkhe <manish.badarkhe@arm.com>
+:G: `ManishVB-Arm`_
+:M: Lauren Wehrmeister <Lauren.Wehrmeister@arm.com>
+:G: `laurenw-arm`_
+:F: lib/fconf/
+
+Performance Measurement Framework (PMF)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:M: Joao Alves <Joao.Alves@arm.com>
+:G: `J-Alves`_
+:M: Jimmy Brisson <Jimmy.Brisson@arm.com>
+:G: `theotherjimmy`_
+:F: lib/pmf/
+
+Arm CPU libraries
+^^^^^^^^^^^^^^^^^
+:M: Lauren Wehrmeister <Lauren.Wehrmeister@arm.com>
+:G: `laurenw-arm`_
+:M: John Powell <John.Powell@arm.com>
+:G: `john-powell-arm`_
+:F: lib/cpus/
+
+Reliability Availability Serviceabilty (RAS) framework
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:M: Olivier Deprez <olivier.deprez@arm.com>
+:G: `odeprez`_
+:M: Manish Pandey <manish.pandey2@arm.com>
+:G: `manish-pandey-arm`_
+:F: lib/extensions/ras/
+
+Activity Monitors Unit (AMU) extensions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
+:G: `AlexeiFedorov`_
+:F: lib/extensions/amu/
+
+Memory Partitioning And Monitoring (MPAM) extensions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:M: Zelalem Aweke <Zelalem.Aweke@arm.com>
+:G: `zelalem-aweke`_
+:M: Jimmy Brisson <Jimmy.Brisson@arm.com>
+:G: `theotherjimmy`_
+:F: lib/extensions/mpam/
+
+Pointer Authentication (PAuth) and Branch Target Identification (BTI) extensions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
+:G: `AlexeiFedorov`_
+:M: Zelalem Aweke <Zelalem.Aweke@arm.com>
+:G: `zelalem-aweke`_
+:F: lib/extensions/pauth/
+
+Statistical Profiling Extension (SPE)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:M: Zelalem Aweke <Zelalem.Aweke@arm.com>
+:G: `zelalem-aweke`_
+:M: Jimmy Brisson <Jimmy.Brisson@arm.com>
+:G: `theotherjimmy`_
+:F: lib/extensions/spe/
+
+Scalable Vector Extension (SVE)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:M: Jimmy Brisson <Jimmy.Brisson@arm.com>
+:G: `theotherjimmy`_
+:F: lib/extensions/sve/
+
+Standard C library
+^^^^^^^^^^^^^^^^^^
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
+:G: `AlexeiFedorov`_
+:M: John Powell <John.Powell@arm.com>
+:G: `john-powell-arm`_
+:F: lib/libc/
+
+Library At ROM (ROMlib)
+^^^^^^^^^^^^^^^^^^^^^^^
+:M: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
+:G: `madhukar-Arm`_
+:F: lib/romlib/
+
+Translation tables (``xlat_tables``) library
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:M: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
+:G: `javieralso-arm`_
+:M: Joao Alves <Joao.Alves@arm.com>
+:G: `J-Alves`_
+:F: lib/xlat\_tables_\*/
+
+IO abstraction layer
+^^^^^^^^^^^^^^^^^^^^
+:M: Manish Pandey <manish.pandey2@arm.com>
+:G: `manish-pandey-arm`_
+:M: Olivier Deprez <olivier.deprez@arm.com>
+:G: `odeprez`_
+:F: drivers/io/
+
+GIC driver
+^^^^^^^^^^
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
+:G: `AlexeiFedorov`_
+:M: Manish Pandey <manish.pandey2@arm.com>
+:G: `manish-pandey-arm`_
+:M: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
+:G: `madhukar-Arm`_
+:M: Olivier Deprez <olivier.deprez@arm.com>
+:G: `odeprez`_
+:F: drivers/arm/gic/
+
+Libfdt wrappers
+^^^^^^^^^^^^^^^
+:M: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
+:G: `madhukar-Arm`_
+:M: Manish Badarkhe <manish.badarkhe@arm.com>
+:G: `ManishVB-Arm`_
+:F: common/fdt_wrappers.c
+
+Firmware Encryption Framework
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:M: Sumit Garg <sumit.garg@linaro.org>
+:G: `b49020`_
+:F: drivers/io/io_encrypted.c
+:F: include/drivers/io/io_encrypted.h
+:F: include/tools_share/firmware_encrypted.h
+
+Measured Boot
+^^^^^^^^^^^^^
+:M: Alexei Fedorov <Alexei.Fedorov@arm.com>
+:G: `AlexeiFedorov`_
+:M: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
+:G: `javieralso-arm`_
+:F: drivers/measured_boot
+:F: include/drivers/measured_boot
+:F: plat/arm/board/fvp/fvp_measured_boot.c
 
 Platform Ports
 ~~~~~~~~~~~~~~
@@ -127,6 +337,14 @@
 :F: docs/plat/meson-axg.rst
 :F: plat/amlogic/axg/
 
+Arm FPGA platform port
+^^^^^^^^^^^^^^^^^^^^^^
+:M: Andre Przywara <andre.przywara@arm.com>
+:G: `Andre-ARM`_
+:M: Javier Almansa Sobrino <Javier.AlmansaSobrino@arm.com>
+:G: `javieralso-arm`_
+:F: plat/arm/board/arm_fpga
+
 Arm System Guidance for Infrastructure / Mobile FVP platforms
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 :M: Nariman Poushin <nariman.poushin@linaro.org>
@@ -318,8 +536,8 @@
 :F: plat/xilinx/
 
 
-Secure Payload Dispatchers
-~~~~~~~~~~~~~~~~~~~~~~~~~~
+Secure Payloads and Dispatchers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 OP-TEE dispatcher
 ^^^^^^^^^^^^^^^^^
@@ -338,6 +556,46 @@
 :F: services/spd/tlkd/
 :F: services/spd/trusty/
 
+Test Secure Payload (TSP)
+^^^^^^^^^^^^^^^^^^^^^^^^^
+:M: Manish Badarkhe <manish.badarkhe@arm.com>
+:G: `ManishVB-Arm`_
+:F: bl32/tsp/
+:F: services/spd/tspd/
+
+Tools
+~~~~~
+
+Fiptool
+^^^^^^^
+:M: Joao Alves <Joao.Alves@arm.com>
+:G: `J-Alves`_
+:F: tools/fiptool/
+
+Cert_create tool
+^^^^^^^^^^^^^^^^
+:M: Sandrine Bailleux <sandrine.bailleux@arm.com>
+:G: `sandrine-bailleux-arm`_
+:F: tools/cert_create/
+
+Encrypt_fw tool
+^^^^^^^^^^^^^^^
+:M: Sumit Garg <sumit.garg@linaro.org>
+:G: `b49020`_
+:F: tools/encrypt_fw/
+
+Sptool
+^^^^^^
+:M: Manish Pandey <manish.pandey2@arm.com>
+:G: `manish-pandey-arm`_
+:F: tools/sptool/
+
+Build system
+^^^^^^^^^^^^
+:M: Manish Pandey <manish.pandey2@arm.com>
+:G: `manish-pandey-arm`_
+:F: Makefile
+:F: make_helpers/
 
 .. _AlexeiFedorov: https://github.com/AlexeiFedorov
 .. _Andre-ARM: https://github.com/Andre-ARM
@@ -380,5 +638,16 @@
 .. _odeprez: https://github.com/odeprez
 .. _bipinravi-arm: https://github.com/bipinravi-arm
 .. _joannafarley-arm: https://github.com/joannafarley-arm
+.. _ManishVB-Arm: https://github.com/ManishVB-Arm
+.. _max-shvetsov: https://github.com/max-shvetsov
+.. _javieralso-arm: https://github.com/javieralso-arm
+.. _laurenw-arm: https://github.com/laurenw-arm
+.. _zelalem-aweke: https://github.com/zelalem-aweke
+.. _theotherjimmy: https://github.com/theotherjimmy
+.. _J-Alves: https://github.com/J-Alves
+.. _madhukar-Arm: https://github.com/madhukar-Arm
+.. _john-powell-arm: https://github.com/john-powell-arm
+.. _raghuncstate: https://github.com/raghuncstate
+.. _jackbondpreston-arm: https://github.com/jackbondpreston-arm
 
 .. _Project Maintenance Process: https://developer.trustedfirmware.org/w/collaboration/project-maintenance-process/
diff --git a/docs/components/cot-binding.rst b/docs/components/cot-binding.rst
new file mode 100644
index 0000000..46915db
--- /dev/null
+++ b/docs/components/cot-binding.rst
@@ -0,0 +1,328 @@
+Chain of trust bindings
+=======================
+
+The device tree allows to describe the chain of trust with the help of
+'cot' node which contain 'manifests' and 'images' as sub-nodes.
+'manifests' and 'images' nodes contains number of sub-nodes (i.e. 'certificate'
+and 'image' nodes) mentioning properties of the certificate and image respectively.
+
+Also, device tree describes 'non-volatile-counters' node which contains number of
+sub-nodes mentioning properties of all non-volatile-counters used in the chain of trust.
+
+cot
+------------------------------------------------------------------
+This is root node which contains 'manifests' and 'images' as sub-nodes
+
+
+Manifests and Certificate node bindings definition
+----------------------------------------------------------------
+
+- Manifests node
+        Description: Container of certificate nodes.
+
+        PROPERTIES
+
+        - compatible:
+                Usage: required
+
+                Value type: <string>
+
+                Definition: must be "arm, cert-descs"
+
+- Certificate node
+        Description:
+
+        Describes certificate properties which are used
+        during the authentication process.
+
+        PROPERTIES
+
+        - root-certificate
+               Usage:
+
+               Required for the certificate with no parent.
+               In other words, certificates which are validated
+               using root of trust public key.
+
+               Value type: <boolean>
+
+        - image-id
+                Usage: Required for every certificate with unique id.
+
+                Value type: <u32>
+
+        - parent
+                Usage:
+
+                It refers to their parent image, which typically contains
+                information to authenticate the certificate.
+                This property is required for all non-root certificates.
+
+                This property is not required for root-certificates
+                as root-certificates are validated using root of trust
+                public key provided by platform.
+
+                Value type: <phandle>
+
+        - signing-key
+                Usage:
+
+                This property is used to refer public key node present in
+                parent certificate node and it is required property for all
+                non-root certificates which are authenticated using public-key
+                present in parent certificate.
+
+                This property is not required for root-certificates
+                as root-certificates are validated using root of trust
+                public key provided by platform.
+
+                Value type: <phandle>
+
+        - antirollback-counter
+                Usage:
+
+                This property is used by all certificates which are
+                protected against rollback attacks using a non-volatile
+                counter and it is an optional property.
+
+                This property is used to refer one of the non-volatile
+                counter sub-node present in 'non-volatile counters' node.
+
+                Value type: <phandle>
+
+
+        SUBNODES
+            - Description:
+
+              Hash and public key information present in the certificate
+              are shown by these nodes.
+
+            - public key node
+                  Description: Provide public key information in the certificate.
+
+                  PROPERTIES
+
+                  - oid
+                     Usage:
+
+                     This property provides the Object ID of public key
+                     provided in the certificate which the help of which
+                     public key information can be extracted.
+
+                     Value type: <string>
+
+            - hash node
+                 Description: Provide the hash information in the certificate.
+
+                 PROPERTIES
+
+                 - oid
+                     Usage:
+
+                     This property provides the Object ID of hash provided in
+                     the certificate which the help of which hash information
+                     can be extracted.
+
+                     Value type: <string>
+
+Example:
+
+.. code:: c
+
+   cot {
+      manifests {
+         compatible = "arm, cert-descs”
+
+         trusted-key-cert: trusted-key-cert {
+            root-certificate;
+            image-id = <TRUSTED_KEY_CERT_ID>;
+            antirollback-counter = <&trusted_nv_counter>;
+
+            trusted-world-pk: trusted-world-pk {
+               oid = TRUSTED_WORLD_PK_OID;
+            };
+            non-trusted-world-pk: non-trusted-world-pk {
+               oid = NON_TRUSTED_WORLD_PK_OID;
+            };
+         };
+
+         scp_fw_key_cert: scp_fw_key_cert {
+            image-id = <SCP_FW_KEY_CERT_ID>;
+            parent = <&trusted-key-cert>;
+            signing-key = <&trusted_world_pk>;
+            antirollback-counter = <&trusted_nv_counter>;
+
+            scp_fw_content_pk: scp_fw_content_pk {
+               oid = SCP_FW_CONTENT_CERT_PK_OID;
+            };
+         };
+         .
+         .
+         .
+
+         next-certificate {
+
+         };
+      };
+   };
+
+Images and Image node bindings definition
+-----------------------------------------
+
+- Images node
+        Description: Container of image nodes
+
+        PROPERTIES
+
+        - compatible:
+                Usage: required
+
+                Value type: <string>
+
+                Definition: must be "arm, img-descs"
+
+- Image node
+        Description:
+
+        Describes image properties which will be used during
+        authentication process.
+
+        PROPERTIES
+
+        - image-id
+                Usage: Required for every image with unique id.
+
+                Value type: <u32>
+
+        - parent
+                Usage:
+
+                Required for every image to provide a reference to
+                its parent image, which contains the necessary information
+                to authenticate it.
+
+                Value type: <phandle>
+
+        - hash
+                Usage:
+
+                Required for all images which are validated using
+                hash method. This property is used to refer hash
+                node present in parent certificate node.
+
+                Value type: <phandle>
+
+                Note:
+
+                Currently, all images are validated using 'hash'
+                method. In future, there may be multiple methods can
+                be used to validate the image.
+
+Example:
+
+.. code:: c
+
+   cot {
+      images {
+         compatible = "arm, img-descs";
+
+         scp_bl2_image {
+            image-id = <SCP_BL2_IMAGE_ID>;
+            parent = <&scp_fw_content_cert>;
+            hash = <&scp_fw_hash>;
+         };
+
+         .
+         .
+         .
+
+         next-img {
+
+         };
+      };
+   };
+
+non-volatile counter node binding definition
+--------------------------------------------
+
+- non-volatile counters node
+        Description: Contains properties for non-volatile counters.
+
+        PROPERTIES
+
+        - compatible:
+                Usage: required
+
+                Value type: <string>
+
+                Definition: must be "arm, non-volatile-counter"
+
+        - #address-cells
+                Usage: required
+
+                Value type: <u32>
+
+                Definition:
+
+                Must be set according to address size
+                of non-volatile counter register
+
+        - #size-cells
+                Usage: required
+
+                Value type: <u32>
+
+                Definition: must be set to 0
+
+        SUBNODE
+            - counters node
+                    Description: Contains various non-volatile counters present in the platform.
+
+            PROPERTIES
+
+                - reg
+                    Usage:
+
+                    Register base address of non-volatile counter and it is required
+                    property.
+
+                    Value type: <u32>
+
+                - oid
+                    Usage:
+
+                    This property provides the Object ID of non-volatile counter
+                    provided in the certificate and it is required property.
+
+                    Value type: <string>
+
+Example:
+Below is non-volatile counters example for ARM platform
+
+.. code:: c
+
+   non-volatile-counters {
+        compatible = "arm, non-volatile-counter";
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        counters {
+            trusted-nv-counter: trusted_nv_counter {
+                reg = <TFW_NVCTR_BASE>;
+                oid = TRUSTED_FW_NVCOUNTER_OID;
+            };
+            non_trusted_nv_counter: non_trusted_nv_counter {
+                reg = <NTFW_CTR_BASE>;
+                oid = NON_TRUSTED_FW_NVCOUNTER_OID;
+
+            };
+        };
+   };
+
+Future update to chain of trust binding
+---------------------------------------
+
+This binding document needs to be revisited to generalise some terminologies
+which are currently specific to X.509 certificates for e.g. Object IDs.
+
+*Copyright (c) 2020, Arm Limited. All rights reserved.*
diff --git a/docs/components/debugfs-design.rst b/docs/components/debugfs-design.rst
index 2096bdb..2536515 100644
--- a/docs/components/debugfs-design.rst
+++ b/docs/components/debugfs-design.rst
@@ -80,8 +80,8 @@
 The communication with the 9p layer in BL31 is made through an SMC conduit
 (`SMC Calling Convention`_), 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.
+data on a read operation. Refer to :ref:`ARM SiP Services <arm sip services>`
+for a description of the SMC interface.
 
 Security considerations
 -----------------------
diff --git a/docs/components/exception-handling.rst b/docs/components/exception-handling.rst
index 4cca5f4..6f223c6 100644
--- a/docs/components/exception-handling.rst
+++ b/docs/components/exception-handling.rst
@@ -10,13 +10,9 @@
 -  Asynchronous External Aborts
 
 |TF-A|'s handling of synchronous ``SMC`` exceptions raised from lower ELs is
-described in the `Firmware Design document`__. However, the |EHF| changes the
-semantics of `interrupt handling`__ and `synchronous exceptions`__ other than
-SMCs.
-
-.. __: firmware-design.rst#handling-an-smc
-.. __: `Interrupt handling`_
-.. __: `Effect on SMC calls`_
+described in the :ref:`Firmware Design document <handling-an-smc>`. However, the
+|EHF| changes the semantics of `Interrupt handling`_ and :ref:`synchronous
+exceptions <Effect on SMC calls>` other than SMCs.
 
 The |EHF| is selected by setting the build option ``EL3_EXCEPTION_HANDLING`` to
 ``1``, and is only available for AArch64 systems.
@@ -77,10 +73,9 @@
 independently depending on platform choice and the nature of the exception
 received.
 
-.. [#spd] Not to be confused with `Secure Payload Dispatcher`__, which is an
-   EL3 component that operates in EL3 on behalf of Secure OS.
-
-.. __: firmware-design.rst#secure-el1-payloads-and-dispatchers
+.. [#spd] Not to be confused with :ref:`Secure Payload Dispatcher
+   <firmware_design_sel1_spd>`, which is an EL3 component that operates in EL3
+   on behalf of Secure OS.
 
 The role of Exception Handling Framework
 ----------------------------------------
@@ -139,6 +134,8 @@
 the case; for non-interrupts, the |EHF| monitors and asserts this. See
 `Transition of priority levels`_.
 
+.. _interrupt-handling:
+
 Interrupt handling
 ------------------
 
@@ -151,15 +148,12 @@
    sufficient priority are signalled as FIQs, and therefore will be routed to
    EL3. As a result, S-EL1 software cannot expect to handle Non-secure
    interrupts at S-EL1. Essentially, this deprecates the routing mode described
-   as `CSS=0, TEL3=0`__.
-
-   .. __: interrupt-framework-design.rst#el3-interrupts
+   as :ref:`CSS=0, TEL3=0 <EL3 interrupts>`.
 
    In order for S-EL1 software to handle Non-secure interrupts while having
    |EHF| enabled, the dispatcher must adopt a model where Non-secure interrupts
-   are received at EL3, but are then `synchronously`__ handled over to S-EL1.
-
-   .. __: interrupt-framework-design.rst#secure-payload
+   are received at EL3, but are then :ref:`synchronously <sp-synchronous-int>`
+   handled over to S-EL1.
 
 -  On GICv2 systems, it's required that the build option ``GICV2_G0_FOR_EL3`` is
    set to ``1`` so that *Group 0* interrupts target EL3.
@@ -176,6 +170,8 @@
 
 Dispatchers are assigned interrupt priority levels in two steps:
 
+.. _Partitioning priority levels:
+
 Partitioning priority levels
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -237,12 +233,11 @@
 expresses the required levels of priority. It however doesn't choose interrupts
 nor program the required priority in GIC.
 
-The `Firmware Design guide`__ explains methods for configuring secure
-interrupts. |EHF| requires the platform to enumerate interrupt properties (as
-opposed to just numbers) of Secure interrupts. The priority of secure interrupts
-must match that as determined in the `Partitioning priority levels`_ section above.
-
-.. __: firmware-design.rst#configuring-secure-interrupts
+The :ref:`Firmware Design guide<configuring-secure-interrupts>` explains methods
+for configuring secure interrupts. |EHF| requires the platform to enumerate
+interrupt properties (as opposed to just numbers) of Secure interrupts. The
+priority of secure interrupts must match that as determined in the
+`Partitioning priority levels`_ section above.
 
 See `Limitations`_, and also refer to `Interrupt handling example`_ for
 illustration.
@@ -281,15 +276,13 @@
    typedef int (*ehf_handler_t)(uint32_t intr_raw, uint32_t flags, void *handle,
                    void *cookie);
 
-The parameters are as obtained from the top-level `EL3 interrupt handler`__.
+The parameters are as obtained from the top-level :ref:`EL3 interrupt handler
+<el3-runtime-firmware>`.
 
-.. __: interrupt-framework-design.rst#el3-runtime-firmware
-
-The `SDEI dispatcher`__, for example, expects the platform to allocate two
-different priority levels—``PLAT_SDEI_CRITICAL_PRI``, and
-``PLAT_SDEI_NORMAL_PRI``—and registers the same handler to handle both levels.
-
-.. __: sdei.rst
+The :ref:`SDEI dispatcher<SDEI: Software Delegated Exception Interface>`, for
+example, expects the platform to allocate two different priority levels—
+``PLAT_SDEI_CRITICAL_PRI``, and ``PLAT_SDEI_NORMAL_PRI`` —and registers the
+same handler to handle both levels.
 
 Interrupt handling example
 --------------------------
@@ -365,16 +358,16 @@
 
 See also the `Build-time flow`_ and the `Run-time flow`_.
 
+.. _Activating and Deactivating priorities:
+
 Activating and Deactivating priorities
 --------------------------------------
 
 A priority level is said to be *active* when an exception of that priority is
 being handled: for interrupts, this is implied when the interrupt is
-acknowledged; for non-interrupt exceptions, such as SErrors or `SDEI explicit
-dispatches`__, this has to be done via calling ``ehf_activate_priority()``. See
-`Run-time flow`_.
-
-.. __: sdei.rst#explicit-dispatch-of-events
+acknowledged; for non-interrupt exceptions, such as SErrors or :ref:`SDEI
+explicit dispatches <explicit-dispatch-of-events>`, this has to be done via
+calling ``ehf_activate_priority()``. See `Run-time flow`_.
 
 Conversely, when the dispatcher has reached a logical resolution for the cause
 of the exception, the corresponding priority level ought to be deactivated. As
@@ -453,6 +446,8 @@
 
 If these are violated, a panic will result.
 
+.. _Effect on SMC calls:
+
 Effect on SMC calls
 -------------------
 
@@ -538,10 +533,8 @@
    interrupts belonging to different dispatchers.
 
 #. The |EHF|, during its initialisation, registers a top-level interrupt handler
-   with the `Interrupt Management Framework`__ for EL3 interrupts. This also
-   results in setting the routing bits in ``SCR_EL3``.
-
-   .. __: interrupt-framework-design.rst#el3-runtime-firmware
+   with the :ref:`Interrupt Management Framework<el3-runtime-firmware>` for EL3
+   interrupts. This also results in setting the routing bits in ``SCR_EL3``.
 
 #. When an interrupt belonging to a dispatcher fires, GIC raises an EL3/Group 0
    interrupt, and is taken to EL3.
diff --git a/docs/components/fconf/index.rst b/docs/components/fconf/index.rst
index 0da56ec..9020633 100644
--- a/docs/components/fconf/index.rst
+++ b/docs/components/fconf/index.rst
@@ -49,8 +49,10 @@
 configuration properties which is usually a device tree file.
 
 Example:
+ - FW_CONFIG: properties related to base address, maximum size and image id
+   of other DTBs etc.
  - TB_FW: properties related to trusted firmware such as IO policies,
-   base address of other DTBs, mbedtls heap info etc.
+   mbedtls heap info etc.
  - HW_CONFIG: properties related to hardware configuration of the SoC
    such as topology, GIC controller, PSCI hooks, CPU ID etc.
 
@@ -88,9 +90,10 @@
 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).
+The ``fconf_load_config(image_id)`` must be called to load fw_config and
+tb_fw_config devices 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
 
diff --git a/docs/components/index.rst b/docs/components/index.rst
index e3ce614..ffeef80 100644
--- a/docs/components/index.rst
+++ b/docs/components/index.rst
@@ -12,10 +12,13 @@
    exception-handling
    fconf/index
    firmware-update
+   measured_boot/index
    platform-interrupt-controller-API
    ras
    romlib-design
    sdei
-   secure-partition-manager-design
-   spci-manifest-binding
+   secure-partition-manager
+   secure-partition-manager-mm
+   psa-ffa-manifest-binding
    xlat-tables-lib-v2-design
+   cot-binding
diff --git a/docs/components/measured_boot/event_log.rst b/docs/components/measured_boot/event_log.rst
new file mode 100644
index 0000000..5347dcc
--- /dev/null
+++ b/docs/components/measured_boot/event_log.rst
@@ -0,0 +1,35 @@
+DTB binding for Event Log properties
+====================================
+
+This document describes the device tree format of Event Log properties.
+These properties are not related to a specific platform and can be queried
+from common code.
+
+Dynamic configuration for Event Log
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Measured Boot driver expects a *tpm_event_log* node with the following field
+in 'nt_fw_config' and 'tsp_fw_config' DTS files:
+
+- compatible [mandatory]
+   - value type: <string>
+   - Must be the string "arm,tpm_event_log".
+
+Then a list of properties representing Event Log configuration, which
+can be used by Measured Boot driver. Each property is named according
+to the information it contains:
+
+- tpm_event_log_sm_addr [fvp_nt_fw_config.dts with OP-TEE]
+    - value type: <u64>
+    - Event Log base address in secure memory.
+
+Note. Currently OP-TEE does not support reading DTBs from Secure memory
+and this property should be removed when this feature is supported.
+
+- tpm_event_log_addr [mandatory]
+    - value type: <u64>
+    - Event Log base address in non-secure memory.
+
+- tpm_event_log_size [mandatory]
+    - value type: <u32>
+    - Event Log size.
diff --git a/docs/components/measured_boot/index.rst b/docs/components/measured_boot/index.rst
new file mode 100644
index 0000000..e7f2634
--- /dev/null
+++ b/docs/components/measured_boot/index.rst
@@ -0,0 +1,12 @@
+Measured Boot Driver (MBD)
+==========================
+
+.. _measured-boot-document:
+
+Properties binding information
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. toctree::
+   :maxdepth: 1
+
+   event_log
diff --git a/docs/components/platform-interrupt-controller-API.rst b/docs/components/platform-interrupt-controller-API.rst
index 9d02f45..069c87b 100644
--- a/docs/components/platform-interrupt-controller-API.rst
+++ b/docs/components/platform-interrupt-controller-API.rst
@@ -286,6 +286,8 @@
 *Priority Mask Register*, and make sure memory updates are visible before
 potential trigger due to mask update.
 
+.. _plat_ic_get_interrupt_id:
+
 Function: unsigned int plat_ic_get_interrupt_id(unsigned int raw); [optional]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/docs/components/spci-manifest-binding.rst b/docs/components/psa-ffa-manifest-binding.rst
similarity index 83%
rename from docs/components/spci-manifest-binding.rst
rename to docs/components/psa-ffa-manifest-binding.rst
index 5848169..09894ae 100644
--- a/docs/components/spci-manifest-binding.rst
+++ b/docs/components/psa-ffa-manifest-binding.rst
@@ -1,49 +1,39 @@
-SPCI manifest binding to device tree
-====================================
+PSA FF-A manifest binding to device tree
+========================================
 
 This document defines the nodes and properties used to define a partition,
-according to the SPCI specification.
+according to the PSA FF-A specification.
 
 Version 1.0
 -----------
 
-spci-manifest-partition
-^^^^^^^^^^^^^^^^^^^^^^^
+Partition Properties
+^^^^^^^^^^^^^^^^^^^^
 
 - compatible [mandatory]
    - value type: <string>
-   - Must be the string "arm,spci-manifest-X.Y" which specifies the major and
-     minor versions fo the device tree binding for the SPCI manifest represented
+   - Must be the string "arm,ffa-manifest-X.Y" which specifies the major and
+     minor versions fo the device tree binding for the FFA manifest represented
      by this node. The minor number is incremented if the binding changes in a
      backwards compatible manner.
 
       - X is an integer representing the major version number of this document.
       - Y is an integer representing the minor version number of this document.
 
-- spci-version [mandatory]
+- ffa-version [mandatory]
    - value type: <u32>
    - Must be two 16 bits values (X, Y), concatenated as 31:16 -> X,
      15:0 -> Y, where:
 
-      - X is the major version of PSA-FF-A expected by the partition at the SPCI
+      - X is the major version of PSA-FF-A expected by the partition at the FFA
         instance it will execute.
-      - Y is the minor version of PSA-FF-A expected by the partition at the SPCI
+      - Y is the minor version of PSA-FF-A expected by the partition at the FFA
         instance it will execute.
 
 - uuid [mandatory]
    - value type: <prop-encoded-array>
    - An array consisting of 4 <u32> values, identifying the UUID of the service
      implemented by this partition. The UUID format is described in RFC 4122.
-     UUID can be shared by multiple instances of partitions that offer the same
-     service For example:
-
-      - If there are multiple instances of a Trusted OS, then the UUID can be
-        shared by all instances.
-      - The TEE driver in the HLOS can use the UUID with the
-        SPCI_PARTITION_INFO_GET interface to determine the:
-
-         - Number of Trusted OSs
-         - The partition ID of each instance of the Trusted OS
 
 - id
    - value type: <u32>
@@ -75,9 +65,6 @@
       - 0x0: EL1
       - 0x1: S_EL0
       - 0x2: S_EL1
-      - 0x3: EL2
-      - 0x4: Supervisor mode
-      - 0x5: Secure User mode
 
 - execution-state [mandatory]
    - value type: <u32>
@@ -104,7 +91,7 @@
 
       - 0x0: 4k
       - 0x1: 16k
-      - 0x2: 32k
+      - 0x2: 64k
 
 - boot-order
    - value type: <u32>
@@ -116,7 +103,7 @@
    - value type: "memory-regions" node
    - Specific "memory-regions" nodes that describe the RX/TX buffers expected
      by the partition.
-     The "compatible" must be the string "arm,spci-manifest-rx_tx-buffer".
+     The "compatible" must be the string "arm,ffa-manifest-rx_tx-buffer".
 
 - messaging-method [mandatory]
    - value type: <u32>
@@ -146,7 +133,7 @@
 - gp-register-num
    - value type: <u32>
    - Presence of this field indicates that the partition expects the
-     spci_init_info structure to be passed in via the specified general purpose
+     ffa_init_info structure to be passed in via the specified general purpose
      register.
      The field specifies the general purpose register number but not its width.
      The width is derived from the partition's execution state, as specified in
@@ -159,12 +146,12 @@
    - List of <u32> tuples, identifying the IDs this partition is acting as
      proxy for.
 
-memory-regions
+Memory Regions
 --------------
 
 - compatible [mandatory]
    - value type: <string>
-   - Must be the string "arm,spci-manifest-memory-regions".
+   - Must be the string "arm,ffa-manifest-memory-regions".
 
 - description
    - value type: <string>
@@ -177,26 +164,30 @@
 
 - attributes [mandatory]
    - value type: <u32>
-   - ?? TO DEFINE
+   - Mapping modes: ORed to get required permission
+
+      - 0x1: Read
+      - 0x2: Write
+      - 0x4: Execute
 
 - base-address
    - value type: <u64>
    - Base address of the region. The address must be aligned to the translation
      granule size.
      The address given may be a Physical Address (PA), Virtual Address (VA), or
-     Intermediate Physical Address (IPA). Refer to the SPCI specification for
+     Intermediate Physical Address (IPA). Refer to the FFA specification for
      more information on the restrictions around the address type.
      If the base address is omitted then the partition manager must map a memory
      region of the specified size into the partition's translation regime and
      then communicate the region properties (including the base address chosen
      by the partition manager) to the partition.
 
-device-regions
+Device Regions
 --------------
 
 - compatible [mandatory]
    - value type: <string>
-   - Must be the string "arm,spci-manifest-device-regions".
+   - Must be the string "arm,ffa-manifest-device-regions".
 
 - description
    - value type: <string>
@@ -213,7 +204,11 @@
 
 - attributes [mandatory]
    - value type: <u32>
-   - ?? TO DEFINE
+   - Mapping modes: ORed to get required permission
+
+     - 0x1: Read
+     - 0x2: Write
+     - 0x4: Execute
 
 - smmu-id
    - value type: <u32>
@@ -222,19 +217,18 @@
      upstream of. If the field is omitted then it is assumed that the device is
      not upstream of any SMMU.
 
-- stream-ids [mandatory]
+- stream-ids
    - value type: <prop-encoded-array>
    - A list of (id, mem-manage) pair, where:
 
       - id: A unique <u32> value amongst all devices assigned to the partition.
-      - mem-manage: A <u32> value used in memory management operations.
 
 - interrupts [mandatory]
    - value type: <prop-encoded-array>
    - A list of (id, attributes) pair describing the device interrupts, where:
 
       - id: The <u32> interrupt IDs.
-      - attributes: A ?? TO DEFINE value,
+      - attributes: A <u32> value,
         containing the attributes for each interrupt ID:
 
          - Interrupt type: SPI, PPI, SGI
diff --git a/docs/components/ras.rst b/docs/components/ras.rst
index 3d81f17..02207d8 100644
--- a/docs/components/ras.rst
+++ b/docs/components/ras.rst
@@ -9,10 +9,8 @@
 paradigm for handling platform errors: exceptions resulting from errors are
 routed to and handled in EL3. Said errors are Synchronous External Abort (SEA),
 Asynchronous External Abort (signalled as SErrors), Fault Handling and Error
-Recovery interrupts.  The |EHF| document mentions various `error handling
-use-cases`__.
-
-.. __: exception-handling.rst#delegation-use-cases
+Recovery interrupts.  The |EHF| document mentions various :ref:`error handling
+use-cases <delegation-use-cases>` .
 
 For the description of Arm RAS extensions, Standard Error Records, and the
 precise definition of RAS terminology, please refer to the Arm Architecture
@@ -32,7 +30,8 @@
 
 The build option ``RAS_EXTENSION`` when set to ``1`` includes the RAS in run
 time firmware; ``EL3_EXCEPTION_HANDLING`` and ``HANDLE_EA_EL3_FIRST`` must also
-be set ``1``.
+be set ``1``. ``RAS_TRAP_LOWER_EL_ERR_ACCESS`` controls the access to the RAS
+error record registers from lower ELs.
 
 .. _ras-figure:
 
@@ -45,9 +44,7 @@
 
 The RAS framework allows the platform to define handlers for External Abort,
 Uncontainable Errors, Double Fault, and errors rising from EL3 execution. Please
-refer to the porting guide for the `RAS platform API descriptions`__.
-
-.. __: ../getting_started/porting-guide.rst#external-abort-handling-and-ras-support
+refer to :ref:`RAS Porting Guide <External Abort handling and RAS Support>`.
 
 Registering RAS error records
 -----------------------------
@@ -113,9 +110,8 @@
 
 The ``data`` constant parameter describes the various properties of the error,
 including the reason for the error, exception syndrome, and also ``flags``,
-``cookie``, and ``handle`` parameters from the `top-level exception handler`__.
-
-.. __: interrupt-framework-design.rst#el3-interrupts
+``cookie``, and ``handle`` parameters from the :ref:`top-level exception handler
+<EL3 interrupts>`.
 
 The platform is expected populate an array using the macros above, and register
 the it with the RAS framework using the macro ``REGISTER_ERR_RECORD_INFO()``,
@@ -228,21 +224,17 @@
 
 As mentioned in earlier sections, RAS framework interacts with the |EHF| to
 arbitrate handling of RAS exceptions with others that are routed to EL3. This
-means that the platform must partition a `priority level`__ for handling RAS
-exceptions. The platform must then define the macro ``PLAT_RAS_PRI`` to the
-priority level used for RAS exceptions. Platforms would typically want to
-allocate the highest secure priority for RAS handling.
+means that the platform must partition a :ref:`priority level <Partitioning
+priority levels>` for handling RAS exceptions. The platform must then define
+the macro ``PLAT_RAS_PRI`` to the priority level used for RAS exceptions.
+Platforms would typically want to allocate the highest secure priority for
+RAS handling.
 
-.. __: exception-handling.rst#partitioning-priority-levels
-
-Handling of both `interrupt`__ and `non-interrupt`__ exceptions follow the
-sequences outlined in the |EHF| documentation. I.e., for interrupts, the
-priority management is implicit; but for non-interrupt exceptions, they're
-explicit using `EHF APIs`__.
-
-.. __: exception-handling.rst#interrupt-flow
-.. __: exception-handling.rst#non-interrupt-flow
-.. __: exception-handling.rst#activating-and-deactivating-priorities
+Handling of both :ref:`interrupt <interrupt-flow>` and :ref:`non-interrupt
+<non-interrupt-flow>` exceptions follow the sequences outlined in the |EHF|
+documentation. I.e., for interrupts, the priority management is implicit; but
+for non-interrupt exceptions, they're explicit using :ref:`EHF APIs
+<Activating and Deactivating priorities>`.
 
 --------------
 
diff --git a/docs/components/sdei.rst b/docs/components/sdei.rst
index c5275a0..60259c8 100644
--- a/docs/components/sdei.rst
+++ b/docs/components/sdei.rst
@@ -205,6 +205,8 @@
 
 See the function ``sdei_client_el()`` in ``sdei_private.h``.
 
+.. _explicit-dispatch-of-events:
+
 Explicit dispatch of events
 ---------------------------
 
diff --git a/docs/components/secure-partition-manager-design.rst b/docs/components/secure-partition-manager-mm.rst
similarity index 97%
rename from docs/components/secure-partition-manager-design.rst
rename to docs/components/secure-partition-manager-mm.rst
index 4f67185..d532901 100644
--- a/docs/components/secure-partition-manager-design.rst
+++ b/docs/components/secure-partition-manager-mm.rst
@@ -1,5 +1,20 @@
-Secure Partition Manager
-************************
+Secure Partition Manager (MM)
+*****************************
+
+Foreword
+========
+
+Two implementations of a Secure Partition Manager co-exist in the TF-A codebase:
+
+-  SPM based on the PSA FF-A specification (:ref:`Secure Partition Manager`).
+-  SPM based on the MM interface.
+
+Both implementations differ in their architectures and only one can be selected
+at build time.
+
+This document describes the latter implementation where the Secure Partition Manager
+resides at EL3 and management services run from isolated Secure Partitions at S-EL0.
+The communication protocol is established through the Management Mode (MM) interface.
 
 Background
 ==========
diff --git a/docs/components/secure-partition-manager.rst b/docs/components/secure-partition-manager.rst
new file mode 100644
index 0000000..c58cd08
--- /dev/null
+++ b/docs/components/secure-partition-manager.rst
@@ -0,0 +1,865 @@
+Secure Partition Manager
+************************
+
+.. contents::
+
+Acronyms
+========
+
++--------+-----------------------------------+
+| DTB    | Device Tree Blob                  |
++--------+-----------------------------------+
+| DTS    | Device Tree Source                |
++--------+-----------------------------------+
+| EC     | Execution Context                 |
++--------+-----------------------------------+
+| FIP    | Firmware Image Package            |
++--------+-----------------------------------+
+| FF-A   | Firmware Framework for A-class    |
++--------+-----------------------------------+
+| IPA    | Intermediate Physical Address     |
++--------+-----------------------------------+
+| NWd    | Normal World                      |
++--------+-----------------------------------+
+| ODM    | Original Design Manufacturer      |
++--------+-----------------------------------+
+| OEM    | Original Equipment Manufacturer   |
++--------+-----------------------------------+
+| PA     | Physical Address                  |
++--------+-----------------------------------+
+| PE     | Processing Element                |
++--------+-----------------------------------+
+| PVM    | Primary VM                        |
++--------+-----------------------------------+
+| PSA    | Platform Security Architecture    |
++--------+-----------------------------------+
+| SP     | Secure Partition                  |
++--------+-----------------------------------+
+| SPM    | Secure Partition Manager          |
++--------+-----------------------------------+
+| SPMC   | SPM Core                          |
++--------+-----------------------------------+
+| SPMD   | SPM Dispatcher                    |
++--------+-----------------------------------+
+| SiP    | Silicon Provider                  |
++--------+-----------------------------------+
+| SWd    | Secure World                      |
++--------+-----------------------------------+
+| TLV    | Tag-Length-Value                  |
++--------+-----------------------------------+
+| TOS    | Trusted Operating System          |
++--------+-----------------------------------+
+| VM     | Virtual Machine                   |
++--------+-----------------------------------+
+
+Foreword
+========
+
+Two implementations of a Secure Partition Manager co-exist in the TF-A codebase:
+
+-  SPM based on the PSA FF-A specification `[1]`_.
+-  SPM based on the MM interface to communicate with an S-EL0 partition `[2]`_.
+
+Both implementations differ in their architectures and only one can be selected
+at build time.
+
+This document:
+
+-  describes the PSA FF-A implementation where the Secure Partition Manager
+   resides at EL3 and S-EL2 (or EL3 and S-EL1).
+-  is not an architecture specification and it might provide assumptions
+   on sections mandated as implementation-defined in the specification.
+-  covers the implications to TF-A used as a bootloader, and Hafnium
+   used as a reference code base for an S-EL2 secure firmware on
+   platforms implementing Armv8.4-SecEL2.
+
+Terminology
+-----------
+
+-  Hypervisor refers to the NS-EL2 component managing Virtual Machines (or
+   partitions) in the Normal World.
+-  SPMC refers to the S-EL2 component managing Virtual Machines (or Secure
+   Partitions) in the Secure World when Armv8.4-SecEL2 extension is implemented.
+-  Alternatively, SPMC can refer to an S-EL1 component, itself being a Secure
+   Partition and implementing the FF-A ABI on pre-Armv8.4 platforms.
+-  VM refers to a Normal World Virtual Machine managed by an Hypervisor.
+-  SP refers to a Secure World "Virtual Machine" managed by the SPMC component.
+
+Support for legacy platforms
+----------------------------
+
+In the implementation, the SPM is split into SPMD and SPMC components
+(although not strictly mandated by the specification). SPMD is located
+at EL3 and principally relays FF-A messages from NWd (Hypervisor or OS
+kernel) to SPMC located either at S-EL1 or S-EL2.
+
+Hence TF-A must support both cases where SPMC is either located at:
+
+-  S-EL1 supporting pre-Armv8.4 platforms. SPMD conveys FF-A protocol
+   from EL3 to S-EL1.
+-  S-EL2 supporting platforms implementing Armv8.4-SecEL2 extension.
+   SPMD conveys FF-A protocol from EL3 to S-EL2.
+
+The same SPMD component is used to support both configurations. The SPMC
+execution level is a build time choice.
+
+Sample reference stack
+======================
+
+The following diagram illustrates a possible configuration with SPMD and SPMC,
+one or multiple Secure Partitions, with or without an optional Hypervisor:
+
+.. image:: ../resources/diagrams/ff-a-spm-sel2.png
+
+TF-A build options
+==================
+
+The following TF-A build options are provisioned:
+
+-  **SPD=spmd**: this option selects the SPMD component to relay FF-A
+   protocol from NWd to SWd back and forth. It is not possible to
+   enable another Secure Payload Dispatcher when this option is chosen.
+-  **SPMD_SPM_AT_SEL2**: this option adjusts the SPMC execution
+   level to being S-EL1 or S-EL2. It defaults to enabled (value 1) when
+   SPD=spmd is chosen.
+-  **CTX_INCLUDE_EL2_REGS**: this option permits saving (resp.
+   restoring) the EL2 system register context before entering (resp.
+   after leaving) the SPMC. It is mandatory when ``SPMD_SPM_AT_SEL2`` is
+   enabled. The context save/restore routine and exhaustive list of
+   registers is visible at `[4]`_.
+-  **SP_LAYOUT_FILE**: this option provides a text description file
+   providing paths to SP binary images and DTS format manifests
+   (see `Specifying partition binary image and DT`_). It
+   is required when ``SPMD_SPM_AT_SEL2`` is enabled hence when multiple
+   secure partitions are to be loaded on behalf of SPMC.
+
++------------------------------+----------------------+------------------+
+|                              | CTX_INCLUDE_EL2_REGS | SPMD_SPM_AT_SEL2 |
++------------------------------+----------------------+------------------+
+| SPMC at S-EL1 (e.g. OP-TEE)  |           0          |        0         |
++------------------------------+----------------------+------------------+
+| SPMC at S-EL2 (e.g. Hafnium) |           1          | 1 (default when  |
+|                              |                      |    SPD=spmd)     |
++------------------------------+----------------------+------------------+
+
+Other combinations of such build options either break the build or are not
+supported.
+
+Note, the ``CTX_INCLUDE_EL2_REGS`` option provides the generic support for
+barely saving/restoring EL2 registers from an Arm arch perspective. As such
+it is decoupled from the ``SPD=spmd`` option.
+
+BL32 option is re-purposed to specify the SPMC image. It can specify either the
+Hafnium binary path (built for the secure world) or the path to a TEE binary
+implementing the FF-A protocol.
+
+BL33 option can specify either:
+
+-  the TFTF binary or
+-  the Hafnium binary path (built for the normal world) if VMs were loaded by
+   TF-A beforehand or
+-  a minimal loader performing the loading of VMs and Hafnium.
+
+Sample TF-A build command line when SPMC is located at S-EL1
+(typically pre-Armv8.4):
+
+.. code:: shell
+
+    make \
+    CROSS_COMPILE=aarch64-none-elf- \
+    SPD=spmd \
+    SPMD_SPM_AT_SEL2=0 \
+    BL32=<path-to-tee-binary> \
+    BL33=<path-to-nwd-binary> \
+    PLAT=fvp \
+    all fip
+
+Sample TF-A build command line for an Armv8.4-SecEL2 enabled system
+where SPMC is located at S-EL2:
+
+.. code:: shell
+
+    make \
+    CROSS_COMPILE=aarch64-none-elf- \
+    SPD=spmd \
+    CTX_INCLUDE_EL2_REGS=1 \
+    ARM_ARCH_MINOR=4 \
+    BL32=<path-to-swd-hafnium-binary>
+    BL33=<path-to-nwd-binary> \
+    SP_LAYOUT_FILE=sp_layout.json \
+    PLAT=fvp \
+    all fip
+
+Build options to enable secure boot:
+
+.. code:: shell
+
+    make \
+    CROSS_COMPILE=aarch64-none-elf- \
+    SPD=spmd \
+    CTX_INCLUDE_EL2_REGS=1 \
+    ARM_ARCH_MINOR=4 \
+    BL32=<path-to-swd-hafnium-binary>
+    BL33=<path-to-nwd-binary> \
+    SP_LAYOUT_FILE=../tf-a-tests/build/fvp/debug/sp_layout.json \
+    MBEDTLS_DIR=<path-to-mbedtls-lib> \
+    TRUSTED_BOARD_BOOT=1 \
+    COT=dualroot \
+    ARM_ROTPK_LOCATION=devel_rsa \
+    ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \
+    GENERATE_COT=1 \
+    PLAT=fvp \
+    all fip
+
+Boot process
+============
+
+Loading Hafnium and Secure Partitions in the secure world
+---------------------------------------------------------
+
+The Hafnium implementation in normal world requires VMs to be loaded in
+memory prior to booting. The mechanism upon which VMs are loaded and
+exposed to Hafnium are either:
+
+-  by supplying a ramdisk image where VM images are concatenated (1)
+-  or by providing VM load addresses within Hafnium manifest (2)
+
+TF-A is the bootlader for the Hafnium and SPs in the secure world. TF-A
+does not provide tooling or libraries manipulating ramdisks as required
+by (1). Thus BL2 loads SPs payloads independently.
+SPs may be signed by different parties (SiP, OEM/ODM, TOS vendor, etc.).
+Thus they are supplied as distinct “self-contained” signed entities within
+the FIP flash image. The FIP image itself is not signed hence providing
+ability to upgrade SPs in the field.
+
+Booting through TF-A
+--------------------
+
+SP manifests
+~~~~~~~~~~~~
+
+An SP manifest describes SP attributes as defined in `[1]`_
+section 3.1 (partition manifest at virtual FF-A instance) in DTS text format. It
+is represented as a single file associated with the SP. A sample is
+provided by `[5]`_. A binding document is provided by `[6]`_.
+
+Secure Partition packages
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Secure Partitions are bundled as independent package files consisting
+of:
+
+-  a header
+-  a DTB
+-  an image payload
+
+The header starts with a magic value and offset values to SP DTB and
+image payload. Each SP package is loaded independently by BL2 loader
+and verified for authenticity and integrity.
+
+The SP package identified by its UUID (matching FF-A uuid) is inserted
+as a single entry into the FIP at end of the TF-A build flow as shown:
+
+.. code:: shell
+
+    Trusted Boot Firmware BL2: offset=0x1F0, size=0x8AE1, cmdline="--tb-fw"
+    EL3 Runtime Firmware BL31: offset=0x8CD1, size=0x13000, cmdline="--soc-fw"
+    Secure Payload BL32 (Trusted OS): offset=0x1BCD1, size=0x15270, cmdline="--tos-fw"
+    Non-Trusted Firmware BL33: offset=0x30F41, size=0x92E0, cmdline="--nt-fw"
+    HW_CONFIG: offset=0x3A221, size=0x2348, cmdline="--hw-config"
+    TB_FW_CONFIG: offset=0x3C569, size=0x37A, cmdline="--tb-fw-config"
+    SOC_FW_CONFIG: offset=0x3C8E3, size=0x48, cmdline="--soc-fw-config"
+    TOS_FW_CONFIG: offset=0x3C92B, size=0x427, cmdline="--tos-fw-config"
+    NT_FW_CONFIG: offset=0x3CD52, size=0x48, cmdline="--nt-fw-config"
+    B4B5671E-4A90-4FE1-B81F-FB13DAE1DACB: offset=0x3CD9A, size=0xC168, cmdline="--blob"
+    D1582309-F023-47B9-827C-4464F5578FC8: offset=0x48F02, size=0xC168, cmdline="--blob"
+
+.. uml:: ../resources/diagrams/plantuml/fip-secure-partitions.puml
+
+Specifying partition binary image and DT
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A description file (json format) is passed to the build flow specifying
+paths to the SP binary image and associated DTS partition manifest file.
+The latter is going through the dtc compiler to generate the dtb fed into
+the SP package.
+
+.. code:: shell
+
+    {
+        "tee1" : {
+            "image": "tee1.bin",
+             "pm": "tee1.dts"
+        },
+
+        "tee2" : {
+            "image": "tee2.bin",
+            "pm": "tee2.dts"
+        }
+    }
+
+SPMC manifest
+~~~~~~~~~~~~~
+
+This manifest contains an SPMC attributes node consumed by SPMD at boot time. It
+is implementing the description from `[1]`_ section 3.2 (SP manifest at physical
+FF-A instance). The SP manifest at physical FF-A instance is used by the SPMD to
+setup a SP that co-resides with the SPMC and executes at S-EL1 or Secure
+Supervisor mode.
+
+In this implementation its usage is extended to the secure physical FF-A
+instance where SPMC executes at S-EL2.
+
+.. code:: shell
+
+    attribute {
+        spmc_id = <0x8000>;
+        maj_ver = <0x1>;
+        min_ver = <0x0>;
+        exec_state = <0x0>;
+        load_address = <0x0 0x6000000>;
+        entrypoint = <0x0 0x6000000>;
+        binary_size = <0x60000>;
+    };
+
+-  *spmc_id* defines the endpoint ID value that SPMC can query through
+   ``FFA_ID_GET``.
+-  *maj_ver/min_ver*. SPMD checks provided version versus its internal
+   version and aborts if not matching.
+-  *exec_state* defines SPMC execution state (can be AArch64 for
+   Hafnium, or AArch64/AArch32 for OP-TEE at S-EL1).
+-  *load_address* and *binary_size* are mostly used to verify secondary
+   entry points fit into the loaded binary image.
+-  *entrypoint* defines the cold boot primary core entry point used by
+   SPMD (currently matches ``BL32_BASE``)
+
+Other nodes in the manifest are consumed by Hafnium in the secure world.
+A sample can be found at [7]:
+
+-  The *chosen* node is currently unused in SWd. It is meant for NWd to
+   specify the init ramdisk image.
+-  The *hypervisor* node describes SPs. *is_ffa_partition* boolean
+   attribute indicates an SP. Load-addr field specifies the load address
+   at which TF-A loaded the SP package.
+-  *cpus* node provide the platform topology and allows MPIDR to VMPIDR
+   mapping. Notice with current implementation primary cpu is declared
+   first, then secondary cpus must be declared in reverse order.
+
+SPMC boot
+~~~~~~~~~
+
+The SPMC is loaded by BL2 as the BL32 image.
+
+The SPMC manifest is loaded by BL2 as the ``TOS_FW_CONFIG`` image.
+
+BL2 passes the SPMC manifest address to BL31 through a register.
+
+BL31(SPMD) runs from primary core, initializes the core contexts and
+launches BL32 passing the SPMC manifest address through a register.
+
+Loading of SPs
+~~~~~~~~~~~~~~
+
+.. uml:: ../resources/diagrams/plantuml/bl2-loading-sp.puml
+
+
+Notice this boot flow is an implementation sample on Arm's FVP platform. Platforms
+not using FW_CONFIG would adjust to a different implementation.
+
+Secure boot
+~~~~~~~~~~~
+
+The SP content certificate is inserted as a separate FIP item so that BL2 loads SPMC,
+SPMC manifest and Secure Partitions and verifies them for authenticity and integrity.
+Refer to TBBR specification `[3]`_.
+
+The multiple-signing domain feature (in current state dual signing domain) allows
+the use of two root keys namely S-ROTPK and NS-ROTPK (see `[8]`_):
+
+-  SPMC(BL32), SPMC manifest, SPs may be signed by the SiP using the S-ROTPK.
+-  BL33 may be signed by the OEM using NS-ROTPK.
+
+Longer term multiple signing domain will allow additional signing keys, e.g.
+if SPs originate from different parties.
+
+See `TF-A build options`_ for a sample build command line.
+
+Hafnium in the secure world
+===========================
+
+**NOTE: this section is work in progress. Descriptions and implementation choices
+are subject to evolve.**
+
+General considerations
+----------------------
+
+Build platform for the secure world
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The implementation might add specific code parts only relevant to the
+secure world. Such code parts might be isolated into different files
+and/or conditional code enclosed by a ``SECURE_WORLD`` macro.
+
+Secure Partitions CPU scheduling
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In the normal world, VMs are scheduled by the FFA_RUN ABI invoked from the
+primary scheduler (in the primary VM), or by a direct message request or
+response.
+
+With the FF-A EAC specification, Secure Partitions are scheduled by direct
+message invocations from a NWd VM or another SP.
+
+Platform topology
+~~~~~~~~~~~~~~~~~
+
+As stated in `[1]`_ section 4.4.1 the SPMC implementation assumes the
+following SP types:
+
+-  Pinned MP SPs: an Execution Context id matches a physical PE id. MP
+   SPs must implement the same number of ECs as the number of PEs in the
+   platform. Hence the *execution-ctx-count* as defined by
+   `[1]`_ (or NWd-Hafnium *vcpu_count*) can only take the
+   value of one or the number of physical PEs.
+-  Migratable UP SPs: a single execution context can run and be migrated
+   on any physical PE. It declares a single EC in its SP manifest. An UP
+   SP can receive a direct message request on any physical core.
+
+Usage of PSCI services in the secure world
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+- The normal world Hypervisor (optional) or OS kernel issues PSCI service
+  invocations e.g. to request PSCI version, wake-up a secondary core, or request
+  core suspend. This happens at the non-secure physical FF-A instance. In the
+  example case of Hafnium in the normal world, it boots on the primary core and
+  one of the first initialization step is to request the PSCI version. It then
+  launches the primary VM. The primary VM upon initializing performs PSCI service
+  calls (at non-secure virtual FF-A instance) which are trapped by the
+  Hypervisor. Invocation from OS Kernel ends straight at EL3. The PVM issues
+  ``PSCI_CPU_ON`` service calls to wake-up secondary cores by passing an
+  ``MPIDR``, entry point address and a CPU context address. The EL3 PSCI layer
+  then performs an exception return to the secondary core entry point on the
+  targeted core. Other PSCI calls can happen at run-time from the PVM e.g. to
+  request core suspend.
+- In the existing TF-A PSCI standard library, PSCI service calls are filtered at
+  EL3 to only originate from the NWd. Thus concerning the SPMC (at secure
+  physical FF-A instance) the PSCI service invocations cannot happen as in the
+  normal world. For example, a ``PSCI_CPU_ON`` service invocation from the SPMC
+  does not reach the PSCI layer.
+
+Parsing SP partition manifests
+------------------------------
+
+Hafnium must be able to consume SP manifests as defined in
+`[1]`_ section 3.1, at least for the mandatory fields.
+
+The SP manifest may contain memory and device regions nodes.
+
+-  Memory regions shall be mapped in the SP Stage-2 translation regime at
+   load time. A memory region node can specify RX/TX buffer regions in which
+   case it is not necessary for an SP to explicitly call the ``FFA_RXTX_MAP``
+   service.
+-  Device regions shall be mapped in SP Stage-2 translation regime as
+   peripherals and possibly allocate additional resources (e.g. interrupts)
+
+Base addresses for memory and device region nodes are IPAs provided SPMC
+identity maps IPAs to PAs within SP Stage-2 translation regime.
+
+Note: currently both VTTBR_EL2 and VSTTBR_EL2 resolve to the same set of page
+tables. It is still open whether two sets of page tables shall be provided per
+SP. The memory region node as defined in the spec (section 3.1 Table 10)
+provides a memory security attribute hinting to map either to the secure or
+non-secure stage-2 table.
+
+Passing boot data to the SP
+---------------------------
+
+`[1]`_ Section 3.4.2 “Protocol for passing data” defines a
+method to passing boot data to SPs (not currently implemented).
+
+Provided that the whole Secure Partition package image (see `Secure
+Partition packages`_) is mapped to the SP's secure Stage-2 translation
+regime, an SP can access its own manifest DTB blob and extract its partition
+manifest properties.
+
+SP Boot order
+-------------
+
+SP manifests provide an optional boot order attribute meant to resolve
+dependencies such as an SP providing a service required to properly boot
+another SP.
+
+Boot phases
+-----------
+
+Primary core boot-up
+~~~~~~~~~~~~~~~~~~~~
+
+The SPMC performs its platform initializations then loads and creates
+secure partitions based on SP packages and manifests. Then each secure
+partition is launched in sequence (see `SP Boot order`_) on their primary
+Execution Context.
+
+Notice the primary physical core may not be core 0. Hence if the primary
+core linear id is N, the 1:1 mapping requires MP SPs are launched using
+EC[N] on PE[N] (see `Platform topology`_).
+
+The SP's primary Execution Context (or the EC used when the partition is booted)
+exits through ``FFA_MSG_WAIT`` to indicate successful initialization.
+
+Secondary physical core boot-up
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Upon boot-up, the SPMC running on the primary core performs
+implementation-defined SPMD service calls at secure physical FF-A instance
+to register the secondary physical cores entry points and context information:
+
+-  This is done through a direct message request invocation to the SPMD
+   (``SET_ENTRY_POINT``). This service call does not wake-up the targeted
+   core immediately. The secondary core is woken up later by a NWd
+   ``PSCI_CPU_ON`` service invocation. A notification is passed from EL3
+   PSCI layer to the SPMD, and then to SPMC through an implementation-defined
+   interface.
+-  The SPMC/SPMD interface can consist of FF-A direct message requests/responses
+   transporting PM events.
+
+If there is no Hypervisor in the normal world, the OS Kernel issues
+``PSCI_CPU_ON`` calls that are directly trapped to EL3.
+
+When a secondary physical core wakes-up the SPMD notifies the SPMC which updates
+its internal states reflecting current physical core is being turned on.
+It might then return straight to the SPMD and then to the NWd.
+
+*(under discussion)* There may be possibility that an SP registers "PM events"
+(during primary EC boot stage) through an ad-hoc interface. Such events would
+be relayed by SPMC to one or more registered SPs on need basis
+(see `Power management`_).
+
+Secondary virtual core boot-up
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In the example case where Hafnium exists in the normal world, secondary VMs
+issue a ``PSCI_CPU_ON`` service call which is trapped to the Hypervisor. The
+latter then enables the vCPU context for the targeted core, and switches to
+the PVM down to the kernel driver with an ``HF_WAKE_UP`` message. The NWd
+driver in PVM can then schedule the newly woken up vCPU context.
+
+In the secure world the primary EC of a given SP passes the secondary EC entry
+point and context. The SMC service call is trapped into the SPMC. This can be
+either *(under discussion)*:
+
+-  a specific interface registering the secondary EC entry point,
+   similarly to above ``SET_ENTRY_POINT`` service.
+-  Re-purposing the ``PSCI_CPU_ON`` function id. It is
+   assumed that even if the input arguments are the same as the ones defined in
+   the PSCI standard, the usage deviates by the fact the secondary EC is not
+   woken up immediately. At least for the PSA-FF-A EAC where only
+   direct messaging is allowed, it is only after the first direct
+   message invocation that the secondary EC is entered. This option
+   might be preferred when the same code base is re-used for a VM or
+   an SP. The ABI to wake-up a secondary EC can remain similar.
+
+SPs are always scheduled from the NWd, this paradigm did not change from legacy
+TEEs. There must always be some logic (or driver) in the NWd to relinquish CPU
+cycles to the SWd. If primary core is 0, an SP EC[x>0] entry point is supplied
+by the SP EC[0] when the system boots in SWd. But this EC[x] is not immediately
+entered at boot. Later in the boot process when NWd is up, a direct message
+request issued from physical core 1 ends up in SP EC[1], and only at this stage
+this context is effectively scheduled.
+
+It should be possible for an SP to call into another SP through direct message
+provided the latter SP has been booted already. The "boot-order" field in
+partition manifests (`SP Boot order`_) fulfills the dependency towards availability
+of a service within an SP offered to another SP.
+
+Mandatory interfaces
+--------------------
+
+The following interfaces must be exposed to any VM or SP:
+
+-  ``FFA_STATUS``
+-  ``FFA_ERROR``
+-  ``FFA_INTERRUPT``
+-  ``FFA_VERSION``
+-  ``FFA_FEATURES``
+-  ``FFA_RX_RELEASE``
+-  ``FFA_RXTX_MAP``
+-  ``FFA_RXTX_UNMAP``
+-  ``FFA_PARTITION_INFO_GET``
+-  ``FFA_ID_GET``
+
+FFA_VERSION
+~~~~~~~~~~~
+
+Per `[1]`_ section 8.1 ``FFA_VERSION`` requires a
+*requested_version* parameter from the caller.
+
+In the current implementation when ``FFA_VERSION`` is invoked from:
+
+-  Hypervisor in NS-EL2: the SPMD returns the SPMC version specified
+   in the SPMC manifest.
+-  OS kernel in NS-EL1 when NS-EL2 is not present: the SPMD returns the
+   SPMC version specified in the SPMC manifest.
+-  VM in NWd: the Hypervisor returns its implemented version.
+-  SP in SWd: the SPMC returns its implemented version.
+-  SPMC at S-EL1/S-EL2: the SPMD returns its implemented version.
+
+FFA_FEATURES
+~~~~~~~~~~~~
+
+FF-A features may be discovered by Secure Partitions while booting
+through the SPMC. However, SPMC cannot get features from Hypervisor
+early at boot time as NS world is not setup yet.
+
+The Hypervisor may decide to gather FF-A features from SPMC through SPMD
+once at boot time and store the result. Later when a VM requests FF-A
+features, the Hypervisor can adjust its own set of features with what
+SPMC advertised, if necessary. Another approach is to always forward FF-A
+features to the SPMC when a VM requests it to the Hypervisor. Although
+the result is not supposed to change over time so there may not be added
+value doing the systematic forwarding.
+
+FFA_RXTX_MAP/FFA_RXTX_UNMAP
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+VM mailboxes are re-purposed to serve as SP RX/TX buffers. The RX/TX
+map API maps the send and receive buffer IPAs to the SP Stage-2 translation regime.
+
+Hafnium in the normal world defines VMs and their attributes as logical structures,
+including a mailbox used for FF-A indirect messaging, memory sharing, or the
+`FFA_PARTITION_INFO_GET`_  ABI.
+This same mailbox structure is re-used in the SPMC. `[1]`_ states only direct
+messaging is allowed to SPs. Thus mailbox usage is restricted to implementing
+`FFA_PARTITION_INFO_GET`_ and memory sharing ABIs.
+
+FFA_PARTITION_INFO_GET
+~~~~~~~~~~~~~~~~~~~~~~
+
+Partition info get service call can originate:
+
+-  from SP to SPM
+-  from VM to Hypervisor
+-  from Hypervisor to SPM
+
+For the latter case, the service call must be forwarded through the SPMD.
+
+FFA_ID_GET
+~~~~~~~~~~
+
+The SPMD returns:
+
+-  a default zero value on invocation from the Hypervisor.
+-  The ``spmc_id`` value specified in the SPMC manifest on invocation from
+   the SPMC (see `SPMC manifest`_)
+
+The FF-A id space is split into a non-secure space and secure space:
+
+-  FF-A id with bit 15 clear refer to normal world VMs.
+-  FF-A id with bit 15 set refer to secure world SPs
+
+Such convention helps the SPMC discriminating the origin and destination worlds
+in an FF-A service invocation. In particular the SPMC shall filter unauthorized
+transactions in its world switch routine. It must not be permitted for a VM to
+use a secure FF-A id as origin world through spoofing:
+
+-  A VM-to-SP messaging passing shall have an origin world being non-secure
+   (FF-A id bit 15 clear) and destination world being secure (FF-A id bit 15
+   set).
+-  Similarly, an SP-to-SP message shall have FF-A id bit 15 set for both origin
+   and destination ids.
+
+An incoming direct message request arriving at SPMD from NWd is forwarded to
+SPMC without a specific check. The SPMC is resumed through eret and "knows" the
+message is coming from normal world in this specific code path. Thus the origin
+endpoint id must be checked by SPMC for being a normal world id.
+
+An SP sending a direct message request must have bit 15 set in its origin
+endpoint id and this can be checked by the SPMC when the SP invokes the ABI.
+
+The SPMC shall reject the direct message if the claimed world in origin endpoint
+id is not consistent:
+
+-  It is either forwarded by SPMD and thus origin endpoint id must be a "normal
+   world id",
+-  or initiated by an SP and thus origin endpoint id must be a "secure world id".
+
+Direct messaging
+----------------
+
+This is a mandatory interface for Secure Partitions consisting in direct
+message request and responses.
+
+The ``ffa_handler`` Hafnium function may:
+
+-  trigger a world change e.g. when an SP invokes the direct message
+   response ABI to a VM.
+-  handle multiple requests from the NWd without resuming an SP.
+
+SP-to-SP
+~~~~~~~~
+
+-  An SP can send a direct message request to another SP
+-  An SP can receive a direct message response from another SP.
+
+VM-to-SP
+~~~~~~~~
+
+-  A VM can send a direct message request to an SP
+-  An SP can send a direct message response to a VM
+
+SPMC-SPMD messaging
+~~~~~~~~~~~~~~~~~~~
+
+Specific implementation-defined endpoint IDs are allocated to the SPMC and SPMD.
+Referring those IDs in source/destination fields of a direct message
+request/response permits SPMD to SPMC messaging back and forth.
+
+Per `[1]`_ Table 114 Config No. 1 (physical FF-A instance):
+
+-  SPMC=>SPMD direct message request uses SMC conduit
+-  SPMD=>SPMC direct message request uses ERET conduit
+
+Per `[1]`_ Table 118 Config No. 1 (physical FF-A instance):
+
+-  SPMC=>SPMD direct message response uses SMC conduit
+-  SPMD=>SPMC direct message response uses ERET conduit
+
+Memory management
+-----------------
+
+This section only deals with the PE MMU configuration.
+
+Hafnium in the normal world deals with NS buffers only and provisions
+a single root page table directory to VMs. In context of S-EL2 enabled
+firmware, two IPA spaces are output from Stage-1 translation (secure
+and non-secure). The Stage-2 translation handles:
+
+-  A single secure IPA space when an SP Stage-1 MMU is disabled.
+-  Two IPA spaces (secure and non-secure) when Stage-1 MMU is enabled.
+
+``VTCR_EL2`` and ``VSTCR_EL2`` provide additional bits for controlling the
+NS/S IPA translations (``VSTCR_EL2.SW``, ``VSTCR_EL2.SA``, ``VTCR_EL2.NSW``,
+``VTCR_EL2.NSA``). There may be two approaches:
+
+-  secure and non-secure mappings are rooted as two separate root page
+   tables
+-  secure and non-secure mappings use the same root page table. Access
+   from S-EL1 to an NS region translates to a secure physical address
+   space access.
+
+Interrupt management
+--------------------
+
+Road to a para-virtualized interface
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Current Hafnium implementation uses an ad-hoc mechanism for a VM to get
+a pending interrupt number through an hypercall. The PVM injects
+interrupts to VMs by delegation from the Hypervisor. The PVM probes a
+pending interrupt directly from the GIC distributor.
+
+The short-term plan is to have Hafnium/SPMC in the secure world owner
+of the GIC configuration.
+
+The SPMC fully owns the GIC configuration at S-EL2. The SPMC manages
+interrupt resources and allocates interrupt ID based on SP manifests.
+The SPMC acknowledges physical interrupts and injects virtual interrupts
+by setting the vIRQ bit when resuming an SP. A Secure Partition gathers
+the interrupt number through an hypercall.
+
+Notice the SPMC/SPMD has to handle Group0 secure interrupts in addition
+to Group1 S/NS interrupts.
+
+Power management
+----------------
+
+Assumption on the Nwd:
+
+-  NWd is the best candidate to own the platform Power Management
+   policy. It is master to invoking PSCI service calls from physical
+   CPUs.
+-  EL3 monitor is in charge of the PM control part (its PSCI layer
+   actually writing to platform registers).
+-  It is fine for the Hypervisor to trap PSCI calls and relay to EL3, or
+   OS kernel driver to emit PSCI service calls.
+
+PSCI notification are relayed through the SPMD/SPD PM hooks to the SPMC.
+This can either be through re-use of PSCI FIDs or an FF-A direct message
+from SPMD to SPMC.
+
+The SPMD performs an exception return to the SPMC which is resumed to
+its ``eret_handler`` routine. It is then either consuming a PSCI FID or
+an FF-A FID. Depending on the servicing, the SPMC may return directly to
+the SPMD (and then NWd) without resuming an SP at this stage. An example
+of this is invocation of ``FFA_PARTITION_INFO_GET`` from NWd relayed by
+the SPMD to the SPMC. The SPMC returns the needed partition information
+to the SPMD (then NWd) without actually resuming a partition in secure world.
+
+*(under discussion)*
+About using PSCI FIDs from SPMD to SPMC to notify of PM events, it is still
+questioned what to use as the return code from the SPMC.
+If the function ID used by the SPMC is not an FF-A ID when doing SMC, then the
+EL3 std svc handler won't route the response to the SPMD. That's where comes the
+idea to embed the notification into an FF-A message. The SPMC can discriminate
+this message as being a PSCI event, process it, and reply with an FF-A return
+message that the SPMD receives as an acknowledgement.
+
+SP notification
+---------------
+
+Power management notifications are conveyed from PSCI library to the
+SPMD / SPD hooks. A range of events can be relayed to SPMC.
+
+SPs may need to be notified about specific PM events.
+
+-  SPs might register PM events to the SPMC
+-  On SPMD to SPMC notification, a limited range of SPs may be notified
+   through a direct message.
+-  This assumes the mentioned SPs supports managed exit.
+
+The SPMC is the first to be notified about PM events from the SPMD. It is up
+to the SPMC to arbitrate to which SP it needs to send PM events.
+An SP explicitly registers to receive notifications to specific PM events.
+The register operation can either be an implementation-defined service call
+to the SPMC when the primary SP EC boots, or be supplied through the SP
+manifest.
+
+References
+==========
+
+.. _[1]:
+
+[1] `Platform Security Architecture Firmware Framework for Arm® v8-A 1.0 Platform Design Document <https://developer.arm.com/docs/den0077/latest>`__
+
+.. _[2]:
+
+[2] :ref:`Secure Partition Manager using MM interface<Secure Partition Manager (MM)>`
+
+.. _[3]:
+
+[3] `Trusted Boot Board Requirements
+Client <https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a>`__
+
+.. _[4]:
+
+[4] https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/lib/el3_runtime/aarch64/context.S#n45
+
+.. _[5]:
+
+[5] https://git.trustedfirmware.org/TF-A/tf-a-tests.git/tree/spm/cactus/cactus.dts
+
+.. _[6]:
+
+[6] https://trustedfirmware-a.readthedocs.io/en/latest/components/psa-ffa-manifest-binding.html
+
+.. _[7]:
+
+[7] https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
+
+.. _[8]:
+
+[8] https://developer.trustedfirmware.org/w/tf_a/poc-multiple-signing-domains/
+
+--------------
+
+*Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/design/auth-framework.rst b/docs/design/auth-framework.rst
index 1a53e22..6913e66 100644
--- a/docs/design/auth-framework.rst
+++ b/docs/design/auth-framework.rst
@@ -619,11 +619,13 @@
 The TBBR CoT
 ~~~~~~~~~~~~
 
-The CoT can be found in ``drivers/auth/tbbr/tbbr_cot.c``. This CoT consists of
-an array of pointers to image descriptors and it is registered in the framework
-using the macro ``REGISTER_COT(cot_desc)``, where ``cot_desc`` must be the name
-of the array (passing a pointer or any other type of indirection will cause the
-registration process to fail).
+CoT specific to BL1 and BL2 can be found in ``drivers/auth/tbbr/tbbr_cot_bl1.c``
+and ``drivers/auth/tbbr/tbbr_cot_bl2.c`` respectively. The common CoT used across
+BL1 and BL2 can be found in ``drivers/auth/tbbr/tbbr_cot_common.c``.
+This CoT consists of an array of pointers to image descriptors and it is
+registered in the framework using the macro ``REGISTER_COT(cot_desc)``, where
+``cot_desc`` must be the name of the array (passing a pointer or any other
+type of indirection will cause the registration process to fail).
 
 The number of images participating in the boot process depends on the CoT.
 There is, however, a minimum set of images that are mandatory in TF-A and thus
@@ -702,7 +704,7 @@
    address/size to store the parameter. The CoT is responsible for allocating
    the required memory to store the parameters. This pointer may be NULL.
 
-In the ``tbbr_cot.c`` file, a set of buffers are allocated to store the parameters
+In the ``tbbr_cot*.c`` file, a set of buffers are allocated to store the parameters
 extracted from the certificates. In the case of the TBBR CoT, these parameters
 are hashes and public keys. In DER format, an RSA-4096 public key requires 550
 bytes, and a hash requires 51 bytes. Depending on the CoT and the authentication
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index 258f73d..6b6c639 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -227,11 +227,21 @@
 -  ``ERRATA_A76_1275112``: This applies errata 1275112 workaround to Cortex-A76
    CPU. This needs to be enabled only for revision <= r3p0 of the CPU.
 
-For Hercules, the following errata build flags are defined :
+-  ``ERRATA_A76_1791580``: This applies errata 1791580 workaround to Cortex-A76
+   CPU. This needs to be enabled only for revision <= r4p0 of the CPU.
 
--  ``ERRATA_HERCULES_1688305``: This applies errata 1688305 workaround to
-   Hercules CPU. This needs to be enabled only for revision r0p0 - r1p0 of
-   the CPU.
+-  ``ERRATA_A76_1800710``: This applies errata 1800710 workaround to Cortex-A76
+   CPU. This needs to be enabled only for revision <= r4p0 of the CPU.
+
+For Cortex-A77, the following errata build flags are defined :
+
+-  ``ERRATA_A77_1800714``: This applies errata 1800714 workaround to Cortex-A77
+   CPU. This needs to be enabled only for revision <= r1p1 of the CPU.
+
+For Cortex-A78, the following errata build flags are defined :
+
+-  ``ERRATA_A78_1688305``: This applies errata 1688305 workaround to Cortex-A78
+   CPU. This needs to be enabled only for revision r0p0 - r1p0 of the CPU.
 
 For Neoverse N1, the following errata build flags are defined :
 
@@ -338,7 +348,7 @@
 
 --------------
 
-*Copyright (c) 2014-2019, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2014-2020, Arm Limited and Contributors. All rights reserved.*
 
 .. _CVE-2017-5715: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
 .. _CVE-2018-3639: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-3639
diff --git a/docs/design/firmware-design.rst b/docs/design/firmware-design.rst
index b336b38..a357d58 100644
--- a/docs/design/firmware-design.rst
+++ b/docs/design/firmware-design.rst
@@ -83,6 +83,10 @@
 platform. The Boot Loader stage may optionally specify a firmware
 configuration file and/or hardware configuration file as listed below:
 
+-  FW_CONFIG - The firmware configuration file. Holds properties shared across
+   all BLx images.
+   An example is the "dtb-registry" node, which contains the information about
+   the other device tree configurations (load-address, size, image_id).
 -  HW_CONFIG - The hardware configuration file. Can be shared by all Boot Loader
    stages and also by the Normal World Rich OS.
 -  TB_FW_CONFIG - Trusted Boot Firmware configuration file. Shared between BL1
@@ -109,8 +113,8 @@
    the generic hardware configuration is passed the next available argument.
    For example,
 
-   -  If TB_FW_CONFIG is loaded by BL1, then its address is passed in ``arg0``
-      to BL2.
+   -  FW_CONFIG is loaded by BL1, then its address is passed in ``arg0`` to BL2.
+   -  TB_FW_CONFIG address is retrieved by BL2 from FW_CONFIG device tree.
    -  If HW_CONFIG is loaded by BL1, then its address is passed in ``arg2`` to
       BL2. Note, ``arg1`` is already used for meminfo_t.
    -  If SOC_FW_CONFIG is loaded by BL2, then its address is passed in ``arg1``
@@ -953,6 +957,8 @@
 
 |Image 1|
 
+.. _handling-an-smc:
+
 Handling an SMC
 ~~~~~~~~~~~~~~~
 
@@ -984,7 +990,7 @@
 Exception Handling Framework
 ----------------------------
 
-Please refer to the `Exception Handling Framework`_ document.
+Please refer to the :ref:`Exception Handling Framework` document.
 
 Power State Coordination Interface
 ----------------------------------
@@ -1296,6 +1302,8 @@
 already been performed and act as appropriate. Possible courses of actions are,
 e.g. skip the action the second time, or undo/redo it.
 
+.. _configuring-secure-interrupts:
+
 Configuring secure interrupts
 -----------------------------
 
@@ -1732,7 +1740,7 @@
 ``bl2_mem_params_descs`` contains parameters passed from BL2 to next the
 BL image during boot.
 
-``fw_configs`` includes soc_fw_config, tos_fw_config and tb_fw_config.
+``fw_configs`` includes soc_fw_config, tos_fw_config, tb_fw_config and fw_config.
 
 **FVP with TSP in Trusted SRAM with firmware configs :**
 (These diagrams only cover the AArch64 case)
@@ -1757,7 +1765,7 @@
                |          |  <<<<<<<<<<<<<  | BL31 PROGBITS  |
                |          |  <<<<<<<<<<<<<  |----------------|
                |          |  <<<<<<<<<<<<<  |     BL32       |
-    0x04002000 +----------+                 +----------------+
+    0x04003000 +----------+                 +----------------+
                |  CONFIG  |
     0x04001000 +----------+
                |  Shared  |
@@ -1794,7 +1802,7 @@
                |--------------|  <<<<<<<<<<<<<  |----------------|
                |              |  <<<<<<<<<<<<<  | BL31 PROGBITS  |
                |              |                 +----------------+
-               +--------------+
+    0x04003000 +--------------+
                |    CONFIG    |
     0x04001000 +--------------+
                |    Shared    |
@@ -1828,7 +1836,7 @@
                |----------|  <<<<<<<<<<<<<  |----------------|
                |          |  <<<<<<<<<<<<<  | BL31 PROGBITS  |
                |          |                 +----------------+
-    0x04002000 +----------+
+    0x04003000 +----------+
                |  CONFIG  |
     0x04001000 +----------+
                |  Shared  |
diff --git a/docs/design/interrupt-framework-design.rst b/docs/design/interrupt-framework-design.rst
index 14f7227..dfb2eac 100644
--- a/docs/design/interrupt-framework-design.rst
+++ b/docs/design/interrupt-framework-design.rst
@@ -138,6 +138,8 @@
    reason to route the interrupt to EL3 software and then hand it back to
    non-secure software for handling.
 
+.. _EL3 interrupts:
+
 EL3 interrupts
 ^^^^^^^^^^^^^^
 
@@ -148,10 +150,8 @@
 
    However, when ``EL3_EXCEPTION_HANDLING`` is ``1``, this routing model is
    invalid as EL3 interrupts are unconditionally routed to EL3, and EL3
-   interrupts will always preempt Secure EL1/EL0 execution. See `exception
-   handling`__ documentation.
-
-   .. __: exception-handling.rst#interrupt-handling
+   interrupts will always preempt Secure EL1/EL0 execution. See :ref:`exception
+   handling<interrupt-handling>` documentation.
 
 #. **CSS=0, TEL3=1**. Interrupt is routed to EL3 when execution is in
    Secure-EL1/Secure-EL0. This is a valid routing model as secure software
@@ -301,6 +301,8 @@
 `Software components`_) during the registration of a handler for an interrupt
 type.
 
+.. _el3-runtime-firmware:
+
 EL3 runtime firmware
 ~~~~~~~~~~~~~~~~~~~~
 
@@ -899,14 +901,14 @@
 
 |Image 2|
 
-Secure payload
-~~~~~~~~~~~~~~
+.. _sp-synchronous-int:
+
+Secure payload interrupt handling
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 The SP should implement one or both of the synchronous and asynchronous
 interrupt handling models depending upon the interrupt routing model it has
-chosen (as described in section `Secure Payload`__).
-
-.. __: #sp-int-registration
+chosen (as described in section :ref:`Secure Payload <sp-int-registration>`).
 
 In the synchronous model, it should begin handling a Secure-EL1 interrupt after
 receiving control from the SPD service at an entrypoint agreed upon during build
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index c863079..0acc886 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -88,6 +88,7 @@
 -  1: Enables all types of branch protection features
 -  2: Return address signing to its standard level
 -  3: Extend the signing to include leaf functions
+-  4: Turn on branch target identification mechanism
 
    The table below summarizes ``BRANCH_PROTECTION`` values, GCC compilation options
    and resulting PAuth/BTI features.
@@ -103,6 +104,8 @@
    +-------+--------------+-------+-----+
    |   3   | pac-ret+leaf |   Y   |  N  |
    +-------+--------------+-------+-----+
+   |   4   |     bti      |   N   |  Y  |
+   +-------+--------------+-------+-----+
 
    This option defaults to 0 and this is an experimental feature.
    Note that Pointer Authentication is enabled for Non-secure world
@@ -116,6 +119,8 @@
 -  ``BUILD_STRING``: Input string for VERSION_STRING, which allows the TF-A
    build to be uniquely identified. Defaults to the current git commit id.
 
+-  ``BUILD_BASE``: Output directory for the build. Defaults to ``./build``
+
 -  ``CFLAGS``: Extra user options appended on the compiler's command line in
    addition to the options set by the build system.
 
@@ -343,16 +348,14 @@
 -  ``GICV2_G0_FOR_EL3``: Unlike GICv3, the GICv2 architecture doesn't have
    inherent support for specific EL3 type interrupts. Setting this build option
    to ``1`` assumes GICv2 *Group 0* interrupts are expected to target EL3, both
-   by `platform abstraction layer`__ and `Interrupt Management Framework`__.
+   by :ref:`platform abstraction layer<platform Interrupt Controller API>` and
+   :ref:`Interrupt Management Framework<Interrupt Management Framework>`.
    This allows GICv2 platforms to enable features requiring EL3 interrupt type.
    This also means that all GICv2 Group 0 interrupts are delivered to EL3, and
    the Secure Payload interrupts needs to be synchronously handed over to Secure
    EL1 for handling. The default value of this option is ``0``, which means the
    Group 0 interrupts are assumed to be handled by Secure EL1.
 
-   .. __: platform-interrupt-controller-API.rst
-   .. __: interrupt-framework-design.rst
-
 -  ``HANDLE_EA_EL3_FIRST``: When set to ``1``, External Aborts and SError
    Interrupts will be always trapped in EL3 i.e. in BL31 at runtime. When set to
    ``0`` (default), these exceptions will be trapped in the current exception
@@ -645,12 +648,25 @@
    configuration device tree, instead of static structure in the code base.
    This is currently an experimental feature.
 
+-  ``COT_DESC_IN_DTB``: This flag determines whether to create COT descriptors
+   at runtime using fconf. If this flag is enabled, COT descriptors are
+   statically captured in tb_fw_config file in the form of device tree nodes
+   and properties. Currently, COT descriptors used by BL2 are moved to the
+   device tree and COT descriptors used by BL1 are retained in the code
+   base statically. This is currently an experimental feature.
+
 -  ``SDEI_IN_FCONF``: This flag determines whether to configure SDEI setup in
    runtime using firmware configuration framework. The platform specific SDEI
    shared and private events configuration is retrieved from device tree rather
    than static C structures at compile time. This is currently an experimental
    feature and is only supported if SDEI_SUPPORT build flag is enabled.
 
+-  ``SEC_INT_DESC_IN_FCONF``: This flag determines whether to configure Group 0
+   and Group1 secure interrupts using the firmware configuration framework. The
+   platform specific secure interrupt property descriptor is retrieved from
+   device tree in runtime rather than depending on static C structure at compile
+   time. This is currently an experimental feature.
+
 -  ``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
@@ -701,6 +717,14 @@
    | 1530924 |  Cortex-A53  |
    +---------+--------------+
 
+- ``RAS_TRAP_LOWER_EL_ERR_ACCESS``: This flag enables/disables the SCR_EL3.TERR
+  bit, to trap access to the RAS ERR and RAS ERX registers from lower ELs.
+  This flag is disabled by default.
+
+- ``OPENSSL_DIR``: This flag is used to provide the installed openssl directory
+  path on the host machine which is used to build certificate generation and
+  firmware encryption tool.
+
 GICv3 driver options
 --------------------
 
@@ -711,8 +735,10 @@
 The driver can be configured with the following options set in the platform
 makefile:
 
--  ``GICV3_IMPL``: Selects between GIC-500 and GIC-600 variants of GICv3.
-   This option can take values GIC500 and GIC600 with default set to GIC500.
+-  ``GICV3_SUPPORT_GIC600``: Add support for the GIC-600 variants of GICv3.
+   Enabling this option will add runtime detection support for the
+   GIC-600, so is safe to select even for a GIC500 implementation.
+   This option defaults to 0.
 
 -  ``GICV3_IMPL_GIC600_MULTICHIP``: Selects GIC-600 variant with multichip
    functionality. This option defaults to 0
diff --git a/docs/getting_started/docs-build.rst b/docs/getting_started/docs-build.rst
index 91b1b3a..87c677f 100644
--- a/docs/getting_started/docs-build.rst
+++ b/docs/getting_started/docs-build.rst
@@ -67,7 +67,7 @@
 
 ::
 
-   docs/build/html/
+   docs/build/html
 
 We also support building documentation in other formats. From the ``docs``
 directory of the project, run the following command to see the supported
@@ -79,6 +79,31 @@
 
    make help
 
+Building rendered documentation from a container
+------------------------------------------------
+
+There may be cases where you can not either install or upgrade required
+dependencies to generate the documents, so in this case, one way to
+create the documentation is through a docker container. The first step is
+to check if `docker`_ is installed in your host, otherwise check main docker
+page for installation instructions. Once installed, run the following script
+from project root directory
+
+.. code:: shell
+
+   docker run --rm -v $PWD:/TF sphinxdoc/sphinx \
+          bash -c 'cd /TF && \
+          pip3 install plantuml -r ./docs/requirements.txt && make doc'
+
+The above command fetches the ``sphinxdoc/sphinx`` container from `docker
+hub`_, launches the container, installs documentation requirements and finally
+creates the documentation. Once done, exit the container and output from the
+build process will be placed in:
+
+::
+
+   docs/build/html
+
 --------------
 
 *Copyright (c) 2019, Arm Limited. All rights reserved.*
@@ -86,3 +111,5 @@
 .. _Sphinx: http://www.sphinx-doc.org/en/master/
 .. _pip homepage: https://pip.pypa.io/en/stable/
 .. _Dia: https://wiki.gnome.org/Apps/Dia
+.. _docker: https://www.docker.com/
+.. _docker hub: https://hub.docker.com/repository/docker/sphinxdoc/sphinx
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index 2d17f12..6b8bbc6 100644
--- a/docs/getting_started/porting-guide.rst
+++ b/docs/getting_started/porting-guide.rst
@@ -1130,6 +1130,7 @@
 
     soc_version[30:24] = JEP-106 continuation code for the SiP
     soc_version[23:16] = JEP-106 identification code with parity bit for the SiP
+    soc_version[15:0]  = Implementation defined SoC ID
 
 Function : plat_get_soc_revision()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1145,6 +1146,18 @@
 
     soc_revision[0:30] = SOC revision of specific SOC
 
+Function : plat_is_smccc_feature_available()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : u_register_t
+    Return   : int32_t
+
+This function returns SMC_ARCH_CALL_SUCCESS if the platform supports
+the SMCCC function specified in the argument; otherwise returns
+SMC_ARCH_CALL_NOT_SUPPORTED.
+
 Modifications specific to a Boot Loader stage
 ---------------------------------------------
 
@@ -1424,7 +1437,7 @@
 
 On Arm standard platforms, the arguments received are :
 
-    arg0 - Points to load address of HW_CONFIG if present
+    arg0 - Points to load address of FW_CONFIG
 
     arg1 - ``meminfo`` structure populated by BL1. The platform copies
     the contents of ``meminfo`` as it may be subsequently overwritten by BL2.
@@ -1736,6 +1749,10 @@
     which is list of executable images following BL31,
 
     arg1 - Points to load address of SOC_FW_CONFIG if present
+           except in case of Arm FVP platform.
+
+           In case of Arm FVP platform, Points to load address
+           of FW_CONFIG.
 
     arg2 - Points to load address of HW_CONFIG if present
 
@@ -1890,6 +1907,21 @@
 of the system counter, which is retrieved from the first entry in the frequency
 modes table.
 
+Function : plat_arm_set_twedel_scr_el3() [optional]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : void
+    Return   : uint32_t
+
+This function is used in v8.6+ systems to set the WFE trap delay value in
+SCR_EL3. If this function returns TWED_DISABLED or is left unimplemented, this
+feature is not enabled.  The only hook provided is to set the TWED fields in
+SCR_EL3, there are similar fields in HCR_EL2, SCTLR_EL2, and SCTLR_EL1 to adjust
+the WFE trap delays in lower ELs and these fields should be set by the
+appropriate EL2 or EL1 code depending on the platform configuration.
+
 #define : PLAT_PERCPU_BAKERY_LOCK_SIZE [optional]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -1941,23 +1973,27 @@
 Functions
 .........
 
-Function: int plat_sdei_validate_entry_point(uintptr_t ep) [optional]
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Function: int plat_sdei_validate_entry_point() [optional]
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 ::
 
-  Argument: uintptr_t
+  Argument: uintptr_t ep, unsigned int client_mode
   Return: int
 
-This function validates the address of client entry points provided for both
-event registration and *Complete and Resume* |SDEI| calls. The function
-takes one argument, which is the address of the handler the |SDEI| client
-requested to register. The function must return ``0`` for successful validation,
-or ``-1`` upon failure.
+This function validates the entry point address of the event handler provided by
+the client for both event registration and *Complete and Resume* |SDEI| calls.
+The function ensures that the address is valid in the client translation regime.
+
+The second argument is the exception level that the client is executing in. It
+can be Non-Secure EL1 or Non-Secure EL2.
+
+The function must return ``0`` for successful validation, or ``-1`` upon failure.
 
 The default implementation always returns ``0``. On Arm platforms, this function
-is implemented to translate the entry point to physical address, and further to
-ensure that the address is located in Non-secure DRAM.
+translates the entry point address within the client translation regime and
+further ensures that the resulting physical address is located in Non-secure
+DRAM.
 
 Function: void plat_sdei_handle_masked_trigger(uint64_t mpidr, unsigned int intr) [optional]
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -2446,9 +2482,7 @@
 ``FVP_USE_GIC_DRIVER`` (See :ref:`build_options_arm_fvp_platform` for more
 details).
 
-See also: `Interrupt Controller Abstraction APIs`__.
-
-.. __: ../design/platform-interrupt-controller-API.rst
+See also: :ref:`Interrupt Controller Abstraction APIs<Platform Interrupt Controller API>`.
 
 Function : plat_interrupt_type_to_line() [mandatory]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2573,9 +2607,7 @@
 the highest pending interrupt has begun. It should return the raw, unmodified
 value obtained from the interrupt controller when acknowledging an interrupt.
 The actual interrupt number shall be extracted from this raw value using the API
-`plat_ic_get_interrupt_id()`__.
-
-.. __: ../design/platform-interrupt-controller-API.rst#function-unsigned-int-plat-ic-get-interrupt-id-unsigned-int-raw-optional
+`plat_ic_get_interrupt_id()<plat_ic_get_interrupt_id>`.
 
 This function in Arm standard platforms using GICv2, reads the *Interrupt
 Acknowledge Register* (``GICC_IAR``). This changes the state of the highest
@@ -2706,6 +2738,8 @@
 registers x0 through x5 to do its work. The return value is 0 on successful
 completion; otherwise the return value is -1.
 
+.. _External Abort handling and RAS Support:
+
 External Abort handling and RAS Support
 ---------------------------------------
 
diff --git a/docs/global_substitutions.txt b/docs/global_substitutions.txt
index 4dda1dc..d33155b 100644
--- a/docs/global_substitutions.txt
+++ b/docs/global_substitutions.txt
@@ -14,6 +14,7 @@
 .. |EHF| replace:: :term:`EHF`
 .. |FCONF| replace:: :term:`FCONF`
 .. |FDT| replace:: :term:`FDT`
+.. |FFA| replace:: :term:`FFA`
 .. |FIP| replace:: :term:`FIP`
 .. |FVP| replace:: :term:`FVP`
 .. |FWU| replace:: :term:`FWU`
@@ -44,7 +45,6 @@
 .. |SMCCC| replace:: :term:`SMCCC`
 .. |SoC| replace:: :term:`SoC`
 .. |SP| replace:: :term:`SP`
-.. |SPCI| replace:: :term:`SPCI`
 .. |SPD| replace:: :term:`SPD`
 .. |SPM| replace:: :term:`SPM`
 .. |SSBS| replace:: :term:`SSBS`
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 3da30b0..e087079 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -57,6 +57,9 @@
    FDT
       Flattened Device Tree
 
+   FFA
+      Firmware Framework for A-class processors
+
    FIP
       Firmware Image Package
 
@@ -107,6 +110,9 @@
    PMF
       Performance Measurement Framework
 
+   PSA
+      Platform Security Architecture
+
    PSCI
       Power State Coordination Interface
 
@@ -149,9 +155,6 @@
    SP
       Secure Partition
 
-   SPCI
-      Secure Partition Client Interface
-
    SPD
       Secure Payload Dispatcher
 
diff --git a/docs/perf/psci-performance-juno.rst b/docs/perf/psci-performance-juno.rst
index c127c1c..eab3e4d 100644
--- a/docs/perf/psci-performance-juno.rst
+++ b/docs/perf/psci-performance-juno.rst
@@ -286,7 +286,7 @@
 
 --------------
 
-*Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.*
 
-.. _Juno R1 platform: https://www.arm.com/files/pdf/Juno_r1_ARM_Dev_datasheet.pdf
+.. _Juno R1 platform: https://static.docs.arm.com/100122/0100/arm_versatile_express_juno_r1_development_platform_(v2m_juno_r1)_technical_reference_manual_100122_0100_05_en.pdf
 .. _TF master as of 31/01/2017: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/?id=c38b36d
diff --git a/docs/plat/allwinner.rst b/docs/plat/allwinner.rst
index a1e0659..d82380d 100644
--- a/docs/plat/allwinner.rst
+++ b/docs/plat/allwinner.rst
@@ -34,7 +34,7 @@
 
     make CROSS_COMPILE=aarch64-linux-gnu- PLAT=sun50i_h6 DEBUG=1 bl31
 
-.. _U-Boot documentation: http://git.denx.de/?p=u-boot.git;f=board/sunxi/README.sunxi64;hb=HEAD
+.. _U-Boot documentation: https://gitlab.denx.de/u-boot/u-boot/-/blob/master/board/sunxi/README.sunxi64
 
 Trusted OS dispatcher
 ---------------------
diff --git a/docs/plat/arm/arm-build-options.rst b/docs/plat/arm/arm-build-options.rst
index 9622de6..2e50068 100644
--- a/docs/plat/arm/arm-build-options.rst
+++ b/docs/plat/arm/arm-build-options.rst
@@ -91,6 +91,9 @@
    platforms. If this option is specified, then the path to the CryptoCell
    SBROM library must be specified via ``CCSBROM_LIB_PATH`` flag.
 
+-  ``ARM_SPMC_MANIFEST_DTS`` : path to an alternate manifest file used as the
+   SPMC Core manifest. Valid when ``SPD=spmd`` is selected.
+
 For a better understanding of these options, the Arm development platform memory
 map is explained in the :ref:`Firmware Design`.
 
diff --git a/docs/plat/arm/fvp/index.rst b/docs/plat/arm/fvp/index.rst
index eb7eb00..745e31f 100644
--- a/docs/plat/arm/fvp/index.rst
+++ b/docs/plat/arm/fvp/index.rst
@@ -37,12 +37,16 @@
 -  ``FVP_Base_Cortex-A76AEx4``
 -  ``FVP_Base_Cortex-A76AEx8``
 -  ``FVP_Base_Cortex-A77x4``
+-  ``FVP_Base_Neoverse-E1x1``
+-  ``FVP_Base_Neoverse-E1x2``
+-  ``FVP_Base_Neoverse-E1x4``
 -  ``FVP_Base_Neoverse-N1x4``
 -  ``FVP_Base_Zeusx4``
--  ``FVP_CSS_SGI-575`` (Version 11.10 build 25)
+-  ``FVP_CSS_SGI-575``     (Version 11.10 build 36)
 -  ``FVP_CSS_SGM-775``
--  ``FVP_RD_E1Edge``
--  ``FVP_RD_N1Edge`` (Version 11.10 build 25)
+-  ``FVP_RD_E1_edge``      (Version 11.10 build 36)
+-  ``FVP_RD_N1_edge``      (Version 11.10 build 36)
+-  ``FVP_RD_N1_edge_dual`` (Version 11.10 build 36)
 -  ``Foundation_Platform``
 
 The latest version of the AArch32 build of TF-A has been tested on the
@@ -116,7 +120,6 @@
 
 -  ``FVP_USE_GIC_DRIVER`` : Selects the GIC driver to be built. Options:
 
-   -  ``FVP_GIC600`` : The GIC600 implementation of GICv3 is selected
    -  ``FVP_GICV2`` : The GICv2 only driver is selected
    -  ``FVP_GICV3`` : The GICv3 only driver is selected (default option)
 
@@ -632,7 +635,7 @@
 
 *Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
 
-.. _TB_FW_CONFIG for FVP: ../plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
+.. _TB_FW_CONFIG for FVP: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
 .. _Arm's website: `FVP models`_
 .. _FVP models: https://developer.arm.com/products/system-design/fixed-virtual-platforms
 .. _Linaro Release 19.06: http://releases.linaro.org/members/arm/platforms/19.06
diff --git a/docs/plat/arm/index.rst b/docs/plat/arm/index.rst
index e26f75e..1afe475 100644
--- a/docs/plat/arm/index.rst
+++ b/docs/plat/arm/index.rst
@@ -8,6 +8,7 @@
    juno/index
    fvp/index
    fvp-ve/index
+   tc0/index
    arm-build-options
 
 This chapter holds documentation related to Arm's development platforms,
diff --git a/docs/plat/arm/tc0/index.rst b/docs/plat/arm/tc0/index.rst
new file mode 100644
index 0000000..34d1f13
--- /dev/null
+++ b/docs/plat/arm/tc0/index.rst
@@ -0,0 +1,50 @@
+TC0 Total Compute Platform
+==========================
+
+Some of the features of TC0 platform referenced in TF-A include:
+
+- A `System Control Processor <https://github.com/ARM-software/SCP-firmware>`_
+  to abstract power and system management tasks away from application
+  processors. The RAM firmware for SCP is included in the TF-A FIP and is
+  loaded by AP BL2 from FIP in flash to SRAM for copying by SCP (SCP has access
+  to AP SRAM).
+- GICv4
+- Trusted Board Boot
+- SCMI
+- MHUv2
+
+Boot Sequence
+-------------
+
+The execution begins from SCP_BL1. SCP_BL1 powers up the AP which starts
+executing AP_BL1 and then executes AP_BL2 which loads the SCP_BL2 from
+FIP to SRAM. The SCP has access to AP SRAM. The address and size of SCP_BL2
+is communicated to SCP using SDS. SCP copies SCP_BL2 from SRAM to its own
+RAM and starts executing it. The AP then continues executing the rest of TF-A
+stages including BL31 runtime stage and hands off executing to
+Non-secure world (u-boot).
+
+Build Procedure (TF-A only)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+-  Obtain arm `toolchain <https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads>`_.
+   Set the CROSS_COMPILE environment variable to point to the toolchain folder.
+
+-  Build TF-A:
+
+   .. code:: shell
+
+      make PLAT=tc0 BL33=<path_to_uboot.bin> \
+      SCP_BL2=<path_to_scp_ramfw.bin>  all fip
+
+   Enable TBBR by adding the following options to the make command:
+
+   .. code:: shell
+
+      MBEDTLS_DIR=<path_to_mbedtls_directory>  \
+      TRUSTED_BOARD_BOOT=1 \
+      GENERATE_COT=1 \
+      ARM_ROTPK_LOCATION=devel_rsa  \
+      ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem
+
+*Copyright (c) 2020, Arm Limited. All rights reserved.*
diff --git a/docs/plat/imx8m.rst b/docs/plat/imx8m.rst
index 8acd13c..f184b69 100644
--- a/docs/plat/imx8m.rst
+++ b/docs/plat/imx8m.rst
@@ -32,6 +32,8 @@
 
    Target_SoC should be "imx8mq" for i.MX8MQ SoC.
    Target_SoC should be "imx8mm" for i.MX8MM SoC.
+   Target_SoC should be "imx8mn" for i.MX8MN SoC.
+   Target_SoC should be "imx8mp" for i.MX8MP SoC.
 
 Deploy TF-A Images
 ~~~~~~~~~~~~~~~~~~
diff --git a/docs/plat/index.rst b/docs/plat/index.rst
index 553d8b5..bd23410 100644
--- a/docs/plat/index.rst
+++ b/docs/plat/index.rst
@@ -19,6 +19,7 @@
    intel-stratix10
    marvell/index
    mt8183
+   mt8192
    nvidia-tegra
    warp7
    imx8
diff --git a/docs/plat/marvell/build.rst b/docs/plat/marvell/armada/build.rst
similarity index 91%
rename from docs/plat/marvell/build.rst
rename to docs/plat/marvell/armada/build.rst
index c10bcff..da4ba56 100644
--- a/docs/plat/marvell/build.rst
+++ b/docs/plat/marvell/armada/build.rst
@@ -77,6 +77,15 @@
 
         Flag defining the LLC (L3) cache state. The cache is enabled by default (``LLC_ENABLE=1``).
 
+- LLC_SRAM
+
+        Flag enabling the LLC (L3) cache SRAM support. The LLC SRAM is activated and used
+        by Trusted OS (OP-TEE OS, BL32). The TF-A only prepares CCU address translation windows
+        for SRAM address range at BL31 execution stage with window target set to DRAM-0.
+        When Trusted OS activates LLC SRAM, the CCU window target is changed to SRAM.
+        There is no reason to enable this feature if OP-TEE OS built with CFG_WITH_PAGER=n.
+        Only set LLC_SRAM=1 if OP-TEE OS is built with CFG_WITH_PAGER=y.
+
 - MARVELL_SECURE_BOOT
 
         Build trusted(=1)/non trusted(=0) image, default is non trusted.
@@ -84,7 +93,7 @@
 - BLE_PATH
 
         Points to BLE (Binary ROM extension) sources folder. Only required for A8K builds.
-        The parameter is optional, its default value is ``plat/marvell/a8k/common/ble``.
+        The parameter is optional, its default value is ``plat/marvell/armada/a8k/common/ble``.
 
 - MV_DDR_PATH
 
@@ -192,7 +201,11 @@
     In order to build UART recovery image this operation should be disabled for
     a70x0 and a80x0 because of hardware limitation (boot from secondary image
     can interrupt UART recovery process). This MACRO definition is set in
-    ``plat/marvell/a8k/common/include/platform_def.h`` file.
+    ``plat/marvell/armada/a8k/common/include/platform_def.h`` file.
+
+- DDR32
+    In order to work in 32bit DDR, instead of the default 64bit ECC DDR,
+    this flag should be set to 1.
 
 For more information about build options, please refer to the
 :ref:`Build Options` document.
diff --git a/docs/plat/marvell/misc/mvebu-a8k-addr-map.rst b/docs/plat/marvell/armada/misc/mvebu-a8k-addr-map.rst
similarity index 100%
rename from docs/plat/marvell/misc/mvebu-a8k-addr-map.rst
rename to docs/plat/marvell/armada/misc/mvebu-a8k-addr-map.rst
diff --git a/docs/plat/marvell/misc/mvebu-amb.rst b/docs/plat/marvell/armada/misc/mvebu-amb.rst
similarity index 100%
rename from docs/plat/marvell/misc/mvebu-amb.rst
rename to docs/plat/marvell/armada/misc/mvebu-amb.rst
diff --git a/docs/plat/marvell/misc/mvebu-ccu.rst b/docs/plat/marvell/armada/misc/mvebu-ccu.rst
similarity index 100%
rename from docs/plat/marvell/misc/mvebu-ccu.rst
rename to docs/plat/marvell/armada/misc/mvebu-ccu.rst
diff --git a/docs/plat/marvell/misc/mvebu-io-win.rst b/docs/plat/marvell/armada/misc/mvebu-io-win.rst
similarity index 100%
rename from docs/plat/marvell/misc/mvebu-io-win.rst
rename to docs/plat/marvell/armada/misc/mvebu-io-win.rst
diff --git a/docs/plat/marvell/misc/mvebu-iob.rst b/docs/plat/marvell/armada/misc/mvebu-iob.rst
similarity index 100%
rename from docs/plat/marvell/misc/mvebu-iob.rst
rename to docs/plat/marvell/armada/misc/mvebu-iob.rst
diff --git a/docs/plat/marvell/porting.rst b/docs/plat/marvell/armada/porting.rst
similarity index 90%
rename from docs/plat/marvell/porting.rst
rename to docs/plat/marvell/armada/porting.rst
index 0a71dbd..1723ebb 100644
--- a/docs/plat/marvell/porting.rst
+++ b/docs/plat/marvell/armada/porting.rst
@@ -8,13 +8,13 @@
 Source Code Structure
 ---------------------
 
-- The customer platform specific code shall reside under ``plat/marvell/<soc family>/<soc>_cust``
-  (e.g. 'plat/marvell/a8k/a7040_cust').
+- The customer platform specific code shall reside under ``plat/marvell/armada/<soc family>/<soc>_cust``
+  (e.g. 'plat/marvell/armada/a8k/a7040_cust').
 - The platform name for build purposes is called ``<soc>_cust`` (e.g. ``a7040_cust``).
 - The build system will reuse all files from within the soc directory, and take only the porting
   files from the customer platform directory.
 
-Files that require porting are located at ``plat/marvell/<soc family>/<soc>_cust`` directory.
+Files that require porting are located at ``plat/marvell/armada/<soc family>/<soc>_cust`` directory.
 
 
 Armada-70x0/Armada-80x0 Porting
@@ -64,7 +64,7 @@
 - Example:
 
 In A7040-DB specific implementation
-(``plat/marvell/a8k/a70x0/board/marvell_plat_config.c``), the image skip is
+(``plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c``), the image skip is
 implemented using GPIO: mpp 33 (SW5).
 
 Before resetting the board make sure there is a valid image on the next flash
@@ -91,7 +91,7 @@
 the boot process.
 
 Each supported platform of the TF-A has its own DDR porting file called
-dram_port.c located at ``atf/plat/marvell/a8k/<platform>/board`` directory.
+dram_port.c located at ``atf/plat/marvell/armada/a8k/<platform>/board`` directory.
 
 Please refer to '<path_to_mv_ddr_sources>/doc/porting_guide.txt' for detailed
 porting description.
@@ -128,7 +128,7 @@
     The porting layer for PHY was introduced in TF-A. There is one file
     ``drivers/marvell/comphy/phy-default-porting-layer.h`` which contains the
     defaults. Those default parameters are used only if there is no appropriate
-    phy-porting-layer.h file under: ``plat/marvell/<soc
+    phy-porting-layer.h file under: ``plat/marvell/armada/<soc
     family>/<platform>/board/phy-porting-layer.h``. If the phy-porting-layer.h
     exists, the phy-default-porting-layer.h is not going to be included.
 
@@ -140,7 +140,7 @@
     The easiest way to prepare the PHY porting layer for custom board is to copy
     existing example to a new platform:
 
-    - cp ``plat/marvell/a8k/a80x0/board/phy-porting-layer.h`` "plat/marvell/<soc family>/<platform>/board/phy-porting-layer.h"
+    - cp ``plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h`` "plat/marvell/armada/<soc family>/<platform>/board/phy-porting-layer.h"
     - adjust relevant parameters or
     - if different comphy index is used for specific feature, move it to proper table entry and then adjust.
 
@@ -150,7 +150,7 @@
 
 - Example:
     Example porting layer for armada-8040-db is under:
-    ``plat/marvell/a8k/a80x0/board/phy-porting-layer.h``
+    ``plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h``
 
     .. note::
         If there is no PHY porting layer for new platform (missing
diff --git a/docs/plat/marvell/index.rst b/docs/plat/marvell/index.rst
index 89ebdc0..0d33432 100644
--- a/docs/plat/marvell/index.rst
+++ b/docs/plat/marvell/index.rst
@@ -5,10 +5,10 @@
    :maxdepth: 1
    :caption: Contents
 
-   build
-   porting
-   misc/mvebu-a8k-addr-map
-   misc/mvebu-amb
-   misc/mvebu-ccu
-   misc/mvebu-io-win
-   misc/mvebu-iob
+   armada/build
+   armada/porting
+   armada/misc/mvebu-a8k-addr-map
+   armada/misc/mvebu-amb
+   armada/misc/mvebu-ccu
+   armada/misc/mvebu-io-win
+   armada/misc/mvebu-iob
diff --git a/docs/plat/meson-axg.rst b/docs/plat/meson-axg.rst
index 1e4b2c2..6f6732e 100644
--- a/docs/plat/meson-axg.rst
+++ b/docs/plat/meson-axg.rst
@@ -24,4 +24,4 @@
 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
+.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/doc/board/amlogic/s400.rst
diff --git a/docs/plat/meson-g12a.rst b/docs/plat/meson-g12a.rst
index 7cd1bf7..9588ec4 100644
--- a/docs/plat/meson-g12a.rst
+++ b/docs/plat/meson-g12a.rst
@@ -20,8 +20,8 @@
     CROSS_COMPILE=aarch64-linux-gnu- make DEBUG=1 PLAT=g12a
 
 This port has been tested on a SEI510 board. After building it, follow the
-instructions in the `gxlimg repository` or `U-Boot repository`_, replacing the
+instructions in the `gxlimg repository`_ or `U-Boot repository`_, replacing the
 mentioned **bl31.img** by the one built from this port.
 
 .. _gxlimg repository: https://github.com/repk/gxlimg/blob/master/README.g12a
-.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/board/amlogic/sei510/README
+.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/doc/board/amlogic/sei510.rst
diff --git a/docs/plat/meson-gxl.rst b/docs/plat/meson-gxl.rst
index c6d8504..0751f1d 100644
--- a/docs/plat/meson-gxl.rst
+++ b/docs/plat/meson-gxl.rst
@@ -20,8 +20,8 @@
     CROSS_COMPILE=aarch64-linux-gnu- make DEBUG=1 PLAT=gxl
 
 This port has been tested on a Lepotato. After building it, follow the
-instructions in the `gxlimg repository` or `U-Boot repository`_, replacing the
+instructions in the `gxlimg repository`_ or `U-Boot repository`_, replacing the
 mentioned **bl31.img** by the one built from this port.
 
 .. _gxlimg repository: https://github.com/repk/gxlimg/blob/master/README
-.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/board/amlogic/p212/README.libretech-cc
+.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/doc/board/amlogic/p212.rst
diff --git a/docs/plat/mt8192.rst b/docs/plat/mt8192.rst
new file mode 100644
index 0000000..369afcf
--- /dev/null
+++ b/docs/plat/mt8192.rst
@@ -0,0 +1,21 @@
+MediaTek 8192
+=============
+
+MediaTek 8192 (MT8192) is a 64-bit ARM SoC introduced by MediaTek in 2020.
+The chip incorporates eight cores - four Cortex-A55 little cores and Cortex-A76.
+Cortex-A76 can operate at up to 2.2 GHz.
+Cortex-A55 can operate at up to 2 GHz.
+
+Boot Sequence
+-------------
+
+::
+
+    Boot Rom --> Coreboot --> TF-A BL31 --> Depthcharge --> Linux Kernel
+
+How to Build
+------------
+
+.. code:: shell
+
+    make CROSS_COMPILE=aarch64-linux-gnu- PLAT=mt8192 DEBUG=1 COREBOOT=1
diff --git a/docs/plat/qemu.rst b/docs/plat/qemu.rst
index afa32c1..66b8247 100644
--- a/docs/plat/qemu.rst
+++ b/docs/plat/qemu.rst
@@ -20,11 +20,46 @@
 Current limitations:
 
 -  Only cold boot is supported
--  No build instructions for QEMU\_EFI.fd and rootfs-arm64.cpio.gz
 
-``QEMU_EFI.fd`` can be dowloaded from
+Getting non-TF images
+---------------------
+
+``QEMU_EFI.fd`` can be downloaded from
 http://snapshots.linaro.org/components/kernel/leg-virt-tianocore-edk2-upstream/latest/QEMU-KERNEL-AARCH64/RELEASE_GCC5/QEMU_EFI.fd
 
+or, can be built as follows:
+
+.. code:: shell
+
+    git clone https://github.com/tianocore/edk2.git
+    cd edk2
+    git submodule update --init
+    make -C BaseTools
+    source edksetup.sh
+    export GCC5_AARCH64_PREFIX=aarch64-linux-gnu-
+    build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtQemuKernel.dsc
+
+````
+
+Then, you will get ``Build/ArmVirtQemuKernel-AARCH64/DEBUG_GCC5/FV/QEMU_EFI.fd``
+
+Please note you do not need to use GCC 5 in spite of the environment variable
+``GCC5_AARCH64_PREFIX``
+
+The rootfs can be built by using Buildroot as follows:
+
+.. code:: shell
+
+    git clone git://git.buildroot.net/buildroot.git
+    cd buildroot
+    make qemu_aarch64_virt_defconfig
+    utils/config -e BR2_TARGET_ROOTFS_CPIO
+    utils/config -e BR2_TARGET_ROOTFS_CPIO_GZIP
+    make olddefconfig
+    make
+
+Then, you will get ``output/images/rootfs.cpio.gz``.
+
 Booting via semi-hosting option
 -------------------------------
 
@@ -43,14 +78,14 @@
 
     make CROSS_COMPILE=aarch64-none-elf- PLAT=qemu
 
-To start (QEMU v4.1.0):
+To start (QEMU v5.0.0):
 
 .. code:: shell
 
     qemu-system-aarch64 -nographic -machine virt,secure=on -cpu cortex-a57  \
         -kernel Image                           \
-        -append "console=ttyAMA0,38400 keep_bootcon root=/dev/vda2"   \
-        -initrd rootfs-arm64.cpio.gz -smp 2 -m 1024 -bios bl1.bin   \
+        -append "console=ttyAMA0,38400 keep_bootcon"   \
+        -initrd rootfs.cpio.gz -smp 2 -m 1024 -bios bl1.bin   \
         -d unimp -semihosting-config enable,target=native
 
 Booting via flash based firmwares
@@ -92,12 +127,12 @@
     dd if=build/qemu/release/bl1.bin of=flash.bin bs=4096 conv=notrunc
     dd if=build/qemu/release/fip.bin of=flash.bin seek=64 bs=4096 conv=notrunc
 
-To start (QEMU v2.6.0):
+To start (QEMU v5.0.0):
 
 .. code:: shell
 
     qemu-system-aarch64 -nographic -machine virt,secure=on -cpu cortex-a57  \
         -kernel Image -no-acpi                     \
-        -append 'console=ttyAMA0,38400 keep_bootcon root=/dev/vda2'  \
-        -initrd rootfs-arm64.cpio.gz -smp 2 -m 1024 -bios flash.bin   \
+        -append 'console=ttyAMA0,38400 keep_bootcon'  \
+        -initrd rootfs.cpio.gz -smp 2 -m 1024 -bios flash.bin   \
         -d unimp
diff --git a/docs/process/security-reporting.asc b/docs/process/security-reporting.asc
deleted file mode 100644
index 8c41f7b..0000000
--- a/docs/process/security-reporting.asc
+++ /dev/null
@@ -1,45 +0,0 @@
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: PGP Desktop 10.2.0 (Build 2317)
-
-mQENBFey/QMBCACyxJaLsMYU794ZfzLdY172tHXRJfP0X3b34HU35G7kYl1zNiYc
-/NoygtQdtDv/aW1B2A/YTNhGge+gX4BWAREd5CYDbdPEoMWC395/qbnmMmez7YNY
-PEJ9Iq9e5AayAWwZTL1zgKwdvE+WTwWok/nMbsifJSEdhdrOIHNqRcZgplUUyZ2R
-sDqFtSbACO3xj4Psk8KJ23Ax7UZgULouZOJaHOnyq8F9V/U7zWvX4Odf96XaC1Em
-cUTsG0kQfa7Y4Hqqjzowq366I4k2o2LAtuLPWNCvq5jjEceLs2+qV4cNLgyL2dzO
-wtUL6EdkrGfkxsPHpsVKXig4wjeX9ehCSqRlABEBAAG0PVRydXN0ZWQgRmlybXdh
-cmUgU2VjdXJpdHkgPHRydXN0ZWQtZmlybXdhcmUtc2VjdXJpdHlAYXJtLmNvbT6J
-AYwEEAECAHYFAley/SEwFIAAAAAAIAAHcHJlZmVycmVkLWVtYWlsLWVuY29kaW5n
-QHBncC5jb21wZ3BtaW1lCAsJCAcDAgEKAhkBGRhsZGFwOi8va2V5c2VydmVyLnBn
-cC5jb20FGwMAAAAFFgADAgEFHgEAAAAGFQgJCgMCAAoJEDq378tFoN/QFJsH/0ly
-H91LYYzKIQrbolQw7Rp47lgzH88uN1rInYpW2GaTbjwPffAhYJ4VsN8RaiFskD9m
-DjMg4vY8p0jPTCUX1Acq20Wq0Ybv3HcrtjUp4ie0+rLUi3043yJyKFMWkJC2Kr+p
-SobnxSrAie4HDFUgSaPoh9Qf1zXEzOavdgcziMiyS5iVUf6NXYZ9z82OTZ6TdPKS
-u+L5zOHTdrV3+hD54w00Xa+EIE7u4v0to6Uwm977508hyGuvpOVq+u7+S3qJQvnY
-+JheStbgLsm6CyoRjyrlTE01ujAD6hI6Ef9yMgEljOBEy4phKAJ67SCRLEOiCp5U
-YHFCULwhzIyg2y3WmZSJASIEEAECAAwFAlezAnwFAwASdQAACgkQlxC4m8pXrXzd
-GAf/T8YEICI9qQt2vnCtCbBvVaTc2sAphVZ51kZVDqCDPB7znDtJYRBpi/9IPELt
-mYwIElMx2mqmahVaeUghmbzmcLZe8QHUi8GanO1mh+ook6uyjRojSIq6VUVV5uUf
-tuscfhpilOvUclqMqYEIgXfl08YwS40Kmmj0qokwad0co0zGQ8GEhlgMi2yvJfiG
-fPS0Xcn1J0980E/VgJQCAKwZvukrbb32WVwuhgepqs/4/62PZNxglcErioFt6P0A
-ik4t9Hr0uErqCeEKiYtmEw5e9ioRdX7CV+tJgIk907Tpv6E0iDFRJHmJBvmsz82O
-stOazS3wZ5Xck7asTqkvoyo9Z7kBDQRXsv0DAQgAsmL1UUIWyoNmYJWixSPDmclP
-0ul3T1FCOsIlWTeVeshnHByYdgZOfce78ETCUoq8G7qvYm4GRrEDpqVbxqTxJioP
-4Li05WDdNCKzSoqWd8ADA48gYnnJEu2NhA7ZkEC6u3+Mdbmd3M0J6nsAWeE0BV1p
-F5zI600sJuoH2QNWB7Kv5N3GCFE4IgCIH8MwDo4Y4FTZtygx4GjEtSExiOIz+bpX
-2+GkFCQGpIyLHLP4FmQmrsNzsIdEyFuG0IdoVuQ2PtNLiw+Wkm7CXWgRmFx/dtPN
-eVnOFWdbTtjBWVv/Z6zbANos2knfc75KR4FCQ6pWRvVeJuMuMopUDkfFDMtR8QAR
-AQABiQJBBBgBAgErBQJXsv0EBRsMAAAAwF0gBBkBCAAGBQJXsv0DAAoJENaB8ph8
-s9hu/nsH/Rx696ZR+1vZi5qCTUwo6s0Qa15x4OuyJEM85VgMLVY7/MZpp1Y8If6u
-A5BynQpy4QIPxIRsRx6twduW9/gb8UVhpMRPyuJ+5sSv0/KeUqkPbKSUGro2zGlR
-sjqPrchi6uafWZqOR/y/DNkEvkgZZaP+f9xs2qWKuoF08yTioo76QoroA4DVuVAT
-MkDFe9d3natAmfmjO4kvxuthg3y7R+sdXrCHpYYJZdbiR6gyj7e8whlSLwHQT3lz
-7QBL/CvVvL/dmhu5pk8fsksbehepMQTkCJ6GGEamOPEhwh7IvlzhEt97U4uzjuMd
-BPjqOCes+4QTmn/+lMTySG0kXxnHOEUACgkQOrfvy0Wg39D8Jgf/Uf3epkMOJ9xm
-N1l5vW8tQQ6RR055YQxQ9P6JMyCQGEJmGOcvrasCho69wMQDy4AYVtJaZd25LH/3
-LX/lcyDOP4C9VYXM+IxlcaRmjBKqWx9UzQeeioIkfmjMpJFU846ZP1dacge0lPx8
-p6ocPbM0rkv0xuF/dwkDQd4BPSmv4/3/UM8FRoYo8Q7SHkDR98wJ8FCm6k9wRtWC
-K/jzmBswY2TewAHom3jLzTM0FZ/n5Sini3EGAI2EvnQrxWRpeE7ZOkHKqLHEOaHl
-zeST4U/cUgxhwgnhbGJ7zmrFsHpYnnZYM3mIKfQ3/EhksZ68TF9IB1tfUiQTij4r
-9jWa0ybRdQ==
-=nZZb
------END PGP PUBLIC KEY BLOCK-----
diff --git a/docs/process/security.rst b/docs/process/security.rst
index c3935da..516eb98 100644
--- a/docs/process/security.rst
+++ b/docs/process/security.rst
@@ -20,40 +20,13 @@
 Although we try to keep TF-A secure, we can only do so with the help of the
 community of developers and security researchers.
 
-If you think you have found a security vulnerability, please **do not** report it
-in the `issue tracker`_. Instead send an email to
-trusted-firmware-security@arm.com
-
-Please include:
-
-* Trusted Firmware-A version (or commit) affected
-
-* A description of the concern or vulnerability
-
-* Details on how to replicate the vulnerability, including:
-
-  - Configuration details
-
-  - Proof of concept exploit code
-
-  - Any additional software or tools required
-
-We recommend using :download:`this PGP/GPG key <./security-reporting.asc>` for
-encrypting the information. This key is also available at
-http://keyserver.pgp.com and LDAP port 389 of the same server.
-
-The fingerprint for this key is:
-
-::
-
-    1309 2C19 22B4 8E87 F17B FE5C 3AB7 EFCB 45A0 DFD0
-
-If you would like replies to be encrypted, please provide your public key.
-
-Please give us the time to respond to you and fix the vulnerability before going
-public. We do our best to respond and fix any issues quickly. We also need to
-ensure providers of products that use TF-A have a chance to consider the
-implications of the vulnerability and its remedy.
+If you think you have found a security vulnerability, please **do not** report
+it in the `issue tracker`_. Instead, please follow the `TrustedFirmware.org
+security incident process`_. One of the goals of this process is to ensure
+providers of products that use TF-A have a chance to consider the implications
+of the vulnerability and its remedy before it is made public. As such, please
+follow the disclosure plan outlined in the process. We do our best to respond
+and fix any issues quickly.
 
 Afterwards, we encourage you to write-up your findings about the TF-A source
 code.
@@ -61,8 +34,8 @@
 Attribution
 -----------
 
-We will name and thank you in the :ref:`Change Log & Release Notes` distributed with the source
-code and in any published security advisory.
+We will name and thank you in the :ref:`Change Log & Release Notes` distributed
+with the source code and in any published security advisory.
 
 Security Advisories
 -------------------
@@ -96,7 +69,6 @@
 +-----------+------------------------------------------------------------------+
 
 .. _issue tracker: https://developer.trustedfirmware.org/project/board/1/
-.. _this PGP/GPG key: security-reporting.asc
 
 .. |TFV-1| replace:: :ref:`Advisory TFV-1 (CVE-2016-10319)`
 .. |TFV-2| replace:: :ref:`Advisory TFV-2 (CVE-2017-7564)`
@@ -107,6 +79,8 @@
 .. |TFV-7| replace:: :ref:`Advisory TFV-7 (CVE-2018-3639)`
 .. |TFV-8| replace:: :ref:`Advisory TFV-8 (CVE-2018-19440)`
 
+.. _TrustedFirmware.org security incident process: https://developer.trustedfirmware.org/w/collaboration/security_center/
+
 --------------
 
-*Copyright (c) 2019, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/docs/resources/diagrams/ff-a-spm-sel2.png b/docs/resources/diagrams/ff-a-spm-sel2.png
new file mode 100644
index 0000000..6479ff5
--- /dev/null
+++ b/docs/resources/diagrams/ff-a-spm-sel2.png
Binary files differ
diff --git a/docs/resources/diagrams/plantuml/bl2-loading-sp.puml b/docs/resources/diagrams/plantuml/bl2-loading-sp.puml
new file mode 100644
index 0000000..3cf7c36
--- /dev/null
+++ b/docs/resources/diagrams/plantuml/bl2-loading-sp.puml
@@ -0,0 +1,44 @@
+/'
+ ' Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ '
+ ' SPDX-License-Identifier: BSD-3-Clause
+ '/
+
+@startuml
+participant bl1
+participant FIP
+
+bl1 -> FIP : read(FW_CONFIG)
+create FW_CONFIG
+bl1 -> FW_CONFIG : load
+
+bl1 -> FIP : read(bl2)
+create bl2
+bl1 -> bl2 : load
+bl1 --> bl2 : hand off (FW_CONFIG)
+
+bl2 -> FW_CONFIG : read_node(SPKs)
+loop for each spkg subnode
+  bl2 -> FW_CONFIG : read(UUID)
+  bl2 -> FW_CONFIG : read(load_address)
+  bl2 -> FIP : read(spkg@UUID)
+  create SPKG
+  bl2 -> SPKG : load
+end loop
+
+bl2 -> FW_CONFIG : read_node(TOS_FW_CONFIG)
+create TOS_FW_CONFIG
+bl2 -> TOS_FW_CONFIG : load
+
+bl2 -> FIP : read(bl32/SPMC)
+create SPMC
+bl2 -> SPMC : load
+
+bl2 -> FIP : read(bl31)
+create bl31
+bl2 -> bl31 : load
+bl2 --> bl31 : hand off (TOS_FW_CONFIG)
+
+bl31 --> SPMC : hand off (TOS_FW_CONFIG)
+
+@enduml
diff --git a/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml b/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml
index e613eef..e513ed4 100644
--- a/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml
+++ b/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml
@@ -13,6 +13,7 @@
 
 box "platform common code"
 	participant plat_bl1_common
+	participant fconf_dyn_cfg_getter
 	participant fconf
 end box
 
@@ -20,12 +21,17 @@
 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()
+arm_bl1_setup -> fconf : set_fw_config_info(fw_config_base, max_size)
+note over fconf
+	set fw_config information
+	(address, size, image_id)
+	in global dtb_infos array.
+end note
 activate fconf
-	note over fconf
-		create and populate an
-		image_desc_t for FW_CONFIG
-	end note
+	arm_bl1_setup -> fconf : fconf_load_config(FW_CONFIG_ID)
+	fconf -> fconf : FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID)
+	fconf -> fconf_dyn_cfg_getter: dyn_cfg_dtb_info_getter(FW_CONFIG_ID)
+	fconf_dyn_cfg_getter -> fconf: fw_config_info
 	fconf -> bl_common : load_auth_image(FW_CONFIG_ID, &image_info)
 	activate bl_common
 	note over bl_common
@@ -33,18 +39,38 @@
 		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
+	arm_io_storage -> fconf: FCONF_GET_PROPERTY(arm, arm_io_policies, FW_CONFIG_ID)
+	note over fconf: use statically defined policies in bl1
+	fconf <- bl_common : image_info
+	deactivate bl_common
+	note over fconf : get fw_config_dtb from image_info
+	arm_bl1_setup -> fconf: FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID)
+	fconf -> fconf_dyn_cfg_getter: dyn_cfg_dtb_info_getter(FW_CONFIG_ID)
+	fconf_dyn_cfg_getter -> arm_bl1_setup: fw_config_info
+	arm_bl1_setup -> fconf_dyn_cfg_getter: populate_dtb_registry(uintptr_t dtb)
+	arm_bl1_setup -> fconf: fconf_load_config(TB_FW_CONFIG_ID)
+	fconf -> fconf : FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID)
+	fconf -> fconf_dyn_cfg_getter: dyn_cfg_dtb_info_getter(TB_FW_CONFIG_ID)
+	fconf_dyn_cfg_getter -> fconf: tb_fw_config_info
+	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_CONFIG_ID)
+	note over fconf: use statically 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 FW_CONFIG base address
+	fconf -> arm_bl1_setup
+	arm_bl1_setup -> plat_bl1_common : bl1_plat_get_image_desc(BL2_IMAGE_ID)
+	arm_bl1_setup <- plat_bl1_common : BL2_IMAGE_DESC
+	note over arm_bl1_setup
+	set ep_info.args.arg0 of BL2_IMAGE_DESC
+	to FW_CONFIG base address
 	end note
-arm_bl1_setup <- fconf
 deactivate fconf
 
 == load & auth, prepare and jump to BL2 ==
diff --git a/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml b/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml
index 881f253..c536ee0 100644
--- a/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml
+++ b/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml
@@ -8,6 +8,7 @@
 box "platform common code"
 	participant fconf
 	participant fconf_tbbr_getter
+participant fconf_dyn_cfg_getter
 end box
 
 box "arm platform code" #LightBlue
@@ -25,10 +26,17 @@
 end note
 arm_bl2_setup -> arm_bl2_setup : arm_bl2_early_platform_setup(\n\t fw_config, mem_layout)
 activate arm_bl2_setup
-	arm_bl2_setup -> fconf: fconf_polulate("TB_FW", fw_config)
+	arm_bl2_setup -> fconf: fconf_populate("FW_CONFIG", fw_config)
 	activate fconf
+		fconf -> fconf_dyn_cfg_getter: populate_dtb_registry(uintptr_t dtb)
+		note over fconf_dyn_cfg_getter: read dtb_registry properties from dtb
+		fconf_dyn_cfg_getter -> arm_bl2_setup
+		arm_bl2_setup -> fconf: FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID)
+		fconf -> fconf_dyn_cfg_getter: dyn_cfg_dtb_info_getter(TB_FW_CONFIG_ID)
+		fconf_dyn_cfg_getter -> arm_bl2_setup: tb_fw_config_info
+		arm_bl2_setup -> fconf: fconf_populate("TB_FW_CONFIG", tb_fw_config)
 		fconf -> fconf_tbbr_getter: fconf_populate_tbbr_dyn_config(uintptr_t dtb)
-		note over fconf_tbbr_getter: read tbbr propeties from dtb
+		note over fconf_tbbr_getter: read tbbr properties 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
diff --git a/docs/resources/diagrams/plantuml/fip-secure-partitions.puml b/docs/resources/diagrams/plantuml/fip-secure-partitions.puml
new file mode 100644
index 0000000..40621db
--- /dev/null
+++ b/docs/resources/diagrams/plantuml/fip-secure-partitions.puml
@@ -0,0 +1,122 @@
+/'
+ ' Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ '
+ ' SPDX-License-Identifier: BSD-3-Clause
+ '/
+
+@startuml
+
+folder SP_vendor_1 {
+ artifact sp_binary_1
+ artifact sp_manifest_1 [
+ sp_manifest_1
+ ===
+ UUID = xxx
+ load_address = 0xaaa
+ ...
+ ]
+}
+
+folder SP_vendor_2 {
+ artifact sp_binary_2
+ artifact sp_manifest_2 [
+ sp_manifest_2
+ ===
+ UUID = yyy
+ load_address = 0xbbb
+ ]
+}
+
+artifact config.json [
+ SP_LAYOUT.json
+ ===
+ path to sp_binary_1
+ path to sp_manifest_1
+ ---
+ path to sp_binary_2
+ path to sp_manifest_2
+ ---
+ ...
+]
+
+control sp_mk_generator
+
+artifact fconf_node [
+ fconf_sp.dts
+ ===
+ spkg_1 UUID
+ spkg_1 load_address
+ ---
+ spkg_2 UUID
+ spkg_2 load_address
+]
+
+artifact sp_gen [
+ sp_gen.mk
+ ===
+ FDT_SOURCE = ...
+ SPTOOL_ARGS = ...
+ FIP_ARG = ...
+]
+
+control dtc
+control sptool
+
+artifact FW_CONFIG
+
+artifact spkg_1 [
+ spkg_1.bin
+ ===
+ <i>header</i>
+ ---
+ manifest
+ ---
+ binary
+]
+
+artifact spkg_2 [
+ spkg_2.bin
+ ===
+ <i>header</i>
+ ---
+ manifest
+ ---
+ binary
+]
+
+control fiptool
+
+artifact fip [
+ fip.bin
+ ===
+ FW_CONFIG.dtb
+ ---
+ ...
+ ---
+ SPKG1
+ ---
+ SPKG2
+ ---
+ ...
+]
+
+config.json .up.> SP_vendor_1
+config.json .up.> SP_vendor_2
+config.json --> sp_mk_generator
+sp_mk_generator --> fconf_node
+sp_mk_generator --> sp_gen
+
+sp_gen --> sptool
+sptool --> spkg_1
+sptool --> spkg_2
+
+fconf_node -down-> dtc
+dtc --> FW_CONFIG
+
+sp_gen --> fiptool
+FW_CONFIG --> fiptool
+spkg_1 -down-> fiptool
+spkg_2 -down-> fiptool
+fiptool -down-> fip
+
+@enduml
diff --git a/drivers/arm/css/scp/css_bom_bootloader.c b/drivers/arm/css/scp/css_bom_bootloader.c
index 1fc1270..74121b4 100644
--- a/drivers/arm/css/scp/css_bom_bootloader.c
+++ b/drivers/arm/css/scp/css_bom_bootloader.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,13 +51,13 @@
  * All CSS platforms load SCP_BL2/SCP_BL2U just below BL2 (this is where BL31
  * usually resides except when ARM_BL31_IN_DRAM is
  * set). Ensure that SCP_BL2/SCP_BL2U do not overflow into shared RAM and
- * the tb_fw_config.
+ * the fw_config.
  */
 CASSERT(SCP_BL2_LIMIT <= BL2_BASE, assert_scp_bl2_overwrite_bl2);
 CASSERT(SCP_BL2U_LIMIT <= BL2_BASE, assert_scp_bl2u_overwrite_bl2);
 
-CASSERT(SCP_BL2_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_scp_bl2_overflow);
-CASSERT(SCP_BL2U_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_scp_bl2u_overflow);
+CASSERT(SCP_BL2_BASE >= ARM_FW_CONFIG_LIMIT, assert_scp_bl2_overflow);
+CASSERT(SCP_BL2U_BASE >= ARM_FW_CONFIG_LIMIT, assert_scp_bl2u_overflow);
 
 static void scp_boot_message_start(void)
 {
diff --git a/drivers/arm/gic/common/gic_common.c b/drivers/arm/gic/common/gic_common.c
index 38b2f67..bf6405f 100644
--- a/drivers/arm/gic/common/gic_common.c
+++ b/drivers/arm/gic/common/gic_common.c
@@ -1,9 +1,11 @@
 /*
- * 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
  */
 
+#pragma message __FILE__ " is deprecated, use gicv2.mk instead"
+
 #include <assert.h>
 
 #include <drivers/arm/gic_common.h>
diff --git a/drivers/arm/gic/v2/gicdv2_helpers.c b/drivers/arm/gic/v2/gicdv2_helpers.c
new file mode 100644
index 0000000..db9ba87
--- /dev/null
+++ b/drivers/arm/gic/v2/gicdv2_helpers.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <drivers/arm/gic_common.h>
+#include <lib/mmio.h>
+
+#include "../common/gic_common_private.h"
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for reading entire registers
+ ******************************************************************************/
+/*
+ * Accessor to read the GIC Distributor IGROUPR corresponding to the interrupt
+ * `id`, 32 interrupt ids at a time.
+ */
+unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> IGROUPR_SHIFT;
+
+	return mmio_read_32(base + GICD_IGROUPR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ISENABLER corresponding to the
+ * interrupt `id`, 32 interrupt ids at a time.
+ */
+unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ISENABLER_SHIFT;
+
+	return mmio_read_32(base + GICD_ISENABLER + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ICENABLER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ICENABLER_SHIFT;
+
+	return mmio_read_32(base + GICD_ICENABLER + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ISPENDR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ISPENDR_SHIFT;
+
+	return mmio_read_32(base + GICD_ISPENDR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ICPENDR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ICPENDR_SHIFT;
+
+	return mmio_read_32(base + GICD_ICPENDR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ISACTIVER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ISACTIVER_SHIFT;
+
+	return mmio_read_32(base + GICD_ISACTIVER + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ICACTIVER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ICACTIVER_SHIFT;
+
+	return mmio_read_32(base + GICD_ICACTIVER + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor IPRIORITYR corresponding to the
+ * interrupt `id`, 4 interrupt IDs at a time.
+ */
+unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> IPRIORITYR_SHIFT;
+
+	return mmio_read_32(base + GICD_IPRIORITYR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor ICGFR corresponding to the
+ * interrupt `id`, 16 interrupt IDs at a time.
+ */
+unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> ICFGR_SHIFT;
+
+	return mmio_read_32(base + GICD_ICFGR + (n << 2));
+}
+
+/*
+ * Accessor to read the GIC Distributor NSACR corresponding to the
+ * interrupt `id`, 16 interrupt IDs at a time.
+ */
+unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id)
+{
+	unsigned int n = id >> NSACR_SHIFT;
+
+	return mmio_read_32(base + GICD_NSACR + (n << 2));
+}
+
+/*******************************************************************************
+ * GIC Distributor interface accessors for writing entire registers
+ ******************************************************************************/
+/*
+ * Accessor to write the GIC Distributor IGROUPR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> IGROUPR_SHIFT;
+
+	mmio_write_32(base + GICD_IGROUPR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ISENABLER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ISENABLER_SHIFT;
+
+	mmio_write_32(base + GICD_ISENABLER + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ICENABLER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ICENABLER_SHIFT;
+
+	mmio_write_32(base + GICD_ICENABLER + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ISPENDR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ISPENDR_SHIFT;
+
+	mmio_write_32(base + GICD_ISPENDR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ICPENDR corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ICPENDR_SHIFT;
+
+	mmio_write_32(base + GICD_ICPENDR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ISACTIVER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ISACTIVER_SHIFT;
+
+	mmio_write_32(base + GICD_ISACTIVER + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ICACTIVER corresponding to the
+ * interrupt `id`, 32 interrupt IDs at a time.
+ */
+void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ICACTIVER_SHIFT;
+
+	mmio_write_32(base + GICD_ICACTIVER + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor IPRIORITYR corresponding to the
+ * interrupt `id`, 4 interrupt IDs at a time.
+ */
+void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> IPRIORITYR_SHIFT;
+
+	mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor ICFGR corresponding to the
+ * interrupt `id`, 16 interrupt IDs at a time.
+ */
+void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> ICFGR_SHIFT;
+
+	mmio_write_32(base + GICD_ICFGR + (n << 2), val);
+}
+
+/*
+ * Accessor to write the GIC Distributor NSACR corresponding to the
+ * interrupt `id`, 16 interrupt IDs at a time.
+ */
+void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val)
+{
+	unsigned int n = id >> NSACR_SHIFT;
+
+	mmio_write_32(base + GICD_NSACR + (n << 2), val);
+}
+
+/*******************************************************************************
+ * GIC Distributor functions for accessing the GIC registers
+ * corresponding to a single interrupt ID. These functions use bitwise
+ * operations or appropriate register accesses to modify or return
+ * the bit-field corresponding the single interrupt ID.
+ ******************************************************************************/
+unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
+	unsigned int reg_val = gicd_read_igroupr(base, id);
+
+	return (reg_val >> bit_num) & 0x1U;
+}
+
+void gicd_set_igroupr(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
+	unsigned int reg_val = gicd_read_igroupr(base, id);
+
+	gicd_write_igroupr(base, id, reg_val | (1U << bit_num));
+}
+
+void gicd_clr_igroupr(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
+	unsigned int reg_val = gicd_read_igroupr(base, id);
+
+	gicd_write_igroupr(base, id, reg_val & ~(1U << bit_num));
+}
+
+void gicd_set_isenabler(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ISENABLER_SHIFT) - 1U);
+
+	gicd_write_isenabler(base, id, (1U << bit_num));
+}
+
+void gicd_set_icenabler(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ICENABLER_SHIFT) - 1U);
+
+	gicd_write_icenabler(base, id, (1U << bit_num));
+}
+
+void gicd_set_ispendr(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ISPENDR_SHIFT) - 1U);
+
+	gicd_write_ispendr(base, id, (1U << bit_num));
+}
+
+void gicd_set_icpendr(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ICPENDR_SHIFT) - 1U);
+
+	gicd_write_icpendr(base, id, (1U << bit_num));
+}
+
+unsigned int gicd_get_isactiver(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
+	unsigned int reg_val = gicd_read_isactiver(base, id);
+
+	return (reg_val >> bit_num) & 0x1U;
+}
+
+void gicd_set_isactiver(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U);
+
+	gicd_write_isactiver(base, id, (1U << bit_num));
+}
+
+void gicd_set_icactiver(uintptr_t base, unsigned int id)
+{
+	unsigned int bit_num = id & ((1U << ICACTIVER_SHIFT) - 1U);
+
+	gicd_write_icactiver(base, id, (1U << bit_num));
+}
+
+void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
+{
+	uint8_t val = pri & GIC_PRI_MASK;
+
+	mmio_write_8(base + GICD_IPRIORITYR + id, val);
+}
+
+void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg)
+{
+	/* Interrupt configuration is a 2-bit field */
+	unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U);
+	unsigned int bit_shift = bit_num << 1;
+
+	uint32_t reg_val = gicd_read_icfgr(base, id);
+
+	/* Clear the field, and insert required configuration */
+	reg_val &= ~(GIC_CFG_MASK << bit_shift);
+	reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift);
+
+	gicd_write_icfgr(base, id, reg_val);
+}
diff --git a/drivers/arm/gic/v2/gicv2.mk b/drivers/arm/gic/v2/gicv2.mk
new file mode 100644
index 0000000..49996bb
--- /dev/null
+++ b/drivers/arm/gic/v2/gicv2.mk
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# No support for extended PPI and SPI range
+GIC_EXT_INTID	:=	0
+
+GICV2_SOURCES	+=	drivers/arm/gic/v2/gicv2_main.c		\
+			drivers/arm/gic/v2/gicv2_helpers.c	\
+			drivers/arm/gic/v2/gicdv2_helpers.c
+
+# Set GICv2 build option
+$(eval $(call add_define,GIC_EXT_INTID))
\ No newline at end of file
diff --git a/drivers/arm/gic/v2/gicv2_main.c b/drivers/arm/gic/v2/gicv2_main.c
index c5bced0..4b21b92 100644
--- a/drivers/arm/gic/v2/gicv2_main.c
+++ b/drivers/arm/gic/v2/gicv2_main.c
@@ -247,6 +247,15 @@
 	assert(driver_data != NULL);
 	assert(driver_data->gicc_base != 0U);
 
+	/*
+	 * Ensure the write to peripheral registers are *complete* before the write
+	 * to GIC_EOIR.
+	 *
+	 * Note: The completion gurantee depends on various factors of system design
+	 * and the barrier is the best core can do by which execution of further
+	 * instructions waits till the barrier is alive.
+	 */
+	dsbishst();
 	gicc_write_EOIR(driver_data->gicc_base, id);
 }
 
diff --git a/drivers/arm/gic/v3/gic-x00.c b/drivers/arm/gic/v3/gic-x00.c
new file mode 100644
index 0000000..6e106ba
--- /dev/null
+++ b/drivers/arm/gic/v3/gic-x00.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Driver for GIC-500 and GIC-600 specific features. This driver only
+ * overrides APIs that are different to those generic ones in GICv3
+ * driver.
+ *
+ * GIC-600 supports independently power-gating redistributor interface.
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <drivers/arm/gicv3.h>
+
+#include "gicv3_private.h"
+
+/* GIC-600 specific register offsets */
+#define GICR_PWRR			0x24U
+#define IIDR_MODEL_ARM_GIC_600		U(0x0200043b)
+#define IIDR_MODEL_ARM_GIC_600AE	U(0x0300043b)
+#define IIDR_MODEL_ARM_GIC_CLAYTON	U(0x0400043b)
+
+/* GICR_PWRR fields */
+#define PWRR_RDPD_SHIFT			0
+#define PWRR_RDAG_SHIFT			1
+#define PWRR_RDGPD_SHIFT		2
+#define PWRR_RDGPO_SHIFT		3
+
+#define PWRR_RDPD			(1U << PWRR_RDPD_SHIFT)
+#define PWRR_RDAG			(1U << PWRR_RDAG_SHIFT)
+#define PWRR_RDGPD			(1U << PWRR_RDGPD_SHIFT)
+#define PWRR_RDGPO			(1U << PWRR_RDGPO_SHIFT)
+
+/*
+ * Values to write to GICR_PWRR register to power redistributor
+ * for operating through the core (GICR_PWRR.RDAG = 0)
+ */
+#define PWRR_ON				(0U << PWRR_RDPD_SHIFT)
+#define PWRR_OFF			(1U << PWRR_RDPD_SHIFT)
+
+#if GICV3_SUPPORT_GIC600
+
+/* GIC-600/Clayton specific accessor functions */
+static void gicr_write_pwrr(uintptr_t base, unsigned int val)
+{
+	mmio_write_32(base + GICR_PWRR, val);
+}
+
+static uint32_t gicr_read_pwrr(uintptr_t base)
+{
+	return mmio_read_32(base + GICR_PWRR);
+}
+
+static void gicr_wait_group_not_in_transit(uintptr_t base)
+{
+	uint32_t pwrr;
+
+	do {
+		pwrr = gicr_read_pwrr(base);
+
+	/* Check group not transitioning: RDGPD == RDGPO */
+	} while (((pwrr & PWRR_RDGPD) >> PWRR_RDGPD_SHIFT) !=
+		 ((pwrr & PWRR_RDGPO) >> PWRR_RDGPO_SHIFT));
+}
+
+static void gic600_pwr_on(uintptr_t base)
+{
+	do {	/* Wait until group not transitioning */
+		gicr_wait_group_not_in_transit(base);
+
+		/* Power on redistributor */
+		gicr_write_pwrr(base, PWRR_ON);
+
+		/*
+		 * Wait until the power on state is reflected.
+		 * If RDPD == 0 then powered on.
+		 */
+	} while ((gicr_read_pwrr(base) & PWRR_RDPD) != PWRR_ON);
+}
+
+static void gic600_pwr_off(uintptr_t base)
+{
+	/* Wait until group not transitioning */
+	gicr_wait_group_not_in_transit(base);
+
+	/* Power off redistributor */
+	gicr_write_pwrr(base, PWRR_OFF);
+
+	/*
+	 * If this is the last man, turning this redistributor frame off will
+	 * result in the group itself being powered off and RDGPD = 1.
+	 * In that case, wait as long as it's in transition, or has aborted
+	 * the transition altogether for any reason.
+	 */
+	if ((gicr_read_pwrr(base) & PWRR_RDGPD) != 0U) {
+		/* Wait until group not transitioning */
+		gicr_wait_group_not_in_transit(base);
+	}
+}
+
+static uintptr_t get_gicr_base(unsigned int proc_num)
+{
+	uintptr_t gicr_base;
+
+	assert(gicv3_driver_data != NULL);
+	assert(proc_num < gicv3_driver_data->rdistif_num);
+	assert(gicv3_driver_data->rdistif_base_addrs != NULL);
+
+	gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
+	assert(gicr_base != 0UL);
+
+	return gicr_base;
+}
+
+static bool gicv3_redists_need_power_mgmt(uintptr_t gicr_base)
+{
+	uint32_t reg = mmio_read_32(gicr_base + GICR_IIDR);
+
+	/*
+	 * The Arm GIC-600 and GIC-Clayton models have their redistributors
+	 * powered down at reset.
+	 */
+	return (((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) ||
+		((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600AE) ||
+		((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_CLAYTON));
+}
+
+#endif	/* GICV3_SUPPORT_GIC600 */
+
+void gicv3_distif_pre_save(unsigned int proc_num)
+{
+	arm_gicv3_distif_pre_save(proc_num);
+}
+
+void gicv3_distif_post_restore(unsigned int proc_num)
+{
+	arm_gicv3_distif_post_restore(proc_num);
+}
+
+/*
+ * Power off GIC-600 redistributor (if configured and detected)
+ */
+void gicv3_rdistif_off(unsigned int proc_num)
+{
+#if GICV3_SUPPORT_GIC600
+	uintptr_t gicr_base = get_gicr_base(proc_num);
+
+	/* Attempt to power redistributor off */
+	if (gicv3_redists_need_power_mgmt(gicr_base)) {
+		gic600_pwr_off(gicr_base);
+	}
+#endif
+}
+
+/*
+ * Power on GIC-600 redistributor (if configured and detected)
+ */
+void gicv3_rdistif_on(unsigned int proc_num)
+{
+#if GICV3_SUPPORT_GIC600
+	uintptr_t gicr_base = get_gicr_base(proc_num);
+
+	/* Power redistributor on */
+	if (gicv3_redists_need_power_mgmt(gicr_base)) {
+		gic600_pwr_on(gicr_base);
+	}
+#endif
+}
diff --git a/drivers/arm/gic/v3/gic500.c b/drivers/arm/gic/v3/gic500.c
deleted file mode 100644
index f03e33f..0000000
--- a/drivers/arm/gic/v3/gic500.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/*
- * Driver for GIC500-specific features. This driver only overrides APIs that are
- * different to those generic ones in GICv3 driver.
- */
-#include "gicv3_private.h"
-
-void gicv3_distif_pre_save(unsigned int proc_num)
-{
-	arm_gicv3_distif_pre_save(proc_num);
-}
-
-void gicv3_distif_post_restore(unsigned int proc_num)
-{
-	arm_gicv3_distif_post_restore(proc_num);
-}
-
diff --git a/drivers/arm/gic/v3/gic600.c b/drivers/arm/gic/v3/gic600.c
deleted file mode 100644
index 59652da..0000000
--- a/drivers/arm/gic/v3/gic600.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/*
- * Driver for GIC-600 specific features. This driver only overrides
- * APIs that are different to those generic ones in GICv3 driver.
- *
- * GIC-600 supports independently power-gating redistributor interface.
- */
-
-#include <assert.h>
-
-#include <arch_helpers.h>
-#include <drivers/arm/gicv3.h>
-
-#include "gicv3_private.h"
-
-/* GIC-600 specific register offsets */
-#define GICR_PWRR	0x24
-
-/* GICR_PWRR fields */
-#define PWRR_RDPD_SHIFT		0
-#define PWRR_RDAG_SHIFT		1
-#define PWRR_RDGPD_SHIFT	2
-#define PWRR_RDGPO_SHIFT	3
-
-#define PWRR_RDPD	(1 << PWRR_RDPD_SHIFT)
-#define PWRR_RDAG	(1 << PWRR_RDAG_SHIFT)
-#define PWRR_RDGPD	(1 << PWRR_RDGPD_SHIFT)
-#define PWRR_RDGPO	(1 << PWRR_RDGPO_SHIFT)
-
-/*
- * Values to write to GICR_PWRR register to power redistributor
- * for operating through the core (GICR_PWRR.RDAG = 0)
- */
-#define PWRR_ON		(0 << PWRR_RDPD_SHIFT)
-#define PWRR_OFF	(1 << PWRR_RDPD_SHIFT)
-
-/* GIC-600 specific accessor functions */
-static void gicr_write_pwrr(uintptr_t base, unsigned int val)
-{
-	mmio_write_32(base + GICR_PWRR, val);
-}
-
-static uint32_t gicr_read_pwrr(uintptr_t base)
-{
-	return mmio_read_32(base + GICR_PWRR);
-}
-
-static void gicr_wait_group_not_in_transit(uintptr_t base)
-{
-	/* Check group not transitioning: RDGPD == RDGPO */
-	while (((gicr_read_pwrr(base) & PWRR_RDGPD) >> PWRR_RDGPD_SHIFT) !=
-		((gicr_read_pwrr(base) & PWRR_RDGPO) >> PWRR_RDGPO_SHIFT))
-		;
-}
-
-static void gic600_pwr_on(uintptr_t base)
-{
-	do {	/* Wait until group not transitioning */
-		gicr_wait_group_not_in_transit(base);
-
-		/* Power on redistributor */
-		gicr_write_pwrr(base, PWRR_ON);
-
-		/*
-		 * Wait until the power on state is reflected.
-		 * If RDPD == 0 then powered on.
-		 */
-	} while ((gicr_read_pwrr(base) & PWRR_RDPD) != PWRR_ON);
-}
-
-static void gic600_pwr_off(uintptr_t base)
-{
-	/* Wait until group not transitioning */
-	gicr_wait_group_not_in_transit(base);
-
-	/* Power off redistributor */
-	gicr_write_pwrr(base, PWRR_OFF);
-
-	/*
-	 * If this is the last man, turning this redistributor frame off will
-	 * result in the group itself being powered off and RDGPD = 1.
-	 * In that case, wait as long as it's in transition, or has aborted
-	 * the transition altogether for any reason.
-	 */
-	if ((gicr_read_pwrr(base) & PWRR_RDGPD) != 0) {
-		/* Wait until group not transitioning */
-		gicr_wait_group_not_in_transit(base);
-	}
-}
-
-void gicv3_distif_pre_save(unsigned int proc_num)
-{
-	arm_gicv3_distif_pre_save(proc_num);
-}
-
-void gicv3_distif_post_restore(unsigned int proc_num)
-{
-	arm_gicv3_distif_post_restore(proc_num);
-}
-
-/*
- * Power off GIC-600 redistributor
- */
-void gicv3_rdistif_off(unsigned int proc_num)
-{
-	uintptr_t gicr_base;
-
-	assert(gicv3_driver_data);
-	assert(proc_num < gicv3_driver_data->rdistif_num);
-	assert(gicv3_driver_data->rdistif_base_addrs);
-
-	gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
-	assert(gicr_base);
-
-	/* Attempt to power redistributor off */
-	gic600_pwr_off(gicr_base);
-}
-
-/*
- * Power on GIC-600 redistributor
- */
-void gicv3_rdistif_on(unsigned int proc_num)
-{
-	uintptr_t gicr_base;
-
-	assert(gicv3_driver_data);
-	assert(proc_num < gicv3_driver_data->rdistif_num);
-	assert(gicv3_driver_data->rdistif_base_addrs);
-
-	gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
-	assert(gicr_base);
-
-	/* Power redistributor on */
-	gic600_pwr_on(gicr_base);
-}
diff --git a/drivers/arm/gic/v3/gicv3.mk b/drivers/arm/gic/v3/gicv3.mk
index 0f40103..a2fc16f 100644
--- a/drivers/arm/gic/v3/gicv3.mk
+++ b/drivers/arm/gic/v3/gicv3.mk
@@ -5,7 +5,7 @@
 #
 
 # Default configuration values
-GICV3_IMPL			?=	GIC500
+GICV3_SUPPORT_GIC600		?=	0
 GICV3_IMPL_GIC600_MULTICHIP	?=	0
 GICV3_OVERRIDE_DISTIF_PWR_OPS	?=	0
 GIC_ENABLE_V4_EXTN		?=	0
@@ -20,19 +20,14 @@
 GICV3_SOURCES	+=	drivers/arm/gic/v3/arm_gicv3_common.c
 endif
 
-# Either GIC-600 or GIC-500 can be selected at one time
-ifeq (${GICV3_IMPL}, GIC600)
-# GIC-600 sources
-GICV3_SOURCES	+=	drivers/arm/gic/v3/gic600.c
+GICV3_SOURCES	+=	drivers/arm/gic/v3/gic-x00.c
 ifeq (${GICV3_IMPL_GIC600_MULTICHIP}, 1)
 GICV3_SOURCES	+=	drivers/arm/gic/v3/gic600_multichip.c
 endif
-else ifeq (${GICV3_IMPL}, GIC500)
-# GIC-500 sources
-GICV3_SOURCES	+=	drivers/arm/gic/v3/gic500.c
-else
-$(error "Incorrect GICV3_IMPL value ${GICV3_IMPL}")
-endif
+
+# Set GIC-600 support
+$(eval $(call assert_boolean,GICV3_SUPPORT_GIC600))
+$(eval $(call add_define,GICV3_SUPPORT_GIC600))
 
 # Set GICv4 extension
 $(eval $(call assert_boolean,GIC_ENABLE_V4_EXTN))
diff --git a/drivers/arm/tzc/tzc_dmc620.c b/drivers/arm/tzc/tzc_dmc620.c
index 64ec5ab..7e307ee 100644
--- a/drivers/arm/tzc/tzc_dmc620.c
+++ b/drivers/arm/tzc/tzc_dmc620.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
  */
@@ -17,7 +17,7 @@
 
 /* Helper macro for getting dmc_base addr of a dmc_inst */
 #define DMC_BASE(plat_data, dmc_inst) \
-	((uintptr_t)(plat_data->dmc_base[dmc_inst]))
+	((uintptr_t)((plat_data)->dmc_base[(dmc_inst)]))
 
 /* Pointer to the tzc_dmc620_config_data structure populated by the platform */
 static const tzc_dmc620_config_data_t *g_plat_config_data;
@@ -31,8 +31,7 @@
 static void tzc_dmc620_validate_plat_driver_data(
 			const tzc_dmc620_driver_data_t *plat_driver_data)
 {
-	uint8_t dmc_inst, dmc_count;
-	unsigned int dmc_id;
+	unsigned int dmc_inst, dmc_count, dmc_id;
 	uintptr_t base;
 
 	assert(plat_driver_data != NULL);
@@ -59,7 +58,7 @@
 {
 	uint32_t min_31_00, min_47_32;
 	uint32_t max_31_00, max_47_32;
-	uint8_t dmc_inst, dmc_count;
+	unsigned int dmc_inst, dmc_count;
 	uintptr_t base;
 	const tzc_dmc620_driver_data_t *plat_driver_data;
 
@@ -67,19 +66,19 @@
 	assert(plat_driver_data != NULL);
 
 	/* Do range checks on regions. */
-	assert((region_no >= 0U) && (region_no <= DMC620_ACC_ADDR_COUNT));
+	assert((region_no >= 0) && (region_no <= DMC620_ACC_ADDR_COUNT));
 
 	/* region_base and (region_top + 1) must be 4KB aligned */
 	assert(((region_base | (region_top + 1U)) & (4096U - 1U)) == 0U);
 
 	dmc_count = plat_driver_data->dmc_count;
 	for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) {
-		min_31_00 = (region_base & MASK_31_16) | sec_attr;
-		min_47_32 = (region_base & MASK_47_32)
-				>> DMC620_ACC_ADDR_WIDTH;
-		max_31_00 = (region_top  & MASK_31_16);
-		max_47_32 = (region_top  & MASK_47_32)
-				>> DMC620_ACC_ADDR_WIDTH;
+		min_31_00 = (uint32_t)((region_base & MASK_31_16) | sec_attr);
+		min_47_32 = (uint32_t)((region_base & MASK_47_32)
+				>> DMC620_ACC_ADDR_WIDTH);
+		max_31_00 = (uint32_t)(region_top  & MASK_31_16);
+		max_47_32 = (uint32_t)((region_top  & MASK_47_32)
+				>> DMC620_ACC_ADDR_WIDTH);
 
 		/* Extract the base address of the DMC-620 instance */
 		base = DMC_BASE(plat_driver_data, dmc_inst);
@@ -100,7 +99,7 @@
  */
 static void tzc_dmc620_set_action(void)
 {
-	uint8_t dmc_inst, dmc_count;
+	unsigned int dmc_inst, dmc_count;
 	uintptr_t base;
 	const tzc_dmc620_driver_data_t *plat_driver_data;
 
@@ -123,7 +122,7 @@
  */
 static void tzc_dmc620_verify_complete(void)
 {
-	uint8_t dmc_inst, dmc_count;
+	unsigned int dmc_inst, dmc_count;
 	uintptr_t base;
 	const tzc_dmc620_driver_data_t *plat_driver_data;
 
@@ -133,8 +132,9 @@
 		/* Extract the base address of the DMC-620 instance */
 		base = DMC_BASE(plat_driver_data, dmc_inst);
 		while ((mmio_read_32(base + DMC620_MEMC_STATUS) &
-				DMC620_MEMC_CMD_MASK) != DMC620_MEMC_CMD_GO)
+				DMC620_MEMC_CMD_MASK) != DMC620_MEMC_CMD_GO) {
 			continue;
+		}
 	}
 }
 
@@ -145,7 +145,7 @@
  */
 void arm_tzc_dmc620_setup(const tzc_dmc620_config_data_t *plat_config_data)
 {
-	int i;
+	uint8_t i;
 
 	/* Check if valid pointer is passed */
 	assert(plat_config_data != NULL);
@@ -164,11 +164,12 @@
 	g_plat_config_data = plat_config_data;
 
 	INFO("Configuring DMC-620 TZC settings\n");
-	for (i = 0U; i < g_plat_config_data->acc_addr_count; i++)
+	for (i = 0U; i < g_plat_config_data->acc_addr_count; i++) {
 		tzc_dmc620_configure_region(i,
 			g_plat_config_data->plat_acc_addr_data[i].region_base,
 			g_plat_config_data->plat_acc_addr_data[i].region_top,
 			g_plat_config_data->plat_acc_addr_data[i].sec_attr);
+	}
 
 	tzc_dmc620_set_action();
 	tzc_dmc620_verify_complete();
diff --git a/drivers/auth/dualroot/cot.c b/drivers/auth/dualroot/cot.c
index eb0b020..68f3d46 100644
--- a/drivers/auth/dualroot/cot.c
+++ b/drivers/auth/dualroot/cot.c
@@ -13,47 +13,10 @@
 #include <tools_share/dualroot_oid.h>
 
 /*
- * TODO: Remove dependency on mbedTLS. The chain of trust should be agnostic of
- * the specific cryptographic library in use.
-*/
-/*
- * 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
-#define PK_DER_LEN			162
-#elif TF_MBEDTLS_KEY_SIZE == 2048
-#define PK_DER_LEN			294
-#elif TF_MBEDTLS_KEY_SIZE == 3072
-#define PK_DER_LEN			422
-#elif TF_MBEDTLS_KEY_SIZE == 4096
-#define PK_DER_LEN			550
-#else
-#error "Invalid value for TF_MBEDTLS_KEY_SIZE"
-#endif
-#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
-
-/*
  * Allocate static buffers to store the authentication parameters extracted from
  * the certificates.
  */
+static unsigned char fw_config_hash_buf[HASH_DER_LEN];
 static unsigned char tb_fw_hash_buf[HASH_DER_LEN];
 static unsigned char tb_fw_config_hash_buf[HASH_DER_LEN];
 static unsigned char hw_config_hash_buf[HASH_DER_LEN];
@@ -68,6 +31,9 @@
 static unsigned char soc_fw_config_hash_buf[HASH_DER_LEN];
 static unsigned char tos_fw_config_hash_buf[HASH_DER_LEN];
 static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN];
+#if defined(SPD_spmd)
+static unsigned char sp_pkg_hash_buf[MAX_SP_IDS][HASH_DER_LEN];
+#endif /* SPD_spmd */
 
 static unsigned char trusted_world_pk_buf[PK_DER_LEN];
 static unsigned char content_pk_buf[PK_DER_LEN];
@@ -93,6 +59,8 @@
 		AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID);
 static auth_param_type_desc_t hw_config_hash = AUTH_PARAM_TYPE_DESC(
 		AUTH_PARAM_HASH, HW_CONFIG_HASH_OID);
+static auth_param_type_desc_t fw_config_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, FW_CONFIG_HASH_OID);
 #ifdef IMAGE_BL1
 static auth_param_type_desc_t scp_bl2u_hash = AUTH_PARAM_TYPE_DESC(
 		AUTH_PARAM_HASH, SCP_FWU_CFG_HASH_OID);
@@ -135,6 +103,24 @@
 		AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID);
 static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC(
 		AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID);
+#if defined(SPD_spmd)
+static auth_param_type_desc_t sp_pkg1_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SP_PKG1_HASH_OID);
+static auth_param_type_desc_t sp_pkg2_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SP_PKG2_HASH_OID);
+static auth_param_type_desc_t sp_pkg3_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SP_PKG3_HASH_OID);
+static auth_param_type_desc_t sp_pkg4_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SP_PKG4_HASH_OID);
+static auth_param_type_desc_t sp_pkg5_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SP_PKG5_HASH_OID);
+static auth_param_type_desc_t sp_pkg6_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SP_PKG6_HASH_OID);
+static auth_param_type_desc_t sp_pkg7_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SP_PKG7_HASH_OID);
+static auth_param_type_desc_t sp_pkg8_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SP_PKG8_HASH_OID);
+#endif /* SPD_spmd */
 #endif /* IMAGE_BL2 */
 
 
@@ -182,6 +168,13 @@
 				.ptr = (void *)hw_config_hash_buf,
 				.len = (unsigned int)HASH_DER_LEN
 			}
+		},
+		[3] = {
+			.type_desc = &fw_config_hash,
+			.data = {
+				.ptr = (void *)fw_config_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
 		}
 	}
 };
@@ -235,6 +228,22 @@
 		}
 	}
 };
+
+static const auth_img_desc_t fw_config = {
+	.img_id = FW_CONFIG_ID,
+	.img_type = IMG_RAW,
+	.parent = &trusted_boot_fw_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &fw_config_hash
+			}
+		}
+	}
+};
+
 #endif /* IMAGE_BL1 */
 
 #ifdef IMAGE_BL2
@@ -680,6 +689,102 @@
 	}
 };
 
+/*
+ * Secure Partitions
+ */
+#if defined(SPD_spmd)
+static const auth_img_desc_t sip_sp_content_cert = {
+	.img_id = SIP_SP_CONTENT_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = &trusted_key_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &trusted_world_pk,
+				.sig = &sig,
+				.alg = &sig_alg,
+				.data = &raw_data
+			}
+		},
+		[1] = {
+			.type = AUTH_METHOD_NV_CTR,
+			.param.nv_ctr = {
+				.cert_nv_ctr = &trusted_nv_ctr,
+				.plat_nv_ctr = &trusted_nv_ctr
+			}
+		}
+	},
+	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &sp_pkg1_hash,
+			.data = {
+				.ptr = (void *)sp_pkg_hash_buf[0],
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[1] = {
+			.type_desc = &sp_pkg2_hash,
+			.data = {
+				.ptr = (void *)sp_pkg_hash_buf[1],
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[2] = {
+			.type_desc = &sp_pkg3_hash,
+			.data = {
+				.ptr = (void *)sp_pkg_hash_buf[2],
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[3] = {
+			.type_desc = &sp_pkg4_hash,
+			.data = {
+				.ptr = (void *)sp_pkg_hash_buf[3],
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[4] = {
+			.type_desc = &sp_pkg5_hash,
+			.data = {
+				.ptr = (void *)sp_pkg_hash_buf[4],
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[5] = {
+			.type_desc = &sp_pkg6_hash,
+			.data = {
+				.ptr = (void *)sp_pkg_hash_buf[5],
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[6] = {
+			.type_desc = &sp_pkg7_hash,
+			.data = {
+				.ptr = (void *)sp_pkg_hash_buf[6],
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[7] = {
+			.type_desc = &sp_pkg8_hash,
+			.data = {
+				.ptr = (void *)sp_pkg_hash_buf[7],
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		}
+	}
+};
+
+DEFINE_SIP_SP_PKG(1);
+DEFINE_SIP_SP_PKG(2);
+DEFINE_SIP_SP_PKG(3);
+DEFINE_SIP_SP_PKG(4);
+DEFINE_SIP_SP_PKG(5);
+DEFINE_SIP_SP_PKG(6);
+DEFINE_SIP_SP_PKG(7);
+DEFINE_SIP_SP_PKG(8);
+#endif /* SPD_spmd */
+
 #else  /* IMAGE_BL2 */
 
 /* FWU auth descriptor */
@@ -781,6 +886,7 @@
 	[BL2_IMAGE_ID]				=	&bl2_image,
 	[HW_CONFIG_ID]				=	&hw_config,
 	[TB_FW_CONFIG_ID]			=	&tb_fw_config,
+	[FW_CONFIG_ID]				=	&fw_config,
 	[FWU_CERT_ID]				=	&fwu_cert,
 	[SCP_BL2U_IMAGE_ID]			=	&scp_bl2u_image,
 	[BL2U_IMAGE_ID]				=	&bl2u_image,
@@ -807,6 +913,17 @@
 	[NON_TRUSTED_FW_CONTENT_CERT_ID]	=	&non_trusted_fw_content_cert,
 	[BL33_IMAGE_ID]				=	&bl33_image,
 	[NT_FW_CONFIG_ID]			=	&nt_fw_config,
+#if defined(SPD_spmd)
+	[SIP_SP_CONTENT_CERT_ID]		=	&sip_sp_content_cert,
+	[SP_PKG1_ID]				=	&sp_pkg1,
+	[SP_PKG2_ID]				=	&sp_pkg2,
+	[SP_PKG3_ID]				=	&sp_pkg3,
+	[SP_PKG4_ID]				=	&sp_pkg4,
+	[SP_PKG5_ID]				=	&sp_pkg5,
+	[SP_PKG6_ID]				=	&sp_pkg6,
+	[SP_PKG7_ID]				=	&sp_pkg7,
+	[SP_PKG8_ID]				=       &sp_pkg8,
+#endif
 };
 #endif
 
diff --git a/drivers/auth/mbedtls/mbedtls_common.mk b/drivers/auth/mbedtls/mbedtls_common.mk
index 564a4c9..94f2f59 100644
--- a/drivers/auth/mbedtls/mbedtls_common.mk
+++ b/drivers/auth/mbedtls/mbedtls_common.mk
@@ -75,19 +75,10 @@
 
 ifeq (${HASH_ALG}, sha384)
     TF_MBEDTLS_HASH_ALG_ID	:=	TF_MBEDTLS_SHA384
-    MBEDTLS_MD_ID		:=	MBEDTLS_MD_SHA384
-    TPM_ALG_ID			:=	TPM_ALG_SHA384
-    TCG_DIGEST_SIZE		:=	48
 else ifeq (${HASH_ALG}, sha512)
     TF_MBEDTLS_HASH_ALG_ID	:=	TF_MBEDTLS_SHA512
-    MBEDTLS_MD_ID		:=	MBEDTLS_MD_SHA512
-    TPM_ALG_ID			:=	TPM_ALG_SHA512
-    TCG_DIGEST_SIZE		:=	64
 else
     TF_MBEDTLS_HASH_ALG_ID	:=	TF_MBEDTLS_SHA256
-    MBEDTLS_MD_ID		:=	MBEDTLS_MD_SHA256
-    TPM_ALG_ID			:=	TPM_ALG_SHA256
-    TCG_DIGEST_SIZE		:=	32
 endif
 
 ifeq (${TF_MBEDTLS_KEY_ALG},ecdsa)
@@ -112,11 +103,6 @@
 $(eval $(call add_define,TF_MBEDTLS_HASH_ALG_ID))
 $(eval $(call add_define,TF_MBEDTLS_USE_AES_GCM))
 
-# Set definitions for measured boot driver
-$(eval $(call add_define,MBEDTLS_MD_ID))
-$(eval $(call add_define,TPM_ALG_ID))
-$(eval $(call add_define,TCG_DIGEST_SIZE))
-
 $(eval $(call MAKE_LIB,mbedtls))
 
 endif
diff --git a/drivers/auth/tbbr/tbbr_cot_bl1.c b/drivers/auth/tbbr/tbbr_cot_bl1.c
new file mode 100644
index 0000000..e4c9221
--- /dev/null
+++ b/drivers/auth/tbbr/tbbr_cot_bl1.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <platform_def.h>
+#include <drivers/auth/mbedtls/mbedtls_config.h>
+
+#include <drivers/auth/auth_mod.h>
+#include <drivers/auth/tbbr_cot_common.h>
+#if USE_TBBR_DEFS
+#include <tools_share/tbbr_oid.h>
+#else
+#include <platform_oid.h>
+#endif
+
+static auth_param_type_desc_t scp_bl2u_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SCP_FWU_CFG_HASH_OID);
+static auth_param_type_desc_t bl2u_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, AP_FWU_CFG_HASH_OID);
+static auth_param_type_desc_t ns_bl2u_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, FWU_HASH_OID);
+
+static const auth_img_desc_t bl2_image = {
+	.img_id = BL2_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &trusted_boot_fw_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &tb_fw_hash
+			}
+		}
+	}
+};
+
+/*
+ * FWU auth descriptor.
+ */
+static const auth_img_desc_t fwu_cert = {
+	.img_id = FWU_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = NULL,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &subject_pk,
+				.sig = &sig,
+				.alg = &sig_alg,
+				.data = &raw_data
+			}
+		}
+	},
+	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &scp_bl2u_hash,
+			.data = {
+				.ptr = (void *)scp_fw_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[1] = {
+			.type_desc = &bl2u_hash,
+			.data = {
+				.ptr = (void *)tb_fw_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[2] = {
+			.type_desc = &ns_bl2u_hash,
+			.data = {
+				.ptr = (void *)nt_world_bl_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		}
+	}
+};
+/*
+ * SCP_BL2U
+ */
+static const auth_img_desc_t scp_bl2u_image = {
+	.img_id = SCP_BL2U_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &fwu_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &scp_bl2u_hash
+			}
+		}
+	}
+};
+/*
+ * BL2U
+ */
+static const auth_img_desc_t bl2u_image = {
+	.img_id = BL2U_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &fwu_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &bl2u_hash
+			}
+		}
+	}
+};
+/*
+ * NS_BL2U
+ */
+static const auth_img_desc_t ns_bl2u_image = {
+	.img_id = NS_BL2U_IMAGE_ID,
+	.img_type = IMG_RAW,
+	.parent = &fwu_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &ns_bl2u_hash
+				}
+			}
+		}
+};
+/*
+ * TB_FW_CONFIG
+ */
+static const auth_img_desc_t tb_fw_config = {
+	.img_id = TB_FW_CONFIG_ID,
+	.img_type = IMG_RAW,
+	.parent = &trusted_boot_fw_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &tb_fw_config_hash
+			}
+		}
+	}
+};
+
+static const auth_img_desc_t fw_config = {
+	.img_id = FW_CONFIG_ID,
+	.img_type = IMG_RAW,
+	.parent = &trusted_boot_fw_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &fw_config_hash
+			}
+		}
+	}
+};
+
+/*
+ * TBBR Chain of trust definition
+ */
+static const auth_img_desc_t * const cot_desc[] = {
+	[TRUSTED_BOOT_FW_CERT_ID]		=	&trusted_boot_fw_cert,
+	[BL2_IMAGE_ID]				=	&bl2_image,
+	[HW_CONFIG_ID]				=	&hw_config,
+	[TB_FW_CONFIG_ID]			=	&tb_fw_config,
+	[FW_CONFIG_ID]				=	&fw_config,
+	[FWU_CERT_ID]				=	&fwu_cert,
+	[SCP_BL2U_IMAGE_ID]			=	&scp_bl2u_image,
+	[BL2U_IMAGE_ID]				=	&bl2u_image,
+	[NS_BL2U_IMAGE_ID]			=	&ns_bl2u_image
+};
+
+/* Register the CoT in the authentication module */
+REGISTER_COT(cot_desc);
diff --git a/drivers/auth/tbbr/tbbr_cot.c b/drivers/auth/tbbr/tbbr_cot_bl2.c
similarity index 70%
rename from drivers/auth/tbbr/tbbr_cot.c
rename to drivers/auth/tbbr/tbbr_cot_bl2.c
index 6f00b18..65a0478 100644
--- a/drivers/auth/tbbr/tbbr_cot.c
+++ b/drivers/auth/tbbr/tbbr_cot_bl2.c
@@ -10,60 +10,13 @@
 #include <drivers/auth/mbedtls/mbedtls_config.h>
 
 #include <drivers/auth/auth_mod.h>
+#include <drivers/auth/tbbr_cot_common.h>
 #if USE_TBBR_DEFS
 #include <tools_share/tbbr_oid.h>
 #else
 #include <platform_oid.h>
 #endif
 
-
-/*
- * 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
-#define PK_DER_LEN			162
-#elif TF_MBEDTLS_KEY_SIZE == 2048
-#define PK_DER_LEN			294
-#elif TF_MBEDTLS_KEY_SIZE == 3072
-#define PK_DER_LEN			422
-#elif TF_MBEDTLS_KEY_SIZE == 4096
-#define PK_DER_LEN			550
-#else
-#error "Invalid value for TF_MBEDTLS_KEY_SIZE"
-#endif
-#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
- * extracted from the certificates. In this case, because of the way the CoT is
- * established, we can reuse some of the buffers on different stages
- */
-
-static unsigned char tb_fw_hash_buf[HASH_DER_LEN];
-static unsigned char tb_fw_config_hash_buf[HASH_DER_LEN];
-static unsigned char hw_config_hash_buf[HASH_DER_LEN];
-static unsigned char scp_fw_hash_buf[HASH_DER_LEN];
-static unsigned char nt_world_bl_hash_buf[HASH_DER_LEN];
-
-#ifdef IMAGE_BL2
 static unsigned char soc_fw_hash_buf[HASH_DER_LEN];
 static unsigned char tos_fw_hash_buf[HASH_DER_LEN];
 static unsigned char tos_fw_extra1_hash_buf[HASH_DER_LEN];
@@ -74,40 +27,10 @@
 static unsigned char soc_fw_config_hash_buf[HASH_DER_LEN];
 static unsigned char tos_fw_config_hash_buf[HASH_DER_LEN];
 static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN];
-#endif
+#if defined(SPD_spmd)
+static unsigned char sp_pkg_hash_buf[MAX_SP_IDS][HASH_DER_LEN];
+#endif /* SPD_spmd */
 
-/*
- * Parameter type descriptors
- */
-static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
-		AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID);
-
-static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
-		AUTH_PARAM_PUB_KEY, 0);
-static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
-		AUTH_PARAM_SIG, 0);
-static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
-		AUTH_PARAM_SIG_ALG, 0);
-static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(
-		AUTH_PARAM_RAW_DATA, 0);
-
-
-static auth_param_type_desc_t tb_fw_hash = AUTH_PARAM_TYPE_DESC(
-		AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID);
-static auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC(
-		AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID);
-static auth_param_type_desc_t hw_config_hash = AUTH_PARAM_TYPE_DESC(
-		AUTH_PARAM_HASH, HW_CONFIG_HASH_OID);
-#ifdef IMAGE_BL1
-static auth_param_type_desc_t scp_bl2u_hash = AUTH_PARAM_TYPE_DESC(
-		AUTH_PARAM_HASH, SCP_FWU_CFG_HASH_OID);
-static auth_param_type_desc_t bl2u_hash = AUTH_PARAM_TYPE_DESC(
-		AUTH_PARAM_HASH, AP_FWU_CFG_HASH_OID);
-static auth_param_type_desc_t ns_bl2u_hash = AUTH_PARAM_TYPE_DESC(
-		AUTH_PARAM_HASH, FWU_HASH_OID);
-#endif /* IMAGE_BL1 */
-
-#ifdef IMAGE_BL2
 static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
 		AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID);
 static auth_param_type_desc_t trusted_world_pk = AUTH_PARAM_TYPE_DESC(
@@ -140,108 +63,25 @@
 		AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID);
 static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC(
 		AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID);
+#if defined(SPD_spmd)
+static auth_param_type_desc_t sp_pkg1_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SP_PKG1_HASH_OID);
+static auth_param_type_desc_t sp_pkg2_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SP_PKG2_HASH_OID);
+static auth_param_type_desc_t sp_pkg3_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SP_PKG3_HASH_OID);
+static auth_param_type_desc_t sp_pkg4_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SP_PKG4_HASH_OID);
+static auth_param_type_desc_t sp_pkg5_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SP_PKG5_HASH_OID);
+static auth_param_type_desc_t sp_pkg6_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SP_PKG6_HASH_OID);
+static auth_param_type_desc_t sp_pkg7_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SP_PKG7_HASH_OID);
+static auth_param_type_desc_t sp_pkg8_hash = AUTH_PARAM_TYPE_DESC(
+		AUTH_PARAM_HASH, SP_PKG8_HASH_OID);
+#endif /* SPD_spmd */
 
-#endif /* IMAGE_BL2 */
-
-
-	/*
-	 * BL2
-	 */
-static const auth_img_desc_t trusted_boot_fw_cert = {
-	.img_id = TRUSTED_BOOT_FW_CERT_ID,
-	.img_type = IMG_CERT,
-	.parent = NULL,
-	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
-		[0] = {
-			.type = AUTH_METHOD_SIG,
-			.param.sig = {
-				.pk = &subject_pk,
-				.sig = &sig,
-				.alg = &sig_alg,
-				.data = &raw_data
-			}
-		},
-		[1] = {
-			.type = AUTH_METHOD_NV_CTR,
-			.param.nv_ctr = {
-				.cert_nv_ctr = &trusted_nv_ctr,
-				.plat_nv_ctr = &trusted_nv_ctr
-			}
-		}
-	},
-	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
-		[0] = {
-			.type_desc = &tb_fw_hash,
-			.data = {
-				.ptr = (void *)tb_fw_hash_buf,
-				.len = (unsigned int)HASH_DER_LEN
-			}
-		},
-		[1] = {
-			.type_desc = &tb_fw_config_hash,
-			.data = {
-				.ptr = (void *)tb_fw_config_hash_buf,
-				.len = (unsigned int)HASH_DER_LEN
-			}
-		},
-		[2] = {
-			.type_desc = &hw_config_hash,
-			.data = {
-				.ptr = (void *)hw_config_hash_buf,
-				.len = (unsigned int)HASH_DER_LEN
-			}
-		}
-	}
-	};
-#ifdef IMAGE_BL1
-static const auth_img_desc_t bl2_image = {
-	.img_id = BL2_IMAGE_ID,
-	.img_type = IMG_RAW,
-	.parent = &trusted_boot_fw_cert,
-	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
-		[0] = {
-			.type = AUTH_METHOD_HASH,
-			.param.hash = {
-				.data = &raw_data,
-				.hash = &tb_fw_hash
-			}
-		}
-	}
-};
-#endif /* IMAGE_BL1 */
-/* HW Config */
-static const auth_img_desc_t hw_config = {
-	.img_id = HW_CONFIG_ID,
-	.img_type = IMG_RAW,
-	.parent = &trusted_boot_fw_cert,
-	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
-		[0] = {
-			.type = AUTH_METHOD_HASH,
-			.param.hash = {
-				.data = &raw_data,
-				.hash = &hw_config_hash
-			}
-		}
-	}
-};
-/* TB FW Config */
-#ifdef IMAGE_BL1
-static const auth_img_desc_t tb_fw_config = {
-	.img_id = TB_FW_CONFIG_ID,
-	.img_type = IMG_RAW,
-	.parent = &trusted_boot_fw_cert,
-	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
-		[0] = {
-			.type = AUTH_METHOD_HASH,
-			.param.hash = {
-				.data = &raw_data,
-				.hash = &tb_fw_config_hash
-			}
-		}
-	}
-};
-#endif /* IMAGE_BL1 */
-#ifdef IMAGE_BL2
 /*
  * Trusted key certificate
  */
@@ -716,117 +556,100 @@
 		}
 	}
 };
-#else  /* IMAGE_BL2 */
-/*
- * FWU auth descriptor.
- */
-static const auth_img_desc_t fwu_cert = {
-	.img_id = FWU_CERT_ID,
+/* Secure Partitions */
+#if defined(SPD_spmd)
+static const auth_img_desc_t sip_sp_content_cert = {
+	.img_id = SIP_SP_CONTENT_CERT_ID,
 	.img_type = IMG_CERT,
-	.parent = NULL,
+	.parent = &trusted_key_cert,
 	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
 		[0] = {
 			.type = AUTH_METHOD_SIG,
 			.param.sig = {
-				.pk = &subject_pk,
+				.pk = &trusted_world_pk,
 				.sig = &sig,
 				.alg = &sig_alg,
 				.data = &raw_data
 			}
+		},
+		[1] = {
+			.type = AUTH_METHOD_NV_CTR,
+			.param.nv_ctr = {
+				.cert_nv_ctr = &trusted_nv_ctr,
+				.plat_nv_ctr = &trusted_nv_ctr
+			}
 		}
 	},
 	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
 		[0] = {
-			.type_desc = &scp_bl2u_hash,
+			.type_desc = &sp_pkg1_hash,
 			.data = {
-				.ptr = (void *)scp_fw_hash_buf,
+				.ptr = (void *)sp_pkg_hash_buf[0],
 				.len = (unsigned int)HASH_DER_LEN
 			}
 		},
 		[1] = {
-			.type_desc = &bl2u_hash,
+			.type_desc = &sp_pkg2_hash,
 			.data = {
-				.ptr = (void *)tb_fw_hash_buf,
+				.ptr = (void *)sp_pkg_hash_buf[1],
 				.len = (unsigned int)HASH_DER_LEN
 			}
 		},
 		[2] = {
-			.type_desc = &ns_bl2u_hash,
+			.type_desc = &sp_pkg3_hash,
 			.data = {
-				.ptr = (void *)nt_world_bl_hash_buf,
+				.ptr = (void *)sp_pkg_hash_buf[2],
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[3] = {
+			.type_desc = &sp_pkg4_hash,
+			.data = {
+				.ptr = (void *)sp_pkg_hash_buf[3],
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[4] = {
+			.type_desc = &sp_pkg5_hash,
+			.data = {
+				.ptr = (void *)sp_pkg_hash_buf[4],
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[5] = {
+			.type_desc = &sp_pkg6_hash,
+			.data = {
+				.ptr = (void *)sp_pkg_hash_buf[5],
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[6] = {
+			.type_desc = &sp_pkg7_hash,
+			.data = {
+				.ptr = (void *)sp_pkg_hash_buf[6],
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[7] = {
+			.type_desc = &sp_pkg8_hash,
+			.data = {
+				.ptr = (void *)sp_pkg_hash_buf[7],
 				.len = (unsigned int)HASH_DER_LEN
 			}
 		}
 	}
 };
-/*
- * SCP_BL2U
- */
-static const auth_img_desc_t scp_bl2u_image = {
-	.img_id = SCP_BL2U_IMAGE_ID,
-	.img_type = IMG_RAW,
-	.parent = &fwu_cert,
-	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
-		[0] = {
-			.type = AUTH_METHOD_HASH,
-			.param.hash = {
-				.data = &raw_data,
-				.hash = &scp_bl2u_hash
-			}
-		}
-	}
-};
-/*
- * BL2U
- */
-static const auth_img_desc_t bl2u_image = {
-	.img_id = BL2U_IMAGE_ID,
-	.img_type = IMG_RAW,
-	.parent = &fwu_cert,
-	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
-		[0] = {
-			.type = AUTH_METHOD_HASH,
-			.param.hash = {
-				.data = &raw_data,
-				.hash = &bl2u_hash
-			}
-		}
-	}
-};
-/*
- * NS_BL2U
- */
-static const auth_img_desc_t ns_bl2u_image = {
-	.img_id = NS_BL2U_IMAGE_ID,
-	.img_type = IMG_RAW,
-	.parent = &fwu_cert,
-	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
-		[0] = {
-			.type = AUTH_METHOD_HASH,
-			.param.hash = {
-				.data = &raw_data,
-				.hash = &ns_bl2u_hash
-				}
-			}
-		}
-	};
-#endif /* IMAGE_BL2 */
-/*
- * TBBR Chain of trust definition
- */
 
-#ifdef IMAGE_BL1
-static const auth_img_desc_t * const cot_desc[] = {
-	[TRUSTED_BOOT_FW_CERT_ID]		=	&trusted_boot_fw_cert,
-	[BL2_IMAGE_ID]				=	&bl2_image,
-	[HW_CONFIG_ID]				=	&hw_config,
-	[TB_FW_CONFIG_ID]			=	&tb_fw_config,
-	[FWU_CERT_ID]				=	&fwu_cert,
-	[SCP_BL2U_IMAGE_ID]			=	&scp_bl2u_image,
-	[BL2U_IMAGE_ID]				=	&bl2u_image,
-	[NS_BL2U_IMAGE_ID]			=	&ns_bl2u_image
-};
-#else /* IMAGE_BL2 */
+DEFINE_SIP_SP_PKG(1);
+DEFINE_SIP_SP_PKG(2);
+DEFINE_SIP_SP_PKG(3);
+DEFINE_SIP_SP_PKG(4);
+DEFINE_SIP_SP_PKG(5);
+DEFINE_SIP_SP_PKG(6);
+DEFINE_SIP_SP_PKG(7);
+DEFINE_SIP_SP_PKG(8);
+#endif /* SPD_spmd */
+
 static const auth_img_desc_t * const cot_desc[] = {
 	[TRUSTED_BOOT_FW_CERT_ID]		=	&trusted_boot_fw_cert,
 	[HW_CONFIG_ID]				=	&hw_config,
@@ -848,8 +671,18 @@
 	[NON_TRUSTED_FW_CONTENT_CERT_ID]	=	&non_trusted_fw_content_cert,
 	[BL33_IMAGE_ID]				=	&bl33_image,
 	[NT_FW_CONFIG_ID]			=	&nt_fw_config,
-};
+#if defined(SPD_spmd)
+	[SIP_SP_CONTENT_CERT_ID]		=	&sip_sp_content_cert,
+	[SP_PKG1_ID]				=	&sp_pkg1,
+	[SP_PKG2_ID]				=	&sp_pkg2,
+	[SP_PKG3_ID]				=	&sp_pkg3,
+	[SP_PKG4_ID]				=	&sp_pkg4,
+	[SP_PKG5_ID]				=	&sp_pkg5,
+	[SP_PKG6_ID]				=	&sp_pkg6,
+	[SP_PKG7_ID]				=	&sp_pkg7,
+	[SP_PKG8_ID]				=       &sp_pkg8,
 #endif
+};
 
 /* Register the CoT in the authentication module */
 REGISTER_COT(cot_desc);
diff --git a/drivers/auth/tbbr/tbbr_cot_common.c b/drivers/auth/tbbr/tbbr_cot_common.c
new file mode 100644
index 0000000..ff3f22d
--- /dev/null
+++ b/drivers/auth/tbbr/tbbr_cot_common.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <platform_def.h>
+#include <drivers/auth/mbedtls/mbedtls_config.h>
+
+#include <drivers/auth/auth_mod.h>
+#include <drivers/auth/tbbr_cot_common.h>
+#if USE_TBBR_DEFS
+#include <tools_share/tbbr_oid.h>
+#else
+#include <platform_oid.h>
+#endif
+
+/*
+ * The platform must allocate buffers to store the authentication parameters
+ * extracted from the certificates. In this case, because of the way the CoT is
+ * established, we can reuse some of the buffers on different stages
+ */
+
+static unsigned char fw_config_hash_buf[HASH_DER_LEN];
+static unsigned char tb_fw_config_hash_buf[HASH_DER_LEN];
+static unsigned char hw_config_hash_buf[HASH_DER_LEN];
+unsigned char tb_fw_hash_buf[HASH_DER_LEN];
+unsigned char scp_fw_hash_buf[HASH_DER_LEN];
+unsigned char nt_world_bl_hash_buf[HASH_DER_LEN];
+
+/*
+ * common Parameter type descriptors across BL1 and BL2
+ */
+auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
+	AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID);
+auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
+	AUTH_PARAM_PUB_KEY, 0);
+auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
+	AUTH_PARAM_SIG, 0);
+auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
+	AUTH_PARAM_SIG_ALG, 0);
+auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(
+	AUTH_PARAM_RAW_DATA, 0);
+
+/* common hash used across BL1 and BL2 */
+auth_param_type_desc_t tb_fw_hash = AUTH_PARAM_TYPE_DESC(
+	AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID);
+auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+	AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID);
+auth_param_type_desc_t fw_config_hash = AUTH_PARAM_TYPE_DESC(
+	AUTH_PARAM_HASH, FW_CONFIG_HASH_OID);
+static auth_param_type_desc_t hw_config_hash = AUTH_PARAM_TYPE_DESC(
+	AUTH_PARAM_HASH, HW_CONFIG_HASH_OID);
+
+/* trusted_boot_fw_cert */
+const auth_img_desc_t trusted_boot_fw_cert = {
+	.img_id = TRUSTED_BOOT_FW_CERT_ID,
+	.img_type = IMG_CERT,
+	.parent = NULL,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_SIG,
+			.param.sig = {
+				.pk = &subject_pk,
+				.sig = &sig,
+				.alg = &sig_alg,
+				.data = &raw_data
+			}
+		},
+		[1] = {
+			.type = AUTH_METHOD_NV_CTR,
+			.param.nv_ctr = {
+				.cert_nv_ctr = &trusted_nv_ctr,
+				.plat_nv_ctr = &trusted_nv_ctr
+			}
+		}
+	},
+	.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+		[0] = {
+			.type_desc = &tb_fw_hash,
+			.data = {
+				.ptr = (void *)tb_fw_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[1] = {
+			.type_desc = &tb_fw_config_hash,
+			.data = {
+				.ptr = (void *)tb_fw_config_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[2] = {
+			.type_desc = &hw_config_hash,
+			.data = {
+				.ptr = (void *)hw_config_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		},
+		[3] = {
+			.type_desc = &fw_config_hash,
+			.data = {
+				.ptr = (void *)fw_config_hash_buf,
+				.len = (unsigned int)HASH_DER_LEN
+			}
+		}
+	}
+};
+
+/* HW Config */
+const auth_img_desc_t hw_config = {
+	.img_id = HW_CONFIG_ID,
+	.img_type = IMG_RAW,
+	.parent = &trusted_boot_fw_cert,
+	.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+		[0] = {
+			.type = AUTH_METHOD_HASH,
+			.param.hash = {
+				.data = &raw_data,
+				.hash = &hw_config_hash
+			}
+		}
+	}
+};
diff --git a/drivers/brcm/rng.c b/drivers/brcm/rng.c
new file mode 100644
index 0000000..ee2e656
--- /dev/null
+++ b/drivers/brcm/rng.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2017 - 2020, Broadcom
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#define RNG_CTRL_REG		(RNG_BASE_ADDR + 0x00)
+#define RNG_CTRL_MASK		0x00001FFF
+#define RNG_CTRL_ENABLE		0x00000001
+#define RNG_CTRL_DISABLE	0x00000000
+
+#define RNG_SOFT_RESET_REG	(RNG_BASE_ADDR + 0x04)
+#define RNG_SOFT_RESET_MASK	0x00000001
+
+#define RNG_FIFO_DATA_REG	(RNG_BASE_ADDR + 0x20)
+
+#define RNG_FIFO_COUNT_REG	(RNG_BASE_ADDR + 0x24)
+#define RNG_FIFO_COUNT_MASK	0x000000FF
+
+#define RNG_FIFO_WORDS_MAX	16
+#define MAX_WAIT_COUNT_50US	20000
+
+
+static void rng_reset(void)
+{
+	/* Disable RBG */
+	mmio_clrbits_32(RNG_CTRL_REG, RNG_CTRL_MASK);
+
+	/* Reset RNG and RBG */
+	mmio_setbits_32(RNG_SOFT_RESET_REG, RNG_SOFT_RESET_MASK);
+
+	/* Take all out of reset */
+	mmio_clrbits_32(RNG_SOFT_RESET_REG, RNG_SOFT_RESET_MASK);
+}
+
+static void rng_enable(void)
+{
+	/* Setup RNG. */
+	mmio_clrsetbits_32(RNG_CTRL_REG, RNG_CTRL_MASK, RNG_CTRL_ENABLE);
+}
+
+int rng_init(void)
+{
+	rng_reset();
+
+	rng_enable();
+
+	return 0;
+}
+
+int rng_read(uint32_t *p_out, uint32_t *words_read)
+{
+	uint32_t available_words;
+	uint32_t i;
+	uint32_t word_processed = 0;
+	uint32_t wait_count = MAX_WAIT_COUNT_50US;
+
+	if (*words_read == 0) {
+		ERROR("RNG Parameter: No word requested\n");
+		return -1;
+	}
+
+	do {
+		available_words = mmio_read_32(RNG_FIFO_COUNT_REG);
+		available_words &= RNG_FIFO_COUNT_MASK;
+
+		if (available_words != 0) {
+			available_words = MIN(available_words,
+					*words_read - word_processed);
+
+			for (i = 0; i < available_words; i++)
+				p_out[word_processed + i] =
+					mmio_read_32(RNG_FIFO_DATA_REG);
+			word_processed += available_words;
+		} else {
+			udelay(50);
+		}
+
+		if (word_processed == *words_read)
+			break;
+
+	} while (--wait_count);
+
+	if (word_processed != *words_read) {
+		ERROR("RNG Timeout: requested %d word(s) got %d\n",
+				*words_read, word_processed);
+		*words_read = word_processed;
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/drivers/io/io_fip.c b/drivers/io/io_fip.c
index 02f85d6..6e15295 100644
--- a/drivers/io/io_fip.c
+++ b/drivers/io/io_fip.c
@@ -36,7 +36,7 @@
 typedef struct {
 	unsigned int file_pos;
 	fip_toc_entry_t entry;
-} file_state_t;
+} fip_file_state_t;
 
 /*
  * Maintain dev_spec per FIP Device
@@ -49,7 +49,6 @@
 	uint16_t plat_toc_flag;
 } fip_dev_state_t;
 
-static const uuid_t uuid_null;
 /*
  * Only one file can be open across all FIP device
  * as backends like io_memmap don't support
@@ -57,7 +56,7 @@
  * backend handle should be maintained per FIP device
  * if the same support is available in the backend
  */
-static file_state_t current_file = {0};
+static fip_file_state_t current_fip_file = {0};
 static uintptr_t backend_dev_handle;
 static uintptr_t backend_image_spec;
 
@@ -288,6 +287,7 @@
 	int result;
 	uintptr_t backend_handle;
 	const io_uuid_spec_t *uuid_spec = (io_uuid_spec_t *)spec;
+	static const uuid_t uuid_null = { {0} }; /* Double braces for clang */
 	size_t bytes_read;
 	int found_file = 0;
 
@@ -300,9 +300,9 @@
 	 * When the system supports dynamic memory allocation we can allow more
 	 * than one open file at a time if needed.
 	 */
-	if (current_file.entry.offset_address != 0) {
+	if (current_fip_file.entry.offset_address != 0U) {
 		WARN("fip_file_open : Only one open file at a time.\n");
-		return -ENOMEM;
+		return -ENFILE;
 	}
 
 	/* Attempt to access the FIP image */
@@ -326,31 +326,32 @@
 	found_file = 0;
 	do {
 		result = io_read(backend_handle,
-				 (uintptr_t)&current_file.entry,
-				 sizeof(current_file.entry),
+				 (uintptr_t)&current_fip_file.entry,
+				 sizeof(current_fip_file.entry),
 				 &bytes_read);
 		if (result == 0) {
-			if (compare_uuids(&current_file.entry.uuid,
+			if (compare_uuids(&current_fip_file.entry.uuid,
 					  &uuid_spec->uuid) == 0) {
 				found_file = 1;
-				break;
 			}
 		} else {
 			WARN("Failed to read FIP (%i)\n", result);
 			goto fip_file_open_close;
 		}
-	} while (compare_uuids(&current_file.entry.uuid, &uuid_null) != 0);
+	} while ((found_file == 0) &&
+			(compare_uuids(&current_fip_file.entry.uuid,
+				&uuid_null) != 0));
 
 	if (found_file == 1) {
 		/* All fine. Update entity info with file state and return. Set
-		 * the file position to 0. The 'current_file.entry' holds the
-		 * base and size of the file.
+		 * the file position to 0. The 'current_fip_file.entry' holds
+		 * the base and size of the file.
 		 */
-		current_file.file_pos = 0;
-		entity->info = (uintptr_t)&current_file;
+		current_fip_file.file_pos = 0;
+		entity->info = (uintptr_t)&current_fip_file;
 	} else {
 		/* Did not find the file in the FIP. */
-		current_file.entry.offset_address = 0;
+		current_fip_file.entry.offset_address = 0;
 		result = -ENOENT;
 	}
 
@@ -368,7 +369,7 @@
 	assert(entity != NULL);
 	assert(length != NULL);
 
-	*length =  ((file_state_t *)entity->info)->entry.size;
+	*length =  ((fip_file_state_t *)entity->info)->entry.size;
 
 	return 0;
 }
@@ -379,7 +380,7 @@
 			  size_t *length_read)
 {
 	int result;
-	file_state_t *fp;
+	fip_file_state_t *fp;
 	size_t file_offset;
 	size_t bytes_read;
 	uintptr_t backend_handle;
@@ -397,7 +398,7 @@
 		goto fip_file_read_exit;
 	}
 
-	fp = (file_state_t *)entity->info;
+	fp = (fip_file_state_t *)entity->info;
 
 	/* Seek to the position in the FIP where the payload lives */
 	file_offset = fp->entry.offset_address + fp->file_pos;
@@ -436,8 +437,8 @@
 	/* Clear our current file pointer.
 	 * If we had malloc() we would free() here.
 	 */
-	if (current_file.entry.offset_address != 0) {
-		zeromem(&current_file, sizeof(current_file));
+	if (current_fip_file.entry.offset_address != 0U) {
+		zeromem(&current_fip_file, sizeof(current_fip_file));
 	}
 
 	/* Clear the Entity info. */
diff --git a/drivers/io/io_memmap.c b/drivers/io/io_memmap.c
index eed50cc..eb69163 100644
--- a/drivers/io/io_memmap.c
+++ b/drivers/io/io_memmap.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
  */
@@ -27,9 +27,9 @@
 	uintptr_t		base;
 	unsigned long long	file_pos;
 	unsigned long long	size;
-} file_state_t;
+} memmap_file_state_t;
 
-static file_state_t current_file = {0};
+static memmap_file_state_t current_memmap_file = {0};
 
 /* Identify the device type as memmap */
 static io_type_t device_type_memmap(void)
@@ -71,7 +71,7 @@
 
 
 /* No state associated with this device so structure can be const */
-static const io_dev_info_t memmap_dev_info = {
+static io_dev_info_t memmap_dev_info = {
 	.funcs = &memmap_dev_funcs,
 	.info = (uintptr_t)NULL
 };
@@ -82,8 +82,7 @@
 			   io_dev_info_t **dev_info)
 {
 	assert(dev_info != NULL);
-	*dev_info = (io_dev_info_t *)&memmap_dev_info; /* cast away const */
-
+	*dev_info = &memmap_dev_info;
 	return 0;
 }
 
@@ -109,16 +108,16 @@
 	 * spec at a time. When we have dynamic memory we can malloc and set
 	 * entity->info.
 	 */
-	if (current_file.in_use == 0) {
+	if (current_memmap_file.in_use == 0) {
 		assert(block_spec != NULL);
 		assert(entity != NULL);
 
-		current_file.in_use = 1;
-		current_file.base = block_spec->offset;
+		current_memmap_file.in_use = 1;
+		current_memmap_file.base = block_spec->offset;
 		/* File cursor offset for seek and incremental reads etc. */
-		current_file.file_pos = 0;
-		current_file.size = block_spec->length;
-		entity->info = (uintptr_t)&current_file;
+		current_memmap_file.file_pos = 0;
+		current_memmap_file.size = block_spec->length;
+		entity->info = (uintptr_t)&current_memmap_file;
 		result = 0;
 	} else {
 		WARN("A Memmap device is already active. Close first.\n");
@@ -133,13 +132,13 @@
 			     signed long long offset)
 {
 	int result = -ENOENT;
-	file_state_t *fp;
+	memmap_file_state_t *fp;
 
 	/* We only support IO_SEEK_SET for the moment. */
 	if (mode == IO_SEEK_SET) {
 		assert(entity != NULL);
 
-		fp = (file_state_t *) entity->info;
+		fp = (memmap_file_state_t *) entity->info;
 
 		/* Assert that new file position is valid */
 		assert((offset >= 0) &&
@@ -160,7 +159,7 @@
 	assert(entity != NULL);
 	assert(length != NULL);
 
-	*length = (size_t)((file_state_t *)entity->info)->size;
+	*length = (size_t)((memmap_file_state_t *)entity->info)->size;
 
 	return 0;
 }
@@ -170,13 +169,13 @@
 static int memmap_block_read(io_entity_t *entity, uintptr_t buffer,
 			     size_t length, size_t *length_read)
 {
-	file_state_t *fp;
+	memmap_file_state_t *fp;
 	unsigned long long pos_after;
 
 	assert(entity != NULL);
 	assert(length_read != NULL);
 
-	fp = (file_state_t *) entity->info;
+	fp = (memmap_file_state_t *) entity->info;
 
 	/* Assert that file position is valid for this read operation */
 	pos_after = fp->file_pos + length;
@@ -198,13 +197,13 @@
 static int memmap_block_write(io_entity_t *entity, const uintptr_t buffer,
 			      size_t length, size_t *length_written)
 {
-	file_state_t *fp;
+	memmap_file_state_t *fp;
 	unsigned long long pos_after;
 
 	assert(entity != NULL);
 	assert(length_written != NULL);
 
-	fp = (file_state_t *) entity->info;
+	fp = (memmap_file_state_t *) entity->info;
 
 	/* Assert that file position is valid for this write operation */
 	pos_after = fp->file_pos + length;
@@ -230,7 +229,7 @@
 	entity->info = 0;
 
 	/* This would be a mem free() if we had malloc.*/
-	zeromem((void *)&current_file, sizeof(current_file));
+	zeromem((void *)&current_memmap_file, sizeof(current_memmap_file));
 
 	return 0;
 }
diff --git a/drivers/io/io_semihosting.c b/drivers/io/io_semihosting.c
index 4ceddc6..1c2f84d 100644
--- a/drivers/io/io_semihosting.c
+++ b/drivers/io/io_semihosting.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,8 +51,7 @@
 };
 
 
-/* No state associated with this device so structure can be const */
-static const io_dev_info_t sh_dev_info = {
+static io_dev_info_t sh_dev_info = {
 	.funcs = &sh_dev_funcs,
 	.info = (uintptr_t)NULL
 };
@@ -63,7 +62,7 @@
 		io_dev_info_t **dev_info)
 {
 	assert(dev_info != NULL);
-	*dev_info = (io_dev_info_t *)&sh_dev_info; /* cast away const */
+	*dev_info = &sh_dev_info;
 	return 0;
 }
 
diff --git a/drivers/io/io_storage.c b/drivers/io/io_storage.c
index b8c1d64..0534268 100644
--- a/drivers/io/io_storage.c
+++ b/drivers/io/io_storage.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -32,36 +32,34 @@
 #if ENABLE_ASSERTIONS
 
 /* Return a boolean value indicating whether a device connector is valid */
-static int is_valid_dev_connector(const io_dev_connector_t *dev_con)
+static bool is_valid_dev_connector(const io_dev_connector_t *dev_con)
 {
-	int result = (dev_con != NULL) && (dev_con->dev_open != NULL);
-	return result;
+	return (dev_con != NULL) && (dev_con->dev_open != NULL);
 }
 
-
 /* Return a boolean value indicating whether a device handle is valid */
-static int is_valid_dev(const uintptr_t dev_handle)
+static bool is_valid_dev(const uintptr_t dev_handle)
 {
 	const io_dev_info_t *dev = (io_dev_info_t *)dev_handle;
-	int result = (dev != NULL) && (dev->funcs != NULL) &&
+
+	return (dev != NULL) && (dev->funcs != NULL) &&
 			(dev->funcs->type != NULL) &&
 			(dev->funcs->type() < IO_TYPE_MAX);
-	return result;
 }
 
 
 /* Return a boolean value indicating whether an IO entity is valid */
-static int is_valid_entity(const uintptr_t handle)
+static bool is_valid_entity(const uintptr_t handle)
 {
 	const io_entity_t *entity = (io_entity_t *)handle;
-	int result = (entity != NULL) &&
+
+	return (entity != NULL) &&
 			(is_valid_dev((uintptr_t)entity->dev_handle));
-	return result;
 }
 
 
 /* Return a boolean value indicating whether a seek mode is valid */
-static int is_valid_seek_mode(io_seek_mode_t mode)
+static bool is_valid_seek_mode(io_seek_mode_t mode)
 {
 	return ((mode != IO_SEEK_INVALID) && (mode < IO_SEEK_MAX));
 }
@@ -71,15 +69,14 @@
 
 
 /* Open a connection to a specific device */
-static int dev_open(const io_dev_connector_t *dev_con, const uintptr_t dev_spec,
+static int io_storage_dev_open(const io_dev_connector_t *dev_con,
+		const uintptr_t dev_spec,
 		io_dev_info_t **dev_info)
 {
-	int result;
 	assert(dev_info != NULL);
 	assert(is_valid_dev_connector(dev_con));
 
-	result = dev_con->dev_open(dev_spec, dev_info);
-	return result;
+	return dev_con->dev_open(dev_spec, dev_info);
 }
 
 
@@ -116,7 +113,8 @@
 		unsigned int index = 0;
 		result = find_first_entity(NULL, &index);
 		assert(result == 0);
-		*entity = entity_map[index] = &entity_pool[index];
+		*entity = &entity_pool[index];
+		entity_map[index] = &entity_pool[index];
 		++entity_count;
 	}
 
@@ -163,11 +161,8 @@
 int io_dev_open(const io_dev_connector_t *dev_con, const uintptr_t dev_spec,
 		uintptr_t *handle)
 {
-	int result;
 	assert(handle != NULL);
-
-	result = dev_open(dev_con, dev_spec, (io_dev_info_t **)handle);
-	return result;
+	return io_storage_dev_open(dev_con, dev_spec, (io_dev_info_t **)handle);
 }
 
 
diff --git a/drivers/marvell/ap807_clocks_init.c b/drivers/marvell/ap807_clocks_init.c
index 04c256b..c1f8619 100644
--- a/drivers/marvell/ap807_clocks_init.c
+++ b/drivers/marvell/ap807_clocks_init.c
@@ -39,19 +39,29 @@
 #define AP807_CPU_PLL_PARAM(cluster)	AP807_CPU_PLL_CTRL(cluster)
 #define AP807_CPU_PLL_CFG(cluster)	(AP807_CPU_PLL_CTRL(cluster) + 0x4)
 #define AP807_CPU_PLL_CFG_BYPASS_MODE	(0x1)
+#define AP807_CPU_PLL_FRC_DSCHG		(0x2)
 #define AP807_CPU_PLL_CFG_USE_REG_FILE	(0x1 << 9)
 
 static void pll_set_freq(unsigned int freq_val)
 {
 	int i;
 
+	if (freq_val != PLL_FREQ_2200)
+		return;
+
 	for (i = 0 ; i < AP807_CLUSTER_NUM ; i++) {
-		mmio_write_32(AP807_CPU_PLL_CFG(i),
-			      AP807_CPU_PLL_CFG_USE_REG_FILE);
-		mmio_write_32(AP807_CPU_PLL_CFG(i),
-			      AP807_CPU_PLL_CFG_USE_REG_FILE |
-			      AP807_CPU_PLL_CFG_BYPASS_MODE);
+		/* Set parameter of cluster i PLL to 2.2GHz */
 		mmio_write_32(AP807_CPU_PLL_PARAM(i), freq_val);
+		/* Set apll_lpf_frc_dschg - Control
+		 * voltage of internal VCO is discharged
+		 */
+		mmio_write_32(AP807_CPU_PLL_CFG(i),
+				AP807_CPU_PLL_FRC_DSCHG);
+		/* Set use_rf_conf  load PLL parameter from register */
+		mmio_write_32(AP807_CPU_PLL_CFG(i),
+				AP807_CPU_PLL_FRC_DSCHG |
+				AP807_CPU_PLL_CFG_USE_REG_FILE);
+		/* Un-set apll_lpf_frc_dschg */
 		mmio_write_32(AP807_CPU_PLL_CFG(i),
 			      AP807_CPU_PLL_CFG_USE_REG_FILE);
 	}
@@ -84,19 +94,16 @@
  */
 void ap807_clocks_init(unsigned int freq_option)
 {
-	/* Switch from ARO to PLL */
-	aro_to_pll();
-
 	/* Modifications in frequency table:
 	 * 0x0: 764x: change to 2000 MHz.
 	 * 0x2: 744x change to 1800 MHz, 764x change to 2200/2400.
 	 * 0x3: 3900/744x/764x change to 1200 MHz.
 	 */
-	switch (freq_option) {
-	case CPU_2000_DDR_1200_RCLK_1200:
-		pll_set_freq(PLL_FREQ_2000);
-		break;
-	default:
-		break;
-	}
+
+	if (freq_option == CPU_2200_DDR_1200_RCLK_1200)
+		pll_set_freq(PLL_FREQ_2200);
+
+	/* Switch from ARO to PLL */
+	aro_to_pll();
+
 }
diff --git a/drivers/marvell/cache_llc.c b/drivers/marvell/cache_llc.c
index 3df93a4..4b06b47 100644
--- a/drivers/marvell/cache_llc.c
+++ b/drivers/marvell/cache_llc.c
@@ -31,19 +31,19 @@
 
 void llc_flush_all(int ap_index)
 {
-	mmio_write_32(L2X0_CLEAN_INV_WAY(ap_index), LLC_WAY_MASK);
+	mmio_write_32(LLC_CLEAN_INV_WAY(ap_index), LLC_ALL_WAYS_MASK);
 	llc_cache_sync(ap_index);
 }
 
 void llc_clean_all(int ap_index)
 {
-	mmio_write_32(L2X0_CLEAN_WAY(ap_index), LLC_WAY_MASK);
+	mmio_write_32(LLC_CLEAN_WAY(ap_index), LLC_ALL_WAYS_MASK);
 	llc_cache_sync(ap_index);
 }
 
 void llc_inv_all(int ap_index)
 {
-	mmio_write_32(L2X0_INV_WAY(ap_index), LLC_WAY_MASK);
+	mmio_write_32(LLC_INV_WAY(ap_index), LLC_ALL_WAYS_MASK);
 	llc_cache_sync(ap_index);
 }
 
@@ -109,3 +109,81 @@
 	reg |= (0x1 << CCU_SET_POC_OFFSET);
 	mmio_write_32(CCU_HTC_CR(ap_index), reg);
 }
+
+#if LLC_SRAM
+int llc_sram_enable(int ap_index, int size)
+{
+	uint32_t tc, way, ways_to_allocate;
+	uint32_t way_addr;
+
+	if ((size <= 0) || (size > LLC_SIZE) || (size % LLC_WAY_SIZE))
+		return -1;
+
+	llc_enable(ap_index, 1);
+	llc_inv_all(ap_index);
+
+	ways_to_allocate = size / LLC_WAY_SIZE;
+
+	/* Lockdown all available ways for all traffic classes */
+	for (tc = 0; tc < LLC_TC_NUM; tc++)
+		mmio_write_32(LLC_TCN_LOCK(ap_index, tc), LLC_ALL_WAYS_MASK);
+
+	/* Clear the high bits of SRAM address */
+	mmio_write_32(LLC_BANKED_MNT_AHR(ap_index), 0);
+
+	way_addr = PLAT_MARVELL_TRUSTED_RAM_BASE;
+	for (way = 0; way < ways_to_allocate; way++) {
+		/* Trigger allocation block command */
+		mmio_write_32(LLC_BLK_ALOC(ap_index),
+			      LLC_BLK_ALOC_BASE_ADDR(way_addr) |
+			      LLC_BLK_ALOC_WAY_DATA_SET |
+			      LLC_BLK_ALOC_WAY_ID(way));
+		way_addr += LLC_WAY_SIZE;
+	}
+	return 0;
+}
+
+void llc_sram_disable(int ap_index)
+{
+	uint32_t tc;
+
+	/* Disable the line lockings */
+	for (tc = 0; tc < LLC_TC_NUM; tc++)
+		mmio_write_32(LLC_TCN_LOCK(ap_index, tc), 0);
+
+	/* Invalidate all ways */
+	llc_inv_all(ap_index);
+}
+
+int llc_sram_test(int ap_index, int size, char *msg)
+{
+	uintptr_t addr, end_addr;
+	uint32_t data = 0;
+
+	if ((size <= 0) || (size > LLC_SIZE))
+		return -1;
+
+	INFO("=== LLC SRAM WRITE test %s\n", msg);
+	for (addr = PLAT_MARVELL_TRUSTED_RAM_BASE,
+	     end_addr = PLAT_MARVELL_TRUSTED_RAM_BASE + size;
+	     addr < end_addr; addr += 4) {
+		mmio_write_32(addr, addr);
+	}
+	INFO("=== LLC SRAM WRITE test %s PASSED\n", msg);
+	INFO("=== LLC SRAM READ test %s\n", msg);
+	for (addr = PLAT_MARVELL_TRUSTED_RAM_BASE,
+	     end_addr = PLAT_MARVELL_TRUSTED_RAM_BASE + size;
+	     addr < end_addr; addr += 4) {
+		data = mmio_read_32(addr);
+		if (data != addr) {
+			INFO("=== LLC SRAM READ test %s FAILED @ 0x%08lx)\n",
+			     msg, addr);
+			return -1;
+		}
+	}
+	INFO("=== LLC SRAM READ test %s PASSED (last read = 0x%08x)\n",
+	     msg, data);
+	return 0;
+}
+
+#endif /* LLC_SRAM */
diff --git a/drivers/marvell/ccu.c b/drivers/marvell/ccu.c
index 1e4ab44..c73516e 100644
--- a/drivers/marvell/ccu.c
+++ b/drivers/marvell/ccu.c
@@ -54,8 +54,8 @@
 							      win_id));
 			start = ((uint64_t)alr << ADDRESS_SHIFT);
 			end = (((uint64_t)ahr + 0x10) << ADDRESS_SHIFT);
-			printf("\tccu    %02x     0x%016llx 0x%016llx\n",
-			       target_id, start, end);
+			printf("\tccu%d    %02x     0x%016llx 0x%016llx\n",
+			       win_id, target_id, start, end);
 		}
 	}
 	win_cr = mmio_read_32(CCU_WIN_GCR_OFFSET(ap_index));
@@ -81,6 +81,12 @@
 	}
 }
 
+int ccu_is_win_enabled(int ap_index, uint32_t win_id)
+{
+	return mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)) &
+			    WIN_ENABLE_BIT;
+}
+
 void ccu_enable_win(int ap_index, struct addr_map_win *win, uint32_t win_id)
 {
 	uint32_t ccu_win_reg;
diff --git a/drivers/marvell/comphy/comphy-cp110.h b/drivers/marvell/comphy/comphy-cp110.h
index 6eb7fd0..3678c90 100644
--- a/drivers/marvell/comphy/comphy-cp110.h
+++ b/drivers/marvell/comphy/comphy-cp110.h
@@ -659,18 +659,32 @@
 			(0x3f << HPIPE_SAVED_DFE_VALUES_SAV_F0D_OFFSET)
 
 #define HPIPE_CDR_CONTROL_REG			0x418
-#define HPIPE_CDR_RX_MAX_DFE_ADAPT_0_OFFSET	14
-#define HPIPE_CDR_RX_MAX_DFE_ADAPT_0_MASK	\
-			(0x3 << HPIPE_CDR_RX_MAX_DFE_ADAPT_0_OFFSET)
-#define HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET	12
-#define HPIPE_CDR_RX_MAX_DFE_ADAPT_1_MASK	\
-			(0x3 << HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET)
-#define HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET	9
-#define HPIPE_CDR_MAX_DFE_ADAPT_0_MASK		\
-			(0x7 << HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET)
+#define HPIPE_CRD_MIDPOINT_PHASE_OS_OFFSET	0
+#define HPIPE_CRD_MIDPOINT_PHASE_OS_MASK	\
+			(0x3f << HPIPE_CRD_MIDPOINT_PHASE_OS_OFFSET)
 #define HPIPE_CDR_MAX_DFE_ADAPT_1_OFFSET	6
 #define HPIPE_CDR_MAX_DFE_ADAPT_1_MASK		\
 			(0x7 << HPIPE_CDR_MAX_DFE_ADAPT_1_OFFSET)
+#define HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET	9
+#define HPIPE_CDR_MAX_DFE_ADAPT_0_MASK		\
+			(0x7 << HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET)
+#define HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET	12
+#define HPIPE_CDR_RX_MAX_DFE_ADAPT_1_MASK	\
+			(0x3 << HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET)
+#define HPIPE_CDR_RX_MAX_DFE_ADAPT_0_OFFSET	14
+#define HPIPE_CDR_RX_MAX_DFE_ADAPT_0_MASK	\
+			(0x3 << HPIPE_CDR_RX_MAX_DFE_ADAPT_0_OFFSET)
+
+
+#define HPIPE_CDR_CONTROL1_REG			0x41c
+#define HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_OFF	12
+#define HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_MASK	\
+			(0xf << HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_OFF)
+
+#define HPIPE_CDR_CONTROL2_REG			0x420
+#define HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_OFF	12
+#define HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_MASK	\
+			(0xf << HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_OFF)
 
 #define HPIPE_TX_TRAIN_CTRL_11_REG		0x438
 #define HPIPE_TX_STATUS_CHECK_MODE_OFFSET	6
@@ -749,6 +763,30 @@
 #define HPIPE_DFE_CTRL_28_PIPE4_MASK		\
 			(0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET)
 
+#define HPIPE_TRX0_REG				0x4cc /*in doc 0x133*4*/
+#define HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_OFF	2
+#define HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_MASK \
+			(0x1 << HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_OFF)
+#define HPIPE_TRX0_GAIN_TRAIN_WITH_C_OFF	0
+#define HPIPE_TRX0_GAIN_TRAIN_WITH_C_MASK	\
+			(0x1 << HPIPE_TRX0_GAIN_TRAIN_WITH_C_OFF)
+
+#define HPIPE_TRX_REG1				0x4d0 /*in doc 0x134*4*/
+#define HPIPE_TRX_REG1_MIN_BOOST_MODE_OFF	3
+#define HPIPE_TRX_REG1_MIN_BOOST_MODE_MASK	\
+			(0x1 << HPIPE_TRX_REG1_MIN_BOOST_MODE_OFF)
+#define HPIPE_TRX_REG1_SUMFTAP_EN_OFF		10
+#define HPIPE_TRX_REG1_SUMFTAP_EN_MASK		\
+			(0x3f << HPIPE_TRX_REG1_SUMFTAP_EN_OFF)
+
+#define HPIPE_TRX_REG2				0x4d8 /*in doc 0x136*4*/
+#define HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_OFF	11
+#define HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_MASK	\
+			(0x1f << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_OFF)
+#define HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_OFF	7
+#define HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_MASK	\
+			(0xf << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_OFF)
+
 #define HPIPE_G1_SETTING_5_REG			0x538
 #define HPIPE_G1_SETTING_5_G1_ICP_OFFSET	0
 #define HPIPE_G1_SETTING_5_G1_ICP_MASK		\
diff --git a/drivers/marvell/comphy/phy-comphy-cp110.c b/drivers/marvell/comphy/phy-comphy-cp110.c
index 384dd39..1d5b6f5 100644
--- a/drivers/marvell/comphy/phy-comphy-cp110.c
+++ b/drivers/marvell/comphy/phy-comphy-cp110.c
@@ -11,6 +11,7 @@
 
 #include <common/debug.h>
 #include <drivers/delay_timer.h>
+#include <mg_conf_cm3/mg_conf_cm3.h>
 #include <lib/mmio.h>
 #include <lib/spinlock.h>
 
@@ -209,8 +210,10 @@
 			   * as SFI1/XFI1 available only for CP115.
 			   */
 			if ((mode == COMPHY_SGMII_MODE ||
-			    mode == COMPHY_HS_SGMII_MODE ||
-			    mode == COMPHY_SFI_MODE || mode == COMPHY_XFI_MODE)
+			     mode == COMPHY_HS_SGMII_MODE ||
+			     mode == COMPHY_SFI_MODE ||
+			     mode == COMPHY_XFI_MODE ||
+			     mode == COMPHY_AP_MODE)
 			    && COMPHY_GET_ID(comphy_mode) == 1)
 				reg |= COMMON_SELECTOR_COMPHY4_PORT1 <<
 					comphy_offset;
@@ -2012,12 +2015,58 @@
 	return ret;
 }
 
+static void rx_pre_train(uint64_t comphy_base, uint8_t comphy_index)
+{
+	uintptr_t hpipe_addr;
+	uint32_t mask, data;
+
+	hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
+				comphy_index);
+
+	debug("rx_training preparation\n\n");
+
+	mask = HPIPE_TRX0_GAIN_TRAIN_WITH_C_MASK;
+	data = (0x1 << HPIPE_TRX0_GAIN_TRAIN_WITH_C_OFF);
+	mask |= HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_MASK;
+	data |= (0x0 << HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_OFF);
+	reg_set(hpipe_addr + HPIPE_TRX0_REG, data, mask);
+
+
+	mask = HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_MASK;
+	data = (0x1e << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_OFF);
+	mask |= HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_MASK;
+	data |= (0x0 << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_OFF);
+	reg_set(hpipe_addr + HPIPE_TRX_REG2, data, mask);
+
+	mask = HPIPE_TRX_REG1_MIN_BOOST_MODE_MASK;
+	data = (0x1 << HPIPE_TRX_REG1_MIN_BOOST_MODE_OFF);
+	reg_set(hpipe_addr + HPIPE_TRX_REG1, data, mask);
+
+	mask = HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_MASK;
+	data = (0x8 << HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_OFF);
+	reg_set(hpipe_addr + HPIPE_CDR_CONTROL1_REG, data, mask);
+
+	mask = HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_MASK;
+	data = (0x8 << HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_OFF);
+	reg_set(hpipe_addr + HPIPE_CDR_CONTROL2_REG, data, mask);
+
+	mask = HPIPE_CRD_MIDPOINT_PHASE_OS_MASK;
+	data = (0x0 << HPIPE_CRD_MIDPOINT_PHASE_OS_OFFSET);
+	reg_set(hpipe_addr + HPIPE_CDR_CONTROL_REG, data, mask);
+
+	mask = HPIPE_TRX_REG1_SUMFTAP_EN_MASK;
+	data = (0x38 << HPIPE_TRX_REG1_SUMFTAP_EN_OFF);
+	mask |= HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_MASK;
+	data |= (0x1e << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_OFF);
+	reg_set(hpipe_addr + HPIPE_TRX_REG1, data, mask);
+}
+
 int mvebu_cp110_comphy_xfi_rx_training(uint64_t comphy_base,
 					      uint8_t comphy_index)
 {
 	uint32_t mask, data, timeout;
 	uint32_t g1_ffe_cap_sel, g1_ffe_res_sel, align90, g1_dfe_res;
-	uintptr_t hpipe_addr, sd_ip_addr;
+	uintptr_t hpipe_addr;
 
 	uint8_t ap_nr, cp_nr;
 
@@ -2025,30 +2074,10 @@
 
 	hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
 				comphy_index);
-	sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
-			     comphy_index);
 
 	debug_enter();
 
-	debug("stage: RF Reset\n");
-
-	/* Release from hard reset */
-	mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
-	data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
-	data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
-	data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
-	reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
-
-	mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
-	data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
-	mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
-	data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
-	reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
-
-	/* Wait 50ms - until band gap and ref clock ready */
-	mdelay(50);
+	rx_pre_train(comphy_base, comphy_index);
 
 	debug("Preparation for rx_training\n\n");
 
@@ -2068,34 +2097,10 @@
 	data = 0 << HPIPE_DFE_RES_FORCE_OFFSET;
 	reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
 
-	debug("PRBS31 loppback\n\n");
-
-	/* Configure PRBS counters */
-	mask = HPIPE_PHY_TEST_PATTERN_SEL_MASK;
-	data = 0xe << HPIPE_PHY_TEST_PATTERN_SEL_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PHY_TEST_CONTROL_REG, data, mask);
-
-	mask = HPIPE_PHY_TEST_DATA_MASK;
-	data = 0xc4 << HPIPE_PHY_TEST_DATA_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PHY_TEST_DATA_REG, data, mask);
-
-	mask = HPIPE_PHY_TEST_EN_MASK;
-	data = 0x1 << HPIPE_PHY_TEST_EN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PHY_TEST_CONTROL_REG, data, mask);
-
-	mdelay(10);
-	debug("Enable TX/RX training\n\n");
+	debug("Enable RX training\n\n");
 
 	mask = HPIPE_TRX_RX_TRAIN_EN_MASK;
 	data = 0x1 << HPIPE_TRX_RX_TRAIN_EN_OFFSET;
-	mask |= HPIPE_TRX_RX_ANA_IF_CLK_ENE_MASK;
-	data |= 0x1 << HPIPE_TRX_RX_ANA_IF_CLK_ENE_OFFSET;
-	mask |= HPIPE_TRX_TX_CTRL_CLK_EN_MASK;
-	data |= 0x1 << HPIPE_TRX_TX_CTRL_CLK_EN_OFFSET;
-	mask |= HPIPE_TRX_UPDATE_THEN_HOLD_MASK;
-	data |= 0x1 << HPIPE_TRX_UPDATE_THEN_HOLD_OFFSET;
-	mask |= HPIPE_TRX_TX_F0T_EO_BASED_MASK;
-	data |= 0x1 << HPIPE_TRX_TX_F0T_EO_BASED_OFFSET;
 	reg_set(hpipe_addr + HPIPE_TRX_TRAIN_CTRL_0_REG, data, mask);
 
 	/* Check the result of RX training */
@@ -2180,21 +2185,9 @@
 	data = 1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET;
 	reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
 
-	/* Use the value from CAL_OS_PH_EXT */
-	mask = HPIPE_CAL_RXCLKALIGN_90_EXT_EN_MASK;
-	data = 1 << HPIPE_CAL_RXCLKALIGN_90_EXT_EN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG,
-		data, mask);
-
-	/* Update align90 */
-	mask = HPIPE_CAL_OS_PH_EXT_MASK;
-	data = align90 << HPIPE_CAL_OS_PH_EXT_OFFSET;
-	reg_set(hpipe_addr + HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG,
-		data, mask);
-
 	/* Force DFE resolution (use gen table value) */
 	mask = HPIPE_DFE_RES_FORCE_MASK;
-	data = 0x0 << HPIPE_DFE_RES_FORCE_OFFSET;
+	data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET;
 	reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
 
 	/* 0x111-G1 DFE_Setting_4 */
@@ -2202,41 +2195,9 @@
 	data = g1_dfe_res << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET;
 	reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask);
 
-	debug("PRBS31 loppback\n\n");
-
-	mask = HPIPE_PHY_TEST_PT_TESTMODE_MASK;
-	data = 0x1 << HPIPE_PHY_TEST_PT_TESTMODE_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PHY_TEST_OOB_0_REGISTER, data, mask);
-
-	/* Configure PRBS counters */
-	mask = HPIPE_PHY_TEST_PATTERN_SEL_MASK;
-	data = 0xe << HPIPE_PHY_TEST_PATTERN_SEL_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PHY_TEST_CONTROL_REG, data, mask);
-
-	mask = HPIPE_PHY_TEST_DATA_MASK;
-	data = 0xc4 << HPIPE_PHY_TEST_DATA_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PHY_TEST_DATA_REG, data, mask);
-
-	mask = HPIPE_PHY_TEST_EN_MASK;
-	data = 0x1 << HPIPE_PHY_TEST_EN_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PHY_TEST_CONTROL_REG, data, mask);
-
-	/* Reset PRBS error counter */
-	mask = HPIPE_PHY_TEST_PATTERN_SEL_MASK;
-	data = 0x1 << HPIPE_PHY_TEST_RESET_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PHY_TEST_CONTROL_REG, data, mask);
-
-	mask = HPIPE_PHY_TEST_PATTERN_SEL_MASK;
-	data = 0x0 << HPIPE_PHY_TEST_RESET_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PHY_TEST_CONTROL_REG, data, mask);
-
-	mask = HPIPE_PHY_TEST_PT_TESTMODE_MASK;
-	data = 0x1 << HPIPE_PHY_TEST_PT_TESTMODE_OFFSET;
-	reg_set(hpipe_addr + HPIPE_PHY_TEST_OOB_0_REGISTER, data, mask);
-
 	printf("########################################################\n");
 	printf("# To use trained values update the ATF sources:\n");
-	printf("# plat/marvell/a8k/<board_type>/board/phy-porting-layer.h ");
+	printf("# plat/marvell/armada/a8k/<board_type>/board/phy-porting-layer.h ");
 	printf("file\n# with new values as below (for appropriate AP nr %d",
 	       ap_nr);
 	printf("and CP nr: %d comphy_index %d\n\n",
@@ -2252,12 +2213,6 @@
 	printf("};\n\n");
 	printf("########################################################\n");
 
-	/* check */
-	debug("PRBS error counter[0x%lx] 0x%x\n\n",
-	      hpipe_addr + HPIPE_PHY_TEST_PRBS_ERROR_COUNTER_1_REG,
-	      mmio_read_32(hpipe_addr +
-			   HPIPE_PHY_TEST_PRBS_ERROR_COUNTER_1_REG));
-
 	rx_trainng_done[ap_nr][cp_nr][comphy_index] = 1;
 
 	return 0;
@@ -2273,12 +2228,17 @@
  * the network registers like: MG, AP, MAC, PCS, Serdes etc.)
  */
 static int mvebu_cp110_comphy_ap_power_on(uint64_t comphy_base,
-					  uint8_t comphy_index)
+					  uint8_t comphy_index,
+					  uint32_t comphy_mode)
 {
 	uint32_t mask, data;
+	uint8_t ap_nr, cp_nr;
 	uintptr_t comphy_addr = comphy_addr =
 				COMPHY_ADDR(comphy_base, comphy_index);
 
+	/* configure phy selector for XFI/SFI */
+	mvebu_cp110_comphy_set_phy_selector(comphy_base, comphy_index,
+					    comphy_mode);
 	debug_enter();
 	debug("stage: RFU configurations - hard reset comphy\n");
 	/* RFU configurations - hard reset comphy */
@@ -2289,6 +2249,10 @@
 	reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask);
 	debug_exit();
 
+	/* Start AP Firmware */
+	mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base);
+	mg_start_ap_fw(cp_nr, comphy_index);
+
 	return 0;
 }
 
@@ -2371,7 +2335,8 @@
 						       comphy_mode);
 		break;
 	case (COMPHY_AP_MODE):
-		err = mvebu_cp110_comphy_ap_power_on(comphy_base, comphy_index);
+		err = mvebu_cp110_comphy_ap_power_on(comphy_base, comphy_index,
+						     comphy_mode);
 		break;
 	default:
 		ERROR("comphy%d: unsupported comphy mode\n", comphy_index);
diff --git a/drivers/marvell/comphy/phy-comphy-cp110.h b/drivers/marvell/comphy/phy-comphy-cp110.h
index 407909b..63aef12 100644
--- a/drivers/marvell/comphy/phy-comphy-cp110.h
+++ b/drivers/marvell/comphy/phy-comphy-cp110.h
@@ -7,7 +7,7 @@
 
 /* Those are parameters for xfi mode, which need to be tune for each board type.
  * For known DB boards the parameters was already calibrated and placed under
- * the plat/marvell/a8k/<board_type>/board/phy-porting-layer.h
+ * the plat/marvell/armada/a8k/<board_type>/board/phy-porting-layer.h
  */
 struct xfi_params {
 	uint8_t g1_ffe_res_sel;
diff --git a/drivers/marvell/mci.c b/drivers/marvell/mci.c
index 06fe88e..2b54700 100644
--- a/drivers/marvell/mci.c
+++ b/drivers/marvell/mci.c
@@ -571,21 +571,21 @@
 
 	debug_enter();
 	/* ID assignment (assigning global ID offset to CP) */
-	mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(0),
+	mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
 			  MCI_DID_GLOBAL_ASSIGN_REQ_MCI_LOCAL_ID(2) |
 			  MCI_DID_GLOBAL_ASSIGN_REQ_MCI_COUNT(2) |
 			  MCI_DID_GLOBAL_ASSIGN_REQ_HOPS_NUM(2));
-	mci_mmio_write_32(MCI_ACCESS_CMD_REG(0),
+	mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
 			  MCI_INDIRECT_REG_CTRL_ADDR(
 				MCI_DID_GLOBAL_ASSIGNMENT_REQUEST_REG) |
 			  MCI_INDIRECT_CTRL_ASSIGN_CMD);
 	ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
 
 	/* Assigning dest. ID=3 to all transactions entering from AXI at AP */
-	mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(0),
+	mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
 			  MCI_HB_CTRL_WIN0_DEST_VALID_FLAG(1) |
 			  MCI_HB_CTRL_WIN0_DEST_ID(3));
-	mci_mmio_write_32(MCI_ACCESS_CMD_REG(0),
+	mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
 			  MCI_INDIRECT_REG_CTRL_ADDR(
 				MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM) |
 			  MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) |
@@ -593,10 +593,10 @@
 	ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
 
 	/* Assigning dest. ID=1 to all transactions entering from AXI at CP */
-	mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(0),
+	mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
 			  MCI_HB_CTRL_WIN0_DEST_VALID_FLAG(1) |
 			  MCI_HB_CTRL_WIN0_DEST_ID(1));
-	mci_mmio_write_32(MCI_ACCESS_CMD_REG(0),
+	mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
 			  MCI_INDIRECT_REG_CTRL_ADDR(
 				MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM) |
 			  MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT) |
@@ -607,8 +607,8 @@
 	 * This will lead to get match for any AXI address
 	 * and receive destination ID=3
 	 */
-	mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(0), 0xffffffff);
-	mci_mmio_write_32(MCI_ACCESS_CMD_REG(0),
+	mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 0xffffffff);
+	mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
 			  MCI_INDIRECT_REG_CTRL_ADDR(
 				MCI_HB_CTRL_WIN0_ADDRESS_MASK_REG_NUM) |
 			  MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) |
@@ -619,8 +619,8 @@
 	 * This will lead to get match for any AXI address
 	 * and receive destination ID=1
 	 */
-	mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(0), 0xffffffff);
-	mci_mmio_write_32(MCI_ACCESS_CMD_REG(0),
+	mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 0xffffffff);
+	mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
 			  MCI_INDIRECT_REG_CTRL_ADDR(
 				MCI_HB_CTRL_WIN0_ADDRESS_MASK_REG_NUM) |
 			  MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT) |
@@ -653,7 +653,7 @@
 	 * performed by BootROM.
 	 */
 	debug_enter();
-	mci_mmio_write_32(MCI_ACCESS_CMD_REG(0),
+	mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
 			  MCI_INDIRECT_REG_CTRL_ADDR(
 				MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM) |
 			  MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) |
@@ -697,7 +697,8 @@
 	 * wasn't already enabled in bootrom.
 	 */
 	if (mci_simulatenous_trans_missing(mci_index)) {
-		VERBOSE("Enabling MCI simultaneous transaction\n");
+		VERBOSE("Enabling MCI simultaneous transaction for mci%d\n",
+		       mci_index);
 		/* set MCI to support read/write transactions
 		 * to arrive at the same time
 		 */
@@ -819,7 +820,7 @@
 }
 
 /* Initialize MCI for performance improvements */
-int mci_initialize(int mci_index)
+int mci_link_tune(int mci_index)
 {
 	int ret;
 
diff --git a/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c b/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c
new file mode 100644
index 0000000..98e1896
--- /dev/null
+++ b/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2019 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <a8k_plat_def.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mss_scp_bl2_format.h>
+
+/* CONFI REGISTERS */
+#define MG_CM3_CONFI_BASE(CP)		(MVEBU_CP_REGS_BASE(CP) + 0x100000)
+#define MG_CM3_SRAM_BASE(CP)		MG_CM3_CONFI_BASE(CP)
+#define MG_CM3_CONFI_GLOB_CFG_REG(CP)	(MG_CM3_CONFI_BASE(CP) + 0x2B500)
+#define CM3_CPU_EN_BIT			BIT(28)
+#define MG_CM3_MG_INT_MFX_REG(CP)	(MG_CM3_CONFI_BASE(CP) + 0x2B054)
+#define CM3_SYS_RESET_BIT		BIT(0)
+
+#define MG_CM3_SHARED_MEM_BASE(CP)	(MG_CM3_SRAM_BASE(CP) + 0x1FC00ULL)
+
+#define MG_SRAM_SIZE	0x20000 /* 128KB */
+
+#define MG_ACK_TIMEOUT 10
+
+/**
+ * struct ap_sharedmem_ctrl - used to pass information between the HOST and CM3
+ * @init_done:	Set by CM3 when ap_proces initialzied. Host check if CM3 set
+ *		this flag to confirm that the process is running
+ * @lane_nr:	Set by Host to mark which comphy lane should be configure. E.g.:
+ *		- A8K development board uses comphy lane 2 for eth0
+ *		- CN913x development board uses comphy lane 4 for eth0
+ */
+struct ap_sharedmem_ctrl {
+	uint32_t init_done;
+	uint32_t lane_nr;
+};
+
+int mg_image_load(uintptr_t src_addr, uint32_t size, int cp_index)
+{
+	uintptr_t mg_regs = MG_CM3_SRAM_BASE(cp_index);
+
+	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;
+}
+
+void mg_start_ap_fw(int cp_nr, uint8_t comphy_index)
+{
+	volatile struct ap_sharedmem_ctrl *ap_shared_ctrl =
+					(void *)MG_CM3_SHARED_MEM_BASE(cp_nr);
+	int timeout = MG_ACK_TIMEOUT;
+
+	if (mmio_read_32(MG_CM3_CONFI_GLOB_CFG_REG(cp_nr)) & CM3_CPU_EN_BIT) {
+		VERBOSE("cm3 already running\n");
+		return;  /* cm3 already running */
+	}
+
+	/*
+	 * Mark which comphy lane should be used - it will be read via shared
+	 * mem by ap process
+	 */
+	ap_shared_ctrl->lane_nr = comphy_index;
+	/* Make sure it took place before enabling cm3 */
+	dmbst();
+
+	mmio_setbits_32(MG_CM3_CONFI_GLOB_CFG_REG(cp_nr), CM3_CPU_EN_BIT);
+	mmio_setbits_32(MG_CM3_MG_INT_MFX_REG(cp_nr), CM3_SYS_RESET_BIT);
+
+	/* Check for ap process initialization by fw */
+	while (ap_shared_ctrl->init_done != 1 && timeout--)
+		VERBOSE("Waiting for ap process ack, timeout %d\n", timeout);
+
+	if (timeout == 0) {
+		ERROR("AP process failed, disabling cm3\n");
+		mmio_clrbits_32(MG_CM3_MG_INT_MFX_REG(cp_nr),
+				CM3_SYS_RESET_BIT);
+		mmio_clrbits_32(MG_CM3_CONFI_GLOB_CFG_REG(cp_nr),
+				CM3_CPU_EN_BIT);
+	}
+}
diff --git a/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h b/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h
new file mode 100644
index 0000000..e2756de
--- /dev/null
+++ b/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2019 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+void mg_start_ap_fw(int cp_nr, uint8_t comphy_index);
+int mg_image_load(uintptr_t src_addr, uint32_t size, int cp_index);
diff --git a/drivers/marvell/mochi/ap807_setup.c b/drivers/marvell/mochi/ap807_setup.c
index 864c923..7b68195 100644
--- a/drivers/marvell/mochi/ap807_setup.c
+++ b/drivers/marvell/mochi/ap807_setup.c
@@ -11,6 +11,7 @@
 #include <drivers/marvell/cache_llc.h>
 #include <drivers/marvell/ccu.h>
 #include <drivers/marvell/io_win.h>
+#include <drivers/marvell/iob.h>
 #include <drivers/marvell/mci.h>
 #include <drivers/marvell/mochi/ap_setup.h>
 #include <lib/mmio.h>
@@ -31,6 +32,11 @@
 #define DSS_CR0					(MVEBU_RFU_BASE + 0x100)
 #define DVM_48BIT_VA_ENABLE			(1 << 21)
 
+
+/* SoC RFU / IHBx4 Control */
+#define MCIX4_807_REG_START_ADDR_REG(unit_id)	(MVEBU_RFU_BASE + \
+						0x4258 + (unit_id * 0x4))
+
 /* Secure MoChi incoming access */
 #define SEC_MOCHI_IN_ACC_REG			(MVEBU_RFU_BASE + 0x4738)
 #define SEC_MOCHI_IN_ACC_IHB0_EN		(1)
@@ -124,7 +130,7 @@
 	uint32_t mci;
 
 	for (mci = 0; mci < MCI_MAX_UNIT_ID; mci++)
-		mmio_write_32(MCIX4_REG_START_ADDRESS_REG(mci),
+		mmio_write_32(MCIX4_807_REG_START_ADDR_REG(mci),
 				  MVEBU_MCI_REG_BASE_REMAP(mci) >>
 				  MCI_REMAP_OFF_SHIFT);
 }
@@ -186,6 +192,38 @@
 	mmio_write_32(MVEBU_SYSRST_OUT_CONFIG_REG, reg);
 }
 
+/*
+ * By default all external CPs start with configuration address space set to
+ * 0xf200_0000. To overcome this issue, go in the loop and initialize the
+ * CP one by one, using temporary window configuration which allows to access
+ * each CP and update its configuration space according to decoding
+ * windows scheme defined for each platform.
+ */
+void update_cp110_default_win(int cp_id)
+{
+	int mci_id = cp_id - 1;
+	uintptr_t cp110_base, cp110_temp_base;
+
+	/* CP110 default configuration address space */
+	cp110_temp_base = MVEBU_AP_IO_BASE(MVEBU_AP0);
+
+	struct addr_map_win iowin_temp_win = {
+		.base_addr = cp110_temp_base,
+		.win_size = MVEBU_CP_OFFSET,
+	};
+
+	iowin_temp_win.target_id = mci_id;
+	iow_temp_win_insert(0, &iowin_temp_win, 1);
+
+	/* Calculate the new CP110 - base address */
+	cp110_base = MVEBU_CP_REGS_BASE(cp_id);
+	/* Go and update the CP110 configuration address space */
+	iob_cfg_space_update(0, cp_id, cp110_temp_base, cp110_base);
+
+	/* Remove the temporary IO-WIN window */
+	iow_temp_win_remove(0, &iowin_temp_win, 1);
+}
+
 void ap_init(void)
 {
 	/* Setup Aurora2. */
diff --git a/drivers/marvell/mochi/apn806_setup.c b/drivers/marvell/mochi/apn806_setup.c
index 1e91c43..1a02bd4 100644
--- a/drivers/marvell/mochi/apn806_setup.c
+++ b/drivers/marvell/mochi/apn806_setup.c
@@ -250,3 +250,6 @@
 	return 1;
 }
 
+void update_cp110_default_win(int cp_id)
+{
+}
diff --git a/drivers/marvell/mochi/cp110_setup.c b/drivers/marvell/mochi/cp110_setup.c
index 7186f98..0fa0497 100644
--- a/drivers/marvell/mochi/cp110_setup.c
+++ b/drivers/marvell/mochi/cp110_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Marvell International Ltd.
+ * Copyright (C) 2018-2020 Marvell International Ltd.
  *
  * SPDX-License-Identifier:     BSD-3-Clause
  * https://spdx.org/licenses
@@ -130,6 +130,7 @@
 #define USB3H_1_STREAM_ID_REG	(RFU_STREAM_ID_BASE + 0x10)
 #define SATA_0_STREAM_ID_REG	(RFU_STREAM_ID_BASE + 0x14)
 #define SATA_1_STREAM_ID_REG	(RFU_STREAM_ID_BASE + 0x18)
+#define SDIO_0_STREAM_ID_REG	(RFU_STREAM_ID_BASE + 0x28)
 
 #define CP_DMA_0_STREAM_ID_REG  (0x6B0010)
 #define CP_DMA_1_STREAM_ID_REG  (0x6D0010)
@@ -144,6 +145,7 @@
 	CP_DMA_1_STREAM_ID_REG,
 	SATA_0_STREAM_ID_REG,
 	SATA_1_STREAM_ID_REG,
+	SDIO_0_STREAM_ID_REG,
 	0
 };
 
diff --git a/drivers/measured_boot/event_log.c b/drivers/measured_boot/event_log.c
new file mode 100644
index 0000000..0042c96
--- /dev/null
+++ b/drivers/measured_boot/event_log.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <arch_helpers.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/auth/crypto_mod.h>
+#include <drivers/measured_boot/event_log.h>
+#include <mbedtls/md.h>
+
+#include <plat/common/platform.h>
+
+/* Event Log data */
+static uint8_t event_log[EVENT_LOG_SIZE];
+
+/* End of Event Log */
+#define	EVENT_LOG_END	((uintptr_t)event_log + sizeof(event_log) - 1U)
+
+CASSERT(sizeof(event_log) >= LOG_MIN_SIZE, assert_event_log_size);
+
+/* Pointer in event_log[] */
+static uint8_t *log_ptr = event_log;
+
+/* Pointer to measured_boot_data_t */
+const static measured_boot_data_t *plat_data_ptr;
+
+static uintptr_t tos_fw_config_base;
+static uintptr_t nt_fw_config_base;
+
+/* TCG_EfiSpecIdEvent */
+static const id_event_headers_t id_event_header = {
+	.header = {
+		.pcr_index = PCR_0,
+		.event_type = EV_NO_ACTION,
+		.digest = {0},
+		.event_size = (uint32_t)(sizeof(id_event_struct_t) +
+				(sizeof(id_event_algorithm_size_t) *
+				HASH_ALG_COUNT))
+	},
+
+	.struct_header = {
+		.signature = TCG_ID_EVENT_SIGNATURE_03,
+		.platform_class = PLATFORM_CLASS_CLIENT,
+		.spec_version_minor = TCG_SPEC_VERSION_MINOR_TPM2,
+		.spec_version_major = TCG_SPEC_VERSION_MAJOR_TPM2,
+		.spec_errata = TCG_SPEC_ERRATA_TPM2,
+		.uintn_size = (uint8_t)(sizeof(unsigned int) /
+					sizeof(uint32_t)),
+		.number_of_algorithms = HASH_ALG_COUNT
+	}
+};
+
+static const event2_header_t locality_event_header = {
+		/*
+		 * All EV_NO_ACTION events SHALL set
+		 * TCG_PCR_EVENT2.pcrIndex = 0, unless otherwise specified
+		 */
+		.pcr_index = PCR_0,
+
+		/*
+		 * All EV_NO_ACTION events SHALL set
+		 * TCG_PCR_EVENT2.eventType = 03h
+		 */
+		.event_type = EV_NO_ACTION,
+
+		/*
+		 * All EV_NO_ACTION events SHALL set
+		 * TCG_PCR_EVENT2.digests to all
+		 * 0x00's for each allocated Hash algorithm
+		 */
+		.digests = {
+			.count = HASH_ALG_COUNT
+		}
+};
+
+/* Platform's table with platform specific image IDs, names and PCRs */
+static const image_data_t plat_images_data[] = {
+	{ BL2_IMAGE_ID, BL2_STRING, PCR_0 },		/* Reserved for BL2 */
+	{ INVALID_ID, NULL, (unsigned int)(-1) }	/* Terminator */
+};
+
+static const measured_boot_data_t plat_measured_boot_data = {
+	plat_images_data,
+	NULL,	/* platform_set_nt_fw_info */
+	NULL	/* platform_set_tos_fw_info */
+};
+
+/*
+ * Function retuns pointer to platform's measured_boot_data_t structure
+ *
+ * Must be overridden in the platform code
+ */
+#pragma weak plat_get_measured_boot_data
+
+const measured_boot_data_t *plat_get_measured_boot_data(void)
+{
+	return &plat_measured_boot_data;
+}
+
+/*
+ * Add TCG_PCR_EVENT2 event
+ *
+ * @param[in] hash	Pointer to hash data of TCG_DIGEST_SIZE bytes
+ * @param[in] image_ptr	Pointer to image_data_t structure
+ * @return:
+ *	0 = success
+ *    < 0 = error code
+ */
+static int add_event2(const uint8_t *hash, const image_data_t *image_ptr)
+{
+	void *ptr = log_ptr;
+	uint32_t name_len;
+	uint32_t size_of_event;
+
+	assert(image_ptr != NULL);
+	assert(image_ptr->name != NULL);
+
+	name_len = (uint32_t)strlen(image_ptr->name) + 1U;
+	size_of_event = name_len + (uint32_t)EVENT2_HDR_SIZE;
+
+	/* Check for space in Event Log buffer */
+	if (((uintptr_t)ptr + size_of_event) > EVENT_LOG_END) {
+		ERROR("%s(): Event Log is short of memory", __func__);
+		return -ENOMEM;
+	}
+
+	/*
+	 * As per TCG specifications, firmware components that are measured
+	 * into PCR[0] must be logged in the event log using the event type
+	 * EV_POST_CODE.
+	 */
+	/* TCG_PCR_EVENT2.PCRIndex */
+	((event2_header_t *)ptr)->pcr_index = image_ptr->pcr;
+
+	/* TCG_PCR_EVENT2.EventType */
+	((event2_header_t *)ptr)->event_type = EV_POST_CODE;
+
+	/* TCG_PCR_EVENT2.Digests.Count */
+	ptr = (uint8_t *)ptr + offsetof(event2_header_t, digests);
+	((tpml_digest_values *)ptr)->count = HASH_ALG_COUNT;
+
+	/* TCG_PCR_EVENT2.Digests[] */
+	ptr = (uint8_t *)ptr + offsetof(tpml_digest_values, digests);
+
+	/* TCG_PCR_EVENT2.Digests[].AlgorithmId */
+	((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID;
+
+	/* TCG_PCR_EVENT2.Digests[].Digest[] */
+	ptr = (uint8_t *)ptr + offsetof(tpmt_ha, digest);
+
+	/* Check for space in Event Log buffer */
+	if (((uintptr_t)ptr + TCG_DIGEST_SIZE) > EVENT_LOG_END) {
+		ERROR("%s(): Event Log is short of memory", __func__);
+		return -ENOMEM;
+	}
+
+	if (hash == NULL) {
+		/* Get BL2 hash from DTB */
+		bl2_plat_get_hash(ptr);
+	} else {
+		/* Copy digest */
+		(void)memcpy(ptr, (const void *)hash, TCG_DIGEST_SIZE);
+	}
+
+	/* TCG_PCR_EVENT2.EventSize */
+	ptr = (uint8_t *)ptr + TCG_DIGEST_SIZE;
+	((event2_data_t *)ptr)->event_size = name_len;
+
+	/* Copy event data to TCG_PCR_EVENT2.Event */
+	(void)memcpy((void *)(((event2_data_t *)ptr)->event),
+			(const void *)image_ptr->name, name_len);
+
+	/* End of event data */
+	log_ptr = (uint8_t *)ptr + offsetof(event2_data_t, event) + name_len;
+
+	return 0;
+}
+
+/*
+ * Init Event Log
+ *
+ * Initialises Event Log by writing Specification ID and
+ * Startup Locality events.
+ */
+void event_log_init(void)
+{
+	const char locality_signature[] = TCG_STARTUP_LOCALITY_SIGNATURE;
+	const uint8_t *start_ptr;
+	void *ptr = event_log;
+
+	/* Get pointer to platform's measured_boot_data_t structure */
+	plat_data_ptr = plat_get_measured_boot_data();
+
+	/*
+	 * Add Specification ID Event first
+	 *
+	 * Copy TCG_EfiSpecIDEventStruct structure header
+	 */
+	(void)memcpy(ptr, (const void *)&id_event_header,
+			sizeof(id_event_header));
+	ptr = (uint8_t *)ptr + sizeof(id_event_header);
+
+	/* TCG_EfiSpecIdEventAlgorithmSize structure */
+	((id_event_algorithm_size_t *)ptr)->algorithm_id = TPM_ALG_ID;
+	((id_event_algorithm_size_t *)ptr)->digest_size = TCG_DIGEST_SIZE;
+	ptr = (uint8_t *)ptr + sizeof(id_event_algorithm_size_t);
+
+	/*
+	 * TCG_EfiSpecIDEventStruct.vendorInfoSize
+	 * No vendor data
+	 */
+	((id_event_struct_data_t *)ptr)->vendor_info_size = 0;
+	ptr = (uint8_t *)ptr + offsetof(id_event_struct_data_t, vendor_info);
+	if ((uintptr_t)ptr != ((uintptr_t)event_log + ID_EVENT_SIZE)) {
+		panic();
+	}
+
+	start_ptr = (uint8_t *)ptr;
+
+	/*
+	 * The Startup Locality event should be placed in the log before
+	 * any event which extends PCR[0].
+	 *
+	 * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3
+	 */
+
+	/* Copy Startup Locality Event Header */
+	(void)memcpy(ptr, (const void *)&locality_event_header,
+			sizeof(locality_event_header));
+	ptr = (uint8_t *)ptr + sizeof(locality_event_header);
+
+	/* TCG_PCR_EVENT2.Digests[].AlgorithmId */
+	((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID;
+
+	/* TCG_PCR_EVENT2.Digests[].Digest[] */
+	(void)memset(&((tpmt_ha *)ptr)->digest, 0, TPM_ALG_ID);
+	ptr = (uint8_t *)ptr + offsetof(tpmt_ha, digest) + TCG_DIGEST_SIZE;
+
+	/* TCG_PCR_EVENT2.EventSize */
+	((event2_data_t *)ptr)->event_size =
+		(uint32_t)sizeof(startup_locality_event_t);
+	ptr = (uint8_t *)ptr + offsetof(event2_data_t, event);
+
+	/* TCG_EfiStartupLocalityEvent.Signature */
+	(void)memcpy(ptr, (const void *)locality_signature,
+		sizeof(TCG_STARTUP_LOCALITY_SIGNATURE));
+
+	/*
+	 * TCG_EfiStartupLocalityEvent.StartupLocality = 0:
+	 * the platform's boot firmware
+	 */
+	((startup_locality_event_t *)ptr)->startup_locality = 0U;
+	ptr = (uint8_t *)ptr + sizeof(startup_locality_event_t);
+	if ((uintptr_t)ptr != ((uintptr_t)start_ptr + LOC_EVENT_SIZE)) {
+		panic();
+	}
+
+	log_ptr = (uint8_t *)ptr;
+
+	/* Add BL2 event */
+	if (add_event2(NULL, plat_data_ptr->images_data) != 0) {
+		panic();
+	}
+}
+
+/*
+ * Calculate and write hash of image, configuration data, etc.
+ * to Event Log.
+ *
+ * @param[in] data_base		Address of data
+ * @param[in] data_size		Size of data
+ * @param[in] data_id		Data ID
+ * @return:
+ *	0 = success
+ *    < 0 = error
+ */
+int tpm_record_measurement(uintptr_t data_base, uint32_t data_size,
+			   uint32_t data_id)
+{
+	const image_data_t *data_ptr = plat_data_ptr->images_data;
+	unsigned char hash_data[MBEDTLS_MD_MAX_SIZE];
+	int rc;
+
+	/* Check if image_id is supported */
+	while (data_ptr->id != data_id) {
+		if ((data_ptr++)->id == INVALID_ID) {
+			ERROR("%s(): image_id %u not supported\n",
+				__func__, data_id);
+			return -EINVAL;
+		}
+	}
+
+	if (data_id == TOS_FW_CONFIG_ID) {
+		tos_fw_config_base = data_base;
+	} else if (data_id == NT_FW_CONFIG_ID) {
+		nt_fw_config_base = data_base;
+	} else {
+		/* No action */
+	}
+
+	/* Calculate hash */
+	rc = crypto_mod_calc_hash((unsigned int)MBEDTLS_MD_ID,
+				(void *)data_base, data_size, hash_data);
+	if (rc != 0) {
+		return rc;
+	}
+
+	return add_event2(hash_data, data_ptr);
+}
+
+/*
+ * Finalise Event Log
+ *
+ * @param[out] log_addr	Pointer to return Event Log address
+ * @param[out] log_size	Pointer to return Event Log size
+ * @return:
+ *	0 = success
+ *    < 0 = error code
+ */
+int event_log_finalise(uint8_t **log_addr, size_t *log_size)
+{
+	/* Event Log size */
+	size_t num_bytes = (uintptr_t)log_ptr - (uintptr_t)event_log;
+	int rc;
+
+	assert(log_addr != NULL);
+	assert(log_size != NULL);
+
+	if (nt_fw_config_base == 0UL) {
+		ERROR("%s(): %s_FW_CONFIG not loaded\n", __func__, "NT");
+		return -ENOENT;
+	}
+
+	/*
+	 * Set Event Log data in NT_FW_CONFIG and
+	 * get Event Log address in Non-Secure memory
+	 */
+	if (plat_data_ptr->set_nt_fw_info != NULL) {
+
+		/* Event Log address in Non-Secure memory */
+		uintptr_t ns_log_addr;
+
+		rc = plat_data_ptr->set_nt_fw_info(
+				nt_fw_config_base,
+#ifdef SPD_opteed
+				(uintptr_t)event_log,
+#endif
+				num_bytes, &ns_log_addr);
+		if (rc != 0) {
+			ERROR("%s(): Unable to update %s_FW_CONFIG\n",
+						__func__, "NT");
+			return rc;
+		}
+
+		/* Copy Event Log to Non-secure memory */
+		(void)memcpy((void *)ns_log_addr, (const void *)event_log,
+				num_bytes);
+
+		/* Ensure that the Event Log is visible in Non-secure memory */
+		flush_dcache_range(ns_log_addr, num_bytes);
+
+		/* Return Event Log address in Non-Secure memory */
+		*log_addr = (uint8_t *)ns_log_addr;
+
+	} else {
+		INFO("%s(): set_%s_fw_info not set\n", __func__, "nt");
+
+		/* Return Event Log address in Secure memory */
+		*log_addr = event_log;
+	}
+
+	if (tos_fw_config_base != 0UL) {
+		if (plat_data_ptr->set_tos_fw_info != NULL) {
+
+			/* Set Event Log data in TOS_FW_CONFIG */
+			rc = plat_data_ptr->set_tos_fw_info(
+						tos_fw_config_base,
+						(uintptr_t)event_log,
+						num_bytes);
+			if (rc != 0) {
+				ERROR("%s(): Unable to update %s_FW_CONFIG\n",
+						__func__, "TOS");
+				return rc;
+			}
+		} else {
+			INFO("%s(): set_%s_fw_info not set\n", __func__, "tos");
+		}
+	} else {
+		INFO("%s(): %s_FW_CONFIG not loaded\n", __func__, "TOS");
+	}
+
+	/* Ensure that the Event Log is visible in Secure memory */
+	flush_dcache_range((uintptr_t)event_log, num_bytes);
+
+	/* Return Event Log size */
+	*log_size = num_bytes;
+
+	return 0;
+}
diff --git a/drivers/measured_boot/event_print.c b/drivers/measured_boot/event_print.c
new file mode 100644
index 0000000..ed970b8
--- /dev/null
+++ b/drivers/measured_boot/event_print.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <drivers/measured_boot/event_log.h>
+
+#if LOG_LEVEL >= EVENT_LOG_LEVEL
+
+/*
+ * Print TCG_EfiSpecIDEventStruct
+ *
+ * @param[in/out] log_addr	Pointer to Event Log
+ * @param[in/out] log_size	Pointer to Event Log size
+ */
+static void id_event_print(uint8_t **log_addr, size_t *log_size)
+{
+	unsigned int i;
+	uint8_t info_size, *info_size_ptr;
+	void *ptr = *log_addr;
+	id_event_headers_t *event = (id_event_headers_t *)ptr;
+	id_event_algorithm_size_t *alg_ptr;
+	uint32_t event_size, number_of_algorithms;
+	size_t digest_len;
+#if ENABLE_ASSERTIONS
+	const uint8_t *end_ptr = *log_addr + *log_size;
+	bool valid = true;
+#endif
+
+	assert(*log_size >= sizeof(id_event_headers_t));
+
+	/* The fields of the event log header are defined to be PCRIndex of 0,
+	 * EventType of EV_NO_ACTION, Digest of 20 bytes of 0, and
+	 * Event content defined as TCG_EfiSpecIDEventStruct.
+	 */
+	LOG_EVENT("TCG_EfiSpecIDEvent:\n");
+	LOG_EVENT("  PCRIndex           : %u\n", event->header.pcr_index);
+	assert(event->header.pcr_index == (uint32_t)PCR_0);
+
+	LOG_EVENT("  EventType          : %u\n", event->header.event_type);
+	assert(event->header.event_type == EV_NO_ACTION);
+
+	LOG_EVENT("  Digest             :");
+	for (i = 0U; i < sizeof(event->header.digest); ++i) {
+		uint8_t val = event->header.digest[i];
+
+		(void)printf(" %02x", val);
+		if ((i & U(0xF)) == 0U) {
+			(void)printf("\n");
+			LOG_EVENT("\t\t      :");
+		}
+#if ENABLE_ASSERTIONS
+		if (val != 0U) {
+			valid = false;
+		}
+#endif
+	}
+	if ((i & U(0xF)) != 0U) {
+		(void)printf("\n");
+	}
+
+	assert(valid);
+
+	/* EventSize */
+	event_size = event->header.event_size;
+	LOG_EVENT("  EventSize          : %u\n", event_size);
+
+	LOG_EVENT("  Signature          : %s\n",
+			event->struct_header.signature);
+	LOG_EVENT("  PlatformClass      : %u\n",
+			event->struct_header.platform_class);
+	LOG_EVENT("  SpecVersion        : %u.%u.%u\n",
+			event->struct_header.spec_version_major,
+			event->struct_header.spec_version_minor,
+			event->struct_header.spec_errata);
+	LOG_EVENT("  UintnSize          : %u\n",
+			event->struct_header.uintn_size);
+
+	/* NumberOfAlgorithms */
+	number_of_algorithms = event->struct_header.number_of_algorithms;
+	LOG_EVENT("  NumberOfAlgorithms : %u\n", number_of_algorithms);
+
+	/* Address of DigestSizes[] */
+	alg_ptr = event->struct_header.digest_size;
+
+	/* Size of DigestSizes[] */
+	digest_len = number_of_algorithms * sizeof(id_event_algorithm_size_t);
+	assert(((uint8_t *)alg_ptr + digest_len) <= end_ptr);
+
+	LOG_EVENT("  DigestSizes        :\n");
+	for (i = 0U; i < number_of_algorithms; ++i) {
+		LOG_EVENT("    #%u AlgorithmId   : SHA", i);
+		uint16_t algorithm_id = alg_ptr[i].algorithm_id;
+
+		switch (algorithm_id) {
+		case TPM_ALG_SHA256:
+			(void)printf("256\n");
+			break;
+		case TPM_ALG_SHA384:
+			(void)printf("384\n");
+			break;
+		case TPM_ALG_SHA512:
+			(void)printf("512\n");
+			break;
+		default:
+			(void)printf("?\n");
+			ERROR("Algorithm 0x%x not found\n", algorithm_id);
+			assert(false);
+		}
+
+		LOG_EVENT("       DigestSize    : %u\n",
+					alg_ptr[i].digest_size);
+	}
+
+	/* Address of VendorInfoSize */
+	info_size_ptr = (uint8_t *)alg_ptr + digest_len;
+	assert(info_size_ptr <= end_ptr);
+
+	info_size = *info_size_ptr++;
+	LOG_EVENT("  VendorInfoSize     : %u\n", info_size);
+
+	/* Check VendorInfo end address */
+	assert((info_size_ptr + info_size) <= end_ptr);
+
+	/* Check EventSize */
+	assert(event_size == (sizeof(id_event_struct_t) +
+				digest_len + info_size));
+	if (info_size != 0U) {
+		LOG_EVENT("  VendorInfo         :");
+		for (i = 0U; i < info_size; ++i) {
+			(void)printf(" %02x", *info_size_ptr++);
+		}
+		(void)printf("\n");
+	}
+
+	*log_size -= (uintptr_t)info_size_ptr - (uintptr_t)*log_addr;
+	*log_addr = info_size_ptr;
+}
+
+/*
+ * Print TCG_PCR_EVENT2
+ *
+ * @param[in/out] log_addr	Pointer to Event Log
+ * @param[in/out] log_size	Pointer to Event Log size
+ */
+static void event2_print(uint8_t **log_addr, size_t *log_size)
+{
+	uint32_t event_size, count;
+	size_t sha_size, digests_size = 0U;
+	void *ptr = *log_addr;
+#if ENABLE_ASSERTIONS
+	const uint8_t *end_ptr = *log_addr + *log_size;
+#endif
+
+	assert(*log_size >= sizeof(event2_header_t));
+
+	LOG_EVENT("PCR_Event2:\n");
+	LOG_EVENT("  PCRIndex           : %u\n",
+			((event2_header_t *)ptr)->pcr_index);
+	LOG_EVENT("  EventType          : %u\n",
+			((event2_header_t *)ptr)->event_type);
+
+	count = ((event2_header_t *)ptr)->digests.count;
+	LOG_EVENT("  Digests Count      : %u\n", count);
+
+	/* Address of TCG_PCR_EVENT2.Digests[] */
+	ptr = (uint8_t *)ptr + sizeof(event2_header_t);
+	assert(((uintptr_t)ptr <= (uintptr_t)end_ptr) && (count != 0U));
+
+	for (unsigned int i = 0U; i < count; ++i) {
+		/* Check AlgorithmId address */
+		assert(((uint8_t *)ptr + offsetof(tpmt_ha, digest)) <= end_ptr);
+
+		LOG_EVENT("    #%u AlgorithmId   : SHA", i);
+		switch (((tpmt_ha *)ptr)->algorithm_id) {
+		case TPM_ALG_SHA256:
+			sha_size = SHA256_DIGEST_SIZE;
+			(void)printf("256\n");
+			break;
+		case TPM_ALG_SHA384:
+			sha_size = SHA384_DIGEST_SIZE;
+			(void)printf("384\n");
+			break;
+		case TPM_ALG_SHA512:
+			sha_size = SHA512_DIGEST_SIZE;
+			(void)printf("512\n");
+			break;
+		default:
+			(void)printf("?\n");
+			ERROR("Algorithm 0x%x not found\n",
+				((tpmt_ha *)ptr)->algorithm_id);
+			panic();
+		}
+
+		/* End of Digest[] */
+		ptr = (uint8_t *)ptr + offsetof(tpmt_ha, digest);
+		assert(((uint8_t *)ptr + sha_size) <= end_ptr);
+
+		/* Total size of all digests */
+		digests_size += sha_size;
+
+		LOG_EVENT("       Digest        :");
+		for (unsigned int j = 0U; j < sha_size; ++j) {
+			(void)printf(" %02x", *(uint8_t *)ptr++);
+			if ((j & U(0xF)) == U(0xF)) {
+				(void)printf("\n");
+				if (j < (sha_size - 1U)) {
+					LOG_EVENT("\t\t      :");
+				}
+			}
+		}
+	}
+
+	/* TCG_PCR_EVENT2.EventSize */
+	assert(((uint8_t *)ptr + offsetof(event2_data_t, event)) <= end_ptr);
+
+	event_size = ((event2_data_t *)ptr)->event_size;
+	LOG_EVENT("  EventSize          : %u\n", event_size);
+
+	/* Address of TCG_PCR_EVENT2.Event[EventSize] */
+	ptr = (uint8_t *)ptr + offsetof(event2_data_t, event);
+
+	/* End of TCG_PCR_EVENT2.Event[EventSize] */
+	assert(((uint8_t *)ptr + event_size) <= end_ptr);
+
+	if ((event_size == sizeof(startup_locality_event_t)) &&
+	     (strcmp((const char *)ptr, TCG_STARTUP_LOCALITY_SIGNATURE) == 0)) {
+		LOG_EVENT("  Signature          : %s\n",
+			((startup_locality_event_t *)ptr)->signature);
+		LOG_EVENT("  StartupLocality    : %u\n",
+			((startup_locality_event_t *)ptr)->startup_locality);
+	} else {
+		LOG_EVENT("  Event              : %s\n", (uint8_t *)ptr);
+	}
+
+	*log_size -= (uintptr_t)ptr + event_size - (uintptr_t)*log_addr;
+	*log_addr = (uint8_t *)ptr + event_size;
+}
+#endif	/* LOG_LEVEL >= EVENT_LOG_LEVEL */
+
+/*
+ * Print Event Log
+ *
+ * @param[in]	log_addr	Pointer to Event Log
+ * @param[in]	log_size	Event Log size
+ */
+void dump_event_log(uint8_t *log_addr, size_t log_size)
+{
+#if LOG_LEVEL >= EVENT_LOG_LEVEL
+	assert(log_addr != NULL);
+
+	/* Print TCG_EfiSpecIDEvent */
+	id_event_print(&log_addr, &log_size);
+
+	while (log_size != 0U) {
+		event2_print(&log_addr, &log_size);
+	}
+#endif
+}
diff --git a/drivers/measured_boot/measured_boot.c b/drivers/measured_boot/measured_boot.c
new file mode 100644
index 0000000..37fddfb
--- /dev/null
+++ b/drivers/measured_boot/measured_boot.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/measured_boot/measured_boot.h>
+
+/*
+ * Init Measured Boot driver
+ *
+ * Initialises Event Log.
+ */
+void measured_boot_init(void)
+{
+	event_log_init();
+}
+
+/*
+ * Finish Measured Boot driver
+ *
+ * Finalises Event Log and dumps the records to the debug console.
+ */
+void measured_boot_finish(void)
+{
+	uint8_t *log_addr;
+	size_t log_size;
+	int rc;
+
+	rc = event_log_finalise(&log_addr, &log_size);
+	if (rc != 0) {
+		panic();
+	}
+
+	dump_event_log(log_addr, log_size);
+}
diff --git a/drivers/measured_boot/measured_boot.mk b/drivers/measured_boot/measured_boot.mk
new file mode 100644
index 0000000..fc005d5
--- /dev/null
+++ b/drivers/measured_boot/measured_boot.mk
@@ -0,0 +1,45 @@
+#
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# TPM hash algorithm
+TPM_HASH_ALG			:=	sha256
+
+ifeq (${TPM_HASH_ALG}, sha512)
+    MBEDTLS_MD_ID		:=	MBEDTLS_MD_SHA512
+    TPM_ALG_ID			:=	TPM_ALG_SHA512
+    TCG_DIGEST_SIZE		:=	64U
+else ifeq (${TPM_HASH_ALG}, sha384)
+    MBEDTLS_MD_ID		:=	MBEDTLS_MD_SHA384
+    TPM_ALG_ID			:=	TPM_ALG_SHA384
+    TCG_DIGEST_SIZE		:=	48U
+else
+    MBEDTLS_MD_ID		:=	MBEDTLS_MD_SHA256
+    TPM_ALG_ID			:=	TPM_ALG_SHA256
+    TCG_DIGEST_SIZE		:=	32U
+endif
+
+# Event Log length in bytes
+EVENT_LOG_SIZE			:= 1024
+
+# Set definitions for mbed TLS library and Measured Boot driver
+$(eval $(call add_define,MBEDTLS_MD_ID))
+$(eval $(call add_define,TPM_ALG_ID))
+$(eval $(call add_define,TCG_DIGEST_SIZE))
+$(eval $(call add_define,EVENT_LOG_SIZE))
+
+ifeq (${HASH_ALG}, sha256)
+ifneq (${TPM_HASH_ALG}, sha256)
+$(eval $(call add_define,MBEDTLS_SHA512_C))
+endif
+endif
+
+MEASURED_BOOT_SRC_DIR	:= drivers/measured_boot/
+
+MEASURED_BOOT_SOURCES	:= ${MEASURED_BOOT_SRC_DIR}measured_boot.c	\
+    			   ${MEASURED_BOOT_SRC_DIR}event_log.c		\
+    			   ${MEASURED_BOOT_SRC_DIR}event_print.c
+
+BL2_SOURCES		+= ${MEASURED_BOOT_SOURCES}
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
index 540c66a..d6cd8b1 100644
--- a/drivers/st/clk/stm32mp1_clk.c
+++ b/drivers/st/clk/stm32mp1_clk.c
@@ -106,10 +106,62 @@
 	_MCUS_SEL,
 	_USBPHY_SEL,
 	_USBO_SEL,
+	_MPU_SEL,
+	_PER_SEL,
+	_RTC_SEL,
 	_PARENT_SEL_NB,
 	_UNKNOWN_SEL = 0xff,
 };
 
+/* State the parent clock ID straight related to a clock */
+static const uint8_t parent_id_clock_id[_PARENT_NB] = {
+	[_HSE] = CK_HSE,
+	[_HSI] = CK_HSI,
+	[_CSI] = CK_CSI,
+	[_LSE] = CK_LSE,
+	[_LSI] = CK_LSI,
+	[_I2S_CKIN] = _UNKNOWN_ID,
+	[_USB_PHY_48] = _UNKNOWN_ID,
+	[_HSI_KER] = CK_HSI,
+	[_HSE_KER] = CK_HSE,
+	[_HSE_KER_DIV2] = CK_HSE_DIV2,
+	[_CSI_KER] = CK_CSI,
+	[_PLL1_P] = PLL1_P,
+	[_PLL1_Q] = PLL1_Q,
+	[_PLL1_R] = PLL1_R,
+	[_PLL2_P] = PLL2_P,
+	[_PLL2_Q] = PLL2_Q,
+	[_PLL2_R] = PLL2_R,
+	[_PLL3_P] = PLL3_P,
+	[_PLL3_Q] = PLL3_Q,
+	[_PLL3_R] = PLL3_R,
+	[_PLL4_P] = PLL4_P,
+	[_PLL4_Q] = PLL4_Q,
+	[_PLL4_R] = PLL4_R,
+	[_ACLK] = CK_AXI,
+	[_PCLK1] = CK_AXI,
+	[_PCLK2] = CK_AXI,
+	[_PCLK3] = CK_AXI,
+	[_PCLK4] = CK_AXI,
+	[_PCLK5] = CK_AXI,
+	[_CK_PER] = CK_PER,
+	[_CK_MPU] = CK_MPU,
+	[_CK_MCU] = CK_MCU,
+};
+
+static unsigned int clock_id2parent_id(unsigned long id)
+{
+	unsigned int n;
+
+	for (n = 0U; n < ARRAY_SIZE(parent_id_clock_id); n++) {
+		if (parent_id_clock_id[n] == id) {
+			return n;
+		}
+	}
+
+	return _UNKNOWN_ID;
+}
+
 enum stm32mp1_pll_id {
 	_PLL1,
 	_PLL2,
@@ -259,7 +311,8 @@
 	[_ ## _label ## _SEL] = {				\
 		.offset = _rcc_selr,				\
 		.src = _rcc_selr ## _ ## _label ## SRC_SHIFT,	\
-		.msk = _rcc_selr ## _ ## _label ## SRC_MASK,	\
+		.msk = (_rcc_selr ## _ ## _label ## SRC_MASK) >> \
+		       (_rcc_selr ## _ ## _label ## SRC_SHIFT), \
 		.parent = (_parents),				\
 		.nb_parent = ARRAY_SIZE(_parents)		\
 	}
@@ -281,19 +334,6 @@
 		.refclk[3] = (p4),			\
 	}
 
-static const uint8_t stm32mp1_clks[][2] = {
-	{ CK_PER, _CK_PER },
-	{ CK_MPU, _CK_MPU },
-	{ CK_AXI, _ACLK },
-	{ CK_MCU, _CK_MCU },
-	{ CK_HSE, _HSE },
-	{ CK_CSI, _CSI },
-	{ CK_LSI, _LSI },
-	{ CK_LSE, _LSE },
-	{ CK_HSI, _HSI },
-	{ CK_HSE_DIV2, _HSE_KER_DIV2 },
-};
-
 #define NB_GATES	ARRAY_SIZE(stm32mp1_clk_gate)
 
 static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
@@ -369,6 +409,7 @@
 	_CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL),
 	_CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL),
 
+	_CLK_SELEC(RCC_BDCR, 20, RTC, _RTC_SEL),
 	_CLK_SELEC(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL),
 };
 
@@ -440,6 +481,18 @@
 	_PLL4_R, _USB_PHY_48
 };
 
+static const uint8_t mpu_parents[] = {
+	_HSI, _HSE, _PLL1_P, _PLL1_P /* specific div */
+};
+
+static const uint8_t per_parents[] = {
+	_HSI, _HSE, _CSI,
+};
+
+static const uint8_t rtc_parents[] = {
+	_UNKNOWN_ID, _LSE, _LSI, _HSE
+};
+
 static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
 	_CLK_PARENT_SEL(I2C12, RCC_I2C12CKSELR, i2c12_parents),
 	_CLK_PARENT_SEL(I2C35, RCC_I2C35CKSELR, i2c35_parents),
@@ -448,6 +501,9 @@
 	_CLK_PARENT_SEL(SPI6, RCC_SPI6CKSELR, spi6_parents),
 	_CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents),
 	_CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents),
+	_CLK_PARENT_SEL(MPU, RCC_MPCKSELR, mpu_parents),
+	_CLK_PARENT_SEL(PER, RCC_CPERCKSELR, per_parents),
+	_CLK_PARENT_SEL(RTC, RCC_BDCR, rtc_parents),
 	_CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents),
 	_CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents),
 	_CLK_PARENT_SEL(UART35, RCC_UART35CKSELR, uart234578_parents),
@@ -521,6 +577,43 @@
 	1, 2, 3, 4, 4, 4, 4, 4
 };
 
+static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = {
+	[_HSI] = "HSI",
+	[_HSE] = "HSE",
+	[_CSI] = "CSI",
+	[_LSI] = "LSI",
+	[_LSE] = "LSE",
+	[_I2S_CKIN] = "I2S_CKIN",
+	[_HSI_KER] = "HSI_KER",
+	[_HSE_KER] = "HSE_KER",
+	[_HSE_KER_DIV2] = "HSE_KER_DIV2",
+	[_CSI_KER] = "CSI_KER",
+	[_PLL1_P] = "PLL1_P",
+	[_PLL1_Q] = "PLL1_Q",
+	[_PLL1_R] = "PLL1_R",
+	[_PLL2_P] = "PLL2_P",
+	[_PLL2_Q] = "PLL2_Q",
+	[_PLL2_R] = "PLL2_R",
+	[_PLL3_P] = "PLL3_P",
+	[_PLL3_Q] = "PLL3_Q",
+	[_PLL3_R] = "PLL3_R",
+	[_PLL4_P] = "PLL4_P",
+	[_PLL4_Q] = "PLL4_Q",
+	[_PLL4_R] = "PLL4_R",
+	[_ACLK] = "ACLK",
+	[_PCLK1] = "PCLK1",
+	[_PCLK2] = "PCLK2",
+	[_PCLK3] = "PCLK3",
+	[_PCLK4] = "PCLK4",
+	[_PCLK5] = "PCLK5",
+	[_HCLK6] = "KCLK6",
+	[_HCLK2] = "HCLK2",
+	[_CK_PER] = "CK_PER",
+	[_CK_MPU] = "CK_MPU",
+	[_CK_MCU] = "CK_MCU",
+	[_USB_PHY_48] = "USB_PHY_48",
+};
+
 /* RCC clock device driver private */
 static unsigned long stm32mp1_osc[NB_OSC];
 static struct spinlock reg_lock;
@@ -618,16 +711,16 @@
 static int stm32mp1_clk_get_parent(unsigned long id)
 {
 	const struct stm32mp1_clk_sel *sel;
-	uint32_t j, p_sel;
+	uint32_t p_sel;
 	int i;
 	enum stm32mp1_parent_id p;
 	enum stm32mp1_parent_sel s;
 	uintptr_t rcc_base = stm32mp_rcc_base();
 
-	for (j = 0U; j < ARRAY_SIZE(stm32mp1_clks); j++) {
-		if (stm32mp1_clks[j][0] == id) {
-			return (int)stm32mp1_clks[j][1];
-		}
+	/* Few non gateable clock have a static parent ID, find them */
+	i = (int)clock_id2parent_id(id);
+	if (i != _UNKNOWN_ID) {
+		return i;
 	}
 
 	i = stm32mp1_clk_get_gated_id(id);
@@ -649,7 +742,8 @@
 	}
 
 	sel = clk_sel_ref(s);
-	p_sel = (mmio_read_32(rcc_base + sel->offset) & sel->msk) >> sel->src;
+	p_sel = (mmio_read_32(rcc_base + sel->offset) &
+		 (sel->msk << sel->src)) >> sel->src;
 	if (p_sel < sel->nb_parent) {
 		return (int)sel->parent[p_sel];
 	}
@@ -931,27 +1025,27 @@
 {
 	uintptr_t rcc_base = stm32mp_rcc_base();
 
+	VERBOSE("Enable clock %u\n", gate->index);
+
 	if (gate->set_clr != 0U) {
 		mmio_write_32(rcc_base + gate->offset, BIT(gate->bit));
 	} else {
 		mmio_setbits_32(rcc_base + gate->offset, BIT(gate->bit));
 	}
-
-	VERBOSE("Clock %d has been enabled", gate->index);
 }
 
 static void __clk_disable(struct stm32mp1_clk_gate const *gate)
 {
 	uintptr_t rcc_base = stm32mp_rcc_base();
 
+	VERBOSE("Disable clock %u\n", gate->index);
+
 	if (gate->set_clr != 0U) {
 		mmio_write_32(rcc_base + gate->offset + RCC_MP_ENCLRR_OFFSET,
 			      BIT(gate->bit));
 	} else {
 		mmio_clrbits_32(rcc_base + gate->offset, BIT(gate->bit));
 	}
-
-	VERBOSE("Clock %d has been disabled", gate->index);
 }
 
 static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate)
@@ -972,12 +1066,41 @@
 	return gate_refcounts[i];
 }
 
+/* Oscillators and PLLs are not gated at runtime */
+static bool clock_is_always_on(unsigned long id)
+{
+	switch (id) {
+	case CK_HSE:
+	case CK_CSI:
+	case CK_LSI:
+	case CK_LSE:
+	case CK_HSI:
+	case CK_HSE_DIV2:
+	case PLL1_Q:
+	case PLL1_R:
+	case PLL2_P:
+	case PLL2_Q:
+	case PLL2_R:
+	case PLL3_P:
+	case PLL3_Q:
+	case PLL3_R:
+		return true;
+	default:
+		return false;
+	}
+}
+
 void __stm32mp1_clk_enable(unsigned long id, bool secure)
 {
 	const struct stm32mp1_clk_gate *gate;
-	int i = stm32mp1_clk_get_gated_id(id);
+	int i;
 	unsigned int *refcnt;
 
+	if (clock_is_always_on(id)) {
+		return;
+	}
+
+	i = stm32mp1_clk_get_gated_id(id);
 	if (i < 0) {
 		ERROR("Clock %d can't be enabled\n", (uint32_t)id);
 		panic();
@@ -998,9 +1121,14 @@
 void __stm32mp1_clk_disable(unsigned long id, bool secure)
 {
 	const struct stm32mp1_clk_gate *gate;
-	int i = stm32mp1_clk_get_gated_id(id);
+	int i;
 	unsigned int *refcnt;
 
+	if (clock_is_always_on(id)) {
+		return;
+	}
+
+	i = stm32mp1_clk_get_gated_id(id);
 	if (i < 0) {
 		ERROR("Clock %d can't be disabled\n", (uint32_t)id);
 		panic();
@@ -1030,8 +1158,13 @@
 
 bool stm32mp_clk_is_enabled(unsigned long id)
 {
-	int i = stm32mp1_clk_get_gated_id(id);
+	int i;
 
+	if (clock_is_always_on(id)) {
+		return true;
+	}
+
+	i = stm32mp1_clk_get_gated_id(id);
 	if (i < 0) {
 		panic();
 	}
@@ -1911,8 +2044,184 @@
 	}
 }
 
+#ifdef STM32MP_SHARED_RESOURCES
+/*
+ * Get the parent ID of the target parent clock, for tagging as secure
+ * shared clock dependencies.
+ */
+static int get_parent_id_parent(unsigned int parent_id)
+{
+	enum stm32mp1_parent_sel s = _UNKNOWN_SEL;
+	enum stm32mp1_pll_id pll_id;
+	uint32_t p_sel;
+	uintptr_t rcc_base = stm32mp_rcc_base();
+
+	switch (parent_id) {
+	case _ACLK:
+	case _PCLK4:
+	case _PCLK5:
+		s = _AXIS_SEL;
+		break;
+	case _PLL1_P:
+	case _PLL1_Q:
+	case _PLL1_R:
+		pll_id = _PLL1;
+		break;
+	case _PLL2_P:
+	case _PLL2_Q:
+	case _PLL2_R:
+		pll_id = _PLL2;
+		break;
+	case _PLL3_P:
+	case _PLL3_Q:
+	case _PLL3_R:
+		pll_id = _PLL3;
+		break;
+	case _PLL4_P:
+	case _PLL4_Q:
+	case _PLL4_R:
+		pll_id = _PLL4;
+		break;
+	case _PCLK1:
+	case _PCLK2:
+	case _HCLK2:
+	case _HCLK6:
+	case _CK_PER:
+	case _CK_MPU:
+	case _CK_MCU:
+	case _USB_PHY_48:
+		/* We do not expect to access these */
+		panic();
+		break;
+	default:
+		/* Other parents have no parent */
+		return -1;
+	}
+
+	if (s != _UNKNOWN_SEL) {
+		const struct stm32mp1_clk_sel *sel = clk_sel_ref(s);
+
+		p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) &
+			sel->msk;
+
+		if (p_sel < sel->nb_parent) {
+			return (int)sel->parent[p_sel];
+		}
+	} else {
+		const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
+
+		p_sel = mmio_read_32(rcc_base + pll->rckxselr) &
+			RCC_SELR_REFCLK_SRC_MASK;
+
+		if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) {
+			return (int)pll->refclk[p_sel];
+		}
+	}
+
+	VERBOSE("No parent selected for %s\n",
+		stm32mp1_clk_parent_name[parent_id]);
+
+	return -1;
+}
+
+static void secure_parent_clocks(unsigned long parent_id)
+{
+	int grandparent_id;
+
+	switch (parent_id) {
+	case _PLL3_P:
+	case _PLL3_Q:
+	case _PLL3_R:
+		stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3);
+		break;
+
+	/* These clocks are always secure when RCC is secure */
+	case _ACLK:
+	case _HCLK2:
+	case _HCLK6:
+	case _PCLK4:
+	case _PCLK5:
+	case _PLL1_P:
+	case _PLL1_Q:
+	case _PLL1_R:
+	case _PLL2_P:
+	case _PLL2_Q:
+	case _PLL2_R:
+	case _HSI:
+	case _HSI_KER:
+	case _LSI:
+	case _CSI:
+	case _CSI_KER:
+	case _HSE:
+	case _HSE_KER:
+	case _HSE_KER_DIV2:
+	case _LSE:
+		break;
+
+	default:
+		VERBOSE("Cannot secure parent clock %s\n",
+			stm32mp1_clk_parent_name[parent_id]);
+		panic();
+	}
+
+	grandparent_id = get_parent_id_parent(parent_id);
+	if (grandparent_id >= 0) {
+		secure_parent_clocks(grandparent_id);
+	}
+}
+
+void stm32mp1_register_clock_parents_secure(unsigned long clock_id)
+{
+	int parent_id;
+
+	if (!stm32mp1_rcc_is_secure()) {
+		return;
+	}
+
+	switch (clock_id) {
+	case PLL1:
+	case PLL2:
+		/* PLL1/PLL2 are always secure: nothing to do */
+		break;
+	case PLL3:
+		stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3);
+		break;
+	case PLL4:
+		ERROR("PLL4 cannot be secured\n");
+		panic();
+		break;
+	default:
+		/* Others are expected gateable clock */
+		parent_id = stm32mp1_clk_get_parent(clock_id);
+		if (parent_id < 0) {
+			INFO("No parent found for clock %lu\n", clock_id);
+		} else {
+			secure_parent_clocks(parent_id);
+		}
+		break;
+	}
+}
+#endif /* STM32MP_SHARED_RESOURCES */
+
 static void sync_earlyboot_clocks_state(void)
 {
+	unsigned int idx;
+	const unsigned long secure_enable[] = {
+		AXIDCG,
+		BSEC,
+		DDRC1, DDRC1LP,
+		DDRC2, DDRC2LP,
+		DDRCAPB, DDRPHYCAPB, DDRPHYCAPBLP,
+		DDRPHYC, DDRPHYCLP,
+		TZC1, TZC2,
+		TZPC,
+		STGEN_K,
+	};
+
+	for (idx = 0U; idx < ARRAY_SIZE(secure_enable); idx++) {
+		stm32mp_clk_enable(secure_enable[idx]);
+	}
+
 	if (!stm32mp_is_single_core()) {
 		stm32mp1_clk_enable_secure(RTCAPB);
 	}
diff --git a/drivers/st/crypto/stm32_hash.c b/drivers/st/crypto/stm32_hash.c
index f72787d..515947c 100644
--- a/drivers/st/crypto/stm32_hash.c
+++ b/drivers/st/crypto/stm32_hash.c
@@ -51,6 +51,7 @@
 #define SHA224_DIGEST_SIZE		28U
 #define SHA256_DIGEST_SIZE		32U
 
+#define RESET_TIMEOUT_US_1MS		1000U
 #define HASH_TIMEOUT_US			10000U
 
 enum stm32_hash_data_format {
@@ -299,7 +300,9 @@
 			break;
 		}
 #else
+		/* BL32 uses hash if it is assigned only to secure world */
 		if (hash_info.status == DT_SECURE) {
+			stm32mp_register_secure_periph_iomem(hash_info.base);
 			break;
 		}
 #endif
@@ -319,9 +322,15 @@
 	stm32mp_clk_enable(stm32_hash.clock);
 
 	if (hash_info.reset >= 0) {
-		stm32mp_reset_assert((unsigned long)hash_info.reset);
+		uint32_t id = (uint32_t)hash_info.reset;
+
+		if (stm32mp_reset_assert(id, RESET_TIMEOUT_US_1MS) != 0) {
+			panic();
+		}
 		udelay(20);
-		stm32mp_reset_deassert((unsigned long)hash_info.reset);
+		if (stm32mp_reset_deassert(id, RESET_TIMEOUT_US_1MS) != 0) {
+			panic();
+		}
 	}
 
 	stm32mp_clk_disable(stm32_hash.clock);
diff --git a/drivers/st/etzpc/etzpc.c b/drivers/st/etzpc/etzpc.c
new file mode 100644
index 0000000..ff52a22
--- /dev/null
+++ b/drivers/st/etzpc/etzpc.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/st/etzpc.h>
+#include <dt-bindings/soc/st,stm32-etzpc.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+#include <libfdt.h>
+
+#include <platform_def.h>
+
+/* Device Tree related definitions */
+#define ETZPC_COMPAT			"st,stm32-etzpc"
+#define ETZPC_LOCK_MASK			0x1U
+#define ETZPC_MODE_SHIFT		8
+#define ETZPC_MODE_MASK			GENMASK(1, 0)
+#define ETZPC_ID_SHIFT			16
+#define ETZPC_ID_MASK			GENMASK(7, 0)
+
+/* ID Registers */
+#define ETZPC_TZMA0_SIZE		0x000U
+#define ETZPC_DECPROT0			0x010U
+#define ETZPC_DECPROT_LOCK0		0x030U
+#define ETZPC_HWCFGR			0x3F0U
+#define ETZPC_VERR			0x3F4U
+
+/* ID Registers fields */
+#define ETZPC_TZMA0_SIZE_LOCK		BIT(31)
+#define ETZPC_DECPROT0_MASK		GENMASK(1, 0)
+#define ETZPC_HWCFGR_NUM_TZMA_SHIFT	0
+#define ETZPC_HWCFGR_NUM_PER_SEC_SHIFT	8
+#define ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT	16
+#define ETZPC_HWCFGR_CHUNCKS1N4_SHIFT	24
+
+#define DECPROT_SHIFT			1
+#define IDS_PER_DECPROT_REGS		16U
+#define IDS_PER_DECPROT_LOCK_REGS	32U
+
+/*
+ * etzpc_instance.
+ * base : register base address set during init given by user
+ * chunk_size : supported TZMA size steps
+ * num_tzma: number of TZMA zone read from register at init
+ * num_ahb_sec : number of securable AHB master zone read from register
+ * num_per_sec : number of securable AHB & APB Peripherals read from register
+ * revision : IP revision read from register at init
+ */
+struct etzpc_instance {
+	uintptr_t base;
+	uint8_t chunck_size;
+	uint8_t num_tzma;
+	uint8_t num_per_sec;
+	uint8_t num_ahb_sec;
+	uint8_t revision;
+};
+
+/* Only 1 instance of the ETZPC is expected per platform */
+static struct etzpc_instance etzpc_dev;
+
+/*
+ * Implementation uses uint8_t to store each securable DECPROT configuration.
+ * When resuming from deep suspend, the DECPROT configurations are restored.
+ */
+#define PERIPH_LOCK_BIT		BIT(7)
+#define PERIPH_ATTR_MASK	GENMASK(2, 0)
+
+#if ENABLE_ASSERTIONS
+static bool valid_decprot_id(unsigned int id)
+{
+	return id < (unsigned int)etzpc_dev.num_per_sec;
+}
+
+static bool valid_tzma_id(unsigned int id)
+{
+	return id < (unsigned int)etzpc_dev.num_tzma;
+}
+#endif
+
+/*
+ * etzpc_configure_decprot : Load a DECPROT configuration
+ * decprot_id : ID of the IP
+ * decprot_attr : Restriction access attribute
+ */
+void etzpc_configure_decprot(uint32_t decprot_id,
+			     enum etzpc_decprot_attributes decprot_attr)
+{
+	uintptr_t offset = 4U * (decprot_id / IDS_PER_DECPROT_REGS);
+	uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT;
+	uint32_t masked_decprot = (uint32_t)decprot_attr & ETZPC_DECPROT0_MASK;
+
+	assert(valid_decprot_id(decprot_id));
+
+	mmio_clrsetbits_32(etzpc_dev.base + ETZPC_DECPROT0 + offset,
+			   (uint32_t)ETZPC_DECPROT0_MASK << shift,
+			   masked_decprot << shift);
+}
+
+/*
+ * etzpc_get_decprot : Get the DECPROT attribute
+ * decprot_id : ID of the IP
+ * return : Attribute of this DECPROT
+ */
+enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id)
+{
+	uintptr_t offset = 4U * (decprot_id / IDS_PER_DECPROT_REGS);
+	uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT;
+	uintptr_t base_decprot = etzpc_dev.base + offset;
+	uint32_t value;
+
+	assert(valid_decprot_id(decprot_id));
+
+	value = (mmio_read_32(base_decprot + ETZPC_DECPROT0) >> shift) &
+		ETZPC_DECPROT0_MASK;
+
+	return (enum etzpc_decprot_attributes)value;
+}
+
+/*
+ * etzpc_lock_decprot : Lock access to the DECPROT attribute
+ * decprot_id : ID of the IP
+ */
+void etzpc_lock_decprot(uint32_t decprot_id)
+{
+	uintptr_t offset = 4U * (decprot_id / IDS_PER_DECPROT_LOCK_REGS);
+	uint32_t shift = BIT(decprot_id % IDS_PER_DECPROT_LOCK_REGS);
+	uintptr_t base_decprot = etzpc_dev.base + offset;
+
+	assert(valid_decprot_id(decprot_id));
+
+	mmio_write_32(base_decprot + ETZPC_DECPROT_LOCK0, shift);
+}
+
+/*
+ * etzpc_configure_tzma : Configure the target TZMA read only size
+ * tzma_id : ID of the memory
+ * tzma_value : read-only size
+ */
+void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value)
+{
+	assert(valid_tzma_id(tzma_id));
+
+	mmio_write_32(etzpc_dev.base + ETZPC_TZMA0_SIZE +
+		      (sizeof(uint32_t) * tzma_id), tzma_value);
+}
+
+/*
+ * etzpc_get_tzma : Get the target TZMA read only size
+ * tzma_id : TZMA ID
+ * return : Size of read only size
+ */
+uint16_t etzpc_get_tzma(uint32_t tzma_id)
+{
+	assert(valid_tzma_id(tzma_id));
+
+	return (uint16_t)mmio_read_32(etzpc_dev.base + ETZPC_TZMA0_SIZE +
+				      (sizeof(uint32_t) * tzma_id));
+}
+
+/*
+ * etzpc_lock_tzma : Lock the target TZMA
+ * tzma_id : TZMA ID
+ */
+void etzpc_lock_tzma(uint32_t tzma_id)
+{
+	assert(valid_tzma_id(tzma_id));
+
+	mmio_setbits_32(etzpc_dev.base + ETZPC_TZMA0_SIZE +
+			(sizeof(uint32_t) * tzma_id), ETZPC_TZMA0_SIZE_LOCK);
+}
+
+/*
+ * etzpc_get_lock_tzma : Return the lock status of the target TZMA
+ * tzma_id : TZMA ID
+ * return : True if TZMA is locked, false otherwise
+ */
+bool etzpc_get_lock_tzma(uint32_t tzma_id)
+{
+	uint32_t tzma_size;
+
+	assert(valid_tzma_id(tzma_id));
+
+	tzma_size = mmio_read_32(etzpc_dev.base + ETZPC_TZMA0_SIZE +
+				 (sizeof(uint32_t) * tzma_id));
+
+	return (tzma_size & ETZPC_TZMA0_SIZE_LOCK) != 0;
+}
+
+/*
+ * etzpc_get_num_per_sec : Return the DECPROT ID limit value
+ */
+uint8_t etzpc_get_num_per_sec(void)
+{
+	return etzpc_dev.num_per_sec;
+}
+
+/*
+ * etzpc_get_revision : Return the ETZPC IP revision
+ */
+uint8_t etzpc_get_revision(void)
+{
+	return etzpc_dev.revision;
+}
+
+/*
+ * etzpc_get_base_address : Return the ETZPC IP base address
+ */
+uintptr_t etzpc_get_base_address(void)
+{
+	return etzpc_dev.base;
+}
+
+/*
+ * etzpc_init : Initialize the ETZPC driver
+ * Return 0 on success and a negative errno on failure
+ */
+int etzpc_init(void)
+{
+	uint32_t hwcfg;
+	int node;
+	struct dt_node_info etzpc_info;
+
+	node = dt_get_node(&etzpc_info, -1, ETZPC_COMPAT);
+	if (node < 0) {
+		return -EIO;
+	}
+
+	/* Check ETZPC is secure only */
+	if (etzpc_info.status != DT_SECURE) {
+		return -EACCES;
+	}
+
+	etzpc_dev.base = etzpc_info.base;
+
+	hwcfg = mmio_read_32(etzpc_dev.base + ETZPC_HWCFGR);
+
+	etzpc_dev.num_tzma = (uint8_t)(hwcfg >> ETZPC_HWCFGR_NUM_TZMA_SHIFT);
+	etzpc_dev.num_per_sec = (uint8_t)(hwcfg >>
+					  ETZPC_HWCFGR_NUM_PER_SEC_SHIFT);
+	etzpc_dev.num_ahb_sec = (uint8_t)(hwcfg >>
+					  ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT);
+	etzpc_dev.chunck_size = (uint8_t)(hwcfg >>
+					  ETZPC_HWCFGR_CHUNCKS1N4_SHIFT);
+
+	etzpc_dev.revision = mmio_read_8(etzpc_dev.base + ETZPC_VERR);
+
+	VERBOSE("ETZPC version 0x%x", etzpc_dev.revision);
+
+	return 0;
+}
diff --git a/drivers/st/fmc/stm32_fmc2_nand.c b/drivers/st/fmc/stm32_fmc2_nand.c
index d2d7e06..dbbeee4 100644
--- a/drivers/st/fmc/stm32_fmc2_nand.c
+++ b/drivers/st/fmc/stm32_fmc2_nand.c
@@ -22,6 +22,9 @@
 #include <lib/mmio.h>
 #include <lib/utils_def.h>
 
+/* Timeout for device interface reset */
+#define TIMEOUT_US_1_MS			1000U
+
 /* FMC2 Compatibility */
 #define DT_FMC2_COMPAT			"st,stm32mp15-fmc2"
 #define MAX_CS				2U
@@ -793,6 +796,7 @@
 	void *fdt = NULL;
 	const fdt32_t *cuint;
 	struct dt_node_info info;
+	int ret;
 
 	if (fdt_get_address(&fdt) == 0) {
 		return -FDT_ERR_NOTFOUND;
@@ -861,8 +865,14 @@
 	stm32mp_clk_enable(stm32_fmc2.clock_id);
 
 	/* Reset IP */
-	stm32mp_reset_assert(stm32_fmc2.reset_id);
-	stm32mp_reset_deassert(stm32_fmc2.reset_id);
+	ret = stm32mp_reset_assert(stm32_fmc2.reset_id, TIMEOUT_US_1_MS);
+	if (ret != 0) {
+		panic();
+	}
+	ret = stm32mp_reset_deassert(stm32_fmc2.reset_id, TIMEOUT_US_1_MS);
+	if (ret != 0) {
+		panic();
+	}
 
 	/* Setup default IP registers */
 	stm32_fmc2_ctrl_init();
diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c
index a13c341..bb77371 100644
--- a/drivers/st/gpio/stm32_gpio.c
+++ b/drivers/st/gpio/stm32_gpio.c
@@ -254,6 +254,15 @@
 		mmio_read_32(base + GPIO_AFRH_OFFSET));
 
 	stm32mp_clk_disable(clock);
+
+	if (status == DT_SECURE) {
+		stm32mp_register_secure_gpio(bank, pin);
+		set_gpio_secure_cfg(bank, pin, true);
+
+	} else {
+		stm32mp_register_non_secure_gpio(bank, pin);
+		set_gpio_secure_cfg(bank, pin, false);
+	}
 }
 
 void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure)
diff --git a/drivers/st/iwdg/stm32_iwdg.c b/drivers/st/iwdg/stm32_iwdg.c
index ea6fbb2..c052b4d 100644
--- a/drivers/st/iwdg/stm32_iwdg.c
+++ b/drivers/st/iwdg/stm32_iwdg.c
@@ -137,6 +137,12 @@
 			((dt_info.status & DT_NON_SECURE) != 0) ?
 			"non-" : "");
 
+		if ((dt_info.status & DT_NON_SECURE) != 0) {
+			stm32mp_register_non_secure_periph_iomem(iwdg->base);
+		} else {
+			stm32mp_register_secure_periph_iomem(iwdg->base);
+		}
+
 #if defined(IMAGE_BL2)
 		if (stm32_iwdg_shadow_update(idx, iwdg->flags) != BSEC_OK) {
 			return -1;
diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c
index 24e6efe..63fbb07 100644
--- a/drivers/st/mmc/stm32_sdmmc2.c
+++ b/drivers/st/mmc/stm32_sdmmc2.c
@@ -113,6 +113,7 @@
 					 SDMMC_STAR_IDMATE   | \
 					 SDMMC_STAR_IDMABTC)
 
+#define TIMEOUT_US_1_MS			1000U
 #define TIMEOUT_US_10_MS		10000U
 #define TIMEOUT_US_1_S			1000000U
 
@@ -711,6 +712,8 @@
 
 int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params)
 {
+	int rc;
+
 	assert((params != NULL) &&
 	       ((params->reg_base & MMC_BLOCK_MASK) == 0U) &&
 	       ((params->bus_width == MMC_BUS_WIDTH_1) ||
@@ -726,9 +729,15 @@
 
 	stm32mp_clk_enable(sdmmc2_params.clock_id);
 
-	stm32mp_reset_assert(sdmmc2_params.reset_id);
+	rc = stm32mp_reset_assert(sdmmc2_params.reset_id, TIMEOUT_US_1_MS);
+	if (rc != 0) {
+		panic();
+	}
 	udelay(2);
-	stm32mp_reset_deassert(sdmmc2_params.reset_id);
+	rc = stm32mp_reset_deassert(sdmmc2_params.reset_id, TIMEOUT_US_1_MS);
+	if (rc != 0) {
+		panic();
+	}
 	mdelay(1);
 
 	sdmmc2_params.clk_rate = stm32mp_clk_get_rate(sdmmc2_params.clock_id);
diff --git a/drivers/st/pmic/stm32mp_pmic.c b/drivers/st/pmic/stm32mp_pmic.c
index 9e9dddc..b2bb482 100644
--- a/drivers/st/pmic/stm32mp_pmic.c
+++ b/drivers/st/pmic/stm32mp_pmic.c
@@ -54,6 +54,15 @@
 	return fdt_get_status(node);
 }
 
+static bool dt_pmic_is_secure(void)
+{
+	int status = dt_pmic_status();
+
+	return (status >= 0) &&
+	       (status == DT_SECURE) &&
+	       (i2c_handle.dt_status == DT_SECURE);
+}
+
 /*
  * Get PMIC and its I2C bus configuration from the device tree.
  * Return 0 on success, negative on error, 1 if no PMIC node is found.
@@ -223,6 +232,19 @@
 	return true;
 }
 
+static void register_pmic_shared_peripherals(void)
+{
+	uintptr_t i2c_base = i2c_handle.i2c_base_addr;
+
+	if (dt_pmic_is_secure()) {
+		stm32mp_register_secure_periph_iomem(i2c_base);
+	} else {
+		if (i2c_base != 0U) {
+			stm32mp_register_non_secure_periph_iomem(i2c_base);
+		}
+	}
+}
+
 void initialize_pmic(void)
 {
 	unsigned long pmic_version;
@@ -232,6 +254,8 @@
 		return;
 	}
 
+	register_pmic_shared_peripherals();
+
 	if (stpmic1_get_version(&pmic_version) != 0) {
 		ERROR("Failed to access PMIC\n");
 		panic();
diff --git a/drivers/st/reset/stm32mp1_reset.c b/drivers/st/reset/stm32mp1_reset.c
index fd3f93e..98c8dcf 100644
--- a/drivers/st/reset/stm32mp1_reset.c
+++ b/drivers/st/reset/stm32mp1_reset.c
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <errno.h>
 #include <limits.h>
 
 #include <platform_def.h>
@@ -15,8 +16,6 @@
 #include <lib/mmio.h>
 #include <lib/utils_def.h>
 
-#define RESET_TIMEOUT_US_1MS	U(1000)
-
 static uint32_t id2reg_offset(unsigned int reset_id)
 {
 	return ((reset_id & GENMASK(31, 5)) >> 5) * sizeof(uint32_t);
@@ -27,36 +26,44 @@
 	return (uint8_t)(reset_id & GENMASK(4, 0));
 }
 
-void stm32mp_reset_assert(uint32_t id)
+int stm32mp_reset_assert(uint32_t id, unsigned int to_us)
 {
 	uint32_t offset = id2reg_offset(id);
 	uint32_t bitmsk = BIT(id2reg_bit_pos(id));
-	uint64_t timeout_ref;
 	uintptr_t rcc_base = stm32mp_rcc_base();
 
 	mmio_write_32(rcc_base + offset, bitmsk);
 
-	timeout_ref = timeout_init_us(RESET_TIMEOUT_US_1MS);
-	while ((mmio_read_32(rcc_base + offset) & bitmsk) == 0U) {
-		if (timeout_elapsed(timeout_ref)) {
-			panic();
+	if (to_us != 0U) {
+		uint64_t timeout_ref = timeout_init_us(to_us);
+
+		while ((mmio_read_32(rcc_base + offset) & bitmsk) == 0U) {
+			if (timeout_elapsed(timeout_ref)) {
+				return -ETIMEDOUT;
+			}
 		}
 	}
+
+	return 0;
 }
 
-void stm32mp_reset_deassert(uint32_t id)
+int stm32mp_reset_deassert(uint32_t id, unsigned int to_us)
 {
 	uint32_t offset = id2reg_offset(id) + RCC_RSTCLRR_OFFSET;
 	uint32_t bitmsk = BIT(id2reg_bit_pos(id));
-	uint64_t timeout_ref;
 	uintptr_t rcc_base = stm32mp_rcc_base();
 
 	mmio_write_32(rcc_base + offset, bitmsk);
 
-	timeout_ref = timeout_init_us(RESET_TIMEOUT_US_1MS);
-	while ((mmio_read_32(rcc_base + offset) & bitmsk) != 0U) {
-		if (timeout_elapsed(timeout_ref)) {
-			panic();
+	if (to_us != 0U) {
+		uint64_t timeout_ref = timeout_init_us(to_us);
+
+		while ((mmio_read_32(rcc_base + offset) & bitmsk) != 0U) {
+			if (timeout_elapsed(timeout_ref)) {
+				return -ETIMEDOUT;
+			}
 		}
 	}
+
+	return 0;
 }
diff --git a/drivers/st/scmi-msg/base.c b/drivers/st/scmi-msg/base.c
new file mode 100644
index 0000000..e44bc52
--- /dev/null
+++ b/drivers/st/scmi-msg/base.c
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Linaro Limited
+ */
+#include <assert.h>
+#include <string.h>
+
+#include <drivers/st/scmi-msg.h>
+#include <drivers/st/scmi.h>
+#include <lib/utils.h>
+#include <lib/utils_def.h>
+
+#include "common.h"
+
+static bool message_id_is_supported(unsigned int message_id);
+
+static void report_version(struct scmi_msg *msg)
+{
+	struct scmi_protocol_version_p2a return_values = {
+		.status = SCMI_SUCCESS,
+		.version = SCMI_PROTOCOL_VERSION_BASE,
+	};
+
+	if (msg->in_size != 0U) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void report_attributes(struct scmi_msg *msg)
+{
+	size_t protocol_count = plat_scmi_protocol_count();
+	struct scmi_protocol_attributes_p2a return_values = {
+		.status = SCMI_SUCCESS,
+		/* Null agent count since agent discovery is not supported */
+		.attributes = SCMI_BASE_PROTOCOL_ATTRIBUTES(protocol_count, 0U),
+	};
+
+	if (msg->in_size != 0U) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void report_message_attributes(struct scmi_msg *msg)
+{
+	struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in;
+	struct scmi_protocol_message_attributes_p2a return_values = {
+		.status = SCMI_SUCCESS,
+		/* For this protocol, attributes shall be zero */
+		.attributes = 0U,
+	};
+
+	if (msg->in_size != sizeof(*in_args)) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	if (!message_id_is_supported(in_args->message_id)) {
+		scmi_status_response(msg, SCMI_NOT_FOUND);
+		return;
+	}
+
+	scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void discover_vendor(struct scmi_msg *msg)
+{
+	const char *name = plat_scmi_vendor_name();
+	struct scmi_base_discover_vendor_p2a return_values = {
+		.status = SCMI_SUCCESS,
+	};
+
+	if (msg->in_size != 0U) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	COPY_NAME_IDENTIFIER(return_values.vendor_identifier, name);
+
+	scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void discover_sub_vendor(struct scmi_msg *msg)
+{
+	const char *name = plat_scmi_sub_vendor_name();
+	struct scmi_base_discover_sub_vendor_p2a return_values = {
+		.status = SCMI_SUCCESS,
+	};
+
+	if (msg->in_size != 0U) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	COPY_NAME_IDENTIFIER(return_values.sub_vendor_identifier, name);
+
+	scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void discover_implementation_version(struct scmi_msg *msg)
+{
+	struct scmi_protocol_version_p2a return_values = {
+		.status = SCMI_SUCCESS,
+		.version = SCMI_IMPL_VERSION,
+	};
+
+	if (msg->in_size != 0U) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static unsigned int count_protocols_in_list(const uint8_t *protocol_list)
+{
+	unsigned int count = 0U;
+
+	if (protocol_list != NULL) {
+		while (protocol_list[count] != 0U) {
+			count++;
+		}
+	}
+
+	return count;
+}
+
+#define MAX_PROTOCOL_IN_LIST		8U
+
+static void discover_list_protocols(struct scmi_msg *msg)
+{
+	const struct scmi_base_discover_list_protocols_a2p *a2p = NULL;
+	struct scmi_base_discover_list_protocols_p2a p2a = {
+		.status = SCMI_SUCCESS,
+	};
+	uint8_t outargs[sizeof(p2a) + MAX_PROTOCOL_IN_LIST] = { 0U };
+	const uint8_t *list = NULL;
+	unsigned int count = 0U;
+
+	if (msg->in_size != sizeof(*a2p)) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	assert(msg->out_size > sizeof(outargs));
+
+	a2p = (void *)msg->in;
+
+	list = plat_scmi_protocol_list(msg->agent_id);
+	count = count_protocols_in_list(list);
+	if (count > a2p->skip) {
+		count = MIN(count - a2p->skip, MAX_PROTOCOL_IN_LIST);
+	} else {
+		count = 0U;
+	}
+
+	p2a.num_protocols = count;
+
+	memcpy(outargs, &p2a, sizeof(p2a));
+	memcpy(outargs + sizeof(p2a), list + a2p->skip, count);
+
+	scmi_write_response(msg, outargs, sizeof(outargs));
+}
+
+static const scmi_msg_handler_t scmi_base_handler_table[] = {
+	[SCMI_PROTOCOL_VERSION] = report_version,
+	[SCMI_PROTOCOL_ATTRIBUTES] = report_attributes,
+	[SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes,
+	[SCMI_BASE_DISCOVER_VENDOR] = discover_vendor,
+	[SCMI_BASE_DISCOVER_SUB_VENDOR] = discover_sub_vendor,
+	[SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION] =
+					discover_implementation_version,
+	[SCMI_BASE_DISCOVER_LIST_PROTOCOLS] = discover_list_protocols,
+};
+
+static bool message_id_is_supported(unsigned int message_id)
+{
+	return (message_id < ARRAY_SIZE(scmi_base_handler_table)) &&
+	       (scmi_base_handler_table[message_id] != NULL);
+}
+
+scmi_msg_handler_t scmi_msg_get_base_handler(struct scmi_msg *msg)
+{
+	unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id);
+
+	if (message_id >= ARRAY_SIZE(scmi_base_handler_table)) {
+		VERBOSE("Base handle not found %u\n", msg->message_id);
+		return NULL;
+	}
+
+	return scmi_base_handler_table[message_id];
+}
diff --git a/drivers/st/scmi-msg/base.h b/drivers/st/scmi-msg/base.h
new file mode 100644
index 0000000..c4a9c64
--- /dev/null
+++ b/drivers/st/scmi-msg/base.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Linaro Limited
+ */
+
+#ifndef SCMI_MSG_BASE_H
+#define SCMI_MSG_BASE_H
+
+#include <stdint.h>
+
+#define SCMI_PROTOCOL_VERSION_BASE	0x20000U
+
+#define SCMI_DEFAULT_STRING_LENGTH	16U
+
+enum scmi_base_message_id {
+	SCMI_BASE_DISCOVER_VENDOR			= 0x003,
+	SCMI_BASE_DISCOVER_SUB_VENDOR			= 0x004,
+	SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION	= 0x005,
+	SCMI_BASE_DISCOVER_LIST_PROTOCOLS		= 0x006,
+	SCMI_BASE_DISCOVER_AGENT			= 0x007,
+	SCMI_BASE_NOTIFY_ERRORS				= 0x008,
+};
+
+/*
+ * PROTOCOL_ATTRIBUTES
+ */
+
+#define SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_POS	0
+#define SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_POS		8
+
+#define SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_MASK	0xFFU
+#define SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_MASK	0xFF00U
+
+#define SCMI_BASE_PROTOCOL_ATTRIBUTES(NUM_PROTOCOLS, NUM_AGENTS) \
+	((((NUM_PROTOCOLS) << SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_POS) & \
+	  SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_MASK) | \
+	(((NUM_AGENTS) << SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_POS) & \
+	 SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_MASK))
+
+/*
+ * BASE_DISCOVER_VENDOR
+ */
+struct scmi_base_discover_vendor_p2a {
+	int32_t status;
+	char vendor_identifier[SCMI_DEFAULT_STRING_LENGTH];
+};
+
+/*
+ * BASE_DISCOVER_SUB_VENDOR
+ */
+struct scmi_base_discover_sub_vendor_p2a {
+	int32_t status;
+	char sub_vendor_identifier[SCMI_DEFAULT_STRING_LENGTH];
+};
+
+/*
+ * BASE_DISCOVER_IMPLEMENTATION_VERSION
+ * No special structure right now, see protocol_version.
+ */
+
+/*
+ * BASE_DISCOVER_LIST_PROTOCOLS
+ */
+struct scmi_base_discover_list_protocols_a2p {
+	uint32_t skip;
+};
+
+struct scmi_base_discover_list_protocols_p2a {
+	int32_t status;
+	uint32_t num_protocols;
+	uint32_t protocols[];
+};
+
+#endif /* SCMI_MSG_BASE_H */
diff --git a/drivers/st/scmi-msg/clock.c b/drivers/st/scmi-msg/clock.c
new file mode 100644
index 0000000..319557c
--- /dev/null
+++ b/drivers/st/scmi-msg/clock.c
@@ -0,0 +1,381 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Linaro Limited
+ */
+#include <cdefs.h>
+#include <string.h>
+
+#include <drivers/st/scmi-msg.h>
+#include <drivers/st/scmi.h>
+#include <lib/utils_def.h>
+
+#include "common.h"
+
+#pragma weak plat_scmi_clock_count
+#pragma weak plat_scmi_clock_get_name
+#pragma weak plat_scmi_clock_rates_array
+#pragma weak plat_scmi_clock_rates_by_step
+#pragma weak plat_scmi_clock_get_rate
+#pragma weak plat_scmi_clock_set_rate
+#pragma weak plat_scmi_clock_get_state
+#pragma weak plat_scmi_clock_set_state
+
+static bool message_id_is_supported(unsigned int message_id);
+
+size_t plat_scmi_clock_count(unsigned int agent_id __unused)
+{
+	return 0U;
+}
+
+const char *plat_scmi_clock_get_name(unsigned int agent_id __unused,
+				     unsigned int scmi_id __unused)
+{
+	return NULL;
+}
+
+int32_t plat_scmi_clock_rates_array(unsigned int agent_id __unused,
+				    unsigned int scmi_id __unused,
+				    unsigned long *rates __unused,
+				    size_t *nb_elts __unused)
+{
+	return SCMI_NOT_SUPPORTED;
+}
+
+int32_t plat_scmi_clock_rates_by_step(unsigned int agent_id __unused,
+				      unsigned int scmi_id __unused,
+				      unsigned long *steps __unused)
+{
+	return SCMI_NOT_SUPPORTED;
+}
+
+unsigned long plat_scmi_clock_get_rate(unsigned int agent_id __unused,
+				       unsigned int scmi_id __unused)
+{
+	return 0U;
+}
+
+int32_t plat_scmi_clock_set_rate(unsigned int agent_id __unused,
+				 unsigned int scmi_id __unused,
+				 unsigned long rate __unused)
+{
+	return SCMI_NOT_SUPPORTED;
+}
+
+int32_t plat_scmi_clock_get_state(unsigned int agent_id __unused,
+				  unsigned int scmi_id __unused)
+{
+	return SCMI_NOT_SUPPORTED;
+}
+
+int32_t plat_scmi_clock_set_state(unsigned int agent_id __unused,
+				  unsigned int scmi_id __unused,
+				  bool enable_not_disable __unused)
+{
+	return SCMI_NOT_SUPPORTED;
+}
+
+static void report_version(struct scmi_msg *msg)
+{
+	struct scmi_protocol_version_p2a return_values = {
+		.status = SCMI_SUCCESS,
+		.version = SCMI_PROTOCOL_VERSION_CLOCK,
+	};
+
+	if (msg->in_size != 0) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void report_attributes(struct scmi_msg *msg)
+{
+	size_t agent_count = plat_scmi_clock_count(msg->agent_id);
+	struct scmi_protocol_attributes_p2a return_values = {
+		.status = SCMI_SUCCESS,
+		.attributes = SCMI_CLOCK_PROTOCOL_ATTRIBUTES(1U, agent_count),
+	};
+
+	if (msg->in_size != 0) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void report_message_attributes(struct scmi_msg *msg)
+{
+	struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in;
+	struct scmi_protocol_message_attributes_p2a return_values = {
+		.status = SCMI_SUCCESS,
+		/* For this protocol, attributes shall be zero */
+		.attributes = 0U,
+	};
+
+	if (msg->in_size != sizeof(*in_args)) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	if (!message_id_is_supported(in_args->message_id)) {
+		scmi_status_response(msg, SCMI_NOT_FOUND);
+		return;
+	}
+
+	scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void scmi_clock_attributes(struct scmi_msg *msg)
+{
+	const struct scmi_clock_attributes_a2p *in_args = (void *)msg->in;
+	struct scmi_clock_attributes_p2a return_values = {
+		.status = SCMI_SUCCESS,
+	};
+	const char *name = NULL;
+	unsigned int clock_id = 0U;
+
+	if (msg->in_size != sizeof(*in_args)) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
+
+	if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
+		scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
+		return;
+	}
+
+
+	name = plat_scmi_clock_get_name(msg->agent_id, clock_id);
+	if (name == NULL) {
+		scmi_status_response(msg, SCMI_NOT_FOUND);
+		return;
+	}
+
+	COPY_NAME_IDENTIFIER(return_values.clock_name, name);
+
+	return_values.attributes = plat_scmi_clock_get_state(msg->agent_id,
+							     clock_id);
+
+	scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void scmi_clock_rate_get(struct scmi_msg *msg)
+{
+	const struct scmi_clock_rate_get_a2p *in_args = (void *)msg->in;
+	unsigned long rate = 0U;
+	struct scmi_clock_rate_get_p2a return_values = {
+		.status = SCMI_SUCCESS,
+	};
+	unsigned int clock_id = 0U;
+
+	if (msg->in_size != sizeof(*in_args)) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
+
+	if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
+		scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
+		return;
+	}
+
+	rate = plat_scmi_clock_get_rate(msg->agent_id, clock_id);
+
+	return_values.rate[0] = (uint32_t)rate;
+	return_values.rate[1] = (uint32_t)((uint64_t)rate >> 32);
+
+	scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void scmi_clock_rate_set(struct scmi_msg *msg)
+{
+	const struct scmi_clock_rate_set_a2p *in_args = (void *)msg->in;
+	unsigned long rate = 0U;
+	int32_t status = 0;
+	unsigned int clock_id = 0U;
+
+	if (msg->in_size != sizeof(*in_args)) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
+
+	if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
+		scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
+		return;
+	}
+
+	rate = (unsigned long)(((uint64_t)in_args->rate[1] << 32) |
+			       in_args->rate[0]);
+
+	status = plat_scmi_clock_set_rate(msg->agent_id, clock_id, rate);
+
+	scmi_status_response(msg, status);
+}
+
+static void scmi_clock_config_set(struct scmi_msg *msg)
+{
+	const struct scmi_clock_config_set_a2p *in_args = (void *)msg->in;
+	int32_t status = SCMI_GENERIC_ERROR;
+	bool enable = false;
+	unsigned int clock_id = 0U;
+
+	if (msg->in_size != sizeof(*in_args)) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
+
+	if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
+		scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
+		return;
+	}
+
+	enable = in_args->attributes & SCMI_CLOCK_CONFIG_SET_ENABLE_MASK;
+
+	status = plat_scmi_clock_set_state(msg->agent_id, clock_id, enable);
+
+	scmi_status_response(msg, status);
+}
+
+#define RATES_ARRAY_SIZE_MAX	(SCMI_PLAYLOAD_MAX - \
+				 sizeof(struct scmi_clock_describe_rates_p2a))
+
+#define SCMI_RATES_BY_ARRAY(_nb_rates, _rem_rates) \
+	SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS((_nb_rates), \
+						SCMI_CLOCK_RATE_FORMAT_LIST, \
+						(_rem_rates))
+#define SCMI_RATES_BY_STEP \
+	SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS(3U, \
+						SCMI_CLOCK_RATE_FORMAT_RANGE, \
+						0U)
+
+#define RATE_DESC_SIZE		sizeof(struct scmi_clock_rate)
+
+static void write_rate_desc_array_in_buffer(char *dest, unsigned long *rates,
+					    size_t nb_elt)
+{
+	uint32_t *out = (uint32_t *)(uintptr_t)dest;
+	size_t n;
+
+	ASSERT_SYM_PTR_ALIGN(out);
+
+	for (n = 0U; n < nb_elt; n++) {
+		out[2 * n] = (uint32_t)rates[n];
+		out[2 * n + 1] = (uint32_t)((uint64_t)rates[n] >> 32);
+	}
+}
+
+static void scmi_clock_describe_rates(struct scmi_msg *msg)
+{
+	const struct scmi_clock_describe_rates_a2p *in_args = (void *)msg->in;
+	struct scmi_clock_describe_rates_p2a p2a = {
+		.status = SCMI_SUCCESS,
+	};
+	size_t nb_rates;
+	int32_t status;
+	unsigned int clock_id;
+
+	if (msg->in_size != sizeof(*in_args)) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id);
+
+	if (clock_id >= plat_scmi_clock_count(msg->agent_id)) {
+		scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
+		return;
+	}
+
+	/* Platform may support array rate description */
+	status = plat_scmi_clock_rates_array(msg->agent_id, clock_id, NULL,
+					     &nb_rates);
+	if (status == SCMI_SUCCESS) {
+		/* Currently 12 cells mex, so it's affordable for the stack */
+		unsigned long plat_rates[RATES_ARRAY_SIZE_MAX / RATE_DESC_SIZE];
+		size_t max_nb = RATES_ARRAY_SIZE_MAX / RATE_DESC_SIZE;
+		size_t ret_nb = MIN(nb_rates - in_args->rate_index, max_nb);
+		size_t rem_nb = nb_rates - in_args->rate_index - ret_nb;
+
+		status =  plat_scmi_clock_rates_array(msg->agent_id, clock_id,
+						      plat_rates, &ret_nb);
+		if (status == SCMI_SUCCESS) {
+			write_rate_desc_array_in_buffer(msg->out + sizeof(p2a),
+							plat_rates, ret_nb);
+
+			p2a.num_rates_flags = SCMI_RATES_BY_ARRAY(ret_nb,
+								  rem_nb);
+			p2a.status = SCMI_SUCCESS;
+
+			memcpy(msg->out, &p2a, sizeof(p2a));
+			msg->out_size_out = sizeof(p2a) +
+					    ret_nb * RATE_DESC_SIZE;
+		}
+	} else if (status == SCMI_NOT_SUPPORTED) {
+		unsigned long triplet[3] = { 0U, 0U, 0U };
+
+		/* Platform may support min§max/step triplet description */
+		status =  plat_scmi_clock_rates_by_step(msg->agent_id, clock_id,
+							triplet);
+		if (status == SCMI_SUCCESS) {
+			write_rate_desc_array_in_buffer(msg->out + sizeof(p2a),
+							triplet, 3U);
+
+			p2a.num_rates_flags = SCMI_RATES_BY_STEP;
+			p2a.status = SCMI_SUCCESS;
+
+			memcpy(msg->out, &p2a, sizeof(p2a));
+			msg->out_size_out = sizeof(p2a) + (3U * RATE_DESC_SIZE);
+		}
+	} else {
+		/* Fallthrough generic exit sequence below with error status */
+	}
+
+	if (status != SCMI_SUCCESS) {
+		scmi_status_response(msg, status);
+	} else {
+		/*
+		 * Message payload is already writen to msg->out, and
+		 * msg->out_size_out updated.
+		 */
+	}
+}
+
+static const scmi_msg_handler_t scmi_clock_handler_table[] = {
+	[SCMI_PROTOCOL_VERSION] = report_version,
+	[SCMI_PROTOCOL_ATTRIBUTES] = report_attributes,
+	[SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes,
+	[SCMI_CLOCK_ATTRIBUTES] = scmi_clock_attributes,
+	[SCMI_CLOCK_DESCRIBE_RATES] = scmi_clock_describe_rates,
+	[SCMI_CLOCK_RATE_SET] = scmi_clock_rate_set,
+	[SCMI_CLOCK_RATE_GET] = scmi_clock_rate_get,
+	[SCMI_CLOCK_CONFIG_SET] = scmi_clock_config_set,
+};
+
+static bool message_id_is_supported(size_t message_id)
+{
+	return (message_id < ARRAY_SIZE(scmi_clock_handler_table)) &&
+	       (scmi_clock_handler_table[message_id] != NULL);
+}
+
+scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg)
+{
+	const size_t array_size = ARRAY_SIZE(scmi_clock_handler_table);
+	unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id);
+
+	if (message_id >= array_size) {
+		VERBOSE("Clock handle not found %u", msg->message_id);
+		return NULL;
+	}
+
+	return scmi_clock_handler_table[message_id];
+}
diff --git a/drivers/st/scmi-msg/clock.h b/drivers/st/scmi-msg/clock.h
new file mode 100644
index 0000000..a637934
--- /dev/null
+++ b/drivers/st/scmi-msg/clock.h
@@ -0,0 +1,150 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019, Linaro Limited
+ */
+
+#ifndef SCMI_MSG_CLOCK_H
+#define SCMI_MSG_CLOCK_H
+
+#include <stdint.h>
+
+#include <lib/utils_def.h>
+
+#define SCMI_PROTOCOL_VERSION_CLOCK	0x20000U
+
+/*
+ * Identifiers of the SCMI Clock Management Protocol commands
+ */
+enum scmi_clock_command_id {
+	SCMI_CLOCK_ATTRIBUTES = 0x003,
+	SCMI_CLOCK_DESCRIBE_RATES = 0x004,
+	SCMI_CLOCK_RATE_SET = 0x005,
+	SCMI_CLOCK_RATE_GET = 0x006,
+	SCMI_CLOCK_CONFIG_SET = 0x007,
+};
+
+/* Protocol attributes */
+#define SCMI_CLOCK_CLOCK_COUNT_MASK			GENMASK(15, 0)
+#define SCMI_CLOCK_MAX_PENDING_TRANSITIONS_MASK		GENMASK(23, 16)
+
+#define SCMI_CLOCK_PROTOCOL_ATTRIBUTES(_max_pending, _clk_count) \
+	((((_max_pending) << 16) & SCMI_CLOCK_MAX_PENDING_TRANSITIONS_MASK) | \
+	 (((_clk_count) & SCMI_CLOCK_CLOCK_COUNT_MASK)))
+
+struct scmi_clock_attributes_a2p {
+	uint32_t clock_id;
+};
+
+#define SCMI_CLOCK_NAME_LENGTH_MAX	16U
+
+struct scmi_clock_attributes_p2a {
+	int32_t status;
+	uint32_t attributes;
+	char clock_name[SCMI_CLOCK_NAME_LENGTH_MAX];
+};
+
+/*
+ * Clock Rate Get
+ */
+
+struct scmi_clock_rate_get_a2p {
+	uint32_t clock_id;
+};
+
+struct scmi_clock_rate_get_p2a {
+	int32_t status;
+	uint32_t rate[2];
+};
+
+/*
+ * Clock Rate Set
+ */
+
+/* If set, set the new clock rate asynchronously */
+#define SCMI_CLOCK_RATE_SET_ASYNC_POS			0
+/* If set, do not send a delayed asynchronous response */
+#define SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_POS	1
+/* Round up, if set, otherwise round down */
+#define SCMI_CLOCK_RATE_SET_ROUND_UP_POS		2
+/* If set, the platform chooses the appropriate rounding mode */
+#define SCMI_CLOCK_RATE_SET_ROUND_AUTO_POS		3
+
+#define SCMI_CLOCK_RATE_SET_ASYNC_MASK \
+		BIT(SCMI_CLOCK_RATE_SET_ASYNC_POS)
+#define SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_MASK \
+		BIT(SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_POS)
+#define SCMI_CLOCK_RATE_SET_ROUND_UP_MASK \
+		BIT(SCMI_CLOCK_RATE_SET_ROUND_UP_POS)
+#define SCMI_CLOCK_RATE_SET_ROUND_AUTO_MASK \
+		BIT(SCMI_CLOCK_RATE_SET_ROUND_AUTO_POS)
+
+struct scmi_clock_rate_set_a2p {
+	uint32_t flags;
+	uint32_t clock_id;
+	uint32_t rate[2];
+};
+
+struct scmi_clock_rate_set_p2a {
+	int32_t status;
+};
+
+/*
+ * Clock Config Set
+ */
+
+#define SCMI_CLOCK_CONFIG_SET_ENABLE_POS	0
+
+#define SCMI_CLOCK_CONFIG_SET_ENABLE_MASK \
+	BIT(SCMI_CLOCK_CONFIG_SET_ENABLE_POS)
+
+struct scmi_clock_config_set_a2p {
+	uint32_t clock_id;
+	uint32_t attributes;
+};
+
+struct scmi_clock_config_set_p2a {
+	int32_t status;
+};
+
+/*
+ * Clock Describe Rates
+ */
+
+#define SCMI_CLOCK_RATE_FORMAT_RANGE			1U
+#define SCMI_CLOCK_RATE_FORMAT_LIST			0U
+
+#define SCMI_CLOCK_DESCRIBE_RATES_REMAINING_MASK	GENMASK_32(31, 16)
+#define SCMI_CLOCK_DESCRIBE_RATES_REMAINING_POS		16
+
+#define SCMI_CLOCK_DESCRIBE_RATES_FORMAT_MASK		BIT(12)
+#define SCMI_CLOCK_DESCRIBE_RATES_FORMAT_POS		12
+
+#define SCMI_CLOCK_DESCRIBE_RATES_COUNT_MASK		GENMASK_32(11, 0)
+
+#define SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS(_count, _fmt, _rem_rates) \
+	( \
+		((_count) & SCMI_CLOCK_DESCRIBE_RATES_COUNT_MASK) | \
+		(((_rem_rates) << SCMI_CLOCK_DESCRIBE_RATES_REMAINING_POS) & \
+		 SCMI_CLOCK_DESCRIBE_RATES_REMAINING_MASK) | \
+		(((_fmt) << SCMI_CLOCK_DESCRIBE_RATES_FORMAT_POS) & \
+		 SCMI_CLOCK_DESCRIBE_RATES_FORMAT_MASK) \
+	)
+
+struct scmi_clock_rate {
+	uint32_t low;
+	uint32_t high;
+};
+
+struct scmi_clock_describe_rates_a2p {
+	uint32_t clock_id;
+	uint32_t rate_index;
+};
+
+struct scmi_clock_describe_rates_p2a {
+	int32_t status;
+	uint32_t num_rates_flags;
+	struct scmi_clock_rate rates[];
+};
+
+#endif /* SCMI_MSG_CLOCK_H */
diff --git a/drivers/st/scmi-msg/common.h b/drivers/st/scmi-msg/common.h
new file mode 100644
index 0000000..ef5953b
--- /dev/null
+++ b/drivers/st/scmi-msg/common.h
@@ -0,0 +1,136 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Linaro Limited
+ */
+#ifndef SCMI_MSG_COMMON_H
+#define SCMI_MSG_COMMON_H
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "base.h"
+#include "clock.h"
+#include "reset_domain.h"
+
+#define SCMI_VERSION			0x20000U
+#define SCMI_IMPL_VERSION		0U
+
+#define SCMI_PLAYLOAD_MAX		92U
+
+/*
+ * Copy name identifier in target buffer following the SCMI specification
+ * that state name identifier shall be a null terminated string.
+ */
+#define COPY_NAME_IDENTIFIER(_dst_array, _name)				\
+	do {								\
+		assert(strlen(_name) < sizeof(_dst_array));		\
+		strlcpy((_dst_array), (_name), sizeof(_dst_array));	\
+	} while (0)
+
+/* Common command identifiers shared by all procotols */
+enum scmi_common_message_id {
+	SCMI_PROTOCOL_VERSION = 0x000,
+	SCMI_PROTOCOL_ATTRIBUTES = 0x001,
+	SCMI_PROTOCOL_MESSAGE_ATTRIBUTES = 0x002
+};
+
+/* Common platform-to-agent (p2a) PROTOCOL_VERSION structure */
+struct scmi_protocol_version_p2a {
+	int32_t status;
+	uint32_t version;
+};
+
+/* Generic platform-to-agent (p2a) PROTOCOL_ATTRIBUTES structure */
+struct scmi_protocol_attributes_p2a {
+	int32_t status;
+	uint32_t attributes;
+};
+
+/* Generic agent-to-platform (a2p) PROTOCOL_MESSAGE_ATTRIBUTES structure */
+struct scmi_protocol_message_attributes_a2p {
+	uint32_t message_id;
+};
+
+/* Generic platform-to-agent (p2a) PROTOCOL_MESSAGE_ATTRIBUTES structure */
+struct scmi_protocol_message_attributes_p2a {
+	int32_t status;
+	uint32_t attributes;
+};
+
+/*
+ * struct scmi_msg - SCMI message context
+ *
+ * @agent_id: SCMI agent ID, safely set from secure world
+ * @protocol_id: SCMI protocol ID for the related message, set by caller agent
+ * @message_id: SCMI message ID for the related message, set by caller agent
+ * @in: Address of the incoming message payload copied in secure memory
+ * @in_size: Byte length of the incoming message payload, set by caller agent
+ * @out: Address of of the output message payload message in non-secure memory
+ * @out_size: Byte length of the provisionned output buffer
+ * @out_size_out: Byte length of the output message payload
+ */
+struct scmi_msg {
+	unsigned int agent_id;
+	unsigned int protocol_id;
+	unsigned int message_id;
+	char *in;
+	size_t in_size;
+	char *out;
+	size_t out_size;
+	size_t out_size_out;
+};
+
+/*
+ * Type scmi_msg_handler_t is used by procotol drivers to safely find
+ * the handler function for the incoming message ID.
+ */
+typedef void (*scmi_msg_handler_t)(struct scmi_msg *msg);
+
+/*
+ * scmi_msg_get_base_handler - Return a handler for a base message
+ * @msg - message to process
+ * Return a function handler for the message or NULL
+ */
+scmi_msg_handler_t scmi_msg_get_base_handler(struct scmi_msg *msg);
+
+/*
+ * scmi_msg_get_clock_handler - Return a handler for a clock message
+ * @msg - message to process
+ * Return a function handler for the message or NULL
+ */
+scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg);
+
+/*
+ * scmi_msg_get_rstd_handler - Return a handler for a reset domain message
+ * @msg - message to process
+ * Return a function handler for the message or NULL
+ */
+scmi_msg_handler_t scmi_msg_get_rstd_handler(struct scmi_msg *msg);
+
+/*
+ * Process Read, process and write response for input SCMI message
+ *
+ * @msg: SCMI message context
+ */
+void scmi_process_message(struct scmi_msg *msg);
+
+/*
+ * Write SCMI response payload to output message shared memory
+ *
+ * @msg: SCMI message context
+ * @payload: Output message payload
+ * @size: Byte size of output message payload
+ */
+void scmi_write_response(struct scmi_msg *msg, void *payload, size_t size);
+
+/*
+ * Write status only SCMI response payload to output message shared memory
+ *
+ * @msg: SCMI message context
+ * @status: SCMI status value returned to caller
+ */
+void scmi_status_response(struct scmi_msg *msg, int32_t status);
+#endif /* SCMI_MSG_COMMON_H */
diff --git a/drivers/st/scmi-msg/entry.c b/drivers/st/scmi-msg/entry.c
new file mode 100644
index 0000000..eefcb31
--- /dev/null
+++ b/drivers/st/scmi-msg/entry.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Linaro Limited
+ */
+
+#include <assert.h>
+
+#include <drivers/st/scmi-msg.h>
+#include <drivers/st/scmi.h>
+
+#include "common.h"
+
+void scmi_status_response(struct scmi_msg *msg, int32_t status)
+{
+	assert(msg->out && msg->out_size >= sizeof(int32_t));
+
+	memcpy(msg->out, &status, sizeof(int32_t));
+	msg->out_size_out = sizeof(int32_t);
+}
+
+void scmi_write_response(struct scmi_msg *msg, void *payload, size_t size)
+{
+	/*
+	 * Output payload shall be at least the size of the status
+	 * Output buffer shall be at least be the size of the status
+	 * Output paylaod shall fit in output buffer
+	 */
+	assert(payload && size >= sizeof(int32_t) && size <= msg->out_size &&
+	       msg->out && msg->out_size >= sizeof(int32_t));
+
+	memcpy(msg->out, payload, size);
+	msg->out_size_out = size;
+}
+
+void scmi_process_message(struct scmi_msg *msg)
+{
+	scmi_msg_handler_t handler = NULL;
+
+	switch (msg->protocol_id) {
+	case SCMI_PROTOCOL_ID_BASE:
+		handler = scmi_msg_get_base_handler(msg);
+		break;
+	case SCMI_PROTOCOL_ID_CLOCK:
+		handler = scmi_msg_get_clock_handler(msg);
+		break;
+	case SCMI_PROTOCOL_ID_RESET_DOMAIN:
+		handler = scmi_msg_get_rstd_handler(msg);
+		break;
+	default:
+		break;
+	}
+
+	if (handler) {
+		handler(msg);
+		return;
+	}
+
+	ERROR("Agent %u Protocol 0x%x Message 0x%x: not supported",
+	      msg->agent_id, msg->protocol_id, msg->message_id);
+
+	scmi_status_response(msg, SCMI_NOT_SUPPORTED);
+}
diff --git a/drivers/st/scmi-msg/reset_domain.c b/drivers/st/scmi-msg/reset_domain.c
new file mode 100644
index 0000000..b477302
--- /dev/null
+++ b/drivers/st/scmi-msg/reset_domain.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Linaro Limited
+ */
+#include <cdefs.h>
+#include <string.h>
+
+#include <drivers/st/scmi-msg.h>
+#include <drivers/st/scmi.h>
+#include <lib/utils.h>
+#include <lib/utils_def.h>
+
+#include "common.h"
+
+static bool message_id_is_supported(unsigned int message_id);
+
+#pragma weak plat_scmi_rstd_count
+#pragma weak plat_scmi_rstd_get_name
+#pragma weak plat_scmi_rstd_autonomous
+#pragma weak plat_scmi_rstd_set_state
+
+size_t plat_scmi_rstd_count(unsigned int agent_id __unused)
+{
+	return 0U;
+}
+
+const char *plat_scmi_rstd_get_name(unsigned int agent_id __unused,
+				  unsigned int scmi_id __unused)
+{
+	return NULL;
+}
+
+int32_t plat_scmi_rstd_autonomous(unsigned int agent_id __unused,
+				unsigned int scmi_id __unused,
+				unsigned int state __unused)
+{
+	return SCMI_NOT_SUPPORTED;
+}
+
+int32_t plat_scmi_rstd_set_state(unsigned int agent_id __unused,
+			       unsigned int scmi_id __unused,
+			       bool assert_not_deassert __unused)
+{
+	return SCMI_NOT_SUPPORTED;
+}
+
+static void report_version(struct scmi_msg *msg)
+{
+	struct scmi_protocol_version_p2a return_values = {
+		.status = SCMI_SUCCESS,
+		.version = SCMI_PROTOCOL_VERSION_RESET_DOMAIN,
+	};
+
+	if (msg->in_size != 0U) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void report_attributes(struct scmi_msg *msg)
+{
+	struct scmi_protocol_attributes_p2a return_values = {
+		.status = SCMI_SUCCESS,
+		.attributes = plat_scmi_rstd_count(msg->agent_id),
+	};
+
+	if (msg->in_size != 0U) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void report_message_attributes(struct scmi_msg *msg)
+{
+	struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in;
+	struct scmi_protocol_message_attributes_p2a return_values = {
+		.status = SCMI_SUCCESS,
+		/* For this protocol, attributes shall be zero */
+		.attributes = 0U,
+	};
+
+	if (msg->in_size != sizeof(*in_args)) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	if (!message_id_is_supported(in_args->message_id)) {
+		scmi_status_response(msg, SCMI_NOT_FOUND);
+		return;
+	}
+
+	scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void reset_domain_attributes(struct scmi_msg *msg)
+{
+	struct scmi_reset_domain_attributes_a2p *in_args = (void *)msg->in;
+	struct scmi_reset_domain_attributes_p2a return_values;
+	const char *name = NULL;
+	unsigned int domain_id = 0U;
+
+	if (msg->in_size != sizeof(*in_args)) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	domain_id = SPECULATION_SAFE_VALUE(in_args->domain_id);
+
+	if (domain_id >= plat_scmi_rstd_count(msg->agent_id)) {
+		scmi_status_response(msg, SCMI_INVALID_PARAMETERS);
+		return;
+	}
+
+	name = plat_scmi_rstd_get_name(msg->agent_id, domain_id);
+	if (name == NULL) {
+		scmi_status_response(msg, SCMI_NOT_FOUND);
+		return;
+	}
+
+	zeromem(&return_values, sizeof(return_values));
+	COPY_NAME_IDENTIFIER(return_values.name, name);
+	return_values.status = SCMI_SUCCESS;
+	return_values.flags = 0U; /* Async and Notif are not supported */
+	return_values.latency = SCMI_RESET_DOMAIN_ATTR_UNK_LAT;
+
+	scmi_write_response(msg, &return_values, sizeof(return_values));
+}
+
+static void reset_request(struct scmi_msg *msg)
+{
+	struct scmi_reset_domain_request_a2p *in_args = (void *)msg->in;
+	struct scmi_reset_domain_request_p2a out_args = {
+		.status = SCMI_SUCCESS,
+	};
+	unsigned int domain_id = 0U;
+
+	if (msg->in_size != sizeof(*in_args)) {
+		scmi_status_response(msg, SCMI_PROTOCOL_ERROR);
+		return;
+	}
+
+	domain_id = SPECULATION_SAFE_VALUE(in_args->domain_id);
+
+	if (domain_id >= plat_scmi_rstd_count(msg->agent_id)) {
+		scmi_status_response(msg, SCMI_NOT_FOUND);
+		return;
+	}
+
+	if ((in_args->flags & SCMI_RESET_DOMAIN_AUTO) != 0U) {
+		out_args.status = plat_scmi_rstd_autonomous(msg->agent_id,
+							  domain_id,
+							  in_args->reset_state);
+	} else if ((in_args->flags & SCMI_RESET_DOMAIN_EXPLICIT) != 0U) {
+		out_args.status = plat_scmi_rstd_set_state(msg->agent_id,
+							 domain_id, true);
+	} else {
+		out_args.status = plat_scmi_rstd_set_state(msg->agent_id,
+							 domain_id, false);
+	}
+
+	if (out_args.status != SCMI_SUCCESS) {
+		scmi_status_response(msg, out_args.status);
+	} else {
+		scmi_write_response(msg, &out_args, sizeof(out_args));
+	}
+}
+
+static const scmi_msg_handler_t scmi_rstd_handler_table[] = {
+	[SCMI_PROTOCOL_VERSION] = report_version,
+	[SCMI_PROTOCOL_ATTRIBUTES] = report_attributes,
+	[SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes,
+	[SCMI_RESET_DOMAIN_ATTRIBUTES] = reset_domain_attributes,
+	[SCMI_RESET_DOMAIN_REQUEST] = reset_request,
+};
+
+static bool message_id_is_supported(unsigned int message_id)
+{
+	return (message_id < ARRAY_SIZE(scmi_rstd_handler_table)) &&
+	       (scmi_rstd_handler_table[message_id] != NULL);
+}
+
+scmi_msg_handler_t scmi_msg_get_rstd_handler(struct scmi_msg *msg)
+{
+	unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id);
+
+	if (message_id >= ARRAY_SIZE(scmi_rstd_handler_table)) {
+		VERBOSE("Reset domain handle not found %u\n", msg->message_id);
+		return NULL;
+	}
+
+	return scmi_rstd_handler_table[message_id];
+}
diff --git a/drivers/st/scmi-msg/reset_domain.h b/drivers/st/scmi-msg/reset_domain.h
new file mode 100644
index 0000000..47bee5e
--- /dev/null
+++ b/drivers/st/scmi-msg/reset_domain.h
@@ -0,0 +1,122 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019, Linaro Limited
+ */
+#ifndef SCMI_MSG_RESET_DOMAIN_H
+#define SCMI_MSG_RESET_DOMAIN_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <lib/utils_def.h>
+
+#define SCMI_PROTOCOL_VERSION_RESET_DOMAIN	0x10000U
+
+#define SCMI_RESET_STATE_ARCH			BIT(31)
+#define SCMI_RESET_STATE_IMPL			0U
+
+/*
+ * Identifiers of the SCMI Reset Domain Management Protocol commands
+ */
+enum scmi_reset_domain_command_id {
+	SCMI_RESET_DOMAIN_ATTRIBUTES = 0x03,
+	SCMI_RESET_DOMAIN_REQUEST = 0x04,
+	SCMI_RESET_DOMAIN_NOTIFY = 0x05,
+};
+
+/*
+ * Identifiers of the SCMI Reset Domain Management Protocol responses
+ */
+enum scmi_reset_domain_response_id {
+	SCMI_RESET_ISSUED = 0x00,
+	SCMI_RESET_COMPLETE = 0x04,
+};
+
+/*
+ * PROTOCOL_ATTRIBUTES
+ */
+
+#define SCMI_RESET_DOMAIN_COUNT_MASK		GENMASK_32(15, 0)
+
+struct scmi_reset_domain_protocol_attributes_p2a {
+	int32_t status;
+	uint32_t attributes;
+};
+
+/* Value for scmi_reset_domain_attributes_p2a:flags */
+#define SCMI_RESET_DOMAIN_ATTR_ASYNC		BIT(31)
+#define SCMI_RESET_DOMAIN_ATTR_NOTIF		BIT(30)
+
+/* Value for scmi_reset_domain_attributes_p2a:latency */
+#define SCMI_RESET_DOMAIN_ATTR_UNK_LAT		0x7fffffffU
+#define SCMI_RESET_DOMAIN_ATTR_MAX_LAT		0x7ffffffeU
+
+/* Macro for scmi_reset_domain_attributes_p2a:name */
+#define SCMI_RESET_DOMAIN_ATTR_NAME_SZ		16U
+
+struct scmi_reset_domain_attributes_a2p {
+	uint32_t domain_id;
+};
+
+struct scmi_reset_domain_attributes_p2a {
+	int32_t status;
+	uint32_t flags;
+	uint32_t latency;
+	char name[SCMI_RESET_DOMAIN_ATTR_NAME_SZ];
+};
+
+/*
+ * RESET
+ */
+
+/* Values for scmi_reset_domain_request_a2p:flags */
+#define SCMI_RESET_DOMAIN_ASYNC			BIT(2)
+#define SCMI_RESET_DOMAIN_EXPLICIT		BIT(1)
+#define SCMI_RESET_DOMAIN_AUTO			BIT(0)
+
+struct scmi_reset_domain_request_a2p {
+	uint32_t domain_id;
+	uint32_t flags;
+	uint32_t reset_state;
+};
+
+struct scmi_reset_domain_request_p2a {
+	int32_t status;
+};
+
+/*
+ * RESET_NOTIFY
+ */
+
+/* Values for scmi_reset_notify_p2a:flags */
+#define SCMI_RESET_DOMAIN_DO_NOTIFY		BIT(0)
+
+struct scmi_reset_domain_notify_a2p {
+	uint32_t domain_id;
+	uint32_t notify_enable;
+};
+
+struct scmi_reset_domain_notify_p2a {
+	int32_t status;
+};
+
+/*
+ * RESET_COMPLETE
+ */
+
+struct scmi_reset_domain_complete_p2a {
+	int32_t status;
+	uint32_t domain_id;
+};
+
+/*
+ * RESET_ISSUED
+ */
+
+struct scmi_reset_domain_issued_p2a {
+	uint32_t domain_id;
+	uint32_t reset_state;
+};
+
+#endif /* SCMI_MSG_RESET_DOMAIN_H */
diff --git a/drivers/st/scmi-msg/smt.c b/drivers/st/scmi-msg/smt.c
new file mode 100644
index 0000000..2d5cd73
--- /dev/null
+++ b/drivers/st/scmi-msg/smt.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Linaro Limited
+ */
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <drivers/st/scmi-msg.h>
+#include <drivers/st/scmi.h>
+#include <lib/cassert.h>
+#include <lib/mmio.h>
+#include <lib/spinlock.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+#include "common.h"
+
+/* Legacy SMT/SCMI messages are 128 bytes at most including SMT header */
+#define SCMI_PLAYLOAD_MAX		92U
+#define SCMI_PLAYLOAD_U32_MAX		(SCMI_PLAYLOAD_MAX / sizeof(uint32_t))
+
+/**
+ * struct smt_header - SMT formatted header for SMT base shared memory transfer
+ *
+ * @status: Bit flags, see SMT_STATUS_*
+ * @flags: Bit flags, see SMT_FLAG_*
+ * @length: Byte size of message payload (variable) + ::message_header (32bit)
+ * payload: SCMI message payload data
+ */
+struct smt_header {
+	uint32_t reserved0;
+	uint32_t status;
+	uint64_t reserved1;
+	uint32_t flags;
+	uint32_t length; /* message_header + payload */
+	uint32_t message_header;
+	uint32_t payload[];
+};
+
+CASSERT(SCMI_PLAYLOAD_MAX + sizeof(struct smt_header) <= SMT_BUF_SLOT_SIZE,
+	assert_scmi_message_max_length_fits_in_smt_buffer_slot);
+
+/* Flag set in smt_header::status when SMT does not contain pending message */
+#define SMT_STATUS_FREE			BIT(0)
+/* Flag set in smt_header::status when SMT reports an error */
+#define SMT_STATUS_ERROR		BIT(1)
+
+/* Flag set in smt_header::flags when SMT uses interrupts */
+#define SMT_FLAG_INTR_ENABLED		BIT(1)
+
+/* Bit fields packed in smt_header::message_header */
+#define SMT_MSG_ID_MASK			GENMASK_32(7, 0)
+#define SMT_HDR_MSG_ID(_hdr)		((_hdr) & SMT_MSG_ID_MASK)
+
+#define SMT_MSG_TYPE_MASK		GENMASK_32(9, 8)
+#define SMT_HDR_TYPE_ID(_hdr)		(((_hdr) & SMT_MSG_TYPE_MASK) >> 8)
+
+#define SMT_MSG_PROT_ID_MASK		GENMASK_32(17, 10)
+#define SMT_HDR_PROT_ID(_hdr)		(((_hdr) & SMT_MSG_PROT_ID_MASK) >> 10)
+
+/*
+ * Provision input message payload buffers for fastcall SMC context entries
+ * and for interrupt context execution entries.
+ */
+static uint32_t fast_smc_payload[PLATFORM_CORE_COUNT][SCMI_PLAYLOAD_U32_MAX];
+static uint32_t interrupt_payload[PLATFORM_CORE_COUNT][SCMI_PLAYLOAD_U32_MAX];
+
+/* SMP protection on channel access */
+static struct spinlock smt_channels_lock;
+
+/* If channel is not busy, set busy and return true, otherwise return false */
+static bool channel_set_busy(struct scmi_msg_channel *chan)
+{
+	bool channel_is_busy;
+
+	spin_lock(&smt_channels_lock);
+
+	channel_is_busy = chan->busy;
+
+	if (!channel_is_busy) {
+		chan->busy = true;
+	}
+
+	spin_unlock(&smt_channels_lock);
+
+	return !channel_is_busy;
+}
+
+static void channel_release_busy(struct scmi_msg_channel *chan)
+{
+	chan->busy = false;
+}
+
+static struct smt_header *channel_to_smt_hdr(struct scmi_msg_channel *chan)
+{
+	return (struct smt_header *)chan->shm_addr;
+}
+
+/*
+ * Creates a SCMI message instance in secure memory and pushes it in the SCMI
+ * message drivers. Message structure contains SCMI protocol meta-data and
+ * references to input payload in secure memory and output message buffer
+ * in shared memory.
+ */
+static void scmi_proccess_smt(unsigned int agent_id, uint32_t *payload_buf)
+{
+	struct scmi_msg_channel *chan;
+	struct smt_header *smt_hdr;
+	size_t in_payload_size;
+	uint32_t smt_status;
+	struct scmi_msg msg;
+	bool error = true;
+
+	chan = plat_scmi_get_channel(agent_id);
+	if (chan == NULL) {
+		return;
+	}
+
+	smt_hdr = channel_to_smt_hdr(chan);
+	assert(smt_hdr);
+
+	smt_status = __atomic_load_n(&smt_hdr->status, __ATOMIC_RELAXED);
+
+	if (!channel_set_busy(chan)) {
+		VERBOSE("SCMI channel %u busy", agent_id);
+		goto out;
+	}
+
+	in_payload_size = __atomic_load_n(&smt_hdr->length, __ATOMIC_RELAXED) -
+			  sizeof(smt_hdr->message_header);
+
+	if (in_payload_size > SCMI_PLAYLOAD_MAX) {
+		VERBOSE("SCMI payload too big %u", in_payload_size);
+		goto out;
+	}
+
+	if ((smt_status & (SMT_STATUS_ERROR | SMT_STATUS_FREE)) != 0U) {
+		VERBOSE("SCMI channel bad status 0x%x",
+			smt_hdr->status & (SMT_STATUS_ERROR | SMT_STATUS_FREE));
+		goto out;
+	}
+
+	/* Fill message */
+	zeromem(&msg, sizeof(msg));
+	msg.in = (char *)payload_buf;
+	msg.in_size = in_payload_size;
+	msg.out = (char *)smt_hdr->payload;
+	msg.out_size = chan->shm_size - sizeof(*smt_hdr);
+
+	assert((msg.out != NULL) && (msg.out_size >= sizeof(int32_t)));
+
+	/* Here the payload is copied in secure memory */
+	memcpy(msg.in, smt_hdr->payload, in_payload_size);
+
+	msg.protocol_id = SMT_HDR_PROT_ID(smt_hdr->message_header);
+	msg.message_id = SMT_HDR_MSG_ID(smt_hdr->message_header);
+	msg.agent_id = agent_id;
+
+	scmi_process_message(&msg);
+
+	/* Update message length with the length of the response message */
+	smt_hdr->length = msg.out_size_out + sizeof(smt_hdr->message_header);
+
+	channel_release_busy(chan);
+	error = false;
+
+out:
+	if (error) {
+		VERBOSE("SCMI error");
+		smt_hdr->status |= SMT_STATUS_ERROR | SMT_STATUS_FREE;
+	} else {
+		smt_hdr->status |= SMT_STATUS_FREE;
+	}
+}
+
+void scmi_smt_fastcall_smc_entry(unsigned int agent_id)
+{
+	scmi_proccess_smt(agent_id,
+			  fast_smc_payload[plat_my_core_pos()]);
+}
+
+void scmi_smt_interrupt_entry(unsigned int agent_id)
+{
+	scmi_proccess_smt(agent_id,
+			  interrupt_payload[plat_my_core_pos()]);
+}
+
+/* Init a SMT header for a shared memory buffer: state it a free/no-error */
+void scmi_smt_init_agent_channel(struct scmi_msg_channel *chan)
+{
+	if (chan != NULL) {
+		struct smt_header *smt_header = channel_to_smt_hdr(chan);
+
+		if (smt_header != NULL) {
+			memset(smt_header, 0, sizeof(*smt_header));
+			smt_header->status = SMT_STATUS_FREE;
+
+			return;
+		}
+	}
+
+	panic();
+}
diff --git a/drivers/st/spi/stm32_qspi.c b/drivers/st/spi/stm32_qspi.c
index ff92796..d67f831 100644
--- a/drivers/st/spi/stm32_qspi.c
+++ b/drivers/st/spi/stm32_qspi.c
@@ -18,6 +18,9 @@
 #include <lib/mmio.h>
 #include <lib/utils_def.h>
 
+/* Timeout for device interface reset */
+#define TIMEOUT_US_1_MS			1000U
+
 /* QUADSPI registers */
 #define QSPI_CR			0x00U
 #define QSPI_DCR		0x04U
@@ -492,8 +495,14 @@
 
 	stm32mp_clk_enable(stm32_qspi.clock_id);
 
-	stm32mp_reset_assert(stm32_qspi.reset_id);
-	stm32mp_reset_deassert(stm32_qspi.reset_id);
+	ret = stm32mp_reset_assert(stm32_qspi.reset_id, TIMEOUT_US_1_MS);
+	if (ret != 0) {
+		panic();
+	}
+	ret = stm32mp_reset_deassert(stm32_qspi.reset_id, TIMEOUT_US_1_MS);
+	if (ret != 0) {
+		panic();
+	}
 
 	mmio_write_32(qspi_base() + QSPI_CR, QSPI_CR_SSHIFT);
 	mmio_write_32(qspi_base() + QSPI_DCR, QSPI_DCR_FSIZE_MASK);
diff --git a/fdts/corstone700.dts b/fdts/corstone700.dtsi
similarity index 88%
rename from fdts/corstone700.dts
rename to fdts/corstone700.dtsi
index 851f5e6..2372207 100644
--- a/fdts/corstone700.dts
+++ b/fdts/corstone700.dtsi
@@ -1,22 +1,18 @@
 /*
- * Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-/dts-v1/;
+#include <dt-bindings/interrupt-controller/arm-gic.h>
 
 / {
-	model = "corstone700";
 	compatible = "arm,Corstone-700";
 	interrupt-parent = <&gic>;
 	#address-cells = <1>;
 	#size-cells = <1>;
 
-	chosen {
-		bootargs = "console=ttyAMA0 \
-		loglevel=9";
-	};
+	chosen { };
 
 	cpus {
 		#address-cells = <1>;
@@ -28,7 +24,6 @@
 			reg = <0>;
 			next-level-cache = <&L2_0>;
 		};
-
 	};
 
 	memory@80000000 {
@@ -99,7 +94,21 @@
 				<1 14 0xf08>,
 				<1 11 0xf08>,
 				<1 10 0xf08>;
+	};
+
+	refclk: refclk@1a220000 {
+		compatible = "arm,armv7-timer-mem";
+		reg = <0x1a220000  0x1000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		frame@1a230000 {
+			frame-number = <0>;
+			interrupts = <0 2 0xf04>;
+			reg = <0x1a230000 0x1000>;
 		};
+	};
 
 	mbox_es0mhu0: mhu@1b000000 {
 		compatible = "arm,mhuv2","arm,primecell";
@@ -149,5 +158,4 @@
 		      <0x1A010314 0x4>;
 		reg-names = "rstreg", "streg";
 	};
-
 };
diff --git a/fdts/corstone700_fpga.dts b/fdts/corstone700_fpga.dts
new file mode 100644
index 0000000..814d6a8
--- /dev/null
+++ b/fdts/corstone700_fpga.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+#include "corstone700.dtsi"
+
+/ {
+	model = "corstone700-fpga";
+
+	ethernet: eth@40100000 {
+		compatible = "smsc,lan9115";
+		reg = <0x40100000 0x10000>;
+		phy-mode = "mii";
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+		reg-io-width = <2>;
+		smsc,irq-push-pull;
+	};
+};
+
+&refclk {
+	clock-frequency = <32000000>;
+};
diff --git a/fdts/corstone700_fvp.dts b/fdts/corstone700_fvp.dts
new file mode 100644
index 0000000..3b1202d
--- /dev/null
+++ b/fdts/corstone700_fvp.dts
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+#include "corstone700.dtsi"
+
+/ {
+	model = "corstone700-fvp";
+
+	/*
+	* Intel StrataFlash J3 NOR flash: 2 x 16-bit interleaved components
+	* Flash total size: 32 MB
+	* Allocated flash space: 8 MB
+	*/
+
+	flash@8500000 {
+		compatible = "cfi-flash";
+		reg = <0x8500000 0x800000>;
+		bank-width = <4>;
+		device-width= <2>;
+	};
+
+	ethernet: eth@4010000 {
+		compatible = "smsc,lan91c111";
+		reg = <0x40100000 0x10000>;
+		phy-mode = "mii";
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 116 0xf04>;
+		reg-io-width = <2>;
+		smsc,irq-push-pull;
+	};
+};
+
+&refclk {
+	clock-frequency = <50000000>;
+};
diff --git a/fdts/cot_descriptors.dtsi b/fdts/cot_descriptors.dtsi
new file mode 100644
index 0000000..9308e17
--- /dev/null
+++ b/fdts/cot_descriptors.dtsi
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <tools_share/tbbr_oid.h>
+#include <common/tbbr/tbbr_img_def.h>
+
+cot {
+	manifests {
+		compatible = "arm, cert-descs";
+
+		trusted_boot_fw_cert: trusted_boot_fw_cert {
+			root-certificate;
+			image-id =<TRUSTED_BOOT_FW_CERT_ID>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			tb_fw_hash: tb_fw_hash {
+				oid = TRUSTED_BOOT_FW_HASH_OID;
+			};
+			tb_fw_config_hash: tb_fw_config_hash {
+				oid = TRUSTED_BOOT_FW_CONFIG_HASH_OID;
+			};
+			hw_config_hash: hw_config_hash {
+				oid = HW_CONFIG_HASH_OID;
+			};
+			fw_config_hash: fw_config_hash {
+				oid = FW_CONFIG_HASH_OID;
+			};
+		};
+
+		trusted_key_cert: trusted_key_cert {
+			root-certificate;
+			image-id = <TRUSTED_KEY_CERT_ID>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			trusted_world_pk: trusted_world_pk {
+				oid = TRUSTED_WORLD_PK_OID;
+			};
+			non_trusted_world_pk: non_trusted_world_pk {
+				oid = NON_TRUSTED_WORLD_PK_OID;
+			};
+		};
+
+		scp_fw_key_cert: scp_fw_key_cert {
+			image-id = <SCP_FW_KEY_CERT_ID>;
+			parent = <&trusted_key_cert>;
+			signing-key = <&trusted_world_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			scp_fw_content_pk: scp_fw_content_pk {
+				oid = SCP_FW_CONTENT_CERT_PK_OID;
+			};
+		};
+
+		scp_fw_content_cert: scp_fw_content_cert {
+			image-id = <SCP_FW_CONTENT_CERT_ID>;
+			parent = <&scp_fw_key_cert>;
+			signing-key = <&scp_fw_content_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			scp_fw_hash: scp_fw_hash {
+				oid = SCP_FW_HASH_OID;
+			};
+		};
+
+		soc_fw_key_cert: soc_fw_key_cert {
+			image-id = <SOC_FW_KEY_CERT_ID>;
+			parent = <&trusted_key_cert>;
+			signing-key = <&trusted_world_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+			soc_fw_content_pk: soc_fw_content_pk {
+				oid = SOC_FW_CONTENT_CERT_PK_OID;
+			};
+		};
+
+		soc_fw_content_cert: soc_fw_content_cert {
+			image-id = <SOC_FW_CONTENT_CERT_ID>;
+			parent = <&soc_fw_key_cert>;
+			signing-key = <&soc_fw_content_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			soc_fw_hash: soc_fw_hash {
+				oid = SOC_AP_FW_HASH_OID;
+			};
+			soc_fw_config_hash: soc_fw_config_hash {
+				oid = SOC_FW_CONFIG_HASH_OID;
+			};
+		};
+
+		trusted_os_fw_key_cert: trusted_os_fw_key_cert {
+			image-id = <TRUSTED_OS_FW_KEY_CERT_ID>;
+			parent = <&trusted_key_cert>;
+			signing-key = <&trusted_world_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			tos_fw_content_pk: tos_fw_content_pk {
+				oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID;
+			};
+		};
+
+		trusted_os_fw_content_cert: trusted_os_fw_content_cert {
+			image-id = <TRUSTED_OS_FW_CONTENT_CERT_ID>;
+			parent = <&trusted_os_fw_key_cert>;
+			signing-key = <&tos_fw_content_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			tos_fw_hash: tos_fw_hash {
+				oid = TRUSTED_OS_FW_HASH_OID;
+			};
+			tos_fw_extra1_hash: tos_fw_extra1_hash {
+				oid = TRUSTED_OS_FW_EXTRA1_HASH_OID;
+			};
+			tos_fw_extra2_hash: tos_fw_extra2_hash {
+				oid = TRUSTED_OS_FW_EXTRA2_HASH_OID;
+			};
+			tos_fw_config_hash: tos_fw_config_hash {
+				oid = TRUSTED_OS_FW_CONFIG_HASH_OID;
+			};
+		};
+
+		non_trusted_fw_key_cert: non_trusted_fw_key_cert {
+			image-id = <NON_TRUSTED_FW_KEY_CERT_ID>;
+			parent = <&trusted_key_cert>;
+			signing-key = <&non_trusted_world_pk>;
+			antirollback-counter = <&non_trusted_nv_counter>;
+
+			nt_fw_content_pk: nt_fw_content_pk {
+				oid = NON_TRUSTED_FW_CONTENT_CERT_PK_OID;
+			};
+		};
+
+		non_trusted_fw_content_cert: non_trusted_fw_content_cert {
+			image-id = <NON_TRUSTED_FW_CONTENT_CERT_ID>;
+			parent = <&non_trusted_fw_key_cert>;
+			signing-key = <&nt_fw_content_pk>;
+			antirollback-counter = <&non_trusted_nv_counter>;
+
+			nt_world_bl_hash: nt_world_bl_hash {
+				oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID;
+			};
+			nt_fw_config_hash: nt_fw_config_hash {
+				oid = NON_TRUSTED_FW_CONFIG_HASH_OID;
+			};
+		};
+
+#if defined(SPD_spmd)
+		sip_sp_content_cert: sip_sp_content_cert {
+			image-id = <SIP_SP_CONTENT_CERT_ID>;
+			parent = <&trusted_key_cert>;
+			signing-key = <&trusted_world_pk>;
+			antirollback-counter = <&trusted_nv_counter>;
+
+			sp_pkg1_hash: sp_pkg1_hash {
+				oid = SP_PKG1_HASH_OID;
+			};
+			sp_pkg2_hash: sp_pkg2_hash {
+				oid = SP_PKG2_HASH_OID;
+			};
+			sp_pkg3_hash: sp_pkg3_hash {
+				oid = SP_PKG3_HASH_OID;
+			};
+			sp_pkg4_hash: sp_pkg4_hash {
+				oid = SP_PKG4_HASH_OID;
+			};
+			sp_pkg5_hash: sp_pkg5_hash {
+				oid = SP_PKG5_HASH_OID;
+			};
+			sp_pkg6_hash: sp_pkg6_hash {
+				oid = SP_PKG6_HASH_OID;
+			};
+			sp_pkg7_hash: sp_pkg7_hash {
+				oid = SP_PKG7_HASH_OID;
+			};
+			sp_pkg8_hash: sp_pkg8_hash {
+				oid = SP_PKG8_HASH_OID;
+			};
+		};
+#endif
+	};
+
+	images {
+		compatible = "arm, img-descs";
+
+		hw_config {
+			image-id = <HW_CONFIG_ID>;
+			parent = <&trusted_boot_fw_cert>;
+			hash = <&hw_config_hash>;
+		};
+
+		tb_fw_config {
+			image-id = <TB_FW_CONFIG_ID>;
+			parent = <&trusted_boot_fw_cert>;
+			hash = <&tb_fw_config_hash>;
+		};
+
+		scp_bl2_image {
+			image-id = <SCP_BL2_IMAGE_ID>;
+			parent = <&scp_fw_content_cert>;
+			hash = <&scp_fw_hash>;
+		};
+
+		bl31_image {
+			image-id = <BL31_IMAGE_ID>;
+			parent = <&soc_fw_content_cert>;
+			hash = <&soc_fw_hash>;
+		};
+
+		soc_fw_config {
+			image-id = <SOC_FW_CONFIG_ID>;
+			parent = <&soc_fw_content_cert>;
+			hash = <&soc_fw_config_hash>;
+		};
+
+		bl32_image {
+			image-id = <BL32_IMAGE_ID>;
+			parent = <&trusted_os_fw_content_cert>;
+			hash = <&tos_fw_hash>;
+		};
+
+		bl32_extra1_image {
+			image-id = <BL32_EXTRA1_IMAGE_ID>;
+			parent = <&trusted_os_fw_content_cert>;
+			hash = <&tos_fw_extra1_hash>;
+		};
+
+		bl32_extra2_image {
+			image-id = <BL32_EXTRA2_IMAGE_ID>;
+			parent = <&trusted_os_fw_content_cert>;
+			hash = <&tos_fw_extra2_hash>;
+		};
+
+		tos_fw_config {
+			image-id = <TOS_FW_CONFIG_ID>;
+			parent = <&trusted_os_fw_content_cert>;
+			hash = <&tos_fw_config_hash>;
+		};
+
+		bl33_image {
+			image-id = <BL33_IMAGE_ID>;
+			parent = <&non_trusted_fw_content_cert>;
+			hash = <&nt_world_bl_hash>;
+		};
+
+		nt_fw_config {
+			image-id = <NT_FW_CONFIG_ID>;
+			parent = <&non_trusted_fw_content_cert>;
+			hash = <&nt_fw_config_hash>;
+		};
+
+#if defined(SPD_spmd)
+		sp_pkg1 {
+			image-id = <SP_PKG1_ID>;
+			parent = <&sip_sp_content_cert>;
+			hash = <&sp_pkg1_hash>;
+		};
+
+		sp_pkg2 {
+			image-id = <SP_PKG2_ID>;
+			parent = <&sip_sp_content_cert>;
+			hash = <&sp_pkg2_hash>;
+		};
+
+		sp_pkg3 {
+			image-id = <SP_PKG3_ID>;
+			parent = <&sip_sp_content_cert>;
+			hash = <&sp_pkg3_hash>;
+		};
+
+		sp_pkg4 {
+			image-id = <SP_PKG4_ID>;
+			parent = <&sip_sp_content_cert>;
+			hash = <&sp_pkg4_hash>;
+		};
+
+		sp_pkg5 {
+			image-id = <SP_PKG5_ID>;
+			parent = <&sip_sp_content_cert>;
+			hash = <&sp_pkg5_hash>;
+		};
+
+		sp_pkg6 {
+			image-id = <SP_PKG6_ID>;
+			parent = <&sip_sp_content_cert>;
+			hash = <&sp_pkg6_hash>;
+		};
+
+		sp_pkg7 {
+			image-id = <SP_PKG7_ID>;
+			parent = <&sip_sp_content_cert>;
+			hash = <&sp_pkg7_hash>;
+		};
+
+		sp_pkg8 {
+			image-id = <SP_PKG8_ID>;
+			parent = <&sip_sp_content_cert>;
+			hash = <&sp_pkg8_hash>;
+		};
+#endif
+	};
+};
+
+non-volatile-counters {
+	compatible = "arm, non-volatile-counter";
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	counters {
+		trusted_nv_counter: trusted_nv_counter {
+			oid = TRUSTED_FW_NVCOUNTER_OID;
+		};
+		non_trusted_nv_counter: non_trusted_nv_counter {
+			oid = NON_TRUSTED_FW_NVCOUNTER_OID;
+		};
+	};
+};
diff --git a/fdts/fvp-base-gicv2-psci-aarch32.dts b/fdts/fvp-base-gicv2-psci-aarch32.dts
index fcef927..591ec58 100644
--- a/fdts/fvp-base-gicv2-psci-aarch32.dts
+++ b/fdts/fvp-base-gicv2-psci-aarch32.dts
@@ -4,8 +4,15 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+/* Configuration: max 4 clusters with up to 4 CPUs */
+
 /dts-v1/;
 
+#define	AFF
+#define	REG_32
+
+#include "fvp-defs.dtsi"
+
 /memreserve/ 0x80000000 0x00010000;
 
 / {
@@ -42,37 +49,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		cpu-map {
-			cluster0 {
-				core0 {
-					cpu = <&CPU0>;
-				};
-				core1 {
-					cpu = <&CPU1>;
-				};
-				core2 {
-					cpu = <&CPU2>;
-				};
-				core3 {
-					cpu = <&CPU3>;
-				};
-			};
-
-			cluster1 {
-				core0 {
-					cpu = <&CPU4>;
-				};
-				core1 {
-					cpu = <&CPU5>;
-				};
-				core2 {
-					cpu = <&CPU6>;
-				};
-				core3 {
-					cpu = <&CPU7>;
-				};
-			};
-		};
+		CPU_MAP
 
 		idle-states {
 			entry-method = "arm,psci";
@@ -96,77 +73,7 @@
 			};
 		};
 
-		CPU0:cpu@0 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU1:cpu@1 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x1>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU2:cpu@2 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x2>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU3:cpu@3 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x3>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU4:cpu@100 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x100>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU5:cpu@101 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x101>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU6:cpu@102 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x102>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU7:cpu@103 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x103>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
+		CPUS
 
 		L2_0: l2-cache0 {
 			compatible = "cache";
diff --git a/fdts/fvp-base-gicv2-psci.dts b/fdts/fvp-base-gicv2-psci.dts
index 1e0a81c..4b3942e 100644
--- a/fdts/fvp-base-gicv2-psci.dts
+++ b/fdts/fvp-base-gicv2-psci.dts
@@ -4,8 +4,14 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+/* Configuration: max 4 clusters with up to 4 CPUs */
+
 /dts-v1/;
 
+#define	AFF
+
+#include "fvp-defs.dtsi"
+
 /memreserve/ 0x80000000 0x00010000;
 
 / {
@@ -42,37 +48,7 @@
 		#address-cells = <2>;
 		#size-cells = <0>;
 
-		cpu-map {
-			cluster0 {
-				core0 {
-					cpu = <&CPU0>;
-				};
-				core1 {
-					cpu = <&CPU1>;
-				};
-				core2 {
-					cpu = <&CPU2>;
-				};
-				core3 {
-					cpu = <&CPU3>;
-				};
-			};
-
-			cluster1 {
-				core0 {
-					cpu = <&CPU4>;
-				};
-				core1 {
-					cpu = <&CPU5>;
-				};
-				core2 {
-					cpu = <&CPU6>;
-				};
-				core3 {
-					cpu = <&CPU7>;
-				};
-			};
-		};
+		CPU_MAP
 
 		idle-states {
 			entry-method = "arm,psci";
@@ -96,77 +72,7 @@
 			};
 		};
 
-		CPU0:cpu@0 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x0>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU1:cpu@1 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x1>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU2:cpu@2 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x2>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU3:cpu@3 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x3>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU4:cpu@100 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x100>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU5:cpu@101 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x101>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU6:cpu@102 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x102>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU7:cpu@103 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x103>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
+		CPUS
 
 		L2_0: l2-cache0 {
 			compatible = "cache";
diff --git a/fdts/fvp-base-gicv3-psci-1t.dts b/fdts/fvp-base-gicv3-psci-1t.dts
index 3c82f7b..c5e0424 100644
--- a/fdts/fvp-base-gicv3-psci-1t.dts
+++ b/fdts/fvp-base-gicv3-psci-1t.dts
@@ -4,38 +4,11 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+/* Configuration: max 4 clusters with up to 4 CPUs with 1 thread per each */
+
 /dts-v1/;
 
+#define	AFF	00
+
+#include "fvp-defs.dtsi"
 #include "fvp-base-gicv3-psci-common.dtsi"
-
-&CPU0 {
-	reg = <0x0 0x0>;
-};
-
-&CPU1 {
-	reg = <0x0 0x100>;
-};
-
-&CPU2 {
-	reg = <0x0 0x200>;
-};
-
-&CPU3 {
-	reg = <0x0 0x300>;
-};
-
-&CPU4 {
-	reg = <0x0 0x10000>;
-};
-
-&CPU5 {
-	reg = <0x0 0x10100>;
-};
-
-&CPU6 {
-	reg = <0x0 0x10200>;
-};
-
-&CPU7 {
-	reg = <0x0 0x10300>;
-};
diff --git a/fdts/fvp-base-gicv3-psci-aarch32-1t.dts b/fdts/fvp-base-gicv3-psci-aarch32-1t.dts
index d1d3348..a31c703 100644
--- a/fdts/fvp-base-gicv3-psci-aarch32-1t.dts
+++ b/fdts/fvp-base-gicv3-psci-aarch32-1t.dts
@@ -4,38 +4,12 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+/* Configuration: max 4 clusters with up to 4 CPUs with 1 thread per each */
+
 /dts-v1/;
 
+#define	AFF	00
+#define	REG_32
+
+#include "fvp-defs.dtsi"
 #include "fvp-base-gicv3-psci-aarch32-common.dtsi"
-
-&CPU0 {
-	reg = <0x0>;
-};
-
-&CPU1 {
-	reg = <0x100>;
-};
-
-&CPU2 {
-	reg = <0x200>;
-};
-
-&CPU3 {
-	reg = <0x300>;
-};
-
-&CPU4 {
-	reg = <0x10000>;
-};
-
-&CPU5 {
-	reg = <0x10100>;
-};
-
-&CPU6 {
-	reg = <0x10200>;
-};
-
-&CPU7 {
-	reg = <0x10300>;
-};
diff --git a/fdts/fvp-base-gicv3-psci-aarch32-common.dtsi b/fdts/fvp-base-gicv3-psci-aarch32-common.dtsi
index a28a4a5..1a1bd12 100644
--- a/fdts/fvp-base-gicv3-psci-aarch32-common.dtsi
+++ b/fdts/fvp-base-gicv3-psci-aarch32-common.dtsi
@@ -40,37 +40,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		cpu-map {
-			cluster0 {
-				core0 {
-					cpu = <&CPU0>;
-				};
-				core1 {
-					cpu = <&CPU1>;
-				};
-				core2 {
-					cpu = <&CPU2>;
-				};
-				core3 {
-					cpu = <&CPU3>;
-				};
-			};
-
-			cluster1 {
-				core0 {
-					cpu = <&CPU4>;
-				};
-				core1 {
-					cpu = <&CPU5>;
-				};
-				core2 {
-					cpu = <&CPU6>;
-				};
-				core3 {
-					cpu = <&CPU7>;
-				};
-			};
-		};
+		CPU_MAP
 
 		idle-states {
 			entry-method = "arm,psci";
@@ -94,77 +64,7 @@
 			};
 		};
 
-		CPU0:cpu@0 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU1:cpu@1 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x1>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU2:cpu@2 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x2>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU3:cpu@3 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x3>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU4:cpu@100 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x100>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU5:cpu@101 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x101>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU6:cpu@102 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x102>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU7:cpu@103 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x103>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
+		CPUS
 
 		L2_0: l2-cache0 {
 			compatible = "cache";
diff --git a/fdts/fvp-base-gicv3-psci-aarch32.dts b/fdts/fvp-base-gicv3-psci-aarch32.dts
index 513014b..971b2e4 100644
--- a/fdts/fvp-base-gicv3-psci-aarch32.dts
+++ b/fdts/fvp-base-gicv3-psci-aarch32.dts
@@ -4,6 +4,12 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+/* Configuration: max 4 clusters with up to 4 CPUs */
+
 /dts-v1/;
 
+#define	REG_32
+#define	AFF
+
+#include "fvp-defs.dtsi"
 #include "fvp-base-gicv3-psci-aarch32-common.dtsi"
diff --git a/fdts/fvp-base-gicv3-psci-common.dtsi b/fdts/fvp-base-gicv3-psci-common.dtsi
index 4a7b656..192f574 100644
--- a/fdts/fvp-base-gicv3-psci-common.dtsi
+++ b/fdts/fvp-base-gicv3-psci-common.dtsi
@@ -6,6 +6,11 @@
 
 #include <services/sdei_flags.h>
 
+#define LEVEL	0
+#define EDGE	2
+#define SDEI_NORMAL	0x70
+#define HIGHEST_SEC	0
+
 /memreserve/ 0x80000000 0x00010000;
 
 / {
@@ -38,8 +43,9 @@
 		max-pwr-lvl = <2>;
 	};
 
-#if SDEI_IN_FCONF
+#if SDEI_IN_FCONF || SEC_INT_DESC_IN_FCONF
 	firmware {
+#if SDEI_IN_FCONF
 		sdei {
 			compatible = "arm,sdei-1.0";
 			method = "smc";
@@ -59,44 +65,43 @@
 						<2001 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>,
 						<2002 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>;
 		};
-	};
 #endif /* SDEI_IN_FCONF */
 
+#if SEC_INT_DESC_IN_FCONF
+		sec_interrupts {
+			compatible = "arm,secure_interrupt_desc";
+			/* Number of G0 and G1 secure interrupts defined by the platform */
+			g0_intr_cnt = <2>;
+			g1s_intr_cnt = <9>;
+			/*
+			 * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+			 * terminology. Each interrupt property descriptor has 3 fields:
+			 * 1. Interrupt number
+			 * 2. Interrupt priority
+			 * 3. Type of interrupt (Edge or Level configured)
+			 */
+			g0_intr_desc =	< 8 SDEI_NORMAL EDGE>,
+					<14 HIGHEST_SEC EDGE>;
+
+			g1s_intr_desc =	< 9 HIGHEST_SEC EDGE>,
+					<10 HIGHEST_SEC EDGE>,
+					<11 HIGHEST_SEC EDGE>,
+					<12 HIGHEST_SEC EDGE>,
+					<13 HIGHEST_SEC EDGE>,
+					<15 HIGHEST_SEC EDGE>,
+					<29 HIGHEST_SEC LEVEL>,
+					<56 HIGHEST_SEC LEVEL>,
+					<57 HIGHEST_SEC LEVEL>;
+		};
+#endif /* SEC_INT_DESC_IN_FCONF */
+	};
+#endif /* SDEI_IN_FCONF || SEC_INT_DESC_IN_FCONF */
+
 	cpus {
 		#address-cells = <2>;
 		#size-cells = <0>;
 
-		CPU_MAP:cpu-map {
-			cluster0 {
-				core0 {
-					cpu = <&CPU0>;
-				};
-				core1 {
-					cpu = <&CPU1>;
-				};
-				core2 {
-					cpu = <&CPU2>;
-				};
-				core3 {
-					cpu = <&CPU3>;
-				};
-			};
-
-			cluster1 {
-				core0 {
-					cpu = <&CPU4>;
-				};
-				core1 {
-					cpu = <&CPU5>;
-				};
-				core2 {
-					cpu = <&CPU6>;
-				};
-				core3 {
-					cpu = <&CPU7>;
-				};
-			};
-		};
+		CPU_MAP
 
 		idle-states {
 			entry-method = "arm,psci";
@@ -120,77 +125,7 @@
 			};
 		};
 
-		CPU0:cpu@0 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x0>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU1:cpu@1 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x1>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU2:cpu@2 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x2>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU3:cpu@3 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x3>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU4:cpu@100 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x100>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU5:cpu@101 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x101>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU6:cpu@102 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x102>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU7:cpu@103 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x103>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
+		CPUS
 
 		L2_0: l2-cache0 {
 			compatible = "cache";
diff --git a/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts b/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts
index 6e63b43..bda4b8d 100644
--- a/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts
+++ b/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts
@@ -4,185 +4,15 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+/* DynamIQ configuration: 1 cluster with up to 8 CPUs with 2 threads per each */
+
+/* Set default value if not passed from platform's makefile */
+#ifdef	FVP_MAX_PE_PER_CPU
+#define	PE_PER_CPU		FVP_MAX_PE_PER_CPU
+#else
+#define	PE_PER_CPU		2
+#endif
+
 /dts-v1/;
 
 #include "fvp-base-gicv3-psci-dynamiq-common.dtsi"
-
-&CPU_MAP {
-	/delete-node/ cluster0;
-
-	cluster0 {
-		core0 {
-			thread0 {
-				cpu = <&CPU0>;
-			};
-			thread1 {
-				cpu = <&CPU1>;
-			};
-		};
-		core1 {
-			thread0 {
-				cpu = <&CPU2>;
-			};
-			thread1 {
-				cpu = <&CPU3>;
-			};
-		};
-		core2 {
-			thread0 {
-				cpu = <&CPU4>;
-			};
-			thread1 {
-				cpu = <&CPU5>;
-			};
-		};
-		core3 {
-			thread0 {
-				cpu = <&CPU6>;
-			};
-			thread1 {
-				cpu = <&CPU7>;
-			};
-		};
-		core4 {
-			thread0 {
-				cpu = <&CPU8>;
-			};
-			thread1 {
-				cpu = <&CPU9>;
-			};
-		};
-		core5 {
-			thread0 {
-				cpu = <&CPU10>;
-			};
-			thread1 {
-				cpu = <&CPU11>;
-			};
-		};
-		core6 {
-			thread0 {
-				cpu = <&CPU12>;
-			};
-			thread1 {
-				cpu = <&CPU13>;
-			};
-		};
-		core7 {
-			thread0 {
-				cpu = <&CPU14>;
-			};
-			thread1 {
-				cpu = <&CPU15>;
-			};
-		};
-	};
-};
-
-/ {
-	cpus {
-		CPU0:cpu@0 {
-			reg = <0x0 0x0>;
-		};
-
-		CPU1:cpu@1 {
-			reg = <0x0 0x1>;
-		};
-
-		CPU2:cpu@2 {
-			reg = <0x0 0x100>;
-		};
-
-		CPU3:cpu@3 {
-			reg = <0x0 0x101>;
-		};
-
-		CPU4:cpu@100 {
-			reg = <0x0 0x200>;
-		};
-
-		CPU5:cpu@101 {
-			reg = <0x0 0x201>;
-		};
-
-		CPU6:cpu@102 {
-			reg = <0x0 0x300>;
-		};
-
-		CPU7:cpu@103 {
-			reg = <0x0 0x301>;
-		};
-
-		CPU8:cpu@200 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x400>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU9:cpu@201 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x401>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU10:cpu@202 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x500>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU11:cpu@203 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x501>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU12:cpu@300 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x600>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU13:cpu@301 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x601>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU14:cpu@302 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x700>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU15:cpu@303 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x701>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-	};
-};
diff --git a/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi b/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi
index 4bed36f..42a439f 100644
--- a/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi
+++ b/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi
@@ -6,38 +6,5 @@
 
 /dts-v1/;
 
+#include "fvp-defs-dynamiq.dtsi"
 #include "fvp-base-gicv3-psci-common.dtsi"
-
-/* DynamIQ based designs have upto 8 CPUs in each cluster */
-
-&CPU_MAP {
-	/delete-node/ cluster0;
-	/delete-node/ cluster1;
-
-	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 b8b0445..b693f75 100644
--- a/fdts/fvp-base-gicv3-psci-dynamiq.dts
+++ b/fdts/fvp-base-gicv3-psci-dynamiq.dts
@@ -4,38 +4,15 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+/* DynamIQ configuration: 1 cluster with up to 8 CPUs */
+
+/* Set default value if not passed from platform's makefile */
+#ifdef	FVP_MAX_PE_PER_CPU
+#define	PE_PER_CPU		FVP_MAX_PE_PER_CPU
+#else
+#define	PE_PER_CPU		1
+#endif
+
 /dts-v1/;
 
 #include "fvp-base-gicv3-psci-dynamiq-common.dtsi"
-
-&CPU0 {
-	reg = <0x0 0x0>;
-};
-
-&CPU1 {
-	reg = <0x0 0x100>;
-};
-
-&CPU2 {
-	reg = <0x0 0x200>;
-};
-
-&CPU3 {
-	reg = <0x0 0x300>;
-};
-
-&CPU4 {
-	reg = <0x0 0x400>;
-};
-
-&CPU5 {
-	reg = <0x0 0x500>;
-};
-
-&CPU6 {
-	reg = <0x0 0x600>;
-};
-
-&CPU7 {
-	reg = <0x0 0x700>;
-};
diff --git a/fdts/fvp-base-gicv3-psci.dts b/fdts/fvp-base-gicv3-psci.dts
index 65fa4b0..eb99472 100644
--- a/fdts/fvp-base-gicv3-psci.dts
+++ b/fdts/fvp-base-gicv3-psci.dts
@@ -4,6 +4,11 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+/* Configuration: max 4 clusters with up to 4 CPUs */
+
 /dts-v1/;
 
+#define	AFF
+
+#include "fvp-defs.dtsi"
 #include "fvp-base-gicv3-psci-common.dtsi"
diff --git a/fdts/fvp-defs-dynamiq.dtsi b/fdts/fvp-defs-dynamiq.dtsi
new file mode 100644
index 0000000..3659cd3
--- /dev/null
+++ b/fdts/fvp-defs-dynamiq.dtsi
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef	FVP_DEFS_DYNAMIQ_DTSI
+#define	FVP_DEFS_DYNAMIQ_DTSI
+
+/* Set default topology values if not passed from platform's makefile */
+#ifdef	FVP_CLUSTER_COUNT
+#define	CLUSTER_COUNT		FVP_CLUSTER_COUNT
+#else
+#define	CLUSTER_COUNT		1
+#endif
+
+#ifdef FVP_MAX_CPUS_PER_CLUSTER
+#define	CPUS_PER_CLUSTER	FVP_MAX_CPUS_PER_CLUSTER
+#else
+#define	CPUS_PER_CLUSTER	8
+#endif
+
+#define CONCAT(x, y)	x##y
+#define CONC(x, y)	CONCAT(x, y)
+
+/*
+ * n - CPU number
+ * r - MPID
+ */
+#define	CPU(n, r)			\
+	CPU##n:cpu@r## {		\
+	device_type = "cpu";		\
+	compatible = "arm,armv8";	\
+	reg = <0x0 0x##r>;		\
+	enable-method = "psci";		\
+	cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;	\
+	next-level-cache = <&L2_0>;	\
+	};
+
+#if (PE_PER_CPU == 2)
+#define THREAD(n)		\
+	thread##n {		\
+		cpu = <&CONC(CPU, __COUNTER__)>;	\
+	};
+
+#define	CORE(n)			\
+	core##n {		\
+		THREAD(0)	\
+		THREAD(1)	\
+	};
+
+#else	/* PE_PER_CPU == 1 */
+#define	CORE(n)			\
+	core##n {		\
+		cpu = <&CPU##n>;\
+	};
+#endif	/* PE_PER_CORE */
+
+#if (CPUS_PER_CLUSTER == 1)
+#if (PE_PER_CPU == 1)
+#define	CPUS		\
+	CPU(0, 0)
+#else
+#define	CPUS		\
+	CPU(0, 0)	\
+	CPU(1, 1)
+#endif
+#define	CLUSTER(n)	\
+	cluster##n {	\
+		CORE(0)	\
+	};
+
+#elif (CPUS_PER_CLUSTER == 2)
+#if (PE_PER_CPU == 1)
+#define	CPUS		\
+	CPU(0, 0)	\
+	CPU(1, 100)
+#else
+#define	CPUS		\
+	CPU(0, 0)	\
+	CPU(1, 1)	\
+	CPU(2, 100)	\
+	CPU(3, 101)
+#endif
+#define	CLUSTER(n)	\
+	cluster##n {	\
+		CORE(0)	\
+		CORE(1)	\
+	};
+
+#elif (CPUS_PER_CLUSTER == 3)
+#if (PE_PER_CPU == 1)
+#define	CPUS		\
+	CPU(0, 0)	\
+	CPU(1, 100)	\
+	CPU(2, 200)
+#else
+#define	CPUS		\
+	CPU(0, 0)	\
+	CPU(1, 1)	\
+	CPU(2, 100)	\
+	CPU(3, 101)	\
+	CPU(4, 200)	\
+	CPU(5, 201)
+#endif
+#define	CLUSTER(n)	\
+	cluster##n {	\
+		CORE(0)	\
+		CORE(1)	\
+		CORE(2)	\
+	};
+
+#elif (CPUS_PER_CLUSTER == 4)
+#if (PE_PER_CPU == 1)
+#define	CPUS		\
+	CPU(0, 0)	\
+	CPU(1, 100)	\
+	CPU(2, 200)	\
+	CPU(3, 300)
+#else
+#define	CPUS		\
+	CPU(0, 0)	\
+	CPU(1, 1)	\
+	CPU(2, 100)	\
+	CPU(3, 101)	\
+	CPU(4, 200)	\
+	CPU(5, 201)	\
+	CPU(6, 300)	\
+	CPU(7, 301)
+#endif
+#define	CLUSTER(n)	\
+	cluster##n {	\
+		CORE(0)	\
+		CORE(1)	\
+		CORE(2)	\
+		CORE(3)	\
+	};
+
+#elif (CPUS_PER_CLUSTER == 5)
+#if (PE_PER_CPU == 1)
+#define	CPUS		\
+	CPU(0, 0)	\
+	CPU(1, 100)	\
+	CPU(2, 200)	\
+	CPU(3, 300)	\
+	CPU(4, 400)
+#else
+#define	CPUS		\
+	CPU(0, 0)	\
+	CPU(1, 1)	\
+	CPU(2, 100)	\
+	CPU(3, 101)	\
+	CPU(4, 200)	\
+	CPU(5, 201)	\
+	CPU(6, 300)	\
+	CPU(7, 301)	\
+	CPU(8, 400)	\
+	CPU(9, 401)
+#endif
+#define	CLUSTER(n)	\
+	cluster##n {	\
+		CORE(0)	\
+		CORE(1)	\
+		CORE(2)	\
+		CORE(3)	\
+		CORE(4)	\
+	};
+
+#elif (CPUS_PER_CLUSTER == 6)
+#if (PE_PER_CPU == 1)
+#define	CPUS		\
+	CPU(0, 0)	\
+	CPU(1, 100)	\
+	CPU(2, 200)	\
+	CPU(3, 300)	\
+	CPU(4, 400)	\
+	CPU(5, 500)
+#else
+#define	CPUS		\
+	CPU(0, 0)	\
+	CPU(1, 1)	\
+	CPU(2, 100)	\
+	CPU(3, 101)	\
+	CPU(4, 200)	\
+	CPU(5, 201)	\
+	CPU(6, 300)	\
+	CPU(7, 301)	\
+	CPU(8, 400)	\
+	CPU(9, 401)	\
+	CPU(10, 500)	\
+	CPU(11, 501)
+#endif
+#define	CLUSTER(n)	\
+	cluster##n {	\
+		CORE(0)	\
+		CORE(1)	\
+		CORE(2)	\
+		CORE(3)	\
+		CORE(4)	\
+		CORE(5)	\
+	};
+
+#elif (CPUS_PER_CLUSTER == 7)
+#if (PE_PER_CPU == 1)
+#define	CPUS		\
+	CPU(0, 0)	\
+	CPU(1, 100)	\
+	CPU(2, 200)	\
+	CPU(3, 300)	\
+	CPU(4, 400)	\
+	CPU(5, 500)	\
+	CPU(6, 600)
+#else
+#define	CPUS		\
+	CPU(0, 0)	\
+	CPU(1, 1)	\
+	CPU(2, 100)	\
+	CPU(3, 101)	\
+	CPU(4, 200)	\
+	CPU(5, 201)	\
+	CPU(6, 300)	\
+	CPU(7, 301)	\
+	CPU(8, 400)	\
+	CPU(9, 401)	\
+	CPU(10, 500)	\
+	CPU(11, 501)	\
+	CPU(12, 600)	\
+	CPU(13, 601)
+#endif
+#define	CLUSTER(n)	\
+	cluster##n {	\
+		CORE(0)	\
+		CORE(1)	\
+		CORE(2)	\
+		CORE(3)	\
+		CORE(4)	\
+		CORE(5)	\
+		CORE(6)	\
+	};
+
+#else
+#if (PE_PER_CPU == 1)
+#define	CPUS		\
+	CPU(0, 0)	\
+	CPU(1, 100)	\
+	CPU(2, 200)	\
+	CPU(3, 300)	\
+	CPU(4, 400)	\
+	CPU(5, 500)	\
+	CPU(6, 600)	\
+	CPU(7, 700)
+#else
+#define	CPUS		\
+	CPU(0, 0)	\
+	CPU(1, 1)	\
+	CPU(2, 100)	\
+	CPU(3, 101)	\
+	CPU(4, 200)	\
+	CPU(5, 201)	\
+	CPU(6, 300)	\
+	CPU(7, 301)	\
+	CPU(8, 400)	\
+	CPU(9, 401)	\
+	CPU(10, 500)	\
+	CPU(11, 501)	\
+	CPU(12, 600)	\
+	CPU(13, 601)	\
+	CPU(14, 700)	\
+	CPU(15, 701)
+#endif
+#define	CLUSTER(n)	\
+	cluster##n {	\
+		CORE(0)	\
+		CORE(1)	\
+		CORE(2)	\
+		CORE(3)	\
+		CORE(4)	\
+		CORE(5)	\
+		CORE(6)	\
+		CORE(7)	\
+	};
+#endif	/* CPUS_PER_CLUSTER */
+
+#define	CPU_MAP			\
+	cpu-map {		\
+		CLUSTER(0)	\
+	};
+
+#endif	/* FVP_DEFS_DYNAMIQ_DTSI */
diff --git a/fdts/fvp-defs.dtsi b/fdts/fvp-defs.dtsi
new file mode 100644
index 0000000..1ffe65a
--- /dev/null
+++ b/fdts/fvp-defs.dtsi
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef	FVP_DEFS_DTSI
+#define	FVP_DEFS_DTSI
+
+/* Set default topology values if not passed from platform's makefile */
+#ifndef	CLUSTER_COUNT
+#ifdef	FVP_CLUSTER_COUNT
+#define	CLUSTER_COUNT		FVP_CLUSTER_COUNT
+#else
+#define	CLUSTER_COUNT		2
+#endif
+#endif	/* CLUSTER_COUNT */
+
+#ifndef CPUS_PER_CLUSTER
+#ifdef FVP_MAX_CPUS_PER_CLUSTER
+#define	CPUS_PER_CLUSTER	FVP_MAX_CPUS_PER_CLUSTER
+#else
+#define	CPUS_PER_CLUSTER	4
+#endif
+#endif	/* CPUS_PER_CLUSTER */
+
+/* Get platform's topology */
+#define	CPUS_COUNT		(CLUSTER_COUNT * CPUS_PER_CLUSTER)
+
+#define CONCAT(x, y)	x##y
+#define CONC(x, y)	CONCAT(x, y)
+
+/* CPU's cluster */
+#define	CLS(n)	(n / CPUS_PER_CLUSTER)
+
+/* CPU's position in cluster */
+#define	POS(n)	(n % CPUS_PER_CLUSTER)
+
+#define	ADR(n, c, p)	\
+	CPU##n:cpu@CONC(c, CONC(p, AFF)) {
+
+#define	PRE			\
+	device_type = "cpu";	\
+	compatible = "arm,armv8";
+
+#ifdef	REG_32
+/* 32-bit address */
+#define	REG(c, p)	\
+	reg = <CONC(0x, CONC(c, CONC(p, AFF)))>;
+#else
+/* 64-bit address */
+#define	REG(c, p)	\
+	reg = <0x0 CONC(0x, CONC(c, CONC(p, AFF)))>;
+#endif	/* REG_32 */
+
+#define	POST				\
+	enable-method = "psci";		\
+	cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;	\
+	next-level-cache = <&L2_0>;	\
+	};
+
+#ifdef	REG_32
+#define	CPU_0		\
+	CPU0:cpu@0 {	\
+	PRE		\
+	reg = <0x0>;	\
+	POST
+#else
+#define	CPU_0		\
+	CPU0:cpu@0 {	\
+	PRE		\
+	reg = <0x0 0x0>;\
+	POST
+#endif	/* REG_32 */
+
+/*
+ * n - CPU number
+ */
+#define	CPU(n, c, p)	\
+	ADR(n, c, p)	\
+	PRE		\
+	REG(c, p)	\
+	POST
+
+/* 2 CPUs */
+#if (CPUS_COUNT > 1)
+#if (CLS(1) == 0)
+#define c1
+#define	p1	1
+#else
+#define	c1	10
+#define p1	0
+#endif
+
+#define	CPU_1	CPU(1, c1, p1)	/* CPU1: 0.1; 1.0 */
+
+/* 3 CPUs */
+#if (CPUS_COUNT > 2)
+#if (CLS(2) == 0)
+#define c2
+#define p2	2
+#elif (CLS(2) == 1)
+#define	c2	10
+#define p2	0
+#else
+#define	c2	20
+#define p2	0
+#endif
+
+#define	CPU_2	CPU(2, c2, p2)	/* CPU2: 0.2; 1.0; 2.0 */
+
+/* 4 CPUs */
+#if (CPUS_COUNT > 3)
+#if (CLS(3) == 0)
+#define c3
+#elif (CLS(3) == 1)
+#define	c3	10
+#else
+#define	c3	30
+#endif
+
+#if (POS(3) == 0)
+#define p3	0
+#elif (POS(3) == 1)
+#define	p3	1
+#else
+#define	p3	3
+#endif
+
+#define	CPU_3	CPU(3, c3, p3)	/* CPU3: 0.3; 1.0; 1.1; 3.0 */
+
+/* 6 CPUs */
+#if (CPUS_COUNT > 4)
+#if (CLS(4) == 1)
+#define	c4	10
+#else
+#define	c4	20
+#endif
+
+#if (POS(4) == 0)
+#define p4	0
+#else
+#define	p4	1
+#endif
+
+#if (CLS(5) == 1)
+#define	c5	10
+#else
+#define	c5	20
+#endif
+
+#if (POS(5) == 1)
+#define	p5	1
+#else
+#define	p5	2
+#endif
+
+#define	CPU_4	CPU(4, c4, p4)	/* CPU4: 1.0; 1.1; 2.0 */
+#define	CPU_5	CPU(5, c5, p5)	/* CPU5: 1.1; 1.2; 2.1 */
+
+/* 8 CPUs */
+#if (CPUS_COUNT > 6)
+#if (CLS(6) == 1)
+#define	c6	10
+#define	p6	2
+#elif (CLS(6) == 2)
+#define	c6	20
+#define	p6	0
+#else
+#define	c6	30
+#define	p6	0
+#endif
+
+#if (CLS(7) == 1)
+#define	c7	10
+#define	p7	3
+#elif (CLS(7) == 2)
+#define	c7	20
+#define	p7	1
+#else
+#define	c7	30
+#define	p7	1
+#endif
+
+#define	CPU_6	CPU(6, c6, p6)	/* CPU6: 1.2; 2.0; 3.0 */
+#define	CPU_7	CPU(7, c7, p7)	/* CPU7: 1.3; 2.1; 3.1 */
+
+/* 9 CPUs */
+#if (CPUS_COUNT > 8)
+#if (POS(8) == 0)
+#define	p8	0
+#else
+#define	p8	2
+#endif
+
+#define	CPU_8	CPU(8, 20, p8)	/* CPU8: 2.0; 2.2 */
+
+/* 12 CPUs */
+#if (CPUS_COUNT > 9)
+#if (CLS(9) == 2)
+#define	c9	20
+#define	p9	1
+#else
+#define	c9	30
+#define	p9	0
+#endif
+
+#if (CLS(10) == 2)
+#define	c10	20
+#define	p10	2
+#else
+#define	c10	30
+#define	p10	1
+#endif
+
+#if (CLS(11) == 2)
+#define	c11	20
+#define	p11	3
+#else
+#define	c11	30
+#define	p11	2
+#endif
+
+#define	CPU_9	CPU(9, c9, p9)		/* CPU9:  2.1; 3.0 */
+#define	CPU_10	CPU(10, c10, p10)	/* CPU10: 2.2; 3.1 */
+#define	CPU_11	CPU(11, c11, p11)	/* CPU11: 2.3; 3.2 */
+
+/* 16 CPUs */
+#if (CPUS_COUNT > 12)
+#define	CPU_12	CPU(12, 30, 0)		/* CPU12: 3.0 */
+#define	CPU_13	CPU(13, 30, 1)		/* CPU13: 3.1 */
+#define	CPU_14	CPU(14, 30, 2)		/* CPU14: 3.2 */
+#define	CPU_15	CPU(15, 30, 3)		/* CPU15: 3.3 */
+#endif	/* > 12 */
+#endif	/* > 9 */
+#endif	/* > 8 */
+#endif	/* > 6 */
+#endif	/* > 4 */
+#endif	/* > 3 */
+#endif	/* > 2 */
+#endif	/* > 1 */
+
+#if (CPUS_COUNT == 1)
+#define	CPUS	\
+	CPU_0
+
+#elif (CPUS_COUNT == 2)
+#define	CPUS	\
+	CPU_0	\
+	CPU_1
+
+#elif (CPUS_COUNT == 3)
+#define	CPUS	\
+	CPU_0	\
+	CPU_1	\
+	CPU_2
+
+#elif (CPUS_COUNT == 4)
+#define	CPUS	\
+	CPU_0	\
+	CPU_1	\
+	CPU_2	\
+	CPU_3
+
+#elif (CPUS_COUNT == 6)
+#define	CPUS	\
+	CPU_0	\
+	CPU_1	\
+	CPU_2	\
+	CPU_3	\
+	CPU_4	\
+	CPU_5
+
+#elif (CPUS_COUNT == 8)
+#define	CPUS	\
+	CPU_0	\
+	CPU_1	\
+	CPU_2	\
+	CPU_3	\
+	CPU_4	\
+	CPU_5	\
+	CPU_6	\
+	CPU_7
+
+#elif (CPUS_COUNT == 9)
+#define	CPUS	\
+	CPU_0	\
+	CPU_1	\
+	CPU_2	\
+	CPU_3	\
+	CPU_4	\
+	CPU_5	\
+	CPU_6	\
+	CPU_7	\
+	CPU_8
+
+#elif (CPUS_COUNT == 12)
+#define	CPUS	\
+	CPU_0	\
+	CPU_1	\
+	CPU_2	\
+	CPU_3	\
+	CPU_4	\
+	CPU_5	\
+	CPU_6	\
+	CPU_7	\
+	CPU_8	\
+	CPU_9	\
+	CPU_10	\
+	CPU_11
+
+#else
+#define	CPUS	\
+	CPU_0	\
+	CPU_1	\
+	CPU_2	\
+	CPU_3	\
+	CPU_4	\
+	CPU_5	\
+	CPU_6	\
+	CPU_7	\
+	CPU_8	\
+	CPU_9	\
+	CPU_10	\
+	CPU_11	\
+	CPU_12	\
+	CPU_13	\
+	CPU_14	\
+	CPU_15
+#endif	/* CPUS_COUNT */
+
+#define	CORE(n)		\
+	core##n {	\
+		cpu = <&CONC(CPU, __COUNTER__)>;	\
+	};
+
+/* Max 4 CPUs per cluster */
+#if (CPUS_PER_CLUSTER == 1)
+#define	CLUSTER(n)		\
+	cluster##n {		\
+		CORE(0)		\
+	};
+#elif (CPUS_PER_CLUSTER == 2)
+#define	CLUSTER(n)		\
+	cluster##n {		\
+		CORE(0)		\
+		CORE(1)		\
+	};
+
+#elif (CPUS_PER_CLUSTER == 3)
+#define	CLUSTER(n)		\
+	cluster##n {		\
+		CORE(0)		\
+		CORE(1)		\
+		CORE(2)		\
+	};
+
+#else
+#define	CLUSTER(n)		\
+	cluster##n {		\
+		CORE(0)		\
+		CORE(1)		\
+		CORE(2)		\
+		CORE(3)		\
+	};
+#endif	/* CPUS_PER_CLUSTER */
+
+/* Max 4 clusters */
+#if (CLUSTER_COUNT == 1)
+#define	CPU_MAP			\
+	cpu-map {		\
+		CLUSTER(0)	\
+	};
+
+#elif (CLUSTER_COUNT == 2)
+#define	CPU_MAP			\
+	cpu-map {		\
+		CLUSTER(0)	\
+		CLUSTER(1)	\
+	};
+
+#elif (CLUSTER_COUNT == 3)
+#define	CPU_MAP			\
+	cpu-map {		\
+		CLUSTER(0)	\
+		CLUSTER(1)	\
+		CLUSTER(2)	\
+	};
+
+#else
+#define	CPU_MAP			\
+	cpu-map {		\
+		CLUSTER(0)	\
+		CLUSTER(1)	\
+		CLUSTER(2)	\
+		CLUSTER(3)	\
+	};
+#endif	/* CLUSTER_COUNT */
+
+#endif	/* FVP_DEFS_DTSI */
diff --git a/fdts/fvp-foundation-gicv2-psci.dts b/fdts/fvp-foundation-gicv2-psci.dts
index 3a204cb..95a800e 100644
--- a/fdts/fvp-foundation-gicv2-psci.dts
+++ b/fdts/fvp-foundation-gicv2-psci.dts
@@ -4,8 +4,15 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+/* Configuration: 1 cluster with up to 4 CPUs */
+
 /dts-v1/;
 
+#define	AFF
+#define	CLUSTER_COUNT	1
+
+#include "fvp-defs.dtsi"
+
 /memreserve/ 0x80000000 0x00010000;
 
 / {
@@ -42,22 +49,7 @@
 		#address-cells = <2>;
 		#size-cells = <0>;
 
-		cpu-map {
-			cluster0 {
-				core0 {
-					cpu = <&CPU0>;
-				};
-				core1 {
-					cpu = <&CPU1>;
-				};
-				core2 {
-					cpu = <&CPU2>;
-				};
-				core3 {
-					cpu = <&CPU3>;
-				};
-			};
-		};
+		CPU_MAP
 
 		idle-states {
 			entry-method = "arm,psci";
@@ -81,41 +73,7 @@
 			};
 		};
 
-		CPU0:cpu@0 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x0>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU1:cpu@1 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x1>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU2:cpu@2 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x2>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU3:cpu@3 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x3>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
+		CPUS
 
 		L2_0: l2-cache0 {
 			compatible = "cache";
diff --git a/fdts/fvp-foundation-gicv3-psci.dts b/fdts/fvp-foundation-gicv3-psci.dts
index d85305a..c295dc1 100644
--- a/fdts/fvp-foundation-gicv3-psci.dts
+++ b/fdts/fvp-foundation-gicv3-psci.dts
@@ -4,8 +4,15 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+/* Configuration: 1 cluster with up to 4 CPUs */
+
 /dts-v1/;
 
+#define	AFF
+#define	CLUSTER_COUNT	1
+
+#include "fvp-defs.dtsi"
+
 /memreserve/ 0x80000000 0x00010000;
 
 / {
@@ -42,22 +49,7 @@
 		#address-cells = <2>;
 		#size-cells = <0>;
 
-		cpu-map {
-			cluster0 {
-				core0 {
-					cpu = <&CPU0>;
-				};
-				core1 {
-					cpu = <&CPU1>;
-				};
-				core2 {
-					cpu = <&CPU2>;
-				};
-				core3 {
-					cpu = <&CPU3>;
-				};
-			};
-		};
+		CPU_MAP
 
 		idle-states {
 			entry-method = "arm,psci";
@@ -81,41 +73,7 @@
 			};
 		};
 
-		CPU0:cpu@0 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x0>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU1:cpu@1 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x1>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU2:cpu@2 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x2>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
-
-		CPU3:cpu@3 {
-			device_type = "cpu";
-			compatible = "arm,armv8";
-			reg = <0x0 0x3>;
-			enable-method = "psci";
-			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
-			next-level-cache = <&L2_0>;
-		};
+		CPUS
 
 		L2_0: l2-cache0 {
 			compatible = "cache";
diff --git a/fdts/n1sdp-multi-chip.dts b/fdts/n1sdp-multi-chip.dts
new file mode 100644
index 0000000..b58d9d8
--- /dev/null
+++ b/fdts/n1sdp-multi-chip.dts
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause)
+/*
+ * Copyright (c) 2019-2020, Arm Limited.
+ */
+
+#include "n1sdp-single-chip.dts"
+
+/ {
+	cpus {
+		cpu4@100000000 {
+			compatible = "arm,neoverse-n1";
+			reg = <0x1 0x0>;
+			device_type = "cpu";
+			enable-method = "psci";
+			numa-node-id = <1>;
+		};
+		cpu5@100000100 {
+			compatible = "arm,neoverse-n1";
+			reg = <0x1 0x00000100>;
+			device_type = "cpu";
+			enable-method = "psci";
+			numa-node-id = <1>;
+		};
+		cpu6@100010000 {
+			compatible = "arm,neoverse-n1";
+			reg = <0x1 0x00010000>;
+			device_type = "cpu";
+			enable-method = "psci";
+			numa-node-id = <1>;
+		};
+		cpu7@100010100 {
+			compatible = "arm,neoverse-n1";
+			reg = <0x1 0x00010100>;
+			device_type = "cpu";
+			enable-method = "psci";
+			numa-node-id = <1>;
+		};
+	};
+
+	/* Remote N1SDP board address is mapped at offset 4TB.
+	 * First DRAM Bank of remote N1SDP board is mapped at 4TB + 2GB.
+	 */
+	memory@40080000000 {
+		device_type = "memory";
+		reg = <0x00000400 0x80000000 0x0 0x80000000>,
+			<0x00000480 0x80000000 0x3 0x80000000>;
+		numa-node-id = <1>;
+	};
+
+	distance-map {
+		compatible = "numa-distance-map-v1";
+		distance-matrix =   <0 0 10>,
+				    <0 1 20>,
+				    <1 1 10>;
+	};
+};
+
+&gic {
+	#redistributor-regions = <2>;
+	reg =   <0x0 0x30000000 0 0x10000>,	/* GICD */
+		<0x0 0x300c0000 0 0x80000>,	/* GICR */
+		<0x400 0x300c0000 0 0x80000>;	/* GICR */
+};
diff --git a/fdts/n1sdp-single-chip.dts b/fdts/n1sdp-single-chip.dts
new file mode 100644
index 0000000..bd48273
--- /dev/null
+++ b/fdts/n1sdp-single-chip.dts
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause)
+/*
+ * Copyright (c) 2019-2020, Arm Limited.
+ */
+
+/dts-v1/;
+
+#include "n1sdp.dtsi"
+
+/ {
+	model = "Arm Neoverse N1 System Development Platform";
+	compatible = "arm,neoverse-n1-sdp", "arm,neoverse-n1-soc";
+
+	aliases {
+		serial0 = &soc_uart0;
+	};
+
+	chosen {
+		stdout-path = "soc_uart0:115200n8";
+	};
+
+	/* This configuration assumes that standard setup with two DIMM modules.
+	 * In the first 2GB of DRAM bank the top 16MB are reserved by firmware as secure memory.
+	 * This configuration assumes 16GB of total DRAM being populated.
+	 */
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x00000000 0x80000000 0x0 0x7f000000>,
+			<0x00000080 0x80000000 0x3 0x80000000>;
+		numa-node-id = <0>;
+	};
+
+	soc_refclk60mhz: refclk60mhz {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <60000000>;
+		clock-output-names = "iofpga_clk";
+	};
+
+	soc_hdlcdclk:  hdlcdclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <23750000>;
+		clock-output-names = "hdlcdclk";
+	};
+
+	hdlcd: hdlcd@1c050000 {
+		compatible = "arm,hdlcd";
+		reg = <0 0x1c050000 0 0x1000>;
+		interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&soc_hdlcdclk>;
+		clock-names = "pxlclk";
+
+		port {
+			hdlcd0_output: endpoint {
+				remote-endpoint = <&tda998x_0_input>;
+			};
+		};
+	};
+
+	i2c@1c0f0000 {
+		compatible = "arm,versatile-i2c";
+		reg = <0x0 0x1c0f0000 0x0 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-frequency = <400000>;
+		i2c-sda-hold-time-ns = <500>;
+		clocks = <&soc_refclk60mhz>;
+
+		hdmi-transmitter@70 {
+			compatible = "nxp,tda998x";
+			reg = <0x70>;
+			port {
+				tda998x_0_input: endpoint {
+					remote-endpoint = <&hdlcd0_output>;
+				};
+			};
+		};
+	};
+};
+
+&pcie_ctlr {
+	status = "okay";
+};
+
+&ccix_pcie_ctlr {
+	status = "okay";
+};
+
+&soc_uart0 {
+	status = "okay";
+};
diff --git a/fdts/n1sdp.dtsi b/fdts/n1sdp.dtsi
new file mode 100644
index 0000000..88f8734
--- /dev/null
+++ b/fdts/n1sdp.dtsi
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause)
+/*
+ * Copyright (c) 2019-2020, Arm Limited.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu0@0 {
+			compatible = "arm,neoverse-n1";
+			reg = <0x0 0x0>;
+			device_type = "cpu";
+			enable-method = "psci";
+			numa-node-id = <0>;
+		};
+		cpu1@100 {
+			compatible = "arm,neoverse-n1";
+			reg = <0x0 0x100>;
+			device_type = "cpu";
+			enable-method = "psci";
+			numa-node-id = <0>;
+		};
+		cpu2@10000 {
+			compatible = "arm,neoverse-n1";
+			reg = <0x0 0x10000>;
+			device_type = "cpu";
+			enable-method = "psci";
+			numa-node-id = <0>;
+		};
+		cpu3@10100 {
+			compatible = "arm,neoverse-n1";
+			reg = <0x0 0x10100>;
+			device_type = "cpu";
+			enable-method = "psci";
+			numa-node-id = <0>;
+		};
+	};
+
+	pmu {
+		compatible = "arm,armv8-pmuv3";
+		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	spe-pmu {
+		compatible = "arm,statistical-profiling-extension-v1";
+		interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+	};
+
+	soc_refclk100mhz: refclk100mhz {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <100000000>;
+		clock-output-names = "apb_pclk";
+	};
+
+	soc_uartclk:  uartclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <50000000>;
+		clock-output-names = "uartclk";
+	};
+
+	soc {
+		compatible = "arm,neoverse-n1-soc", "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		gic: interrupt-controller@30000000 {
+			compatible = "arm,gic-v3";
+			#address-cells = <2>;
+			#interrupt-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+			interrupt-controller;
+			reg = <0x0 0x30000000 0 0x10000>,	/* GICD */
+				<0x0 0x300c0000 0 0x80000>;	/* GICR */
+
+			interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+
+			its1: its@30040000 {
+				compatible = "arm,gic-v3-its";
+				msi-controller;
+				#msi-cells = <1>;
+				reg = <0x0 0x30040000 0x0 0x20000>;
+			};
+
+			its2: its@30060000 {
+				compatible = "arm,gic-v3-its";
+				msi-controller;
+				#msi-cells = <1>;
+				reg = <0x0 0x30060000 0x0 0x20000>;
+			};
+
+			its_ccix: its@30080000 {
+				compatible = "arm,gic-v3-its";
+				msi-controller;
+				#msi-cells = <1>;
+				reg = <0x0 0x30080000 0x0 0x20000>;
+			};
+
+			its_pcie: its@300a0000 {
+				compatible = "arm,gic-v3-its";
+				msi-controller;
+				#msi-cells = <1>;
+				reg = <0x0 0x300a0000 0x0 0x20000>;
+			};
+		};
+
+		smmu_ccix: iommu@4f000000 {
+			compatible = "arm,smmu-v3";
+			reg = <0 0x4f000000 0 0x40000>;
+			interrupts = <GIC_SPI 228 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 229 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 230 IRQ_TYPE_EDGE_RISING>;
+			interrupt-names = "eventq", "cmdq-sync", "gerror";
+			msi-parent = <&its1 0>;
+			#iommu-cells = <1>;
+			dma-coherent;
+		};
+
+		smmu_pcie: iommu@4f400000 {
+			compatible = "arm,smmu-v3";
+			reg = <0 0x4f400000 0 0x40000>;
+			interrupts = <GIC_SPI 235 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 236 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 237 IRQ_TYPE_EDGE_RISING>;
+			interrupt-names = "eventq", "cmdq-sync", "gerror";
+			msi-parent = <&its2 0>;
+			#iommu-cells = <1>;
+			dma-coherent;
+		};
+
+		pcie_ctlr: pcie@70000000 {
+			compatible = "arm,n1sdp-pcie";
+			device_type = "pci";
+			reg = <0 0x70000000 0 0x1200000>;
+			bus-range = <0 17>;
+			linux,pci-domain = <0>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			dma-coherent;
+			ranges = <0x01000000 0x00 0x00000000 0x00 0x75200000 0x00 0x00010000>,
+				 <0x02000000 0x00 0x71200000 0x00 0x71200000 0x00 0x04000000>,
+				 <0x42000000 0x09 0x00000000 0x09 0x00000000 0x20 0x00000000>;
+			#interrupt-cells = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &gic 0 0 0 169 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 2 &gic 0 0 0 170 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 3 &gic 0 0 0 171 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 4 &gic 0 0 0 172 IRQ_TYPE_LEVEL_HIGH>;
+			msi-map = <0 &its_pcie 0 0x10000>;
+			iommu-map = <0 &smmu_pcie 0 0x10000>;
+			status = "disabled";
+		};
+
+		ccix_pcie_ctlr: pcie@68000000 {
+			compatible = "arm,n1sdp-pcie";
+			device_type = "pci";
+			reg = <0 0x68000000 0 0x1200000>;
+			bus-range = <0 17>;
+			linux,pci-domain = <1>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			dma-coherent;
+			ranges = <0x01000000 0x00 0x00000000 0x00 0x6d200000 0x00 0x00010000>,
+				 <0x02000000 0x00 0x69200000 0x00 0x69200000 0x00 0x04000000>,
+				 <0x42000000 0x29 0x00000000 0x29 0x00000000 0x20 0x00000000>;
+			#interrupt-cells = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &gic 0 0 0 201 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 2 &gic 0 0 0 202 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 3 &gic 0 0 0 203 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 4 &gic 0 0 0 204 IRQ_TYPE_LEVEL_HIGH>;
+			msi-map = <0 &its_ccix 0 0x10000>;
+			iommu-map = <0 &smmu_ccix 0 0x10000>;
+			status = "disabled";
+		};
+
+		soc_uart0: serial@2a400000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x0 0x2a400000 0x0 0x1000>;
+			interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&soc_uartclk>, <&soc_refclk100mhz>;
+			clock-names = "uartclk", "apb_pclk";
+			status = "disabled";
+		};
+	};
+};
diff --git a/fdts/optee_sp_manifest.dts b/fdts/optee_sp_manifest.dts
new file mode 100644
index 0000000..02a5ef3
--- /dev/null
+++ b/fdts/optee_sp_manifest.dts
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file is a Partition Manifest (PM) for a minimal Secure Partition (SP)
+ * that has additional optional properties defined.
+ *
+ */
+
+/dts-v1/;
+
+/ {
+	compatible = "arm,ffa-manifest-1.0";
+
+	/* Properties */
+	description = "op-tee";
+	ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */
+	uuid = <0x486178e0 0xe7f811e3 0xbc5e0002 0xa5d5c51b>;
+	id = <1>;
+	execution-ctx-count = <8>;
+	exception-level = <2>; /* S-EL1 */
+	execution-state = <0>; /* AARCH64 */
+	load-address = <0x6280000>;
+	entrypoint-offset = <0x1000>;
+	xlat-granule = <0>; /* 4KiB */
+	boot-order = <0>;
+	messaging-method = <0>; /* Direct messaging only */
+	run-time-model = <1>; /* Run to completion */
+
+	/* Boot protocol */
+	gp-register-num = <0x0>;
+};
diff --git a/fdts/stm32mp157c.dtsi b/fdts/stm32mp157c.dtsi
index 0942a91..91b20fa 100644
--- a/fdts/stm32mp157c.dtsi
+++ b/fdts/stm32mp157c.dtsi
@@ -349,6 +349,14 @@
 			};
 		};
 
+		etzpc: etzpc@5c007000 {
+			compatible = "st,stm32-etzpc";
+			reg = <0x5C007000 0x400>;
+			clocks = <&rcc TZPC>;
+			status = "disabled";
+			secure-status = "okay";
+		};
+
 		i2c6: i2c@5c009000 {
 			compatible = "st,stm32f7-i2c";
 			reg = <0x5c009000 0x400>;
diff --git a/fdts/tc0.dts b/fdts/tc0.dts
new file mode 100644
index 0000000..e736e49
--- /dev/null
+++ b/fdts/tc0.dts
@@ -0,0 +1,316 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+	compatible = "arm,tc0";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		serial0 = &soc_uart0;
+	};
+
+	chosen {
+		stdout-path = "soc_uart0:115200n8";
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&CPU0>;
+				};
+				core1 {
+					cpu = <&CPU1>;
+				};
+				core2 {
+					cpu = <&CPU2>;
+				};
+				core3 {
+					cpu = <&CPU3>;
+				};
+			};
+		};
+
+		CPU0:cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x0>;
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 0>;
+		};
+
+		CPU1:cpu@100 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x100>;
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 0>;
+		};
+
+		CPU2:cpu@200 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x200>;
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 0>;
+		};
+
+		CPU3:cpu@300 {
+			device_type = "cpu";
+			compatible = "arm,armv8";
+			reg = <0x300>;
+			enable-method = "psci";
+			clocks = <&scmi_dvfs 0>;
+		};
+
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x0 0x80000000 0x0 0x80000000>;
+	};
+
+	psci {
+		compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci";
+		method = "smc";
+	};
+
+	sram: sram@6000000 {
+		compatible = "mmio-sram";
+		reg = <0x0 0x06000000 0x0 0x8000>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x0 0x06000000 0x8000>;
+
+		cpu_scp_scmi_mem: scp-shmem@0 {
+			compatible = "arm,scmi-shmem";
+			reg = <0x0 0x80>;
+		};
+	};
+
+	mbox_db_rx: mhu@45010000 {
+		compatible = "arm,mhuv2","arm,primecell";
+		reg = <0x0 0x45010000 0x0 0x1000>;
+		clocks = <&soc_refclk100mhz>;
+		clock-names = "apb_pclk";
+		#mbox-cells = <1>;
+		interrupts = <0 316 4>;
+		interrupt-names = "mhu_rx";
+		mhu-protocol = "doorbell";
+	};
+
+	mbox_db_tx: mhu@45000000 {
+		compatible = "arm,mhuv2","arm,primecell";
+		reg = <0x0 0x45000000 0x0 0x1000>;
+		clocks = <&soc_refclk100mhz>;
+		clock-names = "apb_pclk";
+		#mbox-cells = <1>;
+		interrupt-names = "mhu_tx";
+		mhu-protocol = "doorbell";
+	};
+
+	scmi {
+		compatible = "arm,scmi";
+		method = "mailbox-doorbell";
+		mbox-names = "tx", "rx";
+		mboxes = <&mbox_db_tx 0 &mbox_db_rx 0>;
+		shmem = <&cpu_scp_scmi_mem &cpu_scp_scmi_mem>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		scmi_dvfs: protocol@13 {
+			reg = <0x13>;
+			#clock-cells = <1>;
+		};
+
+		scmi_clk: protocol@14 {
+			reg = <0x14>;
+			#clock-cells = <1>;
+		};
+	};
+
+	gic: interrupt-controller@2c010000 {
+		compatible = "arm,gic-600", "arm,gic-v3";
+		#address-cells = <2>;
+		#interrupt-cells = <3>;
+		#size-cells = <2>;
+		ranges;
+		interrupt-controller;
+		reg = <0x0 0x30000000 0 0x10000>, /* GICD */
+		      <0x0 0x30140000 0 0x200000>; /* GICR */
+		interrupts = <0x1 0x9 0x4>;
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <0x1 13 0x8>,
+			     <0x1 14 0x8>,
+			     <0x1 11 0x8>,
+			     <0x1 10 0x8>;
+	};
+
+	soc_refclk100mhz: refclk100mhz {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <100000000>;
+		clock-output-names = "apb_pclk";
+	};
+
+	soc_refclk60mhz: refclk60mhz {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <60000000>;
+		clock-output-names = "iofpga_clk";
+	};
+
+	soc_uartclk:  uartclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <50000000>;
+		clock-output-names = "uartclk";
+	};
+
+	soc_uart0: uart@7ff80000 {
+		compatible = "arm,pl011", "arm,primecell";
+		reg = <0x0 0x7ff80000 0x0 0x1000>;
+		interrupts = <0x0 116 0x4>;
+		clocks = <&soc_uartclk>, <&soc_refclk100mhz>;
+		clock-names = "uartclk", "apb_pclk";
+		status = "okay";
+	};
+
+	vencoder {
+		compatible = "drm,virtual-encoder";
+
+		port {
+			vencoder_in: endpoint {
+				remote-endpoint = <&hdlcd_out>;
+			};
+		};
+
+		display-timings {
+			panel-timing {
+				clock-frequency = <25175000>;
+				hactive = <640>;
+				vactive = <480>;
+				hfront-porch = <16>;
+				hback-porch = <48>;
+				hsync-len = <96>;
+				vfront-porch = <10>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+			};
+		};
+
+	};
+
+	hdlcd: hdlcd@7ff60000 {
+		compatible = "arm,hdlcd";
+		reg = <0x0 0x7ff60000 0x0 0x1000>;
+		interrupts = <0x0 117 0x4>;
+		clocks = <&fake_hdlcd_clk>;
+		clock-names = "pxlclk";
+		status = "ok";
+
+		port {
+			hdlcd_out: endpoint {
+				remote-endpoint = <&vencoder_in>;
+			};
+		};
+	};
+
+	fake_hdlcd_clk: fake-hdlcd-clk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25175000>;
+		clock-output-names = "pxlclk";
+	};
+
+	ethernet@18000000 {
+		compatible = "smsc,lan91c111";
+		reg = <0x0 0x18000000 0x0 0x10000>;
+		interrupts = <0 109 4>;
+	};
+
+	kmi@1c060000 {
+		compatible = "arm,pl050", "arm,primecell";
+		reg = <0x0 0x001c060000 0x0 0x1000>;
+		interrupts = <0 197 4>;
+		clocks = <&bp_clock24mhz>, <&bp_clock24mhz>;
+		clock-names = "KMIREFCLK", "apb_pclk";
+	};
+
+	kmi@1c070000 {
+		compatible = "arm,pl050", "arm,primecell";
+		reg = <0x0 0x001c070000 0x0 0x1000>;
+		interrupts = <0 103 4>;
+		clocks = <&bp_clock24mhz>, <&bp_clock24mhz>;
+		clock-names = "KMIREFCLK", "apb_pclk";
+	};
+
+	bp_clock24mhz: clock24mhz {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+		clock-output-names = "bp:clock24mhz";
+	};
+
+	virtio_block@1c130000 {
+		compatible = "virtio,mmio";
+		reg = <0x0 0x1c130000 0x0 0x200>;
+		interrupts = <0 204 4>;
+	};
+
+	dp0: display@2cc00000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "arm,mali-d71";
+		reg = <0 0x2cc00000 0 0x20000>;
+		interrupts = <0 69 4>;
+		interrupt-names = "DPU";
+		clocks = <&scmi_clk 0>;
+		clock-names = "aclk";
+		status = "disabled";
+		pl0: pipeline@0 {
+			reg = <0>;
+			clocks = <&scmi_clk 1>;
+			clock-names = "pxclk";
+			pl_id = <0>;
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				port@0 {
+					reg = <0>;
+					dp_pl0_out0: endpoint {
+						remote-endpoint = <&vencoder_in>;
+					};
+				};
+			};
+		};
+
+		pl1: pipeline@1 {
+			reg = <1>;
+			clocks = <&scmi_clk 2>;
+			clock-names = "pxclk";
+			pl_id = <1>;
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				port@0 {
+					reg = <0>;
+				};
+			};
+		};
+	};
+};
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 81e0f27..90569c3 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -211,6 +211,17 @@
 #define PARANGE_0101	U(48)
 #define PARANGE_0110	U(52)
 
+#define ID_AA64MMFR0_EL1_ECV_SHIFT		U(60)
+#define ID_AA64MMFR0_EL1_ECV_MASK		ULL(0xf)
+#define ID_AA64MMFR0_EL1_ECV_NOT_SUPPORTED	ULL(0x0)
+#define ID_AA64MMFR0_EL1_ECV_SUPPORTED		ULL(0x1)
+#define ID_AA64MMFR0_EL1_ECV_SELF_SYNCH	ULL(0x2)
+
+#define ID_AA64MMFR0_EL1_FGT_SHIFT		U(56)
+#define ID_AA64MMFR0_EL1_FGT_MASK		ULL(0xf)
+#define ID_AA64MMFR0_EL1_FGT_SUPPORTED		ULL(0x1)
+#define ID_AA64MMFR0_EL1_FGT_NOT_SUPPORTED	ULL(0x0)
+
 #define ID_AA64MMFR0_EL1_TGRAN4_SHIFT		U(28)
 #define ID_AA64MMFR0_EL1_TGRAN4_MASK		ULL(0xf)
 #define ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED	ULL(0x0)
@@ -226,6 +237,12 @@
 #define ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED	ULL(0x1)
 #define ID_AA64MMFR0_EL1_TGRAN16_NOT_SUPPORTED	ULL(0x0)
 
+/* ID_AA64MMFR1_EL1 definitions */
+#define ID_AA64MMFR1_EL1_TWED_SHIFT		U(32)
+#define ID_AA64MMFR1_EL1_TWED_MASK		ULL(0xf)
+#define ID_AA64MMFR1_EL1_TWED_SUPPORTED		ULL(0x1)
+#define ID_AA64MMFR1_EL1_TWED_NOT_SUPPORTED	ULL(0x0)
+
 /* ID_AA64MMFR2_EL1 definitions */
 #define ID_AA64MMFR2_EL1		S3_0_C0_C7_2
 
@@ -253,6 +270,9 @@
 #define MTE_IMPLEMENTED_EL0	ULL(1)	/* MTE is only implemented at EL0 */
 #define MTE_IMPLEMENTED_ELX	ULL(2)	/* MTE is implemented at all ELs */
 
+#define ID_AA64PFR1_MPAM_FRAC_SHIFT	ULL(16)
+#define ID_AA64PFR1_MPAM_FRAC_MASK	ULL(0xf)
+
 /* ID_PFR1_EL1 definitions */
 #define ID_PFR1_VIRTEXT_SHIFT	U(12)
 #define ID_PFR1_VIRTEXT_MASK	U(0xf)
@@ -312,11 +332,17 @@
 
 /* SCR definitions */
 #define SCR_RES1_BITS		((U(1) << 4) | (U(1) << 5))
+#define SCR_TWEDEL_SHIFT	U(30)
+#define SCR_TWEDEL_MASK		ULL(0xf)
+#define SCR_TWEDEn_BIT		(UL(1) << 29)
+#define SCR_ECVEN_BIT           (U(1) << 28)
+#define SCR_FGTEN_BIT           (U(1) << 27)
 #define SCR_ATA_BIT		(U(1) << 26)
 #define SCR_FIEN_BIT		(U(1) << 21)
 #define SCR_EEL2_BIT		(U(1) << 18)
 #define SCR_API_BIT		(U(1) << 17)
 #define SCR_APK_BIT		(U(1) << 16)
+#define SCR_TERR_BIT		(U(1) << 15)
 #define SCR_TWE_BIT		(U(1) << 13)
 #define SCR_TWI_BIT		(U(1) << 12)
 #define SCR_ST_BIT		(U(1) << 11)
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index 9513e97..6b5d326 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -58,4 +58,39 @@
 		ID_AA64PFR0_SEL2_MASK) == 1ULL;
 }
 
+static inline bool is_armv8_6_twed_present(void)
+{
+	return (((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_TWED_SHIFT) &
+		ID_AA64MMFR1_EL1_TWED_MASK) == ID_AA64MMFR1_EL1_TWED_SUPPORTED);
+}
+
+static inline bool is_armv8_6_fgt_present(void)
+{
+	return ((read_id_aa64mmfr0_el1() >> ID_AA64MMFR0_EL1_FGT_SHIFT) &
+		ID_AA64MMFR0_EL1_FGT_MASK) == ID_AA64MMFR0_EL1_FGT_SUPPORTED;
+}
+
+static inline unsigned long int get_armv8_6_ecv_support(void)
+{
+	return ((read_id_aa64mmfr0_el1() >> ID_AA64MMFR0_EL1_ECV_SHIFT) &
+		ID_AA64MMFR0_EL1_ECV_MASK);
+}
+
+/*
+ * Return MPAM version:
+ *
+ * 0x00: None Armv8.0 or later
+ * 0x01: v0.1 Armv8.4 or later
+ * 0x10: v1.0 Armv8.2 or later
+ * 0x11: v1.1 Armv8.4 or later
+ *
+ */
+static inline unsigned int get_mpam_version(void)
+{
+	return (unsigned int)((((read_id_aa64pfr0_el1() >>
+		ID_AA64PFR0_MPAM_SHIFT) & ID_AA64PFR0_MPAM_MASK) << 4) |
+				((read_id_aa64pfr1_el1() >>
+		ID_AA64PFR1_MPAM_FRAC_SHIFT) & ID_AA64PFR1_MPAM_FRAC_MASK));
+}
+
 #endif /* ARCH_FEATURES_H */
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 9cd1ae5..09059ca 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -358,6 +358,7 @@
 DEFINE_SYSREG_READ_FUNC(midr_el1)
 DEFINE_SYSREG_READ_FUNC(mpidr_el1)
 DEFINE_SYSREG_READ_FUNC(id_aa64mmfr0_el1)
+DEFINE_SYSREG_READ_FUNC(id_aa64mmfr1_el1)
 
 DEFINE_SYSREG_RW_FUNCS(scr_el3)
 DEFINE_SYSREG_RW_FUNCS(hcr_el2)
diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S
index 156b18a..0708de6 100644
--- a/include/arch/aarch64/el3_common_macros.S
+++ b/include/arch/aarch64/el3_common_macros.S
@@ -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
  */
@@ -9,6 +9,7 @@
 
 #include <arch.h>
 #include <asm_macros.S>
+#include <lib/xlat_tables/xlat_tables_defs.h>
 
 	/*
 	 * Helper macro to initialise EL3 registers we care about.
diff --git a/include/common/bl_common.ld.h b/include/common/bl_common.ld.h
index 97fed72..ab3391a 100644
--- a/include/common/bl_common.ld.h
+++ b/include/common/bl_common.ld.h
@@ -101,12 +101,25 @@
 		__DATA_END__ = .;			\
 	}
 
+/*
+ * .rela.dyn needs to come after .data for the read-elf utility to parse
+ * this section correctly.
+ */
+#define RELA_SECTION					\
+	.rela.dyn : ALIGN(STRUCT_ALIGN) {		\
+		__RELA_START__ = .;			\
+		*(.rela*)				\
+		__RELA_END__ = .;			\
+	}
+
+#if !(defined(IMAGE_BL31) && RECLAIM_INIT_CODE)
 #define STACK_SECTION					\
 	stacks (NOLOAD) : {				\
 		__STACKS_START__ = .;			\
 		*(tzfw_normal_stacks)			\
 		__STACKS_END__ = .;			\
 	}
+#endif
 
 /*
  * If BL doesn't use any bakery lock then __PERCPU_BAKERY_LOCK_SIZE__
diff --git a/include/common/fdt_wrappers.h b/include/common/fdt_wrappers.h
index 382651e..a571092 100644
--- a/include/common/fdt_wrappers.h
+++ b/include/common/fdt_wrappers.h
@@ -9,6 +9,8 @@
 #ifndef FDT_WRAPPERS_H
 #define FDT_WRAPPERS_H
 
+#include <libfdt_env.h>
+
 /* Number of cells, given total length in bytes. Each cell is 4 bytes long */
 #define NCELLS(len) ((len) / 4U)
 
@@ -34,4 +36,14 @@
 			      uintptr_t *base, size_t *size);
 int fdt_get_stdout_node_offset(const void *dtb);
 
+uint64_t fdtw_translate_address(const void *dtb, int bus_node,
+				uint64_t base_address);
+
+static inline uint32_t fdt_blob_size(const void *dtb)
+{
+	const uint32_t *dtb_header = dtb;
+
+	return fdt32_to_cpu(dtb_header[1]);
+}
+
 #endif /* FDT_WRAPPERS_H */
diff --git a/include/common/tbbr/cot_def.h b/include/common/tbbr/cot_def.h
index 33350a0..6ce7f80 100644
--- a/include/common/tbbr/cot_def.h
+++ b/include/common/tbbr/cot_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 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,7 +8,44 @@
 #define COT_DEF_H
 
 /* TBBR CoT definitions */
-
+#if defined(SPD_spmd)
+#define COT_MAX_VERIFIED_PARAMS		8
+#else
 #define COT_MAX_VERIFIED_PARAMS		4
+#endif
+
+/*
+ * 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
+#define PK_DER_LEN                      162
+#elif TF_MBEDTLS_KEY_SIZE == 2048
+#define PK_DER_LEN                      294
+#elif TF_MBEDTLS_KEY_SIZE == 3072
+#define PK_DER_LEN                      422
+#elif TF_MBEDTLS_KEY_SIZE == 4096
+#define PK_DER_LEN                      550
+#else
+#error "Invalid value for TF_MBEDTLS_KEY_SIZE"
+#endif
+#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
 
 #endif /* COT_DEF_H */
diff --git a/include/common/tbbr/tbbr_img_def.h b/include/common/tbbr/tbbr_img_def.h
index 1701995..b29b135 100644
--- a/include/common/tbbr/tbbr_img_def.h
+++ b/include/common/tbbr/tbbr_img_def.h
@@ -9,4 +9,20 @@
 
 #include <export/common/tbbr/tbbr_img_def_exp.h>
 
+#if defined(SPD_spmd)
+#define SIP_SP_CONTENT_CERT_ID		MAX_IMAGE_IDS
+#define SP_PKG1_ID			(MAX_IMAGE_IDS + 1)
+#define SP_PKG2_ID			(MAX_IMAGE_IDS + 2)
+#define SP_PKG3_ID			(MAX_IMAGE_IDS + 3)
+#define SP_PKG4_ID			(MAX_IMAGE_IDS + 4)
+#define SP_PKG5_ID			(MAX_IMAGE_IDS + 5)
+#define SP_PKG6_ID			(MAX_IMAGE_IDS + 6)
+#define SP_PKG7_ID			(MAX_IMAGE_IDS + 7)
+#define SP_PKG8_ID			(MAX_IMAGE_IDS + 8)
+#define MAX_SP_IDS			U(8)
+#define MAX_NUMBER_IDS			(MAX_IMAGE_IDS + MAX_SP_IDS + U(1))
+#else
+#define MAX_NUMBER_IDS			MAX_IMAGE_IDS
+#endif
+
 #endif /* TBBR_IMG_DEF_H */
diff --git a/include/drivers/arm/css/css_scp.h b/include/drivers/arm/css/css_scp.h
index f3c08c5..2b506ea 100644
--- a/include/drivers/arm/css/css_scp.h
+++ b/include/drivers/arm/css/css_scp.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
  */
@@ -40,13 +40,13 @@
 /*
  * All CSS platforms load SCP_BL2/SCP_BL2U just below BL2 (this is where BL31
  * usually resides except when ARM_BL31_IN_DRAM is
- * set). Ensure that SCP_BL2/SCP_BL2U do not overflow into tb_fw_config.
+ * set). Ensure that SCP_BL2/SCP_BL2U do not overflow into fw_config.
  */
 CASSERT(SCP_BL2_LIMIT <= BL2_BASE, assert_scp_bl2_overwrite_bl2);
 CASSERT(SCP_BL2U_LIMIT <= BL2_BASE, assert_scp_bl2u_overwrite_bl2);
 
-CASSERT(SCP_BL2_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_scp_bl2_overflow);
-CASSERT(SCP_BL2U_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_scp_bl2u_overflow);
+CASSERT(SCP_BL2_BASE >= ARM_FW_CONFIG_LIMIT, assert_scp_bl2_overflow);
+CASSERT(SCP_BL2U_BASE >= ARM_FW_CONFIG_LIMIT, assert_scp_bl2u_overflow);
 #endif
 
 #endif /* CSS_SCP_H */
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index 03596b9..18d5b73 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.h
@@ -222,6 +222,14 @@
 #define TYPER_PPI_NUM_SHIFT	U(27)
 #define TYPER_PPI_NUM_MASK	U(0x1f)
 
+/* GICR_IIDR bit definitions */
+#define IIDR_PRODUCT_ID_MASK	U(0xff000000)
+#define IIDR_VARIANT_MASK	U(0x000f0000)
+#define IIDR_REVISION_MASK	U(0x0000f000)
+#define IIDR_IMPLEMENTER_MASK	U(0x00000fff)
+#define IIDR_MODEL_MASK		(IIDR_PRODUCT_ID_MASK | \
+				 IIDR_IMPLEMENTER_MASK)
+
 /*******************************************************************************
  * GICv3 and 3.1 CPU interface registers & constants
  ******************************************************************************/
@@ -324,6 +332,18 @@
 
 static inline void gicv3_end_of_interrupt_sel1(unsigned int id)
 {
+	/*
+	 * Interrupt request deassertion from peripheral to GIC happens
+	 * by clearing interrupt condition by a write to the peripheral
+	 * register. It is desired that the write transfer is complete
+	 * before the core tries to change GIC state from 'AP/Active' to
+	 * a new state on seeing 'EOI write'.
+	 * Since ICC interface writes are not ordered against Device
+	 * memory writes, a barrier is required to ensure the ordering.
+	 * The dsb will also ensure *completion* of previous writes with
+	 * DEVICE nGnRnE attribute.
+	 */
+	dsbishst();
 	write_icc_eoir1_el1(id);
 }
 
@@ -337,6 +357,18 @@
 
 static inline void gicv3_end_of_interrupt(unsigned int id)
 {
+	/*
+	 * Interrupt request deassertion from peripheral to GIC happens
+	 * by clearing interrupt condition by a write to the peripheral
+	 * register. It is desired that the write transfer is complete
+	 * before the core tries to change GIC state from 'AP/Active' to
+	 * a new state on seeing 'EOI write'.
+	 * Since ICC interface writes are not ordered against Device
+	 * memory writes, a barrier is required to ensure the ordering.
+	 * The dsb will also ensure *completion* of previous writes with
+	 * DEVICE nGnRnE attribute.
+	 */
+	dsbishst();
 	return write_icc_eoir0_el1(id);
 }
 
diff --git a/include/drivers/arm/tzc_dmc620.h b/include/drivers/arm/tzc_dmc620.h
index e0e6760..26c444d 100644
--- a/include/drivers/arm/tzc_dmc620.h
+++ b/include/drivers/arm/tzc_dmc620.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
  */
@@ -32,16 +32,16 @@
 /* Address offsets of access address next registers */
 #define DMC620_ACC_ADDR_MIN_31_00_NEXT(region_no)	\
 		(DMC620_ACC_ADDR_MIN_31_00_NEXT_BASE +	\
-			(region_no * DMC620_ACC_ADDR_NEXT_SIZE))
+			((region_no) * DMC620_ACC_ADDR_NEXT_SIZE))
 #define DMC620_ACC_ADDR_MIN_47_32_NEXT(region_no)	\
 		(DMC620_ACC_ADDR_MIN_47_32_NEXT_BASE +	\
-			(region_no * DMC620_ACC_ADDR_NEXT_SIZE))
+			((region_no) * DMC620_ACC_ADDR_NEXT_SIZE))
 #define DMC620_ACC_ADDR_MAX_31_00_NEXT(region_no)	\
 		(DMC620_ACC_ADDR_MAX_31_00_NEXT_BASE +	\
-			(region_no * DMC620_ACC_ADDR_NEXT_SIZE))
+			((region_no) * DMC620_ACC_ADDR_NEXT_SIZE))
 #define DMC620_ACC_ADDR_MAX_47_32_NEXT(region_no)	\
 		(DMC620_ACC_ADDR_MAX_47_32_NEXT_BASE +	\
-			(region_no * DMC620_ACC_ADDR_NEXT_SIZE))
+			((region_no) * DMC620_ACC_ADDR_NEXT_SIZE))
 
 /* Number of TZC address regions in DMC-620 */
 #define DMC620_ACC_ADDR_COUNT	U(8)
diff --git a/include/drivers/auth/auth_mod.h b/include/drivers/auth/auth_mod.h
index 1dc9ff4..504e539 100644
--- a/include/drivers/auth/auth_mod.h
+++ b/include/drivers/auth/auth_mod.h
@@ -50,6 +50,24 @@
 extern const size_t cot_desc_size;
 extern unsigned int auth_img_flags[MAX_NUMBER_IDS];
 
+#if defined(SPD_spmd)
+#define DEFINE_SIP_SP_PKG(n) \
+	static const auth_img_desc_t sp_pkg##n = { \
+		.img_id = SP_PKG##n##_ID, \
+		.img_type = IMG_RAW, \
+		.parent = &sip_sp_content_cert, \
+		.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { \
+			[0] = { \
+				.type = AUTH_METHOD_HASH, \
+				.param.hash = { \
+					.data = &raw_data, \
+					.hash = &sp_pkg##n##_hash \
+				} \
+			} \
+		} \
+	}
+#endif
+
 #endif /* TRUSTED_BOARD_BOOT */
 
 #endif /* AUTH_MOD_H */
diff --git a/include/drivers/auth/tbbr_cot_common.h b/include/drivers/auth/tbbr_cot_common.h
new file mode 100644
index 0000000..a51faee
--- /dev/null
+++ b/include/drivers/auth/tbbr_cot_common.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TBBR_COT_COMMON_H
+#define TBBR_COT_COMMON_H
+
+#include <drivers/auth/auth_mod.h>
+
+extern unsigned char tb_fw_hash_buf[HASH_DER_LEN];
+extern unsigned char scp_fw_hash_buf[HASH_DER_LEN];
+extern unsigned char nt_world_bl_hash_buf[HASH_DER_LEN];
+
+extern auth_param_type_desc_t trusted_nv_ctr;
+extern auth_param_type_desc_t subject_pk;
+extern auth_param_type_desc_t sig;
+extern auth_param_type_desc_t sig_alg;
+extern auth_param_type_desc_t raw_data;
+
+extern auth_param_type_desc_t tb_fw_hash;
+extern auth_param_type_desc_t tb_fw_config_hash;
+extern auth_param_type_desc_t fw_config_hash;
+
+extern const auth_img_desc_t trusted_boot_fw_cert;
+extern const auth_img_desc_t hw_config;
+
+#endif /* TBBR_COT_COMMON_H */
diff --git a/include/drivers/brcm/scp.h b/include/drivers/brcm/scp.h
index b7b5bad..7806314 100644
--- a/include/drivers/brcm/scp.h
+++ b/include/drivers/brcm/scp.h
@@ -4,7 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef SCP_H_
+#ifndef SCP_H
 #define SCP_H
 
 #include <stdint.h>
diff --git a/include/drivers/marvell/aro.h b/include/drivers/marvell/aro.h
index c16f625..4d1094a 100644
--- a/include/drivers/marvell/aro.h
+++ b/include/drivers/marvell/aro.h
@@ -21,11 +21,13 @@
 	DDR_FREQ_SAR
 };
 
+#include <mvebu_def.h>
+
 enum cpu_clock_freq_mode {
 	CPU_2000_DDR_1200_RCLK_1200 = 0x0,
 	CPU_2000_DDR_1050_RCLK_1050 = 0x1,
 	CPU_1600_DDR_800_RCLK_800   = 0x4,
-	CPU_1800_DDR_1200_RCLK_1200 = 0x6,
+	CPU_2200_DDR_1200_RCLK_1200 = 0x6,
 	CPU_1800_DDR_1050_RCLK_1050 = 0x7,
 	CPU_1600_DDR_900_RCLK_900   = 0x0B,
 	CPU_1600_DDR_1050_RCLK_1050 = 0x0D,
diff --git a/include/drivers/marvell/cache_llc.h b/include/drivers/marvell/cache_llc.h
index 85babb8..d6dd653 100644
--- a/include/drivers/marvell/cache_llc.h
+++ b/include/drivers/marvell/cache_llc.h
@@ -13,19 +13,35 @@
 #define CACHE_LLC_H
 
 #define LLC_CTRL(ap)			(MVEBU_LLC_BASE(ap) + 0x100)
+#define LLC_SECURE_CTRL(ap)		(MVEBU_LLC_BASE(ap) + 0x10C)
 #define LLC_SYNC(ap)			(MVEBU_LLC_BASE(ap) + 0x700)
-#define L2X0_INV_WAY(ap)		(MVEBU_LLC_BASE(ap) + 0x77C)
-#define L2X0_CLEAN_WAY(ap)		(MVEBU_LLC_BASE(ap) + 0x7BC)
-#define L2X0_CLEAN_INV_WAY(ap)		(MVEBU_LLC_BASE(ap) + 0x7FC)
-#define LLC_TC0_LOCK(ap)		(MVEBU_LLC_BASE(ap) + 0x920)
+#define LLC_BANKED_MNT_AHR(ap)		(MVEBU_LLC_BASE(ap) + 0x724)
+#define LLC_INV_WAY(ap)			(MVEBU_LLC_BASE(ap) + 0x77C)
+#define LLC_BLK_ALOC(ap)		(MVEBU_LLC_BASE(ap) + 0x78c)
+#define LLC_CLEAN_WAY(ap)		(MVEBU_LLC_BASE(ap) + 0x7BC)
+#define LLC_CLEAN_INV_WAY(ap)		(MVEBU_LLC_BASE(ap) + 0x7FC)
+#define LLC_TCN_LOCK(ap, tc)		(MVEBU_LLC_BASE(ap) + 0x920 + 4 * (tc))
 
 #define MASTER_LLC_CTRL			LLC_CTRL(MVEBU_AP0)
-#define MASTER_L2X0_INV_WAY		L2X0_INV_WAY(MVEBU_AP0)
-#define MASTER_LLC_TC0_LOCK		LLC_TC0_LOCK(MVEBU_AP0)
+#define MASTER_LLC_INV_WAY		LLC_INV_WAY(MVEBU_AP0)
+#define MASTER_LLC_TC0_LOCK		LLC_TCN_LOCK(MVEBU_AP0, 0)
 
 #define LLC_CTRL_EN			1
 #define LLC_EXCLUSIVE_EN		0x100
-#define LLC_WAY_MASK			0xFFFFFFFF
+#define LLC_ALL_WAYS_MASK		0xFFFFFFFF
+
+/* AP806/AP807 - 1MB 8-ways LLC */
+#define LLC_WAYS			8
+#define LLC_WAY_MASK			((1 << LLC_WAYS) - 1)
+#define LLC_SIZE			(1024 * 1024)
+#define LLC_WAY_SIZE			(LLC_SIZE / LLC_WAYS)
+#define LLC_TC_NUM			15
+
+#define LLC_BLK_ALOC_WAY_ID(way)	((way) & 0x1f)
+#define LLC_BLK_ALOC_WAY_DATA_DSBL	(0x0 << 6)
+#define LLC_BLK_ALOC_WAY_DATA_CLR	(0x1 << 6)
+#define LLC_BLK_ALOC_WAY_DATA_SET	(0x3 << 6)
+#define LLC_BLK_ALOC_BASE_ADDR(addr)	((addr) & ~(LLC_WAY_SIZE - 1))
 
 #ifndef __ASSEMBLER__
 void llc_cache_sync(int ap_index);
@@ -36,6 +52,11 @@
 void llc_enable(int ap_index, int excl_mode);
 int llc_is_exclusive(int ap_index);
 void llc_runtime_enable(int ap_index);
-#endif
+#if LLC_SRAM
+int llc_sram_enable(int ap_index, int size);
+void llc_sram_disable(int ap_index);
+int llc_sram_test(int ap_index, int size, char *msg);
+#endif /* LLC_SRAM */
+#endif /* __ASSEMBLY__ */
 
 #endif /* CACHE_LLC_H */
diff --git a/include/drivers/marvell/ccu.h b/include/drivers/marvell/ccu.h
index b0d1ec9..413ffb9 100644
--- a/include/drivers/marvell/ccu.h
+++ b/include/drivers/marvell/ccu.h
@@ -46,6 +46,7 @@
 void ccu_dram_target_set(int ap_index, uint32_t target);
 void ccu_save_win_all(int ap_id);
 void ccu_restore_win_all(int ap_id);
+int ccu_is_win_enabled(int ap_index, uint32_t win_id);
 #endif
 
 #endif /* CCU_H */
diff --git a/include/drivers/marvell/mci.h b/include/drivers/marvell/mci.h
index 8ef0234..af5d620 100644
--- a/include/drivers/marvell/mci.h
+++ b/include/drivers/marvell/mci.h
@@ -10,7 +10,7 @@
 #ifndef MCI_H
 #define MCI_H
 
-int mci_initialize(int mci_index);
+int mci_link_tune(int mci_index);
 void mci_turn_link_down(void);
 void mci_turn_link_on(void);
 int mci_get_link_status(void);
diff --git a/include/drivers/marvell/mochi/ap_setup.h b/include/drivers/marvell/mochi/ap_setup.h
index eff4473..5b0e75f 100644
--- a/include/drivers/marvell/mochi/ap_setup.h
+++ b/include/drivers/marvell/mochi/ap_setup.h
@@ -13,5 +13,6 @@
 void ap_init(void);
 void ap_ble_init(void);
 int ap_get_count(void);
+void update_cp110_default_win(int cp_id);
 
 #endif /* AP_SETUP_H */
diff --git a/include/drivers/measured_boot/event_log.h b/include/drivers/measured_boot/event_log.h
new file mode 100644
index 0000000..10dfbb3
--- /dev/null
+++ b/include/drivers/measured_boot/event_log.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EVENT_LOG_H
+#define EVENT_LOG_H
+
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <drivers/measured_boot/tcg.h>
+
+/*
+ * Set Event Log debug level to one of:
+ *
+ * LOG_LEVEL_ERROR
+ * LOG_LEVEL_INFO
+ * LOG_LEVEL_WARNING
+ * LOG_LEVEL_VERBOSE
+ */
+#define	EVENT_LOG_LEVEL	LOG_LEVEL_INFO
+
+#if EVENT_LOG_LEVEL   == LOG_LEVEL_ERROR
+#define	LOG_EVENT	ERROR
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_NOTICE
+#define	LOG_EVENT	NOTICE
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_WARNING
+#define	LOG_EVENT	WARN
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_INFO
+#define	LOG_EVENT	INFO
+#elif EVENT_LOG_LEVEL == LOG_LEVEL_VERBOSE
+#define	LOG_EVENT	VERBOSE
+#else
+#error "Not supported EVENT_LOG_LEVEL"
+#endif
+
+/* Number of hashing algorithms supported */
+#define HASH_ALG_COUNT	1U
+
+#define	INVALID_ID	MAX_NUMBER_IDS
+
+#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
+
+#define BL2_STRING			"BL_2"
+#define BL31_STRING			"BL_31"
+#define BL32_STRING			"BL_32"
+#define	BL32_EXTRA1_IMAGE_STRING	"BL32_EXTRA1_IMAGE"
+#define	BL32_EXTRA2_IMAGE_STRING	"BL32_EXTRA2_IMAGE"
+#define BL33_STRING			"BL_33"
+#define GPT_IMAGE_STRING		"GPT"
+#define HW_CONFIG_STRING		"HW_CONFIG"
+#define NT_FW_CONFIG_STRING		"NT_FW_CONFIG"
+#define SCP_BL2_IMAGE_STRING		"SCP_BL2_IMAGE"
+#define SOC_FW_CONFIG_STRING		"SOC_FW_CONFIG"
+#define STM32_IMAGE_STRING		"STM32"
+#define	TOS_FW_CONFIG_STRING		"TOS_FW_CONFIG"
+
+typedef struct {
+	unsigned int id;
+	const char *name;
+	unsigned int pcr;
+} image_data_t;
+
+typedef struct {
+	const image_data_t *images_data;
+	int (*set_nt_fw_info)(uintptr_t config_base,
+#ifdef SPD_opteed
+				uintptr_t log_addr,
+#endif
+				size_t log_size, uintptr_t *ns_log_addr);
+	int (*set_tos_fw_info)(uintptr_t config_base, uintptr_t log_addr,
+				size_t log_size);
+} measured_boot_data_t;
+
+#define	ID_EVENT_SIZE	(sizeof(id_event_headers_t) + \
+			(sizeof(id_event_algorithm_size_t) * HASH_ALG_COUNT) + \
+			sizeof(id_event_struct_data_t))
+
+#define	LOC_EVENT_SIZE	(sizeof(event2_header_t) + \
+			sizeof(tpmt_ha) + TCG_DIGEST_SIZE + \
+			sizeof(event2_data_t) + \
+			sizeof(startup_locality_event_t))
+
+#define	LOG_MIN_SIZE	(ID_EVENT_SIZE + LOC_EVENT_SIZE)
+
+#define EVENT2_HDR_SIZE	(sizeof(event2_header_t) + \
+			sizeof(tpmt_ha) + TCG_DIGEST_SIZE + \
+			sizeof(event2_data_t))
+
+/* Functions' declarations */
+void event_log_init(void);
+int event_log_finalise(uint8_t **log_addr, size_t *log_size);
+void dump_event_log(uint8_t *log_addr, size_t log_size);
+const measured_boot_data_t *plat_get_measured_boot_data(void);
+int tpm_record_measurement(uintptr_t data_base, uint32_t data_size,
+			   uint32_t data_id);
+#endif /* EVENT_LOG_H */
diff --git a/include/drivers/measured_boot/measured_boot.h b/include/drivers/measured_boot/measured_boot.h
new file mode 100644
index 0000000..f8769ab
--- /dev/null
+++ b/include/drivers/measured_boot/measured_boot.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MEASURED_BOOT_H
+#define MEASURED_BOOT_H
+
+#include <stdint.h>
+
+#include <drivers/measured_boot/event_log.h>
+
+/* Platform specific table of image IDs, names and PCRs */
+extern const image_data_t images_data[];
+
+/* Functions' declarations */
+void measured_boot_init(void);
+void measured_boot_finish(void);
+
+#endif /* MEASURED_BOOT_H */
diff --git a/include/drivers/measured_boot/tcg.h b/include/drivers/measured_boot/tcg.h
new file mode 100644
index 0000000..ab27a08
--- /dev/null
+++ b/include/drivers/measured_boot/tcg.h
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TCG_H
+#define TCG_H
+
+#include <stdint.h>
+
+#define TCG_ID_EVENT_SIGNATURE_03	"Spec ID Event03"
+#define TCG_STARTUP_LOCALITY_SIGNATURE	"StartupLocality"
+
+#define TCG_SPEC_VERSION_MAJOR_TPM2   2
+#define TCG_SPEC_VERSION_MINOR_TPM2   0
+#define TCG_SPEC_ERRATA_TPM2          2
+
+/*
+ * Event types
+ * Ref. Table 9 Events
+ * TCG PC Client Platform Firmware Profile Specification.
+ */
+#define EV_PREBOOT_CERT				U(0x00000000)
+#define EV_POST_CODE				U(0x00000001)
+#define	EV_UNUSED				U(0x00000002)
+#define EV_NO_ACTION				U(0x00000003)
+#define EV_SEPARATOR				U(0x00000004)
+#define EV_ACTION				U(0x00000005)
+#define	EV_EVENT_TAG				U(0x00000006)
+#define EV_S_CRTM_CONTENTS			U(0x00000007)
+#define EV_S_CRTM_VERSION			U(0x00000008)
+#define EV_CPU_MICROCODE			U(0x00000009)
+#define EV_PLATFORM_CONFIG_FLAGS		U(0x0000000A)
+#define EV_TABLE_OF_DEVICES			U(0x0000000B)
+#define EV_COMPACT_HASH				U(0x0000000C)
+#define	EV_IPL					U(0x0000000D)
+#define	EV_IPL_PARTITION_DATA			U(0x0000000E)
+#define EV_NONHOST_CODE				U(0x0000000F)
+#define EV_NONHOST_CONFIG			U(0x00000010)
+#define EV_NONHOST_INFO				U(0x00000011)
+#define EV_OMIT_BOOT_DEVICE_EVENTS		U(0x00000012)
+#define	EV_EFI_EVENT_BASE			U(0x80000000)
+#define	EV_EFI_VARIABLE_DRIVER_CONFIG		U(0x80000001)
+#define EV_EFI_VARIABLE_BOOT			U(0x80000002)
+#define	EV_EFI_BOOT_SERVICES_APPLICATION	U(0x80000003)
+#define	EV_EFI_BOOT_SERVICES_DRIVER		U(0x80000004)
+#define	EV_EFI_RUNTIME_SERVICES_DRIVER		U(0x80000005)
+#define	EV_EFI_GPT_EVENT			U(0x80000006)
+#define	EV_EFI_ACTION				U(0x80000007)
+#define	EV_EFI_PLATFORM_FIRMWARE_BLOB		U(0x80000008)
+#define	EV_EFI_HANDOFF_TABLES			U(0x80000009)
+#define	EV_EFI_HCRTM_EVENT			U(0x80000010)
+#define	EV_EFI_VARIABLE_AUTHORITY		U(0x800000E0)
+
+/*
+ * TPM_ALG_ID constants.
+ * Ref. Table 9 - Definition of (UINT16) TPM_ALG_ID Constants
+ * Trusted Platform Module Library. Part 2: Structures
+ */
+#define TPM_ALG_SHA256		0x000B
+#define TPM_ALG_SHA384		0x000C
+#define TPM_ALG_SHA512		0x000D
+
+/* TCG Platform Type */
+#define PLATFORM_CLASS_CLIENT   0
+#define PLATFORM_CLASS_SERVER   1
+
+/* SHA digest sizes in bytes */
+#define SHA1_DIGEST_SIZE	20
+#define SHA256_DIGEST_SIZE	32
+#define SHA384_DIGEST_SIZE	48
+#define SHA512_DIGEST_SIZE	64
+
+enum {
+	/*
+	 * SRTM, BIOS, Host Platform Extensions, Embedded
+	 * Option ROMs and PI Drivers
+	 */
+	PCR_0 = 0,
+	/* Host Platform Configuration */
+	PCR_1,
+	/* UEFI driver and application Code */
+	PCR_2,
+	/* UEFI driver and application Configuration and Data */
+	PCR_3,
+	/* UEFI Boot Manager Code (usually the MBR) and Boot Attempts */
+	PCR_4,
+	/*
+	 * Boot Manager Code Configuration and Data (for use
+	 * by the Boot Manager Code) and GPT/Partition Table
+	 */
+	PCR_5,
+	/* Host Platform Manufacturer Specific */
+	PCR_6,
+	/* Secure Boot Policy */
+	PCR_7,
+	/* 8-15: Defined for use by the Static OS */
+	PCR_8,
+	/* Debug */
+	PCR_16 = 16
+};
+
+#pragma pack(push, 1)
+
+/*
+ * PCR Event Header
+ * TCG EFI Protocol Specification
+ * 5.3 Event Log Header
+ */
+typedef struct {
+	/* PCRIndex:
+	 * The PCR Index to which this event is extended
+	 */
+	uint32_t	pcr_index;
+
+	/* EventType:
+	 * SHALL be an EV_NO_ACTION event
+	 */
+	uint32_t	event_type;
+
+	/* SHALL be 20 Bytes of 0x00 */
+	uint8_t		digest[SHA1_DIGEST_SIZE];
+
+	/* The size of the event */
+	uint32_t	event_size;
+
+	/* SHALL be a TCG_EfiSpecIdEvent */
+	uint8_t		event[];	/* [event_data_size] */
+} tcg_pcr_event_t;
+
+/*
+ * Log Header Entry Data
+ * Ref. Table 14 TCG_EfiSpecIdEventAlgorithmSize
+ * TCG PC Client Platform Firmware Profile 9.4.5.1
+ */
+typedef struct {
+	/* Algorithm ID (hashAlg) of the Hash used by BIOS */
+	uint16_t	algorithm_id;
+
+	/* The size of the digest produced by the implemented Hash algorithm */
+	uint16_t	digest_size;
+} id_event_algorithm_size_t;
+
+/*
+ * TCG_EfiSpecIdEvent structure
+ * Ref. Table 15 TCG_EfiSpecIdEvent
+ * TCG PC Client Platform Firmware Profile 9.4.5.1
+ */
+typedef struct {
+	/*
+	 * The NUL-terminated ASCII string "Spec ID Event03".
+	 * SHALL be set to {0x53, 0x70, 0x65, 0x63, 0x20, 0x49, 0x44,
+	 * 0x20, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x33, 0x00}.
+	 */
+	uint8_t		signature[16];
+
+	/*
+	 * The value for the Platform Class.
+	 * The enumeration is defined in the TCG ACPI Specification Client
+	 * Common Header.
+	 */
+	uint32_t	platform_class;
+
+	/*
+	 * The PC Client Platform Profile Specification minor version number
+	 * this BIOS supports.
+	 * Any BIOS supporting this version (2.0) MUST set this value to 0x00.
+	 */
+	uint8_t		spec_version_minor;
+
+	/*
+	 * The PC Client Platform Profile Specification major version number
+	 * this BIOS supports.
+	 * Any BIOS supporting this version (2.0) MUST set this value to 0x02.
+	 */
+	uint8_t		spec_version_major;
+
+	/*
+	 * The PC Client Platform Profile Specification errata version number
+	 * this BIOS supports.
+	 * Any BIOS supporting this version (2.0) MUST set this value to 0x02.
+	 */
+	uint8_t		spec_errata;
+
+	/*
+	 * Specifies the size of the UINTN fields used in various data
+	 * structures used in this specification.
+	 * 0x01 indicates UINT32 and 0x02 indicates UINT64.
+	 */
+	uint8_t		uintn_size;
+
+	/*
+	 * The number of Hash algorithms in the digestSizes field.
+	 * This field MUST be set to a value of 0x01 or greater.
+	 */
+	uint32_t	number_of_algorithms;
+
+	/*
+	 * Each TCG_EfiSpecIdEventAlgorithmSize SHALL contain an algorithmId
+	 * and digestSize for each hash algorithm used in the TCG_PCR_EVENT2
+	 * structure, the first of which is a Hash algorithmID and the second
+	 * is the size of the respective digest.
+	 */
+	id_event_algorithm_size_t    digest_size[]; /* number_of_algorithms */
+} id_event_struct_header_t;
+
+typedef struct {
+	/*
+	 * Size in bytes of the VendorInfo field.
+	 * Maximum value MUST be FFh bytes.
+	 */
+	uint8_t		vendor_info_size;
+
+	/*
+	 * Provided for use by Platform Firmware implementer. The value might
+	 * be used, for example, to provide more detailed information about the
+	 * specific BIOS such as BIOS revision numbers, etc. The values within
+	 * this field are not standardized and are implementer-specific.
+	 * Platform-specific or -unique information MUST NOT be provided in
+	 * this field.
+	 *
+	 */
+	uint8_t		vendor_info[];	/* [vendorInfoSize] */
+} id_event_struct_data_t;
+
+typedef struct {
+	id_event_struct_header_t	struct_header;
+	id_event_struct_data_t		struct_data;
+} id_event_struct_t;
+
+typedef struct {
+	tcg_pcr_event_t			header;
+	id_event_struct_header_t	struct_header;
+} id_event_headers_t;
+
+/* TPMT_HA Structure */
+typedef struct {
+	/* Selector of the hash contained in the digest that implies
+	 * the size of the digest
+	 */
+	uint16_t	algorithm_id;	/* AlgorithmId */
+
+	/* Digest, depends on AlgorithmId */
+	uint8_t		digest[];	/* Digest[] */
+} tpmt_ha;
+
+/*
+ * TPML_DIGEST_VALUES Structure
+ */
+typedef struct {
+	/* The number of digests in the list */
+	uint32_t	count;			/* Count */
+
+	/* The list of tagged digests, as sent to the TPM as part of a
+	 * TPM2_PCR_Extend or as received from a TPM2_PCR_Event command
+	 */
+	tpmt_ha		digests[];		/* Digests[Count] */
+} tpml_digest_values;
+
+/*
+ * TCG_PCR_EVENT2 header
+ */
+typedef struct {
+	 /* The PCR Index to which this event was extended */
+	uint32_t		pcr_index;	/* PCRIndex */
+
+	/* Type of event */
+	uint32_t		event_type;	/* EventType */
+
+	/* Digests:
+	 * A counted list of tagged digests, which contain the digest of
+	 * the event data (or external data) for all active PCR banks
+	 */
+	tpml_digest_values	digests;	/* Digests */
+} event2_header_t;
+
+typedef struct event2_data {
+	/* The size of the event data */
+	uint32_t		event_size;	/* EventSize */
+
+	/* The data of the event */
+	uint8_t			event[];	/* Event[EventSize] */
+} event2_data_t;
+
+/*
+ * Startup Locality Event
+ * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3
+ */
+typedef struct {
+	/*
+	 * The NUL-terminated ASCII string "StartupLocality" SHALL be
+	 * set to {0x53 0x74 0x61 0x72 0x74 0x75 0x70 0x4C 0x6F 0x63
+	 * 0x61 0x6C 0x69 0x74 0x79 0x00}
+	 */
+	uint8_t		signature[16];
+
+	/* The Locality Indicator which sent the TPM2_Startup command */
+	uint8_t		startup_locality;
+} startup_locality_event_t;
+
+#pragma pack(pop)
+
+#endif /* TCG_H */
diff --git a/include/drivers/st/etzpc.h b/include/drivers/st/etzpc.h
new file mode 100644
index 0000000..6e3fec1
--- /dev/null
+++ b/include/drivers/st/etzpc.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DRIVERS_ST_ETZPC_H
+#define DRIVERS_ST_ETZPC_H
+
+/* Define security level for each peripheral (DECPROT) */
+enum etzpc_decprot_attributes {
+	ETZPC_DECPROT_S_RW = 0,
+	ETZPC_DECPROT_NS_R_S_W = 1,
+	ETZPC_DECPROT_MCU_ISOLATION = 2,
+	ETZPC_DECPROT_NS_RW = 3,
+	ETZPC_DECPROT_MAX = 4,
+};
+
+void etzpc_configure_decprot(uint32_t decprot_id,
+			     enum etzpc_decprot_attributes decprot_attr);
+enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id);
+void etzpc_lock_decprot(uint32_t decprot_id);
+
+void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value);
+uint16_t etzpc_get_tzma(uint32_t tzma_id);
+void etzpc_lock_tzma(uint32_t tzma_id);
+bool etzpc_get_lock_tzma(uint32_t tzma_id);
+
+uint8_t etzpc_get_num_per_sec(void);
+uint8_t etzpc_get_revision(void);
+uintptr_t etzpc_get_base_address(void);
+
+int etzpc_init(void);
+
+#endif /* DRIVERS_ST_ETZPC_H */
diff --git a/include/drivers/st/scmi-msg.h b/include/drivers/st/scmi-msg.h
new file mode 100644
index 0000000..a9a99cf
--- /dev/null
+++ b/include/drivers/st/scmi-msg.h
@@ -0,0 +1,207 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019, Linaro Limited
+ */
+
+#ifndef SCMI_MSG_H
+#define SCMI_MSG_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/* Minimum size expected for SMT based shared memory message buffers */
+#define SMT_BUF_SLOT_SIZE	128U
+
+/* A channel abstract a communication path between agent and server */
+struct scmi_msg_channel;
+
+/*
+ * struct scmi_msg_channel - Shared memory buffer for a agent-to-server channel
+ *
+ * @shm_addr: Address of the shared memory for the SCMI channel
+ * @shm_size: Byte size of the shared memory for the SCMI channel
+ * @busy: True when channel is busy, flase when channel is free
+ * @agent_name: Agent name, SCMI protocol exposes 16 bytes max, or NULL
+ */
+struct scmi_msg_channel {
+	uintptr_t shm_addr;
+	size_t shm_size;
+	bool busy;
+	const char *agent_name;
+};
+
+/*
+ * Initialize SMT memory buffer, called by platform at init for each
+ * agent channel using the SMT header format.
+ *
+ * @chan: Pointer to the channel shared memory to be initialized
+ */
+void scmi_smt_init_agent_channel(struct scmi_msg_channel *chan);
+
+/*
+ * Process SMT formatted message in a fastcall SMC execution context.
+ * Called by platform on SMC entry. When returning, output message is
+ * available in shared memory for agent to read the response.
+ *
+ * @agent_id: SCMI agent ID the SMT belongs to
+ */
+void scmi_smt_fastcall_smc_entry(unsigned int agent_id);
+
+/*
+ * Process SMT formatted message in a secure interrupt execution context.
+ * Called by platform interrupt handler. When returning, output message is
+ * available in shared memory for agent to read the response.
+ *
+ * @agent_id: SCMI agent ID the SMT belongs to
+ */
+void scmi_smt_interrupt_entry(unsigned int agent_id);
+
+/* Platform callback functions */
+
+/*
+ * Return the SCMI channel related to an agent
+ * @agent_id: SCMI agent ID
+ * Return a pointer to channel on success, NULL otherwise
+ */
+struct scmi_msg_channel *plat_scmi_get_channel(unsigned int agent_id);
+
+/*
+ * Return how many SCMI protocols supported by the platform
+ * According to the SCMI specification, this function does not target
+ * a specific agent ID and shall return all platform known capabilities.
+ */
+size_t plat_scmi_protocol_count(void);
+
+/*
+ * Get the count and list of SCMI protocols (but base) supported for an agent
+ *
+ * @agent_id: SCMI agent ID
+ * Return a pointer to a null terminated array supported protocol IDs.
+ */
+const uint8_t *plat_scmi_protocol_list(unsigned int agent_id);
+
+/* Get the name of the SCMI vendor for the platform */
+const char *plat_scmi_vendor_name(void);
+
+/* Get the name of the SCMI sub-vendor for the platform */
+const char *plat_scmi_sub_vendor_name(void);
+
+/* Handlers for SCMI Clock protocol services */
+
+/*
+ * Return number of clock controllers for an agent
+ * @agent_id: SCMI agent ID
+ * Return number of clock controllers
+ */
+size_t plat_scmi_clock_count(unsigned int agent_id);
+
+/*
+ * Get clock controller string ID (aka name)
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI clock ID
+ * Return pointer to name or NULL
+ */
+const char *plat_scmi_clock_get_name(unsigned int agent_id,
+				     unsigned int scmi_id);
+
+/*
+ * Get clock possible rate as an array of frequencies in Hertz.
+ *
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI clock ID
+ * @rates: If NULL, function returns, else output rates array
+ * @nb_elts: Array size of @rates.
+ * Return an SCMI compliant error code
+ */
+int32_t plat_scmi_clock_rates_array(unsigned int agent_id, unsigned int scmi_id,
+				    unsigned long *rates, size_t *nb_elts);
+
+/*
+ * Get clock possible rate as range with regular steps in Hertz
+ *
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI clock ID
+ * @min_max_step: 3 cell array for min, max and step rate data
+ * Return an SCMI compliant error code
+ */
+int32_t plat_scmi_clock_rates_by_step(unsigned int agent_id,
+				      unsigned int scmi_id,
+				      unsigned long *min_max_step);
+
+/*
+ * Get clock rate in Hertz
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI clock ID
+ * Return clock rate or 0 if not supported
+ */
+unsigned long plat_scmi_clock_get_rate(unsigned int agent_id,
+				       unsigned int scmi_id);
+
+/*
+ * Set clock rate in Hertz
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI clock ID
+ * @rate: Target clock frequency in Hertz
+ * Return a compliant SCMI error code
+ */
+int32_t plat_scmi_clock_set_rate(unsigned int agent_id, unsigned int scmi_id,
+				 unsigned long rate);
+
+/*
+ * Get clock state (enabled or disabled)
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI clock ID
+ * Return 1 if clock is enabled, 0 if disables, or a negative SCMI error code
+ */
+int32_t plat_scmi_clock_get_state(unsigned int agent_id, unsigned int scmi_id);
+
+/*
+ * Get clock state (enabled or disabled)
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI clock ID
+ * @enable_not_disable: Enable clock if true, disable clock otherwise
+ * Return a compliant SCMI error code
+ */
+int32_t plat_scmi_clock_set_state(unsigned int agent_id, unsigned int scmi_id,
+				  bool enable_not_disable);
+
+/* Handlers for SCMI Reset Domain protocol services */
+
+/*
+ * Return number of reset domains for the agent
+ * @agent_id: SCMI agent ID
+ * Return number of reset domains
+ */
+size_t plat_scmi_rstd_count(unsigned int agent_id);
+
+/*
+ * Get reset domain string ID (aka name)
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI reset domain ID
+ * Return pointer to name or NULL
+ */
+const char *plat_scmi_rstd_get_name(unsigned int agent_id, unsigned int scmi_id);
+
+/*
+ * Perform a reset cycle on a target reset domain
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI reset domain ID
+ * @state: Target reset state (see SCMI specification, 0 means context loss)
+ * Return a compliant SCMI error code
+ */
+int32_t plat_scmi_rstd_autonomous(unsigned int agent_id, unsigned int scmi_id,
+				  unsigned int state);
+
+/*
+ * Assert or deassert target reset domain
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI reset domain ID
+ * @assert_not_deassert: Assert domain if true, otherwise deassert domain
+ * Return a compliant SCMI error code
+ */
+int32_t plat_scmi_rstd_set_state(unsigned int agent_id, unsigned int scmi_id,
+				 bool assert_not_deassert);
+
+#endif /* SCMI_MSG_H */
diff --git a/include/drivers/st/scmi.h b/include/drivers/st/scmi.h
new file mode 100644
index 0000000..ac5dc38
--- /dev/null
+++ b/include/drivers/st/scmi.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
+ */
+#ifndef SCMI_MSG_SCMI_H
+#define SCMI_MSG_SCMI_H
+
+#define SCMI_PROTOCOL_ID_BASE			0x10U
+#define SCMI_PROTOCOL_ID_POWER_DOMAIN		0x11U
+#define SCMI_PROTOCOL_ID_SYS_POWER		0x12U
+#define SCMI_PROTOCOL_ID_PERF			0x13U
+#define SCMI_PROTOCOL_ID_CLOCK			0x14U
+#define SCMI_PROTOCOL_ID_SENSOR			0x15U
+#define SCMI_PROTOCOL_ID_RESET_DOMAIN		0x16U
+
+/* SCMI error codes reported to agent through server-to-agent messages */
+#define SCMI_SUCCESS			0
+#define SCMI_NOT_SUPPORTED		(-1)
+#define SCMI_INVALID_PARAMETERS		(-2)
+#define SCMI_DENIED			(-3)
+#define SCMI_NOT_FOUND			(-4)
+#define SCMI_OUT_OF_RANGE		(-5)
+#define SCMI_BUSY			(-6)
+#define SCMI_COMMS_ERROR		(-7)
+#define SCMI_GENERIC_ERROR		(-8)
+#define SCMI_HARDWARE_ERROR		(-9)
+#define SCMI_PROTOCOL_ERROR		(-10)
+
+#endif /* SCMI_MSG_SCMI_H */
diff --git a/include/drivers/st/stm32mp1_clk.h b/include/drivers/st/stm32mp1_clk.h
index 1ebd39f..c46892b 100644
--- a/include/drivers/st/stm32mp1_clk.h
+++ b/include/drivers/st/stm32mp1_clk.h
@@ -59,4 +59,7 @@
 
 void stm32mp1_stgen_increment(unsigned long long offset_in_ms);
 
+#ifdef STM32MP_SHARED_RESOURCES
+void stm32mp1_register_clock_parents_secure(unsigned long id);
+#endif
 #endif /* STM32MP1_CLK_H */
diff --git a/include/drivers/st/stm32mp1_rcc.h b/include/drivers/st/stm32mp1_rcc.h
index 4b4aac8..2ffc3b2 100644
--- a/include/drivers/st/stm32mp1_rcc.h
+++ b/include/drivers/st/stm32mp1_rcc.h
@@ -250,6 +250,8 @@
 #define RCC_MPCKSELR_HSE		0x00000001
 #define RCC_MPCKSELR_PLL		0x00000002
 #define RCC_MPCKSELR_PLL_MPUDIV		0x00000003
+#define RCC_MPCKSELR_MPUSRC_MASK	GENMASK(1, 0)
+#define RCC_MPCKSELR_MPUSRC_SHIFT	0
 
 /* Values of RCC_ASSCKSELR register */
 #define RCC_ASSCKSELR_HSI		0x00000000
@@ -266,6 +268,8 @@
 #define RCC_CPERCKSELR_HSI		0x00000000
 #define RCC_CPERCKSELR_CSI		0x00000001
 #define RCC_CPERCKSELR_HSE		0x00000002
+#define RCC_CPERCKSELR_PERSRC_MASK	GENMASK(1, 0)
+#define RCC_CPERCKSELR_PERSRC_SHIFT	0
 
 /* Used for most of DIVR register: max div for RTC */
 #define RCC_DIVR_DIV_MASK		GENMASK(5, 0)
diff --git a/include/drivers/st/stm32mp_reset.h b/include/drivers/st/stm32mp_reset.h
index 2da5adf..8444805 100644
--- a/include/drivers/st/stm32mp_reset.h
+++ b/include/drivers/st/stm32mp_reset.h
@@ -9,7 +9,42 @@
 
 #include <stdint.h>
 
-void stm32mp_reset_assert(uint32_t reset_id);
-void stm32mp_reset_deassert(uint32_t reset_id);
+/*
+ * Assert target reset, if @to_us non null, wait until reset is asserted
+ *
+ * @reset_id: Reset controller ID
+ * @to_us: Timeout in microsecond, or 0 if not waiting
+ * Return 0 on success and -ETIMEDOUT if waiting and timeout expired
+ */
+int stm32mp_reset_assert(uint32_t reset_id, unsigned int to_us);
+
+/*
+ * Enable reset control for target resource
+ *
+ * @reset_id: Reset controller ID
+ */
+static inline void stm32mp_reset_set(uint32_t reset_id)
+{
+	(void)stm32mp_reset_assert(reset_id, 0U);
+}
+
+/*
+ * Deassert target reset, if @to_us non null, wait until reset is deasserted
+ *
+ * @reset_id: Reset controller ID
+ * @to_us: Timeout in microsecond, or 0 if not waiting
+ * Return 0 on success and -ETIMEDOUT if waiting and timeout expired
+ */
+int stm32mp_reset_deassert(uint32_t reset_id, unsigned int to_us);
+
+/*
+ * Release reset control for target resource
+ *
+ * @reset_id: Reset controller ID
+ */
+static inline void stm32mp_reset_release(uint32_t reset_id)
+{
+	(void)stm32mp_reset_deassert(reset_id, 0U);
+}
 
 #endif /* STM32MP_RESET_H */
diff --git a/include/dt-bindings/clock/stm32mp1-clks.h b/include/dt-bindings/clock/stm32mp1-clks.h
index 18bdb57..67e66b2 100644
--- a/include/dt-bindings/clock/stm32mp1-clks.h
+++ b/include/dt-bindings/clock/stm32mp1-clks.h
@@ -248,4 +248,31 @@
 
 #define STM32MP1_LAST_CLK 232
 
+/* SCMI clock identifiers */
+#define CK_SCMI0_HSE		0
+#define CK_SCMI0_HSI		1
+#define CK_SCMI0_CSI		2
+#define CK_SCMI0_LSE		3
+#define CK_SCMI0_LSI		4
+#define CK_SCMI0_PLL2_Q		5
+#define CK_SCMI0_PLL2_R		6
+#define CK_SCMI0_MPU		7
+#define CK_SCMI0_AXI		8
+#define CK_SCMI0_BSEC		9
+#define CK_SCMI0_CRYP1		10
+#define CK_SCMI0_GPIOZ		11
+#define CK_SCMI0_HASH1		12
+#define CK_SCMI0_I2C4		13
+#define CK_SCMI0_I2C6		14
+#define CK_SCMI0_IWDG1		15
+#define CK_SCMI0_RNG1		16
+#define CK_SCMI0_RTC		17
+#define CK_SCMI0_RTCAPB		18
+#define CK_SCMI0_SPI6		19
+#define CK_SCMI0_USART1		20
+
+#define CK_SCMI1_PLL3_Q		0
+#define CK_SCMI1_PLL3_R		1
+#define CK_SCMI1_MCU		2
+
 #endif /* _DT_BINDINGS_STM32MP1_CLKS_H_ */
diff --git a/include/dt-bindings/reset/stm32mp1-resets.h b/include/dt-bindings/reset/stm32mp1-resets.h
index f0c3aae..bc71924 100644
--- a/include/dt-bindings/reset/stm32mp1-resets.h
+++ b/include/dt-bindings/reset/stm32mp1-resets.h
@@ -105,4 +105,17 @@
 #define GPIOJ_R		19785
 #define GPIOK_R		19786
 
+/* SCMI reset domain identifiers */
+#define RST_SCMI0_SPI6		0
+#define RST_SCMI0_I2C4		1
+#define RST_SCMI0_I2C6		2
+#define RST_SCMI0_USART1	3
+#define RST_SCMI0_STGEN		4
+#define RST_SCMI0_GPIOZ		5
+#define RST_SCMI0_CRYP1		6
+#define RST_SCMI0_HASH1		7
+#define RST_SCMI0_RNG1		8
+#define RST_SCMI0_MDMA		9
+#define RST_SCMI0_MCU		10
+
 #endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */
diff --git a/include/dt-bindings/soc/st,stm32-etzpc.h b/include/dt-bindings/soc/st,stm32-etzpc.h
new file mode 100644
index 0000000..3f9fb3b
--- /dev/null
+++ b/include/dt-bindings/soc/st,stm32-etzpc.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+ */
+
+#ifndef _DT_BINDINGS_STM32_ETZPC_H
+#define _DT_BINDINGS_STM32_ETZPC_H
+
+/* DECPROT modes */
+#define DECPROT_S_RW		0x0
+#define DECPROT_NS_R_S_W	0x1
+#define DECPROT_MCU_ISOLATION	0x2
+#define DECPROT_NS_RW		0x3
+
+/* DECPROT lock */
+#define DECPROT_UNLOCK		0x0
+#define DECPROT_LOCK		0x1
+
+#endif /* _DT_BINDINGS_STM32_ETZPC_H */
diff --git a/include/export/common/tbbr/tbbr_img_def_exp.h b/include/export/common/tbbr/tbbr_img_def_exp.h
index 89dbc58..18f0125 100644
--- a/include/export/common/tbbr/tbbr_img_def_exp.h
+++ b/include/export/common/tbbr/tbbr_img_def_exp.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -88,12 +88,10 @@
 /* Encrypted image identifier */
 #define ENC_IMAGE_ID			U(30)
 
-/* Define size of the array */
-#if defined(SPD_spmd)
-#define MAX_SP_IDS			U(8)
-#define MAX_NUMBER_IDS			MAX_SP_IDS + U(31)
-#else
-#define MAX_NUMBER_IDS			U(31)
-#endif
+/* FW_CONFIG */
+#define FW_CONFIG_ID			U(31)
+
+/* Max Images */
+#define MAX_IMAGE_IDS			U(32)
 
 #endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_TBBR_TBBR_IMG_DEF_EXP_H */
diff --git a/include/lib/cpus/aarch64/cortex_a76.h b/include/lib/cpus/aarch64/cortex_a76.h
index 7dc7e06..b522e8e 100644
--- a/include/lib/cpus/aarch64/cortex_a76.h
+++ b/include/lib/cpus/aarch64/cortex_a76.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
  */
@@ -20,6 +20,7 @@
 
 #define CORTEX_A76_CPUECTLR_EL1_WS_THR_L2	(ULL(3) << 24)
 #define CORTEX_A76_CPUECTLR_EL1_BIT_51		(ULL(1) << 51)
+#define CORTEX_A76_CPUECTLR_EL1_BIT_53		(ULL(1) << 53)
 
 /*******************************************************************************
  * CPU Auxiliary Control register specific definitions.
@@ -32,6 +33,8 @@
 
 #define CORTEX_A76_CPUACTLR2_EL1	S3_0_C15_C1_1
 
+#define CORTEX_A76_CPUACTLR2_EL1_BIT_2	(ULL(1) << 2)
+
 #define CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE	(ULL(1) << 16)
 
 #define CORTEX_A76_CPUACTLR3_EL1	S3_0_C15_C1_2
diff --git a/include/lib/cpus/aarch64/cortex_a77.h b/include/lib/cpus/aarch64/cortex_a77.h
index 0467ef3..bbd647c 100644
--- a/include/lib/cpus/aarch64/cortex_a77.h
+++ b/include/lib/cpus/aarch64/cortex_a77.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,6 +16,7 @@
  * CPU Extended Control register specific definitions.
  ******************************************************************************/
 #define CORTEX_A77_CPUECTLR_EL1				S3_0_C15_C1_4
+#define CORTEX_A77_CPUECTLR_EL1_BIT_53			(ULL(1) << 53)
 
 /*******************************************************************************
  * CPU Power Control register specific definitions.
diff --git a/include/lib/cpus/aarch64/cortex_hercules.h b/include/lib/cpus/aarch64/cortex_a78.h
similarity index 64%
rename from include/lib/cpus/aarch64/cortex_hercules.h
rename to include/lib/cpus/aarch64/cortex_a78.h
index d5ca85e..0d4712b 100644
--- a/include/lib/cpus/aarch64/cortex_hercules.h
+++ b/include/lib/cpus/aarch64/cortex_a78.h
@@ -1,34 +1,34 @@
 /*
- * Copyright (c) 2019, ARM Limited. All rights reserved.
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef CORTEX_HERCULES_H
-#define CORTEX_HERCULES_H
+#ifndef CORTEX_A78_H
+#define CORTEX_A78_H
 
 #include <lib/utils_def.h>
 
-#define CORTEX_HERCULES_MIDR					U(0x410FD410)
+#define CORTEX_A78_MIDR					U(0x410FD410)
 
 /*******************************************************************************
  * CPU Extended Control register specific definitions.
  ******************************************************************************/
-#define CORTEX_HERCULES_CPUECTLR_EL1				S3_0_C15_C1_4
+#define CORTEX_A78_CPUECTLR_EL1				S3_0_C15_C1_4
 
 /*******************************************************************************
  * CPU Power Control register specific definitions
  ******************************************************************************/
-#define CORTEX_HERCULES_CPUPWRCTLR_EL1				S3_0_C15_C2_7
-#define CORTEX_HERCULES_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT	U(1)
+#define CORTEX_A78_CPUPWRCTLR_EL1				S3_0_C15_C2_7
+#define CORTEX_A78_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT	U(1)
 
 /*******************************************************************************
  * CPU Auxiliary Control register specific definitions.
  ******************************************************************************/
-#define CORTEX_HERCULES_ACTLR_TAM_BIT				(ULL(1) << 30)
+#define CORTEX_A78_ACTLR_TAM_BIT				(ULL(1) << 30)
 
-#define CORTEX_HERCULES_ACTLR2_EL1				S3_0_C15_C1_1
-#define CORTEX_HERCULES_ACTLR2_EL1_BIT_1			(ULL(1) << 1)
+#define CORTEX_A78_ACTLR2_EL1				S3_0_C15_C1_1
+#define CORTEX_A78_ACTLR2_EL1_BIT_1			(ULL(1) << 1)
 
 /*******************************************************************************
  * CPU Activity Monitor Unit register specific definitions.
@@ -38,7 +38,7 @@
 #define CPUAMCNTENCLR1_EL0					S3_3_C15_C3_0
 #define CPUAMCNTENSET1_EL0					S3_3_C15_C3_1
 
-#define CORTEX_HERCULES_AMU_GROUP0_MASK				U(0xF)
-#define CORTEX_HERCULES_AMU_GROUP1_MASK				U(0x7)
+#define CORTEX_A78_AMU_GROUP0_MASK				U(0xF)
+#define CORTEX_A78_AMU_GROUP1_MASK				U(0x7)
 
-#endif /* CORTEX_HERCULES_H */
+#endif /* CORTEX_A78_H */
diff --git a/include/lib/cpus/aarch64/cortex_hercules_ae.h b/include/lib/cpus/aarch64/cortex_hercules_ae.h
index 795563b..73c22f7 100644
--- a/include/lib/cpus/aarch64/cortex_hercules_ae.h
+++ b/include/lib/cpus/aarch64/cortex_hercules_ae.h
@@ -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
  */
@@ -7,7 +7,7 @@
 #ifndef CORTEX_HERCULES_AE_H
 #define CORTEX_HERCULES_AE_H
 
-#include <cortex_hercules.h>
+#include <cortex_a78.h>
 
 #define CORTEX_HERCULES_AE_MIDR U(0x410FD420)
 
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index 0029658..90807ce 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -168,76 +168,75 @@
 #define CTX_ELR_EL2		U(0x58)
 #define CTX_ESR_EL2		U(0x60)
 #define CTX_FAR_EL2		U(0x68)
-#define CTX_FPEXC32_EL2		U(0x70)
-#define CTX_HACR_EL2		U(0x78)
-#define CTX_HCR_EL2		U(0x80)
-#define CTX_HPFAR_EL2		U(0x88)
-#define CTX_HSTR_EL2		U(0x90)
-#define CTX_ICC_SRE_EL2		U(0x98)
-#define CTX_ICH_HCR_EL2		U(0xa0)
-#define CTX_ICH_VMCR_EL2	U(0xa8)
-#define CTX_MAIR_EL2		U(0xb0)
-#define CTX_MDCR_EL2		U(0xb8)
-#define CTX_PMSCR_EL2		U(0xc0)
-#define CTX_SCTLR_EL2		U(0xc8)
-#define CTX_SPSR_EL2		U(0xd0)
-#define CTX_SP_EL2		U(0xd8)
-#define CTX_TCR_EL2		U(0xe0)
-#define CTX_TPIDR_EL2		U(0xe8)
-#define CTX_TTBR0_EL2		U(0xf0)
-#define CTX_VBAR_EL2		U(0xf8)
-#define CTX_VMPIDR_EL2		U(0x100)
-#define CTX_VPIDR_EL2		U(0x108)
-#define CTX_VTCR_EL2		U(0x110)
-#define CTX_VTTBR_EL2		U(0x118)
+#define CTX_HACR_EL2		U(0x70)
+#define CTX_HCR_EL2		U(0x78)
+#define CTX_HPFAR_EL2		U(0x80)
+#define CTX_HSTR_EL2		U(0x88)
+#define CTX_ICC_SRE_EL2		U(0x90)
+#define CTX_ICH_HCR_EL2		U(0x98)
+#define CTX_ICH_VMCR_EL2	U(0xa0)
+#define CTX_MAIR_EL2		U(0xa8)
+#define CTX_MDCR_EL2		U(0xb0)
+#define CTX_PMSCR_EL2		U(0xb8)
+#define CTX_SCTLR_EL2		U(0xc0)
+#define CTX_SPSR_EL2		U(0xc8)
+#define CTX_SP_EL2		U(0xd0)
+#define CTX_TCR_EL2		U(0xd8)
+#define CTX_TPIDR_EL2		U(0xe0)
+#define CTX_TTBR0_EL2		U(0xe8)
+#define CTX_VBAR_EL2		U(0xf0)
+#define CTX_VMPIDR_EL2		U(0xf8)
+#define CTX_VPIDR_EL2		U(0x100)
+#define CTX_VTCR_EL2		U(0x108)
+#define CTX_VTTBR_EL2		U(0x110)
 
 // Only if MTE registers in use
-#define CTX_TFSR_EL2		U(0x120)
+#define CTX_TFSR_EL2		U(0x118)
 
 // Only if ENABLE_MPAM_FOR_LOWER_ELS==1
-#define CTX_MPAM2_EL2		U(0x128)
-#define CTX_MPAMHCR_EL2		U(0x130)
-#define CTX_MPAMVPM0_EL2	U(0x138)
-#define CTX_MPAMVPM1_EL2	U(0x140)
-#define CTX_MPAMVPM2_EL2	U(0x148)
-#define CTX_MPAMVPM3_EL2	U(0x150)
-#define CTX_MPAMVPM4_EL2	U(0x158)
-#define CTX_MPAMVPM5_EL2	U(0x160)
-#define CTX_MPAMVPM6_EL2	U(0x168)
-#define CTX_MPAMVPM7_EL2	U(0x170)
-#define CTX_MPAMVPMV_EL2	U(0x178)
+#define CTX_MPAM2_EL2		U(0x120)
+#define CTX_MPAMHCR_EL2		U(0x128)
+#define CTX_MPAMVPM0_EL2	U(0x130)
+#define CTX_MPAMVPM1_EL2	U(0x138)
+#define CTX_MPAMVPM2_EL2	U(0x140)
+#define CTX_MPAMVPM3_EL2	U(0x148)
+#define CTX_MPAMVPM4_EL2	U(0x150)
+#define CTX_MPAMVPM5_EL2	U(0x158)
+#define CTX_MPAMVPM6_EL2	U(0x160)
+#define CTX_MPAMVPM7_EL2	U(0x168)
+#define CTX_MPAMVPMV_EL2	U(0x170)
 
 // Starting with Armv8.6
-#define CTX_HAFGRTR_EL2		U(0x180)
-#define CTX_HDFGRTR_EL2		U(0x188)
-#define CTX_HDFGWTR_EL2		U(0x190)
-#define CTX_HFGITR_EL2		U(0x198)
-#define CTX_HFGRTR_EL2		U(0x1a0)
-#define CTX_HFGWTR_EL2		U(0x1a8)
-#define CTX_CNTPOFF_EL2		U(0x1b0)
+#define CTX_HAFGRTR_EL2		U(0x178)
+#define CTX_HDFGRTR_EL2		U(0x180)
+#define CTX_HDFGWTR_EL2		U(0x188)
+#define CTX_HFGITR_EL2		U(0x190)
+#define CTX_HFGRTR_EL2		U(0x198)
+#define CTX_HFGWTR_EL2		U(0x1a0)
+#define CTX_CNTPOFF_EL2		U(0x1a8)
 
 // Starting with Armv8.4
-#define CTX_CNTHPS_CTL_EL2	U(0x1b8)
-#define CTX_CNTHPS_CVAL_EL2	U(0x1c0)
-#define CTX_CNTHPS_TVAL_EL2	U(0x1c8)
-#define CTX_CNTHVS_CTL_EL2	U(0x1d0)
-#define CTX_CNTHVS_CVAL_EL2	U(0x1d8)
-#define CTX_CNTHVS_TVAL_EL2	U(0x1e0)
-#define CTX_CNTHV_CTL_EL2	U(0x1e8)
-#define CTX_CNTHV_CVAL_EL2	U(0x1f0)
-#define CTX_CNTHV_TVAL_EL2	U(0x1f8)
-#define CTX_CONTEXTIDR_EL2	U(0x200)
-#define CTX_SDER32_EL2		U(0x208)
-#define CTX_TTBR1_EL2		U(0x210)
-#define CTX_VDISR_EL2		U(0x218)
-#define CTX_VNCR_EL2		U(0x220)
-#define CTX_VSESR_EL2		U(0x228)
-#define CTX_VSTCR_EL2		U(0x230)
-#define CTX_VSTTBR_EL2		U(0x238)
-#define CTX_TRFCR_EL2		U(0x240)
+#define CTX_CNTHPS_CTL_EL2	U(0x1b0)
+#define CTX_CNTHPS_CVAL_EL2	U(0x1b8)
+#define CTX_CNTHPS_TVAL_EL2	U(0x1c0)
+#define CTX_CNTHVS_CTL_EL2	U(0x1c8)
+#define CTX_CNTHVS_CVAL_EL2	U(0x1d0)
+#define CTX_CNTHVS_TVAL_EL2	U(0x1d8)
+#define CTX_CNTHV_CTL_EL2	U(0x1e0)
+#define CTX_CNTHV_CVAL_EL2	U(0x1e8)
+#define CTX_CNTHV_TVAL_EL2	U(0x1f0)
+#define CTX_CONTEXTIDR_EL2	U(0x1f8)
+#define CTX_SDER32_EL2		U(0x200)
+#define CTX_TTBR1_EL2		U(0x208)
+#define CTX_VDISR_EL2		U(0x210)
+#define CTX_VNCR_EL2		U(0x218)
+#define CTX_VSESR_EL2		U(0x220)
+#define CTX_VSTCR_EL2		U(0x228)
+#define CTX_VSTTBR_EL2		U(0x230)
+#define CTX_TRFCR_EL2		U(0x238)
 
 // Starting with Armv8.5
-#define CTX_SCXTNUM_EL2		U(0x248)
+#define CTX_SCXTNUM_EL2		U(0x240)
 /* Align to the next 16 byte boundary */
 #define CTX_EL2_SYSREGS_END	U(0x250)
 
diff --git a/include/lib/extensions/ras.h b/include/lib/extensions/ras.h
index 4fc8f04..793ab9f 100644
--- a/include/lib/extensions/ras.h
+++ b/include/lib/extensions/ras.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -192,6 +193,7 @@
 			probe_data);
 }
 
+const char *ras_serr_to_str(unsigned int serr);
 int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
 		void *handle, uint64_t flags);
 void ras_init(void);
diff --git a/include/lib/extensions/ras_arch.h b/include/lib/extensions/ras_arch.h
index 0c98c4a..55760b0 100644
--- a/include/lib/extensions/ras_arch.h
+++ b/include/lib/extensions/ras_arch.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -151,6 +152,9 @@
 #define ERROR_STATUS_SET_UC	0x2     /* Uncontainable */
 #define ERROR_STATUS_SET_CE	0x3     /* Corrected */
 
+/* Number of architecturally-defined primary error codes */
+#define ERROR_STATUS_NUM_SERR	U(22)
+
 /* Implementation Defined Syndrome bit in ESR */
 #define SERROR_IDS_BIT		U(24)
 
diff --git a/include/lib/extensions/twed.h b/include/lib/extensions/twed.h
new file mode 100644
index 0000000..eac4aa3
--- /dev/null
+++ b/include/lib/extensions/twed.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TWED_H
+#define TWED_H
+
+#include <stdint.h>
+
+#define TWED_DISABLED U(0xFFFFFFFF)
+
+uint32_t plat_arm_set_twedel_scr_el3(void);
+
+#endif /* TWEDE_H */
diff --git a/include/lib/fconf/fconf.h b/include/lib/fconf/fconf.h
index 09d2b59..917e053 100644
--- a/include/lib/fconf/fconf.h
+++ b/include/lib/fconf/fconf.h
@@ -43,8 +43,8 @@
 	int (*populate)(uintptr_t config);
 };
 
-/* Load firmware configuration dtb */
-void fconf_load_config(void);
+/* This function supports to load tb_fw_config and fw_config dtb */
+int fconf_load_config(unsigned int image_id);
 
 /* Top level populate function
  *
diff --git a/include/lib/fconf/fconf_dyn_cfg_getter.h b/include/lib/fconf/fconf_dyn_cfg_getter.h
index 0fda8c9..6f8da0d 100644
--- a/include/lib/fconf/fconf_dyn_cfg_getter.h
+++ b/include/lib/fconf/fconf_dyn_cfg_getter.h
@@ -14,11 +14,15 @@
 
 struct dyn_cfg_dtb_info_t {
 	uintptr_t config_addr;
-	size_t config_max_size;
+	uint32_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);
 
+/* Set config information in global DTB array */
+void set_config_info(uintptr_t config_addr, uint32_t config_max_size,
+			unsigned int config_id);
+
 #endif /* FCONF_DYN_CFG_GETTER_H */
diff --git a/include/lib/fconf/fconf_tbbr_getter.h b/include/lib/fconf/fconf_tbbr_getter.h
index db98b68..6066af6 100644
--- a/include/lib/fconf/fconf_tbbr_getter.h
+++ b/include/lib/fconf/fconf_tbbr_getter.h
@@ -23,6 +23,9 @@
 	uint32_t disable_auth;
 	void *mbedtls_heap_addr;
 	size_t mbedtls_heap_size;
+#if MEASURED_BOOT
+	uint8_t bl2_hash_data[TCG_DIGEST_SIZE];
+#endif
 };
 
 extern struct tbbr_dyn_config_t tbbr_dyn_config;
diff --git a/include/lib/libc/stdbool.h b/include/lib/libc/stdbool.h
index e39aef7..b58334c 100644
--- a/include/lib/libc/stdbool.h
+++ b/include/lib/libc/stdbool.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
  */
@@ -9,8 +9,8 @@
 
 #define bool	_Bool
 
-#define true	1
-#define false	0
+#define true	(0 < 1)
+#define false	(0 > 1)
 
 #define __bool_true_false_are_defined	1
 
diff --git a/include/lib/libfdt/fdt.h b/include/lib/libfdt/fdt.h
index ef7c86b..eb9edb7 100644
--- a/include/lib/libfdt/fdt.h
+++ b/include/lib/libfdt/fdt.h
@@ -1,55 +1,10 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
 #ifndef FDT_H
 #define FDT_H
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
  * Copyright 2012 Kim Phillips, Freescale Semiconductor.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef __ASSEMBLER__
@@ -90,7 +45,7 @@
 	char data[0];
 };
 
-#endif /* !__ASSEMBLER__ */
+#endif /* !__ASSEMBLER__*/
 
 #define FDT_MAGIC	0xd00dfeed	/* 4: version, 4: total size */
 #define FDT_TAGSIZE	sizeof(fdt32_t)
diff --git a/include/lib/libfdt/libfdt.h b/include/lib/libfdt/libfdt.h
index c8c00fa..48f375c 100644
--- a/include/lib/libfdt/libfdt.h
+++ b/include/lib/libfdt/libfdt.h
@@ -1,54 +1,9 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
 #ifndef LIBFDT_H
 #define LIBFDT_H
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #include <libfdt_env.h>
@@ -90,8 +45,9 @@
 
 /* Error codes: codes for bad device tree blobs */
 #define FDT_ERR_TRUNCATED	8
-	/* FDT_ERR_TRUNCATED: Structure block of the given device tree
-	 * ends without an FDT_END tag. */
+	/* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly
+	 * terminated (overflows, goes outside allowed bounds, or
+	 * isn't properly terminated).  */
 #define FDT_ERR_BADMAGIC	9
 	/* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
 	 * device tree at all - it is missing the flattened device
@@ -137,7 +93,15 @@
 	/* FDT_ERR_NOPHANDLES: The device tree doesn't have any
 	 * phandle available anymore without causing an overflow */
 
-#define FDT_ERR_MAX		17
+#define FDT_ERR_BADFLAGS	18
+	/* FDT_ERR_BADFLAGS: The function was passed a flags field that
+	 * contains invalid flags or an invalid combination of flags. */
+
+#define FDT_ERR_MAX		18
+
+/* constants */
+#define FDT_MAX_PHANDLE 0xfffffffe
+	/* Valid values for phandles range from 1 to 2^32-2. */
 
 /**********************************************************************/
 /* Low-level functions (you probably don't need these)                */
@@ -153,6 +117,61 @@
 
 uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
 
+/*
+ * Alignment helpers:
+ *     These helpers access words from a device tree blob.  They're
+ *     built to work even with unaligned pointers on platforms (ike
+ *     ARM) that don't like unaligned loads and stores
+ */
+
+static inline uint32_t fdt32_ld(const fdt32_t *p)
+{
+	const uint8_t *bp = (const uint8_t *)p;
+
+	return ((uint32_t)bp[0] << 24)
+		| ((uint32_t)bp[1] << 16)
+		| ((uint32_t)bp[2] << 8)
+		| bp[3];
+}
+
+static inline void fdt32_st(void *property, uint32_t value)
+{
+	uint8_t *bp = (uint8_t *)property;
+
+	bp[0] = value >> 24;
+	bp[1] = (value >> 16) & 0xff;
+	bp[2] = (value >> 8) & 0xff;
+	bp[3] = value & 0xff;
+}
+
+static inline uint64_t fdt64_ld(const fdt64_t *p)
+{
+	const uint8_t *bp = (const uint8_t *)p;
+
+	return ((uint64_t)bp[0] << 56)
+		| ((uint64_t)bp[1] << 48)
+		| ((uint64_t)bp[2] << 40)
+		| ((uint64_t)bp[3] << 32)
+		| ((uint64_t)bp[4] << 24)
+		| ((uint64_t)bp[5] << 16)
+		| ((uint64_t)bp[6] << 8)
+		| bp[7];
+}
+
+static inline void fdt64_st(void *property, uint64_t value)
+{
+	uint8_t *bp = (uint8_t *)property;
+
+	bp[0] = value >> 56;
+	bp[1] = (value >> 48) & 0xff;
+	bp[2] = (value >> 40) & 0xff;
+	bp[3] = (value >> 32) & 0xff;
+	bp[4] = (value >> 24) & 0xff;
+	bp[5] = (value >> 16) & 0xff;
+	bp[6] = (value >> 8) & 0xff;
+	bp[7] = value & 0xff;
+}
+
 /**********************************************************************/
 /* Traversal functions                                                */
 /**********************************************************************/
@@ -195,7 +214,7 @@
  *		...
  *	}
  *
- *	if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) {
+ *	if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) {
  *		Error handling
  *	}
  *
@@ -213,7 +232,7 @@
 /* General functions                                                  */
 /**********************************************************************/
 #define fdt_get_header(fdt, field) \
-	(fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
+	(fdt32_ld(&((const struct fdt_header *)(fdt))->field))
 #define fdt_magic(fdt)			(fdt_get_header(fdt, magic))
 #define fdt_totalsize(fdt)		(fdt_get_header(fdt, totalsize))
 #define fdt_off_dt_struct(fdt)		(fdt_get_header(fdt, off_dt_struct))
@@ -244,18 +263,32 @@
 #undef fdt_set_hdr_
 
 /**
- * fdt_check_header - sanity check a device tree or possible device tree
+ * fdt_header_size - return the size of the tree's header
+ * @fdt: pointer to a flattened device tree
+ */
+size_t fdt_header_size(const void *fdt);
+
+/**
+ * fdt_header_size_ - internal function which takes a version number
+ */
+size_t fdt_header_size_(uint32_t version);
+
+/**
+ * fdt_check_header - sanity check a device tree header
+
  * @fdt: pointer to data which might be a flattened device tree
  *
  * fdt_check_header() checks that the given buffer contains what
- * appears to be a flattened device tree with sane information in its
- * header.
+ * appears to be a flattened device tree, and that the header contains
+ * valid information (to the extent that can be determined from the
+ * header alone).
  *
  * returns:
  *     0, if the buffer appears to contain a valid device tree
  *     -FDT_ERR_BADMAGIC,
  *     -FDT_ERR_BADVERSION,
- *     -FDT_ERR_BADSTATE, standard meanings, as above
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_TRUNCATED, standard meanings, as above
  */
 int fdt_check_header(const void *fdt);
 
@@ -284,6 +317,24 @@
 /* Read-only functions                                                */
 /**********************************************************************/
 
+int fdt_check_full(const void *fdt, size_t bufsize);
+
+/**
+ * fdt_get_string - retrieve a string from the strings block of a device tree
+ * @fdt: pointer to the device tree blob
+ * @stroffset: offset of the string within the strings block (native endian)
+ * @lenp: optional pointer to return the string's length
+ *
+ * fdt_get_string() retrieves a pointer to a single string from the
+ * strings block of the device tree blob at fdt, and optionally also
+ * returns the string's length in *lenp.
+ *
+ * returns:
+ *     a pointer to the string, on success
+ *     NULL, if stroffset is out of bounds, or doesn't point to a valid string
+ */
+const char *fdt_get_string(const void *fdt, int stroffset, int *lenp);
+
 /**
  * fdt_string - retrieve a string from the strings block of a device tree
  * @fdt: pointer to the device tree blob
@@ -294,11 +345,25 @@
  *
  * returns:
  *     a pointer to the string, on success
- *     NULL, if stroffset is out of bounds
+ *     NULL, if stroffset is out of bounds, or doesn't point to a valid string
  */
 const char *fdt_string(const void *fdt, int stroffset);
 
 /**
+ * fdt_find_max_phandle - find and return the highest phandle in a tree
+ * @fdt: pointer to the device tree blob
+ * @phandle: return location for the highest phandle value found in the tree
+ *
+ * fdt_find_max_phandle() finds the highest phandle value in the given device
+ * tree. The value returned in @phandle is only valid if the function returns
+ * success.
+ *
+ * returns:
+ *     0 on success or a negative error code on failure
+ */
+int fdt_find_max_phandle(const void *fdt, uint32_t *phandle);
+
+/**
  * fdt_get_max_phandle - retrieves the highest phandle in a tree
  * @fdt: pointer to the device tree blob
  *
@@ -306,12 +371,39 @@
  * device tree. This will ignore badly formatted phandles, or phandles
  * with a value of 0 or -1.
  *
+ * This function is deprecated in favour of fdt_find_max_phandle().
+ *
  * returns:
  *      the highest phandle on success
  *      0, if no phandle was found in the device tree
  *      -1, if an error occurred
  */
-uint32_t fdt_get_max_phandle(const void *fdt);
+static inline uint32_t fdt_get_max_phandle(const void *fdt)
+{
+	uint32_t phandle;
+	int err;
+
+	err = fdt_find_max_phandle(fdt, &phandle);
+	if (err < 0)
+		return (uint32_t)-1;
+
+	return phandle;
+}
+
+/**
+ * fdt_generate_phandle - return a new, unused phandle for a device tree blob
+ * @fdt: pointer to the device tree blob
+ * @phandle: return location for the new phandle
+ *
+ * Walks the device tree blob and looks for the highest phandle value. On
+ * success, the new, unused phandle value (one higher than the previously
+ * highest phandle value in the device tree blob) will be returned in the
+ * @phandle parameter.
+ *
+ * Returns:
+ *   0 on success or a negative error-code on failure
+ */
+int fdt_generate_phandle(const void *fdt, uint32_t *phandle);
 
 /**
  * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
@@ -503,7 +595,7 @@
  *		...
  *	}
  *
- *	if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) {
+ *	if ((property < 0) && (property != -FDT_ERR_NOTFOUND)) {
  *		Error handling
  *	}
  *
@@ -606,7 +698,7 @@
 /**
  * fdt_getprop_by_offset - retrieve the value of a property at a given offset
  * @fdt: pointer to the device tree blob
- * @ffset: offset of the property to read
+ * @offset: offset of the property to read
  * @namep: pointer to a string variable (will be overwritten) or NULL
  * @lenp: pointer to an integer variable (will be overwritten) or NULL
  *
@@ -1090,7 +1182,7 @@
  *
  * returns:
  *	0 <= n < FDT_MAX_NCELLS, on success
- *      2, if the node has no #address-cells property
+ *      1, if the node has no #size-cells property
  *      -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
  *		#size-cells property
  *	-FDT_ERR_BADMAGIC,
@@ -1297,7 +1389,45 @@
 /* Sequential write functions                                         */
 /**********************************************************************/
 
+/* fdt_create_with_flags flags */
+#define FDT_CREATE_FLAG_NO_NAME_DEDUP 0x1
+	/* FDT_CREATE_FLAG_NO_NAME_DEDUP: Do not try to de-duplicate property
+	 * names in the fdt. This can result in faster creation times, but
+	 * a larger fdt. */
+
+#define FDT_CREATE_FLAGS_ALL	(FDT_CREATE_FLAG_NO_NAME_DEDUP)
+
+/**
+ * fdt_create_with_flags - begin creation of a new fdt
+ * @fdt: pointer to memory allocated where fdt will be created
+ * @bufsize: size of the memory space at fdt
+ * @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0.
+ *
+ * fdt_create_with_flags() begins the process of creating a new fdt with
+ * the sequential write interface.
+ *
+ * fdt creation process must end with fdt_finished() to produce a valid fdt.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt
+ *	-FDT_ERR_BADFLAGS, flags is not valid
+ */
+int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags);
+
+/**
+ * fdt_create - begin creation of a new fdt
+ * @fdt: pointer to memory allocated where fdt will be created
+ * @bufsize: size of the memory space at fdt
+ *
+ * fdt_create() is equivalent to fdt_create_with_flags() with flags=0.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt
+ */
 int fdt_create(void *buf, int bufsize);
+
 int fdt_resize(void *fdt, void *buf, int bufsize);
 int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
 int fdt_finish_reservemap(void *fdt);
@@ -1313,10 +1443,13 @@
 	fdt64_t tmp = cpu_to_fdt64(val);
 	return fdt_property(fdt, name, &tmp, sizeof(tmp));
 }
+
+#ifndef SWIG /* Not available in Python */
 static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
 {
 	return fdt_property_u32(fdt, name, val);
 }
+#endif
 
 /**
  * fdt_property_placeholder - add a new property and return a ptr to its value
@@ -1766,6 +1899,43 @@
 	fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
 
 /**
+ * fdt_appendprop_addrrange - append a address range property
+ * @fdt: pointer to the device tree blob
+ * @parent: offset of the parent node
+ * @nodeoffset: offset of the node to add a property at
+ * @name: name of property
+ * @addr: start address of a given range
+ * @size: size of a given range
+ *
+ * fdt_appendprop_addrrange() appends an address range value (start
+ * address and size) to the value of the named property in the given
+ * node, or creates a new property with that value if it does not
+ * already exist.
+ * If "name" is not specified, a default "reg" is used.
+ * Cell sizes are determined by parent's #address-cells and #size-cells.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
+ *		#address-cells property
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADVALUE, addr or size doesn't fit to respective cells size
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain a new property
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
+			     const char *name, uint64_t addr, uint64_t size);
+
+/**
  * fdt_delprop - delete a property
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to nop
diff --git a/include/lib/libfdt/libfdt_env.h b/include/lib/libfdt/libfdt_env.h
index bd24746..73b6d40 100644
--- a/include/lib/libfdt/libfdt_env.h
+++ b/include/lib/libfdt/libfdt_env.h
@@ -1,61 +1,18 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
 #ifndef LIBFDT_ENV_H
 #define LIBFDT_ENV_H
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
  * Copyright 2012 Kim Phillips, Freescale Semiconductor.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
 
 #ifdef __CHECKER__
 #define FDT_FORCE __attribute__((force))
diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h
index 8eb84a8..359b983 100644
--- a/include/lib/xlat_tables/xlat_tables_v2.h
+++ b/include/lib/xlat_tables/xlat_tables_v2.h
@@ -201,16 +201,20 @@
  * _section_name:
  *   Specify the name of the section where the translation tables have to be
  *   placed by the linker.
+ *
+ * _base_table_section_name:
+ *   Specify the name of the section where the base translation tables have to
+ *   be placed by the linker.
  */
 #define REGISTER_XLAT_CONTEXT2(_ctx_name, _mmap_count, _xlat_tables_count, \
 			_virt_addr_space_size, _phy_addr_space_size,	\
-			_xlat_regime, _section_name)			\
+			_xlat_regime, _section_name, _base_table_section_name) \
 	REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, (_mmap_count),	\
 					 (_xlat_tables_count),		\
 					 (_virt_addr_space_size),	\
 					 (_phy_addr_space_size),	\
 					 (_xlat_regime),		\
-					 (_section_name), ".bss"	\
+					 (_section_name), (_base_table_section_name) \
 )
 
 /******************************************************************************
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 89f7c61..293e7ce 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -81,7 +81,7 @@
 					 ARM_SCP_TZC_DRAM1_SIZE)
 #define ARM_SCP_TZC_DRAM1_SIZE		PLAT_ARM_SCP_TZC_DRAM1_SIZE
 #define ARM_SCP_TZC_DRAM1_END		(ARM_SCP_TZC_DRAM1_BASE +	\
-					 ARM_SCP_TZC_DRAM1_SIZE - 1)
+					 ARM_SCP_TZC_DRAM1_SIZE - 1U)
 
 /*
  * Define a 2MB region within the TZC secured DRAM for use by EL3 runtime
@@ -92,7 +92,7 @@
 #define ARM_EL3_TZC_DRAM1_BASE		(ARM_SCP_TZC_DRAM1_BASE - ARM_EL3_TZC_DRAM1_SIZE)
 #define ARM_EL3_TZC_DRAM1_SIZE		UL(0x00200000) /* 2 MB */
 #define ARM_EL3_TZC_DRAM1_END		(ARM_EL3_TZC_DRAM1_BASE +	\
-					ARM_EL3_TZC_DRAM1_SIZE - 1)
+					ARM_EL3_TZC_DRAM1_SIZE - 1U)
 
 #define ARM_AP_TZC_DRAM1_BASE		(ARM_DRAM1_BASE +		\
 					 ARM_DRAM1_SIZE -		\
@@ -101,7 +101,7 @@
 					 (ARM_SCP_TZC_DRAM1_SIZE +	\
 					 ARM_EL3_TZC_DRAM1_SIZE))
 #define ARM_AP_TZC_DRAM1_END		(ARM_AP_TZC_DRAM1_BASE +	\
-					 ARM_AP_TZC_DRAM1_SIZE - 1)
+					 ARM_AP_TZC_DRAM1_SIZE - 1U)
 
 /* Define the Access permissions for Secure peripherals to NS_DRAM */
 #if ARM_CRYPTOCELL_INTEG
@@ -148,17 +148,17 @@
 #define ARM_NS_DRAM1_SIZE		(ARM_DRAM1_SIZE -		\
 					 ARM_TZC_DRAM1_SIZE)
 #define ARM_NS_DRAM1_END		(ARM_NS_DRAM1_BASE +		\
-					 ARM_NS_DRAM1_SIZE - 1)
+					 ARM_NS_DRAM1_SIZE - 1U)
 
 #define ARM_DRAM1_BASE			ULL(0x80000000)
 #define ARM_DRAM1_SIZE			ULL(0x80000000)
 #define ARM_DRAM1_END			(ARM_DRAM1_BASE +		\
-					 ARM_DRAM1_SIZE - 1)
+					 ARM_DRAM1_SIZE - 1U)
 
 #define ARM_DRAM2_BASE			PLAT_ARM_DRAM2_BASE
 #define ARM_DRAM2_SIZE			PLAT_ARM_DRAM2_SIZE
 #define ARM_DRAM2_END			(ARM_DRAM2_BASE +		\
-					 ARM_DRAM2_SIZE - 1)
+					 ARM_DRAM2_SIZE - 1U)
 
 #define ARM_IRQ_SEC_PHY_TIMER		29
 
@@ -294,12 +294,19 @@
 #define ARM_V2M_MAP_MEM_PROTECT		MAP_REGION_FLAT(PLAT_ARM_MEM_PROT_ADDR,	\
 						V2M_FLASH_BLOCK_SIZE,		\
 						MT_DEVICE | MT_RW | MT_SECURE)
+/*
+ * Map the region for device tree configuration with read and write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION	MAP_REGION_FLAT(ARM_BL_RAM_BASE,	\
+						(ARM_FW_CONFIGS_LIMIT		\
+							- ARM_BL_RAM_BASE),	\
+						MT_MEMORY | MT_RW | MT_SECURE)
 
 /*
  * The max number of regions like RO(code), coherent and data required by
  * different BL stages which need to be mapped in the MMU.
  */
-#define ARM_BL_REGIONS			5
+#define ARM_BL_REGIONS			6
 
 #define MAX_MMAP_REGIONS		(PLAT_ARM_MMAP_ENTRIES +	\
 					 ARM_BL_REGIONS)
@@ -346,24 +353,25 @@
 #define CACHE_WRITEBACK_GRANULE		(U(1) << ARM_CACHE_WRITEBACK_SHIFT)
 
 /*
- * To enable TB_FW_CONFIG to be loaded by BL1, define the corresponding base
+ * To enable FW_CONFIG to be loaded by BL1, define the corresponding base
  * and limit. Leave enough space of BL2 meminfo.
  */
-#define ARM_TB_FW_CONFIG_BASE		(ARM_BL_RAM_BASE + sizeof(meminfo_t))
-#define ARM_TB_FW_CONFIG_LIMIT		(ARM_BL_RAM_BASE + (PAGE_SIZE / 2U))
+#define ARM_FW_CONFIG_BASE		(ARM_BL_RAM_BASE + sizeof(meminfo_t))
+#define ARM_FW_CONFIG_LIMIT		((ARM_BL_RAM_BASE + PAGE_SIZE) \
+					+ (PAGE_SIZE / 2U))
 
 /*
  * Boot parameters passed from BL2 to BL31/BL32 are stored here
  */
-#define ARM_BL2_MEM_DESC_BASE		ARM_TB_FW_CONFIG_LIMIT
-#define ARM_BL2_MEM_DESC_LIMIT		(ARM_BL2_MEM_DESC_BASE +	\
-							(PAGE_SIZE / 2U))
+#define ARM_BL2_MEM_DESC_BASE		(ARM_FW_CONFIG_LIMIT)
+#define ARM_BL2_MEM_DESC_LIMIT		(ARM_BL2_MEM_DESC_BASE \
+					+ (PAGE_SIZE / 2U))
 
 /*
  * Define limit of firmware configuration memory:
- * ARM_TB_FW_CONFIG + ARM_BL2_MEM_DESC memory
+ * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory
  */
-#define ARM_FW_CONFIG_LIMIT		(ARM_BL_RAM_BASE + PAGE_SIZE)
+#define ARM_FW_CONFIGS_LIMIT		(ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
 
 /*******************************************************************************
  * BL1 specific defines.
@@ -461,7 +469,7 @@
  * SP_MIN is the only BL image in SRAM. Allocate the whole of SRAM (excluding
  * the page reserved for fw_configs) to BL32
  */
-#  define BL32_BASE			ARM_FW_CONFIG_LIMIT
+#  define BL32_BASE			ARM_FW_CONFIGS_LIMIT
 #  define BL32_LIMIT			(ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
 # else
 /* Put BL32 below BL2 in the Trusted SRAM.*/
@@ -505,7 +513,7 @@
 #  define TSP_SEC_MEM_BASE		ARM_BL_RAM_BASE
 #  define TSP_SEC_MEM_SIZE		ARM_BL_RAM_SIZE
 #  define TSP_PROGBITS_LIMIT		BL31_BASE
-#  define BL32_BASE			ARM_FW_CONFIG_LIMIT
+#  define BL32_BASE			ARM_FW_CONFIGS_LIMIT
 #  define BL32_LIMIT			BL31_BASE
 # elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_DRAM_ID
 #  define TSP_SEC_MEM_BASE		PLAT_ARM_TRUSTED_DRAM_BASE
diff --git a/include/plat/arm/common/arm_reclaim_init.ld.S b/include/plat/arm/common/arm_reclaim_init.ld.S
index b5bf473..03976f3 100644
--- a/include/plat/arm/common/arm_reclaim_init.ld.S
+++ b/include/plat/arm/common/arm_reclaim_init.ld.S
@@ -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
  */
@@ -12,11 +12,7 @@
             . = . + PLATFORM_STACK_SIZE;
             . = ALIGN(PAGE_SIZE);
             __INIT_CODE_START__ = .;
-            /*
-             * Exclude PSCI initialization functions to ensure the init section
-             * does not become larger than the overlaid stack region
-             */
-            *(EXCLUDE_FILE (*psci_setup.o).text.init*)
+	    *(*text.init*);
             __INIT_CODE_UNALIGNED__ = .;
             .  = ALIGN(PAGE_SIZE);
             __INIT_CODE_END__ = .;
@@ -32,4 +28,41 @@
 
 }
 
+#undef	MIN
+#define	ABS		ABSOLUTE
+#define	COUNT		PLATFORM_CORE_COUNT
+#define	ALIGN_MASK	~(CACHE_WRITEBACK_GRANULE - 1)
+
+#define PRIMARY_STACK							\
+	__STACKS_START__ = .;						\
+	*(tzfw_normal_stacks)						\
+	OFFSET = ABS(SIZEOF(.init) - (. - __STACKS_START__));		\
+	/* Offset sign */						\
+	SIGN = ABS(OFFSET) & (1 << 63);					\
+	/* Offset mask */						\
+	MASK = ABS(SIGN >> 63) - 1;					\
+	. +=  ABS(OFFSET) & ABS(MASK);					\
+	__STACKS_END__ = .;						\
+	/* Total stack size */						\
+	SIZE = ABS(. - __STACKS_START__);				\
+	/* Maximum primary CPU stack */					\
+	STACK = ABS(__STACKS_START__ + SIZE / COUNT) & ALIGN_MASK;	\
+	/* Primary CPU stack */						\
+	__PRIMARY_STACK__ = MIN(STACK, ABS(__INIT_CODE_START__));
+
+#if (COUNT > 1)
+#define	SECONDARY_STACK					\
+	/* Size of the secondary CPUs' stack */		\
+	REST = ABS(__STACKS_END__ - __PRIMARY_STACK__);	\
+	/* Secondary per-CPU stack size */		\
+	__STACK_SIZE__ = ABS(REST / (COUNT - 1));
+#else
+#define	SECONDARY_STACK
+#endif
+
+#define STACK_SECTION		\
+	stacks (NOLOAD) : {	\
+		PRIMARY_STACK	\
+		SECONDARY_STACK	\
+	}
 #endif /* ARM_RECLAIM_INIT_LD_S */
diff --git a/include/plat/arm/common/fconf_arm_sp_getter.h b/include/plat/arm/common/fconf_arm_sp_getter.h
index 38c30fb..236254b 100644
--- a/include/plat/arm/common/fconf_arm_sp_getter.h
+++ b/include/plat/arm/common/fconf_arm_sp_getter.h
@@ -13,7 +13,7 @@
 /* arm_sp getter */
 #define arm__sp_getter(prop)	arm_sp.prop
 
-#define ARM_SP_MAX_SIZE		U(0x10000)
+#define ARM_SP_MAX_SIZE		U(0x80000)
 
 struct arm_sp_t {
 	unsigned int		number_of_sp;
diff --git a/include/plat/arm/common/fconf_sec_intr_config.h b/include/plat/arm/common/fconf_sec_intr_config.h
new file mode 100644
index 0000000..5d6b594
--- /dev/null
+++ b/include/plat/arm/common/fconf_sec_intr_config.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FCONF_SEC_INTR_CONFIG_H
+#define FCONF_SEC_INTR_CONFIG_H
+
+#include <lib/fconf/fconf.h>
+
+#include <platform_def.h>
+
+#define hw_config__sec_intr_prop_getter(id)	sec_intr_prop.id
+
+#define SEC_INT_COUNT_MAX U(15)
+
+struct sec_intr_prop_t {
+	interrupt_prop_t descriptor[SEC_INT_COUNT_MAX];
+	uint32_t count;
+};
+
+int fconf_populate_sec_intr_config(uintptr_t config);
+
+extern struct sec_intr_prop_t sec_intr_prop;
+
+#endif /* FCONF_SEC_INTR_CONFIG_H */
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 1b59795..95fc18e 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -190,7 +190,7 @@
 void arm_bl1_plat_arch_setup(void);
 
 /* BL2 utility functions */
-void arm_bl2_early_platform_setup(uintptr_t tb_fw_config, struct meminfo *mem_layout);
+void arm_bl2_early_platform_setup(uintptr_t fw_config, struct meminfo *mem_layout);
 void arm_bl2_platform_setup(void);
 void arm_bl2_plat_arch_setup(void);
 uint32_t arm_get_spsr_for_bl32_entry(void);
@@ -235,8 +235,20 @@
 
 #if MEASURED_BOOT
 /* Measured boot related functions */
-void arm_bl1_set_bl2_hash(image_desc_t *image_desc);
+void arm_bl1_set_bl2_hash(const image_desc_t *image_desc);
+void arm_bl2_get_hash(void *data);
+int arm_set_tos_fw_info(uintptr_t config_base, uintptr_t log_addr,
+			size_t log_size);
+int arm_set_nt_fw_info(uintptr_t config_base,
+/*
+ * Currently OP-TEE does not support reading DTBs from Secure memory
+ * and this option should be removed when feature is supported.
+ */
+#ifdef SPD_opteed
+			uintptr_t log_addr,
 #endif
+			size_t log_size, uintptr_t *ns_log_addr);
+#endif /* MEASURED_BOOT */
 
 /*
  * Free the memory storing initialization code only used during an images boot
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 720c259..2c1a180 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -175,6 +175,14 @@
 int bl1_plat_handle_pre_image_load(unsigned int image_id);
 int bl1_plat_handle_post_image_load(unsigned int image_id);
 
+#if MEASURED_BOOT
+/*
+ * Calculates and writes BL2 hash data to the platform's defined location.
+ * For ARM platforms the data are written to TB_FW_CONFIG DTB.
+ */
+void bl1_plat_set_bl2_hash(const image_desc_t *image_desc);
+#endif
+
 /*******************************************************************************
  * Mandatory BL2 functions
  ******************************************************************************/
@@ -190,11 +198,13 @@
 int bl2_plat_handle_pre_image_load(unsigned int image_id);
 int bl2_plat_handle_post_image_load(unsigned int image_id);
 
-
 /*******************************************************************************
  * Optional BL2 functions (may be overridden)
  ******************************************************************************/
-
+#if MEASURED_BOOT
+/* Read TCG_DIGEST_SIZE bytes of BL2 hash data */
+void bl2_plat_get_hash(void *data);
+#endif
 
 /*******************************************************************************
  * Mandatory BL2 at EL3 functions: Must be implemented if BL2_AT_EL3 image is
@@ -204,7 +214,6 @@
 				  u_register_t arg2, u_register_t arg3);
 void bl2_el3_plat_arch_setup(void);
 
-
 /*******************************************************************************
  * Optional BL2 at EL3 functions (may be overridden)
  ******************************************************************************/
@@ -332,4 +341,9 @@
  */
 int32_t plat_get_soc_revision(void);
 
+/*
+ * Optional function to check for SMCCC function availability for platform
+ */
+int32_t plat_is_smccc_feature_available(u_register_t fid);
+
 #endif /* PLATFORM_H */
diff --git a/include/plat/marvell/a3700/common/armada_common.h b/include/plat/marvell/armada/a3k/common/armada_common.h
similarity index 100%
rename from include/plat/marvell/a3700/common/armada_common.h
rename to include/plat/marvell/armada/a3k/common/armada_common.h
diff --git a/include/plat/marvell/a3700/common/board_marvell_def.h b/include/plat/marvell/armada/a3k/common/board_marvell_def.h
similarity index 95%
rename from include/plat/marvell/a3700/common/board_marvell_def.h
rename to include/plat/marvell/armada/a3k/common/board_marvell_def.h
index 1782596..bc3e04f 100644
--- a/include/plat/marvell/a3700/common/board_marvell_def.h
+++ b/include/plat/marvell/armada/a3k/common/board_marvell_def.h
@@ -71,6 +71,4 @@
 #define MAX_IO_DEVICES			3
 #define MAX_IO_HANDLES			4
 
-#define PLAT_MARVELL_TRUSTED_SRAM_SIZE	0x80000	/* 512 KB */
-
 #endif /* BOARD_MARVELL_DEF_H */
diff --git a/include/plat/marvell/a3700/common/marvell_def.h b/include/plat/marvell/armada/a3k/common/marvell_def.h
similarity index 89%
rename from include/plat/marvell/a3700/common/marvell_def.h
rename to include/plat/marvell/armada/a3k/common/marvell_def.h
index eb13ba8..1394c05 100644
--- a/include/plat/marvell/a3700/common/marvell_def.h
+++ b/include/plat/marvell/armada/a3k/common/marvell_def.h
@@ -49,15 +49,17 @@
  */
 #define MARVELL_LOCAL_STATE_OFF	2
 
+/* This leaves a gap between end of DRAM and start of ROM block */
+#define MARVELL_TRUSTED_DRAM_SIZE	0x80000	/* 512 KB */
+
 /* The first 4KB of Trusted SRAM are used as shared memory */
-#define MARVELL_TRUSTED_SRAM_BASE	PLAT_MARVELL_ATF_BASE
-#define MARVELL_SHARED_RAM_BASE		MARVELL_TRUSTED_SRAM_BASE
+#define MARVELL_SHARED_RAM_BASE		PLAT_MARVELL_ATF_BASE
 #define MARVELL_SHARED_RAM_SIZE		0x00001000	/* 4 KB */
 
 /* The remaining Trusted SRAM is used to load the BL images */
 #define MARVELL_BL_RAM_BASE		(MARVELL_SHARED_RAM_BASE + \
 					 MARVELL_SHARED_RAM_SIZE)
-#define MARVELL_BL_RAM_SIZE		(PLAT_MARVELL_TRUSTED_SRAM_SIZE - \
+#define MARVELL_BL_RAM_SIZE		(MARVELL_TRUSTED_DRAM_SIZE - \
 					 MARVELL_SHARED_RAM_SIZE)
 
 #define MARVELL_DRAM_BASE		ULL(0x0)
@@ -65,7 +67,7 @@
 #define MARVELL_DRAM_END		(MARVELL_DRAM_BASE + \
 					 MARVELL_DRAM_SIZE - 1)
 
-#define MARVELL_IRQ_SEC_PHY_TIMER		29
+#define MARVELL_IRQ_SEC_PHY_TIMER	29
 
 #define MARVELL_IRQ_SEC_SGI_0		8
 #define MARVELL_IRQ_SEC_SGI_1		9
@@ -86,7 +88,6 @@
 						MARVELL_DRAM_SIZE,	\
 						MT_MEMORY | MT_RW | MT_NS)
 
-
 /*
  * The number of regions like RO(code), coherent and data required by
  * different BL stages which need to be mapped in the MMU.
@@ -173,5 +174,15 @@
 #define BL31_LIMIT			(MARVELL_BL_RAM_BASE +	\
 					 MARVELL_BL_RAM_SIZE)
 
+/*****************************************************************************
+ * BL32 specific defines.
+ *****************************************************************************
+ */
+#define BL32_BASE		PLAT_MARVELL_TRUSTED_RAM_BASE
+#define BL32_LIMIT		(BL32_BASE + PLAT_MARVELL_TRUSTED_RAM_SIZE)
+
+#ifdef SPD_none
+#undef BL32_BASE
+#endif /* SPD_none */
 
 #endif /* MARVELL_DEF_H */
diff --git a/include/plat/marvell/a3700/common/plat_marvell.h b/include/plat/marvell/armada/a3k/common/plat_marvell.h
similarity index 100%
rename from include/plat/marvell/a3700/common/plat_marvell.h
rename to include/plat/marvell/armada/a3k/common/plat_marvell.h
diff --git a/include/plat/marvell/a8k/common/armada_common.h b/include/plat/marvell/armada/a8k/common/armada_common.h
similarity index 100%
rename from include/plat/marvell/a8k/common/armada_common.h
rename to include/plat/marvell/armada/a8k/common/armada_common.h
diff --git a/include/plat/marvell/a8k/common/board_marvell_def.h b/include/plat/marvell/armada/a8k/common/board_marvell_def.h
similarity index 95%
rename from include/plat/marvell/a8k/common/board_marvell_def.h
rename to include/plat/marvell/armada/a8k/common/board_marvell_def.h
index 0da56e7..7e90f5f 100644
--- a/include/plat/marvell/a8k/common/board_marvell_def.h
+++ b/include/plat/marvell/armada/a8k/common/board_marvell_def.h
@@ -71,7 +71,4 @@
 #define MAX_IO_DEVICES			3
 #define MAX_IO_HANDLES			4
 
-#define PLAT_MARVELL_TRUSTED_SRAM_SIZE	0x80000	/* 512 KB */
-
-
 #endif /* BOARD_MARVELL_DEF_H */
diff --git a/include/plat/marvell/a8k/common/marvell_def.h b/include/plat/marvell/armada/a8k/common/marvell_def.h
similarity index 74%
rename from include/plat/marvell/a8k/common/marvell_def.h
rename to include/plat/marvell/armada/a8k/common/marvell_def.h
index 4eda01f..1245b88 100644
--- a/include/plat/marvell/a8k/common/marvell_def.h
+++ b/include/plat/marvell/armada/a8k/common/marvell_def.h
@@ -47,15 +47,17 @@
  */
 #define MARVELL_LOCAL_STATE_OFF	2
 
+/* This leaves a gap between end of DRAM and start of ROM block */
+#define MARVELL_TRUSTED_DRAM_SIZE	0x80000	/* 512 KB */
+
 /* The first 4KB of Trusted SRAM are used as shared memory */
-#define MARVELL_TRUSTED_SRAM_BASE	PLAT_MARVELL_ATF_BASE
-#define MARVELL_SHARED_RAM_BASE		MARVELL_TRUSTED_SRAM_BASE
+#define MARVELL_SHARED_RAM_BASE		PLAT_MARVELL_ATF_BASE
 #define MARVELL_SHARED_RAM_SIZE		0x00001000	/* 4 KB */
 
 /* The remaining Trusted SRAM is used to load the BL images */
 #define MARVELL_BL_RAM_BASE		(MARVELL_SHARED_RAM_BASE +	\
 					 MARVELL_SHARED_RAM_SIZE)
-#define MARVELL_BL_RAM_SIZE		(PLAT_MARVELL_TRUSTED_SRAM_SIZE - \
+#define MARVELL_BL_RAM_SIZE		(MARVELL_TRUSTED_DRAM_SIZE - \
 					 MARVELL_SHARED_RAM_SIZE)
 /* Non-shared DRAM */
 #define MARVELL_DRAM_BASE		ULL(0x0)
@@ -75,9 +77,40 @@
 #define MARVELL_IRQ_SEC_SGI_6		14
 #define MARVELL_IRQ_SEC_SGI_7		15
 
-#define MARVELL_MAP_SHARED_RAM		MAP_REGION_FLAT(		\
-						MARVELL_SHARED_RAM_BASE,\
-						MARVELL_SHARED_RAM_SIZE,\
+#ifdef SPD_opteed
+/*
+ * BL2 needs to map 4MB at the end of TZC_DRAM1 in order to
+ * load/authenticate the trusted os extra image. The first 512KB of
+ * TZC_DRAM1 are reserved for trusted os (OPTEE). The extra image loading
+ * for OPTEE is paged image which only include the paging part using
+ * virtual memory but without "init" data. OPTEE will copy the "init" data
+ * (from pager image) to the first 512KB of TZC_DRAM, and then copy the
+ * extra image behind the "init" data.
+ */
+#define MARVELL_OPTEE_PAGEABLE_LOAD_BASE	\
+					(PLAT_MARVELL_TRUSTED_RAM_BASE + \
+					 PLAT_MARVELL_TRUSTED_RAM_SIZE - \
+					 MARVELL_OPTEE_PAGEABLE_LOAD_SIZE)
+#define MARVELL_OPTEE_PAGEABLE_LOAD_SIZE	0x400000
+#define MARVELL_OPTEE_PAGEABLE_LOAD_MEM		\
+					MAP_REGION_FLAT(		  \
+					MARVELL_OPTEE_PAGEABLE_LOAD_BASE, \
+					MARVELL_OPTEE_PAGEABLE_LOAD_SIZE, \
+					MT_MEMORY | MT_RW | MT_SECURE)
+
+/*
+ * Map the memory for the OP-TEE core (also known as OP-TEE pager when paging
+ * support is enabled).
+ */
+#define MARVELL_MAP_OPTEE_CORE_MEM	MAP_REGION_FLAT(		\
+						BL32_BASE,		\
+						BL32_LIMIT - BL32_BASE,	\
+						MT_MEMORY | MT_RW | MT_SECURE)
+#endif /* SPD_opteed */
+
+#define MARVELL_MAP_SECURE_RAM		MAP_REGION_FLAT(		 \
+						MARVELL_SHARED_RAM_BASE, \
+						MARVELL_SHARED_RAM_SIZE, \
 						MT_MEMORY | MT_RW | MT_SECURE)
 
 #define MARVELL_MAP_DRAM		MAP_REGION_FLAT(		\
@@ -85,7 +118,6 @@
 						MARVELL_DRAM_SIZE,	\
 						MT_MEMORY | MT_RW | MT_NS)
 
-
 /*
  * The number of regions like RO(code), coherent and data required by
  * different BL stages which need to be mapped in the MMU.
@@ -177,5 +209,14 @@
 #define BL31_LIMIT			(MARVELL_BL_RAM_BASE +	\
 					 MARVELL_BL_RAM_SIZE)
 
+/*******************************************************************************
+ * BL32 specific defines.
+ ******************************************************************************/
+#define BL32_BASE		PLAT_MARVELL_TRUSTED_RAM_BASE
+#define BL32_LIMIT		(BL32_BASE + PLAT_MARVELL_TRUSTED_RAM_SIZE)
+
+#ifdef SPD_none
+#undef BL32_BASE
+#endif /* SPD_none */
 
 #endif /* MARVELL_DEF_H */
diff --git a/include/plat/marvell/a8k/common/plat_marvell.h b/include/plat/marvell/armada/a8k/common/plat_marvell.h
similarity index 100%
rename from include/plat/marvell/a8k/common/plat_marvell.h
rename to include/plat/marvell/armada/a8k/common/plat_marvell.h
diff --git a/include/plat/marvell/a8k/common/plat_pm_trace.h b/include/plat/marvell/armada/a8k/common/plat_pm_trace.h
similarity index 100%
rename from include/plat/marvell/a8k/common/plat_pm_trace.h
rename to include/plat/marvell/armada/a8k/common/plat_pm_trace.h
diff --git a/include/plat/marvell/common/aarch64/cci_macros.S b/include/plat/marvell/armada/common/aarch64/cci_macros.S
similarity index 100%
rename from include/plat/marvell/common/aarch64/cci_macros.S
rename to include/plat/marvell/armada/common/aarch64/cci_macros.S
diff --git a/include/plat/marvell/common/aarch64/marvell_macros.S b/include/plat/marvell/armada/common/aarch64/marvell_macros.S
similarity index 100%
rename from include/plat/marvell/common/aarch64/marvell_macros.S
rename to include/plat/marvell/armada/common/aarch64/marvell_macros.S
diff --git a/include/plat/marvell/common/marvell_plat_priv.h b/include/plat/marvell/armada/common/marvell_plat_priv.h
similarity index 100%
rename from include/plat/marvell/common/marvell_plat_priv.h
rename to include/plat/marvell/armada/common/marvell_plat_priv.h
diff --git a/include/plat/marvell/common/marvell_pm.h b/include/plat/marvell/armada/common/marvell_pm.h
similarity index 100%
rename from include/plat/marvell/common/marvell_pm.h
rename to include/plat/marvell/armada/common/marvell_pm.h
diff --git a/include/plat/marvell/common/mvebu.h b/include/plat/marvell/armada/common/mvebu.h
similarity index 100%
rename from include/plat/marvell/common/mvebu.h
rename to include/plat/marvell/armada/common/mvebu.h
diff --git a/include/services/ffa_svc.h b/include/services/ffa_svc.h
new file mode 100644
index 0000000..7285077
--- /dev/null
+++ b/include/services/ffa_svc.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FFA_SVC_H
+#define FFA_SVC_H
+
+#include <lib/smccc.h>
+#include <lib/utils_def.h>
+#include <tools_share/uuid.h>
+
+/* FFA error codes. */
+#define FFA_ERROR_NOT_SUPPORTED		-1
+#define FFA_ERROR_INVALID_PARAMETER	-2
+#define FFA_ERROR_NO_MEMORY		-3
+#define FFA_ERROR_BUSY			-4
+#define FFA_ERROR_INTERRUPTED		-5
+#define FFA_ERROR_DENIED		-6
+#define FFA_ERROR_RETRY			-7
+
+/* The macros below are used to identify FFA calls from the SMC function ID */
+#define FFA_FNUM_MIN_VALUE	U(0x60)
+#define FFA_FNUM_MAX_VALUE	U(0x7f)
+#define is_ffa_fid(fid) __extension__ ({		\
+	__typeof__(fid) _fid = (fid);			\
+	((GET_SMC_NUM(_fid) >= FFA_FNUM_MIN_VALUE) &&	\
+	 (GET_SMC_NUM(_fid) <= FFA_FNUM_MAX_VALUE)); })
+
+/* FFA_VERSION helpers */
+#define FFA_VERSION_MAJOR		U(1)
+#define FFA_VERSION_MAJOR_SHIFT		16
+#define FFA_VERSION_MAJOR_MASK		U(0x7FFF)
+#define FFA_VERSION_MINOR		U(0)
+#define FFA_VERSION_MINOR_SHIFT		0
+#define FFA_VERSION_MINOR_MASK		U(0xFFFF)
+#define FFA_VERSION_BIT31_MASK 		U(0x1u << 31)
+
+
+#define MAKE_FFA_VERSION(major, minor) 	\
+	((((major) & FFA_VERSION_MAJOR_MASK) <<  FFA_VERSION_MAJOR_SHIFT) | \
+	 (((minor) & FFA_VERSION_MINOR_MASK) << FFA_VERSION_MINOR_SHIFT))
+#define FFA_VERSION_COMPILED		MAKE_FFA_VERSION(FFA_VERSION_MAJOR, \
+							  FFA_VERSION_MINOR)
+
+/* FFA_MSG_SEND helpers */
+#define FFA_MSG_SEND_ATTRS_BLK_SHIFT	U(0)
+#define FFA_MSG_SEND_ATTRS_BLK_MASK	U(0x1)
+#define FFA_MSG_SEND_ATTRS_BLK		U(0)
+#define FFA_MSG_SEND_ATTRS_BLK_NOT	U(1)
+#define FFA_MSG_SEND_ATTRS(blk)		\
+	(((blk) & FFA_MSG_SEND_ATTRS_BLK_MASK) \
+	<< FFA_MSG_SEND_ATTRS_BLK_SHIFT)
+
+/* Get FFA fastcall std FID from function number */
+#define FFA_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))
+
+/* FFA function numbers */
+#define FFA_FNUM_ERROR			U(0x60)
+#define FFA_FNUM_SUCCESS		U(0x61)
+#define FFA_FNUM_INTERRUPT		U(0x62)
+#define FFA_FNUM_VERSION		U(0x63)
+#define FFA_FNUM_FEATURES		U(0x64)
+#define FFA_FNUM_RX_RELEASE		U(0x65)
+#define FFA_FNUM_RXTX_MAP		U(0x66)
+#define FFA_FNUM_RXTX_UNMAP		U(0x67)
+#define FFA_FNUM_PARTITION_INFO_GET	U(0x68)
+#define FFA_FNUM_ID_GET		U(0x69)
+#define FFA_FNUM_MSG_POLL		U(0x6A)
+#define FFA_FNUM_MSG_WAIT		U(0x6B)
+#define FFA_FNUM_MSG_YIELD		U(0x6C)
+#define FFA_FNUM_MSG_RUN		U(0x6D)
+#define FFA_FNUM_MSG_SEND		U(0x6E)
+#define FFA_FNUM_MSG_SEND_DIRECT_REQ	U(0x6F)
+#define FFA_FNUM_MSG_SEND_DIRECT_RESP	U(0x70)
+#define FFA_FNUM_MEM_DONATE		U(0x71)
+#define FFA_FNUM_MEM_LEND		U(0x72)
+#define FFA_FNUM_MEM_SHARE		U(0x73)
+#define FFA_FNUM_MEM_RETRIEVE_REQ	U(0x74)
+#define FFA_FNUM_MEM_RETRIEVE_RESP	U(0x75)
+#define FFA_FNUM_MEM_RELINQUISH	U(0x76)
+#define FFA_FNUM_MEM_RECLAIM		U(0x77)
+
+/* FFA SMC32 FIDs */
+#define FFA_ERROR		FFA_FID(SMC_32, FFA_FNUM_ERROR)
+#define FFA_SUCCESS_SMC32	FFA_FID(SMC_32, FFA_FNUM_SUCCESS)
+#define FFA_INTERRUPT		FFA_FID(SMC_32, FFA_FNUM_INTERRUPT)
+#define FFA_VERSION		FFA_FID(SMC_32, FFA_FNUM_VERSION)
+#define FFA_FEATURES		FFA_FID(SMC_32, FFA_FNUM_FEATURES)
+#define FFA_RX_RELEASE		FFA_FID(SMC_32, FFA_FNUM_RX_RELEASE)
+#define FFA_RXTX_MAP_SMC32	FFA_FID(SMC_32, FFA_FNUM_RXTX_MAP)
+#define FFA_RXTX_UNMAP		FFA_FID(SMC_32, FFA_FNUM_RXTX_UNMAP)
+#define FFA_PARTITION_INFO_GET	FFA_FID(SMC_32, FFA_FNUM_PARTITION_INFO_GET)
+#define FFA_ID_GET		FFA_FID(SMC_32, FFA_FNUM_ID_GET)
+#define FFA_MSG_POLL		FFA_FID(SMC_32, FFA_FNUM_MSG_POLL)
+#define FFA_MSG_WAIT		FFA_FID(SMC_32, FFA_FNUM_MSG_WAIT)
+#define FFA_MSG_YIELD		FFA_FID(SMC_32, FFA_FNUM_MSG_YIELD)
+#define FFA_MSG_RUN		FFA_FID(SMC_32, FFA_FNUM_MSG_RUN)
+#define FFA_MSG_SEND		FFA_FID(SMC_32, FFA_FNUM_MSG_SEND)
+#define FFA_MSG_SEND_DIRECT_REQ_SMC32 \
+	FFA_FID(SMC_32, FFA_FNUM_MSG_SEND_DIRECT_REQ)
+#define FFA_MSG_SEND_DIRECT_RESP_SMC32	\
+	FFA_FID(SMC_32, FFA_FNUM_MSG_SEND_DIRECT_RESP)
+#define FFA_MEM_DONATE_SMC32	FFA_FID(SMC_32, FFA_FNUM_MEM_DONATE)
+#define FFA_MEM_LEND_SMC32	FFA_FID(SMC_32, FFA_FNUM_MEM_LEND)
+#define FFA_MEM_SHARE_SMC32	FFA_FID(SMC_32, FFA_FNUM_MEM_SHARE)
+#define FFA_MEM_RETRIEVE_REQ_SMC32 \
+	FFA_FID(SMC_32, FFA_FNUM_MEM_RETRIEVE_REQ)
+#define FFA_MEM_RETRIEVE_RESP	FFA_FID(SMC_32, FFA_FNUM_MEM_RETRIEVE_RESP)
+#define FFA_MEM_RELINQUISH	FFA_FID(SMC_32, FFA_FNUM_MEM_RELINQUISH)
+#define FFA_MEM_RECLAIM	FFA_FID(SMC_32, FFA_FNUM_MEM_RECLAIM)
+
+/* FFA SMC64 FIDs */
+#define FFA_SUCCESS_SMC64	FFA_FID(SMC_64, FFA_FNUM_SUCCESS)
+#define FFA_RXTX_MAP_SMC64	FFA_FID(SMC_64, FFA_FNUM_RXTX_MAP)
+#define FFA_MSG_SEND_DIRECT_REQ_SMC64 \
+	FFA_FID(SMC_64, FFA_FNUM_MSG_SEND_DIRECT_REQ)
+#define FFA_MSG_SEND_DIRECT_RESP_SMC64	\
+	FFA_FID(SMC_64, FFA_FNUM_MSG_SEND_DIRECT_RESP)
+#define FFA_MEM_DONATE_SMC64	FFA_FID(SMC_64, FFA_FNUM_MEM_DONATE)
+#define FFA_MEM_LEND_SMC64	FFA_FID(SMC_64, FFA_FNUM_MEM_LEND)
+#define FFA_MEM_SHARE_SMC64	FFA_FID(SMC_64, FFA_FNUM_MEM_SHARE)
+#define FFA_MEM_RETRIEVE_REQ_SMC64 \
+	FFA_FID(SMC_64, FFA_FNUM_MEM_RETRIEVE_REQ)
+
+/*
+ * Reserve a special value for traffic targeted to the Hypervisor or SPM.
+ */
+#define FFA_TARGET_INFO_MBZ		U(0x0)
+
+/*
+ * Reserve a special value for MBZ parameters.
+ */
+#define FFA_PARAM_MBZ			U(0x0)
+
+#endif /* FFA_SVC_H */
diff --git a/include/services/spci_svc.h b/include/services/spci_svc.h
deleted file mode 100644
index 49ba408..0000000
--- a/include/services/spci_svc.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * 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
index 0c43636..64ecce0 100644
--- a/include/services/spm_core_manifest.h
+++ b/include/services/spm_core_manifest.h
@@ -15,7 +15,7 @@
 
 typedef struct spm_core_manifest_sect_attribute {
 	/*
-	 * SPCI version (mandatory).
+	 * FFA version (mandatory).
 	 */
 	uint32_t major_version;
 	uint32_t minor_version;
diff --git a/include/services/spmd_svc.h b/include/services/spmd_svc.h
index a766dcf..1e7e6aa 100644
--- a/include/services/spmd_svc.h
+++ b/include/services/spmd_svc.h
@@ -8,7 +8,7 @@
 #define SPMD_SVC_H
 
 #ifndef __ASSEMBLER__
-#include <services/spci_svc.h>
+#include <services/ffa_svc.h>
 #include <stdint.h>
 
 int spmd_setup(void);
diff --git a/include/tools_share/firmware_image_package.h b/include/tools_share/firmware_image_package.h
index 598d5c2..7342c0c 100644
--- a/include/tools_share/firmware_image_package.h
+++ b/include/tools_share/firmware_image_package.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
  */
@@ -64,6 +64,8 @@
 	{{0xa4,  0x9f, 0x44, 0x11}, {0x5e, 0x63}, {0xe4, 0x11}, 0x87, 0x28, {0x3f, 0x05, 0x72, 0x2a, 0xf3, 0x3d} }
 #define UUID_NON_TRUSTED_FW_CONTENT_CERT \
 	{{0x8e,  0xc4, 0xc1, 0xf3}, {0x5d, 0x63}, {0xe4, 0x11}, 0xa7, 0xa9, {0x87, 0xee, 0x40, 0xb2, 0x3f, 0xa7} }
+#define UUID_SIP_SECURE_PARTITION_CONTENT_CERT \
+	{{0x77,  0x6d, 0xfd, 0x44}, {0x86, 0x97}, {0x4c, 0x3b}, 0x91, 0xeb, {0xc1, 0x3e, 0x02, 0x5a, 0x2a, 0x6f} }
 /* Dynamic configs */
 #define UUID_HW_CONFIG \
 	{{0x08,  0xb8, 0xf1, 0xd9}, {0xc9, 0xcf}, {0x93, 0x49}, 0xa9, 0x62, {0x6f, 0xbc, 0x6b, 0x72, 0x65, 0xcc} }
@@ -75,6 +77,8 @@
 	{{0x26,  0x25, 0x7c, 0x1a}, {0xdb, 0xc6}, {0x7f, 0x47}, 0x8d, 0x96, {0xc4, 0xc4, 0xb0, 0x24, 0x80, 0x21} }
 #define UUID_NT_FW_CONFIG \
 	{{0x28,  0xda, 0x98, 0x15}, {0x93, 0xe8}, {0x7e, 0x44}, 0xac, 0x66, {0x1a, 0xaf, 0x80, 0x15, 0x50, 0xf9} }
+#define UUID_FW_CONFIG \
+	{{0x58,  0x07, 0xe1, 0x6a}, {0x84, 0x59}, {0x47, 0xbe}, 0x8e, 0xd5, {0x64, 0x8e, 0x8d, 0xdd, 0xab, 0x0e} }
 
 typedef struct fip_toc_header {
 	uint32_t	name;
diff --git a/include/tools_share/tbbr_oid.h b/include/tools_share/tbbr_oid.h
index 6bccfdd..37d87d3 100644
--- a/include/tools_share/tbbr_oid.h
+++ b/include/tools_share/tbbr_oid.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
  */
@@ -43,6 +43,7 @@
 #define TRUSTED_BOOT_FW_HASH_OID		"1.3.6.1.4.1.4128.2100.201"
 #define TRUSTED_BOOT_FW_CONFIG_HASH_OID		"1.3.6.1.4.1.4128.2100.202"
 #define HW_CONFIG_HASH_OID			"1.3.6.1.4.1.4128.2100.203"
+#define FW_CONFIG_HASH_OID			"1.3.6.1.4.1.4128.2100.204"
 
 /*
  * Trusted Key Certificate
@@ -145,4 +146,16 @@
 /* NonTrustedFirmwareConfigHash - NT_FW_CONFIG */
 #define NON_TRUSTED_FW_CONFIG_HASH_OID		"1.3.6.1.4.1.4128.2100.1202"
 
+/*
+ * Secure Partitions Content Certificate
+ */
+#define SP_PKG1_HASH_OID			"1.3.6.1.4.1.4128.2100.1301"
+#define SP_PKG2_HASH_OID			"1.3.6.1.4.1.4128.2100.1302"
+#define SP_PKG3_HASH_OID			"1.3.6.1.4.1.4128.2100.1303"
+#define SP_PKG4_HASH_OID			"1.3.6.1.4.1.4128.2100.1304"
+#define SP_PKG5_HASH_OID			"1.3.6.1.4.1.4128.2100.1305"
+#define SP_PKG6_HASH_OID			"1.3.6.1.4.1.4128.2100.1306"
+#define SP_PKG7_HASH_OID			"1.3.6.1.4.1.4128.2100.1307"
+#define SP_PKG8_HASH_OID			"1.3.6.1.4.1.4128.2100.1308"
+
 #endif /* TBBR_OID_H */
diff --git a/lib/aarch32/misc_helpers.S b/lib/aarch32/misc_helpers.S
index 6d2ec1c..e9734ac 100644
--- a/lib/aarch32/misc_helpers.S
+++ b/lib/aarch32/misc_helpers.S
@@ -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
  */
@@ -149,17 +149,16 @@
 	blo	m_loop1
 	ldr	r3, [r1], #4
 	str	r3, [r0], #4
-	sub	r2, r2, #4
-	b	m_loop4
+	subs	r2, r2, #4
+	bne	m_loop4
+	bx	lr
+
 /* copy byte per byte */
 m_loop1:
-	cmp	r2,#0
-	beq	m_end
 	ldrb	r3, [r1], #1
 	strb	r3, [r0], #1
 	subs	r2, r2, #1
 	bne	m_loop1
-m_end:
 	bx	lr
 endfunc memcpy4
 
diff --git a/lib/cpus/aarch64/cortex_a76.S b/lib/cpus/aarch64/cortex_a76.S
index baefa46..10011f7 100644
--- a/lib/cpus/aarch64/cortex_a76.S
+++ b/lib/cpus/aarch64/cortex_a76.S
@@ -392,6 +392,62 @@
 #endif
 endfunc check_errata_1286807
 
+	/* --------------------------------------------------
+	 * Errata workaround for Cortex A76 Errata #1791580.
+	 * This applies to revisions <= r4p0 of Cortex A76.
+	 * Inputs:
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * --------------------------------------------------
+	 */
+func errata_a76_1791580_wa
+	/* Compare x0 against revision r4p0 */
+	mov	x17, x30
+	bl	check_errata_1791580
+	cbz	x0, 1f
+	mrs	x1, CORTEX_A76_CPUACTLR2_EL1
+	orr	x1, x1, CORTEX_A76_CPUACTLR2_EL1_BIT_2
+	msr	CORTEX_A76_CPUACTLR2_EL1, x1
+	isb
+1:
+	ret	x17
+endfunc errata_a76_1791580_wa
+
+func check_errata_1791580
+	/* Applies to everything <=r4p0. */
+	mov	x1, #0x40
+	b	cpu_rev_var_ls
+endfunc check_errata_1791580
+
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex A76 Errata #1800710.
+	 * This applies to revision <= r4p0 of Cortex A76.
+	 * Inputs:
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * --------------------------------------------------
+	 */
+func errata_a76_1800710_wa
+	/* Compare x0 against revision <= r4p0 */
+	mov	x17, x30
+	bl	check_errata_1800710
+	cbz	x0, 1f
+
+	/* Disable allocation of splintered pages in the L2 TLB */
+	mrs	x1, CORTEX_A76_CPUECTLR_EL1
+	orr	x1, x1, CORTEX_A76_CPUECTLR_EL1_BIT_53
+	msr	CORTEX_A76_CPUECTLR_EL1, x1
+	isb
+1:
+	ret	x17
+endfunc errata_a76_1800710_wa
+
+func check_errata_1800710
+	/* Applies to everything <= r4p0 */
+	mov	x1, #0x40
+	b	cpu_rev_var_ls
+endfunc check_errata_1800710
+
 func check_errata_cve_2018_3639
 #if WORKAROUND_CVE_2018_3639
 	mov	x0, #ERRATA_APPLIES
@@ -449,6 +505,16 @@
 	bl	errata_a76_1262888_wa
 #endif
 
+#if ERRATA_A76_1791580
+	mov	x0, x18
+	bl	errata_a76_1791580_wa
+#endif
+
+#if ERRATA_A76_1800710
+	mov	x0, x18
+	bl	errata_a76_1800710_wa
+#endif
+
 #if WORKAROUND_CVE_2018_3639
 	/* If the PE implements SSBS, we don't need the dynamic workaround */
 	mrs	x0, id_aa64pfr1_el1
@@ -529,6 +595,8 @@
 	report_errata ERRATA_A76_1262888, cortex_a76, 1262888
 	report_errata ERRATA_A76_1275112, cortex_a76, 1275112
 	report_errata ERRATA_A76_1286807, cortex_a76, 1286807
+	report_errata ERRATA_A76_1791580, cortex_a76, 1791580
+	report_errata ERRATA_A76_1800710, cortex_a76, 1800710
 	report_errata WORKAROUND_CVE_2018_3639, cortex_a76, cve_2018_3639
 	report_errata ERRATA_DSU_798953, cortex_a76, dsu_798953
 	report_errata ERRATA_DSU_936184, cortex_a76, dsu_936184
diff --git a/lib/cpus/aarch64/cortex_a77.S b/lib/cpus/aarch64/cortex_a77.S
index f3fd5e1..0c30460 100644
--- a/lib/cpus/aarch64/cortex_a77.S
+++ b/lib/cpus/aarch64/cortex_a77.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
  */
@@ -21,6 +21,53 @@
 #error "Cortex-A77 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex A77 Errata #1800714.
+	 * This applies to revision <= r1p1 of Cortex A77.
+	 * Inputs:
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * --------------------------------------------------
+	 */
+func errata_a77_1800714_wa
+	/* Compare x0 against revision <= r1p1 */
+	mov	x17, x30
+	bl	check_errata_1800714
+	cbz	x0, 1f
+
+	/* Disable allocation of splintered pages in the L2 TLB */
+	mrs	x1, CORTEX_A77_CPUECTLR_EL1
+	orr	x1, x1, CORTEX_A77_CPUECTLR_EL1_BIT_53
+	msr	CORTEX_A77_CPUECTLR_EL1, x1
+	isb
+1:
+	ret	x17
+endfunc errata_a77_1800714_wa
+
+func check_errata_1800714
+	/* Applies to everything <= r1p1 */
+	mov	x1, #0x11
+	b	cpu_rev_var_ls
+endfunc check_errata_1800714
+
+	/* -------------------------------------------------
+	 * The CPU Ops reset function for Cortex-A77.
+	 * Shall clobber: x0-x19
+	 * -------------------------------------------------
+	 */
+func cortex_a77_reset_func
+	mov	x19, x30
+	bl	cpu_get_rev_var
+	mov	x18, x0
+
+#if ERRATA_A77_1800714
+	mov	x0, x18
+	bl	errata_a77_1800714_wa
+#endif
+
+	ret	x19
+endfunc cortex_a77_reset_func
+
 	/* ---------------------------------------------
 	 * HW will do the cache maintenance while powering down
 	 * ---------------------------------------------
@@ -42,6 +89,18 @@
  * Errata printing function for Cortex-A77. Must follow AAPCS.
  */
 func cortex_a77_errata_report
+	stp	x8, x30, [sp, #-16]!
+
+	bl	cpu_get_rev_var
+	mov	x8, x0
+
+	/*
+	 * Report all errata. The revision-variant information is passed to
+	 * checking functions of each errata.
+	 */
+	report_errata ERRATA_A77_1800714, cortex_a77, 1800714
+
+	ldp	x8, x30, [sp], #16
 	ret
 endfunc cortex_a77_errata_report
 #endif
@@ -67,5 +126,5 @@
 endfunc cortex_a77_cpu_reg_dump
 
 declare_cpu_ops cortex_a77, CORTEX_A77_MIDR, \
-	CPU_NO_RESET_FUNC, \
+	cortex_a77_reset_func, \
 	cortex_a77_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_a78.S b/lib/cpus/aarch64/cortex_a78.S
new file mode 100644
index 0000000..9914f12
--- /dev/null
+++ b/lib/cpus/aarch64/cortex_a78.S
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2019-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_a78.h>
+#include <cpu_macros.S>
+#include <plat_macros.S>
+
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "cortex_a78 must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
+
+/* --------------------------------------------------
+ * Errata Workaround for A78 Erratum 1688305.
+ * This applies to revision r0p0 and r1p0 of A78.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_a78_1688305_wa
+	/* Compare x0 against revision r1p0 */
+	mov	x17, x30
+	bl	check_errata_1688305
+	cbz	x0, 1f
+	mrs     x1, CORTEX_A78_ACTLR2_EL1
+	orr	x1, x1, CORTEX_A78_ACTLR2_EL1_BIT_1
+	msr     CORTEX_A78_ACTLR2_EL1, x1
+	isb
+1:
+	ret	x17
+endfunc errata_a78_1688305_wa
+
+func check_errata_1688305
+	/* Applies to r0p0 and r1p0 */
+	mov	x1, #0x10
+	b	cpu_rev_var_ls
+endfunc check_errata_1688305
+
+	/* -------------------------------------------------
+	 * The CPU Ops reset function for Cortex-A78
+	 * -------------------------------------------------
+	 */
+func cortex_a78_reset_func
+	mov	x19, x30
+	bl	cpu_get_rev_var
+	mov	x18, x0
+
+#if ERRATA_A78_1688305
+	mov     x0, x18
+	bl	errata_a78_1688305_wa
+#endif
+
+#if ENABLE_AMU
+	/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
+	mrs	x0, actlr_el3
+	bic	x0, x0, #CORTEX_A78_ACTLR_TAM_BIT
+	msr	actlr_el3, x0
+
+	/* Make sure accesses from non-secure EL0/EL1 are not trapped to EL2 */
+	mrs	x0, actlr_el2
+	bic	x0, x0, #CORTEX_A78_ACTLR_TAM_BIT
+	msr	actlr_el2, x0
+
+	/* Enable group0 counters */
+	mov	x0, #CORTEX_A78_AMU_GROUP0_MASK
+	msr	CPUAMCNTENSET0_EL0, x0
+
+	/* Enable group1 counters */
+	mov	x0, #CORTEX_A78_AMU_GROUP1_MASK
+	msr	CPUAMCNTENSET1_EL0, x0
+#endif
+
+	isb
+	ret	x19
+endfunc cortex_a78_reset_func
+
+	/* ---------------------------------------------
+	 * HW will do the cache maintenance while powering down
+	 * ---------------------------------------------
+	 */
+func cortex_a78_core_pwr_dwn
+	/* ---------------------------------------------
+	 * Enable CPU power down bit in power control register
+	 * ---------------------------------------------
+	 */
+	mrs	x0, CORTEX_A78_CPUPWRCTLR_EL1
+	orr	x0, x0, #CORTEX_A78_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT
+	msr	CORTEX_A78_CPUPWRCTLR_EL1, x0
+	isb
+	ret
+endfunc cortex_a78_core_pwr_dwn
+
+	/*
+	 * Errata printing function for cortex_a78. Must follow AAPCS.
+	 */
+#if REPORT_ERRATA
+func cortex_a78_errata_report
+	stp	x8, x30, [sp, #-16]!
+
+	bl	cpu_get_rev_var
+	mov	x8, x0
+
+	/*
+	 * Report all errata. The revision-variant information is passed to
+	 * checking functions of each errata.
+	 */
+	report_errata ERRATA_A78_1688305, cortex_a78, 1688305
+
+	ldp	x8, x30, [sp], #16
+	ret
+endfunc cortex_a78_errata_report
+#endif
+
+	/* ---------------------------------------------
+	 * This function provides cortex_a78 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_a78_regs, "aS"
+cortex_a78_regs:  /* The ascii list of register names to be reported */
+	.asciz	"cpuectlr_el1", ""
+
+func cortex_a78_cpu_reg_dump
+	adr	x6, cortex_a78_regs
+	mrs	x8, CORTEX_A78_CPUECTLR_EL1
+	ret
+endfunc cortex_a78_cpu_reg_dump
+
+declare_cpu_ops cortex_a78, CORTEX_A78_MIDR, \
+	cortex_a78_reset_func, \
+	cortex_a78_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_hercules.S b/lib/cpus/aarch64/cortex_hercules.S
deleted file mode 100644
index a239196..0000000
--- a/lib/cpus/aarch64/cortex_hercules.S
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2019, 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_hercules.h>
-#include <cpu_macros.S>
-#include <plat_macros.S>
-
-/* Hardware handled coherency */
-#if HW_ASSISTED_COHERENCY == 0
-#error "cortex_hercules must be compiled with HW_ASSISTED_COHERENCY enabled"
-#endif
-
-
-/* --------------------------------------------------
- * Errata Workaround for Hercules Erratum 1688305.
- * This applies to revision r0p0 and r1p0 of Hercules.
- * Inputs:
- * x0: variant[4:7] and revision[0:3] of current cpu.
- * Shall clobber: x0-x17
- * --------------------------------------------------
- */
-func errata_hercules_1688305_wa
-	/* Compare x0 against revision r1p0 */
-	mov	x17, x30
-	bl	check_errata_1688305
-	cbz	x0, 1f
-	mrs     x1, CORTEX_HERCULES_ACTLR2_EL1
-	orr	x1, x1, CORTEX_HERCULES_ACTLR2_EL1_BIT_1
-	msr     CORTEX_HERCULES_ACTLR2_EL1, x1
-	isb
-1:
-	ret	x17
-endfunc errata_hercules_1688305_wa
-
-func check_errata_1688305
-	/* Applies to r0p0 and r1p0 */
-	mov	x1, #0x10
-	b	cpu_rev_var_ls
-endfunc check_errata_1688305
-
-	/* -------------------------------------------------
-	 * The CPU Ops reset function for Cortex-Hercules
-	 * -------------------------------------------------
-	 */
-func cortex_hercules_reset_func
-	mov	x19, x30
-	bl	cpu_get_rev_var
-	mov	x18, x0
-
-#if ERRATA_HERCULES_1688305
-	mov     x0, x18
-	bl	errata_hercules_1688305_wa
-#endif
-
-#if ENABLE_AMU
-	/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
-	mrs	x0, actlr_el3
-	bic	x0, x0, #CORTEX_HERCULES_ACTLR_TAM_BIT
-	msr	actlr_el3, x0
-
-	/* Make sure accesses from non-secure EL0/EL1 are not trapped to EL2 */
-	mrs	x0, actlr_el2
-	bic	x0, x0, #CORTEX_HERCULES_ACTLR_TAM_BIT
-	msr	actlr_el2, x0
-
-	/* Enable group0 counters */
-	mov	x0, #CORTEX_HERCULES_AMU_GROUP0_MASK
-	msr	CPUAMCNTENSET0_EL0, x0
-
-	/* Enable group1 counters */
-	mov	x0, #CORTEX_HERCULES_AMU_GROUP1_MASK
-	msr	CPUAMCNTENSET1_EL0, x0
-#endif
-
-	isb
-	ret	x19
-endfunc cortex_hercules_reset_func
-
-	/* ---------------------------------------------
-	 * HW will do the cache maintenance while powering down
-	 * ---------------------------------------------
-	 */
-func cortex_hercules_core_pwr_dwn
-	/* ---------------------------------------------
-	 * Enable CPU power down bit in power control register
-	 * ---------------------------------------------
-	 */
-	mrs	x0, CORTEX_HERCULES_CPUPWRCTLR_EL1
-	orr	x0, x0, #CORTEX_HERCULES_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT
-	msr	CORTEX_HERCULES_CPUPWRCTLR_EL1, x0
-	isb
-	ret
-endfunc cortex_hercules_core_pwr_dwn
-
-	/*
-	 * Errata printing function for cortex_hercules. Must follow AAPCS.
-	 */
-#if REPORT_ERRATA
-func cortex_hercules_errata_report
-	stp	x8, x30, [sp, #-16]!
-
-	bl	cpu_get_rev_var
-	mov	x8, x0
-
-	/*
-	 * Report all errata. The revision-variant information is passed to
-	 * checking functions of each errata.
-	 */
-	report_errata ERRATA_HERCULES_1688305, cortex_hercules, 1688305
-
-	ldp	x8, x30, [sp], #16
-	ret
-endfunc cortex_hercules_errata_report
-#endif
-
-	/* ---------------------------------------------
-	 * This function provides cortex_hercules 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_hercules_regs, "aS"
-cortex_hercules_regs:  /* The ascii list of register names to be reported */
-	.asciz	"cpuectlr_el1", ""
-
-func cortex_hercules_cpu_reg_dump
-	adr	x6, cortex_hercules_regs
-	mrs	x8, CORTEX_HERCULES_CPUECTLR_EL1
-	ret
-endfunc cortex_hercules_cpu_reg_dump
-
-declare_cpu_ops cortex_hercules, CORTEX_HERCULES_MIDR, \
-	cortex_hercules_reset_func, \
-	cortex_hercules_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_hercules_ae.S b/lib/cpus/aarch64/cortex_hercules_ae.S
index c4a2163..4452c41 100644
--- a/lib/cpus/aarch64/cortex_hercules_ae.S
+++ b/lib/cpus/aarch64/cortex_hercules_ae.S
@@ -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
  */
@@ -24,20 +24,20 @@
 func cortex_hercules_ae_reset_func
 	/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
 	mrs	x0, actlr_el3
-	bic	x0, x0, #CORTEX_HERCULES_ACTLR_TAM_BIT
+	bic	x0, x0, #CORTEX_A78_ACTLR_TAM_BIT
 	msr	actlr_el3, x0
 
 	/* Make sure accesses from non-secure EL0/EL1 are not trapped to EL2 */
 	mrs	x0, actlr_el2
-	bic	x0, x0, #CORTEX_HERCULES_ACTLR_TAM_BIT
+	bic	x0, x0, #CORTEX_A78_ACTLR_TAM_BIT
 	msr	actlr_el2, x0
 
 	/* Enable group0 counters */
-	mov	x0, #CORTEX_HERCULES_AMU_GROUP0_MASK
+	mov	x0, #CORTEX_A78_AMU_GROUP0_MASK
 	msr	CPUAMCNTENSET0_EL0, x0
 
 	/* Enable group1 counters */
-	mov	x0, #CORTEX_HERCULES_AMU_GROUP1_MASK
+	mov	x0, #CORTEX_A78_AMU_GROUP1_MASK
 	msr	CPUAMCNTENSET1_EL0, x0
 	isb
 
@@ -54,9 +54,9 @@
 	 * Enable CPU power down bit in power control register
 	 * -------------------------------------------------------
 	 */
-	mrs	x0, CORTEX_HERCULES_CPUPWRCTLR_EL1
-	orr	x0, x0, #CORTEX_HERCULES_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT
-	msr	CORTEX_HERCULES_CPUPWRCTLR_EL1, x0
+	mrs	x0, CORTEX_A78_CPUPWRCTLR_EL1
+	orr	x0, x0, #CORTEX_A78_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT
+	msr	CORTEX_A78_CPUPWRCTLR_EL1, x0
 	isb
 	ret
 endfunc cortex_hercules_ae_core_pwr_dwn
@@ -85,7 +85,7 @@
 
 func cortex_hercules_ae_cpu_reg_dump
 	adr	x6, cortex_hercules_ae_regs
-	mrs	x8, CORTEX_HERCULES_CPUECTLR_EL1
+	mrs	x8, CORTEX_A78_CPUECTLR_EL1
 	ret
 endfunc cortex_hercules_ae_cpu_reg_dump
 
diff --git a/lib/cpus/aarch64/denver.S b/lib/cpus/aarch64/denver.S
index e260f8d..c050b02 100644
--- a/lib/cpus/aarch64/denver.S
+++ b/lib/cpus/aarch64/denver.S
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -33,6 +34,12 @@
 	.macro	apply_workaround
 	stp	x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0]
 
+	/* Disable cycle counter when event counting is prohibited */
+	mrs	x1, pmcr_el0
+	orr	x0, x1, #PMCR_EL0_DP_BIT
+	msr	pmcr_el0, x0
+	isb
+
 	/* -------------------------------------------------
 	 * A new write-only system register where a write of
 	 * 1 to bit 0 will cause the indirect branch predictor
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 3c0c9cd..e494375 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -250,9 +250,21 @@
 # only to revision <= r3p0 of the Cortex A76 cpu.
 ERRATA_A76_1286807	?=0
 
+# Flag to apply erratum 1791580 workaround during reset. This erratum applies
+# only to revision <= r4p0 of the Cortex A76 cpu.
+ERRATA_A76_1791580	?=0
+
+# Flag to apply erratum 1800710 workaround during reset. This erratum applies
+# only to revision <= r4p0 of the Cortex A76 cpu.
+ERRATA_A76_1800710	?=0
+
+# Flag to apply erratum 1800714 workaround during reset. This erratum applies
+# only to revision <= r1p1 of the Cortex A77 cpu.
+ERRATA_A77_1800714	?=0
+
 # Flag to apply erratum 1688305 workaround during reset. This erratum applies
-# to revisions r0p0 - r1p0 of the Hercules cpu.
-ERRATA_HERCULES_1688305	?=0
+# to revisions r0p0 - r1p0 of the A78 cpu.
+ERRATA_A78_1688305	?=0
 
 # Flag to apply T32 CLREX workaround during reset. This erratum applies
 # only to r0p0 and r1p0 of the Neoverse N1 cpu.
@@ -487,9 +499,21 @@
 $(eval $(call assert_boolean,ERRATA_A76_1286807))
 $(eval $(call add_define,ERRATA_A76_1286807))
 
-# Process ERRATA_HERCULES_1688305 flag
-$(eval $(call assert_boolean,ERRATA_HERCULES_1688305))
-$(eval $(call add_define,ERRATA_HERCULES_1688305))
+# Process ERRATA_A76_1791580 flag
+$(eval $(call assert_boolean,ERRATA_A76_1791580))
+$(eval $(call add_define,ERRATA_A76_1791580))
+
+# Process ERRATA_A76_1800710 flag
+$(eval $(call assert_boolean,ERRATA_A76_1800710))
+$(eval $(call add_define,ERRATA_A76_1800710))
+
+# Process ERRATA_A77_1800714 flag
+$(eval $(call assert_boolean,ERRATA_A77_1800714))
+$(eval $(call add_define,ERRATA_A77_1800714))
+
+# Process ERRATA_A78_1688305 flag
+$(eval $(call assert_boolean,ERRATA_A78_1688305))
+$(eval $(call add_define,ERRATA_A78_1688305))
 
 # Process ERRATA_N1_1043202 flag
 $(eval $(call assert_boolean,ERRATA_N1_1043202))
diff --git a/lib/debugfs/devfip.c b/lib/debugfs/devfip.c
index fc14e70..b0ee39a 100644
--- a/lib/debugfs/devfip.c
+++ b/lib/debugfs/devfip.c
@@ -73,8 +73,10 @@
 	{"soc-fw.cfg",		UUID_SOC_FW_CONFIG},
 	{"tos-fw.cfg",		UUID_TOS_FW_CONFIG},
 	{"nt-fw.cfg",		UUID_NT_FW_CONFIG},
+	{"fw.cfg",		UUID_FW_CONFIG},
 	{"rot-k.crt",		UUID_ROT_KEY_CERT},
-	{"nt-k.crt",		UUID_NON_TRUSTED_WORLD_KEY_CERT}
+	{"nt-k.crt",		UUID_NON_TRUSTED_WORLD_KEY_CERT},
+	{"sip-sp.crt",		UUID_SIP_SECURE_PARTITION_CONTENT_CERT}
 };
 
 /*******************************************************************************
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index 984468a..1568ef0 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -71,53 +71,52 @@
 	mrs	x15, far_el2
 	stp	x14, x15, [x0, #CTX_ESR_EL2]
 
-	mrs	x16, fpexc32_el2
-	mrs	x17, hacr_el2
-	stp	x16, x17, [x0, #CTX_FPEXC32_EL2]
+	mrs	x16, hacr_el2
+	mrs	x17, hcr_el2
+	stp	x16, x17, [x0, #CTX_HACR_EL2]
 
-	mrs	x9, hcr_el2
-	mrs	x10, hpfar_el2
-	stp	x9, x10, [x0, #CTX_HCR_EL2]
+	mrs	x9, hpfar_el2
+	mrs	x10, hstr_el2
+	stp	x9, x10, [x0, #CTX_HPFAR_EL2]
 
-	mrs	x11, hstr_el2
-	mrs	x12, ICC_SRE_EL2
-	stp	x11, x12, [x0, #CTX_HSTR_EL2]
+	mrs	x11, ICC_SRE_EL2
+	mrs	x12, ICH_HCR_EL2
+	stp	x11, x12, [x0, #CTX_ICC_SRE_EL2]
 
-	mrs	x13, ICH_HCR_EL2
-	mrs	x14, ICH_VMCR_EL2
-	stp	x13, x14, [x0, #CTX_ICH_HCR_EL2]
+	mrs	x13, ICH_VMCR_EL2
+	mrs	x14, mair_el2
+	stp	x13, x14, [x0, #CTX_ICH_VMCR_EL2]
 
-	mrs	x15, mair_el2
-	mrs	x16, mdcr_el2
-	stp	x15, x16, [x0, #CTX_MAIR_EL2]
+	mrs	x15, mdcr_el2
+	mrs	x16, PMSCR_EL2
+	stp	x15, x16, [x0, #CTX_MDCR_EL2]
 
-	mrs	x17, PMSCR_EL2
-	mrs	x9, sctlr_el2
-	stp	x17, x9, [x0, #CTX_PMSCR_EL2]
+	mrs	x17, sctlr_el2
+	mrs	x9, spsr_el2
+	stp	x17, x9, [x0, #CTX_SCTLR_EL2]
 
-	mrs	x10, spsr_el2
-	mrs	x11, sp_el2
-	stp	x10, x11, [x0, #CTX_SPSR_EL2]
+	mrs	x10, sp_el2
+	mrs	x11, tcr_el2
+	stp	x10, x11, [x0, #CTX_SP_EL2]
 
-	mrs	x12, tcr_el2
-	mrs	x13, tpidr_el2
-	stp	x12, x13, [x0, #CTX_TCR_EL2]
+	mrs	x12, tpidr_el2
+	mrs	x13, ttbr0_el2
+	stp	x12, x13, [x0, #CTX_TPIDR_EL2]
 
-	mrs	x14, ttbr0_el2
-	mrs	x15, vbar_el2
-	stp	x14, x15, [x0, #CTX_TTBR0_EL2]
+	mrs	x14, vbar_el2
+	mrs	x15, vmpidr_el2
+	stp	x14, x15, [x0, #CTX_VBAR_EL2]
 
-	mrs	x16, vmpidr_el2
-	mrs	x17, vpidr_el2
-	stp	x16, x17, [x0, #CTX_VMPIDR_EL2]
+	mrs	x16, vpidr_el2
+	mrs	x17, vtcr_el2
+	stp	x16, x17, [x0, #CTX_VPIDR_EL2]
 
-	mrs	x9, vtcr_el2
-	mrs	x10, vttbr_el2
-	stp	x9, x10, [x0, #CTX_VTCR_EL2]
+	mrs	x9, vttbr_el2
+	str	x9, [x0, #CTX_VTTBR_EL2]
 
 #if CTX_INCLUDE_MTE_REGS
-	mrs	x11, TFSR_EL2
-	str	x11, [x0, #CTX_TFSR_EL2]
+	mrs	x10, TFSR_EL2
+	str	x10, [x0, #CTX_TFSR_EL2]
 #endif
 
 #if ENABLE_MPAM_FOR_LOWER_ELS
@@ -277,51 +276,48 @@
 	msr	esr_el2, x14
 	msr	far_el2, x15
 
-	ldp	x16, x17, [x0, #CTX_FPEXC32_EL2]
-	msr	fpexc32_el2, x16
-	msr	hacr_el2, x17
+	ldp	x16, x17, [x0, #CTX_HACR_EL2]
+	msr	hacr_el2, x16
+	msr	hcr_el2, x17
 
-	ldp	x9, x10, [x0, #CTX_HCR_EL2]
-	msr	hcr_el2, x9
-	msr	hpfar_el2, x10
+	ldp	x9, x10, [x0, #CTX_HPFAR_EL2]
+	msr	hpfar_el2, x9
+	msr	hstr_el2, x10
 
-	ldp	x11, x12, [x0, #CTX_HSTR_EL2]
-	msr	hstr_el2, x11
-	msr	ICC_SRE_EL2, x12
+	ldp	x11, x12, [x0, #CTX_ICC_SRE_EL2]
+	msr	ICC_SRE_EL2, x11
+	msr	ICH_HCR_EL2, x12
 
-	ldp	x13, x14, [x0, #CTX_ICH_HCR_EL2]
-	msr	ICH_HCR_EL2, x13
-	msr	ICH_VMCR_EL2, x14
+	ldp	x13, x14, [x0, #CTX_ICH_VMCR_EL2]
+	msr	ICH_VMCR_EL2, x13
+	msr	mair_el2, x14
 
-	ldp	x15, x16, [x0, #CTX_MAIR_EL2]
-	msr	mair_el2, x15
-	msr	mdcr_el2, x16
+	ldp	x15, x16, [x0, #CTX_MDCR_EL2]
+	msr	mdcr_el2, x15
+	msr	PMSCR_EL2, x16
 
-	ldr	x17, [x0, #CTX_PMSCR_EL2]
-	msr	PMSCR_EL2, x17
+	ldp	x17, x9, [x0, #CTX_SPSR_EL2]
+	msr	spsr_el2, x17
+	msr	sp_el2, x9
 
-	ldp	x10, x11, [x0, #CTX_SPSR_EL2]
-	msr	spsr_el2, x10
-	msr	sp_el2, x11
+	ldp	x10, x11, [x0, #CTX_TPIDR_EL2]
+	msr	tpidr_el2, x10
+	msr	ttbr0_el2, x11
 
-	ldr	x12, [x0, #CTX_TPIDR_EL2]
-	msr	tpidr_el2, x12
+	ldp	x12, x13, [x0, #CTX_VBAR_EL2]
+	msr	vbar_el2, x12
+	msr	vmpidr_el2, x13
 
-	ldp	x14, x15, [x0, #CTX_TTBR0_EL2]
-	msr	ttbr0_el2, x14
-	msr	vbar_el2, x15
+	ldp	x14, x15, [x0, #CTX_VPIDR_EL2]
+	msr	vpidr_el2, x14
+	msr	vtcr_el2, x15
 
-	ldp	x16, x17, [x0, #CTX_VMPIDR_EL2]
-	msr	vmpidr_el2, x16
-	msr	vpidr_el2, x17
-
-	ldp	x9, x10, [x0, #CTX_VTCR_EL2]
-	msr	vtcr_el2, x9
-	msr	vttbr_el2, x10
+	ldr	x16, [x0, #CTX_VTTBR_EL2]
+	msr	vttbr_el2, x16
 
 #if CTX_INCLUDE_MTE_REGS
-	ldr	x11, [x0, #CTX_TFSR_EL2]
-	msr	TFSR_EL2, x11
+	ldr	x17, [x0, #CTX_TFSR_EL2]
+	msr	TFSR_EL2, x17
 #endif
 
 #if ENABLE_MPAM_FOR_LOWER_ELS
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 0314a85..f4a34bf 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -22,6 +22,7 @@
 #include <lib/extensions/mpam.h>
 #include <lib/extensions/spe.h>
 #include <lib/extensions/sve.h>
+#include <lib/extensions/twed.h>
 #include <lib/utils.h>
 
 
@@ -107,6 +108,14 @@
 	if (EP_GET_ST(ep->h.attr) != 0U)
 		scr_el3 |= SCR_ST_BIT;
 
+#if RAS_TRAP_LOWER_EL_ERR_ACCESS
+	/*
+	 * SCR_EL3.TERR: Trap Error record accesses. Accesses to the RAS ERR
+	 * and RAS ERX registers from EL1 and EL2 are trapped to EL3.
+	 */
+	scr_el3 |= SCR_TERR_BIT;
+#endif
+
 #if !HANDLE_EA_EL3_FIRST
 	/*
 	 * SCR_EL3.EA: Do not route External Abort and SError Interrupt External
@@ -172,11 +181,26 @@
 	 * SCR_EL3.HCE: Enable HVC instructions if next execution state is
 	 * AArch64 and next EL is EL2, or if next execution state is AArch32 and
 	 * next mode is Hyp.
+	 * SCR_EL3.FGTEn: Enable Fine Grained Virtualization Traps under the
+	 * same conditions as HVC instructions and when the processor supports
+	 * ARMv8.6-FGT.
+	 * SCR_EL3.ECVEn: Enable Enhanced Counter Virtualization (ECV)
+	 * CNTPOFF_EL2 register under the same conditions as HVC instructions
+	 * and when the processor supports ECV.
 	 */
 	if (((GET_RW(ep->spsr) == MODE_RW_64) && (GET_EL(ep->spsr) == MODE_EL2))
 	    || ((GET_RW(ep->spsr) != MODE_RW_64)
 		&& (GET_M32(ep->spsr) == MODE32_hyp))) {
 		scr_el3 |= SCR_HCE_BIT;
+
+		if (is_armv8_6_fgt_present()) {
+			scr_el3 |= SCR_FGTEN_BIT;
+		}
+
+		if (get_armv8_6_ecv_support()
+		    == ID_AA64MMFR0_EL1_ECV_SELF_SYNCH) {
+			scr_el3 |= SCR_ECVEN_BIT;
+		}
 	}
 
 	/* Enable S-EL2 if the next EL is EL2 and security state is secure */
@@ -229,6 +253,24 @@
 	sctlr_elx |= SCTLR_IESB_BIT;
 #endif
 
+	/* Enable WFE trap delay in SCR_EL3 if supported and configured */
+	if (is_armv8_6_twed_present()) {
+		uint32_t delay = plat_arm_set_twedel_scr_el3();
+
+		if (delay != TWED_DISABLED) {
+			/* Make sure delay value fits */
+			assert((delay & ~SCR_TWEDEL_MASK) == 0U);
+
+			/* Set delay in SCR_EL3 */
+			scr_el3 &= ~(SCR_TWEDEL_MASK << SCR_TWEDEL_SHIFT);
+			scr_el3 |= ((delay & SCR_TWEDEL_MASK)
+					<< SCR_TWEDEL_SHIFT);
+
+			/* Enable WFE delay */
+			scr_el3 |= SCR_TWEDEn_BIT;
+		}
+	}
+
 	/*
 	 * Store the initialised SCTLR_EL1 value in the cpu_context - SCTLR_EL2
 	 * and other EL2 registers are set up by cm_prepare_ns_entry() as they
diff --git a/lib/extensions/mpam/mpam.c b/lib/extensions/mpam/mpam.c
index e794f01..65601dd 100644
--- a/lib/extensions/mpam/mpam.c
+++ b/lib/extensions/mpam/mpam.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
  */
@@ -7,20 +7,16 @@
 #include <stdbool.h>
 
 #include <arch.h>
+#include <arch_features.h>
 #include <arch_helpers.h>
 #include <lib/extensions/mpam.h>
 
-bool mpam_supported(void)
-{
-	uint64_t features = read_id_aa64dfr0_el1() >> ID_AA64PFR0_MPAM_SHIFT;
-
-	return ((features & ID_AA64PFR0_MPAM_MASK) != 0U);
-}
-
 void mpam_enable(bool el2_unused)
 {
-	if (!mpam_supported())
+	/* Check if MPAM is implemented */
+	if (get_mpam_version() == 0U) {
 		return;
+	}
 
 	/*
 	 * Enable MPAM, and disable trapping to EL3 when lower ELs access their
@@ -34,10 +30,11 @@
 	 * If EL2 is implemented and used, enable trapping to EL2.
 	 */
 	if (el2_unused) {
-		write_mpam2_el2(0);
+		write_mpam2_el2(0ULL);
 
-		if ((read_mpamidr_el1() & MPAMIDR_HAS_HCR_BIT) != 0U)
-			write_mpamhcr_el2(0);
+		if ((read_mpamidr_el1() & MPAMIDR_HAS_HCR_BIT) != 0U) {
+			write_mpamhcr_el2(0ULL);
+		}
 	} else {
 		write_mpam2_el2(MPAM2_EL2_TRAPMPAM0EL1 |
 				MPAM2_EL2_TRAPMPAM1EL1);
diff --git a/lib/extensions/ras/ras_common.c b/lib/extensions/ras/ras_common.c
index 64a4852..36f9a95 100644
--- a/lib/extensions/ras/ras_common.c
+++ b/lib/extensions/ras/ras_common.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,6 +19,47 @@
 # error Platform must define RAS priority value
 #endif
 
+/*
+ * Function to convert architecturally-defined primary error code SERR,
+ * bits[7:0] from ERR<n>STATUS to its corresponding error string.
+ */
+const char *ras_serr_to_str(unsigned int serr)
+{
+	const char *str[ERROR_STATUS_NUM_SERR] = {
+		"No error",
+		"IMPLEMENTATION DEFINED error",
+		"Data value from (non-associative) internal memory",
+		"IMPLEMENTATION DEFINED pin",
+		"Assertion failure",
+		"Error detected on internal data path",
+		"Data value from associative memory",
+		"Address/control value from associative memory",
+		"Data value from a TLB",
+		"Address/control value from a TLB",
+		"Data value from producer",
+		"Address/control value from producer",
+		"Data value from (non-associative) external memory",
+		"Illegal address (software fault)",
+		"Illegal access (software fault)",
+		"Illegal state (software fault)",
+		"Internal data register",
+		"Internal control register",
+		"Error response from slave",
+		"External timeout",
+		"Internal timeout",
+		"Deferred error from slave not supported at master"
+	};
+
+	/*
+	 * All other values are reserved. Reserved values might be defined
+	 * in a future version of the architecture
+	 */
+	if (serr >= ERROR_STATUS_NUM_SERR)
+		return "unknown SERR";
+
+	return str[serr];
+}
+
 /* Handler that receives External Aborts on RAS-capable systems */
 int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
 		void *handle, uint64_t flags)
diff --git a/lib/fconf/fconf.c b/lib/fconf/fconf.c
index a5ec143..24b6bcc 100644
--- a/lib/fconf/fconf.c
+++ b/lib/fconf/fconf.c
@@ -9,48 +9,42 @@
 #include <common/debug.h>
 #include <common/fdt_wrappers.h>
 #include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.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 fconf_load_config(unsigned int image_id)
 {
 	int err;
-	/* fconf FW_CONFIG and TB_FW_CONFIG are currently the same DTB */
-	image_info_t arm_tb_fw_info = {
+	const struct dyn_cfg_dtb_info_t *config_info;
+
+	assert((image_id == FW_CONFIG_ID) || (image_id == TB_FW_CONFIG_ID));
+
+	image_info_t config_image_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)
+		.h.attr = 0
 	};
 
-	VERBOSE("FCONF: Loading FW_CONFIG\n");
-	err = load_auth_image(TB_FW_CONFIG_ID, &arm_tb_fw_info);
+	config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, image_id);
+	assert(config_info != NULL);
+
+	config_image_info.image_base = config_info->config_addr;
+	config_image_info.image_max_size = config_info->config_max_size;
+
+	VERBOSE("FCONF: Loading config with image ID: %d\n", image_id);
+	err = load_auth_image(image_id, &config_image_info);
 	if (err != 0) {
-		/* Return if FW_CONFIG is not loaded */
-		VERBOSE("FW_CONFIG not loaded, continuing without it\n");
-		return;
+		VERBOSE("Failed to load config %d\n", image_id);
+		return err;
 	}
 
-	/* 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;
+	INFO("FCONF: Config file with image ID:%d loaded at address = 0x%lx\n",
+		image_id, config_image_info.image_base);
 
-#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);
+	return 0;
 }
 
 void fconf_populate(const char *config_type, uintptr_t config)
@@ -81,7 +75,4 @@
 			}
 		}
 	}
-
-	/* 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
index c087102..b01dc6f 100644
--- a/lib/fconf/fconf.mk
+++ b/lib/fconf/fconf.mk
@@ -8,5 +8,5 @@
 FCONF_SOURCES		:=	lib/fconf/fconf.c
 FCONF_DYN_SOURCES	:=	lib/fconf/fconf_dyn_cfg_getter.c
 
-BL1_SOURCES		+=	${FCONF_SOURCES}
+BL1_SOURCES		+=	${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
 BL2_SOURCES		+=	${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
diff --git a/lib/fconf/fconf_dyn_cfg_getter.c b/lib/fconf/fconf_dyn_cfg_getter.c
index 7b5bd6e..25dd7f9 100644
--- a/lib/fconf/fconf_dyn_cfg_getter.c
+++ b/lib/fconf/fconf_dyn_cfg_getter.c
@@ -12,42 +12,72 @@
 #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)
+/* We currently use FW, TB_FW, SOC_FW, TOS_FW, NT_FW and HW configs  */
+#define MAX_DTB_INFO	U(6)
+/*
+ * Compile time assert if FW_CONFIG_ID is 0 which is more
+ * unlikely as 0 is a valid image ID for FIP as per the current
+ * code but still to avoid code breakage in case of unlikely
+ * event when image IDs get changed.
+ */
+CASSERT(FW_CONFIG_ID != U(0), assert_invalid_fw_config_id);
 
 static struct dyn_cfg_dtb_info_t dtb_infos[MAX_DTB_INFO];
 static OBJECT_POOL_ARRAY(dtb_info_pool, dtb_infos);
 
+/*
+ * This function is used to alloc memory for config information from
+ * global pool and set the configuration information.
+ */
+void set_config_info(uintptr_t config_addr, uint32_t config_max_size,
+			unsigned int config_id)
+{
+	struct dyn_cfg_dtb_info_t *dtb_info;
+
+	dtb_info = pool_alloc(&dtb_info_pool);
+	dtb_info->config_addr = config_addr;
+	dtb_info->config_max_size = config_max_size;
+	dtb_info->config_id = config_id;
+}
+
 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++) {
+	for (index = 0U; index < MAX_DTB_INFO; index++) {
 		if (dtb_infos[index].config_id == config_id) {
-			info = &dtb_infos[index];
-			break;
+			return &dtb_infos[index];
 		}
 	}
 
-	if (index == MAX_DTB_INFO) {
-		WARN("FCONF: Invalid config id %u\n", config_id);
-		info = NULL;
-	}
+	WARN("FCONF: Invalid config id %u\n", config_id);
 
-	return info;
+	return NULL;
 }
 
 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;
 
+	/*
+	 * In case of BL1, fw_config dtb information is already
+	 * populated in global dtb_infos array by 'set_fw_config_info'
+	 * function, Below check is present to avoid re-population of
+	 * fw_config information.
+	 *
+	 * Other BLs, satisfy below check and populate fw_config information
+	 * in global dtb_infos array.
+	 */
+	if (dtb_infos[0].config_id == 0U) {
+		uint32_t config_max_size = fdt_totalsize(dtb);
+		set_config_info(config, config_max_size, FW_CONFIG_ID);
+	}
+
 	/* Find the node offset point to "fconf,dyn_cfg-dtb_registry" compatible property */
 	const char *compatible_str = "fconf,dyn_cfg-dtb_registry";
 	node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
@@ -57,37 +87,36 @@
 	}
 
 	fdt_for_each_subnode(child, dtb, node) {
-		uint32_t val32;
+		uint32_t config_max_size, config_id;
+		uintptr_t config_addr;
 		uint64_t val64;
 
-		dtb_info = pool_alloc(&dtb_info_pool);
-
 		/* Read configuration dtb information */
 		rc = fdt_read_uint64(dtb, child, "load-address", &val64);
 		if (rc < 0) {
 			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
 			return rc;
 		}
-		dtb_info->config_addr = (uintptr_t)val64;
+		config_addr = (uintptr_t)val64;
 
-		rc = fdt_read_uint32(dtb, child, "max-size", &val32);
+		rc = fdt_read_uint32(dtb, child, "max-size", &config_max_size);
 		if (rc < 0) {
 			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
 			return rc;
 		}
-		dtb_info->config_max_size = val32;
 
-		rc = fdt_read_uint32(dtb, child, "id", &val32);
+		rc = fdt_read_uint32(dtb, child, "id", &config_id);
 		if (rc < 0) {
 			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
 			return rc;
 		}
-		dtb_info->config_id = val32;
 
 		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);
+		VERBOSE("\tload-address = %lx\n", config_addr);
+		VERBOSE("\tmax-size = 0x%x\n", config_max_size);
+		VERBOSE("\tconfig-id = %u\n", config_id);
+
+		set_config_info(config_addr, config_max_size, config_id);
 	}
 
 	if ((child < 0) && (child != -FDT_ERR_NOTFOUND)) {
@@ -98,4 +127,4 @@
 	return 0;
 }
 
-FCONF_REGISTER_POPULATOR(TB_FW, dyn_cfg, fconf_populate_dtb_registry);
+FCONF_REGISTER_POPULATOR(FW_CONFIG, dyn_cfg, fconf_populate_dtb_registry);
diff --git a/lib/fconf/fconf_tbbr_getter.c b/lib/fconf/fconf_tbbr_getter.c
index 2127801..9a20ced 100644
--- a/lib/fconf/fconf_tbbr_getter.c
+++ b/lib/fconf/fconf_tbbr_getter.c
@@ -27,20 +27,25 @@
 	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);
+		ERROR("FCONF: Can't find `%s` compatible in dtb\n",
+						compatible_str);
 		return node;
 	}
 
 	/* Locate the disable_auth cell and read the value */
-	err = fdt_read_uint32(dtb, node, "disable_auth", &tbbr_dyn_config.disable_auth);
+	err = fdt_read_uint32(dtb, node, "disable_auth",
+					&tbbr_dyn_config.disable_auth);
 	if (err < 0) {
-		WARN("FCONF: Read cell failed for `disable_auth`\n");
+		WARN("FCONF: Read %s failed for `%s`\n",
+				"cell", "disable_auth");
 		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);
+	if ((tbbr_dyn_config.disable_auth != 0U) &&
+	    (tbbr_dyn_config.disable_auth != 1U)) {
+		WARN("Invalid value for `%s` cell %d\n",
+			"disable_auth", tbbr_dyn_config.disable_auth);
 		return -1;
 	}
 
@@ -52,25 +57,40 @@
 	/* Retrieve the Mbed TLS heap details from the DTB */
 	err = fdt_read_uint64(dtb, node, "mbedtls_heap_addr", &val64);
 	if (err < 0) {
-		ERROR("FCONF: Read cell failed for mbedtls_heap\n");
+		ERROR("FCONF: Read %s failed for `%s`\n",
+			"cell", "mbedtls_heap_addr");
 		return err;
 	}
 	tbbr_dyn_config.mbedtls_heap_addr = (void *)(uintptr_t)val64;
 
 	err = fdt_read_uint32(dtb, node, "mbedtls_heap_size", &val32);
 	if (err < 0) {
-		ERROR("FCONF: Read cell failed for mbedtls_heap\n");
+		ERROR("FCONF: Read %s failed for `%s`\n",
+			"cell", "mbedtls_heap_size");
 		return err;
 	}
 	tbbr_dyn_config.mbedtls_heap_size = val32;
 
-	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);
-
+#if MEASURED_BOOT
+	/* Retrieve BL2 hash data details from the DTB */
+	err = fdtw_read_bytes(dtb, node, "bl2_hash_data", TCG_DIGEST_SIZE,
+				&tbbr_dyn_config.bl2_hash_data);
+	if (err < 0) {
+		ERROR("FCONF: Read %s failed for '%s'\n",
+				"bytes", "bl2_hash_data");
+		return err;
+	}
+#endif
+	VERBOSE("%s%s%s %d\n", "FCONF: `tbbr.", "disable_auth",
+		"` cell found with value =", tbbr_dyn_config.disable_auth);
+	VERBOSE("%s%s%s %p\n", "FCONF: `tbbr.", "mbedtls_heap_addr",
+		"` cell found with value =", tbbr_dyn_config.mbedtls_heap_addr);
+	VERBOSE("%s%s%s %zu\n", "FCONF: `tbbr.", "mbedtls_heap_size",
+		"` cell found with value =", tbbr_dyn_config.mbedtls_heap_size);
+#if MEASURED_BOOT
+	VERBOSE("%s%s%s %p\n", "FCONF: `tbbr.", "bl2_hash_data",
+		"` array found at address =", tbbr_dyn_config.bl2_hash_data);
+#endif
 	return 0;
 }
 
diff --git a/lib/libfdt/fdt.c b/lib/libfdt/fdt.c
index 7855a17..c28fcc1 100644
--- a/lib/libfdt/fdt.c
+++ b/lib/libfdt/fdt.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "libfdt_env.h"
 
@@ -55,22 +10,125 @@
 
 #include "libfdt_internal.h"
 
-int fdt_check_header(const void *fdt)
+/*
+ * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks
+ * that the given buffer contains what appears to be a flattened
+ * device tree with sane information in its header.
+ */
+int32_t fdt_ro_probe_(const void *fdt)
 {
+	uint32_t totalsize = fdt_totalsize(fdt);
+
+	if (can_assume(VALID_DTB))
+		return totalsize;
+
 	if (fdt_magic(fdt) == FDT_MAGIC) {
 		/* Complete tree */
-		if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
-			return -FDT_ERR_BADVERSION;
-		if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
-			return -FDT_ERR_BADVERSION;
+		if (!can_assume(LATEST)) {
+			if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+				return -FDT_ERR_BADVERSION;
+			if (fdt_last_comp_version(fdt) >
+					FDT_LAST_SUPPORTED_VERSION)
+				return -FDT_ERR_BADVERSION;
+		}
 	} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
 		/* Unfinished sequential-write blob */
-		if (fdt_size_dt_struct(fdt) == 0)
+		if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt) == 0)
 			return -FDT_ERR_BADSTATE;
 	} else {
 		return -FDT_ERR_BADMAGIC;
 	}
 
+	if (totalsize < INT32_MAX)
+		return totalsize;
+	else
+		return -FDT_ERR_TRUNCATED;
+}
+
+static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off)
+{
+	return (off >= hdrsize) && (off <= totalsize);
+}
+
+static int check_block_(uint32_t hdrsize, uint32_t totalsize,
+			uint32_t base, uint32_t size)
+{
+	if (!check_off_(hdrsize, totalsize, base))
+		return 0; /* block start out of bounds */
+	if ((base + size) < base)
+		return 0; /* overflow */
+	if (!check_off_(hdrsize, totalsize, base + size))
+		return 0; /* block end out of bounds */
+	return 1;
+}
+
+size_t fdt_header_size_(uint32_t version)
+{
+	if (version <= 1)
+		return FDT_V1_SIZE;
+	else if (version <= 2)
+		return FDT_V2_SIZE;
+	else if (version <= 3)
+		return FDT_V3_SIZE;
+	else if (version <= 16)
+		return FDT_V16_SIZE;
+	else
+		return FDT_V17_SIZE;
+}
+
+size_t fdt_header_size(const void *fdt)
+{
+	return can_assume(LATEST) ? FDT_V17_SIZE :
+		fdt_header_size_(fdt_version(fdt));
+}
+
+int fdt_check_header(const void *fdt)
+{
+	size_t hdrsize;
+
+	if (fdt_magic(fdt) != FDT_MAGIC)
+		return -FDT_ERR_BADMAGIC;
+	if (!can_assume(LATEST)) {
+		if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+		    || (fdt_last_comp_version(fdt) >
+			FDT_LAST_SUPPORTED_VERSION))
+			return -FDT_ERR_BADVERSION;
+		if (fdt_version(fdt) < fdt_last_comp_version(fdt))
+			return -FDT_ERR_BADVERSION;
+	}
+	hdrsize = fdt_header_size(fdt);
+	if (!can_assume(VALID_DTB)) {
+
+		if ((fdt_totalsize(fdt) < hdrsize)
+		    || (fdt_totalsize(fdt) > INT_MAX))
+			return -FDT_ERR_TRUNCATED;
+
+		/* Bounds check memrsv block */
+		if (!check_off_(hdrsize, fdt_totalsize(fdt),
+				fdt_off_mem_rsvmap(fdt)))
+			return -FDT_ERR_TRUNCATED;
+	}
+
+	if (!can_assume(VALID_DTB)) {
+		/* Bounds check structure block */
+		if (!can_assume(LATEST) && fdt_version(fdt) < 17) {
+			if (!check_off_(hdrsize, fdt_totalsize(fdt),
+					fdt_off_dt_struct(fdt)))
+				return -FDT_ERR_TRUNCATED;
+		} else {
+			if (!check_block_(hdrsize, fdt_totalsize(fdt),
+					  fdt_off_dt_struct(fdt),
+					  fdt_size_dt_struct(fdt)))
+				return -FDT_ERR_TRUNCATED;
+		}
+
+		/* Bounds check strings block */
+		if (!check_block_(hdrsize, fdt_totalsize(fdt),
+				  fdt_off_dt_strings(fdt),
+				  fdt_size_dt_strings(fdt)))
+			return -FDT_ERR_TRUNCATED;
+	}
+
 	return 0;
 }
 
@@ -78,12 +136,13 @@
 {
 	unsigned absoffset = offset + fdt_off_dt_struct(fdt);
 
-	if ((absoffset < offset)
-	    || ((absoffset + len) < absoffset)
-	    || (absoffset + len) > fdt_totalsize(fdt))
-		return NULL;
+	if (!can_assume(VALID_INPUT))
+		if ((absoffset < offset)
+		    || ((absoffset + len) < absoffset)
+		    || (absoffset + len) > fdt_totalsize(fdt))
+			return NULL;
 
-	if (fdt_version(fdt) >= 0x11)
+	if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)
 		if (((offset + len) < offset)
 		    || ((offset + len) > fdt_size_dt_struct(fdt)))
 			return NULL;
@@ -100,7 +159,7 @@
 
 	*nextoffset = -FDT_ERR_TRUNCATED;
 	tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
-	if (!tagp)
+	if (!can_assume(VALID_DTB) && !tagp)
 		return FDT_END; /* premature end */
 	tag = fdt32_to_cpu(*tagp);
 	offset += FDT_TAGSIZE;
@@ -112,18 +171,19 @@
 		do {
 			p = fdt_offset_ptr(fdt, offset++, 1);
 		} while (p && (*p != '\0'));
-		if (!p)
+		if (!can_assume(VALID_DTB) && !p)
 			return FDT_END; /* premature end */
 		break;
 
 	case FDT_PROP:
 		lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
-		if (!lenp)
+		if (!can_assume(VALID_DTB) && !lenp)
 			return FDT_END; /* premature end */
 		/* skip-name offset, length and value */
 		offset += sizeof(struct fdt_property) - FDT_TAGSIZE
 			+ fdt32_to_cpu(*lenp);
-		if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
+		if (!can_assume(LATEST) &&
+		    fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
 		    ((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
 			offset += 4;
 		break;
@@ -146,6 +206,8 @@
 
 int fdt_check_node_offset_(const void *fdt, int offset)
 {
+	if (can_assume(VALID_INPUT))
+		return offset;
 	if ((offset < 0) || (offset % FDT_TAGSIZE)
 	    || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
 		return -FDT_ERR_BADOFFSET;
@@ -244,7 +306,7 @@
 
 int fdt_move(const void *fdt, void *buf, int bufsize)
 {
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	if (fdt_totalsize(fdt) > bufsize)
 		return -FDT_ERR_NOSPACE;
diff --git a/lib/libfdt/fdt_addresses.c b/lib/libfdt/fdt_addresses.c
index eff4dbc..9a82cd0 100644
--- a/lib/libfdt/fdt_addresses.c
+++ b/lib/libfdt/fdt_addresses.c
@@ -1,52 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Copyright (C) 2018 embedded brains GmbH
  */
 #include "libfdt_env.h"
 
@@ -55,42 +11,91 @@
 
 #include "libfdt_internal.h"
 
-int fdt_address_cells(const void *fdt, int nodeoffset)
+static int fdt_cells(const void *fdt, int nodeoffset, const char *name)
 {
-	const fdt32_t *ac;
-	int val;
+	const fdt32_t *c;
+	uint32_t val;
 	int len;
 
-	ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len);
-	if (!ac)
+	c = fdt_getprop(fdt, nodeoffset, name, &len);
+	if (!c)
+		return len;
+
+	if (len != sizeof(*c))
+		return -FDT_ERR_BADNCELLS;
+
+	val = fdt32_to_cpu(*c);
+	if (val > FDT_MAX_NCELLS)
+		return -FDT_ERR_BADNCELLS;
+
+	return (int)val;
+}
+
+int fdt_address_cells(const void *fdt, int nodeoffset)
+{
+	int val;
+
+	val = fdt_cells(fdt, nodeoffset, "#address-cells");
+	if (val == 0)
+		return -FDT_ERR_BADNCELLS;
+	if (val == -FDT_ERR_NOTFOUND)
 		return 2;
-
-	if (len != sizeof(*ac))
-		return -FDT_ERR_BADNCELLS;
-
-	val = fdt32_to_cpu(*ac);
-	if ((val <= 0) || (val > FDT_MAX_NCELLS))
-		return -FDT_ERR_BADNCELLS;
-
 	return val;
 }
 
 int fdt_size_cells(const void *fdt, int nodeoffset)
 {
-	const fdt32_t *sc;
 	int val;
-	int len;
 
-	sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len);
-	if (!sc)
-		return 2;
-
-	if (len != sizeof(*sc))
-		return -FDT_ERR_BADNCELLS;
-
-	val = fdt32_to_cpu(*sc);
-	if ((val < 0) || (val > FDT_MAX_NCELLS))
-		return -FDT_ERR_BADNCELLS;
-
+	val = fdt_cells(fdt, nodeoffset, "#size-cells");
+	if (val == -FDT_ERR_NOTFOUND)
+		return 1;
 	return val;
 }
+
+/* This function assumes that [address|size]_cells is 1 or 2 */
+int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
+			     const char *name, uint64_t addr, uint64_t size)
+{
+	int addr_cells, size_cells, ret;
+	uint8_t data[sizeof(fdt64_t) * 2], *prop;
+
+	ret = fdt_address_cells(fdt, parent);
+	if (ret < 0)
+		return ret;
+	addr_cells = ret;
+
+	ret = fdt_size_cells(fdt, parent);
+	if (ret < 0)
+		return ret;
+	size_cells = ret;
+
+	/* check validity of address */
+	prop = data;
+	if (addr_cells == 1) {
+		if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size))
+			return -FDT_ERR_BADVALUE;
+
+		fdt32_st(prop, (uint32_t)addr);
+	} else if (addr_cells == 2) {
+		fdt64_st(prop, addr);
+	} else {
+		return -FDT_ERR_BADNCELLS;
+	}
+
+	/* check validity of size */
+	prop += addr_cells * sizeof(fdt32_t);
+	if (size_cells == 1) {
+		if (size > UINT32_MAX)
+			return -FDT_ERR_BADVALUE;
+
+		fdt32_st(prop, (uint32_t)size);
+	} else if (size_cells == 2) {
+		fdt64_st(prop, size);
+	} else {
+		return -FDT_ERR_BADNCELLS;
+	}
+
+	return fdt_appendprop(fdt, nodeoffset, name, data,
+			      (addr_cells + size_cells) * sizeof(fdt32_t));
+}
diff --git a/lib/libfdt/fdt_empty_tree.c b/lib/libfdt/fdt_empty_tree.c
index f2ae9b7..49d54d4 100644
--- a/lib/libfdt/fdt_empty_tree.c
+++ b/lib/libfdt/fdt_empty_tree.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2012 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "libfdt_env.h"
 
diff --git a/lib/libfdt/fdt_overlay.c b/lib/libfdt/fdt_overlay.c
index bf75388..b310e49 100644
--- a/lib/libfdt/fdt_overlay.c
+++ b/lib/libfdt/fdt_overlay.c
@@ -1,53 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2016 Free Electrons
  * Copyright (C) 2016 NextThing Co.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "libfdt_env.h"
 
@@ -93,11 +48,11 @@
  * @pathp: pointer which receives the path of the target (or NULL)
  *
  * overlay_get_target() retrieves the target offset in the base
- * device tree of a fragment, no matter how the actual targetting is
+ * device tree of a fragment, no matter how the actual targeting is
  * done (through a phandle or a path)
  *
  * returns:
- *      the targetted node offset in the base device tree
+ *      the targeted node offset in the base device tree
  *      Negative error code on error
  */
 static int overlay_get_target(const void *fdt, const void *fdto,
@@ -697,7 +652,7 @@
 	int len = 0, namelen;
 	const char *name;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	for (;;) {
 		name = fdt_get_name(fdt, nodeoffset, &namelen);
@@ -778,26 +733,36 @@
 		/* keep end marker to avoid strlen() */
 		e = path + path_len;
 
-		/* format: /<fragment-name>/__overlay__/<relative-subnode-path> */
-
 		if (*path != '/')
 			return -FDT_ERR_BADVALUE;
 
 		/* get fragment name first */
 		s = strchr(path + 1, '/');
-		if (!s)
-			return -FDT_ERR_BADOVERLAY;
+		if (!s) {
+			/* Symbol refers to something that won't end
+			 * up in the target tree */
+			continue;
+		}
 
 		frag_name = path + 1;
 		frag_name_len = s - path - 1;
 
 		/* verify format; safe since "s" lies in \0 terminated prop */
 		len = sizeof("/__overlay__/") - 1;
-		if ((e - s) < len || memcmp(s, "/__overlay__/", len))
-			return -FDT_ERR_BADOVERLAY;
-
-		rel_path = s + len;
-		rel_path_len = e - rel_path;
+		if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) {
+			/* /<fragment-name>/__overlay__/<relative-subnode-path> */
+			rel_path = s + len;
+			rel_path_len = e - rel_path - 1;
+		} else if ((e - s) == len
+			   && (memcmp(s, "/__overlay__", len - 1) == 0)) {
+			/* /<fragment-name>/__overlay__ */
+			rel_path = "";
+			rel_path_len = 0;
+		} else {
+			/* Symbol refers to something that won't end
+			 * up in the target tree */
+			continue;
+		}
 
 		/* find the fragment index in which the symbol lies */
 		ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
@@ -863,11 +828,15 @@
 
 int fdt_overlay_apply(void *fdt, void *fdto)
 {
-	uint32_t delta = fdt_get_max_phandle(fdt);
+	uint32_t delta;
 	int ret;
 
-	FDT_CHECK_HEADER(fdt);
-	FDT_CHECK_HEADER(fdto);
+	FDT_RO_PROBE(fdt);
+	FDT_RO_PROBE(fdto);
+
+	ret = fdt_find_max_phandle(fdt, &delta);
+	if (ret)
+		goto err;
 
 	ret = overlay_adjust_local_phandles(fdto, delta);
 	if (ret)
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index dfb3236..e03570a 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "libfdt_env.h"
 
@@ -76,60 +31,169 @@
 		return 0;
 }
 
+const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
+{
+	int32_t totalsize;
+	uint32_t absoffset;
+	size_t len;
+	int err;
+	const char *s, *n;
+
+	if (can_assume(VALID_INPUT)) {
+		s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+
+		if (lenp)
+			*lenp = strlen(s);
+		return s;
+	}
+	totalsize = fdt_ro_probe_(fdt);
+	err = totalsize;
+	if (totalsize < 0)
+		goto fail;
+
+	err = -FDT_ERR_BADOFFSET;
+	absoffset = stroffset + fdt_off_dt_strings(fdt);
+	if (absoffset >= totalsize)
+		goto fail;
+	len = totalsize - absoffset;
+
+	if (fdt_magic(fdt) == FDT_MAGIC) {
+		if (stroffset < 0)
+			goto fail;
+		if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
+			if (stroffset >= fdt_size_dt_strings(fdt))
+				goto fail;
+			if ((fdt_size_dt_strings(fdt) - stroffset) < len)
+				len = fdt_size_dt_strings(fdt) - stroffset;
+		}
+	} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
+		if ((stroffset >= 0)
+		    || (stroffset < -fdt_size_dt_strings(fdt)))
+			goto fail;
+		if ((-stroffset) < len)
+			len = -stroffset;
+	} else {
+		err = -FDT_ERR_INTERNAL;
+		goto fail;
+	}
+
+	s = (const char *)fdt + absoffset;
+	n = memchr(s, '\0', len);
+	if (!n) {
+		/* missing terminating NULL */
+		err = -FDT_ERR_TRUNCATED;
+		goto fail;
+	}
+
+	if (lenp)
+		*lenp = n - s;
+	return s;
+
+fail:
+	if (lenp)
+		*lenp = err;
+	return NULL;
+}
+
 const char *fdt_string(const void *fdt, int stroffset)
 {
-	return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+	return fdt_get_string(fdt, stroffset, NULL);
 }
 
 static int fdt_string_eq_(const void *fdt, int stroffset,
 			  const char *s, int len)
 {
-	const char *p = fdt_string(fdt, stroffset);
+	int slen;
+	const char *p = fdt_get_string(fdt, stroffset, &slen);
 
-	return (strlen(p) == len) && (memcmp(p, s, len) == 0);
+	return p && (slen == len) && (memcmp(p, s, len) == 0);
 }
 
-uint32_t fdt_get_max_phandle(const void *fdt)
+int fdt_find_max_phandle(const void *fdt, uint32_t *phandle)
 {
-	uint32_t max_phandle = 0;
-	int offset;
+	uint32_t max = 0;
+	int offset = -1;
 
-	for (offset = fdt_next_node(fdt, -1, NULL);;
-	     offset = fdt_next_node(fdt, offset, NULL)) {
-		uint32_t phandle;
+	while (true) {
+		uint32_t value;
 
-		if (offset == -FDT_ERR_NOTFOUND)
-			return max_phandle;
+		offset = fdt_next_node(fdt, offset, NULL);
+		if (offset < 0) {
+			if (offset == -FDT_ERR_NOTFOUND)
+				break;
 
-		if (offset < 0)
-			return (uint32_t)-1;
+			return offset;
+		}
 
-		phandle = fdt_get_phandle(fdt, offset);
-		if (phandle == (uint32_t)-1)
-			continue;
+		value = fdt_get_phandle(fdt, offset);
 
-		if (phandle > max_phandle)
-			max_phandle = phandle;
+		if (value > max)
+			max = value;
 	}
 
+	if (phandle)
+		*phandle = max;
+
 	return 0;
 }
 
+int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
+{
+	uint32_t max;
+	int err;
+
+	err = fdt_find_max_phandle(fdt, &max);
+	if (err < 0)
+		return err;
+
+	if (max == FDT_MAX_PHANDLE)
+		return -FDT_ERR_NOPHANDLES;
+
+	if (phandle)
+		*phandle = max + 1;
+
+	return 0;
+}
+
+static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
+{
+	int offset = n * sizeof(struct fdt_reserve_entry);
+	int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
+
+	if (!can_assume(VALID_INPUT)) {
+		if (absoffset < fdt_off_mem_rsvmap(fdt))
+			return NULL;
+		if (absoffset > fdt_totalsize(fdt) -
+		    sizeof(struct fdt_reserve_entry))
+			return NULL;
+	}
+	return fdt_mem_rsv_(fdt, n);
+}
+
 int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
 {
-	FDT_CHECK_HEADER(fdt);
-	*address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address);
-	*size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size);
+	const struct fdt_reserve_entry *re;
+
+	FDT_RO_PROBE(fdt);
+	re = fdt_mem_rsv(fdt, n);
+	if (!can_assume(VALID_INPUT) && !re)
+		return -FDT_ERR_BADOFFSET;
+
+	*address = fdt64_ld(&re->address);
+	*size = fdt64_ld(&re->size);
 	return 0;
 }
 
 int fdt_num_mem_rsv(const void *fdt)
 {
-	int i = 0;
+	int i;
+	const struct fdt_reserve_entry *re;
 
-	while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0)
-		i++;
-	return i;
+	for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
+		if (fdt64_ld(&re->size) == 0)
+			return i;
+	}
+	return -FDT_ERR_TRUNCATED;
 }
 
 static int nextprop_(const void *fdt, int offset)
@@ -161,7 +225,7 @@
 {
 	int depth;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	for (depth = 0;
 	     (offset >= 0) && (depth >= 0);
@@ -187,7 +251,7 @@
 	const char *p = path;
 	int offset = 0;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	/* see if we have an alias */
 	if (*path != '/') {
@@ -237,13 +301,13 @@
 	const char *nameptr;
 	int err;
 
-	if (((err = fdt_check_header(fdt)) != 0)
+	if (((err = fdt_ro_probe_(fdt)) < 0)
 	    || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
 			goto fail;
 
 	nameptr = nh->name;
 
-	if (fdt_version(fdt) < 0x10) {
+	if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
 		/*
 		 * For old FDT versions, match the naming conventions of V16:
 		 * give only the leaf name (after all /). The actual tree
@@ -294,7 +358,8 @@
 	int err;
 	const struct fdt_property *prop;
 
-	if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) {
+	if (!can_assume(VALID_INPUT) &&
+	    (err = fdt_check_prop_offset_(fdt, offset)) < 0) {
 		if (lenp)
 			*lenp = err;
 		return NULL;
@@ -303,7 +368,7 @@
 	prop = fdt_offset_ptr_(fdt, offset);
 
 	if (lenp)
-		*lenp = fdt32_to_cpu(prop->len);
+		*lenp = fdt32_ld(&prop->len);
 
 	return prop;
 }
@@ -315,7 +380,7 @@
 	/* Prior to version 16, properties may need realignment
 	 * and this API does not work. fdt_getprop_*() will, however. */
 
-	if (fdt_version(fdt) < 0x10) {
+	if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
 		if (lenp)
 			*lenp = -FDT_ERR_BADVERSION;
 		return NULL;
@@ -336,11 +401,12 @@
 	     (offset = fdt_next_property_offset(fdt, offset))) {
 		const struct fdt_property *prop;
 
-		if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) {
+		prop = fdt_get_property_by_offset_(fdt, offset, lenp);
+		if (!can_assume(LIBFDT_FLAWLESS) && !prop) {
 			offset = -FDT_ERR_INTERNAL;
 			break;
 		}
-		if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
+		if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
 				   name, namelen)) {
 			if (poffset)
 				*poffset = offset;
@@ -361,7 +427,7 @@
 {
 	/* Prior to version 16, properties may need realignment
 	 * and this API does not work. fdt_getprop_*() will, however. */
-	if (fdt_version(fdt) < 0x10) {
+	if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
 		if (lenp)
 			*lenp = -FDT_ERR_BADVERSION;
 		return NULL;
@@ -392,8 +458,8 @@
 		return NULL;
 
 	/* Handle realignment */
-	if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 &&
-	    fdt32_to_cpu(prop->len) >= 8)
+	if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
+	    (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
 		return prop->data + 4;
 	return prop->data;
 }
@@ -406,12 +472,27 @@
 	prop = fdt_get_property_by_offset_(fdt, offset, lenp);
 	if (!prop)
 		return NULL;
-	if (namep)
-		*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+	if (namep) {
+		const char *name;
+		int namelen;
+
+		if (!can_assume(VALID_INPUT)) {
+			name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
+					      &namelen);
+			if (!name) {
+				if (lenp)
+					*lenp = namelen;
+				return NULL;
+			}
+			*namep = name;
+		} else {
+			*namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
+		}
+	}
 
 	/* Handle realignment */
-	if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
-	    fdt32_to_cpu(prop->len) >= 8)
+	if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
+	    (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
 		return prop->data + 4;
 	return prop->data;
 }
@@ -436,7 +517,7 @@
 			return 0;
 	}
 
-	return fdt32_to_cpu(*php);
+	return fdt32_ld(php);
 }
 
 const char *fdt_get_alias_namelen(const void *fdt,
@@ -462,7 +543,7 @@
 	int offset, depth, namelen;
 	const char *name;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	if (buflen < 2)
 		return -FDT_ERR_NOSPACE;
@@ -514,7 +595,7 @@
 	int offset, depth;
 	int supernodeoffset = -FDT_ERR_INTERNAL;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	if (supernodedepth < 0)
 		return -FDT_ERR_NOTFOUND;
@@ -536,10 +617,12 @@
 		}
 	}
 
-	if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
-		return -FDT_ERR_BADOFFSET;
-	else if (offset == -FDT_ERR_BADOFFSET)
-		return -FDT_ERR_BADSTRUCTURE;
+	if (!can_assume(VALID_INPUT)) {
+		if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+			return -FDT_ERR_BADOFFSET;
+		else if (offset == -FDT_ERR_BADOFFSET)
+			return -FDT_ERR_BADSTRUCTURE;
+	}
 
 	return offset; /* error from fdt_next_node() */
 }
@@ -551,7 +634,8 @@
 
 	err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
 	if (err)
-		return (err < 0) ? err : -FDT_ERR_INTERNAL;
+		return (can_assume(LIBFDT_FLAWLESS) || err < 0) ? err :
+			-FDT_ERR_INTERNAL;
 	return nodedepth;
 }
 
@@ -573,7 +657,7 @@
 	const void *val;
 	int len;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	/* FIXME: The algorithm here is pretty horrible: we scan each
 	 * property of a node in fdt_getprop(), then if that didn't
@@ -599,7 +683,7 @@
 	if ((phandle == 0) || (phandle == -1))
 		return -FDT_ERR_BADPHANDLE;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	/* FIXME: The algorithm here is pretty horrible: we
 	 * potentially scan each property of a node in
@@ -752,7 +836,7 @@
 {
 	int offset, err;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	/* FIXME: The algorithm here is pretty horrible: we scan each
 	 * property of a node in fdt_node_check_compatible(), then if
diff --git a/lib/libfdt/fdt_rw.c b/lib/libfdt/fdt_rw.c
index 9b82905..93e4a2b 100644
--- a/lib/libfdt/fdt_rw.c
+++ b/lib/libfdt/fdt_rw.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "libfdt_env.h"
 
@@ -67,29 +22,31 @@
 		    (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
 }
 
-static int fdt_rw_check_header_(void *fdt)
+static int fdt_rw_probe_(void *fdt)
 {
-	FDT_CHECK_HEADER(fdt);
+	if (can_assume(VALID_DTB))
+		return 0;
+	FDT_RO_PROBE(fdt);
 
-	if (fdt_version(fdt) < 17)
+	if (!can_assume(LATEST) && fdt_version(fdt) < 17)
 		return -FDT_ERR_BADVERSION;
 	if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry),
 				   fdt_size_dt_struct(fdt)))
 		return -FDT_ERR_BADLAYOUT;
-	if (fdt_version(fdt) > 17)
+	if (!can_assume(LATEST) && fdt_version(fdt) > 17)
 		fdt_set_version(fdt, 17);
 
 	return 0;
 }
 
-#define FDT_RW_CHECK_HEADER(fdt) \
+#define FDT_RW_PROBE(fdt) \
 	{ \
 		int err_; \
-		if ((err_ = fdt_rw_check_header_(fdt)) != 0) \
+		if ((err_ = fdt_rw_probe_(fdt)) != 0) \
 			return err_; \
 	}
 
-static inline int fdt_data_size_(void *fdt)
+static inline unsigned int fdt_data_size_(void *fdt)
 {
 	return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
 }
@@ -97,15 +54,16 @@
 static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
 {
 	char *p = splicepoint;
-	char *end = (char *)fdt + fdt_data_size_(fdt);
+	unsigned int dsize = fdt_data_size_(fdt);
+	size_t soff = p - (char *)fdt;
 
-	if (((p + oldlen) < p) || ((p + oldlen) > end))
+	if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize))
 		return -FDT_ERR_BADOFFSET;
-	if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))
+	if ((p < (char *)fdt) || (dsize + newlen < oldlen))
 		return -FDT_ERR_BADOFFSET;
-	if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
+	if (dsize - oldlen + newlen > fdt_totalsize(fdt))
 		return -FDT_ERR_NOSPACE;
-	memmove(p + newlen, p + oldlen, end - p - oldlen);
+	memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen));
 	return 0;
 }
 
@@ -136,6 +94,14 @@
 	return 0;
 }
 
+/* Must only be used to roll back in case of error */
+static void fdt_del_last_string_(void *fdt, const char *s)
+{
+	int newlen = strlen(s) + 1;
+
+	fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen);
+}
+
 static int fdt_splice_string_(void *fdt, int newlen)
 {
 	void *p = (char *)fdt
@@ -149,7 +115,16 @@
 	return 0;
 }
 
-static int fdt_find_add_string_(void *fdt, const char *s)
+/**
+ * fdt_find_add_string_() - Find or allocate a string
+ *
+ * @fdt: pointer to the device tree to check/adjust
+ * @s: string to find/add
+ * @allocated: Set to 0 if the string was found, 1 if not found and so
+ *	allocated. Ignored if can_assume(NO_ROLLBACK)
+ * @return offset of string in the string table (whether found or added)
+ */
+static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
 {
 	char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
 	const char *p;
@@ -157,6 +132,9 @@
 	int len = strlen(s) + 1;
 	int err;
 
+	if (!can_assume(NO_ROLLBACK))
+		*allocated = 0;
+
 	p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);
 	if (p)
 		/* found it */
@@ -167,6 +145,9 @@
 	if (err)
 		return err;
 
+	if (!can_assume(NO_ROLLBACK))
+		*allocated = 1;
+
 	memcpy(new, s, len);
 	return (new - strtab);
 }
@@ -176,7 +157,7 @@
 	struct fdt_reserve_entry *re;
 	int err;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt));
 	err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
@@ -192,7 +173,7 @@
 {
 	struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n);
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	if (n >= fdt_num_mem_rsv(fdt))
 		return -FDT_ERR_NOTFOUND;
@@ -225,11 +206,12 @@
 	int nextoffset;
 	int namestroff;
 	int err;
+	int allocated;
 
 	if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
 		return nextoffset;
 
-	namestroff = fdt_find_add_string_(fdt, name);
+	namestroff = fdt_find_add_string_(fdt, name, &allocated);
 	if (namestroff < 0)
 		return namestroff;
 
@@ -237,8 +219,12 @@
 	proplen = sizeof(**prop) + FDT_TAGALIGN(len);
 
 	err = fdt_splice_struct_(fdt, *prop, 0, proplen);
-	if (err)
+	if (err) {
+		/* Delete the string if we failed to add it */
+		if (!can_assume(NO_ROLLBACK) && allocated)
+			fdt_del_last_string_(fdt, name);
 		return err;
+	}
 
 	(*prop)->tag = cpu_to_fdt32(FDT_PROP);
 	(*prop)->nameoff = cpu_to_fdt32(namestroff);
@@ -252,7 +238,7 @@
 	int oldlen, newlen;
 	int err;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
 	if (!namep)
@@ -275,7 +261,7 @@
 	struct fdt_property *prop;
 	int err;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
 	if (err == -FDT_ERR_NOTFOUND)
@@ -308,7 +294,7 @@
 	struct fdt_property *prop;
 	int err, oldlen, newlen;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
 	if (prop) {
@@ -334,7 +320,7 @@
 	struct fdt_property *prop;
 	int len, proplen;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
 	if (!prop)
@@ -354,7 +340,7 @@
 	uint32_t tag;
 	fdt32_t *endtag;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
 	if (offset >= 0)
@@ -394,7 +380,7 @@
 {
 	int endoffset;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	endoffset = fdt_node_end_offset_(fdt, nodeoffset);
 	if (endoffset < 0)
@@ -435,12 +421,12 @@
 	const char *fdtend = fdtstart + fdt_totalsize(fdt);
 	char *tmp;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
 		* sizeof(struct fdt_reserve_entry);
 
-	if (fdt_version(fdt) >= 17) {
+	if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
 		struct_size = fdt_size_dt_struct(fdt);
 	} else {
 		struct_size = 0;
@@ -450,7 +436,8 @@
 			return struct_size;
 	}
 
-	if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
+	if (can_assume(LIBFDT_ORDER) ||
+	    !fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
 		/* no further work necessary */
 		err = fdt_move(fdt, buf, bufsize);
 		if (err)
@@ -494,7 +481,7 @@
 {
 	int mem_rsv_size;
 
-	FDT_RW_CHECK_HEADER(fdt);
+	FDT_RW_PROBE(fdt);
 
 	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
 		* sizeof(struct fdt_reserve_entry);
diff --git a/lib/libfdt/fdt_strerror.c b/lib/libfdt/fdt_strerror.c
index 9677a18..768db66 100644
--- a/lib/libfdt/fdt_strerror.c
+++ b/lib/libfdt/fdt_strerror.c
@@ -1,51 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "libfdt_env.h"
@@ -82,6 +38,7 @@
 	FDT_ERRTABENT(FDT_ERR_BADVALUE),
 	FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
 	FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
+	FDT_ERRTABENT(FDT_ERR_BADFLAGS),
 };
 #define FDT_ERRTABSIZE	(sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
 
diff --git a/lib/libfdt/fdt_sw.c b/lib/libfdt/fdt_sw.c
index 6d33cc2..26759d5 100644
--- a/lib/libfdt/fdt_sw.c
+++ b/lib/libfdt/fdt_sw.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "libfdt_env.h"
 
@@ -55,21 +10,87 @@
 
 #include "libfdt_internal.h"
 
-static int fdt_sw_check_header_(void *fdt)
+static int fdt_sw_probe_(void *fdt)
 {
-	if (fdt_magic(fdt) != FDT_SW_MAGIC)
-		return -FDT_ERR_BADMAGIC;
-	/* FIXME: should check more details about the header state */
+	if (!can_assume(VALID_INPUT)) {
+		if (fdt_magic(fdt) == FDT_MAGIC)
+			return -FDT_ERR_BADSTATE;
+		else if (fdt_magic(fdt) != FDT_SW_MAGIC)
+			return -FDT_ERR_BADMAGIC;
+	}
+
 	return 0;
 }
 
-#define FDT_SW_CHECK_HEADER(fdt) \
+#define FDT_SW_PROBE(fdt) \
 	{ \
 		int err; \
-		if ((err = fdt_sw_check_header_(fdt)) != 0) \
+		if ((err = fdt_sw_probe_(fdt)) != 0) \
 			return err; \
 	}
 
+/* 'memrsv' state:	Initial state after fdt_create()
+ *
+ * Allowed functions:
+ *	fdt_add_reservmap_entry()
+ *	fdt_finish_reservemap()		[moves to 'struct' state]
+ */
+static int fdt_sw_probe_memrsv_(void *fdt)
+{
+	int err = fdt_sw_probe_(fdt);
+	if (err)
+		return err;
+
+	if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0)
+		return -FDT_ERR_BADSTATE;
+	return 0;
+}
+
+#define FDT_SW_PROBE_MEMRSV(fdt) \
+	{ \
+		int err; \
+		if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \
+			return err; \
+	}
+
+/* 'struct' state:	Enter this state after fdt_finish_reservemap()
+ *
+ * Allowed functions:
+ *	fdt_begin_node()
+ *	fdt_end_node()
+ *	fdt_property*()
+ *	fdt_finish()			[moves to 'complete' state]
+ */
+static int fdt_sw_probe_struct_(void *fdt)
+{
+	int err = fdt_sw_probe_(fdt);
+	if (err)
+		return err;
+
+	if (!can_assume(VALID_INPUT) &&
+	    fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
+		return -FDT_ERR_BADSTATE;
+	return 0;
+}
+
+#define FDT_SW_PROBE_STRUCT(fdt) \
+	{ \
+		int err; \
+		if ((err = fdt_sw_probe_struct_(fdt)) != 0) \
+			return err; \
+	}
+
+static inline uint32_t sw_flags(void *fdt)
+{
+	/* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */
+	return fdt_last_comp_version(fdt);
+}
+
+/* 'complete' state:	Enter this state after fdt_finish()
+ *
+ * Allowed functions: none
+ */
+
 static void *fdt_grab_space_(void *fdt, size_t len)
 {
 	int offset = fdt_size_dt_struct(fdt);
@@ -85,38 +106,59 @@
 	return fdt_offset_ptr_w_(fdt, offset);
 }
 
-int fdt_create(void *buf, int bufsize)
+int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags)
 {
+	const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
+					 sizeof(struct fdt_reserve_entry));
 	void *fdt = buf;
 
-	if (bufsize < sizeof(struct fdt_header))
+	if (bufsize < hdrsize)
 		return -FDT_ERR_NOSPACE;
 
+	if (flags & ~FDT_CREATE_FLAGS_ALL)
+		return -FDT_ERR_BADFLAGS;
+
 	memset(buf, 0, bufsize);
 
+	/*
+	 * magic and last_comp_version keep intermediate state during the fdt
+	 * creation process, which is replaced with the proper FDT format by
+	 * fdt_finish().
+	 *
+	 * flags should be accessed with sw_flags().
+	 */
 	fdt_set_magic(fdt, FDT_SW_MAGIC);
 	fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
-	fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
+	fdt_set_last_comp_version(fdt, flags);
+
 	fdt_set_totalsize(fdt,  bufsize);
 
-	fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
-					      sizeof(struct fdt_reserve_entry)));
+	fdt_set_off_mem_rsvmap(fdt, hdrsize);
 	fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
-	fdt_set_off_dt_strings(fdt, bufsize);
+	fdt_set_off_dt_strings(fdt, 0);
 
 	return 0;
 }
 
+int fdt_create(void *buf, int bufsize)
+{
+	return fdt_create_with_flags(buf, bufsize, 0);
+}
+
 int fdt_resize(void *fdt, void *buf, int bufsize)
 {
 	size_t headsize, tailsize;
 	char *oldtail, *newtail;
 
-	FDT_SW_CHECK_HEADER(fdt);
+	FDT_SW_PROBE(fdt);
 
-	headsize = fdt_off_dt_struct(fdt);
+	headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
 	tailsize = fdt_size_dt_strings(fdt);
 
+	if (!can_assume(VALID_DTB) &&
+	    headsize + tailsize > fdt_totalsize(fdt))
+		return -FDT_ERR_INTERNAL;
+
 	if ((headsize + tailsize) > bufsize)
 		return -FDT_ERR_NOSPACE;
 
@@ -133,8 +175,9 @@
 		memmove(buf, fdt, headsize);
 	}
 
-	fdt_set_off_dt_strings(buf, bufsize);
 	fdt_set_totalsize(buf, bufsize);
+	if (fdt_off_dt_strings(buf))
+		fdt_set_off_dt_strings(buf, bufsize);
 
 	return 0;
 }
@@ -144,10 +187,7 @@
 	struct fdt_reserve_entry *re;
 	int offset;
 
-	FDT_SW_CHECK_HEADER(fdt);
-
-	if (fdt_size_dt_struct(fdt))
-		return -FDT_ERR_BADSTATE;
+	FDT_SW_PROBE_MEMRSV(fdt);
 
 	offset = fdt_off_dt_struct(fdt);
 	if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
@@ -164,16 +204,23 @@
 
 int fdt_finish_reservemap(void *fdt)
 {
-	return fdt_add_reservemap_entry(fdt, 0, 0);
+	int err = fdt_add_reservemap_entry(fdt, 0, 0);
+
+	if (err)
+		return err;
+
+	fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt));
+	return 0;
 }
 
 int fdt_begin_node(void *fdt, const char *name)
 {
 	struct fdt_node_header *nh;
-	int namelen = strlen(name) + 1;
+	int namelen;
 
-	FDT_SW_CHECK_HEADER(fdt);
+	FDT_SW_PROBE_STRUCT(fdt);
 
+	namelen = strlen(name) + 1;
 	nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
 	if (! nh)
 		return -FDT_ERR_NOSPACE;
@@ -187,7 +234,7 @@
 {
 	fdt32_t *en;
 
-	FDT_SW_CHECK_HEADER(fdt);
+	FDT_SW_PROBE_STRUCT(fdt);
 
 	en = fdt_grab_space_(fdt, FDT_TAGSIZE);
 	if (! en)
@@ -197,19 +244,13 @@
 	return 0;
 }
 
-static int fdt_find_add_string_(void *fdt, const char *s)
+static int fdt_add_string_(void *fdt, const char *s)
 {
 	char *strtab = (char *)fdt + fdt_totalsize(fdt);
-	const char *p;
 	int strtabsize = fdt_size_dt_strings(fdt);
 	int len = strlen(s) + 1;
 	int struct_top, offset;
 
-	p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
-	if (p)
-		return p - strtab;
-
-	/* Add it */
 	offset = -strtabsize - len;
 	struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
 	if (fdt_totalsize(fdt) + offset < struct_top)
@@ -220,20 +261,56 @@
 	return offset;
 }
 
+/* Must only be used to roll back in case of error */
+static void fdt_del_last_string_(void *fdt, const char *s)
+{
+	int strtabsize = fdt_size_dt_strings(fdt);
+	int len = strlen(s) + 1;
+
+	fdt_set_size_dt_strings(fdt, strtabsize - len);
+}
+
+static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
+{
+	char *strtab = (char *)fdt + fdt_totalsize(fdt);
+	int strtabsize = fdt_size_dt_strings(fdt);
+	const char *p;
+
+	*allocated = 0;
+
+	p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
+	if (p)
+		return p - strtab;
+
+	*allocated = 1;
+
+	return fdt_add_string_(fdt, s);
+}
+
 int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
 {
 	struct fdt_property *prop;
 	int nameoff;
+	int allocated;
 
-	FDT_SW_CHECK_HEADER(fdt);
+	FDT_SW_PROBE_STRUCT(fdt);
 
-	nameoff = fdt_find_add_string_(fdt, name);
+	/* String de-duplication can be slow, _NO_NAME_DEDUP skips it */
+	if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) {
+		allocated = 1;
+		nameoff = fdt_add_string_(fdt, name);
+	} else {
+		nameoff = fdt_find_add_string_(fdt, name, &allocated);
+	}
 	if (nameoff == 0)
 		return -FDT_ERR_NOSPACE;
 
 	prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
-	if (! prop)
+	if (! prop) {
+		if (allocated)
+			fdt_del_last_string_(fdt, name);
 		return -FDT_ERR_NOSPACE;
+	}
 
 	prop->tag = cpu_to_fdt32(FDT_PROP);
 	prop->nameoff = cpu_to_fdt32(nameoff);
@@ -262,7 +339,7 @@
 	uint32_t tag;
 	int offset, nextoffset;
 
-	FDT_SW_CHECK_HEADER(fdt);
+	FDT_SW_PROBE_STRUCT(fdt);
 
 	/* Add terminator */
 	end = fdt_grab_space_(fdt, sizeof(*end));
@@ -295,6 +372,10 @@
 
 	/* Finally, adjust the header */
 	fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
+
+	/* And fix up fields that were keeping intermediate state. */
+	fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
 	fdt_set_magic(fdt, FDT_MAGIC);
+
 	return 0;
 }
diff --git a/lib/libfdt/fdt_wip.c b/lib/libfdt/fdt_wip.c
index 534c1cb..f64139e 100644
--- a/lib/libfdt/fdt_wip.c
+++ b/lib/libfdt/fdt_wip.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "libfdt_env.h"
 
diff --git a/lib/libfdt/libfdt_internal.h b/lib/libfdt/libfdt_internal.h
index 7681e19..d4e0bd4 100644
--- a/lib/libfdt/libfdt_internal.h
+++ b/lib/libfdt/libfdt_internal.h
@@ -1,65 +1,21 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
 #ifndef LIBFDT_INTERNAL_H
 #define LIBFDT_INTERNAL_H
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include <fdt.h>
 
 #define FDT_ALIGN(x, a)		(((x) + (a) - 1) & ~((a) - 1))
 #define FDT_TAGALIGN(x)		(FDT_ALIGN((x), FDT_TAGSIZE))
 
-#define FDT_CHECK_HEADER(fdt) \
-	{ \
-		int err_; \
-		if ((err_ = fdt_check_header(fdt)) != 0) \
-			return err_; \
+int32_t fdt_ro_probe_(const void *fdt);
+#define FDT_RO_PROBE(fdt)					\
+	{							\
+		int32_t totalsize_;				\
+		if ((totalsize_ = fdt_ro_probe_(fdt)) < 0)	\
+			return totalsize_;			\
 	}
 
 int fdt_check_node_offset_(const void *fdt, int offset);
@@ -92,4 +48,126 @@
 
 #define FDT_SW_MAGIC		(~FDT_MAGIC)
 
+/**********************************************************************/
+/* Checking controls                                                  */
+/**********************************************************************/
+
+#ifndef FDT_ASSUME_MASK
+#define FDT_ASSUME_MASK 0
+#endif
+
+/*
+ * Defines assumptions which can be enabled. Each of these can be enabled
+ * individually. For maximum safety, don't enable any assumptions!
+ *
+ * For minimal code size and no safety, use ASSUME_PERFECT at your own risk.
+ * You should have another method of validating the device tree, such as a
+ * signature or hash check before using libfdt.
+ *
+ * For situations where security is not a concern it may be safe to enable
+ * ASSUME_SANE.
+ */
+enum {
+	/*
+	 * This does essentially no checks. Only the latest device-tree
+	 * version is correctly handled. Inconsistencies or errors in the device
+	 * tree may cause undefined behaviour or crashes. Invalid parameters
+	 * passed to libfdt may do the same.
+	 *
+	 * If an error occurs when modifying the tree it may leave the tree in
+	 * an intermediate (but valid) state. As an example, adding a property
+	 * where there is insufficient space may result in the property name
+	 * being added to the string table even though the property itself is
+	 * not added to the struct section.
+	 *
+	 * Only use this if you have a fully validated device tree with
+	 * the latest supported version and wish to minimise code size.
+	 */
+	ASSUME_PERFECT		= 0xff,
+
+	/*
+	 * This assumes that the device tree is sane. i.e. header metadata
+	 * and basic hierarchy are correct.
+	 *
+	 * With this assumption enabled, normal device trees produced by libfdt
+	 * and the compiler should be handled safely. Malicious device trees and
+	 * complete garbage may cause libfdt to behave badly or crash. Truncated
+	 * device trees (e.g. those only partially loaded) can also cause
+	 * problems.
+	 *
+	 * Note: Only checks that relate exclusively to the device tree itself
+	 * (not the parameters passed to libfdt) are disabled by this
+	 * assumption. This includes checking headers, tags and the like.
+	 */
+	ASSUME_VALID_DTB	= 1 << 0,
+
+	/*
+	 * This builds on ASSUME_VALID_DTB and further assumes that libfdt
+	 * functions are called with valid parameters, i.e. not trigger
+	 * FDT_ERR_BADOFFSET or offsets that are out of bounds. It disables any
+	 * extensive checking of parameters and the device tree, making various
+	 * assumptions about correctness.
+	 *
+	 * It doesn't make sense to enable this assumption unless
+	 * ASSUME_VALID_DTB is also enabled.
+	 */
+	ASSUME_VALID_INPUT	= 1 << 1,
+
+	/*
+	 * This disables checks for device-tree version and removes all code
+	 * which handles older versions.
+	 *
+	 * Only enable this if you know you have a device tree with the latest
+	 * version.
+	 */
+	ASSUME_LATEST		= 1 << 2,
+
+	/*
+	 * This assumes that it is OK for a failed addition to the device tree,
+	 * due to lack of space or some other problem, to skip any rollback
+	 * steps (such as dropping the property name from the string table).
+	 * This is safe to enable in most circumstances, even though it may
+	 * leave the tree in a sub-optimal state.
+	 */
+	ASSUME_NO_ROLLBACK	= 1 << 3,
+
+	/*
+	 * This assumes that the device tree components appear in a 'convenient'
+	 * order, i.e. the memory reservation block first, then the structure
+	 * block and finally the string block.
+	 *
+	 * This order is not specified by the device-tree specification,
+	 * but is expected by libfdt. The device-tree compiler always created
+	 * device trees with this order.
+	 *
+	 * This assumption disables a check in fdt_open_into() and removes the
+	 * ability to fix the problem there. This is safe if you know that the
+	 * device tree is correctly ordered. See fdt_blocks_misordered_().
+	 */
+	ASSUME_LIBFDT_ORDER	= 1 << 4,
+
+	/*
+	 * This assumes that libfdt itself does not have any internal bugs. It
+	 * drops certain checks that should never be needed unless libfdt has an
+	 * undiscovered bug.
+	 *
+	 * This can generally be considered safe to enable.
+	 */
+	ASSUME_LIBFDT_FLAWLESS	= 1 << 5,
+};
+
+/**
+ * can_assume_() - check if a particular assumption is enabled
+ *
+ * @mask: Mask to check (ASSUME_...)
+ * @return true if that assumption is enabled, else false
+ */
+static inline bool can_assume_(int mask)
+{
+	return FDT_ASSUME_MASK & mask;
+}
+
+/** helper macros for checking assumptions */
+#define can_assume(_assume)	can_assume_(ASSUME_ ## _assume)
+
 #endif /* LIBFDT_INTERNAL_H */
diff --git a/lib/romlib/Makefile b/lib/romlib/Makefile
index cec9404..2ff480b 100644
--- a/lib/romlib/Makefile
+++ b/lib/romlib/Makefile
@@ -10,14 +10,14 @@
 OC          = $(CROSS_COMPILE)objcopy
 CPP         = $(CROSS_COMPILE)cpp
 ROMLIB_GEN  = ./romlib_generator.py
-BUILD_DIR   = ../../$(BUILD_PLAT)/romlib
-LIB_DIR     = ../../$(BUILD_PLAT)/lib
-WRAPPER_DIR = ../../$(BUILD_PLAT)/libwrapper
+BUILD_DIR   = $(BUILD_PLAT)/romlib
+LIB_DIR     = $(BUILD_PLAT)/lib
+WRAPPER_DIR = $(BUILD_PLAT)/libwrapper
 LIBS        = -lmbedtls -lfdt -lc
 INC         = $(INCLUDES:-I%=-I../../%)
 PPFLAGS     = $(INC) $(DEFINES) -P -x assembler-with-cpp -D__LINKER__ -MD -MP -MT $(BUILD_DIR)/romlib.ld
 OBJS        = $(BUILD_DIR)/jmptbl.o $(BUILD_DIR)/init.o
-MAPFILE     = ../../$(BUILD_PLAT)/romlib/romlib.map
+MAPFILE     = $(BUILD_PLAT)/romlib/romlib.map
 
 ifneq ($(PLAT_DIR),)
   WRAPPER_SOURCES   = $(shell $(ROMLIB_GEN) genwrappers -b $(WRAPPER_DIR) --list ../../$(PLAT_DIR)/jmptbl.i)
diff --git a/lib/semihosting/semihosting.c b/lib/semihosting/semihosting.c
index 60fc52a..e0845c1 100644
--- a/lib/semihosting/semihosting.c
+++ b/lib/semihosting/semihosting.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
  */
@@ -14,8 +14,7 @@
 #define SEMIHOSTING_SUPPORTED  1
 #endif
 
-long semihosting_call(unsigned long operation,
-			uintptr_t system_block_address);
+long semihosting_call(unsigned long operation, uintptr_t system_block_address);
 
 typedef struct {
 	const char *file_name;
@@ -52,8 +51,7 @@
 	open_block.mode = mode;
 	open_block.name_length = strlen(file_name);
 
-	return semihosting_call(SEMIHOSTING_SYS_OPEN,
-				(uintptr_t) &open_block);
+	return semihosting_call(SEMIHOSTING_SYS_OPEN, (uintptr_t)&open_block);
 }
 
 long semihosting_file_seek(long file_handle, ssize_t offset)
@@ -64,11 +62,11 @@
 	seek_block.handle = file_handle;
 	seek_block.location = offset;
 
-	result = semihosting_call(SEMIHOSTING_SYS_SEEK,
-				  (uintptr_t) &seek_block);
+	result = semihosting_call(SEMIHOSTING_SYS_SEEK, (uintptr_t)&seek_block);
 
-	if (result)
+	if (result != 0) {
 		result = semihosting_call(SEMIHOSTING_SYS_ERRNO, 0);
+	}
 
 	return result;
 }
@@ -78,41 +76,42 @@
 	smh_file_read_write_block_t read_block;
 	long result = -EINVAL;
 
-	if ((length == NULL) || (buffer == (uintptr_t)NULL))
+	if ((length == NULL) || (buffer == (uintptr_t)NULL)) {
 		return result;
+	}
 
 	read_block.handle = file_handle;
 	read_block.buffer = buffer;
 	read_block.length = *length;
 
-	result = semihosting_call(SEMIHOSTING_SYS_READ,
-				  (uintptr_t) &read_block);
+	result = semihosting_call(SEMIHOSTING_SYS_READ, (uintptr_t)&read_block);
 
 	if (result == *length) {
 		return -EINVAL;
 	} else if (result < *length) {
 		*length -= result;
 		return 0;
-	} else
+	} else {
 		return result;
+	}
 }
 
-long semihosting_file_write(long file_handle,
-			    size_t *length,
-			    const uintptr_t buffer)
+long semihosting_file_write(long file_handle, size_t *length,
+				const uintptr_t buffer)
 {
 	smh_file_read_write_block_t write_block;
 	long result = -EINVAL;
 
-	if ((length == NULL) || (buffer == (uintptr_t)NULL))
+	if ((length == NULL) || (buffer == (uintptr_t)NULL)) {
 		return -EINVAL;
+	}
 
 	write_block.handle = file_handle;
 	write_block.buffer = (uintptr_t)buffer; /* cast away const */
 	write_block.length = *length;
 
 	result = semihosting_call(SEMIHOSTING_SYS_WRITE,
-				   (uintptr_t) &write_block);
+		(uintptr_t)&write_block);
 
 	*length = result;
 
@@ -121,14 +120,12 @@
 
 long semihosting_file_close(long file_handle)
 {
-	return semihosting_call(SEMIHOSTING_SYS_CLOSE,
-				(uintptr_t) &file_handle);
+	return semihosting_call(SEMIHOSTING_SYS_CLOSE, (uintptr_t)&file_handle);
 }
 
 long semihosting_file_length(long file_handle)
 {
-	return semihosting_call(SEMIHOSTING_SYS_FLEN,
-				(uintptr_t) &file_handle);
+	return semihosting_call(SEMIHOSTING_SYS_FLEN, (uintptr_t)&file_handle);
 }
 
 char semihosting_read_char(void)
@@ -138,12 +135,12 @@
 
 void semihosting_write_char(char character)
 {
-	semihosting_call(SEMIHOSTING_SYS_WRITEC, (uintptr_t) &character);
+	semihosting_call(SEMIHOSTING_SYS_WRITEC, (uintptr_t)&character);
 }
 
 void semihosting_write_string(char *string)
 {
-	semihosting_call(SEMIHOSTING_SYS_WRITE0, (uintptr_t) string);
+	semihosting_call(SEMIHOSTING_SYS_WRITE0, (uintptr_t)string);
 }
 
 long semihosting_system(char *command_line)
@@ -154,7 +151,7 @@
 	system_block.command_length = strlen(command_line);
 
 	return semihosting_call(SEMIHOSTING_SYS_SYSTEM,
-				(uintptr_t) &system_block);
+		(uintptr_t)&system_block);
 }
 
 long semihosting_get_flen(const char *file_name)
@@ -162,16 +159,17 @@
 	long file_handle;
 	long length;
 
-	assert(semihosting_connection_supported());
+	assert(semihosting_connection_supported() != 0);
 
 	file_handle = semihosting_file_open(file_name, FOPEN_MODE_RB);
-	if (file_handle == -1)
+	if (file_handle == -1) {
 		return file_handle;
+	}
 
 	/* Find the length of the file */
 	length = semihosting_file_length(file_handle);
 
-	return semihosting_file_close(file_handle) ? -1 : length;
+	return (semihosting_file_close(file_handle) != 0) ? -1 : length;
 }
 
 long semihosting_download_file(const char *file_name,
@@ -183,23 +181,27 @@
 	long file_handle;
 
 	/* Null pointer check */
-	if (!buf)
+	if (buf == 0U) {
 		return ret;
+	}
 
-	assert(semihosting_connection_supported());
+	assert(semihosting_connection_supported() != 0);
 
 	file_handle = semihosting_file_open(file_name, FOPEN_MODE_RB);
-	if (file_handle == -1)
+	if (file_handle == -1) {
 		return ret;
+	}
 
 	/* Find the actual length of the file */
 	length = semihosting_file_length(file_handle);
-	if (length == -1)
+	if (length == (size_t)(-1)) {
 		goto semihosting_fail;
+	}
 
 	/* Signal error if we do not have enough space for the file */
-	if (length > buf_size)
+	if (length > buf_size) {
 		goto semihosting_fail;
+	}
 
 	/*
 	 * A successful read will return 0 in which case we pass back
@@ -207,10 +209,11 @@
 	 * value indicating an error.
 	 */
 	ret = semihosting_file_read(file_handle, &length, buf);
-	if (ret)
+	if (ret != 0) {
 		goto semihosting_fail;
-	else
-		ret = length;
+	} else {
+		ret = (long)length;
+	}
 
 semihosting_fail:
 	semihosting_file_close(file_handle);
@@ -222,9 +225,9 @@
 #ifdef __aarch64__
 	uint64_t parameters[] = {reason, subcode};
 
-	(void) semihosting_call(SEMIHOSTING_SYS_EXIT, (uintptr_t) &parameters);
+	(void)semihosting_call(SEMIHOSTING_SYS_EXIT, (uintptr_t)&parameters);
 #else
 	/* The subcode is not supported on AArch32. */
-	(void) semihosting_call(SEMIHOSTING_SYS_EXIT, reason);
+	(void)semihosting_call(SEMIHOSTING_SYS_EXIT, reason);
 #endif
 }
diff --git a/lib/utils/mem_region.c b/lib/utils/mem_region.c
index 6bd78ba..fec086b 100644
--- a/lib/utils/mem_region.c
+++ b/lib/utils/mem_region.c
@@ -33,7 +33,7 @@
 	size_t i;
 
 	assert(tbl != NULL);
-	assert(nregions > 0);
+	assert(nregions > 0U);
 
 	for (i = 0; i < nregions; i++) {
 		assert(tbl->nbytes > 0);
@@ -64,28 +64,32 @@
 	const unsigned int attr = MT_MEMORY | MT_RW | MT_NS;
 
 	assert(regions != NULL);
-	assert(nregions > 0 && chunk > 0);
+	assert(nregions != 0U);
+	assert(chunk != 0U);
 
-	for ( ; nregions--; regions++) {
-		begin = regions->base;
-		size = regions->nbytes;
-		if ((begin & (chunk-1)) != 0 || (size & (chunk-1)) != 0) {
+	for (unsigned int i = 0U; i < nregions; i++) {
+		begin = regions[i].base;
+		size = regions[i].nbytes;
+		if (((begin & (chunk-1U)) != 0U) ||
+				((size & (chunk-1U)) != 0U)) {
 			INFO("PSCI: Not correctly aligned region\n");
 			panic();
 		}
 
-		while (size > 0) {
+		while (size > 0U) {
 			r = mmap_add_dynamic_region(begin, va, chunk, attr);
 			if (r != 0) {
-				INFO("PSCI: mmap_add_dynamic_region failed with %d\n", r);
+				INFO("PSCI: %s failed with %d\n",
+					"mmap_add_dynamic_region", r);
 				panic();
 			}
 
-			zero_normalmem((void *) va, chunk);
+			zero_normalmem((void *)va, chunk);
 
 			r = mmap_remove_dynamic_region(va, chunk);
 			if (r != 0) {
-				INFO("PSCI: mmap_remove_dynamic_region failed with %d\n", r);
+				INFO("PSCI: %s failed with %d\n",
+					"mmap_remove_dynamic_region", r);
 				panic();
 			}
 
@@ -115,18 +119,19 @@
 	size_t i;
 
 	assert(tbl != NULL);
-	assert(nbytes > 0);
+	assert(nbytes != 0U);
 	assert(!check_uptr_overflow(addr, nbytes-1));
 
 	region_start = addr;
-	region_end = addr + (nbytes - 1);
-	for (i = 0; i < nregions; i++) {
+	region_end = addr + (nbytes - 1U);
+	for (i = 0U; i < nregions; i++) {
 		assert(tbl->nbytes > 0);
 		assert(!check_uptr_overflow(tbl->base, tbl->nbytes-1));
 		start = tbl->base;
 		end = start + (tbl->nbytes - 1);
-		if (region_start >= start && region_end <= end)
+		if ((region_start >= start) && (region_end <= end)) {
 			return 0;
+		}
 		tbl++;
 	}
 
diff --git a/lib/xlat_tables/aarch32/nonlpae_tables.c b/lib/xlat_tables/aarch32/nonlpae_tables.c
index b8c2686..7cd509d 100644
--- a/lib/xlat_tables/aarch32/nonlpae_tables.c
+++ b/lib/xlat_tables/aarch32/nonlpae_tables.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2016-2017, Linaro Limited. All rights reserved.
- * Copyright (c) 2014-2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2014-2020, Arm Limited. All rights reserved.
  * Copyright (c) 2014, STMicroelectronics International N.V.
  * All rights reserved.
  *
@@ -30,8 +30,8 @@
 CASSERT(PLAT_VIRT_ADDR_SPACE_SIZE == (1ULL << 32), invalid_vaddr_space_size);
 CASSERT(PLAT_PHY_ADDR_SPACE_SIZE == (1ULL << 32), invalid_paddr_space_size);
 
-#define MMU32B_UNSET_DESC	~0ul
-#define MMU32B_INVALID_DESC	0ul
+#define MMU32B_UNSET_DESC	~0UL
+#define MMU32B_INVALID_DESC	0UL
 
 #define MT_UNKNOWN	~0U
 
@@ -40,38 +40,38 @@
  */
 
 /* Sharable */
-#define MMU32B_TTB_S           (1 << 1)
+#define MMU32B_TTB_S           (1U << 1)
 
 /* Not Outer Sharable */
-#define MMU32B_TTB_NOS         (1 << 5)
+#define MMU32B_TTB_NOS         (1U << 5)
 
 /* Normal memory, Inner Non-cacheable */
-#define MMU32B_TTB_IRGN_NC     0
+#define MMU32B_TTB_IRGN_NC     0U
 
 /* Normal memory, Inner Write-Back Write-Allocate Cacheable */
-#define MMU32B_TTB_IRGN_WBWA   (1 << 6)
+#define MMU32B_TTB_IRGN_WBWA   (1U << 6)
 
 /* Normal memory, Inner Write-Through Cacheable */
-#define MMU32B_TTB_IRGN_WT     1
+#define MMU32B_TTB_IRGN_WT     1U
 
 /* Normal memory, Inner Write-Back no Write-Allocate Cacheable */
-#define MMU32B_TTB_IRGN_WB     (1 | (1 << 6))
+#define MMU32B_TTB_IRGN_WB     (1U | (1U << 6))
 
 /* Normal memory, Outer Write-Back Write-Allocate Cacheable */
-#define MMU32B_TTB_RNG_WBWA    (1 << 3)
+#define MMU32B_TTB_RNG_WBWA    (1U << 3)
 
 #define MMU32B_DEFAULT_ATTRS \
 		(MMU32B_TTB_S | MMU32B_TTB_NOS | \
 		 MMU32B_TTB_IRGN_WBWA | MMU32B_TTB_RNG_WBWA)
 
 /* armv7 memory mapping attributes: section mapping */
-#define SECTION_SECURE			(0 << 19)
-#define SECTION_NOTSECURE		(1 << 19)
-#define SECTION_SHARED			(1 << 16)
-#define SECTION_NOTGLOBAL		(1 << 17)
-#define SECTION_ACCESS_FLAG		(1 << 10)
-#define SECTION_UNPRIV			(1 << 11)
-#define SECTION_RO			(1 << 15)
+#define SECTION_SECURE			(0U << 19)
+#define SECTION_NOTSECURE		(1U << 19)
+#define SECTION_SHARED			(1U << 16)
+#define SECTION_NOTGLOBAL		(1U << 17)
+#define SECTION_ACCESS_FLAG		(1U << 10)
+#define SECTION_UNPRIV			(1U << 11)
+#define SECTION_RO			(1U << 15)
 #define SECTION_TEX(tex)		((((tex) >> 2) << 12) | \
 					((((tex) >> 1) & 0x1) << 3) | \
 					(((tex) & 0x1) << 2))
@@ -80,16 +80,16 @@
 #define SECTION_NORMAL_CACHED		\
 				SECTION_TEX(MMU32B_ATTR_IWBWA_OWBWA_INDEX)
 
-#define SECTION_XN			(1 << 4)
-#define SECTION_PXN			(1 << 0)
-#define SECTION_SECTION			(2 << 0)
+#define SECTION_XN			(1U << 4)
+#define SECTION_PXN			(1U << 0)
+#define SECTION_SECTION			(2U << 0)
 
-#define SECTION_PT_NOTSECURE		(1 << 3)
-#define SECTION_PT_PT			(1 << 0)
+#define SECTION_PT_NOTSECURE		(1U << 3)
+#define SECTION_PT_PT			(1U << 0)
 
-#define SMALL_PAGE_SMALL_PAGE		(1 << 1)
-#define SMALL_PAGE_SHARED		(1 << 10)
-#define SMALL_PAGE_NOTGLOBAL		(1 << 11)
+#define SMALL_PAGE_SMALL_PAGE		(1U << 1)
+#define SMALL_PAGE_SHARED		(1U << 10)
+#define SMALL_PAGE_NOTGLOBAL		(1U << 11)
 #define SMALL_PAGE_TEX(tex)		((((tex) >> 2) << 6) | \
 					((((tex) >> 1) & 0x1) << 3) | \
 					(((tex) & 0x1) << 2))
@@ -99,39 +99,39 @@
 				SMALL_PAGE_TEX(MMU32B_ATTR_DEVICE_INDEX)
 #define SMALL_PAGE_NORMAL_CACHED	\
 				SMALL_PAGE_TEX(MMU32B_ATTR_IWBWA_OWBWA_INDEX)
-#define SMALL_PAGE_ACCESS_FLAG		(1 << 4)
-#define SMALL_PAGE_UNPRIV		(1 << 5)
-#define SMALL_PAGE_RO			(1 << 9)
-#define SMALL_PAGE_XN			(1 << 0)
+#define SMALL_PAGE_ACCESS_FLAG		(1U << 4)
+#define SMALL_PAGE_UNPRIV		(1U << 5)
+#define SMALL_PAGE_RO			(1U << 9)
+#define SMALL_PAGE_XN			(1U << 0)
 
 /* The TEX, C and B bits concatenated */
-#define MMU32B_ATTR_DEVICE_INDEX		0x0
-#define MMU32B_ATTR_IWBWA_OWBWA_INDEX		0x1
+#define MMU32B_ATTR_DEVICE_INDEX	0U
+#define MMU32B_ATTR_IWBWA_OWBWA_INDEX	1U
 
 #define MMU32B_PRRR_IDX(idx, tr, nos)	(((tr) << (2 * (idx))) | \
 					 ((uint32_t)(nos) << ((idx) + 24)))
 #define MMU32B_NMRR_IDX(idx, ir, or)	(((ir) << (2 * (idx))) | \
 					 ((uint32_t)(or) << (2 * (idx) + 16)))
-#define MMU32B_PRRR_DS0			(1 << 16)
-#define MMU32B_PRRR_DS1			(1 << 17)
-#define MMU32B_PRRR_NS0			(1 << 18)
-#define MMU32B_PRRR_NS1			(1 << 19)
+#define MMU32B_PRRR_DS0			(1U << 16)
+#define MMU32B_PRRR_DS1			(1U << 17)
+#define MMU32B_PRRR_NS0			(1U << 18)
+#define MMU32B_PRRR_NS1			(1U << 19)
 
 #define DACR_DOMAIN(num, perm)		((perm) << ((num) * 2))
-#define DACR_DOMAIN_PERM_NO_ACCESS	0x0
-#define DACR_DOMAIN_PERM_CLIENT		0x1
-#define DACR_DOMAIN_PERM_MANAGER	0x3
+#define DACR_DOMAIN_PERM_NO_ACCESS	0U
+#define DACR_DOMAIN_PERM_CLIENT		1U
+#define DACR_DOMAIN_PERM_MANAGER	3U
 
-#define NUM_1MB_IN_4GB		(1U << 12)
-#define NUM_4K_IN_1MB		(1U << 8)
+#define NUM_1MB_IN_4GB		(1UL << 12)
+#define NUM_4K_IN_1MB		(1UL << 8)
 
 #define ONE_MB_SHIFT		20
 
 /* mmu 32b integration */
 #define MMU32B_L1_TABLE_SIZE		(NUM_1MB_IN_4GB * 4)
 #define MMU32B_L2_TABLE_SIZE		(NUM_4K_IN_1MB * 4)
-#define MMU32B_L1_TABLE_ALIGN		(1 << 14)
-#define MMU32B_L2_TABLE_ALIGN		(1 << 10)
+#define MMU32B_L1_TABLE_ALIGN		(1U << 14)
+#define MMU32B_L2_TABLE_ALIGN		(1U << 10)
 
 static unsigned int next_xlat;
 static unsigned long long xlat_max_pa;
@@ -190,8 +190,9 @@
 	assert(IS_PAGE_ALIGNED(base_va));
 	assert(IS_PAGE_ALIGNED(size));
 
-	if (size == 0U)
+	if (size == 0U) {
 		return;
+	}
 
 	assert(base_pa < end_pa); /* Check for overflows */
 	assert(base_va < end_va);
@@ -249,8 +250,9 @@
 #endif /* ENABLE_ASSERTIONS */
 
 	/* Find correct place in mmap to insert new region */
-	while ((mm->base_va < base_va) && (mm->size != 0U))
+	while ((mm->base_va < base_va) && (mm->size != 0U)) {
 		++mm;
+	}
 
 	/*
 	 * If a section is contained inside another one with the same base
@@ -263,8 +265,9 @@
 	 * This is required for mmap_region_attr() to get the attributes of the
 	 * small region correctly.
 	 */
-	while ((mm->base_va == base_va) && (mm->size > size))
+	while ((mm->base_va == base_va) && (mm->size > size)) {
 		++mm;
+	}
 
 	/* Make room for new region by moving other regions up by one place */
 	(void)memmove(mm + 1, mm, (uintptr_t)mm_last - (uintptr_t)mm);
@@ -277,10 +280,12 @@
 	mm->size = size;
 	mm->attr = attr;
 
-	if (end_pa > xlat_max_pa)
+	if (end_pa > xlat_max_pa) {
 		xlat_max_pa = end_pa;
-	if (end_va > xlat_max_va)
+	}
+	if (end_va > xlat_max_va) {
 		xlat_max_va = end_va;
+	}
 }
 
 /* map all memory as shared/global/domain0/no-usr access */
@@ -290,42 +295,44 @@
 	uint32_t desc;
 
 	switch (level) {
-	case 1:
-		assert(!(addr_pa & (MMU32B_L1_TABLE_ALIGN - 1)));
+	case 1U:
+		assert((addr_pa & (MMU32B_L1_TABLE_ALIGN - 1)) == 0U);
 
 		desc = SECTION_SECTION | SECTION_SHARED;
 
-		desc |= attr & MT_NS ? SECTION_NOTSECURE : 0;
+		desc |= (attr & MT_NS) != 0U ? SECTION_NOTSECURE : 0U;
 
 		desc |= SECTION_ACCESS_FLAG;
-		desc |= attr & MT_RW ? 0 : SECTION_RO;
+		desc |= (attr & MT_RW) != 0U ? 0U : SECTION_RO;
 
-		desc |= attr & MT_MEMORY ?
+		desc |= (attr & MT_MEMORY) != 0U ?
 			SECTION_NORMAL_CACHED : SECTION_DEVICE;
 
-		if ((attr & MT_RW) || !(attr & MT_MEMORY))
+		if (((attr & MT_RW) != 0U) || ((attr & MT_MEMORY) == 0U)) {
 			desc |= SECTION_XN;
+		}
 		break;
-	case 2:
-		assert(!(addr_pa & (MMU32B_L2_TABLE_ALIGN - 1)));
+	case 2U:
+		assert((addr_pa & (MMU32B_L2_TABLE_ALIGN - 1)) == 0U);
 
 		desc = SMALL_PAGE_SMALL_PAGE | SMALL_PAGE_SHARED;
 
 		desc |= SMALL_PAGE_ACCESS_FLAG;
-		desc |= attr & MT_RW ? 0 : SMALL_PAGE_RO;
+		desc |= (attr & MT_RW) != 0U ? 0U : SMALL_PAGE_RO;
 
-		desc |= attr & MT_MEMORY ?
+		desc |= (attr & MT_MEMORY) != 0U ?
 			SMALL_PAGE_NORMAL_CACHED : SMALL_PAGE_DEVICE;
 
-		if ((attr & MT_RW) || !(attr & MT_MEMORY))
+		if (((attr & MT_RW) != 0U) || ((attr & MT_MEMORY) == 0U)) {
 			desc |= SMALL_PAGE_XN;
+		}
 		break;
 	default:
 		panic();
 	}
 #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
 	/* dump only the non-lpae level 2 tables */
-	if (level == 2) {
+	if (level == 2U) {
 		printf(attr & MT_MEMORY ? "MEM" : "dev");
 		printf(attr & MT_RW ? "-rw" : "-RO");
 		printf(attr & MT_NS ? "-NS" : "-S");
@@ -357,26 +364,31 @@
 	 */
 	for ( ; ; ++mm) {
 
-		if (mm->size == 0U)
+		if (mm->size == 0U) {
 			return ret; /* Reached end of list */
+		}
 
-		if (mm->base_va > (base_va + size - 1U))
+		if (mm->base_va > (base_va + size - 1U)) {
 			return ret; /* Next region is after area so end */
+		}
 
-		if ((mm->base_va + mm->size - 1U) < base_va)
+		if ((mm->base_va + mm->size - 1U) < base_va) {
 			continue; /* Next region has already been overtaken */
+		}
 
-		if ((ret == 0U) && (mm->attr == *attr))
+		if ((ret == 0U) && (mm->attr == *attr)) {
 			continue; /* Region doesn't override attribs so skip */
+		}
 
 		if ((mm->base_va > base_va) ||
-			((mm->base_va + mm->size - 1U) < (base_va + size - 1U)))
+			((mm->base_va + mm->size - 1U) <
+					(base_va + size - 1U))) {
 			return MT_UNKNOWN; /* Region doesn't fully cover area */
+		}
 
 		*attr = mm->attr;
 		ret = 0U;
 	}
-	return ret;
 }
 
 static mmap_region_t *init_xlation_table_inner(mmap_region_t *mm,
@@ -384,16 +396,16 @@
 						uint32_t *table,
 						unsigned int level)
 {
-	unsigned int level_size_shift = (level == 1) ?
+	unsigned int level_size_shift = (level == 1U) ?
 					ONE_MB_SHIFT : FOUR_KB_SHIFT;
-	unsigned int level_size = 1 << level_size_shift;
-	unsigned int level_index_mask = (level == 1) ?
+	unsigned int level_size = 1U << level_size_shift;
+	unsigned int level_index_mask = (level == 1U) ?
 					(NUM_1MB_IN_4GB - 1) << ONE_MB_SHIFT :
 					(NUM_4K_IN_1MB - 1) << FOUR_KB_SHIFT;
 
-	assert(level == 1 || level == 2);
+	assert((level == 1U) || (level == 2U));
 
-	VERBOSE("init xlat table at %p (level%1d)\n", (void *)table, level);
+	VERBOSE("init xlat table at %p (level%1u)\n", (void *)table, level);
 
 	do  {
 		uint32_t desc = MMU32B_UNSET_DESC;
@@ -405,15 +417,17 @@
 		}
 #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
 		/* dump only non-lpae level 2 tables content */
-		if (level == 2)
+		if (level == 2U) {
 			printf("      0x%lx %x " + 6 - 2 * level,
 						base_va, level_size);
+		}
 #endif
 		if (mm->base_va >= base_va + level_size) {
 			/* Next region is after area so nothing to map yet */
 			desc = MMU32B_INVALID_DESC;
-		} else if (mm->base_va <= base_va && mm->base_va + mm->size >=
-				base_va + level_size) {
+		} else if ((mm->base_va <= base_va) &&
+				(mm->base_va + mm->size) >=
+				(base_va + level_size)) {
 			/* Next region covers all of area */
 			unsigned int attr = mm->attr;
 			unsigned int r = mmap_region_attr(mm, base_va,
@@ -436,8 +450,8 @@
 			 */
 			if (*table) {
 				assert((*table & 3) == SECTION_PT_PT);
-				assert(!(*table & SECTION_PT_NOTSECURE) ==
-							!(mm->attr & MT_NS));
+				assert(((*table & SECTION_PT_NOTSECURE) == 0U)
+						== ((mm->attr & MT_NS) == 0U));
 
 				xlat_table = (*table) &
 						~(MMU32B_L1_TABLE_ALIGN - 1);
@@ -447,11 +461,11 @@
 					next_xlat * MMU32B_L2_TABLE_SIZE;
 				next_xlat++;
 				assert(next_xlat <= MAX_XLAT_TABLES);
-				memset((char *)xlat_table, 0,
+				(void)memset((char *)xlat_table, 0,
 					MMU32B_L2_TABLE_SIZE);
 
 				desc = xlat_table | SECTION_PT_PT;
-				desc |= mm->attr & MT_NS ?
+				desc |= (mm->attr & MT_NS) != 0U ?
 					SECTION_PT_NOTSECURE : 0;
 			}
 			/* Recurse to fill in new table */
@@ -461,12 +475,13 @@
 		}
 #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
 		/* dump only non-lpae level 2 tables content */
-		if (level == 2)
+		if (level == 2U) {
 			printf("\n");
+		}
 #endif
 		*table++ = desc;
 		base_va += level_size;
-	} while (mm->size && (base_va & level_index_mask));
+	} while ((mm->size != 0U) && ((base_va & level_index_mask) != 0U));
 
 	return mm;
 }
@@ -475,17 +490,16 @@
 {
 	print_mmap();
 
-	assert(!((unsigned int)mmu_l1_base & (MMU32B_L1_TABLE_ALIGN - 1)));
-	assert(!((unsigned int)mmu_l2_base & (MMU32B_L2_TABLE_ALIGN - 1)));
+	assert(((unsigned int)mmu_l1_base & (MMU32B_L1_TABLE_ALIGN - 1)) == 0U);
+	assert(((unsigned int)mmu_l2_base & (MMU32B_L2_TABLE_ALIGN - 1)) == 0U);
 
-	memset(mmu_l1_base, 0, MMU32B_L1_TABLE_SIZE);
+	(void)memset(mmu_l1_base, 0, MMU32B_L1_TABLE_SIZE);
 
 	init_xlation_table_inner(mmap, 0, (uint32_t *)mmu_l1_base, 1);
 
 	VERBOSE("init xlat - max_va=%p, max_pa=%llx\n",
 			(void *)xlat_max_va, xlat_max_pa);
-	assert(xlat_max_va <= PLAT_VIRT_ADDR_SPACE_SIZE - 1);
-	assert(xlat_max_pa <= PLAT_VIRT_ADDR_SPACE_SIZE - 1);
+	assert(xlat_max_pa <= (PLAT_VIRT_ADDR_SPACE_SIZE - 1));
 }
 
 /*******************************************************************************
@@ -499,7 +513,7 @@
 	unsigned int sctlr;
 
 	assert(IS_IN_SECURE());
-	assert((read_sctlr() & SCTLR_M_BIT) == 0);
+	assert((read_sctlr() & SCTLR_M_BIT) == 0U);
 
 	/* Enable Access flag (simplified access permissions) and TEX remap */
 	write_sctlr(read_sctlr() | SCTLR_AFE_BIT | SCTLR_TRE_BIT);
@@ -522,7 +536,7 @@
 
 	/* set MMU base xlat table entry (use only TTBR0) */
 	write_ttbr0((uint32_t)mmu_l1_base | MMU32B_DEFAULT_ATTRS);
-	write_ttbr1(0);
+	write_ttbr1(0U);
 
 	/*
 	 * Ensure all translation table writes have drained
@@ -535,14 +549,15 @@
 
 	sctlr = read_sctlr();
 	sctlr |= SCTLR_M_BIT;
-#if ARMV7_SUPPORTS_VIRTUALIZATION
+#ifdef ARMV7_SUPPORTS_VIRTUALIZATION
 	sctlr |= SCTLR_WXN_BIT;
 #endif
 
-	if (flags & DISABLE_DCACHE)
+	if ((flags & DISABLE_DCACHE) != 0U) {
 		sctlr &= ~SCTLR_C_BIT;
-	else
+	} else {
 		sctlr |= SCTLR_C_BIT;
+	}
 
 	write_sctlr(sctlr);
 
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index e5880d2..caf5990 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -226,7 +226,10 @@
 ARM_IO_IN_DTB			:= 0
 
 # Build option to support SDEI through fconf
-SDEI_IN_FCONF			:=0
+SDEI_IN_FCONF			:= 0
+
+# Build option to support Secure Interrupt descriptors through fconf
+SEC_INT_DESC_IN_FCONF		:= 0
 
 # Build option to choose whether Trusted Firmware uses library at ROM
 USE_ROMLIB			:= 0
@@ -299,3 +302,12 @@
 
 # Select workaround for AT speculative behaviour.
 ERRATA_SPECULATIVE_AT           := 0
+
+# Trap RAS error record access from lower EL
+RAS_TRAP_LOWER_EL_ERR_ACCESS	:= 0
+
+# Build option to create cot descriptors using fconf
+COT_DESC_IN_DTB			:= 0
+
+# Build option to provide openssl directory path
+OPENSSL_DIR			:= /usr
diff --git a/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk
index f0adfe1..9520934 100644
--- a/make_helpers/tbbr/tbbr_tools.mk
+++ b/make_helpers/tbbr/tbbr_tools.mk
@@ -99,3 +99,8 @@
     $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/nt_fw_key.crt,--nt-fw-key-cert))
 endif
 endif
+
+# Add SiP owned Secure Partitions CoT (image cert)
+ifneq (${SP_LAYOUT_FILE},)
+    $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/sip_sp_content.crt,--sip-sp-cert))
+endif
diff --git a/plat/allwinner/common/sunxi_security.c b/plat/allwinner/common/sunxi_security.c
index 1f16a0b..92c83b0 100644
--- a/plat/allwinner/common/sunxi_security.c
+++ b/plat/allwinner/common/sunxi_security.c
@@ -39,8 +39,8 @@
 	/* set MBUS clocks, bus clocks (AXI/AHB/APB) and PLLs to non-secure */
 	mmio_write_32(SUNXI_CCU_SEC_SWITCH_REG, 0x7);
 
-	/* set R_PRCM clocks to non-secure */
-	mmio_write_32(SUNXI_R_PRCM_BASE + R_PRCM_SEC_SWITCH_REG, 0x7);
+	/* Set R_PRCM bus clocks to non-secure */
+	mmio_write_32(SUNXI_R_PRCM_BASE + R_PRCM_SEC_SWITCH_REG, 0x1);
 
 	/* Set all DMA channels (16 max.) to non-secure */
 	mmio_write_32(SUNXI_DMA_BASE + DMA_SEC_REG, 0xffff);
diff --git a/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts b/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts
index ff079ab..b9ff8bf 100644
--- a/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts
+++ b/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts
@@ -4,7 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <export/common/tbbr/tbbr_img_def_exp.h>
+#include <common/tbbr/tbbr_img_def.h>
 
 /dts-v1/;
 
@@ -12,9 +12,8 @@
 	dtb-registry {
 		compatible = "fconf,dyn_cfg-dtb_registry";
 
-		/* tb_fw_config is temporarily contained in this dtb */
 		tb_fw-config {
-			load-address = <0x0 0x2001010>;
+			load-address = <0x0 0x2001300>;
 			max-size = <0x200>;
 			id = <TB_FW_CONFIG_ID>;
 		};
@@ -25,11 +24,4 @@
 			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
new file mode 100644
index 0000000..c66186f
--- /dev/null
+++ b/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+	};
+};
diff --git a/plat/arm/board/a5ds/include/platform_def.h b/plat/arm/board/a5ds/include/platform_def.h
index ab0ff58..792a754 100644
--- a/plat/arm/board/a5ds/include/platform_def.h
+++ b/plat/arm/board/a5ds/include/platform_def.h
@@ -152,10 +152,18 @@
 #endif
 
 /*
+ * Map the region for device tree configuration with read and write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION	MAP_REGION_FLAT(ARM_BL_RAM_BASE,	\
+						(ARM_FW_CONFIGS_LIMIT		\
+							- ARM_BL_RAM_BASE),	\
+						MT_MEMORY | MT_RW | MT_SECURE)
+
+/*
  * The max number of regions like RO(code), coherent and data required by
  * different BL stages which need to be mapped in the MMU.
  */
-#define ARM_BL_REGIONS			5
+#define ARM_BL_REGIONS			6
 
 #define MAX_MMAP_REGIONS		(PLAT_ARM_MMAP_ENTRIES +	\
 					 ARM_BL_REGIONS)
@@ -188,11 +196,17 @@
 #define CACHE_WRITEBACK_GRANULE		(U(1) << ARM_CACHE_WRITEBACK_SHIFT)
 
 /*
- * To enable TB_FW_CONFIG to be loaded by BL1, define the corresponding base
+ * To enable FW_CONFIG to be loaded by BL1, define the corresponding base
  * and limit. Leave enough space of BL2 meminfo.
  */
-#define ARM_TB_FW_CONFIG_BASE		(ARM_BL_RAM_BASE + sizeof(meminfo_t))
-#define ARM_TB_FW_CONFIG_LIMIT		(ARM_BL_RAM_BASE + PAGE_SIZE)
+#define ARM_FW_CONFIG_BASE		(ARM_BL_RAM_BASE + sizeof(meminfo_t))
+#define ARM_FW_CONFIG_LIMIT		(ARM_BL_RAM_BASE + PAGE_SIZE)
+
+/*
+ * Define limit of firmware configuration memory:
+ * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory
+ */
+#define ARM_FW_CONFIGS_LIMIT		(ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
 
 /*******************************************************************************
  * BL1 specific defines.
@@ -220,7 +234,9 @@
 #define BL2_LIMIT			BL1_RW_BASE
 
 /* Put BL32 below BL2 in NS DRAM.*/
-#define ARM_BL2_MEM_DESC_BASE		ARM_TB_FW_CONFIG_LIMIT
+#define ARM_BL2_MEM_DESC_BASE		ARM_FW_CONFIG_LIMIT
+#define ARM_BL2_MEM_DESC_LIMIT		(ARM_BL2_MEM_DESC_BASE \
+					+ (PAGE_SIZE / 2U))
 
 #define BL32_BASE			((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)\
 						- PLAT_ARM_MAX_BL32_SIZE)
diff --git a/plat/arm/board/a5ds/platform.mk b/plat/arm/board/a5ds/platform.mk
index 3a4d5e5..5d610f4 100644
--- a/plat/arm/board/a5ds/platform.mk
+++ b/plat/arm/board/a5ds/platform.mk
@@ -14,9 +14,10 @@
 				plat/arm/common/arm_dyn_cfg_helpers.c	\
 				common/fdt_wrappers.c
 
-A5DS_GIC_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
-				drivers/arm/gic/v2/gicv2_main.c		\
-				drivers/arm/gic/v2/gicv2_helpers.c	\
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+A5DS_GIC_SOURCES	:=	${GICV2_SOURCES}			\
 				plat/common/plat_gicv2.c		\
 				plat/arm/common/arm_gicv2.c
 
@@ -72,10 +73,13 @@
 # Add the FDT_SOURCES and options for Dynamic Config (only for Unix env)
 ifdef UNIX_MK
 
-FVP_TB_FW_CONFIG	:=	${BUILD_PLAT}/fdts/a5ds_fw_config.dtb
+FW_CONFIG	:=      ${BUILD_PLAT}/fdts/a5ds_fw_config.dtb
+TB_FW_CONFIG	:=	${BUILD_PLAT}/fdts/a5ds_tb_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))
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config))
 
 $(eval FVP_HW_CONFIG	:=	${BUILD_PLAT}/$(patsubst %.dts,%.dtb, \
 	fdts/$(notdir ${FVP_HW_CONFIG_DTS})))
@@ -83,6 +87,7 @@
 $(eval $(call TOOL_ADD_PAYLOAD,${FVP_HW_CONFIG},--hw-config))
 
 FDT_SOURCES		+=	plat/arm/board/a5ds/fdts/a5ds_fw_config.dts \
+				plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts \
 					${FVP_HW_CONFIG_DTS}
 endif
 
diff --git a/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S b/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S
index aeed310..20120c9 100644
--- a/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S
+++ b/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S
@@ -7,6 +7,8 @@
 #include <arch.h>
 #include <asm_macros.S>
 #include <common/bl_common.h>
+#include "../fpga_private.h"
+
 #include <platform_def.h>
 
 	.globl	plat_get_my_entrypoint
@@ -14,10 +16,10 @@
 	.globl	plat_is_my_cpu_primary
 	.globl	platform_mem_init
 	.globl	plat_my_core_pos
-	.globl	plat_fpga_calc_core_pos
 	.globl	plat_crash_console_init
 	.globl	plat_crash_console_putc
 	.globl	plat_crash_console_flush
+	.globl	plat_fpga_calc_core_pos
 
 /* -----------------------------------------------------------------------
  * Indicate a cold boot for every CPU - warm boot is unsupported for the
@@ -34,23 +36,59 @@
  * -----------------------------------------------------------------------
  */
 func plat_secondary_cold_boot_setup
+
+	/*
+	 * Wait for the primary processor to initialise the .BSS segment
+	 * to avoid a race condition that would erase fpga_valid_mpids
+	 * if it is populated before the C runtime is ready.
+	 *
+	 * We cannot use the current spin-lock implementation until the
+	 * runtime is up and we should not rely on sevl/wfe instructions as
+	 * it is optional whether they are implemented or not, so we use
+	 * a global variable as lock and wait for the primary processor to
+	 * finish the C runtime bring-up.
+	 */
+
+	ldr	w0, =C_RUNTIME_READY_KEY
+	adrp	x1, secondary_core_spinlock
+	add	x1, x1, :lo12:secondary_core_spinlock
+1:
+	wfe
+	ldr	w2, [x1]
+	cmp	w2, w0
+	b.ne	1b
+	/* Prevent reordering of the store into fpga_valid_mpids below */
+	dmb	ish
+
+	mov	x10, x30
+	bl	plat_my_core_pos
+	mov	x30, x10
+
+	adrp	x4, fpga_valid_mpids
+	add	x4, x4, :lo12:fpga_valid_mpids
+	mov	x5, #VALID_MPID
+	strb	w5, [x4, x0]
+
 	/*
 	 * Poll the CPU's hold entry until it indicates to jump
 	 * to the entrypoint address.
 	 */
-	bl	plat_my_core_pos
-	lsl	x0, x0, #PLAT_FPGA_HOLD_ENTRY_SHIFT
-	ldr	x1, =hold_base
-	ldr	x2, =fpga_sec_entrypoint
+
+	adrp	x1, hold_base
+	add	x1, x1, :lo12:hold_base
 poll_hold_entry:
-	ldr	x3, [x1, x0]
+	ldr	x3, [x1, x0, LSL #PLAT_FPGA_HOLD_ENTRY_SHIFT]
 	cmp	x3, #PLAT_FPGA_HOLD_STATE_GO
 	b.ne	1f
+
+	adrp	x2, fpga_sec_entrypoint
+	add	x2, x2, :lo12:fpga_sec_entrypoint
 	ldr	x3, [x2]
 	br	x3
 1:
 	wfe
 	b	poll_hold_entry
+
 endfunc plat_secondary_cold_boot_setup
 
 /* -----------------------------------------------------------------------
@@ -73,12 +111,16 @@
 endfunc platform_mem_init
 
 func plat_my_core_pos
+	ldr	x1, =(MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT))
 	mrs	x0, mpidr_el1
+	and	x0, x0, x1
 	b	plat_fpga_calc_core_pos
+
 endfunc plat_my_core_pos
 
 /* -----------------------------------------------------------------------
- * unsigned int plat_fpga_calc_core_pos(u_register_t mpidr)
+ * unsigned int plat_fpga_calc_core_pos (uint32_t mpid)
+ * Clobber registers: x0 to x5
  * -----------------------------------------------------------------------
  */
 func plat_fpga_calc_core_pos
@@ -88,6 +130,7 @@
 	 *
 	 * If not set, shift MPIDR to left to make it look as if in a
 	 * multi-threaded implementation.
+	 *
 	 */
 	tst	x0, #MPIDR_MT_MASK
 	lsl	x3, x0, #MPIDR_AFFINITY_BITS
@@ -98,11 +141,13 @@
 	ubfx	x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
 	ubfx	x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
 
-	/* Compute linear position */
 	mov	x4, #FPGA_MAX_CPUS_PER_CLUSTER
-	madd	x1, x2, x4, x1
 	mov	x5, #FPGA_MAX_PE_PER_CPU
+
+	/* Compute linear position */
+	madd	x1, x2, x4, x1
 	madd	x0, x1, x5, x0
+
 	ret
 endfunc plat_fpga_calc_core_pos
 
diff --git a/plat/arm/board/arm_fpga/fpga_bl31_setup.c b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
index e4b9767..9db107c 100644
--- a/plat/arm/board/arm_fpga/fpga_bl31_setup.c
+++ b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
@@ -7,23 +7,23 @@
 #include <assert.h>
 
 #include <common/fdt_wrappers.h>
+#include <drivers/delay_timer.h>
 #include <drivers/generic_delay_timer.h>
-#include <lib/mmio.h>
 #include <libfdt.h>
 
+#include "fpga_private.h"
 #include <plat/common/platform.h>
 #include <platform_def.h>
 
-#include "fpga_private.h"
-
 static entry_point_info_t bl33_image_ep_info;
+volatile uint32_t secondary_core_spinlock;
 
 uintptr_t plat_get_ns_image_entrypoint(void)
 {
 #ifdef PRELOADED_BL33_BASE
 	return PRELOADED_BL33_BASE;
 #else
-	return 0;
+	return 0ULL;
 #endif
 }
 
@@ -35,6 +35,17 @@
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
+	/* Add this core to the VALID mpids list */
+	fpga_valid_mpids[plat_my_core_pos()] = VALID_MPID;
+
+	/*
+	 * Notify the secondary CPUs that the C runtime is ready
+	 * so they can announce themselves.
+	 */
+	secondary_core_spinlock = C_RUNTIME_READY_KEY;
+	dsbish();
+	sev();
+
 	fpga_console_init();
 
 	bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
@@ -54,11 +65,37 @@
 
 void bl31_platform_setup(void)
 {
-	/* Initialize the GIC driver, cpu and distributor interfaces */
-	plat_fpga_gic_init();
-
 	/* Write frequency to CNTCRL and initialize timer */
 	generic_delay_timer_init();
+
+	/*
+	 * Before doing anything else, wait for some time to ensure that
+	 * the secondary CPUs have populated the fpga_valid_mpids array.
+	 * As the number of secondary cores is unknown and can even be 0,
+	 * it is not possible to rely on any signal from them, so use a
+	 * delay instead.
+	 */
+	mdelay(5);
+
+	/*
+	 * On the event of a cold reset issued by, for instance, a reset pin
+	 * assertion, we cannot guarantee memory to be initialized to zero.
+	 * In such scenario, if the secondary cores reached
+	 * plat_secondary_cold_boot_setup before the primary one initialized
+	 * .BSS, we could end up having a race condition if the spinlock
+	 * was not cleared before.
+	 *
+	 * Similarly, if there were a reset before the spinlock had been
+	 * cleared, the secondary cores would find the lock opened before
+	 * .BSS is cleared, causing another race condition.
+	 *
+	 * So clean the spinlock as soon as we think it is safe to reduce the
+	 * chances of any race condition on a reset.
+	 */
+	secondary_core_spinlock = 0UL;
+
+	/* Initialize the GIC driver, cpu and distributor interfaces */
+	plat_fpga_gic_init();
 }
 
 entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
@@ -91,6 +128,84 @@
 				       FPGA_DEFAULT_TIMER_FREQUENCY);
 }
 
+static void fpga_prepare_dtb(void)
+{
+	void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE;
+	const char *cmdline = (void *)(uintptr_t)FPGA_PRELOADED_CMD_LINE;
+	int err;
+
+	err = fdt_open_into(fdt, fdt, FPGA_MAX_DTB_SIZE);
+	if (err < 0) {
+		ERROR("cannot open devicetree at %p: %d\n", fdt, err);
+		panic();
+	}
+
+	/* Check for the command line signature. */
+	if (!strncmp(cmdline, "CMD:", 4)) {
+		int chosen;
+
+		INFO("using command line at 0x%x\n", FPGA_PRELOADED_CMD_LINE);
+
+		chosen = fdt_add_subnode(fdt, 0, "chosen");
+		if (chosen == -FDT_ERR_EXISTS) {
+			chosen = fdt_path_offset(fdt, "/chosen");
+		}
+		if (chosen < 0) {
+			ERROR("cannot find /chosen node: %d\n", chosen);
+		} else {
+			const char *eol;
+			char nul = 0;
+			int slen;
+
+			/*
+			 * There is most likely an EOL at the end of the
+			 * command line, make sure we terminate the line there.
+			 * We can't replace the EOL with a NUL byte in the
+			 * source, as this is in read-only memory. So we first
+			 * create the property without any termination, then
+			 * append a single NUL byte.
+			 */
+			eol = strchr(cmdline, '\n');
+			if (!eol) {
+				eol = strchr(cmdline, 0);
+			}
+			/* Skip the signature and omit the EOL/NUL byte. */
+			slen = eol - (cmdline + 4);
+
+			/*
+			 * Let's limit the size of the property, just in case
+			 * we find the signature by accident. The Linux kernel
+			 * limits to 4096 characters at most (in fact 2048 for
+			 * arm64), so that sounds like a reasonable number.
+			 */
+			if (slen > 4095) {
+				slen = 4095;
+			}
+			err = fdt_setprop(fdt, chosen, "bootargs",
+					  cmdline + 4, slen);
+			if (!err) {
+				err = fdt_appendprop(fdt, chosen, "bootargs",
+						     &nul, 1);
+			}
+			if (err) {
+				ERROR("Could not set command line: %d\n", err);
+			}
+		}
+	}
+
+	err = fdt_pack(fdt);
+	if (err < 0) {
+		ERROR("Failed to pack Device Tree at %p: error %d\n", fdt, err);
+	}
+
+	clean_dcache_range((uintptr_t)fdt, fdt_blob_size(fdt));
+}
+
+void bl31_plat_runtime_setup(void)
+{
+	fpga_prepare_dtb();
+}
+
 void bl31_plat_enable_mmu(uint32_t flags)
 {
 	/* TODO: determine if MMU needs to be enabled */
diff --git a/plat/arm/board/arm_fpga/fpga_def.h b/plat/arm/board/arm_fpga/fpga_def.h
index 0378729..2884ea6 100644
--- a/plat/arm/board/arm_fpga/fpga_def.h
+++ b/plat/arm/board/arm_fpga/fpga_def.h
@@ -18,7 +18,8 @@
  * that are present will still be indexed appropriately regardless of any empty
  * entries in the array used to represent the topology.
  */
-#define FPGA_MAX_CLUSTER_COUNT			2
+
+#define FPGA_MAX_CLUSTER_COUNT			4
 #define FPGA_MAX_CPUS_PER_CLUSTER		8
 #define FPGA_MAX_PE_PER_CPU			4
 
diff --git a/plat/arm/board/arm_fpga/fpga_private.h b/plat/arm/board/arm_fpga/fpga_private.h
index 7545bd1..47059d6 100644
--- a/plat/arm/board/arm_fpga/fpga_private.h
+++ b/plat/arm/board/arm_fpga/fpga_private.h
@@ -7,12 +7,24 @@
 #ifndef FPGA_PRIVATE_H
 #define FPGA_PRIVATE_H
 
-unsigned int plat_fpga_calc_core_pos(u_register_t mpidr);
+#include "../fpga_def.h"
+#include <platform_def.h>
+
+#define C_RUNTIME_READY_KEY	(0xaa55aa55)
+#define VALID_MPID		(1U)
+#define FPGA_MAX_DTB_SIZE	0x10000
+
+#ifndef __ASSEMBLER__
+
+extern unsigned char fpga_valid_mpids[PLATFORM_CORE_COUNT];
 
 void fpga_console_init(void);
 
 void plat_fpga_gic_init(void);
 void fpga_pwr_gic_on_finish(void);
 void fpga_pwr_gic_off(void);
+unsigned int plat_fpga_calc_core_pos(uint32_t mpid);
 
-#endif
+#endif /* __ASSEMBLER__ */
+
+#endif /* FPGA_PRIVATE_H */
diff --git a/plat/arm/board/arm_fpga/fpga_topology.c b/plat/arm/board/arm_fpga/fpga_topology.c
index a705429..7fead86 100644
--- a/plat/arm/board/arm_fpga/fpga_topology.c
+++ b/plat/arm/board/arm_fpga/fpga_topology.c
@@ -5,15 +5,20 @@
  */
 
 #include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/spinlock.h>
 
 #include "fpga_private.h"
+#include <plat/common/platform.h>
 #include <platform_def.h>
 
-static unsigned char fpga_power_domain_tree_desc[FPGA_MAX_CLUSTER_COUNT + 2];
+unsigned char fpga_power_domain_tree_desc[FPGA_MAX_CLUSTER_COUNT + 2];
+unsigned char fpga_valid_mpids[PLATFORM_CORE_COUNT];
 
 const unsigned char *plat_get_power_domain_tree_desc(void)
 {
-	int i;
+	unsigned int i;
+
 	/*
 	* The highest level is the system level. The next level is constituted
 	* by clusters and then cores in clusters.
@@ -21,12 +26,26 @@
 	* This description of the power domain topology is aligned with the CPU
 	* indices returned by the plat_core_pos_by_mpidr() and plat_my_core_pos()
 	* APIs.
+	*
+	* A description of the topology tree can be found at
+	* https://trustedfirmware-a.readthedocs.io/en/latest/design/psci-pd-tree.html#design
 	*/
-	fpga_power_domain_tree_desc[0] = 1;
-	fpga_power_domain_tree_desc[1] = FPGA_MAX_CLUSTER_COUNT;
 
-	for (i = 0; i < FPGA_MAX_CLUSTER_COUNT; i++) {
-		fpga_power_domain_tree_desc[i + 2] = FPGA_MAX_CPUS_PER_CLUSTER;
+	if (fpga_power_domain_tree_desc[0] == 0U) {
+		/*
+		 * As fpga_power_domain_tree_desc[0] == 0, assume that the
+		 * Power Domain Topology Tree has not been initialized, so
+		 * perform the initialization here.
+		 */
+
+		fpga_power_domain_tree_desc[0] = 1U;
+		fpga_power_domain_tree_desc[1] = FPGA_MAX_CLUSTER_COUNT;
+
+		for (i = 0U; i < FPGA_MAX_CLUSTER_COUNT; i++) {
+			fpga_power_domain_tree_desc[2 + i] =
+				(FPGA_MAX_CPUS_PER_CLUSTER *
+				 FPGA_MAX_PE_PER_CPU);
+		}
 	}
 
 	return fpga_power_domain_tree_desc;
@@ -34,38 +53,25 @@
 
 int plat_core_pos_by_mpidr(u_register_t mpidr)
 {
-	unsigned int cluster_id, cpu_id, thread_id;
+	unsigned int core_pos;
 
-	mpidr &= MPIDR_AFFINITY_MASK;
-	if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) {
-		return -1;
-	}
-
-	if (mpidr & MPIDR_MT_MASK) {
-		thread_id = MPIDR_AFFLVL0_VAL(mpidr);
-	} else {
-		thread_id = 0;
-	}
-
-	cpu_id = MPIDR_AFFLVL1_VAL(mpidr);
-	cluster_id = MPIDR_AFFLVL2_VAL(mpidr);
-
-	if (cluster_id >= FPGA_MAX_CLUSTER_COUNT) {
-		return -1;
-	} else if (cpu_id >= FPGA_MAX_CPUS_PER_CLUSTER) {
-		return -1;
-	} else if (thread_id >= FPGA_MAX_PE_PER_CPU) {
-		return -1;
-	}
-
-	/*
-	 * The image running on the FPGA may or may not implement multithreading,
-	 * and it shouldn't be assumed this is consistent across all CPUs.
-	 * This ensures that any passed mpidr values reflect the status of the
-	 * primary CPU's MT bit.
-	 */
+	mpidr &= (MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT));
 	mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
 
-	/* Calculate the correct core, catering for multi-threaded images */
-	return (int) plat_fpga_calc_core_pos(mpidr);
+	if ((MPIDR_AFFLVL2_VAL(mpidr) >= FPGA_MAX_CLUSTER_COUNT) ||
+	    (MPIDR_AFFLVL1_VAL(mpidr) >= FPGA_MAX_CPUS_PER_CLUSTER) ||
+	    (MPIDR_AFFLVL0_VAL(mpidr) >= FPGA_MAX_PE_PER_CPU)) {
+		ERROR ("Invalid mpidr: 0x%08x\n", (uint32_t)mpidr);
+		panic();
+	}
+
+	/* Calculate the core position, based on the maximum topology. */
+	core_pos = plat_fpga_calc_core_pos(mpidr);
+
+	/* Check whether this core is actually present. */
+	if (fpga_valid_mpids[core_pos] != VALID_MPID) {
+		return -1;
+	}
+
+	return core_pos;
 }
diff --git a/plat/arm/board/arm_fpga/include/platform_def.h b/plat/arm/board/arm_fpga/include/platform_def.h
index 31fc987..411b936 100644
--- a/plat/arm/board/arm_fpga/include/platform_def.h
+++ b/plat/arm/board/arm_fpga/include/platform_def.h
@@ -21,11 +21,12 @@
 #define CACHE_WRITEBACK_SHIFT		U(6)
 #define CACHE_WRITEBACK_GRANULE		(U(1) << CACHE_WRITEBACK_SHIFT)
 
-#define PLATFORM_CORE_COUNT \
-	(FPGA_MAX_CLUSTER_COUNT * FPGA_MAX_CPUS_PER_CLUSTER * FPGA_MAX_PE_PER_CPU)
+#define PLATFORM_CORE_COUNT		\
+	(FPGA_MAX_CLUSTER_COUNT *	\
+	 FPGA_MAX_CPUS_PER_CLUSTER *	\
+	 FPGA_MAX_PE_PER_CPU)
 
-#define PLAT_NUM_PWR_DOMAINS		(FPGA_MAX_CLUSTER_COUNT + \
-					PLATFORM_CORE_COUNT) + 1
+#define PLAT_NUM_PWR_DOMAINS (FPGA_MAX_CLUSTER_COUNT + PLATFORM_CORE_COUNT + 1)
 
 #if !ENABLE_PIE
 #define BL31_BASE			UL(0x80000000)
diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk
index 0d0d010..1e7badf 100644
--- a/plat/arm/board/arm_fpga/platform.mk
+++ b/plat/arm/board/arm_fpga/platform.mk
@@ -24,15 +24,13 @@
 $(error "TRUSTED_BOARD_BOOT must be disabled")
 endif
 
-ifndef PRELOADED_BL33_BASE
-$(error "PRELOADED_BL33_BASE is not set")
-endif
+PRELOADED_BL33_BASE := 0x80080000
 
-ifndef FPGA_PRELOADED_DTB_BASE
-$(error "FPGA_PRELOADED_DTB_BASE is not set")
-else
+FPGA_PRELOADED_DTB_BASE := 0x80070000
 $(eval $(call add_define,FPGA_PRELOADED_DTB_BASE))
-endif
+
+FPGA_PRELOADED_CMD_LINE := 0x1000
+$(eval $(call add_define,FPGA_PRELOADED_CMD_LINE))
 
 # Treating this as a memory-constrained port for now
 USE_COHERENT_MEM	:=	0
@@ -58,20 +56,23 @@
 	FPGA_CPU_LIBS	+=	lib/cpus/aarch64/cortex_a76.S		\
 				lib/cpus/aarch64/cortex_a76ae.S		\
 				lib/cpus/aarch64/cortex_a77.S		\
+				lib/cpus/aarch64/cortex_a78.S		\
 				lib/cpus/aarch64/neoverse_n1.S		\
 				lib/cpus/aarch64/neoverse_e1.S		\
 				lib/cpus/aarch64/neoverse_zeus.S	\
-				lib/cpus/aarch64/cortex_hercules.S	\
 				lib/cpus/aarch64/cortex_hercules_ae.S	\
 				lib/cpus/aarch64/cortex_a65.S		\
-				lib/cpus/aarch64/cortex_a65ae.S
+				lib/cpus/aarch64/cortex_a65ae.S		\
+				lib/cpus/aarch64/cortex_klein.S		\
+				lib/cpus/aarch64/cortex_matterhorn.S
+
 # AArch64/AArch32 cores
 	FPGA_CPU_LIBS	+=	lib/cpus/aarch64/cortex_a55.S	\
 				lib/cpus/aarch64/cortex_a75.S
 endif
 
-# GIC-600 configuration
-GICV3_IMPL		:=	GIC600
+# Allow detection of GIC-600
+GICV3_SUPPORT_GIC600	:=	1
 
 # Include GICv3 driver files
 include drivers/arm/gic/v3/gicv3.mk
diff --git a/plat/arm/board/corstone700/corstone700_helpers.S b/plat/arm/board/corstone700/common/corstone700_helpers.S
similarity index 100%
rename from plat/arm/board/corstone700/corstone700_helpers.S
rename to plat/arm/board/corstone700/common/corstone700_helpers.S
diff --git a/plat/arm/board/corstone700/corstone700_plat.c b/plat/arm/board/corstone700/common/corstone700_plat.c
similarity index 86%
rename from plat/arm/board/corstone700/corstone700_plat.c
rename to plat/arm/board/corstone700/common/corstone700_plat.c
index e2ade70..629f076 100644
--- a/plat/arm/board/corstone700/corstone700_plat.c
+++ b/plat/arm/board/corstone700/common/corstone700_plat.c
@@ -18,6 +18,7 @@
 
 const mmap_region_t plat_arm_mmap[] = {
 	ARM_MAP_SHARED_RAM,
+	ARM_MAP_NS_SHARED_RAM,
 	ARM_MAP_NS_DRAM1,
 	CORSTONE700_MAP_DEVICE,
 	{0}
@@ -33,5 +34,6 @@
 
 unsigned int plat_get_syscnt_freq2(void)
 {
-	return CORSTONE700_TIMER_BASE_FREQUENCY;
+	/* Returning the Generic Timer Frequency */
+	return SYS_COUNTER_FREQ_IN_TICKS;
 }
diff --git a/plat/arm/board/corstone700/corstone700_pm.c b/plat/arm/board/corstone700/common/corstone700_pm.c
similarity index 100%
rename from plat/arm/board/corstone700/corstone700_pm.c
rename to plat/arm/board/corstone700/common/corstone700_pm.c
diff --git a/plat/arm/board/corstone700/corstone700_security.c b/plat/arm/board/corstone700/common/corstone700_security.c
similarity index 100%
rename from plat/arm/board/corstone700/corstone700_security.c
rename to plat/arm/board/corstone700/common/corstone700_security.c
diff --git a/plat/arm/board/corstone700/corstone700_stack_protector.c b/plat/arm/board/corstone700/common/corstone700_stack_protector.c
similarity index 100%
rename from plat/arm/board/corstone700/corstone700_stack_protector.c
rename to plat/arm/board/corstone700/common/corstone700_stack_protector.c
diff --git a/plat/arm/board/corstone700/corstone700_topology.c b/plat/arm/board/corstone700/common/corstone700_topology.c
similarity index 100%
rename from plat/arm/board/corstone700/corstone700_topology.c
rename to plat/arm/board/corstone700/common/corstone700_topology.c
diff --git a/plat/arm/board/corstone700/drivers/mhu/mhu.c b/plat/arm/board/corstone700/common/drivers/mhu/mhu.c
similarity index 100%
rename from plat/arm/board/corstone700/drivers/mhu/mhu.c
rename to plat/arm/board/corstone700/common/drivers/mhu/mhu.c
diff --git a/plat/arm/board/corstone700/drivers/mhu/mhu.h b/plat/arm/board/corstone700/common/drivers/mhu/mhu.h
similarity index 100%
rename from plat/arm/board/corstone700/drivers/mhu/mhu.h
rename to plat/arm/board/corstone700/common/drivers/mhu/mhu.h
diff --git a/plat/arm/board/corstone700/include/platform_def.h b/plat/arm/board/corstone700/common/include/platform_def.h
similarity index 84%
rename from plat/arm/board/corstone700/include/platform_def.h
rename to plat/arm/board/corstone700/common/include/platform_def.h
index cc4dc3a..57b0551 100644
--- a/plat/arm/board/corstone700/include/platform_def.h
+++ b/plat/arm/board/corstone700/common/include/platform_def.h
@@ -67,6 +67,9 @@
 #define ARM_BL_RAM_SIZE			(PLAT_ARM_TRUSTED_SRAM_SIZE -   \
 					ARM_SHARED_RAM_SIZE)
 
+#define ARM_NS_SHARED_RAM_BASE		ARM_TRUSTED_SRAM_BASE + UL(0x00100000)
+#define ARM_NS_SHARED_RAM_SIZE		0x00300000
+
 /*
  * SP_MIN is the only BL image in SRAM. Allocate the whole of SRAM (excluding
  * the page reserved for fw_configs) to BL32
@@ -83,17 +86,30 @@
 #define ARM_CACHE_WRITEBACK_SHIFT	6
 
 /*
- * To enable TB_FW_CONFIG to be loaded by BL1, define the corresponding base
+ * To enable FW_CONFIG to be loaded by BL1, define the corresponding base
  * and limit. Leave enough space for BL2 meminfo.
  */
-#define ARM_TB_FW_CONFIG_BASE		(ARM_BL_RAM_BASE + sizeof(meminfo_t))
-#define ARM_TB_FW_CONFIG_LIMIT		(ARM_BL_RAM_BASE + (PAGE_SIZE / 2U))
+#define ARM_FW_CONFIG_BASE		(ARM_BL_RAM_BASE + sizeof(meminfo_t))
+#define ARM_FW_CONFIG_LIMIT		(ARM_BL_RAM_BASE + (PAGE_SIZE / 2U))
+
+/*
+ * Boot parameters passed from BL2 to BL31/BL32 are stored here
+ */
+#define ARM_BL2_MEM_DESC_BASE		(ARM_FW_CONFIG_LIMIT)
+#define ARM_BL2_MEM_DESC_LIMIT		(ARM_BL2_MEM_DESC_BASE \
+					+ (PAGE_SIZE / 2U))
+
+/*
+ * Define limit of firmware configuration memory:
+ * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory
+ */
+#define ARM_FW_CONFIGS_LIMIT		(ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
 
 /*
  * The max number of regions like RO(code), coherent and data required by
  * different BL stages which need to be mapped in the MMU.
  */
-#define ARM_BL_REGIONS			2
+#define ARM_BL_REGIONS			3
 #define PLAT_ARM_MMAP_ENTRIES		8
 #define MAX_XLAT_TABLES			5
 #define MAX_MMAP_REGIONS		(PLAT_ARM_MMAP_ENTRIES +        \
@@ -111,7 +127,13 @@
 #define ARM_SYS_CNTCTL_BASE			UL(0x1a200000)
 #define ARM_SYS_CNTREAD_BASE			UL(0x1a210000)
 #define ARM_SYS_TIMCTL_BASE			UL(0x1a220000)
-#define CORSTONE700_TIMER_BASE_FREQUENCY	UL(24000000)
+
+#ifdef TARGET_PLATFORM_FVP
+#define SYS_COUNTER_FREQ_IN_TICKS	UL(50000000) /* 50MHz */
+#else
+#define SYS_COUNTER_FREQ_IN_TICKS	UL(32000000) /* 32MHz */
+#endif
+
 #define CORSTONE700_IRQ_TZ_WDOG			32
 #define CORSTONE700_IRQ_SEC_SYS_TIMER		34
 
@@ -140,7 +162,7 @@
 #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_BASE			(ARM_NS_SHARED_RAM_BASE)
 
 #define PLAT_PHY_ADDR_SPACE_SIZE		(1ULL << 32)
 #define PLAT_VIRT_ADDR_SPACE_SIZE		(1ULL << 32)
@@ -162,7 +184,12 @@
 #define ARM_MAP_SHARED_RAM			MAP_REGION_FLAT(	\
 						ARM_SHARED_RAM_BASE,	\
 						ARM_SHARED_RAM_SIZE,	\
-						MT_DEVICE | MT_RW | MT_SECURE)
+						MT_MEMORY | MT_RW | MT_SECURE)
+
+#define ARM_MAP_NS_SHARED_RAM			MAP_REGION_FLAT(	\
+						ARM_NS_SHARED_RAM_BASE,	\
+						ARM_NS_SHARED_RAM_SIZE,	\
+						MT_MEMORY | MT_RW | MT_NS)
 
 #define ARM_MAP_NS_DRAM1		MAP_REGION_FLAT(		\
 						ARM_NS_DRAM1_BASE,	\
@@ -187,6 +214,14 @@
 						MT_DEVICE | MT_RW | MT_SECURE)
 #endif
 
+/*
+ * Map the region for device tree configuration with read and write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION	MAP_REGION_FLAT(ARM_BL_RAM_BASE,	\
+						(ARM_FW_CONFIGS_LIMIT		\
+							- ARM_BL_RAM_BASE),	\
+						MT_MEMORY | MT_RW | MT_SECURE)
+
 #define CORSTONE700_DEVICE_BASE		(0x1A000000)
 #define CORSTONE700_DEVICE_SIZE		(0x26000000)
 #define CORSTONE700_MAP_DEVICE		MAP_REGION_FLAT(		\
diff --git a/plat/arm/board/corstone700/platform.mk b/plat/arm/board/corstone700/platform.mk
index a4d4f22..513af3c 100644
--- a/plat/arm/board/corstone700/platform.mk
+++ b/plat/arm/board/corstone700/platform.mk
@@ -4,6 +4,11 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+# Making sure the corstone700 platform type is specified
+ifeq ($(filter ${TARGET_PLATFORM}, fpga fvp),)
+        $(error TARGET_PLATFORM must be fpga or fvp)
+endif
+
 CORSTONE700_CPU_LIBS	+=	lib/cpus/aarch32/cortex_a32.S
 
 BL32_SOURCES		+=	plat/arm/common/aarch32/arm_helpers.S	\
@@ -12,17 +17,18 @@
 				lib/xlat_tables/aarch32/xlat_tables.c	\
 				lib/xlat_tables/xlat_tables_common.c	\
 				${CORSTONE700_CPU_LIBS}	\
-				plat/arm/board/corstone700/drivers/mhu/mhu.c
+				plat/arm/board/corstone700/common/drivers/mhu/mhu.c
 
-PLAT_INCLUDES		:=	-Iplat/arm/board/corstone700/include	\
+PLAT_INCLUDES		:=	-Iplat/arm/board/corstone700/common/include	\
 				-Iinclude/plat/arm/common	\
-				-Iplat/arm/board/corstone700/drivers/mhu
+				-Iplat/arm/board/corstone700/common/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	\
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+CORSTONE700_GIC_SOURCES	:=	${GICV2_SOURCES}			\
 				plat/common/plat_gicv2.c		\
 				plat/arm/common/arm_gicv2.c
 
@@ -30,13 +36,14 @@
 override NEED_BL1	:=	no
 override NEED_BL2	:=	no
 override NEED_BL2U	:=	no
+override NEED_BL33	:=	yes
 
 #TFA for Corstone700 starts from BL32
 override RESET_TO_SP_MIN	:=	1
 
 #Device tree
-CORSTONE700_HW_CONFIG_DTS	:=	fdts/corstone700.dts
-CORSTONE700_HW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}.dtb
+CORSTONE700_HW_CONFIG_DTS	:=	fdts/corstone700_${TARGET_PLATFORM}.dts
+CORSTONE700_HW_CONFIG		:=	${BUILD_PLAT}/fdts/corstone700_${TARGET_PLATFORM}.dtb
 FDT_SOURCES			+=	${CORSTONE700_HW_CONFIG_DTS}
 $(eval CORSTONE700_HW_CONFIG	:=	${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(CORSTONE700_HW_CONFIG_DTS)))
 
@@ -49,4 +56,8 @@
     $(error "ARM_PRELOADED_DTB_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used.")
   endif
   $(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
+
+# Adding TARGET_PLATFORM as a GCC define (-D option)
+$(eval $(call add_define,TARGET_PLATFORM_$(call uppercase,${TARGET_PLATFORM})))
+
 include plat/arm/board/common/board_common.mk
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 acee6c3..75dc0f1 100644
--- a/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk
+++ b/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk
@@ -7,17 +7,17 @@
 # SP_MIN source files specific to FVP platform
 BL32_SOURCES	+=	drivers/cfi/v2m/v2m_flash.c				\
 			lib/utils/mem_region.c					\
-			plat/arm/board/corstone700/corstone700_helpers.S	\
-			plat/arm/board/corstone700/corstone700_topology.c	\
-			plat/arm/board/corstone700/corstone700_security.c	\
-			plat/arm/board/corstone700/corstone700_plat.c		\
-			plat/arm/board/corstone700/corstone700_pm.c		\
+			plat/arm/board/corstone700/common/corstone700_helpers.S	\
+			plat/arm/board/corstone700/common/corstone700_topology.c	\
+			plat/arm/board/corstone700/common/corstone700_security.c	\
+			plat/arm/board/corstone700/common/corstone700_plat.c		\
+			plat/arm/board/corstone700/common/corstone700_pm.c		\
 			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
+		BL32_SOURCES += plat/arm/board/corstone700/common/corstone700_stack_protector.c
 	endif
 endif
 
diff --git a/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
index f1d9b93..35a777b 100644
--- a/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
+++ b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
@@ -13,6 +13,10 @@
 
 struct gicv3_config_t gicv3_config;
 struct hw_topology_t soc_topology;
+struct uart_serial_config_t uart_serial_config;
+struct cpu_timer_t cpu_timer;
+
+#define ILLEGAL_ADDR	ULL(~0)
 
 int fconf_populate_gicv3_config(uintptr_t config)
 {
@@ -147,7 +151,8 @@
 			return -1;
 		}
 
-		INFO("CLUSTER ID: %d cpu-count: %d\n", cluster_count, cpus_per_cluster[cluster_count]);
+		VERBOSE("CLUSTER ID: %d cpu-count: %d\n", cluster_count,
+					cpus_per_cluster[cluster_count]);
 
 		/* Find the maximum number of cpus in any cluster */
 		max_cpu_per_cluster = MAX(max_cpu_per_cluster, cpus_per_cluster[cluster_count]);
@@ -170,5 +175,122 @@
 	return 0;
 }
 
+int fconf_populate_uart_config(uintptr_t config)
+{
+	int uart_node, node, err;
+	uintptr_t addr;
+	const char *path;
+	uint32_t phandle;
+	uint64_t translated_addr;
+
+	/* Necessary to work with libfdt APIs */
+	const void *hw_config_dtb = (const void *)config;
+
+	/*
+	 * uart child node is indirectly referenced through its path which is
+	 * specified in the `serial1` property of the "aliases" node.
+	 * Note that TF-A boot console is mapped to serial0 while runtime
+	 * console is mapped to serial1.
+	 */
+
+	path = fdt_get_alias(hw_config_dtb, "serial1");
+	if (path == NULL) {
+		ERROR("FCONF: Could not read serial1 property in aliases node\n");
+		return -1;
+	}
+
+	/* Find the offset of the uart serial node */
+	uart_node = fdt_path_offset(hw_config_dtb, path);
+	if (uart_node < 0) {
+		ERROR("FCONF: Failed to locate uart serial node using its path\n");
+		return -1;
+	}
+
+	/* uart serial node has its offset and size of address in reg property */
+	err = fdt_get_reg_props_by_index(hw_config_dtb, uart_node, 0, &addr,
+						NULL);
+	if (err < 0) {
+		ERROR("FCONF: Failed to read reg property of '%s' node\n",
+			"uart serial");
+		return err;
+	}
+	VERBOSE("FCONF: UART node address: %lx\n", addr);
+
+	/*
+	 * Perform address translation of local device address to CPU address
+	 * domain.
+	 */
+	translated_addr = fdtw_translate_address(hw_config_dtb,
+						 uart_node, (uint64_t)addr);
+	if (translated_addr == ILLEGAL_ADDR) {
+		ERROR("FCONF: failed to translate UART node base address");
+		return -1;
+	}
+
+	uart_serial_config.uart_base = translated_addr;
+
+	VERBOSE("FCONF: UART serial device base address: %llx\n",
+		uart_serial_config.uart_base);
+
+	/*
+	 * The phandle of the DT node which captures the clock info of uart
+	 * serial node is specified in the "clocks" property.
+	 */
+	err = fdt_read_uint32(hw_config_dtb, uart_node, "clocks", &phandle);
+	if (err < 0) {
+		ERROR("FCONF: Could not read clocks property in uart serial node\n");
+		return err;
+	}
+
+	node = fdt_node_offset_by_phandle(hw_config_dtb, phandle);
+	if (node < 0) {
+		ERROR("FCONF: Failed to locate clk node using its path\n");
+		return node;
+	}
+
+	/*
+	 * Retrieve clock frequency. We assume clock provider generates a fixed
+	 * clock.
+	 */
+	err = fdt_read_uint32(hw_config_dtb, node, "clock-frequency",
+				&uart_serial_config.uart_clk);
+	if (err < 0) {
+		ERROR("FCONF: Could not read clock-frequency property in clk node\n");
+		return err;
+	}
+
+	VERBOSE("FCONF: UART serial device clk frequency: %x\n",
+		uart_serial_config.uart_clk);
+
+	return 0;
+}
+
+int fconf_populate_cpu_timer(uintptr_t config)
+{
+	int err, node;
+
+	/* Necessary to work with libfdt APIs */
+	const void *hw_config_dtb = (const void *)config;
+
+	/* Find the node offset point to "arm,armv8-timer" compatible property,
+	 * a per-core architected timer attached to a GIC to deliver its per-processor
+	 * interrupts via PPIs */
+	node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,armv8-timer");
+	if (node < 0) {
+		ERROR("FCONF: Unrecognized hardware configuration dtb (%d)\n", node);
+		return node;
+	}
+
+	/* Locate the cell holding the clock-frequency, an optional field */
+	err = fdt_read_uint32(hw_config_dtb, node, "clock-frequency", &cpu_timer.clock_freq);
+	if (err < 0) {
+		WARN("FCONF failed to read clock-frequency property\n");
+	}
+
+	return 0;
+}
+
 FCONF_REGISTER_POPULATOR(HW_CONFIG, gicv3_config, fconf_populate_gicv3_config);
 FCONF_REGISTER_POPULATOR(HW_CONFIG, topology, fconf_populate_topology);
+FCONF_REGISTER_POPULATOR(HW_CONFIG, uart_config, fconf_populate_uart_config);
+FCONF_REGISTER_POPULATOR(HW_CONFIG, cpu_timer, fconf_populate_cpu_timer);
diff --git a/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c b/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c
new file mode 100644
index 0000000..e258015
--- /dev/null
+++ b/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+
+#include <libfdt.h>
+#include <fconf_nt_config_getter.h>
+
+#include <plat/common/platform.h>
+
+struct event_log_config_t event_log_config;
+
+int fconf_populate_event_log_config(uintptr_t config)
+{
+	int err;
+	int node;
+
+	/* Necessary to work with libfdt APIs */
+	const void *dtb = (const void *)config;
+
+	/*
+	 * Find the offset of the node containing "arm,tpm_event_log"
+	 * compatible property
+	 */
+	const char *compatible_str = "arm,tpm_event_log";
+
+	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;
+	}
+
+	/* Retrieve Event Log details from the DTB */
+#ifdef SPD_opteed
+	err = fdtw_read_cells(dtb, node, "tpm_event_log_sm_addr", 2,
+				&event_log_config.tpm_event_log_sm_addr);
+	if (err < 0) {
+		ERROR("FCONF: Read cell failed for 'tpm_event_log_sm_addr'\n");
+		return err;
+	}
+#endif
+	err = fdtw_read_cells(dtb, node,
+		"tpm_event_log_addr", 2, &event_log_config.tpm_event_log_addr);
+	if (err < 0) {
+		ERROR("FCONF: Read cell failed for 'tpm_event_log_addr'\n");
+		return err;
+	}
+
+	err = fdtw_read_cells(dtb, node,
+		"tpm_event_log_size", 1, &event_log_config.tpm_event_log_size);
+	if (err < 0) {
+		ERROR("FCONF: Read cell failed for 'tpm_event_log_size'\n");
+	}
+
+	return err;
+}
+
+FCONF_REGISTER_POPULATOR(NT_CONFIG, event_log_config,
+				fconf_populate_event_log_config);
diff --git a/plat/arm/board/fvp/fdts/event_log.dtsi b/plat/arm/board/fvp/fdts/event_log.dtsi
new file mode 100644
index 0000000..47af672
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/event_log.dtsi
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* TPM Event Log Config */
+event_log: tpm_event_log {
+	compatible = "arm,tpm_event_log";
+	tpm_event_log_addr = <0x0 0x0>;
+	tpm_event_log_size = <0x0>;
+};
diff --git a/plat/arm/board/fvp/fdts/fvp_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_fw_config.dts
index 7c11108..9fb566b 100644
--- a/plat/arm/board/fvp/fdts/fvp_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_fw_config.dts
@@ -4,7 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <export/common/tbbr/tbbr_img_def_exp.h>
+#include <common/tbbr/tbbr_img_def.h>
 
 /dts-v1/;
 
@@ -12,10 +12,9 @@
 	dtb-registry {
 		compatible = "fconf,dyn_cfg-dtb_registry";
 
-		/* tb_fw_config is temporarily contained on this dtb */
 		tb_fw-config {
-			load-address = <0x0 0x4001010>;
-			max-size = <0x200>;
+			load-address = <0x0 0x4001300>;
+			max-size = <0x1800>;
 			id = <TB_FW_CONFIG_ID>;
 		};
 
@@ -32,14 +31,14 @@
 		 * is loaded at base of DRAM.
 		 */
 		soc_fw-config {
-			load-address = <0x0 0x04001000>;
+			load-address = <0x0 0x04001300>;
 			max-size = <0x200>;
 			id = <SOC_FW_CONFIG_ID>;
 		};
 
 		tos_fw-config {
-			load-address = <0x0 0x04001200>;
-			max-size = <0x1000>;
+			load-address = <0x0 0x04001500>;
+			max-size = <0xB00>;
 			id = <TOS_FW_CONFIG_ID>;
 		};
 
@@ -49,82 +48,4 @@
 			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>;
-
-#if MEASURED_BOOT
-		/* BL2 image hash calculated by BL1 */
-		bl2_hash_data = [
-			00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-#if BL2_HASH_SIZE > 32
-			00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-#if BL2_HASH_SIZE > 48
-			00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-#endif /* > 48 */
-#endif /* > 32 */
-			00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00];
-#endif /* MEASURED_BOOT */
-	};
-
-	/*
-	 * Though TF-A is UUID RFC 4122 compliant meaning fields are stored in
-	 * network order (big endian), UUID's mentioned in this file are are
-	 * stored in machine order (little endian).
-	 * This will be fixed in future.
-	 */
-#if ARM_IO_IN_DTB
-	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>;
-		};
-	};
-#endif /* ARM_IO_IN_DTB */
-
-	secure-partitions {
-		compatible = "arm,sp";
-		cactus-primary {
-			uuid = <0x1e67b5b4 0xe14f904a 0x13fb1fb8 0xcbdae1da>;
-			load-address = <0x7000000>;
-		};
-
-		cactus-secondary {
-			uuid = <0x092358d1 0xb94723f0 0x64447c82 0xc88f57f5>;
-			load-address = <0x7100000>;
-		};
-	};
 };
diff --git a/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts
index 7ab980b..8f32b98 100644
--- a/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_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
  */
@@ -7,5 +7,13 @@
 /dts-v1/;
 
 / {
-
+#if MEASURED_BOOT
+#include "event_log.dtsi"
+#endif
 };
+
+#if MEASURED_BOOT && defined(SPD_opteed)
+&event_log {
+	tpm_event_log_sm_addr = <0x0 0x0>;
+};
+#endif
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
index ebfbe17..a1c9094 100644
--- a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
@@ -6,12 +6,14 @@
 /dts-v1/;
 
 / {
-	compatible = "arm,spci-core-manifest-1.0";
+	compatible = "arm,ffa-core-manifest-1.0";
+	#address-cells = <2>;
+	#size-cells = <1>;
 
 	attribute {
 		spmc_id = <0x8000>;
-		maj_ver = <0x0>;
-		min_ver = <0x9>;
+		maj_ver = <0x1>;
+		min_ver = <0x0>;
 		exec_state = <0x0>;
 		load_address = <0x0 0x6000000>;
 		entrypoint = <0x0 0x6000000>;
@@ -25,12 +27,12 @@
 	hypervisor {
 		compatible = "hafnium,hafnium";
 		vm1 {
-			is_spci_partition;
+			is_ffa_partition;
 			debug_name = "cactus-primary";
 			load_address = <0x7000000>;
 		};
 		vm2 {
-			is_spci_partition;
+			is_ffa_partition;
 			debug_name = "cactus-secondary";
 			load_address = <0x7100000>;
 			vcpu_count = <2>;
@@ -62,6 +64,6 @@
 
 	memory@60000000 {
 		device_type = "memory";
-		reg = <0x6000000 0x2000000>; /* Trusted DRAM */
+		reg = <0x0 0x6000000 0x2000000>; /* Trusted DRAM */
 	};
 };
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts
new file mode 100644
index 0000000..f5b31b4
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+/dts-v1/;
+
+#define	AFF	00
+
+#include "fvp-defs.dtsi"
+#undef POST
+#define	POST \
+	};
+
+/ {
+	compatible = "arm,ffa-core-manifest-1.0";
+	#address-cells = <2>;
+	#size-cells = <1>;
+
+	attribute {
+		spmc_id = <0x8000>;
+		maj_ver = <0x1>;
+		min_ver = <0x0>;
+		exec_state = <0x0>;
+		load_address = <0x0 0x6000000>;
+		entrypoint = <0x0 0x6000000>;
+		binary_size = <0x80000>;
+	};
+
+	chosen {
+		linux,initrd-start = <0>;
+		linux,initrd-end = <0>;
+	};
+
+	hypervisor {
+		compatible = "hafnium,hafnium";
+		vm1 {
+			is_ffa_partition;
+			debug_name = "op-tee";
+			load_address = <0x6280000>;
+			smc_whitelist = <0xbe000000>;
+		};
+	};
+
+	cpus {
+		#address-cells = <0x2>;
+		#size-cells = <0x0>;
+
+		CPU_0
+
+		/*
+		 * SPMC(Hafnium) requires secondary core nodes are declared
+		 * in descending order.
+		 */
+		CPU_7
+		CPU_6
+		CPU_5
+		CPU_4
+		CPU_3
+		CPU_2
+		CPU_1
+	};
+
+	memory@60000000 {
+		device_type = "memory";
+		reg = <0x0 0x6000000 0x2000000>; /* Trusted DRAM */
+	};
+};
diff --git a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
new file mode 100644
index 0000000..280a64a
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+
+#if MEASURED_BOOT
+		/* BL2 image hash calculated by BL1 */
+		bl2_hash_data = [
+			00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+#if BL2_HASH_SIZE > 32
+			00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+#if BL2_HASH_SIZE > 48
+			00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+#endif /* > 48 */
+#endif /* > 32 */
+			00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00];
+#endif /* MEASURED_BOOT */
+	};
+
+	/*
+	 * Though TF-A is UUID RFC 4122 compliant meaning fields are stored in
+	 * network order (big endian), UUID's mentioned in this file are are
+	 * stored in machine order (little endian).
+	 * This will be fixed in future.
+	 */
+#if ARM_IO_IN_DTB
+	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>;
+			sp_content_cert_uuid = <0x44fd6d77 0x3b4c9786 0x3ec1eb91 0x6f2a5a02>;
+		};
+	};
+#endif /* ARM_IO_IN_DTB */
+
+	secure-partitions {
+		compatible = "arm,sp";
+#ifdef OPTEE_SP_FW_CONFIG
+		op-tee {
+			uuid = <0xe0786148 0xe311f8e7 0x02005ebc 0x1bc5d5a5>;
+			load-address = <0x6280000>;
+		};
+#else
+		cactus-primary {
+			uuid = <0x1e67b5b4 0xe14f904a 0x13fb1fb8 0xcbdae1da>;
+			load-address = <0x7000000>;
+		};
+
+		cactus-secondary {
+			uuid = <0x092358d1 0xb94723f0 0x64447c82 0xc88f57f5>;
+			load-address = <0x7100000>;
+		};
+#endif
+	};
+
+#if COT_DESC_IN_DTB
+	#include "cot_descriptors.dtsi"
+#endif
+
+};
+
+#if COT_DESC_IN_DTB
+
+#include "../fvp_def.h"
+
+&trusted_nv_counter {
+	reg = <TFW_NVCTR_BASE>;
+};
+
+&non_trusted_nv_counter {
+	reg = <NTFW_CTR_BASE>;
+};
+#endif
diff --git a/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts
index 7ab980b..7bed6cb 100644
--- a/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_tsp_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
  */
@@ -7,5 +7,7 @@
 /dts-v1/;
 
 / {
-
+#if MEASURED_BOOT
+#include "event_log.dtsi"
+#endif
 };
diff --git a/plat/arm/board/fvp/fvp_bl1_setup.c b/plat/arm/board/fvp/fvp_bl1_setup.c
index d13cc81..0e77c4d 100644
--- a/plat/arm/board/fvp/fvp_bl1_setup.c
+++ b/plat/arm/board/fvp/fvp_bl1_setup.c
@@ -70,6 +70,14 @@
 
 #if MEASURED_BOOT
 /*
+ * Calculates and writes BL2 hash data to TB_FW_CONFIG DTB.
+ */
+void bl1_plat_set_bl2_hash(const image_desc_t *image_desc)
+{
+	arm_bl1_set_bl2_hash(image_desc);
+}
+
+/*
  * Implementation for bl1_plat_handle_post_image_load(). This function
  * populates the default arguments to BL2. The BL2 memory layout structure
  * is allocated and the calculated layout is populated in arg1 to BL2.
@@ -90,7 +98,7 @@
 	assert(image_desc != NULL);
 
 	/* Calculate BL2 hash and set it in TB_FW_CONFIG */
-	arm_bl1_set_bl2_hash(image_desc);
+	bl1_plat_set_bl2_hash(image_desc);
 
 	/* Get the entry point info */
 	ep_info = &image_desc->ep_info;
diff --git a/plat/arm/board/fvp/fvp_bl2_setup.c b/plat/arm/board/fvp/fvp_bl2_setup.c
index 43b1374..f2f2143 100644
--- a/plat/arm/board/fvp/fvp_bl2_setup.c
+++ b/plat/arm/board/fvp/fvp_bl2_setup.c
@@ -4,7 +4,17 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/desc_image_load.h>
 #include <drivers/arm/sp804_delay_timer.h>
+#if MEASURED_BOOT
+#include <drivers/measured_boot/measured_boot.h>
+#endif
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 #include <platform_def.h>
@@ -26,3 +36,82 @@
 	/* Initialize System level generic or SP804 timer */
 	fvp_timer_init();
 }
+
+/*******************************************************************************
+ * This function returns the list of executable images
+ ******************************************************************************/
+struct bl_params *plat_get_next_bl_params(void)
+{
+	struct bl_params *arm_bl_params;
+
+	arm_bl_params = arm_get_next_bl_params();
+
+#if __aarch64__ && !BL2_AT_EL3
+	const struct dyn_cfg_dtb_info_t *fw_config_info;
+	bl_mem_params_node_t *param_node;
+	uintptr_t fw_config_base = 0U;
+	entry_point_info_t *ep_info;
+
+	/* Get BL31 image node */
+	param_node = get_bl_mem_params_node(BL31_IMAGE_ID);
+	assert(param_node != NULL);
+
+	/* get fw_config load address */
+	fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID);
+	assert(fw_config_info != NULL);
+
+	fw_config_base = fw_config_info->config_addr;
+	assert(fw_config_base != 0U);
+
+	/*
+	 * Get the entry point info of BL31 image and override
+	 * arg1 of entry point info with fw_config base address
+	 */
+	ep_info = &param_node->ep_info;
+	ep_info->args.arg1 = (uint32_t)fw_config_base;
+#endif /* __aarch64__ && !BL2_AT_EL3 */
+
+	return arm_bl_params;
+}
+#if MEASURED_BOOT
+static int fvp_bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+	const bl_mem_params_node_t *bl_mem_params =
+				get_bl_mem_params_node(image_id);
+
+	assert(bl_mem_params != NULL);
+
+	image_info_t info = bl_mem_params->image_info;
+	int err;
+
+	if ((info.h.attr & IMAGE_ATTRIB_SKIP_LOADING) == 0U) {
+		/* Calculate image hash and record data in Event Log */
+		err = tpm_record_measurement(info.image_base,
+					     info.image_size, image_id);
+		if (err != 0) {
+			ERROR("%s%s image id %u (%i)\n",
+				"BL2: Failed to ", "record", image_id, err);
+			return err;
+		}
+	}
+
+	err = arm_bl2_handle_post_image_load(image_id);
+	if (err != 0) {
+		ERROR("%s%s image id %u (%i)\n",
+			"BL2: Failed to ", "handle", image_id, err);
+	}
+
+	return err;
+}
+
+int arm_bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+	int err = fvp_bl2_plat_handle_post_image_load(image_id);
+
+	if (err != 0) {
+		ERROR("%s() returns %i\n", __func__, err);
+	}
+
+	return err;
+}
+#endif	/* MEASURED_BOOT */
diff --git a/plat/arm/board/fvp/fvp_bl31_setup.c b/plat/arm/board/fvp/fvp_bl31_setup.c
index dc7bfa2..f9ee449 100644
--- a/plat/arm/board/fvp/fvp_bl31_setup.c
+++ b/plat/arm/board/fvp/fvp_bl31_setup.c
@@ -7,18 +7,32 @@
 #include <assert.h>
 #include <common/debug.h>
 #include <drivers/arm/smmu_v3.h>
+#include <fconf_hw_config_getter.h>
 #include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <lib/mmio.h>
 #include <plat/arm/common/arm_config.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 
 #include "fvp_private.h"
 
-uintptr_t hw_config_dtb;
-
 void __init bl31_early_platform_setup2(u_register_t arg0,
 		u_register_t arg1, u_register_t arg2, u_register_t arg3)
 {
+#if !RESET_TO_BL31 && !BL2_AT_EL3
+	const struct dyn_cfg_dtb_info_t *soc_fw_config_info;
+
+	INFO("BL31 FCONF: FW_CONFIG address = %lx\n", (uintptr_t)arg1);
+	/* Fill the properties struct with the info from the config dtb */
+	fconf_populate("FW_CONFIG", arg1);
+
+	soc_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, SOC_FW_CONFIG_ID);
+	if (soc_fw_config_info != NULL) {
+		arg1 = soc_fw_config_info->config_addr;
+	}
+#endif /* !RESET_TO_BL31 && !BL2_AT_EL3 */
+
 	arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
 
 	/* Initialize the platform config for future decision making */
@@ -45,8 +59,6 @@
 	/* On FVP RevC, initialize SMMUv3 */
 	if ((arm_config.flags & ARM_CONFIG_FVP_HAS_SMMUV3) != 0U)
 		smmuv3_init(PLAT_FVP_SMMUV3_BASE);
-
-	hw_config_dtb = arg2;
 }
 
 void __init bl31_plat_arch_setup(void)
@@ -59,9 +71,35 @@
 	 * control is passed to BL31.
 	 */
 #if !RESET_TO_BL31 && !BL2_AT_EL3
-	assert(hw_config_dtb != 0U);
+	/* HW_CONFIG was also loaded by BL2 */
+	const struct dyn_cfg_dtb_info_t *hw_config_info;
 
-	INFO("BL31 FCONF: HW_CONFIG address = %p\n", (void *)hw_config_dtb);
-	fconf_populate("HW_CONFIG", hw_config_dtb);
+	hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID);
+	assert(hw_config_info != NULL);
+
+	fconf_populate("HW_CONFIG", hw_config_info->config_addr);
 #endif
 }
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	unsigned int counter_base_frequency;
+
+#if !RESET_TO_BL31 && !BL2_AT_EL3
+	/* Get the frequency through FCONF API for HW_CONFIG */
+	counter_base_frequency = FCONF_GET_PROPERTY(hw_config, cpu_timer, clock_freq);
+	if (counter_base_frequency > 0U) {
+		return counter_base_frequency;
+	}
+#endif
+
+	/* Read the frequency from Frequency modes table */
+	counter_base_frequency = mmio_read_32(ARM_SYS_CNTCTL_BASE + CNTFID_OFF);
+
+	/* The first entry of the frequency modes table must not be 0 */
+	if (counter_base_frequency == 0U) {
+		panic();
+	}
+
+	return counter_base_frequency;
+}
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index c5fae56..cb717e0 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -18,7 +18,10 @@
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 #include <platform_def.h>
+
+#if SPM_MM
 #include <services/spm_mm_partition.h>
+#endif
 
 #include "fvp_private.h"
 
diff --git a/plat/arm/board/fvp/fvp_console.c b/plat/arm/board/fvp/fvp_console.c
new file mode 100644
index 0000000..928b47b
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_console.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/console.h>
+#include <fconf_hw_config_getter.h>
+#include <plat/arm/common/plat_arm.h>
+
+static console_t fvp_runtime_console;
+
+/* Initialize the runtime console */
+void arm_console_runtime_init(void)
+{
+	uintptr_t uart_base;
+	uint32_t uart_clk;
+
+	/*
+	 * fconf APIs are not supported for RESET_TO_SP_MIN, RESET_TO_BL31 and
+	 * BL2_AT_EL3 systems.
+	 */
+#if RESET_TO_SP_MIN || RESET_TO_BL31 || BL2_AT_EL3
+	uart_base = PLAT_ARM_RUN_UART_BASE;
+	uart_clk = PLAT_ARM_RUN_UART_CLK_IN_HZ;
+#else
+	uart_base = FCONF_GET_PROPERTY(hw_config, uart_serial_config,
+					uart_base);
+	uart_clk = FCONF_GET_PROPERTY(hw_config, uart_serial_config,
+					uart_clk);
+#endif
+
+	int rc = console_pl011_register(uart_base, uart_clk,
+					ARM_CONSOLE_BAUDRATE,
+					&fvp_runtime_console);
+
+	if (rc == 0) {
+		panic();
+	}
+
+	console_set_scope(&fvp_runtime_console, CONSOLE_FLAG_RUNTIME);
+}
+
+void arm_console_runtime_end(void)
+{
+	(void)console_flush();
+	(void)console_unregister(&fvp_runtime_console);
+}
diff --git a/plat/arm/board/fvp/fvp_gicv3.c b/plat/arm/board/fvp/fvp_gicv3.c
new file mode 100644
index 0000000..3e04d6b
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_gicv3.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <platform_def.h>
+
+#include <common/interrupt_props.h>
+#include <drivers/arm/gicv3.h>
+#include <fconf_hw_config_getter.h>
+#include <lib/utils.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/arm/common/fconf_sec_intr_config.h>
+#include <plat/common/platform.h>
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+static uintptr_t fvp_rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+/* Default GICR base address to be used for GICR probe. */
+static uint64_t fvp_gicr_base_addrs[2] = { 0U };
+
+/* List of zero terminated GICR frame addresses which CPUs will probe */
+static uint64_t *fvp_gicr_frames = fvp_gicr_base_addrs;
+
+#if  !(SEC_INT_DESC_IN_FCONF && ((!defined(__aarch64__) && defined(IMAGE_BL32)) || \
+	(defined(__aarch64__) && defined(IMAGE_BL31))))
+static const interrupt_prop_t fvp_interrupt_props[] = {
+	PLAT_ARM_G1S_IRQ_PROPS(INTR_GROUP1S),
+	PLAT_ARM_G0_IRQ_PROPS(INTR_GROUP0)
+};
+#endif
+
+/*
+ * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register
+ * to core position.
+ *
+ * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity
+ * values read from GICR_TYPER don't have an MT field. To reuse the same
+ * translation used for CPUs, we insert MT bit read from the PE's MPIDR into
+ * that read from GICR_TYPER.
+ *
+ * Assumptions:
+ *
+ *   - All CPUs implemented in the system have MPIDR_EL1.MT bit set;
+ *   - No CPUs implemented in the system use affinity level 3.
+ */
+static unsigned int fvp_gicv3_mpidr_hash(u_register_t mpidr)
+{
+	u_register_t temp_mpidr = mpidr;
+
+	temp_mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK);
+	return plat_arm_calc_core_pos(temp_mpidr);
+}
+
+
+static gicv3_driver_data_t fvp_gic_data = {
+	.rdistif_num = PLATFORM_CORE_COUNT,
+	.rdistif_base_addrs = fvp_rdistif_base_addrs,
+	.mpidr_to_core_pos = fvp_gicv3_mpidr_hash
+};
+
+void plat_arm_gic_driver_init(void)
+{
+	/*
+	 * Get GICD and GICR base addressed through FCONF APIs.
+	 * FCONF is not supported in BL32 for FVP.
+	 */
+#if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \
+	(defined(__aarch64__) && defined(IMAGE_BL31))
+	fvp_gic_data.gicd_base = (uintptr_t)FCONF_GET_PROPERTY(hw_config,
+							       gicv3_config,
+							       gicd_base);
+	fvp_gicr_base_addrs[0] = FCONF_GET_PROPERTY(hw_config, gicv3_config,
+						    gicr_base);
+#if SEC_INT_DESC_IN_FCONF
+	fvp_gic_data.interrupt_props = FCONF_GET_PROPERTY(hw_config,
+					sec_intr_prop, descriptor);
+	fvp_gic_data.interrupt_props_num = FCONF_GET_PROPERTY(hw_config,
+					sec_intr_prop, count);
+#else
+	fvp_gic_data.interrupt_props = fvp_interrupt_props;
+	fvp_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props);
+#endif
+#else
+	fvp_gic_data.gicd_base = PLAT_ARM_GICD_BASE;
+	fvp_gicr_base_addrs[0] = PLAT_ARM_GICR_BASE;
+	fvp_gic_data.interrupt_props = fvp_interrupt_props;
+	fvp_gic_data.interrupt_props_num = ARRAY_SIZE(fvp_interrupt_props);
+#endif
+
+	/*
+	 * The GICv3 driver is initialized in EL3 and does not need
+	 * to be initialized again in SEL1. This is because the S-EL1
+	 * can use GIC system registers to manage interrupts and does
+	 * not need GIC interface base addresses to be configured.
+	 */
+
+#if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \
+	(defined(__aarch64__) && defined(IMAGE_BL31))
+	gicv3_driver_init(&fvp_gic_data);
+	if (gicv3_rdistif_probe((uintptr_t)fvp_gicr_base_addrs[0]) == -1) {
+		ERROR("No GICR base frame found for Primary CPU\n");
+		panic();
+	}
+#endif
+}
+
+/******************************************************************************
+ * Function to iterate over all GICR frames and discover the corresponding
+ * per-cpu redistributor frame as well as initialize the corresponding
+ * interface in GICv3.
+ *****************************************************************************/
+void plat_arm_gic_pcpu_init(void)
+{
+	int result;
+	const uint64_t *plat_gicr_frames = fvp_gicr_frames;
+
+	do {
+		result = gicv3_rdistif_probe(*plat_gicr_frames);
+
+		/* If the probe is successful, no need to proceed further */
+		if (result == 0)
+			break;
+
+		plat_gicr_frames++;
+	} while (*plat_gicr_frames != 0U);
+
+	if (result == -1) {
+		ERROR("No GICR base frame found for CPU 0x%lx\n", read_mpidr());
+		panic();
+	}
+	gicv3_rdistif_init(plat_my_core_pos());
+}
diff --git a/plat/arm/board/fvp/fvp_measured_boot.c b/plat/arm/board/fvp/fvp_measured_boot.c
new file mode 100644
index 0000000..b145aae
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_measured_boot.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/measured_boot/event_log.h>
+#include <plat/arm/common/plat_arm.h>
+
+/* FVP table with platform specific image IDs, names and PCRs */
+static const image_data_t fvp_images_data[] = {
+	{ BL2_IMAGE_ID, BL2_STRING, PCR_0 },		/* Reserved for BL2 */
+	{ BL31_IMAGE_ID, BL31_STRING, PCR_0 },
+	{ BL32_IMAGE_ID, BL32_STRING, PCR_0 },
+	{ BL32_EXTRA1_IMAGE_ID, BL32_EXTRA1_IMAGE_STRING, PCR_0 },
+	{ BL32_EXTRA2_IMAGE_ID, BL32_EXTRA2_IMAGE_STRING, PCR_0 },
+	{ BL33_IMAGE_ID, BL33_STRING, PCR_0 },
+	{ GPT_IMAGE_ID, GPT_IMAGE_STRING, PCR_0 },
+	{ HW_CONFIG_ID, HW_CONFIG_STRING, PCR_0 },
+	{ NT_FW_CONFIG_ID, NT_FW_CONFIG_STRING, PCR_0 },
+	{ SCP_BL2_IMAGE_ID, SCP_BL2_IMAGE_STRING, PCR_0 },
+	{ SOC_FW_CONFIG_ID, SOC_FW_CONFIG_STRING, PCR_0 },
+	{ STM32_IMAGE_ID, STM32_IMAGE_STRING, PCR_0 },
+	{ TOS_FW_CONFIG_ID, TOS_FW_CONFIG_STRING, PCR_0 },
+	{ INVALID_ID, NULL, (unsigned int)(-1) }	/* Terminator */
+};
+
+static const measured_boot_data_t fvp_measured_boot_data = {
+	fvp_images_data,
+	arm_set_nt_fw_info,
+	arm_set_tos_fw_info
+};
+
+/*
+ * Function retuns pointer to FVP plat_measured_boot_data_t structure
+ */
+const measured_boot_data_t *plat_get_measured_boot_data(void)
+{
+	return &fvp_measured_boot_data;
+}
diff --git a/plat/arm/board/fvp/include/fconf_hw_config_getter.h b/plat/arm/board/fvp/include/fconf_hw_config_getter.h
index a9e569e..ca85f7a 100644
--- a/plat/arm/board/fvp/include/fconf_hw_config_getter.h
+++ b/plat/arm/board/fvp/include/fconf_hw_config_getter.h
@@ -11,12 +11,13 @@
 
 /* Hardware Config related getter */
 #define hw_config__gicv3_config_getter(prop) gicv3_config.prop
-
 #define hw_config__topology_getter(prop) soc_topology.prop
+#define hw_config__uart_serial_config_getter(prop) uart_serial_config.prop
+#define hw_config__cpu_timer_getter(prop) cpu_timer.prop
 
 struct gicv3_config_t {
-	uintptr_t gicd_base;
-	uintptr_t gicr_base;
+	uint64_t gicd_base;
+	uint64_t gicr_base;
 };
 
 struct hw_topology_t {
@@ -26,10 +27,22 @@
 	uint32_t plat_max_pwr_level;
 };
 
+struct uart_serial_config_t {
+	uint64_t uart_base;
+	uint32_t uart_clk;
+};
+
+struct cpu_timer_t {
+	uint32_t clock_freq;
+};
+
 int fconf_populate_gicv3_config(uintptr_t config);
 int fconf_populate_topology(uintptr_t config);
+int fconf_populate_uart_config(uintptr_t config);
+int fconf_populate_cpu_timer(uintptr_t config);
 
 extern struct gicv3_config_t gicv3_config;
 extern struct hw_topology_t soc_topology;
-
+extern struct uart_serial_config_t uart_serial_config;
+extern struct cpu_timer_t cpu_timer;
 #endif /* FCONF_HW_CONFIG_GETTER_H */
diff --git a/plat/arm/board/fvp/include/fconf_nt_config_getter.h b/plat/arm/board/fvp/include/fconf_nt_config_getter.h
new file mode 100644
index 0000000..0824c35
--- /dev/null
+++ b/plat/arm/board/fvp/include/fconf_nt_config_getter.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FCONF_NT_CONFIG_GETTER_H
+#define FCONF_NT_CONFIG_GETTER_H
+
+#include <lib/fconf/fconf.h>
+
+/* NT Firmware Config related getter */
+#define nt_config__event_log_config_getter(prop) event_log.prop
+
+struct event_log_config_t {
+#ifdef SPD_opteed
+	void *tpm_event_log_sm_addr;
+#endif
+	void *tpm_event_log_addr;
+	size_t tpm_event_log_size;
+};
+
+int fconf_populate_event_log_config(uintptr_t config);
+
+extern struct event_log_config_t event_log_config;
+
+#endif /* FCONF_NT_CONFIG_GETTER_H */
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 62ede9a..a986017 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -120,7 +120,7 @@
 #if TRUSTED_BOARD_BOOT
 # define PLAT_ARM_MAX_BL2_SIZE	(UL(0x1D000) - FVP_BL2_ROMLIB_OPTIMIZATION)
 #else
-# define PLAT_ARM_MAX_BL2_SIZE	(UL(0x12000) - FVP_BL2_ROMLIB_OPTIMIZATION)
+# define PLAT_ARM_MAX_BL2_SIZE	(UL(0x13000) - FVP_BL2_ROMLIB_OPTIMIZATION)
 #endif
 
 #if RESET_TO_BL31
@@ -133,7 +133,7 @@
  * calculated using the current BL31 PROGBITS debug size plus the sizes of
  * BL2 and BL1-RW
  */
-#define PLAT_ARM_MAX_BL31_SIZE		UL(0x3E000)
+#define PLAT_ARM_MAX_BL31_SIZE		UL(0x3D000)
 #endif /* RESET_TO_BL31 */
 
 #ifndef __aarch64__
@@ -243,8 +243,8 @@
 
 /*
  * GIC related constants to cater for both GICv2 and GICv3 instances of an
- * FVP. They could be overriden at runtime in case the FVP implements the legacy
- * VE memory map.
+ * FVP. They could be overridden at runtime in case the FVP implements the
+ * legacy VE memory map.
  */
 #define PLAT_ARM_GICD_BASE		BASE_GICD_BASE
 #define PLAT_ARM_GICR_BASE		BASE_GICR_BASE
diff --git a/plat/arm/board/fvp/jmptbl.i b/plat/arm/board/fvp/jmptbl.i
index 213a974..b72bdab 100644
--- a/plat/arm/board/fvp/jmptbl.i
+++ b/plat/arm/board/fvp/jmptbl.i
@@ -16,6 +16,7 @@
 
 rom     rom_lib_init
 fdt     fdt_getprop
+fdt     fdt_get_property
 fdt     fdt_getprop_namelen
 fdt     fdt_setprop_inplace
 fdt     fdt_check_header
@@ -31,6 +32,9 @@
 fdt     fdt_parent_offset
 fdt     fdt_stringlist_search
 fdt     fdt_get_alias_namelen
+fdt     fdt_get_name
+fdt     fdt_get_alias
+fdt     fdt_node_offset_by_phandle
 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 04cebca..f75f556 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -49,13 +49,10 @@
 $(eval $(call add_define,FVP_INTERCONNECT_DRIVER))
 
 # Choose the GIC sources depending upon the how the FVP will be invoked
-ifeq (${FVP_USE_GIC_DRIVER},$(filter ${FVP_USE_GIC_DRIVER},FVP_GICV3 FVP_GIC600))
+ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV3)
 
-	# GIC500 is the default option in case GICV3_IMPL is not set
-	ifeq (${FVP_USE_GIC_DRIVER}, FVP_GIC600)
-		GICV3_IMPL	:=	GIC600
-	endif
-
+# The GIC model (GIC-600 or GIC-500) will be detected at runtime
+GICV3_SUPPORT_GIC600		:=	1
 GICV3_OVERRIDE_DISTIF_PWR_OPS	:=	1
 
 # Include GICv3 driver files
@@ -65,19 +62,20 @@
 				plat/common/plat_gicv3.c		\
 				plat/arm/common/arm_gicv3.c
 
+	ifeq ($(filter 1,${BL2_AT_EL3} ${RESET_TO_BL31} ${RESET_TO_SP_MIN}),)
+		FVP_GIC_SOURCES += plat/arm/board/fvp/fvp_gicv3.c
+	endif
+
 else ifeq (${FVP_USE_GIC_DRIVER}, FVP_GICV2)
 
 # No GICv4 extension
 GIC_ENABLE_V4_EXTN	:=	0
 $(eval $(call add_define,GIC_ENABLE_V4_EXTN))
 
-# No support for extended PPI and SPI range
-GIC_EXT_INTID		:=	0
-$(eval $(call add_define,GIC_EXT_INTID))
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
 
-FVP_GIC_SOURCES		:=	drivers/arm/gic/common/gic_common.c	\
-				drivers/arm/gic/v2/gicv2_main.c		\
-				drivers/arm/gic/v2/gicv2_helpers.c	\
+FVP_GIC_SOURCES		:=	${GICV2_SOURCES}			\
 				plat/common/plat_gicv2.c		\
 				plat/arm/common/arm_gicv2.c
 
@@ -125,10 +123,10 @@
 		FVP_CPU_LIBS	+=	lib/cpus/aarch64/cortex_a76.S		\
 					lib/cpus/aarch64/cortex_a76ae.S		\
 					lib/cpus/aarch64/cortex_a77.S		\
+					lib/cpus/aarch64/cortex_a78.S		\
 					lib/cpus/aarch64/neoverse_n1.S		\
 					lib/cpus/aarch64/neoverse_e1.S		\
 					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	\
@@ -201,6 +199,7 @@
 				drivers/cfi/v2m/v2m_flash.c			\
 				lib/utils/mem_region.c				\
 				plat/arm/board/fvp/fvp_bl31_setup.c		\
+				plat/arm/board/fvp/fvp_console.c		\
 				plat/arm/board/fvp/fvp_pm.c			\
 				plat/arm/board/fvp/fvp_topology.c		\
 				plat/arm/board/fvp/aarch64/fvp_helpers.S	\
@@ -215,7 +214,13 @@
 ifeq ($(filter 1,${BL2_AT_EL3} ${RESET_TO_BL31}),)
 BL31_SOURCES		+=	common/fdt_wrappers.c				\
 				lib/fconf/fconf.c				\
+				lib/fconf/fconf_dyn_cfg_getter.c		\
 				plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
+
+ifeq (${SEC_INT_DESC_IN_FCONF},1)
+BL31_SOURCES		+=	plat/arm/common/fconf/fconf_sec_intr_config.c
+endif
+
 endif
 
 ifeq (${FVP_USE_SP804_TIMER},1)
@@ -229,11 +234,13 @@
 FVP_HW_CONFIG_DTS	:=	fdts/${FVP_DT_PREFIX}.dts
 FDT_SOURCES		+=	$(addprefix plat/arm/board/fvp/fdts/,	\
 					${PLAT}_fw_config.dts		\
+					${PLAT}_tb_fw_config.dts	\
 					${PLAT}_soc_fw_config.dts	\
 					${PLAT}_nt_fw_config.dts	\
 				)
 
-FVP_TB_FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+FVP_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+FVP_TB_FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_tb_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
 
@@ -246,13 +253,20 @@
 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
+
+ifeq ($(ARM_SPMC_MANIFEST_DTS),)
+ARM_SPMC_MANIFEST_DTS	:=	plat/arm/board/fvp/fdts/${PLAT}_spmc_manifest.dts
+endif
+
+FDT_SOURCES		+=	${ARM_SPMC_MANIFEST_DTS}
+FVP_TOS_FW_CONFIG	:=	${BUILD_PLAT}/fdts/$(notdir $(basename ${ARM_SPMC_MANIFEST_DTS})).dtb
 
 # Add the TOS_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${FVP_TOS_FW_CONFIG},--tos-fw-config))
 endif
 
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FVP_FW_CONFIG},--fw-config))
 # 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
@@ -345,6 +359,11 @@
 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
+
+ifeq (${MEASURED_BOOT},1)
+BL2_SOURCES		+=	plat/arm/board/fvp/fvp_measured_boot.c
+endif
+
 # FVP being a development platform, enable capability to disable Authentication
 # dynamically if TRUSTED_BOARD_BOOT is set.
 DYN_DISABLE_AUTH	:=	1
diff --git a/plat/arm/board/fvp/sp_min/sp_min-fvp.mk b/plat/arm/board/fvp/sp_min/sp_min-fvp.mk
index 36bf441..64cb7ad 100644
--- a/plat/arm/board/fvp/sp_min/sp_min-fvp.mk
+++ b/plat/arm/board/fvp/sp_min/sp_min-fvp.mk
@@ -10,6 +10,7 @@
 				lib/utils/mem_region.c				\
 				plat/arm/board/fvp/aarch32/fvp_helpers.S	\
 				plat/arm/board/fvp/fvp_pm.c			\
+				plat/arm/board/fvp/fvp_console.c		\
 				plat/arm/board/fvp/fvp_topology.c		\
 				plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c	\
 				plat/arm/common/arm_nor_psci_mem_protect.c	\
@@ -24,6 +25,11 @@
 BL32_SOURCES		+=	common/fdt_wrappers.c				\
 				lib/fconf/fconf.c				\
 				plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
+
+ifeq (${SEC_INT_DESC_IN_FCONF},1)
+BL32_SOURCES		+=	plat/arm/common/fconf/fconf_sec_intr_config.c
+endif
+
 endif
 
 include plat/arm/common/sp_min/arm_sp_min.mk
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
index 1727e2e..6e5691b 100644
--- a/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts
+++ b/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts
@@ -4,7 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <export/common/tbbr/tbbr_img_def_exp.h>
+#include <common/tbbr/tbbr_img_def.h>
 
 /dts-v1/;
 
@@ -12,9 +12,8 @@
 	dtb-registry {
 		compatible = "fconf,dyn_cfg-dtb_registry";
 
-		/* tb_fw_config is temporarily contained on this dtb */
 		tb_fw-config {
-			load-address = <0x0 0x80001010>;
+			load-address = <0x0 0x80001300>;
 			max-size = <0x200>;
 			id = <TB_FW_CONFIG_ID>;
 		};
@@ -25,11 +24,4 @@
 			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
new file mode 100644
index 0000000..c66186f
--- /dev/null
+++ b/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+	};
+};
diff --git a/plat/arm/board/fvp_ve/include/platform_def.h b/plat/arm/board/fvp_ve/include/platform_def.h
index 70a12ea..3f2fcee 100644
--- a/plat/arm/board/fvp_ve/include/platform_def.h
+++ b/plat/arm/board/fvp_ve/include/platform_def.h
@@ -121,10 +121,19 @@
 #endif
 
 /*
+ * Map the region for device tree configuration with read and write permissions
+ */
+#define ARM_MAP_BL_CONFIG_REGION	MAP_REGION_FLAT(ARM_BL_RAM_BASE,	\
+						(ARM_FW_CONFIGS_LIMIT		\
+							- ARM_BL_RAM_BASE),	\
+						MT_MEMORY | MT_RW | MT_SECURE)
+
+
+/*
  * The max number of regions like RO(code), coherent and data required by
  * different BL stages which need to be mapped in the MMU.
  */
-#define ARM_BL_REGIONS			5
+#define ARM_BL_REGIONS			6
 
 #define MAX_MMAP_REGIONS		(PLAT_ARM_MMAP_ENTRIES +	\
 					 ARM_BL_REGIONS)
@@ -169,11 +178,18 @@
 #define CACHE_WRITEBACK_GRANULE		(U(1) << ARM_CACHE_WRITEBACK_SHIFT)
 
 /*
- * To enable TB_FW_CONFIG to be loaded by BL1, define the corresponding base
+ * To enable FW_CONFIG to be loaded by BL1, define the corresponding base
  * and limit. Leave enough space of BL2 meminfo.
  */
-#define ARM_TB_FW_CONFIG_BASE		(ARM_BL_RAM_BASE + sizeof(meminfo_t))
-#define ARM_TB_FW_CONFIG_LIMIT		(ARM_BL_RAM_BASE + PAGE_SIZE)
+#define ARM_FW_CONFIG_BASE		(ARM_BL_RAM_BASE + sizeof(meminfo_t))
+#define ARM_FW_CONFIG_LIMIT		((ARM_BL_RAM_BASE + PAGE_SIZE) \
+					+ (PAGE_SIZE / 2U))
+
+/*
+ * Define limit of firmware configuration memory:
+ * ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory
+ */
+#define ARM_FW_CONFIGS_LIMIT		(ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
 
 /*******************************************************************************
  * BL1 specific defines.
@@ -204,7 +220,9 @@
 
 
 /* Put BL32 below BL2 in NS DRAM.*/
-#define ARM_BL2_MEM_DESC_BASE		ARM_TB_FW_CONFIG_LIMIT
+#define ARM_BL2_MEM_DESC_BASE		ARM_FW_CONFIG_LIMIT
+#define ARM_BL2_MEM_DESC_LIMIT		(ARM_BL2_MEM_DESC_BASE \
+					+ (PAGE_SIZE / 2U))
 
 #define BL32_BASE			((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)\
 						- PLAT_ARM_MAX_BL32_SIZE)
diff --git a/plat/arm/board/fvp_ve/platform.mk b/plat/arm/board/fvp_ve/platform.mk
index 9ada86b..f8e38ff 100644
--- a/plat/arm/board/fvp_ve/platform.mk
+++ b/plat/arm/board/fvp_ve/platform.mk
@@ -11,10 +11,11 @@
 BL2_SOURCES		+=	drivers/arm/sp804/sp804_delay_timer.c
 endif
 
-FVP_VE_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		\
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+FVP_VE_GIC_SOURCES	:=	${GICV2_SOURCES}		\
+				plat/common/plat_gicv2.c	\
 				plat/arm/common/arm_gicv2.c
 
 FVP_VE_SECURITY_SOURCES	:=	plat/arm/board/fvp_ve/fvp_ve_security.c
@@ -74,10 +75,14 @@
 # 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_fw_config.dts
+FDT_SOURCES		+=	plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts	\
+				plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts
 
-FVP_TB_FW_CONFIG	:=	${BUILD_PLAT}/fdts/fvp_ve_fw_config.dtb
+FVP_FW_CONFIG		:=	${BUILD_PLAT}/fdts/fvp_ve_fw_config.dtb
+FVP_TB_FW_CONFIG	:=	${BUILD_PLAT}/fdts/fvp_ve_tb_fw_config.dtb
 
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FVP_FW_CONFIG},--fw-config))
 # 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))
 
diff --git a/plat/arm/board/juno/fdts/juno_fw_config.dts b/plat/arm/board/juno/fdts/juno_fw_config.dts
index 4e460aa..c0538f8 100644
--- a/plat/arm/board/juno/fdts/juno_fw_config.dts
+++ b/plat/arm/board/juno/fdts/juno_fw_config.dts
@@ -4,7 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <export/common/tbbr/tbbr_img_def_exp.h>
+#include <common/tbbr/tbbr_img_def.h>
 
 /dts-v1/;
 
@@ -12,29 +12,10 @@
 	dtb-registry {
 		compatible = "fconf,dyn_cfg-dtb_registry";
 
-		/* tb_fw_config is temporarily contained on this dtb */
 		tb_fw-config {
-			load-address = <0x0 0x4001010>;
+			load-address = <0x0 0x4001300>;
 			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
new file mode 100644
index 0000000..80cfa3e
--- /dev/null
+++ b/plat/arm/board/juno/fdts/juno_tb_fw_config.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+};
diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h
index 67802d4..91c3ae7 100644
--- a/plat/arm/board/juno/include/platform_def.h
+++ b/plat/arm/board/juno/include/platform_def.h
@@ -139,7 +139,7 @@
 # define PLAT_ARM_MAX_BL2_SIZE	(UL(0x1D000) - JUNO_BL2_ROMLIB_OPTIMIZATION)
 #endif
 #else
-# define PLAT_ARM_MAX_BL2_SIZE	(UL(0x11000) - JUNO_BL2_ROMLIB_OPTIMIZATION)
+# define PLAT_ARM_MAX_BL2_SIZE	(UL(0x13000) - JUNO_BL2_ROMLIB_OPTIMIZATION)
 #endif
 
 /*
@@ -148,7 +148,7 @@
  * BL2 and BL1-RW.  SCP_BL2 image is loaded into the space BL31 -> BL2_BASE.
  * Hence the BL31 PROGBITS size should be >= PLAT_CSS_MAX_SCP_BL2_SIZE.
  */
-#define PLAT_ARM_MAX_BL31_SIZE		UL(0x3E000)
+#define PLAT_ARM_MAX_BL31_SIZE		UL(0x3D000)
 
 #if JUNO_AARCH32_EL3_RUNTIME
 /*
@@ -157,7 +157,7 @@
  * BL2 and BL1-RW.  SCP_BL2 image is loaded into the space BL32 -> BL2_BASE.
  * Hence the BL32 PROGBITS size should be >= PLAT_CSS_MAX_SCP_BL2_SIZE.
  */
-#define PLAT_ARM_MAX_BL32_SIZE		UL(0x3E000)
+#define PLAT_ARM_MAX_BL32_SIZE		UL(0x3D000)
 #endif
 
 /*
@@ -254,7 +254,7 @@
  * BL31 is loaded over the top.
  */
 #define PLAT_CSS_MAX_SCP_BL2_SIZE \
-	((SCP_BL2_LIMIT - ARM_TB_FW_CONFIG_LIMIT) & ~PAGE_SIZE_MASK)
+	((SCP_BL2_LIMIT - ARM_FW_CONFIG_LIMIT) & ~PAGE_SIZE_MASK)
 
 #define PLAT_CSS_MAX_SCP_BL2U_SIZE	PLAT_CSS_MAX_SCP_BL2_SIZE
 
diff --git a/plat/arm/board/juno/jmptbl.i b/plat/arm/board/juno/jmptbl.i
index 09017ac..393a648 100644
--- a/plat/arm/board/juno/jmptbl.i
+++ b/plat/arm/board/juno/jmptbl.i
@@ -16,6 +16,7 @@
 
 rom     rom_lib_init
 fdt     fdt_getprop
+fdt     fdt_get_property
 fdt     fdt_getprop_namelen
 fdt     fdt_setprop_inplace
 fdt     fdt_check_header
@@ -28,6 +29,11 @@
 fdt     fdt_get_alias_namelen
 fdt     fdt_path_offset
 fdt     fdt_path_offset_namelen
+fdt     fdt_address_cells
+fdt     fdt_size_cells
+fdt     fdt_get_name
+fdt     fdt_get_alias
+fdt     fdt_node_offset_by_phandle
 mbedtls mbedtls_asn1_get_alg
 mbedtls mbedtls_asn1_get_alg_null
 mbedtls mbedtls_asn1_get_bitstring_null
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index a871e81..196d3c0 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -4,9 +4,10 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
-JUNO_GIC_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
-				drivers/arm/gic/v2/gicv2_main.c		\
-				drivers/arm/gic/v2/gicv2_helpers.c	\
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+JUNO_GIC_SOURCES	:=	${GICV2_SOURCES}			\
 				plat/common/plat_gicv2.c		\
 				plat/arm/common/arm_gicv2.c
 
@@ -164,9 +165,14 @@
 endif
 
 # Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES		+=	plat/arm/board/juno/fdts/${PLAT}_fw_config.dts
-TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+FDT_SOURCES		+=	plat/arm/board/juno/fdts/${PLAT}_fw_config.dts	\
+				plat/arm/board/juno/fdts/${PLAT}_tb_fw_config.dts
 
+FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config))
 # 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/platform.mk b/plat/arm/board/n1sdp/platform.mk
index 44f7b8a..4b621e3 100644
--- a/plat/arm/board/n1sdp/platform.mk
+++ b/plat/arm/board/n1sdp/platform.mk
@@ -15,7 +15,7 @@
 N1SDP_CPU_SOURCES	:=	lib/cpus/aarch64/neoverse_n1.S
 
 # GIC-600 configuration
-GICV3_IMPL			:=	GIC600
+GICV3_SUPPORT_GIC600		:=	1
 GICV3_IMPL_GIC600_MULTICHIP	:=	1
 
 # Include GICv3 driver files
@@ -38,6 +38,8 @@
 				${N1SDP_BASE}/n1sdp_security.c		\
 				drivers/arm/css/sds/sds.c
 
+FDT_SOURCES		+=	fdts/${PLAT}-single-chip.dts	\
+				fdts/${PLAT}-multi-chip.dts
 
 # TF-A not required to load the SCP Images
 override CSS_LOAD_SCP_IMAGES	  	:=	0
diff --git a/plat/arm/board/rddaniel/fdts/rddaniel_fw_config.dts b/plat/arm/board/rddaniel/fdts/rddaniel_fw_config.dts
index bb544a4..9c9cefe 100644
--- a/plat/arm/board/rddaniel/fdts/rddaniel_fw_config.dts
+++ b/plat/arm/board/rddaniel/fdts/rddaniel_fw_config.dts
@@ -4,7 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <export/common/tbbr/tbbr_img_def_exp.h>
+#include <common/tbbr/tbbr_img_def.h>
 
 /dts-v1/;
 
@@ -12,9 +12,8 @@
 	dtb-registry {
 		compatible = "fconf,dyn_cfg-dtb_registry";
 
-		/* tb_fw_config is temporarily contained on this dtb */
 		tb_fw-config {
-			load-address = <0x0 0x4001010>;
+			load-address = <0x0 0x4001300>;
 			max-size = <0x200>;
 			id = <TB_FW_CONFIG_ID>;
 		};
@@ -25,23 +24,4 @@
 			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_tb_fw_config.dts b/plat/arm/board/rddaniel/fdts/rddaniel_tb_fw_config.dts
new file mode 100644
index 0000000..49eda27
--- /dev/null
+++ b/plat/arm/board/rddaniel/fdts/rddaniel_tb_fw_config.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+};
diff --git a/plat/arm/board/rddaniel/platform.mk b/plat/arm/board/rddaniel/platform.mk
index 94a3928..81632a5 100644
--- a/plat/arm/board/rddaniel/platform.mk
+++ b/plat/arm/board/rddaniel/platform.mk
@@ -32,10 +32,19 @@
 				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
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES		+=	${RDDANIEL_BASE}/rddaniel_trusted_boot.c
+BL2_SOURCES		+=	${RDDANIEL_BASE}/rddaniel_trusted_boot.c
+endif
 
+# Add the FDT_SOURCES and options for Dynamic Config
+FDT_SOURCES		+=	${RDDANIEL_BASE}/fdts/${PLAT}_fw_config.dts	\
+				${RDDANIEL_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config))
 # 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/rddaniel/rddaniel_trusted_boot.c b/plat/arm/board/rddaniel/rddaniel_trusted_boot.c
new file mode 100644
index 0000000..4592b8f
--- /dev/null
+++ b/plat/arm/board/rddaniel/rddaniel_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(cookie, key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/rddanielxlr/fdts/rddanielxlr_fw_config.dts b/plat/arm/board/rddanielxlr/fdts/rddanielxlr_fw_config.dts
index bb544a4..9c9cefe 100644
--- a/plat/arm/board/rddanielxlr/fdts/rddanielxlr_fw_config.dts
+++ b/plat/arm/board/rddanielxlr/fdts/rddanielxlr_fw_config.dts
@@ -4,7 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <export/common/tbbr/tbbr_img_def_exp.h>
+#include <common/tbbr/tbbr_img_def.h>
 
 /dts-v1/;
 
@@ -12,9 +12,8 @@
 	dtb-registry {
 		compatible = "fconf,dyn_cfg-dtb_registry";
 
-		/* tb_fw_config is temporarily contained on this dtb */
 		tb_fw-config {
-			load-address = <0x0 0x4001010>;
+			load-address = <0x0 0x4001300>;
 			max-size = <0x200>;
 			id = <TB_FW_CONFIG_ID>;
 		};
@@ -25,23 +24,4 @@
 			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/rddanielxlr/fdts/rddanielxlr_tb_fw_config.dts b/plat/arm/board/rddanielxlr/fdts/rddanielxlr_tb_fw_config.dts
new file mode 100644
index 0000000..49eda27
--- /dev/null
+++ b/plat/arm/board/rddanielxlr/fdts/rddanielxlr_tb_fw_config.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+};
diff --git a/plat/arm/board/rddanielxlr/platform.mk b/plat/arm/board/rddanielxlr/platform.mk
index 36a0099..93967ad 100644
--- a/plat/arm/board/rddanielxlr/platform.mk
+++ b/plat/arm/board/rddanielxlr/platform.mk
@@ -32,13 +32,22 @@
 				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
+ifeq (${TRUSTED_BOARD_BOOT}, 1)
+BL1_SOURCES		+=	${RDDANIELXLR_BASE}/rddanielxlr_trusted_boot.c
+BL2_SOURCES		+=	${RDDANIELXLR_BASE}/rddanielxlr_trusted_boot.c
+endif
+
 # Enable dynamic addition of MMAP regions in BL31
 BL31_CFLAGS		+=	-DPLAT_XLAT_TABLES_DYNAMIC
 
 # Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES		+=	${RDDANIELXLR_BASE}/fdts/${PLAT}_fw_config.dts
-TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+FDT_SOURCES		+=	${RDDANIELXLR_BASE}/fdts/${PLAT}_fw_config.dts	\
+				${RDDANIELXLR_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
 
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config))
 # 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/rddanielxlr/rddanielxlr_trusted_boot.c b/plat/arm/board/rddanielxlr/rddanielxlr_trusted_boot.c
new file mode 100644
index 0000000..4592b8f
--- /dev/null
+++ b/plat/arm/board/rddanielxlr/rddanielxlr_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(cookie, key_ptr, key_len, flags);
+}
diff --git a/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts b/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts
index a5b4a58..69fb0d4 100644
--- a/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts
+++ b/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts
@@ -4,7 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <export/common/tbbr/tbbr_img_def_exp.h>
+#include <common/tbbr/tbbr_img_def.h>
 
 /dts-v1/;
 
@@ -12,9 +12,8 @@
 	dtb-registry {
 		compatible = "fconf,dyn_cfg-dtb_registry";
 
-		/* tb_fw_config is temporarily contained on this dtb */
 		tb_fw-config {
-			load-address = <0x0 0x4001010>;
+			load-address = <0x0 0x4001300>;
 			max-size = <0x200>;
 			id = <TB_FW_CONFIG_ID>;
 		};
@@ -25,23 +24,4 @@
 			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_tb_fw_config.dts b/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts
new file mode 100644
index 0000000..dba91e5
--- /dev/null
+++ b/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+};
diff --git a/plat/arm/board/rde1edge/platform.mk b/plat/arm/board/rde1edge/platform.mk
index 1a4dd17..e09afca 100644
--- a/plat/arm/board/rde1edge/platform.mk
+++ b/plat/arm/board/rde1edge/platform.mk
@@ -35,9 +35,13 @@
 endif
 
 # Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES		+=	${RDE1EDGE_BASE}/fdts/${PLAT}_fw_config.dts
-TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+FDT_SOURCES		+=	${RDE1EDGE_BASE}/fdts/${PLAT}_fw_config.dts	\
+				${RDE1EDGE_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
 
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config))
 # 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/rdn1edge/fdts/rdn1edge_fw_config.dts b/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts
index 1f460f1..d3b7fba 100644
--- a/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts
+++ b/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts
@@ -4,16 +4,15 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <export/common/tbbr/tbbr_img_def_exp.h>
+#include <common/tbbr/tbbr_img_def.h>
 
 /dts-v1/;
 / {
 	dtb-registry {
 		compatible = "fconf,dyn_cfg-dtb_registry";
 
-		/* tb_fw_config is temporarily contained on this dtb */
 		tb_fw-config {
-			load-address = <0x0 0x80001010>;
+			load-address = <0x0 0x4001300>;
 			max-size = <0x200>;
 			id = <TB_FW_CONFIG_ID>;
 		};
@@ -24,24 +23,5 @@
 			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_tb_fw_config.dts b/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts
new file mode 100644
index 0000000..257ef4a
--- /dev/null
+++ b/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+};
diff --git a/plat/arm/board/rdn1edge/platform.mk b/plat/arm/board/rdn1edge/platform.mk
index e436542..3f0cc7f 100644
--- a/plat/arm/board/rdn1edge/platform.mk
+++ b/plat/arm/board/rdn1edge/platform.mk
@@ -41,9 +41,13 @@
 BL31_CPPFLAGS		+=	-DPLAT_XLAT_TABLES_DYNAMIC
 
 # Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES		+=	${RDN1EDGE_BASE}/fdts/${PLAT}_fw_config.dts
-TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+FDT_SOURCES		+=	${RDN1EDGE_BASE}/fdts/${PLAT}_fw_config.dts	\
+				${RDN1EDGE_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
 
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config))
 # 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/sgi575/fdts/sgi575_fw_config.dts b/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts
index da933e5..84fc1ad 100644
--- a/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts
+++ b/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts
@@ -4,7 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <export/common/tbbr/tbbr_img_def_exp.h>
+#include <common/tbbr/tbbr_img_def.h>
 
 /dts-v1/;
 
@@ -12,9 +12,8 @@
 	dtb-registry {
 		compatible = "fconf,dyn_cfg-dtb_registry";
 
-		/* tb_fw_config is temporarily contained on this dtb */
 		tb_fw-config {
-			load-address = <0x0 0x4001010>;
+			load-address = <0x0 0x4001300>;
 			max-size = <0x200>;
 			id = <TB_FW_CONFIG_ID>;
 		};
@@ -25,23 +24,4 @@
 			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_tb_fw_config.dts b/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts
new file mode 100644
index 0000000..49eda27
--- /dev/null
+++ b/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+};
diff --git a/plat/arm/board/sgi575/platform.mk b/plat/arm/board/sgi575/platform.mk
index d91f829..f5d547d 100644
--- a/plat/arm/board/sgi575/platform.mk
+++ b/plat/arm/board/sgi575/platform.mk
@@ -35,9 +35,14 @@
 endif
 
 # Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES		+=	${SGI575_BASE}/fdts/${PLAT}_fw_config.dts
-TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+FDT_SOURCES		+=	${SGI575_BASE}/fdts/${PLAT}_fw_config.dts	\
+				${SGI575_BASE}/fdts/${PLAT}_tb_fw_config.dts
 
+FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config))
 # 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/sgm775/fdts/sgm775_fw_config.dts b/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts
index 306bd89..5d478e9 100644
--- a/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts
+++ b/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts
@@ -4,7 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <export/common/tbbr/tbbr_img_def_exp.h>
+#include <common/tbbr/tbbr_img_def.h>
 
 /dts-v1/;
 
@@ -12,30 +12,10 @@
 	dtb-registry {
 		compatible = "fconf,dyn_cfg-dtb_registry";
 
-		/* tb_fw_config is temporarily contained on this dtb */
 		tb_fw-config {
-			load-address = <0x0 0x4001010>;
+			load-address = <0x0 0x4001300>;
 			max-size = <0x200>;
 			id = <TB_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/sgm775/fdts/sgm775_tb_fw_config.dts b/plat/arm/board/sgm775/fdts/sgm775_tb_fw_config.dts
new file mode 100644
index 0000000..49eda27
--- /dev/null
+++ b/plat/arm/board/sgm775/fdts/sgm775_tb_fw_config.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+};
diff --git a/plat/arm/board/sgm775/platform.mk b/plat/arm/board/sgm775/platform.mk
index 57edb92..26bc25d 100644
--- a/plat/arm/board/sgm775/platform.mk
+++ b/plat/arm/board/sgm775/platform.mk
@@ -9,9 +9,13 @@
 SGM775_BASE= plat/arm/board/sgm775
 
 # Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES            +=      ${SGM775_BASE}/fdts/${PLAT}_fw_config.dts
-TB_FW_CONFIG           :=      ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+FDT_SOURCES		+=      ${SGM775_BASE}/fdts/${PLAT}_fw_config.dts	\
+				${SGM775_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG		:=      ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG		:=      ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
 
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config))
 # 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/tc0/fdts/tc0_fw_config.dts b/plat/arm/board/tc0/fdts/tc0_fw_config.dts
new file mode 100644
index 0000000..381ce1f
--- /dev/null
+++ b/plat/arm/board/tc0/fdts/tc0_fw_config.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/tbbr/tbbr_img_def.h>
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "fconf,dyn_cfg-dtb_registry";
+
+		tb_fw-config {
+			load-address = <0x0 0x4001300>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+
+		hw-config {
+			load-address = <0x0 0x83000000>;
+			max-size = <0x01000000>;
+			id = <HW_CONFIG_ID>;
+		};
+	};
+};
diff --git a/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts b/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts
new file mode 100644
index 0000000..2fd25d9
--- /dev/null
+++ b/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+};
diff --git a/plat/arm/board/tc0/include/plat_macros.S b/plat/arm/board/tc0/include/plat_macros.S
new file mode 100644
index 0000000..6006fa5
--- /dev/null
+++ b/plat/arm/board/tc0/include/plat_macros.S
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <arm_macros.S>
+
+/* ---------------------------------------------
+ * The below required platform porting macro
+ * prints out relevant platform registers
+ * whenever an unhandled exception is taken in
+ * BL31.
+ *
+ * There are currently no platform specific regs
+ * to print.
+ * ---------------------------------------------
+ */
+	.macro plat_crash_print_regs
+	.endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/arm/board/tc0/include/platform_def.h b/plat/arm/board/tc0/include/platform_def.h
new file mode 100644
index 0000000..56c71c1
--- /dev/null
+++ b/plat/arm/board/tc0/include/platform_def.h
@@ -0,0 +1,194 @@
+/*
+ * 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 <lib/xlat_tables/xlat_tables_defs.h>
+#include <plat/arm/board/common/board_css_def.h>
+#include <plat/arm/board/common/v2m_def.h>
+#include <plat/arm/common/arm_def.h>
+#include <plat/arm/common/arm_spm_def.h>
+#include <plat/arm/css/common/css_def.h>
+#include <plat/arm/soc/common/soc_css_def.h>
+#include <plat/common/common_def.h>
+
+#define PLATFORM_CORE_COUNT		4
+
+#define PLAT_ARM_TRUSTED_SRAM_SIZE	0x00080000	/* 512 KB */
+
+/*
+ * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
+ * plat_arm_mmap array defined for each BL stage.
+ */
+#if defined(IMAGE_BL31)
+# if SPM_MM
+#  define PLAT_ARM_MMAP_ENTRIES		9
+#  define MAX_XLAT_TABLES		7
+#  define PLAT_SP_IMAGE_MMAP_REGIONS	7
+#  define PLAT_SP_IMAGE_MAX_XLAT_TABLES	10
+# else
+#  define PLAT_ARM_MMAP_ENTRIES		8
+#  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		7
+#else
+# define PLAT_ARM_MMAP_ENTRIES		12
+# define MAX_XLAT_TABLES		6
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
+ * plus a little space for growth.
+ */
+#define PLAT_ARM_MAX_BL1_RW_SIZE	0xC000
+
+/*
+ * PLAT_ARM_MAX_ROMLIB_RW_SIZE is define to use a full page
+ */
+
+#if USE_ROMLIB
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE	0x1000
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE	0xe000
+#else
+#define PLAT_ARM_MAX_ROMLIB_RW_SIZE	0
+#define PLAT_ARM_MAX_ROMLIB_RO_SIZE	0
+#endif
+
+/*
+ * PLAT_ARM_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
+ * little space for growth.
+ */
+#if TRUSTED_BOARD_BOOT
+# define PLAT_ARM_MAX_BL2_SIZE		0x1E000
+#else
+# define PLAT_ARM_MAX_BL2_SIZE		0x11000
+#endif
+
+/*
+ * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is
+ * calculated using the current BL31 PROGBITS debug size plus the sizes of
+ * BL2 and BL1-RW
+ */
+#define PLAT_ARM_MAX_BL31_SIZE		0x3B000
+
+/*
+ * Size of cacheable stacks
+ */
+#if defined(IMAGE_BL1)
+# if TRUSTED_BOARD_BOOT
+#  define PLATFORM_STACK_SIZE		0x1000
+# else
+#  define PLATFORM_STACK_SIZE		0x440
+# endif
+#elif defined(IMAGE_BL2)
+# if TRUSTED_BOARD_BOOT
+#  define PLATFORM_STACK_SIZE		0x1000
+# else
+#  define PLATFORM_STACK_SIZE		0x400
+# endif
+#elif defined(IMAGE_BL2U)
+# define PLATFORM_STACK_SIZE		0x400
+#elif defined(IMAGE_BL31)
+# if SPM_MM
+#  define PLATFORM_STACK_SIZE		0x500
+# else
+#  define PLATFORM_STACK_SIZE		0x400
+# endif
+#elif defined(IMAGE_BL32)
+# define PLATFORM_STACK_SIZE		0x440
+#endif
+
+
+#define TC0_DEVICE_BASE			0x21000000
+#define TC0_DEVICE_SIZE			0x5f000000
+
+// TC0_MAP_DEVICE covers different peripherals
+// available to the platform
+#define TC0_MAP_DEVICE	MAP_REGION_FLAT(		\
+					TC0_DEVICE_BASE,	\
+					TC0_DEVICE_SIZE,	\
+					MT_DEVICE | MT_RW | MT_SECURE)
+
+
+#define TC0_FLASH0_RO	MAP_REGION_FLAT(V2M_FLASH0_BASE,\
+						V2M_FLASH0_SIZE,	\
+						MT_DEVICE | MT_RO | MT_SECURE)
+
+#define PLAT_ARM_NSTIMER_FRAME_ID	0
+
+#define PLAT_ARM_TRUSTED_ROM_BASE	0x0
+#define PLAT_ARM_TRUSTED_ROM_SIZE	0x00080000	/* 512KB */
+
+#define PLAT_ARM_NSRAM_BASE		0x06000000
+#define PLAT_ARM_NSRAM_SIZE		0x00080000	/* 512KB */
+
+#define PLAT_ARM_DRAM2_BASE		ULL(0x8080000000)
+#define PLAT_ARM_DRAM2_SIZE		ULL(0x180000000)
+
+#define PLAT_ARM_G1S_IRQ_PROPS(grp)	CSS_G1S_IRQ_PROPS(grp)
+#define PLAT_ARM_G0_IRQ_PROPS(grp)	ARM_G0_IRQ_PROPS(grp)
+
+#define PLAT_ARM_SP_IMAGE_STACK_BASE	(PLAT_SP_IMAGE_NS_BUF_BASE +	\
+					 PLAT_SP_IMAGE_NS_BUF_SIZE)
+
+/*******************************************************************************
+ * Memprotect definitions
+ ******************************************************************************/
+/* PSCI memory protect definitions:
+ * This variable is stored in a non-secure flash because some ARM reference
+ * platforms do not have secure NVRAM. Real systems that provided MEM_PROTECT
+ * support must use a secure NVRAM to store the PSCI MEM_PROTECT definitions.
+ */
+#define PLAT_ARM_MEM_PROT_ADDR		(V2M_FLASH0_BASE + \
+					 V2M_FLASH0_SIZE - V2M_FLASH_BLOCK_SIZE)
+
+/*Secure Watchdog Constants */
+#define SBSA_SECURE_WDOG_BASE		UL(0x2A480000)
+#define SBSA_SECURE_WDOG_TIMEOUT	UL(100)
+
+#define PLAT_ARM_SCMI_CHANNEL_COUNT	1
+
+#define PLAT_ARM_CLUSTER_COUNT		U(1)
+#define PLAT_MAX_CPUS_PER_CLUSTER	U(4)
+#define PLAT_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
+ */
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 36)
+
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE		UL(0x30000000)
+#define PLAT_ARM_GICC_BASE		UL(0x2C000000)
+#define PLAT_ARM_GICR_BASE		UL(0x30140000)
+
+/*
+ * PLAT_CSS_MAX_SCP_BL2_SIZE is calculated using the current
+ * SCP_BL2 size plus a little space for growth.
+ */
+#define PLAT_CSS_MAX_SCP_BL2_SIZE	0x14000
+
+/*
+ * PLAT_CSS_MAX_SCP_BL2U_SIZE is calculated using the current
+ * SCP_BL2U size plus a little space for growth.
+ */
+#define PLAT_CSS_MAX_SCP_BL2U_SIZE	0x14000
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/tc0/include/tc0_helpers.S b/plat/arm/board/tc0/include/tc0_helpers.S
new file mode 100644
index 0000000..90623a2
--- /dev/null
+++ b/plat/arm/board/tc0/include/tc0_helpers.S
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+#include <cpu_macros.S>
+
+	.globl	plat_arm_calc_core_pos
+	.globl	plat_reset_handler
+
+	/* ---------------------------------------------------------------------
+	 * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
+	 *
+	 * Function to calculate the core position on TC0.
+	 *
+	 * (ClusterId * PLAT_MAX_CPUS_PER_CLUSTER * PLAT_MAX_PE_PER_CPU) +
+	 * (CPUId * PLAT_MAX_PE_PER_CPU) +
+	 * ThreadId
+	 *
+	 * which can be simplified as:
+	 *
+	 * ((ClusterId * PLAT_MAX_CPUS_PER_CLUSTER + CPUId) * PLAT_MAX_PE_PER_CPU)
+	 * + ThreadId
+	 * ---------------------------------------------------------------------
+	 */
+func plat_arm_calc_core_pos
+	/*
+	 * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
+	 * look as if in a multi-threaded implementation.
+	 */
+	tst	x0, #MPIDR_MT_MASK
+	lsl	x3, x0, #MPIDR_AFFINITY_BITS
+	csel	x3, x3, x0, eq
+
+	/* Extract individual affinity fields from MPIDR */
+	ubfx	x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+
+	/* Compute linear position */
+	mov	x4, #PLAT_MAX_CPUS_PER_CLUSTER
+	madd	x1, x2, x4, x1
+	mov	x5, #PLAT_MAX_PE_PER_CPU
+	madd	x0, x1, x5, x0
+	ret
+endfunc plat_arm_calc_core_pos
+
+	/* -----------------------------------------------------
+	 * void plat_reset_handler(void);
+	 *
+	 * Determine the CPU MIDR and disable power down bit for
+	 * that CPU.
+	 * -----------------------------------------------------
+	 */
+func plat_reset_handler
+	ret
+endfunc plat_reset_handler
diff --git a/plat/arm/board/tc0/include/tc0_plat.h b/plat/arm/board/tc0/include/tc0_plat.h
new file mode 100644
index 0000000..f0cb431
--- /dev/null
+++ b/plat/arm/board/tc0/include/tc0_plat.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef tc0_bl31_common_platform_setup_PLAT_H
+#define tc0_bl31_common_platform_setup_PLAT_H
+
+void tc0_bl31_common_platform_setup(void);
+
+#endif /* tc0_bl31_common_platform_setup_PLAT_H */
diff --git a/plat/arm/board/tc0/platform.mk b/plat/arm/board/tc0/platform.mk
new file mode 100644
index 0000000..0bf18e4
--- /dev/null
+++ b/plat/arm/board/tc0/platform.mk
@@ -0,0 +1,102 @@
+# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+CSS_LOAD_SCP_IMAGES	:=	1
+
+CSS_USE_SCMI_SDS_DRIVER	:=	1
+
+RAS_EXTENSION		:=	0
+
+SDEI_SUPPORT		:=	0
+
+EL3_EXCEPTION_HANDLING	:=	0
+
+HANDLE_EA_EL3_FIRST	:=	0
+
+# System coherency is managed in hardware
+HW_ASSISTED_COHERENCY	:=	1
+
+# When building for systems with hardware-assisted coherency, there's no need to
+# use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too.
+USE_COHERENT_MEM	:=	0
+
+GIC_ENABLE_V4_EXTN	:=      1
+
+# GIC-600 configuration
+GICV3_SUPPORT_GIC600	:=	1
+
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+ENT_GIC_SOURCES		:=	${GICV3_SOURCES}		\
+				plat/common/plat_gicv3.c	\
+				plat/arm/common/arm_gicv3.c
+
+override NEED_BL2U	:=	no
+
+override ARM_PLAT_MT	:=	1
+
+TC0_BASE	=	plat/arm/board/tc0
+
+PLAT_INCLUDES		+=	-I${TC0_BASE}/include/
+
+TC0_CPU_SOURCES	:=	lib/cpus/aarch64/cortex_matterhorn.S
+
+INTERCONNECT_SOURCES	:=	${TC0_BASE}/tc0_interconnect.c
+
+PLAT_BL_COMMON_SOURCES	+=	${TC0_BASE}/tc0_plat.c	\
+				${TC0_BASE}/include/tc0_helpers.S
+
+BL1_SOURCES		+=	${INTERCONNECT_SOURCES}	\
+				${TC0_CPU_SOURCES}	\
+				${TC0_BASE}/tc0_trusted_boot.c	\
+				${TC0_BASE}/tc0_err.c	\
+				drivers/arm/sbsa/sbsa.c
+
+
+BL2_SOURCES		+=	${TC0_BASE}/tc0_security.c	\
+				${TC0_BASE}/tc0_err.c		\
+				${TC0_BASE}/tc0_trusted_boot.c		\
+				lib/utils/mem_region.c			\
+				plat/arm/common/arm_nor_psci_mem_protect.c
+
+BL31_SOURCES		+=	${INTERCONNECT_SOURCES}	\
+				${TC0_CPU_SOURCES}	\
+				${ENT_GIC_SOURCES}			\
+				${TC0_BASE}/tc0_bl31_setup.c	\
+				${TC0_BASE}/tc0_topology.c	\
+				drivers/cfi/v2m/v2m_flash.c		\
+				lib/utils/mem_region.c			\
+				plat/arm/common/arm_nor_psci_mem_protect.c
+
+# Add the FDT_SOURCES and options for Dynamic Config
+FDT_SOURCES		+=	${TC0_BASE}/fdts/${PLAT}_fw_config.dts	\
+				${TC0_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config))
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
+
+#Device tree
+TC0_HW_CONFIG_DTS	:=	fdts/tc0.dts
+TC0_HW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}.dtb
+FDT_SOURCES		+=	${TC0_HW_CONFIG_DTS}
+$(eval TC0_HW_CONFIG	:=	${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(TC0_HW_CONFIG_DTS)))
+
+# Add the HW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TC0_HW_CONFIG},--hw-config))
+
+override CTX_INCLUDE_AARCH32_REGS	:= 0
+
+override CTX_INCLUDE_PAUTH_REGS	:= 1
+
+include plat/arm/common/arm_common.mk
+include plat/arm/css/common/css_common.mk
+include plat/arm/soc/common/soc_css.mk
+include plat/arm/board/common/board_common.mk
diff --git a/plat/arm/board/tc0/tc0_bl31_setup.c b/plat/arm/board/tc0/tc0_bl31_setup.c
new file mode 100644
index 0000000..b91b11c
--- /dev/null
+++ b/plat/arm/board/tc0/tc0_bl31_setup.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <libfdt.h>
+#include <tc0_plat.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/css/css_mhu_doorbell.h>
+#include <drivers/arm/css/scmi.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+static scmi_channel_plat_info_t tc0_scmi_plat_info[] = {
+	{
+		.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
+		.db_reg_addr = PLAT_CSS_MHU_BASE + SENDER_REG_SET(0),
+		.db_preserve_mask = 0xfffffffe,
+		.db_modify_mask = 0x1,
+		.ring_doorbell = &mhuv2_ring_doorbell,
+	}
+};
+
+void bl31_platform_setup(void)
+{
+	tc0_bl31_common_platform_setup();
+}
+
+scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id)
+{
+
+	return &tc0_scmi_plat_info[channel_id];
+
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				u_register_t arg2, u_register_t arg3)
+{
+	arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
+}
+
+void tc0_bl31_common_platform_setup(void)
+{
+	arm_bl31_platform_setup();
+}
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+	return css_scmi_override_pm_ops(ops);
+}
diff --git a/plat/arm/board/tc0/tc0_err.c b/plat/arm/board/tc0/tc0_err.c
new file mode 100644
index 0000000..4fc0505
--- /dev/null
+++ b/plat/arm/board/tc0/tc0_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>
+
+/*
+ * tc0 error handler
+ */
+void __dead2 plat_arm_error_handler(int err)
+{
+	while (1) {
+		wfi();
+	}
+}
diff --git a/plat/arm/board/tc0/tc0_interconnect.c b/plat/arm/board/tc0/tc0_interconnect.c
new file mode 100644
index 0000000..e2fc4e1
--- /dev/null
+++ b/plat/arm/board/tc0/tc0_interconnect.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * For Total Compute we should not do anything in these interface functions.
+ * They are used to override the weak functions in cci drivers.
+ */
+
+/******************************************************************************
+ * Helper function to initialize ARM interconnect driver.
+ *****************************************************************************/
+void __init plat_arm_interconnect_init(void)
+{
+}
+
+/******************************************************************************
+ * Helper function to place current master into coherency
+ *****************************************************************************/
+void plat_arm_interconnect_enter_coherency(void)
+{
+}
+
+/******************************************************************************
+ * Helper function to remove current master from coherency
+ *****************************************************************************/
+void plat_arm_interconnect_exit_coherency(void)
+{
+}
diff --git a/plat/arm/board/tc0/tc0_plat.c b/plat/arm/board/tc0/tc0_plat.c
new file mode 100644
index 0000000..0546192
--- /dev/null
+++ b/plat/arm/board/tc0/tc0_plat.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <platform_def.h>
+
+#include <plat/common/platform.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/ccn.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <drivers/arm/sbsa.h>
+
+#if SPM_MM
+#include <services/spm_mm_partition.h>
+#endif
+
+/*
+ * Table of regions for different BL stages to map using the MMU.
+ * This doesn't include Trusted RAM as the 'mem_layout' argument passed to
+ * arm_configure_mmu_elx() will give the available subset of that.
+ */
+#if IMAGE_BL1
+const mmap_region_t plat_arm_mmap[] = {
+	ARM_MAP_SHARED_RAM,
+	TC0_FLASH0_RO,
+	TC0_MAP_DEVICE,
+	{0}
+};
+#endif
+#if IMAGE_BL2
+const mmap_region_t plat_arm_mmap[] = {
+	ARM_MAP_SHARED_RAM,
+	TC0_FLASH0_RO,
+	TC0_MAP_DEVICE,
+	ARM_MAP_NS_DRAM1,
+#if ARM_BL31_IN_DRAM
+	ARM_MAP_BL31_SEC_DRAM,
+#endif
+#if SPM_MM
+	ARM_SP_IMAGE_MMAP,
+#endif
+#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3
+	ARM_MAP_BL1_RW,
+#endif
+	{0}
+};
+#endif
+#if IMAGE_BL31
+const mmap_region_t plat_arm_mmap[] = {
+	ARM_MAP_SHARED_RAM,
+	V2M_MAP_IOFPGA,
+	TC0_MAP_DEVICE,
+#if SPM_MM
+	ARM_SPM_BUF_EL3_MMAP,
+#endif
+	{0}
+};
+
+#if SPM_MM && defined(IMAGE_BL31)
+const mmap_region_t plat_arm_secure_partition_mmap[] = {
+	PLAT_ARM_SECURE_MAP_DEVICE,
+	ARM_SP_IMAGE_MMAP,
+	ARM_SP_IMAGE_NS_BUF_MMAP,
+	ARM_SP_CPER_BUF_MMAP,
+	ARM_SP_IMAGE_RW_MMAP,
+	ARM_SPM_BUF_EL0_MMAP,
+	{0}
+};
+#endif /* SPM_MM && defined(IMAGE_BL31) */
+#endif
+
+ARM_CASSERT_MMAP
+
+#if SPM_MM && defined(IMAGE_BL31)
+/*
+ * Boot information passed to a secure partition during initialisation. Linear
+ * indices in MP information will be filled at runtime.
+ */
+static spm_mm_mp_info_t sp_mp_info[] = {
+	[0] = {0x81000000, 0},
+	[1] = {0x81000100, 0},
+	[2] = {0x81000200, 0},
+	[3] = {0x81000300, 0},
+	[4] = {0x81010000, 0},
+	[5] = {0x81010100, 0},
+	[6] = {0x81010200, 0},
+	[7] = {0x81010300, 0},
+};
+
+const spm_mm_boot_info_t plat_arm_secure_partition_boot_info = {
+	.h.type              = PARAM_SP_IMAGE_BOOT_INFO,
+	.h.version           = VERSION_1,
+	.h.size              = sizeof(spm_mm_boot_info_t),
+	.h.attr              = 0,
+	.sp_mem_base         = ARM_SP_IMAGE_BASE,
+	.sp_mem_limit        = ARM_SP_IMAGE_LIMIT,
+	.sp_image_base       = ARM_SP_IMAGE_BASE,
+	.sp_stack_base       = PLAT_SP_IMAGE_STACK_BASE,
+	.sp_heap_base        = ARM_SP_IMAGE_HEAP_BASE,
+	.sp_ns_comm_buf_base = PLAT_SP_IMAGE_NS_BUF_BASE,
+	.sp_shared_buf_base  = PLAT_SPM_BUF_BASE,
+	.sp_image_size       = ARM_SP_IMAGE_SIZE,
+	.sp_pcpu_stack_size  = PLAT_SP_IMAGE_STACK_PCPU_SIZE,
+	.sp_heap_size        = ARM_SP_IMAGE_HEAP_SIZE,
+	.sp_ns_comm_buf_size = PLAT_SP_IMAGE_NS_BUF_SIZE,
+	.sp_shared_buf_size  = PLAT_SPM_BUF_SIZE,
+	.num_sp_mem_regions  = ARM_SP_IMAGE_NUM_MEM_REGIONS,
+	.num_cpus            = PLATFORM_CORE_COUNT,
+	.mp_info             = &sp_mp_info[0],
+};
+
+const struct mmap_region *plat_get_secure_partition_mmap(void *cookie)
+{
+	return plat_arm_secure_partition_mmap;
+}
+
+const struct spm_mm_boot_info *plat_get_secure_partition_boot_info(
+		void *cookie)
+{
+	return &plat_arm_secure_partition_boot_info;
+}
+#endif /* SPM_MM && defined(IMAGE_BL31) */
+
+#if TRUSTED_BOARD_BOOT
+int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size)
+{
+	assert(heap_addr != NULL);
+	assert(heap_size != NULL);
+
+	return arm_get_mbedtls_heap(heap_addr, heap_size);
+}
+#endif
+
+void plat_arm_secure_wdt_start(void)
+{
+	sbsa_wdog_start(SBSA_SECURE_WDOG_BASE, SBSA_SECURE_WDOG_TIMEOUT);
+}
+
+void plat_arm_secure_wdt_stop(void)
+{
+	sbsa_wdog_stop(SBSA_SECURE_WDOG_BASE);
+}
diff --git a/plat/arm/board/tc0/tc0_security.c b/plat/arm/board/tc0/tc0_security.c
new file mode 100644
index 0000000..6aa38c8
--- /dev/null
+++ b/plat/arm/board/tc0/tc0_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/tc0/tc0_topology.c b/plat/arm/board/tc0/tc0_topology.c
new file mode 100644
index 0000000..5478fbc
--- /dev/null
+++ b/plat/arm/board/tc0/tc0_topology.c
@@ -0,0 +1,55 @@
+/*
+ * 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 tc0_pd_tree_desc[] = {
+	PLAT_ARM_CLUSTER_COUNT,
+	PLAT_MAX_CPUS_PER_CLUSTER,
+};
+
+/*******************************************************************************
+ * This function returns the topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return tc0_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)),
+};
+
+/*******************************************************************************
+ * This function returns the core count within the cluster corresponding to
+ * `mpidr`.
+ ******************************************************************************/
+unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr)
+{
+	return PLAT_MAX_CPUS_PER_CLUSTER;
+}
+
+#if ARM_PLAT_MT
+/******************************************************************************
+ * Return the number of PE's supported by the CPU.
+ *****************************************************************************/
+unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr)
+{
+	return PLAT_MAX_PE_PER_CPU;
+}
+#endif
diff --git a/plat/arm/board/tc0/tc0_trusted_boot.c b/plat/arm/board/tc0/tc0_trusted_boot.c
new file mode 100644
index 0000000..614f7e2
--- /dev/null
+++ b/plat/arm/board/tc0/tc0_trusted_boot.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * Return the ROTPK hash in the following ASN.1 structure in DER format:
+ *
+ * AlgorithmIdentifier  ::=  SEQUENCE  {
+ *     algorithm         OBJECT IDENTIFIER,
+ *     parameters        ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ *     digestAlgorithm   AlgorithmIdentifier,
+ *     digest            OCTET STRING
+ * }
+ */
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+			unsigned int *flags)
+{
+	return arm_get_rotpk_info(cookie, key_ptr, key_len, flags);
+}
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index c2f49c2..4b2a062 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -12,6 +12,7 @@
 #include <bl1/bl1.h>
 #include <common/bl_common.h>
 #include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
 #include <lib/utils.h>
 #include <lib/xlat_tables/xlat_tables_compat.h>
 #include <plat/arm/common/plat_arm.h>
@@ -53,6 +54,9 @@
 /* Data structure which holds the extents of the trusted SRAM for BL1*/
 static meminfo_t bl1_tzram_layout;
 
+/* Boolean variable to hold condition whether firmware update needed or not */
+static bool is_fwu_needed;
+
 struct meminfo *bl1_plat_sec_mem_layout(void)
 {
 	return &bl1_tzram_layout;
@@ -142,11 +146,58 @@
  */
 void arm_bl1_platform_setup(void)
 {
+	const struct dyn_cfg_dtb_info_t *fw_config_info;
+	image_desc_t *desc;
+	uint32_t fw_config_max_size;
+	int err = -1;
+
 	/* Initialise the IO layer and register platform IO devices */
 	plat_arm_io_setup();
 
-	/* Load fw config */
-	fconf_load_config();
+	/* Check if we need FWU before further processing */
+	is_fwu_needed = plat_arm_bl1_fwu_needed();
+	if (is_fwu_needed) {
+		ERROR("Skip platform setup as FWU detected\n");
+		return;
+	}
+
+	/* Set global DTB info for fixed fw_config information */
+	fw_config_max_size = ARM_FW_CONFIG_LIMIT - ARM_FW_CONFIG_BASE;
+	set_config_info(ARM_FW_CONFIG_BASE, fw_config_max_size, FW_CONFIG_ID);
+
+	/* Fill the device tree information struct with the info from the config dtb */
+	err = fconf_load_config(FW_CONFIG_ID);
+	if (err < 0) {
+		ERROR("Loading of FW_CONFIG failed %d\n", err);
+		plat_error_handler(err);
+	}
+
+	/*
+	 * FW_CONFIG loaded successfully. If FW_CONFIG device tree parsing
+	 * is successful then load TB_FW_CONFIG device tree.
+	 */
+	fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID);
+	if (fw_config_info != NULL) {
+		err = fconf_populate_dtb_registry(fw_config_info->config_addr);
+		if (err < 0) {
+			ERROR("Parsing of FW_CONFIG failed %d\n", err);
+			plat_error_handler(err);
+		}
+		/* load TB_FW_CONFIG */
+		err = fconf_load_config(TB_FW_CONFIG_ID);
+		if (err < 0) {
+			ERROR("Loading of TB_FW_CONFIG failed %d\n", err);
+			plat_error_handler(err);
+		}
+	} else {
+		ERROR("Invalid FW_CONFIG address\n");
+		plat_error_handler(err);
+	}
+
+	/* 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 = fw_config_info->config_addr;
 
 #if TRUSTED_BOARD_BOOT
 	/* Share the Mbed TLS heap info with other images */
@@ -199,5 +250,5 @@
  ******************************************************************************/
 unsigned int bl1_plat_get_next_image_id(void)
 {
-	return plat_arm_bl1_fwu_needed() ? NS_BL1U_IMAGE_ID : BL2_IMAGE_ID;
+	return  is_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 6c3f64f..60d8f6e 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -15,6 +15,7 @@
 #include <common/desc_image_load.h>
 #include <drivers/generic_delay_timer.h>
 #include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
 #ifdef SPD_opteed
 #include <lib/optee_utils.h>
 #endif
@@ -25,17 +26,23 @@
 /* Data structure which holds the extents of the trusted SRAM for BL2 */
 static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
 
+/* Base address of fw_config received from BL1 */
+static uintptr_t fw_config_base;
+
 /*
- * Check that BL2_BASE is above ARM_TB_FW_CONFIG_LIMIT. This reserved page is
+ * Check that BL2_BASE is above ARM_FW_CONFIG_LIMIT. This reserved page is
  * for `meminfo_t` data structure and fw_configs passed from BL1.
  */
-CASSERT(BL2_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_bl2_base_overflows);
+CASSERT(BL2_BASE >= ARM_FW_CONFIG_LIMIT, assert_bl2_base_overflows);
 
 /* Weak definitions may be overridden in specific ARM standard platform */
 #pragma weak bl2_early_platform_setup2
 #pragma weak bl2_platform_setup
 #pragma weak bl2_plat_arch_setup
 #pragma weak bl2_plat_sec_mem_layout
+#if MEASURED_BOOT
+#pragma weak bl2_plat_get_hash
+#endif
 
 #define MAP_BL2_TOTAL		MAP_REGION_FLAT(			\
 					bl2_tzram_layout.total_base,	\
@@ -50,7 +57,7 @@
  * in x0. This memory layout is sitting at the base of the free trusted SRAM.
  * Copy it to a safe location before its reclaimed by later BL2 functionality.
  ******************************************************************************/
-void arm_bl2_early_platform_setup(uintptr_t tb_fw_config,
+void arm_bl2_early_platform_setup(uintptr_t fw_config,
 				  struct meminfo *mem_layout)
 {
 	/* Initialize the console to provide early debug support */
@@ -59,10 +66,7 @@
 	/* 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", tb_fw_config);
-	}
+	fw_config_base = fw_config;
 
 	/* Initialise the IO layer and register platform IO devices */
 	plat_arm_io_setup();
@@ -126,6 +130,7 @@
 #if ARM_CRYPTOCELL_INTEG
 		ARM_MAP_BL_COHERENT_RAM,
 #endif
+		ARM_MAP_BL_CONFIG_REGION,
 		{0}
 	};
 
@@ -142,7 +147,18 @@
 
 void bl2_plat_arch_setup(void)
 {
+	const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
+
 	arm_bl2_plat_arch_setup();
+
+	/* Fill the properties struct with the info from the config dtb */
+	fconf_populate("FW_CONFIG", fw_config_base);
+
+	/* TB_FW_CONFIG was also loaded by BL1 */
+	tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
+	assert(tb_fw_config_info != NULL);
+
+	fconf_populate("TB_FW", tb_fw_config_info->config_addr);
 }
 
 int arm_bl2_handle_post_image_load(unsigned int image_id)
@@ -219,3 +235,11 @@
 {
 	return arm_bl2_plat_handle_post_image_load(image_id);
 }
+
+#if MEASURED_BOOT
+/* Read TCG_DIGEST_SIZE bytes of BL2 hash data */
+void bl2_plat_get_hash(void *data)
+{
+	arm_bl2_get_hash(data);
+}
+#endif
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index 85535c1..58ccf0e 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -28,10 +28,10 @@
 
 #if !RESET_TO_BL31
 /*
- * Check that BL31_BASE is above ARM_TB_FW_CONFIG_LIMIT. The reserved page
+ * Check that BL31_BASE is above ARM_FW_CONFIG_LIMIT. The reserved page
  * is required for SOC_FW_CONFIG/TOS_FW_CONFIG passed from BL2.
  */
-CASSERT(BL31_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_bl31_base_overflows);
+CASSERT(BL31_BASE >= ARM_FW_CONFIG_LIMIT, assert_bl31_base_overflows);
 #endif
 
 /* Weak definitions may be overridden in specific ARM standard platform */
@@ -114,6 +114,18 @@
 	SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
 	bl32_image_ep_info.pc = BL32_BASE;
 	bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry();
+
+#if defined(SPD_spmd)
+	/* SPM (hafnium in secure world) expects SPM Core manifest base address
+	 * in x0, which in !RESET_TO_BL31 case loaded after base of non shared
+	 * SRAM(after 4KB offset of SRAM). But in RESET_TO_BL31 case all non
+	 * shared SRAM is allocated to BL31, so to avoid overwriting of manifest
+	 * keep it in the last page.
+	 */
+	bl32_image_ep_info.args.arg0 = ARM_TRUSTED_SRAM_BASE +
+				PLAT_ARM_TRUSTED_SRAM_SIZE - PAGE_SIZE;
+#endif
+
 # endif /* BL32_BASE */
 
 	/* Populate entry point information for BL33 */
@@ -130,6 +142,14 @@
 	bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry();
 	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
 
+#if defined(SPD_spmd) && !(ARM_LINUX_KERNEL_AS_BL33)
+	/*
+	 * Hafnium in normal world expects its manifest address in x0, which
+	 * is loaded at base of DRAM.
+	 */
+	bl33_image_ep_info.args.arg0 = (u_register_t)ARM_DRAM1_BASE;
+#endif
+
 # if ARM_LINUX_KERNEL_AS_BL33
 	/*
 	 * According to the file ``Documentation/arm64/booting.txt`` of the
diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c
index 60c777e..e2b99a3 100644
--- a/plat/arm/common/arm_common.c
+++ b/plat/arm/common/arm_common.c
@@ -13,7 +13,9 @@
 #include <common/debug.h>
 #include <common/romlib.h>
 #include <lib/mmio.h>
+#include <lib/smccc.h>
 #include <lib/xlat_tables/xlat_tables_compat.h>
+#include <services/arm_arch_svc.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 
@@ -235,6 +237,23 @@
 }
 #endif
 
+/*****************************************************************************
+ * plat_is_smccc_feature_available() - This function checks whether SMCCC
+ *                                     feature is availabile for platform.
+ * @fid: SMCCC function id
+ *
+ * Return SMC_OK if SMCCC feature is available and SMC_ARCH_CALL_NOT_SUPPORTED
+ * otherwise.
+ *****************************************************************************/
+int32_t plat_is_smccc_feature_available(u_register_t fid)
+{
+	switch (fid) {
+	case SMCCC_ARCH_SOC_ID:
+	default:
+		return SMC_ARCH_CALL_NOT_SUPPORTED;
+	}
+}
+
 /*
  * Weak function to get ARM platform SOC-ID, Always return SOC-ID=0
  * ToDo: Get proper SOC-ID for every ARM platform and define this
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 387c131..96ab2d3 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -297,7 +297,9 @@
 
     # Include the selected chain of trust sources.
     ifeq (${COT},tbbr)
-        AUTH_SOURCES	+=	drivers/auth/tbbr/tbbr_cot.c
+        AUTH_SOURCES	+=	drivers/auth/tbbr/tbbr_cot_common.c
+	BL1_SOURCES     +=      drivers/auth/tbbr/tbbr_cot_bl1.c
+	BL2_SOURCES     +=      drivers/auth/tbbr/tbbr_cot_bl2.c
     else ifeq (${COT},dualroot)
         AUTH_SOURCES	+=	drivers/auth/dualroot/cot.c
     else
@@ -335,3 +337,9 @@
         $(error "To reclaim init code xlat tables v2 must be used")
     endif
 endif
+
+ifeq (${MEASURED_BOOT},1)
+    MEASURED_BOOT_MK := drivers/measured_boot/measured_boot.mk
+    $(info Including ${MEASURED_BOOT_MK})
+    include ${MEASURED_BOOT_MK}
+endif
diff --git a/plat/arm/common/arm_console.c b/plat/arm/common/arm_console.c
index 0cac5d9..c2281c4 100644
--- a/plat/arm/common/arm_console.c
+++ b/plat/arm/common/arm_console.c
@@ -13,6 +13,9 @@
 #include <drivers/console.h>
 #include <plat/arm/common/plat_arm.h>
 
+#pragma weak arm_console_runtime_init
+#pragma weak arm_console_runtime_end
+
 /*******************************************************************************
  * Functions that set up the console
  ******************************************************************************/
diff --git a/plat/arm/common/arm_dyn_cfg.c b/plat/arm/common/arm_dyn_cfg.c
index ffa2a64..6b3a611 100644
--- a/plat/arm/common/arm_dyn_cfg.c
+++ b/plat/arm/common/arm_dyn_cfg.c
@@ -23,6 +23,7 @@
 #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>
 
@@ -77,6 +78,7 @@
 {
 	int err;
 	uintptr_t tb_fw_cfg_dtb;
+	const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
 
 	/*
 	 * If tb_fw_cfg_dtb==NULL then DTB is not present for the current
@@ -91,17 +93,20 @@
 	 * the default heap's address and size.
 	 */
 
-	/* fconf FW_CONFIG and TB_FW_CONFIG are currently the same DTB */
-	tb_fw_cfg_dtb = FCONF_GET_PROPERTY(fconf, dtb, base_addr);
+	tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
+	assert(tb_fw_config_info != NULL);
+
+	tb_fw_cfg_dtb = tb_fw_config_info->config_addr;
 
 	if ((tb_fw_cfg_dtb != 0UL) && (mbedtls_heap_addr != NULL)) {
-		/* As libfdt use void *, we can't avoid this cast */
+		/* As libfdt uses 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");
+			ERROR("%swrite shared Mbed TLS heap information%s",
+				"BL1: unable to ", " to DTB\n");
 			panic();
 		}
 #if !MEASURED_BOOT
@@ -121,18 +126,21 @@
 
 #if MEASURED_BOOT
 /*
- * Puts the BL2 hash data to TB_FW_CONFIG DTB.
+ * Calculates and writes BL2 hash data to TB_FW_CONFIG DTB.
  * Executed only from BL1.
  */
-void arm_bl1_set_bl2_hash(image_desc_t *image_desc)
+void arm_bl1_set_bl2_hash(const image_desc_t *image_desc)
 {
 	unsigned char hash_data[MBEDTLS_MD_MAX_SIZE];
-	image_info_t image_info = image_desc->image_info;
+	const image_info_t image_info = image_desc->image_info;
 	uintptr_t tb_fw_cfg_dtb;
 	int err;
+	const struct dyn_cfg_dtb_info_t *tb_fw_config_info;
 
-	/* fconf FW_CONFIG and TB_FW_CONFIG are currently the same DTB */
-	tb_fw_cfg_dtb = FCONF_GET_PROPERTY(fconf, dtb, base_addr);
+	tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID);
+	assert(tb_fw_config_info != NULL);
+
+	tb_fw_cfg_dtb = tb_fw_config_info->config_addr;
 
 	/*
 	 * If tb_fw_cfg_dtb==NULL then DTB is not present for the current
@@ -148,13 +156,15 @@
 					(void *)image_info.image_base,
 					image_info.image_size, hash_data);
 	if (err != 0) {
-		ERROR("BL1: unable to calculate BL2 hash\n");
+		ERROR("%scalculate%s\n", "BL1: unable to ",
+						" BL2 hash");
 		panic();
 	}
 
 	err = arm_set_bl2_hash_info((void *)tb_fw_cfg_dtb, hash_data);
 	if (err < 0) {
-		ERROR("BL1: unable to write BL2 hash data to DTB\n");
+		ERROR("%swrite%sdata%s\n", "BL1: unable to ",
+					" BL2 hash ", "to DTB\n");
 		panic();
 	}
 
@@ -165,20 +175,35 @@
 	 */
 	flush_dcache_range(tb_fw_cfg_dtb, fdt_totalsize((void *)tb_fw_cfg_dtb));
 }
+
+/*
+ * Reads TCG_DIGEST_SIZE bytes of BL2 hash data from the DTB.
+ * Executed only from BL2.
+ */
+void arm_bl2_get_hash(void *data)
+{
+	const void *bl2_hash;
+
+	assert(data != NULL);
+
+	/* Retrieve TCG_DIGEST_SIZE bytes of BL2 hash data from the DTB */
+	bl2_hash = FCONF_GET_PROPERTY(tbbr, dyn_config, bl2_hash_data);
+	(void)memcpy(data, bl2_hash, TCG_DIGEST_SIZE);
+}
 #endif /* MEASURED_BOOT */
 #endif /* TRUSTED_BOARD_BOOT */
 
 /*
  * 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.
+ * FW_CONFIG. Populate the bl_mem_params_node_t of other FW_CONFIGs if
+ * specified in FW_CONFIG.
  */
 void arm_bl2_dyn_cfg_init(void)
 {
 	unsigned int i;
 	bl_mem_params_node_t *cfg_mem_params = NULL;
 	uintptr_t image_base;
-	size_t image_size;
+	uint32_t image_size;
 	const unsigned int config_ids[] = {
 			HW_CONFIG_ID,
 			SOC_FW_CONFIG_ID,
@@ -196,14 +221,15 @@
 		/* Get the config load address and size from TB_FW_CONFIG */
 		cfg_mem_params = get_bl_mem_params_node(config_ids[i]);
 		if (cfg_mem_params == NULL) {
-			VERBOSE("Couldn't find HW_CONFIG in bl_mem_params_node\n");
+			VERBOSE("%sHW_CONFIG in bl_mem_params_node\n",
+				"Couldn't find ");
 			continue;
 		}
 
 		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]);
+			VERBOSE("%sconfig_id %d load info in TB_FW_CONFIG\n",
+				"Couldn't find ", config_ids[i]);
 			continue;
 		}
 
@@ -217,30 +243,32 @@
 		 */
 		if (config_ids[i] != HW_CONFIG_ID) {
 
-			if (check_uptr_overflow(image_base, image_size))
+			if (check_uptr_overflow(image_base, image_size)) {
 				continue;
-
+			}
 #ifdef	BL31_BASE
 			/* Ensure the configs don't overlap with BL31 */
 			if ((image_base >= BL31_BASE) &&
-			    (image_base <= BL31_LIMIT))
+			    (image_base <= BL31_LIMIT)) {
 				continue;
+			}
 #endif
 			/* Ensure the configs are loaded in a valid address */
-			if (image_base < ARM_BL_RAM_BASE)
+			if (image_base < ARM_BL_RAM_BASE) {
 				continue;
+			}
 #ifdef BL32_BASE
 			/*
 			 * If BL32 is present, ensure that the configs don't
 			 * overlap with it.
 			 */
 			if ((image_base >= BL32_BASE) &&
-			    (image_base <= BL32_LIMIT))
+			    (image_base <= BL32_LIMIT)) {
 				continue;
+			}
 #endif
 		}
 
-
 		cfg_mem_params->image_info.image_base = image_base;
 		cfg_mem_params->image_info.image_max_size = (uint32_t)image_size;
 
diff --git a/plat/arm/common/arm_dyn_cfg_helpers.c b/plat/arm/common/arm_dyn_cfg_helpers.c
index f110e3b..5f20c8d 100644
--- a/plat/arm/common/arm_dyn_cfg_helpers.c
+++ b/plat/arm/common/arm_dyn_cfg_helpers.c
@@ -6,9 +6,13 @@
 
 #include <assert.h>
 
+#if MEASURED_BOOT
+#include <common/desc_image_load.h>
+#endif
+#include <common/fdt_wrappers.h>
+
 #include <libfdt.h>
 
-#include <common/fdt_wrappers.h>
 #include <plat/arm/common/arm_dyn_cfg_helpers.h>
 #include <plat/arm/common/plat_arm.h>
 
@@ -17,6 +21,15 @@
 
 #if MEASURED_BOOT
 #define DTB_PROP_BL2_HASH_DATA	"bl2_hash_data"
+#ifdef SPD_opteed
+/*
+ * Currently OP-TEE does not support reading DTBs from Secure memory
+ * and this property should be removed when this feature is supported.
+ */
+#define DTB_PROP_HW_SM_LOG_ADDR	"tpm_event_log_sm_addr"
+#endif
+#define DTB_PROP_HW_LOG_ADDR	"tpm_event_log_addr"
+#define DTB_PROP_HW_LOG_SIZE    "tpm_event_log_size"
 
 static int dtb_root = -1;
 #endif /* MEASURED_BOOT */
@@ -37,18 +50,19 @@
 
 	/* Check if the pointer to DT is correct */
 	if (fdt_check_header(dtb) != 0) {
-		WARN("Invalid DTB file passed as TB_FW_CONFIG\n");
+		WARN("Invalid DTB file passed as%s\n", " TB_FW_CONFIG");
 		return -1;
 	}
 
 	/* Assert the node offset point to "arm,tb_fw" compatible property */
 	*node = fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw");
 	if (*node < 0) {
-		WARN("The compatible property `arm,tb_fw` not found in the config\n");
+		WARN("The compatible property '%s' not%s", "arm,tb_fw",
+			" found in the config\n");
 		return -1;
 	}
 
-	VERBOSE("Dyn cfg: Found \"arm,tb_fw\" in the config\n");
+	VERBOSE("Dyn cfg: '%s'%s", "arm,tb_fw", " found in the config\n");
 	return 0;
 }
 
@@ -76,7 +90,8 @@
 	 */
 	int err = arm_dyn_tb_fw_cfg_init(dtb, &dtb_root);
 	if (err < 0) {
-		ERROR("Invalid TB_FW_CONFIG loaded. Unable to get root node\n");
+		ERROR("Invalid%s loaded. Unable to get root node\n",
+			" TB_FW_CONFIG");
 		return -1;
 	}
 
@@ -90,16 +105,16 @@
 	err = fdtw_write_inplace_cells(dtb, dtb_root,
 		DTB_PROP_MBEDTLS_HEAP_ADDR, 2, &heap_addr);
 	if (err < 0) {
-		ERROR("Unable to write DTB property %s\n",
-			DTB_PROP_MBEDTLS_HEAP_ADDR);
+		ERROR("%sDTB property '%s'\n",
+			"Unable to write ", DTB_PROP_MBEDTLS_HEAP_ADDR);
 		return -1;
 	}
 
 	err = fdtw_write_inplace_cells(dtb, dtb_root,
 		DTB_PROP_MBEDTLS_HEAP_SIZE, 1, &heap_size);
 	if (err < 0) {
-		ERROR("Unable to write DTB property %s\n",
-			DTB_PROP_MBEDTLS_HEAP_SIZE);
+		ERROR("%sDTB property '%s'\n",
+			"Unable to write ", DTB_PROP_MBEDTLS_HEAP_SIZE);
 		return -1;
 	}
 
@@ -124,7 +139,165 @@
 	/*
 	 * Write the BL2 hash data in the DTB.
 	 */
-	return fdtw_write_inplace_bytes(dtb, dtb_root, DTB_PROP_BL2_HASH_DATA,
+	return fdtw_write_inplace_bytes(dtb, dtb_root,
+					DTB_PROP_BL2_HASH_DATA,
 					TCG_DIGEST_SIZE, data);
 }
+
+/*
+ * Write the Event Log address and its size in the DTB.
+ *
+ * This function is supposed to be called only by BL2.
+ *
+ * Returns:
+ *	0 = success
+ *    < 0 = error
+ */
+static int arm_set_event_log_info(uintptr_t config_base,
+#ifdef SPD_opteed
+				  uintptr_t sm_log_addr,
+#endif
+				  uintptr_t log_addr, size_t log_size)
+{
+	/* As libfdt uses void *, we can't avoid this cast */
+	void *dtb = (void *)config_base;
+	const char *compatible = "arm,tpm_event_log";
+	int err, node;
+
+	/*
+	 * Verify that the DTB is valid, before attempting to write to it,
+	 * and get the DTB root node.
+	 */
+
+	/* Check if the pointer to DT is correct */
+	err = fdt_check_header(dtb);
+	if (err < 0) {
+		WARN("Invalid DTB file passed\n");
+		return err;
+	}
+
+	/* Assert the node offset point to compatible property */
+	node = fdt_node_offset_by_compatible(dtb, -1, compatible);
+	if (node < 0) {
+		WARN("The compatible property '%s' not%s", compatible,
+			" found in the config\n");
+		return node;
+	}
+
+	VERBOSE("Dyn cfg: '%s'%s", compatible, " found in the config\n");
+
+#ifdef SPD_opteed
+	if (sm_log_addr != 0UL) {
+		err = fdtw_write_inplace_cells(dtb, node,
+			DTB_PROP_HW_SM_LOG_ADDR, 2, &sm_log_addr);
+		if (err < 0) {
+			ERROR("%sDTB property '%s'\n",
+				"Unable to write ", DTB_PROP_HW_SM_LOG_ADDR);
+			return err;
+		}
+	}
+#endif
+	err = fdtw_write_inplace_cells(dtb, node,
+		DTB_PROP_HW_LOG_ADDR, 2, &log_addr);
+	if (err < 0) {
+		ERROR("%sDTB property '%s'\n",
+			"Unable to write ", DTB_PROP_HW_LOG_ADDR);
+		return err;
+	}
+
+	err = fdtw_write_inplace_cells(dtb, node,
+		DTB_PROP_HW_LOG_SIZE, 1, &log_size);
+	if (err < 0) {
+		ERROR("%sDTB property '%s'\n",
+			"Unable to write ", DTB_PROP_HW_LOG_SIZE);
+	} else {
+		/*
+		 * Ensure that the info written to the DTB is visible
+		 * to other images.
+		 */
+		flush_dcache_range(config_base, fdt_totalsize(dtb));
+	}
+
+	return err;
+}
+
+/*
+ * This function writes the Event Log address and its size
+ * in the TOS_FW_CONFIG DTB.
+ *
+ * This function is supposed to be called only by BL2.
+ *
+ * Returns:
+ *	0 = success
+ *    < 0 = error
+ */
+int arm_set_tos_fw_info(uintptr_t config_base, uintptr_t log_addr,
+			size_t log_size)
+{
+	int err;
+
+	assert(config_base != 0UL);
+	assert(log_addr != 0UL);
+
+	/* Write the Event Log address and its size in the DTB */
+	err = arm_set_event_log_info(config_base,
+#ifdef SPD_opteed
+					0UL,
+#endif
+					log_addr, log_size);
+	if (err < 0) {
+		ERROR("%sEvent Log data to TOS_FW_CONFIG\n",
+					"Unable to write ");
+	}
+
+	return err;
+}
+
+/*
+ * This function writes the Event Log address and its size
+ * in the NT_FW_CONFIG DTB.
+ *
+ * This function is supposed to be called only by BL2.
+ *
+ * Returns:
+ *	0 = success
+ *    < 0 = error
+ */
+int arm_set_nt_fw_info(uintptr_t config_base,
+#ifdef SPD_opteed
+			uintptr_t log_addr,
+#endif
+			size_t log_size, uintptr_t *ns_log_addr)
+{
+	uintptr_t ns_addr;
+	const bl_mem_params_node_t *cfg_mem_params;
+	int err;
+
+	assert(config_base != 0UL);
+	assert(ns_log_addr != NULL);
+
+	/* Get the config load address and size from NT_FW_CONFIG */
+	cfg_mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID);
+	assert(cfg_mem_params != NULL);
+
+	/* Calculate Event Log address in Non-secure memory */
+	ns_addr = cfg_mem_params->image_info.image_base +
+			cfg_mem_params->image_info.image_max_size;
+
+	/* Check for memory space */
+	if ((uint64_t)(ns_addr + log_size) > ARM_NS_DRAM1_END) {
+		return -1;
+	}
+
+	/* Write the Event Log address and its size in the DTB */
+	err = arm_set_event_log_info(config_base,
+#ifdef SPD_opteed
+					log_addr,
+#endif
+					ns_addr, log_size);
+
+	/* Return Event Log address in Non-secure memory */
+	*ns_log_addr = (err < 0) ? 0UL : ns_addr;
+	return err;
+}
 #endif /* MEASURED_BOOT */
diff --git a/plat/arm/common/fconf/arm_fconf_io.c b/plat/arm/common/fconf/arm_fconf_io.c
index 26e51b2..350ecd1 100644
--- a/plat/arm/common/fconf/arm_fconf_io.c
+++ b/plat/arm/common/fconf/arm_fconf_io.c
@@ -25,6 +25,7 @@
 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},
+	[FW_CONFIG_ID] = {UUID_FW_CONFIG},
 #if !ARM_IO_IN_DTB
 	[SCP_BL2_IMAGE_ID] = {UUID_SCP_FIRMWARE_SCP_BL2},
 	[BL31_IMAGE_ID] = {UUID_EL3_RUNTIME_FIRMWARE_BL31},
@@ -49,6 +50,9 @@
 	[SOC_FW_CONTENT_CERT_ID] = {UUID_SOC_FW_CONTENT_CERT},
 	[TRUSTED_OS_FW_CONTENT_CERT_ID] = {UUID_TRUSTED_OS_FW_CONTENT_CERT},
 	[NON_TRUSTED_FW_CONTENT_CERT_ID] = {UUID_NON_TRUSTED_FW_CONTENT_CERT},
+#if defined(SPD_spmd)
+	[SIP_SP_CONTENT_CERT_ID] = {UUID_SIP_SECURE_PARTITION_CONTENT_CERT},
+#endif
 #endif /* ARM_IO_IN_DTB */
 #endif /* TRUSTED_BOARD_BOOT */
 };
@@ -70,6 +74,11 @@
 		(uintptr_t)&arm_uuid_spec[TB_FW_CONFIG_ID],
 		open_fip
 	},
+	[FW_CONFIG_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&arm_uuid_spec[FW_CONFIG_ID],
+		open_fip
+	},
 #if !ARM_IO_IN_DTB
 	[SCP_BL2_IMAGE_ID] = {
 		&fip_dev_handle,
@@ -174,6 +183,13 @@
 		(uintptr_t)&arm_uuid_spec[NON_TRUSTED_FW_CONTENT_CERT_ID],
 		open_fip
 	},
+#if defined(SPD_spmd)
+	[SIP_SP_CONTENT_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&arm_uuid_spec[SIP_SP_CONTENT_CERT_ID],
+		open_fip
+	},
+#endif
 #endif /* ARM_IO_IN_DTB */
 #endif /* TRUSTED_BOARD_BOOT */
 };
@@ -181,7 +197,7 @@
 #ifdef IMAGE_BL2
 
 #if TRUSTED_BOARD_BOOT
-#define FCONF_ARM_IO_UUID_NUMBER	U(19)
+#define FCONF_ARM_IO_UUID_NUMBER	U(20)
 #else
 #define FCONF_ARM_IO_UUID_NUMBER	U(10)
 #endif
@@ -216,6 +232,9 @@
 	{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"},
+#if defined(SPD_spmd)
+	{SIP_SP_CONTENT_CERT_ID, "sip_sp_content_cert_uuid"},
+#endif
 #endif /* TRUSTED_BOARD_BOOT */
 };
 
diff --git a/plat/arm/common/fconf/arm_fconf_sp.c b/plat/arm/common/fconf/arm_fconf_sp.c
index 1b09bc8..4459264 100644
--- a/plat/arm/common/fconf/arm_fconf_sp.c
+++ b/plat/arm/common/fconf/arm_fconf_sp.c
@@ -30,7 +30,7 @@
 	union uuid_helper_t uuid_helper;
 	unsigned int index = 0;
 	uint32_t val32;
-	const unsigned int sp_start_index = MAX_NUMBER_IDS - MAX_SP_IDS;
+	const unsigned int sp_start_index = SP_PKG1_ID;
 
 	/* As libfdt use void *, we can't avoid this cast */
 	const void *dtb = (void *)config;
@@ -45,6 +45,11 @@
 	}
 
 	fdt_for_each_subnode(sp_node, dtb, node) {
+		if (index == MAX_SP_IDS) {
+			ERROR("FCONF: Reached max number of SPs\n");
+			return -1;
+		}
+
 		err = fdt_read_uint32_array(dtb, sp_node, "uuid", 4,
 					    uuid_helper.word);
 		if (err < 0) {
@@ -87,15 +92,10 @@
 		policies[sp_start_index + index].check = open_fip;
 
 		index++;
-
-		if (index >= MAX_SP_IDS) {
-			ERROR("FCONF: reached max number of SPs\n");
-			return -1;
-		}
 	}
 
 	if ((sp_node < 0) && (sp_node != -FDT_ERR_NOTFOUND)) {
-		ERROR("%d: fdt_for_each_subnode(): %d\n", __LINE__, node);
+		ERROR("%u: fdt_for_each_subnode(): %d\n", __LINE__, node);
 		return sp_node;
 	}
 
diff --git a/plat/arm/common/fconf/fconf_sec_intr_config.c b/plat/arm/common/fconf/fconf_sec_intr_config.c
new file mode 100644
index 0000000..f28be24
--- /dev/null
+++ b/plat/arm/common/fconf/fconf_sec_intr_config.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <libfdt.h>
+#include <plat/arm/common/fconf_sec_intr_config.h>
+
+#define G0_INTR_NUM(i)		g0_intr_prop[3U * (i)]
+#define G0_INTR_PRIORITY(i)	g0_intr_prop[3U * (i) + 1]
+#define G0_INTR_CONFIG(i)	g0_intr_prop[3U * (i) + 2]
+
+#define G1S_INTR_NUM(i)		g1s_intr_prop[3U * (i)]
+#define G1S_INTR_PRIORITY(i)	g1s_intr_prop[3U * (i) + 1]
+#define G1S_INTR_CONFIG(i)	g1s_intr_prop[3U * (i) + 2]
+
+struct sec_intr_prop_t sec_intr_prop;
+
+static void print_intr_prop(interrupt_prop_t prop)
+{
+	VERBOSE("FCONF: Secure Interrupt NUM: %d, PRI: %d, TYPE: %d\n",
+		prop.intr_num, prop.intr_pri, prop.intr_cfg);
+}
+
+int fconf_populate_sec_intr_config(uintptr_t config)
+{
+	int node, err;
+	uint32_t g0_intr_count, g1s_intr_count;
+	uint32_t g0_intr_prop[SEC_INT_COUNT_MAX * 3];
+	uint32_t g1s_intr_prop[SEC_INT_COUNT_MAX * 3];
+
+	/* Necessary to work with libfdt APIs */
+	const void *hw_config_dtb = (const void *)config;
+
+	node = fdt_node_offset_by_compatible(hw_config_dtb, -1,
+						"arm,secure_interrupt_desc");
+	if (node < 0) {
+		ERROR("FCONF: Unable to locate node with %s compatible property\n",
+						"arm,secure_interrupt_desc");
+		return node;
+	}
+
+	/* Read number of Group 0 interrupts specified by platform */
+	err = fdt_read_uint32(hw_config_dtb, node, "g0_intr_cnt", &g0_intr_count);
+	if (err < 0) {
+		ERROR("FCONF: Could not locate g0s_intr_cnt property\n");
+		return err;
+	}
+
+	/* At least 1 Group 0 interrupt description has to be provided*/
+	if (g0_intr_count < 1U) {
+		ERROR("FCONF: Invalid number of Group 0 interrupts count specified\n");
+		return -1;
+	}
+
+	/* Read number of Group 1 secure interrupts specified by platform */
+	err = fdt_read_uint32(hw_config_dtb, node, "g1s_intr_cnt",
+				&g1s_intr_count);
+	if (err < 0) {
+		ERROR("FCONF: Could not locate g1s_intr_cnt property\n");
+		return err;
+	}
+
+	/* At least one Group 1 interrupt description has to be provided*/
+	if (g1s_intr_count < 1U) {
+		ERROR("FCONF: Invalid number of Group 1 secure interrupts count specified\n");
+		return -1;
+	}
+
+	/*
+	 * Check if the total number of secure interrupts described are within
+	 * the limit defined statically by the platform.
+	 */
+	if ((g0_intr_count + g1s_intr_count) > SEC_INT_COUNT_MAX) {
+		ERROR("FCONF: Total number of secure interrupts exceed limit the of %d\n",
+				SEC_INT_COUNT_MAX);
+		return -1;
+	}
+
+	sec_intr_prop.count = g0_intr_count + g1s_intr_count;
+
+	/* Read the Group 0 interrupt descriptors */
+	err = fdt_read_uint32_array(hw_config_dtb, node, "g0_intr_desc",
+				g0_intr_count * 3, g0_intr_prop);
+	if (err < 0) {
+		ERROR("FCONF: Read cell failed for 'g0s_intr_desc': %d\n", err);
+		return err;
+	}
+
+	/* Read the Group 1 secure interrupt descriptors */
+	err = fdt_read_uint32_array(hw_config_dtb, node, "g1s_intr_desc",
+				g1s_intr_count * 3, g1s_intr_prop);
+	if (err < 0) {
+		ERROR("FCONF: Read cell failed for 'g1s_intr_desc': %d\n", err);
+		return err;
+	}
+
+	/* Populate Group 0 interrupt descriptors into fconf based C struct */
+	for (uint32_t i = 0; i < g0_intr_count; i++) {
+		interrupt_prop_t sec_intr_property;
+
+		/* Secure Interrupt Group: INTR_GROUP0 i.e., 0x1 */
+		sec_intr_property.intr_grp = 1;
+		sec_intr_property.intr_num = G0_INTR_NUM(i);
+		sec_intr_property.intr_pri = G0_INTR_PRIORITY(i);
+		sec_intr_property.intr_cfg = G0_INTR_CONFIG(i);
+		sec_intr_prop.descriptor[i] = sec_intr_property;
+		print_intr_prop(sec_intr_property);
+	}
+
+	/* Populate G1 secure interrupt descriptors into fconf based C struct */
+	for (uint32_t i = 0; i < g1s_intr_count; i++) {
+		interrupt_prop_t sec_intr_property;
+
+		/* Secure Interrupt Group: INTR_GROUP1S i.e., 0x0 */
+		sec_intr_property.intr_grp = 0;
+		sec_intr_property.intr_num = G1S_INTR_NUM(i);
+		sec_intr_property.intr_pri = G1S_INTR_PRIORITY(i);
+		sec_intr_property.intr_cfg = G1S_INTR_CONFIG(i);
+		sec_intr_prop.descriptor[i + g0_intr_count] = sec_intr_property;
+		print_intr_prop(sec_intr_property);
+	}
+
+	return 0;
+}
+
+FCONF_REGISTER_POPULATOR(HW_CONFIG, sec_intr_prop, fconf_populate_sec_intr_config);
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 2904ad9..6100b78 100644
--- a/plat/arm/common/sp_min/arm_sp_min_setup.c
+++ b/plat/arm/common/sp_min/arm_sp_min_setup.c
@@ -29,10 +29,10 @@
 					MT_MEMORY | MT_RW | MT_SECURE)
 
 /*
- * Check that BL32_BASE is above ARM_TB_FW_CONFIG_LIMIT. The reserved page
+ * Check that BL32_BASE is above ARM_FW_CONFIG_LIMIT. The reserved page
  * is required for SOC_FW_CONFIG/TOS_FW_CONFIG passed from BL2.
  */
-CASSERT(BL32_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_bl32_base_overflows);
+CASSERT(BL32_BASE >= ARM_FW_CONFIG_LIMIT, assert_bl32_base_overflows);
 
 /*******************************************************************************
  * Return a pointer to the 'entry_point_info' structure of the next image for the
diff --git a/plat/arm/css/sgi/sgi-common.mk b/plat/arm/css/sgi/sgi-common.mk
index 2504581..6b9e0cd 100644
--- a/plat/arm/css/sgi/sgi-common.mk
+++ b/plat/arm/css/sgi/sgi-common.mk
@@ -23,7 +23,7 @@
 PLAT_INCLUDES		+=	-I${CSS_ENT_BASE}/include
 
 # GIC-600 configuration
-GICV3_IMPL			:=	GIC600
+GICV3_SUPPORT_GIC600	:=	1
 
 # Include GICv3 driver files
 include drivers/arm/gic/v3/gicv3.mk
diff --git a/plat/arm/css/sgi/sgi_plat.c b/plat/arm/css/sgi/sgi_plat.c
index b611eaf..a2117f6 100644
--- a/plat/arm/css/sgi/sgi_plat.c
+++ b/plat/arm/css/sgi/sgi_plat.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
  */
@@ -15,7 +15,10 @@
 #include <plat/common/platform.h>
 #include <drivers/arm/sbsa.h>
 #include <sgi_base_platform_def.h>
+
+#if SPM_MM
 #include <services/spm_mm_partition.h>
+#endif
 
 #define SGI_MAP_FLASH0_RO	MAP_REGION_FLAT(V2M_FLASH0_BASE,\
 						V2M_FLASH0_SIZE,	\
diff --git a/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts b/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts
index d481018..54b2423 100644
--- a/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts
+++ b/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,7 +8,7 @@
 
 / {
 	/* Platform Config */
-	plat_arm_bl2 {
+	tb_fw-config {
 		compatible = "arm,tb_fw";
 		hw_config_addr = <0x0 0x83000000>;
 		hw_config_max_size = <0x01000000>;
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 8be0b34..2d8e677 100644
--- a/plat/arm/css/sgm/include/sgm_base_platform_def.h
+++ b/plat/arm/css/sgm/include/sgm_base_platform_def.h
@@ -138,7 +138,7 @@
  * BL31 is loaded over the top.
  */
 #define PLAT_CSS_MAX_SCP_BL2_SIZE \
-	((SCP_BL2_LIMIT - ARM_TB_FW_CONFIG_LIMIT) & ~PAGE_SIZE_MASK)
+	((SCP_BL2_LIMIT - ARM_FW_CONFIG_LIMIT) & ~PAGE_SIZE_MASK)
 
 #define PLAT_CSS_MAX_SCP_BL2U_SIZE	PLAT_CSS_MAX_SCP_BL2_SIZE
 
diff --git a/plat/arm/css/sgm/sgm-common.mk b/plat/arm/css/sgm/sgm-common.mk
index 60e9fb2..5b954f8 100644
--- a/plat/arm/css/sgm/sgm-common.mk
+++ b/plat/arm/css/sgm/sgm-common.mk
@@ -23,7 +23,7 @@
 INTERCONNECT_SOURCES	:=	${CSS_SGM_BASE}/sgm_interconnect.c
 
 # GIC-600 configuration
-GICV3_IMPL		:=	GIC600
+GICV3_SUPPORT_GIC600	:=	1
 
 # Include GICv3 driver files
 include drivers/arm/gic/v3/gicv3.mk
diff --git a/plat/brcm/board/common/board_common.mk b/plat/brcm/board/common/board_common.mk
index 1795ce7..3069f91 100644
--- a/plat/brcm/board/common/board_common.mk
+++ b/plat/brcm/board/common/board_common.mk
@@ -133,6 +133,12 @@
 				plat/brcm/board/common/sbl_util.c \
 				drivers/arm/sp805/sp805.c
 
+# Add RNG driver
+DRIVER_RNG_ENABLE := 1
+ifeq (${DRIVER_RNG_ENABLE},1)
+PLAT_BL_COMMON_SOURCES	+=	drivers/brcm/rng.c
+endif
+
 # Add eMMC driver
 ifeq (${DRIVER_EMMC_ENABLE},1)
 $(eval $(call add_define,DRIVER_EMMC_ENABLE))
@@ -213,7 +219,8 @@
 AUTH_SOURCES	+= 	drivers/auth/auth_mod.c \
 			drivers/auth/crypto_mod.c \
 			drivers/auth/img_parser_mod.c \
-			drivers/auth/tbbr/tbbr_cot.c
+			drivers/auth/tbbr/tbbr_cot_common.c \
+			drivers/auth/tbbr/tbbr_cot_bl2.c
 
 BL2_SOURCES	+=	${AUTH_SOURCES}
 
diff --git a/plat/brcm/board/stingray/include/sr_def.h b/plat/brcm/board/stingray/include/sr_def.h
index ac3ee78..be0dee1 100644
--- a/plat/brcm/board/stingray/include/sr_def.h
+++ b/plat/brcm/board/stingray/include/sr_def.h
@@ -292,6 +292,11 @@
 #define ICFG_PKA_MEM_PWR_CTRL__ISO		BIT(8)
 
 /*******************************************************************************
+ * RNG constants
+ ******************************************************************************/
+#define RNG_BASE_ADDR			0x68b20000
+
+/*******************************************************************************
  * Trusted Watchdog constants
  ******************************************************************************/
 #define ARM_SP805_TWDG_BASE		0x68b30000
diff --git a/plat/brcm/board/stingray/src/bl31_setup.c b/plat/brcm/board/stingray/src/bl31_setup.c
index d947551..a2a274d 100644
--- a/plat/brcm/board/stingray/src/bl31_setup.c
+++ b/plat/brcm/board/stingray/src/bl31_setup.c
@@ -923,7 +923,7 @@
 
 	scp_image_info.image_base = PRELOADED_SCP_BASE;
 	scp_image_info.image_size = PRELOADED_SCP_SIZE;
-	bcm_bl2_plat_handle_scp_bl2(&scp_image_info);
+	plat_bcm_bl2_plat_handle_scp_bl2(&scp_image_info);
 #endif
 	/*
 	 * In BL31, logs are saved to DDR and we have much larger space to
diff --git a/plat/common/aarch64/plat_common.c b/plat/common/aarch64/plat_common.c
index 63871d9..b8a4d01 100644
--- a/plat/common/aarch64/plat_common.c
+++ b/plat/common/aarch64/plat_common.c
@@ -11,6 +11,7 @@
 #if RAS_EXTENSION
 #include <lib/extensions/ras.h>
 #endif
+#include <lib/extensions/twed.h>
 #include <lib/xlat_tables/xlat_mmu_helpers.h>
 #include <plat/common/platform.h>
 
@@ -20,6 +21,7 @@
  * platforms but may also be overridden by a platform if required.
  */
 #pragma weak bl31_plat_runtime_setup
+#pragma weak plat_arm_set_twedel_scr_el3
 
 #if SDEI_SUPPORT
 #pragma weak plat_sdei_handle_masked_trigger
@@ -100,3 +102,16 @@
 #endif
 	panic();
 }
+
+/*******************************************************************************
+ * In v8.6+ platforms with delayed trapping of WFE this hook sets the delay. It
+ * is a weak function definition so can be overridden depending on the
+ * requirements of a platform.  The only hook provided is for the TWED fields
+ * in SCR_EL3, the TWED fields in HCR_EL2, SCTLR_EL2, and SCTLR_EL1 should be
+ * configured as needed in lower exception levels.
+ ******************************************************************************/
+
+uint32_t plat_arm_set_twedel_scr_el3(void)
+{
+	return TWED_DISABLED;
+}
diff --git a/plat/common/aarch64/platform_mp_stack.S b/plat/common/aarch64/platform_mp_stack.S
index f9780e8..ee0dbb4 100644
--- a/plat/common/aarch64/platform_mp_stack.S
+++ b/plat/common/aarch64/platform_mp_stack.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
  */
@@ -32,9 +32,42 @@
 	 * -----------------------------------------------------
 	 */
 func plat_get_my_stack
-	mov	x10, x30 // lr
+#if (defined(IMAGE_BL31) && RECLAIM_INIT_CODE)
+#if (PLATFORM_CORE_COUNT == 1)
+	/* Single CPU */
+	adrp	x0, __PRIMARY_STACK__
+	add	x0, x0, :lo12:__PRIMARY_STACK__
+	ret
+#else
+	mov	x10, x30
+	bl	plat_my_core_pos
+	cbnz	x0, 2f
+
+	/* Primary CPU */
+	adrp	x0, __PRIMARY_STACK__
+	add	x0, x0, :lo12:__PRIMARY_STACK__
+	ret	x10
+
+	/* Secondary CPU */
+2:	sub	x0, x0, #(PLATFORM_CORE_COUNT - 1)
+	adrp	x1, __STACKS_END__
+	adrp	x2, __STACK_SIZE__
+	add	x1, x1, :lo12:__STACKS_END__
+	add	x2, x2, :lo12:__STACK_SIZE__
+
+	madd	x0, x0, x2, x1
+	bic	x0, x0, #(CACHE_WRITEBACK_GRANULE - 1)
+	ret	x10
+#endif
+	/* Prevent linker from removal of stack section */
+	.quad	platform_normal_stacks
+
+#else /* !(IMAGE_BL31 && RECLAIM_INIT_CODE) */
+	mov	x10, x30
 	get_my_mp_stack platform_normal_stacks, PLATFORM_STACK_SIZE
 	ret	x10
+
+#endif /* IMAGE_BL31 && RECLAIM_INIT_CODE */
 endfunc plat_get_my_stack
 
 	/* -----------------------------------------------------
@@ -45,14 +78,14 @@
 	 * -----------------------------------------------------
 	 */
 func plat_set_my_stack
-	mov	x9, x30 // lr
+	mov	x9, x30
 	bl 	plat_get_my_stack
 	mov	sp, x0
 	ret	x9
 endfunc plat_set_my_stack
 
 	/* -----------------------------------------------------
-	 * Per-cpu stacks in normal memory. Each cpu gets a
+	 * Per-CPU stacks in normal memory. Each CPU gets a
 	 * stack of PLATFORM_STACK_SIZE bytes.
 	 * -----------------------------------------------------
 	 */
diff --git a/plat/common/plat_bl1_common.c b/plat/common/plat_bl1_common.c
index 5733781..2baa29a 100644
--- a/plat/common/plat_bl1_common.c
+++ b/plat/common/plat_bl1_common.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
  */
@@ -27,7 +27,9 @@
 #pragma weak bl1_plat_fwu_done
 #pragma weak bl1_plat_handle_pre_image_load
 #pragma weak bl1_plat_handle_post_image_load
-
+#if MEASURED_BOOT
+#pragma weak bl1_plat_set_bl2_hash
+#endif
 
 unsigned int bl1_plat_get_next_image_id(void)
 {
@@ -116,3 +118,12 @@
 		(void *) bl2_tzram_layout);
 	return 0;
 }
+
+#if MEASURED_BOOT
+/*
+ * Calculates and writes BL2 hash data to TB_FW_CONFIG DTB.
+ */
+void bl1_plat_set_bl2_hash(const image_desc_t *image_desc)
+{
+}
+#endif
diff --git a/plat/common/plat_bl_common.c b/plat/common/plat_bl_common.c
index d38fc6f..89b77ba 100644
--- a/plat/common/plat_bl_common.c
+++ b/plat/common/plat_bl_common.c
@@ -11,6 +11,7 @@
 #include <common/debug.h>
 #include <lib/xlat_tables/xlat_tables_compat.h>
 #include <plat/common/platform.h>
+#include <services/arm_arch_svc.h>
 #include <smccc_helpers.h>
 #include <tools_share/firmware_encrypted.h>
 
@@ -25,6 +26,7 @@
 #pragma weak bl2_plat_handle_post_image_load
 #pragma weak plat_try_next_boot_source
 #pragma weak plat_get_enc_key_info
+#pragma weak plat_is_smccc_feature_available
 #pragma weak plat_get_soc_version
 #pragma weak plat_get_soc_revision
 
@@ -38,6 +40,11 @@
 	return SMC_ARCH_CALL_NOT_SUPPORTED;
 }
 
+int32_t plat_is_smccc_feature_available(u_register_t fid __unused)
+{
+	return SMC_ARCH_CALL_NOT_SUPPORTED;
+}
+
 void bl2_el3_plat_prepare_exit(void)
 {
 }
diff --git a/plat/common/plat_spmd_manifest.c b/plat/common/plat_spmd_manifest.c
index 109b001..e65980b 100644
--- a/plat/common/plat_spmd_manifest.c
+++ b/plat/common/plat_spmd_manifest.c
@@ -31,14 +31,14 @@
 
 	rc = fdt_read_uint32(fdt, node, "maj_ver", &attr->major_version);
 	if (rc != 0) {
-		ERROR("Missing SPCI %s version in SPM Core manifest.\n",
+		ERROR("Missing FFA %s version in SPM Core manifest.\n",
 			"major");
 		return rc;
 	}
 
 	rc = fdt_read_uint32(fdt, node, "min_ver", &attr->minor_version);
 	if (rc != 0) {
-		ERROR("Missing SPCI %s version in SPM Core manifest.\n",
+		ERROR("Missing FFA %s version in SPM Core manifest.\n",
 			"minor");
 		return rc;
 	}
@@ -128,7 +128,13 @@
 	 */
 	pm_base = (uintptr_t)pm_addr;
 	pm_base_align = page_align(pm_base, UP);
-	mapped_size = pm_base_align - pm_base;
+
+	if (pm_base == pm_base_align) {
+		/* Page aligned */
+		mapped_size = PAGE_SIZE;
+	} else {
+		mapped_size = pm_base_align - pm_base;
+	}
 
 	/* Check space within the page at least maps the FDT header */
 	if (mapped_size < sizeof(struct fdt_header)) {
@@ -163,7 +169,7 @@
 	VERBOSE("Reading SPM Core manifest at address %p\n", pm_addr);
 
 	rc = fdt_node_offset_by_compatible(pm_addr, -1,
-				"arm,spci-core-manifest-1.0");
+				"arm,ffa-core-manifest-1.0");
 	if (rc < 0) {
 		ERROR("Unrecognized SPM Core manifest\n");
 		goto exit_unmap;
diff --git a/plat/hisilicon/hikey/platform.mk b/plat/hisilicon/hikey/platform.mk
index fbf7432..18197cf 100644
--- a/plat/hisilicon/hikey/platform.mk
+++ b/plat/hisilicon/hikey/platform.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
 #
@@ -126,17 +126,19 @@
 AUTH_SOURCES		:=	drivers/auth/auth_mod.c			\
 				drivers/auth/crypto_mod.c		\
 				drivers/auth/img_parser_mod.c		\
-				drivers/auth/tbbr/tbbr_cot.c
+				drivers/auth/tbbr/tbbr_cot_common.c
 
 BL1_SOURCES		+=	${AUTH_SOURCES}				\
 				plat/common/tbbr/plat_tbbr.c		\
 				plat/hisilicon/hikey/hikey_tbbr.c	\
-				plat/hisilicon/hikey/hikey_rotpk.S
+				plat/hisilicon/hikey/hikey_rotpk.S	\
+				drivers/auth/tbbr/tbbr_cot_bl1.c
 
 BL2_SOURCES		+=	${AUTH_SOURCES}				\
 				plat/common/tbbr/plat_tbbr.c		\
 				plat/hisilicon/hikey/hikey_tbbr.c	\
-				plat/hisilicon/hikey/hikey_rotpk.S
+				plat/hisilicon/hikey/hikey_rotpk.S	\
+				drivers/auth/tbbr/tbbr_cot_bl2.c
 
 ROT_KEY		=	$(BUILD_PLAT)/rot_key.pem
 ROTPK_HASH		=	$(BUILD_PLAT)/rotpk_sha256.bin
diff --git a/plat/hisilicon/hikey960/platform.mk b/plat/hisilicon/hikey960/platform.mk
index 8ebabeb..fc2c209 100644
--- a/plat/hisilicon/hikey960/platform.mk
+++ b/plat/hisilicon/hikey960/platform.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
 #
@@ -118,17 +118,19 @@
 AUTH_SOURCES		:=	drivers/auth/auth_mod.c			\
 				drivers/auth/crypto_mod.c		\
 				drivers/auth/img_parser_mod.c		\
-				drivers/auth/tbbr/tbbr_cot.c
+				drivers/auth/tbbr/tbbr_cot_common.c
 
 BL1_SOURCES		+=	${AUTH_SOURCES}				\
 				plat/common/tbbr/plat_tbbr.c		\
 				plat/hisilicon/hikey960/hikey960_tbbr.c	\
-				plat/hisilicon/hikey960/hikey960_rotpk.S
+				plat/hisilicon/hikey960/hikey960_rotpk.S \
+				drivers/auth/tbbr/tbbr_cot_bl1.c
 
 BL2_SOURCES		+=	${AUTH_SOURCES}				\
 				plat/common/tbbr/plat_tbbr.c		\
 				plat/hisilicon/hikey960/hikey960_tbbr.c	\
-				plat/hisilicon/hikey960/hikey960_rotpk.S
+				plat/hisilicon/hikey960/hikey960_rotpk.S \
+				drivers/auth/tbbr/tbbr_cot_bl2.c
 
 ROT_KEY		=	$(BUILD_PLAT)/rot_key.pem
 ROTPK_HASH		=	$(BUILD_PLAT)/rotpk_sha256.bin
diff --git a/plat/imx/common/imx_ehf.c b/plat/imx/common/imx_ehf.c
new file mode 100644
index 0000000..a9396cd
--- /dev/null
+++ b/plat/imx/common/imx_ehf.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <bl31/ehf.h>
+
+#include <platform_def.h>
+
+ehf_pri_desc_t imx_exceptions[] = {
+#if SDEI_SUPPORT
+	/* Critical priority SDEI */
+	EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SDEI_CRITICAL_PRI),
+
+	/* Normal priority SDEI */
+	EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SDEI_NORMAL_PRI),
+#endif
+};
+
+/* Plug in ARM exceptions to Exception Handling Framework. */
+EHF_REGISTER_PRIORITIES(imx_exceptions, ARRAY_SIZE(imx_exceptions), PLAT_PRI_BITS);
diff --git a/plat/imx/common/imx_sdei.c b/plat/imx/common/imx_sdei.c
new file mode 100644
index 0000000..4b6033f
--- /dev/null
+++ b/plat/imx/common/imx_sdei.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* SDEI configuration for ARM platforms */
+
+#include <bl31/ehf.h>
+#include <common/debug.h>
+#include <services/sdei.h>
+#include <lib/utils_def.h>
+
+#include <platform_def.h>
+
+/* Private event mappings */
+static sdei_ev_map_t imx_sdei_private[] = {
+	SDEI_DEFINE_EVENT_0(PLAT_SDEI_SGI_PRIVATE),
+};
+
+/* Shared event mappings */
+static sdei_ev_map_t imx_sdei_shared[] = {
+};
+
+void plat_sdei_setup(void)
+{
+	INFO("SDEI platform setup\n");
+}
+
+/* Export ARM SDEI events */
+REGISTER_SDEI_MAP(imx_sdei_private, imx_sdei_shared);
diff --git a/plat/imx/common/imx_sip_handler.c b/plat/imx/common/imx_sip_handler.c
index 62048b6..f9f5577 100644
--- a/plat/imx/common/imx_sip_handler.c
+++ b/plat/imx/common/imx_sip_handler.c
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <arch.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <services/std_svc.h>
@@ -12,6 +13,7 @@
 #include <common/debug.h>
 #include <common/runtime_svc.h>
 #include <imx_sip_svc.h>
+#include <lib/el3_runtime/context_mgmt.h>
 #include <sci/sci.h>
 
 #if defined(PLAT_imx8qm) || defined(PLAT_imx8qx)
@@ -185,3 +187,37 @@
 
 	return ret;
 }
+
+int imx_kernel_entry_handler(uint32_t smc_fid,
+		u_register_t x1,
+		u_register_t x2,
+		u_register_t x3,
+		u_register_t x4)
+{
+	static entry_point_info_t bl33_image_ep_info;
+	entry_point_info_t *next_image_info;
+	unsigned int mode;
+
+	if (x1 < (PLAT_NS_IMAGE_OFFSET & 0xF0000000))
+		return SMC_UNK;
+
+	mode = MODE32_svc;
+
+	next_image_info = &bl33_image_ep_info;
+
+	next_image_info->pc = x1;
+
+	next_image_info->spsr = SPSR_MODE32(mode, SPSR_T_ARM, SPSR_E_LITTLE,
+			(DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT));
+
+	next_image_info->args.arg0 = 0;
+	next_image_info->args.arg1 = 0;
+	next_image_info->args.arg2 = x3;
+
+	SET_SECURITY_STATE(next_image_info->h.attr, NON_SECURE);
+
+	cm_init_my_context(next_image_info);
+	cm_prepare_el3_exit(NON_SECURE);
+
+	return 0;
+}
diff --git a/plat/imx/common/imx_sip_svc.c b/plat/imx/common/imx_sip_svc.c
index 4893b9f..20e1479 100644
--- a/plat/imx/common/imx_sip_svc.c
+++ b/plat/imx/common/imx_sip_svc.c
@@ -26,6 +26,9 @@
 			u_register_t flags)
 {
 	switch (smc_fid) {
+	case IMX_SIP_AARCH32:
+		SMC_RET1(handle, imx_kernel_entry_handler(smc_fid, x1, x2, x3, x4));
+		break;
 #if defined(PLAT_imx8mq)
 	case IMX_SIP_GET_SOC_INFO:
 		SMC_RET1(handle, imx_soc_info_handler(smc_fid, x1, x2, x3));
diff --git a/plat/imx/common/include/imx_sip_svc.h b/plat/imx/common/include/imx_sip_svc.h
index 5898f7a..0a2d750 100644
--- a/plat/imx/common/include/imx_sip_svc.h
+++ b/plat/imx/common/include/imx_sip_svc.h
@@ -28,6 +28,11 @@
 
 #define IMX_SIP_MISC_SET_TEMP		0xC200000C
 
+#define IMX_SIP_AARCH32			0xC20000FD
+
+int imx_kernel_entry_handler(uint32_t smc_fid, u_register_t x1,
+			     u_register_t x2, u_register_t x3,
+			     u_register_t x4);
 #if defined(PLAT_imx8mq)
 int imx_soc_info_handler(uint32_t smc_fid, u_register_t x1,
 			 u_register_t x2, u_register_t x3);
diff --git a/plat/imx/common/plat_imx8_gic.c b/plat/imx/common/plat_imx8_gic.c
index afb9d1f..150e81e 100644
--- a/plat/imx/common/plat_imx8_gic.c
+++ b/plat/imx/common/plat_imx8_gic.c
@@ -22,6 +22,10 @@
 static const interrupt_prop_t g01s_interrupt_props[] = {
 	INTR_PROP_DESC(8, GIC_HIGHEST_SEC_PRIORITY,
 		       INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+#if SDEI_SUPPORT
+	INTR_PROP_DESC(PLAT_SDEI_SGI_PRIVATE, PLAT_SDEI_NORMAL_PRI,
+		       INTR_GROUP0, GIC_INTR_CFG_LEVEL),
+#endif
 };
 
 static unsigned int plat_imx_mpidr_to_core_pos(unsigned long mpidr)
diff --git a/plat/imx/imx7/common/imx7.mk b/plat/imx/imx7/common/imx7.mk
index 849ddcd..3a95772 100644
--- a/plat/imx/imx7/common/imx7.mk
+++ b/plat/imx/imx7/common/imx7.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
 #
@@ -58,12 +58,13 @@
 AUTH_SOURCES	:=	drivers/auth/auth_mod.c			\
 			drivers/auth/crypto_mod.c		\
 			drivers/auth/img_parser_mod.c		\
-			drivers/auth/tbbr/tbbr_cot.c
+			drivers/auth/tbbr/tbbr_cot_common.c
 
 BL2_SOURCES		+=	${AUTH_SOURCES}					\
 				plat/common/tbbr/plat_tbbr.c			\
 				plat/imx/imx7/common/imx7_trusted_boot.c	\
-				plat/imx/imx7/common/imx7_rotpk.S
+				plat/imx/imx7/common/imx7_rotpk.S		\
+				drivers/auth/tbbr/tbbr_cot_bl2.c
 
 ROT_KEY             = $(BUILD_PLAT)/rot_key.pem
 ROTPK_HASH          = $(BUILD_PLAT)/rotpk_sha256.bin
diff --git a/plat/imx/imx8m/imx8mm/include/gpc_reg.h b/plat/imx/imx8m/imx8mm/include/gpc_reg.h
new file mode 100644
index 0000000..c697af2
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/include/gpc_reg.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPC_REG_H
+#define GPC_REG_H
+
+#define LPCR_A53_BSC			0x0
+#define LPCR_A53_BSC2			0x108
+#define LPCR_A53_AD			0x4
+#define LPCR_M4				0x8
+#define SLPCR				0x14
+#define MST_CPU_MAPPING			0x18
+#define MLPCR				0x20
+#define PGC_ACK_SEL_A53			0x24
+#define IMR1_CORE0_A53			0x30
+#define IMR1_CORE1_A53			0x40
+#define IMR1_CORE2_A53			0x1C0
+#define IMR1_CORE3_A53			0x1D0
+#define IMR1_CORE0_M4			0x50
+#define SLT0_CFG			0xB0
+#define GPC_PU_PWRHSK			0x1FC
+#define PGC_CPU_0_1_MAPPING		0xEC
+#define CPU_PGC_UP_TRG			0xF0
+#define PU_PGC_UP_TRG			0xF8
+#define CPU_PGC_DN_TRG			0xFC
+#define PU_PGC_DN_TRG			0x104
+#define LPS_CPU1			0x114
+#define A53_CORE0_PGC			0x800
+#define A53_PLAT_PGC			0x900
+#define PLAT_PGC_PCR			0x900
+#define NOC_PGC_PCR			0xa40
+#define PGC_SCU_TIMING			0x910
+
+#define MASK_DSM_TRIGGER_A53		BIT(31)
+#define IRQ_SRC_A53_WUP			BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT		30
+#define IRQ_SRC_C1			BIT(29)
+#define IRQ_SRC_C0			BIT(28)
+#define IRQ_SRC_C3			BIT(23)
+#define IRQ_SRC_C2			BIT(22)
+#define CPU_CLOCK_ON_LPM		BIT(14)
+#define A53_CLK_ON_LPM			BIT(14)
+#define MASTER0_LPM_HSK			BIT(6)
+#define MASTER1_LPM_HSK			BIT(7)
+#define MASTER2_LPM_HSK			BIT(8)
+
+#define L2PGE				BIT(31)
+#define EN_L2_WFI_PDN			BIT(5)
+#define EN_PLAT_PDN			BIT(4)
+
+#define SLPCR_EN_DSM			BIT(31)
+#define SLPCR_RBC_EN			BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE	BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE	BIT(16)
+#define SLPCR_VSTBY			BIT(2)
+#define SLPCR_SBYOS			BIT(1)
+#define SLPCR_BYPASS_PMIC_READY		BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT		24
+#define SLPCR_STBY_COUNT_SHFT		3
+
+#define A53_DUMMY_PDN_ACK		BIT(15)
+#define A53_DUMMY_PUP_ACK		BIT(31)
+#define A53_PLAT_PDN_ACK		BIT(2)
+#define A53_PLAT_PUP_ACK		BIT(18)
+#define NOC_PDN_SLT_CTRL		BIT(10)
+#define NOC_PUP_SLT_CTRL		BIT(11)
+#define NOC_PGC_PDN_ACK			BIT(3)
+#define NOC_PGC_PUP_ACK			BIT(19)
+
+#define PLAT_PUP_SLT_CTRL		BIT(9)
+#define PLAT_PDN_SLT_CTRL		BIT(8)
+
+#define SLT_PLAT_PDN			BIT(8)
+#define SLT_PLAT_PUP			BIT(9)
+
+#define MASTER1_MAPPING			BIT(1)
+#define MASTER2_MAPPING			BIT(2)
+
+#define MIPI_PWR_REQ			BIT(0)
+#define PCIE_PWR_REQ			BIT(1)
+#define OTG1_PWR_REQ			BIT(2)
+#define OTG2_PWR_REQ			BIT(3)
+#define HSIOMIX_PWR_REQ			BIT(4)
+#define DDRMIX_PWR_REQ			BIT(5)
+#define GPU2D_PWR_REQ			BIT(6)
+#define GPUMIX_PWR_REQ			BIT(7)
+#define VPUMIX_PWR_REQ			BIT(8)
+#define GPU3D_PWR_REQ			BIT(9)
+#define DISPMIX_PWR_REQ			BIT(10)
+#define VPU_G1_PWR_REQ			BIT(11)
+#define VPU_G2_PWR_REQ			BIT(12)
+#define VPU_H1_PWR_REQ			BIT(13)
+
+#define DDRMIX_ADB400_SYNC		BIT(2)
+#define HSIOMIX_ADB400_SYNC		(0x3 << 5)
+#define DISPMIX_ADB400_SYNC		BIT(7)
+#define VPUMIX_ADB400_SYNC		BIT(8)
+#define GPU3D_ADB400_SYNC		BIT(9)
+#define GPU2D_ADB400_SYNC		BIT(10)
+#define GPUMIX_ADB400_SYNC		BIT(11)
+#define DDRMIX_ADB400_ACK		BIT(20)
+#define HSIOMIX_ADB400_ACK		(0x3 << 23)
+#define DISPMIX_ADB400_ACK		BIT(25)
+#define VPUMIX_ADB400_ACK		BIT(26)
+#define GPU3D_ADB400_ACK		BIT(27)
+#define GPU2D_ADB400_ACK		BIT(28)
+#define GPUMIX_ADB400_ACK		BIT(29)
+
+#define MIPI_PGC			0xc00
+#define PCIE_PGC			0xc40
+#define OTG1_PGC			0xc80
+#define OTG2_PGC			0xcc0
+#define HSIOMIX_PGC			0xd00
+#define DDRMIX_PGC			0xd40
+#define GPU2D_PGC			0xd80
+#define GPUMIX_PGC			0xdc0
+#define VPUMIX_PGC			0xe00
+#define GPU3D_PGC			0xe40
+#define DISPMIX_PGC			0xe80
+#define VPU_G1_PGC			0xec0
+#define VPU_G2_PGC			0xf00
+#define VPU_H1_PGC			0xf40
+
+#endif /* GPC_REG_H */
diff --git a/plat/imx/imx8m/imx8mm/include/platform_def.h b/plat/imx/imx8m/imx8mm/include/platform_def.h
index f25ceb0..1041459 100644
--- a/plat/imx/imx8m/imx8mm/include/platform_def.h
+++ b/plat/imx/imx8m/imx8mm/include/platform_def.h
@@ -29,6 +29,11 @@
 #define PLAT_WAIT_RET_STATE		U(1)
 #define PLAT_STOP_OFF_STATE		U(3)
 
+#define PLAT_PRI_BITS			U(3)
+#define PLAT_SDEI_CRITICAL_PRI		0x10
+#define PLAT_SDEI_NORMAL_PRI		0x20
+#define PLAT_SDEI_SGI_PRIVATE		U(9)
+
 #define BL31_BASE			U(0x920000)
 #define BL31_LIMIT			U(0x940000)
 
diff --git a/plat/imx/imx8m/imx8mm/platform.mk b/plat/imx/imx8m/imx8mm/platform.mk
index 3ead7b0..ac636fa 100644
--- a/plat/imx/imx8m/imx8mm/platform.mk
+++ b/plat/imx/imx8m/imx8mm/platform.mk
@@ -29,6 +29,8 @@
 				plat/imx/common/imx_sip_handler.c		\
 				plat/imx/common/imx_sip_svc.c			\
 				plat/imx/common/imx_uart_console.S		\
+				plat/imx/common/imx_ehf.c                       \
+				plat/imx/common/imx_sdei.c                      \
 				lib/xlat_tables/aarch64/xlat_tables.c		\
 				lib/xlat_tables/xlat_tables_common.c		\
 				lib/cpus/aarch64/cortex_a53.S			\
@@ -53,3 +55,6 @@
 
 IMX_BOOT_UART_BASE	?=	0x30890000
 $(eval $(call add_define,IMX_BOOT_UART_BASE))
+
+EL3_EXCEPTION_HANDLING := 1
+SDEI_SUPPORT := 1
diff --git a/plat/imx/imx8m/imx8mn/gpc.c b/plat/imx/imx8m/imx8mn/gpc.c
new file mode 100644
index 0000000..37d4226
--- /dev/null
+++ b/plat/imx/imx8m/imx8mn/gpc.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2019-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <lib/smccc.h>
+#include <services/std_svc.h>
+
+#include <gpc.h>
+#include <imx_sip_svc.h>
+#include <platform_def.h>
+
+#define CCGR(x)		(0x4000 + (x) * 0x10)
+
+void imx_gpc_init(void)
+{
+	unsigned int val;
+	int i;
+
+	/* mask all the wakeup irq by default */
+	for (i = 0; i < 4; i++) {
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0);
+	}
+
+	val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+	/* use GIC wake_request to wakeup C0~C3 from LPM */
+	val |= CORE_WKUP_FROM_GIC;
+	/* clear the MASTER0 LPM handshake */
+	val &= ~MASTER0_LPM_HSK;
+	mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+
+	/* clear MASTER1 & MASTER2 mapping in CPU0(A53) */
+	mmio_clrbits_32(IMX_GPC_BASE + MST_CPU_MAPPING, (MASTER1_MAPPING |
+		MASTER2_MAPPING));
+
+	/* set all mix/PU in A53 domain */
+	mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0xffff);
+
+	/*
+	 * Set the CORE & SCU power up timing:
+	 * SW = 0x1, SW2ISO = 0x1;
+	 * the CPU CORE and SCU power up timming counter
+	 * is drived  by 32K OSC, each domain's power up
+	 * latency is (SW + SW2ISO) / 32768
+	 */
+	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(0) + 0x4, 0x401);
+	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(1) + 0x4, 0x401);
+	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(2) + 0x4, 0x401);
+	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(3) + 0x4, 0x401);
+	mmio_write_32(IMX_GPC_BASE + PLAT_PGC_PCR + 0x4, 0x401);
+	mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING,
+		      (0x59 << TMC_TMR_SHIFT) | 0x5B | (0x2 << TRC1_TMC_SHIFT));
+
+	/* set DUMMY PDN/PUP ACK by default for A53 domain */
+	mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53,
+		      A53_DUMMY_PUP_ACK | A53_DUMMY_PDN_ACK);
+
+	/* clear DSM by default */
+	val = mmio_read_32(IMX_GPC_BASE + SLPCR);
+	val &= ~SLPCR_EN_DSM;
+	/* enable the fast wakeup wait mode */
+	val |= SLPCR_A53_FASTWUP_WAIT_MODE;
+	/* clear the RBC */
+	val &= ~(0x3f << SLPCR_RBC_COUNT_SHIFT);
+	/* set the STBY_COUNT to 0x5, (128 * 30)us */
+	val &= ~(0x7 << SLPCR_STBY_COUNT_SHFT);
+	val |= (0x5 << SLPCR_STBY_COUNT_SHFT);
+	mmio_write_32(IMX_GPC_BASE + SLPCR, val);
+
+	/*
+	 * USB PHY power up needs to make sure RESET bit in SRC is clear,
+	 * otherwise, the PU power up bit in GPC will NOT self-cleared.
+	 * only need to do it once.
+	 */
+	mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1);
+
+	/* enable all the power domain by default */
+	for (i = 0; i < 103; i++)
+		mmio_write_32(IMX_CCM_BASE + CCGR(i), 0x3);
+	mmio_write_32(IMX_GPC_BASE + PU_PGC_UP_TRG, 0x485);
+}
diff --git a/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c b/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c
new file mode 100644
index 0000000..d4705ee
--- /dev/null
+++ b/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2019-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <context.h>
+#include <drivers/arm/tzc380.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <gpc.h>
+#include <imx_aipstz.h>
+#include <imx_uart.h>
+#include <imx_rdc.h>
+#include <imx8m_caam.h>
+#include <platform_def.h>
+#include <plat_imx8.h>
+
+static const mmap_region_t imx_mmap[] = {
+	GIC_MAP, AIPS_MAP, OCRAM_S_MAP, DDRC_MAP, {0},
+};
+
+static const struct aipstz_cfg aipstz[] = {
+	{IMX_AIPSTZ1, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{IMX_AIPSTZ2, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{IMX_AIPSTZ3, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{IMX_AIPSTZ4, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{0},
+};
+
+static const struct imx_rdc_cfg rdc[] = {
+	/* Master domain assignment */
+	RDC_MDAn(0x1, DID1),
+
+	/* peripherals domain permission */
+
+	/* memory region */
+	RDC_MEM_REGIONn(16, 0x0, 0x0, 0xff),
+	RDC_MEM_REGIONn(17, 0x0, 0x0, 0xff),
+	RDC_MEM_REGIONn(18, 0x0, 0x0, 0xff),
+
+	/* Sentinel */
+	{0},
+};
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/* get SPSR for BL33 entry */
+static uint32_t get_spsr_for_bl33_entry(void)
+{
+	unsigned long el_status;
+	unsigned long mode;
+	uint32_t spsr;
+
+	/* figure out what mode we enter the non-secure world */
+	el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+	el_status &= ID_AA64PFR0_ELX_MASK;
+
+	mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+	spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+	return spsr;
+}
+
+static void bl31_tzc380_setup(void)
+{
+	unsigned int val;
+
+	val = mmio_read_32(IMX_IOMUX_GPR_BASE + 0x28);
+	if ((val & GPR_TZASC_EN) != GPR_TZASC_EN)
+		return;
+
+	tzc380_init(IMX_TZASC_BASE);
+
+	/*
+	 * Need to substact offset 0x40000000 from CPU address when
+	 * programming tzasc region for i.mx8mn.
+	 */
+
+	/* Enable 1G-5G S/NS RW */
+	tzc380_configure_region(0, 0x00000000, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_4G) |
+		TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL);
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+		u_register_t arg2, u_register_t arg3)
+{
+	static console_t console;
+	int i;
+
+	/* Enable CSU NS access permission */
+	for (i = 0; i < 64; i++) {
+		mmio_write_32(IMX_CSU_BASE + i * 4, 0x00ff00ff);
+	}
+
+	imx_aipstz_init(aipstz);
+
+	imx_rdc_init(rdc);
+
+	imx8m_caam_init();
+
+	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_FLAG_BOOT);
+
+	/*
+	 * tell BL3-1 where the non-secure software image is located
+	 * and the entry state information.
+	 */
+	bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET;
+	bl33_image_ep_info.spsr = get_spsr_for_bl33_entry();
+	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#ifdef SPD_opteed
+	/* Populate entry point information for BL32 */
+	SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
+	SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+	bl32_image_ep_info.pc = BL32_BASE;
+	bl32_image_ep_info.spsr = 0;
+
+	/* Pass TEE base and size to bl33 */
+	bl33_image_ep_info.args.arg1 = BL32_BASE;
+	bl33_image_ep_info.args.arg2 = BL32_SIZE;
+#endif
+
+	bl31_tzc380_setup();
+}
+
+void bl31_plat_arch_setup(void)
+{
+	mmap_add_region(BL31_BASE, BL31_BASE, (BL31_LIMIT - BL31_BASE),
+		MT_MEMORY | MT_RW | MT_SECURE);
+	mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, (BL_CODE_END - BL_CODE_BASE),
+		MT_MEMORY | MT_RO | MT_SECURE);
+#if USE_COHERENT_MEM
+	mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
+		(BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE),
+		MT_DEVICE | MT_RW | MT_SECURE);
+#endif
+	mmap_add(imx_mmap);
+
+	init_xlat_tables();
+
+	enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+	generic_delay_timer_init();
+
+	/* select the CKIL source to 32K OSC */
+	mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_MISC_CTL, 0x1);
+
+	plat_gic_driver_init();
+	plat_gic_init();
+
+	imx_gpc_init();
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type)
+{
+	if (type == NON_SECURE)
+		return &bl33_image_ep_info;
+	if (type == SECURE)
+		return &bl32_image_ep_info;
+
+	return NULL;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return COUNTER_FREQUENCY;
+}
diff --git a/plat/imx/imx8m/imx8mn/imx8mn_psci.c b/plat/imx/imx8m/imx8mn/imx8mn_psci.c
new file mode 100644
index 0000000..f541fc1
--- /dev/null
+++ b/plat/imx/imx8m/imx8mn/imx8mn_psci.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <gpc.h>
+#include <imx8m_psci.h>
+#include <plat_imx8.h>
+
+static const plat_psci_ops_t imx_plat_psci_ops = {
+	.pwr_domain_on = imx_pwr_domain_on,
+	.pwr_domain_on_finish = imx_pwr_domain_on_finish,
+	.pwr_domain_off = imx_pwr_domain_off,
+	.validate_ns_entrypoint = imx_validate_ns_entrypoint,
+	.validate_power_state = imx_validate_power_state,
+	.cpu_standby = imx_cpu_standby,
+	.pwr_domain_suspend = imx_domain_suspend,
+	.pwr_domain_suspend_finish = imx_domain_suspend_finish,
+	.pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi,
+	.get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
+	.system_reset = imx_system_reset,
+	.system_off = imx_system_off,
+};
+
+/* export the platform specific psci ops */
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	/* sec_entrypoint is used for warm reset */
+	imx_mailbox_init(sec_entrypoint);
+
+	*psci_ops = &imx_plat_psci_ops;
+
+	return 0;
+}
diff --git a/plat/imx/imx8m/imx8mn/include/gpc_reg.h b/plat/imx/imx8m/imx8mn/include/gpc_reg.h
new file mode 100644
index 0000000..fd10438
--- /dev/null
+++ b/plat/imx/imx8m/imx8mn/include/gpc_reg.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPC_REG_H
+#define GPC_REG_H
+
+#define LPCR_A53_BSC			0x0
+#define LPCR_A53_BSC2			0x108
+#define LPCR_A53_AD			0x4
+#define LPCR_M4				0x8
+#define SLPCR				0x14
+#define MST_CPU_MAPPING			0x18
+#define MLPCR				0x20
+#define PGC_ACK_SEL_A53			0x24
+#define IMR1_CORE0_A53			0x30
+#define IMR1_CORE1_A53			0x40
+#define IMR1_CORE2_A53			0x1C0
+#define IMR1_CORE3_A53			0x1D0
+#define IMR1_CORE0_M4			0x50
+#define SLT0_CFG			0xB0
+#define GPC_PU_PWRHSK			0x1FC
+#define PGC_CPU_0_1_MAPPING		0xEC
+#define CPU_PGC_UP_TRG			0xF0
+#define PU_PGC_UP_TRG			0xF8
+#define CPU_PGC_DN_TRG			0xFC
+#define PU_PGC_DN_TRG			0x104
+#define LPS_CPU1			0x114
+#define A53_CORE0_PGC			0x800
+#define A53_PLAT_PGC			0x900
+#define PLAT_PGC_PCR			0x900
+#define NOC_PGC_PCR			0xa40
+#define PGC_SCU_TIMING			0x910
+
+#define MASK_DSM_TRIGGER_A53		BIT(31)
+#define IRQ_SRC_A53_WUP			BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT		30
+#define IRQ_SRC_C1			BIT(29)
+#define IRQ_SRC_C0			BIT(28)
+#define IRQ_SRC_C3			BIT(23)
+#define IRQ_SRC_C2			BIT(22)
+#define CPU_CLOCK_ON_LPM		BIT(14)
+#define A53_CLK_ON_LPM			BIT(14)
+#define MASTER0_LPM_HSK			BIT(6)
+#define MASTER1_LPM_HSK			BIT(7)
+#define MASTER2_LPM_HSK			BIT(8)
+
+#define L2PGE				BIT(31)
+#define EN_L2_WFI_PDN			BIT(5)
+#define EN_PLAT_PDN			BIT(4)
+
+#define SLPCR_EN_DSM			BIT(31)
+#define SLPCR_RBC_EN			BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE	BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE	BIT(16)
+#define SLPCR_VSTBY			BIT(2)
+#define SLPCR_SBYOS			BIT(1)
+#define SLPCR_BYPASS_PMIC_READY		BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT		24
+#define SLPCR_STBY_COUNT_SHFT		3
+
+#define A53_DUMMY_PDN_ACK		BIT(15)
+#define A53_DUMMY_PUP_ACK		BIT(31)
+#define A53_PLAT_PDN_ACK		BIT(2)
+#define A53_PLAT_PUP_ACK		BIT(18)
+#define NOC_PDN_SLT_CTRL		BIT(10)
+#define NOC_PUP_SLT_CTRL		BIT(11)
+#define NOC_PGC_PDN_ACK			BIT(3)
+#define NOC_PGC_PUP_ACK			BIT(19)
+
+#define PLAT_PUP_SLT_CTRL		BIT(9)
+#define PLAT_PDN_SLT_CTRL		BIT(8)
+
+#define SLT_PLAT_PDN			BIT(8)
+#define SLT_PLAT_PUP			BIT(9)
+
+#define MASTER1_MAPPING			BIT(1)
+#define MASTER2_MAPPING			BIT(2)
+
+#define TMR_TCD2_SHIFT			0
+#define TMC_TMR_SHIFT			10
+#define TRC1_TMC_SHIFT			20
+
+#define MIPI_PWR_REQ			BIT(0)
+#define OTG1_PWR_REQ			BIT(2)
+#define HSIOMIX_PWR_REQ			BIT(4)
+#define DDRMIX_PWR_REQ			BIT(5)
+#define GPUMIX_PWR_REQ			BIT(7)
+#define DISPMIX_PWR_REQ			BIT(10)
+
+#define DDRMIX_ADB400_SYNC		BIT(2)
+#define HSIOMIX_ADB400_SYNC		BIT(5)
+#define DISPMIX_ADB400_SYNC		BIT(7)
+#define GPUMIX_ADB400_SYNC		(0x5 << 9)
+#define DDRMIX_ADB400_ACK		BIT(20)
+#define HSIOMIX_ADB400_ACK		BIT(23)
+#define DISPMIX_ADB400_ACK		BIT(25)
+#define GPUMIX_ADB400_ACK		(0x5 << 27)
+
+#define MIPI_PGC			0xc00
+#define OTG1_PGC			0xc80
+#define HSIOMIX_PGC			0xd00
+#define DDRMIX_PGC			0xd40
+#define GPUMIX_PGC			0xdc0
+#define DISPMIX_PGC			0xe80
+
+#endif /* GPC_REG_H */
diff --git a/plat/imx/imx8m/imx8mn/include/platform_def.h b/plat/imx/imx8m/imx8mn/include/platform_def.h
new file mode 100644
index 0000000..2444e66
--- /dev/null
+++ b/plat/imx/imx8m/imx8mn/include/platform_def.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH		aarch64
+
+#define PLATFORM_STACK_SIZE		0xB00
+#define CACHE_WRITEBACK_GRANULE		64
+
+#define PLAT_PRIMARY_CPU		U(0x0)
+#define PLATFORM_MAX_CPU_PER_CLUSTER	U(4)
+#define PLATFORM_CLUSTER_COUNT		U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT	U(4)
+#define PLATFORM_CLUSTER1_CORE_COUNT	U(0)
+#define PLATFORM_CORE_COUNT		(PLATFORM_CLUSTER0_CORE_COUNT)
+
+#define IMX_PWR_LVL0			MPIDR_AFFLVL0
+#define IMX_PWR_LVL1			MPIDR_AFFLVL1
+#define IMX_PWR_LVL2			MPIDR_AFFLVL2
+
+#define PWR_DOMAIN_AT_MAX_LVL		U(1)
+#define PLAT_MAX_PWR_LVL		U(2)
+#define PLAT_MAX_OFF_STATE		U(4)
+#define PLAT_MAX_RET_STATE		U(2)
+
+#define PLAT_WAIT_RET_STATE		U(1)
+#define PLAT_STOP_OFF_STATE		U(3)
+
+#define BL31_BASE			U(0x960000)
+#define BL31_LIMIT			U(0x980000)
+
+/* non-secure uboot base */
+#define PLAT_NS_IMAGE_OFFSET		U(0x40200000)
+
+/* GICv3 base address */
+#define PLAT_GICD_BASE			U(0x38800000)
+#define PLAT_GICR_BASE			U(0x38880000)
+
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(ULL(1) << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE	(ULL(1) << 32)
+
+#define MAX_XLAT_TABLES			8
+#define MAX_MMAP_REGIONS		16
+
+#define HAB_RVT_BASE			U(0x00000900) /* HAB_RVT for i.MX8MM */
+
+#define IMX_BOOT_UART_CLK_IN_HZ		24000000 /* Select 24MHz oscillator */
+#define PLAT_CRASH_UART_BASE		IMX_BOOT_UART_BASE
+#define PLAT_CRASH_UART_CLK_IN_HZ	24000000
+#define IMX_CONSOLE_BAUDRATE		115200
+
+#define IMX_AIPSTZ1			U(0x301f0000)
+#define IMX_AIPSTZ2			U(0x305f0000)
+#define IMX_AIPSTZ3			U(0x309f0000)
+#define IMX_AIPSTZ4			U(0x32df0000)
+
+#define IMX_AIPS_BASE			U(0x30000000)
+#define IMX_AIPS_SIZE			U(0xC00000)
+#define IMX_GPV_BASE			U(0x32000000)
+#define IMX_GPV_SIZE			U(0x800000)
+#define IMX_AIPS1_BASE			U(0x30200000)
+#define IMX_AIPS4_BASE			U(0x32c00000)
+#define IMX_ANAMIX_BASE			U(0x30360000)
+#define IMX_CCM_BASE			U(0x30380000)
+#define IMX_SRC_BASE			U(0x30390000)
+#define IMX_GPC_BASE			U(0x303a0000)
+#define IMX_RDC_BASE			U(0x303d0000)
+#define IMX_CSU_BASE			U(0x303e0000)
+#define IMX_WDOG_BASE			U(0x30280000)
+#define IMX_SNVS_BASE			U(0x30370000)
+#define IMX_NOC_BASE			U(0x32700000)
+#define IMX_TZASC_BASE			U(0x32F80000)
+#define IMX_IOMUX_GPR_BASE		U(0x30340000)
+#define IMX_CAAM_BASE			U(0x30900000)
+#define IMX_DDRC_BASE			U(0x3d400000)
+#define IMX_DDRPHY_BASE			U(0x3c000000)
+#define IMX_DDR_IPS_BASE		U(0x3d000000)
+#define IMX_DDR_IPS_SIZE		U(0x1800000)
+#define IMX_ROM_BASE			U(0x0)
+
+#define IMX_GIC_BASE			PLAT_GICD_BASE
+#define IMX_GIC_SIZE			U(0x200000)
+
+#define WDOG_WSR			U(0x2)
+#define WDOG_WCR_WDZST			BIT(0)
+#define WDOG_WCR_WDBG			BIT(1)
+#define WDOG_WCR_WDE			BIT(2)
+#define WDOG_WCR_WDT			BIT(3)
+#define WDOG_WCR_SRS			BIT(4)
+#define WDOG_WCR_WDA			BIT(5)
+#define WDOG_WCR_SRE			BIT(6)
+#define WDOG_WCR_WDW			BIT(7)
+
+#define SRC_A53RCR0			U(0x4)
+#define SRC_A53RCR1			U(0x8)
+#define SRC_OTG1PHY_SCR			U(0x20)
+#define SRC_GPR1_OFFSET			U(0x74)
+
+#define SNVS_LPCR			U(0x38)
+#define SNVS_LPCR_SRTC_ENV		BIT(0)
+#define SNVS_LPCR_DP_EN			BIT(5)
+#define SNVS_LPCR_TOP			BIT(6)
+
+#define IOMUXC_GPR10			U(0x28)
+#define GPR_TZASC_EN			BIT(0)
+#define GPR_TZASC_EN_LOCK		BIT(16)
+
+#define ANAMIX_MISC_CTL			U(0x124)
+#define DRAM_PLL_CTRL			(IMX_ANAMIX_BASE + 0x50)
+
+#define MAX_CSU_NUM			U(64)
+
+#define OCRAM_S_BASE			U(0x00180000)
+#define OCRAM_S_SIZE			U(0x8000)
+#define OCRAM_S_LIMIT			(OCRAM_S_BASE + OCRAM_S_SIZE)
+#define SAVED_DRAM_TIMING_BASE		OCRAM_S_BASE
+
+#define COUNTER_FREQUENCY		8000000 /* 8MHz */
+
+#define IMX_WDOG_B_RESET
+
+#define GIC_MAP		MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW)
+#define AIPS_MAP	MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW) /* AIPS map */
+#define OCRAM_S_MAP	MAP_REGION_FLAT(OCRAM_S_BASE, OCRAM_S_SIZE, MT_DEVICE | MT_RW) /* OCRAM_S */
+#define DDRC_MAP	MAP_REGION_FLAT(IMX_DDRPHY_BASE, IMX_DDR_IPS_SIZE, MT_DEVICE | MT_RW) /* DDRMIX */
+
+#endif /* platform_def.h */
diff --git a/plat/imx/imx8m/imx8mn/platform.mk b/plat/imx/imx8m/imx8mn/platform.mk
new file mode 100644
index 0000000..8c4ad1c
--- /dev/null
+++ b/plat/imx/imx8m/imx8mn/platform.mk
@@ -0,0 +1,56 @@
+#
+# Copyright 2019-2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES		:=	-Iplat/imx/common/include		\
+				-Iplat/imx/imx8m/include		\
+				-Iplat/imx/imx8m/imx8mn/include
+# Translation tables library
+include lib/xlat_tables_v2/xlat_tables.mk
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+IMX_GIC_SOURCES		:=	${GICV3_SOURCES}			\
+				plat/common/plat_gicv3.c		\
+				plat/common/plat_psci_common.c		\
+				plat/imx/common/plat_imx8_gic.c
+
+BL31_SOURCES		+=	plat/imx/common/imx8_helpers.S			\
+				plat/imx/imx8m/gpc_common.c			\
+				plat/imx/imx8m/imx_aipstz.c			\
+				plat/imx/imx8m/imx_rdc.c			\
+				plat/imx/imx8m/imx8m_caam.c			\
+				plat/imx/imx8m/imx8m_psci_common.c		\
+				plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c	\
+				plat/imx/imx8m/imx8mn/imx8mn_psci.c		\
+				plat/imx/imx8m/imx8mn/gpc.c			\
+				plat/imx/common/imx8_topology.c			\
+				plat/imx/common/imx_sip_handler.c		\
+				plat/imx/common/imx_sip_svc.c			\
+				plat/imx/common/imx_uart_console.S		\
+				lib/cpus/aarch64/cortex_a53.S			\
+				drivers/arm/tzc/tzc380.c			\
+				drivers/delay_timer/delay_timer.c		\
+				drivers/delay_timer/generic_delay_timer.c	\
+				${IMX_GIC_SOURCES}				\
+				${XLAT_TABLES_LIB_SRCS}
+
+USE_COHERENT_MEM	:=	1
+RESET_TO_BL31		:=	1
+A53_DISABLE_NON_TEMPORAL_HINT := 0
+
+ERRATA_A53_835769	:=	1
+ERRATA_A53_843419	:=	1
+ERRATA_A53_855873	:=	1
+
+BL32_BASE		?=	0xbe000000
+$(eval $(call add_define,BL32_BASE))
+
+BL32_SIZE		?=	0x2000000
+$(eval $(call add_define,BL32_SIZE))
+
+IMX_BOOT_UART_BASE	?=	0x30890000
+$(eval $(call add_define,IMX_BOOT_UART_BASE))
diff --git a/plat/imx/imx8m/imx8mp/gpc.c b/plat/imx/imx8m/imx8mp/gpc.c
new file mode 100644
index 0000000..d660e3d
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/gpc.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright 2019-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <lib/smccc.h>
+#include <services/std_svc.h>
+
+#include <gpc.h>
+#include <imx_aipstz.h>
+#include <imx_sip_svc.h>
+#include <platform_def.h>
+
+#define CCGR(x)		(0x4000 + (x) * 0x10)
+#define IMR_NUM		U(5)
+
+struct imx_noc_setting {
+	uint32_t domain_id;
+	uint32_t start;
+	uint32_t end;
+	uint32_t prioriy;
+	uint32_t mode;
+	uint32_t socket_qos_en;
+};
+
+enum clk_type {
+	CCM_ROOT_SLICE,
+	CCM_CCGR,
+};
+
+struct clk_setting {
+	uint32_t offset;
+	uint32_t val;
+	enum clk_type type;
+};
+
+enum pu_domain_id {
+	/* hsio ss */
+	HSIOMIX,
+	PCIE_PHY,
+	USB1_PHY,
+	USB2_PHY,
+	MLMIX,
+	AUDIOMIX,
+	/* gpu ss */
+	GPUMIX,
+	GPU2D,
+	GPU3D,
+	/* vpu ss */
+	VPUMIX,
+	VPU_G1,
+	VPU_G2,
+	VPU_H1,
+	/* media ss */
+	MEDIAMIX,
+	MEDIAMIX_ISPDWP,
+	MIPI_PHY1,
+	MIPI_PHY2,
+	/* HDMI ss */
+	HDMIMIX,
+	HDMI_PHY,
+	DDRMIX,
+};
+
+/* PU domain, add some hole to minimize the uboot change */
+static struct imx_pwr_domain pu_domains[20] = {
+	[MIPI_PHY1] = IMX_PD_DOMAIN(MIPI_PHY1, false),
+	[PCIE_PHY] = IMX_PD_DOMAIN(PCIE_PHY, false),
+	[USB1_PHY] = IMX_PD_DOMAIN(USB1_PHY, true),
+	[USB2_PHY] = IMX_PD_DOMAIN(USB2_PHY, true),
+	[MLMIX] = IMX_MIX_DOMAIN(MLMIX, false),
+	[AUDIOMIX] = IMX_MIX_DOMAIN(AUDIOMIX, false),
+	[GPU2D] = IMX_PD_DOMAIN(GPU2D, false),
+	[GPUMIX] = IMX_MIX_DOMAIN(GPUMIX, false),
+	[VPUMIX] = IMX_MIX_DOMAIN(VPUMIX, false),
+	[GPU3D] = IMX_PD_DOMAIN(GPU3D, false),
+	[MEDIAMIX] = IMX_MIX_DOMAIN(MEDIAMIX, false),
+	[VPU_G1] = IMX_PD_DOMAIN(VPU_G1, false),
+	[VPU_G2] = IMX_PD_DOMAIN(VPU_G2, false),
+	[VPU_H1] = IMX_PD_DOMAIN(VPU_H1, false),
+	[HDMIMIX] = IMX_MIX_DOMAIN(HDMIMIX, false),
+	[HDMI_PHY] = IMX_PD_DOMAIN(HDMI_PHY, false),
+	[MIPI_PHY2] = IMX_PD_DOMAIN(MIPI_PHY2, false),
+	[HSIOMIX] = IMX_MIX_DOMAIN(HSIOMIX, false),
+	[MEDIAMIX_ISPDWP] = IMX_PD_DOMAIN(MEDIAMIX_ISPDWP, false),
+};
+
+static struct imx_noc_setting noc_setting[] = {
+	{MLMIX, 0x180, 0x180, 0x80000303, 0x0, 0x0},
+	{AUDIOMIX, 0x200, 0x200, 0x80000303, 0x0, 0x0},
+	{AUDIOMIX, 0x280, 0x480, 0x80000404, 0x0, 0x0},
+	{GPUMIX, 0x500, 0x580, 0x80000303, 0x0, 0x0},
+	{HDMIMIX, 0x600, 0x680, 0x80000202, 0x0, 0x1},
+	{HDMIMIX, 0x700, 0x700, 0x80000505, 0x0, 0x0},
+	{HSIOMIX, 0x780, 0x900, 0x80000303, 0x0, 0x0},
+	{MEDIAMIX, 0x980, 0xb80, 0x80000202, 0x0, 0x1},
+	{MEDIAMIX_ISPDWP, 0xc00, 0xd00, 0x80000505, 0x0, 0x0},
+	{VPU_G1, 0xd80, 0xd80, 0x80000303, 0x0, 0x0},
+	{VPU_G2, 0xe00, 0xe00, 0x80000303, 0x0, 0x0},
+	{VPU_H1, 0xe80, 0xe80, 0x80000303, 0x0, 0x0}
+};
+
+static struct clk_setting hsiomix_clk[] = {
+	{ 0x8380, 0x0, CCM_ROOT_SLICE },
+	{ 0x44d0, 0x0, CCM_CCGR },
+	{ 0x45c0, 0x0, CCM_CCGR },
+};
+
+static struct aipstz_cfg aipstz5[] = {
+	{IMX_AIPSTZ5, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{0},
+};
+
+static unsigned int pu_domain_status;
+
+static void imx_noc_qos(unsigned int domain_id)
+{
+	unsigned int i;
+	uint32_t hurry;
+
+	if (domain_id == HDMIMIX) {
+		mmio_write_32(IMX_HDMI_CTL_BASE + TX_CONTROL1, 0x22018);
+		mmio_write_32(IMX_HDMI_CTL_BASE + TX_CONTROL1, 0x22010);
+
+		/* set GPR to make lcdif read hurry level 0x7 */
+		hurry = mmio_read_32(IMX_HDMI_CTL_BASE + TX_CONTROL0);
+		hurry |= 0x00077000;
+		mmio_write_32(IMX_HDMI_CTL_BASE + TX_CONTROL0, hurry);
+	}
+
+	if (domain_id == MEDIAMIX) {
+		/* handle mediamix special */
+		mmio_write_32(IMX_MEDIAMIX_CTL_BASE + RSTn_CSR, 0x1FFFFFF);
+		mmio_write_32(IMX_MEDIAMIX_CTL_BASE + CLK_EN_CSR, 0x1FFFFFF);
+		mmio_write_32(IMX_MEDIAMIX_CTL_BASE + RST_DIV, 0x40030000);
+
+		/* set GPR to make lcdif read hurry level 0x7 */
+		hurry = mmio_read_32(IMX_MEDIAMIX_CTL_BASE + LCDIF_ARCACHE_CTRL);
+		hurry |= 0xfc00;
+		mmio_write_32(IMX_MEDIAMIX_CTL_BASE + LCDIF_ARCACHE_CTRL, hurry);
+		/* set GPR to make isi write hurry level 0x7 */
+		hurry = mmio_read_32(IMX_MEDIAMIX_CTL_BASE + ISI_CACHE_CTRL);
+		hurry |= 0x1ff00000;
+		mmio_write_32(IMX_MEDIAMIX_CTL_BASE + ISI_CACHE_CTRL, hurry);
+	}
+
+	/* set MIX NoC */
+	for (i = 0; i < ARRAY_SIZE(noc_setting); i++) {
+		if (noc_setting[i].domain_id == domain_id) {
+			udelay(50);
+			uint32_t offset = noc_setting[i].start;
+
+			while (offset <= noc_setting[i].end) {
+				mmio_write_32(IMX_NOC_BASE + offset + 0x8, noc_setting[i].prioriy);
+				mmio_write_32(IMX_NOC_BASE + offset + 0xc, noc_setting[i].mode);
+				mmio_write_32(IMX_NOC_BASE + offset + 0x18, noc_setting[i].socket_qos_en);
+				offset += 0x80;
+			}
+		}
+	}
+}
+
+static void imx_gpc_pm_domain_enable(uint32_t domain_id, bool on)
+{
+	struct imx_pwr_domain *pwr_domain = &pu_domains[domain_id];
+	unsigned int i;
+
+	if (domain_id == HSIOMIX) {
+		for (i = 0; i < ARRAY_SIZE(hsiomix_clk); i++) {
+			hsiomix_clk[i].val = mmio_read_32(IMX_CCM_BASE + hsiomix_clk[i].offset);
+			mmio_setbits_32(IMX_CCM_BASE + hsiomix_clk[i].offset,
+					hsiomix_clk[i].type == CCM_ROOT_SLICE ? BIT(28) : 0x3);
+		}
+	}
+
+	if (on) {
+		if (pwr_domain->need_sync) {
+			pu_domain_status |= (1 << domain_id);
+		}
+
+		if (domain_id == HDMIMIX) {
+			/* assert the reset */
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_RESET_CTL0, 0x0);
+			/* enable all th function clock */
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL0, 0xFFFFFFFF);
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL1, 0x7ffff87e);
+		}
+
+		/* clear the PGC bit */
+		mmio_clrbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+		/* power up the domain */
+		mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, pwr_domain->pwr_req);
+
+		/* wait for power request done */
+		while (mmio_read_32(IMX_GPC_BASE + PU_PGC_UP_TRG) & pwr_domain->pwr_req)
+			;
+
+		if (domain_id == HDMIMIX) {
+			/* wait for memory repair done for HDMIMIX */
+			while (!(mmio_read_32(IMX_SRC_BASE + 0x94) & BIT(8)))
+				;
+			/* disable all the function clock */
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL0, 0x0);
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL1, 0x0);
+			/* deassert the reset */
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_RESET_CTL0, 0xffffffff);
+			/* enable all the clock again */
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL0, 0xFFFFFFFF);
+			mmio_write_32(IMX_HDMI_CTL_BASE + RTX_CLK_CTL1, 0x7ffff87e);
+		}
+
+		if (domain_id == HSIOMIX) {
+			/* enable HSIOMIX clock */
+			mmio_write_32(IMX_HSIOMIX_CTL_BASE, 0x2);
+		}
+
+		/* handle the ADB400 sync */
+		if (pwr_domain->need_sync) {
+			/* clear adb power down request */
+			mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+			/* wait for adb power request ack */
+			while (!(mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack))
+				;
+		}
+
+		imx_noc_qos(domain_id);
+
+		/* AIPS5 config is lost when audiomix is off, so need to re-init it */
+		if (domain_id == AUDIOMIX) {
+			imx_aipstz_init(aipstz5);
+		}
+	} else {
+		if (pwr_domain->always_on) {
+			return;
+		}
+
+		if (pwr_domain->need_sync) {
+			pu_domain_status &= ~(1 << domain_id);
+		}
+
+		/* handle the ADB400 sync */
+		if (pwr_domain->need_sync) {
+			/* set adb power down request */
+			mmio_clrbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, pwr_domain->adb400_sync);
+
+			/* wait for adb power request ack */
+			while ((mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & pwr_domain->adb400_ack))
+				;
+		}
+
+		/* set the PGC bit */
+		mmio_setbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
+
+		/*
+		 * leave the G1, G2, H1 power domain on until VPUMIX power off,
+		 * otherwise system will hang due to VPUMIX ACK
+		 */
+		if (domain_id == VPU_H1 || domain_id == VPU_G1 || domain_id == VPU_G2) {
+			return;
+		}
+
+		if (domain_id == VPUMIX) {
+			mmio_write_32(IMX_GPC_BASE + PU_PGC_DN_TRG, VPU_G1_PWR_REQ |
+				 VPU_G2_PWR_REQ | VPU_H1_PWR_REQ);
+
+			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & (VPU_G1_PWR_REQ |
+					VPU_G2_PWR_REQ | VPU_H1_PWR_REQ))
+				;
+		}
+
+		/* power down the domain */
+		mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, pwr_domain->pwr_req);
+
+		/* wait for power request done */
+		while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & pwr_domain->pwr_req)
+			;
+
+		if (domain_id == HDMIMIX) {
+			/* disable all the clocks of HDMIMIX */
+			mmio_write_32(IMX_HDMI_CTL_BASE + 0x40, 0x0);
+			mmio_write_32(IMX_HDMI_CTL_BASE + 0x50, 0x0);
+		}
+	}
+
+	if (domain_id == HSIOMIX) {
+		for (i = 0; i < ARRAY_SIZE(hsiomix_clk); i++) {
+			mmio_write_32(IMX_CCM_BASE + hsiomix_clk[i].offset, hsiomix_clk[i].val);
+		}
+	}
+}
+
+void imx_gpc_init(void)
+{
+	uint32_t val;
+	unsigned int i;
+
+	/* mask all the wakeup irq by default */
+	for (i = 0; i < IMR_NUM; i++) {
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE1_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE2_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE3_A53 + i * 4, ~0x0);
+		mmio_write_32(IMX_GPC_BASE + IMR1_CORE0_M4 + i * 4, ~0x0);
+	}
+
+	val = mmio_read_32(IMX_GPC_BASE + LPCR_A53_BSC);
+	/* use GIC wake_request to wakeup C0~C3 from LPM */
+	val |= CORE_WKUP_FROM_GIC;
+	/* clear the MASTER0 LPM handshake */
+	val &= ~MASTER0_LPM_HSK;
+	mmio_write_32(IMX_GPC_BASE + LPCR_A53_BSC, val);
+
+	/* clear MASTER1 & MASTER2 mapping in CPU0(A53) */
+	mmio_clrbits_32(IMX_GPC_BASE + MST_CPU_MAPPING, (MASTER1_MAPPING |
+		MASTER2_MAPPING));
+
+	/* set all mix/PU in A53 domain */
+	mmio_write_32(IMX_GPC_BASE + PGC_CPU_0_1_MAPPING, 0x3fffff);
+
+	/*
+	 * Set the CORE & SCU power up timing:
+	 * SW = 0x1, SW2ISO = 0x1;
+	 * the CPU CORE and SCU power up timming counter
+	 * is drived  by 32K OSC, each domain's power up
+	 * latency is (SW + SW2ISO) / 32768
+	 */
+	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(0) + 0x4, 0x401);
+	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(1) + 0x4, 0x401);
+	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(2) + 0x4, 0x401);
+	mmio_write_32(IMX_GPC_BASE + COREx_PGC_PCR(3) + 0x4, 0x401);
+	mmio_write_32(IMX_GPC_BASE + PLAT_PGC_PCR + 0x4, 0x401);
+	mmio_write_32(IMX_GPC_BASE + PGC_SCU_TIMING,
+		      (0x59 << TMC_TMR_SHIFT) | 0x5B | (0x2 << TRC1_TMC_SHIFT));
+
+	/* set DUMMY PDN/PUP ACK by default for A53 domain */
+	mmio_write_32(IMX_GPC_BASE + PGC_ACK_SEL_A53,
+		      A53_DUMMY_PUP_ACK | A53_DUMMY_PDN_ACK);
+
+	/* clear DSM by default */
+	val = mmio_read_32(IMX_GPC_BASE + SLPCR);
+	val &= ~SLPCR_EN_DSM;
+	/* enable the fast wakeup wait/stop mode */
+	val |= SLPCR_A53_FASTWUP_WAIT_MODE;
+	val |= SLPCR_A53_FASTWUP_STOP_MODE;
+	/* clear the RBC */
+	val &= ~(0x3f << SLPCR_RBC_COUNT_SHIFT);
+	/* set the STBY_COUNT to 0x5, (128 * 30)us */
+	val &= ~(0x7 << SLPCR_STBY_COUNT_SHFT);
+	val |= (0x5 << SLPCR_STBY_COUNT_SHFT);
+	mmio_write_32(IMX_GPC_BASE + SLPCR, val);
+
+	/*
+	 * USB PHY power up needs to make sure RESET bit in SRC is clear,
+	 * otherwise, the PU power up bit in GPC will NOT self-cleared.
+	 * only need to do it once.
+	 */
+	mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG1PHY_SCR, 0x1);
+	mmio_clrbits_32(IMX_SRC_BASE + SRC_OTG2PHY_SCR, 0x1);
+
+	/* enable all the power domain by default */
+	for (i = 0; i < 101; i++) {
+		mmio_write_32(IMX_CCM_BASE + CCGR(i), 0x3);
+	}
+
+	for (i = 0; i < 20; i++) {
+		imx_gpc_pm_domain_enable(i, true);
+	}
+}
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c b/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c
new file mode 100644
index 0000000..22fbd5e
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <context.h>
+#include <drivers/arm/tzc380.h>
+#include <drivers/console.h>
+#include <drivers/generic_delay_timer.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
+
+#include <gpc.h>
+#include <imx_aipstz.h>
+#include <imx_uart.h>
+#include <imx_rdc.h>
+#include <imx8m_caam.h>
+#include <platform_def.h>
+#include <plat_imx8.h>
+
+static const mmap_region_t imx_mmap[] = {
+	GIC_MAP, AIPS_MAP, OCRAM_S_MAP, DDRC_MAP,
+	NOC_MAP, {0},
+};
+
+static const struct aipstz_cfg aipstz[] = {
+	{IMX_AIPSTZ1, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{IMX_AIPSTZ2, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{IMX_AIPSTZ3, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{IMX_AIPSTZ4, 0x77777777, 0x77777777, .opacr = {0x0, 0x0, 0x0, 0x0, 0x0}, },
+	{0},
+};
+
+static const struct imx_rdc_cfg rdc[] = {
+	/* Master domain assignment */
+	RDC_MDAn(0x1, DID1),
+
+	/* peripherals domain permission */
+
+	/* memory region */
+
+	/* Sentinel */
+	{0},
+};
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+/* get SPSR for BL33 entry */
+static uint32_t get_spsr_for_bl33_entry(void)
+{
+	unsigned long el_status;
+	unsigned long mode;
+	uint32_t spsr;
+
+	/* figure out what mode we enter the non-secure world */
+	el_status = read_id_aa64pfr0_el1() >> ID_AA64PFR0_EL2_SHIFT;
+	el_status &= ID_AA64PFR0_ELX_MASK;
+
+	mode = (el_status) ? MODE_EL2 : MODE_EL1;
+
+	spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+	return spsr;
+}
+
+static void bl31_tzc380_setup(void)
+{
+	unsigned int val;
+
+	val = mmio_read_32(IMX_IOMUX_GPR_BASE + 0x28);
+	if ((val & GPR_TZASC_EN) != GPR_TZASC_EN)
+		return;
+
+	tzc380_init(IMX_TZASC_BASE);
+
+	/*
+	 * Need to substact offset 0x40000000 from CPU address when
+	 * programming tzasc region for i.mx8mp.
+	 */
+
+	/* Enable 1G-5G S/NS RW */
+	tzc380_configure_region(0, 0x00000000, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_4G) |
+		TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL);
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+		u_register_t arg2, u_register_t arg3)
+{
+	static console_t console;
+	unsigned int i;
+
+	/* Enable CSU NS access permission */
+	for (i = 0; i < 64; i++) {
+		mmio_write_32(IMX_CSU_BASE + i * 4, 0x00ff00ff);
+	}
+
+	imx_aipstz_init(aipstz);
+
+	imx_rdc_init(rdc);
+
+	imx8m_caam_init();
+
+	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_FLAG_BOOT);
+
+	/*
+	 * tell BL3-1 where the non-secure software image is located
+	 * and the entry state information.
+	 */
+	bl33_image_ep_info.pc = PLAT_NS_IMAGE_OFFSET;
+	bl33_image_ep_info.spsr = get_spsr_for_bl33_entry();
+	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+#ifdef SPD_opteed
+	/* Populate entry point information for BL32 */
+	SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
+	SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+	bl32_image_ep_info.pc = BL32_BASE;
+	bl32_image_ep_info.spsr = 0;
+
+	/* Pass TEE base and size to bl33 */
+	bl33_image_ep_info.args.arg1 = BL32_BASE;
+	bl33_image_ep_info.args.arg2 = BL32_SIZE;
+#endif
+
+	bl31_tzc380_setup();
+}
+
+void bl31_plat_arch_setup(void)
+{
+	mmap_add_region(BL31_BASE, BL31_BASE, (BL31_LIMIT - BL31_BASE),
+		MT_MEMORY | MT_RW | MT_SECURE);
+	mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, (BL_CODE_END - BL_CODE_BASE),
+		MT_MEMORY | MT_RO | MT_SECURE);
+#if USE_COHERENT_MEM
+	mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
+		(BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE),
+		MT_DEVICE | MT_RW | MT_SECURE);
+#endif
+	mmap_add(imx_mmap);
+
+	init_xlat_tables();
+
+	enable_mmu_el3(0);
+}
+
+void bl31_platform_setup(void)
+{
+	generic_delay_timer_init();
+
+	/* select the CKIL source to 32K OSC */
+	mmio_write_32(IMX_ANAMIX_BASE + ANAMIX_MISC_CTL, 0x1);
+
+	plat_gic_driver_init();
+	plat_gic_init();
+
+	imx_gpc_init();
+}
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type)
+{
+	if (type == NON_SECURE) {
+		return &bl33_image_ep_info;
+	}
+
+	if (type == SECURE) {
+		return &bl32_image_ep_info;
+	}
+
+	return NULL;
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return COUNTER_FREQUENCY;
+}
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_psci.c b/plat/imx/imx8m/imx8mp/imx8mp_psci.c
new file mode 100644
index 0000000..bc7b246
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/imx8mp_psci.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+
+#include <gpc.h>
+#include <imx8m_psci.h>
+#include <plat_imx8.h>
+
+static const plat_psci_ops_t imx_plat_psci_ops = {
+	.pwr_domain_on = imx_pwr_domain_on,
+	.pwr_domain_on_finish = imx_pwr_domain_on_finish,
+	.pwr_domain_off = imx_pwr_domain_off,
+	.validate_ns_entrypoint = imx_validate_ns_entrypoint,
+	.validate_power_state = imx_validate_power_state,
+	.cpu_standby = imx_cpu_standby,
+	.pwr_domain_suspend = imx_domain_suspend,
+	.pwr_domain_suspend_finish = imx_domain_suspend_finish,
+	.pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi,
+	.get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
+	.system_reset = imx_system_reset,
+	.system_off = imx_system_off,
+};
+
+/* export the platform specific psci ops */
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	/* sec_entrypoint is used for warm reset */
+	imx_mailbox_init(sec_entrypoint);
+
+	*psci_ops = &imx_plat_psci_ops;
+
+	return 0;
+}
diff --git a/plat/imx/imx8m/imx8mp/include/gpc_reg.h b/plat/imx/imx8m/imx8mp/include/gpc_reg.h
new file mode 100644
index 0000000..12da6ac
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/include/gpc_reg.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPC_REG_H
+#define GPC_REG_H
+
+#define LPCR_A53_BSC			0x0
+#define LPCR_A53_BSC2			0x180
+#define LPCR_A53_AD			0x4
+#define LPCR_M4				0x8
+#define SLPCR				0x14
+#define MST_CPU_MAPPING			0x18
+#define MLPCR				0x20
+#define PGC_ACK_SEL_A53			0x24
+#define IMR1_CORE0_A53			0x30
+#define IMR1_CORE1_A53			0x44
+#define IMR1_CORE2_A53			0x194
+#define IMR1_CORE3_A53			0x1A8
+#define IMR1_CORE0_M4			0x58
+
+#define SLT0_CFG			0x200
+#define GPC_PU_PWRHSK			0x190
+#define PGC_CPU_0_1_MAPPING		0x1CC
+#define CPU_PGC_UP_TRG			0xD0
+#define PU_PGC_UP_TRG			0xD8
+#define CPU_PGC_DN_TRG			0xDC
+#define PU_PGC_DN_TRG			0xE4
+#define LPS_CPU1			0xEC
+
+#define A53_CORE0_PGC			0x800
+#define A53_PLAT_PGC			0x900
+#define PLAT_PGC_PCR			0x900
+#define NOC_PGC_PCR			0xa40
+#define PGC_SCU_TIMING			0x910
+
+#define MASK_DSM_TRIGGER_A53		BIT(31)
+#define IRQ_SRC_A53_WUP			BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT		30
+#define IRQ_SRC_C1			BIT(29)
+#define IRQ_SRC_C0			BIT(28)
+#define IRQ_SRC_C3			BIT(23)
+#define IRQ_SRC_C2			BIT(22)
+#define CPU_CLOCK_ON_LPM		BIT(14)
+#define A53_CLK_ON_LPM			BIT(14)
+#define MASTER0_LPM_HSK			BIT(6)
+#define MASTER1_LPM_HSK			BIT(7)
+#define MASTER2_LPM_HSK			BIT(8)
+
+#define L2PGE				BIT(31)
+#define EN_L2_WFI_PDN			BIT(5)
+#define EN_PLAT_PDN			BIT(4)
+
+#define SLPCR_EN_DSM			BIT(31)
+#define SLPCR_RBC_EN			BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE	BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE	BIT(16)
+#define SLPCR_VSTBY			BIT(2)
+#define SLPCR_SBYOS			BIT(1)
+#define SLPCR_BYPASS_PMIC_READY		BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT		24
+#define SLPCR_STBY_COUNT_SHFT		3
+
+#define A53_DUMMY_PDN_ACK		BIT(30)
+#define A53_DUMMY_PUP_ACK		BIT(31)
+#define A53_PLAT_PDN_ACK		BIT(8)
+#define A53_PLAT_PUP_ACK		BIT(9)
+
+#define NOC_PDN_SLT_CTRL		BIT(12)
+#define NOC_PUP_SLT_CTRL		BIT(13)
+#define NOC_PGC_PDN_ACK			BIT(12)
+#define NOC_PGC_PUP_ACK			BIT(13)
+
+#define PLAT_PUP_SLT_CTRL		BIT(9)
+#define PLAT_PDN_SLT_CTRL		BIT(8)
+
+#define SLT_PLAT_PDN			BIT(8)
+#define SLT_PLAT_PUP			BIT(9)
+
+#define MASTER1_MAPPING			BIT(1)
+#define MASTER2_MAPPING			BIT(2)
+
+#define TMR_TCD2_SHIFT			0
+#define TMC_TMR_SHIFT			10
+#define TRC1_TMC_SHIFT			20
+
+#define MIPI_PHY1_PWR_REQ		BIT(0)
+#define PCIE_PHY_PWR_REQ		BIT(1)
+#define USB1_PHY_PWR_REQ		BIT(2)
+#define USB2_PHY_PWR_REQ		BIT(3)
+#define MLMIX_PWR_REQ			BIT(4)
+#define AUDIOMIX_PWR_REQ		BIT(5)
+#define GPU2D_PWR_REQ			BIT(6)
+#define GPUMIX_PWR_REQ			BIT(7)
+#define VPUMIX_PWR_REQ			BIT(8)
+#define GPU3D_PWR_REQ			BIT(9)
+#define MEDIAMIX_PWR_REQ		BIT(10)
+#define VPU_G1_PWR_REQ			BIT(11)
+#define VPU_G2_PWR_REQ			BIT(12)
+#define VPU_H1_PWR_REQ			BIT(13)
+#define HDMIMIX_PWR_REQ			BIT(14)
+#define HDMI_PHY_PWR_REQ		BIT(15)
+#define MIPI_PHY2_PWR_REQ		BIT(16)
+#define HSIOMIX_PWR_REQ			BIT(17)
+#define MEDIAMIX_ISPDWP_PWR_REQ		BIT(18)
+#define DDRMIX_PWR_REQ			BIT(19)
+
+#define AUDIOMIX_ADB400_SYNC		(BIT(4) | BIT(15))
+#define MLMIX_ADB400_SYNC		(BIT(7) | BIT(8))
+#define GPUMIX_ADB400_SYNC		BIT(9)
+#define VPUMIX_ADB400_SYNC		BIT(10)
+#define DDRMIX_ADB400_SYNC		BIT(11)
+#define HSIOMIX_ADB400_SYNC		BIT(12)
+#define HDMIMIX_ADB400_SYNC		BIT(13)
+#define MEDIAMIX_ADB400_SYNC		BIT(14)
+
+#define AUDIOMIX_ADB400_ACK		(BIT(20) | BIT(31))
+#define MLMIX_ADB400_ACK		(BIT(23) | BIT(24))
+#define GPUMIX_ADB400_ACK		BIT(25)
+#define VPUMIX_ADB400_ACK		BIT(26)
+#define DDRMIX_ADB400_ACK		BIT(27)
+#define HSIOMIX_ADB400_ACK		BIT(28)
+#define HDMIMIX_ADB400_ACK		BIT(29)
+#define MEDIAMIX_ADB400_ACK		BIT(30)
+
+#define MIPI_PHY1_PGC			0xb00
+#define PCIE_PHY_PGC			0xb40
+#define USB1_PHY_PGC			0xb80
+#define USB2_PHY_PGC			0xbc0
+#define MLMIX_PGC			0xc00
+#define AUDIOMIX_PGC			0xc40
+#define GPU2D_PGC			0xc80
+#define GPUMIX_PGC			0xcc0
+#define VPUMIX_PGC			0xd00
+#define GPU3D_PGC			0xd40
+#define MEDIAMIX_PGC			0xd80
+#define VPU_G1_PGC			0xdc0
+#define VPU_G2_PGC			0xe00
+#define VPU_H1_PGC			0xe40
+#define HDMIMIX_PGC			0xe80
+#define HDMI_PHY_PGC			0xec0
+#define MIPI_PHY2_PGC			0xf00
+#define HSIOMIX_PGC			0xf40
+#define MEDIAMIX_ISPDWP_PGC		0xf80
+#define DDRMIX_PGC			0xfc0
+
+#endif /* GPC_REG_H */
diff --git a/plat/imx/imx8m/imx8mp/include/platform_def.h b/plat/imx/imx8m/imx8mp/include/platform_def.h
new file mode 100644
index 0000000..644adc7
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/include/platform_def.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH		aarch64
+
+#define PLATFORM_STACK_SIZE		0xB00
+#define CACHE_WRITEBACK_GRANULE		64
+
+#define PLAT_PRIMARY_CPU		U(0x0)
+#define PLATFORM_MAX_CPU_PER_CLUSTER	U(4)
+#define PLATFORM_CLUSTER_COUNT		U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT	U(4)
+#define PLATFORM_CLUSTER1_CORE_COUNT	U(0)
+#define PLATFORM_CORE_COUNT		(PLATFORM_CLUSTER0_CORE_COUNT)
+
+#define IMX_PWR_LVL0			MPIDR_AFFLVL0
+#define IMX_PWR_LVL1			MPIDR_AFFLVL1
+#define IMX_PWR_LVL2			MPIDR_AFFLVL2
+
+#define PWR_DOMAIN_AT_MAX_LVL		U(1)
+#define PLAT_MAX_PWR_LVL		U(2)
+#define PLAT_MAX_OFF_STATE		U(4)
+#define PLAT_MAX_RET_STATE		U(2)
+
+#define PLAT_WAIT_RET_STATE		U(1)
+#define PLAT_STOP_OFF_STATE		U(3)
+
+#define BL31_BASE			U(0x960000)
+#define BL31_LIMIT			U(0x980000)
+
+/* non-secure uboot base */
+#define PLAT_NS_IMAGE_OFFSET		U(0x40200000)
+
+/* GICv3 base address */
+#define PLAT_GICD_BASE			U(0x38800000)
+#define PLAT_GICR_BASE			U(0x38880000)
+
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(ULL(1) << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE	(ULL(1) << 32)
+
+#define MAX_XLAT_TABLES			8
+#define MAX_MMAP_REGIONS		16
+
+#define HAB_RVT_BASE			U(0x00000900) /* HAB_RVT for i.MX8MM */
+
+#define IMX_BOOT_UART_CLK_IN_HZ		24000000 /* Select 24MHz oscillator */
+#define PLAT_CRASH_UART_BASE		IMX_BOOT_UART_BASE
+#define PLAT_CRASH_UART_CLK_IN_HZ	24000000
+#define IMX_CONSOLE_BAUDRATE		115200
+
+#define IMX_AIPSTZ1			U(0x301f0000)
+#define IMX_AIPSTZ2			U(0x305f0000)
+#define IMX_AIPSTZ3			U(0x309f0000)
+#define IMX_AIPSTZ4			U(0x32df0000)
+#define IMX_AIPSTZ5			U(0x30df0000)
+
+#define IMX_AIPS_BASE			U(0x30000000)
+#define IMX_AIPS_SIZE			U(0x3000000)
+#define IMX_GPV_BASE			U(0x32000000)
+#define IMX_GPV_SIZE			U(0x800000)
+#define IMX_AIPS1_BASE			U(0x30200000)
+#define IMX_AIPS4_BASE			U(0x32c00000)
+#define IMX_ANAMIX_BASE			U(0x30360000)
+#define IMX_CCM_BASE			U(0x30380000)
+#define IMX_SRC_BASE			U(0x30390000)
+#define IMX_GPC_BASE			U(0x303a0000)
+#define IMX_RDC_BASE			U(0x303d0000)
+#define IMX_CSU_BASE			U(0x303e0000)
+#define IMX_WDOG_BASE			U(0x30280000)
+#define IMX_SNVS_BASE			U(0x30370000)
+#define IMX_NOC_BASE			U(0x32700000)
+#define IMX_NOC_SIZE			U(0x100000)
+#define IMX_TZASC_BASE			U(0x32F80000)
+#define IMX_IOMUX_GPR_BASE		U(0x30340000)
+#define IMX_CAAM_BASE			U(0x30900000)
+#define IMX_DDRC_BASE			U(0x3d400000)
+#define IMX_DDRPHY_BASE			U(0x3c000000)
+#define IMX_DDR_IPS_BASE		U(0x3d000000)
+#define IMX_DDR_IPS_SIZE		U(0x1800000)
+#define IMX_ROM_BASE			U(0x0)
+
+#define IMX_GIC_BASE			PLAT_GICD_BASE
+#define IMX_GIC_SIZE			U(0x200000)
+
+#define IMX_HSIOMIX_CTL_BASE		U(0x32f10000)
+#define IMX_HDMI_CTL_BASE		U(0x32fc0000)
+#define RTX_RESET_CTL0			U(0x20)
+#define RTX_CLK_CTL0			U(0x40)
+#define RTX_CLK_CTL1			U(0x50)
+#define TX_CONTROL0			U(0x200)
+#define TX_CONTROL1			U(0x220)
+
+#define IMX_MEDIAMIX_CTL_BASE		U(0x32ec0000)
+#define RSTn_CSR			U(0x0)
+#define CLK_EN_CSR			U(0x4)
+#define RST_DIV				U(0x8)
+#define LCDIF_ARCACHE_CTRL		U(0x4c)
+#define ISI_CACHE_CTRL			U(0x50)
+
+#define WDOG_WSR			U(0x2)
+#define WDOG_WCR_WDZST			BIT(0)
+#define WDOG_WCR_WDBG			BIT(1)
+#define WDOG_WCR_WDE			BIT(2)
+#define WDOG_WCR_WDT			BIT(3)
+#define WDOG_WCR_SRS			BIT(4)
+#define WDOG_WCR_WDA			BIT(5)
+#define WDOG_WCR_SRE			BIT(6)
+#define WDOG_WCR_WDW			BIT(7)
+
+#define SRC_A53RCR0			U(0x4)
+#define SRC_A53RCR1			U(0x8)
+#define SRC_OTG1PHY_SCR			U(0x20)
+#define SRC_OTG2PHY_SCR			U(0x24)
+#define SRC_GPR1_OFFSET			U(0x74)
+
+#define SNVS_LPCR			U(0x38)
+#define SNVS_LPCR_SRTC_ENV		BIT(0)
+#define SNVS_LPCR_DP_EN			BIT(5)
+#define SNVS_LPCR_TOP			BIT(6)
+
+#define IOMUXC_GPR10			U(0x28)
+#define GPR_TZASC_EN			BIT(0)
+#define GPR_TZASC_EN_LOCK		BIT(16)
+
+#define ANAMIX_MISC_CTL			U(0x124)
+#define DRAM_PLL_CTRL			(IMX_ANAMIX_BASE + 0x50)
+
+#define MAX_CSU_NUM			U(64)
+
+#define OCRAM_S_BASE			U(0x00180000)
+#define OCRAM_S_SIZE			U(0x8000)
+#define OCRAM_S_LIMIT			(OCRAM_S_BASE + OCRAM_S_SIZE)
+#define SAVED_DRAM_TIMING_BASE		OCRAM_S_BASE
+
+#define COUNTER_FREQUENCY		8000000 /* 8MHz */
+
+#define IMX_WDOG_B_RESET
+
+#define GIC_MAP		MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW)
+#define AIPS_MAP	MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW) /* AIPS map */
+#define OCRAM_S_MAP	MAP_REGION_FLAT(OCRAM_S_BASE, OCRAM_S_SIZE, MT_MEMORY | MT_RW) /* OCRAM_S */
+#define DDRC_MAP	MAP_REGION_FLAT(IMX_DDRPHY_BASE, IMX_DDR_IPS_SIZE, MT_DEVICE | MT_RW) /* DDRMIX */
+#define NOC_MAP		MAP_REGION_FLAT(IMX_NOC_BASE, IMX_NOC_SIZE, MT_DEVICE | MT_RW) /* NOC QoS */
+
+#endif /* platform_def.h */
diff --git a/plat/imx/imx8m/imx8mp/platform.mk b/plat/imx/imx8m/imx8mp/platform.mk
new file mode 100644
index 0000000..1d11e3d
--- /dev/null
+++ b/plat/imx/imx8m/imx8mp/platform.mk
@@ -0,0 +1,56 @@
+#
+# Copyright 2019-2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES		:=	-Iplat/imx/common/include		\
+				-Iplat/imx/imx8m/include		\
+				-Iplat/imx/imx8m/imx8mp/include
+# Translation tables library
+include lib/xlat_tables_v2/xlat_tables.mk
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+IMX_GIC_SOURCES		:=	${GICV3_SOURCES}			\
+				plat/common/plat_gicv3.c		\
+				plat/common/plat_psci_common.c		\
+				plat/imx/common/plat_imx8_gic.c
+
+BL31_SOURCES		+=	plat/imx/common/imx8_helpers.S			\
+				plat/imx/imx8m/gpc_common.c			\
+				plat/imx/imx8m/imx_aipstz.c			\
+				plat/imx/imx8m/imx_rdc.c			\
+				plat/imx/imx8m/imx8m_caam.c			\
+				plat/imx/imx8m/imx8m_psci_common.c		\
+				plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c	\
+				plat/imx/imx8m/imx8mp/imx8mp_psci.c		\
+				plat/imx/imx8m/imx8mp/gpc.c			\
+				plat/imx/common/imx8_topology.c			\
+				plat/imx/common/imx_sip_handler.c		\
+				plat/imx/common/imx_sip_svc.c			\
+				plat/imx/common/imx_uart_console.S		\
+				lib/cpus/aarch64/cortex_a53.S			\
+				drivers/arm/tzc/tzc380.c			\
+				drivers/delay_timer/delay_timer.c		\
+				drivers/delay_timer/generic_delay_timer.c	\
+				${IMX_GIC_SOURCES}				\
+				${XLAT_TABLES_LIB_SRCS}
+
+USE_COHERENT_MEM	:=	1
+RESET_TO_BL31		:=	1
+A53_DISABLE_NON_TEMPORAL_HINT := 0
+
+ERRATA_A53_835769	:=	1
+ERRATA_A53_843419	:=	1
+ERRATA_A53_855873	:=	1
+
+BL32_BASE		?=	0x56000000
+$(eval $(call add_define,BL32_BASE))
+
+BL32_SIZE		?=	0x2000000
+$(eval $(call add_define,BL32_SIZE))
+
+IMX_BOOT_UART_BASE	?=	0x30890000
+$(eval $(call add_define,IMX_BOOT_UART_BASE))
diff --git a/plat/imx/imx8m/imx8mq/include/gpc_reg.h b/plat/imx/imx8m/imx8mq/include/gpc_reg.h
new file mode 100644
index 0000000..9f472d6
--- /dev/null
+++ b/plat/imx/imx8m/imx8mq/include/gpc_reg.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GPC_REG_H
+#define GPC_REG_H
+
+#define LPCR_A53_BSC			0x0
+#define LPCR_A53_BSC2			0x108
+#define LPCR_A53_AD			0x4
+#define LPCR_M4				0x8
+#define SLPCR				0x14
+#define MST_CPU_MAPPING			0x18
+#define MLPCR				0x20
+#define PGC_ACK_SEL_A53			0x24
+#define IMR1_CORE0_A53			0x30
+#define IMR1_CORE1_A53			0x40
+#define IMR1_CORE2_A53			0x1C0
+#define IMR1_CORE3_A53			0x1D0
+#define IMR1_CORE0_M4			0x50
+#define SLT0_CFG			0xB0
+#define GPC_PU_PWRHSK			0x1FC
+#define PGC_CPU_0_1_MAPPING		0xEC
+#define CPU_PGC_UP_TRG			0xF0
+#define PU_PGC_UP_TRG			0xF8
+#define CPU_PGC_DN_TRG			0xFC
+#define PU_PGC_DN_TRG			0x104
+#define LPS_CPU1			0x114
+#define A53_CORE0_PGC			0x800
+#define A53_PLAT_PGC			0x900
+#define PLAT_PGC_PCR			0x900
+#define NOC_PGC_PCR			0xa40
+#define PGC_SCU_TIMING			0x910
+
+#define MASK_DSM_TRIGGER_A53		BIT(31)
+#define IRQ_SRC_A53_WUP			BIT(30)
+#define IRQ_SRC_A53_WUP_SHIFT		30
+#define IRQ_SRC_C1			BIT(29)
+#define IRQ_SRC_C0			BIT(28)
+#define IRQ_SRC_C3			BIT(23)
+#define IRQ_SRC_C2			BIT(22)
+#define CPU_CLOCK_ON_LPM		BIT(14)
+#define A53_CLK_ON_LPM			BIT(14)
+#define MASTER0_LPM_HSK			BIT(6)
+#define MASTER1_LPM_HSK			BIT(7)
+#define MASTER2_LPM_HSK			BIT(8)
+
+#define L2PGE				BIT(31)
+#define EN_L2_WFI_PDN			BIT(5)
+#define EN_PLAT_PDN			BIT(4)
+
+#define SLPCR_EN_DSM			BIT(31)
+#define SLPCR_RBC_EN			BIT(30)
+#define SLPCR_A53_FASTWUP_STOP_MODE	BIT(17)
+#define SLPCR_A53_FASTWUP_WAIT_MODE	BIT(16)
+#define SLPCR_VSTBY			BIT(2)
+#define SLPCR_SBYOS			BIT(1)
+#define SLPCR_BYPASS_PMIC_READY		BIT(0)
+#define SLPCR_RBC_COUNT_SHIFT		24
+#define SLPCR_STBY_COUNT_SHFT		3
+
+#define A53_DUMMY_PDN_ACK		BIT(15)
+#define A53_DUMMY_PUP_ACK		BIT(31)
+#define A53_PLAT_PDN_ACK		BIT(2)
+#define A53_PLAT_PUP_ACK		BIT(18)
+#define NOC_PDN_SLT_CTRL		BIT(10)
+#define NOC_PUP_SLT_CTRL		BIT(11)
+#define NOC_PGC_PDN_ACK			BIT(3)
+#define NOC_PGC_PUP_ACK			BIT(19)
+
+#define DDRMIX_PWR_REQ			BIT(5)
+#define DDRMIX_ADB400_SYNC		BIT(1)
+#define DDRMIX_ADB400_ACK		BIT(18)
+#define DDRMIX_PGC			0xd40
+
+#define PLAT_PUP_SLT_CTRL		BIT(9)
+#define PLAT_PDN_SLT_CTRL		BIT(8)
+
+#define SLT_PLAT_PDN			BIT(8)
+#define SLT_PLAT_PUP			BIT(9)
+
+#define MASTER1_MAPPING			BIT(1)
+#define MASTER2_MAPPING			BIT(2)
+
+#endif /* GPC_REG_H */
diff --git a/plat/imx/imx8m/include/gpc.h b/plat/imx/imx8m/include/gpc.h
index 139132c..89a0b9d 100644
--- a/plat/imx/imx8m/include/gpc.h
+++ b/plat/imx/imx8m/include/gpc.h
@@ -7,69 +7,7 @@
 #ifndef IMX8M_GPC_H
 #define IMX8M_GPC_H
 
-#define LPCR_A53_BSC			0x0
-#define LPCR_A53_BSC2			0x108
-#define LPCR_A53_AD			0x4
-#define LPCR_M4				0x8
-#define SLPCR				0x14
-#define MST_CPU_MAPPING			0x18
-#define MLPCR				0x20
-#define PGC_ACK_SEL_A53			0x24
-#define IMR1_CORE0_A53			0x30
-#define IMR1_CORE1_A53			0x40
-#define IMR1_CORE2_A53			0x1C0
-#define IMR1_CORE3_A53			0x1D0
-#define IMR1_CORE0_M4			0x50
-#define SLT0_CFG			0xB0
-#define GPC_PU_PWRHSK			0x1FC
-#define PGC_CPU_0_1_MAPPING		0xEC
-#define CPU_PGC_UP_TRG			0xF0
-#define PU_PGC_UP_TRG			0xF8
-#define CPU_PGC_DN_TRG			0xFC
-#define PU_PGC_DN_TRG			0x104
-#define A53_CORE0_PGC			0x800
-#define A53_PLAT_PGC			0x900
-#define PLAT_PGC_PCR			0x900
-#define PGC_SCU_TIMING			0x910
-
-#define MASK_DSM_TRIGGER_A53		BIT(31)
-#define IRQ_SRC_A53_WUP			BIT(30)
-#define IRQ_SRC_A53_WUP_SHIFT		30
-#define IRQ_SRC_C1			BIT(29)
-#define IRQ_SRC_C0			BIT(28)
-#define IRQ_SRC_C3			BIT(23)
-#define IRQ_SRC_C2			BIT(22)
-#define CPU_CLOCK_ON_LPM		BIT(14)
-#define A53_CLK_ON_LPM			BIT(14)
-#define MASTER0_LPM_HSK			BIT(6)
-
-#define L2PGE				BIT(31)
-#define EN_L2_WFI_PDN			BIT(5)
-#define EN_PLAT_PDN			BIT(4)
-
-#define SLPCR_EN_DSM			BIT(31)
-#define SLPCR_RBC_EN			BIT(30)
-#define SLPCR_A53_FASTWUP_STOP_MODE	BIT(17)
-#define SLPCR_A53_FASTWUP_WAIT_MODE	BIT(16)
-#define SLPCR_VSTBY			BIT(2)
-#define SLPCR_SBYOS			BIT(1)
-#define SLPCR_BYPASS_PMIC_READY		BIT(0)
-#define SLPCR_RBC_COUNT_SHIFT		24
-#define SLPCR_STBY_COUNT_SHFT		3
-
-#define A53_DUMMY_PDN_ACK		BIT(15)
-#define A53_DUMMY_PUP_ACK		BIT(31)
-#define A53_PLAT_PDN_ACK		BIT(2)
-#define A53_PLAT_PUP_ACK		BIT(18)
-
-#define PLAT_PUP_SLT_CTRL		BIT(9)
-#define PLAT_PDN_SLT_CTRL		BIT(8)
-
-#define SLT_PLAT_PDN			BIT(8)
-#define SLT_PLAT_PUP			BIT(9)
-
-#define MASTER1_MAPPING			BIT(1)
-#define MASTER2_MAPPING			BIT(2)
+#include <gpc_reg.h>
 
 /* helper macro */
 #define A53_LPM_MASK	U(0xF)
@@ -78,7 +16,7 @@
 #define LPM_MODE(local_state)		((local_state) == PLAT_WAIT_RET_STATE ? A53_LPM_WAIT : A53_LPM_STOP)
 
 #define DSM_MODE_MASK	BIT(31)
-
+#define CORE_WKUP_FROM_GIC		(IRQ_SRC_C0 | IRQ_SRC_C1 | IRQ_SRC_C2 | IRQ_SRC_C3)
 #define A53_CORE_WUP_SRC(core_id)	(1 << ((core_id) < 2 ? 28 + (core_id) : 22 + (core_id) - 2))
 #define COREx_PGC_PCR(core_id)		(0x800 + (core_id) * 0x40)
 #define COREx_WFI_PDN(core_id)		(1 << ((core_id) < 2 ? (core_id) * 2 : ((core_id) - 2) * 2 + 16))
@@ -90,6 +28,33 @@
 #define IRQ_IMR_NUM	4
 #define IMR_MASK_ALL	0xffffffff
 
+#define IMX_PD_DOMAIN(name, on)				\
+	{						\
+		.pwr_req = name##_PWR_REQ,		\
+		.pgc_offset = name##_PGC,		\
+		.need_sync = false,			\
+		.always_on = true,			\
+	}
+
+#define IMX_MIX_DOMAIN(name, on)			\
+	{						\
+		.pwr_req = name##_PWR_REQ,		\
+		.pgc_offset = name##_PGC,		\
+		.adb400_sync = name##_ADB400_SYNC,	\
+		.adb400_ack = name##_ADB400_ACK,	\
+		.need_sync = true,			\
+		.always_on = true,			\
+	}
+
+struct imx_pwr_domain {
+	uint32_t pwr_req;
+	uint32_t adb400_sync;
+	uint32_t adb400_ack;
+	uint32_t pgc_offset;
+	bool need_sync;
+	bool always_on;
+};
+
 /* function declare */
 void imx_gpc_init(void);
 void imx_set_cpu_secure_entry(unsigned int core_index, uintptr_t sec_entrypoint);
diff --git a/plat/intel/soc/agilex/bl2_plat_setup.c b/plat/intel/soc/agilex/bl2_plat_setup.c
index a87dea8..f002947 100644
--- a/plat/intel/soc/agilex/bl2_plat_setup.c
+++ b/plat/intel/soc/agilex/bl2_plat_setup.c
@@ -15,6 +15,7 @@
 #include <drivers/ti/uart/uart_16550.h>
 #include <lib/xlat_tables/xlat_tables.h>
 
+#include "agilex_mmc.h"
 #include "agilex_clock_manager.h"
 #include "agilex_memory_controller.h"
 #include "agilex_pinmux.h"
@@ -76,6 +77,7 @@
 	socfpga_emac_init();
 	init_hard_memory_controller();
 	mailbox_init();
+	agx_mmc_init();
 
 	if (!intel_mailbox_is_fpga_not_ready())
 		socfpga_bridges_enable();
diff --git a/plat/intel/soc/agilex/include/agilex_clock_manager.h b/plat/intel/soc/agilex/include/agilex_clock_manager.h
index 8af6a60..20667f0 100644
--- a/plat/intel/soc/agilex/include/agilex_clock_manager.h
+++ b/plat/intel/soc/agilex/include/agilex_clock_manager.h
@@ -89,6 +89,7 @@
 
 /* Peripheral PLL Macros */
 #define CLKMGR_PERPLL_EN_RESET			0x00000fff
+#define CLKMGR_PERPLL_EN_SDMMCCLK		BIT(5)
 #define CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET(x)	(((x) << 0) & 0x0000ffff)
 
 /* Altera Macros */
diff --git a/plat/intel/soc/agilex/include/agilex_mmc.h b/plat/intel/soc/agilex/include/agilex_mmc.h
new file mode 100644
index 0000000..00f4ca5
--- /dev/null
+++ b/plat/intel/soc/agilex/include/agilex_mmc.h
@@ -0,0 +1,7 @@
+/*
+ * Copyright (c) 2020, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+void agx_mmc_init(void);
diff --git a/plat/intel/soc/agilex/platform.mk b/plat/intel/soc/agilex/platform.mk
index 0a91c23..8f857d1 100644
--- a/plat/intel/soc/agilex/platform.mk
+++ b/plat/intel/soc/agilex/platform.mk
@@ -37,6 +37,7 @@
 		plat/intel/soc/agilex/bl2_plat_setup.c			\
 		plat/intel/soc/agilex/soc/agilex_clock_manager.c	\
 		plat/intel/soc/agilex/soc/agilex_memory_controller.c	\
+		plat/intel/soc/agilex/soc/agilex_mmc.c			\
 		plat/intel/soc/agilex/soc/agilex_pinmux.c		\
                 plat/intel/soc/common/bl2_plat_mem_params_desc.c	\
 		plat/intel/soc/common/socfpga_delay_timer.c		\
diff --git a/plat/intel/soc/agilex/soc/agilex_clock_manager.c b/plat/intel/soc/agilex/soc/agilex_clock_manager.c
index c6c48ba..4efd713 100644
--- a/plat/intel/soc/agilex/soc/agilex_clock_manager.c
+++ b/plat/intel/soc/agilex/soc/agilex_clock_manager.c
@@ -47,14 +47,14 @@
 	return 0;
 }
 
-uint32_t pll_source_sync_config(uint32_t pll_mem_offset)
+uint32_t pll_source_sync_config(uint32_t pll_mem_offset, uint32_t data)
 {
 	uint32_t val = 0;
 	uint32_t count = 0;
 	uint32_t req_status = 0;
 
 	val = (CLKMGR_MEM_WR | CLKMGR_MEM_REQ |
-		CLKMGR_MEM_WDAT << CLKMGR_MEM_WDAT_OFFSET | CLKMGR_MEM_ADDR);
+		(data << CLKMGR_MEM_WDAT_OFFSET) | CLKMGR_MEM_ADDR);
 	mmio_write_32(pll_mem_offset, val);
 
 	do {
@@ -89,14 +89,17 @@
 	rdata = mmio_read_32(pll_mem_offset + 0x4);
 	INFO("rdata (%x) = %x\n", pll_mem_offset + 0x4, rdata);
 
-	return 0;
+	return rdata;
 }
 
 void config_clkmgr_handoff(handoff *hoff_ptr)
 {
 	uint32_t mdiv, mscnt, hscnt;
-	uint32_t arefclk_div, drefclk_div;
+	uint32_t drefclk_div, refclk_div, rdata;
 
+	/* Set clock maanger into boot mode before running configuration */
+	mmio_setbits_32(CLKMGR_OFFSET + CLKMGR_CTRL,
+		CLKMGR_CTRL_BOOTMODE_SET_MSK);
 	/* Bypass all mainpllgrp's clocks */
 	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_BYPASS, 0x7);
 	wait_fsm();
@@ -116,26 +119,24 @@
 	/* Setup main PLL dividers */
 	mdiv = CLKMGR_PLLM_MDIV(hoff_ptr->main_pll_pllm);
 
-	arefclk_div = CLKMGR_PLLGLOB_AREFCLKDIV(
-			hoff_ptr->main_pll_pllglob);
 	drefclk_div = CLKMGR_PLLGLOB_DREFCLKDIV(
 			hoff_ptr->main_pll_pllglob);
+	refclk_div = CLKMGR_PLLGLOB_REFCLKDIV(
+			hoff_ptr->main_pll_pllglob);
 
-	mscnt = 100 / (mdiv / BIT(drefclk_div));
+	mscnt = 100 / (mdiv * BIT(drefclk_div));
 	if (!mscnt)
 		mscnt = 1;
-	hscnt = (mdiv * mscnt * BIT(drefclk_div) / arefclk_div) - 4;
+	hscnt = (mdiv * mscnt * BIT(drefclk_div) / refclk_div) - 4;
 
+	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB,
+			hoff_ptr->main_pll_pllglob &
+			~CLKMGR_PLLGLOB_RST_SET_MSK);
+	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_FDBCK,
+			hoff_ptr->main_pll_fdbck);
 	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_VCOCALIB,
 			CLKMGR_VCOCALIB_HSCNT_SET(hscnt) |
 			CLKMGR_VCOCALIB_MSCNT_SET(mscnt));
-
-	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCDIV,
-			hoff_ptr->main_pll_nocdiv);
-	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB,
-			hoff_ptr->main_pll_pllglob);
-	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_FDBCK,
-			hoff_ptr->main_pll_fdbck);
 	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC0,
 			hoff_ptr->main_pll_pllc0);
 	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLC1,
@@ -150,33 +151,33 @@
 			hoff_ptr->main_pll_mpuclk);
 	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCCLK,
 			hoff_ptr->main_pll_nocclk);
+	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCDIV,
+			hoff_ptr->main_pll_nocdiv);
 
 	/* Setup peripheral PLL dividers */
 	mdiv = CLKMGR_PLLM_MDIV(hoff_ptr->per_pll_pllm);
 
-	arefclk_div = CLKMGR_PLLGLOB_AREFCLKDIV(
-			hoff_ptr->per_pll_pllglob);
 	drefclk_div = CLKMGR_PLLGLOB_DREFCLKDIV(
 			hoff_ptr->per_pll_pllglob);
+	refclk_div = CLKMGR_PLLGLOB_REFCLKDIV(
+			hoff_ptr->per_pll_pllglob);
 
-	mscnt = 100 / (mdiv / BIT(drefclk_div));
+
+	mscnt = 100 / (mdiv * BIT(drefclk_div));
 	if (!mscnt)
 		mscnt = 1;
-	hscnt = (mdiv * mscnt * BIT(drefclk_div) / arefclk_div) - 4;
+	hscnt = (mdiv * mscnt * BIT(drefclk_div) / refclk_div) - 4;
+
+	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB,
+			hoff_ptr->per_pll_pllglob &
+			~CLKMGR_PLLGLOB_RST_SET_MSK);
+	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_FDBCK,
+			hoff_ptr->per_pll_fdbck);
 
 	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_VCOCALIB,
 			CLKMGR_VCOCALIB_HSCNT_SET(hscnt) |
 			CLKMGR_VCOCALIB_MSCNT_SET(mscnt));
 
-	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EMACCTL,
-			hoff_ptr->per_pll_emacctl);
-	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_GPIODIV,
-			CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET(
-			hoff_ptr->per_pll_gpiodiv));
-	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB,
-			hoff_ptr->per_pll_pllglob);
-	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_FDBCK,
-			hoff_ptr->per_pll_fdbck);
 	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC0,
 			hoff_ptr->per_pll_pllc0);
 	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLC1,
@@ -187,6 +188,10 @@
 			hoff_ptr->per_pll_pllc3);
 	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLM,
 			hoff_ptr->per_pll_pllm);
+	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EMACCTL,
+			hoff_ptr->per_pll_emacctl);
+	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_GPIODIV,
+			hoff_ptr->per_pll_gpiodiv);
 
 	/* Take both PLL out of reset and power up */
 	mmio_setbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB,
@@ -196,14 +201,17 @@
 			CLKMGR_PLLGLOB_PD_SET_MSK |
 			CLKMGR_PLLGLOB_RST_SET_MSK);
 
+	rdata = pll_source_sync_read(CLKMGR_MAINPLL +
+		CLKMGR_MAINPLL_MEM);
+	pll_source_sync_config(CLKMGR_MAINPLL + CLKMGR_MAINPLL_MEM,
+		rdata | 0x80);
+
+	rdata = pll_source_sync_read(CLKMGR_PERPLL + CLKMGR_PERPLL_MEM);
+	pll_source_sync_config(CLKMGR_PERPLL + CLKMGR_PERPLL_MEM,
+		rdata | 0x80);
+
 	wait_pll_lock();
 
-	pll_source_sync_config(CLKMGR_MAINPLL + CLKMGR_MAINPLL_MEM);
-	pll_source_sync_read(CLKMGR_MAINPLL + CLKMGR_MAINPLL_MEM);
-
-	pll_source_sync_config(CLKMGR_PERPLL + CLKMGR_PERPLL_MEM);
-	pll_source_sync_read(CLKMGR_PERPLL + CLKMGR_PERPLL_MEM);
-
 	/*Configure Ping Pong counters in altera group */
 	mmio_write_32(CLKMGR_ALTERA + CLKMGR_ALTERA_EMACACTR,
 			hoff_ptr->alt_emacactr);
@@ -241,7 +249,7 @@
 
 	/* Clear loss lock  interrupt status register that */
 	/* might be set during configuration */
-	mmio_setbits_32(CLKMGR_OFFSET + CLKMGR_INTRCLR,
+	mmio_clrbits_32(CLKMGR_OFFSET + CLKMGR_INTRCLR,
 			CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK |
 			CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK);
 
diff --git a/plat/intel/soc/agilex/soc/agilex_mmc.c b/plat/intel/soc/agilex/soc/agilex_mmc.c
new file mode 100644
index 0000000..e05d92a
--- /dev/null
+++ b/plat/intel/soc/agilex/soc/agilex_mmc.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2020, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <lib/mmio.h>
+
+#include "socfpga_system_manager.h"
+#include "agilex_clock_manager.h"
+
+void agx_mmc_init(void)
+{
+	mmio_clrbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EN,
+		CLKMGR_PERPLL_EN_SDMMCCLK);
+	mmio_write_32(SOCFPGA_SYSMGR(SDMMC),
+		SYSMGR_SDMMC_SMPLSEL(0) | SYSMGR_SDMMC_DRVSEL(3));
+	mmio_setbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EN,
+		CLKMGR_PERPLL_EN_SDMMCCLK);
+}
diff --git a/plat/intel/soc/agilex/soc/agilex_pinmux.c b/plat/intel/soc/agilex/soc/agilex_pinmux.c
index eff1947..0b908cf 100644
--- a/plat/intel/soc/agilex/soc/agilex_pinmux.c
+++ b/plat/intel/soc/agilex/soc/agilex_pinmux.c
@@ -7,6 +7,7 @@
 #include <lib/mmio.h>
 
 #include "agilex_pinmux.h"
+#include "socfpga_system_manager.h"
 
 const uint32_t sysmgr_pinmux_array_sel[] = {
 	0x00000000, 0x00000001, /* usb */
@@ -185,6 +186,12 @@
 	0x0000011c, 0x00000000
 };
 
+void config_fpgaintf_mod(void)
+{
+	mmio_write_32(SOCFPGA_SYSMGR(FPGAINTF_EN_2), 1<<8);
+}
+
+
 void config_pinmux(handoff *hoff_ptr)
 {
 	unsigned int i;
@@ -213,5 +220,6 @@
 			hoff_ptr->pinmux_iodelay_array[i+1]);
 	}
 
+	config_fpgaintf_mod();
 }
 
diff --git a/plat/intel/soc/common/drivers/ccu/ncore_ccu.c b/plat/intel/soc/common/drivers/ccu/ncore_ccu.c
index fce816b..b4fce7b 100644
--- a/plat/intel/soc/common/drivers/ccu/ncore_ccu.c
+++ b/plat/intel/soc/common/drivers/ccu/ncore_ccu.c
@@ -35,14 +35,12 @@
 	uint32_t dir, sf, ret;
 
 	for (dir = 0; dir < subsystem_id.num_directory; dir++) {
-
-		dir_sf_mtn = DIRECTORY_UNIT(dir, NCORE_DIRUSFMCR);
-		dir_sf_en = DIRECTORY_UNIT(dir, NCORE_DIRUSFER);
-
 		for (sf = 0; sf < subsystem_id.num_snoop_filter; sf++) {
+			dir_sf_mtn = DIRECTORY_UNIT(dir, NCORE_DIRUSFMCR);
+			dir_sf_en = DIRECTORY_UNIT(dir, NCORE_DIRUSFER);
 
 			/* Initialize All Entries */
-			mmio_write_32(dir_sf_mtn, SNOOP_FILTER_ID(sf));
+			mmio_write_32(dir_sf_mtn, SNOOP_FILTER_ID(dir));
 
 			/* Poll Active Bit */
 			ret = poll_active_bit(dir);
@@ -52,7 +50,7 @@
 			}
 
 			/* Snoope Filter Enable */
-			mmio_write_32(dir_sf_en, BIT(sf));
+			mmio_setbits_32(dir_sf_en, BIT(sf));
 		}
 	}
 
@@ -64,11 +62,8 @@
 	uint32_t dir, ca, ca_id, ca_type, ca_snoop_en;
 
 	for (dir = 0; dir < subsystem_id.num_directory; dir++) {
-
-		ca_snoop_en = DIRECTORY_UNIT(dir, NCORE_DIRUCASER0);
-
 		for (ca = 0; ca < subsystem_id.num_coh_agent; ca++) {
-
+			ca_snoop_en = DIRECTORY_UNIT(ca, NCORE_DIRUCASER0);
 			ca_id = mmio_read_32(COH_AGENT_UNIT(ca, NCORE_CAIUIDR));
 
 			/* Coh Agent Snoop Enable */
diff --git a/plat/intel/soc/common/include/socfpga_system_manager.h b/plat/intel/soc/common/include/socfpga_system_manager.h
index 76565bc..8b42d47 100644
--- a/plat/intel/soc/common/include/socfpga_system_manager.h
+++ b/plat/intel/soc/common/include/socfpga_system_manager.h
@@ -13,6 +13,8 @@
 
 #define SOCFPGA_SYSMGR_SDMMC				0x28
 
+#define SOCFPGA_SYSMGR_FPGAINTF_EN_2			0x6c
+
 #define SOCFPGA_SYSMGR_EMAC_0				0x44
 #define SOCFPGA_SYSMGR_EMAC_1				0x48
 #define SOCFPGA_SYSMGR_EMAC_2				0x4c
@@ -32,6 +34,7 @@
 /* Field Masking */
 
 #define SYSMGR_SDMMC_DRVSEL(x)			(((x) & 0x7) << 0)
+#define SYSMGR_SDMMC_SMPLSEL(x)			(((x) & 0x7) << 4)
 
 #define IDLE_DATA_LWSOC2FPGA				BIT(0)
 #define IDLE_DATA_SOC2FPGA				BIT(4)
diff --git a/plat/intel/soc/common/socfpga_delay_timer.c b/plat/intel/soc/common/socfpga_delay_timer.c
index ff8a556..c55cc9d 100644
--- a/plat/intel/soc/common/socfpga_delay_timer.c
+++ b/plat/intel/soc/common/socfpga_delay_timer.c
@@ -36,4 +36,8 @@
 {
 	timer_init(&plat_timer_ops);
 	mmio_write_32(SOCFPGA_GLOBAL_TIMER, SOCFPGA_GLOBAL_TIMER_EN);
+
+	asm volatile("msr cntp_ctl_el0, %0" : : "r" (SOCFPGA_GLOBAL_TIMER_EN));
+	asm volatile("msr cntp_tval_el0, %0" : : "r" (~0));
+
 }
diff --git a/plat/marvell/a3700/a3700/platform.mk b/plat/marvell/a3700/a3700/platform.mk
deleted file mode 100644
index 4f7ac08..0000000
--- a/plat/marvell/a3700/a3700/platform.mk
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# Copyright (C) 2018 Marvell International Ltd.
-#
-# SPDX-License-Identifier:	BSD-3-Clause
-# https://spdx.org/licenses
-#
-
-include plat/marvell/a3700/common/a3700_common.mk
-
-include plat/marvell/common/marvell_common.mk
diff --git a/plat/marvell/a8k/a70x0_amc/platform.mk b/plat/marvell/a8k/a70x0_amc/platform.mk
deleted file mode 100644
index d3a0167..0000000
--- a/plat/marvell/a8k/a70x0_amc/platform.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Copyright (C) 2018 Marvell International Ltd.
-#
-# SPDX-License-Identifier:     BSD-3-Clause
-# https://spdx.org/licenses
-#
-
-PCI_EP_SUPPORT		:= 0
-
-CP_NUM			:= 1
-$(eval $(call add_define,CP_NUM))
-
-DOIMAGE_SEC     	:=	tools/doimage/secure/sec_img_7K.cfg
-
-MARVELL_MOCHI_DRV	:=	drivers/marvell/mochi/apn806_setup.c
-
-include plat/marvell/a8k/common/a8k_common.mk
-
-include plat/marvell/common/marvell_common.mk
diff --git a/plat/marvell/a8k/a80x0/platform.mk b/plat/marvell/a8k/a80x0/platform.mk
deleted file mode 100644
index 00d24b2..0000000
--- a/plat/marvell/a8k/a80x0/platform.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# Copyright (C) 2018 Marvell International Ltd.
-#
-# SPDX-License-Identifier:     BSD-3-Clause
-# https://spdx.org/licenses
-#
-
-PCI_EP_SUPPORT		:= 0
-
-CP_NUM			:= 2
-$(eval $(call add_define,CP_NUM))
-
-DOIMAGE_SEC     	:=	tools/doimage/secure/sec_img_8K.cfg
-
-MARVELL_MOCHI_DRV	:=	drivers/marvell/mochi/apn806_setup.c
-
-include plat/marvell/a8k/common/a8k_common.mk
-
-include plat/marvell/common/marvell_common.mk
-PLAT_INCLUDES		+=	-Iplat/marvell/a8k/a80x0/board
diff --git a/plat/marvell/a3700/a3700/board/pm_src.c b/plat/marvell/armada/a3k/a3700/board/pm_src.c
similarity index 100%
rename from plat/marvell/a3700/a3700/board/pm_src.c
rename to plat/marvell/armada/a3k/a3700/board/pm_src.c
diff --git a/plat/marvell/a3700/a3700/mvebu_def.h b/plat/marvell/armada/a3k/a3700/mvebu_def.h
similarity index 100%
rename from plat/marvell/a3700/a3700/mvebu_def.h
rename to plat/marvell/armada/a3k/a3700/mvebu_def.h
diff --git a/plat/marvell/a3700/a3700/plat_bl31_setup.c b/plat/marvell/armada/a3k/a3700/plat_bl31_setup.c
similarity index 100%
rename from plat/marvell/a3700/a3700/plat_bl31_setup.c
rename to plat/marvell/armada/a3k/a3700/plat_bl31_setup.c
diff --git a/plat/marvell/armada/a3k/a3700/platform.mk b/plat/marvell/armada/a3k/a3700/platform.mk
new file mode 100644
index 0000000..050af41
--- /dev/null
+++ b/plat/marvell/armada/a3k/a3700/platform.mk
@@ -0,0 +1,10 @@
+#
+# Copyright (C) 2018 Marvell International Ltd.
+#
+# SPDX-License-Identifier:	BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+include plat/marvell/armada/a3k/common/a3700_common.mk
+
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/marvell/a3700/common/a3700_common.mk b/plat/marvell/armada/a3k/common/a3700_common.mk
similarity index 97%
rename from plat/marvell/a3700/common/a3700_common.mk
rename to plat/marvell/armada/a3k/common/a3700_common.mk
index 76c0677..9965567 100644
--- a/plat/marvell/a3700/common/a3700_common.mk
+++ b/plat/marvell/armada/a3k/common/a3700_common.mk
@@ -5,9 +5,9 @@
 # https://spdx.org/licenses
 #
 
-MARVELL_PLAT_BASE		:= plat/marvell
-MARVELL_PLAT_INCLUDE_BASE	:= include/plat/marvell
-PLAT_FAMILY			:= a3700
+MARVELL_PLAT_BASE		:= plat/marvell/armada
+MARVELL_PLAT_INCLUDE_BASE	:= include/plat/marvell/armada
+PLAT_FAMILY			:= a3k
 PLAT_FAMILY_BASE		:= $(MARVELL_PLAT_BASE)/$(PLAT_FAMILY)
 PLAT_INCLUDE_BASE		:= $(MARVELL_PLAT_INCLUDE_BASE)/$(PLAT_FAMILY)
 PLAT_COMMON_BASE		:= $(PLAT_FAMILY_BASE)/common
@@ -15,7 +15,7 @@
 MARVELL_COMMON_BASE		:= $(MARVELL_PLAT_BASE)/common
 HANDLE_EA_EL3_FIRST		:= 1
 
-include $(MARVELL_PLAT_BASE)/marvell.mk
+include plat/marvell/marvell.mk
 
 #*********** A3700 *************
 DOIMAGEPATH	:= $(WTP)
diff --git a/plat/marvell/a3700/common/a3700_ea.c b/plat/marvell/armada/a3k/common/a3700_ea.c
similarity index 100%
rename from plat/marvell/a3700/common/a3700_ea.c
rename to plat/marvell/armada/a3k/common/a3700_ea.c
diff --git a/plat/marvell/a3700/common/a3700_sip_svc.c b/plat/marvell/armada/a3k/common/a3700_sip_svc.c
similarity index 100%
rename from plat/marvell/a3700/common/a3700_sip_svc.c
rename to plat/marvell/armada/a3k/common/a3700_sip_svc.c
diff --git a/plat/marvell/a3700/common/aarch64/a3700_common.c b/plat/marvell/armada/a3k/common/aarch64/a3700_common.c
similarity index 100%
rename from plat/marvell/a3700/common/aarch64/a3700_common.c
rename to plat/marvell/armada/a3k/common/aarch64/a3700_common.c
diff --git a/plat/marvell/a3700/common/aarch64/plat_helpers.S b/plat/marvell/armada/a3k/common/aarch64/plat_helpers.S
similarity index 100%
rename from plat/marvell/a3700/common/aarch64/plat_helpers.S
rename to plat/marvell/armada/a3k/common/aarch64/plat_helpers.S
diff --git a/plat/marvell/a3700/common/dram_win.c b/plat/marvell/armada/a3k/common/dram_win.c
similarity index 100%
rename from plat/marvell/a3700/common/dram_win.c
rename to plat/marvell/armada/a3k/common/dram_win.c
diff --git a/plat/marvell/a3700/common/include/a3700_plat_def.h b/plat/marvell/armada/a3k/common/include/a3700_plat_def.h
similarity index 100%
rename from plat/marvell/a3700/common/include/a3700_plat_def.h
rename to plat/marvell/armada/a3k/common/include/a3700_plat_def.h
diff --git a/plat/marvell/a3700/common/include/a3700_pm.h b/plat/marvell/armada/a3k/common/include/a3700_pm.h
similarity index 100%
rename from plat/marvell/a3700/common/include/a3700_pm.h
rename to plat/marvell/armada/a3k/common/include/a3700_pm.h
diff --git a/plat/marvell/a3700/common/include/ddr_info.h b/plat/marvell/armada/a3k/common/include/ddr_info.h
similarity index 100%
rename from plat/marvell/a3700/common/include/ddr_info.h
rename to plat/marvell/armada/a3k/common/include/ddr_info.h
diff --git a/plat/marvell/a3700/common/include/dram_win.h b/plat/marvell/armada/a3k/common/include/dram_win.h
similarity index 100%
rename from plat/marvell/a3700/common/include/dram_win.h
rename to plat/marvell/armada/a3k/common/include/dram_win.h
diff --git a/plat/marvell/a3700/common/include/io_addr_dec.h b/plat/marvell/armada/a3k/common/include/io_addr_dec.h
similarity index 100%
rename from plat/marvell/a3700/common/include/io_addr_dec.h
rename to plat/marvell/armada/a3k/common/include/io_addr_dec.h
diff --git a/plat/marvell/a3700/common/include/plat_macros.S b/plat/marvell/armada/a3k/common/include/plat_macros.S
similarity index 100%
rename from plat/marvell/a3700/common/include/plat_macros.S
rename to plat/marvell/armada/a3k/common/include/plat_macros.S
diff --git a/plat/marvell/a3700/common/include/platform_def.h b/plat/marvell/armada/a3k/common/include/platform_def.h
similarity index 92%
rename from plat/marvell/a3700/common/include/platform_def.h
rename to plat/marvell/armada/a3k/common/include/platform_def.h
index e6660d4..61c7dfe 100644
--- a/plat/marvell/a3700/common/include/platform_def.h
+++ b/plat/marvell/armada/a3k/common/include/platform_def.h
@@ -81,11 +81,13 @@
 #define PLAT_MARVELL_CLUSTER_CORE_COUNT		U(2)
 /* DRAM[2MB..66MB] is used  as Trusted ROM */
 #define PLAT_MARVELL_TRUSTED_ROM_BASE		PLAT_MARVELL_ATF_LOAD_ADDR
-/* 64 MB TODO: reduce this to minimum needed according to fip image size*/
-#define PLAT_MARVELL_TRUSTED_ROM_SIZE		0x04000000
-/* Reserve 16M for SCP (Secure PayLoad) Trusted DRAM */
-#define PLAT_MARVELL_TRUSTED_DRAM_BASE		0x04400000
-#define PLAT_MARVELL_TRUSTED_DRAM_SIZE		0x01000000	/* 16 MB */
+/* 4 MB for FIP image */
+#define PLAT_MARVELL_TRUSTED_ROM_SIZE		0x00400000
+/* Reserve 12M for SCP (Secure PayLoad) Trusted RAM
+ * OP-TEE SHMEM follows this region
+ */
+#define PLAT_MARVELL_TRUSTED_RAM_BASE		0x04400000
+#define PLAT_MARVELL_TRUSTED_RAM_SIZE		0x00C00000	/* 12 MB DRAM */
 
 /*
  * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
@@ -169,8 +171,7 @@
 #define PLAT_MARVELL_NSTIMER_FRAME_ID		1
 
 /* Mailbox base address */
-#define PLAT_MARVELL_MAILBOX_BASE		\
-			(MARVELL_TRUSTED_SRAM_BASE + 0x400)
+#define PLAT_MARVELL_MAILBOX_BASE	(MARVELL_SHARED_RAM_BASE + 0x400)
 #define PLAT_MARVELL_MAILBOX_SIZE		0x100
 #define PLAT_MARVELL_MAILBOX_MAGIC_NUM		0x6D72766C	/* mrvl */
 
@@ -221,12 +222,4 @@
 /* Securities */
 #define IRQ_SEC_OS_TICK_INT	MARVELL_IRQ_SEC_PHY_TIMER
 
-#define TRUSTED_DRAM_BASE	PLAT_MARVELL_TRUSTED_DRAM_BASE
-#define TRUSTED_DRAM_SIZE	PLAT_MARVELL_TRUSTED_DRAM_SIZE
-
-#ifdef BL32
-#define BL32_BASE		TRUSTED_DRAM_BASE
-#define BL32_LIMIT		TRUSTED_DRAM_SIZE
-#endif
-
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/marvell/a3700/common/io_addr_dec.c b/plat/marvell/armada/a3k/common/io_addr_dec.c
similarity index 100%
rename from plat/marvell/a3700/common/io_addr_dec.c
rename to plat/marvell/armada/a3k/common/io_addr_dec.c
diff --git a/plat/marvell/a3700/common/marvell_plat_config.c b/plat/marvell/armada/a3k/common/marvell_plat_config.c
similarity index 100%
rename from plat/marvell/a3700/common/marvell_plat_config.c
rename to plat/marvell/armada/a3k/common/marvell_plat_config.c
diff --git a/plat/marvell/a3700/common/plat_pm.c b/plat/marvell/armada/a3k/common/plat_pm.c
similarity index 100%
rename from plat/marvell/a3700/common/plat_pm.c
rename to plat/marvell/armada/a3k/common/plat_pm.c
diff --git a/plat/marvell/a8k/a70x0/board/dram_port.c b/plat/marvell/armada/a8k/a70x0/board/dram_port.c
similarity index 100%
rename from plat/marvell/a8k/a70x0/board/dram_port.c
rename to plat/marvell/armada/a8k/a70x0/board/dram_port.c
diff --git a/plat/marvell/a8k/a70x0/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c
similarity index 94%
rename from plat/marvell/a8k/a70x0/board/marvell_plat_config.c
rename to plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c
index d126f55..a409261 100644
--- a/plat/marvell/a8k/a70x0/board/marvell_plat_config.c
+++ b/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c
@@ -102,6 +102,12 @@
 #ifdef IMAGE_BLE
 	{0x00000000f2000000,	0x4000000,	IO_0_TID}, /* IO window */
 #else
+#if LLC_SRAM
+	/* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+	 * and changes the window target to SRAM_TID.
+	 */
+	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
+#endif
 	{0x00000000f2000000,	0xe000000,	IO_0_TID},
 	{0x00000000c0000000,	0x30000000,	IO_0_TID}, /* IO window */
 	{0x0000000800000000,	0x100000000,	IO_0_TID}, /* IO window */
diff --git a/plat/marvell/a8k/a70x0/mvebu_def.h b/plat/marvell/armada/a8k/a70x0/mvebu_def.h
similarity index 100%
rename from plat/marvell/a8k/a70x0/mvebu_def.h
rename to plat/marvell/armada/a8k/a70x0/mvebu_def.h
diff --git a/plat/marvell/a8k/a70x0/platform.mk b/plat/marvell/armada/a8k/a70x0/platform.mk
similarity index 65%
rename from plat/marvell/a8k/a70x0/platform.mk
rename to plat/marvell/armada/a8k/a70x0/platform.mk
index d3a0167..39eb712 100644
--- a/plat/marvell/a8k/a70x0/platform.mk
+++ b/plat/marvell/armada/a8k/a70x0/platform.mk
@@ -14,6 +14,7 @@
 
 MARVELL_MOCHI_DRV	:=	drivers/marvell/mochi/apn806_setup.c
 
-include plat/marvell/a8k/common/a8k_common.mk
+BOARD_DIR		:= $(shell dirname $(lastword $(MAKEFILE_LIST)))
+include plat/marvell/armada/a8k/common/a8k_common.mk
 
-include plat/marvell/common/marvell_common.mk
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/marvell/a8k/a70x0_amc/board/dram_port.c b/plat/marvell/armada/a8k/a70x0_amc/board/dram_port.c
similarity index 100%
rename from plat/marvell/a8k/a70x0_amc/board/dram_port.c
rename to plat/marvell/armada/a8k/a70x0_amc/board/dram_port.c
diff --git a/plat/marvell/a8k/a70x0_amc/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c
similarity index 93%
rename from plat/marvell/a8k/a70x0_amc/board/marvell_plat_config.c
rename to plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c
index f8a1c40..3b68e91 100644
--- a/plat/marvell/a8k/a70x0_amc/board/marvell_plat_config.c
+++ b/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c
@@ -93,6 +93,12 @@
 #ifdef IMAGE_BLE
 	{0x00000000f2000000,	0x4000000,	IO_0_TID}, /* IO window */
 #else
+#if LLC_SRAM
+	/* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+	 * and changes the window target to SRAM_TID.
+	 */
+	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
+#endif
 	{0x00000000f2000000,	0xe000000,	IO_0_TID},
 	{0x00000000c0000000,    0x30000000,	IO_0_TID}, /* IO window */
 	{0x0000000800000000,    0x200000000,	IO_0_TID}, /* IO window */
diff --git a/plat/marvell/a8k/a70x0_amc/mvebu_def.h b/plat/marvell/armada/a8k/a70x0_amc/mvebu_def.h
similarity index 100%
rename from plat/marvell/a8k/a70x0_amc/mvebu_def.h
rename to plat/marvell/armada/a8k/a70x0_amc/mvebu_def.h
diff --git a/plat/marvell/a8k/a70x0/platform.mk b/plat/marvell/armada/a8k/a70x0_amc/platform.mk
similarity index 65%
copy from plat/marvell/a8k/a70x0/platform.mk
copy to plat/marvell/armada/a8k/a70x0_amc/platform.mk
index d3a0167..39eb712 100644
--- a/plat/marvell/a8k/a70x0/platform.mk
+++ b/plat/marvell/armada/a8k/a70x0_amc/platform.mk
@@ -14,6 +14,7 @@
 
 MARVELL_MOCHI_DRV	:=	drivers/marvell/mochi/apn806_setup.c
 
-include plat/marvell/a8k/common/a8k_common.mk
+BOARD_DIR		:= $(shell dirname $(lastword $(MAKEFILE_LIST)))
+include plat/marvell/armada/a8k/common/a8k_common.mk
 
-include plat/marvell/common/marvell_common.mk
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/marvell/a8k/a80x0/board/dram_port.c b/plat/marvell/armada/a8k/a80x0/board/dram_port.c
similarity index 97%
rename from plat/marvell/a8k/a80x0/board/dram_port.c
rename to plat/marvell/armada/a8k/a80x0/board/dram_port.c
index 02f4ffb..017d8a7 100644
--- a/plat/marvell/a8k/a80x0/board/dram_port.c
+++ b/plat/marvell/armada/a8k/a80x0/board/dram_port.c
@@ -52,7 +52,11 @@
 	   MV_DDR_FREQ_SAR,		/* frequency */
 	   0, 0,			/* cas_l, cas_wl */
 	   MV_DDR_TEMP_LOW} },		/* temperature */
+#if DDR32
+	MV_DDR_32BIT_ECC_PUP8_BUS_MASK, /* subphys mask */
+#else
 	MV_DDR_64BIT_ECC_PUP8_BUS_MASK, /* subphys mask */
+#endif
 	MV_DDR_CFG_SPD,			/* ddr configuration data source */
 	{ {0} },			/* raw spd data */
 	{0},				/* timing parameters */
diff --git a/plat/marvell/a8k/a80x0/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c
similarity index 95%
rename from plat/marvell/a8k/a80x0/board/marvell_plat_config.c
rename to plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c
index 7901dd2..4ccda14 100644
--- a/plat/marvell/a8k/a80x0/board/marvell_plat_config.c
+++ b/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c
@@ -131,6 +131,12 @@
 #ifdef IMAGE_BLE
 	{0x00000000f2000000,	0x4000000,  IO_0_TID}, /* IO window */
 #else
+#if LLC_SRAM
+	/* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+	 * and changes the window target to SRAM_TID.
+	 */
+	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
+#endif
 	{0x00000000f2000000,	0xe000000,  IO_0_TID}, /* IO window */
 	{0x00000000c0000000,	0x30000000,  IO_0_TID}, /* IO window */
 	{0x0000000800000000,	0x100000000,  IO_0_TID}, /* IO window */
diff --git a/plat/marvell/a8k/a80x0/board/phy-porting-layer.h b/plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h
similarity index 100%
rename from plat/marvell/a8k/a80x0/board/phy-porting-layer.h
rename to plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h
diff --git a/plat/marvell/a8k/a80x0/mvebu_def.h b/plat/marvell/armada/a8k/a80x0/mvebu_def.h
similarity index 100%
rename from plat/marvell/a8k/a80x0/mvebu_def.h
rename to plat/marvell/armada/a8k/a80x0/mvebu_def.h
diff --git a/plat/marvell/a8k/a80x0_mcbin/platform.mk b/plat/marvell/armada/a8k/a80x0/platform.mk
similarity index 65%
copy from plat/marvell/a8k/a80x0_mcbin/platform.mk
copy to plat/marvell/armada/a8k/a80x0/platform.mk
index 3749c37..115dd4a 100644
--- a/plat/marvell/a8k/a80x0_mcbin/platform.mk
+++ b/plat/marvell/armada/a8k/a80x0/platform.mk
@@ -14,6 +14,7 @@
 
 MARVELL_MOCHI_DRV	:=	drivers/marvell/mochi/apn806_setup.c
 
-include plat/marvell/a8k/common/a8k_common.mk
+BOARD_DIR		:= $(shell dirname $(lastword $(MAKEFILE_LIST)))
+include plat/marvell/armada/a8k/common/a8k_common.mk
 
-include plat/marvell/common/marvell_common.mk
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/marvell/a8k/a80x0_mcbin/board/dram_port.c b/plat/marvell/armada/a8k/a80x0_mcbin/board/dram_port.c
similarity index 100%
rename from plat/marvell/a8k/a80x0_mcbin/board/dram_port.c
rename to plat/marvell/armada/a8k/a80x0_mcbin/board/dram_port.c
diff --git a/plat/marvell/a8k/a80x0_mcbin/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c
similarity index 94%
copy from plat/marvell/a8k/a80x0_mcbin/board/marvell_plat_config.c
copy to plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c
index fa4e144..75a1b0c 100644
--- a/plat/marvell/a8k/a80x0_mcbin/board/marvell_plat_config.c
+++ b/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c
@@ -78,12 +78,8 @@
 	/* CP1 (MCI0) internal regs */
 	{0x00000000f4000000,		0x2000000,  MCI_0_TID},
 #ifndef IMAGE_BLE
-	/* PCIe0 and SPI1_CS0 (RUNIT) on CP1*/
-	{0x00000000f9000000,		0x2000000,  MCI_0_TID},
-	/* PCIe1 on CP1*/
-	{0x00000000fb000000,		0x1000000,  MCI_0_TID},
-	/* PCIe2 on CP1*/
-	{0x00000000fc000000,		0x1000000,  MCI_0_TID},
+	/* PCIe0-2 and SPI1_CS0 (RUNIT) on CP1*/
+	{0x00000000f9000000,		0x4000000,  MCI_0_TID},
 	/* MCI 0 indirect window */
 	{MVEBU_MCI_REG_BASE_REMAP(0),	0x100000,   MCI_0_TID},
 	/* MCI 1 indirect window */
@@ -165,6 +161,12 @@
 #ifdef IMAGE_BLE
 	{0x00000000f2000000,	0x4000000,  IO_0_TID}, /* IO window */
 #else
+#if LLC_SRAM
+	/* This entry is prepared for OP-TEE OS that enables the LLC SRAM
+	 * and changes the window target to SRAM_TID.
+	 */
+	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
+#endif
 	{0x00000000f2000000,	0xe000000,  IO_0_TID}, /* IO window */
 	{0x00000000c0000000,	0x30000000,  IO_0_TID}, /* IO window */
 	{0x0000000800000000,	0x100000000,  IO_0_TID}, /* IO window */
diff --git a/plat/marvell/a8k/a80x0_mcbin/mvebu_def.h b/plat/marvell/armada/a8k/a80x0_mcbin/mvebu_def.h
similarity index 100%
rename from plat/marvell/a8k/a80x0_mcbin/mvebu_def.h
rename to plat/marvell/armada/a8k/a80x0_mcbin/mvebu_def.h
diff --git a/plat/marvell/a8k/a80x0_mcbin/platform.mk b/plat/marvell/armada/a8k/a80x0_mcbin/platform.mk
similarity index 65%
copy from plat/marvell/a8k/a80x0_mcbin/platform.mk
copy to plat/marvell/armada/a8k/a80x0_mcbin/platform.mk
index 3749c37..115dd4a 100644
--- a/plat/marvell/a8k/a80x0_mcbin/platform.mk
+++ b/plat/marvell/armada/a8k/a80x0_mcbin/platform.mk
@@ -14,6 +14,7 @@
 
 MARVELL_MOCHI_DRV	:=	drivers/marvell/mochi/apn806_setup.c
 
-include plat/marvell/a8k/common/a8k_common.mk
+BOARD_DIR		:= $(shell dirname $(lastword $(MAKEFILE_LIST)))
+include plat/marvell/armada/a8k/common/a8k_common.mk
 
-include plat/marvell/common/marvell_common.mk
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/marvell/a8k/a80x0/board/dram_port.c b/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c
similarity index 79%
copy from plat/marvell/a8k/a80x0/board/dram_port.c
copy to plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c
index 02f4ffb..46a9a26 100644
--- a/plat/marvell/a8k/a80x0/board/dram_port.c
+++ b/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c
@@ -14,11 +14,11 @@
 #include <mvebu_def.h>
 #include <plat_marvell.h>
 
-#define MVEBU_AP_MPP_CTRL0_7_REG		MVEBU_AP_MPP_REGS(0)
-#define MVEBU_AP_MPP_CTRL4_OFFS			16
-#define MVEBU_AP_MPP_CTRL5_OFFS			20
-#define MVEBU_AP_MPP_CTRL4_I2C0_SDA_ENA		0x3
-#define MVEBU_AP_MPP_CTRL5_I2C0_SCK_ENA		0x3
+#define MVEBU_AP_MPP_CTRL0_7_REG                MVEBU_AP_MPP_REGS(0)
+#define MVEBU_AP_MPP_CTRL4_OFFS                 16
+#define MVEBU_AP_MPP_CTRL5_OFFS                 20
+#define MVEBU_AP_MPP_CTRL4_I2C0_SDA_ENA         0x3
+#define MVEBU_AP_MPP_CTRL5_I2C0_SCK_ENA         0x3
 
 #define MVEBU_CP_MPP_CTRL37_OFFS		20
 #define MVEBU_CP_MPP_CTRL38_OFFS		24
@@ -32,7 +32,7 @@
  * the appropriate board DRAM configuration
  */
 static struct mv_ddr_topology_map board_topology_map = {
-	/* MISL board with 1CS 8Gb x4 devices of Micron 2400T */
+	/* Board with 1CS 8Gb x4 devices of Micron 2400T */
 	DEBUG_LEVEL_ERROR,
 	0x1, /* active interfaces */
 	/* cs_mask, mirror, dqs_swap, ck_swap X subphys */
@@ -52,8 +52,8 @@
 	   MV_DDR_FREQ_SAR,		/* frequency */
 	   0, 0,			/* cas_l, cas_wl */
 	   MV_DDR_TEMP_LOW} },		/* temperature */
-	MV_DDR_64BIT_ECC_PUP8_BUS_MASK, /* subphys mask */
-	MV_DDR_CFG_SPD,			/* ddr configuration data source */
+	   MV_DDR_64BIT_BUS_MASK,	/* subphys mask */
+	   MV_DDR_CFG_SPD,		/* ddr configuration data source */
 	{ {0} },			/* raw spd data */
 	{0},				/* timing parameters */
 	{				/* electrical configuration */
@@ -99,18 +99,18 @@
 
 static void mpp_config(void)
 {
-	uintptr_t reg;
 	uint32_t val;
+	uintptr_t reg;
 
-	reg = MVEBU_CP_MPP_REGS(0, 4);
-	/* configure CP0 MPP 37 and 38 to i2c */
+       /* configure ap mmps 4, 5 to I2C */
+	reg = MVEBU_AP_MPP_CTRL0_7_REG;
+
 	val = mmio_read_32(reg);
-	val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL37_OFFS) |
-		(MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL38_OFFS));
-	val |= (MVEBU_CP_MPP_CTRL37_I2C0_SCK_ENA <<
-			MVEBU_CP_MPP_CTRL37_OFFS) |
-		(MVEBU_CP_MPP_CTRL38_I2C0_SDA_ENA <<
-			MVEBU_CP_MPP_CTRL38_OFFS);
+	val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_AP_MPP_CTRL4_OFFS) |
+		(MVEBU_MPP_CTRL_MASK << MVEBU_AP_MPP_CTRL5_OFFS));
+	val |= ((MVEBU_AP_MPP_CTRL4_I2C0_SDA_ENA << MVEBU_AP_MPP_CTRL4_OFFS) |
+		(MVEBU_AP_MPP_CTRL5_I2C0_SCK_ENA << MVEBU_AP_MPP_CTRL5_OFFS));
+
 	mmio_write_32(reg, val);
 }
 
@@ -128,13 +128,10 @@
 	if (tm->cfg_src == MV_DDR_CFG_SPD) {
 		/* configure MPPs to enable i2c */
 		mpp_config();
-
-		/* initialize i2c */
-		i2c_init((void *)MVEBU_CP0_I2C_BASE);
-
+		/* initialize the MVEBU_AP_I2C_BASE I2C bus */
+		i2c_init((void *)MVEBU_AP_I2C_BASE);
 		/* select SPD memory page 0 to access DRAM configuration */
 		i2c_write(I2C_SPD_P0_ADDR, 0x0, 1, tm->spd_data.all_bytes, 1);
-
 		/* read data from spd */
 		i2c_read(I2C_SPD_ADDR, 0x0, 1, tm->spd_data.all_bytes,
 			 sizeof(tm->spd_data.all_bytes));
diff --git a/plat/marvell/a8k/a80x0_mcbin/board/marvell_plat_config.c b/plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c
similarity index 97%
rename from plat/marvell/a8k/a80x0_mcbin/board/marvell_plat_config.c
rename to plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c
index fa4e144..0edc977 100644
--- a/plat/marvell/a8k/a80x0_mcbin/board/marvell_plat_config.c
+++ b/plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c
@@ -165,6 +165,9 @@
 #ifdef IMAGE_BLE
 	{0x00000000f2000000,	0x4000000,  IO_0_TID}, /* IO window */
 #else
+#if LLC_SRAM
+	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, SRAM_TID},
+#endif
 	{0x00000000f2000000,	0xe000000,  IO_0_TID}, /* IO window */
 	{0x00000000c0000000,	0x30000000,  IO_0_TID}, /* IO window */
 	{0x0000000800000000,	0x100000000,  IO_0_TID}, /* IO window */
diff --git a/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c b/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c
new file mode 100644
index 0000000..5147dd5
--- /dev/null
+++ b/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2020 Sartura Ltd.
+ * Author: Luka Kovacic <luka.kovacic@sartura.hr>
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <armada_common.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <drivers/console.h>
+#include <plat_marvell.h>
+
+/*****************************************************************************
+ * Platform specific power off functions
+ * Power off PSU / Send command to power management MCU / ...
+ *****************************************************************************
+ */
+
+unsigned char add_xor_checksum(unsigned char *buf, unsigned char xor_len)
+{
+	unsigned char xor_sum = 0;
+	unsigned int i;
+
+	for (i = 0; i < xor_len; i++)
+		xor_sum ^= buf[i];
+
+	return xor_sum;
+}
+
+int system_power_off(void)
+{
+	static console_t console;
+
+	/* WT61P803 MCU system_off_now command */
+	unsigned char system_off_now[4] = { '@', 'C', '0' };
+	int i, len;
+
+	len = sizeof(system_off_now);
+	system_off_now[len - 1] = add_xor_checksum(system_off_now, len);
+
+	console_16550_register(PLAT_MARVELL_BOOT_UART_BASE + 0x100,
+		PLAT_MARVELL_BOOT_UART_CLK_IN_HZ, 115200, &console);
+
+	/* Send system_off_now to console */
+	for (i = 0; i < len; i++) {
+		console.putc(system_off_now[i],	&console);
+		udelay(1000);
+	}
+
+	console.flush(&console);
+	(void)console_unregister(&console);
+
+	mdelay(100);
+
+	return 0;
+}
diff --git a/plat/marvell/a8k/a80x0/mvebu_def.h b/plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h
similarity index 100%
copy from plat/marvell/a8k/a80x0/mvebu_def.h
copy to plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h
diff --git a/plat/marvell/a8k/a80x0_mcbin/platform.mk b/plat/marvell/armada/a8k/a80x0_puzzle/platform.mk
similarity index 65%
rename from plat/marvell/a8k/a80x0_mcbin/platform.mk
rename to plat/marvell/armada/a8k/a80x0_puzzle/platform.mk
index 3749c37..3378d53 100644
--- a/plat/marvell/a8k/a80x0_mcbin/platform.mk
+++ b/plat/marvell/armada/a8k/a80x0_puzzle/platform.mk
@@ -14,6 +14,7 @@
 
 MARVELL_MOCHI_DRV	:=	drivers/marvell/mochi/apn806_setup.c
 
-include plat/marvell/a8k/common/a8k_common.mk
+BOARD_DIR		:= 	$(shell dirname $(lastword $(MAKEFILE_LIST)))
+include plat/marvell/armada/a8k/common/a8k_common.mk
 
-include plat/marvell/common/marvell_common.mk
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/marvell/a8k/common/a8k_common.mk b/plat/marvell/armada/a8k/common/a8k_common.mk
similarity index 82%
rename from plat/marvell/a8k/common/a8k_common.mk
rename to plat/marvell/armada/a8k/common/a8k_common.mk
index bf79ebe..02f1553 100644
--- a/plat/marvell/a8k/common/a8k_common.mk
+++ b/plat/marvell/armada/a8k/common/a8k_common.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2016 - 2018 Marvell International Ltd.
+# Copyright (C) 2016 - 2020 Marvell International Ltd.
 #
 # SPDX-License-Identifier:     BSD-3-Clause
 # https://spdx.org/licenses
@@ -7,11 +7,10 @@
 include tools/marvell/doimage/doimage.mk
 
 PLAT_FAMILY		:= a8k
-PLAT_FAMILY_BASE	:= plat/marvell/$(PLAT_FAMILY)
-PLAT_INCLUDE_BASE	:= include/plat/marvell/$(PLAT_FAMILY)
-PLAT_COMMON_BASE	:= $(PLAT_FAMILY_BASE)/common
+PLAT_INCLUDE_BASE	:= include/plat/marvell/armada/$(PLAT_FAMILY)
+PLAT_COMMON_BASE	:= plat/marvell/armada/a8k/common
 MARVELL_DRV_BASE	:= drivers/marvell
-MARVELL_COMMON_BASE	:= plat/marvell/common
+MARVELL_COMMON_BASE	:= plat/marvell/armada/common
 
 MARVELL_SVC_TEST		:= 0
 $(eval $(call add_define,MARVELL_SVC_TEST))
@@ -22,7 +21,7 @@
 MSS_SUPPORT		:= 1
 
 # Disable EL3 cache for power management
-BL31_CACHE_DISABLE	:= 1
+BL31_CACHE_DISABLE	:= 0
 $(eval $(call add_define,BL31_CACHE_DISABLE))
 
 $(eval $(call add_define,PCI_EP_SUPPORT))
@@ -38,7 +37,7 @@
 DOIMAGE_FLAGS	+= -b $(ROM_BIN_EXT) $(NAND_DOIMAGE_FLAGS) $(DOIMAGE_SEC_FLAGS)
 
 # Check whether to build system_power.c for the platform
-ifneq ("$(wildcard $(PLAT_FAMILY_BASE)/$(PLAT)/board/system_power.c)","")
+ifneq ("$(wildcard $(BOARD_DIR)/board/system_power.c)","")
 SYSTEM_POWER_SUPPORT = 1
 else
 SYSTEM_POWER_SUPPORT = 0
@@ -52,15 +51,16 @@
 				drivers/arm/gic/v2/gicv2_helpers.c	\
 				plat/common/plat_gicv2.c
 
-PLAT_INCLUDES		:=	-I$(PLAT_FAMILY_BASE)/$(PLAT)		\
+PLAT_INCLUDES		:=	-I$(BOARD_DIR)				\
+				-I$(BOARD_DIR)/board			\
 				-I$(PLAT_COMMON_BASE)/include		\
 				-I$(PLAT_INCLUDE_BASE)/common
 
 PLAT_BL_COMMON_SOURCES	:=	$(PLAT_COMMON_BASE)/aarch64/a8k_common.c \
 				drivers/ti/uart/aarch64/16550_console.S
 
-BLE_PORTING_SOURCES	:=	$(PLAT_FAMILY_BASE)/$(PLAT)/board/dram_port.c \
-				$(PLAT_FAMILY_BASE)/$(PLAT)/board/marvell_plat_config.c
+BLE_PORTING_SOURCES	:=	$(BOARD_DIR)/board/dram_port.c \
+				$(BOARD_DIR)/board/marvell_plat_config.c
 
 MARVELL_MOCHI_DRV	+=	$(MARVELL_DRV_BASE)/mochi/cp110_setup.c
 
@@ -85,12 +85,13 @@
 				$(MARVELL_DRV_BASE)/ccu.c	\
 				$(MARVELL_DRV_BASE)/cache_llc.c	\
 				$(MARVELL_DRV_BASE)/comphy/phy-comphy-cp110.c \
-				$(MARVELL_DRV_BASE)/mc_trustzone/mc_trustzone.c
+				$(MARVELL_DRV_BASE)/mc_trustzone/mc_trustzone.c \
+				$(MARVELL_DRV_BASE)/mg_conf_cm3/mg_conf_cm3.c
 
-BL31_PORTING_SOURCES	:=	$(PLAT_FAMILY_BASE)/$(PLAT)/board/marvell_plat_config.c
+BL31_PORTING_SOURCES	:=	$(BOARD_DIR)/board/marvell_plat_config.c
 
 ifeq ($(SYSTEM_POWER_SUPPORT),1)
-BL31_PORTING_SOURCES	+=	$(PLAT_FAMILY_BASE)/$(PLAT)/board/system_power.c
+BL31_PORTING_SOURCES	+=	$(BOARD_DIR)/board/system_power.c
 endif
 
 BL31_SOURCES		+=	lib/cpus/aarch64/cortex_a72.S		       \
diff --git a/plat/marvell/a8k/common/aarch64/a8k_common.c b/plat/marvell/armada/a8k/common/aarch64/a8k_common.c
similarity index 82%
rename from plat/marvell/a8k/common/aarch64/a8k_common.c
rename to plat/marvell/armada/a8k/common/aarch64/a8k_common.c
index 7c2bf31..4332a76 100644
--- a/plat/marvell/a8k/common/aarch64/a8k_common.c
+++ b/plat/marvell/armada/a8k/common/aarch64/a8k_common.c
@@ -18,22 +18,27 @@
  */
 #if IMAGE_BL1
 const mmap_region_t plat_marvell_mmap[] = {
-	MARVELL_MAP_SHARED_RAM,
+	MARVELL_MAP_SECURE_RAM,
 	MAP_DEVICE0,
 	{0}
 };
 #endif
 #if IMAGE_BL2
 const mmap_region_t plat_marvell_mmap[] = {
-	MARVELL_MAP_SHARED_RAM,
+	MARVELL_MAP_SECURE_RAM,
 	MAP_DEVICE0,
 	MARVELL_MAP_DRAM,
+#ifdef SPD_opteed
+	MARVELL_MAP_OPTEE_CORE_MEM,
+	MARVELL_OPTEE_PAGEABLE_LOAD_MEM,
+#endif
 	{0}
 };
 #endif
 
 #if IMAGE_BL2U
 const mmap_region_t plat_marvell_mmap[] = {
+	MARVELL_MAP_SECURE_RAM,
 	MAP_DEVICE0,
 	{0}
 };
@@ -48,7 +53,7 @@
 
 #if IMAGE_BL31
 const mmap_region_t plat_marvell_mmap[] = {
-	MARVELL_MAP_SHARED_RAM,
+	MARVELL_MAP_SECURE_RAM,
 	MAP_DEVICE0,
 	MARVELL_MAP_DRAM,
 	{0}
@@ -56,6 +61,7 @@
 #endif
 #if IMAGE_BL32
 const mmap_region_t plat_marvell_mmap[] = {
+	MARVELL_MAP_SECURE_RAM,
 	MAP_DEVICE0,
 	{0}
 };
diff --git a/plat/marvell/a8k/common/aarch64/plat_arch_config.c b/plat/marvell/armada/a8k/common/aarch64/plat_arch_config.c
similarity index 72%
rename from plat/marvell/a8k/common/aarch64/plat_arch_config.c
rename to plat/marvell/armada/a8k/common/aarch64/plat_arch_config.c
index 06dc841..9facdbc 100644
--- a/plat/marvell/a8k/common/aarch64/plat_arch_config.c
+++ b/plat/marvell/armada/a8k/common/aarch64/plat_arch_config.c
@@ -13,7 +13,21 @@
 
 #define CCU_HTC_ASET			(MVEBU_CCU_BASE(MVEBU_AP0) + 0x264)
 #define MVEBU_IO_AFFINITY		(0xF00)
+#define MVEBU_SF_REG			(MVEBU_REGS_BASE + 0x40)
+#define MVEBU_SF_EN			BIT(8)
 
+#ifdef MVEBU_SOC_AP807
+static void plat_enable_snoop_filter(void)
+{
+	int cpu_id = plat_my_core_pos();
+
+	/* Snoop filter needs to be enabled once per cluster */
+	if (cpu_id % 2)
+		return;
+
+	mmio_setbits_32(MVEBU_SF_REG, MVEBU_SF_EN);
+}
+#endif
 
 static void plat_enable_affinity(void)
 {
@@ -42,4 +56,8 @@
 
 	/* Enable Affinity */
 	plat_enable_affinity();
+
+#ifdef MVEBU_SOC_AP807
+	plat_enable_snoop_filter();
+#endif
 }
diff --git a/plat/marvell/a8k/common/aarch64/plat_helpers.S b/plat/marvell/armada/a8k/common/aarch64/plat_helpers.S
similarity index 100%
rename from plat/marvell/a8k/common/aarch64/plat_helpers.S
rename to plat/marvell/armada/a8k/common/aarch64/plat_helpers.S
diff --git a/plat/marvell/a8k/common/ble/ble.ld.S b/plat/marvell/armada/a8k/common/ble/ble.ld.S
similarity index 100%
rename from plat/marvell/a8k/common/ble/ble.ld.S
rename to plat/marvell/armada/a8k/common/ble/ble.ld.S
diff --git a/plat/marvell/a8k/common/ble/ble.mk b/plat/marvell/armada/a8k/common/ble/ble.mk
similarity index 75%
rename from plat/marvell/a8k/common/ble/ble.mk
rename to plat/marvell/armada/a8k/common/ble/ble.mk
index b6a9cd2..60fbf5f 100644
--- a/plat/marvell/a8k/common/ble/ble.mk
+++ b/plat/marvell/armada/a8k/common/ble/ble.mk
@@ -5,10 +5,10 @@
 
 MV_DDR_PATH		?=	drivers/marvell/mv_ddr
 
-MV_DDR_LIB		= 	$(CURDIR)/$(BUILD_PLAT)/ble/mv_ddr_lib.a
-LIBC_LIB		=	$(CURDIR)/$(BUILD_PLAT)/lib/libc.a
-BLE_LIBS		= 	$(MV_DDR_LIB) $(LIBC_LIB)
-PLAT_MARVELL		=	plat/marvell
+MV_DDR_LIB		=	$(BUILD_PLAT)/ble/mv_ddr_lib.a
+LIBC_LIB		=	$(BUILD_PLAT)/lib/libc.a
+BLE_LIBS		=	$(MV_DDR_LIB) $(LIBC_LIB)
+PLAT_MARVELL		=	plat/marvell/armada
 
 BLE_SOURCES		+= 	$(BLE_PATH)/ble_main.c				\
 				$(BLE_PATH)/ble_mem.S				\
@@ -29,4 +29,4 @@
 FORCE:
 
 $(MV_DDR_LIB): FORCE
-	@+make -C $(MV_DDR_PATH) --no-print-directory PLAT_INCLUDES="$(PLAT_INCLUDES)" PLATFORM=$(PLAT) ARCH=AARCH64 OBJ_DIR=$(CURDIR)/$(BUILD_PLAT)/ble
+	@+make -C $(MV_DDR_PATH) --no-print-directory PLAT_INCLUDES="$(PLAT_INCLUDES)" PLATFORM=$(PLAT) ARCH=AARCH64 OBJ_DIR=$(BUILD_PLAT)/ble
diff --git a/plat/marvell/a8k/common/ble/ble_main.c b/plat/marvell/armada/a8k/common/ble/ble_main.c
similarity index 100%
rename from plat/marvell/a8k/common/ble/ble_main.c
rename to plat/marvell/armada/a8k/common/ble/ble_main.c
diff --git a/plat/marvell/a8k/common/ble/ble_mem.S b/plat/marvell/armada/a8k/common/ble/ble_mem.S
similarity index 100%
rename from plat/marvell/a8k/common/ble/ble_mem.S
rename to plat/marvell/armada/a8k/common/ble/ble_mem.S
diff --git a/plat/marvell/a8k/common/include/a8k_plat_def.h b/plat/marvell/armada/a8k/common/include/a8k_plat_def.h
similarity index 100%
rename from plat/marvell/a8k/common/include/a8k_plat_def.h
rename to plat/marvell/armada/a8k/common/include/a8k_plat_def.h
diff --git a/plat/marvell/a8k/common/include/ddr_info.h b/plat/marvell/armada/a8k/common/include/ddr_info.h
similarity index 100%
rename from plat/marvell/a8k/common/include/ddr_info.h
rename to plat/marvell/armada/a8k/common/include/ddr_info.h
diff --git a/plat/marvell/a8k/common/include/mentor_i2c_plat.h b/plat/marvell/armada/a8k/common/include/mentor_i2c_plat.h
similarity index 100%
rename from plat/marvell/a8k/common/include/mentor_i2c_plat.h
rename to plat/marvell/armada/a8k/common/include/mentor_i2c_plat.h
diff --git a/plat/marvell/a8k/common/include/plat_macros.S b/plat/marvell/armada/a8k/common/include/plat_macros.S
similarity index 100%
rename from plat/marvell/a8k/common/include/plat_macros.S
rename to plat/marvell/armada/a8k/common/include/plat_macros.S
diff --git a/plat/marvell/a8k/common/include/platform_def.h b/plat/marvell/armada/a8k/common/include/platform_def.h
similarity index 90%
rename from plat/marvell/a8k/common/include/platform_def.h
rename to plat/marvell/armada/a8k/common/include/platform_def.h
index ec1c903..944a151 100644
--- a/plat/marvell/a8k/common/include/platform_def.h
+++ b/plat/marvell/armada/a8k/common/include/platform_def.h
@@ -92,13 +92,18 @@
 #define PLAT_MARVELL_CORE_COUNT			(PLAT_MARVELL_CLUSTER_COUNT * \
 						PLAT_MARVELL_CLUSTER_CORE_COUNT)
 
-/* DRAM[2MB..66MB] is used as Trusted ROM */
+/* Part of DRAM that is used as Trusted ROM */
 #define PLAT_MARVELL_TRUSTED_ROM_BASE		PLAT_MARVELL_ATF_LOAD_ADDR
-/* 64 MB TODO: reduce this to minimum needed according to fip image size */
-#define PLAT_MARVELL_TRUSTED_ROM_SIZE		0x04000000
-/* Reserve 16M for SCP (Secure PayLoad) Trusted DRAM */
-#define PLAT_MARVELL_TRUSTED_DRAM_BASE		0x04400000
-#define PLAT_MARVELL_TRUSTED_DRAM_SIZE		0x01000000	/* 16 MB */
+/* 4 MB for FIP image */
+#define PLAT_MARVELL_TRUSTED_ROM_SIZE		0x00400000
+/* Reserve 12MB for SCP (Secure PayLoad) Trusted RAM
+ * OP-TEE 4MB SHMEM follows this region
+ */
+#define PLAT_MARVELL_TRUSTED_RAM_BASE		0x04400000
+#define PLAT_MARVELL_TRUSTED_RAM_SIZE		0x00C00000	/* 12 MB DRAM */
+
+#define PLAT_MARVELL_LLC_SRAM_BASE		0x05400000
+#define PLAT_MARVELL_LLC_SRAM_SIZE		0x00100000	/* 1 MB SRAM */
 
 /*
  * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
@@ -182,22 +187,14 @@
 /* Mailbox base address (note the lower memory space
  * is reserved for BLE data)
  */
-#define PLAT_MARVELL_MAILBOX_BASE		(MARVELL_TRUSTED_SRAM_BASE \
-							+ 0x400)
+#define PLAT_MARVELL_MAILBOX_BASE		(MARVELL_SHARED_RAM_BASE  \
+						+ 0x400)
 #define PLAT_MARVELL_MAILBOX_SIZE		0x100
 #define PLAT_MARVELL_MAILBOX_MAGIC_NUM		0x6D72766C	/* mrvl */
 
 /* Securities */
 #define IRQ_SEC_OS_TICK_INT			MARVELL_IRQ_SEC_PHY_TIMER
 
-#define TRUSTED_DRAM_BASE			PLAT_MARVELL_TRUSTED_DRAM_BASE
-#define TRUSTED_DRAM_SIZE			PLAT_MARVELL_TRUSTED_DRAM_SIZE
-
-#ifdef BL32
-#define BL32_BASE				TRUSTED_DRAM_BASE
-#define BL32_LIMIT				TRUSTED_DRAM_SIZE
-#endif
-
 #define MVEBU_PMU_IRQ_WA
 
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/marvell/a8k/common/mss/mss_a8k.mk b/plat/marvell/armada/a8k/common/mss/mss_a8k.mk
similarity index 92%
rename from plat/marvell/a8k/common/mss/mss_a8k.mk
rename to plat/marvell/armada/a8k/common/mss/mss_a8k.mk
index efd03c5..d8d4921 100644
--- a/plat/marvell/a8k/common/mss/mss_a8k.mk
+++ b/plat/marvell/armada/a8k/common/mss/mss_a8k.mk
@@ -5,7 +5,7 @@
 # https://spdx.org/licenses
 #
 
-PLAT_MARVELL		:=	plat/marvell
+PLAT_MARVELL		:=	plat/marvell/armada
 A8K_MSS_SOURCE		:=	$(PLAT_MARVELL)/a8k/common/mss
 
 BL2_SOURCES		+=	$(A8K_MSS_SOURCE)/mss_bl2_setup.c \
diff --git a/plat/marvell/a8k/common/mss/mss_bl2_setup.c b/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c
similarity index 85%
rename from plat/marvell/a8k/common/mss/mss_bl2_setup.c
rename to plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c
index 09b8446..c2cd933 100644
--- a/plat/marvell/a8k/common/mss/mss_bl2_setup.c
+++ b/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c
@@ -10,6 +10,7 @@
 #include <common/bl_common.h>
 #include <common/debug.h>
 #include <drivers/marvell/ccu.h>
+#include <drivers/marvell/mochi/ap_setup.h>
 #include <drivers/marvell/mochi/cp110_setup.h>
 #include <lib/mmio.h>
 
@@ -18,9 +19,6 @@
 
 #include "mss_scp_bootloader.h"
 
-/* IO windows configuration */
-#define IOW_GCR_OFFSET		(0x70)
-
 /* MSS windows configuration */
 #define MSS_AEBR(base)			(base + 0x160)
 #define MSS_AIBR(base)			(base + 0x164)
@@ -51,7 +49,7 @@
  */
 static int bl2_plat_mmap_init(void)
 {
-	int cfg_num, win_id, cfg_idx;
+	int cfg_num, win_id, cfg_idx, cp;
 
 	cfg_num =  ARRAY_SIZE(ccu_mem_map);
 
@@ -65,20 +63,29 @@
 	 * Do not touch CCU window 0,
 	 * it's used for the internal registers access
 	 */
-	for (cfg_idx = 0, win_id = 1; cfg_idx < cfg_num; cfg_idx++, win_id++) {
+	for (cfg_idx = 0, win_id = 1;
+	     (win_id < MVEBU_CCU_MAX_WINS) && (cfg_idx < cfg_num); win_id++) {
+		/* Skip already enabled CCU windows */
+		if (ccu_is_win_enabled(MVEBU_AP0, win_id))
+			continue;
 		/* Enable required CCU windows */
 		ccu_win_check(&ccu_mem_map[cfg_idx]);
 		ccu_enable_win(MVEBU_AP0, &ccu_mem_map[cfg_idx], win_id);
+		cfg_idx++;
 	}
 
-	/* Set the default target id to PIDI */
-	mmio_write_32(MVEBU_IO_WIN_BASE(MVEBU_AP0) + IOW_GCR_OFFSET, PIDI_TID);
+	/* Config address for each cp other than cp0 */
+	for (cp = 1; cp < CP_COUNT; cp++)
+		update_cp110_default_win(cp);
+
+	/* There is need to configure IO_WIN windows again to overwrite
+	 * temporary configuration done during update_cp110_default_win
+	 */
+	init_io_win(MVEBU_AP0);
 
 	/* 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));
+	for (cp = 0; cp < CP_COUNT; cp++)
+		cp110_amb_init(MVEBU_CP_REGS_BASE(cp));
 
 	return 0;
 }
diff --git a/plat/marvell/a8k/common/mss/mss_pm_ipc.c b/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c
similarity index 100%
rename from plat/marvell/a8k/common/mss/mss_pm_ipc.c
rename to plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c
diff --git a/plat/marvell/a8k/common/mss/mss_pm_ipc.h b/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.h
similarity index 100%
rename from plat/marvell/a8k/common/mss/mss_pm_ipc.h
rename to plat/marvell/armada/a8k/common/mss/mss_pm_ipc.h
diff --git a/plat/marvell/a8k/common/plat_bl1_setup.c b/plat/marvell/armada/a8k/common/plat_bl1_setup.c
similarity index 100%
rename from plat/marvell/a8k/common/plat_bl1_setup.c
rename to plat/marvell/armada/a8k/common/plat_bl1_setup.c
diff --git a/plat/marvell/a8k/common/plat_bl31_setup.c b/plat/marvell/armada/a8k/common/plat_bl31_setup.c
similarity index 95%
rename from plat/marvell/a8k/common/plat_bl31_setup.c
rename to plat/marvell/armada/a8k/common/plat_bl31_setup.c
index 98b3966..552c9b2 100644
--- a/plat/marvell/a8k/common/plat_bl31_setup.c
+++ b/plat/marvell/armada/a8k/common/plat_bl31_setup.c
@@ -116,18 +116,15 @@
 		marvell_bl31_plat_arch_setup();
 
 	for (cp = 0; cp < CP_COUNT; cp++) {
-	/* configure cp110 for CP0*/
-		if (cp == 1)
-			mci_initialize(MVEBU_MCI0);
-
-	/* initialize MCI & CP1 */
 		cp110_init(MVEBU_CP_REGS_BASE(cp),
 			   STREAM_ID_BASE + (cp * MAX_STREAM_ID_PER_CP));
 
-	/* Should be called only after setting IOB windows */
 		marvell_bl31_mpp_init(cp);
 	}
 
+	for (cp = 1; cp < CP_COUNT; cp++)
+		mci_link_tune(cp - 1);
+
 	/* initialize IPC between MSS and ATF */
 	if (mailbox[MBOX_IDX_MAGIC] != MVEBU_MAILBOX_MAGIC_NUM ||
 	    mailbox[MBOX_IDX_SUSPEND_MAGIC] != MVEBU_MAILBOX_SUSPEND_STATE)
diff --git a/plat/marvell/a8k/common/plat_ble_setup.c b/plat/marvell/armada/a8k/common/plat_ble_setup.c
similarity index 98%
rename from plat/marvell/a8k/common/plat_ble_setup.c
rename to plat/marvell/armada/a8k/common/plat_ble_setup.c
index 7f9e242..f11b5ac 100644
--- a/plat/marvell/a8k/common/plat_ble_setup.c
+++ b/plat/marvell/armada/a8k/common/plat_ble_setup.c
@@ -89,6 +89,12 @@
 					 (0x1 << AVS_SOFT_RESET_OFFSET) | \
 					 (0x1 << AVS_ENABLE_OFFSET))
 
+#define AVS_CN9130_HIGH_CLK_VALUE	((0x80 << 24) | \
+					 (0x2dc << 13) | \
+					 (0x2dc << 3) | \
+					 (0x1 << AVS_SOFT_RESET_OFFSET) | \
+					 (0x1 << AVS_ENABLE_OFFSET))
+
 #define MVEBU_AP_EFUSE_SRV_CTRL_REG	(MVEBU_AP_GEN_MGMT_BASE + 0x8)
 #define EFUSE_SRV_CTRL_LD_SELECT_OFFS	6
 #define EFUSE_SRV_CTRL_LD_SEL_USER_MASK	(1 << EFUSE_SRV_CTRL_LD_SELECT_OFFS)
@@ -224,10 +230,19 @@
 	/* Check which SoC is running and act accordingly */
 	if (ble_get_ap_type() == CHIP_ID_AP807) {
 		/* Increase CPU voltage for higher CPU clock */
-		if (freq_mode == CPU_2000_DDR_1200_RCLK_1200)
+		switch (freq_mode) {
+		case CPU_2000_DDR_1200_RCLK_1200:
 			avs_val = AVS_A3900_HIGH_CLK_VALUE;
-		else
+			break;
+#ifdef MVEBU_SOC_AP807
+		case CPU_2200_DDR_1200_RCLK_1200:
+			avs_val = AVS_CN9130_HIGH_CLK_VALUE;
+			break;
+#endif
+		default:
 			avs_val = AVS_A3900_CLK_VALUE;
+		}
+
 	} else {
 		/* Check which SoC is running and act accordingly */
 		device_id = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
@@ -463,7 +478,6 @@
 		NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n",
 			single_cluster == 0 ? "8040" : "8020", freq_pidi_mode);
 		switch (freq_pidi_mode) {
-		case CPU_1800_DDR_1200_RCLK_1200:
 		case CPU_1800_DDR_1050_RCLK_1050:
 			if (perr[1])
 				goto perror;
diff --git a/plat/marvell/a8k/common/plat_pm.c b/plat/marvell/armada/a8k/common/plat_pm.c
similarity index 100%
rename from plat/marvell/a8k/common/plat_pm.c
rename to plat/marvell/armada/a8k/common/plat_pm.c
diff --git a/plat/marvell/a8k/common/plat_pm_trace.c b/plat/marvell/armada/a8k/common/plat_pm_trace.c
similarity index 100%
rename from plat/marvell/a8k/common/plat_pm_trace.c
rename to plat/marvell/armada/a8k/common/plat_pm_trace.c
diff --git a/plat/marvell/a8k/common/plat_thermal.c b/plat/marvell/armada/a8k/common/plat_thermal.c
similarity index 100%
rename from plat/marvell/a8k/common/plat_thermal.c
rename to plat/marvell/armada/a8k/common/plat_thermal.c
diff --git a/plat/marvell/common/aarch64/marvell_bl2_mem_params_desc.c b/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c
similarity index 77%
rename from plat/marvell/common/aarch64/marvell_bl2_mem_params_desc.c
rename to plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c
index 6a8e11c..8d909dc 100644
--- a/plat/marvell/common/aarch64/marvell_bl2_mem_params_desc.c
+++ b/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c
@@ -100,6 +100,45 @@
 
 	    .next_handoff_image_id = BL33_IMAGE_ID,
     },
+
+	/*
+	 * Fill BL32 external 1 related information.
+	 * A typical use for extra1 image is with OP-TEE
+	 * where it is the pager image.
+	 */
+	{
+	    .image_id = BL32_EXTRA1_IMAGE_ID,
+
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+	    VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+	    .image_info.image_base = BL32_BASE,
+	    .image_info.image_max_size = BL32_LIMIT - BL32_BASE,
+
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+
+	/*
+	 * Fill BL32 external 2 related information.
+	 * A typical use for extra2 image is with OP-TEE,
+	 * where it is the paged image.
+	 */
+	{
+	    .image_id = BL32_EXTRA2_IMAGE_ID,
+
+	    SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+		    VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE),
+
+	    SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+		    VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING),
+#ifdef SPD_opteed
+	    .image_info.image_base = MARVELL_OPTEE_PAGEABLE_LOAD_BASE,
+	    .image_info.image_max_size = MARVELL_OPTEE_PAGEABLE_LOAD_SIZE,
+#endif
+	    .next_handoff_image_id = INVALID_IMAGE_ID,
+	},
 # endif /* BL32_BASE */
 
 	/* Fill BL33 related information */
diff --git a/plat/marvell/common/aarch64/marvell_common.c b/plat/marvell/armada/common/aarch64/marvell_common.c
similarity index 100%
rename from plat/marvell/common/aarch64/marvell_common.c
rename to plat/marvell/armada/common/aarch64/marvell_common.c
diff --git a/plat/marvell/common/aarch64/marvell_helpers.S b/plat/marvell/armada/common/aarch64/marvell_helpers.S
similarity index 99%
rename from plat/marvell/common/aarch64/marvell_helpers.S
rename to plat/marvell/armada/common/aarch64/marvell_helpers.S
index 6f625b9..4ddc73d 100644
--- a/plat/marvell/common/aarch64/marvell_helpers.S
+++ b/plat/marvell/armada/common/aarch64/marvell_helpers.S
@@ -185,7 +185,7 @@
 
 	/* Invalidate all ways */
 	ldr	w1, =LLC_WAY_MASK
-	ldr	x0, =MASTER_L2X0_INV_WAY
+	ldr	x0, =MASTER_LLC_INV_WAY
 	str	w1, [x0]
 
 	/* Finally disable LLC */
diff --git a/plat/marvell/common/marvell_bl1_setup.c b/plat/marvell/armada/common/marvell_bl1_setup.c
similarity index 100%
rename from plat/marvell/common/marvell_bl1_setup.c
rename to plat/marvell/armada/common/marvell_bl1_setup.c
diff --git a/plat/marvell/common/marvell_bl2_setup.c b/plat/marvell/armada/common/marvell_bl2_setup.c
similarity index 83%
rename from plat/marvell/common/marvell_bl2_setup.c
rename to plat/marvell/armada/common/marvell_bl2_setup.c
index 3c1c391..3dfa82e 100644
--- a/plat/marvell/common/marvell_bl2_setup.c
+++ b/plat/marvell/armada/common/marvell_bl2_setup.c
@@ -17,6 +17,9 @@
 #include <drivers/console.h>
 #include <lib/utils.h>
 
+#ifdef SPD_opteed
+#include <optee_utils.h>
+#endif
 #include <marvell_def.h>
 #include <plat_marvell.h>
 
@@ -97,9 +100,29 @@
 	int err = 0;
 	bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
 
+#ifdef SPD_opteed
+	bl_mem_params_node_t *pager_mem_params = NULL;
+	bl_mem_params_node_t *paged_mem_params = NULL;
+#endif /* SPD_opteed */
 	assert(bl_mem_params);
 
 	switch (image_id) {
+	case BL32_IMAGE_ID:
+#ifdef SPD_opteed
+		pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+		assert(pager_mem_params);
+
+		paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+		assert(paged_mem_params);
+
+		err = parse_optee_header(&bl_mem_params->ep_info,
+					 &pager_mem_params->image_info,
+					 &paged_mem_params->image_info);
+		if (err != 0)
+			WARN("OPTEE header parse error.\n");
+#endif /* SPD_opteed */
+		bl_mem_params->ep_info.spsr = marvell_get_spsr_for_bl32_entry();
+		break;
 
 	case BL33_IMAGE_ID:
 		/* BL33 expects to receive the primary CPU MPID (through r0) */
diff --git a/plat/marvell/common/marvell_bl31_setup.c b/plat/marvell/armada/common/marvell_bl31_setup.c
similarity index 100%
rename from plat/marvell/common/marvell_bl31_setup.c
rename to plat/marvell/armada/common/marvell_bl31_setup.c
diff --git a/plat/marvell/common/marvell_cci.c b/plat/marvell/armada/common/marvell_cci.c
similarity index 100%
rename from plat/marvell/common/marvell_cci.c
rename to plat/marvell/armada/common/marvell_cci.c
diff --git a/plat/marvell/common/marvell_common.mk b/plat/marvell/armada/common/marvell_common.mk
similarity index 76%
rename from plat/marvell/common/marvell_common.mk
rename to plat/marvell/armada/common/marvell_common.mk
index f41d7a4..2e96e2f 100644
--- a/plat/marvell/common/marvell_common.mk
+++ b/plat/marvell/armada/common/marvell_common.mk
@@ -3,11 +3,11 @@
 # SPDX-License-Identifier:     BSD-3-Clause
 # https://spdx.org/licenses
 
-MARVELL_PLAT_BASE		:= plat/marvell
-MARVELL_PLAT_INCLUDE_BASE	:= include/plat/marvell
+MARVELL_PLAT_BASE		:= plat/marvell/armada
+MARVELL_PLAT_INCLUDE_BASE	:= include/plat/marvell/armada
 
-include $(MARVELL_PLAT_BASE)/version.mk
-include $(MARVELL_PLAT_BASE)/marvell.mk
+include plat/marvell/version.mk
+include plat/marvell/marvell.mk
 
 VERSION_STRING			+=(Marvell-${SUBVERSION})
 
@@ -16,6 +16,11 @@
 # flag to switch from PLL to ARO
 ARO_ENABLE			:= 0
 $(eval $(call add_define,ARO_ENABLE))
+
+# Convert LLC to secure SRAM
+LLC_SRAM			:= 0
+$(eval $(call add_define,LLC_SRAM))
+
 # Enable/Disable LLC
 LLC_ENABLE			:= 1
 $(eval $(call add_define,LLC_ENABLE))
@@ -53,6 +58,10 @@
 				$(MARVELL_PLAT_BASE)/common/aarch64/marvell_bl2_mem_params_desc.c	\
 				$(MARVELL_PLAT_BASE)/common/marvell_image_load.c
 
+ifeq (${SPD},opteed)
+PLAT_INCLUDES		+=	-Iinclude/lib
+BL2_SOURCES		+=	lib/optee/optee_utils.c
+endif
 
 BL31_SOURCES		+=	$(MARVELL_PLAT_BASE)/common/marvell_bl31_setup.c	\
 				$(MARVELL_PLAT_BASE)/common/marvell_pm.c		\
@@ -64,6 +73,15 @@
 # PSCI functionality
 $(eval $(call add_define,CONFIG_ARM64))
 
+# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
+# in the FIP if the platform requires.
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call TOOL_ADD_IMG,bl32_extra1,--tos-fw-extra1))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call TOOL_ADD_IMG,bl32_extra2,--tos-fw-extra2))
+endif
+
 # MSS (SCP) build
 ifeq (${MSS_SUPPORT}, 1)
 include $(MARVELL_PLAT_BASE)/common/mss/mss_common.mk
diff --git a/plat/marvell/common/marvell_console.c b/plat/marvell/armada/common/marvell_console.c
similarity index 100%
rename from plat/marvell/common/marvell_console.c
rename to plat/marvell/armada/common/marvell_console.c
diff --git a/plat/marvell/common/marvell_ddr_info.c b/plat/marvell/armada/common/marvell_ddr_info.c
similarity index 100%
rename from plat/marvell/common/marvell_ddr_info.c
rename to plat/marvell/armada/common/marvell_ddr_info.c
diff --git a/plat/marvell/common/marvell_gicv2.c b/plat/marvell/armada/common/marvell_gicv2.c
similarity index 100%
rename from plat/marvell/common/marvell_gicv2.c
rename to plat/marvell/armada/common/marvell_gicv2.c
diff --git a/plat/marvell/common/marvell_gicv3.c b/plat/marvell/armada/common/marvell_gicv3.c
similarity index 100%
rename from plat/marvell/common/marvell_gicv3.c
rename to plat/marvell/armada/common/marvell_gicv3.c
diff --git a/plat/marvell/common/marvell_image_load.c b/plat/marvell/armada/common/marvell_image_load.c
similarity index 100%
rename from plat/marvell/common/marvell_image_load.c
rename to plat/marvell/armada/common/marvell_image_load.c
diff --git a/plat/marvell/common/marvell_io_storage.c b/plat/marvell/armada/common/marvell_io_storage.c
similarity index 91%
rename from plat/marvell/common/marvell_io_storage.c
rename to plat/marvell/armada/common/marvell_io_storage.c
index 065f956..2627ba4 100644
--- a/plat/marvell/common/marvell_io_storage.c
+++ b/plat/marvell/armada/common/marvell_io_storage.c
@@ -43,6 +43,15 @@
 static const io_uuid_spec_t bl32_uuid_spec = {
 	.uuid = UUID_SECURE_PAYLOAD_BL32,
 };
+
+static const io_uuid_spec_t bl32_extra1_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
+};
+
+static const io_uuid_spec_t bl32_extra2_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
+};
+
 static const io_uuid_spec_t bl33_uuid_spec = {
 	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
 };
@@ -83,6 +92,16 @@
 		(uintptr_t)&bl32_uuid_spec,
 		open_fip
 	},
+	[BL32_EXTRA1_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_extra1_uuid_spec,
+		open_fip
+	},
+	[BL32_EXTRA2_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_extra2_uuid_spec,
+		open_fip
+	},
 	[BL33_IMAGE_ID] = {
 		&fip_dev_handle,
 		(uintptr_t)&bl33_uuid_spec,
diff --git a/plat/marvell/common/marvell_pm.c b/plat/marvell/armada/common/marvell_pm.c
similarity index 100%
rename from plat/marvell/common/marvell_pm.c
rename to plat/marvell/armada/common/marvell_pm.c
diff --git a/plat/marvell/common/marvell_topology.c b/plat/marvell/armada/common/marvell_topology.c
similarity index 100%
rename from plat/marvell/common/marvell_topology.c
rename to plat/marvell/armada/common/marvell_topology.c
diff --git a/plat/marvell/common/mrvl_sip_svc.c b/plat/marvell/armada/common/mrvl_sip_svc.c
similarity index 100%
rename from plat/marvell/common/mrvl_sip_svc.c
rename to plat/marvell/armada/common/mrvl_sip_svc.c
diff --git a/plat/marvell/common/mss/mss_common.mk b/plat/marvell/armada/common/mss/mss_common.mk
similarity index 82%
rename from plat/marvell/common/mss/mss_common.mk
rename to plat/marvell/armada/common/mss/mss_common.mk
index 898b6dc..4ab4359 100644
--- a/plat/marvell/common/mss/mss_common.mk
+++ b/plat/marvell/armada/common/mss/mss_common.mk
@@ -6,14 +6,14 @@
 #
 
 
-PLAT_MARVELL		:= 	plat/marvell
+PLAT_MARVELL		:= 	plat/marvell/armada
 MSS_SOURCE		:= 	$(PLAT_MARVELL)/common/mss
 
 BL2_SOURCES		+=	$(MSS_SOURCE)/mss_scp_bootloader.c		\
 				$(PLAT_MARVELL)/common/plat_delay_timer.c	\
 				drivers/delay_timer/delay_timer.c		\
 				$(MARVELL_DRV)					\
-				$(PLAT_FAMILY_BASE)/$(PLAT)/board/marvell_plat_config.c
+				$(BOARD_DIR)/board/marvell_plat_config.c
 
 BL31_SOURCES		+=	$(MSS_SOURCE)/mss_ipc_drv.c
 
diff --git a/plat/marvell/common/mss/mss_ipc_drv.c b/plat/marvell/armada/common/mss/mss_ipc_drv.c
similarity index 100%
rename from plat/marvell/common/mss/mss_ipc_drv.c
rename to plat/marvell/armada/common/mss/mss_ipc_drv.c
diff --git a/plat/marvell/common/mss/mss_ipc_drv.h b/plat/marvell/armada/common/mss/mss_ipc_drv.h
similarity index 100%
rename from plat/marvell/common/mss/mss_ipc_drv.h
rename to plat/marvell/armada/common/mss/mss_ipc_drv.h
diff --git a/plat/marvell/common/mss/mss_mem.h b/plat/marvell/armada/common/mss/mss_mem.h
similarity index 100%
rename from plat/marvell/common/mss/mss_mem.h
rename to plat/marvell/armada/common/mss/mss_mem.h
diff --git a/plat/marvell/common/mss/mss_scp_bl2_format.h b/plat/marvell/armada/common/mss/mss_scp_bl2_format.h
similarity index 95%
rename from plat/marvell/common/mss/mss_scp_bl2_format.h
rename to plat/marvell/armada/common/mss/mss_scp_bl2_format.h
index 7150f0a..74dddc6 100644
--- a/plat/marvell/common/mss/mss_scp_bl2_format.h
+++ b/plat/marvell/armada/common/mss/mss_scp_bl2_format.h
@@ -13,7 +13,6 @@
 #define HEADER_VERSION	0x1
 
 #define MSS_IDRAM_SIZE	0x10000 /* 64KB */
-#define MG_SRAM_SIZE	0x20000 /* 128KB */
 
 /* Types definitions */
 typedef struct file_header {
diff --git a/plat/marvell/common/mss/mss_scp_bootloader.c b/plat/marvell/armada/common/mss/mss_scp_bootloader.c
similarity index 92%
rename from plat/marvell/common/mss/mss_scp_bootloader.c
rename to plat/marvell/armada/common/mss/mss_scp_bootloader.c
index 4473d81..adf570e 100644
--- a/plat/marvell/common/mss/mss_scp_bootloader.c
+++ b/plat/marvell/armada/common/mss/mss_scp_bootloader.c
@@ -12,6 +12,7 @@
 #include <arch_helpers.h>
 #include <common/debug.h>
 #include <drivers/delay_timer.h>
+#include <mg_conf_cm3/mg_conf_cm3.h>
 #include <lib/mmio.h>
 
 #include <plat_pm_trace.h>
@@ -42,8 +43,6 @@
 
 #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;
@@ -61,28 +60,6 @@
 	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;
@@ -258,8 +235,7 @@
 			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));
+		ret = mg_image_load(single_img, image_size, cp_index);
 		if (ret != 0) {
 			ERROR("SCP Image load failed\n");
 			return -1;
diff --git a/plat/marvell/common/mss/mss_scp_bootloader.h b/plat/marvell/armada/common/mss/mss_scp_bootloader.h
similarity index 100%
rename from plat/marvell/common/mss/mss_scp_bootloader.h
rename to plat/marvell/armada/common/mss/mss_scp_bootloader.h
diff --git a/plat/marvell/common/plat_delay_timer.c b/plat/marvell/armada/common/plat_delay_timer.c
similarity index 100%
rename from plat/marvell/common/plat_delay_timer.c
rename to plat/marvell/armada/common/plat_delay_timer.c
diff --git a/plat/marvell/marvell.mk b/plat/marvell/marvell.mk
index d8be0dd..8245753 100644
--- a/plat/marvell/marvell.mk
+++ b/plat/marvell/marvell.mk
@@ -16,6 +16,10 @@
 PALLADIUM			:= 0
 $(eval $(call add_define,PALLADIUM))
 
+# Set board to work with DDR 32bit
+DDR32				:= 0
+$(eval $(call add_define,DDR32))
+
 ifeq (${MARVELL_SECURE_BOOT},1)
 DOIMAGE_SEC_FLAGS := -c $(DOIMAGE_SEC)
 DOIMAGE_LIBS_CHECK = \
diff --git a/plat/mediatek/mt8192/aarch64/plat_helpers.S b/plat/mediatek/mt8192/aarch64/plat_helpers.S
new file mode 100644
index 0000000..99274de
--- /dev/null
+++ b/plat/mediatek/mt8192/aarch64/plat_helpers.S
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+	.globl plat_is_my_cpu_primary
+	.globl plat_my_core_pos
+	.globl plat_mediatek_calc_core_pos
+
+func plat_is_my_cpu_primary
+	mrs x0, mpidr_el1
+	and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
+	cmp x0, #PLAT_PRIMARY_CPU
+	cset x0, eq
+	ret
+endfunc plat_is_my_cpu_primary
+
+	/* -----------------------------------------------------
+	 *  unsigned int plat_my_core_pos(void)
+	 *  This function uses the plat_mediatek_calc_core_pos()
+	 *  definition to get the index of the calling CPU.
+	 * -----------------------------------------------------
+	 */
+func plat_my_core_pos
+	mrs	x0, mpidr_el1
+	b plat_mediatek_calc_core_pos
+endfunc plat_my_core_pos
+
+	/* -----------------------------------------------------
+	 * unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr);
+	 *
+	 * In ARMv8.2, AFF2 is cluster id, AFF1 is core id and
+	 * AFF0 is thread id. There is only one cluster in ARMv8.2
+	 * and one thread in current implementation.
+	 *
+	 * With this function: CorePos = CoreID (AFF1)
+	 * we do it with x0 = (x0 >> 8) & 0xff
+	 * -----------------------------------------------------
+	 */
+func plat_mediatek_calc_core_pos
+	mov	x1, #MPIDR_AFFLVL_MASK
+	and	x0, x1, x0, lsr #MPIDR_AFF1_SHIFT
+	ret
+endfunc plat_mediatek_calc_core_pos
diff --git a/plat/mediatek/mt8192/aarch64/platform_common.c b/plat/mediatek/mt8192/aarch64/platform_common.c
new file mode 100644
index 0000000..eb1bb44
--- /dev/null
+++ b/plat/mediatek/mt8192/aarch64/platform_common.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Project Includes */
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+/* Platform Includes */
+#include <platform_def.h>
+
+/* Table of regions to map using the MMU.  */
+const mmap_region_t plat_mmap[] = {
+	/* for TF text, RO, RW */
+	MAP_REGION_FLAT(MTK_DEV_RNG0_BASE, MTK_DEV_RNG0_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(MTK_DEV_RNG1_BASE, MTK_DEV_RNG1_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(MTK_DEV_RNG2_BASE, MTK_DEV_RNG2_SIZE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+	{ 0 }
+};
+
+/*******************************************************************************
+ * Macro generating the code for the function setting up the pagetables as per
+ * the platform memory map & initialize the mmu, for the given exception level
+ ******************************************************************************/
+void plat_configure_mmu_el3(uintptr_t total_base,
+			    uintptr_t total_size,
+			    uintptr_t ro_start,
+			    uintptr_t ro_limit)
+{
+	mmap_add_region(total_base, total_base, total_size,
+			MT_RW_DATA | MT_SECURE);
+	mmap_add_region(ro_start, ro_start, ro_limit - ro_start,
+			MT_CODE | MT_SECURE);
+	mmap_add(plat_mmap);
+	init_xlat_tables();
+	enable_mmu_el3(0);
+}
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return SYS_COUNTER_FREQ_IN_TICKS;
+}
diff --git a/plat/mediatek/mt8192/bl31_plat_setup.c b/plat/mediatek/mt8192/bl31_plat_setup.c
new file mode 100644
index 0000000..4378c5a
--- /dev/null
+++ b/plat/mediatek/mt8192/bl31_plat_setup.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* System Includes */
+#include <assert.h>
+
+/* Project Includes */
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/coreboot.h>
+
+/* Platform Includes */
+#include <plat_params.h>
+#include <plat_private.h>
+
+static entry_point_info_t bl32_ep_info;
+static entry_point_info_t bl33_ep_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_ep_info : &bl32_ep_info;
+	assert(next_image_info->h.type == PARAM_EP);
+
+	/* None of the images on this platform can have 0x0 as the entrypoint */
+	if (next_image_info->pc) {
+		return next_image_info;
+	} else {
+		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.
+ ******************************************************************************/
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				u_register_t arg2, u_register_t arg3)
+{
+	static console_t console;
+
+	params_early_setup(arg1);
+
+#if COREBOOT
+	if (coreboot_serial.type) {
+		console_16550_register(coreboot_serial.baseaddr,
+				       coreboot_serial.input_hertz,
+				       coreboot_serial.baud,
+				       &console);
+	}
+#else
+	console_16550_register(UART0_BASE, UART_CLOCK, UART_BAUDRATE, &console);
+#endif
+
+	NOTICE("MT8192 bl31_setup\n");
+
+	bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info);
+}
+
+
+/*******************************************************************************
+ * Perform any BL31 platform setup code
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+}
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+	plat_configure_mmu_el3(BL31_START,
+			       BL31_END - BL31_START,
+			       BL_CODE_BASE,
+			       BL_CODE_END);
+}
diff --git a/plat/mediatek/mt8192/include/plat_helpers.h b/plat/mediatek/mt8192/include/plat_helpers.h
new file mode 100644
index 0000000..9b550ee
--- /dev/null
+++ b/plat/mediatek/mt8192/include/plat_helpers.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_HELPERS_H__
+#define __PLAT_HELPERS_H__
+
+unsigned int plat_mediatek_calc_core_pos(u_register_t mpidr);
+
+#endif /* __PLAT_HELPERS_H__ */
diff --git a/plat/mediatek/mt8192/include/plat_macros.S b/plat/mediatek/mt8192/include/plat_macros.S
new file mode 100644
index 0000000..92cda07
--- /dev/null
+++ b/plat/mediatek/mt8192/include/plat_macros.S
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLAT_MACROS_S
+#define PLAT_MACROS_S
+
+#include <platform_def.h>
+
+.section .rodata.gic_reg_name, "aS"
+gicc_regs:
+	.asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
+gicd_pend_reg:
+	.asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n"	\
+		" Offset:\t\t\tvalue\n"
+newline:
+	.asciz "\n"
+spacer:
+	.asciz ":\t\t0x"
+
+.section .rodata.cci_reg_name, "aS"
+cci_iface_regs:
+	.asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
+
+	/* ---------------------------------------------
+	 * The below macro prints out relevant GIC and
+	 * CCI registers whenever an unhandled exception
+	 * is taken in BL31.
+	 * Clobbers: x0 - x10, x26, x27, sp
+	 * ---------------------------------------------
+	 */
+	.macro plat_crash_print_regs
+	/* To-do: GIC owner */
+	/* To-do: CCI owner */
+	.endm
+
+#endif /* PLAT_MACROS_S */
diff --git a/plat/mediatek/mt8192/include/plat_private.h b/plat/mediatek/mt8192/include/plat_private.h
new file mode 100644
index 0000000..42ca415
--- /dev/null
+++ b/plat/mediatek/mt8192/include/plat_private.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PRIVATE_H
+#define PLAT_PRIVATE_H
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void plat_configure_mmu_el3(uintptr_t total_base,
+			    uintptr_t total_size,
+			    uintptr_t ro_start,
+			    uintptr_t ro_limit);
+
+#endif /* PLAT_PRIVATE_H */
diff --git a/plat/mediatek/mt8192/include/platform_def.h b/plat/mediatek/mt8192/include/platform_def.h
new file mode 100644
index 0000000..e1f0faf
--- /dev/null
+++ b/plat/mediatek/mt8192/include/platform_def.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+
+#define PLAT_PRIMARY_CPU   0x0
+
+#define MT_GIC_BASE        0x0c000000
+#define PLAT_MT_CCI_BASE   0x0c500000
+#define MCUCFG_BASE        0x0c530000
+
+#define IO_PHYS            0x10000000
+
+/* Aggregate of all devices for MMU mapping */
+#define MTK_DEV_RNG0_BASE    IO_PHYS
+#define MTK_DEV_RNG0_SIZE    0x10000000
+#define MTK_DEV_RNG1_BASE    (IO_PHYS + 0x10000000)
+#define MTK_DEV_RNG1_SIZE    0x10000000
+#define MTK_DEV_RNG2_BASE    0x0c000000
+#define MTK_DEV_RNG2_SIZE    0x600000
+
+/*******************************************************************************
+ * UART related constants
+ ******************************************************************************/
+#define UART0_BASE    (IO_PHYS + 0x01002000)
+#define UART1_BASE    (IO_PHYS + 0x01003000)
+
+#define UART_BAUDRATE 115200
+
+/*******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS    13000000
+#define SYS_COUNTER_FREQ_IN_MHZ      13
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT      "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH        aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+#define PLATFORM_STACK_SIZE    0x800
+
+#define PLAT_MAX_PWR_LVL        U(2)
+#define PLAT_MAX_RET_STATE      U(1)
+#define PLAT_MAX_OFF_STATE      U(2)
+
+#define PLATFORM_SYSTEM_COUNT           U(1)
+#define PLATFORM_CLUSTER_COUNT          U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT    U(8)
+#define PLATFORM_CORE_COUNT             (PLATFORM_CLUSTER0_CORE_COUNT)
+#define PLATFORM_MAX_CPUS_PER_CLUSTER   U(8)
+
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+#define TZRAM_BASE          0x54600000
+#define TZRAM_SIZE          0x00030000
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL31 at the top of the Trusted SRAM (just below the shared memory, if
+ * present). BL31_BASE is calculated using the current BL31 debug size plus a
+ * little space for growth.
+ */
+#define BL31_BASE       (TZRAM_BASE + 0x1000)
+#define BL31_LIMIT      (TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE    (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE   (1ULL << 32)
+#define MAX_XLAT_TABLES             16
+#define MAX_MMAP_REGIONS            16
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * 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. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT    6
+#define CACHE_WRITEBACK_GRANULE  (1 << CACHE_WRITEBACK_SHIFT)
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/mediatek/mt8192/plat_pm.c b/plat/mediatek/mt8192/plat_pm.c
new file mode 100644
index 0000000..81a170d
--- /dev/null
+++ b/plat/mediatek/mt8192/plat_pm.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* common headers */
+#include <lib/psci/psci.h>
+
+/* mediatek platform specific headers */
+
+
+/*******************************************************************************
+ * MTK_platform handler called when an affinity instance is about to be turned
+ * on. The level and mpidr determine the affinity instance.
+ ******************************************************************************/
+static const plat_psci_ops_t plat_plat_pm_ops = {
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+			const plat_psci_ops_t **psci_ops)
+{
+	*psci_ops = &plat_plat_pm_ops;
+
+	return 0;
+}
diff --git a/plat/mediatek/mt8192/plat_topology.c b/plat/mediatek/mt8192/plat_topology.c
new file mode 100644
index 0000000..aa4975e
--- /dev/null
+++ b/plat/mediatek/mt8192/plat_topology.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Project Includes */
+#include <arch.h>
+#include <arch_helpers.h>
+#include <lib/psci/psci.h>
+
+/* Platform Includes */
+#include <plat_helpers.h>
+#include <platform_def.h>
+
+const unsigned char mtk_power_domain_tree_desc[] = {
+	/* Number of root nodes */
+	PLATFORM_SYSTEM_COUNT,
+	/* Number of children for the root node */
+	PLATFORM_CLUSTER_COUNT,
+	/* Number of children for the first cluster node */
+	PLATFORM_CLUSTER0_CORE_COUNT,
+};
+
+/*******************************************************************************
+ * This function returns the MT8192 default topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	return mtk_power_domain_tree_desc;
+}
+
+/*******************************************************************************
+ * This function implements a part of the critical interface between the psci
+ * generic layer and the platform that allows the former to query the platform
+ * to convert an MPIDR to a unique linear index. An error code (-1) is returned
+ * in case the MPIDR is invalid.
+ ******************************************************************************/
+int plat_core_pos_by_mpidr(u_register_t mpidr)
+{
+	unsigned int cluster_id, cpu_id;
+
+	if (read_mpidr() & MPIDR_MT_MASK) {
+		/* ARMv8.2 arch */
+		if (mpidr & (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) {
+			return -1;
+		}
+		return plat_mediatek_calc_core_pos(mpidr);
+	}
+
+	mpidr &= MPIDR_AFFINITY_MASK;
+
+	if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) {
+		return -1;
+	}
+
+	cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
+	cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+
+	if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
+		return -1;
+	}
+
+	/*
+	 * Validate cpu_id by checking whether it represents a CPU in
+	 * one of the two clusters present on the platform.
+	 */
+	if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
+		return -1;
+	}
+
+	return (cpu_id + (cluster_id * 8));
+}
diff --git a/plat/mediatek/mt8192/platform.mk b/plat/mediatek/mt8192/platform.mk
new file mode 100644
index 0000000..f4ee7e7
--- /dev/null
+++ b/plat/mediatek/mt8192/platform.mk
@@ -0,0 +1,50 @@
+#
+# Copyright (c) 2020, MediaTek Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+MTK_PLAT      := plat/mediatek
+MTK_PLAT_SOC  := ${MTK_PLAT}/${PLAT}
+
+PLAT_INCLUDES := -I${MTK_PLAT}/common/                            \
+                 -I${MTK_PLAT_SOC}/include/
+
+include drivers/arm/gic/v3/gicv3.mk
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_BL_COMMON_SOURCES := ${GICV3_SOURCES}                              \
+                          ${XLAT_TABLES_LIB_SRCS}                       \
+                          plat/common/aarch64/crash_console_helpers.S   \
+                          plat/common/plat_psci_common.c
+
+BL31_SOURCES    += common/desc_image_load.c                              \
+                   drivers/ti/uart/aarch64/16550_console.S               \
+                   lib/bl_aux_params/bl_aux_params.c                     \
+                   lib/cpus/aarch64/cortex_a55.S                         \
+                   lib/cpus/aarch64/cortex_a76.S                         \
+                   plat/common/plat_gicv3.c                              \
+                   ${MTK_PLAT}/common/mtk_plat_common.c                  \
+                   ${MTK_PLAT}/common/params_setup.c                     \
+                   ${MTK_PLAT_SOC}/aarch64/platform_common.c             \
+                   ${MTK_PLAT_SOC}/aarch64/plat_helpers.S                \
+                   ${MTK_PLAT_SOC}/bl31_plat_setup.c                     \
+                   ${MTK_PLAT_SOC}/plat_pm.c                             \
+                   ${MTK_PLAT_SOC}/plat_topology.c
+
+
+# Configs for A76 and A55
+HW_ASSISTED_COHERENCY := 1
+USE_COHERENT_MEM := 0
+CTX_INCLUDE_AARCH32_REGS := 0
+
+# indicate the reset vector address can be programmed
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+COLD_BOOT_SINGLE_CPU := 1
+
+MACH_MT8192 := 1
+$(eval $(call add_define,MACH_MT8192))
+
+include lib/coreboot/coreboot.mk
+
diff --git a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
index 5555f5d..4d69ccc 100644
--- a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
+++ b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
@@ -280,57 +280,33 @@
 {
 	int ret;
 
+	INFO("Cleaning previous Video Memory Carveout\n");
+
 	/*
 	 * Map the NS memory first, clean it and then unmap it.
 	 */
 	ret = mmap_add_dynamic_region(non_overlap_area_start, /* PA */
 				non_overlap_area_start, /* VA */
 				non_overlap_area_size, /* size */
-				MT_NS | MT_RW | MT_EXECUTE_NEVER |
-				MT_NON_CACHEABLE); /* attrs */
+				MT_DEVICE | MT_RW | MT_NS); /* attrs */
 	assert(ret == 0);
 
-	zero_normalmem((void *)non_overlap_area_start, non_overlap_area_size);
+	zeromem((void *)non_overlap_area_start, non_overlap_area_size);
 	flush_dcache_range(non_overlap_area_start, non_overlap_area_size);
 
-	(void)mmap_remove_dynamic_region(non_overlap_area_start,
+	ret = mmap_remove_dynamic_region(non_overlap_area_start,
 		non_overlap_area_size);
+	assert(ret == 0);
 }
 
-/*
- * Program the Video Memory carveout region
- *
- * phys_base = physical base of aperture
- * size_in_bytes = size of aperture in bytes
- */
-void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes)
+static void tegra_clear_videomem_nonoverlap(uintptr_t phys_base,
+		unsigned long size_in_bytes)
 {
 	uintptr_t vmem_end_old = video_mem_base + (video_mem_size_mb << 20);
 	uintptr_t vmem_end_new = phys_base + size_in_bytes;
 	unsigned long long non_overlap_area_size;
 
 	/*
-	 * Setup the Memory controller to restrict CPU accesses to the Video
-	 * Memory region
-	 */
-	INFO("Configuring Video Memory Carveout\n");
-
-	/*
-	 * Configure Memory Controller directly for the first time.
-	 */
-	if (video_mem_base == 0U)
-		goto done;
-
-	/*
-	 * Lock the non overlapping memory being cleared so that other masters
-	 * do not accidently write to it. The memory would be unlocked once
-	 * the non overlapping region is cleared and the new memory
-	 * settings take effect.
-	 */
-	tegra_lock_videomem_nonoverlap(video_mem_base,
-				       video_mem_size_mb << 20);
-
-	/*
 	 * Clear the old regions now being exposed. The following cases
 	 * can occur -
 	 *
@@ -338,8 +314,6 @@
 	 * 2. clear old sub-region below new base
 	 * 3. clear old sub-region above new end
 	 */
-	INFO("Cleaning previous Video Memory Carveout\n");
-
 	if ((phys_base > vmem_end_old) || (video_mem_base > vmem_end_new)) {
 		tegra_clear_videomem(video_mem_base,
 				     video_mem_size_mb << 20U);
@@ -353,26 +327,55 @@
 			tegra_clear_videomem(vmem_end_new, non_overlap_area_size);
 		}
 	}
+}
 
-done:
+/*
+ * Program the Video Memory carveout region
+ *
+ * phys_base = physical base of aperture
+ * size_in_bytes = size of aperture in bytes
+ */
+void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes)
+{
+	/*
+	 * Setup the Memory controller to restrict CPU accesses to the Video
+	 * Memory region
+	 */
+
+	INFO("Configuring Video Memory Carveout\n");
+
+	if (video_mem_base != 0U) {
+		/*
+		 * Lock the non overlapping memory being cleared so that
+		 * other masters do not accidently write to it. The memory
+		 * would be unlocked once the non overlapping region is
+		 * cleared and the new memory settings take effect.
+		 */
+		tegra_lock_videomem_nonoverlap(video_mem_base,
+			video_mem_size_mb << 20);
+	}
+
 	/* program the Videomem aperture */
 	tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)phys_base);
 	tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI,
 			  (uint32_t)(phys_base >> 32));
 	tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes >> 20);
 
-	/* unlock the previous locked nonoverlapping aperture */
-	tegra_unlock_videomem_nonoverlap();
-
-	/* store new values */
-	video_mem_base = phys_base;
-	video_mem_size_mb = size_in_bytes >> 20;
-
 	/*
 	 * MCE propagates the VideoMem configuration values across the
 	 * CCPLEX.
 	 */
-	mce_update_gsc_videomem();
+	(void)mce_update_gsc_videomem();
+
+	/* Clear the non-overlapping memory */
+	if (video_mem_base != 0U) {
+		tegra_clear_videomem_nonoverlap(phys_base, size_in_bytes);
+		tegra_unlock_videomem_nonoverlap();
+	}
+
+	/* store new values */
+	video_mem_base = phys_base;
+	video_mem_size_mb = (uint64_t)size_in_bytes >> 20;
 }
 
 /*
diff --git a/plat/nvidia/tegra/common/tegra_bl31_setup.c b/plat/nvidia/tegra/common/tegra_bl31_setup.c
index 269afb1..40713b2 100644
--- a/plat/nvidia/tegra/common/tegra_bl31_setup.c
+++ b/plat/nvidia/tegra/common/tegra_bl31_setup.c
@@ -367,7 +367,15 @@
 int32_t bl31_check_ns_address(uint64_t base, uint64_t size_in_bytes)
 {
 	uint64_t end = base + size_in_bytes - U(1);
-	int32_t ret = 0;
+
+	/*
+	 * Sanity check the input values
+	 */
+	if ((base == 0U) || (size_in_bytes == 0U)) {
+		ERROR("NS address 0x%llx (%lld bytes) is invalid\n",
+			base, size_in_bytes);
+		return -EINVAL;
+	}
 
 	/*
 	 * Check if the NS DRAM address is valid
@@ -376,7 +384,7 @@
 	    (end > TEGRA_DRAM_END)) {
 
 		ERROR("NS address 0x%llx is out-of-bounds!\n", base);
-		ret = -EFAULT;
+		return -EFAULT;
 	}
 
 	/*
@@ -385,9 +393,9 @@
 	 */
 	if ((base < (uint64_t)TZDRAM_END) && (end > tegra_bl31_phys_base)) {
 		ERROR("NS address 0x%llx overlaps TZDRAM!\n", base);
-		ret = -ENOTSUP;
+		return -ENOTSUP;
 	}
 
 	/* valid NS address */
-	return ret;
+	return 0;
 }
diff --git a/plat/nvidia/tegra/common/tegra_common.mk b/plat/nvidia/tegra/common/tegra_common.mk
index c946a75..f412a80 100644
--- a/plat/nvidia/tegra/common/tegra_common.mk
+++ b/plat/nvidia/tegra/common/tegra_common.mk
@@ -1,5 +1,6 @@
 #
-# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+# 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
 #
@@ -13,9 +14,16 @@
 
 COMMON_DIR		:=	plat/nvidia/tegra/common
 
-TEGRA_GICv2_SOURCES	:=	drivers/arm/gic/common/gic_common.c		\
-				drivers/arm/gic/v2/gicv2_main.c			\
-				drivers/arm/gic/v2/gicv2_helpers.c		\
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+TEGRA_GICv3_SOURCES	:=	$(GICV3_SOURCES)				\
+				plat/common/plat_gicv3.c			\
+				${COMMON_DIR}/tegra_gicv3.c
+
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+
+TEGRA_GICv2_SOURCES	:=	${GICV2_SOURCES}				\
 				plat/common/plat_gicv2.c			\
 				${COMMON_DIR}/tegra_gicv2.c
 
@@ -27,8 +35,14 @@
 				${COMMON_DIR}/lib/debug/profiler.c		\
 				${COMMON_DIR}/tegra_bl31_setup.c		\
 				${COMMON_DIR}/tegra_delay_timer.c		\
+				${COMMON_DIR}/tegra_ehf.c			\
 				${COMMON_DIR}/tegra_fiq_glue.c			\
 				${COMMON_DIR}/tegra_io_storage.c		\
 				${COMMON_DIR}/tegra_platform.c			\
 				${COMMON_DIR}/tegra_pm.c			\
-				${COMMON_DIR}/tegra_sip_calls.c
+				${COMMON_DIR}/tegra_sip_calls.c			\
+				${COMMON_DIR}/tegra_sdei.c
+
+ifneq ($(ENABLE_STACK_PROTECTOR), 0)
+BL31_SOURCES		+=	${COMMON_DIR}/tegra_stack_protector.c
+endif
diff --git a/plat/nvidia/tegra/common/tegra_ehf.c b/plat/nvidia/tegra/common/tegra_ehf.c
new file mode 100644
index 0000000..ea6e443
--- /dev/null
+++ b/plat/nvidia/tegra/common/tegra_ehf.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <bl31/ehf.h>
+
+/*
+ * Enumeration of priority levels on Tegra platforms.
+ */
+ehf_pri_desc_t tegra_exceptions[] = {
+	/* Watchdog priority */
+	EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_TEGRA_WDT_PRIO),
+
+#if SDEI_SUPPORT
+	/* Critical priority SDEI */
+	EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SDEI_CRITICAL_PRI),
+
+	/* Normal priority SDEI */
+	EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_SDEI_NORMAL_PRI),
+#endif
+};
+
+/* Plug in Tegra exceptions to Exception Handling Framework. */
+EHF_REGISTER_PRIORITIES(tegra_exceptions, ARRAY_SIZE(tegra_exceptions), PLAT_PRI_BITS);
diff --git a/plat/nvidia/tegra/common/tegra_fiq_glue.c b/plat/nvidia/tegra/common/tegra_fiq_glue.c
index bb5add8..5309d98 100644
--- a/plat/nvidia/tegra/common/tegra_fiq_glue.c
+++ b/plat/nvidia/tegra/common/tegra_fiq_glue.c
@@ -26,15 +26,6 @@
 /* Legacy FIQ used by earlier Tegra platforms */
 #define LEGACY_FIQ_PPI_WDT		28U
 
-/* Install priority level descriptors for each dispatcher */
-ehf_pri_desc_t plat_exceptions[] = {
-	EHF_PRI_DESC(PLAT_PRI_BITS, PLAT_TEGRA_WDT_PRIO),
-};
-
-/* Expose priority descriptors to Exception Handling Framework */
-EHF_REGISTER_PRIORITIES(plat_exceptions, ARRAY_SIZE(plat_exceptions),
-	PLAT_PRI_BITS);
-
 /*******************************************************************************
  * Static variables
  ******************************************************************************/
diff --git a/plat/nvidia/tegra/common/tegra_gicv3.c b/plat/nvidia/tegra/common/tegra_gicv3.c
new file mode 100644
index 0000000..cba2f9b
--- /dev/null
+++ b/plat/nvidia/tegra/common/tegra_gicv3.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/bl_common.h>
+#include <drivers/arm/gicv3.h>
+#include <lib/utils.h>
+
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <tegra_private.h>
+#include <tegra_def.h>
+
+/* The GICv3 driver only needs to be initialized in EL3 */
+static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
+
+static unsigned int plat_tegra_mpidr_to_core_pos(unsigned long mpidr)
+{
+	return (unsigned int)plat_core_pos_by_mpidr(mpidr);
+}
+
+/******************************************************************************
+ * Tegra common helper to setup the GICv3 driver data.
+ *****************************************************************************/
+void tegra_gic_setup(const interrupt_prop_t *interrupt_props,
+		     unsigned int interrupt_props_num)
+{
+	/*
+	 * Tegra GIC configuration settings
+	 */
+	static gicv3_driver_data_t tegra_gic_data;
+
+	/*
+	 * Register Tegra GICv3 driver
+	 */
+	tegra_gic_data.gicd_base = TEGRA_GICD_BASE;
+	tegra_gic_data.gicr_base = TEGRA_GICR_BASE;
+	tegra_gic_data.rdistif_num = PLATFORM_CORE_COUNT;
+	tegra_gic_data.rdistif_base_addrs = rdistif_base_addrs;
+	tegra_gic_data.mpidr_to_core_pos = plat_tegra_mpidr_to_core_pos;
+	tegra_gic_data.interrupt_props = interrupt_props;
+	tegra_gic_data.interrupt_props_num = interrupt_props_num;
+	gicv3_driver_init(&tegra_gic_data);
+
+	/* initialize the GICD and GICR */
+	tegra_gic_init();
+}
+
+/******************************************************************************
+ * Tegra common helper to initialize the GICv3 only driver.
+ *****************************************************************************/
+void tegra_gic_init(void)
+{
+	gicv3_distif_init();
+	gicv3_rdistif_init(plat_my_core_pos());
+	gicv3_cpuif_enable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Tegra common helper to disable the GICv3 CPU interface
+ *****************************************************************************/
+void tegra_gic_cpuif_deactivate(void)
+{
+	gicv3_cpuif_disable(plat_my_core_pos());
+}
+
+/******************************************************************************
+ * Tegra common helper to initialize the per cpu distributor interface
+ * in GICv3
+ *****************************************************************************/
+void tegra_gic_pcpu_init(void)
+{
+	gicv3_rdistif_init(plat_my_core_pos());
+	gicv3_cpuif_enable(plat_my_core_pos());
+}
diff --git a/plat/nvidia/tegra/common/tegra_platform.c b/plat/nvidia/tegra/common/tegra_platform.c
index e4338b9..0804135 100644
--- a/plat/nvidia/tegra/common/tegra_platform.c
+++ b/plat/nvidia/tegra/common/tegra_platform.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
  * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -8,6 +8,8 @@
 #include <arch_helpers.h>
 #include <assert.h>
 #include <lib/mmio.h>
+#include <lib/smccc.h>
+#include <services/arm_arch_svc.h>
 #include <tegra_def.h>
 #include <tegra_platform.h>
 #include <tegra_private.h>
@@ -286,3 +288,21 @@
 {
 	return (int32_t)((tegra_get_chipid_major() << 8) | tegra_get_chipid_minor());
 }
+
+/*****************************************************************************
+ * plat_smccc_feature_available() - This function checks whether SMCCC feature
+ *                                  is availabile for the platform or not.
+ * @fid: SMCCC function id
+ *
+ * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and
+ * SMC_ARCH_CALL_NOT_SUPPORTED otherwise.
+ *****************************************************************************/
+int32_t plat_smccc_feature_available(u_register_t fid)
+{
+	switch (fid) {
+	case SMCCC_ARCH_SOC_ID:
+		return SMC_ARCH_CALL_SUCCESS;
+	default:
+		return SMC_ARCH_CALL_NOT_SUPPORTED;
+	}
+}
diff --git a/plat/nvidia/tegra/common/tegra_sdei.c b/plat/nvidia/tegra/common/tegra_sdei.c
new file mode 100644
index 0000000..9241b81
--- /dev/null
+++ b/plat/nvidia/tegra/common/tegra_sdei.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* SDEI configuration for Tegra platforms */
+
+#include <platform_def.h>
+
+#include <bl31/ehf.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <lib/utils_def.h>
+#include <services/sdei.h>
+
+/* Private event mappings */
+static sdei_ev_map_t tegra_sdei_private[] = {
+	/* Event 0 definition */
+	SDEI_DEFINE_EVENT_0(TEGRA_SDEI_SGI_PRIVATE),
+
+	/* Dynamic private events */
+	SDEI_PRIVATE_EVENT(TEGRA_SDEI_DP_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
+	SDEI_PRIVATE_EVENT(TEGRA_SDEI_DP_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
+	SDEI_PRIVATE_EVENT(TEGRA_SDEI_DP_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
+
+	/* General purpose explicit events */
+	SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_0, SDEI_MAPF_CRITICAL),
+	SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_1, SDEI_MAPF_CRITICAL),
+	SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_2, SDEI_MAPF_CRITICAL),
+	SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_3, SDEI_MAPF_CRITICAL),
+	SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_4, SDEI_MAPF_CRITICAL),
+	SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_5, SDEI_MAPF_CRITICAL),
+	SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_6, SDEI_MAPF_CRITICAL),
+	SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_7, SDEI_MAPF_CRITICAL),
+	SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_8, SDEI_MAPF_CRITICAL),
+	SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_9, SDEI_MAPF_CRITICAL),
+	SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_10, SDEI_MAPF_CRITICAL),
+	SDEI_EXPLICIT_EVENT(TEGRA_SDEI_EP_EVENT_11, SDEI_MAPF_CRITICAL)
+};
+
+/* Shared event mappings */
+static sdei_ev_map_t tegra_sdei_shared[] = {
+	/* Dynamic shared events */
+	SDEI_SHARED_EVENT(TEGRA_SDEI_DS_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
+	SDEI_SHARED_EVENT(TEGRA_SDEI_DS_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC),
+	SDEI_SHARED_EVENT(TEGRA_SDEI_DS_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC)
+};
+
+void plat_sdei_setup(void)
+{
+	INFO("SDEI platform setup\n");
+}
+
+/* Export Tegra SDEI events */
+REGISTER_SDEI_MAP(tegra_sdei_private, tegra_sdei_shared);
diff --git a/plat/nvidia/tegra/common/tegra_stack_protector.c b/plat/nvidia/tegra/common/tegra_stack_protector.c
new file mode 100644
index 0000000..f6c459a
--- /dev/null
+++ b/plat/nvidia/tegra/common/tegra_stack_protector.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+	u_register_t seed;
+
+	/*
+	 * Ideally, a random number should be returned instead. As the
+	 * platform does not have any random number generator, this is
+	 * better than nothing, but not really secure.
+	 */
+	seed = mmio_read_32(TEGRA_MISC_BASE + HARDWARE_REVISION_OFFSET);
+	seed <<= 32;
+	seed |= mmio_read_32(TEGRA_TMRUS_BASE);
+
+	return seed ^ read_cntpct_el0();
+}
diff --git a/plat/nvidia/tegra/include/platform_def.h b/plat/nvidia/tegra/include/platform_def.h
index 6bfad23..2331869 100644
--- a/plat/nvidia/tegra/include/platform_def.h
+++ b/plat/nvidia/tegra/include/platform_def.h
@@ -87,9 +87,44 @@
 #define MAX_IO_HANDLES			U(0)
 
 /*******************************************************************************
+ * Platforms macros to support SDEI
+ ******************************************************************************/
+#define TEGRA_SDEI_SGI_PRIVATE		U(8)
+
+/*******************************************************************************
  * Platform macros to support exception handling framework
  ******************************************************************************/
 #define PLAT_PRI_BITS			U(3)
+#define PLAT_RAS_PRI			U(0x10)
+#define PLAT_SDEI_CRITICAL_PRI		U(0x20)
+#define PLAT_SDEI_NORMAL_PRI		U(0x30)
 #define PLAT_TEGRA_WDT_PRIO		U(0x40)
 
+/*******************************************************************************
+ * SDEI events
+ ******************************************************************************/
+/* SDEI dynamic private event numbers */
+#define TEGRA_SDEI_DP_EVENT_0		U(100)
+#define TEGRA_SDEI_DP_EVENT_1		U(101)
+#define TEGRA_SDEI_DP_EVENT_2		U(102)
+
+/* SDEI dynamic shared event numbers */
+#define TEGRA_SDEI_DS_EVENT_0		U(200)
+#define TEGRA_SDEI_DS_EVENT_1		U(201)
+#define TEGRA_SDEI_DS_EVENT_2		U(202)
+
+/* SDEI explicit events */
+#define TEGRA_SDEI_EP_EVENT_0		U(300)
+#define TEGRA_SDEI_EP_EVENT_1		U(301)
+#define TEGRA_SDEI_EP_EVENT_2		U(302)
+#define TEGRA_SDEI_EP_EVENT_3		U(303)
+#define TEGRA_SDEI_EP_EVENT_4		U(304)
+#define TEGRA_SDEI_EP_EVENT_5		U(305)
+#define TEGRA_SDEI_EP_EVENT_6		U(306)
+#define TEGRA_SDEI_EP_EVENT_7		U(307)
+#define TEGRA_SDEI_EP_EVENT_8		U(308)
+#define TEGRA_SDEI_EP_EVENT_9		U(309)
+#define TEGRA_SDEI_EP_EVENT_10		U(310)
+#define TEGRA_SDEI_EP_EVENT_11		U(311)
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/nvidia/tegra/include/t194/tegra194_ras_private.h b/plat/nvidia/tegra/include/t194/tegra194_ras_private.h
new file mode 100644
index 0000000..336461a
--- /dev/null
+++ b/plat/nvidia/tegra/include/t194/tegra194_ras_private.h
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TEGRA194_RAS_PRIVATE
+#define TEGRA194_RAS_PRIVATE
+
+#include <stdint.h>
+
+/* Implementation defined RAS error and corresponding error message */
+struct ras_error {
+	const char *error_msg;
+	/* IERR(bits[15:8]) from ERR<n>STATUS */
+	uint8_t error_code;
+};
+
+/* RAS error node-specific auxiliary data */
+struct ras_aux_data {
+	/* name for current RAS node. */
+	const char *name;
+	/* point to null-terminated ras_error array to convert error code to msg. */
+	const struct ras_error *error_records;
+	/*
+	 * function to return an value which needs to be programmed into ERXCTLR_EL1
+	 * to enable all specified RAS errors for current node.
+	 */
+	uint64_t (*err_ctrl)(void);
+};
+
+/* IFU Uncorrectable RAS ERROR */
+#define IFU_UNCORR_RAS_ERROR_LIST(X)
+
+/* JSR_RET Uncorrectable RAS ERROR */
+#define JSR_RET_UNCORR_RAS_ERROR_LIST(X)					\
+	/* Name, ERR_CTRL, IERR, ISA Desc */					\
+	X(JSR_RET, 35, 0x13, "Floating Point Register File Parity Error")	\
+	X(JSR_RET, 34, 0x12, "Integer Register File Parity Error")		\
+	X(JSR_RET, 33, 0x11, "Garbage Bundle")					\
+	X(JSR_RET, 32, 0x10, "Bundle Completion Timeout")
+
+/* JSR_MTS Uncorrectable RAS ERROR */
+#define JSR_MTS_UNCORR_RAS_ERROR_LIST(X)					\
+	/* Name, ERR_CTRL, IERR, ISA Desc */					\
+	X(JSR_MTS, 40, 0x28, "CoreSight Access Error")				\
+	X(JSR_MTS, 39, 0x27, "Dual Execution Uncorrectable Error")		\
+	X(JSR_MTS, 37, 0x25, "CTU MMIO Region")					\
+	X(JSR_MTS, 36, 0x24, "MTS MMCRAB Region Access")			\
+	X(JSR_MTS, 35, 0x23, "MTS_CARVEOUT Access from ARM SW")			\
+	X(JSR_MTS, 34, 0x22, "NAFLL PLL Failure to Lock")			\
+	X(JSR_MTS, 32, 0x20, "Internal Uncorrectable  MTS Error")
+
+/* LSD_STQ Uncorrectable RAS ERROR */
+#define LSD_STQ_UNCORR_RAS_ERROR_LIST(X)					\
+	/* Name, ERR_CTRL, IERR, ISA Desc */					\
+	X(LSD_STQ, 41, 0x39, "Coherent Cache Data Store Multi-Line ECC Error")	\
+	X(LSD_STQ, 40, 0x38, "Coherent Cache Data Store Uncorrectable ECC Error") \
+	X(LSD_STQ, 38, 0x36, "Coherent Cache Data Load Uncorrectable ECC Error") \
+	X(LSD_STQ, 33, 0x31, "Coherent Cache Tag Store Parity Error")		\
+	X(LSD_STQ, 32, 0x30, "Coherent Cache Tag Load Parity Error")
+
+/* LSD_DCC Uncorrectable RAS ERROR */
+#define LSD_DCC_UNCORR_RAS_ERROR_LIST(X)					\
+	/* Name, ERR_CTRL, IERR, ISA Desc */					\
+	X(LSD_DCC, 41, 0x49, "BTU Copy Mini-Cache PPN Multi-Hit Error")		\
+	X(LSD_DCC, 39, 0x47, "Coherent Cache Data Uncorrectable ECC Error")	\
+	X(LSD_DCC, 37, 0x45, "Version Cache Byte-Enable Parity Error")		\
+	X(LSD_DCC, 36, 0x44, "Version Cache Data Uncorrectable ECC Error")	\
+	X(LSD_DCC, 33, 0x41, "BTU Copy Coherent Cache PPN Parity Error")	\
+	X(LSD_DCC, 32, 0x40, "BTU Copy Coherent Cache VPN Parity Error")
+
+/* LSD_L1HPF Uncorrectable RAS ERROR */
+#define LSD_L1HPF_UNCORR_RAS_ERROR_LIST(X)
+
+/* L2 Uncorrectable RAS ERROR */
+#define L2_UNCORR_RAS_ERROR_LIST(X)						\
+	/* Name, ERR_CTRL, IERR, ISA Desc */					\
+	X(L2, 56, 0x68, "URT Timeout")						\
+	X(L2, 55, 0x67, "L2 Protocol Violation")				\
+	X(L2, 54, 0x66, "SCF to L2 Slave Error Read")				\
+	X(L2, 53, 0x65, "SCF to L2 Slave Error Write")				\
+	X(L2, 52, 0x64, "SCF to L2 Decode Error Read")				\
+	X(L2, 51, 0x63, "SCF to L2 Decode Error Write")				\
+	X(L2, 50, 0x62, "SCF to L2 Request Response Interface Parity Errors")	\
+	X(L2, 49, 0x61, "SCF to L2 Advance notice interface parity errors")	\
+	X(L2, 48, 0x60, "SCF to L2 Filldata Parity Errors")			\
+	X(L2, 47, 0x5F, "SCF to L2 UnCorrectable ECC Data Error on interface")	\
+	X(L2, 45, 0x5D, "Core 1 to L2 Parity Error")				\
+	X(L2, 44, 0x5C, "Core 0 to L2 Parity Error")				\
+	X(L2, 43, 0x5B, "L2 Multi-Hit")						\
+	X(L2, 42, 0x5A, "L2 URT Tag Parity Error")				\
+	X(L2, 41, 0x59, "L2 NTT Tag Parity Error")				\
+	X(L2, 40, 0x58, "L2 MLT Tag Parity Error")				\
+	X(L2, 39, 0x57, "L2 URD Data")						\
+	X(L2, 38, 0x56, "L2 NTP Data")						\
+	X(L2, 36, 0x54, "L2 MLC Uncorrectable Clean")				\
+	X(L2, 35, 0x53, "L2 URD Uncorrectable Dirty")				\
+	X(L2, 34, 0x52, "L2 MLC Uncorrectable Dirty")
+
+/* CLUSTER_CLOCKS Uncorrectable RAS ERROR */
+#define CLUSTER_CLOCKS_UNCORR_RAS_ERROR_LIST(X)					\
+	/* Name, ERR_CTRL, IERR, ISA Desc */					\
+	X(CLUSTER_CLOCKS, 32, 0xE4, "Frequency Monitor Error")
+
+/* MMU Uncorrectable RAS ERROR */
+#define MMU_UNCORR_RAS_ERROR_LIST(X)
+
+/* L3 Uncorrectable RAS ERROR */
+#define L3_UNCORR_RAS_ERROR_LIST(X)						\
+	/* Name, ERR_CTRL, IERR, ISA Desc */					\
+	X(L3, 43, 0x7B, "SNOC Interface Parity Error")				\
+	X(L3, 42, 0x7A, "MCF Interface Parity Error")				\
+	X(L3, 41, 0x79, "L3 Tag Parity Error")					\
+	X(L3, 40, 0x78, "L3 Dir Parity Error")					\
+	X(L3, 39, 0x77, "L3 Uncorrectable ECC Error")				\
+	X(L3, 37, 0x75, "Multi-Hit CAM Error")					\
+	X(L3, 36, 0x74, "Multi-Hit Tag Error")					\
+	X(L3, 35, 0x73, "Unrecognized Command Error")				\
+	X(L3, 34, 0x72, "L3 Protocol Error")
+
+/* CCPMU Uncorrectable RAS ERROR */
+#define CCPMU_UNCORR_RAS_ERROR_LIST(X)						\
+	/* Name, ERR_CTRL, IERR, ISA Desc */					\
+	X(CCPMU, 40, 0x87, "CoreSight Access Error")				\
+	X(CCPMU, 36, 0x84, "MCE Ucode Error")					\
+	X(CCPMU, 35, 0x83, "MCE IL1 Parity Error")				\
+	X(CCPMU, 34, 0x82, "MCE Timeout Error")					\
+	X(CCPMU, 33, 0x81, "CRAB Access Error")					\
+	X(CCPMU, 32, 0x80, "MCE Memory Access Error")
+
+/* SCF_IOB Uncorrectable RAS ERROR */
+#define SCF_IOB_UNCORR_RAS_ERROR_LIST(X)					\
+	/* Name, ERR_CTRL, IERR, ISA Desc */					\
+	X(SCF_IOB, 41, 0x99, "Request parity error")				\
+	X(SCF_IOB, 40, 0x98, "Putdata parity error")				\
+	X(SCF_IOB, 39, 0x97, "Uncorrectable ECC on Putdata")			\
+	X(SCF_IOB, 38, 0x96, "CBB Interface Error")				\
+	X(SCF_IOB, 37, 0x95, "MMCRAB Error")					\
+	X(SCF_IOB, 36, 0x94, "IHI Interface Error")				\
+	X(SCF_IOB, 35, 0x93, "CRI Error")					\
+	X(SCF_IOB, 34, 0x92, "TBX Interface Error")				\
+	X(SCF_IOB, 33, 0x91, "EVP Interface Error")
+
+/* SCF_SNOC Uncorrectable RAS ERROR */
+#define SCF_SNOC_UNCORR_RAS_ERROR_LIST(X)					\
+	/* Name, ERR_CTRL, IERR, ISA Desc */					\
+	X(SCF_SNOC, 42, 0xAA, "Misc Client Parity Error")			\
+	X(SCF_SNOC, 41, 0xA9, "Misc Filldata Parity Error")			\
+	X(SCF_SNOC, 40, 0xA8, "Uncorrectable ECC Misc Client")			\
+	X(SCF_SNOC, 39, 0xA7, "DVMU Interface Parity Error")			\
+	X(SCF_SNOC, 38, 0xA6, "DVMU Interface Timeout Error")			\
+	X(SCF_SNOC, 37, 0xA5, "CPE Request Error")				\
+	X(SCF_SNOC, 36, 0xA4, "CPE Response Error")				\
+	X(SCF_SNOC, 35, 0xA3, "CPE Timeout Error")				\
+	X(SCF_SNOC, 34, 0xA2, "Uncorrectable Carveout Error")
+
+/* SCF_CTU Uncorrectable RAS ERROR */
+#define SCF_CTU_UNCORR_RAS_ERROR_LIST(X)					\
+	/* Name, ERR_CTRL, IERR, ISA Desc */					\
+	X(SCF_CTU, 39, 0xB7, "Timeout error for TRC_DMA request")		\
+	X(SCF_CTU, 38, 0xB6, "Timeout error for CTU Snp")			\
+	X(SCF_CTU, 37, 0xB5, "Parity error in CTU TAG RAM")			\
+	X(SCF_CTU, 36, 0xB3, "Parity error in CTU DATA RAM")			\
+	X(SCF_CTU, 35, 0xB4, "Parity error for Cluster Rsp")			\
+	X(SCF_CTU, 34, 0xB2, "Parity error for TRL requests from 9 agents")	\
+	X(SCF_CTU, 33, 0xB1, "Parity error for MCF request")			\
+	X(SCF_CTU, 32, 0xB0, "TRC DMA fillsnoop parity error")
+
+/* CMU_CLOCKS Uncorrectable RAS ERROR */
+#define CMU_CLOCKS_UNCORR_RAS_ERROR_LIST(X)					\
+	/* Name, ERR_CTRL, IERR, ISA Desc */					\
+	X(CMU_CLOCKS, 39, 0xC7, "Cluster 3 frequency monitor error")		\
+	X(CMU_CLOCKS, 38, 0xC6, "Cluster 2 frequency monitor error")		\
+	X(CMU_CLOCKS, 37, 0xC5, "Cluster 1 frequency monitor error")		\
+	X(CMU_CLOCKS, 36, 0xC3, "Cluster 0 frequency monitor error")		\
+	X(CMU_CLOCKS, 35, 0xC4, "Voltage error on ADC1 Monitored Logic")	\
+	X(CMU_CLOCKS, 34, 0xC2, "Voltage error on ADC0 Monitored Logic")	\
+	X(CMU_CLOCKS, 33, 0xC1, "Lookup Table 1 Parity Error")			\
+	X(CMU_CLOCKS, 32, 0xC0, "Lookup Table 0 Parity Error")
+
+/*
+ * Define one ras_error entry.
+ *
+ * This macro wille be used to to generate ras_error records for each node
+ * defined by <NODE_NAME>_UNCORR_RAS_ERROR_LIST macro.
+ */
+#define DEFINE_ONE_RAS_ERROR_MSG(unit, ras_bit, ierr, msg)			\
+	{									\
+		.error_msg = (msg),						\
+		.error_code = (ierr)						\
+	},
+
+/*
+ * Set one implementation defined bit in ERR<n>CTLR
+ *
+ * This macro will be used to collect all defined ERR_CTRL bits for each node
+ * defined by <NODE_NAME>_UNCORR_RAS_ERROR_LIST macro.
+ */
+#define DEFINE_ENABLE_RAS_BIT(unit, ras_bit, ierr, msg)				\
+	do {									\
+		val |= (1ULL << ras_bit##U);					\
+	} while (0);
+
+/* Represent one RAS node with 0 or more error bits (ERR_CTLR) enabled */
+#define DEFINE_ONE_RAS_NODE(node)						\
+static const struct ras_error node##_uncorr_ras_errors[] = {			\
+	node##_UNCORR_RAS_ERROR_LIST(DEFINE_ONE_RAS_ERROR_MSG)			\
+	{									\
+		NULL,								\
+		0U								\
+	},									\
+};										\
+static inline uint64_t node##_err_ctrl(void)					\
+{										\
+	uint64_t val = 0ULL;							\
+	node##_UNCORR_RAS_ERROR_LIST(DEFINE_ENABLE_RAS_BIT)			\
+	return val;								\
+}
+
+#define DEFINE_ONE_RAS_AUX_DATA(node)						\
+	{									\
+		.name = #node,							\
+		.error_records = node##_uncorr_ras_errors,			\
+		.err_ctrl = &node##_err_ctrl					\
+	},
+
+#define PER_CORE_RAS_NODE_LIST(X)						\
+	X(IFU)									\
+	X(JSR_RET)								\
+	X(JSR_MTS)								\
+	X(LSD_STQ)								\
+	X(LSD_DCC)								\
+	X(LSD_L1HPF)
+
+#define PER_CORE_RAS_GROUP_NODES	PER_CORE_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA)
+
+#define PER_CLUSTER_RAS_NODE_LIST(X)						\
+	X(L2)									\
+	X(CLUSTER_CLOCKS)							\
+	X(MMU)
+
+#define PER_CLUSTER_RAS_GROUP_NODES	PER_CLUSTER_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA)
+
+#define SCF_L3_BANK_RAS_NODE_LIST(X)	X(L3)
+
+/* we have 4 SCF_L3 nodes:3*256 + L3_Bank_ID(0-3) */
+#define SCF_L3_BANK_RAS_GROUP_NODES						\
+	SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA)			\
+	SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA)			\
+	SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA)			\
+	SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA)
+
+#define CCPLEX_RAS_NODE_LIST(X)							\
+	X(CCPMU)								\
+	X(SCF_IOB)								\
+	X(SCF_SNOC)								\
+	X(SCF_CTU)								\
+	X(CMU_CLOCKS)
+
+#define CCPLEX_RAS_GROUP_NODES		CCPLEX_RAS_NODE_LIST(DEFINE_ONE_RAS_AUX_DATA)
+
+#endif /* TEGRA194_RAS_PRIVATE */
diff --git a/plat/nvidia/tegra/include/tegra_private.h b/plat/nvidia/tegra/include/tegra_private.h
index f72c9cf..c181c36 100644
--- a/plat/nvidia/tegra/include/tegra_private.h
+++ b/plat/nvidia/tegra/include/tegra_private.h
@@ -89,7 +89,7 @@
 
 /* Declarations for tegra_fiq_glue.c */
 void tegra_fiq_handler_setup(void);
-int tegra_fiq_get_intr_context(void);
+int32_t tegra_fiq_get_intr_context(void);
 void tegra_fiq_set_ns_entrypoint(uint64_t entrypoint);
 
 /* Declarations for tegra_security.c */
@@ -157,4 +157,9 @@
 		     void *handle,
 		     uint64_t flags);
 
+#if RAS_EXTENSION
+void tegra194_ras_enable(void);
+void tegra194_ras_corrected_err_clear(void);
+#endif
+
 #endif /* TEGRA_PRIVATE_H */
diff --git a/plat/nvidia/tegra/platform.mk b/plat/nvidia/tegra/platform.mk
index e03e1f3..a4724e6 100644
--- a/plat/nvidia/tegra/platform.mk
+++ b/plat/nvidia/tegra/platform.mk
@@ -49,6 +49,12 @@
 # Flag to allow relocation of BL32 image to TZDRAM during boot
 RELOCATE_BL32_IMAGE		?= 0
 
+# Enable stack protection
+ENABLE_STACK_PROTECTOR		:=	strong
+
+# Enable SDEI
+SDEI_SUPPORT			:= 1
+
 include plat/nvidia/tegra/common/tegra_common.mk
 include ${SOC_DIR}/platform_${TARGET_SOC}.mk
 
@@ -56,13 +62,14 @@
 $(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}
+BUILD_PLAT	:=	$(abspath ${BUILD_BASE})/${PLAT}/${TARGET_SOC}/${BUILD_TYPE}
 
 # platform cflags (enable signed comparisons, disable stdlib)
 TF_CFLAGS	+= -Wsign-compare -nostdlib
 
 # override with necessary libc files for the Tegra platform
 override LIBC_SRCS :=	$(addprefix lib/libc/,		\
+			aarch64/setjmp.S		\
 			assert.c			\
 			memcpy.c			\
 			memmove.c			\
diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c
index 1c7c25d..c216b5d 100644
--- a/plat/nvidia/tegra/soc/t186/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t186/plat_setup.c
@@ -214,6 +214,8 @@
 
 /* Secure IRQs for Tegra186 */
 static const interrupt_prop_t tegra186_interrupt_props[] = {
+	INTR_PROP_DESC(TEGRA_SDEI_SGI_PRIVATE, PLAT_SDEI_CRITICAL_PRI,
+			GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
 	INTR_PROP_DESC(TEGRA186_TOP_WDT_IRQ, PLAT_TEGRA_WDT_PRIO,
 			GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
 	INTR_PROP_DESC(TEGRA186_AON_WDT_IRQ, PLAT_TEGRA_WDT_PRIO,
diff --git a/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h b/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h
index 1fe3aad..6dafeb2 100644
--- a/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h
+++ b/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h
@@ -58,6 +58,7 @@
 void nvg_enable_strict_checking_mode(void);
 void nvg_system_shutdown(void);
 void nvg_system_reboot(void);
+void nvg_clear_hsm_corr_status(void);
 
 /* declarations for assembly functions */
 void nvg_set_request_data(uint64_t req, uint64_t data);
@@ -71,5 +72,6 @@
 void mce_enable_strict_checking(void);
 void mce_system_shutdown(void);
 void mce_system_reboot(void);
+void mce_clear_hsm_corr_status(void);
 
 #endif /* MCE_PRIVATE_H */
diff --git a/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c b/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c
index 7edd7a0..4663a3d 100644
--- a/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c
+++ b/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c
@@ -234,3 +234,11 @@
 {
 	nvg_system_reboot();
 }
+
+/*******************************************************************************
+ * Handler to clear CCPLEX->HSM correctable RAS error signal.
+ ******************************************************************************/
+void mce_clear_hsm_corr_status(void)
+{
+	nvg_clear_hsm_corr_status();
+}
diff --git a/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c b/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c
index ef740a1..fdf9429 100644
--- a/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c
+++ b/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c
@@ -236,3 +236,15 @@
 	nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_SHUTDOWN,
 			     (uint64_t)TEGRA_NVG_SHUTDOWN);
 }
+
+/*
+ * Request to clear CCPLEX->HSM correctable error signal.
+ * NVGDATA[1]: A write of 1 clears the CCPLEX->HSM correctable error signal,
+ *             A write of 0 has no effect.
+ */
+void nvg_clear_hsm_corr_status(void)
+{
+	nvg_hsm_error_ctrl_channel_t status = { .bits = { .corr = 1U, }, };
+
+	nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_HSM_ERROR_CTRL, status.flat);
+}
diff --git a/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
index ce5815b..e226372 100644
--- a/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
@@ -73,19 +73,16 @@
 	switch (state_id) {
 	case PSTATE_ID_CORE_IDLE:
 
+		if (psci_get_pstate_type(power_state) != PSTATE_TYPE_STANDBY) {
+			ret = PSCI_E_INVALID_PARAMS;
+			break;
+		}
+
 		/* Core idle request */
 		req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE;
 		req_state->pwr_domain_state[MPIDR_AFFLVL1] = PSCI_LOCAL_STATE_RUN;
 		break;
 
-	case PSTATE_ID_CORE_POWERDN:
-
-		/* Core powerdown request */
-		req_state->pwr_domain_state[MPIDR_AFFLVL0] = state_id;
-		req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id;
-
-		break;
-
 	default:
 		ERROR("%s: unsupported state id (%d)\n", __func__, state_id);
 		ret = PSCI_E_INVALID_PARAMS;
@@ -117,7 +114,7 @@
 int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
 {
 	const plat_local_state_t *pwr_domain_state;
-	uint8_t stateid_afflvl0, stateid_afflvl2;
+	uint8_t stateid_afflvl2;
 	plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
 	uint64_t mc_ctx_base;
 	uint32_t val;
@@ -128,25 +125,14 @@
 		.system_state_force = 1U,
 		.update_wake_mask = 1U,
 	};
-	uint32_t cpu = plat_my_core_pos();
 	int32_t ret = 0;
 
 	/* get the state ID */
 	pwr_domain_state = target_state->pwr_domain_state;
-	stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0] &
-		TEGRA194_STATE_ID_MASK;
 	stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] &
 		TEGRA194_STATE_ID_MASK;
 
-	if (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN) {
-
-		/* Enter CPU powerdown */
-		(void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE,
-					  (uint64_t)TEGRA_NVG_CORE_C7,
-					  t19x_percpu_data[cpu].wake_time,
-					  0U);
-
-	} else if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
+	if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
 
 		/* save 'Secure Boot' Processor Feature Config Register */
 		val = mmio_read_32(TEGRA_MISC_BASE + MISCREG_PFCFG);
@@ -187,8 +173,6 @@
 
 		/* set system suspend state for house-keeping */
 		tegra194_set_system_suspend_entry();
-	} else {
-		; /* do nothing */
 	}
 
 	return PSCI_E_SUCCESS;
@@ -226,15 +210,6 @@
 	plat_local_state_t target = states[core_pos];
 	mce_cstate_info_t cstate_info = { 0 };
 
-	/* CPU suspend */
-	if (target == PSTATE_ID_CORE_POWERDN) {
-
-		/* Program default wake mask */
-		cstate_info.wake_mask = TEGRA194_CORE_WAKE_MASK;
-		cstate_info.update_wake_mask = 1;
-		mce_update_cstate_info(&cstate_info);
-	}
-
 	/* CPU off */
 	if (target == PLAT_MAX_OFF_STATE) {
 
diff --git a/plat/nvidia/tegra/soc/t194/plat_ras.c b/plat/nvidia/tegra/soc/t194/plat_ras.c
new file mode 100644
index 0000000..54c2924
--- /dev/null
+++ b/plat/nvidia/tegra/soc/t194/plat_ras.c
@@ -0,0 +1,418 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <lib/bakery_lock.h>
+#include <lib/extensions/ras.h>
+#include <lib/utils_def.h>
+#include <services/sdei.h>
+
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <tegra194_ras_private.h>
+#include <tegra_def.h>
+#include <tegra_platform.h>
+#include <tegra_private.h>
+
+/*
+ * ERR<n>FR bits[63:32], it indicates supported RAS errors which can be enabled
+ * by setting corresponding bits in ERR<n>CTLR
+ */
+#define ERR_FR_EN_BITS_MASK	0xFFFFFFFF00000000ULL
+
+/* bakery lock for platform RAS handler. */
+static DEFINE_BAKERY_LOCK(ras_handler_lock);
+#define ras_lock()		bakery_lock_get(&ras_handler_lock)
+#define ras_unlock()		bakery_lock_release(&ras_handler_lock)
+
+/*
+ * Function to handle an External Abort received at EL3.
+ * This function is invoked by RAS framework.
+ */
+static void tegra194_ea_handler(unsigned int ea_reason, uint64_t syndrome,
+		void *cookie, void *handle, uint64_t flags)
+{
+	int32_t ret;
+
+	ras_lock();
+
+	ERROR("MPIDR 0x%lx: exception reason=%u syndrome=0x%llx\n",
+		read_mpidr(), ea_reason, syndrome);
+
+	/* Call RAS EA handler */
+	ret = ras_ea_handler(ea_reason, syndrome, cookie, handle, flags);
+	if (ret != 0) {
+		ERROR("RAS error handled!\n");
+		ret = sdei_dispatch_event(TEGRA_SDEI_EP_EVENT_0 +
+				plat_my_core_pos());
+		if (ret != 0)
+			ERROR("sdei_dispatch_event returned %d\n", ret);
+	} else {
+		ERROR("Not a RAS error!\n");
+	}
+
+	ras_unlock();
+}
+
+/*
+ * Function to enable all supported RAS error report.
+ *
+ * Uncorrected errors are set to report as External abort (SError)
+ * Corrected errors are set to report as interrupt.
+ */
+void tegra194_ras_enable(void)
+{
+	VERBOSE("%s\n", __func__);
+
+	/* skip RAS enablement if not a silicon platform. */
+	if (!tegra_platform_is_silicon()) {
+		return;
+	}
+
+	/*
+	 * Iterate for each group(num_idx ERRSELRs starting from idx_start)
+	 * use normal for loop instead of for_each_err_record_info to get rid
+	 * of MISRA noise..
+	 */
+	for (uint32_t i = 0U; i < err_record_mappings.num_err_records; i++) {
+
+		const struct err_record_info *info = &err_record_mappings.err_records[i];
+
+		uint32_t idx_start = info->sysreg.idx_start;
+		uint32_t num_idx = info->sysreg.num_idx;
+		const struct ras_aux_data *aux_data = (const struct ras_aux_data *)info->aux_data;
+
+		assert(aux_data != NULL);
+
+		for (uint32_t j = 0; j < num_idx; j++) {
+
+			/* ERR<n>CTLR register value. */
+			uint64_t err_ctrl = 0ULL;
+			/* all supported errors for this node. */
+			uint64_t err_fr;
+			/* uncorrectable errors */
+			uint64_t uncorr_errs;
+			/* correctable errors */
+			uint64_t corr_errs;
+
+			/*
+			 * Catch error if something wrong with the RAS aux data
+			 * record table.
+			 */
+			assert(aux_data[j].err_ctrl != NULL);
+
+			/*
+			 * Write to ERRSELR_EL1 to select the RAS error node.
+			 * Always program this at first to select corresponding
+			 * RAS node before any other RAS register r/w.
+			 */
+			ser_sys_select_record(idx_start + j);
+
+			err_fr = read_erxfr_el1() & ERR_FR_EN_BITS_MASK;
+			uncorr_errs = aux_data[j].err_ctrl();
+			corr_errs = ~uncorr_errs & err_fr;
+
+			/* enable error reporting */
+			ERR_CTLR_ENABLE_FIELD(err_ctrl, ED);
+
+			/* enable SError reporting for uncorrectable errors */
+			if ((uncorr_errs & err_fr) != 0ULL) {
+				ERR_CTLR_ENABLE_FIELD(err_ctrl, UE);
+			}
+
+			/* generate interrupt for corrected errors. */
+			if (corr_errs != 0ULL) {
+				ERR_CTLR_ENABLE_FIELD(err_ctrl, CFI);
+			}
+
+			/* enable the supported errors */
+			err_ctrl |= err_fr;
+
+			VERBOSE("errselr_el1:0x%x, erxfr:0x%llx, err_ctrl:0x%llx\n",
+				idx_start + j, err_fr, err_ctrl);
+
+			/* enable specified errors, or set to 0 if no supported error */
+			write_erxctlr_el1(err_ctrl);
+
+			/*
+			 * Check if all the bit settings have been enabled to detect
+			 * uncorrected/corrected errors, if not assert.
+			 */
+			assert(read_erxctlr_el1() == err_ctrl);
+		}
+	}
+}
+
+/*
+ * Function to clear RAS ERR<n>STATUS for corrected RAS error.
+ * This function ignores any new RAS error signaled during clearing; it is not
+ * multi-core safe(no ras_lock is taken to reduce overhead).
+ */
+void tegra194_ras_corrected_err_clear(void)
+{
+	uint64_t clear_ce_status = 0ULL;
+
+	ERR_STATUS_SET_FIELD(clear_ce_status, AV, 0x1UL);
+	ERR_STATUS_SET_FIELD(clear_ce_status, V, 0x1UL);
+	ERR_STATUS_SET_FIELD(clear_ce_status, OF, 0x1UL);
+	ERR_STATUS_SET_FIELD(clear_ce_status, MV, 0x1UL);
+	ERR_STATUS_SET_FIELD(clear_ce_status, CE, 0x3UL);
+
+	for (uint32_t i = 0U; i < err_record_mappings.num_err_records; i++) {
+
+		const struct err_record_info *info = &err_record_mappings.err_records[i];
+		uint32_t idx_start = info->sysreg.idx_start;
+		uint32_t num_idx = info->sysreg.num_idx;
+
+		for (uint32_t j = 0U; j < num_idx; j++) {
+
+			uint64_t status;
+			uint32_t err_idx = idx_start + j;
+
+			write_errselr_el1(err_idx);
+			status = read_erxstatus_el1();
+
+			if (ERR_STATUS_GET_FIELD(status, CE) != 0U) {
+				write_erxstatus_el1(clear_ce_status);
+			}
+		}
+	}
+}
+
+/* Function to probe an error from error record group. */
+static int32_t tegra194_ras_record_probe(const struct err_record_info *info,
+		int *probe_data)
+{
+	/* Skip probing if not a silicon platform */
+	if (!tegra_platform_is_silicon()) {
+		return 0;
+	}
+
+	return ser_probe_sysreg(info->sysreg.idx_start, info->sysreg.num_idx, probe_data);
+}
+
+/* Function to handle error from one given node */
+static int32_t tegra194_ras_node_handler(uint32_t errselr, const char *name,
+		const struct ras_error *errors, uint64_t status)
+{
+	bool found = false;
+	uint32_t ierr = (uint32_t)ERR_STATUS_GET_FIELD(status, IERR);
+	uint32_t serr = (uint32_t)ERR_STATUS_GET_FIELD(status, SERR);
+	uint64_t val = 0;
+
+	/* not a valid error. */
+	if (ERR_STATUS_GET_FIELD(status, V) == 0U) {
+		return 0;
+	}
+
+	ERR_STATUS_SET_FIELD(val, V, 1);
+
+	/* keep the log print same as linux arm64_ras driver. */
+	ERROR("**************************************\n");
+	ERROR("RAS Error in %s, ERRSELR_EL1=0x%x:\n", name, errselr);
+	ERROR("\tStatus = 0x%llx\n", status);
+
+	/* Print uncorrectable errror information. */
+	if (ERR_STATUS_GET_FIELD(status, UE) != 0U) {
+
+		ERR_STATUS_SET_FIELD(val, UE, 1);
+		ERR_STATUS_SET_FIELD(val, UET, 1);
+
+		/* IERR to error message */
+		for (uint32_t i = 0; errors[i].error_msg != NULL; i++) {
+			if (ierr == errors[i].error_code) {
+				ERROR("\tIERR = %s: 0x%x\n",
+					errors[i].error_msg, ierr);
+
+				found = true;
+				break;
+			}
+		}
+
+		if (!found) {
+			ERROR("\tUnknown IERR: 0x%x\n", ierr);
+		}
+
+		ERROR("SERR = %s: 0x%x\n", ras_serr_to_str(serr), serr);
+
+		/* Overflow, multiple errors have been detected. */
+		if (ERR_STATUS_GET_FIELD(status, OF) != 0U) {
+			ERROR("\tOverflow (there may be more errors) - "
+				"Uncorrectable\n");
+			ERR_STATUS_SET_FIELD(val, OF, 1);
+		}
+
+		ERROR("\tUncorrectable (this is fatal)\n");
+
+		/* Miscellaneous Register Valid. */
+		if (ERR_STATUS_GET_FIELD(status, MV) != 0U) {
+			ERROR("\tMISC0 = 0x%lx\n", read_erxmisc0_el1());
+			ERROR("\tMISC1 = 0x%lx\n", read_erxmisc1_el1());
+			ERR_STATUS_SET_FIELD(val, MV, 1);
+		}
+
+		/* Address Valid. */
+		if (ERR_STATUS_GET_FIELD(status, AV) != 0U) {
+			ERROR("\tADDR = 0x%lx\n", read_erxaddr_el1());
+			ERR_STATUS_SET_FIELD(val, AV, 1);
+		}
+
+		/* Deferred error */
+		if (ERR_STATUS_GET_FIELD(status, DE) != 0U) {
+			ERROR("\tDeferred error\n");
+			ERR_STATUS_SET_FIELD(val, DE, 1);
+		}
+
+	} else {
+		/* For corrected error, simply clear it. */
+		VERBOSE("corrected RAS error is cleared: ERRSELR_EL1:0x%x, "
+			"IERR:0x%x, SERR:0x%x\n", errselr, ierr, serr);
+		ERR_STATUS_SET_FIELD(val, CE, 1);
+	}
+
+	ERROR("**************************************\n");
+
+	/* Write to clear reported errors. */
+	write_erxstatus_el1(val);
+
+	/* error handled */
+	return 0;
+}
+
+/* Function to handle one error node from an error record group. */
+static int32_t tegra194_ras_record_handler(const struct err_record_info *info,
+		int probe_data, const struct err_handler_data *const data __unused)
+{
+	uint32_t num_idx = info->sysreg.num_idx;
+	uint32_t idx_start = info->sysreg.idx_start;
+	const struct ras_aux_data *aux_data = info->aux_data;
+	const struct ras_error *errors;
+	uint32_t offset;
+	const char *node_name;
+
+	uint64_t status = 0ULL;
+
+	VERBOSE("%s\n", __func__);
+
+	assert(probe_data >= 0);
+	assert((uint32_t)probe_data < num_idx);
+
+	offset = (uint32_t)probe_data;
+	errors = aux_data[offset].error_records;
+	node_name = aux_data[offset].name;
+
+	assert(errors != NULL);
+
+	/* Write to ERRSELR_EL1 to select the error record */
+	ser_sys_select_record(idx_start + offset);
+
+	/* Retrieve status register from the error record */
+	status = read_erxstatus_el1();
+
+	return tegra194_ras_node_handler(idx_start + offset, node_name,
+			errors, status);
+}
+
+
+/* Instantiate RAS nodes */
+PER_CORE_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE)
+PER_CLUSTER_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE)
+SCF_L3_BANK_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE)
+CCPLEX_RAS_NODE_LIST(DEFINE_ONE_RAS_NODE)
+
+/* Instantiate RAS node groups */
+static struct ras_aux_data per_core_ras_group[] = {
+	PER_CORE_RAS_GROUP_NODES
+};
+
+static struct ras_aux_data per_cluster_ras_group[] = {
+	PER_CLUSTER_RAS_GROUP_NODES
+};
+
+static struct ras_aux_data scf_l3_ras_group[] = {
+	SCF_L3_BANK_RAS_GROUP_NODES
+};
+
+static struct ras_aux_data ccplex_ras_group[] = {
+    CCPLEX_RAS_GROUP_NODES
+};
+
+/*
+ * We have same probe and handler for each error record group, use a macro to
+ * simply the record definition.
+ */
+#define ADD_ONE_ERR_GROUP(errselr_start, group) \
+	ERR_RECORD_SYSREG_V1((errselr_start), (uint32_t)ARRAY_SIZE((group)), \
+			&tegra194_ras_record_probe, \
+			&tegra194_ras_record_handler, (group))
+
+/* RAS error record group information */
+static struct err_record_info carmel_ras_records[] = {
+	/*
+	 * Per core ras error records
+	 * ERRSELR starts from 0*256 + Logical_CPU_ID*16 + 0 to
+	 * 0*256 + Logical_CPU_ID*16 + 5 for each group.
+	 * 8 cores/groups, 6 * 8 nodes in total.
+	 */
+	ADD_ONE_ERR_GROUP(0x000, per_core_ras_group),
+	ADD_ONE_ERR_GROUP(0x010, per_core_ras_group),
+	ADD_ONE_ERR_GROUP(0x020, per_core_ras_group),
+	ADD_ONE_ERR_GROUP(0x030, per_core_ras_group),
+	ADD_ONE_ERR_GROUP(0x040, per_core_ras_group),
+	ADD_ONE_ERR_GROUP(0x050, per_core_ras_group),
+	ADD_ONE_ERR_GROUP(0x060, per_core_ras_group),
+	ADD_ONE_ERR_GROUP(0x070, per_core_ras_group),
+
+	/*
+	 * Per cluster ras error records
+	 * ERRSELR starts from 2*256 + Logical_Cluster_ID*16 + 0 to
+	 * 2*256 + Logical_Cluster_ID*16 + 3.
+	 * 4 clusters/groups, 3 * 4 nodes in total.
+	 */
+	ADD_ONE_ERR_GROUP(0x200, per_cluster_ras_group),
+	ADD_ONE_ERR_GROUP(0x210, per_cluster_ras_group),
+	ADD_ONE_ERR_GROUP(0x220, per_cluster_ras_group),
+	ADD_ONE_ERR_GROUP(0x230, per_cluster_ras_group),
+
+	/*
+	 * SCF L3_Bank ras error records
+	 * ERRSELR: 3*256 + L3_Bank_ID, L3_Bank_ID: 0-3
+	 * 1 groups, 4 nodes in total.
+	 */
+	ADD_ONE_ERR_GROUP(0x300, scf_l3_ras_group),
+
+	/*
+	 * CCPLEX ras error records
+	 * ERRSELR: 4*256 + Unit_ID, Unit_ID: 0 - 4
+	 * 1 groups, 5 nodes in total.
+	 */
+	ADD_ONE_ERR_GROUP(0x400, ccplex_ras_group),
+};
+
+REGISTER_ERR_RECORD_INFO(carmel_ras_records);
+
+/* dummy RAS interrupt */
+static struct ras_interrupt carmel_ras_interrupts[] = {};
+REGISTER_RAS_INTERRUPTS(carmel_ras_interrupts);
+
+/*******************************************************************************
+ * RAS handler for the platform
+ ******************************************************************************/
+void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
+		void *handle, uint64_t flags)
+{
+#if RAS_EXTENSION
+	tegra194_ea_handler(ea_reason, syndrome, cookie, handle, flags);
+#else
+	ERROR("Unhandled External Abort received on 0x%llx at EL3!\n",
+			read_mpidr_el1());
+	ERROR(" exception reason=%u syndrome=0x%lx\n", ea_reason, syndrome);
+	panic();
+#endif
+}
diff --git a/plat/nvidia/tegra/soc/t194/plat_setup.c b/plat/nvidia/tegra/soc/t194/plat_setup.c
index f90a69e..399aebb 100644
--- a/plat/nvidia/tegra/soc/t194/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t194/plat_setup.c
@@ -208,6 +208,11 @@
 	/* sanity check MCE firmware compatibility */
 	mce_verify_firmware_version();
 
+#if RAS_EXTENSION
+	/* Enable Uncorrectable RAS error */
+	tegra194_ras_enable();
+#endif
+
 	/*
 	 * Program XUSB STREAMIDs
 	 * ======================
@@ -275,6 +280,8 @@
 
 /* Secure IRQs for Tegra194 */
 static const interrupt_prop_t tegra194_interrupt_props[] = {
+	INTR_PROP_DESC(TEGRA_SDEI_SGI_PRIVATE, PLAT_SDEI_CRITICAL_PRI,
+			GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
 	INTR_PROP_DESC(TEGRA194_TOP_WDT_IRQ, PLAT_TEGRA_WDT_PRIO,
 			GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
 	INTR_PROP_DESC(TEGRA194_AON_WDT_IRQ, PLAT_TEGRA_WDT_PRIO,
diff --git a/plat/nvidia/tegra/soc/t194/plat_sip_calls.c b/plat/nvidia/tegra/soc/t194/plat_sip_calls.c
index 884762d..a3f996d 100644
--- a/plat/nvidia/tegra/soc/t194/plat_sip_calls.c
+++ b/plat/nvidia/tegra/soc/t194/plat_sip_calls.c
@@ -12,6 +12,7 @@
 #include <common/debug.h>
 #include <errno.h>
 #include <mce.h>
+#include <mce_private.h>
 #include <memctrl.h>
 #include <common/runtime_svc.h>
 #include <tegra_private.h>
@@ -23,6 +24,7 @@
  * Tegra194 SiP SMCs
  ******************************************************************************/
 #define TEGRA_SIP_GET_SMMU_PER		0xC200FF00U
+#define TEGRA_SIP_CLEAR_RAS_CORRECTED_ERRORS	0xC200FF01U
 
 /*******************************************************************************
  * This function is responsible for handling all T194 SiP calls
@@ -69,6 +71,15 @@
 
 		break;
 
+#if RAS_EXTENSION
+	case TEGRA_SIP_CLEAR_RAS_CORRECTED_ERRORS:
+		/* clear all RAS error records for corrected errors at first. */
+		tegra194_ras_corrected_err_clear();
+		/* clear HSM corrected error status. */
+		mce_clear_hsm_corr_status();
+		break;
+#endif
+
 	default:
 		ret = -ENOTSUP;
 		break;
diff --git a/plat/nvidia/tegra/soc/t194/platform_t194.mk b/plat/nvidia/tegra/soc/t194/platform_t194.mk
index c02128c..d7d15f5 100644
--- a/plat/nvidia/tegra/soc/t194/platform_t194.mk
+++ b/plat/nvidia/tegra/soc/t194/platform_t194.mk
@@ -30,6 +30,10 @@
 MAX_MMAP_REGIONS			:= 30
 $(eval $(call add_define,MAX_MMAP_REGIONS))
 
+# enable RAS handling
+HANDLE_EA_EL3_FIRST			:= 1
+RAS_EXTENSION				:= 1
+
 # platform files
 PLAT_INCLUDES		+=	-Iplat/nvidia/tegra/include/t194 \
 				-I${SOC_DIR}/drivers/include
@@ -56,3 +60,10 @@
 ifeq (${ENABLE_CONSOLE_SPE},1)
 BL31_SOURCES		+=	${COMMON_DIR}/drivers/spe/shared_console.S
 endif
+
+# RAS sources
+ifeq (${RAS_EXTENSION},1)
+BL31_SOURCES		+=	lib/extensions/ras/std_err_record.c		\
+				lib/extensions/ras/ras_common.c			\
+				${SOC_DIR}/plat_ras.c
+endif
diff --git a/plat/nvidia/tegra/soc/t210/plat_setup.c b/plat/nvidia/tegra/soc/t210/plat_setup.c
index 930eeac..f2b267b 100644
--- a/plat/nvidia/tegra/soc/t210/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t210/plat_setup.c
@@ -179,6 +179,8 @@
 
 /* Secure IRQs for Tegra186 */
 static const interrupt_prop_t tegra210_interrupt_props[] = {
+	INTR_PROP_DESC(TEGRA_SDEI_SGI_PRIVATE, PLAT_SDEI_CRITICAL_PRI,
+			GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
 	INTR_PROP_DESC(TEGRA210_TIMER1_IRQ, PLAT_TEGRA_WDT_PRIO,
 			GICV2_INTR_GROUP0, GIC_INTR_CFG_EDGE),
 	INTR_PROP_DESC(TEGRA210_WDT_CPU_LEGACY_FIQ, PLAT_TEGRA_WDT_PRIO,
diff --git a/plat/qemu/qemu/platform.mk b/plat/qemu/qemu/platform.mk
index 1bf4e08..9441437 100644
--- a/plat/qemu/qemu/platform.mk
+++ b/plat/qemu/qemu/platform.mk
@@ -59,18 +59,20 @@
     AUTH_SOURCES	:=	drivers/auth/auth_mod.c			\
 				drivers/auth/crypto_mod.c		\
 				drivers/auth/img_parser_mod.c		\
-				drivers/auth/tbbr/tbbr_cot.c
+				drivers/auth/tbbr/tbbr_cot_common.c
 
     BL1_SOURCES		+=	${AUTH_SOURCES}				\
 				bl1/tbbr/tbbr_img_desc.c		\
 				plat/common/tbbr/plat_tbbr.c		\
 				${PLAT_QEMU_COMMON_PATH}/qemu_trusted_boot.c	     	\
-				$(PLAT_QEMU_COMMON_PATH)/qemu_rotpk.S
+				$(PLAT_QEMU_COMMON_PATH)/qemu_rotpk.S	\
+				drivers/auth/tbbr/tbbr_cot_bl1.c
 
     BL2_SOURCES		+=	${AUTH_SOURCES}				\
 				plat/common/tbbr/plat_tbbr.c		\
 				${PLAT_QEMU_COMMON_PATH}/qemu_trusted_boot.c	     	\
-				$(PLAT_QEMU_COMMON_PATH)/qemu_rotpk.S
+				$(PLAT_QEMU_COMMON_PATH)/qemu_rotpk.S	\
+				drivers/auth/tbbr/tbbr_cot_bl2.c
 
     ROT_KEY             = $(BUILD_PLAT)/rot_key.pem
     ROTPK_HASH          = $(BUILD_PLAT)/rotpk_sha256.bin
diff --git a/plat/qemu/qemu_sbsa/include/platform_def.h b/plat/qemu/qemu_sbsa/include/platform_def.h
index f44b9f6..d0a56cf 100644
--- a/plat/qemu/qemu_sbsa/include/platform_def.h
+++ b/plat/qemu/qemu_sbsa/include/platform_def.h
@@ -233,7 +233,7 @@
  * DT related constants
  */
 #define PLAT_QEMU_DT_BASE		NS_DRAM0_BASE
-#define PLAT_QEMU_DT_MAX_SIZE		0x10000
+#define PLAT_QEMU_DT_MAX_SIZE		0x100000
 
 /*
  * System counter
diff --git a/plat/rockchip/common/params_setup.c b/plat/rockchip/common/params_setup.c
index b2fd201..2ff81ed 100644
--- a/plat/rockchip/common/params_setup.c
+++ b/plat/rockchip/common/params_setup.c
@@ -37,7 +37,8 @@
 static uint32_t rk_uart_base = PLAT_RK_UART_BASE;
 static uint32_t rk_uart_baudrate = PLAT_RK_UART_BAUDRATE;
 static uint32_t rk_uart_clock = PLAT_RK_UART_CLOCK;
-static uint8_t fdt_buffer[0x10000];
+#define FDT_BUFFER_SIZE 0x20000
+static uint8_t fdt_buffer[FDT_BUFFER_SIZE];
 
 void *plat_get_fdt(void)
 {
@@ -136,7 +137,7 @@
 	void *fdt = plat_get_fdt();
 	int ret;
 
-	ret = fdt_open_into((void *)param_from_bl2, fdt, 0x10000);
+	ret = fdt_open_into((void *)param_from_bl2, fdt, FDT_BUFFER_SIZE);
 	if (ret < 0)
 		return ret;
 
diff --git a/plat/rockchip/rk3368/include/platform_def.h b/plat/rockchip/rk3368/include/platform_def.h
index 12115b4..519a025 100644
--- a/plat/rockchip/rk3368/include/platform_def.h
+++ b/plat/rockchip/rk3368/include/platform_def.h
@@ -48,7 +48,7 @@
 					 PLATFORM_CLUSTER_COUNT +	\
 					 PLATFORM_CORE_COUNT)
 
-#define PLAT_RK_CLST_TO_CPUID_SHIFT	8
+#define PLAT_RK_CLST_TO_CPUID_SHIFT	6
 
 #define PLAT_MAX_PWR_LVL		MPIDR_AFFLVL2
 
@@ -86,7 +86,7 @@
 #define PLAT_VIRT_ADDR_SPACE_SIZE   (1ULL << 32)
 #define PLAT_PHY_ADDR_SPACE_SIZE    (1ULL << 32)
 #define MAX_XLAT_TABLES		8
-#define MAX_MMAP_REGIONS	16
+#define MAX_MMAP_REGIONS	20
 
 /*******************************************************************************
  * Declarations and constants to access the mailboxes safely. Each mailbox is
diff --git a/plat/rpi/rpi3/platform.mk b/plat/rpi/rpi3/platform.mk
index bcfc34e..4d627b8 100644
--- a/plat/rpi/rpi3/platform.mk
+++ b/plat/rpi/rpi3/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
 #
@@ -185,18 +185,20 @@
     AUTH_SOURCES	:=	drivers/auth/auth_mod.c			\
 				drivers/auth/crypto_mod.c		\
 				drivers/auth/img_parser_mod.c		\
-				drivers/auth/tbbr/tbbr_cot.c
+				drivers/auth/tbbr/tbbr_cot_common.c
 
     BL1_SOURCES		+=	${AUTH_SOURCES}				\
 				bl1/tbbr/tbbr_img_desc.c		\
 				plat/common/tbbr/plat_tbbr.c		\
 				plat/rpi/common/rpi3_trusted_boot.c    	\
-				plat/rpi/common/rpi3_rotpk.S
+				plat/rpi/common/rpi3_rotpk.S		\
+				drivers/auth/tbbr/tbbr_cot_bl1.c
 
     BL2_SOURCES		+=	${AUTH_SOURCES}				\
 				plat/common/tbbr/plat_tbbr.c		\
 				plat/rpi/common/rpi3_trusted_boot.c    	\
-				plat/rpi/common/rpi3_rotpk.S
+				plat/rpi/common/rpi3_rotpk.S		\
+				drivers/auth/tbbr/tbbr_cot_bl2.c
 
     ROT_KEY             = $(BUILD_PLAT)/rot_key.pem
     ROTPK_HASH          = $(BUILD_PLAT)/rotpk_sha256.bin
diff --git a/plat/rpi/rpi4/rpi4_bl31_setup.c b/plat/rpi/rpi4/rpi4_bl31_setup.c
index 0a49d81..cfacd1f 100644
--- a/plat/rpi/rpi4/rpi4_bl31_setup.c
+++ b/plat/rpi/rpi4/rpi4_bl31_setup.c
@@ -17,6 +17,7 @@
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #include <plat/common/platform.h>
 #include <common/fdt_fixup.h>
+#include <common/fdt_wrappers.h>
 #include <libfdt.h>
 
 #include <drivers/arm/gicv2.h>
@@ -200,13 +201,6 @@
 	enable_mmu_el3(0);
 }
 
-static uint32_t dtb_size(const void *dtb)
-{
-	const uint32_t *dtb_header = dtb;
-
-	return fdt32_to_cpu(dtb_header[1]);
-}
-
 static void rpi4_prepare_dtb(void)
 {
 	void *dtb = (void *)rpi4_get_dtb_address();
@@ -250,7 +244,7 @@
 	if (ret < 0)
 		ERROR("Failed to pack Device Tree at %p: error %d\n", dtb, ret);
 
-	clean_dcache_range((uintptr_t)dtb, dtb_size(dtb));
+	clean_dcache_range((uintptr_t)dtb, fdt_blob_size(dtb));
 	INFO("Changed device tree to advertise PSCI.\n");
 }
 
diff --git a/plat/socionext/synquacer/include/plat.ld.S b/plat/socionext/synquacer/include/plat.ld.S
index a06fe2a..af7a172 100644
--- a/plat/socionext/synquacer/include/plat.ld.S
+++ b/plat/socionext/synquacer/include/plat.ld.S
@@ -25,7 +25,6 @@
 	 */
 	sp_xlat_table (NOLOAD) : ALIGN(PAGE_SIZE) {
 		*(sp_xlat_table)
-		*(.bss.sp_base_xlat_table)
 	} >SP_DRAM
 }
 
diff --git a/plat/socionext/synquacer/include/platform_def.h b/plat/socionext/synquacer/include/platform_def.h
index b87ac3f..2f8613a 100644
--- a/plat/socionext/synquacer/include/platform_def.h
+++ b/plat/socionext/synquacer/include/platform_def.h
@@ -144,6 +144,7 @@
 #define PLAT_SP_IMAGE_MMAP_REGIONS	30
 #define PLAT_SP_IMAGE_MAX_XLAT_TABLES	20
 #define PLAT_SP_IMAGE_XLAT_SECTION_NAME	"sp_xlat_table"
+#define PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME	"sp_xlat_table"
 
 #define PLAT_SQ_UART1_BASE		PLAT_SQ_BOOT_UART_BASE
 #define PLAT_SQ_UART1_SIZE		ULL(0x1000)
diff --git a/plat/socionext/uniphier/platform.mk b/plat/socionext/uniphier/platform.mk
index 2c0ed92..6edd181 100644
--- a/plat/socionext/uniphier/platform.mk
+++ b/plat/socionext/uniphier/platform.mk
@@ -92,7 +92,8 @@
 BL2_SOURCES		+=	drivers/auth/auth_mod.c			\
 				drivers/auth/crypto_mod.c		\
 				drivers/auth/img_parser_mod.c		\
-				drivers/auth/tbbr/tbbr_cot.c		\
+				drivers/auth/tbbr/tbbr_cot_common.c	\
+				drivers/auth/tbbr/tbbr_cot_bl2.c	\
 				plat/common/tbbr/plat_tbbr.c		\
 				$(PLAT_PATH)/uniphier_rotpk.S		\
 				$(PLAT_PATH)/uniphier_tbbr.c
diff --git a/plat/socionext/uniphier/uniphier_bl2_setup.c b/plat/socionext/uniphier/uniphier_bl2_setup.c
index 679f14d..4524610 100644
--- a/plat/socionext/uniphier/uniphier_bl2_setup.c
+++ b/plat/socionext/uniphier/uniphier_bl2_setup.c
@@ -21,8 +21,8 @@
 
 #include "uniphier.h"
 
-#define UNIPHIER_IMAGE_BUF_OFFSET	0x04300000UL
-#define UNIPHIER_IMAGE_BUF_SIZE		0x00100000UL
+#define UNIPHIER_IMAGE_BUF_OFFSET	0x03800000UL
+#define UNIPHIER_IMAGE_BUF_SIZE		0x00800000UL
 
 static uintptr_t uniphier_mem_base = UNIPHIER_MEM_BASE;
 static unsigned int uniphier_soc = UNIPHIER_SOC_UNKNOWN;
diff --git a/plat/socionext/uniphier/uniphier_image_desc.c b/plat/socionext/uniphier/uniphier_image_desc.c
index 8c232ba..dd62d1e 100644
--- a/plat/socionext/uniphier/uniphier_image_desc.c
+++ b/plat/socionext/uniphier/uniphier_image_desc.c
@@ -14,9 +14,9 @@
 #include "uniphier.h"
 
 #define UNIPHIER_BL33_OFFSET		0x04000000UL
-#define UNIPHIER_BL33_MAX_SIZE		0x00100000UL
+#define UNIPHIER_BL33_MAX_SIZE		0x00800000UL
 
-#define UNIPHIER_SCP_OFFSET		0x04100000UL
+#define UNIPHIER_SCP_OFFSET		0x04800000UL
 #define UNIPHIER_SCP_MAX_SIZE		0x00020000UL
 
 static struct bl_mem_params_node uniphier_image_descs[] = {
diff --git a/plat/socionext/uniphier/uniphier_io_storage.c b/plat/socionext/uniphier/uniphier_io_storage.c
index 77d1eaf..92e15b0 100644
--- a/plat/socionext/uniphier/uniphier_io_storage.c
+++ b/plat/socionext/uniphier/uniphier_io_storage.c
@@ -25,8 +25,8 @@
 
 #define UNIPHIER_OCM_REGION_SIZE	0x00040000ULL
 
-#define UNIPHIER_BLOCK_BUF_OFFSET	0x04200000UL
-#define UNIPHIER_BLOCK_BUF_SIZE		0x00100000UL
+#define UNIPHIER_BLOCK_BUF_OFFSET	0x03000000UL
+#define UNIPHIER_BLOCK_BUF_SIZE		0x00800000UL
 
 static const io_dev_connector_t *uniphier_fip_dev_con;
 static uintptr_t uniphier_fip_dev_handle;
diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h
index 27ddab0..feeb4a7 100644
--- a/plat/st/common/include/stm32mp_common.h
+++ b/plat/st/common/include/stm32mp_common.h
@@ -61,6 +61,9 @@
 unsigned long stm32_get_gpio_bank_clock(unsigned int bank);
 uint32_t stm32_get_gpio_bank_offset(unsigned int bank);
 
+/* Return node offset for target GPIO bank ID @bank or a FDT error code */
+int stm32_get_gpio_bank_pinctrl_node(void *fdt, unsigned int bank);
+
 /* Print CPU information */
 void stm32mp_print_cpuinfo(void);
 
diff --git a/plat/st/common/include/stm32mp_dt.h b/plat/st/common/include/stm32mp_dt.h
index e79551a..44ad820 100644
--- a/plat/st/common/include/stm32mp_dt.h
+++ b/plat/st/common/include/stm32mp_dt.h
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2020, STMicroelectronics - All Rights Reserved
  * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -39,5 +40,6 @@
 uint32_t dt_get_pwr_vdd_voltage(void);
 uintptr_t dt_get_syscfg_base(void);
 const char *dt_get_board_model(void);
+int fdt_get_gpio_bank_pin_count(unsigned int bank);
 
 #endif /* STM32MP_DT_H */
diff --git a/plat/st/common/include/stm32mp_shared_resources.h b/plat/st/common/include/stm32mp_shared_resources.h
new file mode 100644
index 0000000..13f4b13
--- /dev/null
+++ b/plat/st/common/include/stm32mp_shared_resources.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP_SHARED_RESOURCES_H
+#define STM32MP_SHARED_RESOURCES_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef STM32MP_SHARED_RESOURCES
+enum stm32mp_shres;
+
+/* Return true if @clock_id is shared by secure and non-secure worlds */
+bool stm32mp_nsec_can_access_clock(unsigned long clock_id);
+
+/* Return true if and only if @reset_id relates to a non-secure peripheral */
+bool stm32mp_nsec_can_access_reset(unsigned int reset_id);
+
+/* Register a shared resource assigned to the secure world */
+void stm32mp_register_secure_periph(enum stm32mp_shres id);
+
+/* Register a shared resource assigned to the non-secure world */
+void stm32mp_register_non_secure_periph(enum stm32mp_shres id);
+
+/* Register a peripheral as secure or non-secure based on IO base address */
+void stm32mp_register_secure_periph_iomem(uintptr_t base);
+void stm32mp_register_non_secure_periph_iomem(uintptr_t base);
+
+/* Register a GPIO as secure or non-secure based on its bank and pin numbers */
+void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin);
+void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin);
+
+/* Consolidate peripheral states and lock against new peripheral registering */
+void stm32mp_lock_periph_registering(void);
+#else
+static inline void stm32mp_register_secure_periph_iomem(uintptr_t base __unused)
+{
+}
+
+static inline
+void stm32mp_register_non_secure_periph_iomem(uintptr_t base __unused)
+{
+}
+
+static inline void stm32mp_register_secure_gpio(unsigned int bank __unused,
+						unsigned int pin __unused)
+{
+}
+
+static inline void stm32mp_register_non_secure_gpio(unsigned int bank __unused,
+						    unsigned int pin __unused)
+{
+}
+#endif /* STM32MP_SHARED_RESOURCES */
+#endif /* STM32MP_SHARED_RESOURCES_H */
diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c
index 9af1564..48a747c 100644
--- a/plat/st/common/stm32mp_common.c
+++ b/plat/st/common/stm32mp_common.c
@@ -97,28 +97,6 @@
 	return (read_sctlr() & c_m_bits) == c_m_bits;
 }
 
-uintptr_t stm32_get_gpio_bank_base(unsigned int bank)
-{
-	if (bank == GPIO_BANK_Z) {
-		return GPIOZ_BASE;
-	}
-
-	assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K);
-
-	return GPIOA_BASE + (bank * GPIO_BANK_OFFSET);
-}
-
-uint32_t stm32_get_gpio_bank_offset(unsigned int bank)
-{
-	if (bank == GPIO_BANK_Z) {
-		return 0;
-	}
-
-	assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K);
-
-	return bank * GPIO_BANK_OFFSET;
-}
-
 int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer)
 {
 	uint32_t i;
diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c
index 155f784..4b8b2db 100644
--- a/plat/st/common/stm32mp_dt.c
+++ b/plat/st/common/stm32mp_dt.c
@@ -393,3 +393,51 @@
 
 	return (const char *)fdt_getprop(fdt, node, "model", NULL);
 }
+
+/*******************************************************************************
+ * This function gets the pin count for a GPIO bank based from the FDT.
+ * It also checks node consistency.
+ ******************************************************************************/
+int fdt_get_gpio_bank_pin_count(unsigned int bank)
+{
+	int pinctrl_node;
+	int node;
+	uint32_t bank_offset;
+
+	pinctrl_node = stm32_get_gpio_bank_pinctrl_node(fdt, bank);
+	if (pinctrl_node < 0) {
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	bank_offset = stm32_get_gpio_bank_offset(bank);
+
+	fdt_for_each_subnode(node, fdt, pinctrl_node) {
+		const fdt32_t *cuint;
+
+		if (fdt_getprop(fdt, node, "gpio-controller", NULL) == NULL) {
+			continue;
+		}
+
+		cuint = fdt_getprop(fdt, node, "reg", NULL);
+		if (cuint == NULL) {
+			continue;
+		}
+
+		if (fdt32_to_cpu(*cuint) != bank_offset) {
+			continue;
+		}
+
+		if (fdt_get_status(node) == DT_DISABLED) {
+			return 0;
+		}
+
+		cuint = fdt_getprop(fdt, node, "ngpios", NULL);
+		if (cuint == NULL) {
+			return -FDT_ERR_NOTFOUND;
+		}
+
+		return (int)fdt32_to_cpu(*cuint);
+	}
+
+	return 0;
+}
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index 652765c..e09ce63 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -31,6 +31,8 @@
 #include <stm32mp1_context.h>
 #include <stm32mp1_dbgmcu.h>
 
+#define RESET_TIMEOUT_US_1MS		1000U
+
 static console_t console;
 static struct stm32mp_auth_ops stm32mp1_auth_ops;
 
@@ -263,9 +265,18 @@
 
 	stm32mp_clk_enable((unsigned long)dt_uart_info.clock);
 
-	stm32mp_reset_assert((uint32_t)dt_uart_info.reset);
+	if (stm32mp_reset_assert((uint32_t)dt_uart_info.reset,
+				 RESET_TIMEOUT_US_1MS) != 0) {
+		panic();
+	}
+
 	udelay(2);
-	stm32mp_reset_deassert((uint32_t)dt_uart_info.reset);
+
+	if (stm32mp_reset_deassert((uint32_t)dt_uart_info.reset,
+				   RESET_TIMEOUT_US_1MS) != 0) {
+		panic();
+	}
+
 	mdelay(1);
 
 	clk_rate = stm32mp_clk_get_rate((unsigned long)dt_uart_info.clock);
diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h
index 27ba6f7..7076a71 100644
--- a/plat/st/stm32mp1/include/platform_def.h
+++ b/plat/st/stm32mp1/include/platform_def.h
@@ -196,4 +196,11 @@
  ******************************************************************************/
 #define PLAT_PCPU_DATA_SIZE	2
 
+/*******************************************************************************
+ * Number of parallel entry slots in SMT SCMI server entry context. For this
+ * platform, SCMI server is reached through SMC only, hence the number of
+ * entry slots.
+ ******************************************************************************/
+#define PLAT_SMT_ENTRY_COUNT		PLATFORM_CORE_COUNT
+
 #endif /* PLATFORM_DEF_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h
index 2da64ac..b6cb91e 100644
--- a/plat/st/stm32mp1/include/stm32mp1_private.h
+++ b/plat/st/stm32mp1/include/stm32mp1_private.h
@@ -22,4 +22,6 @@
 void stm32mp1_syscfg_disable_io_compensation(void);
 
 uint32_t stm32mp_get_ddr_ns_size(void);
+
+void stm32mp1_init_scmi_server(void);
 #endif /* STM32MP1_PRIVATE_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_shared_resources.h b/plat/st/stm32mp1/include/stm32mp1_shared_resources.h
new file mode 100644
index 0000000..3f6367e
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_shared_resources.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_SHARED_RESOURCES_H
+#define STM32MP1_SHARED_RESOURCES_H
+
+#include <stm32mp_shared_resources.h>
+
+#define STM32MP1_SHRES_GPIOZ(i)		(STM32MP1_SHRES_GPIOZ_0 + (i))
+
+enum stm32mp_shres {
+	STM32MP1_SHRES_CRYP1,
+	STM32MP1_SHRES_GPIOZ_0,
+	STM32MP1_SHRES_GPIOZ_1,
+	STM32MP1_SHRES_GPIOZ_2,
+	STM32MP1_SHRES_GPIOZ_3,
+	STM32MP1_SHRES_GPIOZ_4,
+	STM32MP1_SHRES_GPIOZ_5,
+	STM32MP1_SHRES_GPIOZ_6,
+	STM32MP1_SHRES_GPIOZ_7,
+	STM32MP1_SHRES_HASH1,
+	STM32MP1_SHRES_I2C4,
+	STM32MP1_SHRES_I2C6,
+	STM32MP1_SHRES_IWDG1,
+	STM32MP1_SHRES_MCU,
+	STM32MP1_SHRES_MDMA,
+	STM32MP1_SHRES_PLL3,
+	STM32MP1_SHRES_RNG1,
+	STM32MP1_SHRES_RTC,
+	STM32MP1_SHRES_SPI6,
+	STM32MP1_SHRES_USART1,
+
+	STM32MP1_SHRES_COUNT
+};
+#endif /* STM32MP1_SHARED_RESOURCES_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_smc.h b/plat/st/stm32mp1/include/stm32mp1_smc.h
index b872758..57240bc 100644
--- a/plat/st/stm32mp1/include/stm32mp1_smc.h
+++ b/plat/st/stm32mp1/include/stm32mp1_smc.h
@@ -29,6 +29,16 @@
  */
 #define STM32_SMC_BSEC			0x82001003
 
+/*
+ * STM32_SIP_SMC_SCMI_AGENT0
+ * STM32_SIP_SMC_SCMI_AGENT1
+ * Process SCMI message pending in SCMI shared memory buffer.
+ *
+ * Argument a0: (input) SMCC ID
+ */
+#define STM32_SIP_SMC_SCMI_AGENT0	0x82002000
+#define STM32_SIP_SMC_SCMI_AGENT1	0x82002001
+
 /* SMC function IDs for SiP Service queries */
 #define STM32_SIP_SVC_CALL_COUNT	0x8200ff00
 #define STM32_SIP_SVC_UID		0x8200ff01
@@ -40,7 +50,7 @@
 #define STM32_SIP_SVC_VERSION_MINOR	0x1
 
 /* Number of STM32 SiP Calls implemented */
-#define STM32_COMMON_SIP_NUM_CALLS	4
+#define STM32_COMMON_SIP_NUM_CALLS	3
 
 /* Service for BSEC */
 #define STM32_SMC_READ_SHADOW		0x01
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index b0ba82a..9998236 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -16,6 +16,11 @@
 $(eval $(call assert_boolean,PLAT_XLAT_TABLES_DYNAMIC))
 $(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC))
 
+ifeq ($(AARCH32_SP),sp_min)
+# Disable Neon support: sp_min runtime may conflict with non-secure world
+TF_CFLAGS		+=      -mfloat-abi=soft
+endif
+
 # Not needed for Cortex-A7
 WORKAROUND_CVE_2017_5715:=	0
 
diff --git a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
index 72af9ff..49375a6 100644
--- a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
+++ b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
@@ -9,6 +9,7 @@
 
 #include <common/debug.h>
 #include <common/runtime_svc.h>
+#include <drivers/st/scmi-msg.h>
 #include <lib/psci/psci.h>
 #include <tools_share/uuid.h>
 
@@ -65,6 +66,13 @@
 		ret2_enabled = true;
 		break;
 
+	case STM32_SIP_SMC_SCMI_AGENT0:
+		scmi_smt_fastcall_smc_entry(0);
+		break;
+	case STM32_SIP_SMC_SCMI_AGENT1:
+		scmi_smt_fastcall_smc_entry(1);
+		break;
+
 	default:
 		WARN("Unimplemented STM32MP1 Service Call: 0x%x\n", smc_fid);
 		ret1 = SMC_UNK;
diff --git a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
index 4188cc5..5d7d495 100644
--- a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
+++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
@@ -6,10 +6,15 @@
 
 SP_MIN_WITH_SECURE_FIQ	:=	1
 
-BL32_SOURCES		+=	plat/common/aarch32/platform_mp_stack.S		\
+BL32_CFLAGS		+=	-DSTM32MP_SHARED_RESOURCES
+
+BL32_SOURCES		+=	drivers/st/etzpc/etzpc.c			\
+				plat/common/aarch32/platform_mp_stack.S		\
 				plat/st/stm32mp1/sp_min/sp_min_setup.c		\
 				plat/st/stm32mp1/stm32mp1_pm.c			\
+				plat/st/stm32mp1/stm32mp1_shared_resources.c	\
 				plat/st/stm32mp1/stm32mp1_topology.c
+
 # Generic GIC v2
 BL32_SOURCES		+=	drivers/arm/gic/common/gic_common.c	\
 				drivers/arm/gic/v2/gicv2_helpers.c	\
@@ -20,6 +25,17 @@
 # Generic PSCI
 BL32_SOURCES		+=	plat/common/plat_psci_common.c
 
+# SCMI server drivers
+BL32_SOURCES		+=	drivers/st/scmi-msg/base.c		\
+				drivers/st/scmi-msg/clock.c		\
+				drivers/st/scmi-msg/entry.c		\
+				drivers/st/scmi-msg/reset_domain.c	\
+				drivers/st/scmi-msg/smt.c
+
 # stm32mp1 specific services
 BL32_SOURCES		+=	plat/st/stm32mp1/services/bsec_svc.c		\
-				plat/st/stm32mp1/services/stm32mp1_svc_setup.c
+				plat/st/stm32mp1/services/stm32mp1_svc_setup.c	\
+				plat/st/stm32mp1/stm32mp1_scmi.c
+
+# Arm Archtecture services
+BL32_SOURCES		+=	services/arm_arch_svc/arm_arch_svc_setup.c
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
index 4e74c27..b639fcb 100644
--- a/plat/st/stm32mp1/sp_min/sp_min_setup.c
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
@@ -17,6 +17,7 @@
 #include <drivers/arm/tzc400.h>
 #include <drivers/generic_delay_timer.h>
 #include <drivers/st/bsec.h>
+#include <drivers/st/etzpc.h>
 #include <drivers/st/stm32_console.h>
 #include <drivers/st/stm32_gpio.h>
 #include <drivers/st/stm32_iwdg.h>
@@ -76,6 +77,37 @@
 	return next_image_info;
 }
 
+CASSERT((STM32MP_SEC_SYSRAM_BASE == STM32MP_SYSRAM_BASE) &&
+	((STM32MP_SEC_SYSRAM_BASE + STM32MP_SEC_SYSRAM_SIZE) <=
+	 (STM32MP_SYSRAM_BASE + STM32MP_SYSRAM_SIZE)),
+	assert_secure_sysram_fits_at_begining_of_sysram);
+
+#ifdef STM32MP_NS_SYSRAM_BASE
+CASSERT((STM32MP_NS_SYSRAM_BASE >= STM32MP_SEC_SYSRAM_BASE) &&
+	((STM32MP_NS_SYSRAM_BASE + STM32MP_NS_SYSRAM_SIZE) ==
+	 (STM32MP_SYSRAM_BASE + STM32MP_SYSRAM_SIZE)),
+	assert_non_secure_sysram_fits_at_end_of_sysram);
+
+CASSERT((STM32MP_NS_SYSRAM_BASE & (PAGE_SIZE_4KB - U(1))) == 0U,
+	assert_non_secure_sysram_base_is_4kbyte_aligned);
+
+#define TZMA1_SECURE_RANGE \
+	(((STM32MP_NS_SYSRAM_BASE - STM32MP_SYSRAM_BASE) >> FOUR_KB_SHIFT) - 1U)
+#else
+#define TZMA1_SECURE_RANGE		STM32MP1_ETZPC_TZMA_ALL_SECURE
+#endif /* STM32MP_NS_SYSRAM_BASE */
+#define TZMA0_SECURE_RANGE		STM32MP1_ETZPC_TZMA_ALL_SECURE
+
+static void stm32mp1_etzpc_early_setup(void)
+{
+	if (etzpc_init() != 0) {
+		panic();
+	}
+
+	etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_ROM, TZMA0_SECURE_RANGE);
+	etzpc_configure_tzma(STM32MP1_ETZPC_TZMA_SYSRAM, TZMA1_SECURE_RANGE);
+}
+
 /*******************************************************************************
  * Perform any BL32 specific platform actions.
  ******************************************************************************/
@@ -144,6 +176,8 @@
 #endif
 		console_set_scope(&console, console_flags);
 	}
+
+	stm32mp1_etzpc_early_setup();
 }
 
 /*******************************************************************************
@@ -158,19 +192,13 @@
 
 	stm32mp1_gic_init();
 
-	/* Unlock ETZPC securable peripherals */
-#define STM32MP1_ETZPC_BASE	0x5C007000U
-#define ETZPC_DECPROT0		0x010U
-	mmio_write_32(STM32MP1_ETZPC_BASE + ETZPC_DECPROT0, 0xFFFFFFFF);
-
-	/* Set GPIO bank Z as non secure */
-	for (uint32_t pin = 0U; pin < STM32MP_GPIOZ_PIN_MAX_COUNT; pin++) {
-		set_gpio_secure_cfg(GPIO_BANK_Z, pin, false);
-	}
-
 	if (stm32_iwdg_init() < 0) {
 		panic();
 	}
+
+	stm32mp_lock_periph_registering();
+
+	stm32mp1_init_scmi_server();
 }
 
 void sp_min_plat_arch_setup(void)
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index fc776ae..ea18a30 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -25,6 +25,7 @@
 #include <stm32mp_shres_helpers.h>
 #include <stm32mp1_dbgmcu.h>
 #include <stm32mp1_private.h>
+#include <stm32mp1_shared_resources.h>
 #endif
 
 /*******************************************************************************
@@ -56,6 +57,18 @@
 #define STM32MP_SYSRAM_BASE		U(0x2FFC0000)
 #define STM32MP_SYSRAM_SIZE		U(0x00040000)
 
+#define STM32MP_NS_SYSRAM_SIZE		PAGE_SIZE
+#define STM32MP_NS_SYSRAM_BASE		(STM32MP_SYSRAM_BASE + \
+					 STM32MP_SYSRAM_SIZE - \
+					 STM32MP_NS_SYSRAM_SIZE)
+
+#define STM32MP_SCMI_NS_SHM_BASE	STM32MP_NS_SYSRAM_BASE
+#define STM32MP_SCMI_NS_SHM_SIZE	STM32MP_NS_SYSRAM_SIZE
+
+#define STM32MP_SEC_SYSRAM_BASE		STM32MP_SYSRAM_BASE
+#define STM32MP_SEC_SYSRAM_SIZE		(STM32MP_SYSRAM_SIZE - \
+					 STM32MP_NS_SYSRAM_SIZE)
+
 /* DDR configuration */
 #define STM32MP_DDR_BASE		U(0xC0000000)
 #define STM32MP_DDR_MAX_SIZE		U(0x40000000)	/* Max 1GB */
@@ -81,18 +94,18 @@
 /* 256 Octets reserved for header */
 #define STM32MP_HEADER_SIZE		U(0x00000100)
 
-#define STM32MP_BINARY_BASE		(STM32MP_SYSRAM_BASE +		\
+#define STM32MP_BINARY_BASE		(STM32MP_SEC_SYSRAM_BASE +	\
 					 STM32MP_PARAM_LOAD_SIZE +	\
 					 STM32MP_HEADER_SIZE)
 
-#define STM32MP_BINARY_SIZE		(STM32MP_SYSRAM_SIZE -		\
+#define STM32MP_BINARY_SIZE		(STM32MP_SEC_SYSRAM_SIZE -	\
 					 (STM32MP_PARAM_LOAD_SIZE +	\
 					  STM32MP_HEADER_SIZE))
 
 #ifdef AARCH32_SP_OPTEE
 #define STM32MP_BL32_SIZE		U(0)
 
-#define STM32MP_OPTEE_BASE		STM32MP_SYSRAM_BASE
+#define STM32MP_OPTEE_BASE		STM32MP_SEC_SYSRAM_BASE
 
 #define STM32MP_OPTEE_SIZE		(STM32MP_DTB_BASE -  \
 					 STM32MP_OPTEE_BASE)
@@ -104,8 +117,8 @@
 #endif
 #endif
 
-#define STM32MP_BL32_BASE		(STM32MP_SYSRAM_BASE + \
-					 STM32MP_SYSRAM_SIZE - \
+#define STM32MP_BL32_BASE		(STM32MP_SEC_SYSRAM_BASE + \
+					 STM32MP_SEC_SYSRAM_SIZE - \
 					 STM32MP_BL32_SIZE)
 
 #ifdef AARCH32_SP_OPTEE
@@ -247,6 +260,104 @@
 #define DEBUG_UART_TX_EN		RCC_MP_APB1ENSETR_UART4EN
 
 /*******************************************************************************
+ * STM32MP1 ETZPC
+ ******************************************************************************/
+#define STM32MP1_ETZPC_BASE		U(0x5C007000)
+
+/* ETZPC TZMA IDs */
+#define STM32MP1_ETZPC_TZMA_ROM		U(0)
+#define STM32MP1_ETZPC_TZMA_SYSRAM	U(1)
+
+#define STM32MP1_ETZPC_TZMA_ALL_SECURE	GENMASK_32(9, 0)
+
+/* ETZPC DECPROT IDs */
+#define STM32MP1_ETZPC_STGENC_ID	0
+#define STM32MP1_ETZPC_BKPSRAM_ID	1
+#define STM32MP1_ETZPC_IWDG1_ID		2
+#define STM32MP1_ETZPC_USART1_ID	3
+#define STM32MP1_ETZPC_SPI6_ID		4
+#define STM32MP1_ETZPC_I2C4_ID		5
+#define STM32MP1_ETZPC_RNG1_ID		7
+#define STM32MP1_ETZPC_HASH1_ID		8
+#define STM32MP1_ETZPC_CRYP1_ID		9
+#define STM32MP1_ETZPC_DDRCTRL_ID	10
+#define STM32MP1_ETZPC_DDRPHYC_ID	11
+#define STM32MP1_ETZPC_I2C6_ID		12
+#define STM32MP1_ETZPC_SEC_ID_LIMIT	13
+
+#define STM32MP1_ETZPC_TIM2_ID		16
+#define STM32MP1_ETZPC_TIM3_ID		17
+#define STM32MP1_ETZPC_TIM4_ID		18
+#define STM32MP1_ETZPC_TIM5_ID		19
+#define STM32MP1_ETZPC_TIM6_ID		20
+#define STM32MP1_ETZPC_TIM7_ID		21
+#define STM32MP1_ETZPC_TIM12_ID		22
+#define STM32MP1_ETZPC_TIM13_ID		23
+#define STM32MP1_ETZPC_TIM14_ID		24
+#define STM32MP1_ETZPC_LPTIM1_ID	25
+#define STM32MP1_ETZPC_WWDG1_ID		26
+#define STM32MP1_ETZPC_SPI2_ID		27
+#define STM32MP1_ETZPC_SPI3_ID		28
+#define STM32MP1_ETZPC_SPDIFRX_ID	29
+#define STM32MP1_ETZPC_USART2_ID	30
+#define STM32MP1_ETZPC_USART3_ID	31
+#define STM32MP1_ETZPC_UART4_ID		32
+#define STM32MP1_ETZPC_UART5_ID		33
+#define STM32MP1_ETZPC_I2C1_ID		34
+#define STM32MP1_ETZPC_I2C2_ID		35
+#define STM32MP1_ETZPC_I2C3_ID		36
+#define STM32MP1_ETZPC_I2C5_ID		37
+#define STM32MP1_ETZPC_CEC_ID		38
+#define STM32MP1_ETZPC_DAC_ID		39
+#define STM32MP1_ETZPC_UART7_ID		40
+#define STM32MP1_ETZPC_UART8_ID		41
+#define STM32MP1_ETZPC_MDIOS_ID		44
+#define STM32MP1_ETZPC_TIM1_ID		48
+#define STM32MP1_ETZPC_TIM8_ID		49
+#define STM32MP1_ETZPC_USART6_ID	51
+#define STM32MP1_ETZPC_SPI1_ID		52
+#define STM32MP1_ETZPC_SPI4_ID		53
+#define STM32MP1_ETZPC_TIM15_ID		54
+#define STM32MP1_ETZPC_TIM16_ID		55
+#define STM32MP1_ETZPC_TIM17_ID		56
+#define STM32MP1_ETZPC_SPI5_ID		57
+#define STM32MP1_ETZPC_SAI1_ID		58
+#define STM32MP1_ETZPC_SAI2_ID		59
+#define STM32MP1_ETZPC_SAI3_ID		60
+#define STM32MP1_ETZPC_DFSDM_ID		61
+#define STM32MP1_ETZPC_TT_FDCAN_ID	62
+#define STM32MP1_ETZPC_LPTIM2_ID	64
+#define STM32MP1_ETZPC_LPTIM3_ID	65
+#define STM32MP1_ETZPC_LPTIM4_ID	66
+#define STM32MP1_ETZPC_LPTIM5_ID	67
+#define STM32MP1_ETZPC_SAI4_ID		68
+#define STM32MP1_ETZPC_VREFBUF_ID	69
+#define STM32MP1_ETZPC_DCMI_ID		70
+#define STM32MP1_ETZPC_CRC2_ID		71
+#define STM32MP1_ETZPC_ADC_ID		72
+#define STM32MP1_ETZPC_HASH2_ID		73
+#define STM32MP1_ETZPC_RNG2_ID		74
+#define STM32MP1_ETZPC_CRYP2_ID		75
+#define STM32MP1_ETZPC_SRAM1_ID		80
+#define STM32MP1_ETZPC_SRAM2_ID		81
+#define STM32MP1_ETZPC_SRAM3_ID		82
+#define STM32MP1_ETZPC_SRAM4_ID		83
+#define STM32MP1_ETZPC_RETRAM_ID	84
+#define STM32MP1_ETZPC_OTG_ID		85
+#define STM32MP1_ETZPC_SDMMC3_ID	86
+#define STM32MP1_ETZPC_DLYBSD3_ID	87
+#define STM32MP1_ETZPC_DMA1_ID		88
+#define STM32MP1_ETZPC_DMA2_ID		89
+#define STM32MP1_ETZPC_DMAMUX_ID	90
+#define STM32MP1_ETZPC_FMC_ID		91
+#define STM32MP1_ETZPC_QSPI_ID		92
+#define STM32MP1_ETZPC_DLYBQ_ID		93
+#define STM32MP1_ETZPC_ETH_ID		94
+#define STM32MP1_ETZPC_RSV_ID		95
+
+#define STM32MP_ETZPC_MAX_ID		96
+
+/*******************************************************************************
  * STM32MP1 TZC (TZ400)
  ******************************************************************************/
 #define STM32MP1_TZC_BASE		U(0x5C006000)
@@ -386,14 +497,16 @@
 #define IWDG2_BASE			U(0x5A002000)
 
 /*******************************************************************************
- * STM32MP1 I2C4
+ * Miscellaneous STM32MP1 peripherals base address
  ******************************************************************************/
-#define I2C4_BASE			U(0x5C002000)
-
-/*******************************************************************************
- * STM32MP1 DBGMCU
- ******************************************************************************/
+#define CRYP1_BASE			U(0x54001000)
 #define DBGMCU_BASE			U(0x50081000)
+#define HASH1_BASE			U(0x54002000)
+#define I2C4_BASE			U(0x5C002000)
+#define I2C6_BASE			U(0x5c009000)
+#define RNG1_BASE			U(0x54003000)
+#define RTC_BASE			U(0x5c004000)
+#define SPI6_BASE			U(0x5c001000)
 
 /*******************************************************************************
  * Device Tree defines
diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c
index cf9fa8e..31a9ae7 100644
--- a/plat/st/stm32mp1/stm32mp1_pm.c
+++ b/plat/st/stm32mp1/stm32mp1_pm.c
@@ -10,6 +10,7 @@
 #include <platform_def.h>
 
 #include <arch_helpers.h>
+#include <bl32/sp_min/platform_sp_min.h>
 #include <common/debug.h>
 #include <drivers/arm/gic_common.h>
 #include <drivers/arm/gicv2.h>
@@ -68,9 +69,8 @@
 		return PSCI_E_INVALID_PARAMS;
 	}
 
-	if ((stm32_sec_entrypoint < STM32MP_SYSRAM_BASE) ||
-	    (stm32_sec_entrypoint > (STM32MP_SYSRAM_BASE +
-				     (STM32MP_SYSRAM_SIZE - 1)))) {
+	/* Only one valid entry point */
+	if (stm32_sec_entrypoint != (uintptr_t)&sp_min_warm_entrypoint) {
 		return PSCI_E_INVALID_ADDRESS;
 	}
 
diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c
index ac45195..fd60db2 100644
--- a/plat/st/stm32mp1/stm32mp1_private.c
+++ b/plat/st/stm32mp1/stm32mp1_private.c
@@ -30,12 +30,29 @@
 					 BOARD_ID_REVISION_SHIFT)
 #define BOARD_ID2BOM(_id)		((_id) & BOARD_ID_BOM_MASK)
 
-#define MAP_SRAM	MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \
+#if defined(IMAGE_BL2)
+#define MAP_SEC_SYSRAM	MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \
 					STM32MP_SYSRAM_SIZE, \
 					MT_MEMORY | \
 					MT_RW | \
 					MT_SECURE | \
 					MT_EXECUTE_NEVER)
+#elif defined(IMAGE_BL32)
+#define MAP_SEC_SYSRAM	MAP_REGION_FLAT(STM32MP_SEC_SYSRAM_BASE, \
+					STM32MP_SEC_SYSRAM_SIZE, \
+					MT_MEMORY | \
+					MT_RW | \
+					MT_SECURE | \
+					MT_EXECUTE_NEVER)
+
+/* Non-secure SYSRAM is used a uncached memory for SCMI message transfer */
+#define MAP_NS_SYSRAM	MAP_REGION_FLAT(STM32MP_NS_SYSRAM_BASE, \
+					STM32MP_NS_SYSRAM_SIZE, \
+					MT_DEVICE | \
+					MT_RW | \
+					MT_NS | \
+					MT_EXECUTE_NEVER)
+#endif
 
 #define MAP_DEVICE1	MAP_REGION_FLAT(STM32MP1_DEVICE1_BASE, \
 					STM32MP1_DEVICE1_SIZE, \
@@ -53,7 +70,7 @@
 
 #if defined(IMAGE_BL2)
 static const mmap_region_t stm32mp1_mmap[] = {
-	MAP_SRAM,
+	MAP_SEC_SYSRAM,
 	MAP_DEVICE1,
 	MAP_DEVICE2,
 	{0}
@@ -61,7 +78,8 @@
 #endif
 #if defined(IMAGE_BL32)
 static const mmap_region_t stm32mp1_mmap[] = {
-	MAP_SRAM,
+	MAP_SEC_SYSRAM,
+	MAP_NS_SYSRAM,
 	MAP_DEVICE1,
 	MAP_DEVICE2,
 	{0}
@@ -76,6 +94,28 @@
 	enable_mmu_svc_mon(0);
 }
 
+uintptr_t stm32_get_gpio_bank_base(unsigned int bank)
+{
+	if (bank == GPIO_BANK_Z) {
+		return GPIOZ_BASE;
+	}
+
+	assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K);
+
+	return GPIOA_BASE + (bank * GPIO_BANK_OFFSET);
+}
+
+uint32_t stm32_get_gpio_bank_offset(unsigned int bank)
+{
+	if (bank == GPIO_BANK_Z) {
+		return 0;
+	}
+
+	assert(GPIO_BANK_A == 0 && bank <= GPIO_BANK_K);
+
+	return bank * GPIO_BANK_OFFSET;
+}
+
 unsigned long stm32_get_gpio_bank_clock(unsigned int bank)
 {
 	if (bank == GPIO_BANK_Z) {
@@ -87,6 +127,28 @@
 	return GPIOA + (bank - GPIO_BANK_A);
 }
 
+int stm32_get_gpio_bank_pinctrl_node(void *fdt, unsigned int bank)
+{
+	switch (bank) {
+	case GPIO_BANK_A:
+	case GPIO_BANK_B:
+	case GPIO_BANK_C:
+	case GPIO_BANK_D:
+	case GPIO_BANK_E:
+	case GPIO_BANK_F:
+	case GPIO_BANK_G:
+	case GPIO_BANK_H:
+	case GPIO_BANK_I:
+	case GPIO_BANK_J:
+	case GPIO_BANK_K:
+		return fdt_path_offset(fdt, "/soc/pin-controller");
+	case GPIO_BANK_Z:
+		return fdt_path_offset(fdt, "/soc/pin-controller-z");
+	default:
+		panic();
+	}
+}
+
 static int get_part_number(uint32_t *part_nb)
 {
 	uint32_t part_number;
diff --git a/plat/st/stm32mp1/stm32mp1_scmi.c b/plat/st/stm32mp1/stm32mp1_scmi.c
new file mode 100644
index 0000000..80faf0c
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_scmi.c
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+#include <stdint.h>
+
+#include <platform_def.h>
+
+#include <drivers/st/scmi-msg.h>
+#include <drivers/st/scmi.h>
+#include <drivers/st/stm32mp1_clk.h>
+#include <drivers/st/stm32mp_reset.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/reset/stm32mp1-resets.h>
+
+#define TIMEOUT_US_1MS		1000U
+
+#define SCMI_CLOCK_NAME_SIZE	16U
+#define SCMI_RSTD_NAME_SIZE	16U
+
+/*
+ * struct stm32_scmi_clk - Data for the exposed clock
+ * @clock_id: Clock identifier in RCC clock driver
+ * @name: Clock string ID exposed to agent
+ * @enabled: State of the SCMI clock
+ */
+struct stm32_scmi_clk {
+	unsigned long clock_id;
+	const char *name;
+	bool enabled;
+};
+
+/*
+ * struct stm32_scmi_rstd - Data for the exposed reset controller
+ * @reset_id: Reset identifier in RCC reset driver
+ * @name: Reset string ID exposed to agent
+ */
+struct stm32_scmi_rstd {
+	unsigned long reset_id;
+	const char *name;
+};
+
+/* Locate all non-secure SMT message buffers in last page of SYSRAM */
+#define SMT_BUFFER_BASE		STM32MP_SCMI_NS_SHM_BASE
+#define SMT_BUFFER0_BASE	SMT_BUFFER_BASE
+#define SMT_BUFFER1_BASE	(SMT_BUFFER_BASE + 0x200)
+
+CASSERT((STM32MP_SCMI_NS_SHM_BASE + STM32MP_SCMI_NS_SHM_SIZE) >=
+	(SMT_BUFFER1_BASE + SMT_BUF_SLOT_SIZE),
+	assert_scmi_non_secure_shm_fits_scmi_overall_buffer_size);
+
+static struct scmi_msg_channel scmi_channel[] = {
+	[0] = {
+		.shm_addr = SMT_BUFFER0_BASE,
+		.shm_size = SMT_BUF_SLOT_SIZE,
+	},
+	[1] = {
+		.shm_addr = SMT_BUFFER1_BASE,
+		.shm_size = SMT_BUF_SLOT_SIZE,
+	},
+};
+
+struct scmi_msg_channel *plat_scmi_get_channel(unsigned int agent_id)
+{
+	assert(agent_id < ARRAY_SIZE(scmi_channel));
+
+	return &scmi_channel[agent_id];
+}
+
+#define CLOCK_CELL(_scmi_id, _id, _name, _init_enabled) \
+	[_scmi_id] = { \
+		.clock_id = _id, \
+		.name = _name, \
+		.enabled = _init_enabled, \
+	}
+
+static struct stm32_scmi_clk stm32_scmi0_clock[] = {
+	CLOCK_CELL(CK_SCMI0_HSE, CK_HSE, "ck_hse", true),
+	CLOCK_CELL(CK_SCMI0_HSI, CK_HSI, "ck_hsi", true),
+	CLOCK_CELL(CK_SCMI0_CSI, CK_CSI, "ck_csi", true),
+	CLOCK_CELL(CK_SCMI0_LSE, CK_LSE, "ck_lse", true),
+	CLOCK_CELL(CK_SCMI0_LSI, CK_LSI, "ck_lsi", true),
+	CLOCK_CELL(CK_SCMI0_PLL2_Q, PLL2_Q, "pll2_q", true),
+	CLOCK_CELL(CK_SCMI0_PLL2_R, PLL2_R, "pll2_r", true),
+	CLOCK_CELL(CK_SCMI0_MPU, CK_MPU, "ck_mpu", true),
+	CLOCK_CELL(CK_SCMI0_AXI, CK_AXI, "ck_axi", true),
+	CLOCK_CELL(CK_SCMI0_BSEC, BSEC, "bsec", true),
+	CLOCK_CELL(CK_SCMI0_CRYP1, CRYP1, "cryp1", false),
+	CLOCK_CELL(CK_SCMI0_GPIOZ, GPIOZ, "gpioz", false),
+	CLOCK_CELL(CK_SCMI0_HASH1, HASH1, "hash1", false),
+	CLOCK_CELL(CK_SCMI0_I2C4, I2C4_K, "i2c4_k", false),
+	CLOCK_CELL(CK_SCMI0_I2C6, I2C6_K, "i2c6_k", false),
+	CLOCK_CELL(CK_SCMI0_IWDG1, IWDG1, "iwdg1", false),
+	CLOCK_CELL(CK_SCMI0_RNG1, RNG1_K, "rng1_k", true),
+	CLOCK_CELL(CK_SCMI0_RTC, RTC, "ck_rtc", true),
+	CLOCK_CELL(CK_SCMI0_RTCAPB, RTCAPB, "rtcapb", true),
+	CLOCK_CELL(CK_SCMI0_SPI6, SPI6_K, "spi6_k", false),
+	CLOCK_CELL(CK_SCMI0_USART1, USART1_K, "usart1_k", false),
+};
+
+static struct stm32_scmi_clk stm32_scmi1_clock[] = {
+	CLOCK_CELL(CK_SCMI1_PLL3_Q, PLL3_Q, "pll3_q", true),
+	CLOCK_CELL(CK_SCMI1_PLL3_R, PLL3_R, "pll3_r", true),
+	CLOCK_CELL(CK_SCMI1_MCU, CK_MCU, "ck_mcu", false),
+};
+
+#define RESET_CELL(_scmi_id, _id, _name) \
+	[_scmi_id] = { \
+		.reset_id = _id, \
+		.name = _name, \
+	}
+
+static struct stm32_scmi_rstd stm32_scmi0_reset_domain[] = {
+	RESET_CELL(RST_SCMI0_SPI6, SPI6_R, "spi6"),
+	RESET_CELL(RST_SCMI0_I2C4, I2C4_R, "i2c4"),
+	RESET_CELL(RST_SCMI0_I2C6, I2C6_R, "i2c6"),
+	RESET_CELL(RST_SCMI0_USART1, USART1_R, "usart1"),
+	RESET_CELL(RST_SCMI0_STGEN, STGEN_R, "stgen"),
+	RESET_CELL(RST_SCMI0_GPIOZ, GPIOZ_R, "gpioz"),
+	RESET_CELL(RST_SCMI0_CRYP1, CRYP1_R, "cryp1"),
+	RESET_CELL(RST_SCMI0_HASH1, HASH1_R, "hash1"),
+	RESET_CELL(RST_SCMI0_RNG1, RNG1_R, "rng1"),
+	RESET_CELL(RST_SCMI0_MDMA, MDMA_R, "mdma"),
+	RESET_CELL(RST_SCMI0_MCU, MCU_R, "mcu"),
+};
+
+struct scmi_agent_resources {
+	struct stm32_scmi_clk *clock;
+	size_t clock_count;
+	struct stm32_scmi_rstd *rstd;
+	size_t rstd_count;
+};
+
+static const struct scmi_agent_resources agent_resources[] = {
+	[0] = {
+		.clock = stm32_scmi0_clock,
+		.clock_count = ARRAY_SIZE(stm32_scmi0_clock),
+		.rstd = stm32_scmi0_reset_domain,
+		.rstd_count = ARRAY_SIZE(stm32_scmi0_reset_domain),
+	},
+	[1] = {
+		.clock = stm32_scmi1_clock,
+		.clock_count = ARRAY_SIZE(stm32_scmi1_clock),
+	},
+};
+
+static const struct scmi_agent_resources *find_resource(unsigned int agent_id)
+{
+	assert(agent_id < ARRAY_SIZE(agent_resources));
+
+	return &agent_resources[agent_id];
+}
+
+#if ENABLE_ASSERTIONS
+static size_t plat_scmi_protocol_count_paranoid(void)
+{
+	unsigned int n = 0U;
+	unsigned int count = 0U;
+
+	for (n = 0U; n < ARRAY_SIZE(agent_resources); n++) {
+		if (agent_resources[n].clock_count) {
+			count++;
+			break;
+		}
+	}
+
+	for (n = 0U; n < ARRAY_SIZE(agent_resources); n++) {
+		if (agent_resources[n].rstd_count) {
+			count++;
+			break;
+		}
+	}
+
+	return count;
+}
+#endif
+
+static const char vendor[] = "ST";
+static const char sub_vendor[] = "";
+
+const char *plat_scmi_vendor_name(void)
+{
+	return vendor;
+}
+
+const char *plat_scmi_sub_vendor_name(void)
+{
+	return sub_vendor;
+}
+
+/* Currently supporting Clocks and Reset Domains */
+static const uint8_t plat_protocol_list[] = {
+	SCMI_PROTOCOL_ID_CLOCK,
+	SCMI_PROTOCOL_ID_RESET_DOMAIN,
+	0U /* Null termination */
+};
+
+size_t plat_scmi_protocol_count(void)
+{
+	const size_t count = ARRAY_SIZE(plat_protocol_list) - 1U;
+
+	assert(count == plat_scmi_protocol_count_paranoid());
+
+	return count;
+}
+
+const uint8_t *plat_scmi_protocol_list(unsigned int agent_id __unused)
+{
+	assert(plat_scmi_protocol_count_paranoid() ==
+	       (ARRAY_SIZE(plat_protocol_list) - 1U));
+
+	return plat_protocol_list;
+}
+
+/*
+ * Platform SCMI clocks
+ */
+static struct stm32_scmi_clk *find_clock(unsigned int agent_id,
+					 unsigned int scmi_id)
+{
+	const struct scmi_agent_resources *resource = find_resource(agent_id);
+	size_t n = 0U;
+
+	if (resource != NULL) {
+		for (n = 0U; n < resource->clock_count; n++) {
+			if (n == scmi_id) {
+				return &resource->clock[n];
+			}
+		}
+	}
+
+	return NULL;
+}
+
+size_t plat_scmi_clock_count(unsigned int agent_id)
+{
+	const struct scmi_agent_resources *resource = find_resource(agent_id);
+
+	if (resource == NULL) {
+		return 0U;
+	}
+
+	return resource->clock_count;
+}
+
+const char *plat_scmi_clock_get_name(unsigned int agent_id,
+				     unsigned int scmi_id)
+{
+	struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+	if ((clock == NULL) ||
+	    !stm32mp_nsec_can_access_clock(clock->clock_id)) {
+		return NULL;
+	}
+
+	return clock->name;
+}
+
+int32_t plat_scmi_clock_rates_array(unsigned int agent_id, unsigned int scmi_id,
+				    unsigned long *array, size_t *nb_elts)
+{
+	struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+	if (clock == NULL) {
+		return SCMI_NOT_FOUND;
+	}
+
+	if (!stm32mp_nsec_can_access_clock(clock->clock_id)) {
+		return SCMI_DENIED;
+	}
+
+	if (array == NULL) {
+		*nb_elts = 1U;
+	} else if (*nb_elts == 1U) {
+		*array = stm32mp_clk_get_rate(clock->clock_id);
+	} else {
+		return SCMI_GENERIC_ERROR;
+	}
+
+	return SCMI_SUCCESS;
+}
+
+unsigned long plat_scmi_clock_get_rate(unsigned int agent_id,
+				       unsigned int scmi_id)
+{
+	struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+	if ((clock == NULL) ||
+	    !stm32mp_nsec_can_access_clock(clock->clock_id)) {
+		return 0U;
+	}
+
+	return stm32mp_clk_get_rate(clock->clock_id);
+}
+
+int32_t plat_scmi_clock_get_state(unsigned int agent_id, unsigned int scmi_id)
+{
+	struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+	if ((clock == NULL) ||
+	    !stm32mp_nsec_can_access_clock(clock->clock_id)) {
+		return 0U;
+	}
+
+	return (int32_t)clock->enabled;
+}
+
+int32_t plat_scmi_clock_set_state(unsigned int agent_id, unsigned int scmi_id,
+				  bool enable_not_disable)
+{
+	struct stm32_scmi_clk *clock = find_clock(agent_id, scmi_id);
+
+	if (clock == NULL) {
+		return SCMI_NOT_FOUND;
+	}
+
+	if (!stm32mp_nsec_can_access_clock(clock->clock_id)) {
+		return SCMI_DENIED;
+	}
+
+	if (enable_not_disable) {
+		if (!clock->enabled) {
+			VERBOSE("SCMI clock %u enable\n", scmi_id);
+			stm32mp_clk_enable(clock->clock_id);
+			clock->enabled = true;
+		}
+	} else {
+		if (clock->enabled) {
+			VERBOSE("SCMI clock %u disable\n", scmi_id);
+			stm32mp_clk_disable(clock->clock_id);
+			clock->enabled = false;
+		}
+	}
+
+	return SCMI_SUCCESS;
+}
+
+/*
+ * Platform SCMI reset domains
+ */
+static struct stm32_scmi_rstd *find_rstd(unsigned int agent_id,
+					 unsigned int scmi_id)
+{
+	const struct scmi_agent_resources *resource = find_resource(agent_id);
+	size_t n;
+
+	if (resource != NULL) {
+		for (n = 0U; n < resource->rstd_count; n++) {
+			if (n == scmi_id) {
+				return &resource->rstd[n];
+			}
+		}
+	}
+
+	return NULL;
+}
+
+const char *plat_scmi_rstd_get_name(unsigned int agent_id, unsigned int scmi_id)
+{
+	const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
+
+	if (rstd == NULL) {
+		return NULL;
+	}
+
+	return rstd->name;
+}
+
+size_t plat_scmi_rstd_count(unsigned int agent_id)
+{
+	const struct scmi_agent_resources *resource = find_resource(agent_id);
+
+	if (resource == NULL) {
+		return 0U;
+	}
+
+	return resource->rstd_count;
+}
+
+int32_t plat_scmi_rstd_autonomous(unsigned int agent_id, unsigned int scmi_id,
+				uint32_t state)
+{
+	const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
+
+	if (rstd == NULL) {
+		return SCMI_NOT_FOUND;
+	}
+
+	if (!stm32mp_nsec_can_access_reset(rstd->reset_id)) {
+		return SCMI_DENIED;
+	}
+
+	/* Supports only reset with context loss */
+	if (state != 0U) {
+		return SCMI_NOT_SUPPORTED;
+	}
+
+	VERBOSE("SCMI reset %lu cycle\n", rstd->reset_id);
+
+	if (stm32mp_reset_assert(rstd->reset_id, TIMEOUT_US_1MS)) {
+		return SCMI_HARDWARE_ERROR;
+	}
+
+	if (stm32mp_reset_deassert(rstd->reset_id, TIMEOUT_US_1MS)) {
+		return SCMI_HARDWARE_ERROR;
+	}
+
+	return SCMI_SUCCESS;
+}
+
+int32_t plat_scmi_rstd_set_state(unsigned int agent_id, unsigned int scmi_id,
+				 bool assert_not_deassert)
+{
+	const struct stm32_scmi_rstd *rstd = find_rstd(agent_id, scmi_id);
+
+	if (rstd == NULL) {
+		return SCMI_NOT_FOUND;
+	}
+
+	if (!stm32mp_nsec_can_access_reset(rstd->reset_id)) {
+		return SCMI_DENIED;
+	}
+
+	if (assert_not_deassert) {
+		VERBOSE("SCMI reset %lu set\n", rstd->reset_id);
+		stm32mp_reset_set(rstd->reset_id);
+	} else {
+		VERBOSE("SCMI reset %lu release\n", rstd->reset_id);
+		stm32mp_reset_release(rstd->reset_id);
+	}
+
+	return SCMI_SUCCESS;
+}
+
+/*
+ * Initialize platform SCMI resources
+ */
+void stm32mp1_init_scmi_server(void)
+{
+	size_t i;
+
+	for (i = 0U; i < ARRAY_SIZE(scmi_channel); i++) {
+		scmi_smt_init_agent_channel(&scmi_channel[i]);
+	}
+
+	for (i = 0U; i < ARRAY_SIZE(agent_resources); i++) {
+		const struct scmi_agent_resources *res = &agent_resources[i];
+		size_t j;
+
+		for (j = 0U; j < res->clock_count; j++) {
+			struct stm32_scmi_clk *clk = &res->clock[j];
+
+			if ((clk->name == NULL) ||
+			    (strlen(clk->name) >= SCMI_CLOCK_NAME_SIZE)) {
+				ERROR("Invalid SCMI clock name\n");
+				panic();
+			}
+
+			/* Sync SCMI clocks with their targeted initial state */
+			if (clk->enabled &&
+			    stm32mp_nsec_can_access_clock(clk->clock_id)) {
+				stm32mp_clk_enable(clk->clock_id);
+			}
+		}
+
+		for (j = 0U; j < res->rstd_count; j++) {
+			struct stm32_scmi_rstd *rstd = &res->rstd[j];
+
+			if ((rstd->name == NULL) ||
+			    (strlen(rstd->name) >= SCMI_RSTD_NAME_SIZE)) {
+				ERROR("Invalid SCMI reset domain name\n");
+				panic();
+			}
+		}
+	}
+}
diff --git a/plat/st/stm32mp1/stm32mp1_shared_resources.c b/plat/st/stm32mp1/stm32mp1_shared_resources.c
new file mode 100644
index 0000000..208e34a
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_shared_resources.c
@@ -0,0 +1,597 @@
+/*
+ * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/st/etzpc.h>
+#include <drivers/st/stm32_gpio.h>
+
+#include <stm32mp_shared_resources.h>
+
+/*
+ * Once one starts to get the resource registering state, one cannot register
+ * new resources. This ensures resource state cannot change.
+ */
+static bool registering_locked;
+
+/*
+ * Shared peripherals and resources registration
+ *
+ * Each resource assignation is stored in a table. The state defaults
+ * to PERIPH_UNREGISTERED if the resource is not explicitly assigned.
+ *
+ * Resource driver that as not embedded (a.k.a their related CFG_xxx build
+ * directive is disabled) are assigned to the non-secure world.
+ *
+ * Each pin of the GPIOZ bank can be secure or non-secure.
+ *
+ * It is the platform responsibility the ensure resource assignation
+ * matches the access permission firewalls configuration.
+ */
+enum shres_state {
+	SHRES_UNREGISTERED = 0,
+	SHRES_SECURE,
+	SHRES_NON_SECURE,
+};
+
+/* Force uint8_t array for array of enum shres_state for size considerations */
+static uint8_t shres_state[STM32MP1_SHRES_COUNT];
+
+static const char *shres2str_id_tbl[STM32MP1_SHRES_COUNT] __unused = {
+	[STM32MP1_SHRES_GPIOZ(0)] = "GPIOZ0",
+	[STM32MP1_SHRES_GPIOZ(1)] = "GPIOZ1",
+	[STM32MP1_SHRES_GPIOZ(2)] = "GPIOZ2",
+	[STM32MP1_SHRES_GPIOZ(3)] = "GPIOZ3",
+	[STM32MP1_SHRES_GPIOZ(4)] = "GPIOZ4",
+	[STM32MP1_SHRES_GPIOZ(5)] = "GPIOZ5",
+	[STM32MP1_SHRES_GPIOZ(6)] = "GPIOZ6",
+	[STM32MP1_SHRES_GPIOZ(7)] = "GPIOZ7",
+	[STM32MP1_SHRES_IWDG1] = "IWDG1",
+	[STM32MP1_SHRES_USART1] = "USART1",
+	[STM32MP1_SHRES_SPI6] = "SPI6",
+	[STM32MP1_SHRES_I2C4] = "I2C4",
+	[STM32MP1_SHRES_RNG1] = "RNG1",
+	[STM32MP1_SHRES_HASH1] = "HASH1",
+	[STM32MP1_SHRES_CRYP1] = "CRYP1",
+	[STM32MP1_SHRES_I2C6] = "I2C6",
+	[STM32MP1_SHRES_RTC] = "RTC",
+	[STM32MP1_SHRES_MCU] = "MCU",
+	[STM32MP1_SHRES_MDMA] = "MDMA",
+	[STM32MP1_SHRES_PLL3] = "PLL3",
+};
+
+static const char __unused *shres2str_id(enum stm32mp_shres id)
+{
+	assert(id < ARRAY_SIZE(shres2str_id_tbl));
+
+	return shres2str_id_tbl[id];
+}
+
+static const char __unused *shres2str_state_tbl[] = {
+	[SHRES_UNREGISTERED] = "unregistered",
+	[SHRES_NON_SECURE] = "non-secure",
+	[SHRES_SECURE] = "secure",
+};
+
+static const char __unused *shres2str_state(unsigned int state)
+{
+	assert(state < ARRAY_SIZE(shres2str_state_tbl));
+
+	return shres2str_state_tbl[state];
+}
+
+/* Get resource state: these accesses lock the registering support */
+static void lock_registering(void)
+{
+	registering_locked = true;
+}
+
+static bool periph_is_non_secure(enum stm32mp_shres id)
+{
+	lock_registering();
+
+	return (shres_state[id] == SHRES_NON_SECURE) ||
+	       (shres_state[id] == SHRES_UNREGISTERED);
+}
+
+static bool periph_is_secure(enum stm32mp_shres id)
+{
+	return !periph_is_non_secure(id);
+}
+
+/* GPIOZ pin count is saved in RAM to prevent parsing FDT several times */
+static int8_t gpioz_nbpin = -1;
+
+static unsigned int get_gpio_nbpin(unsigned int bank)
+{
+	if (bank != GPIO_BANK_Z) {
+		int count = fdt_get_gpio_bank_pin_count(bank);
+
+		assert((count >= 0) || (count <= (GPIO_PIN_MAX + 1)));
+
+		return (unsigned int)count;
+	}
+
+	if (gpioz_nbpin < 0) {
+		int count = fdt_get_gpio_bank_pin_count(GPIO_BANK_Z);
+
+		assert((count == 0) || (count == STM32MP_GPIOZ_PIN_MAX_COUNT));
+
+		gpioz_nbpin = count;
+	}
+
+	return (unsigned int)gpioz_nbpin;
+}
+
+static unsigned int get_gpioz_nbpin(void)
+{
+	return get_gpio_nbpin(GPIO_BANK_Z);
+}
+
+static void register_periph(enum stm32mp_shres id, unsigned int state)
+{
+	assert((id < STM32MP1_SHRES_COUNT) &&
+	       ((state == SHRES_SECURE) || (state == SHRES_NON_SECURE)));
+
+	if (registering_locked) {
+		if (shres_state[id] == state) {
+			return;
+		}
+		panic();
+	}
+
+	if ((shres_state[id] != SHRES_UNREGISTERED) &&
+	    (shres_state[id] != state)) {
+		VERBOSE("Cannot change %s from %s to %s\n",
+			shres2str_id(id),
+			shres2str_state(shres_state[id]),
+			shres2str_state(state));
+		panic();
+	}
+
+	if (shres_state[id] == SHRES_UNREGISTERED) {
+		VERBOSE("Register %s as %s\n",
+			shres2str_id(id), shres2str_state(state));
+	}
+
+	if ((id >= STM32MP1_SHRES_GPIOZ(0)) &&
+	    (id <= STM32MP1_SHRES_GPIOZ(7)) &&
+	    ((id - STM32MP1_SHRES_GPIOZ(0)) >= get_gpioz_nbpin())) {
+		ERROR("Invalid GPIO pin %u, %u pin(s) available\n",
+		      id - STM32MP1_SHRES_GPIOZ(0), get_gpioz_nbpin());
+		panic();
+	}
+
+	shres_state[id] = (uint8_t)state;
+
+	/* Explore clock tree to lock dependencies */
+	if (state == SHRES_SECURE) {
+		enum stm32mp_shres clock_res_id;
+
+		switch (id) {
+		case STM32MP1_SHRES_GPIOZ(0):
+		case STM32MP1_SHRES_GPIOZ(1):
+		case STM32MP1_SHRES_GPIOZ(2):
+		case STM32MP1_SHRES_GPIOZ(3):
+		case STM32MP1_SHRES_GPIOZ(4):
+		case STM32MP1_SHRES_GPIOZ(5):
+		case STM32MP1_SHRES_GPIOZ(6):
+		case STM32MP1_SHRES_GPIOZ(7):
+			clock_res_id = GPIOZ;
+			break;
+		case STM32MP1_SHRES_IWDG1:
+			clock_res_id = IWDG1;
+			break;
+		case STM32MP1_SHRES_USART1:
+			clock_res_id = USART1_K;
+			break;
+		case STM32MP1_SHRES_SPI6:
+			clock_res_id = SPI6_K;
+			break;
+		case STM32MP1_SHRES_I2C4:
+			clock_res_id = I2C4_K;
+			break;
+		case STM32MP1_SHRES_RNG1:
+			clock_res_id = RNG1_K;
+			break;
+		case STM32MP1_SHRES_HASH1:
+			clock_res_id = HASH1;
+			break;
+		case STM32MP1_SHRES_CRYP1:
+			clock_res_id = CRYP1;
+			break;
+		case STM32MP1_SHRES_I2C6:
+			clock_res_id = I2C6_K;
+			break;
+		case STM32MP1_SHRES_RTC:
+			clock_res_id = RTC;
+			break;
+		default:
+			/* No clock resource dependency */
+			return;
+		}
+
+		stm32mp1_register_clock_parents_secure(clock_res_id);
+	}
+}
+
+/* Register resource by ID */
+void stm32mp_register_secure_periph(enum stm32mp_shres id)
+{
+	register_periph(id, SHRES_SECURE);
+}
+
+void stm32mp_register_non_secure_periph(enum stm32mp_shres id)
+{
+	register_periph(id, SHRES_NON_SECURE);
+}
+
+static void register_periph_iomem(uintptr_t base, unsigned int state)
+{
+	enum stm32mp_shres id;
+
+	switch (base) {
+	case CRYP1_BASE:
+		id = STM32MP1_SHRES_CRYP1;
+		break;
+	case HASH1_BASE:
+		id = STM32MP1_SHRES_HASH1;
+		break;
+	case I2C4_BASE:
+		id = STM32MP1_SHRES_I2C4;
+		break;
+	case I2C6_BASE:
+		id = STM32MP1_SHRES_I2C6;
+		break;
+	case IWDG1_BASE:
+		id = STM32MP1_SHRES_IWDG1;
+		break;
+	case RNG1_BASE:
+		id = STM32MP1_SHRES_RNG1;
+		break;
+	case RTC_BASE:
+		id = STM32MP1_SHRES_RTC;
+		break;
+	case SPI6_BASE:
+		id = STM32MP1_SHRES_SPI6;
+		break;
+	case USART1_BASE:
+		id = STM32MP1_SHRES_USART1;
+		break;
+
+	case GPIOA_BASE:
+	case GPIOB_BASE:
+	case GPIOC_BASE:
+	case GPIOD_BASE:
+	case GPIOE_BASE:
+	case GPIOF_BASE:
+	case GPIOG_BASE:
+	case GPIOH_BASE:
+	case GPIOI_BASE:
+	case GPIOJ_BASE:
+	case GPIOK_BASE:
+	case USART2_BASE:
+	case USART3_BASE:
+	case UART4_BASE:
+	case UART5_BASE:
+	case USART6_BASE:
+	case UART7_BASE:
+	case UART8_BASE:
+	case IWDG2_BASE:
+		/* Allow drivers to register some non-secure resources */
+		VERBOSE("IO for non-secure resource 0x%x\n",
+			(unsigned int)base);
+		if (state != SHRES_NON_SECURE) {
+			panic();
+		}
+
+		return;
+
+	default:
+		panic();
+	}
+
+	register_periph(id, state);
+}
+
+void stm32mp_register_secure_periph_iomem(uintptr_t base)
+{
+	register_periph_iomem(base, SHRES_SECURE);
+}
+
+void stm32mp_register_non_secure_periph_iomem(uintptr_t base)
+{
+	register_periph_iomem(base, SHRES_NON_SECURE);
+}
+
+void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin)
+{
+	switch (bank) {
+	case GPIO_BANK_Z:
+		register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_SECURE);
+		break;
+	default:
+		ERROR("GPIO bank %u cannot be secured\n", bank);
+		panic();
+	}
+}
+
+void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin)
+{
+	switch (bank) {
+	case GPIO_BANK_Z:
+		register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_NON_SECURE);
+		break;
+	default:
+		break;
+	}
+}
+
+static bool stm32mp_gpio_bank_is_non_secure(unsigned int bank)
+{
+	unsigned int non_secure = 0U;
+	unsigned int i;
+
+	lock_registering();
+
+	if (bank != GPIO_BANK_Z) {
+		return true;
+	}
+
+	for (i = 0U; i < get_gpioz_nbpin(); i++) {
+		if (periph_is_non_secure(STM32MP1_SHRES_GPIOZ(i))) {
+			non_secure++;
+		}
+	}
+
+	return non_secure == get_gpioz_nbpin();
+}
+
+static bool stm32mp_gpio_bank_is_secure(unsigned int bank)
+{
+	unsigned int secure = 0U;
+	unsigned int i;
+
+	lock_registering();
+
+	if (bank != GPIO_BANK_Z) {
+		return false;
+	}
+
+	for (i = 0U; i < get_gpioz_nbpin(); i++) {
+		if (periph_is_secure(STM32MP1_SHRES_GPIOZ(i))) {
+			secure++;
+		}
+	}
+
+	return secure == get_gpioz_nbpin();
+}
+
+bool stm32mp_nsec_can_access_clock(unsigned long clock_id)
+{
+	enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT;
+
+	switch (clock_id) {
+	case CK_CSI:
+	case CK_HSE:
+	case CK_HSE_DIV2:
+	case CK_HSI:
+	case CK_LSE:
+	case CK_LSI:
+	case PLL1_P:
+	case PLL1_Q:
+	case PLL1_R:
+	case PLL2_P:
+	case PLL2_Q:
+	case PLL2_R:
+	case PLL3_P:
+	case PLL3_Q:
+	case PLL3_R:
+	case RTCAPB:
+		return true;
+	case GPIOZ:
+		/* Allow clock access if at least one pin is non-secure */
+		return !stm32mp_gpio_bank_is_secure(GPIO_BANK_Z);
+	case CRYP1:
+		shres_id = STM32MP1_SHRES_CRYP1;
+		break;
+	case HASH1:
+		shres_id = STM32MP1_SHRES_HASH1;
+		break;
+	case I2C4_K:
+		shres_id = STM32MP1_SHRES_I2C4;
+		break;
+	case I2C6_K:
+		shres_id = STM32MP1_SHRES_I2C6;
+		break;
+	case IWDG1:
+		shres_id = STM32MP1_SHRES_IWDG1;
+		break;
+	case RNG1_K:
+		shres_id = STM32MP1_SHRES_RNG1;
+		break;
+	case RTC:
+		shres_id = STM32MP1_SHRES_RTC;
+		break;
+	case SPI6_K:
+		shres_id = STM32MP1_SHRES_SPI6;
+		break;
+	case USART1_K:
+		shres_id = STM32MP1_SHRES_USART1;
+		break;
+	default:
+		return false;
+	}
+
+	return periph_is_non_secure(shres_id);
+}
+
+bool stm32mp_nsec_can_access_reset(unsigned int reset_id)
+{
+	enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT;
+
+	switch (reset_id) {
+	case CRYP1_R:
+		shres_id = STM32MP1_SHRES_CRYP1;
+		break;
+	case GPIOZ_R:
+		/* GPIOZ reset mandates all pins are non-secure */
+		return stm32mp_gpio_bank_is_non_secure(GPIO_BANK_Z);
+	case HASH1_R:
+		shres_id = STM32MP1_SHRES_HASH1;
+		break;
+	case I2C4_R:
+		shres_id = STM32MP1_SHRES_I2C4;
+		break;
+	case I2C6_R:
+		shres_id = STM32MP1_SHRES_I2C6;
+		break;
+	case MCU_R:
+		shres_id = STM32MP1_SHRES_MCU;
+		break;
+	case MDMA_R:
+		shres_id = STM32MP1_SHRES_MDMA;
+		break;
+	case RNG1_R:
+		shres_id = STM32MP1_SHRES_RNG1;
+		break;
+	case SPI6_R:
+		shres_id = STM32MP1_SHRES_SPI6;
+		break;
+	case USART1_R:
+		shres_id = STM32MP1_SHRES_USART1;
+		break;
+	default:
+		return false;
+	}
+
+	return periph_is_non_secure(shres_id);
+}
+
+static bool mckprot_protects_periph(enum stm32mp_shres id)
+{
+	switch (id) {
+	case STM32MP1_SHRES_MCU:
+	case STM32MP1_SHRES_PLL3:
+		return true;
+	default:
+		return false;
+	}
+}
+
+/* ETZPC configuration at drivers initialization completion */
+static enum etzpc_decprot_attributes shres2decprot_attr(enum stm32mp_shres id)
+{
+	assert((id < STM32MP1_SHRES_GPIOZ(0)) ||
+	       (id > STM32MP1_SHRES_GPIOZ(7)));
+
+	if (periph_is_non_secure(id)) {
+		return ETZPC_DECPROT_NS_RW;
+	}
+
+	return ETZPC_DECPROT_S_RW;
+}
+
+static void set_etzpc_secure_configuration(void)
+{
+	/* Some system peripherals shall be secure */
+	etzpc_configure_decprot(STM32MP1_ETZPC_STGENC_ID, ETZPC_DECPROT_S_RW);
+	etzpc_configure_decprot(STM32MP1_ETZPC_BKPSRAM_ID, ETZPC_DECPROT_S_RW);
+	etzpc_configure_decprot(STM32MP1_ETZPC_DDRCTRL_ID,
+				ETZPC_DECPROT_NS_R_S_W);
+	etzpc_configure_decprot(STM32MP1_ETZPC_DDRPHYC_ID,
+				ETZPC_DECPROT_NS_R_S_W);
+
+	/* Configure ETZPC with peripheral registering */
+	etzpc_configure_decprot(STM32MP1_ETZPC_CRYP1_ID,
+				shres2decprot_attr(STM32MP1_SHRES_CRYP1));
+	etzpc_configure_decprot(STM32MP1_ETZPC_HASH1_ID,
+				shres2decprot_attr(STM32MP1_SHRES_HASH1));
+	etzpc_configure_decprot(STM32MP1_ETZPC_I2C4_ID,
+				shres2decprot_attr(STM32MP1_SHRES_I2C4));
+	etzpc_configure_decprot(STM32MP1_ETZPC_I2C6_ID,
+				shres2decprot_attr(STM32MP1_SHRES_I2C6));
+	etzpc_configure_decprot(STM32MP1_ETZPC_IWDG1_ID,
+				shres2decprot_attr(STM32MP1_SHRES_IWDG1));
+	etzpc_configure_decprot(STM32MP1_ETZPC_RNG1_ID,
+				shres2decprot_attr(STM32MP1_SHRES_RNG1));
+	etzpc_configure_decprot(STM32MP1_ETZPC_USART1_ID,
+				shres2decprot_attr(STM32MP1_SHRES_USART1));
+	etzpc_configure_decprot(STM32MP1_ETZPC_SPI6_ID,
+				shres2decprot_attr(STM32MP1_SHRES_SPI6));
+}
+
+static void check_rcc_secure_configuration(void)
+{
+	uint32_t n;
+	uint32_t error = 0U;
+	bool mckprot = stm32mp1_rcc_is_mckprot();
+	bool secure = stm32mp1_rcc_is_secure();
+
+	for (n = 0U; n < ARRAY_SIZE(shres_state); n++) {
+		if (shres_state[n] != SHRES_SECURE) {
+			continue;
+		}
+
+		if (!secure || (mckprot_protects_periph(n) && (!mckprot))) {
+			ERROR("RCC %s MCKPROT %s and %s secure\n",
+			      secure ? "secure" : "non-secure",
+			      mckprot ? "set" : "not set",
+			      shres2str_id(n));
+			error++;
+		}
+	}
+
+	if (error != 0U) {
+		panic();
+	}
+}
+
+static void set_gpio_secure_configuration(void)
+{
+	uint32_t pin;
+
+	for (pin = 0U; pin < get_gpioz_nbpin(); pin++) {
+		bool secure_state = periph_is_secure(STM32MP1_SHRES_GPIOZ(pin));
+
+		set_gpio_secure_cfg(GPIO_BANK_Z, pin, secure_state);
+	}
+}
+
+static void print_shared_resources_state(void)
+{
+	unsigned int id;
+
+	for (id = 0U; id < STM32MP1_SHRES_COUNT; id++) {
+		switch (shres_state[id]) {
+		case SHRES_SECURE:
+			INFO("stm32mp1 %s is secure\n", shres2str_id(id));
+			break;
+		case SHRES_NON_SECURE:
+		case SHRES_UNREGISTERED:
+			VERBOSE("stm32mp %s is non-secure\n", shres2str_id(id));
+			break;
+		default:
+			VERBOSE("stm32mp %s is invalid\n", shres2str_id(id));
+			panic();
+		}
+	}
+}
+
+void stm32mp_lock_periph_registering(void)
+{
+	registering_locked = true;
+
+	print_shared_resources_state();
+
+	check_rcc_secure_configuration();
+	set_etzpc_secure_configuration();
+	set_gpio_secure_configuration();
+}
diff --git a/plat/ti/k3/common/k3_psci.c b/plat/ti/k3/common/k3_psci.c
index d6ed766..0500740 100644
--- a/plat/ti/k3/common/k3_psci.c
+++ b/plat/ti/k3/common/k3_psci.c
@@ -203,6 +203,13 @@
 	k3_gic_cpuif_enable();
 }
 
+static void __dead2 k3_system_off(void)
+{
+	ERROR("System Off: operation not handled.\n");
+	while (true)
+		wfi();
+}
+
 static void __dead2 k3_system_reset(void)
 {
 	/* Send the system reset request to system firmware */
@@ -232,6 +239,7 @@
 	.pwr_domain_on = k3_pwr_domain_on,
 	.pwr_domain_off = k3_pwr_domain_off,
 	.pwr_domain_on_finish = k3_pwr_domain_on_finish,
+	.system_off = k3_system_off,
 	.system_reset = k3_system_reset,
 	.validate_power_state = k3_validate_power_state,
 	.validate_ns_entrypoint = k3_validate_ns_entrypoint
diff --git a/plat/ti/k3/common/plat_common.mk b/plat/ti/k3/common/plat_common.mk
index 03d39f1..c00262b 100644
--- a/plat/ti/k3/common/plat_common.mk
+++ b/plat/ti/k3/common/plat_common.mk
@@ -37,6 +37,9 @@
 TI_16550_MDR_QUIRK	:=	1
 $(eval $(call add_define,TI_16550_MDR_QUIRK))
 
+K3_USART		:=	0
+$(eval $(call add_define,K3_USART))
+
 # Allow customizing the UART baud rate
 K3_USART_BAUD		:=	115200
 $(eval $(call add_define,K3_USART_BAUD))
diff --git a/plat/ti/k3/include/platform_def.h b/plat/ti/k3/include/platform_def.h
index 690c68e..98db626 100644
--- a/plat/ti/k3/include/platform_def.h
+++ b/plat/ti/k3/include/platform_def.h
@@ -91,7 +91,7 @@
 
 /* Platform default console definitions */
 #ifndef K3_USART_BASE
-#define K3_USART_BASE 0x02800000
+#define K3_USART_BASE			(0x02800000 + 0x10000 * K3_USART)
 #endif
 
 /* USART has a default size for address space */
diff --git a/plat/ti/k3/platform.mk b/plat/ti/k3/platform.mk
index 65d5cc2..2de21aa 100644
--- a/plat/ti/k3/platform.mk
+++ b/plat/ti/k3/platform.mk
@@ -11,4 +11,4 @@
 include ${PLAT_PATH}/board/${TARGET_BOARD}/board.mk
 
 # modify BUILD_PLAT to point to board specific build directory
-BUILD_PLAT := ${BUILD_BASE}/${PLAT}/${TARGET_BOARD}/${BUILD_TYPE}
+BUILD_PLAT := $(abspath ${BUILD_BASE})/${PLAT}/${TARGET_BOARD}/${BUILD_TYPE}
diff --git a/services/arm_arch_svc/arm_arch_svc_setup.c b/services/arm_arch_svc/arm_arch_svc_setup.c
index 588656d..37bfc62 100644
--- a/services/arm_arch_svc/arm_arch_svc_setup.c
+++ b/services/arm_arch_svc/arm_arch_svc_setup.c
@@ -24,8 +24,9 @@
 	switch (arg1) {
 	case SMCCC_VERSION:
 	case SMCCC_ARCH_FEATURES:
+		return SMC_ARCH_CALL_SUCCESS;
 	case SMCCC_ARCH_SOC_ID:
-		return SMC_OK;
+		return plat_is_smccc_feature_available(arg1);
 #if WORKAROUND_CVE_2017_5715
 	case SMCCC_ARCH_WORKAROUND_1:
 		if (check_wa_cve_2017_5715() == ERRATA_NOT_APPLIES)
diff --git a/services/std_svc/spm_mm/spm_mm_xlat.c b/services/std_svc/spm_mm/spm_mm_xlat.c
index 6c02f07..eae597c 100644
--- a/services/std_svc/spm_mm/spm_mm_xlat.c
+++ b/services/std_svc/spm_mm/spm_mm_xlat.c
@@ -21,13 +21,17 @@
 #ifndef PLAT_SP_IMAGE_XLAT_SECTION_NAME
 #define PLAT_SP_IMAGE_XLAT_SECTION_NAME	"xlat_table"
 #endif
+#ifndef PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME
+#define PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME	".bss"
+#endif
 
 /* Allocate and initialise the translation context for the secure partitions. */
 REGISTER_XLAT_CONTEXT2(sp,
 		       PLAT_SP_IMAGE_MMAP_REGIONS,
 		       PLAT_SP_IMAGE_MAX_XLAT_TABLES,
 		       PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE,
-		       EL1_EL0_REGIME, PLAT_SP_IMAGE_XLAT_SECTION_NAME);
+		       EL1_EL0_REGIME, PLAT_SP_IMAGE_XLAT_SECTION_NAME,
+		       PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME);
 
 /* Lock used for SP_MEMORY_ATTRIBUTES_GET and SP_MEMORY_ATTRIBUTES_SET */
 static spinlock_t mem_attr_smc_lock;
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
index 501782f..4c2b58d 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -20,7 +20,7 @@
 #include <plat/common/common_def.h>
 #include <plat/common/platform.h>
 #include <platform_def.h>
-#include <services/spci_svc.h>
+#include <services/ffa_svc.h>
 #include <services/spmd_svc.h>
 #include <smccc_helpers.h>
 #include "spmd_private.h"
@@ -56,7 +56,7 @@
  ******************************************************************************/
 static int32_t spmd_init(void);
 static int spmd_spmc_init(void *pm_addr);
-static uint64_t spmd_spci_error_return(void *handle,
+static uint64_t spmd_ffa_error_return(void *handle,
 				       int error_code);
 static uint64_t spmd_smc_forward(uint32_t smc_fid,
 				 bool secure_origin,
@@ -161,14 +161,14 @@
 	 * 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 (%u.%u)\n",
+	if ((spmc_attrs.major_version != FFA_VERSION_MAJOR) ||
+	    (spmc_attrs.minor_version > FFA_VERSION_MINOR)) {
+		WARN("Unsupported FFA version (%u.%u)\n",
 		     spmc_attrs.major_version, spmc_attrs.minor_version);
 		return -EINVAL;
 	}
 
-	VERBOSE("SPCI version (%u.%u)\n", spmc_attrs.major_version,
+	VERBOSE("FFA version (%u.%u)\n", spmc_attrs.major_version,
 	     spmc_attrs.minor_version);
 
 	VERBOSE("SPM Core run time EL%x.\n",
@@ -324,18 +324,18 @@
 }
 
 /*******************************************************************************
- * Return SPCI_ERROR with specified error code
+ * Return FFA_ERROR with specified error code
  ******************************************************************************/
-static uint64_t spmd_spci_error_return(void *handle, int error_code)
+static uint64_t spmd_ffa_error_return(void *handle, int error_code)
 {
-	SMC_RET8(handle, SPCI_ERROR,
-		 SPCI_TARGET_INFO_MBZ, error_code,
-		 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
-		 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ);
+	SMC_RET8(handle, FFA_ERROR,
+		 FFA_TARGET_INFO_MBZ, error_code,
+		 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+		 FFA_PARAM_MBZ, FFA_PARAM_MBZ);
 }
 
 /*******************************************************************************
- * This function handles all SMCs in the range reserved for SPCI. Each call is
+ * This function handles all SMCs in the range reserved for FFA. 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,
@@ -350,6 +350,7 @@
 	spmd_spm_core_context_t *ctx = spmd_get_context();
 	bool secure_origin;
 	int32_t ret;
+	uint32_t input_version;
 
 	/* Determine which security state this SMC originated from */
 	secure_origin = is_caller_secure(flags);
@@ -360,7 +361,7 @@
 	     SMC_GET_GP(handle, CTX_GPREG_X7));
 
 	switch (smc_fid) {
-	case SPCI_ERROR:
+	case FFA_ERROR:
 		/*
 		 * Check if this is the first invocation of this interface on
 		 * this CPU. If so, then indicate that the SPM Core initialised
@@ -374,33 +375,42 @@
 					x1, x2, x3, x4, handle);
 		break; /* not reached */
 
-	case SPCI_VERSION:
+	case FFA_VERSION:
+		input_version = (uint32_t)(0xFFFFFFFF & x1);
 		/*
-		 * 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.
+		 * If caller is secure and SPMC was initialized,
+		 * return FFA_VERSION of SPMD.
+		 * If caller is non secure and SPMC was initialized,
+		 * return SPMC's version.
+		 * Sanity check to "input_version".
 		 */
-		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);
+		if ((input_version & FFA_VERSION_BIT31_MASK) ||
+			(ctx->state == SPMC_STATE_RESET)) {
+			ret = FFA_ERROR_NOT_SUPPORTED;
+		} else if (!secure_origin) {
+			ret = MAKE_FFA_VERSION(spmc_attrs.major_version, spmc_attrs.minor_version);
+		} else {
+			ret = MAKE_FFA_VERSION(FFA_VERSION_MAJOR, FFA_VERSION_MINOR);
+		}
+
+		SMC_RET8(handle, ret, FFA_TARGET_INFO_MBZ, FFA_TARGET_INFO_MBZ,
+			 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+			 FFA_PARAM_MBZ, FFA_PARAM_MBZ);
 		break; /* not reached */
 
-	case SPCI_FEATURES:
+	case FFA_FEATURES:
 		/*
 		 * This is an optional interface. Do the minimal checks and
 		 * forward to SPM Core which will handle it if implemented.
 		 */
 
 		/*
-		 * Check if x1 holds a valid SPCI fid. This is an
+		 * Check if x1 holds a valid FFA fid. This is an
 		 * optimization.
 		 */
-		if (!is_spci_fid(x1)) {
-			return spmd_spci_error_return(handle,
-						      SPCI_ERROR_NOT_SUPPORTED);
+		if (!is_ffa_fid(x1)) {
+			return spmd_ffa_error_return(handle,
+						      FFA_ERROR_NOT_SUPPORTED);
 		}
 
 		/* Forward SMC from Normal world to the SPM Core */
@@ -411,68 +421,68 @@
 
 		/*
 		 * Return success if call was from secure world i.e. all
-		 * SPCI functions are supported. This is essentially a
+		 * FFA functions are supported. This is essentially a
 		 * nop.
 		 */
-		SMC_RET8(handle, SPCI_SUCCESS_SMC32, x1, x2, x3, x4,
+		SMC_RET8(handle, FFA_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_ID_GET:
+	case FFA_ID_GET:
 		/*
-		 * Returns the ID of the calling SPCI component.
+		 * Returns the ID of the calling FFA component.
 		 */
 		if (!secure_origin) {
-			SMC_RET8(handle, SPCI_SUCCESS_SMC32,
-				 SPCI_TARGET_INFO_MBZ, SPCI_NS_ENDPOINT_ID,
-				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
-				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
-				 SPCI_PARAM_MBZ);
+			SMC_RET8(handle, FFA_SUCCESS_SMC32,
+				 FFA_TARGET_INFO_MBZ, FFA_NS_ENDPOINT_ID,
+				 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+				 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+				 FFA_PARAM_MBZ);
 		}
 
-		SMC_RET8(handle, SPCI_SUCCESS_SMC32,
-			 SPCI_TARGET_INFO_MBZ, spmc_attrs.spmc_id,
-			 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
-			 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
-			 SPCI_PARAM_MBZ);
+		SMC_RET8(handle, FFA_SUCCESS_SMC32,
+			 FFA_TARGET_INFO_MBZ, spmc_attrs.spmc_id,
+			 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+			 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+			 FFA_PARAM_MBZ);
 
 		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:
+	case FFA_RX_RELEASE:
+	case FFA_RXTX_MAP_SMC32:
+	case FFA_RXTX_MAP_SMC64:
+	case FFA_RXTX_UNMAP:
+	case FFA_MSG_RUN:
 		/* This interface must be invoked only by the Normal world */
 		if (secure_origin) {
-			return spmd_spci_error_return(handle,
-						      SPCI_ERROR_NOT_SUPPORTED);
+			return spmd_ffa_error_return(handle,
+						      FFA_ERROR_NOT_SUPPORTED);
 		}
 
 		/* 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:
+	case FFA_PARTITION_INFO_GET:
+	case FFA_MSG_SEND:
+	case FFA_MSG_SEND_DIRECT_REQ_SMC32:
+	case FFA_MSG_SEND_DIRECT_REQ_SMC64:
+	case FFA_MSG_SEND_DIRECT_RESP_SMC32:
+	case FFA_MSG_SEND_DIRECT_RESP_SMC64:
+	case FFA_MEM_DONATE_SMC32:
+	case FFA_MEM_DONATE_SMC64:
+	case FFA_MEM_LEND_SMC32:
+	case FFA_MEM_LEND_SMC64:
+	case FFA_MEM_SHARE_SMC32:
+	case FFA_MEM_SHARE_SMC64:
+	case FFA_MEM_RETRIEVE_REQ_SMC32:
+	case FFA_MEM_RETRIEVE_REQ_SMC64:
+	case FFA_MEM_RETRIEVE_RESP:
+	case FFA_MEM_RELINQUISH:
+	case FFA_MEM_RECLAIM:
+	case FFA_SUCCESS_SMC32:
+	case FFA_SUCCESS_SMC64:
 		/*
 		 * TODO: Assume that no requests originate from EL3 at the
 		 * moment. This will change if a SP service is required in
@@ -484,7 +494,7 @@
 					x1, x2, x3, x4, handle);
 		break; /* not reached */
 
-	case SPCI_MSG_WAIT:
+	case FFA_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
@@ -496,11 +506,11 @@
 
 		/* Fall through to forward the call to the other world */
 
-	case SPCI_MSG_YIELD:
+	case FFA_MSG_YIELD:
 		/* This interface must be invoked only by the Secure world */
 		if (!secure_origin) {
-			return spmd_spci_error_return(handle,
-						      SPCI_ERROR_NOT_SUPPORTED);
+			return spmd_ffa_error_return(handle,
+						      FFA_ERROR_NOT_SUPPORTED);
 		}
 
 		return spmd_smc_forward(smc_fid, secure_origin,
@@ -509,6 +519,6 @@
 
 	default:
 		WARN("SPM: Unsupported call 0x%08x\n", smc_fid);
-		return spmd_spci_error_return(handle, SPCI_ERROR_NOT_SUPPORTED);
+		return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
 	}
 }
diff --git a/services/std_svc/spmd/spmd_private.h b/services/std_svc/spmd/spmd_private.h
index 232031b..4946309 100644
--- a/services/std_svc/spmd/spmd_private.h
+++ b/services/std_svc/spmd/spmd_private.h
@@ -30,7 +30,7 @@
 #define SPMD_C_RT_CTX_ENTRIES		(SPMD_C_RT_CTX_SIZE >> DWORD_SHIFT)
 
 #ifndef __ASSEMBLER__
-#include <services/spci_svc.h>
+#include <services/ffa_svc.h>
 #include <stdint.h>
 
 typedef enum spmc_state {
@@ -49,11 +49,11 @@
 } spmd_spm_core_context_t;
 
 /*
- * Reserve ID for NS physical SPCI Endpoint.
+ * Reserve ID for NS physical FFA Endpoint.
  */
-#define SPCI_NS_ENDPOINT_ID		U(0)
+#define FFA_NS_ENDPOINT_ID		U(0)
 
-/* Mask and shift to check valid secure SPCI Endpoint ID. */
+/* Mask and shift to check valid secure FFA Endpoint ID. */
 #define SPMC_SECURE_ID_MASK		U(1)
 #define SPMC_SECURE_ID_SHIFT		U(15)
 
diff --git a/services/std_svc/std_svc_setup.c b/services/std_svc/std_svc_setup.c
index 895fd29..cdd17bc 100644
--- a/services/std_svc/std_svc_setup.c
+++ b/services/std_svc/std_svc_setup.c
@@ -123,10 +123,10 @@
 
 #if defined(SPD_spmd)
 	/*
-	 * Dispatch SPCI calls to the SPCI SMC handler implemented by the SPM
+	 * Dispatch FFA calls to the FFA SMC handler implemented by the SPM
 	 * dispatcher and return its return value
 	 */
-	if (is_spci_fid(smc_fid)) {
+	if (is_ffa_fid(smc_fid)) {
 		return spmd_smc_handler(smc_fid, x1, x2, x3, x4, cookie,
 					handle, flags);
 	}
diff --git a/tools/cert_create/include/cert.h b/tools/cert_create/include/cert.h
index 6db9b57..daf27a7 100644
--- a/tools/cert_create/include/cert.h
+++ b/tools/cert_create/include/cert.h
@@ -12,7 +12,7 @@
 #include "ext.h"
 #include "key.h"
 
-#define CERT_MAX_EXT			5
+#define CERT_MAX_EXT			9
 
 /*
  * This structure contains information related to the generation of the
diff --git a/tools/cert_create/include/dualroot/cot.h b/tools/cert_create/include/dualroot/cot.h
index 5701206..1d959d4 100644
--- a/tools/cert_create/include/dualroot/cot.h
+++ b/tools/cert_create/include/dualroot/cot.h
@@ -18,6 +18,7 @@
 	SOC_FW_CONTENT_CERT,
 	TRUSTED_OS_FW_KEY_CERT,
 	TRUSTED_OS_FW_CONTENT_CERT,
+	SIP_SECURE_PARTITION_CONTENT_CERT,
 	FWU_CERT,
 
 	/* Certificates owned by the platform owner. */
@@ -31,6 +32,7 @@
 	TRUSTED_BOOT_FW_HASH_EXT,
 	TRUSTED_BOOT_FW_CONFIG_HASH_EXT,
 	HW_CONFIG_HASH_EXT,
+	FW_CONFIG_HASH_EXT,
 	TRUSTED_WORLD_PK_EXT,
 	SCP_FW_CONTENT_CERT_PK_EXT,
 	SCP_FW_HASH_EXT,
@@ -42,6 +44,14 @@
 	TRUSTED_OS_FW_EXTRA1_HASH_EXT,
 	TRUSTED_OS_FW_EXTRA2_HASH_EXT,
 	TRUSTED_OS_FW_CONFIG_HASH_EXT,
+	SP_PKG1_HASH_EXT,
+	SP_PKG2_HASH_EXT,
+	SP_PKG3_HASH_EXT,
+	SP_PKG4_HASH_EXT,
+	SP_PKG5_HASH_EXT,
+	SP_PKG6_HASH_EXT,
+	SP_PKG7_HASH_EXT,
+	SP_PKG8_HASH_EXT,
 	SCP_FWU_CFG_HASH_EXT,
 	AP_FWU_CFG_HASH_EXT,
 	FWU_HASH_EXT,
diff --git a/tools/cert_create/include/tbbr/tbb_cert.h b/tools/cert_create/include/tbbr/tbb_cert.h
index 628ef3a..e5fa3a2 100644
--- a/tools/cert_create/include/tbbr/tbb_cert.h
+++ b/tools/cert_create/include/tbbr/tbb_cert.h
@@ -23,6 +23,7 @@
 	TRUSTED_OS_FW_CONTENT_CERT,
 	NON_TRUSTED_FW_KEY_CERT,
 	NON_TRUSTED_FW_CONTENT_CERT,
+	SIP_SECURE_PARTITION_CONTENT_CERT,
 	FWU_CERT
 };
 
diff --git a/tools/cert_create/include/tbbr/tbb_ext.h b/tools/cert_create/include/tbbr/tbb_ext.h
index 462aafc..692b2d4 100644
--- a/tools/cert_create/include/tbbr/tbb_ext.h
+++ b/tools/cert_create/include/tbbr/tbb_ext.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
  */
@@ -15,6 +15,7 @@
 	TRUSTED_BOOT_FW_HASH_EXT,
 	TRUSTED_BOOT_FW_CONFIG_HASH_EXT,
 	HW_CONFIG_HASH_EXT,
+	FW_CONFIG_HASH_EXT,
 	TRUSTED_WORLD_PK_EXT,
 	NON_TRUSTED_WORLD_PK_EXT,
 	SCP_FW_CONTENT_CERT_PK_EXT,
@@ -30,6 +31,14 @@
 	NON_TRUSTED_FW_CONTENT_CERT_PK_EXT,
 	NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT,
 	NON_TRUSTED_FW_CONFIG_HASH_EXT,
+	SP_PKG1_HASH_EXT,
+	SP_PKG2_HASH_EXT,
+	SP_PKG3_HASH_EXT,
+	SP_PKG4_HASH_EXT,
+	SP_PKG5_HASH_EXT,
+	SP_PKG6_HASH_EXT,
+	SP_PKG7_HASH_EXT,
+	SP_PKG8_HASH_EXT,
 	SCP_FWU_CFG_HASH_EXT,
 	AP_FWU_CFG_HASH_EXT,
 	FWU_HASH_EXT
diff --git a/tools/cert_create/src/dualroot/cot.c b/tools/cert_create/src/dualroot/cot.c
index 8117ffc..a12ea21 100644
--- a/tools/cert_create/src/dualroot/cot.c
+++ b/tools/cert_create/src/dualroot/cot.c
@@ -30,9 +30,10 @@
 			TRUSTED_FW_NVCOUNTER_EXT,
 			TRUSTED_BOOT_FW_HASH_EXT,
 			TRUSTED_BOOT_FW_CONFIG_HASH_EXT,
-			HW_CONFIG_HASH_EXT
+			HW_CONFIG_HASH_EXT,
+			FW_CONFIG_HASH_EXT
 		},
-		.num_ext = 4
+		.num_ext = 5
 	},
 
 	[TRUSTED_KEY_CERT] = {
@@ -137,6 +138,28 @@
 		.num_ext = 5
 	},
 
+	[SIP_SECURE_PARTITION_CONTENT_CERT] = {
+		.id = SIP_SECURE_PARTITION_CONTENT_CERT,
+		.opt = "sip-sp-cert",
+		.help_msg = "SiP owned Secure Partition Content Certificate (output file)",
+		.fn = NULL,
+		.cn = "SiP owned Secure Partition Content Certificate",
+		.key = TRUSTED_WORLD_KEY,
+		.issuer = SIP_SECURE_PARTITION_CONTENT_CERT,
+		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
+			SP_PKG1_HASH_EXT,
+			SP_PKG2_HASH_EXT,
+			SP_PKG3_HASH_EXT,
+			SP_PKG4_HASH_EXT,
+			SP_PKG5_HASH_EXT,
+			SP_PKG6_HASH_EXT,
+			SP_PKG7_HASH_EXT,
+			SP_PKG8_HASH_EXT,
+		},
+		.num_ext = 9
+	},
+
 	[FWU_CERT] = {
 		.id = FWU_CERT,
 		.opt = "fwu-cert",
@@ -217,6 +240,17 @@
 		.optional = 1
 	},
 
+	[FW_CONFIG_HASH_EXT] = {
+		.oid = FW_CONFIG_HASH_OID,
+		.opt = "fw-config",
+		.help_msg = "Firmware Config file",
+		.sn = "FirmwareConfigHash",
+		.ln = "Firmware Config hash",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+
 	[TRUSTED_WORLD_PK_EXT] = {
 		.oid = TRUSTED_WORLD_PK_OID,
 		.sn = "TrustedWorldPublicKey",
@@ -327,6 +361,87 @@
 		.optional = 1
 	},
 
+	[SP_PKG1_HASH_EXT] = {
+		.oid = SP_PKG1_HASH_OID,
+		.opt = "sp-pkg1",
+		.help_msg = "Secure Partition Package1 file",
+		.sn = "SPPkg1Hash",
+		.ln = "SP Pkg1 hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+	[SP_PKG2_HASH_EXT] = {
+		.oid = SP_PKG2_HASH_OID,
+		.opt = "sp-pkg2",
+		.help_msg = "Secure Partition Package2 file",
+		.sn = "SPPkg2Hash",
+		.ln = "SP Pkg2 hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+	[SP_PKG3_HASH_EXT] = {
+		.oid = SP_PKG3_HASH_OID,
+		.opt = "sp-pkg3",
+		.help_msg = "Secure Partition Package3 file",
+		.sn = "SPPkg3Hash",
+		.ln = "SP Pkg3 hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+	[SP_PKG4_HASH_EXT] = {
+		.oid = SP_PKG4_HASH_OID,
+		.opt = "sp-pkg4",
+		.help_msg = "Secure Partition Package4 file",
+		.sn = "SPPkg4Hash",
+		.ln = "SP Pkg4 hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+	[SP_PKG5_HASH_EXT] = {
+		.oid = SP_PKG5_HASH_OID,
+		.opt = "sp-pkg5",
+		.help_msg = "Secure Partition Package5 file",
+		.sn = "SPPkg5Hash",
+		.ln = "SP Pkg5 hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+	[SP_PKG6_HASH_EXT] = {
+		.oid = SP_PKG6_HASH_OID,
+		.opt = "sp-pkg6",
+		.help_msg = "Secure Partition Package6 file",
+		.sn = "SPPkg6Hash",
+		.ln = "SP Pkg6 hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+	[SP_PKG7_HASH_EXT] = {
+		.oid = SP_PKG7_HASH_OID,
+		.opt = "sp-pkg7",
+		.help_msg = "Secure Partition Package7 file",
+		.sn = "SPPkg7Hash",
+		.ln = "SP Pkg7 hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+	[SP_PKG8_HASH_EXT] = {
+		.oid = SP_PKG8_HASH_OID,
+		.opt = "sp-pkg8",
+		.help_msg = "Secure Partition Package8 file",
+		.sn = "SPPkg8Hash",
+		.ln = "SP Pkg8 hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+
 	[SCP_FWU_CFG_HASH_EXT] = {
 		.oid = SCP_FWU_CFG_HASH_OID,
 		.opt = "scp-fwu-cfg",
diff --git a/tools/cert_create/src/tbbr/tbb_cert.c b/tools/cert_create/src/tbbr/tbb_cert.c
index 7fb32d8..f4fe63d 100644
--- a/tools/cert_create/src/tbbr/tbb_cert.c
+++ b/tools/cert_create/src/tbbr/tbb_cert.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
  */
@@ -28,9 +28,10 @@
 			TRUSTED_FW_NVCOUNTER_EXT,
 			TRUSTED_BOOT_FW_HASH_EXT,
 			TRUSTED_BOOT_FW_CONFIG_HASH_EXT,
-			HW_CONFIG_HASH_EXT
+			HW_CONFIG_HASH_EXT,
+			FW_CONFIG_HASH_EXT
 		},
-		.num_ext = 4
+		.num_ext = 5
 	},
 	[TRUSTED_KEY_CERT] = {
 		.id = TRUSTED_KEY_CERT,
@@ -164,6 +165,27 @@
 		},
 		.num_ext = 3
 	},
+	[SIP_SECURE_PARTITION_CONTENT_CERT] = {
+		.id = SIP_SECURE_PARTITION_CONTENT_CERT,
+		.opt = "sip-sp-cert",
+		.help_msg = "SiP owned Secure Partition Content Certificate (output file)",
+		.fn = NULL,
+		.cn = "SiP owned Secure Partition Content Certificate",
+		.key = TRUSTED_WORLD_KEY,
+		.issuer = SIP_SECURE_PARTITION_CONTENT_CERT,
+		.ext = {
+			TRUSTED_FW_NVCOUNTER_EXT,
+			SP_PKG1_HASH_EXT,
+			SP_PKG2_HASH_EXT,
+			SP_PKG3_HASH_EXT,
+			SP_PKG4_HASH_EXT,
+			SP_PKG5_HASH_EXT,
+			SP_PKG6_HASH_EXT,
+			SP_PKG7_HASH_EXT,
+			SP_PKG8_HASH_EXT,
+		},
+		.num_ext = 9
+	},
 	[FWU_CERT] = {
 		.id = FWU_CERT,
 		.opt = "fwu-cert",
diff --git a/tools/cert_create/src/tbbr/tbb_ext.c b/tools/cert_create/src/tbbr/tbb_ext.c
index ee5377f..60bafb4 100644
--- a/tools/cert_create/src/tbbr/tbb_ext.c
+++ b/tools/cert_create/src/tbbr/tbb_ext.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,6 +69,16 @@
 		.type = EXT_TYPE_HASH,
 		.optional = 1
 	},
+	[FW_CONFIG_HASH_EXT] = {
+		.oid = FW_CONFIG_HASH_OID,
+		.opt = "fw-config",
+		.help_msg = "Firmware Config file",
+		.sn = "FirmwareConfigHash",
+		.ln = "Firmware Config hash",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
 	[TRUSTED_WORLD_PK_EXT] = {
 		.oid = TRUSTED_WORLD_PK_OID,
 		.sn = "TrustedWorldPublicKey",
@@ -203,6 +213,86 @@
 		.type = EXT_TYPE_HASH,
 		.optional = 1
 	},
+	[SP_PKG1_HASH_EXT] = {
+		.oid = SP_PKG1_HASH_OID,
+		.opt = "sp-pkg1",
+		.help_msg = "Secure Partition Package1 file",
+		.sn = "SPPkg1Hash",
+		.ln = "SP Pkg1 hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+	[SP_PKG2_HASH_EXT] = {
+		.oid = SP_PKG2_HASH_OID,
+		.opt = "sp-pkg2",
+		.help_msg = "Secure Partition Package2 file",
+		.sn = "SPPkg2Hash",
+		.ln = "SP Pkg2 hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+	[SP_PKG3_HASH_EXT] = {
+		.oid = SP_PKG3_HASH_OID,
+		.opt = "sp-pkg3",
+		.help_msg = "Secure Partition Package3 file",
+		.sn = "SPPkg3Hash",
+		.ln = "SP Pkg3 hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+	[SP_PKG4_HASH_EXT] = {
+		.oid = SP_PKG4_HASH_OID,
+		.opt = "sp-pkg4",
+		.help_msg = "Secure Partition Package4 file",
+		.sn = "SPPkg4Hash",
+		.ln = "SP Pkg4 hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+	[SP_PKG5_HASH_EXT] = {
+		.oid = SP_PKG5_HASH_OID,
+		.opt = "sp-pkg5",
+		.help_msg = "Secure Partition Package5 file",
+		.sn = "SPPkg5Hash",
+		.ln = "SP Pkg5 hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+	[SP_PKG6_HASH_EXT] = {
+		.oid = SP_PKG6_HASH_OID,
+		.opt = "sp-pkg6",
+		.help_msg = "Secure Partition Package6 file",
+		.sn = "SPPkg6Hash",
+		.ln = "SP Pkg6 hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+	[SP_PKG7_HASH_EXT] = {
+		.oid = SP_PKG7_HASH_OID,
+		.opt = "sp-pkg7",
+		.help_msg = "Secure Partition Package7 file",
+		.sn = "SPPkg7Hash",
+		.ln = "SP Pkg7 hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
+	[SP_PKG8_HASH_EXT] = {
+		.oid = SP_PKG8_HASH_OID,
+		.opt = "sp-pkg8",
+		.help_msg = "Secure Partition Package8 file",
+		.sn = "SPPkg8Hash",
+		.ln = "SP Pkg8 hash (SHA256)",
+		.asn1_type = V_ASN1_OCTET_STRING,
+		.type = EXT_TYPE_HASH,
+		.optional = 1
+	},
 	[SCP_FWU_CFG_HASH_EXT] = {
 		.oid = SCP_FWU_CFG_HASH_OID,
 		.opt = "scp-fwu-cfg",
diff --git a/tools/fiptool/fiptool.c b/tools/fiptool/fiptool.c
index 80b498e..8c5b04a 100644
--- a/tools/fiptool/fiptool.c
+++ b/tools/fiptool/fiptool.c
@@ -24,17 +24,17 @@
 #define OPT_ALIGN 2
 
 static int info_cmd(int argc, char *argv[]);
-static void info_usage(void);
+static void info_usage(int);
 static int create_cmd(int argc, char *argv[]);
-static void create_usage(void);
+static void create_usage(int);
 static int update_cmd(int argc, char *argv[]);
-static void update_usage(void);
+static void update_usage(int);
 static int unpack_cmd(int argc, char *argv[]);
-static void unpack_usage(void);
+static void unpack_usage(int);
 static int remove_cmd(int argc, char *argv[]);
-static void remove_usage(void);
+static void remove_usage(int);
 static int version_cmd(int argc, char *argv[]);
-static void version_usage(void);
+static void version_usage(int);
 static int help_cmd(int argc, char *argv[]);
 static void usage(void);
 
@@ -448,7 +448,7 @@
 	fip_toc_header_t toc_header;
 
 	if (argc != 2)
-		info_usage();
+		info_usage(EXIT_FAILURE);
 	argc--, argv++;
 
 	parse_fip(argv[0], &toc_header);
@@ -487,10 +487,10 @@
 	return 0;
 }
 
-static void info_usage(void)
+static void info_usage(int exit_status)
 {
 	printf("fiptool info FIP_FILENAME\n");
-	exit(1);
+	exit(exit_status);
 }
 
 static int pack_images(const char *filename, uint64_t toc_flags, unsigned long align)
@@ -669,7 +669,7 @@
 	unsigned long align = 1;
 
 	if (argc < 2)
-		create_usage();
+		create_usage(EXIT_FAILURE);
 
 	opts = fill_common_opts(opts, &nr_opts, required_argument);
 	opts = add_opt(opts, &nr_opts, "plat-toc-flags", required_argument,
@@ -710,7 +710,7 @@
 
 			if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0 ||
 			    filename[0] == '\0')
-				create_usage();
+				create_usage(EXIT_FAILURE);
 
 			desc = lookup_image_desc_from_uuid(&uuid);
 			if (desc == NULL) {
@@ -722,7 +722,7 @@
 			break;
 		}
 		default:
-			create_usage();
+			create_usage(EXIT_FAILURE);
 		}
 	}
 	argc -= optind;
@@ -730,7 +730,7 @@
 	free(opts);
 
 	if (argc == 0)
-		create_usage();
+		create_usage(EXIT_SUCCESS);
 
 	update_fip();
 
@@ -738,7 +738,7 @@
 	return 0;
 }
 
-static void create_usage(void)
+static void create_usage(int exit_status)
 {
 	toc_entry_t *toc_entry = toc_entries;
 
@@ -753,7 +753,7 @@
 	for (; toc_entry->cmdline_name != NULL; toc_entry++)
 		printf("  --%-16s FILENAME\t%s\n", toc_entry->cmdline_name,
 		    toc_entry->name);
-	exit(1);
+	exit(exit_status);
 }
 
 static int update_cmd(int argc, char *argv[])
@@ -767,7 +767,7 @@
 	int pflag = 0;
 
 	if (argc < 2)
-		update_usage();
+		update_usage(EXIT_FAILURE);
 
 	opts = fill_common_opts(opts, &nr_opts, required_argument);
 	opts = add_opt(opts, &nr_opts, "align", required_argument, OPT_ALIGN);
@@ -807,7 +807,7 @@
 
 			if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0 ||
 			    filename[0] == '\0')
-				update_usage();
+				update_usage(EXIT_FAILURE);
 
 			desc = lookup_image_desc_from_uuid(&uuid);
 			if (desc == NULL) {
@@ -825,7 +825,7 @@
 			snprintf(outfile, sizeof(outfile), "%s", optarg);
 			break;
 		default:
-			update_usage();
+			update_usage(EXIT_FAILURE);
 		}
 	}
 	argc -= optind;
@@ -833,7 +833,7 @@
 	free(opts);
 
 	if (argc == 0)
-		update_usage();
+		update_usage(EXIT_SUCCESS);
 
 	if (outfile[0] == '\0')
 		snprintf(outfile, sizeof(outfile), "%s", argv[0]);
@@ -851,7 +851,7 @@
 	return 0;
 }
 
-static void update_usage(void)
+static void update_usage(int exit_status)
 {
 	toc_entry_t *toc_entry = toc_entries;
 
@@ -867,7 +867,7 @@
 	for (; toc_entry->cmdline_name != NULL; toc_entry++)
 		printf("  --%-16s FILENAME\t%s\n", toc_entry->cmdline_name,
 		    toc_entry->name);
-	exit(1);
+	exit(exit_status);
 }
 
 static int unpack_cmd(int argc, char *argv[])
@@ -880,7 +880,7 @@
 	int unpack_all = 1;
 
 	if (argc < 2)
-		unpack_usage();
+		unpack_usage(EXIT_FAILURE);
 
 	opts = fill_common_opts(opts, &nr_opts, required_argument);
 	opts = add_opt(opts, &nr_opts, "blob", required_argument, 'b');
@@ -915,7 +915,7 @@
 
 			if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0 ||
 			    filename[0] == '\0')
-				unpack_usage();
+				unpack_usage(EXIT_FAILURE);
 
 			desc = lookup_image_desc_from_uuid(&uuid);
 			if (desc == NULL) {
@@ -934,7 +934,7 @@
 			snprintf(outdir, sizeof(outdir), "%s", optarg);
 			break;
 		default:
-			unpack_usage();
+			unpack_usage(EXIT_FAILURE);
 		}
 	}
 	argc -= optind;
@@ -942,7 +942,7 @@
 	free(opts);
 
 	if (argc == 0)
-		unpack_usage();
+		unpack_usage(EXIT_SUCCESS);
 
 	parse_fip(argv[0], NULL);
 
@@ -986,7 +986,7 @@
 	return 0;
 }
 
-static void unpack_usage(void)
+static void unpack_usage(int exit_status)
 {
 	toc_entry_t *toc_entry = toc_entries;
 
@@ -1003,7 +1003,7 @@
 		    toc_entry->name);
 	printf("\n");
 	printf("If no options are provided, all images will be unpacked.\n");
-	exit(1);
+	exit(exit_status);
 }
 
 static int remove_cmd(int argc, char *argv[])
@@ -1017,7 +1017,7 @@
 	int fflag = 0;
 
 	if (argc < 2)
-		remove_usage();
+		remove_usage(EXIT_FAILURE);
 
 	opts = fill_common_opts(opts, &nr_opts, no_argument);
 	opts = add_opt(opts, &nr_opts, "align", required_argument, OPT_ALIGN);
@@ -1053,7 +1053,7 @@
 			    filename, sizeof(filename));
 
 			if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0)
-				remove_usage();
+				remove_usage(EXIT_FAILURE);
 
 			desc = lookup_image_desc_from_uuid(&uuid);
 			if (desc == NULL) {
@@ -1071,7 +1071,7 @@
 			snprintf(outfile, sizeof(outfile), "%s", optarg);
 			break;
 		default:
-			remove_usage();
+			remove_usage(EXIT_FAILURE);
 		}
 	}
 	argc -= optind;
@@ -1079,7 +1079,7 @@
 	free(opts);
 
 	if (argc == 0)
-		remove_usage();
+		remove_usage(EXIT_SUCCESS);
 
 	if (outfile[0] != '\0' && access(outfile, F_OK) == 0 && !fflag)
 		log_errx("File %s already exists, use --force to overwrite it",
@@ -1110,7 +1110,7 @@
 	return 0;
 }
 
-static void remove_usage(void)
+static void remove_usage(int exit_status)
 {
 	toc_entry_t *toc_entry = toc_entries;
 
@@ -1126,7 +1126,7 @@
 	for (; toc_entry->cmdline_name != NULL; toc_entry++)
 		printf("  --%-16s\t%s\n", toc_entry->cmdline_name,
 		    toc_entry->name);
-	exit(1);
+	exit(exit_status);
 }
 
 static int version_cmd(int argc, char *argv[])
@@ -1140,10 +1140,10 @@
 	return 0;
 }
 
-static void version_usage(void)
+static void version_usage(int exit_status)
 {
 	printf("fiptool version\n");
-	exit(1);
+	exit(exit_status);
 }
 
 static int help_cmd(int argc, char *argv[])
@@ -1157,7 +1157,7 @@
 	for (i = 0; i < NELEM(cmds); i++) {
 		if (strcmp(cmds[i].name, argv[0]) == 0 &&
 		    cmds[i].usage != NULL)
-			cmds[i].usage();
+			cmds[i].usage(EXIT_SUCCESS);
 	}
 	if (i == NELEM(cmds))
 		printf("No help for subcommand '%s'\n", argv[0]);
@@ -1178,7 +1178,7 @@
 	printf("  remove\tRemove images from FIP.\n");
 	printf("  version\tShow fiptool version.\n");
 	printf("  help\t\tShow help for given command.\n");
-	exit(1);
+	exit(EXIT_SUCCESS);
 }
 
 int main(int argc, char *argv[])
diff --git a/tools/fiptool/fiptool.h b/tools/fiptool/fiptool.h
index af3fcbd..88c4a7e 100644
--- a/tools/fiptool/fiptool.h
+++ b/tools/fiptool/fiptool.h
@@ -48,7 +48,7 @@
 typedef struct cmd {
 	char              *name;
 	int              (*handler)(int, char **);
-	void             (*usage)(void);
+	void             (*usage)(int);
 } cmd_t;
 
 #endif /* FIPTOOL_H */
diff --git a/tools/fiptool/tbbr_config.c b/tools/fiptool/tbbr_config.c
index 86b8581..bf721c1 100644
--- a/tools/fiptool/tbbr_config.c
+++ b/tools/fiptool/tbbr_config.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
  */
@@ -69,6 +69,11 @@
 	},
 	/* Dynamic Configs */
 	{
+		.name = "FW_CONFIG",
+		.uuid = UUID_FW_CONFIG,
+		.cmdline_name = "fw-config"
+	},
+	{
 		.name = "HW_CONFIG",
 		.uuid = UUID_HW_CONFIG,
 		.cmdline_name = "hw-config"
@@ -152,6 +157,11 @@
 		.cmdline_name = "nt-fw-cert"
 	},
 	{
+		.name = "SiP owned Secure Partition content certificate",
+		.uuid = UUID_SIP_SECURE_PARTITION_CONTENT_CERT,
+		.cmdline_name = "sip-sp-cert"
+	},
+	{
 		.name = NULL,
 		.uuid = { {0} },
 		.cmdline_name = NULL,
diff --git a/tools/marvell/doimage/doimage.c b/tools/marvell/doimage/doimage.c
index 82fd375..e08b820 100644
--- a/tools/marvell/doimage/doimage.c
+++ b/tools/marvell/doimage/doimage.c
@@ -51,7 +51,7 @@
 /* Number of address pairs in control array */
 #define CP_CTRL_EL_ARRAY_SZ	32
 
-#define VERSION_STRING		"Marvell(C) doimage utility version 3.2"
+#define VERSION_STRING		"Marvell(C) doimage utility version 3.3"
 
 /* A8K definitions */
 
@@ -303,7 +303,7 @@
 				MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
 
 	/* First compute the SHA256 hash for the input blob */
-	mbedtls_sha256(input, ilen, hash, 0);
+	mbedtls_sha256_ret(input, ilen, hash, 0);
 
 	/* Then calculate the hash signature */
 	rval = mbedtls_rsa_rsassa_pss_sign(mbedtls_pk_rsa(*pk_ctx),
@@ -354,6 +354,7 @@
 	mbedtls_pk_context		pk_ctx;
 	unsigned char			hash[32];
 	int				rval;
+	unsigned char			*pkey = (unsigned char *)pub_key;
 
 	/* Not sure this is required,
 	 * but it's safer to start with empty buffer
@@ -373,8 +374,7 @@
 	}
 
 	/* Check ability to read the public key */
-	rval = mbedtls_pk_parse_public_key(&pk_ctx, pub_key,
-					   MAX_RSA_DER_BYTE_LEN);
+	rval = mbedtls_pk_parse_subpubkey(&pkey, pub_key + klen, &pk_ctx);
 	if (rval != 0) {
 		fprintf(stderr, " Failed in pk_parse_public_key (%#x)!\n",
 			rval);
@@ -387,7 +387,7 @@
 				MBEDTLS_MD_SHA256);
 
 	/* Compute the SHA256 hash for the input buffer */
-	mbedtls_sha256(input, ilen, hash, 0);
+	mbedtls_sha256_ret(input, ilen, hash, 0);
 
 	rval = mbedtls_rsa_rsassa_pss_verify(mbedtls_pk_rsa(pk_ctx),
 					     mbedtls_ctr_drbg_random,
@@ -458,7 +458,7 @@
 	/* compute SHA-256 digest of the results
 	 * and use it as the init vector (IV)
 	 */
-	mbedtls_sha256(IV, AES_BLOCK_SZ, digest, 0);
+	mbedtls_sha256_ret(IV, AES_BLOCK_SZ, digest, 0);
 	memcpy(IV, digest, AES_BLOCK_SZ);
 	mbedtls_aes_setkey_enc(&aes_ctx, opts.sec_opts->aes_key,
 			       AES_KEY_BIT_LEN);
@@ -880,11 +880,13 @@
 				fname);
 			return 1;
 		}
+
 		/* Data in the output buffer is aligned to the buffer end */
 		der_buf_start = output_buf + sizeof(output_buf) - output_len;
 		/* In the header DER data is aligned
 		 * to the start of appropriate field
 		 */
+		bzero(out_der_key, MAX_RSA_DER_BYTE_LEN);
 		memcpy(out_der_key, der_buf_start, output_len);
 
 	} /* for every private key file */
@@ -899,8 +901,10 @@
 		fprintf(stderr, "Failed to sign CSK keys block!\n");
 		return 1;
 	}
+
 	/* Check that everything is correct */
-	if (verify_rsa_signature(sec_ext.kak_key, MAX_RSA_DER_BYTE_LEN,
+	if (verify_rsa_signature(sec_ext.kak_key,
+				 MAX_RSA_DER_BYTE_LEN,
 				 &sec_ext.csk_keys[0][0],
 				 sizeof(sec_ext.csk_keys),
 				 opts.sec_opts->kak_key_file,
@@ -1333,7 +1337,7 @@
 					goto error;
 				}
 
-				mbedtls_sha256(sec_entry->kak_key,
+				mbedtls_sha256_ret(sec_entry->kak_key,
 					       MAX_RSA_DER_BYTE_LEN, hash, 0);
 				fprintf(stdout,
 					">>>>>>>>>> KAK KEY HASH >>>>>>>>>>\n");
@@ -1559,13 +1563,9 @@
 
 int write_boot_image(uint8_t *buf, uint32_t image_size, FILE *out_fd)
 {
-	int aligned_size;
 	int written;
 
-	/* Image size must be aligned to 4 bytes */
-	aligned_size = (image_size + 3) & (~0x3);
-
-	written = fwrite(buf, aligned_size, 1, out_fd);
+	written = fwrite(buf, image_size, 1, out_fd);
 	if (written != 1) {
 		fprintf(stderr, "Error: Failed to write boot image\n");
 		goto error;
@@ -1587,7 +1587,7 @@
 	int ext_cnt = 0;
 	int opt;
 	int ret = 0;
-	int image_size;
+	int image_size, file_size;
 	uint8_t *image_buf = NULL;
 	int read;
 	size_t len;
@@ -1683,16 +1683,18 @@
 		goto main_exit;
 	}
 
-	/* Read the input file to buffer */
-	image_size = get_file_size(in_file);
-	image_buf = calloc((image_size + AES_BLOCK_SZ - 1) &
-			   ~(AES_BLOCK_SZ - 1), 1);
+	/* Read the input file to buffer
+	 * Always align the image to 16 byte boundary
+	 */
+	file_size  = get_file_size(in_file);
+	image_size = (file_size + AES_BLOCK_SZ - 1) & ~(AES_BLOCK_SZ - 1);
+	image_buf  = calloc(image_size, 1);
 	if (image_buf == NULL) {
 		fprintf(stderr, "Error: failed allocating input buffer\n");
 		return 1;
 	}
 
-	read = fread(image_buf, image_size, 1, in_fd);
+	read = fread(image_buf, file_size, 1, in_fd);
 	if (read != 1) {
 		fprintf(stderr, "Error: failed to read input file\n");
 		goto main_exit;
diff --git a/tools/sptool/sp_mk_generator.py b/tools/sptool/sp_mk_generator.py
index 6b6fa19..2153a56 100755
--- a/tools/sptool/sp_mk_generator.py
+++ b/tools/sptool/sp_mk_generator.py
@@ -11,7 +11,8 @@
 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.
+FDT_SOURCES, FIP_ARGS, CRT_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.
 
@@ -24,6 +25,7 @@
     FDT_SOURCES +=  sp1.dts
     SPTOOL_ARGS += -i sp1.bin:sp1.dtb -o sp1.pkg
     FIP_ARGS += --blob uuid=XXXXX-XXX...,file=sp1.pkg
+    CRT_ARGS += --sp-pkg1 sp1.pkg
 
 A typical SP_LAYOUT_FILE file will look like
 {
@@ -53,13 +55,13 @@
     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:]
+gen_file = os.path.abspath(sys.argv[1])
+out_dir = os.path.abspath(sys.argv[3])
 dtb_dir = out_dir + "/fdts/"
 print(dtb_dir)
 
 with open(gen_file, 'w') as out_file:
-    for key in data.keys():
+    for idx, key in enumerate(data.keys()):
 
         """
         Append FDT_SOURCES
@@ -97,4 +99,9 @@
         Append FIP_ARGS
         """
         out_file.write("FIP_ARGS += --blob uuid=" + uuid_std + ",file=" + dst + "\n")
+
+        """
+        Append CRT_ARGS
+        """
+        out_file.write("CRT_ARGS += --sp-pkg" + str(idx + 1) + " " + dst + "\n")
         out_file.write("\n")