Merge "fix(layerscape): update WA for Errata A-050426" into integration
diff --git a/Makefile b/Makefile
index 1baacf0..fb50f0c 100644
--- a/Makefile
+++ b/Makefile
@@ -945,6 +945,9 @@
 # Variables for use with documentation build using Sphinx tool
 DOCS_PATH		?=	docs
 
+# Defination of SIMICS flag
+SIMICS_BUILD	?=	0
+
 ################################################################################
 # Include BL specific makefiles
 ################################################################################
@@ -1055,6 +1058,7 @@
         ENABLE_FEAT_FGT \
         ENABLE_FEAT_AMUv1 \
         ENABLE_FEAT_ECV \
+        SIMICS_BUILD \
 )))
 
 $(eval $(call assert_numerics,\
@@ -1172,6 +1176,7 @@
         ENABLE_FEAT_FGT \
         ENABLE_FEAT_AMUv1 \
         ENABLE_FEAT_ECV \
+        SIMICS_BUILD \
 )))
 
 ifeq (${SANITIZE_UB},trap)
@@ -1360,7 +1365,7 @@
 	${Q}set MAKEFLAGS= && ${MSVC_NMAKE} /nologo /f ${FIPTOOLPATH}/Makefile.msvc FIPTOOLPATH=$(subst /,\,$(FIPTOOLPATH)) FIPTOOL=$(subst /,\,$(FIPTOOL)) realclean
 endif
 	${Q}${MAKE} --no-print-directory -C ${SPTOOLPATH} clean
-	${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} clean
+	${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} realclean
 	${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${ENCTOOLPATH} realclean
 	${Q}${MAKE} --no-print-directory -C ${ROMLIBPATH} clean
 
diff --git a/changelog.yaml b/changelog.yaml
index 64c935f..fa42e96 100644
--- a/changelog.yaml
+++ b/changelog.yaml
@@ -185,6 +185,13 @@
                 deprecated:
                   - plat/tc0
 
+      - title: Intel
+        scope: intel
+
+        subsections:
+          - title: SoC
+            scope: soc
+
       - title: Marvell
         scope: marvell
 
@@ -738,6 +745,9 @@
           - title: QSPI
             scope: nxp-qspi
 
+          - title: NXP Crypto
+            scope: nxp-crypto
+
       - title: Renesas
         scope: renesas-drivers
 
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index 16c41bd..ad125cf 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -480,6 +480,7 @@
 ^^^^^^^^^^^^^^^^^^^^^^^
 :|M|: Rex-BC Chen <rex-bc.chen@mediatek.com>
 :|G|: `mtk-rex-bc-chen`_
+:|F|: docs/plat/mt\*.rst
 :|F|: plat/mediatek/
 
 Marvell platform ports and SoC drivers
diff --git a/docs/components/realm-management-extension.rst b/docs/components/realm-management-extension.rst
index 2c4e0b8..5fa5140 100644
--- a/docs/components/realm-management-extension.rst
+++ b/docs/components/realm-management-extension.rst
@@ -154,6 +154,8 @@
 
  git clone --recurse-submodules https://git.trustedfirmware.org/hafnium/hafnium.git
  cd hafnium
+ #  Use the default prebuilt LLVM/clang toolchain
+ PATH=$PWD/prebuilts/linux-x64/clang/bin:$PWD/prebuilts/linux-x64/dtc:$PATH
  make PROJECT=reference
 
 The Hafnium binary should be located at
@@ -254,6 +256,8 @@
                                                                 Passed
  > Test suite 'Realm payload tests'
                                                                 Passed
+ > Test suite 'Invalid memory access'
+                                                                Passed
  ...
 
 
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index 6029035..b7d1168 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -29,6 +29,10 @@
    platform contains at least 1 CPU that requires dynamic mitigation.
    Defaults to 0.
 
+-  ``WORKAROUND_CVE_2022_23960``: Enables mitigation for `CVE-2022-23960`_.
+   This build option should be set to 1 if the target platform contains at
+   least 1 CPU that requires this mitigation. Defaults to 1.
+
 .. _arm_cpu_macros_errata_workarounds:
 
 CPU Errata Workarounds
@@ -417,6 +421,10 @@
    Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0
    of the CPU and is fixed in r2p1.
 
+-  ``ERRATA_A710_2282622``: This applies errata 2282622 workaround to
+   Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0
+   of the CPU and is fixed in r2p1.
+
 For Neoverse N2, the following errata build flags are defined :
 
 -  ``ERRATA_N2_2002655``: This applies errata 2002655 workaround to Neoverse-N2
@@ -474,6 +482,38 @@
    Cortex-X2 CPU. This needs to be enabled only for revisions r0p0, r1p0 and
    r2p0 of the CPU, it is fixed in r2p1.
 
+For Cortex-A510, the following errata build flags are defined :
+
+-  ``ERRATA_A510_1922240``: This applies errata 1922240 workaround to
+   Cortex-A510 CPU. This needs to be enabled only for revision r0p0, it is
+   fixed in r0p1.
+
+-  ``ERRATA_A510_2288014``: This applies errata 2288014 workaround to
+   Cortex-A510 CPU. This needs to be enabled only for revisions r0p0, r0p1,
+   r0p2, r0p3 and r1p0, it is fixed in r1p1.
+
+-  ``ERRATA_A510_2042739``: This applies errata 2042739 workaround to
+   Cortex-A510 CPU. This needs to be enabled only for revisions r0p0, r0p1 and
+   r0p2, it is fixed in r0p3.
+
+-  ``ERRATA_A510_2041909``: This applies errata 2041909 workaround to
+   Cortex-A510 CPU. This needs to be enabled only for revision r0p2 and is fixed
+   in r0p3. The issue is also present in r0p0 and r0p1 but there is no
+   workaround for those revisions.
+
+-  ``ERRATA_A510_2250311``: This applies errata 2250311 workaround to
+   Cortex-A510 CPU. This needs to be enabled for revisions r0p0, r0p1, r0p2,
+   r0p3 and r1p0, it is fixed in r1p1. This workaround disables MPMM even if
+   ENABLE_MPMM=1.
+
+-  ``ERRATA_A510_2218950``: This applies errata 2218950 workaround to
+   Cortex-A510 CPU. This needs to be enabled for revisions r0p0, r0p1, r0p2,
+   r0p3 and r1p0, it is fixed in r1p1.
+
+-  ``ERRATA_A510_2172148``: This applies errata 2172148 workaround to
+   Cortex-A510 CPU. This needs to be enabled for revisions r0p0, r0p1, r0p2,
+   r0p3 and r1p0, it is fixed in r1p1.
+
 DSU Errata Workarounds
 ----------------------
 
@@ -549,6 +589,7 @@
 
 .. _CVE-2017-5715: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715
 .. _CVE-2018-3639: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-3639
+.. _CVE-2022-23960: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23960
 .. _Cortex-A53 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm048406/index.html
 .. _Cortex-A57 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm049219/index.html
 .. _Cortex-A72 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm012079/index.html
diff --git a/docs/design_documents/context_mgmt_rework.rst b/docs/design_documents/context_mgmt_rework.rst
new file mode 100644
index 0000000..59f9d4e
--- /dev/null
+++ b/docs/design_documents/context_mgmt_rework.rst
@@ -0,0 +1,197 @@
+Enhance Context Management library for EL3 firmware
+===================================================
+
+:Authors: Soby Mathew & Zelalem Aweke
+:Organization: Arm Limited
+:Contact: Soby Mathew <soby.mathew@arm.com> & Zelalem Aweke <zelalem.aweke@arm.com>
+:Status: RFC
+
+.. contents:: Table of Contents
+
+Introduction
+------------
+The context management library in TF-A provides the basic CPU context
+initialization and management routines for use by different components
+in EL3 firmware. The original design of the library was done keeping in
+mind the 2 world switch and hence this design pattern has been extended to
+keep up with growing requirements of EL3 firmware. With the introduction
+of a new Realm world and a separate Root world for EL3 firmware, it is clear
+that this library needs to be refactored to cater for future enhancements and
+reduce chances of introducing error in code. This also aligns with the overall
+goal of reducing EL3 firmware complexity and footprint.
+
+It is expected that the suggestions below could have legacy implications and
+hence we are mainly targeting SPM/RMM based systems. It is expected that these
+legacy issues will need to be sorted out as part of implementation on a case
+by case basis.
+
+Design Principles
+-----------------
+The below section lays down the design principles for re-factoring the context
+management library :
+
+(1) **Decentralized model for context mgmt**
+
+    Both the Secure and Realm worlds have associated dispatcher component in
+    EL3 firmware to allow management of their respective worlds. Allowing the
+    dispatcher to own the context for their respective world and moving away
+    from a centralized policy management by context management library will
+    remove the world differentiation code in the library. This also means that
+    the library will not be responsible for CPU feature enablement for
+    Secure and Realm worlds. See point 3 and 4 for more details.
+
+    The Non Secure world does not have a dispatcher component and hence EL3
+    firmware (BL31)/context management library needs to have routines to help
+    initialize the Non Secure world context.
+
+(2) **EL3 should only initialize immediate used lower EL**
+
+    Due to the way TF-A evolved, from EL3 interacting with an S-EL1 payload to
+    SPM in S-EL2, there is some code initializing S-EL1 registers which is
+    probably redundant when SPM is present in S-EL2. As a principle, EL3
+    firmware should only initialize the next immediate lower EL in use.
+    If EL2 needs to be skipped and is not to be used at runtime, then
+    EL3 can do the bare minimal EL2 init and init EL1 to prepare for EL3 exit.
+    It is expected that this skip EL2 configuration is only needed for NS
+    world to support legacy Android deployments. It is worth removing this
+    `skip EL2 for Non Secure` config support if this is no longer used.
+
+(3) **Maintain EL3 sysregs which affect lower EL within CPU context**
+
+    The CPU context contains some EL3 sysregs and gets applied on a per-world
+    basis (eg: cptr_el3, scr_el3, zcr_el3 is part of the context
+    because different settings need to be applied between each world).
+    But this design pattern is not enforced in TF-A. It is possible to directly
+    modify EL3 sysreg dynamically during the transition between NS and Secure
+    worlds. Having multiple ways of manipulating EL3 sysregs for different
+    values between the worlds is flaky and error prone. The proposal is to
+    enforce the rule that any EL3 sysreg which can be different between worlds
+    is maintained in the CPU Context. Once the context is initialized the
+    EL3 sysreg values corresponding to the world being entered will be restored.
+
+(4) **Allow more flexibility for Dispatchers to select feature set to save and restore**
+
+    The current functions for EL2 CPU context save and restore is a single
+    function which takes care of saving and restoring all the registers for
+    EL2. This method is inflexible and it does not allow to dynamically detect
+    CPU features to select registers to save and restore. It also assumes that
+    both Realm and Secure world will have the same feature set enabled from
+    EL3 at runtime and makes it hard to enable different features for each
+    world. The framework should cater for selective save and restore of CPU
+    registers which can be controlled by the dispatcher.
+
+    For the implementation, this could mean that there is a separate assembly
+    save and restore routine corresponding to Arch feature. The memory allocation
+    within the CPU Context for each set of registers will be controlled by a
+    FEAT_xxx build option. It is a valid configuration to have
+    context memory allocated but not used at runtime based on feature detection
+    at runtime or the platform owner has decided not to enable the feature
+    for the particular world.
+
+Context Allocation and Initialization
+-------------------------------------
+
+|context_mgmt_abs|
+
+.. |context_mgmt_abs| image::
+   ../resources/diagrams/context_management_abs.png
+
+The above figure shows how the CPU context is allocated within TF-A. The
+allocation for Secure and Realm world is by the respective dispatcher. In the case
+of NS world, the context is allocated by the PSCI lib. This scheme allows TF-A
+to be built in various configurations (with or without Secure/Realm worlds) and
+will result in optimal memory footprint. The Secure and Realm world contexts are
+initialized by invoking context management library APIs which then initialize
+each world based on conditional evaluation of the security state of the
+context. The proposal here is to move the conditional initialization
+of context for Secure and Realm worlds to their respective dispatchers and
+have the library do only the common init needed. The library can export
+helpers to initialize registers corresponding to certain features but
+should not try to do different initialization between the worlds. The library
+can also export helpers for initialization of NS CPU Context since there is no
+dispatcher for that world.
+
+This implies that any world specific code in context mgmt lib should now be
+migrated to the respective "owners". To maintain compatibility with legacy, the
+current functions can be retained in the lib and perhaps define new ones for
+use by SPMD and RMMD. The details of this can be worked out during
+implementation.
+
+Introducing Root Context
+------------------------
+Till now, we have been ignoring the fact that Root world (or EL3) itself could
+have some settings which are distinct from NS/S/Realm worlds. In this case,
+Root world itself would need to maintain some sysregs settings for its own
+execution and would need to use sysregs of lower EL (eg: PAuth, pmcr) to enable
+some functionalities in EL3. The current sequence for context save and restore
+in TF-A is as given below:
+
+|context_mgmt_existing|
+
+.. |context_mgmt_existing| image::
+   ../resources/diagrams/context_mgmt_existing.png
+
+Note1: The EL3 CPU context is not a homogenous collection of EL3 sysregs but
+a collection of EL3 and some other lower EL registers. The save and restore
+is also not done homogenously but based on the objective of using the
+particular register.
+
+Note2: The EL1 context save and restore can possibly be removed when switching
+to S-EL2 as SPM can take care of saving the incoming NS EL1 context.
+
+It can be seen that the EL3 sysreg values applied while the execution is in Root
+world corresponds to the world it came from (eg: if entering EL3 from NS world,
+the sysregs correspond to the values in NS context). There is a case that EL3
+itself may have some settings to apply for various reasons. A good example for
+this is the cptr_el3 regsiter. Although FPU traps need to be disabled for
+Non Secure, Secure and Realm worlds, the EL3 execution itself may keep the trap
+enabled for the sake of robustness. Another example is, if the MTE feature
+is enabled for a particular world, this feature will be enabled for Root world
+as well when entering EL3 from that world. The firmware at EL3 may not
+be expecting this feature to be enabled and may cause unwanted side-effects
+which could be problematic. Thus it would be more robust if Root world is not
+subject to EL3 sysreg values from other worlds but maintains its own values
+which is stable and predictable throughout root world execution.
+
+There is also the case that when EL3 would like to make use of some
+Architectural feature(s) or do some security hardening, it might need
+programming of some lower EL sysregs. For example, if EL3 needs to make
+use of Pointer Authentication (PAuth) feature, it needs to program
+its own PAuth Keys during execution at EL3. Hence EL3 needs its
+own copy of PAuth registers which needs to be restored on every
+entry to EL3. A similar case can be made for DIT bit in PSTATE,
+or use of SP_EL0 for C Runtime Stack at EL3.
+
+The proposal here is to maintain a separate root world CPU context
+which gets applied for Root world execution. This is not the full
+CPU_Context, but subset of EL3 sysregs (`el3_sysreg`) and lower EL
+sysregs (`root_exc_context`) used by EL3. The save and restore
+sequence for this Root context would need to be done in
+an optimal way. The `el3_sysreg` does not need to be saved
+on EL3 Exit and possibly only some registers in `root_exc_context`
+of Root world context would need to be saved on EL3 exit (eg: SP_EL0).
+
+The new sequence for world switch including Root world context would
+be as given below :
+
+|context_mgmt_proposed|
+
+.. |context_mgmt_proposed| image::
+   ../resources/diagrams/context_mgmt_proposed.png
+
+Having this framework in place will allow Root world to make use of lower EL
+registers easily for its own purposes and also have a fixed EL3 sysreg setting
+which is not affected by the settings of other worlds. This will unify the
+Root world register usage pattern for its own execution and remove some
+of the adhoc usages in code.
+
+Conclusion
+----------
+Of all the proposals, the introduction of Root world context would likely need
+further prototyping to confirm the design and we will need to measure the
+performance and memory impact of this change. Other changes are incremental
+improvements which are thought to have negligible impact on EL3 performance.
+
+--------------
+
+*Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/design_documents/index.rst b/docs/design_documents/index.rst
index c82d2ee..257a510 100644
--- a/docs/design_documents/index.rst
+++ b/docs/design_documents/index.rst
@@ -7,6 +7,7 @@
    :numbered:
 
    cmake_framework
+   context_mgmt_rework
    measured_boot_poc
 
 --------------
diff --git a/docs/plat/marvell/armada/build.rst b/docs/plat/marvell/armada/build.rst
index 07848d3..5147cf2 100644
--- a/docs/plat/marvell/armada/build.rst
+++ b/docs/plat/marvell/armada/build.rst
@@ -317,11 +317,19 @@
         Use this parameter to point to the directory with
         compiled Crypto++ library. By default it points to the CRYPTOPP_PATH.
 
+        On Debian systems it is possible to install system-wide Crypto++ library
+        via command ``apt install libcrypto++-dev`` and specify CRYPTOPP_LIBDIR
+        to ``/usr/lib/``.
+
 - CRYPTOPP_INCDIR
 
         Use this parameter to point to the directory with
         header files of Crypto++ library. By default it points to the CRYPTOPP_PATH.
 
+        On Debian systems it is possible to install system-wide Crypto++ library
+        via command ``apt install libcrypto++-dev`` and specify CRYPTOPP_INCDIR
+        to ``/usr/include/crypto++/``.
+
 
 For example, in order to build the image in debug mode with log level up to 'notice' level run
 
diff --git a/docs/plat/stm32mp1.rst b/docs/plat/stm32mp1.rst
index af302c6..cefc21f 100644
--- a/docs/plat/stm32mp1.rst
+++ b/docs/plat/stm32mp1.rst
@@ -115,6 +115,24 @@
 - ``STM32MP_SPI_NAND``
 - ``STM32MP_SPI_NOR``
 
+Serial boot devices:
+
+- ``STM32MP_UART_PROGRAMMER``
+- ``STM32MP_USB_PROGRAMMER``
+
+
+Other configuration flags:
+
+- | ``DTB_FILE_NAME``: to precise board device-tree blob to be used.
+  | Default: stm32mp157c-ev1.dtb
+- | ``STM32MP_EARLY_CONSOLE``: to enable early traces before clock driver is setup.
+  | Default: 0 (disabled)
+- | ``STM32MP_UART_BAUDRATE``: to select UART baud rate.
+  | Default: 115200
+- | ``STM32_TF_VERSION``: to manage BL2 monotonic counter.
+  | Default: 0
+
+
 Boot with FIP
 ~~~~~~~~~~~~~
 You need to build BL2, BL32 (SP_min or OP-TEE) and BL33 (U-Boot) before building FIP binary.
diff --git a/docs/resources/diagrams/context_management_abs.png b/docs/resources/diagrams/context_management_abs.png
new file mode 100644
index 0000000..717ecec
--- /dev/null
+++ b/docs/resources/diagrams/context_management_abs.png
Binary files differ
diff --git a/docs/resources/diagrams/context_mgmt_existing.png b/docs/resources/diagrams/context_mgmt_existing.png
new file mode 100644
index 0000000..5170960
--- /dev/null
+++ b/docs/resources/diagrams/context_mgmt_existing.png
Binary files differ
diff --git a/docs/resources/diagrams/context_mgmt_proposed.png b/docs/resources/diagrams/context_mgmt_proposed.png
new file mode 100644
index 0000000..41ae92f
--- /dev/null
+++ b/docs/resources/diagrams/context_mgmt_proposed.png
Binary files differ
diff --git a/docs/security_advisories/index.rst b/docs/security_advisories/index.rst
index ce2c843..887b06a 100644
--- a/docs/security_advisories/index.rst
+++ b/docs/security_advisories/index.rst
@@ -14,3 +14,4 @@
    security-advisory-tfv-6.rst
    security-advisory-tfv-7.rst
    security-advisory-tfv-8.rst
+   security-advisory-tfv-9.rst
diff --git a/docs/security_advisories/security-advisory-tfv-9.rst b/docs/security_advisories/security-advisory-tfv-9.rst
new file mode 100644
index 0000000..74b85dc
--- /dev/null
+++ b/docs/security_advisories/security-advisory-tfv-9.rst
@@ -0,0 +1,104 @@
+Advisory TFV-9 (CVE-2022-23960)
+============================================================
+
++----------------+-------------------------------------------------------------+
+| Title          | Trusted Firmware-A exposure to speculative processor        |
+|                | vulnerabilities with branch prediction target reuse         |
++================+=============================================================+
+| CVE ID         | `CVE-2022-23960`_                                           |
++----------------+-------------------------------------------------------------+
+| Date           | 08 Mar 2022                                                 |
++----------------+-------------------------------------------------------------+
+| Versions       | All, up to and including v2.6                               |
+| Affected       |                                                             |
++----------------+-------------------------------------------------------------+
+| Configurations | All                                                         |
+| Affected       |                                                             |
++----------------+-------------------------------------------------------------+
+| Impact         | Potential leakage of secure world data to normal world      |
+|                | if an attacker is able to find a TF-A exfiltration primitive|
+|                | that can be predicted as a valid branch target, and somehow |
+|                | induce misprediction onto that primitive. There are         |
+|                | currently no known exploits.                                |
++----------------+-------------------------------------------------------------+
+| Fix Version    | `Gerrit topic #spectre_bhb`_                                |
++----------------+-------------------------------------------------------------+
+| Credit         | Systems and Network Security Group at Vrije Universiteit    |
+|                | Amsterdam for CVE-2022-23960, Arm for patches               |
++----------------+-------------------------------------------------------------+
+
+This security advisory describes the current understanding of the Trusted
+Firmware-A exposure to the new speculative processor vulnerability.
+To understand the background and wider impact of these vulnerabilities on Arm
+systems, please refer to the `Arm Processor Security Update`_. The whitepaper
+referred to below describes the Spectre attack and mitigation in more detail
+including implementation specific mitigation details for all impacted Arm CPUs.
+
+
+`CVE-2022-23960`_
+-----------------
+
+Where possible on vulnerable CPUs that implement FEAT_CSV2, Arm recommends
+inserting a loop workaround with implementation specific number of iterations
+that will discard the branch history on exception entry to a higher exception
+level for the given CPU. This is done as early as possible on entry into EL3,
+before any branch instruction is executed. This is sufficient to mitigate
+Spectre-BHB on behalf of all secure world code, assuming that no secure world
+code is under attacker control.
+
+The below table lists the CPUs that mitigate against this vulnerability in
+TF-A using the loop workaround(all cores that implement FEAT_CSV2 except the
+revisions of Cortex-A73 and Cortex-A75 that implements FEAT_CSV2).
+
++----------------------+
+| Core                 |
++----------------------+
+| Cortex-A72(from r1p0)|
++----------------------+
+| Cortex-A76           |
++----------------------+
+| Cortex-A77           |
++----------------------+
+| Cortex-A78           |
++----------------------+
+| Cortex-X2            |
++----------------------+
+| Cortex-A710          |
++----------------------+
+| Neoverse-N1          |
++----------------------+
+| Neoverse-N2          |
++----------------------+
+| Neoverse-V1          |
++----------------------+
+
+For all other cores impacted by Spectre-BHB, some of which that do not implement
+FEAT_CSV2 and some that do e.g. Cortex-A73, the recommended mitigation is to
+flush all branch predictions via an implementation specific route.
+
+In case local workaround is not feasible, the Rich OS can invoke the SMC
+(``SMCCC_ARCH_WORKAROUND_3``) to apply the workaround. Refer to `SMCCC Calling
+Convention specification`_ for more details.
+
+`Gerrit topic #spectre_bhb`_ This patchset implements the Spectre-BHB loop
+workaround for CPUs mentioned in the above table. It also mitigates against
+this vulnerability for Cortex-A72 CPU versions that support the CSV2 feature
+(from r1p0). The patch stack also includes an implementation for a specified
+`CVE-2022-23960`_ workaround SMC(``SMCCC_ARCH_WORKAROUND_3``) for use by normal
+world privileged software. Details of ``SMCCC_ARCH_WORKAROUND_3`` can be found
+in the `SMCCC Calling Convention specification`_. The specification and
+implementation also enables the normal world to discover the presence of this
+firmware service. This patch also implements ``SMCCC_ARCH_WORKAROUND_3`` for
+Cortex-A57, Coxtex-A72, Cortex-A73 and Cortex-A75 using the existing workaround.
+for CVE-2017-5715.
+
+The above workaround is enabled by default (on vulnerable CPUs only). Platforms
+can choose to disable them at compile time if they do not require them.
+
+For more information about non-Arm CPUs, please contact the CPU vendor.
+
+.. _Arm Processor Security Update: http://www.arm.com/security-update
+.. _CVE-2022-23960: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23960
+.. _Gerrit topic #spectre_bhb: https://review.trustedfirmware.org/q/topic:"spectre_bhb"+(status:open%20OR%20status:merged)
+.. _CVE-2022-23960 mitigation specification: https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability
+.. _SMCCC Calling Convention specification: https://developer.arm.com/documentation/den0028/latest
diff --git a/drivers/auth/dualroot/cot.c b/drivers/auth/dualroot/cot.c
index e1e47bc..8368503 100644
--- a/drivers/auth/dualroot/cot.c
+++ b/drivers/auth/dualroot/cot.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,7 +8,7 @@
 
 #include <platform_def.h>
 
-#include <drivers/auth/mbedtls/mbedtls_config.h>
+#include MBEDTLS_CONFIG_FILE
 #include <drivers/auth/auth_mod.h>
 #include <tools_share/dualroot_oid.h>
 
diff --git a/drivers/auth/mbedtls/mbedtls_common.c b/drivers/auth/mbedtls/mbedtls_common.c
index 4a8efae..a12e49c 100644
--- a/drivers/auth/mbedtls/mbedtls_common.c
+++ b/drivers/auth/mbedtls/mbedtls_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,7 +13,7 @@
 
 #include <common/debug.h>
 #include <drivers/auth/mbedtls/mbedtls_common.h>
-#include <drivers/auth/mbedtls/mbedtls_config.h>
+#include MBEDTLS_CONFIG_FILE
 #include <plat/common/platform.h>
 
 static void cleanup(void)
diff --git a/drivers/auth/mbedtls/mbedtls_common.mk b/drivers/auth/mbedtls/mbedtls_common.mk
index 54c819c..0a4775d 100644
--- a/drivers/auth/mbedtls/mbedtls_common.mk
+++ b/drivers/auth/mbedtls/mbedtls_common.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2021, Arm Limited. All rights reserved.
+# Copyright (c) 2015-2022, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -16,7 +16,7 @@
 MBEDTLS_INC		=	-I${MBEDTLS_DIR}/include
 
 # Specify mbed TLS configuration file
-MBEDTLS_CONFIG_FILE	:=	"<drivers/auth/mbedtls/mbedtls_config.h>"
+MBEDTLS_CONFIG_FILE	?=	"<drivers/auth/mbedtls/mbedtls_config.h>"
 $(eval $(call add_define,MBEDTLS_CONFIG_FILE))
 
 MBEDTLS_SOURCES	+=		drivers/auth/mbedtls/mbedtls_common.c
diff --git a/drivers/auth/tbbr/tbbr_cot_bl1.c b/drivers/auth/tbbr/tbbr_cot_bl1.c
index e4c9221..44f8638 100644
--- a/drivers/auth/tbbr/tbbr_cot_bl1.c
+++ b/drivers/auth/tbbr/tbbr_cot_bl1.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,7 +7,7 @@
 #include <stddef.h>
 
 #include <platform_def.h>
-#include <drivers/auth/mbedtls/mbedtls_config.h>
+#include MBEDTLS_CONFIG_FILE
 
 #include <drivers/auth/auth_mod.h>
 #include <drivers/auth/tbbr_cot_common.h>
diff --git a/drivers/auth/tbbr/tbbr_cot_bl1_r64.c b/drivers/auth/tbbr/tbbr_cot_bl1_r64.c
index e8e017c..78e38f6 100644
--- a/drivers/auth/tbbr/tbbr_cot_bl1_r64.c
+++ b/drivers/auth/tbbr/tbbr_cot_bl1_r64.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,7 +7,7 @@
 #include <stddef.h>
 
 #include <drivers/auth/auth_mod.h>
-#include <drivers/auth/mbedtls/mbedtls_config.h>
+#include MBEDTLS_CONFIG_FILE
 #include <drivers/auth/tbbr_cot_common.h>
 
 #if USE_TBBR_DEFS
diff --git a/drivers/auth/tbbr/tbbr_cot_bl2.c b/drivers/auth/tbbr/tbbr_cot_bl2.c
index 65a0478..11e2f46 100644
--- a/drivers/auth/tbbr/tbbr_cot_bl2.c
+++ b/drivers/auth/tbbr/tbbr_cot_bl2.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,7 +7,7 @@
 #include <stddef.h>
 
 #include <platform_def.h>
-#include <drivers/auth/mbedtls/mbedtls_config.h>
+#include MBEDTLS_CONFIG_FILE
 
 #include <drivers/auth/auth_mod.h>
 #include <drivers/auth/tbbr_cot_common.h>
diff --git a/drivers/auth/tbbr/tbbr_cot_common.c b/drivers/auth/tbbr/tbbr_cot_common.c
index ff3f22d..0983d42 100644
--- a/drivers/auth/tbbr/tbbr_cot_common.c
+++ b/drivers/auth/tbbr/tbbr_cot_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,7 +7,7 @@
 #include <stddef.h>
 
 #include <platform_def.h>
-#include <drivers/auth/mbedtls/mbedtls_config.h>
+#include MBEDTLS_CONFIG_FILE
 
 #include <drivers/auth/auth_mod.h>
 #include <drivers/auth/tbbr_cot_common.h>
diff --git a/drivers/nxp/crypto/caam/src/jobdesc.c b/drivers/nxp/crypto/caam/src/jobdesc.c
index 9c235af..f559c4b 100644
--- a/drivers/nxp/crypto/caam/src/jobdesc.c
+++ b/drivers/nxp/crypto/caam/src/jobdesc.c
@@ -60,8 +60,8 @@
 #ifdef CONFIG_PHYS_64BIT
 	ptr_addr_t *ptr_addr = (ptr_addr_t *) last;
 
-	ptr_addr->m_halves.high = PHYS_ADDR_HI(ptr);
-	ptr_addr->m_halves.low = PHYS_ADDR_LO(ptr);
+	ptr_addr->high = PHYS_ADDR_HI(ptr);
+	ptr_addr->low = PHYS_ADDR_LO(ptr);
 #else
 	*last = ptr;
 #endif
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
index f525741..534ee3b 100644
--- a/drivers/st/clk/stm32mp1_clk.c
+++ b/drivers/st/clk/stm32mp1_clk.c
@@ -1564,7 +1564,7 @@
 	/* Wait PLL lock */
 	while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) {
 		if (timeout_elapsed(timeout)) {
-			ERROR("PLL%d start failed @ 0x%lx: 0x%x\n",
+			ERROR("PLL%u start failed @ 0x%lx: 0x%x\n",
 			      pll_id, pllxcr, mmio_read_32(pllxcr));
 			return -ETIMEDOUT;
 		}
@@ -1593,7 +1593,7 @@
 	/* Wait PLL stopped */
 	while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) {
 		if (timeout_elapsed(timeout)) {
-			ERROR("PLL%d stop failed @ 0x%lx: 0x%x\n",
+			ERROR("PLL%u stop failed @ 0x%lx: 0x%x\n",
 			      pll_id, pllxcr, mmio_read_32(pllxcr));
 			return -ETIMEDOUT;
 		}
@@ -1852,7 +1852,7 @@
 	for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) {
 		char name[12];
 
-		snprintf(name, sizeof(name), "st,pll@%d", i);
+		snprintf(name, sizeof(name), "st,pll@%u", i);
 		plloff[i] = fdt_rcc_subnode_offset(name);
 
 		pllcfg_valid[i] = fdt_check_node(plloff[i]);
@@ -1921,14 +1921,21 @@
 
 	if ((mmio_read_32(rcc_base + RCC_MP_RSTSCLRR) &
 	     RCC_MP_RSTSCLRR_MPUP0RSTF) != 0) {
-		pll3_preserve = stm32mp1_check_pll_conf(_PLL3,
+		if (pllcfg_valid[_PLL3]) {
+			pll3_preserve =
+				stm32mp1_check_pll_conf(_PLL3,
 							clksrc[CLKSRC_PLL3],
 							pllcfg[_PLL3],
 							plloff[_PLL3]);
-		pll4_preserve = stm32mp1_check_pll_conf(_PLL4,
+		}
+
+		if (pllcfg_valid[_PLL4]) {
+			pll4_preserve =
+				stm32mp1_check_pll_conf(_PLL4,
 							clksrc[CLKSRC_PLL4],
 							pllcfg[_PLL4],
 							plloff[_PLL4]);
+		}
 	}
 	/* Don't initialize PLL4, when used by BOOTROM */
 	if ((stm32mp_get_boot_itf_selected() ==
diff --git a/drivers/st/pmic/stm32mp_pmic.c b/drivers/st/pmic/stm32mp_pmic.c
index 0139661..7030cf5 100644
--- a/drivers/st/pmic/stm32mp_pmic.c
+++ b/drivers/st/pmic/stm32mp_pmic.c
@@ -403,7 +403,7 @@
 	}
 }
 
-struct regul_ops pmic_ops = {
+static const struct regul_ops pmic_ops = {
 	.set_state = pmic_set_state,
 	.get_state = pmic_get_state,
 	.set_voltage = pmic_set_voltage,
diff --git a/drivers/st/uart/aarch32/stm32_console.S b/drivers/st/uart/aarch32/stm32_console.S
index 2b8879a..e467f09 100644
--- a/drivers/st/uart/aarch32/stm32_console.S
+++ b/drivers/st/uart/aarch32/stm32_console.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -67,9 +67,24 @@
 	bic	r3, r3, #USART_CR2_STOP
 	str	r3, [r0, #USART_CR2]
 	/* Divisor =  (Uart clock + (baudrate / 2)) / baudrate */
-	lsl	r3, r2, #1
+	lsr	r3, r2, #1
 	add	r3, r1, r3
 	udiv	r3, r3, r2
+	cmp	r3, #16
+	bhi	2f
+	/* Oversampling 8 */
+	/* Divisor =  (2 * Uart clock + (baudrate / 2)) / baudrate */
+	lsr	r3, r2, #1
+	add	r3, r3, r1, lsl #1
+	udiv	r3, r3, r2
+	and	r1, r3, #USART_BRR_DIV_FRACTION
+	lsr	r1, r1, #1
+	bic	r3, r3, #USART_BRR_DIV_FRACTION
+	orr	r3, r3, r1
+	ldr	r1, [r0, #USART_CR1]
+	orr	r1, r1, #USART_CR1_OVER8
+	str	r1, [r0, #USART_CR1]
+2:
 	str	r3, [r0, #USART_BRR]
 	/* Enable UART */
 	ldr	r3, [r0, #USART_CR1]
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index 5c20932..3d6d99f 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -702,7 +702,6 @@
 	       (ufs_params.desc_base != 0) &&
 	       (ufs_params.desc_size >= UFS_DESC_SIZE));
 
-	memset((void *)buf, 0, size);
 	get_utrd(&utrd);
 	ufs_prepare_cmd(&utrd, CDBCMD_READ_10, lun, lba, buf, size);
 	ufs_send_request(utrd.task_tag);
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 009eb90..10b0a0b 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -224,6 +224,7 @@
 DEFINE_SYSOP_PARAM_FUNC(xpaci)
 
 void flush_dcache_range(uintptr_t addr, size_t size);
+void flush_dcache_to_popa_range(uintptr_t addr, size_t size);
 void clean_dcache_range(uintptr_t addr, size_t size);
 void inv_dcache_range(uintptr_t addr, size_t size);
 bool is_dcache_enabled(void);
@@ -274,8 +275,10 @@
 DEFINE_SYSOP_TYPE_FUNC(dmb, st)
 DEFINE_SYSOP_TYPE_FUNC(dmb, ld)
 DEFINE_SYSOP_TYPE_FUNC(dsb, ish)
+DEFINE_SYSOP_TYPE_FUNC(dsb, osh)
 DEFINE_SYSOP_TYPE_FUNC(dsb, nsh)
 DEFINE_SYSOP_TYPE_FUNC(dsb, ishst)
+DEFINE_SYSOP_TYPE_FUNC(dsb, oshst)
 DEFINE_SYSOP_TYPE_FUNC(dmb, oshld)
 DEFINE_SYSOP_TYPE_FUNC(dmb, oshst)
 DEFINE_SYSOP_TYPE_FUNC(dmb, osh)
@@ -610,14 +613,13 @@
 }
 
 /*
- * Invalidate cached copies of GPT entries
- * from TLBs by physical address
+ * Invalidate TLBs of GPT entries by Physical address, last level.
  *
  * @pa: the starting address for the range
  *      of invalidation
  * @size: size of the range of invalidation
  */
-void gpt_tlbi_by_pa(uint64_t pa, size_t size);
+void gpt_tlbi_by_pa_ll(uint64_t pa, size_t size);
 
 
 /* Previously defined accessor functions with incomplete register names  */
diff --git a/include/drivers/measured_boot/event_log/event_log.h b/include/drivers/measured_boot/event_log/event_log.h
index a687d41..0a19f8a 100644
--- a/include/drivers/measured_boot/event_log/event_log.h
+++ b/include/drivers/measured_boot/event_log/event_log.h
@@ -77,6 +77,7 @@
 #define EVLOG_STM32_STRING		"STM32"
 #define EVLOG_TB_FW_CONFIG_STRING	"TB_FW_CONFIG"
 #define	EVLOG_TOS_FW_CONFIG_STRING	"TOS_FW_CONFIG"
+#define EVLOG_RMM_STRING 		"RMM"
 
 typedef struct {
 	unsigned int id;
diff --git a/include/drivers/nxp/crypto/caam/sec_hw_specific.h b/include/drivers/nxp/crypto/caam/sec_hw_specific.h
index a4fc022..9800793 100644
--- a/include/drivers/nxp/crypto/caam/sec_hw_specific.h
+++ b/include/drivers/nxp/crypto/caam/sec_hw_specific.h
@@ -187,9 +187,7 @@
 				((value) & JRINT_JRE)
 
  /* Macros for manipulating JR registers */
-typedef union {
-	uint64_t m_whole;
-	struct {
+typedef struct {
 #ifdef NXP_SEC_BE
 		uint32_t high;
 		uint32_t low;
@@ -197,7 +195,6 @@
 		uint32_t low;
 		uint32_t high;
 #endif
-	} m_halves;
 } ptr_addr_t;
 
 #if defined(CONFIG_PHYS_64BIT)
diff --git a/include/lib/cpus/aarch64/cortex_a510.h b/include/lib/cpus/aarch64/cortex_a510.h
index 6a4cfdf..2b8db14 100644
--- a/include/lib/cpus/aarch64/cortex_a510.h
+++ b/include/lib/cpus/aarch64/cortex_a510.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, ARM Limited. All rights reserved.
+ * Copyright (c) 2022, ARM Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,6 +13,10 @@
  * CPU Extended Control register specific definitions
  ******************************************************************************/
 #define CORTEX_A510_CPUECTLR_EL1				S3_0_C15_C1_4
+#define CORTEX_A510_CPUECTLR_EL1_READPREFERUNIQUE_SHIFT		U(19)
+#define CORTEX_A510_CPUECTLR_EL1_READPREFERUNIQUE_DISABLE	U(1)
+#define CORTEX_A510_CPUECTLR_EL1_RSCTL_SHIFT			U(23)
+#define CORTEX_A510_CPUECTLR_EL1_NTCTL_SHIFT			U(46)
 
 /*******************************************************************************
  * CPU Power Control register specific definitions
@@ -20,4 +24,14 @@
 #define CORTEX_A510_CPUPWRCTLR_EL1				S3_0_C15_C2_7
 #define CORTEX_A510_CPUPWRCTLR_EL1_CORE_PWRDN_BIT		U(1)
 
+/*******************************************************************************
+ * Complex auxiliary control register specific definitions
+ ******************************************************************************/
+#define CORTEX_A510_CMPXACTLR_EL1				S3_0_C15_C1_3
+
+/*******************************************************************************
+ * Auxiliary control register specific definitions
+ ******************************************************************************/
+#define CORTEX_A510_CPUACTLR_EL1				S3_0_C15_C1_0
+
 #endif /* CORTEX_A510_H */
diff --git a/include/lib/cpus/aarch64/cortex_a710.h b/include/lib/cpus/aarch64/cortex_a710.h
index dc56b62..09614ee 100644
--- a/include/lib/cpus/aarch64/cortex_a710.h
+++ b/include/lib/cpus/aarch64/cortex_a710.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,6 +9,9 @@
 
 #define CORTEX_A710_MIDR					U(0x410FD470)
 
+/* Cortex-A710 loop count for CVE-2022-23960 mitigation */
+#define CORTEX_A710_BHB_LOOP_COUNT				U(32)
+
 /*******************************************************************************
  * CPU Extended Control register specific definitions
  ******************************************************************************/
@@ -29,7 +32,12 @@
 #define CORTEX_A710_CPUACTLR_EL1_BIT_22				(ULL(1) << 22)
 
 /*******************************************************************************
- * CPU Auxiliary Control register specific definitions.
+ * CPU Auxiliary Control register 2 specific definitions.
+ ******************************************************************************/
+#define CORTEX_A710_CPUACTLR2_EL1				S3_0_C15_C1_1
+
+/*******************************************************************************
+ * CPU Auxiliary Control register 5 specific definitions.
  ******************************************************************************/
 #define CORTEX_A710_CPUACTLR5_EL1				S3_0_C15_C8_0
 #define CORTEX_A710_CPUACTLR5_EL1_BIT_13			(ULL(1) << 13)
diff --git a/include/lib/cpus/aarch64/cortex_a72.h b/include/lib/cpus/aarch64/cortex_a72.h
index 28b440e..1777645 100644
--- a/include/lib/cpus/aarch64/cortex_a72.h
+++ b/include/lib/cpus/aarch64/cortex_a72.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,6 +12,9 @@
 /* Cortex-A72 midr for revision 0 */
 #define CORTEX_A72_MIDR 				U(0x410FD080)
 
+/* Cortex-A72 loop count for CVE-2022-23960 mitigation */
+#define CORTEX_A72_BHB_LOOP_COUNT			U(8)
+
 /*******************************************************************************
  * CPU Extended Control register specific definitions.
  ******************************************************************************/
diff --git a/include/lib/cpus/aarch64/cortex_a76.h b/include/lib/cpus/aarch64/cortex_a76.h
index a61825f..74fb6e9 100644
--- a/include/lib/cpus/aarch64/cortex_a76.h
+++ b/include/lib/cpus/aarch64/cortex_a76.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,38 +10,41 @@
 #include <lib/utils_def.h>
 
 /* Cortex-A76 MIDR for revision 0 */
-#define CORTEX_A76_MIDR		U(0x410fd0b0)
+#define CORTEX_A76_MIDR						U(0x410fd0b0)
+
+/* Cortex-A76 loop count for CVE-2022-23960 mitigation */
+#define CORTEX_A76_BHB_LOOP_COUNT				U(24)
 
 /*******************************************************************************
  * CPU Extended Control register specific definitions.
  ******************************************************************************/
-#define CORTEX_A76_CPUPWRCTLR_EL1	S3_0_C15_C2_7
-#define CORTEX_A76_CPUECTLR_EL1		S3_0_C15_C1_4
+#define CORTEX_A76_CPUPWRCTLR_EL1				S3_0_C15_C2_7
+#define CORTEX_A76_CPUECTLR_EL1					S3_0_C15_C1_4
 
-#define CORTEX_A76_CPUECTLR_EL1_WS_THR_L2	(ULL(3) << 24)
-#define CORTEX_A76_CPUECTLR_EL1_BIT_51		(ULL(1) << 51)
+#define CORTEX_A76_CPUECTLR_EL1_WS_THR_L2			(ULL(3) << 24)
+#define CORTEX_A76_CPUECTLR_EL1_BIT_51				(ULL(1) << 51)
 
 /*******************************************************************************
  * CPU Auxiliary Control register specific definitions.
  ******************************************************************************/
-#define CORTEX_A76_CPUACTLR_EL1		S3_0_C15_C1_0
+#define CORTEX_A76_CPUACTLR_EL1					S3_0_C15_C1_0
 
 #define CORTEX_A76_CPUACTLR_EL1_DISABLE_STATIC_PREDICTION	(ULL(1) << 6)
 
-#define CORTEX_A76_CPUACTLR_EL1_BIT_13	(ULL(1) << 13)
+#define CORTEX_A76_CPUACTLR_EL1_BIT_13				(ULL(1) << 13)
 
-#define CORTEX_A76_CPUACTLR2_EL1	S3_0_C15_C1_1
+#define CORTEX_A76_CPUACTLR2_EL1				S3_0_C15_C1_1
 
-#define CORTEX_A76_CPUACTLR2_EL1_BIT_2	(ULL(1) << 2)
+#define CORTEX_A76_CPUACTLR2_EL1_BIT_2				(ULL(1) << 2)
 
 #define CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE	(ULL(1) << 16)
 
-#define CORTEX_A76_CPUACTLR3_EL1	S3_0_C15_C1_2
+#define CORTEX_A76_CPUACTLR3_EL1				S3_0_C15_C1_2
 
-#define CORTEX_A76_CPUACTLR3_EL1_BIT_10	(ULL(1) << 10)
+#define CORTEX_A76_CPUACTLR3_EL1_BIT_10				(ULL(1) << 10)
 
 
 /* Definitions of register field mask in CORTEX_A76_CPUPWRCTLR_EL1 */
-#define CORTEX_A76_CORE_PWRDN_EN_MASK	U(0x1)
+#define CORTEX_A76_CORE_PWRDN_EN_MASK				U(0x1)
 
 #endif /* CORTEX_A76_H */
diff --git a/include/lib/cpus/aarch64/cortex_a77.h b/include/lib/cpus/aarch64/cortex_a77.h
index 5753e90..4a87168 100644
--- a/include/lib/cpus/aarch64/cortex_a77.h
+++ b/include/lib/cpus/aarch64/cortex_a77.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,6 +12,9 @@
 /* Cortex-A77 MIDR */
 #define CORTEX_A77_MIDR					U(0x410FD0D0)
 
+/* Cortex-A77 loop count for CVE-2022-23960 mitigation */
+#define CORTEX_A77_BHB_LOOP_COUNT			U(24)
+
 /*******************************************************************************
  * CPU Extended Control register specific definitions.
  ******************************************************************************/
diff --git a/include/lib/cpus/aarch64/cortex_a78.h b/include/lib/cpus/aarch64/cortex_a78.h
index 42b0833..f3cb39f 100644
--- a/include/lib/cpus/aarch64/cortex_a78.h
+++ b/include/lib/cpus/aarch64/cortex_a78.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2021, ARM Limited. All rights reserved.
+ * Copyright (c) 2019-2022, ARM Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,6 +11,9 @@
 
 #define CORTEX_A78_MIDR					U(0x410FD410)
 
+/* Cortex-A78 loop count for CVE-2022-23960 mitigation */
+#define CORTEX_A78_BHB_LOOP_COUNT			U(32)
+
 /*******************************************************************************
  * CPU Extended Control register specific definitions.
  ******************************************************************************/
diff --git a/include/lib/cpus/aarch64/cortex_x2.h b/include/lib/cpus/aarch64/cortex_x2.h
index e3d0fa9..62530e2 100644
--- a/include/lib/cpus/aarch64/cortex_x2.h
+++ b/include/lib/cpus/aarch64/cortex_x2.h
@@ -9,6 +9,9 @@
 
 #define CORTEX_X2_MIDR						U(0x410FD480)
 
+/* Cortex-X2 loop count for CVE-2022-23960 mitigation */
+#define CORTEX_X2_BHB_LOOP_COUNT       				U(32)
+
 /*******************************************************************************
  * CPU Extended Control register specific definitions
  ******************************************************************************/
diff --git a/include/lib/cpus/aarch64/cpu_macros.S b/include/lib/cpus/aarch64/cpu_macros.S
index 92891ce..92e65ae 100644
--- a/include/lib/cpus/aarch64/cpu_macros.S
+++ b/include/lib/cpus/aarch64/cpu_macros.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,6 +21,7 @@
 
 #define CPU_NO_EXTRA1_FUNC		0
 #define CPU_NO_EXTRA2_FUNC		0
+#define CPU_NO_EXTRA3_FUNC		0
 
 /* Word size for 64-bit CPUs */
 #define CPU_WORD_SIZE			8
@@ -39,6 +40,7 @@
 	.equ	CPU_MIDR_SIZE, CPU_WORD_SIZE
 	.equ	CPU_EXTRA1_FUNC_SIZE, CPU_WORD_SIZE
 	.equ	CPU_EXTRA2_FUNC_SIZE, CPU_WORD_SIZE
+	.equ	CPU_EXTRA3_FUNC_SIZE, CPU_WORD_SIZE
 	.equ	CPU_E_HANDLER_FUNC_SIZE, CPU_WORD_SIZE
 	.equ	CPU_RESET_FUNC_SIZE, CPU_WORD_SIZE
 	.equ	CPU_PWR_DWN_OPS_SIZE, CPU_WORD_SIZE * CPU_MAX_PWR_DWN_OPS
@@ -80,7 +82,8 @@
 	.equ	CPU_RESET_FUNC, CPU_MIDR + CPU_MIDR_SIZE
 	.equ	CPU_EXTRA1_FUNC, CPU_RESET_FUNC + CPU_RESET_FUNC_SIZE
 	.equ	CPU_EXTRA2_FUNC, CPU_EXTRA1_FUNC + CPU_EXTRA1_FUNC_SIZE
-	.equ	CPU_E_HANDLER_FUNC, CPU_EXTRA2_FUNC + CPU_EXTRA2_FUNC_SIZE
+	.equ	CPU_EXTRA3_FUNC, CPU_EXTRA2_FUNC + CPU_EXTRA2_FUNC_SIZE
+	.equ	CPU_E_HANDLER_FUNC, CPU_EXTRA3_FUNC + CPU_EXTRA3_FUNC_SIZE
 	.equ	CPU_PWR_DWN_OPS, CPU_E_HANDLER_FUNC + CPU_E_HANDLER_FUNC_SIZE
 	.equ	CPU_ERRATA_FUNC, CPU_PWR_DWN_OPS + CPU_PWR_DWN_OPS_SIZE
 	.equ	CPU_ERRATA_LOCK, CPU_ERRATA_FUNC + CPU_ERRATA_FUNC_SIZE
@@ -134,9 +137,13 @@
 	 *	some CPUs use this entry to set a test function to determine if
 	 *	the workaround for CVE-2017-5715 needs to be applied or not.
 	 * _extra2:
-	 *	This is a placeholder for future per CPU operations.  Currently
+	 *	This is a placeholder for future per CPU operations. Currently
 	 *	some CPUs use this entry to set a function to disable the
 	 *	workaround for CVE-2018-3639.
+	 * _extra3:
+	 *	This is a placeholder for future per CPU operations. Currently,
+	 *	some CPUs use this entry to set a test function to determine if
+	 *	the workaround for CVE-2022-23960 needs to be applied or not.
 	 * _e_handler:
 	 *	This is a placeholder for future per CPU exception handlers.
 	 * _power_down_ops:
@@ -149,7 +156,7 @@
 	 *	used to handle power down at subsequent levels
 	 */
 	.macro declare_cpu_ops_base _name:req, _midr:req, _resetfunc:req, \
-		_extra1:req, _extra2:req, _e_handler:req, _power_down_ops:vararg
+		_extra1:req, _extra2:req, _extra3:req, _e_handler:req, _power_down_ops:vararg
 	.section cpu_ops, "a"
 	.align 3
 	.type cpu_ops_\_name, %object
@@ -159,6 +166,7 @@
 #endif
 	.quad \_extra1
 	.quad \_extra2
+	.quad \_extra3
 	.quad \_e_handler
 #ifdef IMAGE_BL31
 	/* Insert list of functions */
@@ -204,21 +212,21 @@
 
 	.macro declare_cpu_ops _name:req, _midr:req, _resetfunc:req, \
 		_power_down_ops:vararg
-		declare_cpu_ops_base \_name, \_midr, \_resetfunc, 0, 0, 0, \
+		declare_cpu_ops_base \_name, \_midr, \_resetfunc, 0, 0, 0, 0, \
 			\_power_down_ops
 	.endm
 
 	.macro declare_cpu_ops_eh _name:req, _midr:req, _resetfunc:req, \
 		_e_handler:req, _power_down_ops:vararg
 		declare_cpu_ops_base \_name, \_midr, \_resetfunc, \
-			0, 0, \_e_handler, \_power_down_ops
+			0, 0, 0, \_e_handler, \_power_down_ops
 	.endm
 
 	.macro declare_cpu_ops_wa _name:req, _midr:req, \
 		_resetfunc:req, _extra1:req, _extra2:req, \
-		_power_down_ops:vararg
+		_extra3:req, _power_down_ops:vararg
 		declare_cpu_ops_base \_name, \_midr, \_resetfunc, \
-			\_extra1, \_extra2, 0, \_power_down_ops
+			\_extra1, \_extra2, \_extra3, 0, \_power_down_ops
 	.endm
 
 #if REPORT_ERRATA
diff --git a/include/lib/cpus/aarch64/neoverse_n1.h b/include/lib/cpus/aarch64/neoverse_n1.h
index b50befa..b6b8d8d 100644
--- a/include/lib/cpus/aarch64/neoverse_n1.h
+++ b/include/lib/cpus/aarch64/neoverse_n1.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,58 +10,61 @@
 #include <lib/utils_def.h>
 
 /* Neoverse N1 MIDR for revision 0 */
-#define NEOVERSE_N1_MIDR		U(0x410fd0c0)
+#define NEOVERSE_N1_MIDR				U(0x410fd0c0)
+
+/* Neoverse N1 loop count for CVE-2022-23960 mitigation */
+#define NEOVERSE_N1_BHB_LOOP_COUNT			U(24)
 
 /* Exception Syndrome register EC code for IC Trap */
-#define NEOVERSE_N1_EC_IC_TRAP		U(0x1f)
+#define NEOVERSE_N1_EC_IC_TRAP				U(0x1f)
 
 /*******************************************************************************
  * CPU Power Control register specific definitions.
  ******************************************************************************/
-#define NEOVERSE_N1_CPUPWRCTLR_EL1	S3_0_C15_C2_7
+#define NEOVERSE_N1_CPUPWRCTLR_EL1			S3_0_C15_C2_7
 
 /* Definitions of register field mask in NEOVERSE_N1_CPUPWRCTLR_EL1 */
-#define NEOVERSE_N1_CORE_PWRDN_EN_MASK	U(0x1)
+#define NEOVERSE_N1_CORE_PWRDN_EN_MASK			U(0x1)
 
-#define NEOVERSE_N1_ACTLR_AMEN_BIT	(U(1) << 4)
+#define NEOVERSE_N1_ACTLR_AMEN_BIT			(U(1) << 4)
 
-#define NEOVERSE_N1_AMU_NR_COUNTERS	U(5)
-#define NEOVERSE_N1_AMU_GROUP0_MASK	U(0x1f)
+#define NEOVERSE_N1_AMU_NR_COUNTERS			U(5)
+#define NEOVERSE_N1_AMU_GROUP0_MASK			U(0x1f)
 
 /*******************************************************************************
  * CPU Extended Control register specific definitions.
  ******************************************************************************/
-#define NEOVERSE_N1_CPUECTLR_EL1	S3_0_C15_C1_4
+#define NEOVERSE_N1_CPUECTLR_EL1			S3_0_C15_C1_4
 
-#define NEOVERSE_N1_WS_THR_L2_MASK	(ULL(3) << 24)
+#define NEOVERSE_N1_WS_THR_L2_MASK			(ULL(3) << 24)
 #define NEOVERSE_N1_CPUECTLR_EL1_MM_TLBPF_DIS_BIT	(ULL(1) << 51)
 #define NEOVERSE_N1_CPUECTLR_EL1_EXTLLC_BIT		(ULL(1) << 0)
 
 /*******************************************************************************
  * CPU Auxiliary Control register specific definitions.
  ******************************************************************************/
-#define NEOVERSE_N1_CPUACTLR_EL1	S3_0_C15_C1_0
+#define NEOVERSE_N1_CPUACTLR_EL1			S3_0_C15_C1_0
 
-#define NEOVERSE_N1_CPUACTLR_EL1_BIT_6	(ULL(1) << 6)
-#define NEOVERSE_N1_CPUACTLR_EL1_BIT_13	(ULL(1) << 13)
+#define NEOVERSE_N1_CPUACTLR_EL1_BIT_6			(ULL(1) << 6)
+#define NEOVERSE_N1_CPUACTLR_EL1_BIT_13			(ULL(1) << 13)
 
-#define NEOVERSE_N1_CPUACTLR2_EL1	S3_0_C15_C1_1
+#define NEOVERSE_N1_CPUACTLR2_EL1			S3_0_C15_C1_1
 
-#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_0		(ULL(1) << 0)
-#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_2		(ULL(1) << 2)
-#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_11	(ULL(1) << 11)
-#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_15	(ULL(1) << 15)
-#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_16	(ULL(1) << 16)
-#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_59	(ULL(1) << 59)
+#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_0			(ULL(1) << 0)
+#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_2			(ULL(1) << 2)
+#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_11		(ULL(1) << 11)
+#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_15		(ULL(1) << 15)
+#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_16		(ULL(1) << 16)
+#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_59		(ULL(1) << 59)
 
-#define NEOVERSE_N1_CPUACTLR3_EL1	S3_0_C15_C1_2
+#define NEOVERSE_N1_CPUACTLR3_EL1			S3_0_C15_C1_2
 
-#define NEOVERSE_N1_CPUACTLR3_EL1_BIT_10	(ULL(1) << 10)
+#define NEOVERSE_N1_CPUACTLR3_EL1_BIT_10		(ULL(1) << 10)
 
 /* Instruction patching registers */
-#define CPUPSELR_EL3	S3_6_C15_C8_0
-#define CPUPCR_EL3	S3_6_C15_C8_1
-#define CPUPOR_EL3	S3_6_C15_C8_2
-#define CPUPMR_EL3	S3_6_C15_C8_3
+#define CPUPSELR_EL3					S3_6_C15_C8_0
+#define CPUPCR_EL3					S3_6_C15_C8_1
+#define CPUPOR_EL3					S3_6_C15_C8_2
+#define CPUPMR_EL3					S3_6_C15_C8_3
 
 #endif /* NEOVERSE_N1_H */
diff --git a/include/lib/cpus/aarch64/neoverse_n2.h b/include/lib/cpus/aarch64/neoverse_n2.h
index a1e676e..0452b39 100644
--- a/include/lib/cpus/aarch64/neoverse_n2.h
+++ b/include/lib/cpus/aarch64/neoverse_n2.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,6 +10,9 @@
 /* Neoverse N2 ID register for revision r0p0 */
 #define NEOVERSE_N2_MIDR				U(0x410FD490)
 
+/* Neoverse N2 loop count for CVE-2022-23960 mitigation */
+#define NEOVERSE_N2_BHB_LOOP_COUNT			U(32)
+
 /*******************************************************************************
  * CPU Power control register
  ******************************************************************************/
diff --git a/include/lib/cpus/aarch64/neoverse_v1.h b/include/lib/cpus/aarch64/neoverse_v1.h
index e43c907..a904c04 100644
--- a/include/lib/cpus/aarch64/neoverse_v1.h
+++ b/include/lib/cpus/aarch64/neoverse_v1.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2021, ARM Limited. All rights reserved.
+ * Copyright (c) 2019-2022, ARM Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,6 +9,9 @@
 
 #define NEOVERSE_V1_MIDR					U(0x410FD400)
 
+/* Neoverse V1 loop count for CVE-2022-23960 mitigation */
+#define NEOVERSE_V1_BHB_LOOP_COUNT				U(32)
+
 /*******************************************************************************
  * CPU Extended Control register specific definitions.
  ******************************************************************************/
diff --git a/include/lib/cpus/wa_cve_2022_23960.h b/include/lib/cpus/wa_cve_2022_23960.h
new file mode 100644
index 0000000..35b3fd8
--- /dev/null
+++ b/include/lib/cpus/wa_cve_2022_23960.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef WA_CVE_2022_23960_H
+#define WA_CVE_2022_23960_H
+
+int check_smccc_arch_wa3_applies(void);
+
+#endif /* WA_CVE_2022_23960_H */
diff --git a/include/lib/gpt_rme/gpt_rme.h b/include/lib/gpt_rme/gpt_rme.h
index 379b915..94a88b0 100644
--- a/include/lib/gpt_rme/gpt_rme.h
+++ b/include/lib/gpt_rme/gpt_rme.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -35,6 +35,13 @@
 #define GPT_GPI_ANY			U(0xF)
 #define GPT_GPI_VAL_MASK		UL(0xF)
 
+#define GPT_NSE_SECURE			U(0b00)
+#define GPT_NSE_ROOT			U(0b01)
+#define GPT_NSE_NS			U(0b10)
+#define GPT_NSE_REALM			U(0b11)
+
+#define GPT_NSE_SHIFT                   U(62)
+
 /* PAS attribute GPI definitions. */
 #define GPT_PAS_ATTR_GPI_SHIFT		U(0)
 #define GPT_PAS_ATTR_GPI_MASK		U(0xF)
@@ -262,15 +269,12 @@
  *   base: Base address of the region to transition, must be aligned to granule
  *         size.
  *   size: Size of region to transition, must be aligned to granule size.
- *   src_sec_state: Security state of the caller.
- *   target_pas: Target PAS of the specified memory region.
+ *   src_sec_state: Security state of the originating SMC invoking the API.
  *
  * Return
  *    Negative Linux error code in the event of a failure, 0 for success.
  */
-int gpt_transition_pas(uint64_t base,
-		       size_t size,
-		       unsigned int src_sec_state,
-		       unsigned int target_pas);
+int gpt_delegate_pas(uint64_t base, size_t size, unsigned int src_sec_state);
+int gpt_undelegate_pas(uint64_t base, size_t size, unsigned int src_sec_state);
 
 #endif /* GPT_RME_H */
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 1993cb4..2af8c11 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -381,7 +381,7 @@
  * The max number of regions like RO(code), coherent and data required by
  * different BL stages which need to be mapped in the MMU.
  */
-#define ARM_BL_REGIONS			6
+#define ARM_BL_REGIONS			7
 
 #define MAX_MMAP_REGIONS		(PLAT_ARM_MMAP_ENTRIES +	\
 					 ARM_BL_REGIONS)
diff --git a/include/services/arm_arch_svc.h b/include/services/arm_arch_svc.h
index 5bbd8bb..645b388 100644
--- a/include/services/arm_arch_svc.h
+++ b/include/services/arm_arch_svc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,6 +12,7 @@
 #define SMCCC_ARCH_SOC_ID		U(0x80000002)
 #define SMCCC_ARCH_WORKAROUND_1		U(0x80008000)
 #define SMCCC_ARCH_WORKAROUND_2		U(0x80007FFF)
+#define SMCCC_ARCH_WORKAROUND_3		U(0x80003FFF)
 
 #define SMCCC_GET_SOC_VERSION		U(0)
 #define SMCCC_GET_SOC_REVISION		U(1)
diff --git a/lib/aarch64/cache_helpers.S b/lib/aarch64/cache_helpers.S
index d1f3847..6faf545 100644
--- a/lib/aarch64/cache_helpers.S
+++ b/lib/aarch64/cache_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,6 +8,7 @@
 #include <asm_macros.S>
 
 	.globl	flush_dcache_range
+	.globl	flush_dcache_to_popa_range
 	.globl	clean_dcache_range
 	.globl	inv_dcache_range
 	.globl	dcsw_op_louis
@@ -63,6 +64,35 @@
 endfunc inv_dcache_range
 
 
+	/*
+	 * On implementations with FEAT_MTE2,
+	 * Root firmware must issue DC_CIGDPAPA instead of DC_CIPAPA ,
+	 * in order to additionally clean and invalidate Allocation Tags
+	 * associated with the affected locations.
+	 *
+	 * ------------------------------------------
+	 * Clean+Invalidate by PA to POPA
+	 * from base address till size.
+	 * 'x0' = addr, 'x1' = size
+	 * ------------------------------------------
+	 */
+func flush_dcache_to_popa_range
+	/* Exit early if size is zero */
+	cbz	x1, exit_loop_dc_cipapa
+	dcache_line_size x2, x3
+	sub	x3, x2, #1
+	bic	x0, x0, x3
+	add	x1, x1, x0
+loop_dc_cipapa:
+	sys	#6, c7, c14, #1, x0 /* DC CIPAPA,<Xt> */
+	add	x0, x0, x2
+	cmp	x0, x1
+	b.lo	loop_dc_cipapa
+	dsb	osh
+exit_loop_dc_cipapa:
+	ret
+endfunc	flush_dcache_to_popa_range
+
 	/* ---------------------------------------------------------------
 	 * Data cache operations by set/way to the level specified
 	 *
diff --git a/lib/aarch64/misc_helpers.S b/lib/aarch64/misc_helpers.S
index 01531ca..e8110b0 100644
--- a/lib/aarch64/misc_helpers.S
+++ b/lib/aarch64/misc_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,7 +15,7 @@
 	.globl	zero_normalmem
 	.globl	zeromem
 	.globl	memcpy16
-	.globl	gpt_tlbi_by_pa
+	.globl	gpt_tlbi_by_pa_ll
 
 	.globl	disable_mmu_el1
 	.globl	disable_mmu_el3
@@ -599,7 +599,7 @@
  * TODO: Currently only supports size of 4KB,
  * support other sizes as well.
  */
-func gpt_tlbi_by_pa
+func gpt_tlbi_by_pa_ll
 #if ENABLE_ASSERTIONS
 	cmp	x1, #PAGE_SIZE_4KB
 	ASM_ASSERT(eq)
@@ -607,7 +607,7 @@
 	ASM_ASSERT(eq)
 #endif
 	lsr	x0, x0, #FOUR_KB_SHIFT	/* 4KB size encoding is zero */
-	sys	#6, c8, c4, #3, x0 	/* TLBI RPAOS, <Xt> */
+	sys	#6, c8, c4, #7, x0 	/* TLBI RPALOS, <Xt> */
 	dsb	sy
 	ret
-endfunc gpt_tlbi_by_pa
+endfunc gpt_tlbi_by_pa_ll
diff --git a/lib/cpus/aarch64/cortex_a510.S b/lib/cpus/aarch64/cortex_a510.S
index 3310322..34e1082 100644
--- a/lib/cpus/aarch64/cortex_a510.S
+++ b/lib/cpus/aarch64/cortex_a510.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, ARM Limited. All rights reserved.
+ * Copyright (c) 2022, ARM Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,14 +13,257 @@
 
 /* Hardware handled coherency */
 #if HW_ASSISTED_COHERENCY == 0
-#error "Cortex A510 must be compiled with HW_ASSISTED_COHERENCY enabled"
+#error "Cortex-A510 must be compiled with HW_ASSISTED_COHERENCY enabled"
 #endif
 
 /* 64-bit only core */
 #if CTX_INCLUDE_AARCH32_REGS == 1
-#error "Cortex A510 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
+#error "Cortex-A510 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex-A510 Errata #1922240.
+	 * This applies only to revision r0p0 (fixed in r0p1)
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0, x1, x17
+	 * --------------------------------------------------
+	 */
+func errata_cortex_a510_1922240_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_1922240
+	cbz	x0, 1f
+
+	/* Apply the workaround by setting IMP_CMPXACTLR_EL1[11:10] = 0b11. */
+	mrs	x0, CORTEX_A510_CMPXACTLR_EL1
+	mov	x1, #3
+	bfi	x0, x1, #10, #2
+	msr	CORTEX_A510_CMPXACTLR_EL1, x0
+
+1:
+	ret	x17
+endfunc errata_cortex_a510_1922240_wa
+
+func check_errata_1922240
+	/* Applies to r0p0 only */
+	mov	x1, #0x00
+	b	cpu_rev_var_ls
+endfunc check_errata_1922240
+
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex-A510 Errata #2288014.
+	 * This applies only to revisions r0p0, r0p1, r0p2,
+	 * r0p3 and r1p0. (fixed in r1p1)
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0, x1, x17
+	 * --------------------------------------------------
+	 */
+func errata_cortex_a510_2288014_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_2288014
+	cbz	x0, 1f
+
+	/* Apply the workaround by setting IMP_CPUACTLR_EL1[18] = 0b1. */
+	mrs	x0, CORTEX_A510_CPUACTLR_EL1
+	mov	x1, #1
+	bfi	x0, x1, #18, #1
+	msr	CORTEX_A510_CPUACTLR_EL1, x0
+
+1:
+	ret	x17
+endfunc errata_cortex_a510_2288014_wa
+
+func check_errata_2288014
+	/* Applies to r1p0 and below */
+	mov	x1, #0x10
+	b	cpu_rev_var_ls
+endfunc check_errata_2288014
+
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex-A510 Errata #2042739.
+	 * This applies only to revisions r0p0, r0p1 and r0p2.
+	 * (fixed in r0p3)
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0, x1, x17
+	 * --------------------------------------------------
+	 */
+func errata_cortex_a510_2042739_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_2042739
+	cbz	x0, 1f
+
+	/* Apply the workaround by disabling ReadPreferUnique. */
+	mrs	x0, CORTEX_A510_CPUECTLR_EL1
+	mov	x1, #CORTEX_A510_CPUECTLR_EL1_READPREFERUNIQUE_DISABLE
+	bfi	x0, x1, #CORTEX_A510_CPUECTLR_EL1_READPREFERUNIQUE_SHIFT, #1
+	msr	CORTEX_A510_CPUECTLR_EL1, x0
+
+1:
+	ret	x17
+endfunc errata_cortex_a510_2042739_wa
+
+func check_errata_2042739
+	/* Applies to revisions r0p0 - r0p2 */
+	mov	x1, #0x02
+	b	cpu_rev_var_ls
+endfunc check_errata_2042739
+
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex-A510 Errata #2041909.
+	 * This applies only to revision r0p2 and it is fixed in
+	 * r0p3. The issue is also present in r0p0 and r0p1 but
+	 * there is no workaround in those revisions.
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0, x1, x2, x17
+	 * --------------------------------------------------
+	 */
+func errata_cortex_a510_2041909_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_2041909
+	cbz	x0, 1f
+
+	/* Apply workaround */
+	mov	x0, xzr
+	msr	S3_6_C15_C4_0, x0
+	isb
+
+	mov	x0, #0x8500000
+	msr	S3_6_C15_C4_2, x0
+
+	mov	x0, #0x1F700000
+	movk	x0, #0x8, lsl #32
+	msr	S3_6_C15_C4_3, x0
+
+	mov	x0, #0x3F1
+	movk	x0, #0x110, lsl #16
+	msr	S3_6_C15_C4_1, x0
+	isb
+
+1:
+	ret	x17
+endfunc errata_cortex_a510_2041909_wa
+
+func check_errata_2041909
+	/* Applies only to revision r0p2 */
+	mov	x1, #0x02
+	mov	x2, #0x02
+	b	cpu_rev_var_range
+endfunc check_errata_2041909
+
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex-A510 Errata #2250311.
+	 * This applies only to revisions r0p0, r0p1, r0p2,
+	 * r0p3 and r1p0, and is fixed in r1p1.
+	 * This workaround is not a typical errata fix. MPMM
+	 * is disabled here, but this conflicts with the BL31
+	 * MPMM support. So in addition to simply disabling
+	 * the feature, a flag is set in the MPMM library
+	 * indicating that it should not be enabled even if
+	 * ENABLE_MPMM=1.
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0, x1, x17
+	 * --------------------------------------------------
+	 */
+func errata_cortex_a510_2250311_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_2250311
+	cbz	x0, 1f
+
+	/* Disable MPMM */
+	mrs	x0, CPUMPMMCR_EL3
+	bfm	x0, xzr, #0, #0 /* bfc instruction does not work in GCC */
+	msr	CPUMPMMCR_EL3, x0
+
+#if ENABLE_MPMM && IMAGE_BL31
+	/* If ENABLE_MPMM is set, tell the runtime lib to skip enabling it. */
+	bl mpmm_errata_disable
+#endif
+
+1:
+	ret x17
+endfunc errata_cortex_a510_2250311_wa
+
+func check_errata_2250311
+	/* Applies to r1p0 and lower */
+	mov	x1, #0x10
+	b	cpu_rev_var_ls
+endfunc check_errata_2250311
+
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex-A510 Errata #2218950.
+	 * This applies only to revisions r0p0, r0p1, r0p2,
+	 * r0p3 and r1p0, and is fixed in r1p1.
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0, x1, x17
+	 * --------------------------------------------------
+	 */
+func errata_cortex_a510_2218950_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_2218950
+	cbz	x0, 1f
+
+	/* Source register for BFI */
+	mov	x1, #1
+
+	/* Set bit 18 in CPUACTLR_EL1 */
+	mrs	x0, CORTEX_A510_CPUACTLR_EL1
+	bfi	x0, x1, #18, #1
+	msr	CORTEX_A510_CPUACTLR_EL1, x0
+
+	/* Set bit 25 in CMPXACTLR_EL1 */
+	mrs	x0, CORTEX_A510_CMPXACTLR_EL1
+	bfi	x0, x1, #25, #1
+	msr	CORTEX_A510_CMPXACTLR_EL1, x0
+
+1:
+	ret x17
+endfunc errata_cortex_a510_2218950_wa
+
+func check_errata_2218950
+	/* Applies to r1p0 and lower */
+	mov	x1, #0x10
+	b	cpu_rev_var_ls
+endfunc check_errata_2218950
+
+	/* --------------------------------------------------
+	 * Errata Workaround for Cortex-A510 Errata #2172148.
+	 * This applies only to revisions r0p0, r0p1, r0p2,
+	 * r0p3 and r1p0, and is fixed in r1p1.
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0, x1, x17
+	 * --------------------------------------------------
+	 */
+func errata_cortex_a510_2172148_wa
+	/* Check workaround compatibility. */
+	mov	x17, x30
+	bl	check_errata_2172148
+	cbz	x0, 1f
+
+	/*
+	 * Force L2 allocation of transient lines by setting
+	 * CPUECTLR_EL1.RSCTL=0b01 and CPUECTLR_EL1.NTCTL=0b01.
+	 */
+	mrs	x0, CORTEX_A510_CPUECTLR_EL1
+	mov	x1, #1
+	bfi	x0, x1, #CORTEX_A510_CPUECTLR_EL1_RSCTL_SHIFT, #2
+	bfi	x0, x1, #CORTEX_A510_CPUECTLR_EL1_NTCTL_SHIFT, #2
+	msr	CORTEX_A510_CPUECTLR_EL1, x0
+
+1:
+	ret x17
+endfunc errata_cortex_a510_2172148_wa
+
+func check_errata_2172148
+	/* Applies to r1p0 and lower */
+	mov	x1, #0x10
+	b	cpu_rev_var_ls
+endfunc check_errata_2172148
+
 	/* ----------------------------------------------------
 	 * HW will do the cache maintenance while powering down
 	 * ----------------------------------------------------
@@ -38,19 +281,79 @@
 endfunc cortex_a510_core_pwr_dwn
 
 	/*
-	 * Errata printing function for Cortex A510. Must follow AAPCS.
+	 * Errata printing function for Cortex-A510. Must follow AAPCS.
 	 */
 #if REPORT_ERRATA
 func cortex_a510_errata_report
+	stp	x8, x30, [sp, #-16]!
+
+	bl	cpu_get_rev_var
+	mov	x8, x0
+
+	/*
+	 * Report all errata. The revision-variant information is passed to
+	 * checking functions of each errata.
+	 */
+	report_errata ERRATA_A510_1922240, cortex_a510, 1922240
+	report_errata ERRATA_A510_2288014, cortex_a510, 2288014
+	report_errata ERRATA_A510_2042739, cortex_a510, 2042739
+	report_errata ERRATA_A510_2041909, cortex_a510, 2041909
+	report_errata ERRATA_A510_2250311, cortex_a510, 2250311
+	report_errata ERRATA_A510_2218950, cortex_a510, 2218950
+	report_errata ERRATA_A510_2172148, cortex_a510, 2172148
+
+	ldp	x8, x30, [sp], #16
 	ret
 endfunc cortex_a510_errata_report
 #endif
 
 func cortex_a510_reset_func
+	mov	x19, x30
+
 	/* Disable speculative loads */
 	msr	SSBS, xzr
 	isb
-	ret
+
+	/* Get the CPU revision and stash it in x18. */
+	bl	cpu_get_rev_var
+	mov	x18, x0
+
+#if ERRATA_A510_1922240
+	mov	x0, x18
+	bl	errata_cortex_a510_1922240_wa
+#endif
+
+#if ERRATA_A510_2288014
+	mov	x0, x18
+	bl	errata_cortex_a510_2288014_wa
+#endif
+
+#if ERRATA_A510_2042739
+	mov	x0, x18
+	bl	errata_cortex_a510_2042739_wa
+#endif
+
+#if ERRATA_A510_2041909
+	mov	x0, x18
+	bl	errata_cortex_a510_2041909_wa
+#endif
+
+#if ERRATA_A510_2250311
+	mov	x0, x18
+	bl	errata_cortex_a510_2250311_wa
+#endif
+
+#if ERRATA_A510_2218950
+	mov	x0, x18
+	bl	errata_cortex_a510_2218950_wa
+#endif
+
+#if ERRATA_A510_2172148
+	mov	x0, x18
+	bl	errata_cortex_a510_2172148_wa
+#endif
+
+	ret	x19
 endfunc cortex_a510_reset_func
 
 	/* ---------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a57.S b/lib/cpus/aarch64/cortex_a57.S
index 8ef0f92..3766ec7 100644
--- a/lib/cpus/aarch64/cortex_a57.S
+++ b/lib/cpus/aarch64/cortex_a57.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2022, ARM Limited and Contributors. All rights reserved.
  * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -470,7 +470,12 @@
 	bl	errata_a57_859972_wa
 #endif
 
-#if IMAGE_BL31 && WORKAROUND_CVE_2017_5715
+#if IMAGE_BL31 && ( WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960 )
+	/* ---------------------------------------------------------------
+	 * Override vector table & enable existing workaround if either of
+	 * the build flags are enabled
+	 * ---------------------------------------------------------------
+	 */
 	adr	x0, wa_cve_2017_5715_mmu_vbar
 	msr	vbar_el3, x0
 	/* isb will be performed before returning from this function */
@@ -506,6 +511,20 @@
 	ret	x19
 endfunc cortex_a57_reset_func
 
+func check_errata_cve_2022_23960
+#if WORKAROUND_CVE_2022_23960
+	mov	x0, #ERRATA_APPLIES
+#else
+	mov	x0, #ERRATA_MISSING
+#endif
+	ret
+endfunc check_errata_cve_2022_23960
+
+func check_smccc_arch_workaround_3
+	mov	x0, #ERRATA_APPLIES
+	ret
+endfunc check_smccc_arch_workaround_3
+
 	/* ----------------------------------------------------
 	 * The CPU Ops core power down function for Cortex-A57.
 	 * ----------------------------------------------------
@@ -630,6 +649,7 @@
 	report_errata ERRATA_A57_1319537, cortex_a57, 1319537
 	report_errata WORKAROUND_CVE_2017_5715, cortex_a57, cve_2017_5715
 	report_errata WORKAROUND_CVE_2018_3639, cortex_a57, cve_2018_3639
+	report_errata WORKAROUND_CVE_2022_23960, cortex_a57, cve_2022_23960
 
 	ldp	x8, x30, [sp], #16
 	ret
@@ -661,5 +681,6 @@
 	cortex_a57_reset_func, \
 	check_errata_cve_2017_5715, \
 	CPU_NO_EXTRA2_FUNC, \
+	check_smccc_arch_workaround_3, \
 	cortex_a57_core_pwr_dwn, \
 	cortex_a57_cluster_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_a710.S b/lib/cpus/aarch64/cortex_a710.S
index 92f7363..aea62ae 100644
--- a/lib/cpus/aarch64/cortex_a710.S
+++ b/lib/cpus/aarch64/cortex_a710.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,6 +10,7 @@
 #include <cortex_a710.h>
 #include <cpu_macros.S>
 #include <plat_macros.S>
+#include "wa_cve_2022_23960_bhb_vector.S"
 
 /* Hardware handled coherency */
 #if HW_ASSISTED_COHERENCY == 0
@@ -21,6 +22,10 @@
 #error "Cortex A710 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+#if WORKAROUND_CVE_2022_23960
+	wa_cve_2022_23960_bhb_vector_table CORTEX_A710_BHB_LOOP_COUNT, cortex_a710
+#endif /* WORKAROUND_CVE_2022_23960 */
+
 /* --------------------------------------------------
  * Errata Workaround for Cortex-A710 Erratum 1987031.
  * This applies to revision r0p0, r1p0 and r2p0 of Cortex-A710. It is still
@@ -275,6 +280,45 @@
 	b       cpu_rev_var_ls
 endfunc check_errata_2136059
 
+/* ---------------------------------------------------------------
+ * Errata Workaround for Cortex-A710 Erratum 2282622.
+ * This applies to revision r0p0, r1p0 and r2p0.
+ * It is fixed in r2p1.
+ * Inputs:
+ * x0: variant[4:7] and revision[0:3] of current cpu.
+ * Shall clobber: x0, x1, x17
+ * ---------------------------------------------------------------
+ */
+func errata_a710_2282622_wa
+	/* Compare x0 against revision r2p0 */
+	mov     x17, x30
+	bl      check_errata_2282622
+	cbz     x0, 1f
+
+	/* Apply the workaround */
+	mrs     x1, CORTEX_A710_CPUACTLR2_EL1
+	orr     x1, x1, BIT(0)
+	msr     CORTEX_A710_CPUACTLR2_EL1, x1
+
+1:
+	ret     x17
+endfunc errata_a710_2282622_wa
+
+func check_errata_2282622
+	/* Applies to r0p0, r1p0 and r2p0 */
+	mov     x1, #0x20
+	b       cpu_rev_var_ls
+endfunc check_errata_2282622
+
+func check_errata_cve_2022_23960
+#if WORKAROUND_CVE_2022_23960
+	mov	x0, #ERRATA_APPLIES
+#else
+	mov	x0, #ERRATA_MISSING
+#endif
+	ret
+endfunc check_errata_cve_2022_23960
+
 	/* ----------------------------------------------------
 	 * HW will do the cache maintenance while powering down
 	 * ----------------------------------------------------
@@ -313,6 +357,8 @@
 	report_errata ERRATA_A710_2058056, cortex_a710, 2058056
 	report_errata ERRATA_A710_2267065, cortex_a710, 2267065
 	report_errata ERRATA_A710_2136059, cortex_a710, 2136059
+	report_errata ERRATA_A710_2282622, cortex_a710, 2282622
+	report_errata WORKAROUND_CVE_2022_23960, cortex_a710, cve_2022_23960
 
 	ldp	x8, x30, [sp], #16
 	ret
@@ -368,6 +414,20 @@
 	bl	errata_a710_2136059_wa
 #endif
 
+#if ERRATA_A710_2282622
+	mov	x0, x18
+	bl	errata_a710_2282622_wa
+#endif
+
+#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960
+	/*
+	 * The Cortex-A710 generic vectors are overridden to apply errata
+         * mitigation on exception entry from lower ELs.
+         */
+	adr	x0, wa_cve_vbar_cortex_a710
+	msr	vbar_el3, x0
+#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */
+
 	isb
 	ret	x19
 endfunc cortex_a710_reset_func
diff --git a/lib/cpus/aarch64/cortex_a72.S b/lib/cpus/aarch64/cortex_a72.S
index aff6072..de2d36e 100644
--- a/lib/cpus/aarch64/cortex_a72.S
+++ b/lib/cpus/aarch64/cortex_a72.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,6 +9,11 @@
 #include <cortex_a72.h>
 #include <cpu_macros.S>
 #include <plat_macros.S>
+#include "wa_cve_2022_23960_bhb_vector.S"
+
+#if WORKAROUND_CVE_2022_23960
+	wa_cve_2022_23960_bhb_vector_table CORTEX_A72_BHB_LOOP_COUNT, cortex_a72
+#endif /* WORKAROUND_CVE_2022_23960 */
 
 	/* ---------------------------------------------
 	 * Disable L1 data cache and unified L2 cache
@@ -133,6 +138,24 @@
 	ret
 endfunc check_errata_1319367
 
+func check_errata_cve_2022_23960
+#if WORKAROUND_CVE_2022_23960
+	mov	x0, #ERRATA_APPLIES
+#else
+	mov	x0, #ERRATA_MISSING
+#endif
+	ret
+endfunc check_errata_cve_2022_23960
+
+func check_smccc_arch_workaround_3
+	cpu_check_csv2	x0, 1f
+	mov	x0, #ERRATA_APPLIES
+	ret
+1:
+	mov	x0, #ERRATA_NOT_APPLIES
+	ret
+endfunc check_smccc_arch_workaround_3
+
 	/* -------------------------------------------------
 	 * The CPU Ops reset function for Cortex-A72.
 	 * -------------------------------------------------
@@ -147,13 +170,28 @@
 	bl	errata_a72_859971_wa
 #endif
 
-#if IMAGE_BL31 && WORKAROUND_CVE_2017_5715
+#if IMAGE_BL31 && (WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960)
 	cpu_check_csv2	x0, 1f
 	adr	x0, wa_cve_2017_5715_mmu_vbar
 	msr	vbar_el3, x0
 	/* isb will be performed before returning from this function */
+
+	/* Skip CVE_2022_23960 mitigation if cve_2017_5715 mitigation applied */
+	b	2f
 1:
-#endif
+#if WORKAROUND_CVE_2022_23960
+	/*
+	 * The Cortex-A72 generic vectors are overridden to apply the
+         * mitigation on exception entry from lower ELs for revisions >= r1p0
+	 * which has CSV2 implemented.
+	 */
+	adr	x0, wa_cve_vbar_cortex_a72
+	msr	vbar_el3, x0
+
+	/* isb will be performed before returning from this function */
+#endif /* WORKAROUND_CVE_2022_23960 */
+2:
+#endif /* IMAGE_BL31 &&  (WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960) */
 
 #if WORKAROUND_CVE_2018_3639
 	mrs	x0, CORTEX_A72_CPUACTLR_EL1
@@ -299,6 +337,7 @@
 	report_errata ERRATA_A72_1319367, cortex_a72, 1319367
 	report_errata WORKAROUND_CVE_2017_5715, cortex_a72, cve_2017_5715
 	report_errata WORKAROUND_CVE_2018_3639, cortex_a72, cve_2018_3639
+	report_errata WORKAROUND_CVE_2022_23960, cortex_a72, cve_2022_23960
 
 	ldp	x8, x30, [sp], #16
 	ret
@@ -330,5 +369,6 @@
 	cortex_a72_reset_func, \
 	check_errata_cve_2017_5715, \
 	CPU_NO_EXTRA2_FUNC, \
+	check_smccc_arch_workaround_3, \
 	cortex_a72_core_pwr_dwn, \
 	cortex_a72_cluster_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_a73.S b/lib/cpus/aarch64/cortex_a73.S
index 5c8a887..edcd1f5 100644
--- a/lib/cpus/aarch64/cortex_a73.S
+++ b/lib/cpus/aarch64/cortex_a73.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -111,13 +111,21 @@
 	bl	errata_a73_855423_wa
 #endif
 
-#if IMAGE_BL31 && WORKAROUND_CVE_2017_5715
+#if IMAGE_BL31 && (WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960)
 	cpu_check_csv2	x0, 1f
 	adr	x0, wa_cve_2017_5715_bpiall_vbar
 	msr	vbar_el3, x0
-	/* isb will be performed before returning from this function */
+	isb
+	/* Skip installing vector table again for CVE_2022_23960 */
+        b       2f
 1:
+#if WORKAROUND_CVE_2022_23960
+	adr	x0, wa_cve_2017_5715_bpiall_vbar
+	msr	vbar_el3, x0
+	isb
 #endif
+2:
+#endif /* IMAGE_BL31 &&  (WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960) */
 
 #if WORKAROUND_CVE_2018_3639
 	mrs	x0, CORTEX_A73_IMP_DEF_REG1
@@ -221,6 +229,28 @@
 	ret
 endfunc check_errata_cve_2018_3639
 
+func check_errata_cve_2022_23960
+#if WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960
+	cpu_check_csv2	x0, 1f
+	mov	x0, #ERRATA_APPLIES
+	ret
+ 1:
+# if WORKAROUND_CVE_2022_23960
+	mov	x0, #ERRATA_APPLIES
+# else
+	mov	x0, #ERRATA_MISSING
+# endif /* WORKAROUND_CVE_2022_23960 */
+	ret
+#endif /* WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960 */
+	mov	x0, #ERRATA_MISSING
+	ret
+endfunc check_errata_cve_2022_23960
+
+func check_smccc_arch_workaround_3
+	mov	x0, #ERRATA_APPLIES
+	ret
+endfunc check_smccc_arch_workaround_3
+
 #if REPORT_ERRATA
 /*
  * Errata printing function for Cortex A75. Must follow AAPCS.
@@ -239,6 +269,7 @@
 	report_errata ERRATA_A73_855423, cortex_a73, 855423
 	report_errata WORKAROUND_CVE_2017_5715, cortex_a73, cve_2017_5715
 	report_errata WORKAROUND_CVE_2018_3639, cortex_a73, cve_2018_3639
+	report_errata WORKAROUND_CVE_2022_23960, cortex_a73, cve_2022_23960
 
 	ldp	x8, x30, [sp], #16
 	ret
@@ -269,5 +300,6 @@
 	cortex_a73_reset_func, \
 	check_errata_cve_2017_5715, \
 	CPU_NO_EXTRA2_FUNC, \
+	check_smccc_arch_workaround_3, \
 	cortex_a73_core_pwr_dwn, \
 	cortex_a73_cluster_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_a75.S b/lib/cpus/aarch64/cortex_a75.S
index 657457e..d561be4 100644
--- a/lib/cpus/aarch64/cortex_a75.S
+++ b/lib/cpus/aarch64/cortex_a75.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -90,13 +90,21 @@
 	bl	errata_a75_790748_wa
 #endif
 
-#if IMAGE_BL31 && WORKAROUND_CVE_2017_5715
+#if IMAGE_BL31 && (WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960)
 	cpu_check_csv2	x0, 1f
 	adr	x0, wa_cve_2017_5715_bpiall_vbar
 	msr	vbar_el3, x0
 	isb
+	/* Skip installing vector table again for CVE_2022_23960 */
+        b       2f
 1:
+#if WORKAROUND_CVE_2022_23960
+	adr	x0, wa_cve_2017_5715_bpiall_vbar
+	msr	vbar_el3, x0
+	isb
 #endif
+2:
+#endif /* IMAGE_BL31 &&  (WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960) */
 
 #if WORKAROUND_CVE_2018_3639
 	mrs	x0, CORTEX_A75_CPUACTLR_EL1
@@ -161,6 +169,28 @@
 	ret
 endfunc check_errata_cve_2018_3639
 
+func check_errata_cve_2022_23960
+#if WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960
+	cpu_check_csv2	x0, 1f
+	mov	x0, #ERRATA_APPLIES
+	ret
+1:
+# if WORKAROUND_CVE_2022_23960
+	mov	x0, #ERRATA_APPLIES
+# else
+	mov	x0, #ERRATA_MISSING
+# endif /* WORKAROUND_CVE_2022_23960 */
+	ret
+#endif /* WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960 */
+	mov	x0, #ERRATA_MISSING
+	ret
+endfunc check_errata_cve_2022_23960
+
+func check_smccc_arch_workaround_3
+	mov	x0, #ERRATA_APPLIES
+	ret
+endfunc check_smccc_arch_workaround_3
+
 	/* ---------------------------------------------
 	 * HW will do the cache maintenance while powering down
 	 * ---------------------------------------------
@@ -197,6 +227,7 @@
 	report_errata WORKAROUND_CVE_2018_3639, cortex_a75, cve_2018_3639
 	report_errata ERRATA_DSU_798953, cortex_a75, dsu_798953
 	report_errata ERRATA_DSU_936184, cortex_a75, dsu_936184
+	report_errata WORKAROUND_CVE_2022_23960, cortex_a75, cve_2022_23960
 
 	ldp	x8, x30, [sp], #16
 	ret
@@ -226,4 +257,5 @@
 	cortex_a75_reset_func, \
 	check_errata_cve_2017_5715, \
 	CPU_NO_EXTRA2_FUNC, \
+	check_smccc_arch_workaround_3, \
 	cortex_a75_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_a76.S b/lib/cpus/aarch64/cortex_a76.S
index 4f7f4bb..50bd8cd 100644
--- a/lib/cpus/aarch64/cortex_a76.S
+++ b/lib/cpus/aarch64/cortex_a76.S
@@ -7,11 +7,11 @@
 #include <arch.h>
 #include <asm_macros.S>
 #include <common/bl_common.h>
-#include <context.h>
 #include <cortex_a76.h>
 #include <cpu_macros.S>
 #include <plat_macros.S>
 #include <services/arm_arch_svc.h>
+#include "wa_cve_2022_23960_bhb.S"
 
 /* Hardware handled coherency */
 #if HW_ASSISTED_COHERENCY == 0
@@ -35,59 +35,17 @@
 	 *
 	 * The macro saves x2-x3 to the context. In the fast path
 	 * x0-x3 registers do not need to be restored as the calling
-	 * context will have saved them.
+	 * context will have saved them. The macro also saves
+	 * x29-x30 to the context in the sync_exception path.
 	 */
 	.macro apply_cve_2018_3639_wa _is_sync_exception _esr_el3_val
 	stp	x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
-
 	.if \_is_sync_exception
-		/*
-		 * Ensure SMC is coming from A64/A32 state on #0
-		 * with W0 = SMCCC_ARCH_WORKAROUND_2
-		 *
-		 * This sequence evaluates as:
-		 *    (W0==SMCCC_ARCH_WORKAROUND_2) ? (ESR_EL3==SMC#0) : (NE)
-		 * allowing use of a single branch operation
-		 */
-		orr	w2, wzr, #SMCCC_ARCH_WORKAROUND_2
-		cmp	x0, x2
-		mrs	x3, esr_el3
-		mov_imm	w2, \_esr_el3_val
-		ccmp	w2, w3, #0, eq
-		/*
-		 * Static predictor will predict a fall-through, optimizing
-		 * the `SMCCC_ARCH_WORKAROUND_2` fast path.
-		 */
-		bne	1f
-
-		/*
-		 * The sequence below implements the `SMCCC_ARCH_WORKAROUND_2`
-		 * fast path.
-		 */
-		cmp	x1, xzr /* enable/disable check */
-
-		/*
-		 * When the calling context wants mitigation disabled,
-		 * we program the mitigation disable function in the
-		 * CPU context, which gets invoked on subsequent exits from
-		 * EL3 via the `el3_exit` function. Otherwise NULL is
-		 * programmed in the CPU context, which results in caller's
-		 * inheriting the EL3 mitigation state (enabled) on subsequent
-		 * `el3_exit`.
-		 */
-		mov	x0, xzr
-		adr	x1, cortex_a76_disable_wa_cve_2018_3639
-		csel	x1, x1, x0, eq
-		str	x1, [sp, #CTX_CVE_2018_3639_OFFSET + CTX_CVE_2018_3639_DISABLE]
-
-		mrs	x2, CORTEX_A76_CPUACTLR2_EL1
-		orr	x1, x2, #CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE
-		bic	x3, x2, #CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE
-		csel	x3, x3, x1, eq
-		msr	CORTEX_A76_CPUACTLR2_EL1, x3
-		exception_return /* exception_return contains ISB */
+	stp	x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29]
+	mov_imm	w2, \_esr_el3_val
+	bl	apply_cve_2018_3639_sync_wa
+	ldp	x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29]
 	.endif
-1:
 	/*
 	 * Always enable v4 mitigation during EL3 execution. This is not
 	 * required for the fast path above because it does not perform any
@@ -105,8 +63,10 @@
 	 */
 	ldp	x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
 	.endm
+#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639 */
 
-vector_base cortex_a76_wa_cve_2018_3639_a76_vbar
+#if DYNAMIC_WORKAROUND_CVE_2018_3639 || WORKAROUND_CVE_2022_23960
+vector_base cortex_a76_wa_cve_vbar
 
 	/* ---------------------------------------------------------------------
 	 * Current EL with SP_EL0 : 0x0 - 0x200
@@ -153,22 +113,54 @@
 	 * ---------------------------------------------------------------------
 	 */
 vector_entry cortex_a76_sync_exception_aarch64
+
+#if WORKAROUND_CVE_2022_23960
+	apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT
+#endif /* WORKAROUND_CVE_2022_23960 */
+
+#if DYNAMIC_WORKAROUND_CVE_2018_3639
 	apply_cve_2018_3639_wa _is_sync_exception=1 _esr_el3_val=ESR_EL3_A64_SMC0
+#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/
+
 	b	sync_exception_aarch64
 end_vector_entry cortex_a76_sync_exception_aarch64
 
 vector_entry cortex_a76_irq_aarch64
+
+#if WORKAROUND_CVE_2022_23960
+	apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT
+#endif /* WORKAROUND_CVE_2022_23960 */
+
+#if DYNAMIC_WORKAROUND_CVE_2018_3639
 	apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0
+#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/
+
 	b	irq_aarch64
 end_vector_entry cortex_a76_irq_aarch64
 
 vector_entry cortex_a76_fiq_aarch64
+
+#if WORKAROUND_CVE_2022_23960
+	apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT
+#endif /* WORKAROUND_CVE_2022_23960 */
+
+#if DYNAMIC_WORKAROUND_CVE_2018_3639
 	apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0
+#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/
+
 	b	fiq_aarch64
 end_vector_entry cortex_a76_fiq_aarch64
 
 vector_entry cortex_a76_serror_aarch64
+
+#if WORKAROUND_CVE_2022_23960
+	apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT
+#endif /* WORKAROUND_CVE_2022_23960 */
+
+#if DYNAMIC_WORKAROUND_CVE_2018_3639
 	apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0
+#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/
+
 	b	serror_aarch64
 end_vector_entry cortex_a76_serror_aarch64
 
@@ -177,24 +169,130 @@
 	 * ---------------------------------------------------------------------
 	 */
 vector_entry cortex_a76_sync_exception_aarch32
+
+#if WORKAROUND_CVE_2022_23960
+	apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT
+#endif /* WORKAROUND_CVE_2022_23960 */
+
+#if DYNAMIC_WORKAROUND_CVE_2018_3639
 	apply_cve_2018_3639_wa _is_sync_exception=1 _esr_el3_val=ESR_EL3_A32_SMC0
+#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/
+
 	b	sync_exception_aarch32
 end_vector_entry cortex_a76_sync_exception_aarch32
 
 vector_entry cortex_a76_irq_aarch32
+
+#if WORKAROUND_CVE_2022_23960
+	apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT
+#endif /* WORKAROUND_CVE_2022_23960 */
+
+#if DYNAMIC_WORKAROUND_CVE_2018_3639
 	apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0
+#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/
+
 	b	irq_aarch32
 end_vector_entry cortex_a76_irq_aarch32
 
 vector_entry cortex_a76_fiq_aarch32
+
+#if WORKAROUND_CVE_2022_23960
+	apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT
+#endif /* WORKAROUND_CVE_2022_23960 */
+
+#if DYNAMIC_WORKAROUND_CVE_2018_3639
 	apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0
+#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/
+
 	b	fiq_aarch32
 end_vector_entry cortex_a76_fiq_aarch32
 
 vector_entry cortex_a76_serror_aarch32
+
+#if WORKAROUND_CVE_2022_23960
+	apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT
+#endif /* WORKAROUND_CVE_2022_23960 */
+
+#if DYNAMIC_WORKAROUND_CVE_2018_3639
 	apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0
+#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/
+
 	b	serror_aarch32
 end_vector_entry cortex_a76_serror_aarch32
+#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639 || WORKAROUND_CVE_2022_23960 */
+
+#if DYNAMIC_WORKAROUND_CVE_2018_3639
+	/*
+	 * -----------------------------------------------------------------
+	 * This function applies the mitigation for CVE-2018-3639
+	 * specifically for sync exceptions. It implements a fast path
+	 * where `SMCCC_ARCH_WORKAROUND_2` SMC calls from a lower EL
+	 * running in AArch64 will go through the fast and return early.
+	 *
+	 * In the fast path x0-x3 registers do not need to be restored as the
+	 * calling context will have saved them.
+	 *
+	 * Caller must pass value of esr_el3 to compare via x2.
+	 * Save and restore these registers outside of this function from the
+	 * context before jumping to the main runtime vector table entry.
+	 *
+	 * Shall clobber: x0-x3, x30
+	 * -----------------------------------------------------------------
+	 */
+func apply_cve_2018_3639_sync_wa
+	/*
+	 * Ensure SMC is coming from A64/A32 state on #0
+	 * with W0 = SMCCC_ARCH_WORKAROUND_2
+	 *
+	 * This sequence evaluates as:
+	 *    (W0==SMCCC_ARCH_WORKAROUND_2) ? (ESR_EL3==SMC#0) : (NE)
+	 * allowing use of a single branch operation
+	 * X2 populated outside this function with the SMC FID.
+	 */
+	orr	w3, wzr, #SMCCC_ARCH_WORKAROUND_2
+	cmp	x0, x3
+	mrs	x3, esr_el3
+
+	ccmp	w2, w3, #0, eq
+	/*
+	 * Static predictor will predict a fall-through, optimizing
+	 * the `SMCCC_ARCH_WORKAROUND_2` fast path.
+	 */
+	bne	1f
+
+	/*
+	* The sequence below implements the `SMCCC_ARCH_WORKAROUND_2`
+	* fast path.
+	*/
+	cmp	x1, xzr /* enable/disable check */
+
+	/*
+	 * When the calling context wants mitigation disabled,
+	 * we program the mitigation disable function in the
+	 * CPU context, which gets invoked on subsequent exits from
+	 * EL3 via the `el3_exit` function. Otherwise NULL is
+	 * programmed in the CPU context, which results in caller's
+	 * inheriting the EL3 mitigation state (enabled) on subsequent
+	 * `el3_exit`.
+	 */
+	mov	x0, xzr
+	adr	x1, cortex_a76_disable_wa_cve_2018_3639
+	csel	x1, x1, x0, eq
+	str	x1, [sp, #CTX_CVE_2018_3639_OFFSET + CTX_CVE_2018_3639_DISABLE]
+
+	mrs	x2, CORTEX_A76_CPUACTLR2_EL1
+	orr	x1, x2, #CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE
+	bic	x3, x2, #CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE
+	csel	x3, x3, x1, eq
+	msr	CORTEX_A76_CPUACTLR2_EL1, x3
+	ldp	x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29]
+	/*
+	* `SMCCC_ARCH_WORKAROUND_2`fast path return to lower EL.
+	*/
+	exception_return /* exception_return contains ISB */
+1:
+	ret
+endfunc apply_cve_2018_3639_sync_wa
 #endif /* DYNAMIC_WORKAROUND_CVE_2018_3639 */
 
 	/* --------------------------------------------------
@@ -519,6 +617,15 @@
 #endif
 endfunc check_errata_1165522
 
+func check_errata_cve_2022_23960
+#if WORKAROUND_CVE_2022_23960
+	mov	x0, #ERRATA_APPLIES
+#else
+	mov	x0, #ERRATA_MISSING
+#endif /* WORKAROUND_CVE_2022_23960 */
+	ret
+endfunc check_errata_cve_2022_23960
+
 	/* -------------------------------------------------
 	 * The CPU Ops reset function for Cortex-A76.
 	 * Shall clobber: x0-x19
@@ -590,16 +697,31 @@
 	 * The Cortex-A76 generic vectors are overwritten to use the vectors
 	 * defined above. This is required in order to apply mitigation
 	 * against CVE-2018-3639 on exception entry from lower ELs.
+	 * If the below vector table is used, skip overriding it again for
+	 *  CVE_2022_23960 as both use the same vbar.
 	 */
-	adr	x0, cortex_a76_wa_cve_2018_3639_a76_vbar
+	adr	x0, cortex_a76_wa_cve_vbar
 	msr	vbar_el3, x0
 	isb
+	b	2f
 #endif /* IMAGE_BL31 */
 
 1:
 #endif /* DYNAMIC_WORKAROUND_CVE_2018_3639 */
 #endif /* WORKAROUND_CVE_2018_3639 */
 
+#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960
+	/*
+	 * The Cortex-A76 generic vectors are overridden to apply errata
+	 * mitigation on exception entry from lower ELs. This will be bypassed
+	 * if DYNAMIC_WORKAROUND_CVE_2018_3639 has overridden the vectors.
+	 */
+	adr	x0, cortex_a76_wa_cve_vbar
+	msr	vbar_el3, x0
+	isb
+#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */
+2:
+
 #if ERRATA_DSU_798953
 	bl	errata_dsu_798953_wa
 #endif
@@ -656,6 +778,7 @@
 	report_errata WORKAROUND_CVE_2018_3639, cortex_a76, cve_2018_3639
 	report_errata ERRATA_DSU_798953, cortex_a76, dsu_798953
 	report_errata ERRATA_DSU_936184, cortex_a76, dsu_936184
+	report_errata WORKAROUND_CVE_2022_23960, cortex_a76, cve_2022_23960
 
 	ldp	x8, x30, [sp], #16
 	ret
@@ -685,4 +808,5 @@
 	cortex_a76_reset_func, \
 	CPU_NO_EXTRA1_FUNC, \
 	cortex_a76_disable_wa_cve_2018_3639, \
+	CPU_NO_EXTRA3_FUNC, \
 	cortex_a76_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_a77.S b/lib/cpus/aarch64/cortex_a77.S
index 8c8f4d3..e7365e2 100644
--- a/lib/cpus/aarch64/cortex_a77.S
+++ b/lib/cpus/aarch64/cortex_a77.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,6 +10,7 @@
 #include <cortex_a77.h>
 #include <cpu_macros.S>
 #include <plat_macros.S>
+#include "wa_cve_2022_23960_bhb_vector.S"
 
 /* Hardware handled coherency */
 #if HW_ASSISTED_COHERENCY == 0
@@ -21,6 +22,10 @@
 #error "Cortex-A77 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+#if WORKAROUND_CVE_2022_23960
+	wa_cve_2022_23960_bhb_vector_table CORTEX_A77_BHB_LOOP_COUNT, cortex_a77
+#endif /* WORKAROUND_CVE_2022_23960 */
+
 	/* --------------------------------------------------
 	 * Errata Workaround for Cortex A77 Errata #1508412.
 	 * This applies only to revision <= r1p0 of Cortex A77.
@@ -194,6 +199,15 @@
 	b	cpu_rev_var_ls
 endfunc check_errata_1791578
 
+func check_errata_cve_2022_23960
+#if WORKAROUND_CVE_2022_23960
+	mov	x0, #ERRATA_APPLIES
+#else
+	mov	x0, #ERRATA_MISSING
+#endif
+	ret
+endfunc check_errata_cve_2022_23960
+
 	/* -------------------------------------------------
 	 * The CPU Ops reset function for Cortex-A77.
 	 * Shall clobber: x0-x19
@@ -224,6 +238,16 @@
 	bl	errata_a77_1791578_wa
 #endif
 
+#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960
+	/*
+	 * The Cortex-A77 generic vectors are overridden to apply errata
+         * mitigation on exception entry from lower ELs.
+	 */
+	adr	x0, wa_cve_vbar_cortex_a77
+	msr	vbar_el3, x0
+#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */
+
+	isb
 	ret	x19
 endfunc cortex_a77_reset_func
 
@@ -261,6 +285,7 @@
 	report_errata ERRATA_A77_1925769, cortex_a77, 1925769
 	report_errata ERRATA_A77_1946167, cortex_a77, 1946167
 	report_errata ERRATA_A77_1791578, cortex_a77, 1791578
+	report_errata WORKAROUND_CVE_2022_23960, cortex_a77, cve_2022_23960
 
 	ldp	x8, x30, [sp], #16
 	ret
diff --git a/lib/cpus/aarch64/cortex_a78.S b/lib/cpus/aarch64/cortex_a78.S
index a1288ba..1a6f848 100644
--- a/lib/cpus/aarch64/cortex_a78.S
+++ b/lib/cpus/aarch64/cortex_a78.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2021, ARM Limited. All rights reserved.
+ * Copyright (c) 2019-2022, ARM Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,12 +10,16 @@
 #include <cortex_a78.h>
 #include <cpu_macros.S>
 #include <plat_macros.S>
+#include "wa_cve_2022_23960_bhb_vector.S"
 
 /* Hardware handled coherency */
 #if HW_ASSISTED_COHERENCY == 0
 #error "cortex_a78 must be compiled with HW_ASSISTED_COHERENCY enabled"
 #endif
 
+#if WORKAROUND_CVE_2022_23960
+	wa_cve_2022_23960_bhb_vector_table CORTEX_A78_BHB_LOOP_COUNT, cortex_a78
+#endif /* WORKAROUND_CVE_2022_23960 */
 
 /* --------------------------------------------------
  * Errata Workaround for A78 Erratum 1688305.
@@ -263,6 +267,15 @@
 	b	cpu_rev_var_range
 endfunc check_errata_2242635
 
+func check_errata_cve_2022_23960
+#if WORKAROUND_CVE_2022_23960
+	mov	x0, #ERRATA_APPLIES
+#else
+	mov	x0, #ERRATA_MISSING
+#endif
+	ret
+endfunc check_errata_cve_2022_23960
+
 	/* -------------------------------------------------
 	 * The CPU Ops reset function for Cortex-A78
 	 * -------------------------------------------------
@@ -327,6 +340,15 @@
 	msr	CPUAMCNTENSET1_EL0, x0
 #endif
 
+#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960
+	/*
+	 * The Cortex-A78 generic vectors are overridden to apply errata
+	 * mitigation on exception entry from lower ELs.
+	 */
+	adr	x0, wa_cve_vbar_cortex_a78
+	msr	vbar_el3, x0
+#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */
+
 	isb
 	ret	x19
 endfunc cortex_a78_reset_func
@@ -368,6 +390,7 @@
 	report_errata ERRATA_A78_1952683, cortex_a78, 1952683
 	report_errata ERRATA_A78_2132060, cortex_a78, 2132060
 	report_errata ERRATA_A78_2242635, cortex_a78, 2242635
+	report_errata WORKAROUND_CVE_2022_23960, cortex_a78, cve_2022_23960
 
 	ldp	x8, x30, [sp], #16
 	ret
diff --git a/lib/cpus/aarch64/cortex_x2.S b/lib/cpus/aarch64/cortex_x2.S
index 2ecfbbb..9586a5b 100644
--- a/lib/cpus/aarch64/cortex_x2.S
+++ b/lib/cpus/aarch64/cortex_x2.S
@@ -10,6 +10,7 @@
 #include <cortex_x2.h>
 #include <cpu_macros.S>
 #include <plat_macros.S>
+#include "wa_cve_2022_23960_bhb_vector.S"
 
 /* Hardware handled coherency */
 #if HW_ASSISTED_COHERENCY == 0
@@ -21,6 +22,10 @@
 #error "Cortex X2 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+#if WORKAROUND_CVE_2022_23960
+	wa_cve_2022_23960_bhb_vector_table CORTEX_X2_BHB_LOOP_COUNT, cortex_x2
+#endif /* WORKAROUND_CVE_2022_23960 */
+
 	/* --------------------------------------------------
 	 * Errata Workaround for Cortex X2 Errata #2002765.
 	 * This applies to revisions r0p0, r1p0, and r2p0 and
@@ -222,6 +227,16 @@
 	mov	x1, #0x20
 	b	cpu_rev_var_ls
 endfunc check_errata_2216384
+
+func check_errata_cve_2022_23960
+#if WORKAROUND_CVE_2022_23960
+	mov	x0, #ERRATA_APPLIES
+#else
+	mov	x0, #ERRATA_MISSING
+#endif
+	ret
+endfunc check_errata_cve_2022_23960
+
 	/* ----------------------------------------------------
 	 * HW will do the cache maintenance while powering down
 	 * ----------------------------------------------------
@@ -258,6 +273,7 @@
 	report_errata ERRATA_X2_2017096, cortex_x2, 2017096
 	report_errata ERRATA_X2_2081180, cortex_x2, 2081180
 	report_errata ERRATA_X2_2216384, cortex_x2, 2216384
+	report_errata WORKAROUND_CVE_2022_23960, cortex_x2, cve_2022_23960
 
 	ldp	x8, x30, [sp], #16
 	ret
@@ -305,6 +321,16 @@
 	bl	errata_x2_2216384_wa
 #endif
 
+#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960
+	/*
+	 * The Cortex-X2 generic vectors are overridden to apply errata
+         * mitigation on exception entry from lower ELs.
+         */
+	adr	x0, wa_cve_vbar_cortex_x2
+	msr	vbar_el3, x0
+#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */
+
+	isb
 	ret x19
 endfunc cortex_x2_reset_func
 
diff --git a/lib/cpus/aarch64/cpu_helpers.S b/lib/cpus/aarch64/cpu_helpers.S
index bd8f85f..2385627 100644
--- a/lib/cpus/aarch64/cpu_helpers.S
+++ b/lib/cpus/aarch64/cpu_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -381,7 +381,7 @@
 	 * If the reserved function pointer is NULL, this CPU
 	 * is unaffected by CVE-2017-5715 so bail out.
 	 */
-	cmp	x0, #0
+	cmp	x0, #CPU_NO_EXTRA1_FUNC
 	beq	1f
 	br	x0
 1:
@@ -416,3 +416,41 @@
 	ldr	x0, [x0, #CPU_EXTRA2_FUNC]
 	ret
 endfunc wa_cve_2018_3639_get_disable_ptr
+
+/*
+ * int check_smccc_arch_wa3_applies(void);
+ *
+ * This function checks whether SMCCC_ARCH_WORKAROUND_3 is enabled to mitigate
+ * CVE-2022-23960 for this CPU. It returns:
+ *  - ERRATA_APPLIES when SMCCC_ARCH_WORKAROUND_3 can be invoked to mitigate
+ *    the CVE.
+ *  - ERRATA_NOT_APPLIES when SMCCC_ARCH_WORKAROUND_3 should not be invoked to
+ *    mitigate the CVE.
+ *
+ * NOTE: Must be called only after cpu_ops have been initialized
+ *       in per-CPU data.
+ */
+	.globl	check_smccc_arch_wa3_applies
+func check_smccc_arch_wa3_applies
+	mrs	x0, tpidr_el3
+#if ENABLE_ASSERTIONS
+	cmp	x0, #0
+	ASM_ASSERT(ne)
+#endif
+	ldr	x0, [x0, #CPU_DATA_CPU_OPS_PTR]
+#if ENABLE_ASSERTIONS
+	cmp	x0, #0
+	ASM_ASSERT(ne)
+#endif
+	ldr	x0, [x0, #CPU_EXTRA3_FUNC]
+	/*
+	 * If the reserved function pointer is NULL, this CPU
+	 * is unaffected by CVE-2022-23960 so bail out.
+	 */
+	cmp	x0, #CPU_NO_EXTRA3_FUNC
+	beq	1f
+	br	x0
+1:
+	mov	x0, #ERRATA_NOT_APPLIES
+	ret
+endfunc check_smccc_arch_wa3_applies
diff --git a/lib/cpus/aarch64/neoverse_n1.S b/lib/cpus/aarch64/neoverse_n1.S
index 9c97cf6..b75b0c1 100644
--- a/lib/cpus/aarch64/neoverse_n1.S
+++ b/lib/cpus/aarch64/neoverse_n1.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,8 +8,8 @@
 #include <asm_macros.S>
 #include <cpuamu.h>
 #include <cpu_macros.S>
-#include <context.h>
 #include <neoverse_n1.h>
+#include "wa_cve_2022_23960_bhb_vector.S"
 
 /* Hardware handled coherency */
 #if HW_ASSISTED_COHERENCY == 0
@@ -23,6 +23,10 @@
 
 	.global neoverse_n1_errata_ic_trap_handler
 
+#if WORKAROUND_CVE_2022_23960
+	wa_cve_2022_23960_bhb_vector_table NEOVERSE_N1_BHB_LOOP_COUNT, neoverse_n1
+#endif /* WORKAROUND_CVE_2022_23960 */
+
 /* --------------------------------------------------
  * Errata Workaround for Neoverse N1 Erratum 1043202.
  * This applies to revision r0p0 and r1p0 of Neoverse N1.
@@ -464,6 +468,15 @@
 	b	cpu_rev_var_range
 endfunc check_errata_1946160
 
+func check_errata_cve_2022_23960
+#if WORKAROUND_CVE_2022_23960
+	mov	x0, #ERRATA_APPLIES
+#else
+	mov	x0, #ERRATA_MISSING
+#endif
+	ret
+endfunc check_errata_cve_2022_23960
+
 func neoverse_n1_reset_func
 	mov	x19, x30
 
@@ -575,6 +588,15 @@
 	bl	errata_dsu_936184_wa
 #endif
 
+#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960
+	/*
+	 * The Neoverse-N1 generic vectors are overridden to apply errata
+         * mitigation on exception entry from lower ELs.
+	 */
+	adr	x0, wa_cve_vbar_neoverse_n1
+	msr	vbar_el3, x0
+#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */
+
 	isb
 	ret	x19
 endfunc neoverse_n1_reset_func
@@ -624,6 +646,7 @@
 	report_errata ERRATA_N1_1868343, neoverse_n1, 1868343
 	report_errata ERRATA_N1_1946160, neoverse_n1, 1946160
 	report_errata ERRATA_DSU_936184, neoverse_n1, dsu_936184
+	report_errata WORKAROUND_CVE_2022_23960, neoverse_n1, cve_2022_23960
 
 	ldp	x8, x30, [sp], #16
 	ret
diff --git a/lib/cpus/aarch64/neoverse_n2.S b/lib/cpus/aarch64/neoverse_n2.S
index 621aded..b93f2a6 100644
--- a/lib/cpus/aarch64/neoverse_n2.S
+++ b/lib/cpus/aarch64/neoverse_n2.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,6 +8,7 @@
 #include <asm_macros.S>
 #include <cpu_macros.S>
 #include <neoverse_n2.h>
+#include "wa_cve_2022_23960_bhb_vector.S"
 
 /* Hardware handled coherency */
 #if HW_ASSISTED_COHERENCY == 0
@@ -19,6 +20,10 @@
 #error "Neoverse-N2 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+#if WORKAROUND_CVE_2022_23960
+	wa_cve_2022_23960_bhb_vector_table NEOVERSE_N2_BHB_LOOP_COUNT, neoverse_n2
+#endif /* WORKAROUND_CVE_2022_23960 */
+
 /* --------------------------------------------------
  * Errata Workaround for Neoverse N2 Erratum 2002655.
  * This applies to revision r0p0 of Neoverse N2. it is still open.
@@ -333,6 +338,15 @@
 	b	cpu_rev_var_ls
 endfunc check_errata_2280757
 
+func check_errata_cve_2022_23960
+#if WORKAROUND_CVE_2022_23960
+	mov	x0, #ERRATA_APPLIES
+#else
+	mov	x0, #ERRATA_MISSING
+#endif
+	ret
+endfunc check_errata_cve_2022_23960
+
 	/* -------------------------------------------
 	 * The CPU Ops reset function for Neoverse N2.
 	 * -------------------------------------------
@@ -428,6 +442,15 @@
 	bl	errata_n2_2002655_wa
 #endif
 
+#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960
+	/*
+	 * The Neoverse-N2 generic vectors are overridden to apply errata
+         * mitigation on exception entry from lower ELs.
+	 */
+	adr	x0, wa_cve_vbar_neoverse_n2
+	msr	vbar_el3, x0
+#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */
+
 	isb
 	ret	x19
 endfunc neoverse_n2_reset_func
@@ -469,6 +492,7 @@
 	report_errata ERRATA_N2_2138958, neoverse_n2, 2138958
 	report_errata ERRATA_N2_2242400, neoverse_n2, 2242400
 	report_errata ERRATA_N2_2280757, neoverse_n2, 2280757
+	report_errata WORKAROUND_CVE_2022_23960, neoverse_n2, cve_2022_23960
 
 	ldp	x8, x30, [sp], #16
 	ret
diff --git a/lib/cpus/aarch64/neoverse_v1.S b/lib/cpus/aarch64/neoverse_v1.S
index 62a7a30..6adb3a8 100644
--- a/lib/cpus/aarch64/neoverse_v1.S
+++ b/lib/cpus/aarch64/neoverse_v1.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,6 +10,7 @@
 #include <neoverse_v1.h>
 #include <cpu_macros.S>
 #include <plat_macros.S>
+#include "wa_cve_2022_23960_bhb_vector.S"
 
 /* Hardware handled coherency */
 #if HW_ASSISTED_COHERENCY == 0
@@ -21,6 +22,10 @@
 #error "Neoverse-V1 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
 #endif
 
+#if WORKAROUND_CVE_2022_23960
+	wa_cve_2022_23960_bhb_vector_table NEOVERSE_V1_BHB_LOOP_COUNT, neoverse_v1
+#endif /* WORKAROUND_CVE_2022_23960 */
+
 	/* --------------------------------------------------
 	 * Errata Workaround for Neoverse V1 Errata #1774420.
 	 * This applies to revisions r0p0 and r1p0, fixed in r1p1.
@@ -325,6 +330,15 @@
 	b	cpu_rev_var_range
 endfunc check_errata_2216392
 
+func check_errata_cve_2022_23960
+#if WORKAROUND_CVE_2022_23960
+	mov	x0, #ERRATA_APPLIES
+#else
+	mov	x0, #ERRATA_MISSING
+#endif
+	ret
+endfunc check_errata_cve_2022_23960
+
 	/* ---------------------------------------------
 	 * HW will do the cache maintenance while powering down
 	 * ---------------------------------------------
@@ -364,6 +378,7 @@
 	report_errata ERRATA_V1_2139242, neoverse_v1, 2139242
 	report_errata ERRATA_V1_2108267, neoverse_v1, 2108267
 	report_errata ERRATA_V1_2216392, neoverse_v1, 2216392
+	report_errata WORKAROUND_CVE_2022_23960, neoverse_v1, cve_2022_23960
 
 	ldp	x8, x30, [sp], #16
 	ret
@@ -422,6 +437,16 @@
 	bl	errata_neoverse_v1_2216392_wa
 #endif
 
+#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960
+	/*
+	 * The Neoverse-V1 generic vectors are overridden to apply errata
+         * mitigation on exception entry from lower ELs.
+	 */
+	adr	x0, wa_cve_vbar_neoverse_v1
+	msr	vbar_el3, x0
+#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */
+
+	isb
 	ret	x19
 endfunc neoverse_v1_reset_func
 
diff --git a/lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S b/lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S
index c9a9544..0222818 100644
--- a/lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S
+++ b/lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -308,22 +308,25 @@
 
 	/*
 	 * Check if SMC is coming from A64 state on #0
-	 * with W0 = SMCCC_ARCH_WORKAROUND_1
+	 * with W0 = SMCCC_ARCH_WORKAROUND_1 or W0 = SMCCC_ARCH_WORKAROUND_3
 	 *
 	 * This sequence evaluates as:
-	 *    (W0==SMCCC_ARCH_WORKAROUND_1) ? (ESR_EL3==SMC#0) : (NE)
+	 *    (W0==SMCCC_ARCH_WORKAROUND_1) || (W0==SMCCC_ARCH_WORKAROUND_3) ?
+	 *    (ESR_EL3==SMC#0) : (NE)
 	 * allowing use of a single branch operation
 	 */
 	orr	w2, wzr, #SMCCC_ARCH_WORKAROUND_1
 	cmp	w0, w2
+	orr	w2, wzr, #SMCCC_ARCH_WORKAROUND_3
+	ccmp	w0, w2, #4, ne
 	mov_imm	w2, ESR_EL3_A64_SMC0
 	ccmp	w3, w2, #0, eq
 	/* Static predictor will predict a fall through */
 	bne	1f
 	eret
 1:
-	ldp	x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
-	b	sync_exception_aarch64
+	/* restore x2 and x3 and continue sync exception handling */
+	b	bpiall_ret_sync_exception_aarch32_tail
 end_vector_entry bpiall_ret_sync_exception_aarch32
 
 vector_entry bpiall_ret_irq_aarch32
@@ -355,3 +358,11 @@
 vector_entry bpiall_ret_serror_aarch32
 	b	report_unhandled_exception
 end_vector_entry bpiall_ret_serror_aarch32
+
+	/*
+	 * Part of bpiall_ret_sync_exception_aarch32 to save vector space
+	 */
+func bpiall_ret_sync_exception_aarch32_tail
+	ldp	x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
+	b	sync_exception_aarch64
+endfunc bpiall_ret_sync_exception_aarch32_tail
diff --git a/lib/cpus/aarch64/wa_cve_2017_5715_mmu.S b/lib/cpus/aarch64/wa_cve_2017_5715_mmu.S
index 5134ee3..ed0a549 100644
--- a/lib/cpus/aarch64/wa_cve_2017_5715_mmu.S
+++ b/lib/cpus/aarch64/wa_cve_2017_5715_mmu.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -34,15 +34,18 @@
 
 	/*
 	 * Ensure SMC is coming from A64/A32 state on #0
-	 * with W0 = SMCCC_ARCH_WORKAROUND_1
+	 * with W0 = SMCCC_ARCH_WORKAROUND_1 or W0 = SMCCC_ARCH_WORKAROUND_3
 	 *
 	 * This sequence evaluates as:
-	 *    (W0==SMCCC_ARCH_WORKAROUND_1) ? (ESR_EL3==SMC#0) : (NE)
+	 *    (W0==SMCCC_ARCH_WORKAROUND_1) || (W0==SMCCC_ARCH_WORKAROUND_3) ?
+	 *    (ESR_EL3==SMC#0) : (NE)
 	 * allowing use of a single branch operation
 	 */
 	.if \_is_sync_exception
 		orr	w1, wzr, #SMCCC_ARCH_WORKAROUND_1
 		cmp	w0, w1
+		orr	w1, wzr, #SMCCC_ARCH_WORKAROUND_3
+		ccmp	w0, w1, #4, ne
 		mrs	x0, esr_el3
 		mov_imm	w1, \_esr_el3_val
 		ccmp	w0, w1, #0, eq
diff --git a/lib/cpus/aarch64/wa_cve_2022_23960_bhb.S b/lib/cpus/aarch64/wa_cve_2022_23960_bhb.S
new file mode 100644
index 0000000..e0e41cc
--- /dev/null
+++ b/lib/cpus/aarch64/wa_cve_2022_23960_bhb.S
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <context.h>
+
+#if WORKAROUND_CVE_2022_23960
+	/*
+	 * This macro applies the mitigation for CVE-2022-23960.
+         * The macro saves x2-x3 to the CPU context.
+         * SP should point to the CPU context.
+	 */
+	.macro	apply_cve_2022_23960_bhb_wa _bhb_loop_count
+	stp	x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
+
+	/* CVE-BHB-NUM loop count */
+	mov	x2, \_bhb_loop_count
+
+1:
+	/* b pc+4 part of the workaround */
+	b	2f
+2:
+	subs	x2, x2, #1
+	bne	1b
+	dsb	sy
+	isb
+	ldp	x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
+	.endm
+#endif /* WORKAROUND_CVE_2022_23960 */
diff --git a/lib/cpus/aarch64/wa_cve_2022_23960_bhb_vector.S b/lib/cpus/aarch64/wa_cve_2022_23960_bhb_vector.S
new file mode 100644
index 0000000..220fa11
--- /dev/null
+++ b/lib/cpus/aarch64/wa_cve_2022_23960_bhb_vector.S
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <services/arm_arch_svc.h>
+#include "wa_cve_2022_23960_bhb.S"
+
+	/*
+	 * This macro is used to isolate the vector table for relevant CPUs
+	 * used in the mitigation for CVE_2022_23960.
+	 */
+	.macro wa_cve_2022_23960_bhb_vector_table _bhb_loop_count, _cpu
+
+	.globl	wa_cve_vbar_\_cpu
+
+vector_base wa_cve_vbar_\_cpu
+	/* ---------------------------------------------------------------------
+	 * Current EL with SP_EL0 : 0x0 - 0x200
+	 * ---------------------------------------------------------------------
+	 */
+vector_entry bhb_sync_exception_sp_el0_\_cpu
+	b	sync_exception_sp_el0
+end_vector_entry bhb_sync_exception_sp_el0_\_cpu
+
+vector_entry bhb_irq_sp_el0_\_cpu
+	b	irq_sp_el0
+end_vector_entry bhb_irq_sp_el0_\_cpu
+
+vector_entry bhb_fiq_sp_el0_\_cpu
+	b	fiq_sp_el0
+end_vector_entry bhb_fiq_sp_el0_\_cpu
+
+vector_entry bhb_serror_sp_el0_\_cpu
+	b	serror_sp_el0
+end_vector_entry bhb_serror_sp_el0_\_cpu
+
+	/* ---------------------------------------------------------------------
+	 * Current EL with SP_ELx: 0x200 - 0x400
+	 * ---------------------------------------------------------------------
+	 */
+vector_entry bhb_sync_exception_sp_elx_\_cpu
+	b	sync_exception_sp_elx
+end_vector_entry bhb_sync_exception_sp_elx_\_cpu
+
+vector_entry bhb_irq_sp_elx_\_cpu
+	b	irq_sp_elx
+end_vector_entry bhb_irq_sp_elx_\_cpu
+
+vector_entry bhb_fiq_sp_elx_\_cpu
+	b	fiq_sp_elx
+end_vector_entry bhb_fiq_sp_elx_\_cpu
+
+vector_entry bhb_serror_sp_elx_\_cpu
+	b	serror_sp_elx
+end_vector_entry bhb_serror_sp_elx_\_cpu
+
+	/* ---------------------------------------------------------------------
+	 * Lower EL using AArch64 : 0x400 - 0x600
+	 * ---------------------------------------------------------------------
+	 */
+vector_entry bhb_sync_exception_aarch64_\_cpu
+	apply_cve_2022_23960_bhb_wa \_bhb_loop_count
+	b	sync_exception_aarch64
+end_vector_entry bhb_sync_exception_aarch64_\_cpu
+
+vector_entry bhb_irq_aarch64_\_cpu
+	apply_cve_2022_23960_bhb_wa \_bhb_loop_count
+	b	irq_aarch64
+end_vector_entry bhb_irq_aarch64_\_cpu
+
+vector_entry bhb_fiq_aarch64_\_cpu
+	apply_cve_2022_23960_bhb_wa \_bhb_loop_count
+	b	fiq_aarch64
+end_vector_entry bhb_fiq_aarch64_\_cpu
+
+vector_entry bhb_serror_aarch64_\_cpu
+	apply_cve_2022_23960_bhb_wa \_bhb_loop_count
+	b	serror_aarch64
+end_vector_entry bhb_serror_aarch64_\_cpu
+
+	/* ---------------------------------------------------------------------
+	 * Lower EL using AArch32 : 0x600 - 0x800
+	 * ---------------------------------------------------------------------
+	 */
+vector_entry bhb_sync_exception_aarch32_\_cpu
+	apply_cve_2022_23960_bhb_wa \_bhb_loop_count
+	b	sync_exception_aarch32
+end_vector_entry bhb_sync_exception_aarch32_\_cpu
+
+vector_entry bhb_irq_aarch32_\_cpu
+	apply_cve_2022_23960_bhb_wa \_bhb_loop_count
+	b	irq_aarch32
+end_vector_entry bhb_irq_aarch32_\_cpu
+
+vector_entry bhb_fiq_aarch32_\_cpu
+	apply_cve_2022_23960_bhb_wa \_bhb_loop_count
+	b	fiq_aarch32
+end_vector_entry bhb_fiq_aarch32_\_cpu
+
+vector_entry bhb_serror_aarch32_\_cpu
+	apply_cve_2022_23960_bhb_wa \_bhb_loop_count
+	b	serror_aarch32
+end_vector_entry bhb_serror_aarch32_\_cpu
+	.endm
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index e02aa01..c7630fb 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -7,27 +7,28 @@
 
 # Cortex A57 specific optimisation to skip L1 cache flush when
 # cluster is powered down.
-SKIP_A57_L1_FLUSH_PWR_DWN	?=0
+SKIP_A57_L1_FLUSH_PWR_DWN		?=0
 
 # Flag to disable the cache non-temporal hint.
 # It is enabled by default.
-A53_DISABLE_NON_TEMPORAL_HINT	?=1
+A53_DISABLE_NON_TEMPORAL_HINT		?=1
 
 # Flag to disable the cache non-temporal hint.
 # It is enabled by default.
-A57_DISABLE_NON_TEMPORAL_HINT	?=1
+A57_DISABLE_NON_TEMPORAL_HINT		?=1
 
 # Flag to enable higher performance non-cacheable load forwarding.
 # It is disabled by default.
 A57_ENABLE_NONCACHEABLE_LOAD_FWD	?= 0
 
-WORKAROUND_CVE_2017_5715	?=1
-WORKAROUND_CVE_2018_3639	?=1
+WORKAROUND_CVE_2017_5715		?=1
+WORKAROUND_CVE_2018_3639		?=1
 DYNAMIC_WORKAROUND_CVE_2018_3639	?=0
+WORKAROUND_CVE_2022_23960		?=1
 
 # Flags to indicate internal or external Last level cache
 # By default internal
-NEOVERSE_Nx_EXTERNAL_LLC	?=0
+NEOVERSE_Nx_EXTERNAL_LLC		?=0
 
 # Process A57_ENABLE_NONCACHEABLE_LOAD_FWD flag
 $(eval $(call assert_boolean,A57_ENABLE_NONCACHEABLE_LOAD_FWD))
@@ -56,13 +57,17 @@
 $(eval $(call assert_boolean,DYNAMIC_WORKAROUND_CVE_2018_3639))
 $(eval $(call add_define,DYNAMIC_WORKAROUND_CVE_2018_3639))
 
+# Process WORKAROUND_CVE_2022_23960 flag
+$(eval $(call assert_boolean,WORKAROUND_CVE_2022_23960))
+$(eval $(call add_define,WORKAROUND_CVE_2022_23960))
+
 $(eval $(call assert_boolean,NEOVERSE_Nx_EXTERNAL_LLC))
 $(eval $(call add_define,NEOVERSE_Nx_EXTERNAL_LLC))
 
 ifneq (${DYNAMIC_WORKAROUND_CVE_2018_3639},0)
-    ifeq (${WORKAROUND_CVE_2018_3639},0)
-        $(error "Error: WORKAROUND_CVE_2018_3639 must be 1 if DYNAMIC_WORKAROUND_CVE_2018_3639 is 1")
-    endif
+	ifeq (${WORKAROUND_CVE_2018_3639},0)
+		$(error "Error: WORKAROUND_CVE_2018_3639 must be 1 if DYNAMIC_WORKAROUND_CVE_2018_3639 is 1")
+	endif
 endif
 
 # CPU Errata Build flags.
@@ -108,7 +113,7 @@
 # only to revision <= r0p2 of the Cortex A53 cpu.
 ERRATA_A53_827319	?=0
 
-# Flag to apply erratum 835769 workaround at compile and link time.  This
+# Flag to apply erratum 835769 workaround at compile and link time. This
 # erratum applies to revision <= r0p4 of the Cortex A53 cpu. Enabling this
 # workaround can lead the linker to create "*.stub" sections.
 ERRATA_A53_835769	?=0
@@ -170,11 +175,11 @@
 # only to revision r0p0 of the Cortex A57 cpu.
 ERRATA_A57_813419	?=0
 
-# Flag to apply erratum 813420  workaround during reset. This erratum applies
+# Flag to apply erratum 813420 workaround during reset. This erratum applies
 # only to revision r0p0 of the Cortex A57 cpu.
 ERRATA_A57_813420	?=0
 
-# Flag to apply erratum 814670  workaround during reset. This erratum applies
+# Flag to apply erratum 814670 workaround during reset. This erratum applies
 # only to revision r0p0 of the Cortex A57 cpu.
 ERRATA_A57_814670	?=0
 
@@ -307,7 +312,7 @@
 ERRATA_A78_1941498	?=0
 
 # Flag to apply erratum 1951500 workaround during reset. This erratum applies
-# to revisions r1p0 and r1p1 of the A78 cpu.  The issue is present in r0p0 as
+# to revisions r1p0 and r1p1 of the A78 cpu. The issue is present in r0p0 as
 # well but there is no workaround for that revision.
 ERRATA_A78_1951500	?=0
 
@@ -317,11 +322,11 @@
 
 # Flag to apply erratum 1952683 workaround during reset. This erratum applies
 # to revision r0p0 of the A78 cpu and was fixed in the revision r1p0.
-ERRATA_A78_1952683  ?=0
+ERRATA_A78_1952683	?=0
 
 # Flag to apply erratum 2132060 workaround during reset. This erratum applies
 # to revisions r0p0, r1p0, r1p1, and r1p2 of the A78 cpu. It is still open.
-ERRATA_A78_2132060  ?=0
+ERRATA_A78_2132060	?=0
 
 # Flag to apply erratum 2242635 workaround during reset. This erratum applies
 # to revisions r1p0, r1p1, and r1p2 of the A78 cpu and is open. The issue is
@@ -389,7 +394,7 @@
 ERRATA_N1_1868343	?=0
 
 # Flag to apply erratum 1946160 workaround during reset. This erratum applies
-# to revisions r3p0, r3p1, r4p0, and r4p1 of the Neoverse N1 cpu.  The issue
+# to revisions r3p0, r3p1, r4p0, and r4p1 of the Neoverse N1 cpu. The issue
 # exists in revisions r0p0, r1p0, and r2p0 as well but there is no workaround.
 ERRATA_N1_1946160	?=0
 
@@ -397,19 +402,19 @@
 # to revisions r0p0 of the Neoverse-N2 cpu, it is still open.
 ERRATA_N2_2002655	?=0
 
-# Flag to apply erratum 1774420 workaround during reset.  This erratum applies
+# Flag to apply erratum 1774420 workaround during reset. This erratum applies
 # to revisions r0p0 and r1p0 of the Neoverse V1 core, and was fixed in r1p1.
 ERRATA_V1_1774420	?=0
 
-# Flag to apply erratum 1791573 workaround during reset.  This erratum applies
+# Flag to apply erratum 1791573 workaround during reset. This erratum applies
 # to revisions r0p0 and r1p0 of the Neoverse V1 core, and was fixed in r1p1.
 ERRATA_V1_1791573	?=0
 
-# Flag to apply erratum 1852267 workaround during reset.  This erratum applies
+# Flag to apply erratum 1852267 workaround during reset. This erratum applies
 # to revisions r0p0 and r1p0 of the Neoverse V1 core, and was fixed in r1p1.
 ERRATA_V1_1852267	?=0
 
-# Flag to apply erratum 1925756 workaround during reset.  This needs to be
+# Flag to apply erratum 1925756 workaround during reset. This needs to be
 # enabled for r0p0, r1p0, and r1p1 of the Neoverse V1 core, it is still open.
 ERRATA_V1_1925756	?=0
 
@@ -418,7 +423,7 @@
 ERRATA_V1_1940577	?=0
 
 # Flag to apply erratum 1966096 workaround during reset. This erratum applies
-# to revisions r1p0 and r1p1 of the Neoverse V1 CPU and is open.  This issue
+# to revisions r1p0 and r1p1 of the Neoverse V1 CPU and is open. This issue
 # exists in r0p0 as well but there is no workaround for that revision.
 ERRATA_V1_1966096	?=0
 
@@ -451,6 +456,26 @@
 # to revisions r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is still open.
 ERRATA_A710_2058056	?=0
 
+# Flag to apply erratum 2055002 workaround during reset. This erratum applies
+# to revision r1p0, r2p0 of the Cortex-A710 cpu and is still open.
+ERRATA_A710_2055002	?=0
+
+# Flag to apply erratum 2017096 workaround during reset. This erratum applies
+# to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is still open.
+ERRATA_A710_2017096	?=0
+
+# Flag to apply erratum 2267065 workaround during reset. This erratum applies
+# to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is fixed in r2p1.
+ERRATA_A710_2267065	?=0
+
+# Flag to apply erratum 2136059 workaround during reset. This erratum applies
+# to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is fixed in r2p1.
+ERRATA_A710_2136059	?=0
+
+# Flag to apply erratum 2282622 workaround during reset. This erratum applies
+# to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is fixed in r2p1.
+ERRATA_A710_2282622	?=0
+
 # Flag to apply erratum 2067956 workaround during reset. This erratum applies
 # to revision r0p0 of the Neoverse N2 cpu and is still open.
 ERRATA_N2_2067956	?=0
@@ -487,22 +512,6 @@
 # to revision r0p0 of the Neoverse N2 cpu and is still open.
 ERRATA_N2_2280757	?=0
 
-# Flag to apply erratum 2055002 workaround during reset. This erratum applies
-# to revision r1p0, r2p0 of the Cortex-A710 cpu and is still open.
-ERRATA_A710_2055002	?=0
-
-# Flag to apply erratum 2017096 workaround during reset. This erratum applies
-# to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is still open.
-ERRATA_A710_2017096	?=0
-
-# Flag to apply erratum 2267065 workaround during reset. This erratum applies
-# to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is fixed in r2p1.
-ERRATA_A710_2267065	?=0
-
-# Flag to apply erratum 2136059 workaround during reset. This erratum applies
-# to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is fixed in r2p1.
-ERRATA_A710_2136059	?=0
-
 # Flag to apply erratum 2002765 workaround during reset. This erratum applies
 # to revisions r0p0, r1p0, and r2p0 of the Cortex-X2 cpu and is still open.
 ERRATA_X2_2002765	?=0
@@ -530,6 +539,36 @@
 # r2p1.
 ERRATA_X2_2216384	?=0
 
+# Flag to apply erratum 1922240 workaround during reset. This erratum applies
+# to revision r0p0 of the Cortex-A510 cpu and is fixed in r0p1.
+ERRATA_A510_1922240	?=0
+
+# Flag to apply erratum 2288014 workaround during reset. This erratum applies
+# to revisions r0p0, r0p1, r0p2, r0p3 and r1p0 of the Cortex-A510 cpu and is
+# fixed in r1p1.
+ERRATA_A510_2288014	?=0
+
+# Flag to apply erratum 2042739 workaround during reset. This erratum applies
+# to revisions r0p0, r0p1 and r0p2 of the Cortex-A510 cpu and is fixed in r0p3.
+ERRATA_A510_2042739	?=0
+
+# Flag to apply erratum 2041909 workaround during reset. This erratum applies
+# to revision r0p2 of the Cortex-A510 cpu and is fixed in r0p3. The issue is
+# present in r0p0 and r0p1 but there is no workaround for those revisions.
+ERRATA_A510_2041909	?=0
+
+# Flag to apply erratum 2250311 workaround during reset. This erratum applies
+# to revisions r0p0, r0p1, r0p2, r0p3 and r1p0, and is fixed in r1p1.
+ERRATA_A510_2250311	?=0
+
+# Flag to apply erratum 2218950 workaround during reset. This erratum applies
+# to revisions r0p0, r0p1, r0p2, r0p3 and r1p0, and is fixed in r1p1.
+ERRATA_A510_2218950	?=0
+
+# Flag to apply erratum 2172148 workaround during reset. This erratum applies
+# to revisions r0p0, r0p1, r0p2, r0p3 and r1p0, and is fixed in r1p1.
+ERRATA_A510_2172148	?=0
+
 # Flag to apply DSU erratum 798953. This erratum applies to DSUs revision r0p0.
 # Applying the workaround results in higher DSU power consumption on idle.
 ERRATA_DSU_798953	?=0
@@ -911,6 +950,26 @@
 $(eval $(call assert_boolean,ERRATA_A710_2058056))
 $(eval $(call add_define,ERRATA_A710_2058056))
 
+# Process ERRATA_A710_2055002 flag
+$(eval $(call assert_boolean,ERRATA_A710_2055002))
+$(eval $(call add_define,ERRATA_A710_2055002))
+
+# Process ERRATA_A710_2017096 flag
+$(eval $(call assert_boolean,ERRATA_A710_2017096))
+$(eval $(call add_define,ERRATA_A710_2017096))
+
+# Process ERRATA_A710_2267065 flag
+$(eval $(call assert_boolean,ERRATA_A710_2267065))
+$(eval $(call add_define,ERRATA_A710_2267065))
+
+# Process ERRATA_A710_2136059 flag
+$(eval $(call assert_boolean,ERRATA_A710_2136059))
+$(eval $(call add_define,ERRATA_A710_2136059))
+
+# Process ERRATA_A710_2282622 flag
+$(eval $(call assert_boolean,ERRATA_A710_2282622))
+$(eval $(call add_define,ERRATA_A710_2282622))
+
 # Process ERRATA_N2_2067956 flag
 $(eval $(call assert_boolean,ERRATA_N2_2067956))
 $(eval $(call add_define,ERRATA_N2_2067956))
@@ -947,22 +1006,6 @@
 $(eval $(call assert_boolean,ERRATA_N2_2280757))
 $(eval $(call add_define,ERRATA_N2_2280757))
 
-# Process ERRATA_A710_2055002 flag
-$(eval $(call assert_boolean,ERRATA_A710_2055002))
-$(eval $(call add_define,ERRATA_A710_2055002))
-
-# Process ERRATA_A710_2017096 flag
-$(eval $(call assert_boolean,ERRATA_A710_2017096))
-$(eval $(call add_define,ERRATA_A710_2017096))
-
-# Process ERRATA_A710_2267065 flag
-$(eval $(call assert_boolean,ERRATA_A710_2267065))
-$(eval $(call add_define,ERRATA_A710_2267065))
-
-# Process ERRATA_A710_2136059 flag
-$(eval $(call assert_boolean,ERRATA_A710_2136059))
-$(eval $(call add_define,ERRATA_A710_2136059))
-
 # Process ERRATA_X2_2002765 flag
 $(eval $(call assert_boolean,ERRATA_X2_2002765))
 $(eval $(call add_define,ERRATA_X2_2002765))
@@ -987,6 +1030,34 @@
 $(eval $(call assert_boolean,ERRATA_X2_2216384))
 $(eval $(call add_define,ERRATA_X2_2216384))
 
+# Process ERRATA_A510_1922240 flag
+$(eval $(call assert_boolean,ERRATA_A510_1922240))
+$(eval $(call add_define,ERRATA_A510_1922240))
+
+# Process ERRATA_A510_2288014 flag
+$(eval $(call assert_boolean,ERRATA_A510_2288014))
+$(eval $(call add_define,ERRATA_A510_2288014))
+
+# Process ERRATA_A510_2042739 flag
+$(eval $(call assert_boolean,ERRATA_A510_2042739))
+$(eval $(call add_define,ERRATA_A510_2042739))
+
+# Process ERRATA_A510_2041909 flag
+$(eval $(call assert_boolean,ERRATA_A510_2041909))
+$(eval $(call add_define,ERRATA_A510_2041909))
+
+# Process ERRATA_A510_2250311 flag
+$(eval $(call assert_boolean,ERRATA_A510_2250311))
+$(eval $(call add_define,ERRATA_A510_2250311))
+
+# Process ERRATA_A510_2218950 flag
+$(eval $(call assert_boolean,ERRATA_A510_2218950))
+$(eval $(call add_define,ERRATA_A510_2218950))
+
+# Process ERRATA_A510_2172148 flag
+$(eval $(call assert_boolean,ERRATA_A510_2172148))
+$(eval $(call add_define,ERRATA_A510_2172148))
+
 # Process ERRATA_DSU_798953 flag
 $(eval $(call assert_boolean,ERRATA_DSU_798953))
 $(eval $(call add_define,ERRATA_DSU_798953))
diff --git a/lib/fconf/fconf_cot_getter.c b/lib/fconf/fconf_cot_getter.c
index adfa534..ae59d8c 100644
--- a/lib/fconf/fconf_cot_getter.c
+++ b/lib/fconf/fconf_cot_getter.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,7 +8,7 @@
 #include <stddef.h>
 
 #include <common/fdt_wrappers.h>
-#include <drivers/auth/mbedtls/mbedtls_config.h>
+#include MBEDTLS_CONFIG_FILE
 #include <drivers/auth/auth_mod.h>
 #include <lib/fconf/fconf.h>
 #include <lib/object_pool.h>
diff --git a/lib/gpt_rme/gpt_rme.c b/lib/gpt_rme/gpt_rme.c
index e424fe2..d6fbc04 100644
--- a/lib/gpt_rme/gpt_rme.c
+++ b/lib/gpt_rme/gpt_rme.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -95,9 +95,8 @@
 	if ((gpi == GPT_GPI_NO_ACCESS) || (gpi == GPT_GPI_ANY) ||
 	    ((gpi >= GPT_GPI_SECURE) && (gpi <= GPT_GPI_REALM))) {
 		return true;
-	} else {
-		return false;
 	}
+	return false;
 }
 
 /*
@@ -117,9 +116,8 @@
 {
 	if (((base_1 + size_1) > base_2) && ((base_2 + size_2) > base_1)) {
 		return true;
-	} else {
-		return false;
 	}
+	return false;
 }
 
 /*
@@ -434,14 +432,14 @@
 	gpt_desc = GPT_L0_BLK_DESC(GPT_PAS_ATTR_GPI(pas->attrs));
 
 	/* Start index of this region in L0 GPTs */
-	idx = pas->base_pa >> GPT_L0_IDX_SHIFT;
+	idx = GPT_L0_IDX(pas->base_pa);
 
 	/*
 	 * Determine number of L0 GPT descriptors covered by
 	 * this PAS region and use the count to populate these
 	 * descriptors.
 	 */
-	end_idx = (pas->base_pa + pas->size) >> GPT_L0_IDX_SHIFT;
+	end_idx = GPT_L0_IDX(pas->base_pa + pas->size);
 
 	/* Generate the needed block descriptors. */
 	for (; idx < end_idx; idx++) {
@@ -471,8 +469,8 @@
 	uintptr_t cur_idx;
 	uintptr_t end_idx;
 
-	cur_idx = cur_pa >> GPT_L0_IDX_SHIFT;
-	end_idx = end_pa >> GPT_L0_IDX_SHIFT;
+	cur_idx = GPT_L0_IDX(cur_pa);
+	end_idx = GPT_L0_IDX(end_pa);
 
 	assert(cur_idx <= end_idx);
 
@@ -770,7 +768,7 @@
 
 	/* Validate other parameters. */
 	ret = gpt_validate_l0_params(pps, l0_mem_base, l0_mem_size);
-	if (ret < 0) {
+	if (ret != 0) {
 		return ret;
 	}
 
@@ -849,7 +847,7 @@
 	if (l1_gpt_cnt > 0) {
 		ret = gpt_validate_l1_params(l1_mem_base, l1_mem_size,
 		      l1_gpt_cnt);
-		if (ret < 0) {
+		if (ret != 0) {
 			return ret;
 		}
 
@@ -958,55 +956,170 @@
 static spinlock_t gpt_lock;
 
 /*
- * Check if caller is allowed to transition a PAS.
- *
- * - Secure world caller can only request S <-> NS transitions on a
- *   granule that is already in either S or NS PAS.
+ * A helper to write the value (target_pas << gpi_shift) to the index of
+ * the gpt_l1_addr
+ */
+static inline void write_gpt(uint64_t *gpt_l1_desc, uint64_t *gpt_l1_addr,
+			     unsigned int gpi_shift, unsigned int idx,
+			     unsigned int target_pas)
+{
+	*gpt_l1_desc &= ~(GPT_L1_GRAN_DESC_GPI_MASK << gpi_shift);
+	*gpt_l1_desc |= ((uint64_t)target_pas << gpi_shift);
+	gpt_l1_addr[idx] = *gpt_l1_desc;
+}
+
+/*
+ * Helper to retrieve the gpt_l1_* information from the base address
+ * returned in gpi_info
+ */
+static int get_gpi_params(uint64_t base, gpi_info_t *gpi_info)
+{
+	uint64_t gpt_l0_desc, *gpt_l0_base;
+
+	gpt_l0_base = (uint64_t *)gpt_config.plat_gpt_l0_base;
+	gpt_l0_desc = gpt_l0_base[GPT_L0_IDX(base)];
+	if (GPT_L0_TYPE(gpt_l0_desc) != GPT_L0_TYPE_TBL_DESC) {
+		VERBOSE("[GPT] Granule is not covered by a table descriptor!\n");
+		VERBOSE("      Base=0x%" PRIx64 "\n", base);
+		return -EINVAL;
+	}
+
+	/* Get the table index and GPI shift from PA. */
+	gpi_info->gpt_l1_addr = GPT_L0_TBLD_ADDR(gpt_l0_desc);
+	gpi_info->idx = GPT_L1_IDX(gpt_config.p, base);
+	gpi_info->gpi_shift = GPT_L1_GPI_IDX(gpt_config.p, base) << 2;
+
+	gpi_info->gpt_l1_desc = (gpi_info->gpt_l1_addr)[gpi_info->idx];
+	gpi_info->gpi = (gpi_info->gpt_l1_desc >> gpi_info->gpi_shift) &
+		GPT_L1_GRAN_DESC_GPI_MASK;
+	return 0;
+}
+
+/*
+ * This function is the granule transition delegate service. When a granule
+ * transition request occurs it is routed to this function to have the request,
+ * if valid, fulfilled following A1.1.1 Delegate of RME supplement
  *
- * - Realm world caller can only request R <-> NS transitions on a
- *   granule that is already in either R or NS PAS.
+ * TODO: implement support for transitioning multiple granules at once.
  *
  * Parameters
+ *   base		Base address of the region to transition, must be
+ *			aligned to granule size.
+ *   size		Size of region to transition, must be aligned to granule
+ *			size.
  *   src_sec_state	Security state of the caller.
- *   current_gpi	Current GPI of the granule.
- *   target_gpi		Requested new GPI for the granule.
  *
  * Return
  *   Negative Linux error code in the event of a failure, 0 for success.
  */
-static int gpt_check_transition_gpi(unsigned int src_sec_state,
-				    unsigned int current_gpi,
-				    unsigned int target_gpi)
+int gpt_delegate_pas(uint64_t base, size_t size, unsigned int src_sec_state)
 {
-	unsigned int check_gpi;
+	gpi_info_t gpi_info;
+	uint64_t nse;
+	int res;
+	unsigned int target_pas;
+
+	/* Ensure that the tables have been set up before taking requests. */
+	assert(gpt_config.plat_gpt_l0_base != 0UL);
 
-	/* Cannot transition a granule to the state it is already in. */
-	if (current_gpi == target_gpi) {
+	/* Ensure that caches are enabled. */
+	assert((read_sctlr_el3() & SCTLR_C_BIT) != 0UL);
+
+	/* Delegate request can only come from REALM or SECURE */
+	assert(src_sec_state == SMC_FROM_REALM ||
+	       src_sec_state == SMC_FROM_SECURE);
+
+	/* See if this is a single or a range of granule transition. */
+	if (size != GPT_PGS_ACTUAL_SIZE(gpt_config.p)) {
 		return -EINVAL;
 	}
 
-	/* Check security state, only secure and realm can transition. */
-	if (src_sec_state == SMC_FROM_REALM) {
-		check_gpi = GPT_GPI_REALM;
-	} else if (src_sec_state == SMC_FROM_SECURE) {
-		check_gpi = GPT_GPI_SECURE;
-	} else {
+	/* Check that base and size are valid */
+	if ((ULONG_MAX - base) < size) {
+		VERBOSE("[GPT] Transition request address overflow!\n");
+		VERBOSE("      Base=0x%" PRIx64 "\n", base);
+		VERBOSE("      Size=0x%lx\n", size);
 		return -EINVAL;
 	}
 
-	/* Make sure security state is allowed to make the transition. */
-	if ((target_gpi != check_gpi) && (target_gpi != GPT_GPI_NS)) {
+	/* Make sure base and size are valid. */
+	if (((base & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) != 0UL) ||
+	    ((size & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) != 0UL) ||
+	    (size == 0UL) ||
+	    ((base + size) >= GPT_PPS_ACTUAL_SIZE(gpt_config.t))) {
+		VERBOSE("[GPT] Invalid granule transition address range!\n");
+		VERBOSE("      Base=0x%" PRIx64 "\n", base);
+		VERBOSE("      Size=0x%lx\n", size);
 		return -EINVAL;
 	}
+
+	target_pas = GPT_GPI_REALM;
+	if (src_sec_state == SMC_FROM_SECURE) {
+		target_pas = GPT_GPI_SECURE;
+	}
-	if ((current_gpi != check_gpi) && (current_gpi != GPT_GPI_NS)) {
+
+	/*
+	 * Access to L1 tables is controlled by a global lock to ensure
+	 * that no more than one CPU is allowed to make changes at any
+	 * given time.
+	 */
+	spin_lock(&gpt_lock);
+	res = get_gpi_params(base, &gpi_info);
+	if (res != 0) {
+		spin_unlock(&gpt_lock);
+		return res;
+	}
+
+	/* Check that the current address is in NS state */
+	if (gpi_info.gpi != GPT_GPI_NS) {
+		VERBOSE("[GPT] Only Granule in NS state can be delegated.\n");
+		VERBOSE("      Caller: %u, Current GPI: %u\n", src_sec_state,
+			gpi_info.gpi);
+		spin_unlock(&gpt_lock);
 		return -EINVAL;
 	}
 
+	if (src_sec_state == SMC_FROM_SECURE) {
+		nse = (uint64_t)GPT_NSE_SECURE << GPT_NSE_SHIFT;
+	} else {
+		nse = (uint64_t)GPT_NSE_REALM << GPT_NSE_SHIFT;
+	}
+
+	/*
+	 * In order to maintain mutual distrust between Realm and Secure
+	 * states, remove any data speculatively fetched into the target
+	 * physical address space. Issue DC CIPAPA over address range
+	 */
+	flush_dcache_to_popa_range(nse | base,
+				   GPT_PGS_ACTUAL_SIZE(gpt_config.p));
+
+	write_gpt(&gpi_info.gpt_l1_desc, gpi_info.gpt_l1_addr,
+		  gpi_info.gpi_shift, gpi_info.idx, target_pas);
+	dsboshst();
+
+	gpt_tlbi_by_pa_ll(base, GPT_PGS_ACTUAL_SIZE(gpt_config.p));
+	dsbosh();
+
+	nse = (uint64_t)GPT_NSE_NS << GPT_NSE_SHIFT;
+
+	flush_dcache_to_popa_range(nse | base,
+				   GPT_PGS_ACTUAL_SIZE(gpt_config.p));
+
+	/* Unlock access to the L1 tables. */
+	spin_unlock(&gpt_lock);
+
+	/*
+	 * The isb() will be done as part of context
+	 * synchronization when returning to lower EL
+	 */
+	VERBOSE("[GPT] Granule 0x%" PRIx64 ", GPI 0x%x->0x%x\n",
+		base, gpi_info.gpi, target_pas);
+
 	return 0;
 }
 
 /*
- * This function is the core of the granule transition service. When a granule
+ * This function is the granule transition undelegate service. When a granule
  * transition request occurs it is routed to this function where the request is
  * validated then fulfilled if possible.
  *
@@ -1018,29 +1131,32 @@
  *   size		Size of region to transition, must be aligned to granule
  *			size.
  *   src_sec_state	Security state of the caller.
- *   target_pas		Target PAS of the specified memory region.
  *
  * Return
  *    Negative Linux error code in the event of a failure, 0 for success.
  */
-int gpt_transition_pas(uint64_t base, size_t size, unsigned int src_sec_state,
-	unsigned int target_pas)
+int gpt_undelegate_pas(uint64_t base, size_t size, unsigned int src_sec_state)
 {
-	int idx;
-	unsigned int gpi_shift;
-	unsigned int gpi;
-	uint64_t gpt_l0_desc;
-	uint64_t gpt_l1_desc;
-	uint64_t *gpt_l1_addr;
-	uint64_t *gpt_l0_base;
+	gpi_info_t gpi_info;
+	uint64_t nse;
+	int res;
 
 	/* Ensure that the tables have been set up before taking requests. */
-	assert(gpt_config.plat_gpt_l0_base != 0U);
+	assert(gpt_config.plat_gpt_l0_base != 0UL);
 
-	/* Ensure that MMU and data caches are enabled. */
-	assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
+	/* Ensure that MMU and caches are enabled. */
+	assert((read_sctlr_el3() & SCTLR_C_BIT) != 0UL);
+
+	/* Delegate request can only come from REALM or SECURE */
+	assert(src_sec_state == SMC_FROM_REALM ||
+	       src_sec_state == SMC_FROM_SECURE);
 
-	/* Check for address range overflow. */
+	/* See if this is a single or a range of granule transition. */
+	if (size != GPT_PGS_ACTUAL_SIZE(gpt_config.p)) {
+		return -EINVAL;
+	}
+
+	/* Check that base and size are valid */
 	if ((ULONG_MAX - base) < size) {
 		VERBOSE("[GPT] Transition request address overflow!\n");
 		VERBOSE("      Base=0x%" PRIx64 "\n", base);
@@ -1049,9 +1165,9 @@
 	}
 
 	/* Make sure base and size are valid. */
-	if (((base & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) != 0U) ||
-	    ((size & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) != 0U) ||
-	    (size == 0U) ||
+	if (((base & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) != 0UL) ||
+	    ((size & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) != 0UL) ||
+	    (size == 0UL) ||
 	    ((base + size) >= GPT_PPS_ACTUAL_SIZE(gpt_config.t))) {
 		VERBOSE("[GPT] Invalid granule transition address range!\n");
 		VERBOSE("      Base=0x%" PRIx64 "\n", base);
@@ -1059,66 +1175,81 @@
 		return -EINVAL;
 	}
 
-	/* See if this is a single granule transition or a range of granules. */
-	if (size != GPT_PGS_ACTUAL_SIZE(gpt_config.p)) {
-		/*
-		 * TODO: Add support for transitioning multiple granules with a
-		 * single call to this function.
-		 */
-		panic();
-	}
-
-	/* Get the L0 descriptor and make sure it is for a table. */
-	gpt_l0_base = (uint64_t *)gpt_config.plat_gpt_l0_base;
-	gpt_l0_desc = gpt_l0_base[GPT_L0_IDX(base)];
-	if (GPT_L0_TYPE(gpt_l0_desc) != GPT_L0_TYPE_TBL_DESC) {
-		VERBOSE("[GPT] Granule is not covered by a table descriptor!\n");
-		VERBOSE("      Base=0x%" PRIx64 "\n", base);
-		return -EINVAL;
-	}
-
-	/* Get the table index and GPI shift from PA. */
-	gpt_l1_addr = GPT_L0_TBLD_ADDR(gpt_l0_desc);
-	idx = GPT_L1_IDX(gpt_config.p, base);
-	gpi_shift = GPT_L1_GPI_IDX(gpt_config.p, base) << 2;
-
 	/*
 	 * Access to L1 tables is controlled by a global lock to ensure
 	 * that no more than one CPU is allowed to make changes at any
 	 * given time.
 	 */
 	spin_lock(&gpt_lock);
-	gpt_l1_desc = gpt_l1_addr[idx];
-	gpi = (gpt_l1_desc >> gpi_shift) & GPT_L1_GRAN_DESC_GPI_MASK;
 
-	/* Make sure caller state and source/target PAS are allowed. */
-	if (gpt_check_transition_gpi(src_sec_state, gpi, target_pas) < 0) {
+	res = get_gpi_params(base, &gpi_info);
+	if (res != 0) {
 		spin_unlock(&gpt_lock);
-			VERBOSE("[GPT] Invalid caller state and PAS combo!\n");
-		VERBOSE("      Caller: %u, Current GPI: %u, Target GPI: %u\n",
-			src_sec_state, gpi, target_pas);
-		return -EPERM;
+		return res;
+	}
+
+	/* Check that the current address is in the delegated state */
+	if ((src_sec_state == SMC_FROM_REALM  &&
+	     gpi_info.gpi != GPT_GPI_REALM) ||
+	    (src_sec_state == SMC_FROM_SECURE &&
+	     gpi_info.gpi != GPT_GPI_SECURE)) {
+		VERBOSE("[GPT] Only Granule in REALM or SECURE state can be undelegated.\n");
+		VERBOSE("      Caller: %u, Current GPI: %u\n", src_sec_state,
+			gpi_info.gpi);
+		spin_unlock(&gpt_lock);
+		return -EINVAL;
 	}
 
+
+	/* In order to maintain mutual distrust between Realm and Secure
+	 * states, remove access now, in order to guarantee that writes
+	 * to the currently-accessible physical address space will not
+	 * later become observable.
+	 */
+	write_gpt(&gpi_info.gpt_l1_desc, gpi_info.gpt_l1_addr,
+		  gpi_info.gpi_shift, gpi_info.idx, GPT_GPI_NO_ACCESS);
+	dsboshst();
+
+	gpt_tlbi_by_pa_ll(base, GPT_PGS_ACTUAL_SIZE(gpt_config.p));
+	dsbosh();
+
+	if (src_sec_state == SMC_FROM_SECURE) {
+		nse = (uint64_t)GPT_NSE_SECURE << GPT_NSE_SHIFT;
+	} else {
+		nse = (uint64_t)GPT_NSE_REALM << GPT_NSE_SHIFT;
+	}
+
+	/* Ensure that the scrubbed data has made it past the PoPA */
+	flush_dcache_to_popa_range(nse | base,
+				   GPT_PGS_ACTUAL_SIZE(gpt_config.p));
+
+	/*
+	 * Remove any data loaded speculatively
+	 * in NS space from before the scrubbing
+	 */
+	nse = (uint64_t)GPT_NSE_NS << GPT_NSE_SHIFT;
+
+	flush_dcache_to_popa_range(nse | base,
+				   GPT_PGS_ACTUAL_SIZE(gpt_config.p));
+
 	/* Clear existing GPI encoding and transition granule. */
-	gpt_l1_desc &= ~(GPT_L1_GRAN_DESC_GPI_MASK << gpi_shift);
-	gpt_l1_desc |= ((uint64_t)target_pas << gpi_shift);
-	gpt_l1_addr[idx] = gpt_l1_desc;
+	write_gpt(&gpi_info.gpt_l1_desc, gpi_info.gpt_l1_addr,
+		  gpi_info.gpi_shift, gpi_info.idx, GPT_GPI_NS);
+	dsboshst();
 
-	/* Ensure that the write operation will be observed by GPC */
-	dsbishst();
+	/* Ensure that all agents observe the new NS configuration */
+	gpt_tlbi_by_pa_ll(base, GPT_PGS_ACTUAL_SIZE(gpt_config.p));
+	dsbosh();
 
 	/* Unlock access to the L1 tables. */
 	spin_unlock(&gpt_lock);
 
-	gpt_tlbi_by_pa(base, GPT_PGS_ACTUAL_SIZE(gpt_config.p));
-	dsbishst();
 	/*
 	 * The isb() will be done as part of context
 	 * synchronization when returning to lower EL
 	 */
-	VERBOSE("[GPT] Granule 0x%" PRIx64 ", GPI 0x%x->0x%x\n", base, gpi,
-		target_pas);
+	VERBOSE("[GPT] Granule 0x%" PRIx64 ", GPI 0x%x->0x%x\n",
+		base, gpi_info.gpi, GPT_GPI_NS);
 
 	return 0;
 }
diff --git a/lib/gpt_rme/gpt_rme_private.h b/lib/gpt_rme/gpt_rme_private.h
index 4203bba..3c817f3 100644
--- a/lib/gpt_rme/gpt_rme_private.h
+++ b/lib/gpt_rme/gpt_rme_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -106,6 +106,17 @@
 	PGS_64KB_P =	16U
 } gpt_p_val_e;
 
+/*
+ * Internal structure to retrieve the values from get_gpi_info();
+ */
+typedef struct gpi_info {
+	uint64_t gpt_l1_desc;
+	uint64_t *gpt_l1_addr;
+	unsigned int idx;
+	unsigned int gpi_shift;
+	unsigned int gpi;
+} gpi_info_t;
+
 /* Max valid value for PGS. */
 #define GPT_PGS_MAX			(2U)
 
diff --git a/lib/mpmm/mpmm.c b/lib/mpmm/mpmm.c
index a66f2aa..dc61cf6 100644
--- a/lib/mpmm/mpmm.c
+++ b/lib/mpmm/mpmm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -62,11 +62,25 @@
 	return supported;
 }
 
+/* Defaults to false */
+static bool mpmm_disable_for_errata;
+
 void mpmm_enable(void)
 {
-	bool supported = mpmm_supported();
-
-	if (supported) {
+	if (mpmm_supported()) {
+		if (mpmm_disable_for_errata) {
+			WARN("MPMM: disabled by errata workaround\n");
+			return;
+		}
 		write_cpumpmmcr_el3_mpmm_en(1U);
 	}
 }
+
+/*
+ * This function is called from assembly code very early in BL31 so it must be
+ * small and simple.
+ */
+void mpmm_errata_disable(void)
+{
+	mpmm_disable_for_errata = true;
+}
diff --git a/plat/arm/board/fvp/fdts/optee_sp_manifest.dts b/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
index 551efe6..b803340 100644
--- a/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
+++ b/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
@@ -40,11 +40,5 @@
 			pages-count = <1>;
 			attributes = <0x3>; /* read-write */
 		};
-
-		gicd {
-			base-address = <0x00000000 0x2f000000>;
-			pages-count = <16>;
-			attributes = <0x3>; /* read-write */
-		};
 	};
 };
diff --git a/plat/arm/board/fvp/fvp_bl2_measured_boot.c b/plat/arm/board/fvp/fvp_bl2_measured_boot.c
index af43065..1f38278 100644
--- a/plat/arm/board/fvp/fvp_bl2_measured_boot.c
+++ b/plat/arm/board/fvp/fvp_bl2_measured_boot.c
@@ -28,6 +28,7 @@
 	{ SCP_BL2_IMAGE_ID, EVLOG_SCP_BL2_STRING, PCR_0 },
 	{ SOC_FW_CONFIG_ID, EVLOG_SOC_FW_CONFIG_STRING, PCR_0 },
 	{ TOS_FW_CONFIG_ID, EVLOG_TOS_FW_CONFIG_STRING, PCR_0 },
+	{ RMM_IMAGE_ID, EVLOG_RMM_STRING, PCR_0},
 
 	{ CRITICAL_DATA_ID, EVLOG_CRITICAL_DATA_STRING, PCR_1 },
 
diff --git a/plat/arm/board/fvp/fvp_bl31_setup.c b/plat/arm/board/fvp/fvp_bl31_setup.c
index f9ee449..a94a4f4 100644
--- a/plat/arm/board/fvp/fvp_bl31_setup.c
+++ b/plat/arm/board/fvp/fvp_bl31_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -20,6 +20,9 @@
 void __init bl31_early_platform_setup2(u_register_t arg0,
 		u_register_t arg1, u_register_t arg2, u_register_t arg3)
 {
+	/* Initialize the console to provide early debug support */
+	arm_console_boot_init();
+
 #if !RESET_TO_BL31 && !BL2_AT_EL3
 	const struct dyn_cfg_dtb_info_t *soc_fw_config_info;
 
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index a24a2e5..acac886 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -308,14 +308,6 @@
 # Enable dynamic mitigation support by default
 DYNAMIC_WORKAROUND_CVE_2018_3639	:=	1
 
-# Enable reclaiming of BL31 initialisation code for secondary cores
-# stacks for FVP. However, don't enable reclaiming for clang.
-ifneq (${RESET_TO_BL31},1)
-ifeq ($(findstring clang,$(notdir $(CC))),)
-RECLAIM_INIT_CODE	:=	1
-endif
-endif
-
 ifeq (${ENABLE_AMU},1)
 BL31_SOURCES		+=	lib/cpus/aarch64/cpuamu.c		\
 				lib/cpus/aarch64/cpuamu_helpers.S
diff --git a/plat/arm/board/rdn2/platform.mk b/plat/arm/board/rdn2/platform.mk
index 753ba32..b882dc8 100644
--- a/plat/arm/board/rdn2/platform.mk
+++ b/plat/arm/board/rdn2/platform.mk
@@ -30,7 +30,8 @@
 
 PLAT_INCLUDES		+=	-I${RDN2_BASE}/include/
 
-SGI_CPU_SOURCES		:=	lib/cpus/aarch64/neoverse_n2.S
+SGI_CPU_SOURCES		:=	lib/cpus/aarch64/neoverse_n2.S \
+				lib/cpus/aarch64/neoverse_demeter.S
 
 PLAT_BL_COMMON_SOURCES	+=	${CSS_ENT_BASE}/sgi_plat_v2.c
 
diff --git a/plat/arm/common/arm_console.c b/plat/arm/common/arm_console.c
index af5f11e..51830c9 100644
--- a/plat/arm/common/arm_console.c
+++ b/plat/arm/common/arm_console.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -25,6 +25,11 @@
 /* Initialize the console to provide early debug support */
 void __init arm_console_boot_init(void)
 {
+	/* If the console was initialized already, don't initialize again */
+	if (arm_boot_console.base == PLAT_ARM_BOOT_UART_BASE) {
+		return;
+	}
+
 	int rc = console_pl011_register(PLAT_ARM_BOOT_UART_BASE,
 					PLAT_ARM_BOOT_UART_CLK_IN_HZ,
 					ARM_CONSOLE_BAUDRATE,
diff --git a/plat/arm/css/sgi/include/sgi_variant.h b/plat/arm/css/sgi/include/sgi_variant.h
index 0062b97..41467f7 100644
--- a/plat/arm/css/sgi/include/sgi_variant.h
+++ b/plat/arm/css/sgi/include/sgi_variant.h
@@ -23,6 +23,10 @@
 /* SID Version values for RD-N2 variants */
 #define RD_N2_CFG1_SID_VER_PART_NUM		0x07B6
 
+/* SID Version values for RD-Edmunds */
+#define RD_EDMUNDS_SID_VER_PART_NUM		0x07F2
+#define RD_EDMUNDS_CONFIG_ID			0x1
+
 /* Structure containing SGI platform variant information */
 typedef struct sgi_platform_info {
 	unsigned int platform_id;	/* Part Number of the platform */
diff --git a/plat/arm/css/sgi/sgi_bl31_setup.c b/plat/arm/css/sgi/sgi_bl31_setup.c
index 541689b..99f2f20 100644
--- a/plat/arm/css/sgi/sgi_bl31_setup.c
+++ b/plat/arm/css/sgi/sgi_bl31_setup.c
@@ -76,6 +76,7 @@
 	if (sgi_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM ||
 		sgi_plat_info.platform_id == RD_V1_SID_VER_PART_NUM ||
 		sgi_plat_info.platform_id == RD_N2_SID_VER_PART_NUM ||
+		sgi_plat_info.platform_id == RD_EDMUNDS_SID_VER_PART_NUM ||
 		sgi_plat_info.platform_id == RD_N2_CFG1_SID_VER_PART_NUM) {
 		if (channel_id >= ARRAY_SIZE(plat_rd_scmi_info))
 			panic();
diff --git a/plat/brcm/board/common/board_common.mk b/plat/brcm/board/common/board_common.mk
index 3b3e92d..24a27ed 100644
--- a/plat/brcm/board/common/board_common.mk
+++ b/plat/brcm/board/common/board_common.mk
@@ -214,14 +214,12 @@
 endif
 
 # Include mbedtls if it can be located
-MBEDTLS_DIR := mbedtls
-MBEDTLS_CHECK := $(shell find ${MBEDTLS_DIR}/include -name '${MBEDTLS_DIR}')
+MBEDTLS_DIR ?= mbedtls
+MBEDTLS_CHECK := $(shell find ${MBEDTLS_DIR}/include -name '$(notdir ${MBEDTLS_DIR})')
 
 ifneq (${MBEDTLS_CHECK},)
 $(info Found mbedTLS at ${MBEDTLS_DIR})
 PLAT_INCLUDES += -I${MBEDTLS_DIR}/include/mbedtls
-# Specify mbedTLS configuration file
-MBEDTLS_CONFIG_FILE	:=	"<brcm_mbedtls_config.h>"
 
 # By default, use RSA keys
 KEY_ALG := rsa_1_5
diff --git a/plat/intel/soc/agilex/bl2_plat_setup.c b/plat/intel/soc/agilex/bl2_plat_setup.c
index b6b3e16..6e67502 100644
--- a/plat/intel/soc/agilex/bl2_plat_setup.c
+++ b/plat/intel/soc/agilex/bl2_plat_setup.c
@@ -7,6 +7,7 @@
 
 #include <arch.h>
 #include <arch_helpers.h>
+#include <assert.h>
 #include <common/bl_common.h>
 #include <common/debug.h>
 #include <common/desc_image_load.h>
@@ -113,6 +114,9 @@
 	mmc_info.mmc_dev_type = MMC_IS_SD;
 	mmc_info.ocr_voltage = OCR_3_3_3_4 | OCR_3_2_3_3;
 
+	/* Request ownership and direct access to QSPI */
+	mailbox_hps_qspi_enable();
+
 	switch (boot_source) {
 	case BOOT_SOURCE_SDMMC:
 		dw_mmc_init(&params, &mmc_info);
@@ -120,8 +124,6 @@
 		break;
 
 	case BOOT_SOURCE_QSPI:
-		mailbox_set_qspi_open();
-		mailbox_set_qspi_direct();
 		cad_qspi_init(0, QSPI_CONFIG_CPHA, QSPI_CONFIG_CPOL,
 			QSPI_CONFIG_CSDA, QSPI_CONFIG_CSDADS,
 			QSPI_CONFIG_CSEOT, QSPI_CONFIG_CSSOT, 0);
@@ -161,6 +163,8 @@
 {
 	bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
 
+	assert(bl_mem_params);
+
 	switch (image_id) {
 	case BL33_IMAGE_ID:
 		bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
diff --git a/plat/intel/soc/agilex/include/socfpga_plat_def.h b/plat/intel/soc/agilex/include/socfpga_plat_def.h
index 6c9d81c..9c87e45 100644
--- a/plat/intel/soc/agilex/include/socfpga_plat_def.h
+++ b/plat/intel/soc/agilex/include/socfpga_plat_def.h
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,6 +14,10 @@
 #define PLATFORM_MODEL				PLAT_SOCFPGA_AGILEX
 #define BOOT_SOURCE				BOOT_SOURCE_SDMMC
 
+/* FPGA config helpers */
+#define INTEL_SIP_SMC_FPGA_CONFIG_ADDR		0x400000
+#define INTEL_SIP_SMC_FPGA_CONFIG_SIZE		0x2000000
+
 /* Register Mapping */
 #define SOCFPGA_MMC_REG_BASE			0xff808000
 
diff --git a/plat/intel/soc/agilex/platform.mk b/plat/intel/soc/agilex/platform.mk
index bf5cc14..10a3eec 100644
--- a/plat/intel/soc/agilex/platform.mk
+++ b/plat/intel/soc/agilex/platform.mk
@@ -1,6 +1,6 @@
 #
-# Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
-# Copyright (c) 2019-2020, Intel Corporation. All rights reserved.
+# Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -65,6 +65,8 @@
 		plat/intel/soc/common/socfpga_psci.c			\
 		plat/intel/soc/common/socfpga_sip_svc.c			\
 		plat/intel/soc/common/socfpga_topology.c		\
+		plat/intel/soc/common/sip/socfpga_sip_ecc.c		\
+		plat/intel/soc/common/sip/socfpga_sip_fcs.c		\
 		plat/intel/soc/common/soc/socfpga_mailbox.c		\
 		plat/intel/soc/common/soc/socfpga_reset_manager.c
 
@@ -72,4 +74,5 @@
 BL2_AT_EL3			:= 1
 BL2_INV_DCACHE			:= 0
 MULTI_CONSOLE_API		:= 1
+SIMICS_BUILD			:= 0
 USE_COHERENT_MEM		:= 1
diff --git a/plat/intel/soc/common/drivers/ccu/ncore_ccu.c b/plat/intel/soc/common/drivers/ccu/ncore_ccu.c
index b4fce7b..d4716cf 100644
--- a/plat/intel/soc/common/drivers/ccu/ncore_ccu.c
+++ b/plat/intel/soc/common/drivers/ccu/ncore_ccu.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -107,6 +107,17 @@
 			OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK);
 }
 
+void ncore_enable_ocram_firewall(void)
+{
+	mmio_setbits_32(COH_CPU0_BYPASS_REG(NCORE_FW_OCRAM_BLK_CGF1),
+			OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK);
+	mmio_setbits_32(COH_CPU0_BYPASS_REG(NCORE_FW_OCRAM_BLK_CGF2),
+			OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK);
+	mmio_setbits_32(COH_CPU0_BYPASS_REG(NCORE_FW_OCRAM_BLK_CGF3),
+			OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK);
+	mmio_setbits_32(COH_CPU0_BYPASS_REG(NCORE_FW_OCRAM_BLK_CGF4),
+			OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK);
+}
 uint32_t init_ncore_ccu(void)
 {
 	uint32_t status;
diff --git a/plat/intel/soc/common/drivers/ccu/ncore_ccu.h b/plat/intel/soc/common/drivers/ccu/ncore_ccu.h
index d25ecac..3f662ff 100644
--- a/plat/intel/soc/common/drivers/ccu/ncore_ccu.h
+++ b/plat/intel/soc/common/drivers/ccu/ncore_ccu.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -104,5 +104,6 @@
 } coh_ss_id_t;
 
 uint32_t init_ncore_ccu(void);
+void ncore_enable_ocram_firewall(void);
 
 #endif
diff --git a/plat/intel/soc/common/include/platform_def.h b/plat/intel/soc/common/include/platform_def.h
index 55600ee..7859493 100644
--- a/plat/intel/soc/common/include/platform_def.h
+++ b/plat/intel/soc/common/include/platform_def.h
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2019-2020, Intel Corporation. All rights reserved.
+ * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,8 +13,10 @@
 #include <common/tbbr/tbbr_img_def.h>
 #include <plat/common/common_def.h>
 
+/* Platform Type */
 #define PLAT_SOCFPGA_STRATIX10			1
 #define PLAT_SOCFPGA_AGILEX			2
+#define PLAT_SOCFPGA_N5X			3
 
 /* sysmgr.boot_scratch_cold4 & 5 used for CPU release address for SPL */
 #define PLAT_CPU_RELEASE_ADDR			0xffd12210
@@ -167,9 +169,16 @@
 
 #define CRASH_CONSOLE_BASE	PLAT_UART0_BASE
 
+#ifndef SIMICS_BUILD
 #define PLAT_BAUDRATE		(115200)
 #define PLAT_UART_CLOCK		(100000000)
 
+#else
+#define PLAT_BAUDRATE		(4800)
+#define PLAT_UART_CLOCK		(76800)
+
+#endif
+
 /*******************************************************************************
  * PHY related constants
  ******************************************************************************/
diff --git a/plat/intel/soc/common/include/socfpga_fcs.h b/plat/intel/soc/common/include/socfpga_fcs.h
new file mode 100644
index 0000000..ff10d36
--- /dev/null
+++ b/plat/intel/soc/common/include/socfpga_fcs.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2020-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOCFPGA_FCS_H
+#define SOCFPGA_FCS_H
+
+/* FCS Definitions */
+
+#define FCS_RANDOM_WORD_SIZE		8U
+#define FCS_PROV_DATA_WORD_SIZE		44U
+
+#define FCS_RANDOM_BYTE_SIZE		(FCS_RANDOM_WORD_SIZE * 4U)
+#define FCS_PROV_DATA_BYTE_SIZE		(FCS_PROV_DATA_WORD_SIZE * 4U)
+
+#define FCS_CRYPTION_DATA_0		0x10100
+
+/* FCS Payload Structure */
+
+typedef struct fcs_crypt_payload_t {
+	uint32_t first_word;
+	uint32_t src_addr;
+	uint32_t src_size;
+	uint32_t dst_addr;
+	uint32_t dst_size;
+} fcs_crypt_payload;
+
+/* Functions Definitions */
+
+uint32_t intel_fcs_random_number_gen(uint64_t addr, uint64_t *ret_size,
+				uint32_t *mbox_error);
+uint32_t intel_fcs_send_cert(uint64_t addr, uint64_t size,
+				uint32_t *send_id);
+uint32_t intel_fcs_get_provision_data(uint32_t *send_id);
+uint32_t intel_fcs_cryption(uint32_t mode, uint32_t src_addr,
+			uint32_t src_size, uint32_t dst_addr,
+			uint32_t dst_size, uint32_t *send_id);
+
+#endif /* SOCFPGA_FCS_H */
diff --git a/plat/intel/soc/common/include/socfpga_mailbox.h b/plat/intel/soc/common/include/socfpga_mailbox.h
index 923c4f1..6b7e0fc 100644
--- a/plat/intel/soc/common/include/socfpga_mailbox.h
+++ b/plat/intel/soc/common/include/socfpga_mailbox.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020, Intel Corporation. All rights reserved.
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -40,6 +40,7 @@
 #define MBOX_CMD_SYNC			0x01
 #define MBOX_CMD_RESTART		0x02
 #define MBOX_CMD_CANCEL			0x03
+#define MBOX_CMD_VAB_SRC_CERT		0x0B
 #define MBOX_CMD_GET_IDCODE		0x10
 #define MBOX_CMD_REBOOT_HPS		0x47
 
@@ -61,6 +62,11 @@
 #define MBOX_RSU_UPDATE			0x5C
 #define MBOX_HPS_STAGE_NOTIFY		0x5D
 
+/* FCS Command */
+#define MBOX_FCS_GET_PROVISION			0x7B
+#define MBOX_FCS_ENCRYPT_REQ			0x7E
+#define MBOX_FCS_DECRYPT_REQ			0x7F
+#define MBOX_FCS_RANDOM_GEN			0x80
 
 /* Mailbox Definitions */
 
@@ -69,6 +75,7 @@
 #define CMD_CASUAL			0
 #define CMD_URGENT			1
 
+#define MBOX_WORD_BYTE			4U
 #define MBOX_RESP_BUFFER_SIZE		16
 #define MBOX_CMD_BUFFER_SIZE		32
 
@@ -108,6 +115,9 @@
 
 /* Mailbox Macros */
 
+#define MBOX_ENTRY_TO_ADDR(_buf, ptr)	(MBOX_OFFSET + (MBOX_##_buf##_BUFFER) \
+						+ MBOX_WORD_BYTE * (ptr))
+
 /* Mailbox interrupt flags and masks */
 #define MBOX_INT_FLAG_COE		0x1
 #define MBOX_INT_FLAG_RIE		0x2
@@ -139,23 +149,22 @@
 void mailbox_set_int(uint32_t interrupt_input);
 int mailbox_init(void);
 void mailbox_set_qspi_close(void);
-void mailbox_set_qspi_open(void);
-void mailbox_set_qspi_direct(void);
+void mailbox_hps_qspi_enable(void);
 
 int mailbox_send_cmd(uint32_t job_id, uint32_t cmd, uint32_t *args,
 			unsigned int len, uint32_t urgent, uint32_t *response,
-			unsigned int resp_len);
+			unsigned int *resp_len);
 int mailbox_send_cmd_async(uint32_t *job_id, uint32_t cmd, uint32_t *args,
 			unsigned int len, unsigned int indirect);
 int mailbox_read_response(uint32_t *job_id, uint32_t *response,
-			unsigned int resp_len);
-unsigned int iterate_resp(uint32_t mbox_resp_len, uint32_t *resp_buf,
-			unsigned int resp_len);
+			unsigned int *resp_len);
+int iterate_resp(uint32_t mbox_resp_len, uint32_t *resp_buf,
+			unsigned int *resp_len);
 
 void mailbox_reset_cold(void);
 void mailbox_clear_response(void);
 
-int intel_mailbox_get_config_status(uint32_t cmd);
+int intel_mailbox_get_config_status(uint32_t cmd, bool init_done);
 int intel_mailbox_is_fpga_not_ready(void);
 
 int mailbox_rsu_get_spt_offset(uint32_t *resp_buf, uint32_t resp_buf_len);
diff --git a/plat/intel/soc/common/include/socfpga_reset_manager.h b/plat/intel/soc/common/include/socfpga_reset_manager.h
index 637f8df..a976df7 100644
--- a/plat/intel/soc/common/include/socfpga_reset_manager.h
+++ b/plat/intel/soc/common/include/socfpga_reset_manager.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
diff --git a/plat/intel/soc/common/include/socfpga_sip_svc.h b/plat/intel/soc/common/include/socfpga_sip_svc.h
index 92adfa3..0db71e2 100644
--- a/plat/intel/soc/common/include/socfpga_sip_svc.h
+++ b/plat/intel/soc/common/include/socfpga_sip_svc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020, Intel Corporation. All rights reserved.
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,6 +15,8 @@
 #define INTEL_SIP_SMC_STATUS_ERROR			0x4
 #define INTEL_SIP_SMC_RSU_ERROR				0x7
 
+/* SiP mailbox error code */
+#define GENERIC_RESPONSE_ERROR				0x3FF
 
 /* SMC SiP service function identifier */
 
@@ -35,6 +37,12 @@
 #define INTEL_SIP_SMC_RSU_UPDATE			0xC200000C
 #define INTEL_SIP_SMC_RSU_NOTIFY			0xC200000E
 #define INTEL_SIP_SMC_RSU_RETRY_COUNTER			0xC200000F
+#define INTEL_SIP_SMC_RSU_DCMF_VERSION			0xC2000010
+#define INTEL_SIP_SMC_RSU_COPY_DCMF_VERSION		0xC2000011
+
+
+/* ECC */
+#define INTEL_SIP_SMC_ECC_DBE				0xC200000D
 
 /* Send Mailbox Command */
 #define INTEL_SIP_SMC_MBOX_SEND_CMD			0xC200001E
@@ -42,9 +50,11 @@
 
 /* SiP Definitions */
 
-/* FPGA config helpers */
-#define INTEL_SIP_SMC_FPGA_CONFIG_ADDR			0x400000
-#define INTEL_SIP_SMC_FPGA_CONFIG_SIZE			0x2000000
+/* ECC DBE */
+#define WARM_RESET_WFI_FLAG				BIT(31)
+#define SYSMGR_ECC_DBE_COLD_RST_MASK		(SYSMGR_ECC_OCRAM_MASK |\
+							SYSMGR_ECC_DDR0_MASK |\
+							SYSMGR_ECC_DDR1_MASK)
 
 /* SMC function IDs for SiP Service queries */
 #define SIP_SVC_CALL_COUNT	0x8200ff00
@@ -70,4 +80,8 @@
 
 bool is_address_in_ddr_range(uint64_t addr, uint64_t size);
 
+/* ECC DBE */
+bool cold_reset_for_ecc_dbe(void);
+uint32_t intel_ecc_dbe_notification(uint64_t dbe_value);
+
 #endif /* SOCFPGA_SIP_SVC_H */
diff --git a/plat/intel/soc/common/include/socfpga_system_manager.h b/plat/intel/soc/common/include/socfpga_system_manager.h
index 8b42d47..2b13f1f 100644
--- a/plat/intel/soc/common/include/socfpga_system_manager.h
+++ b/plat/intel/soc/common/include/socfpga_system_manager.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020, Intel Corporation. All rights reserved.
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -30,6 +30,8 @@
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_0		0x200
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_1		0x204
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_2		0x208
+#define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_8		0x220
+#define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_9		0x224
 
 /* Field Masking */
 
@@ -47,6 +49,10 @@
 					| SCR_MPU_MASK)
 #define DISABLE_BRIDGE_FIREWALL				0x0ffe0101
 
+#define SYSMGR_ECC_OCRAM_MASK				BIT(1)
+#define SYSMGR_ECC_DDR0_MASK				BIT(16)
+#define SYSMGR_ECC_DDR1_MASK				BIT(17)
+
 /* Macros */
 
 #define SOCFPGA_SYSMGR(_reg)		(SOCFPGA_SYSMGR_REG_BASE \
diff --git a/plat/intel/soc/common/sip/socfpga_sip_ecc.c b/plat/intel/soc/common/sip/socfpga_sip_ecc.c
new file mode 100644
index 0000000..c4e06a6
--- /dev/null
+++ b/plat/intel/soc/common/sip/socfpga_sip_ecc.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved.
+ */
+
+#include <assert.h>
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/mmio.h>
+#include <tools_share/uuid.h>
+
+#include "socfpga_fcs.h"
+#include "socfpga_mailbox.h"
+#include "socfpga_reset_manager.h"
+#include "socfpga_sip_svc.h"
+#include "socfpga_system_manager.h"
+
+uint32_t intel_ecc_dbe_notification(uint64_t dbe_value)
+{
+	dbe_value &= WARM_RESET_WFI_FLAG;
+
+	/* Trap CPUs in WFI if warm reset flag is set */
+	if (dbe_value > 0) {
+		while (1) {
+			wfi();
+		}
+	}
+
+	return INTEL_SIP_SMC_STATUS_OK;
+}
+
+bool cold_reset_for_ecc_dbe(void)
+{
+	uint32_t dbe_int_status;
+
+	dbe_int_status = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_8));
+
+	/* Trigger cold reset only for error in critical memory (DDR/OCRAM) */
+	dbe_int_status &= SYSMGR_ECC_DBE_COLD_RST_MASK;
+
+	if (dbe_int_status > 0) {
+		return true;
+	}
+
+	return false;
+}
diff --git a/plat/intel/soc/common/sip/socfpga_sip_fcs.c b/plat/intel/soc/common/sip/socfpga_sip_fcs.c
new file mode 100644
index 0000000..fe5461b
--- /dev/null
+++ b/plat/intel/soc/common/sip/socfpga_sip_fcs.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2020-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <lib/mmio.h>
+
+#include "socfpga_fcs.h"
+#include "socfpga_mailbox.h"
+#include "socfpga_sip_svc.h"
+
+uint32_t intel_fcs_random_number_gen(uint64_t addr, uint64_t *ret_size,
+					uint32_t *mbox_error)
+{
+	int status;
+	unsigned int i;
+	unsigned int resp_len = FCS_RANDOM_WORD_SIZE;
+	uint32_t random_data[FCS_RANDOM_WORD_SIZE] = {0U};
+
+	if (!is_address_in_ddr_range(addr, FCS_RANDOM_BYTE_SIZE)) {
+		return INTEL_SIP_SMC_STATUS_REJECTED;
+	}
+
+	status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_RANDOM_GEN, NULL, 0U,
+			CMD_CASUAL, random_data, &resp_len);
+
+	if (status < 0) {
+		*mbox_error = -status;
+		return INTEL_SIP_SMC_STATUS_ERROR;
+	}
+
+	if (resp_len != FCS_RANDOM_WORD_SIZE) {
+		*mbox_error = GENERIC_RESPONSE_ERROR;
+		return INTEL_SIP_SMC_STATUS_ERROR;
+	}
+
+	*ret_size = FCS_RANDOM_BYTE_SIZE;
+
+	for (i = 0U; i < FCS_RANDOM_WORD_SIZE; i++) {
+		mmio_write_32(addr, random_data[i]);
+		addr += MBOX_WORD_BYTE;
+	}
+
+	flush_dcache_range(addr - *ret_size, *ret_size);
+
+	return INTEL_SIP_SMC_STATUS_OK;
+}
+
+uint32_t intel_fcs_send_cert(uint64_t addr, uint64_t size,
+					uint32_t *send_id)
+{
+	int status;
+
+	if (!is_address_in_ddr_range(addr, size)) {
+		return INTEL_SIP_SMC_STATUS_REJECTED;
+	}
+
+	status = mailbox_send_cmd_async(send_id, MBOX_CMD_VAB_SRC_CERT,
+				(uint32_t *)addr, size / MBOX_WORD_BYTE,
+				CMD_DIRECT);
+
+	if (status < 0) {
+		return INTEL_SIP_SMC_STATUS_ERROR;
+	}
+
+	return INTEL_SIP_SMC_STATUS_OK;
+}
+
+uint32_t intel_fcs_get_provision_data(uint32_t *send_id)
+{
+	int status;
+
+	status = mailbox_send_cmd_async(send_id, MBOX_FCS_GET_PROVISION,
+				NULL, 0U, CMD_DIRECT);
+
+	if (status < 0) {
+		return INTEL_SIP_SMC_STATUS_ERROR;
+	}
+
+	return INTEL_SIP_SMC_STATUS_OK;
+}
+
+uint32_t intel_fcs_cryption(uint32_t mode, uint32_t src_addr,
+		uint32_t src_size, uint32_t dst_addr,
+		uint32_t dst_size, uint32_t *send_id)
+{
+	int status;
+	uint32_t cmd;
+
+	if (!is_address_in_ddr_range(src_addr, src_size) ||
+		!is_address_in_ddr_range(dst_addr, dst_size)) {
+		return INTEL_SIP_SMC_STATUS_REJECTED;
+	}
+
+	fcs_crypt_payload payload = {
+		FCS_CRYPTION_DATA_0,
+		src_addr,
+		src_size,
+		dst_addr,
+		dst_size };
+
+	if (mode != 0U) {
+		cmd = MBOX_FCS_ENCRYPT_REQ;
+	} else {
+		cmd = MBOX_FCS_DECRYPT_REQ;
+	}
+
+	status = mailbox_send_cmd_async(send_id, cmd, (uint32_t *) &payload,
+				sizeof(fcs_crypt_payload) / MBOX_WORD_BYTE,
+				CMD_INDIRECT);
+	inv_dcache_range(dst_addr, dst_size);
+
+	if (status < 0) {
+		return INTEL_SIP_SMC_STATUS_REJECTED;
+	}
+
+	return INTEL_SIP_SMC_STATUS_OK;
+}
diff --git a/plat/intel/soc/common/soc/socfpga_mailbox.c b/plat/intel/soc/common/soc/socfpga_mailbox.c
index aec94af..be900c9 100644
--- a/plat/intel/soc/common/soc/socfpga_mailbox.c
+++ b/plat/intel/soc/common/soc/socfpga_mailbox.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, Intel Corporation. All rights reserved.
+ * Copyright (c) 2020-2022, Intel Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -59,9 +59,7 @@
 			}
 			mdelay(10U);
 		} else {
-			mmio_write_32(MBOX_OFFSET + MBOX_CMD_BUFFER +
-				      (*cin * 4), data);
-			(*cin)++;
+			mmio_write_32(MBOX_ENTRY_TO_ADDR(CMD, (*cin)++), data);
 			*cin %= MBOX_CMD_BUFFER_SIZE;
 			mmio_write_32(MBOX_OFFSET + MBOX_CIN, *cin);
 			break;
@@ -107,9 +105,7 @@
 		}
 	}
 
-	if (!is_doorbell_triggered) {
-		mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U);
-	}
+	mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U);
 
 	return MBOX_RET_OK;
 
@@ -131,7 +127,7 @@
 }
 
 int mailbox_read_response(unsigned int *job_id, uint32_t *response,
-				unsigned int resp_len)
+				unsigned int *resp_len)
 {
 	uint32_t rin;
 	uint32_t rout;
@@ -146,8 +142,7 @@
 	rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
 
 	if (rout != rin) {
-		resp_data = mmio_read_32(MBOX_OFFSET +
-				    MBOX_RESP_BUFFER + ((rout++)*4U));
+		resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++));
 
 		rout %= MBOX_RESP_BUFFER_SIZE;
 		mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
@@ -161,9 +156,9 @@
 
 		ret_resp_len = MBOX_RESP_LEN(resp_data);
 
-		if (ret_resp_len != 0U) {
-			ret_resp_len = iterate_resp(ret_resp_len, response,
-						    resp_len);
+		if (iterate_resp(ret_resp_len, response, resp_len)
+			!= MBOX_RET_OK) {
+			return MBOX_TIMEOUT;
 		}
 
 		if (MBOX_RESP_ERR(resp_data) > 0U) {
@@ -171,14 +166,14 @@
 			return -MBOX_RESP_ERR(resp_data);
 		}
 
-		return ret_resp_len;
+		return MBOX_RET_OK;
 	}
 	return MBOX_NO_RESPONSE;
 }
 
 
 int mailbox_poll_response(uint32_t job_id, uint32_t urgent, uint32_t *response,
-				unsigned int resp_len)
+				unsigned int *resp_len)
 {
 	unsigned int timeout = 40U;
 	unsigned int sdm_loop = 255U;
@@ -221,8 +216,8 @@
 		rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
 
 		while (rout != rin) {
-			resp_data = mmio_read_32(MBOX_OFFSET +
-					    MBOX_RESP_BUFFER + ((rout++)*4U));
+			resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP,
+								(rout)++));
 
 			rout %= MBOX_RESP_BUFFER_SIZE;
 			mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
@@ -234,10 +229,9 @@
 
 			ret_resp_len = MBOX_RESP_LEN(resp_data);
 
-			if (ret_resp_len != 0U) {
-				ret_resp_len = iterate_resp(ret_resp_len,
-							    response,
-							    resp_len);
+			if (iterate_resp(ret_resp_len, response, resp_len)
+				!= MBOX_RET_OK) {
+				return MBOX_TIMEOUT;
 			}
 
 			if (MBOX_RESP_ERR(resp_data) > 0U) {
@@ -245,7 +239,7 @@
 				return -MBOX_RESP_ERR(resp_data);
 			}
 
-			return ret_resp_len;
+			return MBOX_RET_OK;
 		}
 
 	sdm_loop--;
@@ -255,8 +249,8 @@
 	return MBOX_TIMEOUT;
 }
 
-unsigned int iterate_resp(uint32_t mbox_resp_len, uint32_t *resp_buf,
-			unsigned int resp_len)
+int iterate_resp(uint32_t mbox_resp_len, uint32_t *resp_buf,
+			unsigned int *resp_len)
 {
 	unsigned int timeout, total_resp_len = 0U;
 	uint32_t resp_data;
@@ -266,17 +260,15 @@
 	while (mbox_resp_len > 0U) {
 		timeout = 100U;
 		mbox_resp_len--;
-		resp_data = mmio_read_32(MBOX_OFFSET +
-					MBOX_RESP_BUFFER +
-					(rout)*4U);
+		resp_data = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++));
 
-		if ((resp_buf != NULL) && (resp_len != 0U)) {
+		if ((resp_buf != NULL) && (resp_len != NULL)
+			&& (*resp_len != 0U)) {
 			*(resp_buf + total_resp_len)
 					= resp_data;
-			resp_len--;
+			*resp_len = *resp_len - 1;
 			total_resp_len++;
 		}
-		rout++;
 		rout %= MBOX_RESP_BUFFER_SIZE;
 		mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
 
@@ -295,7 +287,11 @@
 			return MBOX_TIMEOUT;
 		}
 	}
-	return total_resp_len;
+
+	if (resp_len)
+		*resp_len = total_resp_len;
+
+	return MBOX_RET_OK;
 }
 
 int mailbox_send_cmd_async(uint32_t *job_id, uint32_t cmd, uint32_t *args,
@@ -320,7 +316,7 @@
 
 int mailbox_send_cmd(uint32_t job_id, uint32_t cmd, uint32_t *args,
 			unsigned int len, uint32_t urgent, uint32_t *response,
-			unsigned int resp_len)
+			unsigned int *resp_len)
 {
 	int status = 0;
 
@@ -366,20 +362,20 @@
 {
 	mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
 	mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_OPEN, NULL, 0U,
-				CMD_CASUAL, NULL, 0U);
+				CMD_CASUAL, NULL, NULL);
 }
 
 void mailbox_set_qspi_direct(void)
 {
 	mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_DIRECT, NULL, 0U,
-				CMD_CASUAL, NULL, 0U);
+				CMD_CASUAL, NULL, NULL);
 }
 
 void mailbox_set_qspi_close(void)
 {
 	mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
 	mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_CLOSE, NULL, 0U,
-				CMD_CASUAL, NULL, 0U);
+				CMD_CASUAL, NULL, NULL);
 }
 
 void mailbox_qspi_set_cs(uint32_t device_select)
@@ -390,21 +386,27 @@
 	cs_setting = (device_select << 28);
 	mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
 	mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_QSPI_SET_CS, &cs_setting,
-				1U, CMD_CASUAL, NULL, 0U);
+				1U, CMD_CASUAL, NULL, NULL);
 }
 
+void mailbox_hps_qspi_enable(void)
+{
+	mailbox_set_qspi_open();
+	mailbox_set_qspi_direct();
+}
+
 void mailbox_reset_cold(void)
 {
 	mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
 	mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_REBOOT_HPS, NULL, 0U,
-				CMD_CASUAL, NULL, 0U);
+				CMD_CASUAL, NULL, NULL);
 }
 
 int mailbox_rsu_get_spt_offset(uint32_t *resp_buf, unsigned int resp_buf_len)
 {
 	return mailbox_send_cmd(MBOX_JOB_ID, MBOX_GET_SUBPARTITION_TABLE,
 				NULL, 0U, CMD_CASUAL, resp_buf,
-				resp_buf_len);
+				&resp_buf_len);
 }
 
 struct rsu_status_info {
@@ -426,7 +428,7 @@
 
 	ret = mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_STATUS, NULL, 0U,
 				CMD_CASUAL, resp_buf,
-				resp_buf_len);
+				&resp_buf_len);
 
 	if (ret < 0) {
 		return ret;
@@ -445,14 +447,14 @@
 {
 	return mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_UPDATE,
 				flash_offset, 2U,
-				CMD_CASUAL, NULL, 0U);
+				CMD_CASUAL, NULL, NULL);
 }
 
 int mailbox_hps_stage_notify(uint32_t execution_stage)
 {
 	return mailbox_send_cmd(MBOX_JOB_ID, MBOX_HPS_STAGE_NOTIFY,
 				&execution_stage, 1U, CMD_CASUAL,
-				NULL, 0U);
+				NULL, NULL);
 }
 
 int mailbox_init(void)
@@ -465,7 +467,7 @@
 	mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U);
 
 	status = mailbox_send_cmd(0U, MBOX_CMD_RESTART, NULL, 0U,
-					CMD_URGENT, NULL, 0U);
+					CMD_URGENT, NULL, NULL);
 
 	if (status != 0) {
 		return status;
@@ -477,13 +479,14 @@
 	return MBOX_RET_OK;
 }
 
-int intel_mailbox_get_config_status(uint32_t cmd)
+int intel_mailbox_get_config_status(uint32_t cmd, bool init_done)
 {
 	int status;
 	uint32_t res, response[6];
+	unsigned int resp_len = ARRAY_SIZE(response);
 
 	status = mailbox_send_cmd(MBOX_JOB_ID, cmd, NULL, 0U, CMD_CASUAL,
-				response, ARRAY_SIZE(response));
+				response, &resp_len);
 
 	if (status < 0) {
 		return status;
@@ -504,20 +507,22 @@
 		return MBOX_CFGSTAT_STATE_ERROR_HARDWARE;
 	}
 
-	if ((res & SOFTFUNC_STATUS_CONF_DONE) != 0U &&
-		(res & SOFTFUNC_STATUS_INIT_DONE) != 0U) {
-		return MBOX_RET_OK;
-	}
+	if ((res & SOFTFUNC_STATUS_CONF_DONE) == 0U)
+		return MBOX_CFGSTAT_STATE_CONFIG;
 
-	return MBOX_CFGSTAT_STATE_CONFIG;
+	if (init_done && (res & SOFTFUNC_STATUS_INIT_DONE) == 0U)
+		return MBOX_CFGSTAT_STATE_CONFIG;
+
+	return MBOX_RET_OK;
 }
 
 int intel_mailbox_is_fpga_not_ready(void)
 {
-	int ret = intel_mailbox_get_config_status(MBOX_RECONFIG_STATUS);
+	int ret = intel_mailbox_get_config_status(MBOX_RECONFIG_STATUS, true);
 
 	if ((ret != MBOX_RET_OK) && (ret != MBOX_CFGSTAT_STATE_CONFIG)) {
-		ret = intel_mailbox_get_config_status(MBOX_CONFIG_STATUS);
+		ret = intel_mailbox_get_config_status(MBOX_CONFIG_STATUS,
+							false);
 	}
 
 	return ret;
diff --git a/plat/intel/soc/common/soc/socfpga_reset_manager.c b/plat/intel/soc/common/soc/socfpga_reset_manager.c
index 32604c9..b0de60e 100644
--- a/plat/intel/soc/common/soc/socfpga_reset_manager.c
+++ b/plat/intel/soc/common/soc/socfpga_reset_manager.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -134,7 +134,7 @@
 #if PLATFORM_MODEL == PLAT_SOCFPGA_STRATIX10
 	mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST),
 		~(RSTMGR_FIELD(BRG, DDRSCH) | RSTMGR_FIELD(BRG, FPGA2SOC)));
-#elif PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX
+#else
 	mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST),
 		~(RSTMGR_FIELD(BRG, MPFE) | RSTMGR_FIELD(BRG, FPGA2SOC)));
 #endif
diff --git a/plat/intel/soc/common/socfpga_psci.c b/plat/intel/soc/common/socfpga_psci.c
index 4b57b8f..5fd6559 100644
--- a/plat/intel/soc/common/socfpga_psci.c
+++ b/plat/intel/soc/common/socfpga_psci.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,9 +14,9 @@
 #include "socfpga_mailbox.h"
 #include "socfpga_plat_def.h"
 #include "socfpga_reset_manager.h"
+#include "socfpga_sip_svc.h"
 
 
-
 /*******************************************************************************
  * plat handler called when a CPU is about to enter standby.
  ******************************************************************************/
@@ -151,6 +151,9 @@
 static int socfpga_system_reset2(int is_vendor, int reset_type,
 					u_register_t cookie)
 {
+	if (cold_reset_for_ecc_dbe()) {
+		mailbox_reset_cold();
+	}
 	/* disable cpuif */
 	gicv2_cpuif_disable();
 
diff --git a/plat/intel/soc/common/socfpga_sip_svc.c b/plat/intel/soc/common/socfpga_sip_svc.c
index 86a4455..14cd9e0 100644
--- a/plat/intel/soc/common/socfpga_sip_svc.c
+++ b/plat/intel/soc/common/socfpga_sip_svc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,6 +10,7 @@
 #include <lib/mmio.h>
 #include <tools_share/uuid.h>
 
+#include "socfpga_fcs.h"
 #include "socfpga_mailbox.h"
 #include "socfpga_reset_manager.h"
 #include "socfpga_sip_svc.h"
@@ -83,9 +84,9 @@
 	uint32_t ret;
 
 	if (query_type == 1)
-		ret = intel_mailbox_get_config_status(MBOX_CONFIG_STATUS);
+		ret = intel_mailbox_get_config_status(MBOX_CONFIG_STATUS, false);
 	else
-		ret = intel_mailbox_get_config_status(MBOX_RECONFIG_STATUS);
+		ret = intel_mailbox_get_config_status(MBOX_RECONFIG_STATUS, true);
 
 	if (ret) {
 		if (ret == MBOX_CFGSTAT_STATE_CONFIG)
@@ -128,32 +129,34 @@
 static int intel_fpga_config_completed_write(uint32_t *completed_addr,
 					uint32_t *count, uint32_t *job_id)
 {
-	uint32_t status = INTEL_SIP_SMC_STATUS_OK;
-	*count = 0;
-	int resp_len = 0;
 	uint32_t resp[5];
+	unsigned int resp_len = ARRAY_SIZE(resp);
+	int status = INTEL_SIP_SMC_STATUS_OK;
 	int all_completed = 1;
+	*count = 0;
 
 	while (*count < 3) {
 
-		resp_len = mailbox_read_response(job_id,
-				resp, ARRAY_SIZE(resp));
+		status = mailbox_read_response(job_id,
+				resp, &resp_len);
 
-		if (resp_len < 0)
+		if (status < 0) {
 			break;
+		}
 
 		max_blocks++;
 
 		if (mark_last_buffer_xfer_completed(
-			&completed_addr[*count]) == 0)
+			&completed_addr[*count]) == 0) {
 			*count = *count + 1;
-		else
+		} else {
 			break;
+		}
 	}
 
 	if (*count <= 0) {
-		if (resp_len != MBOX_NO_RESPONSE &&
-			resp_len != MBOX_TIMEOUT && resp_len != 0) {
+		if (status != MBOX_NO_RESPONSE &&
+			status != MBOX_TIMEOUT && resp_len != 0) {
 			mailbox_clear_response();
 			return INTEL_SIP_SMC_STATUS_ERROR;
 		}
@@ -183,17 +186,21 @@
 
 static int intel_fpga_config_start(uint32_t config_type)
 {
+	uint32_t argument = 0x1;
 	uint32_t response[3];
 	int status = 0;
+	unsigned int size = 0;
+	unsigned int resp_len = ARRAY_SIZE(response);
 
 	is_partial_reconfig = config_type;
 
 	mailbox_clear_response();
 
-	mailbox_send_cmd(1U, MBOX_CMD_CANCEL, NULL, 0U, CMD_CASUAL, NULL, 0U);
+	mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_CANCEL, NULL, 0U,
+			CMD_CASUAL, NULL, NULL);
 
-	status = mailbox_send_cmd(1U, MBOX_RECONFIG, NULL, 0U, CMD_CASUAL,
-			response, ARRAY_SIZE(response));
+	status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_RECONFIG, &argument, size,
+			CMD_CASUAL, response, &resp_len);
 
 	if (status < 0)
 		return status;
@@ -234,6 +241,9 @@
 
 bool is_address_in_ddr_range(uint64_t addr, uint64_t size)
 {
+	if (!addr && !size) {
+		return true;
+	}
 	if (size > (UINT64_MAX - addr))
 		return false;
 	if (addr < BL31_LIMIT)
@@ -341,7 +351,7 @@
 {
 	if (!intel_secure_reg_read(reg_addr, retval)) {
 		*retval &= ~mask;
-		*retval |= val;
+		*retval |= val & mask;
 		return intel_secure_reg_write(reg_addr, *retval, retval);
 	}
 
@@ -384,10 +394,11 @@
 }
 
 /* Mailbox services */
-static uint32_t intel_mbox_send_cmd(uint32_t cmd, uint32_t *args, uint32_t len,
-				    uint32_t urgent, uint32_t *response,
-				    uint32_t resp_len, int *mbox_status,
-				    int *len_in_resp)
+static uint32_t intel_mbox_send_cmd(uint32_t cmd, uint32_t *args,
+				unsigned int len,
+				uint32_t urgent, uint32_t *response,
+				unsigned int resp_len, int *mbox_status,
+				unsigned int *len_in_resp)
 {
 	*len_in_resp = 0;
 	*mbox_status = 0;
@@ -396,7 +407,7 @@
 		return INTEL_SIP_SMC_STATUS_REJECTED;
 
 	int status = mailbox_send_cmd(MBOX_JOB_ID, cmd, args, len, urgent,
-				      response, resp_len);
+				      response, &resp_len);
 
 	if (status < 0) {
 		*mbox_status = -status;
@@ -404,7 +415,7 @@
 	}
 
 	*mbox_status = 0;
-	*len_in_resp = status;
+	*len_in_resp = resp_len;
 	return INTEL_SIP_SMC_STATUS_OK;
 }
 
@@ -422,12 +433,12 @@
 			 u_register_t flags)
 {
 	uint32_t retval = 0;
-	uint32_t status = INTEL_SIP_SMC_STATUS_OK;
 	uint32_t completed_addr[3];
 	uint64_t rsu_respbuf[9];
+	int status = INTEL_SIP_SMC_STATUS_OK;
+	int mbox_status;
+	unsigned int len_in_resp;
 	u_register_t x5, x6;
-	int mbox_status, len_in_resp;
-
 
 	switch (smc_fid) {
 	case SIP_SVC_UID:
@@ -519,13 +530,17 @@
 			SMC_RET2(handle, status, retval);
 		}
 
+	case INTEL_SIP_SMC_ECC_DBE:
+		status = intel_ecc_dbe_notification(x1);
+		SMC_RET1(handle, status);
+
 	case INTEL_SIP_SMC_MBOX_SEND_CMD:
 		x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
 		x6 = SMC_GET_GP(handle, CTX_GPREG_X6);
 		status = intel_mbox_send_cmd(x1, (uint32_t *)x2, x3, x4,
 					     (uint32_t *)x5, x6, &mbox_status,
 					     &len_in_resp);
-		SMC_RET4(handle, status, mbox_status, x5, len_in_resp);
+		SMC_RET3(handle, status, mbox_status, len_in_resp);
 
 	default:
 		return socfpga_sip_handler(smc_fid, x1, x2, x3, x4,
diff --git a/plat/intel/soc/n5x/bl31_plat_setup.c b/plat/intel/soc/n5x/bl31_plat_setup.c
new file mode 100644
index 0000000..2a8daa6
--- /dev/null
+++ b/plat/intel/soc/n5x/bl31_plat_setup.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2020-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <arch.h>
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables.h>
+
+#include "ccu/ncore_ccu.h"
+#include "socfpga_mailbox.h"
+#include "socfpga_private.h"
+
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
+entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+{
+	entry_point_info_t *next_image_info;
+
+	next_image_info = (type == NON_SECURE) ?
+			  &bl33_image_ep_info : &bl32_image_ep_info;
+
+	/* None of the images on this platform can have 0x0 as the entrypoint */
+	if (next_image_info->pc) {
+		return next_image_info;
+	} else {
+		return NULL;
+	}
+}
+
+void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
+				u_register_t arg2, u_register_t arg3)
+{
+	static console_t console;
+
+	mmio_write_64(PLAT_SEC_ENTRY, 0);
+
+	console_16550_register(PLAT_UART0_BASE, PLAT_UART_CLOCK, PLAT_BAUDRATE,
+		&console);
+	/*
+	 * Check params passed from BL31 should not be NULL,
+	 */
+	void *from_bl2 = (void *) arg0;
+
+	bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
+
+	assert(params_from_bl2 != NULL);
+
+	/*
+	 * Copy BL32 (if populated by BL31) and BL33 entry point information.
+	 * They are stored in Secure RAM, in BL31's address space.
+	 */
+
+	if (params_from_bl2->h.type == PARAM_BL_PARAMS &&
+		params_from_bl2->h.version >= VERSION_2) {
+
+		bl_params_node_t *bl_params = params_from_bl2->head;
+
+		while (bl_params != NULL) {
+			if (bl_params->image_id == BL33_IMAGE_ID)
+				bl33_image_ep_info = *bl_params->ep_info;
+
+			bl_params = bl_params->next_params_info;
+		}
+	} else {
+		struct socfpga_bl31_params *arg_from_bl2 =
+			(struct socfpga_bl31_params *) from_bl2;
+
+		assert(arg_from_bl2->h.type == PARAM_BL31);
+		assert(arg_from_bl2->h.version >= VERSION_1);
+
+		bl32_image_ep_info = *arg_from_bl2->bl32_ep_info;
+		bl33_image_ep_info = *arg_from_bl2->bl33_ep_info;
+	}
+	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+}
+
+static const interrupt_prop_t s10_interrupt_props[] = {
+	PLAT_INTEL_SOCFPGA_G1S_IRQ_PROPS(GICV2_INTR_GROUP0),
+	PLAT_INTEL_SOCFPGA_G0_IRQ_PROPS(GICV2_INTR_GROUP0)
+};
+
+static unsigned int target_mask_array[PLATFORM_CORE_COUNT];
+
+static const gicv2_driver_data_t plat_gicv2_gic_data = {
+	.gicd_base = PLAT_INTEL_SOCFPGA_GICD_BASE,
+	.gicc_base = PLAT_INTEL_SOCFPGA_GICC_BASE,
+	.interrupt_props = s10_interrupt_props,
+	.interrupt_props_num = ARRAY_SIZE(s10_interrupt_props),
+	.target_masks = target_mask_array,
+	.target_masks_num = ARRAY_SIZE(target_mask_array),
+};
+
+/*******************************************************************************
+ * Perform any BL3-1 platform setup code
+ ******************************************************************************/
+void bl31_platform_setup(void)
+{
+	socfpga_delay_timer_init();
+
+	/* Initialize the gic cpu and distributor interfaces */
+	gicv2_driver_init(&plat_gicv2_gic_data);
+	gicv2_distif_init();
+	gicv2_pcpu_distif_init();
+	gicv2_cpuif_enable();
+
+	/* Signal secondary CPUs to jump to BL31 (BL2 = U-boot SPL) */
+	mmio_write_64(PLAT_CPU_RELEASE_ADDR,
+		(uint64_t)plat_secondary_cpus_bl31_entry);
+
+	mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL);
+
+	ncore_enable_ocram_firewall();
+}
+
+const mmap_region_t plat_dm_mmap[] = {
+	MAP_REGION_FLAT(DRAM_BASE, DRAM_SIZE,
+		MT_MEMORY | MT_RW | MT_NS),
+	MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE,
+		MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(DEVICE2_BASE, DEVICE2_SIZE,
+		MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(OCRAM_BASE, OCRAM_SIZE,
+		MT_NON_CACHEABLE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(DEVICE3_BASE, DEVICE3_SIZE,
+		MT_DEVICE | MT_RW | MT_SECURE),
+	MAP_REGION_FLAT(MEM64_BASE, MEM64_SIZE,
+		MT_DEVICE | MT_RW | MT_NS),
+	MAP_REGION_FLAT(DEVICE4_BASE, DEVICE4_SIZE,
+		MT_DEVICE | MT_RW | MT_NS),
+	{0}
+};
+
+/*******************************************************************************
+ * Perform the very early platform specific architectural setup here. At the
+ * moment this is only intializes the mmu in a quick and dirty way.
+ ******************************************************************************/
+void bl31_plat_arch_setup(void)
+{
+	const mmap_region_t bl_regions[] = {
+		MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_BASE,
+			MT_MEMORY | MT_RW | MT_SECURE),
+		MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE,
+			MT_CODE | MT_SECURE),
+		MAP_REGION_FLAT(BL_RO_DATA_BASE,
+			BL_RO_DATA_END - BL_RO_DATA_BASE,
+			MT_RO_DATA | MT_SECURE),
+#if USE_COHERENT_MEM
+		MAP_REGION_FLAT(BL_COHERENT_RAM_BASE,
+			BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
+			MT_DEVICE | MT_RW | MT_SECURE),
+#endif
+		{0}
+	};
+
+	setup_page_tables(bl_regions, plat_dm_mmap);
+	enable_mmu_el3(0);
+}
diff --git a/plat/intel/soc/n5x/include/socfpga_plat_def.h b/plat/intel/soc/n5x/include/socfpga_plat_def.h
new file mode 100644
index 0000000..9186852
--- /dev/null
+++ b/plat/intel/soc/n5x/include/socfpga_plat_def.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2022, Intel Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_SOCFPGA_DEF_H
+#define PLAT_SOCFPGA_DEF_H
+
+#include <platform_def.h>
+
+/* Platform Setting */
+#define PLATFORM_MODEL				PLAT_SOCFPGA_N5X
+#define BOOT_SOURCE				BOOT_SOURCE_SDMMC
+
+/* FPGA config helpers */
+#define INTEL_SIP_SMC_FPGA_CONFIG_ADDR		0x400000
+#define INTEL_SIP_SMC_FPGA_CONFIG_SIZE		0x2000000
+
+/* Register Mapping */
+#define SOCFPGA_MMC_REG_BASE			U(0xff808000)
+
+#define SOCFPGA_RSTMGR_REG_BASE			U(0xffd11000)
+#define SOCFPGA_SYSMGR_REG_BASE			U(0xffd12000)
+
+#define SOCFPGA_L4_PER_SCR_REG_BASE			U(0xffd21000)
+#define SOCFPGA_L4_SYS_SCR_REG_BASE			U(0xffd21100)
+#define SOCFPGA_SOC2FPGA_SCR_REG_BASE			U(0xffd21200)
+#define SOCFPGA_LWSOC2FPGA_SCR_REG_BASE			U(0xffd21300)
+
+#endif /* PLAT_SOCFPGA_DEF_H */
diff --git a/plat/intel/soc/n5x/platform.mk b/plat/intel/soc/n5x/platform.mk
new file mode 100644
index 0000000..b72bcc4
--- /dev/null
+++ b/plat/intel/soc/n5x/platform.mk
@@ -0,0 +1,52 @@
+#
+# Copyright (c) 2020-2022, Intel Corporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES		:=	\
+			-Iplat/intel/soc/n5x/include/			\
+			-Iplat/intel/soc/common/drivers/		\
+			-Iplat/intel/soc/common/include/
+
+# Include GICv2 driver files
+include drivers/arm/gic/v2/gicv2.mk
+DM_GICv2_SOURCES	:=	\
+			${GICV2_SOURCES}                                \
+			plat/common/plat_gicv2.c
+
+
+PLAT_BL_COMMON_SOURCES	:=	\
+			${DM_GICv2_SOURCES}				\
+			drivers/delay_timer/delay_timer.c		\
+			drivers/delay_timer/generic_delay_timer.c  	\
+			drivers/ti/uart/aarch64/16550_console.S		\
+			lib/xlat_tables/aarch64/xlat_tables.c 		\
+			lib/xlat_tables/xlat_tables_common.c 		\
+			plat/intel/soc/common/aarch64/platform_common.c \
+			plat/intel/soc/common/aarch64/plat_helpers.S	\
+			plat/intel/soc/common/socfpga_delay_timer.c     \
+			plat/intel/soc/common/drivers/ccu/ncore_ccu.c
+
+BL2_SOURCES     +=
+
+BL31_SOURCES	+=	\
+		drivers/arm/cci/cci.c					\
+		lib/cpus/aarch64/aem_generic.S				\
+		lib/cpus/aarch64/cortex_a53.S				\
+		plat/common/plat_psci_common.c				\
+		plat/intel/soc/n5x/bl31_plat_setup.c			\
+		plat/intel/soc/common/socfpga_psci.c			\
+		plat/intel/soc/common/socfpga_sip_svc.c			\
+		plat/intel/soc/common/socfpga_topology.c		\
+		plat/intel/soc/common/sip/socfpga_sip_ecc.c             \
+		plat/intel/soc/common/sip/socfpga_sip_fcs.c		\
+		plat/intel/soc/common/soc/socfpga_mailbox.c		\
+		plat/intel/soc/common/soc/socfpga_reset_manager.c
+
+PROGRAMMABLE_RESET_ADDRESS	:= 0
+BL2_AT_EL3			:= 1
+BL2_INV_DCACHE			:= 0
+MULTI_CONSOLE_API		:= 1
+SIMICS_BUILD			:= 0
+USE_COHERENT_MEM		:= 1
diff --git a/plat/intel/soc/stratix10/bl2_plat_setup.c b/plat/intel/soc/stratix10/bl2_plat_setup.c
index ecf1f01..a8026ea 100644
--- a/plat/intel/soc/stratix10/bl2_plat_setup.c
+++ b/plat/intel/soc/stratix10/bl2_plat_setup.c
@@ -7,6 +7,7 @@
 
 #include <arch.h>
 #include <arch_helpers.h>
+#include <assert.h>
 #include <common/bl_common.h>
 #include <common/debug.h>
 #include <common/desc_image_load.h>
@@ -109,6 +110,9 @@
 	mmc_info.mmc_dev_type = MMC_IS_SD;
 	mmc_info.ocr_voltage = OCR_3_3_3_4 | OCR_3_2_3_3;
 
+	/* Request ownership and direct access to QSPI */
+	mailbox_hps_qspi_enable();
+
 	switch (boot_source) {
 	case BOOT_SOURCE_SDMMC:
 		dw_mmc_init(&params, &mmc_info);
@@ -116,8 +120,6 @@
 		break;
 
 	case BOOT_SOURCE_QSPI:
-		mailbox_set_qspi_open();
-		mailbox_set_qspi_direct();
 		cad_qspi_init(0, QSPI_CONFIG_CPHA, QSPI_CONFIG_CPOL,
 			QSPI_CONFIG_CSDA, QSPI_CONFIG_CSDADS,
 			QSPI_CONFIG_CSEOT, QSPI_CONFIG_CSSOT, 0);
@@ -157,6 +159,8 @@
 {
 	bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
 
+	assert(bl_mem_params);
+
 	switch (image_id) {
 	case BL33_IMAGE_ID:
 		bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
diff --git a/plat/intel/soc/stratix10/include/socfpga_plat_def.h b/plat/intel/soc/stratix10/include/socfpga_plat_def.h
index a2bd57b..b84a567 100644
--- a/plat/intel/soc/stratix10/include/socfpga_plat_def.h
+++ b/plat/intel/soc/stratix10/include/socfpga_plat_def.h
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,6 +14,10 @@
 #define PLATFORM_MODEL				PLAT_SOCFPGA_STRATIX10
 #define BOOT_SOURCE				BOOT_SOURCE_SDMMC
 
+/* FPGA config helpers */
+#define INTEL_SIP_SMC_FPGA_CONFIG_ADDR		0x400000
+#define INTEL_SIP_SMC_FPGA_CONFIG_SIZE		0x1000000
+
 /* Register Mapping */
 #define SOCFPGA_MMC_REG_BASE                    0xff808000
 
diff --git a/plat/intel/soc/stratix10/platform.mk b/plat/intel/soc/stratix10/platform.mk
index 8bbd010..d9d88d4 100644
--- a/plat/intel/soc/stratix10/platform.mk
+++ b/plat/intel/soc/stratix10/platform.mk
@@ -1,6 +1,6 @@
 #
-# Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
-# Copyright (c) 2019-2020, Intel Corporation. All rights reserved.
+# Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -63,9 +63,12 @@
 		plat/intel/soc/common/socfpga_psci.c			\
 		plat/intel/soc/common/socfpga_sip_svc.c			\
 		plat/intel/soc/common/socfpga_topology.c		\
+		plat/intel/soc/common/sip/socfpga_sip_ecc.c		\
+		plat/intel/soc/common/sip/socfpga_sip_fcs.c		\
 		plat/intel/soc/common/soc/socfpga_mailbox.c		\
 		plat/intel/soc/common/soc/socfpga_reset_manager.c
 
 PROGRAMMABLE_RESET_ADDRESS	:= 0
 BL2_AT_EL3			:= 1
+SIMICS_BUILD			:= 0
 USE_COHERENT_MEM		:= 1
diff --git a/plat/marvell/armada/a3k/common/cm3_system_reset.c b/plat/marvell/armada/a3k/common/cm3_system_reset.c
index 548ff51..f105d59 100644
--- a/plat/marvell/armada/a3k/common/cm3_system_reset.c
+++ b/plat/marvell/armada/a3k/common/cm3_system_reset.c
@@ -58,5 +58,5 @@
 	}
 
 	/* If we reach here, the command is not implemented. */
-	ERROR("System reset command not implemented in WTMI firmware!\n");
+	WARN("System reset command not implemented in WTMI firmware!\n");
 }
diff --git a/plat/marvell/armada/a3k/common/dram_win.c b/plat/marvell/armada/a3k/common/dram_win.c
index e89f295..9d7b3a9 100644
--- a/plat/marvell/armada/a3k/common/dram_win.c
+++ b/plat/marvell/armada/a3k/common/dram_win.c
@@ -106,7 +106,9 @@
 	 *    to configure it again here;
 	 *
 	 *	0xFFFFFFFF ---> +-----------------------+
-	 *			|	 Boot ROM	| 64 KB
+	 *			|	 Boot ROM	| 1 MB
+	 *			| AP Boot ROM - 16 KB:  |
+	 *			| 0xFFFF0000-0xFFFF4000 |
 	 *	0xFFF00000 ---> +-----------------------+
 	 *			:			:
 	 *	0xFE010000 ---> +-----------------------+
diff --git a/plat/mediatek/mt8186/drivers/dfd/plat_dfd.c b/plat/mediatek/mt8186/drivers/dfd/plat_dfd.c
new file mode 100644
index 0000000..ade0837
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/dfd/plat_dfd.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <mtk_sip_svc.h>
+#include <plat_dfd.h>
+
+static bool dfd_enabled;
+static uint64_t dfd_base_addr;
+static uint64_t dfd_chain_length;
+static uint64_t dfd_cache_dump;
+
+static void dfd_setup(uint64_t base_addr, uint64_t chain_length,
+		      uint64_t cache_dump)
+{
+	mmio_write_32(MCUSYS_DFD_MAP, base_addr >> 24);
+	mmio_write_32(WDT_DEBUG_CTL, WDT_DEBUG_CTL_VAL_0);
+
+	sync_writel(DFD_INTERNAL_CTL, (BIT(0) | BIT(2)));
+
+	mmio_setbits_32(DFD_INTERNAL_CTL, BIT(13));
+	mmio_setbits_32(DFD_INTERNAL_CTL, BIT(3));
+	mmio_setbits_32(DFD_INTERNAL_CTL, (BIT(19) | BIT(20)));
+	mmio_write_32(DFD_INTERNAL_PWR_ON, (BIT(0) | BIT(1) | BIT(3)));
+	mmio_write_32(DFD_CHAIN_LENGTH0, chain_length);
+	mmio_write_32(DFD_INTERNAL_SHIFT_CLK_RATIO, 0);
+	mmio_write_32(DFD_INTERNAL_TEST_SO_0, DFD_INTERNAL_TEST_SO_0_VAL);
+	mmio_write_32(DFD_INTERNAL_NUM_OF_TEST_SO_GROUP, 1);
+
+	mmio_write_32(DFD_TEST_SI_0, DFD_TEST_SI_0_VAL);
+	mmio_write_32(DFD_TEST_SI_1, DFD_TEST_SI_1_VAL);
+
+	sync_writel(DFD_V30_CTL, 1);
+
+	mmio_write_32(DFD_V30_BASE_ADDR, (base_addr & 0xFFF00000));
+
+	/* setup global variables for suspend and resume */
+	dfd_enabled = true;
+	dfd_base_addr = base_addr;
+	dfd_chain_length = chain_length;
+	dfd_cache_dump = cache_dump;
+
+	if ((cache_dump & DFD_CACHE_DUMP_ENABLE) != 0UL) {
+		mmio_write_32(WDT_DEBUG_CTL, WDT_DEBUG_CTL_VAL_1);
+		sync_writel(DFD_V35_ENALBE, 1);
+		sync_writel(DFD_V35_TAP_NUMBER, DFD_V35_TAP_NUMBER_VAL);
+		sync_writel(DFD_V35_TAP_EN, DFD_V35_TAP_EN_VAL);
+		sync_writel(DFD_V35_SEQ0_0, DFD_V35_SEQ0_0_VAL);
+
+		if (cache_dump & DFD_PARITY_ERR_TRIGGER) {
+			sync_writel(DFD_HW_TRIGGER_MASK, DFD_HW_TRIGGER_MASK_VAL);
+			mmio_setbits_32(DFD_INTERNAL_CTL, BIT(4));
+		}
+	}
+	dsbsy();
+}
+
+void dfd_resume(void)
+{
+	if (dfd_enabled == true) {
+		dfd_setup(dfd_base_addr, dfd_chain_length, dfd_cache_dump);
+	}
+}
+
+uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1,
+			    uint64_t arg2, uint64_t arg3)
+{
+	uint64_t ret = 0L;
+
+	switch (arg0) {
+	case PLAT_MTK_DFD_SETUP_MAGIC:
+		INFO("[%s] DFD setup call from kernel\n", __func__);
+		dfd_setup(arg1, arg2, arg3);
+		break;
+	case PLAT_MTK_DFD_READ_MAGIC:
+		/* only allow to access DFD register base + 0x200 */
+		if (arg1 <= 0x200) {
+			ret = mmio_read_32(MISC1_CFG_BASE + arg1);
+		}
+		break;
+	case PLAT_MTK_DFD_WRITE_MAGIC:
+		/* only allow to access DFD register base + 0x200 */
+		if (arg1 <= 0x200) {
+			sync_writel(MISC1_CFG_BASE + arg1, arg2);
+		}
+		break;
+	default:
+		ret = MTK_SIP_E_INVALID_PARAM;
+		break;
+	}
+
+	return ret;
+}
diff --git a/plat/mediatek/mt8186/drivers/dfd/plat_dfd.h b/plat/mediatek/mt8186/drivers/dfd/plat_dfd.h
new file mode 100644
index 0000000..1901ec9
--- /dev/null
+++ b/plat/mediatek/mt8186/drivers/dfd/plat_dfd.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_DFD_H
+#define PLAT_DFD_H
+
+#include <arch_helpers.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#define sync_writel(addr, val)	do { mmio_write_32((addr), (val)); \
+				dsbsy(); \
+				} while (0)
+
+#define PLAT_MTK_DFD_SETUP_MAGIC		(0x99716150)
+#define PLAT_MTK_DFD_READ_MAGIC			(0x99716151)
+#define PLAT_MTK_DFD_WRITE_MAGIC		(0x99716152)
+
+#define MCU_BIU_BASE				(MCUCFG_BASE)
+#define MISC1_CFG_BASE				(MCU_BIU_BASE + 0xA040)
+
+#define DFD_INTERNAL_CTL			(MISC1_CFG_BASE + 0x00)
+#define DFD_INTERNAL_PWR_ON			(MISC1_CFG_BASE + 0x08)
+#define DFD_CHAIN_LENGTH0			(MISC1_CFG_BASE + 0x0C)
+#define DFD_INTERNAL_SHIFT_CLK_RATIO		(MISC1_CFG_BASE + 0x10)
+#define DFD_INTERNAL_TEST_SO_0			(MISC1_CFG_BASE + 0x28)
+#define DFD_INTERNAL_NUM_OF_TEST_SO_GROUP	(MISC1_CFG_BASE + 0x30)
+#define DFD_V30_CTL				(MISC1_CFG_BASE + 0x48)
+#define DFD_V30_BASE_ADDR			(MISC1_CFG_BASE + 0x4C)
+#define DFD_TEST_SI_0				(MISC1_CFG_BASE + 0x58)
+#define DFD_TEST_SI_1				(MISC1_CFG_BASE + 0x5C)
+#define DFD_HW_TRIGGER_MASK			(MISC1_CFG_BASE + 0xBC)
+
+#define DFD_V35_ENALBE				(MCU_BIU_BASE + 0xA0A8)
+#define DFD_V35_TAP_NUMBER			(MCU_BIU_BASE + 0xA0AC)
+#define DFD_V35_TAP_EN				(MCU_BIU_BASE + 0xA0B0)
+#define DFD_V35_SEQ0_0				(MCU_BIU_BASE + 0xA0C0)
+#define DFD_V35_SEQ0_1				(MCU_BIU_BASE + 0xA0C4)
+
+#define DFD_CACHE_DUMP_ENABLE			(1U)
+#define DFD_PARITY_ERR_TRIGGER			(2U)
+
+#define MCUSYS_DFD_MAP				(0x10001390)
+#define WDT_DEBUG_CTL				(0x10007048)
+
+#define WDT_DEBUG_CTL_VAL_0			(0x950603A0)
+#define DFD_INTERNAL_TEST_SO_0_VAL		(0x3B)
+#define DFD_TEST_SI_0_VAL			(0x108)
+#define DFD_TEST_SI_1_VAL			(0x20200000)
+
+#define WDT_DEBUG_CTL_VAL_1			(0x95063E80)
+#define DFD_V35_TAP_NUMBER_VAL			(0xA)
+#define DFD_V35_TAP_EN_VAL			(0x3FF)
+#define DFD_V35_SEQ0_0_VAL			(0x63668820)
+#define DFD_HW_TRIGGER_MASK_VAL			(0xC)
+
+void dfd_resume(void);
+uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1,
+			    uint64_t arg2, uint64_t arg3);
+
+#endif /* PLAT_DFD_H */
diff --git a/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.c b/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.c
index ef1fff8..df533a6 100644
--- a/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.c
+++ b/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.c
@@ -76,11 +76,11 @@
 	.reg_ccif_event_apsrc_req_mask_b = 0,
 
 	/* SPM_SRC_REQ */
-	.reg_spm_apsrc_req = 1,
-	.reg_spm_f26m_req = 1,
-	.reg_spm_infra_req = 1,
-	.reg_spm_vrf18_req = 1,
-	.reg_spm_ddren_req = 1,
+	.reg_spm_apsrc_req = 0,
+	.reg_spm_f26m_req = 0,
+	.reg_spm_infra_req = 0,
+	.reg_spm_vrf18_req = 0,
+	.reg_spm_ddren_req = 0,
 	.reg_spm_dvfs_req = 0,
 	.reg_spm_sw_mailbox_req = 0,
 	.reg_spm_sspm_mailbox_req = 0,
diff --git a/plat/mediatek/mt8186/include/plat_sip_calls.h b/plat/mediatek/mt8186/include/plat_sip_calls.h
index 598a5b8..9e3726b 100644
--- a/plat/mediatek/mt8186/include/plat_sip_calls.h
+++ b/plat/mediatek/mt8186/include/plat_sip_calls.h
@@ -10,6 +10,10 @@
 /*******************************************************************************
  * Plat SiP function constants
  ******************************************************************************/
-#define MTK_PLAT_SIP_NUM_CALLS    0
+#define MTK_PLAT_SIP_NUM_CALLS		(2)
+
+/* DFD */
+#define MTK_SIP_KERNEL_DFD_AARCH32	(0x82000205)
+#define MTK_SIP_KERNEL_DFD_AARCH64	(0xC2000205)
 
 #endif /* PLAT_SIP_CALLS_H */
diff --git a/plat/mediatek/mt8186/plat_pm.c b/plat/mediatek/mt8186/plat_pm.c
index 6bc6b9d..e125c99 100644
--- a/plat/mediatek/mt8186/plat_pm.c
+++ b/plat/mediatek/mt8186/plat_pm.c
@@ -13,6 +13,7 @@
 #include <mt_gic_v3.h>
 #include <mtspmc.h>
 #include <plat/common/platform.h>
+#include <plat_dfd.h>
 #include <plat_mtk_lpm.h>
 #include <plat_params.h>
 #include <plat_pm.h>
@@ -164,6 +165,8 @@
 	mt_gic_distif_restore();
 	gic_sgi_restore_all();
 
+	dfd_resume();
+
 	(void)plat_mt_pm_invoke(plat_mt_pm->pwr_mcusys_on_finished, cpu, state);
 }
 
diff --git a/plat/mediatek/mt8186/plat_sip_calls.c b/plat/mediatek/mt8186/plat_sip_calls.c
index 87ba786..cb66218 100644
--- a/plat/mediatek/mt8186/plat_sip_calls.c
+++ b/plat/mediatek/mt8186/plat_sip_calls.c
@@ -8,6 +8,7 @@
 #include <common/runtime_svc.h>
 #include <mt_spm_vcorefs.h>
 #include <mtk_sip_svc.h>
+#include <plat_dfd.h>
 #include "plat_sip_calls.h"
 
 uintptr_t mediatek_plat_sip_handler(uint32_t smc_fid,
@@ -27,6 +28,11 @@
 		ret = spm_vcorefs_args(x1, x2, x3, (uint64_t *)&x4);
 		SMC_RET2(handle, ret, x4);
 		break;
+	case MTK_SIP_KERNEL_DFD_AARCH32:
+	case MTK_SIP_KERNEL_DFD_AARCH64:
+		ret = dfd_smc_dispatcher(x1, x2, x3, x4);
+		SMC_RET1(handle, ret);
+		break;
 	default:
 		ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
 		break;
diff --git a/plat/mediatek/mt8186/platform.mk b/plat/mediatek/mt8186/platform.mk
index 6108a05..b6d9ca8 100644
--- a/plat/mediatek/mt8186/platform.mk
+++ b/plat/mediatek/mt8186/platform.mk
@@ -15,6 +15,7 @@
 		 -I${MTK_PLAT}/common/lpm/                        \
                  -I${MTK_PLAT_SOC}/drivers/spm/                   \
                  -I${MTK_PLAT_SOC}/drivers/dcm/                   \
+                 -I${MTK_PLAT_SOC}/drivers/dfd/                    \
                  -I${MTK_PLAT_SOC}/drivers/emi_mpu/               \
                  -I${MTK_PLAT_SOC}/drivers/gpio/               \
                  -I${MTK_PLAT_SOC}/drivers/mcdi/                  \
@@ -58,6 +59,7 @@
                 ${MTK_PLAT_SOC}/bl31_plat_setup.c                     \
                 ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c                 \
                 ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c           \
+                ${MTK_PLAT_SOC}/drivers/dfd/plat_dfd.c                \
                 ${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c             \
                 ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c                 \
                 ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm.c              \
diff --git a/plat/nxp/soc-lx2160a/aarch64/lx2160a.S b/plat/nxp/soc-lx2160a/aarch64/lx2160a.S
index 4679fc2..cc679f2 100644
--- a/plat/nxp/soc-lx2160a/aarch64/lx2160a.S
+++ b/plat/nxp/soc-lx2160a/aarch64/lx2160a.S
@@ -563,14 +563,6 @@
  */
 func _soc_sys_off
 
-	/* A-009810: LPM20 entry sequence might cause
-	 * spurious timeout reset request
-	 * workaround: MASK RESET REQ RPTOE
-	 */
-	ldr  x0, =NXP_RESET_ADDR
-	ldr  w1, =RSTRQMR_RPTOE_MASK
-	str  w1, [x0, #RST_RSTRQMR1_OFFSET]
-
 	/* disable sec, QBman, spi and qspi */
 	ldr  x2, =NXP_DCFG_ADDR
 	ldr  x0, =DCFG_DEVDISR1_OFFSET
diff --git a/plat/st/common/bl2_stm32_io_storage.c b/plat/st/common/bl2_stm32_io_storage.c
index 2d68a50..4391195 100644
--- a/plat/st/common/bl2_stm32_io_storage.c
+++ b/plat/st/common/bl2_stm32_io_storage.c
@@ -379,19 +379,21 @@
 		stm32_sdmmc2_mmc_get_device_size();
 
 #if STM32MP_EMMC_BOOT
-	magic = get_boot_part_ssbl_header();
+	if (mmc_dev_type == MMC_IS_EMMC) {
+		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;
+		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__);
+			goto emmc_boot;
+		} else {
+			WARN("%s: Can't find STM32 header on a boot partition\n", __func__);
+		}
 	}
 #endif
 
diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c
index f99cad5..d922d3c 100644
--- a/plat/st/common/stm32mp_common.c
+++ b/plat/st/common/stm32mp_common.c
@@ -210,7 +210,7 @@
 	unsigned int console_flags;
 
 	if (console_stm32_register(base, clk_rate,
-				   STM32MP_UART_BAUDRATE, &console) == 0) {
+				   (uint32_t)STM32MP_UART_BAUDRATE, &console) == 0) {
 		panic();
 	}
 
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index ca2bad8..a4c40c4 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -10,6 +10,7 @@
 USE_COHERENT_MEM	:=	0
 
 STM32MP_EARLY_CONSOLE	?=	0
+STM32MP_UART_BAUDRATE	?=	115200
 
 # Allow TF-A to concatenate BL2 & BL32 binaries in a single file,
 # share DTB file between BL2 and BL32
@@ -37,6 +38,7 @@
 
 # Not needed for Cortex-A7
 WORKAROUND_CVE_2017_5715:=	0
+WORKAROUND_CVE_2022_23960:=	0
 
 ifeq (${PSA_FWU_SUPPORT},1)
 ifneq (${STM32MP_USE_STM32IMAGE},1)
@@ -172,6 +174,7 @@
 		PLAT_PARTITION_MAX_ENTRIES \
 		STM32_TF_A_COPIES \
 		STM32_TF_VERSION \
+		STM32MP_UART_BAUDRATE \
 )))
 
 $(eval $(call add_defines,\
@@ -189,6 +192,7 @@
 		STM32MP_SDMMC \
 		STM32MP_SPI_NAND \
 		STM32MP_SPI_NOR \
+		STM32MP_UART_BAUDRATE \
 		STM32MP_UART_PROGRAMMER \
 		STM32MP_USB_PROGRAMMER \
 		STM32MP_USE_STM32IMAGE \
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index aabe81f..801b947 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -202,7 +202,6 @@
 #define USART6_BASE			U(0x44003000)
 #define UART7_BASE			U(0x40018000)
 #define UART8_BASE			U(0x40019000)
-#define STM32MP_UART_BAUDRATE		U(115200)
 
 /* For UART crash console */
 #define STM32MP_DEBUG_USART_BASE	UART4_BASE
diff --git a/plat/st/stm32mp1/stm32mp1_shared_resources.c b/plat/st/stm32mp1/stm32mp1_shared_resources.c
index 2a518e1..a0ca697 100644
--- a/plat/st/stm32mp1/stm32mp1_shared_resources.c
+++ b/plat/st/stm32mp1/stm32mp1_shared_resources.c
@@ -164,7 +164,7 @@
 	    (id <= STM32MP1_SHRES_GPIOZ(7)) &&
 	    ((unsigned int)(id - STM32MP1_SHRES_GPIOZ(0)) >= get_gpioz_nbpin())) {
 		ERROR("Invalid GPIO pin %d, %u pin(s) available\n",
-		      id - STM32MP1_SHRES_GPIOZ(0), get_gpioz_nbpin());
+		      (int)(id - STM32MP1_SHRES_GPIOZ(0)), get_gpioz_nbpin());
 		panic();
 	}
 
diff --git a/plat/xilinx/common/pm_service/pm_ipi.c b/plat/xilinx/common/pm_service/pm_ipi.c
index 7b2c8ec..03a7278 100644
--- a/plat/xilinx/common/pm_service/pm_ipi.c
+++ b/plat/xilinx/common/pm_service/pm_ipi.c
@@ -6,10 +6,8 @@
 
 
 #include <arch_helpers.h>
-
 #include <lib/bakery_lock.h>
 #include <lib/mmio.h>
-
 #include <ipi.h>
 #include <plat_ipi.h>
 #include <plat_private.h>
@@ -17,7 +15,6 @@
 
 #include "pm_ipi.h"
 
-
 #define ERROR_CODE_MASK		0xFFFFU
 
 DEFINE_BAKERY_LOCK(pm_secure_lock);
diff --git a/plat/xilinx/versal/aarch64/versal_common.c b/plat/xilinx/versal/aarch64/versal_common.c
index 2fa8476..897ed59 100644
--- a/plat/xilinx/versal/aarch64/versal_common.c
+++ b/plat/xilinx/versal/aarch64/versal_common.c
@@ -39,26 +39,11 @@
 
 void versal_config_setup(void)
 {
-	uint32_t val;
-
 	/* Configure IPI data for versal */
 	versal_ipi_config_table_init();
 
 	versal_print_platform_name();
 
-	/* Global timer init - Program time stamp reference clk */
-	val = mmio_read_32(VERSAL_CRL_TIMESTAMP_REF_CTRL);
-	val |= VERSAL_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT;
-	mmio_write_32(VERSAL_CRL_TIMESTAMP_REF_CTRL, val);
-
-	/* Clear reset of timestamp reg */
-	mmio_write_32(VERSAL_CRL_RST_TIMESTAMP_OFFSET, 0x0);
-
-	/* Program freq register in System counter and enable system counter. */
-	mmio_write_32(VERSAL_IOU_SCNTRS_BASE_FREQ, VERSAL_CPU_CLOCK);
-	mmio_write_32(VERSAL_IOU_SCNTRS_COUNTER_CONTROL_REG,
-		      VERSAL_IOU_SCNTRS_CONTROL_EN);
-
 	generic_delay_timer_init();
 }
 
diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c
index 60f7449..78bfc29 100644
--- a/plat/xilinx/versal/bl31_versal_setup.c
+++ b/plat/xilinx/versal/bl31_versal_setup.c
@@ -112,10 +112,12 @@
 						  atf_handoff_addr);
 	if (ret == FSBL_HANDOFF_NO_STRUCT || ret == FSBL_HANDOFF_INVAL_STRUCT) {
 		bl31_set_default_config();
+	} else if (ret == FSBL_HANDOFF_TOO_MANY_PARTS) {
+		ERROR("BL31: Error too many partitions %u\n", ret);
 	} else if (ret != FSBL_HANDOFF_SUCCESS) {
 		panic();
 	} else {
-		ERROR("BL31: Error during fsbl-atf handover %d.\n", ret);
+		INFO("BL31: fsbl-atf handover success %u\n", ret);
 	}
 
 	NOTICE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc);
diff --git a/plat/xilinx/versal/pm_service/pm_client.c b/plat/xilinx/versal/pm_service/pm_client.c
index 77ec20e..4c1d340 100644
--- a/plat/xilinx/versal/pm_service/pm_client.c
+++ b/plat/xilinx/versal/pm_service/pm_client.c
@@ -136,6 +136,7 @@
 			enum pm_device_node_idx node_idx;
 			uint32_t idx, irq, lowest_set = reg & (-reg);
 			enum pm_ret_status ret;
+
 			idx = __builtin_ctz(lowest_set);
 			irq = base_irq + idx;
 
diff --git a/plat/xilinx/zynqmp/include/platform_def.h b/plat/xilinx/zynqmp/include/platform_def.h
index 0c14315..1c4daa1 100644
--- a/plat/xilinx/zynqmp/include/platform_def.h
+++ b/plat/xilinx/zynqmp/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -38,7 +38,7 @@
 #ifndef ZYNQMP_ATF_MEM_BASE
 #if !DEBUG && defined(SPD_none) && !SDEI_SUPPORT
 # define BL31_BASE			0xfffea000
-# define BL31_LIMIT			0xffffffff
+# define BL31_LIMIT			0x100000000
 #else
 # define BL31_BASE			0x1000
 # define BL31_LIMIT			0x7ffff
@@ -91,10 +91,11 @@
 #define PLAT_VIRT_ADDR_SPACE_SIZE	(1ULL << 32)
 #if (BL31_LIMIT < PLAT_DDR_LOWMEM_MAX)
 #define MAX_MMAP_REGIONS		8
+#define MAX_XLAT_TABLES			6
 #else
 #define MAX_MMAP_REGIONS		7
-#endif
 #define MAX_XLAT_TABLES			5
+#endif
 
 #define CACHE_WRITEBACK_SHIFT   6
 #define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
diff --git a/plat/xilinx/zynqmp/plat_psci.c b/plat/xilinx/zynqmp/plat_psci.c
index f78b88c..b2b473a 100644
--- a/plat/xilinx/zynqmp/plat_psci.c
+++ b/plat/xilinx/zynqmp/plat_psci.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -33,6 +33,8 @@
 {
 	unsigned int cpu_id = plat_core_pos_by_mpidr(mpidr);
 	const struct pm_proc *proc;
+	uint32_t buff[3];
+	enum pm_ret_status ret;
 
 	VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr);
 
@@ -40,6 +42,13 @@
 		return PSCI_E_INTERN_FAIL;
 
 	proc = pm_get_proc(cpu_id);
+
+	/* Check the APU proc status before wakeup */
+	ret = pm_get_node_status(proc->node_id, buff);
+	if ((ret != PM_RET_SUCCESS) || (buff[0] == PM_PROC_STATE_SUSPENDING)) {
+		return PSCI_E_INTERN_FAIL;
+	}
+
 	/* Clear power down request */
 	pm_client_wakeup(proc);
 
diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk
index 3d98584..620bf6c 100644
--- a/plat/xilinx/zynqmp/platform.mk
+++ b/plat/xilinx/zynqmp/platform.mk
@@ -45,11 +45,11 @@
 
 
 ifdef ZYNQMP_WDT_RESTART
-$(eval $(call add_define,ZYNQMP_WDT_RESTART))
+    $(eval $(call add_define,ZYNQMP_WDT_RESTART))
 endif
 
 ifdef ZYNQMP_IPI_CRC_CHECK
-  $(warning "ZYNQMP_IPI_CRC_CHECK macro is deprecated...instead please use IPI_CRC_CHECK.")
+    $(warning "ZYNQMP_IPI_CRC_CHECK macro is deprecated...instead please use IPI_CRC_CHECK.")
 endif
 
 ifdef IPI_CRC_CHECK
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
index 0cc517e..4109830 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
@@ -2443,8 +2443,6 @@
  *
  * This function is used by master to get nmae of clock specified
  * by given clock ID.
- *
- * @return	Returns success. In case of error, name data is 0.
  */
 void pm_api_clock_get_name(unsigned int clock_id, char *name)
 {
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
index 9c5af88..a87681b 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -618,6 +618,7 @@
 				unsigned int *value)
 {
 	enum pm_ret_status ret;
+	uint32_t payload[PAYLOAD_ARG_CNT];
 
 	switch (ioctl_id) {
 	case IOCTL_GET_RPU_OPER_MODE:
@@ -677,14 +678,57 @@
 	case IOCTL_AFI:
 		ret = pm_ioctl_afi(arg1, arg2);
 		break;
-	case IOCTL_SET_FEATURE_CONFIG:
-	case IOCTL_GET_FEATURE_CONFIG:
-		ret = pm_feature_config(ioctl_id, arg1, arg2, value);
-		break;
 	default:
-		ret = PM_RET_ERROR_NOTSUPPORTED;
+		/* Send request to the PMU */
+		PM_PACK_PAYLOAD5(payload, PM_IOCTL, nid, ioctl_id, arg1, arg2);
+
+		ret = pm_ipi_send_sync(primary_proc, payload, value, 1);
 		break;
 	}
 
 	return ret;
 }
+
+/**
+ * pm_update_ioctl_bitmask() -  API to get supported IOCTL ID mask
+ * @bit_mask		Returned bit mask of supported IOCTL IDs
+ */
+enum pm_ret_status atf_ioctl_bitmask(uint32_t *bit_mask)
+{
+	uint8_t supported_ids[] = {
+		IOCTL_GET_RPU_OPER_MODE,
+		IOCTL_SET_RPU_OPER_MODE,
+		IOCTL_RPU_BOOT_ADDR_CONFIG,
+		IOCTL_TCM_COMB_CONFIG,
+		IOCTL_SET_TAPDELAY_BYPASS,
+		IOCTL_SET_SGMII_MODE,
+		IOCTL_SD_DLL_RESET,
+		IOCTL_SET_SD_TAPDELAY,
+		IOCTL_SET_PLL_FRAC_MODE,
+		IOCTL_GET_PLL_FRAC_MODE,
+		IOCTL_SET_PLL_FRAC_DATA,
+		IOCTL_GET_PLL_FRAC_DATA,
+		IOCTL_WRITE_GGS,
+		IOCTL_READ_GGS,
+		IOCTL_WRITE_PGGS,
+		IOCTL_READ_PGGS,
+		IOCTL_ULPI_RESET,
+		IOCTL_SET_BOOT_HEALTH_STATUS,
+		IOCTL_AFI,
+	};
+	uint8_t i, ioctl_id;
+	int ret;
+
+	for (i = 0U; i < ARRAY_SIZE(supported_ids); i++) {
+		ioctl_id = supported_ids[i];
+		if (ioctl_id >= 64U) {
+			return PM_RET_ERROR_NOTSUPPORTED;
+		}
+		ret = check_api_dependency(ioctl_id);
+		if (ret == PM_RET_SUCCESS) {
+			bit_mask[ioctl_id / 32] |= BIT(ioctl_id % 32);
+		}
+	}
+
+	return PM_RET_SUCCESS;
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h
index f18dc00..0c5f33f 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -49,9 +49,6 @@
 	IOCTL_AIE_ISR_CLEAR = 24,
 	/* Register SGI to ATF */
 	IOCTL_REGISTER_SGI = 25,
-	/* Runtime feature configuration */
-	IOCTL_SET_FEATURE_CONFIG = 26,
-	IOCTL_GET_FEATURE_CONFIG = 27,
 };
 
 //RPU operation mode
@@ -95,4 +92,5 @@
 				unsigned int arg1,
 				unsigned int arg2,
 				unsigned int *value);
+enum pm_ret_status atf_ioctl_bitmask(uint32_t *bit_mask);
 #endif /* PM_API_IOCTL_H */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
index 5d9408c..f9af451 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -20,6 +20,225 @@
 #include "pm_common.h"
 #include "pm_ipi.h"
 
+#define PM_QUERY_FEATURE_BITMASK ( \
+	(1ULL << (uint64_t)PM_QID_CLOCK_GET_NAME) | \
+	(1ULL << (uint64_t)PM_QID_CLOCK_GET_TOPOLOGY) |	\
+	(1ULL << (uint64_t)PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS) | \
+	(1ULL << (uint64_t)PM_QID_CLOCK_GET_PARENTS) | \
+	(1ULL << (uint64_t)PM_QID_CLOCK_GET_ATTRIBUTES) | \
+	(1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_PINS) | \
+	(1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_FUNCTIONS) | \
+	(1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS) | \
+	(1ULL << (uint64_t)PM_QID_PINCTRL_GET_FUNCTION_NAME) | \
+	(1ULL << (uint64_t)PM_QID_PINCTRL_GET_FUNCTION_GROUPS) | \
+	(1ULL << (uint64_t)PM_QID_PINCTRL_GET_PIN_GROUPS) | \
+	(1ULL << (uint64_t)PM_QID_CLOCK_GET_NUM_CLOCKS) | \
+	(1ULL << (uint64_t)PM_QID_CLOCK_GET_MAX_DIVISOR))
+
+/**
+ * struct eemi_api_dependency - Dependent EEMI APIs which are implemented
+ * on both the ATF and firmware
+ *
+ * @id:		EEMI API id or IOCTL id to be checked
+ * @api_id:	Dependent EEMI API
+ */
+typedef struct __attribute__((packed)) {
+	uint8_t id;
+	uint8_t api_id;
+} eemi_api_dependency;
+
+/* Dependent APIs for ATF to check their version from firmware */
+static const eemi_api_dependency api_dep_table[] = {
+	{
+		.id = PM_SELF_SUSPEND,
+		.api_id = PM_SELF_SUSPEND,
+	},
+	{
+		.id = PM_REQ_WAKEUP,
+		.api_id = PM_REQ_WAKEUP,
+	},
+	{
+		.id = PM_ABORT_SUSPEND,
+		.api_id = PM_ABORT_SUSPEND,
+	},
+	{
+		.id = PM_SET_WAKEUP_SOURCE,
+		.api_id = PM_SET_WAKEUP_SOURCE,
+	},
+	{
+		.id = PM_SYSTEM_SHUTDOWN,
+		.api_id = PM_SYSTEM_SHUTDOWN,
+	},
+	{
+		.id = PM_GET_API_VERSION,
+		.api_id = PM_GET_API_VERSION,
+	},
+	{
+		.id = PM_CLOCK_ENABLE,
+		.api_id = PM_PLL_SET_MODE,
+	},
+	{
+		.id = PM_CLOCK_ENABLE,
+		.api_id = PM_CLOCK_ENABLE,
+	},
+	{
+		.id = PM_CLOCK_DISABLE,
+		.api_id = PM_PLL_SET_MODE,
+	},
+	{
+		.id = PM_CLOCK_DISABLE,
+		.api_id = PM_CLOCK_DISABLE,
+	},
+	{
+		.id = PM_CLOCK_GETSTATE,
+		.api_id = PM_PLL_GET_MODE,
+	},
+	{
+		.id = PM_CLOCK_GETSTATE,
+		.api_id = PM_CLOCK_GETSTATE,
+	},
+	{
+		.id = PM_CLOCK_SETDIVIDER,
+		.api_id = PM_PLL_SET_PARAMETER,
+	},
+	{
+		.id = PM_CLOCK_SETDIVIDER,
+		.api_id = PM_CLOCK_SETDIVIDER,
+	},
+	{
+		.id = PM_CLOCK_GETDIVIDER,
+		.api_id = PM_PLL_GET_PARAMETER,
+	},
+	{
+		.id = PM_CLOCK_GETDIVIDER,
+		.api_id = PM_CLOCK_GETDIVIDER,
+	},
+	{
+		.id = PM_CLOCK_SETPARENT,
+		.api_id = PM_PLL_SET_PARAMETER,
+	},
+	{
+		.id = PM_CLOCK_SETPARENT,
+		.api_id = PM_CLOCK_SETPARENT,
+	},
+	{
+		.id = PM_CLOCK_GETPARENT,
+		.api_id = PM_PLL_GET_PARAMETER,
+	},
+	{
+		.id = PM_CLOCK_GETPARENT,
+		.api_id = PM_CLOCK_GETPARENT,
+	},
+	{
+		.id = PM_PLL_SET_PARAMETER,
+		.api_id = PM_PLL_SET_PARAMETER,
+	},
+	{
+		.id = PM_PLL_GET_PARAMETER,
+		.api_id = PM_PLL_GET_PARAMETER,
+	},
+	{
+		.id = PM_PLL_SET_MODE,
+		.api_id = PM_PLL_SET_MODE,
+	},
+	{
+		.id = PM_PLL_GET_MODE,
+		.api_id = PM_PLL_GET_MODE,
+	},
+	{
+		.id = PM_REGISTER_ACCESS,
+		.api_id = PM_MMIO_WRITE,
+	},
+	{
+		.id = PM_REGISTER_ACCESS,
+		.api_id = PM_MMIO_READ,
+	},
+	{
+		.id = PM_FEATURE_CHECK,
+		.api_id = PM_FEATURE_CHECK,
+	},
+	{
+		.id = IOCTL_SET_TAPDELAY_BYPASS,
+		.api_id = PM_MMIO_WRITE,
+	},
+	{
+		.id = IOCTL_SET_SGMII_MODE,
+		.api_id = PM_MMIO_WRITE,
+	},
+	{
+		.id = IOCTL_SD_DLL_RESET,
+		.api_id = PM_MMIO_WRITE,
+	},
+	{
+		.id = IOCTL_SET_SD_TAPDELAY,
+		.api_id = PM_MMIO_WRITE,
+	},
+	{
+		.id = IOCTL_SET_SD_TAPDELAY,
+		.api_id = PM_MMIO_READ,
+	},
+	{
+		.id = IOCTL_SET_PLL_FRAC_DATA,
+		.api_id = PM_PLL_SET_PARAMETER,
+	},
+	{
+		.id = IOCTL_GET_PLL_FRAC_DATA,
+		.api_id = PM_PLL_GET_PARAMETER,
+	},
+	{
+		.id = IOCTL_WRITE_GGS,
+		.api_id = PM_MMIO_WRITE,
+	},
+	{
+		.id = IOCTL_READ_GGS,
+		.api_id = PM_MMIO_READ,
+	},
+	{
+		.id = IOCTL_WRITE_PGGS,
+		.api_id = PM_MMIO_WRITE,
+	},
+	{
+		.id = IOCTL_READ_PGGS,
+		.api_id = PM_MMIO_READ,
+	},
+	{
+		.id = IOCTL_ULPI_RESET,
+		.api_id = PM_MMIO_WRITE,
+	},
+	{
+		.id = IOCTL_SET_BOOT_HEALTH_STATUS,
+		.api_id = PM_MMIO_WRITE,
+	},
+	{
+		.id = IOCTL_AFI,
+		.api_id = PM_MMIO_WRITE,
+	},
+};
+
+/* Expected firmware API version to ATF */
+static const uint8_t atf_expected_ver_id[] = {
+	[PM_SELF_SUSPEND] = FW_API_BASE_VERSION,
+	[PM_REQ_WAKEUP] = FW_API_BASE_VERSION,
+	[PM_ABORT_SUSPEND] = FW_API_BASE_VERSION,
+	[PM_SET_WAKEUP_SOURCE] = FW_API_BASE_VERSION,
+	[PM_SYSTEM_SHUTDOWN] = FW_API_BASE_VERSION,
+	[PM_GET_API_VERSION] = FW_API_BASE_VERSION,
+	[PM_PLL_SET_MODE] = FW_API_BASE_VERSION,
+	[PM_PLL_GET_MODE] = FW_API_BASE_VERSION,
+	[PM_CLOCK_ENABLE] = FW_API_BASE_VERSION,
+	[PM_CLOCK_DISABLE] = FW_API_BASE_VERSION,
+	[PM_CLOCK_GETSTATE] = FW_API_BASE_VERSION,
+	[PM_PLL_SET_PARAMETER] = FW_API_BASE_VERSION,
+	[PM_PLL_GET_PARAMETER] = FW_API_BASE_VERSION,
+	[PM_CLOCK_SETDIVIDER] = FW_API_BASE_VERSION,
+	[PM_CLOCK_GETDIVIDER] = FW_API_BASE_VERSION,
+	[PM_CLOCK_SETPARENT] = FW_API_BASE_VERSION,
+	[PM_CLOCK_GETPARENT] = FW_API_BASE_VERSION,
+	[PM_MMIO_WRITE] = FW_API_BASE_VERSION,
+	[PM_MMIO_READ] = FW_API_BASE_VERSION,
+	[PM_FEATURE_CHECK] = FW_API_VERSION_2,
+};
+
 /* default shutdown/reboot scope is system(2) */
 static unsigned int pm_shutdown_scope = PMF_SHUTDOWN_SUBTYPE_SYSTEM;
 
@@ -33,38 +252,6 @@
 	return pm_shutdown_scope;
 }
 
-/**
- * Assigning of argument values into array elements.
- */
-#define PM_PACK_PAYLOAD1(pl, arg0) {	\
-	pl[0] = (uint32_t)(arg0);	\
-}
-
-#define PM_PACK_PAYLOAD2(pl, arg0, arg1) {	\
-	pl[1] = (uint32_t)(arg1);		\
-	PM_PACK_PAYLOAD1(pl, arg0);		\
-}
-
-#define PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2) {	\
-	pl[2] = (uint32_t)(arg2);			\
-	PM_PACK_PAYLOAD2(pl, arg0, arg1);		\
-}
-
-#define PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3) {	\
-	pl[3] = (uint32_t)(arg3);			\
-	PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2);		\
-}
-
-#define PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4) {	\
-	pl[4] = (uint32_t)(arg4);				\
-	PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3);		\
-}
-
-#define PM_PACK_PAYLOAD6(pl, arg0, arg1, arg2, arg3, arg4, arg5) {	\
-	pl[5] = (uint32_t)(arg5);					\
-	PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4);		\
-}
-
 #define EM_PACK_PAYLOAD1(pl, arg0) {	\
 	pl[0] = (uint16_t)(0xE) << 16 | (uint16_t)arg0;	\
 }
@@ -305,36 +492,6 @@
 		return pm_ipi_send(primary_proc, payload);
 }
 
-/**
- * pm_release_node() - PM call to release a node
- * @nid		Node id of the slave
- *
- * @return	Returns status, either success or error+reason
- */
-enum pm_ret_status pm_release_node(enum pm_node_id nid)
-{
-	uint32_t payload[PAYLOAD_ARG_CNT];
-
-	PM_PACK_PAYLOAD2(payload, PM_RELEASE_NODE, nid);
-	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-/**
- * pm_set_max_latency() - PM call to set wakeup latency requirements
- * @nid		Node id of the slave
- * @latency	Requested maximum wakeup latency
- *
- * @return	Returns status, either success or error+reason
- */
-enum pm_ret_status pm_set_max_latency(enum pm_node_id nid,
-				      unsigned int latency)
-{
-	uint32_t payload[PAYLOAD_ARG_CNT];
-
-	PM_PACK_PAYLOAD3(payload, PM_SET_MAX_LATENCY, nid, latency);
-	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
 /* Miscellaneous API functions */
 
 /**
@@ -353,36 +510,6 @@
 }
 
 /**
- * pm_set_configuration() - PM call to set system configuration
- * @phys_addr	Physical 32-bit address of data structure in memory
- *
- * @return	Returns status, either success or error+reason
- */
-enum pm_ret_status pm_set_configuration(unsigned int phys_addr)
-{
-	uint32_t payload[PAYLOAD_ARG_CNT];
-
-	PM_PACK_PAYLOAD2(payload, PM_SET_CONFIGURATION, phys_addr);
-	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-/**
- * pm_init_finalize() - Call to notify PMU firmware that master has power
- *			management enabled and that it has finished its
- *			initialization
- *
- * @return	Status returned by the PMU firmware
- */
-enum pm_ret_status pm_init_finalize(void)
-{
-	uint32_t payload[PAYLOAD_ARG_CNT];
-
-	/* Send request to the PMU */
-	PM_PACK_PAYLOAD1(payload, PM_INIT_FINALIZE);
-	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-/**
  * pm_get_node_status() - PM call to request a node's current status
  * @nid		Node id
  * @ret_buff	Buffer for the return values:
@@ -402,86 +529,6 @@
 }
 
 /**
- * pm_register_notifier() - Register the PU to be notified of PM events
- * @nid		Node id of the slave
- * @event	The event to be notified about
- * @wake	Wake up on event
- * @enable	Enable or disable the notifier
- *
- * @return	Returns status, either success or error+reason
- */
-enum pm_ret_status pm_register_notifier(enum pm_node_id nid,
-					unsigned int event,
-					unsigned int wake,
-					unsigned int enable)
-{
-	uint32_t payload[PAYLOAD_ARG_CNT];
-
-	PM_PACK_PAYLOAD5(payload, PM_REGISTER_NOTIFIER,
-			 nid, event, wake, enable);
-
-	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-/**
- * pm_get_op_characteristic() - PM call to request operating characteristics
- *				of a node
- * @nid		Node id of the slave
- * @type	Type of the operating characteristic
- *		(power, temperature and latency)
- * @result	Returns the operating characteristic for the requested node,
- *		specified by the type
- *
- * @return	Returns status, either success or error+reason
- */
-enum pm_ret_status pm_get_op_characteristic(enum pm_node_id nid,
-					    enum pm_opchar_type type,
-					    uint32_t *result)
-{
-	uint32_t payload[PAYLOAD_ARG_CNT];
-
-	/* Send request to the PMU */
-	PM_PACK_PAYLOAD3(payload, PM_GET_OP_CHARACTERISTIC, nid, type);
-	return pm_ipi_send_sync(primary_proc, payload, result, 1);
-}
-
-/* Direct-Control API functions */
-
-/**
- * pm_reset_assert() - Assert reset
- * @reset	Reset ID
- * @assert	Assert (1) or de-assert (0)
- *
- * @return	Returns status, either success or error+reason
- */
-enum pm_ret_status pm_reset_assert(unsigned int reset,
-				   unsigned int assert)
-{
-	uint32_t payload[PAYLOAD_ARG_CNT];
-
-	/* Send request to the PMU */
-	PM_PACK_PAYLOAD3(payload, PM_RESET_ASSERT, reset, assert);
-	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-/**
- * pm_reset_get_status() - Get current status of a reset line
- * @reset	Reset ID
- * @reset_status Returns current status of selected reset line
- *
- * @return	Returns status, either success or error+reason
- */
-enum pm_ret_status pm_reset_get_status(unsigned int reset,
-				       unsigned int *reset_status)
-{
-	uint32_t payload[PAYLOAD_ARG_CNT];
-
-	/* Send request to the PMU */
-	PM_PACK_PAYLOAD2(payload, PM_RESET_GET_STATUS, reset);
-	return pm_ipi_send_sync(primary_proc, payload, reset_status, 1);
-}
-
-/**
  * pm_mmio_write() - Perform write to protected mmio
  * @address	Address to write to
  * @mask	Mask to apply
@@ -650,131 +697,238 @@
 }
 
 /**
- * pm_pinctrl_request() - Request Pin from firmware
- * @pin		Pin number to request
+ * pm_ioctl() -  PM IOCTL API for device control and configs
+ * @node_id	Node ID of the device
+ * @ioctl_id	ID of the requested IOCTL
+ * @arg1	Argument 1 to requested IOCTL call
+ * @arg2	Argument 2 to requested IOCTL call
+ * @out		Returned output value
  *
- * This function requests pin from firmware.
+ * This function calls IOCTL to firmware for device control and configuration.
  *
- * @return	Returns status, either success or error+reason.
+ * @return	Returns status, either success or error+reason
  */
-enum pm_ret_status pm_pinctrl_request(unsigned int pin)
+enum pm_ret_status pm_ioctl(enum pm_node_id nid,
+			    unsigned int ioctl_id,
+			    unsigned int arg1,
+			    unsigned int arg2,
+			    unsigned int *value)
 {
-	uint32_t payload[PAYLOAD_ARG_CNT];
-
-	/* Send request to the PMU */
-	PM_PACK_PAYLOAD2(payload, PM_PINCTRL_REQUEST, pin);
-	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+	return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value);
 }
 
 /**
- * pm_pinctrl_release() - Release Pin from firmware
- * @pin		Pin number to release
+ * fw_api_version() - Returns API version implemented in firmware
+ * @api_id	API ID to check
+ * @version	Returned supported API version
+ * @len		Number of words to be returned
  *
- * This function releases pin from firmware.
- *
- * @return	Returns status, either success or error+reason.
+ * @return	Returns status, either success or error+reason
  */
-enum pm_ret_status pm_pinctrl_release(unsigned int pin)
+static enum pm_ret_status fw_api_version(uint32_t id, uint32_t *version,
+					 uint32_t len)
 {
 	uint32_t payload[PAYLOAD_ARG_CNT];
 
-	/* Send request to the PMU */
-	PM_PACK_PAYLOAD2(payload, PM_PINCTRL_RELEASE, pin);
-	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+	PM_PACK_PAYLOAD2(payload, PM_FEATURE_CHECK, id);
+	return pm_ipi_send_sync(primary_proc, payload, version, len);
 }
 
 /**
- * pm_pinctrl_get_function() - Read function id set for the given pin
- * @pin		Pin number
- * @fid		ID of function currently set for given pin
- *
- * This function provides the function currently set for the given pin.
+ * check_api_dependency() -  API to check dependent EEMI API version
+ * @id		EEMI API ID to check
  *
  * @return	Returns status, either success or error+reason
  */
-enum pm_ret_status pm_pinctrl_get_function(unsigned int pin, unsigned int *fid)
+enum pm_ret_status check_api_dependency(uint8_t id)
 {
-	uint32_t payload[PAYLOAD_ARG_CNT];
+	uint8_t i;
+	uint32_t version;
+	int ret;
 
-	PM_PACK_PAYLOAD2(payload, PM_PINCTRL_GET_FUNCTION, pin);
-	return pm_ipi_send_sync(primary_proc, payload, fid, 1);
+	for (i = 0U; i < ARRAY_SIZE(api_dep_table); i++) {
+		if (api_dep_table[i].id == id) {
+			if (api_dep_table[i].api_id == 0U) {
+				break;
+			}
+
+			ret = fw_api_version(api_dep_table[i].api_id,
+					     &version, 1);
+			if (ret != PM_RET_SUCCESS) {
+				return ret;
+			}
+
+			/* Check if fw version matches ATF expected version */
+			if (version != atf_expected_ver_id[api_dep_table[i].api_id]) {
+				return PM_RET_ERROR_NOTSUPPORTED;
+			}
+		}
+	}
+
+	return PM_RET_SUCCESS;
 }
 
 /**
- * pm_pinctrl_set_function() - Set function id set for the given pin
- * @pin		Pin number
- * @fid		ID of function to set for given pin
+ * feature_check_atf() - These are API's completely implemented in ATF
+ * @api_id	API ID to check
+ * @version	Returned supported API version
  *
  * @return	Returns status, either success or error+reason
  */
-enum pm_ret_status pm_pinctrl_set_function(unsigned int pin, unsigned int fid)
+static enum pm_ret_status feature_check_atf(uint32_t api_id, uint32_t *version,
+					    uint32_t *bit_mask)
 {
-	uint32_t payload[PAYLOAD_ARG_CNT];
-
-	/* Send request to the PMU */
-	PM_PACK_PAYLOAD3(payload, PM_PINCTRL_SET_FUNCTION, pin, fid);
-	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+	switch (api_id) {
+	case PM_QUERY_DATA:
+		*version = ATF_API_BASE_VERSION;
+		bit_mask[0] = (uint32_t)(PM_QUERY_FEATURE_BITMASK);
+		bit_mask[1] = (uint32_t)(PM_QUERY_FEATURE_BITMASK >> 32);
+		return PM_RET_SUCCESS;
+	case PM_GET_CALLBACK_DATA:
+	case PM_GET_TRUSTZONE_VERSION:
+	case PM_SET_SUSPEND_MODE:
+		*version = ATF_API_BASE_VERSION;
+		return PM_RET_SUCCESS;
+	default:
+		return PM_RET_ERROR_NO_FEATURE;
+	}
 }
 
 /**
- * pm_pinctrl_get_config() - Read value of requested config param for given pin
- * @pin		Pin number
- * @param	Parameter values to be read
- * @value	Buffer for configuration Parameter value
- *
- * This function provides the configuration parameter value for the given pin.
+ * get_atf_version_for_partial_apis() - Return ATF version for partially
+ * implemented APIs
+ * @api_id	API ID to check
+ * @version	Returned supported API version
  *
  * @return	Returns status, either success or error+reason
  */
-enum pm_ret_status pm_pinctrl_get_config(unsigned int pin,
-					 unsigned int param,
-					 unsigned int *value)
+static enum pm_ret_status get_atf_version_for_partial_apis(uint32_t api_id,
+							   uint32_t *version)
 {
-	uint32_t payload[PAYLOAD_ARG_CNT];
-
-	PM_PACK_PAYLOAD3(payload, PM_PINCTRL_CONFIG_PARAM_GET, pin, param);
-	return pm_ipi_send_sync(primary_proc, payload, value, 1);
+	switch (api_id) {
+	case PM_SELF_SUSPEND:
+	case PM_REQ_WAKEUP:
+	case PM_ABORT_SUSPEND:
+	case PM_SET_WAKEUP_SOURCE:
+	case PM_SYSTEM_SHUTDOWN:
+	case PM_GET_API_VERSION:
+	case PM_CLOCK_ENABLE:
+	case PM_CLOCK_DISABLE:
+	case PM_CLOCK_GETSTATE:
+	case PM_CLOCK_SETDIVIDER:
+	case PM_CLOCK_GETDIVIDER:
+	case PM_CLOCK_SETPARENT:
+	case PM_CLOCK_GETPARENT:
+	case PM_PLL_SET_PARAMETER:
+	case PM_PLL_GET_PARAMETER:
+	case PM_PLL_SET_MODE:
+	case PM_PLL_GET_MODE:
+	case PM_REGISTER_ACCESS:
+		*version = ATF_API_BASE_VERSION;
+		return PM_RET_SUCCESS;
+	case PM_FEATURE_CHECK:
+		*version = FW_API_VERSION_2;
+		return PM_RET_SUCCESS;
+	default:
+		return PM_RET_ERROR_ARGS;
+	}
 }
 
 /**
- * pm_pinctrl_set_config() - Set value of requested config param for given pin
- * @pin		Pin number
- * @param	Parameter to set
- * @value	Parameter value to set
+ * feature_check_partial() - These are API's partially implemented in
+ * ATF and firmware both
+ * @api_id	API ID to check
+ * @version	Returned supported API version
  *
  * @return	Returns status, either success or error+reason
  */
-enum pm_ret_status pm_pinctrl_set_config(unsigned int pin,
-					 unsigned int param,
-					 unsigned int value)
+static enum pm_ret_status feature_check_partial(uint32_t api_id,
+						uint32_t *version)
 {
-	uint32_t payload[PAYLOAD_ARG_CNT];
+	uint32_t status;
 
-	/* Send request to the PMU */
-	PM_PACK_PAYLOAD4(payload, PM_PINCTRL_CONFIG_PARAM_SET, pin, param,
-			 value);
-	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+	switch (api_id) {
+	case PM_SELF_SUSPEND:
+	case PM_REQ_WAKEUP:
+	case PM_ABORT_SUSPEND:
+	case PM_SET_WAKEUP_SOURCE:
+	case PM_SYSTEM_SHUTDOWN:
+	case PM_GET_API_VERSION:
+	case PM_CLOCK_ENABLE:
+	case PM_CLOCK_DISABLE:
+	case PM_CLOCK_GETSTATE:
+	case PM_CLOCK_SETDIVIDER:
+	case PM_CLOCK_GETDIVIDER:
+	case PM_CLOCK_SETPARENT:
+	case PM_CLOCK_GETPARENT:
+	case PM_PLL_SET_PARAMETER:
+	case PM_PLL_GET_PARAMETER:
+	case PM_PLL_SET_MODE:
+	case PM_PLL_GET_MODE:
+	case PM_REGISTER_ACCESS:
+	case PM_FEATURE_CHECK:
+		status = check_api_dependency(api_id);
+		if (status != PM_RET_SUCCESS) {
+			return status;
+		}
+		return get_atf_version_for_partial_apis(api_id, version);
+	default:
+		return PM_RET_ERROR_NO_FEATURE;
+	}
 }
 
 /**
- * pm_ioctl() -  PM IOCTL API for device control and configs
- * @node_id	Node ID of the device
- * @ioctl_id	ID of the requested IOCTL
- * @arg1	Argument 1 to requested IOCTL call
- * @arg2	Argument 2 to requested IOCTL call
- * @out		Returned output value
- *
- * This function calls IOCTL to firmware for device control and configuration.
+ * pm_feature_check() - Returns the supported API version if supported
+ * @api_id	API ID to check
+ * @version	Returned supported API version
+ * @bit_mask	Returned supported IOCTL id version
+ * @len		Number of bytes to be returned in bit_mask variable
  *
  * @return	Returns status, either success or error+reason
  */
-enum pm_ret_status pm_ioctl(enum pm_node_id nid,
-			    unsigned int ioctl_id,
-			    unsigned int arg1,
-			    unsigned int arg2,
-			    unsigned int *value)
+enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *version,
+				    uint32_t *bit_mask, uint8_t len)
 {
-	return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value);
+	uint32_t ret_payload[PAYLOAD_ARG_CNT] = {0U};
+	uint32_t status;
+
+	/* Get API version implemented in ATF */
+	status = feature_check_atf(api_id, version, bit_mask);
+	if (status != PM_RET_ERROR_NO_FEATURE) {
+		return status;
+	}
+
+	/* Get API version implemented by firmware and ATF both */
+	status = feature_check_partial(api_id, version);
+	if (status != PM_RET_ERROR_NO_FEATURE) {
+		return status;
+	}
+
+	/* Get API version implemented by firmware */
+	status = fw_api_version(api_id, ret_payload, 3);
+	/* IOCTL call may return failure whose ID is not implemented in
+	 * firmware but implemented in ATF
+	 */
+	if ((api_id != PM_IOCTL) && (status != PM_RET_SUCCESS)) {
+		return status;
+	}
+
+	*version = ret_payload[0];
+
+	/* Update IOCTL bit mask which are implemented in ATF */
+	if (api_id == PM_IOCTL) {
+		if (len < 2) {
+			return PM_RET_ERROR_ARGS;
+		}
+		bit_mask[0] = ret_payload[1];
+		bit_mask[1] = ret_payload[2];
+		/* Get IOCTL's implemented by ATF */
+		status = atf_ioctl_bitmask(bit_mask);
+	} else {
+		/* Requires for MISRA */
+	}
+
+	return status;
 }
 
 /**
@@ -1648,36 +1802,3 @@
 	EM_PACK_PAYLOAD1(payload, EM_SEND_ERRORS);
 	return pm_ipi_send_sync(primary_proc, payload, value, 1);
 }
-
-/**
- * pm_feature_config() - feature configuration at runtime
- *
- * This function is used to send IPI request to PMUFW to configure feature
- * at runtime. The feature can be enable or disable as well as the feature
- * can be configure at runtime using an IOCTL call.
- *
- * @ioctl_id	The ioctl id for the feature configuration
- * @config_id	The config id of the feature to be configured
- * @value	The value to be configured
- * @response	Return to reference pointer
- *
- * @return      Returns 0 on success or error value on failure
- */
-enum pm_ret_status pm_feature_config(unsigned int ioctl_id,
-				     unsigned int config_id,
-				     unsigned int value,
-				     unsigned int *response)
-{
-	uint32_t payload[PAYLOAD_ARG_CNT];
-
-	/* Send request to the PMU */
-	PM_PACK_PAYLOAD5(payload, PM_IOCTL, 0, ioctl_id, config_id, value);
-
-	if (ioctl_id == IOCTL_GET_FEATURE_CONFIG) {
-		return pm_ipi_send_sync(primary_proc, payload, response, 1);
-	} else if (ioctl_id == IOCTL_SET_FEATURE_CONFIG) {
-		return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-	} else {
-		return PM_RET_ERROR_ARGS;
-	}
-}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
index ca07cef..48b3877 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -33,6 +33,38 @@
 	CONFIG_REG_READ,
 };
 
+/**
+ * Assigning of argument values into array elements.
+ */
+#define PM_PACK_PAYLOAD1(pl, arg0) {	\
+	pl[0] = (uint32_t)(arg0);	\
+}
+
+#define PM_PACK_PAYLOAD2(pl, arg0, arg1) {	\
+	pl[1] = (uint32_t)(arg1);		\
+	PM_PACK_PAYLOAD1(pl, arg0);		\
+}
+
+#define PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2) {	\
+	pl[2] = (uint32_t)(arg2);			\
+	PM_PACK_PAYLOAD2(pl, arg0, arg1);		\
+}
+
+#define PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3) {	\
+	pl[3] = (uint32_t)(arg3);			\
+	PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2);		\
+}
+
+#define PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4) {	\
+	pl[4] = (uint32_t)(arg4);				\
+	PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3);		\
+}
+
+#define PM_PACK_PAYLOAD6(pl, arg0, arg1, arg2, arg3, arg4, arg5) {	\
+	pl[5] = (uint32_t)(arg5);					\
+	PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4);		\
+}
+
 /**********************************************************
  * System-level API function declarations
  **********************************************************/
@@ -72,28 +104,16 @@
 			       unsigned int capabilities,
 			       unsigned int qos,
 			       enum pm_request_ack ack);
-enum pm_ret_status pm_release_node(enum pm_node_id nid);
 
 enum pm_ret_status pm_set_requirement(enum pm_node_id nid,
 				      unsigned int capabilities,
 				      unsigned int qos,
 				      enum pm_request_ack ack);
-enum pm_ret_status pm_set_max_latency(enum pm_node_id nid,
-				      unsigned int latency);
 
 /* Miscellaneous API functions */
 enum pm_ret_status pm_get_api_version(unsigned int *version);
-enum pm_ret_status pm_set_configuration(unsigned int phys_addr);
-enum pm_ret_status pm_init_finalize(void);
 enum pm_ret_status pm_get_node_status(enum pm_node_id node,
 				      uint32_t *ret_buff);
-enum pm_ret_status pm_register_notifier(enum pm_node_id nid,
-					unsigned int event,
-					unsigned int wake,
-					unsigned int enable);
-enum pm_ret_status pm_get_op_characteristic(enum pm_node_id nid,
-					    enum pm_opchar_type type,
-					    uint32_t *result);
 enum pm_ret_status pm_acknowledge_cb(enum pm_node_id nid,
 				     enum pm_ret_status status,
 				     unsigned int oppoint);
@@ -102,10 +122,6 @@
 				unsigned int oppoint);
 
 /* Direct-Control API functions */
-enum pm_ret_status pm_reset_assert(unsigned int reset_id,
-				   unsigned int assert);
-enum pm_ret_status pm_reset_get_status(unsigned int reset_id,
-				       unsigned int *reset_status);
 enum pm_ret_status pm_mmio_write(uintptr_t address,
 				 unsigned int mask,
 				 unsigned int value);
@@ -123,18 +139,6 @@
 				    uint32_t flags);
 unsigned int pm_get_shutdown_scope(void);
 void pm_get_callbackdata(uint32_t *data, size_t count);
-enum pm_ret_status pm_pinctrl_request(unsigned int pin);
-enum pm_ret_status pm_pinctrl_release(unsigned int pin);
-enum pm_ret_status pm_pinctrl_get_function(unsigned int pin,
-					   enum pm_node_id *nid);
-enum pm_ret_status pm_pinctrl_set_function(unsigned int pin,
-					   enum pm_node_id nid);
-enum pm_ret_status pm_pinctrl_get_config(unsigned int pin,
-					 unsigned int param,
-					 unsigned int *value);
-enum pm_ret_status pm_pinctrl_set_config(unsigned int pin,
-					 unsigned int param,
-					 unsigned int value);
 enum pm_ret_status pm_ioctl(enum pm_node_id nid,
 			    unsigned int ioctl_id,
 			    unsigned int arg1,
@@ -171,7 +175,6 @@
 				   uint32_t key_lo,
 				   uint32_t key_hi,
 				   uint32_t *value);
-
 enum pm_ret_status pm_fpga_read(uint32_t reg_numframes,
 				uint32_t address_low,
 				uint32_t address_high,
@@ -185,15 +188,12 @@
 				      unsigned int mask,
 				      unsigned int value,
 				      unsigned int *out);
-
 enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid,
-				enum pm_pll_param param_id,
-				unsigned int value);
-
+					enum pm_pll_param param_id,
+					unsigned int value);
 enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid,
-				enum pm_pll_param param_id,
-				unsigned int *value);
-
+					enum pm_pll_param param_id,
+					unsigned int *value);
 enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode);
 enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode);
 enum pm_ret_status pm_efuse_access(uint32_t address_high,
@@ -201,10 +201,12 @@
 enum pm_ret_status em_set_action(unsigned int *value);
 enum pm_ret_status em_remove_action(unsigned int *value);
 enum pm_ret_status em_send_errors(unsigned int *value);
-
 enum pm_ret_status pm_feature_config(unsigned int ioctl_id,
 				     unsigned int config_id,
 				     unsigned int value,
 				     unsigned int *response);
+enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *version,
+				    uint32_t *bit_mask, uint8_t len);
+enum pm_ret_status check_api_dependency(uint8_t id);
 
 #endif /* PM_API_SYS_H */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h
index 3324431..8eb197a 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_defs.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -22,6 +22,16 @@
 
 #define PM_VERSION	((PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR)
 
+/**
+ * PM API versions
+ */
+/* Expected version of firmware APIs */
+#define FW_API_BASE_VERSION		(1U)
+/* Expected version of firmware API for feature check */
+#define FW_API_VERSION_2		(2U)
+/* Version of APIs implemented in ATF */
+#define ATF_API_BASE_VERSION		(1U)
+
 /* Capabilities for RAM */
 #define PM_CAP_ACCESS	0x1U
 #define PM_CAP_CONTEXT	0x2U
@@ -33,7 +43,18 @@
 #define PM_STATE_CPU_IDLE		0x0U
 #define PM_STATE_SUSPEND_TO_RAM		0xFU
 
+/* APU processor states */
+#define PM_PROC_STATE_FORCEDOFF		0U
+#define PM_PROC_STATE_ACTIVE		1U
+#define PM_PROC_STATE_SLEEP		2U
+#define PM_PROC_STATE_SUSPENDING	3U
+
 #define EM_FUNID_NUM_MASK    0xF0000U
+
+#define PM_GET_CALLBACK_DATA		0xa01
+#define PM_SET_SUSPEND_MODE		0xa02
+#define PM_GET_TRUSTZONE_VERSION	0xa03
+
 /*********************************************************************
  * Enum definitions
  ********************************************************************/
@@ -101,6 +122,9 @@
 	/* PM Register Access API */
 	PM_REGISTER_ACCESS,
 	PM_EFUSE_ACCESS,
+	PM_FPGA_GET_VERSION,
+	PM_FPGA_GET_FEATURE_LIST,
+	PM_FEATURE_CHECK = 63,
 	PM_API_MAX
 };
 
@@ -241,7 +265,8 @@
 	PM_RET_ERROR_DOUBLE_REQ = 2004,
 	PM_RET_ERROR_ABORT_SUSPEND = 2005,
 	PM_RET_ERROR_TIMEOUT = 2006,
-	PM_RET_ERROR_NODE_USED = 2007
+	PM_RET_ERROR_NODE_USED = 2007,
+	PM_RET_ERROR_NO_FEATURE = 2008
 };
 
 /**
@@ -278,16 +303,16 @@
 };
 
 /**
- * @PM_PLL_PARAM_DIV2:         Enable for divide by 2 function inside the PLL
- * @PM_PLL_PARAM_FBDIV:        Feedback divisor integer portion for the PLL
- * @PM_PLL_PARAM_DATA:         Feedback divisor fractional portion for the PLL
- * @PM_PLL_PARAM_PRE_SRC:      Clock source for PLL input
- * @PM_PLL_PARAM_POST_SRC:     Clock source for PLL Bypass mode
- * @PM_PLL_PARAM_LOCK_DLY:     Lock circuit config settings for lock windowsize
- * @PM_PLL_PARAM_LOCK_CNT:     Lock circuit counter setting
- * @PM_PLL_PARAM_LFHF:         PLL loop filter high frequency capacitor control
- * @PM_PLL_PARAM_CP:           PLL charge pump control
- * @PM_PLL_PARAM_RES:          PLL loop filter resistor control
+ * @PM_PLL_PARAM_DIV2:		Enable for divide by 2 function inside the PLL
+ * @PM_PLL_PARAM_FBDIV:		Feedback divisor integer portion for the PLL
+ * @PM_PLL_PARAM_DATA:		Feedback divisor fractional portion for the PLL
+ * @PM_PLL_PARAM_PRE_SRC:	Clock source for PLL input
+ * @PM_PLL_PARAM_POST_SRC:	Clock source for PLL Bypass mode
+ * @PM_PLL_PARAM_LOCK_DLY:	Lock circuit config settings for lock windowsize
+ * @PM_PLL_PARAM_LOCK_CNT:	Lock circuit counter setting
+ * @PM_PLL_PARAM_LFHF:		PLL loop filter high frequency capacitor control
+ * @PM_PLL_PARAM_CP:		PLL charge pump control
+ * @PM_PLL_PARAM_RES:		PLL loop filter resistor control
  */
 enum pm_pll_param {
 	PM_PLL_PARAM_DIV2,
@@ -304,9 +329,9 @@
 };
 
 /**
- * @PM_PLL_MODE_RESET:         PLL is in reset (not locked)
- * @PM_PLL_MODE_INTEGER:       PLL is locked in integer mode
- * @PM_PLL_MODE_FRACTIONAL:    PLL is locked in fractional mode
+ * @PM_PLL_MODE_RESET:		PLL is in reset (not locked)
+ * @PM_PLL_MODE_INTEGER:	PLL is locked in integer mode
+ * @PM_PLL_MODE_FRACTIONAL:	PLL is locked in fractional mode
  */
 enum pm_pll_mode {
 	PM_PLL_MODE_RESET,
@@ -316,8 +341,8 @@
 };
 
 /**
- * @PM_CLOCK_DIV0_ID:          Clock divider 0
- * @PM_CLOCK_DIV1_ID:          Clock divider 1
+ * @PM_CLOCK_DIV0_ID:		Clock divider 0
+ * @PM_CLOCK_DIV1_ID:		Clock divider 1
  */
 enum pm_clock_div_id {
 	PM_CLOCK_DIV0_ID,
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
index a49bda8..d88e5fa 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -23,12 +23,9 @@
 #include <plat_private.h>
 #include "pm_api_sys.h"
 #include "pm_client.h"
+#include "pm_defs.h"
 #include "pm_ipi.h"
 
-#define PM_GET_CALLBACK_DATA	0xa01
-#define PM_SET_SUSPEND_MODE	0xa02
-#define PM_GET_TRUSTZONE_VERSION	0xa03
-
 /* pm_up = !0 - UP, pm_up = 0 - DOWN */
 static int32_t pm_up, ipi_irq_flag;
 
@@ -37,7 +34,6 @@
 static int active_cores = 0;
 #endif
 
-
 /**
  * pm_context - Structure which contains data for power management
  * @api_version		version of PM API, must match with one on PMU side
@@ -106,7 +102,7 @@
  * action.
  */
 static uint64_t ttc_fiq_handler(uint32_t id, uint32_t flags, void *handle,
-                               void *cookie)
+				void *cookie)
 {
 	INFO("BL31: Got TTC FIQ\n");
 
@@ -139,7 +135,7 @@
  * running CPU calls system restart.
  */
 static uint64_t __unused __dead2 zynqmp_sgi7_irq(uint32_t id, uint32_t flags,
-                                                void *handle, void *cookie)
+						 void *handle, void *cookie)
 {
 	int i;
 	uint32_t value;
@@ -262,8 +258,11 @@
 			uint64_t x4, void *cookie, void *handle, uint64_t flags)
 {
 	enum pm_ret_status ret;
+	uint32_t payload[PAYLOAD_ARG_CNT];
 
 	uint32_t pm_arg[4];
+	uint32_t result[PAYLOAD_ARG_CNT];
+	uint32_t api_id;
 
 	/* Handle case where PM wasn't initialized properly */
 	if (!pm_up)
@@ -273,8 +272,11 @@
 	pm_arg[1] = (uint32_t)(x1 >> 32);
 	pm_arg[2] = (uint32_t)x2;
 	pm_arg[3] = (uint32_t)(x2 >> 32);
+	pm_arg[4] = (uint32_t)x3;
 
-	switch (smc_fid & FUNCID_NUM_MASK) {
+	api_id = smc_fid & FUNCID_NUM_MASK;
+
+	switch (api_id) {
 	/* PM API Functions */
 	case PM_SELF_SUSPEND:
 		ret = pm_self_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
@@ -318,19 +320,11 @@
 		ret = pm_req_node(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]);
 		SMC_RET1(handle, (uint64_t)ret);
 
-	case PM_RELEASE_NODE:
-		ret = pm_release_node(pm_arg[0]);
-		SMC_RET1(handle, (uint64_t)ret);
-
 	case PM_SET_REQUIREMENT:
 		ret = pm_set_requirement(pm_arg[0], pm_arg[1], pm_arg[2],
 					 pm_arg[3]);
 		SMC_RET1(handle, (uint64_t)ret);
 
-	case PM_SET_MAX_LATENCY:
-		ret = pm_set_max_latency(pm_arg[0], pm_arg[1]);
-		SMC_RET1(handle, (uint64_t)ret);
-
 	case PM_GET_API_VERSION:
 		/* Check is PM API version already verified */
 		if (pm_ctx.api_version >= PM_VERSION) {
@@ -348,62 +342,6 @@
 				 ((uint64_t)pm_ctx.api_version << 32));
 		}
 
-	case PM_SET_CONFIGURATION:
-		ret = pm_set_configuration(pm_arg[0]);
-		SMC_RET1(handle, (uint64_t)ret);
-
-	case PM_INIT_FINALIZE:
-		ret = pm_init_finalize();
-		SMC_RET1(handle, (uint64_t)ret);
-
-	case PM_GET_NODE_STATUS:
-	{
-		uint32_t buff[3];
-
-		ret = pm_get_node_status(pm_arg[0], buff);
-		SMC_RET2(handle, (uint64_t)ret | ((uint64_t)buff[0] << 32),
-			 (uint64_t)buff[1] | ((uint64_t)buff[2] << 32));
-	}
-
-	case PM_GET_OP_CHARACTERISTIC:
-	{
-		uint32_t result;
-
-		ret = pm_get_op_characteristic(pm_arg[0], pm_arg[1], &result);
-		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)result << 32));
-	}
-
-	case PM_REGISTER_NOTIFIER:
-		ret = pm_register_notifier(pm_arg[0], pm_arg[1], pm_arg[2],
-					   pm_arg[3]);
-		SMC_RET1(handle, (uint64_t)ret);
-
-	case PM_RESET_ASSERT:
-		ret = pm_reset_assert(pm_arg[0], pm_arg[1]);
-		SMC_RET1(handle, (uint64_t)ret);
-
-	case PM_RESET_GET_STATUS:
-	{
-		uint32_t reset_status;
-
-		ret = pm_reset_get_status(pm_arg[0], &reset_status);
-		SMC_RET1(handle, (uint64_t)ret |
-			 ((uint64_t)reset_status << 32));
-	}
-
-	/* PM memory access functions */
-	case PM_MMIO_WRITE:
-		ret = pm_mmio_write(pm_arg[0], pm_arg[1], pm_arg[2]);
-		SMC_RET1(handle, (uint64_t)ret);
-
-	case PM_MMIO_READ:
-	{
-		uint32_t value;
-
-		ret = pm_mmio_read(pm_arg[0], &value);
-		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
-	}
-
 	case PM_FPGA_LOAD:
 		ret = pm_fpga_load(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]);
 		SMC_RET1(handle, (uint64_t)ret);
@@ -416,62 +354,16 @@
 		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
 	}
 
-	case PM_GET_CHIPID:
-	{
-		uint32_t result[2];
-
-		ret = pm_get_chipid(result);
-		SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32),
-			 result[1]);
-	}
-
 	case PM_SECURE_RSA_AES:
 		ret = pm_secure_rsaaes(pm_arg[0], pm_arg[1], pm_arg[2],
 				       pm_arg[3]);
 		SMC_RET1(handle, (uint64_t)ret);
 
 	case PM_GET_CALLBACK_DATA:
-	{
-		uint32_t result[4] = {0};
-
 		pm_get_callbackdata(result, ARRAY_SIZE(result));
 		SMC_RET2(handle,
 			 (uint64_t)result[0] | ((uint64_t)result[1] << 32),
 			 (uint64_t)result[2] | ((uint64_t)result[3] << 32));
-	}
-
-	case PM_PINCTRL_REQUEST:
-		ret = pm_pinctrl_request(pm_arg[0]);
-		SMC_RET1(handle, (uint64_t)ret);
-
-	case PM_PINCTRL_RELEASE:
-		ret = pm_pinctrl_release(pm_arg[0]);
-		SMC_RET1(handle, (uint64_t)ret);
-
-	case PM_PINCTRL_GET_FUNCTION:
-	{
-		uint32_t value = 0;
-
-		ret = pm_pinctrl_get_function(pm_arg[0], &value);
-		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
-	}
-
-	case PM_PINCTRL_SET_FUNCTION:
-		ret = pm_pinctrl_set_function(pm_arg[0], pm_arg[1]);
-		SMC_RET1(handle, (uint64_t)ret);
-
-	case PM_PINCTRL_CONFIG_PARAM_GET:
-	{
-		uint32_t value;
-
-		ret = pm_pinctrl_get_config(pm_arg[0], pm_arg[1], &value);
-		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
-	}
-
-	case PM_PINCTRL_CONFIG_PARAM_SET:
-		ret = pm_pinctrl_set_config(pm_arg[0], pm_arg[1], pm_arg[2]);
-		SMC_RET1(handle, (uint64_t)ret);
-
 	case PM_IOCTL:
 	{
 		uint32_t value;
@@ -568,8 +460,6 @@
 
 	case PM_SECURE_IMAGE:
 	{
-		uint32_t result[2];
-
 		ret = pm_secure_image(pm_arg[0], pm_arg[1], pm_arg[2],
 				      pm_arg[3], &result[0]);
 		SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32),
@@ -634,9 +524,37 @@
 		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
 	}
 
+	case PM_FPGA_GET_VERSION:
+	case PM_FPGA_GET_FEATURE_LIST:
+	{
+		uint32_t ret_payload[PAYLOAD_ARG_CNT];
+
+		PM_PACK_PAYLOAD5(payload, smc_fid & FUNCID_NUM_MASK,
+				 pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]);
+		ret = pm_ipi_send_sync(primary_proc, payload, ret_payload, 3U);
+		SMC_RET2(handle, (uint64_t)ret | (uint64_t)ret_payload[0] << 32,
+			 (uint64_t)ret_payload[1] | (uint64_t)ret_payload[2] << 32);
+	}
+
+	case PM_FEATURE_CHECK:
+	{
+		uint32_t version;
+		uint32_t bit_mask[2] = {0};
+
+		ret = pm_feature_check(pm_arg[0], &version, bit_mask,
+				       ARRAY_SIZE(bit_mask));
+		SMC_RET2(handle, (uint64_t)ret | ((uint64_t)version << 32),
+			 (uint64_t)bit_mask[0] | ((uint64_t)bit_mask[1] << 32));
+	}
+
 	default:
-		WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid);
-		SMC_RET1(handle, SMC_UNK);
+		/* Send request to the PMU */
+		PM_PACK_PAYLOAD6(payload, api_id, pm_arg[0], pm_arg[1],
+				 pm_arg[2], pm_arg[3], pm_arg[4]);
+		ret = pm_ipi_send_sync(primary_proc, payload, result,
+				       PAYLOAD_ARG_CNT);
+		SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32),
+			 (uint64_t)result[1] | ((uint64_t)result[2] << 32));
 	}
 }
 
diff --git a/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
index 5e770f7..352ba82 100644
--- a/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
+++ b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c
@@ -8,7 +8,6 @@
 #include <common/debug.h>
 #include <drivers/console.h>
 #include <plat/arm/common/plat_arm.h>
-
 #include <plat_private.h>
 #include <platform_tsp.h>
 
diff --git a/services/arm_arch_svc/arm_arch_svc_setup.c b/services/arm_arch_svc/arm_arch_svc_setup.c
index 5523a1c..46ccd9e 100644
--- a/services/arm_arch_svc/arm_arch_svc_setup.c
+++ b/services/arm_arch_svc/arm_arch_svc_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,6 +9,7 @@
 #include <lib/cpus/errata_report.h>
 #include <lib/cpus/wa_cve_2017_5715.h>
 #include <lib/cpus/wa_cve_2018_3639.h>
+#include <lib/cpus/wa_cve_2022_23960.h>
 #include <lib/smccc.h>
 #include <services/arm_arch_svc.h>
 #include <smccc_helpers.h>
@@ -74,6 +75,20 @@
 	}
 #endif
 
+#if (WORKAROUND_CVE_2022_23960 || WORKAROUND_CVE_2017_5715)
+	case SMCCC_ARCH_WORKAROUND_3:
+		/*
+		 * SMCCC_ARCH_WORKAROUND_3 should also take into account
+		 * CVE-2017-5715 since this SMC can be used instead of
+		 * SMCCC_ARCH_WORKAROUND_1.
+		 */
+		if ((check_smccc_arch_wa3_applies() == ERRATA_NOT_APPLIES) &&
+		    (check_wa_cve_2017_5715() == ERRATA_NOT_APPLIES)) {
+			return 1;
+		}
+		return 0; /* ERRATA_APPLIES || ERRATA_MISSING */
+#endif
+
 	/* Fallthrough */
 
 	default:
@@ -117,7 +132,7 @@
 	case SMCCC_ARCH_WORKAROUND_1:
 		/*
 		 * The workaround has already been applied on affected PEs
-		 * during entry to EL3.  On unaffected PEs, this function
+		 * during entry to EL3. On unaffected PEs, this function
 		 * has no effect.
 		 */
 		SMC_RET0(handle);
@@ -132,6 +147,15 @@
 		 */
 		SMC_RET0(handle);
 #endif
+#if (WORKAROUND_CVE_2022_23960 || WORKAROUND_CVE_2017_5715)
+	case SMCCC_ARCH_WORKAROUND_3:
+		/*
+		 * The workaround has already been applied on affected PEs
+		 * during entry to EL3. On unaffected PEs, this function
+		 * has no effect.
+		 */
+		SMC_RET0(handle);
+#endif
 	default:
 		WARN("Unimplemented Arm Architecture Service Call: 0x%x \n",
 			smc_fid);
diff --git a/services/std_svc/rmmd/rmmd_main.c b/services/std_svc/rmmd/rmmd_main.c
index c4ea706..28d0b01 100644
--- a/services/std_svc/rmmd/rmmd_main.c
+++ b/services/std_svc/rmmd/rmmd_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -325,30 +325,6 @@
 /* Subscribe to PSCI CPU on to initialize RMM on secondary */
 SUBSCRIBE_TO_EVENT(psci_cpu_on_finish, rmmd_cpu_on_finish_handler);
 
-static int gtsi_transition_granule(uint64_t pa,
-					unsigned int src_sec_state,
-					unsigned int target_pas)
-{
-	int ret;
-
-	ret = gpt_transition_pas(pa, PAGE_SIZE_4KB, src_sec_state, target_pas);
-
-	/* Convert TF-A error codes into GTSI error codes */
-	if (ret == -EINVAL) {
-		ERROR("[GTSI] Transition failed: invalid %s\n", "address");
-		ERROR("       PA: 0x%" PRIx64 ", SRC: %d, PAS: %d\n", pa,
-		      src_sec_state, target_pas);
-		ret = GRAN_TRANS_RET_BAD_ADDR;
-	} else if (ret == -EPERM) {
-		ERROR("[GTSI] Transition failed: invalid %s\n", "caller/PAS");
-		ERROR("       PA: 0x%" PRIx64 ", SRC: %d, PAS: %d\n", pa,
-		      src_sec_state, target_pas);
-		ret = GRAN_TRANS_RET_BAD_PAS;
-	}
-
-	return ret;
-}
-
 /*******************************************************************************
  * This function handles all SMCs in the range reserved for GTF.
  ******************************************************************************/
@@ -357,6 +333,7 @@
 				void *handle, uint64_t flags)
 {
 	uint32_t src_sec_state;
+	int ret;
 
 	/* Determine which security state this SMC originated from */
 	src_sec_state = caller_sec_state(flags);
@@ -368,13 +345,27 @@
 
 	switch (smc_fid) {
 	case SMC_ASC_MARK_REALM:
-		SMC_RET1(handle, gtsi_transition_granule(x1, SMC_FROM_REALM,
-								GPT_GPI_REALM));
+		ret = gpt_delegate_pas(x1, PAGE_SIZE_4KB, SMC_FROM_REALM);
+		break;
 	case SMC_ASC_MARK_NONSECURE:
-		SMC_RET1(handle, gtsi_transition_granule(x1, SMC_FROM_REALM,
-								GPT_GPI_NS));
+		ret = gpt_undelegate_pas(x1, PAGE_SIZE_4KB, SMC_FROM_REALM);
+		break;
 	default:
 		WARN("RMM: Unsupported GTF call 0x%08x\n", smc_fid);
 		SMC_RET1(handle, SMC_UNK);
 	}
+
+	if (ret == -EINVAL) {
+		ERROR("[GTSI] Transition failed: invalid %s\n", "address");
+		ERROR("       PA: 0x%"PRIx64 ", SRC: %d, PAS: %d\n", x1,
+		      SMC_FROM_REALM, smc_fid);
+		ret = GRAN_TRANS_RET_BAD_ADDR;
+	} else if (ret == -EPERM) {
+		ERROR("[GTSI] Transition failed: invalid %s\n", "caller/PAS");
+		ERROR("       PA: 0x%"PRIx64 ", SRC: %d, PAS: %d\n", x1,
+		      SMC_FROM_REALM, smc_fid);
+		ret = GRAN_TRANS_RET_BAD_PAS;
+	}
+
+	SMC_RET1(handle, ret);
 }
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
index bfee2dd..27a8382 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -90,6 +90,21 @@
 				 uint64_t x4,
 				 void *handle);
 
+/******************************************************************************
+ * Builds an SPMD to SPMC direct message request.
+ *****************************************************************************/
+void spmd_build_spmc_message(gp_regs_t *gpregs, uint8_t target_func,
+			     unsigned long long message)
+{
+	write_ctx_reg(gpregs, CTX_GPREG_X0, FFA_MSG_SEND_DIRECT_REQ_SMC32);
+	write_ctx_reg(gpregs, CTX_GPREG_X1,
+		(SPMD_DIRECT_MSG_ENDPOINT_ID << FFA_DIRECT_MSG_SOURCE_SHIFT) |
+		 spmd_spmc_id_get());
+	write_ctx_reg(gpregs, CTX_GPREG_X2, BIT(31) | target_func);
+	write_ctx_reg(gpregs, CTX_GPREG_X3, message);
+}
+
+
 /*******************************************************************************
  * This function takes an SPMC context pointer and performs a synchronous
  * SPMC entry.
@@ -543,8 +558,59 @@
 			(ctx->state == SPMC_STATE_RESET)) {
 			ret = FFA_ERROR_NOT_SUPPORTED;
 		} else if (!secure_origin) {
-			ret = MAKE_FFA_VERSION(spmc_attrs.major_version,
-					       spmc_attrs.minor_version);
+			gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx);
+			uint64_t rc;
+
+			if (spmc_attrs.major_version == 1 &&
+			    spmc_attrs.minor_version == 0) {
+				ret = MAKE_FFA_VERSION(spmc_attrs.major_version,
+						       spmc_attrs.minor_version);
+				SMC_RET8(handle, (uint32_t)ret,
+					 FFA_TARGET_INFO_MBZ,
+					 FFA_TARGET_INFO_MBZ,
+					 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+					 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+					 FFA_PARAM_MBZ);
+				break;
+			}
+			/* Save non-secure system registers context */
+			cm_el1_sysregs_context_save(NON_SECURE);
+#if SPMD_SPM_AT_SEL2
+			cm_el2_sysregs_context_save(NON_SECURE);
+#endif
+
+			/*
+			 * The incoming request has FFA_VERSION as X0 smc_fid
+			 * and requested version in x1. Prepare a direct request
+			 * from SPMD to SPMC with FFA_VERSION framework function
+			 * identifier in X2 and requested version in X3.
+			 */
+			spmd_build_spmc_message(gpregs,
+						SPMD_FWK_MSG_FFA_VERSION_REQ,
+						input_version);
+
+			rc = spmd_spm_core_sync_entry(ctx);
+
+			if ((rc != 0ULL) ||
+			    (SMC_GET_GP(gpregs, CTX_GPREG_X0) !=
+				FFA_MSG_SEND_DIRECT_RESP_SMC32) ||
+			    (SMC_GET_GP(gpregs, CTX_GPREG_X2) !=
+				(SPMD_FWK_MSG_BIT |
+				 SPMD_FWK_MSG_FFA_VERSION_RESP))) {
+				ERROR("Failed to forward FFA_VERSION\n");
+				ret = FFA_ERROR_NOT_SUPPORTED;
+			} else {
+				ret = SMC_GET_GP(gpregs, CTX_GPREG_X3);
+			}
+
+			/*
+			 * Return here after SPMC has handled FFA_VERSION.
+			 * The returned SPMC version is held in X3.
+			 * Forward this version in X0 to the non-secure caller.
+			 */
+			return spmd_smc_forward(ret, true, FFA_PARAM_MBZ,
+						FFA_PARAM_MBZ, FFA_PARAM_MBZ,
+						FFA_PARAM_MBZ, gpregs);
 		} else {
 			ret = MAKE_FFA_VERSION(FFA_VERSION_MAJOR,
 					       FFA_VERSION_MINOR);
diff --git a/services/std_svc/spmd/spmd_pm.c b/services/std_svc/spmd/spmd_pm.c
index 6ebafca..b719161 100644
--- a/services/std_svc/spmd/spmd_pm.c
+++ b/services/std_svc/spmd/spmd_pm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -20,21 +20,6 @@
 } g_spmd_pm;
 
 /*******************************************************************************
- * spmd_build_spmc_message
- *
- * Builds an SPMD to SPMC direct message request.
- ******************************************************************************/
-static void spmd_build_spmc_message(gp_regs_t *gpregs, unsigned long long message)
-{
-	write_ctx_reg(gpregs, CTX_GPREG_X0, FFA_MSG_SEND_DIRECT_REQ_SMC32);
-	write_ctx_reg(gpregs, CTX_GPREG_X1,
-		(SPMD_DIRECT_MSG_ENDPOINT_ID << FFA_DIRECT_MSG_SOURCE_SHIFT) |
-		spmd_spmc_id_get());
-	write_ctx_reg(gpregs, CTX_GPREG_X2, FFA_PARAM_MBZ);
-	write_ctx_reg(gpregs, CTX_GPREG_X3, message);
-}
-
-/*******************************************************************************
  * spmd_pm_secondary_ep_register
  ******************************************************************************/
 int spmd_pm_secondary_ep_register(uintptr_t entry_point)
@@ -137,7 +122,8 @@
 	assert(ctx->state != SPMC_STATE_OFF);
 
 	/* Build an SPMD to SPMC direct message request. */
-	spmd_build_spmc_message(get_gpregs_ctx(&ctx->cpu_ctx), PSCI_CPU_OFF);
+	spmd_build_spmc_message(get_gpregs_ctx(&ctx->cpu_ctx),
+				SPMD_FWK_MSG_PSCI, PSCI_CPU_OFF);
 
 	rc = spmd_spm_core_sync_entry(ctx);
 	if (rc != 0ULL) {
diff --git a/services/std_svc/spmd/spmd_private.h b/services/std_svc/spmd/spmd_private.h
index 1fe5065..4cd6a74 100644
--- a/services/std_svc/spmd/spmd_private.h
+++ b/services/std_svc/spmd/spmd_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -64,6 +64,16 @@
 
 #define SPMD_DIRECT_MSG_ENDPOINT_ID		U(FFA_ENDPOINT_ID_MAX - 1)
 
+/* Define SPMD target function IDs for framework messages to the SPMC */
+#define SPMD_FWK_MSG_BIT			BIT(31)
+#define SPMD_FWK_MSG_PSCI			U(0)
+#define SPMD_FWK_MSG_FFA_VERSION_REQ		U(0x8)
+#define SPMD_FWK_MSG_FFA_VERSION_RESP		U(0x9)
+
+/* Function to build SPMD to SPMC message */
+void spmd_build_spmc_message(gp_regs_t *gpregs, uint8_t target,
+			     unsigned long long message);
+
 /* Functions used to enter/exit SPMC synchronously */
 uint64_t spmd_spm_core_sync_entry(spmd_spm_core_context_t *ctx);
 __dead2 void spmd_spm_core_sync_exit(uint64_t rc);