Merge "intel: Fix Coverity Scan Defects" into integration
diff --git a/Makefile b/Makefile
index 5167d2e..547b584 100644
--- a/Makefile
+++ b/Makefile
@@ -207,9 +207,10 @@
 CPP			=	$(CC) -E $(TF_CFLAGS_$(ARCH))
 PP			=	$(CC) -E $(TF_CFLAGS_$(ARCH))
 else ifneq ($(findstring clang,$(notdir $(CC))),)
+CLANG_CCDIR		=	$(if $(filter-out ./,$(dir $(CC))),$(dir $(CC)),)
 TF_CFLAGS_aarch32	=	$(target32-directive) $(march32-directive)
 TF_CFLAGS_aarch64	=	-target aarch64-elf $(march64-directive)
-LD			=	ld.lld
+LD			=	$(CLANG_CCDIR)ld.lld
 ifeq (, $(shell which $(LD)))
 $(error "No $(LD) in PATH, make sure it is installed or set LD to a different linker")
 endif
@@ -418,11 +419,20 @@
         $(warning "SPD and EL3_PAYLOAD_BASE are incompatible build options.")
         $(warning "The SPD and its BL32 companion will be present but ignored.")
 endif
-        # We expect to locate an spd.mk under the specified SPD directory
-        SPD_MAKE	:=	$(wildcard services/spd/${SPD}/${SPD}.mk)
+	ifeq (${SPD},spmd)
+		# SPMD is located in std_svc directory
+		SPD_DIR := std_svc
+	else
+		# All other SPDs in spd directory
+		SPD_DIR := spd
+	endif
+
+	# We expect to locate an spd.mk under the specified SPD directory
+	SPD_MAKE	:=	$(wildcard services/${SPD_DIR}/${SPD}/${SPD}.mk)
+
 
         ifeq (${SPD_MAKE},)
-                $(error Error: No services/spd/${SPD}/${SPD}.mk located)
+                $(error Error: No services/${SPD_DIR}/${SPD}/${SPD}.mk located)
         endif
         $(info Including ${SPD_MAKE})
         include ${SPD_MAKE}
@@ -777,6 +787,7 @@
 $(eval $(call assert_boolean,TRUSTED_BOARD_BOOT))
 $(eval $(call assert_boolean,USE_COHERENT_MEM))
 $(eval $(call assert_boolean,USE_DEBUGFS))
+$(eval $(call assert_boolean,USE_FCONF_BASED_IO))
 $(eval $(call assert_boolean,USE_ROMLIB))
 $(eval $(call assert_boolean,USE_TBBR_DEFS))
 $(eval $(call assert_boolean,WARMBOOT_ENABLE_DCACHE_EARLY))
@@ -845,6 +856,7 @@
 $(eval $(call add_define,TRUSTED_BOARD_BOOT))
 $(eval $(call add_define,USE_COHERENT_MEM))
 $(eval $(call add_define,USE_DEBUGFS))
+$(eval $(call add_define,USE_FCONF_BASED_IO))
 $(eval $(call add_define,USE_ROMLIB))
 $(eval $(call add_define,USE_TBBR_DEFS))
 $(eval $(call add_define,WARMBOOT_ENABLE_DCACHE_EARLY))
diff --git a/bl1/bl1.ld.S b/bl1/bl1.ld.S
index 877af8e..b20859b 100644
--- a/bl1/bl1.ld.S
+++ b/bl1/bl1.ld.S
@@ -65,8 +65,13 @@
          * No need to pad out the .rodata section to a page boundary. Next is
          * the .data section, which can mapped in ROM with the same memory
          * attributes as the .rodata section.
+         *
+         * Pad out to 16 bytes though as .data section needs to be 16 byte
+         * aligned and lld does not align the LMA to the aligment specified
+         * on the .data section.
          */
         __RODATA_END__ = .;
+         . = ALIGN(16);
     } >ROM
 #else
     ro . : {
@@ -92,6 +97,13 @@
 
         *(.vectors)
         __RO_END__ = .;
+
+        /*
+         * Pad out to 16 bytes as .data section needs to be 16 byte aligned and
+         * lld does not align the LMA to the aligment specified on the .data
+         * section.
+         */
+         . = ALIGN(16);
     } >ROM
 #endif
 
diff --git a/bl1/bl1_fwu.c b/bl1/bl1_fwu.c
index 48f08d2..42a3ded 100644
--- a/bl1/bl1_fwu.c
+++ b/bl1/bl1_fwu.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -55,11 +55,11 @@
 /*******************************************************************************
  * Top level handler for servicing FWU SMCs.
  ******************************************************************************/
-register_t bl1_fwu_smc_handler(unsigned int smc_fid,
-			register_t x1,
-			register_t x2,
-			register_t x3,
-			register_t x4,
+u_register_t bl1_fwu_smc_handler(unsigned int smc_fid,
+			u_register_t x1,
+			u_register_t x2,
+			u_register_t x3,
+			u_register_t x4,
 			void *cookie,
 			void *handle,
 			unsigned int flags)
@@ -76,7 +76,7 @@
 		SMC_RET1(handle, bl1_fwu_image_execute(x1, &handle, flags));
 
 	case FWU_SMC_IMAGE_RESUME:
-		SMC_RET1(handle, bl1_fwu_image_resume(x1, &handle, flags));
+		SMC_RET1(handle, bl1_fwu_image_resume((register_t)x1, &handle, flags));
 
 	case FWU_SMC_SEC_IMAGE_DONE:
 		SMC_RET1(handle, bl1_fwu_sec_image_done(&handle, flags));
diff --git a/bl1/bl1_main.c b/bl1/bl1_main.c
index bff8d22..e11ead6 100644
--- a/bl1/bl1_main.c
+++ b/bl1/bl1_main.c
@@ -226,11 +226,11 @@
 /*******************************************************************************
  * Top level handler for servicing BL1 SMCs.
  ******************************************************************************/
-register_t bl1_smc_handler(unsigned int smc_fid,
-	register_t x1,
-	register_t x2,
-	register_t x3,
-	register_t x4,
+u_register_t bl1_smc_handler(unsigned int smc_fid,
+	u_register_t x1,
+	u_register_t x2,
+	u_register_t x3,
+	u_register_t x4,
 	void *cookie,
 	void *handle,
 	unsigned int flags)
@@ -269,12 +269,12 @@
  * BL1 SMC wrapper.  This function is only used in AArch32 mode to ensure ABI
  * compliance when invoking bl1_smc_handler.
  ******************************************************************************/
-register_t bl1_smc_wrapper(uint32_t smc_fid,
+u_register_t bl1_smc_wrapper(uint32_t smc_fid,
 	void *cookie,
 	void *handle,
 	unsigned int flags)
 {
-	register_t x1, x2, x3, x4;
+	u_register_t x1, x2, x3, x4;
 
 	assert(handle != NULL);
 
diff --git a/bl1/bl1_private.h b/bl1/bl1_private.h
index 927c7b8..2cfeeea 100644
--- a/bl1/bl1_private.h
+++ b/bl1/bl1_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,11 +19,11 @@
 
 void bl1_prepare_next_image(unsigned int image_id);
 
-register_t bl1_fwu_smc_handler(unsigned int smc_fid,
-		register_t x1,
-		register_t x2,
-		register_t x3,
-		register_t x4,
+u_register_t bl1_fwu_smc_handler(unsigned int smc_fid,
+		u_register_t x1,
+		u_register_t x2,
+		u_register_t x3,
+		u_register_t x4,
 		void *cookie,
 		void *handle,
 		unsigned int flags);
diff --git a/bl2/bl2.ld.S b/bl2/bl2.ld.S
index 6230562..c1338e2 100644
--- a/bl2/bl2.ld.S
+++ b/bl2/bl2.ld.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -46,6 +46,11 @@
         __RODATA_START__ = .;
         *(SORT_BY_ALIGNMENT(.rodata*))
 
+       . = ALIGN(8);
+        __FCONF_POPULATOR_START__ = .;
+        KEEP(*(.fconf_populator))
+        __FCONF_POPULATOR_END__ = .;
+
         /* Ensure 8-byte alignment for descriptors and ensure inclusion */
         . = ALIGN(8);
         __PARSER_LIB_DESCS_START__ = .;
@@ -62,6 +67,11 @@
         *(SORT_BY_ALIGNMENT(.text*))
         *(SORT_BY_ALIGNMENT(.rodata*))
 
+	. = ALIGN(8);
+         __FCONF_POPULATOR_START__ = .;
+         KEEP(*(.fconf_populator))
+         __FCONF_POPULATOR_END__ = .;
+
         /* Ensure 8-byte alignment for descriptors and ensure inclusion */
         . = ALIGN(8);
         __PARSER_LIB_DESCS_START__ = .;
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index 58909e8..0948e94 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -31,6 +31,7 @@
 				services/arm_arch_svc/arm_arch_svc_setup.c	\
 				services/std_svc/std_svc_setup.c		\
 				${PSCI_LIB_SOURCES}				\
+				${SPMD_SOURCES}					\
 				${SPM_SOURCES}
 
 
diff --git a/common/bl_common.c b/common/bl_common.c
index b74225b..2fcb538 100644
--- a/common/bl_common.c
+++ b/common/bl_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
diff --git a/common/desc_image_load.c b/common/desc_image_load.c
index b483597..0769226 100644
--- a/common/desc_image_load.c
+++ b/common/desc_image_load.c
@@ -215,6 +215,9 @@
 	bl_params_node_t *params_node;
 	unsigned int fw_config_id;
 	uintptr_t hw_config_base = 0, fw_config_base;
+#if defined(SPD_spmd)
+	uint32_t fw_config_size = 0;
+#endif
 	bl_mem_params_node_t *mem_params;
 
 	assert(bl2_to_next_bl_params != NULL);
@@ -249,10 +252,14 @@
 
 		if (fw_config_id != INVALID_IMAGE_ID) {
 			mem_params = get_bl_mem_params_node(fw_config_id);
-			if (mem_params != NULL)
+			if (mem_params != NULL) {
 				fw_config_base = mem_params->image_info.image_base;
+#if defined(SPD_spmd)
+				fw_config_size =
+					mem_params->image_info.image_size;
+#endif
+			}
 		}
-
 		/*
 		 * Pass hw and tb_fw config addresses to next images. NOTE - for
 		 * EL3 runtime images (BL31 for AArch64 and BL32 for AArch32),
@@ -273,6 +280,11 @@
 			if (params_node->ep_info->args.arg1 == 0U)
 				params_node->ep_info->args.arg1 =
 								hw_config_base;
+#if defined(SPD_spmd)
+			if (params_node->ep_info->args.arg2 == 0U)
+				params_node->ep_info->args.arg2 =
+								fw_config_size;
+#endif
 		}
 	}
 }
diff --git a/docs/components/debugfs-design.rst b/docs/components/debugfs-design.rst
index 06916f3..8ce1ba6 100644
--- a/docs/components/debugfs-design.rst
+++ b/docs/components/debugfs-design.rst
@@ -15,8 +15,9 @@
 ------------------
 
 The core functionality lies in a virtual file system based on a 9p file server
-interface (`Notes on the Plan 9 Kernel Source`_). The implementation permits
-exposing virtual files, firmware drivers, and file blobs.
+interface (`Notes on the Plan 9 Kernel Source`_ and
+`Linux 9p remote filesystem protocol`_).
+The implementation permits exposing virtual files, firmware drivers, and file blobs.
 
 Namespace
 ~~~~~~~~~
@@ -77,10 +78,10 @@
 -------------
 
 The communication with the 9p layer in BL31 is made through an SMC conduit
-(`SMC Calling Convention PDD`_), using a specific SiP Function Id. An NS shared
-buffer is used to pass path string parameters, or e.g. to exchange data on a
-read operation. Refer to `ARM SiP Services`_ for a description of the SMC
-interface.
+(`SMC Calling Convention PDD`_), using a specific SiP Function Id. An NS
+shared buffer is used to pass path string parameters, or e.g. to exchange
+data on a read operation. Refer to `ARM SiP Services`_ for a description
+of the SMC interface.
 
 Security considerations
 -----------------------
@@ -114,17 +115,9 @@
 - a Linux kernel driver running at NS-EL1
 - a Linux userspace application through the kernel driver
 
-References
-----------
-
-.. [#] `SMC Calling Convention PDD`_
-.. [#] `Notes on the Plan 9 Kernel Source`_
-.. [#] `Linux 9p remote filesystem protocol`_
-.. [#] `ARM SiP Services`_
-
 --------------
 
-*Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.*
 
 .. _SMC Calling Convention PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/
 .. _Notes on the Plan 9 Kernel Source: http://lsub.org/who/nemo/9.pdf
diff --git a/docs/components/fconf.rst b/docs/components/fconf.rst
new file mode 100644
index 0000000..cec3ceb
--- /dev/null
+++ b/docs/components/fconf.rst
@@ -0,0 +1,85 @@
+Firmware Configuration Framework
+================================
+
+This document provides an overview of the |FCONF| framework.
+
+Introduction
+~~~~~~~~~~~~
+
+The Firmware CONfiguration Framework (|FCONF|) is an abstraction layer for
+platform specific data, allowing a "property" to be queried and a value
+retrieved without the requesting entity knowing what backing store is being used
+to hold the data.
+
+It is used to bridge new and old ways of providing platform-specific data.
+Today, information like the Chain of Trust is held within several, nested
+platform-defined tables. In the future, it may be provided as part of a device
+blob, along with the rest of the information about images to load.
+Introducing this abstraction layer will make migration easier and will preserve
+functionality for platforms that cannot / don't want to use device tree.
+
+Accessing properties
+~~~~~~~~~~~~~~~~~~~~
+
+Properties defined in the |FCONF| are grouped around namespaces and
+sub-namespaces: a.b.property.
+Examples namespace can be:
+
+- (|TBBR|) Chain of Trust data: tbbr.cot.trusted_boot_fw_cert
+- (|TBBR|) dynamic configuration info: tbbr.dyn_config.disable_auth
+- Arm io policies: arm.io_policies.bl2_image
+
+Properties can be accessed with the ``FCONF_GET_PROPERTY(a,b,property)`` macro.
+
+Defining properties
+~~~~~~~~~~~~~~~~~~~
+
+Properties composing the |FCONF| have to be stored in C structures. If another
+backing store is wanted to be used, the platform has to provide a ``populate()``
+function to fill the corresponding C structure.
+
+The ``populate()`` function must be registered to the |FCONF| framework with
+the ``FCONF_REGISTER_POPULATOR()`` macro. This ensures that the function would
+be called inside the generic ``fconf_populate()`` function during
+initialization.
+
+::
+
+    int fconf_populate_tbbr_dyn_config(uintptr_t config)
+    {
+        /* read dtb and fill tbbr_dyn_config struct */
+    }
+
+    FCONF_REGISTER_POPULATOR(fconf_populate_tbbr_dyn_config);
+
+Then, a wrapper has to be provided to match the ``FCONF_GET_PROPERTY()`` macro:
+
+::
+
+    /* generic getter */
+    #define FCONF_GET_PROPERTY(a,b,property)	a##__##b##_getter(property)
+
+    /* my specific getter */
+    #define tbbr__dyn_config_getter(id)	tbbr_dyn_config.id
+
+This second level wrapper can be used to remap the ``FCONF_GET_PROPERTY()`` to
+anything appropriate: structure, array, function, etc..
+
+Loading the property device tree
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``fconf_load_config()`` must be called to load the device tree containing
+the properties' values. This must be done after the io layer is initialized, as
+the |DTB| is stored on an external device (FIP).
+
+.. uml:: ../resources/diagrams/plantuml/fconf_bl1_load_config.puml
+
+Populating the properties
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Once a valid device tree is available, the ``fconf_populate(config)`` function
+can be used to fill the C data structure with the data from the config |DTB|.
+This function will call all the ``populate()`` callbacks which have been
+registered with ``FCONF_REGISTER_POPULATOR()``.
+
+.. uml:: ../resources/diagrams/plantuml/fconf_bl2_populate.puml
diff --git a/docs/components/index.rst b/docs/components/index.rst
index f1904c0..ae78b2b 100644
--- a/docs/components/index.rst
+++ b/docs/components/index.rst
@@ -8,7 +8,9 @@
 
    spd/index
    arm-sip-service
+   debugfs-design
    exception-handling
+   fconf
    firmware-update
    platform-interrupt-controller-API
    ras
diff --git a/docs/design/firmware-design.rst b/docs/design/firmware-design.rst
index 5fc1335..d0d6ef6 100644
--- a/docs/design/firmware-design.rst
+++ b/docs/design/firmware-design.rst
@@ -2696,13 +2696,13 @@
 
 --------------
 
-*Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.*
 
 .. _Power State Coordination Interface PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf
 .. _SMCCC: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf
 .. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf
 .. _Power State Coordination Interface PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf
-.. _Arm ARM: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0487a.e/index.html
+.. _Arm ARM: https://developer.arm.com/docs/ddi0487/latest
 .. _SMC Calling Convention PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf
 .. _Trusted Board Boot Requirements CLIENT (TBBR-CLIENT) Armv8-A (ARM DEN0006D): https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a
 
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 031836a..8854a79 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -578,6 +578,11 @@
    exposing a virtual filesystem interface through BL31 as a SiP SMC function.
    Default is 0.
 
+-  ``USE_FCONF_BASED_IO``: This flag determines whether to use IO based on the
+   firmware configuration framework. This allows moving the io_policies into a
+   configuration device tree, instead of static structure in the code base.
+
+
 -  ``USE_ROMLIB``: This flag determines whether library at ROM will be used.
    This feature creates a library of functions to be placed in ROM and thus
    reduces SRAM usage. Refer to :ref:`Library at ROM` for further details. Default
diff --git a/docs/global_substitutions.txt b/docs/global_substitutions.txt
index 491b160..4dda1dc 100644
--- a/docs/global_substitutions.txt
+++ b/docs/global_substitutions.txt
@@ -6,11 +6,13 @@
 .. |COT| replace:: :term:`COT`
 .. |CSS| replace:: :term:`CSS`
 .. |CVE| replace:: :term:`CVE`
+.. |DTB| replace:: :term:`DTB`
 .. |DS-5| replace:: :term:`DS-5`
 .. |DSU| replace:: :term:`DSU`
 .. |DT| replace:: :term:`DT`
 .. |EL| replace:: :term:`EL`
 .. |EHF| replace:: :term:`EHF`
+.. |FCONF| replace:: :term:`FCONF`
 .. |FDT| replace:: :term:`FDT`
 .. |FIP| replace:: :term:`FIP`
 .. |FVP| replace:: :term:`FVP`
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 2f19df5..3da30b0 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -42,12 +42,18 @@
    DT
       Device Tree
 
+   DTB
+      Device Tree Blob
+
    EL
       Exception Level
 
    EHF
       Exception Handling Framework
 
+   FCONF
+      Firmware Configuration Framework
+
    FDT
       Flattened Device Tree
 
diff --git a/docs/perf/index.rst b/docs/perf/index.rst
index 0f49b48..1482b80 100644
--- a/docs/perf/index.rst
+++ b/docs/perf/index.rst
@@ -8,7 +8,8 @@
 
    psci-performance-juno
    tsp
+   performance-monitoring-unit
 
 --------------
 
-*Copyright (c) 2019, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
diff --git a/docs/perf/performance-monitoring-unit.rst b/docs/perf/performance-monitoring-unit.rst
new file mode 100644
index 0000000..5dd1af5
--- /dev/null
+++ b/docs/perf/performance-monitoring-unit.rst
@@ -0,0 +1,158 @@
+Performance Monitoring Unit
+===========================
+
+The Performance Monitoring Unit (PMU) allows recording of architectural and
+microarchitectural events for profiling purposes.
+
+This document gives an overview of the PMU counter configuration to assist with
+implementation and to complement the PMU security guidelines given in the
+:ref:`Secure Development Guidelines` document.
+
+.. note::
+   This section applies to Armv8-A implementations which have version 3
+   of the Performance Monitors Extension (PMUv3).
+
+PMU Counters
+------------
+
+The PMU makes 32 counters available at all privilege levels:
+
+-  31 programmable event counters: ``PMEVCNTR<n>``, where ``n`` is ``0`` to
+   ``30``.
+-  A dedicated cycle counter: ``PMCCNTR``.
+
+Architectural mappings
+~~~~~~~~~~~~~~~~~~~~~~
+
++--------------+---------+----------------------------+
+| Counters     | State   | System Register Name       |
++==============+=========+============================+
+|              | AArch64 | ``PMEVCNTR<n>_EL0[63*:0]`` |
+| Programmable +---------+----------------------------+
+|              | AArch32 | ``PMEVCNTR<n>[31:0]``      |
++--------------+---------+----------------------------+
+|              | AArch64 | ``PMCCNTR_EL0[63:0]``      |
+| Cycle        +---------+----------------------------+
+|              | AArch32 | ``PMCCNTR[63:0]``          |
++--------------+---------+----------------------------+
+
+.. note::
+   Bits [63:32] are only available if ARMv8.5-PMU is implemented. Refer to the
+   `Arm ARM`_ for a detailed description of ARMv8.5-PMU features.
+
+Configuring the PMU for counting events
+---------------------------------------
+
+Each programmable counter has an associated register, ``PMEVTYPER<n>`` which
+configures it. The cycle counter has the ``PMCCFILTR_EL0`` register, which has
+an identical function and bit field layout as ``PMEVTYPER<n>``. In addition,
+the counters are enabled (permitted to increment) via the ``PMCNTENSET`` and
+``PMCR`` registers. These can be accessed at all privilege levels.
+
+Architectural mappings
+~~~~~~~~~~~~~~~~~~~~~~
+
++-----------------------------+------------------------+
+| AArch64                     | AArch32                |
++=============================+========================+
+| ``PMEVTYPER<n>_EL0[63*:0]`` | ``PMEVTYPER<n>[31:0]`` |
++-----------------------------+------------------------+
+| ``PMCCFILTR_EL0[63*:0]``    | ``PMCCFILTR[31:0]``    |
++-----------------------------+------------------------+
+| ``PMCNTENSET_EL0[63*:0]``   | ``PMCNTENSET[31:0]``   |
++-----------------------------+------------------------+
+| ``PMCR_EL0[63*:0]``         | ``PMCR[31:0]``         |
++-----------------------------+------------------------+
+
+.. note::
+   Bits [63:32] are reserved.
+
+Relevant register fields
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+For ``PMEVTYPER<n>_EL0``/``PMEVTYPER<n>`` and ``PMCCFILTR_EL0/PMCCFILTR``, the
+most important fields are:
+
+-  ``P``:
+
+   -  Bit 31.
+   -  If set to ``0``, will increment the associated ``PMEVCNTR<n>`` at EL1.
+
+-  ``NSK``:
+
+   -  Bit 29.
+   -  If equal to the ``P`` bit it enables the associated ``PMEVCNTR<n>`` at
+      Non-secure EL1.
+   -  Reserved if EL3 not implemented.
+
+-  ``NSH``:
+
+   -  Bit 27.
+   -  If set to ``1``, will increment the associated ``PMEVCNTR<n>`` at EL2.
+   -  Reserved if EL2 not implemented.
+
+-  ``SH``:
+
+   -  Bit 24.
+   -  If different to the ``NSH`` bit it enables the associated ``PMEVCNTR<n>``
+      at Secure EL2.
+   -  Reserved if Secure EL2 not implemented.
+
+-  ``M``:
+
+   -  Bit 26.
+   -  If equal to the ``P`` bit it enables the associated ``PMEVCNTR<n>`` at
+      EL3.
+
+-  ``evtCount[15:10]``:
+
+   -  Extension to ``evtCount[9:0]``. Reserved unless ARMv8.1-PMU implemented.
+
+-  ``evtCount[9:0]``:
+
+   -  The event number that the associated ``PMEVCNTR<n>`` will count.
+
+For ``PMCNTENSET_EL0``/``PMCNTENSET``, the most important fields are:
+
+-  ``P[30:0]``:
+
+   -  Setting bit ``P[n]`` to ``1`` enables counter ``PMEVCNTR<n>``.
+   -  The effects of ``PMEVTYPER<n>`` are applied on top of this.
+      In other words, the counter will not increment at any privilege level or
+      security state unless it is enabled here.
+
+-  ``C``:
+
+   -  Bit 31.
+   -  If set to ``1`` enables the cycle counter ``PMCCNTR``.
+
+For ``PMCR``/``PMCR_EL0``, the most important fields are:
+
+-  ``DP``:
+
+   -  Bit 5.
+   -  If set to ``1`` it disables the cycle counter ``PMCCNTR`` where event
+      counting (by ``PMEVCNTR<n>``) is prohibited (e.g. EL2 and the Secure
+      world).
+   -  If set to ``0``, ``PMCCNTR`` will not be affected by this bit and
+      therefore will be able to count where the programmable counters are
+      prohibited.
+
+-  ``E``:
+
+   -  Bit 0.
+   -  Enables/disables counting altogether.
+   -  The effects of ``PMCNTENSET`` and ``PMCR.DP`` are applied on top of this.
+      In other words, if this bit is ``0`` then no counters will increment
+      regardless of how the other PMU system registers or bit fields are
+      configured.
+
+.. rubric:: References
+
+-  `Arm ARM`_
+
+--------------
+
+*Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.*
+
+.. _Arm ARM: https://developer.arm.com/docs/ddi0487/latest
diff --git a/docs/plat/arm/fvp/index.rst b/docs/plat/arm/fvp/index.rst
index 37010e1..40e9661 100644
--- a/docs/plat/arm/fvp/index.rst
+++ b/docs/plat/arm/fvp/index.rst
@@ -277,15 +277,15 @@
     -C cluster0.NUM_CORES=4                                     \
     -C cluster1.NUM_CORES=4                                     \
     -C cache_state_modelled=1                                   \
-    -C cluster0.cpu0.RVBAR=0x04020000                           \
-    -C cluster0.cpu1.RVBAR=0x04020000                           \
-    -C cluster0.cpu2.RVBAR=0x04020000                           \
-    -C cluster0.cpu3.RVBAR=0x04020000                           \
-    -C cluster1.cpu0.RVBAR=0x04020000                           \
-    -C cluster1.cpu1.RVBAR=0x04020000                           \
-    -C cluster1.cpu2.RVBAR=0x04020000                           \
-    -C cluster1.cpu3.RVBAR=0x04020000                           \
-    --data cluster0.cpu0="<path-to>/bl31.bin"@0x04020000        \
+    -C cluster0.cpu0.RVBAR=0x04001000                           \
+    -C cluster0.cpu1.RVBAR=0x04001000                           \
+    -C cluster0.cpu2.RVBAR=0x04001000                           \
+    -C cluster0.cpu3.RVBAR=0x04001000                           \
+    -C cluster1.cpu0.RVBAR=0x04001000                           \
+    -C cluster1.cpu1.RVBAR=0x04001000                           \
+    -C cluster1.cpu2.RVBAR=0x04001000                           \
+    -C cluster1.cpu3.RVBAR=0x04001000                           \
+    --data cluster0.cpu0="<path-to>/bl31.bin"@0x04001000        \
     --data cluster0.cpu0="<path-to>/<patched-fdt>"@0x82000000   \
     --data cluster0.cpu0="<path-to>/<kernel-binary>"@0x80080000 \
     --data cluster0.cpu0="<path-to>/<ramdisk.img>"@0x84000000
diff --git a/docs/process/security-hardening.rst b/docs/process/security-hardening.rst
index 43a5721..507046f 100644
--- a/docs/process/security-hardening.rst
+++ b/docs/process/security-hardening.rst
@@ -25,6 +25,99 @@
 many normal world requests (a *Denial of Service* or *DoS* attack). It should
 have a mechanism for throttling or ignoring normal world requests.
 
+Preventing Secure-world timing information leakage via PMU counters
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The Secure world needs to implement some defenses to prevent the Non-secure
+world from making it leak timing information. In general, higher privilege
+levels must defend from those below when the PMU is treated as an attack
+vector.
+
+Refer to the :ref:`Performance Monitoring Unit` guide for detailed information
+on the PMU registers.
+
+Timing leakage attacks from the Non-secure world
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Since the Non-secure world has access to the ``PMCR`` register, it can
+configure the PMU to increment counters at any exception level and in both
+Secure and Non-secure state. Thus, it attempts to leak timing information from
+the Secure world.
+
+Shown below is an example of such a configuration:
+
+-  ``PMEVTYPER0_EL0`` and ``PMCCFILTR_EL0``:
+
+   -  Set ``P`` to ``0``.
+   -  Set ``NSK`` to ``1``.
+   -  Set ``M`` to ``0``.
+   -  Set ``NSH`` to ``0``.
+   -  Set ``SH`` to ``1``.
+
+-  ``PMCNTENSET_EL0``:
+
+   -  Set ``P[0]`` to ``1``.
+   -  Set ``C`` to ``1``.
+
+-  ``PMCR_EL0``:
+
+   -  Set ``DP`` to ``0``.
+   -  Set ``E`` to ``1``.
+
+This configuration instructs ``PMEVCNTR0_EL0`` and ``PMCCNTR_EL0`` to increment
+at Secure EL1, Secure EL2 (if implemented) and EL3.
+
+Since the Non-secure world has fine-grained control over where (at which
+exception levels) it instructs counters to increment, obtaining event counts
+would allow it to carry out side-channel timing attacks against the Secure
+world. Examples include Spectre, Meltdown, as well as extracting secrets from
+cryptographic algorithms with data-dependent variations in their execution
+time.
+
+Secure world mitigation strategies
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``MDCR_EL3`` register allows EL3 to configure the PMU (among other things).
+The `Arm ARM`_ details all of the bit fields in this register, but for the PMU
+there are two bits which determine the permissions of the counters:
+
+-  ``SPME`` for the programmable counters.
+-  ``SCCD`` for the cycle counter.
+
+Depending on the implemented features, the Secure world can prohibit counting
+in AArch64 state via the following:
+
+-  ARMv8.2-Debug not implemented:
+
+   -  Prohibit general event counters and the cycle counter:
+      ``MDCR_EL3.SPME == 0 && PMCR_EL0.DP == 1 && !ExternalSecureNoninvasiveDebugEnabled()``.
+
+      -  ``MDCR_EL3.SPME`` resets to ``0``, so by default general events should
+         not be counted in the Secure world.
+      -  The ``PMCR_EL0.DP`` bit therefore needs to be set to ``1`` when EL3 is
+         entered and ``PMCR_EL0`` needs to be saved and restored in EL3.
+      -  ``ExternalSecureNoninvasiveDebugEnabled()`` is an authentication
+         interface which is implementation-defined unless ARMv8.4-Debug is
+         implemented. The `Arm ARM`_ has detailed information on this topic.
+
+   -  The only other way is to disable the ``PMCR_EL0.E`` bit upon entering
+      EL3, which disables counting altogether.
+
+-  ARMv8.2-Debug implemented:
+
+   -  Prohibit general event counters: ``MDCR_EL3.SPME == 0``.
+   -  Prohibit cycle counter: ``MDCR_EL3.SPME == 0 && PMCR_EL0.DP == 1``.
+      ``PMCR_EL0`` therefore needs to be saved and restored in EL3.
+
+-  ARMv8.5-PMU implemented:
+
+   -  Prohibit general event counters: as in ARMv8.2-Debug.
+   -  Prohibit cycle counter: ``MDCR_EL3.SCCD == 1``
+
+In Aarch32 execution state the ``MDCR_EL3`` alias is the ``SDCR`` register,
+which has some of the bit fields of ``MDCR_EL3``, most importantly the ``SPME``
+and ``SCCD`` bits.
+
 Build options
 -------------
 
@@ -71,6 +164,12 @@
   NB: The ``Werror`` flag is enabled by default in TF-A and can be disabled by
   setting the ``E`` build flag to 0.
 
+.. rubric:: References
+
+-  `Arm ARM`_
+
 --------------
 
 *Copyright (c) 2019-2020, Arm Limited. All rights reserved.*
+
+.. _Arm ARM: https://developer.arm.com/docs/ddi0487/latest
diff --git a/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml b/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml
new file mode 100644
index 0000000..c36e544
--- /dev/null
+++ b/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml
@@ -0,0 +1,52 @@
+@startuml
+
+box "BL1 common code"
+	participant bl1_main
+	participant bl_common
+end box
+
+box "arm platform code" #LightBlue
+	participant fvp_bl1_setup
+	participant arm_bl1_setup
+	participant arm_io_storage
+end box
+
+box "platform common code"
+	participant plat_bl1_common
+	participant fconf
+end box
+
+bl1_main -> fvp_bl1_setup : bl1_platform_setup()
+fvp_bl1_setup -> arm_bl1_setup : arm_bl1_platform_setup()
+arm_bl1_setup -> arm_io_storage : plat_arm_io_setup()
+note over arm_io_storage : register and setup fip
+arm_bl1_setup -> fconf : fconf_load_config()
+activate fconf
+	note over fconf
+		create and populate an
+		image_desc_t for TB_FW_CONFIG
+	end note
+	fconf -> bl_common : load_auth_image(TB_FW_CONFIG_ID, &image_info)
+	activate bl_common
+	note over bl_common
+		load and auth image from fip
+		with info from plat_io_policy
+	end note
+	bl_common -> arm_io_storage
+	arm_io_storage -> fconf: FCONF_GET_PROPERTY(arm, arm_io_policies, tb_fw_cfg)
+	note over fconf: use staticaly defined policies in bl1
+	fconf <- bl_common : image_info
+	deactivate bl_common
+	note over fconf : get tb_fw_config_dtb from image_info
+	fconf -> plat_bl1_common : bl1_plat_get_image_desc(BL2_IMAGE_ID)
+	fconf <- plat_bl1_common : BL2_IMAGE_DESC
+	note over fconf
+		set ep_info.args.arg0 of BL2_IMAGE_DESC
+		to TB_FW_CONFIG base address
+	end note
+arm_bl1_setup <- fconf
+deactivate fconf
+
+== load & auth, prepare and jump to BL2 ==
+
+@enduml
diff --git a/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml b/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml
new file mode 100644
index 0000000..98a3ff1
--- /dev/null
+++ b/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml
@@ -0,0 +1,41 @@
+@startuml
+
+box "BL2 common code"
+	participant bl2_entrypoint
+	participant bl2_main
+end box
+
+box "platform common code"
+	participant fconf
+	participant fconf_tbbr_getter
+end box
+
+box "arm platform code" #LightBlue
+	participant arm_bl2_setup
+	participant arm_io_storage
+	participant arm_fconf_io
+end box
+
+== bl2 setup ==
+bl2_entrypoint -> bl2_main : bl2_setup()
+bl2_main -> arm_bl2_setup : bl2_early_platform_setup2(\n\t arg0, arg1, arg2, arg3)
+note over arm_bl2_setup
+	arg0 = tb_fw_config
+	arg1 = mem_layout
+end note
+arm_bl2_setup -> arm_bl2_setup : arm_bl2_early_platform_setup(\n\t tb_fw_config, mem_layout)
+activate arm_bl2_setup
+	arm_bl2_setup -> fconf: fconf_polulate(tb_fw_config)
+	activate fconf
+		fconf -> fconf_tbbr_getter: fconf_populate_tbbr_dyn_config(uintptr_t dtb)
+		note over fconf_tbbr_getter: read tbbr propeties from dtb
+		fconf -> arm_fconf_io: fconf_populate_arm_io_policies(uintptr_t dtb)
+		note over arm_fconf_io: read arm io propeties from dtb
+	deactivate fconf
+	arm_bl2_setup -> arm_io_storage : plat_arm_io_setup()
+	note over arm_io_storage: use populated properties
+deactivate arm_bl2_setup
+
+== bl2 main ==
+
+@enduml
diff --git a/drivers/auth/auth_mod.c b/drivers/auth/auth_mod.c
index 3fb2d1a..91ee1be 100644
--- a/drivers/auth/auth_mod.c
+++ b/drivers/auth/auth_mod.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,6 +16,7 @@
 #include <drivers/auth/auth_mod.h>
 #include <drivers/auth/crypto_mod.h>
 #include <drivers/auth/img_parser_mod.h>
+#include <lib/fconf/fconf_tbbr_getter.h>
 #include <plat/common/platform.h>
 
 /* ASN.1 tags */
@@ -302,9 +303,8 @@
 	const auth_img_desc_t *img_desc = NULL;
 
 	assert(parent_id != NULL);
-
 	/* Get the image descriptor */
-	img_desc = cot_desc_ptr[img_id];
+	img_desc = FCONF_GET_PROPERTY(tbbr, cot, img_id);
 
 	/* Check if the image has no parent (ROT) */
 	if (img_desc->parent == NULL) {
@@ -353,7 +353,7 @@
 	int rc, i;
 
 	/* Get the image descriptor from the chain of trust */
-	img_desc = cot_desc_ptr[img_id];
+	img_desc = FCONF_GET_PROPERTY(tbbr, cot, img_id);
 
 	/* Ask the parser to check the image integrity */
 	rc = img_parser_check_integrity(img_desc->img_type, img_ptr, img_len);
diff --git a/drivers/auth/tbbr/tbbr_cot.c b/drivers/auth/tbbr/tbbr_cot.c
index 6dd4ae2..6f00b18 100644
--- a/drivers/auth/tbbr/tbbr_cot.c
+++ b/drivers/auth/tbbr/tbbr_cot.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,7 +18,12 @@
 
 
 /*
- * Maximum key and hash sizes (in DER format)
+ * Maximum key and hash sizes (in DER format).
+ *
+ * Both RSA and ECDSA keys may be used at the same time. In this case, the key
+ * buffers must be big enough to hold either. As RSA keys are bigger than ECDSA
+ * ones for all key sizes we support, they impose the minimum size of these
+ * buffers.
  */
 #if TF_MBEDTLS_USE_RSA
 #if TF_MBEDTLS_KEY_SIZE == 1024
@@ -32,11 +37,19 @@
 #else
 #error "Invalid value for TF_MBEDTLS_KEY_SIZE"
 #endif
-#else
-#define PK_DER_LEN			294
+#else /* Only using ECDSA keys. */
+#define PK_DER_LEN			91
 #endif
 
+#if TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA256
+#define HASH_DER_LEN			51
+#elif TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA384
+#define HASH_DER_LEN			67
+#elif TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA512
 #define HASH_DER_LEN			83
+#else
+#error "Invalid value for TF_MBEDTLS_HASH_ALG_ID"
+#endif
 
 /*
  * The platform must allocate buffers to store the authentication parameters
diff --git a/drivers/cfi/v2m/v2m_flash.c b/drivers/cfi/v2m/v2m_flash.c
index aadafbc..6690189 100644
--- a/drivers/cfi/v2m/v2m_flash.c
+++ b/drivers/cfi/v2m/v2m_flash.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -27,7 +27,7 @@
 #define DWS_WORD_LOCK_RETRIES		1000
 
 /* Helper macro to detect end of command */
-#define NOR_CMD_END (NOR_DWS | NOR_DWS << 16l)
+#define NOR_CMD_END (NOR_DWS | (NOR_DWS << 16l))
 
 /* Helper macros to access two flash banks in parallel */
 #define NOR_2X16(d)			((d << 16) | (d & 0xffff))
diff --git a/drivers/marvell/mochi/cp110_setup.c b/drivers/marvell/mochi/cp110_setup.c
index b4b4e0c..7186f98 100644
--- a/drivers/marvell/mochi/cp110_setup.c
+++ b/drivers/marvell/mochi/cp110_setup.c
@@ -303,7 +303,7 @@
 			      DOMAIN_SYSTEM_SHAREABLE);
 }
 
-static void amb_bridge_init(uintptr_t base)
+void cp110_amb_init(uintptr_t base)
 {
 	uint32_t reg;
 
@@ -399,7 +399,7 @@
 	cp110_stream_id_init(cp110_base, stream_id);
 
 	/* Open AMB bridge for comphy for CP0 & CP1*/
-	amb_bridge_init(cp110_base);
+	cp110_amb_init(cp110_base);
 
 	/* Reset RTC if needed */
 	cp110_rtc_init(cp110_base);
@@ -411,7 +411,7 @@
 #if PCI_EP_SUPPORT
 	INFO("%s: Initialize CPx - base = %lx\n", __func__, cp110_base);
 
-	amb_bridge_init(cp110_base);
+	cp110_amb_init(cp110_base);
 
 	/* Configure PCIe clock */
 	cp110_pcie_clk_cfg(cp110_base);
diff --git a/drivers/renesas/rcar/board/board.c b/drivers/renesas/rcar/board/board.c
index df17802..cd194ff 100644
--- a/drivers/renesas/rcar/board/board.c
+++ b/drivers/renesas/rcar/board/board.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights
+ * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights
  * reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -33,7 +33,7 @@
 #define SXS_ID	{ 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
 #define SX_ID	{ 0x10U, 0x11U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
 #define SKP_ID	{ 0x10U, 0x10U, 0x20U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
-#define SK_ID	{ 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
+#define SK_ID	{ 0x10U, 0x30U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
 #define EB4_ID	{ 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
 #define EB_ID	{ 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
 #define DR_ID	{ 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
diff --git a/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram.c b/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram.c
index 1d6e83a..ac83c9a 100644
--- a/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram.c
+++ b/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, Renesas Electronics Corporation.
+ * Copyright (c) 2015-2020, Renesas Electronics Corporation.
  * All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -510,6 +510,14 @@
 	dsb_sev();
 }
 
+static void dbwait_loop(uint32_t wait_loop)
+{
+	uint32_t i;
+
+	for (i = 0; i < wait_loop; i++)
+		wait_dbcmd();
+}
+
 /* DDRPHY register access (raw) */
 static uint32_t reg_ddrphy_read(uint32_t phyno, uint32_t regadd)
 {
@@ -866,6 +874,7 @@
 	uint8_t WL;
 	uint8_t nwr;
 	uint8_t nrtp;
+	uint8_t odtlon;
 	uint8_t MR1;
 	uint8_t MR2;
 };
@@ -877,21 +886,21 @@
 #define JS1_MR2(f) (0x00 | ((f) << 3) | (f))
 const struct _jedec_spec1 js1[JS1_FREQ_TBL_NUM] = {
 	/* 533.333Mbps */
-	{  800,  6,  6,  4,  6,  8, JS1_MR1(0), JS1_MR2(0) | 0x40 },
+	{  800,  6,  6,  4,  6,  8, 0, JS1_MR1(0), JS1_MR2(0) | 0x40 },
 	/* 1066.666Mbps */
-	{ 1600, 10, 12,  8, 10,  8, JS1_MR1(1), JS1_MR2(1) | 0x40 },
+	{ 1600, 10, 12,  8, 10,  8, 0, JS1_MR1(1), JS1_MR2(1) | 0x40 },
 	/* 1600.000Mbps */
-	{ 2400, 14, 16, 12, 16,  8, JS1_MR1(2), JS1_MR2(2) | 0x40 },
+	{ 2400, 14, 16, 12, 16,  8, 6, JS1_MR1(2), JS1_MR2(2) | 0x40 },
 	/* 2133.333Mbps */
-	{ 3200, 20, 22, 10, 20,  8, JS1_MR1(3), JS1_MR2(3) },
+	{ 3200, 20, 22, 10, 20,  8, 4, JS1_MR1(3), JS1_MR2(3) },
 	/* 2666.666Mbps */
-	{ 4000, 24, 28, 12, 24, 10, JS1_MR1(4), JS1_MR2(4) },
+	{ 4000, 24, 28, 12, 24, 10, 4, JS1_MR1(4), JS1_MR2(4) },
 	/* 3200.000Mbps */
-	{ 4800, 28, 32, 14, 30, 12, JS1_MR1(5), JS1_MR2(5) },
+	{ 4800, 28, 32, 14, 30, 12, 6, JS1_MR1(5), JS1_MR2(5) },
 	/* 3733.333Mbps */
-	{ 5600, 32, 36, 16, 34, 14, JS1_MR1(6), JS1_MR2(6) },
+	{ 5600, 32, 36, 16, 34, 14, 6, JS1_MR1(6), JS1_MR2(6) },
 	/* 4266.666Mbps */
-	{ 6400, 36, 40, 18, 40, 16, JS1_MR1(7), JS1_MR2(7) }
+	{ 6400, 36, 40, 18, 40, 16, 8, JS1_MR1(7), JS1_MR2(7) }
 };
 
 struct _jedec_spec2 {
@@ -921,7 +930,8 @@
 #define js2_tzqcalns 19
 #define js2_tzqlat 20
 #define js2_tiedly 21
-#define JS2_TBLCNT 22
+#define js2_tODTon_min 22
+#define JS2_TBLCNT 23
 
 #define js2_trcpb (JS2_TBLCNT)
 #define js2_trcab (JS2_TBLCNT + 1)
@@ -954,7 +964,8 @@
 /*tMRD*/ {14000, 10},
 /*tZQCALns*/ {1000 * 10, 0},
 /*tZQLAT*/ {30000, 10},
-/*tIEdly*/ {12500, 0}
+/*tIEdly*/ {12500, 0},
+/*tODTon_min*/ {1500, 0}
 	 }, {
 /*tSR   */ {15000, 3},
 /*tXP   */ {7500, 3},
@@ -977,7 +988,8 @@
 /*tMRD*/ {14000, 10},
 /*tZQCALns*/ {1000 * 10, 0},
 /*tZQLAT*/ {30000, 10},
-/*tIEdly*/ {12500, 0}
+/*tIEdly*/ {12500, 0},
+/*tODTon_min*/ {1500, 0}
 	}
 };
 
@@ -1452,7 +1464,7 @@
 	if ((prr_product == PRR_PRODUCT_M3N) ||
 	    (prr_product == PRR_PRODUCT_V3H)) {
 		ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET,
-			      _reg_PHY_RDDATA_EN_OE_DLY, dataS);
+			      _reg_PHY_RDDATA_EN_OE_DLY, dataS - 2);
 	}
 	ddrtbl_setval(_cnf_DDR_PI_REGSET, _reg_PI_RDLAT_ADJ_F1, RL - dataS);
 
@@ -1498,9 +1510,10 @@
 
 	/* DDRPHY INT START */
 	if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
-		/*  non */
+		/* non */
 	} else {
 		regif_pll_wa();
+		dbwait_loop(5);
 	}
 
 	/* FREQ_SEL_MULTICAST & PER_CS_TRAINING_MULTICAST SET (for safety) */
@@ -2067,12 +2080,18 @@
 	/* DBTR9.TRDPR : tRTP */
 	mmio_write_32(DBSC_DBTR(9), js2[js2_trtp]);
 
-	/* DBTR10.TWR : nwr */
+	/* DBTR10.TWR : nWR */
 	mmio_write_32(DBSC_DBTR(10), js1[js1_ind].nwr);
 
-	/* DBTR11.TRDWR : RL + tDQSCK + BL/2 + Rounddown(tRPST) - WL + tWPRE */
+	/*
+	 * DBTR11.TRDWR : RL +  BL / 2 + Rounddown(tRPST) + PHY_ODTLoff -
+	 * 		  odtlon + tDQSCK - tODTon,min +
+	 * 		  PCB delay (out+in) + tPHY_ODToff
+	 */
 	mmio_write_32(DBSC_DBTR(11),
-		      RL + js2[js2_tdqsck] + (16 / 2) + 1 - WL + 2 + 2);
+		      RL + (16 / 2) + 1 + 2 - js1[js1_ind].odtlon +
+		      js2[js2_tdqsck] - js2[js2_tODTon_min] +
+		      _f_scale(ddr_mbps, ddr_mbpsdiv, 1300, 0));
 
 	/* DBTR12.TWRRD : WL + 1 + BL/2 + tWTR */
 	data_l = WL + 1 + (16 / 2) + js2[js2_twtr];
@@ -2338,10 +2357,23 @@
 		}
 	}
 	if ((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) {
+#if RCAR_DRAM_SPLIT == 2
+		if (board_cnf->phyvalid == 0x05) {
+			mmio_write_32(DBSC_DBTR(24),
+				      (rdlat_max << 24) + (rdlat_min << 16) +
+				      mmio_read_32(DBSC_DBTR(24)));
+		} else {
+			mmio_write_32(DBSC_DBTR(24),
+				      ((rdlat_max * 2 - rdlat_min + 4) << 24) +
+				      ((rdlat_min + 2) << 16) +
+				      mmio_read_32(DBSC_DBTR(24)));
+		}
+#else /*RCAR_DRAM_SPLIT == 2 */
 		mmio_write_32(DBSC_DBTR(24),
 			      ((rdlat_max * 2 - rdlat_min + 4) << 24) +
 			      ((rdlat_min + 2) << 16) +
 			      mmio_read_32(DBSC_DBTR(24)));
+#endif /*RCAR_DRAM_SPLIT == 2 */
 	} else {
 		mmio_write_32(DBSC_DBTR(24),
 			      ((rdlat_max + 2) << 24) +
@@ -2383,37 +2415,6 @@
 	mmio_write_32(DBSC_DBRFCNF1, 0x00080000 | (data_l & 0x0000ffff));
 	mmio_write_32(DBSC_DBRFCNF2, 0x00010000 | DBSC_REFINTS);
 
-#ifdef DDR_BACKUPMODE
-	if (ddr_backup == DRAM_BOOT_STATUS_WARM) {
-#ifdef DDR_BACKUPMODE_HALF	/* for Half channel(ch0,1 only) */
-		DEBUG(" DEBUG_MESS : DDR_BACKUPMODE_HALF ", 1);
-		send_dbcmd(0x08040001);
-		wait_dbcmd();
-		send_dbcmd(0x0A040001);
-		wait_dbcmd();
-		send_dbcmd(0x04040010);
-		wait_dbcmd();
-
-		if (prr_product == PRR_PRODUCT_H3) {
-			send_dbcmd(0x08140001);
-			wait_dbcmd();
-			send_dbcmd(0x0A140001);
-			wait_dbcmd();
-			send_dbcmd(0x04140010);
-			wait_dbcmd();
-		}
-#else /* DDR_BACKUPMODE_HALF                              //for All channels */
-		send_dbcmd(0x08840001);
-		wait_dbcmd();
-		send_dbcmd(0x0A840001);
-		wait_dbcmd();
-
-		send_dbcmd(0x04840010);
-		wait_dbcmd();
-#endif /* DDR_BACKUPMODE_HALF */
-	}
-#endif /* DDR_BACKUPMODE */
-
 #if RCAR_REWT_TRAINING != 0
 	/* Periodic-WriteDQ Training seeting */
 	if (((prr_product == PRR_PRODUCT_H3) &&
@@ -2422,12 +2423,7 @@
 	     (prr_cut == PRR_PRODUCT_10))) {
 		/* non : H3 Ver.1.x/M3-W Ver.1.0 not support */
 	} else {
-		/*
-		 * H3 Ver.2.0 or later/M3-W Ver.1.1 or
-		 * later/M3-N/V3H -> Periodic-WriteDQ Training seeting
-		 */
-
-		/* Periodic WriteDQ Training seeting */
+		/* H3 Ver.2.0 or later/M3-W Ver.1.1 or later/M3-N/V3H */
 		mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000000);
 
 		ddr_setval_ach_as(_reg_PHY_WDQLVL_PATT, 0x04);
@@ -2440,7 +2436,6 @@
 					     _reg_PI_WDQLVL_CS_MAP));
 		ddr_setval_ach(_reg_PI_LONG_COUNT_MASK, 0x1f);
 		ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x00);
-		ddr_setval_ach(_reg_PI_WDQLVL_INTERVAL, 0x0100);
 		ddr_setval_ach(_reg_PI_WDQLVL_ROTATE, 0x01);
 		ddr_setval_ach(_reg_PI_TREF_F0, 0x0000);
 		ddr_setval_ach(_reg_PI_TREF_F1, 0x0000);
@@ -2458,8 +2453,10 @@
 		mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000011);
 	}
 #endif /* RCAR_REWT_TRAINING */
-	/* periodic dram zqcal and phy ctrl update enable */
+	/* periodic dram zqcal enable */
 	mmio_write_32(DBSC_DBCALCNF, 0x01000010);
+
+	/* periodic phy ctrl update enable */
 	if (((prr_product == PRR_PRODUCT_H3) &&
 	     (prr_cut <= PRR_PRODUCT_11)) ||
 	    ((prr_product == PRR_PRODUCT_M3) &&
@@ -2477,7 +2474,36 @@
 #endif /* RCAR_DRAM_SPLIT == 2 */
 	}
 
+#ifdef DDR_BACKUPMODE
+	/* SRX */
+	if (ddr_backup == DRAM_BOOT_STATUS_WARM) {
+#ifdef DDR_BACKUPMODE_HALF		/* for Half channel(ch0, 1 only) */
+		NOTICE("BL2: [DEBUG_MESS] DDR_BACKUPMODE_HALF\n");
+		send_dbcmd(0x0A040001);
+		if (Prr_Product == PRR_PRODUCT_H3)
+			send_dbcmd(0x0A140001);
+#else /* DDR_BACKUPMODE_HALF */		/* for All channels */
+		send_dbcmd(0x0A840001);
+#endif /* DDR_BACKUPMODE_HALF */
+	}
+#endif /* DDR_BACKUPMODE */
+
+	/* set Auto Refresh */
 	mmio_write_32(DBSC_DBRFEN, 0x00000001);
+
+#if RCAR_REWT_TRAINING != 0
+	/* Periodic WriteDQ Traning */
+	if (((prr_product == PRR_PRODUCT_H3) &&
+	     (prr_cut <= PRR_PRODUCT_11)) ||
+	    ((prr_product == PRR_PRODUCT_M3) &&
+	     (prr_cut == PRR_PRODUCT_10))) {
+		/* non : H3 Ver.1.x/M3-W Ver.1.0 not support */
+	} else {
+		/* H3 Ver.2.0 or later/M3-W Ver.1.1 or later/M3-N/V3H */
+		ddr_setval_ach(_reg_PI_WDQLVL_INTERVAL, 0x0100);
+	}
+#endif /* RCAR_REWT_TRAINING */
+
 	/* dram access enable */
 	mmio_write_32(DBSC_DBACEN, 0x00000001);
 
@@ -3026,6 +3052,9 @@
 		return INITDRAM_ERR_O;
 	MSG_LF(__func__ ":5\n");
 
+	/* Dummy PDE */
+	send_dbcmd(0x08840000);
+
 	/* PDX */
 	send_dbcmd(0x08840001);
 
@@ -3477,10 +3506,13 @@
 {
 	uint32_t err, retry_cnt;
 	const uint32_t retry_max = 0x10;
-	uint32_t ch, ddr_csn, mr14_bkup[4][4];
+	uint32_t datal, ch, ddr_csn, mr14_bkup[4][4];
+
+	datal = RL + js2[js2_tdqsck] + (16 / 2) + 1 - WL + 2 + 2 + 19;
+	if ((mmio_read_32(DBSC_DBTR(11)) & 0xFF) > datal)
+		datal = mmio_read_32(DBSC_DBTR(11)) & 0xFF;
+	ddr_setval_ach(_reg_PI_TDFI_WDQLVL_RW, datal);
 
-	ddr_setval_ach(_reg_PI_TDFI_WDQLVL_RW,
-		       (mmio_read_32(DBSC_DBTR(11)) & 0xFF) + 19);
 	if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) ||
 	    (prr_product == PRR_PRODUCT_M3N) ||
 	    (prr_product == PRR_PRODUCT_V3H)) {
diff --git a/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram_config.c b/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram_config.c
index f8caade..de126de 100644
--- a/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram_config.c
+++ b/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram_config.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, Renesas Electronics Corporation.
+ * Copyright (c) 2015-2020, Renesas Electronics Corporation.
  * All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -1571,8 +1571,13 @@
 {
 	uint32_t md;
 
-	md = (mmio_read_32(RST_MODEMR) >> 17) & 0x5;
-	md = (md | (md >> 1)) & 0x3;
+	if (prr_product == PRR_PRODUCT_V3H) {
+		md = (mmio_read_32(RST_MODEMR) >> 19) & 0x1;
+		md = (md | (md << 1)) & 0x3; /* 0 or 3 */
+	} else {
+		md = (mmio_read_32(RST_MODEMR) >> 17) & 0x5;
+		md = (md | (md >> 1)) & 0x3;
+	}
 	switch (md) {
 	case 0x0:
 		*mbps = 3200;
@@ -1722,8 +1727,13 @@
 #endif
 		}
 	} else if (prr_product == PRR_PRODUCT_M3) {
-		/* RENESAS Starter Kit(M3-W/SIP 8Gbit 1rank) board */
-		brd = 3;
+		if (prr_cut >= PRR_PRODUCT_30) {
+			/* RENESAS Starter Kit (M3-W Ver.3.0/SIP) */
+			brd = 18;
+		} else {
+			/* RENESAS Starter Kit(M3-W/SIP 8Gbit 1rank) board */
+			brd = 3;
+		}
 	} else {
 		/* RENESAS Starter Kit(M3-N/SIP) board */
 		brd = 11;
diff --git a/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram_regdef.h b/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram_regdef.h
index 5047e5c..56363eb 100644
--- a/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram_regdef.h
+++ b/drivers/renesas/rcar/ddr/ddr_b/boot_init_dram_regdef.h
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2015-2019, Renesas Electronics Corporation.
+ * Copyright (c) 2015-2020, Renesas Electronics Corporation.
  * All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#define RCAR_DDR_VERSION	"rev.0.37"
+#define RCAR_DDR_VERSION	"rev.0.40"
 #define DRAM_CH_CNT		0x04
 #define SLICE_CNT		0x04
 #define CS_CNT			0x02
@@ -22,7 +22,7 @@
 
 /* for ddr deisity setting */
 #define DBMEMCONF_REG(d3, row, bank, col, dw)	\
-	((d3) << 30 | ((row) << 24) | ((bank) << 16) | ((col) << 8) | (dw))
+	(((d3) << 30) | ((row) << 24) | ((bank) << 16) | ((col) << 8) | (dw))
 
 #define DBMEMCONF_REGD(density)		\
 	(DBMEMCONF_REG((density) % 2, ((density) + 1) / \
diff --git a/drivers/renesas/rcar/ddr/ddr_b/init_dram_tbl_m3n.h b/drivers/renesas/rcar/ddr/ddr_b/init_dram_tbl_m3n.h
index 8d80842..fb3032d 100644
--- a/drivers/renesas/rcar/ddr/ddr_b/init_dram_tbl_m3n.h
+++ b/drivers/renesas/rcar/ddr/ddr_b/init_dram_tbl_m3n.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, Renesas Electronics Corporation.
+ * Copyright (c) 2015-2020, Renesas Electronics Corporation.
  * All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -116,7 +116,7 @@
 	/*0859*/ 0x00000200,
 	/*085a*/ 0x00000004,
 	/*085b*/ 0x4041a151,
-	/*085c*/ 0x0141c0a0,
+	/*085c*/ 0x0141a0a0,
 	/*085d*/ 0x0000c0c0,
 	/*085e*/ 0x0e0c000e,
 	/*085f*/ 0x10001000,
diff --git a/fdts/corstone700.dts b/fdts/corstone700.dts
index 16cf412..c13d3b2 100644
--- a/fdts/corstone700.dts
+++ b/fdts/corstone700.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,9 +14,10 @@
 	#size-cells = <1>;
 
 	chosen {
-		bootargs = "console=ttyAMA0 root=/dev/vda2 rw loglevel=9";
-		linux,initrd-start = <0x02a00000>;
-		linux,initrd-end = <0x04000000>;
+		bootargs = "console=ttyAMA0 \
+		root=mtd:physmap-flash.0 \
+		ro \
+		loglevel=9";
 	};
 
 	cpus {
@@ -32,9 +33,9 @@
 
 	};
 
-	memory@2000000 {
+	memory@80000000 {
 		device_type = "memory";
-		reg = <0x02000000 0x02000000>;
+		reg = <0x80000000 0x80000000>;
 	};
 
 	gic: interrupt-controller@1c000000 {
@@ -68,14 +69,21 @@
 		clock-output-names = "smclk";
 	};
 
+	uartclk: uartclk {
+		/* UART clock - 32MHz */
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32000000>;
+		clock-output-names = "uartclk";
+	};
 
 	serial0: uart@1a510000 {
 		compatible = "arm,pl011", "arm,primecell";
 		reg = <0x1a510000 0x1000>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 19 4>;
-		clocks = <&refclk100mhz>, <&smbclk>;
-		clock-names = "apb_pclk", "smclk";
+		clocks = <&uartclk>, <&refclk100mhz>;
+		clock-names = "uartclk", "apb_pclk";
 	};
 
 	serial1: uart@1a520000 {
@@ -83,8 +91,8 @@
 		reg = <0x1a520000 0x1000>;
 		interrupt-parent = <&gic>;
 		interrupts = <0 20 4>;
-		clocks = <&refclk100mhz>, <&smbclk>;
-		clock-names = "apb_pclk", "smclk";
+		clocks = <&uartclk>, <&refclk100mhz>;
+		clock-names = "uartclk", "apb_pclk";
 	};
 
 	timer {
diff --git a/fdts/fvp-base-gicv3-psci-common.dtsi b/fdts/fvp-base-gicv3-psci-common.dtsi
index 94ed67d..5b0470d 100644
--- a/fdts/fvp-base-gicv3-psci-common.dtsi
+++ b/fdts/fvp-base-gicv3-psci-common.dtsi
@@ -39,7 +39,7 @@
 		#address-cells = <2>;
 		#size-cells = <0>;
 
-		cpu-map {
+		CPU_MAP:cpu-map {
 			cluster0 {
 				core0 {
 					cpu = <&CPU0>;
diff --git a/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts b/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts
index 48269a0..daa2e66 100644
--- a/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts
+++ b/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts
@@ -6,7 +6,7 @@
 
 /dts-v1/;
 
-#include "fvp-base-gicv3-psci-common.dtsi"
+#include "fvp-base-gicv3-psci-dynamiq-common.dtsi"
 
 &CPU0 {
 	reg = <0x0 0x0>;
diff --git a/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi b/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi
new file mode 100644
index 0000000..f3f7684
--- /dev/null
+++ b/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+#include "fvp-base-gicv3-psci-common.dtsi"
+
+/* DynamIQ based designs have upto 8 CPUs in each cluster */
+
+&CPU_MAP {
+	cluster0 {
+		core0 {
+			cpu = <&CPU0>;
+		};
+		core1 {
+			cpu = <&CPU1>;
+		};
+		core2 {
+			cpu = <&CPU2>;
+		};
+		core3 {
+			cpu = <&CPU3>;
+		};
+		core4 {
+			cpu = <&CPU4>;
+		};
+		core5 {
+			cpu = <&CPU5>;
+		};
+		core6 {
+			cpu = <&CPU6>;
+		};
+		core7 {
+			cpu = <&CPU7>;
+		};
+	};
+};
diff --git a/fdts/fvp-base-gicv3-psci-dynamiq.dts b/fdts/fvp-base-gicv3-psci-dynamiq.dts
index 51c7aca..b8b0445 100644
--- a/fdts/fvp-base-gicv3-psci-dynamiq.dts
+++ b/fdts/fvp-base-gicv3-psci-dynamiq.dts
@@ -6,7 +6,7 @@
 
 /dts-v1/;
 
-#include "fvp-base-gicv3-psci-common.dtsi"
+#include "fvp-base-gicv3-psci-dynamiq-common.dtsi"
 
 &CPU0 {
 	reg = <0x0 0x0>;
diff --git a/include/bl1/bl1.h b/include/bl1/bl1.h
index d81f434..e6447f2 100644
--- a/include/bl1/bl1.h
+++ b/include/bl1/bl1.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -67,16 +67,16 @@
 
 struct entry_point_info;
 
-register_t bl1_smc_wrapper(uint32_t smc_fid,
+u_register_t bl1_smc_wrapper(uint32_t smc_fid,
 	void *cookie,
 	void *handle,
 	unsigned int flags);
 
-register_t bl1_smc_handler(unsigned int smc_fid,
-	register_t x1,
-	register_t x2,
-	register_t x3,
-	register_t x4,
+u_register_t bl1_smc_handler(unsigned int smc_fid,
+	u_register_t x1,
+	u_register_t x2,
+	u_register_t x3,
+	u_register_t x4,
 	void *cookie,
 	void *handle,
 	unsigned int flags);
diff --git a/include/drivers/io/io_storage.h b/include/drivers/io/io_storage.h
index 0e6ffd6..a301ad5 100644
--- a/include/drivers/io/io_storage.h
+++ b/include/drivers/io/io_storage.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -53,7 +53,7 @@
 /* UUID specification - used to refer to data accessed using UUIDs (i.e. FIP
  * images) */
 typedef struct io_uuid_spec {
-	const uuid_t uuid;
+	uuid_t uuid;
 } io_uuid_spec_t;
 
 /* Block specification - used to refer to data on a device supporting
diff --git a/include/drivers/marvell/mochi/cp110_setup.h b/include/drivers/marvell/mochi/cp110_setup.h
index 3686257..f8cd26b 100644
--- a/include/drivers/marvell/mochi/cp110_setup.h
+++ b/include/drivers/marvell/mochi/cp110_setup.h
@@ -51,5 +51,6 @@
 
 void cp110_init(uintptr_t cp110_base, uint32_t stream_id);
 void cp110_ble_init(uintptr_t cp110_base);
+void cp110_amb_init(uintptr_t base);
 
 #endif /* CP110_SETUP_H */
diff --git a/include/lib/el3_runtime/aarch32/context.h b/include/lib/el3_runtime/aarch32/context.h
index c5567c9..5604c8e 100644
--- a/include/lib/el3_runtime/aarch32/context.h
+++ b/include/lib/el3_runtime/aarch32/context.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -37,7 +37,7 @@
 #define WORD_SHIFT		U(2)
 #define DEFINE_REG_STRUCT(name, num_regs)	\
 	typedef struct name {			\
-		uint32_t _regs[num_regs];	\
+		uint32_t ctx_regs[num_regs];	\
 	}  __aligned(8) name##_t
 
 /* Constants to determine the size of individual context structures */
@@ -47,8 +47,8 @@
 
 #undef CTX_REG_ALL
 
-#define read_ctx_reg(ctx, offset)	((ctx)->_regs[offset >> WORD_SHIFT])
-#define write_ctx_reg(ctx, offset, val)	(((ctx)->_regs[offset >> WORD_SHIFT]) \
+#define read_ctx_reg(ctx, offset)	((ctx)->ctx_regs[offset >> WORD_SHIFT])
+#define write_ctx_reg(ctx, offset, val)	(((ctx)->ctx_regs[offset >> WORD_SHIFT]) \
 					 = val)
 typedef struct cpu_context {
 	regs_t regs_ctx;
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index 7a1f3a3..4158c02 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -230,7 +230,7 @@
 #define DWORD_SHIFT		U(3)
 #define DEFINE_REG_STRUCT(name, num_regs)	\
 	typedef struct name {			\
-		uint64_t _regs[num_regs];	\
+		uint64_t ctx_regs[num_regs];	\
 	}  __aligned(16) name##_t
 
 /* Constants to determine the size of individual context structures */
@@ -288,8 +288,8 @@
  * Macros to access members of any of the above structures using their
  * offsets
  */
-#define read_ctx_reg(ctx, offset)	((ctx)->_regs[(offset) >> DWORD_SHIFT])
-#define write_ctx_reg(ctx, offset, val)	(((ctx)->_regs[(offset) >> DWORD_SHIFT]) \
+#define read_ctx_reg(ctx, offset)	((ctx)->ctx_regs[(offset) >> DWORD_SHIFT])
+#define write_ctx_reg(ctx, offset, val)	(((ctx)->ctx_regs[(offset) >> DWORD_SHIFT]) \
 					 = (uint64_t) (val))
 
 /*
diff --git a/include/lib/fconf/fconf.h b/include/lib/fconf/fconf.h
new file mode 100644
index 0000000..f58ff57
--- /dev/null
+++ b/include/lib/fconf/fconf.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FCONF_H
+#define FCONF_H
+
+#include <stdint.h>
+
+/* Public API */
+#define FCONF_GET_PROPERTY(a, b, c)	a##__##b##_getter(c)
+
+#define FCONF_REGISTER_POPULATOR(name, callback)				\
+	__attribute__((used, section(".fconf_populator")))			\
+	const struct fconf_populator name##__populator = {			\
+		.info = #name,							\
+		.populate = callback						\
+	};
+
+/*
+ * Populator callback
+ *
+ * This structure are used by the fconf_populate function and should only be
+ * defined by the FCONF_REGISTER_POPULATOR macro.
+ */
+struct fconf_populator {
+	/* Description of the data loaded by the callback */
+	const char *info;
+
+	/* Callback used by fconf_populate function with a provided config dtb.
+	 * Return 0 on success, err_code < 0 otherwise.
+	 */
+	int (*populate)(uintptr_t config);
+};
+
+/* Load firmware configuration dtb */
+void fconf_load_config(void);
+
+/* Top level populate function
+ *
+ * This function takes a configuration dtb and calls all the registered
+ * populator callback with it.
+ *
+ *  Panic on error.
+ */
+void fconf_populate(uintptr_t config);
+
+/* FCONF specific getter */
+#define fconf__dtb_getter(prop)	fconf_dtb_info.prop
+
+/* Structure used to locally keep a reference to the config dtb. */
+struct fconf_dtb_info_t {
+	uintptr_t base_addr;
+	size_t size;
+};
+
+extern struct fconf_dtb_info_t fconf_dtb_info;
+
+#endif /* FCONF_H */
diff --git a/include/lib/fconf/fconf_dyn_cfg_getter.h b/include/lib/fconf/fconf_dyn_cfg_getter.h
new file mode 100644
index 0000000..0fda8c9
--- /dev/null
+++ b/include/lib/fconf/fconf_dyn_cfg_getter.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FCONF_DYN_CFG_GETTER_H
+#define FCONF_DYN_CFG_GETTER_H
+
+#include <lib/fconf/fconf.h>
+
+/* Dynamic configuration related getter */
+#define dyn_cfg__dtb_getter(id)	dyn_cfg_dtb_info_getter(id)
+
+struct dyn_cfg_dtb_info_t {
+	uintptr_t config_addr;
+	size_t config_max_size;
+	unsigned int config_id;
+};
+
+struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id);
+int fconf_populate_dtb_registry(uintptr_t config);
+
+#endif /* FCONF_DYN_CFG_GETTER_H */
diff --git a/include/lib/fconf/fconf_tbbr_getter.h b/include/lib/fconf/fconf_tbbr_getter.h
new file mode 100644
index 0000000..eddc0c4
--- /dev/null
+++ b/include/lib/fconf/fconf_tbbr_getter.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FCONF_TBBR_GETTER_H
+#define FCONF_TBBR_GETTER_H
+
+#include <lib/fconf/fconf.h>
+
+/* TBBR related getter */
+#define tbbr__cot_getter(id)	cot_desc_ptr[id]
+
+#define tbbr__dyn_config_getter(id)	tbbr_dyn_config.id
+
+struct tbbr_dyn_config_t {
+	uint32_t disable_auth;
+	void *mbedtls_heap_addr;
+	size_t mbedtls_heap_size;
+};
+
+extern struct tbbr_dyn_config_t tbbr_dyn_config;
+
+int fconf_populate_tbbr_dyn_config(uintptr_t config);
+
+#endif /* FCONF_TBBR_GETTER_H */
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index c825bf4..7df6b0d 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -229,6 +229,14 @@
 						ARM_EL3_TZC_DRAM1_SIZE,	\
 						MT_MEMORY | MT_RW | MT_SECURE)
 
+#if defined(SPD_spmd)
+#define ARM_MAP_TRUSTED_DRAM		MAP_REGION_FLAT(		    \
+						PLAT_ARM_TRUSTED_DRAM_BASE, \
+						PLAT_ARM_TRUSTED_DRAM_SIZE, \
+						MT_MEMORY | MT_RW | MT_SECURE)
+#endif
+
+
 /*
  * Mapping for the BL1 RW region. This mapping is needed by BL2 in order to
  * share the Mbed TLS heap. Since the heap is allocated inside BL1, it resides
@@ -477,6 +485,12 @@
 #  define BL32_BASE			(ARM_AP_TZC_DRAM1_BASE + ULL(0x200000))
 #  define BL32_LIMIT			(ARM_AP_TZC_DRAM1_BASE +	\
 						ARM_AP_TZC_DRAM1_SIZE)
+# elif defined(SPD_spmd)
+#  define TSP_SEC_MEM_BASE		(ARM_AP_TZC_DRAM1_BASE + ULL(0x200000))
+#  define TSP_SEC_MEM_SIZE		(ARM_AP_TZC_DRAM1_SIZE - ULL(0x200000))
+#  define BL32_BASE			PLAT_ARM_TRUSTED_DRAM_BASE
+#  define BL32_LIMIT			(PLAT_ARM_TRUSTED_DRAM_BASE	\
+						+ (UL(1) << 21))
 # elif ARM_BL31_IN_DRAM
 #  define TSP_SEC_MEM_BASE		(ARM_AP_TZC_DRAM1_BASE +	\
 						PLAT_ARM_MAX_BL31_SIZE)
@@ -511,12 +525,12 @@
 
 /*
  * BL32 is mandatory in AArch32. In AArch64, undefine BL32_BASE if there is no
- * SPD and no SPM, as they are the only ones that can be used as BL32.
+ * SPD and no SPM-MM, as they are the only ones that can be used as BL32.
  */
 #if defined(__aarch64__) && !JUNO_AARCH32_EL3_RUNTIME
 # if defined(SPD_none) && !SPM_MM
 #  undef BL32_BASE
-# endif /* defined(SPD_none) && !SPM_MM*/
+# endif /* defined(SPD_none) && !SPM_MM */
 #endif /* defined(__aarch64__) && !JUNO_AARCH32_EL3_RUNTIME */
 
 /*******************************************************************************
diff --git a/include/plat/arm/common/arm_dyn_cfg_helpers.h b/include/plat/arm/common/arm_dyn_cfg_helpers.h
index 3ad6d54..2dc94ab 100644
--- a/include/plat/arm/common/arm_dyn_cfg_helpers.h
+++ b/include/plat/arm/common/arm_dyn_cfg_helpers.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,12 +10,7 @@
 #include <stdint.h>
 
 /* Function declarations */
-int arm_dyn_get_config_load_info(void *dtb, int node, unsigned int config_id,
-		uint64_t *config_addr, uint32_t *config_size);
 int arm_dyn_tb_fw_cfg_init(void *dtb, int *node);
-int arm_dyn_get_disable_auth(void *dtb, int node, uint32_t *disable_auth);
-int arm_get_dtb_mbedtls_heap_info(void *dtb, void **heap_addr,
-	size_t *heap_size);
 int arm_set_dtb_mbedtls_heap_info(void *dtb, void *heap_addr,
 	size_t heap_size);
 
diff --git a/include/plat/arm/common/arm_fconf_getter.h b/include/plat/arm/common/arm_fconf_getter.h
new file mode 100644
index 0000000..28913a4
--- /dev/null
+++ b/include/plat/arm/common/arm_fconf_getter.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ARM_FCONF_GETTER
+#define ARM_FCONF_GETTER
+
+#include <lib/fconf/fconf.h>
+
+/* ARM io policies */
+#define arm__io_policies_getter(id)	&policies[id]
+
+struct plat_io_policy {
+	uintptr_t *dev_handle;
+	uintptr_t image_spec;
+	int (*check)(const uintptr_t spec);
+};
+
+extern struct plat_io_policy policies[];
+int fconf_populate_arm_io_policies(uintptr_t config);
+
+#endif /* ARM_FCONF_GETTER */
diff --git a/include/plat/arm/common/arm_fconf_io_storage.h b/include/plat/arm/common/arm_fconf_io_storage.h
new file mode 100644
index 0000000..02ee66c
--- /dev/null
+++ b/include/plat/arm/common/arm_fconf_io_storage.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef ARM_FCONF_IO_STORAGE_H
+#define ARM_FCONF_IO_STORAGE_H
+
+#include <stdint.h>
+
+/* IO devices handle */
+extern uintptr_t memmap_dev_handle;
+extern uintptr_t fip_dev_handle;
+
+/* Function declarations */
+int open_fip(const uintptr_t spec);
+int open_memmap(const uintptr_t spec);
+
+#endif /* ARM_FCONF_IO_STORAGE_H */
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 32dc9f9..025a64f 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -6,6 +6,7 @@
 #ifndef PLAT_ARM_H
 #define PLAT_ARM_H
 
+#include <stdbool.h>
 #include <stdint.h>
 
 #include <drivers/arm/tzc_common.h>
@@ -148,7 +149,7 @@
 #define ARM_ROTPK_DEVEL_ECDSA_ID	3
 
 /* IO storage utility functions */
-void arm_io_setup(void);
+int arm_io_setup(void);
 
 /* Security utility functions */
 void arm_tzc400_setup(const arm_tzc_regions_info_t *tzc_regions);
@@ -222,11 +223,9 @@
 void arm_sp_min_plat_runtime_setup(void);
 
 /* FIP TOC validity check */
-int arm_io_is_toc_valid(void);
+bool arm_io_is_toc_valid(void);
 
 /* Utility functions for Dynamic Config */
-void arm_load_tb_fw_config(void);
-void arm_bl2_set_tb_cfg_addr(void *dtb);
 void arm_bl2_dyn_cfg_init(void);
 void arm_bl1_set_mbedtls_heap(void);
 int arm_get_mbedtls_heap(void **heap_addr, size_t *heap_size);
@@ -256,7 +255,7 @@
 void plat_arm_interconnect_enter_coherency(void);
 void plat_arm_interconnect_exit_coherency(void);
 void plat_arm_program_trusted_mailbox(uintptr_t address);
-int plat_arm_bl1_fwu_needed(void);
+bool plat_arm_bl1_fwu_needed(void);
 __dead2 void plat_arm_error_handler(int err);
 
 /*
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 332cfca..f5bd298 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,6 +10,9 @@
 #include <stdint.h>
 
 #include <lib/psci/psci.h>
+#if defined(SPD_spmd)
+ #include <services/spm_core_manifest.h>
+#endif
 
 /*******************************************************************************
  * Forward declarations
@@ -272,7 +275,11 @@
 int plat_spm_sp_rd_load(struct sp_res_desc *rd, const void *ptr, size_t size);
 int plat_spm_sp_get_next_address(void **sp_base, size_t *sp_size,
 				 void **rd_base, size_t *rd_size);
-
+#if defined(SPD_spmd)
+int plat_spm_core_manifest_load(spmc_manifest_sect_attribute_t *manifest,
+				const void *ptr,
+				size_t size);
+#endif
 /*******************************************************************************
  * Mandatory BL image load functions(may be overridden).
  ******************************************************************************/
diff --git a/include/services/spci_svc.h b/include/services/spci_svc.h
new file mode 100644
index 0000000..49ba408
--- /dev/null
+++ b/include/services/spci_svc.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SPCI_SVC_H
+#define SPCI_SVC_H
+
+#include <lib/smccc.h>
+#include <lib/utils_def.h>
+#include <tools_share/uuid.h>
+
+/* SPCI error codes. */
+#define SPCI_ERROR_NOT_SUPPORTED	-1
+#define SPCI_ERROR_INVALID_PARAMETER	-2
+#define SPCI_ERROR_NO_MEMORY		-3
+#define SPCI_ERROR_BUSY			-4
+#define SPCI_ERROR_INTERRUPTED		-5
+#define SPCI_ERROR_DENIED		-6
+#define SPCI_ERROR_RETRY		-7
+
+/* The macros below are used to identify SPCI calls from the SMC function ID */
+#define SPCI_FNUM_MIN_VALUE	U(0x60)
+#define SPCI_FNUM_MAX_VALUE	U(0x7f)
+#define is_spci_fid(fid) __extension__ ({		\
+	__typeof__(fid) _fid = (fid);			\
+	((GET_SMC_NUM(_fid) >= SPCI_FNUM_MIN_VALUE) &&	\
+	 (GET_SMC_NUM(_fid) <= SPCI_FNUM_MAX_VALUE)); })
+
+/* SPCI_VERSION helpers */
+#define SPCI_VERSION_MAJOR		U(0)
+#define SPCI_VERSION_MAJOR_SHIFT	16
+#define SPCI_VERSION_MAJOR_MASK		U(0x7FFF)
+#define SPCI_VERSION_MINOR		U(9)
+#define SPCI_VERSION_MINOR_SHIFT	0
+#define SPCI_VERSION_MINOR_MASK		U(0xFFFF)
+
+#define MAKE_SPCI_VERSION(major, minor) \
+	((((major) & SPCI_VERSION_MAJOR_MASK) <<  SPCI_VERSION_MAJOR_SHIFT) | \
+	 (((minor) & SPCI_VERSION_MINOR_MASK) << SPCI_VERSION_MINOR_SHIFT))
+#define SPCI_VERSION_COMPILED		MAKE_SPCI_VERSION(SPCI_VERSION_MAJOR, \
+							  SPCI_VERSION_MINOR)
+
+/* SPCI_MSG_SEND helpers */
+#define SPCI_MSG_SEND_ATTRS_BLK_SHIFT	U(0)
+#define SPCI_MSG_SEND_ATTRS_BLK_MASK	U(0x1)
+#define SPCI_MSG_SEND_ATTRS_BLK		U(0)
+#define SPCI_MSG_SEND_ATTRS_BLK_NOT	U(1)
+#define SPCI_MSG_SEND_ATTRS(blk)		\
+	(((blk) & SPCI_MSG_SEND_ATTRS_BLK_MASK) \
+	<< SPCI_MSG_SEND_ATTRS_BLK_SHIFT)
+
+/* Get SPCI fastcall std FID from function number */
+#define SPCI_FID(smc_cc, func_num)			\
+		((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) |	\
+		 ((smc_cc) << FUNCID_CC_SHIFT) |	\
+		 (OEN_STD_START << FUNCID_OEN_SHIFT) |	\
+		 ((func_num) << FUNCID_NUM_SHIFT))
+
+/* SPCI function numbers */
+#define SPCI_FNUM_ERROR			U(0x60)
+#define SPCI_FNUM_SUCCESS		U(0x61)
+#define SPCI_FNUM_INTERRUPT		U(0x62)
+#define SPCI_FNUM_VERSION		U(0x63)
+#define SPCI_FNUM_FEATURES		U(0x64)
+#define SPCI_FNUM_RX_RELEASE		U(0x65)
+#define SPCI_FNUM_RXTX_MAP		U(0x66)
+#define SPCI_FNUM_RXTX_UNMAP		U(0x67)
+#define SPCI_FNUM_PARTITION_INFO_GET	U(0x68)
+#define SPCI_FNUM_ID_GET		U(0x69)
+#define SPCI_FNUM_MSG_POLL		U(0x6A)
+#define SPCI_FNUM_MSG_WAIT		U(0x6B)
+#define SPCI_FNUM_MSG_YIELD		U(0x6C)
+#define SPCI_FNUM_MSG_RUN		U(0x6D)
+#define SPCI_FNUM_MSG_SEND		U(0x6E)
+#define SPCI_FNUM_MSG_SEND_DIRECT_REQ	U(0x6F)
+#define SPCI_FNUM_MSG_SEND_DIRECT_RESP	U(0x70)
+#define SPCI_FNUM_MEM_DONATE		U(0x71)
+#define SPCI_FNUM_MEM_LEND		U(0x72)
+#define SPCI_FNUM_MEM_SHARE		U(0x73)
+#define SPCI_FNUM_MEM_RETRIEVE_REQ	U(0x74)
+#define SPCI_FNUM_MEM_RETRIEVE_RESP	U(0x75)
+#define SPCI_FNUM_MEM_RELINQUISH	U(0x76)
+#define SPCI_FNUM_MEM_RECLAIM		U(0x77)
+
+/* SPCI SMC32 FIDs */
+#define SPCI_ERROR		SPCI_FID(SMC_32, SPCI_FNUM_ERROR)
+#define SPCI_SUCCESS_SMC32	SPCI_FID(SMC_32, SPCI_FNUM_SUCCESS)
+#define SPCI_INTERRUPT		SPCI_FID(SMC_32, SPCI_FNUM_INTERRUPT)
+#define SPCI_VERSION		SPCI_FID(SMC_32, SPCI_FNUM_VERSION)
+#define SPCI_FEATURES		SPCI_FID(SMC_32, SPCI_FNUM_FEATURES)
+#define SPCI_RX_RELEASE		SPCI_FID(SMC_32, SPCI_FNUM_RX_RELEASE)
+#define SPCI_RXTX_MAP_SMC32	SPCI_FID(SMC_32, SPCI_FNUM_RXTX_MAP)
+#define SPCI_RXTX_UNMAP		SPCI_FID(SMC_32, SPCI_FNUM_RXTX_UNMAP)
+#define SPCI_PARTITION_INFO_GET	SPCI_FID(SMC_32, SPCI_FNUM_PARTITION_INFO_GET)
+#define SPCI_ID_GET		SPCI_FID(SMC_32, SPCI_FNUM_ID_GET)
+#define SPCI_MSG_POLL		SPCI_FID(SMC_32, SPCI_FNUM_MSG_POLL)
+#define SPCI_MSG_WAIT		SPCI_FID(SMC_32, SPCI_FNUM_MSG_WAIT)
+#define SPCI_MSG_YIELD		SPCI_FID(SMC_32, SPCI_FNUM_MSG_YIELD)
+#define SPCI_MSG_RUN		SPCI_FID(SMC_32, SPCI_FNUM_MSG_RUN)
+#define SPCI_MSG_SEND		SPCI_FID(SMC_32, SPCI_FNUM_MSG_SEND)
+#define SPCI_MSG_SEND_DIRECT_REQ_SMC32 \
+	SPCI_FID(SMC_32, SPCI_FNUM_MSG_SEND_DIRECT_REQ)
+#define SPCI_MSG_SEND_DIRECT_RESP_SMC32	\
+	SPCI_FID(SMC_32, SPCI_FNUM_MSG_SEND_DIRECT_RESP)
+#define SPCI_MEM_DONATE_SMC32	SPCI_FID(SMC_32, SPCI_FNUM_MEM_DONATE)
+#define SPCI_MEM_LEND_SMC32	SPCI_FID(SMC_32, SPCI_FNUM_MEM_LEND)
+#define SPCI_MEM_SHARE_SMC32	SPCI_FID(SMC_32, SPCI_FNUM_MEM_SHARE)
+#define SPCI_MEM_RETRIEVE_REQ_SMC32 \
+	SPCI_FID(SMC_32, SPCI_FNUM_MEM_RETRIEVE_REQ)
+#define SPCI_MEM_RETRIEVE_RESP	SPCI_FID(SMC_32, SPCI_FNUM_MEM_RETRIEVE_RESP)
+#define SPCI_MEM_RELINQUISH	SPCI_FID(SMC_32, SPCI_FNUM_MEM_RELINQUISH)
+#define SPCI_MEM_RECLAIM	SPCI_FID(SMC_32, SPCI_FNUM_MEM_RECLAIM)
+
+/* SPCI SMC64 FIDs */
+#define SPCI_SUCCESS_SMC64	SPCI_FID(SMC_64, SPCI_FNUM_SUCCESS)
+#define SPCI_RXTX_MAP_SMC64	SPCI_FID(SMC_64, SPCI_FNUM_RXTX_MAP)
+#define SPCI_MSG_SEND_DIRECT_REQ_SMC64 \
+	SPCI_FID(SMC_64, SPCI_FNUM_MSG_SEND_DIRECT_REQ)
+#define SPCI_MSG_SEND_DIRECT_RESP_SMC64	\
+	SPCI_FID(SMC_64, SPCI_FNUM_MSG_SEND_DIRECT_RESP)
+#define SPCI_MEM_DONATE_SMC64	SPCI_FID(SMC_64, SPCI_FNUM_MEM_DONATE)
+#define SPCI_MEM_LEND_SMC64	SPCI_FID(SMC_64, SPCI_FNUM_MEM_LEND)
+#define SPCI_MEM_SHARE_SMC64	SPCI_FID(SMC_64, SPCI_FNUM_MEM_SHARE)
+#define SPCI_MEM_RETRIEVE_REQ_SMC64 \
+	SPCI_FID(SMC_64, SPCI_FNUM_MEM_RETRIEVE_REQ)
+
+/*
+ * Reserve a special value for traffic targeted to the Hypervisor or SPM.
+ */
+#define SPCI_TARGET_INFO_MBZ		U(0x0)
+
+/*
+ * Reserve a special value for MBZ parameters.
+ */
+#define SPCI_PARAM_MBZ			U(0x0)
+
+#endif /* SPCI_SVC_H */
diff --git a/include/services/spm_core_manifest.h b/include/services/spm_core_manifest.h
new file mode 100644
index 0000000..06ecc13
--- /dev/null
+++ b/include/services/spm_core_manifest.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SPMC_MANIFEST_H
+#define SPMC_MANIFEST_H
+
+#include <stdint.h>
+
+/*******************************************************************************
+ * Attribute Section
+ ******************************************************************************/
+
+typedef struct spm_core_manifest_sect_attribute {
+	/*
+	 * SPCI version (mandatory).
+	 */
+	uint32_t major_version;
+	uint32_t minor_version;
+
+	/*
+	 * Run-Time Exception Level (mandatory):
+	 * - 1: SEL1
+	 * - 2: SEL2
+	 */
+	uint32_t runtime_el;
+
+	/*
+	 * Run-Time Execution state (optional):
+	 * - 0: AArch64 (default)
+	 * - 1: AArch32
+	 */
+	uint32_t exec_state;
+
+	/*
+	 * Address of binary image containing SPM core in bytes (optional).
+	 */
+	uint64_t load_address;
+
+	/*
+	 * Offset from the base of the partition's binary image to the entry
+	 * point of the partition.
+	 */
+	uint64_t entrypoint;
+
+	/*
+	 * Size of binary image containing SPM core in bytes (mandatory).
+	 */
+	uint32_t binary_size;
+
+} spmc_manifest_sect_attribute_t;
+
+#endif /* SPMC_MANIFEST_H */
diff --git a/include/services/spmd_svc.h b/include/services/spmd_svc.h
new file mode 100644
index 0000000..6e4caf2
--- /dev/null
+++ b/include/services/spmd_svc.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SPMD_SVC_H
+#define SPMD_SVC_H
+
+#ifndef __ASSEMBLER__
+#include <services/spci_svc.h>
+#include <stdint.h>
+
+int32_t spmd_setup(void);
+uint64_t spmd_smc_handler(uint32_t smc_fid,
+			  uint64_t x1,
+			  uint64_t x2,
+			  uint64_t x3,
+			  uint64_t x4,
+			  void *cookie,
+			  void *handle,
+			  uint64_t flags);
+#endif /* __ASSEMBLER__ */
+
+#endif /* SPMD_SVC_H */
diff --git a/include/tools_share/uuid.h b/include/tools_share/uuid.h
index 7d00432..36be9ed 100644
--- a/include/tools_share/uuid.h
+++ b/include/tools_share/uuid.h
@@ -27,7 +27,7 @@
  */
 
 /*
- * Portions copyright (c) 2014, ARM Limited and Contributors.
+ * Portions copyright (c) 2014-2020, ARM Limited and Contributors.
  * All rights reserved.
  */
 
@@ -56,6 +56,11 @@
 	uint8_t		node[_UUID_NODE_LEN];
 };
 
+union uuid_helper_t {
+	struct uuid uuid_struct;
+	uint32_t word[4];
+};
+
 /* XXX namespace pollution? */
 typedef struct uuid uuid_t;
 
diff --git a/lib/fconf/fconf.c b/lib/fconf/fconf.c
new file mode 100644
index 0000000..a6da56b
--- /dev/null
+++ b/lib/fconf/fconf.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <lib/fconf/fconf.h>
+#include <libfdt.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+struct fconf_dtb_info_t fconf_dtb_info;
+
+void fconf_load_config(void)
+{
+	int err;
+	/* fconf FW_CONFIG and TB_FW_CONFIG are currently the same DTB */
+	image_info_t arm_tb_fw_info = {
+		.h.type = (uint8_t)PARAM_IMAGE_BINARY,
+		.h.version = (uint8_t)VERSION_2,
+		.h.size = (uint16_t)sizeof(image_info_t),
+		.h.attr = 0,
+		.image_base = ARM_TB_FW_CONFIG_BASE,
+		.image_max_size = (uint32_t)
+				(ARM_TB_FW_CONFIG_LIMIT - ARM_TB_FW_CONFIG_BASE)
+	};
+
+	VERBOSE("FCONF: Loading FW_CONFIG\n");
+	err = load_auth_image(TB_FW_CONFIG_ID, &arm_tb_fw_info);
+	if (err != 0) {
+		/* Return if FW_CONFIG is not loaded */
+		VERBOSE("Failed to load FW_CONFIG\n");
+		return;
+	}
+
+	/* At this point we know that a DTB is indeed available */
+	fconf_dtb_info.base_addr = arm_tb_fw_info.image_base;
+	fconf_dtb_info.size = (size_t)arm_tb_fw_info.image_size;
+
+#if !BL2_AT_EL3
+	image_desc_t *desc;
+
+	/* The BL2 ep_info arg0 is modified to point to FW_CONFIG */
+	desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
+	assert(desc != NULL);
+	desc->ep_info.args.arg0 = arm_tb_fw_info.image_base;
+#endif
+
+	INFO("FCONF: FW_CONFIG loaded at address = 0x%lx\n", arm_tb_fw_info.image_base);
+}
+
+void fconf_populate(uintptr_t config)
+{
+	assert(config != 0UL);
+
+	/* Check if the pointer to DTB is correct */
+	if (fdt_check_header((void *)config) != 0) {
+		ERROR("FCONF: Invalid DTB file passed for FW_CONFIG\n");
+		panic();
+	}
+
+	INFO("FCONF: Reading firmware configuration file from: 0x%lx\n", config);
+
+	/* Go through all registered populate functions */
+	IMPORT_SYM(struct fconf_populator *, __FCONF_POPULATOR_START__, start);
+	IMPORT_SYM(struct fconf_populator *, __FCONF_POPULATOR_END__, end);
+	const struct fconf_populator *populator;
+
+	for (populator = start; populator != end; populator++) {
+		assert((populator->info != NULL) && (populator->populate != NULL));
+
+		INFO("FCONF: Reading firmware configuration information for: %s\n", populator->info);
+		if (populator->populate(config) != 0) {
+			/* TODO: handle property miss */
+			panic();
+		}
+	}
+
+	/* save local pointer to the config dtb */
+	fconf_dtb_info.base_addr = config;
+}
diff --git a/lib/fconf/fconf.mk b/lib/fconf/fconf.mk
new file mode 100644
index 0000000..7031969
--- /dev/null
+++ b/lib/fconf/fconf.mk
@@ -0,0 +1,12 @@
+#
+# Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Add Firmware Configuration files
+FCONF_SOURCES		:=	lib/fconf/fconf.c				\
+				lib/fconf/fconf_dyn_cfg_getter.c
+
+BL1_SOURCES		+=	${FCONF_SOURCES}
+BL2_SOURCES		+=	${FCONF_SOURCES}
diff --git a/lib/fconf/fconf_dyn_cfg_getter.c b/lib/fconf/fconf_dyn_cfg_getter.c
new file mode 100644
index 0000000..d313a56
--- /dev/null
+++ b/lib/fconf/fconf_dyn_cfg_getter.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <lib/object_pool.h>
+#include <libfdt.h>
+
+/* We currently use TB_FW, SOC_FW, TOS_FW, NS_fw and HW configs  */
+#define MAX_DTB_INFO	U(5)
+
+static struct dyn_cfg_dtb_info_t dtb_infos[MAX_DTB_INFO];
+static OBJECT_POOL_ARRAY(dtb_info_pool, dtb_infos);
+
+struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id)
+{
+	unsigned int index;
+	struct dyn_cfg_dtb_info_t *info;
+
+	/* Positions index to the proper config-id */
+	for (index = 0; index < MAX_DTB_INFO; index++) {
+		if (dtb_infos[index].config_id == config_id) {
+			info = &dtb_infos[index];
+			break;
+		}
+	}
+
+	if (index == MAX_DTB_INFO) {
+		WARN("FCONF: Invalid config id %u\n", config_id);
+		info = NULL;
+	}
+
+	return info;
+}
+
+int fconf_populate_dtb_registry(uintptr_t config)
+{
+	int rc;
+	int node, child;
+	struct dyn_cfg_dtb_info_t *dtb_info;
+
+	/* As libfdt use void *, we can't avoid this cast */
+	const void *dtb = (void *)config;
+
+	/* Find the node offset point to "arm,dyn_cfg-dtb_registry" compatible property */
+	const char *compatible_str = "arm,dyn_cfg-dtb_registry";
+	node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+	if (node < 0) {
+		ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str);
+		return node;
+	}
+
+	fdt_for_each_subnode(child, dtb, node) {
+		dtb_info = pool_alloc(&dtb_info_pool);
+
+		/* Read configuration dtb information */
+		rc = fdtw_read_cells(dtb, child, "load-address", 2, &dtb_info->config_addr);
+		if (rc < 0) {
+			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
+			return rc;
+		}
+
+		rc = fdtw_read_cells(dtb, child, "max-size", 1, &dtb_info->config_max_size);
+		if (rc < 0) {
+			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
+			return rc;
+		}
+
+		rc = fdtw_read_cells(dtb, child, "id", 1, &dtb_info->config_id);
+		if (rc < 0) {
+			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
+			return rc;
+		}
+
+		VERBOSE("FCONF: dyn_cfg.dtb_registry cell found with:\n");
+		VERBOSE("\tload-address = %lx\n", dtb_info->config_addr);
+		VERBOSE("\tmax-size = 0x%zx\n", dtb_info->config_max_size);
+		VERBOSE("\tconfig-id = %u\n", dtb_info->config_id);
+	}
+
+	if ((child < 0) && (child != -FDT_ERR_NOTFOUND)) {
+		ERROR("%d: fdt_for_each_subnode(): %d\n", __LINE__, node);
+		return child;
+	}
+
+	return 0;
+}
+
+FCONF_REGISTER_POPULATOR(dyn_cfg, fconf_populate_dtb_registry);
diff --git a/lib/fconf/fconf_tbbr_getter.c b/lib/fconf/fconf_tbbr_getter.c
new file mode 100644
index 0000000..c6df9c8
--- /dev/null
+++ b/lib/fconf/fconf_tbbr_getter.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <assert.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <lib/fconf/fconf_tbbr_getter.h>
+#include <libfdt.h>
+
+struct tbbr_dyn_config_t tbbr_dyn_config;
+
+int fconf_populate_tbbr_dyn_config(uintptr_t config)
+{
+	int err;
+	int node;
+
+	/* As libfdt use void *, we can't avoid this cast */
+	const void *dtb = (void *)config;
+
+	/* Assert the node offset point to "arm,tb_fw" compatible property */
+	const char *compatible_str = "arm,tb_fw";
+	node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+	if (node < 0) {
+		ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str);
+		return node;
+	}
+
+	/* Locate the disable_auth cell and read the value */
+	err = fdtw_read_cells(dtb, node, "disable_auth", 1, &tbbr_dyn_config.disable_auth);
+	if (err < 0) {
+		WARN("FCONF: Read cell failed for `disable_auth`\n");
+		return err;
+	}
+
+	/* Check if the value is boolean */
+	if ((tbbr_dyn_config.disable_auth != 0U) && (tbbr_dyn_config.disable_auth != 1U)) {
+		WARN("Invalid value for `disable_auth` cell %d\n", tbbr_dyn_config.disable_auth);
+		return -1;
+	}
+
+#if defined(DYN_DISABLE_AUTH)
+	if (tbbr_dyn_config.disable_auth == 1)
+		dyn_disable_auth();
+#endif
+
+	/* Retrieve the Mbed TLS heap details from the DTB */
+	err = fdtw_read_cells(dtb, node,
+		"mbedtls_heap_addr", 2, &tbbr_dyn_config.mbedtls_heap_addr);
+	if (err < 0) {
+		ERROR("FCONF: Read cell failed for mbedtls_heap\n");
+		return err;
+	}
+
+	err = fdtw_read_cells(dtb, node,
+		"mbedtls_heap_size", 1, &tbbr_dyn_config.mbedtls_heap_size);
+	if (err < 0) {
+		ERROR("FCONF: Read cell failed for mbedtls_heap\n");
+		return err;
+	}
+
+	VERBOSE("FCONF:tbbr.disable_auth cell found with value = %d\n",
+					tbbr_dyn_config.disable_auth);
+	VERBOSE("FCONF:tbbr.mbedtls_heap_addr cell found with value = %p\n",
+					tbbr_dyn_config.mbedtls_heap_addr);
+	VERBOSE("FCONF:tbbr.mbedtls_heap_size cell found with value = %zu\n",
+					tbbr_dyn_config.mbedtls_heap_size);
+
+	return 0;
+}
+
+FCONF_REGISTER_POPULATOR(tbbr, fconf_populate_tbbr_dyn_config);
diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c
index 5ab15c6..cced276 100644
--- a/lib/psci/psci_common.c
+++ b/lib/psci/psci_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -601,7 +601,7 @@
 	unsigned int level;
 
 	/* Unlock top down. No unlocking required for level 0. */
-	for (level = end_pwrlvl; level >= PSCI_CPU_PWR_LVL + 1U; level--) {
+	for (level = end_pwrlvl; level >= (PSCI_CPU_PWR_LVL + 1U); level--) {
 		parent_idx = parent_nodes[level - 1U];
 		psci_lock_release(&psci_non_cpu_pd_nodes[parent_idx]);
 	}
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index 1fa26cc..b6925d3 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -67,6 +67,17 @@
 $(if $(__numeric),$(error $(1) must be numeric))
 endef
 
+# CREATE_SEQ is a recursive function to create sequence of numbers from 1 to
+# $(2) and assign the sequence to $(1)
+define CREATE_SEQ
+$(if $(word $(2), $($(1))),\
+  $(eval $(1) += $(words $($(1))))\
+  $(eval $(1) := $(filter-out 0,$($(1)))),\
+  $(eval $(1) += $(words $($(1))))\
+  $(call CREATE_SEQ,$(1),$(2))\
+)
+endef
+
 # IMG_LINKERFILE defines the linker script corresponding to a BL stage
 #   $(1) = BL stage (2, 30, 31, 32, 33)
 define IMG_LINKERFILE
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index fff336c..e8e990d 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -201,6 +201,9 @@
 # Build option to add debugfs support
 USE_DEBUGFS			:= 0
 
+# Build option to fconf based io
+USE_FCONF_BASED_IO		:= 0
+
 # Build option to choose whether Trusted Firmware uses library at ROM
 USE_ROMLIB			:= 0
 
diff --git a/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts b/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts
new file mode 100644
index 0000000..2f2d265
--- /dev/null
+++ b/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "arm,dyn_cfg-dtb_registry";
+
+		/* tb_fw_config is temporarily contained in this dtb */
+		tb_fw-config {
+			load-address = <0x0 0x2001010>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+
+		hw-config {
+			load-address = <0x0 0x83000000>;
+			max-size = <0x01000000>;
+			id = <HW_CONFIG_ID>;
+		};
+	};
+
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+	};
+};
diff --git a/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts b/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts
deleted file mode 100644
index 7b3aa11..0000000
--- a/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/dts-v1/;
-
-/ {
-	/* Platform Config */
-	plat_arm_bl2 {
-		compatible = "arm,tb_fw";
-		hw_config_addr = <0x0 0x83000000>;
-		hw_config_max_size = <0x01000000>;
-		/* Disable authentication for development */
-		disable_auth = <0x0>;
-	};
-};
diff --git a/plat/arm/board/a5ds/platform.mk b/plat/arm/board/a5ds/platform.mk
index d42b2bf..7198842 100644
--- a/plat/arm/board/a5ds/platform.mk
+++ b/plat/arm/board/a5ds/platform.mk
@@ -1,9 +1,12 @@
 #
-# Copyright (c) 2019, Arm Limited. All rights reserved.
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+# Firmware Configuration Framework sources
+include lib/fconf/fconf.mk
+
 # Add `libfdt` and Arm common helpers required for Dynamic Config
 include lib/libfdt/libfdt.mk
 
@@ -67,7 +70,7 @@
 # Add the FDT_SOURCES and options for Dynamic Config (only for Unix env)
 ifdef UNIX_MK
 
-FVP_TB_FW_CONFIG	:=	${BUILD_PLAT}/fdts/a5ds_tb_fw_config.dtb
+FVP_TB_FW_CONFIG	:=	${BUILD_PLAT}/fdts/a5ds_fw_config.dtb
 
 # Add the TB_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${FVP_TB_FW_CONFIG},--tb-fw-config))
@@ -77,7 +80,7 @@
 # Add the HW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${FVP_HW_CONFIG},--hw-config))
 
-FDT_SOURCES		+=	plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts \
+FDT_SOURCES		+=	plat/arm/board/a5ds/fdts/a5ds_fw_config.dts \
 					${FVP_HW_CONFIG_DTS}
 endif
 
diff --git a/plat/arm/board/common/board_common.mk b/plat/arm/board/common/board_common.mk
index da63430..459156b 100644
--- a/plat/arm/board/common/board_common.mk
+++ b/plat/arm/board/common/board_common.mk
@@ -17,7 +17,7 @@
 ifeq (${ARM_ROTPK_LOCATION}, regs)
 	ARM_ROTPK_LOCATION_ID = ARM_ROTPK_REGS_ID
 else ifeq (${ARM_ROTPK_LOCATION}, devel_rsa)
-	KEY_ALG := rsa
+	CRYPTO_ALG=rsa
 	ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_RSA_ID
 	ARM_ROTPK_HASH = plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin
 $(eval $(call add_define_val,ARM_ROTPK_HASH,'"$(ARM_ROTPK_HASH)"'))
@@ -25,7 +25,7 @@
 $(warning Development keys support for FVP is deprecated. Use `regs` \
 option instead)
 else ifeq (${ARM_ROTPK_LOCATION}, devel_ecdsa)
-	KEY_ALG := ecdsa
+	CRYPTO_ALG=ec
 	ARM_ROTPK_LOCATION_ID = ARM_ROTPK_DEVEL_ECDSA_ID
 	ARM_ROTPK_HASH = plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin
 $(eval $(call add_define_val,ARM_ROTPK_HASH,'"$(ARM_ROTPK_HASH)"'))
@@ -50,7 +50,7 @@
 ifndef ROT_KEY
 	$(error Cannot generate hash: no ROT_KEY defined)
 endif
-	openssl rsa -in $< -pubout -outform DER | openssl dgst \
+	openssl ${CRYPTO_ALG} -in $< -pubout -outform DER | openssl dgst \
 		-sha256 -binary > $@
 
 # Certificate NV-Counters. Use values corresponding to tied off values in
diff --git a/plat/arm/board/corstone700/corstone700_plat.c b/plat/arm/board/corstone700/corstone700_plat.c
index cee6fd6..e2ade70 100644
--- a/plat/arm/board/corstone700/corstone700_plat.c
+++ b/plat/arm/board/corstone700/corstone700_plat.c
@@ -1,10 +1,12 @@
 /*
- * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <common/bl_common.h>
+
+#include <mhu.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 #include <platform_def.h>
@@ -26,6 +28,7 @@
  */
 void __init plat_arm_pwrc_setup(void)
 {
+	mhu_secure_init();
 }
 
 unsigned int plat_get_syscnt_freq2(void)
diff --git a/plat/arm/board/corstone700/corstone700_stack_protector.c b/plat/arm/board/corstone700/corstone700_stack_protector.c
new file mode 100644
index 0000000..6fd09da
--- /dev/null
+++ b/plat/arm/board/corstone700/corstone700_stack_protector.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <plat/common/platform.h>
+
+static uint32_t plat_generate_random_number(void)
+{
+	uintptr_t return_addr = (uintptr_t)__builtin_return_address(0U);
+	uintptr_t frame_addr = (uintptr_t)__builtin_frame_address(0U);
+	uint64_t cntpct = read_cntpct_el0();
+
+	/* Generate 32-bit pattern: saving the 2 least significant bytes
+	 * in random_lo and random_hi
+	 */
+	uint16_t random_lo = (uint16_t)(
+			(((uint64_t)return_addr) << 13) ^ frame_addr ^ cntpct
+			);
+
+	uint16_t random_hi = (uint16_t)(
+			(((uint64_t)frame_addr) << 15) ^ return_addr ^ cntpct
+			);
+
+	return (((uint32_t)random_hi) << 16) | random_lo;
+}
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+	return  plat_generate_random_number(); /* a 32-bit pattern is returned */
+}
diff --git a/plat/arm/board/corstone700/corstone700_topology.c b/plat/arm/board/corstone700/corstone700_topology.c
index d9445e0..904f5ab 100644
--- a/plat/arm/board/corstone700/corstone700_topology.c
+++ b/plat/arm/board/corstone700/corstone700_topology.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,8 +8,8 @@
 #include <plat/common/platform.h>
 
 /* The Corstone700 power domain tree descriptor */
-static unsigned char corstone700_power_domain_tree_desc
-			[PLAT_ARM_CLUSTER_COUNT + 2];
+static unsigned char corstone700_power_domain_tree_desc[PLAT_ARM_CLUSTER_COUNT
+							+ 2];
 /*******************************************************************************
  * This function dynamically constructs the topology according to
  * CLUSTER_COUNT and returns it.
diff --git a/plat/arm/board/corstone700/drivers/mhu/mhu.c b/plat/arm/board/corstone700/drivers/mhu/mhu.c
new file mode 100644
index 0000000..2231d11
--- /dev/null
+++ b/plat/arm/board/corstone700/drivers/mhu/mhu.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+
+#include "mhu.h"
+#include <plat_arm.h>
+#include <platform_def.h>
+
+ARM_INSTANTIATE_LOCK;
+
+#pragma weak plat_arm_pwrc_setup
+
+/*
+ * Slot 31 is reserved because the MHU hardware uses this register bit to
+ * indicate a non-secure access attempt. The total number of available slots is
+ * therefore 31 [30:0].
+ */
+#define MHU_MAX_SLOT_ID		30
+
+void mhu_secure_message_start(uintptr_t address, unsigned int slot_id)
+{
+	unsigned int intr_stat_check;
+	uint64_t timeout_cnt;
+	volatile uint8_t expiration;
+
+	assert(slot_id <= MHU_MAX_SLOT_ID);
+	arm_lock_get();
+
+	/*
+	 * Make sure any previous command has finished
+	 * and polling timeout not expired
+	 */
+
+	timeout_cnt = timeout_init_us(MHU_POLL_INTR_STAT_TIMEOUT);
+
+	do {
+		intr_stat_check = (mmio_read_32(address + CPU_INTR_S_STAT) &
+						(1 << slot_id));
+
+		expiration = timeout_elapsed(timeout_cnt);
+
+	} while ((intr_stat_check != 0U) && (expiration == 0U));
+
+	/*
+	 * Note: No risk of timer overflows while waiting
+	 * for the timeout expiration.
+	 * According to Armv8 TRM: System counter roll-over
+	 * time of not less than 40 years
+	 */
+}
+
+void mhu_secure_message_send(uintptr_t address,
+				unsigned int slot_id,
+				unsigned int message)
+{
+	unsigned char access_ready;
+	uint64_t timeout_cnt;
+	volatile uint8_t expiration;
+
+	assert(slot_id <= MHU_MAX_SLOT_ID);
+	assert((mmio_read_32(address + CPU_INTR_S_STAT) &
+						(1 << slot_id)) == 0U);
+
+	MHU_V2_ACCESS_REQUEST(address);
+
+	timeout_cnt = timeout_init_us(MHU_POLL_INTR_STAT_TIMEOUT);
+
+	do {
+		access_ready = MHU_V2_IS_ACCESS_READY(address);
+		expiration = timeout_elapsed(timeout_cnt);
+
+	} while ((access_ready == 0U) && (expiration == 0U));
+
+	/*
+	 * Note: No risk of timer overflows while waiting
+	 * for the timeout expiration.
+	 * According to Armv8 TRM: System counter roll-over
+	 * time of not less than 40 years
+	 */
+
+	mmio_write_32(address + CPU_INTR_S_SET, message);
+}
+
+void mhu_secure_message_end(uintptr_t address, unsigned int slot_id)
+{
+	assert(slot_id <= MHU_MAX_SLOT_ID);
+	/*
+	 * Clear any response we got by writing one in the relevant slot bit to
+	 * the CLEAR register
+	 */
+	MHU_V2_CLEAR_REQUEST(address);
+
+	arm_lock_release();
+}
+
+void __init mhu_secure_init(void)
+{
+	arm_lock_init();
+
+	/*
+	 * The STAT register resets to zero. Ensure it is in the expected state,
+	 * as a stale or garbage value would make us think it's a message we've
+	 * already sent.
+	 */
+
+	assert(mmio_read_32(PLAT_SDK700_MHU0_SEND + CPU_INTR_S_STAT) == 0);
+}
diff --git a/plat/arm/board/corstone700/drivers/mhu/mhu.h b/plat/arm/board/corstone700/drivers/mhu/mhu.h
new file mode 100644
index 0000000..3808746
--- /dev/null
+++ b/plat/arm/board/corstone700/drivers/mhu/mhu.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MHU_H
+#define MHU_H
+
+#define MHU_POLL_INTR_STAT_TIMEOUT		50000 /*timeout value in us*/
+
+/* CPU MHU secure channel registers */
+#define CPU_INTR_S_STAT				0x00
+#define CPU_INTR_S_SET				0x0C
+
+/* MHUv2 Control Registers Offsets */
+#define MHU_V2_MSG_CFG_OFFSET			0xF80
+#define MHU_V2_ACCESS_REQ_OFFSET		0xF88
+#define MHU_V2_ACCESS_READY_OFFSET		0xF8C
+
+#define MHU_V2_ACCESS_REQUEST(addr)     \
+	mmio_write_32((addr) + MHU_V2_ACCESS_REQ_OFFSET, 0x1)
+
+#define MHU_V2_CLEAR_REQUEST(addr)      \
+	mmio_write_32((addr) + MHU_V2_ACCESS_REQ_OFFSET, 0x0)
+
+#define MHU_V2_IS_ACCESS_READY(addr)    \
+	(mmio_read_32((addr) + MHU_V2_ACCESS_READY_OFFSET) & 0x1)
+
+void mhu_secure_message_start(uintptr_t address, unsigned int slot_id);
+void mhu_secure_message_send(uintptr_t address,
+				unsigned int slot_id,
+				unsigned int message);
+void mhu_secure_message_end(uintptr_t address, unsigned int slot_id);
+void mhu_secure_init(void);
+
+#endif /* MHU_H */
diff --git a/plat/arm/board/corstone700/include/platform_def.h b/plat/arm/board/corstone700/include/platform_def.h
index 8dff3ec..0fb74e4 100644
--- a/plat/arm/board/corstone700/include/platform_def.h
+++ b/plat/arm/board/corstone700/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,20 +9,35 @@
 
 #include <lib/utils_def.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
+
 #include <plat/arm/board/common/v2m_def.h>
 #include <plat/arm/common/arm_spm_def.h>
 #include <plat/common/common_def.h>
 
+/* PL011 UART related constants */
+#ifdef V2M_IOFPGA_UART0_CLK_IN_HZ
+#undef V2M_IOFPGA_UART0_CLK_IN_HZ
+#endif
+
+#ifdef V2M_IOFPGA_UART1_CLK_IN_HZ
+#undef V2M_IOFPGA_UART1_CLK_IN_HZ
+#endif
+
+#define V2M_IOFPGA_UART0_CLK_IN_HZ		32000000
+#define V2M_IOFPGA_UART1_CLK_IN_HZ		32000000
+
 /* Core/Cluster/Thread counts for Corstone700 */
 #define CORSTONE700_CLUSTER_COUNT		U(1)
 #define CORSTONE700_MAX_CPUS_PER_CLUSTER	U(4)
 #define CORSTONE700_MAX_PE_PER_CPU		U(1)
-#define CORSTONE700_CORE_COUNT		(CORSTONE700_CLUSTER_COUNT *	\
-					CORSTONE700_MAX_CPUS_PER_CLUSTER * \
-					CORSTONE700_MAX_PE_PER_CPU)
-#define PLATFORM_CORE_COUNT		CORSTONE700_CORE_COUNT
+
 #define PLAT_ARM_CLUSTER_COUNT		CORSTONE700_CLUSTER_COUNT
 
+#define PLATFORM_CORE_COUNT		(PLAT_ARM_CLUSTER_COUNT *       \
+					CORSTONE700_MAX_CPUS_PER_CLUSTER *   \
+					CORSTONE700_MAX_PE_PER_CPU)
+
+
 /* UART related constants */
 #define PLAT_ARM_BOOT_UART_BASE		0x1a510000
 #define PLAT_ARM_BOOT_UART_CLK_IN_HZ	V2M_IOFPGA_UART0_CLK_IN_HZ
@@ -85,8 +100,12 @@
 					ARM_BL_REGIONS)
 
 /* GIC related constants */
-#define PLAT_ARM_GICD_BASE			0x1C010000
-#define PLAT_ARM_GICC_BASE			0x1C02F000
+#define PLAT_ARM_GICD_BASE		0x1C010000
+#define PLAT_ARM_GICC_BASE		0x1C02F000
+
+/* MHUv2 Secure Channel receiver and sender */
+#define PLAT_SDK700_MHU0_SEND		0x1B800000
+#define PLAT_SDK700_MHU0_RECV		0x1B810000
 
 /* Timer/watchdog related constants */
 #define ARM_SYS_CNTCTL_BASE			UL(0x1a200000)
@@ -101,46 +120,46 @@
  * Macros mapping the MPIDR Affinity levels to ARM Platform Power levels. The
  * power levels have a 1:1 mapping with the MPIDR affinity levels.
  */
-#define ARM_PWR_LVL0		MPIDR_AFFLVL0
-#define ARM_PWR_LVL1		MPIDR_AFFLVL1
-#define ARM_PWR_LVL2		MPIDR_AFFLVL2
+#define ARM_PWR_LVL0				MPIDR_AFFLVL0
+#define ARM_PWR_LVL1				MPIDR_AFFLVL1
+#define ARM_PWR_LVL2				MPIDR_AFFLVL2
 
 /*
  *  Macros for local power states in ARM platforms encoded by State-ID field
  *  within the power-state parameter.
  */
 /* Local power state for power domains in Run state. */
-#define ARM_LOCAL_STATE_RUN	U(0)
+#define ARM_LOCAL_STATE_RUN			U(0)
 /* Local power state for retention. Valid only for CPU power domains */
-#define ARM_LOCAL_STATE_RET	U(1)
+#define ARM_LOCAL_STATE_RET			U(1)
 /* Local power state for OFF/power-down. Valid for CPU and cluster
  * power domains
  */
-#define ARM_LOCAL_STATE_OFF	U(2)
+#define ARM_LOCAL_STATE_OFF			U(2)
 
-#define PLAT_ARM_TRUSTED_MAILBOX_BASE	ARM_TRUSTED_SRAM_BASE
-#define PLAT_ARM_NSTIMER_FRAME_ID	U(1)
+#define PLAT_ARM_TRUSTED_MAILBOX_BASE		ARM_TRUSTED_SRAM_BASE
+#define PLAT_ARM_NSTIMER_FRAME_ID		U(1)
 
-#define PLAT_ARM_NS_IMAGE_OFFSET	(ARM_DRAM1_BASE + UL(0x8000000))
+#define PLAT_ARM_NS_IMAGE_OFFSET		(ARM_DRAM1_BASE + UL(0x8000000))
 
-#define PLAT_PHY_ADDR_SPACE_SIZE	(1ULL << 32)
-#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
+#define PLAT_PHY_ADDR_SPACE_SIZE		(1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE		(1ULL << 32)
 
 /*
  * This macro defines the deepest retention state possible. A higher state
  * ID will represent an invalid or a power down state.
  */
-#define PLAT_MAX_RET_STATE		1
+#define PLAT_MAX_RET_STATE			1
 
 /*
  * This macro defines the deepest power down states possible. Any state ID
  * higher than this is invalid.
  */
-#define PLAT_MAX_OFF_STATE		2
+#define PLAT_MAX_OFF_STATE			2
 
-#define PLATFORM_STACK_SIZE		UL(0x440)
+#define PLATFORM_STACK_SIZE			UL(0x440)
 
-#define ARM_MAP_SHARED_RAM		MAP_REGION_FLAT(		\
+#define ARM_MAP_SHARED_RAM			MAP_REGION_FLAT(	\
 						ARM_SHARED_RAM_BASE,	\
 						ARM_SHARED_RAM_SIZE,	\
 						MT_DEVICE | MT_RW | MT_SECURE)
@@ -170,21 +189,21 @@
 
 #define CORSTONE700_DEVICE_BASE		(0x1A000000)
 #define CORSTONE700_DEVICE_SIZE		(0x26000000)
-#define CORSTONE700_MAP_DEVICE	MAP_REGION_FLAT(			\
-					CORSTONE700_DEVICE_BASE,	\
-					CORSTONE700_DEVICE_SIZE,	\
-					MT_DEVICE | MT_RW | MT_SECURE)
+#define CORSTONE700_MAP_DEVICE		MAP_REGION_FLAT(		\
+						CORSTONE700_DEVICE_BASE,\
+						CORSTONE700_DEVICE_SIZE,\
+						MT_DEVICE | MT_RW | MT_SECURE)
 
-#define ARM_IRQ_SEC_PHY_TIMER		29
+#define ARM_IRQ_SEC_PHY_TIMER			29
 
-#define ARM_IRQ_SEC_SGI_0		8
-#define ARM_IRQ_SEC_SGI_1		9
-#define ARM_IRQ_SEC_SGI_2		10
-#define ARM_IRQ_SEC_SGI_3		11
-#define ARM_IRQ_SEC_SGI_4		12
-#define ARM_IRQ_SEC_SGI_5		13
-#define ARM_IRQ_SEC_SGI_6		14
-#define ARM_IRQ_SEC_SGI_7		15
+#define ARM_IRQ_SEC_SGI_0			8
+#define ARM_IRQ_SEC_SGI_1			9
+#define ARM_IRQ_SEC_SGI_2			10
+#define ARM_IRQ_SEC_SGI_3			11
+#define ARM_IRQ_SEC_SGI_4			12
+#define ARM_IRQ_SEC_SGI_5			13
+#define ARM_IRQ_SEC_SGI_6			14
+#define ARM_IRQ_SEC_SGI_7			15
 
 /*
  * Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3
@@ -192,7 +211,7 @@
  * as Group 0 interrupts.
  */
 #define ARM_G1S_IRQ_PROPS(grp) \
-	INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,	\
+	INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \
 		(grp), GIC_INTR_CFG_LEVEL), \
 	INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY,	\
 		(grp), GIC_INTR_CFG_EDGE), \
@@ -217,11 +236,11 @@
  * as Group 0 interrupts.
  */
 #define PLAT_ARM_G1S_IRQ_PROPS(grp)	\
-	ARM_G1S_IRQ_PROPS(grp),	\
-	INTR_PROP_DESC(CORSTONE700_IRQ_TZ_WDOG,	\
-		GIC_HIGHEST_SEC_PRIORITY, (grp), GIC_INTR_CFG_LEVEL),	\
-	INTR_PROP_DESC(CORSTONE700_IRQ_SEC_SYS_TIMER,	\
-		GIC_HIGHEST_SEC_PRIORITY, (grp), GIC_INTR_CFG_LEVEL)	\
+	ARM_G1S_IRQ_PROPS(grp), \
+	INTR_PROP_DESC(CORSTONE700_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, \
+			(grp), GIC_INTR_CFG_LEVEL), \
+	INTR_PROP_DESC(CORSTONE700_IRQ_SEC_SYS_TIMER, \
+			GIC_HIGHEST_SEC_PRIORITY, (grp), GIC_INTR_CFG_LEVEL)
 
 #define PLAT_ARM_G0_IRQ_PROPS(grp)	ARM_G0_IRQ_PROPS(grp)
 
diff --git a/plat/arm/board/corstone700/platform.mk b/plat/arm/board/corstone700/platform.mk
index bff3589..a4d4f22 100644
--- a/plat/arm/board/corstone700/platform.mk
+++ b/plat/arm/board/corstone700/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -11,16 +11,19 @@
 				plat/arm/common/arm_common.c	\
 				lib/xlat_tables/aarch32/xlat_tables.c	\
 				lib/xlat_tables/xlat_tables_common.c	\
-				${CORSTONE700_CPU_LIBS}
+				${CORSTONE700_CPU_LIBS}	\
+				plat/arm/board/corstone700/drivers/mhu/mhu.c
 
-PLAT_INCLUDES		:=	-Iplat/arm/board/corstone700/include
+PLAT_INCLUDES		:=	-Iplat/arm/board/corstone700/include	\
+				-Iinclude/plat/arm/common	\
+				-Iplat/arm/board/corstone700/drivers/mhu
 
 NEED_BL32		:=	yes
 
-CORSTONE700_GIC_SOURCES      :=	drivers/arm/gic/common/gic_common.c     \
-				drivers/arm/gic/v2/gicv2_main.c         \
-				drivers/arm/gic/v2/gicv2_helpers.c      \
-				plat/common/plat_gicv2.c                \
+CORSTONE700_GIC_SOURCES	:=	drivers/arm/gic/common/gic_common.c	\
+				drivers/arm/gic/v2/gicv2_main.c		\
+				drivers/arm/gic/v2/gicv2_helpers.c	\
+				plat/common/plat_gicv2.c		\
 				plat/arm/common/arm_gicv2.c
 
 # BL1/BL2 Image not a part of the capsule Image for Corstone700
diff --git a/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk b/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk
index 57e1ec3..acee6c3 100644
--- a/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk
+++ b/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -15,4 +15,10 @@
 			plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c	\
 			${CORSTONE700_GIC_SOURCES}
 
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+	ifneq (${ENABLE_STACK_PROTECTOR},none)
+		BL32_SOURCES += plat/arm/board/corstone700/corstone700_stack_protector.c
+	endif
+endif
+
 include plat/arm/common/sp_min/arm_sp_min.mk
diff --git a/plat/arm/board/fvp/fdts/fvp_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_fw_config.dts
new file mode 100644
index 0000000..d0f6033
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_fw_config.dts
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "arm,dyn_cfg-dtb_registry";
+
+		/* tb_fw_config is temporarily contained on this dtb */
+		tb_fw-config {
+			load-address = <0x0 0x4001010>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+
+		hw-config {
+			load-address = <0x0 0x82000000>;
+			max-size = <0x01000000>;
+			id = <HW_CONFIG_ID>;
+		};
+
+		/*
+		 * Load SoC and TOS firmware configs at the base of
+		 * non shared SRAM. The runtime checks ensure we don't
+		 * overlap BL2, BL31 or BL32. The NT firmware config
+		 * is loaded at base of DRAM.
+		 */
+		soc_fw-config {
+			load-address = <0x0 0x04001000>;
+			max-size = <0x200>;
+			id = <SOC_FW_CONFIG_ID>;
+		};
+
+		tos_fw-config {
+			load-address = <0x0 0x04001200>;
+			max-size = <0x200>;
+			id = <TOS_FW_CONFIG_ID>;
+		};
+
+		nt_fw-config {
+			load-address = <0x0 0x80000000>;
+			max-size = <0x200>;
+			id = <NT_FW_CONFIG_ID>;
+		};
+	};
+
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+
+	arm-io_policies {
+		fip-handles {
+			compatible = "arm,io-fip-handle";
+			scp_bl2_uuid = <0x3dfd6697 0x49e8be89 0xa1785dae 0x13826040>;
+			bl31_uuid = <0x6d08d447 0x4698fe4c 0x5029959b 0x005abdcb>;
+			bl32_uuid = <0x89e1d005 0x4713dc53 0xa502b8d 0x383e7a4b>;
+			bl32_extra1_uuid = <0x9bc2700b 0x40785a2a 0x560a659f 0x88827382>;
+			bl32_extra2_uuid = <0xb17ba88e 0x4d3fa2cf 0xbbe7fd85 0xd92002a5>;
+			bl33_uuid = <0xa7eed0d6 0x4bd5eafc 0x34998297 0xe4b634f2>;
+			hw_cfg_uuid = <0xd9f1b808 0x4993cfc9 0xbc6f62a9 0xcc65726b>;
+			soc_fw_cfg_uuid = <0x4b817999 0x46fb7603 0x268d8e8c 0xe059787f>;
+			tos_fw_cfg_uuid = <0x1a7c2526 0x477fc6db 0xc4c4968d 0x218024b0>;
+			nt_fw_cfg_uuid = <0x1598da28 0x447ee893 0xaf1a66ac 0xf9501580>;
+			t_key_cert_uuid = <0x90e87e82 0x11e460f8 0x7a77b4a1 0x4cf9b421>;
+			scp_fw_key_uuid = <0xa1214202 0x11e460f8 0x3cf39b8d 0x14a0150e>;
+			soc_fw_key_uuid = <0xccbeb88a 0x11e460f9 0x48ebd09a 0xf8dcd822>;
+			tos_fw_key_cert_uuid = <0x3d67794 0x11e460fb 0x10b7dd85 0x4ee8c5b>;
+			nt_fw_key_cert_uuid = <0x2a83d58a 0x11e460fb 0x30dfaf8a 0x5998c4bb>;
+			scp_fw_content_cert_uuid = <0x046fbe44 0x11e4635e 0xd8738bb2 0x5696aeea>;
+			soc_fw_content_cert_uuid = <0x200cb2e2 0x11e4635e 0xccabe89c 0x66b62bf9>;
+			tos_fw_content_cert_uuid = <0x11449fa4 0x11e4635e 0x53f2887 0x3df32a72>;
+			nt_fw_content_cert_uuid = <0xf3c1c48e 0x11e4635d 0xee87a9a7 0xa73fb240>;
+		};
+	};
+};
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
new file mode 100644
index 0000000..e1c106f
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+/dts-v1/;
+
+/ {
+	compatible = "spci-core-manifest-1.0";
+
+	attribute {
+		maj_ver = <0x0>;
+		min_ver = <0x9>;
+		runtime_el = <0x1>;
+		exec_state = <0x0>;
+		load_address = <0x0 0x6000000>;
+		entrypoint = <0x0 0x6000000>;
+	};
+};
diff --git a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
deleted file mode 100644
index ce58938..0000000
--- a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/dts-v1/;
-
-/ {
-	/* Platform Config */
-	plat_arm_bl2 {
-		compatible = "arm,tb_fw";
-		hw_config_addr = <0x0 0x82000000>;
-		hw_config_max_size = <0x01000000>;
-		/* Disable authentication for development */
-		disable_auth = <0x0>;
-		/*
-		 * Load SoC and TOS firmware configs at the base of
-		 * non shared SRAM. The runtime checks ensure we don't
-		 * overlap BL2, BL31 or BL32. The NT firmware config
-		 * is loaded at base of DRAM.
-		 */
-		soc_fw_config_addr = <0x0 0x04001000>;
-		soc_fw_config_max_size = <0x200>;
-		tos_fw_config_addr = <0x0 0x04001200>;
-		tos_fw_config_max_size = <0x200>;
-		nt_fw_config_addr = <0x0 0x80000000>;
-		nt_fw_config_max_size = <0x200>;
-		/*
-		 * The following two entries are placeholders for Mbed TLS
-		 * heap information. The default values don't matter since
-		 * they will be overwritten by BL1.
-		 * In case of having shared Mbed TLS heap between BL1 and BL2,
-		 * BL1 will populate these two properties with the respective
-		 * info about the shared heap. This info will be available for
-		 * BL2 in order to locate and re-use the heap.
-		 */
-		mbedtls_heap_addr = <0x0 0x0>;
-		mbedtls_heap_size = <0x0>;
-	};
-};
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index ffaa93d..2c880fc 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -86,6 +86,9 @@
 #ifdef __aarch64__
 	ARM_MAP_DRAM2,
 #endif
+#if defined(SPD_spmd)
+	ARM_MAP_TRUSTED_DRAM,
+#endif
 #ifdef SPD_tspd
 	ARM_MAP_TSP_SEC_MEM,
 #endif
diff --git a/plat/arm/board/fvp/fvp_io_storage.c b/plat/arm/board/fvp/fvp_io_storage.c
index 9c4c1d5..109d321 100644
--- a/plat/arm/board/fvp/fvp_io_storage.c
+++ b/plat/arm/board/fvp/fvp_io_storage.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -120,18 +120,22 @@
 {
 	int io_result;
 
-	arm_io_setup();
+	io_result = arm_io_setup();
+	if (io_result < 0) {
+		panic();
+	}
 
 	/* Register the additional IO devices on this platform */
 	io_result = register_io_dev_sh(&sh_dev_con);
-	assert(io_result == 0);
+	if (io_result < 0) {
+		panic();
+	}
 
 	/* Open connections to devices and cache the handles */
 	io_result = io_dev_open(sh_dev_con, (uintptr_t)NULL, &sh_dev_handle);
-	assert(io_result == 0);
-
-	/* Ignore improbable errors in release builds */
-	(void)io_result;
+	if (io_result < 0) {
+		panic();
+	}
 }
 
 /*
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 602ea6d..bfe207a 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -116,12 +116,18 @@
 # define PLAT_ARM_MAX_BL2_SIZE	(UL(0x11000) - FVP_BL2_ROMLIB_OPTIMIZATION)
 #endif
 
+#if RESET_TO_BL31
+/* Size of Trusted SRAM - the first 4KB of shared memory */
+#define PLAT_ARM_MAX_BL31_SIZE		(PLAT_ARM_TRUSTED_SRAM_SIZE - \
+					 ARM_SHARED_RAM_SIZE)
+#else
 /*
  * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is
  * calculated using the current BL31 PROGBITS debug size plus the sizes of
  * BL2 and BL1-RW
  */
 #define PLAT_ARM_MAX_BL31_SIZE		UL(0x3B000)
+#endif /* RESET_TO_BL31 */
 
 #ifndef __aarch64__
 /*
diff --git a/plat/arm/board/fvp/jmptbl.i b/plat/arm/board/fvp/jmptbl.i
index 6ccdd28..b1b9ed4 100644
--- a/plat/arm/board/fvp/jmptbl.i
+++ b/plat/arm/board/fvp/jmptbl.i
@@ -20,6 +20,8 @@
 fdt     fdt_check_header
 fdt     fdt_node_offset_by_compatible
 fdt     fdt_setprop_inplace_namelen_partial
+fdt     fdt_first_subnode
+fdt     fdt_next_subnode
 mbedtls mbedtls_asn1_get_alg
 mbedtls mbedtls_asn1_get_alg_null
 mbedtls mbedtls_asn1_get_bitstring_null
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 6fb34c4..6037435 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -10,6 +10,11 @@
 # Use the SP804 timer instead of the generic one
 FVP_USE_SP804_TIMER	:= 0
 
+# Use fconf based io for FVP
+ifeq ($(BL2_AT_EL3), 0)
+USE_FCONF_BASED_IO	:= 1
+endif
+
 # Default cluster count for FVP
 FVP_CLUSTER_COUNT	:= 2
 
@@ -205,12 +210,12 @@
 ifdef UNIX_MK
 FVP_HW_CONFIG_DTS	:=	fdts/${FVP_DT_PREFIX}.dts
 FDT_SOURCES		+=	$(addprefix plat/arm/board/fvp/fdts/,	\
-					${PLAT}_tb_fw_config.dts	\
+					${PLAT}_fw_config.dts		\
 					${PLAT}_soc_fw_config.dts	\
 					${PLAT}_nt_fw_config.dts	\
 				)
 
-FVP_TB_FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+FVP_TB_FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
 FVP_SOC_FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_soc_fw_config.dtb
 FVP_NT_FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb
 
@@ -222,6 +227,14 @@
 $(eval $(call TOOL_ADD_PAYLOAD,${FVP_TOS_FW_CONFIG},--tos-fw-config))
 endif
 
+ifeq (${SPD},spmd)
+FDT_SOURCES		+=	plat/arm/board/fvp/fdts/${PLAT}_spmc_manifest.dts
+FVP_TOS_FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_spmc_manifest.dtb
+
+# Add the TOS_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TOS_FW_CONFIG},--tos-fw-config))
+endif
+
 # Add the TB_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${FVP_TB_FW_CONFIG},--tb-fw-config))
 # Add the SOC_FW_CONFIG to FIP and specify the same to certtool
diff --git a/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts b/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts
new file mode 100644
index 0000000..147c8f3
--- /dev/null
+++ b/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "arm,dyn_cfg-dtb_registry";
+
+		/* tb_fw_config is temporarily contained on this dtb */
+		tb_fw-config {
+			load-address = <0x0 0x80001010>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+
+		hw-config {
+			load-address = <0x0 0x82000000>;
+			max-size = <0x01000000>;
+			id = <HW_CONFIG_ID>;
+		};
+	};
+
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+	};
+};
diff --git a/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts b/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts
deleted file mode 100644
index 9ab2d96..0000000
--- a/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (c) 2019, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/dts-v1/;
-
-/ {
-	/* Platform Config */
-	plat_arm_bl2 {
-		compatible = "arm,tb_fw";
-		hw_config_addr = <0x0 0x82000000>;
-		hw_config_max_size = <0x01000000>;
-		/* Disable authentication for development */
-		disable_auth = <0x0>;
-	};
-};
diff --git a/plat/arm/board/fvp_ve/platform.mk b/plat/arm/board/fvp_ve/platform.mk
index 4d21f4b..7883719 100644
--- a/plat/arm/board/fvp_ve/platform.mk
+++ b/plat/arm/board/fvp_ve/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2019, Arm Limited. All rights reserved.
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -72,9 +72,9 @@
 # Add the FDT_SOURCES and options for Dynamic Config (only for Unix env)
 ifdef UNIX_MK
 
-FDT_SOURCES		+=	plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts
+FDT_SOURCES		+=	plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts
 
-FVP_TB_FW_CONFIG	:=	${BUILD_PLAT}/fdts/fvp_ve_tb_fw_config.dtb
+FVP_TB_FW_CONFIG	:=	${BUILD_PLAT}/fdts/fvp_ve_fw_config.dtb
 
 # Add the TB_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${FVP_TB_FW_CONFIG},--tb-fw-config))
@@ -116,6 +116,9 @@
 	PLAT_BL_COMMON_SOURCES	+=	${XLAT_TABLES_LIB_SRCS}
 endif
 
+# Firmware Configuration Framework sources
+include lib/fconf/fconf.mk
+
 # Add `libfdt` and Arm common helpers required for Dynamic Config
 include lib/libfdt/libfdt.mk
 
diff --git a/plat/arm/board/juno/fdts/juno_fw_config.dts b/plat/arm/board/juno/fdts/juno_fw_config.dts
new file mode 100644
index 0000000..cab6f2b
--- /dev/null
+++ b/plat/arm/board/juno/fdts/juno_fw_config.dts
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "arm,dyn_cfg-dtb_registry";
+
+		/* tb_fw_config is temporarily contained on this dtb */
+		tb_fw-config {
+			load-address = <0x0 0x4001010>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+	};
+
+	tb_fw-config {
+		/* Platform Config */
+		compatible = "arm,tb_fw";
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+};
diff --git a/plat/arm/board/juno/fdts/juno_tb_fw_config.dts b/plat/arm/board/juno/fdts/juno_tb_fw_config.dts
deleted file mode 100644
index a8ab6c5..0000000
--- a/plat/arm/board/juno/fdts/juno_tb_fw_config.dts
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/dts-v1/;
-
-/ {
-	/* Platform Config */
-	compatible = "arm,tb_fw";
-	/* Disable authentication for development */
-	disable_auth = <0x0>;
-	/*
-	 * The following two entries are placeholders for Mbed TLS
-	 * heap information. The default values don't matter since
-	 * they will be overwritten by BL1.
-	 * In case of having shared Mbed TLS heap between BL1 and BL2,
-	 * BL1 will populate these two properties with the respective
-	 * info about the shared heap. This info will be available for
-	 * BL2 in order to locate and re-use the heap.
-	 */
-	mbedtls_heap_addr = <0x0 0x0>;
-	mbedtls_heap_size = <0x0>;
-};
diff --git a/plat/arm/board/juno/jmptbl.i b/plat/arm/board/juno/jmptbl.i
index 6ccdd28..b1b9ed4 100644
--- a/plat/arm/board/juno/jmptbl.i
+++ b/plat/arm/board/juno/jmptbl.i
@@ -20,6 +20,8 @@
 fdt     fdt_check_header
 fdt     fdt_node_offset_by_compatible
 fdt     fdt_setprop_inplace_namelen_partial
+fdt     fdt_first_subnode
+fdt     fdt_next_subnode
 mbedtls mbedtls_asn1_get_alg
 mbedtls mbedtls_asn1_get_alg_null
 mbedtls mbedtls_asn1_get_bitstring_null
diff --git a/plat/arm/board/juno/juno_bl1_setup.c b/plat/arm/board/juno/juno_bl1_setup.c
index 89398d6..25a27da 100644
--- a/plat/arm/board/juno/juno_bl1_setup.c
+++ b/plat/arm/board/juno/juno_bl1_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -60,17 +60,13 @@
  * The following function checks if Firmware update is needed,
  * by checking if TOC in FIP image is valid or watchdog reset happened.
  ******************************************************************************/
-int plat_arm_bl1_fwu_needed(void)
+bool plat_arm_bl1_fwu_needed(void)
 {
 	const int32_t *nv_flags_ptr = (const int32_t *)V2M_SYS_NVFLAGS_ADDR;
 
 	/* Check if TOC is invalid or watchdog reset happened. */
-	if ((arm_io_is_toc_valid() != 1) ||
-		(((*nv_flags_ptr == -EAUTH) || (*nv_flags_ptr == -ENOENT))
-		&& is_watchdog_reset()))
-		return 1;
-
-	return 0;
+	return (!arm_io_is_toc_valid() || (((*nv_flags_ptr == -EAUTH) ||
+		(*nv_flags_ptr == -ENOENT)) && is_watchdog_reset()));
 }
 
 /*******************************************************************************
diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk
index a85ad53..27650d2 100644
--- a/plat/arm/board/juno/platform.mk
+++ b/plat/arm/board/juno/platform.mk
@@ -156,8 +156,8 @@
 endif
 
 # Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES		+=	plat/arm/board/juno/fdts/${PLAT}_tb_fw_config.dts
-TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+FDT_SOURCES		+=	plat/arm/board/juno/fdts/${PLAT}_fw_config.dts
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
 
 # Add the TB_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
diff --git a/plat/arm/board/rddaniel/fdts/rddaniel_fw_config.dts b/plat/arm/board/rddaniel/fdts/rddaniel_fw_config.dts
new file mode 100644
index 0000000..81e4cc1
--- /dev/null
+++ b/plat/arm/board/rddaniel/fdts/rddaniel_fw_config.dts
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "arm,dyn_cfg-dtb_registry";
+
+		/* tb_fw_config is temporarily contained on this dtb */
+		tb_fw-config {
+			load-address = <0x0 0x4001010>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+
+		nt_fw-config {
+			load-address = <0x0 0xFEF00000>;
+			max-size = <0x0100000>;
+			id = <NT_FW_CONFIG_ID>;
+		};
+	};
+
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+};
diff --git a/plat/arm/board/rddaniel/fdts/rddaniel_tb_fw_config.dts b/plat/arm/board/rddaniel/fdts/rddaniel_tb_fw_config.dts
deleted file mode 100644
index 9acec13..0000000
--- a/plat/arm/board/rddaniel/fdts/rddaniel_tb_fw_config.dts
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/dts-v1/;
-
-/ {
-	/* Platform Config */
-	compatible = "arm,tb_fw";
-	nt_fw_config_addr = <0x0 0xFEF00000>;
-	nt_fw_config_max_size = <0x0100000>;
-
-	/*
-	 * The following two entries are placeholders for Mbed TLS
-	 * heap information. The default values don't matter since
-	 * they will be overwritten by BL1.
-	 * In case of having shared Mbed TLS heap between BL1 and BL2,
-	 * BL1 will populate these two properties with the respective
-	 * info about the shared heap. This info will be available for
-	 * BL2 in order to locate and re-use the heap.
-	 */
-	mbedtls_heap_addr = <0x0 0x0>;
-	mbedtls_heap_size = <0x0>;
-};
diff --git a/plat/arm/board/rddaniel/platform.mk b/plat/arm/board/rddaniel/platform.mk
index 67f5777..c7e3c7d 100644
--- a/plat/arm/board/rddaniel/platform.mk
+++ b/plat/arm/board/rddaniel/platform.mk
@@ -28,8 +28,8 @@
 				plat/arm/common/arm_nor_psci_mem_protect.c
 
 # Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES		+=	${RDDANIEL_BASE}/fdts/${PLAT}_tb_fw_config.dts
-TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+FDT_SOURCES		+=	${RDDANIEL_BASE}/fdts/${PLAT}_fw_config.dts
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
 
 # Add the TB_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
diff --git a/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts b/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts
new file mode 100644
index 0000000..2719ab4
--- /dev/null
+++ b/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "arm,dyn_cfg-dtb_registry";
+
+		/* tb_fw_config is temporarily contained on this dtb */
+		tb_fw-config {
+			load-address = <0x0 0x4001010>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+
+		nt_fw-config {
+			load-address = <0x0 0xFEF00000>;
+			max-size = <0x0100000>;
+			id = <NT_FW_CONFIG_ID>;
+		};
+	};
+
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+};
diff --git a/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts b/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts
deleted file mode 100644
index 766dc00..0000000
--- a/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/dts-v1/;
-
-/ {
-	/* Platform Config */
-	compatible = "arm,tb_fw";
-	nt_fw_config_addr = <0x0 0xFEF00000>;
-	nt_fw_config_max_size = <0x0100000>;
-	/*
-	 * The following two entries are placeholders for Mbed TLS
-	 * heap information. The default values don't matter since
-	 * they will be overwritten by BL1.
-	 * In case of having shared Mbed TLS heap between BL1 and BL2,
-	 * BL1 will populate these two properties with the respective
-	 * info about the shared heap. This info will be available for
-	 * BL2 in order to locate and re-use the heap.
-	 */
-	mbedtls_heap_addr = <0x0 0x0>;
-	mbedtls_heap_size = <0x0>;
-};
diff --git a/plat/arm/board/rde1edge/platform.mk b/plat/arm/board/rde1edge/platform.mk
index 88aa634..1a4dd17 100644
--- a/plat/arm/board/rde1edge/platform.mk
+++ b/plat/arm/board/rde1edge/platform.mk
@@ -35,8 +35,8 @@
 endif
 
 # Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES		+=	${RDE1EDGE_BASE}/fdts/${PLAT}_tb_fw_config.dts
-TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+FDT_SOURCES		+=	${RDE1EDGE_BASE}/fdts/${PLAT}_fw_config.dts
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
 
 # Add the TB_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
diff --git a/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts b/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts
new file mode 100644
index 0000000..ba74b75
--- /dev/null
+++ b/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/dts-v1/;
+/ {
+	dtb-registry {
+		compatible = "arm,dyn_cfg-dtb_registry";
+
+		/* tb_fw_config is temporarily contained on this dtb */
+		tb_fw-config {
+			load-address = <0x0 0x80001010>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+
+		nt_fw-config {
+			load-address = <0x0 0xFEF00000>;
+			max-size = <0x0100000>;
+			id = <NT_FW_CONFIG_ID>;
+		};
+	};
+
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+};
+
diff --git a/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts b/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts
deleted file mode 100644
index b14d7ad..0000000
--- a/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/dts-v1/;
-
-/ {
-	/* Platform Config */
-	compatible = "arm,tb_fw";
-	nt_fw_config_addr = <0x0 0xFEF00000>;
-	nt_fw_config_max_size = <0x0100000>;
-	/*
-	 * The following two entries are placeholders for Mbed TLS
-	 * heap information. The default values don't matter since
-	 * they will be overwritten by BL1.
-	 * In case of having shared Mbed TLS heap between BL1 and BL2,
-	 * BL1 will populate these two properties with the respective
-	 * info about the shared heap. This info will be available for
-	 * BL2 in order to locate and re-use the heap.
-	 */
-	mbedtls_heap_addr = <0x0 0x0>;
-	mbedtls_heap_size = <0x0>;
-};
diff --git a/plat/arm/board/rdn1edge/platform.mk b/plat/arm/board/rdn1edge/platform.mk
index 04f70f3..135676d 100644
--- a/plat/arm/board/rdn1edge/platform.mk
+++ b/plat/arm/board/rdn1edge/platform.mk
@@ -39,8 +39,8 @@
 BL31_CFLAGS		+=	-DPLAT_XLAT_TABLES_DYNAMIC=1
 
 # Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES		+=	${RDN1EDGE_BASE}/fdts/${PLAT}_tb_fw_config.dts
-TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+FDT_SOURCES		+=	${RDN1EDGE_BASE}/fdts/${PLAT}_fw_config.dts
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
 
 # Add the TB_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
@@ -51,8 +51,9 @@
 # Add the NT_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config))
 
-ifneq ($(CSS_SGI_CHIP_COUNT),$(filter $(CSS_SGI_CHIP_COUNT),1 2))
- $(error  "Chip count for RDN1Edge platform should either 1 or 2, currently \
+$(eval $(call CREATE_SEQ,SEQ,2))
+ifneq ($(CSS_SGI_CHIP_COUNT),$(filter $(CSS_SGI_CHIP_COUNT),$(SEQ)))
+ $(error  "Chip count for RDN1Edge platform should be one of $(SEQ), currently \
    set to ${CSS_SGI_CHIP_COUNT}.")
 endif
 
diff --git a/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts b/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts
new file mode 100644
index 0000000..605cc08
--- /dev/null
+++ b/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "arm,dyn_cfg-dtb_registry";
+
+		/* tb_fw_config is temporarily contained on this dtb */
+		tb_fw-config {
+			load-address = <0x0 0x4001010>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+
+		nt_fw-config {
+			load-address = <0x0 0xFEF00000>;
+			max-size = <0x0100000>;
+			id = <NT_FW_CONFIG_ID>;
+		};
+	};
+
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+};
diff --git a/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts b/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts
deleted file mode 100644
index b14d7ad..0000000
--- a/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/dts-v1/;
-
-/ {
-	/* Platform Config */
-	compatible = "arm,tb_fw";
-	nt_fw_config_addr = <0x0 0xFEF00000>;
-	nt_fw_config_max_size = <0x0100000>;
-	/*
-	 * The following two entries are placeholders for Mbed TLS
-	 * heap information. The default values don't matter since
-	 * they will be overwritten by BL1.
-	 * In case of having shared Mbed TLS heap between BL1 and BL2,
-	 * BL1 will populate these two properties with the respective
-	 * info about the shared heap. This info will be available for
-	 * BL2 in order to locate and re-use the heap.
-	 */
-	mbedtls_heap_addr = <0x0 0x0>;
-	mbedtls_heap_size = <0x0>;
-};
diff --git a/plat/arm/board/sgi575/platform.mk b/plat/arm/board/sgi575/platform.mk
index 76cc4e2..d91f829 100644
--- a/plat/arm/board/sgi575/platform.mk
+++ b/plat/arm/board/sgi575/platform.mk
@@ -35,8 +35,8 @@
 endif
 
 # Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES		+=	${SGI575_BASE}/fdts/${PLAT}_tb_fw_config.dts
-TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+FDT_SOURCES		+=	${SGI575_BASE}/fdts/${PLAT}_fw_config.dts
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
 
 # Add the TB_FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
diff --git a/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts b/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts
new file mode 100644
index 0000000..a0d0ea9
--- /dev/null
+++ b/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "arm,dyn_cfg-dtb_registry";
+
+		/* tb_fw_config is temporarily contained on this dtb */
+		tb_fw-config {
+			load-address = <0x0 0x4001010>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+
+		hw-config {
+			load-address = <0x0 0x83000000>;
+			max-size = <0x01000000>;
+			id = <HW_CONFIG_ID>;
+		};
+	};
+
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+	};
+};
diff --git a/plat/arm/board/sgm775/fdts/sgm775_tb_fw_config.dts b/plat/arm/board/sgm775/fdts/sgm775_tb_fw_config.dts
deleted file mode 100644
index 9502549..0000000
--- a/plat/arm/board/sgm775/fdts/sgm775_tb_fw_config.dts
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/dts-v1/;
-
-/ {
-	/* Platform Config */
-	plat_arm_bl2 {
-		compatible = "arm,tb_fw";
-		hw_config_addr = <0x0 0x83000000>;
-		hw_config_max_size = <0x01000000>;
-	};
-};
diff --git a/plat/arm/board/sgm775/platform.mk b/plat/arm/board/sgm775/platform.mk
index f096ca5..355b9ee 100644
--- a/plat/arm/board/sgm775/platform.mk
+++ b/plat/arm/board/sgm775/platform.mk
@@ -8,7 +8,7 @@
 
 SGM775_BASE= plat/arm/board/sgm775
 
-FDT_SOURCES += ${SGM775_BASE}/fdts/sgm775_tb_fw_config.dts
+FDT_SOURCES += ${SGM775_BASE}/fdts/sgm775_fw_config.dts
 
 PLAT_INCLUDES +=-I${SGM775_BASE}/include/
 
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index b19a7c3..c2f49c2 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,6 +11,7 @@
 #include <arch.h>
 #include <bl1/bl1.h>
 #include <common/bl_common.h>
+#include <lib/fconf/fconf.h>
 #include <lib/utils.h>
 #include <lib/xlat_tables/xlat_tables_compat.h>
 #include <plat/arm/common/plat_arm.h>
@@ -143,7 +144,10 @@
 {
 	/* Initialise the IO layer and register platform IO devices */
 	plat_arm_io_setup();
-	arm_load_tb_fw_config();
+
+	/* Load fw config */
+	fconf_load_config();
+
 #if TRUSTED_BOARD_BOOT
 	/* Share the Mbed TLS heap info with other images */
 	arm_bl1_set_mbedtls_heap();
@@ -184,9 +188,9 @@
  * On Arm platforms, the FWU process is triggered when the FIP image has
  * been tampered with.
  */
-int plat_arm_bl1_fwu_needed(void)
+bool plat_arm_bl1_fwu_needed(void)
 {
-	return (arm_io_is_toc_valid() != 1);
+	return !arm_io_is_toc_valid();
 }
 
 /*******************************************************************************
@@ -195,8 +199,5 @@
  ******************************************************************************/
 unsigned int bl1_plat_get_next_image_id(void)
 {
-	if (plat_arm_bl1_fwu_needed() != 0)
-		return NS_BL1U_IMAGE_ID;
-
-	return BL2_IMAGE_ID;
+	return plat_arm_bl1_fwu_needed() ? NS_BL1U_IMAGE_ID : BL2_IMAGE_ID;
 }
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 9adb1ea..dd39208 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -14,6 +14,7 @@
 #include <common/debug.h>
 #include <common/desc_image_load.h>
 #include <drivers/generic_delay_timer.h>
+#include <lib/fconf/fconf.h>
 #ifdef SPD_opteed
 #include <lib/optee_utils.h>
 #endif
@@ -58,11 +59,13 @@
 	/* Setup the BL2 memory layout */
 	bl2_tzram_layout = *mem_layout;
 
+	/* Fill the properties struct with the info from the config dtb */
+	if (tb_fw_config != 0U) {
+		fconf_populate(tb_fw_config);
+	}
+
 	/* Initialise the IO layer and register platform IO devices */
 	plat_arm_io_setup();
-
-	if (tb_fw_config != 0U)
-		arm_bl2_set_tb_cfg_addr((void *)tb_fw_config);
 }
 
 void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3)
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 9f4bc21..17058d1 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -177,12 +177,20 @@
 PLAT_BL_COMMON_SOURCES	+=	${XLAT_TABLES_LIB_SRCS}
 endif
 
+ifeq (${USE_FCONF_BASED_IO}, 0)
+ARM_IO_SOURCES		+=	plat/arm/common/arm_io_storage.c
+else
+ARM_IO_SOURCES		+=	plat/arm/common/arm_fconf_io_storage.c		\
+				plat/arm/common/fconf/arm_fconf_io.c
+endif
+
 BL1_SOURCES		+=	drivers/io/io_fip.c				\
 				drivers/io/io_memmap.c				\
 				drivers/io/io_storage.c				\
 				plat/arm/common/arm_bl1_setup.c			\
 				plat/arm/common/arm_err.c			\
-				plat/arm/common/arm_io_storage.c
+				${ARM_IO_SOURCES}
+
 ifdef EL3_PAYLOAD_BASE
 # Need the plat_arm_program_trusted_mailbox() function to release secondary CPUs from
 # their holding pen
@@ -196,7 +204,10 @@
 				drivers/io/io_storage.c				\
 				plat/arm/common/arm_bl2_setup.c			\
 				plat/arm/common/arm_err.c			\
-				plat/arm/common/arm_io_storage.c
+				${ARM_IO_SOURCES}
+
+# Firmware Configuration Framework sources
+include lib/fconf/fconf.mk
 
 # Add `libfdt` and Arm common helpers required for Dynamic Config
 include lib/libfdt/libfdt.mk
@@ -265,12 +276,20 @@
 				lib/extensions/pauth/pauth_helpers.S
 endif
 
+ifeq (${SPD},spmd)
+BL31_SOURCES		+=	plat/common/plat_spmd_manifest.c	\
+				common/fdt_wrappers.c			\
+				${LIBFDT_SRCS}
+
+endif
+
 ifneq (${TRUSTED_BOARD_BOOT},0)
 
     # Include common TBB sources
     AUTH_SOURCES	:=	drivers/auth/auth_mod.c				\
 				drivers/auth/crypto_mod.c			\
 				drivers/auth/img_parser_mod.c			\
+				lib/fconf/fconf_tbbr_getter.c
 
     # Include the selected chain of trust sources.
     ifeq (${COT},tbbr)
diff --git a/plat/arm/common/arm_dyn_cfg.c b/plat/arm/common/arm_dyn_cfg.c
index e6c5a73..443d40f 100644
--- a/plat/arm/common/arm_dyn_cfg.c
+++ b/plat/arm/common/arm_dyn_cfg.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,13 +16,13 @@
 #if TRUSTED_BOARD_BOOT
 #include <drivers/auth/mbedtls/mbedtls_config.h>
 #endif
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <lib/fconf/fconf_tbbr_getter.h>
 #include <plat/arm/common/arm_dyn_cfg_helpers.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 
-/* Variable to store the address to TB_FW_CONFIG passed from BL1 */
-static void *tb_fw_cfg_dtb;
-
 #if TRUSTED_BOARD_BOOT
 
 static void *mbedtls_heap_addr;
@@ -57,20 +57,10 @@
 
 #elif defined(IMAGE_BL2)
 
-	int err;
-
 	/* If in BL2, retrieve the already allocated heap's info from DTB */
-	if (tb_fw_cfg_dtb != NULL) {
-		err = arm_get_dtb_mbedtls_heap_info(tb_fw_cfg_dtb, heap_addr,
-			heap_size);
-		if (err < 0) {
-			ERROR("BL2: unable to retrieve shared Mbed TLS heap information from DTB\n");
-			panic();
-		}
-	} else {
-		ERROR("BL2: DTB missing, cannot get Mbed TLS heap\n");
-		panic();
-	}
+	*heap_addr = FCONF_GET_PROPERTY(tbbr, dyn_config, mbedtls_heap_addr);
+	*heap_size = FCONF_GET_PROPERTY(tbbr, dyn_config, mbedtls_heap_size);
+
 #endif
 
 	return 0;
@@ -83,6 +73,7 @@
 void arm_bl1_set_mbedtls_heap(void)
 {
 	int err;
+	uintptr_t tb_fw_cfg_dtb;
 
 	/*
 	 * If tb_fw_cfg_dtb==NULL then DTB is not present for the current
@@ -96,8 +87,15 @@
 	 * information, we would need to call plat_get_mbedtls_heap to retrieve
 	 * the default heap's address and size.
 	 */
-	if ((tb_fw_cfg_dtb != NULL) && (mbedtls_heap_addr != NULL)) {
-		err = arm_set_dtb_mbedtls_heap_info(tb_fw_cfg_dtb,
+
+	/* fconf FW_CONFIG and TB_FW_CONFIG are currently the same DTB*/
+	tb_fw_cfg_dtb = FCONF_GET_PROPERTY(fconf, dtb, base_addr);
+
+	if ((tb_fw_cfg_dtb != 0UL) && (mbedtls_heap_addr != NULL)) {
+		/* As libfdt use void *, we can't avoid this cast */
+		void *dtb = (void *)tb_fw_cfg_dtb;
+
+		err = arm_set_dtb_mbedtls_heap_info(dtb,
 			mbedtls_heap_addr, mbedtls_heap_size);
 		if (err < 0) {
 			ERROR("BL1: unable to write shared Mbed TLS heap information to DTB\n");
@@ -108,111 +106,34 @@
 		 * images. It's critical because BL2 won't be able to proceed
 		 * without the heap info.
 		 */
-		flush_dcache_range((uintptr_t)tb_fw_cfg_dtb,
-			fdt_totalsize(tb_fw_cfg_dtb));
+		flush_dcache_range(tb_fw_cfg_dtb, fdt_totalsize(dtb));
 	}
 }
 
 #endif /* TRUSTED_BOARD_BOOT */
 
 /*
- * Helper function to load TB_FW_CONFIG and populate the load information to
- * arg0 of BL2 entrypoint info.
- */
-void arm_load_tb_fw_config(void)
-{
-	int err;
-	uintptr_t config_base = 0UL;
-	image_desc_t *desc;
-
-	image_desc_t arm_tb_fw_info = {
-		.image_id = TB_FW_CONFIG_ID,
-		SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
-				VERSION_2, image_info_t, 0),
-		.image_info.image_base = ARM_TB_FW_CONFIG_BASE,
-		.image_info.image_max_size =
-			ARM_TB_FW_CONFIG_LIMIT - ARM_TB_FW_CONFIG_BASE
-	};
-
-	VERBOSE("BL1: Loading TB_FW_CONFIG\n");
-	err = load_auth_image(TB_FW_CONFIG_ID, &arm_tb_fw_info.image_info);
-	if (err != 0) {
-		/* Return if TB_FW_CONFIG is not loaded */
-		VERBOSE("Failed to load TB_FW_CONFIG\n");
-		return;
-	}
-
-	/* At this point we know that a DTB is indeed available */
-	config_base = arm_tb_fw_info.image_info.image_base;
-	tb_fw_cfg_dtb = (void *)config_base;
-
-	/* The BL2 ep_info arg0 is modified to point to TB_FW_CONFIG */
-	desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
-	assert(desc != NULL);
-	desc->ep_info.args.arg0 = config_base;
-
-	INFO("BL1: TB_FW_CONFIG loaded at address = 0x%lx\n", config_base);
-
-#if TRUSTED_BOARD_BOOT && defined(DYN_DISABLE_AUTH)
-	int tb_fw_node;
-	uint32_t disable_auth = 0;
-
-	err = arm_dyn_tb_fw_cfg_init((void *)config_base, &tb_fw_node);
-	if (err < 0) {
-		ERROR("Invalid TB_FW_CONFIG loaded\n");
-		panic();
-	}
-
-	err = arm_dyn_get_disable_auth((void *)config_base, tb_fw_node, &disable_auth);
-	if (err < 0)
-		return;
-
-	if (disable_auth == 1)
-		dyn_disable_auth();
-#endif
-}
-
-/*
- * BL2 utility function to set the address of TB_FW_CONFIG passed from BL1.
- */
-void arm_bl2_set_tb_cfg_addr(void *dtb)
-{
-	assert(dtb != NULL);
-	tb_fw_cfg_dtb = dtb;
-}
-
-/*
  * BL2 utility function to initialize dynamic configuration specified by
  * TB_FW_CONFIG. Populate the bl_mem_params_node_t of other FW_CONFIGs if
  * specified in TB_FW_CONFIG.
  */
 void arm_bl2_dyn_cfg_init(void)
 {
-	int err = 0, tb_fw_node;
 	unsigned int i;
 	bl_mem_params_node_t *cfg_mem_params = NULL;
-	uint64_t image_base;
-	uint32_t image_size;
+	uintptr_t image_base;
+	size_t image_size;
 	const unsigned int config_ids[] = {
 			HW_CONFIG_ID,
 			SOC_FW_CONFIG_ID,
 			NT_FW_CONFIG_ID,
-#ifdef SPD_tspd
-			/* Currently tos_fw_config is only present for TSP */
+#if defined(SPD_tspd) || defined(SPD_spmd)
+			/* tos_fw_config is only present for TSPD/SPMD */
 			TOS_FW_CONFIG_ID
 #endif
 	};
 
-	if (tb_fw_cfg_dtb == NULL) {
-		VERBOSE("No TB_FW_CONFIG specified\n");
-		return;
-	}
-
-	err = arm_dyn_tb_fw_cfg_init(tb_fw_cfg_dtb, &tb_fw_node);
-	if (err < 0) {
-		ERROR("Invalid TB_FW_CONFIG passed from BL1\n");
-		panic();
-	}
+	const struct dyn_cfg_dtb_info_t *dtb_info;
 
 	/* Iterate through all the fw config IDs */
 	for (i = 0; i < ARRAY_SIZE(config_ids); i++) {
@@ -223,14 +144,16 @@
 			continue;
 		}
 
-		err = arm_dyn_get_config_load_info(tb_fw_cfg_dtb, tb_fw_node,
-				config_ids[i], &image_base, &image_size);
-		if (err < 0) {
+		dtb_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, config_ids[i]);
+		if (dtb_info == NULL) {
 			VERBOSE("Couldn't find config_id %d load info in TB_FW_CONFIG\n",
 					config_ids[i]);
 			continue;
 		}
 
+		image_base = dtb_info->config_addr;
+		image_size = dtb_info->config_max_size;
+
 		/*
 		 * Do some runtime checks on the load addresses of soc_fw_config,
 		 * tos_fw_config, nt_fw_config. This is not a comprehensive check
@@ -262,8 +185,8 @@
 		}
 
 
-		cfg_mem_params->image_info.image_base = (uintptr_t)image_base;
-		cfg_mem_params->image_info.image_max_size = image_size;
+		cfg_mem_params->image_info.image_base = image_base;
+		cfg_mem_params->image_info.image_max_size = (uint32_t)image_size;
 
 		/*
 		 * Remove the IMAGE_ATTRIB_SKIP_LOADING attribute from
@@ -271,16 +194,4 @@
 		 */
 		cfg_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING;
 	}
-
-#if TRUSTED_BOARD_BOOT && defined(DYN_DISABLE_AUTH)
-	uint32_t disable_auth = 0;
-
-	err = arm_dyn_get_disable_auth(tb_fw_cfg_dtb, tb_fw_node,
-					&disable_auth);
-	if (err < 0)
-		return;
-
-	if (disable_auth == 1)
-		dyn_disable_auth();
-#endif
 }
diff --git a/plat/arm/common/arm_dyn_cfg_helpers.c b/plat/arm/common/arm_dyn_cfg_helpers.c
index daf0f0a..909c4a6 100644
--- a/plat/arm/common/arm_dyn_cfg_helpers.c
+++ b/plat/arm/common/arm_dyn_cfg_helpers.c
@@ -15,128 +15,6 @@
 #define DTB_PROP_MBEDTLS_HEAP_ADDR "mbedtls_heap_addr"
 #define DTB_PROP_MBEDTLS_HEAP_SIZE "mbedtls_heap_size"
 
-typedef struct config_load_info_prop {
-	unsigned int config_id;
-	const char *config_addr;
-	const char *config_max_size;
-} config_load_info_prop_t;
-
-static const config_load_info_prop_t prop_names[] = {
-	{HW_CONFIG_ID, "hw_config_addr", "hw_config_max_size"},
-	{SOC_FW_CONFIG_ID, "soc_fw_config_addr", "soc_fw_config_max_size"},
-	{TOS_FW_CONFIG_ID, "tos_fw_config_addr", "tos_fw_config_max_size"},
-	{NT_FW_CONFIG_ID, "nt_fw_config_addr", "nt_fw_config_max_size"}
-};
-
-/*******************************************************************************
- * Helper to read the load information corresponding to the `config_id` in
- * TB_FW_CONFIG. This function expects the following properties to be defined :
- *	<config>_addr		size : 2 cells
- *	<config>_max_size	size : 1 cell
- *
- * Arguments:
- *	void *dtb		 - pointer to the TB_FW_CONFIG in memory
- *	int node		 - The node offset to appropriate node in the
- *					 DTB.
- *	unsigned int config_id	 - The configuration id
- *	uint64_t *config_addr	 - Returns the `config` load address if read
- *					 is successful.
- *	uint32_t *config_size	 - Returns the `config` size if read is
- *					 successful.
- *
- * Returns 0 on success and -1 on error.
- ******************************************************************************/
-int arm_dyn_get_config_load_info(void *dtb, int node, unsigned int config_id,
-		uint64_t *config_addr, uint32_t *config_size)
-{
-	int err;
-	unsigned int i;
-
-	assert(dtb != NULL);
-	assert(config_addr != NULL);
-	assert(config_size != NULL);
-
-	for (i = 0; i < ARRAY_SIZE(prop_names); i++) {
-		if (prop_names[i].config_id == config_id)
-			break;
-	}
-
-	if (i == ARRAY_SIZE(prop_names)) {
-		WARN("Invalid config id %d\n", config_id);
-		return -1;
-	}
-
-	/* Check if the pointer to DT is correct */
-	assert(fdt_check_header(dtb) == 0);
-
-	/* Assert the node offset point to "arm,tb_fw" compatible property */
-	assert(node == fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw"));
-
-	err = fdtw_read_cells(dtb, node, prop_names[i].config_addr, 2,
-				(void *) config_addr);
-	if (err < 0) {
-		WARN("Read cell failed for %s\n", prop_names[i].config_addr);
-		return -1;
-	}
-
-	err = fdtw_read_cells(dtb, node, prop_names[i].config_max_size, 1,
-				(void *) config_size);
-	if (err < 0) {
-		WARN("Read cell failed for %s\n", prop_names[i].config_max_size);
-		return -1;
-	}
-
-	VERBOSE("Dyn cfg: Read config_id %d load info from TB_FW_CONFIG 0x%llx 0x%x\n",
-				config_id, (unsigned long long)*config_addr, *config_size);
-
-	return 0;
-}
-
-/*******************************************************************************
- * Helper to read the `disable_auth` property in config DTB. This function
- * expects the following properties to be present in the config DTB.
- *	name : disable_auth		size : 1 cell
- *
- * Arguments:
- *	void *dtb		 - pointer to the TB_FW_CONFIG in memory
- *	int node		 - The node offset to appropriate node in the
- *				   DTB.
- *	uint64_t *disable_auth	 - The value of `disable_auth` property on
- *				   successful read. Must be 0 or 1.
- *
- * Returns 0 on success and -1 on error.
- ******************************************************************************/
-int arm_dyn_get_disable_auth(void *dtb, int node, uint32_t *disable_auth)
-{
-	int err;
-
-	assert(dtb != NULL);
-	assert(disable_auth != NULL);
-
-	/* Check if the pointer to DT is correct */
-	assert(fdt_check_header(dtb) == 0);
-
-	/* Assert the node offset point to "arm,tb_fw" compatible property */
-	assert(node == fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw"));
-
-	/* Locate the disable_auth cell and read the value */
-	err = fdtw_read_cells(dtb, node, "disable_auth", 1, disable_auth);
-	if (err < 0) {
-		WARN("Read cell failed for `disable_auth`\n");
-		return -1;
-	}
-
-	/* Check if the value is boolean */
-	if ((*disable_auth != 0U) && (*disable_auth != 1U)) {
-		WARN("Invalid value for `disable_auth` cell %d\n", *disable_auth);
-		return -1;
-	}
-
-	VERBOSE("Dyn cfg: `disable_auth` cell found with value = %d\n",
-					*disable_auth);
-	return 0;
-}
-
 /*******************************************************************************
  * Validate the tb_fw_config is a valid DTB file and returns the node offset
  * to "arm,tb_fw" property.
@@ -169,47 +47,6 @@
 }
 
 /*
- * Reads and returns the Mbed TLS shared heap information from the DTB.
- * This function is supposed to be called *only* when a DTB is present.
- * This function is supposed to be called only by BL2.
- *
- * Returns:
- *	0 = success
- *	-1 = error. In this case the values of heap_addr, heap_size should be
- *	    considered as garbage by the caller.
- */
-int arm_get_dtb_mbedtls_heap_info(void *dtb, void **heap_addr,
-	size_t *heap_size)
-{
-	int err, dtb_root;
-
-	/* Verify the DTB is valid and get the root node */
-	err = arm_dyn_tb_fw_cfg_init(dtb, &dtb_root);
-	if (err < 0) {
-		ERROR("Invalid TB_FW_CONFIG. Cannot retrieve Mbed TLS heap information from DTB\n");
-		return -1;
-	}
-
-	/* Retrieve the Mbed TLS heap details from the DTB */
-	err = fdtw_read_cells(dtb, dtb_root,
-		DTB_PROP_MBEDTLS_HEAP_ADDR, 2, heap_addr);
-	if (err < 0) {
-		ERROR("Error while reading %s from DTB\n",
-			DTB_PROP_MBEDTLS_HEAP_ADDR);
-		return -1;
-	}
-	err = fdtw_read_cells(dtb, dtb_root,
-		DTB_PROP_MBEDTLS_HEAP_SIZE, 1, heap_size);
-	if (err < 0) {
-		ERROR("Error while reading %s from DTB\n",
-			DTB_PROP_MBEDTLS_HEAP_SIZE);
-		return -1;
-	}
-	return 0;
-}
-
-
-/*
  * This function writes the Mbed TLS heap address and size in the DTB. When it
  * is called, it is guaranteed that a DTB is available. However it is not
  * guaranteed that the shared Mbed TLS heap implementation is used. Thus we
diff --git a/plat/arm/common/arm_fconf_io_storage.c b/plat/arm/common/arm_fconf_io_storage.c
new file mode 100644
index 0000000..341622a
--- /dev/null
+++ b/plat/arm/common/arm_fconf_io_storage.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2015-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_fip.h>
+#include <drivers/io/io_memmap.h>
+#include <drivers/io/io_storage.h>
+#include <lib/utils.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <plat/arm/common/arm_fconf_getter.h>
+#include <plat/arm/common/arm_fconf_io_storage.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+
+/* IO devices */
+static const io_dev_connector_t *fip_dev_con;
+uintptr_t fip_dev_handle;
+static const io_dev_connector_t *memmap_dev_con;
+uintptr_t memmap_dev_handle;
+
+/* Weak definitions may be overridden in specific ARM standard platform */
+#pragma weak plat_arm_io_setup
+#pragma weak plat_arm_get_alt_image_source
+
+int open_fip(const uintptr_t spec)
+{
+	int result;
+	uintptr_t local_image_handle;
+
+	/* See if a Firmware Image Package is available */
+	result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
+	if (result == 0) {
+		result = io_open(fip_dev_handle, spec, &local_image_handle);
+		if (result == 0) {
+			VERBOSE("Using FIP\n");
+			io_close(local_image_handle);
+		}
+	}
+	return result;
+}
+
+int open_memmap(const uintptr_t spec)
+{
+	int result;
+	uintptr_t local_image_handle;
+
+	result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
+	if (result == 0) {
+		result = io_open(memmap_dev_handle, spec, &local_image_handle);
+		if (result == 0) {
+			VERBOSE("Using Memmap\n");
+			io_close(local_image_handle);
+		}
+	}
+	return result;
+}
+
+int arm_io_setup(void)
+{
+	int io_result;
+
+	io_result = register_io_dev_fip(&fip_dev_con);
+	if (io_result < 0) {
+		return io_result;
+	}
+
+	io_result = register_io_dev_memmap(&memmap_dev_con);
+	if (io_result < 0) {
+		return io_result;
+	}
+
+	/* Open connections to devices and cache the handles */
+	io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
+				&fip_dev_handle);
+	if (io_result < 0) {
+		return io_result;
+	}
+
+	io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
+				&memmap_dev_handle);
+
+	return io_result;
+}
+
+void plat_arm_io_setup(void)
+{
+	int err;
+
+	err = arm_io_setup();
+	if (err < 0) {
+		panic();
+	}
+}
+
+int plat_arm_get_alt_image_source(
+	unsigned int image_id __unused,
+	uintptr_t *dev_handle __unused,
+	uintptr_t *image_spec __unused)
+{
+	/* By default do not try an alternative */
+	return -ENOENT;
+}
+
+/* Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+			  uintptr_t *image_spec)
+{
+	int result;
+	const struct plat_io_policy *policy;
+
+	assert(image_id < MAX_NUMBER_IDS);
+
+	policy = FCONF_GET_PROPERTY(arm, io_policies, image_id);
+	result = policy->check(policy->image_spec);
+	if (result == 0) {
+		*image_spec = policy->image_spec;
+		*dev_handle = *(policy->dev_handle);
+	} else {
+		VERBOSE("Trying alternative IO\n");
+		result = plat_arm_get_alt_image_source(image_id, dev_handle,
+						       image_spec);
+	}
+
+	return result;
+}
+
+/*
+ * See if a Firmware Image Package is available,
+ * by checking if TOC is valid or not.
+ */
+bool arm_io_is_toc_valid(void)
+{
+	return (io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID) == 0);
+}
diff --git a/plat/arm/common/arm_io_storage.c b/plat/arm/common/arm_io_storage.c
index fc1eb49..f5d8a41 100644
--- a/plat/arm/common/arm_io_storage.c
+++ b/plat/arm/common/arm_io_storage.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -292,32 +292,41 @@
 }
 
 
-void arm_io_setup(void)
+int arm_io_setup(void)
 {
 	int io_result;
 
 	io_result = register_io_dev_fip(&fip_dev_con);
-	assert(io_result == 0);
+	if (io_result < 0) {
+		return io_result;
+	}
 
 	io_result = register_io_dev_memmap(&memmap_dev_con);
-	assert(io_result == 0);
+	if (io_result < 0) {
+		return io_result;
+	}
 
 	/* Open connections to devices and cache the handles */
 	io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
 				&fip_dev_handle);
-	assert(io_result == 0);
+	if (io_result < 0) {
+		return io_result;
+	}
 
 	io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
 				&memmap_dev_handle);
-	assert(io_result == 0);
 
-	/* Ignore improbable errors in release builds */
-	(void)io_result;
+	return io_result;
 }
 
 void plat_arm_io_setup(void)
 {
-	arm_io_setup();
+	int err;
+
+	err = arm_io_setup();
+	if (err < 0) {
+		panic();
+	}
 }
 
 int plat_arm_get_alt_image_source(
@@ -357,12 +366,8 @@
  * See if a Firmware Image Package is available,
  * by checking if TOC is valid or not.
  */
-int arm_io_is_toc_valid(void)
+bool arm_io_is_toc_valid(void)
 {
-	int result;
-
-	result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
-
-	return (result == 0);
+	return (io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID) == 0);
 }
 
diff --git a/plat/arm/common/fconf/arm_fconf_io.c b/plat/arm/common/fconf/arm_fconf_io.c
new file mode 100644
index 0000000..3c0586f
--- /dev/null
+++ b/plat/arm/common/fconf/arm_fconf_io.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <drivers/io/io_storage.h>
+#include <lib/object_pool.h>
+#include <libfdt.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <plat/arm/common/arm_fconf_getter.h>
+#include <plat/arm/common/arm_fconf_io_storage.h>
+#include <platform_def.h>
+
+const io_block_spec_t fip_block_spec = {
+	.offset = PLAT_ARM_FIP_BASE,
+	.length = PLAT_ARM_FIP_MAX_SIZE
+};
+
+const io_uuid_spec_t arm_uuid_spec[MAX_NUMBER_IDS] = {
+	[BL2_IMAGE_ID] = {UUID_TRUSTED_BOOT_FIRMWARE_BL2},
+	[TB_FW_CONFIG_ID] = {UUID_TB_FW_CONFIG},
+#if TRUSTED_BOARD_BOOT
+	[TRUSTED_BOOT_FW_CERT_ID] = {UUID_TRUSTED_BOOT_FW_CERT},
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+/* By default, ARM platforms load images from the FIP */
+struct plat_io_policy policies[MAX_NUMBER_IDS] = {
+	[FIP_IMAGE_ID] = {
+		&memmap_dev_handle,
+		(uintptr_t)&fip_block_spec,
+		open_memmap
+	},
+	[BL2_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&arm_uuid_spec[BL2_IMAGE_ID],
+		open_fip
+	},
+	[TB_FW_CONFIG_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&arm_uuid_spec[TB_FW_CONFIG_ID],
+		open_fip
+	},
+#if TRUSTED_BOARD_BOOT
+	[TRUSTED_BOOT_FW_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&arm_uuid_spec[TRUSTED_BOOT_FW_CERT_ID],
+		open_fip
+	},
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+#ifdef IMAGE_BL2
+
+#if TRUSTED_BOARD_BOOT
+#define FCONF_ARM_IO_UUID_NUMBER	19
+#else
+#define FCONF_ARM_IO_UUID_NUMBER	10
+#endif
+
+static io_uuid_spec_t fconf_arm_uuids[FCONF_ARM_IO_UUID_NUMBER];
+static OBJECT_POOL_ARRAY(fconf_arm_uuids_pool, fconf_arm_uuids);
+
+struct policies_load_info {
+	unsigned int image_id;
+	const char *name;
+};
+
+/* image id to property name table */
+static const struct policies_load_info load_info[FCONF_ARM_IO_UUID_NUMBER] = {
+	{SCP_BL2_IMAGE_ID, "scp_bl2_uuid"},
+	{BL31_IMAGE_ID, "bl31_uuid"},
+	{BL32_IMAGE_ID, "bl32_uuid"},
+	{BL32_EXTRA1_IMAGE_ID, "bl32_extra1_uuid"},
+	{BL32_EXTRA2_IMAGE_ID, "bl32_extra2_uuid"},
+	{BL33_IMAGE_ID, "bl33_uuid"},
+	{HW_CONFIG_ID, "hw_cfg_uuid"},
+	{SOC_FW_CONFIG_ID, "soc_fw_cfg_uuid"},
+	{TOS_FW_CONFIG_ID, "tos_fw_cfg_uuid"},
+	{NT_FW_CONFIG_ID, "nt_fw_cfg_uuid"},
+#if TRUSTED_BOARD_BOOT
+	{TRUSTED_KEY_CERT_ID, "t_key_cert_uuid"},
+	{SCP_FW_KEY_CERT_ID, "scp_fw_key_uuid"},
+	{SOC_FW_KEY_CERT_ID, "soc_fw_key_uuid"},
+	{TRUSTED_OS_FW_KEY_CERT_ID, "tos_fw_key_cert_uuid"},
+	{NON_TRUSTED_FW_KEY_CERT_ID, "nt_fw_key_cert_uuid"},
+	{SCP_FW_CONTENT_CERT_ID, "scp_fw_content_cert_uuid"},
+	{SOC_FW_CONTENT_CERT_ID, "soc_fw_content_cert_uuid"},
+	{TRUSTED_OS_FW_CONTENT_CERT_ID, "tos_fw_content_cert_uuid"},
+	{NON_TRUSTED_FW_CONTENT_CERT_ID, "nt_fw_content_cert_uuid"},
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+int fconf_populate_arm_io_policies(uintptr_t config)
+{
+	int err, node;
+	unsigned int i;
+
+	union uuid_helper_t uuid_helper;
+	io_uuid_spec_t *uuid_ptr;
+
+	/* As libfdt uses void *, we can't avoid this cast */
+	const void *dtb = (void *)config;
+
+	/* Assert the node offset point to "arm,io-fip-handle" compatible property */
+	const char *compatible_str = "arm,io-fip-handle";
+	node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+	if (node < 0) {
+		ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str);
+		return node;
+	}
+
+	/* Locate the uuid cells and read the value for all the load info uuid */
+	for (i = 0; i < FCONF_ARM_IO_UUID_NUMBER; i++) {
+		uuid_ptr = pool_alloc(&fconf_arm_uuids_pool);
+		err = fdtw_read_array(dtb, node, load_info[i].name, 4, &uuid_helper.word);
+		if (err < 0) {
+			WARN("FCONF: Read cell failed for %s\n", load_info[i].name);
+			return err;
+		}
+
+		VERBOSE("FCONF: arm-io_policies.%s cell found with value = 0x%x 0x%x 0x%x 0x%x\n",
+			load_info[i].name,
+			uuid_helper.word[0], uuid_helper.word[1],
+			uuid_helper.word[2], uuid_helper.word[3]);
+
+		uuid_ptr->uuid = uuid_helper.uuid_struct;
+		policies[load_info[i].image_id].image_spec = (uintptr_t)uuid_ptr;
+		policies[load_info[i].image_id].dev_handle = &fip_dev_handle;
+		policies[load_info[i].image_id].check = open_fip;
+	}
+	return 0;
+}
+
+FCONF_REGISTER_POPULATOR(arm_io, fconf_populate_arm_io_policies);
+
+#endif /* IMAGE_BL2 */
diff --git a/plat/common/plat_spmd_manifest.c b/plat/common/plat_spmd_manifest.c
new file mode 100644
index 0000000..4c78979
--- /dev/null
+++ b/plat/common/plat_spmd_manifest.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <libfdt.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <errno.h>
+#include <platform_def.h>
+#include <services/spm_core_manifest.h>
+
+/*******************************************************************************
+ * Attribute section handler
+ ******************************************************************************/
+static int manifest_parse_attribute(spmc_manifest_sect_attribute_t *attr,
+				    const void *fdt,
+				    int node)
+{
+	int rc = 0;
+
+	assert(attr && fdt);
+
+	rc = fdtw_read_cells(fdt, node, "maj_ver", 1, &attr->major_version);
+	if (rc) {
+		ERROR("Missing SPCI major version in SPM core manifest.\n");
+		return -ENOENT;
+	}
+
+	rc = fdtw_read_cells(fdt, node, "min_ver", 1, &attr->minor_version);
+	if (rc) {
+		ERROR("Missing SPCI minor version in SPM core manifest.\n");
+		return -ENOENT;
+	}
+
+	rc = fdtw_read_cells(fdt, node, "runtime_el", 1, &attr->runtime_el);
+	if (rc) {
+		ERROR("Missing SPM core runtime EL in manifest.\n");
+		return -ENOENT;
+	}
+
+	rc = fdtw_read_cells(fdt, node, "exec_state", 1, &attr->exec_state);
+	if (rc)
+		NOTICE("Execution state not specified in SPM core manifest.\n");
+
+	rc = fdtw_read_cells(fdt, node, "binary_size", 1, &attr->binary_size);
+	if (rc)
+		NOTICE("Binary size not specified in SPM core manifest.\n");
+
+	rc = fdtw_read_cells(fdt, node, "load_address", 2, &attr->load_address);
+	if (rc)
+		NOTICE("Load address not specified in SPM core manifest.\n");
+
+	rc = fdtw_read_cells(fdt, node, "entrypoint", 2, &attr->entrypoint);
+	if (rc)
+		NOTICE("Entrypoint not specified in SPM core manifest.\n");
+
+	VERBOSE("SPM core manifest attribute section:\n");
+	VERBOSE("  version: %x.%x\n", attr->major_version, attr->minor_version);
+	VERBOSE("  runtime_el: 0x%x\n", attr->runtime_el);
+	VERBOSE("  binary_size: 0x%x\n", attr->binary_size);
+	VERBOSE("  load_address: 0x%llx\n", attr->load_address);
+	VERBOSE("  entrypoint: 0x%llx\n", attr->entrypoint);
+
+	return 0;
+}
+
+/*******************************************************************************
+ * Root node handler
+ ******************************************************************************/
+static int manifest_parse_root(spmc_manifest_sect_attribute_t *manifest,
+				const void *fdt,
+				int root)
+{
+	int node;
+	char *str;
+
+	str = "attribute";
+	node = fdt_subnode_offset_namelen(fdt, root, str, strlen(str));
+	if (node < 0) {
+		ERROR("Root node doesn't contain subnode '%s'\n", str);
+		return -ENOENT;
+	}
+
+	return manifest_parse_attribute(manifest, fdt, node);
+}
+
+/*******************************************************************************
+ * Platform handler to parse a SPM core manifest.
+ ******************************************************************************/
+int plat_spm_core_manifest_load(spmc_manifest_sect_attribute_t *manifest,
+				const void *ptr,
+				size_t size)
+{
+	int rc;
+	int root_node;
+
+	assert(manifest != NULL);
+	assert(ptr != NULL);
+
+	INFO("Reading SPM core manifest at address %p\n", ptr);
+
+	rc = fdt_check_header(ptr);
+	if (rc != 0) {
+		ERROR("Wrong format for SPM core manifest (%d).\n", rc);
+		return -EINVAL;
+	}
+
+	INFO("Reading SPM core manifest at address %p\n", ptr);
+
+	root_node = fdt_node_offset_by_compatible(ptr, -1,
+				"arm,spci-core-manifest-1.0");
+	if (root_node < 0) {
+		ERROR("Unrecognized SPM core manifest\n");
+		return -ENOENT;
+	}
+
+	INFO("Reading SPM core manifest at address %p\n", ptr);
+	return manifest_parse_root(manifest, ptr, root_node);
+}
diff --git a/plat/intel/soc/agilex/bl2_plat_setup.c b/plat/intel/soc/agilex/bl2_plat_setup.c
index 9587d48..f328207 100644
--- a/plat/intel/soc/agilex/bl2_plat_setup.c
+++ b/plat/intel/soc/agilex/bl2_plat_setup.c
@@ -46,7 +46,7 @@
 	{0},
 };
 
-boot_source_type boot_source;
+boot_source_type boot_source = BOOT_SOURCE;
 
 void bl2_el3_early_platform_setup(u_register_t x0, u_register_t x1,
 				u_register_t x2, u_register_t x4)
@@ -59,7 +59,6 @@
 	if (socfpga_get_handoff(&reverse_handoff_ptr))
 		return;
 	config_pinmux(&reverse_handoff_ptr);
-	boot_source = reverse_handoff_ptr.boot_source;
 	config_clkmgr_handoff(&reverse_handoff_ptr);
 
 	enable_nonsecure_access();
diff --git a/plat/intel/soc/agilex/include/socfpga_plat_def.h b/plat/intel/soc/agilex/include/socfpga_plat_def.h
index b4e0921..6c9d81c 100644
--- a/plat/intel/soc/agilex/include/socfpga_plat_def.h
+++ b/plat/intel/soc/agilex/include/socfpga_plat_def.h
@@ -12,6 +12,7 @@
 
 /* Platform Setting */
 #define PLATFORM_MODEL				PLAT_SOCFPGA_AGILEX
+#define BOOT_SOURCE				BOOT_SOURCE_SDMMC
 
 /* Register Mapping */
 #define SOCFPGA_MMC_REG_BASE			0xff808000
diff --git a/plat/intel/soc/common/include/socfpga_handoff.h b/plat/intel/soc/common/include/socfpga_handoff.h
index 889d137..ba0f7f3 100644
--- a/plat/intel/soc/common/include/socfpga_handoff.h
+++ b/plat/intel/soc/common/include/socfpga_handoff.h
@@ -125,7 +125,6 @@
 	uint32_t	misc_magic;
 	uint32_t	misc_length;
 	uint32_t	_pad_0x618_0x620[2];
-	uint32_t	boot_source;
 } handoff;
 
 int verify_handoff_image(handoff *hoff_ptr, handoff *reverse_hoff_ptr);
diff --git a/plat/intel/soc/stratix10/bl2_plat_setup.c b/plat/intel/soc/stratix10/bl2_plat_setup.c
index 7d183db..78ca253 100644
--- a/plat/intel/soc/stratix10/bl2_plat_setup.c
+++ b/plat/intel/soc/stratix10/bl2_plat_setup.c
@@ -45,7 +45,7 @@
 	{0},
 };
 
-boot_source_type boot_source;
+boot_source_type boot_source = BOOT_SOURCE;
 
 void bl2_el3_early_platform_setup(u_register_t x0, u_register_t x1,
 				u_register_t x2, u_register_t x4)
@@ -58,7 +58,6 @@
 	if (socfpga_get_handoff(&reverse_handoff_ptr))
 		return;
 	config_pinmux(&reverse_handoff_ptr);
-	boot_source = reverse_handoff_ptr.boot_source;
 
 	config_clkmgr_handoff(&reverse_handoff_ptr);
 	enable_nonsecure_access();
diff --git a/plat/intel/soc/stratix10/include/socfpga_plat_def.h b/plat/intel/soc/stratix10/include/socfpga_plat_def.h
index 9dc5151..a2bd57b 100644
--- a/plat/intel/soc/stratix10/include/socfpga_plat_def.h
+++ b/plat/intel/soc/stratix10/include/socfpga_plat_def.h
@@ -10,7 +10,8 @@
 #include <platform_def.h>
 
 /* Platform Setting */
-#define PLATFORM_MODEL		PLAT_SOCFPGA_STRATIX10
+#define PLATFORM_MODEL				PLAT_SOCFPGA_STRATIX10
+#define BOOT_SOURCE				BOOT_SOURCE_SDMMC
 
 /* Register Mapping */
 #define SOCFPGA_MMC_REG_BASE                    0xff808000
diff --git a/plat/marvell/a8k/common/mss/mss_a8k.mk b/plat/marvell/a8k/common/mss/mss_a8k.mk
index 58f23d8..efd03c5 100644
--- a/plat/marvell/a8k/common/mss/mss_a8k.mk
+++ b/plat/marvell/a8k/common/mss/mss_a8k.mk
@@ -8,7 +8,8 @@
 PLAT_MARVELL		:=	plat/marvell
 A8K_MSS_SOURCE		:=	$(PLAT_MARVELL)/a8k/common/mss
 
-BL2_SOURCES		+=	$(A8K_MSS_SOURCE)/mss_bl2_setup.c
+BL2_SOURCES		+=	$(A8K_MSS_SOURCE)/mss_bl2_setup.c \
+				$(MARVELL_MOCHI_DRV)
 
 BL31_SOURCES		+=	$(A8K_MSS_SOURCE)/mss_pm_ipc.c
 
diff --git a/plat/marvell/a8k/common/mss/mss_bl2_setup.c b/plat/marvell/a8k/common/mss/mss_bl2_setup.c
index 728ee54..09b8446 100644
--- a/plat/marvell/a8k/common/mss/mss_bl2_setup.c
+++ b/plat/marvell/a8k/common/mss/mss_bl2_setup.c
@@ -74,6 +74,12 @@
 	/* Set the default target id to PIDI */
 	mmio_write_32(MVEBU_IO_WIN_BASE(MVEBU_AP0) + IOW_GCR_OFFSET, PIDI_TID);
 
+	/* Open AMB bridge required for MG access */
+	cp110_amb_init(MVEBU_CP_REGS_BASE(0));
+
+	if (CP_COUNT == 2)
+		cp110_amb_init(MVEBU_CP_REGS_BASE(1));
+
 	return 0;
 }
 
diff --git a/plat/marvell/common/mss/mss_scp_bl2_format.h b/plat/marvell/common/mss/mss_scp_bl2_format.h
index 7cf8d32..7150f0a 100644
--- a/plat/marvell/common/mss/mss_scp_bl2_format.h
+++ b/plat/marvell/common/mss/mss_scp_bl2_format.h
@@ -8,7 +8,7 @@
 #ifndef MSS_SCP_BL2_FORMAT_H
 #define MSS_SCP_BL2_FORMAT_H
 
-#define MAX_NR_OF_FILES	5
+#define MAX_NR_OF_FILES	8
 #define FILE_MAGIC	0xddd01ff
 #define HEADER_VERSION	0x1
 
@@ -31,6 +31,7 @@
 	MSS_CP3,
 	MG_CP0,
 	MG_CP1,
+	MG_CP2,
 };
 
 typedef struct img_header {
diff --git a/plat/marvell/common/mss/mss_scp_bootloader.c b/plat/marvell/common/mss/mss_scp_bootloader.c
index 7e442c6..4473d81 100644
--- a/plat/marvell/common/mss/mss_scp_bootloader.c
+++ b/plat/marvell/common/mss/mss_scp_bootloader.c
@@ -42,6 +42,8 @@
 
 #define MSS_HANDSHAKE_TIMEOUT		50
 
+#define MG_CM3_SRAM_BASE(CP)		(MVEBU_CP_REGS_BASE(CP) + 0x100000)
+
 static int mss_check_image_ready(volatile struct mss_pm_ctrl_block *mss_pm_crtl)
 {
 	int timeout = MSS_HANDSHAKE_TIMEOUT;
@@ -59,6 +61,28 @@
 	return 0;
 }
 
+static int mg_image_load(uintptr_t src_addr, uint32_t size, uintptr_t mg_regs)
+{
+	if (size > MG_SRAM_SIZE) {
+		ERROR("image is too big to fit into MG CM3 memory\n");
+		return 1;
+	}
+
+	NOTICE("Loading MG image from address 0x%lx Size 0x%x to MG at 0x%lx\n",
+	       src_addr, size, mg_regs);
+
+	/* Copy image to MG CM3 SRAM */
+	memcpy((void *)mg_regs, (void *)src_addr, size);
+
+	/*
+	 * Don't release MG CM3 from reset - it will be done by next step
+	 * bootloader (e.g. U-Boot), when appriopriate device-tree setup (which
+	 * has enabeld 802.3. auto-neg) will be choosen.
+	 */
+
+	return 0;
+}
+
 static int mss_image_load(uint32_t src_addr, uint32_t size, uintptr_t mss_regs)
 {
 	uint32_t i, loop_num, timeout;
@@ -225,12 +249,21 @@
 		}
 		break;
 	case MG_CP0:
-		/* TODO: */
-		NOTICE("Load image to CP0 MG not supported\n");
-		break;
 	case MG_CP1:
-		/* TODO: */
-		NOTICE("Load image to CP1 MG not supported\n");
+	case MG_CP2:
+		cp_index = cm3_type - MG_CP0;
+		if (bl2_plat_get_cp_count(0) <= cp_index) {
+			NOTICE("Skipping MG CP%d related image\n",
+			       cp_index);
+			break;
+		}
+		NOTICE("Load image to CP%d MG\n", cp_index);
+		ret = mg_image_load(single_img, image_size,
+				    MG_CM3_SRAM_BASE(cp_index));
+		if (ret != 0) {
+			ERROR("SCP Image load failed\n");
+			return -1;
+		}
 		break;
 	default:
 		ERROR("SCP_BL2 wrong img format (cm3_type=%d)\n", cm3_type);
@@ -261,7 +294,7 @@
 	}
 
 	if (file_hdr->nr_of_imgs > MAX_NR_OF_FILES) {
-		ERROR("SCP_BL2 concatenated image contains to many images\n");
+		ERROR("SCP_BL2 concatenated image contains too many images\n");
 		return -1;
 	}
 
diff --git a/plat/renesas/rcar/bl2_plat_setup.c b/plat/renesas/rcar/bl2_plat_setup.c
index 578892e..8910967 100644
--- a/plat/renesas/rcar/bl2_plat_setup.c
+++ b/plat/renesas/rcar/bl2_plat_setup.c
@@ -16,6 +16,8 @@
 #include <common/debug.h>
 #include <common/desc_image_load.h>
 #include <drivers/console.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_storage.h>
 #include <lib/mmio.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 #include <plat/common/platform.h>
@@ -33,6 +35,7 @@
 #endif
 
 #include "io_common.h"
+#include "io_rcar.h"
 #include "qos_init.h"
 #include "rcar_def.h"
 #include "rcar_private.h"
@@ -382,10 +385,28 @@
 	return 0;
 }
 
+static uint64_t rcar_get_dest_addr_from_cert(uint32_t certid, uintptr_t *dest)
+{
+	uint32_t cert, len;
+	int ret;
+
+	ret = rcar_get_certificate(certid, &cert);
+	if (ret) {
+		ERROR("%s : cert file load error", __func__);
+		return 1;
+	}
+
+	rcar_read_certificate((uint64_t) cert, &len, dest);
+
+	return 0;
+}
+
 int bl2_plat_handle_post_image_load(unsigned int image_id)
 {
 	static bl2_to_bl31_params_mem_t *params;
 	bl_mem_params_node_t *bl_mem_params;
+	uintptr_t dest;
+	int ret;
 
 	if (!params) {
 		params = (bl2_to_bl31_params_mem_t *) PARAMS_BASE;
@@ -396,8 +417,17 @@
 
 	switch (image_id) {
 	case BL31_IMAGE_ID:
+		ret = rcar_get_dest_addr_from_cert(SOC_FW_CONTENT_CERT_ID,
+						   &dest);
+		if (!ret)
+			bl_mem_params->image_info.image_base = dest;
 		break;
 	case BL32_IMAGE_ID:
+		ret = rcar_get_dest_addr_from_cert(TRUSTED_OS_FW_CONTENT_CERT_ID,
+						   &dest);
+		if (!ret)
+			bl_mem_params->image_info.image_base = dest;
+
 		memcpy(&params->bl32_ep_info, &bl_mem_params->ep_info,
 			sizeof(entry_point_info_t));
 		break;
diff --git a/plat/renesas/rcar/include/rcar_version.h b/plat/renesas/rcar/include/rcar_version.h
index 2d400e0..67cbd71 100644
--- a/plat/renesas/rcar/include/rcar_version.h
+++ b/plat/renesas/rcar/include/rcar_version.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,8 +9,8 @@
 
 #include <arch_helpers.h>
 
-#define VERSION_OF_RENESAS		"2.0.4"
-#define	VERSION_OF_RENESAS_MAXLEN	(128)
+#define VERSION_OF_RENESAS		"2.0.6"
+#define VERSION_OF_RENESAS_MAXLEN	128
 
 extern const uint8_t version_of_renesas[VERSION_OF_RENESAS_MAXLEN];
 
diff --git a/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c b/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c
index 4f58b68..091a6f7 100644
--- a/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c
+++ b/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c
@@ -4,16 +4,25 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <errno.h>
+
 #include <platform_def.h>
 
 #include <common/bl_common.h>
 #include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <plat/common/platform.h>
 
 #include "../uniphier.h"
 
+static unsigned int uniphier_soc = UNIPHIER_SOC_UNKNOWN;
+
 void tsp_early_platform_setup(void)
 {
-	uniphier_console_setup();
+	uniphier_soc = uniphier_get_soc_id();
+	if (uniphier_soc == UNIPHIER_SOC_UNKNOWN)
+		plat_error_handler(-ENOTSUP);
+
+	uniphier_console_setup(uniphier_soc);
 }
 
 void tsp_platform_setup(void)
@@ -22,6 +31,6 @@
 
 void tsp_plat_arch_setup(void)
 {
-	uniphier_mmap_setup();
+	uniphier_mmap_setup(uniphier_soc);
 	enable_mmu_el1(0);
 }
diff --git a/plat/socionext/uniphier/uniphier.h b/plat/socionext/uniphier/uniphier.h
index 729dc5c..ee520ad 100644
--- a/plat/socionext/uniphier/uniphier.h
+++ b/plat/socionext/uniphier/uniphier.h
@@ -25,7 +25,8 @@
 #define UNIPHIER_BOOT_DEVICE_EMMC	0
 #define UNIPHIER_BOOT_DEVICE_NAND	1
 #define UNIPHIER_BOOT_DEVICE_NOR	2
-#define UNIPHIER_BOOT_DEVICE_USB	3
+#define UNIPHIER_BOOT_DEVICE_SD		3
+#define UNIPHIER_BOOT_DEVICE_USB	4
 #define UNIPHIER_BOOT_DEVICE_RSV	0xffffffff
 
 unsigned int uniphier_get_boot_master(unsigned int soc);
@@ -34,11 +35,13 @@
 #define UNIPHIER_BOOT_MASTER_SCP	1
 #define UNIPHIER_BOOT_MASTER_EXT	2
 
-void uniphier_console_setup(void);
+void uniphier_console_setup(unsigned int soc);
 
 struct io_block_dev_spec;
-int uniphier_emmc_init(struct io_block_dev_spec **block_dev_spec);
-int uniphier_nand_init(struct io_block_dev_spec **block_dev_spec);
+int uniphier_emmc_init(unsigned int soc,
+		       struct io_block_dev_spec **block_dev_spec);
+int uniphier_nand_init(unsigned int soc,
+		       struct io_block_dev_spec **block_dev_spec);
 int uniphier_usb_init(unsigned int soc,
 		      struct io_block_dev_spec **block_dev_spec);
 
@@ -54,7 +57,7 @@
 void uniphier_scp_system_off(void);
 void uniphier_scp_system_reset(void);
 
-void uniphier_mmap_setup(void);
+void uniphier_mmap_setup(unsigned int soc);
 
 void uniphier_cci_init(unsigned int soc);
 void uniphier_cci_enable(void);
@@ -66,6 +69,8 @@
 void uniphier_gic_cpuif_disable(void);
 void uniphier_gic_pcpu_init(void);
 
+void uniphier_psci_init(unsigned int soc);
+
 unsigned int uniphier_calc_core_pos(u_register_t mpidr);
 
 #endif /* UNIPHIER_H */
diff --git a/plat/socionext/uniphier/uniphier_bl2_setup.c b/plat/socionext/uniphier/uniphier_bl2_setup.c
index 11d837c..7a7f786 100644
--- a/plat/socionext/uniphier/uniphier_bl2_setup.c
+++ b/plat/socionext/uniphier/uniphier_bl2_setup.c
@@ -25,39 +25,37 @@
 #define UNIPHIER_IMAGE_BUF_SIZE		0x00100000UL
 
 static uintptr_t uniphier_mem_base = UNIPHIER_MEM_BASE;
+static unsigned int uniphier_soc = UNIPHIER_SOC_UNKNOWN;
 static int uniphier_bl2_kick_scp;
 
 void bl2_el3_early_platform_setup(u_register_t x0, u_register_t x1,
 				  u_register_t x2, u_register_t x3)
 {
-	uniphier_console_setup();
+	uniphier_soc = uniphier_get_soc_id();
+	if (uniphier_soc == UNIPHIER_SOC_UNKNOWN)
+		plat_error_handler(-ENOTSUP);
+
+	uniphier_console_setup(uniphier_soc);
 }
 
 void bl2_el3_plat_arch_setup(void)
 {
-	unsigned int soc;
 	int skip_scp = 0;
 	int ret;
 
-	uniphier_mmap_setup();
+	uniphier_mmap_setup(uniphier_soc);
 	enable_mmu_el3(0);
 
 	/* add relocation offset (run-time-address - link-address) */
 	uniphier_mem_base += BL_CODE_BASE - BL2_BASE;
 
-	soc = uniphier_get_soc_id();
-	if (soc == UNIPHIER_SOC_UNKNOWN) {
-		ERROR("unsupported SoC\n");
-		plat_error_handler(-ENOTSUP);
-	}
-
-	ret = uniphier_io_setup(soc, uniphier_mem_base);
+	ret = uniphier_io_setup(uniphier_soc, uniphier_mem_base);
 	if (ret) {
 		ERROR("failed to setup io devices\n");
 		plat_error_handler(ret);
 	}
 
-	switch (uniphier_get_boot_master(soc)) {
+	switch (uniphier_get_boot_master(uniphier_soc)) {
 	case UNIPHIER_BOOT_MASTER_THIS:
 		INFO("Booting from this SoC\n");
 		skip_scp = 1;
diff --git a/plat/socionext/uniphier/uniphier_bl31_setup.c b/plat/socionext/uniphier/uniphier_bl31_setup.c
index 47f2378..f2f0b29 100644
--- a/plat/socionext/uniphier/uniphier_bl31_setup.c
+++ b/plat/socionext/uniphier/uniphier_bl31_setup.c
@@ -21,6 +21,7 @@
 
 static entry_point_info_t bl32_image_ep_info;
 static entry_point_info_t bl33_image_ep_info;
+static unsigned int uniphier_soc = UNIPHIER_SOC_UNKNOWN;
 
 entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
 {
@@ -37,7 +38,11 @@
 
 	bl_params_node_t *bl_params = ((bl_params_t *)from_bl2)->head;
 
-	uniphier_console_setup();
+	uniphier_soc = uniphier_get_soc_id();
+	if (uniphier_soc == UNIPHIER_SOC_UNKNOWN)
+		plat_error_handler(-ENOTSUP);
+
+	uniphier_console_setup(uniphier_soc);
 
 	while (bl_params) {
 		if (bl_params->image_id == BL32_IMAGE_ID)
@@ -53,32 +58,34 @@
 		panic();
 }
 
-#define UNIPHIER_SYS_CNTCTL_BASE	0x60E00000
+static const uintptr_t uniphier_cntctl_base[] = {
+	[UNIPHIER_SOC_LD11] = 0x60e00000,
+	[UNIPHIER_SOC_LD20] = 0x60e00000,
+	[UNIPHIER_SOC_PXS3] = 0x60e00000,
+};
 
 void bl31_platform_setup(void)
 {
-	unsigned int soc;
+	uintptr_t cntctl_base;
 
-	soc = uniphier_get_soc_id();
-	if (soc == UNIPHIER_SOC_UNKNOWN) {
-		ERROR("unsupported SoC\n");
-		plat_error_handler(-ENOTSUP);
-	}
-
-	uniphier_cci_init(soc);
+	uniphier_cci_init(uniphier_soc);
 	uniphier_cci_enable();
 
 	/* Initialize the GIC driver, cpu and distributor interfaces */
-	uniphier_gic_driver_init(soc);
+	uniphier_gic_driver_init(uniphier_soc);
 	uniphier_gic_init();
 
+	assert(uniphier_soc < ARRAY_SIZE(uniphier_cntctl_base));
+	cntctl_base = uniphier_cntctl_base[uniphier_soc];
+
 	/* Enable and initialize the System level generic timer */
-	mmio_write_32(UNIPHIER_SYS_CNTCTL_BASE + CNTCR_OFF,
-		      CNTCR_FCREQ(0U) | CNTCR_EN);
+	mmio_write_32(cntctl_base + CNTCR_OFF, CNTCR_FCREQ(0U) | CNTCR_EN);
+
+	uniphier_psci_init(uniphier_soc);
 }
 
 void bl31_plat_arch_setup(void)
 {
-	uniphier_mmap_setup();
+	uniphier_mmap_setup(uniphier_soc);
 	enable_mmu_el3(0);
 }
diff --git a/plat/socionext/uniphier/uniphier_boot_device.c b/plat/socionext/uniphier/uniphier_boot_device.c
index 462c085..36a9908 100644
--- a/plat/socionext/uniphier/uniphier_boot_device.c
+++ b/plat/socionext/uniphier/uniphier_boot_device.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,22 +13,29 @@
 
 #include "uniphier.h"
 
-#define UNIPHIER_PINMON0		0x5f900100
-#define UNIPHIER_PINMON2		0x5f900108
+#define UNIPHIER_PINMON0		0x0
+#define UNIPHIER_PINMON2		0x8
 
-static int uniphier_ld11_is_usb_boot(uint32_t pinmon)
+static const uintptr_t uniphier_pinmon_base[] = {
+	[UNIPHIER_SOC_LD11] = 0x5f900100,
+	[UNIPHIER_SOC_LD20] = 0x5f900100,
+	[UNIPHIER_SOC_PXS3] = 0x5f900100,
+};
+
+static bool uniphier_ld11_is_usb_boot(uint32_t pinmon)
 {
 	return !!(~pinmon & 0x00000080);
 }
 
-static int uniphier_ld20_is_usb_boot(uint32_t pinmon)
+static bool uniphier_ld20_is_usb_boot(uint32_t pinmon)
 {
 	return !!(~pinmon & 0x00000780);
 }
 
-static int uniphier_pxs3_is_usb_boot(uint32_t pinmon)
+static bool uniphier_pxs3_is_usb_boot(uint32_t pinmon)
 {
-	uint32_t pinmon2 = mmio_read_32(UNIPHIER_PINMON2);
+	uintptr_t pinmon_base = uniphier_pinmon_base[UNIPHIER_SOC_PXS3];
+	uint32_t pinmon2 = mmio_read_32(pinmon_base + UNIPHIER_PINMON2);
 
 	return !!(pinmon2 & BIT(31));
 }
@@ -106,20 +113,25 @@
 }
 
 struct uniphier_boot_device_info {
-	int (*is_usb_boot)(uint32_t pinmon);
+	bool have_boot_swap;
+	bool (*is_sd_boot)(uint32_t pinmon);
+	bool (*is_usb_boot)(uint32_t pinmon);
 	unsigned int (*get_boot_device)(uint32_t pinmon);
 };
 
 static const struct uniphier_boot_device_info uniphier_boot_device_info[] = {
 	[UNIPHIER_SOC_LD11] = {
+		.have_boot_swap = true,
 		.is_usb_boot = uniphier_ld11_is_usb_boot,
 		.get_boot_device = uniphier_ld11_get_boot_device,
 	},
 	[UNIPHIER_SOC_LD20] = {
+		.have_boot_swap = true,
 		.is_usb_boot = uniphier_ld20_is_usb_boot,
 		.get_boot_device = uniphier_ld11_get_boot_device,
 	},
 	[UNIPHIER_SOC_PXS3] = {
+		.have_boot_swap = true,
 		.is_usb_boot = uniphier_pxs3_is_usb_boot,
 		.get_boot_device = uniphier_pxs3_get_boot_device,
 	},
@@ -128,17 +140,24 @@
 unsigned int uniphier_get_boot_device(unsigned int soc)
 {
 	const struct uniphier_boot_device_info *info;
+	uintptr_t pinmon_base;
 	uint32_t pinmon;
 
 	assert(soc < ARRAY_SIZE(uniphier_boot_device_info));
 	info = &uniphier_boot_device_info[soc];
 
-	pinmon = mmio_read_32(UNIPHIER_PINMON0);
+	assert(soc < ARRAY_SIZE(uniphier_boot_device_info));
+	pinmon_base = uniphier_pinmon_base[soc];
+
+	pinmon = mmio_read_32(pinmon_base + UNIPHIER_PINMON0);
 
-	if (!(pinmon & BIT(29)))
+	if (info->have_boot_swap && !(pinmon & BIT(29)))
 		return UNIPHIER_BOOT_DEVICE_NOR;
 
-	if (info->is_usb_boot(pinmon))
+	if (info->is_sd_boot && info->is_sd_boot(pinmon))
+		return UNIPHIER_BOOT_DEVICE_SD;
+
+	if (info->is_usb_boot && info->is_usb_boot(pinmon))
 		return UNIPHIER_BOOT_DEVICE_USB;
 
 	return info->get_boot_device(pinmon);
@@ -155,7 +174,12 @@
 	assert(soc < ARRAY_SIZE(uniphier_have_onchip_scp));
 
 	if (uniphier_have_onchip_scp[soc]) {
-		if (mmio_read_32(UNIPHIER_PINMON0) & BIT(27))
+		uintptr_t pinmon_base;
+
+		assert(soc < ARRAY_SIZE(uniphier_boot_device_info));
+		pinmon_base = uniphier_pinmon_base[soc];
+
+		if (mmio_read_32(pinmon_base + UNIPHIER_PINMON0) & BIT(27))
 			return UNIPHIER_BOOT_MASTER_THIS;
 		else
 			return UNIPHIER_BOOT_MASTER_SCP;
diff --git a/plat/socionext/uniphier/uniphier_console_setup.c b/plat/socionext/uniphier/uniphier_console_setup.c
index 64ee797..1851e4d 100644
--- a/plat/socionext/uniphier/uniphier_console_setup.c
+++ b/plat/socionext/uniphier/uniphier_console_setup.c
@@ -1,9 +1,11 @@
 /*
- * Copyright (c) 2019, Socionext Inc. All rights reserved.
+ * Copyright (c) 2019-2020, Socionext Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <assert.h>
+
 #include <drivers/console.h>
 #include <errno.h>
 #include <lib/mmio.h>
@@ -12,9 +14,8 @@
 #include "uniphier.h"
 #include "uniphier_console.h"
 
-#define UNIPHIER_UART_BASE	0x54006800
-#define UNIPHIER_UART_END	0x54006c00
 #define UNIPHIER_UART_OFFSET	0x100
+#define UNIPHIER_UART_NR_PORTS	4
 
 struct uniphier_console {
 	struct console console;
@@ -40,16 +41,26 @@
 	},
 };
 
+static const uintptr_t uniphier_uart_base[] = {
+	[UNIPHIER_SOC_LD11] = 0x54006800,
+	[UNIPHIER_SOC_LD20] = 0x54006800,
+	[UNIPHIER_SOC_PXS3] = 0x54006800,
+};
+
 /*
  * There are 4 UART ports available on this platform. By default, we want to
  * use the same one as used in the previous firmware stage.
  */
-static uintptr_t uniphier_console_get_base(void)
+static uintptr_t uniphier_console_get_base(unsigned int soc)
 {
-	uintptr_t base = UNIPHIER_UART_BASE;
+	uintptr_t base, end;
 	uint32_t div;
 
-	while (base < UNIPHIER_UART_END) {
+	assert(soc < ARRAY_SIZE(uniphier_uart_base));
+	base = uniphier_uart_base[soc];
+	end = base + UNIPHIER_UART_OFFSET * UNIPHIER_UART_NR_PORTS;
+
+	while (base < end) {
 		div = mmio_read_32(base + UNIPHIER_UART_DLR);
 		if (div)
 			return base;
@@ -66,11 +77,11 @@
 		      UNIPHIER_UART_LCR_WLEN8 << 8);
 }
 
-void uniphier_console_setup(void)
+void uniphier_console_setup(unsigned int soc)
 {
 	uintptr_t base;
 
-	base = uniphier_console_get_base();
+	base = uniphier_console_get_base(soc);
 	if (!base)
 		plat_error_handler(-EINVAL);
 
diff --git a/plat/socionext/uniphier/uniphier_emmc.c b/plat/socionext/uniphier/uniphier_emmc.c
index d666ba7..b3d23cb 100644
--- a/plat/socionext/uniphier/uniphier_emmc.c
+++ b/plat/socionext/uniphier/uniphier_emmc.c
@@ -87,7 +87,12 @@
 	unsigned int is_data;
 };
 
-static int uniphier_emmc_block_addressing;
+struct uniphier_emmc_host {
+	uintptr_t base;
+	bool is_block_addressing;
+};
+
+static struct uniphier_emmc_host uniphier_emmc_host;
 
 static int uniphier_emmc_send_cmd(uintptr_t host_base,
 				  struct uniphier_mmc_cmd *cmd)
@@ -157,7 +162,8 @@
 	return uniphier_emmc_send_cmd(host_base, &cmd);
 }
 
-static int uniphier_emmc_is_over_2gb(uintptr_t host_base)
+static int uniphier_emmc_check_device_size(uintptr_t host_base,
+					   bool *is_block_addressing)
 {
 	struct uniphier_mmc_cmd cmd = {0};
 	uint32_t csd40, csd72;	/* CSD[71:40], CSD[103:72] */
@@ -174,7 +180,10 @@
 	csd40 = mmio_read_32(host_base + SDHCI_RESPONSE + 4);
 	csd72 = mmio_read_32(host_base + SDHCI_RESPONSE + 8);
 
-	return !(~csd40 & 0xffc00380) && !(~csd72 & 0x3);
+	/* C_SIZE == 0xfff && C_SIZE_MULT == 0x7 ? */
+	*is_block_addressing = !(~csd40 & 0xffc00380) && !(~csd72 & 0x3);
+
+	return 0;
 }
 
 static int uniphier_emmc_load_image(uintptr_t host_base,
@@ -210,15 +219,15 @@
 
 static size_t uniphier_emmc_read(int lba, uintptr_t buf, size_t size)
 {
-	uintptr_t host_base = 0x5a000200;
 	int ret;
 
 	inv_dcache_range(buf, size);
 
-	if (!uniphier_emmc_block_addressing)
+	if (!uniphier_emmc_host.is_block_addressing)
 		lba *= 512;
 
-	ret = uniphier_emmc_load_image(host_base, lba, buf, size / 512);
+	ret = uniphier_emmc_load_image(uniphier_emmc_host.base,
+				       lba, buf, size / 512);
 
 	inv_dcache_range(buf, size);
 
@@ -232,10 +241,10 @@
 	.block_size = 512,
 };
 
-static int uniphier_emmc_hw_init(void)
+static int uniphier_emmc_hw_init(struct uniphier_emmc_host *host)
 {
-	uintptr_t host_base = 0x5a000200;
 	struct uniphier_mmc_cmd cmd = {0};
+	uintptr_t host_base = uniphier_emmc_host.base;
 	int ret;
 
 	/*
@@ -253,12 +262,11 @@
 	while (mmio_read_8(host_base + SDHCI_SOFTWARE_RESET))
 		;
 
-	ret = uniphier_emmc_is_over_2gb(host_base);
-	if (ret < 0)
+	ret = uniphier_emmc_check_device_size(host_base,
+				&uniphier_emmc_host.is_block_addressing);
+	if (ret)
 		return ret;
 
-	uniphier_emmc_block_addressing = ret;
-
 	cmd.cmdarg = UNIPHIER_EMMC_RCA << 16;
 
 	/* select card again */
@@ -274,11 +282,23 @@
 	return 0;
 }
 
+static const uintptr_t uniphier_emmc_base[] = {
+	[UNIPHIER_SOC_LD11] = 0x5a000200,
+	[UNIPHIER_SOC_LD20] = 0x5a000200,
+	[UNIPHIER_SOC_PXS3] = 0x5a000200,
+};
+
-int uniphier_emmc_init(struct io_block_dev_spec **block_dev_spec)
+int uniphier_emmc_init(unsigned int soc,
+		       struct io_block_dev_spec **block_dev_spec)
 {
 	int ret;
 
-	ret = uniphier_emmc_hw_init();
+	assert(soc < ARRAY_SIZE(uniphier_emmc_base));
+	uniphier_emmc_host.base = uniphier_emmc_base[soc];
+	if (uniphier_emmc_host.base == 0UL)
+		return -ENOTSUP;
+
+	ret = uniphier_emmc_hw_init(&uniphier_emmc_host);
 	if (ret)
 		return ret;
 
diff --git a/plat/socionext/uniphier/uniphier_io_storage.c b/plat/socionext/uniphier/uniphier_io_storage.c
index 89c8718..96180f1 100644
--- a/plat/socionext/uniphier/uniphier_io_storage.c
+++ b/plat/socionext/uniphier/uniphier_io_storage.c
@@ -249,24 +249,24 @@
 	return io_dev_open(uniphier_fip_dev_con, 0, &uniphier_fip_dev_handle);
 }
 
-static int uniphier_io_emmc_setup(unsigned int soc_id, size_t buffer_offset)
+static int uniphier_io_emmc_setup(unsigned int soc, size_t buffer_offset)
 {
 	struct io_block_dev_spec *block_dev_spec;
 	int ret;
 
-	ret = uniphier_emmc_init(&block_dev_spec);
+	ret = uniphier_emmc_init(soc, &block_dev_spec);
 	if (ret)
 		return ret;
 
 	return uniphier_io_block_setup(0x20000, block_dev_spec, buffer_offset);
 }
 
-static int uniphier_io_nand_setup(unsigned int soc_id, size_t buffer_offset)
+static int uniphier_io_nand_setup(unsigned int soc, size_t buffer_offset)
 {
 	struct io_block_dev_spec *block_dev_spec;
 	int ret;
 
-	ret = uniphier_nand_init(&block_dev_spec);
+	ret = uniphier_nand_init(soc, &block_dev_spec);
 	if (ret)
 		return ret;
 
diff --git a/plat/socionext/uniphier/uniphier_nand.c b/plat/socionext/uniphier/uniphier_nand.c
index 3925177..71cb96c 100644
--- a/plat/socionext/uniphier/uniphier_nand.c
+++ b/plat/socionext/uniphier/uniphier_nand.c
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <assert.h>
 #include <stdint.h>
 
 #include <platform_def.h>
@@ -237,8 +238,7 @@
 	for (i = 0; i < ARRAY_SIZE(nand->bbt); i++)
 		nand->bbt[i] = UNIPHIER_NAND_BBT_UNKNOWN;
 
-	nand->host_base = 0x68000000;
-	nand->reg_base = 0x68100000;
+	nand->reg_base = nand->host_base + 0x100000;
 
 	nand->pages_per_block =
 			mmio_read_32(nand->reg_base + DENALI_PAGES_PER_BLOCK);
@@ -255,10 +255,22 @@
 	return 0;
 }
 
-int uniphier_nand_init(struct io_block_dev_spec **block_dev_spec)
+static const uintptr_t uniphier_nand_base[] = {
+	[UNIPHIER_SOC_LD11] = 0x68000000,
+	[UNIPHIER_SOC_LD20] = 0x68000000,
+	[UNIPHIER_SOC_PXS3] = 0x68000000,
+};
+
+int uniphier_nand_init(unsigned int soc,
+		       struct io_block_dev_spec **block_dev_spec)
 {
 	int ret;
 
+	assert(soc < ARRAY_SIZE(uniphier_nand_base));
+	uniphier_nand.host_base = uniphier_nand_base[soc];
+	if (!uniphier_nand.host_base)
+		return -ENOTSUP;
+
 	ret = uniphier_nand_hw_init(&uniphier_nand);
 	if (ret)
 		return ret;
diff --git a/plat/socionext/uniphier/uniphier_psci.c b/plat/socionext/uniphier/uniphier_psci.c
index 2acc874..a371705 100644
--- a/plat/socionext/uniphier/uniphier_psci.c
+++ b/plat/socionext/uniphier/uniphier_psci.c
@@ -1,9 +1,11 @@
 /*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <assert.h>
+
 #include <arch_helpers.h>
 #include <common/debug.h>
 #include <errno.h>
@@ -12,15 +14,18 @@
 
 #include "uniphier.h"
 
-#define UNIPHIER_ROM_RSV0		0x59801200
+#define UNIPHIER_ROM_RSV0		0x0
 
-#define UNIPHIER_SLFRSTSEL		0x61843010
+#define UNIPHIER_SLFRSTSEL		0x10
 #define   UNIPHIER_SLFRSTSEL_MASK		GENMASK(1, 0)
-#define UNIPHIER_SLFRSTCTL		0x61843014
+#define UNIPHIER_SLFRSTCTL		0x14
 #define   UNIPHIER_SLFRSTCTL_RST		BIT(0)
 
 #define MPIDR_AFFINITY_INVALID		((u_register_t)-1)
 
+static uintptr_t uniphier_rom_rsv_base;
+static uintptr_t uniphier_slfrst_base;
+
 uintptr_t uniphier_sec_entrypoint;
 
 void uniphier_warmboot_entrypoint(void);
@@ -34,7 +39,7 @@
 	flush_dcache_range((uint64_t)&uniphier_holding_pen_release,
 			   sizeof(uniphier_holding_pen_release));
 
-	mmio_write_64(UNIPHIER_ROM_RSV0,
+	mmio_write_64(uniphier_rom_rsv_base + UNIPHIER_ROM_RSV0,
 		      (uint64_t)&uniphier_warmboot_entrypoint);
 	sev();
 
@@ -71,8 +76,10 @@
 
 static void uniphier_self_system_reset(void)
 {
-	mmio_clrbits_32(UNIPHIER_SLFRSTSEL, UNIPHIER_SLFRSTSEL_MASK);
-	mmio_setbits_32(UNIPHIER_SLFRSTCTL, UNIPHIER_SLFRSTCTL_RST);
+	mmio_clrbits_32(uniphier_slfrst_base + UNIPHIER_SLFRSTSEL,
+			UNIPHIER_SLFRSTSEL_MASK);
+	mmio_setbits_32(uniphier_slfrst_base + UNIPHIER_SLFRSTCTL,
+			UNIPHIER_SLFRSTCTL_RST);
 }
 
 static void __dead2 uniphier_psci_system_off(void)
@@ -114,13 +121,40 @@
 int plat_setup_psci_ops(uintptr_t sec_entrypoint,
 			const struct plat_psci_ops **psci_ops)
 {
-	unsigned int soc;
+	uniphier_sec_entrypoint = sec_entrypoint;
+	flush_dcache_range((uint64_t)&uniphier_sec_entrypoint,
+			   sizeof(uniphier_sec_entrypoint));
 
-	soc = uniphier_get_soc_id();
-	if (soc == UNIPHIER_SOC_UNKNOWN) {
-		ERROR("unsupported SoC\n");
-		return -ENOTSUP;
-	}
+	*psci_ops = &uniphier_psci_ops;
+
+	return 0;
+}
+
+struct uniphier_psci_ctrl_base {
+	uintptr_t rom_rsv_base;
+	uintptr_t slfrst_base;
+};
+
+static const struct uniphier_psci_ctrl_base uniphier_psci_ctrl_base[] = {
+	[UNIPHIER_SOC_LD11] = {
+		.rom_rsv_base = 0x59801200,
+		.slfrst_base = 0x61843000,
+	},
+	[UNIPHIER_SOC_LD20] = {
+		.rom_rsv_base = 0x59801200,
+		.slfrst_base = 0x61843000,
+	},
+	[UNIPHIER_SOC_PXS3] = {
+		.rom_rsv_base = 0x59801200,
+		.slfrst_base = 0x61843000,
+	},
+};
+
+void uniphier_psci_init(unsigned int soc)
+{
+	assert(soc < ARRAY_SIZE(uniphier_psci_ctrl_base));
+	uniphier_rom_rsv_base = uniphier_psci_ctrl_base[soc].rom_rsv_base;
+	uniphier_slfrst_base = uniphier_psci_ctrl_base[soc].slfrst_base;
 
 	if (uniphier_get_boot_master(soc) == UNIPHIER_BOOT_MASTER_SCP) {
 		uniphier_psci_scp_mode = uniphier_scp_is_running();
@@ -130,12 +164,4 @@
 		if (uniphier_psci_scp_mode)
 			uniphier_scp_open_com();
 	}
-
-	uniphier_sec_entrypoint = sec_entrypoint;
-	flush_dcache_range((uint64_t)&uniphier_sec_entrypoint,
-			   sizeof(uniphier_sec_entrypoint));
-
-	*psci_ops = &uniphier_psci_ops;
-
-	return 0;
 }
diff --git a/plat/socionext/uniphier/uniphier_xlat_setup.c b/plat/socionext/uniphier/uniphier_xlat_setup.c
index 18d2f9e..66c7834 100644
--- a/plat/socionext/uniphier/uniphier_xlat_setup.c
+++ b/plat/socionext/uniphier/uniphier_xlat_setup.c
@@ -4,15 +4,36 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <assert.h>
+
 #include <platform_def.h>
 
 #include <common/debug.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
 
+#include "uniphier.h"
+
-#define UNIPHIER_REG_REGION_BASE	0x50000000ULL
-#define UNIPHIER_REG_REGION_SIZE	0x20000000ULL
+struct uniphier_reg_region {
+	uintptr_t base;
+	size_t size;
+};
 
-void uniphier_mmap_setup(void)
+static const struct uniphier_reg_region uniphier_reg_region[] = {
+	[UNIPHIER_SOC_LD11] = {
+		.base = 0x50000000UL,
+		.size = 0x20000000UL,
+	},
+	[UNIPHIER_SOC_LD20] = {
+		.base = 0x50000000UL,
+		.size = 0x20000000UL,
+	},
+	[UNIPHIER_SOC_PXS3] = {
+		.base = 0x50000000UL,
+		.size = 0x20000000UL,
+	},
+};
+
+void uniphier_mmap_setup(unsigned int soc)
 {
 	VERBOSE("Trusted RAM seen by this BL image: %p - %p\n",
 		(void *)BL_CODE_BASE, (void *)BL_END);
@@ -35,8 +56,10 @@
 			MT_DEVICE | MT_RW | MT_SECURE);
 
 	/* register region */
-	mmap_add_region(UNIPHIER_REG_REGION_BASE, UNIPHIER_REG_REGION_BASE,
-			UNIPHIER_REG_REGION_SIZE,
+	assert(soc < ARRAY_SIZE(uniphier_reg_region));
+	mmap_add_region(uniphier_reg_region[soc].base,
+			uniphier_reg_region[soc].base,
+			uniphier_reg_region[soc].size,
 			MT_DEVICE | MT_RW | MT_SECURE);
 
 	init_xlat_tables();
diff --git a/services/spd/trusty/generic-arm64-smcall.c b/services/spd/trusty/generic-arm64-smcall.c
index dfc3e71..5c3a628 100644
--- a/services/spd/trusty/generic-arm64-smcall.c
+++ b/services/spd/trusty/generic-arm64-smcall.c
@@ -12,6 +12,22 @@
 
 #include "generic-arm64-smcall.h"
 
+#ifndef PLAT_ARM_GICD_BASE
+#ifdef GICD_BASE
+#define PLAT_ARM_GICD_BASE GICD_BASE
+#define PLAT_ARM_GICC_BASE GICC_BASE
+#ifdef GICR_BASE
+#define PLAT_ARM_GICR_BASE GICR_BASE
+#endif
+#else
+#error PLAT_ARM_GICD_BASE or GICD_BASE must be defined
+#endif
+#endif
+
+#ifndef PLAT_ARM_GICR_BASE
+#define PLAT_ARM_GICR_BASE SMC_UNK
+#endif
+
 int trusty_disable_serial_debug;
 
 struct dputc_state {
@@ -48,12 +64,15 @@
 static uint64_t trusty_get_reg_base(uint32_t reg)
 {
 	switch (reg) {
-	case 0:
+	case SMC_GET_GIC_BASE_GICD:
 		return PLAT_ARM_GICD_BASE;
 
-	case 1:
+	case SMC_GET_GIC_BASE_GICC:
 		return PLAT_ARM_GICC_BASE;
 
+	case SMC_GET_GIC_BASE_GICR:
+		return PLAT_ARM_GICR_BASE;
+
 	default:
 		NOTICE("%s(0x%x) unknown reg\n", __func__, reg);
 		return SMC_UNK;
diff --git a/services/spd/trusty/generic-arm64-smcall.h b/services/spd/trusty/generic-arm64-smcall.h
index 06efc72..ac03469 100644
--- a/services/spd/trusty/generic-arm64-smcall.h
+++ b/services/spd/trusty/generic-arm64-smcall.h
@@ -23,5 +23,6 @@
  */
 #define SMC_GET_GIC_BASE_GICD	0
 #define SMC_GET_GIC_BASE_GICC	1
+#define SMC_GET_GIC_BASE_GICR	2
 #define SMC_FC_GET_REG_BASE	SMC_FASTCALL_NR(SMC_ENTITY_PLATFORM_MONITOR, 0x1)
 #define SMC_FC64_GET_REG_BASE	SMC_FASTCALL64_NR(SMC_ENTITY_PLATFORM_MONITOR, 0x1)
diff --git a/services/spd/trusty/trusty.c b/services/spd/trusty/trusty.c
index d6c092c..092ffa8 100644
--- a/services/spd/trusty/trusty.c
+++ b/services/spd/trusty/trusty.c
@@ -390,6 +390,10 @@
 
 void plat_trusty_set_boot_args(aapcs64_params_t *args);
 
+#if !defined(TSP_SEC_MEM_SIZE) && defined(BL32_MEM_SIZE)
+#define TSP_SEC_MEM_SIZE BL32_MEM_SIZE
+#endif
+
 #ifdef TSP_SEC_MEM_SIZE
 #pragma weak plat_trusty_set_boot_args
 void plat_trusty_set_boot_args(aapcs64_params_t *args)
diff --git a/services/spd/tspd/tspd_main.c b/services/spd/tspd/tspd_main.c
index f206724..b0cbf62 100644
--- a/services/spd/tspd/tspd_main.c
+++ b/services/spd/tspd/tspd_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -126,7 +126,7 @@
 	 * interrupt handling.
 	 */
 	if (get_yield_smc_active_flag(tsp_ctx->state)) {
-		tsp_ctx->saved_spsr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx,
+		tsp_ctx->saved_spsr_el3 = (uint32_t)SMC_GET_EL3(&tsp_ctx->cpu_ctx,
 						      CTX_SPSR_EL3);
 		tsp_ctx->saved_elr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx,
 						     CTX_ELR_EL3);
diff --git a/services/std_svc/spmd/aarch64/spmd_helpers.S b/services/std_svc/spmd/aarch64/spmd_helpers.S
new file mode 100644
index 0000000..d7bffca
--- /dev/null
+++ b/services/std_svc/spmd/aarch64/spmd_helpers.S
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include "../spmd_private.h"
+
+	.global spmd_spm_core_enter
+	.global spmd_spm_core_exit
+
+	/* ---------------------------------------------------------------------
+	 * This function is called with SP_EL0 as stack. Here we stash our EL3
+	 * callee-saved registers on to the stack as a part of saving the C
+	 * runtime and enter the secure payload.
+	 * 'x0' contains a pointer to the memory where the address of the C
+	 *  runtime context is to be saved.
+	 * ---------------------------------------------------------------------
+	 */
+func spmd_spm_core_enter
+	/* Make space for the registers that we're going to save */
+	mov	x3, sp
+	str	x3, [x0, #0]
+	sub	sp, sp, #SPMD_C_RT_CTX_SIZE
+
+	/* Save callee-saved registers on to the stack */
+	stp	x19, x20, [sp, #SPMD_C_RT_CTX_X19]
+	stp	x21, x22, [sp, #SPMD_C_RT_CTX_X21]
+	stp	x23, x24, [sp, #SPMD_C_RT_CTX_X23]
+	stp	x25, x26, [sp, #SPMD_C_RT_CTX_X25]
+	stp	x27, x28, [sp, #SPMD_C_RT_CTX_X27]
+	stp	x29, x30, [sp, #SPMD_C_RT_CTX_X29]
+
+	/* ---------------------------------------------------------------------
+	 * Everything is setup now. el3_exit() will use the secure context to
+	 * restore to the general purpose and EL3 system registers to ERET
+	 * into the secure payload.
+	 * ---------------------------------------------------------------------
+	 */
+	b	el3_exit
+endfunc spmd_spm_core_enter
+
+	/* ---------------------------------------------------------------------
+	 * This function is called with 'x0' pointing to a C runtime context.
+	 * It restores the saved registers and jumps to that runtime with 'x0'
+	 * as the new SP register. This destroys the C runtime context that had
+	 * been built on the stack below the saved context by the caller. Later
+	 * the second parameter 'x1' is passed as a return value to the caller.
+	 * ---------------------------------------------------------------------
+	 */
+func spmd_spm_core_exit
+	/* Restore the previous stack */
+	mov	sp, x0
+
+	/* Restore callee-saved registers on to the stack */
+	ldp	x19, x20, [x0, #(SPMD_C_RT_CTX_X19 - SPMD_C_RT_CTX_SIZE)]
+	ldp	x21, x22, [x0, #(SPMD_C_RT_CTX_X21 - SPMD_C_RT_CTX_SIZE)]
+	ldp	x23, x24, [x0, #(SPMD_C_RT_CTX_X23 - SPMD_C_RT_CTX_SIZE)]
+	ldp	x25, x26, [x0, #(SPMD_C_RT_CTX_X25 - SPMD_C_RT_CTX_SIZE)]
+	ldp	x27, x28, [x0, #(SPMD_C_RT_CTX_X27 - SPMD_C_RT_CTX_SIZE)]
+	ldp	x29, x30, [x0, #(SPMD_C_RT_CTX_X29 - SPMD_C_RT_CTX_SIZE)]
+
+	/* ---------------------------------------------------------------------
+	 * This should take us back to the instruction after the call to the
+	 * last spm_secure_partition_enter().* Place the second parameter to x0
+	 * so that the caller will see it as a return value from the original
+	 * entry call.
+	 * ---------------------------------------------------------------------
+	 */
+	mov	x0, x1
+	ret
+endfunc spmd_spm_core_exit
diff --git a/services/std_svc/spmd/spmd.mk b/services/std_svc/spmd/spmd.mk
new file mode 100644
index 0000000..38d43f1
--- /dev/null
+++ b/services/std_svc/spmd/spmd.mk
@@ -0,0 +1,21 @@
+#
+# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ifneq (${ARCH},aarch64)
+        $(error "Error: SPMD is only supported on aarch64.")
+endif
+
+SPMD_SOURCES	+=	$(addprefix services/std_svc/spmd/,	\
+			${ARCH}/spmd_helpers.S			\
+			spmd_main.c)
+
+# Let the top-level Makefile know that we intend to include a BL32 image
+NEED_BL32		:=	yes
+
+# Enable dynamic memory mapping
+# The SPMD component maps the SPMC DTB within BL31 virtual space.
+PLAT_XLAT_TABLES_DYNAMIC :=	1
+$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC))
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
new file mode 100644
index 0000000..677f639
--- /dev/null
+++ b/services/std_svc/spmd/spmd_main.c
@@ -0,0 +1,487 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <bl31/bl31.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/smccc.h>
+#include <lib/spinlock.h>
+#include <lib/utils.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/common_def.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <services/spci_svc.h>
+#include <services/spmd_svc.h>
+#include <smccc_helpers.h>
+#include "spmd_private.h"
+
+/*******************************************************************************
+ * SPM Core context information.
+ ******************************************************************************/
+spmd_spm_core_context_t spm_core_context[PLATFORM_CORE_COUNT];
+
+/*******************************************************************************
+ * SPM Core attribute information read from its manifest.
+ ******************************************************************************/
+spmc_manifest_sect_attribute_t spmc_attrs;
+
+/*******************************************************************************
+ * This function takes an SP context pointer and performs a synchronous entry
+ * into it.
+ ******************************************************************************/
+uint64_t spmd_spm_core_sync_entry(spmd_spm_core_context_t *spmc_ctx)
+{
+	uint64_t rc;
+
+	assert(spmc_ctx != NULL);
+
+	cm_set_context(&(spmc_ctx->cpu_ctx), SECURE);
+
+	/* Restore the context assigned above */
+	cm_el1_sysregs_context_restore(SECURE);
+	cm_set_next_eret_context(SECURE);
+
+	/* Invalidate TLBs at EL1. */
+	tlbivmalle1();
+	dsbish();
+
+	/* Enter Secure Partition */
+	rc = spmd_spm_core_enter(&spmc_ctx->c_rt_ctx);
+
+	/* Save secure state */
+	cm_el1_sysregs_context_save(SECURE);
+
+	return rc;
+}
+
+/*******************************************************************************
+ * This function returns to the place where spm_sp_synchronous_entry() was
+ * called originally.
+ ******************************************************************************/
+__dead2 void spmd_spm_core_sync_exit(uint64_t rc)
+{
+	spmd_spm_core_context_t *ctx = &spm_core_context[plat_my_core_pos()];
+
+	/* Get context of the SP in use by this CPU. */
+	assert(cm_get_context(SECURE) == &(ctx->cpu_ctx));
+
+	/*
+	 * The SPMD must have initiated the original request through a
+	 * synchronous entry into SPMC. Jump back to the original C runtime
+	 * context with the value of rc in x0;
+	 */
+	spmd_spm_core_exit(ctx->c_rt_ctx, rc);
+
+	panic();
+}
+
+/*******************************************************************************
+ * Jump to the SPM core for the first time.
+ ******************************************************************************/
+static int32_t spmd_init(void)
+{
+	uint64_t rc = 0;
+	spmd_spm_core_context_t *ctx = &spm_core_context[plat_my_core_pos()];
+
+	INFO("SPM Core init start.\n");
+	ctx->state = SPMC_STATE_RESET;
+
+	rc = spmd_spm_core_sync_entry(ctx);
+	if (rc) {
+		ERROR("SPMC initialisation failed 0x%llx\n", rc);
+		panic();
+	}
+
+	ctx->state = SPMC_STATE_IDLE;
+	INFO("SPM Core init end.\n");
+
+	return 1;
+}
+
+/*******************************************************************************
+ * Initialize context of SPM core.
+ ******************************************************************************/
+int32_t spmd_setup(void)
+{
+	int rc;
+	void *rd_base;
+	size_t rd_size;
+	entry_point_info_t *spmc_ep_info;
+	uintptr_t rd_base_align;
+	uintptr_t rd_size_align;
+	uint32_t ep_attr;
+
+	spmc_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
+	if (!spmc_ep_info) {
+		WARN("No SPM core image provided by BL2 boot loader, Booting "
+		     "device without SP initialization. SMC`s destined for SPM "
+		     "core will return SMC_UNK\n");
+		return 1;
+	}
+
+	/* Under no circumstances will this parameter be 0 */
+	assert(spmc_ep_info->pc != 0U);
+
+	/*
+	 * Check if BL32 ep_info has a reference to 'tos_fw_config'. This will
+	 * be used as a manifest for the SPM core at the next lower EL/mode.
+	 */
+	if (spmc_ep_info->args.arg0 == 0U || spmc_ep_info->args.arg2 == 0U) {
+		ERROR("Invalid or absent SPM core manifest\n");
+		panic();
+	}
+
+	/* Obtain whereabouts of SPM core manifest */
+	rd_base = (void *) spmc_ep_info->args.arg0;
+	rd_size = spmc_ep_info->args.arg2;
+
+	rd_base_align = page_align((uintptr_t) rd_base, DOWN);
+	rd_size_align = page_align((uintptr_t) rd_size, UP);
+
+	/* Map the manifest in the SPMD translation regime first */
+	VERBOSE("SPM core manifest base : 0x%lx\n", rd_base_align);
+	VERBOSE("SPM core manifest size : 0x%lx\n", rd_size_align);
+	rc = mmap_add_dynamic_region((unsigned long long) rd_base_align,
+				     (uintptr_t) rd_base_align,
+				     rd_size_align,
+				     MT_RO_DATA);
+	if (rc < 0) {
+		ERROR("Error while mapping SPM core manifest (%d).\n", rc);
+		panic();
+	}
+
+	/* Load the SPM core manifest */
+	rc = plat_spm_core_manifest_load(&spmc_attrs, rd_base, rd_size);
+	if (rc < 0) {
+		WARN("No or invalid SPM core manifest image provided by BL2 "
+		     "boot loader. ");
+		goto error;
+	}
+
+	/*
+	 * Ensure that the SPM core version is compatible with the SPM
+	 * dispatcher version
+	 */
+	if ((spmc_attrs.major_version != SPCI_VERSION_MAJOR) ||
+	    (spmc_attrs.minor_version > SPCI_VERSION_MINOR)) {
+		WARN("Unsupported SPCI version (%x.%x) specified in SPM core "
+		     "manifest image provided by BL2 boot loader.\n",
+		     spmc_attrs.major_version, spmc_attrs.minor_version);
+		goto error;
+	}
+
+	INFO("SPCI version (%x.%x).\n", spmc_attrs.major_version,
+	     spmc_attrs.minor_version);
+
+	/* Validate the SPM core runtime EL */
+	if ((spmc_attrs.runtime_el != MODE_EL1) &&
+	    (spmc_attrs.runtime_el != MODE_EL2)) {
+		WARN("Unsupported SPM core run time EL%x specified in "
+		     "manifest image provided by BL2 boot loader.\n",
+		     spmc_attrs.runtime_el);
+		goto error;
+	}
+
+	INFO("SPM core run time EL%x.\n", spmc_attrs.runtime_el);
+
+	/* Validate the SPM core execution state */
+	if ((spmc_attrs.exec_state != MODE_RW_64) &&
+	    (spmc_attrs.exec_state != MODE_RW_32)) {
+		WARN("Unsupported SPM core execution state %x specified in "
+		     "manifest image provided by BL2 boot loader.\n",
+		     spmc_attrs.exec_state);
+		goto error;
+	}
+
+	INFO("SPM core execution state %x.\n", spmc_attrs.exec_state);
+
+	/* Ensure manifest has not requested S-EL2 in AArch32 state */
+	if ((spmc_attrs.exec_state == MODE_RW_32) &&
+	    (spmc_attrs.runtime_el == MODE_EL2)) {
+		WARN("Invalid combination of SPM core execution state (%x) "
+		     "and run time EL (%x).\n", spmc_attrs.exec_state,
+		     spmc_attrs.runtime_el);
+		goto error;
+	}
+
+	/*
+	 * Check if S-EL2 is supported on this system if S-EL2
+	 * is required for SPM
+	 */
+	if (spmc_attrs.runtime_el == MODE_EL2) {
+		uint64_t sel2 = read_id_aa64pfr0_el1();
+
+		sel2 >>= ID_AA64PFR0_SEL2_SHIFT;
+		sel2 &= ID_AA64PFR0_SEL2_MASK;
+
+		if (!sel2) {
+			WARN("SPM core run time EL: S-EL%x is not supported "
+			     "but specified in manifest image provided by "
+			     "BL2 boot loader.\n", spmc_attrs.runtime_el);
+			goto error;
+		}
+	}
+
+	/* Initialise an entrypoint to set up the CPU context */
+	ep_attr = SECURE | EP_ST_ENABLE;
+	if (read_sctlr_el3() & SCTLR_EE_BIT)
+		ep_attr |= EP_EE_BIG;
+	SET_PARAM_HEAD(spmc_ep_info, PARAM_EP, VERSION_1, ep_attr);
+	assert(spmc_ep_info->pc == BL32_BASE);
+
+	/*
+	 * Populate SPSR for SPM core based upon validated parameters from the
+	 * manifest
+	 */
+	if (spmc_attrs.exec_state == MODE_RW_32) {
+		spmc_ep_info->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
+						 SPSR_E_LITTLE,
+						 DAIF_FIQ_BIT |
+						 DAIF_IRQ_BIT |
+						 DAIF_ABT_BIT);
+	} else {
+		spmc_ep_info->spsr = SPSR_64(spmc_attrs.runtime_el,
+					     MODE_SP_ELX,
+					     DISABLE_ALL_EXCEPTIONS);
+	}
+
+	/* Initialise SPM core context with this entry point information */
+	cm_setup_context(&(spm_core_context[plat_my_core_pos()].cpu_ctx),
+			 spmc_ep_info);
+
+	INFO("SPM core setup done.\n");
+
+	/* Register init function for deferred init.  */
+	bl31_register_bl32_init(&spmd_init);
+
+	return 0;
+
+error:
+	WARN("Booting device without SPM initialization. "
+	     "SPCI SMCs destined for SPM core will return "
+	     "ENOTSUPPORTED\n");
+
+	rc = mmap_remove_dynamic_region(rd_base_align, rd_size_align);
+	if (rc < 0) {
+		ERROR("Error while unmapping SPM core manifest (%d).\n",
+		      rc);
+		panic();
+	}
+
+	return 1;
+}
+
+/*******************************************************************************
+ * This function handles all SMCs in the range reserved for SPCI. Each call is
+ * either forwarded to the other security state or handled by the SPM dispatcher
+ ******************************************************************************/
+uint64_t spmd_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2,
+			  uint64_t x3, uint64_t x4, void *cookie, void *handle,
+			  uint64_t flags)
+{
+	uint32_t in_sstate;
+	uint32_t out_sstate;
+	int32_t ret;
+	spmd_spm_core_context_t *ctx = &spm_core_context[plat_my_core_pos()];
+
+	/* Determine which security state this SMC originated from */
+	if (is_caller_secure(flags)) {
+		in_sstate = SECURE;
+		out_sstate = NON_SECURE;
+	} else {
+		in_sstate = NON_SECURE;
+		out_sstate = SECURE;
+	}
+
+	INFO("SPM: 0x%x, 0x%llx, 0x%llx, 0x%llx, 0x%llx, "
+	     "0x%llx, 0x%llx, 0x%llx\n",
+	     smc_fid, x1, x2, x3, x4, SMC_GET_GP(handle, CTX_GPREG_X5),
+	     SMC_GET_GP(handle, CTX_GPREG_X6),
+	     SMC_GET_GP(handle, CTX_GPREG_X7));
+
+	switch (smc_fid) {
+	case SPCI_ERROR:
+		/*
+		 * Check if this is the first invocation of this interface on
+		 * this CPU. If so, then indicate that the SPM core initialised
+		 * unsuccessfully.
+		 */
+		if ((in_sstate == SECURE) && (ctx->state == SPMC_STATE_RESET))
+			spmd_spm_core_sync_exit(x2);
+
+		/* Save incoming security state */
+		cm_el1_sysregs_context_save(in_sstate);
+
+		/* Restore outgoing security state */
+		cm_el1_sysregs_context_restore(out_sstate);
+		cm_set_next_eret_context(out_sstate);
+
+		SMC_RET8(cm_get_context(out_sstate), smc_fid, x1, x2, x3, x4,
+			 SMC_GET_GP(handle, CTX_GPREG_X5),
+			 SMC_GET_GP(handle, CTX_GPREG_X6),
+			 SMC_GET_GP(handle, CTX_GPREG_X7));
+		break; /* not reached */
+
+	case SPCI_VERSION:
+		/*
+		 * TODO: This is an optimization that the version information
+		 * provided by the SPM core manifest is returned by the SPM
+		 * dispatcher. It might be a better idea to simply forward this
+		 * call to the SPM core and wash our hands completely.
+		 */
+		ret = MAKE_SPCI_VERSION(spmc_attrs.major_version,
+					spmc_attrs.minor_version);
+		SMC_RET8(handle, SPCI_SUCCESS_SMC32, SPCI_TARGET_INFO_MBZ, ret,
+			 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
+			 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ);
+		break; /* not reached */
+
+	case SPCI_FEATURES:
+		/*
+		 * This is an optional interface. Do the minimal checks and
+		 * forward to SPM core which will handle it if implemented.
+		 */
+
+		/*
+		 * Check if w1 holds a valid SPCI fid. This is an
+		 * optimization.
+		 */
+		if (!is_spci_fid(x1))
+			SMC_RET8(handle, SPCI_ERROR,
+				 SPCI_TARGET_INFO_MBZ, SPCI_ERROR_NOT_SUPPORTED,
+				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
+				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ);
+
+		/* Forward SMC from Normal world to the SPM core */
+		if (in_sstate == NON_SECURE) {
+			/* Save incoming security state */
+			cm_el1_sysregs_context_save(in_sstate);
+
+			/* Restore outgoing security state */
+			cm_el1_sysregs_context_restore(out_sstate);
+			cm_set_next_eret_context(out_sstate);
+
+			SMC_RET8(cm_get_context(out_sstate), smc_fid,
+				 x1, x2, x3, x4,
+				 SMC_GET_GP(handle, CTX_GPREG_X5),
+				 SMC_GET_GP(handle, CTX_GPREG_X6),
+				 SMC_GET_GP(handle, CTX_GPREG_X7));
+		} else {
+			/*
+			 * Return success if call was from secure world i.e. all
+			 * SPCI functions are supported. This is essentially a
+			 * nop.
+			 */
+			SMC_RET8(handle, SPCI_SUCCESS_SMC32, x1, x2, x3, x4,
+				 SMC_GET_GP(handle, CTX_GPREG_X5),
+				 SMC_GET_GP(handle, CTX_GPREG_X6),
+				 SMC_GET_GP(handle, CTX_GPREG_X7));
+		}
+		break; /* not reached */
+
+	case SPCI_RX_RELEASE:
+	case SPCI_RXTX_MAP_SMC32:
+	case SPCI_RXTX_MAP_SMC64:
+	case SPCI_RXTX_UNMAP:
+	case SPCI_MSG_RUN:
+		/* This interface must be invoked only by the Normal world */
+		if (in_sstate == SECURE) {
+			SMC_RET8(handle, SPCI_ERROR,
+				 SPCI_TARGET_INFO_MBZ, SPCI_ERROR_NOT_SUPPORTED,
+				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
+				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ);
+		}
+
+		/* Fall through to forward the call to the other world */
+
+	case SPCI_PARTITION_INFO_GET:
+	case SPCI_MSG_SEND:
+	case SPCI_MSG_SEND_DIRECT_REQ_SMC32:
+	case SPCI_MSG_SEND_DIRECT_REQ_SMC64:
+	case SPCI_MSG_SEND_DIRECT_RESP_SMC32:
+	case SPCI_MSG_SEND_DIRECT_RESP_SMC64:
+	case SPCI_MEM_DONATE_SMC32:
+	case SPCI_MEM_DONATE_SMC64:
+	case SPCI_MEM_LEND_SMC32:
+	case SPCI_MEM_LEND_SMC64:
+	case SPCI_MEM_SHARE_SMC32:
+	case SPCI_MEM_SHARE_SMC64:
+	case SPCI_MEM_RETRIEVE_REQ_SMC32:
+	case SPCI_MEM_RETRIEVE_REQ_SMC64:
+	case SPCI_MEM_RETRIEVE_RESP:
+	case SPCI_MEM_RELINQUISH:
+	case SPCI_MEM_RECLAIM:
+	case SPCI_SUCCESS_SMC32:
+	case SPCI_SUCCESS_SMC64:
+		/*
+		 * TODO: Assume that no requests originate from EL3 at the
+		 * moment. This will change if a SP service is required in
+		 * response to secure interrupts targeted to EL3. Until then
+		 * simply forward the call to the Normal world.
+		 */
+
+		/* Save incoming security state */
+		cm_el1_sysregs_context_save(in_sstate);
+
+		/* Restore outgoing security state */
+		cm_el1_sysregs_context_restore(out_sstate);
+		cm_set_next_eret_context(out_sstate);
+
+		SMC_RET8(cm_get_context(out_sstate), smc_fid, x1, x2, x3, x4,
+			 SMC_GET_GP(handle, CTX_GPREG_X5),
+			 SMC_GET_GP(handle, CTX_GPREG_X6),
+			 SMC_GET_GP(handle, CTX_GPREG_X7));
+		break; /* not reached */
+
+	case SPCI_MSG_WAIT:
+		/*
+		 * Check if this is the first invocation of this interface on
+		 * this CPU from the Secure world. If so, then indicate that the
+		 * SPM core initialised successfully.
+		 */
+		if ((in_sstate == SECURE) && (ctx->state == SPMC_STATE_RESET)) {
+			spmd_spm_core_sync_exit(0);
+		}
+
+		/* Intentional fall-through */
+
+	case SPCI_MSG_YIELD:
+		/* This interface must be invoked only by the Secure world */
+		if (in_sstate == NON_SECURE) {
+			SMC_RET8(handle, SPCI_ERROR,
+				 SPCI_TARGET_INFO_MBZ, SPCI_ERROR_NOT_SUPPORTED,
+				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
+				 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ);
+		}
+
+		/* Save incoming security state */
+		cm_el1_sysregs_context_save(in_sstate);
+
+		/* Restore outgoing security state */
+		cm_el1_sysregs_context_restore(out_sstate);
+		cm_set_next_eret_context(out_sstate);
+
+		SMC_RET8(cm_get_context(out_sstate), smc_fid, x1, x2, x3, x4,
+			 SMC_GET_GP(handle, CTX_GPREG_X5),
+			 SMC_GET_GP(handle, CTX_GPREG_X6),
+			 SMC_GET_GP(handle, CTX_GPREG_X7));
+		break; /* not reached */
+
+	default:
+		WARN("SPM: Unsupported call 0x%08x\n", smc_fid);
+		SMC_RET8(handle, SPCI_ERROR,
+			 SPCI_TARGET_INFO_MBZ, SPCI_ERROR_NOT_SUPPORTED,
+			 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ, SPCI_PARAM_MBZ,
+			 SPCI_PARAM_MBZ, SPCI_PARAM_MBZ);
+	}
+}
diff --git a/services/std_svc/spmd/spmd_private.h b/services/std_svc/spmd/spmd_private.h
new file mode 100644
index 0000000..61b479a
--- /dev/null
+++ b/services/std_svc/spmd/spmd_private.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SPMD_PRIVATE_H
+#define SPMD_PRIVATE_H
+
+#include <context.h>
+
+/*******************************************************************************
+ * Constants that allow assembler code to preserve callee-saved registers of the
+ * C runtime context while performing a security state switch.
+ ******************************************************************************/
+#define SPMD_C_RT_CTX_X19		0x0
+#define SPMD_C_RT_CTX_X20		0x8
+#define SPMD_C_RT_CTX_X21		0x10
+#define SPMD_C_RT_CTX_X22		0x18
+#define SPMD_C_RT_CTX_X23		0x20
+#define SPMD_C_RT_CTX_X24		0x28
+#define SPMD_C_RT_CTX_X25		0x30
+#define SPMD_C_RT_CTX_X26		0x38
+#define SPMD_C_RT_CTX_X27		0x40
+#define SPMD_C_RT_CTX_X28		0x48
+#define SPMD_C_RT_CTX_X29		0x50
+#define SPMD_C_RT_CTX_X30		0x58
+
+#define SPMD_C_RT_CTX_SIZE		0x60
+#define SPMD_C_RT_CTX_ENTRIES		(SPMD_C_RT_CTX_SIZE >> DWORD_SHIFT)
+
+#ifndef __ASSEMBLER__
+#include <services/spci_svc.h>
+#include <stdint.h>
+
+/*
+ * Convert a function no. in a FID to a bit position. All function nos. are
+ * between 0 and 0x1f
+ */
+#define SPCI_FNO_TO_BIT_POS(_fid)	(1 << ((_fid) & U(0x1f)))
+
+typedef enum spmc_state {
+	SPMC_STATE_RESET = 0,
+	SPMC_STATE_IDLE
+} spmc_state_t;
+
+/*
+ * Data structure used by the SPM dispatcher (SPMD) in EL3 to track context of
+ * the SPM core (SPMC) at the next lower EL.
+ */
+typedef struct spmd_spm_core_context {
+	uint64_t c_rt_ctx;
+	cpu_context_t cpu_ctx;
+	spmc_state_t state;
+} spmd_spm_core_context_t;
+
+/*
+ * Data structure used by the SPM dispatcher (SPMD) in EL3 to track sequence of
+ * SPCI calls from lower ELs.
+ *
+ * next_smc_bit_map: Per-cpu bit map of SMCs from each world that are expected
+ *                   next.
+ */
+typedef struct spmd_spci_context {
+	uint32_t next_smc_bit_map[2];
+} spmd_spci_context_t;
+
+/* Functions used to enter/exit a Secure Partition synchronously */
+uint64_t spmd_spm_core_sync_entry(spmd_spm_core_context_t *ctx);
+__dead2 void spmd_spm_core_sync_exit(uint64_t rc);
+
+/* Assembly helpers */
+uint64_t spmd_spm_core_enter(uint64_t *c_rt_ctx);
+void __dead2 spmd_spm_core_exit(uint64_t c_rt_ctx, uint64_t ret);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* SPMD_PRIVATE_H */
diff --git a/services/std_svc/std_svc_setup.c b/services/std_svc/std_svc_setup.c
index 7787a2f..895fd29 100644
--- a/services/std_svc/std_svc_setup.c
+++ b/services/std_svc/std_svc_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,6 +15,7 @@
 #include <lib/runtime_instr.h>
 #include <services/sdei.h>
 #include <services/spm_mm_svc.h>
+#include <services/spmd_svc.h>
 #include <services/std_svc.h>
 #include <smccc_helpers.h>
 #include <tools_share/uuid.h>
@@ -51,6 +52,12 @@
 	}
 #endif
 
+#if defined(SPD_spmd)
+	if (spmd_setup() != 0) {
+		ret = 1;
+	}
+#endif
+
 #if SDEI_SUPPORT
 	/* SDEI initialisation */
 	sdei_init();
@@ -114,6 +121,17 @@
 	}
 #endif
 
+#if defined(SPD_spmd)
+	/*
+	 * Dispatch SPCI calls to the SPCI SMC handler implemented by the SPM
+	 * dispatcher and return its return value
+	 */
+	if (is_spci_fid(smc_fid)) {
+		return spmd_smc_handler(smc_fid, x1, x2, x3, x4, cookie,
+					handle, flags);
+	}
+#endif
+
 #if SDEI_SUPPORT
 	if (is_sdei_fid(smc_fid)) {
 		return sdei_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle,