Merge "refactor(spmd): boot interface and pass core id" into integration
diff --git a/Makefile b/Makefile
index b4bebf1..9d1e945 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
@@ -964,6 +968,9 @@
         ENABLE_FEAT_RNG \
         ENABLE_FEAT_SB \
         PSA_FWU_SUPPORT \
+        ENABLE_TRBE_FOR_NS \
+        ENABLE_SYS_REG_TRACE_FOR_NS \
+        ENABLE_TRF_FOR_NS \
 )))
 
 $(eval $(call assert_numerics,\
@@ -1064,6 +1071,9 @@
         NR_OF_FW_BANKS \
         NR_OF_IMAGES_IN_FW_BANK \
         PSA_FWU_SUPPORT \
+        ENABLE_TRBE_FOR_NS \
+        ENABLE_SYS_REG_TRACE_FOR_NS \
+        ENABLE_TRF_FOR_NS \
 )))
 
 ifeq (${SANITIZE_UB},trap)
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index 1fdf545..7819141 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -90,6 +90,18 @@
 BL31_SOURCES		+=	lib/extensions/mpam/mpam.c
 endif
 
+ifeq (${ENABLE_TRBE_FOR_NS},1)
+BL31_SOURCES		+=	lib/extensions/trbe/trbe.c
+endif
+
+ifeq (${ENABLE_SYS_REG_TRACE_FOR_NS},1)
+BL31_SOURCES		+=      lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c
+endif
+
+ifeq (${ENABLE_TRF_FOR_NS},1)
+BL31_SOURCES		+=	lib/extensions/trf/aarch64/trf.c
+endif
+
 ifeq (${WORKAROUND_CVE_2017_5715},1)
 BL31_SOURCES		+=	lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S	\
 				lib/cpus/aarch64/wa_cve_2017_5715_mmu.S
diff --git a/bl32/sp_min/sp_min.mk b/bl32/sp_min/sp_min.mk
index 8b5eddd..6339cf8 100644
--- a/bl32/sp_min/sp_min.mk
+++ b/bl32/sp_min/sp_min.mk
@@ -42,6 +42,14 @@
 				services/std_svc/trng/trng_entropy_pool.c
 endif
 
+ifeq (${ENABLE_SYS_REG_TRACE_FOR_NS},1)
+BL32_SOURCES		+=	lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c
+endif
+
+ifeq (${ENABLE_TRF_FOR_NS},1)
+BL32_SOURCES		+=	lib/extensions/trf/aarch32/trf.c
+endif
+
 BL32_LINKERFILE	:=	bl32/sp_min/sp_min.ld.S
 
 # Include the platform-specific SP_MIN Makefile
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index 07f258c..1bd4666 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -535,7 +535,10 @@
 ^^^^^^^^^^^^^^^^^
 :|M|: Saurabh Gorecha <sgorecha@codeaurora.org>
 :|G|: `sgorecha`_
-:|M|: Debasish Mandal <dmandal@codeaurora.org>
+:|M|: Lachit Patel <lpatel@codeaurora.org>
+:|G|: `lachitp`_
+:|M|: Sreevyshanavi Kare <skare@codeaurora.org>
+:|G|: `sreekare`_
 :|M|: QTI TF Maintainers <qti.trustedfirmware.maintainers@codeaurora.org>
 :|F|: docs/plat/qti.rst
 :|F|: plat/qti/
@@ -732,6 +735,7 @@
 .. _jenswi-linaro: https://github.com/jenswi-linaro
 .. _jwerner-chromium: https://github.com/jwerner-chromium
 .. _kostapr: https://github.com/kostapr
+.. _lachitp: https://github.com/lachitp
 .. _ldts: https://github.com/ldts
 .. _marex: https://github.com/marex
 .. _masahir0y: https://github.com/masahir0y
@@ -750,6 +754,7 @@
 .. _shawnguo2: https://github.com/shawnguo2
 .. _smaeul: https://github.com/smaeul
 .. _soby-mathew: https://github.com/soby-mathew
+.. _sreekare: https://github.com/sreekare
 .. _thloh85-intel: https://github.com/thloh85-intel
 .. _thomas-arm: https://github.com/thomas-arm
 .. _TonyXie06: https://github.com/TonyXie06
diff --git a/docs/components/ffa-manifest-binding.rst b/docs/components/ffa-manifest-binding.rst
index 437df67..df2985c 100644
--- a/docs/components/ffa-manifest-binding.rst
+++ b/docs/components/ffa-manifest-binding.rst
@@ -110,10 +110,13 @@
    - Specifies which messaging methods are supported by the partition, set bit
      means the feature is supported, clear bit - not supported:
 
-      - 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
+      - Bit[0]: partition can receive direct requests if set
+      - Bit[1]: partition can send direct requests if set
+      - Bit[2]: partition can send and receive indirect messages
+
+- managed-exit
+   - value type: <empty>
+   - Specifies if managed exit is supported.
 
 - has-primary-scheduler
    - value type: <empty>
diff --git a/docs/components/secure-partition-manager.rst b/docs/components/secure-partition-manager.rst
index 0b80083..fa51fe0 100644
--- a/docs/components/secure-partition-manager.rst
+++ b/docs/components/secure-partition-manager.rst
@@ -6,59 +6,59 @@
 Acronyms
 ========
 
-+--------+-----------------------------------+
-| CoT    | Chain of Trust                    |
-+--------+-----------------------------------+
-| DMA    | Direct Memory Access              |
-+--------+-----------------------------------+
-| DTB    | Device Tree Blob                  |
-+--------+-----------------------------------+
-| DTS    | Device Tree Source                |
-+--------+-----------------------------------+
-| EC     | Execution Context                 |
-+--------+-----------------------------------+
-| FIP    | Firmware Image Package            |
-+--------+-----------------------------------+
-| FF-A   | Firmware Framework for Armv8-A    |
-+--------+-----------------------------------+
-| IPA    | Intermediate Physical Address     |
-+--------+-----------------------------------+
-| NWd    | Normal World                      |
-+--------+-----------------------------------+
-| ODM    | Original Design Manufacturer      |
-+--------+-----------------------------------+
-| OEM    | Original Equipment Manufacturer   |
-+--------+-----------------------------------+
-| PA     | Physical Address                  |
-+--------+-----------------------------------+
-| PE     | Processing Element                |
-+--------+-----------------------------------+
-| PM     | Power Management                  |
-+--------+-----------------------------------+
-| PVM    | Primary VM                        |
-+--------+-----------------------------------+
-| SMMU   | System Memory Management Unit     |
-+--------+-----------------------------------+
-| SP     | Secure Partition                  |
-+--------+-----------------------------------+
-| SPD    | Secure Payload Dispatcher         |
-+--------+-----------------------------------+
-| SPM    | Secure Partition Manager          |
-+--------+-----------------------------------+
-| SPMC   | SPM Core                          |
-+--------+-----------------------------------+
-| SPMD   | SPM Dispatcher                    |
-+--------+-----------------------------------+
-| SiP    | Silicon Provider                  |
-+--------+-----------------------------------+
-| SWd    | Secure World                      |
-+--------+-----------------------------------+
-| TLV    | Tag-Length-Value                  |
-+--------+-----------------------------------+
-| TOS    | Trusted Operating System          |
-+--------+-----------------------------------+
-| VM     | Virtual Machine                   |
-+--------+-----------------------------------+
++--------+--------------------------------------+
+| CoT    | Chain of Trust                       |
++--------+--------------------------------------+
+| DMA    | Direct Memory Access                 |
++--------+--------------------------------------+
+| DTB    | Device Tree Blob                     |
++--------+--------------------------------------+
+| DTS    | Device Tree Source                   |
++--------+--------------------------------------+
+| EC     | Execution Context                    |
++--------+--------------------------------------+
+| FIP    | Firmware Image Package               |
++--------+--------------------------------------+
+| FF-A   | Firmware Framework for Arm A-profile |
++--------+--------------------------------------+
+| IPA    | Intermediate Physical Address        |
++--------+--------------------------------------+
+| NWd    | Normal World                         |
++--------+--------------------------------------+
+| ODM    | Original Design Manufacturer         |
++--------+--------------------------------------+
+| OEM    | Original Equipment Manufacturer      |
++--------+--------------------------------------+
+| PA     | Physical Address                     |
++--------+--------------------------------------+
+| PE     | Processing Element                   |
++--------+--------------------------------------+
+| PM     | Power Management                     |
++--------+--------------------------------------+
+| PVM    | Primary VM                           |
++--------+--------------------------------------+
+| SMMU   | System Memory Management Unit        |
++--------+--------------------------------------+
+| SP     | Secure Partition                     |
++--------+--------------------------------------+
+| SPD    | Secure Payload Dispatcher            |
++--------+--------------------------------------+
+| SPM    | Secure Partition Manager             |
++--------+--------------------------------------+
+| SPMC   | SPM Core                             |
++--------+--------------------------------------+
+| SPMD   | SPM Dispatcher                       |
++--------+--------------------------------------+
+| SiP    | Silicon Provider                     |
++--------+--------------------------------------+
+| SWd    | Secure World                         |
++--------+--------------------------------------+
+| TLV    | Tag-Length-Value                     |
++--------+--------------------------------------+
+| TOS    | Trusted Operating System             |
++--------+--------------------------------------+
+| VM     | Virtual Machine                      |
++--------+--------------------------------------+
 
 Foreword
 ========
@@ -924,7 +924,7 @@
 
 .. _[1]:
 
-[1] `Arm Firmware Framework for Armv8-A <https://developer.arm.com/docs/den0077/latest>`__
+[1] `Arm Firmware Framework for Arm A-profile <https://developer.arm.com/docs/den0077/latest>`__
 
 .. _[2]:
 
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 901a72a..115b2b2 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -775,6 +775,21 @@
   functions that wait for an arbitrary time length (udelay and mdelay). The
   default value is 0.
 
+- ``ENABLE_TRBE_FOR_NS``: This flag is used to enable access of trace buffer
+  control registers from NS ELs, NS-EL2 or NS-EL1(when NS-EL2 is implemented
+  but unused) when FEAT_TRBE is implemented. TRBE is an optional architectural
+  feature for AArch64. The default is 0 and it is automatically disabled when
+  the target architecture is AArch32.
+
+- ``ENABLE_SYS_REG_TRACE_FOR_NS``: Boolean option to enable trace system
+  registers access from NS ELs, NS-EL2 or NS-EL1 (when NS-EL2 is implemented
+  but unused). This feature is available if trace unit such as ETMv4.x, and
+  ETE(extending ETM feature) is implemented. This flag is disabled by default.
+
+- ``ENABLE_TRF_FOR_NS``: Boolean option to enable trace filter control registers
+  access from NS ELs, NS-EL2 or NS-EL1 (when NS-EL2 is implemented but unused),
+  if FEAT_TRF is implemented. This flag is disabled by default.
+
 GICv3 driver options
 --------------------
 
@@ -790,6 +805,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
 
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 54820e4..f4912f5 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -60,8 +60,8 @@
    FDT
       Flattened Device Tree
 
-   FFA
-      Firmware Framework for A-class processors
+   FF-A
+      Firmware Framework for Arm A-profile
 
    FIP
       Firmware Image Package
diff --git a/docs/plat/arm/arm-build-options.rst b/docs/plat/arm/arm-build-options.rst
index d4fa98d..339ebbe 100644
--- a/docs/plat/arm/arm-build-options.rst
+++ b/docs/plat/arm/arm-build-options.rst
@@ -100,12 +100,15 @@
 -  ``ARM_SPMC_MANIFEST_DTS`` : path to an alternate manifest file used as the
    SPMC Core manifest. Valid when ``SPD=spmd`` is selected.
 
+-  ``ARM_BL2_SP_LIST_DTS``: Path to DTS file snippet to override the hardcoded
+   SP nodes in tb_fw_config.
+
 -  ``OPTEE_SP_FW_CONFIG``: DTC build flag to include OP-TEE as SP in tb_fw_config
    device tree. This flag is defined only when ``ARM_SPMC_MANIFEST_DTS`` manifest
    file name contains pattern optee_sp.
 
 -  ``TS_SP_FW_CONFIG``: DTC build flag to include Trusted Services (Crypto and
-   secure-storage) as SP in tb_fw_config device tree.
+   internal-trusted-storage) as SP in tb_fw_config device tree.
 
 -  ``ARM_GPT_SUPPORT``: Enable GPT parser to get the entry address and length of
    the various partitions present in the GPT image. This support is available
diff --git a/docs/plat/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 8af27b1..b125144 100644
--- a/docs/plat/marvell/armada/build.rst
+++ b/docs/plat/marvell/armada/build.rst
@@ -153,6 +153,29 @@
 
 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.
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/qti.rst b/docs/plat/qti.rst
index 814e672..1d483e7 100644
--- a/docs/plat/qti.rst
+++ b/docs/plat/qti.rst
@@ -1,8 +1,8 @@
 Qualcomm Technologies, Inc.
 ===========================
 
-Trusted Firmware-A (TF-A) implements the EL3 firmware layer for QTI SC7180.
-
+Trusted Firmware-A (TF-A) implements the EL3 firmware layer for QTI SC7180,
+SC7280.
 
 Boot Trace
 -------------
@@ -38,4 +38,6 @@
 added to satisfy compilation.
 
 QTISELIB for SC7180 is available at
-`link <https://review.coreboot.org/cgit/qc_blobs.git/plain/sc7180/qtiseclib/libqtisec.a>`__
+`link <https://github.com/coreboot/qc_blobs/blob/master/sc7180/qtiseclib/libqtisec.a?raw=true>`__
+QTISELIB for SC7280 is available at
+`link <https://github.com/coreboot/qc_blobs/blob/master/sc7280/qtiseclib/libqtisec.a?raw=true>`__
diff --git a/docs/plat/stm32mp1.rst b/docs/plat/stm32mp1.rst
index 0ef2923..17f7a86 100644
--- a/docs/plat/stm32mp1.rst
+++ b/docs/plat/stm32mp1.rst
@@ -37,6 +37,17 @@
 for ROM code is able to load this image.
 Tool stm32image can be used to prepend this header to the generated TF-A binary.
 
+Boot with FIP
+~~~~~~~~~~~~~
+The use of FIP is now the recommended way to boot STM32MP1 platform.
+Only BL2 (with STM32 header) is loaded by ROM code. The other binaries are
+inside the FIP binary: BL32 (SP_min or OP-TEE), U-Boot and their respective
+device tree blobs.
+
+STM32IMAGE bootchain
+~~~~~~~~~~~~~~~~~~~~
+Although still supported, this way of booting is not recommended.
+Pease use FIP instead.
 At compilation step, BL2, BL32 and DTB file are linked together in a single
 binary. The stm32image tool is also generated and the header is added to TF-A
 binary. This binary file with header is named tf-a-stm32mp157c-ev1.stm32.
@@ -55,15 +66,17 @@
                |       ...       |
                |                 |
     0x2FFC0000 +-----------------+ \
-               |                 | |
+               |     BL32 DTB    | |
+    0x2FFC5000 +-----------------+ |
+               |       BL32      | |
+    0x2FFDF000 +-----------------+ |
                |       ...       | |
-               |                 | |
-    0x2FFD8000 +-----------------+ |
-               |    TF-A DTB     | | Embedded SRAM
-    0x2FFDC000 +-----------------+ |
+    0x2FFE3000 +-----------------+ |
+               |     BL2 DTB     | | Embedded SRAM
+    0x2FFEA000 +-----------------+ |
                |       BL2       | |
-    0x2FFEF000 +-----------------+ |
-               |       BL32      | |
+    0x2FFFF000 +-----------------+ |
+               |  SCMI mailbox   | |
     0x30000000 +-----------------+ /
                |                 |
                |       ...       |
@@ -102,23 +115,110 @@
 - ``STM32MP_SPI_NAND``
 - ``STM32MP_SPI_NOR``
 
-To build with SP_min and support for all bootable devices:
+Boot with FIP
+~~~~~~~~~~~~~
+You need to build BL2, BL32 (SP_min or OP-TEE) and BL33 (U-Boot) before building FIP binary.
+
+U-Boot
+______
 
 .. code:: bash
 
-    make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=sp_min STM32MP_SDMMC=1 STM32MP_EMMC=1 STM32MP_RAW_NAND=1 STM32MP_SPI_NAND=1
-    STM32MP_SPI_NOR=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb
     cd <u-boot_directory>
     make stm32mp15_trusted_defconfig
     make DEVICE_TREE=stm32mp157c-ev1 all
 
-To build TF-A with OP-TEE support for all bootable devices:
+OP-TEE (optional)
+_________________
 
 .. code:: bash
 
-    make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 AARCH32_SP=optee STM32MP_SDMMC=1 STM32MP_EMMC=1 STM32MP_RAW_NAND=1 STM32MP_SPI_NAND=1 STM32MP_SPI_NOR=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb
     cd <optee_directory>
-    make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm PLATFORM=stm32mp1 CFG_EMBED_DTB_SOURCE_FILE=stm32mp157c-ev1.dts
+    make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm PLATFORM=stm32mp1 \
+        CFG_EMBED_DTB_SOURCE_FILE=stm32mp157c-ev1.dts
+
+
+TF-A BL32 (SP_min)
+__________________
+If you choose not to use OP-TEE, you can use TF-A SP_min.
+To build TF-A BL32, and its device tree file:
+
+.. code:: bash
+
+    make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \
+        AARCH32_SP=sp_min DTB_FILE_NAME=stm32mp157c-ev1.dtb bl32 dtbs
+
+TF-A BL2
+________
+To build TF-A BL2 with its STM32 header for SD-card boot:
+
+.. code:: bash
+
+    make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \
+        DTB_FILE_NAME=stm32mp157c-ev1.dtb STM32MP_SDMMC=1
+
+For other boot devices, you have to replace STM32MP_SDMMC in the previous command
+with the desired device flag.
+
+This BL2 is independent of the BL32 used (SP_min or OP-TEE)
+
+
+FIP
+___
+With BL32 SP_min:
+
+.. code:: bash
+
+    make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \
+        AARCH32_SP=sp_min \
+        DTB_FILE_NAME=stm32mp157c-ev1.dtb \
+        BL33=<u-boot_directory>/u-boot-nodtb.bin \
+        BL33_CFG=<u-boot_directory>/u-boot.dtb \
+        fip
+
+With OP-TEE:
+
+.. code:: bash
+
+    make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \
+        DTB_FILE_NAME=stm32mp157c-ev1.dtb \
+        BL33=<u-boot_directory>/u-boot-nodtb.bin \
+        BL33_CFG=<u-boot_directory>/u-boot.dtb \
+        BL32=<optee_directory>/tee-header_v2.bin \
+        BL32_EXTRA1=<optee_directory>/tee-pager_v2.bin
+        BL32_EXTRA2=<optee_directory>/tee-pageable_v2.bin
+        fip
+
+
+STM32IMAGE bootchain
+~~~~~~~~~~~~~~~~~~~~
+You need to add the following flag to the make command:
+``STM32MP_USE_STM32IMAGE=1``
+
+To build with SP_min and support for SD-card boot:
+
+.. code:: bash
+
+    make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \
+        AARCH32_SP=sp_min STM32MP_SDMMC=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb \
+        STM32MP_USE_STM32IMAGE=1
+
+    cd <u-boot_directory>
+    make stm32mp15_trusted_defconfig
+    make DEVICE_TREE=stm32mp157c-ev1 all
+
+To build TF-A with OP-TEE support for SD-card boot:
+
+.. code:: bash
+
+    make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \
+        AARCH32_SP=optee STM32MP_SDMMC=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb \
+        STM32MP_USE_STM32IMAGE=1
+
+    cd <optee_directory>
+    make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm PLATFORM=stm32mp1 \
+        CFG_EMBED_DTB_SOURCE_FILE=stm32mp157c-ev1.dts
+
     cd <u-boot_directory>
     make stm32mp15_trusted_defconfig
     make DEVICE_TREE=stm32mp157c-ev1 all
@@ -132,7 +232,19 @@
 Populate SD-card
 ----------------
 
+Boot with FIP
+~~~~~~~~~~~~~
+The SD-card has to be formatted with GPT.
+It should contain at least those partitions:
+
+- fsbl: to copy the tf-a-stm32mp157c-ev1.stm32 binary (BL2)
+- fip: which contains the FIP binary
+
+Usually, two copies of fsbl are used (fsbl1 and fsbl2) instead of one partition fsbl.
+
-The SD-card has to be formated with GPT.
+STM32IMAGE bootchain
+~~~~~~~~~~~~~~~~~~~~
+The SD-card has to be formatted with GPT.
 It should contain at least those partitions:
 
 - fsbl: to copy the tf-a-stm32mp157c-ev1.stm32 binary
diff --git a/docs/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/threat_model/threat_model_spm.rst b/docs/threat_model/threat_model_spm.rst
index 96d33a2..82f9916 100644
--- a/docs/threat_model/threat_model_spm.rst
+++ b/docs/threat_model/threat_model_spm.rst
@@ -8,7 +8,7 @@
 (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.
+Arm A-profile`_ specification.
 
 In brief, the broad FF-A specification and S-EL2 firmware implementation
 provide:
@@ -611,7 +611,7 @@
 
 *Copyright (c) 2021, Arm Limited. All rights reserved.*
 
-.. _Arm Firmware Framework for Armv8-A: https://developer.arm.com/docs/den0077/latest
+.. _Arm Firmware Framework for Arm A-profile: https://developer.arm.com/docs/den0077/latest
 .. _Secure Partition Manager: ../components/secure-partition-manager.html
 .. _Generic TF-A threat model: ./threat_model.html#threat-analysis
 .. _FF-A ACS: https://github.com/ARM-software/ff-a-acs/releases
diff --git a/drivers/arm/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..e4fc8c9 100644
--- a/drivers/arm/tzc/tzc400.c
+++ b/drivers/arm/tzc/tzc400.c
@@ -68,6 +68,7 @@
 DEFINE_TZC_COMMON_WRITE_REGION_TOP(400, 400)
 DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(400, 400)
 DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(400, 400)
+DEFINE_TZC_COMMON_UPDATE_FILTERS(400, 400)
 DEFINE_TZC_COMMON_CONFIGURE_REGION0(400)
 DEFINE_TZC_COMMON_CONFIGURE_REGION(400)
 
@@ -271,6 +272,15 @@
 						sec_attr, nsaid_permissions);
 }
 
+void tzc400_update_filters(unsigned int region, unsigned int filters)
+{
+	/* Do range checks on filters and regions. */
+	assert(((filters >> tzc400.num_filters) == 0U) &&
+	       (region < tzc400.num_regions));
+
+	_tzc400_update_filters(tzc400.base, region, tzc400.num_filters, filters);
+}
+
 void tzc400_enable_filters(void)
 {
 	unsigned int state;
@@ -281,6 +291,11 @@
 	for (filter = 0U; filter < tzc400.num_filters; filter++) {
 		state = _tzc400_get_gate_keeper(tzc400.base, filter);
 		if (state != 0U) {
+			/* Filter 0 is special and cannot be disabled.
+			 * So here we allow it being already enabled. */
+			if (filter == 0U) {
+				continue;
+			}
 			/*
 			 * The TZC filter is already configured. Changing the
 			 * programmer's view in an active system can cause
@@ -302,14 +317,17 @@
 void tzc400_disable_filters(void)
 {
 	unsigned int filter;
+	unsigned int state;
+	unsigned int start = 0U;
 
 	assert(tzc400.base != 0U);
 
-	/*
-	 * We don't do the same state check as above as the Gatekeepers are
-	 * disabled after reset.
-	 */
-	for (filter = 0; filter < tzc400.num_filters; filter++)
+	/* Filter 0 is special and cannot be disabled. */
+	state = _tzc400_get_gate_keeper(tzc400.base, 0);
+	if (state != 0U) {
+		start++;
+	}
+	for (filter = start; filter < tzc400.num_filters; filter++)
 		_tzc400_set_gate_keeper(tzc400.base, filter, 0);
 }
 
diff --git a/drivers/arm/tzc/tzc_common_private.h b/drivers/arm/tzc/tzc_common_private.h
index 1d99077..2090944 100644
--- a/drivers/arm/tzc/tzc_common_private.h
+++ b/drivers/arm/tzc/tzc_common_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -90,6 +90,27 @@
 	}
 
 /*
+ * It is used to modify the filters status for a defined region.
+ */
+#define DEFINE_TZC_COMMON_UPDATE_FILTERS(fn_name, macro_name)		\
+	static inline void _tzc##fn_name##_update_filters(		\
+						uintptr_t base,		\
+						unsigned int region_no,	\
+						unsigned int nbfilters, \
+						unsigned int filters)	\
+	{								\
+		uint32_t filters_mask = GENMASK(nbfilters - 1U, 0);	\
+									\
+		mmio_clrsetbits_32(base +				\
+			TZC_REGION_OFFSET(				\
+				TZC_##macro_name##_REGION_SIZE,		\
+				region_no) +				\
+			TZC_##macro_name##_REGION_ATTR_0_OFFSET,	\
+			filters_mask << TZC_REGION_ATTR_F_EN_SHIFT,	\
+			filters << TZC_REGION_ATTR_F_EN_SHIFT);		\
+	}
+
+/*
  * It is used to program region 0 ATTRIBUTES and ACCESS register.
  */
 #define DEFINE_TZC_COMMON_CONFIGURE_REGION0(fn_name)			\
diff --git a/drivers/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/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/include/arch/aarch32/arch.h b/include/arch/aarch32/arch.h
index 54ec009..7221b62 100644
--- a/include/arch/aarch32/arch.h
+++ b/include/arch/aarch32/arch.h
@@ -102,6 +102,16 @@
 /* CSSELR definitions */
 #define LEVEL_SHIFT		U(1)
 
+/* ID_DFR0_EL1 definitions */
+#define ID_DFR0_COPTRC_SHIFT		U(12)
+#define ID_DFR0_COPTRC_MASK		U(0xf)
+#define ID_DFR0_COPTRC_SUPPORTED	U(1)
+#define ID_DFR0_COPTRC_LENGTH		U(4)
+#define ID_DFR0_TRACEFILT_SHIFT		U(28)
+#define ID_DFR0_TRACEFILT_MASK		U(0xf)
+#define ID_DFR0_TRACEFILT_SUPPORTED	U(1)
+#define ID_DFR0_TRACEFILT_LENGTH	U(4)
+
 /* ID_DFR1_EL1 definitions */
 #define ID_DFR1_MTPMU_SHIFT	U(0)
 #define ID_DFR1_MTPMU_MASK	U(0xf)
@@ -173,6 +183,7 @@
 #define SDCR_SPD_DISABLE	U(0x2)
 #define SDCR_SPD_ENABLE		U(0x3)
 #define SDCR_SCCD_BIT		(U(1) << 23)
+#define SDCR_TTRF_BIT		(U(1) << 19)
 #define SDCR_SPME_BIT		(U(1) << 17)
 #define SDCR_RESET_VAL		U(0x0)
 #define SDCR_MTPME_BIT		(U(1) << 28)
@@ -516,6 +527,7 @@
 #define CTR		p15, 0, c0, c0, 1
 #define CNTFRQ		p15, 0, c14, c0, 0
 #define ID_MMFR4	p15, 0, c0, c2, 6
+#define ID_DFR0		p15, 0, c0, c1, 2
 #define ID_DFR1		p15, 0, c0, c3, 5
 #define ID_PFR0		p15, 0, c0, c1, 0
 #define ID_PFR1		p15, 0, c0, c1, 1
diff --git a/include/arch/aarch32/arch_helpers.h b/include/arch/aarch32/arch_helpers.h
index 726baf5..0330989 100644
--- a/include/arch/aarch32/arch_helpers.h
+++ b/include/arch/aarch32/arch_helpers.h
@@ -217,6 +217,7 @@
 DEFINE_COPROCR_READ_FUNC(mpidr, MPIDR)
 DEFINE_COPROCR_READ_FUNC(midr, MIDR)
 DEFINE_COPROCR_READ_FUNC(id_mmfr4, ID_MMFR4)
+DEFINE_COPROCR_READ_FUNC(id_dfr0, ID_DFR0)
 DEFINE_COPROCR_READ_FUNC(id_pfr0, ID_PFR0)
 DEFINE_COPROCR_READ_FUNC(id_pfr1, ID_PFR1)
 DEFINE_COPROCR_READ_FUNC(isr, ISR)
@@ -282,6 +283,7 @@
 DEFINE_COPROCR_RW_FUNCS_64(icc_sgi0r_el1, ICC_SGI0R_EL1_64)
 DEFINE_COPROCR_WRITE_FUNC_64(icc_sgi1r, ICC_SGI1R_EL1_64)
 
+DEFINE_COPROCR_RW_FUNCS(sdcr, SDCR)
 DEFINE_COPROCR_RW_FUNCS(hdcr, HDCR)
 DEFINE_COPROCR_RW_FUNCS(cnthp_ctl, CNTHP_CTL)
 DEFINE_COPROCR_READ_FUNC(pmcr, PMCR)
diff --git a/include/arch/aarch32/el3_common_macros.S b/include/arch/aarch32/el3_common_macros.S
index 7fff4c7..65f9a8e 100644
--- a/include/arch/aarch32/el3_common_macros.S
+++ b/include/arch/aarch32/el3_common_macros.S
@@ -63,11 +63,23 @@
 	 *  cp11 field is ignored, but is set to same value as cp10. The cp10
 	 *  field is set to allow access to Advanced SIMD and floating point
 	 *  features from both Security states.
+	 *
+	 * NSACR.NSTRCDIS: When system register trace implemented, Set to one
+	 *  so that NS System register accesses to all implemented trace
+	 *  registers are disabled.
+	 *  When system register trace is not implemented, this bit is RES0 and
+	 *  hence set to zero.
 	 * ---------------------------------------------------------------------
 	 */
 	ldcopr	r0, NSACR
 	and	r0, r0, #NSACR_IMP_DEF_MASK
 	orr	r0, r0, #(NSACR_RESET_VAL | NSACR_ENABLE_FP_ACCESS)
+	ldcopr	r1, ID_DFR0
+	ubfx	r1, r1, #ID_DFR0_COPTRC_SHIFT, #ID_DFR0_COPTRC_LENGTH
+	cmp	r1, #ID_DFR0_COPTRC_SUPPORTED
+	bne	1f
+	orr	r0, r0, #NSTRCDIS_BIT
+1:
 	stcopr	r0, NSACR
 	isb
 
@@ -119,9 +131,22 @@
 	 *  in Secure state. This bit is RES0 in versions of the architecture
 	 *  earlier than ARMv8.5, setting it to 1 doesn't have any effect on
 	 *  them.
+	 *
+	 * SDCR.TTRF: Set to one so that access to trace filter control
+	 *  registers in non-monitor mode generate Monitor trap exception,
+	 *  unless the access generates a higher priority exception when
+	 *  trace filter control(FEAT_TRF) is implemented.
+	 *  When FEAT_TRF is not implemented, this bit is RES0.
 	 * ---------------------------------------------------------------------
 	 */
-	ldr	r0, =(SDCR_RESET_VAL | SDCR_SPD(SDCR_SPD_DISABLE) | SDCR_SCCD_BIT)
+	ldr	r0, =((SDCR_RESET_VAL | SDCR_SPD(SDCR_SPD_DISABLE) | \
+		      SDCR_SCCD_BIT) & ~SDCR_TTRF_BIT)
+	ldcopr	r1, ID_DFR0
+	ubfx	r1, r1, #ID_DFR0_TRACEFILT_SHIFT, #ID_DFR0_TRACEFILT_LENGTH
+	cmp	r1, #ID_DFR0_TRACEFILT_SUPPORTED
+	bne	1f
+	orr	r0, r0, #SDCR_TTRF_BIT
+1:
 	stcopr	r0, SDCR
 
 	/* ---------------------------------------------------------------------
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index c12dbc4..9ea1114 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -188,10 +188,25 @@
 #define EL_IMPL_A64ONLY		ULL(1)
 #define EL_IMPL_A64_A32		ULL(2)
 
+/* ID_AA64DFR0_EL1.TraceVer definitions */
+#define ID_AA64DFR0_TRACEVER_SHIFT	U(4)
+#define ID_AA64DFR0_TRACEVER_MASK	ULL(0xf)
+#define ID_AA64DFR0_TRACEVER_SUPPORTED	ULL(1)
+#define ID_AA64DFR0_TRACEVER_LENGTH	U(4)
+#define ID_AA64DFR0_TRACEFILT_SHIFT	U(40)
+#define ID_AA64DFR0_TRACEFILT_MASK	U(0xf)
+#define ID_AA64DFR0_TRACEFILT_SUPPORTED	U(1)
+#define ID_AA64DFR0_TRACEFILT_LENGTH	U(4)
+
 /* ID_AA64DFR0_EL1.PMS definitions (for ARMv8.2+) */
 #define ID_AA64DFR0_PMS_SHIFT	U(32)
 #define ID_AA64DFR0_PMS_MASK	ULL(0xf)
 
+/* ID_AA64DFR0_EL1.TraceBuffer definitions */
+#define ID_AA64DFR0_TRACEBUFFER_SHIFT		U(44)
+#define ID_AA64DFR0_TRACEBUFFER_MASK		ULL(0xf)
+#define ID_AA64DFR0_TRACEBUFFER_SUPPORTED	ULL(1)
+
 /* ID_AA64DFR0_EL1.MTPMU definitions (for ARMv8.6+) */
 #define ID_AA64DFR0_MTPMU_SHIFT		U(48)
 #define ID_AA64DFR0_MTPMU_MASK		ULL(0xf)
@@ -442,6 +457,9 @@
 #define MDCR_EnPMSN_BIT		(ULL(1) << 36)
 #define MDCR_MPMX_BIT		(ULL(1) << 35)
 #define MDCR_MCCD_BIT		(ULL(1) << 34)
+#define MDCR_NSTB(x)		((x) << 24)
+#define MDCR_NSTB_EL1		ULL(0x3)
+#define MDCR_NSTBE		(ULL(1) << 26)
 #define MDCR_MTPME_BIT		(ULL(1) << 28)
 #define MDCR_TDCC_BIT		(ULL(1) << 27)
 #define MDCR_SCCD_BIT		(ULL(1) << 23)
@@ -465,6 +483,8 @@
 /* MDCR_EL2 definitions */
 #define MDCR_EL2_MTPME		(U(1) << 28)
 #define MDCR_EL2_HLP		(U(1) << 26)
+#define MDCR_EL2_E2TB(x)	((x) << 24)
+#define MDCR_EL2_E2TB_EL1	U(0x3)
 #define MDCR_EL2_HCCD		(U(1) << 23)
 #define MDCR_EL2_TTRF		(U(1) << 19)
 #define MDCR_EL2_HPMD		(U(1) << 17)
diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S
index 9734335..d496584 100644
--- a/include/arch/aarch64/el3_common_macros.S
+++ b/include/arch/aarch64/el3_common_macros.S
@@ -126,13 +126,31 @@
 	 *  Debug is not implemented this bit does not have any effect on the
 	 *  counters unless there is support for the implementation defined
 	 *  authentication interface ExternalSecureNoninvasiveDebugEnabled().
+	 *
+	 * MDCR_EL3.NSTB, MDCR_EL3.NSTBE: Set to zero so that Trace Buffer
+	 *  owning security state is Secure state. If FEAT_TRBE is implemented,
+	 *  accesses to Trace Buffer control registers at EL2 and EL1 in any
+	 *  security state generates trap exceptions to EL3.
+	 *  If FEAT_TRBE is not implemented, these bits are RES0.
+	 *
+	 * MDCR_EL3.TTRF: Set to one so that access to trace filter control
+	 *  registers in non-monitor mode generate EL3 trap exception,
+	 *  unless the access generates a higher priority exception when trace
+	 *  filter control(FEAT_TRF) is implemented.
+	 *  When FEAT_TRF is not implemented, this bit is RES0.
 	 * ---------------------------------------------------------------------
 	 */
 	mov_imm	x0, ((MDCR_EL3_RESET_VAL | MDCR_SDD_BIT | \
 		      MDCR_SPD32(MDCR_SPD32_DISABLE) | MDCR_SCCD_BIT | \
 		      MDCR_MCCD_BIT) & ~(MDCR_SPME_BIT | MDCR_TDOSA_BIT | \
-		      MDCR_TDA_BIT | MDCR_TPM_BIT))
+		      MDCR_TDA_BIT | MDCR_TPM_BIT | MDCR_NSTB(MDCR_NSTB_EL1) | \
+		      MDCR_NSTBE | MDCR_TTRF_BIT))
 
+	mrs	x1, id_aa64dfr0_el1
+	ubfx	x1, x1, #ID_AA64DFR0_TRACEFILT_SHIFT, #ID_AA64DFR0_TRACEFILT_LENGTH
+	cbz	x1, 1f
+	orr	x0, x0, #MDCR_TTRF_BIT
+1:
 	msr	mdcr_el3, x0
 
 	/* ---------------------------------------------------------------------
@@ -179,6 +197,12 @@
 	 * CPTR_EL3.TCPAC: Set to zero so that any accesses to CPACR_EL1,
 	 *  CPTR_EL2, CPACR, or HCPTR do not trap to EL3.
 	 *
+	 * CPTR_EL3.TTA: Set to one so that accesses to the trace system
+	 *  registers trap to EL3 from all exception levels and security
+	 *  states when system register trace is implemented.
+	 *  When system register trace is not implemented, this bit is RES0 and
+	 *  hence set to zero.
+	 *
 	 * CPTR_EL3.TTA: Set to zero so that System register accesses to the
 	 *  trace registers do not trap to EL3.
 	 *
@@ -194,6 +218,11 @@
 	 */
 
 	mov_imm x0, (CPTR_EL3_RESET_VAL & ~(TCPAC_BIT | TTA_BIT | TFP_BIT))
+	mrs	x1, id_aa64dfr0_el1
+	ubfx	x1, x1, #ID_AA64DFR0_TRACEVER_SHIFT, #ID_AA64DFR0_TRACEVER_LENGTH
+	cbz	x1, 1f
+	orr	x0, x0, #TTA_BIT
+1:
 	msr	cptr_el3, x0
 
 	/*
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/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/lib/extensions/sys_reg_trace.h b/include/lib/extensions/sys_reg_trace.h
new file mode 100644
index 0000000..74470fe
--- /dev/null
+++ b/include/lib/extensions/sys_reg_trace.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SYS_REG_TRACE_H
+#define SYS_REG_TRACE_H
+
+#include <context.h>
+
+#if __aarch64__
+void sys_reg_trace_enable(cpu_context_t *context);
+#else
+void sys_reg_trace_enable(void);
+#endif /* __aarch64__ */
+
+#endif /* SYS_REG_TRACE_H */
diff --git a/include/lib/extensions/trbe.h b/include/lib/extensions/trbe.h
new file mode 100644
index 0000000..1753ab6
--- /dev/null
+++ b/include/lib/extensions/trbe.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TRBE_H
+#define TRBE_H
+
+void trbe_enable(void);
+
+#endif /* TRBE_H */
diff --git a/include/lib/extensions/trf.h b/include/lib/extensions/trf.h
new file mode 100644
index 0000000..18f17f3
--- /dev/null
+++ b/include/lib/extensions/trf.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TRF_H
+#define TRF_H
+
+void trf_enable(void);
+
+#endif /* TRF_H */
diff --git a/include/lib/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/lib/el3_runtime/aarch32/context_mgmt.c b/lib/el3_runtime/aarch32/context_mgmt.c
index 81d793b..3ef378c 100644
--- a/lib/el3_runtime/aarch32/context_mgmt.c
+++ b/lib/el3_runtime/aarch32/context_mgmt.c
@@ -16,6 +16,8 @@
 #include <context.h>
 #include <lib/el3_runtime/context_mgmt.h>
 #include <lib/extensions/amu.h>
+#include <lib/extensions/sys_reg_trace.h>
+#include <lib/extensions/trf.h>
 #include <lib/utils.h>
 
 /*******************************************************************************
@@ -136,6 +138,14 @@
 #if ENABLE_AMU
 	amu_enable(el2_unused);
 #endif
+
+#if ENABLE_SYS_REG_TRACE_FOR_NS
+	sys_reg_trace_enable();
+#endif /* ENABLE_SYS_REG_TRACE_FOR_NS */
+
+#if ENABLE_TRF_FOR_NS
+	trf_enable();
+#endif /* ENABLE_TRF_FOR_NS */
 #endif
 }
 
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 7c6f953..52102dd 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -22,6 +22,9 @@
 #include <lib/extensions/mpam.h>
 #include <lib/extensions/spe.h>
 #include <lib/extensions/sve.h>
+#include <lib/extensions/sys_reg_trace.h>
+#include <lib/extensions/trbe.h>
+#include <lib/extensions/trf.h>
 #include <lib/extensions/twed.h>
 #include <lib/utils.h>
 
@@ -348,6 +351,19 @@
 #if ENABLE_MPAM_FOR_LOWER_ELS
 	mpam_enable(el2_unused);
 #endif
+
+#if ENABLE_TRBE_FOR_NS
+	trbe_enable();
+#endif /* ENABLE_TRBE_FOR_NS */
+
+#if ENABLE_SYS_REG_TRACE_FOR_NS
+	sys_reg_trace_enable(ctx);
+#endif /* ENABLE_SYS_REG_TRACE_FOR_NS */
+
+#if ENABLE_TRF_FOR_NS
+	trf_enable();
+#endif /* ENABLE_TRF_FOR_NS */
+
 #endif
 }
 
@@ -457,6 +473,8 @@
 			 * CPTR_EL2.TTA: Set to zero so that Non-secure System
 			 *  register accesses to the trace registers from both
 			 *  Execution states do not trap to EL2.
+			 *  If PE trace unit System registers are not implemented
+			 *  then this bit is reserved, and must be set to zero.
 			 *
 			 * CPTR_EL2.TFP: Set to zero so that Non-secure accesses
 			 *  to SIMD and floating-point functionality from both
@@ -565,6 +583,11 @@
 			 *
 			 * MDCR_EL2.HPMN: Set to value of PMCR_EL0.N which is the
 			 *  architecturally-defined reset value.
+			 *
+			 * MDCR_EL2.E2TB: Set to zero so that the trace Buffer
+			 *  owning exception level is NS-EL1 and, tracing is
+			 *  prohibited at NS-EL2. These bits are RES0 when
+			 *  FEAT_TRBE is not implemented.
 			 */
 			mdcr_el2 = ((MDCR_EL2_RESET_VAL | MDCR_EL2_HLP |
 				     MDCR_EL2_HPMD) |
@@ -574,7 +597,8 @@
 				     MDCR_EL2_TDRA_BIT | MDCR_EL2_TDOSA_BIT |
 				     MDCR_EL2_TDA_BIT | MDCR_EL2_TDE_BIT |
 				     MDCR_EL2_HPME_BIT | MDCR_EL2_TPM_BIT |
-				     MDCR_EL2_TPMCR_BIT);
+				     MDCR_EL2_TPMCR_BIT |
+				     MDCR_EL2_E2TB(MDCR_EL2_E2TB_EL1));
 
 			write_mdcr_el2(mdcr_el2);
 
diff --git a/lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c b/lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c
new file mode 100644
index 0000000..89b8029
--- /dev/null
+++ b/lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <lib/extensions/sys_reg_trace.h>
+
+static bool sys_reg_trace_supported(void)
+{
+	uint32_t features;
+
+	features = read_id_dfr0() >> ID_DFR0_COPTRC_SHIFT;
+	return ((features & ID_DFR0_COPTRC_MASK) ==
+		ID_DFR0_COPTRC_SUPPORTED);
+}
+
+void sys_reg_trace_enable(void)
+{
+	uint32_t val;
+
+	if (sys_reg_trace_supported()) {
+		/*
+		 * NSACR.NSTRCDIS = b0
+		 * enable NS system register access to implemented trace
+		 * registers.
+		 */
+		val = read_nsacr();
+		val &= ~NSTRCDIS_BIT;
+		write_nsacr(val);
+	}
+}
diff --git a/lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c b/lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c
new file mode 100644
index 0000000..960d698
--- /dev/null
+++ b/lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <lib/extensions/sys_reg_trace.h>
+
+static bool sys_reg_trace_supported(void)
+{
+	uint64_t features;
+
+	features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEVER_SHIFT;
+	return ((features & ID_AA64DFR0_TRACEVER_MASK) ==
+		ID_AA64DFR0_TRACEVER_SUPPORTED);
+}
+
+void sys_reg_trace_enable(cpu_context_t *ctx)
+{
+	uint64_t val;
+
+	if (sys_reg_trace_supported()) {
+		/* Retrieve CPTR_EL3 value from the given context 'ctx',
+		 * and update CPTR_EL3.TTA bit to 0.
+		 * This function is called while switching context to NS to
+		 * allow system trace register access to NS-EL2 and NS-EL1
+		 * when NS-EL2 is implemented but not used.
+		 */
+		val = read_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3);
+		val &= ~TTA_BIT;
+		write_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3, val);
+	}
+}
diff --git a/lib/extensions/trbe/trbe.c b/lib/extensions/trbe/trbe.c
new file mode 100644
index 0000000..9f754d5
--- /dev/null
+++ b/lib/extensions/trbe/trbe.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <lib/el3_runtime/pubsub.h>
+#include <lib/extensions/trbe.h>
+
+static void tsb_csync(void)
+{
+	/*
+	 * The assembler does not yet understand the tsb csync mnemonic
+	 * so use the equivalent hint instruction.
+	 */
+	__asm__ volatile("hint #18");
+}
+
+static bool trbe_supported(void)
+{
+	uint64_t features;
+
+	features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEBUFFER_SHIFT;
+	return ((features & ID_AA64DFR0_TRACEBUFFER_MASK) ==
+		ID_AA64DFR0_TRACEBUFFER_SUPPORTED);
+}
+
+void trbe_enable(void)
+{
+	uint64_t val;
+
+	if (trbe_supported()) {
+		/*
+		 * MDCR_EL3.NSTB = 0b11
+		 * Allow access of trace buffer control registers from NS-EL1
+		 * and NS-EL2, tracing is prohibited in Secure and Realm state
+		 * (if implemented).
+		 */
+		val = read_mdcr_el3();
+		val |= MDCR_NSTB(MDCR_NSTB_EL1);
+		write_mdcr_el3(val);
+	}
+}
+
+static void *trbe_drain_trace_buffers_hook(const void *arg __unused)
+{
+	if (trbe_supported()) {
+		/*
+		 * Before switching from normal world to secure world
+		 * the trace buffers need to be drained out to memory. This is
+		 * required to avoid an invalid memory access when TTBR is switched
+		 * for entry to S-EL1.
+		 */
+		tsb_csync();
+		dsbnsh();
+	}
+
+	return (void *)0;
+}
+
+SUBSCRIBE_TO_EVENT(cm_entering_secure_world, trbe_drain_trace_buffers_hook);
diff --git a/lib/extensions/trf/aarch32/trf.c b/lib/extensions/trf/aarch32/trf.c
new file mode 100644
index 0000000..834092d
--- /dev/null
+++ b/lib/extensions/trf/aarch32/trf.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <lib/extensions/trf.h>
+
+static bool trf_supported(void)
+{
+	uint32_t features;
+
+	features = read_id_dfr0() >> ID_DFR0_TRACEFILT_SHIFT;
+	return ((features & ID_DFR0_TRACEFILT_MASK) ==
+		ID_DFR0_TRACEFILT_SUPPORTED);
+}
+
+void trf_enable(void)
+{
+	uint32_t val;
+
+	if (trf_supported()) {
+		/*
+		 * Allow access of trace filter control registers from
+		 * non-monitor mode
+		 */
+		val = read_sdcr();
+		val &= ~SDCR_TTRF_BIT;
+		write_sdcr(val);
+	}
+}
diff --git a/lib/extensions/trf/aarch64/trf.c b/lib/extensions/trf/aarch64/trf.c
new file mode 100644
index 0000000..1da5dce
--- /dev/null
+++ b/lib/extensions/trf/aarch64/trf.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <lib/extensions/trf.h>
+
+static bool trf_supported(void)
+{
+	uint64_t features;
+
+	features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEFILT_SHIFT;
+	return ((features & ID_AA64DFR0_TRACEFILT_MASK) ==
+		ID_AA64DFR0_TRACEFILT_SUPPORTED);
+}
+
+void trf_enable(void)
+{
+	uint64_t val;
+
+	if (trf_supported()) {
+		/*
+		 * MDCR_EL3.TTRF = b0
+		 * Allow access of trace filter control registers from NS-EL2
+		 * and NS-EL1 when NS-EL2 is implemented but not used
+		 */
+		val = read_mdcr_el3();
+		val &= ~MDCR_TTRF_BIT;
+		write_mdcr_el3(val);
+	}
+}
diff --git a/lib/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/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 72f84b5..c188621 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -355,3 +355,24 @@
 
 # Disable Firmware update support by default
 PSA_FWU_SUPPORT			:= 0
+
+# By default, disable access of trace buffer control registers from NS
+# lower ELs  i.e. NS-EL2, or NS-EL1 if NS-EL2 implemented but unused
+# if FEAT_TRBE is implemented.
+# Note FEAT_TRBE is only supported on AArch64 - therefore do not enable in
+# AArch32.
+ifneq (${ARCH},aarch32)
+    ENABLE_TRBE_FOR_NS		:= 0
+else
+    override ENABLE_TRBE_FOR_NS	:= 0
+endif
+
+# By default, disable access of trace system registers from NS lower
+# ELs  i.e. NS-EL2, or NS-EL1 if NS-EL2 implemented but unused if
+# system register trace is implemented.
+ENABLE_SYS_REG_TRACE_FOR_NS	:= 0
+
+# By default, disable trace filter control registers access to NS
+# lower ELs, i.e. NS-EL2, or NS-EL1 if NS-EL2 implemented but unused
+# if FEAT_TRF is implemented.
+ENABLE_TRF_FOR_NS		:= 0
diff --git a/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 f80ea2f..baffbcf 100644
--- a/plat/arm/board/arm_fpga/platform.mk
+++ b/plat/arm/board/arm_fpga/platform.mk
@@ -89,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/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/platform.mk b/plat/arm/board/fvp/platform.mk
index 3c70eed..2f8a65e 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -378,3 +378,12 @@
 # dynamically if TRUSTED_BOARD_BOOT is set.
 DYN_DISABLE_AUTH	:=	1
 endif
+
+# enable trace buffer control registers access to NS by default
+ENABLE_TRBE_FOR_NS		:= 1
+
+# enable trace system registers access to NS by default
+ENABLE_SYS_REG_TRACE_FOR_NS	:= 1
+
+# enable trace filter control registers access to NS by default
+ENABLE_TRF_FOR_NS		:= 1
diff --git a/plat/arm/board/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/tc/fdts/tc_fw_config.dts b/plat/arm/board/tc/fdts/tc_fw_config.dts
index 4b6abd4..a84c7f8 100644
--- a/plat/arm/board/tc/fdts/tc_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/tc/fdts/tc_spmc_optee_sp_manifest.dts b/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts
index 34b4e74..92e2ddd 100644
--- a/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts
+++ b/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts
@@ -36,7 +36,7 @@
 #ifdef TS_SP_FW_CONFIG
 		vm2 {
 			is_ffa_partition;
-			debug_name = "secure-storage";
+			debug_name = "internal-trusted-storage";
 			load_address = <0xfee00000>;
 			vcpu_count = <1>;
 			mem_size = <2097152>; /* 2MB TZC DRAM */
diff --git a/plat/arm/board/tc/fdts/tc_tb_fw_config.dts b/plat/arm/board/tc/fdts/tc_tb_fw_config.dts
index 28ed7ae..af80550 100644
--- a/plat/arm/board/tc/fdts/tc_tb_fw_config.dts
+++ b/plat/arm/board/tc/fdts/tc_tb_fw_config.dts
@@ -4,6 +4,8 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <lib/libc/cdefs.h>
+
 /dts-v1/;
 
 / {
@@ -27,8 +29,11 @@
 
 	secure-partitions {
 		compatible = "arm,sp";
+#ifdef ARM_BL2_SP_LIST_DTS
+	#include __XSTRING(ARM_BL2_SP_LIST_DTS)
+#else
 #ifdef TS_SP_FW_CONFIG
-		secure-storage {
+		internal-trusted-storage {
 		       uuid = "dc1eef48-b17a-4ccf-ac8b-dfcff7711b14";
 		       load-address = <0xfee00000>;
 		};
@@ -60,5 +65,6 @@
 			load-address = <0xfe200000>;
 		};
 #endif
+#endif /* ARM_BL2_SP_LIST_DTS */
 	};
 };
diff --git a/plat/arm/board/tc/include/platform_def.h b/plat/arm/board/tc/include/platform_def.h
index c8edd2f..ccabced 100644
--- a/plat/arm/board/tc/include/platform_def.h
+++ b/plat/arm/board/tc/include/platform_def.h
@@ -55,6 +55,14 @@
 						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 tc. With SPMD enabled this value corresponds to
  * max size of BL32 image.
@@ -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
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
index 8db764c..7ebf639 100644
--- a/plat/arm/board/tc/platform.mk
+++ b/plat/arm/board/tc/platform.mk
@@ -31,6 +31,9 @@
 # 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
@@ -77,6 +80,7 @@
 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		\
@@ -87,6 +91,9 @@
 				${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
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
index ecec26c..0523ef8 100644
--- a/plat/arm/board/tc/tc_bl31_setup.c
+++ b/plat/arm/board/tc/tc_bl31_setup.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
  */
@@ -13,6 +13,8 @@
 #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>
 
@@ -42,6 +44,9 @@
 				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)
@@ -53,3 +58,16 @@
 {
 	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/tc/tc_plat.c b/plat/arm/board/tc/tc_plat.c
index 3863a0a..a9668e1 100644
--- a/plat/arm/board/tc/tc_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
  */
@@ -63,6 +63,7 @@
 	ARM_MAP_SHARED_RAM,
 	V2M_MAP_IOFPGA,
 	TC_MAP_DEVICE,
+	PLAT_DTB_DRAM_NS,
 #if SPM_MM
 	ARM_SPM_BUF_EL3_MMAP,
 #endif
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 3a4f720..4a58fc6 100644
--- a/plat/marvell/armada/a3k/common/a3700_ea.c
+++ b/plat/marvell/armada/a3k/common/a3700_ea.c
@@ -8,14 +8,79 @@
 #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)
+	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/mediatek/mt8195/bl31_plat_setup.c b/plat/mediatek/mt8195/bl31_plat_setup.c
index 8745454..dff6670 100644
--- a/plat/mediatek/mt8195/bl31_plat_setup.c
+++ b/plat/mediatek/mt8195/bl31_plat_setup.c
@@ -16,6 +16,7 @@
 #include <lib/coreboot.h>
 
 /* Platform Includes */
+#include <emi_mpu.h>
 #include <mt_gic_v3.h>
 #include <mt_spm.h>
 #include <mt_timer.h>
@@ -90,6 +91,9 @@
 		ERROR("Failed to set default dcm on!!\n");
 	}
 
+	/* Initialize EMI MPU */
+	emi_mpu_init();
+
 	/* Initialize the GIC driver, CPU and distributor interfaces */
 	mt_gic_driver_init();
 	mt_gic_init();
diff --git a/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c b/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c
new file mode 100644
index 0000000..4330b77
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <emi_mpu.h>
+
+#if ENABLE_EMI_MPU_SW_LOCK
+static unsigned char region_lock_state[EMI_MPU_REGION_NUM];
+#endif
+
+#define EMI_MPU_START_MASK		(0x00FFFFFF)
+#define EMI_MPU_END_MASK		(0x00FFFFFF)
+#define EMI_MPU_APC_SW_LOCK_MASK	(0x00FFFFFF)
+#define EMI_MPU_APC_HW_LOCK_MASK	(0x80FFFFFF)
+
+static int _emi_mpu_set_protection(unsigned int start, unsigned int end,
+					unsigned int apc)
+{
+	unsigned int dgroup;
+	unsigned int region;
+
+	region = (start >> 24) & 0xFF;
+	start &= EMI_MPU_START_MASK;
+	dgroup = (end >> 24) & 0xFF;
+	end &= EMI_MPU_END_MASK;
+
+	if  ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) {
+		WARN("invalid region, domain\n");
+		return -1;
+	}
+
+#if ENABLE_EMI_MPU_SW_LOCK
+	if (region_lock_state[region] == 1) {
+		WARN("invalid region\n");
+		return -1;
+	}
+
+	if ((dgroup == 0) && ((apc >> 31) & 0x1)) {
+		region_lock_state[region] = 1;
+	}
+
+	apc &= EMI_MPU_APC_SW_LOCK_MASK;
+#else
+	apc &= EMI_MPU_APC_HW_LOCK_MASK;
+#endif
+
+	if ((start >= DRAM_OFFSET) && (end >= start)) {
+		start -= DRAM_OFFSET;
+		end -= DRAM_OFFSET;
+	} else {
+		WARN("invalid range\n");
+		return -1;
+	}
+
+	mmio_write_32(EMI_MPU_SA(region), start);
+	mmio_write_32(EMI_MPU_EA(region), end);
+	mmio_write_32(EMI_MPU_APC(region, dgroup), apc);
+
+#if defined(SUB_EMI_MPU_BASE)
+	mmio_write_32(SUB_EMI_MPU_SA(region), start);
+	mmio_write_32(SUB_EMI_MPU_EA(region), end);
+	mmio_write_32(SUB_EMI_MPU_APC(region, dgroup), apc);
+#endif
+	return 1;
+}
+
+int emi_mpu_set_protection(struct emi_region_info_t *region_info)
+{
+	unsigned int start, end;
+	int i;
+
+	if (region_info->region >= EMI_MPU_REGION_NUM) {
+		WARN("invalid region\n");
+		return -1;
+	}
+
+	start = (unsigned int)(region_info->start >> EMI_MPU_ALIGN_BITS) |
+		(region_info->region << 24);
+
+	for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) {
+		end = (unsigned int)(region_info->end >> EMI_MPU_ALIGN_BITS) |
+			(i << 24);
+		_emi_mpu_set_protection(start, end, region_info->apc[i]);
+	}
+
+	return 0;
+}
+
+void emi_mpu_init(void)
+{
+	/* TODO: more setting for EMI MPU. */
+}
diff --git a/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.h b/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.h
new file mode 100644
index 0000000..415146e
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EMI_MPU_H
+#define EMI_MPU_H
+
+#include <platform_def.h>
+
+#define ENABLE_EMI_MPU_SW_LOCK		1
+
+#define EMI_MPU_CTRL			(EMI_MPU_BASE + 0x000)
+#define EMI_MPU_DBG			(EMI_MPU_BASE + 0x004)
+#define EMI_MPU_SA0			(EMI_MPU_BASE + 0x100)
+#define EMI_MPU_EA0			(EMI_MPU_BASE + 0x200)
+#define EMI_MPU_SA(region)		(EMI_MPU_SA0 + (region * 4))
+#define EMI_MPU_EA(region)		(EMI_MPU_EA0 + (region * 4))
+#define EMI_MPU_APC0			(EMI_MPU_BASE + 0x300)
+#define EMI_MPU_APC(region, dgroup)	(EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100))
+#define EMI_MPU_CTRL_D0			(EMI_MPU_BASE + 0x800)
+#define EMI_MPU_CTRL_D(domain)		(EMI_MPU_CTRL_D0 + (domain * 4))
+#define EMI_RG_MASK_D0			(EMI_MPU_BASE + 0x900)
+#define EMI_RG_MASK_D(domain)		(EMI_RG_MASK_D0 + (domain * 4))
+#define EMI_MPU_START			(0x000)
+#define EMI_MPU_END			(0x93C)
+
+#define SUB_EMI_MPU_CTRL		(SUB_EMI_MPU_BASE + 0x000)
+#define SUB_EMI_MPU_DBG			(SUB_EMI_MPU_BASE + 0x004)
+#define SUB_EMI_MPU_SA0			(SUB_EMI_MPU_BASE + 0x100)
+#define SUB_EMI_MPU_EA0			(SUB_EMI_MPU_BASE + 0x200)
+#define SUB_EMI_MPU_SA(region)		(SUB_EMI_MPU_SA0 + (region * 4))
+#define SUB_EMI_MPU_EA(region)		(SUB_EMI_MPU_EA0 + (region * 4))
+#define SUB_EMI_MPU_APC0		(SUB_EMI_MPU_BASE + 0x300)
+#define SUB_EMI_MPU_APC(region, dgroup)	(SUB_EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100))
+#define SUB_EMI_MPU_CTRL_D0		(SUB_EMI_MPU_BASE + 0x800)
+#define SUB_EMI_MPU_CTRL_D(domain)	(SUB_EMI_MPU_CTRL_D0 + (domain * 4))
+#define SUB_EMI_RG_MASK_D0		(SUB_EMI_MPU_BASE + 0x900)
+#define SUB_EMI_RG_MASK_D(domain)	(SUB_EMI_RG_MASK_D0 + (domain * 4))
+
+#define EMI_MPU_DOMAIN_NUM		(16)
+#define EMI_MPU_REGION_NUM		(32)
+#define EMI_MPU_ALIGN_BITS		(16)
+#define DRAM_OFFSET			(0x40000000 >> EMI_MPU_ALIGN_BITS)
+
+#define NO_PROTECTION			0
+#define SEC_RW				1
+#define SEC_RW_NSEC_R			2
+#define SEC_RW_NSEC_W			3
+#define SEC_R_NSEC_R			4
+#define FORBIDDEN			5
+#define SEC_R_NSEC_RW			6
+
+#define LOCK				1
+#define UNLOCK				0
+
+#define EMI_MPU_DGROUP_NUM		(EMI_MPU_DOMAIN_NUM / 8)
+
+#if (EMI_MPU_DGROUP_NUM == 1)
+#define SET_ACCESS_PERMISSION(apc_ary, lock, d7, d6, d5, d4, d3, d2, d1, d0) \
+do { \
+	apc_ary[1] = 0; \
+	apc_ary[0] = \
+		(((unsigned int)  d7) << 21) | (((unsigned int)  d6) << 18) | \
+		(((unsigned int)  d5) << 15) | (((unsigned int)  d4) << 12) | \
+		(((unsigned int)  d3) <<  9) | (((unsigned int)  d2) <<  6) | \
+		(((unsigned int)  d1) <<  3) |  ((unsigned int)  d0) | \
+		((unsigned int) lock << 31); \
+} while (0)
+#elif (EMI_MPU_DGROUP_NUM == 2)
+#define SET_ACCESS_PERMISSION(apc_ary, lock, d15, d14, d13, d12, d11, d10, \
+				d9, d8, d7, d6, d5, d4, d3, d2, d1, d0) \
+do { \
+	apc_ary[1] = \
+		(((unsigned int) d15) << 21) | (((unsigned int) d14) << 18) | \
+		(((unsigned int) d13) << 15) | (((unsigned int) d12) << 12) | \
+		(((unsigned int) d11) <<  9) | (((unsigned int) d10) <<  6) | \
+		(((unsigned int)  d9) <<  3) |  ((unsigned int)  d8); \
+	apc_ary[0] = \
+		(((unsigned int)  d7) << 21) | (((unsigned int)  d6) << 18) | \
+		(((unsigned int)  d5) << 15) | (((unsigned int)  d4) << 12) | \
+		(((unsigned int)  d3) <<  9) | (((unsigned int)  d2) <<  6) | \
+		(((unsigned int)  d1) <<  3) |  ((unsigned int)  d0) | \
+		((unsigned int) lock << 31); \
+} while (0)
+#endif
+
+struct emi_region_info_t {
+	unsigned long long start;
+	unsigned long long end;
+	unsigned int region;
+	unsigned int apc[EMI_MPU_DGROUP_NUM];
+};
+
+void emi_mpu_init(void);
+
+#endif
diff --git a/plat/mediatek/mt8195/drivers/spm/build.mk b/plat/mediatek/mt8195/drivers/spm/build.mk
index d1ee092..28b2d07 100644
--- a/plat/mediatek/mt8195/drivers/spm/build.mk
+++ b/plat/mediatek/mt8195/drivers/spm/build.mk
@@ -30,7 +30,8 @@
 	${CUR_SPM_FOLDER}/constraints/mt_spm_rc_syspll.c	\
 	${CUR_SPM_FOLDER}/mt_spm_cond.c				\
 	${CUR_SPM_FOLDER}/mt_spm_suspend.c			\
-	${CUR_SPM_FOLDER}/mt_spm_idle.c
+	${CUR_SPM_FOLDER}/mt_spm_idle.c				\
+	${CUR_SPM_FOLDER}/mt_spm_vcorefs.c
 
 ifeq (${MT_SPM_FEATURE_SUPPORT}, no)
 PLAT_SPM_DEBUG_CFLAGS += -DATF_PLAT_SPM_UNSUPPORT
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.c b/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.c
new file mode 100644
index 0000000..2a9a789
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.c
@@ -0,0 +1,522 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <stddef.h>
+#include <string.h>
+#include <common/debug.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <mt_spm.h>
+#include <mt_spm_internal.h>
+#include <mt_spm_pmic_wrap.h>
+#include <mt_spm_reg.h>
+#include <mt_spm_vcorefs.h>
+#include <mtk_plat_common.h>
+#include <mtk_sip_svc.h>
+#include <platform_def.h>
+
+#define VCORE_MAX_OPP 4
+#define DRAM_MAX_OPP 7
+
+static bool spm_dvfs_init_done;
+static bool dvfs_enable_done;
+static int vcore_opp_0_uv = 750000;
+static int vcore_opp_1_uv = 650000;
+static int vcore_opp_2_uv = 600000;
+static int vcore_opp_3_uv = 550000;
+
+static struct reg_config dvfsrc_init_configs[] = {
+	{ DVFSRC_HRT_REQ_UNIT,       0x0000001E },
+	{ DVFSRC_DEBOUNCE_TIME,      0x19651965 },
+	{ DVFSRC_TIMEOUT_NEXTREQ,    0x00000015 },
+	{ DVFSRC_LEVEL_MASK,         0x000EE000 },
+	{ DVFSRC_DDR_QOS0,           0x00000019 },
+	{ DVFSRC_DDR_QOS1,           0x00000026 },
+	{ DVFSRC_DDR_QOS2,           0x00000033 },
+	{ DVFSRC_DDR_QOS3,           0x0000003B },
+	{ DVFSRC_DDR_QOS4,           0x0000004C },
+	{ DVFSRC_DDR_QOS5,           0x00000066 },
+	{ DVFSRC_DDR_QOS6,           0x00660066 },
+	{ DVFSRC_LEVEL_LABEL_0_1,    0x50436053 },
+	{ DVFSRC_LEVEL_LABEL_2_3,    0x40335042 },
+	{ DVFSRC_LEVEL_LABEL_4_5,    0x40314032 },
+	{ DVFSRC_LEVEL_LABEL_6_7,    0x30223023 },
+	{ DVFSRC_LEVEL_LABEL_8_9,    0x20133021 },
+	{ DVFSRC_LEVEL_LABEL_10_11,  0x20112012 },
+	{ DVFSRC_LEVEL_LABEL_12_13,  0x10032010 },
+	{ DVFSRC_LEVEL_LABEL_14_15,  0x10011002 },
+	{ DVFSRC_LEVEL_LABEL_16_17,  0x00131000 },
+	{ DVFSRC_LEVEL_LABEL_18_19,  0x00110012 },
+	{ DVFSRC_LEVEL_LABEL_20_21,  0x00000010 },
+	{ DVFSRC_MD_LATENCY_IMPROVE, 0x00000040 },
+	{ DVFSRC_DDR_REQUEST,        0x00004321 },
+	{ DVFSRC_DDR_REQUEST3,       0x00000065 },
+	{ DVFSRC_DDR_ADD_REQUEST,    0x66543210 },
+	{ DVFSRC_HRT_REQUEST,        0x66654321 },
+	{ DVFSRC_DDR_REQUEST5,       0x54321000 },
+	{ DVFSRC_DDR_REQUEST7,       0x66000000 },
+	{ DVFSRC_VCORE_USER_REQ,     0x00010A29 },
+	{ DVFSRC_HRT_HIGH_3,         0x18A618A6 },
+	{ DVFSRC_HRT_HIGH_2,         0x18A61183 },
+	{ DVFSRC_HRT_HIGH_1,         0x0D690B80 },
+	{ DVFSRC_HRT_HIGH,           0x070804B0 },
+	{ DVFSRC_HRT_LOW_3,          0x18A518A5 },
+	{ DVFSRC_HRT_LOW_2,          0x18A51182 },
+	{ DVFSRC_HRT_LOW_1,          0x0D680B7F },
+	{ DVFSRC_HRT_LOW,            0x070704AF },
+	{ DVFSRC_BASIC_CONTROL_3,    0x00000006 },
+	{ DVFSRC_INT_EN,             0x00000002 },
+	{ DVFSRC_QOS_EN,             0x0000407C },
+	{ DVFSRC_HRT_BW_BASE,        0x00000004 },
+	{ DVFSRC_PCIE_VCORE_REQ,     0x65908101 },
+	{ DVFSRC_CURRENT_FORCE,      0x00000001 },
+	{ DVFSRC_BASIC_CONTROL,      0x6698444B },
+	{ DVFSRC_BASIC_CONTROL,      0x6698054B },
+	{ DVFSRC_CURRENT_FORCE,      0x00000000 },
+};
+
+static struct pwr_ctrl vcorefs_ctrl = {
+	.wake_src		= R12_REG_CPU_WAKEUP,
+
+	/* default VCORE DVFS is disabled */
+	.pcm_flags = (SPM_FLAG_RUN_COMMON_SCENARIO |
+			SPM_FLAG_DISABLE_VCORE_DVS | SPM_FLAG_DISABLE_VCORE_DFS),
+
+	/* SPM_AP_STANDBY_CON */
+	/* [0] */
+	.reg_wfi_op = 0,
+	/* [1] */
+	.reg_wfi_type = 0,
+	/* [2] */
+	.reg_mp0_cputop_idle_mask = 0,
+	/* [3] */
+	.reg_mp1_cputop_idle_mask = 0,
+	/* [4] */
+	.reg_mcusys_idle_mask = 0,
+	/* [25] */
+	.reg_md_apsrc_1_sel = 0,
+	/* [26] */
+	.reg_md_apsrc_0_sel = 0,
+	/* [29] */
+	.reg_conn_apsrc_sel = 0,
+
+	/* SPM_SRC_REQ */
+	/* [0] */
+	.reg_spm_apsrc_req = 0,
+	/* [1] */
+	.reg_spm_f26m_req = 0,
+	/* [3] */
+	.reg_spm_infra_req = 0,
+	/* [4] */
+	.reg_spm_vrf18_req = 0,
+	/* [7] FIXME: default disable HW Auto S1*/
+	.reg_spm_ddr_en_req = 1,
+	/* [8] */
+	.reg_spm_dvfs_req = 0,
+	/* [9] */
+	.reg_spm_sw_mailbox_req = 0,
+	/* [10] */
+	.reg_spm_sspm_mailbox_req = 0,
+	/* [11] */
+	.reg_spm_adsp_mailbox_req = 0,
+	/* [12] */
+	.reg_spm_scp_mailbox_req = 0,
+
+	/* SPM_SRC_MASK */
+	/* [0] */
+	.reg_sspm_srcclkena_0_mask_b = 1,
+	/* [1] */
+	.reg_sspm_infra_req_0_mask_b = 1,
+	/* [2] */
+	.reg_sspm_apsrc_req_0_mask_b = 1,
+	/* [3] */
+	.reg_sspm_vrf18_req_0_mask_b = 1,
+	/* [4] */
+	.reg_sspm_ddr_en_0_mask_b = 1,
+	/* [5] */
+	.reg_scp_srcclkena_mask_b = 1,
+	/* [6] */
+	.reg_scp_infra_req_mask_b = 1,
+	/* [7] */
+	.reg_scp_apsrc_req_mask_b = 1,
+	/* [8] */
+	.reg_scp_vrf18_req_mask_b = 1,
+	/* [9] */
+	.reg_scp_ddr_en_mask_b = 1,
+	/* [10] */
+	.reg_audio_dsp_srcclkena_mask_b = 1,
+	/* [11] */
+	.reg_audio_dsp_infra_req_mask_b = 1,
+	/* [12] */
+	.reg_audio_dsp_apsrc_req_mask_b = 1,
+	/* [13] */
+	.reg_audio_dsp_vrf18_req_mask_b = 1,
+	/* [14] */
+	.reg_audio_dsp_ddr_en_mask_b = 1,
+	/* [15] */
+	.reg_apu_srcclkena_mask_b = 1,
+	/* [16] */
+	.reg_apu_infra_req_mask_b = 1,
+	/* [17] */
+	.reg_apu_apsrc_req_mask_b = 1,
+	/* [18] */
+	.reg_apu_vrf18_req_mask_b = 1,
+	/* [19] */
+	.reg_apu_ddr_en_mask_b = 1,
+	/* [20] */
+	.reg_cpueb_srcclkena_mask_b = 1,
+	/* [21] */
+	.reg_cpueb_infra_req_mask_b = 1,
+	/* [22] */
+	.reg_cpueb_apsrc_req_mask_b = 1,
+	/* [23] */
+	.reg_cpueb_vrf18_req_mask_b = 1,
+	/* [24] */
+	.reg_cpueb_ddr_en_mask_b = 1,
+	/* [25] */
+	.reg_bak_psri_srcclkena_mask_b = 0,
+	/* [26] */
+	.reg_bak_psri_infra_req_mask_b = 0,
+	/* [27] */
+	.reg_bak_psri_apsrc_req_mask_b = 0,
+	/* [28] */
+	.reg_bak_psri_vrf18_req_mask_b = 0,
+	/* [29] */
+	.reg_bak_psri_ddr_en_mask_b = 0,
+
+	/* SPM_SRC2_MASK */
+	/* [0] */
+	.reg_msdc0_srcclkena_mask_b = 1,
+	/* [1] */
+	.reg_msdc0_infra_req_mask_b = 1,
+	/* [2] */
+	.reg_msdc0_apsrc_req_mask_b = 1,
+	/* [3] */
+	.reg_msdc0_vrf18_req_mask_b = 1,
+	/* [4] */
+	.reg_msdc0_ddr_en_mask_b = 1,
+	/* [5] */
+	.reg_msdc1_srcclkena_mask_b = 1,
+	/* [6] */
+	.reg_msdc1_infra_req_mask_b = 1,
+	/* [7] */
+	.reg_msdc1_apsrc_req_mask_b = 1,
+	/* [8] */
+	.reg_msdc1_vrf18_req_mask_b = 1,
+	/* [9] */
+	.reg_msdc1_ddr_en_mask_b = 1,
+	/* [10] */
+	.reg_msdc2_srcclkena_mask_b = 1,
+	/* [11] */
+	.reg_msdc2_infra_req_mask_b = 1,
+	/* [12] */
+	.reg_msdc2_apsrc_req_mask_b = 1,
+	/* [13] */
+	.reg_msdc2_vrf18_req_mask_b = 1,
+	/* [14] */
+	.reg_msdc2_ddr_en_mask_b = 1,
+	/* [15] */
+	.reg_ufs_srcclkena_mask_b = 1,
+	/* [16] */
+	.reg_ufs_infra_req_mask_b = 1,
+	/* [17] */
+	.reg_ufs_apsrc_req_mask_b = 1,
+	/* [18] */
+	.reg_ufs_vrf18_req_mask_b = 1,
+	/* [19] */
+	.reg_ufs_ddr_en_mask_b = 1,
+	/* [20] */
+	.reg_usb_srcclkena_mask_b = 1,
+	/* [21] */
+	.reg_usb_infra_req_mask_b = 1,
+	/* [22] */
+	.reg_usb_apsrc_req_mask_b = 1,
+	/* [23] */
+	.reg_usb_vrf18_req_mask_b = 1,
+	/* [24] */
+	.reg_usb_ddr_en_mask_b = 1,
+	/* [25] */
+	.reg_pextp_p0_srcclkena_mask_b = 1,
+	/* [26] */
+	.reg_pextp_p0_infra_req_mask_b = 1,
+	/* [27] */
+	.reg_pextp_p0_apsrc_req_mask_b = 1,
+	/* [28] */
+	.reg_pextp_p0_vrf18_req_mask_b = 1,
+	/* [29] */
+	.reg_pextp_p0_ddr_en_mask_b = 1,
+
+	/* SPM_SRC3_MASK */
+	/* [0] */
+	.reg_pextp_p1_srcclkena_mask_b = 1,
+	/* [1] */
+	.reg_pextp_p1_infra_req_mask_b = 1,
+	/* [2] */
+	.reg_pextp_p1_apsrc_req_mask_b = 1,
+	/* [3] */
+	.reg_pextp_p1_vrf18_req_mask_b = 1,
+	/* [4] */
+	.reg_pextp_p1_ddr_en_mask_b = 1,
+	/* [5] */
+	.reg_gce0_infra_req_mask_b = 1,
+	/* [6] */
+	.reg_gce0_apsrc_req_mask_b = 1,
+	/* [7] */
+	.reg_gce0_vrf18_req_mask_b = 1,
+	/* [8] */
+	.reg_gce0_ddr_en_mask_b = 1,
+	/* [9] */
+	.reg_gce1_infra_req_mask_b = 1,
+	/* [10] */
+	.reg_gce1_apsrc_req_mask_b = 1,
+	/* [11] */
+	.reg_gce1_vrf18_req_mask_b = 1,
+	/* [12] */
+	.reg_gce1_ddr_en_mask_b = 1,
+	/* [13] */
+	.reg_spm_srcclkena_reserved_mask_b = 1,
+	/* [14] */
+	.reg_spm_infra_req_reserved_mask_b = 1,
+	/* [15] */
+	.reg_spm_apsrc_req_reserved_mask_b = 1,
+	/* [16] */
+	.reg_spm_vrf18_req_reserved_mask_b = 1,
+	/* [17] */
+	.reg_spm_ddr_en_reserved_mask_b = 1,
+	/* [18] */
+	.reg_disp0_apsrc_req_mask_b = 1,
+	/* [19] */
+	.reg_disp0_ddr_en_mask_b = 1,
+	/* [20] */
+	.reg_disp1_apsrc_req_mask_b = 1,
+	/* [21] */
+	.reg_disp1_ddr_en_mask_b = 1,
+	/* [22] */
+	.reg_disp2_apsrc_req_mask_b = 1,
+	/* [23] */
+	.reg_disp2_ddr_en_mask_b = 1,
+	/* [24] */
+	.reg_disp3_apsrc_req_mask_b = 1,
+	/* [25] */
+	.reg_disp3_ddr_en_mask_b = 1,
+	/* [26] */
+	.reg_infrasys_apsrc_req_mask_b = 0,
+	/* [27] */
+	.reg_infrasys_ddr_en_mask_b = 1,
+
+	/* [28] */
+	.reg_cg_check_srcclkena_mask_b = 1,
+	/* [29] */
+	.reg_cg_check_apsrc_req_mask_b = 1,
+	/* [30] */
+	.reg_cg_check_vrf18_req_mask_b = 1,
+	/* [31] */
+	.reg_cg_check_ddr_en_mask_b = 1,
+
+	/* SPM_SRC4_MASK */
+	/* [8:0] */
+	.reg_mcusys_merge_apsrc_req_mask_b = 0x11,
+	/* [17:9] */
+	.reg_mcusys_merge_ddr_en_mask_b = 0x11,
+	/* [19:18] */
+	.reg_dramc_md32_infra_req_mask_b = 0,
+	/* [21:20] */
+	.reg_dramc_md32_vrf18_req_mask_b = 0,
+	/* [23:22] */
+	.reg_dramc_md32_ddr_en_mask_b = 0,
+	/* [24] */
+	.reg_dvfsrc_event_trigger_mask_b = 1,
+
+	/* SPM_WAKEUP_EVENT_MASK2 */
+	/* [3:0] */
+	.reg_sc_sw2spm_wakeup_mask_b = 0,
+	/* [4] */
+	.reg_sc_adsp2spm_wakeup_mask_b = 0,
+	/* [8:5] */
+	.reg_sc_sspm2spm_wakeup_mask_b = 0,
+	/* [9] */
+	.reg_sc_scp2spm_wakeup_mask_b = 0,
+	/* [10] */
+	.reg_csyspwrup_ack_mask = 0,
+	/* [11] */
+	.reg_csyspwrup_req_mask = 1,
+
+	/* SPM_WAKEUP_EVENT_MASK */
+	/* [31:0] */
+	.reg_wakeup_event_mask = 0xEFFFFFFF,
+
+	/* SPM_WAKEUP_EVENT_EXT_MASK */
+	/* [31:0] */
+	.reg_ext_wakeup_event_mask = 0xFFFFFFFF,
+};
+
+struct spm_lp_scen __spm_vcorefs = {
+	.pwrctrl	= &vcorefs_ctrl,
+};
+
+static void spm_vcorefs_pwarp_cmd(uint64_t cmd, uint64_t val)
+{
+	if (cmd < NR_IDX_ALL) {
+		mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_ALLINONE, cmd, val);
+	} else {
+		INFO("cmd out of range!\n");
+	}
+}
+
+void spm_dvfsfw_init(uint64_t boot_up_opp, uint64_t dram_issue)
+{
+	if (spm_dvfs_init_done == false) {
+		mmio_write_32(SPM_DVFS_MISC, (mmio_read_32(SPM_DVFS_MISC) &
+				~(SPM_DVFS_FORCE_ENABLE_LSB)) | (SPM_DVFSRC_ENABLE_LSB));
+
+		mmio_write_32(SPM_DVFS_LEVEL, 0x00000001);
+		mmio_write_32(SPM_DVS_DFS_LEVEL, 0x00010001);
+
+		spm_dvfs_init_done = true;
+	}
+}
+
+void __spm_sync_vcore_dvfs_power_control(struct pwr_ctrl *dest_pwr_ctrl,
+						const struct pwr_ctrl *src_pwr_ctrl)
+{
+	uint32_t dvfs_mask = SPM_FLAG_DISABLE_VCORE_DVS |
+			     SPM_FLAG_DISABLE_VCORE_DFS |
+			     SPM_FLAG_ENABLE_VOLTAGE_BIN;
+
+	dest_pwr_ctrl->pcm_flags = (dest_pwr_ctrl->pcm_flags & (~dvfs_mask)) |
+					(src_pwr_ctrl->pcm_flags & dvfs_mask);
+
+	if (dest_pwr_ctrl->pcm_flags_cust) {
+		dest_pwr_ctrl->pcm_flags_cust = (dest_pwr_ctrl->pcm_flags_cust & (~dvfs_mask)) |
+						(src_pwr_ctrl->pcm_flags & dvfs_mask);
+	}
+}
+
+void spm_go_to_vcorefs(uint64_t spm_flags)
+{
+	__spm_set_power_control(__spm_vcorefs.pwrctrl);
+	__spm_set_wakeup_event(__spm_vcorefs.pwrctrl);
+	__spm_set_pcm_flags(__spm_vcorefs.pwrctrl);
+	__spm_send_cpu_wakeup_event();
+}
+
+uint64_t spm_vcorefs_args(uint64_t x1, uint64_t x2, uint64_t x3)
+{
+	uint64_t ret = 0U;
+	uint64_t cmd = x1;
+	uint64_t spm_flags;
+
+	switch (cmd) {
+	case VCOREFS_SMC_CMD_0:
+		spm_dvfsfw_init(x2, x3);
+		break;
+	case VCOREFS_SMC_CMD_1:
+		spm_flags = SPM_FLAG_RUN_COMMON_SCENARIO;
+		if (x2 & SPM_FLAG_DISABLE_VCORE_DVS)
+			spm_flags |= SPM_FLAG_DISABLE_VCORE_DVS;
+		if (x2 & SPM_FLAG_DISABLE_VCORE_DFS)
+			spm_flags |= SPM_FLAG_DISABLE_VCORE_DFS;
+		spm_go_to_vcorefs(spm_flags);
+		break;
+	case VCOREFS_SMC_CMD_3:
+		spm_vcorefs_pwarp_cmd(x2, x3);
+		break;
+	case VCOREFS_SMC_CMD_2:
+	case VCOREFS_SMC_CMD_4:
+	case VCOREFS_SMC_CMD_5:
+	case VCOREFS_SMC_CMD_7:
+	default:
+		break;
+	}
+	return ret;
+}
+
+static void dvfsrc_init(void)
+{
+	int i;
+	int count = ARRAY_SIZE(dvfsrc_init_configs);
+
+	if (dvfs_enable_done == false) {
+		for (i = 0; i < count; i++) {
+			mmio_write_32(dvfsrc_init_configs[i].offset,
+				dvfsrc_init_configs[i].val);
+		}
+
+		mmio_write_32(DVFSRC_QOS_EN, 0x0011007C);
+
+		dvfs_enable_done = true;
+	}
+}
+
+static void spm_vcorefs_vcore_setting(uint64_t flag)
+{
+	spm_vcorefs_pwarp_cmd(3, __vcore_uv_to_pmic(vcore_opp_3_uv));
+	spm_vcorefs_pwarp_cmd(2, __vcore_uv_to_pmic(vcore_opp_2_uv));
+	spm_vcorefs_pwarp_cmd(1, __vcore_uv_to_pmic(vcore_opp_1_uv));
+	spm_vcorefs_pwarp_cmd(0, __vcore_uv_to_pmic(vcore_opp_0_uv));
+}
+
+int spm_vcorefs_get_vcore(unsigned int gear)
+{
+	int ret_val;
+
+	switch (gear) {
+	case 3:
+		ret_val = vcore_opp_0_uv;
+	case 2:
+		ret_val = vcore_opp_1_uv;
+	case 1:
+		ret_val = vcore_opp_2_uv;
+	case 0:
+	default:
+		ret_val = vcore_opp_3_uv;
+	}
+	return ret_val;
+}
+
+uint64_t spm_vcorefs_v2_args(u_register_t x1, u_register_t x2, u_register_t x3, u_register_t *x4)
+{
+	uint64_t ret = 0U;
+	uint64_t cmd = x1;
+	uint64_t spm_flags;
+
+	switch (cmd) {
+	case VCOREFS_SMC_CMD_INIT:
+		/* vcore_dvfs init + kick */
+		spm_dvfsfw_init(0, 0);
+		spm_vcorefs_vcore_setting(x3 & 0xF);
+		spm_flags = SPM_FLAG_RUN_COMMON_SCENARIO;
+		if (x2 & 0x1) {
+			spm_flags |= SPM_FLAG_DISABLE_VCORE_DVS;
+		}
+		if (x2 & 0x2) {
+			spm_flags |= SPM_FLAG_DISABLE_VCORE_DFS;
+		}
+		spm_go_to_vcorefs(spm_flags);
+		dvfsrc_init();
+		*x4 = 0U;
+		break;
+	case VCOREFS_SMC_CMD_OPP_TYPE:
+		/* get dram type */
+		*x4 = 0U;
+		break;
+	case VCOREFS_SMC_CMD_FW_TYPE:
+		*x4 = 0U;
+		break;
+	case VCOREFS_SMC_CMD_GET_UV:
+		*x4 = spm_vcorefs_get_vcore(x2);
+		break;
+	case VCOREFS_SMC_CMD_GET_NUM_V:
+		*x4 = VCORE_MAX_OPP;
+		break;
+	case VCOREFS_SMC_CMD_GET_NUM_F:
+		*x4 = DRAM_MAX_OPP;
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
diff --git a/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.h b/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.h
new file mode 100644
index 0000000..b08fcce
--- /dev/null
+++ b/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.h
@@ -0,0 +1,328 @@
+/*
+ * Copyright (c) 2021, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef __MT_SPM_VCOREFS__H__
+#define __MT_SPM_VCOREFS__H__
+
+int spm_vcorefs_get_vcore(unsigned int gear);
+uint64_t spm_vcorefs_v2_args(u_register_t x1, u_register_t x2, u_register_t x3,
+			     u_register_t *x4);
+
+enum vcorefs_smc_cmd {
+	VCOREFS_SMC_CMD_0 = 0,
+	VCOREFS_SMC_CMD_1,
+	VCOREFS_SMC_CMD_2,
+	VCOREFS_SMC_CMD_3,
+	VCOREFS_SMC_CMD_4,
+	/* check spmfw status */
+	VCOREFS_SMC_CMD_5,
+
+	/* get spmfw type */
+	VCOREFS_SMC_CMD_6,
+
+	/* get spm reg status */
+	VCOREFS_SMC_CMD_7,
+
+	NUM_VCOREFS_SMC_CMD,
+};
+
+enum vcorefs_smc_cmd_new {
+	VCOREFS_SMC_CMD_INIT = 0,
+	VCOREFS_SMC_CMD_KICK = 1,
+	VCOREFS_SMC_CMD_OPP_TYPE = 2,
+	VCOREFS_SMC_CMD_FW_TYPE = 3,
+	VCOREFS_SMC_CMD_GET_UV = 4,
+	VCOREFS_SMC_CMD_GET_FREQ = 5,
+	VCOREFS_SMC_CMD_GET_NUM_V = 6,
+	VCOREFS_SMC_CMD_GET_NUM_F = 7,
+	VCOREFS_SMC_CMD_FB_ACTION = 8,
+	/*chip specific setting */
+	VCOREFS_SMC_CMD_SET_FREQ = 16,
+	VCOREFS_SMC_CMD_SET_EFUSE = 17,
+	VCOREFS_SMC_CMD_GET_EFUSE = 18,
+	VCOREFS_SMC_CMD_DVFS_HOPPING = 19,
+	VCOREFS_SMC_CMD_DVFS_HOPPING_STATE = 20,
+};
+
+enum dvfsrc_channel {
+	DVFSRC_CHANNEL_1 = 1,
+	DVFSRC_CHANNEL_2,
+	DVFSRC_CHANNEL_3,
+	DVFSRC_CHANNEL_4,
+	NUM_DVFSRC_CHANNEL,
+};
+
+#define _VCORE_BASE_UV		400000
+#define _VCORE_STEP_UV		6250
+
+/* PMIC */
+#define __vcore_pmic_to_uv(pmic)	\
+	(((pmic) * _VCORE_STEP_UV) + _VCORE_BASE_UV)
+
+#define __vcore_uv_to_pmic(uv)	/* pmic >= uv */	\
+	((((uv) - _VCORE_BASE_UV) + (_VCORE_STEP_UV - 1)) / _VCORE_STEP_UV)
+
+struct reg_config {
+	uint32_t offset;
+	uint32_t val;
+};
+
+#define DVFSRC_BASIC_CONTROL             (DVFSRC_BASE + 0x0)
+#define DVFSRC_SW_REQ1                   (DVFSRC_BASE + 0x4)
+#define DVFSRC_SW_REQ2                   (DVFSRC_BASE + 0x8)
+#define DVFSRC_SW_REQ3                   (DVFSRC_BASE + 0xC)
+#define DVFSRC_SW_REQ4                   (DVFSRC_BASE + 0x10)
+#define DVFSRC_SW_REQ5                   (DVFSRC_BASE + 0x14)
+#define DVFSRC_SW_REQ6                   (DVFSRC_BASE + 0x18)
+#define DVFSRC_SW_REQ7                   (DVFSRC_BASE + 0x1C)
+#define DVFSRC_SW_REQ8                   (DVFSRC_BASE + 0x20)
+#define DVFSRC_EMI_REQUEST               (DVFSRC_BASE + 0x24)
+#define DVFSRC_EMI_REQUEST2              (DVFSRC_BASE + 0x28)
+#define DVFSRC_EMI_REQUEST3              (DVFSRC_BASE + 0x2C)
+#define DVFSRC_EMI_REQUEST4              (DVFSRC_BASE + 0x30)
+#define DVFSRC_EMI_REQUEST5              (DVFSRC_BASE + 0x34)
+#define DVFSRC_EMI_REQUEST6              (DVFSRC_BASE + 0x38)
+#define DVFSRC_EMI_HRT                   (DVFSRC_BASE + 0x3C)
+#define DVFSRC_EMI_HRT2                  (DVFSRC_BASE + 0x40)
+#define DVFSRC_EMI_HRT3                  (DVFSRC_BASE + 0x44)
+#define DVFSRC_EMI_QOS0                  (DVFSRC_BASE + 0x48)
+#define DVFSRC_EMI_QOS1                  (DVFSRC_BASE + 0x4C)
+#define DVFSRC_EMI_QOS2                  (DVFSRC_BASE + 0x50)
+#define DVFSRC_EMI_MD2SPM0               (DVFSRC_BASE + 0x54)
+#define DVFSRC_EMI_MD2SPM1               (DVFSRC_BASE + 0x58)
+#define DVFSRC_EMI_MD2SPM2               (DVFSRC_BASE + 0x5C)
+#define DVFSRC_EMI_MD2SPM0_T             (DVFSRC_BASE + 0x60)
+#define DVFSRC_EMI_MD2SPM1_T             (DVFSRC_BASE + 0x64)
+#define DVFSRC_EMI_MD2SPM2_T             (DVFSRC_BASE + 0x68)
+#define DVFSRC_VCORE_REQUEST             (DVFSRC_BASE + 0x6C)
+#define DVFSRC_VCORE_REQUEST2            (DVFSRC_BASE + 0x70)
+#define DVFSRC_VCORE_REQUEST3            (DVFSRC_BASE + 0x74)
+#define DVFSRC_VCORE_REQUEST4            (DVFSRC_BASE + 0x78)
+#define DVFSRC_VCORE_HRT                 (DVFSRC_BASE + 0x7C)
+#define DVFSRC_VCORE_HRT2                (DVFSRC_BASE + 0x80)
+#define DVFSRC_VCORE_HRT3                (DVFSRC_BASE + 0x84)
+#define DVFSRC_VCORE_QOS0                (DVFSRC_BASE + 0x88)
+#define DVFSRC_VCORE_QOS1                (DVFSRC_BASE + 0x8C)
+#define DVFSRC_VCORE_QOS2                (DVFSRC_BASE + 0x90)
+#define DVFSRC_VCORE_MD2SPM0             (DVFSRC_BASE + 0x94)
+#define DVFSRC_VCORE_MD2SPM1             (DVFSRC_BASE + 0x98)
+#define DVFSRC_VCORE_MD2SPM2             (DVFSRC_BASE + 0x9C)
+#define DVFSRC_VCORE_MD2SPM0_T           (DVFSRC_BASE + 0xA0)
+#define DVFSRC_VCORE_MD2SPM1_T           (DVFSRC_BASE + 0xA4)
+#define DVFSRC_VCORE_MD2SPM2_T           (DVFSRC_BASE + 0xA8)
+#define DVFSRC_MD_VSRAM_REMAP            (DVFSRC_BASE + 0xBC)
+#define DVFSRC_HALT_SW_CONTROL           (DVFSRC_BASE + 0xC0)
+#define DVFSRC_INT                       (DVFSRC_BASE + 0xC4)
+#define DVFSRC_INT_EN                    (DVFSRC_BASE + 0xC8)
+#define DVFSRC_INT_CLR                   (DVFSRC_BASE + 0xCC)
+#define DVFSRC_BW_MON_WINDOW             (DVFSRC_BASE + 0xD0)
+#define DVFSRC_BW_MON_THRES_1            (DVFSRC_BASE + 0xD4)
+#define DVFSRC_BW_MON_THRES_2            (DVFSRC_BASE + 0xD8)
+#define DVFSRC_MD_TURBO                  (DVFSRC_BASE + 0xDC)
+#define DVFSRC_PCIE_VCORE_REQ            (DVFSRC_BASE + 0xE0)
+#define DVFSRC_VCORE_USER_REQ            (DVFSRC_BASE + 0xE4)
+#define DVFSRC_DEBOUNCE_FOUR             (DVFSRC_BASE + 0xF0)
+#define DVFSRC_DEBOUNCE_RISE_FALL        (DVFSRC_BASE + 0xF4)
+#define DVFSRC_TIMEOUT_NEXTREQ           (DVFSRC_BASE + 0xF8)
+#define DVFSRC_LEVEL_LABEL_0_1           (DVFSRC_BASE + 0x100)
+#define DVFSRC_LEVEL_LABEL_2_3           (DVFSRC_BASE + 0x104)
+#define DVFSRC_LEVEL_LABEL_4_5           (DVFSRC_BASE + 0x108)
+#define DVFSRC_LEVEL_LABEL_6_7           (DVFSRC_BASE + 0x10C)
+#define DVFSRC_LEVEL_LABEL_8_9           (DVFSRC_BASE + 0x110)
+#define DVFSRC_LEVEL_LABEL_10_11         (DVFSRC_BASE + 0x114)
+#define DVFSRC_LEVEL_LABEL_12_13         (DVFSRC_BASE + 0x118)
+#define DVFSRC_LEVEL_LABEL_14_15         (DVFSRC_BASE + 0x11C)
+#define DVFSRC_MM_BW_0                   (DVFSRC_BASE + 0x200)
+#define DVFSRC_MM_BW_1                   (DVFSRC_BASE + 0x204)
+#define DVFSRC_MM_BW_2                   (DVFSRC_BASE + 0x208)
+#define DVFSRC_MM_BW_3                   (DVFSRC_BASE + 0x20C)
+#define DVFSRC_MM_BW_4                   (DVFSRC_BASE + 0x210)
+#define DVFSRC_MM_BW_5                   (DVFSRC_BASE + 0x214)
+#define DVFSRC_MM_BW_6                   (DVFSRC_BASE + 0x218)
+#define DVFSRC_MM_BW_7                   (DVFSRC_BASE + 0x21C)
+#define DVFSRC_MM_BW_8                   (DVFSRC_BASE + 0x220)
+#define DVFSRC_MM_BW_9                   (DVFSRC_BASE + 0x224)
+#define DVFSRC_MM_BW_10                  (DVFSRC_BASE + 0x228)
+#define DVFSRC_MM_BW_11                  (DVFSRC_BASE + 0x22C)
+#define DVFSRC_MM_BW_12                  (DVFSRC_BASE + 0x230)
+#define DVFSRC_MM_BW_13                  (DVFSRC_BASE + 0x234)
+#define DVFSRC_MM_BW_14                  (DVFSRC_BASE + 0x238)
+#define DVFSRC_MM_BW_15                  (DVFSRC_BASE + 0x23C)
+#define DVFSRC_MD_BW_0                   (DVFSRC_BASE + 0x240)
+#define DVFSRC_MD_BW_1                   (DVFSRC_BASE + 0x244)
+#define DVFSRC_MD_BW_2                   (DVFSRC_BASE + 0x248)
+#define DVFSRC_MD_BW_3                   (DVFSRC_BASE + 0x24C)
+#define DVFSRC_MD_BW_4                   (DVFSRC_BASE + 0x250)
+#define DVFSRC_MD_BW_5                   (DVFSRC_BASE + 0x254)
+#define DVFSRC_MD_BW_6                   (DVFSRC_BASE + 0x258)
+#define DVFSRC_MD_BW_7                   (DVFSRC_BASE + 0x25C)
+#define DVFSRC_SW_BW_0                   (DVFSRC_BASE + 0x260)
+#define DVFSRC_SW_BW_1                   (DVFSRC_BASE + 0x264)
+#define DVFSRC_SW_BW_2                   (DVFSRC_BASE + 0x268)
+#define DVFSRC_SW_BW_3                   (DVFSRC_BASE + 0x26C)
+#define DVFSRC_SW_BW_4                   (DVFSRC_BASE + 0x270)
+#define DVFSRC_SW_BW_5                   (DVFSRC_BASE + 0x274)
+#define DVFSRC_SW_BW_6                   (DVFSRC_BASE + 0x278)
+#define DVFSRC_QOS_EN                    (DVFSRC_BASE + 0x280)
+#define DVFSRC_MD_BW_URG                 (DVFSRC_BASE + 0x284)
+#define DVFSRC_ISP_HRT                   (DVFSRC_BASE + 0x290)
+#define DVFSRC_HRT_BW_BASE               (DVFSRC_BASE + 0x294)
+#define DVFSRC_SEC_SW_REQ                (DVFSRC_BASE + 0x304)
+#define DVFSRC_EMI_MON_DEBOUNCE_TIME     (DVFSRC_BASE + 0x308)
+#define DVFSRC_MD_LATENCY_IMPROVE        (DVFSRC_BASE + 0x30C)
+#define DVFSRC_BASIC_CONTROL_3           (DVFSRC_BASE + 0x310)
+#define DVFSRC_DEBOUNCE_TIME             (DVFSRC_BASE + 0x314)
+#define DVFSRC_LEVEL_MASK                (DVFSRC_BASE + 0x318)
+#define DVFSRC_DEFAULT_OPP               (DVFSRC_BASE + 0x31C)
+#define DVFSRC_95MD_SCEN_EMI0            (DVFSRC_BASE + 0x500)
+#define DVFSRC_95MD_SCEN_EMI1            (DVFSRC_BASE + 0x504)
+#define DVFSRC_95MD_SCEN_EMI2            (DVFSRC_BASE + 0x508)
+#define DVFSRC_95MD_SCEN_EMI3            (DVFSRC_BASE + 0x50C)
+#define DVFSRC_95MD_SCEN_EMI0_T          (DVFSRC_BASE + 0x510)
+#define DVFSRC_95MD_SCEN_EMI1_T          (DVFSRC_BASE + 0x514)
+#define DVFSRC_95MD_SCEN_EMI2_T          (DVFSRC_BASE + 0x518)
+#define DVFSRC_95MD_SCEN_EMI3_T          (DVFSRC_BASE + 0x51C)
+#define DVFSRC_95MD_SCEN_EMI4            (DVFSRC_BASE + 0x520)
+#define DVFSRC_95MD_SCEN_BW0             (DVFSRC_BASE + 0x524)
+#define DVFSRC_95MD_SCEN_BW1             (DVFSRC_BASE + 0x528)
+#define DVFSRC_95MD_SCEN_BW2             (DVFSRC_BASE + 0x52C)
+#define DVFSRC_95MD_SCEN_BW3             (DVFSRC_BASE + 0x530)
+#define DVFSRC_95MD_SCEN_BW0_T           (DVFSRC_BASE + 0x534)
+#define DVFSRC_95MD_SCEN_BW1_T           (DVFSRC_BASE + 0x538)
+#define DVFSRC_95MD_SCEN_BW2_T           (DVFSRC_BASE + 0x53C)
+#define DVFSRC_95MD_SCEN_BW3_T           (DVFSRC_BASE + 0x540)
+#define DVFSRC_95MD_SCEN_BW4             (DVFSRC_BASE + 0x544)
+#define DVFSRC_MD_LEVEL_SW_REG           (DVFSRC_BASE + 0x548)
+#define DVFSRC_RSRV_0                    (DVFSRC_BASE + 0x600)
+#define DVFSRC_RSRV_1                    (DVFSRC_BASE + 0x604)
+#define DVFSRC_RSRV_2                    (DVFSRC_BASE + 0x608)
+#define DVFSRC_RSRV_3                    (DVFSRC_BASE + 0x60C)
+#define DVFSRC_RSRV_4                    (DVFSRC_BASE + 0x610)
+#define DVFSRC_RSRV_5                    (DVFSRC_BASE + 0x614)
+#define DVFSRC_SPM_RESEND                (DVFSRC_BASE + 0x630)
+#define DVFSRC_DEBUG_STA_0               (DVFSRC_BASE + 0x700)
+#define DVFSRC_DEBUG_STA_1               (DVFSRC_BASE + 0x704)
+#define DVFSRC_DEBUG_STA_2               (DVFSRC_BASE + 0x708)
+#define DVFSRC_DEBUG_STA_3               (DVFSRC_BASE + 0x70C)
+#define DVFSRC_DEBUG_STA_4               (DVFSRC_BASE + 0x710)
+#define DVFSRC_DEBUG_STA_5               (DVFSRC_BASE + 0x714)
+#define DVFSRC_EMI_REQUEST7              (DVFSRC_BASE + 0x800)
+#define DVFSRC_EMI_HRT_1                 (DVFSRC_BASE + 0x804)
+#define DVFSRC_EMI_HRT2_1                (DVFSRC_BASE + 0x808)
+#define DVFSRC_EMI_HRT3_1                (DVFSRC_BASE + 0x80C)
+#define DVFSRC_EMI_QOS3                  (DVFSRC_BASE + 0x810)
+#define DVFSRC_EMI_QOS4                  (DVFSRC_BASE + 0x814)
+#define DVFSRC_DDR_REQUEST               (DVFSRC_BASE + 0xA00)
+#define DVFSRC_DDR_REQUEST2              (DVFSRC_BASE + 0xA04)
+#define DVFSRC_DDR_REQUEST3              (DVFSRC_BASE + 0xA08)
+#define DVFSRC_DDR_REQUEST4              (DVFSRC_BASE + 0xA0C)
+#define DVFSRC_DDR_REQUEST5              (DVFSRC_BASE + 0xA10)
+#define DVFSRC_DDR_REQUEST6              (DVFSRC_BASE + 0xA14)
+#define DVFSRC_DDR_REQUEST7              (DVFSRC_BASE + 0xA18)
+#define DVFSRC_DDR_HRT                   (DVFSRC_BASE + 0xA1C)
+#define DVFSRC_DDR_HRT2                  (DVFSRC_BASE + 0xA20)
+#define DVFSRC_DDR_HRT3                  (DVFSRC_BASE + 0xA24)
+#define DVFSRC_DDR_HRT_1                 (DVFSRC_BASE + 0xA28)
+#define DVFSRC_DDR_HRT2_1                (DVFSRC_BASE + 0xA2C)
+#define DVFSRC_DDR_HRT3_1                (DVFSRC_BASE + 0xA30)
+#define DVFSRC_DDR_QOS0                  (DVFSRC_BASE + 0xA34)
+#define DVFSRC_DDR_QOS1                  (DVFSRC_BASE + 0xA38)
+#define DVFSRC_DDR_QOS2                  (DVFSRC_BASE + 0xA3C)
+#define DVFSRC_DDR_QOS3                  (DVFSRC_BASE + 0xA40)
+#define DVFSRC_DDR_QOS4                  (DVFSRC_BASE + 0xA44)
+#define DVFSRC_DDR_MD2SPM0               (DVFSRC_BASE + 0xA48)
+#define DVFSRC_DDR_MD2SPM1               (DVFSRC_BASE + 0xA4C)
+#define DVFSRC_DDR_MD2SPM2               (DVFSRC_BASE + 0xA50)
+#define DVFSRC_DDR_MD2SPM0_T             (DVFSRC_BASE + 0xA54)
+#define DVFSRC_DDR_MD2SPM1_T             (DVFSRC_BASE + 0xA58)
+#define DVFSRC_DDR_MD2SPM2_T             (DVFSRC_BASE + 0xA5C)
+#define DVFSRC_HRT_REQ_UNIT              (DVFSRC_BASE + 0xA60)
+#define DVSFRC_HRT_REQ_MD_URG            (DVFSRC_BASE + 0xA64)
+#define DVFSRC_HRT_REQ_MD_BW_0           (DVFSRC_BASE + 0xA68)
+#define DVFSRC_HRT_REQ_MD_BW_1           (DVFSRC_BASE + 0xA6C)
+#define DVFSRC_HRT_REQ_MD_BW_2           (DVFSRC_BASE + 0xA70)
+#define DVFSRC_HRT_REQ_MD_BW_3           (DVFSRC_BASE + 0xA74)
+#define DVFSRC_HRT_REQ_MD_BW_4           (DVFSRC_BASE + 0xA78)
+#define DVFSRC_HRT_REQ_MD_BW_5           (DVFSRC_BASE + 0xA7C)
+#define DVFSRC_HRT_REQ_MD_BW_6           (DVFSRC_BASE + 0xA80)
+#define DVFSRC_HRT_REQ_MD_BW_7           (DVFSRC_BASE + 0xA84)
+#define DVFSRC_HRT1_REQ_MD_BW_0          (DVFSRC_BASE + 0xA88)
+#define DVFSRC_HRT1_REQ_MD_BW_1          (DVFSRC_BASE + 0xA8C)
+#define DVFSRC_HRT1_REQ_MD_BW_2          (DVFSRC_BASE + 0xA90)
+#define DVFSRC_HRT1_REQ_MD_BW_3          (DVFSRC_BASE + 0xA94)
+#define DVFSRC_HRT1_REQ_MD_BW_4          (DVFSRC_BASE + 0xA98)
+#define DVFSRC_HRT1_REQ_MD_BW_5          (DVFSRC_BASE + 0xA9C)
+#define DVFSRC_HRT1_REQ_MD_BW_6          (DVFSRC_BASE + 0xAA0)
+#define DVFSRC_HRT1_REQ_MD_BW_7          (DVFSRC_BASE + 0xAA4)
+#define DVFSRC_HRT_REQ_MD_BW_8           (DVFSRC_BASE + 0xAA8)
+#define DVFSRC_HRT_REQ_MD_BW_9           (DVFSRC_BASE + 0xAAC)
+#define DVFSRC_HRT_REQ_MD_BW_10          (DVFSRC_BASE + 0xAB0)
+#define DVFSRC_HRT1_REQ_MD_BW_8          (DVFSRC_BASE + 0xAB4)
+#define DVFSRC_HRT1_REQ_MD_BW_9          (DVFSRC_BASE + 0xAB8)
+#define DVFSRC_HRT1_REQ_MD_BW_10         (DVFSRC_BASE + 0xABC)
+#define DVFSRC_HRT_REQ_BW_SW_REG         (DVFSRC_BASE + 0xAC0)
+#define DVFSRC_HRT_REQUEST               (DVFSRC_BASE + 0xAC4)
+#define DVFSRC_HRT_HIGH_2                (DVFSRC_BASE + 0xAC8)
+#define DVFSRC_HRT_HIGH_1                (DVFSRC_BASE + 0xACC)
+#define DVFSRC_HRT_HIGH                  (DVFSRC_BASE + 0xAD0)
+#define DVFSRC_HRT_LOW_2                 (DVFSRC_BASE + 0xAD4)
+#define DVFSRC_HRT_LOW_1                 (DVFSRC_BASE + 0xAD8)
+#define DVFSRC_HRT_LOW                   (DVFSRC_BASE + 0xADC)
+#define DVFSRC_DDR_ADD_REQUEST           (DVFSRC_BASE + 0xAE0)
+#define DVFSRC_LAST                      (DVFSRC_BASE + 0xAE4)
+#define DVFSRC_LAST_L                    (DVFSRC_BASE + 0xAE8)
+#define DVFSRC_MD_SCENARIO               (DVFSRC_BASE + 0xAEC)
+#define DVFSRC_RECORD_0_0                (DVFSRC_BASE + 0xAF0)
+#define DVFSRC_RECORD_0_1                (DVFSRC_BASE + 0xAF4)
+#define DVFSRC_RECORD_0_2                (DVFSRC_BASE + 0xAF8)
+#define DVFSRC_RECORD_0_3                (DVFSRC_BASE + 0xAFC)
+#define DVFSRC_RECORD_0_4                (DVFSRC_BASE + 0xB00)
+#define DVFSRC_RECORD_0_5                (DVFSRC_BASE + 0xB04)
+#define DVFSRC_RECORD_0_6                (DVFSRC_BASE + 0xB08)
+#define DVFSRC_RECORD_0_7                (DVFSRC_BASE + 0xB0C)
+#define DVFSRC_RECORD_0_L_0              (DVFSRC_BASE + 0xBF0)
+#define DVFSRC_RECORD_0_L_1              (DVFSRC_BASE + 0xBF4)
+#define DVFSRC_RECORD_0_L_2              (DVFSRC_BASE + 0xBF8)
+#define DVFSRC_RECORD_0_L_3              (DVFSRC_BASE + 0xBFC)
+#define DVFSRC_RECORD_0_L_4              (DVFSRC_BASE + 0xC00)
+#define DVFSRC_RECORD_0_L_5              (DVFSRC_BASE + 0xC04)
+#define DVFSRC_RECORD_0_L_6              (DVFSRC_BASE + 0xC08)
+#define DVFSRC_RECORD_0_L_7              (DVFSRC_BASE + 0xC0C)
+#define DVFSRC_EMI_REQUEST8              (DVFSRC_BASE + 0xCF0)
+#define DVFSRC_DDR_REQUEST8              (DVFSRC_BASE + 0xCF4)
+#define DVFSRC_EMI_HRT_2                 (DVFSRC_BASE + 0xCF8)
+#define DVFSRC_EMI_HRT2_2                (DVFSRC_BASE + 0xCFC)
+#define DVFSRC_EMI_HRT3_2                (DVFSRC_BASE + 0xD00)
+#define DVFSRC_EMI_QOS5                  (DVFSRC_BASE + 0xD04)
+#define DVFSRC_EMI_QOS6                  (DVFSRC_BASE + 0xD08)
+#define DVFSRC_DDR_HRT_2                 (DVFSRC_BASE + 0xD0C)
+#define DVFSRC_DDR_HRT2_2                (DVFSRC_BASE + 0xD10)
+#define DVFSRC_DDR_HRT3_2                (DVFSRC_BASE + 0xD14)
+#define DVFSRC_DDR_QOS5                  (DVFSRC_BASE + 0xD18)
+#define DVFSRC_DDR_QOS6                  (DVFSRC_BASE + 0xD1C)
+#define DVFSRC_VCORE_REQUEST5            (DVFSRC_BASE + 0xD20)
+#define DVFSRC_VCORE_HRT_1               (DVFSRC_BASE + 0xD24)
+#define DVFSRC_VCORE_HRT2_1              (DVFSRC_BASE + 0xD28)
+#define DVFSRC_VCORE_HRT3_1              (DVFSRC_BASE + 0xD2C)
+#define DVFSRC_VCORE_QOS3                (DVFSRC_BASE + 0xD30)
+#define DVFSRC_VCORE_QOS4                (DVFSRC_BASE + 0xD34)
+#define DVFSRC_HRT_HIGH_3                (DVFSRC_BASE + 0xD38)
+#define DVFSRC_HRT_LOW_3                 (DVFSRC_BASE + 0xD3C)
+#define DVFSRC_BASIC_CONTROL_2           (DVFSRC_BASE + 0xD40)
+#define DVFSRC_CURRENT_LEVEL             (DVFSRC_BASE + 0xD44)
+#define DVFSRC_TARGET_LEVEL              (DVFSRC_BASE + 0xD48)
+#define DVFSRC_LEVEL_LABEL_16_17         (DVFSRC_BASE + 0xD4C)
+#define DVFSRC_LEVEL_LABEL_18_19         (DVFSRC_BASE + 0xD50)
+#define DVFSRC_LEVEL_LABEL_20_21         (DVFSRC_BASE + 0xD54)
+#define DVFSRC_LEVEL_LABEL_22_23         (DVFSRC_BASE + 0xD58)
+#define DVFSRC_LEVEL_LABEL_24_25         (DVFSRC_BASE + 0xD5C)
+#define DVFSRC_LEVEL_LABEL_26_27         (DVFSRC_BASE + 0xD60)
+#define DVFSRC_LEVEL_LABEL_28_29         (DVFSRC_BASE + 0xD64)
+#define DVFSRC_LEVEL_LABEL_30_31         (DVFSRC_BASE + 0xD68)
+#define DVFSRC_CURRENT_FORCE             (DVFSRC_BASE + 0xD6C)
+#define DVFSRC_TARGET_FORCE              (DVFSRC_BASE + 0xD70)
+#define DVFSRC_EMI_ADD_REQUEST           (DVFSRC_BASE + 0xD74)
+
+#endif /* __MT_SPM_VCOREFS__H__ */
diff --git a/plat/mediatek/mt8195/include/platform_def.h b/plat/mediatek/mt8195/include/platform_def.h
index b84e73f..44de8eb 100644
--- a/plat/mediatek/mt8195/include/platform_def.h
+++ b/plat/mediatek/mt8195/include/platform_def.h
@@ -31,6 +31,7 @@
 #define VPPSYS1_BASE            (IO_PHYS + 0x04f00000)
 #define VDOSYS0_BASE            (IO_PHYS + 0x0C01A000)
 #define VDOSYS1_BASE            (IO_PHYS + 0x0C100000)
+#define DVFSRC_BASE             (IO_PHYS + 0x00012000)
 
 /*******************************************************************************
  * DP/eDP related constants
@@ -65,6 +66,12 @@
 #define PMIC_WRAP_BASE			(IO_PHYS + 0x00024000)
 
 /*******************************************************************************
+ * EMI MPU related constants
+ ******************************************************************************/
+#define EMI_MPU_BASE		(IO_PHYS + 0x00226000)
+#define SUB_EMI_MPU_BASE	(IO_PHYS + 0x00225000)
+
+/*******************************************************************************
  * System counter frequency related constants
  ******************************************************************************/
 #define SYS_COUNTER_FREQ_IN_TICKS	13000000
diff --git a/plat/mediatek/mt8195/plat_sip_calls.c b/plat/mediatek/mt8195/plat_sip_calls.c
index 99e1eb3..ee36898 100644
--- a/plat/mediatek/mt8195/plat_sip_calls.c
+++ b/plat/mediatek/mt8195/plat_sip_calls.c
@@ -7,6 +7,8 @@
 #include <common/debug.h>
 #include <common/runtime_svc.h>
 #include <mt_dp.h>
+#include <mt_spm.h>
+#include <mt_spm_vcorefs.h>
 #include <mtk_sip_svc.h>
 #include "plat_sip_calls.h"
 
@@ -28,6 +30,11 @@
 		ret = dp_secure_handler(x1, x2, &ret_val);
 		SMC_RET2(handle, ret, ret_val);
 		break;
+	case MTK_SIP_VCORE_CONTROL_ARCH32:
+	case MTK_SIP_VCORE_CONTROL_ARCH64:
+		ret = spm_vcorefs_v2_args(x1, x2, x3, &x4);
+		SMC_RET2(handle, ret, x4);
+		break;
 	default:
 		ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
 		break;
diff --git a/plat/mediatek/mt8195/platform.mk b/plat/mediatek/mt8195/platform.mk
index f4604c4..48a2f72 100644
--- a/plat/mediatek/mt8195/platform.mk
+++ b/plat/mediatek/mt8195/platform.mk
@@ -16,6 +16,7 @@
                  -I${MTK_PLAT}/common/lpm/                        \
                  -I${MTK_PLAT_SOC}/drivers/dcm                    \
                  -I${MTK_PLAT_SOC}/drivers/dp/                    \
+                 -I${MTK_PLAT_SOC}/drivers/emi_mpu/               \
                  -I${MTK_PLAT_SOC}/drivers/gpio/                  \
                  -I${MTK_PLAT_SOC}/drivers/mcdi/                  \
                  -I${MTK_PLAT_SOC}/drivers/pmic/                  \
@@ -60,6 +61,7 @@
                 ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c                 \
                 ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c           \
                 ${MTK_PLAT_SOC}/drivers/dp/mt_dp.c                    \
+                ${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c             \
                 ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c                 \
                 ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm.c              \
                 ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm_cpc.c          \
diff --git a/plat/qti/common/inc/qti_cpu.h b/plat/qti/common/inc/qti_cpu.h
index 3eda02b..3316f7b 100644
--- a/plat/qti/common/inc/qti_cpu.h
+++ b/plat/qti/common/inc/qti_cpu.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,4 +13,10 @@
 /* KRYO-4xx Silver MIDR */
 #define QTI_KRYO4_SILVER_MIDR	0x517F805D
 
+/* KRYO-6xx Gold MIDR */
+#define QTI_KRYO6_GOLD_MIDR	0x412FD410
+
+/* KRYO-6xx Silver MIDR */
+#define QTI_KRYO6_SILVER_MIDR	0x412FD050
+
 #endif /* QTI_CPU_H */
diff --git a/plat/qti/common/src/aarch64/qti_kryo6_gold.S b/plat/qti/common/src/aarch64/qti_kryo6_gold.S
new file mode 100644
index 0000000..db1a304
--- /dev/null
+++ b/plat/qti/common/src/aarch64/qti_kryo6_gold.S
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <cpu_macros.S>
+
+#include <plat_macros.S>
+#include <qti_cpu.h>
+
+	.p2align 3
+
+/* -------------------------------------------------
+ * The CPU Ops reset function for Kryo-3 Gold
+ * -------------------------------------------------
+ */
+func qti_kryo6_gold_reset_func
+#if IMAGE_BL31 && WORKAROUND_CVE_2017_5715
+	adr	x0, wa_cve_2017_5715_bpiall_vbar
+	msr	vbar_el3, x0
+	isb
+#endif
+
+	mov	x19, x30
+
+	bl	qtiseclib_kryo6_gold_reset_asm
+
+	ret	x19
+
+endfunc qti_kryo6_gold_reset_func
+
+/* ----------------------------------------------------
+ * The CPU Ops core power down function for Kryo-3 Gold
+ * ----------------------------------------------------
+ */
+func qti_kryo6_gold_core_pwr_dwn
+	ret
+endfunc qti_kryo6_gold_core_pwr_dwn
+
+/* -------------------------------------------------------
+ * The CPU Ops cluster power down function for Kryo-3 Gold
+ * -------------------------------------------------------
+ */
+func qti_kryo6_gold_cluster_pwr_dwn
+	ret
+endfunc qti_kryo6_gold_cluster_pwr_dwn
+
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Kryo4 Gold. Must follow AAPCS.
+ */
+func qti_kryo6_gold_errata_report
+	/* TODO : Need to add support. Required only for debug bl31 image.*/
+	ret
+endfunc qti_kryo6_gold_errata_report
+#endif
+
+/* ---------------------------------------------
+ * This function provides kryo4_gold specific
+ * register information for crash reporting.
+ * It needs to return with x6 pointing to
+ * a list of register names in ASCII and
+ * x8 - x15 having values of registers to be
+ * reported.
+ * ---------------------------------------------
+ */
+.section .rodata.qti_kryo4_gold_regs, "aS"
+qti_kryo6_gold_regs:  /* The ASCII list of register names to be reported */
+	.asciz	""
+
+func qti_kryo6_gold_cpu_reg_dump
+	adr	x6, qti_kryo6_gold_regs
+	ret
+endfunc qti_kryo6_gold_cpu_reg_dump
+
+declare_cpu_ops	qti_kryo6_gold, QTI_KRYO6_GOLD_MIDR,	\
+		qti_kryo6_gold_reset_func,		\
+		qti_kryo6_gold_core_pwr_dwn,	\
+		qti_kryo6_gold_cluster_pwr_dwn
diff --git a/plat/qti/common/src/aarch64/qti_kryo6_silver.S b/plat/qti/common/src/aarch64/qti_kryo6_silver.S
new file mode 100644
index 0000000..2d189f2
--- /dev/null
+++ b/plat/qti/common/src/aarch64/qti_kryo6_silver.S
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <cpu_macros.S>
+
+#include <plat_macros.S>
+#include <qti_cpu.h>
+
+	.p2align 3
+
+/* -------------------------------------------------
+ * The CPU Ops reset function for Kryo-3 Silver
+ * -------------------------------------------------
+ */
+func qti_kryo6_silver_reset_func
+	mov	x19, x30
+
+	bl	qtiseclib_kryo6_silver_reset_asm
+
+	ret	x19
+
+endfunc qti_kryo6_silver_reset_func
+
+/* ------------------------------------------------------
+ * The CPU Ops core power down function for Kryo-3 Silver
+ * ------------------------------------------------------
+ */
+func qti_kryo6_silver_core_pwr_dwn
+	ret
+endfunc qti_kryo6_silver_core_pwr_dwn
+
+/* ---------------------------------------------------------
+ * The CPU Ops cluster power down function for Kryo-3 Silver
+ * ---------------------------------------------------------
+ */
+func qti_kryo6_silver_cluster_pwr_dwn
+	ret
+endfunc qti_kryo6_silver_cluster_pwr_dwn
+
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Kryo4 Silver. Must follow AAPCS.
+ */
+func qti_kryo6_silver_errata_report
+	/* TODO : Need to add support. Required only for debug bl31 image.*/
+	ret
+endfunc qti_kryo6_silver_errata_report
+#endif
+
+
+/* ---------------------------------------------
+ * This function provides kryo4_silver specific
+ * register information for crash reporting.
+ * It needs to return with x6 pointing to
+ * a list of register names in ASCII and
+ * x8 - x15 having values of registers to be
+ * reported.
+ * ---------------------------------------------
+ */
+.section .rodata.qti_kryo4_silver_regs, "aS"
+qti_kryo6_silver_regs:  /* The ASCII list of register names to be reported */
+	.asciz	""
+
+func qti_kryo6_silver_cpu_reg_dump
+	adr	x6, qti_kryo6_silver_regs
+	ret
+endfunc qti_kryo6_silver_cpu_reg_dump
+
+
+declare_cpu_ops	qti_kryo6_silver, QTI_KRYO6_SILVER_MIDR,	\
+		qti_kryo6_silver_reset_func,		\
+		qti_kryo6_silver_core_pwr_dwn,		\
+		qti_kryo6_silver_cluster_pwr_dwn
diff --git a/plat/qti/common/src/qti_gic_v3.c b/plat/qti/common/src/qti_gic_v3.c
index a5e0ae7..f00267a 100644
--- a/plat/qti/common/src/qti_gic_v3.c
+++ b/plat/qti/common/src/qti_gic_v3.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -72,6 +72,16 @@
 	INTR_PROP_DESC(QTISECLIB_INT_ID_MMSS_NOC_ERROR,
 		       GIC_HIGHEST_SEC_PRIORITY, INTR_GROUP0,
 		       GIC_INTR_CFG_EDGE),
+#ifdef QTISECLIB_INT_ID_LPASS_AGNOC_ERROR
+	INTR_PROP_DESC(QTISECLIB_INT_ID_LPASS_AGNOC_ERROR, GIC_HIGHEST_SEC_PRIORITY,
+		       INTR_GROUP0,
+		       GIC_INTR_CFG_EDGE),
+#endif
+#ifdef QTISECLIB_INT_ID_NSP_NOC_ERROR
+	INTR_PROP_DESC(QTISECLIB_INT_ID_NSP_NOC_ERROR, GIC_HIGHEST_SEC_PRIORITY,
+		       INTR_GROUP0,
+		       GIC_INTR_CFG_EDGE),
+#endif
 };
 
 const gicv3_driver_data_t qti_gic_data = {
diff --git a/plat/qti/common/src/qti_syscall.c b/plat/qti/common/src/qti_syscall.c
index a7601b6..d8e5be9 100644
--- a/plat/qti/common/src/qti_syscall.c
+++ b/plat/qti/common/src/qti_syscall.c
@@ -21,6 +21,7 @@
 #include <qti_plat.h>
 #include <qti_secure_io_cfg.h>
 #include <qtiseclib_interface.h>
+
 /*
  * SIP service - SMC function IDs for SiP Service queries
  *
@@ -29,7 +30,7 @@
 #define	QTI_SIP_SVC_UID_ID				U(0x0200ff01)
 /*							0x8200ff02 is reserved*/
 #define	QTI_SIP_SVC_VERSION_ID				U(0x0200ff03)
-
+#define QTI_SIP_SVC_AVAILABLE_ID			U(0x02000601)
 /*
  * Syscall's to allow Non Secure world accessing peripheral/IO memory
  * those are secure/proteced BUT not required to be secure.
@@ -83,6 +84,22 @@
 	return false;
 }
 
+static bool qti_check_syscall_availability(u_register_t smc_fid)
+{
+	switch (smc_fid) {
+	case QTI_SIP_SVC_CALL_COUNT_ID:
+	case QTI_SIP_SVC_UID_ID:
+	case QTI_SIP_SVC_VERSION_ID:
+	case QTI_SIP_SVC_AVAILABLE_ID:
+	case QTI_SIP_SVC_SECURE_IO_READ_ID:
+	case QTI_SIP_SVC_SECURE_IO_WRITE_ID:
+	case QTI_SIP_SVC_MEM_ASSIGN_ID:
+		return true;
+	default:
+		return false;
+	}
+}
+
 bool qti_mem_assign_validate_param(memprot_info_t *mem_info,
 				   u_register_t u_num_mappings,
 				   uint32_t *source_vm_list,
@@ -315,6 +332,18 @@
 				 QTI_SIP_SVC_VERSION_MINOR);
 			break;
 		}
+	case QTI_SIP_SVC_AVAILABLE_ID:
+		{
+			if (x1 != 1) {
+				SMC_RET1(handle, QTI_SIP_INVALID_PARAM);
+			}
+			if (qti_check_syscall_availability(x2) == true) {
+				SMC_RET2(handle, QTI_SIP_SUCCESS, 1);
+			} else {
+				SMC_RET2(handle, QTI_SIP_SUCCESS, 0);
+			}
+			break;
+		}
 	case QTI_SIP_SVC_SECURE_IO_READ_ID:
 		{
 			if ((x1 == QTI_SIP_SVC_SECURE_IO_READ_PARAM_ID) &&
diff --git a/plat/qti/qtiseclib/inc/qtiseclib_interface.h b/plat/qti/qtiseclib/inc/qtiseclib_interface.h
index 315bd6b..babed1b 100644
--- a/plat/qti/qtiseclib/inc/qtiseclib_interface.h
+++ b/plat/qti/qtiseclib/inc/qtiseclib_interface.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -50,6 +50,14 @@
 void qtiseclib_kryo4_gold_reset_asm(void);
 
 /*
+ * Execute CPU (Kryo46 gold) specific reset handler / system initialization.
+ * This takes care of executing required CPU errata's.
+ *
+ * Clobbers: x0 - x16
+ */
+void qtiseclib_kryo6_gold_reset_asm(void);
+
+/*
  * Execute CPU (Kryo4 silver) specific reset handler / system initialization.
  * This takes care of executing required CPU errata's.
  *
@@ -58,6 +66,14 @@
 void qtiseclib_kryo4_silver_reset_asm(void);
 
 /*
+ * Execute CPU (Kryo6 silver) specific reset handler / system initialization.
+ * This takes care of executing required CPU errata's.
+ *
+ * Clobbers: x0 - x16
+ */
+void qtiseclib_kryo6_silver_reset_asm(void);
+
+/*
  * C Api's
  */
 void qtiseclib_bl31_platform_setup(void);
diff --git a/plat/qti/qtiseclib/inc/sc7280/qtiseclib_defs_plat.h b/plat/qti/qtiseclib/inc/sc7280/qtiseclib_defs_plat.h
new file mode 100644
index 0000000..b3d309f
--- /dev/null
+++ b/plat/qti/qtiseclib/inc/sc7280/qtiseclib_defs_plat.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __QTISECLIB_DEFS_PLAT_H__
+#define __QTISECLIB_DEFS_PLAT_H__
+
+#define QTISECLIB_PLAT_CLUSTER_COUNT	1
+#define QTISECLIB_PLAT_CORE_COUNT	8
+
+#define BL31_BASE						0xC0000000
+#define BL31_SIZE						0x00100000
+
+/*----------------------------------------------------------------------------*/
+/* AOP CMD DB  address space for mapping */
+/*----------------------------------------------------------------------------*/
+#define QTI_AOP_CMD_DB_BASE			0x80860000
+#define QTI_AOP_CMD_DB_SIZE			0x00020000
+
+/* Chipset specific secure interrupt number/ID defs. */
+#define QTISECLIB_INT_ID_SEC_WDOG_BARK			(0x204)
+#define QTISECLIB_INT_ID_NON_SEC_WDOG_BITE		(0x21)
+
+#define QTISECLIB_INT_ID_VMIDMT_ERR_CLT_SEC		(0xE6)
+#define QTISECLIB_INT_ID_VMIDMT_ERR_CLT_NONSEC		(0xE7)
+#define QTISECLIB_INT_ID_VMIDMT_ERR_CFG_SEC		(0xE8)
+#define QTISECLIB_INT_ID_VMIDMT_ERR_CFG_NONSEC		(0xE9)
+
+#define QTISECLIB_INT_ID_XPU_SEC			(0xE3)
+#define QTISECLIB_INT_ID_XPU_NON_SEC			(0xE4)
+
+//NOC INterrupt
+#define QTISECLIB_INT_ID_A1_NOC_ERROR			(0xC9)
+#define QTISECLIB_INT_ID_A2_NOC_ERROR			(0xEA)
+#define QTISECLIB_INT_ID_CONFIG_NOC_ERROR		(0xE2)
+#define QTISECLIB_INT_ID_DC_NOC_ERROR			(0x122)
+#define QTISECLIB_INT_ID_MEM_NOC_ERROR			(0x6C)
+#define QTISECLIB_INT_ID_SYSTEM_NOC_ERROR		(0xC8)
+#define QTISECLIB_INT_ID_MMSS_NOC_ERROR			(0xBA)
+#define QTISECLIB_INT_ID_LPASS_AGNOC_ERROR		(0x143)
+#define QTISECLIB_INT_ID_NSP_NOC_ERROR			(0x1CE)
+
+#endif /* __QTISECLIB_DEFS_PLAT_H__ */
diff --git a/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c b/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c
index bb552c6..c4cd259 100644
--- a/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c
+++ b/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c
@@ -132,6 +132,10 @@
 	void *ctx;
 
 	ctx = cm_get_context(NON_SECURE);
+	if (ctx) {
+		/* nothing to be done w/o ns context */
+		return;
+	}
 
 	qti_ns_ctx->spsr_el3 =
 	    read_ctx_reg(get_el3state_ctx(ctx), CTX_SPSR_EL3);
diff --git a/plat/qti/sc7280/inc/platform_def.h b/plat/qti/sc7280/inc/platform_def.h
new file mode 100644
index 0000000..660cb33
--- /dev/null
+++ b/plat/qti/sc7280/inc/platform_def.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+/* Enable the dynamic translation tables library. */
+#define PLAT_XLAT_TABLES_DYNAMIC	1
+
+#include <common_def.h>
+
+#include <qti_board_def.h>
+#include <qtiseclib_defs_plat.h>
+
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/*
+ * MPIDR_PRIMARY_CPU
+ * You just need to have the correct core_affinity_val i.e. [7:0]
+ * and cluster_affinity_val i.e. [15:8]
+ * the other bits will be ignored
+ */
+/*----------------------------------------------------------------------------*/
+#define MPIDR_PRIMARY_CPU	0x0000
+/*----------------------------------------------------------------------------*/
+
+#define QTI_PWR_LVL0		MPIDR_AFFLVL0
+#define QTI_PWR_LVL1		MPIDR_AFFLVL1
+#define QTI_PWR_LVL2		MPIDR_AFFLVL2
+#define QTI_PWR_LVL3		MPIDR_AFFLVL3
+
+/*
+ *  Macros for local power states encoded by State-ID field
+ *  within the power-state parameter.
+ */
+/* Local power state for power domains in Run state. */
+#define QTI_LOCAL_STATE_RUN	0
+/*
+ * Local power state for clock-gating. Valid only for CPU and not cluster power
+ * domains
+ */
+#define QTI_LOCAL_STATE_STB	1
+/*
+ * Local power state for retention. Valid for CPU and cluster power
+ * domains
+ */
+#define QTI_LOCAL_STATE_RET	2
+/*
+ * Local power state for OFF/power down. Valid for CPU, cluster, RSC and PDC
+ * power domains
+ */
+#define QTI_LOCAL_STATE_OFF	3
+/*
+ * Local power state for DEEPOFF/power rail down. Valid for CPU, cluster and RSC
+ * power domains
+ */
+#define QTI_LOCAL_STATE_DEEPOFF	4
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE	QTI_LOCAL_STATE_RET
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE	QTI_LOCAL_STATE_DEEPOFF
+
+/******************************************************************************
+ * Required platform porting definitions common to all ARM standard platforms
+ *****************************************************************************/
+
+/*
+ * Platform specific page table and MMU setup constants.
+ */
+#define MAX_MMAP_REGIONS	(PLAT_QTI_MMAP_ENTRIES)
+
+#define PLAT_PHY_ADDR_SPACE_SIZE	(1ull << 36)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	(1ull << 36)
+
+#define ARM_CACHE_WRITEBACK_SHIFT	6
+
+/*
+ * Some data must be aligned on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ */
+#define CACHE_WRITEBACK_GRANULE		(1 << ARM_CACHE_WRITEBACK_SHIFT)
+
+/*
+ * One cache line needed for bakery locks on ARM platforms
+ */
+#define PLAT_PERCPU_BAKERY_LOCK_SIZE	(1 * CACHE_WRITEBACK_GRANULE)
+
+/*----------------------------------------------------------------------------*/
+/* PSCI power domain topology definitions */
+/*----------------------------------------------------------------------------*/
+/* One domain each to represent RSC and PDC level */
+#define PLAT_PDC_COUNT			1
+#define PLAT_RSC_COUNT			1
+
+/* There is one top-level FCM cluster */
+#define PLAT_CLUSTER_COUNT		1
+
+/* No. of cores in the FCM cluster */
+#define PLAT_CLUSTER0_CORE_COUNT	8
+
+#define PLATFORM_CORE_COUNT		(PLAT_CLUSTER0_CORE_COUNT)
+
+#define PLAT_NUM_PWR_DOMAINS		(PLAT_PDC_COUNT +\
+					PLAT_RSC_COUNT	+\
+					PLAT_CLUSTER_COUNT	+\
+					PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_PWR_LVL		3
+
+/*****************************************************************************/
+/* Memory mapped Generic timer interfaces  */
+/*****************************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/* GIC-600 constants */
+/*----------------------------------------------------------------------------*/
+#define BASE_GICD_BASE		0x17A00000
+#define BASE_GICR_BASE		0x17A60000
+#define BASE_GICC_BASE		0x0
+#define BASE_GICH_BASE		0x0
+#define BASE_GICV_BASE		0x0
+
+#define QTI_GICD_BASE		BASE_GICD_BASE
+#define QTI_GICR_BASE		BASE_GICR_BASE
+#define QTI_GICC_BASE		BASE_GICC_BASE
+
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
+/* UART related constants. */
+/*----------------------------------------------------------------------------*/
+/* BASE ADDRESS OF DIFFERENT REGISTER SPACES IN HW */
+#define GENI4_CFG				0x0
+#define GENI4_IMAGE_REGS			0x100
+#define GENI4_DATA				0x600
+
+/* COMMON STATUS/CONFIGURATION REGISTERS AND MASKS */
+#define GENI_STATUS_REG				(GENI4_CFG + 0x00000040)
+#define GENI_STATUS_M_GENI_CMD_ACTIVE_MASK	(0x1)
+#define UART_TX_TRANS_LEN_REG			(GENI4_IMAGE_REGS + 0x00000170)
+/* MASTER/TX ENGINE REGISTERS */
+#define GENI_M_CMD0_REG				(GENI4_DATA + 0x00000000)
+/* FIFO, STATUS REGISTERS AND MASKS */
+#define GENI_TX_FIFOn_REG			(GENI4_DATA + 0x00000100)
+
+#define GENI_M_CMD_TX				(0x08000000)
+
+/*----------------------------------------------------------------------------*/
+/* Device address space for mapping. Excluding starting 4K */
+/*----------------------------------------------------------------------------*/
+#define QTI_DEVICE_BASE				0x1000
+#define QTI_DEVICE_SIZE				(0x80000000 - QTI_DEVICE_BASE)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL31 at DDR as per memory map. BL31_BASE is calculated using the
+ * current BL31 debug size plus a little space for growth.
+ */
+#define BL31_LIMIT				(BL31_BASE + BL31_SIZE)
+
+/*----------------------------------------------------------------------------*/
+/* AOSS registers */
+/*----------------------------------------------------------------------------*/
+#define QTI_PS_HOLD_REG				0x0C264000
+/*----------------------------------------------------------------------------*/
+/* AOP CMD DB  address space for mapping */
+/*----------------------------------------------------------------------------*/
+#define QTI_AOP_CMD_DB_BASE			0x80860000
+#define QTI_AOP_CMD_DB_SIZE			0x00020000
+/*----------------------------------------------------------------------------*/
+/* SOC hw version register */
+/*----------------------------------------------------------------------------*/
+#define QTI_SOC_VERSION				U(0x7280)
+#define QTI_SOC_VERSION_MASK			U(0xFFFF)
+#define QTI_SOC_REVISION_REG			0x1FC8000
+#define QTI_SOC_REVISION_MASK			U(0xFFFF)
+/*----------------------------------------------------------------------------*/
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/qti/sc7280/inc/qti_rng_io.h b/plat/qti/sc7280/inc/qti_rng_io.h
new file mode 100644
index 0000000..0f41fd6
--- /dev/null
+++ b/plat/qti/sc7280/inc/qti_rng_io.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef QTI_RNG_IO_H
+#define QTI_RNG_IO_H
+
+#define SEC_PRNG_STATUS			0x10D1004
+#define SEC_PRNG_STATUS_DATA_AVAIL_BMSK	0x1
+#define SEC_PRNG_DATA_OUT		0x10D1000
+
+
+#endif /* QTI_RNG_IO_H */
+
diff --git a/plat/qti/sc7280/inc/qti_secure_io_cfg.h b/plat/qti/sc7280/inc/qti_secure_io_cfg.h
new file mode 100644
index 0000000..058c5b5
--- /dev/null
+++ b/plat/qti/sc7280/inc/qti_secure_io_cfg.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef QTI_SECURE_IO_CFG_H
+#define QTI_SECURE_IO_CFG_H
+
+#include <stdint.h>
+
+/*
+ * List of peripheral/IO memory areas that are protected from
+ * non-secure world but not required to be secure.
+ */
+
+#define APPS_SMMU_TBU_PWR_STATUS		0x15002204
+#define APPS_SMMU_CUSTOM_CFG			0x15002300
+#define APPS_SMMU_STATS_SYNC_INV_TBU_ACK	0x150025DC
+#define APPS_SMMU_SAFE_SEC_CFG			0x15002648
+#define APPS_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR	0x15002670
+
+static const uintptr_t qti_secure_io_allowed_regs[] = {
+	APPS_SMMU_TBU_PWR_STATUS,
+	APPS_SMMU_CUSTOM_CFG,
+	APPS_SMMU_STATS_SYNC_INV_TBU_ACK,
+	APPS_SMMU_SAFE_SEC_CFG,
+	APPS_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR,
+};
+
+#endif /* QTI_SECURE_IO_CFG_H */
diff --git a/plat/qti/sc7280/platform.mk b/plat/qti/sc7280/platform.mk
new file mode 100644
index 0000000..6e26781
--- /dev/null
+++ b/plat/qti/sc7280/platform.mk
@@ -0,0 +1,119 @@
+#
+# Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Make for SC7280 QTI platform.
+
+QTI_PLAT_PATH		:=	plat/qti
+CHIPSET			:=	${PLAT}
+
+# Turn On Separate code & data.
+SEPARATE_CODE_AND_RODATA	:=	1
+USE_COHERENT_MEM		:=	1
+WARMBOOT_ENABLE_DCACHE_EARLY	:=	1
+
+# Disable the PSCI platform compatibility layer
+ENABLE_PLAT_COMPAT		:=	0
+
+# Enable PSCI v1.0 extended state ID format
+PSCI_EXTENDED_STATE_ID	:=  1
+ARM_RECOM_STATE_ID_ENC  :=  1
+
+COLD_BOOT_SINGLE_CPU		:=	1
+PROGRAMMABLE_RESET_ADDRESS	:=	1
+
+RESET_TO_BL31			:=	0
+
+MULTI_CONSOLE_API		:=	1
+
+QTI_SDI_BUILD := 0
+$(eval $(call assert_boolean,QTI_SDI_BUILD))
+$(eval $(call add_define,QTI_SDI_BUILD))
+
+#disable CTX_INCLUDE_AARCH32_REGS to support sc7280 gold cores
+override CTX_INCLUDE_AARCH32_REGS	:=	0
+WORKAROUND_CVE_2017_5715		:=      0
+DYNAMIC_WORKAROUND_CVE_2018_3639	:=      1
+# Enable stack protector.
+ENABLE_STACK_PROTECTOR := strong
+
+
+QTI_EXTERNAL_INCLUDES	:=	-I${QTI_PLAT_PATH}/${CHIPSET}/inc			\
+				-I${QTI_PLAT_PATH}/common/inc				\
+				-I${QTI_PLAT_PATH}/common/inc/$(ARCH)			\
+				-I${QTI_PLAT_PATH}/qtiseclib/inc			\
+				-I${QTI_PLAT_PATH}/qtiseclib/inc/${CHIPSET}			\
+
+QTI_BL31_SOURCES	:=	$(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_helpers.S	\
+				$(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_kryo6_silver.S	\
+				$(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_kryo6_gold.S	\
+				$(QTI_PLAT_PATH)/common/src/$(ARCH)/qti_uart_console.S	\
+				$(QTI_PLAT_PATH)/common/src/pm8998.c			\
+				$(QTI_PLAT_PATH)/common/src/qti_stack_protector.c	\
+				$(QTI_PLAT_PATH)/common/src/qti_common.c		\
+				$(QTI_PLAT_PATH)/common/src/qti_bl31_setup.c		\
+				$(QTI_PLAT_PATH)/common/src/qti_gic_v3.c		\
+				$(QTI_PLAT_PATH)/common/src/qti_interrupt_svc.c		\
+				$(QTI_PLAT_PATH)/common/src/qti_syscall.c		\
+				$(QTI_PLAT_PATH)/common/src/qti_topology.c		\
+				$(QTI_PLAT_PATH)/common/src/qti_pm.c			\
+				$(QTI_PLAT_PATH)/common/src/qti_rng.c			\
+				$(QTI_PLAT_PATH)/common/src/spmi_arb.c			\
+				$(QTI_PLAT_PATH)/qtiseclib/src/qtiseclib_cb_interface.c	\
+
+
+PLAT_INCLUDES		:=	-Iinclude/plat/common/					\
+
+PLAT_INCLUDES		+=	${QTI_EXTERNAL_INCLUDES}
+
+include lib/xlat_tables_v2/xlat_tables.mk
+PLAT_BL_COMMON_SOURCES	+=	${XLAT_TABLES_LIB_SRCS}					\
+				plat/common/aarch64/crash_console_helpers.S    \
+				common/desc_image_load.c			\
+				lib/bl_aux_params/bl_aux_params.c		\
+
+include lib/coreboot/coreboot.mk
+
+#PSCI Sources.
+PSCI_SOURCES		:=	plat/common/plat_psci_common.c				\
+
+# GIC-600 configuration
+GICV3_SUPPORT_GIC600	:=	1
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+#Timer sources
+TIMER_SOURCES		:=	drivers/delay_timer/generic_delay_timer.c	\
+				drivers/delay_timer/delay_timer.c		\
+
+#GIC sources.
+GIC_SOURCES		:=	plat/common/plat_gicv3.c			\
+				${GICV3_SOURCES}				\
+
+BL31_SOURCES		+=	${QTI_BL31_SOURCES}					\
+				${PSCI_SOURCES}						\
+				${GIC_SOURCES}						\
+				${TIMER_SOURCES}					\
+
+LIB_QTI_PATH	:=	${QTI_PLAT_PATH}/qtiseclib/lib/${CHIPSET}
+
+
+# Override this on the command line to point to the qtiseclib library which
+# will be available in coreboot.org
+QTISECLIB_PATH ?=
+
+ifeq ($(QTISECLIB_PATH),)
+# if No lib then use stub implementation for qtiseclib interface
+$(warning QTISECLIB_PATH is not provided while building, using stub implementation. \
+		Please refer docs/plat/qti.rst for more details \
+		THIS FIRMWARE WILL NOT BOOT!)
+BL31_SOURCES	+=	plat/qti/qtiseclib/src/qtiseclib_interface_stub.c
+else
+# use library provided by QTISECLIB_PATH
+LDFLAGS += -L $(dir $(QTISECLIB_PATH))
+LDLIBS += -l$(patsubst lib%.a,%,$(notdir $(QTISECLIB_PATH)))
+endif
+
diff --git a/plat/socionext/synquacer/sq_psci.c b/plat/socionext/synquacer/sq_psci.c
index 0c97fcf..4168df9 100644
--- a/plat/socionext/synquacer/sq_psci.c
+++ b/plat/socionext/synquacer/sq_psci.c
@@ -97,6 +97,14 @@
 void sq_pwr_domain_off(const psci_power_state_t *target_state)
 {
 #if SQ_USE_SCMI_DRIVER
+	/* Prevent interrupts from spuriously waking up this cpu */
+	sq_gic_cpuif_disable();
+
+	/* Cluster is to be turned off, so disable coherency */
+	if (SQ_CLUSTER_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF) {
+		plat_sq_interconnect_exit_coherency();
+	}
+
 	sq_scmi_off(target_state);
 #else
 	sq_power_down_common(target_state);
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
index e603267..7e76083 100644
--- a/plat/st/common/bl2_io_storage.c
+++ b/plat/st/common/bl2_io_storage.c
@@ -7,13 +7,12 @@
 #include <assert.h>
 #include <string.h>
 
-#include <platform_def.h>
-
 #include <arch_helpers.h>
 #include <common/debug.h>
+#include <common/desc_image_load.h>
 #include <drivers/io/io_block.h>
 #include <drivers/io/io_driver.h>
-#include <drivers/io/io_dummy.h>
+#include <drivers/io/io_fip.h>
 #include <drivers/io/io_mtd.h>
 #include <drivers/io/io_storage.h>
 #include <drivers/mmc.h>
@@ -22,34 +21,30 @@
 #include <drivers/spi_nand.h>
 #include <drivers/spi_nor.h>
 #include <drivers/st/io_mmc.h>
-#include <drivers/st/io_stm32image.h>
 #include <drivers/st/stm32_fmc2_nand.h>
 #include <drivers/st/stm32_qspi.h>
 #include <drivers/st/stm32_sdmmc2.h>
+#include <lib/fconf/fconf.h>
 #include <lib/mmio.h>
 #include <lib/utils.h>
 #include <plat/common/platform.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <platform_def.h>
+#include <stm32mp_fconf_getter.h>
 
 /* IO devices */
-#ifndef AARCH32_SP_OPTEE
-static const io_dev_connector_t *dummy_dev_con;
-static uintptr_t dummy_dev_handle;
-static uintptr_t dummy_dev_spec;
-#endif
+uintptr_t fip_dev_handle;
+uintptr_t storage_dev_handle;
 
-static uintptr_t image_dev_handle;
-static uintptr_t storage_dev_handle;
+static const io_dev_connector_t *fip_dev_con;
 
 #if STM32MP_SDMMC || STM32MP_EMMC
 static struct mmc_device_info mmc_info;
-static io_block_spec_t gpt_block_spec = {
-	.offset = 0,
-	.length = 34 * MMC_BLOCK_SIZE, /* Size of GPT table */
-};
 
 static uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE);
 
-static const io_block_dev_spec_t mmc_block_dev_spec = {
+static io_block_dev_spec_t mmc_block_dev_spec = {
 	/* It's used as temp buffer in block driver */
 	.buffer = {
 		.offset = (size_t)&block_buffer,
@@ -62,30 +57,6 @@
 	.block_size = MMC_BLOCK_SIZE,
 };
 
-#if STM32MP_EMMC_BOOT
-static io_block_spec_t emmc_boot_ssbl_block_spec = {
-	.offset = PLAT_EMMC_BOOT_SSBL_OFFSET,
-	.length = MMC_BLOCK_SIZE, /* We are interested only in first 4 bytes */
-};
-
-static const io_block_dev_spec_t mmc_block_dev_boot_part_spec = {
-	/* It's used as temp buffer in block driver */
-	.buffer = {
-		.offset = (size_t)&block_buffer,
-		.length = MMC_BLOCK_SIZE,
-	},
-	.ops = {
-		.read = mmc_boot_part_read_blocks,
-		.write = NULL,
-	},
-	.block_size = MMC_BLOCK_SIZE,
-};
-#endif
-
-static struct io_mmc_dev_spec mmc_device_spec = {
-	.use_boot_part = false,
-};
-
 static const io_dev_connector_t *mmc_dev_con;
 #endif /* STM32MP_SDMMC || STM32MP_EMMC */
 
@@ -103,6 +74,7 @@
 	.ops = {
 		.init = nand_raw_init,
 		.read = nand_read,
+		.seek = nand_seek_bb
 	},
 };
 
@@ -114,6 +86,7 @@
 	.ops = {
 		.init = spi_nand_init,
 		.read = nand_read,
+		.seek = nand_seek_bb
 	},
 };
 #endif
@@ -122,176 +95,21 @@
 static const io_dev_connector_t *spi_dev_con;
 #endif
 
-#ifdef AARCH32_SP_OPTEE
-static const struct stm32image_part_info optee_header_partition_spec = {
-	.name = OPTEE_HEADER_IMAGE_NAME,
-	.binary_type = OPTEE_HEADER_BINARY_TYPE,
-};
-
-static const struct stm32image_part_info optee_core_partition_spec = {
-	.name = OPTEE_CORE_IMAGE_NAME,
-	.binary_type = OPTEE_CORE_BINARY_TYPE,
-};
-
-static const struct stm32image_part_info optee_paged_partition_spec = {
-	.name = OPTEE_PAGED_IMAGE_NAME,
-	.binary_type = OPTEE_PAGED_BINARY_TYPE,
-};
-#else
-static const io_block_spec_t bl32_block_spec = {
-	.offset = BL32_BASE,
-	.length = STM32MP_BL32_SIZE
-};
-#endif
-
-static const struct stm32image_part_info bl33_partition_spec = {
-	.name = BL33_IMAGE_NAME,
-	.binary_type = BL33_BINARY_TYPE,
-};
-
-enum {
-	IMG_IDX_BL33,
-#ifdef AARCH32_SP_OPTEE
-	IMG_IDX_OPTEE_HEADER,
-	IMG_IDX_OPTEE_CORE,
-	IMG_IDX_OPTEE_PAGED,
-#endif
-	IMG_IDX_NUM
-};
-
-static struct stm32image_device_info stm32image_dev_info_spec __unused = {
-	.lba_size = MMC_BLOCK_SIZE,
-	.part_info[IMG_IDX_BL33] = {
-		.name = BL33_IMAGE_NAME,
-		.binary_type = BL33_BINARY_TYPE,
-	},
-#ifdef AARCH32_SP_OPTEE
-	.part_info[IMG_IDX_OPTEE_HEADER] = {
-		.name = OPTEE_HEADER_IMAGE_NAME,
-		.binary_type = OPTEE_HEADER_BINARY_TYPE,
-	},
-	.part_info[IMG_IDX_OPTEE_CORE] = {
-		.name = OPTEE_CORE_IMAGE_NAME,
-		.binary_type = OPTEE_CORE_BINARY_TYPE,
-	},
-	.part_info[IMG_IDX_OPTEE_PAGED] = {
-		.name = OPTEE_PAGED_IMAGE_NAME,
-		.binary_type = OPTEE_PAGED_BINARY_TYPE,
-	},
-#endif
-};
-
-static io_block_spec_t stm32image_block_spec = {
-	.offset = 0,
-	.length = 0,
+io_block_spec_t image_block_spec = {
+	.offset = 0U,
+	.length = 0U,
 };
 
-static const io_dev_connector_t *stm32image_dev_con __unused;
-
-#ifndef AARCH32_SP_OPTEE
-static int open_dummy(const uintptr_t spec);
-#endif
-static int open_image(const uintptr_t spec);
-static int open_storage(const uintptr_t spec);
-
-struct plat_io_policy {
-	uintptr_t *dev_handle;
-	uintptr_t image_spec;
-	int (*check)(const uintptr_t spec);
-};
-
-static const struct plat_io_policy policies[] = {
-#ifdef AARCH32_SP_OPTEE
-	[BL32_IMAGE_ID] = {
-		.dev_handle = &image_dev_handle,
-		.image_spec = (uintptr_t)&optee_header_partition_spec,
-		.check = open_image
-	},
-	[BL32_EXTRA1_IMAGE_ID] = {
-		.dev_handle = &image_dev_handle,
-		.image_spec = (uintptr_t)&optee_core_partition_spec,
-		.check = open_image
-	},
-	[BL32_EXTRA2_IMAGE_ID] = {
-		.dev_handle = &image_dev_handle,
-		.image_spec = (uintptr_t)&optee_paged_partition_spec,
-		.check = open_image
-	},
-#else
-	[BL32_IMAGE_ID] = {
-		.dev_handle = &dummy_dev_handle,
-		.image_spec = (uintptr_t)&bl32_block_spec,
-		.check = open_dummy
-	},
-#endif
-	[BL33_IMAGE_ID] = {
-		.dev_handle = &image_dev_handle,
-		.image_spec = (uintptr_t)&bl33_partition_spec,
-		.check = open_image
-	},
-#if STM32MP_SDMMC || STM32MP_EMMC
-	[GPT_IMAGE_ID] = {
-		.dev_handle = &storage_dev_handle,
-		.image_spec = (uintptr_t)&gpt_block_spec,
-		.check = open_storage
-	},
-#endif
-	[STM32_IMAGE_ID] = {
-		.dev_handle = &storage_dev_handle,
-		.image_spec = (uintptr_t)&stm32image_block_spec,
-		.check = open_storage
-	}
-};
-
-#ifndef AARCH32_SP_OPTEE
-static int open_dummy(const uintptr_t spec)
-{
-	return io_dev_init(dummy_dev_handle, 0);
-}
-#endif
-
-static int open_image(const uintptr_t spec)
+int open_fip(const uintptr_t spec)
 {
-	return io_dev_init(image_dev_handle, 0);
+	return io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
 }
 
-static int open_storage(const uintptr_t spec)
+int open_storage(const uintptr_t spec)
 {
 	return io_dev_init(storage_dev_handle, 0);
 }
 
-#if STM32MP_EMMC_BOOT
-static uint32_t get_boot_part_ssbl_header(void)
-{
-	uint32_t magic = 0;
-	int io_result;
-	size_t bytes_read;
-
-	io_result = register_io_dev_block(&mmc_dev_con);
-	if (io_result != 0) {
-		panic();
-	}
-
-	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_boot_part_spec,
-				&storage_dev_handle);
-	assert(io_result == 0);
-
-	io_result = io_open(storage_dev_handle, (uintptr_t) &emmc_boot_ssbl_block_spec,
-			    &image_dev_handle);
-	assert(io_result == 0);
-
-	io_result = io_read(image_dev_handle, (uintptr_t) &magic, sizeof(magic),
-			    &bytes_read);
-	assert(io_result == 0);
-	assert(bytes_read == sizeof(magic));
-
-	io_result = io_dev_close(storage_dev_handle);
-	assert(io_result == 0);
-
-	return magic;
-}
-#endif
-
 static void print_boot_device(boot_api_context_t *boot_context)
 {
 	switch (boot_context->boot_interface_selected) {
@@ -311,7 +129,8 @@
 		INFO("Using SPI NAND\n");
 		break;
 	default:
-		ERROR("Boot interface not found\n");
+		ERROR("Boot interface %u not found\n",
+		      boot_context->boot_interface_selected);
 		panic();
 		break;
 	}
@@ -321,29 +140,12 @@
 	}
 }
 
-static void stm32image_io_setup(void)
-{
-	int io_result __unused;
-
-	io_result = register_io_dev_stm32image(&stm32image_dev_con);
-	assert(io_result == 0);
-
-	io_result = io_dev_open(stm32image_dev_con,
-				(uintptr_t)&stm32image_dev_info_spec,
-				&image_dev_handle);
-	assert(io_result == 0);
-}
-
 #if STM32MP_SDMMC || STM32MP_EMMC
 static void boot_mmc(enum mmc_device_type mmc_dev_type,
 		     uint16_t boot_interface_instance)
 {
 	int io_result __unused;
-	uint8_t idx;
-	struct stm32image_part_info *part;
 	struct stm32_sdmmc2_params params;
-	const partition_entry_t *entry __unused;
-	uint32_t magic __unused;
 
 	zeromem(&params, sizeof(struct stm32_sdmmc2_params));
 
@@ -375,26 +177,6 @@
 		panic();
 	}
 
-	stm32image_dev_info_spec.device_size =
-		stm32_sdmmc2_mmc_get_device_size();
-
-#if STM32MP_EMMC_BOOT
-	magic = get_boot_part_ssbl_header();
-
-	if (magic == BOOT_API_IMAGE_HEADER_MAGIC_NB) {
-		VERBOSE("%s, header found, jump to emmc load\n", __func__);
-		idx = IMG_IDX_BL33;
-		part = &stm32image_dev_info_spec.part_info[idx];
-		part->part_offset = PLAT_EMMC_BOOT_SSBL_OFFSET;
-		part->bkp_offset = 0U;
-		mmc_device_spec.use_boot_part = true;
-
-		goto emmc_boot;
-	} else {
-		WARN("%s: Can't find STM32 header on a boot partition\n", __func__);
-	}
-#endif
-
 	/* Open MMC as a block device to read GPT table */
 	io_result = register_io_dev_block(&mmc_dev_con);
 	if (io_result != 0) {
@@ -404,37 +186,6 @@
 	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_spec,
 				&storage_dev_handle);
 	assert(io_result == 0);
-
-	partition_init(GPT_IMAGE_ID);
-
-	io_result = io_dev_close(storage_dev_handle);
-	assert(io_result == 0);
-
-	for (idx = 0U; idx < IMG_IDX_NUM; idx++) {
-		part = &stm32image_dev_info_spec.part_info[idx];
-		entry = get_partition_entry(part->name);
-		if (entry == NULL) {
-			ERROR("Partition %s not found\n", part->name);
-			panic();
-		}
-
-		part->part_offset = entry->start;
-		part->bkp_offset = 0U;
-	}
-
-#if STM32MP_EMMC_BOOT
-emmc_boot:
-#endif
-	/*
-	 * Re-open MMC with io_mmc, for better perfs compared to
-	 * io_block.
-	 */
-	io_result = register_io_dev_mmc(&mmc_dev_con);
-	assert(io_result == 0);
-
-	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_device_spec,
-				&storage_dev_handle);
-	assert(io_result == 0);
 }
 #endif /* STM32MP_SDMMC || STM32MP_EMMC */
 
@@ -442,8 +193,6 @@
 static void boot_spi_nor(boot_api_context_t *boot_context)
 {
 	int io_result __unused;
-	uint8_t idx;
-	struct stm32image_part_info *part;
 
 	io_result = stm32_qspi_init();
 	assert(io_result == 0);
@@ -456,30 +205,6 @@
 				(uintptr_t)&spi_nor_dev_spec,
 				&storage_dev_handle);
 	assert(io_result == 0);
-
-	stm32image_dev_info_spec.device_size = spi_nor_dev_spec.device_size;
-
-	idx = IMG_IDX_BL33;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NOR_BL33_OFFSET;
-	part->bkp_offset = 0U;
-
-#ifdef AARCH32_SP_OPTEE
-	idx = IMG_IDX_OPTEE_HEADER;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NOR_TEEH_OFFSET;
-	part->bkp_offset = 0U;
-
-	idx = IMG_IDX_OPTEE_PAGED;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NOR_TEED_OFFSET;
-	part->bkp_offset = 0U;
-
-	idx = IMG_IDX_OPTEE_CORE;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NOR_TEEX_OFFSET;
-	part->bkp_offset = 0U;
-#endif
 }
 #endif /* STM32MP_SPI_NOR */
 
@@ -487,8 +212,6 @@
 static void boot_fmc2_nand(boot_api_context_t *boot_context)
 {
 	int io_result __unused;
-	uint8_t idx;
-	struct stm32image_part_info *part;
 
 	io_result = stm32_fmc2_init();
 	assert(io_result == 0);
@@ -501,30 +224,6 @@
 	io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec,
 				&storage_dev_handle);
 	assert(io_result == 0);
-
-	stm32image_dev_info_spec.device_size = nand_dev_spec.device_size;
-
-	idx = IMG_IDX_BL33;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_BL33_OFFSET;
-	part->bkp_offset = nand_dev_spec.erase_size;
-
-#ifdef AARCH32_SP_OPTEE
-	idx = IMG_IDX_OPTEE_HEADER;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_TEEH_OFFSET;
-	part->bkp_offset = nand_dev_spec.erase_size;
-
-	idx = IMG_IDX_OPTEE_PAGED;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_TEED_OFFSET;
-	part->bkp_offset = nand_dev_spec.erase_size;
-
-	idx = IMG_IDX_OPTEE_CORE;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_TEEX_OFFSET;
-	part->bkp_offset = nand_dev_spec.erase_size;
-#endif
 }
 #endif /* STM32MP_RAW_NAND */
 
@@ -532,8 +231,6 @@
 static void boot_spi_nand(boot_api_context_t *boot_context)
 {
 	int io_result __unused;
-	uint8_t idx;
-	struct stm32image_part_info *part;
 
 	io_result = stm32_qspi_init();
 	assert(io_result == 0);
@@ -546,31 +243,6 @@
 				(uintptr_t)&spi_nand_dev_spec,
 				&storage_dev_handle);
 	assert(io_result == 0);
-
-	stm32image_dev_info_spec.device_size =
-		spi_nand_dev_spec.device_size;
-
-	idx = IMG_IDX_BL33;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_BL33_OFFSET;
-	part->bkp_offset = spi_nand_dev_spec.erase_size;
-
-#ifdef AARCH32_SP_OPTEE
-	idx = IMG_IDX_OPTEE_HEADER;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_TEEH_OFFSET;
-	part->bkp_offset = spi_nand_dev_spec.erase_size;
-
-	idx = IMG_IDX_OPTEE_PAGED;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_TEED_OFFSET;
-	part->bkp_offset = spi_nand_dev_spec.erase_size;
-
-	idx = IMG_IDX_OPTEE_CORE;
-	part = &stm32image_dev_info_spec.part_info[idx];
-	part->part_offset = STM32MP_NAND_TEEX_OFFSET;
-	part->bkp_offset = spi_nand_dev_spec.erase_size;
-#endif
 }
 #endif /* STM32MP_SPI_NAND */
 
@@ -584,53 +256,45 @@
 
 	if ((boot_context->boot_partition_used_toboot == 1U) ||
 	    (boot_context->boot_partition_used_toboot == 2U)) {
-		INFO("Boot used partition fsbl%d\n",
+		INFO("Boot used partition fsbl%u\n",
 		     boot_context->boot_partition_used_toboot);
 	}
 
-#ifndef AARCH32_SP_OPTEE
-	io_result = register_io_dev_dummy(&dummy_dev_con);
+	io_result = register_io_dev_fip(&fip_dev_con);
 	assert(io_result == 0);
 
-	io_result = io_dev_open(dummy_dev_con, dummy_dev_spec,
-				&dummy_dev_handle);
-	assert(io_result == 0);
-#endif
+	io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
+				&fip_dev_handle);
 
 	switch (boot_context->boot_interface_selected) {
 #if STM32MP_SDMMC
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
 		dmbsy();
 		boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance);
-		stm32image_io_setup();
 		break;
 #endif
 #if STM32MP_EMMC
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
 		dmbsy();
 		boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance);
-		stm32image_io_setup();
 		break;
 #endif
 #if STM32MP_SPI_NOR
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
 		dmbsy();
 		boot_spi_nor(boot_context);
-		stm32image_io_setup();
 		break;
 #endif
 #if STM32MP_RAW_NAND
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
 		dmbsy();
 		boot_fmc2_nand(boot_context);
-		stm32image_io_setup();
 		break;
 #endif
 #if STM32MP_SPI_NAND
 	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
 		dmbsy();
 		boot_spi_nand(boot_context);
-		stm32image_io_setup();
 		break;
 #endif
 
@@ -642,6 +306,65 @@
 	}
 }
 
+int bl2_plat_handle_pre_image_load(unsigned int image_id)
+{
+	static bool gpt_init_done __unused;
+	uint16_t boot_itf = stm32mp_get_boot_itf_selected();
+
+	switch (boot_itf) {
+#if STM32MP_SDMMC || STM32MP_EMMC
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
+		if (!gpt_init_done) {
+			const partition_entry_t *entry;
+
+			partition_init(GPT_IMAGE_ID);
+			entry = get_partition_entry(FIP_IMAGE_NAME);
+			if (entry == NULL) {
+				ERROR("Could NOT find the %s partition!\n",
+				      FIP_IMAGE_NAME);
+				return -ENOENT;
+			}
+
+			image_block_spec.offset = entry->start;
+			image_block_spec.length = entry->length;
+
+			gpt_init_done = true;
+		} else {
+			bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+
+			mmc_block_dev_spec.buffer.offset = bl_mem_params->image_info.image_base;
+			mmc_block_dev_spec.buffer.length = bl_mem_params->image_info.image_max_size;
+		}
+
+		break;
+#endif
+
+#if STM32MP_RAW_NAND || STM32MP_SPI_NAND
+#if STM32MP_RAW_NAND
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
+#endif
+#if STM32MP_SPI_NAND
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
+#endif
+		image_block_spec.offset = STM32MP_NAND_FIP_OFFSET;
+		break;
+#endif
+
+#if STM32MP_SPI_NOR
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
+		image_block_spec.offset = STM32MP_NOR_FIP_OFFSET;
+		break;
+#endif
+
+	default:
+		ERROR("FIP Not found\n");
+		panic();
+	}
+
+	return 0;
+}
+
 /*
  * Return an IO device handle and specification which can be used to access
  * an image. Use this to enforce platform load policy.
@@ -652,9 +375,7 @@
 	int rc;
 	const struct plat_io_policy *policy;
 
-	assert(image_id < ARRAY_SIZE(policies));
-
-	policy = &policies[image_id];
+	policy = FCONF_GET_PROPERTY(stm32mp, io_policies, image_id);
 	rc = policy->check(policy->image_spec);
 	if (rc == 0) {
 		*image_spec = policy->image_spec;
diff --git a/plat/st/common/bl2_stm32_io_storage.c b/plat/st/common/bl2_stm32_io_storage.c
new file mode 100644
index 0000000..2d68a50
--- /dev/null
+++ b/plat/st/common/bl2_stm32_io_storage.c
@@ -0,0 +1,665 @@
+/*
+ * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/io/io_block.h>
+#include <drivers/io/io_driver.h>
+#include <drivers/io/io_dummy.h>
+#include <drivers/io/io_mtd.h>
+#include <drivers/io/io_storage.h>
+#include <drivers/mmc.h>
+#include <drivers/partition/partition.h>
+#include <drivers/raw_nand.h>
+#include <drivers/spi_nand.h>
+#include <drivers/spi_nor.h>
+#include <drivers/st/io_mmc.h>
+#include <drivers/st/io_stm32image.h>
+#include <drivers/st/stm32_fmc2_nand.h>
+#include <drivers/st/stm32_qspi.h>
+#include <drivers/st/stm32_sdmmc2.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+
+/* IO devices */
+#ifndef AARCH32_SP_OPTEE
+static const io_dev_connector_t *dummy_dev_con;
+static uintptr_t dummy_dev_handle;
+static uintptr_t dummy_dev_spec;
+#endif
+
+static uintptr_t image_dev_handle;
+static uintptr_t storage_dev_handle;
+
+#if STM32MP_SDMMC || STM32MP_EMMC
+static struct mmc_device_info mmc_info;
+static io_block_spec_t gpt_block_spec = {
+	.offset = 0U,
+	.length = 34U * MMC_BLOCK_SIZE, /* Size of GPT table */
+};
+
+static uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE);
+
+static const io_block_dev_spec_t mmc_block_dev_spec = {
+	/* It's used as temp buffer in block driver */
+	.buffer = {
+		.offset = (size_t)&block_buffer,
+		.length = MMC_BLOCK_SIZE,
+	},
+	.ops = {
+		.read = mmc_read_blocks,
+		.write = NULL,
+	},
+	.block_size = MMC_BLOCK_SIZE,
+};
+
+#if STM32MP_EMMC_BOOT
+static io_block_spec_t emmc_boot_ssbl_block_spec = {
+	.offset = PLAT_EMMC_BOOT_SSBL_OFFSET,
+	.length = MMC_BLOCK_SIZE, /* We are interested only in first 4 bytes */
+};
+
+static const io_block_dev_spec_t mmc_block_dev_boot_part_spec = {
+	/* It's used as temp buffer in block driver */
+	.buffer = {
+		.offset = (size_t)&block_buffer,
+		.length = MMC_BLOCK_SIZE,
+	},
+	.ops = {
+		.read = mmc_boot_part_read_blocks,
+		.write = NULL,
+	},
+	.block_size = MMC_BLOCK_SIZE,
+};
+#endif
+
+static struct io_mmc_dev_spec mmc_device_spec = {
+	.use_boot_part = false,
+};
+
+static const io_dev_connector_t *mmc_dev_con;
+#endif /* STM32MP_SDMMC || STM32MP_EMMC */
+
+#if STM32MP_SPI_NOR
+static io_mtd_dev_spec_t spi_nor_dev_spec = {
+	.ops = {
+		.init = spi_nor_init,
+		.read = spi_nor_read,
+	},
+};
+#endif
+
+#if STM32MP_RAW_NAND
+static io_mtd_dev_spec_t nand_dev_spec = {
+	.ops = {
+		.init = nand_raw_init,
+		.read = nand_read,
+	},
+};
+
+static const io_dev_connector_t *nand_dev_con;
+#endif
+
+#if STM32MP_SPI_NAND
+static io_mtd_dev_spec_t spi_nand_dev_spec = {
+	.ops = {
+		.init = spi_nand_init,
+		.read = nand_read,
+	},
+};
+#endif
+
+#if STM32MP_SPI_NAND || STM32MP_SPI_NOR
+static const io_dev_connector_t *spi_dev_con;
+#endif
+
+#ifdef AARCH32_SP_OPTEE
+static const struct stm32image_part_info optee_header_partition_spec = {
+	.name = OPTEE_HEADER_IMAGE_NAME,
+	.binary_type = OPTEE_HEADER_BINARY_TYPE,
+};
+
+static const struct stm32image_part_info optee_core_partition_spec = {
+	.name = OPTEE_CORE_IMAGE_NAME,
+	.binary_type = OPTEE_CORE_BINARY_TYPE,
+};
+
+static const struct stm32image_part_info optee_paged_partition_spec = {
+	.name = OPTEE_PAGED_IMAGE_NAME,
+	.binary_type = OPTEE_PAGED_BINARY_TYPE,
+};
+#else
+static const io_block_spec_t bl32_block_spec = {
+	.offset = BL32_BASE,
+	.length = STM32MP_BL32_SIZE
+};
+#endif
+
+static const struct stm32image_part_info bl33_partition_spec = {
+	.name = BL33_IMAGE_NAME,
+	.binary_type = BL33_BINARY_TYPE,
+};
+
+enum {
+	IMG_IDX_BL33,
+#ifdef AARCH32_SP_OPTEE
+	IMG_IDX_OPTEE_HEADER,
+	IMG_IDX_OPTEE_CORE,
+	IMG_IDX_OPTEE_PAGED,
+#endif
+	IMG_IDX_NUM
+};
+
+static struct stm32image_device_info stm32image_dev_info_spec __unused = {
+	.lba_size = MMC_BLOCK_SIZE,
+	.part_info[IMG_IDX_BL33] = {
+		.name = BL33_IMAGE_NAME,
+		.binary_type = BL33_BINARY_TYPE,
+	},
+#ifdef AARCH32_SP_OPTEE
+	.part_info[IMG_IDX_OPTEE_HEADER] = {
+		.name = OPTEE_HEADER_IMAGE_NAME,
+		.binary_type = OPTEE_HEADER_BINARY_TYPE,
+	},
+	.part_info[IMG_IDX_OPTEE_CORE] = {
+		.name = OPTEE_CORE_IMAGE_NAME,
+		.binary_type = OPTEE_CORE_BINARY_TYPE,
+	},
+	.part_info[IMG_IDX_OPTEE_PAGED] = {
+		.name = OPTEE_PAGED_IMAGE_NAME,
+		.binary_type = OPTEE_PAGED_BINARY_TYPE,
+	},
+#endif
+};
+
+static io_block_spec_t stm32image_block_spec = {
+	.offset = 0U,
+	.length = 0U,
+};
+
+static const io_dev_connector_t *stm32image_dev_con __unused;
+
+#ifndef AARCH32_SP_OPTEE
+static int open_dummy(const uintptr_t spec);
+#endif
+static int open_image(const uintptr_t spec);
+static int open_storage(const uintptr_t spec);
+
+struct plat_io_policy {
+	uintptr_t *dev_handle;
+	uintptr_t image_spec;
+	int (*check)(const uintptr_t spec);
+};
+
+static const struct plat_io_policy policies[] = {
+#ifdef AARCH32_SP_OPTEE
+	[BL32_IMAGE_ID] = {
+		.dev_handle = &image_dev_handle,
+		.image_spec = (uintptr_t)&optee_header_partition_spec,
+		.check = open_image
+	},
+	[BL32_EXTRA1_IMAGE_ID] = {
+		.dev_handle = &image_dev_handle,
+		.image_spec = (uintptr_t)&optee_core_partition_spec,
+		.check = open_image
+	},
+	[BL32_EXTRA2_IMAGE_ID] = {
+		.dev_handle = &image_dev_handle,
+		.image_spec = (uintptr_t)&optee_paged_partition_spec,
+		.check = open_image
+	},
+#else
+	[BL32_IMAGE_ID] = {
+		.dev_handle = &dummy_dev_handle,
+		.image_spec = (uintptr_t)&bl32_block_spec,
+		.check = open_dummy
+	},
+#endif
+	[BL33_IMAGE_ID] = {
+		.dev_handle = &image_dev_handle,
+		.image_spec = (uintptr_t)&bl33_partition_spec,
+		.check = open_image
+	},
+#if STM32MP_SDMMC || STM32MP_EMMC
+	[GPT_IMAGE_ID] = {
+		.dev_handle = &storage_dev_handle,
+		.image_spec = (uintptr_t)&gpt_block_spec,
+		.check = open_storage
+	},
+#endif
+	[STM32_IMAGE_ID] = {
+		.dev_handle = &storage_dev_handle,
+		.image_spec = (uintptr_t)&stm32image_block_spec,
+		.check = open_storage
+	}
+};
+
+#ifndef AARCH32_SP_OPTEE
+static int open_dummy(const uintptr_t spec)
+{
+	return io_dev_init(dummy_dev_handle, 0);
+}
+#endif
+
+static int open_image(const uintptr_t spec)
+{
+	return io_dev_init(image_dev_handle, 0);
+}
+
+static int open_storage(const uintptr_t spec)
+{
+	return io_dev_init(storage_dev_handle, 0);
+}
+
+#if STM32MP_EMMC_BOOT
+static uint32_t get_boot_part_ssbl_header(void)
+{
+	uint32_t magic = 0U;
+	int io_result;
+	size_t bytes_read;
+
+	io_result = register_io_dev_block(&mmc_dev_con);
+	if (io_result != 0) {
+		panic();
+	}
+
+	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_boot_part_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
+
+	io_result = io_open(storage_dev_handle, (uintptr_t)&emmc_boot_ssbl_block_spec,
+			    &image_dev_handle);
+	assert(io_result == 0);
+
+	io_result = io_read(image_dev_handle, (uintptr_t)&magic, sizeof(magic),
+			    &bytes_read);
+	assert(io_result == 0);
+	assert(bytes_read == sizeof(magic));
+
+	io_result = io_dev_close(storage_dev_handle);
+	assert(io_result == 0);
+
+	return magic;
+}
+#endif
+
+static void print_boot_device(boot_api_context_t *boot_context)
+{
+	switch (boot_context->boot_interface_selected) {
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
+		INFO("Using SDMMC\n");
+		break;
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
+		INFO("Using EMMC\n");
+		break;
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
+		INFO("Using QSPI NOR\n");
+		break;
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
+		INFO("Using FMC NAND\n");
+		break;
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
+		INFO("Using SPI NAND\n");
+		break;
+	default:
+		ERROR("Boot interface not found\n");
+		panic();
+		break;
+	}
+
+	if (boot_context->boot_interface_instance != 0U) {
+		INFO("  Instance %d\n", boot_context->boot_interface_instance);
+	}
+}
+
+static void stm32image_io_setup(void)
+{
+	int io_result __unused;
+
+	io_result = register_io_dev_stm32image(&stm32image_dev_con);
+	assert(io_result == 0);
+
+	io_result = io_dev_open(stm32image_dev_con,
+				(uintptr_t)&stm32image_dev_info_spec,
+				&image_dev_handle);
+	assert(io_result == 0);
+}
+
+#if STM32MP_SDMMC || STM32MP_EMMC
+static void boot_mmc(enum mmc_device_type mmc_dev_type,
+		     uint16_t boot_interface_instance)
+{
+	int io_result __unused;
+	uint8_t idx;
+	struct stm32image_part_info *part;
+	struct stm32_sdmmc2_params params;
+	const partition_entry_t *entry __unused;
+	uint32_t magic __unused;
+
+	zeromem(&params, sizeof(struct stm32_sdmmc2_params));
+
+	mmc_info.mmc_dev_type = mmc_dev_type;
+
+	switch (boot_interface_instance) {
+	case 1:
+		params.reg_base = STM32MP_SDMMC1_BASE;
+		break;
+	case 2:
+		params.reg_base = STM32MP_SDMMC2_BASE;
+		break;
+	case 3:
+		params.reg_base = STM32MP_SDMMC3_BASE;
+		break;
+	default:
+		WARN("SDMMC instance not found, using default\n");
+		if (mmc_dev_type == MMC_IS_SD) {
+			params.reg_base = STM32MP_SDMMC1_BASE;
+		} else {
+			params.reg_base = STM32MP_SDMMC2_BASE;
+		}
+		break;
+	}
+
+	params.device_info = &mmc_info;
+	if (stm32_sdmmc2_mmc_init(&params) != 0) {
+		ERROR("SDMMC%u init failed\n", boot_interface_instance);
+		panic();
+	}
+
+	stm32image_dev_info_spec.device_size =
+		stm32_sdmmc2_mmc_get_device_size();
+
+#if STM32MP_EMMC_BOOT
+	magic = get_boot_part_ssbl_header();
+
+	if (magic == BOOT_API_IMAGE_HEADER_MAGIC_NB) {
+		VERBOSE("%s, header found, jump to emmc load\n", __func__);
+		idx = IMG_IDX_BL33;
+		part = &stm32image_dev_info_spec.part_info[idx];
+		part->part_offset = PLAT_EMMC_BOOT_SSBL_OFFSET;
+		part->bkp_offset = 0U;
+		mmc_device_spec.use_boot_part = true;
+
+		goto emmc_boot;
+	} else {
+		WARN("%s: Can't find STM32 header on a boot partition\n", __func__);
+	}
+#endif
+
+	/* Open MMC as a block device to read GPT table */
+	io_result = register_io_dev_block(&mmc_dev_con);
+	if (io_result != 0) {
+		panic();
+	}
+
+	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
+
+	partition_init(GPT_IMAGE_ID);
+
+	io_result = io_dev_close(storage_dev_handle);
+	assert(io_result == 0);
+
+	for (idx = 0U; idx < IMG_IDX_NUM; idx++) {
+		part = &stm32image_dev_info_spec.part_info[idx];
+		entry = get_partition_entry(part->name);
+		if (entry == NULL) {
+			ERROR("Partition %s not found\n", part->name);
+			panic();
+		}
+
+		part->part_offset = entry->start;
+		part->bkp_offset = 0U;
+	}
+
+#if STM32MP_EMMC_BOOT
+emmc_boot:
+#endif
+	/*
+	 * Re-open MMC with io_mmc, for better perfs compared to
+	 * io_block.
+	 */
+	io_result = register_io_dev_mmc(&mmc_dev_con);
+	assert(io_result == 0);
+
+	io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_device_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
+}
+#endif /* STM32MP_SDMMC || STM32MP_EMMC */
+
+#if STM32MP_SPI_NOR
+static void boot_spi_nor(boot_api_context_t *boot_context)
+{
+	int io_result __unused;
+	uint8_t idx;
+	struct stm32image_part_info *part;
+
+	io_result = stm32_qspi_init();
+	assert(io_result == 0);
+
+	io_result = register_io_dev_mtd(&spi_dev_con);
+	assert(io_result == 0);
+
+	/* Open connections to device */
+	io_result = io_dev_open(spi_dev_con,
+				(uintptr_t)&spi_nor_dev_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
+
+	stm32image_dev_info_spec.device_size = spi_nor_dev_spec.device_size;
+
+	idx = IMG_IDX_BL33;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NOR_BL33_OFFSET;
+	part->bkp_offset = 0U;
+
+#ifdef AARCH32_SP_OPTEE
+	idx = IMG_IDX_OPTEE_HEADER;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NOR_TEEH_OFFSET;
+	part->bkp_offset = 0U;
+
+	idx = IMG_IDX_OPTEE_PAGED;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NOR_TEED_OFFSET;
+	part->bkp_offset = 0U;
+
+	idx = IMG_IDX_OPTEE_CORE;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NOR_TEEX_OFFSET;
+	part->bkp_offset = 0U;
+#endif
+}
+#endif /* STM32MP_SPI_NOR */
+
+#if STM32MP_RAW_NAND
+static void boot_fmc2_nand(boot_api_context_t *boot_context)
+{
+	int io_result __unused;
+	uint8_t idx;
+	struct stm32image_part_info *part;
+
+	io_result = stm32_fmc2_init();
+	assert(io_result == 0);
+
+	/* Register the IO device on this platform */
+	io_result = register_io_dev_mtd(&nand_dev_con);
+	assert(io_result == 0);
+
+	/* Open connections to device */
+	io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
+
+	stm32image_dev_info_spec.device_size = nand_dev_spec.device_size;
+
+	idx = IMG_IDX_BL33;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_BL33_OFFSET;
+	part->bkp_offset = nand_dev_spec.erase_size;
+
+#ifdef AARCH32_SP_OPTEE
+	idx = IMG_IDX_OPTEE_HEADER;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_TEEH_OFFSET;
+	part->bkp_offset = nand_dev_spec.erase_size;
+
+	idx = IMG_IDX_OPTEE_PAGED;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_TEED_OFFSET;
+	part->bkp_offset = nand_dev_spec.erase_size;
+
+	idx = IMG_IDX_OPTEE_CORE;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_TEEX_OFFSET;
+	part->bkp_offset = nand_dev_spec.erase_size;
+#endif
+}
+#endif /* STM32MP_RAW_NAND */
+
+#if STM32MP_SPI_NAND
+static void boot_spi_nand(boot_api_context_t *boot_context)
+{
+	int io_result __unused;
+	uint8_t idx;
+	struct stm32image_part_info *part;
+
+	io_result = stm32_qspi_init();
+	assert(io_result == 0);
+
+	io_result = register_io_dev_mtd(&spi_dev_con);
+	assert(io_result == 0);
+
+	/* Open connections to device */
+	io_result = io_dev_open(spi_dev_con,
+				(uintptr_t)&spi_nand_dev_spec,
+				&storage_dev_handle);
+	assert(io_result == 0);
+
+	stm32image_dev_info_spec.device_size =
+		spi_nand_dev_spec.device_size;
+
+	idx = IMG_IDX_BL33;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_BL33_OFFSET;
+	part->bkp_offset = spi_nand_dev_spec.erase_size;
+
+#ifdef AARCH32_SP_OPTEE
+	idx = IMG_IDX_OPTEE_HEADER;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_TEEH_OFFSET;
+	part->bkp_offset = spi_nand_dev_spec.erase_size;
+
+	idx = IMG_IDX_OPTEE_PAGED;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_TEED_OFFSET;
+	part->bkp_offset = spi_nand_dev_spec.erase_size;
+
+	idx = IMG_IDX_OPTEE_CORE;
+	part = &stm32image_dev_info_spec.part_info[idx];
+	part->part_offset = STM32MP_NAND_TEEX_OFFSET;
+	part->bkp_offset = spi_nand_dev_spec.erase_size;
+#endif
+}
+#endif /* STM32MP_SPI_NAND */
+
+void stm32mp_io_setup(void)
+{
+	int io_result __unused;
+	boot_api_context_t *boot_context =
+		(boot_api_context_t *)stm32mp_get_boot_ctx_address();
+
+	print_boot_device(boot_context);
+
+	if ((boot_context->boot_partition_used_toboot == 1U) ||
+	    (boot_context->boot_partition_used_toboot == 2U)) {
+		INFO("Boot used partition fsbl%u\n",
+		     boot_context->boot_partition_used_toboot);
+	}
+
+#ifndef AARCH32_SP_OPTEE
+	io_result = register_io_dev_dummy(&dummy_dev_con);
+	assert(io_result == 0);
+
+	io_result = io_dev_open(dummy_dev_con, dummy_dev_spec,
+				&dummy_dev_handle);
+	assert(io_result == 0);
+#endif
+
+	switch (boot_context->boot_interface_selected) {
+#if STM32MP_SDMMC
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
+		dmbsy();
+		boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance);
+		stm32image_io_setup();
+		break;
+#endif
+#if STM32MP_EMMC
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
+		dmbsy();
+		boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance);
+		stm32image_io_setup();
+		break;
+#endif
+#if STM32MP_SPI_NOR
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
+		dmbsy();
+		boot_spi_nor(boot_context);
+		stm32image_io_setup();
+		break;
+#endif
+#if STM32MP_RAW_NAND
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
+		dmbsy();
+		boot_fmc2_nand(boot_context);
+		stm32image_io_setup();
+		break;
+#endif
+#if STM32MP_SPI_NAND
+	case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
+		dmbsy();
+		boot_spi_nand(boot_context);
+		stm32image_io_setup();
+		break;
+#endif
+
+	default:
+		ERROR("Boot interface %d not supported\n",
+		      boot_context->boot_interface_selected);
+		panic();
+		break;
+	}
+}
+
+/*
+ * Return an IO device handle and specification which can be used to access
+ * an image. Use this to enforce platform load policy.
+ */
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+			  uintptr_t *image_spec)
+{
+	int rc;
+	const struct plat_io_policy *policy;
+
+	assert(image_id < ARRAY_SIZE(policies));
+
+	policy = &policies[image_id];
+	rc = policy->check(policy->image_spec);
+	if (rc == 0) {
+		*image_spec = policy->image_spec;
+		*dev_handle = *(policy->dev_handle);
+	}
+
+	return rc;
+}
diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h
index edced71..8a5fe48 100644
--- a/plat/st/common/include/stm32mp_common.h
+++ b/plat/st/common/include/stm32mp_common.h
@@ -95,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
@@ -102,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 5e5958b..17ac145 100644
--- a/plat/st/common/stm32mp_common.c
+++ b/plat/st/common/stm32mp_common.c
@@ -76,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;
@@ -109,6 +110,7 @@
 
 	return 0;
 }
+#endif /* STM32MP_USE_STM32IMAGE */
 
 int stm32mp_map_ddr_non_cacheable(void)
 {
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 b4c42fc..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>
@@ -151,11 +155,13 @@
 		panic();
 	}
 
+#if STM32MP_USE_STM32IMAGE
 #ifdef AARCH32_SP_OPTEE
 	INFO("BL2 runs OP-TEE setup\n");
 #else
 	INFO("BL2 runs SP_MIN setup\n");
 #endif
+#endif /* STM32MP_USE_STM32IMAGE */
 }
 
 void bl2_el3_plat_arch_setup(void)
@@ -173,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,
@@ -316,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`.
@@ -329,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);
 
-		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;
+			config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, image_ids[i]);
+			if (config_info == NULL) {
+				continue;
+			}
 
-		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;
+			bl_mem_params->image_info.image_base = config_info->config_addr;
+			bl_mem_params->image_info.image_max_size = config_info->config_max_size;
 
-		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();
+			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;
+
+				/* 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;
+
+			case BL33_IMAGE_ID:
+				bl_mem_params->ep_info.pc = config_info->config_addr;
+				break;
+
+			case HW_CONFIG_ID:
+			case TOS_FW_CONFIG_ID:
+				break;
+
+			default:
+				return -EINVAL;
+			}
 		}
+		break;
+#endif /* !STM32MP_USE_STM32IMAGE */
 
-		/* 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 */
+	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;
+
+			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:
@@ -379,6 +471,19 @@
 		/* Do nothing in default case */
 		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;
 }
@@ -387,4 +492,3 @@
 {
 	stm32mp1_security_setup();
 }
-#endif
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 2ee5f4a..19ef4f0 100644
--- a/plat/st/stm32mp1/stm32mp1_security.c
+++ b/plat/st/stm32mp1/stm32mp1_security.c
@@ -12,21 +12,9 @@
 #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)
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 */