Merge "fix: add support for 128-bit sysregs to EL3 crash handler" into integration
diff --git a/Makefile b/Makefile
index fae34c5..28ff849 100644
--- a/Makefile
+++ b/Makefile
@@ -1253,6 +1253,7 @@
 	ENABLE_MPMM_FCONF \
 	FEATURE_DETECTION \
 	TRNG_SUPPORT \
+	ENABLE_ERRATA_ALL \
 	ERRATA_ABI_SUPPORT \
 	ERRATA_NON_ARM_INTERCONNECT \
 	CONDITIONAL_CMO \
diff --git a/bl31/aarch64/ea_delegate.S b/bl31/aarch64/ea_delegate.S
index 28d2187..91ea75d 100644
--- a/bl31/aarch64/ea_delegate.S
+++ b/bl31/aarch64/ea_delegate.S
@@ -158,6 +158,8 @@
 	b.eq	1f
 	ret
 1:
+	ldr	x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
+	str	xzr, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
 	exception_return
 endfunc handle_pending_async_ea
 
diff --git a/docs/design_documents/context_mgmt_rework.rst b/docs/design_documents/context_mgmt_rework.rst
deleted file mode 100644
index b086e3c..0000000
--- a/docs/design_documents/context_mgmt_rework.rst
+++ /dev/null
@@ -1,197 +0,0 @@
-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: Implementation is ongoing. Refer to :ref:`Context Management Library` for more details.
-
-.. 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-2024, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/design_documents/index.rst b/docs/design_documents/index.rst
index ac982e0..f1d8386 100644
--- a/docs/design_documents/index.rst
+++ b/docs/design_documents/index.rst
@@ -6,7 +6,6 @@
    :caption: Contents
 
    cmake_framework
-   context_mgmt_rework
    measured_boot_poc
    drtm_poc
    rse
@@ -15,4 +14,4 @@
 
 --------------
 
-*Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2020-2025, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 58321e7..5b83448 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -587,6 +587,11 @@
    platform hook needs to be implemented. The value is passed as the last
    component of the option ``-fstack-protector-$ENABLE_STACK_PROTECTOR``.
 
+- ``ENABLE_ERRATA_ALL``: This option is used only for testing purposes, Boolean
+   option to enable the workarounds for all errata that TF-A implements. Normally
+   they should be explicitly enabled depending on each platform's needs. Not
+   recommended for release builds. This option is default set to 0.
+
 -  ``ENCRYPT_BL31``: Binary flag to enable encryption of BL31 firmware. This
    flag depends on ``DECRYPTION_SUPPORT`` build flag.
 
@@ -1474,7 +1479,7 @@
 
 --------------
 
-*Copyright (c) 2019-2024, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2025, Arm Limited. All rights reserved.*
 
 .. _DEN0115: https://developer.arm.com/docs/den0115/latest
 .. _PSA FW update specification: https://developer.arm.com/documentation/den0118/latest/
diff --git a/docs/getting_started/prerequisites.rst b/docs/getting_started/prerequisites.rst
index 32c2b39..768e4fe 100644
--- a/docs/getting_started/prerequisites.rst
+++ b/docs/getting_started/prerequisites.rst
@@ -26,7 +26,7 @@
 ======================== =====================
         Program          Min supported version
 ======================== =====================
-Arm Compiler             6.18
+Arm Compiler             6.23
 Arm GNU Compiler         13.3
 Clang/LLVM               18.1.8
 Device Tree Compiler     1.6.1
@@ -184,7 +184,7 @@
 
 --------------
 
-*Copyright (c) 2021-2024, Arm Limited. All rights reserved.*
+*Copyright (c) 2021-2025, Arm Limited. All rights reserved.*
 
 .. _Arm Developer website: https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/downloads
 .. _Gerrit Code Review: https://www.gerritcodereview.com/
diff --git a/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h b/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h
index e54d581..665930b 100644
--- a/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h
+++ b/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: BSD-3-Clause
 /*
- * Copyright 2020-2021, 2023-2024 NXP
+ * Copyright 2020-2021, 2023-2025 NXP
  */
 #ifndef S32CC_CLK_REGS_H
 #define S32CC_CLK_REGS_H
@@ -48,6 +48,8 @@
 #define PLLDIG_PLLDV_RDIV_MASK		GENMASK_32(14U, PLLDIG_PLLDV_RDIV_OFFSET)
 #define PLLDIG_PLLDV_RDIV_SET(VAL)	(PLLDIG_PLLDV_RDIV_MASK & \
 					((VAL) << PLLDIG_PLLDV_RDIV_OFFSET))
+#define PLLDIG_PLLDV_RDIV(VAL)		(((VAL) & PLLDIG_PLLDV_RDIV_MASK) >> \
+					 PLLDIG_PLLDV_RDIV_OFFSET)
 #define PLLDIG_PLLDV_MFI_MASK		GENMASK_32(7U, 0U)
 #define PLLDIG_PLLDV_MFI(DIV)		(PLLDIG_PLLDV_MFI_MASK & (DIV))
 
diff --git a/drivers/nxp/clk/s32cc/s32cc_clk_drv.c b/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
index 235b988..c235e04 100644
--- a/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
+++ b/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2024 NXP
+ * Copyright 2024-2025 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -33,6 +33,14 @@
 	uintptr_t rdc;
 };
 
+static int set_module_rate(const struct s32cc_clk_obj *module,
+			   unsigned long rate, unsigned long *orate,
+			   unsigned int *depth);
+static int get_module_rate(const struct s32cc_clk_obj *module,
+			   const struct s32cc_clk_drv *drv,
+			   unsigned long *rate,
+			   unsigned int depth);
+
 static int update_stack_depth(unsigned int *depth)
 {
 	if (*depth == 0U) {
@@ -273,6 +281,70 @@
 	mmio_setbits_32(PLLDIG_PLLODIV(pll_addr, div_index), PLLDIG_PLLODIV_DE);
 }
 
+static void enable_odivs(uintptr_t pll_addr, uint32_t ndivs, uint32_t mask)
+{
+	uint32_t i;
+
+	for (i = 0; i < ndivs; i++) {
+		if ((mask & BIT_32(i)) != 0U) {
+			enable_odiv(pll_addr, i);
+		}
+	}
+}
+
+static int adjust_odiv_settings(const struct s32cc_pll *pll, uintptr_t pll_addr,
+				uint32_t odivs_mask, unsigned long old_vco)
+{
+	uint64_t old_odiv_freq, odiv_freq;
+	uint32_t i, pllodiv, pdiv;
+	int ret = 0;
+
+	if (old_vco == 0UL) {
+		return 0;
+	}
+
+	for (i = 0; i < pll->ndividers; i++) {
+		if ((odivs_mask & BIT_32(i)) == 0U) {
+			continue;
+		}
+
+		pllodiv = mmio_read_32(PLLDIG_PLLODIV(pll_addr, i));
+
+		pdiv = PLLDIG_PLLODIV_DIV(pllodiv);
+
+		old_odiv_freq = ((old_vco * FP_PRECISION) / (pdiv + 1U)) / FP_PRECISION;
+		pdiv = (uint32_t)(pll->vco_freq * FP_PRECISION / old_odiv_freq / FP_PRECISION);
+
+		odiv_freq = pll->vco_freq * FP_PRECISION / pdiv / FP_PRECISION;
+
+		if (old_odiv_freq != odiv_freq) {
+			ERROR("Failed to adjust ODIV %" PRIu32 " to match previous frequency\n",
+			      i);
+		}
+
+		pllodiv = PLLDIG_PLLODIV_DIV_SET(pdiv - 1U);
+		mmio_write_32(PLLDIG_PLLODIV(pll_addr, i), pllodiv);
+	}
+
+	return ret;
+}
+
+static uint32_t get_enabled_odivs(uintptr_t pll_addr, uint32_t ndivs)
+{
+	uint32_t mask = 0;
+	uint32_t pllodiv;
+	uint32_t i;
+
+	for (i = 0; i < ndivs; i++) {
+		pllodiv = mmio_read_32(PLLDIG_PLLODIV(pll_addr, i));
+		if ((pllodiv & PLLDIG_PLLODIV_DE) != 0U) {
+			mask |= BIT_32(i);
+		}
+	}
+
+	return mask;
+}
+
 static void disable_odivs(uintptr_t pll_addr, uint32_t ndivs)
 {
 	uint32_t i;
@@ -297,18 +369,54 @@
 	mmio_write_32(PLLDIG_PLLCR(pll_addr), PLLDIG_PLLCR_PLLPD);
 }
 
+static bool is_pll_enabled(uintptr_t pll_base)
+{
+	uint32_t pllcr, pllsr;
+
+	pllcr = mmio_read_32(PLLDIG_PLLCR(pll_base));
+	pllsr = mmio_read_32(PLLDIG_PLLSR(pll_base));
+
+	/* Enabled and locked PLL */
+	if ((pllcr & PLLDIG_PLLCR_PLLPD) != 0U) {
+		return false;
+	}
+
+	if ((pllsr & PLLDIG_PLLSR_LOCK) == 0U) {
+		return false;
+	}
+
+	return true;
+}
+
 static int program_pll(const struct s32cc_pll *pll, uintptr_t pll_addr,
 		       const struct s32cc_clk_drv *drv, uint32_t sclk_id,
-		       unsigned long sclk_freq)
+		       unsigned long sclk_freq, unsigned int depth)
 {
 	uint32_t rdiv = 1, mfi, mfn;
+	unsigned long old_vco = 0UL;
+	unsigned int ldepth = depth;
+	uint32_t odivs_mask;
 	int ret;
 
+	ret = update_stack_depth(&ldepth);
+	if (ret != 0) {
+		return ret;
+	}
+
 	ret = get_pll_mfi_mfn(pll->vco_freq, sclk_freq, &mfi, &mfn);
 	if (ret != 0) {
 		return -EINVAL;
 	}
 
+	odivs_mask = get_enabled_odivs(pll_addr, pll->ndividers);
+
+	if (is_pll_enabled(pll_addr)) {
+		ret = get_module_rate(&pll->desc, drv, &old_vco, ldepth);
+		if (ret != 0) {
+			return ret;
+		}
+	}
+
 	/* Disable ODIVs*/
 	disable_odivs(pll_addr, pll->ndividers);
 
@@ -326,8 +434,16 @@
 	mmio_write_32(PLLDIG_PLLFD(pll_addr),
 		      PLLDIG_PLLFD_MFN_SET(mfn) | PLLDIG_PLLFD_SMDEN);
 
+	ret = adjust_odiv_settings(pll, pll_addr, odivs_mask, old_vco);
+	if (ret != 0) {
+		return ret;
+	}
+
 	enable_pll_hw(pll_addr);
 
+	/* Enable out dividers */
+	enable_odivs(pll_addr, pll->ndividers, odivs_mask);
+
 	return ret;
 }
 
@@ -336,10 +452,11 @@
 		      unsigned int depth)
 {
 	const struct s32cc_pll *pll = s32cc_obj2pll(module);
+	unsigned int clk_src, ldepth = depth;
+	unsigned long sclk_freq, pll_vco;
 	const struct s32cc_clkmux *mux;
 	uintptr_t pll_addr = UL(0x0);
-	unsigned int ldepth = depth;
-	unsigned long sclk_freq;
+	bool pll_enabled;
 	uint32_t sclk_id;
 	int ret;
 
@@ -379,7 +496,20 @@
 		return -EINVAL;
 	};
 
+	ret = get_module_rate(&pll->desc, drv, &pll_vco, depth);
+	if (ret != 0) {
+		return ret;
+	}
+
+	pll_enabled = is_pll_enabled(pll_addr);
+	clk_src = mmio_read_32(PLLDIG_PLLCLKMUX(pll_addr));
+
+	if ((clk_src == sclk_id) && pll_enabled &&
+	    (pll_vco == pll->vco_freq)) {
+		return 0;
+	}
+
-	return program_pll(pll, pll_addr, drv, sclk_id, sclk_freq);
+	return program_pll(pll, pll_addr, drv, sclk_id, sclk_freq, ldepth);
 }
 
 static inline struct s32cc_pll *get_div_pll(const struct s32cc_pll_out_div *pdiv)
@@ -441,6 +571,7 @@
 	uintptr_t pll_addr = 0x0ULL;
 	unsigned int ldepth = depth;
 	const struct s32cc_pll *pll;
+	unsigned long pll_vco;
 	uint32_t dc;
 	int ret;
 
@@ -461,7 +592,14 @@
 		return -EINVAL;
 	}
 
-	dc = (uint32_t)(pll->vco_freq / pdiv->freq);
+	ret = get_module_rate(&pll->desc, drv, &pll_vco, ldepth);
+	if (ret != 0) {
+		ERROR("Failed to enable the PLL due to unknown rate for 0x%" PRIxPTR "\n",
+		      pll_addr);
+		return ret;
+	}
+
+	dc = (uint32_t)(pll_vco / pdiv->freq);
 
 	config_pll_out_div(pll_addr, pdiv->index, dc);
 
@@ -651,34 +789,39 @@
 	return 0;
 }
 
-static struct s32cc_dfs *get_div_dfs(const struct s32cc_dfs_div *dfs_div)
+static int get_dfs_freq(const struct s32cc_clk_obj *module,
+			const struct s32cc_clk_drv *drv,
+			unsigned long *rate, unsigned int depth)
 {
-	const struct s32cc_clk_obj *parent = dfs_div->parent;
+	const struct s32cc_dfs *dfs = s32cc_obj2dfs(module);
+	unsigned int ldepth = depth;
+	uintptr_t dfs_addr;
+	int ret;
 
-	if (parent->type != s32cc_dfs_t) {
-		ERROR("DFS DIV doesn't have a DFS as parent\n");
-		return NULL;
+	ret = update_stack_depth(&ldepth);
+	if (ret != 0) {
+		return ret;
 	}
 
-	return s32cc_obj2dfs(parent);
+	ret = get_base_addr(dfs->instance, drv, &dfs_addr);
+	if (ret != 0) {
+		ERROR("Failed to detect the DFS instance\n");
+		return ret;
+	}
+
+	return get_module_rate(dfs->parent, drv, rate, ldepth);
 }
 
-static struct s32cc_pll *dfsdiv2pll(const struct s32cc_dfs_div *dfs_div)
+static struct s32cc_dfs *get_div_dfs(const struct s32cc_dfs_div *dfs_div)
 {
-	const struct s32cc_clk_obj *parent;
-	const struct s32cc_dfs *dfs;
-
-	dfs = get_div_dfs(dfs_div);
-	if (dfs == NULL) {
-		return NULL;
-	}
+	const struct s32cc_clk_obj *parent = dfs_div->parent;
 
-	parent = dfs->parent;
-	if (parent->type != s32cc_pll_t) {
+	if (parent->type != s32cc_dfs_t) {
+		ERROR("DFS DIV doesn't have a DFS as parent\n");
 		return NULL;
 	}
 
-	return s32cc_obj2pll(parent);
+	return s32cc_obj2dfs(parent);
 }
 
 static int get_dfs_mfi_mfn(unsigned long dfs_freq, const struct s32cc_dfs_div *dfs_div,
@@ -808,9 +951,9 @@
 {
 	const struct s32cc_dfs_div *dfs_div = s32cc_obj2dfsdiv(module);
 	unsigned int ldepth = depth;
-	const struct s32cc_pll *pll;
 	const struct s32cc_dfs *dfs;
 	uintptr_t dfs_addr = 0UL;
+	unsigned long dfs_freq;
 	uint32_t mfi, mfn;
 	int ret = 0;
 
@@ -824,18 +967,17 @@
 		return -EINVAL;
 	}
 
-	pll = dfsdiv2pll(dfs_div);
-	if (pll == NULL) {
-		ERROR("Failed to identify DFS divider's parent\n");
-		return -EINVAL;
-	}
-
 	ret = get_base_addr(dfs->instance, drv, &dfs_addr);
 	if ((ret != 0) || (dfs_addr == 0UL)) {
 		return -EINVAL;
 	}
 
+	ret = get_module_rate(&dfs->desc, drv, &dfs_freq, depth);
+	if (ret != 0) {
+		return ret;
+	}
+
-	ret = get_dfs_mfi_mfn(pll->vco_freq, dfs_div, &mfi, &mfn);
+	ret = get_dfs_mfi_mfn(dfs_freq, dfs_div, &mfi, &mfn);
 	if (ret != 0) {
 		return -EINVAL;
 	}
@@ -927,6 +1069,22 @@
 	return link->parent;
 }
 
+static int get_part_block_link_freq(const struct s32cc_clk_obj *module,
+				    const struct s32cc_clk_drv *drv,
+				    unsigned long *rate, unsigned int depth)
+{
+	const struct s32cc_part_block_link *block = s32cc_obj2partblocklink(module);
+	unsigned int ldepth = depth;
+	int ret;
+
+	ret = update_stack_depth(&ldepth);
+	if (ret != 0) {
+		return ret;
+	}
+
+	return get_module_rate(block->parent, drv, rate, ldepth);
+}
+
 static int no_enable(struct s32cc_clk_obj *module,
 		     const struct s32cc_clk_drv *drv,
 		     unsigned int depth)
@@ -1059,15 +1217,6 @@
 	return false;
 }
 
-static unsigned long s32cc_clk_get_rate(unsigned long id)
-{
-	return 0;
-}
-
-static int set_module_rate(const struct s32cc_clk_obj *module,
-			   unsigned long rate, unsigned long *orate,
-			   unsigned int *depth);
-
 static int set_osc_freq(const struct s32cc_clk_obj *module, unsigned long rate,
 			unsigned long *orate, unsigned int *depth)
 {
@@ -1091,6 +1240,29 @@
 	return 0;
 }
 
+static int get_osc_freq(const struct s32cc_clk_obj *module,
+			const struct s32cc_clk_drv *drv,
+			unsigned long *rate, unsigned int depth)
+{
+	const struct s32cc_osc *osc = s32cc_obj2osc(module);
+	unsigned int ldepth = depth;
+	int ret;
+
+	ret = update_stack_depth(&ldepth);
+	if (ret != 0) {
+		return ret;
+	}
+
+	if (osc->freq == 0UL) {
+		ERROR("Uninitialized oscillator\n");
+		return -EINVAL;
+	}
+
+	*rate = osc->freq;
+
+	return 0;
+}
+
 static int set_clk_freq(const struct s32cc_clk_obj *module, unsigned long rate,
 			unsigned long *orate, unsigned int *depth)
 {
@@ -1120,6 +1292,36 @@
 	return -EINVAL;
 }
 
+static int get_clk_freq(const struct s32cc_clk_obj *module,
+			const struct s32cc_clk_drv *drv, unsigned long *rate,
+			unsigned int depth)
+{
+	const struct s32cc_clk *clk = s32cc_obj2clk(module);
+	unsigned int ldepth = depth;
+	int ret;
+
+	ret = update_stack_depth(&ldepth);
+	if (ret != 0) {
+		return ret;
+	}
+
+	if (clk == NULL) {
+		ERROR("Invalid clock\n");
+		return -EINVAL;
+	}
+
+	if (clk->module != NULL) {
+		return get_module_rate(clk->module, drv, rate, ldepth);
+	}
+
+	if (clk->pclock == NULL) {
+		ERROR("Invalid clock parent\n");
+		return -EINVAL;
+	}
+
+	return get_clk_freq(&clk->pclock->desc, drv, rate, ldepth);
+}
+
 static int set_pll_freq(const struct s32cc_clk_obj *module, unsigned long rate,
 			unsigned long *orate, unsigned int *depth)
 {
@@ -1142,6 +1344,80 @@
 	return 0;
 }
 
+static int get_pll_freq(const struct s32cc_clk_obj *module,
+			const struct s32cc_clk_drv *drv,
+			unsigned long *rate, unsigned int depth)
+{
+	const struct s32cc_pll *pll = s32cc_obj2pll(module);
+	const struct s32cc_clk *source;
+	uint32_t mfi, mfn, rdiv, plldv;
+	unsigned long prate, clk_src;
+	unsigned int ldepth = depth;
+	uintptr_t pll_addr = 0UL;
+	uint64_t t1, t2;
+	int ret;
+
+	ret = update_stack_depth(&ldepth);
+	if (ret != 0) {
+		return ret;
+	}
+
+	ret = get_base_addr(pll->instance, drv, &pll_addr);
+	if (ret != 0) {
+		ERROR("Failed to detect PLL instance\n");
+		return ret;
+	}
+
+	/* Disabled PLL */
+	if (!is_pll_enabled(pll_addr)) {
+		*rate = pll->vco_freq;
+		return 0;
+	}
+
+	clk_src = mmio_read_32(PLLDIG_PLLCLKMUX(pll_addr));
+	switch (clk_src) {
+	case 0:
+		clk_src = S32CC_CLK_FIRC;
+		break;
+	case 1:
+		clk_src = S32CC_CLK_FXOSC;
+		break;
+	default:
+		ERROR("Failed to identify PLL source id %" PRIu64 "\n", clk_src);
+		return -EINVAL;
+	};
+
+	source = s32cc_get_arch_clk(clk_src);
+	if (source == NULL) {
+		ERROR("Failed to get PLL source clock\n");
+		return -EINVAL;
+	}
+
+	ret = get_module_rate(&source->desc, drv, &prate, ldepth);
+	if (ret != 0) {
+		ERROR("Failed to get PLL's parent frequency\n");
+		return ret;
+	}
+
+	plldv = mmio_read_32(PLLDIG_PLLDV(pll_addr));
+	mfi = PLLDIG_PLLDV_MFI(plldv);
+	rdiv = PLLDIG_PLLDV_RDIV(plldv);
+	if (rdiv == 0U) {
+		rdiv = 1;
+	}
+
+	/* Frac-N mode */
+	mfn = PLLDIG_PLLFD_MFN_SET(mmio_read_32(PLLDIG_PLLFD(pll_addr)));
+
+	/* PLL VCO frequency in Fractional mode when PLLDV[RDIV] is not 0 */
+	t1 = prate / rdiv;
+	t2 = (mfi * FP_PRECISION) + (mfn * FP_PRECISION / 18432U);
+
+	*rate = t1 * t2 / FP_PRECISION;
+
+	return 0;
+}
+
 static int set_pll_div_freq(const struct s32cc_clk_obj *module, unsigned long rate,
 			    unsigned long *orate, unsigned int *depth)
 {
@@ -1190,6 +1466,57 @@
 	return 0;
 }
 
+static int get_pll_div_freq(const struct s32cc_clk_obj *module,
+			    const struct s32cc_clk_drv *drv,
+			    unsigned long *rate, unsigned int depth)
+{
+	const struct s32cc_pll_out_div *pdiv = s32cc_obj2plldiv(module);
+	const struct s32cc_pll *pll;
+	unsigned int ldepth = depth;
+	uintptr_t pll_addr = 0UL;
+	unsigned long pfreq;
+	uint32_t pllodiv;
+	uint32_t dc;
+	int ret;
+
+	ret = update_stack_depth(&ldepth);
+	if (ret != 0) {
+		return ret;
+	}
+
+	pll = get_div_pll(pdiv);
+	if (pll == NULL) {
+		ERROR("The parent of the PLL DIV is invalid\n");
+		return -EINVAL;
+	}
+
+	ret = get_base_addr(pll->instance, drv, &pll_addr);
+	if (ret != 0) {
+		ERROR("Failed to detect PLL instance\n");
+		return -EINVAL;
+	}
+
+	ret = get_module_rate(pdiv->parent, drv, &pfreq, ldepth);
+	if (ret != 0) {
+		ERROR("Failed to get the frequency of PLL %" PRIxPTR "\n",
+		      pll_addr);
+		return ret;
+	}
+
+	pllodiv = mmio_read_32(PLLDIG_PLLODIV(pll_addr, pdiv->index));
+
+	/* Disabled module */
+	if ((pllodiv & PLLDIG_PLLODIV_DE) == 0U) {
+		*rate = pdiv->freq;
+		return 0;
+	}
+
+	dc = PLLDIG_PLLODIV_DIV(pllodiv);
+	*rate = (pfreq * FP_PRECISION) / (dc + 1U) / FP_PRECISION;
+
+	return 0;
+}
+
 static int set_fixed_div_freq(const struct s32cc_clk_obj *module, unsigned long rate,
 			      unsigned long *orate, unsigned int *depth)
 {
@@ -1214,6 +1541,23 @@
 	return ret;
 }
 
+static int get_fixed_div_freq(const struct s32cc_clk_obj *module,
+			      const struct s32cc_clk_drv *drv,
+			      unsigned long *rate, unsigned int depth)
+{
+	const struct s32cc_fixed_div *fdiv = s32cc_obj2fixeddiv(module);
+	unsigned long pfreq;
+	int ret;
+
+	ret = get_module_rate(fdiv->parent, drv, &pfreq, depth);
+	if (ret != 0) {
+		return ret;
+	}
+
+	*rate = (pfreq * FP_PRECISION / fdiv->rate_div) / FP_PRECISION;
+	return 0;
+}
+
 static int set_mux_freq(const struct s32cc_clk_obj *module, unsigned long rate,
 			unsigned long *orate, unsigned int *depth)
 {
@@ -1235,6 +1579,29 @@
 	return set_module_rate(&clk->desc, rate, orate, depth);
 }
 
+static int get_mux_freq(const struct s32cc_clk_obj *module,
+			const struct s32cc_clk_drv *drv,
+			unsigned long *rate, unsigned int depth)
+{
+	const struct s32cc_clkmux *mux = s32cc_obj2clkmux(module);
+	const struct s32cc_clk *clk = s32cc_get_arch_clk(mux->source_id);
+	unsigned int ldepth = depth;
+	int ret;
+
+	ret = update_stack_depth(&ldepth);
+	if (ret != 0) {
+		return ret;
+	}
+
+	if (clk == NULL) {
+		ERROR("Mux (id:%" PRIu8 ") without a valid source (%lu)\n",
+		      mux->index, mux->source_id);
+		return -EINVAL;
+	}
+
+	return get_clk_freq(&clk->desc, drv, rate, ldepth);
+}
+
 static int set_dfs_div_freq(const struct s32cc_clk_obj *module, unsigned long rate,
 			    unsigned long *orate, unsigned int *depth)
 {
@@ -1271,6 +1638,71 @@
 	return ret;
 }
 
+static unsigned long compute_dfs_div_freq(unsigned long pfreq, uint32_t mfi, uint32_t mfn)
+{
+	unsigned long freq;
+
+	/**
+	 * Formula for input and output clocks of each port divider.
+	 * See 'Digital Frequency Synthesizer' chapter from Reference Manual.
+	 *
+	 * freq = pfreq / (2 * (mfi + mfn / 36.0));
+	 */
+	freq = (mfi * FP_PRECISION) + (mfn * FP_PRECISION / 36UL);
+	freq *= 2UL;
+	freq = pfreq * FP_PRECISION / freq;
+
+	return freq;
+}
+
+static int get_dfs_div_freq(const struct s32cc_clk_obj *module,
+			    const struct s32cc_clk_drv *drv,
+			    unsigned long *rate, unsigned int depth)
+{
+	const struct s32cc_dfs_div *dfs_div = s32cc_obj2dfsdiv(module);
+	unsigned int ldepth = depth;
+	const struct s32cc_dfs *dfs;
+	uint32_t dvport, mfi, mfn;
+	uintptr_t dfs_addr = 0UL;
+	unsigned long pfreq;
+	int ret;
+
+	ret = update_stack_depth(&ldepth);
+	if (ret != 0) {
+		return ret;
+	}
+
+	dfs = get_div_dfs(dfs_div);
+	if (dfs == NULL) {
+		return -EINVAL;
+	}
+
+	ret = get_module_rate(dfs_div->parent, drv, &pfreq, ldepth);
+	if (ret != 0) {
+		return ret;
+	}
+
+	ret = get_base_addr(dfs->instance, drv, &dfs_addr);
+	if (ret != 0) {
+		ERROR("Failed to detect the DFS instance\n");
+		return ret;
+	}
+
+	dvport = mmio_read_32(DFS_DVPORTn(dfs_addr, dfs_div->index));
+
+	mfi = DFS_DVPORTn_MFI(dvport);
+	mfn = DFS_DVPORTn_MFN(dvport);
+
+	/* Disabled port */
+	if ((mfi == 0U) && (mfn == 0U)) {
+		*rate = dfs_div->freq;
+		return 0;
+	}
+
+	*rate = compute_dfs_div_freq(pfreq, mfi, mfn);
+	return 0;
+}
+
 static int set_module_rate(const struct s32cc_clk_obj *module,
 			   unsigned long rate, unsigned long *orate,
 			   unsigned int *depth)
@@ -1319,6 +1751,64 @@
 	return ret;
 }
 
+static int get_module_rate(const struct s32cc_clk_obj *module,
+			   const struct s32cc_clk_drv *drv,
+			   unsigned long *rate,
+			   unsigned int depth)
+{
+	unsigned int ldepth = depth;
+	int ret = 0;
+
+	ret = update_stack_depth(&ldepth);
+	if (ret != 0) {
+		return ret;
+	}
+
+	switch (module->type) {
+	case s32cc_osc_t:
+		ret = get_osc_freq(module, drv, rate, ldepth);
+		break;
+	case s32cc_clk_t:
+		ret = get_clk_freq(module, drv, rate, ldepth);
+		break;
+	case s32cc_pll_t:
+		ret = get_pll_freq(module, drv, rate, ldepth);
+		break;
+	case s32cc_dfs_t:
+		ret = get_dfs_freq(module, drv, rate, ldepth);
+		break;
+	case s32cc_dfs_div_t:
+		ret = get_dfs_div_freq(module, drv, rate, ldepth);
+		break;
+	case s32cc_fixed_div_t:
+		ret = get_fixed_div_freq(module, drv, rate, ldepth);
+		break;
+	case s32cc_pll_out_div_t:
+		ret = get_pll_div_freq(module, drv, rate, ldepth);
+		break;
+	case s32cc_clkmux_t:
+		ret = get_mux_freq(module, drv, rate, ldepth);
+		break;
+	case s32cc_shared_clkmux_t:
+		ret = get_mux_freq(module, drv, rate, ldepth);
+		break;
+	case s32cc_part_t:
+		ERROR("s32cc_part_t cannot be used to get rate\n");
+		break;
+	case s32cc_part_block_t:
+		ERROR("s32cc_part_block_t cannot be used to get rate\n");
+		break;
+	case s32cc_part_block_link_t:
+		ret = get_part_block_link_freq(module, drv, rate, ldepth);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
 static int s32cc_clk_set_rate(unsigned long id, unsigned long rate,
 			      unsigned long *orate)
 {
@@ -1340,6 +1830,29 @@
 	return ret;
 }
 
+static unsigned long s32cc_clk_get_rate(unsigned long id)
+{
+	const struct s32cc_clk_drv *drv = get_drv();
+	unsigned int depth = MAX_STACK_DEPTH;
+	const struct s32cc_clk *clk;
+	unsigned long rate = 0UL;
+	int ret;
+
+	clk = s32cc_get_arch_clk(id);
+	if (clk == NULL) {
+		return 0;
+	}
+
+	ret = get_module_rate(&clk->desc, drv, &rate, depth);
+	if (ret != 0) {
+		ERROR("Failed to get frequency (%lu MHz) for clock %lu\n",
+		      rate, id);
+		return 0;
+	}
+
+	return rate;
+}
+
 static struct s32cc_clk_obj *get_no_parent(const struct s32cc_clk_obj *module)
 {
 	return NULL;
diff --git a/drivers/nxp/clk/s32cc/s32cc_clk_modules.c b/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
index 71055ab..f7af465 100644
--- a/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
+++ b/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020-2024 NXP
+ * Copyright 2020-2025 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -20,7 +20,7 @@
 	S32CC_MODULE_CLK(fxosc);
 
 static struct s32cc_osc firc =
-	S32CC_OSC_INIT(S32CC_FIRC);
+	S32CC_OSC_INIT_FREQ(S32CC_FIRC, 48 * MHZ);
 static struct s32cc_clk firc_clk =
 	S32CC_MODULE_CLK(firc);
 
diff --git a/fdts/rdv3-defs.dtsi b/fdts/rdv3-defs.dtsi
new file mode 100644
index 0000000..0ec4ccc
--- /dev/null
+++ b/fdts/rdv3-defs.dtsi
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef	RD_V3_DEFS_DTSI
+#define	RD_V3_DEFS_DTSI
+
+#define CONCAT(x, y)	x##y
+#define CONC(x, y)	CONCAT(x, y)
+
+#define	ADR(n)	\
+	CPU##n:cpu@n##0000 {
+
+#define	PRE			\
+	device_type = "cpu";	\
+	compatible = "arm,armv8";
+
+#define	CPU_0		\
+	CPU0:cpu@0 {	\
+	PRE		\
+	reg = <0x0 0x0>;\
+	};
+
+#define POST };
+
+/*
+ * n - CPU number
+ */
+#define	CPU(n)	\
+	ADR(n)	\
+	PRE		\
+	reg = <0x0 CONC(0x, CONC(n, 0000))>;	\
+	POST
+
+#endif	/* RD_V3_DEFS_DTSI */
diff --git a/fdts/tc4.dts b/fdts/tc4.dts
index df9a7e9..816c622 100644
--- a/fdts/tc4.dts
+++ b/fdts/tc4.dts
@@ -61,6 +61,14 @@
 #include "tc3-4-base.dtsi"
 
 / {
+	spe-pmu-mid {
+		status = "okay";
+	};
+
+	spe-pmu-big {
+		status = "okay";
+	};
+
 	smmu_700: iommu@3f000000 {
 		status = "okay";
 	};
diff --git a/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h b/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h
index 4837f79..c91f3b6 100644
--- a/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h
+++ b/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause */
 /*
- * Copyright 2020-2024 NXP
+ * Copyright 2020-2025 NXP
  */
 #ifndef S32CC_CLK_MODULES_H
 #define S32CC_CLK_MODULES_H
@@ -52,14 +52,18 @@
 	void *base;
 };
 
-#define S32CC_OSC_INIT(SOURCE)       \
-{                                    \
-	.desc = {                    \
-		.type = s32cc_osc_t, \
-	},                           \
-	.source = (SOURCE),          \
+#define S32CC_OSC_INIT_FREQ(SOURCE, FREQ) \
+{                                         \
+	.desc = {                         \
+		.type = s32cc_osc_t,      \
+	},                                \
+	.source = (SOURCE),               \
+	.freq = (FREQ),                   \
 }
 
+#define S32CC_OSC_INIT(SOURCE) \
+	S32CC_OSC_INIT_FREQ(SOURCE, 0)
+
 struct s32cc_clkmux {
 	struct s32cc_clk_obj desc;
 	enum s32cc_clk_source module;
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index ec5f90b..3ce6a91 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -753,6 +753,21 @@
 # endif /* defined(SPD_none) && !SPM_MM || !SPMC_AT_EL3 */
 #endif /* defined(__aarch64__) && !JUNO_AARCH32_EL3_RUNTIME */
 
+#if RESET_TO_BL31 && defined(SPD_spmd) && defined(PLAT_ARM_SPMC_MANIFEST_BASE)
+#define ARM_SPMC_MANIFEST_BASE  PLAT_ARM_SPMC_MANIFEST_BASE
+#else
+
+/*
+ * SPM expects SPM Core manifest base address in x0, which in !RESET_TO_BL31
+ * case loaded after base of non shared SRAM(after 4KB offset of SRAM). But in
+ * RESET_TO_BL31 case all non shared SRAM is allocated to BL31, so to avoid
+ * overwriting of manifest keep it in the last page.
+ */
+#define ARM_SPMC_MANIFEST_BASE		(ARM_TRUSTED_SRAM_BASE +	    \
+					 PLAT_ARM_TRUSTED_SRAM_SIZE -\
+					 PAGE_SIZE)
+#endif
+
 /*******************************************************************************
  * FWU Images: NS_BL1U, BL2U & NS_BL2U defines.
  ******************************************************************************/
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index fb904e2..0db7e94 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -1081,7 +1081,11 @@
 endif
 
 # process all flags
+ifeq (${ENABLE_ERRATA_ALL},1)
+$(eval $(call default_ones, $(CPU_FLAG_LIST)))
+else
 $(eval $(call default_zeros, $(CPU_FLAG_LIST)))
+endif
 $(eval $(call add_defines, $(CPU_FLAG_LIST)))
 $(eval $(call assert_booleans, $(CPU_FLAG_LIST)))
 
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 4985c0c..b1cfda2 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016-2024, Arm Limited. All rights reserved.
+# Copyright (c) 2016-2025, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -106,6 +106,10 @@
 # Flag to enable exception handling in EL3
 EL3_EXCEPTION_HANDLING		:= 0
 
+# Flag to include all errata for all CPUs TF-A implements workarounds for
+# Its supposed to be used only for testing.
+ENABLE_ERRATA_ALL		:= 0
+
 # By default BL31 encryption disabled
 ENCRYPT_BL31			:= 0
 
diff --git a/plat/amd/versal2/aarch64/common.c b/plat/amd/versal2/aarch64/common.c
index c78d711..8d9e05c 100644
--- a/plat/amd/versal2/aarch64/common.c
+++ b/plat/amd/versal2/aarch64/common.c
@@ -18,7 +18,7 @@
 #include <plat_ipi.h>
 #include <plat_private.h>
 
-uint32_t platform_id, platform_version;
+uint32_t platform_id, platform_version, rtlversion, psversion, pmcversion;
 
 /*
  * Table of regions to map using the MMU.
@@ -77,6 +77,9 @@
 	version_type = mmio_read_32(PMC_TAP_VERSION);
 	platform_id = FIELD_GET((uint32_t)PLATFORM_MASK, version_type);
 	platform_version = FIELD_GET((uint32_t)PLATFORM_VERSION_MASK, version_type);
+	rtlversion = FIELD_GET((uint32_t)RTL_VERSION, version_type);
+	psversion = FIELD_GET((uint32_t)PS_VERSION, version_type);
+	pmcversion = FIELD_GET((uint32_t)PMC_VERSION, version_type);
 
 	if (platform_id == QEMU_COSIM) {
 		platform_id = QEMU;
diff --git a/plat/amd/versal2/bl31_setup.c b/plat/amd/versal2/bl31_setup.c
index 05e4c96..1914830 100644
--- a/plat/amd/versal2/bl31_setup.c
+++ b/plat/amd/versal2/bl31_setup.c
@@ -132,8 +132,12 @@
 
 	setup_console();
 
-	NOTICE("TF-A running on %s %d.%d\n", board_name_decode(),
-	       platform_version / 10U, platform_version % 10U);
+	NOTICE("TF-A running on %s v%d.%d, RTL v%d.%d, PS v%d.%d, PMC v%d.%d\n",
+		board_name_decode(),
+		(platform_version >> 1), platform_version % 10U,
+		(rtlversion >> 1), rtlversion % 10U,
+		(psversion >> 1), psversion % 10U,
+		(pmcversion >> 1), pmcversion % 10U);
 
 	/*
 	 * Do initial security configuration to allow DRAM/device access. On
diff --git a/plat/amd/versal2/include/def.h b/plat/amd/versal2/include/def.h
index 0c43d1b..938b118 100644
--- a/plat/amd/versal2/include/def.h
+++ b/plat/amd/versal2/include/def.h
@@ -45,6 +45,9 @@
 /* For platform detection */
 #define PMC_TAP				U(0xF11A0000)
 #define PMC_TAP_VERSION			(PMC_TAP + 0x4U)
+# define PMC_VERSION			GENMASK(7U, 0U)
+# define PS_VERSION			GENMASK(15U, 8U)
+# define RTL_VERSION			GENMASK(23U, 16U)
 # define PLATFORM_MASK			GENMASK(27U, 24U)
 # define PLATFORM_VERSION_MASK		GENMASK(31U, 28U)
 
diff --git a/plat/amd/versal2/include/plat_private.h b/plat/amd/versal2/include/plat_private.h
index 5a2e5bd..4be2061 100644
--- a/plat/amd/versal2/include/plat_private.h
+++ b/plat/amd/versal2/include/plat_private.h
@@ -41,6 +41,7 @@
 void plat_gic_redistif_off(void);
 
 extern uint32_t cpu_clock, platform_id, platform_version;
+extern uint32_t rtlversion, psversion, pmcversion;
 void board_detection(void);
 const char *board_name_decode(void);
 uint64_t smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
diff --git a/plat/amd/versal2/include/platform_def.h b/plat/amd/versal2/include/platform_def.h
index be1e351..8f694f7 100644
--- a/plat/amd/versal2/include/platform_def.h
+++ b/plat/amd/versal2/include/platform_def.h
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2021-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -55,8 +55,8 @@
  * BL32 specific defines.
  ******************************************************************************/
 #ifndef BL32_MEM_BASE
-# define BL32_BASE			U(0x60000000)
-# define BL32_LIMIT			U(0x80000000)
+# define BL32_BASE			U(0x01800000)
+# define BL32_LIMIT			U(0x09800000)
 #else
 # define BL32_BASE			U(BL32_MEM_BASE)
 # define BL32_LIMIT			U(BL32_MEM_BASE + BL32_MEM_SIZE)
@@ -66,7 +66,7 @@
  * BL33 specific defines.
  ******************************************************************************/
 #ifndef PRELOADED_BL33_BASE
-# define PLAT_ARM_NS_IMAGE_BASE		U(0x8000000)
+# define PLAT_ARM_NS_IMAGE_BASE		U(0x40000000)
 #else
 # define PLAT_ARM_NS_IMAGE_BASE		U(PRELOADED_BL33_BASE)
 #endif
@@ -99,8 +99,8 @@
  * FIXME: This address should come from firmware before TF-A
  * Having this to make sure the transfer list functionality works
  */
-#define FW_HANDOFF_BASE         U(0x70000000)
-#define FW_HANDOFF_SIZE         U(0x10000)
+#define FW_HANDOFF_BASE         U(0x1000000)
+#define FW_HANDOFF_SIZE         U(0x600000)
 #endif
 
 #define IS_TFA_IN_OCM(x)	((x >= PLAT_OCM_BASE) && (x < PLAT_OCM_LIMIT))
diff --git a/plat/arm/board/common/board_common.mk b/plat/arm/board/common/board_common.mk
index 124a44b..889b8b3 100644
--- a/plat/arm/board/common/board_common.mk
+++ b/plat/arm/board/common/board_common.mk
@@ -67,7 +67,7 @@
 	PK_PREREQUISITES = $(ROT_KEY) FORCE
 endif
 
-$(ARM_ROTPK) : $(PK_PREREQUISITES)
+$(ARM_ROTPK) : $(PK_PREREQUISITES) | $$(@D)/
 ifndef ROT_KEY
 	$(error Cannot generate public key: no ROT_KEY defined)
 endif
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 8793840..ce06146 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -219,6 +219,20 @@
 				lib/cpus/aarch64/cortex_a75.S
 endif
 
+#Include all CPUs to build to support all-errata build.
+ifeq (${ENABLE_ERRATA_ALL},1)
+	BUILD_CPUS_WITH_NO_FVP_MODEL = 1
+	FVP_CPU_LIBS    +=	lib/cpus/aarch64/cortex_a510.S		\
+				lib/cpus/aarch64/cortex_a520.S		\
+				lib/cpus/aarch64/cortex_a725.S          \
+				lib/cpus/aarch64/cortex_x1.S            \
+				lib/cpus/aarch64/cortex_x3.S            \
+				lib/cpus/aarch64/cortex_x925.S          \
+				lib/cpus/aarch64/neoverse_n3.S          \
+				lib/cpus/aarch64/neoverse_v2.S          \
+				lib/cpus/aarch64/neoverse_v3.S
+endif
+
 #Build AArch64-only CPUs with no FVP model yet.
 ifeq (${BUILD_CPUS_WITH_NO_FVP_MODEL},1)
 	FVP_CPU_LIBS    +=	lib/cpus/aarch64/neoverse_n3.S		\
diff --git a/plat/arm/board/neoverse_rd/common/include/nrd3/nrd_css_fw_def3.h b/plat/arm/board/neoverse_rd/common/include/nrd3/nrd_css_fw_def3.h
index 706b201..bbfbe01 100644
--- a/plat/arm/board/neoverse_rd/common/include/nrd3/nrd_css_fw_def3.h
+++ b/plat/arm/board/neoverse_rd/common/include/nrd3/nrd_css_fw_def3.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -111,6 +111,14 @@
 			ARM_REALM_SIZE,					\
 			MT_MEMORY | MT_RW | MT_REALM)
 
+#if SPD_spmd && SPMD_SPM_AT_SEL2
+#define NRD_CSS_SPM_CORE_REGION_MMAP						\
+		MAP_REGION_FLAT(					\
+			BL32_BASE,					\
+			BL32_LIMIT - BL32_BASE,				\
+			MT_MEMORY | MT_RW | MT_SECURE)
+#endif
+
 #if RESET_TO_BL31
 /*******************************************************************************
  * BL31 specific defines.
diff --git a/plat/arm/board/neoverse_rd/common/include/nrd3/nrd_pas_def3.h b/plat/arm/board/neoverse_rd/common/include/nrd3/nrd_pas_def3.h
index 7d14e81..914560c 100644
--- a/plat/arm/board/neoverse_rd/common/include/nrd3/nrd_pas_def3.h
+++ b/plat/arm/board/neoverse_rd/common/include/nrd3/nrd_pas_def3.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -177,6 +177,9 @@
  * ---------------------------------------------------------------------
  * 0x80000000       |2GB -   |L1 GPT |NS     |NS DRAM                  |
  * 0xF3FFFFFF       |192MB   |       |       |                         |
+ * --------------------------------------------------------------------|
+ * 0xF4000000       |9692KB  |L1 GPT |SECURE |BL32                     |
+ * 0xFB200000       |        |       |       |                         |
  * ---------------------------------------------------------------------
  * 0x80000000       |26MB    |L1 GPT |REALM  |RMM                      |
  * 0x37FFFFFF       |        |       |       |TF-A SHARED              |
@@ -514,6 +517,14 @@
 			ARM_DRAM1_SIZE,					\
 			GPT_GPI_NS)
 
+#if SPD_spmd && SPMD_SPM_AT_SEL2
+#define NRD_PAS_BL32							\
+		GPT_MAP_REGION_GRANULE(					\
+			PLAT_ARM_SPMC_BASE,				\
+			PLAT_ARM_SPMC_SIZE,				\
+			GPT_GPI_SECURE)
+#endif
+
 #define NRD_PAS_RMM							\
 		GPT_MAP_REGION_GRANULE(					\
 			ARM_REALM_BASE,					\
diff --git a/plat/arm/board/neoverse_rd/common/include/nrd3/nrd_plat_arm_def3.h b/plat/arm/board/neoverse_rd/common/include/nrd3/nrd_plat_arm_def3.h
index 8d6d1cb..7fa2b77 100644
--- a/plat/arm/board/neoverse_rd/common/include/nrd3/nrd_plat_arm_def3.h
+++ b/plat/arm/board/neoverse_rd/common/include/nrd3/nrd_plat_arm_def3.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -118,7 +118,7 @@
 #elif defined(IMAGE_BL2U)
 # define PLATFORM_STACK_SIZE		UL(0x400)
 #elif defined(IMAGE_BL31)
-# if SPM_MM
+# if SPM_MM || SPMD_SPM_AT_SEL2
 #  define PLATFORM_STACK_SIZE		UL(0x500)
 # else
 #  define PLATFORM_STACK_SIZE		UL(0x400)
@@ -608,9 +608,13 @@
  *   - L1 GPT DRAM: Reserved for L1 GPT if RME is enabled
  *   - TF-A <-> RMM SHARED: Area shared for communication between TF-A and RMM
  *   - REALM DRAM: Reserved for Realm world if RME is enabled
+ *   - BL32: Carveout for BL32 image if BL32 is present
  *
  *                    DRAM layout
  *               +------------------+
+ *               |                  |
+ *               |        BL32      |
+ *               +------------------+
  *               |   REALM (RMM)    |
  *               |   (32MB - 4KB)   |
  *               +------------------+
@@ -696,6 +700,14 @@
 #define RMM_SHARED_SIZE			(ARM_EL3_RMM_SHARED_SIZE)
 
 /*******************************************************************************
+ * S-EL2 SPMC region defines.
+ ******************************************************************************/
+/* BL32 (1500KB) +  PLAT_ARM_SP_MAX_SIZE (3MB) + SP HEAP (5MB) */
+/* 9692KB */
+#define PLAT_ARM_SPMC_SIZE	(UL(1500 * 1024) + UL(0x300000) + UL(0x500000))
+#define PLAT_ARM_SPMC_BASE	(RMM_BASE - PLAT_ARM_SPMC_SIZE)
+
+/*******************************************************************************
  * NRD_CSS_CARVEOUT_RESERVED region specific defines.
  ******************************************************************************/
 
@@ -705,12 +717,29 @@
 #define NRD_CSS_CARVEOUT_RESERVED_SIZE	(NRD_CSS_DRAM1_CARVEOUT_SIZE -	\
 					(ARM_EL3_RMM_SHARED_SIZE +	\
 					 ARM_REALM_SIZE +		\
-					 ARM_L1_GPT_SIZE))
+					 ARM_L1_GPT_SIZE +		\
+					 PLAT_ARM_SPMC_SIZE))
 
 #define NRD_CSS_CARVEOUT_RESERVED_END	(NRD_CSS_CARVEOUT_RESERVED_BASE +\
 					 NRD_CSS_CARVEOUT_RESERVED_SIZE - 1U)
 
 /*******************************************************************************
+ * BL32 specific defines for EL3 runtime in AArch64 mode
+ ******************************************************************************/
+
+#if SPD_spmd && SPMD_SPM_AT_SEL2
+#  define BL32_BASE			PLAT_ARM_SPMC_BASE
+#  define BL32_LIMIT			(PLAT_ARM_SPMC_BASE +		\
+					 PLAT_ARM_SPMC_SIZE)
+
+#if RESET_TO_BL31
+#  define PLAT_ARM_SPMC_MANIFEST_BASE	UL(0x1F500)
+#  define ARM_SPMC_MANIFEST_BASE	PLAT_ARM_SPMC_MANIFEST_BASE
+#endif
+
+# endif
+
+/*******************************************************************************
  * NS RAM specific defines specific defines.
  ******************************************************************************/
 
@@ -722,6 +751,12 @@
 					 ARM_NS_DRAM1_SIZE - 1U)
 
 /*******************************************************************************
+ * Secure Partition specific defines.
+ ******************************************************************************/
+
+#define PLAT_ARM_SP_MAX_SIZE		U(0x300000) /* 3MB */
+
+/*******************************************************************************
  * MMU mapping
  ******************************************************************************/
 
diff --git a/plat/arm/board/neoverse_rd/common/nrd_bl31_setup.c b/plat/arm/board/neoverse_rd/common/nrd_bl31_setup.c
index 39a86b1..d3038ec 100644
--- a/plat/arm/board/neoverse_rd/common/nrd_bl31_setup.c
+++ b/plat/arm/board/neoverse_rd/common/nrd_bl31_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,6 +13,8 @@
 #include <drivers/arm/css/css_mhu_doorbell.h>
 #include <drivers/arm/css/scmi.h>
 #include <drivers/generic_delay_timer.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/arm/css/common/css_pm.h>
 #include <plat/common/platform.h>
@@ -155,6 +157,21 @@
 	/* Initialize generic timer */
 	generic_delay_timer_init();
 
+#if SPMD_SPM_AT_SEL2 && !RESET_TO_BL31
+	INFO("BL31 FCONF: FW_CONFIG address = 0x%lx\n", (uintptr_t)arg1);
+	/* Initialize BL31's copy of the DTB registry because SPMD needs the
+	 * TOS_FW_CONFIG's addresses to make a copy.
+	 */
+	fconf_populate("FW_CONFIG", arg1);
+
+	/* arg1 is supposed to point to SOC_FW_CONFIG */
+	const struct dyn_cfg_dtb_info_t *soc_fw_config_info;
+
+	soc_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, SOC_FW_CONFIG_ID);
+	if (soc_fw_config_info != NULL) {
+		arg1 = soc_fw_config_info->config_addr;
+	}
+#endif /* SPMD_SPM_AT_SEL2 && !RESET_TO_BL31 */
 	arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
 }
 
diff --git a/plat/arm/board/neoverse_rd/common/nrd_image_load.c b/plat/arm/board/neoverse_rd/common/nrd_image_load.c
index 15d90be..ee1f265 100644
--- a/plat/arm/board/neoverse_rd/common/nrd_image_load.c
+++ b/plat/arm/board/neoverse_rd/common/nrd_image_load.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,6 +10,8 @@
 #include <common/debug.h>
 #include <common/desc_image_load.h>
 #include <drivers/arm/css/sds.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 #include <platform_def.h>
@@ -145,11 +147,37 @@
  ******************************************************************************/
 bl_params_t *plat_get_next_bl_params(void)
 {
+	struct bl_params *arm_bl_params;
 	int ret;
 
 	ret = plat_nrd_append_config_node();
 	if (ret != 0)
 		panic();
 
-	return arm_get_next_bl_params();
+	arm_bl_params = arm_get_next_bl_params();
+
+#if !EL3_PAYLOAD_BASE
+	const struct dyn_cfg_dtb_info_t *fw_config_info;
+	bl_mem_params_node_t *param_node;
+	uintptr_t fw_config_base = 0UL;
+
+	/* Get BL31 image node */
+	param_node = get_bl_mem_params_node(BL31_IMAGE_ID);
+	assert(param_node != NULL);
+
+	/* Get fw_config load address */
+	fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID);
+	assert(fw_config_info != NULL);
+
+	fw_config_base = fw_config_info->config_addr;
+	assert(fw_config_base != 0UL);
+
+	/*
+	 * Get the entry point info of next executable image and override
+	 * arg1 of entry point info with fw_config base address
+	 */
+	param_node->ep_info.args.arg1 = (uint64_t)fw_config_base;
+
+#endif
+	return arm_bl_params;
 }
diff --git a/plat/arm/board/neoverse_rd/common/nrd_plat3.c b/plat/arm/board/neoverse_rd/common/nrd_plat3.c
index 00f346e..5811bc0 100644
--- a/plat/arm/board/neoverse_rd/common/nrd_plat3.c
+++ b/plat/arm/board/neoverse_rd/common/nrd_plat3.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -39,6 +39,9 @@
 	NRD_ROS_PLATFORM_PERIPH_MMAP,
 	NRD_ROS_SYSTEM_PERIPH_MMAP,
 	NRD_CSS_NS_DRAM1_MMAP,
+#if SPD_spmd && SPMD_SPM_AT_SEL2
+	NRD_CSS_SPM_CORE_REGION_MMAP,
+#endif
 #if TRUSTED_BOARD_BOOT && !RESET_TO_BL2
 	NRD_CSS_BL1_RW_MMAP,
 #endif
diff --git a/plat/arm/board/neoverse_rd/platform/rdn2/platform.mk b/plat/arm/board/neoverse_rd/platform/rdn2/platform.mk
index c2dfba6..5776948 100644
--- a/plat/arm/board/neoverse_rd/platform/rdn2/platform.mk
+++ b/plat/arm/board/neoverse_rd/platform/rdn2/platform.mk
@@ -1,4 +1,4 @@
-# Copyright (c) 2020-2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2020-2025, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -113,6 +113,8 @@
 override ENABLE_FEAT_MTE2       	:= 2
 override SPMD_SPM_AT_SEL2		:= 0
 
+# FEAT_SVE related flags
+override SVE_VECTOR_LEN			:= 128
 # Enable the flag since RD-N2 has a system level cache
 NEOVERSE_Nx_EXTERNAL_LLC		:=	1
 
diff --git a/plat/arm/board/neoverse_rd/platform/rdv1/platform.mk b/plat/arm/board/neoverse_rd/platform/rdv1/platform.mk
index db8efbb..241133f 100644
--- a/plat/arm/board/neoverse_rd/platform/rdv1/platform.mk
+++ b/plat/arm/board/neoverse_rd/platform/rdv1/platform.mk
@@ -1,4 +1,4 @@
-# Copyright (c) 2020-2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2020-2025, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -61,6 +61,9 @@
 override ENABLE_FEAT_AMU		:= 2
 override SPMD_SPM_AT_SEL2		:= 0
 
+# FEAT_SVE related flags
+override SVE_VECTOR_LEN			:= 256
+
 ifneq ($(NRD_PLATFORM_VARIANT),0)
  $(error "NRD_PLATFORM_VARIANT for RD-V1 should always be 0, \
      currently set to ${NRD_PLATFORM_VARIANT}.")
diff --git a/plat/arm/board/neoverse_rd/platform/rdv1mc/platform.mk b/plat/arm/board/neoverse_rd/platform/rdv1mc/platform.mk
index 6d518d5..7af0bd8 100644
--- a/plat/arm/board/neoverse_rd/platform/rdv1mc/platform.mk
+++ b/plat/arm/board/neoverse_rd/platform/rdv1mc/platform.mk
@@ -1,4 +1,4 @@
-# Copyright (c) 2020-2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2020-2025, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -72,6 +72,9 @@
 override ENABLE_FEAT_AMU		:= 2
 override SPMD_SPM_AT_SEL2		:= 0
 
+# FEAT_SVE related flags
+override SVE_VECTOR_LEN			:= 256
+
 ifneq ($(NRD_PLATFORM_VARIANT),0)
  $(error "NRD_PLATFORM_VARIANT for RD-V1-MC should always be 0, \
      currently set to ${NRD_PLATFORM_VARIANT}.")
diff --git a/plat/arm/board/neoverse_rd/platform/rdv3/fdts/rdv3_fw_config.dts b/plat/arm/board/neoverse_rd/platform/rdv3/fdts/rdv3_fw_config.dts
index 62ba0fa..7a904fe 100644
--- a/plat/arm/board/neoverse_rd/platform/rdv3/fdts/rdv3_fw_config.dts
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/fdts/rdv3_fw_config.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,6 +18,13 @@
 			id = <TB_FW_CONFIG_ID>;
 		};
 
+		tos_fw-config {
+			load-address = <0x0 0x01f500>;
+			secondary-load-address = <0x0 0xF9200000>;
+			max-size = <0x1000>;
+			id = <TOS_FW_CONFIG_ID>;
+		};
+
 		nt_fw-config {
 			load-address = <0x0 0xF3000000>;
 			max-size = <0x0100000>;
diff --git a/plat/arm/board/neoverse_rd/platform/rdv3/fdts/rdv3_spmc_sp_manifest.dts b/plat/arm/board/neoverse_rd/platform/rdv3/fdts/rdv3_spmc_sp_manifest.dts
new file mode 100644
index 0000000..c9764e4
--- /dev/null
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/fdts/rdv3_spmc_sp_manifest.dts
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+/dts-v1/;
+
+#define	AFF	00
+
+#include "rdv3-defs.dtsi"
+
+/ {
+	compatible = "arm,ffa-core-manifest-1.0";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	attribute {
+		spmc_id = <0x8000>;
+		maj_ver = <0x1>;
+		min_ver = <0x1>;
+		exec_state = <0x0>;
+		load_address = <0x0 0xfa889000>;
+		entrypoint = <0x0 0xfa889000>;
+		binary_size = <0x177000>;
+	};
+
+	hypervisor {
+		compatible = "hafnium,hafnium";
+		vm1 {
+			is_ffa_partition;
+			debug_name = "stmm";
+			load_address = <0xFAA00000>;
+			vcpu_count = <1>;
+			mem_size = <0x300000>;
+		};
+	};
+
+	cpus {
+		#address-cells = <0x2>;
+		#size-cells = <0x0>;
+
+		CPU_0
+
+		/*
+		 * SPMC (Hafnium) requires secondary core nodes are declared
+		 * in descending order.
+		 */
+#if (NRD_PLATFORM_VARIANT != 1)
+		CPU(F)
+		CPU(E)
+		CPU(D)
+		CPU(C)
+		CPU(B)
+		CPU(A)
+		CPU(9)
+		CPU(8)
+#endif
+		CPU(7)
+		CPU(6)
+		CPU(5)
+		CPU(4)
+		CPU(3)
+		CPU(2)
+		CPU(1)
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = /* Trusted DRAM for SPMC and SP */
+		      <0x0 0xfa889000 0x0 0x400000
+		      /* Trusted DRAM for SP Heap*/
+		      0x0 0xfad00000 0x0 0x500000>;
+	};
+
+	memory@1 {
+		device_type = "ns-memory";
+		/* DRAM for SP NS mappings*/
+		reg = <0x0 0x80000000 0x0 0x78FE0000>;
+	};
+	memory@2 {
+		device_type = "device-memory";
+		reg = /* AP Memory Expansion 2 - Secure Flash*/
+		      <0x6 0x04000000 0x0 0x04000000>;
+	};
+};
diff --git a/plat/arm/board/neoverse_rd/platform/rdv3/fdts/rdv3_tb_fw_config.dts b/plat/arm/board/neoverse_rd/platform/rdv3/fdts/rdv3_tb_fw_config.dts
index a4c7c72..77c4725 100644
--- a/plat/arm/board/neoverse_rd/platform/rdv3/fdts/rdv3_tb_fw_config.dts
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/fdts/rdv3_tb_fw_config.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -25,4 +25,13 @@
 		mbedtls_heap_addr = <0x0 0x0>;
 		mbedtls_heap_size = <0x0>;
 	};
+
+	secure-partitions {
+		compatible = "arm,sp";
+		stmm {
+			uuid = "eaba83d8-baaf-4eaf-8144-f7fdcbe544a7";
+			load-address = <0xFAA00000>;
+			owner = "Plat";
+		};
+	};
 };
diff --git a/plat/arm/board/neoverse_rd/platform/rdv3/platform.mk b/plat/arm/board/neoverse_rd/platform/rdv3/platform.mk
index f37d903..49b7cc3 100644
--- a/plat/arm/board/neoverse_rd/platform/rdv3/platform.mk
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/platform.mk
@@ -1,4 +1,4 @@
-# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -127,6 +127,13 @@
 BL31_SOURCES	+=	drivers/arm/gic/v3/gic600_multichip.c
 endif
 
+ifneq (${PLAT_RESET_TO_BL31}, 1)
+ifeq ($(SPMD_SPM_AT_SEL2),1)
+# Firmware Configuration Framework sources
+BL31_SOURCES    +=    ${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
+endif
+endif
+
 # XLAT options for RD-V3 variants
 BL31_CFLAGS	+=      -DPLAT_XLAT_TABLES_DYNAMIC
 BL2_CFLAGS	+=      -DPLAT_XLAT_TABLES_DYNAMIC
@@ -136,6 +143,12 @@
 			${RDV3_BASE}/fdts/${PLAT}_tb_fw_config.dts \
 			${RDV3_BASE}/fdts/${PLAT}_nt_fw_config.dts
 
+ifeq (${SPMD_SPM_AT_SEL2}, 1)
+BL32_CONFIG_DTS                :=      ${RDV3_BASE}/fdts/${PLAT}_spmc_sp_manifest.dts
+FDT_SOURCES            +=      ${BL32_CONFIG_DTS}
+TOS_FW_CONFIG          :=      ${BUILD_PLAT}/fdts/$(notdir $(basename ${BL32_CONFIG_DTS})).dtb
+endif
+
 FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
 TB_FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
 NT_FW_CONFIG	:=	${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb
@@ -153,4 +166,7 @@
 override ENABLE_SVE_FOR_SWD	:= 1
 override ENABLE_SVE_FOR_NS	:= 2
 override ENABLE_FEAT_MTE2	:= 2
+
+# FEAT_SVE related flags
+override SVE_VECTOR_LEN		:= 128
 override CTX_INCLUDE_SVE_REGS	:= 1
diff --git a/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl2_setup.c b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl2_setup.c
index 8dac8d3..1ee5f53 100644
--- a/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl2_setup.c
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl2_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -59,6 +59,9 @@
 	NRD_PAS_SCP_MCP_RSE_SHARED_SRAM,
 	NRD_PAS_GIC,
 	NRD_PAS_NS_DRAM,
+#if SPD_spmd && SPMD_SPM_AT_SEL2
+	NRD_PAS_BL32,
+#endif
 	NRD_PAS_RMM,
 	NRD_PAS_L1GPT,
 	NRD_PAS_CMN,
diff --git a/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c
index dba83ab..3ef9681 100644
--- a/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -198,3 +198,13 @@
 	/* Initialize the communication channel between AP and RSE */
 	return rse_comms_init(snd_base, rcv_base);
 }
+
+int plat_spmd_handle_group0_interrupt(uint32_t intid)
+{
+	/*
+	 * As of now, there are no sources of Group0 secure interrupt enabled
+	 * for FVP.
+	 */
+	(void)intid;
+	return -1;
+}
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index 4787995..ce1545f 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -210,14 +210,7 @@
 	bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry();
 
 #if defined(SPD_spmd)
-	/* SPM (hafnium in secure world) expects SPM Core manifest base address
-	 * in x0, which in !RESET_TO_BL31 case loaded after base of non shared
-	 * SRAM(after 4KB offset of SRAM). But in RESET_TO_BL31 case all non
-	 * shared SRAM is allocated to BL31, so to avoid overwriting of manifest
-	 * keep it in the last page.
-	 */
-	bl32_image_ep_info.args.arg0 = ARM_TRUSTED_SRAM_BASE +
-				PLAT_ARM_TRUSTED_SRAM_SIZE - PAGE_SIZE;
+	bl32_image_ep_info.args.arg0 = ARM_SPMC_MANIFEST_BASE;
 #endif
 
 # endif /* BL32_BASE */
diff --git a/plat/mediatek/drivers/cpu_pm/cpcv5_4/mt_cpu_pm.c b/plat/mediatek/drivers/cpu_pm/cpcv5_4/mt_cpu_pm.c
index f105b88..606a7b7 100644
--- a/plat/mediatek/drivers/cpu_pm/cpcv5_4/mt_cpu_pm.c
+++ b/plat/mediatek/drivers/cpu_pm/cpcv5_4/mt_cpu_pm.c
@@ -14,7 +14,7 @@
 
 #include <lib/mtk_init/mtk_init.h>
 #include <lib/pm/mtk_pm.h>
-#include <lpm/mt_lp_rm.h>
+#include <lpm_v2/mt_lp_rm.h>
 #include "mt_cpu_pm.h"
 #include "mt_cpu_pm_cpc.h"
 #include "mt_cpu_pm_mbox.h"
@@ -773,11 +773,13 @@
 static int cpupm_invoke(unsigned int func_id, void *priv)
 {
 	int ret = MTK_CPUPM_E_OK;
+#ifdef CPU_PM_SUSPEND_NOTIFY
 	int i, reverse = 0;
 	struct cpupm_invoke_data *save_status = (struct cpupm_invoke_data *) priv;
+	unsigned int cpu_status;
+#endif
 	struct cpupm_pwr_req *req = (struct cpupm_pwr_req *)priv;
 	unsigned int pwr_req = req->req;
-	unsigned int cpu_status;
 
 	switch (func_id) {
 #ifdef CPU_PM_SUSPEND_NOTIFY
diff --git a/plat/mediatek/drivers/cpu_pm/cpcv5_4/mt_cpu_pm_smc.h b/plat/mediatek/drivers/cpu_pm/cpcv5_4/mt_cpu_pm_smc.h
index 8b643b0..5cd2f5c 100644
--- a/plat/mediatek/drivers/cpu_pm/cpcv5_4/mt_cpu_pm_smc.h
+++ b/plat/mediatek/drivers/cpu_pm/cpcv5_4/mt_cpu_pm_smc.h
@@ -7,9 +7,9 @@
 #ifndef MT_CPU_PM_SMC_H
 #define MT_CPU_PM_SMC_H
 
-#include <lpm/mt_lp_rm.h>
-#include <lpm/mt_lpm_dispatch.h>
-#include <lpm/mt_lpm_smc.h>
+#include <lpm_v2/mt_lp_rm.h>
+#include <lpm_v2/mt_lpm_dispatch.h>
+#include <lpm_v2/mt_lpm_smc.h>
 
 void cpupm_smc_init(void);
 
diff --git a/plat/mediatek/drivers/cpu_pm/cpcv5_4/mt_lp_irqremain.c b/plat/mediatek/drivers/cpu_pm/cpcv5_4/mt_lp_irqremain.c
index ded1a60..563e6b5 100644
--- a/plat/mediatek/drivers/cpu_pm/cpcv5_4/mt_lp_irqremain.c
+++ b/plat/mediatek/drivers/cpu_pm/cpcv5_4/mt_lp_irqremain.c
@@ -12,7 +12,7 @@
 #include <platform_def.h>
 
 #include <lib/pm/mtk_pm.h>
-#include <lpm/mt_lp_rm.h>
+#include <lpm_v2/mt_lp_rm.h>
 #include "mt_cpu_pm.h"
 #include "mt_lp_irqremain.h"
 
diff --git a/plat/mediatek/drivers/cpu_pm/cpcv5_4/rules.mk b/plat/mediatek/drivers/cpu_pm/cpcv5_4/rules.mk
index 9819d0e..c6937e1 100644
--- a/plat/mediatek/drivers/cpu_pm/cpcv5_4/rules.mk
+++ b/plat/mediatek/drivers/cpu_pm/cpcv5_4/rules.mk
@@ -29,8 +29,6 @@
 $(eval $(call add_defined_option,CPU_PM_CORE_ARCH64_ONLY))
 $(eval $(call add_defined_option,CPU_PM_TINYSYS_SUPPORT))
 
-$(eval $(call add_defined_option,CPU_PM_SUSPEND_NOTIFY))
-
 $(eval $(call add_defined_option,CPU_PM_PWR_REQ))
 $(eval $(call add_defined_option,CPU_PM_PWR_REQ_DEBUG))
 
diff --git a/plat/mediatek/include/mtk_sip_def.h b/plat/mediatek/include/mtk_sip_def.h
index 85b7230..2e0b501 100644
--- a/plat/mediatek/include/mtk_sip_def.h
+++ b/plat/mediatek/include/mtk_sip_def.h
@@ -12,6 +12,7 @@
 	_func(MTK_SIP_KERNEL_TIME_SYNC, 0x202) \
 	_func(MTK_SIP_KERNEL_DFD, 0x205) \
 	_func(MTK_SIP_KERNEL_MSDC, 0x273) \
+	_func(MTK_SIP_KERNEL_UFS_CONTROL, 0x276) \
 	_func(MTK_SIP_VCORE_CONTROL, 0x506) \
 	_func(MTK_SIP_MTK_LPM_CONTROL, 0x507) \
 	_func(MTK_SIP_EMIDBG_CONTROL, 0x50B) \
@@ -20,14 +21,17 @@
 	_func(MTK_SIP_APUSYS_CONTROL, 0x51E) \
 	_func(MTK_SIP_DP_CONTROL, 0x523) \
 	_func(MTK_SIP_KERNEL_GIC_OP, 0x526) \
-	_func(MTK_SIP_KERNEL_VCP_CONTROL, 0x52C)
+	_func(MTK_SIP_KERNEL_VCP_CONTROL, 0x52C) \
+	_func(MTK_SIP_KERNEL_SLBC_CONTROL, 0x53E)
 
 #define MTK_SIP_SMC_FROM_S_EL1_TABLE(_func) \
 	_func(MTK_SIP_TEE_MPU_PERM_SET, 0x031) \
-	_func(MTK_SIP_TEE_EMI_MPU_CONTROL, 0x048)
+	_func(MTK_SIP_TEE_EMI_MPU_CONTROL, 0x048) \
+	_func(MTK_SIP_TEE_SMMU_CONTROL, 0x04D)
 
 #define MTK_SIP_SMC_FROM_BL33_TABLE(_func) \
 	_func(MTK_SIP_KERNEL_BOOT, 0x115) \
+	_func(MTK_SIP_BL_UFS_CONTROL, 0x40D) \
 	_func(MTK_SIP_BL_LPM_CONTROL, 0x410) \
 	_func(MTK_SIP_BL_EMIMPU_CONTROL, 0x415)
 
diff --git a/plat/mediatek/lib/pm/armv9_0/pwr_ctrl.c b/plat/mediatek/lib/pm/armv9_0/pwr_ctrl.c
index 73b1f68..ace2700 100644
--- a/plat/mediatek/lib/pm/armv9_0/pwr_ctrl.c
+++ b/plat/mediatek/lib/pm/armv9_0/pwr_ctrl.c
@@ -16,6 +16,7 @@
 #include <drivers/console.h>
 #include <lib/psci/psci.h>
 #include <lib/utils.h>
+#include <mt_gic_v3.h>
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 #include <platform_def.h>
@@ -108,6 +109,9 @@
 
 static void mcusys_pwr_on_common(const struct mtk_cpupm_pwrstate *state)
 {
+	mt_gic_distif_restore();
+	mt_gic_rdistif_restore();
+
 	if (IS_CPUIDLE_FN_ENABLE(MTK_CPUPM_FN_RESUME_MCUSYS))
 		imtk_cpu_pwr.ops->mcusys_resume(state);
 }
@@ -121,6 +125,9 @@
 	if (IS_CPUIDLE_FN_ENABLE(MTK_CPUPM_FN_SUSPEND_MCUSYS))
 		imtk_cpu_pwr.ops->mcusys_suspend(state);
 
+	mt_gic_rdistif_save();
+	/* save gic context after cirq enable */
+	mt_gic_distif_save();
 }
 
 static void cluster_pwr_on_common(const struct mtk_cpupm_pwrstate *state)
@@ -140,8 +147,7 @@
 {
 	coordinate_cluster_pwron();
 
-	gicv3_rdistif_init(plat_my_core_pos());
-	gicv3_cpuif_enable(plat_my_core_pos());
+	mt_gic_cpuif_enable();
 }
 
 static void cpu_pwr_dwn_common(const struct mtk_cpupm_pwrstate *state,
@@ -149,6 +155,8 @@
 {
 	if (pstate & MT_CPUPM_PWR_DOMAIN_PERCORE_DSU)
 		coordinate_cluster_pwroff();
+
+	mt_gic_cpuif_disable();
 }
 
 static void cpu_pwr_resume(const struct mtk_cpupm_pwrstate *state,
@@ -217,6 +225,8 @@
 		},
 	};
 
+	mt_gic_pcpu_init();
+
 	cpu_pwr_on(&pm_state, pstate);
 
 	nb.cpuid = pm_state.info.cpuid;
@@ -243,7 +253,7 @@
 
 	cpu_pwr_off(&pm_state, pstate);
 
-	gicv3_rdistif_off(plat_my_core_pos());
+	mt_gic_redistif_off();
 
 	nb.cpuid = pm_state.info.cpuid;
 	nb.pwr_domain = pstate;
@@ -278,8 +288,6 @@
 	if (pstate & MT_CPUPM_PWR_DOMAIN_MCUSYS)
 		mcusys_pwr_dwn_common(&pm_state);
 
-	gicv3_rdistif_off(plat_my_core_pos());
-
 	nb.cpuid = pm_state.info.cpuid;
 	nb.pwr_domain = pstate;
 	MT_CPUPM_EVENT_PWR_OFF(&nb);
diff --git a/plat/mediatek/lib/system_reset/reset_cros.c b/plat/mediatek/lib/system_reset/reset_cros.c
index 40e68ba..5f97650 100644
--- a/plat/mediatek/lib/system_reset/reset_cros.c
+++ b/plat/mediatek/lib/system_reset/reset_cros.c
@@ -1,18 +1,25 @@
 /*
- * Copyright (c) 2022, MediaTek Inc. All rights reserved.
+ * Copyright (c) 2022-2025, MediaTek Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <assert.h>
+
 #include <arch_helpers.h>
 #include <common/debug.h>
+#include <drivers/delay_timer.h>
 #include <drivers/gpio.h>
+#if CONFIG_MTK_PMIC_SHUTDOWN_CFG
+#include <drivers/pmic/pmic_psc.h>
+#endif
 #include <lib/mtk_init/mtk_init.h>
 #include <lib/pm/mtk_pm.h>
 #include <plat_params.h>
+#if !CONFIG_MTK_PMIC_SHUTDOWN_CFG
 #include <pmic.h>
 #include <rtc.h>
+#endif
 
 static void __dead2 mtk_system_reset_cros(void)
 {
@@ -31,8 +38,13 @@
 {
 	INFO("MTK System Off\n");
 
+#if CONFIG_MTK_PMIC_SHUTDOWN_CFG
+	platform_power_hold(false);
+	mdelay(1000);
+#else
 	rtc_power_off_sequence();
 	pmic_power_off();
+#endif
 
 	wfi();
 	ERROR("MTK System Off: operation not handled.\n");
diff --git a/plat/mediatek/mt8196/include/platform_def.h b/plat/mediatek/mt8196/include/platform_def.h
index 72d83e6..4fa3079 100644
--- a/plat/mediatek/mt8196/include/platform_def.h
+++ b/plat/mediatek/mt8196/include/platform_def.h
@@ -87,7 +87,7 @@
  * GPIO related constants
  ******************************************************************************/
 #define GPIO_BASE		(IO_PHYS + 0x0002D000)
-#define RGU_BASE		(IO_PHYS + 0x0C00B000)
+#define RGU_BASE		(IO_PHYS + 0x0C010000)
 #define DRM_BASE		(IO_PHYS + 0x0000D000)
 #define IOCFG_RT_BASE		(IO_PHYS + 0x02000000)
 #define IOCFG_RM1_BASE		(IO_PHYS + 0x02020000)
@@ -280,8 +280,6 @@
  ******************************************************************************/
 #define PLAT_CPU_PM_B_BUCK_ISO_ID	(6)
 #define PLAT_CPU_PM_ILDO_ID		(6)
-#define CPU_IDLE_SRAM_BASE		(0x11B000)
-#define CPU_IDLE_SRAM_SIZE		(0x1000)
 
 /*******************************************************************************
  * SYSTIMER related definitions
diff --git a/plat/mediatek/mt8196/plat_mmap.c b/plat/mediatek/mt8196/plat_mmap.c
index d32f4ee..11cb700 100644
--- a/plat/mediatek/mt8196/plat_mmap.c
+++ b/plat/mediatek/mt8196/plat_mmap.c
@@ -15,8 +15,6 @@
 			MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(MTK_DEV_RNG1_BASE, MTK_DEV_RNG1_SIZE,
 			MT_DEVICE | MT_RW | MT_SECURE),
-	MAP_REGION_FLAT(CPU_IDLE_SRAM_BASE, CPU_IDLE_SRAM_SIZE,
-			MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(DP_SEC_BASE, DP_SEC_SIZE,
 			MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(EDP_SEC_BASE, EDP_SEC_SIZE,
diff --git a/plat/mediatek/mt8196/platform.mk b/plat/mediatek/mt8196/platform.mk
index 5050809..36048fe 100644
--- a/plat/mediatek/mt8196/platform.mk
+++ b/plat/mediatek/mt8196/platform.mk
@@ -41,6 +41,7 @@
 MODULES-y += $(MTK_PLAT)/common/lpm_v2
 MODULES-y += $(MTK_PLAT)/lib/mtk_init
 MODULES-y += $(MTK_PLAT)/lib/pm
+MODULES-y += $(MTK_PLAT)/lib/system_reset
 MODULES-y += $(MTK_PLAT)/drivers/apusys
 MODULES-y += $(MTK_PLAT)/drivers/cirq
 MODULES-y += $(MTK_PLAT)/drivers/dp
@@ -62,7 +63,7 @@
 
 ifneq ($(MTKLIB_PATH),)
 LDFLAGS += -L $(dir $(MTKLIB_PATH))
-LDLIBS += -l$(patsubst lib%.a,%,$(notdir $(MTKLIB_PATH)))
+LDLIBS += -Wl,--whole-archive -l$(patsubst lib%.a,%,$(notdir $(MTKLIB_PATH))) -Wl,--no-whole-archive
 endif
 
 PLAT_BL_COMMON_SOURCES := common/desc_image_load.c \