Merge "fix(plat/synquacer): update scmi power domain off handling" into integration
diff --git a/Makefile b/Makefile
index 4dbc2be..8411355 100644
--- a/Makefile
+++ b/Makefile
@@ -525,6 +525,10 @@
         ifeq ($(TS_SP_FW_CONFIG),1)
             DTC_CPPFLAGS	+=	-DTS_SP_FW_CONFIG
         endif
+
+        ifneq ($(ARM_BL2_SP_LIST_DTS),)
+            DTC_CPPFLAGS += -DARM_BL2_SP_LIST_DTS=$(ARM_BL2_SP_LIST_DTS)
+        endif
     else
         # All other SPDs in spd directory
         SPD_DIR := spd
@@ -746,6 +750,10 @@
     endif
 endif
 
+ifeq ($(PSA_FWU_SUPPORT),1)
+    $(info PSA_FWU_SUPPORT is an experimental feature)
+endif
+
 ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1)
     ifeq (${ALLOW_RO_XLAT_TABLES}, 1)
         $(error "ALLOW_RO_XLAT_TABLES requires translation tables library v2")
@@ -959,6 +967,7 @@
         USE_SP804_TIMER \
         ENABLE_FEAT_RNG \
         ENABLE_FEAT_SB \
+        PSA_FWU_SUPPORT \
 )))
 
 $(eval $(call assert_numerics,\
@@ -967,6 +976,8 @@
         ARM_ARCH_MINOR \
         BRANCH_PROTECTION \
         FW_ENC_STATUS \
+        NR_OF_FW_BANKS \
+        NR_OF_IMAGES_IN_FW_BANK \
 )))
 
 ifdef KEY_SIZE
@@ -1054,6 +1065,9 @@
         USE_SP804_TIMER \
         ENABLE_FEAT_RNG \
         ENABLE_FEAT_SB \
+        NR_OF_FW_BANKS \
+        NR_OF_IMAGES_IN_FW_BANK \
+        PSA_FWU_SUPPORT \
 )))
 
 ifeq (${SANITIZE_UB},trap)
diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c
index 203e1d4..d2de135 100644
--- a/bl2/bl2_main.c
+++ b/bl2/bl2_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,6 +14,7 @@
 #include <common/debug.h>
 #include <drivers/auth/auth_mod.h>
 #include <drivers/console.h>
+#include <drivers/fwu/fwu.h>
 #if MEASURED_BOOT
 #include <drivers/measured_boot/measured_boot.h>
 #endif
@@ -88,6 +89,10 @@
 	/* Perform remaining generic architectural setup in S-EL1 */
 	bl2_arch_setup();
 
+#if PSA_FWU_SUPPORT
+	fwu_init();
+#endif /* PSA_FWU_SUPPORT */
+
 #if TRUSTED_BOARD_BOOT
 	/* Initialize authentication module */
 	auth_mod_init();
diff --git a/common/bl_common.c b/common/bl_common.c
index f17afcb..a7e2816 100644
--- a/common/bl_common.c
+++ b/common/bl_common.c
@@ -239,9 +239,18 @@
 {
 	int err;
 
+/*
+ * All firmware banks should be part of the same non-volatile storage as per
+ * PSA FWU specification, hence don't check for any alternate boot source
+ * when PSA FWU is enabled.
+ */
+#if PSA_FWU_SUPPORT
+	err = load_auth_image_internal(image_id, image_data);
+#else
 	do {
 		err = load_auth_image_internal(image_id, image_data);
 	} while ((err != 0) && (plat_try_next_boot_source() != 0));
+#endif /* PSA_FWU_SUPPORT */
 
 	return err;
 }
diff --git a/common/hw_crc32.c b/common/tf_crc32.c
similarity index 86%
rename from common/hw_crc32.c
rename to common/tf_crc32.c
index a8731da..b33d36e 100644
--- a/common/hw_crc32.c
+++ b/common/tf_crc32.c
@@ -9,8 +9,9 @@
 
 #include <arm_acle.h>
 #include <common/debug.h>
+#include <common/tf_crc32.h>
 
-/* hw_crc32 - compute CRC using Arm intrinsic function
+/* compute CRC using Arm intrinsic function
  *
  * This function is useful for the platforms with the CPU ARMv8.0
  * (with CRC instructions supported), and onwards.
@@ -23,7 +24,7 @@
  *
  * Return calculated CRC value
  */
-uint32_t hw_crc32(uint32_t crc, const unsigned char *buf, size_t size)
+uint32_t tf_crc32(uint32_t crc, const unsigned char *buf, size_t size)
 {
 	assert(buf != NULL);
 
diff --git a/common/tf_log.c b/common/tf_log.c
index 08d3cf4..68f1be4 100644
--- a/common/tf_log.c
+++ b/common/tf_log.c
@@ -49,6 +49,20 @@
 	va_end(args);
 }
 
+void tf_log_newline(const char log_fmt[2])
+{
+	unsigned int log_level = log_fmt[0];
+
+	/* Verify that log_level is one of LOG_MARKER_* macro defined in debug.h */
+	assert((log_level > 0U) && (log_level <= LOG_LEVEL_VERBOSE));
+	assert((log_level % 10U) == 0U);
+
+	if (log_level > max_log_level)
+		return;
+
+	putchar('\n');
+}
+
 /*
  * The helper function to set the log level dynamically by platform. The
  * maximum log level is determined by `LOG_LEVEL` build flag at compile time
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index 725e96b..07f258c 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -415,13 +415,13 @@
 :|F|: plat/arm/board/rdv1mc/
 :|F|: plat/arm/board/sgi575/
 
-Arm Total Compute(tc0) platform port
+Arm Total Compute platform port
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 :|M|: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
 :|G|: `arugan02`_
 :|M|: Usama Arif <usama.arif@arm.com>
 :|G|: `uarif1`_
-:|F|: plat/arm/board/tc0
+:|F|: plat/arm/board/tc
 
 HiSilicon HiKey and HiKey960 platform ports
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/docs/components/ffa-manifest-binding.rst b/docs/components/ffa-manifest-binding.rst
index 9e3919d..437df67 100644
--- a/docs/components/ffa-manifest-binding.rst
+++ b/docs/components/ffa-manifest-binding.rst
@@ -106,14 +106,14 @@
      The "compatible" must be the string "arm,ffa-manifest-rx_tx-buffer".
 
 - messaging-method [mandatory]
-   - value type: <u32>
-   - Specifies which messaging methods are supported by the partition:
+   - value type: <u8>
+   - Specifies which messaging methods are supported by the partition, set bit
+     means the feature is supported, clear bit - not supported:
 
-      - 0x0: direct messaging method
-      - 0x1: indirect messaging method
-      - 0x2: both direct and indirect messaging methods
-      - 0x3: direct messaging method with managed exit support
-      - 0x4: both messaging methods with managed exit support
+      - Bit[0]: support for receiving direct message requests
+      - Bit[1]: support for sending direct messages
+      - Bit[2]: support for indirect messaging
+      - Bit[3]: support for managed exit
 
 - has-primary-scheduler
    - value type: <empty>
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index 949845a..bde6d97 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -281,6 +281,19 @@
 -  ``ERRATA_A78_1821534``: This applies errata 1821534 workaround to Cortex-A78
    CPU. This needs to be enabled for revisions r0p0 and r1p0.
 
+-  ``ERRATA_A78_1952683``: This applies errata 1952683 workaround to Cortex-A78
+   CPU. This needs to be enabled for revision r0p0, it is fixed in r1p0.
+
+For Cortex-A78 AE, the following errata build flags are defined :
+
+- ``ERRATA_A78_AE_1941500`` : This applies errata 1941500 workaround to Cortex-A78
+   AE CPU. This needs to be enabled for revisions r0p0 and r0p1. This erratum is
+   still open.
+
+- ``ERRATA_A78_AE_1951502`` : This applies errata 1951502 workaround to Cortex-A78
+  AE CPU. This needs to be enabled for revisions r0p0 and r0p1. This erratum is
+  still open.
+
 For Neoverse N1, the following errata build flags are defined :
 
 -  ``ERRATA_N1_1073348``: This applies errata 1073348 workaround to Neoverse-N1
@@ -323,16 +336,73 @@
    CPU. This needs to be enabled for revisions r3p0, r3p1, r4p0, and r4p1, for
    revisions r0p0, r1p0, and r2p0 there is no workaround.
 
+For Neoverse N2, the following errata build flags are defined :
+
+-  ``ERRATA_N2_2002655``: This applies errata 2002655 workaround to Neoverse-N2
+   CPU. This needs to be enabled for revision r0p0 of the CPU, it is still open.
+
 For Neoverse V1, the following errata build flags are defined :
 
+-  ``ERRATA_V1_1774420``: This applies errata 1774420 workaround to Neoverse-V1
+   CPU. This needs to be enabled only for revisions r0p0 and r1p0, it is fixed
+   in r1p1.
+
 -  ``ERRATA_V1_1791573``: This applies errata 1791573 workaround to Neoverse-V1
    CPU. This needs to be enabled only for revisions r0p0 and r1p0, it is fixed
    in r1p1.
 
+-  ``ERRATA_V1_1852267``: This applies errata 1852267 workaround to Neoverse-V1
+   CPU. This needs to be enabled only for revisions r0p0 and r1p0, it is fixed
+   in r1p1.
+
+-  ``ERRATA_V1_1925756``: This applies errata 1925756 workaround to Neoverse-V1
+   CPU. This needs to be enabled for r0p0, r1p0, and r1p1, it is still open.
+
 -  ``ERRATA_V1_1940577``: This applies errata 1940577 workaround to Neoverse-V1
    CPU. This needs to be enabled only for revision r1p0 and r1p1 of the
    CPU.
 
+-  ``ERRATA_V1_1966096``: This applies errata 1966096 workaround to Neoverse-V1
+   CPU. This needs to be enabled for revisions r1p0 and r1p1 of the CPU, the
+   issue is present in r0p0 as well but there is no workaround for that
+   revision.  It is still open.
+
+-  ``ERRATA_V1_2139242``: This applies errata 2139242 workaround to Neoverse-V1
+   CPU. This needs to be enabled for revisions r0p0, r1p0, and r1p1 of the
+   CPU.  It is still open.
+
+For Cortex-A710, the following errata build flags are defined :
+
+-  ``ERRATA_A710_1987031``: This applies errata 1987031 workaround to
+   Cortex-A710 CPU. This needs to be enabled only for revisions r0p0, r1p0 and
+   r2p0 of the CPU. It is still open.
+
+-  ``ERRATA_A710_2081180``: This applies errata 2081180 workaround to
+   Cortex-A710 CPU. This needs to be enabled only for revisions r0p0, r1p0 and
+   r2p0 of the CPU. It is still open.
+
+-  ``ERRATA_A710_2055002``: This applies errata 2055002 workaround to
+   Cortex-A710 CPU. This needs to be enabled for revisions r1p0, r2p0 of the CPU
+   and is still open.
+
+-  ``ERRATA_A710_2017096``: This applies errata 2017096 workaround to
+   Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0
+   of the CPU and is still open.
+
+For Neoverse N2, the following errata build flags are defined :
+
+-  ``ERRATA_N2_2067956``: This applies errata 2067956 workaround to Neoverse-N2
+   CPU. This needs to be enabled for revision r0p0 of the CPU and is still open.
+
+-  ``ERRATA_N2_2025414``: This applies errata 2025414 workaround to Neoverse-N2
+   CPU. This needs to be enabled for revision r0p0 of the CPU and is still open.
+
+-  ``ERRATA_N2_2189731``: This applies errata 2189731 workaround to Neoverse-N2
+   CPU. This needs to be enabled for revision r0p0 of the CPU and is still open.
+
+-  ``ERRATA_N2_2138956``: This applies errata 2138956 workaround to Neoverse-N2
+   CPU. This needs to be enabled for revision r0p0 of the CPU and is still open.
+
 DSU Errata Workarounds
 ----------------------
 
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 86618e4..bac8847 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -790,6 +790,11 @@
    GIC-600, so is safe to select even for a GIC500 implementation.
    This option defaults to 0.
 
+- ``GICV3_SUPPORT_GIC600AE_FMU``: Add support for the Fault Management Unit
+   for GIC-600 AE. Enabling this option will introduce support to initialize
+   the FMU. Platforms should call the init function during boot to enable the
+   FMU and its safety mechanisms. This option defaults to 0.
+
 -  ``GICV3_IMPL_GIC600_MULTICHIP``: Selects GIC-600 variant with multichip
    functionality. This option defaults to 0
 
@@ -860,9 +865,31 @@
     # Resume execution
     continue
 
+Firmware update options
+-----------------------
+
+-  ``NR_OF_FW_BANKS``: Define the number of firmware banks. This flag is used
+   in defining the firmware update metadata structure. This flag is by default
+   set to '2'.
+
+-  ``NR_OF_IMAGES_IN_FW_BANK``: Define the number of firmware images in each
+   firmware bank. Each firmware bank must have the same number of images as per
+   the `PSA FW update specification`_.
+   This flag is used in defining the firmware update metadata structure. This
+   flag is by default set to '1'.
+
+-  ``PSA_FWU_SUPPORT``: Enable the firmware update mechanism as per the
+   `PSA FW update specification`_. The default value is 0, and this is an
+   experimental feature.
+   PSA firmware update implementation has some limitations, such as BL2 is
+   not part of the protocol-updatable images, if BL2 needs to be updated, then
+   it should be done through another platform-defined mechanism, and it assumes
+   that the platform's hardware supports CRC32 instructions.
+
 --------------
 
 *Copyright (c) 2019-2021, Arm Limited. All rights reserved.*
 
 .. _DEN0115: https://developer.arm.com/docs/den0115/latest
+.. _PSA FW update specification: https://developer.arm.com/documentation/den0118/a/
 
diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst
index 906daf8..54754fe 100644
--- a/docs/getting_started/porting-guide.rst
+++ b/docs/getting_started/porting-guide.rst
@@ -894,6 +894,54 @@
 Note that this API depends on ``DECRYPTION_SUPPORT`` build flag which is
 marked as experimental.
 
+Function : plat_fwu_set_images_source() [when PSA_FWU_SUPPORT == 1]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : struct fwu_metadata *metadata
+    Return   : void
+
+This function is mandatory when PSA_FWU_SUPPORT is enabled.
+It provides a means to retrieve image specification (offset in
+non-volatile storage and length) of active/updated images using the passed
+FWU metadata, and update I/O policies of active/updated images using retrieved
+image specification information.
+Further I/O layer operations such as I/O open, I/O read, etc. on these
+images rely on this function call.
+
+In Arm platforms, this function is used to set an I/O policy of the FIP image,
+container of all active/updated secure and non-secure images.
+
+Function : plat_fwu_set_metadata_image_source() [when PSA_FWU_SUPPORT == 1]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : unsigned int image_id, uintptr_t *dev_handle,
+               uintptr_t *image_spec
+    Return   : int
+
+This function is mandatory when PSA_FWU_SUPPORT is enabled. It is
+responsible for setting up the platform I/O policy of the requested metadata
+image (either FWU_METADATA_IMAGE_ID or BKUP_FWU_METADATA_IMAGE_ID) that will
+be used to load this image from the platform's non-volatile storage.
+
+FWU metadata can not be always stored as a raw image in non-volatile storage
+to define its image specification (offset in non-volatile storage and length)
+statically in I/O policy.
+For example, the FWU metadata image is stored as a partition inside the GUID
+partition table image. Its specification is defined in the partition table
+that needs to be parsed dynamically.
+This function provides a means to retrieve such dynamic information to set
+the I/O policy of the FWU metadata image.
+Further I/O layer operations such as I/O open, I/O read, etc. on FWU metadata
+image relies on this function call.
+
+It returns '0' on success, otherwise a negative error value on error.
+Alongside, returns device handle and image specification from the I/O policy
+of the requested FWU metadata image.
+
 Common optional modifications
 -----------------------------
 
diff --git a/docs/index.rst b/docs/index.rst
index 29e5839..edc2535 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -30,6 +30,7 @@
 -  `SMC Calling Convention`_
 -  `System Control and Management Interface (SCMI)`_
 -  `Software Delegated Exception Interface (SDEI)`_
+-  `PSA FW update specification`_
 
 Where possible, the code is designed for reuse or porting to other Armv7-A and
 Armv8-A model and hardware platforms.
@@ -92,3 +93,4 @@
 .. _System Control and Management Interface (SCMI): http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/DEN0056A_System_Control_and_Management_Interface.pdf
 .. _Software Delegated Exception Interface (SDEI): http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf
 .. _SMC Calling Convention: https://developer.arm.com/docs/den0028/latest
+.. _PSA FW update specification: https://developer.arm.com/documentation/den0118/a/
diff --git a/docs/plat/arm/arm-build-options.rst b/docs/plat/arm/arm-build-options.rst
index d4fa98d..74251bd 100644
--- a/docs/plat/arm/arm-build-options.rst
+++ b/docs/plat/arm/arm-build-options.rst
@@ -100,6 +100,9 @@
 -  ``ARM_SPMC_MANIFEST_DTS`` : path to an alternate manifest file used as the
    SPMC Core manifest. Valid when ``SPD=spmd`` is selected.
 
+-  ``ARM_BL2_SP_LIST_DTS``: Path to DTS file snippet to override the hardcoded
+   SP nodes in tb_fw_config.
+
 -  ``OPTEE_SP_FW_CONFIG``: DTC build flag to include OP-TEE as SP in tb_fw_config
    device tree. This flag is defined only when ``ARM_SPMC_MANIFEST_DTS`` manifest
    file name contains pattern optee_sp.
diff --git a/docs/plat/arm/index.rst b/docs/plat/arm/index.rst
index f50dab5..c834f6a 100644
--- a/docs/plat/arm/index.rst
+++ b/docs/plat/arm/index.rst
@@ -8,7 +8,7 @@
    juno/index
    fvp/index
    fvp-ve/index
-   tc0/index
+   tc/index
    arm_fpga/index
    arm-build-options
    morello/index
diff --git a/docs/plat/arm/tc0/index.rst b/docs/plat/arm/tc/index.rst
similarity index 73%
rename from docs/plat/arm/tc0/index.rst
rename to docs/plat/arm/tc/index.rst
index 34d1f13..20d3e56 100644
--- a/docs/plat/arm/tc0/index.rst
+++ b/docs/plat/arm/tc/index.rst
@@ -1,7 +1,7 @@
-TC0 Total Compute Platform
+TC Total Compute Platform
 ==========================
 
-Some of the features of TC0 platform referenced in TF-A include:
+Some of the features of TC platform referenced in TF-A include:
 
 - A `System Control Processor <https://github.com/ARM-software/SCP-firmware>`_
   to abstract power and system management tasks away from application
@@ -13,6 +13,12 @@
 - SCMI
 - MHUv2
 
+Currently, the main difference between TC0 (TARGET_PLATFORM=0) and TC1
+(TARGET_PLATFORM=1) platforms w.r.t to TF-A is the CPUs supported. TC0 has
+support for Cortex A510, Cortex A710 and Cortex X2, while TC1 has support for
+Cortex A510, Cortex Makalu and Cortex Makalu ELP Arm CPUs.
+
+
 Boot Sequence
 -------------
 
@@ -34,8 +40,8 @@
 
    .. code:: shell
 
-      make PLAT=tc0 BL33=<path_to_uboot.bin> \
-      SCP_BL2=<path_to_scp_ramfw.bin>  all fip
+      make PLAT=tc BL33=<path_to_uboot.bin> \
+      SCP_BL2=<path_to_scp_ramfw.bin> TARGET_PLATFORM={0,1} all fip
 
    Enable TBBR by adding the following options to the make command:
 
@@ -47,4 +53,4 @@
       ARM_ROTPK_LOCATION=devel_rsa  \
       ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem
 
-*Copyright (c) 2020, Arm Limited. All rights reserved.*
+*Copyright (c) 2020-2021, Arm Limited. All rights reserved.*
diff --git a/docs/plat/index.rst b/docs/plat/index.rst
index 4dc9ecd..5848005 100644
--- a/docs/plat/index.rst
+++ b/docs/plat/index.rst
@@ -27,6 +27,7 @@
    imx8
    imx8m
    ls1043a
+   nxp/index
    poplar
    qemu
    qemu-sbsa
diff --git a/docs/plat/marvell/armada/build.rst b/docs/plat/marvell/armada/build.rst
index ca84be6..b125144 100644
--- a/docs/plat/marvell/armada/build.rst
+++ b/docs/plat/marvell/armada/build.rst
@@ -62,6 +62,7 @@
             - a80x0_mcbin  - MacchiatoBin
             - a80x0_puzzle - IEI Puzzle-M801
             - t9130        - CN913x
+            - t9130_cex7_eval - CN913x CEx7 Evaluation Board
 
 - DEBUG
 
@@ -136,9 +137,45 @@
         The parameter is optional, its default value is ``plat/marvell/armada/a8k/common/ble``
         which uses TF-A in-tree BLE implementation.
 
+- MSS_SUPPORT
+
+        When ``MSS_SUPPORT=1``, then TF-A includes support for Management SubSystem (MSS).
+        When enabled it is required to specify path to the MSS firmware image via ``SCP_BL2``
+        option.
+
+        This option is by default enabled.
+
+- SCP_BL2
+
+        Specify path to the MSS fimware image binary which will run on Cortex-M3 coprocessor.
+        It is available in Marvell binaries-marvell git repository. Required when ``MSS_SUPPORT=1``.
+
 
 Armada37x0 specific build options:
 
+- HANDLE_EA_EL3_FIRST
+
+        When ``HANDLE_EA_EL3_FIRST=1``, External Aborts and SError Interrupts will be always trapped
+        in TF-A. TF-A in this case enables dirty hack / workaround for a bug found in U-Boot and
+        Linux kernel PCIe controller driver pci-aardvark.c, traps and then masks SError interrupt
+        caused by AXI SLVERR on external access (syndrome 0xbf000002).
+
+        Otherwise when ``HANDLE_EA_EL3_FIRST=0``, these exceptions will be trapped in the current
+        exception level (or in EL1 if the current exception level is EL0). So exceptions caused by
+        U-Boot will be trapped in U-Boot, exceptions caused by Linux kernel (or user applications)
+        will be trapped in Linux kernel.
+
+        Mentioned bug in pci-aardvark.c driver is fixed in U-Boot version v2021.07 and Linux kernel
+        version v5.13 (workarounded since Linux kernel version 5.9) and also backported in Linux
+        kernel stable releases since versions v5.12.13, v5.10.46, v5.4.128, v4.19.198, v4.14.240.
+
+        If target system has already patched version of U-Boot and Linux kernel then it is strongly
+        recommended to not enable this workaround as it disallows propagating of all External Aborts
+        to running Linux kernel and makes correctable errors as fatal aborts.
+
+        This option is now disabled by default. In past this option was enabled by default in
+        TF-A versions v2.2, v2.3, v2.4 and v2.5.
+
 - CM3_SYSTEM_RESET
 
         When ``CM3_SYSTEM_RESET=1``, the Cortex-M3 secure coprocessor will be used for system reset.
@@ -405,10 +442,15 @@
 
     https://gitlab.nic.cz/turris/mox-boot-builder.git
 
-Armada70x0 and Armada80x0 Builds require installation of an additional component
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Armada70x0, Armada80x0 and CN913x Builds require installation of additional components
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 (1) DDR initialization library sources (mv_ddr) available at the following repository
     (use the "master" branch):
 
     https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git
+
+(2) MSS Management SubSystem Firmware available at the following repository
+    (use the "binaries-marvell-armada-SDK10.0.1.0" branch):
+
+    https://github.com/MarvellEmbeddedProcessors/binaries-marvell.git
diff --git a/docs/plat/nvidia-tegra.rst b/docs/plat/nvidia-tegra.rst
index 02ff38b..391c7c8 100644
--- a/docs/plat/nvidia-tegra.rst
+++ b/docs/plat/nvidia-tegra.rst
@@ -19,7 +19,7 @@
 multi-processing (HMP) solution designed to optimize performance and
 efficiency.
 
-T186 has Dual NVIDIA Denver 2 ARM® CPU cores, plus Quad ARM Cortex®-A57 cores,
+T186 has Dual NVIDIA Denver2 ARM® CPU cores, plus Quad ARM Cortex®-A57 cores,
 in a coherent multiprocessor configuration. The Denver 2 and Cortex-A57 cores
 support ARMv8, executing both 64-bit Aarch64 code, and 32-bit Aarch32 code
 including legacy ARMv7 applications. The Denver 2 processors each have 128 KB
@@ -29,20 +29,6 @@
 high speed coherency fabric connects these two processor complexes and allows
 heterogeneous multi-processing with all six cores if required.
 
--  .. rubric:: T210
-      :name: t210
-
-T210 has Quad Arm® Cortex®-A57 cores in a switched configuration with a
-companion set of quad Arm Cortex-A53 cores. The Cortex-A57 and A53 cores
-support Armv8-A, executing both 64-bit Aarch64 code, and 32-bit Aarch32 code
-including legacy Armv7-A applications. The Cortex-A57 processors each have
-48 KB Instruction and 32 KB Data Level 1 caches; and have a 2 MB shared
-Level 2 unified cache. The Cortex-A53 processors each have 32 KB Instruction
-and 32 KB Data Level 1 caches; and have a 512 KB shared Level 2 unified cache.
-
--  .. rubric:: T132
-      :name: t132
-
 Denver is NVIDIA's own custom-designed, 64-bit, dual-core CPU which is
 fully Armv8-A architecture compatible. Each of the two Denver cores
 implements a 7-way superscalar microarchitecture (up to 7 concurrent
@@ -68,6 +54,17 @@
 to extensive power-gating and dynamic voltage and clock scaling based on
 workloads.
 
+-  .. rubric:: T210
+      :name: t210
+
+T210 has Quad Arm® Cortex®-A57 cores in a switched configuration with a
+companion set of quad Arm Cortex-A53 cores. The Cortex-A57 and A53 cores
+support Armv8-A, executing both 64-bit Aarch64 code, and 32-bit Aarch32 code
+including legacy Armv7-A applications. The Cortex-A57 processors each have
+48 KB Instruction and 32 KB Data Level 1 caches; and have a 2 MB shared
+Level 2 unified cache. The Cortex-A53 processors each have 32 KB Instruction
+and 32 KB Data Level 1 caches; and have a 512 KB shared Level 2 unified cache.
+
 Directory structure
 -------------------
 
@@ -89,7 +86,6 @@
 
 These are the supported Trusted OS' by Tegra platforms.
 
-- Tegra132: TLK
 - Tegra210: TLK and Trusty
 - Tegra186: Trusty
 - Tegra194: Trusty
@@ -110,7 +106,7 @@
 .. code:: shell
 
     CROSS_COMPILE=<path-to-aarch64-gcc>/bin/aarch64-none-elf- make PLAT=tegra \
-    TARGET_SOC=<target-soc e.g. t194|t186|t210|t132> SPD=<dispatcher e.g. trusty|tlkd>
+    TARGET_SOC=<target-soc e.g. t194|t186|t210> SPD=<dispatcher e.g. trusty|tlkd>
     bl31
 
 Platforms wanting to use different TZDRAM\_BASE, can add ``TZDRAM_BASE=<value>``
diff --git a/docs/plat/nxp/index.rst b/docs/plat/nxp/index.rst
new file mode 100644
index 0000000..8546887
--- /dev/null
+++ b/docs/plat/nxp/index.rst
@@ -0,0 +1,17 @@
+NXP Reference Development Platforms
+===================================
+
+.. toctree::
+   :maxdepth: 1
+   :caption: Contents
+
+   nxp-layerscape
+   nxp-ls-fuse-prov
+   nxp-ls-tbbr
+
+This chapter holds documentation related to NXP reference development platforms.
+It includes details on image flashing, fuse provisioning and trusted board boot-up.
+
+--------------
+
+*Copyright (c) 2021, NXP Limited. All rights reserved.*
diff --git a/docs/plat/nxp/nxp-layerscape.rst b/docs/plat/nxp/nxp-layerscape.rst
new file mode 100644
index 0000000..3d98354
--- /dev/null
+++ b/docs/plat/nxp/nxp-layerscape.rst
@@ -0,0 +1,232 @@
+NXP SoCs - Overview
+=====================
+.. section-numbering::
+    :suffix: .
+
+The QorIQ family of ARM based SoCs that are supported on TF-A are:
+
+1. LX2160ARDB:
+        Platform Name:
+
+        a. lx2160ardb (Board details can be fetched from the link: `lx2160ardb`_)
+
+
+Table of supported boot-modes by each platform & platform that needs FIP-DDR:
+-----------------------------------------------------------------------------
+
++---+-----------------+-------+--------+-------+-------+-------+-------------+--------------+-----------------+
+|   |     BOOT_MODE-->|  sd   |  qspi  |  nor  | nand  | emmc  | flexspi_nor | flexspi_nand | fip_ddr needed  |
+|   |                 |       |        |       |       |       |             |              |                 |
+|   |     PLAT        |       |        |       |       |       |             |              |                 |
++===+=================+=======+========+=======+=======+=======+=============+==============+=================+
+| 1.| lx2160ardb      |  yes  |        |       |       |  yes  |   yes       |              |       yes       |
++---+-----------------+-------+--------+-------+-------+-------+-------------+--------------+-----------------+
+
+Boot Sequence
+-------------
+::
+
++                           Secure World        |     Normal World
++ EL0                                           |
++                                               |
++ EL1                           BL32(Tee OS)    |     kernel
++                                ^ |            |       ^
++                                | |            |       |
++ EL2                            | |            |     BL33(u-boot)
++                                | |            |      ^
++                                | v            |     /
++ EL3        BootROM --> BL2 --> BL31 ---------------/
++
+
+Boot Sequence with FIP-DDR
+--------------------------
+::
+
++                           Secure World        |     Normal World
++ EL0                                           |
++                                               |
++ EL1               fip-ddr     BL32(Tee OS)    |     kernel
++                     ^ |         ^ |           |       ^
++                     | |         | |           |       |
++ EL2                 | |         | |           |     BL33(u-boot)
++                     | |         | |           |      ^
++                     | v         | v           |     /
++ EL3     BootROM --> BL2 -----> BL31 ---------------/
++
+
+
+How to build
+=============
+
+Code Locations
+--------------
+
+-  OP-TEE:
+   `link <https://source.codeaurora.org/external/qoriq/qoriq-components/optee_os>`__
+
+-  U-Boot:
+   `link <https://source.codeaurora.org/external/qoriq/qoriq-components/u-boot>`__
+
+-  RCW:
+   `link <https://source.codeaurora.org/external/qoriq/qoriq-components/rcw>`__
+
+-  ddr-phy-binary: Required by platforms that need fip-ddr.
+   `link <https:://github.com/NXP/ddr-phy-binary>`__
+
+-  cst: Required for TBBR.
+   `link <https:://source.codeaurora.org/external/qoriq/qoriq-components/cst>`__
+
+Build Procedure
+---------------
+
+-  Fetch all the above repositories into local host.
+
+-  Prepare AARCH64 toolchain and set the environment variable "CROSS_COMPILE".
+
+   .. code:: shell
+
+       export CROSS_COMPILE=.../bin/aarch64-linux-gnu-
+
+-  Build RCW. Refer README from the respective cloned folder for more details.
+
+-  Build u-boot and OPTee firstly, and get binary images: u-boot.bin and tee.bin.
+   For u-boot you can use the <platform>_tfa_defconfig for build.
+
+-  Copy/clone the repo "ddr-phy-binary" to the tfa directory for platform needing ddr-fip.
+
+-  Below are the steps to build TF-A images for the supported platforms.
+
+Compilation steps without BL32
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+BUILD BL2:
+
+-To compile
+   .. code:: shell
+
+       make PLAT=$PLAT \
+       BOOT_MODE=<platform_supported_boot_mode> \
+       RCW=$RCW_BIN \
+       pbl
+
+BUILD FIP:
+
+   .. code:: shell
+
+       make PLAT=$PLAT \
+       BOOT_MODE=<platform_supported_boot_mode> \
+       RCW=$RCW_BIN \
+       BL33=$UBOOT_SECURE_BIN \
+       pbl \
+       fip
+
+Compilation steps with BL32
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+BUILD BL2:
+
+-To compile
+   .. code:: shell
+
+       make PLAT=$PLAT \
+       BOOT_MODE=<platform_supported_boot_mode> \
+       RCW=$RCW_BIN \
+       BL32=$TEE_BIN SPD=opteed\
+       pbl
+
+BUILD FIP:
+
+   .. code:: shell
+
+       make PLAT=$PLAT \
+       BOOT_MODE=<platform_supported_boot_mode> \
+       RCW=$RCW_BIN \
+       BL32=$TEE_BIN SPD=opteed\
+       BL33=$UBOOT_SECURE_BIN \
+       pbl \
+       fip
+
+
+BUILD fip-ddr (Mandatory for certain platforms, refer table above):
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+-To compile additional fip-ddr for selected platforms(Refer above table if the platform needs fip-ddr).
+   .. code:: shell
+
+	make PLAT=<platform_name> fip-ddr
+
+
+Deploy ATF Images
+=================
+
+Note: The size in the standard uboot commands for copy to nor, qspi, nand or sd
+should be modified based on the binary size of the image to be copied.
+
+-  Deploy ATF images on flexspi-Nor flash Alt Bank from U-Boot prompt.
+   --  Commands to flash images for bl2_xxx.pbl and fip.bin.
+
+   .. code:: shell
+
+        tftp 82000000  $path/bl2_flexspi_nor.pbl;
+        i2c mw 66 50 20;sf probe 0:0; sf erase 0 +$filesize; sf write 0x82000000 0x0 $filesize;
+
+        tftp 82000000  $path/fip.bin;
+        i2c mw 66 50 20;sf probe 0:0; sf erase 0x100000 +$filesize; sf write 0x82000000 0x100000 $filesize;
+
+   --  Next step is valid for platform where FIP-DDR is needed.
+
+   .. code:: shell
+
+        tftp 82000000  $path/ddr_fip.bin;
+        i2c mw 66 50 20;sf probe 0:0; sf erase 0x800000 +$filesize; sf write 0x82000000 0x800000 $filesize;
+
+   --  Then reset to alternate bank to boot up ATF.
+
+   .. code:: shell
+
+        qixisreset altbank;
+
+-  Deploy ATF images on SD/eMMC from U-Boot prompt.
+   -- file_size_in_block_sizeof_512 = (Size_of_bytes_tftp / 512)
+
+   .. code:: shell
+
+        mmc dev <idx>; (idx = 1 for eMMC; idx = 0 for SD)
+
+        tftp 82000000  $path/bl2_<sd>_or_<emmc>.pbl;
+        mmc write 82000000 8 <file_size_in_block_sizeof_512>;
+
+        tftp 82000000  $path/fip.bin;
+        mmc write 82000000 0x800 <file_size_in_block_sizeof_512>;
+
+    --  Next step is valid for platform that needs FIP-DDR.
+
+   .. code:: shell
+
+        tftp 82000000  $path/ddr_fip.bin;
+        mmc write 82000000 0x4000 <file_size_in_block_sizeof_512>;
+
+   --  Then reset to sd/emmc to boot up ATF from sd/emmc as boot-source.
+
+   .. code:: shell
+
+        qixisreset <sd or emmc>;
+
+Trusted Board Boot:
+===================
+
+For TBBR, the binary name changes:
+
++-------------+--------------------------+---------+-------------------+
+|  Boot Type  |           BL2            |   FIP   |      FIP-DDR      |
++=============+==========================+=========+===================+
+| Normal Boot |  bl2_<boot_mode>.pbl     | fip.bin | ddr_fip.bin       |
++-------------+--------------------------+---------+-------------------+
+| TBBR Boot   |  bl2_<boot_mode>_sec.pbl | fip.bin | ddr_fip_sec.bin   |
++-------------+--------------------------+---------+-------------------+
+
+Refer `nxp-ls-tbbr.rst`_ for detailed user steps.
+
+
+.. _lx2160ardb: https://www.nxp.com/products/processors-and-microcontrollers/arm-processors/layerscape-communication-process/layerscape-lx2160a-multicore-communications-processor:LX2160A
+.. _nxp-ls-tbbr.rst: ./nxp-ls-tbbr.rst
diff --git a/docs/plat/nxp/nxp-ls-fuse-prov.rst b/docs/plat/nxp/nxp-ls-fuse-prov.rst
new file mode 100644
index 0000000..64e1c6f
--- /dev/null
+++ b/docs/plat/nxp/nxp-ls-fuse-prov.rst
@@ -0,0 +1,271 @@
+
+Steps to blow fuses on NXP LS SoC:
+==================================
+
+
+- Enable POVDD
+  -- Refer board GSG(Getting Started Guide) for the steps to enable POVDD.
+  -- Once the POVDD is enabled, make sure to set variable POVDD_ENABLE := yes, in the platform.mk.
+
++---+-----------------+-----------+------------+-----------------+-----------------------------+
+|   |   Platform      |  Jumper   |  Switch    | LED to Verify   |  Through GPIO Pin (=number) |
++===+=================+===========+============+=================+=============================+
+| 1.| lx2160ardb      |  J9       |            |                 |             no              |
++---+-----------------+-----------+------------+-----------------+-----------------------------+
+| 2.| lx2160aqds      |  J35      |            |                 |             no              |
++---+-----------------+-----------+------------+-----------------+-----------------------------+
+| 3.| lx2162aqds      |  J35      | SW9[4] = 1 |    D15          |             no              |
++---+-----------------+-----------+------------+-----------------+-----------------------------+
+
+- SFP registers to be written to:
+
++---+----------------------------------+----------------------+----------------------+
+|   |   Platform                       |   OTPMKR0..OTPMKR7   |   SRKHR0..SRKHR7     |
++===+==================================+======================+======================+
+| 1.| lx2160ardb/lx2160aqds/lx2162aqds | 0x1e80234..0x1e80250 | 0x1e80254..0x1e80270 |
++---+----------------------------------+----------------------+----------------------+
+
+- At U-Boot prompt, verify that SNVS register - HPSR, whether OTPMK was written, already:
+
++---+----------------------------------+-------------------------------------------+---------------+
+|   |   Platform                       |           OTPMK_ZERO_BIT(=value)          | SNVS_HPSR_REG |
++===+==================================+===========================================+===============+
+| 1.| lx2160ardb/lx2160aqds/lx2162aqds | 27 (= 1 means not blown, =0 means blown)  | 0x01E90014    |
++---+----------------------------------+-------------------------------------------+---------------+
+
+From u-boot prompt:
+
+  --  Check for the OTPMK.
+   .. code:: shell
+
+        md $SNVS_HPSR_REG
+
+      Command Output:
+          01e90014: 88000900
+
+          In case it is read as 00000000, then read this register using jtag (in development mode only through CW tap).
+                       +0       +4       +8       +C
+          [0x01E90014] 88000900
+
+          Note: OTPMK_ZERO_BIT is 1, indicating that the OTPMK is not blown.
+
+  --  Check for the SRK Hash.
+   .. code:: shell
+
+        md $SRKHR0 0x10
+
+      Command Output:
+          01e80254: 00000000 00000000 00000000 00000000    ................
+          01e80264: 00000000 00000000 00000000 00000000    ................
+
+          Note: Zero means that SRK hash is not blown.
+
+- If not blown, then from the U-Boot prompt, using following commands:
+  --  Provision the OTPMK.
+
+   .. code:: shell
+
+        mw.l $OTPMKR0  <OTMPKR_0_32Bit_val>
+        mw.l $OTPMKR1  <OTMPKR_1_32Bit_val>
+        mw.l $OTPMKR2  <OTMPKR_2_32Bit_val>
+        mw.l $OTPMKR3  <OTMPKR_3_32Bit_val>
+        mw.l $OTPMKR4  <OTMPKR_4_32Bit_val>
+        mw.l $OTPMKR5  <OTMPKR_5_32Bit_val>
+        mw.l $OTPMKR6  <OTMPKR_6_32Bit_val>
+        mw.l $OTPMKR7  <OTMPKR_7_32Bit_val>
+
+  --  Provision the SRK Hash.
+
+   .. code:: shell
+
+        mw.l $SRKHR0  <SRKHR_0_32Bit_val>
+        mw.l $SRKHR1  <SRKHR_1_32Bit_val>
+        mw.l $SRKHR2  <SRKHR_2_32Bit_val>
+        mw.l $SRKHR3  <SRKHR_3_32Bit_val>
+        mw.l $SRKHR4  <SRKHR_4_32Bit_val>
+        mw.l $SRKHR5  <SRKHR_5_32Bit_val>
+        mw.l $SRKHR6  <SRKHR_6_32Bit_val>
+        mw.l $SRKHR7  <SRKHR_7_32Bit_val>
+
+      Note: SRK Hash should be carefully written keeping in mind the SFP Block Endianness.
+
+- At U-Boot prompt, verify that SNVS registers for OTPMK are correctly written:
+
+  --  Check for the OTPMK.
+   .. code:: shell
+
+        md $SNVS_HPSR_REG
+
+      Command Output:
+          01e90014: 80000900
+
+          OTPMK_ZERO_BIT is zero, indicating that the OTPMK is blown.
+
+          Note: In case it is read as 00000000, then read this register using jtag (in development mode only through CW tap).
+
+   .. code:: shell
+
+        md $OTPMKR0 0x10
+
+      Command Output:
+          01e80234: ffffffff ffffffff ffffffff ffffffff    ................
+          01e80244: ffffffff ffffffff ffffffff ffffffff    ................
+
+          Note: OTPMK will never be visible in plain.
+
+  --  Check for the SRK Hash. For example, if following SRK hash is written:
+
+       SFP SRKHR0 = fdc2fed4
+       SFP SRKHR1 = 317f569e
+       SFP SRKHR2 = 1828425c
+       SFP SRKHR3 = e87b5cfd
+       SFP SRKHR4 = 34beab8f
+       SFP SRKHR5 = df792a70
+       SFP SRKHR6 = 2dff85e1
+       SFP SRKHR7 = 32a29687,
+
+       then following would be the value on dumping SRK hash.
+
+   .. code:: shell
+
+        md $SRKHR0 0x10
+
+      Command Output:
+          01e80254: d4fec2fd 9e567f31 5c422818 fd5c7be8    ....1.V..(B\.{\.
+          01e80264: 8fabbe34 702a79df e185ff2d 8796a232    4....y*p-...2...
+
+          Note: SRK Hash is visible in plain based on the SFP Block Endianness.
+
+- Caution: Donot proceed to the next step, until you are sure that OTPMK and SRKH are correctly blown from above steps.
+  -- After the next step, there is no turning back.
+  -- Fuses will be burnt, which cannot be undo.
+
+- Write SFP_INGR[INST] with the PROGFB(0x2) instruction to blow the fuses.
+  -- User need to save the SRK key pair and OTPMK Key forever, to continue using this board.
+
++---+----------------------------------+-------------------------------------------+-----------+
+|   |   Platform                       | SFP_INGR_REG | SFP_WRITE_DATE_FRM_MIRROR_REG_TO_FUSE  |
++===+==================================+=======================================================+
+| 1.| lx2160ardb/lx2160aqds/lx2162aqds | 0x01E80020   |    0x2                                 |
++---+----------------------------------+--------------+----------------------------------------+
+
+   .. code:: shell
+
+        md $SFP_INGR_REG  $SFP_WRITE_DATE_FRM_MIRROR_REG_TO_FUSE
+
+- On reset, if the SFP register were read from u-boot, it will show the following:
+  --  Check for the OTPMK.
+
+   .. code:: shell
+
+        md $SNVS_HPSR_REG
+
+      Command Output:
+          01e90014: 80000900
+
+          In case it is read as 00000000, then read this register using jtag (in development mode only through CW tap).
+                       +0       +4       +8       +C
+          [0x01E90014] 80000900
+
+          Note: OTPMK_ZERO_BIT is zero, indicating that the OTPMK is blown.
+
+   .. code:: shell
+
+        md $OTPMKR0 0x10
+
+      Command Output:
+          01e80234: ffffffff ffffffff ffffffff ffffffff    ................
+          01e80244: ffffffff ffffffff ffffffff ffffffff    ................
+
+          Note: OTPMK will never be visible in plain.
+
+  -- SRK Hash
+
+   .. code:: shell
+
+        md $SRKHR0 0x10
+
+      Command Output:
+          01e80254: d4fec2fd 9e567f31 5c422818 fd5c7be8    ....1.V..(B\.{\.
+          01e80264: 8fabbe34 702a79df e185ff2d 8796a232    4....y*p-...2...
+
+          Note: SRK Hash is visible in plain based on the SFP Block Endianness.
+
+Second method to do the fuse provsioning:
+=========================================
+
+This method is used for quick way to provision fuses.
+Typically used by those who needs to provision number of boards.
+
+- Enable POVDD:
+  -- Refer the table above to enable POVDD.
+
+     Note: If GPIO Pin supports enabling POVDD, it can be done through the below input_fuse_file.
+
+  -- Once the POVDD is enabled, make sure to set variable POVDD_ENABLE := yes, in the platform.mk.
+
+- User need to populate the "input_fuse_file", corresponding to the platform for:
+
+  -- OTPMK
+  -- SRKH
+
+  Table of fuse provisioning input file for every supported platform:
+
++---+----------------------------------+-----------------------------------------------------------------+
+|   |   Platform                       |                        FUSE_PROV_FILE                           |
++===+==================================+=================================================================+
+| 1.| lx2160ardb/lx2160aqds/lx2162aqds | ${CST_DIR}/input_files/gen_fusescr/ls2088_1088/input_fuse_file  |
++---+----------------------------------+--------------+--------------------------------------------------+
+
+- Create the TF-A binary with FUSE_PROG=1.
+
+   .. code:: shell
+
+        make PLAT=$PLAT FUSE_PROG=1\
+          BOOT_MODE=<platform_supported_boot_mode> \
+          RCW=$RCW_BIN \
+          BL32=$TEE_BIN SPD=opteed\
+          BL33=$UBOOT_SECURE_BIN \
+          pbl \
+          fip \
+          fip_fuse \
+          FUSE_PROV_FILE=../../apps/security/cst/input_files/gen_fusescr/ls2088_1088/input_fuse_file
+
+- Deployment:
+  -- Refer the nxp-layerscape.rst for deploying TF-A images.
+  -- Deploying fip_fuse.bin:
+
+       For Flexspi-Nor:
+
+   .. code:: shell
+
+        tftp 82000000  $path/fuse_fip.bin;
+        i2c mw 66 50 20;sf probe 0:0; sf erase 0x880000 +$filesize; sf write 0x82000000 0x880000 $filesize;
+
+      For SD or eMMC [file_size_in_block_sizeof_512 = (Size_of_bytes_tftp / 512)]:
+
+   .. code:: shell
+
+        tftp 82000000  $path/fuse_fip.bin;
+        mmc write 82000000 0x4408 <file_size_in_block_sizeof_512>;
+
+- Valiation:
+
++---+----------------------------------+---------------------------------------------------+
+|   |   Platform                       |    Error_Register        | Error_Register_Address |
++===+==================================+===================================================+
+| 1.| lx2160ardb/lx2160aqds/lx2162aqds | DCFG scratch 4 register  |     0x01EE020C         |
++---+----------------------------------+---------------------------------------------------+
+
+   At the U-Boot prompt, check DCFG scratch 4 register for any error.
+
+   .. code:: shell
+
+        md $Error_Register_Address 1
+
+      Command Ouput:
+          01ee020c: 00000000
+
+      Note:
+       - 0x00000000 shows no error, then fuse provisioning is successful.
+       - For non-zero value, refer the code header file ".../drivers/nxp/sfp/sfp_error_codes.h"
diff --git a/docs/plat/nxp/nxp-ls-tbbr.rst b/docs/plat/nxp/nxp-ls-tbbr.rst
new file mode 100644
index 0000000..43e15f7
--- /dev/null
+++ b/docs/plat/nxp/nxp-ls-tbbr.rst
@@ -0,0 +1,210 @@
+
+--------------
+NXP Platforms:
+--------------
+TRUSTED_BOARD_BOOT option can be enabled by specifying TRUSTED_BOARD_BOOT=1 on command line during make.
+
+
+
+Bare-Minimum Preparation to run  TBBR on NXP Platforms:
+=======================================================
+- OTPMK(One Time Programable Key) needs to be burnt in fuses.
+  -- It is the 256 bit key that stores a secret value used by the NXP SEC 4.0 IP in Trusted or Secure mode.
+
+     Note: It is primarily for the purpose of decrypting additional secrets stored in system non-volatile memory.
+
+  -- NXP CST tool gives an option to generate it.
+
+   Use the below command from directory 'cst', with correct options.
+
+   .. code:: shell
+
+     ./gen_otpmk_drbg
+
+- SRKH (Super Root Key Hash) needs to be burnt in fuses.
+  -- It is the 256 bit hash of the list of the public keys of the SRK key pair.
+  -- NXP CST tool gives an option to generate the RSA key pair and its hash.
+
+   Use the below command from directory 'cst', with correct options.
+
+   .. code:: shell
+
+     ./gen_keys
+
+Refer fuse frovisioning readme 'nxp-ls-fuse-prov.rst' for steps to blow these keys.
+
+
+
+Two options are provided for TRUSTED_BOARD_BOOT:
+================================================
+
+-------------------------------------------------------------------------
+Option 1: CoT using X 509 certificates
+-------------------------------------------------------------------------
+
+- This CoT is as provided by ARM.
+
+- To use this option user needs to specify mbedtld dir path in MBEDTLS_DIR.
+
+- To generate CSF header, path of CST repository needs to be specified as CST_DIR
+
+- CSF header is embedded to each of the BL2 image.
+
+- GENERATE_COT=1 adds the tool 'cert_create' to the build environment to generate:
+  -- X509 Certificates as (.crt) files.
+  -- X509 Pem key file as (.pem) files.
+
+- SAVE_KEYS=1 saves the keys and certificates, if GENERATE_COT=1.
+  -- For this to work, file name for cert and keys are provided as part of  compilation or build command.
+
+     --- default file names will be used, incase not provided as part compilation or build command.
+     --- default folder 'BUILD_PLAT' will be used to store them.
+
+- ROTPK for x.509 certificates is generated and embedded in bl2.bin and
+  verified as part of CoT by Boot ROM during secure boot.
+
+- Compilation steps:
+
+All Images
+   .. code:: shell
+
+       make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 MBEDTLS_DIR=$MBEDTLS_PATH CST_DIR=$CST_DIR_PATH \
+       BOOT_MODE=<platform_supported_boot_mode> \
+       RCW=$RCW_BIN \
+       BL32=$TEE_BIN SPD=opteed\
+       BL33=$UBOOT_SECURE_BIN \
+       pbl \
+       fip
+
+Additional FIP_DDR Image (For NXP platforms like lx2160a)
+   .. code:: shell
+
+       make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 MBEDTLS_DIR=$MBEDTLS_PATH fip_ddr
+
+      Note: make target 'fip_ddr' should never be combine with other make target 'fip', 'pbl' & 'bl2'.
+
+-------------------------------------------------------------------------
+Option 2: CoT using NXP CSF headers.
+-------------------------------------------------------------------------
+
+- This option is automatically selected when TRUSTED_BOARD_BOOT is set but MBEDTLS_DIR path is not specified.
+
+- CSF header is embedded to each of the BL31, BL32 and  BL33 image.
+
+- To generate CSF header, path of CST repository needs to be specified as CST_DIR
+
+- Default input files for CSF header generation is added in this repo.
+
+- Default input file requires user to generate RSA key pair named
+  -- srk.pri, and
+  -- srk.pub, and add them in ATF repo.
+  -- These keys can be generated using gen_keys tool of CST.
+
+- To change the input file , user can use the options BL33_INPUT_FILE, BL32_INPUT_FILE, BL31_INPUT_FILE
+
+- There are 2 paths in secure boot flow :
+  -- Development Mode (sb_en in RCW = 1, SFP->OSPR, ITS = 0)
+
+     --- In this flow , even on ROTPK comparison failure, flow would continue.
+     --- However SNVS is transitioned to non-secure state
+
+  -- Production mode (SFP->OSPR, ITS = 1)
+
+     --- Any failure is fatal failure
+
+- Compilation steps:
+
+All Images
+   .. code:: shell
+
+       make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 CST_DIR=$CST_DIR_PATH \
+       BOOT_MODE=<platform_supported_boot_mode> \
+       RCW=$RCW_BIN \
+       BL32=$TEE_BIN SPD=opteed\
+       BL33=$UBOOT_SECURE_BIN \
+       pbl \
+       fip
+
+Additional FIP_DDR Image (For NXP platforms like lx2160a)
+   .. code:: shell
+
+       make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 CST_DIR=$CST_DIR_PATH fip_ddr
+
+- Compilation Steps with build option for generic image processing filters to prepend CSF header:
+  --  Generic image processing filters to prepend CSF header
+
+      BL32_INPUT_FILE = < file name>
+      BL33_INPUT_FILE = <file name>
+
+   .. code:: shell
+
+       make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 CST_DIR=$CST_DIR_PATH \
+       BOOT_MODE=<platform_supported_boot_mode> \
+       RCW=$RCW_BIN \
+       BL32=$TEE_BIN SPD=opteed\
+       BL33=$UBOOT_SECURE_BIN \
+       BL33_INPUT_FILE = <ip file> \
+       BL32_INPUT_FILE = <ip_file> \
+       BL31_INPUT_FILE = <ip file> \
+       pbl \
+       fip
+
+
+Deploy ATF Images
+=================
+Same steps as mentioned in the readme "nxp-layerscape.rst".
+
+
+
+Verification to check if Secure state is achieved:
+==================================================
+
++---+----------------+-----------------+------------------------+----------------------------------+-------------------------------+
+|   |   Platform     |  SNVS_HPSR_REG  | SYS_SECURE_BIT(=value) | SYSTEM_SECURE_CONFIG_BIT(=value) | SSM_STATE                     |
++===+================+=================+========================+==================================+===============================+
+| 1.| lx2160ardb  or |    0x01E90014   | 15                     | 14-12                            | 11-8                          |
+|   | lx2160aqds  or |                 | ( = 1, BootROM Booted) | ( = 010 means Intent to Secure,  | (=1111 means secure boot)     |
+|   | lx2162aqds     |                 |                        | ( = 000 Unsecure)                | (=1011 means Non-secure Boot) |
++---+----------------+-----------------+------------------------+----------------------------------+-------------------------------+
+
+- Production mode (SFP->OSPR, ITS = 1)
+  -- Linux prompt will successfully come. if the TBBR is successful.
+
+     --- Else, Linux boot will be successful.
+
+  -- For secure-boot status, read SNVS Register $SNVS_HPSR_REG from u-boot prompt:
+
+   .. code:: shell
+
+        md $SNVS_HPSR_REG
+
+      Command Output:
+          1e90014: 8000AF00
+
+          In case it is read as 00000000, then read this register using jtag (in development mode only through CW tap).
+                       +0       +4       +8       +C
+          [0x01E90014] 8000AF00
+
+
+- Development Mode (sb_en in RCW = 1, SFP->OSPR, ITS = 0)
+  -- Refer the SoC specific table to read the register to interpret whether the secure boot is achieved or not.
+  -- Using JTAG (in development environment only, using CW tap):
+
+     --- For secure-boot status, read SNVS Register $SNVS_HPSR_REG
+
+   .. code:: shell
+
+        ccs::display_regs 86 0x01E90014 4 0 1
+
+      Command Output:
+          Using the SAP chain position number 86, following is the output.
+
+                       +0       +4       +8       +C
+          [0x01E90014] 8000AF00
+
+          Note: Chain position number will vary from one SoC to other SoC.
+
+- Interpretation of the value:
+
+  -- 0xA indicates BootROM booted, with intent to secure.
+  -- 0xF = secure boot, as SSM_STATE.
diff --git a/docs/plat/stm32mp1.rst b/docs/plat/stm32mp1.rst
index 0ef2923..17f7a86 100644
--- a/docs/plat/stm32mp1.rst
+++ b/docs/plat/stm32mp1.rst
@@ -37,6 +37,17 @@
 for ROM code is able to load this image.
 Tool stm32image can be used to prepend this header to the generated TF-A binary.
 
+Boot with FIP
+~~~~~~~~~~~~~
+The use of FIP is now the recommended way to boot STM32MP1 platform.
+Only BL2 (with STM32 header) is loaded by ROM code. The other binaries are
+inside the FIP binary: BL32 (SP_min or OP-TEE), U-Boot and their respective
+device tree blobs.
+
+STM32IMAGE bootchain
+~~~~~~~~~~~~~~~~~~~~
+Although still supported, this way of booting is not recommended.
+Pease use FIP instead.
 At compilation step, BL2, BL32 and DTB file are linked together in a single
 binary. The stm32image tool is also generated and the header is added to TF-A
 binary. This binary file with header is named tf-a-stm32mp157c-ev1.stm32.
@@ -55,15 +66,17 @@
                |       ...       |
                |                 |
     0x2FFC0000 +-----------------+ \
-               |                 | |
+               |     BL32 DTB    | |
+    0x2FFC5000 +-----------------+ |
+               |       BL32      | |
+    0x2FFDF000 +-----------------+ |
                |       ...       | |
-               |                 | |
-    0x2FFD8000 +-----------------+ |
-               |    TF-A DTB     | | Embedded SRAM
-    0x2FFDC000 +-----------------+ |
+    0x2FFE3000 +-----------------+ |
+               |     BL2 DTB     | | Embedded SRAM
+    0x2FFEA000 +-----------------+ |
                |       BL2       | |
-    0x2FFEF000 +-----------------+ |
-               |       BL32      | |
+    0x2FFFF000 +-----------------+ |
+               |  SCMI mailbox   | |
     0x30000000 +-----------------+ /
                |                 |
                |       ...       |
@@ -102,23 +115,110 @@
 - ``STM32MP_SPI_NAND``
 - ``STM32MP_SPI_NOR``
 
-To build with SP_min and support for all bootable devices:
+Boot with FIP
+~~~~~~~~~~~~~
+You need to build BL2, BL32 (SP_min or OP-TEE) and BL33 (U-Boot) before building FIP binary.
+
+U-Boot
+______
 
 .. code:: bash
 
-    make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=sp_min STM32MP_SDMMC=1 STM32MP_EMMC=1 STM32MP_RAW_NAND=1 STM32MP_SPI_NAND=1
-    STM32MP_SPI_NOR=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb
     cd <u-boot_directory>
     make stm32mp15_trusted_defconfig
     make DEVICE_TREE=stm32mp157c-ev1 all
 
-To build TF-A with OP-TEE support for all bootable devices:
+OP-TEE (optional)
+_________________
 
 .. code:: bash
 
-    make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=optee STM32MP_SDMMC=1 STM32MP_EMMC=1 STM32MP_RAW_NAND=1 STM32MP_SPI_NAND=1 STM32MP_SPI_NOR=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb
     cd <optee_directory>
-    make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm PLATFORM=stm32mp1 CFG_EMBED_DTB_SOURCE_FILE=stm32mp157c-ev1.dts
+    make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm PLATFORM=stm32mp1 \
+        CFG_EMBED_DTB_SOURCE_FILE=stm32mp157c-ev1.dts
+
+
+TF-A BL32 (SP_min)
+__________________
+If you choose not to use OP-TEE, you can use TF-A SP_min.
+To build TF-A BL32, and its device tree file:
+
+.. code:: bash
+
+    make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \
+        AARCH32_SP=sp_min DTB_FILE_NAME=stm32mp157c-ev1.dtb bl32 dtbs
+
+TF-A BL2
+________
+To build TF-A BL2 with its STM32 header for SD-card boot:
+
+.. code:: bash
+
+    make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \
+        DTB_FILE_NAME=stm32mp157c-ev1.dtb STM32MP_SDMMC=1
+
+For other boot devices, you have to replace STM32MP_SDMMC in the previous command
+with the desired device flag.
+
+This BL2 is independent of the BL32 used (SP_min or OP-TEE)
+
+
+FIP
+___
+With BL32 SP_min:
+
+.. code:: bash
+
+    make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \
+        AARCH32_SP=sp_min \
+        DTB_FILE_NAME=stm32mp157c-ev1.dtb \
+        BL33=<u-boot_directory>/u-boot-nodtb.bin \
+        BL33_CFG=<u-boot_directory>/u-boot.dtb \
+        fip
+
+With OP-TEE:
+
+.. code:: bash
+
+    make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \
+        DTB_FILE_NAME=stm32mp157c-ev1.dtb \
+        BL33=<u-boot_directory>/u-boot-nodtb.bin \
+        BL33_CFG=<u-boot_directory>/u-boot.dtb \
+        BL32=<optee_directory>/tee-header_v2.bin \
+        BL32_EXTRA1=<optee_directory>/tee-pager_v2.bin
+        BL32_EXTRA2=<optee_directory>/tee-pageable_v2.bin
+        fip
+
+
+STM32IMAGE bootchain
+~~~~~~~~~~~~~~~~~~~~
+You need to add the following flag to the make command:
+``STM32MP_USE_STM32IMAGE=1``
+
+To build with SP_min and support for SD-card boot:
+
+.. code:: bash
+
+    make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \
+        AARCH32_SP=sp_min STM32MP_SDMMC=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb \
+        STM32MP_USE_STM32IMAGE=1
+
+    cd <u-boot_directory>
+    make stm32mp15_trusted_defconfig
+    make DEVICE_TREE=stm32mp157c-ev1 all
+
+To build TF-A with OP-TEE support for SD-card boot:
+
+.. code:: bash
+
+    make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \
+        AARCH32_SP=optee STM32MP_SDMMC=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb \
+        STM32MP_USE_STM32IMAGE=1
+
+    cd <optee_directory>
+    make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm PLATFORM=stm32mp1 \
+        CFG_EMBED_DTB_SOURCE_FILE=stm32mp157c-ev1.dts
+
     cd <u-boot_directory>
     make stm32mp15_trusted_defconfig
     make DEVICE_TREE=stm32mp157c-ev1 all
@@ -132,7 +232,19 @@
 Populate SD-card
 ----------------
 
+Boot with FIP
+~~~~~~~~~~~~~
+The SD-card has to be formatted with GPT.
+It should contain at least those partitions:
+
+- fsbl: to copy the tf-a-stm32mp157c-ev1.stm32 binary (BL2)
+- fip: which contains the FIP binary
+
+Usually, two copies of fsbl are used (fsbl1 and fsbl2) instead of one partition fsbl.
+
-The SD-card has to be formated with GPT.
+STM32IMAGE bootchain
+~~~~~~~~~~~~~~~~~~~~
+The SD-card has to be formatted with GPT.
 It should contain at least those partitions:
 
 - fsbl: to copy the tf-a-stm32mp157c-ev1.stm32 binary
diff --git a/docs/plat/xilinx-versal.rst b/docs/plat/xilinx-versal.rst
index 3d4c4a4..d65b048 100644
--- a/docs/plat/xilinx-versal.rst
+++ b/docs/plat/xilinx-versal.rst
@@ -24,6 +24,11 @@
 make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal bl31 VERSAL_CONSOLE=dcc
 ```
 
+To build TF-A with Straight-Line Speculation(SLS)
+```bash
+make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal bl31 HARDEN_SLS_ALL=1
+```
+
 Xilinx Versal platform specific build options
 ---------------------------------------------
 
diff --git a/docs/process/contributing.rst b/docs/process/contributing.rst
index c91903a..aa050da 100644
--- a/docs/process/contributing.rst
+++ b/docs/process/contributing.rst
@@ -209,6 +209,65 @@
       revert your patches and ask you to resubmit a reworked version of them or
       they may ask you to provide a fix-up patch.
 
+Add Build Configurations
+------------------------
+
+-  TF-A uses Jenkins tool for Continuous Integration and testing activities.
+   Various CI Jobs are deployed which run tests on every patch before being
+   merged. So each of your patches go through a series of checks before they
+   get merged on to the master branch.
+
+-  ``Coverity Scan analysis`` is one of the tests we perform on our source code
+   at regular intervals. We maintain a build script ``tf-cov-make`` which contains the
+   build configurations of various platforms in order to cover the entire source
+   code being analysed by Coverity.
+
+-  When you submit your patches for review containing new source files, please
+   ensure to include them for the ``Coverity Scan analysis`` by adding the
+   respective build configurations in the ``tf-cov-make`` build script.
+
+-  In this section you find the details on how to append your new build
+   configurations for Coverity Scan analysis:
+
+#. We maintain a separate repository named `tf-a-ci-scripts repository`_
+   for placing all the test scripts which will be executed by the CI Jobs.
+
+#. In this repository, ``tf-cov-make`` script is located at
+   ``tf-a-ci-scripts/script/tf-coverity/tf-cov-make``
+
+#. Edit `tf-cov-make`_ script by appending all the possible build configurations with
+   the specific ``build-flags`` relevant to your platform, so that newly added
+   source files get built and analysed by Coverity.
+
+#. For better understanding follow the below specified examples listed in the
+   ``tf-cov-make`` script.
+
+.. code:: shell
+
+    Example 1:
+    #Intel
+    make PLAT=stratix10 $(common_flags) all
+    make PLAT=agilex $(common_flags) all
+
+-  In the above example there are two different SoCs ``stratix`` and ``agilex``
+   under the Intel platform and the build configurations has been added suitably
+   to include most of their source files.
+
+.. code:: shell
+
+    Example 2:
+    #Hikey
+    make PLAT=hikey $(common_flags) ${TBB_OPTIONS} ENABLE_PMF=1 all
+    make PLAT=hikey960 $(common_flags) ${TBB_OPTIONS} all
+    make PLAT=poplar $(common_flags) all
+
+-  In this case for ``Hikey`` boards additional ``build-flags`` has been included
+   along with the ``commom_flags`` to cover most of the files relevant to it.
+
+-  Similar to this you can still find many other different build configurations
+   of various other platforms listed in the ``tf-cov-make`` script. Kindly refer
+   them and append your build configurations respectively.
+
 Binary Components
 -----------------
 
@@ -228,7 +287,7 @@
 
 --------------
 
-*Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.*
 
 .. _Conventional Commits: https://www.conventionalcommits.org/en/v1.0.0
 .. _developer.trustedfirmware.org: https://developer.trustedfirmware.org
@@ -243,3 +302,5 @@
 .. _Trusted Firmware binary repository: https://review.trustedfirmware.org/admin/repos/tf-binaries
 .. _tf-binaries-readme: https://git.trustedfirmware.org/tf-binaries.git/tree/readme.rst
 .. _TF-A mailing list: https://lists.trustedfirmware.org/mailman/listinfo/tf-a
+.. _tf-a-ci-scripts repository: https://git.trustedfirmware.org/ci/tf-a-ci-scripts.git/
+.. _tf-cov-make: https://git.trustedfirmware.org/ci/tf-a-ci-scripts.git/tree/script/tf-coverity/tf-cov-make
diff --git a/docs/resources/diagrams/plantuml/spm_dfd.puml b/docs/resources/diagrams/plantuml/spm_dfd.puml
new file mode 100644
index 0000000..ad4996e
--- /dev/null
+++ b/docs/resources/diagrams/plantuml/spm_dfd.puml
@@ -0,0 +1,82 @@
+/'
+ ' Copyright (c) 2021, Arm Limited. All rights reserved.
+ '
+ ' SPDX-License-Identifier: BSD-3-Clause
+ '/
+
+/'
+TF-A SPMC Data Flow Diagram
+'/
+
+@startuml
+digraph tfa_dfd {
+
+    # Allow arrows to end on cluster boundaries
+    compound=true
+
+    # Default settings for edges and nodes
+    edge [minlen=2 color="#8c1b07"]
+    node [fillcolor="#ffb866" style=filled shape=box fixedsize=true width=1.6 height=0.7]
+
+    # Nodes outside of the trust boundary
+    nsec [label="NS Client"]
+    ddr  [label="External memory (DDR)"]
+
+    # Trust boundary cluster
+    subgraph cluster_trusted {
+        graph [style=dashed color="#f22430"]
+
+        # HW IPs cluster
+        subgraph cluster_ip {
+            label ="Hardware IPs";
+            graph [style=filled color="#000000" fillcolor="#ffd29e"]
+
+            rank="same"
+            gic [label="GIC" width=1.2 height=0.5]
+            smmu [label="SMMU" width=1.2 height=0.5]
+            uart [label="UART" width=1.2 height=0.5]
+	    pe [label="PE" width=1.2 height=0.5]
+        }
+
+        # TF-A cluster
+        subgraph cluster_tfa {
+            label ="EL3 monitor";
+            graph [style=filled color="#000000" fillcolor="#faf9cd"]
+
+            bl31 [label="BL31" fillcolor="#ddffb3"];
+            spmd [label="SPMD" fillcolor="#ddffb3" height=1]
+        }
+
+        # SPMC cluster
+        subgraph cluster_spmc {
+            label ="SPMC";
+            graph [style=filled color="#000000" fillcolor="#faf9cd"]
+
+            spmc [label="SPMC" fillcolor="#ddffb3" height=1]
+        }
+	bl2 [label="BL2" width=1.2 height=0.5]
+    }
+
+    # Secure Partitions cluster
+    subgraph cluster_sp {
+        label ="Secure Partitions";
+        graph [style=filled color="#000000" fillcolor="#faf9cd"]
+
+        sp1 [label="SP1" fillcolor="#ddffb3" height=1]
+        sp2 [label="SP2" fillcolor="#ddffb3" height=1]
+        spn [label="SP..." fillcolor="#ddffb3" height=1]
+    }
+
+    # Interactions between nodes
+    sp1 -> spmc [dir="both" label="DF1"]
+    spmc -> spmd [dir="both" label="DF2"]
+    spmd -> nsec [dir="both" label="DF3"]
+    sp1 -> sp2 [dir="both" label="DF4"]
+    spmc -> smmu [lhead=cluster_spmc label="DF5"]
+    bl2 -> spmc [lhead=cluster_spmc label="DF6"]
+    bl2 -> spn [lhead=cluster_spmc label="DF6"]
+    sp1 -> ddr [dir="both"  label="DF7"]
+    spmc -> ddr [dir="both"  label="DF7"]
+}
+
+@enduml
diff --git a/docs/resources/diagrams/spm-threat-model-trust-boundaries.png b/docs/resources/diagrams/spm-threat-model-trust-boundaries.png
new file mode 100644
index 0000000..58898c5
--- /dev/null
+++ b/docs/resources/diagrams/spm-threat-model-trust-boundaries.png
Binary files differ
diff --git a/docs/threat_model/index.rst b/docs/threat_model/index.rst
index e8f09b9..b5ede69 100644
--- a/docs/threat_model/index.rst
+++ b/docs/threat_model/index.rst
@@ -1,5 +1,12 @@
 Threat Model
-=============
+============
+
+Threat modeling is an important part of Secure Development Lifecycle (SDL)
+that helps us identify potential threats and mitigations affecting a system.
+
+In the next sections, we first give a description of the target of evaluation
+using a data flow diagram. Then we provide a list of threats we have identified
+based on the data flow diagram and potential threat mitigations.
 
 .. toctree::
    :maxdepth: 1
@@ -7,6 +14,7 @@
    :numbered:
 
    threat_model
+   threat_model_spm
 
 --------------
 
diff --git a/docs/threat_model/threat_model.rst b/docs/threat_model/threat_model.rst
index 9cee104..9f26487 100644
--- a/docs/threat_model/threat_model.rst
+++ b/docs/threat_model/threat_model.rst
@@ -1,13 +1,10 @@
-*****************
-Introduction
-*****************
-Threat modeling is an important part of Secure Development Lifecycle (SDL)
-that helps us identify potential threats and mitigations affecting a system.
+Generic threat model
+********************
 
-This document provides a generic threat model for TF-A firmware. In the
-next sections, we first give a description of the target of evaluation
-using a data flow diagram. Then we provide a list of threats we have
-identified based on the data flow diagram and potential threat mitigations.
+************************
+Introduction
+************************
+This document provides a generic threat model for TF-A firmware.
 
 ************************
 Target of Evaluation
@@ -781,4 +778,4 @@
 .. _Trusted Board Boot (TBB): https://trustedfirmware-a.readthedocs.io/en/latest/design/trusted-board-boot.html
 .. _TF-A error handling policy: https://trustedfirmware-a.readthedocs.io/en/latest/process/coding-guidelines.html#error-handling-and-robustness
 .. _Secure Development Guidelines: https://trustedfirmware-a.readthedocs.io/en/latest/process/security-hardening.html#secure-development-guidelines
-.. _Trusted Firmware-A Tests: https://git.trustedfirmware.org/TF-A/tf-a-tests.git/about/
\ No newline at end of file
+.. _Trusted Firmware-A Tests: https://git.trustedfirmware.org/TF-A/tf-a-tests.git/about/
diff --git a/docs/threat_model/threat_model_spm.rst b/docs/threat_model/threat_model_spm.rst
new file mode 100644
index 0000000..96d33a2
--- /dev/null
+++ b/docs/threat_model/threat_model_spm.rst
@@ -0,0 +1,617 @@
+SPMC threat model
+*****************
+
+************************
+Introduction
+************************
+This document provides a threat model for the TF-A `Secure Partition Manager`_
+(SPM) implementation or more generally the S-EL2 reference firmware running on
+systems implementing the FEAT_SEL2 (formerly Armv8.4 Secure EL2) architecture
+extension. The SPM implementation is based on the `Arm Firmware Framework for
+Armv8-A`_ specification.
+
+In brief, the broad FF-A specification and S-EL2 firmware implementation
+provide:
+
+- Isolation of mutually mistrusting SW components, or endpoints in the FF-A
+  terminology.
+- Distinct sandboxes in the secure world called secure partitions. This permits
+  isolation of services from multiple vendors.
+- A standard protocol for communication and memory sharing between FF-A
+  endpoints.
+- Mutual isolation of the normal world and the secure world (e.g. a Trusted OS
+  is prevented to map an arbitrary NS physical memory region such as the kernel
+  or the Hypervisor).
+
+************************
+Target of Evaluation
+************************
+In this threat model, the target of evaluation is the S-EL2 firmware or the
+``Secure Partition Manager Core`` component (SPMC).
+The monitor and SPMD at EL3 are covered by the `Generic TF-A threat model`_.
+
+The scope for this threat model is:
+
+- The TF-A implementation for the S-EL2 SPMC based on the Hafnium hypervisor
+  running in the secure world of TrustZone (at S-EL2 exception level).
+  The threat model is not related to the normal world Hypervisor or VMs.
+  The S-EL1 SPMC solution is not covered.
+- The implementation complies with the FF-A v1.0 specification.
+- Secure partitions are statically provisioned at boot time.
+- Focus on the run-time part of the life-cycle (no specific emphasis on boot
+  time, factory firmware provisioning, firmware udpate etc.)
+- Not covering advanced or invasive physical attacks such as decapsulation,
+  FIB etc.
+- Assumes secure boot or in particular TF-A trusted boot (TBBR or dual CoT) is
+  enabled. An attacker cannot boot arbitrary images that are not approved by the
+  SiP or platform providers.
+
+Data Flow Diagram
+======================
+Figure 1 shows a high-level data flow diagram for the SPM split into an SPMD
+component at EL3 and an SPMC component at S-EL2. The SPMD mostly acts as a
+relayer/pass-through between the normal world and the secure world. It is
+assumed to expose small attack surface.
+
+A description of each diagram element is given in Table 1. In the diagram, the
+red broken lines indicate trust boundaries.
+
+Components outside of the broken lines are considered untrusted.
+
+.. uml:: ../resources/diagrams/plantuml/spm_dfd.puml
+  :caption: Figure 1: SPMC Data Flow Diagram
+
+.. table:: Table 1: SPMC Data Flow Diagram Description
+
+  +---------------------+--------------------------------------------------------+
+  | Diagram Element     | Description                                            |
+  +=====================+========================================================+
+  | ``DF1``             | SP to SPMC communication. FF-A function invocation or  |
+  |                     | implementation-defined Hypervisor call.                |
+  +---------------------+--------------------------------------------------------+
+  | ``DF2``             | SPMC to SPMD FF-A call.                                |
+  +---------------------+--------------------------------------------------------+
+  | ``DF3``             | SPMD to NS forwarding.                                 |
+  +---------------------+--------------------------------------------------------+
+  | ``DF4``             | SP to SP FF-A direct message request/response.         |
+  |                     | Note as a matter of simplifying the diagram            |
+  |                     | the SP to SP communication happens through the SPMC    |
+  |                     | (SP1 performs a direct message request to the          |
+  |                     | SPMC targeting SP2 as destination. And similarly for   |
+  |                     | the direct message response from SP2 to SP1).          |
+  +---------------------+--------------------------------------------------------+
+  | ``DF5``             | HW control.                                            |
+  +---------------------+--------------------------------------------------------+
+  | ``DF6``             | Bootloader image loading.                              |
+  +---------------------+--------------------------------------------------------+
+  | ``DF7``             | External memory access.                                |
+  +---------------------+--------------------------------------------------------+
+
+*********************
+Threat Analysis
+*********************
+
+This threat model follows a similar methodology to the `Generic TF-A threat model`_.
+The following sections define:
+
+- Trust boundaries
+- Assets
+- Theat agents
+- Threat types
+
+Trust boundaries
+============================
+
+- Normal world is untrusted.
+- Secure world and normal world are separate trust boundaries.
+- EL3 monitor, SPMD and SPMC are trusted.
+- Bootloaders (in particular BL1/BL2 if using TF-A) and run-time BL31 are
+  implicitely trusted by the usage of secure boot.
+- EL3 monitor, SPMD, SPMC do not trust SPs.
+
+.. figure:: ../resources/diagrams/spm-threat-model-trust-boundaries.png
+
+    Figure 2: Trust boundaries
+
+Assets
+============================
+
+The following assets are identified:
+
+- SPMC state.
+- SP state.
+- Information exchange between endpoints (partition messages).
+- SPMC secrets (e.g. pointer authentication key when enabled)
+- SP secrets (e.g. application keys).
+- Scheduling cycles.
+- Shared memory.
+
+Threat Agents
+============================
+
+The following threat agents are identified:
+
+- NS-Endpoint identifies a non-secure endpoint: normal world client at NS-EL2
+  (Hypervisor) or NS-EL1 (VM or OS kernel).
+- S-Endpoint identifies a secure endpoint typically a secure partition.
+- Hardware attacks (non-invasive) requiring a physical access to the device,
+  such as bus probing or DRAM stress.
+
+Threat types
+============================
+
+The following threat categories as exposed in the `Generic TF-A threat model`_
+are re-used:
+
+- Spoofing
+- Tampering
+- Repudiation
+- Information disclosure
+- Denial of service
+- Elevation of privileges
+
+Similarly this threat model re-uses the same threat risk ratings. The risk
+analysis is evaluated based on the environment being ``Server`` or ``Mobile``.
+
+Threat Assessment
+============================
+
+The following threats are identified by applying STRIDE analysis on each diagram
+element of the data flow diagram.
+
++------------------------+----------------------------------------------------+
+| ID                     | 01                                                 |
++========================+====================================================+
+| ``Threat``             | **An endpoint impersonates the sender or receiver  |
+|                        | FF-A ID in a direct request/response invocation.** |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF1, DF2, DF3, DF4                                 |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMD, SPMC                                         |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | SP state                                           |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | NS-Endpoint, S-Endpoint                            |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Spoofing                                           |
++------------------------+------------------+-----------------+---------------+
+| ``Application``        |   ``Server``     |   ``Mobile``    |               |
++------------------------+------------------++----------------+---------------+
+| ``Impact``             | Critical(5)      | Critical(5)     |               |
++------------------------+------------------++----------------+---------------+
+| ``Likelihood``         | Critical(5)      | Critical(5)     |               |
++------------------------+------------------++----------------+---------------+
+| ``Total Risk Rating``  | Critical(25)     | Critical(25)    |               |
++------------------------+------------------+-----------------+---------------+
+| ``Mitigations``        | The TF-A SPMC does not mitigate this threat.       |
+|                        | The guidance below is left for a system integrator |
+|                        | to implemented as necessary.                       |
+|                        | The SPMC must enforce checks in the direct message |
+|                        | request/response interfaces such an endpoint cannot|
+|                        | spoof the origin and destination worlds (e.g. a NWd|
+|                        | originated message directed to the SWd cannot use a|
+|                        | SWd ID as the sender ID).                          |
+|                        | Additionally a software component residing in the  |
+|                        | SPMC can be added for the purpose of direct        |
+|                        | request/response filtering.                        |
+|                        | It can be configured with the list of known IDs    |
+|                        | and about which interaction can occur between one  |
+|                        | and another endpoint (e.g. which NWd endpoint ID   |
+|                        | sends a direct request to which SWd endpoint ID).  |
+|                        | This component checks the sender/receiver fields   |
+|                        | for a legitimate communication between endpoints.  |
+|                        | A similar component can exist in the OS kernel     |
+|                        | driver, or Hypervisor although it remains untrusted|
+|                        | by the SPMD/SPMC.                                  |
++------------------------+----------------------------------------------------+
+
++------------------------+----------------------------------------------------+
+| ID                     | 02                                                 |
++========================+====================================================+
+| ``Threat``             | **Tampering with memory shared between an endpoint |
+|                        | and the SPMC.**                                    |
+|                        | A malicious endpoint may attempt tampering with its|
+|                        | RX/TX buffer contents while the SPMC is processing |
+|                        | it (TOCTOU).                                       |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF1, DF3, DF4, DF7                                 |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMC                                               |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | Shared memory, Information exchange                |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | NS-Endpoint, S-Endpoint                            |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Tampering                                          |
++------------------------+------------------+-----------------+---------------+
+| ``Application``        |   ``Server``     |   ``Mobile``    |               |
++------------------------+------------------+-----------------+---------------+
+| ``Impact``             | High (4)         | High (4)        |               |
++------------------------+------------------+-----------------+---------------+
+| ``Likelihood``         | High (4)         | High (4)        |               |
++------------------------+------------------+-----------------+---------------+
+| ``Total Risk Rating``  | High (16)        | High (16)       |               |
++------------------------+------------------+-----------------+---------------+
+| ``Mitigations``        | In context of FF-A v1.0 this is the case of sharing|
+|                        | the RX/TX buffer pair and usage in the             |
+|                        | PARTITION_INFO_GET or mem sharing primitives.      |
+|                        | The SPMC must copy the contents of the TX buffer   |
+|                        | to an internal temporary buffer before processing  |
+|                        | its contents. The SPMC must implement hardened     |
+|                        | input validation on data transmitted through the TX|
+|                        | buffer by an untrusted endpoint.                   |
+|                        | The TF-A SPMC mitigates this threat by enforcing   |
+|                        | checks on data transmitted through RX/TX buffers.  |
++------------------------+----------------------------------------------------+
+
++------------------------+----------------------------------------------------+
+| ID                     | 03                                                 |
++========================+====================================================+
+| ``Threat``             | **An endpoint may tamper with its own state or the |
+|                        | state of another endpoint.**                       |
+|                        | A malicious endpoint may attempt violating:        |
+|                        | - its own or another SP state by using an unusual  |
+|                        | combination (or out-of-order) FF-A function        |
+|                        | invocations.                                       |
+|                        | This can also be an endpoint emitting              |
+|                        | FF-A function invocations to another endpoint while|
+|                        | the latter in not in a state to receive it (e.g. a |
+|                        | SP sends a direct request to the normal world early|
+|                        | while the normal world is not booted yet).         |
+|                        | - the SPMC state itself by employing unexpected    |
+|                        | transitions in FF-A memory sharing, direct requests|
+|                        | and responses, or handling of interrupts.          |
+|                        | This can be led by random stimuli injection or     |
+|                        | fuzzing.                                           |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF1, DF2, DF3, DF4                                 |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMD, SPMC                                         |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | SP state, SPMC state                               |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | NS-Endpoint, S-Endpoint                            |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Tampering                                          |
++------------------------+------------------+-----------------+---------------+
+| ``Application``        |   ``Server``     |   ``Mobile``    |               |
++------------------------+------------------+-----------------+---------------+
+| ``Impact``             | High (4)         | High (4)        |               |
++------------------------+------------------+-----------------+---------------+
+| ``Likelihood``         | Medium (3)       | Medium (3)      |               |
++------------------------+------------------+-----------------+---------------+
+| ``Total Risk Rating``  | High (12)        | High (12)       |               |
++------------------------+------------------+-----------------+---------------+
+| ``Mitigations``        | The SPMC may be vulnerable to invalid state        |
+|                        | transitions for itself or while handling an SP     |
+|                        | state. The FF-A v1.1 specification provides a      |
+|                        | guidance on those state transitions (run-time      |
+|                        | model). The TF-A SPMC will be hardened in future   |
+|                        | releases to follow this guidance.                  |
+|                        | Additionally The TF-A SPMC mitigates the threat by |
+|                        | runs of the Arm `FF-A ACS`_ compliance test suite. |
++------------------------+----------------------------------------------------+
+
++------------------------+----------------------------------------------------+
+| ID                     | 04                                                 |
++========================+====================================================+
+| ``Threat``             | *An attacker may attempt injecting errors by the   |
+|                        | use of external DRAM stress techniques.**          |
+|                        | A malicious agent may attempt toggling an SP       |
+|                        | Stage-2 MMU descriptor bit within the page tables  |
+|                        | that the SPMC manages. This can happen in Rowhammer|
+|                        | types of attack.                                   |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF7                                                |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMC                                               |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | SP or SPMC state                                   |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | Hardware attack                                    |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Tampering                                          |
++------------------------+------------------+---------------+-----------------+
+| ``Application``        |   ``Server``     |  ``Mobile``   |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Impact``             | High (4)         | High (4)	    |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Likelihood``         | Low (2)          | Medium (3)    |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Total Risk Rating``  | Medium (8)       | High (12)	    |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Mitigations``        | The TF-A SPMC does not provide mitigations to this |
+|                        | type of attack. It can be addressed by the use of  |
+|                        | dedicated HW circuity or hardening at the chipset  |
+|                        | or platform level left to the integrator.          |
++------------------------+----------------------------------------------------+
+
++------------------------+----------------------------------------------------+
+| ID                     | 05                                                 |
++========================+====================================================+
+| ``Threat``             | **Protection of the SPMC from a DMA capable device |
+|                        | upstream to an SMMU.**                             |
+|                        | A device may attempt to tamper with the internal   |
+|                        | SPMC code/data sections.                           |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF5                                                |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMC                                               |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | SPMC or SP state                                   |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | NS-Endpoint, S-Endpoint                            |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Tampering, Elevation of privileges                 |
++------------------------+------------------+---------------+-----------------+
+| ``Application``        |   ``Server``     |  ``Mobile``   |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Impact``             | High (4)         | High (4)      |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Likelihood``         | Medium (3)       | Medium (3)    |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Total Risk Rating``  | High (12)        | High (12)     |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Mitigations``        | A platform may prefer assigning boot time,         |
+|                        | statically alocated memory regions through the SMMU|
+|                        | configuration and page tables. The FF-A v1.1       |
+|                        | specification provisions this capability through   |
+|                        | static DMA isolation.                              |
+|                        | The TF-A SPMC does not mitigate this threat.       |
+|                        | It will adopt the static DMA isolation approach in |
+|                        | a future release.                                  |
++------------------------+----------------------------------------------------+
+
++------------------------+----------------------------------------------------+
+| ID                     | 06                                                 |
++========================+====================================================+
+| ``Threat``             | **Replay fragments of past communication between   |
+|                        | endpoints.**                                       |
+|                        | A malicious endpoint may replay a message exchange |
+|                        | that occured between two legitimate endpoint as    |
+|                        | a matter of triggering a malfunction or extracting |
+|                        | secrets from the receiving endpoint. In particular |
+|                        | the memory sharing operation with fragmented       |
+|                        | messages between an endpoint and the SPMC may be   |
+|                        | replayed by a malicious agent as a matter of       |
+|                        | getting access or gaining permissions to a memory  |
+|                        | region which does not belong to this agent.        |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF2, DF3                                           |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMC                                               |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | Information exchange                               |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | NS-Endpoint, S-Endpoint                            |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Repdudiation                                       |
++------------------------+------------------+---------------+-----------------+
+| ``Application``        |   ``Server``     |  ``Mobile``   |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Impact``             | Medium (3)       | Medium (3)    |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Likelihood``         | High (4)         | High (4)	    |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Total Risk Rating``  | High (12)        | High (12)     |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Mitigations``        | The TF-A SPMC does not mitigate this threat.       |
++------------------------+----------------------------------------------------+
+
++------------------------+----------------------------------------------------+
+| ID                     | 07                                                 |
++========================+====================================================+
+| ``Threat``             | **A malicious endpoint may attempt to extract data |
+|                        | or state information by the use of invalid or      |
+|                        | incorrect input arguments.**                       |
+|                        | Lack of input parameter validation or side effects |
+|                        | of maliciously forged input parameters might affect|
+|                        | the SPMC.                                          |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF1, DF2, DF3, DF4                                 |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMD, SPMC                                         |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | SP secrets, SPMC secrets, SP state, SPMC state     |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | NS-Endpoint, S-Endpoint                            |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Information discolure                              |
++------------------------+------------------+---------------+-----------------+
+| ``Application``        |   ``Server``     |  ``Mobile``   |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Impact``             | High (4)         | High (4)      |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Likelihood``         | Medium (3)       | Medium (3)    |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Total Risk Rating``  | High (12)        | High (12)     |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Mitigations``        | Secure Partitions must follow security standards   |
+|                        | and best practises as a way to mitigate the risk   |
+|                        | of common vulnerabilities to be exploited.         |
+|                        | The use of software (canaries) or hardware         |
+|                        | hardening techniques (XN, WXN, BTI, pointer        |
+|                        | authentication, MTE) helps detecting and stopping  |
+|                        | an exploitation early.                             |
+|                        | The TF-A SPMC mitigates this threat by implementing|
+|                        | stack protector, pointer authentication, BTI, XN,  |
+|                        | WXN, security hardening techniques.                |
++------------------------+----------------------------------------------------+
+
++------------------------+----------------------------------------------------+
+| ID                     | 08                                                 |
++========================+====================================================+
+| ``Threat``             | **A malicious endpoint may forge a direct message  |
+|                        | request such that it reveals the internal state of |
+|                        | another endpoint through the direct message        |
+|                        | response.**                                        |
+|                        | The secure partition or SPMC replies to a partition|
+|                        | message by a direct message response with          |
+|                        | information which may reveal its internal state    |
+|                        | (.e.g. partition message response outside of       |
+|                        | allowed bounds).                                   |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF1, DF2, DF3, DF4                                 |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMC                                               |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | SPMC or SP state                                   |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | NS-Endpoint, S-Endpoint                            |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Information discolure                              |
++------------------------+------------------+---------------+-----------------+
+| ``Application``        |   ``Server``     |  ``Mobile``   |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Impact``             | Medium (3)       | Medium (3)    |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Likelihood``         | Low (2)          | Low (2)	    |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Total Risk Rating``  | Medium (6)       | Medium (6)    |                 |
++------------------------+------------------+---------------+-----------------+
+| ``Mitigations``        | For the specific case of direct requests targetting|
+|                        | the SPMC, the latter is hardened to prevent        |
+|                        | its internal state or the state of an SP to be     |
+|                        | revealed through a direct message response.        |
+|                        | Further FF-A v1.1 guidance about run time models   |
+|                        | and partition states will be implemented in future |
+|                        | TF-A SPMC releases.                                |
++------------------------+----------------------------------------------------+
+
++------------------------+----------------------------------------------------+
+| ID                     | 09                                                 |
++========================+====================================================+
+| ``Threat``             | **Probing the FF-A communication between           |
+|                        | endpoints.**                                       |
+|                        | SPMC and SPs are typically loaded to external      |
+|                        | memory (protected by a TrustZone memory            |
+|                        | controller). A malicious agent may use non invasive|
+|                        | methods to probe the external memory bus and       |
+|                        | extract the traffic between an SP and the SPMC or  |
+|                        | among SPs when shared buffers are held in external |
+|                        | memory.                                            |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF7                                                |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMC                                               |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | SP/SPMC state, SP/SPMC secrets                     |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | Hardware attack                                    |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Information disclosure                             |
++------------------------+------------------+-----------------+---------------+
+| ``Application``        |   ``Server``     |   ``Mobile``    |               |
++------------------------+------------------+-----------------+---------------+
+| ``Impact``             | Medium (3)       | Medium (3)      |               |
++------------------------+------------------+-----------------+---------------+
+| ``Likelihood``         | Low (2)          | Medium (3)      |               |
++------------------------+------------------+-----------------+---------------+
+| ``Total Risk Rating``  | Medium (6)       | Medium (9)      |               |
++------------------------+------------------+-----------------+---------------+
+| ``Mitigations``        | It is expected the platform or chipset provides    |
+|                        | guarantees in protecting the DRAM contents.        |
+|                        | The TF-A SPMC does not mitigate this class of      |
+|                        | attack and this is left to the integrator.         |
++------------------------+----------------------------------------------------+
+
++------------------------+----------------------------------------------------+
+| ID                     | 10                                                 |
++========================+====================================================+
+| ``Threat``             | **A malicious agent may attempt revealing the SPMC |
+|                        | state or secrets by the use of software-based cache|
+|                        | side-channel attack techniques.**                  |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF7                                                |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMC                                               |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | SP or SPMC state                                   |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | NS-Endpoint, S-Endpoint                            |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Information disclosure                             |
++------------------------+------------------+-----------------+---------------+
+| ``Application``        |   ``Server``     |   ``Mobile``    |               |
++------------------------+------------------+-----------------+---------------+
+| ``Impact``             | Medium (3)       | Medium (3)      |               |
++------------------------+------------------+-----------------+---------------+
+| ``Likelihood``         | Low (2)          | Low (2)         |               |
++------------------------+------------------+-----------------+---------------+
+| ``Total Risk Rating``  | Medium (6)       | Medium (6)      |               |
++------------------------+------------------+-----------------+---------------+
+| ``Mitigations``        | From an integration perspective it is assumed      |
+|                        | platforms consuming the SPMC component at S-EL2    |
+|                        | (hence implementing the Armv8.4 FEAT_SEL2          |
+|                        | architecture extension) implement mitigations to   |
+|                        | Spectre, Meltdown or other cache timing            |
+|                        | side-channel type of attacks.                      |
+|                        | The TF-A SPMC implements one mitigation (barrier   |
+|                        | preventing speculation past exeception returns).   |
+|                        | The SPMC may be hardened further with SW           |
+|                        | mitigations (e.g. speculation barriers) for the    |
+|                        | cases not covered in HW. Usage of hardened         |
+|                        | compilers and appropriate options, code inspection |
+|                        | are recommended ways to mitigate Spectre types of  |
+|                        | attacks. For non-hardened cores, the usage of      |
+|                        | techniques such a kernel page table isolation can  |
+|                        | help mitigating Meltdown type of attacks.          |
++------------------------+----------------------------------------------------+
+
++------------------------+----------------------------------------------------+
+| ID                     | 11                                                 |
++========================+====================================================+
+| ``Threat``             | **A malicious endpoint may attempt flooding the    |
+|                        | SPMC with requests targetting a service within an  |
+|                        | endpoint such that it denies another endpoint to   |
+|                        | access this service.**                             |
+|                        | Similarly, the malicious endpoint may target a     |
+|                        | a service within an endpoint such that the latter  |
+|                        | is unable to request services from another         |
+|                        | endpoint.                                          |
++------------------------+----------------------------------------------------+
+| ``Diagram Elements``   | DF1, DF2, DF3, DF4                                 |
++------------------------+----------------------------------------------------+
+| ``Affected TF-A        | SPMC                                               |
+| Components``           |                                                    |
++------------------------+----------------------------------------------------+
+| ``Assets``             | SPMC state                                         |
++------------------------+----------------------------------------------------+
+| ``Threat Agent``       | NS-Endpoint, S-Endpoint                            |
++------------------------+----------------------------------------------------+
+| ``Threat Type``        | Denial of service                                  |
++------------------------+------------------+-----------------+---------------+
+| ``Application``        |   ``Server``     |   ``Mobile``    |               |
++------------------------+------------------+-----------------+---------------+
+| ``Impact``             | Medium (3)       | Medium (3)      |               |
++------------------------+------------------+-----------------+---------------+
+| ``Likelihood``         | Medium (3)       | Medium (3)      |               |
++------------------------+------------------+-----------------+---------------+
+| ``Total Risk Rating``  | Medium (9)       | Medium (9)      |               |
++------------------------+------------------+-----------------+---------------+
+| ``Mitigations``        | The TF-A SPMC does not mitigate this threat.       |
+|                        | Bounding the time for operations to complete can   |
+|                        | be achieved by the usage of a trusted watchdog.    |
+|                        | Other quality of service monitoring can be achieved|
+|                        | in the SPMC such as counting a number of operations|
+|                        | in a limited timeframe.                            |
++------------------------+----------------------------------------------------+
+
+--------------
+
+*Copyright (c) 2021, Arm Limited. All rights reserved.*
+
+.. _Arm Firmware Framework for Armv8-A: https://developer.arm.com/docs/den0077/latest
+.. _Secure Partition Manager: ../components/secure-partition-manager.html
+.. _Generic TF-A threat model: ./threat_model.html#threat-analysis
+.. _FF-A ACS: https://github.com/ARM-software/ff-a-acs/releases
diff --git a/drivers/arm/gic/v3/gic-x00.c b/drivers/arm/gic/v3/gic-x00.c
index 6e106ba..aaef485 100644
--- a/drivers/arm/gic/v3/gic-x00.c
+++ b/drivers/arm/gic/v3/gic-x00.c
@@ -16,15 +16,13 @@
 #include <assert.h>
 
 #include <arch_helpers.h>
+#include <drivers/arm/arm_gicv3_common.h>
 #include <drivers/arm/gicv3.h>
 
 #include "gicv3_private.h"
 
 /* GIC-600 specific register offsets */
 #define GICR_PWRR			0x24U
-#define IIDR_MODEL_ARM_GIC_600		U(0x0200043b)
-#define IIDR_MODEL_ARM_GIC_600AE	U(0x0300043b)
-#define IIDR_MODEL_ARM_GIC_CLAYTON	U(0x0400043b)
 
 /* GICR_PWRR fields */
 #define PWRR_RDPD_SHIFT			0
@@ -46,7 +44,7 @@
 
 #if GICV3_SUPPORT_GIC600
 
-/* GIC-600/Clayton specific accessor functions */
+/* GIC-600/700 specific accessor functions */
 static void gicr_write_pwrr(uintptr_t base, unsigned int val)
 {
 	mmio_write_32(base + GICR_PWRR, val);
@@ -123,12 +121,12 @@
 	uint32_t reg = mmio_read_32(gicr_base + GICR_IIDR);
 
 	/*
-	 * The Arm GIC-600 and GIC-Clayton models have their redistributors
+	 * The Arm GIC-600 and GIC-700 models have their redistributors
 	 * powered down at reset.
 	 */
 	return (((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) ||
 		((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600AE) ||
-		((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_CLAYTON));
+		((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_700));
 }
 
 #endif	/* GICV3_SUPPORT_GIC600 */
diff --git a/drivers/arm/gic/v3/gic600_multichip.c b/drivers/arm/gic/v3/gic600_multichip.c
index ca7c43b..fd3d8c2 100644
--- a/drivers/arm/gic/v3/gic600_multichip.c
+++ b/drivers/arm/gic/v3/gic600_multichip.c
@@ -11,6 +11,7 @@
 #include <assert.h>
 
 #include <common/debug.h>
+#include <drivers/arm/arm_gicv3_common.h>
 #include <drivers/arm/gic600_multichip.h>
 #include <drivers/arm/gicv3.h>
 
@@ -73,6 +74,7 @@
 				unsigned int spi_id_max)
 {
 	unsigned int spi_block_min, spi_blocks;
+	unsigned int gicd_iidr_val = gicd_read_iidr(base);
 	uint64_t chipr_n_val;
 
 	/*
@@ -100,8 +102,24 @@
 	spi_block_min = SPI_BLOCK_MIN_VALUE(spi_id_min);
 	spi_blocks    = SPI_BLOCKS_VALUE(spi_id_min, spi_id_max);
 
-	chipr_n_val = (GICD_CHIPR_VALUE(chip_addr, spi_block_min, spi_blocks)) |
-		GICD_CHIPRx_SOCKET_STATE;
+	switch ((gicd_iidr_val & IIDR_MODEL_MASK)) {
+	case IIDR_MODEL_ARM_GIC_600:
+		chipr_n_val = GICD_CHIPR_VALUE_GIC_600(chip_addr,
+						       spi_block_min,
+						       spi_blocks);
+		break;
+	case IIDR_MODEL_ARM_GIC_700:
+		chipr_n_val = GICD_CHIPR_VALUE_GIC_700(chip_addr,
+						       spi_block_min,
+						       spi_blocks);
+		break;
+	default:
+		ERROR("Unsupported GIC model 0x%x for multichip setup.\n",
+		      gicd_iidr_val);
+		panic();
+		break;
+	}
+	chipr_n_val |= GICD_CHIPRx_SOCKET_STATE;
 
 	/*
 	 * Wait for DCHIPR.PUP to be zero before commencing writes to
diff --git a/drivers/arm/gic/v3/gic600_multichip_private.h b/drivers/arm/gic/v3/gic600_multichip_private.h
index fe4134c..5d1ff6a 100644
--- a/drivers/arm/gic/v3/gic600_multichip_private.h
+++ b/drivers/arm/gic/v3/gic600_multichip_private.h
@@ -27,17 +27,11 @@
 #define GICD_CHIPSR_RTS_SHIFT		4
 #define GICD_DCHIPR_RT_OWNER_SHIFT	4
 
-/*
- * If GIC v4 extension is enabled, then use SPI macros specific to GIC-Clayton.
- * Other shifts and mask remains same between GIC-600 and GIC-Clayton.
- */
-#if GIC_ENABLE_V4_EXTN
-#define GICD_CHIPRx_SPI_BLOCK_MIN_SHIFT	9
-#define GICD_CHIPRx_SPI_BLOCKS_SHIFT	3
-#else
-#define GICD_CHIPRx_SPI_BLOCK_MIN_SHIFT	10
-#define GICD_CHIPRx_SPI_BLOCKS_SHIFT	5
-#endif
+/* Other shifts and masks remain the same between GIC-600 and GIC-700. */
+#define GIC_700_SPI_BLOCK_MIN_SHIFT	9
+#define GIC_700_SPI_BLOCKS_SHIFT	3
+#define GIC_600_SPI_BLOCK_MIN_SHIFT	10
+#define GIC_600_SPI_BLOCKS_SHIFT	5
 
 #define GICD_CHIPSR_RTS_STATE_DISCONNECTED	U(0)
 #define GICD_CHIPSR_RTS_STATE_UPDATING		U(1)
@@ -59,10 +53,14 @@
 #define SPI_BLOCKS_VALUE(spi_id_min, spi_id_max) \
 			(((spi_id_max) - (spi_id_min) + 1) / \
 			GIC600_SPI_ID_MIN)
-#define GICD_CHIPR_VALUE(chip_addr, spi_block_min, spi_blocks) \
+#define GICD_CHIPR_VALUE_GIC_700(chip_addr, spi_block_min, spi_blocks) \
+			(((chip_addr) << GICD_CHIPRx_ADDR_SHIFT) | \
+			((spi_block_min) << GIC_700_SPI_BLOCK_MIN_SHIFT) | \
+			((spi_blocks) << GIC_700_SPI_BLOCKS_SHIFT))
+#define GICD_CHIPR_VALUE_GIC_600(chip_addr, spi_block_min, spi_blocks) \
 			(((chip_addr) << GICD_CHIPRx_ADDR_SHIFT) | \
-			((spi_block_min) << GICD_CHIPRx_SPI_BLOCK_MIN_SHIFT) | \
-			((spi_blocks) << GICD_CHIPRx_SPI_BLOCKS_SHIFT))
+			((spi_block_min) << GIC_600_SPI_BLOCK_MIN_SHIFT) | \
+			((spi_blocks) << GIC_600_SPI_BLOCKS_SHIFT))
 
 /*
  * Multichip data assertion macros
diff --git a/drivers/arm/gic/v3/gic600ae_fmu.c b/drivers/arm/gic/v3/gic600ae_fmu.c
new file mode 100644
index 0000000..13979fa
--- /dev/null
+++ b/drivers/arm/gic/v3/gic600ae_fmu.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Driver for GIC-600AE Fault Management Unit
+ */
+
+#include <assert.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/gic600ae_fmu.h>
+#include <drivers/arm/gicv3.h>
+
+/* GIC-600 AE FMU specific register offsets */
+
+/* GIC-600 AE FMU specific macros */
+#define FMU_ERRIDR_NUM			U(44)
+#define FMU_ERRIDR_NUM_MASK		U(0xFFFF)
+
+/* Safety mechanisms for GICD block */
+static char *gicd_sm_info[] = {
+	"Reserved",
+	"GICD dual lockstep error",
+	"GICD AXI4 slave interface error",
+	"GICD-PPI AXI4-Stream interface error",
+	"GICD-ITS AXI4-Stream interface error",
+	"GICD-SPI-Collator AXI4-Stream interface error",
+	"GICD AXI4 master interface error",
+	"SPI RAM DED error",
+	"SGI RAM DED error",
+	"Reserved",
+	"LPI RAM DED error",
+	"GICD-remote-GICD AXI4-Stream interface error",
+	"GICD Q-Channel interface error",
+	"GICD P-Channel interface error",
+	"SPI RAM address decode error",
+	"SGI RAM address decode error",
+	"Reserved",
+	"LPI RAM address decode error",
+	"FMU dual lockstep error",
+	"FMU ping ACK error",
+	"FMU APB parity error",
+	"GICD-Wake AXI4-Stream interface error",
+	"GICD PageOffset or Chip ID error",
+	"MBIST REQ error",
+	"SPI RAM SEC error",
+	"SGI RAM SEC error",
+	"Reserved",
+	"LPI RAM SEC error",
+	"User custom SM0 error",
+	"User custom SM1 error",
+	"GICD-ITS Monolithic switch error",
+	"GICD-ITS Q-Channel interface error",
+	"GICD-ITS Monolithic interface error",
+	"GICD FMU ClkGate override"
+};
+
+/* Safety mechanisms for PPI block */
+static char *ppi_sm_info[] = {
+	"Reserved",
+	"PPI dual lockstep error",
+	"PPI-GICD AXI4-Stream interface error",
+	"PPI-CPU-IF AXI4-Stream interface error",
+	"PPI Q-Channel interface error",
+	"PPI RAM DED error",
+	"PPI RAM address decode error",
+	"PPI RAM SEC error",
+	"PPI User0 SM",
+	"PPI User1 SM",
+	"MBIST REQ error",
+	"PPI interrupt parity protection error",
+	"PPI FMU ClkGate override"
+};
+
+/* Safety mechanisms for ITS block */
+static char *its_sm_info[] = {
+	"Reserved",
+	"ITS dual lockstep error",
+	"ITS-GICD AXI4-Stream interface error",
+	"ITS AXI4 slave interface error",
+	"ITS AXI4 master interface error",
+	"ITS Q-Channel interface error",
+	"ITS RAM DED error",
+	"ITS RAM address decode error",
+	"Bypass ACE switch error",
+	"ITS RAM SEC error",
+	"ITS User0 SM",
+	"ITS User1 SM",
+	"ITS-GICD Monolithic interface error",
+	"MBIST REQ error",
+	"ITS FMU ClkGate override"
+};
+
+/* Safety mechanisms for SPI Collator block */
+static char *spicol_sm_info[] = {
+	"Reserved",
+	"SPI Collator dual lockstep error",
+	"SPI-Collator-GICD AXI4-Stream interface error",
+	"SPI Collator Q-Channel interface error",
+	"SPI Collator Q-Channel clock error",
+	"SPI interrupt parity error"
+};
+
+/* Safety mechanisms for Wake Request block */
+static char *wkrqst_sm_info[] = {
+	"Reserved",
+	"Wake dual lockstep error",
+	"Wake-GICD AXI4-Stream interface error"
+};
+
+/*
+ * Initialization sequence for the FMU
+ *
+ * 1. enable error detection for error records that are passed in the blk_present_mask
+ * 2. enable MBIST REQ and FMU Clk Gate override safety mechanisms for error records
+ *    that are present on the platform
+ *
+ * The platforms are expected to pass `errctlr_ce_en` and `errctlr_ue_en`.
+ */
+void gic600_fmu_init(uint64_t base, uint64_t blk_present_mask,
+		     bool errctlr_ce_en, bool errctlr_ue_en)
+{
+	unsigned int num_blk = gic_fmu_read_erridr(base) & FMU_ERRIDR_NUM_MASK;
+	uint64_t errctlr;
+	uint32_t smen;
+
+	INFO("GIC600-AE FMU supports %d error records\n", num_blk);
+
+	assert(num_blk == FMU_ERRIDR_NUM);
+
+	/* sanitize block present mask */
+	blk_present_mask &= FMU_BLK_PRESENT_MASK;
+
+	/* Enable error detection for all error records */
+	for (unsigned int i = 0U; i < num_blk; i++) {
+
+		/* Skip next steps if the block is not present */
+		if ((blk_present_mask & BIT(i)) == 0U) {
+			continue;
+		}
+
+		/* Read the error record control register */
+		errctlr = gic_fmu_read_errctlr(base, i);
+
+		/* Enable error reporting and logging, if it is disabled */
+		if ((errctlr & FMU_ERRCTLR_ED_BIT) == 0U) {
+			errctlr |= FMU_ERRCTLR_ED_BIT;
+		}
+
+		/* Enable client provided ERRCTLR settings */
+		errctlr |= (errctlr_ce_en ? (FMU_ERRCTLR_CI_BIT | FMU_ERRCTLR_CE_EN_BIT) : 0);
+		errctlr |= (errctlr_ue_en ? FMU_ERRCTLR_UI_BIT : 0U);
+
+		gic_fmu_write_errctlr(base, i, errctlr);
+	}
+
+	/*
+	 * Enable MBIST REQ error and FMU CLK gate override safety mechanisms for
+	 * all blocks
+	 *
+	 * GICD, SMID 23 and SMID 33
+	 * PPI, SMID 10 and SMID 12
+	 * ITS, SMID 13 and SMID 14
+	 */
+	if ((blk_present_mask & BIT(FMU_BLK_GICD)) != 0U) {
+		smen = (GICD_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
+			(FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT);
+		gic_fmu_write_smen(base, smen);
+
+		smen = (GICD_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
+			(FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT);
+		gic_fmu_write_smen(base, smen);
+	}
+
+	for (unsigned int i = FMU_BLK_PPI0; i < FMU_BLK_PPI31; i++) {
+		if ((blk_present_mask & BIT(i)) != 0U) {
+			smen = (PPI_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
+				(i << FMU_SMEN_BLK_SHIFT);
+			gic_fmu_write_smen(base, smen);
+
+			smen = (PPI_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
+				(i << FMU_SMEN_BLK_SHIFT);
+			gic_fmu_write_smen(base, smen);
+		}
+	}
+
+	for (unsigned int i = FMU_BLK_ITS0; i < FMU_BLK_ITS7; i++) {
+		if ((blk_present_mask & BIT(i)) != 0U) {
+			smen = (ITS_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) |
+				(i << FMU_SMEN_BLK_SHIFT);
+			gic_fmu_write_smen(base, smen);
+
+			smen = (ITS_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) |
+				(i << FMU_SMEN_BLK_SHIFT);
+			gic_fmu_write_smen(base, smen);
+		}
+	}
+}
+
+/*
+ * This function enable the GICD background ping engine. The GICD sends ping
+ * messages to each remote GIC block, and expects a PING_ACK back within the
+ * specified timeout. Pings need to be enabled after programming the timeout
+ * value.
+ */
+void gic600_fmu_enable_ping(uint64_t base, uint64_t blk_present_mask,
+		unsigned int timeout_val, unsigned int interval_diff)
+{
+	/*
+	 * Populate the PING Mask to skip a specific block while generating
+	 * background ping messages and enable the ping mechanism.
+	 */
+	gic_fmu_write_pingmask(base, ~blk_present_mask);
+	gic_fmu_write_pingctlr(base, (interval_diff << FMU_PINGCTLR_INTDIFF_SHIFT) |
+		(timeout_val << FMU_PINGCTLR_TIMEOUTVAL_SHIFT) | FMU_PINGCTLR_EN_BIT);
+}
+
+/* Print the safety mechanism description for a given block */
+void gic600_fmu_print_sm_info(uint64_t base, unsigned int blk, unsigned int smid)
+{
+	if (blk == FMU_BLK_GICD && smid <= FMU_SMID_GICD_MAX) {
+		INFO("GICD, SMID %d: %s\n", smid, gicd_sm_info[smid]);
+	}
+
+	if (blk == FMU_BLK_SPICOL && smid <= FMU_SMID_SPICOL_MAX) {
+		INFO("SPI Collator, SMID %d: %s\n", smid, spicol_sm_info[smid]);
+	}
+
+	if (blk == FMU_BLK_WAKERQ && (smid <= FMU_SMID_WAKERQ_MAX)) {
+		INFO("Wake Request, SMID %d: %s\n", smid, wkrqst_sm_info[smid]);
+	}
+
+	if (((blk >= FMU_BLK_ITS0) && (blk <= FMU_BLK_ITS7)) && (smid <= FMU_SMID_ITS_MAX)) {
+		INFO("ITS, SMID %d: %s\n", smid, its_sm_info[smid]);
+	}
+
+	if (((blk >= FMU_BLK_PPI0) && (blk <= FMU_BLK_PPI31)) && (smid <= FMU_SMID_PPI_MAX)) {
+		INFO("PPI, SMID %d: %s\n", smid, ppi_sm_info[smid]);
+	}
+}
diff --git a/drivers/arm/gic/v3/gic600ae_fmu_helpers.c b/drivers/arm/gic/v3/gic600ae_fmu_helpers.c
new file mode 100644
index 0000000..84f7292
--- /dev/null
+++ b/drivers/arm/gic/v3/gic600ae_fmu_helpers.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <drivers/arm/gic600ae_fmu.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+
+#define GICFMU_IDLE_TIMEOUT_US		U(2000000)
+
+/* Macro to write 32-bit FMU registers */
+#define GIC_FMU_WRITE_32(base, reg, val) \
+	do { \
+		/* \
+		 * This register receives the unlock key that is required for \
+		 * writes to FMU registers to be successful. \
+		 */ \
+		mmio_write_32(base + GICFMU_KEY, 0xBE); \
+		/* Perform the actual write */ \
+		mmio_write_32((base) + (reg), (val)); \
+	} while (false)
+
+/* Macro to write 64-bit FMU registers */
+#define GIC_FMU_WRITE_64(base, reg, n, val) \
+	do { \
+		/* \
+		 * This register receives the unlock key that is required for \
+		 * writes to FMU registers to be successful. \
+		 */ \
+		mmio_write_32(base + GICFMU_KEY, 0xBE); \
+		/* \
+		 * APB bus is 32-bit wide; so split the 64-bit write into \
+		 * two 32-bit writes \
+		 */ \
+		mmio_write_32((base) + reg##_LO + (n * 64), (val)); \
+		mmio_write_32((base) + reg##_HI + (n * 64), (val)); \
+	} while (false)
+
+/* Helper function to wait until FMU is ready to accept the next command */
+static void wait_until_fmu_is_idle(uintptr_t base)
+{
+	uint64_t timeout_ref = timeout_init_us(GICFMU_IDLE_TIMEOUT_US);
+	uint64_t status;
+
+	/* wait until status is 'busy' */
+	do {
+		status = (gic_fmu_read_status(base) & BIT(0));
+
+		if (timeout_elapsed(timeout_ref)) {
+			ERROR("GIC600 AE FMU is not responding\n");
+			panic();
+		}
+	} while (status == U(0));
+}
+
+#define GIC_FMU_WRITE_ON_IDLE_32(base, reg, val) \
+	do { \
+		/* Wait until FMU is ready */ \
+		wait_until_fmu_is_idle(base); \
+		/* Actual register write */ \
+		GIC_FMU_WRITE_32(base, reg, val); \
+		/* Wait until FMU is ready */ \
+		wait_until_fmu_is_idle(base); \
+	} while (false)
+
+#define GIC_FMU_WRITE_ON_IDLE_64(base, reg, n, val) \
+	do { \
+		/* Wait until FMU is ready */ \
+		wait_until_fmu_is_idle(base); \
+		/* Actual register write */ \
+		GIC_FMU_WRITE_64(base, reg, n, val); \
+		/* Wait until FMU is ready */ \
+		wait_until_fmu_is_idle(base); \
+	} while (false)
+
+/*******************************************************************************
+ * GIC FMU functions for accessing the Fault Management Unit registers
+ ******************************************************************************/
+
+/*
+ * Accessors to read the Error Record Feature Register bits corresponding
+ * to an error record 'n'
+ */
+uint64_t gic_fmu_read_errfr(uintptr_t base, unsigned int n)
+{
+	/*
+	 * APB bus is 32-bit wide; so split the 64-bit read into
+	 * two 32-bit reads
+	 */
+	uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRFR_LO + n * 64U);
+
+	reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRFR_HI + n * 64U) << 32);
+	return reg_val;
+}
+
+/*
+ * Accessors to read the Error Record Control Register bits corresponding
+ * to an error record 'n'
+ */
+uint64_t gic_fmu_read_errctlr(uintptr_t base, unsigned int n)
+{
+	/*
+	 * APB bus is 32-bit wide; so split the 64-bit read into
+	 * two 32-bit reads
+	 */
+	uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRCTLR_LO + n * 64U);
+
+	reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRCTLR_HI + n * 64U) << 32);
+	return reg_val;
+}
+
+/*
+ * Accessors to read the Error Record Primary Status Register bits
+ * corresponding to an error record 'n'
+ */
+uint64_t gic_fmu_read_errstatus(uintptr_t base, unsigned int n)
+{
+	/*
+	 * APB bus is 32-bit wide; so split the 64-bit read into
+	 * two 32-bit reads
+	 */
+	uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRSTATUS_LO + n * 64U);
+
+	reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRSTATUS_HI + n * 64U) << 32);
+	return reg_val;
+}
+
+/*
+ * Accessors to read the Error Group Status Register
+ */
+uint64_t gic_fmu_read_errgsr(uintptr_t base)
+{
+	/*
+	 * APB bus is 32-bit wide; so split the 64-bit read into
+	 * two 32-bit reads
+	 */
+	uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRGSR_LO);
+
+	reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRGSR_HI) << 32);
+	return reg_val;
+}
+
+/*
+ * Accessors to read the Ping Control Register
+ */
+uint32_t gic_fmu_read_pingctlr(uintptr_t base)
+{
+	return mmio_read_32(base + GICFMU_PINGCTLR);
+}
+
+/*
+ * Accessors to read the Ping Now Register
+ */
+uint32_t gic_fmu_read_pingnow(uintptr_t base)
+{
+	return mmio_read_32(base + GICFMU_PINGNOW);
+}
+
+/*
+ * Accessors to read the Ping Mask Register
+ */
+uint64_t gic_fmu_read_pingmask(uintptr_t base)
+{
+	/*
+	 * APB bus is 32-bit wide; so split the 64-bit read into
+	 * two 32-bit reads
+	 */
+	uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_PINGMASK_LO);
+
+	reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_PINGMASK_HI) << 32);
+	return reg_val;
+}
+
+/*
+ * Accessors to read the FMU Status Register
+ */
+uint32_t gic_fmu_read_status(uintptr_t base)
+{
+	return mmio_read_32(base + GICFMU_STATUS);
+}
+
+/*
+ * Accessors to read the Error Record ID Register
+ */
+uint32_t gic_fmu_read_erridr(uintptr_t base)
+{
+	return mmio_read_32(base + GICFMU_ERRIDR);
+}
+
+/*
+ * Accessors to write a 64 bit value to the Error Record Control Register
+ */
+void gic_fmu_write_errctlr(uintptr_t base, unsigned int n, uint64_t val)
+{
+	GIC_FMU_WRITE_64(base, GICFMU_ERRCTLR, n, val);
+}
+
+/*
+ * Accessors to write a 64 bit value to the Error Record Primary Status
+ * Register
+ */
+void gic_fmu_write_errstatus(uintptr_t base, unsigned int n, uint64_t val)
+{
+	/* Wait until FMU is ready before writing */
+	GIC_FMU_WRITE_ON_IDLE_64(base, GICFMU_ERRSTATUS, n, val);
+}
+
+/*
+ * Accessors to write a 32 bit value to the Ping Control Register
+ */
+void gic_fmu_write_pingctlr(uintptr_t base, uint32_t val)
+{
+	GIC_FMU_WRITE_32(base, GICFMU_PINGCTLR, val);
+}
+
+/*
+ * Accessors to write a 32 bit value to the Ping Now Register
+ */
+void gic_fmu_write_pingnow(uintptr_t base, uint32_t val)
+{
+	/* Wait until FMU is ready before writing */
+	GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_PINGNOW, val);
+}
+
+/*
+ * Accessors to write a 32 bit value to the Safety Mechanism Enable Register
+ */
+void gic_fmu_write_smen(uintptr_t base, uint32_t val)
+{
+	/* Wait until FMU is ready before writing */
+	GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_SMEN, val);
+}
+
+/*
+ * Accessors to write a 32 bit value to the Safety Mechanism Inject Error
+ * Register
+ */
+void gic_fmu_write_sminjerr(uintptr_t base, uint32_t val)
+{
+	/* Wait until FMU is ready before writing */
+	GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_SMINJERR, val);
+}
+
+/*
+ * Accessors to write a 64 bit value to the Ping Mask Register
+ */
+void gic_fmu_write_pingmask(uintptr_t base, uint64_t val)
+{
+	GIC_FMU_WRITE_64(base, GICFMU_PINGMASK, 0, val);
+}
diff --git a/drivers/arm/gic/v3/gicv3.mk b/drivers/arm/gic/v3/gicv3.mk
index a2fc16f..d7e3536 100644
--- a/drivers/arm/gic/v3/gicv3.mk
+++ b/drivers/arm/gic/v3/gicv3.mk
@@ -1,11 +1,13 @@
 #
 # Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
 # Default configuration values
 GICV3_SUPPORT_GIC600		?=	0
+GICV3_SUPPORT_GIC600AE_FMU	?=	0
 GICV3_IMPL_GIC600_MULTICHIP	?=	0
 GICV3_OVERRIDE_DISTIF_PWR_OPS	?=	0
 GIC_ENABLE_V4_EXTN		?=	0
@@ -16,6 +18,11 @@
 			drivers/arm/gic/v3/gicdv3_helpers.c	\
 			drivers/arm/gic/v3/gicrv3_helpers.c
 
+ifeq (${GICV3_SUPPORT_GIC600AE_FMU}, 1)
+GICV3_SOURCES	+=	drivers/arm/gic/v3/gic600ae_fmu.c	\
+			drivers/arm/gic/v3/gic600ae_fmu_helpers.c
+endif
+
 ifeq (${GICV3_OVERRIDE_DISTIF_PWR_OPS}, 0)
 GICV3_SOURCES	+=	drivers/arm/gic/v3/arm_gicv3_common.c
 endif
@@ -29,6 +36,10 @@
 $(eval $(call assert_boolean,GICV3_SUPPORT_GIC600))
 $(eval $(call add_define,GICV3_SUPPORT_GIC600))
 
+# Set GIC-600AE FMU support
+$(eval $(call assert_boolean,GICV3_SUPPORT_GIC600AE_FMU))
+$(eval $(call add_define,GICV3_SUPPORT_GIC600AE_FMU))
+
 # Set GICv4 extension
 $(eval $(call assert_boolean,GIC_ENABLE_V4_EXTN))
 $(eval $(call add_define,GIC_ENABLE_V4_EXTN))
diff --git a/drivers/arm/gic/v3/gicv3_helpers.c b/drivers/arm/gic/v3/gicv3_helpers.c
index a0f44e9..d752013 100644
--- a/drivers/arm/gic/v3/gicv3_helpers.c
+++ b/drivers/arm/gic/v3/gicv3_helpers.c
@@ -86,8 +86,7 @@
 		if (proc_num < rdistif_num) {
 			rdistif_base_addrs[proc_num] = rdistif_base;
 		}
-
-		rdistif_base += (1U << GICR_PCPUBASE_SHIFT);
+		rdistif_base += gicv3_redist_size(typer_val);
 	} while ((typer_val & TYPER_LAST_BIT) == 0U);
 }
 
@@ -383,11 +382,13 @@
 	uintptr_t rdistif_base = gicr_frame;
 	unsigned int count;
 
-	for (count = 1; count < PLATFORM_CORE_COUNT; count++) {
-		if ((gicr_read_typer(rdistif_base) & TYPER_LAST_BIT) != 0U) {
+	for (count = 1U; count < PLATFORM_CORE_COUNT; count++) {
+		uint64_t typer_val = gicr_read_typer(rdistif_base);
+
+		if ((typer_val & TYPER_LAST_BIT) != 0U) {
 			break;
 		}
-		rdistif_base += (1U << GICR_PCPUBASE_SHIFT);
+		rdistif_base += gicv3_redist_size(typer_val);
 	}
 
 	return count;
diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c
index b1139b5..53a8fae 100644
--- a/drivers/arm/gic/v3/gicv3_main.c
+++ b/drivers/arm/gic/v3/gicv3_main.c
@@ -123,13 +123,7 @@
 	gic_version &= PIDR2_ARCH_REV_MASK;
 
 	/* Check GIC version */
-#if GIC_ENABLE_V4_EXTN
-	assert(gic_version == ARCH_REV_GICV4);
-
-	/* GICv4 supports Direct Virtual LPI injection */
-	assert((gicd_read_typer(plat_driver_data->gicd_base)
-					& TYPER_DVIS) != 0);
-#else
+#if !GIC_ENABLE_V4_EXTN
 	assert(gic_version == ARCH_REV_GICV3);
 #endif
 	/*
@@ -1298,7 +1292,7 @@
 			gicr_frame_found = true;
 			break;
 		}
-		rdistif_base += (uintptr_t)(ULL(1) << GICR_PCPUBASE_SHIFT);
+		rdistif_base += gicv3_redist_size(typer_val);
 	} while ((typer_val & TYPER_LAST_BIT) == 0U);
 
 	if (!gicr_frame_found) {
diff --git a/drivers/arm/tzc/tzc400.c b/drivers/arm/tzc/tzc400.c
index 9fc1578..f1dacbb 100644
--- a/drivers/arm/tzc/tzc400.c
+++ b/drivers/arm/tzc/tzc400.c
@@ -68,6 +68,7 @@
 DEFINE_TZC_COMMON_WRITE_REGION_TOP(400, 400)
 DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(400, 400)
 DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(400, 400)
+DEFINE_TZC_COMMON_UPDATE_FILTERS(400, 400)
 DEFINE_TZC_COMMON_CONFIGURE_REGION0(400)
 DEFINE_TZC_COMMON_CONFIGURE_REGION(400)
 
@@ -271,6 +272,15 @@
 						sec_attr, nsaid_permissions);
 }
 
+void tzc400_update_filters(unsigned int region, unsigned int filters)
+{
+	/* Do range checks on filters and regions. */
+	assert(((filters >> tzc400.num_filters) == 0U) &&
+	       (region < tzc400.num_regions));
+
+	_tzc400_update_filters(tzc400.base, region, tzc400.num_filters, filters);
+}
+
 void tzc400_enable_filters(void)
 {
 	unsigned int state;
diff --git a/drivers/arm/tzc/tzc_common_private.h b/drivers/arm/tzc/tzc_common_private.h
index 1d99077..2090944 100644
--- a/drivers/arm/tzc/tzc_common_private.h
+++ b/drivers/arm/tzc/tzc_common_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -90,6 +90,27 @@
 	}
 
 /*
+ * It is used to modify the filters status for a defined region.
+ */
+#define DEFINE_TZC_COMMON_UPDATE_FILTERS(fn_name, macro_name)		\
+	static inline void _tzc##fn_name##_update_filters(		\
+						uintptr_t base,		\
+						unsigned int region_no,	\
+						unsigned int nbfilters, \
+						unsigned int filters)	\
+	{								\
+		uint32_t filters_mask = GENMASK(nbfilters - 1U, 0);	\
+									\
+		mmio_clrsetbits_32(base +				\
+			TZC_REGION_OFFSET(				\
+				TZC_##macro_name##_REGION_SIZE,		\
+				region_no) +				\
+			TZC_##macro_name##_REGION_ATTR_0_OFFSET,	\
+			filters_mask << TZC_REGION_ATTR_F_EN_SHIFT,	\
+			filters << TZC_REGION_ATTR_F_EN_SHIFT);		\
+	}
+
+/*
  * It is used to program region 0 ATTRIBUTES and ACCESS register.
  */
 #define DEFINE_TZC_COMMON_CONFIGURE_REGION0(fn_name)			\
diff --git a/drivers/auth/auth_mod.c b/drivers/auth/auth_mod.c
index c7f84af..917ee4a 100644
--- a/drivers/auth/auth_mod.c
+++ b/drivers/auth/auth_mod.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,6 +16,7 @@
 #include <drivers/auth/auth_mod.h>
 #include <drivers/auth/crypto_mod.h>
 #include <drivers/auth/img_parser_mod.h>
+#include <drivers/fwu/fwu.h>
 #include <lib/fconf/fconf_tbbr_getter.h>
 #include <plat/common/platform.h>
 
@@ -242,6 +243,7 @@
 	unsigned int data_len, len, i;
 	unsigned int plat_nv_ctr;
 	int rc = 0;
+	bool is_trial_run = false;
 
 	/* Get the counter value from current image. The AM expects the IPM
 	 * to return the counter value as a DER encoded integer */
@@ -284,7 +286,10 @@
 		/* Invalid NV-counter */
 		return 1;
 	} else if (*cert_nv_ctr > plat_nv_ctr) {
-		*need_nv_ctr_upgrade = true;
+#if PSA_FWU_SUPPORT && IMAGE_BL2
+		is_trial_run = fwu_is_trial_run_state();
+#endif /* PSA_FWU_SUPPORT && IMAGE_BL2 */
+		*need_nv_ctr_upgrade = !is_trial_run;
 	}
 
 	return 0;
diff --git a/drivers/fwu/fwu.c b/drivers/fwu/fwu.c
new file mode 100644
index 0000000..7cb4c29
--- /dev/null
+++ b/drivers/fwu/fwu.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/tf_crc32.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/fwu/fwu.h>
+#include <drivers/fwu/fwu_metadata.h>
+#include <drivers/io/io_storage.h>
+
+#include <plat/common/platform.h>
+
+/*
+ * Assert that crc_32 is the first member of fwu_metadata structure.
+ * It avoids accessing data outside of the metadata structure during
+ * CRC32 computation if the crc_32 field gets moved due the structure
+ * member(s) addition in the future.
+ */
+CASSERT((offsetof(struct fwu_metadata, crc_32) == 0),
+	crc_32_must_be_first_member_of_structure);
+
+static struct fwu_metadata metadata;
+static bool is_fwu_initialized;
+
+/*******************************************************************************
+ * Compute CRC32 of the FWU metadata, and check it against the CRC32 value
+ * present in the FWU metadata.
+ *
+ * return -1 on error, otherwise 0
+ ******************************************************************************/
+static int fwu_metadata_crc_check(void)
+{
+	unsigned char *data = (unsigned char *)&metadata;
+
+	uint32_t calc_crc = tf_crc32(0U, data + sizeof(metadata.crc_32),
+				     (sizeof(metadata) -
+				      sizeof(metadata.crc_32)));
+
+	if (metadata.crc_32 != calc_crc) {
+		return -1;
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+ * Check the sanity of FWU metadata.
+ *
+ * return -1 on error, otherwise 0
+ ******************************************************************************/
+static int fwu_metadata_sanity_check(void)
+{
+	/* ToDo: add more conditions for sanity check */
+	if ((metadata.active_index >= NR_OF_FW_BANKS) ||
+	    (metadata.previous_active_index >= NR_OF_FW_BANKS)) {
+		return -1;
+	}
+
+	return 0;
+}
+
+/*******************************************************************************
+ * Verify and load specified FWU metadata image to local FWU metadata structure.
+ *
+ * @image_id: FWU metadata image id (either FWU_METADATA_IMAGE_ID or
+ *				     BKUP_FWU_METADATA_IMAGE_ID)
+ *
+ * return a negative value on error, otherwise 0
+ ******************************************************************************/
+static int fwu_metadata_load(unsigned int image_id)
+{
+	int result;
+	uintptr_t dev_handle, image_handle, image_spec;
+	size_t bytes_read;
+
+	assert((image_id == FWU_METADATA_IMAGE_ID) ||
+	       (image_id == BKUP_FWU_METADATA_IMAGE_ID));
+
+	result = plat_fwu_set_metadata_image_source(image_id,
+						    &dev_handle,
+						    &image_spec);
+	if (result != 0) {
+		WARN("Failed to set reference to image id=%u (%i)\n",
+		     image_id, result);
+		return result;
+	}
+
+	result = io_open(dev_handle, image_spec, &image_handle);
+	if (result != 0) {
+		WARN("Failed to load image id id=%u (%i)\n",
+		     image_id, result);
+		return result;
+	}
+
+	result = io_read(image_handle, (uintptr_t)&metadata,
+			 sizeof(struct fwu_metadata), &bytes_read);
+
+	if (result != 0) {
+		WARN("Failed to read image id=%u (%i)\n", image_id, result);
+		goto exit;
+	}
+
+	if (sizeof(struct fwu_metadata) != bytes_read) {
+		/* return -1 in case of partial/no read */
+		result = -1;
+		WARN("Read bytes (%zu) instead of expected (%zu) bytes\n",
+		     bytes_read, sizeof(struct fwu_metadata));
+		goto exit;
+	}
+
+	/* sanity check on loaded parameters */
+	result = fwu_metadata_sanity_check();
+	if (result != 0) {
+		WARN("Sanity %s\n", "check failed on FWU metadata");
+		goto exit;
+	}
+
+	/* CRC check on loaded parameters */
+	result = fwu_metadata_crc_check();
+	if (result != 0) {
+		WARN("CRC %s\n", "check failed on FWU metadata");
+	}
+
+exit:
+	(void)io_close(image_handle);
+
+	return result;
+}
+
+/*******************************************************************************
+ * The system runs in the trial run state if any of the images in the active
+ * firmware bank has not been accepted yet.
+ *
+ * Returns true if the system is running in the trial state.
+ ******************************************************************************/
+bool fwu_is_trial_run_state(void)
+{
+	bool trial_run = false;
+
+	assert(is_fwu_initialized == true);
+
+	for (unsigned int i = 0U; i < NR_OF_IMAGES_IN_FW_BANK; i++) {
+		struct fwu_image_entry *entry = &metadata.img_entry[i];
+		struct fwu_image_properties *img_props =
+			&entry->img_props[metadata.active_index];
+		if (img_props->accepted == 0) {
+			trial_run = true;
+			break;
+		}
+	}
+
+	return trial_run;
+}
+
+/*******************************************************************************
+ * Load verified copy of FWU metadata image kept in the platform NV storage
+ * into local FWU metadata structure.
+ * Also, update platform I/O policies with the offset address and length of
+ * firmware-updated images kept in the platform NV storage.
+ ******************************************************************************/
+void fwu_init(void)
+{
+	/* Load FWU metadata which will be used to load the images in the
+	 * active bank as per PSA FWU specification
+	 */
+	int result = fwu_metadata_load(FWU_METADATA_IMAGE_ID);
+
+	if (result != 0) {
+		WARN("loading of FWU-Metadata failed, "
+		     "using Bkup-FWU-Metadata\n");
+
+		result = fwu_metadata_load(BKUP_FWU_METADATA_IMAGE_ID);
+		if (result != 0) {
+			ERROR("loading of Bkup-FWU-Metadata failed\n");
+			panic();
+		}
+	}
+
+	plat_fwu_set_images_source(&metadata);
+
+	is_fwu_initialized = true;
+}
diff --git a/drivers/fwu/fwu.mk b/drivers/fwu/fwu.mk
new file mode 100644
index 0000000..f4452e0
--- /dev/null
+++ b/drivers/fwu/fwu.mk
@@ -0,0 +1,11 @@
+#
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+FWU_SRC_DIR	:= drivers/fwu/
+
+FWU_SRCS	:= ${FWU_SRC_DIR}fwu.c
+
+BL2_SOURCES	+= ${FWU_SRCS}
diff --git a/drivers/io/io_mtd.c b/drivers/io/io_mtd.c
index 7575fa2..ba8cecd 100644
--- a/drivers/io/io_mtd.c
+++ b/drivers/io/io_mtd.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,8 +18,9 @@
 typedef struct {
 	io_mtd_dev_spec_t	*dev_spec;
 	uintptr_t		base;
-	unsigned long long	offset;		/* Offset in bytes */
-	unsigned long long	size;	/* Size of device in bytes */
+	unsigned long long	pos;		/* Offset in bytes */
+	unsigned long long	size;		/* Size of device in bytes */
+	unsigned long long	extra_offset;	/* Extra offset in bytes */
 } mtd_dev_state_t;
 
 io_type_t device_type_mtd(void);
@@ -110,16 +111,47 @@
 	return 0;
 }
 
+static int mtd_add_extra_offset(mtd_dev_state_t *cur, size_t *extra_offset)
+{
+	io_mtd_ops_t *ops = &cur->dev_spec->ops;
+	int ret;
+
+	if (ops->seek == NULL) {
+		return 0;
+	}
+
+	ret = ops->seek(cur->base, cur->pos, extra_offset);
+	if (ret != 0) {
+		ERROR("%s: Seek error %d\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 static int mtd_open(io_dev_info_t *dev_info, const uintptr_t spec,
 		    io_entity_t *entity)
 {
 	mtd_dev_state_t *cur;
+	io_block_spec_t *region;
+	size_t extra_offset = 0U;
+	int ret;
 
 	assert((dev_info->info != 0UL) && (entity->info == 0UL));
 
+	region = (io_block_spec_t *)spec;
 	cur = (mtd_dev_state_t *)dev_info->info;
 	entity->info = (uintptr_t)cur;
-	cur->offset = 0U;
+	cur->base = region->offset;
+	cur->pos = 0U;
+	cur->extra_offset = 0U;
+
+	ret = mtd_add_extra_offset(cur, &extra_offset);
+	if (ret != 0) {
+		return ret;
+	}
+
+	cur->base += extra_offset;
 
 	return 0;
 }
@@ -128,6 +160,8 @@
 static int mtd_seek(io_entity_t *entity, int mode, signed long long offset)
 {
 	mtd_dev_state_t *cur;
+	size_t extra_offset = 0U;
+	int ret;
 
 	assert((entity->info != (uintptr_t)NULL) && (offset >= 0));
 
@@ -140,22 +174,29 @@
 			return -EINVAL;
 		}
 
-		cur->offset = offset;
+		cur->pos = offset;
 		break;
 	case IO_SEEK_CUR:
-		if (((cur->offset + (unsigned long long)offset) >=
+		if (((cur->base + cur->pos + (unsigned long long)offset) >=
 		     cur->size) ||
-		    ((cur->offset + (unsigned long long)offset) <
-		     cur->offset)) {
+		    ((cur->base + cur->pos + (unsigned long long)offset) <
+		     cur->base + cur->pos)) {
 			return -EINVAL;
 		}
 
-		cur->offset += (unsigned long long)offset;
+		cur->pos += (unsigned long long)offset;
 		break;
 	default:
 		return -EINVAL;
 	}
 
+	ret = mtd_add_extra_offset(cur, &extra_offset);
+	if (ret != 0) {
+		return ret;
+	}
+
+	cur->extra_offset = extra_offset;
+
 	return 0;
 }
 
@@ -174,18 +215,19 @@
 	assert(ops->read != NULL);
 
 	VERBOSE("Read at %llx into %lx, length %zi\n",
-		cur->offset, buffer, length);
-	if ((cur->offset + length) > cur->dev_spec->device_size) {
+		cur->base + cur->pos, buffer, length);
+	if ((cur->base + cur->pos + length) > cur->dev_spec->device_size) {
 		return -EINVAL;
 	}
 
-	ret = ops->read(cur->offset, buffer, length, out_length);
+	ret = ops->read(cur->base + cur->pos + cur->extra_offset, buffer,
+			length, out_length);
 	if (ret < 0) {
 		return ret;
 	}
 
 	assert(*out_length == length);
-	cur->offset += *out_length;
+	cur->pos += *out_length;
 
 	return 0;
 }
diff --git a/drivers/marvell/comphy/comphy-cp110.h b/drivers/marvell/comphy/comphy-cp110.h
index 9b10619..af5c715 100644
--- a/drivers/marvell/comphy/comphy-cp110.h
+++ b/drivers/marvell/comphy/comphy-cp110.h
@@ -54,7 +54,7 @@
 #define COMMON_SELECTOR_PIPE_COMPHY_USBH	0x1
 #define COMMON_SELECTOR_PIPE_COMPHY_USBD	0x2
 
-/* SGMII/HS-SGMII/SFI/RXAUI */
+/* SGMII/Base-X/SFI/RXAUI */
 #define COMMON_SELECTOR_COMPHY0_1_2_NETWORK	0x1
 #define COMMON_SELECTOR_COMPHY3_RXAUI		0x1
 #define COMMON_SELECTOR_COMPHY3_SGMII		0x2
diff --git a/drivers/marvell/comphy/phy-comphy-3700.c b/drivers/marvell/comphy/phy-comphy-3700.c
index 7377e5e..027d07d 100644
--- a/drivers/marvell/comphy/phy-comphy-3700.c
+++ b/drivers/marvell/comphy/phy-comphy-3700.c
@@ -135,7 +135,7 @@
 		break;
 
 	case (COMPHY_SGMII_MODE):
-	case (COMPHY_HS_SGMII_MODE):
+	case (COMPHY_2500BASEX_MODE):
 		if (comphy_index == COMPHY_LANE0)
 			reg &= ~COMPHY_SELECTOR_USB3_GBE1_SEL_BIT;
 		else if (comphy_index == COMPHY_LANE1)
@@ -183,7 +183,7 @@
  * with COMPHY_USB3D_MODE or COMPHY_USB3H_MODE. (The usb3 phy initialization
  * code does not differentiate between these modes.)
  * Also it returns COMPHY_SGMII_MODE even if the phy was configures with
- * COMPHY_HS_SGMII_MODE. (The sgmii phy initialization code does differentiate
+ * COMPHY_2500BASEX_MODE. (The sgmii phy initialization code does differentiate
  * between these modes, but it is irrelevant when powering the phy off.)
  */
 static int mvebu_a3700_comphy_get_mode(uint8_t comphy_index)
@@ -401,8 +401,8 @@
 		/* SGMII 1G, SerDes speed 1.25G */
 		data |= SD_SPEED_1_25_G << GEN_RX_SEL_OFFSET;
 		data |= SD_SPEED_1_25_G << GEN_TX_SEL_OFFSET;
-	} else if (mode == COMPHY_HS_SGMII_MODE) {
-		/* HS SGMII (2.5G), SerDes speed 3.125G */
+	} else if (mode == COMPHY_2500BASEX_MODE) {
+		/* 2500Base-X, SerDes speed 3.125G */
 		data |= SD_SPEED_2_5_G << GEN_RX_SEL_OFFSET;
 		data |= SD_SPEED_2_5_G << GEN_TX_SEL_OFFSET;
 	} else {
@@ -479,7 +479,7 @@
 	 * 25 MHz the default values stored in PHY registers are OK.
 	 */
 	debug("Running C-DPI phy init %s mode\n",
-	      mode == COMPHY_HS_SGMII_MODE ? "2G5" : "1G");
+	      mode == COMPHY_2500BASEX_MODE ? "2G5" : "1G");
 	if (get_ref_clk() == 40)
 		comphy_sgmii_phy_init(comphy_index, mode, sd_ip_addr);
 
@@ -883,7 +883,7 @@
 						       comphy_mode);
 		break;
 	case(COMPHY_SGMII_MODE):
-	case(COMPHY_HS_SGMII_MODE):
+	case(COMPHY_2500BASEX_MODE):
 		ret = mvebu_a3700_comphy_sgmii_power_on(comphy_index,
 							comphy_mode);
 		break;
@@ -960,7 +960,7 @@
 
 	switch (mode) {
 	case(COMPHY_SGMII_MODE):
-	case(COMPHY_HS_SGMII_MODE):
+	case(COMPHY_2500BASEX_MODE):
 		err = mvebu_a3700_comphy_sgmii_power_off(comphy_index);
 		break;
 	case (COMPHY_USB3_MODE):
diff --git a/drivers/marvell/comphy/phy-comphy-common.h b/drivers/marvell/comphy/phy-comphy-common.h
index e3b430a..c599437 100644
--- a/drivers/marvell/comphy/phy-comphy-common.h
+++ b/drivers/marvell/comphy/phy-comphy-common.h
@@ -87,7 +87,7 @@
 
 #define COMPHY_SATA_MODE	0x1
 #define COMPHY_SGMII_MODE	0x2	/* SGMII 1G */
-#define COMPHY_HS_SGMII_MODE	0x3	/* SGMII 2.5G */
+#define COMPHY_2500BASEX_MODE	0x3	/* 2500Base-X */
 #define COMPHY_USB3H_MODE	0x4
 #define COMPHY_USB3D_MODE	0x5
 #define COMPHY_PCIE_MODE	0x6
diff --git a/drivers/marvell/comphy/phy-comphy-cp110.c b/drivers/marvell/comphy/phy-comphy-cp110.c
index 86f4c77..d10425b 100644
--- a/drivers/marvell/comphy/phy-comphy-cp110.c
+++ b/drivers/marvell/comphy/phy-comphy-cp110.c
@@ -30,7 +30,7 @@
 /* COMPHY speed macro */
 #define COMPHY_SPEED_1_25G		0 /* SGMII 1G */
 #define COMPHY_SPEED_2_5G		1
-#define COMPHY_SPEED_3_125G		2 /* SGMII 2.5G */
+#define COMPHY_SPEED_3_125G		2 /* 2500Base-X */
 #define COMPHY_SPEED_5G			3
 #define COMPHY_SPEED_5_15625G		4 /* XFI 5G */
 #define COMPHY_SPEED_6G			5
@@ -191,7 +191,7 @@
 		case(3):
 			/* For comphy 3:
 			 * 0x1 = RXAUI_Lane1
-			 * 0x2 = SGMII/HS-SGMII Port1
+			 * 0x2 = SGMII/Base-X Port1
 			 */
 			if (mode == COMPHY_RXAUI_MODE)
 				reg |= COMMON_SELECTOR_COMPHY3_RXAUI <<
@@ -202,20 +202,20 @@
 			break;
 		case(4):
 			 /* For comphy 4:
-			  * 0x1 = SGMII/HS-SGMII Port1, XFI1/SFI1
-			  * 0x2 = SGMII/HS-SGMII Port0: XFI0/SFI0, RXAUI_Lane0
+			  * 0x1 = SGMII/Base-X Port1, XFI1/SFI1
+			  * 0x2 = SGMII/Base-X Port0: XFI0/SFI0, RXAUI_Lane0
 			  *
-			  * We want to check if SGMII1/HS_SGMII1 is the
+			  * We want to check if SGMII1 is the
 			  * requested mode in order to determine which value
 			  * should be set (all other modes use the same value)
 			  * so we need to strip the mode, and check the ID
-			  * because we might handle SGMII0/HS_SGMII0 too.
+			  * because we might handle SGMII0 too.
 			  */
 			  /* TODO: need to distinguish between CP110 and CP115
 			   * as SFI1/XFI1 available only for CP115.
 			   */
 			if ((mode == COMPHY_SGMII_MODE ||
-			     mode == COMPHY_HS_SGMII_MODE ||
+			     mode == COMPHY_2500BASEX_MODE ||
 			     mode == COMPHY_SFI_MODE ||
 			     mode == COMPHY_XFI_MODE ||
 			     mode == COMPHY_AP_MODE)
@@ -228,7 +228,7 @@
 			break;
 		case(5):
 			/* For comphy 5:
-			 * 0x1 = SGMII/HS-SGMII Port2
+			 * 0x1 = SGMII/Base-X Port2
 			 * 0x2 = RXAUI Lane1
 			 */
 			if (mode == COMPHY_RXAUI_MODE)
@@ -713,7 +713,7 @@
 		data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
 		data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
 	} else if (sgmii_speed == COMPHY_SPEED_3_125G) {
-		/* HS SGMII (2.5G), SerDes speed 3.125G */
+		/* 2500Base-X, SerDes speed 3.125G */
 		data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET;
 		data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET;
 	} else {
@@ -2343,7 +2343,7 @@
 
 	switch (mode) {
 	case (COMPHY_SGMII_MODE):
-	case (COMPHY_HS_SGMII_MODE):
+	case (COMPHY_2500BASEX_MODE):
 	case (COMPHY_XFI_MODE):
 	case (COMPHY_SFI_MODE):
 	case (COMPHY_RXAUI_MODE):
@@ -2378,7 +2378,7 @@
 						       comphy_mode);
 		break;
 	case(COMPHY_SGMII_MODE):
-	case(COMPHY_HS_SGMII_MODE):
+	case(COMPHY_2500BASEX_MODE):
 		err = mvebu_cp110_comphy_sgmii_power_on(comphy_base,
 							comphy_index,
 							comphy_mode);
diff --git a/drivers/mtd/nand/core.c b/drivers/mtd/nand/core.c
index 44b001e..9f0331a 100644
--- a/drivers/mtd/nand/core.c
+++ b/drivers/mtd/nand/core.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -112,6 +112,47 @@
 	return 0;
 }
 
+int nand_seek_bb(uintptr_t base, unsigned int offset, size_t *extra_offset)
+{
+	unsigned int block;
+	unsigned int offset_block;
+	unsigned int max_block;
+	int is_bad;
+	size_t count_bb = 0U;
+
+	block = base / nand_dev.block_size;
+
+	if (offset != 0U) {
+		offset_block = (base + offset - 1U) / nand_dev.block_size;
+	} else {
+		offset_block = block;
+	}
+
+	max_block = nand_dev.size / nand_dev.block_size;
+
+	while (block <= offset_block) {
+		if (offset_block >= max_block) {
+			return -EIO;
+		}
+
+		is_bad = nand_dev.mtd_block_is_bad(block);
+		if (is_bad < 0) {
+			return is_bad;
+		}
+
+		if (is_bad == 1) {
+			count_bb++;
+			offset_block++;
+		}
+
+		block++;
+	}
+
+	*extra_offset = count_bb * nand_dev.block_size;
+
+	return 0;
+}
+
 struct nand_device *get_nand_device(void)
 {
 	return &nand_dev;
diff --git a/drivers/nxp/auth/csf_hdr_parser/csf_hdr.mk b/drivers/nxp/auth/csf_hdr_parser/csf_hdr.mk
index d518dbb..1af51f8 100644
--- a/drivers/nxp/auth/csf_hdr_parser/csf_hdr.mk
+++ b/drivers/nxp/auth/csf_hdr_parser/csf_hdr.mk
@@ -1,5 +1,5 @@
 #
-# Copyright 2020 NXP
+# Copyright 2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -9,7 +9,7 @@
 
 CSF_HDR_SOURCES	+=  $(PLAT_DRIVERS_PATH)/auth/csf_hdr_parser/plat_img_parser.c
 
-PLAT_INCLUDES	+= -I$(PLAT_DRIVERS_PATH)/auth/csf_hdr_parser/
+PLAT_INCLUDES	+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/auth/csf_hdr_parser/
 
 $(eval $(call add_define, CSF_HEADER_PREPENDED))
 
diff --git a/drivers/nxp/console/console.mk b/drivers/nxp/console/console.mk
index 22d1336..6174650 100644
--- a/drivers/nxp/console/console.mk
+++ b/drivers/nxp/console/console.mk
@@ -14,7 +14,7 @@
 
 ADD_CONSOLE		:= 1
 
-PLAT_INCLUDES		+=	-I$(PLAT_DRIVERS_PATH)/console
+PLAT_INCLUDES		+=	-I$(PLAT_DRIVERS_INCLUDE_PATH)/console
 
 ifeq ($(CONSOLE), NS16550)
 NXP_CONSOLE		:=	NS16550
diff --git a/drivers/nxp/crypto/caam/caam.mk b/drivers/nxp/crypto/caam/caam.mk
index 548c7b1..f929f53 100644
--- a/drivers/nxp/crypto/caam/caam.mk
+++ b/drivers/nxp/crypto/caam/caam.mk
@@ -1,5 +1,5 @@
 #
-# Copyright 2020 NXP
+# Copyright 2020-2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,11 +8,10 @@
 ifeq (${ADD_CAAM},)
 
 ADD_CAAM		:= 1
-CAAM_DRIVER_PATH	:= drivers/nxp/crypto/caam
 
-CAAM_DRIVER_SOURCES	+=  $(wildcard $(CAAM_DRIVER_PATH)/src/*.c)
+CAAM_DRIVER_SOURCES	+=  $(wildcard $(PLAT_DRIVERS_PATH)/crypto/caam/src/*.c)
 
-PLAT_INCLUDES		+= -I$(CAAM_DRIVER_PATH)/include
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/crypto/caam
 
 ifeq (${BL_COMM_CRYPTO_NEEDED},yes)
 BL_COMMON_SOURCES	+= ${CAAM_DRIVER_SOURCES}
diff --git a/drivers/nxp/csu/csu.mk b/drivers/nxp/csu/csu.mk
index ebdf674..bc16035 100644
--- a/drivers/nxp/csu/csu.mk
+++ b/drivers/nxp/csu/csu.mk
@@ -1,5 +1,5 @@
 #
-# Copyright 2020 NXP
+# Copyright 2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,11 +8,9 @@
 
 CSU_ADDED		:= 1
 
-CSU_DRIVERS_PATH	:=  ${PLAT_DRIVERS_PATH}/csu
-
-PLAT_INCLUDES		+= -I$(CSU_DRIVERS_PATH)
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/csu
 
-CSU_SOURCES		+= $(CSU_DRIVERS_PATH)/csu.c
+CSU_SOURCES		+= $(PLAT_DRIVERS_PATH)/csu/csu.c
 
 ifeq (${BL_COMM_CSU_NEEDED},yes)
 BL_COMMON_SOURCES	+= ${CSU_SOURCES}
diff --git a/drivers/nxp/dcfg/dcfg.c b/drivers/nxp/dcfg/dcfg.c
index 2e813e7..a988c5d 100644
--- a/drivers/nxp/dcfg/dcfg.c
+++ b/drivers/nxp/dcfg/dcfg.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 NXP
+ * Copyright 2020-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -43,20 +43,12 @@
 
 	reg = gur_in32(dcfg_init_info->g_nxp_dcfg_addr + DCFG_SVR_OFFSET);
 
-	soc_info.mfr_id = (reg & SVR_MFR_ID_MASK) >> SVR_MFR_ID_SHIFT;
-#if defined(CONFIG_CHASSIS_3_2)
-	soc_info.family = (reg & SVR_FAMILY_MASK) >> SVR_FAMILY_SHIFT;
-	soc_info.dev_id = (reg & SVR_DEV_ID_MASK) >> SVR_DEV_ID_SHIFT;
-#endif
+	soc_info.svr_reg.val = reg;
+
 	/* zero means SEC enabled. */
 	soc_info.sec_enabled =
 		(((reg & SVR_SEC_MASK) >> SVR_SEC_SHIFT) == 0) ? true : false;
 
-	soc_info.personality = (reg & SVR_PERSONALITY_MASK)
-				>> SVR_PERSONALITY_SHIFT;
-	soc_info.maj_ver = (reg & SVR_MAJ_VER_MASK) >> SVR_MAJ_VER_SHIFT;
-	soc_info.min_ver = reg & SVR_MIN_VER_MASK;
-
 	soc_info.is_populated = true;
 	return (const soc_info_t *) &soc_info;
 }
diff --git a/drivers/nxp/dcfg/dcfg.mk b/drivers/nxp/dcfg/dcfg.mk
index 61d1850..206595f 100644
--- a/drivers/nxp/dcfg/dcfg.mk
+++ b/drivers/nxp/dcfg/dcfg.mk
@@ -1,5 +1,5 @@
 #
-# Copyright 2020 NXP
+# Copyright 2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,11 +8,9 @@
 
 ADD_DCFG		:= 1
 
-DCFG_DRIVERS_PATH	:=  ${PLAT_DRIVERS_PATH}/dcfg
-
-PLAT_INCLUDES		+= -I$(DCFG_DRIVERS_PATH)
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/dcfg
 
-DCFG_SOURCES		+= $(DCFG_DRIVERS_PATH)/dcfg.c
+DCFG_SOURCES		+= $(PLAT_DRIVERS_PATH)/dcfg/dcfg.c
 
 ifeq (${BL_COMM_DCFG_NEEDED},yes)
 BL_COMMON_SOURCES	+= ${DCFG_SOURCES}
diff --git a/drivers/nxp/ddr/fsl-mmdc/ddr.mk b/drivers/nxp/ddr/fsl-mmdc/ddr.mk
index e6cc7c1..afccb62 100644
--- a/drivers/nxp/ddr/fsl-mmdc/ddr.mk
+++ b/drivers/nxp/ddr/fsl-mmdc/ddr.mk
@@ -9,11 +9,11 @@
 
 DDR_DRIVERS_PATH	:=	drivers/nxp/ddr
 
-DDR_CNTLR_SOURCES	:=	${DDR_DRIVERS_PATH}/fsl-mmdc/fsl_mmdc.c \
-				${DDR_DRIVERS_PATH}/nxp-ddr/utility.c	\
-				${DDR_DRIVERS_PATH}/nxp-ddr/ddr.c	\
-				${DDR_DRIVERS_PATH}/nxp-ddr/ddrc.c
+DDR_CNTLR_SOURCES	:=	${PLAT_DRIVERS_PATH}/ddr/fsl-mmdc/fsl_mmdc.c \
+				${PLAT_DRIVERS_PATH}/ddr/nxp-ddr/utility.c	\
+				${PLAT_DRIVERS_PATH}/ddr/nxp-ddr/ddr.c	\
+				${PLAT_DRIVERS_PATH}/ddr/nxp-ddr/ddrc.c
 
-PLAT_INCLUDES		+=	-I$(DDR_DRIVERS_PATH)/include	\
-				-I$(DDR_DRIVERS_PATH)/fsl-mmdc
+PLAT_INCLUDES		+=	-I$(PLAT_DRIVERS_INCLUDE_PATH)/ddr	\
+				-I$(PLAT_DRIVERS_INCLUDE_PATH)/ddr/fsl-mmdc
 #------------------------------------------------
diff --git a/drivers/nxp/ddr/nxp-ddr/ddr.mk b/drivers/nxp/ddr/nxp-ddr/ddr.mk
index 866c092..6bdd947 100644
--- a/drivers/nxp/ddr/nxp-ddr/ddr.mk
+++ b/drivers/nxp/ddr/nxp-ddr/ddr.mk
@@ -4,8 +4,6 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
-DDR_DRIVERS_PATH	:= ${PLAT_DRIVERS_PATH}/ddr
-
 ifeq ($(PLAT_DDR_PHY), PHY_GEN2)
 $(eval $(call add_define, PHY_GEN2))
 PLAT_DDR_PHY_DIR		:= phy-gen2
@@ -68,12 +66,11 @@
 $(eval $(call add_define, DEBUG_DDR_INPUT_CONFIG))
 endif
 
-DDR_CNTLR_SOURCES	:= $(DDR_DRIVERS_PATH)/nxp-ddr/ddr.c \
-			   $(DDR_DRIVERS_PATH)/nxp-ddr/ddrc.c \
-			   $(DDR_DRIVERS_PATH)/nxp-ddr/dimm.c \
-			   $(DDR_DRIVERS_PATH)/nxp-ddr/regs.c \
-			   $(DDR_DRIVERS_PATH)/nxp-ddr/utility.c \
-			   $(DDR_DRIVERS_PATH)/$(PLAT_DDR_PHY_DIR)/phy.c
+DDR_CNTLR_SOURCES	:= $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/ddr.c \
+			   $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/ddrc.c \
+			   $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/dimm.c \
+			   $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/regs.c \
+			   $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/utility.c \
+			   $(PLAT_DRIVERS_PATH)/ddr/$(PLAT_DDR_PHY_DIR)/phy.c
 
-PLAT_INCLUDES		+= -I$(DDR_DRIVERS_PATH)/nxp-ddr \
-			   -I$(DDR_DRIVERS_PATH)/include
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/ddr
diff --git a/drivers/nxp/ddr/phy-gen2/phy.c b/drivers/nxp/ddr/phy-gen2/phy.c
index 97de1ae..9c84b00 100644
--- a/drivers/nxp/ddr/phy-gen2/phy.c
+++ b/drivers/nxp/ddr/phy-gen2/phy.c
@@ -672,7 +672,7 @@
 
 #ifdef DDR_PLL_FIX
 	soc_info = get_soc_info();
-	if (soc_info->maj_ver == 1) {
+	if (soc_info->svr_reg.bf.maj_ver == 1) {
 		ps_count[0] = 0x520; /* seq0bdly0 */
 		ps_count[1] = 0xa41; /* seq0bdly1 */
 		ps_count[2] = 0x668a; /* seq0bdly2 */
@@ -1093,8 +1093,8 @@
 
 #ifdef ERRATA_DDR_A011396
 	/* Only apply to DDRC 5.05.00 */
-	soc_info = get_soc_info(NXP_DCFG_ADDR);
-	if ((soc_info->maj_ver == 1U) && (ip_rev == U(0x50500))) {
+	soc_info = get_soc_info();
+	if ((soc_info->svr_reg.bf.maj_ver == 1U) && (ip_rev == U(0x50500))) {
 		phy_io_write16(phy,
 				t_master | csr_dfi_rd_data_cs_dest_map_addr,
 				0U);
@@ -1890,8 +1890,8 @@
 		prog_pll_ctrl2(phy, input);
 #ifdef DDR_PLL_FIX
 		soc_info = get_soc_info();
-		debug("SOC_SI_REV = %x\n", soc_info->maj_ver);
-		if (soc_info->maj_ver == 1) {
+		debug("SOC_SI_REV = %x\n", soc_info->svr_reg.bf.maj_ver);
+		if (soc_info->svr_reg.bf.maj_ver == 1) {
 			prog_pll_pwr_dn(phy, input);
 
 			/*Enable FFE aka TxEqualizationMode for rev1 SI*/
@@ -2601,8 +2601,8 @@
 		}
 
 #ifdef NXP_APPLY_MAX_CDD
-		soc_info = get_soc_info(NXP_DCFG_ADDR);
-		if (soc_info->maj_ver == 2) {
+		soc_info = get_soc_info();
+		if (soc_info->svr_reg.bf.maj_ver == 2) {
 			tcfg0 = regs->timing_cfg[0];
 			tcfg4 = regs->timing_cfg[4];
 			rank = findrank(conf->cs_in_use);
diff --git a/drivers/nxp/drivers.mk b/drivers/nxp/drivers.mk
index c6d5541..c2db363 100644
--- a/drivers/nxp/drivers.mk
+++ b/drivers/nxp/drivers.mk
@@ -1,5 +1,5 @@
 #
-# Copyright 2020 NXP
+# Copyright 2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,7 +8,8 @@
 ###############################################################################
 
 
-PLAT_DRIVERS_PATH	:=	drivers/nxp
+PLAT_DRIVERS_PATH		:=	drivers/nxp
+PLAT_DRIVERS_INCLUDE_PATH	:=	include/drivers/nxp
 
 ifeq (${SMMU_NEEDED},yes)
 PLAT_INCLUDES	+= -Iinclude/drivers/nxp/smmu/
diff --git a/drivers/nxp/gic/gic.mk b/drivers/nxp/gic/gic.mk
index 68091e8..d75e071 100644
--- a/drivers/nxp/gic/gic.mk
+++ b/drivers/nxp/gic/gic.mk
@@ -17,7 +17,7 @@
 GIC_SOURCES		+=	${PLAT_DRIVERS_PATH}/gic/ls_gicv2.c	\
 				plat/common/plat_gicv2.c
 
-PLAT_INCLUDES		+=	-I${PLAT_DRIVERS_PATH}/gic/include/gicv2
+PLAT_INCLUDES		+=	-I${PLAT_DRIVERS_INCLUDE_PATH}/gic/gicv2
 else
 ifeq ($(GIC), GIC500)
 include drivers/arm/gic/v3/gicv3.mk
@@ -25,7 +25,7 @@
 GIC_SOURCES		+=	${PLAT_DRIVERS_PATH}/gic/ls_gicv3.c	\
 				plat/common/plat_gicv3.c
 
-PLAT_INCLUDES		+=	-I${PLAT_DRIVERS_PATH}/gic/include/gicv3
+PLAT_INCLUDES		+=	-I${PLAT_DRIVERS_INCLUDE_PATH}/gic/gicv3
 else
     $(error -> GIC type not set!)
 endif
diff --git a/drivers/nxp/gpio/gpio.mk b/drivers/nxp/gpio/gpio.mk
index 157c60a..74f0dc4 100644
--- a/drivers/nxp/gpio/gpio.mk
+++ b/drivers/nxp/gpio/gpio.mk
@@ -9,11 +9,9 @@
 
 GPIO_ADDED		:= 1
 
-GPIO_DRIVERS_PATH	:=  drivers/nxp/gpio
-
-PLAT_INCLUDES		+=  -I$(GPIO_DRIVERS_PATH)
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/gpio
 
-GPIO_SOURCES		:= $(GPIO_DRIVERS_PATH)/nxp_gpio.c
+GPIO_SOURCES		:= $(PLAT_DRIVERS_PATH)/gpio/nxp_gpio.c
 
 ifeq (${BL_COMM_GPIO_NEEDED},yes)
 BL_COMMON_SOURCES	+= ${GPIO_SOURCES}
diff --git a/drivers/nxp/i2c/i2c.mk b/drivers/nxp/i2c/i2c.mk
index ae89115..716e14a 100644
--- a/drivers/nxp/i2c/i2c.mk
+++ b/drivers/nxp/i2c/i2c.mk
@@ -1,5 +1,5 @@
 #
-# Copyright 2020 NXP
+# Copyright 2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -7,10 +7,10 @@
 ifeq (${ADD_I2C},)
 
 ADD_I2C			:= 1
-I2C_DRIVERS_PATH        := ${PLAT_DRIVERS_PATH}/i2c
+
+I2C_SOURCES		+= $(PLAT_DRIVERS_PATH)/i2c/i2c.c
 
-I2C_SOURCES		+= $(I2C_DRIVERS_PATH)/i2c.c
-PLAT_INCLUDES		+= -I$(I2C_DRIVERS_PATH)
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/i2c
 
 ifeq (${BL_COMM_I2C_NEEDED},yes)
 BL_COMMON_SOURCES	+= ${I2C_SOURCES}
diff --git a/drivers/nxp/interconnect/interconnect.mk b/drivers/nxp/interconnect/interconnect.mk
index 81e3fa9..aa51be4 100644
--- a/drivers/nxp/interconnect/interconnect.mk
+++ b/drivers/nxp/interconnect/interconnect.mk
@@ -1,4 +1,4 @@
-# Copyright 2020 NXP
+# Copyright 2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -12,7 +12,7 @@
 ifeq (${ADD_INTERCONNECT},)
 
 ADD_INTERCONNECT	:= 1
-PLAT_INCLUDES		+= -I${PLAT_DRIVERS_PATH}/interconnect
+PLAT_INCLUDES		+= -I${PLAT_DRIVERS_INCLUDE_PATH}/interconnect
 
 ifeq (, $(filter $(INTERCONNECT), CCI400 CCN502 CCN504 CCN508))
     $(error -> Interconnect type not set!)
diff --git a/drivers/nxp/pmu/pmu.mk b/drivers/nxp/pmu/pmu.mk
index 56b0422..8d2ef07 100644
--- a/drivers/nxp/pmu/pmu.mk
+++ b/drivers/nxp/pmu/pmu.mk
@@ -8,11 +8,9 @@
 
 PMU_ADDED		:= 1
 
-PMU_DRIVERS_PATH	:=  ${PLAT_DRIVERS_PATH}/pmu
-
-PLAT_INCLUDES		+= -I$(PMU_DRIVERS_PATH)
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/pmu
 
-PMU_SOURCES		+= $(PMU_DRIVERS_PATH)/pmu.c
+PMU_SOURCES		+= $(PLAT_DRIVERS_PATH)/pmu/pmu.c
 
 ifeq (${BL_COMM_PMU_NEEDED},yes)
 BL_COMMON_SOURCES	+= ${PMU_SOURCES}
diff --git a/drivers/nxp/qspi/qspi.mk b/drivers/nxp/qspi/qspi.mk
index 3e2c735..b83dee2 100644
--- a/drivers/nxp/qspi/qspi.mk
+++ b/drivers/nxp/qspi/qspi.mk
@@ -1,5 +1,5 @@
 #
-# Copyright 2020 NXP
+# Copyright 2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,11 +8,9 @@
 
 QSPI_ADDED		:= 1
 
-QSPI_DRIVERS_PATH	:=  ${PLAT_DRIVERS_PATH}/qspi
-
-QSPI_SOURCES		:=  $(QSPI_DRIVERS_PATH)/qspi.c
+QSPI_SOURCES		:= $(PLAT_DRIVERS_PATH)/qspi/qspi.c
 
-PLAT_INCLUDES		+= -I$(QSPI_DRIVERS_PATH)
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_PATH)/qspi
 
 ifeq (${BL_COMM_QSPI_NEEDED},yes)
 BL_COMMON_SOURCES	+= ${QSPI_SOURCES}
diff --git a/drivers/nxp/sd/sd_mmc.mk b/drivers/nxp/sd/sd_mmc.mk
index af91b1f..c83b1bd 100644
--- a/drivers/nxp/sd/sd_mmc.mk
+++ b/drivers/nxp/sd/sd_mmc.mk
@@ -1,5 +1,5 @@
 #
-# Copyright 2020 NXP
+# Copyright 2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,12 +8,10 @@
 
 ADD_SD_MMC	:= 1
 
-SD_DRIVERS_PATH		:=  ${PLAT_DRIVERS_PATH}/sd
-
-SD_MMC_BOOT_SOURCES	+= ${SD_DRIVERS_PATH}/sd_mmc.c \
+SD_MMC_BOOT_SOURCES	+= ${PLAT_DRIVERS_PATH}/sd/sd_mmc.c \
 			   drivers/io/io_block.c
 
-PLAT_INCLUDES		+= -I$(SD_DRIVERS_PATH)
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/sd
 
 ifeq (${BL_COMM_SD_MMC_NEEDED},yes)
 BL_COMMON_SOURCES	+= ${SD_MMC_BOOT_SOURCES}
diff --git a/drivers/nxp/sec_mon/sec_mon.mk b/drivers/nxp/sec_mon/sec_mon.mk
index 51e3e86..aaac53f 100644
--- a/drivers/nxp/sec_mon/sec_mon.mk
+++ b/drivers/nxp/sec_mon/sec_mon.mk
@@ -8,11 +8,9 @@
 
 ADD_SNVS		:= 1
 
-SNVS_DRIVERS_PATH	:= ${PLAT_DRIVERS_PATH}/sec_mon
-
-PLAT_INCLUDES		+= -I$(SNVS_DRIVERS_PATH)
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/sec_mon
 
-SNVS_SOURCES		+= $(SNVS_DRIVERS_PATH)/snvs.c
+SNVS_SOURCES		+= $(PLAT_DRIVERS_PATH)/sec_mon/snvs.c
 
 ifeq (${BL_COMM_SNVS_NEEDED},yes)
 BL_COMMON_SOURCES	+= ${SNVS_SOURCES}
diff --git a/drivers/nxp/sfp/sfp.mk b/drivers/nxp/sfp/sfp.mk
index 2546dc2..de708c5 100644
--- a/drivers/nxp/sfp/sfp.mk
+++ b/drivers/nxp/sfp/sfp.mk
@@ -1,5 +1,5 @@
 #
-# Copyright 2020 NXP
+# Copyright 2021 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -9,14 +9,12 @@
 SFP_ADDED		:= 1
 $(eval $(call add_define, NXP_SFP_ENABLED))
 
-SFP_DRIVERS_PATH	:=  ${PLAT_DRIVERS_PATH}/sfp
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/sfp
 
-PLAT_INCLUDES		+= -I$(SFP_DRIVERS_PATH)
-
-SFP_SOURCES		+= $(SFP_DRIVERS_PATH)/sfp.c
+SFP_SOURCES		+= $(PLAT_DRIVERS_PATH)/sfp/sfp.c
 
 ifeq (${FUSE_PROG}, 1)
-SFP_BL2_SOURCES		+= $(SFP_DRIVERS_PATH)/fuse_prov.c
+SFP_BL2_SOURCES		+= $(PLAT_DRIVERS_PATH)/sfp/fuse_prov.c
 endif
 
 ifeq (${BL_COMM_SFP_NEEDED},yes)
diff --git a/drivers/nxp/timer/timer.mk b/drivers/nxp/timer/timer.mk
index b9e298f..d658d19 100644
--- a/drivers/nxp/timer/timer.mk
+++ b/drivers/nxp/timer/timer.mk
@@ -8,10 +8,8 @@
 
 ADD_TIMER		:= 1
 
-TIMER_DRIVERS_PATH	:=  ${PLAT_DRIVERS_PATH}/timer
-
-PLAT_INCLUDES		+= -I$(TIMER_DRIVERS_PATH)
-TIMER_SOURCES	+= drivers/delay_timer/delay_timer.c	\
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/timer
+TIMER_SOURCES		+= drivers/delay_timer/delay_timer.c	\
 			   $(PLAT_DRIVERS_PATH)/timer/nxp_timer.c
 
 ifeq (${BL_COMM_TIMER_NEEDED},yes)
diff --git a/drivers/nxp/tzc/tzc.mk b/drivers/nxp/tzc/tzc.mk
index 830d78e..3fba28f 100644
--- a/drivers/nxp/tzc/tzc.mk
+++ b/drivers/nxp/tzc/tzc.mk
@@ -8,13 +8,11 @@
 
 ADD_TZASC		:= 1
 
-TZASC_DRIVERS_PATH	:=  ${PLAT_DRIVERS_PATH}/tzc
-
-PLAT_INCLUDES		+= -I$(TZASC_DRIVERS_PATH)
+PLAT_INCLUDES		+= -I$(PLAT_DRIVERS_INCLUDE_PATH)/tzc
 
 ifeq ($(TZC_ID), TZC400)
 TZASC_SOURCES		+= drivers/arm/tzc/tzc400.c\
-			   $(TZASC_DRIVERS_PATH)/plat_tzc400.c
+			   $(PLAT_DRIVERS_PATH)/tzc/plat_tzc400.c
 else ifeq ($(TZC_ID), NONE)
     $(info -> No TZC present on platform)
 else
diff --git a/drivers/renesas/common/common.c b/drivers/renesas/common/common.c
index 9b7c1eb..a0aa480 100644
--- a/drivers/renesas/common/common.c
+++ b/drivers/renesas/common/common.c
@@ -1,11 +1,12 @@
 /*
- * Copyright (c) 2018-2020, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2018-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <lib/mmio.h>
 
+#include "cpg_registers.h"
 #include "rcar_private.h"
 
 #if IMAGE_BL31
@@ -16,7 +17,7 @@
 {
 	uint32_t value = regval;
 
-	mmio_write_32((uintptr_t) RCAR_CPGWPR, ~value);
+	mmio_write_32(CPG_CPGWPR, ~value);
 	mmio_write_32(regadr, value);
 }
 
diff --git a/drivers/renesas/common/ddr/ddr_b/boot_init_dram.c b/drivers/renesas/common/ddr/ddr_b/boot_init_dram.c
index aa3bc24..8d002de 100644
--- a/drivers/renesas/common/ddr/ddr_b/boot_init_dram.c
+++ b/drivers/renesas/common/ddr/ddr_b/boot_init_dram.c
@@ -4147,7 +4147,13 @@
 	}
 
 	/* THCTR Bit6: PONM=0 , Bit0: THSST=0   */
-	data_l = mmio_read_32(THS1_THCTR) & 0xFFFFFFBE;
+	data_l = mmio_read_32(THS1_THCTR);
+	if (data_l & 0x00000040U) {
+		data_l = data_l & 0xFFFFFFBEU;
+	} else {
+		data_l = data_l | BIT(1);
+	}
+
 	mmio_write_32(THS1_THCTR, data_l);
 
 	/* Judge product and cut */
diff --git a/drivers/renesas/common/ddr/ddr_b/boot_init_dram_config.c b/drivers/renesas/common/ddr/ddr_b/boot_init_dram_config.c
index 45b6b08..bbb0200 100644
--- a/drivers/renesas/common/ddr/ddr_b/boot_init_dram_config.c
+++ b/drivers/renesas/common/ddr/ddr_b/boot_init_dram_config.c
@@ -12,6 +12,9 @@
 #if (RZG_SOC == 1)
 #define BOARDNUM 4
 #else
+
+#include <board.h>
+
 #define BOARDNUM 22
 #endif /* RZG_SOC == 1 */
 #define BOARD_JUDGE_AUTO
@@ -1967,6 +1970,44 @@
 }
 #endif /* RZG_SOC == 1 */
 
+#if (RZG_SOC == 0) && (RCAR_DRAM_LPDDR4_MEMCONF != 0)
+static uint32_t ddr_rank_judge(void)
+{
+	uint32_t brd;
+
+#if (RCAR_DRAM_MEMRANK == 0)
+	int32_t ret;
+	uint32_t type = 0U;
+	uint32_t rev = 0U;
+
+	brd = 99U;
+	ret = rcar_get_board_type(&type, &rev);
+	if ((ret == 0) && (rev != 0xFFU)) {
+		if (type == (uint32_t)BOARD_SALVATOR_XS) {
+			if (rev == 0x11U) {
+				brd = 14U;
+			} else {
+				brd = 8U;
+			}
+		} else if (type == (uint32_t)BOARD_STARTER_KIT_PRE) {
+			if (rev == 0x21U) {
+				brd = 14U;
+			} else {
+				brd = 8U;
+			}
+		}
+	}
+#elif (RCAR_DRAM_MEMRANK == 1)
+	brd = 14U;
+#elif (RCAR_DRAM_MEMRANK == 2)
+	brd = 8U;
+#else
+#error Invalid value was set to RCAR_DRAM_MEMRANK
+#endif /* (RCAR_DRAM_MEMRANK == 0) */
+	return brd;
+}
+#endif /* (RCAR_DRAM_LPDDR4_MEMCONF != 0) */
+
 static uint32_t _board_judge(void)
 {
 	uint32_t brd;
@@ -1985,7 +2026,7 @@
 #if (RCAR_DRAM_LPDDR4_MEMCONF == 0)
 			brd = 7;
 #else
-			brd = 8;
+			brd = ddr_rank_judge();
 #endif
 		}
 	} else if (prr_product == PRR_PRODUCT_M3) {
@@ -2039,7 +2080,7 @@
 #if (RCAR_DRAM_LPDDR4_MEMCONF == 0)
 				brd = 7;
 #else
-				brd = 8;
+				brd = ddr_rank_judge();
 #endif
 			}
 		} else if (prr_product == PRR_PRODUCT_M3N) {
diff --git a/drivers/renesas/common/ddr/ddr_b/boot_init_dram_regdef.h b/drivers/renesas/common/ddr/ddr_b/boot_init_dram_regdef.h
index 56363eb..3cb1975 100644
--- a/drivers/renesas/common/ddr/ddr_b/boot_init_dram_regdef.h
+++ b/drivers/renesas/common/ddr/ddr_b/boot_init_dram_regdef.h
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2015-2020, Renesas Electronics Corporation.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation.
  * All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#define RCAR_DDR_VERSION	"rev.0.40"
+#define RCAR_DDR_VERSION	"rev.0.41"
 #define DRAM_CH_CNT		0x04
 #define SLICE_CNT		0x04
 #define CS_CNT			0x02
diff --git a/drivers/renesas/common/emmc/emmc_init.c b/drivers/renesas/common/emmc/emmc_init.c
index 354aa3c..c0ec600 100644
--- a/drivers/renesas/common/emmc/emmc_init.c
+++ b/drivers/renesas/common/emmc/emmc_init.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,6 +14,7 @@
 #include "emmc_registers.h"
 #include "emmc_def.h"
 #include "rcar_private.h"
+#include "cpg_registers.h"
 
 st_mmc_base mmc_drv_obj;
 
@@ -87,11 +88,11 @@
 	SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR);	/* all interrupt disable */
 	SETR_32(SD_CLK_CTRL, 0x00000000U);	/* MMC clock stop */
 
-	dataL = mmio_read_32(CPG_SMSTPCR3);
+	dataL = mmio_read_32(SMSTPCR3);
 	if ((dataL & CPG_MSTP_MMC) == 0U) {
 		dataL |= (CPG_MSTP_MMC);
 		mmio_write_32(CPG_CPGWPR, (~dataL));
-		mmio_write_32(CPG_SMSTPCR3, dataL);
+		mmio_write_32(SMSTPCR3, dataL);
 	}
 
 	return result;
@@ -100,7 +101,7 @@
 static EMMC_ERROR_CODE emmc_dev_init(void)
 {
 	/* Enable clock supply to eMMC. */
-	mstpcr_write(CPG_SMSTPCR3, CPG_MSTPSR3, CPG_MSTP_MMC);
+	mstpcr_write(SMSTPCR3, CPG_MSTPSR3, CPG_MSTP_MMC);
 
 	/* Set SD clock */
 	mmio_write_32(CPG_CPGWPR, ~((uint32_t) (BIT9 | BIT0)));	/* SD phy 200MHz */
diff --git a/drivers/renesas/common/emmc/emmc_registers.h b/drivers/renesas/common/emmc/emmc_registers.h
index 7fae5e4..67d285d 100644
--- a/drivers/renesas/common/emmc/emmc_registers.h
+++ b/drivers/renesas/common/emmc/emmc_registers.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -50,19 +50,6 @@
 #define BIT30	(0x40000000U)
 #define BIT31	(0x80000000U)
 
-/* Clock Pulse Generator (CPG) registers */
-#define CPG_BASE	(0xE6150000U)
-/* Module stop status register 3 */
-#define CPG_MSTPSR3	(CPG_BASE + 0x0048U)
-/* System module stop control register 3 */
-#define CPG_SMSTPCR3	(CPG_BASE + 0x013CU)
-/* SDHI2 clock frequency control register */
-#define CPG_SD2CKCR	(CPG_BASE + 0x0268U)
-/* SDHI3 clock frequency control register */
-#define CPG_SD3CKCR	(CPG_BASE + 0x026CU)
-/* CPG Write Protect Register */
-#define CPG_CPGWPR	(CPG_BASE + 0x0900U)
-
 #if USE_MMC_CH == MMC_CH0
 #define CPG_SDxCKCR		(CPG_SD2CKCR)	/* SDHI2/MMC0 */
 #else /* USE_MMC_CH == MMC_CH0 */
diff --git a/drivers/renesas/common/iic_dvfs/iic_dvfs.c b/drivers/renesas/common/iic_dvfs/iic_dvfs.c
index e1c9a5b..bf80697 100644
--- a/drivers/renesas/common/iic_dvfs/iic_dvfs.c
+++ b/drivers/renesas/common/iic_dvfs/iic_dvfs.c
@@ -517,7 +517,7 @@
 	uint32_t err = 0U;
 
 	mstpcr_write(SCMSTPCR9, CPG_MSTPSR9, CPG_BIT_SMSTPCR9_DVFS);
-	mmio_write_8(IIC_DVFS_REG_ICCR, 0U);
+	mmio_write_8(IIC_DVFS_REG_ICCR, 1U);
 again:
 	switch (state) {
 	case DVFS_START:
@@ -557,7 +557,7 @@
 	uint32_t err = 0U;
 
 	mstpcr_write(SCMSTPCR9, CPG_MSTPSR9, CPG_BIT_SMSTPCR9_DVFS);
-	mmio_write_8(IIC_DVFS_REG_ICCR, 0U);
+	mmio_write_8(IIC_DVFS_REG_ICCR, 1U);
 again:
 	switch (state) {
 	case DVFS_START:
diff --git a/drivers/renesas/common/pwrc/pwrc.c b/drivers/renesas/common/pwrc/pwrc.c
index c0f015f..3f60fe6 100644
--- a/drivers/renesas/common/pwrc/pwrc.c
+++ b/drivers/renesas/common/pwrc/pwrc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -20,6 +20,7 @@
 #include "pwrc.h"
 #include "rcar_def.h"
 #include "rcar_private.h"
+#include "cpg_registers.h"
 
 /*
  * Someday there will be a generic power controller api. At the moment each
@@ -238,7 +239,7 @@
 	scu_power_up(mpidr);
 	cpu = mpidr & MPIDR_CPU_MASK;
 	on_data = 1 << cpu;
-	mmio_write_32(RCAR_CPGWPR, ~on_data);
+	mmio_write_32(CPG_CPGWPR, ~on_data);
 	mmio_write_32(on_reg, on_data);
 	mmio_write_32(res_reg, res_data & (~(1 << (3 - cpu))));
 
@@ -260,7 +261,7 @@
 	if (read_mpidr_el1() != mpidr)
 		panic();
 
-	mmio_write_32(RCAR_CPGWPR, ~CPU_PWR_OFF);
+	mmio_write_32(CPG_CPGWPR, ~CPU_PWR_OFF);
 	mmio_write_32(reg + cpu * 0x0010, CPU_PWR_OFF);
 
 	rcar_lock_release();
diff --git a/drivers/renesas/rcar/board/board.c b/drivers/renesas/rcar/board/board.c
index cd194ff..dbbaed6 100644
--- a/drivers/renesas/rcar/board/board.c
+++ b/drivers/renesas/rcar/board/board.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights
  * reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -30,9 +30,9 @@
 #define BOARD_CODE_SHIFT	(0x03)
 #define BOARD_ID_UNKNOWN	(0xFF)
 
-#define SXS_ID	{ 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
+#define SXS_ID	{ 0x10U, 0x11U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
 #define SX_ID	{ 0x10U, 0x11U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
-#define SKP_ID	{ 0x10U, 0x10U, 0x20U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
+#define SKP_ID	{ 0x10U, 0x10U, 0x20U, 0x21U, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
 #define SK_ID	{ 0x10U, 0x30U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
 #define EB4_ID	{ 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
 #define EB_ID	{ 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }
diff --git a/fdts/stm32mp15-bl2.dtsi b/fdts/stm32mp15-bl2.dtsi
new file mode 100644
index 0000000..da95b25
--- /dev/null
+++ b/fdts/stm32mp15-bl2.dtsi
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2020-2021 - All Rights Reserved
+ */
+
+/ {
+	cpus {
+		/delete-node/ cpu@1;
+	};
+
+	/delete-node/ psci;
+
+	soc {
+		/delete-node/ timer@40006000;
+		/delete-node/ timer@44006000;
+		/delete-node/ pwr_mcu@50001014;
+		/delete-node/ cryp@54001000;
+		/delete-node/ rng@54003000;
+		/delete-node/ spi@5c001000;
+		/delete-node/ rtc@5c004000;
+		/delete-node/ etzpc@5c007000;
+		/delete-node/ stgen@5c008000;
+		/delete-node/ i2c@5c009000;
+		/delete-node/ tamp@5c00a000;
+
+		pin-controller@50002000 {
+			/delete-node/ rtc-out2-rmp-pins-0;
+		};
+	};
+
+#if !STM32MP_USE_STM32IMAGE
+	/*
+	 * UUID's here are UUID RFC 4122 compliant meaning fieds are stored in
+	 * network order (big endian)
+	 */
+
+	st-io_policies {
+		fip-handles {
+			compatible = "st,io-fip-handle";
+			fw_cfg_uuid = "5807e16a-8459-47be-8ed5-648e8dddab0e";
+			bl32_uuid = "05d0e189-53dc-1347-8d2b-500a4b7a3e38";
+			bl32_extra1_uuid = "0b70c29b-2a5a-7840-9f65-0a5682738288";
+			bl32_extra2_uuid = "8ea87bb1-cfa2-3f4d-85fd-e7bba50220d9";
+			bl33_uuid = "d6d0eea7-fcea-d54b-9782-9934f234b6e4";
+			hw_cfg_uuid = "08b8f1d9-c9cf-9349-a962-6fbc6b7265cc";
+			tos_fw_cfg_uuid = "26257c1a-dbc6-7f47-8d96-c4c4b0248021";
+			nt_fw_cfg_uuid = "28da9815-93e8-7e44-ac66-1aaf801550f9";
+		};
+	};
+#endif /* !STM32MP_USE_STM32IMAGE */
+};
diff --git a/fdts/stm32mp15-bl32.dtsi b/fdts/stm32mp15-bl32.dtsi
new file mode 100644
index 0000000..f005d56
--- /dev/null
+++ b/fdts/stm32mp15-bl32.dtsi
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2020-2021 - All Rights Reserved
+ */
+
+/ {
+	aliases {
+		/delete-property/ mmc0;
+		/delete-property/ mmc1;
+	};
+
+	cpus {
+		/delete-node/ cpu@1;
+	};
+
+	/delete-node/ psci;
+
+	soc {
+		/delete-node/ usb-otg@49000000;
+		/delete-node/ hash@54002000;
+		/delete-node/ memory-controller@58002000;
+		/delete-node/ spi@58003000;
+		/delete-node/ sdmmc@58005000;
+		/delete-node/ sdmmc@58007000;
+		/delete-node/ usbphyc@5a006000;
+		/delete-node/ spi@5c001000;
+		/delete-node/ stgen@5c008000;
+		/delete-node/ i2c@5c009000;
+
+		pin-controller@50002000 {
+			/delete-node/ fmc-0;
+			/delete-node/ qspi-clk-0;
+			/delete-node/ qspi-bk1-0;
+			/delete-node/ qspi-bk2-0;
+			/delete-node/ sdmmc1-b4-0;
+			/delete-node/ sdmmc1-dir-0;
+			/delete-node/ sdmmc2-b4-0;
+			/delete-node/ sdmmc2-b4-1;
+			/delete-node/ sdmmc2-d47-0;
+			/delete-node/ usbotg_hs-0;
+			/delete-node/ usbotg-fs-dp-dm-0;
+		};
+	};
+};
diff --git a/fdts/stm32mp15-fw-config.dtsi b/fdts/stm32mp15-fw-config.dtsi
new file mode 100644
index 0000000..8aece28
--- /dev/null
+++ b/fdts/stm32mp15-fw-config.dtsi
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common/tbbr/tbbr_img_def.h>
+#include <dt-bindings/soc/stm32mp15-tzc400.h>
+
+#include <platform_def.h>
+
+#ifndef DDR_SIZE
+#error "DDR_SIZE is not defined"
+#endif
+
+#define DDR_NS_BASE	STM32MP_DDR_BASE
+#ifdef AARCH32_SP_OPTEE
+/* OP-TEE reserved shared memory: located at DDR top */
+#define DDR_SHARE_SIZE	STM32MP_DDR_SHMEM_SIZE
+#define DDR_SHARE_BASE	(STM32MP_DDR_BASE + (DDR_SIZE - DDR_SHARE_SIZE))
+/* OP-TEE secure memory: located right below OP-TEE reserved shared memory */
+#define DDR_SEC_SIZE	STM32MP_DDR_S_SIZE
+#define DDR_SEC_BASE	(DDR_SHARE_BASE - DDR_SEC_SIZE)
+#define DDR_NS_SIZE	(DDR_SEC_BASE - DDR_NS_BASE)
+#else /* !AARCH32_SP_OPTEE */
+#define DDR_NS_SIZE	DDR_SIZE
+#endif /* AARCH32_SP_OPTEE */
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "fconf,dyn_cfg-dtb_registry";
+
+		hw-config {
+			load-address = <0x0 STM32MP_HW_CONFIG_BASE>;
+			max-size = <STM32MP_HW_CONFIG_MAX_SIZE>;
+			id = <HW_CONFIG_ID>;
+		};
+
+		nt_fw {
+			load-address = <0x0 STM32MP_BL33_BASE>;
+			max-size = <STM32MP_BL33_MAX_SIZE>;
+			id = <BL33_IMAGE_ID>;
+		};
+
+#ifdef AARCH32_SP_OPTEE
+		tos_fw {
+			load-address = <0x0 STM32MP_OPTEE_BASE>;
+			max-size = <STM32MP_OPTEE_SIZE>;
+			id = <BL32_IMAGE_ID>;
+		};
+#else
+		tos_fw {
+			load-address = <0x0 STM32MP_BL32_BASE>;
+			max-size = <STM32MP_BL32_SIZE>;
+			id = <BL32_IMAGE_ID>;
+		};
+
+		tos_fw-config {
+			load-address = <0x0 STM32MP_BL32_DTB_BASE>;
+			max-size = <STM32MP_BL32_DTB_SIZE>;
+			id = <TOS_FW_CONFIG_ID>;
+		};
+#endif
+	};
+
+	st-mem-firewall {
+		compatible = "st,mem-firewall";
+#ifdef AARCH32_SP_OPTEE
+		memory-ranges = <
+			DDR_NS_BASE DDR_NS_SIZE TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR
+			DDR_SEC_BASE DDR_SEC_SIZE TZC_REGION_S_RDWR 0
+			DDR_SHARE_BASE DDR_SHARE_SIZE TZC_REGION_S_NONE
+			TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID)>;
+#else
+		memory-ranges = <
+			DDR_NS_BASE DDR_NS_SIZE TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR>;
+#endif
+	};
+};
diff --git a/fdts/stm32mp157a-avenger96-fw-config.dts b/fdts/stm32mp157a-avenger96-fw-config.dts
new file mode 100644
index 0000000..2abbe50
--- /dev/null
+++ b/fdts/stm32mp157a-avenger96-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157a-dk1-fw-config.dts b/fdts/stm32mp157a-dk1-fw-config.dts
new file mode 100644
index 0000000..83116d1
--- /dev/null
+++ b/fdts/stm32mp157a-dk1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x20000000 /* 512MB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157a-ed1-fw-config.dts b/fdts/stm32mp157a-ed1-fw-config.dts
new file mode 100644
index 0000000..2abbe50
--- /dev/null
+++ b/fdts/stm32mp157a-ed1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157a-ev1-fw-config.dts b/fdts/stm32mp157a-ev1-fw-config.dts
new file mode 100644
index 0000000..2abbe50
--- /dev/null
+++ b/fdts/stm32mp157a-ev1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157c-dk2-fw-config.dts b/fdts/stm32mp157c-dk2-fw-config.dts
new file mode 100644
index 0000000..83116d1
--- /dev/null
+++ b/fdts/stm32mp157c-dk2-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x20000000 /* 512MB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157c-ed1-fw-config.dts b/fdts/stm32mp157c-ed1-fw-config.dts
new file mode 100644
index 0000000..2abbe50
--- /dev/null
+++ b/fdts/stm32mp157c-ed1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157c-ev1-fw-config.dts b/fdts/stm32mp157c-ev1-fw-config.dts
new file mode 100644
index 0000000..2abbe50
--- /dev/null
+++ b/fdts/stm32mp157c-ev1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157c-lxa-mc1-fw-config.dts b/fdts/stm32mp157c-lxa-mc1-fw-config.dts
new file mode 100644
index 0000000..9ee09e9
--- /dev/null
+++ b/fdts/stm32mp157c-lxa-mc1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x20000000 /* 512MB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157c-odyssey-fw-config.dts b/fdts/stm32mp157c-odyssey-fw-config.dts
new file mode 100644
index 0000000..9ee09e9
--- /dev/null
+++ b/fdts/stm32mp157c-odyssey-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x20000000 /* 512MB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157d-dk1-fw-config.dts b/fdts/stm32mp157d-dk1-fw-config.dts
new file mode 100644
index 0000000..83116d1
--- /dev/null
+++ b/fdts/stm32mp157d-dk1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x20000000 /* 512MB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157d-ed1-fw-config.dts b/fdts/stm32mp157d-ed1-fw-config.dts
new file mode 100644
index 0000000..2abbe50
--- /dev/null
+++ b/fdts/stm32mp157d-ed1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157d-ev1-fw-config.dts b/fdts/stm32mp157d-ev1-fw-config.dts
new file mode 100644
index 0000000..2abbe50
--- /dev/null
+++ b/fdts/stm32mp157d-ev1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157f-dk2-fw-config.dts b/fdts/stm32mp157f-dk2-fw-config.dts
new file mode 100644
index 0000000..83116d1
--- /dev/null
+++ b/fdts/stm32mp157f-dk2-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x20000000 /* 512MB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157f-ed1-fw-config.dts b/fdts/stm32mp157f-ed1-fw-config.dts
new file mode 100644
index 0000000..2abbe50
--- /dev/null
+++ b/fdts/stm32mp157f-ed1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157f-ev1-fw-config.dts b/fdts/stm32mp157f-ev1-fw-config.dts
new file mode 100644
index 0000000..2abbe50
--- /dev/null
+++ b/fdts/stm32mp157f-ev1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/tc0.dts b/fdts/tc.dts
similarity index 99%
rename from fdts/tc0.dts
rename to fdts/tc.dts
index 9051b7b..f66d556 100644
--- a/fdts/tc0.dts
+++ b/fdts/tc.dts
@@ -7,7 +7,7 @@
 /dts-v1/;
 
 / {
-	compatible = "arm,tc0";
+	compatible = "arm,tc";
 	interrupt-parent = <&gic>;
 	#address-cells = <2>;
 	#size-cells = <2>;
diff --git a/include/common/debug.h b/include/common/debug.h
index ed0e8bf..a7ca0d7 100644
--- a/include/common/debug.h
+++ b/include/common/debug.h
@@ -61,8 +61,10 @@
 
 #if LOG_LEVEL >= LOG_LEVEL_ERROR
 # define ERROR(...)	tf_log(LOG_MARKER_ERROR __VA_ARGS__)
+# define ERROR_NL()	tf_log_newline(LOG_MARKER_ERROR)
 #else
 # define ERROR(...)	no_tf_log(LOG_MARKER_ERROR __VA_ARGS__)
+# define ERROR_NL()
 #endif
 
 #if LOG_LEVEL >= LOG_LEVEL_NOTICE
@@ -109,6 +111,7 @@
 void __dead2 __stack_chk_fail(void);
 
 void tf_log(const char *fmt, ...) __printflike(1, 2);
+void tf_log_newline(const char log_fmt[2]);
 void tf_log_set_max_level(unsigned int log_level);
 
 #endif /* __ASSEMBLER__ */
diff --git a/include/common/hw_crc32.h b/include/common/tf_crc32.h
similarity index 62%
rename from include/common/hw_crc32.h
rename to include/common/tf_crc32.h
index 0d14d57..38c56a5 100644
--- a/include/common/hw_crc32.h
+++ b/include/common/tf_crc32.h
@@ -4,13 +4,13 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#ifndef HW_CRC32_H
-#define HW_CRC32_H
+#ifndef TF_CRC32_H
+#define TF_CRC32_H
 
 #include <stddef.h>
 #include <stdint.h>
 
 /* compute CRC using Arm intrinsic function */
-uint32_t hw_crc32(uint32_t crc, const unsigned char *buf, size_t size);
+uint32_t tf_crc32(uint32_t crc, const unsigned char *buf, size_t size);
 
-#endif /* HW_CRC32_H */
+#endif /* TF_CRC32_H */
diff --git a/include/drivers/arm/arm_gicv3_common.h b/include/drivers/arm/arm_gicv3_common.h
index b88b59f..e5df311 100644
--- a/include/drivers/arm/arm_gicv3_common.h
+++ b/include/drivers/arm/arm_gicv3_common.h
@@ -17,4 +17,8 @@
 #define WAKER_SL_BIT		(1U << WAKER_SL_SHIFT)
 #define WAKER_QSC_BIT		(1U << WAKER_QSC_SHIFT)
 
+#define IIDR_MODEL_ARM_GIC_600		U(0x0200043b)
+#define IIDR_MODEL_ARM_GIC_600AE	U(0x0300043b)
+#define IIDR_MODEL_ARM_GIC_700		U(0x0400043b)
+
 #endif /* ARM_GICV3_COMMON_H */
diff --git a/include/drivers/arm/gic600ae_fmu.h b/include/drivers/arm/gic600ae_fmu.h
new file mode 100644
index 0000000..691ffc7
--- /dev/null
+++ b/include/drivers/arm/gic600ae_fmu.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef GIC600AE_FMU_H
+#define GIC600AE_FMU_H
+
+/*******************************************************************************
+ * GIC600-AE FMU register offsets and constants
+ ******************************************************************************/
+#define GICFMU_ERRFR_LO		U(0x000)
+#define GICFMU_ERRFR_HI		U(0x004)
+#define GICFMU_ERRCTLR_LO	U(0x008)
+#define GICFMU_ERRCTLR_HI	U(0x00C)
+#define GICFMU_ERRSTATUS_LO	U(0x010)
+#define GICFMU_ERRSTATUS_HI	U(0x014)
+#define GICFMU_ERRGSR_LO	U(0xE00)
+#define GICFMU_ERRGSR_HI	U(0xE04)
+#define GICFMU_KEY		U(0xEA0)
+#define GICFMU_PINGCTLR		U(0xEA4)
+#define GICFMU_PINGNOW		U(0xEA8)
+#define GICFMU_SMEN		U(0xEB0)
+#define GICFMU_SMINJERR		U(0xEB4)
+#define GICFMU_PINGMASK_LO	U(0xEC0)
+#define GICFMU_PINGMASK_HI	U(0xEC4)
+#define GICFMU_STATUS		U(0xF00)
+#define GICFMU_ERRIDR		U(0xFC8)
+
+/* ERRCTLR bits */
+#define FMU_ERRCTLR_ED_BIT	BIT(0)
+#define FMU_ERRCTLR_CE_EN_BIT	BIT(1)
+#define FMU_ERRCTLR_UI_BIT	BIT(2)
+#define FMU_ERRCTLR_CI_BIT	BIT(3)
+
+/* SMEN constants */
+#define FMU_SMEN_BLK_SHIFT	U(8)
+#define FMU_SMEN_SMID_SHIFT	U(24)
+
+/* Error record IDs */
+#define FMU_BLK_GICD		U(0)
+#define FMU_BLK_SPICOL		U(1)
+#define FMU_BLK_WAKERQ		U(2)
+#define FMU_BLK_ITS0		U(4)
+#define FMU_BLK_ITS1		U(5)
+#define FMU_BLK_ITS2		U(6)
+#define FMU_BLK_ITS3		U(7)
+#define FMU_BLK_ITS4		U(8)
+#define FMU_BLK_ITS5		U(9)
+#define FMU_BLK_ITS6		U(10)
+#define FMU_BLK_ITS7		U(11)
+#define FMU_BLK_PPI0		U(12)
+#define FMU_BLK_PPI1		U(13)
+#define FMU_BLK_PPI2		U(14)
+#define FMU_BLK_PPI3		U(15)
+#define FMU_BLK_PPI4		U(16)
+#define FMU_BLK_PPI5		U(17)
+#define FMU_BLK_PPI6		U(18)
+#define FMU_BLK_PPI7		U(19)
+#define FMU_BLK_PPI8		U(20)
+#define FMU_BLK_PPI9		U(21)
+#define FMU_BLK_PPI10		U(22)
+#define FMU_BLK_PPI11		U(23)
+#define FMU_BLK_PPI12		U(24)
+#define FMU_BLK_PPI13		U(25)
+#define FMU_BLK_PPI14		U(26)
+#define FMU_BLK_PPI15		U(27)
+#define FMU_BLK_PPI16		U(28)
+#define FMU_BLK_PPI17		U(29)
+#define FMU_BLK_PPI18		U(30)
+#define FMU_BLK_PPI19		U(31)
+#define FMU_BLK_PPI20		U(32)
+#define FMU_BLK_PPI21		U(33)
+#define FMU_BLK_PPI22		U(34)
+#define FMU_BLK_PPI23		U(35)
+#define FMU_BLK_PPI24		U(36)
+#define FMU_BLK_PPI25		U(37)
+#define FMU_BLK_PPI26		U(38)
+#define FMU_BLK_PPI27		U(39)
+#define FMU_BLK_PPI28		U(40)
+#define FMU_BLK_PPI29		U(41)
+#define FMU_BLK_PPI30		U(42)
+#define FMU_BLK_PPI31		U(43)
+#define FMU_BLK_PRESENT_MASK	U(0xFFFFFFFFFFF)
+
+/* Safety Mechamism limit */
+#define FMU_SMID_GICD_MAX	U(33)
+#define FMU_SMID_SPICOL_MAX	U(5)
+#define FMU_SMID_WAKERQ_MAX	U(2)
+#define FMU_SMID_ITS_MAX	U(14)
+#define FMU_SMID_PPI_MAX	U(12)
+
+/* MBIST Safety Mechanism ID */
+#define GICD_MBIST_REQ_ERROR	U(23)
+#define GICD_FMU_CLKGATE_ERROR	U(33)
+#define PPI_MBIST_REQ_ERROR	U(10)
+#define PPI_FMU_CLKGATE_ERROR	U(12)
+#define ITS_MBIST_REQ_ERROR	U(13)
+#define ITS_FMU_CLKGATE_ERROR	U(14)
+
+/* ERRSTATUS bits */
+#define FMU_ERRSTATUS_V_BIT	BIT(30)
+#define FMU_ERRSTATUS_UE_BIT	BIT(29)
+#define FMU_ERRSTATUS_OV_BIT	BIT(27)
+#define FMU_ERRSTATUS_CE_BITS	(BIT(25) | BIT(24))
+#define FMU_ERRSTATUS_CLEAR	(FMU_ERRSTATUS_V_BIT | FMU_ERRSTATUS_UE_BIT | \
+				 FMU_ERRSTATUS_OV_BIT | FMU_ERRSTATUS_CE_BITS)
+
+/* PINGCTLR constants */
+#define FMU_PINGCTLR_INTDIFF_SHIFT	U(16)
+#define FMU_PINGCTLR_TIMEOUTVAL_SHIFT	U(4)
+#define FMU_PINGCTLR_EN_BIT		BIT(0)
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+#include <arch_helpers.h>
+
+/*******************************************************************************
+ * GIC600 FMU EL3 driver API
+ ******************************************************************************/
+uint64_t gic_fmu_read_errfr(uintptr_t base, unsigned int n);
+uint64_t gic_fmu_read_errctlr(uintptr_t base, unsigned int n);
+uint64_t gic_fmu_read_errstatus(uintptr_t base, unsigned int n);
+uint64_t gic_fmu_read_errgsr(uintptr_t base);
+uint32_t gic_fmu_read_pingctlr(uintptr_t base);
+uint32_t gic_fmu_read_pingnow(uintptr_t base);
+uint64_t gic_fmu_read_pingmask(uintptr_t base);
+uint32_t gic_fmu_read_status(uintptr_t base);
+uint32_t gic_fmu_read_erridr(uintptr_t base);
+void gic_fmu_write_errctlr(uintptr_t base, unsigned int n, uint64_t val);
+void gic_fmu_write_errstatus(uintptr_t base, unsigned int n, uint64_t val);
+void gic_fmu_write_pingctlr(uintptr_t base, uint32_t val);
+void gic_fmu_write_pingnow(uintptr_t base, uint32_t val);
+void gic_fmu_write_smen(uintptr_t base, uint32_t val);
+void gic_fmu_write_sminjerr(uintptr_t base, uint32_t val);
+void gic_fmu_write_pingmask(uintptr_t base, uint64_t val);
+
+void gic600_fmu_init(uint64_t base, uint64_t blk_present_mask, bool errctlr_ce_en, bool errctlr_ue_en);
+void gic600_fmu_enable_ping(uint64_t base, uint64_t blk_present_mask,
+		unsigned int timeout_val, unsigned int interval_diff);
+void gic600_fmu_print_sm_info(uint64_t base, unsigned int blk, unsigned int smid);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* GIC600AE_FMU_H */
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index d8ac4cb..fa8946b 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.h
@@ -153,11 +153,8 @@
 /*******************************************************************************
  * Common GIC Redistributor interface registers & constants
  ******************************************************************************/
-#if GIC_ENABLE_V4_EXTN
-#define GICR_PCPUBASE_SHIFT	0x12
-#else
-#define GICR_PCPUBASE_SHIFT	0x11
-#endif
+#define GICR_V4_PCPUBASE_SHIFT	0x12
+#define GICR_V3_PCPUBASE_SHIFT	0x11
 #define GICR_SGIBASE_OFFSET	U(65536)	/* 64 KB */
 #define GICR_CTLR		U(0x0)
 #define GICR_IIDR		U(0x04)
@@ -212,12 +209,14 @@
 #define TYPER_AFF_VAL_SHIFT	32
 #define TYPER_PROC_NUM_SHIFT	8
 #define TYPER_LAST_SHIFT	4
+#define TYPER_VLPI_SHIFT	1
 
 #define TYPER_AFF_VAL_MASK	U(0xffffffff)
 #define TYPER_PROC_NUM_MASK	U(0xffff)
 #define TYPER_LAST_MASK		U(0x1)
 
 #define TYPER_LAST_BIT		BIT_32(TYPER_LAST_SHIFT)
+#define TYPER_VLPI_BIT		BIT_32(TYPER_VLPI_SHIFT)
 
 #define TYPER_PPI_NUM_SHIFT	U(27)
 #define TYPER_PPI_NUM_MASK	U(0x1f)
@@ -312,6 +311,19 @@
 #include <drivers/arm/gic_common.h>
 #include <lib/utils_def.h>
 
+static inline uintptr_t gicv3_redist_size(uint64_t typer_val)
+{
+#if GIC_ENABLE_V4_EXTN
+	if ((typer_val & TYPER_VLPI_BIT) != 0U) {
+		return 1U << GICR_V4_PCPUBASE_SHIFT;
+	} else {
+		return 1U << GICR_V3_PCPUBASE_SHIFT;
+	}
+#else
+	return 1U << GICR_V3_PCPUBASE_SHIFT;
+#endif
+}
+
 static inline bool gicv3_is_intr_id_special_identifier(unsigned int id)
 {
 	return (id >= PENDING_G1S_INTID) && (id <= GIC_SPURIOUS_INTERRUPT);
diff --git a/include/drivers/arm/tzc400.h b/include/drivers/arm/tzc400.h
index 5f8a48f..765c130 100644
--- a/include/drivers/arm/tzc400.h
+++ b/include/drivers/arm/tzc400.h
@@ -109,6 +109,7 @@
 			  unsigned long long region_top,
 			  unsigned int sec_attr,
 			  unsigned int nsaid_permissions);
+void tzc400_update_filters(unsigned int region, unsigned int filters);
 void tzc400_set_action(unsigned int action);
 void tzc400_enable_filters(void);
 void tzc400_disable_filters(void);
diff --git a/include/drivers/fwu/fwu.h b/include/drivers/fwu/fwu.h
new file mode 100644
index 0000000..ae06da9
--- /dev/null
+++ b/include/drivers/fwu/fwu.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FWU_H
+#define FWU_H
+
+#include <stdbool.h>
+
+void fwu_init(void);
+bool fwu_is_trial_run_state(void);
+
+#endif /* FWU_H */
diff --git a/include/drivers/fwu/fwu_metadata.h b/include/drivers/fwu/fwu_metadata.h
new file mode 100644
index 0000000..2e88de5
--- /dev/null
+++ b/include/drivers/fwu/fwu_metadata.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * FWU metadata information as per the specification section 4.1:
+ * https://developer.arm.com/documentation/den0118/a/
+ *
+ */
+
+#ifndef FWU_METADATA_H
+#define FWU_METADATA_H
+
+#include <stdint.h>
+#include <tools_share/uuid.h>
+
+/* Properties of image in a bank */
+struct fwu_image_properties {
+
+	/* UUID of the image in this bank */
+	uuid_t img_uuid;
+
+	/* [0]: bit describing the image acceptance status –
+	 *      1 means the image is accepted
+	 * [31:1]: MBZ
+	 */
+	uint32_t accepted;
+
+	/* reserved (MBZ) */
+	uint32_t reserved;
+
+} __packed;
+
+/* Image entry information */
+struct fwu_image_entry {
+
+	/* UUID identifying the image type */
+	uuid_t img_type_uuid;
+
+	/* UUID of the storage volume where the image is located */
+	uuid_t location_uuid;
+
+	/* Properties of images with img_type_uuid in the different FW banks */
+	struct fwu_image_properties img_props[NR_OF_FW_BANKS];
+
+} __packed;
+
+/*
+ * FWU metadata filled by the updater and consumed by TF-A for
+ * various purposes as below:
+ * 1. Get active FW bank.
+ * 2. Rollback to previous working FW bank.
+ * 3. Get properties of all images present in all banks.
+ */
+struct fwu_metadata {
+
+	/* Metadata CRC value */
+	uint32_t crc_32;
+
+	/* Metadata version */
+	uint32_t version;
+
+	/* Bank index with which device boots */
+	uint32_t active_index;
+
+	/* Previous bank index with which device booted successfully */
+	uint32_t previous_active_index;
+
+	/* Image entry information */
+	struct fwu_image_entry img_entry[NR_OF_IMAGES_IN_FW_BANK];
+
+} __packed;
+
+#endif /* FWU_METADATA_H */
diff --git a/include/drivers/io/io_mtd.h b/include/drivers/io/io_mtd.h
index 1395ff6..2b5d9b1 100644
--- a/include/drivers/io/io_mtd.h
+++ b/include/drivers/io/io_mtd.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -44,11 +44,22 @@
 	 * Return 0 on success, a negative error code otherwise.
 	 */
 	int (*write)(unsigned int offset, uintptr_t buffer, size_t length);
+
+	/*
+	 * Look for an offset to be added to the given offset.
+	 *
+	 * @base: Base address of the area.
+	 * @offset: Offset in bytes to start read operation.
+	 * @extra_offset: [out] Offset to be added to the previous offset.
+	 * Return 0 on success, a negative error code otherwise.
+	 */
+	int (*seek)(uintptr_t base, unsigned int offset, size_t *extra_offset);
 } io_mtd_ops_t;
 
 typedef struct io_mtd_dev_spec {
 	unsigned long long device_size;
 	unsigned int erase_size;
+	size_t offset;
 	io_mtd_ops_t ops;
 } io_mtd_dev_spec_t;
 
diff --git a/include/drivers/nand.h b/include/drivers/nand.h
index 1dbb008..1b78ad4 100644
--- a/include/drivers/nand.h
+++ b/include/drivers/nand.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -46,6 +46,16 @@
 	      size_t *length_read);
 
 /*
+ * Look for an extra offset to be added in case of bad blocks
+ *
+ * @base: Base address of the area
+ * @offset: Byte offset to read from in device
+ * @extra_offset: [out] Extra offset to be added if bad blocks are found
+ * Return: 0 on success, a negative errno on failure
+ */
+int nand_seek_bb(uintptr_t base, unsigned int offset, size_t *extra_offset);
+
+/*
  * Get NAND device instance
  *
  * Return: NAND device instance reference
diff --git a/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h b/include/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h
similarity index 98%
rename from drivers/nxp/auth/csf_hdr_parser/csf_hdr.h
rename to include/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h
index eaead76..ae56d3b 100644
--- a/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h
+++ b/include/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017-2020 NXP
+ * Copyright 2017-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/console/plat_console.h b/include/drivers/nxp/console/plat_console.h
similarity index 100%
rename from drivers/nxp/console/plat_console.h
rename to include/drivers/nxp/console/plat_console.h
diff --git a/drivers/nxp/crypto/caam/include/caam.h b/include/drivers/nxp/crypto/caam/caam.h
similarity index 97%
rename from drivers/nxp/crypto/caam/include/caam.h
rename to include/drivers/nxp/crypto/caam/caam.h
index 580e133..4984b54 100644
--- a/drivers/nxp/crypto/caam/include/caam.h
+++ b/include/drivers/nxp/crypto/caam/caam.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017-2020 NXP
+ * Copyright 2017-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/crypto/caam/include/caam_io.h b/include/drivers/nxp/crypto/caam/caam_io.h
similarity index 97%
rename from drivers/nxp/crypto/caam/include/caam_io.h
rename to include/drivers/nxp/crypto/caam/caam_io.h
index 4fdb04d..b68f836 100644
--- a/drivers/nxp/crypto/caam/include/caam_io.h
+++ b/include/drivers/nxp/crypto/caam/caam_io.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2020 NXP
+ * Copyright 2018-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/crypto/caam/include/hash.h b/include/drivers/nxp/crypto/caam/hash.h
similarity index 98%
rename from drivers/nxp/crypto/caam/include/hash.h
rename to include/drivers/nxp/crypto/caam/hash.h
index 946087d..9136dca 100644
--- a/drivers/nxp/crypto/caam/include/hash.h
+++ b/include/drivers/nxp/crypto/caam/hash.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017-2020 NXP
+ * Copyright 2017-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/crypto/caam/include/jobdesc.h b/include/drivers/nxp/crypto/caam/jobdesc.h
similarity index 97%
rename from drivers/nxp/crypto/caam/include/jobdesc.h
rename to include/drivers/nxp/crypto/caam/jobdesc.h
index 5921f7b..efef228 100644
--- a/drivers/nxp/crypto/caam/include/jobdesc.h
+++ b/include/drivers/nxp/crypto/caam/jobdesc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017-2020 NXP
+ * Copyright 2017-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/crypto/caam/include/jr_driver_config.h b/include/drivers/nxp/crypto/caam/jr_driver_config.h
similarity index 99%
rename from drivers/nxp/crypto/caam/include/jr_driver_config.h
rename to include/drivers/nxp/crypto/caam/jr_driver_config.h
index f25c42e..1b3c447 100644
--- a/drivers/nxp/crypto/caam/include/jr_driver_config.h
+++ b/include/drivers/nxp/crypto/caam/jr_driver_config.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017-2020 NXP
+ * Copyright 2017-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/crypto/caam/include/rsa.h b/include/drivers/nxp/crypto/caam/rsa.h
similarity index 96%
rename from drivers/nxp/crypto/caam/include/rsa.h
rename to include/drivers/nxp/crypto/caam/rsa.h
index bd5dc71..dd9ecdc 100644
--- a/drivers/nxp/crypto/caam/include/rsa.h
+++ b/include/drivers/nxp/crypto/caam/rsa.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017-2020 NXP
+ * Copyright 2017-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/crypto/caam/include/sec_hw_specific.h b/include/drivers/nxp/crypto/caam/sec_hw_specific.h
similarity index 99%
rename from drivers/nxp/crypto/caam/include/sec_hw_specific.h
rename to include/drivers/nxp/crypto/caam/sec_hw_specific.h
index a82a1a0..a4fc022 100644
--- a/drivers/nxp/crypto/caam/include/sec_hw_specific.h
+++ b/include/drivers/nxp/crypto/caam/sec_hw_specific.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017-2020 NXP
+ * Copyright 2017-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/crypto/caam/include/sec_jr_driver.h b/include/drivers/nxp/crypto/caam/sec_jr_driver.h
similarity index 99%
rename from drivers/nxp/crypto/caam/include/sec_jr_driver.h
rename to include/drivers/nxp/crypto/caam/sec_jr_driver.h
index 1381eab..57e0fa0 100644
--- a/drivers/nxp/crypto/caam/include/sec_jr_driver.h
+++ b/include/drivers/nxp/crypto/caam/sec_jr_driver.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017-2020 NXP
+ * Copyright 2017-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/csu/csu.h b/include/drivers/nxp/csu/csu.h
similarity index 96%
rename from drivers/nxp/csu/csu.h
rename to include/drivers/nxp/csu/csu.h
index 9f82feb..3a43e45 100644
--- a/drivers/nxp/csu/csu.h
+++ b/include/drivers/nxp/csu/csu.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 NXP
+ * Copyright 2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/dcfg/dcfg.h b/include/drivers/nxp/dcfg/dcfg.h
similarity index 71%
rename from drivers/nxp/dcfg/dcfg.h
rename to include/drivers/nxp/dcfg/dcfg.h
index 161e295..524450a 100644
--- a/drivers/nxp/dcfg/dcfg.h
+++ b/include/drivers/nxp/dcfg/dcfg.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2020 NXP
+ * Copyright 2018-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -27,23 +27,41 @@
 #endif
 
 typedef struct {
-	bool is_populated;
-	uint8_t mfr_id;
-#if defined(CONFIG_CHASSIS_3_2)
-	uint8_t family;
-	uint8_t dev_id;
+	union {
+		uint32_t val;
+		struct {
+			uint32_t min_ver:4;
+			uint32_t maj_ver:4;
+#if defined(CONFIG_CHASSIS_3) || defined(CONFIG_CHASSIS_3_2)
+			uint32_t personality:6;
+			uint32_t rsv1:2;
+#elif defined(CONFIG_CHASSIS_2)
+			uint32_t personality:8;
+
 #endif
-	uint8_t personality;
+#if defined(CONFIG_CHASSIS_3) || defined(CONFIG_CHASSIS_3_2)
+			uint32_t dev_id:6;
+			uint32_t rsv2:2;
+			uint32_t family:4;
+#elif defined(CONFIG_CHASSIS_2)
+			uint32_t dev_id:12;
+#endif
+			uint32_t mfr_id;
+		} __packed bf;
+		struct {
+			uint32_t maj_min:8;
+			uint32_t version; /* SoC version without major and minor info */
+		} __packed bf_ver;
+	} __packed svr_reg;
 	bool sec_enabled;
-	uint8_t maj_ver;
-	uint8_t min_ver;
+	bool is_populated;
 } soc_info_t;
 
 typedef struct {
 	bool is_populated;
 	uint8_t ocram_present;
 	uint8_t ddrc1_present;
-#if defined(CONFIG_CHASSIS_3_2)
+#if defined(CONFIG_CHASSIS_3) || defined(CONFIG_CHASSIS_3_2)
 	uint8_t ddrc2_present;
 #endif
 } devdisr5_info_t;
diff --git a/drivers/nxp/dcfg/dcfg_lsch2.h b/include/drivers/nxp/dcfg/dcfg_lsch2.h
similarity index 90%
rename from drivers/nxp/dcfg/dcfg_lsch2.h
rename to include/drivers/nxp/dcfg/dcfg_lsch2.h
index c021aa1..1e56729 100644
--- a/drivers/nxp/dcfg/dcfg_lsch2.h
+++ b/include/drivers/nxp/dcfg/dcfg_lsch2.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 NXP
+ * Copyright 2020-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -34,12 +34,10 @@
 
 #define SVR_MFR_ID_MASK			0xF0000000
 #define SVR_MFR_ID_SHIFT		28
-#define SVR_FAMILY_MASK			0xF000000
-#define SVR_FAMILY_SHIFT		24
-#define SVR_DEV_ID_MASK			0x3F0000
+#define SVR_DEV_ID_MASK			0xFFF0000
 #define SVR_DEV_ID_SHIFT		16
-#define SVR_PERSONALITY_MASK		0x3E00
-#define SVR_PERSONALITY_SHIFT		9
+#define SVR_PERSONALITY_MASK		0xFF00
+#define SVR_PERSONALITY_SHIFT		8
 #define SVR_SEC_MASK			0x100
 #define SVR_SEC_SHIFT			8
 #define SVR_MAJ_VER_MASK		0xF0
diff --git a/drivers/nxp/dcfg/dcfg_lsch3.h b/include/drivers/nxp/dcfg/dcfg_lsch3.h
similarity index 98%
rename from drivers/nxp/dcfg/dcfg_lsch3.h
rename to include/drivers/nxp/dcfg/dcfg_lsch3.h
index 8144542..40f02c1 100644
--- a/drivers/nxp/dcfg/dcfg_lsch3.h
+++ b/include/drivers/nxp/dcfg/dcfg_lsch3.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 NXP
+ * Copyright 2020-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/dcfg/scfg.h b/include/drivers/nxp/dcfg/scfg.h
similarity index 98%
rename from drivers/nxp/dcfg/scfg.h
rename to include/drivers/nxp/dcfg/scfg.h
index 81df9a6..b6e3df5 100644
--- a/drivers/nxp/dcfg/scfg.h
+++ b/include/drivers/nxp/dcfg/scfg.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 NXP
+ * Copyright 2020-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/ddr/include/ddr.h b/include/drivers/nxp/ddr/ddr.h
similarity index 100%
rename from drivers/nxp/ddr/include/ddr.h
rename to include/drivers/nxp/ddr/ddr.h
diff --git a/drivers/nxp/ddr/include/ddr_io.h b/include/drivers/nxp/ddr/ddr_io.h
similarity index 100%
rename from drivers/nxp/ddr/include/ddr_io.h
rename to include/drivers/nxp/ddr/ddr_io.h
diff --git a/drivers/nxp/ddr/include/dimm.h b/include/drivers/nxp/ddr/dimm.h
similarity index 100%
rename from drivers/nxp/ddr/include/dimm.h
rename to include/drivers/nxp/ddr/dimm.h
diff --git a/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h b/include/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h
similarity index 100%
rename from drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h
rename to include/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h
diff --git a/drivers/nxp/ddr/include/immap.h b/include/drivers/nxp/ddr/immap.h
similarity index 100%
rename from drivers/nxp/ddr/include/immap.h
rename to include/drivers/nxp/ddr/immap.h
diff --git a/drivers/nxp/ddr/include/opts.h b/include/drivers/nxp/ddr/opts.h
similarity index 100%
rename from drivers/nxp/ddr/include/opts.h
rename to include/drivers/nxp/ddr/opts.h
diff --git a/drivers/nxp/ddr/include/regs.h b/include/drivers/nxp/ddr/regs.h
similarity index 100%
rename from drivers/nxp/ddr/include/regs.h
rename to include/drivers/nxp/ddr/regs.h
diff --git a/drivers/nxp/ddr/include/utility.h b/include/drivers/nxp/ddr/utility.h
similarity index 100%
rename from drivers/nxp/ddr/include/utility.h
rename to include/drivers/nxp/ddr/utility.h
diff --git a/drivers/nxp/gic/include/gicv2/plat_gic.h b/include/drivers/nxp/gic/gicv2/plat_gic.h
similarity index 100%
rename from drivers/nxp/gic/include/gicv2/plat_gic.h
rename to include/drivers/nxp/gic/gicv2/plat_gic.h
diff --git a/drivers/nxp/gic/include/gicv3/plat_gic.h b/include/drivers/nxp/gic/gicv3/plat_gic.h
similarity index 100%
rename from drivers/nxp/gic/include/gicv3/plat_gic.h
rename to include/drivers/nxp/gic/gicv3/plat_gic.h
diff --git a/drivers/nxp/gpio/nxp_gpio.h b/include/drivers/nxp/gpio/nxp_gpio.h
similarity index 100%
rename from drivers/nxp/gpio/nxp_gpio.h
rename to include/drivers/nxp/gpio/nxp_gpio.h
diff --git a/drivers/nxp/i2c/i2c.h b/include/drivers/nxp/i2c/i2c.h
similarity index 97%
rename from drivers/nxp/i2c/i2c.h
rename to include/drivers/nxp/i2c/i2c.h
index 925bbc0..85e6eb4 100644
--- a/drivers/nxp/i2c/i2c.h
+++ b/include/drivers/nxp/i2c/i2c.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2020 NXP
+ * Copyright 2016-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/interconnect/ls_interconnect.h b/include/drivers/nxp/interconnect/ls_interconnect.h
similarity index 92%
rename from drivers/nxp/interconnect/ls_interconnect.h
rename to include/drivers/nxp/interconnect/ls_interconnect.h
index 26787fb..777089c 100644
--- a/drivers/nxp/interconnect/ls_interconnect.h
+++ b/include/drivers/nxp/interconnect/ls_interconnect.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 NXP
+ * Copyright 2020-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/pmu/pmu.h b/include/drivers/nxp/pmu/pmu.h
similarity index 100%
rename from drivers/nxp/pmu/pmu.h
rename to include/drivers/nxp/pmu/pmu.h
diff --git a/drivers/nxp/qspi/qspi.h b/include/drivers/nxp/qspi/qspi.h
similarity index 100%
rename from drivers/nxp/qspi/qspi.h
rename to include/drivers/nxp/qspi/qspi.h
diff --git a/drivers/nxp/sd/sd_mmc.h b/include/drivers/nxp/sd/sd_mmc.h
similarity index 99%
rename from drivers/nxp/sd/sd_mmc.h
rename to include/drivers/nxp/sd/sd_mmc.h
index 29ad328..32b41f1 100644
--- a/drivers/nxp/sd/sd_mmc.h
+++ b/include/drivers/nxp/sd/sd_mmc.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2015, 2016 Freescale Semiconductor, Inc.
- * Copyright 2017-2020 NXP
+ * Copyright 2017-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
diff --git a/drivers/nxp/sec_mon/snvs.h b/include/drivers/nxp/sec_mon/snvs.h
similarity index 100%
rename from drivers/nxp/sec_mon/snvs.h
rename to include/drivers/nxp/sec_mon/snvs.h
diff --git a/drivers/nxp/sfp/fuse_prov.h b/include/drivers/nxp/sfp/fuse_prov.h
similarity index 100%
rename from drivers/nxp/sfp/fuse_prov.h
rename to include/drivers/nxp/sfp/fuse_prov.h
diff --git a/drivers/nxp/sfp/sfp.h b/include/drivers/nxp/sfp/sfp.h
similarity index 100%
rename from drivers/nxp/sfp/sfp.h
rename to include/drivers/nxp/sfp/sfp.h
diff --git a/drivers/nxp/sfp/sfp_error_codes.h b/include/drivers/nxp/sfp/sfp_error_codes.h
similarity index 100%
rename from drivers/nxp/sfp/sfp_error_codes.h
rename to include/drivers/nxp/sfp/sfp_error_codes.h
diff --git a/drivers/nxp/timer/nxp_timer.h b/include/drivers/nxp/timer/nxp_timer.h
similarity index 100%
rename from drivers/nxp/timer/nxp_timer.h
rename to include/drivers/nxp/timer/nxp_timer.h
diff --git a/drivers/nxp/tzc/plat_tzc400.h b/include/drivers/nxp/tzc/plat_tzc400.h
similarity index 100%
rename from drivers/nxp/tzc/plat_tzc400.h
rename to include/drivers/nxp/tzc/plat_tzc400.h
diff --git a/include/dt-bindings/soc/stm32mp15-tzc400.h b/include/dt-bindings/soc/stm32mp15-tzc400.h
new file mode 100644
index 0000000..54cd902
--- /dev/null
+++ b/include/dt-bindings/soc/stm32mp15-tzc400.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (C) 2021, STMicroelectronics - All Rights Reserved
+ */
+
+#ifndef _DT_BINDINGS_STM32MP15_TZC400_H
+#define _DT_BINDINGS_STM32MP15_TZC400_H
+
+#include <drivers/arm/tzc_common.h>
+
+#define STM32MP1_TZC_A7_ID		U(0)
+#define STM32MP1_TZC_M4_ID		U(1)
+#define STM32MP1_TZC_LCD_ID		U(3)
+#define STM32MP1_TZC_GPU_ID		U(4)
+#define STM32MP1_TZC_MDMA_ID		U(5)
+#define STM32MP1_TZC_DMA_ID		U(6)
+#define STM32MP1_TZC_USB_HOST_ID	U(7)
+#define STM32MP1_TZC_USB_OTG_ID		U(8)
+#define STM32MP1_TZC_SDMMC_ID		U(9)
+#define STM32MP1_TZC_ETH_ID		U(10)
+#define STM32MP1_TZC_DAP_ID		U(15)
+
+#define TZC_REGION_NSEC_ALL_ACCESS_RDWR \
+	(TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_M4_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID))
+
+#endif /* _DT_BINDINGS_STM32MP15_TZC400_H */
diff --git a/include/export/common/tbbr/tbbr_img_def_exp.h b/include/export/common/tbbr/tbbr_img_def_exp.h
index 18f0125..2623c75 100644
--- a/include/export/common/tbbr/tbbr_img_def_exp.h
+++ b/include/export/common/tbbr/tbbr_img_def_exp.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -91,7 +91,17 @@
 /* FW_CONFIG */
 #define FW_CONFIG_ID			U(31)
 
+/*
+ * Primary FWU metadata image ID
+ */
+#define FWU_METADATA_IMAGE_ID		U(32)
+
+/*
+ * Backup FWU metadata image ID
+ */
+#define BKUP_FWU_METADATA_IMAGE_ID	U(33)
+
 /* Max Images */
-#define MAX_IMAGE_IDS			U(32)
+#define MAX_IMAGE_IDS			U(34)
 
 #endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_TBBR_TBBR_IMG_DEF_EXP_H */
diff --git a/include/lib/cpus/aarch64/cortex_a710.h b/include/lib/cpus/aarch64/cortex_a710.h
index 44c540c..8b011aa 100644
--- a/include/lib/cpus/aarch64/cortex_a710.h
+++ b/include/lib/cpus/aarch64/cortex_a710.h
@@ -13,6 +13,7 @@
  * CPU Extended Control register specific definitions
  ******************************************************************************/
 #define CORTEX_A710_CPUECTLR_EL1				S3_0_C15_C1_4
+#define CORTEX_A710_CPUECTLR_EL1_PFSTIDIS_BIT                   (ULL(1) << 8)
 
 /*******************************************************************************
  * CPU Power Control register specific definitions
@@ -20,4 +21,10 @@
 #define CORTEX_A710_CPUPWRCTLR_EL1				S3_0_C15_C2_7
 #define CORTEX_A710_CPUPWRCTLR_EL1_CORE_PWRDN_BIT		U(1)
 
+/*******************************************************************************
+ * CPU Auxiliary Control register specific definitions.
+ ******************************************************************************/
+#define CORTEX_A710_CPUACTLR_EL1 				S3_0_C15_C1_0
+#define CORTEX_A710_CPUACTLR_EL1_BIT_46 			(ULL(1) << 46)
+
 #endif /* CORTEX_A710_H */
diff --git a/include/lib/cpus/aarch64/cortex_a78_ae.h b/include/lib/cpus/aarch64/cortex_a78_ae.h
index 24ae7ee..0c8adcf 100644
--- a/include/lib/cpus/aarch64/cortex_a78_ae.h
+++ b/include/lib/cpus/aarch64/cortex_a78_ae.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,4 +12,10 @@
 
 #define CORTEX_A78_AE_MIDR U(0x410FD420)
 
+/*******************************************************************************
+ * CPU Extended Control register specific definitions.
+ ******************************************************************************/
+#define CORTEX_A78_AE_CPUECTLR_EL1			CORTEX_A78_CPUECTLR_EL1
+#define CORTEX_A78_AE_CPUECTLR_EL1_BIT_8		CORTEX_A78_CPUECTLR_EL1_BIT_8
+
 #endif /* CORTEX_A78_AE_H */
diff --git a/include/lib/cpus/aarch64/cortex_demeter.h b/include/lib/cpus/aarch64/cortex_demeter.h
new file mode 100644
index 0000000..9dd0987
--- /dev/null
+++ b/include/lib/cpus/aarch64/cortex_demeter.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CORTEX_DEMETER_H
+#define CORTEX_DEMETER_H
+
+#define CORTEX_DEMETER_MIDR				U(0x410FD4F0)
+
+/*******************************************************************************
+ * CPU Extended Control register specific definitions
+ ******************************************************************************/
+#define CORTEX_DEMETER_CPUECTLR_EL1			S3_0_C15_C1_4
+
+/*******************************************************************************
+ * CPU Power Control register specific definitions
+ ******************************************************************************/
+#define CORTEX_DEMETER_CPUPWRCTLR_EL1			S3_0_C15_C2_7
+#define CORTEX_DEMETER_CPUPWRCTLR_EL1_CORE_PWRDN_BIT	U(1)
+
+#endif /* CORTEX_DEMETER_H */
diff --git a/include/lib/cpus/aarch64/neoverse_n2.h b/include/lib/cpus/aarch64/neoverse_n2.h
index 7cbd8c1..948f965 100644
--- a/include/lib/cpus/aarch64/neoverse_n2.h
+++ b/include/lib/cpus/aarch64/neoverse_n2.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,11 +21,24 @@
  ******************************************************************************/
 #define NEOVERSE_N2_CPUECTLR_EL1		S3_0_C15_C1_4
 #define NEOVERSE_N2_CPUECTLR_EL1_EXTLLC_BIT	(ULL(1) << 0)
+#define NEOVERSE_N2_CPUECTLR_EL1_PFSTIDIS_BIT	(ULL(1) << 8)
 
 /*******************************************************************************
  * CPU Auxiliary Control register specific definitions.
  ******************************************************************************/
+#define NEOVERSE_N2_CPUACTLR_EL1		S3_0_C15_C1_0
+#define NEOVERSE_N2_CPUACTLR_EL1_BIT_46	        (ULL(1) << 46)
+
+/*******************************************************************************
+ * CPU Auxiliary Control register 2 specific definitions.
+ ******************************************************************************/
 #define NEOVERSE_N2_CPUACTLR2_EL1		S3_0_C15_C1_1
 #define NEOVERSE_N2_CPUACTLR2_EL1_BIT_2		(ULL(1) << 2)
 
+/*******************************************************************************
+ * CPU Auxiliary Control register 5 specific definitions.
+ ******************************************************************************/
+#define NEOVERSE_N2_CPUACTLR5_EL1		S3_0_C15_C8_0
+#define NEOVERSE_N2_CPUACTLR5_EL1_BIT_44	(ULL(1) << 44)
+
 #endif /* NEOVERSE_N2_H */
diff --git a/include/lib/cpus/aarch64/neoverse_v1.h b/include/lib/cpus/aarch64/neoverse_v1.h
index cea2659..cfb26ab 100644
--- a/include/lib/cpus/aarch64/neoverse_v1.h
+++ b/include/lib/cpus/aarch64/neoverse_v1.h
@@ -13,6 +13,8 @@
  * CPU Extended Control register specific definitions.
  ******************************************************************************/
 #define NEOVERSE_V1_CPUECTLR_EL1				S3_0_C15_C1_4
+#define NEOVERSE_V1_CPUECTLR_EL1_BIT_8				(ULL(1) << 8)
+#define NEOVERSE_V1_CPUECTLR_EL1_BIT_53				(ULL(1) << 53)
 
 /*******************************************************************************
  * CPU Power Control register specific definitions
@@ -25,5 +27,6 @@
  ******************************************************************************/
 #define NEOVERSE_V1_ACTLR2_EL1					S3_0_C15_C1_1
 #define NEOVERSE_V1_ACTLR2_EL1_BIT_2				(ULL(1) << 2)
+#define NEOVERSE_V1_ACTLR2_EL1_BIT_28				(ULL(1) << 28)
 
 #endif /* NEOVERSE_V1_H */
diff --git a/include/lib/el3_runtime/cpu_data.h b/include/lib/el3_runtime/cpu_data.h
index 5426135..3d57a5c 100644
--- a/include/lib/el3_runtime/cpu_data.h
+++ b/include/lib/el3_runtime/cpu_data.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -125,7 +125,7 @@
 #if ENABLE_PAUTH
 CASSERT(CPU_DATA_APIAKEY_OFFSET == __builtin_offsetof
 	(cpu_data_t, apiakey),
-	assert_cpu_data_crash_stack_offset_mismatch);
+	assert_cpu_data_pauth_stack_offset_mismatch);
 #endif
 
 #if CRASH_REPORTING
diff --git a/include/lib/optee_utils.h b/include/lib/optee_utils.h
index 6067caf..06378eb 100644
--- a/include/lib/optee_utils.h
+++ b/include/lib/optee_utils.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,8 +7,12 @@
 #ifndef OPTEE_UTILS_H
 #define OPTEE_UTILS_H
 
+#include <stdbool.h>
+
 #include <common/bl_common.h>
 
+bool optee_header_is_valid(uintptr_t header_base);
+
 int parse_optee_header(entry_point_info_t *header_ep,
 	image_info_t *pager_image_info,
 	image_info_t *paged_image_info);
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 846c9a4..0a19d8b 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -153,7 +153,9 @@
 int arm_io_setup(void);
 
 /* Set image specification in IO block policy */
-int arm_set_image_source(unsigned int image_id, const char *part_name);
+int arm_set_image_source(unsigned int image_id, const char *part_name,
+			 uintptr_t *dev_handle, uintptr_t *image_spec);
+void arm_set_fip_addr(uint32_t active_fw_bank_idx);
 
 /* Security utility functions */
 void arm_tzc400_setup(uintptr_t tzc_base,
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index 1def86e..434835e 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -16,6 +16,7 @@
 #if TRNG_SUPPORT
 #include "plat_trng.h"
 #endif
+#include <drivers/fwu/fwu_metadata.h>
 
 /*******************************************************************************
  * Forward declarations
@@ -140,6 +141,8 @@
 void plat_sdei_handle_masked_trigger(uint64_t mpidr, unsigned int intr);
 #endif
 
+void plat_default_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
+		void *handle, uint64_t flags);
 void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
 		void *handle, uint64_t flags);
 
@@ -349,4 +352,12 @@
  */
 int32_t plat_is_smccc_feature_available(u_register_t fid);
 
+/*******************************************************************************
+ * FWU platform specific functions
+ ******************************************************************************/
+int plat_fwu_set_metadata_image_source(unsigned int image_id,
+				       uintptr_t *dev_handle,
+				       uintptr_t *image_spec);
+void plat_fwu_set_images_source(struct fwu_metadata *metadata);
+
 #endif /* PLATFORM_H */
diff --git a/include/services/ffa_svc.h b/include/services/ffa_svc.h
index 5b39c42..ab36d9e 100644
--- a/include/services/ffa_svc.h
+++ b/include/services/ffa_svc.h
@@ -22,7 +22,7 @@
 
 /* The macros below are used to identify FFA calls from the SMC function ID */
 #define FFA_FNUM_MIN_VALUE	U(0x60)
-#define FFA_FNUM_MAX_VALUE	U(0x85)
+#define FFA_FNUM_MAX_VALUE	U(0x87)
 #define is_ffa_fid(fid) __extension__ ({		\
 	__typeof__(fid) _fid = (fid);			\
 	((GET_SMC_NUM(_fid) >= FFA_FNUM_MIN_VALUE) &&	\
@@ -32,7 +32,7 @@
 #define FFA_VERSION_MAJOR		U(1)
 #define FFA_VERSION_MAJOR_SHIFT		16
 #define FFA_VERSION_MAJOR_MASK		U(0x7FFF)
-#define FFA_VERSION_MINOR		U(0)
+#define FFA_VERSION_MINOR		U(1)
 #define FFA_VERSION_MINOR_SHIFT		0
 #define FFA_VERSION_MINOR_MASK		U(0xFFFF)
 #define FFA_VERSION_BIT31_MASK 		U(0x1u << 31)
@@ -61,32 +61,44 @@
 		 ((func_num) << FUNCID_NUM_SHIFT))
 
 /* FFA function numbers */
-#define FFA_FNUM_ERROR			U(0x60)
-#define FFA_FNUM_SUCCESS		U(0x61)
-#define FFA_FNUM_INTERRUPT		U(0x62)
-#define FFA_FNUM_VERSION		U(0x63)
-#define FFA_FNUM_FEATURES		U(0x64)
-#define FFA_FNUM_RX_RELEASE		U(0x65)
-#define FFA_FNUM_RXTX_MAP		U(0x66)
-#define FFA_FNUM_RXTX_UNMAP		U(0x67)
-#define FFA_FNUM_PARTITION_INFO_GET	U(0x68)
-#define FFA_FNUM_ID_GET			U(0x69)
-#define FFA_FNUM_MSG_POLL		U(0x6A)
-#define FFA_FNUM_MSG_WAIT		U(0x6B)
-#define FFA_FNUM_MSG_YIELD		U(0x6C)
-#define FFA_FNUM_MSG_RUN		U(0x6D)
-#define FFA_FNUM_MSG_SEND		U(0x6E)
-#define FFA_FNUM_MSG_SEND_DIRECT_REQ	U(0x6F)
-#define FFA_FNUM_MSG_SEND_DIRECT_RESP	U(0x70)
-#define FFA_FNUM_MEM_DONATE		U(0x71)
-#define FFA_FNUM_MEM_LEND		U(0x72)
-#define FFA_FNUM_MEM_SHARE		U(0x73)
-#define FFA_FNUM_MEM_RETRIEVE_REQ	U(0x74)
-#define FFA_FNUM_MEM_RETRIEVE_RESP	U(0x75)
-#define FFA_FNUM_MEM_RELINQUISH	U(0x76)
-#define FFA_FNUM_MEM_RECLAIM		U(0x77)
-#define FFA_FNUM_SECONDARY_EP_REGISTER	U(0x84)
-#define FFA_FNUM_SPM_ID_GET		U(0x85)
+#define FFA_FNUM_ERROR				U(0x60)
+#define FFA_FNUM_SUCCESS			U(0x61)
+#define FFA_FNUM_INTERRUPT			U(0x62)
+#define FFA_FNUM_VERSION			U(0x63)
+#define FFA_FNUM_FEATURES			U(0x64)
+#define FFA_FNUM_RX_RELEASE			U(0x65)
+#define FFA_FNUM_RXTX_MAP			U(0x66)
+#define FFA_FNUM_RXTX_UNMAP			U(0x67)
+#define FFA_FNUM_PARTITION_INFO_GET		U(0x68)
+#define FFA_FNUM_ID_GET				U(0x69)
+#define FFA_FNUM_MSG_POLL			U(0x6A) /* Legacy FF-A v1.0 */
+#define FFA_FNUM_MSG_WAIT			U(0x6B)
+#define FFA_FNUM_MSG_YIELD			U(0x6C)
+#define FFA_FNUM_MSG_RUN			U(0x6D)
+#define FFA_FNUM_MSG_SEND			U(0x6E) /* Legacy FF-A v1.0 */
+#define FFA_FNUM_MSG_SEND_DIRECT_REQ		U(0x6F)
+#define FFA_FNUM_MSG_SEND_DIRECT_RESP		U(0x70)
+#define FFA_FNUM_MEM_DONATE			U(0x71)
+#define FFA_FNUM_MEM_LEND			U(0x72)
+#define FFA_FNUM_MEM_SHARE			U(0x73)
+#define FFA_FNUM_MEM_RETRIEVE_REQ		U(0x74)
+#define FFA_FNUM_MEM_RETRIEVE_RESP		U(0x75)
+#define FFA_FNUM_MEM_RELINQUISH			U(0x76)
+#define FFA_FNUM_MEM_RECLAIM			U(0x77)
+#define FFA_FNUM_NORMAL_WORLD_RESUME		U(0x7C)
+
+/* FF-A v1.1 */
+#define FFA_FNUM_NOTIFICATION_BITMAP_CREATE	U(0x7D)
+#define FFA_FNUM_NOTIFICATION_BITMAP_DESTROY	U(0x7E)
+#define FFA_FNUM_NOTIFICATION_BIND		U(0x7F)
+#define FFA_FNUM_NOTIFICATION_UNBIND		U(0x80)
+#define FFA_FNUM_NOTIFICATION_SET		U(0x81)
+#define FFA_FNUM_NOTIFICATION_GET		U(0x82)
+#define FFA_FNUM_NOTIFICATION_INFO_GET		U(0x83)
+#define FFA_FNUM_RX_ACQUIRE			U(0x84)
+#define FFA_FNUM_SPM_ID_GET			U(0x85)
+#define FFA_FNUM_MSG_SEND2			U(0x86)
+#define FFA_FNUM_SECONDARY_EP_REGISTER		U(0x87)
 
 /* FFA SMC32 FIDs */
 #define FFA_ERROR		FFA_FID(SMC_32, FFA_FNUM_ERROR)
diff --git a/lib/cpus/aarch64/cortex_a710.S b/lib/cpus/aarch64/cortex_a710.S
index 4f979f8..75b7647 100644
--- a/lib/cpus/aarch64/cortex_a710.S
+++ b/lib/cpus/aarch64/cortex_a710.S
@@ -21,6 +21,145 @@
 #error "Cortex A710 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+/* --------------------------------------------------
+ * Errata Workaround for Cortex-A710 Erratum 1987031.
+ * This applies to revision r0p0, r1p0 and r2p0 of Cortex-A710. It is still
+ * open.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_a710_1987031_wa
+	/* Check revision. */
+	mov	x17, x30
+	bl	check_errata_1987031
+	cbz	x0, 1f
+
+	/* Apply instruction patching sequence */
+	ldr x0,=0x6
+	msr S3_6_c15_c8_0,x0
+	ldr x0,=0xF3A08002
+	msr S3_6_c15_c8_2,x0
+	ldr x0,=0xFFF0F7FE
+	msr S3_6_c15_c8_3,x0
+	ldr x0,=0x40000001003ff
+	msr S3_6_c15_c8_1,x0
+	ldr x0,=0x7
+	msr S3_6_c15_c8_0,x0
+	ldr x0,=0xBF200000
+	msr S3_6_c15_c8_2,x0
+	ldr x0,=0xFFEF0000
+	msr S3_6_c15_c8_3,x0
+	ldr x0,=0x40000001003f3
+	msr S3_6_c15_c8_1,x0
+	isb
+1:
+	ret	x17
+endfunc errata_a710_1987031_wa
+
+func check_errata_1987031
+	/* Applies to r0p0, r1p0 and r2p0 */
+	mov	x1, #0x20
+	b	cpu_rev_var_ls
+endfunc check_errata_1987031
+
+/* --------------------------------------------------
+ * Errata Workaround for Cortex-A710 Erratum 2081180.
+ * This applies to revision r0p0, r1p0 and r2p0 of Cortex-A710.
+ * It is still open.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_a710_2081180_wa
+	/* Check revision. */
+	mov	x17, x30
+	bl	check_errata_2081180
+	cbz	x0, 1f
+
+	/* Apply instruction patching sequence */
+	ldr	x0,=0x3
+	msr	S3_6_c15_c8_0,x0
+	ldr	x0,=0xF3A08002
+	msr	S3_6_c15_c8_2,x0
+	ldr	x0,=0xFFF0F7FE
+	msr	S3_6_c15_c8_3,x0
+	ldr	x0,=0x10002001003FF
+	msr	S3_6_c15_c8_1,x0
+	ldr	x0,=0x4
+	msr	S3_6_c15_c8_0,x0
+	ldr	x0,=0xBF200000
+	msr	S3_6_c15_c8_2,x0
+	ldr	x0,=0xFFEF0000
+	msr	S3_6_c15_c8_3,x0
+	ldr	x0,=0x10002001003F3
+	msr	S3_6_c15_c8_1,x0
+	isb
+1:
+	ret	x17
+endfunc errata_a710_2081180_wa
+
+func check_errata_2081180
+	/* Applies to r0p0, r1p0 and r2p0 */
+	mov	x1, #0x20
+	b	cpu_rev_var_ls
+endfunc check_errata_2081180
+
+/* ---------------------------------------------------------------------
+ * Errata Workaround for Cortex-A710 Erratum 2055002.
+ * This applies to revision r1p0, r2p0 of Cortex-A710 and is still open.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * ---------------------------------------------------------------------
+ */
+func errata_a710_2055002_wa
+	/* Compare x0 against revision r2p0 */
+	mov	x17, x30
+	bl	check_errata_2055002
+	cbz	x0, 1f
+	mrs	x1, CORTEX_A710_CPUACTLR_EL1
+	orr	x1, x1, CORTEX_A710_CPUACTLR_EL1_BIT_46
+	msr	CORTEX_A710_CPUACTLR_EL1, x1
+1:
+	ret	x17
+endfunc errata_a710_2055002_wa
+
+func check_errata_2055002
+	/* Applies to r1p0, r2p0 */
+	mov	x1, #0x20
+	b	cpu_rev_var_ls
+endfunc check_errata_2055002
+
+/* -------------------------------------------------------------
+ * Errata Workaround for Cortex-A710 Erratum 2017096.
+ * This applies to revisions r0p0, r1p0 and r2p0 of Cortex-A710.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * -------------------------------------------------------------
+ */
+func errata_a710_2017096_wa
+	/* Compare x0 against revision r0p0 to r2p0 */
+	mov     x17, x30
+	bl      check_errata_2017096
+	cbz     x0, 1f
+	mrs     x1, CORTEX_A710_CPUECTLR_EL1
+	orr     x1, x1, CORTEX_A710_CPUECTLR_EL1_PFSTIDIS_BIT
+	msr     CORTEX_A710_CPUECTLR_EL1, x1
+
+1:
+	ret     x17
+endfunc errata_a710_2017096_wa
+
+func check_errata_2017096
+	/* Applies to r0p0, r1p0, r2p0 */
+	mov     x1, #0x20
+	b       cpu_rev_var_ls
+endfunc check_errata_2017096
+
 	/* ----------------------------------------------------
 	 * HW will do the cache maintenance while powering down
 	 * ----------------------------------------------------
@@ -37,20 +176,60 @@
 	ret
 endfunc cortex_a710_core_pwr_dwn
 
+#if REPORT_ERRATA
 	/*
-	 * Errata printing function for Cortex A710. Must follow AAPCS.
+	 * Errata printing function for Cortex-A710. Must follow AAPCS.
 	 */
-#if REPORT_ERRATA
 func cortex_a710_errata_report
+	stp	x8, x30, [sp, #-16]!
+
+	bl	cpu_get_rev_var
+	mov	x8, x0
+
+	/*
+	 * Report all errata. The revision-variant information is passed to
+	 * checking functions of each errata.
+	 */
+	report_errata ERRATA_A710_1987031, cortex_a710, 1987031
+	report_errata ERRATA_A710_2081180, cortex_a710, 2081180
+	report_errata ERRATA_A710_2055002, cortex_a710, 2055002
+	report_errata ERRATA_A710_2017096, cortex_a710, 2017096
+
+	ldp	x8, x30, [sp], #16
 	ret
 endfunc cortex_a710_errata_report
 #endif
 
 func cortex_a710_reset_func
+	mov	x19, x30
+
 	/* Disable speculative loads */
 	msr	SSBS, xzr
+
+	bl	cpu_get_rev_var
+	mov	x18, x0
+
+#if ERRATA_A710_1987031
+	mov	x0, x18
+	bl	errata_a710_1987031_wa
+#endif
+
+#if ERRATA_A710_2081180
+	mov	x0, x18
+	bl	errata_a710_2081180_wa
+#endif
+
+#if ERRATA_A710_2055002
+	mov	x0, x18
+	bl	errata_a710_2055002_wa
+#endif
+
+#if ERRATA_A710_2017096
+	mov     x0, x18
+	bl      errata_a710_2017096_wa
+#endif
 	isb
-	ret
+	ret	x19
 endfunc cortex_a710_reset_func
 
 	/* ---------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a78.S b/lib/cpus/aarch64/cortex_a78.S
index 8c5a45a..3a74571 100644
--- a/lib/cpus/aarch64/cortex_a78.S
+++ b/lib/cpus/aarch64/cortex_a78.S
@@ -154,6 +154,50 @@
 	b	cpu_rev_var_ls
 endfunc check_errata_1821534
 
+/* --------------------------------------------------
+ * Errata Workaround for Cortex A78 Errata 1952683.
+ * This applies to revision r0p0.
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_a78_1952683_wa
+	/* Check revision. */
+	mov	x17, x30
+	bl	check_errata_1952683
+	cbz	x0, 1f
+
+	ldr	x0,=0x5
+	msr	S3_6_c15_c8_0,x0
+	ldr	x0,=0xEEE10A10
+	msr	S3_6_c15_c8_2,x0
+	ldr	x0,=0xFFEF0FFF
+	msr	S3_6_c15_c8_3,x0
+	ldr	x0,=0x0010F000
+	msr	S3_6_c15_c8_4,x0
+	ldr	x0,=0x0010F000
+	msr	S3_6_c15_c8_5,x0
+	ldr	x0,=0x40000080023ff
+	msr	S3_6_c15_c8_1,x0
+	ldr	x0,=0x6
+	msr	S3_6_c15_c8_0,x0
+	ldr	x0,=0xEE640F34
+	msr	S3_6_c15_c8_2,x0
+	ldr	x0,=0xFFEF0FFF
+	msr	S3_6_c15_c8_3,x0
+	ldr	x0,=0x40000080023ff
+	msr	S3_6_c15_c8_1,x0
+	isb
+1:
+	ret	x17
+endfunc errata_a78_1952683_wa
+
+func check_errata_1952683
+	/* Applies to r0p0 only */
+	mov	x1, #0x00
+	b	cpu_rev_var_ls
+endfunc check_errata_1952683
+
 	/* -------------------------------------------------
 	 * The CPU Ops reset function for Cortex-A78
 	 * -------------------------------------------------
@@ -183,6 +227,11 @@
 	bl	errata_a78_1821534_wa
 #endif
 
+#if ERRATA_A78_1952683
+	mov	x0, x18
+	bl	errata_a78_1952683_wa
+#endif
+
 #if ENABLE_AMU
 	/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
 	mrs	x0, actlr_el3
@@ -241,6 +290,7 @@
 	report_errata ERRATA_A78_1941498, cortex_a78, 1941498
 	report_errata ERRATA_A78_1951500, cortex_a78, 1951500
 	report_errata ERRATA_A78_1821534, cortex_a78, 1821534
+	report_errata ERRATA_A78_1952683, cortex_a78, 1952683
 
 	ldp	x8, x30, [sp], #16
 	ret
diff --git a/lib/cpus/aarch64/cortex_a78_ae.S b/lib/cpus/aarch64/cortex_a78_ae.S
index 9aff9ac..421c174 100644
--- a/lib/cpus/aarch64/cortex_a78_ae.S
+++ b/lib/cpus/aarch64/cortex_a78_ae.S
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,12 +17,108 @@
 #error "cortex_a78_ae must be compiled with HW_ASSISTED_COHERENCY enabled"
 #endif
 
+/* --------------------------------------------------
+ * Errata Workaround for A78 AE Erratum 1941500.
+ * This applies to revisions r0p0 and r0p1 of A78 AE.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_a78_ae_1941500_wa
+	/* Compare x0 against revisions r0p0 - r0p1 */
+	mov	x17, x30
+	bl	check_errata_1941500
+	cbz	x0, 1f
+
+	/* Set bit 8 in ECTLR_EL1 */
+	mrs	x0, CORTEX_A78_AE_CPUECTLR_EL1
+	bic	x0, x0, #CORTEX_A78_AE_CPUECTLR_EL1_BIT_8
+	msr	CORTEX_A78_AE_CPUECTLR_EL1, x0
+	isb
+1:
+	ret	x17
+endfunc errata_a78_ae_1941500_wa
+
+func check_errata_1941500
+	/* Applies to revisions r0p0 and r0p1. */
+	mov	x1, #CPU_REV(0, 0)
+	mov	x2, #CPU_REV(0, 1)
+	b	cpu_rev_var_range
+endfunc check_errata_1941500
+
+/* --------------------------------------------------
+ * Errata Workaround for A78 AE Erratum 1951502.
+ * This applies to revisions r0p0 and r0p1 of A78 AE.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_a78_ae_1951502_wa
+	/* Compare x0 against revisions r0p0 - r0p1 */
+	mov	x17, x30
+	bl	check_errata_1951502
+	cbz	x0, 1f
+
+	msr	S3_6_c15_c8_0, xzr
+	ldr	x0, =0x10E3900002
+	msr	S3_6_c15_c8_2, x0
+	ldr	x0, =0x10FFF00083
+	msr	S3_6_c15_c8_3, x0
+	ldr	x0, =0x2001003FF
+	msr	S3_6_c15_c8_1, x0
+
+	mov	x0, #1
+	msr	S3_6_c15_c8_0, x0
+	ldr	x0, =0x10E3800082
+	msr	S3_6_c15_c8_2, x0
+	ldr	x0, =0x10FFF00083
+	msr	S3_6_c15_c8_3, x0
+	ldr	x0, =0x2001003FF
+	msr	S3_6_c15_c8_1, x0
+
+	mov	x0, #2
+	msr	S3_6_c15_c8_0, x0
+	ldr	x0, =0x10E3800200
+	msr	S3_6_c15_c8_2, x0
+	ldr	x0, =0x10FFF003E0
+	msr	S3_6_c15_c8_3, x0
+	ldr	x0, =0x2001003FF
+	msr	S3_6_c15_c8_1, x0
+
+	isb
+1:
+	ret	x17
+endfunc errata_a78_ae_1951502_wa
+
+func check_errata_1951502
+	/* Applies to revisions r0p0 and r0p1. */
+	mov	x1, #CPU_REV(0, 0)
+	mov	x2, #CPU_REV(0, 1)
+	b	cpu_rev_var_range
+endfunc check_errata_1951502
+
 	/* -------------------------------------------------
 	 * The CPU Ops reset function for Cortex-A78-AE
 	 * -------------------------------------------------
 	 */
-#if ENABLE_AMU
 func cortex_a78_ae_reset_func
+	mov	x19, x30
+	bl	cpu_get_rev_var
+	mov	x18, x0
+
+#if ERRATA_A78_AE_1941500
+	mov	x0, x18
+	bl	errata_a78_ae_1941500_wa
+#endif
+
+#if ERRATA_A78_AE_1951502
+	mov	x0, x18
+	bl	errata_a78_ae_1951502_wa
+#endif
+
+#if ENABLE_AMU
 	/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
 	mrs	x0, actlr_el3
 	bic	x0, x0, #CORTEX_A78_ACTLR_TAM_BIT
@@ -39,11 +136,12 @@
 	/* Enable group1 counters */
 	mov	x0, #CORTEX_A78_AMU_GROUP1_MASK
 	msr	CPUAMCNTENSET1_EL0, x0
+#endif
+
 	isb
 
-	ret
+	ret	x19
 endfunc cortex_a78_ae_reset_func
-#endif
 
 	/* -------------------------------------------------------
 	 * HW will do the cache maintenance while powering down
@@ -66,6 +164,19 @@
 	 */
 #if REPORT_ERRATA
 func cortex_a78_ae_errata_report
+	stp	x8, x30, [sp, #-16]!
+
+	bl	cpu_get_rev_var
+	mov	x8, x0
+
+	/*
+	 * Report all errata. The revision-variant information is passed to
+	 * checking functions of each errata.
+	 */
+	report_errata ERRATA_A78_AE_1941500, cortex_a78_ae, 1941500
+	report_errata ERRATA_A78_AE_1951502, cortex_a78_ae, 1951502
+
+	ldp	x8, x30, [sp], #16
 	ret
 endfunc cortex_a78_ae_errata_report
 #endif
@@ -89,12 +200,6 @@
 	ret
 endfunc cortex_a78_ae_cpu_reg_dump
 
-#if ENABLE_AMU
-#define A78_AE_RESET_FUNC cortex_a78_ae_reset_func
-#else
-#define A78_AE_RESET_FUNC CPU_NO_RESET_FUNC
-#endif
-
 declare_cpu_ops cortex_a78_ae, CORTEX_A78_AE_MIDR, \
-	A78_AE_RESET_FUNC, \
+	cortex_a78_ae_reset_func, \
 	cortex_a78_ae_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_demeter.S b/lib/cpus/aarch64/cortex_demeter.S
new file mode 100644
index 0000000..9ad8b86
--- /dev/null
+++ b/lib/cpus/aarch64/cortex_demeter.S
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <cortex_demeter.h>
+#include <cpu_macros.S>
+#include <plat_macros.S>
+
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "Cortex Demeter must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
+/* 64-bit only core */
+#if CTX_INCLUDE_AARCH32_REGS == 1
+#error "Cortex Demeter supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
+#endif
+
+	/* ----------------------------------------------------
+	 * HW will do the cache maintenance while powering down
+	 * ----------------------------------------------------
+	 */
+func cortex_demeter_core_pwr_dwn
+	/* ---------------------------------------------------
+	 * Enable CPU power down bit in power control register
+	 * ---------------------------------------------------
+	 */
+	mrs	x0, CORTEX_DEMETER_CPUPWRCTLR_EL1
+	orr	x0, x0, #CORTEX_DEMETER_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
+	msr	CORTEX_DEMETER_CPUPWRCTLR_EL1, x0
+	isb
+	ret
+endfunc cortex_demeter_core_pwr_dwn
+
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Cortex Demeter. Must follow AAPCS.
+ */
+func cortex_demeter_errata_report
+	ret
+endfunc cortex_demeter_errata_report
+#endif
+
+func cortex_demeter_reset_func
+	/* Disable speculative loads */
+	msr	SSBS, xzr
+	isb
+	ret
+endfunc cortex_demeter_reset_func
+
+	/* ---------------------------------------------
+	 * This function provides Cortex Demeter-
+	 * specific register information for crash
+	 * reporting. It needs to return with x6
+	 * pointing to a list of register names in ascii
+	 * and x8 - x15 having values of registers to be
+	 * reported.
+	 * ---------------------------------------------
+	 */
+.section .rodata.cortex_demeter_regs, "aS"
+cortex_demeter_regs:  /* The ascii list of register names to be reported */
+	.asciz	"cpuectlr_el1", ""
+
+func cortex_demeter_cpu_reg_dump
+	adr	x6, cortex_demeter_regs
+	mrs	x8, CORTEX_DEMETER_CPUECTLR_EL1
+	ret
+endfunc cortex_demeter_cpu_reg_dump
+
+declare_cpu_ops cortex_demeter, CORTEX_DEMETER_MIDR, \
+	cortex_demeter_reset_func, \
+	cortex_demeter_core_pwr_dwn
diff --git a/lib/cpus/aarch64/neoverse_n2.S b/lib/cpus/aarch64/neoverse_n2.S
index 8d646cb..9e7bbf7 100644
--- a/lib/cpus/aarch64/neoverse_n2.S
+++ b/lib/cpus/aarch64/neoverse_n2.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,11 +19,177 @@
 #error "Neoverse-N2 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
-	/* -------------------------------------------------
+/* --------------------------------------------------
+ * Errata Workaround for Neoverse N2 Erratum 2002655.
+ * This applies to revision r0p0 of Neoverse N2. it is still open.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_n2_2002655_wa
+	/* Check revision. */
+	mov	x17, x30
+	bl	check_errata_2002655
+	cbz	x0, 1f
+
+	/* Apply instruction patching sequence */
+	ldr x0,=0x6
+	msr S3_6_c15_c8_0,x0
+	ldr x0,=0xF3A08002
+	msr S3_6_c15_c8_2,x0
+	ldr x0,=0xFFF0F7FE
+	msr S3_6_c15_c8_3,x0
+	ldr x0,=0x40000001003ff
+	msr S3_6_c15_c8_1,x0
+	ldr x0,=0x7
+	msr S3_6_c15_c8_0,x0
+	ldr x0,=0xBF200000
+	msr S3_6_c15_c8_2,x0
+	ldr x0,=0xFFEF0000
+	msr S3_6_c15_c8_3,x0
+	ldr x0,=0x40000001003f3
+	msr S3_6_c15_c8_1,x0
+	isb
+1:
+	ret	x17
+endfunc errata_n2_2002655_wa
+
+func check_errata_2002655
+	/* Applies to r0p0 */
+	mov	x1, #0x00
+	b	cpu_rev_var_ls
+endfunc check_errata_2002655
+
+/* ---------------------------------------------------------------
+ * Errata Workaround for Neoverse N2 Erratum 2067956.
+ * This applies to revision r0p0 of Neoverse N2 and is still open.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * ---------------------------------------------------------------
+ */
+func errata_n2_2067956_wa
+	/* Compare x0 against revision r0p0 */
+	mov	x17, x30
+	bl	check_errata_2067956
+	cbz	x0, 1f
+	mrs	x1, NEOVERSE_N2_CPUACTLR_EL1
+	orr	x1, x1, NEOVERSE_N2_CPUACTLR_EL1_BIT_46
+	msr	NEOVERSE_N2_CPUACTLR_EL1, x1
+1:
+	ret	x17
+endfunc errata_n2_2067956_wa
+
+func check_errata_2067956
+	/* Applies to r0p0 */
+	mov	x1, #0x00
+	b	cpu_rev_var_ls
+endfunc check_errata_2067956
+
+/* ---------------------------------------------------------------
+ * Errata Workaround for Neoverse N2 Erratum 2025414.
+ * This applies to revision r0p0 of Neoverse N2 and is still open.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * ---------------------------------------------------------------
+ */
+func errata_n2_2025414_wa
+	/* Compare x0 against revision r0p0 */
+	mov     x17, x30
+	bl      check_errata_2025414
+	cbz     x0, 1f
+	mrs     x1, NEOVERSE_N2_CPUECTLR_EL1
+	orr     x1, x1, NEOVERSE_N2_CPUECTLR_EL1_PFSTIDIS_BIT
+	msr     NEOVERSE_N2_CPUECTLR_EL1, x1
+
+1:
+	ret     x17
+endfunc errata_n2_2025414_wa
+
+func check_errata_2025414
+	/* Applies to r0p0 */
+	mov     x1, #0x00
+	b       cpu_rev_var_ls
+endfunc check_errata_2025414
+
+/* ---------------------------------------------------------------
+ * Errata Workaround for Neoverse N2 Erratum 2189731.
+ * This applies to revision r0p0 of Neoverse N2 and is still open.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * ---------------------------------------------------------------
+ */
+func errata_n2_2189731_wa
+	/* Compare x0 against revision r0p0 */
+	mov     x17, x30
+	bl      check_errata_2189731
+	cbz     x0, 1f
+	mrs     x1, NEOVERSE_N2_CPUACTLR5_EL1
+	orr     x1, x1, NEOVERSE_N2_CPUACTLR5_EL1_BIT_44
+	msr     NEOVERSE_N2_CPUACTLR5_EL1, x1
+
+1:
+	ret     x17
+endfunc errata_n2_2189731_wa
+
+func check_errata_2189731
+	/* Applies to r0p0 */
+	mov     x1, #0x00
+	b       cpu_rev_var_ls
+endfunc check_errata_2189731
+
+/* --------------------------------------------------
+ * Errata Workaround for Neoverse N2 Erratum 2138956.
+ * This applies to revision r0p0 of Neoverse N2. it is still open.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0-x17
+ * --------------------------------------------------
+ */
+func errata_n2_2138956_wa
+	/* Check revision. */
+	mov	x17, x30
+	bl	check_errata_2138956
+	cbz	x0, 1f
+
+	/* Apply instruction patching sequence */
+	ldr	x0,=0x3
+	msr	S3_6_c15_c8_0,x0
+	ldr	x0,=0xF3A08002
+	msr	S3_6_c15_c8_2,x0
+	ldr	x0,=0xFFF0F7FE
+	msr	S3_6_c15_c8_3,x0
+	ldr	x0,=0x10002001003FF
+	msr	S3_6_c15_c8_1,x0
+	ldr	x0,=0x4
+	msr	S3_6_c15_c8_0,x0
+	ldr	x0,=0xBF200000
+	msr	S3_6_c15_c8_2,x0
+	ldr	x0,=0xFFEF0000
+	msr	S3_6_c15_c8_3,x0
+	ldr	x0,=0x10002001003F3
+	msr	S3_6_c15_c8_1,x0
+	isb
+1:
+	ret	x17
+endfunc errata_n2_2138956_wa
+
+func check_errata_2138956
+	/* Applies to r0p0 */
+	mov	x1, #0x00
+	b	cpu_rev_var_ls
+endfunc check_errata_2138956
+
+	/* -------------------------------------------
 	 * The CPU Ops reset function for Neoverse N2.
-	 * -------------------------------------------------
+	 * -------------------------------------------
 	 */
 func neoverse_n2_reset_func
+	mov	x19, x30
+
 	/* Check if the PE implements SSBS */
 	mrs	x0, id_aa64pfr1_el1
 	tst	x0, #(ID_AA64PFR1_EL1_SSBS_MASK << ID_AA64PFR1_EL1_SSBS_SHIFT)
@@ -37,6 +203,27 @@
 	orr	x0, x0, #NEOVERSE_N2_CPUACTLR2_EL1_BIT_2
 	msr	NEOVERSE_N2_CPUACTLR2_EL1, x0
 
+#if ERRATA_N2_2067956
+	mov	x0, x18
+	bl	errata_n2_2067956_wa
+#endif
+
+#if ERRATA_N2_2025414
+	mov     x0, x18
+	bl      errata_n2_2025414_wa
+#endif
+
+#if ERRATA_N2_2189731
+	mov     x0, x18
+	bl      errata_n2_2189731_wa
+#endif
+
+
+#if ERRATA_N2_2138956
+	mov	x0, x18
+	bl	errata_n2_2138956_wa
+#endif
+
 #if ENABLE_AMU
 	/* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */
 	mrs	x0, cptr_el3
@@ -53,20 +240,28 @@
 
 #if NEOVERSE_Nx_EXTERNAL_LLC
 	/* Some systems may have External LLC, core needs to be made aware */
-	mrs     x0, NEOVERSE_N2_CPUECTLR_EL1
-	orr     x0, x0, NEOVERSE_N2_CPUECTLR_EL1_EXTLLC_BIT
-	msr     NEOVERSE_N2_CPUECTLR_EL1, x0
+	mrs	x0, NEOVERSE_N2_CPUECTLR_EL1
+	orr	x0, x0, NEOVERSE_N2_CPUECTLR_EL1_EXTLLC_BIT
+	msr	NEOVERSE_N2_CPUECTLR_EL1, x0
 #endif
 
+	bl	cpu_get_rev_var
+	mov	x18, x0
+
+#if ERRATA_N2_2002655
+	mov	x0, x18
+	bl	errata_n2_2002655_wa
+#endif
+
 	isb
-	ret
+	ret	x19
 endfunc neoverse_n2_reset_func
 
 func neoverse_n2_core_pwr_dwn
-	/* ---------------------------------------------
+	/* ---------------------------------------------------
 	 * Enable CPU power down bit in power control register
 	 * No need to do cache maintenance here.
-	 * ---------------------------------------------
+	 * ---------------------------------------------------
 	 */
 	mrs	x0, NEOVERSE_N2_CPUPWRCTLR_EL1
 	orr	x0, x0, #NEOVERSE_N2_CORE_PWRDN_EN_BIT
@@ -80,7 +275,22 @@
  * Errata printing function for Neoverse N2 cores. Must follow AAPCS.
  */
 func neoverse_n2_errata_report
-	/* No errata reported for Neoverse N2 cores */
+	stp	x8, x30, [sp, #-16]!
+
+	bl	cpu_get_rev_var
+	mov	x8, x0
+
+	/*
+	 * Report all errata. The revision-variant information is passed to
+	 * checking functions of each errata.
+	 */
+	report_errata ERRATA_N2_2002655, neoverse_n2, 2002655
+	report_errata ERRATA_N2_2067956, neoverse_n2, 2067956
+	report_errata ERRATA_N2_2025414, neoverse_n2, 2025414
+        report_errata ERRATA_N2_2189731, neoverse_n2, 2189731
+	report_errata ERRATA_N2_2138956, neoverse_n2, 2138956
+
+	ldp	x8, x30, [sp], #16
 	ret
 endfunc neoverse_n2_errata_report
 #endif
diff --git a/lib/cpus/aarch64/neoverse_v1.S b/lib/cpus/aarch64/neoverse_v1.S
index cee0bb7..0bcf52a 100644
--- a/lib/cpus/aarch64/neoverse_v1.S
+++ b/lib/cpus/aarch64/neoverse_v1.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
+ * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -22,6 +22,34 @@
 #endif
 
 	/* --------------------------------------------------
+	 * Errata Workaround for Neoverse V1 Errata #1774420.
+	 * This applies to revisions r0p0 and r1p0, fixed in r1p1.
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * --------------------------------------------------
+	 */
+func errata_neoverse_v1_1774420_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_1774420
+	cbz	x0, 1f
+
+	/* Set bit 53 in CPUECTLR_EL1 */
+	mrs     x1, NEOVERSE_V1_CPUECTLR_EL1
+	orr	x1, x1, #NEOVERSE_V1_CPUECTLR_EL1_BIT_53
+	msr     NEOVERSE_V1_CPUECTLR_EL1, x1
+	isb
+1:
+	ret	x17
+endfunc errata_neoverse_v1_1774420_wa
+
+func check_errata_1774420
+	/* Applies to r0p0 and r1p0. */
+	mov	x1, #0x10
+	b	cpu_rev_var_ls
+endfunc check_errata_1774420
+
+	/* --------------------------------------------------
 	 * Errata Workaround for Neoverse V1 Errata #1791573.
 	 * This applies to revisions r0p0 and r1p0, fixed in r1p1.
 	 * x0: variant[4:7] and revision[0:3] of current cpu.
@@ -35,9 +63,9 @@
 	cbz	x0, 1f
 
 	/* Set bit 2 in ACTLR2_EL1 */
-	mrs     x1, NEOVERSE_V1_ACTLR2_EL1
+	mrs	x1, NEOVERSE_V1_ACTLR2_EL1
 	orr	x1, x1, #NEOVERSE_V1_ACTLR2_EL1_BIT_2
-	msr     NEOVERSE_V1_ACTLR2_EL1, x1
+	msr	NEOVERSE_V1_ACTLR2_EL1, x1
 	isb
 1:
 	ret	x17
@@ -50,6 +78,62 @@
 endfunc check_errata_1791573
 
 	/* --------------------------------------------------
+	 * Errata Workaround for Neoverse V1 Errata #1852267.
+	 * This applies to revisions r0p0 and r1p0, fixed in r1p1.
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * --------------------------------------------------
+	 */
+func errata_neoverse_v1_1852267_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_1852267
+	cbz	x0, 1f
+
+	/* Set bit 28 in ACTLR2_EL1 */
+	mrs	x1, NEOVERSE_V1_ACTLR2_EL1
+	orr	x1, x1, #NEOVERSE_V1_ACTLR2_EL1_BIT_28
+	msr	NEOVERSE_V1_ACTLR2_EL1, x1
+	isb
+1:
+	ret	x17
+endfunc errata_neoverse_v1_1852267_wa
+
+func check_errata_1852267
+	/* Applies to r0p0 and r1p0. */
+	mov	x1, #0x10
+	b	cpu_rev_var_ls
+endfunc check_errata_1852267
+
+	/* --------------------------------------------------
+	 * Errata Workaround for Neoverse V1 Errata #1925756.
+	 * This applies to revisions <= r1p1.
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * --------------------------------------------------
+	 */
+func errata_neoverse_v1_1925756_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_1925756
+	cbz	x0, 1f
+
+	/* Set bit 8 in CPUECTLR_EL1 */
+	mrs	x1, NEOVERSE_V1_CPUECTLR_EL1
+	orr	x1, x1, #NEOVERSE_V1_CPUECTLR_EL1_BIT_8
+	msr	NEOVERSE_V1_CPUECTLR_EL1, x1
+	isb
+1:
+	ret	x17
+endfunc errata_neoverse_v1_1925756_wa
+
+func check_errata_1925756
+	/* Applies to <= r1p1. */
+	mov	x1, #0x11
+	b	cpu_rev_var_ls
+endfunc check_errata_1925756
+
+	/* --------------------------------------------------
 	 * Errata Workaround for Neoverse V1 Erratum #1940577
 	 * This applies to revisions r1p0 - r1p1 and is open.
 	 * It also exists in r0p0 but there is no fix in that
@@ -104,6 +188,77 @@
 	b	cpu_rev_var_range
 endfunc check_errata_1940577
 
+	/* --------------------------------------------------
+	 * Errata Workaround for Neoverse V1 Errata #1966096
+	 * This applies to revisions r1p0 - r1p1 and is open.
+	 * It also exists in r0p0 but there is no workaround
+	 * for that revision.
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * --------------------------------------------------
+	 */
+func errata_neoverse_v1_1966096_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_1966096
+	cbz	x0, 1f
+
+	/* Apply the workaround. */
+	mov	x0, #0x3
+	msr	S3_6_C15_C8_0, x0
+	ldr	x0, =0xEE010F12
+	msr	S3_6_C15_C8_2, x0
+	ldr	x0, =0xFFFF0FFF
+	msr	S3_6_C15_C8_3, x0
+	ldr	x0, =0x80000000003FF
+	msr	S3_6_C15_C8_1, x0
+	isb
+
+1:
+	ret	x17
+endfunc errata_neoverse_v1_1966096_wa
+
+func check_errata_1966096
+	mov	x1, #0x10
+	mov	x2, #0x11
+	b	cpu_rev_var_range
+endfunc check_errata_1966096
+
+	/* --------------------------------------------------
+	 * Errata Workaround for Neoverse V1 Errata #2139242.
+	 * This applies to revisions r0p0, r1p0, and r1p1, it
+	 * is still open.
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0-x17
+	 * --------------------------------------------------
+	 */
+func errata_neoverse_v1_2139242_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_2139242
+	cbz	x0, 1f
+
+	/* Apply the workaround. */
+	mov	x0, #0x3
+	msr	S3_6_C15_C8_0, x0
+	ldr	x0, =0xEE720F14
+	msr	S3_6_C15_C8_2, x0
+	ldr	x0, =0xFFFF0FDF
+	msr	S3_6_C15_C8_3, x0
+	ldr	x0, =0x40000005003FF
+	msr	S3_6_C15_C8_1, x0
+	isb
+
+1:
+	ret	x17
+endfunc errata_neoverse_v1_2139242_wa
+
+func check_errata_2139242
+	/* Applies to r0p0, r1p0, r1p1 */
+	mov	x1, #0x11
+	b	cpu_rev_var_ls
+endfunc check_errata_2139242
+
 	/* ---------------------------------------------
 	 * HW will do the cache maintenance while powering down
 	 * ---------------------------------------------
@@ -134,8 +289,13 @@
 	 * Report all errata. The revision-variant information is passed to
 	 * checking functions of each errata.
 	 */
+	report_errata ERRATA_V1_1774420, neoverse_v1, 1774420
 	report_errata ERRATA_V1_1791573, neoverse_v1, 1791573
+	report_errata ERRATA_V1_1852267, neoverse_v1, 1852267
+	report_errata ERRATA_V1_1925756, neoverse_v1, 1925756
 	report_errata ERRATA_V1_1940577, neoverse_v1, 1940577
+	report_errata ERRATA_V1_1966096, neoverse_v1, 1966096
+	report_errata ERRATA_V1_2139242, neoverse_v1, 2139242
 
 	ldp	x8, x30, [sp], #16
 	ret
@@ -149,16 +309,41 @@
 	msr	SSBS, xzr
 	isb
 
+#if ERRATA_V1_1774420
+	mov	x0, x18
+	bl	errata_neoverse_v1_1774420_wa
+#endif
+
 #if ERRATA_V1_1791573
 	mov	x0, x18
 	bl	errata_neoverse_v1_1791573_wa
 #endif
 
+#if ERRATA_V1_1852267
+	mov	x0, x18
+	bl	errata_neoverse_v1_1852267_wa
+#endif
+
+#if ERRATA_V1_1925756
+	mov	x0, x18
+	bl	errata_neoverse_v1_1925756_wa
+#endif
+
 #if ERRATA_V1_1940577
 	mov	x0, x18
 	bl	errata_neoverse_v1_1940577_wa
 #endif
 
+#if ERRATA_V1_1966096
+	mov	x0, x18
+	bl	errata_neoverse_v1_1966096_wa
+#endif
+
+#if ERRATA_V1_2139242
+	mov	x0, x18
+	bl	errata_neoverse_v1_2139242_wa
+#endif
+
 	ret	x19
 endfunc neoverse_v1_reset_func
 
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 6f80d2d..6103a5a 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -1,6 +1,6 @@
 #
 # Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved.
-# Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+# Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -311,10 +311,22 @@
 # well but there is no workaround for that revision.
 ERRATA_A78_1951500	?=0
 
+# Flag to apply erratum 1941500 workaround during reset. This erratum applies
+# to revisions r0p0 and r0p1 of the A78 AE cpu. It is still open.
+ERRATA_A78_AE_1941500	?=0
+
+# Flag to apply erratum 1951502 workaround during reset. This erratum applies
+# to revisions r0p0 and r0p1 of the A78 AE cpu. It is still open.
+ERRATA_A78_AE_1951502	?=0
+
 # Flag to apply erratum 1821534 workaround during reset. This erratum applies
 # to revisions r0p0 and r1p0 of the A78 cpu.
 ERRATA_A78_1821534	?=0
 
+# Flag to apply erratum 1952683 workaround during reset. This erratum applies
+# to revision r0p0 of the A78 cpu and was fixed in the revision r1p0.
+ERRATA_A78_1952683	?=0
+
 # Flag to apply T32 CLREX workaround during reset. This erratum applies
 # only to r0p0 and r1p0 of the Neoverse N1 cpu.
 ERRATA_N1_1043202	?=0
@@ -372,14 +384,71 @@
 # exists in revisions r0p0, r1p0, and r2p0 as well but there is no workaround.
 ERRATA_N1_1946160	?=0
 
+# Flag to apply erratum 2002655 workaround during reset. This erratum applies
+# to revisions r0p0 of the Neoverse-N2 cpu, it is still open.
+ERRATA_N2_2002655	?=0
+
+# Flag to apply erratum 1774420 workaround during reset.  This erratum applies
+# to revisions r0p0 and r1p0 of the Neoverse V1 core, and was fixed in r1p1.
+ERRATA_V1_1774420	?=0
+
 # Flag to apply erratum 1791573 workaround during reset.  This erratum applies
 # to revisions r0p0 and r1p0 of the Neoverse V1 core, and was fixed in r1p1.
 ERRATA_V1_1791573	?=0
 
+# Flag to apply erratum 1852267 workaround during reset.  This erratum applies
+# to revisions r0p0 and r1p0 of the Neoverse V1 core, and was fixed in r1p1.
+ERRATA_V1_1852267	?=0
+
+# Flag to apply erratum 1925756 workaround during reset.  This needs to be
+# enabled for r0p0, r1p0, and r1p1 of the Neoverse V1 core, it is still open.
+ERRATA_V1_1925756	?=0
+
 # Flag to apply erratum 1940577 workaround during reset. This erratum applies
 # to revisions r1p0 and r1p1 of the Neoverse V1 cpu.
 ERRATA_V1_1940577	?=0
 
+# Flag to apply erratum 1966096 workaround during reset. This erratum applies
+# to revisions r1p0 and r1p1 of the Neoverse V1 CPU and is open.  This issue
+# exists in r0p0 as well but there is no workaround for that revision.
+ERRATA_V1_1966096   ?=0
+
+# Flag to apply erratum 2139242 workaround during reset. This erratum applies
+# to revisions r0p0, r1p0, and r1p1 of the Neoverse V1 cpu and is still open.
+ERRATA_V1_2139242   ?=0
+
+# Flag to apply erratum 1987031 workaround during reset. This erratum applies
+# to revisions r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is still open.
+ERRATA_A710_1987031	?=0
+
+# Flag to apply erratum 2081180 workaround during reset. This erratum applies
+# to revisions r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is still open.
+ERRATA_A710_2081180	?=0
+
+# Flag to apply erratum 2067956 workaround during reset. This erratum applies
+# to revision r0p0 of the Neoverse N2 cpu and is still open.
+ERRATA_N2_2067956	?=0
+
+# Flag to apply erratum 2025414 workaround during reset. This erratum applies
+# to revision r0p0 of the Neoverse N2 cpu and is still open.
+ERRATA_N2_2025414	?=0
+
+# Flag to apply erratum 2189731 workaround during reset. This erratum applies
+# to revision r0p0 of the Neoverse N2 cpu and is still open.
+ERRATA_N2_2189731	?=0
+
+# Flag to apply erratum 2138956 workaround during reset. This erratum applies
+# to revision r0p0 of the Neoverse N2 cpu and is still open.
+ERRATA_N2_2138956	?=0
+
+# Flag to apply erratum 2055002 workaround during reset. This erratum applies
+# to revision r1p0, r2p0 of the Cortex-A710 cpu and is still open.
+ERRATA_A710_2055002	?=0
+
+# Flag to apply erratum 2017096 workaround during reset. This erratum applies
+# to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is still open.
+ERRATA_A710_2017096	?=0
+
 # Flag to apply DSU erratum 798953. This erratum applies to DSUs revision r0p0.
 # Applying the workaround results in higher DSU power consumption on idle.
 ERRATA_DSU_798953	?=0
@@ -625,10 +694,22 @@
 $(eval $(call assert_boolean,ERRATA_A78_1951500))
 $(eval $(call add_define,ERRATA_A78_1951500))
 
+# Process ERRATA_A78_AE_1941500 flag
+$(eval $(call assert_boolean,ERRATA_A78_AE_1941500))
+$(eval $(call add_define,ERRATA_A78_AE_1941500))
+
+# Process ERRATA_A78_AE_1951502 flag
+$(eval $(call assert_boolean,ERRATA_A78_AE_1951502))
+$(eval $(call add_define,ERRATA_A78_AE_1951502))
+
 # Process ERRATA_A78_1821534 flag
 $(eval $(call assert_boolean,ERRATA_A78_1821534))
 $(eval $(call add_define,ERRATA_A78_1821534))
 
+# Process ERRATA_A78_1952683 flag
+$(eval $(call assert_boolean,ERRATA_A78_1952683))
+$(eval $(call add_define,ERRATA_A78_1952683))
+
 # Process ERRATA_N1_1043202 flag
 $(eval $(call assert_boolean,ERRATA_N1_1043202))
 $(eval $(call add_define,ERRATA_N1_1043202))
@@ -685,14 +766,70 @@
 $(eval $(call assert_boolean,ERRATA_N1_1946160))
 $(eval $(call add_define,ERRATA_N1_1946160))
 
+# Process ERRATA_N2_2002655 flag
+$(eval $(call assert_boolean,ERRATA_N2_2002655))
+$(eval $(call add_define,ERRATA_N2_2002655))
+
+# Process ERRATA_V1_1774420 flag
+$(eval $(call assert_boolean,ERRATA_V1_1774420))
+$(eval $(call add_define,ERRATA_V1_1774420))
+
 # Process ERRATA_V1_1791573 flag
 $(eval $(call assert_boolean,ERRATA_V1_1791573))
 $(eval $(call add_define,ERRATA_V1_1791573))
 
+# Process ERRATA_V1_1852267 flag
+$(eval $(call assert_boolean,ERRATA_V1_1852267))
+$(eval $(call add_define,ERRATA_V1_1852267))
+
+# Process ERRATA_V1_1925756 flag
+$(eval $(call assert_boolean,ERRATA_V1_1925756))
+$(eval $(call add_define,ERRATA_V1_1925756))
+
 # Process ERRATA_V1_1940577 flag
 $(eval $(call assert_boolean,ERRATA_V1_1940577))
 $(eval $(call add_define,ERRATA_V1_1940577))
 
+# Process ERRATA_V1_1966096 flag
+$(eval $(call assert_boolean,ERRATA_V1_1966096))
+$(eval $(call add_define,ERRATA_V1_1966096))
+
+# Process ERRATA_V1_2139242 flag
+$(eval $(call assert_boolean,ERRATA_V1_2139242))
+$(eval $(call add_define,ERRATA_V1_2139242))
+
+# Process ERRATA_A710_1987031 flag
+$(eval $(call assert_boolean,ERRATA_A710_1987031))
+$(eval $(call add_define,ERRATA_A710_1987031))
+
+# Process ERRATA_A710_2081180 flag
+$(eval $(call assert_boolean,ERRATA_A710_2081180))
+$(eval $(call add_define,ERRATA_A710_2081180))
+
+# Process ERRATA_N2_2067956 flag
+$(eval $(call assert_boolean,ERRATA_N2_2067956))
+$(eval $(call add_define,ERRATA_N2_2067956))
+
+# Process ERRATA_N2_2025414 flag
+$(eval $(call assert_boolean,ERRATA_N2_2025414))
+$(eval $(call add_define,ERRATA_N2_2025414))
+
+# Process ERRATA_N2_2189731 flag
+$(eval $(call assert_boolean,ERRATA_N2_2189731))
+$(eval $(call add_define,ERRATA_N2_2189731))
+
+# Process ERRATA_N2_2138956 flag
+$(eval $(call assert_boolean,ERRATA_N2_2138956))
+$(eval $(call add_define,ERRATA_N2_2138956))
+
+# Process ERRATA_A710_2055002 flag
+$(eval $(call assert_boolean,ERRATA_A710_2055002))
+$(eval $(call add_define,ERRATA_A710_2055002))
+
+# Process ERRATA_A710_2017096 flag
+$(eval $(call assert_boolean,ERRATA_A710_2017096))
+$(eval $(call add_define,ERRATA_A710_2017096))
+
 # Process ERRATA_DSU_798953 flag
 $(eval $(call assert_boolean,ERRATA_DSU_798953))
 $(eval $(call add_define,ERRATA_DSU_798953))
diff --git a/lib/optee/optee_utils.c b/lib/optee/optee_utils.c
index 0ad1082..d090b38 100644
--- a/lib/optee/optee_utils.c
+++ b/lib/optee/optee_utils.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -47,25 +47,24 @@
 
 /*******************************************************************************
  * Check if it is a valid tee header
- * Return 1 if valid
- * Return 0 if invalid
+ * Return true if valid
+ * Return false if invalid
  ******************************************************************************/
-static inline int tee_validate_header(optee_header_t *header)
+static bool tee_validate_header(optee_header_t *header)
 {
-	int valid = 0;
-
 	if ((header->magic == TEE_MAGIC_NUM_OPTEE) &&
 		(header->version == 2u) &&
 		(header->nb_images > 0u) &&
 		(header->nb_images <= OPTEE_MAX_NUM_IMAGES)) {
-		valid = 1;
+		return true;
 	}
 
-	else {
-		WARN("Not a known TEE, use default loading options.\n");
-	}
+	return false;
+}
 
-	return valid;
+bool optee_header_is_valid(uintptr_t header_base)
+{
+	return tee_validate_header((optee_header_t *)header_base);
 }
 
 /*******************************************************************************
diff --git a/lib/zlib/tf_gunzip.c b/lib/zlib/tf_gunzip.c
index fd56dfc..3ac80bc 100644
--- a/lib/zlib/tf_gunzip.c
+++ b/lib/zlib/tf_gunzip.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,6 +9,7 @@
 #include <string.h>
 
 #include <common/debug.h>
+#include <common/tf_crc32.h>
 #include <lib/utils.h>
 #include <tf_gunzip.h>
 
@@ -100,3 +101,15 @@
 
 	return ret;
 }
+
+/* Wrapper function to calculate CRC
+ * @crc: previous accumulated CRC
+ * @buf: buffer base address
+ * @size: size of the buffer
+ *
+ * Return calculated CRC32 value
+ */
+uint32_t tf_crc32(uint32_t crc, const unsigned char *buf, size_t size)
+{
+	return (uint32_t)crc32((unsigned long)crc, buf, size);
+}
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index b2d1ee2..72f84b5 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -344,3 +344,14 @@
 
 # Build option to use the SP804 timer instead of the generic one
 USE_SP804_TIMER			:= 0
+
+# Build option to define number of firmware banks, used in firmware update
+# metadata structure.
+NR_OF_FW_BANKS			:= 2
+
+# Build option to define number of images in firmware bank, used in firmware
+# update metadata structure.
+NR_OF_IMAGES_IN_FW_BANK		:= 1
+
+# Disable Firmware update support by default
+PSA_FWU_SUPPORT			:= 0
diff --git a/package-lock.json b/package-lock.json
index 46d8bf3..61caf57 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1561,9 +1561,9 @@
       "dev": true
     },
     "path-parse": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
-      "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
       "dev": true
     },
     "path-type": {
diff --git a/plat/allwinner/common/include/platform_def.h b/plat/allwinner/common/include/platform_def.h
index 56a2ad6..49951e0 100644
--- a/plat/allwinner/common/include/platform_def.h
+++ b/plat/allwinner/common/include/platform_def.h
@@ -25,7 +25,8 @@
 
 #else	/* !SUNXI_BL31_IN_DRAM */
 
-#define BL31_BASE			(SUNXI_SRAM_A2_BASE + 0x4000)
+#define BL31_BASE			(SUNXI_SRAM_A2_BASE + \
+					 SUNXI_SRAM_A2_BL31_OFFSET)
 #define BL31_LIMIT			(SUNXI_SRAM_A2_BASE + \
 					 SUNXI_SRAM_A2_SIZE - SUNXI_SCP_SIZE)
 
diff --git a/plat/allwinner/common/include/sunxi_def.h b/plat/allwinner/common/include/sunxi_def.h
index f036816..ec50887 100644
--- a/plat/allwinner/common/include/sunxi_def.h
+++ b/plat/allwinner/common/include/sunxi_def.h
@@ -18,5 +18,6 @@
 #define SUNXI_SOC_H5			0x1718
 #define SUNXI_SOC_H6			0x1728
 #define SUNXI_SOC_H616			0x1823
+#define SUNXI_SOC_R329			0x1851
 
 #endif /* SUNXI_DEF_H */
diff --git a/plat/allwinner/common/sunxi_bl31_setup.c b/plat/allwinner/common/sunxi_bl31_setup.c
index 72bfbd9..14049e8 100644
--- a/plat/allwinner/common/sunxi_bl31_setup.c
+++ b/plat/allwinner/common/sunxi_bl31_setup.c
@@ -128,6 +128,9 @@
 	case SUNXI_SOC_H616:
 		soc_name = "H616";
 		break;
+	case SUNXI_SOC_R329:
+		soc_name = "R329";
+		break;
 	default:
 		soc_name = "unknown";
 		break;
diff --git a/plat/allwinner/common/sunxi_cpu_ops.c b/plat/allwinner/common/sunxi_cpu_ops.c
index 420b507..46e7090 100644
--- a/plat/allwinner/common/sunxi_cpu_ops.c
+++ b/plat/allwinner/common/sunxi_cpu_ops.c
@@ -42,6 +42,7 @@
 	mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xe0);
 	mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x80);
 	mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x00);
+	udelay(1);
 }
 
 /* We can't turn ourself off like this, but it works for other cores. */
@@ -75,7 +76,8 @@
 	/* Assert CPU power-on reset */
 	mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
 	/* Set CPU to start in AArch64 mode */
-	mmio_setbits_32(SUNXI_CPUCFG_CLS_CTRL_REG0(cluster), BIT(24 + core));
+	mmio_setbits_32(SUNXI_AA64nAA32_REG(cluster),
+			BIT(SUNXI_AA64nAA32_OFFSET + core));
 	/* Apply power to the CPU */
 	sunxi_cpu_enable_power(cluster, core);
 	/* Release the core output clamps */
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h
index c3eeadb..aed3585 100644
--- a/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h
+++ b/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h
@@ -33,4 +33,7 @@
 #define SUNXI_R_CPUCFG_SS_ENTRY_REG	(SUNXI_R_CPUCFG_BASE + 0x01a8)
 #define SUNXI_R_CPUCFG_HP_FLAG_REG	(SUNXI_R_CPUCFG_BASE + 0x01ac)
 
+#define SUNXI_AA64nAA32_REG		SUNXI_CPUCFG_CLS_CTRL_REG0
+#define SUNXI_AA64nAA32_OFFSET		24
+
 #endif /* SUNXI_CPUCFG_H */
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
index 6c847d3..6d10921 100644
--- a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
+++ b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
@@ -15,6 +15,7 @@
 #define SUNXI_SRAM_A1_BASE		0x00010000
 #define SUNXI_SRAM_A1_SIZE		0x00008000
 #define SUNXI_SRAM_A2_BASE		0x00040000
+#define SUNXI_SRAM_A2_BL31_OFFSET	0x00004000
 #define SUNXI_SRAM_A2_SIZE		0x00014000
 #define SUNXI_SRAM_C_BASE		0x00018000
 #define SUNXI_SRAM_C_SIZE		0x0001c000
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h
index a2b94af..5bfda5d 100644
--- a/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h
+++ b/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h
@@ -29,4 +29,7 @@
 #define SUNXI_PWR_SW_DELAY_REG		(SUNXI_R_CPUCFG_BASE + 0x0140)
 #define SUNXI_CONFIG_DELAY_REG		(SUNXI_R_CPUCFG_BASE + 0x0144)
 
+#define SUNXI_AA64nAA32_REG		SUNXI_CPUCFG_CLS_CTRL_REG0
+#define SUNXI_AA64nAA32_OFFSET		24
+
 #endif /* SUNXI_CPUCFG_H */
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
index 2d7b098..58216d8 100644
--- a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
+++ b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
@@ -15,6 +15,7 @@
 #define SUNXI_SRAM_A1_BASE		0x00020000
 #define SUNXI_SRAM_A1_SIZE		0x00008000
 #define SUNXI_SRAM_A2_BASE		0x00100000
+#define SUNXI_SRAM_A2_BL31_OFFSET	0x00004000
 #define SUNXI_SRAM_A2_SIZE		0x00018000
 #define SUNXI_SRAM_C_BASE		0x00028000
 #define SUNXI_SRAM_C_SIZE		0x0001e000
diff --git a/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h
index a637554..dab663b 100644
--- a/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h
+++ b/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h
@@ -29,4 +29,7 @@
 #define SUNXI_PWR_SW_DELAY_REG		(SUNXI_R_CPUCFG_BASE + 0x0140)
 #define SUNXI_CONFIG_DELAY_REG		(SUNXI_R_CPUCFG_BASE + 0x0144)
 
+#define SUNXI_AA64nAA32_REG		SUNXI_CPUCFG_CLS_CTRL_REG0
+#define SUNXI_AA64nAA32_OFFSET		24
+
 #endif /* SUNXI_CPUCFG_H */
diff --git a/plat/allwinner/sun50i_r329/include/sunxi_ccu.h b/plat/allwinner/sun50i_r329/include/sunxi_ccu.h
new file mode 100644
index 0000000..0e6b543
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/include/sunxi_ccu.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2021 Sipeed
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_CCU_H
+#define SUNXI_CCU_H
+
+#define SUNXI_CCU_SEC_SWITCH_REG	(SUNXI_CCU_BASE + 0x0f00)
+
+#define SUNXI_R_PRCM_SEC_SWITCH_REG	(SUNXI_R_PRCM_BASE + 0x0290)
+
+#endif /* SUNXI_CCU_H */
diff --git a/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h
new file mode 100644
index 0000000..9478f32
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2021 Sipeed
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_CPUCFG_H
+#define SUNXI_CPUCFG_H
+
+#include <sunxi_mmap.h>
+
+/* c = cluster, n = core */
+#define SUNXI_CPUCFG_CLS_CTRL_REG0(c)	(SUNXI_C0_CPUXCFG_BASE + 0x0010)
+#define SUNXI_CPUCFG_CLS_CTRL_REG1(c)	(SUNXI_C0_CPUXCFG_BASE + 0x0014)
+#define SUNXI_CPUCFG_CACHE_CFG_REG	(SUNXI_C0_CPUXCFG_BASE + 0x0024)
+#define SUNXI_CPUCFG_DBG_REG0		(SUNXI_C0_CPUXCFG_BASE + 0x00c0)
+
+#define SUNXI_CPUCFG_RST_CTRL_REG(c)	(SUNXI_C0_CPUXCFG_BASE + 0x0000)
+#define SUNXI_CPUCFG_GEN_CTRL_REG0(c)	(SUNXI_CPUCFG_BASE + 0x0000)
+#define SUNXI_CPUCFG_RVBAR_LO_REG(n)	(SUNXI_CPUCFG_BASE + 0x0040 + (n) * 8)
+#define SUNXI_CPUCFG_RVBAR_HI_REG(n)	(SUNXI_CPUCFG_BASE + 0x0044 + (n) * 8)
+
+#define SUNXI_POWERON_RST_REG(c)	(SUNXI_R_CPUCFG_BASE + 0x0040 + (c) * 4)
+#define SUNXI_POWEROFF_GATING_REG(c)	(SUNXI_R_CPUCFG_BASE + 0x0044 + (c) * 4)
+#define SUNXI_CPU_POWER_CLAMP_REG(c, n)	(SUNXI_R_CPUCFG_BASE + 0x0050 + \
+					(c) * 0x10 + (n) * 4)
+
+#define SUNXI_AA64nAA32_REG		SUNXI_CPUCFG_GEN_CTRL_REG0
+#define SUNXI_AA64nAA32_OFFSET		4
+
+#endif /* SUNXI_CPUCFG_H */
diff --git a/plat/allwinner/sun50i_r329/include/sunxi_mmap.h b/plat/allwinner/sun50i_r329/include/sunxi_mmap.h
new file mode 100644
index 0000000..a4469b5
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/include/sunxi_mmap.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_MMAP_H
+#define SUNXI_MMAP_H
+
+/* Memory regions */
+#define SUNXI_ROM_BASE			0x00000000
+#define SUNXI_ROM_SIZE			0x00010000
+/*
+ * In fact all SRAM from 0x100000 is SRAM A2. However as it's too big for
+ * firmware, and the user manual gives a tip on a 2*64K/27*64K partition,
+ * only use the first 2*64K for firmwares now, with the SPL using the first
+ * 64K and BL3-1 using the second one.
+ *
+ * Only the used 2*64K SRAM is defined here, to prevent a gaint translation
+ * table to be generated.
+ */
+#define SUNXI_SRAM_BASE			0x00100000
+#define SUNXI_SRAM_SIZE			0x00020000
+#define SUNXI_SRAM_A1_BASE		0x00100000
+#define SUNXI_SRAM_A1_SIZE		0x00010000
+#define SUNXI_SRAM_A2_BASE		0x00110000
+#define SUNXI_SRAM_A2_BL31_OFFSET	0x00000000
+#define SUNXI_SRAM_A2_SIZE		0x00010000
+#define SUNXI_DEV_BASE			0x01000000
+#define SUNXI_DEV_SIZE			0x09000000
+#define SUNXI_DRAM_BASE			0x40000000
+#define SUNXI_DRAM_VIRT_BASE		0x0a000000
+
+/* Memory-mapped devices */
+#define SUNXI_WDOG_BASE			0x020000a0
+#define SUNXI_R_WDOG_BASE		SUNXI_WDOG_BASE
+#define SUNXI_PIO_BASE			0x02000400
+#define SUNXI_SPC_BASE			0x02000800
+#define SUNXI_CCU_BASE			0x02001000
+#define SUNXI_UART0_BASE		0x02500000
+#define SUNXI_SYSCON_BASE		0x03000000
+#define SUNXI_DMA_BASE			0x03002000
+#define SUNXI_SID_BASE			0x03006000
+#define SUNXI_GICD_BASE			0x03021000
+#define SUNXI_GICC_BASE			0x03022000
+#define SUNXI_SPI0_BASE			0x04025000
+#define SUNXI_R_CPUCFG_BASE		0x07000400
+#define SUNXI_R_PRCM_BASE		0x07010000
+#define SUNXI_R_PIO_BASE		0x07022000
+#define SUNXI_R_UART_BASE		0x07080000
+#define SUNXI_R_I2C_BASE		0x07081400
+#define SUNXI_CPUCFG_BASE		0x08100000
+#define SUNXI_C0_CPUXCFG_BASE		0x09010000
+
+#endif /* SUNXI_MMAP_H */
diff --git a/plat/allwinner/sun50i_r329/include/sunxi_spc.h b/plat/allwinner/sun50i_r329/include/sunxi_spc.h
new file mode 100644
index 0000000..2c87bca
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/include/sunxi_spc.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2021 Sipeed
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SUNXI_SPC_H
+#define SUNXI_SPC_H
+
+/* Get by REing stock ATF and checking initialization loop boundary */
+#define SUNXI_SPC_NUM_PORTS		11
+
+#define SUNXI_SPC_DECPORT_STA_REG(p)	(SUNXI_SPC_BASE + 0x0000 + 0x10 * (p))
+#define SUNXI_SPC_DECPORT_SET_REG(p)	(SUNXI_SPC_BASE + 0x0004 + 0x10 * (p))
+#define SUNXI_SPC_DECPORT_CLR_REG(p)	(SUNXI_SPC_BASE + 0x0008 + 0x10 * (p))
+
+#endif /* SUNXI_SPC_H */
diff --git a/plat/allwinner/sun50i_r329/platform.mk b/plat/allwinner/sun50i_r329/platform.mk
new file mode 100644
index 0000000..05d7cde
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/platform.mk
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2021 Sipeed
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Without a management processor there is no SCPI support.
+SUNXI_PSCI_USE_SCPI	:=	0
+SUNXI_PSCI_USE_NATIVE	:=	1
+
+# The differences between the platforms are covered by the include files.
+include plat/allwinner/common/allwinner-common.mk
+
+# the above could be overwritten on the command line
+ifeq (${SUNXI_PSCI_USE_SCPI}, 1)
+    $(error "R329 does not support SCPI PSCI ops")
+endif
+
+# Put NOBITS memory in the first 64K of SRAM A2, overwriting U-Boot's SPL.
+SEPARATE_NOBITS_REGION	:=	1
diff --git a/plat/allwinner/sun50i_r329/sunxi_power.c b/plat/allwinner/sun50i_r329/sunxi_power.c
new file mode 100644
index 0000000..96a24d5
--- /dev/null
+++ b/plat/allwinner/sun50i_r329/sunxi_power.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2021 Sipeed
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <sunxi_mmap.h>
+#include <sunxi_cpucfg.h>
+#include <sunxi_private.h>
+
+int sunxi_pmic_setup(uint16_t socid, const void *fdt)
+{
+	/* Currently known hardware has no PMIC */
+
+	return 0;
+}
+
+void sunxi_power_down(void)
+{
+}
+
+void sunxi_cpu_power_off_self(void)
+{
+	/* TODO: It's still unknown whether CPUIDLE exists on R329 */
+}
diff --git a/plat/arm/board/arm_fpga/fpga_bl31_setup.c b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
index a5f5ea0..81d040c 100644
--- a/plat/arm/board/arm_fpga/fpga_bl31_setup.c
+++ b/plat/arm/board/arm_fpga/fpga_bl31_setup.c
@@ -218,7 +218,7 @@
 			INFO("Adjusting GICR DT region to cover %u cores\n",
 			      nr_cores);
 			err = fdt_adjust_gic_redist(fdt, nr_cores,
-						    1U << GICR_PCPUBASE_SHIFT);
+						    fpga_get_redist_size());
 			if (err < 0) {
 				ERROR("Error %d fixing up GIC DT node\n", err);
 			}
diff --git a/plat/arm/board/arm_fpga/fpga_gicv3.c b/plat/arm/board/arm_fpga/fpga_gicv3.c
index bfc116b..4a97beb 100644
--- a/plat/arm/board/arm_fpga/fpga_gicv3.c
+++ b/plat/arm/board/arm_fpga/fpga_gicv3.c
@@ -8,6 +8,7 @@
 #include <common/fdt_wrappers.h>
 #include <drivers/arm/gicv3.h>
 #include <drivers/arm/gic_common.h>
+#include <lib/mmio.h>
 #include <libfdt.h>
 
 #include <platform_def.h>
@@ -82,3 +83,11 @@
 {
 	return gicv3_rdistif_get_number_frames(fpga_gicv3_driver_data.gicr_base);
 }
+
+uintptr_t fpga_get_redist_size(void)
+{
+	uint64_t typer_val = mmio_read_64(fpga_gicv3_driver_data.gicr_base +
+					  GICR_TYPER);
+
+	return gicv3_redist_size(typer_val);
+}
diff --git a/plat/arm/board/arm_fpga/fpga_private.h b/plat/arm/board/arm_fpga/fpga_private.h
index 1ca241f..cc809c4 100644
--- a/plat/arm/board/arm_fpga/fpga_private.h
+++ b/plat/arm/board/arm_fpga/fpga_private.h
@@ -25,6 +25,7 @@
 void fpga_pwr_gic_off(void);
 unsigned int plat_fpga_calc_core_pos(uint32_t mpid);
 unsigned int fpga_get_nr_gic_cores(void);
+uintptr_t fpga_get_redist_size(void);
 
 #endif /* __ASSEMBLER__ */
 
diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk
index f1fd777..baffbcf 100644
--- a/plat/arm/board/arm_fpga/platform.mk
+++ b/plat/arm/board/arm_fpga/platform.mk
@@ -32,6 +32,8 @@
 FPGA_PRELOADED_CMD_LINE := 0x1000
 $(eval $(call add_define,FPGA_PRELOADED_CMD_LINE))
 
+ENABLE_AMU		:=	1
+
 # Treating this as a memory-constrained port for now
 USE_COHERENT_MEM	:=	0
 
@@ -87,6 +89,8 @@
 # Allow detection of GIC-600
 GICV3_SUPPORT_GIC600	:=	1
 
+GIC_ENABLE_V4_EXTN	:=	1
+
 # Include GICv3 driver files
 include drivers/arm/gic/v3/gicv3.mk
 
diff --git a/plat/arm/board/diphda/common/fdts/diphda_spmc_manifest.dts b/plat/arm/board/diphda/common/fdts/diphda_spmc_manifest.dts
index def04cd..536bdc3 100644
--- a/plat/arm/board/diphda/common/fdts/diphda_spmc_manifest.dts
+++ b/plat/arm/board/diphda/common/fdts/diphda_spmc_manifest.dts
@@ -20,7 +20,7 @@
 	attribute {
 		spmc_id = <0x8000>;
 		maj_ver = <0x1>;
-		min_ver = <0x0>;
+		min_ver = <0x1>;
 		exec_state = <0x0>;
 		load_address = <0x0 0x2002000>;
 		entrypoint = <0x0 0x2002000>;
diff --git a/plat/arm/board/diphda/platform.mk b/plat/arm/board/diphda/platform.mk
index 5ff0862..8b89cee 100644
--- a/plat/arm/board/diphda/platform.mk
+++ b/plat/arm/board/diphda/platform.mk
@@ -59,6 +59,13 @@
 			${DIPHDA_CPU_LIBS}					\
 			${DIPHDA_GIC_SOURCES}
 
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+	ifneq (${ENABLE_STACK_PROTECTOR},none)
+		DIPHDA_SECURITY_SOURCES := plat/arm/board/diphda/common/diphda_stack_protector.c
+		BL2_SOURCES += ${DIPHDA_SECURITY_SOURCES}
+		BL31_SOURCES += ${DIPHDA_SECURITY_SOURCES}
+	endif
+endif
 
 FDT_SOURCES		+=	plat/arm/board/diphda/common/fdts/diphda_spmc_manifest.dts
 DIPHDA_TOS_FW_CONFIG	:=	${BUILD_PLAT}/fdts/diphda_spmc_manifest.dtb
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
index 67e5504..21a6073 100644
--- a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
@@ -20,7 +20,7 @@
 	attribute {
 		spmc_id = <0x8000>;
 		maj_ver = <0x1>;
-		min_ver = <0x0>;
+		min_ver = <0x1>;
 		exec_state = <0x0>;
 		load_address = <0x0 0x6000000>;
 		entrypoint = <0x0 0x6000000>;
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts
index 088179b..041dade 100644
--- a/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts
@@ -20,7 +20,7 @@
 	attribute {
 		spmc_id = <0x8000>;
 		maj_ver = <0x1>;
-		min_ver = <0x0>;
+		min_ver = <0x1>;
 		exec_state = <0x0>;
 		load_address = <0x0 0x6000000>;
 		entrypoint = <0x0 0x6000000>;
diff --git a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
index 62ab27c..08d3c32 100644
--- a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
@@ -4,6 +4,8 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <lib/libc/cdefs.h>
+
 /dts-v1/;
 
 / {
@@ -74,6 +76,10 @@
 
 	secure-partitions {
 		compatible = "arm,sp";
+
+#ifdef ARM_BL2_SP_LIST_DTS
+	#include __XSTRING(ARM_BL2_SP_LIST_DTS)
+#else
 #ifdef OPTEE_SP_FW_CONFIG
 		op-tee {
 			uuid = "486178e0-e7f8-11e3-bc5e-0002a5d5c51b";
@@ -104,6 +110,7 @@
 			owner = "Plat";
 		};
 #endif
+#endif /* ARM_BL2_SP_LIST_DTS */
 	};
 
 #if COT_DESC_IN_DTB
diff --git a/plat/arm/board/fvp/fdts/optee_sp_manifest.dts b/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
index 928d0d3..07235b0 100644
--- a/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
+++ b/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
@@ -25,7 +25,7 @@
 	entrypoint-offset = <0x1000>;
 	xlat-granule = <0>; /* 4KiB */
 	boot-order = <0>;
-	messaging-method = <0>; /* Direct messaging only */
+	messaging-method = <3>; /* Direct messaging only */
 	run-time-model = <1>; /* Run to completion */
 
 	/* Boot protocol */
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 10258ad..3c70eed 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -135,6 +135,7 @@
 					lib/cpus/aarch64/cortex_a710.S	\
 					lib/cpus/aarch64/cortex_makalu.S	\
 					lib/cpus/aarch64/cortex_makalu_elp_arm.S \
+					lib/cpus/aarch64/cortex_demeter.S	\
 					lib/cpus/aarch64/cortex_a65.S		\
 					lib/cpus/aarch64/cortex_a65ae.S		\
 					lib/cpus/aarch64/cortex_a78c.S
diff --git a/plat/arm/board/rdn2/include/platform_def.h b/plat/arm/board/rdn2/include/platform_def.h
index 30a0c5c..194814f 100644
--- a/plat/arm/board/rdn2/include/platform_def.h
+++ b/plat/arm/board/rdn2/include/platform_def.h
@@ -44,6 +44,8 @@
 #define TZC_NSAID_ALL_AP		U(0)
 #define TZC_NSAID_PCI			U(1)
 #define TZC_NSAID_HDLCD0		U(2)
+#define TZC_NSAID_DMA			U(5)
+#define TZC_NSAID_DMA2			U(8)
 #define TZC_NSAID_CLCD			U(7)
 #define TZC_NSAID_AP			U(9)
 #define TZC_NSAID_VIRTIO		U(15)
@@ -52,6 +54,8 @@
 		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_ALL_AP)) | \
 		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_HDLCD0)) | \
 		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_PCI))    | \
+		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_DMA))    | \
+		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_DMA2))   | \
 		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_AP))     | \
 		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_CLCD))   | \
 		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_VIRTIO))
diff --git a/plat/arm/board/rdn2/platform.mk b/plat/arm/board/rdn2/platform.mk
index 794f897..5b24c32 100644
--- a/plat/arm/board/rdn2/platform.mk
+++ b/plat/arm/board/rdn2/platform.mk
@@ -3,7 +3,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
-# RD-N2 platform uses GIC-Clayton which is based on GICv4.1
+# RD-N2 platform uses GIC-700 which is based on GICv4.1
 GIC_ENABLE_V4_EXTN	:=	1
 
 include plat/arm/css/sgi/sgi-common.mk
diff --git a/plat/arm/board/rdv1/platform.mk b/plat/arm/board/rdv1/platform.mk
index 1ae85de..11f5212 100644
--- a/plat/arm/board/rdv1/platform.mk
+++ b/plat/arm/board/rdv1/platform.mk
@@ -3,7 +3,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
-# RD-V1 platform uses GIC-Clayton which is based on GICv4.1
+# RD-V1 platform uses GIC-700 which is based on GICv4.1
 GIC_ENABLE_V4_EXTN	:=	1
 
 include plat/arm/css/sgi/sgi-common.mk
diff --git a/plat/arm/board/tc0/fdts/tc0_fw_config.dts b/plat/arm/board/tc/fdts/tc_fw_config.dts
similarity index 84%
rename from plat/arm/board/tc0/fdts/tc0_fw_config.dts
rename to plat/arm/board/tc/fdts/tc_fw_config.dts
index 4b6abd4..a84c7f8 100644
--- a/plat/arm/board/tc0/fdts/tc0_fw_config.dts
+++ b/plat/arm/board/tc/fdts/tc_fw_config.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -26,7 +26,7 @@
 
 		hw-config {
 			load-address = <0x0 0x83000000>;
-			max-size = <0x01000000>;
+			max-size = <0x8000>;
 			id = <HW_CONFIG_ID>;
 		};
 	};
diff --git a/plat/arm/board/tc0/fdts/tc0_spmc_manifest.dts b/plat/arm/board/tc/fdts/tc_spmc_manifest.dts
similarity index 97%
rename from plat/arm/board/tc0/fdts/tc0_spmc_manifest.dts
rename to plat/arm/board/tc/fdts/tc_spmc_manifest.dts
index 44c7008..a8592f6 100644
--- a/plat/arm/board/tc0/fdts/tc0_spmc_manifest.dts
+++ b/plat/arm/board/tc/fdts/tc_spmc_manifest.dts
@@ -13,7 +13,7 @@
 	attribute {
 		spmc_id = <0x8000>;
 		maj_ver = <0x1>;
-		min_ver = <0x0>;
+		min_ver = <0x1>;
 		exec_state = <0x0>;
 		load_address = <0x0 0xfd000000>;
 		entrypoint = <0x0 0xfd000000>;
@@ -110,7 +110,7 @@
 		};
 	};
 
-	/* 32MB of TC0_TZC_DRAM1_BASE */
+	/* 32MB of TC_TZC_DRAM1_BASE */
 	memory@fd000000 {
 		device_type = "memory";
 		reg = <0x0 0xfd000000 0x2000000>;
diff --git a/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts b/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts
similarity index 94%
rename from plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts
rename to plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts
index 0830d5c..34b4e74 100644
--- a/plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts
+++ b/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,7 +13,7 @@
 	attribute {
 		spmc_id = <0x8000>;
 		maj_ver = <0x1>;
-		min_ver = <0x0>;
+		min_ver = <0x1>;
 		exec_state = <0x0>;
 		load_address = <0x0 0xfd000000>;
 		entrypoint = <0x0 0xfd000000>;
@@ -116,7 +116,7 @@
 		};
 	};
 
-	/* 32MB of TC0_TZC_DRAM1_BASE */
+	/* 32MB of TC_TZC_DRAM1_BASE */
 	memory@fd000000 {
 		device_type = "memory";
 		reg = <0x0 0xfd000000 0x2000000>;
diff --git a/plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts b/plat/arm/board/tc/fdts/tc_tb_fw_config.dts
similarity index 100%
rename from plat/arm/board/tc0/fdts/tc0_tb_fw_config.dts
rename to plat/arm/board/tc/fdts/tc_tb_fw_config.dts
diff --git a/plat/arm/board/tc0/include/plat_macros.S b/plat/arm/board/tc/include/plat_macros.S
similarity index 100%
rename from plat/arm/board/tc0/include/plat_macros.S
rename to plat/arm/board/tc/include/plat_macros.S
diff --git a/plat/arm/board/tc0/include/platform_def.h b/plat/arm/board/tc/include/platform_def.h
similarity index 80%
rename from plat/arm/board/tc0/include/platform_def.h
rename to plat/arm/board/tc/include/platform_def.h
index b169d77..ccabced 100644
--- a/plat/arm/board/tc0/include/platform_def.h
+++ b/plat/arm/board/tc/include/platform_def.h
@@ -29,38 +29,46 @@
  *   - BL32_BASE when SPD_spmd is enabled
  *   - Region to load Trusted OS
  */
-#define TC0_TZC_DRAM1_BASE		(ARM_AP_TZC_DRAM1_BASE -	\
-					 TC0_TZC_DRAM1_SIZE)
-#define TC0_TZC_DRAM1_SIZE		UL(0x02000000)	/* 32 MB */
-#define TC0_TZC_DRAM1_END		(TC0_TZC_DRAM1_BASE +		\
-					 TC0_TZC_DRAM1_SIZE - 1)
+#define TC_TZC_DRAM1_BASE		(ARM_AP_TZC_DRAM1_BASE -	\
+					 TC_TZC_DRAM1_SIZE)
+#define TC_TZC_DRAM1_SIZE		UL(0x02000000)	/* 32 MB */
+#define TC_TZC_DRAM1_END		(TC_TZC_DRAM1_BASE +		\
+					 TC_TZC_DRAM1_SIZE - 1)
 
-#define TC0_NS_DRAM1_BASE		ARM_DRAM1_BASE
-#define TC0_NS_DRAM1_SIZE		(ARM_DRAM1_SIZE -		\
+#define TC_NS_DRAM1_BASE		ARM_DRAM1_BASE
+#define TC_NS_DRAM1_SIZE		(ARM_DRAM1_SIZE -		\
 					 ARM_TZC_DRAM1_SIZE -		\
-					 TC0_TZC_DRAM1_SIZE)
-#define TC0_NS_DRAM1_END		(TC0_NS_DRAM1_BASE +		\
-					 TC0_NS_DRAM1_SIZE - 1)
+					 TC_TZC_DRAM1_SIZE)
+#define TC_NS_DRAM1_END		(TC_NS_DRAM1_BASE +		\
+					 TC_NS_DRAM1_SIZE - 1)
 
 /*
- * Mappings for TC0 DRAM1 (non-secure) and TC0 TZC DRAM1 (secure)
+ * Mappings for TC DRAM1 (non-secure) and TC TZC DRAM1 (secure)
  */
-#define TC0_MAP_NS_DRAM1		MAP_REGION_FLAT(		\
-						TC0_NS_DRAM1_BASE,	\
-						TC0_NS_DRAM1_SIZE,	\
+#define TC_MAP_NS_DRAM1		MAP_REGION_FLAT(		\
+						TC_NS_DRAM1_BASE,	\
+						TC_NS_DRAM1_SIZE,	\
 						MT_MEMORY | MT_RW | MT_NS)
 
 
-#define TC0_MAP_TZC_DRAM1		MAP_REGION_FLAT(		\
-						TC0_TZC_DRAM1_BASE,	\
-						TC0_TZC_DRAM1_SIZE,	\
+#define TC_MAP_TZC_DRAM1		MAP_REGION_FLAT(		\
+						TC_TZC_DRAM1_BASE,	\
+						TC_TZC_DRAM1_SIZE,	\
 						MT_MEMORY | MT_RW | MT_SECURE)
+
+#define PLAT_HW_CONFIG_DTB_BASE	ULL(0x83000000)
+#define PLAT_HW_CONFIG_DTB_SIZE	ULL(0x8000)
+
+#define PLAT_DTB_DRAM_NS MAP_REGION_FLAT(	\
+					PLAT_HW_CONFIG_DTB_BASE,	\
+					PLAT_HW_CONFIG_DTB_SIZE,	\
+					MT_MEMORY | MT_RO | MT_NS)
 /*
- * Max size of SPMC is 2MB for tc0. With SPMD enabled this value corresponds to
+ * Max size of SPMC is 2MB for tc. With SPMD enabled this value corresponds to
  * max size of BL32 image.
  */
 #if defined(SPD_spmd)
-#define PLAT_ARM_SPMC_BASE		TC0_TZC_DRAM1_BASE
+#define PLAT_ARM_SPMC_BASE		TC_TZC_DRAM1_BASE
 #define PLAT_ARM_SPMC_SIZE		UL(0x200000)  /* 2 MB */
 #endif
 
@@ -122,7 +130,7 @@
  * calculated using the current BL31 PROGBITS debug size plus the sizes of
  * BL2 and BL1-RW
  */
-#define PLAT_ARM_MAX_BL31_SIZE		0x3B000
+#define PLAT_ARM_MAX_BL31_SIZE		0x3F000
 
 /*
  * Size of cacheable stacks
@@ -152,18 +160,18 @@
 #endif
 
 
-#define TC0_DEVICE_BASE			0x21000000
-#define TC0_DEVICE_SIZE			0x5f000000
+#define TC_DEVICE_BASE			0x21000000
+#define TC_DEVICE_SIZE			0x5f000000
 
-// TC0_MAP_DEVICE covers different peripherals
+// TC_MAP_DEVICE covers different peripherals
 // available to the platform
-#define TC0_MAP_DEVICE	MAP_REGION_FLAT(		\
-					TC0_DEVICE_BASE,	\
-					TC0_DEVICE_SIZE,	\
+#define TC_MAP_DEVICE	MAP_REGION_FLAT(		\
+					TC_DEVICE_BASE,	\
+					TC_DEVICE_SIZE,	\
 					MT_DEVICE | MT_RW | MT_SECURE)
 
 
-#define TC0_FLASH0_RO	MAP_REGION_FLAT(V2M_FLASH0_BASE,\
+#define TC_FLASH0_RO	MAP_REGION_FLAT(V2M_FLASH0_BASE,\
 						V2M_FLASH0_SIZE,	\
 						MT_DEVICE | MT_RO | MT_SECURE)
 
@@ -250,14 +258,14 @@
 		(TZC_REGION_ACCESS_RDWR(TZC_NSAID_DEFAULT))
 
 /*
- * The first region below, TC0_TZC_DRAM1_BASE (0xfd000000) to
+ * The first region below, TC_TZC_DRAM1_BASE (0xfd000000) to
  * ARM_SCP_TZC_DRAM1_END (0xffffffff) will mark the last 48 MB of DRAM as
  * secure. The second region gives non secure access to rest of DRAM.
  */
-#define TC0_TZC_REGIONS_DEF						\
-	{TC0_TZC_DRAM1_BASE, ARM_SCP_TZC_DRAM1_END,			\
+#define TC_TZC_REGIONS_DEF						\
+	{TC_TZC_DRAM1_BASE, ARM_SCP_TZC_DRAM1_END,			\
 		TZC_REGION_S_RDWR, PLAT_ARM_TZC_NS_DEV_ACCESS},		\
-	{TC0_NS_DRAM1_BASE, TC0_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \
+	{TC_NS_DRAM1_BASE, TC_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \
 		PLAT_ARM_TZC_NS_DEV_ACCESS}
 
 /* virtual address used by dynamic mem_protect for chunk_base */
diff --git a/plat/arm/board/tc0/include/tc0_helpers.S b/plat/arm/board/tc/include/tc_helpers.S
similarity index 96%
rename from plat/arm/board/tc0/include/tc0_helpers.S
rename to plat/arm/board/tc/include/tc_helpers.S
index 90623a2..5f54856 100644
--- a/plat/arm/board/tc0/include/tc0_helpers.S
+++ b/plat/arm/board/tc/include/tc_helpers.S
@@ -15,7 +15,7 @@
 	/* ---------------------------------------------------------------------
 	 * unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
 	 *
-	 * Function to calculate the core position on TC0.
+	 * Function to calculate the core position on TC.
 	 *
 	 * (ClusterId * PLAT_MAX_CPUS_PER_CLUSTER * PLAT_MAX_PE_PER_CPU) +
 	 * (CPUId * PLAT_MAX_PE_PER_CPU) +
diff --git a/plat/arm/board/tc/include/tc_plat.h b/plat/arm/board/tc/include/tc_plat.h
new file mode 100644
index 0000000..28c0308
--- /dev/null
+++ b/plat/arm/board/tc/include/tc_plat.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TC_PLAT_H
+#define TC_PLAT_H
+
+void tc_bl31_common_platform_setup(void);
+
+#endif /* TC_PLAT_H */
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
new file mode 100644
index 0000000..7ebf639
--- /dev/null
+++ b/plat/arm/board/tc/platform.mk
@@ -0,0 +1,144 @@
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ifeq ($(filter ${TARGET_PLATFORM}, 0 1),)
+        $(error TARGET_PLATFORM must be 0 or 1)
+endif
+
+CSS_LOAD_SCP_IMAGES	:=	1
+
+CSS_USE_SCMI_SDS_DRIVER	:=	1
+
+RAS_EXTENSION		:=	0
+
+SDEI_SUPPORT		:=	0
+
+EL3_EXCEPTION_HANDLING	:=	0
+
+HANDLE_EA_EL3_FIRST	:=	0
+
+# System coherency is managed in hardware
+HW_ASSISTED_COHERENCY	:=	1
+
+# When building for systems with hardware-assisted coherency, there's no need to
+# use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too.
+USE_COHERENT_MEM	:=	0
+
+GIC_ENABLE_V4_EXTN	:=      1
+
+# GIC-600 configuration
+GICV3_SUPPORT_GIC600	:=	1
+
+# Enable SVE
+ENABLE_SVE_FOR_NS	:=	1
+ENABLE_SVE_FOR_SWD	:=	1
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+ENT_GIC_SOURCES		:=	${GICV3_SOURCES}		\
+				plat/common/plat_gicv3.c	\
+				plat/arm/common/arm_gicv3.c
+
+override NEED_BL2U	:=	no
+
+override ARM_PLAT_MT	:=	1
+
+TC_BASE	=	plat/arm/board/tc
+
+PLAT_INCLUDES		+=	-I${TC_BASE}/include/
+
+# Common CPU libraries
+TC_CPU_SOURCES	:=	lib/cpus/aarch64/cortex_a510.S
+
+# CPU libraries for TARGET_PLATFORM=0
+ifeq (${TARGET_PLATFORM}, 0)
+TC_CPU_SOURCES	+=	lib/cpus/aarch64/cortex_a710.S \
+			lib/cpus/aarch64/cortex_x2.S
+endif
+
+# CPU libraries for TARGET_PLATFORM=1
+ifeq (${TARGET_PLATFORM}, 1)
+TC_CPU_SOURCES	+=	lib/cpus/aarch64/cortex_makalu.S \
+			lib/cpus/aarch64/cortex_makalu_elp_arm.S
+endif
+
+INTERCONNECT_SOURCES	:=	${TC_BASE}/tc_interconnect.c
+
+PLAT_BL_COMMON_SOURCES	+=	${TC_BASE}/tc_plat.c	\
+				${TC_BASE}/include/tc_helpers.S
+
+BL1_SOURCES		+=	${INTERCONNECT_SOURCES}	\
+				${TC_CPU_SOURCES}	\
+				${TC_BASE}/tc_trusted_boot.c	\
+				${TC_BASE}/tc_err.c	\
+				drivers/arm/sbsa/sbsa.c
+
+
+BL2_SOURCES		+=	${TC_BASE}/tc_security.c	\
+				${TC_BASE}/tc_err.c		\
+				${TC_BASE}/tc_trusted_boot.c		\
+				${TC_BASE}/tc_bl2_setup.c		\
+				lib/utils/mem_region.c			\
+				drivers/arm/tzc/tzc400.c		\
+				plat/arm/common/arm_tzc400.c		\
+				plat/arm/common/arm_nor_psci_mem_protect.c
+
+BL31_SOURCES		+=	${INTERCONNECT_SOURCES}	\
+				${TC_CPU_SOURCES}	\
+				${ENT_GIC_SOURCES}			\
+				${TC_BASE}/tc_bl31_setup.c	\
+				${TC_BASE}/tc_topology.c	\
+				common/fdt_wrappers.c			\
+				lib/fconf/fconf.c			\
+				lib/fconf/fconf_dyn_cfg_getter.c	\
+				drivers/cfi/v2m/v2m_flash.c		\
+				lib/utils/mem_region.c			\
+				plat/arm/common/arm_nor_psci_mem_protect.c
+
+# Add the FDT_SOURCES and options for Dynamic Config
+FDT_SOURCES		+=	${TC_BASE}/fdts/${PLAT}_fw_config.dts	\
+				${TC_BASE}/fdts/${PLAT}_tb_fw_config.dts
+FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
+
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG}))
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG}))
+
+ifeq (${SPD},spmd)
+ifeq ($(ARM_SPMC_MANIFEST_DTS),)
+ARM_SPMC_MANIFEST_DTS	:=	${TC_BASE}/fdts/${PLAT}_spmc_manifest.dts
+endif
+
+FDT_SOURCES		+=	${ARM_SPMC_MANIFEST_DTS}
+TC_TOS_FW_CONFIG	:=	${BUILD_PLAT}/fdts/$(notdir $(basename ${ARM_SPMC_MANIFEST_DTS})).dtb
+
+# Add the TOS_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TC_TOS_FW_CONFIG},--tos-fw-config,${TC_TOS_FW_CONFIG}))
+endif
+
+#Device tree
+TC_HW_CONFIG_DTS	:=	fdts/tc.dts
+TC_HW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}.dtb
+FDT_SOURCES		+=	${TC_HW_CONFIG_DTS}
+$(eval TC_HW_CONFIG	:=	${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(TC_HW_CONFIG_DTS)))
+
+# Add the HW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TC_HW_CONFIG},--hw-config,${TC_HW_CONFIG}))
+
+override CTX_INCLUDE_AARCH32_REGS	:= 0
+
+override CTX_INCLUDE_PAUTH_REGS	:= 1
+
+override ENABLE_SPE_FOR_LOWER_ELS	:= 0
+
+override ENABLE_AMU := 1
+
+include plat/arm/common/arm_common.mk
+include plat/arm/css/common/css_common.mk
+include plat/arm/soc/common/soc_css.mk
+include plat/arm/board/common/board_common.mk
diff --git a/plat/arm/board/tc/tc_bl2_setup.c b/plat/arm/board/tc/tc_bl2_setup.c
new file mode 100644
index 0000000..74ef569
--- /dev/null
+++ b/plat/arm/board/tc/tc_bl2_setup.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * This function returns the list of executable images
+ ******************************************************************************/
+struct bl_params *plat_get_next_bl_params(void)
+{
+	struct bl_params *arm_bl_params = arm_get_next_bl_params();
+
+	const struct dyn_cfg_dtb_info_t *fw_config_info;
+	bl_mem_params_node_t *param_node;
+	uintptr_t fw_config_base = 0U;
+	entry_point_info_t *ep_info;
+
+	/* Get BL31 image node */
+	param_node = get_bl_mem_params_node(BL31_IMAGE_ID);
+	assert(param_node != NULL);
+
+	/* Get fw_config load address */
+	fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID);
+	assert(fw_config_info != NULL);
+
+	fw_config_base = fw_config_info->config_addr;
+	assert(fw_config_base != 0U);
+
+	/*
+	 * Get the entry point info of BL31 image and override
+	 * arg1 of entry point info with fw_config base address
+	 */
+	ep_info = &param_node->ep_info;
+	ep_info->args.arg1 = (uint32_t)fw_config_base;
+
+	return arm_bl_params;
+}
diff --git a/plat/arm/board/tc/tc_bl31_setup.c b/plat/arm/board/tc/tc_bl31_setup.c
new file mode 100644
index 0000000..0523ef8
--- /dev/null
+++ b/plat/arm/board/tc/tc_bl31_setup.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <libfdt.h>
+#include <tc_plat.h>
+
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <drivers/arm/css/css_mhu_doorbell.h>
+#include <drivers/arm/css/scmi.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+static scmi_channel_plat_info_t tc_scmi_plat_info[] = {
+	{
+		.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
+		.db_reg_addr = PLAT_CSS_MHU_BASE + SENDER_REG_SET(0),
+		.db_preserve_mask = 0xfffffffe,
+		.db_modify_mask = 0x1,
+		.ring_doorbell = &mhuv2_ring_doorbell,
+	}
+};
+
+void bl31_platform_setup(void)
+{
+	tc_bl31_common_platform_setup();
+}
+
+scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id)
+{
+
+	return &tc_scmi_plat_info[channel_id];
+
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				u_register_t arg2, u_register_t arg3)
+{
+	arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
+
+	/* Fill the properties struct with the info from the config dtb */
+	fconf_populate("FW_CONFIG", arg1);
+}
+
+void tc_bl31_common_platform_setup(void)
+{
+	arm_bl31_platform_setup();
+}
+
+const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
+{
+	return css_scmi_override_pm_ops(ops);
+}
+
+void __init bl31_plat_arch_setup(void)
+{
+	arm_bl31_plat_arch_setup();
+
+	/* HW_CONFIG was also loaded by BL2 */
+	const struct dyn_cfg_dtb_info_t *hw_config_info;
+
+	hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID);
+	assert(hw_config_info != NULL);
+
+	fconf_populate("HW_CONFIG", hw_config_info->config_addr);
+}
diff --git a/plat/arm/board/tc0/tc0_err.c b/plat/arm/board/tc/tc_err.c
similarity index 91%
rename from plat/arm/board/tc0/tc0_err.c
rename to plat/arm/board/tc/tc_err.c
index 83f2e9f..9ed7e92 100644
--- a/plat/arm/board/tc0/tc0_err.c
+++ b/plat/arm/board/tc/tc_err.c
@@ -7,7 +7,7 @@
 #include <plat/arm/common/plat_arm.h>
 
 /*
- * tc0 error handler
+ * tc error handler
  */
 void __dead2 plat_arm_error_handler(int err)
 {
diff --git a/plat/arm/board/tc0/tc0_interconnect.c b/plat/arm/board/tc/tc_interconnect.c
similarity index 100%
rename from plat/arm/board/tc0/tc0_interconnect.c
rename to plat/arm/board/tc/tc_interconnect.c
diff --git a/plat/arm/board/tc0/tc0_plat.c b/plat/arm/board/tc/tc_plat.c
similarity index 93%
rename from plat/arm/board/tc0/tc0_plat.c
rename to plat/arm/board/tc/tc_plat.c
index b5698c0..a9668e1 100644
--- a/plat/arm/board/tc0/tc0_plat.c
+++ b/plat/arm/board/tc/tc_plat.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -28,19 +28,19 @@
 #if IMAGE_BL1
 const mmap_region_t plat_arm_mmap[] = {
 	ARM_MAP_SHARED_RAM,
-	TC0_FLASH0_RO,
-	TC0_MAP_DEVICE,
+	TC_FLASH0_RO,
+	TC_MAP_DEVICE,
 	{0}
 };
 #endif
 #if IMAGE_BL2
 const mmap_region_t plat_arm_mmap[] = {
 	ARM_MAP_SHARED_RAM,
-	TC0_FLASH0_RO,
-	TC0_MAP_DEVICE,
-	TC0_MAP_NS_DRAM1,
+	TC_FLASH0_RO,
+	TC_MAP_DEVICE,
+	TC_MAP_NS_DRAM1,
 #if defined(SPD_spmd)
-	TC0_MAP_TZC_DRAM1,
+	TC_MAP_TZC_DRAM1,
 #endif
 #if ARM_BL31_IN_DRAM
 	ARM_MAP_BL31_SEC_DRAM,
@@ -62,7 +62,8 @@
 const mmap_region_t plat_arm_mmap[] = {
 	ARM_MAP_SHARED_RAM,
 	V2M_MAP_IOFPGA,
-	TC0_MAP_DEVICE,
+	TC_MAP_DEVICE,
+	PLAT_DTB_DRAM_NS,
 #if SPM_MM
 	ARM_SPM_BUF_EL3_MMAP,
 #endif
diff --git a/plat/arm/board/tc0/tc0_security.c b/plat/arm/board/tc/tc_security.c
similarity index 94%
rename from plat/arm/board/tc0/tc0_security.c
rename to plat/arm/board/tc/tc_security.c
index f543762..6a34501 100644
--- a/plat/arm/board/tc0/tc0_security.c
+++ b/plat/arm/board/tc/tc_security.c
@@ -8,7 +8,7 @@
 #include <platform_def.h>
 
 static const arm_tzc_regions_info_t tzc_regions[] = {
-	TC0_TZC_REGIONS_DEF,
+	TC_TZC_REGIONS_DEF,
 	{}
 };
 
diff --git a/plat/arm/board/tc0/tc0_topology.c b/plat/arm/board/tc/tc_topology.c
similarity index 96%
rename from plat/arm/board/tc0/tc0_topology.c
rename to plat/arm/board/tc/tc_topology.c
index 8cfc3b5..9e18da6 100644
--- a/plat/arm/board/tc0/tc0_topology.c
+++ b/plat/arm/board/tc/tc_topology.c
@@ -10,7 +10,7 @@
 /******************************************************************************
  * The power domain tree descriptor.
  ******************************************************************************/
-const unsigned char tc0_pd_tree_desc[] = {
+const unsigned char tc_pd_tree_desc[] = {
 	PLAT_ARM_CLUSTER_COUNT,
 	PLAT_MAX_CPUS_PER_CLUSTER,
 };
@@ -20,7 +20,7 @@
  ******************************************************************************/
 const unsigned char *plat_get_power_domain_tree_desc(void)
 {
-	return tc0_pd_tree_desc;
+	return tc_pd_tree_desc;
 }
 
 /*******************************************************************************
diff --git a/plat/arm/board/tc0/tc0_trusted_boot.c b/plat/arm/board/tc/tc_trusted_boot.c
similarity index 100%
rename from plat/arm/board/tc0/tc0_trusted_boot.c
rename to plat/arm/board/tc/tc_trusted_boot.c
diff --git a/plat/arm/board/tc0/include/tc0_plat.h b/plat/arm/board/tc0/include/tc0_plat.h
deleted file mode 100644
index f0cb431..0000000
--- a/plat/arm/board/tc0/include/tc0_plat.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef tc0_bl31_common_platform_setup_PLAT_H
-#define tc0_bl31_common_platform_setup_PLAT_H
-
-void tc0_bl31_common_platform_setup(void);
-
-#endif /* tc0_bl31_common_platform_setup_PLAT_H */
diff --git a/plat/arm/board/tc0/platform.mk b/plat/arm/board/tc0/platform.mk
deleted file mode 100644
index 5ae87d1..0000000
--- a/plat/arm/board/tc0/platform.mk
+++ /dev/null
@@ -1,122 +0,0 @@
-# Copyright (c) 2020-2021, Arm Limited. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-CSS_LOAD_SCP_IMAGES	:=	1
-
-CSS_USE_SCMI_SDS_DRIVER	:=	1
-
-RAS_EXTENSION		:=	0
-
-SDEI_SUPPORT		:=	0
-
-EL3_EXCEPTION_HANDLING	:=	0
-
-HANDLE_EA_EL3_FIRST	:=	0
-
-# System coherency is managed in hardware
-HW_ASSISTED_COHERENCY	:=	1
-
-# When building for systems with hardware-assisted coherency, there's no need to
-# use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too.
-USE_COHERENT_MEM	:=	0
-
-GIC_ENABLE_V4_EXTN	:=      1
-
-# GIC-600 configuration
-GICV3_SUPPORT_GIC600	:=	1
-
-
-# Include GICv3 driver files
-include drivers/arm/gic/v3/gicv3.mk
-
-ENT_GIC_SOURCES		:=	${GICV3_SOURCES}		\
-				plat/common/plat_gicv3.c	\
-				plat/arm/common/arm_gicv3.c
-
-override NEED_BL2U	:=	no
-
-override ARM_PLAT_MT	:=	1
-
-TC0_BASE	=	plat/arm/board/tc0
-
-PLAT_INCLUDES		+=	-I${TC0_BASE}/include/
-
-TC0_CPU_SOURCES	:=	lib/cpus/aarch64/cortex_a510.S         \
-			lib/cpus/aarch64/cortex_a710.S \
-			lib/cpus/aarch64/cortex_x2.S
-
-INTERCONNECT_SOURCES	:=	${TC0_BASE}/tc0_interconnect.c
-
-PLAT_BL_COMMON_SOURCES	+=	${TC0_BASE}/tc0_plat.c	\
-				${TC0_BASE}/include/tc0_helpers.S
-
-BL1_SOURCES		+=	${INTERCONNECT_SOURCES}	\
-				${TC0_CPU_SOURCES}	\
-				${TC0_BASE}/tc0_trusted_boot.c	\
-				${TC0_BASE}/tc0_err.c	\
-				drivers/arm/sbsa/sbsa.c
-
-
-BL2_SOURCES		+=	${TC0_BASE}/tc0_security.c	\
-				${TC0_BASE}/tc0_err.c		\
-				${TC0_BASE}/tc0_trusted_boot.c		\
-				lib/utils/mem_region.c			\
-				drivers/arm/tzc/tzc400.c		\
-				plat/arm/common/arm_tzc400.c		\
-				plat/arm/common/arm_nor_psci_mem_protect.c
-
-BL31_SOURCES		+=	${INTERCONNECT_SOURCES}	\
-				${TC0_CPU_SOURCES}	\
-				${ENT_GIC_SOURCES}			\
-				${TC0_BASE}/tc0_bl31_setup.c	\
-				${TC0_BASE}/tc0_topology.c	\
-				drivers/cfi/v2m/v2m_flash.c		\
-				lib/utils/mem_region.c			\
-				plat/arm/common/arm_nor_psci_mem_protect.c
-
-# Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES		+=	${TC0_BASE}/fdts/${PLAT}_fw_config.dts	\
-				${TC0_BASE}/fdts/${PLAT}_tb_fw_config.dts
-FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
-TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
-
-# Add the FW_CONFIG to FIP and specify the same to certtool
-$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG}))
-# Add the TB_FW_CONFIG to FIP and specify the same to certtool
-$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG}))
-
-ifeq (${SPD},spmd)
-ifeq ($(ARM_SPMC_MANIFEST_DTS),)
-ARM_SPMC_MANIFEST_DTS	:=	${TC0_BASE}/fdts/${PLAT}_spmc_manifest.dts
-endif
-
-FDT_SOURCES		+=	${ARM_SPMC_MANIFEST_DTS}
-TC0_TOS_FW_CONFIG	:=	${BUILD_PLAT}/fdts/$(notdir $(basename ${ARM_SPMC_MANIFEST_DTS})).dtb
-
-# Add the TOS_FW_CONFIG to FIP and specify the same to certtool
-$(eval $(call TOOL_ADD_PAYLOAD,${TC0_TOS_FW_CONFIG},--tos-fw-config,${TC0_TOS_FW_CONFIG}))
-endif
-
-#Device tree
-TC0_HW_CONFIG_DTS	:=	fdts/tc0.dts
-TC0_HW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}.dtb
-FDT_SOURCES		+=	${TC0_HW_CONFIG_DTS}
-$(eval TC0_HW_CONFIG	:=	${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(TC0_HW_CONFIG_DTS)))
-
-# Add the HW_CONFIG to FIP and specify the same to certtool
-$(eval $(call TOOL_ADD_PAYLOAD,${TC0_HW_CONFIG},--hw-config,${TC0_HW_CONFIG}))
-
-override CTX_INCLUDE_AARCH32_REGS	:= 0
-
-override CTX_INCLUDE_PAUTH_REGS	:= 1
-
-override ENABLE_SPE_FOR_LOWER_ELS	:= 0
-
-override ENABLE_AMU := 1
-
-include plat/arm/common/arm_common.mk
-include plat/arm/css/common/css_common.mk
-include plat/arm/soc/common/soc_css.mk
-include plat/arm/board/common/board_common.mk
diff --git a/plat/arm/board/tc0/tc0_bl31_setup.c b/plat/arm/board/tc0/tc0_bl31_setup.c
deleted file mode 100644
index b91b11c..0000000
--- a/plat/arm/board/tc0/tc0_bl31_setup.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-
-#include <libfdt.h>
-#include <tc0_plat.h>
-
-#include <common/bl_common.h>
-#include <common/debug.h>
-#include <drivers/arm/css/css_mhu_doorbell.h>
-#include <drivers/arm/css/scmi.h>
-#include <plat/arm/common/plat_arm.h>
-#include <plat/common/platform.h>
-
-static scmi_channel_plat_info_t tc0_scmi_plat_info[] = {
-	{
-		.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
-		.db_reg_addr = PLAT_CSS_MHU_BASE + SENDER_REG_SET(0),
-		.db_preserve_mask = 0xfffffffe,
-		.db_modify_mask = 0x1,
-		.ring_doorbell = &mhuv2_ring_doorbell,
-	}
-};
-
-void bl31_platform_setup(void)
-{
-	tc0_bl31_common_platform_setup();
-}
-
-scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id)
-{
-
-	return &tc0_scmi_plat_info[channel_id];
-
-}
-
-void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
-				u_register_t arg2, u_register_t arg3)
-{
-	arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
-}
-
-void tc0_bl31_common_platform_setup(void)
-{
-	arm_bl31_platform_setup();
-}
-
-const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops)
-{
-	return css_scmi_override_pm_ops(ops);
-}
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 63ed9fe..26af383 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -94,13 +94,10 @@
 {
 	arm_bl2_dyn_cfg_init();
 
-#if ARM_GPT_SUPPORT
-	int result = arm_set_image_source(FIP_IMAGE_ID, "FIP_A");
-
-	if (result != 0) {
-		panic();
-	}
-#endif /* ARM_GPT_SUPPORT */
+#if ARM_GPT_SUPPORT && !PSA_FWU_SUPPORT
+	/* Always use the FIP from bank 0 */
+	arm_set_fip_addr(0U);
+#endif /* ARM_GPT_SUPPORT && !PSA_FWU_SUPPORT */
 }
 
 /*
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index de25a53..4d5e8b4 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -185,6 +185,18 @@
   BL2_CPPFLAGS += -march=armv8-a+crc
 endif
 
+ifeq ($(PSA_FWU_SUPPORT),1)
+    # GPT support is recommended as per PSA FWU specification hence
+    # PSA FWU implementation is tightly coupled with GPT support,
+    # and it does not support other formats.
+    ifneq ($(ARM_GPT_SUPPORT),1)
+      $(error For PSA_FWU_SUPPORT, ARM_GPT_SUPPORT must be enabled)
+    endif
+    FWU_MK := drivers/fwu/fwu.mk
+    $(info Including ${FWU_MK})
+    include ${FWU_MK}
+endif
+
 ifeq (${ARCH}, aarch64)
 PLAT_INCLUDES		+=	-Iinclude/plat/arm/common/aarch64
 endif
@@ -230,7 +242,7 @@
 				drivers/io/io_storage.c				\
 				plat/arm/common/arm_bl2_setup.c			\
 				plat/arm/common/arm_err.c			\
-				common/hw_crc32.c				\
+				common/tf_crc32.c				\
 				${ARM_IO_SOURCES}
 
 # Firmware Configuration Framework sources
diff --git a/plat/arm/common/arm_io_storage.c b/plat/arm/common/arm_io_storage.c
index c5d913e..387086a 100644
--- a/plat/arm/common/arm_io_storage.c
+++ b/plat/arm/common/arm_io_storage.c
@@ -5,6 +5,7 @@
  */
 
 #include <common/debug.h>
+#include <drivers/fwu/fwu_metadata.h>
 #include <drivers/io/io_driver.h>
 #include <drivers/io/io_fip.h>
 #include <drivers/io/io_memmap.h>
@@ -24,6 +25,13 @@
 static const io_dev_connector_t *memmap_dev_con;
 uintptr_t memmap_dev_handle;
 
+#if ARM_GPT_SUPPORT
+/* fip partition names */
+static const char * const fip_part_names[] = {"FIP_A", "FIP_B"};
+CASSERT(sizeof(fip_part_names)/sizeof(char *) == NR_OF_FW_BANKS,
+	assert_fip_partition_names_missing);
+#endif /* ARM_GPT_SUPPORT */
+
 /* Weak definitions may be overridden in specific ARM standard platform */
 #pragma weak plat_arm_io_setup
 #pragma weak plat_arm_get_alt_image_source
@@ -139,17 +147,20 @@
 }
 
 #if ARM_GPT_SUPPORT
-/**********************************************************************
- * arm_set_image_source: Set image specification in IO policy
+/******************************************************************************
+ * Retrieve partition entry details such as offset and length, and set these
+ * details in the I/O policy of the requested image.
  *
- * @image_id: id of the image whose specification to be set
+ * @image_id: image id whose I/O policy to be updated
  *
- * @part_name: name of the partition that to be read for entry details
+ * @part_name: partition name whose details to be retrieved
  *
- * set the entry and offset details of partition in global IO policy
- * of the image
- *********************************************************************/
-int arm_set_image_source(unsigned int image_id, const char *part_name)
+ * Returns 0 on success, error otherwise
+ * Alongside, returns device handle and image specification of requested
+ * image.
+ ******************************************************************************/
+int arm_set_image_source(unsigned int image_id, const char *part_name,
+			 uintptr_t *dev_handle, uintptr_t *image_spec)
 {
 	const partition_entry_t *entry = get_partition_entry(part_name);
 
@@ -158,19 +169,82 @@
 		return -ENOENT;
 	}
 
-	const struct plat_io_policy *policy = FCONF_GET_PROPERTY(arm,
-								 io_policies,
-								 image_id);
+	struct plat_io_policy *policy = FCONF_GET_PROPERTY(arm,
+							   io_policies,
+							   image_id);
 
 	assert(policy != NULL);
 	assert(policy->image_spec != 0UL);
 
+	io_block_spec_t *spec = (io_block_spec_t *)policy->image_spec;
 	/* set offset and length of the image */
-	io_block_spec_t *image_spec = (io_block_spec_t *)policy->image_spec;
+	spec->offset = PLAT_ARM_FLASH_IMAGE_BASE + entry->start;
+	spec->length = entry->length;
 
-	image_spec->offset = PLAT_ARM_FLASH_IMAGE_BASE + entry->start;
-	image_spec->length = entry->length;
+	*dev_handle = *(policy->dev_handle);
+	*image_spec = policy->image_spec;
 
 	return 0;
 }
+
+/*******************************************************************************
+ * Set the source offset and length of the FIP image in its I/O policy.
+ *
+ * @active_fw_bank_idx: active firmware bank index gathered from FWU metadata.
+ ******************************************************************************/
+void arm_set_fip_addr(uint32_t active_fw_bank_idx)
+{
+	uintptr_t dev_handle __unused;
+	uintptr_t image_spec __unused;
+
+	assert(active_fw_bank_idx < NR_OF_FW_BANKS);
+
+	INFO("Booting with partition %s\n", fip_part_names[active_fw_bank_idx]);
+
+	int result = arm_set_image_source(FIP_IMAGE_ID,
+					  fip_part_names[active_fw_bank_idx],
+					  &dev_handle,
+					  &image_spec);
+	if (result != 0) {
+		panic();
+	}
+}
+#endif /* ARM_GPT_SUPPORT */
+
+#if PSA_FWU_SUPPORT
+/*******************************************************************************
+ * Read the FIP partition of the GPT image corresponding to the active firmware
+ * bank to get its offset and length, and update these details in the I/O policy
+ * of the FIP image.
+ ******************************************************************************/
+void plat_fwu_set_images_source(struct fwu_metadata *metadata)
+{
+	arm_set_fip_addr(metadata->active_index);
+}
+
+/*******************************************************************************
+ * Read the requested FWU metadata partition of the GPT image to get its offset
+ * and length, and update these details in the I/O policy of the requested FWU
+ * metadata image.
+ ******************************************************************************/
+int plat_fwu_set_metadata_image_source(unsigned int image_id,
+				       uintptr_t *dev_handle,
+				       uintptr_t *image_spec)
+{
+	int result = -1;
+
+	if (image_id == FWU_METADATA_IMAGE_ID) {
+		result = arm_set_image_source(FWU_METADATA_IMAGE_ID,
+					      "FWU-Metadata",
+					      dev_handle,
+					      image_spec);
+	} else if (image_id == BKUP_FWU_METADATA_IMAGE_ID) {
+		result = arm_set_image_source(BKUP_FWU_METADATA_IMAGE_ID,
+					      "Bkup-FWU-Metadata",
+					      dev_handle,
+					      image_spec);
+	}
+
+	return result;
+}
-#endif
+#endif /* PSA_FWU_SUPPORT */
diff --git a/plat/arm/common/fconf/arm_fconf_io.c b/plat/arm/common/fconf/arm_fconf_io.c
index 8e4469f..86fd6d5 100644
--- a/plat/arm/common/fconf/arm_fconf_io.c
+++ b/plat/arm/common/fconf/arm_fconf_io.c
@@ -18,6 +18,11 @@
 #include <plat/arm/common/arm_fconf_io_storage.h>
 #include <platform_def.h>
 
+#if PSA_FWU_SUPPORT
+/* metadata entry details */
+static io_block_spec_t fwu_metadata_spec;
+#endif /* PSA_FWU_SUPPORT */
+
 io_block_spec_t fip_block_spec = {
 /*
  * This is fixed FIP address used by BL1, BL2 loads partition table
@@ -92,6 +97,20 @@
 		open_memmap
 	},
 #endif /* ARM_GPT_SUPPORT */
+#if PSA_FWU_SUPPORT
+	[FWU_METADATA_IMAGE_ID] = {
+		&memmap_dev_handle,
+		/* filled runtime from partition information */
+		(uintptr_t)&fwu_metadata_spec,
+		open_memmap
+	},
+	[BKUP_FWU_METADATA_IMAGE_ID] = {
+		&memmap_dev_handle,
+		/* filled runtime from partition information */
+		(uintptr_t)&fwu_metadata_spec,
+		open_memmap
+	},
+#endif /* PSA_FWU_SUPPORT */
 	[FIP_IMAGE_ID] = {
 		&memmap_dev_handle,
 		(uintptr_t)&fip_block_spec,
diff --git a/plat/arm/css/sgi/sgi_ras.c b/plat/arm/css/sgi/sgi_ras.c
index 7aa477d..4f03ac4 100644
--- a/plat/arm/css/sgi/sgi_ras.c
+++ b/plat/arm/css/sgi/sgi_ras.c
@@ -20,13 +20,6 @@
 static int sgi_ras_intr_handler(const struct err_record_info *err_rec,
 				int probe_data,
 				const struct err_handler_data *const data);
-struct efi_guid {
-	uint32_t	data1;
-	uint16_t	data2;
-	uint16_t	data3;
-	uint8_t		data4[8];
-};
-
 typedef struct mm_communicate_header {
 	struct efi_guid	header_guid;
 	size_t		message_len;
diff --git a/plat/common/aarch64/plat_common.c b/plat/common/aarch64/plat_common.c
index ba4c366..345fec3 100644
--- a/plat/common/aarch64/plat_common.c
+++ b/plat/common/aarch64/plat_common.c
@@ -28,7 +28,7 @@
 #pragma weak plat_sdei_validate_entry_point
 #endif
 
-#pragma weak plat_ea_handler
+#pragma weak plat_ea_handler = plat_default_ea_handler
 
 void bl31_plat_runtime_setup(void)
 {
@@ -79,7 +79,7 @@
 #endif /* !ENABLE_BACKTRACE */
 
 /* RAS functions common to AArch64 ARM platforms */
-void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
+void plat_default_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
 		void *handle, uint64_t flags)
 {
 #if RAS_EXTENSION
@@ -90,6 +90,7 @@
 #endif
 	unsigned int level = (unsigned int)GET_EL(read_spsr_el3());
 
+	ERROR_NL();
 	ERROR("Unhandled External Abort received on 0x%lx from %s\n",
 		read_mpidr_el1(), get_el_str(level));
 	ERROR("exception reason=%u syndrome=0x%llx\n", ea_reason, syndrome);
diff --git a/plat/imx/imx8m/imx8mm/include/platform_def.h b/plat/imx/imx8m/imx8mm/include/platform_def.h
index f8efa56..940d22b 100644
--- a/plat/imx/imx8m/imx8mm/include/platform_def.h
+++ b/plat/imx/imx8m/imx8mm/include/platform_def.h
@@ -42,7 +42,7 @@
 #define BL31_BASE			U(0x900000)
 #define BL31_LIMIT			U(0x920000)
 #define IMX8MM_FIP_BASE			U(0x40310000)
-#define IMX8MM_FIP_SIZE			U(0x000200000)
+#define IMX8MM_FIP_SIZE			U(0x000300000)
 #define IMX8MM_FIP_LIMIT		U(FIP_BASE + FIP_SIZE)
 
 /* Define FIP image location on eMMC */
@@ -56,7 +56,7 @@
 
 /* non-secure uboot base */
 #define PLAT_NS_IMAGE_OFFSET		U(0x40200000)
-#define PLAT_NS_IMAGE_SIZE		U(0x00100000)
+#define PLAT_NS_IMAGE_SIZE		U(0x00200000)
 
 /* GICv3 base address */
 #define PLAT_GICD_BASE			U(0x38800000)
diff --git a/plat/marvell/armada/a3k/common/a3700_common.mk b/plat/marvell/armada/a3k/common/a3700_common.mk
index 0a89742..9550452 100644
--- a/plat/marvell/armada/a3k/common/a3700_common.mk
+++ b/plat/marvell/armada/a3k/common/a3700_common.mk
@@ -13,7 +13,7 @@
 PLAT_COMMON_BASE		:= $(PLAT_FAMILY_BASE)/common
 MARVELL_DRV_BASE		:= drivers/marvell
 MARVELL_COMMON_BASE		:= $(MARVELL_PLAT_BASE)/common
-HANDLE_EA_EL3_FIRST		:= 1
+ERRATA_A53_1530924		:= 1
 
 include plat/marvell/marvell.mk
 
@@ -53,7 +53,6 @@
 				$(PLAT_COMMON_BASE)/dram_win.c		\
 				$(PLAT_COMMON_BASE)/io_addr_dec.c	\
 				$(PLAT_COMMON_BASE)/marvell_plat_config.c     \
-				$(PLAT_COMMON_BASE)/a3700_ea.c		\
 				$(PLAT_FAMILY_BASE)/$(PLAT)/plat_bl31_setup.c \
 				$(MARVELL_COMMON_BASE)/marvell_cci.c	\
 				$(MARVELL_COMMON_BASE)/marvell_ddr_info.c	\
@@ -63,6 +62,10 @@
 				$(PLAT_COMMON_BASE)/a3700_sip_svc.c	\
 				$(MARVELL_DRV)
 
+ifeq ($(HANDLE_EA_EL3_FIRST),1)
+BL31_SOURCES		+=	$(PLAT_COMMON_BASE)/a3700_ea.c
+endif
+
 ifeq ($(CM3_SYSTEM_RESET),1)
 BL31_SOURCES		+=	$(PLAT_COMMON_BASE)/cm3_system_reset.c
 endif
diff --git a/plat/marvell/armada/a3k/common/a3700_ea.c b/plat/marvell/armada/a3k/common/a3700_ea.c
index dd46beb..4a58fc6 100644
--- a/plat/marvell/armada/a3k/common/a3700_ea.c
+++ b/plat/marvell/armada/a3k/common/a3700_ea.c
@@ -7,17 +7,80 @@
 #include <common/bl_common.h>
 #include <common/debug.h>
 #include <arch_helpers.h>
+#include <plat/common/platform.h>
+#include <bl31/ea_handle.h>
 
-#define ADVK_SERROR_SYNDROME 0xbf000002
+#define A53_SERR_INT_AXI_SLVERR_ON_EXTERNAL_ACCESS 0xbf000002
 
+#if !ENABLE_BACKTRACE
+static const char *get_el_str(unsigned int el)
+{
+	if (el == MODE_EL3) {
+		return "EL3";
+	} else if (el == MODE_EL2) {
+		return "EL2";
+	}
+	return "S-EL1";
+}
+#endif /* !ENABLE_BACKTRACE */
+
+/*
+ * This source file with custom plat_ea_handler function is compiled only when
+ * building TF-A with compile option HANDLE_EA_EL3_FIRST=1
+ */
 void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie,
 		void *handle, uint64_t flags)
 {
-	if (syndrome != ADVK_SERROR_SYNDROME) {
-		ERROR("Unhandled External Abort received on 0x%lx at EL3!\n",
-			read_mpidr_el1());
-		ERROR(" exception reason=%u syndrome=0x%llx\n", ea_reason,
-				syndrome);
-		panic();
+	unsigned int level = (unsigned int)GET_EL(read_spsr_el3());
+
+	/*
+	 * Asynchronous External Abort with syndrome 0xbf000002 on Cortex A53
+	 * core means SError interrupt caused by AXI SLVERR on external access.
+	 *
+	 * In most cases this indicates a bug in U-Boot or Linux kernel driver
+	 * pci-aardvark.c which implements access to A3700 PCIe config space.
+	 * Driver does not wait for PCIe PIO transfer completion and try to
+	 * start a new PCIe PIO transfer while previous has not finished yet.
+	 * A3700 PCIe controller in this case sends SLVERR via AXI which results
+	 * in a fatal Asynchronous SError interrupt on Cortex A53 CPU.
+	 *
+	 * Following patches fix that bug in U-Boot and Linux kernel drivers:
+	 * https://source.denx.de/u-boot/u-boot/-/commit/eccbd4ad8e4e182638eafbfb87ac139c04f24a01
+	 * https://git.kernel.org/stable/c/f18139966d072dab8e4398c95ce955a9742e04f7
+	 *
+	 * As a hacky workaround for unpatched U-Boot and Linux kernel drivers
+	 * ignore all asynchronous aborts with that syndrome value received on
+	 * CPU from level lower than EL3.
+	 *
+	 * Because these aborts are delivered on CPU asynchronously, they are
+	 * imprecise and we cannot check the real reason of abort and neither
+	 * who and why sent this abort. We expect that on A3700 it is always
+	 * PCIe controller.
+	 *
+	 * Hence ignoring all aborts with this syndrome value is just a giant
+	 * hack that we need only because of bugs in old U-Boot and Linux kernel
+	 * versions and because it was decided that TF-A would implement this
+	 * hack for U-Boot and Linux kernel it in this way. New patched U-Boot
+	 * and kernel versions do not need it anymore.
+	 *
+	 * Links to discussion about this workaround:
+	 * https://lore.kernel.org/linux-pci/20190316161243.29517-1-repk@triplefau.lt/
+	 * https://lore.kernel.org/linux-pci/971be151d24312cc533989a64bd454b4@www.loen.fr/
+	 * https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/1541
+	 */
+	if (level < MODE_EL3 && ea_reason == ERROR_EA_ASYNC &&
+	    syndrome == A53_SERR_INT_AXI_SLVERR_ON_EXTERNAL_ACCESS) {
+		ERROR_NL();
+		ERROR("Ignoring Asynchronous External Abort with"
+		     " syndrome 0x%llx received on 0x%lx from %s\n",
+		     syndrome, read_mpidr_el1(), get_el_str(level));
+		ERROR("SError interrupt: AXI SLVERR on external access\n");
+		ERROR("This indicates a bug in pci-aardvark.c driver\n");
+		ERROR("Please update U-Boot/Linux to the latest version\n");
+		ERROR_NL();
+		console_flush();
+		return;
 	}
+
+	plat_default_ea_handler(ea_reason, syndrome, cookie, handle, flags);
 }
diff --git a/plat/marvell/armada/a8k/common/a8k_common.mk b/plat/marvell/armada/a8k/common/a8k_common.mk
index 773b912..30e6280 100644
--- a/plat/marvell/armada/a8k/common/a8k_common.mk
+++ b/plat/marvell/armada/a8k/common/a8k_common.mk
@@ -80,7 +80,7 @@
 				drivers/arm/gic/v2/gicv2_helpers.c	\
 				plat/common/plat_gicv2.c
 
-PLAT_INCLUDES		:=	-I$(BOARD_DIR)				\
+PLAT_INCLUDES		+=	-I$(BOARD_DIR)				\
 				-I$(BOARD_DIR)/board			\
 				-I$(CURDIR)/drivers/marvell		\
 				-I$(PLAT_COMMON_BASE)/include		\
@@ -89,8 +89,10 @@
 PLAT_BL_COMMON_SOURCES	:=	$(PLAT_COMMON_BASE)/aarch64/a8k_common.c \
 				drivers/ti/uart/aarch64/16550_console.S
 
+ifndef BLE_PORTING_SOURCES
 BLE_PORTING_SOURCES	:=	$(BOARD_DIR)/board/dram_port.c \
 				$(BOARD_DIR)/board/marvell_plat_config.c
+endif
 
 MARVELL_MOCHI_DRV	+=	$(MARVELL_DRV_BASE)/mochi/cp110_setup.c
 
@@ -125,7 +127,9 @@
 MARVELL_DRV		+=	$(MARVELL_DRV_BASE)/mg_conf_cm3/mg_conf_cm3.c
 endif
 
+ifndef BL31_PORTING_SOURCES
 BL31_PORTING_SOURCES	:=	$(BOARD_DIR)/board/marvell_plat_config.c
+endif
 
 ifeq ($(SYSTEM_POWER_SUPPORT),1)
 BL31_PORTING_SOURCES	+=	$(BOARD_DIR)/board/system_power.c
diff --git a/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c b/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c
new file mode 100644
index 0000000..5bae8eb
--- /dev/null
+++ b/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ * Copyright (C) 2021 Semihalf.
+ *
+ * SPDX-License-Identifier:	BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <armada_common.h>
+#include <mvebu_def.h>
+
+/*
+ * If bootrom is currently at BLE there's no need to include the memory
+ * maps structure at this point
+ */
+#ifndef IMAGE_BLE
+
+/*****************************************************************************
+ * AMB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win amb_memory_map_cp0[] = {
+	/* CP0 SPI1 CS0 Direct Mode access */
+	{0xef00,	0x1000000,	AMB_SPI1_CS0_ID},
+};
+
+struct addr_map_win amb_memory_map_cp1[] = {
+	/* CP1 SPI1 CS0 Direct Mode access */
+	{0xe800,	0x1000000,	AMB_SPI1_CS0_ID},
+};
+
+int marvell_get_amb_memory_map(struct addr_map_win **win, uint32_t *size,
+			       uintptr_t base)
+{
+	switch (base) {
+	case MVEBU_CP_REGS_BASE(0):
+		*win = amb_memory_map_cp0;
+		*size = ARRAY_SIZE(amb_memory_map_cp0);
+		return 0;
+	case MVEBU_CP_REGS_BASE(1):
+		*win = amb_memory_map_cp1;
+		*size = ARRAY_SIZE(amb_memory_map_cp1);
+		return 0;
+	case MVEBU_CP_REGS_BASE(2):
+	default:
+		*size = 0;
+		*win = 0;
+		return 1;
+	}
+}
+#endif
+
+/*****************************************************************************
+ * IO WIN Configuration
+ *****************************************************************************
+ */
+struct addr_map_win io_win_memory_map[] = {
+#if (CP_COUNT > 1)
+	/* SB (MCi0) internal regs */
+	{0x00000000f4000000,		0x2000000,	MCI_0_TID},
+	/* SB (MCi0) PCIe0-2 on CP1 */
+	{0x00000000e2000000,		0x7000000,	MCI_0_TID},
+	/*
+	 * Due to lack of sufficient number of IO windows registers,
+	 * below CP1 PCIE configuration must be performed in the
+	 * later firmware stages. It should replace the MCI 0 indirect
+	 * window, which becomes no longer needed.
+	 */
+	/* {0x0000000890000000,		0x30000000,	MCI_0_TID}, */
+#if (CP_COUNT > 2)
+	/* SB (MCi1) internal regs */
+	{0x00000000f6000000,		0x2000000,	MCI_1_TID},
+	/* SB (MCi1) PCIe0-2 on CP2 */
+	{0x00000000e9000000,		0x6000000,	MCI_1_TID},
+	/*
+	 * Due to lack of sufficient number of IO windows registers,
+	 * below CP2 PCIE configuration must be performed in the
+	 * later firmware stages. It should replace the MCI 1 indirect
+	 * window, which becomes no longer needed.
+	 */
+	/* {0x00000008c0000000,		0x30000000,	MCI_1_TID}, */
+#endif
+#endif
+#ifndef IMAGE_BLE
+	/* MCI 0 indirect window */
+	{MVEBU_MCI_REG_BASE_REMAP(0),	0x100000,	MCI_0_TID},
+	/* MCI 1 indirect window */
+	{MVEBU_MCI_REG_BASE_REMAP(1),	0x100000,	MCI_1_TID},
+#endif
+};
+
+/* Global Control Register - window default target */
+uint32_t marvell_get_io_win_gcr_target(int ap_index)
+{
+	/*
+	 * PIDI == iMCIP AP to SB internal MoChi connection.
+	 * In other words CP0
+	 */
+	return PIDI_TID;
+}
+
+int marvell_get_io_win_memory_map(int ap_index, struct addr_map_win **win,
+				  uint32_t *size)
+{
+	*win = io_win_memory_map;
+	if (*win == NULL)
+		*size = 0;
+	else
+		*size = ARRAY_SIZE(io_win_memory_map);
+
+	return 0;
+}
+
+#ifndef IMAGE_BLE
+/*****************************************************************************
+ * IOB Configuration
+ *****************************************************************************
+ */
+struct addr_map_win iob_memory_map_cp0[] = {
+	/* SPI1_CS0 (RUNIT) window */
+	{0x00000000ef000000,	0x1000000,	RUNIT_TID},
+	/* PEX2_X1 window */
+	{0x00000000e1000000,	0x1000000,	PEX2_TID},
+	/* PEX1_X1 window */
+	{0x00000000e0000000,	0x1000000,	PEX1_TID},
+	/* PEX0_X4 window */
+	{0x00000000c0000000,	0x20000000,	PEX0_TID},
+	{0x0000000800000000,	0x90000000,	PEX0_TID},
+};
+
+struct addr_map_win iob_memory_map_cp1[] = {
+	/* SPI1_CS0 (RUNIT) window */
+	{0x00000000e8000000,	0x1000000,	RUNIT_TID},
+	/* PEX2_X1 window */
+	{0x00000000e6000000,	0x2000000,	PEX2_TID},
+	{0x00000008b0000000,	0x10000000,	PEX2_TID},
+	/* PEX1_X1 window */
+	{0x00000000e4000000,	0x2000000,	PEX1_TID},
+	{0x00000008a0000000,	0x10000000,	PEX1_TID},
+	/* PEX0_X2 window */
+	{0x00000000e2000000,	0x2000000,	PEX0_TID},
+	{0x0000000890000000,	0x10000000,	PEX0_TID},
+};
+
+struct addr_map_win iob_memory_map_cp2[] = {
+
+	/* PEX2_X1 window */
+	{0x00000000ed000000,	0x2000000,	PEX2_TID},
+	{0x00000008e0000000,	0x10000000,	PEX2_TID},
+	/* PEX1_X1 window */
+	{0x00000000eb000000,	0x2000000,	PEX1_TID},
+	{0x00000008d0000000,	0x10000000,	PEX1_TID},
+	/* PEX0_X1 window */
+	{0x00000000e9000000,	0x2000000,	PEX0_TID},
+	{0x00000008c0000000,	0x10000000,	PEX0_TID},
+};
+
+int marvell_get_iob_memory_map(struct addr_map_win **win, uint32_t *size,
+			       uintptr_t base)
+{
+	switch (base) {
+	case MVEBU_CP_REGS_BASE(0):
+		*win = iob_memory_map_cp0;
+		*size = ARRAY_SIZE(iob_memory_map_cp0);
+		return 0;
+	case MVEBU_CP_REGS_BASE(1):
+		*win = iob_memory_map_cp1;
+		*size = ARRAY_SIZE(iob_memory_map_cp1);
+		return 0;
+	case MVEBU_CP_REGS_BASE(2):
+		*win = iob_memory_map_cp2;
+		*size = ARRAY_SIZE(iob_memory_map_cp2);
+		return 0;
+	default:
+		*size = 0;
+		*win = 0;
+		return 1;
+	}
+}
+#endif
+
+/*****************************************************************************
+ * CCU Configuration
+ *****************************************************************************
+ */
+struct addr_map_win ccu_memory_map[] = {	/* IO window */
+#ifdef IMAGE_BLE
+	{0x00000000f2000000,	0x6000000,	IO_0_TID}, /* IO window */
+#else
+#if LLC_SRAM
+	{PLAT_MARVELL_LLC_SRAM_BASE, PLAT_MARVELL_LLC_SRAM_SIZE, DRAM_0_TID},
+#endif
+	{0x00000000f2000000,	0xe000000,	IO_0_TID}, /* IO window */
+	{0x00000000c0000000,	0x30000000,	IO_0_TID}, /* IO window */
+	{0x0000000800000000,	0x100000000,    IO_0_TID}, /* IO window */
+	{0x0000002000000000,	0x70e000000,	IO_0_TID}, /* IO for CV-OS */
+#endif
+};
+
+uint32_t marvell_get_ccu_gcr_target(int ap)
+{
+	return DRAM_0_TID;
+}
+
+int marvell_get_ccu_memory_map(int ap_index, struct addr_map_win **win,
+			       uint32_t *size)
+{
+	*win = ccu_memory_map;
+	*size = ARRAY_SIZE(ccu_memory_map);
+
+	return 0;
+}
+
+#ifdef IMAGE_BLE
+/*****************************************************************************
+ * SKIP IMAGE Configuration
+ *****************************************************************************
+ */
+void *plat_get_skip_image_data(void)
+{
+	/* No recovery button on CN-9130 board? */
+	return NULL;
+}
+#endif
diff --git a/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/platform.mk b/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/platform.mk
new file mode 100644
index 0000000..ee55455
--- /dev/null
+++ b/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/platform.mk
@@ -0,0 +1,33 @@
+#
+# Copyright (C) 2018 Marvell International Ltd.
+# Copyright (C) 2021 Semihalf.
+#
+# SPDX-License-Identifier:	BSD-3-Clause
+# https://spdx.org/licenses
+#
+
+PCI_EP_SUPPORT		:=	0
+
+CP_NUM			:=	1
+$(eval $(call add_define,CP_NUM))
+
+DOIMAGE_SEC     	:=	tools/doimage/secure/sec_img_7K.cfg
+
+MARVELL_MOCHI_DRV	:=	drivers/marvell/mochi/ap807_setup.c
+
+BOARD_DIR		:=	$(shell dirname $(lastword $(MAKEFILE_LIST)))
+
+#
+# CN913X CEx7 Evaluation Board shares the DRAM connectivity
+# and SerDes settings with the CN913X DB - reuse relevant
+# board-specific files.
+#
+T9130_DIR		:=	$(BOARD_DIR)/../t9130
+PLAT_INCLUDES		:=	-I$(T9130_DIR)				\
+				-I$(T9130_DIR)/board
+BLE_PORTING_SOURCES	:=	$(T9130_DIR)/board/dram_port.c		\
+				$(BOARD_DIR)/board/marvell_plat_config.c
+
+include plat/marvell/armada/a8k/common/a8k_common.mk
+
+include plat/marvell/armada/common/marvell_common.mk
diff --git a/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c b/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c
new file mode 100644
index 0000000..69c395e
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mtk_sip_svc.h>
+#include <plat_dfd.h>
+
+static bool dfd_enabled;
+static uint64_t dfd_base_addr;
+static uint64_t dfd_chain_length;
+static uint64_t dfd_cache_dump;
+
+static void dfd_setup(uint64_t base_addr, uint64_t chain_length,
+		      uint64_t cache_dump)
+{
+	/* bit[0]: rg_rw_dfd_internal_dump_en -> 1 */
+	/* bit[2]: rg_rw_dfd_clock_stop_en -> 1 */
+	sync_writel(DFD_INTERNAL_CTL, 0x5);
+
+	/* bit[13]: xreset_b_update_disable */
+	mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 13);
+
+	/*
+	 * bit[10:3]: DFD trigger selection mask
+	 * bit[3]: rg_rw_dfd_trigger_sel[0] = 1(enable wdt trigger)
+	 * bit[4]: rg_rw_dfd_trigger_sel[1] = 1(enable HW trigger)
+	 * bit[5]: rg_rw_dfd_trigger_sel[2] = 1(enable SW trigger)
+	 * bit[6]: rg_rw_dfd_trigger_sel[3] = 1(enable SW non-security trigger)
+	 * bit[7]: rg_rw_dfd_trigger_sel[4] = 1(enable timer trigger)
+	 */
+	mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 3);
+
+	/* bit[20:19]: rg_dfd_armpll_div_mux_sel switch to PLL2 for DFD */
+	mmio_setbits_32(DFD_INTERNAL_CTL, 0x3 << 19);
+
+	/*
+	 * bit[0]: rg_rw_dfd_auto_power_on = 1
+	 * bit[2:1]: rg_rw_dfd_auto_power_on_dely = 1(10us)
+	 * bit[4:2]: rg_rw_dfd_power_on_wait_time = 1(20us)
+	 */
+	mmio_write_32(DFD_INTERNAL_PWR_ON, 0xB);
+
+	/* longest scan chain length */
+	mmio_write_32(DFD_CHAIN_LENGTH0, chain_length);
+
+	/* bit[1:0]: rg_rw_dfd_shift_clock_ratio */
+	mmio_write_32(DFD_INTERNAL_SHIFT_CLK_RATIO, 0x0);
+
+	/* rg_dfd_test_so_over_64 */
+	mmio_write_32(DFD_INTERNAL_TEST_SO_OVER_64, 0x1);
+
+	/* DFD3.0 */
+	mmio_write_32(DFD_TEST_SI_0, DFD_TEST_SI_0_CACHE_DIS_VAL);
+	mmio_write_32(DFD_TEST_SI_1, DFD_TEST_SI_1_VAL);
+	mmio_write_32(DFD_TEST_SI_2, DFD_TEST_SI_2_VAL);
+	mmio_write_32(DFD_TEST_SI_3, DFD_TEST_SI_3_VAL);
+
+	/* for iLDO feature */
+	sync_writel(DFD_POWER_CTL, 0xF9);
+
+	/* set base address */
+	mmio_write_32(DFD_O_SET_BASEADDR_REG, base_addr >> 24);
+
+	/*
+	 * disable sleep protect of DFD
+	 * 10001220[8]: protect_en_reg[8]
+	 * 10001a3c[2]: infra_mcu_pwr_ctl_mask[2]
+	 */
+	mmio_clrbits_32(DFD_O_PROTECT_EN_REG, 1 << 8);
+	mmio_clrbits_32(DFD_O_INTRF_MCU_PWR_CTL_MASK, 1 << 2);
+
+	/* clean DFD trigger status */
+	sync_writel(DFD_CLEAN_STATUS, 0x1);
+	sync_writel(DFD_CLEAN_STATUS, 0x0);
+
+	/* DFD-3.0 */
+	sync_writel(DFD_V30_CTL, 0x1);
+
+	/* setup global variables for suspend and resume */
+	dfd_enabled = true;
+	dfd_base_addr = base_addr;
+	dfd_chain_length = chain_length;
+	dfd_cache_dump = cache_dump;
+
+	if ((cache_dump & DFD_CACHE_DUMP_ENABLE) != 0UL) {
+		/* DFD3.5 */
+		mmio_write_32(DFD_TEST_SI_0, DFD_TEST_SI_0_CACHE_EN_VAL);
+		sync_writel(DFD_V35_ENALBE, 0x1);
+		sync_writel(DFD_V35_TAP_NUMBER, 0xB);
+		sync_writel(DFD_V35_TAP_EN, DFD_V35_TAP_EN_VAL);
+		sync_writel(DFD_V35_SEQ0_0, DFD_V35_SEQ0_0_VAL);
+
+		if (cache_dump & DFD_PARITY_ERR_TRIGGER) {
+			sync_writel(DFD_HW_TRIGGER_MASK, 0xC);
+			mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 4);
+		}
+	}
+	dsbsy();
+}
+
+void dfd_resume(void)
+{
+	if (dfd_enabled == true) {
+		dfd_setup(dfd_base_addr, dfd_chain_length, dfd_cache_dump);
+	}
+}
+
+uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1,
+			    uint64_t arg2, uint64_t arg3)
+{
+	uint64_t ret = 0L;
+
+	switch (arg0) {
+	case PLAT_MTK_DFD_SETUP_MAGIC:
+		dfd_setup(arg1, arg2, arg3);
+		break;
+	case PLAT_MTK_DFD_READ_MAGIC:
+		/* only allow to access DFD register base + 0x200 */
+		if (arg1 <= 0x200) {
+			ret = mmio_read_32(MISC1_CFG_BASE + arg1);
+		}
+		break;
+	case PLAT_MTK_DFD_WRITE_MAGIC:
+		/* only allow to access DFD register base + 0x200 */
+		if (arg1 <= 0x200) {
+			sync_writel(MISC1_CFG_BASE + arg1, arg2);
+		}
+		break;
+	default:
+		ret = MTK_SIP_E_INVALID_PARAM;
+		break;
+	}
+
+	return ret;
+}
diff --git a/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h b/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h
new file mode 100644
index 0000000..7f0f4b5
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DFD_H
+#define PLAT_DFD_H
+
+#include <arch_helpers.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#define sync_writel(addr, val)	do { mmio_write_32((addr), (val)); \
+				dsbsy(); \
+				} while (0)
+
+#define PLAT_MTK_DFD_SETUP_MAGIC		(0x99716150)
+#define PLAT_MTK_DFD_READ_MAGIC			(0x99716151)
+#define PLAT_MTK_DFD_WRITE_MAGIC		(0x99716152)
+
+#define MCU_BIU_BASE				(MCUCFG_BASE)
+#define MISC1_CFG_BASE				(MCU_BIU_BASE + 0xE040)
+#define DFD_INTERNAL_CTL			(MISC1_CFG_BASE + 0x00)
+#define DFD_INTERNAL_PWR_ON			(MISC1_CFG_BASE + 0x08)
+#define DFD_CHAIN_LENGTH0			(MISC1_CFG_BASE + 0x0C)
+#define DFD_INTERNAL_SHIFT_CLK_RATIO		(MISC1_CFG_BASE + 0x10)
+#define DFD_CHAIN_LENGTH1			(MISC1_CFG_BASE + 0x1C)
+#define DFD_CHAIN_LENGTH2			(MISC1_CFG_BASE + 0x20)
+#define DFD_CHAIN_LENGTH3			(MISC1_CFG_BASE + 0x24)
+#define DFD_INTERNAL_TEST_SO_0			(MISC1_CFG_BASE + 0x28)
+#define DFD_INTERNAL_NUM_OF_TEST_SO_GROUP	(MISC1_CFG_BASE + 0x30)
+#define DFD_INTERNAL_TEST_SO_OVER_64		(MISC1_CFG_BASE + 0x34)
+#define DFD_V30_CTL				(MISC1_CFG_BASE + 0x48)
+#define DFD_V30_BASE_ADDR			(MISC1_CFG_BASE + 0x4C)
+#define DFD_POWER_CTL				(MISC1_CFG_BASE + 0x50)
+#define DFD_TEST_SI_0				(MISC1_CFG_BASE + 0x58)
+#define DFD_TEST_SI_1				(MISC1_CFG_BASE + 0x5C)
+#define DFD_CLEAN_STATUS			(MISC1_CFG_BASE + 0x60)
+#define DFD_TEST_SI_2				(MISC1_CFG_BASE + 0x1D8)
+#define DFD_TEST_SI_3				(MISC1_CFG_BASE + 0x1DC)
+#define DFD_HW_TRIGGER_MASK			(MISC1_CFG_BASE + 0xBC)
+
+#define DFD_V35_ENALBE				(MCU_BIU_BASE + 0xE0A8)
+#define DFD_V35_TAP_NUMBER			(MCU_BIU_BASE + 0xE0AC)
+#define DFD_V35_TAP_EN				(MCU_BIU_BASE + 0xE0B0)
+#define DFD_V35_CTL				(MCU_BIU_BASE + 0xE0B4)
+#define DFD_V35_SEQ0_0				(MCU_BIU_BASE + 0xE0C0)
+#define DFD_V35_SEQ0_1				(MCU_BIU_BASE + 0xE0C4)
+
+#define DFD_O_PROTECT_EN_REG			(0x10001220)
+#define DFD_O_INTRF_MCU_PWR_CTL_MASK		(0x10001A3C)
+#define DFD_O_SET_BASEADDR_REG			(0x10043034)
+
+#define DFD_CACHE_DUMP_ENABLE			1U
+#define DFD_PARITY_ERR_TRIGGER			2U
+
+#define DFD_TEST_SI_0_CACHE_DIS_VAL		(0x1E000202)
+#define DFD_TEST_SI_0_CACHE_EN_VAL		(0x1E000002)
+#define DFD_TEST_SI_1_VAL			(0x20408100)
+#define DFD_TEST_SI_2_VAL			(0x10101000)
+#define DFD_TEST_SI_3_VAL			(0x00000010)
+#define	DFD_V35_TAP_EN_VAL			(0x43FF)
+#define	DFD_V35_SEQ0_0_VAL			(0x63668820)
+
+void dfd_resume(void);
+uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1,
+			    uint64_t arg2, uint64_t arg3);
+
+#endif /* PLAT_DFD_H */
diff --git a/plat/mediatek/mt8192/include/plat_sip_calls.h b/plat/mediatek/mt8192/include/plat_sip_calls.h
index 0e42322..f68a4ea 100644
--- a/plat/mediatek/mt8192/include/plat_sip_calls.h
+++ b/plat/mediatek/mt8192/include/plat_sip_calls.h
@@ -10,6 +10,10 @@
 /*******************************************************************************
  * Plat SiP function constants
  ******************************************************************************/
-#define MTK_PLAT_SIP_NUM_CALLS    0
+#define MTK_PLAT_SIP_NUM_CALLS    2
+
+/* DFD */
+#define MTK_SIP_KERNEL_DFD_AARCH32		0x82000205
+#define MTK_SIP_KERNEL_DFD_AARCH64		0xC2000205
 
 #endif /* PLAT_SIP_CALLS_H */
diff --git a/plat/mediatek/mt8192/plat_pm.c b/plat/mediatek/mt8192/plat_pm.c
index 6dfb6c9..018e418 100644
--- a/plat/mediatek/mt8192/plat_pm.c
+++ b/plat/mediatek/mt8192/plat_pm.c
@@ -17,6 +17,7 @@
 #include <mtk_ptp3_common.h>
 #include <mtspmc.h>
 #include <plat/common/platform.h>
+#include <plat_dfd.h>
 #include <plat_mtk_lpm.h>
 #include <plat_params.h>
 #include <plat_pm.h>
@@ -168,6 +169,8 @@
 	mt_gic_distif_restore();
 	gic_sgi_restore_all();
 
+	dfd_resume();
+
 	plat_mt_pm_invoke_no_check(pwr_mcusys_on_finished, cpu, state);
 }
 
diff --git a/plat/mediatek/mt8192/plat_sip_calls.c b/plat/mediatek/mt8192/plat_sip_calls.c
index f567f02..353faf8 100644
--- a/plat/mediatek/mt8192/plat_sip_calls.c
+++ b/plat/mediatek/mt8192/plat_sip_calls.c
@@ -9,6 +9,7 @@
 #include <mtk_apusys.h>
 #include <mtk_sip_svc.h>
 #include <mt_spm_vcorefs.h>
+#include <plat_dfd.h>
 #include "plat_sip_calls.h"
 
 uintptr_t mediatek_plat_sip_handler(uint32_t smc_fid,
@@ -34,6 +35,11 @@
 		ret = apusys_kernel_ctrl(x1, x2, x3, x4, &rnd_val0);
 		SMC_RET2(handle, ret, rnd_val0);
 		break;
+	case MTK_SIP_KERNEL_DFD_AARCH32:
+	case MTK_SIP_KERNEL_DFD_AARCH64:
+		ret = dfd_smc_dispatcher(x1, x2, x3, x4);
+		SMC_RET1(handle, ret);
+		break;
 	default:
 		ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
 		break;
diff --git a/plat/mediatek/mt8192/platform.mk b/plat/mediatek/mt8192/platform.mk
index 7761a55..cbdaadd 100644
--- a/plat/mediatek/mt8192/platform.mk
+++ b/plat/mediatek/mt8192/platform.mk
@@ -19,6 +19,7 @@
                  -I${MTK_PLAT_SOC}/drivers/apusys/                \
                  -I${MTK_PLAT_SOC}/drivers/dcm                    \
                  -I${MTK_PLAT_SOC}/drivers/devapc                 \
+                 -I${MTK_PLAT_SOC}/drivers/dfd                    \
                  -I${MTK_PLAT_SOC}/drivers/emi_mpu/               \
                  -I${MTK_PLAT_SOC}/drivers/gpio/                  \
                  -I${MTK_PLAT_SOC}/drivers/mcdi/                  \
@@ -68,6 +69,7 @@
                    ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c                 \
                    ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c           \
                    ${MTK_PLAT_SOC}/drivers/devapc/devapc.c               \
+                   ${MTK_PLAT_SOC}/drivers/dfd/plat_dfd.c                \
                    ${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c             \
                    ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c                 \
                    ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm.c              \
diff --git a/plat/nvidia/tegra/common/tegra_platform.c b/plat/nvidia/tegra/common/tegra_platform.c
index 3894b74..f3aa3ea 100644
--- a/plat/nvidia/tegra/common/tegra_platform.c
+++ b/plat/nvidia/tegra/common/tegra_platform.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -82,13 +82,6 @@
 	return (tegra_get_chipid() >> PRE_SI_PLATFORM_SHIFT) & PRE_SI_PLATFORM_MASK;
 }
 
-bool tegra_chipid_is_t132(void)
-{
-	uint32_t chip_id = ((tegra_get_chipid() >> CHIP_ID_SHIFT) & CHIP_ID_MASK);
-
-	return (chip_id == TEGRA_CHIPID_TEGRA13);
-}
-
 bool tegra_chipid_is_t186(void)
 {
 	uint32_t chip_id = (tegra_get_chipid() >> CHIP_ID_SHIFT) & CHIP_ID_MASK;
diff --git a/plat/nvidia/tegra/include/t132/tegra_def.h b/plat/nvidia/tegra/include/t132/tegra_def.h
deleted file mode 100644
index 6b87655..0000000
--- a/plat/nvidia/tegra/include/t132/tegra_def.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef TEGRA_DEF_H
-#define TEGRA_DEF_H
-
-#include <lib/utils_def.h>
-
-/*******************************************************************************
- * Platform BL31 specific defines.
- ******************************************************************************/
-#define BL31_SIZE			U(0x40000)
-
-/*******************************************************************************
- * This value is used by the PSCI implementation during the `SYSTEM_SUSPEND`
- * call as the `state-id` field in the 'power state' parameter.
- ******************************************************************************/
-#define PSTATE_ID_SOC_POWERDN	U(0xD)
-
-/*******************************************************************************
- * Platform power states (used by PSCI framework)
- *
- * - PLAT_MAX_RET_STATE should be less than lowest PSTATE_ID
- * - PLAT_MAX_OFF_STATE should be greater than the highest PSTATE_ID
- ******************************************************************************/
-#define PLAT_MAX_RET_STATE		U(1)
-#define PLAT_MAX_OFF_STATE		(PSTATE_ID_SOC_POWERDN + U(1))
-
-/*******************************************************************************
- * Chip specific page table and MMU setup constants
- ******************************************************************************/
-#define PLAT_PHY_ADDR_SPACE_SIZE	(ULL(1) << 35)
-#define PLAT_VIRT_ADDR_SPACE_SIZE	(ULL(1) << 35)
-
-/*******************************************************************************
- * GIC memory map
- ******************************************************************************/
-#define TEGRA_GICD_BASE			U(0x50041000)
-#define TEGRA_GICC_BASE			U(0x50042000)
-
-/*******************************************************************************
- * Tegra micro-seconds timer constants
- ******************************************************************************/
-#define TEGRA_TMRUS_BASE		U(0x60005010)
-#define TEGRA_TMRUS_SIZE		U(0x1000)
-
-/*******************************************************************************
- * Tegra Clock and Reset Controller constants
- ******************************************************************************/
-#define TEGRA_CAR_RESET_BASE		U(0x60006000)
-#define TEGRA_GPU_RESET_REG_OFFSET	U(0x28C)
-#define TEGRA_GPU_RESET_GPU_SET_OFFSET	U(0x290)
-#define  GPU_RESET_BIT			(U(1) << 24)
-#define  GPU_SET_BIT			(U(1) << 24)
-
-/*******************************************************************************
- * Tegra Flow Controller constants
- ******************************************************************************/
-#define TEGRA_FLOWCTRL_BASE		U(0x60007000)
-
-/*******************************************************************************
- * Tegra Secure Boot Controller constants
- ******************************************************************************/
-#define TEGRA_SB_BASE			U(0x6000C200)
-
-/*******************************************************************************
- * Tegra Exception Vectors constants
- ******************************************************************************/
-#define TEGRA_EVP_BASE			U(0x6000F000)
-
-/*******************************************************************************
- * Tegra Miscellaneous register constants
- ******************************************************************************/
-#define TEGRA_MISC_BASE			U(0x70000000)
-#define  HARDWARE_REVISION_OFFSET	U(0x804)
-
-/*******************************************************************************
- * Tegra UART controller base addresses
- ******************************************************************************/
-#define TEGRA_UARTA_BASE		U(0x70006000)
-#define TEGRA_UARTB_BASE		U(0x70006040)
-#define TEGRA_UARTC_BASE		U(0x70006200)
-#define TEGRA_UARTD_BASE		U(0x70006300)
-#define TEGRA_UARTE_BASE		U(0x70006400)
-
-/*******************************************************************************
- * Tegra Power Mgmt Controller constants
- ******************************************************************************/
-#define TEGRA_PMC_BASE			U(0x7000E400)
-
-/*******************************************************************************
- * Tegra Memory Controller constants
- ******************************************************************************/
-#define TEGRA_MC_BASE			U(0x70019000)
-
-/* Memory Controller Interrupt Status */
-#define MC_INTSTATUS			0x00U
-
-/* TZDRAM carveout configuration registers */
-#define MC_SECURITY_CFG0_0		U(0x70)
-#define MC_SECURITY_CFG1_0		U(0x74)
-#define MC_SECURITY_CFG3_0		U(0x9BC)
-
-/* Video Memory carveout configuration registers */
-#define MC_VIDEO_PROTECT_BASE_HI	U(0x978)
-#define MC_VIDEO_PROTECT_BASE_LO	U(0x648)
-#define MC_VIDEO_PROTECT_SIZE_MB	U(0x64c)
-#define MC_VIDEO_PROTECT_REG_CTRL	U(0x650)
-#define MC_VIDEO_PROTECT_WRITE_ACCESS_ENABLED	U(3)
-
-/*******************************************************************************
- * Tegra TZRAM constants
- ******************************************************************************/
-#define TEGRA_TZRAM_BASE		U(0x7C010000)
-#define TEGRA_TZRAM_SIZE		U(0x10000)
-
-/*******************************************************************************
- * Tegra DRAM memory base address
- ******************************************************************************/
-#define TEGRA_DRAM_BASE			ULL(0x80000000)
-#define TEGRA_DRAM_END			ULL(0x27FFFFFFF)
-
-#endif /* TEGRA_DEF_H */
diff --git a/plat/nvidia/tegra/include/tegra_platform.h b/plat/nvidia/tegra/include/tegra_platform.h
index b8297fd..ab51dfe 100644
--- a/plat/nvidia/tegra/include/tegra_platform.h
+++ b/plat/nvidia/tegra/include/tegra_platform.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -49,7 +49,6 @@
 /*
  * Tegra chip ID identifiers
  */
-bool tegra_chipid_is_t132(void);
 bool tegra_chipid_is_t186(void);
 bool tegra_chipid_is_t210(void);
 bool tegra_chipid_is_t210_b01(void);
diff --git a/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c
deleted file mode 100644
index 0e2edf0..0000000
--- a/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-
-#include <platform_def.h>
-
-#include <arch.h>
-#include <arch_helpers.h>
-#include <common/debug.h>
-#include <drivers/delay_timer.h>
-#include <denver.h>
-#include <lib/mmio.h>
-#include <lib/psci/psci.h>
-
-#include <flowctrl.h>
-#include <pmc.h>
-#include <tegra_def.h>
-#include <tegra_private.h>
-
-/*
- * Register used to clear CPU reset signals. Each CPU has two reset
- * signals: CPU reset (3:0) and Core reset (19:16)
- */
-#define CPU_CMPLX_RESET_CLR		0x344
-#define CPU_CORE_RESET_MASK		0x10001
-
-/* Clock and Reset controller registers for system clock's settings */
-#define SCLK_RATE			0x30
-#define SCLK_BURST_POLICY		0x28
-#define SCLK_BURST_POLICY_DEFAULT	0x10000000
-
-static int cpu_powergate_mask[PLATFORM_MAX_CPUS_PER_CLUSTER];
-
-plat_local_state_t tegra_soc_get_target_pwr_state(uint32_t lvl,
-					     const plat_local_state_t *states,
-					     uint32_t ncpu)
-{
-	plat_local_state_t target = PLAT_MAX_OFF_STATE, temp;
-	uint32_t num_cpu = ncpu;
-	const plat_local_state_t *local_state = states;
-
-	(void)lvl;
-
-	assert(ncpu != 0U);
-
-	do {
-		temp = *local_state;
-		if ((temp < target)) {
-			target = temp;
-		}
-		--num_cpu;
-		local_state++;
-	} while (num_cpu != 0U);
-
-	return target;
-}
-
-int32_t tegra_soc_validate_power_state(unsigned int power_state,
-					psci_power_state_t *req_state)
-{
-	int state_id = psci_get_pstate_id(power_state);
-	int cpu = read_mpidr() & MPIDR_CPU_MASK;
-
-	/*
-	 * Sanity check the requested state id, power level and CPU number.
-	 * Currently T132 only supports SYSTEM_SUSPEND on last standing CPU
-	 * i.e. CPU 0
-	 */
-	if ((state_id != PSTATE_ID_SOC_POWERDN) || (cpu != 0)) {
-		ERROR("unsupported state id @ power level\n");
-		return PSCI_E_INVALID_PARAMS;
-	}
-
-	/* Set lower power states to PLAT_MAX_OFF_STATE */
-	for (uint32_t i = MPIDR_AFFLVL0; i < PLAT_MAX_PWR_LVL; i++)
-		req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
-
-	/* Set the SYSTEM_SUSPEND state-id */
-	req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] =
-		PSTATE_ID_SOC_POWERDN;
-
-	return PSCI_E_SUCCESS;
-}
-
-int tegra_soc_pwr_domain_on(u_register_t mpidr)
-{
-	int cpu = mpidr & MPIDR_CPU_MASK;
-	uint32_t mask = CPU_CORE_RESET_MASK << cpu;
-
-	if (cpu_powergate_mask[cpu] == 0) {
-
-		/* Deassert CPU reset signals */
-		mmio_write_32(TEGRA_CAR_RESET_BASE + CPU_CMPLX_RESET_CLR, mask);
-
-		/* Power on CPU using PMC */
-		tegra_pmc_cpu_on(cpu);
-
-		/* Fill in the CPU powergate mask */
-		cpu_powergate_mask[cpu] = 1;
-
-	} else {
-		/* Power on CPU using Flow Controller */
-		tegra_fc_cpu_on(cpu);
-	}
-
-	return PSCI_E_SUCCESS;
-}
-
-int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
-{
-	/*
-	 * Lock scratch registers which hold the CPU vectors
-	 */
-	tegra_pmc_lock_cpu_vectors();
-
-	return PSCI_E_SUCCESS;
-}
-
-int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
-{
-	uint64_t val;
-
-	tegra_fc_cpu_off(read_mpidr() & MPIDR_CPU_MASK);
-
-	/* Disable DCO operations */
-	denver_disable_dco();
-
-	/* Power down the CPU */
-	val = read_actlr_el1() & ~ACTLR_EL1_PMSTATE_MASK;
-	write_actlr_el1(val | DENVER_CPU_STATE_POWER_DOWN);
-
-	return PSCI_E_SUCCESS;
-}
-
-int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state)
-{
-	(void)cpu_state;
-	return PSCI_E_SUCCESS;
-}
-
-int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
-{
-	uint64_t val;
-
-#if ENABLE_ASSERTIONS
-	int cpu = read_mpidr() & MPIDR_CPU_MASK;
-
-	/* SYSTEM_SUSPEND only on CPU0 */
-	assert(cpu == 0);
-#endif
-
-	/* Allow restarting CPU #1 using PMC on suspend exit */
-	cpu_powergate_mask[1] = 0;
-
-	/* Program FC to enter suspend state */
-	tegra_fc_cpu_powerdn(read_mpidr());
-
-	/* Disable DCO operations */
-	denver_disable_dco();
-
-	/* Program the suspend state ID */
-	val = read_actlr_el1() & ~ACTLR_EL1_PMSTATE_MASK;
-	write_actlr_el1(val | target_state->pwr_domain_state[PLAT_MAX_PWR_LVL]);
-
-	return PSCI_E_SUCCESS;
-}
-
-int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state)
-{
-	return PSCI_E_NOT_SUPPORTED;
-}
-
-int tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)
-{
-	return PSCI_E_SUCCESS;
-}
-
-int tegra_soc_prepare_system_reset(void)
-{
-	/*
-	 * Set System Clock (SCLK) to POR default so that the clock source
-	 * for the PMC APB clock would not be changed due to system reset.
-	 */
-	mmio_write_32((uintptr_t)TEGRA_CAR_RESET_BASE + SCLK_BURST_POLICY,
-		       SCLK_BURST_POLICY_DEFAULT);
-	mmio_write_32((uintptr_t)TEGRA_CAR_RESET_BASE + SCLK_RATE, 0);
-
-	/* Wait 1 ms to make sure clock source/device logic is stabilized. */
-	mdelay(1);
-
-	/*
-	 * Program the PMC in order to restart the system.
-	 */
-	tegra_pmc_system_reset();
-
-	return PSCI_E_SUCCESS;
-}
-
-__dead2 void tegra_soc_prepare_system_off(void)
-{
-	ERROR("Tegra System Off: operation not handled.\n");
-	panic();
-}
diff --git a/plat/nvidia/tegra/soc/t132/plat_secondary.c b/plat/nvidia/tegra/soc/t132/plat_secondary.c
deleted file mode 100644
index f46ad3b..0000000
--- a/plat/nvidia/tegra/soc/t132/plat_secondary.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-
-#include <arch_helpers.h>
-#include <common/debug.h>
-#include <denver.h>
-#include <lib/mmio.h>
-#include <lib/psci/psci.h>
-#include <plat/common/platform.h>
-
-#include <pmc.h>
-#include <tegra_def.h>
-
-#define SB_CSR				0x0
-#define  SB_CSR_NS_RST_VEC_WR_DIS	(1 << 1)
-
-/* AARCH64 CPU reset vector */
-#define SB_AA64_RESET_LOW		0x30	/* width = 31:0 */
-#define SB_AA64_RESET_HI		0x34	/* width = 11:0 */
-
-/* AARCH32 CPU reset vector */
-#define EVP_CPU_RESET_VECTOR		0x100
-
-extern void tegra_secure_entrypoint(void);
-
-/*
- * For T132, CPUs reset to AARCH32, so the reset vector is first
- * armv8_trampoline which does a warm reset to AARCH64 and starts
- * execution at the address in SB_AA64_RESET_LOW/SB_AA64_RESET_HI.
- */
-__aligned(8) const uint32_t armv8_trampoline[] = {
-	0xE3A00003,		/* mov	r0, #3 */
-	0xEE0C0F50,		/* mcr	p15, 0, r0, c12, c0, 2 */
-	0xEAFFFFFE,		/* b	. */
-};
-
-/*******************************************************************************
- * Setup secondary CPU vectors
- ******************************************************************************/
-void plat_secondary_setup(void)
-{
-	uint32_t val;
-	uint64_t reset_addr = (uint64_t)tegra_secure_entrypoint;
-
-	/*
-	 * For T132, CPUs reset to AARCH32, so the reset vector is first
-	 * armv8_trampoline, which does a warm reset to AARCH64 and starts
-	 * execution at the address in SCRATCH34/SCRATCH35.
-	 */
-	INFO("Setting up T132 CPU boot\n");
-
-	/* initial AARCH32 reset address */
-	tegra_pmc_write_32(PMC_SECURE_SCRATCH22,
-		(unsigned long)&armv8_trampoline);
-
-	/* set AARCH32 exception vector (read to flush) */
-	mmio_write_32(TEGRA_EVP_BASE + EVP_CPU_RESET_VECTOR,
-		(unsigned long)&armv8_trampoline);
-	val = mmio_read_32(TEGRA_EVP_BASE + EVP_CPU_RESET_VECTOR);
-
-	/* setup secondary CPU vector */
-	mmio_write_32(TEGRA_SB_BASE + SB_AA64_RESET_LOW,
-			(reset_addr & 0xFFFFFFFF) | 1);
-	val = reset_addr >> 32;
-	mmio_write_32(TEGRA_SB_BASE + SB_AA64_RESET_HI, val & 0x7FF);
-
-	/* configure PMC */
-	tegra_pmc_cpu_setup(reset_addr);
-	tegra_pmc_lock_cpu_vectors();
-}
diff --git a/plat/nvidia/tegra/soc/t132/plat_setup.c b/plat/nvidia/tegra/soc/t132/plat_setup.c
deleted file mode 100644
index 49e8b5d..0000000
--- a/plat/nvidia/tegra/soc/t132/plat_setup.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <arch_helpers.h>
-#include <assert.h>
-#include <common/bl_common.h>
-#include <drivers/console.h>
-#include <lib/xlat_tables/xlat_tables_v2.h>
-#include <memctrl.h>
-#include <plat/common/platform.h>
-#include <tegra_def.h>
-#include <tegra_platform.h>
-#include <tegra_private.h>
-
-/* sets of MMIO ranges setup */
-#define MMIO_RANGE_0_ADDR	0x50000000
-#define MMIO_RANGE_1_ADDR	0x60000000
-#define MMIO_RANGE_2_ADDR	0x70000000
-#define MMIO_RANGE_SIZE		0x200000
-
-/*
- * Table of regions to map using the MMU.
- */
-static const mmap_region_t tegra_mmap[] = {
-	MAP_REGION_FLAT(MMIO_RANGE_0_ADDR, MMIO_RANGE_SIZE,
-			MT_DEVICE | MT_RW | MT_SECURE),
-	MAP_REGION_FLAT(MMIO_RANGE_1_ADDR, MMIO_RANGE_SIZE,
-			MT_DEVICE | MT_RW | MT_SECURE),
-	MAP_REGION_FLAT(MMIO_RANGE_2_ADDR, MMIO_RANGE_SIZE,
-			MT_DEVICE | MT_RW | MT_SECURE),
-	{0}
-};
-
-/*******************************************************************************
- * Set up the pagetables as per the platform memory map & initialize the MMU
- ******************************************************************************/
-const mmap_region_t *plat_get_mmio_map(void)
-{
-	/* MMIO space */
-	return tegra_mmap;
-}
-
-/*******************************************************************************
- * The Tegra power domain tree has a single system level power domain i.e. a
- * single root node. The first entry in the power domain descriptor specifies
- * the number of power domains at the highest power level.
- *******************************************************************************
- */
-const unsigned char tegra_power_domain_tree_desc[] = {
-	/* No of root nodes */
-	1,
-	/* No of clusters */
-	PLATFORM_CLUSTER_COUNT,
-	/* No of CPU cores */
-	PLATFORM_CORE_COUNT,
-};
-
-/*******************************************************************************
- * This function returns the Tegra default topology tree information.
- ******************************************************************************/
-const unsigned char *plat_get_power_domain_tree_desc(void)
-{
-	return tegra_power_domain_tree_desc;
-}
-
-unsigned int plat_get_syscnt_freq2(void)
-{
-	return 12000000;
-}
-
-/*******************************************************************************
- * Maximum supported UART controllers
- ******************************************************************************/
-#define TEGRA132_MAX_UART_PORTS		5
-
-/*******************************************************************************
- * This variable holds the UART port base addresses
- ******************************************************************************/
-static uint32_t tegra132_uart_addresses[TEGRA132_MAX_UART_PORTS + 1] = {
-	0,	/* undefined - treated as an error case */
-	TEGRA_UARTA_BASE,
-	TEGRA_UARTB_BASE,
-	TEGRA_UARTC_BASE,
-	TEGRA_UARTD_BASE,
-	TEGRA_UARTE_BASE,
-};
-
-/*******************************************************************************
- * Enable console corresponding to the console ID
- ******************************************************************************/
-void plat_enable_console(int32_t id)
-{
-	static console_t uart_console;
-	uint32_t console_clock;
-
-	if ((id > 0) && (id < TEGRA132_MAX_UART_PORTS)) {
-		/*
-		 * Reference clock used by the FPGAs is a lot slower.
-		 */
-		if (tegra_platform_is_fpga()) {
-			console_clock = TEGRA_BOOT_UART_CLK_13_MHZ;
-		} else {
-			console_clock = TEGRA_BOOT_UART_CLK_408_MHZ;
-		}
-
-		(void)console_16550_register(tegra132_uart_addresses[id],
-					     console_clock,
-					     TEGRA_CONSOLE_BAUDRATE,
-					     &uart_console);
-		console_set_scope(&uart_console, CONSOLE_FLAG_BOOT |
-			CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
-	}
-}
-
-/*******************************************************************************
- * Initialize the GIC and SGIs
- ******************************************************************************/
-void plat_gic_setup(void)
-{
-	tegra_gic_setup(NULL, 0);
-	tegra_gic_init();
-}
-
-/*******************************************************************************
- * Return pointer to the BL31 params from previous bootloader
- ******************************************************************************/
-struct tegra_bl31_params *plat_get_bl31_params(void)
-{
-	return NULL;
-}
-
-/*******************************************************************************
- * Return pointer to the BL31 platform params from previous bootloader
- ******************************************************************************/
-plat_params_from_bl2_t *plat_get_bl31_plat_params(void)
-{
-	return NULL;
-}
-
-/*******************************************************************************
- * Handler for early platform setup
- ******************************************************************************/
-void plat_early_platform_setup(void)
-{
-	plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
-
-	/* Verify chip id is t132 */
-	assert(tegra_chipid_is_t132());
-
-	/*
-	 * Do initial security configuration to allow DRAM/device access.
-	 */
-	tegra_memctrl_tzdram_setup(plat_params->tzdram_base,
-			(uint32_t)plat_params->tzdram_size);
-}
-
-/*******************************************************************************
- * Handler for late platform setup
- ******************************************************************************/
-void plat_late_platform_setup(void)
-{
-	; /* do nothing */
-}
-
-/*******************************************************************************
- * Handler to indicate support for System Suspend
- ******************************************************************************/
-bool plat_supports_system_suspend(void)
-{
-	return true;
-}
-
-/*******************************************************************************
- * Platform specific runtime setup.
- ******************************************************************************/
-void plat_runtime_setup(void)
-{
-	/*
-	 * During cold boot, it is observed that the arbitration
-	 * bit is set in the Memory controller leading to false
-	 * error interrupts in the non-secure world. To avoid
-	 * this, clean the interrupt status register before
-	 * booting into the non-secure world
-	 */
-	tegra_memctrl_clear_pending_interrupts();
-
-	/*
-	 * During boot, USB3 and flash media (SDMMC/SATA) devices need
-	 * access to IRAM. Because these clients connect to the MC and
-	 * do not have a direct path to the IRAM, the MC implements AHB
-	 * redirection during boot to allow path to IRAM. In this mode
-	 * accesses to a programmed memory address aperture are directed
-	 * to the AHB bus, allowing access to the IRAM. This mode must be
-	 * disabled before we jump to the non-secure world.
-	 */
-	tegra_memctrl_disable_ahb_redirection();
-}
diff --git a/plat/nvidia/tegra/soc/t132/plat_sip_calls.c b/plat/nvidia/tegra/soc/t132/plat_sip_calls.c
deleted file mode 100644
index 90c6bb2..0000000
--- a/plat/nvidia/tegra/soc/t132/plat_sip_calls.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-#include <errno.h>
-
-#include <arch.h>
-#include <arch_helpers.h>
-#include <common/bl_common.h>
-#include <common/debug.h>
-#include <lib/el3_runtime/context_mgmt.h>
-
-#include <tegra_private.h>
-
-#define NS_SWITCH_AARCH32	1
-#define SCR_RW_BITPOS		__builtin_ctz(SCR_RW_BIT)
-
-/*******************************************************************************
- * Tegra132 SiP SMCs
- ******************************************************************************/
-#define TEGRA_SIP_AARCH_SWITCH			0x82000004
-
-/*******************************************************************************
- * SPSR settings for AARCH32/AARCH64 modes
- ******************************************************************************/
-#define SPSR32		SPSR_MODE32(MODE32_svc, SPSR_T_ARM, SPSR_E_LITTLE, \
-			DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT)
-#define SPSR64		SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS)
-
-/*******************************************************************************
- * This function is responsible for handling all T132 SiP calls
- ******************************************************************************/
-int plat_sip_handler(uint32_t smc_fid,
-		     uint64_t x1,
-		     uint64_t x2,
-		     uint64_t x3,
-		     uint64_t x4,
-		     const void *cookie,
-		     void *handle,
-		     uint64_t flags)
-{
-	switch (smc_fid) {
-
-	case TEGRA_SIP_AARCH_SWITCH:
-
-		/* clean up the high bits */
-		x1 = (uint32_t)x1;
-		x2 = (uint32_t)x2;
-
-		if (!x1 || x2 > NS_SWITCH_AARCH32) {
-			ERROR("%s: invalid parameters\n", __func__);
-			return -EINVAL;
-		}
-
-		/* x1 = ns entry point */
-		cm_set_elr_spsr_el3(NON_SECURE, x1,
-			(x2 == NS_SWITCH_AARCH32) ? SPSR32 : SPSR64);
-
-		/* switch NS world mode */
-		cm_write_scr_el3_bit(NON_SECURE, SCR_RW_BITPOS, !x2);
-
-		INFO("CPU switched to AARCH%s mode\n",
-			(x2 == NS_SWITCH_AARCH32) ? "32" : "64");
-		return 0;
-
-	default:
-		ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
-		break;
-	}
-
-	return -ENOTSUP;
-}
diff --git a/plat/nvidia/tegra/soc/t132/platform_t132.mk b/plat/nvidia/tegra/soc/t132/platform_t132.mk
deleted file mode 100644
index 9534c07..0000000
--- a/plat/nvidia/tegra/soc/t132/platform_t132.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
-# Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-TZDRAM_BASE			:= 0xF5C00000
-$(eval $(call add_define,TZDRAM_BASE))
-
-PLATFORM_CLUSTER_COUNT		:= 1
-$(eval $(call add_define,PLATFORM_CLUSTER_COUNT))
-
-PLATFORM_MAX_CPUS_PER_CLUSTER	:= 2
-$(eval $(call add_define,PLATFORM_MAX_CPUS_PER_CLUSTER))
-
-MAX_XLAT_TABLES			:= 3
-$(eval $(call add_define,MAX_XLAT_TABLES))
-
-MAX_MMAP_REGIONS		:= 8
-$(eval $(call add_define,MAX_MMAP_REGIONS))
-
-# platform files
-PLAT_INCLUDES		+=	-Iplat/nvidia/tegra/include/t132
-
-BL31_SOURCES		+=	${TEGRA_GICv2_SOURCES}			\
-				drivers/ti/uart/aarch64/16550_console.S	\
-				lib/cpus/aarch64/denver.S		\
-				${TEGRA_DRIVERS}/flowctrl/flowctrl.c	\
-				${TEGRA_DRIVERS}/memctrl/memctrl_v1.c	\
-				${TEGRA_DRIVERS}/pmc/pmc.c		\
-				${SOC_DIR}/plat_psci_handlers.c		\
-				${SOC_DIR}/plat_sip_calls.c		\
-				${SOC_DIR}/plat_setup.c			\
-				${SOC_DIR}/plat_secondary.c
diff --git a/plat/nvidia/tegra/soc/t194/plat_ras.c b/plat/nvidia/tegra/soc/t194/plat_ras.c
index 0c4c6fa..a322403 100644
--- a/plat/nvidia/tegra/soc/t194/plat_ras.c
+++ b/plat/nvidia/tegra/soc/t194/plat_ras.c
@@ -493,9 +493,6 @@
 #if RAS_EXTENSION
 	tegra194_ea_handler(ea_reason, syndrome, cookie, handle, flags);
 #else
-	ERROR("Unhandled External Abort received on 0x%llx at EL3!\n",
-			read_mpidr_el1());
-	ERROR(" exception reason=%u syndrome=0x%lx\n", ea_reason, syndrome);
-	panic();
+	plat_default_ea_handler(ea_reason, syndrome, cookie, handle, flags);
 #endif
 }
diff --git a/plat/nxp/common/setup/include/plat_common.h b/plat/nxp/common/setup/include/plat_common.h
index 18d36ca..97a9cb7 100644
--- a/plat/nxp/common/setup/include/plat_common.h
+++ b/plat/nxp/common/setup/include/plat_common.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2020 NXP
+ * Copyright 2018-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -10,7 +10,9 @@
 
 #include <stdbool.h>
 
+#include <dcfg.h>
 #include <lib/el3_runtime/cpu_data.h>
+
 #include <platform_def.h>
 
 #ifdef IMAGE_BL31
@@ -129,18 +131,19 @@
 #endif
 );
 
-
 /* Structure to define SoC personality */
 struct soc_type {
 	char name[10];
-	uint32_t personality;
-	uint32_t num_clusters;
-	uint32_t cores_per_cluster;
+	uint32_t version;
+	uint8_t num_clusters;
+	uint8_t cores_per_cluster;
 };
+void get_cluster_info(const struct soc_type *soc_list, uint8_t ps_count,
+		uint8_t *num_clusters, uint8_t *cores_per_cluster);
 
 #define SOC_ENTRY(n, v, ncl, nc) {	\
 		.name = #n,		\
-		.personality = SVR_##v,	\
+		.version = SVR_##v,	\
 		.num_clusters = (ncl),	\
 		.cores_per_cluster = (nc)}
 
diff --git a/plat/nxp/common/setup/ls_common.c b/plat/nxp/common/setup/ls_common.c
index a6946e1..e7ae060 100644
--- a/plat/nxp/common/setup/ls_common.c
+++ b/plat/nxp/common/setup/ls_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2020 NXP
+ * Copyright 2018-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -238,3 +238,27 @@
 {
 	return plat_ls_mmap;
 }
+
+/*
+ * This function get the number of clusters and cores count per cluster
+ * in the SoC.
+ */
+void get_cluster_info(const struct soc_type *soc_list, uint8_t ps_count,
+		uint8_t *num_clusters, uint8_t *cores_per_cluster)
+{
+	const soc_info_t *soc_info = get_soc_info();
+	*num_clusters = NUMBER_OF_CLUSTERS;
+	*cores_per_cluster = CORES_PER_CLUSTER;
+	unsigned int i;
+
+	for (i = 0U; i < ps_count; i++) {
+		if (soc_list[i].version == soc_info->svr_reg.bf_ver.version) {
+			*num_clusters = soc_list[i].num_clusters;
+			*cores_per_cluster = soc_list[i].cores_per_cluster;
+			break;
+		}
+	}
+
+	VERBOSE("NUM of cluster = 0x%x, Cores per cluster = 0x%x\n",
+			*num_clusters, *cores_per_cluster);
+}
diff --git a/plat/nxp/common/soc_errata/errata.c b/plat/nxp/common/soc_errata/errata.c
new file mode 100644
index 0000000..fb1818a
--- /dev/null
+++ b/plat/nxp/common/soc_errata/errata.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <common/debug.h>
+
+#include "errata_list.h"
+
+void soc_errata(void)
+{
+#ifdef ERRATA_SOC_A050426
+	INFO("SoC workaround for Errata A050426 was applied\n");
+	erratum_a050426();
+#endif
+	/*
+	 * The following DDR Erratas workaround are implemented in DDR driver,
+	 * but print information here.
+	 */
+#if ERRATA_DDR_A011396
+	INFO("SoC workaround for DDR Errata A011396 was applied\n");
+#endif
+#if ERRATA_DDR_A050450
+	INFO("SoC workaround for DDR Errata A050450 was applied\n");
+#endif
+}
diff --git a/plat/nxp/common/soc_errata/errata.h b/plat/nxp/common/soc_errata/errata.h
new file mode 100644
index 0000000..b543b4b
--- /dev/null
+++ b/plat/nxp/common/soc_errata/errata.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2020-2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef ERRATA_H
+#define ERRATA_H
+
+void soc_errata(void);
+
+#endif /* ERRATA_H */
diff --git a/plat/nxp/common/soc_errata/errata.mk b/plat/nxp/common/soc_errata/errata.mk
new file mode 100644
index 0000000..2942615
--- /dev/null
+++ b/plat/nxp/common/soc_errata/errata.mk
@@ -0,0 +1,23 @@
+#
+# Copyright 2021 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# Platform Errata Build flags.
+# These should be enabled by the platform if the erratum workaround needs to be
+# applied.
+
+ERRATA := \
+  ERRATA_SOC_A050426
+
+define enable_errata
+  $(1) ?= 0
+  ifeq ($$($(1)),1)
+    $$(eval $$(call add_define,$(1)))
+    BL2_SOURCES += $(PLAT_COMMON_PATH)/soc_errata/errata_a$(shell echo $(1)|awk -F '_A' '{print $$NF}').c
+  endif
+endef
+
+$(foreach e,$(ERRATA),$(eval $(call enable_errata,$(strip $(e)))))
+
+BL2_SOURCES += $(PLAT_COMMON_PATH)/soc_errata/errata.c
diff --git a/plat/nxp/soc-lx2160a/erratas_soc.c b/plat/nxp/common/soc_errata/errata_a050426.c
similarity index 98%
rename from plat/nxp/soc-lx2160a/erratas_soc.c
rename to plat/nxp/common/soc_errata/errata_a050426.c
index 8f3aa9f..13a0000 100644
--- a/plat/nxp/soc-lx2160a/erratas_soc.c
+++ b/plat/nxp/common/soc_errata/errata_a050426.c
@@ -7,7 +7,6 @@
 
 #include <mmio.h>
 
-#ifdef ERRATA_SOC_A050426
 void erratum_a050426(void)
 {
 	uint32_t i, val3, val4;
@@ -411,8 +410,6 @@
 	}
 
 	/* Disable BIST */
-
 	mmio_write_32(0x700117E60, val3);
 	mmio_write_32(0x700117E90, val4);
 }
-#endif
diff --git a/plat/nxp/common/soc_errata/errata_list.h b/plat/nxp/common/soc_errata/errata_list.h
new file mode 100644
index 0000000..74d2315
--- /dev/null
+++ b/plat/nxp/common/soc_errata/errata_list.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef ERRATA_LIST_H
+#define ERRATA_LIST_H
+
+#ifdef ERRATA_SOC_A050426
+void erratum_a050426(void);
+#endif
+
+#endif /* ERRATA_LIST_H */
diff --git a/plat/nxp/soc-lx2160a/erratas_soc.mk b/plat/nxp/soc-lx2160a/erratas_soc.mk
deleted file mode 100644
index 07bed03..0000000
--- a/plat/nxp/soc-lx2160a/erratas_soc.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Copyright 2020 NXP
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-# Platform Errata Build flags.
-# These should be enabled by the platform if the erratum workaround needs to be
-# applied.
-
-# Flag to apply erratum 50426 workaround during reset.
-ERRATA_SOC_A050426	?= 0
-
-# Process ERRATA_SOC_A050426 flag
-ifeq (${ERRATA_SOC_A050426}, 1)
-INCL_SOC_ERRATA_SOURCES	:= yes
-$(eval $(call add_define,ERRATA_SOC_A050426))
-endif
-
-ifeq (${INCL_SOC_ERRATA_SOURCES},yes)
-BL2_SOURCES	+= 	${PLAT_SOC_PATH}/erratas_soc.c
-endif
diff --git a/plat/nxp/soc-lx2160a/include/errata.h b/plat/nxp/soc-lx2160a/include/errata.h
deleted file mode 100644
index 937824a..0000000
--- a/plat/nxp/soc-lx2160a/include/errata.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright 2020 NXP
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef ERRATA_H
-#define ERRATA_H
-
-#ifdef ERRATA_SOC_A050426
-void erratum_a050426(void);
-#endif
-
-#endif /* ERRATA_H */
diff --git a/plat/nxp/soc-lx2160a/include/soc.h b/plat/nxp/soc-lx2160a/include/soc.h
index bd23620..7cc4a03 100644
--- a/plat/nxp/soc-lx2160a/include/soc.h
+++ b/plat/nxp/soc-lx2160a/include/soc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2020 NXP
+ * Copyright 2018-2021 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -52,11 +52,10 @@
 #define FLEXSPI_NOR		0xf
 /* End: Macros used by soc.c: get_boot_dev */
 
-/* bits */
-/* SVR Definition */
-#define SVR_LX2160A		0x04
-#define SVR_LX2120A		0x14
-#define SVR_LX2080A		0x05
+/* SVR Definition (not include major and minor rev) */
+#define SVR_LX2160A		0x873601
+#define SVR_LX2120A		0x873621
+#define SVR_LX2080A		0x873603
 
 /* Number of cores in platform */
 /* Used by common code for array initialization */
diff --git a/plat/nxp/soc-lx2160a/soc.c b/plat/nxp/soc-lx2160a/soc.c
index e0a2fe9..2209fda 100644
--- a/plat/nxp/soc-lx2160a/soc.c
+++ b/plat/nxp/soc-lx2160a/soc.c
@@ -82,28 +82,6 @@
 	.master_to_rn_id_map = master_to_rn_id_map
 };
 
-/*******************************************************************************
- * This function returns the number of clusters in the SoC
- ******************************************************************************/
-static unsigned int get_num_cluster(void)
-{
-	const soc_info_t *soc_info = get_soc_info();
-	uint32_t num_clusters = NUMBER_OF_CLUSTERS;
-	unsigned int i;
-
-	for (i = 0U; i < ARRAY_SIZE(soc_list); i++) {
-		if (soc_list[i].personality == soc_info->personality) {
-			num_clusters = soc_list[i].num_clusters;
-			break;
-		}
-	}
-
-	VERBOSE("NUM of cluster = 0x%x\n", num_clusters);
-
-	return num_clusters;
-}
-
-
 /******************************************************************************
  * Function returns the base counter frequency
  * after reading the first entry at CNTFID0 (0x20 offset).
@@ -142,8 +120,10 @@
 static void soc_interconnect_config(void)
 {
 	unsigned long long val = 0x0U;
+	uint8_t num_clusters, cores_per_cluster;
 
-	uint32_t num_clusters = get_num_cluster();
+	get_cluster_info(soc_list, ARRAY_SIZE(soc_list),
+			&num_clusters, &cores_per_cluster);
 
 	if (num_clusters == 6U) {
 		ccn_init(&plat_six_cluster_ccn_desc);
@@ -271,9 +251,7 @@
 				MT_DEVICE | MT_RW | MT_NS);
 	}
 
-#ifdef ERRATA_SOC_A050426
-	erratum_a050426();
-#endif
+	soc_errata();
 
 #if (TRUSTED_BOARD_BOOT) || defined(POLICY_FUSE_PROVISION)
 	sfp_init(NXP_SFP_ADDR);
@@ -466,7 +444,12 @@
  ******************************************************************************/
 void soc_init(void)
 {
-	 /* low-level init of the soc */
+	uint8_t num_clusters, cores_per_cluster;
+
+	get_cluster_info(soc_list, ARRAY_SIZE(soc_list),
+			&num_clusters, &cores_per_cluster);
+
+	/* low-level init of the soc */
 	soc_init_start();
 	soc_init_percpu();
 	_init_global_data();
@@ -478,8 +461,6 @@
 		panic();
 	}
 
-	uint32_t num_clusters = get_num_cluster();
-
 	if (num_clusters == 6U) {
 		ccn_init(&plat_six_cluster_ccn_desc);
 	} else {
diff --git a/plat/nxp/soc-lx2160a/soc.mk b/plat/nxp/soc-lx2160a/soc.mk
index 8ab1430..75a3af2 100644
--- a/plat/nxp/soc-lx2160a/soc.mk
+++ b/plat/nxp/soc-lx2160a/soc.mk
@@ -99,7 +99,8 @@
 PLAT_INCLUDES		+=	-I${PLAT_COMMON_PATH}/include/default\
 				-I${BOARD_PATH}\
 				-I${PLAT_COMMON_PATH}/include/default/ch_${CHASSIS}\
-				-I${PLAT_SOC_PATH}/include
+				-I${PLAT_SOC_PATH}/include\
+				-I${PLAT_COMMON_PATH}/soc_errata
 
 ifeq (${SECURE_BOOT},yes)
 include ${PLAT_COMMON_PATH}/tbbr/tbbr.mk
@@ -138,7 +139,7 @@
 include ${PLAT_DRIVERS_PATH}/drivers.mk
 
  # Adding SoC specific files
-include ${PLAT_SOC_PATH}/erratas_soc.mk
+include ${PLAT_COMMON_PATH}/soc_errata/errata.mk
 
 PLAT_INCLUDES		+=	${NV_STORAGE_INCLUDES}\
 				${WARM_RST_INCLUDES}
diff --git a/plat/qemu/qemu/include/platform_def.h b/plat/qemu/qemu/include/platform_def.h
index 0891d80..c02eff9 100644
--- a/plat/qemu/qemu/include/platform_def.h
+++ b/plat/qemu/qemu/include/platform_def.h
@@ -80,8 +80,8 @@
 #define SEC_ROM_BASE			0x00000000
 #define SEC_ROM_SIZE			0x00020000
 
-#define NS_DRAM0_BASE			0x40000000
-#define NS_DRAM0_SIZE			0xc0000000
+#define NS_DRAM0_BASE			ULL(0x40000000)
+#define NS_DRAM0_SIZE			ULL(0xc0000000)
 
 #define SEC_SRAM_BASE			0x0e000000
 #define SEC_SRAM_SIZE			0x00060000
diff --git a/plat/qti/common/src/qti_syscall.c b/plat/qti/common/src/qti_syscall.c
index a7601b6..d8e5be9 100644
--- a/plat/qti/common/src/qti_syscall.c
+++ b/plat/qti/common/src/qti_syscall.c
@@ -21,6 +21,7 @@
 #include <qti_plat.h>
 #include <qti_secure_io_cfg.h>
 #include <qtiseclib_interface.h>
+
 /*
  * SIP service - SMC function IDs for SiP Service queries
  *
@@ -29,7 +30,7 @@
 #define	QTI_SIP_SVC_UID_ID				U(0x0200ff01)
 /*							0x8200ff02 is reserved*/
 #define	QTI_SIP_SVC_VERSION_ID				U(0x0200ff03)
-
+#define QTI_SIP_SVC_AVAILABLE_ID			U(0x02000601)
 /*
  * Syscall's to allow Non Secure world accessing peripheral/IO memory
  * those are secure/proteced BUT not required to be secure.
@@ -83,6 +84,22 @@
 	return false;
 }
 
+static bool qti_check_syscall_availability(u_register_t smc_fid)
+{
+	switch (smc_fid) {
+	case QTI_SIP_SVC_CALL_COUNT_ID:
+	case QTI_SIP_SVC_UID_ID:
+	case QTI_SIP_SVC_VERSION_ID:
+	case QTI_SIP_SVC_AVAILABLE_ID:
+	case QTI_SIP_SVC_SECURE_IO_READ_ID:
+	case QTI_SIP_SVC_SECURE_IO_WRITE_ID:
+	case QTI_SIP_SVC_MEM_ASSIGN_ID:
+		return true;
+	default:
+		return false;
+	}
+}
+
 bool qti_mem_assign_validate_param(memprot_info_t *mem_info,
 				   u_register_t u_num_mappings,
 				   uint32_t *source_vm_list,
@@ -315,6 +332,18 @@
 				 QTI_SIP_SVC_VERSION_MINOR);
 			break;
 		}
+	case QTI_SIP_SVC_AVAILABLE_ID:
+		{
+			if (x1 != 1) {
+				SMC_RET1(handle, QTI_SIP_INVALID_PARAM);
+			}
+			if (qti_check_syscall_availability(x2) == true) {
+				SMC_RET2(handle, QTI_SIP_SUCCESS, 1);
+			} else {
+				SMC_RET2(handle, QTI_SIP_SUCCESS, 0);
+			}
+			break;
+		}
 	case QTI_SIP_SVC_SECURE_IO_READ_ID:
 		{
 			if ((x1 == QTI_SIP_SVC_SECURE_IO_READ_PARAM_ID) &&
diff --git a/plat/renesas/common/include/platform_def.h b/plat/renesas/common/include/platform_def.h
index 7378714..72c7688 100644
--- a/plat/renesas/common/include/platform_def.h
+++ b/plat/renesas/common/include/platform_def.h
@@ -151,7 +151,8 @@
  * BL33
  ******************************************************************************/
 #define BL33_BASE		DRAM1_NS_BASE
-
+#define BL33_COMP_SIZE		U(0x200000)
+#define BL33_COMP_BASE		(BL33_BASE - BL33_COMP_SIZE)
 
 /*******************************************************************************
  * Platform specific page table and MMU setup constants
diff --git a/plat/renesas/common/include/rcar_def.h b/plat/renesas/common/include/rcar_def.h
index 6c5b295..93a65f1 100644
--- a/plat/renesas/common/include/rcar_def.h
+++ b/plat/renesas/common/include/rcar_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -120,7 +120,6 @@
 /* Timer control */
 #define RCAR_CNTC_BASE		U(0xE6080000)
 /* Reset */
-#define RCAR_CPGWPR		U(0xE6150900)	/* CPG write protect    */
 #define RCAR_MODEMR		U(0xE6160060)	/* Mode pin             */
 #define RCAR_CA57RESCNT		U(0xE6160040)	/* Reset control A57    */
 #define RCAR_CA53RESCNT		U(0xE6160044)	/* Reset control A53    */
diff --git a/plat/renesas/common/include/rcar_version.h b/plat/renesas/common/include/rcar_version.h
index 67cbd71..173111d 100644
--- a/plat/renesas/common/include/rcar_version.h
+++ b/plat/renesas/common/include/rcar_version.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,7 +9,7 @@
 
 #include <arch_helpers.h>
 
-#define VERSION_OF_RENESAS		"2.0.6"
+#define VERSION_OF_RENESAS		"3.0.0"
 #define VERSION_OF_RENESAS_MAXLEN	128
 
 extern const uint8_t version_of_renesas[VERSION_OF_RENESAS_MAXLEN];
diff --git a/plat/renesas/common/include/registers/cpg_registers.h b/plat/renesas/common/include/registers/cpg_registers.h
index 0d698d9..5d2bb9e 100644
--- a/plat/renesas/common/include/registers/cpg_registers.h
+++ b/plat/renesas/common/include/registers/cpg_registers.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,6 +16,8 @@
 #define CPG_SRCR2	(CPG_BASE + 0x00B0U)
 /* CPG module stop status 2 */
 #define CPG_MSTPSR2	(CPG_BASE + 0x0040U)
+/* CPG module stop status 2 */
+#define CPG_MSTPSR3	(CPG_BASE + 0x0048U)
 /* CPG write protect */
 #define CPG_CPGWPR	(CPG_BASE + 0x0900U)
 /* CPG write protect control */
@@ -24,6 +26,10 @@
 #define CPG_SMSTPCR9    (CPG_BASE + 0x0994U)
 /* CPG module stop status 9 */
 #define CPG_MSTPSR9     (CPG_BASE + 0x09A4U)
+/* SDHI2 clock frequency control register */
+#define	CPG_SD2CKCR	(CPG_BASE + 0x0268U)
+/* SDHI3 clock frequency control register */
+#define CPG_SD3CKCR	(CPG_BASE + 0x026CU)
 
 /* CPG (SECURITY) registers */
 
diff --git a/plat/renesas/common/rcar_common.c b/plat/renesas/common/rcar_common.c
index dec7229..df4c30c 100644
--- a/plat/renesas/common/rcar_common.c
+++ b/plat/renesas/common/rcar_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Renesas Electronics Corporation. All rights reserved.
+ * Copyright (c) 2019-2021, Renesas Electronics Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,9 +12,8 @@
 #include <plat/common/platform.h>
 
 #include <lib/mmio.h>
+#include <cpg_registers.h>
 
-#define CPG_BASE		0xE6150000
-#define CPG_MSTPSR3		0x0048
 #define MSTP318			(1 << 18)
 #define MSTP319			(1 << 19)
 #define PMSR			0x5c
@@ -31,7 +30,7 @@
 	int ret = 0;
 
 	/* Test if PCIECx is enabled */
-	cpg = mmio_read_32(CPG_BASE + CPG_MSTPSR3);
+	cpg = mmio_read_32(CPG_MSTPSR3);
 	if (cpg & (MSTP318 << !controller))
 		return ret;
 
@@ -61,11 +60,7 @@
 	if (fixed)
 		return;
 
-	ERROR("Unhandled External Abort received on 0x%lx at EL3!\n",
-			read_mpidr_el1());
-	ERROR(" exception reason=%u syndrome=0x%llx\n", ea_reason, syndrome);
-
-	panic();
+	plat_default_ea_handler(ea_reason, syndrome, cookie, handle, flags);
 }
 
 #include <drivers/renesas/rcar/console/console.h>
diff --git a/plat/renesas/rcar/bl2_plat_setup.c b/plat/renesas/rcar/bl2_plat_setup.c
index add2a4f..41b2d11 100644
--- a/plat/renesas/rcar/bl2_plat_setup.c
+++ b/plat/renesas/rcar/bl2_plat_setup.c
@@ -15,12 +15,16 @@
 #include <common/bl_common.h>
 #include <common/debug.h>
 #include <common/desc_image_load.h>
+#include <common/image_decompress.h>
 #include <drivers/console.h>
 #include <drivers/io/io_driver.h>
 #include <drivers/io/io_storage.h>
 #include <lib/mmio.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 #include <plat/common/platform.h>
+#if RCAR_GEN3_BL33_GZIP == 1
+#include <tf_gunzip.h>
+#endif
 
 #include "avs_driver.h"
 #include "boot_init_dram.h"
@@ -357,16 +361,29 @@
 #endif
 }
 
+#if RCAR_GEN3_BL33_GZIP == 1
+void bl2_plat_preload_setup(void)
+{
+	image_decompress_init(BL33_COMP_BASE, BL33_COMP_SIZE, gunzip);
+}
+#endif
+
 int bl2_plat_handle_pre_image_load(unsigned int image_id)
 {
 	u_register_t *boot_kind = (void *) BOOT_KIND_BASE;
 	bl_mem_params_node_t *bl_mem_params;
 
+	bl_mem_params = get_bl_mem_params_node(image_id);
+
+#if RCAR_GEN3_BL33_GZIP == 1
+	if (image_id == BL33_IMAGE_ID) {
+		image_decompress_prepare(&bl_mem_params->image_info);
+	}
+#endif
+
 	if (image_id != BL31_IMAGE_ID)
 		return 0;
 
-	bl_mem_params = get_bl_mem_params_node(image_id);
-
 	if (is_ddr_backup_mode() == RCAR_COLD_BOOT)
 		goto cold_boot;
 
@@ -433,6 +450,19 @@
 			sizeof(entry_point_info_t));
 		break;
 	case BL33_IMAGE_ID:
+#if RCAR_GEN3_BL33_GZIP == 1
+		if ((mmio_read_32(BL33_COMP_BASE) & 0xffff) == 0x8b1f) {
+			/* decompress gzip-compressed image */
+			ret = image_decompress(&bl_mem_params->image_info);
+			if (ret != 0) {
+				return ret;
+			}
+		} else {
+			/* plain image, copy it in place */
+			memcpy((void *)BL33_BASE, (void *)BL33_COMP_BASE,
+				bl_mem_params->image_info.image_size);
+		}
+#endif
 		memcpy(&params->bl33_ep_info, &bl_mem_params->ep_info,
 			sizeof(entry_point_info_t));
 		break;
@@ -535,12 +565,75 @@
 	}
 }
 
-static void bl2_advertise_dram_entries(uint64_t dram_config[8])
+static void bl2_add_rpc_node(void)
+{
+#if (RCAR_RPC_HYPERFLASH_LOCKED == 0)
+	int ret, node;
+
+	node = ret = fdt_add_subnode(fdt, 0, "soc");
+	if (ret < 0) {
+		goto err;
+	}
+
+	node = ret = fdt_add_subnode(fdt, node, "rpc@ee200000");
+	if (ret < 0) {
+		goto err;
+	}
+
+	ret = fdt_setprop_string(fdt, node, "status", "okay");
+	if (ret < 0) {
+		goto err;
+	}
+
+	return;
+err:
+	NOTICE("BL2: Cannot add RPC node to FDT (ret=%i)\n", ret);
+	panic();
+#endif
+}
+
+static void bl2_add_dram_entry(uint64_t start, uint64_t size)
 {
 	char nodename[32] = { 0 };
-	uint64_t start, size;
 	uint64_t fdtsize;
-	int ret, node, chan;
+	int ret, node;
+
+	fdtsize = cpu_to_fdt64(size);
+
+	snprintf(nodename, sizeof(nodename), "memory@");
+	unsigned_num_print(start, 16, nodename + strlen(nodename));
+	node = ret = fdt_add_subnode(fdt, 0, nodename);
+	if (ret < 0) {
+		goto err;
+	}
+
+	ret = fdt_setprop_string(fdt, node, "device_type", "memory");
+	if (ret < 0) {
+		goto err;
+	}
+
+	ret = fdt_setprop_u64(fdt, node, "reg", start);
+	if (ret < 0) {
+		goto err;
+	}
+
+	ret = fdt_appendprop(fdt, node, "reg", &fdtsize,
+			     sizeof(fdtsize));
+	if (ret < 0) {
+		goto err;
+	}
+
+	return;
+err:
+	NOTICE("BL2: Cannot add memory node [%llx - %llx] to FDT (ret=%i)\n",
+		start, start + size - 1, ret);
+	panic();
+}
+
+static void bl2_advertise_dram_entries(uint64_t dram_config[8])
+{
+	uint64_t start, size, size32;
+	int chan;
 
 	for (chan = 0; chan < 4; chan++) {
 		start = dram_config[2 * chan];
@@ -568,39 +661,43 @@
 
 		/*
 		 * Channel 0 is mapped in 32bit space and the first
-		 * 128 MiB are reserved
+		 * 128 MiB are reserved and the maximum size is 2GiB.
 		 */
 		if (chan == 0) {
-			start = 0x48000000;
-			size -= 0x8000000;
-		}
-
-		fdtsize = cpu_to_fdt64(size);
+			/* Limit the 32bit entry to 2 GiB - 128 MiB */
+			size32 = size - 0x8000000U;
+			if (size32 >= 0x78000000U) {
+				size32 = 0x78000000U;
+			}
 
-		snprintf(nodename, sizeof(nodename), "memory@");
-		unsigned_num_print(start, 16, nodename + strlen(nodename));
-		node = ret = fdt_add_subnode(fdt, 0, nodename);
-		if (ret < 0)
-			goto err;
+			/* Emit 32bit entry, up to 2 GiB - 128 MiB long. */
+			bl2_add_dram_entry(0x48000000, size32);
 
-		ret = fdt_setprop_string(fdt, node, "device_type", "memory");
-		if (ret < 0)
-			goto err;
+			/*
+			 * If channel 0 is less than 2 GiB long, the
+			 * entire memory fits into the 32bit space entry,
+			 * so move on to the next channel.
+			 */
+			if (size <= 0x80000000U) {
+				continue;
+			}
 
-		ret = fdt_setprop_u64(fdt, node, "reg", start);
-		if (ret < 0)
-			goto err;
+			/*
+			 * If channel 0 is more than 2 GiB long, emit
+			 * another entry which covers the rest of the
+			 * memory in channel 0, in the 64bit space.
+			 *
+			 * Start of this new entry is at 2 GiB offset
+			 * from the beginning of the 64bit channel 0
+			 * address, size is 2 GiB shorter than total
+			 * size of the channel.
+			 */
+			start += 0x80000000U;
+			size -= 0x80000000U;
+		}
 
-		ret = fdt_appendprop(fdt, node, "reg", &fdtsize,
-				     sizeof(fdtsize));
-		if (ret < 0)
-			goto err;
+		bl2_add_dram_entry(start, size);
 	}
-
-	return;
-err:
-	NOTICE("BL2: Cannot add memory node to FDT (ret=%i)\n", ret);
-	panic();
 }
 
 static void bl2_advertise_dram_size(uint32_t product)
@@ -648,8 +745,13 @@
 		break;
 
 	case PRR_PRODUCT_M3N:
+#if (RCAR_DRAM_LPDDR4_MEMCONF == 2)
+		/* 4GB(4GBx1) */
+		dram_config[1] = 0x100000000ULL;
+#elif (RCAR_DRAM_LPDDR4_MEMCONF == 1)
 		/* 2GB(1GBx2) */
 		dram_config[1] = 0x80000000ULL;
+#endif
 		break;
 
 	case PRR_PRODUCT_V3M:
@@ -935,6 +1037,9 @@
 	/* Add platform compatible string */
 	bl2_populate_compatible_string(fdt);
 
+	/* Enable RPC if unlocked */
+	bl2_add_rpc_node();
+
 	/* Print DRAM layout */
 	bl2_advertise_dram_size(product);
 
diff --git a/plat/renesas/rcar/platform.mk b/plat/renesas/rcar/platform.mk
index 7a7a56c..670d499 100644
--- a/plat/renesas/rcar/platform.mk
+++ b/plat/renesas/rcar/platform.mk
@@ -245,6 +245,12 @@
 endif
 $(eval $(call add_define,RCAR_DRAM_LPDDR4_MEMCONF))
 
+# Process RCAR_DRAM_MEMRANK flag
+ifndef RCAR_DRAM_MEMRANK
+RCAR_DRAM_MEMRANK :=0
+endif
+$(eval $(call add_define,RCAR_DRAM_MEMRANK))
+
 # Process RCAR_DRAM_DDR3L_MEMCONF flag
 ifndef RCAR_DRAM_DDR3L_MEMCONF
 RCAR_DRAM_DDR3L_MEMCONF :=1
@@ -280,6 +286,11 @@
 endif
 $(eval $(call add_define,RCAR_SYSTEM_RESET_KEEPON_DDR))
 
+ifndef RCAR_GEN3_BL33_GZIP
+RCAR_GEN3_BL33_GZIP := 0
+endif
+$(eval $(call add_define,RCAR_GEN3_BL33_GZIP))
+
 # RCAR_SYSTEM_RESET_KEEPON_DDR requires power control of PMIC etc.
 # When executing SYSTEM_SUSPEND other than Salvator-X, Salvator-XS and Ebisu,
 # processing equivalent to that implemented in PMIC_ROHM_BD9571 is necessary.
@@ -315,6 +326,13 @@
 BL2_SOURCES	+=	plat/renesas/rcar/bl2_plat_setup.c	\
 			drivers/renesas/rcar/board/board.c
 
+ifeq (${RCAR_GEN3_BL33_GZIP},1)
+include lib/zlib/zlib.mk
+
+BL2_SOURCES	+=	common/image_decompress.c               \
+			$(ZLIB_SOURCES)
+endif
+
 ifeq (${RCAR_GEN3_ULCB},1)
 BL31_SOURCES		+=	drivers/renesas/rcar/cpld/ulcb_cpld.c
 endif
diff --git a/plat/rpi/rpi4/rpi4_bl31_setup.c b/plat/rpi/rpi4/rpi4_bl31_setup.c
index cfacd1f..5259859 100644
--- a/plat/rpi/rpi4/rpi4_bl31_setup.c
+++ b/plat/rpi/rpi4/rpi4_bl31_setup.c
@@ -201,6 +201,44 @@
 	enable_mmu_el3(0);
 }
 
+/*
+ * Remove the FDT /memreserve/ entry that covers the region at the very
+ * beginning of memory (if that exists). This is where the secondaries
+ * originally spin, but we pull them out there.
+ * Having overlapping /reserved-memory and /memreserve/ regions confuses
+ * the Linux kernel, so we need to get rid of this one.
+ */
+static void remove_spintable_memreserve(void *dtb)
+{
+	uint64_t addr, size;
+	int regions = fdt_num_mem_rsv(dtb);
+	int i;
+
+	for (i = 0; i < regions; i++) {
+		if (fdt_get_mem_rsv(dtb, i, &addr, &size) != 0) {
+			return;
+		}
+		if (size == 0U) {
+			return;
+		}
+		/* We only look for the region at the beginning of DRAM. */
+		if (addr != 0U) {
+			continue;
+		}
+		/*
+		 * Currently the region in the existing DTs is exactly 4K
+		 * in size. Should this value ever change, there is probably
+		 * a reason for that, so inform the user about this.
+		 */
+		if (size == 4096U) {
+			fdt_del_mem_rsv(dtb, i);
+			return;
+		}
+		WARN("Keeping unknown /memreserve/ region at 0, size: %lld\n",
+		     size);
+	}
+}
+
 static void rpi4_prepare_dtb(void)
 {
 	void *dtb = (void *)rpi4_get_dtb_address();
@@ -227,7 +265,11 @@
 		return;
 	}
 
-	/* Reserve memory used by Trusted Firmware. */
+	/*
+	 * Remove the original reserved region (used for the spintable), and
+	 * replace it with a region describing the whole of Trusted Firmware.
+	 */
+	remove_spintable_memreserve(dtb);
 	if (fdt_add_reserved_memory(dtb, "atf@0", 0, 0x80000))
 		WARN("Failed to add reserved memory nodes to DT.\n");
 
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
index e603267..7e76083 100644
--- a/plat/st/common/bl2_io_storage.c
+++ b/plat/st/common/bl2_io_storage.c
@@ -7,13 +7,12 @@
 #include <assert.h>
 #include <string.h>
 
-#include <platform_def.h>
-
 #include <arch_helpers.h>
 #include <common/debug.h>
+#include <common/desc_image_load.h>
 #include <drivers/io/io_block.h>
 #include <drivers/io/io_driver.h>
-#include <drivers/io/io_dummy.h>
+#include <drivers/io/io_fip.h>
 #include <drivers/io/io_mtd.h>
 #include <drivers/io/io_storage.h>
 #include <drivers/mmc.h>
@@ -22,34 +21,30 @@
 #include <drivers/spi_nand.h>
 #include <drivers/spi_nor.h>
 #include <drivers/st/io_mmc.h>
-#include <drivers/st/io_stm32image.h>
 #include <drivers/st/stm32_fmc2_nand.h>
 #include <drivers/st/stm32_qspi.h>
 #include <drivers/st/stm32_sdmmc2.h>
+#include <lib/fconf/fconf.h>
 #include <lib/mmio.h>
 #include <lib/utils.h>
 #include <plat/common/platform.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <platform_def.h>
+#include <stm32mp_fconf_getter.h>
 
 /* IO devices */
-#ifndef AARCH32_SP_OPTEE
-static const io_dev_connector_t *dummy_dev_con;
-static uintptr_t dummy_dev_handle;
-static uintptr_t dummy_dev_spec;
-#endif
+uintptr_t fip_dev_handle;
+uintptr_t storage_dev_handle;
 
-static uintptr_t image_dev_handle;
-static uintptr_t storage_dev_handle;
+static const io_dev_connector_t *fip_dev_con;
 
 #if STM32MP_SDMMC || STM32MP_EMMC
 static struct mmc_device_info mmc_info;
-static io_block_spec_t gpt_block_spec = {
-	.offset = 0,
-	.length = 34 * MMC_BLOCK_SIZE, /* Size of GPT table */
-};
 
 static uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE);
 
-static const io_block_dev_spec_t mmc_block_dev_spec = {
+static io_block_dev_spec_t mmc_block_dev_spec = {
 	/* It's used as temp buffer in block driver */
 	.buffer = {
 		.offset = (size_t)&block_buffer,
@@ -62,30 +57,6 @@
 	.block_size = MMC_BLOCK_SIZE,
 };
 
-#if STM32MP_EMMC_BOOT
-static io_block_spec_t emmc_boot_ssbl_block_spec = {
-	.offset = PLAT_EMMC_BOOT_SSBL_OFFSET,
-	.length = MMC_BLOCK_SIZE, /* We are interested only in first 4 bytes */
-};
-
-static const io_block_dev_spec_t mmc_block_dev_boot_part_spec = {
-	/* It's used as temp buffer in block driver */
-	.buffer = {
-		.offset = (size_t)&block_buffer,
-		.length = MMC_BLOCK_SIZE,
-	},
-	.ops = {
-		.read = mmc_boot_part_read_blocks,
-		.write = NULL,
-	},
-	.block_size = MMC_BLOCK_SIZE,
-};
-#endif
-
-static struct io_mmc_dev_spec mmc_device_spec = {
-	.use_boot_part = false,
-};
-
 static const io_dev_connector_t *mmc_dev_con;
 #endif /* STM32MP_SDMMC || STM32MP_EMMC */
 
@@ -103,6 +74,7 @@
 	.ops = {
 		.init = nand_raw_init,
 		.read = nand_read,
+		.seek = nand_seek_bb
 	},
 };
 
@@ -114,6 +86,7 @@
 	.ops = {
 		.init = spi_nand_init,
 		.read = nand_read,
+		.seek = nand_seek_bb
 	},
 };
 #endif
@@ -122,176 +95,21 @@
 static const io_dev_connector_t *spi_dev_con;
 #endif
 
-#ifdef AARCH32_SP_OPTEE
-static const struct stm32image_part_info optee_header_partition_spec = {
-	.name = OPTEE_HEADER_IMAGE_NAME,
-	.binary_type = OPTEE_HEADER_BINARY_TYPE,
-};
-
-static const struct stm32image_part_info optee_core_partition_spec = {
-	.name = OPTEE_CORE_IMAGE_NAME,
-	.binary_type = OPTEE_CORE_BINARY_TYPE,
-};
-
-static const struct stm32image_part_info optee_paged_partition_spec = {
-	.name = OPTEE_PAGED_IMAGE_NAME,
-	.binary_type = OPTEE_PAGED_BINARY_TYPE,
-};
-#else
-static const io_block_spec_t bl32_block_spec = {
-	.offset = BL32_BASE,
-	.length = STM32MP_BL32_SIZE
-};
-#endif
-
-static const struct stm32image_part_info bl33_partition_spec = {
-	.name = BL33_IMAGE_NAME,
-	.binary_type = BL33_BINARY_TYPE,
-};
-
-enum {
-	IMG_IDX_BL33,
-#ifdef AARCH32_SP_OPTEE
-	IMG_IDX_OPTEE_HEADER,
-	IMG_IDX_OPTEE_CORE,
-	IMG_IDX_OPTEE_PAGED,
-#endif
-	IMG_IDX_NUM
-};
-
-static struct stm32image_device_info stm32image_dev_info_spec __unused = {
-	.lba_size = MMC_BLOCK_SIZE,
-	.part_info[IMG_IDX_BL33] = {
-		.name = BL33_IMAGE_NAME,
-		.binary_type = BL33_BINARY_TYPE,
-	},
-#ifdef AARCH32_SP_OPTEE
-	.part_info[IMG_IDX_OPTEE_HEADER] = {
-		.name = OPTEE_HEADER_IMAGE_NAME,
-		.binary_type = OPTEE_HEADER_BINARY_TYPE,
-	},
-	.part_info[IMG_IDX_OPTEE_CORE] = {
-		.name = OPTEE_CORE_IMAGE_NAME,
-		.binary_type = OPTEE_CORE_BINARY_TYPE,
-	},
-	.part_info[IMG_IDX_OPTEE_PAGED] = {
-		.name = OPTEE_PAGED_IMAGE_NAME,
-		.binary_type = OPTEE_PAGED_BINARY_TYPE,
-	},
-#endif
-};
-
-static io_block_spec_t stm32image_block_spec = {
-	.offset = 0,
-	.length = 0,
+io_block_spec_t image_block_spec = {
+	.offset = 0U,
+	.length = 0U,
 };
 
-static const io_dev_connector_t *stm32image_dev_con __unused;
-
-#ifndef AARCH32_SP_OPTEE
-static int open_dummy(const uintptr_t spec);
-#endif
-static int open_image(const uintptr_t spec);
-static int open_storage(const uintptr_t spec);
-
-struct plat_io_policy {
-	uintptr_t *dev_handle;
-	uintptr_t image_spec;
-	int (*check)(const uintptr_t spec);
-};
-
-static const struct plat_io_policy policies[] = {
-#ifdef AARCH32_SP_OPTEE
-	[BL32_IMAGE_ID] = {
-		.dev_handle = &image_dev_handle,
-		.image_spec = (uintptr_t)&optee_header_partition_spec,
-		.check = open_image
-	},
-	[BL32_EXTRA1_IMAGE_ID] = {
-		.dev_handle = &image_dev_handle,
-		.image_spec = (uintptr_t)&optee_core_partition_spec,
-		.check = open_image
-	},
-	[BL32_EXTRA2_IMAGE_ID] = {
-		.dev_handle = &image_dev_handle,
-		.image_spec = (uintptr_t)&optee_paged_partition_spec,
-		.check = open_image
-	},
-#else
-	[BL32_IMAGE_ID] = {
-		.dev_handle = &dummy_dev_handle,
-		.image_spec = (uintptr_t)&bl32_block_spec,
-		.check = open_dummy
-	},
-#endif
-	[BL33_IMAGE_ID] = {
-		.dev_handle = &image_dev_handle,
-		.image_spec = (uintptr_t)&bl33_partition_spec,
-		.check = open_image
-	},
-#if STM32MP_SDMMC || STM32MP_EMMC
-	[GPT_IMAGE_ID] = {
-		.dev_handle = &storage_dev_handle,
-		.image_spec = (uintptr_t)&gpt_block_spec,
-		.check = open_storage
-	},
-#endif
-	[STM32_IMAGE_ID] = {
-		.dev_handle = &storage_dev_handle,
-		.image_spec = (uintptr_t)&stm32image_block_spec,
-		.check = open_storage
-	}
-};
-
-#ifndef AARCH32_SP_OPTEE
-static int open_dummy(const uintptr_t spec)
-{
-	return io_dev_init(dummy_dev_handle, 0);
-}
-#endif
-
-static int open_image(const uintptr_t spec)
+int open_fip(const uintptr_t spec)
 {
-	return io_dev_init(image_dev_handle, 0);
+	return io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
 }
 
-static int open_storage(const uintptr_t spec)
+int open_storage(const uintptr_t spec)
 {
 	return io_dev_init(storage_dev_handle, 0);
 }
 
-#if STM32MP_EMMC_BOOT
-static uint32_t get_boot_part_ssbl_header(void)
-{
-	uint32_t magic = 0;
-	int io_result;
-	size_t bytes_read;
-
-	io_result = register_io_dev_block(&mmc_dev_con);
-	if (io_result != 0) {
-		panic();
-	}
-
-	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_boot_part_spec,
-				&storage_dev_handle);
-	assert(io_result == 0);
-
-	io_result = io_open(storage_dev_handle, (uintptr_t) &emmc_boot_ssbl_block_spec,
-			    &image_dev_handle);
-	assert(io_result == 0);
-
-	io_result = io_read(image_dev_handle, (uintptr_t) &magic, sizeof(magic),
-			    &bytes_read);
-	assert(io_result == 0);
-	assert(bytes_read == sizeof(magic));
-
-	io_result = io_dev_close(storage_dev_handle);
-	assert(io_result == 0);
-
-	return magic;
-}
-#endif
-
 static void print_boot_device(boot_api_context_t *boot_context)
 {
 	switch (boot_context->boot_interface_selected) {
@@ -311,7 +129,8 @@
 		INFO("Using SPI NAND\n");
 		break;
 	default:
-		ERROR("Boot interface not found\n");
+		ERROR("Boot interface %u not found\n",
+		      boot_context->boot_interface_selected);
 		panic();
 		break;
 	}
@@ -321,29 +140,12 @@
 	}
 }
 
-static void stm32image_io_setup(void)
-{
-	int io_result __unused;
-
-	io_result = register_io_dev_stm32image(&stm32image_dev_con);
-	assert(io_result == 0);
-
-	io_result = io_dev_open(stm32image_dev_con,
-				(uintptr_t)&stm32image_dev_info_spec,
-				&image_dev_handle);
-	assert(io_result == 0);
-}
-
 #if STM32MP_SDMMC || STM32MP_EMMC
 static void boot_mmc(enum mmc_device_type mmc_dev_type,
 		     uint16_t boot_interface_instance)
 {
 	int io_result __unused;
-	uint8_t idx;
-	struct stm32image_part_info *part;
 	struct stm32_sdmmc2_params params;
-	const partition_entry_t *entry __unused;
-	uint32_t magic __unused;
 
 	zeromem(&params, sizeof(struct stm32_sdmmc2_params));
 
@@ -375,26 +177,6 @@
 		panic();
 	}
 
-	stm32image_dev_info_spec.device_size =
-		stm32_sdmmc2_mmc_get_device_size();
-
-#if STM32MP_EMMC_BOOT
-	magic = get_boot_part_ssbl_header();
-
-	if (magic == BOOT_API_IMAGE_HEADER_MAGIC_NB) {
-		VERBOSE("%s, header found, jump to emmc load\n", __func__);
-		idx = IMG_IDX_BL33;
-		part = &stm32image_dev_info_spec.part_info[idx];
-		part->part_offset = PLAT_EMMC_BOOT_SSBL_OFFSET;
-		part->bkp_offset = 0U;
-		mmc_device_spec.use_boot_part = true;
-
-		goto emmc_boot;
-	} else {
-		WARN("%s: Can't find STM32 header on a boot partition\n", __func__);
-	}
-#endif
-
 	/* Open MMC as a block device to read GPT table */
 	io_result = register_io_dev_block(&mmc_dev_con);
 	if (io_result != 0) {
@@ -404,37 +186,6 @@
 	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_spec,
 				&storage_dev_handle);
 	assert(io_result == 0);
-
-	partition_init(GPT_IMAGE_ID);
-
-	io_result = io_dev_close(storage_dev_handle);
-	assert(io_result == 0);
-
-	for (idx = 0U; idx < IMG_IDX_NUM; idx++) {
-		part = &stm32image_dev_info_spec.part_info[idx];
-		entry = get_partition_entry(part->name);
-		if (entry == NULL) {
-			ERROR("Partition %s not found\n", part->name);
-			panic();
-		}
-
-		part->part_offset = entry->start;
-		part->bkp_offset = 0U;
-	}
-
-#if STM32MP_EMMC_BOOT
-emmc_boot:
-#endif
-	/*
-	 * Re-open MMC with io_mmc, for better perfs compared to
-	 * io_block.
-	 */
-	io_result = register_io_dev_mmc(&mmc_dev_con);
-	assert(io_result == 0);
-
-	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_device_spec,
-				&storage_dev_handle);
-	assert(io_result == 0);
 }
 #endif /* STM32MP_SDMMC || STM32MP_EMMC */
 
@@ -442,8 +193,6 @@
 static void boot_spi_nor(boot_api_context_t *boot_context)
 {
 	int io_result __unused;
-	uint8_t idx;
-	struct stm32image_part_info *part;
 
 	io_result = stm32_qspi_init();
 	assert(io_result == 0);
@@ -456,30 +205,6 @@
 				(uintptr_t)&spi_nor_dev_spec,
 				&storage_dev_handle);
 	assert(io_result == 0);
-
-	stm32image_dev_info_spec.device_size = spi_nor_dev_spec.device_size;
-
-	idx = IMG_IDX_BL33;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NOR_BL33_OFFSET;
-	part->bkp_offset = 0U;
-
-#ifdef AARCH32_SP_OPTEE
-	idx = IMG_IDX_OPTEE_HEADER;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NOR_TEEH_OFFSET;
-	part->bkp_offset = 0U;
-
-	idx = IMG_IDX_OPTEE_PAGED;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NOR_TEED_OFFSET;
-	part->bkp_offset = 0U;
-
-	idx = IMG_IDX_OPTEE_CORE;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NOR_TEEX_OFFSET;
-	part->bkp_offset = 0U;
-#endif
 }
 #endif /* STM32MP_SPI_NOR */
 
@@ -487,8 +212,6 @@
 static void boot_fmc2_nand(boot_api_context_t *boot_context)
 {
 	int io_result __unused;
-	uint8_t idx;
-	struct stm32image_part_info *part;
 
 	io_result = stm32_fmc2_init();
 	assert(io_result == 0);
@@ -501,30 +224,6 @@
 	io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec,
 				&storage_dev_handle);
 	assert(io_result == 0);
-
-	stm32image_dev_info_spec.device_size = nand_dev_spec.device_size;
-
-	idx = IMG_IDX_BL33;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_BL33_OFFSET;
-	part->bkp_offset = nand_dev_spec.erase_size;
-
-#ifdef AARCH32_SP_OPTEE
-	idx = IMG_IDX_OPTEE_HEADER;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_TEEH_OFFSET;
-	part->bkp_offset = nand_dev_spec.erase_size;
-
-	idx = IMG_IDX_OPTEE_PAGED;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_TEED_OFFSET;
-	part->bkp_offset = nand_dev_spec.erase_size;
-
-	idx = IMG_IDX_OPTEE_CORE;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_TEEX_OFFSET;
-	part->bkp_offset = nand_dev_spec.erase_size;
-#endif
 }
 #endif /* STM32MP_RAW_NAND */
 
@@ -532,8 +231,6 @@
 static void boot_spi_nand(boot_api_context_t *boot_context)
 {
 	int io_result __unused;
-	uint8_t idx;
-	struct stm32image_part_info *part;
 
 	io_result = stm32_qspi_init();
 	assert(io_result == 0);
@@ -546,31 +243,6 @@
 				(uintptr_t)&spi_nand_dev_spec,
 				&storage_dev_handle);
 	assert(io_result == 0);
-
-	stm32image_dev_info_spec.device_size =
-		spi_nand_dev_spec.device_size;
-
-	idx = IMG_IDX_BL33;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_BL33_OFFSET;
-	part->bkp_offset = spi_nand_dev_spec.erase_size;
-
-#ifdef AARCH32_SP_OPTEE
-	idx = IMG_IDX_OPTEE_HEADER;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_TEEH_OFFSET;
-	part->bkp_offset = spi_nand_dev_spec.erase_size;
-
-	idx = IMG_IDX_OPTEE_PAGED;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_TEED_OFFSET;
-	part->bkp_offset = spi_nand_dev_spec.erase_size;
-
-	idx = IMG_IDX_OPTEE_CORE;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_TEEX_OFFSET;
-	part->bkp_offset = spi_nand_dev_spec.erase_size;
-#endif
 }
 #endif /* STM32MP_SPI_NAND */
 
@@ -584,53 +256,45 @@
 
 	if ((boot_context->boot_partition_used_toboot == 1U) ||
 	    (boot_context->boot_partition_used_toboot == 2U)) {
-		INFO("Boot used partition fsbl%d\n",
+		INFO("Boot used partition fsbl%u\n",
 		     boot_context->boot_partition_used_toboot);
 	}
 
-#ifndef AARCH32_SP_OPTEE
-	io_result = register_io_dev_dummy(&dummy_dev_con);
+	io_result = register_io_dev_fip(&fip_dev_con);
 	assert(io_result == 0);
 
-	io_result = io_dev_open(dummy_dev_con, dummy_dev_spec,
-				&dummy_dev_handle);
-	assert(io_result == 0);
-#endif
+	io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
+				&fip_dev_handle);
 
 	switch (boot_context->boot_interface_selected) {
 #if STM32MP_SDMMC
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
 		dmbsy();
 		boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance);
-		stm32image_io_setup();
 		break;
 #endif
 #if STM32MP_EMMC
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
 		dmbsy();
 		boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance);
-		stm32image_io_setup();
 		break;
 #endif
 #if STM32MP_SPI_NOR
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
 		dmbsy();
 		boot_spi_nor(boot_context);
-		stm32image_io_setup();
 		break;
 #endif
 #if STM32MP_RAW_NAND
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
 		dmbsy();
 		boot_fmc2_nand(boot_context);
-		stm32image_io_setup();
 		break;
 #endif
 #if STM32MP_SPI_NAND
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
 		dmbsy();
 		boot_spi_nand(boot_context);
-		stm32image_io_setup();
 		break;
 #endif
 
@@ -642,6 +306,65 @@
 	}
 }
 
+int bl2_plat_handle_pre_image_load(unsigned int image_id)
+{
+	static bool gpt_init_done __unused;
+	uint16_t boot_itf = stm32mp_get_boot_itf_selected();
+
+	switch (boot_itf) {
+#if STM32MP_SDMMC || STM32MP_EMMC
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
+		if (!gpt_init_done) {
+			const partition_entry_t *entry;
+
+			partition_init(GPT_IMAGE_ID);
+			entry = get_partition_entry(FIP_IMAGE_NAME);
+			if (entry == NULL) {
+				ERROR("Could NOT find the %s partition!\n",
+				      FIP_IMAGE_NAME);
+				return -ENOENT;
+			}
+
+			image_block_spec.offset = entry->start;
+			image_block_spec.length = entry->length;
+
+			gpt_init_done = true;
+		} else {
+			bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+
+			mmc_block_dev_spec.buffer.offset = bl_mem_params->image_info.image_base;
+			mmc_block_dev_spec.buffer.length = bl_mem_params->image_info.image_max_size;
+		}
+
+		break;
+#endif
+
+#if STM32MP_RAW_NAND || STM32MP_SPI_NAND
+#if STM32MP_RAW_NAND
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
+#endif
+#if STM32MP_SPI_NAND
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
+#endif
+		image_block_spec.offset = STM32MP_NAND_FIP_OFFSET;
+		break;
+#endif
+
+#if STM32MP_SPI_NOR
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
+		image_block_spec.offset = STM32MP_NOR_FIP_OFFSET;
+		break;
+#endif
+
+	default:
+		ERROR("FIP Not found\n");
+		panic();
+	}
+
+	return 0;
+}
+
 /*
  * Return an IO device handle and specification which can be used to access
  * an image. Use this to enforce platform load policy.
@@ -652,9 +375,7 @@
 	int rc;
 	const struct plat_io_policy *policy;
 
-	assert(image_id < ARRAY_SIZE(policies));
-
-	policy = &policies[image_id];
+	policy = FCONF_GET_PROPERTY(stm32mp, io_policies, image_id);
 	rc = policy->check(policy->image_spec);
 	if (rc == 0) {
 		*image_spec = policy->image_spec;
diff --git a/plat/st/common/bl2_stm32_io_storage.c b/plat/st/common/bl2_stm32_io_storage.c
new file mode 100644
index 0000000..2d68a50
--- /dev/null
+++ b/plat/st/common/bl2_stm32_io_storage.c
@@ -0,0 +1,665 @@
+/*
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/io/io_block.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_dummy.h>
+#include <drivers/io/io_mtd.h>
+#include <drivers/io/io_storage.h>
+#include <drivers/mmc.h>
+#include <drivers/partition/partition.h>
+#include <drivers/raw_nand.h>
+#include <drivers/spi_nand.h>
+#include <drivers/spi_nor.h>
+#include <drivers/st/io_mmc.h>
+#include <drivers/st/io_stm32image.h>
+#include <drivers/st/stm32_fmc2_nand.h>
+#include <drivers/st/stm32_qspi.h>
+#include <drivers/st/stm32_sdmmc2.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+/* IO devices */
+#ifndef AARCH32_SP_OPTEE
+static const io_dev_connector_t *dummy_dev_con;
+static uintptr_t dummy_dev_handle;
+static uintptr_t dummy_dev_spec;
+#endif
+
+static uintptr_t image_dev_handle;
+static uintptr_t storage_dev_handle;
+
+#if STM32MP_SDMMC || STM32MP_EMMC
+static struct mmc_device_info mmc_info;
+static io_block_spec_t gpt_block_spec = {
+	.offset = 0U,
+	.length = 34U * MMC_BLOCK_SIZE, /* Size of GPT table */
+};
+
+static uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE);
+
+static const io_block_dev_spec_t mmc_block_dev_spec = {
+	/* It's used as temp buffer in block driver */
+	.buffer = {
+		.offset = (size_t)&block_buffer,
+		.length = MMC_BLOCK_SIZE,
+	},
+	.ops = {
+		.read = mmc_read_blocks,
+		.write = NULL,
+	},
+	.block_size = MMC_BLOCK_SIZE,
+};
+
+#if STM32MP_EMMC_BOOT
+static io_block_spec_t emmc_boot_ssbl_block_spec = {
+	.offset = PLAT_EMMC_BOOT_SSBL_OFFSET,
+	.length = MMC_BLOCK_SIZE, /* We are interested only in first 4 bytes */
+};
+
+static const io_block_dev_spec_t mmc_block_dev_boot_part_spec = {
+	/* It's used as temp buffer in block driver */
+	.buffer = {
+		.offset = (size_t)&block_buffer,
+		.length = MMC_BLOCK_SIZE,
+	},
+	.ops = {
+		.read = mmc_boot_part_read_blocks,
+		.write = NULL,
+	},
+	.block_size = MMC_BLOCK_SIZE,
+};
+#endif
+
+static struct io_mmc_dev_spec mmc_device_spec = {
+	.use_boot_part = false,
+};
+
+static const io_dev_connector_t *mmc_dev_con;
+#endif /* STM32MP_SDMMC || STM32MP_EMMC */
+
+#if STM32MP_SPI_NOR
+static io_mtd_dev_spec_t spi_nor_dev_spec = {
+	.ops = {
+		.init = spi_nor_init,
+		.read = spi_nor_read,
+	},
+};
+#endif
+
+#if STM32MP_RAW_NAND
+static io_mtd_dev_spec_t nand_dev_spec = {
+	.ops = {
+		.init = nand_raw_init,
+		.read = nand_read,
+	},
+};
+
+static const io_dev_connector_t *nand_dev_con;
+#endif
+
+#if STM32MP_SPI_NAND
+static io_mtd_dev_spec_t spi_nand_dev_spec = {
+	.ops = {
+		.init = spi_nand_init,
+		.read = nand_read,
+	},
+};
+#endif
+
+#if STM32MP_SPI_NAND || STM32MP_SPI_NOR
+static const io_dev_connector_t *spi_dev_con;
+#endif
+
+#ifdef AARCH32_SP_OPTEE
+static const struct stm32image_part_info optee_header_partition_spec = {
+	.name = OPTEE_HEADER_IMAGE_NAME,
+	.binary_type = OPTEE_HEADER_BINARY_TYPE,
+};
+
+static const struct stm32image_part_info optee_core_partition_spec = {
+	.name = OPTEE_CORE_IMAGE_NAME,
+	.binary_type = OPTEE_CORE_BINARY_TYPE,
+};
+
+static const struct stm32image_part_info optee_paged_partition_spec = {
+	.name = OPTEE_PAGED_IMAGE_NAME,
+	.binary_type = OPTEE_PAGED_BINARY_TYPE,
+};
+#else
+static const io_block_spec_t bl32_block_spec = {
+	.offset = BL32_BASE,
+	.length = STM32MP_BL32_SIZE
+};
+#endif
+
+static const struct stm32image_part_info bl33_partition_spec = {
+	.name = BL33_IMAGE_NAME,
+	.binary_type = BL33_BINARY_TYPE,
+};
+
+enum {
+	IMG_IDX_BL33,
+#ifdef AARCH32_SP_OPTEE
+	IMG_IDX_OPTEE_HEADER,
+	IMG_IDX_OPTEE_CORE,
+	IMG_IDX_OPTEE_PAGED,
+#endif
+	IMG_IDX_NUM
+};
+
+static struct stm32image_device_info stm32image_dev_info_spec __unused = {
+	.lba_size = MMC_BLOCK_SIZE,
+	.part_info[IMG_IDX_BL33] = {
+		.name = BL33_IMAGE_NAME,
+		.binary_type = BL33_BINARY_TYPE,
+	},
+#ifdef AARCH32_SP_OPTEE
+	.part_info[IMG_IDX_OPTEE_HEADER] = {
+		.name = OPTEE_HEADER_IMAGE_NAME,
+		.binary_type = OPTEE_HEADER_BINARY_TYPE,
+	},
+	.part_info[IMG_IDX_OPTEE_CORE] = {
+		.name = OPTEE_CORE_IMAGE_NAME,
+		.binary_type = OPTEE_CORE_BINARY_TYPE,
+	},
+	.part_info[IMG_IDX_OPTEE_PAGED] = {
+		.name = OPTEE_PAGED_IMAGE_NAME,
+		.binary_type = OPTEE_PAGED_BINARY_TYPE,
+	},
+#endif
+};
+
+static io_block_spec_t stm32image_block_spec = {
+	.offset = 0U,
+	.length = 0U,
+};
+
+static const io_dev_connector_t *stm32image_dev_con __unused;
+
+#ifndef AARCH32_SP_OPTEE
+static int open_dummy(const uintptr_t spec);
+#endif
+static int open_image(const uintptr_t spec);
+static int open_storage(const uintptr_t spec);
+
+struct plat_io_policy {
+	uintptr_t *dev_handle;
+	uintptr_t image_spec;
+	int (*check)(const uintptr_t spec);
+};
+
+static const struct plat_io_policy policies[] = {
+#ifdef AARCH32_SP_OPTEE
+	[BL32_IMAGE_ID] = {
+		.dev_handle = &image_dev_handle,
+		.image_spec = (uintptr_t)&optee_header_partition_spec,
+		.check = open_image
+	},
+	[BL32_EXTRA1_IMAGE_ID] = {
+		.dev_handle = &image_dev_handle,
+		.image_spec = (uintptr_t)&optee_core_partition_spec,
+		.check = open_image
+	},
+	[BL32_EXTRA2_IMAGE_ID] = {
+		.dev_handle = &image_dev_handle,
+		.image_spec = (uintptr_t)&optee_paged_partition_spec,
+		.check = open_image
+	},
+#else
+	[BL32_IMAGE_ID] = {
+		.dev_handle = &dummy_dev_handle,
+		.image_spec = (uintptr_t)&bl32_block_spec,
+		.check = open_dummy
+	},
+#endif
+	[BL33_IMAGE_ID] = {
+		.dev_handle = &image_dev_handle,
+		.image_spec = (uintptr_t)&bl33_partition_spec,
+		.check = open_image
+	},
+#if STM32MP_SDMMC || STM32MP_EMMC
+	[GPT_IMAGE_ID] = {
+		.dev_handle = &storage_dev_handle,
+		.image_spec = (uintptr_t)&gpt_block_spec,
+		.check = open_storage
+	},
+#endif
+	[STM32_IMAGE_ID] = {
+		.dev_handle = &storage_dev_handle,
+		.image_spec = (uintptr_t)&stm32image_block_spec,
+		.check = open_storage
+	}
+};
+
+#ifndef AARCH32_SP_OPTEE
+static int open_dummy(const uintptr_t spec)
+{
+	return io_dev_init(dummy_dev_handle, 0);
+}
+#endif
+
+static int open_image(const uintptr_t spec)
+{
+	return io_dev_init(image_dev_handle, 0);
+}
+
+static int open_storage(const uintptr_t spec)
+{
+	return io_dev_init(storage_dev_handle, 0);
+}
+
+#if STM32MP_EMMC_BOOT
+static uint32_t get_boot_part_ssbl_header(void)
+{
+	uint32_t magic = 0U;
+	int io_result;
+	size_t bytes_read;
+
+	io_result = register_io_dev_block(&mmc_dev_con);
+	if (io_result != 0) {
+		panic();
+	}
+
+	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_boot_part_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
+
+	io_result = io_open(storage_dev_handle, (uintptr_t)&emmc_boot_ssbl_block_spec,
+			    &image_dev_handle);
+	assert(io_result == 0);
+
+	io_result = io_read(image_dev_handle, (uintptr_t)&magic, sizeof(magic),
+			    &bytes_read);
+	assert(io_result == 0);
+	assert(bytes_read == sizeof(magic));
+
+	io_result = io_dev_close(storage_dev_handle);
+	assert(io_result == 0);
+
+	return magic;
+}
+#endif
+
+static void print_boot_device(boot_api_context_t *boot_context)
+{
+	switch (boot_context->boot_interface_selected) {
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
+		INFO("Using SDMMC\n");
+		break;
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
+		INFO("Using EMMC\n");
+		break;
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
+		INFO("Using QSPI NOR\n");
+		break;
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
+		INFO("Using FMC NAND\n");
+		break;
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
+		INFO("Using SPI NAND\n");
+		break;
+	default:
+		ERROR("Boot interface not found\n");
+		panic();
+		break;
+	}
+
+	if (boot_context->boot_interface_instance != 0U) {
+		INFO("  Instance %d\n", boot_context->boot_interface_instance);
+	}
+}
+
+static void stm32image_io_setup(void)
+{
+	int io_result __unused;
+
+	io_result = register_io_dev_stm32image(&stm32image_dev_con);
+	assert(io_result == 0);
+
+	io_result = io_dev_open(stm32image_dev_con,
+				(uintptr_t)&stm32image_dev_info_spec,
+				&image_dev_handle);
+	assert(io_result == 0);
+}
+
+#if STM32MP_SDMMC || STM32MP_EMMC
+static void boot_mmc(enum mmc_device_type mmc_dev_type,
+		     uint16_t boot_interface_instance)
+{
+	int io_result __unused;
+	uint8_t idx;
+	struct stm32image_part_info *part;
+	struct stm32_sdmmc2_params params;
+	const partition_entry_t *entry __unused;
+	uint32_t magic __unused;
+
+	zeromem(&params, sizeof(struct stm32_sdmmc2_params));
+
+	mmc_info.mmc_dev_type = mmc_dev_type;
+
+	switch (boot_interface_instance) {
+	case 1:
+		params.reg_base = STM32MP_SDMMC1_BASE;
+		break;
+	case 2:
+		params.reg_base = STM32MP_SDMMC2_BASE;
+		break;
+	case 3:
+		params.reg_base = STM32MP_SDMMC3_BASE;
+		break;
+	default:
+		WARN("SDMMC instance not found, using default\n");
+		if (mmc_dev_type == MMC_IS_SD) {
+			params.reg_base = STM32MP_SDMMC1_BASE;
+		} else {
+			params.reg_base = STM32MP_SDMMC2_BASE;
+		}
+		break;
+	}
+
+	params.device_info = &mmc_info;
+	if (stm32_sdmmc2_mmc_init(&params) != 0) {
+		ERROR("SDMMC%u init failed\n", boot_interface_instance);
+		panic();
+	}
+
+	stm32image_dev_info_spec.device_size =
+		stm32_sdmmc2_mmc_get_device_size();
+
+#if STM32MP_EMMC_BOOT
+	magic = get_boot_part_ssbl_header();
+
+	if (magic == BOOT_API_IMAGE_HEADER_MAGIC_NB) {
+		VERBOSE("%s, header found, jump to emmc load\n", __func__);
+		idx = IMG_IDX_BL33;
+		part = &stm32image_dev_info_spec.part_info[idx];
+		part->part_offset = PLAT_EMMC_BOOT_SSBL_OFFSET;
+		part->bkp_offset = 0U;
+		mmc_device_spec.use_boot_part = true;
+
+		goto emmc_boot;
+	} else {
+		WARN("%s: Can't find STM32 header on a boot partition\n", __func__);
+	}
+#endif
+
+	/* Open MMC as a block device to read GPT table */
+	io_result = register_io_dev_block(&mmc_dev_con);
+	if (io_result != 0) {
+		panic();
+	}
+
+	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
+
+	partition_init(GPT_IMAGE_ID);
+
+	io_result = io_dev_close(storage_dev_handle);
+	assert(io_result == 0);
+
+	for (idx = 0U; idx < IMG_IDX_NUM; idx++) {
+		part = &stm32image_dev_info_spec.part_info[idx];
+		entry = get_partition_entry(part->name);
+		if (entry == NULL) {
+			ERROR("Partition %s not found\n", part->name);
+			panic();
+		}
+
+		part->part_offset = entry->start;
+		part->bkp_offset = 0U;
+	}
+
+#if STM32MP_EMMC_BOOT
+emmc_boot:
+#endif
+	/*
+	 * Re-open MMC with io_mmc, for better perfs compared to
+	 * io_block.
+	 */
+	io_result = register_io_dev_mmc(&mmc_dev_con);
+	assert(io_result == 0);
+
+	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_device_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
+}
+#endif /* STM32MP_SDMMC || STM32MP_EMMC */
+
+#if STM32MP_SPI_NOR
+static void boot_spi_nor(boot_api_context_t *boot_context)
+{
+	int io_result __unused;
+	uint8_t idx;
+	struct stm32image_part_info *part;
+
+	io_result = stm32_qspi_init();
+	assert(io_result == 0);
+
+	io_result = register_io_dev_mtd(&spi_dev_con);
+	assert(io_result == 0);
+
+	/* Open connections to device */
+	io_result = io_dev_open(spi_dev_con,
+				(uintptr_t)&spi_nor_dev_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
+
+	stm32image_dev_info_spec.device_size = spi_nor_dev_spec.device_size;
+
+	idx = IMG_IDX_BL33;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NOR_BL33_OFFSET;
+	part->bkp_offset = 0U;
+
+#ifdef AARCH32_SP_OPTEE
+	idx = IMG_IDX_OPTEE_HEADER;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NOR_TEEH_OFFSET;
+	part->bkp_offset = 0U;
+
+	idx = IMG_IDX_OPTEE_PAGED;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NOR_TEED_OFFSET;
+	part->bkp_offset = 0U;
+
+	idx = IMG_IDX_OPTEE_CORE;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NOR_TEEX_OFFSET;
+	part->bkp_offset = 0U;
+#endif
+}
+#endif /* STM32MP_SPI_NOR */
+
+#if STM32MP_RAW_NAND
+static void boot_fmc2_nand(boot_api_context_t *boot_context)
+{
+	int io_result __unused;
+	uint8_t idx;
+	struct stm32image_part_info *part;
+
+	io_result = stm32_fmc2_init();
+	assert(io_result == 0);
+
+	/* Register the IO device on this platform */
+	io_result = register_io_dev_mtd(&nand_dev_con);
+	assert(io_result == 0);
+
+	/* Open connections to device */
+	io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
+
+	stm32image_dev_info_spec.device_size = nand_dev_spec.device_size;
+
+	idx = IMG_IDX_BL33;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_BL33_OFFSET;
+	part->bkp_offset = nand_dev_spec.erase_size;
+
+#ifdef AARCH32_SP_OPTEE
+	idx = IMG_IDX_OPTEE_HEADER;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_TEEH_OFFSET;
+	part->bkp_offset = nand_dev_spec.erase_size;
+
+	idx = IMG_IDX_OPTEE_PAGED;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_TEED_OFFSET;
+	part->bkp_offset = nand_dev_spec.erase_size;
+
+	idx = IMG_IDX_OPTEE_CORE;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_TEEX_OFFSET;
+	part->bkp_offset = nand_dev_spec.erase_size;
+#endif
+}
+#endif /* STM32MP_RAW_NAND */
+
+#if STM32MP_SPI_NAND
+static void boot_spi_nand(boot_api_context_t *boot_context)
+{
+	int io_result __unused;
+	uint8_t idx;
+	struct stm32image_part_info *part;
+
+	io_result = stm32_qspi_init();
+	assert(io_result == 0);
+
+	io_result = register_io_dev_mtd(&spi_dev_con);
+	assert(io_result == 0);
+
+	/* Open connections to device */
+	io_result = io_dev_open(spi_dev_con,
+				(uintptr_t)&spi_nand_dev_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
+
+	stm32image_dev_info_spec.device_size =
+		spi_nand_dev_spec.device_size;
+
+	idx = IMG_IDX_BL33;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_BL33_OFFSET;
+	part->bkp_offset = spi_nand_dev_spec.erase_size;
+
+#ifdef AARCH32_SP_OPTEE
+	idx = IMG_IDX_OPTEE_HEADER;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_TEEH_OFFSET;
+	part->bkp_offset = spi_nand_dev_spec.erase_size;
+
+	idx = IMG_IDX_OPTEE_PAGED;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_TEED_OFFSET;
+	part->bkp_offset = spi_nand_dev_spec.erase_size;
+
+	idx = IMG_IDX_OPTEE_CORE;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_TEEX_OFFSET;
+	part->bkp_offset = spi_nand_dev_spec.erase_size;
+#endif
+}
+#endif /* STM32MP_SPI_NAND */
+
+void stm32mp_io_setup(void)
+{
+	int io_result __unused;
+	boot_api_context_t *boot_context =
+		(boot_api_context_t *)stm32mp_get_boot_ctx_address();
+
+	print_boot_device(boot_context);
+
+	if ((boot_context->boot_partition_used_toboot == 1U) ||
+	    (boot_context->boot_partition_used_toboot == 2U)) {
+		INFO("Boot used partition fsbl%u\n",
+		     boot_context->boot_partition_used_toboot);
+	}
+
+#ifndef AARCH32_SP_OPTEE
+	io_result = register_io_dev_dummy(&dummy_dev_con);
+	assert(io_result == 0);
+
+	io_result = io_dev_open(dummy_dev_con, dummy_dev_spec,
+				&dummy_dev_handle);
+	assert(io_result == 0);
+#endif
+
+	switch (boot_context->boot_interface_selected) {
+#if STM32MP_SDMMC
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
+		dmbsy();
+		boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance);
+		stm32image_io_setup();
+		break;
+#endif
+#if STM32MP_EMMC
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
+		dmbsy();
+		boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance);
+		stm32image_io_setup();
+		break;
+#endif
+#if STM32MP_SPI_NOR
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
+		dmbsy();
+		boot_spi_nor(boot_context);
+		stm32image_io_setup();
+		break;
+#endif
+#if STM32MP_RAW_NAND
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
+		dmbsy();
+		boot_fmc2_nand(boot_context);
+		stm32image_io_setup();
+		break;
+#endif
+#if STM32MP_SPI_NAND
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
+		dmbsy();
+		boot_spi_nand(boot_context);
+		stm32image_io_setup();
+		break;
+#endif
+
+	default:
+		ERROR("Boot interface %d not supported\n",
+		      boot_context->boot_interface_selected);
+		panic();
+		break;
+	}
+}
+
+/*
+ * Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy.
+ */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+			  uintptr_t *image_spec)
+{
+	int rc;
+	const struct plat_io_policy *policy;
+
+	assert(image_id < ARRAY_SIZE(policies));
+
+	policy = &policies[image_id];
+	rc = policy->check(policy->image_spec);
+	if (rc == 0) {
+		*image_spec = policy->image_spec;
+		*dev_handle = *(policy->dev_handle);
+	}
+
+	return rc;
+}
diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h
index 42d3487..8a5fe48 100644
--- a/plat/st/common/include/stm32mp_common.h
+++ b/plat/st/common/include/stm32mp_common.h
@@ -17,6 +17,7 @@
 /* Functions to save and get boot context address given by ROM code */
 void stm32mp_save_boot_ctx_address(uintptr_t address);
 uintptr_t stm32mp_get_boot_ctx_address(void);
+uint16_t stm32mp_get_boot_itf_selected(void);
 
 bool stm32mp_is_single_core(void);
 bool stm32mp_is_closed_device(void);
@@ -94,6 +95,7 @@
 /* Initialise the IO layer and register platform IO devices */
 void stm32mp_io_setup(void);
 
+#if STM32MP_USE_STM32IMAGE
 /*
  * Check that the STM32 header of a .stm32 binary image is valid
  * @param header: pointer to the stm32 image header
@@ -101,6 +103,7 @@
  * @return: 0 on success, negative value in case of error
  */
 int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer);
+#endif /* STM32MP_USE_STM32IMAGE */
 
 /* Functions to map DDR in MMU with non-cacheable attribute, and unmap it */
 int stm32mp_map_ddr_non_cacheable(void);
diff --git a/plat/st/common/include/stm32mp_fconf_getter.h b/plat/st/common/include/stm32mp_fconf_getter.h
new file mode 100644
index 0000000..3a8bb11
--- /dev/null
+++ b/plat/st/common/include/stm32mp_fconf_getter.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP_FCONF_GETTER
+#define STM32MP_FCONF_GETTER
+
+#include <assert.h>
+
+#include <lib/fconf/fconf.h>
+
+/* IO policies */
+#define stm32mp__io_policies_getter(id) __extension__ ({	\
+	assert((id) < MAX_NUMBER_IDS);				\
+	&policies[id];						\
+})
+
+struct plat_io_policy {
+	uintptr_t *dev_handle;
+	uintptr_t image_spec;
+	int (*check)(const uintptr_t spec);
+};
+
+extern struct plat_io_policy policies[];
+int fconf_populate_stm32mp_io_policies(uintptr_t config);
+
+#endif /* STM32MP_FCONF_GETTER */
diff --git a/plat/st/common/include/stm32mp_io_storage.h b/plat/st/common/include/stm32mp_io_storage.h
new file mode 100644
index 0000000..989c890
--- /dev/null
+++ b/plat/st/common/include/stm32mp_io_storage.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef STM32MP_IO_STORAGE_H
+#define STM32MP_IO_STORAGE_H
+
+#include <stdint.h>
+
+#include <drivers/io/io_storage.h>
+
+/* IO devices handle */
+extern uintptr_t storage_dev_handle;
+extern uintptr_t fip_dev_handle;
+
+extern io_block_spec_t image_block_spec;
+
+/* Function declarations */
+int open_fip(const uintptr_t spec);
+int open_storage(const uintptr_t spec);
+
+#endif /* STM32MP_IO_STORAGE_H */
diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c
index d3de1e1..17ac145 100644
--- a/plat/st/common/stm32mp_common.c
+++ b/plat/st/common/stm32mp_common.c
@@ -28,10 +28,14 @@
 }
 
 static uintptr_t boot_ctx_address;
+static uint16_t boot_itf_selected;
 
 void stm32mp_save_boot_ctx_address(uintptr_t address)
 {
+	boot_api_context_t *boot_context = (boot_api_context_t *)address;
+
 	boot_ctx_address = address;
+	boot_itf_selected = boot_context->boot_interface_selected;
 }
 
 uintptr_t stm32mp_get_boot_ctx_address(void)
@@ -39,6 +43,11 @@
 	return boot_ctx_address;
 }
 
+uint16_t stm32mp_get_boot_itf_selected(void)
+{
+	return boot_itf_selected;
+}
+
 uintptr_t stm32mp_ddrctrl_base(void)
 {
 	return DDRCTRL_BASE;
@@ -67,6 +76,7 @@
 	return (read_sctlr() & c_m_bits) == c_m_bits;
 }
 
+#if STM32MP_USE_STM32IMAGE
 int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer)
 {
 	uint32_t i;
@@ -100,12 +110,13 @@
 
 	return 0;
 }
+#endif /* STM32MP_USE_STM32IMAGE */
 
 int stm32mp_map_ddr_non_cacheable(void)
 {
 	return  mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE,
 					STM32MP_DDR_MAX_SIZE,
-					MT_NON_CACHEABLE | MT_RW | MT_NS);
+					MT_NON_CACHEABLE | MT_RW | MT_SECURE);
 }
 
 int stm32mp_unmap_ddr(void)
diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c
index 6465c10..0b35646 100644
--- a/plat/st/common/stm32mp_dt.c
+++ b/plat/st/common/stm32mp_dt.c
@@ -209,15 +209,24 @@
  ******************************************************************************/
 uint32_t dt_get_ddr_size(void)
 {
+	static uint32_t size;
 	int node;
 
+	if (size != 0U) {
+		return size;
+	}
+
 	node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
 	if (node < 0) {
 		INFO("%s: Cannot read DDR node in DT\n", __func__);
 		return 0;
 	}
 
-	return fdt_read_uint32_default(fdt, node, "st,mem-size", 0);
+	size = fdt_read_uint32_default(fdt, node, "st,mem-size", 0U);
+
+	flush_dcache_range((uintptr_t)&size, sizeof(uint32_t));
+
+	return size;
 }
 
 /*******************************************************************************
diff --git a/plat/st/common/stm32mp_fconf_io.c b/plat/st/common/stm32mp_fconf_io.c
new file mode 100644
index 0000000..aa8cd54
--- /dev/null
+++ b/plat/st/common/stm32mp_fconf_io.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <drivers/io/io_storage.h>
+#include <drivers/mmc.h>
+#include <lib/fconf/fconf.h>
+#include <lib/object_pool.h>
+#include <libfdt.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <platform_def.h>
+#include <stm32mp_fconf_getter.h>
+#include <stm32mp_io_storage.h>
+
+#if STM32MP_SDMMC || STM32MP_EMMC
+static io_block_spec_t gpt_block_spec = {
+	.offset = 0U,
+	.length = 34U * MMC_BLOCK_SIZE, /* Size of GPT table */
+};
+#endif
+
+/* By default, STM32 platforms load images from the FIP */
+struct plat_io_policy policies[MAX_NUMBER_IDS] = {
+	[FIP_IMAGE_ID] = {
+		&storage_dev_handle,
+		(uintptr_t)&image_block_spec,
+		open_storage
+	},
+#if STM32MP_SDMMC || STM32MP_EMMC
+	[GPT_IMAGE_ID] = {
+		&storage_dev_handle,
+		(uintptr_t)&gpt_block_spec,
+		open_storage
+	},
+#endif
+};
+
+#define FCONF_ST_IO_UUID_NUMBER	U(8)
+
+static io_uuid_spec_t fconf_stm32mp_uuids[FCONF_ST_IO_UUID_NUMBER];
+static OBJECT_POOL_ARRAY(fconf_stm32mp_uuids_pool, fconf_stm32mp_uuids);
+
+struct policies_load_info {
+	unsigned int image_id;
+	const char *name;
+};
+
+/* image id to property name table */
+static const struct policies_load_info load_info[FCONF_ST_IO_UUID_NUMBER] = {
+	{FW_CONFIG_ID, "fw_cfg_uuid"},
+	{BL32_IMAGE_ID, "bl32_uuid"},
+	{BL32_EXTRA1_IMAGE_ID, "bl32_extra1_uuid"},
+	{BL32_EXTRA2_IMAGE_ID, "bl32_extra2_uuid"},
+	{BL33_IMAGE_ID, "bl33_uuid"},
+	{HW_CONFIG_ID, "hw_cfg_uuid"},
+	{TOS_FW_CONFIG_ID, "tos_fw_cfg_uuid"},
+	{NT_FW_CONFIG_ID, "nt_fw_cfg_uuid"},
+};
+
+int fconf_populate_stm32mp_io_policies(uintptr_t config)
+{
+	int node;
+	unsigned int i;
+
+	/* As libfdt uses void *, we can't avoid this cast */
+	const void *dtb = (void *)config;
+
+	/* Assert the node offset point to "st,io-fip-handle" compatible property */
+	const char *compatible_str = "st,io-fip-handle";
+
+	node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+	if (node < 0) {
+		ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str);
+		return node;
+	}
+
+	/* Locate the uuid cells and read the value for all the load info uuid */
+	for (i = 0U; i < FCONF_ST_IO_UUID_NUMBER; i++) {
+		union uuid_helper_t uuid_helper;
+		io_uuid_spec_t *uuid_ptr;
+		int err;
+
+		uuid_ptr = pool_alloc(&fconf_stm32mp_uuids_pool);
+		err = fdtw_read_uuid(dtb, node, load_info[i].name, 16,
+				     (uint8_t *)&uuid_helper);
+		if (err < 0) {
+			WARN("FCONF: Read cell failed for %s\n", load_info[i].name);
+			return err;
+		}
+
+		VERBOSE("FCONF: stm32mp-io_policies.%s cell found with value = "
+			"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
+			load_info[i].name,
+			uuid_helper.uuid_struct.time_low[0], uuid_helper.uuid_struct.time_low[1],
+			uuid_helper.uuid_struct.time_low[2], uuid_helper.uuid_struct.time_low[3],
+			uuid_helper.uuid_struct.time_mid[0], uuid_helper.uuid_struct.time_mid[1],
+			uuid_helper.uuid_struct.time_hi_and_version[0],
+			uuid_helper.uuid_struct.time_hi_and_version[1],
+			uuid_helper.uuid_struct.clock_seq_hi_and_reserved,
+			uuid_helper.uuid_struct.clock_seq_low,
+			uuid_helper.uuid_struct.node[0], uuid_helper.uuid_struct.node[1],
+			uuid_helper.uuid_struct.node[2], uuid_helper.uuid_struct.node[3],
+			uuid_helper.uuid_struct.node[4], uuid_helper.uuid_struct.node[5]);
+
+		uuid_ptr->uuid = uuid_helper.uuid_struct;
+		policies[load_info[i].image_id].image_spec = (uintptr_t)uuid_ptr;
+		policies[load_info[i].image_id].dev_handle = &fip_dev_handle;
+		policies[load_info[i].image_id].check = open_fip;
+	}
+
+	return 0;
+}
+
+FCONF_REGISTER_POPULATOR(TB_FW, stm32mp_io, fconf_populate_stm32mp_io_policies);
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index 91073b8..e87c529 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -5,6 +5,7 @@
  */
 
 #include <assert.h>
+#include <errno.h>
 #include <string.h>
 
 #include <platform_def.h>
@@ -15,6 +16,7 @@
 #include <common/desc_image_load.h>
 #include <drivers/delay_timer.h>
 #include <drivers/generic_delay_timer.h>
+#include <drivers/mmc.h>
 #include <drivers/st/bsec.h>
 #include <drivers/st/stm32_console.h>
 #include <drivers/st/stm32_iwdg.h>
@@ -23,6 +25,8 @@
 #include <drivers/st/stm32mp1_clk.h>
 #include <drivers/st/stm32mp1_pwr.h>
 #include <drivers/st/stm32mp1_ram.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
 #include <lib/mmio.h>
 #include <lib/optee_utils.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
@@ -132,7 +136,6 @@
 void bl2_platform_setup(void)
 {
 	int ret;
-	uint32_t ddr_ns_size;
 
 	if (dt_pmic_status() > 0) {
 		initialize_pmic();
@@ -144,29 +147,21 @@
 		panic();
 	}
 
-	ddr_ns_size = stm32mp_get_ddr_ns_size();
-	assert(ddr_ns_size > 0U);
-
-	/* Map non secure DDR for BL33 load, now with cacheable attribute */
+	/* Map DDR for binary load, now with cacheable attribute */
 	ret = mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE,
-				      ddr_ns_size, MT_MEMORY | MT_RW | MT_NS);
-	assert(ret == 0);
+				      STM32MP_DDR_MAX_SIZE, MT_MEMORY | MT_RW | MT_SECURE);
+	if (ret < 0) {
+		ERROR("DDR mapping: error %d\n", ret);
+		panic();
+	}
 
+#if STM32MP_USE_STM32IMAGE
 #ifdef AARCH32_SP_OPTEE
 	INFO("BL2 runs OP-TEE setup\n");
-
-	/* Map secure DDR for OP-TEE paged area */
-	ret = mmap_add_dynamic_region(STM32MP_DDR_BASE + ddr_ns_size,
-				      STM32MP_DDR_BASE + ddr_ns_size,
-				      STM32MP_DDR_S_SIZE,
-				      MT_MEMORY | MT_RW | MT_SECURE);
-	assert(ret == 0);
-
-	/* Initialize tzc400 after DDR initialization */
-	stm32mp1_security_setup();
 #else
 	INFO("BL2 runs SP_MIN setup\n");
 #endif
+#endif /* STM32MP_USE_STM32IMAGE */
 }
 
 void bl2_el3_plat_arch_setup(void)
@@ -184,11 +179,19 @@
 			BL_CODE_END - BL_CODE_BASE,
 			MT_CODE | MT_SECURE);
 
+#if STM32MP_USE_STM32IMAGE
 #ifdef AARCH32_SP_OPTEE
 	mmap_add_region(STM32MP_OPTEE_BASE, STM32MP_OPTEE_BASE,
 			STM32MP_OPTEE_SIZE,
 			MT_MEMORY | MT_RW | MT_SECURE);
+#else
+	/* Prevent corruption of preloaded BL32 */
+	mmap_add_region(BL32_BASE, BL32_BASE,
+			BL32_LIMIT - BL32_BASE,
+			MT_RO_DATA | MT_SECURE);
 #endif
+#endif /* STM32MP_USE_STM32IMAGE */
+
 	/* Prevent corruption of preloaded Device Tree */
 	mmap_add_region(DTB_BASE, DTB_BASE,
 			DTB_LIMIT - DTB_BASE,
@@ -327,10 +330,13 @@
 
 	print_reset_reason();
 
+#if !STM32MP_USE_STM32IMAGE
+	fconf_populate("TB_FW", STM32MP_DTB_BASE);
+#endif /* !STM32MP_USE_STM32IMAGE */
+
 	stm32mp_io_setup();
 }
 
-#if defined(AARCH32_SP_OPTEE)
 /*******************************************************************************
  * This function can be used by the platforms to update/use image
  * information for given `image_id`.
@@ -340,44 +346,119 @@
 	int err = 0;
 	bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
 	bl_mem_params_node_t *bl32_mem_params;
-	bl_mem_params_node_t *pager_mem_params;
-	bl_mem_params_node_t *paged_mem_params;
+	bl_mem_params_node_t *pager_mem_params __unused;
+	bl_mem_params_node_t *paged_mem_params __unused;
+#if !STM32MP_USE_STM32IMAGE
+	const struct dyn_cfg_dtb_info_t *config_info;
+	bl_mem_params_node_t *tos_fw_mem_params;
+	unsigned int i;
+	unsigned long long ddr_top __unused;
+	const unsigned int image_ids[] = {
+		BL32_IMAGE_ID,
+		BL33_IMAGE_ID,
+		HW_CONFIG_ID,
+		TOS_FW_CONFIG_ID,
+	};
+#endif /* !STM32MP_USE_STM32IMAGE */
 
 	assert(bl_mem_params != NULL);
 
 	switch (image_id) {
-	case BL32_IMAGE_ID:
-		bl_mem_params->ep_info.pc =
-					bl_mem_params->image_info.image_base;
+#if !STM32MP_USE_STM32IMAGE
+	case FW_CONFIG_ID:
+		/* Set global DTB info for fixed fw_config information */
+		set_config_info(STM32MP_FW_CONFIG_BASE, STM32MP_FW_CONFIG_MAX_SIZE, FW_CONFIG_ID);
+		fconf_populate("FW_CONFIG", STM32MP_FW_CONFIG_BASE);
+
+		/* Iterate through all the fw config IDs */
+		for (i = 0U; i < ARRAY_SIZE(image_ids); i++) {
+			bl_mem_params = get_bl_mem_params_node(image_ids[i]);
+			assert(bl_mem_params != NULL);
+
+			config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, image_ids[i]);
+			if (config_info == NULL) {
+				continue;
+			}
+
+			bl_mem_params->image_info.image_base = config_info->config_addr;
+			bl_mem_params->image_info.image_max_size = config_info->config_max_size;
+
+			bl_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING;
+
+			switch (image_ids[i]) {
+			case BL32_IMAGE_ID:
+				bl_mem_params->ep_info.pc = config_info->config_addr;
+
+				/* In case of OPTEE, initialize address space with tos_fw addr */
+				pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+				pager_mem_params->image_info.image_base = config_info->config_addr;
+				pager_mem_params->image_info.image_max_size =
+					config_info->config_max_size;
 
-		pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
-		assert(pager_mem_params != NULL);
-		pager_mem_params->image_info.image_base = STM32MP_OPTEE_BASE;
-		pager_mem_params->image_info.image_max_size =
-			STM32MP_OPTEE_SIZE;
+				/* Init base and size for pager if exist */
+				paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+				paged_mem_params->image_info.image_base = STM32MP_DDR_BASE +
+					(dt_get_ddr_size() - STM32MP_DDR_S_SIZE -
+					 STM32MP_DDR_SHMEM_SIZE);
+				paged_mem_params->image_info.image_max_size = STM32MP_DDR_S_SIZE;
+				break;
 
-		paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
-		assert(paged_mem_params != NULL);
-		paged_mem_params->image_info.image_base = STM32MP_DDR_BASE +
-			stm32mp_get_ddr_ns_size();
-		paged_mem_params->image_info.image_max_size =
-			STM32MP_DDR_S_SIZE;
+			case BL33_IMAGE_ID:
+				bl_mem_params->ep_info.pc = config_info->config_addr;
+				break;
 
-		err = parse_optee_header(&bl_mem_params->ep_info,
-					 &pager_mem_params->image_info,
-					 &paged_mem_params->image_info);
-		if (err) {
-			ERROR("OPTEE header parse error.\n");
-			panic();
+			case HW_CONFIG_ID:
+			case TOS_FW_CONFIG_ID:
+				break;
+
+			default:
+				return -EINVAL;
+			}
 		}
+		break;
+#endif /* !STM32MP_USE_STM32IMAGE */
+
+	case BL32_IMAGE_ID:
+		if (optee_header_is_valid(bl_mem_params->image_info.image_base)) {
+			/* BL32 is OP-TEE header */
+			bl_mem_params->ep_info.pc = bl_mem_params->image_info.image_base;
+			pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+			paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
+			assert((pager_mem_params != NULL) && (paged_mem_params != NULL));
+
+#if STM32MP_USE_STM32IMAGE && defined(AARCH32_SP_OPTEE)
+			/* Set OP-TEE extra image load areas at run-time */
+			pager_mem_params->image_info.image_base = STM32MP_OPTEE_BASE;
+			pager_mem_params->image_info.image_max_size = STM32MP_OPTEE_SIZE;
 
-		/* Set optee boot info from parsed header data */
-		bl_mem_params->ep_info.pc =
-				pager_mem_params->image_info.image_base;
-		bl_mem_params->ep_info.args.arg0 =
-				paged_mem_params->image_info.image_base;
-		bl_mem_params->ep_info.args.arg1 = 0; /* Unused */
-		bl_mem_params->ep_info.args.arg2 = 0; /* No DT supported */
+			paged_mem_params->image_info.image_base = STM32MP_DDR_BASE +
+								  dt_get_ddr_size() -
+								  STM32MP_DDR_S_SIZE -
+								  STM32MP_DDR_SHMEM_SIZE;
+			paged_mem_params->image_info.image_max_size = STM32MP_DDR_S_SIZE;
+#endif /* STM32MP_USE_STM32IMAGE && defined(AARCH32_SP_OPTEE) */
+
+			err = parse_optee_header(&bl_mem_params->ep_info,
+						 &pager_mem_params->image_info,
+						 &paged_mem_params->image_info);
+			if (err) {
+				ERROR("OPTEE header parse error.\n");
+				panic();
+			}
+
+			/* Set optee boot info from parsed header data */
+			bl_mem_params->ep_info.args.arg0 = paged_mem_params->image_info.image_base;
+			bl_mem_params->ep_info.args.arg1 = 0; /* Unused */
+			bl_mem_params->ep_info.args.arg2 = 0; /* No DT supported */
+		} else {
+#if !STM32MP_USE_STM32IMAGE
+			bl_mem_params->ep_info.pc = bl_mem_params->image_info.image_base;
+			tos_fw_mem_params = get_bl_mem_params_node(TOS_FW_CONFIG_ID);
+			bl_mem_params->image_info.image_max_size +=
+				tos_fw_mem_params->image_info.image_max_size;
+#endif /* !STM32MP_USE_STM32IMAGE */
+			bl_mem_params->ep_info.args.arg0 = 0;
+		}
 		break;
 
 	case BL33_IMAGE_ID:
@@ -391,6 +472,23 @@
 		break;
 	}
 
+#if STM32MP_SDMMC || STM32MP_EMMC
+	/*
+	 * Invalidate remaining data read from MMC but not flushed by load_image_flush().
+	 * We take the worst case which is 2 MMC blocks.
+	 */
+	if ((image_id != FW_CONFIG_ID) &&
+	    ((bl_mem_params->image_info.h.attr & IMAGE_ATTRIB_SKIP_LOADING) == 0U)) {
+		inv_dcache_range(bl_mem_params->image_info.image_base +
+				 bl_mem_params->image_info.image_size,
+				 2U * MMC_BLOCK_SIZE);
+	}
+#endif /* STM32MP_SDMMC || STM32MP_EMMC */
+
 	return err;
 }
-#endif
+
+void bl2_el3_plat_prepare_exit(void)
+{
+	stm32mp1_security_setup();
+}
diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h
index 2d7d369..8a065bf 100644
--- a/plat/st/stm32mp1/include/platform_def.h
+++ b/plat/st/stm32mp1/include/platform_def.h
@@ -25,6 +25,7 @@
 #define PLATFORM_STACK_SIZE		0xC00
 #endif
 
+#if STM32MP_USE_STM32IMAGE
 #ifdef AARCH32_SP_OPTEE
 #define OPTEE_HEADER_IMAGE_NAME		"teeh"
 #define OPTEE_CORE_IMAGE_NAME		"teex"
@@ -37,6 +38,9 @@
 /* SSBL = second stage boot loader */
 #define BL33_IMAGE_NAME			"ssbl"
 #define BL33_BINARY_TYPE		U(0x0)
+#else /* STM32MP_USE_STM32IMAGE */
+#define FIP_IMAGE_NAME			"fip"
+#endif /* STM32MP_USE_STM32IMAGE */
 
 #define STM32MP_PRIMARY_CPU		U(0x0)
 #define STM32MP_SECONDARY_CPU		U(0x1)
@@ -67,7 +71,7 @@
 /*******************************************************************************
  * BL32 specific defines.
  ******************************************************************************/
-#ifndef AARCH32_SP_OPTEE
+#if STM32MP_USE_STM32IMAGE || defined(IMAGE_BL32)
 #if ENABLE_PIE
 #define BL32_BASE			0
 #define BL32_LIMIT			STM32MP_BL32_SIZE
@@ -76,7 +80,7 @@
 #define BL32_LIMIT			(STM32MP_BL32_BASE + \
 					 STM32MP_BL32_SIZE)
 #endif
-#endif
+#endif /* STM32MP_USE_STM32IMAGE || defined(IMAGE_BL32) */
 
 /*******************************************************************************
  * BL33 specific defines.
diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h
index b6cb91e..729d233 100644
--- a/plat/st/stm32mp1/include/stm32mp1_private.h
+++ b/plat/st/stm32mp1/include/stm32mp1_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,7 +21,9 @@
 void stm32mp1_syscfg_enable_io_compensation(void);
 void stm32mp1_syscfg_disable_io_compensation(void);
 
+#if STM32MP_USE_STM32IMAGE
 uint32_t stm32mp_get_ddr_ns_size(void);
+#endif /* STM32MP_USE_STM32IMAGE */
 
 void stm32mp1_init_scmi_server(void);
 #endif /* STM32MP1_PRIVATE_H */
diff --git a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
index 984c6ba..7963c4a 100644
--- a/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
+++ b/plat/st/stm32mp1/plat_bl2_mem_params_desc.c
@@ -4,12 +4,12 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <platform_def.h>
-
 #include <common/bl_common.h>
 #include <common/desc_image_load.h>
 #include <plat/common/platform.h>
 
+#include <platform_def.h>
+
 /*******************************************************************************
  * Following descriptor provides BL image/ep information that gets used
  * by BL2 to load the images and also subset of this information is
@@ -19,6 +19,22 @@
  * the next executable image id.
  ******************************************************************************/
 static bl_mem_params_node_t bl2_mem_params_descs[] = {
+	/* Fill FW_CONFIG related information if it exists */
+	{
+		.image_id = FW_CONFIG_ID,
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | NON_EXECUTABLE),
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_PLAT_SETUP),
+
+		.image_info.image_base = STM32MP_FW_CONFIG_BASE,
+		.image_info.image_max_size = STM32MP_FW_CONFIG_MAX_SIZE,
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+
 	/* Fill BL32 related information */
 	{
 		.image_id = BL32_IMAGE_ID,
@@ -27,28 +43,17 @@
 				      VERSION_2, entry_point_info_t,
 				      SECURE | EXECUTABLE | EP_FIRST_EXE),
 
-#if !defined(AARCH32_SP_OPTEE)
-		.ep_info.pc = STM32MP_BL32_BASE,
-#endif
 		.ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
 					    SPSR_E_LITTLE,
 					    DISABLE_ALL_EXCEPTIONS),
 
 		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
 				      VERSION_2, image_info_t,
-				      IMAGE_ATTRIB_PLAT_SETUP),
-#if defined(AARCH32_SP_OPTEE)
-		/* optee header is loaded in SYSRAM above BL2 */
-		.image_info.image_base = STM32MP_OPTEE_BASE,
-		.image_info.image_max_size = STM32MP_OPTEE_SIZE,
-#else
-		.image_info.image_base = STM32MP_BL32_BASE,
-		.image_info.image_max_size = STM32MP_BL32_SIZE,
-#endif
+				      IMAGE_ATTRIB_SKIP_LOADING),
+
 		.next_handoff_image_id = BL33_IMAGE_ID,
 	},
 
-#if defined(AARCH32_SP_OPTEE)
 	/* Fill BL32 external 1 image related information */
 	{
 		.image_id = BL32_EXTRA1_IMAGE_ID,
@@ -77,7 +82,32 @@
 
 		.next_handoff_image_id = INVALID_IMAGE_ID,
 	},
-#endif /* AARCH32_SP_OPTEE */
+
+	/* Fill HW_CONFIG related information if it exists */
+	{
+		.image_id = HW_CONFIG_ID,
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+				      VERSION_2, entry_point_info_t,
+				      NON_SECURE | NON_EXECUTABLE),
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+
+	/* Fill TOS_FW_CONFIG related information if it exists */
+	{
+		.image_id = TOS_FW_CONFIG_ID,
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | NON_EXECUTABLE),
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
 
 	/* Fill BL33 related information */
 	{
@@ -87,17 +117,13 @@
 				      VERSION_2, entry_point_info_t,
 				      NON_SECURE | EXECUTABLE),
 
-		.ep_info.pc = PLAT_STM32MP_NS_IMAGE_OFFSET,
 		.ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
 					    SPSR_E_LITTLE,
 					    DISABLE_ALL_EXCEPTIONS),
 
 		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
-				      VERSION_2, image_info_t, 0),
-
-		.image_info.image_base = PLAT_STM32MP_NS_IMAGE_OFFSET,
-		.image_info.image_max_size = STM32MP_DDR_MAX_SIZE -
-			(PLAT_STM32MP_NS_IMAGE_OFFSET - STM32MP_DDR_BASE),
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
 
 		.next_handoff_image_id = INVALID_IMAGE_ID,
 	}
diff --git a/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c b/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c
new file mode 100644
index 0000000..4fce55a
--- /dev/null
+++ b/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+/*******************************************************************************
+ * Following descriptor provides BL image/ep information that gets used
+ * by BL2 to load the images and also subset of this information is
+ * passed to next BL image. The image loading sequence is managed by
+ * populating the images in required loading order. The image execution
+ * sequence is managed by populating the `next_handoff_image_id` with
+ * the next executable image id.
+ ******************************************************************************/
+static bl_mem_params_node_t bl2_mem_params_descs[] = {
+	/* Fill BL32 related information */
+	{
+		.image_id = BL32_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | EXECUTABLE | EP_FIRST_EXE),
+
+		/* Updated at runtime if OP-TEE is loaded */
+		.ep_info.pc = STM32MP_BL32_BASE,
+
+		.ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
+					    SPSR_E_LITTLE,
+					    DISABLE_ALL_EXCEPTIONS),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_PLAT_SETUP),
+
+		/* Updated at runtime if OP-TEE is loaded */
+		.image_info.image_base = STM32MP_BL32_BASE,
+		.image_info.image_max_size = STM32MP_BL32_SIZE,
+
+		.next_handoff_image_id = BL33_IMAGE_ID,
+	},
+
+#if defined(AARCH32_SP_OPTEE)
+	/* Fill BL32 external 1 image related information */
+	{
+		.image_id = BL32_EXTRA1_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | NON_EXECUTABLE),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+	/* Fill BL32 external 2 image related information */
+	{
+		.image_id = BL32_EXTRA2_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | NON_EXECUTABLE),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+#endif /* AARCH32_SP_OPTEE */
+
+	/* Fill BL33 related information */
+	{
+		.image_id = BL33_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      NON_SECURE | EXECUTABLE),
+
+		.ep_info.pc = PLAT_STM32MP_NS_IMAGE_OFFSET,
+		.ep_info.spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
+					    SPSR_E_LITTLE,
+					    DISABLE_ALL_EXCEPTIONS),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t, 0U),
+
+		.image_info.image_base = PLAT_STM32MP_NS_IMAGE_OFFSET,
+		.image_info.image_max_size = STM32MP_DDR_MAX_SIZE -
+			(PLAT_STM32MP_NS_IMAGE_OFFSET - STM32MP_DDR_BASE),
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	}
+};
+
+REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/st/stm32mp1/plat_image_load.c b/plat/st/stm32mp1/plat_image_load.c
index 6d7af74..36a3a1c 100644
--- a/plat/st/stm32mp1/plat_image_load.c
+++ b/plat/st/stm32mp1/plat_image_load.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -23,12 +23,14 @@
  ******************************************************************************/
 bl_load_info_t *plat_get_bl_image_load_info(void)
 {
+#if STM32MP_USE_STM32IMAGE
 	bl_mem_params_node_t *bl33 = get_bl_mem_params_node(BL33_IMAGE_ID);
 	uint32_t ddr_ns_size = stm32mp_get_ddr_ns_size();
 
 	/* Max size is non-secure DDR end address minus image_base */
 	bl33->image_info.image_max_size = STM32MP_DDR_BASE + ddr_ns_size -
 					  bl33->image_info.image_base;
+#endif /* STM32MP_USE_STM32IMAGE */
 
 	return get_bl_load_info_from_mem_params_desc();
 }
@@ -38,5 +40,9 @@
  ******************************************************************************/
 bl_params_t *plat_get_next_bl_params(void)
 {
-	return get_next_bl_params_from_mem_params_desc();
+	bl_params_t *bl_params = get_next_bl_params_from_mem_params_desc();
+
+	populate_next_bl_params_config(bl_params);
+
+	return bl_params;
 }
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index 1693135..1c2c9f0 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -9,7 +9,14 @@
 BL2_AT_EL3		:=	1
 USE_COHERENT_MEM	:=	0
 
+# Allow TF-A to concatenate BL2 & BL32 binaries in a single file,
+# share DTB file between BL2 and BL32
+# If it is set to 0, then FIP is used
+STM32MP_USE_STM32IMAGE	?=	0
+
+ifneq ($(STM32MP_USE_STM32IMAGE),1)
 ENABLE_PIE		:=	1
+endif
 
 STM32_TF_VERSION	?=	0
 
@@ -29,8 +36,10 @@
 STM32_BL33_PARTS_NUM		:=	1
 ifeq ($(AARCH32_SP),optee)
 STM32_RUNTIME_PARTS_NUM		:=	3
-else
+else ifeq ($(STM32MP_USE_STM32IMAGE),1)
 STM32_RUNTIME_PARTS_NUM		:=	0
+else
+STM32_RUNTIME_PARTS_NUM		:=	1
 endif
 PLAT_PARTITION_MAX_ENTRIES	:=	$(shell echo $$(($(STM32_TF_A_COPIES) + \
 							 $(STM32_BL33_PARTS_NUM) + \
@@ -46,7 +55,22 @@
 
 # Device tree
 DTB_FILE_NAME		?=	stm32mp157c-ev1.dtb
+ifeq ($(STM32MP_USE_STM32IMAGE),1)
+ifeq ($(AARCH32_SP),optee)
+BL2_DTSI		:=	stm32mp15-bl2.dtsi
+FDT_SOURCES		:=	$(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME)))
+else
 FDT_SOURCES		:=	$(addprefix fdts/, $(patsubst %.dtb,%.dts,$(DTB_FILE_NAME)))
+endif
+else
+BL2_DTSI		:=	stm32mp15-bl2.dtsi
+FDT_SOURCES		:=	$(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME)))
+ifeq ($(AARCH32_SP),sp_min)
+BL32_DTSI		:=	stm32mp15-bl32.dtsi
+FDT_SOURCES		+=	$(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dts,$(DTB_FILE_NAME)))
+endif
+endif
+DTC_CPPFLAGS		+=	${INCLUDES}
 DTC_FLAGS		+=	-Wno-unit_address_vs_reg
 
 # Macros and rules to build TF binary
@@ -66,6 +90,33 @@
 STM32IMAGE		?= ${STM32IMAGEPATH}/stm32image${BIN_EXT}
 STM32IMAGE_SRC		:= ${STM32IMAGEPATH}/stm32image.c
 
+ifneq (${STM32MP_USE_STM32IMAGE},1)
+FIP_DEPS		+=	dtbs
+STM32MP_HW_CONFIG	:=	${BL33_CFG}
+STM32MP_FW_CONFIG_NAME	:=	$(patsubst %.dtb,%-fw-config.dtb,$(DTB_FILE_NAME))
+STM32MP_FW_CONFIG	:=	${BUILD_PLAT}/fdts/$(STM32MP_FW_CONFIG_NAME)
+ifneq (${AARCH32_SP},none)
+FDT_SOURCES		+=	$(addprefix fdts/, $(patsubst %.dtb,%.dts,$(STM32MP_FW_CONFIG_NAME)))
+endif
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_FW_CONFIG},--fw-config))
+# Add the HW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_HW_CONFIG},--hw-config))
+ifeq ($(AARCH32_SP),sp_min)
+STM32MP_TOS_FW_CONFIG	:= $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dtb,$(DTB_FILE_NAME)))
+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_TOS_FW_CONFIG},--tos-fw-config))
+else
+# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
+# in the FIP if the platform requires.
+ifneq ($(BL32_EXTRA1),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA1,--tos-fw-extra1))
+endif
+ifneq ($(BL32_EXTRA2),)
+$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2))
+endif
+endif
+endif
+
 # Enable flags for C files
 $(eval $(call assert_booleans,\
 	$(sort \
@@ -76,6 +127,7 @@
 		STM32MP_SPI_NOR \
 		STM32MP_EMMC_BOOT \
 		PLAT_XLAT_TABLES_DYNAMIC \
+		STM32MP_USE_STM32IMAGE \
 )))
 
 $(eval $(call assert_numerics,\
@@ -95,6 +147,7 @@
 		PLAT_XLAT_TABLES_DYNAMIC \
 		STM32_TF_A_COPIES \
 		PLAT_PARTITION_MAX_ENTRIES \
+		STM32MP_USE_STM32IMAGE \
 )))
 
 # Include paths and source files
@@ -104,6 +157,7 @@
 include lib/libfdt/libfdt.mk
 
 PLAT_BL_COMMON_SOURCES	:=	common/fdt_wrappers.c					\
+				common/uuid.c						\
 				plat/st/common/stm32mp_common.c				\
 				plat/st/stm32mp1/stm32mp1_private.c
 
@@ -135,17 +189,29 @@
 				plat/st/stm32mp1/stm32mp1_context.c			\
 				plat/st/stm32mp1/stm32mp1_dbgmcu.c			\
 				plat/st/stm32mp1/stm32mp1_helper.S			\
-				plat/st/stm32mp1/stm32mp1_security.c			\
 				plat/st/stm32mp1/stm32mp1_syscfg.c
 
+ifneq (${STM32MP_USE_STM32IMAGE},1)
+BL2_SOURCES		+=	drivers/io/io_fip.c					\
+				lib/fconf/fconf.c					\
+				lib/fconf/fconf_dyn_cfg_getter.c			\
+				plat/st/common/bl2_io_storage.c				\
+				plat/st/common/stm32mp_fconf_io.c			\
+				plat/st/stm32mp1/plat_bl2_mem_params_desc.c		\
+				plat/st/stm32mp1/stm32mp1_fconf_firewall.c
+else
+BL2_SOURCES		+=	drivers/io/io_dummy.c					\
+				drivers/st/io/io_stm32image.c				\
+				plat/st/common/bl2_stm32_io_storage.c			\
+				plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c	\
+				plat/st/stm32mp1/stm32mp1_security.c
+endif
+
 BL2_SOURCES		+=	drivers/io/io_block.c					\
-				drivers/io/io_dummy.c					\
 				drivers/io/io_mtd.c					\
 				drivers/io/io_storage.c					\
 				drivers/st/crypto/stm32_hash.c				\
-				drivers/st/io/io_stm32image.c				\
 				plat/st/common/stm32mp_auth.c				\
-				plat/st/common/bl2_io_storage.c				\
 				plat/st/stm32mp1/bl2_plat_setup.c
 
 ifneq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC}),)
@@ -187,12 +253,9 @@
 				drivers/st/ddr/stm32mp1_ram.c
 
 BL2_SOURCES		+=	common/desc_image_load.c				\
-				plat/st/stm32mp1/plat_bl2_mem_params_desc.c		\
 				plat/st/stm32mp1/plat_image_load.c
 
-ifeq ($(AARCH32_SP),optee)
 BL2_SOURCES		+=	lib/optee/optee_utils.c
-endif
 
 # Compilation rules
 .PHONY: check_dtc_version stm32image clean_stm32image check_boot_device
@@ -230,12 +293,35 @@
 		false; \
 	fi
 
-
+ifeq ($(STM32MP_USE_STM32IMAGE)-$(AARCH32_SP),1-sp_min)
 ${BUILD_PLAT}/stm32mp1-%.o: ${BUILD_PLAT}/fdts/%.dtb plat/st/stm32mp1/stm32mp1.S bl2 ${BL32_DEP}
 	@echo "  AS      stm32mp1.S"
 	${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \
 		-DDTB_BIN_PATH=\"$<\" \
+		-c $(word 2,$^) -o $@
+else
+# Create DTB file for BL2
+${BUILD_PLAT}/fdts/%-bl2.dts: fdts/%.dts fdts/${BL2_DTSI} | ${BUILD_PLAT} fdt_dirs
+	@echo '#include "$(patsubst fdts/%,%,$<)"' > $@
+	@echo '#include "${BL2_DTSI}"' >> $@
+
+${BUILD_PLAT}/fdts/%-bl2.dtb: ${BUILD_PLAT}/fdts/%-bl2.dts
+
+ifeq ($(AARCH32_SP),sp_min)
+# Create DTB file for BL32
+${BUILD_PLAT}/fdts/%-bl32.dts: fdts/%.dts fdts/${BL32_DTSI} | ${BUILD_PLAT} fdt_dirs
+	@echo '#include "$(patsubst fdts/%,%,$<)"' > $@
+	@echo '#include "${BL32_DTSI}"' >> $@
+
+${BUILD_PLAT}/fdts/%-bl32.dtb: ${BUILD_PLAT}/fdts/%-bl32.dts
+endif
+
+${BUILD_PLAT}/stm32mp1-%.o: ${BUILD_PLAT}/fdts/%-bl2.dtb plat/st/stm32mp1/stm32mp1.S bl2
+	@echo "  AS      stm32mp1.S"
+	${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \
+		-DDTB_BIN_PATH=\"$<\" \
 		-c plat/st/stm32mp1/stm32mp1.S -o $@
+endif
 
 $(eval $(call MAKE_LD,${STM32_TF_LINKERFILE},plat/st/stm32mp1/stm32mp1.ld.S,2))
 
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
index 334f914..1495e02 100644
--- a/plat/st/stm32mp1/sp_min/sp_min_setup.c
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
@@ -45,6 +45,7 @@
 {
 	switch (id & INT_ID_MASK) {
 	case STM32MP1_IRQ_TZC400:
+		tzc400_init(STM32MP1_TZC_BASE);
 		(void)tzc400_it_handler();
 		panic();
 		break;
@@ -117,6 +118,11 @@
 	struct dt_node_info dt_uart_info;
 	int result;
 	bl_params_t *params_from_bl2 = (bl_params_t *)arg0;
+#if STM32MP_USE_STM32IMAGE
+	uintptr_t dt_addr = STM32MP_DTB_BASE;
+#else
+	uintptr_t dt_addr = arg1;
+#endif
 
 	/* Imprecise aborts can be masked in NonSecure */
 	write_scr(read_scr() | SCR_AW_BIT);
@@ -140,13 +146,23 @@
 	while (bl_params != NULL) {
 		if (bl_params->image_id == BL33_IMAGE_ID) {
 			bl33_image_ep_info = *bl_params->ep_info;
+			/*
+			 *  Check if hw_configuration is given to BL32 and
+			 *  share it to BL33.
+			 */
+			if (arg2 != 0U) {
+				bl33_image_ep_info.args.arg0 = 0U;
+				bl33_image_ep_info.args.arg1 = 0U;
+				bl33_image_ep_info.args.arg2 = arg2;
+			}
+
 			break;
 		}
 
 		bl_params = bl_params->next_params_info;
 	}
 
-	if (dt_open_and_check(STM32MP_DTB_BASE) < 0) {
+	if (dt_open_and_check(dt_addr) < 0) {
 		panic();
 	}
 
@@ -185,9 +201,6 @@
  ******************************************************************************/
 void sp_min_platform_setup(void)
 {
-	/* Initialize tzc400 after DDR initialization */
-	stm32mp1_security_setup();
-
 	generic_delay_timer_init();
 
 	stm32mp1_gic_init();
diff --git a/plat/st/stm32mp1/stm32mp1.S b/plat/st/stm32mp1/stm32mp1.S
index 7255fe5..85caa0a 100644
--- a/plat/st/stm32mp1/stm32mp1.S
+++ b/plat/st/stm32mp1/stm32mp1.S
@@ -1,13 +1,15 @@
 /*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#if STM32MP_USE_STM32IMAGE
 #ifdef BL32_BIN_PATH
 .section .bl32_image
 .incbin BL32_BIN_PATH
 #endif
+#endif /* STM32MP_USE_STM32IMAGE */
 
 .section .bl2_image
 .incbin BL2_BIN_PATH
diff --git a/plat/st/stm32mp1/stm32mp1.ld.S b/plat/st/stm32mp1/stm32mp1.ld.S
index b347bad..945de99 100644
--- a/plat/st/stm32mp1/stm32mp1.ld.S
+++ b/plat/st/stm32mp1/stm32mp1.ld.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -43,7 +43,11 @@
          * The strongest and only alignment contraint is MMU 4K page.
          * Indeed as images below will be removed, 4K pages will be re-used.
          */
+#if STM32MP_USE_STM32IMAGE
         . = ( STM32MP_DTB_BASE - STM32MP_BINARY_BASE );
+#else
+        . = ( STM32MP_BL2_DTB_BASE - STM32MP_BINARY_BASE );
+#endif /* STM32MP_USE_STM32IMAGE */
         __DTB_IMAGE_START__ = .;
         *(.dtb_image*)
         __DTB_IMAGE_END__ = .;
@@ -58,7 +62,7 @@
         *(.bl2_image*)
         __BL2_IMAGE_END__ = .;
 
-#ifndef AARCH32_SP_OPTEE
+#if STM32MP_USE_STM32IMAGE && !defined(AARCH32_SP_OPTEE)
         /*
          * bl32 will be settled by bl2.
          * The strongest and only alignment constraint is 8 words to simplify
@@ -68,7 +72,7 @@
         __BL32_IMAGE_START__ = .;
         *(.bl32_image*)
         __BL32_IMAGE_END__ = .;
-#endif
+#endif /* STM32MP_USE_STM32IMAGE && !defined(AARCH32_SP_OPTEE) */
 
         __DATA_END__ = .;
     } >RAM
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index 155d63d..0d36660 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -28,6 +28,12 @@
 #include <stm32mp1_shared_resources.h>
 #endif
 
+#if !STM32MP_USE_STM32IMAGE
+#include "stm32mp1_fip_def.h"
+#else /* STM32MP_USE_STM32IMAGE */
+#include "stm32mp1_stm32image_def.h"
+#endif /* STM32MP_USE_STM32IMAGE */
+
 /*******************************************************************************
  * CHIP ID
  ******************************************************************************/
@@ -81,13 +87,6 @@
 /* DDR configuration */
 #define STM32MP_DDR_BASE		U(0xC0000000)
 #define STM32MP_DDR_MAX_SIZE		U(0x40000000)	/* Max 1GB */
-#ifdef AARCH32_SP_OPTEE
-#define STM32MP_DDR_S_SIZE		U(0x01E00000)	/* 30 MB */
-#define STM32MP_DDR_SHMEM_SIZE		U(0x00200000)	/* 2 MB */
-#else
-#define STM32MP_DDR_S_SIZE		U(0)
-#define STM32MP_DDR_SHMEM_SIZE		U(0)
-#endif
 
 /* DDR power initializations */
 #ifndef __ASSEMBLER__
@@ -111,26 +110,6 @@
 					 (STM32MP_PARAM_LOAD_SIZE +	\
 					  STM32MP_HEADER_SIZE))
 
-#ifdef AARCH32_SP_OPTEE
-#define STM32MP_BL32_SIZE		U(0)
-
-#define STM32MP_OPTEE_BASE		STM32MP_SEC_SYSRAM_BASE
-
-#define STM32MP_OPTEE_SIZE		(STM32MP_DTB_BASE -  \
-					 STM32MP_OPTEE_BASE)
-#else
-#define STM32MP_BL32_SIZE		U(0x00012000)	/* 72 KB for BL32 */
-#endif
-
-#define STM32MP_BL32_BASE		(STM32MP_SEC_SYSRAM_BASE + \
-					 STM32MP_SEC_SYSRAM_SIZE - \
-					 STM32MP_BL32_SIZE)
-
-#define STM32MP_BL2_SIZE		U(0x0001A000)	/* 100 KB for BL2 */
-
-#define STM32MP_BL2_BASE		(STM32MP_BL32_BASE - \
-					 STM32MP_BL2_SIZE)
-
 /* BL2 and BL32/sp_min require 4 tables */
 #define MAX_XLAT_TABLES			U(4)		/* 16 KB for mapping */
 
@@ -141,39 +120,14 @@
 #if defined(IMAGE_BL2)
   #define MAX_MMAP_REGIONS		11
 #endif
-#if defined(IMAGE_BL32)
-  #define MAX_MMAP_REGIONS		6
-#endif
-
-/* DTB initialization value */
-#define STM32MP_DTB_SIZE		U(0x00005000)	/* 20 KB for DTB */
-
-#define STM32MP_DTB_BASE		(STM32MP_BL2_BASE - \
-					 STM32MP_DTB_SIZE)
 
 #define STM32MP_BL33_BASE		(STM32MP_DDR_BASE + U(0x100000))
+#define STM32MP_BL33_MAX_SIZE		U(0x400000)
 
 /* Define maximum page size for NAND devices */
 #define PLATFORM_MTD_MAX_PAGE_SIZE	U(0x1000)
 
 /*******************************************************************************
- * STM32MP1 RAW partition offset for MTD devices
- ******************************************************************************/
-#define STM32MP_NOR_BL33_OFFSET		U(0x00080000)
-#ifdef AARCH32_SP_OPTEE
-#define STM32MP_NOR_TEEH_OFFSET		U(0x00280000)
-#define STM32MP_NOR_TEED_OFFSET		U(0x002C0000)
-#define STM32MP_NOR_TEEX_OFFSET		U(0x00300000)
-#endif
-
-#define STM32MP_NAND_BL33_OFFSET	U(0x00200000)
-#ifdef AARCH32_SP_OPTEE
-#define STM32MP_NAND_TEEH_OFFSET	U(0x00600000)
-#define STM32MP_NAND_TEED_OFFSET	U(0x00680000)
-#define STM32MP_NAND_TEEX_OFFSET	U(0x00700000)
-#endif
-
-/*******************************************************************************
  * STM32MP1 device/io map related constants (used for MMU)
  ******************************************************************************/
 #define STM32MP1_DEVICE1_BASE		U(0x40000000)
@@ -355,18 +309,6 @@
  ******************************************************************************/
 #define STM32MP1_TZC_BASE		U(0x5C006000)
 
-#define STM32MP1_TZC_A7_ID		U(0)
-#define STM32MP1_TZC_M4_ID		U(1)
-#define STM32MP1_TZC_LCD_ID		U(3)
-#define STM32MP1_TZC_GPU_ID		U(4)
-#define STM32MP1_TZC_MDMA_ID		U(5)
-#define STM32MP1_TZC_DMA_ID		U(6)
-#define STM32MP1_TZC_USB_HOST_ID	U(7)
-#define STM32MP1_TZC_USB_OTG_ID		U(8)
-#define STM32MP1_TZC_SDMMC_ID		U(9)
-#define STM32MP1_TZC_ETH_ID		U(10)
-#define STM32MP1_TZC_DAP_ID		U(15)
-
 #define STM32MP1_FILTER_BIT_ALL		(TZC_400_REGION_ATTR_FILTER_BIT(0) | \
 					 TZC_400_REGION_ATTR_FILTER_BIT(1))
 
diff --git a/plat/st/stm32mp1/stm32mp1_fconf_firewall.c b/plat/st/stm32mp1/stm32mp1_fconf_firewall.c
new file mode 100644
index 0000000..caf9ff1
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_fconf_firewall.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <drivers/arm/tzc400.h>
+#include <drivers/st/stm32mp1_clk.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <lib/fconf/fconf.h>
+#include <lib/object_pool.h>
+#include <libfdt.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <platform_def.h>
+#include <stm32mp_fconf_getter.h>
+
+#define STM32MP_REGION_PARAMS	4
+#define STM32MP_MAX_REGIONS	8
+#define FORCE_SEC_REGION	BIT(31)
+
+static uint32_t nb_regions;
+
+struct dt_id_attr {
+	fdt32_t id_attr[STM32MP_MAX_REGIONS];
+};
+
+void stm32mp1_arch_security_setup(void)
+{
+	stm32mp_clk_enable(TZC1);
+	stm32mp_clk_enable(TZC2);
+
+	tzc400_init(STM32MP1_TZC_BASE);
+	tzc400_disable_filters();
+
+	/*
+	 * Region 0 set to cover all DRAM at 0xC000_0000
+	 * Only secure access is granted in read/write.
+	 */
+	tzc400_configure_region0(TZC_REGION_S_RDWR, 0);
+
+	tzc400_set_action(TZC_ACTION_ERR);
+	tzc400_enable_filters();
+}
+
+void stm32mp1_security_setup(void)
+{
+	uint8_t i;
+
+	assert(nb_regions > 0U);
+
+	tzc400_init(STM32MP1_TZC_BASE);
+	tzc400_disable_filters();
+
+	/*
+	 * Region 0 set to cover all DRAM at 0xC000_0000
+	 * No access is allowed.
+	 */
+	tzc400_configure_region0(TZC_REGION_S_NONE, 0);
+
+	for (i = 1U; i <= nb_regions; i++) {
+		tzc400_update_filters(i, STM32MP1_FILTER_BIT_ALL);
+	}
+
+	tzc400_set_action(TZC_ACTION_INT);
+	tzc400_enable_filters();
+}
+
+static int fconf_populate_stm32mp1_firewall(uintptr_t config)
+{
+	int node, len;
+	unsigned int i;
+	const struct dt_id_attr *conf_list;
+	const void *dtb = (const void *)config;
+
+	/* Assert the node offset point to "st,mem-firewall" compatible property */
+	const char *compatible_str = "st,mem-firewall";
+
+	node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+	if (node < 0) {
+		ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str);
+		return node;
+	}
+
+	conf_list = (const struct dt_id_attr *)fdt_getprop(dtb, node, "memory-ranges", &len);
+	if (conf_list == NULL) {
+		WARN("FCONF: Read cell failed for %s\n", "memory-ranges");
+		return -1;
+	}
+
+	/* Locate the memory cells and read all values */
+	for (i = 0U; i < (unsigned int)(len / (sizeof(uint32_t) * STM32MP_REGION_PARAMS)); i++) {
+		uint32_t base;
+		uint32_t size;
+		uint32_t sec_attr;
+		uint32_t nsaid;
+
+		base = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS]);
+		size = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 1]);
+		sec_attr = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 2]);
+		nsaid = fdt32_to_cpu(conf_list->id_attr[i * STM32MP_REGION_PARAMS + 3]);
+
+		VERBOSE("FCONF: stm32mp1-firewall cell found with value = 0x%x 0x%x 0x%x 0x%x\n",
+			base, size, sec_attr, nsaid);
+
+		nb_regions++;
+
+		/* Configure region but keep disabled for secure access for BL2 load */
+		tzc400_configure_region(0U, nb_regions, (unsigned long long)base,
+					(unsigned long long)base + size - 1ULL, sec_attr, nsaid);
+	}
+
+	/* Force flush as the value will be used cache off */
+	flush_dcache_range((uintptr_t)&nb_regions, sizeof(uint32_t));
+
+	return 0;
+}
+
+FCONF_REGISTER_POPULATOR(FW_CONFIG, stm32mp1_firewall, fconf_populate_stm32mp1_firewall);
diff --git a/plat/st/stm32mp1/stm32mp1_fip_def.h b/plat/st/stm32mp1/stm32mp1_fip_def.h
new file mode 100644
index 0000000..d8561dc
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_fip_def.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_FIP_DEF_H
+#define STM32MP1_FIP_DEF_H
+
+#define STM32MP_DDR_S_SIZE		U(0x01E00000)	/* 30 MB */
+#define STM32MP_DDR_SHMEM_SIZE		U(0x00200000)	/* 2 MB */
+
+#define STM32MP_BL2_SIZE		U(0x0001B000)	/* 108 KB for BL2 */
+#define STM32MP_BL2_DTB_SIZE		U(0x00006000)	/* 24 KB for DTB */
+#define STM32MP_BL32_SIZE		U(0x00019000)	/* 100 KB for BL32 */
+#define STM32MP_BL32_DTB_SIZE		U(0x00005000)	/* 20 KB for DTB */
+#define STM32MP_FW_CONFIG_MAX_SIZE	PAGE_SIZE	/* 4 KB for FCONF DTB */
+#define STM32MP_HW_CONFIG_MAX_SIZE	U(0x40000)	/* 256 KB for HW config DTB */
+
+#define STM32MP_BL2_BASE		(STM32MP_SEC_SYSRAM_BASE + \
+					 STM32MP_SEC_SYSRAM_SIZE - \
+					 STM32MP_BL2_SIZE)
+
+#define STM32MP_BL2_DTB_BASE		(STM32MP_BL2_BASE - \
+					 STM32MP_BL2_DTB_SIZE)
+
+#define STM32MP_BL32_DTB_BASE		STM32MP_SYSRAM_BASE
+
+#define STM32MP_BL32_BASE		(STM32MP_BL32_DTB_BASE + \
+					 STM32MP_BL32_DTB_SIZE)
+
+
+#if defined(IMAGE_BL2)
+#define STM32MP_DTB_SIZE		STM32MP_BL2_DTB_SIZE
+#define STM32MP_DTB_BASE		STM32MP_BL2_DTB_BASE
+#endif
+#if defined(IMAGE_BL32)
+#define STM32MP_DTB_SIZE		STM32MP_BL32_DTB_SIZE
+#define STM32MP_DTB_BASE		STM32MP_BL32_DTB_BASE
+#endif
+
+#ifdef AARCH32_SP_OPTEE
+#define STM32MP_OPTEE_BASE		STM32MP_SEC_SYSRAM_BASE
+
+#define STM32MP_OPTEE_SIZE		(STM32MP_BL2_DTB_BASE -  \
+					 STM32MP_OPTEE_BASE)
+#endif
+
+#define STM32MP_FW_CONFIG_BASE		(STM32MP_SYSRAM_BASE + \
+					 STM32MP_SYSRAM_SIZE - \
+					 PAGE_SIZE)
+#define STM32MP_HW_CONFIG_BASE		(STM32MP_BL33_BASE + \
+					STM32MP_BL33_MAX_SIZE)
+
+/*
+ * MAX_MMAP_REGIONS is usually:
+ * BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup
+ */
+#if defined(IMAGE_BL32)
+#define MAX_MMAP_REGIONS		10
+#endif
+
+/*******************************************************************************
+ * STM32MP1 RAW partition offset for MTD devices
+ ******************************************************************************/
+#define STM32MP_NOR_FIP_OFFSET		U(0x00080000)
+#define STM32MP_NAND_FIP_OFFSET		U(0x00200000)
+
+#endif /* STM32MP1_FIP_DEF_H */
diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c
index 1af0075..e4065c1 100644
--- a/plat/st/stm32mp1/stm32mp1_private.c
+++ b/plat/st/stm32mp1/stm32mp1_private.c
@@ -452,6 +452,7 @@
 }
 #endif
 
+#if STM32MP_USE_STM32IMAGE
 /* Get the non-secure DDR size */
 uint32_t stm32mp_get_ddr_ns_size(void)
 {
@@ -472,3 +473,4 @@
 
 	return ddr_ns_size;
 }
+#endif /* STM32MP_USE_STM32IMAGE */
diff --git a/plat/st/stm32mp1/stm32mp1_security.c b/plat/st/stm32mp1/stm32mp1_security.c
index 195b3a5..19ef4f0 100644
--- a/plat/st/stm32mp1/stm32mp1_security.c
+++ b/plat/st/stm32mp1/stm32mp1_security.c
@@ -12,20 +12,47 @@
 #include <drivers/arm/tzc400.h>
 #include <drivers/st/stm32mp1_clk.h>
 #include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/soc/stm32mp15-tzc400.h>
 #include <lib/mmio.h>
 
-#define TZC_REGION_NSEC_ALL_ACCESS_RDWR \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) | \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) | \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) | \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_M4_ID) | \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) | \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) | \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) | \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) | \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) | \
-	TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID)
+static unsigned int region_nb;
+
+static void init_tzc400_begin(unsigned int region0_attr)
+{
+	tzc400_init(STM32MP1_TZC_BASE);
+	tzc400_disable_filters();
+
+	/* Region 0 set to cover all DRAM at 0xC000_0000 */
+	tzc400_configure_region0(region0_attr, 0);
+
+	region_nb = 1U;
+}
+
+static void init_tzc400_end(unsigned int action)
+{
+	tzc400_set_action(action);
+	tzc400_enable_filters();
+}
+
+static void tzc400_add_region(unsigned long long region_base,
+			      unsigned long long region_top, bool sec)
+{
+	unsigned int sec_attr;
+	unsigned int nsaid_permissions;
+
+	if (sec) {
+		sec_attr = TZC_REGION_S_RDWR;
+		nsaid_permissions = 0;
+	} else {
+		sec_attr = TZC_REGION_S_NONE;
+		nsaid_permissions = TZC_REGION_NSEC_ALL_ACCESS_RDWR;
+	}
+
+	tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, region_nb, region_base,
+				region_top, sec_attr, nsaid_permissions);
+
+	region_nb++;
+}
 
 /*******************************************************************************
  * Initialize the TrustZone Controller. Configure Region 0 with Secure RW access
@@ -38,10 +65,9 @@
 	unsigned long long ddr_ns_size =
 		(unsigned long long)stm32mp_get_ddr_ns_size();
 	unsigned long long ddr_ns_top = ddr_base + (ddr_ns_size - 1U);
-
-	tzc400_init(STM32MP1_TZC_BASE);
+	unsigned long long ddr_top __unused;
 
-	tzc400_disable_filters();
+	init_tzc400_begin(TZC_REGION_S_NONE);
 
 	/*
 	 * Region 1 set to cover all non-secure DRAM at 0xC000_0000. Apply the
@@ -49,35 +75,28 @@
 	 */
 	region_base = ddr_base;
 	region_top = ddr_ns_top;
-	tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1,
-				region_base,
-				region_top,
-				TZC_REGION_S_NONE,
-				TZC_REGION_NSEC_ALL_ACCESS_RDWR);
+	tzc400_add_region(region_base, region_top, false);
 
 #ifdef AARCH32_SP_OPTEE
 	/* Region 2 set to cover all secure DRAM. */
 	region_base = region_top + 1U;
 	region_top += STM32MP_DDR_S_SIZE;
-	tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 2,
-				region_base,
-				region_top,
-				TZC_REGION_S_RDWR,
-				0);
+	tzc400_add_region(region_base, region_top, true);
 
-	/* Region 3 set to cover non-secure shared memory DRAM. */
-	region_base = region_top + 1U;
-	region_top += STM32MP_DDR_SHMEM_SIZE;
-	tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 3,
-				region_base,
-				region_top,
-				TZC_REGION_S_NONE,
-				TZC_REGION_NSEC_ALL_ACCESS_RDWR);
+	ddr_top = STM32MP_DDR_BASE + dt_get_ddr_size() - 1U;
+	if (region_top < ddr_top) {
+		/* Region 3 set to cover non-secure memory DRAM after BL32. */
+		region_base = region_top + 1U;
+		region_top = ddr_top;
+		tzc400_add_region(region_base, region_top, false);
+	}
 #endif
 
-	tzc400_set_action(TZC_ACTION_INT);
-
-	tzc400_enable_filters();
+	/*
+	 * Raise an interrupt (secure FIQ) if a NS device tries to access
+	 * secure memory
+	 */
+	init_tzc400_end(TZC_ACTION_INT);
 }
 
 /*******************************************************************************
@@ -90,23 +109,11 @@
 	stm32mp_clk_enable(TZC1);
 	stm32mp_clk_enable(TZC2);
 
-	tzc400_init(STM32MP1_TZC_BASE);
-
-	tzc400_disable_filters();
-
-	/* Region 1 set to cover Non-Secure DRAM at 0xC000_0000 */
-	tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1,
-				STM32MP_DDR_BASE,
-				STM32MP_DDR_BASE +
-				(STM32MP_DDR_MAX_SIZE - 1U),
-				TZC_REGION_S_NONE,
-				TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) |
-				TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID));
+	/* Region 0 set to cover all DRAM secure at 0xC000_0000 */
+	init_tzc400_begin(TZC_REGION_S_RDWR);
 
 	/* Raise an exception if a NS device tries to access secure memory */
-	tzc400_set_action(TZC_ACTION_ERR);
-
-	tzc400_enable_filters();
+	init_tzc400_end(TZC_ACTION_ERR);
 }
 
 /*******************************************************************************
diff --git a/plat/st/stm32mp1/stm32mp1_stm32image_def.h b/plat/st/stm32mp1/stm32mp1_stm32image_def.h
new file mode 100644
index 0000000..8efa342
--- /dev/null
+++ b/plat/st/stm32mp1/stm32mp1_stm32image_def.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP1_STM32IMAGE_DEF_H
+#define STM32MP1_STM32IMAGE_DEF_H
+
+#ifdef AARCH32_SP_OPTEE
+#define STM32MP_DDR_S_SIZE		U(0x01E00000)	/* 30 MB */
+#define STM32MP_DDR_SHMEM_SIZE		U(0x00200000)	/* 2 MB */
+#else
+#define STM32MP_DDR_S_SIZE		U(0)
+#define STM32MP_DDR_SHMEM_SIZE		U(0)
+#endif
+
+#define STM32MP_BL2_SIZE		U(0x0001C000)	/* 112 KB for BL2 */
+#define STM32MP_DTB_SIZE		U(0x00006000)	/* 24 KB for DTB */
+
+#ifdef AARCH32_SP_OPTEE
+#define STM32MP_BL32_BASE		STM32MP_SEC_SYSRAM_BASE
+
+#define STM32MP_BL2_BASE		(STM32MP_SEC_SYSRAM_BASE + \
+					 STM32MP_SEC_SYSRAM_SIZE - \
+					 STM32MP_BL2_SIZE)
+
+/* OP-TEE loads from SYSRAM base to BL2 DTB start address */
+#define STM32MP_OPTEE_BASE		STM32MP_BL32_BASE
+#define STM32MP_OPTEE_SIZE		(STM32MP_SEC_SYSRAM_SIZE -  \
+					 STM32MP_BL2_SIZE - STM32MP_DTB_SIZE)
+#define STM32MP_BL32_SIZE		STM32MP_OPTEE_SIZE
+#else /* AARCH32_SP_OPTEE */
+#define STM32MP_BL32_SIZE		U(0x00019000)	/* 96 KB for BL32 */
+
+#define STM32MP_BL32_BASE		(STM32MP_SEC_SYSRAM_BASE + \
+					 STM32MP_SEC_SYSRAM_SIZE - \
+					 STM32MP_BL32_SIZE)
+
+#define STM32MP_BL2_BASE		(STM32MP_BL32_BASE - \
+					 STM32MP_BL2_SIZE)
+#endif /* AARCH32_SP_OPTEE */
+
+/* DTB initialization value */
+#define STM32MP_DTB_BASE		(STM32MP_BL2_BASE -	\
+					 STM32MP_DTB_SIZE)
+
+/*
+ * MAX_MMAP_REGIONS is usually:
+ * BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup
+ */
+#if defined(IMAGE_BL32)
+#define MAX_MMAP_REGIONS		6
+#endif
+
+/*******************************************************************************
+ * STM32MP1 RAW partition offset for MTD devices
+ ******************************************************************************/
+#define STM32MP_NOR_BL33_OFFSET		U(0x00080000)
+#ifdef AARCH32_SP_OPTEE
+#define STM32MP_NOR_TEEH_OFFSET		U(0x00280000)
+#define STM32MP_NOR_TEED_OFFSET		U(0x002C0000)
+#define STM32MP_NOR_TEEX_OFFSET		U(0x00300000)
+#endif
+
+#define STM32MP_NAND_BL33_OFFSET	U(0x00200000)
+#ifdef AARCH32_SP_OPTEE
+#define STM32MP_NAND_TEEH_OFFSET	U(0x00600000)
+#define STM32MP_NAND_TEED_OFFSET	U(0x00680000)
+#define STM32MP_NAND_TEEX_OFFSET	U(0x00700000)
+#endif
+
+#endif /* STM32MP1_STM32IMAGE_DEF_H */
diff --git a/plat/xilinx/common/include/ipi.h b/plat/xilinx/common/include/ipi.h
index 9c1d0f2..483902e 100644
--- a/plat/xilinx/common/include/ipi.h
+++ b/plat/xilinx/common/include/ipi.h
@@ -63,7 +63,7 @@
 int ipi_mb_enquire_status(uint32_t local, uint32_t remote);
 
 /* Trigger notification on the IPI mailbox */
-int ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking);
+void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking);
 
 /* Ack IPI mailbox notification */
 void ipi_mb_ack(uint32_t local, uint32_t remote);
diff --git a/plat/xilinx/common/ipi.c b/plat/xilinx/common/ipi.c
index ca4146e..0b8020b 100644
--- a/plat/xilinx/common/ipi.c
+++ b/plat/xilinx/common/ipi.c
@@ -13,7 +13,6 @@
 
 #include <common/debug.h>
 #include <common/runtime_svc.h>
-#include <drivers/delay_timer.h>
 #include <lib/bakery_lock.h>
 #include <lib/mmio.h>
 
@@ -39,9 +38,6 @@
 /* IPI register bit mask */
 #define IPI_BIT_MASK(I) (ipi_table[(I)].ipi_bit_mask)
 
-/* IPI Timeout */
-#define TIMEOUT_COUNT_US	U(0x4000)
-
 /* IPI configuration table */
 const static struct ipi_config *ipi_table;
 
@@ -160,30 +156,21 @@
  * @remote - remote IPI ID
  * @is_blocking - if to trigger the notification in blocking mode or not.
  *
- * return - 0 - Success or Error incase of timeout
  * It sets the remote bit in the IPI agent trigger register.
  *
  */
-int ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking)
+void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking)
 {
 	uint32_t status;
-	const unsigned int timeout_count = TIMEOUT_COUNT_US;
-	uint64_t timeout;
 
 	mmio_write_32(IPI_REG_BASE(local) + IPI_TRIG_OFFSET,
 		      IPI_BIT_MASK(remote));
 	if (is_blocking) {
-		timeout = timeout_init_us(timeout_count);
 		do {
 			status = mmio_read_32(IPI_REG_BASE(local) +
 					      IPI_OBR_OFFSET);
-			if (timeout_elapsed(timeout)) {
-				return -ETIMEDOUT;
-			}
 		} while (status & IPI_BIT_MASK(remote));
 	}
-
-	return 0;
 }
 
 /* ipi_mb_ack() - Ack IPI mailbox notification from the other end
diff --git a/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c b/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c
index cd5d830..f531158 100644
--- a/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c
+++ b/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c
@@ -107,8 +107,8 @@
 		uint32_t is_blocking;
 
 		is_blocking = (x3 & IPI_SMC_NOTIFY_BLOCK_MASK) ? 1 : 0;
-		ret = ipi_mb_notify(ipi_local_id, ipi_remote_id, is_blocking);
-		SMC_RET1(handle, ret);
+		ipi_mb_notify(ipi_local_id, ipi_remote_id, is_blocking);
+		SMC_RET1(handle, 0);
 	}
 	case IPI_MAILBOX_ACK:
 	{
diff --git a/plat/xilinx/common/pm_service/pm_ipi.c b/plat/xilinx/common/pm_service/pm_ipi.c
index 7b5bd02..7b2c8ec 100644
--- a/plat/xilinx/common/pm_service/pm_ipi.c
+++ b/plat/xilinx/common/pm_service/pm_ipi.c
@@ -55,7 +55,6 @@
 					     uint32_t payload[PAYLOAD_ARG_CNT],
 					     uint32_t is_blocking)
 {
-	int status;
 	unsigned int offset = 0;
 	uintptr_t buffer_base = proc->ipi->buffer_base +
 					IPI_BUFFER_TARGET_REMOTE_OFFSET +
@@ -71,13 +70,10 @@
 	}
 
 	/* Generate IPI to remote processor */
-	status = ipi_mb_notify(proc->ipi->local_ipi_id, proc->ipi->remote_ipi_id,
+	ipi_mb_notify(proc->ipi->local_ipi_id, proc->ipi->remote_ipi_id,
 		      is_blocking);
-	if (status == 0) {
-		return PM_RET_SUCCESS;
-	}
 
-	return PM_RET_ERROR_TIMEOUT;
+	return PM_RET_SUCCESS;
 }
 
 /**
diff --git a/plat/xilinx/versal/platform.mk b/plat/xilinx/versal/platform.mk
index a0b317f..a8b2c94 100644
--- a/plat/xilinx/versal/platform.mk
+++ b/plat/xilinx/versal/platform.mk
@@ -9,6 +9,7 @@
 override RESET_TO_BL31 := 1
 PL011_GENERIC_UART := 1
 IPI_CRC_CHECK := 0
+HARDEN_SLS_ALL := 0
 
 ifdef VERSAL_ATF_MEM_BASE
     $(eval $(call add_define,VERSAL_ATF_MEM_BASE))
@@ -87,3 +88,7 @@
 				plat/xilinx/versal/pm_service/pm_svc_main.c	\
 				plat/xilinx/versal/pm_service/pm_api_sys.c	\
 				plat/xilinx/versal/pm_service/pm_client.c
+
+ifeq ($(HARDEN_SLS_ALL), 1)
+TF_CFLAGS_aarch64      +=      -mharden-sls=all
+endif
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
index f165fb0..9c5af88 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
@@ -677,6 +677,10 @@
 	case IOCTL_AFI:
 		ret = pm_ioctl_afi(arg1, arg2);
 		break;
+	case IOCTL_SET_FEATURE_CONFIG:
+	case IOCTL_GET_FEATURE_CONFIG:
+		ret = pm_feature_config(ioctl_id, arg1, arg2, value);
+		break;
 	default:
 		ret = PM_RET_ERROR_NOTSUPPORTED;
 		break;
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h
index 337f732..f18dc00 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h
@@ -15,28 +15,43 @@
 
 //ioctl id
 enum {
-	IOCTL_GET_RPU_OPER_MODE,
-	IOCTL_SET_RPU_OPER_MODE,
-	IOCTL_RPU_BOOT_ADDR_CONFIG,
-	IOCTL_TCM_COMB_CONFIG,
-	IOCTL_SET_TAPDELAY_BYPASS,
-	IOCTL_SET_SGMII_MODE,
-	IOCTL_SD_DLL_RESET,
-	IOCTL_SET_SD_TAPDELAY,
+	IOCTL_GET_RPU_OPER_MODE = 0,
+	IOCTL_SET_RPU_OPER_MODE = 1,
+	IOCTL_RPU_BOOT_ADDR_CONFIG = 2,
+	IOCTL_TCM_COMB_CONFIG = 3,
+	IOCTL_SET_TAPDELAY_BYPASS = 4,
+	IOCTL_SET_SGMII_MODE = 5,
+	IOCTL_SD_DLL_RESET = 6,
+	IOCTL_SET_SD_TAPDELAY = 7,
 	 /* Ioctl for clock driver */
-	IOCTL_SET_PLL_FRAC_MODE,
-	IOCTL_GET_PLL_FRAC_MODE,
-	IOCTL_SET_PLL_FRAC_DATA,
-	IOCTL_GET_PLL_FRAC_DATA,
-	IOCTL_WRITE_GGS,
-	IOCTL_READ_GGS,
-	IOCTL_WRITE_PGGS,
-	IOCTL_READ_PGGS,
+	IOCTL_SET_PLL_FRAC_MODE = 8,
+	IOCTL_GET_PLL_FRAC_MODE = 9,
+	IOCTL_SET_PLL_FRAC_DATA = 10,
+	IOCTL_GET_PLL_FRAC_DATA = 11,
+	IOCTL_WRITE_GGS = 12,
+	IOCTL_READ_GGS = 13,
+	IOCTL_WRITE_PGGS = 14,
+	IOCTL_READ_PGGS = 15,
 	/* IOCTL for ULPI reset */
-	IOCTL_ULPI_RESET,
+	IOCTL_ULPI_RESET = 16,
 	/* Set healthy bit value */
-	IOCTL_SET_BOOT_HEALTH_STATUS,
-	IOCTL_AFI,
+	IOCTL_SET_BOOT_HEALTH_STATUS = 17,
+	IOCTL_AFI = 18,
+	/* Probe counter read/write */
+	IOCTL_PROBE_COUNTER_READ = 19,
+	IOCTL_PROBE_COUNTER_WRITE = 20,
+	IOCTL_OSPI_MUX_SELECT = 21,
+	/* IOCTL for USB power request */
+	IOCTL_USB_SET_STATE = 22,
+	/* IOCTL to get last reset reason */
+	IOCTL_GET_LAST_RESET_REASON = 23,
+	/* AI engine NPI ISR clear */
+	IOCTL_AIE_ISR_CLEAR = 24,
+	/* Register SGI to ATF */
+	IOCTL_REGISTER_SGI = 25,
+	/* Runtime feature configuration */
+	IOCTL_SET_FEATURE_CONFIG = 26,
+	IOCTL_GET_FEATURE_CONFIG = 27,
 };
 
 //RPU operation mode
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
index 62260bc..5d9408c 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
@@ -1648,3 +1648,36 @@
 	EM_PACK_PAYLOAD1(payload, EM_SEND_ERRORS);
 	return pm_ipi_send_sync(primary_proc, payload, value, 1);
 }
+
+/**
+ * pm_feature_config() - feature configuration at runtime
+ *
+ * This function is used to send IPI request to PMUFW to configure feature
+ * at runtime. The feature can be enable or disable as well as the feature
+ * can be configure at runtime using an IOCTL call.
+ *
+ * @ioctl_id	The ioctl id for the feature configuration
+ * @config_id	The config id of the feature to be configured
+ * @value	The value to be configured
+ * @response	Return to reference pointer
+ *
+ * @return      Returns 0 on success or error value on failure
+ */
+enum pm_ret_status pm_feature_config(unsigned int ioctl_id,
+				     unsigned int config_id,
+				     unsigned int value,
+				     unsigned int *response)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD5(payload, PM_IOCTL, 0, ioctl_id, config_id, value);
+
+	if (ioctl_id == IOCTL_GET_FEATURE_CONFIG) {
+		return pm_ipi_send_sync(primary_proc, payload, response, 1);
+	} else if (ioctl_id == IOCTL_SET_FEATURE_CONFIG) {
+		return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+	} else {
+		return PM_RET_ERROR_ARGS;
+	}
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
index b0c2652..ca07cef 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
@@ -202,4 +202,9 @@
 enum pm_ret_status em_remove_action(unsigned int *value);
 enum pm_ret_status em_send_errors(unsigned int *value);
 
+enum pm_ret_status pm_feature_config(unsigned int ioctl_id,
+				     unsigned int config_id,
+				     unsigned int value,
+				     unsigned int *response);
+
 #endif /* PM_API_SYS_H */