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 \