Merge "feat(spm_mm): move mm_communication header define to general header" into integration
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 4c610ad..46e5f67 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -2,17 +2,19 @@
updates:
- target-branch: "main"
package-ecosystem: "npm"
- directories: ["/"]
+ versioning-strategy: "lockfile-only"
+ directories: ["/", "/tools/conventional-changelog-tf-a"]
schedule:
interval: "daily"
groups:
dev-deps:
patterns: ["*"]
- update-types: ["major", "minor", "patch"]
+ update-types: ["minor", "patch"]
- target-branch: "lts-v2.10"
package-ecosystem: "npm"
- directories: ["/"]
+ versioning-strategy: "lockfile-only"
+ directories: ["/", "/tools/conventional-changelog-tf-a"]
schedule:
interval: "daily"
groups:
@@ -22,7 +24,8 @@
- target-branch: "lts-v2.8"
package-ecosystem: "npm"
- directories: ["/"]
+ versioning-strategy: "lockfile-only"
+ directories: ["/", "/tools/conventional-changelog-tf-a"]
schedule:
interval: "daily"
groups:
@@ -32,16 +35,18 @@
- target-branch: "main"
package-ecosystem: "pip"
- directories: ["/", "/tools/cot_dt2c", "/tools/tlc"]
+ versioning-strategy: "lockfile-only"
+ directories: ["/", "/tools/cot_dt2c", "/tools/memory", "/tools/tlc"]
schedule:
interval: "daily"
groups:
dev-deps:
patterns: ["*"]
- update-types: ["major", "minor", "patch"]
+ update-types: ["minor", "patch"]
- target-branch: "lts-v2.10"
package-ecosystem: "pip"
+ versioning-strategy: "lockfile-only"
directories: ["/"]
schedule:
interval: "daily"
@@ -52,6 +57,7 @@
- target-branch: "lts-v2.8"
package-ecosystem: "pip"
+ versioning-strategy: "lockfile-only"
directories: ["/"]
schedule:
interval: "daily"
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
index 2d1afab..d308fdd 100644
--- a/.readthedocs.yaml
+++ b/.readthedocs.yaml
@@ -1,4 +1,4 @@
-# Copyright (c) 2023-2024, Arm Limited. All rights reserved
+# Copyright (c) 2023-2025, Arm Limited. All rights reserved
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -20,7 +20,7 @@
post_create_environment:
- pip install poetry=="1.3.2"
post_install:
- - VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH poetry install --with docs
+ - VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH poetry install --no-root --with docs
sphinx:
configuration: docs/conf.py
@@ -28,4 +28,3 @@
# Auxiliary formats to export to (in addition to the default HTML output).
formats:
- pdf
-
diff --git a/Makefile b/Makefile
index 28ff849..4cba2b0 100644
--- a/Makefile
+++ b/Makefile
@@ -433,28 +433,12 @@
################################################################################
ifneq (${SPD},none)
- ifeq (${ARCH},aarch32)
- $(error "Error: SPD is incompatible with AArch32.")
- endif
-
- ifdef EL3_PAYLOAD_BASE
- $(warning "SPD and EL3_PAYLOAD_BASE are incompatible build options.")
- $(warning "The SPD and its BL32 companion will be present but \
- ignored.")
- endif
-
ifeq (${SPD},spmd)
# SPMD is located in std_svc directory
SPD_DIR := std_svc
ifeq ($(SPMD_SPM_AT_SEL2),1)
CTX_INCLUDE_EL2_REGS := 1
- ifeq ($(SPMC_AT_EL3),1)
- $(error SPM cannot be enabled in both S-EL2 and EL3.)
- endif
- ifeq ($(CTX_INCLUDE_SVE_REGS),1)
- $(error SVE context management not needed with Hafnium SPMC.)
- endif
endif
ifeq ($(findstring optee_sp,$(ARM_SPMC_MANIFEST_DTS)),optee_sp)
@@ -476,12 +460,6 @@
ifneq ($(SP_LAYOUT_FILE),)
BL2_ENABLE_SP_LOAD := 1
endif
-
- ifeq ($(SPMC_AT_EL3_SEL0_SP),1)
- ifneq ($(SPMC_AT_EL3),1)
- $(error SEL0 SP cannot be enabled without SPMC at EL3)
- endif
- endif
else
# All other SPDs in spd directory
SPD_DIR := spd
@@ -507,15 +485,6 @@
# over the sources.
endif #(SPD=none)
-ifeq (${ENABLE_SPMD_LP}, 1)
-ifneq (${SPD},spmd)
- $(error Error: ENABLE_SPMD_LP requires SPD=spmd.)
-endif
-ifeq ($(SPMC_AT_EL3),1)
- $(error SPMC at EL3 not supported when enabling SPMD Logical partitions.)
-endif
-endif
-
################################################################################
# Include the platform specific Makefile after the SPD Makefile (the platform
# makefile may use all previous definitions in this file)
@@ -774,6 +743,42 @@
# Check incompatible options and dependencies
################################################################################
+# Handle all invalid build configurations with SPMD usage.
+ifeq (${ENABLE_SPMD_LP}, 1)
+ifneq (${SPD},spmd)
+ $(error Error: ENABLE_SPMD_LP requires SPD=spmd.)
+endif
+ifeq ($(SPMC_AT_EL3),1)
+ $(error SPMC at EL3 not supported when enabling SPMD Logical partitions.)
+endif
+endif
+
+ifneq (${SPD},none)
+ifeq (${ARCH},aarch32)
+ $(error "Error: SPD is incompatible with AArch32.")
+endif
+ifdef EL3_PAYLOAD_BASE
+ $(warning "SPD and EL3_PAYLOAD_BASE are incompatible build options.")
+ $(warning "The SPD and its BL32 companion will be present but ignored.")
+endif
+ifeq (${SPD},spmd)
+ifeq ($(SPMD_SPM_AT_SEL2),1)
+ ifeq ($(SPMC_AT_EL3),1)
+ $(error SPM cannot be enabled in both S-EL2 and EL3.)
+ endif
+ ifeq ($(CTX_INCLUDE_SVE_REGS),1)
+ $(error SVE context management not needed with Hafnium SPMC.)
+ endif
+endif
+
+ifeq ($(SPMC_AT_EL3_SEL0_SP),1)
+ ifneq ($(SPMC_AT_EL3),1)
+ $(error SEL0 SP cannot be enabled without SPMC at EL3)
+ endif
+endif
+endif #(SPD=spmd)
+endif #(SPD!=none)
+
# USE_DEBUGFS experimental feature recommended only in debug builds
ifeq (${USE_DEBUGFS},1)
ifeq (${DEBUG},1)
@@ -1185,7 +1190,6 @@
DYN_DISABLE_AUTH \
EL3_EXCEPTION_HANDLING \
ENABLE_AMU_AUXILIARY_COUNTERS \
- ENABLE_AMU_FCONF \
AMU_RESTRICT_COUNTERS \
ENABLE_ASSERTIONS \
ENABLE_PIE \
@@ -1244,13 +1248,14 @@
ENCRYPT_BL31 \
ENCRYPT_BL32 \
ERRATA_SPECULATIVE_AT \
+ ERRATA_SME_POWER_DOWN \
RAS_TRAP_NS_ERR_REC_ACCESS \
COT_DESC_IN_DTB \
USE_SP804_TIMER \
PSA_FWU_SUPPORT \
PSA_FWU_METADATA_FW_STORE_DESC \
ENABLE_MPMM \
- ENABLE_MPMM_FCONF \
+ FEAT_PABANDON \
FEATURE_DETECTION \
TRNG_SUPPORT \
ENABLE_ERRATA_ALL \
@@ -1359,7 +1364,6 @@
DISABLE_MTPMU \
ENABLE_FEAT_AMU \
ENABLE_AMU_AUXILIARY_COUNTERS \
- ENABLE_AMU_FCONF \
AMU_RESTRICT_COUNTERS \
ENABLE_ASSERTIONS \
ENABLE_BTI \
@@ -1433,6 +1437,7 @@
BL2_INV_DCACHE \
USE_SPINLOCK_CAS \
ERRATA_SPECULATIVE_AT \
+ ERRATA_SME_POWER_DOWN \
RAS_TRAP_NS_ERR_REC_ACCESS \
COT_DESC_IN_DTB \
USE_SP804_TIMER \
@@ -1450,7 +1455,7 @@
ENABLE_TRF_FOR_NS \
ENABLE_FEAT_HCX \
ENABLE_MPMM \
- ENABLE_MPMM_FCONF \
+ FEAT_PABANDON \
ENABLE_FEAT_FGT \
ENABLE_FEAT_FGT2 \
ENABLE_FEAT_FPMR \
@@ -1633,12 +1638,28 @@
# Expand build macros for the different images
ifeq (${NEED_FDT},yes)
$(eval $(call MAKE_DTBS,$(BUILD_PLAT)/fdts,$(FDT_SOURCES)))
+
+ ifneq (${INITRD_SIZE}${INITRD_PATH},)
+ ifndef INITRD_BASE
+ $(error INITRD_BASE must be set when inserting initrd properties to the DTB.)
+ endif
+
+ INITRD_SIZE ?= $(shell printf "0x%x\n" $$(stat -Lc %s $(INITRD_PATH)))
+ initrd_end = $(shell printf "0x%x\n" $$(expr $$(($(INITRD_BASE) + $(INITRD_SIZE)))))
+
+ define $(HW_CONFIG)-after +=
+ $(s)echo " INITRD $(HW_CONFIG)"
+ $(q)fdtput -t x $@ /chosen linux,initrd-start $(INITRD_BASE)
+ $(q)fdtput -t x $@ /chosen linux,initrd-end $(initrd_end)
+ endef
+ endif
endif #(NEED_FDT)
# Add Secure Partition packages
ifeq (${NEED_SP_PKG},yes)
$(BUILD_PLAT)/sp_gen.mk: ${SP_MK_GEN} ${SP_LAYOUT_FILE} | $$(@D)/
- $(q)${PYTHON} "$<" "$@" $(filter-out $<,$^) $(BUILD_PLAT) ${COT} ${SP_DTS_LIST_FRAGMENT}
+ $(if $(host-poetry),$(q)poetry -q install)
+ $(q)$(if $(host-poetry),poetry run )${PYTHON} "$<" "$@" $(filter-out $<,$^) $(BUILD_PLAT) ${COT} ${SP_DTS_LIST_FRAGMENT}
sp: $(DTBS) $(BUILD_PLAT)/sp_gen.mk $(SP_PKGS)
$(s)echo
$(s)echo "Built SP Images successfully"
@@ -1757,8 +1778,8 @@
$(q)${MAKE} PLAT_DIR=${PLAT_DIR} BUILD_PLAT=${BUILD_PLAT} ENABLE_BTI=${ENABLE_BTI} CRYPTO_SUPPORT=${CRYPTO_SUPPORT} ARM_ARCH_MINOR=${ARM_ARCH_MINOR} INCLUDES=$(call escape-shell,$(INCLUDES)) DEFINES=$(call escape-shell,$(DEFINES)) --no-print-directory -C ${ROMLIBPATH} all
memmap: all
- $(q)PYTHONPATH=${CURDIR}/tools/memory \
- ${PYTHON} -m memory.memmap -sr ${BUILD_PLAT}
+ $(if $(host-poetry),$(q)poetry -q install)
+ $(q)$(if $(host-poetry),poetry run )memory -sr ${BUILD_PLAT}
tl: ${BUILD_PLAT}/tl.bin
${BUILD_PLAT}/tl.bin: ${HW_CONFIG}
diff --git a/bl1/bl1.mk b/bl1/bl1.mk
index a8a0061..c068ea5 100644
--- a/bl1/bl1.mk
+++ b/bl1/bl1.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -18,8 +18,7 @@
${MBEDTLS_SOURCES}
ifeq (${ARCH},aarch64)
-BL1_SOURCES += lib/cpus/aarch64/dsu_helpers.S \
- lib/el3_runtime/aarch64/context.S \
+BL1_SOURCES += lib/el3_runtime/aarch64/context.S \
lib/cpus/errata_common.c
endif
diff --git a/bl2/bl2.mk b/bl2/bl2.mk
index 850d826..2a212e1 100644
--- a/bl2/bl2.mk
+++ b/bl2/bl2.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -43,10 +43,6 @@
bl2/${ARCH}/bl2_run_next_image.S \
lib/cpus/${ARCH}/cpu_helpers.S
-ifeq (${ARCH},aarch64)
-BL2_SOURCES += lib/cpus/aarch64/dsu_helpers.S
-endif
-
BL2_DEFAULT_LINKER_SCRIPT_SOURCE := bl2/bl2_el3.ld.S
endif
diff --git a/bl31/aarch64/ea_delegate.S b/bl31/aarch64/ea_delegate.S
index 91ea75d..fce17e1 100644
--- a/bl31/aarch64/ea_delegate.S
+++ b/bl31/aarch64/ea_delegate.S
@@ -245,26 +245,30 @@
*/
func ea_proceed
/*
- * If the ESR loaded earlier is not zero, we were processing an EA
- * already, and this is a double fault.
+ * If it is a double fault invoke platform handler.
+ * Double fault scenario would arise when platform is handling a fault in
+ * lower EL using plat_ea_handler() and another fault happens which would
+ * trap into EL3 as FFH_SUPPORT is enabled for the platform.
*/
- ldr x5, [sp, #CTX_EL3STATE_OFFSET + CTX_ESR_EL3]
+ ldr x5, [sp, #CTX_EL3STATE_OFFSET + CTX_DOUBLE_FAULT_ESR]
cbz x5, 1f
no_ret plat_handle_double_fault
1:
- /* Save EL3 state */
+ /* Save EL3 state as handling might involve lower ELs */
mrs x2, spsr_el3
mrs x3, elr_el3
stp x2, x3, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
+ mrs x4, scr_el3
+ str x4, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
/*
- * Save ESR as handling might involve lower ELs, and returning back to
- * EL3 from there would trample the original ESR.
+ * Save CTX_DOUBLE_FAULT_ESR, so that if another fault happens in lower EL, we
+ * catch it as DoubleFault in next invocation of ea_proceed() along with
+ * preserving original ESR_EL3.
*/
- mrs x4, scr_el3
mrs x5, esr_el3
- stp x4, x5, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
+ str x5, [sp, #CTX_EL3STATE_OFFSET + CTX_DOUBLE_FAULT_ESR]
/*
* Setup rest of arguments, and call platform External Abort handler.
@@ -305,23 +309,15 @@
/* Make SP point to context */
msr spsel, #MODE_SP_ELX
- /* Restore EL3 state and ESR */
+ /* Clear Double Fault storage */
+ str xzr, [sp, #CTX_EL3STATE_OFFSET + CTX_DOUBLE_FAULT_ESR]
+
+ /* Restore EL3 state */
ldp x1, x2, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
msr spsr_el3, x1
msr elr_el3, x2
-
- /* Restore ESR_EL3 and SCR_EL3 */
- ldp x3, x4, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
+ ldr x3, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
msr scr_el3, x3
- msr esr_el3, x4
-
-#if ENABLE_ASSERTIONS
- cmp x4, xzr
- ASM_ASSERT(ne)
-#endif
-
- /* Clear ESR storage */
- str xzr, [sp, #CTX_EL3STATE_OFFSET + CTX_ESR_EL3]
ret x29
endfunc ea_proceed
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index 2f9dc65..e390915 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -24,7 +24,6 @@
endif
include lib/extensions/amu/amu.mk
-include lib/mpmm/mpmm.mk
ifeq (${SPMC_AT_EL3},1)
$(info Including EL3 SPMC makefile)
@@ -43,7 +42,6 @@
bl31/bl31_traps.c \
common/runtime_svc.c \
lib/cpus/errata_common.c \
- lib/cpus/aarch64/dsu_helpers.S \
plat/common/aarch64/platform_mp_stack.S \
services/arm_arch_svc/arm_arch_svc_setup.c \
services/std_svc/std_svc_setup.c \
@@ -115,10 +113,6 @@
BL31_SOURCES += lib/extensions/tcr/tcr2.c
endif
-ifeq (${ENABLE_MPMM},1)
-BL31_SOURCES += ${MPMM_SOURCES}
-endif
-
ifneq (${ENABLE_SME_FOR_NS},0)
BL31_SOURCES += lib/extensions/sme/sme.c
endif
diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c
index 83be0f6..db0ea6c 100644
--- a/bl31/bl31_main.c
+++ b/bl31/bl31_main.c
@@ -127,7 +127,7 @@
void bl31_main(void)
{
/* Init registers that never change for the lifetime of TF-A */
- cm_manage_extensions_el3();
+ cm_manage_extensions_el3(plat_my_core_pos());
/* Init per-world context registers for non-secure world */
manage_extensions_nonsecure_per_world();
diff --git a/common/fdt_wrappers.c b/common/fdt_wrappers.c
index b213ffa..8638351 100644
--- a/common/fdt_wrappers.c
+++ b/common/fdt_wrappers.c
@@ -277,7 +277,7 @@
return err;
}
-static uint64_t fdt_read_prop_cells(const fdt32_t *prop, int nr_cells)
+uint64_t fdt_read_prop_cells(const fdt32_t *prop, int nr_cells)
{
uint64_t reg = fdt32_to_cpu(prop[0]);
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index 210ae7e..3e33824 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -387,7 +387,7 @@
Firmware Encryption Framework
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:|M|: Sumit Garg <sumit.garg@linaro.org>
+:|M|: Sumit Garg <sumit.garg@kernel.org>
:|G|: `b49020`_
:|F|: drivers/io/io_encrypted.c
:|F|: include/drivers/io/io_encrypted.h
@@ -447,8 +447,7 @@
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:|M|: Chris Kay <chris.kay@arm.com>
:|G|: `CJKay`_
-:|F|: include/lib/mpmm/
-:|F|: lib/mpmm/
+:|F|: include/lib/cpus/aarch64/cpu_macros.S
Granule Protection Tables Library (GPT-RME)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -896,7 +895,7 @@
Synquacer platform port
^^^^^^^^^^^^^^^^^^^^^^^
-:|M|: Sumit Garg <sumit.garg@linaro.org>
+:|M|: Sumit Garg <sumit.garg@kernel.org>
:|G|: `b49020`_
:|M|: Masahisa Kojima <kojima.masahisa@socionext.com>
:|G|: `masahisak`_
@@ -997,7 +996,7 @@
Encrypt_fw tool
^^^^^^^^^^^^^^^
-:|M|: Sumit Garg <sumit.garg@linaro.org>
+:|M|: Sumit Garg <sumit.garg@kernel.org>
:|G|: `b49020`_
:|F|: tools/encrypt_fw/
diff --git a/docs/components/activity-monitors.rst b/docs/components/activity-monitors.rst
index 5c1c2c2..4c33d42 100644
--- a/docs/components/activity-monitors.rst
+++ b/docs/components/activity-monitors.rst
@@ -20,15 +20,9 @@
build option.
As a security precaution, Trusted Firmware-A does not enable these by default.
-Instead, platforms may configure their auxiliary counters through one of two
-possible mechanisms:
-
-- |FCONF|, controlled by the ``ENABLE_AMU_FCONF`` build option.
-- A platform implementation of the ``plat_amu_topology`` function (the default).
-
-See :ref:`Activity Monitor Unit (AMU) Bindings` for documentation on the |FCONF|
-device tree bindings.
+Instead, platforms must configure their auxiliary counters through the
+``plat_amu_aux_enables`` platform hook.
--------------
-*Copyright (c) 2021, Arm Limited. All rights reserved.*
+*Copyright (c) 2021-2025, Arm Limited. All rights reserved.*
diff --git a/docs/components/context-management-library.rst b/docs/components/context-management-library.rst
index 6a76ada..8cb1ace 100644
--- a/docs/components/context-management-library.rst
+++ b/docs/components/context-management-library.rst
@@ -498,7 +498,6 @@
typedef struct per_world_context {
uint64_t ctx_cptr_el3;
- uint64_t ctx_zcr_el3;
uint64_t ctx_mpam3_el3;
} per_world_context_t;
@@ -555,7 +554,7 @@
EL3 execution context needs to setup at both boot time (cold and warm boot)
entrypaths and at all the possible exception handlers routing to EL3 at runtime.
-*Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.*
.. |Context Memory Allocation| image:: ../resources/diagrams/context_memory_allocation.png
.. |CPU Context Memory Configuration| image:: ../resources/diagrams/cpu_data_config_context_memory.png
diff --git a/docs/components/fconf/amu-bindings.rst b/docs/components/fconf/amu-bindings.rst
deleted file mode 100644
index 047f75e..0000000
--- a/docs/components/fconf/amu-bindings.rst
+++ /dev/null
@@ -1,142 +0,0 @@
-Activity Monitor Unit (AMU) Bindings
-====================================
-
-To support platform-defined Activity Monitor Unit (|AMU|) auxiliary counters
-through FCONF, the ``HW_CONFIG`` device tree accepts several |AMU|-specific
-nodes and properties.
-
-Bindings
-^^^^^^^^
-
-.. contents::
- :local:
-
-``/cpus/cpus/cpu*`` node properties
-"""""""""""""""""""""""""""""""""""
-
-The ``cpu`` node has been augmented to support a handle to an associated |AMU|
-view, which should describe the counters offered by the core.
-
-+---------------+-------+---------------+-------------------------------------+
-| Property name | Usage | Value type | Description |
-+===============+=======+===============+=====================================+
-| ``amu`` | O | ``<phandle>`` | If present, indicates that an |AMU| |
-| | | | is available and its counters are |
-| | | | described by the node provided. |
-+---------------+-------+---------------+-------------------------------------+
-
-``/cpus/amus`` node properties
-""""""""""""""""""""""""""""""
-
-The ``amus`` node describes the |AMUs| implemented by the cores in the system.
-This node does not have any properties.
-
-``/cpus/amus/amu*`` node properties
-"""""""""""""""""""""""""""""""""""
-
-An ``amu`` node describes the layout and meaning of the auxiliary counter
-registers of one or more |AMUs|, and may be shared by multiple cores.
-
-+--------------------+-------+------------+------------------------------------+
-| Property name | Usage | Value type | Description |
-+====================+=======+============+====================================+
-| ``#address-cells`` | R | ``<u32>`` | Value shall be 1. Specifies that |
-| | | | the ``reg`` property array of |
-| | | | children of this node uses a |
-| | | | single cell. |
-+--------------------+-------+------------+------------------------------------+
-| ``#size-cells`` | R | ``<u32>`` | Value shall be 0. Specifies that |
-| | | | no size is required in the ``reg`` |
-| | | | property in children of this node. |
-+--------------------+-------+------------+------------------------------------+
-
-``/cpus/amus/amu*/counter*`` node properties
-""""""""""""""""""""""""""""""""""""""""""""
-
-A ``counter`` node describes an auxiliary counter belonging to the parent |AMU|
-view.
-
-+-------------------+-------+-------------+------------------------------------+
-| Property name | Usage | Value type | Description |
-+===================+=======+=============+====================================+
-| ``reg`` | R | array | Represents the counter register |
-| | | | index, and must be a single cell. |
-+-------------------+-------+-------------+------------------------------------+
-| ``enable-at-el3`` | O | ``<empty>`` | The presence of this property |
-| | | | indicates that this counter should |
-| | | | be enabled prior to EL3 exit. |
-+-------------------+-------+-------------+------------------------------------+
-
-Example
-^^^^^^^
-
-An example system offering four cores made up of two clusters, where the cores
-of each cluster share different |AMUs|, may use something like the following:
-
-.. code-block::
-
- cpus {
- #address-cells = <2>;
- #size-cells = <0>;
-
- amus {
- amu0: amu-0 {
- #address-cells = <1>;
- #size-cells = <0>;
-
- counterX: counter@0 {
- reg = <0>;
-
- enable-at-el3;
- };
-
- counterY: counter@1 {
- reg = <1>;
-
- enable-at-el3;
- };
- };
-
- amu1: amu-1 {
- #address-cells = <1>;
- #size-cells = <0>;
-
- counterZ: counter@0 {
- reg = <0>;
-
- enable-at-el3;
- };
- };
- };
-
- cpu0@00000 {
- ...
-
- amu = <&amu0>;
- };
-
- cpu1@00100 {
- ...
-
- amu = <&amu0>;
- };
-
- cpu2@10000 {
- ...
-
- amu = <&amu1>;
- };
-
- cpu3@10100 {
- ...
-
- amu = <&amu1>;
- };
- }
-
-In this situation, ``cpu0`` and ``cpu1`` (the two cores in the first cluster),
-share the view of their AMUs defined by ``amu0``. Likewise, ``cpu2`` and
-``cpu3`` (the two cores in the second cluster), share the view of their |AMUs|
-defined by ``amu1``. This will cause ``counterX`` and ``counterY`` to be enabled
-for both ``cpu0`` and ``cpu1``, and ``counterZ`` to be enabled for both ``cpu2``
-and ``cpu3``.
diff --git a/docs/components/fconf/index.rst b/docs/components/fconf/index.rst
index b8b4519..6cb6774 100644
--- a/docs/components/fconf/index.rst
+++ b/docs/components/fconf/index.rst
@@ -145,6 +145,4 @@
:maxdepth: 1
fconf_properties
- amu-bindings
- mpmm-bindings
tb_fw_bindings
diff --git a/docs/components/fconf/mpmm-bindings.rst b/docs/components/fconf/mpmm-bindings.rst
deleted file mode 100644
index d3cc857..0000000
--- a/docs/components/fconf/mpmm-bindings.rst
+++ /dev/null
@@ -1,48 +0,0 @@
-Maximum Power Mitigation Mechanism (MPMM) Bindings
-==================================================
-
-|MPMM| support cannot be determined at runtime by the firmware. Instead, these
-DTB bindings allow the platform to communicate per-core support for |MPMM| via
-the ``HW_CONFIG`` device tree blob.
-
-Bindings
-^^^^^^^^
-
-.. contents::
- :local:
-
-``/cpus/cpus/cpu*`` node properties
-"""""""""""""""""""""""""""""""""""
-
-The ``cpu`` node has been augmented to allow the platform to indicate support
-for |MPMM| on a given core.
-
-+-------------------+-------+-------------+------------------------------------+
-| Property name | Usage | Value type | Description |
-+===================+=======+=============+====================================+
-| ``supports-mpmm`` | O | ``<empty>`` | If present, indicates that |MPMM| |
-| | | | is available on this core. |
-+-------------------+-------+-------------+------------------------------------+
-
-Example
-^^^^^^^
-
-An example system offering two cores, one with support for |MPMM| and one
-without, can be described as follows:
-
-.. code-block::
-
- cpus {
- #address-cells = <2>;
- #size-cells = <0>;
-
- cpu0@00000 {
- ...
-
- supports-mpmm;
- };
-
- cpu1@00100 {
- ...
- };
- }
diff --git a/docs/components/granule-protection-tables-design.rst b/docs/components/granule-protection-tables-design.rst
index 78d2f12..91673c6 100644
--- a/docs/components/granule-protection-tables-design.rst
+++ b/docs/components/granule-protection-tables-design.rst
@@ -124,10 +124,7 @@
The GPT initialization APIs require memory to be passed in for the tables to be
constructed. The ``gpt_init_l0_tables`` API takes a memory address and size for
-building the level 0 tables and also memory for allocating the fine-grained bitlock
-data structure. The amount of memory needed for bitlock structure is controlled via
-``RME_GPT_BITLOCK_BLOCK`` config which defines the block size for each bit of the
-the bitlock.
+building the level 0 tables.
The ``gpt_init_pas_l1_tables`` API takes an address and size for
building the level 1 tables which are linked from level 0 descriptors. The
@@ -156,7 +153,7 @@
During Granule Transition access to L1 tables is controlled by a lock to ensure
that no more than one CPU is allowed to make changes at any given time.
The granularity of the lock is defined by ``RME_GPT_BITLOCK_BLOCK`` build option
-which defines the size of the memory block protected by one bit of ``bitlock``
+which defines the size of the memory block protected by one bit of ``bitlock_t``
structure. Setting this option to 0 chooses a single spinlock for all GPT L1
table entries.
@@ -185,6 +182,10 @@
#. In systems that make use of the granule transition service, runtime
firmware must call ``gpt_runtime_init`` to set up the data structures needed
by the GTSI to find the tables and transition granules between PAS types.
+ The base address of bitlocks array and its size are provided to this function
+ as arguments. These parameters are not used in case of a single spinlock for
+ all GPT L1 table entries(``RME_GPT_BITLOCK_BLOCK`` is 0) and are passed as zero
+ values.
API Constraints
~~~~~~~~~~~~~~~
@@ -225,9 +226,6 @@
is greater. L0 table size is the total protected space (PPS) divided by the
size of each L0 region (L0GPTSZ) multiplied by the size of each L0 descriptor
(8 bytes). ((PPS / L0GPTSZ) * 8)
-* The L0 memory size must be greater than the table size and have enough space
- to allocate array of ``bitlock`` structures at the end of L0 table if
- required (``RME_GPT_BITLOCK_BLOCK`` is not 0).
* The L0 memory must fall within a PAS of type GPT_GPI_ROOT.
The L1 memory also has some constraints.
@@ -237,6 +235,10 @@
the granules controlled in each byte (2). ((L0GPTSZ / PGS) / 2)
* There must be enough L1 memory supplied to build all requested L1 tables.
* The L1 memory must fall within a PAS of type GPT_GPI_ROOT.
+* The platform allocates the bitlock array which contains fine-grained
+ ``bitlock_t`` data structures. The RME GPT library will check that the array
+ has at least the amount of memory defined by PPS and ``RME_GPT_BITLOCK_BLOCK``
+ value.
If an invalid combination of parameters is supplied, the APIs will print an
error message and return a negative value. The return values of APIs should be
@@ -245,7 +247,7 @@
Sample Calculation for L0 memory size and alignment
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Let PPS=GPCCR_PPS_4GB and L0GPTSZ=GPCCR_L0GPTSZ_30BITS
+Let PPS=4GB and L0GPTSZ=GPCCR_L0GPTSZ_30BITS
We can find the total L0 table size with ((PPS / L0GPTSZ) * 8)
@@ -254,19 +256,19 @@
And solve to get 32 bytes. In this case, 4096 is greater than 32, so the L0
tables must be aligned to 4096 bytes.
-Sample calculation for bitlock array size
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Sample calculation for bitlocks array size
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Let PGS=GPCCR_PPS_256TB and RME_GPT_BITLOCK_BLOCK=1
+Let PPS=256TB and RME_GPT_BITLOCK_BLOCK=1
-The size of bit lock array in bits is the total protected space (PPS) divided
+The size of bitlocks array in bits is the total protected space (PPS) divided
by the size of memory block per bit. The size of memory block
is ``RME_GPT_BITLOCK_BLOCK`` (number of 512MB blocks per bit) times
-512MB (0x20000000). This is then divided by the number of bits in ``bitlock``
-structure (8) to get the size of bit array in bytes.
+512MB (0x20000000). This is then divided by the number of bits in ``bitlock_t``
+structure (8) to get the size of array in bytes.
-In other words, we can find the total size of ``bitlock`` array
-in bytes with PPS / (RME_GPT_BITLOCK_BLOCK * 0x20000000 * 8).
+In other words, we can find the total size of ``bitlock_t`` array
+in bytes with PPS / (RME_GPT_BITLOCK_BLOCK * 0x20000000 * 8).
Substitute values to get this: 0x1000000000000 / (1 * 0x20000000 * 8)
diff --git a/docs/components/mpmm.rst b/docs/components/mpmm.rst
index 1b1c6d8..aaa9481 100644
--- a/docs/components/mpmm.rst
+++ b/docs/components/mpmm.rst
@@ -8,16 +8,7 @@
triggering of whole-rail (i.e. clock chopping) responses to overcurrent
conditions.
-|MPMM| is enabled on a per-core basis by the EL3 runtime firmware. The presence
-of |MPMM| cannot be determined at runtime by the firmware, and therefore the
-platform must expose this information through one of two possible mechanisms:
-
-- |FCONF|, controlled by the ``ENABLE_MPMM_FCONF`` build option.
-- A platform implementation of the ``plat_mpmm_topology`` function (the
- default).
-
-See :ref:`Maximum Power Mitigation Mechanism (MPMM) Bindings` for documentation
-on the |FCONF| device tree bindings.
+|MPMM| is enabled on a per-core basis by the EL3 runtime firmware.
.. warning::
diff --git a/docs/components/rmm-el3-comms-spec.rst b/docs/components/rmm-el3-comms-spec.rst
index 79e1d2c..f1ca031 100644
--- a/docs/components/rmm-el3-comms-spec.rst
+++ b/docs/components/rmm-el3-comms-spec.rst
@@ -53,7 +53,7 @@
consistency with the versioning schemes used in other parts of RMM.
This document specifies the 0.4 version of Boot Interface ABI and RMM-EL3
-services specification and the 0.3 version of the Boot Manifest.
+services specification and the 0.4 version of the Boot Manifest.
.. _rmm_el3_boot_interface:
@@ -182,12 +182,12 @@
This Boot Manifest is versioned independently of the Boot Interface, to help
evolve the former independent of the latter.
-The current version for the Boot Manifest is ``v0.3`` and the rules explained
+The current version for the Boot Manifest is ``v0.4`` and the rules explained
in :ref:`rmm_el3_ifc_versioning` apply on this version as well.
-The Boot Manifest v0.3 has the following fields:
+The Boot Manifest v0.4 has the following fields:
- - version : Version of the Manifest (v0.3)
+ - version : Version of the Manifest (v0.4)
- plat_data : Pointer to the platform specific data and not specified by this
document. These data are optional and can be NULL.
- plat_dram : Structure encoding the NS DRAM information on the platform. This
@@ -720,61 +720,65 @@
RMM-EL3 Boot Manifest structure
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The RMM-EL3 Boot Manifest v0.3 structure contains platform boot information passed
-from EL3 to RMM. The size of the Boot Manifest is 64 bytes.
+The RMM-EL3 Boot Manifest v0.4 structure contains platform boot information passed
+from EL3 to RMM. The size of the Boot Manifest is 112 bytes.
The members of the RMM-EL3 Boot Manifest structure are shown in the following
table:
-+--------------+--------+----------------+----------------------------------------+
-| Name | Offset | Type | Description |
-+==============+========+================+========================================+
-| version | 0 | uint32_t | Boot Manifest version |
-+--------------+--------+----------------+----------------------------------------+
-| padding | 4 | uint32_t | Reserved, set to 0 |
-+--------------+--------+----------------+----------------------------------------+
-| plat_data | 8 | uintptr_t | Pointer to Platform Data section |
-+--------------+--------+----------------+----------------------------------------+
-| plat_dram | 16 | ns_dram_info | NS DRAM Layout Info structure |
-+--------------+--------+----------------+----------------------------------------+
-| plat_console | 40 | console_list | List of consoles available to RMM |
-+--------------+--------+----------------+----------------------------------------+
++--------------------+--------+-------------------+----------------------------------------------+
+| Name | Offset | Type | Description |
++====================+========+===================+==============================================+
+| version | 0 | uint32_t | Boot Manifest version |
++--------------------+--------+-------------------+----------------------------------------------+
+| padding | 4 | uint32_t | Reserved, set to 0 |
++--------------------+--------+-------------------+----------------------------------------------+
+| plat_data | 8 | uintptr_t | Pointer to Platform Data section |
++--------------------+--------+-------------------+----------------------------------------------+
+| plat_dram | 16 | memory_info | NS DRAM Layout Info structure |
++--------------------+--------+-------------------+----------------------------------------------+
+| plat_console | 40 | console_list | List of consoles available to RMM |
++--------------------+--------+-------------------+----------------------------------------------+
+| plat_ncoh_region | 64 | memory_info | Device non-coherent ranges Info structure |
++--------------------+--------+-------------------+----------------------------------------------+
+| plat_coh_region | 88 | memory_info | Device coherent ranges Info structure |
++--------------------+--------+-------------------+----------------------------------------------+
-.. _ns_dram_info_struct:
+.. _memory_info_struct:
-NS DRAM Layout Info structure
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Memory Info structure
+~~~~~~~~~~~~~~~~~~~~~~
-NS DRAM Layout Info structure contains information about platform Non-secure
-DRAM layout. The members of this structure are shown in the table below:
+Memory Info structure contains information about platform memory layout.
+The members of this structure are shown in the table below:
+-----------+--------+----------------+----------------------------------------+
| Name | Offset | Type | Description |
+===========+========+================+========================================+
-| num_banks | 0 | uint64_t | Number of NS DRAM banks |
+| num_banks | 0 | uint64_t | Number of memory banks/device regions |
+-----------+--------+----------------+----------------------------------------+
-| banks | 8 | ns_dram_bank * | Pointer to 'ns_dram_bank'[] array |
+| banks | 8 | memory_bank * | Pointer to 'memory_bank'[] array |
+-----------+--------+----------------+----------------------------------------+
| checksum | 16 | uint64_t | Checksum |
+-----------+--------+----------------+----------------------------------------+
Checksum is calculated as two's complement sum of 'num_banks', 'banks' pointer
-and DRAM banks data array pointed by it.
+and memory banks data array pointed by it.
-.. _ns_dram_bank_struct:
+.. _memory_bank_struct:
-NS DRAM Bank structure
-~~~~~~~~~~~~~~~~~~~~~~
+Memory Bank/Device region structure
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-NS DRAM Bank structure contains information about each Non-secure DRAM bank:
+Memory Bank structure contains information about each memory bank/device region:
-+-----------+--------+----------------+----------------------------------------+
-| Name | Offset | Type | Description |
-+===========+========+================+========================================+
-| base | 0 | uintptr_t | Base address |
-+-----------+--------+----------------+----------------------------------------+
-| size | 8 | uint64_t | Size of bank in bytes |
-+-----------+--------+----------------+----------------------------------------+
++-----------+--------+----------------+--------------------------------------------+
+| Name | Offset | Type | Description |
++===========+========+================+============================================+
+| base | 0 | uintptr_t | Base address |
++-----------+--------+----------------+--------------------------------------------+
+| size | 8 | uint64_t | Size of memory bank/device region in bytes |
++-----------+--------+----------------+--------------------------------------------+
.. _console_list_struct:
@@ -784,15 +788,15 @@
Console List structure contains information about the available consoles for RMM.
The members of this structure are shown in the table below:
-+--------------+--------+----------------+----------------------------------------+
-| Name | Offset | Type | Description |
-+==============+========+================+========================================+
-| num_consoles | 0 | uint64_t | Number of consoles |
-+--------------+--------+----------------+----------------------------------------+
-| consoles | 8 | console_info * | Pointer to 'console_info'[] array |
-+--------------+--------+----------------+----------------------------------------+
-| checksum | 16 | uint64_t | Checksum |
-+--------------+--------+----------------+----------------------------------------+
++--------------+--------+----------------+-------------------------------------+
+| Name | Offset | Type | Description |
++==============+========+================+=====================================+
+| num_consoles | 0 | uint64_t | Number of consoles |
++--------------+--------+----------------+-------------------------------------+
+| consoles | 8 | console_info * | Pointer to 'console_info'[] array |
++--------------+--------+----------------+-------------------------------------+
+| checksum | 16 | uint64_t | Checksum |
++--------------+--------+----------------+-------------------------------------+
Checksum is calculated as two's complement sum of 'num_consoles', 'consoles'
pointer and the consoles array pointed by it.
@@ -804,28 +808,28 @@
Console Info structure contains information about each Console available to RMM.
-+-----------+--------+---------------+----------------------------------------+
-| Name | Offset | Type | Description |
-+===========+========+===============+========================================+
-| base | 0 | uintptr_t | Console Base address |
-+-----------+--------+---------------+----------------------------------------+
-| map_pages | 8 | uint64_t | Num of pages to map for console MMIO |
-+-----------+--------+---------------+----------------------------------------+
-| name | 16 | char[] | Name of console |
-+-----------+--------+---------------+----------------------------------------+
-| clk_in_hz | 24 | uint64_t | UART clock (in hz) for console |
-+-----------+--------+---------------+----------------------------------------+
-| baud_rate | 32 | uint64_t | Baud rate |
-+-----------+--------+---------------+----------------------------------------+
-| flags | 40 | uint64_t | Additional flags (RES0) |
-+-----------+--------+---------------+----------------------------------------+
++-----------+--------+---------------+-----------------------------------------+
+| Name | Offset | Type | Description |
++===========+========+===============+=========================================+
+| base | 0 | uintptr_t | Console Base address |
++-----------+--------+---------------+-----------------------------------------+
+| map_pages | 8 | uint64_t | Num of pages to map for console MMIO |
++-----------+--------+---------------+-----------------------------------------+
+| name | 16 | char[8] | Name of console |
++-----------+--------+---------------+-----------------------------------------+
+| clk_in_hz | 24 | uint64_t | UART clock (in Hz) for console |
++-----------+--------+---------------+-----------------------------------------+
+| baud_rate | 32 | uint64_t | Baud rate |
++-----------+--------+---------------+-----------------------------------------+
+| flags | 40 | uint64_t | Additional flags (RES0) |
++-----------+--------+---------------+-----------------------------------------+
.. _el3_token_sign_request_struct:
EL3 Token Sign Request structure
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-This structure represents a realm attestation toekn signing request.
+This structure represents a realm attestation token signing request.
+-------------+--------+---------------+-----------------------------------------+
| Name | Offset | Type | Description |
diff --git a/docs/design/console-framework.rst b/docs/design/console-framework.rst
new file mode 100644
index 0000000..fcd2e68
--- /dev/null
+++ b/docs/design/console-framework.rst
@@ -0,0 +1,341 @@
+Console Framework
+=================
+
+The TF-A console framework is used to register consoles for different boot states
+so that user's output can be displayed on physical consoles throughout the different
+boot stages. The framework also supports debug mode for general debugging purposes.
+
+The console framework supports a number of different UARTs, it is highly likely
+that the driver of the UART that is needed is already implemented. If not, a driver
+will need to be written for the new UART in TF-A. Current supported UARTs are:
+
+* Amlogic Meson
+* Arm PL011
+* Cadence CDNS
+* Coreboot CBMEM
+* Marvell A3700
+* NXP
+ * i.MX LPUART
+ * i.MX UART
+ * Linflex
+* Nvidia SPE
+* Qualcomm UARTDM
+* Renesas RCAR
+* STMicroelectronics STM32
+* Texas Instruments 16550
+
+ .. note::
+ The supported UART list is non-exhaustive. Check if the UART driver has
+ already been written before writing a new one.
+
+::
+
+ Console scopes and flags
+
+ Scope : Flag
+ BOOT : CONSOLE_FLAG_BOOT
+ RUNTIME : CONSOLE_FLAG_RUNTIME
+ CRASH : CONSOLE_FLAG_CRASH
+
+The console framework supports multiple consoles. Multiple instances of a UART
+can be registered at any given moment. Any registered console can have a single
+scope or multiple scopes. In single scope for example, setting three different
+consoles with each having BOOT, RUNTIME, and CRASH states respectively, the boot
+console will display only boot logs, the runtime console will display only the
+runtime output, while the crash console will be used to print the crash log in the
+event of a crash. Similarly, a console with all three scopes will display any and
+all output destined for BOOT, RUNTIME, or CRASH consoles.
+
+These multiple scopes can be useful in many ways, for example:
+
+* Having different consoles for Boot and Runtime messages
+* Having a single console for both Runtime and Boot messages
+* Having no runtime console at all and just having a single Boot console.
+* Having a separate console for crash reporting when debugging.
+
+.. Registering a console:
+
+Registering a console
+---------------------
+To register a console in TF-A check if the hardware (UART) that is going to be used
+is already defined, if not we will need to define it, for example, the **PL011**
+UART driver API is defined in ``include/drivers/arm/pl011.h``.
+
+A skeleton console driver (assembly) is provided in TF-A ``drivers/console/aarch64/
+skeleton_console.S``, this skeleton sets the rules for writing a new console_driver.
+Have a look at ``drivers/arm/pl011/aarch64/pl011_console.S`` for an actual
+implementation using this skeleton.
+
+Function : console_xxx_register
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : console_t *, ...
+ Return : int
+
+This ASM Function is used to initialize and register a console. The caller needs
+to pass an empty ``console_t`` struct which *MUST* be allocated in persistent
+memory (e.g. a global or static local variable, *NOT* on the stack).
+
+This function takes a ``console_t`` struct placed in x0 and additional
+arguments placed in x1 - x7. It returns x0 with either a 0 on failure or 1
+on success.
+
+See ``console_pl011_register`` ASM function for an implementation of this
+function.
+
+ .. note::
+ The ``xxx`` in the function name is replaced with the console driver
+ name, for example, ``console_xxx_register`` becomes
+ ``console_pl011_register`` in the driver for pl011.
+
+Function : console_xxx_putc
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : int, console_t *
+ Return : int
+
+This ASM function is used to send a character to the UART's Transmit FIFO. It takes
+two arguments, a character as int stored in w0, and the ``console_t`` struct pointer
+stored in x1. It returns w0 with either the character on successs or a negative
+value on error. In a crash context this function must only clobber x0 - x2, x16 - x17.
+
+See ``console_pl011_putc`` ASM function for an implementation.
+
+ .. note::
+ Avoid the direct use of this function for printing to the console, instead use
+ the ``debug.h`` print macros, such as: VERBOSE(...), INFO(...), WARN(...),
+ NOTICE(...) and ERROR(...).
+
+Function : console_xxx_getc
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : console_t *
+ Return : int
+
+This ASM function is used to read a character from the receive FIFO. It takes a pointer
+to the console_struct as an argument and returns a character on success or a negative
+value below -2 on failure. This function is dependent on the ``ENABLE_CONSOLE_GETC`` flag,
+which is optional and is left to the platform because there may be security implications.
+
+See ``console_pl011_getc`` ASM function for an implementation.
+
+Function : console_xxx_flush
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : console_t *
+ Return : void
+
+This ASM function flushes any characters, that are still in the Transmit FIFO but
+haven't been printed yet to the console. It takes a pointer to the console_struct
+but doesn't return any value. In a crash context this function must only clobber
+x0 - x5, x16 - x17.
+
+See ``console_pl011_flush`` ASM function for an implementation.
+
+Macro : finish_console_register xxx putc=1 getc=ENABLE_CONSOLE_GETC flush=1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Callbacks
+ xxx : name of the console driver
+ putc : 0 for off, 1 to turn on putc function
+ getc : 0 for off, ENABLE_CONSOLE_GETC to turn on the getc function
+ flush : 0 for off, 1 to turn on flush function
+
+This assembly macro function is called by the ``console_xxx_register`` to
+encapsulate the common setup that has to be done at the end of a console
+driver's register function. It takes ``putc``, ``getc`` and ``flush`` macro
+arguments. It will register all of the driver's callbacks in the ``console_t``
+struct and initialize the ``flags`` field (by default consoles are enabled for
+"boot" and "crash" states, this can be changed after registration using the
+``console_set_scope`` function). This macro ends with a tail call that will
+include return to the caller.
+
+This macro requires ``console_t`` pointer in x0 and a valid return address in x30.
+
+See ``include/arch/aarch64/console_macros.S``.
+
+Registering a console using C
+-----------------------------
+
+A console can be implemented in pure C, which is much easier than using assembly.
+Currently there is no C template for implementing a console driver in C but it can
+easily be implemented using existing examples. See ``drivers/arm/dcc/dcc_console.c``
+for an implementation of a console driver in C.
+
+The assembly functions in `Registering a console`_ section can be written in C when
+implementing a console driver using C.
+
+ .. note::
+ A crash callback needs to be able to run without a stack. If crash mode
+ support is required then the console driver will need to be written in
+ Assembly (only the putc and flush functions are needed in a crash
+ context).
+
+Multi Console API
+-----------------
+
+TF-A uses the multi-console API to manage the registered console instances and the
+characters print queue. This can be found in ``drivers/console/multi_console.c``.
+
+The multi-console API stores all registered consoles in a struct list ``console_list``.
+Consoles can be removed from the console_list if no longer needed.
+
+Consoles are registered with BOOT and CRASH scopes by default. These scopes can be
+changed after registration using ``console_set_scope`` function, as per the platform
+requirement.
+
+This API also helps print characters to the specified consoles, characters can also
+be retrieved from the receive FIFO (this implementation is disabled by default but can
+be enabled if there is a need for it). The API can also help flush the transmit FIFO
+to get rid of any lingering characters from the queue when switching from secure world
+to the non-secure world.
+
+The following functions are defined in the multi_console API.
+
+Function : console_register()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : console_t*
+ Return : int
+
+This function adds a console to the ``console_list`` declared in
+``include/drivers/console.h`` and makes sure that there is only one instance
+of a specific console in this list. This function is called by the
+``finish_console_register`` asm macro function, at the end of the console
+registration process.
+
+This function always return 1. If the console is already present in the
+``console_list`` it will return immediately with a value of 1, otherwise
+it will add the console to the ``console_list`` and then return 1.
+
+ .. note::
+ The ``console_list`` is a list of type ``console_t``, it is an **extern**
+ variable declared in ``include/drivers/console.h``.
+
+Function : console_unregister()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : console_t*
+ Return : console_t* or NULL
+
+This function removes a console from the ``console_list``. It will return the
+removed console on success or a ``NULL`` character upon failure.
+
+Function : console_set_scope()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : console_t*, int
+ Return : void
+
+This function is used to set the scope of the registered console. A console
+can be registered with upto three states (called the scope). These states are
+
+* BOOT - set using the flag ``CONSOLE_FLAG_BOOT``
+* RUNTIME - set using the flag ``CONSOLE_FLAG_RUNTIME``
+* CRASH - set using the flag ``CONSOLE_FLAG_CRASH``
+
+It takes a pointer to the console and an int value (which is provided as the
+FLAG value) as its arguments. This function does not return anything.
+
+Function : console_switch_state()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : int
+ Return : void
+
+This function sets the console state (scope) for printing, i.e, TF-A will
+start sending all logs (INFO, WARNING, ERROR, NOTICE, VERBOSE) to the consoles
+that are registered with this new state (scope). For example, calling
+``console_switch_state(CONSOLE_FLAG_RUNTIME)``, TF-A will start sending all log
+messages to all consoles marked with the RUNTIME flag. BOOT is the default
+console state.
+
+This function takes a console state as the function's only argument. This function
+does not return a value.
+
+Function : console_putc()
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : int
+ Return : int
+
+Invoking this function sends a character to the ``console->putc`` (struct
+member) function of all consoles registered for the current scope, for example,
+BOOT logs will only be printed on consoles set with a BOOT scope. In the PL011
+implementation ``console->putc`` call points to the ``console_pl011_putc()``
+function.
+
+This function takes the int value of a character as an argument and returns the
+int value of the character back on success or a negative int value on error.
+
+ .. note::
+ Do not use this function in TF-A release builds, instead use the log
+ prefixes, for example, ``INFO("Print information here.")`` to print
+ messages on the active console.
+
+Function : console_getc()
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : void
+ Return : int
+
+This function is used to fetch a character from the receive FIFO that has
+not been printed to the console yet. This function is disabled by default for
+security reasons but can be enabled using the ``ENABLE_CONSOLE_GETC`` macro
+if there is a need for it.
+
+This function doesn't take any argument but returns a character as an int.
+
+Function : console_flush()
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : void
+ Return : void
+
+This function flushes all the characters pending in the transmit FIFO of the
+active UART thus removing them from the print queue.
+
+This function has no arguments and do not return a value.
+
+Function : putchar()
+~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : int
+ Return : int
+
+This function overrides the weak implementation of the putchar library. It is
+used to send a character to the ``console_putc()`` function to be printed to
+the active console.
+
+This function will either return the character on success or an **EOF** character
+otherwise.
+
+--------------
+
+*Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.*
\ No newline at end of file
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index 4637908..67f29f0 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -580,6 +580,9 @@
For Neoverse V3, the following errata build flags are defined :
+- ``ERRATA_V3_2970647``: This applies errata 2970647 workaround to Neoverse-V3
+ CPU. This needs to be enabled for revision r0p0. It is fixed in r0p1.
+
- ``ERRATA_V3_3701767``: This applies errata 3701767 workaround to Neoverse-V3
CPU. This needs to be enabled for revisions r0p0, r0p1, r0p2 of the CPU and
is still open.
@@ -882,6 +885,9 @@
- ``ERRATA_X4_2923985``: This applies errata 2923985 workaround to Cortex-X4
CPU. This needs to be enabled for revisions r0p0 and r0p1. It is fixed in r0p2.
+- ``ERRATA_X4_2957258``: This applies errata 2957258 workaround to Cortex-X4
+ CPU. This needs to be enabled for revisions r0p0 and r0p1. It is fixed in r0p2.
+
- ``ERRATA_X4_3076789``: This applies errata 3076789 workaround to Cortex-X4
CPU. This needs to be enabled for revisions r0p0 and r0p1. It is fixed in r0p2.
@@ -891,6 +897,9 @@
For Cortex-X925, the following errata build flags are defined :
+- ``ERRATA_X925_2963999``: This applies errata 2963999 workaround to Cortex-X925
+ CPU. This needs to be enabled for revision r0p0. It is fixed in r0p1.
+
- ``ERRATA_X925_3701747``: This applies errata 3701747 workaround to Cortex-X925
CPU. This needs to be enabled for revisions r0p0 and r0p1. It is still open.
@@ -1021,7 +1030,7 @@
For Cortex-A720_AE, the following errata build flags are defined :
- ``ERRATA_A720_AE_3699562``: This applies errata 3699562 workaround
- to Cortex-A715_AE CPU. This needs to be enabled for revisions r0p0.
+ to Cortex-A720_AE CPU. This needs to be enabled for revisions r0p0.
It is still open.
For Cortex-A725, the following errata build flags are defined :
diff --git a/docs/design/firmware-design.rst b/docs/design/firmware-design.rst
index 2ba54ea..cf8cbc7 100644
--- a/docs/design/firmware-design.rst
+++ b/docs/design/firmware-design.rst
@@ -247,7 +247,7 @@
- CPU initialization
- BL1 calls the ``reset_handler()`` function which in turn calls the CPU
+ BL1 calls the ``reset_handler`` macro/function which in turn calls the CPU
specific reset handler function (see the section: "CPU specific operations
framework").
@@ -1337,7 +1337,7 @@
TF-A implements a framework that allows CPU and platform ports to perform
actions very early after a CPU is released from reset in both the cold and warm
-boot paths. This is done by calling the ``reset_handler()`` function in both
+boot paths. This is done by calling the ``reset_handler`` macro/function in both
the BL1 and BL31 images. It in turn calls the platform and CPU specific reset
handling functions.
@@ -1481,7 +1481,9 @@
handling for that CPU and also any errata workarounds enabled by the platform.
It should be defined using the ``cpu_reset_func_{start,end}`` macros and its
-body may only clobber x0 to x14 with x14 being the cpu_rev parameter.
+body may only clobber x0 to x14 with x14 being the cpu_rev parameter. The cpu
+file should also include a call to ``cpu_reset_prologue`` at the start of the
+file for errata to work correctly.
CPU specific power down sequence
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1504,6 +1506,19 @@
perform platform specific operations during a power down sequence, for example
turning off CCI coherency during a cluster power down.
+Newer CPUs include a feature called "powerdown abandon". The feature is based on
+the observation that events like GIC wakeups have a high likelihood of happening
+while the core is in the middle of its powerdown sequence (at ``wfi``). Older
+cores will powerdown and immediately power back up when this happens. To save on
+the work and latency involved, the newer cores will "give up" mid way through if
+no context has been lost yet. This is possible as the powerdown operation is
+lengthy and a large part of it does not lose context.
+
+To cater for this possibility, the powerdown hook will be called a second time
+after a wakeup. The expectation is that the first call will operate as before,
+while the second call will undo anything the first call did. This should be done
+statelessly, for example by toggling the relevant bits.
+
CPU specific register reporting during crash
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2891,7 +2906,7 @@
--------------
-*Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.*
.. _SMCCC: https://developer.arm.com/docs/den0028/latest
.. _PSCI: https://developer.arm.com/documentation/den0022/latest/
diff --git a/docs/design/index.rst b/docs/design/index.rst
index 17ef756..f0ca540 100644
--- a/docs/design/index.rst
+++ b/docs/design/index.rst
@@ -12,9 +12,10 @@
interrupt-framework-design
psci-pd-tree
reset-design
+ console-framework
trusted-board-boot
trusted-board-boot-build
--------------
-*Copyright (c) 2019, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2025, Arm Limited. All rights reserved.*
diff --git a/docs/design_documents/rse.rst b/docs/design_documents/rse.rst
index 21e5fd4..d1a5b9e 100644
--- a/docs/design_documents/rse.rst
+++ b/docs/design_documents/rse.rst
@@ -25,9 +25,15 @@
-----------------------
The communication between RSE and other subsystems are primarily relying on the
-Message Handling Unit (MHU) module. The number of MHU interfaces between RSE
-and other cores is IMPDEF. Besides MHU other modules also could take part in
-the communication. RSE is capable of mapping the AP memory to its address space.
+Message Handling Unit (MHU) module.
+
+However, this is possible to use this communication protocol with a different
+mailbox than MHU, by setting the flag ``PLAT_MHU=NO_MHU`` and implementing the
+APIs given in the file: ``include/drivers/arm/rse_comms.h``.
+
+The number of MHU interfaces between RSE and other cores is IMPDEF. Besides MHU
+other modules also could take part in the communication. RSE is capable of
+mapping the AP memory to its address space.
Thereby either RSE core itself or a DMA engine if it is present, can move the
data between memory belonging to RSE or AP. In this way, a bigger amount of data
can be transferred in a short time.
@@ -812,3 +818,4 @@
*Copyright (c) 2023-2024, Arm Limited. All rights reserved.*
*Copyright (c) 2024, Linaro Limited. All rights reserved.*
+*Copyright (c) 2025, STMicroelectronics - All Rights Reserved*
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 5b83448..2b36fda 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -258,10 +258,6 @@
(also known as group 1 counters). These are implementation-defined counters,
and as such require additional platform configuration. Default is 0.
-- ``ENABLE_AMU_FCONF``: Enables configuration of the AMU through FCONF, which
- allows platforms with auxiliary counters to describe them via the
- ``HW_CONFIG`` device tree blob. Default is 0.
-
- ``ENABLE_ASSERTIONS``: This option controls whether or not calls to ``assert()``
are compiled out. For debug builds, this option defaults to 1, and calls to
``assert()`` are left in place. For release builds, this option defaults to 0
@@ -526,9 +522,11 @@
power domain dynamic power budgeting and limit the triggering of whole-rail
(i.e. clock chopping) responses to overcurrent conditions. Defaults to ``0``.
-- ``ENABLE_MPMM_FCONF``: Enables configuration of MPMM through FCONF, which
- allows platforms with cores supporting MPMM to describe them via the
- ``HW_CONFIG`` device tree blob. Default is 0.
+ - ``FEAT_PABANDON``: Boolean option to enable support for powerdown abandon on
+ Arm cores that support it (currently Gelas and Travis). Extends the PSCI
+ implementation to expect waking up after the terminal ``wfi``. Currently,
+ introduces a performance penalty. Once this is removed, this option will be
+ removed and the feature will be enabled by default. Defaults to ``0``.
- ``ENABLE_PIE``: Boolean option to enable Position Independent Executable(PIE)
support within generic code in TF-A. This option is currently only supported
@@ -1206,6 +1204,12 @@
implement this workaround due to the behaviour of the errata mentioned
in new SDEN document which will get published soon.
+- ``ERRATA_SME_POWER_DOWN``: Boolean option to disable SME (PSTATE.{ZA,SM}=0)
+ before power down and downgrade a suspend to power down request to a normal
+ suspend request. This is necessary when software running at lower ELs requests
+ power down without first clearing these bits. On affected cores, the CME
+ connected to it will reject its power down request. The default value is 0.
+
- ``RAS_TRAP_NS_ERR_REC_ACCESS``: This flag enables/disables the SCR_EL3.TERR
bit, to trap access to the RAS ERR and RAS ERX registers from lower ELs.
This flag is disabled by default.
diff --git a/docs/plat/arm/arm-build-options.rst b/docs/plat/arm/arm-build-options.rst
index a086a98..3fad566 100644
--- a/docs/plat/arm/arm-build-options.rst
+++ b/docs/plat/arm/arm-build-options.rst
@@ -137,7 +137,8 @@
---------------------
- ``FVP_TRUSTED_SRAM_SIZE``: Size (in kilobytes) of the Trusted SRAM region to
- utilize when building for the FVP platform. This option defaults to 256.
+ utilize when building for the FVP platform. This option defaults to 256 with
+ build option ENABLE_RME=0 and 384 for ENABLE_RME=1.
Arm Juno Build Options
----------------------
diff --git a/docs/plat/arm/fvp/fvp-build-options.rst b/docs/plat/arm/fvp/fvp-build-options.rst
index b0359fa..79dc0dc 100644
--- a/docs/plat/arm/fvp/fvp-build-options.rst
+++ b/docs/plat/arm/fvp/fvp-build-options.rst
@@ -46,6 +46,16 @@
is ``0``, which means the redistributor pages of all CPU cores are marked
as read and write.
+- ``INITRD_SIZE`` : Enable the insertion of initrd properties to the device
+ tree blob at build time. Takes an initrd size value in hex format
+
+- ``INITRD_PATH`` : Enable the insertion of initrd properties to the device tree
+ blob at build time. Takes a path to an initrd file. Can be used as an
+ alternative to ``INITRD_SIZE``. ``INITRD_SIZE`` takes precedence over
+ ``INITRD_PATH`` if both values are provided.
+
+- ``INITRD_BASE`` : Provide the preloaded initrd base address in memory (hex format).
+
--------------
-*Copyright (c) 2019-2024, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2025, Arm Limited. All rights reserved.*
diff --git a/docs/plat/arm/fvp/fvp-specific-configs.rst b/docs/plat/arm/fvp/fvp-specific-configs.rst
index 63b3c31..0f51e4b 100644
--- a/docs/plat/arm/fvp/fvp-specific-configs.rst
+++ b/docs/plat/arm/fvp/fvp-specific-configs.rst
@@ -73,85 +73,122 @@
The address provided to the FVP must match the ``EL3_PAYLOAD_BASE`` address
used when building TF-A.
-Booting a preloaded kernel image (Base FVP)
--------------------------------------------
+Booting a kernel image in BL33
+------------------------------
-The following example uses a simplified boot flow by directly jumping from the
-TF-A to the Linux kernel, which will use a ramdisk as filesystem. This can be
-useful if both the kernel and the device tree blob (DTB) are already present in
-memory (like in FVP).
+TF-A can boot a Linux kernel, which uses a ramdisk as a filesystem. The
+required initrd properties are injected in to the device tree blob (DTB) at
+build time.
-For example, if the kernel is loaded at ``0x80080000`` and the DTB is loaded at
-address ``0x82000000``, the firmware can be built like this:
+Kernel image packaged in fip as a BL33 image
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A Linux kernel image can be packaged in the fip as a BL33 image and then
+booted in TF-A.
+
+For example, the firmware can be built as:
.. code:: shell
- CROSS_COMPILE=aarch64-none-elf- \
make PLAT=fvp DEBUG=1 \
- RESET_TO_BL31=1 \
- ARM_LINUX_KERNEL_AS_BL33=1 \
- PRELOADED_BL33_BASE=0x80080000 \
- ARM_PRELOADED_DTB_BASE=0x82000000 \
+ ARM_LINUX_KERNEL_AS_BL33 \
+ BL33=<path-to-kernel-binary> \
+ INITRD_SIZE=0x8000000 \
all fip
+The options ``INITRD_SIZE`` or ``INITRD_PATH`` triggers the insertion of initrd
+properties in to the DTB. ``INITRD_BASE`` is also required but a default value
+is set by the FVP platform.
+
+The options available here are:
+
+::
+
-Now, it is needed to modify the DTB so that the kernel knows the address of the
-ramdisk. The following script generates a patched DTB from the provided one,
-assuming that the ramdisk is loaded at address ``0x84000000``. Note that this
-script assumes that the user is using a ramdisk image prepared for U-Boot, like
-the ones provided by Linaro. If using a ramdisk without this header,the ``0x40``
-offset in ``INITRD_START`` has to be removed.
+ INITRD_BASE: Set the initrd base address in memory. Defaults to 0x90000000 in FVP.
+ INITRD_SIZE: Set the initrd size in dec or hex format. Hex format must precede with '0x'.
+ INITRD_PATH: Provide an initrd path for the build time to determine its exact size.
-.. code:: bash
+Users can provide either ``INITRD_SIZE`` or ``INITRD_PATH`` to set the initrd
+size value. ``INITRD_SIZE`` takes prioty over ``INITRD_PATH``.
- #!/bin/bash
+Now the fvp binary can be run as:
- # Path to the input DTB
- KERNEL_DTB=<path-to>/<fdt>
- # Path to the output DTB
- PATCHED_KERNEL_DTB=<path-to>/<patched-fdt>
- # Base address of the ramdisk
- INITRD_BASE=0x84000000
- # Path to the ramdisk
- INITRD=<path-to>/<ramdisk.img>
+.. code:: shell
+
+ <path-to>/FVP_Base_AEMv8A-AEMv8A \
+ -C bp.secureflashloader.fname=<path-to>/bl1.bin \
+ -C bp.flashloader0.fname=<path-to>/fip.bin \
+ --data cluster0.cpu0="<path-to>/<initrd.bin>"@0x90000000
+
+.. note::
+ Providing a higher value for an initrd size than the actual size of the file
+ is supported but it will trigger a non-breaking "Initramfs unpacking failed"
+ error by the kernel at runtime. This error can be ignored because initrd's
+ can be stacked one after another, when the kernel unpacks the first initrd it
+ looks for another in the extra space which it won't find, hence the error.
- # Skip uboot header (64 bytes)
- INITRD_START=$(printf "0x%x" $((${INITRD_BASE} + 0x40)) )
- INITRD_SIZE=$(stat -Lc %s ${INITRD})
- INITRD_END=$(printf "0x%x" $((${INITRD_BASE} + ${INITRD_SIZE})) )
+Preloaded kernel image - Normal flow
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- CHOSEN_NODE=$(echo \
- "/ { \
- chosen { \
- linux,initrd-start = <${INITRD_START}>; \
- linux,initrd-end = <${INITRD_END}>; \
- }; \
- };")
+The following example uses a simplified boot flow to boot a Linux kernel
+using TF-A. This can be useful if the kernel is already present in memory
+(like in FVP).
+
+For example, if the kernel is loaded at ``0x80080000`` the firmware can be
+built like this:
+
+.. code:: shell
- echo $(dtc -O dts -I dtb ${KERNEL_DTB}) ${CHOSEN_NODE} | \
- dtc -O dtb -o ${PATCHED_KERNEL_DTB} -
+ make PLAT=fvp DEBUG=1 \
+ ARM_LINUX_KERNEL_AS_BL33=1 \
+ PRELOADED_BL33_BASE=0x80080000 \
+ INITRD_SIZE=0x8000000 \
+ all fip
-And the FVP binary can be run with the following command:
+Now the FVP binary can be run with the following command:
.. code:: shell
<path-to>/FVP_Base_AEMv8A-AEMv8A \
- -C pctl.startup=0.0.0.0 \
- -C bp.secure_memory=1 \
- -C cluster0.NUM_CORES=4 \
- -C cluster1.NUM_CORES=4 \
- -C cache_state_modelled=1 \
- -C cluster0.cpu0.RVBAR=0x04001000 \
- -C cluster0.cpu1.RVBAR=0x04001000 \
- -C cluster0.cpu2.RVBAR=0x04001000 \
- -C cluster0.cpu3.RVBAR=0x04001000 \
- -C cluster1.cpu0.RVBAR=0x04001000 \
- -C cluster1.cpu1.RVBAR=0x04001000 \
- -C cluster1.cpu2.RVBAR=0x04001000 \
- -C cluster1.cpu3.RVBAR=0x04001000 \
- --data cluster0.cpu0="<path-to>/bl31.bin"@0x04001000 \
- --data cluster0.cpu0="<path-to>/<patched-fdt>"@0x82000000 \
+ -C bp.secureflashloader.fname=<path-to>/bl1.bin \
+ -C bp.flashloader0.fname=<path-to>/fip.bin \
--data cluster0.cpu0="<path-to>/<kernel-binary>"@0x80080000 \
- --data cluster0.cpu0="<path-to>/<ramdisk.img>"@0x84000000
+ --data cluster0.cpu0="<path-to>/<initrd.bin>"@0x90000000
+
+Preloaded kernel image - Reset to BL31
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+We can also boot a Linux kernel by jumping directly to BL31 ``RESET_TO_BL31=1``.
+This requires preloading a DTB into memory. We can inject the initrd start and
+end properties into the DTB (HW_CONFIG) at build time which is then stored by
+TF-A in ``build/fvp/<build-type>/fdts/`` directory.
+
+For example, we can build the firmware as:
+
+.. code:: shell
+
+ make PLAT=fvp DEBUG=1 \
+ RESET_TO_BL31=1 \
+ ARM_LINUX_KERNEL_AS_BL33=1 \
+ PRELOADED_BL33_BASE=0x80080000 \
+ ARM_PRELOADED_DTB_BASE=0x87F00000 \
+ INITRD_BASE=0x88000000 \
+ INITRD_PATH=<path-to>/initrd.bin
+
+Now we can run the binary as:
+
+.. code:: shell
+
+ <path-to>/FVP_Base_AEMv8A-AEMv8A \
+ -C cluster0.NUM_CORES=4 \
+ -C cluster0.cpu0.RVBAR=0x04001000 \
+ -C cluster0.cpu1.RVBAR=0x04001000 \
+ -C cluster0.cpu2.RVBAR=0x04001000 \
+ -C cluster0.cpu3.RVBAR=0x04001000 \
+ --data cluster0.cpu0="<path-to>/bl31.bin"@0x04001000 \
+ --data cluster0.cpu0="<path-to>/<kernel-binary>"@0x80080000 \
+ --data cluster0.cpu0="<path-to>/<initrd.bin>"@0x88000000 \
+ --data cluster0.cpu0="<path-to>/fdts/fvp-base-gicv3-psci.dtb"@87F00000
Obtaining the Flattened Device Trees
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/docs/plat/arm/fvp/fvp-support.rst b/docs/plat/arm/fvp/fvp-support.rst
index ad76cf1..0ce1905 100644
--- a/docs/plat/arm/fvp/fvp-support.rst
+++ b/docs/plat/arm/fvp/fvp-support.rst
@@ -9,24 +9,22 @@
(64-bit host machine only).
.. note::
- The FVP models used are Version 11.26 Build 11, unless otherwise stated.
+ The FVP models used are version 11.28 Build 23.
- ``FVP_Base_AEMvA-AEMvA``
- ``FVP_Base_RevC-2xAEMvA``
-- ``FVP_Base_Cortex-A32x4``
-- ``FVP_Base_Cortex-A35x4``
-- ``FVP_Base_Cortex-A53x4``
+- ``FVP_Base_Cortex-A32``
+- ``FVP_Base_Cortex-A35``
+- ``FVP_Base_Cortex-A53``
- ``FVP_Base_Cortex-A55``
- ``FVP_Base_Cortex-A57x1-A53x1``
- ``FVP_Base_Cortex-A57x2-A53x4``
-- ``FVP_Base_Cortex-A57x4``
+- ``FVP_Base_Cortex-A57``
- ``FVP_Base_Cortex-A57x4-A53x4``
-- ``FVP_Base_Cortex-A65`` (Version 11.24/24)
-- ``FVP_Base_Cortex-A65AE`` (Version 11.24/24)
-- ``FVP_Base_Cortex-A710``
-- ``FVP_Base_Cortex-A72x4``
-- ``FVP_Base_Cortex-A72x4-A53x4``
-- ``FVP_Base_Cortex-A73x4``
+- ``FVP_Base_Cortex-A65``
+- ``FVP_Base_Cortex-A65AE``
+- ``FVP_Base_Cortex-A72``
+- ``FVP_Base_Cortex-A73``
- ``FVP_Base_Cortex-A73x4-A53x4``
- ``FVP_Base_Cortex-A75``
- ``FVP_Base_Cortex-A76``
@@ -35,17 +33,17 @@
- ``FVP_Base_Cortex-A78``
- ``FVP_Base_Cortex-A78AE``
- ``FVP_Base_Cortex-A78C``
+- ``FVP_Base_Cortex-A710``
- ``FVP_Base_Cortex-X2``
-- ``FVP_Base_Neoverse-E1`` (Version 11.24/24)
+- ``FVP_Base_Cortex-X4``
+- ``FVP_Base_Cortex-X925``
+- ``FVP_Base_Neoverse-E1``
- ``FVP_Base_Neoverse-N1``
- ``FVP_Base_Neoverse-N2``
- ``FVP_Base_Neoverse-V1``
- ``FVP_BaseR_AEMv8R``
-- ``FVP_Morello`` (Version 0.11/33)
-- ``FVP_RD_V1``
-- ``FVP_RD_1_AE`` (Version 11.27/20)
-- ``FVP_TC3`` (Version 11.26/16)
-- ``FVP_TC4`` (Version 0.0/8404)
+- ``FVP_RD_1_AE``
+- ``FVP_TC4``
The latest version of the AArch32 build of TF-A has been tested on the
following Arm FVPs without shifted affinities, and that do not support threaded
@@ -53,7 +51,7 @@
- ``FVP_Base_AEMvA``
- ``FVP_Base_AEMvA-AEMvA``
-- ``FVP_Base_Cortex-A32x4``
+- ``FVP_Base_Cortex-A32``
.. note::
The ``FVP_Base_RevC-2xAEMv8A`` FVP only supports shifted affinities, which
@@ -94,7 +92,7 @@
--------------
-*Copyright (c) 2019-2024, Arm Limited. All rights reserved.*
+*Copyright (c) 2019-2025, Arm Limited. All rights reserved.*
.. _Arm's website: `FVP models`_
.. _FVP models: https://developer.arm.com/products/system-design/fixed-virtual-platforms
diff --git a/docs/plat/rockchip.rst b/docs/plat/rockchip.rst
index 384cd73..016bed7 100644
--- a/docs/plat/rockchip.rst
+++ b/docs/plat/rockchip.rst
@@ -11,6 +11,7 @@
- rk3368: Octa-Core Cortex-A53
- rk3399: Hexa-Core Cortex-A53/A72
- rk3566/rk3568: Quad-Core Cortex-A55
+- rk3576: Octa-Core Cortex-A53/A72
- rk3588: Octa-Core Cortex-A55/A76
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index 6d03f44..0f0dedd 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -1001,7 +1001,7 @@
This function returns the size normal-world DCE of the platform.
Function : plat_drtm_get_imp_def_dlme_region_size()
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
@@ -1012,7 +1012,7 @@
of the platform.
Function : plat_drtm_get_tcb_hash_table_size()
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
@@ -1021,8 +1021,18 @@
This function returns the size of TCB hash table of the platform.
+Function : plat_drtm_get_acpi_tables_region_size()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : void
+ Return : uint64_t
+
+This function returns the size of ACPI tables region of the platform.
+
Function : plat_drtm_get_tcb_hash_features()
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
@@ -1033,6 +1043,17 @@
platform.
For more details see section 3.3 Table 6 of `DRTM`_ specification.
+Function : plat_drtm_get_dlme_img_auth_features()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+ Argument : void
+ Return : uint64_t
+
+This function returns the DLME image authentication features.
+For more details see section 3.3 Table 6 of `DRTM`_ specification.
+
Function : plat_drtm_validate_ns_region()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2220,10 +2241,10 @@
Argument : void
Return : void
-The purpose of this function is allow the platform to perform any BL31 runtime
-setup just prior to BL31 exit during cold boot. The default weak
-implementation of this function will invoke ``console_switch_state()`` to switch
-console output to consoles marked for use in the ``runtime`` state.
+The purpose of this function is to allow the platform to perform any BL31 runtime
+setup just prior to BL31 exit during cold boot. The default weak implementation
+of this function is empty. Any platform that needs to perform additional runtime
+setup, before BL31 exits, will need to override this function.
Function : bl31_plat_get_next_image_ep_info() [mandatory]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2897,23 +2918,27 @@
data, for example in DRAM. The Distributor can then be powered down using an
implementation-defined sequence.
-plat_psci_ops.pwr_domain_pwr_down_wfi()
+plat_psci_ops.pwr_domain_pwr_down()
.......................................
This is an optional function and, if implemented, is expected to perform
-platform specific actions including the ``wfi`` invocation which allows the
-CPU to powerdown. Since this function is invoked outside the PSCI locks,
-the actions performed in this hook must be local to the CPU or the platform
-must ensure that races between multiple CPUs cannot occur.
+platform specific actions before the CPU is powered down. Since this function is
+invoked outside the PSCI locks, the actions performed in this hook must be local
+to the CPU or the platform must ensure that races between multiple CPUs cannot
+occur.
The ``target_state`` has a similar meaning as described in the ``pwr_domain_off()``
operation and it encodes the platform coordinated target local power states for
-the CPU power domain and its parent power domain levels. This function must
-not return back to the caller (by calling wfi in an infinite loop to ensure
-some CPUs power down mitigations work properly).
+the CPU power domain and its parent power domain levels.
-If this function is not implemented by the platform, PSCI generic
-implementation invokes ``psci_power_down_wfi()`` for power down.
+It is preferred that this function returns. The caller will invoke
+``psci_power_down_wfi()`` to powerdown the CPU, mitigate any powerdown errata,
+and handle any wakeups that may arise. Previously, this function did not return
+and instead called ``wfi`` (in an infinite loop) directly. This is still
+possible on platforms where this is guaranteed to be terminal, however, it is
+strongly discouraged going forward.
+
+Previously this function was called ``pwr_domain_pwr_down_wfi()``.
plat_psci_ops.pwr_domain_on_finish()
....................................
@@ -2965,14 +2990,16 @@
This function is called by PSCI implementation in response to a ``SYSTEM_OFF``
call. It performs the platform-specific system poweroff sequence after
-notifying the Secure Payload Dispatcher.
+notifying the Secure Payload Dispatcher. The caller will call ``wfi`` if this
+function returns, similar to `plat_psci_ops.pwr_domain_pwr_down()`_.
plat_psci_ops.system_reset()
............................
This function is called by PSCI implementation in response to a ``SYSTEM_RESET``
call. It performs the platform-specific system reset sequence after
-notifying the Secure Payload Dispatcher.
+notifying the Secure Payload Dispatcher. The caller will call ``wfi`` if this
+function returns, similar to `plat_psci_ops.pwr_domain_pwr_down()`_.
plat_psci_ops.validate_power_state()
....................................
@@ -3060,7 +3087,8 @@
function must return ``PSCI_E_NOT_SUPPORTED``. For architectural
resets, all failures must return ``PSCI_E_INVALID_PARAMETERS``
and vendor reset can return other PSCI error codes as defined
-in `PSCI`_. On success this function will not return.
+in `PSCI`_. If this function returns success, the caller will call
+``wfi`` similar to `plat_psci_ops.pwr_domain_pwr_down()`_.
plat_psci_ops.write_mem_protect()
.................................
@@ -3296,6 +3324,21 @@
(``GICD_IGRPMODRn``) is read to figure out whether the interrupt is configured
as Group 0 secure interrupt, Group 1 secure interrupt or Group 1 NS interrupt.
+Registering a console
+---------------------
+
+Platforms will need to implement the TF-A console framework to register and use
+a console for visual data output in TF-A. These can be used for data output during
+the different stages of the firmware boot process and also for debugging purposes.
+
+The console framework can be used to output data on to a console using a number of
+TF-A supported UARTs. Multiple consoles can be registered at the same time with
+different output scopes (BOOT, RUNTIME, CRASH) so that data can be displayed on
+their respective consoles without unnecessary cluttering of a single console.
+
+Information for registering a console can be found in the :ref:`Console Framework` section
+of the :ref:`System Design` documentation.
+
Common helper functions
-----------------------
Function : elx_panic()
@@ -3416,6 +3459,18 @@
External Abort handling and RAS Support
---------------------------------------
+If any cores on the platform support powerdown abandon (i.e. ``FEAT_PABANDON``
+is set, check the "Core powerup and powerdown sequence" in their TRMs), then
+these functions should be able to handle being called with power domains off and
+after the powerdown ``wfi``. In other words it may run after a call to
+``pwr_domain_suspend()`` and before a call to ``pwr_domain_suspend_finish()``
+(and their power off counterparts).
+
+Should this not be desirable, or if there is no powerdown abandon support, then
+RAS errors should be masked by writing any relevant error records in any
+powerdown hooks to prevent deadlocks due to a RAS error after the point of no
+return. See the core's TRM for further information.
+
Function : plat_ea_handler
~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -3700,7 +3755,7 @@
--------------
-*Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.*
.. _PSCI: https://developer.arm.com/documentation/den0022/latest/
.. _Arm Generic Interrupt Controller version 2.0 (GICv2): http://infocenter.arm.com/help/topic/com.arm.doc.ihi0048b/index.html
diff --git a/docs/tools/memory-layout-tool.rst b/docs/tools/memory-layout-tool.rst
index 8874bd7..d9c358d 100644
--- a/docs/tools/memory-layout-tool.rst
+++ b/docs/tools/memory-layout-tool.rst
@@ -23,7 +23,7 @@
.. code:: shell
- poetry install --with memory
+ poetry install --no-root
#. Verify that the tool runs in the installed virtual environment
@@ -231,6 +231,6 @@
--------------
-*Copyright (c) 2023, Arm Limited. All rights reserved.*
+*Copyright (c) 2023-2025, Arm Limited. All rights reserved.*
.. _Poetry: https://python-poetry.org/docs/
diff --git a/drivers/arm/css/scp/css_pm_scmi.c b/drivers/arm/css/scp/css_pm_scmi.c
index fbcbdc7..b310ff4 100644
--- a/drivers/arm/css/scp/css_pm_scmi.c
+++ b/drivers/arm/css/scp/css_pm_scmi.c
@@ -298,7 +298,7 @@
#endif
}
-void __dead2 css_scp_system_off(int state)
+void css_scp_system_off(int state)
{
int ret;
@@ -339,16 +339,13 @@
}
/* Powerdown of primary core */
- psci_pwrdown_cpu(PLAT_MAX_PWR_LVL);
- wfi();
- ERROR("CSS set power state: operation not handled.\n");
- panic();
+ psci_pwrdown_cpu_start(PLAT_MAX_PWR_LVL);
}
/*
* Helper function to shutdown the system via SCMI.
*/
-void __dead2 css_scp_sys_shutdown(void)
+void css_scp_sys_shutdown(void)
{
css_scp_system_off(SCMI_SYS_PWR_SHUTDOWN);
}
@@ -356,7 +353,7 @@
/*
* Helper function to reset the system via SCMI.
*/
-void __dead2 css_scp_sys_reboot(void)
+void css_scp_sys_reboot(void)
{
css_scp_system_off(SCMI_SYS_PWR_COLD_RESET);
}
@@ -472,12 +469,8 @@
return PSCI_E_INVALID_PARAMS;
css_scp_system_off(SCMI_SYS_PWR_WARM_RESET);
- /*
- * css_scp_system_off cannot return (it is a __dead function),
- * but css_system_reset2 has to return some value, even in
- * this case.
- */
- return 0;
+ /* return SUCCESS to finish the powerdown */
+ return PSCI_E_SUCCESS;
}
#if PROGRAMMABLE_RESET_ADDRESS
diff --git a/drivers/arm/css/scp/css_pm_scpi.c b/drivers/arm/css/scp/css_pm_scpi.c
index b4019ce..02be070 100644
--- a/drivers/arm/css/scp/css_pm_scpi.c
+++ b/drivers/arm/css/scp/css_pm_scpi.c
@@ -117,7 +117,7 @@
/*
* Helper function to shutdown the system via SCPI.
*/
-void __dead2 css_scp_sys_shutdown(void)
+void css_scp_sys_shutdown(void)
{
uint32_t response;
@@ -134,15 +134,12 @@
ERROR("CSS System Off: SCP error %u.\n", response);
panic();
}
- wfi();
- ERROR("CSS System Off: operation not handled.\n");
- panic();
}
/*
* Helper function to reset the system via SCPI.
*/
-void __dead2 css_scp_sys_reboot(void)
+void css_scp_sys_reboot(void)
{
uint32_t response;
@@ -159,7 +156,4 @@
ERROR("CSS System Reset: SCP error %u.\n", response);
panic();
}
- wfi();
- ERROR("CSS System Reset: operation not handled.\n");
- panic();
}
diff --git a/drivers/arm/gic/v3/gic600_multichip.c b/drivers/arm/gic/v3/gic600_multichip.c
index 5e44aa9..6e9567e 100644
--- a/drivers/arm/gic/v3/gic600_multichip.c
+++ b/drivers/arm/gic/v3/gic600_multichip.c
@@ -322,12 +322,40 @@
}
/*******************************************************************************
+ * Initialize GIC-600 and GIC-700 Multichip operation in LCA mode by setting up
+ * the routing table first.
+ ******************************************************************************/
+static void gic600_multichip_lca_init(
+ struct gic600_multichip_data *multichip_data)
+{
+ unsigned int i, j;
+ unsigned int rt_owner = multichip_data->rt_owner;
+
+ for (i = 0; i < multichip_data->chip_count; i++) {
+ for (j = 0; j < multichip_data->chip_count; j++) {
+ INFO("RT(LCA): CHIP%u -> CHIP%u 0x%lx\n", i, j,
+ multichip_data->chip_addrs[i][j]);
+ set_gicd_chipr_n(multichip_data->base_addrs[i], j,
+ multichip_data->chip_addrs[i][j],
+ multichip_data->spi_ids[j].spi_id_min,
+ multichip_data->spi_ids[j].spi_id_max);
+ }
+ }
+
+ /* Initialize the GICD which is marked as routing table owner last */
+ set_gicd_dchipr_rt_owner(multichip_data->base_addrs[rt_owner],
+ rt_owner);
+}
+
+/*******************************************************************************
* Initialize GIC-600 and GIC-700 Multichip operation.
******************************************************************************/
void gic600_multichip_init(struct gic600_multichip_data *multichip_data)
{
unsigned int i;
- uint32_t gicd_iidr_val = gicd_read_iidr(multichip_data->rt_owner_base);
+ unsigned int rt_owner = multichip_data->rt_owner;
+ uint32_t gicd_iidr_val =
+ gicd_read_iidr(multichip_data->base_addrs[rt_owner]);
if ((gicd_iidr_val & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) {
gic600_multichip_validate_data(multichip_data);
@@ -341,16 +369,16 @@
* Ensure that G0/G1S/G1NS interrupts are disabled. This also ensures
* that GIC-600 Multichip configuration is done first.
*/
- if ((gicd_read_ctlr(multichip_data->rt_owner_base) &
- (CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT |
- CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) {
+ if ((gicd_read_ctlr(multichip_data->base_addrs[rt_owner]) &
+ (CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT |
+ CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) {
ERROR("GICD_CTLR group interrupts are either enabled or have "
"pending writes.\n");
panic();
}
/* Ensure that the routing table owner is in disconnected state */
- if (((read_gicd_chipsr(multichip_data->rt_owner_base) &
+ if (((read_gicd_chipsr(multichip_data->base_addrs[rt_owner]) &
GICD_CHIPSR_RTS_MASK) >> GICD_CHIPSR_RTS_SHIFT) !=
GICD_CHIPSR_RTS_STATE_DISCONNECTED) {
ERROR("GIC-600 routing table owner is not in disconnected "
@@ -358,25 +386,34 @@
panic();
}
- /* Initialize the GICD which is marked as routing table owner first */
- set_gicd_dchipr_rt_owner(multichip_data->rt_owner_base,
- multichip_data->rt_owner);
+ /* If LCA is not enabled */
+ if ((read_gicd_cfgid(multichip_data->base_addrs[rt_owner]) &
+ GICD_CFGID_LCA_BIT) == 0) {
+ /*
+ * Initialize the GICD which is marked as routing table
+ * owner first.
+ */
+ set_gicd_dchipr_rt_owner(multichip_data->base_addrs[rt_owner],
+ rt_owner);
- set_gicd_chipr_n(multichip_data->rt_owner_base, multichip_data->rt_owner,
- multichip_data->chip_addrs[multichip_data->rt_owner],
- multichip_data->
- spi_ids[multichip_data->rt_owner].spi_id_min,
- multichip_data->
- spi_ids[multichip_data->rt_owner].spi_id_max);
+ set_gicd_chipr_n(multichip_data->base_addrs[rt_owner], rt_owner,
+ multichip_data->chip_addrs[rt_owner][rt_owner],
+ multichip_data->spi_ids[rt_owner].spi_id_min,
+ multichip_data->spi_ids[rt_owner].spi_id_max);
- for (i = 0; i < multichip_data->chip_count; i++) {
- if (i == multichip_data->rt_owner)
- continue;
-
- set_gicd_chipr_n(multichip_data->rt_owner_base, i,
- multichip_data->chip_addrs[i],
+ for (i = 0; i < multichip_data->chip_count; i++) {
+ if (i == rt_owner)
+ continue;
+ set_gicd_chipr_n(
+ multichip_data->base_addrs[rt_owner], i,
+ multichip_data->chip_addrs[rt_owner][i],
multichip_data->spi_ids[i].spi_id_min,
multichip_data->spi_ids[i].spi_id_max);
+ }
+ } else {
+ /* If LCA is enabled */
+ INFO("GIC Local chip addressing is enabled\n");
+ gic600_multichip_lca_init(multichip_data);
}
plat_gic_multichip_data = multichip_data;
diff --git a/drivers/arm/gic/v3/gic600_multichip_private.h b/drivers/arm/gic/v3/gic600_multichip_private.h
index fd1cb57..33030b3 100644
--- a/drivers/arm/gic/v3/gic600_multichip_private.h
+++ b/drivers/arm/gic/v3/gic600_multichip_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2023, ARM Limited. All rights reserved.
+ * Copyright (c) 2019-2024, ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -15,12 +15,14 @@
#define GICD_CHIPSR U(0xC000)
#define GICD_DCHIPR U(0xC004)
#define GICD_CHIPR U(0xC008)
+#define GICD_CFGID U(0xF000)
/* GIC600 GICD multichip related masks */
#define GICD_CHIPRx_PUP_BIT BIT_64(1)
#define GICD_CHIPRx_SOCKET_STATE BIT_64(0)
#define GICD_DCHIPR_PUP_BIT BIT_32(0)
#define GICD_CHIPSR_RTS_MASK (BIT_32(4) | BIT_32(5))
+#define GICD_CFGID_LCA_BIT BIT_64(21)
/* GIC600 GICD multichip related shifts */
#define GICD_CHIPRx_ADDR_SHIFT 16
@@ -98,6 +100,11 @@
return mmio_read_32(base + GICD_CHIPSR);
}
+static inline uint64_t read_gicd_cfgid(uintptr_t base)
+{
+ return mmio_read_64(base + GICD_CFGID);
+}
+
static inline void write_gicd_dchipr(uintptr_t base, uint32_t val)
{
mmio_write_32(base + GICD_DCHIPR, val);
diff --git a/drivers/arm/rse/rse_comms.c b/drivers/arm/rse/rse_comms.c
index cfc5a83..48023bc 100644
--- a/drivers/arm/rse/rse_comms.c
+++ b/drivers/arm/rse/rse_comms.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -8,7 +8,6 @@
#include <string.h>
#include <common/debug.h>
-#include <drivers/arm/mhu.h>
#include <drivers/arm/rse_comms.h>
#include <psa/client.h>
#include <rse_comms_protocol.h>
@@ -24,7 +23,7 @@
static uint8_t select_protocol_version(const psa_invec *in_vec, size_t in_len,
const psa_outvec *out_vec, size_t out_len)
{
- size_t comms_mhu_msg_size;
+ size_t comms_mbx_msg_size;
size_t comms_embed_msg_min_size;
size_t comms_embed_reply_min_size;
size_t in_size_total = 0;
@@ -38,7 +37,7 @@
out_size_total += out_vec[i].len;
}
- comms_mhu_msg_size = mhu_get_max_message_size();
+ comms_mbx_msg_size = rse_mbx_get_max_message_size();
comms_embed_msg_min_size = sizeof(struct serialized_rse_comms_header_t) +
sizeof(struct rse_embed_msg_t) -
@@ -49,9 +48,9 @@
PLAT_RSE_COMMS_PAYLOAD_MAX_SIZE;
/* Use embed if we can pack into one message and reply, else use
- * pointer_access. The underlying MHU transport protocol uses a
+ * pointer_access. The underlying mailbox transport protocol uses a
* single uint32_t to track the length, so the amount of data that
- * can be in a message is 4 bytes less than mhu_get_max_message_size
+ * can be in a message is 4 bytes less than rse_mbx_get_max_message_size
* reports.
*
* TODO tune this with real performance numbers, it's possible a
@@ -60,9 +59,9 @@
* pointers.
*/
if ((comms_embed_msg_min_size + in_size_total >
- comms_mhu_msg_size - sizeof(uint32_t)) ||
+ comms_mbx_msg_size - sizeof(uint32_t)) ||
(comms_embed_reply_min_size + out_size_total >
- comms_mhu_msg_size - sizeof(uint32_t))) {
+ comms_mbx_msg_size - sizeof(uint32_t))) {
return RSE_COMMS_PROTOCOL_POINTER_ACCESS;
} else {
return RSE_COMMS_PROTOCOL_EMBED;
@@ -76,7 +75,7 @@
* functions not being reentrant becomes a problem.
*/
static union rse_comms_io_buffer_t io_buf;
- enum mhu_error_t err;
+ int err;
psa_status_t status;
static uint8_t seq_num = 1U;
size_t msg_size;
@@ -109,8 +108,8 @@
VERBOSE("in_vec[%lu].buf=%p\n", idx, (void *)in_vec[idx].base);
}
- err = mhu_send_data((uint8_t *)&io_buf.msg, msg_size);
- if (err != MHU_ERR_NONE) {
+ err = rse_mbx_send_data((uint8_t *)&io_buf.msg, msg_size);
+ if (err != 0) {
return PSA_ERROR_COMMUNICATION_FAILURE;
}
@@ -122,8 +121,8 @@
memset(&io_buf.msg, 0xA5, msg_size);
#endif
- err = mhu_receive_data((uint8_t *)&io_buf.reply, &reply_size);
- if (err != MHU_ERR_NONE) {
+ err = rse_mbx_receive_data((uint8_t *)&io_buf.reply, &reply_size);
+ if (err != 0) {
return PSA_ERROR_COMMUNICATION_FAILURE;
}
@@ -144,37 +143,10 @@
VERBOSE("out_vec[%lu].buf=%p\n", idx, (void *)out_vec[idx].base);
}
- /* Clear the MHU message buffer to remove assets from memory */
+ /* Clear the mailbox message buffer to remove assets from memory */
memset(&io_buf, 0x0, sizeof(io_buf));
seq_num++;
return return_val;
}
-
-int rse_comms_init(uintptr_t mhu_sender_base, uintptr_t mhu_receiver_base)
-{
- enum mhu_error_t err;
-
- err = mhu_init_sender(mhu_sender_base);
- if (err != MHU_ERR_NONE) {
- if (err == MHU_ERR_ALREADY_INIT) {
- INFO("[RSE-COMMS] Host to RSE MHU driver already initialized\n");
- } else {
- ERROR("[RSE-COMMS] Host to RSE MHU driver initialization failed: %d\n", err);
- return -1;
- }
- }
-
- err = mhu_init_receiver(mhu_receiver_base);
- if (err != MHU_ERR_NONE) {
- if (err == MHU_ERR_ALREADY_INIT) {
- INFO("[RSE-COMMS] RSE to Host MHU driver already initialized\n");
- } else {
- ERROR("[RSE-COMMS] RSE to Host MHU driver initialization failed: %d\n", err);
- return -1;
- }
- }
-
- return 0;
-}
diff --git a/drivers/arm/rse/rse_comms.mk b/drivers/arm/rse/rse_comms.mk
index 3b87fe2..743e978 100644
--- a/drivers/arm/rse/rse_comms.mk
+++ b/drivers/arm/rse/rse_comms.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2022-2024, Arm Limited. All rights reserved.
+# Copyright (c) 2022-2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -13,15 +13,16 @@
rse_comms_protocol_pointer_access.c \
)
-# Default to MHUv2 if PLAT_MHU_VERSION undefined
-PLAT_MHU_VERSION ?= 2
+# Default to MHUv2 if PLAT_MHU undefined
+PLAT_MHU ?= MHUv2
-ifeq (${PLAT_MHU_VERSION}, 3)
+ifneq (${PLAT_MHU}, NO_MHU)
+ifeq (${PLAT_MHU}, MHUv3)
RSE_COMMS_SOURCES += $(addprefix drivers/arm/mhu/, \
mhu_v3_x.c \
mhu_wrapper_v3_x.c \
)
-else ifeq (${PLAT_MHU_VERSION}, 2)
+else ifeq (${PLAT_MHU}, MHUv2)
RSE_COMMS_SOURCES += $(addprefix drivers/arm/mhu/, \
mhu_v2_x.c \
mhu_wrapper_v2_x.c \
@@ -30,6 +31,12 @@
$(error Unsupported MHU version)
endif
+RSE_COMMS_SOURCES += $(addprefix drivers/arm/rse/, \
+ rse_comms_mhu.c \
+ )
+
+PLAT_INCLUDES += -Idrivers/arm/mhu
+endif
+
PLAT_INCLUDES += -Idrivers/arm/rse \
- -Idrivers/arm/mhu \
-Iinclude/lib/psa
diff --git a/drivers/arm/rse/rse_comms_mhu.c b/drivers/arm/rse/rse_comms_mhu.c
new file mode 100644
index 0000000..8032393
--- /dev/null
+++ b/drivers/arm/rse/rse_comms_mhu.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <drivers/arm/mhu.h>
+#include <drivers/arm/rse_comms.h>
+
+size_t rse_mbx_get_max_message_size(void)
+{
+ return mhu_get_max_message_size();
+}
+
+int rse_mbx_send_data(const uint8_t *send_buffer, size_t size)
+{
+ enum mhu_error_t err = mhu_send_data(send_buffer, size);
+
+ if (err != MHU_ERR_NONE) {
+ ERROR("mhu_send_data err=%d\n", err);
+ return -1;
+ }
+
+ return 0;
+}
+
+int rse_mbx_receive_data(uint8_t *receive_buffer, size_t *size)
+{
+ enum mhu_error_t err = mhu_receive_data(receive_buffer, size);
+
+ if (err != MHU_ERR_NONE) {
+ ERROR("mhu_receive_data err=%d\n", err);
+ return -1;
+ }
+
+ return 0;
+}
+
+int rse_mbx_init(const void *init_data)
+{
+ enum mhu_error_t err;
+ const struct mhu_addr *mbx_addr = (const struct mhu_addr *)init_data;
+
+ err = mhu_init_sender(mbx_addr->sender_base);
+ if (err != MHU_ERR_NONE) {
+ if (err == MHU_ERR_ALREADY_INIT) {
+ INFO("[RSE-COMMS] Host to RSE MHU driver already initialized\n");
+ } else {
+ ERROR("[RSE-COMMS] Host to RSE MHU driver initialization failed: %d\n",
+ err);
+ return -1;
+ }
+ }
+
+ err = mhu_init_receiver(mbx_addr->receiver_base);
+ if (err != MHU_ERR_NONE) {
+ if (err == MHU_ERR_ALREADY_INIT) {
+ INFO("[RSE-COMMS] RSE to Host MHU driver already initialized\n");
+ } else {
+ ERROR("[RSE-COMMS] RSE to Host MHU driver initialization failed: %d\n",
+ err);
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h b/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h
index 665930b..79e5ed1 100644
--- a/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h
+++ b/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h
@@ -11,6 +11,7 @@
#define ARMPLL_BASE_ADDR (0x40038000UL)
#define PERIPHPLL_BASE_ADDR (0x4003C000UL)
#define ARM_DFS_BASE_ADDR (0x40054000UL)
+#define PERIPH_DFS_BASE_ADDR (0x40058000UL)
#define CGM0_BASE_ADDR (0x40030000UL)
#define CGM1_BASE_ADDR (0x40034000UL)
#define DDRPLL_BASE_ADDR (0x40044000UL)
@@ -92,6 +93,25 @@
#define MC_CGM_MUXn_CSS_SWTRG_SAFE_CLK_INACTIVE 0x5U
#define MC_CGM_MUXn_CSS_SWIP BIT_32(16U)
#define MC_CGM_MUXn_CSS_SAFE_SW BIT_32(3U)
+#define MC_CGM_MUXn_DCm(CGM_ADDR, MUX, DC) \
+ (((CGM_ADDR) + 0x308UL) + \
+ ((MUX) * 0x40UL) + ((DC) * 0x4UL))
+#define MC_CGM_MUXn_DCm_DIV_OFFSET (16U)
+#define MC_CGM_MUXn_DCm_DIV_MASK GENMASK_32(23U, MC_CGM_MUXn_DCm_DIV_OFFSET)
+#define MC_CGM_MUXn_DCm_DIV_SET(VAL) (MC_CGM_MUXn_DCm_DIV_MASK & ((VAL) \
+ << MC_CGM_MUXn_DCm_DIV_OFFSET))
+#define MC_CGM_MUXn_DCm_DIV(VAL) ((MC_CGM_MUXn_DCm_DIV_MASK & (VAL)) \
+ >> MC_CGM_MUXn_DCm_DIV_OFFSET)
+#define MC_CGM_MUXn_DCm_DE BIT_32(31U)
+#define MC_CGM_MUXn_DIV_UPD_STAT(CGM_ADDR, MUX) \
+ (((CGM_ADDR) + 0x33CUL + ((MUX) * 0x40UL)))
+#define MC_CGM_MUXn_DIV_UPD_STAT_DIVSTAT_OFFSET (0U)
+#define MC_CGM_MUXn_DIV_UPD_STAT_DIVSTAT(CSS) \
+ ((MC_CGM_MUXn_DIV_UPD_STAT_DIVSTAT_MASK \
+ & (CSS)) \
+ >> MC_CGM_MUXn_DIV_UPD_STAT_DIVSTAT_OFFSET)
+#define MC_CGM_MUXn_DIV_UPD_STAT_DIVSTAT_MASK BIT_32(0U)
+
/* DFS */
#define DFS_PORTSR(DFS_ADDR) ((DFS_ADDR) + 0xCUL)
diff --git a/drivers/nxp/clk/s32cc/s32cc_clk_drv.c b/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
index c235e04..0a71152 100644
--- a/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
+++ b/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
@@ -24,6 +24,7 @@
uintptr_t armpll_base;
uintptr_t periphpll_base;
uintptr_t armdfs_base;
+ uintptr_t periphdfs_base;
uintptr_t cgm0_base;
uintptr_t cgm1_base;
uintptr_t cgm5_base;
@@ -58,6 +59,7 @@
.armpll_base = ARMPLL_BASE_ADDR,
.periphpll_base = PERIPHPLL_BASE_ADDR,
.armdfs_base = ARM_DFS_BASE_ADDR,
+ .periphdfs_base = PERIPH_DFS_BASE_ADDR,
.cgm0_base = CGM0_BASE_ADDR,
.cgm1_base = CGM1_BASE_ADDR,
.cgm5_base = MC_CGM5_BASE_ADDR,
@@ -110,6 +112,9 @@
case S32CC_ARM_DFS:
*base = drv->armdfs_base;
break;
+ case S32CC_PERIPH_DFS:
+ *base = drv->periphdfs_base;
+ break;
case S32CC_CGM0:
*base = drv->cgm0_base;
break;
@@ -1085,6 +1090,232 @@
return get_module_rate(block->parent, drv, rate, ldepth);
}
+static void cgm_mux_div_config(uintptr_t cgm_addr, uint32_t mux,
+ uint32_t dc, uint32_t div_index)
+{
+ uint32_t updstat;
+ uint32_t dc_val = mmio_read_32(MC_CGM_MUXn_DCm(cgm_addr, mux, div_index));
+
+ dc_val &= (MC_CGM_MUXn_DCm_DIV_MASK | MC_CGM_MUXn_DCm_DE);
+
+ if (dc_val == (MC_CGM_MUXn_DCm_DE | MC_CGM_MUXn_DCm_DIV_SET(dc))) {
+ return;
+ }
+
+ /* Set the divider */
+ mmio_write_32(MC_CGM_MUXn_DCm(cgm_addr, mux, div_index),
+ MC_CGM_MUXn_DCm_DE | MC_CGM_MUXn_DCm_DIV_SET(dc));
+
+ /* Wait for divider to get updated */
+ do {
+ updstat = mmio_read_32(MC_CGM_MUXn_DIV_UPD_STAT(cgm_addr, mux));
+ } while (MC_CGM_MUXn_DIV_UPD_STAT_DIVSTAT(updstat) != 0U);
+}
+
+static inline struct s32cc_clkmux *get_cgm_div_mux(const struct s32cc_cgm_div *cgm_div)
+{
+ const struct s32cc_clk_obj *parent = cgm_div->parent;
+ const struct s32cc_clk_obj *mux_obj;
+ const struct s32cc_clk *clk;
+
+ if (parent == NULL) {
+ ERROR("Failed to identify CGM DIV's parent\n");
+ return NULL;
+ }
+
+ if (parent->type != s32cc_clk_t) {
+ ERROR("The parent of the CGM DIV isn't a clock\n");
+ return NULL;
+ }
+
+ clk = s32cc_obj2clk(parent);
+
+ if (clk->module == NULL) {
+ ERROR("The clock isn't connected to a module\n");
+ return NULL;
+ }
+
+ mux_obj = clk->module;
+
+ if ((mux_obj->type != s32cc_clkmux_t) &&
+ (mux_obj->type != s32cc_shared_clkmux_t)) {
+ ERROR("The parent of the CGM DIV isn't a MUX\n");
+ return NULL;
+ }
+
+ return s32cc_obj2clkmux(mux_obj);
+}
+
+static int enable_cgm_div(struct s32cc_clk_obj *module,
+ const struct s32cc_clk_drv *drv, unsigned int depth)
+{
+ const struct s32cc_cgm_div *cgm_div = s32cc_obj2cgmdiv(module);
+ const struct s32cc_clkmux *mux;
+ unsigned int ldepth = depth;
+ uintptr_t cgm_addr = 0ULL;
+ uint64_t pfreq, dc64;
+ uint32_t dc;
+ int ret;
+
+ ret = update_stack_depth(&ldepth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (cgm_div->parent == NULL) {
+ ERROR("Failed to identify CGM divider's parent\n");
+ return -EINVAL;
+ }
+
+ if (cgm_div->freq == 0U) {
+ ERROR("The frequency of the divider %" PRIu32 " is not set\n",
+ cgm_div->index);
+ return -EINVAL;
+ }
+
+ mux = get_cgm_div_mux(cgm_div);
+ if (mux == NULL) {
+ return -EINVAL;
+ }
+
+ ret = get_base_addr(mux->module, drv, &cgm_addr);
+ if (ret != 0) {
+ ERROR("Failed to get CGM base address of the MUX module %d\n",
+ mux->module);
+ return ret;
+ }
+
+ ret = get_module_rate(cgm_div->parent, drv, &pfreq, ldepth);
+ if (ret != 0) {
+ ERROR("Failed to enable the div due to unknown frequency of "
+ "the CGM MUX %" PRIu8 "(CGM=%" PRIxPTR ")\n",
+ mux->index, cgm_addr);
+ return -EINVAL;
+ }
+
+ dc64 = ((pfreq * FP_PRECISION) / cgm_div->freq) / FP_PRECISION;
+ dc = (uint32_t)dc64;
+
+ if ((pfreq / dc64) != cgm_div->freq) {
+ ERROR("Cannot set CGM divider (mux:%" PRIu8 ", div:%" PRIu32
+ ") for input = %lu & output = %lu, Nearest freq = %lu\n",
+ mux->index, cgm_div->index, (unsigned long)pfreq,
+ cgm_div->freq, (unsigned long)(pfreq / dc));
+ return -EINVAL;
+ }
+
+ cgm_mux_div_config(cgm_addr, mux->index, dc - 1U, cgm_div->index);
+ return 0;
+}
+
+static int set_cgm_div_freq(const struct s32cc_clk_obj *module,
+ unsigned long rate, unsigned long *orate,
+ unsigned int *depth)
+{
+ struct s32cc_cgm_div *cgm_div = s32cc_obj2cgmdiv(module);
+ int ret;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (cgm_div->parent == NULL) {
+ ERROR("Failed to identify the CGM divider's parent\n");
+ return -EINVAL;
+ }
+
+ cgm_div->freq = rate;
+ *orate = rate;
+
+ return 0;
+}
+
+static inline bool is_cgm_div_enabled(uintptr_t cgm_addr, uint32_t mux,
+ uint32_t div_index)
+{
+ uint32_t dc_val;
+
+ dc_val = mmio_read_32(MC_CGM_MUXn_DCm(cgm_addr, mux, div_index));
+
+ return ((dc_val & MC_CGM_MUXn_DCm_DE) != 0U);
+}
+
+static unsigned long calc_cgm_div_freq(uintptr_t cgm_addr, uint32_t mux,
+ uint32_t div_index, unsigned long pfreq)
+{
+ uint32_t dc_val;
+ uint32_t dc_div;
+
+ dc_val = mmio_read_32(MC_CGM_MUXn_DCm(cgm_addr, mux, div_index));
+ dc_div = MC_CGM_MUXn_DCm_DIV(dc_val) + 1U;
+
+ return pfreq * FP_PRECISION / dc_div / FP_PRECISION;
+}
+
+static int get_cgm_div_freq(const struct s32cc_clk_obj *module,
+ const struct s32cc_clk_drv *drv,
+ unsigned long *rate, unsigned int depth)
+{
+ const struct s32cc_cgm_div *cgm_div = s32cc_obj2cgmdiv(module);
+ const struct s32cc_clkmux *mux;
+ unsigned int ldepth = depth;
+ uintptr_t cgm_addr = 0ULL;
+ unsigned long pfreq;
+ int ret;
+
+ ret = update_stack_depth(&ldepth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (cgm_div->parent == NULL) {
+ ERROR("Failed to identify CGM divider's parent\n");
+ return -EINVAL;
+ }
+
+ mux = get_cgm_div_mux(cgm_div);
+ if (mux == NULL) {
+ return -EINVAL;
+ }
+
+ ret = get_base_addr(mux->module, drv, &cgm_addr);
+ if (ret != 0) {
+ ERROR("Failed to get CGM base address of the MUX module %d\n",
+ mux->module);
+ return ret;
+ }
+
+ if (!is_cgm_div_enabled(cgm_addr, mux->index, cgm_div->index)) {
+ *rate = cgm_div->freq;
+ return 0;
+ }
+
+ ret = get_module_rate(cgm_div->parent, drv, &pfreq, ldepth);
+ if (ret != 0) {
+ ERROR("Failed to get the frequency of CGM MUX %" PRIu8 "(CGM=0x%" PRIxPTR ")\n",
+ mux->index, cgm_addr);
+ return ret;
+ }
+
+ *rate = calc_cgm_div_freq(cgm_addr, mux->index, cgm_div->index, pfreq);
+
+ return 0;
+}
+
+static struct s32cc_clk_obj *
+get_cgm_div_parent(const struct s32cc_clk_obj *module)
+{
+ const struct s32cc_cgm_div *cgm_div = s32cc_obj2cgmdiv(module);
+
+ if (cgm_div->parent == NULL) {
+ ERROR("Failed to identify the CGM divider's parent\n");
+ return NULL;
+ }
+
+ return cgm_div->parent;
+}
+
static int no_enable(struct s32cc_clk_obj *module,
const struct s32cc_clk_drv *drv,
unsigned int depth)
@@ -1131,7 +1362,7 @@
unsigned int depth)
{
struct s32cc_clk_obj *parent = get_module_parent(module);
- static const enable_clk_t enable_clbs[12] = {
+ static const enable_clk_t enable_clbs[13] = {
[s32cc_clk_t] = no_enable,
[s32cc_osc_t] = enable_osc,
[s32cc_pll_t] = enable_pll,
@@ -1143,6 +1374,7 @@
[s32cc_part_t] = enable_part,
[s32cc_part_block_t] = enable_part_block,
[s32cc_part_block_link_t] = enable_part_block_link,
+ [s32cc_cgm_div_t] = enable_cgm_div,
};
unsigned int ldepth = depth;
uint32_t index;
@@ -1558,6 +1790,13 @@
return 0;
}
+static inline struct s32cc_clk_obj *get_fixed_div_parent(const struct s32cc_clk_obj *module)
+{
+ const struct s32cc_fixed_div *fdiv = s32cc_obj2fixeddiv(module);
+
+ return fdiv->parent;
+}
+
static int set_mux_freq(const struct s32cc_clk_obj *module, unsigned long rate,
unsigned long *orate, unsigned int *depth)
{
@@ -1703,6 +1942,28 @@
return 0;
}
+static int set_part_block_link_freq(const struct s32cc_clk_obj *module,
+ unsigned long rate, unsigned long *orate,
+ const unsigned int *depth)
+{
+ const struct s32cc_part_block_link *link = s32cc_obj2partblocklink(module);
+ const struct s32cc_clk_obj *parent = link->parent;
+ unsigned int ldepth = *depth;
+ int ret;
+
+ ret = update_stack_depth(&ldepth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (parent == NULL) {
+ ERROR("Partition block link with no parent\n");
+ return -EINVAL;
+ }
+
+ return set_module_rate(parent, rate, orate, &ldepth);
+}
+
static int set_module_rate(const struct s32cc_clk_obj *module,
unsigned long rate, unsigned long *orate,
unsigned int *depth)
@@ -1738,12 +1999,24 @@
case s32cc_shared_clkmux_t:
ret = set_mux_freq(module, rate, orate, depth);
break;
+ case s32cc_cgm_div_t:
+ ret = set_cgm_div_freq(module, rate, orate, depth);
+ break;
case s32cc_dfs_t:
ERROR("Setting the frequency of a DFS is not allowed!");
break;
case s32cc_dfs_div_t:
ret = set_dfs_div_freq(module, rate, orate, depth);
break;
+ case s32cc_part_block_link_t:
+ ret = set_part_block_link_freq(module, rate, orate, depth);
+ break;
+ case s32cc_part_t:
+ ERROR("It's not allowed to set the frequency of a partition !");
+ break;
+ case s32cc_part_block_t:
+ ERROR("It's not allowed to set the frequency of a partition block !");
+ break;
default:
break;
}
@@ -1801,6 +2074,9 @@
case s32cc_part_block_link_t:
ret = get_part_block_link_freq(module, drv, rate, ldepth);
break;
+ case s32cc_cgm_div_t:
+ ret = get_cgm_div_freq(module, drv, rate, ldepth);
+ break;
default:
ret = -EINVAL;
break;
@@ -1862,7 +2138,7 @@
static struct s32cc_clk_obj *get_module_parent(const struct s32cc_clk_obj *module)
{
- static const get_parent_clb_t parents_clbs[12] = {
+ static const get_parent_clb_t parents_clbs[13] = {
[s32cc_clk_t] = get_clk_parent,
[s32cc_osc_t] = get_no_parent,
[s32cc_pll_t] = get_pll_parent,
@@ -1872,8 +2148,10 @@
[s32cc_dfs_t] = get_dfs_parent,
[s32cc_dfs_div_t] = get_dfs_div_parent,
[s32cc_part_t] = get_no_parent,
+ [s32cc_fixed_div_t] = get_fixed_div_parent,
[s32cc_part_block_t] = get_part_block_parent,
[s32cc_part_block_link_t] = get_part_block_link_parent,
+ [s32cc_cgm_div_t] = get_cgm_div_parent,
};
uint32_t index;
@@ -1980,11 +2258,12 @@
static int s32cc_clk_mmap_regs(const struct s32cc_clk_drv *drv)
{
- const uintptr_t base_addrs[11] = {
+ const uintptr_t base_addrs[12] = {
drv->fxosc_base,
drv->armpll_base,
drv->periphpll_base,
drv->armdfs_base,
+ drv->periphdfs_base,
drv->cgm0_base,
drv->cgm1_base,
drv->cgm5_base,
diff --git a/drivers/nxp/clk/s32cc/s32cc_clk_modules.c b/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
index f7af465..127453e 100644
--- a/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
+++ b/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
@@ -68,6 +68,12 @@
S32CC_CLK_FXOSC, 0, 0);
static struct s32cc_clk cgm0_mux8_clk = S32CC_MODULE_CLK(cgm0_mux8);
+static struct s32cc_clkmux cgm0_mux14 =
+ S32CC_CLKMUX_INIT(S32CC_CGM0, 14, 2,
+ S32CC_CLK_FIRC,
+ S32CC_CLK_PERIPH_PLL_DFS3, 0, 0, 0);
+static struct s32cc_clk cgm0_mux14_clk = S32CC_MODULE_CLK(cgm0_mux14);
+
/* XBAR */
static struct s32cc_clk xbar_2x_clk =
S32CC_CHILD_CLK(cgm0_mux0_clk, 48 * MHZ, 800 * MHZ);
@@ -142,6 +148,14 @@
static struct s32cc_clk periph_pll_phi3_clk =
S32CC_FREQ_MODULE_CLK(periph_pll_phi3_div, 0, 133333333);
+/* PERIPH DFS */
+static struct s32cc_dfs periphdfs =
+ S32CC_DFS_INIT(periphpll, S32CC_PERIPH_DFS);
+static struct s32cc_dfs_div periph_dfs3_div =
+ S32CC_DFS_DIV_INIT(periphdfs, 0);
+static struct s32cc_clk periph_dfs3_clk =
+ S32CC_FREQ_MODULE_CLK(periph_dfs3_div, 416 * MHZ, 800 * MHZ);
+
/* DDR PLL */
static struct s32cc_clkmux ddr_pll_mux =
S32CC_CLKMUX_INIT(S32CC_DDR_PLL, 0, 2,
@@ -175,6 +189,15 @@
static struct s32cc_clk ddr_clk =
S32CC_FREQ_MODULE_CLK(ddr_block_link, 0, 800 * MHZ);
+/* SDHC_CLK */
+static struct s32cc_part_block part0_block0 =
+ S32CC_PART_BLOCK(&part0, s32cc_part_block0);
+static struct s32cc_cgm_div sdhc_div = S32CC_CGM_DIV_INIT(cgm0_mux14_clk, 0);
+static struct s32cc_part_block_link usdhc_block_link =
+ S32CC_PART_BLOCK_LINK(sdhc_div, &part0_block0);
+static struct s32cc_clk usdhc_clk =
+ S32CC_FREQ_MODULE_CLK(usdhc_block_link, 0, 400 * MHZ);
+
static struct s32cc_clk *s32cc_hw_clk_list[37] = {
/* Oscillators */
[S32CC_CLK_ID(S32CC_CLK_FIRC)] = &firc_clk,
@@ -186,6 +209,8 @@
[S32CC_CLK_ID(S32CC_CLK_ARM_PLL_DFS1)] = &arm_dfs1_clk,
/* PERIPH PLL */
[S32CC_CLK_ID(S32CC_CLK_PERIPH_PLL_PHI3)] = &periph_pll_phi3_clk,
+ /* PERIPH DFS */
+ [S32CC_CLK_ID(S32CC_CLK_PERIPH_PLL_DFS3)] = &periph_dfs3_clk,
/* DDR PLL */
[S32CC_CLK_ID(S32CC_CLK_DDR_PLL_PHI0)] = &ddr_pll_phi0_clk,
};
@@ -196,7 +221,7 @@
.n_clks = ARRAY_SIZE(s32cc_hw_clk_list),
};
-static struct s32cc_clk *s32cc_arch_clk_list[22] = {
+static struct s32cc_clk *s32cc_arch_clk_list[24] = {
/* ARM PLL */
[S32CC_CLK_ID(S32CC_CLK_ARM_PLL_MUX)] = &arm_pll_mux_clk,
[S32CC_CLK_ID(S32CC_CLK_ARM_PLL_VCO)] = &arm_pll_vco_clk,
@@ -206,6 +231,7 @@
/* MC_CGM0 */
[S32CC_CLK_ID(S32CC_CLK_MC_CGM0_MUX0)] = &cgm0_mux0_clk,
[S32CC_CLK_ID(S32CC_CLK_MC_CGM0_MUX8)] = &cgm0_mux8_clk,
+ [S32CC_CLK_ID(S32CC_CLK_MC_CGM0_MUX14)] = &cgm0_mux14_clk,
/* XBAR */
[S32CC_CLK_ID(S32CC_CLK_XBAR_2X)] = &xbar_2x_clk,
[S32CC_CLK_ID(S32CC_CLK_XBAR)] = &xbar_clk,
@@ -229,6 +255,8 @@
[S32CC_CLK_ID(S32CC_CLK_MC_CGM5_MUX0)] = &cgm5_mux0_clk,
/* DDR */
[S32CC_CLK_ID(S32CC_CLK_DDR)] = &ddr_clk,
+ /* USDHC */
+ [S32CC_CLK_ID(S32CC_CLK_USDHC)] = &usdhc_clk,
};
static struct s32cc_clk_array s32cc_arch_clocks = {
diff --git a/drivers/nxp/clk/s32cc/s32cc_early_clks.c b/drivers/nxp/clk/s32cc/s32cc_early_clks.c
index f001568..92182a0 100644
--- a/drivers/nxp/clk/s32cc/s32cc_early_clks.c
+++ b/drivers/nxp/clk/s32cc/s32cc_early_clks.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2024 NXP
+ * Copyright 2024-2025 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -18,6 +18,8 @@
#define S32CC_PERIPH_PLL_PHI3_FREQ UART_CLOCK_HZ
#define S32CC_DDR_PLL_VCO_FREQ (1600U * MHZ)
#define S32CC_DDR_PLL_PHI0_FREQ (800U * MHZ)
+#define S32CC_PERIPH_DFS_PHI3_FREQ (800U * MHZ)
+#define S32CC_USDHC_FREQ (400U * MHZ)
static int setup_fxosc(void)
{
@@ -180,6 +182,35 @@
return ret;
}
+static int enable_usdhc_clk(void)
+{
+ int ret;
+
+ ret = clk_set_parent(S32CC_CLK_MC_CGM0_MUX14,
+ S32CC_CLK_PERIPH_PLL_DFS3);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_set_rate(S32CC_CLK_PERIPH_PLL_DFS3,
+ S32CC_PERIPH_DFS_PHI3_FREQ, NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_set_rate(S32CC_CLK_USDHC, S32CC_USDHC_FREQ, NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_enable(S32CC_CLK_USDHC);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return ret;
+}
+
int s32cc_init_core_clocks(void)
{
int ret;
@@ -241,5 +272,10 @@
return ret;
}
+ ret = enable_usdhc_clk();
+ if (ret != 0) {
+ return ret;
+ }
+
return ret;
}
diff --git a/drivers/st/pmic/stpmic2.c b/drivers/st/pmic/stpmic2.c
index 05a80ec..7f233db 100644
--- a/drivers/st/pmic/stpmic2.c
+++ b/drivers/st/pmic/stpmic2.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2024, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2024-2025, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -247,10 +247,6 @@
{
const struct regul_struct *regul = ®ul_table[id];
- if (regul == NULL) {
- return RET_ERROR_BAD_PARAMETERS;
- }
-
if (levels_count != NULL) {
*levels_count = regul->volt_table_size;
}
diff --git a/fdts/fvp-base-psci-common.dtsi b/fdts/fvp-base-psci-common.dtsi
index 583bba7..95ea2a1 100644
--- a/fdts/fvp-base-psci-common.dtsi
+++ b/fdts/fvp-base-psci-common.dtsi
@@ -7,7 +7,7 @@
*
* RTSM_VE_AEMv8A.lisa
*
- * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, ARM Limited and Contributors. All rights reserved.
*/
#include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -249,4 +249,39 @@
<0 0 44 &gic 0 GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
<0 0 46 &gic 0 GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
};
+
+#if (ENABLE_RME == 1)
+ pci: pci@40000000 {
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ compatible = "pci-host-ecam-generic";
+ device_type = "pci";
+ reg = <0x0 0x40000000 0x0 0x10000000>;
+ ranges = <0x2000000 0x0 0x50000000 0x0 0x50000000 0x0 0x10000000>,
+ /* First 3GB of 256GB PCIe memory region 2 */
+ <0x2000000 0x40 0x00000000 0x40 0x00000000 0x0 0xc0000000>;
+ interrupt-map = <0 0 0 1 &gic 0 0 GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &gic 0 0 GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &gic 0 0 GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &gic 0 0 GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ msi-map = <0x0 &its 0x0 0x10000>;
+ iommu-map = <0x0 &smmu 0x0 0x10000>;
+ dma-coherent;
+ };
+
+ smmu: iommu@2b400000 {
+ compatible = "arm,smmu-v3";
+ reg = <0x0 0x2b400000 0x0 0x100000>;
+ interrupts = <GIC_SPI 74 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 79 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 77 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "eventq", "gerror", "priq", "cmdq-sync";
+ dma-coherent;
+ #iommu-cells = <1>;
+ msi-parent = <&its 0x10000>;
+ };
+#endif /* ENABLE_RME */
};
diff --git a/fdts/stm32mp157a-dk1-sp_min-fw-config.dts b/fdts/stm32mp157a-dk1-sp_min-fw-config.dts
new file mode 100644
index 0000000..40164f3
--- /dev/null
+++ b/fdts/stm32mp157a-dk1-sp_min-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+/*
+ * Copyright (c) 2025, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE 0x20000000 /* 512MB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157a-dk1-sp_min.dts b/fdts/stm32mp157a-dk1-sp_min.dts
new file mode 100644
index 0000000..ac5c2af
--- /dev/null
+++ b/fdts/stm32mp157a-dk1-sp_min.dts
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+/*
+ * Copyright (C) 2025, STMicroelectronics - All Rights Reserved
+ */
+
+#include "stm32mp157a-dk1.dts"
+
+/ {
+ model = "STMicroelectronics STM32MP157A-DK1 Discovery Board (SP_MIN)";
+};
+
+&rcc {
+ st,clksrc = <
+ CLK_MPU_PLL1P
+ CLK_AXI_PLL2P
+ CLK_MCU_PLL3P
+ CLK_RTC_LSE
+ CLK_MCO1_DISABLED
+ CLK_MCO2_DISABLED
+ CLK_CKPER_HSE
+ CLK_FMC_ACLK
+ CLK_QSPI_ACLK
+ CLK_ETH_PLL4P
+ CLK_SDMMC12_PLL4P
+ CLK_DSI_DSIPLL
+ CLK_STGEN_HSE
+ CLK_USBPHY_HSE
+ CLK_SPI2S1_PLL3Q
+ CLK_SPI2S23_PLL3Q
+ CLK_SPI45_HSI
+ CLK_SPI6_HSI
+ CLK_I2C46_HSI
+ CLK_SDMMC3_PLL4P
+ CLK_USBO_USBPHY
+ CLK_ADC_CKPER
+ CLK_CEC_LSE
+ CLK_I2C12_HSI
+ CLK_I2C35_HSI
+ CLK_UART1_HSI
+ CLK_UART24_HSI
+ CLK_UART35_HSI
+ CLK_UART6_HSI
+ CLK_UART78_HSI
+ CLK_SPDIF_PLL4P
+ CLK_FDCAN_PLL4R
+ CLK_SAI1_PLL3Q
+ CLK_SAI2_PLL3Q
+ CLK_SAI3_PLL3Q
+ CLK_SAI4_PLL3Q
+ CLK_RNG1_CSI
+ CLK_RNG2_LSI
+ CLK_LPTIM1_PCLK1
+ CLK_LPTIM23_PCLK3
+ CLK_LPTIM45_LSE
+ >;
+
+ st,clkdiv = <
+ DIV(DIV_MPU, 1)
+ DIV(DIV_AXI, 0)
+ DIV(DIV_MCU, 0)
+ DIV(DIV_APB1, 1)
+ DIV(DIV_APB2, 1)
+ DIV(DIV_APB3, 1)
+ DIV(DIV_APB4, 1)
+ DIV(DIV_APB5, 2)
+ DIV(DIV_MCO1, 0)
+ DIV(DIV_MCO2, 0)
+ >;
+};
diff --git a/fdts/stm32mp157c-dk2-sp_min-fw-config.dts b/fdts/stm32mp157c-dk2-sp_min-fw-config.dts
new file mode 100644
index 0000000..40164f3
--- /dev/null
+++ b/fdts/stm32mp157c-dk2-sp_min-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+/*
+ * Copyright (c) 2025, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE 0x20000000 /* 512MB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157c-dk2-sp_min.dts b/fdts/stm32mp157c-dk2-sp_min.dts
new file mode 100644
index 0000000..350cd34
--- /dev/null
+++ b/fdts/stm32mp157c-dk2-sp_min.dts
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+/*
+ * Copyright (C) 2025, STMicroelectronics - All Rights Reserved
+ */
+
+#include "stm32mp157c-dk2.dts"
+
+/ {
+ model = "STMicroelectronics STM32MP157C-DK2 Discovery Board (SP_MIN)";
+};
+
+&rcc {
+ st,clksrc = <
+ CLK_MPU_PLL1P
+ CLK_AXI_PLL2P
+ CLK_MCU_PLL3P
+ CLK_RTC_LSE
+ CLK_MCO1_DISABLED
+ CLK_MCO2_DISABLED
+ CLK_CKPER_HSE
+ CLK_FMC_ACLK
+ CLK_QSPI_ACLK
+ CLK_ETH_PLL4P
+ CLK_SDMMC12_PLL4P
+ CLK_DSI_DSIPLL
+ CLK_STGEN_HSE
+ CLK_USBPHY_HSE
+ CLK_SPI2S1_PLL3Q
+ CLK_SPI2S23_PLL3Q
+ CLK_SPI45_HSI
+ CLK_SPI6_HSI
+ CLK_I2C46_HSI
+ CLK_SDMMC3_PLL4P
+ CLK_USBO_USBPHY
+ CLK_ADC_CKPER
+ CLK_CEC_LSE
+ CLK_I2C12_HSI
+ CLK_I2C35_HSI
+ CLK_UART1_HSI
+ CLK_UART24_HSI
+ CLK_UART35_HSI
+ CLK_UART6_HSI
+ CLK_UART78_HSI
+ CLK_SPDIF_PLL4P
+ CLK_FDCAN_PLL4R
+ CLK_SAI1_PLL3Q
+ CLK_SAI2_PLL3Q
+ CLK_SAI3_PLL3Q
+ CLK_SAI4_PLL3Q
+ CLK_RNG1_CSI
+ CLK_RNG2_LSI
+ CLK_LPTIM1_PCLK1
+ CLK_LPTIM23_PCLK3
+ CLK_LPTIM45_LSE
+ >;
+
+ st,clkdiv = <
+ DIV(DIV_MPU, 1)
+ DIV(DIV_AXI, 0)
+ DIV(DIV_MCU, 0)
+ DIV(DIV_APB1, 1)
+ DIV(DIV_APB2, 1)
+ DIV(DIV_APB3, 1)
+ DIV(DIV_APB4, 1)
+ DIV(DIV_APB5, 2)
+ DIV(DIV_MCO1, 0)
+ DIV(DIV_MCO2, 0)
+ >;
+};
diff --git a/fdts/stm32mp157c-ed1-sp_min-fw-config.dts b/fdts/stm32mp157c-ed1-sp_min-fw-config.dts
new file mode 100644
index 0000000..5aff97f
--- /dev/null
+++ b/fdts/stm32mp157c-ed1-sp_min-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+/*
+ * Copyright (c) 2025, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE 0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157c-ed1-sp_min.dts b/fdts/stm32mp157c-ed1-sp_min.dts
new file mode 100644
index 0000000..85d4fb1
--- /dev/null
+++ b/fdts/stm32mp157c-ed1-sp_min.dts
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+/*
+ * Copyright (c) 2025, STMicroelectronics - All Rights Reserved
+ */
+
+#include "stm32mp157c-ed1.dts"
+
+/ {
+ model = "STMicroelectronics STM32MP157C eval daughter (SP_MIN)";
+};
+
+&rcc {
+ st,clksrc = <
+ CLK_MPU_PLL1P
+ CLK_AXI_PLL2P
+ CLK_MCU_PLL3P
+ CLK_RTC_LSE
+ CLK_MCO1_DISABLED
+ CLK_MCO2_DISABLED
+ CLK_CKPER_HSE
+ CLK_FMC_ACLK
+ CLK_QSPI_ACLK
+ CLK_ETH_PLL4P
+ CLK_SDMMC12_PLL4P
+ CLK_DSI_DSIPLL
+ CLK_STGEN_HSE
+ CLK_USBPHY_HSE
+ CLK_SPI2S1_PLL3Q
+ CLK_SPI2S23_PLL3Q
+ CLK_SPI45_HSI
+ CLK_SPI6_HSI
+ CLK_I2C46_HSI
+ CLK_SDMMC3_PLL4P
+ CLK_USBO_USBPHY
+ CLK_ADC_CKPER
+ CLK_CEC_LSE
+ CLK_I2C12_HSI
+ CLK_I2C35_HSI
+ CLK_UART1_HSI
+ CLK_UART24_HSI
+ CLK_UART35_HSI
+ CLK_UART6_HSI
+ CLK_UART78_HSI
+ CLK_SPDIF_PLL4P
+ CLK_FDCAN_PLL4R
+ CLK_SAI1_PLL3Q
+ CLK_SAI2_PLL3Q
+ CLK_SAI3_PLL3Q
+ CLK_SAI4_PLL3Q
+ CLK_RNG1_CSI
+ CLK_RNG2_LSI
+ CLK_LPTIM1_PCLK1
+ CLK_LPTIM23_PCLK3
+ CLK_LPTIM45_LSE
+ >;
+
+ st,clkdiv = <
+ DIV(DIV_MPU, 1)
+ DIV(DIV_AXI, 0)
+ DIV(DIV_MCU, 0)
+ DIV(DIV_APB1, 1)
+ DIV(DIV_APB2, 1)
+ DIV(DIV_APB3, 1)
+ DIV(DIV_APB4, 1)
+ DIV(DIV_APB5, 2)
+ DIV(DIV_MCO1, 0)
+ DIV(DIV_MCO2, 0)
+ >;
+};
diff --git a/fdts/stm32mp157c-ed1.dts b/fdts/stm32mp157c-ed1.dts
index fe5f464..dddfe3a 100644
--- a/fdts/stm32mp157c-ed1.dts
+++ b/fdts/stm32mp157c-ed1.dts
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/*
- * Copyright (c) 2017-2024, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2025, STMicroelectronics - All Rights Reserved
* Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
*/
/dts-v1/;
@@ -195,43 +195,13 @@
CLK_AXI_PLL2P
CLK_MCU_PLL3P
CLK_RTC_LSE
- CLK_MCO1_DISABLED
- CLK_MCO2_DISABLED
CLK_CKPER_HSE
CLK_FMC_ACLK
CLK_QSPI_ACLK
- CLK_ETH_PLL4P
CLK_SDMMC12_PLL4P
- CLK_DSI_DSIPLL
CLK_STGEN_HSE
- CLK_USBPHY_HSE
- CLK_SPI2S1_PLL3Q
- CLK_SPI2S23_PLL3Q
- CLK_SPI45_HSI
- CLK_SPI6_HSI
CLK_I2C46_HSI
- CLK_SDMMC3_PLL4P
- CLK_USBO_USBPHY
- CLK_ADC_CKPER
- CLK_CEC_LSE
- CLK_I2C12_HSI
- CLK_I2C35_HSI
- CLK_UART1_HSI
CLK_UART24_HSI
- CLK_UART35_HSI
- CLK_UART6_HSI
- CLK_UART78_HSI
- CLK_SPDIF_PLL4P
- CLK_FDCAN_PLL4R
- CLK_SAI1_PLL3Q
- CLK_SAI2_PLL3Q
- CLK_SAI3_PLL3Q
- CLK_SAI4_PLL3Q
- CLK_RNG1_CSI
- CLK_RNG2_LSI
- CLK_LPTIM1_PCLK1
- CLK_LPTIM23_PCLK3
- CLK_LPTIM45_LSE
>;
st,clkdiv = <
@@ -244,8 +214,6 @@
DIV(DIV_APB4, 1)
DIV(DIV_APB5, 2)
DIV(DIV_RTC, 23)
- DIV(DIV_MCO1, 0)
- DIV(DIV_MCO2, 0)
>;
st,pll_vco {
diff --git a/fdts/stm32mp157c-ev1-sp_min-fw-config.dts b/fdts/stm32mp157c-ev1-sp_min-fw-config.dts
new file mode 100644
index 0000000..5aff97f
--- /dev/null
+++ b/fdts/stm32mp157c-ev1-sp_min-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+/*
+ * Copyright (c) 2025, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE 0x40000000 /* 1GB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp157c-ev1-sp_min.dts b/fdts/stm32mp157c-ev1-sp_min.dts
new file mode 100644
index 0000000..9513449
--- /dev/null
+++ b/fdts/stm32mp157c-ev1-sp_min.dts
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2017-2025, STMicroelectronics - All Rights Reserved
+ */
+/dts-v1/;
+
+#include "stm32mp157c-ed1-sp_min.dts"
+
+/ {
+ model = "STMicroelectronics STM32MP157C eval daughter on eval mother (SP_MIN)";
+ compatible = "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", "st,stm32mp157";
+
+ aliases {
+ serial1 = &usart3;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&fmc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&fmc_pins_a>;
+ status = "okay";
+
+ nand-controller@4,0 {
+ status = "okay";
+
+ nand@0 {
+ reg = <0>;
+ nand-on-flash-bbt;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+ };
+};
+
+&qspi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&qspi_clk_pins_a
+ &qspi_bk1_pins_a
+ &qspi_cs1_pins_a>;
+ reg = <0x58003000 0x1000>, <0x70000000 0x4000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ flash0: flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-rx-bus-width = <4>;
+ spi-max-frequency = <108000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+};
+
+&usart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&usart3_pins_b>;
+ uart-has-rtscts;
+ status = "disabled";
+};
diff --git a/fdts/stm32mp15xx-dkx.dtsi b/fdts/stm32mp15xx-dkx.dtsi
index 3115a00..1c7c4c3 100644
--- a/fdts/stm32mp15xx-dkx.dtsi
+++ b/fdts/stm32mp15xx-dkx.dtsi
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/*
- * Copyright (c) 2019-2024, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2025, STMicroelectronics - All Rights Reserved
* Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
*/
@@ -199,43 +199,11 @@
CLK_AXI_PLL2P
CLK_MCU_PLL3P
CLK_RTC_LSE
- CLK_MCO1_DISABLED
- CLK_MCO2_DISABLED
CLK_CKPER_HSE
- CLK_FMC_ACLK
- CLK_QSPI_ACLK
- CLK_ETH_PLL4P
CLK_SDMMC12_PLL4P
- CLK_DSI_DSIPLL
CLK_STGEN_HSE
- CLK_USBPHY_HSE
- CLK_SPI2S1_PLL3Q
- CLK_SPI2S23_PLL3Q
- CLK_SPI45_HSI
- CLK_SPI6_HSI
CLK_I2C46_HSI
- CLK_SDMMC3_PLL4P
- CLK_USBO_USBPHY
- CLK_ADC_CKPER
- CLK_CEC_LSE
- CLK_I2C12_HSI
- CLK_I2C35_HSI
- CLK_UART1_HSI
CLK_UART24_HSI
- CLK_UART35_HSI
- CLK_UART6_HSI
- CLK_UART78_HSI
- CLK_SPDIF_PLL4P
- CLK_FDCAN_PLL4R
- CLK_SAI1_PLL3Q
- CLK_SAI2_PLL3Q
- CLK_SAI3_PLL3Q
- CLK_SAI4_PLL3Q
- CLK_RNG1_CSI
- CLK_RNG2_LSI
- CLK_LPTIM1_PCLK1
- CLK_LPTIM23_PCLK3
- CLK_LPTIM45_LSE
>;
st,clkdiv = <
@@ -248,8 +216,6 @@
DIV(DIV_APB4, 1)
DIV(DIV_APB5, 2)
DIV(DIV_RTC, 23)
- DIV(DIV_MCO1, 0)
- DIV(DIV_MCO2, 0)
>;
st,pll_vco {
diff --git a/fdts/tc-base.dtsi b/fdts/tc-base.dtsi
index fc0b3b6..ac08e0b 100644
--- a/fdts/tc-base.dtsi
+++ b/fdts/tc-base.dtsi
@@ -104,28 +104,6 @@
};
};
- amus {
- amu: amu-0 {
- #address-cells = <1>;
- #size-cells = <0>;
-
- mpmm_gear0: counter@0 {
- reg = <0>;
- enable-at-el3;
- };
-
- mpmm_gear1: counter@1 {
- reg = <1>;
- enable-at-el3;
- };
-
- mpmm_gear2: counter@2 {
- reg = <2>;
- enable-at-el3;
- };
- };
- };
-
CPU0:cpu@0 {
device_type = "cpu";
compatible = "arm,armv8";
@@ -134,8 +112,6 @@
clocks = <&scmi_dvfs 0>;
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
capacity-dmips-mhz = <LIT_CAPACITY>;
- amu = <&amu>;
- supports-mpmm;
};
CPU1:cpu@100 {
@@ -146,8 +122,6 @@
clocks = <&scmi_dvfs 0>;
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
capacity-dmips-mhz = <LIT_CAPACITY>;
- amu = <&amu>;
- supports-mpmm;
};
CPU2:cpu@200 {
@@ -156,8 +130,6 @@
reg = <0x200>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
- amu = <&amu>;
- supports-mpmm;
};
CPU3:cpu@300 {
@@ -166,8 +138,6 @@
reg = <0x300>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
- amu = <&amu>;
- supports-mpmm;
};
CPU4:cpu@400 {
@@ -178,8 +148,6 @@
clocks = <&scmi_dvfs 1>;
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
capacity-dmips-mhz = <MID_CAPACITY>;
- amu = <&amu>;
- supports-mpmm;
};
CPU5:cpu@500 {
@@ -190,8 +158,6 @@
clocks = <&scmi_dvfs 1>;
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
capacity-dmips-mhz = <MID_CAPACITY>;
- amu = <&amu>;
- supports-mpmm;
};
CPU6:cpu@600 {
@@ -200,8 +166,6 @@
reg = <0x600>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
- amu = <&amu>;
- supports-mpmm;
};
CPU7:cpu@700 {
@@ -210,8 +174,6 @@
reg = <0x700>;
enable-method = "psci";
cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
- amu = <&amu>;
- supports-mpmm;
};
};
diff --git a/fdts/tc2.dts b/fdts/tc2.dts
index 8aa77ce..fa16dcd 100644
--- a/fdts/tc2.dts
+++ b/fdts/tc2.dts
@@ -123,8 +123,6 @@
enable-method = "psci";
clocks = <&scmi_dvfs 1>;
capacity-dmips-mhz = <MID_CAPACITY>;
- amu = <&amu>;
- supports-mpmm;
};
CPU9:cpu@900 {
@@ -134,8 +132,6 @@
enable-method = "psci";
clocks = <&scmi_dvfs 2>;
capacity-dmips-mhz = <BIG2_CAPACITY>;
- amu = <&amu>;
- supports-mpmm;
};
CPU10:cpu@A00 {
@@ -145,8 +141,6 @@
enable-method = "psci";
clocks = <&scmi_dvfs 2>;
capacity-dmips-mhz = <BIG2_CAPACITY>;
- amu = <&amu>;
- supports-mpmm;
};
CPU11:cpu@B00 {
@@ -156,8 +150,6 @@
enable-method = "psci";
clocks = <&scmi_dvfs 2>;
capacity-dmips-mhz = <BIG2_CAPACITY>;
- amu = <&amu>;
- supports-mpmm;
};
CPU12:cpu@C00 {
@@ -167,8 +159,6 @@
enable-method = "psci";
clocks = <&scmi_dvfs 3>;
capacity-dmips-mhz = <BIG_CAPACITY>;
- amu = <&amu>;
- supports-mpmm;
};
CPU13:cpu@D00 {
@@ -178,8 +168,6 @@
enable-method = "psci";
clocks = <&scmi_dvfs 3>;
capacity-dmips-mhz = <BIG_CAPACITY>;
- amu = <&amu>;
- supports-mpmm;
};
#endif
};
diff --git a/include/arch/aarch32/arch.h b/include/arch/aarch32/arch.h
index d2591dd..41be1a1 100644
--- a/include/arch/aarch32/arch.h
+++ b/include/arch/aarch32/arch.h
@@ -761,7 +761,7 @@
/* AMCNTENSET0 definitions */
#define AMCNTENSET0_Pn_SHIFT U(0)
-#define AMCNTENSET0_Pn_MASK U(0xffff)
+#define AMCNTENSET0_Pn_MASK U(0xf)
/* AMCNTENSET1 definitions */
#define AMCNTENSET1_Pn_SHIFT U(0)
@@ -769,7 +769,7 @@
/* AMCNTENCLR0 definitions */
#define AMCNTENCLR0_Pn_SHIFT U(0)
-#define AMCNTENCLR0_Pn_MASK U(0xffff)
+#define AMCNTENCLR0_Pn_MASK U(0xf)
/* AMCNTENCLR1 definitions */
#define AMCNTENCLR1_Pn_SHIFT U(0)
diff --git a/include/arch/aarch32/arch_features.h b/include/arch/aarch32/arch_features.h
index e347240..e80faf2 100644
--- a/include/arch/aarch32/arch_features.h
+++ b/include/arch/aarch32/arch_features.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -85,6 +85,10 @@
CREATE_FEATURE_FUNCS(feat_amu, id_pfr0, ID_PFR0_AMU_SHIFT,
ID_PFR0_AMU_MASK, ID_PFR0_AMU_V1, ENABLE_FEAT_AMU)
+/* Auxiliary counters for FEAT_AMU */
+CREATE_FEATURE_FUNCS(feat_amu_aux, amcfgr, AMCFGR_NCG_SHIFT,
+ AMCFGR_NCG_MASK, 1U, ENABLE_AMU_AUXILIARY_COUNTERS)
+
/* FEAT_AMUV1P1: AMU Extension v1.1 */
CREATE_FEATURE_FUNCS(feat_amuv1p1, id_pfr0, ID_PFR0_AMU_SHIFT,
ID_PFR0_AMU_MASK, ID_PFR0_AMU_V1P1, ENABLE_FEAT_AMUv1p1)
diff --git a/include/arch/aarch32/arch_helpers.h b/include/arch/aarch32/arch_helpers.h
index adc96ae..4f80e3a 100644
--- a/include/arch/aarch32/arch_helpers.h
+++ b/include/arch/aarch32/arch_helpers.h
@@ -324,6 +324,23 @@
DEFINE_COPROCR_RW_FUNCS_64(amevcntr02, AMEVCNTR02)
DEFINE_COPROCR_RW_FUNCS_64(amevcntr03, AMEVCNTR03)
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr10, AMEVCNTR10);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr11, AMEVCNTR11);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr12, AMEVCNTR12);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr13, AMEVCNTR13);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr14, AMEVCNTR14);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr15, AMEVCNTR15);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr16, AMEVCNTR16);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr17, AMEVCNTR17);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr18, AMEVCNTR18);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr19, AMEVCNTR19);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr1a, AMEVCNTR1A);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr1b, AMEVCNTR1B);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr1c, AMEVCNTR1C);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr1d, AMEVCNTR1D);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr1e, AMEVCNTR1E);
+DEFINE_COPROCR_RW_FUNCS_64(amevcntr1f, AMEVCNTR1F);
+
/*
* TLBI operation prototypes
*/
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index dfa2f97..85b33aa 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -1141,6 +1141,7 @@
******************************************************************************/
#define ID_AA64SMFR0_EL1 S3_0_C0_C4_5
#define SMCR_EL3 S3_6_C1_C2_6
+#define SVCR S3_3_C4_C2_2
/* ID_AA64SMFR0_EL1 definitions */
#define ID_AA64SMFR0_EL1_SME_FA64_SHIFT U(63)
@@ -1529,6 +1530,11 @@
#define SCTLR2_EL1 S3_0_C1_C0_3
/*******************************************************************************
+ * FEAT_BRBE - Branch Record Buffer Extension Registers
+ ******************************************************************************/
+#define BRBCR_EL2 S2_4_C9_C0_0
+
+/*******************************************************************************
* FEAT_LS64_ACCDATA - LoadStore64B with status data
******************************************************************************/
#define ACCDATA_EL1 S3_0_C13_C0_5
@@ -1554,12 +1560,10 @@
******************************************************************************/
#define CPUPPMCR_EL3 S3_6_C15_C2_0
-#define CPUPPMCR_EL3_MPMMPINCTL_SHIFT UINT64_C(0)
-#define CPUPPMCR_EL3_MPMMPINCTL_MASK UINT64_C(0x1)
+#define CPUPPMCR_EL3_MPMMPINCTL_BIT BIT(0)
#define CPUMPMMCR_EL3 S3_6_C15_C2_1
-#define CPUMPMMCR_EL3_MPMM_EN_SHIFT UINT64_C(0)
-#define CPUMPMMCR_EL3_MPMM_EN_MASK UINT64_C(0x1)
+#define CPUMPMMCR_EL3_MPMM_EN_BIT BIT(0)
/* alternative system register encoding for the "sb" speculation barrier */
#define SYSREG_SB S0_3_C3_C0_7
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index 1d0a2e0..a580213 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -311,6 +311,10 @@
CREATE_FEATURE_FUNCS(feat_amu, id_aa64pfr0_el1, ID_AA64PFR0_AMU_SHIFT,
ID_AA64PFR0_AMU_MASK, 1U, ENABLE_FEAT_AMU)
+/* Auxiliary counters for FEAT_AMU */
+CREATE_FEATURE_FUNCS(feat_amu_aux, amcfgr_el0, AMCFGR_EL0_NCG_SHIFT,
+ AMCFGR_EL0_NCG_MASK, 1U, ENABLE_AMU_AUXILIARY_COUNTERS)
+
/* FEAT_AMUV1P1: AMU Extension v1.1 */
CREATE_FEATURE_FUNCS(feat_amuv1p1, id_aa64pfr0_el1, ID_AA64PFR0_AMU_SHIFT,
ID_AA64PFR0_AMU_MASK, ID_AA64PFR0_AMU_V1P1, ENABLE_FEAT_AMUv1p1)
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 8b92f19..f85da97 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -564,6 +564,27 @@
DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset0_el0, AMCNTENSET0_EL0)
DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr1_el0, AMCNTENCLR1_EL0)
DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset1_el0, AMCNTENSET1_EL0)
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr00_el0, AMEVCNTR00_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr01_el0, AMEVCNTR01_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr02_el0, AMEVCNTR02_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr03_el0, AMEVCNTR03_EL0);
+
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr10_el0, AMEVCNTR10_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr11_el0, AMEVCNTR11_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr12_el0, AMEVCNTR12_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr13_el0, AMEVCNTR13_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr14_el0, AMEVCNTR14_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr15_el0, AMEVCNTR15_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr16_el0, AMEVCNTR16_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr17_el0, AMEVCNTR17_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr18_el0, AMEVCNTR18_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr19_el0, AMEVCNTR19_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr1a_el0, AMEVCNTR1A_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr1b_el0, AMEVCNTR1B_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr1c_el0, AMEVCNTR1C_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr1d_el0, AMEVCNTR1D_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr1e_el0, AMEVCNTR1E_EL0);
+DEFINE_RENAME_SYSREG_RW_FUNCS(amevcntr1f_el0, AMEVCNTR1F_EL0);
DEFINE_RENAME_SYSREG_RW_FUNCS(pmblimitr_el1, PMBLIMITR_EL1)
@@ -572,6 +593,7 @@
DEFINE_RENAME_IDREG_READ_FUNC(id_aa64smfr0_el1, ID_AA64SMFR0_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(smcr_el3, SMCR_EL3)
+DEFINE_RENAME_SYSREG_RW_FUNCS(svcr, SVCR)
DEFINE_RENAME_SYSREG_READ_FUNC(erridr_el1, ERRIDR_EL1)
DEFINE_RENAME_SYSREG_WRITE_FUNC(errselr_el1, ERRSELR_EL1)
@@ -715,6 +737,9 @@
DEFINE_RENAME_SYSREG_RW_FUNCS(cpuppmcr_el3, CPUPPMCR_EL3)
DEFINE_RENAME_SYSREG_RW_FUNCS(cpumpmmcr_el3, CPUMPMMCR_EL3)
+/* Armv9.1 FEAT_BRBE Registers */
+DEFINE_RENAME_SYSREG_RW_FUNCS(brbcr_el2, BRBCR_EL2)
+
/* Armv9.2 RME Registers */
DEFINE_RENAME_SYSREG_RW_FUNCS(gptbr_el3, GPTBR_EL3)
DEFINE_RENAME_SYSREG_RW_FUNCS(gpccr_el3, GPCCR_EL3)
diff --git a/include/arch/aarch64/asm_macros.S b/include/arch/aarch64/asm_macros.S
index ff01278..dce07d9 100644
--- a/include/arch/aarch64/asm_macros.S
+++ b/include/arch/aarch64/asm_macros.S
@@ -8,6 +8,7 @@
#include <arch.h>
#include <common/asm_macros_common.S>
+#include <lib/cpus/cpu_ops.h>
#include <lib/spinlock.h>
/*
@@ -340,4 +341,26 @@
mrs \reg, ID_AA64ISAR2_EL1
ands \reg, \reg, #(ID_AA64ISAR2_SYSREG128_MASK << ID_AA64ISAR2_SYSREG128_SHIFT)
.endm
+
+.macro call_reset_handler
+#if !(defined(IMAGE_BL2) && ENABLE_RME)
+ /* ---------------------------------------------------------------------
+ * It is a cold boot.
+ * Perform any processor specific actions upon reset e.g. cache, TLB
+ * invalidations etc.
+ * ---------------------------------------------------------------------
+ */
+ /* The plat_reset_handler can clobber x0 - x18, x30 */
+ bl plat_reset_handler
+
+ /* Get the matching cpu_ops pointer */
+ bl get_cpu_ops_ptr
+
+ /* Get the cpu_ops reset handler */
+ ldr x2, [x0, #CPU_RESET_FUNC]
+
+ /* The cpu_ops reset handler can clobber x0 - x19, x30 */
+ blr x2
+#endif
+.endm
#endif /* ASM_MACROS_S */
diff --git a/include/arch/aarch64/el2_common_macros.S b/include/arch/aarch64/el2_common_macros.S
index b9b0e3d..5db6831 100644
--- a/include/arch/aarch64/el2_common_macros.S
+++ b/include/arch/aarch64/el2_common_macros.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2024, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -293,7 +293,7 @@
* invalidations etc.
* ---------------------------------------------------------------------
*/
- bl reset_handler
+ call_reset_handler
el2_arch_init_common
diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S
index 204625c..2f2aeaf 100644
--- a/include/arch/aarch64/el3_common_macros.S
+++ b/include/arch/aarch64/el3_common_macros.S
@@ -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
*/
@@ -49,7 +49,9 @@
* due to a NULL TPIDR_EL3.
* ---------------------------------------------------------------------
*/
- bl init_cpu_data_ptr
+ bl plat_my_core_pos
+ bl _cpu_data_by_index
+ msr tpidr_el3, x0
#endif /* IMAGE_BL31 */
/* ---------------------------------------------------------------------
@@ -219,15 +221,7 @@
msr vbar_el3, x0
isb
-#if !(defined(IMAGE_BL2) && ENABLE_RME)
- /* ---------------------------------------------------------------------
- * It is a cold boot.
- * Perform any processor specific actions upon reset e.g. cache, TLB
- * invalidations etc.
- * ---------------------------------------------------------------------
- */
- bl reset_handler
-#endif
+ call_reset_handler
el3_arch_init_common
@@ -460,6 +454,10 @@
* Necessary on PMUv3 <= p7 where MDCR_EL3.{SCCD,MCCD} are not
* available.
*
+ * CPTR_EL3.EZ: Set to one so that accesses to ZCR_EL3 do not trap
+ * CPTR_EL3.TFP: Set to zero so that advanced SIMD operations don't trap
+ * CPTR_EL3.ESM: Set to one so that SME related registers don't trap
+ *
* PSTATE.DIT: Set to one to enable the Data Independent Timing (DIT)
* functionality, if implemented in EL3.
* ---------------------------------------------------------------------
@@ -479,6 +477,12 @@
orr x15, x15, #PMCR_EL0_DP_BIT
msr pmcr_el0, x15
+ mrs x15, cptr_el3
+ orr x15, x15, #CPTR_EZ_BIT
+ orr x15, x15, #ESM_BIT
+ bic x15, x15, #TFP_BIT
+ msr cptr_el3, x15
+
#if ENABLE_FEAT_DIT
#if ENABLE_FEAT_DIT > 1
mrs x15, id_aa64pfr0_el1
diff --git a/include/common/fdt_wrappers.h b/include/common/fdt_wrappers.h
index de08f1d..7f6af59 100644
--- a/include/common/fdt_wrappers.h
+++ b/include/common/fdt_wrappers.h
@@ -49,6 +49,8 @@
int fdtw_find_or_add_subnode(void *fdt, int parentoffset, const char *name);
+uint64_t fdt_read_prop_cells(const fdt32_t *prop, int nr_cells);
+
static inline uint32_t fdt_blob_size(const void *dtb)
{
const uint32_t *dtb_header = (const uint32_t *)dtb;
diff --git a/include/drivers/arm/css/css_scp.h b/include/drivers/arm/css/css_scp.h
index 2b506ea..5395546 100644
--- a/include/drivers/arm/css/css_scp.h
+++ b/include/drivers/arm/css/css_scp.h
@@ -22,9 +22,9 @@
void css_scp_off(const struct psci_power_state *target_state);
void css_scp_on(u_register_t mpidr);
int css_scp_get_power_state(u_register_t mpidr, unsigned int power_level);
-void __dead2 css_scp_sys_shutdown(void);
-void __dead2 css_scp_sys_reboot(void);
-void __dead2 css_scp_system_off(int state);
+void css_scp_sys_shutdown(void);
+void css_scp_sys_reboot(void);
+void css_scp_system_off(int state);
/* API for SCP Boot Image transfer. Return 0 on success, -1 on error */
int css_scp_boot_image_xfer(void *image, unsigned int image_size);
diff --git a/include/drivers/arm/gic600_multichip.h b/include/drivers/arm/gic600_multichip.h
index 978d735..d0f9027 100644
--- a/include/drivers/arm/gic600_multichip.h
+++ b/include/drivers/arm/gic600_multichip.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, ARM Limited. All rights reserved.
+ * Copyright (c) 2019-2024, ARM Limited. All rights reserved.
* Copyright (c) 2023, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -49,10 +49,10 @@
* value of {0, 0, 0} should be passed.
******************************************************************************/
struct gic600_multichip_data {
- uintptr_t rt_owner_base;
+ uintptr_t base_addrs[GIC600_MAX_MULTICHIP];
unsigned int rt_owner;
unsigned int chip_count;
- uint64_t chip_addrs[GIC600_MAX_MULTICHIP];
+ uint64_t chip_addrs[GIC600_MAX_MULTICHIP][GIC600_MAX_MULTICHIP];
multichip_spi_ids_desc_t spi_ids[GIC600_MAX_MULTICHIP];
};
diff --git a/include/drivers/arm/mhu.h b/include/drivers/arm/mhu.h
index 31c6a81..cc74e27 100644
--- a/include/drivers/arm/mhu.h
+++ b/include/drivers/arm/mhu.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -25,6 +26,14 @@
};
/**
+ * Structure used by RSE comms
+ */
+struct mhu_addr {
+ uintptr_t sender_base;
+ uintptr_t receiver_base;
+};
+
+/**
* Initializes sender MHU.
*
* mhu_sender_base Base address of sender MHU.
diff --git a/include/drivers/arm/rse_comms.h b/include/drivers/arm/rse_comms.h
index e4169a5..43c8b70 100644
--- a/include/drivers/arm/rse_comms.h
+++ b/include/drivers/arm/rse_comms.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -8,8 +8,12 @@
#ifndef RSE_COMMS_H
#define RSE_COMMS_H
+#include <stddef.h>
#include <stdint.h>
-int rse_comms_init(uintptr_t mhu_sender_base, uintptr_t mhu_receiver_base);
+size_t rse_mbx_get_max_message_size(void);
+int rse_mbx_send_data(const uint8_t *send_buffer, size_t size);
+int rse_mbx_receive_data(uint8_t *receive_buffer, size_t *size);
+int rse_mbx_init(const void *init_data);
#endif /* RSE_COMMS_H */
diff --git a/include/drivers/nxp/clk/s32cc/s32cc-clk-ids.h b/include/drivers/nxp/clk/s32cc/s32cc-clk-ids.h
index d34dc22..63716e8 100644
--- a/include/drivers/nxp/clk/s32cc/s32cc-clk-ids.h
+++ b/include/drivers/nxp/clk/s32cc/s32cc-clk-ids.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause */
/*
- * Copyright 2024 NXP
+ * Copyright 2024-2025 NXP
*/
#ifndef S32CC_CLK_IDS_H
#define S32CC_CLK_IDS_H
@@ -103,4 +103,8 @@
#define S32CC_CLK_MC_CGM5_MUX0 S32CC_ARCH_CLK(20)
#define S32CC_CLK_DDR S32CC_ARCH_CLK(21)
+/* USDHC clock */
+#define S32CC_CLK_MC_CGM0_MUX14 S32CC_ARCH_CLK(22)
+#define S32CC_CLK_USDHC S32CC_ARCH_CLK(23)
+
#endif /* S32CC_CLK_IDS_H */
diff --git a/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h b/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h
index c91f3b6..285aeb3 100644
--- a/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h
+++ b/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h
@@ -19,6 +19,7 @@
s32cc_pll_out_div_t,
s32cc_dfs_t,
s32cc_dfs_div_t,
+ s32cc_cgm_div_t,
s32cc_clkmux_t,
s32cc_shared_clkmux_t,
s32cc_fixed_div_t,
@@ -37,6 +38,7 @@
S32CC_CGM0,
S32CC_CGM1,
S32CC_DDR_PLL,
+ S32CC_PERIPH_DFS,
S32CC_CGM5,
};
@@ -287,6 +289,22 @@
.block = (BLOCK), \
}
+struct s32cc_cgm_div {
+ struct s32cc_clk_obj desc;
+ struct s32cc_clk_obj *parent;
+ unsigned long freq;
+ uint32_t index;
+};
+
+#define S32CC_CGM_DIV_INIT(PARENT, INDEX) \
+{ \
+ .desc = { \
+ .type = s32cc_cgm_div_t, \
+ }, \
+ .parent = &(PARENT).desc, \
+ .index = (INDEX), \
+}
+
static inline struct s32cc_osc *s32cc_obj2osc(const struct s32cc_clk_obj *mod)
{
uintptr_t osc_addr;
@@ -399,4 +417,12 @@
return (struct s32cc_part_block_link *)blk_link;
}
+static inline struct s32cc_cgm_div *s32cc_obj2cgmdiv(const struct s32cc_clk_obj *mod)
+{
+ uintptr_t cgm_div_addr;
+
+ cgm_div_addr = ((uintptr_t)mod) - offsetof(struct s32cc_cgm_div, desc);
+ return (struct s32cc_cgm_div *)cgm_div_addr;
+}
+
#endif /* S32CC_CLK_MODULES_H */
diff --git a/include/lib/cpus/aarch32/cpu_macros.S b/include/lib/cpus/aarch32/cpu_macros.S
index cfa5831..31f8811 100644
--- a/include/lib/cpus/aarch32/cpu_macros.S
+++ b/include/lib/cpus/aarch32/cpu_macros.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -48,8 +48,7 @@
* _midr:
* Numeric value expected to read from CPU's MIDR
* _resetfunc:
- * Reset function for the CPU. If there's no CPU reset function,
- * specify CPU_NO_RESET_FUNC
+ * Reset function for the CPU
* _power_down_ops:
* Comma-separated list of functions to perform power-down
* operatios on the CPU. At least one, and up to
@@ -173,11 +172,6 @@
\_cpu\()_errata_list_start:
.endif
- /* unused on AArch32, maintain for portability */
- .word 0
- /* TODO(errata ABI): this prevents all checker functions from
- * being optimised away. Can be done away with unless the ABI
- * needs them */
.ifnb \_special
.word check_errata_\_special
.elseif \_cve
@@ -189,9 +183,7 @@
.word \_id
.hword \_cve
.byte \_chosen
- /* TODO(errata ABI): mitigated field for known but unmitigated
- * errata*/
- .byte 0x1
+ .byte 0x0 /* alignment */
.popsection
.endm
diff --git a/include/lib/cpus/aarch64/cortex_a320.h b/include/lib/cpus/aarch64/cortex_a320.h
new file mode 100644
index 0000000..5231151
--- /dev/null
+++ b/include/lib/cpus/aarch64/cortex_a320.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2024-2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CORTEX_A320_H
+#define CORTEX_A320_H
+
+#define CORTEX_A320_MIDR U(0x410FD8F0)
+
+/*******************************************************************************
+ * CPU Extended Control register specific definitions
+ ******************************************************************************/
+#define CORTEX_A320_CPUECTLR_EL1 S3_0_C15_C1_4
+#define CORTEX_A320_CPUECTLR_EL1_EXTLLC_BIT U(0)
+
+/*******************************************************************************
+ * CPU Power Control register specific definitions
+ ******************************************************************************/
+#define CORTEX_A320_CPUPWRCTLR_EL1 S3_0_C15_C2_7
+#define CORTEX_A320_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1)
+
+#endif /* CORTEX_A320_H */
diff --git a/include/lib/cpus/aarch64/cortex_alto.h b/include/lib/cpus/aarch64/cortex_alto.h
index 1c8786a..9e2929f 100644
--- a/include/lib/cpus/aarch64/cortex_alto.h
+++ b/include/lib/cpus/aarch64/cortex_alto.h
@@ -20,10 +20,4 @@
#define CORTEX_ALTO_IMP_CPUPWRCTLR_EL1 S3_0_C15_C2_7
#define CORTEX_ALTO_IMP_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT U(1)
-/*******************************************************************************
- * SME Control registers
- ******************************************************************************/
-#define CORTEX_ALTO_SVCRSM S0_3_C4_C2_3
-#define CORTEX_ALTO_SVCRZA S0_3_C4_C4_3
-
#endif /* CORTEX_ALTO_H */
diff --git a/include/lib/cpus/aarch64/cortex_arcadia.h b/include/lib/cpus/aarch64/cortex_arcadia.h
deleted file mode 100644
index 8b74de2..0000000
--- a/include/lib/cpus/aarch64/cortex_arcadia.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2024, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef CORTEX_ARCADIA_H
-#define CORTEX_ARCADIA_H
-
-#define CORTEX_ARCADIA_MIDR U(0x410FD8F0)
-
-/*******************************************************************************
- * CPU Extended Control register specific definitions
- ******************************************************************************/
-#define CORTEX_ARCADIA_CPUECTLR_EL1 S3_0_C15_C1_4
-#define CORTEX_ARCADIA_CPUECTLR_EL1_EXTLLC_BIT U(0)
-
-/*******************************************************************************
- * CPU Power Control register specific definitions
- ******************************************************************************/
-#define CORTEX_ARCADIA_CPUPWRCTLR_EL1 S3_0_C15_C2_7
-#define CORTEX_ARCADIA_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1)
-
-#endif /* CORTEX_ARCADIA_H */
diff --git a/include/lib/cpus/aarch64/cortex_gelas.h b/include/lib/cpus/aarch64/cortex_gelas.h
index 486b868..9024faf 100644
--- a/include/lib/cpus/aarch64/cortex_gelas.h
+++ b/include/lib/cpus/aarch64/cortex_gelas.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -23,10 +23,4 @@
#define CORTEX_GELAS_CPUPWRCTLR_EL1 S3_0_C15_C2_7
#define CORTEX_GELAS_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1)
-/*******************************************************************************
- * SME Control registers
- ******************************************************************************/
-#define CORTEX_GELAS_SVCRSM S0_3_C4_C2_3
-#define CORTEX_GELAS_SVCRZA S0_3_C4_C4_3
-
#endif /* CORTEX_GELAS_H */
diff --git a/include/lib/cpus/aarch64/cpu_macros.S b/include/lib/cpus/aarch64/cpu_macros.S
index 0ce9c3c..a43746f 100644
--- a/include/lib/cpus/aarch64/cpu_macros.S
+++ b/include/lib/cpus/aarch64/cpu_macros.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -49,8 +49,7 @@
* _midr:
* Numeric value expected to read from CPU's MIDR
* _resetfunc:
- * Reset function for the CPU. If there's no CPU reset function,
- * specify CPU_NO_RESET_FUNC
+ * Reset function for the CPU.
* _extra1:
* This is a placeholder for future per CPU operations. Currently,
* some CPUs use this entry to set a test function to determine if
@@ -239,50 +238,22 @@
* _apply_at_reset:
* Whether the erratum should be automatically applied at reset
*/
-.macro add_erratum_entry _cpu:req, _cve:req, _id:req, _chosen:req, _apply_at_reset:req
+.macro add_erratum_entry _cpu:req, _cve:req, _id:req, _chosen:req
+#if REPORT_ERRATA || ERRATA_ABI_SUPPORT
.pushsection .rodata.errata_entries
.align 3
.ifndef \_cpu\()_errata_list_start
\_cpu\()_errata_list_start:
.endif
- /* check if unused and compile out if no references */
- .if \_apply_at_reset && \_chosen
- .quad erratum_\_cpu\()_\_id\()_wa
- .else
- .quad 0
- .endif
- /* TODO(errata ABI): this prevents all checker functions from
- * being optimised away. Can be done away with unless the ABI
- * needs them */
.quad check_erratum_\_cpu\()_\_id
/* Will fit CVEs with up to 10 character in the ID field */
.word \_id
.hword \_cve
.byte \_chosen
- /* TODO(errata ABI): mitigated field for known but unmitigated
- * errata */
- .byte 0x1
+ .byte 0x0 /* alignment */
.popsection
-.endm
-
-.macro _workaround_start _cpu:req, _cve:req, _id:req, _chosen:req, _apply_at_reset:req
- add_erratum_entry \_cpu, \_cve, \_id, \_chosen, \_apply_at_reset
-
- func erratum_\_cpu\()_\_id\()_wa
- mov x8, x30
-
- /* save rev_var for workarounds that might need it but don't
- * restore to x0 because few will care */
- mov x7, x0
- bl check_erratum_\_cpu\()_\_id
- cbz x0, erratum_\_cpu\()_\_id\()_skip
-.endm
-
-.macro _workaround_end _cpu:req, _id:req
- erratum_\_cpu\()_\_id\()_skip:
- ret x8
- endfunc erratum_\_cpu\()_\_id\()_wa
+#endif
.endm
/*******************************************************************************
@@ -312,7 +283,22 @@
* _wa clobbers: x0-x8 (PCS compliant)
*/
.macro workaround_reset_start _cpu:req, _cve:req, _id:req, _chosen:req
- _workaround_start \_cpu, \_cve, \_id, \_chosen, 1
+ add_erratum_entry \_cpu, \_cve, \_id, \_chosen
+
+ .if \_chosen
+ /* put errata directly into the reset function */
+ .pushsection .text.asm.\_cpu\()_reset_func, "ax"
+ .else
+ /* or something else that will get garbage collected by the
+ * linker */
+ .pushsection .text.asm.erratum_\_cpu\()_\_id\()_wa, "ax"
+ .endif
+ /* revision is stored in x14, get it */
+ mov x0, x14
+ bl check_erratum_\_cpu\()_\_id
+ /* save rev_var for workarounds that might need it */
+ mov x7, x14
+ cbz x0, erratum_\_cpu\()_\_id\()_skip_reset
.endm
/*
@@ -323,6 +309,10 @@
* for errata applied in generic code
*/
.macro workaround_runtime_start _cpu:req, _cve:req, _id:req, _chosen:req, _midr
+ add_erratum_entry \_cpu, \_cve, \_id, \_chosen
+
+ func erratum_\_cpu\()_\_id\()_wa
+ mov x8, x30
/*
* Let errata specify if they need MIDR checking. Sadly, storing the
* MIDR in an .equ to retrieve automatically blows up as it stores some
@@ -330,11 +320,15 @@
*/
.ifnb \_midr
jump_if_cpu_midr \_midr, 1f
- b erratum_\_cpu\()_\_id\()_skip
+ b erratum_\_cpu\()_\_id\()_skip_runtime
1:
.endif
- _workaround_start \_cpu, \_cve, \_id, \_chosen, 0
+ /* save rev_var for workarounds that might need it but don't
+ * restore to x0 because few will care */
+ mov x7, x0
+ bl check_erratum_\_cpu\()_\_id
+ cbz x0, erratum_\_cpu\()_\_id\()_skip_runtime
.endm
/*
@@ -342,7 +336,8 @@
* is kept here so the same #define can be used as that macro
*/
.macro workaround_reset_end _cpu:req, _cve:req, _id:req
- _workaround_end \_cpu, \_id
+ erratum_\_cpu\()_\_id\()_skip_reset:
+ .popsection
.endm
/*
@@ -362,7 +357,9 @@
.ifb \_no_isb
isb
.endif
- _workaround_end \_cpu, \_id
+ erratum_\_cpu\()_\_id\()_skip_runtime:
+ ret x8
+ endfunc erratum_\_cpu\()_\_id\()_wa
.endm
/*******************************************************************************
@@ -402,6 +399,18 @@
msr \_reg, x1
.endm
+/*
+ * Toggle a bit in a system register. Can toggle multiple bits but is limited by
+ * the way the EOR instrucion encodes them.
+ *
+ * see sysreg_bit_set for usage
+ */
+.macro sysreg_bit_toggle _reg:req, _bit:req, _assert=1
+ mrs x1, \_reg
+ eor x1, x1, #\_bit
+ msr \_reg, x1
+.endm
+
.macro override_vector_table _table:req
adr x1, \_table
msr vbar_el3, x1
@@ -429,6 +438,29 @@
.endm
/*
+ * Extract CPU revision and variant, and combine them into a single numeric for
+ * easier comparison.
+ *
+ * _res:
+ * register where the result will be placed
+ * _tmp:
+ * register to clobber for temporaries
+ */
+.macro get_rev_var _res:req, _tmp:req
+ mrs \_tmp, midr_el1
+
+ /*
+ * Extract the variant[23:20] and revision[3:0] from MIDR, and pack them
+ * as variant[7:4] and revision[3:0] of x0.
+ *
+ * First extract x1[23:16] to x0[7:0] and zero fill the rest. Then
+ * extract x1[3:0] into x0[3:0] retaining other bits.
+ */
+ ubfx \_res, \_tmp, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS)
+ bfxil \_res, \_tmp, #MIDR_REV_SHIFT, #MIDR_REV_BITS
+.endm
+
+/*
* Apply erratum
*
* _cpu:
@@ -451,7 +483,7 @@
* clobbers: x0-x10 (PCS compliant)
*/
.macro apply_erratum _cpu:req, _cve:req, _id:req, _chosen:req, _get_rev=GET_CPU_REV
- .if (\_chosen & \_get_rev)
+ .if (\_chosen && \_get_rev)
mov x9, x30
bl cpu_get_rev_var
mov x10, x0
@@ -467,8 +499,35 @@
.endm
/*
- * Helpers to select which revisions errata apply to. Don't leave a link
- * register as the cpu_rev_var_*** will call the ret and we can save on one.
+ * Helpers to report if an erratum applies. Compares the given revision variant
+ * to the given value. Return ERRATA_APPLIES or ERRATA_NOT_APPLIES accordingly.
+ *
+ * _rev_num: the given revision variant. Or
+ * _rev_num_lo,_rev_num_hi: the lower and upper bounds of the revision variant
+ *
+ * in body:
+ * clobber: x0
+ * argument: x0 - cpu_rev_var
+ */
+.macro cpu_rev_var_ls _rev_num:req
+ cmp x0, #\_rev_num
+ cset x0, ls
+.endm
+
+.macro cpu_rev_var_hs _rev_num:req
+ cmp x0, #\_rev_num
+ cset x0, hs
+.endm
+
+.macro cpu_rev_var_range _rev_num_lo:req, _rev_num_hi:req
+ cmp x0, #\_rev_num_lo
+ mov x1, #\_rev_num_hi
+ ccmp x0, x1, #2, hs
+ cset x0, ls
+.endm
+
+/*
+ * Helpers to select which revisions errata apply to.
*
* _cpu:
* Name of cpu as given to declare_cpu_ops
@@ -484,28 +543,27 @@
* Revision to apply to
*
* in body:
- * clobber: x0 to x4
+ * clobber: x0 to x1
* argument: x0 - cpu_rev_var
*/
.macro check_erratum_ls _cpu:req, _cve:req, _id:req, _rev_num:req
func check_erratum_\_cpu\()_\_id
- mov x1, #\_rev_num
- b cpu_rev_var_ls
+ cpu_rev_var_ls \_rev_num
+ ret
endfunc check_erratum_\_cpu\()_\_id
.endm
.macro check_erratum_hs _cpu:req, _cve:req, _id:req, _rev_num:req
func check_erratum_\_cpu\()_\_id
- mov x1, #\_rev_num
- b cpu_rev_var_hs
+ cpu_rev_var_hs \_rev_num
+ ret
endfunc check_erratum_\_cpu\()_\_id
.endm
.macro check_erratum_range _cpu:req, _cve:req, _id:req, _rev_num_lo:req, _rev_num_hi:req
func check_erratum_\_cpu\()_\_id
- mov x1, #\_rev_num_lo
- mov x2, #\_rev_num_hi
- b cpu_rev_var_range
+ cpu_rev_var_range \_rev_num_lo, \_rev_num_hi
+ ret
endfunc check_erratum_\_cpu\()_\_id
.endm
@@ -520,7 +578,10 @@
endfunc check_erratum_\_cpu\()_\_id
.endm
-/* provide a shorthand for the name format for annoying errata */
+/*
+ * provide a shorthand for the name format for annoying errata
+ * body: clobber x0 to x4
+ */
.macro check_erratum_custom_start _cpu:req, _cve:req, _id:req
func check_erratum_\_cpu\()_\_id
.endm
@@ -535,7 +596,21 @@
******************************************************************************/
/*
+ * Helper to register a cpu with the errata framework. Begins the definition of
+ * the reset function.
+ *
+ * _cpu:
+ * Name of cpu as given to declare_cpu_ops
+ */
+.macro cpu_reset_prologue _cpu:req
+ func \_cpu\()_reset_func
+ mov x15, x30
+ get_rev_var x14, x0
+.endm
+
+/*
- * Wrapper to automatically apply all reset-time errata. Will end with an isb.
+ * Wrapper of the reset function to automatically apply all reset-time errata.
+ * Will end with an isb.
*
* _cpu:
* Name of cpu as given to declare_cpu_ops
@@ -545,39 +620,9 @@
* argument x14 - cpu_rev_var
*/
.macro cpu_reset_func_start _cpu:req
- func \_cpu\()_reset_func
- mov x15, x30
- bl cpu_get_rev_var
- mov x14, x0
-
- /* short circuit the location to avoid searching the list */
- adrp x12, \_cpu\()_errata_list_start
- add x12, x12, :lo12:\_cpu\()_errata_list_start
- adrp x13, \_cpu\()_errata_list_end
- add x13, x13, :lo12:\_cpu\()_errata_list_end
-
- errata_begin:
- /* if head catches up with end of list, exit */
- cmp x12, x13
- b.eq errata_end
-
- ldr x10, [x12, #ERRATUM_WA_FUNC]
- /* TODO(errata ABI): check mitigated and checker function fields
- * for 0 */
- ldrb w11, [x12, #ERRATUM_CHOSEN]
-
- /* skip if not chosen */
- cbz x11, 1f
- /* skip if runtime erratum */
- cbz x10, 1f
-
- /* put cpu revision in x0 and call workaround */
- mov x0, x14
- blr x10
- 1:
- add x12, x12, #ERRATUM_ENTRY_SIZE
- b errata_begin
- errata_end:
+ /* the func/endfunc macros will change sections. So change the section
+ * back to the reset function's */
+ .section .text.asm.\_cpu\()_reset_func, "ax"
.endm
.macro cpu_reset_func_end _cpu:req
@@ -586,4 +631,21 @@
endfunc \_cpu\()_reset_func
.endm
+/*
+ * Helper macro that enables Maximum Power Mitigation Mechanism (MPMM) on
+ * compatible Arm cores.
+ *
+ * Clobbers x0.
+ */
+.macro enable_mpmm
+#if ENABLE_MPMM
+ mrs x0, CPUPPMCR_EL3
+ /* if CPUPPMCR_EL3.MPMMPINCTL != 0, skip enabling MPMM */
+ ands x0, x0, CPUPPMCR_EL3_MPMMPINCTL_BIT
+ b.ne 1f
+ sysreg_bit_set CPUPPMCR_EL3, CPUMPMMCR_EL3_MPMM_EN_BIT
+ 1:
+#endif
+.endm
+
#endif /* CPU_MACROS_S */
diff --git a/include/lib/cpus/aarch64/dsu_def.h b/include/lib/cpus/aarch64/dsu_def.h
index 51fbfd1..78b3e7f 100644
--- a/include/lib/cpus/aarch64/dsu_def.h
+++ b/include/lib/cpus/aarch64/dsu_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -40,7 +40,23 @@
********************************************************************/
#define DSU_ERRATA_936184_MASK (U(0x3) << 15)
+#define CPUCFR_EL1 S3_0_C15_C0_0
+/* SCU bit of CPU Configuration Register, EL1 */
+#define SCU_SHIFT U(2)
+
#ifndef __ASSEMBLER__
-void dsu_pwr_dwn(void);
+DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpwrctlr_el1, CLUSTERPWRCTLR_EL1);
+
+/* ---------------------------------------------
+ * controls power features of the cluster
+ * 1. Cache portion power not request
+ * 2. Disable the retention circuit
+ * ---------------------------------------------
+ */
+static inline void dsu_pwr_dwn(void)
+{
+ write_clusterpwrctlr_el1(0);
+ isb();
+}
#endif
#endif /* DSU_DEF_H */
diff --git a/include/lib/cpus/aarch64/dsu_macros.S b/include/lib/cpus/aarch64/dsu_macros.S
new file mode 100644
index 0000000..6c8cb69
--- /dev/null
+++ b/include/lib/cpus/aarch64/dsu_macros.S
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2019-2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DSU_MACROS_S
+#define DSU_MACROS_S
+
+#include <asm_macros.S>
+#include <dsu_def.h>
+#include <lib/cpus/errata.h>
+
+.macro check_errata_dsu_798953_impl
+ mov x2, #ERRATA_APPLIES
+ mov x3, #ERRATA_NOT_APPLIES
+
+ /* Check if DSU is equal to r0p0 */
+ mrs x1, CLUSTERIDR_EL1
+
+ /* DSU variant and revision bitfields in CLUSTERIDR are adjacent */
+ ubfx x0, x1, #CLUSTERIDR_REV_SHIFT,\
+ #(CLUSTERIDR_REV_BITS + CLUSTERIDR_VAR_BITS)
+ mov x1, #(0x0 << CLUSTERIDR_REV_SHIFT)
+ cmp x0, x1
+ csel x0, x2, x3, EQ
+.endm
+
+.macro errata_dsu_798953_wa_impl
+ /* If erratum applies, disable high-level clock gating */
+ mrs x0, CLUSTERACTLR_EL1
+ orr x0, x0, #CLUSTERACTLR_EL1_DISABLE_CLOCK_GATING
+ msr CLUSTERACTLR_EL1, x0
+.endm
+
+.macro branch_if_scu_not_present _target:req
+ /* Check if the SCU L3 Unit is present on the DSU */
+ mrs x0, CPUCFR_EL1
+ ubfx x0, x0, #SCU_SHIFT, #1
+ eor x0, x0, #1
+ /* If SCU is not present, return without applying patch */
+ cmp x0, xzr
+ mov x0, #ERRATA_NOT_APPLIES
+ b.eq \_target
+.endm
+
+.macro check_errata_dsu_936184_impl
+ mov x0, #ERRATA_NOT_APPLIES
+ /* Erratum applies only if DSU has the ACP interface */
+ mrs x1, CLUSTERCFR_EL1
+ ubfx x1, x1, #CLUSTERCFR_ACP_SHIFT, #1
+ cbz x1, 1f
+
+ /* If ACP is present, check if DSU is older than r2p0 */
+ mrs x1, CLUSTERIDR_EL1
+
+ /* DSU variant and revision bitfields in CLUSTERIDR are adjacent */
+ ubfx x2, x1, #CLUSTERIDR_REV_SHIFT,\
+ #(CLUSTERIDR_REV_BITS + CLUSTERIDR_VAR_BITS)
+ cmp x2, #(0x2 << CLUSTERIDR_VAR_SHIFT)
+ b.hs 1f
+ mov x0, #ERRATA_APPLIES
+1:
+.endm
+
+.macro errata_dsu_936184_wa_impl
+ /* If erratum applies, we set a mask to a DSU control register */
+ mrs x0, CLUSTERACTLR_EL1
+ ldr x1, =DSU_ERRATA_936184_MASK
+ orr x0, x0, x1
+ msr CLUSTERACTLR_EL1, x0
+.endm
+
+.macro check_errata_dsu_2313941_impl
+ mov x2, #ERRATA_APPLIES
+ mov x3, #ERRATA_NOT_APPLIES
+
+ /* Check if DSU version is less than or equal to r3p1 */
+ mrs x1, CLUSTERIDR_EL1
+
+ mov x0, #ERRATA_NOT_APPLIES
+ /* DSU variant and revision bitfields in CLUSTERIDR are adjacent */
+ ubfx x0, x1, #CLUSTERIDR_REV_SHIFT,\
+ #(CLUSTERIDR_REV_BITS + CLUSTERIDR_VAR_BITS)
+ mov x1, #(0x31 << CLUSTERIDR_REV_SHIFT)
+ cmp x0, x1
+ csel x0, x2, x3, LS
+1:
+.endm
+
+.macro errata_dsu_2313941_wa_impl
+ /* If erratum applies, disable high-level clock gating */
+ mrs x0, CLUSTERACTLR_EL1
+ orr x0, x0, #CLUSTERACTLR_EL1_DISABLE_SCLK_GATING
+ msr CLUSTERACTLR_EL1, x0
+.endm
+#endif /* DSU_MACROS_S */
diff --git a/include/lib/cpus/aarch64/neoverse_n_common.h b/include/lib/cpus/aarch64/neoverse_n_common.h
deleted file mode 100644
index 7cb91cd..0000000
--- a/include/lib/cpus/aarch64/neoverse_n_common.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef NEOVERSE_N_COMMON_H
-#define NEOVERSE_N_COMMON_H
-
-/******************************************************************************
- * Neoverse Nx CPU Configuration register definitions
- *****************************************************************************/
-#define CPUCFR_EL1 S3_0_C15_C0_0
-
-/* SCU bit of CPU Configuration Register, EL1 */
-#define SCU_SHIFT U(2)
-
-#endif /* NEOVERSE_N_COMMON_H */
diff --git a/include/lib/cpus/aarch64/travis.h b/include/lib/cpus/aarch64/travis.h
index a8a2556..b622ea0 100644
--- a/include/lib/cpus/aarch64/travis.h
+++ b/include/lib/cpus/aarch64/travis.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -20,10 +20,4 @@
#define TRAVIS_IMP_CPUPWRCTLR_EL1 S3_0_C15_C2_7
#define TRAVIS_IMP_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT U(1)
-/*******************************************************************************
- * SME Control registers
- ******************************************************************************/
-#define TRAVIS_SVCRSM S0_3_C4_C2_3
-#define TRAVIS_SVCRZA S0_3_C4_C4_3
-
#endif /* TRAVIS_H */
diff --git a/include/lib/cpus/cpu_ops.h b/include/lib/cpus/cpu_ops.h
index c1bdf8d..0b08919 100644
--- a/include/lib/cpus/cpu_ops.h
+++ b/include/lib/cpus/cpu_ops.h
@@ -21,8 +21,6 @@
/* The number of CPU operations allowed */
#define CPU_MAX_PWR_DWN_OPS 2
-/* Special constant to specify that CPU has no reset function */
-#define CPU_NO_RESET_FUNC 0
#if __aarch64__
#define CPU_NO_EXTRA1_FUNC 0
diff --git a/include/lib/cpus/errata.h b/include/lib/cpus/errata.h
index b9166f7..10b949f 100644
--- a/include/lib/cpus/errata.h
+++ b/include/lib/cpus/errata.h
@@ -9,20 +9,18 @@
#include <lib/cpus/cpu_ops.h>
-#define ERRATUM_WA_FUNC_SIZE CPU_WORD_SIZE
#define ERRATUM_CHECK_FUNC_SIZE CPU_WORD_SIZE
#define ERRATUM_ID_SIZE 4
#define ERRATUM_CVE_SIZE 2
#define ERRATUM_CHOSEN_SIZE 1
-#define ERRATUM_MITIGATED_SIZE 1
+#define ERRATUM_ALIGNMENT_SIZE 1
-#define ERRATUM_WA_FUNC 0
-#define ERRATUM_CHECK_FUNC ERRATUM_WA_FUNC + ERRATUM_WA_FUNC_SIZE
+#define ERRATUM_CHECK_FUNC 0
#define ERRATUM_ID ERRATUM_CHECK_FUNC + ERRATUM_CHECK_FUNC_SIZE
#define ERRATUM_CVE ERRATUM_ID + ERRATUM_ID_SIZE
#define ERRATUM_CHOSEN ERRATUM_CVE + ERRATUM_CVE_SIZE
-#define ERRATUM_MITIGATED ERRATUM_CHOSEN + ERRATUM_CHOSEN_SIZE
-#define ERRATUM_ENTRY_SIZE ERRATUM_MITIGATED + ERRATUM_MITIGATED_SIZE
+#define ERRATUM_ALIGNMENT ERRATUM_CHOSEN + ERRATUM_CHOSEN_SIZE
+#define ERRATUM_ENTRY_SIZE ERRATUM_ALIGNMENT + ERRATUM_ALIGNMENT_SIZE
/* Errata status */
#define ERRATA_NOT_APPLIES 0
@@ -39,15 +37,13 @@
* uintptr_t will reflect the change and the alignment will be correct in both.
*/
struct erratum_entry {
- uintptr_t (*wa_func)(uint64_t cpu_rev);
uintptr_t (*check_func)(uint64_t cpu_rev);
/* Will fit CVEs with up to 10 character in the ID field */
uint32_t id;
/* Denote CVEs with their year or errata with 0 */
uint16_t cve;
uint8_t chosen;
- /* TODO(errata ABI): placeholder for the mitigated field */
- uint8_t _mitigated;
+ uint8_t _alignment;
} __packed;
CASSERT(sizeof(struct erratum_entry) == ERRATUM_ENTRY_SIZE,
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index 87f1541..d9a9188 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -67,25 +67,25 @@
******************************************************************************/
#define CTX_EL3STATE_OFFSET (CTX_GPREGS_OFFSET + CTX_GPREGS_END)
#define CTX_SCR_EL3 U(0x0)
-#define CTX_ESR_EL3 U(0x8)
-#define CTX_RUNTIME_SP U(0x10)
-#define CTX_SPSR_EL3 U(0x18)
-#define CTX_ELR_EL3 U(0x20)
-#define CTX_PMCR_EL0 U(0x28)
-#define CTX_IS_IN_EL3 U(0x30)
-#define CTX_MDCR_EL3 U(0x38)
+#define CTX_RUNTIME_SP U(0x8)
+#define CTX_SPSR_EL3 U(0x10)
+#define CTX_ELR_EL3 U(0x18)
+#define CTX_PMCR_EL0 U(0x20)
+#define CTX_IS_IN_EL3 U(0x28)
+#define CTX_MDCR_EL3 U(0x30)
/* Constants required in supporting nested exception in EL3 */
-#define CTX_SAVED_ELR_EL3 U(0x40)
+#define CTX_SAVED_ELR_EL3 U(0x38)
/*
* General purpose flag, to save various EL3 states
* FFH mode : Used to identify if handling nested exception
* KFH mode : Used as counter value
*/
-#define CTX_NESTED_EA_FLAG U(0x48)
+#define CTX_NESTED_EA_FLAG U(0x40)
#if FFH_SUPPORT
- #define CTX_SAVED_ESR_EL3 U(0x50)
- #define CTX_SAVED_SPSR_EL3 U(0x58)
- #define CTX_SAVED_GPREG_LR U(0x60)
+ #define CTX_SAVED_ESR_EL3 U(0x48)
+ #define CTX_SAVED_SPSR_EL3 U(0x50)
+ #define CTX_SAVED_GPREG_LR U(0x58)
+ #define CTX_DOUBLE_FAULT_ESR U(0x60)
#define CTX_EL3STATE_END U(0x70) /* Align to the next 16 byte boundary */
#else
#define CTX_EL3STATE_END U(0x50) /* Align to the next 16 byte boundary */
@@ -167,9 +167,8 @@
* Registers initialised in a per-world context.
******************************************************************************/
#define CTX_CPTR_EL3 U(0x0)
-#define CTX_ZCR_EL3 U(0x8)
-#define CTX_MPAM3_EL3 U(0x10)
-#define CTX_PERWORLD_EL3STATE_END U(0x18)
+#define CTX_MPAM3_EL3 U(0x8)
+#define CTX_PERWORLD_EL3STATE_END U(0x10)
#ifndef __ASSEMBLER__
@@ -278,7 +277,6 @@
*/
typedef struct per_world_context {
uint64_t ctx_cptr_el3;
- uint64_t ctx_zcr_el3;
uint64_t ctx_mpam3_el3;
} per_world_context_t;
diff --git a/include/lib/el3_runtime/context_el2.h b/include/lib/el3_runtime/context_el2.h
index f35a091..672f533 100644
--- a/include/lib/el3_runtime/context_el2.h
+++ b/include/lib/el3_runtime/context_el2.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -142,6 +142,10 @@
uint64_t sctlr2_el2;
} el2_sctlr2_regs_t;
+typedef struct el2_brbe_regs {
+ uint64_t brbcr_el2;
+} el2_brbe_regs_t;
+
typedef struct el2_sysregs {
el2_common_regs_t common;
@@ -214,6 +218,10 @@
el2_sctlr2_regs_t sctlr2;
#endif
+#if ENABLE_BRBE_FOR_NS
+ el2_brbe_regs_t brbe;
+#endif
+
} el2_sysregs_t;
/*
@@ -384,6 +392,15 @@
#define write_el2_ctx_sctlr2(ctx, reg, val)
#endif /* ENABLE_FEAT_SCTLR2 */
+#if ENABLE_BRBE_FOR_NS
+#define read_el2_ctx_brbe(ctx, reg) (((ctx)->brbe).reg)
+#define write_el2_ctx_brbe(ctx, reg, val) ((((ctx)->brbe).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el2_ctx_brbe(ctx, reg) ULL(0)
+#define write_el2_ctx_brbe(ctx, reg, val)
+#endif /* ENABLE_BRBE_FOR_NS */
+
/******************************************************************************/
#endif /* __ASSEMBLER__ */
diff --git a/include/lib/el3_runtime/context_mgmt.h b/include/lib/el3_runtime/context_mgmt.h
index 70dbd46..a48ed96 100644
--- a/include/lib/el3_runtime/context_mgmt.h
+++ b/include/lib/el3_runtime/context_mgmt.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -41,7 +41,7 @@
#ifdef __aarch64__
#if IMAGE_BL31
-void cm_manage_extensions_el3(void);
+void cm_manage_extensions_el3(unsigned int my_idx);
void manage_extensions_nonsecure_per_world(void);
void cm_el3_arch_init_per_world(per_world_context_t *per_world_ctx);
void cm_handle_asymmetric_features(void);
@@ -95,7 +95,7 @@
#else
void *cm_get_next_context(void);
void cm_set_next_context(void *context);
-static inline void cm_manage_extensions_el3(void) {}
+static inline void cm_manage_extensions_el3(unsigned int cpu_idx) {}
static inline void manage_extensions_nonsecure_per_world(void) {}
static inline void cm_handle_asymmetric_features(void) {}
#endif /* __aarch64__ */
diff --git a/include/lib/el3_runtime/cpu_data.h b/include/lib/el3_runtime/cpu_data.h
index 8b54806..e417f45 100644
--- a/include/lib/el3_runtime/cpu_data.h
+++ b/include/lib/el3_runtime/cpu_data.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -230,7 +230,6 @@
* APIs for initialising and accessing per-cpu data
*************************************************************************/
-void init_cpu_data_ptr(void);
void init_cpu_ops(void);
#define get_cpu_data(_m) _cpu_data()->_m
diff --git a/include/lib/extensions/amu.h b/include/lib/extensions/amu.h
index a396b99..4020331 100644
--- a/include/lib/extensions/amu.h
+++ b/include/lib/extensions/amu.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -17,7 +17,7 @@
#if ENABLE_FEAT_AMU
#if __aarch64__
void amu_enable(cpu_context_t *ctx);
-void amu_init_el3(void);
+void amu_init_el3(unsigned int core_pos);
void amu_init_el2_unused(void);
void amu_enable_per_world(per_world_context_t *per_world_ctx);
#else
@@ -29,7 +29,7 @@
void amu_enable(cpu_context_t *ctx)
{
}
-void amu_init_el3(void)
+void amu_init_el3(unsigned int core_pos)
{
}
void amu_init_el2_unused(void)
@@ -45,28 +45,57 @@
#endif /*__aarch64__ */
#endif /* ENABLE_FEAT_AMU */
-#if ENABLE_AMU_AUXILIARY_COUNTERS
/*
- * AMU data for a single core.
+ * Per-core list of the counters to be enabled. Value will be written into
+ * AMCNTENSET1_EL0 verbatim.
*/
-struct amu_core {
- uint16_t enable; /* Mask of auxiliary counters to enable */
-};
+#if ENABLE_AMU_AUXILIARY_COUNTERS
+extern uint16_t plat_amu_aux_enables[PLATFORM_CORE_COUNT];
+#endif
-/*
- * Topological platform data specific to the AMU.
- */
-struct amu_topology {
- struct amu_core cores[PLATFORM_CORE_COUNT]; /* Per-core data */
-};
+#define CTX_AMU_GRP0_ALL U(4)
+#define CTX_AMU_GRP1_ALL U(16)
-#if !ENABLE_AMU_FCONF
-/*
- * Retrieve the platform's AMU topology. A `NULL` return value is treated as a
- * non-fatal error, in which case no auxiliary counters will be enabled.
- */
-const struct amu_topology *plat_amu_topology(void);
-#endif /* ENABLE_AMU_FCONF */
-#endif /* ENABLE_AMU_AUXILIARY_COUNTERS */
+typedef struct amu_regs {
+ u_register_t grp0[CTX_AMU_GRP0_ALL];
+#if ENABLE_AMU_AUXILIARY_COUNTERS
+ u_register_t grp1[CTX_AMU_GRP1_ALL];
+#endif
+} amu_regs_t;
+
+static inline u_register_t read_amu_grp0_ctx_reg(amu_regs_t *ctx, size_t index)
+{
+ return ctx->grp0[index];
+}
+
+static inline void write_amu_grp0_ctx_reg(amu_regs_t *ctx, size_t index, u_register_t val)
+{
+ ctx->grp0[index] = val;
+}
+
+static inline uint16_t get_amu_aux_enables(size_t index)
+{
+#if ENABLE_AMU_AUXILIARY_COUNTERS
+ return plat_amu_aux_enables[index];
+#else
+ return 0;
+#endif
+}
+
+static inline u_register_t read_amu_grp1_ctx_reg(amu_regs_t *ctx, size_t index)
+{
+#if ENABLE_AMU_AUXILIARY_COUNTERS
+ return ctx->grp1[index];
+#else
+ return 0;
+#endif
+}
+
+static inline void write_amu_grp1_ctx_reg(amu_regs_t *ctx, size_t index, u_register_t val)
+{
+#if ENABLE_AMU_AUXILIARY_COUNTERS
+ ctx->grp1[index] = val;
+#endif
+}
#endif /* AMU_H */
diff --git a/include/lib/extensions/ras_arch.h b/include/lib/extensions/ras_arch.h
index e0aee50..fb2d526 100644
--- a/include/lib/extensions/ras_arch.h
+++ b/include/lib/extensions/ras_arch.h
@@ -143,14 +143,16 @@
/* Uncorrected error types for Asynchronous exceptions */
#define ERROR_STATUS_UET_UC 0x0 /* Uncontainable */
#define ERROR_STATUS_UET_UEU 0x1 /* Unrecoverable */
-#define ERROR_STATUS_UET_UEO 0x2 /* Restable */
+#define ERROR_STATUS_UET_UEO 0x2 /* Restartable */
#define ERROR_STATUS_UET_UER 0x3 /* Recoverable */
+/* Corrected error types for Asynchronous exceptions */
+#define ERROR_STATUS_CET_CE 0x6 /* Corrected (CE) */
+
/* Error types for Synchronous exceptions */
#define ERROR_STATUS_SET_UER 0x0 /* Recoverable */
-#define ERROR_STATUS_SET_UEO 0x1 /* Restable */
#define ERROR_STATUS_SET_UC 0x2 /* Uncontainable */
-#define ERROR_STATUS_SET_CE 0x3 /* Corrected */
+#define ERROR_STATUS_SET_UEO 0x3 /* Restartable */
/* Number of architecturally-defined primary error codes */
#define ERROR_STATUS_NUM_SERR U(22)
@@ -176,6 +178,9 @@
#define EABORT_SET_WIDTH U(2)
#define EABORT_SET_MASK U(0x3)
+#define EABORT_GET_FIELD(_esr_el3, _field) \
+ (((_esr_el3) >> EABORT_ ##_field ##_SHIFT) & EABORT_ ##_field ##_MASK)
+
/* DFSC code for SErrors */
#define DFSC_SERROR 0x11
diff --git a/include/lib/extensions/sve.h b/include/lib/extensions/sve.h
index 2979efb..a471efb 100644
--- a/include/lib/extensions/sve.h
+++ b/include/lib/extensions/sve.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,10 +11,14 @@
#if (ENABLE_SME_FOR_NS || ENABLE_SVE_FOR_NS)
+void sve_init_el3(void);
void sve_init_el2_unused(void);
void sve_enable_per_world(per_world_context_t *per_world_ctx);
void sve_disable_per_world(per_world_context_t *per_world_ctx);
#else
+static inline void sve_init_el3(void)
+{
+}
static inline void sve_init_el2_unused(void)
{
}
diff --git a/include/lib/fconf/fconf_amu_getter.h b/include/lib/fconf/fconf_amu_getter.h
deleted file mode 100644
index 2faee73..0000000
--- a/include/lib/fconf/fconf_amu_getter.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef FCONF_AMU_GETTER_H
-#define FCONF_AMU_GETTER_H
-
-#include <lib/extensions/amu.h>
-
-#define amu__config_getter(id) fconf_amu_config.id
-
-struct fconf_amu_config {
- const struct amu_topology *topology;
-};
-
-extern struct fconf_amu_config fconf_amu_config;
-
-#endif /* FCONF_AMU_GETTER_H */
diff --git a/include/lib/fconf/fconf_mpmm_getter.h b/include/lib/fconf/fconf_mpmm_getter.h
deleted file mode 100644
index 50d991a..0000000
--- a/include/lib/fconf/fconf_mpmm_getter.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef FCONF_MPMM_GETTER_H
-#define FCONF_MPMM_GETTER_H
-
-#include <lib/mpmm/mpmm.h>
-
-#define mpmm__config_getter(id) fconf_mpmm_config.id
-
-struct fconf_mpmm_config {
- const struct mpmm_topology *topology;
-};
-
-extern struct fconf_mpmm_config fconf_mpmm_config;
-
-#endif /* FCONF_MPMM_GETTER_H */
diff --git a/include/lib/gpt_rme/gpt_rme.h b/include/lib/gpt_rme/gpt_rme.h
index 94a88b0..135a948 100644
--- a/include/lib/gpt_rme/gpt_rme.h
+++ b/include/lib/gpt_rme/gpt_rme.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -8,13 +8,20 @@
#define GPT_RME_H
#include <stdint.h>
-
-#include <arch.h>
+#include <lib/spinlock.h>
/******************************************************************************/
/* GPT helper macros and definitions */
/******************************************************************************/
+#if (RME_GPT_BITLOCK_BLOCK != 0)
+#define LOCK_SIZE sizeof(((bitlock_t *)NULL)->lock)
+#define LOCK_TYPE typeof(((bitlock_t *)NULL)->lock)
+#define LOCK_BITS (LOCK_SIZE * UL(8))
+
+CASSERT((UL(1) == LOCK_SIZE), assert_bitlock_type_not_uint8_t);
+#endif /* RME_GPT_BITLOCK_BLOCK */
+
/*
* Structure for specifying a mapping range and it's properties. This should not
* be manually initialized, using the MAP_GPT_REGION_x macros is recommended as
@@ -238,10 +245,14 @@
* initialization from a previous stage. Granule protection checks must be
* enabled already or this function will return an error.
*
+ * Parameters
+ * l1_bitlocks_base Base address of memory for L1 tables bitlocks.
+ * l1_bitlocks_size Total size of memory available for L1 tables bitlocks.
+ *
* Return
* Negative Linux error code in the event of a failure, 0 for success.
*/
-int gpt_runtime_init(void);
+int gpt_runtime_init(uintptr_t l1_bitlocks_base, size_t l1_bitlocks_size);
/*
* Public API to enable granule protection checks once the tables have all been
diff --git a/include/lib/libc/cdefs.h b/include/lib/libc/cdefs.h
index b11d072..97b7824 100644
--- a/include/lib/libc/cdefs.h
+++ b/include/lib/libc/cdefs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -36,4 +36,7 @@
#define __STRING(x) #x
#define __XSTRING(x) __STRING(x)
+#define __predict_true(exp) (exp)
+#define __predict_false(exp) (exp)
+
#endif /* CDEFS_H */
diff --git a/include/lib/libc/stdlib.h b/include/lib/libc/stdlib.h
index 4e5a824..71bb4ba 100644
--- a/include/lib/libc/stdlib.h
+++ b/include/lib/libc/stdlib.h
@@ -29,4 +29,6 @@
unsigned long strtoul(const char *nptr, char **endptr, int base);
long long strtoll(const char *nptr, char **endptr, int base);
unsigned long long strtoull(const char *nptr, char **endptr, int base);
+void qsort(void *, size_t, size_t,
+ int (*)(const void *, const void *));
#endif /* STDLIB_H */
diff --git a/include/lib/mpmm/mpmm.h b/include/lib/mpmm/mpmm.h
deleted file mode 100644
index 955c530..0000000
--- a/include/lib/mpmm/mpmm.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef MPMM_H
-#define MPMM_H
-
-#include <stdbool.h>
-
-#include <platform_def.h>
-
-/*
- * Enable the Maximum Power Mitigation Mechanism.
- *
- * This function will enable MPMM for the current core. The AMU counters
- * representing the MPMM gears must have been configured and enabled prior to
- * calling this function.
- */
-void mpmm_enable(void);
-
-/*
- * MPMM core data.
- *
- * This structure represents per-core data retrieved from the hardware
- * configuration device tree.
- */
-struct mpmm_core {
- /*
- * Whether MPMM is supported.
- *
- * Cores with support for MPMM offer one or more auxiliary AMU counters
- * representing MPMM gears.
- */
- bool supported;
-};
-
-/*
- * MPMM topology.
- *
- * This topology structure describes the system-wide representation of the
- * information retrieved from the hardware configuration device tree.
- */
-struct mpmm_topology {
- struct mpmm_core cores[PLATFORM_CORE_COUNT]; /* Per-core data */
-};
-
-#if !ENABLE_MPMM_FCONF
-/*
- * Retrieve the platform's MPMM topology. A `NULL` return value is treated as a
- * non-fatal error, in which case MPMM will not be enabled for any core.
- */
-const struct mpmm_topology *plat_mpmm_topology(void);
-#endif /* ENABLE_MPMM_FCONF */
-
-#endif /* MPMM_H */
diff --git a/include/lib/psci/psci.h b/include/lib/psci/psci.h
index f12a4d6..68e721a 100644
--- a/include/lib/psci/psci.h
+++ b/include/lib/psci/psci.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2023, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -331,10 +331,10 @@
const psci_power_state_t *target_state);
void (*pwr_domain_suspend_finish)(
const psci_power_state_t *target_state);
- void __dead2 (*pwr_domain_pwr_down_wfi)(
+ void (*pwr_domain_pwr_down)(
const psci_power_state_t *target_state);
- void __dead2 (*system_off)(void);
- void __dead2 (*system_reset)(void);
+ void (*system_off)(void);
+ void (*system_reset)(void);
int (*validate_power_state)(unsigned int power_state,
psci_power_state_t *req_state);
int (*validate_ns_entrypoint)(uintptr_t ns_entrypoint);
@@ -376,7 +376,7 @@
#if PSCI_OS_INIT_MODE
int psci_set_suspend_mode(unsigned int mode);
#endif
-void __dead2 psci_power_down_wfi(void);
+void psci_power_down_wfi(void);
void psci_arch_setup(void);
#endif /*__ASSEMBLER__*/
diff --git a/include/lib/psci/psci_lib.h b/include/lib/psci/psci_lib.h
index 9950a6e..8c9296b 100644
--- a/include/lib/psci/psci_lib.h
+++ b/include/lib/psci/psci_lib.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -94,6 +94,9 @@
bool psci_is_last_on_cpu_safe(unsigned int this_core);
bool psci_are_all_cpus_on_safe(unsigned int this_core);
void psci_pwrdown_cpu(unsigned int power_level);
+void psci_pwrdown_cpu_start(unsigned int power_level);
+void __dead2 psci_pwrdown_cpu_end_terminal(void);
+void psci_pwrdown_cpu_end_wakeup(unsigned int power_level);
void psci_do_manage_extensions(void);
#endif /* __ASSEMBLER__ */
diff --git a/include/lib/transfer_list.h b/include/lib/transfer_list.h
index bcf9fc9..c403031 100644
--- a/include/lib/transfer_list.h
+++ b/include/lib/transfer_list.h
@@ -110,6 +110,7 @@
CASSERT(sizeof(struct transfer_list_entry) == U(0x8), assert_transfer_list_entry_size);
+void transfer_entry_dump(struct transfer_list_entry *te);
void transfer_list_dump(struct transfer_list_header *tl);
struct transfer_list_header *transfer_list_ensure(void *addr, size_t size);
entry_point_info_t *
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 3ce6a91..cc1dcde 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -20,7 +20,6 @@
* Definitions common to all ARM standard platforms
*****************************************************************************/
-
/* Special value used to verify platform parameters from BL2 to BL31 */
#define ARM_BL31_PLAT_PARAM_VAL ULL(0x0f1e2d3c4b5a6978)
@@ -63,11 +62,22 @@
#define ARM_SHARED_RAM_BASE ARM_TRUSTED_SRAM_BASE
#define ARM_SHARED_RAM_SIZE UL(0x00001000) /* 4 KB */
+#if ENABLE_RME
+/* Store level 0 GPT at the top of the Trusted SRAM */
+#define ARM_L0_GPT_BASE (ARM_TRUSTED_SRAM_BASE + \
+ PLAT_ARM_TRUSTED_SRAM_SIZE - \
+ ARM_L0_GPT_SIZE)
+#define ARM_L0_GPT_SIZE UL(0x00002000) /* 8 KB */
+#else
+#define ARM_L0_GPT_SIZE UL(0)
+#endif
+
/* The remaining Trusted SRAM is used to load the BL images */
-#define ARM_BL_RAM_BASE (ARM_SHARED_RAM_BASE + \
+#define ARM_BL_RAM_BASE (ARM_SHARED_RAM_BASE + \
ARM_SHARED_RAM_SIZE)
-#define ARM_BL_RAM_SIZE (PLAT_ARM_TRUSTED_SRAM_SIZE - \
- ARM_SHARED_RAM_SIZE)
+#define ARM_BL_RAM_SIZE (PLAT_ARM_TRUSTED_SRAM_SIZE - \
+ ARM_SHARED_RAM_SIZE - \
+ ARM_L0_GPT_SIZE)
/*
* The top 16MB (or 64MB if RME is enabled) of DRAM1 is configured as
@@ -110,6 +120,7 @@
* placed here. 3MB region is reserved if RME is enabled, 2MB otherwise.
*/
#define ARM_EL3_TZC_DRAM1_SIZE UL(0x00300000) /* 3MB */
+/* 8 x 128KB L1 pages (L0GPTSZ = 1GB, PGS = 4KB) */
#define ARM_L1_GPT_SIZE UL(0x00100000) /* 1MB */
/* 32MB - ARM_EL3_RMM_SHARED_SIZE */
#define ARM_REALM_SIZE (UL(0x02000000) - \
@@ -150,7 +161,7 @@
#endif /* (SPD_tspd || SPD_opteed || SPD_spmd) && MEASURED_BOOT */
#if ENABLE_RME
-#define ARM_L1_GPT_BASE (ARM_DRAM1_BASE + \
+#define ARM_L1_GPT_BASE (ARM_DRAM1_BASE + \
ARM_DRAM1_SIZE - \
ARM_L1_GPT_SIZE)
#define ARM_L1_GPT_END (ARM_L1_GPT_BASE + \
@@ -246,6 +257,9 @@
/* Number of DRAM banks */
#define ARM_DRAM_NUM_BANKS 2UL
+/* Number of PCIe memory regions */
+#define ARM_PCI_NUM_REGIONS 2UL
+
#define ARM_IRQ_SEC_PHY_TIMER 29
#define ARM_IRQ_SEC_SGI_0 8
@@ -352,7 +366,6 @@
ARM_EL3_RMM_SHARED_BASE, \
ARM_EL3_RMM_SHARED_SIZE, \
MT_MEMORY | MT_RW | MT_REALM)
-
#endif /* ENABLE_RME */
/*
@@ -540,18 +553,6 @@
#define ARM_FW_CONFIGS_LIMIT (ARM_BL_RAM_BASE + ARM_FW_CONFIGS_SIZE)
#endif
-#if ENABLE_RME
-/*
- * Store the L0 GPT on Trusted SRAM next to firmware
- * configuration memory, 4KB aligned.
- */
-#define ARM_L0_GPT_SIZE (PAGE_SIZE)
-#define ARM_L0_GPT_BASE (ARM_FW_CONFIGS_LIMIT)
-#define ARM_L0_GPT_LIMIT (ARM_L0_GPT_BASE + ARM_L0_GPT_SIZE)
-#else
-#define ARM_L0_GPT_SIZE U(0)
-#endif
-
/*******************************************************************************
* BL1 specific defines.
* BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of
@@ -567,7 +568,8 @@
#endif
/*
- * Put BL1 RW at the top of the Trusted SRAM.
+ * With ENABLE_RME=1 put BL1 RW below L0 GPT,
+ * or at the top of Trusted SRAM otherwise.
*/
#define BL1_RW_BASE (ARM_BL_RAM_BASE + \
ARM_BL_RAM_SIZE - \
diff --git a/include/plat/arm/css/common/css_pm.h b/include/plat/arm/css/common/css_pm.h
index 84e6b38..d5a3c42 100644
--- a/include/plat/arm/css/common/css_pm.h
+++ b/include/plat/arm/css/common/css_pm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -35,8 +35,8 @@
void css_pwr_domain_suspend(const psci_power_state_t *target_state);
void css_pwr_domain_suspend_finish(
const psci_power_state_t *target_state);
-void __dead2 css_system_off(void);
-void __dead2 css_system_reset(void);
+void css_system_off(void);
+void css_system_reset(void);
void css_cpu_standby(plat_local_state_t cpu_state);
void css_get_sys_suspend_power_state(psci_power_state_t *req_state);
int css_node_hw_state(u_register_t mpidr, unsigned int power_level);
diff --git a/include/plat/common/common_def.h b/include/plat/common/common_def.h
index ecec5bc..3cfab4f 100644
--- a/include/plat/common/common_def.h
+++ b/include/plat/common/common_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
*/
@@ -43,6 +43,11 @@
#define SZ_1G UL(0x40000000)
#define SZ_2G UL(0x80000000)
+
+#define SZ_1T UL(0x10000000000)
+#define SZ_4T UL(0x40000000000)
+
+#define SZ_1P UL(0x4000000000000)
#else /* !__aarch64__ */
#define SZ_32 U(0x00000020)
#define SZ_64 U(0x00000040)
diff --git a/include/plat/common/plat_drtm.h b/include/plat/common/plat_drtm.h
index 07545a6..0d6a818 100644
--- a/include/plat/common/plat_drtm.h
+++ b/include/plat/common/plat_drtm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -59,6 +59,8 @@
uint64_t plat_drtm_get_tcb_hash_table_size(void);
uint64_t plat_drtm_get_imp_def_dlme_region_size(void);
uint64_t plat_drtm_get_tcb_hash_features(void);
+uint64_t plat_drtm_get_acpi_tables_region_size(void);
+uint64_t plat_drtm_get_dlme_img_auth_features(void);
/* DRTM error handling functions */
int plat_set_drtm_error(uint64_t error_code);
diff --git a/include/services/drtm_svc.h b/include/services/drtm_svc.h
index f0d3c63..3503fa4 100644
--- a/include/services/drtm_svc.h
+++ b/include/services/drtm_svc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022-2024 Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -49,6 +49,7 @@
#define ARM_DRTM_FEATURES_DMA_PROT U(0x3)
#define ARM_DRTM_FEATURES_BOOT_PE_ID U(0x4)
#define ARM_DRTM_FEATURES_TCB_HASHES U(0x5)
+#define ARM_DRTM_FEATURES_DLME_IMG_AUTH U(0x6)
#define is_drtm_fid(_fid) \
(((_fid) >= ARM_DRTM_SVC_VERSION) && ((_fid) <= ARM_DRTM_SVC_LOCK_TCB_HASH))
@@ -109,6 +110,9 @@
#define ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_SHIFT U(0)
#define ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_MASK ULL(0xFF)
+#define ARM_DRTM_DLME_IMAGE_AUTH_SUPPORT_SHIFT U(0)
+#define ARM_DRTM_DLME_IMAGE_AUTH_SUPPORT_MASK ULL(0x1)
+
#define ARM_DRTM_TPM_FEATURES_SET_PCR_SCHEMA(reg, val) \
do { \
reg = (((reg) & ~(ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_MASK \
@@ -178,6 +182,16 @@
ARM_DRTM_TCB_HASH_FEATURES_MAX_NUM_HASHES_SHIFT)); \
} while (false)
+#define ARM_DRTM_DLME_IMG_AUTH_SUPPORT(reg, val) \
+ do { \
+ reg = (((reg) & \
+ ~(ARM_DRTM_DLME_IMAGE_AUTH_SUPPORT_MASK << \
+ ARM_DRTM_DLME_IMAGE_AUTH_SUPPORT_SHIFT)) | \
+ (((val) & \
+ ARM_DRTM_DLME_IMAGE_AUTH_SUPPORT_MASK) << \
+ ARM_DRTM_DLME_IMAGE_AUTH_SUPPORT_SHIFT)); \
+ } while (false)
+
/* Definitions for DRTM address map */
#define ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_SHIFT U(55)
#define ARM_DRTM_REGION_SIZE_TYPE_CACHEABILITY_MASK ULL(0x3)
diff --git a/include/services/rmm_core_manifest.h b/include/services/rmm_core_manifest.h
index 6b57267..2d6e71f 100644
--- a/include/services/rmm_core_manifest.h
+++ b/include/services/rmm_core_manifest.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -14,7 +14,7 @@
#include <lib/cassert.h>
#define RMMD_MANIFEST_VERSION_MAJOR U(0)
-#define RMMD_MANIFEST_VERSION_MINOR U(3)
+#define RMMD_MANIFEST_VERSION_MINOR U(4)
#define RMM_CONSOLE_MAX_NAME_LEN U(8)
@@ -37,29 +37,29 @@
#define RMMD_GET_MANIFEST_VERSION_MINOR(_version) \
(_version & 0xFFFF)
-/* NS DRAM bank structure */
-struct ns_dram_bank {
+/* Memory bank/device region structure */
+struct memory_bank {
uintptr_t base; /* Base address */
- uint64_t size; /* Size of bank */
+ uint64_t size; /* Size of memory bank/device region */
};
-CASSERT(offsetof(struct ns_dram_bank, base) == 0UL,
+CASSERT(offsetof(struct memory_bank, base) == 0UL,
rmm_manifest_base_unaligned);
-CASSERT(offsetof(struct ns_dram_bank, size) == 8UL,
+CASSERT(offsetof(struct memory_bank, size) == 8UL,
rmm_manifest_size_unaligned);
-/* NS DRAM layout info structure */
-struct ns_dram_info {
- uint64_t num_banks; /* Number of NS DRAM banks */
- struct ns_dram_bank *banks; /* Pointer to ns_dram_bank[] */
- uint64_t checksum; /* Checksum of ns_dram_info data */
+/* Memory/device region layout info structure */
+struct memory_info {
+ uint64_t num_banks; /* Number of memory banks/device regions */
+ struct memory_bank *banks; /* Pointer to memory_bank[] */
+ uint64_t checksum; /* Checksum of memory_info data */
};
-CASSERT(offsetof(struct ns_dram_info, num_banks) == 0UL,
+CASSERT(offsetof(struct memory_info, num_banks) == 0UL,
rmm_manifest_num_banks_unaligned);
-CASSERT(offsetof(struct ns_dram_info, banks) == 8UL,
+CASSERT(offsetof(struct memory_info, banks) == 8UL,
rmm_manifest_dram_data_unaligned);
-CASSERT(offsetof(struct ns_dram_info, checksum) == 16UL,
+CASSERT(offsetof(struct memory_info, checksum) == 16UL,
rmm_manifest_checksum_unaligned);
/* Console info structure */
@@ -98,13 +98,18 @@
CASSERT(offsetof(struct console_list, checksum) == 16UL,
rmm_manifest_console_list_checksum);
-/* Boot manifest core structure as per v0.3 */
+/* Boot manifest core structure as per v0.4 */
struct rmm_manifest {
uint32_t version; /* Manifest version */
uint32_t padding; /* RES0 */
uintptr_t plat_data; /* Manifest platform data */
- struct ns_dram_info plat_dram; /* Platform NS DRAM data (v0.2) */
- struct console_list plat_console; /* Platform console list (v0.3) */
+ /* Platform NS DRAM data (v0.2) */
+ struct memory_info plat_dram;
+ /* Platform console list (v0.3) */
+ struct console_list plat_console;
+ /* Platform device address ranges (v0.4) */
+ struct memory_info plat_ncoh_region;
+ struct memory_info plat_coh_region;
};
CASSERT(offsetof(struct rmm_manifest, version) == 0UL,
@@ -115,5 +120,9 @@
rmm_manifest_plat_dram_unaligned);
CASSERT(offsetof(struct rmm_manifest, plat_console) == 40UL,
rmm_manifest_plat_console_unaligned);
+CASSERT(offsetof(struct rmm_manifest, plat_ncoh_region) == 64UL,
+ rmm_manifest_plat_ncoh_region_unaligned);
+CASSERT(offsetof(struct rmm_manifest, plat_coh_region) == 88UL,
+ rmm_manifest_plat_coh_region_unaligned);
#endif /* RMM_CORE_MANIFEST_H */
diff --git a/lib/cpus/aarch32/aem_generic.S b/lib/cpus/aarch32/aem_generic.S
index f4dc0d1..a424575 100644
--- a/lib/cpus/aarch32/aem_generic.S
+++ b/lib/cpus/aarch32/aem_generic.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -40,8 +40,11 @@
b dcsw_op_all
endfunc aem_generic_cluster_pwr_dwn
+func aem_generic_reset_func
+ bx lr
+endfunc aem_generic_reset_func
/* cpu_ops for Base AEM FVP */
-declare_cpu_ops aem_generic, BASE_AEM_MIDR, CPU_NO_RESET_FUNC, \
+declare_cpu_ops aem_generic, BASE_AEM_MIDR, aem_generic_reset_func, \
aem_generic_core_pwr_dwn, \
aem_generic_cluster_pwr_dwn
diff --git a/lib/cpus/aarch64/a64fx.S b/lib/cpus/aarch64/a64fx.S
index 4893a44..a53467a 100644
--- a/lib/cpus/aarch64/a64fx.S
+++ b/lib/cpus/aarch64/a64fx.S
@@ -29,12 +29,15 @@
a64fx_regs: /* The ascii list of register names to be reported */
.asciz ""
+cpu_reset_func_start a64fx
+cpu_reset_func_end a64fx
+
func a64fx_cpu_reg_dump
adr x6, a64fx_regs
ret
endfunc a64fx_cpu_reg_dump
-declare_cpu_ops a64fx, A64FX_MIDR, CPU_NO_RESET_FUNC \
+declare_cpu_ops a64fx, A64FX_MIDR, a64fx_reset_func \
a64fx_core_pwr_dwn, \
a64fx_cluster_pwr_dwn
diff --git a/lib/cpus/aarch64/aem_generic.S b/lib/cpus/aarch64/aem_generic.S
index d5634cf..9843943 100644
--- a/lib/cpus/aarch64/aem_generic.S
+++ b/lib/cpus/aarch64/aem_generic.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -8,6 +8,8 @@
#include <asm_macros.S>
#include <cpu_macros.S>
+cpu_reset_prologue aem_generic
+
func aem_generic_core_pwr_dwn
/* ---------------------------------------------
* Disable the Data Cache.
@@ -74,6 +76,9 @@
b dcsw_op_all
endfunc aem_generic_cluster_pwr_dwn
+cpu_reset_func_start aem_generic
+cpu_reset_func_end aem_generic
+
/* ---------------------------------------------
* This function provides cpu specific
* register information for crash reporting.
@@ -94,11 +99,11 @@
/* cpu_ops for Base AEM FVP */
-declare_cpu_ops aem_generic, BASE_AEM_MIDR, CPU_NO_RESET_FUNC, \
+declare_cpu_ops aem_generic, BASE_AEM_MIDR, aem_generic_reset_func, \
aem_generic_core_pwr_dwn, \
aem_generic_cluster_pwr_dwn
/* cpu_ops for Foundation FVP */
-declare_cpu_ops aem_generic, FOUNDATION_AEM_MIDR, CPU_NO_RESET_FUNC, \
+declare_cpu_ops aem_generic, FOUNDATION_AEM_MIDR, aem_generic_reset_func, \
aem_generic_core_pwr_dwn, \
aem_generic_cluster_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_a320.S b/lib/cpus/aarch64/cortex_a320.S
new file mode 100644
index 0000000..2d38b88
--- /dev/null
+++ b/lib/cpus/aarch64/cortex_a320.S
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2024-2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <cortex_a320.h>
+#include <cpu_macros.S>
+#include <plat_macros.S>
+
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "Cortex-A320 must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
+/* 64-bit only core */
+#if CTX_INCLUDE_AARCH32_REGS == 1
+#error "Cortex-A320 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
+#endif
+
+cpu_reset_prologue cortex_a320
+
+cpu_reset_func_start cortex_a320
+ /* Disable speculative loads */
+ msr SSBS, xzr
+ enable_mpmm
+cpu_reset_func_end cortex_a320
+
+ /* ----------------------------------------------------
+ * HW will do the cache maintenance while powering down
+ * ----------------------------------------------------
+ */
+func cortex_a320_core_pwr_dwn
+ /* ---------------------------------------------------
+ * Enable CPU power down bit in power control register
+ * ---------------------------------------------------
+ */
+ sysreg_bit_set CORTEX_A320_CPUPWRCTLR_EL1, CORTEX_A320_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
+ isb
+ ret
+endfunc cortex_a320_core_pwr_dwn
+
+ /* ---------------------------------------------
+ * This function provides Cortex-A320 specific
+ * register information for crash reporting.
+ * It needs to return with x6 pointing to
+ * a list of register names in ascii and
+ * x8 - x15 having values of registers to be
+ * reported.
+ * ---------------------------------------------
+ */
+.section .rodata.cortex_a320_regs, "aS"
+cortex_a320_regs: /* The ascii list of register names to be reported */
+ .asciz "cpuectlr_el1", ""
+
+func cortex_a320_cpu_reg_dump
+ adr x6, cortex_a320_regs
+ mrs x8, CORTEX_A320_CPUECTLR_EL1
+ ret
+endfunc cortex_a320_cpu_reg_dump
+
+declare_cpu_ops cortex_a320, CORTEX_A320_MIDR, \
+ cortex_a320_reset_func, \
+ cortex_a320_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_a35.S b/lib/cpus/aarch64/cortex_a35.S
index c3d8c8d..40e6200 100644
--- a/lib/cpus/aarch64/cortex_a35.S
+++ b/lib/cpus/aarch64/cortex_a35.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,6 +11,7 @@
#include <cpu_macros.S>
#include <plat_macros.S>
+cpu_reset_prologue cortex_a35
/* ---------------------------------------------
* Disable L1 data cache and unified L2 cache
* ---------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a510.S b/lib/cpus/aarch64/cortex_a510.S
index b49d45a..81a227b 100644
--- a/lib/cpus/aarch64/cortex_a510.S
+++ b/lib/cpus/aarch64/cortex_a510.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,6 +9,7 @@
#include <common/bl_common.h>
#include <cortex_a510.h>
#include <cpu_macros.S>
+#include <dsu_macros.S>
#include <plat_macros.S>
/* Hardware handled coherency */
@@ -21,6 +22,8 @@
#error "Cortex-A510 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
+cpu_reset_prologue cortex_a510
+
workaround_reset_start cortex_a510, ERRATUM(1922240), ERRATA_A510_1922240
/* Apply the workaround by setting IMP_CMPXACTLR_EL1[11:10] = 0b11. */
sysreg_bitfield_insert CORTEX_A510_CMPXACTLR_EL1, CORTEX_A510_CMPXACTLR_EL1_SNPPREFERUNIQUE_DISABLE, \
@@ -108,25 +111,11 @@
check_erratum_ls cortex_a510, ERRATUM(2218950), CPU_REV(1, 0)
- /* --------------------------------------------------
- * This workaround is not a typical errata fix. MPMM
- * is disabled here, but this conflicts with the BL31
- * MPMM support. So in addition to simply disabling
- * the feature, a flag is set in the MPMM library
- * indicating that it should not be enabled even if
- * ENABLE_MPMM=1.
- * --------------------------------------------------
- */
workaround_reset_start cortex_a510, ERRATUM(2250311), ERRATA_A510_2250311
/* Disable MPMM */
mrs x0, CPUMPMMCR_EL3
bfm x0, xzr, #0, #0 /* bfc instruction does not work in GCC */
msr CPUMPMMCR_EL3, x0
-
-#if ENABLE_MPMM && IMAGE_BL31
- /* If ENABLE_MPMM is set, tell the runtime lib to skip enabling it. */
- bl mpmm_errata_disable
-#endif
workaround_reset_end cortex_a510, ERRATUM(2250311)
check_erratum_ls cortex_a510, ERRATUM(2250311), CPU_REV(1, 0)
@@ -180,15 +169,14 @@
check_erratum_ls cortex_a510, ERRATUM(2684597), CPU_REV(1, 2)
-/*
- * ERRATA_DSU_2313941 :
- * The errata is defined in dsu_helpers.S but applies to cortex_a510
- * as well. Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_cortex_a510_2313941, check_errata_dsu_2313941
-.equ erratum_cortex_a510_2313941_wa, errata_dsu_2313941_wa
-add_erratum_entry cortex_a510, ERRATUM(2313941), ERRATA_DSU_2313941, APPLY_AT_RESET
+workaround_reset_start cortex_a510, ERRATUM(2313941), ERRATA_DSU_2313941
+ errata_dsu_2313941_wa_impl
+workaround_reset_end cortex_a510, ERRATUM(2313941)
+
+check_erratum_custom_start cortex_a510, ERRATUM(2313941)
+ check_errata_dsu_2313941_impl
+ ret
+check_erratum_custom_end cortex_a510, ERRATUM(2313941)
/* ----------------------------------------------------
* HW will do the cache maintenance while powering down
@@ -207,6 +195,15 @@
cpu_reset_func_start cortex_a510
/* Disable speculative loads */
msr SSBS, xzr
+ /* skip enabling MPMM if this erratum is present */
+#if ERRATA_A510_2250311
+ /* the cpu_rev_var is kept in x14 */
+ mov x14, x0
+ bl check_erratum_cortex_a510_2250311
+ cbz x0, skip_mpmm
+#endif
+ enable_mpmm
+skip_mpmm:
cpu_reset_func_end cortex_a510
/* ---------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a520.S b/lib/cpus/aarch64/cortex_a520.S
index 811c836..ac8019e 100644
--- a/lib/cpus/aarch64/cortex_a520.S
+++ b/lib/cpus/aarch64/cortex_a520.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,7 +11,6 @@
#include <cpu_macros.S>
#include <plat_macros.S>
-/* .global erratum_cortex_a520_2938996_wa */
.global check_erratum_cortex_a520_2938996
/* Hardware handled coherency */
@@ -24,6 +23,8 @@
#error "Cortex A520 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
+cpu_reset_prologue cortex_a520
+
workaround_reset_start cortex_a520, ERRATUM(2630792), ERRATA_A520_2630792
sysreg_bit_set CORTEX_A520_CPUACTLR_EL1, BIT(38)
workaround_reset_end cortex_a520, ERRATUM(2630792)
@@ -36,23 +37,9 @@
check_erratum_ls cortex_a520, ERRATUM(2858100), CPU_REV(0, 1)
-workaround_runtime_start cortex_a520, ERRATUM(2938996), ERRATA_A520_2938996, CORTEX_A520_MIDR
-workaround_runtime_end cortex_a520, ERRATUM(2938996)
-
-check_erratum_custom_start cortex_a520, ERRATUM(2938996)
+add_erratum_entry cortex_a520, ERRATUM(2938996), ERRATA_A520_2938996
- /* This erratum needs to be enabled for r0p0 and r0p1.
- * Check if revision is less than or equal to r0p1.
- */
-
-#if ERRATA_A520_2938996
- mov x1, #1
- b cpu_rev_var_ls
-#else
- mov x0, #ERRATA_MISSING
-#endif
- ret
-check_erratum_custom_end cortex_a520, ERRATUM(2938996)
+check_erratum_ls cortex_a520, ERRATUM(2938996), CPU_REV(0, 1)
/* ----------------------------------------------------
* HW will do the cache maintenance while powering down
@@ -71,6 +58,7 @@
cpu_reset_func_start cortex_a520
/* Disable speculative loads */
msr SSBS, xzr
+ enable_mpmm
cpu_reset_func_end cortex_a520
/* ---------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a53.S b/lib/cpus/aarch64/cortex_a53.S
index 4a5b318..dbfff87 100644
--- a/lib/cpus/aarch64/cortex_a53.S
+++ b/lib/cpus/aarch64/cortex_a53.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,6 +12,8 @@
#include <plat_macros.S>
#include <lib/cpus/errata.h>
+cpu_reset_prologue cortex_a53
+
/* ---------------------------------------------
* Disable L1 data cache and unified L2 cache
* ---------------------------------------------
@@ -36,12 +38,12 @@
/* Due to the nature of the errata it is applied unconditionally when chosen */
check_erratum_ls cortex_a53, ERRATUM(819472), CPU_REV(0, 1)
/* erratum workaround is interleaved with generic code */
-add_erratum_entry cortex_a53, ERRATUM(819472), ERRATUM_ALWAYS_CHOSEN, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a53, ERRATUM(819472), ERRATUM_ALWAYS_CHOSEN
/* Due to the nature of the errata it is applied unconditionally when chosen */
check_erratum_ls cortex_a53, ERRATUM(824069), CPU_REV(0, 2)
/* erratum workaround is interleaved with generic code */
-add_erratum_entry cortex_a53, ERRATUM(824069), ERRATUM_ALWAYS_CHOSEN, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a53, ERRATUM(824069), ERRATUM_ALWAYS_CHOSEN
workaround_reset_start cortex_a53, ERRATUM(826319), ERRATA_A53_826319
mrs x1, CORTEX_A53_L2ACTLR_EL1
@@ -55,7 +57,7 @@
/* Due to the nature of the errata it is applied unconditionally when chosen */
check_erratum_ls cortex_a53, ERRATUM(827319), CPU_REV(0, 2)
/* erratum workaround is interleaved with generic code */
-add_erratum_entry cortex_a53, ERRATUM(827319), ERRATUM_ALWAYS_CHOSEN, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a53, ERRATUM(827319), ERRATUM_ALWAYS_CHOSEN
check_erratum_custom_start cortex_a53, ERRATUM(835769)
cmp x0, CPU_REV(0, 4)
@@ -78,7 +80,7 @@
check_erratum_custom_end cortex_a53, ERRATUM(835769)
/* workaround at build time */
-add_erratum_entry cortex_a53, ERRATUM(835769), ERRATA_A53_835769, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a53, ERRATUM(835769), ERRATA_A53_835769
/*
* Disable the cache non-temporal hint.
@@ -114,7 +116,7 @@
check_erratum_custom_end cortex_a53, ERRATUM(843419)
/* workaround at build time */
-add_erratum_entry cortex_a53, ERRATUM(843419), ERRATA_A53_843419, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a53, ERRATUM(843419), ERRATA_A53_843419
/*
* Earlier revisions of the core are affected as well, but don't
@@ -131,7 +133,7 @@
check_erratum_chosen cortex_a53, ERRATUM(1530924), ERRATA_A53_1530924
/* erratum has no workaround in the cpu. Generic code must take care */
-add_erratum_entry cortex_a53, ERRATUM(1530924), ERRATA_A53_1530924, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a53, ERRATUM(1530924), ERRATA_A53_1530924
cpu_reset_func_start cortex_a53
/* Enable the SMP bit. */
diff --git a/lib/cpus/aarch64/cortex_a55.S b/lib/cpus/aarch64/cortex_a55.S
index d5a74e9..cf91431 100644
--- a/lib/cpus/aarch64/cortex_a55.S
+++ b/lib/cpus/aarch64/cortex_a55.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,6 +9,7 @@
#include <common/bl_common.h>
#include <cortex_a55.h>
#include <cpu_macros.S>
+#include <dsu_macros.S>
#include <plat_macros.S>
/* Hardware handled coherency */
@@ -19,23 +20,25 @@
.globl cortex_a55_reset_func
.globl cortex_a55_core_pwr_dwn
-/* ERRATA_DSU_798953:
- * The errata is defined in dsu_helpers.S but applies to cortex_a55
- * as well. Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_cortex_a55_798953, check_errata_dsu_798953
-.equ erratum_cortex_a55_798953_wa, errata_dsu_798953_wa
-add_erratum_entry cortex_a55, ERRATUM(798953), ERRATA_DSU_798953, APPLY_AT_RESET
+cpu_reset_prologue cortex_a55
-/* ERRATA_DSU_936184:
- * The errata is defined in dsu_helpers.S but applies to cortex_a55
- * as well. Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_cortex_a55_936184, check_errata_dsu_936184
-.equ erratum_cortex_a55_936184_wa, errata_dsu_936184_wa
-add_erratum_entry cortex_a55, ERRATUM(936184), ERRATA_DSU_936184, APPLY_AT_RESET
+workaround_reset_start cortex_a55, ERRATUM(798953), ERRATA_DSU_798953
+ errata_dsu_798953_wa_impl
+workaround_reset_end cortex_a55, ERRATUM(798953)
+
+check_erratum_custom_start cortex_a55, ERRATUM(798953)
+ check_errata_dsu_798953_impl
+ ret
+check_erratum_custom_end cortex_a55, ERRATUM(798953)
+
+workaround_reset_start cortex_a55, ERRATUM(936184), ERRATA_DSU_936184
+ errata_dsu_936184_wa_impl
+workaround_reset_end cortex_a55, ERRATUM(936184)
+
+check_erratum_custom_start cortex_a55, ERRATUM(936184)
+ check_errata_dsu_936184_impl
+ ret
+check_erratum_custom_end cortex_a55, ERRATUM(936184)
workaround_reset_start cortex_a55, ERRATUM(768277), ERRATA_A55_768277
sysreg_bit_set CORTEX_A55_CPUACTLR_EL1, CORTEX_A55_CPUACTLR_EL1_DISABLE_DUAL_ISSUE
@@ -50,8 +53,7 @@
check_erratum_custom_start cortex_a55, ERRATUM(778703)
mov x16, x30
- mov x1, #0x00
- bl cpu_rev_var_ls
+ cpu_rev_var_ls CPU_REV(0, 0)
/*
* Check that no private L2 cache is configured
*/
@@ -111,7 +113,7 @@
check_erratum_chosen cortex_a55, ERRATUM(1530923), ERRATA_A55_1530923
/* erratum has no workaround in the cpu. Generic code must take care */
-add_erratum_entry cortex_a55, ERRATUM(1530923), ERRATA_A55_1530923, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a55, ERRATUM(1530923), ERRATA_A55_1530923
cpu_reset_func_start cortex_a55
cpu_reset_func_end cortex_a55
diff --git a/lib/cpus/aarch64/cortex_a57.S b/lib/cpus/aarch64/cortex_a57.S
index fecb56f..adacc5c 100644
--- a/lib/cpus/aarch64/cortex_a57.S
+++ b/lib/cpus/aarch64/cortex_a57.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -13,6 +13,8 @@
#include <cpu_macros.S>
#include <plat_macros.S>
+cpu_reset_prologue cortex_a57
+
/* ---------------------------------------------
* Disable L1 data cache and unified L2 cache
* ---------------------------------------------
@@ -81,7 +83,7 @@
/* erratum always worked around, but report it correctly */
check_erratum_ls cortex_a57, ERRATUM(813419), CPU_REV(0, 0)
-add_erratum_entry cortex_a57, ERRATUM(813419), ERRATUM_ALWAYS_CHOSEN, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a57, ERRATUM(813419), ERRATUM_ALWAYS_CHOSEN
workaround_reset_start cortex_a57, ERRATUM(813420), ERRATA_A57_813420
sysreg_bit_set CORTEX_A57_CPUACTLR_EL1, CORTEX_A57_CPUACTLR_EL1_DCC_AS_DCCI
@@ -95,7 +97,7 @@
check_erratum_ls cortex_a57, ERRATUM(814670), CPU_REV(0, 0)
-workaround_runtime_start cortex_a57, ERRATUM(817169), ERRATA_A57_817169, CORTEX_A57_MIDR
+workaround_runtime_start cortex_a57, ERRATUM(817169), ERRATA_A57_817169
/* Invalidate any TLB address */
mov x0, #0
tlbi vae3, x0
@@ -150,7 +152,7 @@
check_erratum_chosen cortex_a57, ERRATUM(1319537), ERRATA_A57_1319537
/* erratum has no workaround in the cpu. Generic code must take care */
-add_erratum_entry cortex_a57, ERRATUM(1319537), ERRATA_A57_1319537, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a57, ERRATUM(1319537), ERRATA_A57_1319537
workaround_reset_start cortex_a57, CVE(2017, 5715), WORKAROUND_CVE_2017_5715
#if IMAGE_BL31
diff --git a/lib/cpus/aarch64/cortex_a65.S b/lib/cpus/aarch64/cortex_a65.S
index 3023ecb..3c32adb 100644
--- a/lib/cpus/aarch64/cortex_a65.S
+++ b/lib/cpus/aarch64/cortex_a65.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -10,6 +10,7 @@
#include <common/debug.h>
#include <cortex_a65.h>
#include <cpu_macros.S>
+#include <dsu_macros.S>
#include <plat_macros.S>
/* Hardware handled coherency */
@@ -22,20 +23,19 @@
#error "Cortex-A65 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
-/* -------------------------------------------------
- * The CPU Ops reset function for Cortex-A65.
- * Shall clobber: x0-x19
- * -------------------------------------------------
- */
-func cortex_a65_reset_func
- mov x19, x30
+cpu_reset_prologue cortex_a65
-#if ERRATA_DSU_936184
- bl errata_dsu_936184_wa
-#endif
+workaround_reset_start cortex_a65, ERRATUM(936184), ERRATA_DSU_936184
+ errata_dsu_936184_wa_impl
+workaround_reset_end cortex_a65, ERRATUM(936184)
- ret x19
-endfunc cortex_a65_reset_func
+check_erratum_custom_start cortex_a65, ERRATUM(936184)
+ check_errata_dsu_936184_impl
+ ret
+check_erratum_custom_end cortex_a65, ERRATUM(936184)
+
+cpu_reset_func_start cortex_a65
+cpu_reset_func_end cortex_a65
func cortex_a65_cpu_pwr_dwn
mrs x0, CORTEX_A65_CPUPWRCTLR_EL1
@@ -45,7 +45,6 @@
ret
endfunc cortex_a65_cpu_pwr_dwn
-
.section .rodata.cortex_a65_regs, "aS"
cortex_a65_regs: /* The ascii list of register names to be reported */
.asciz "cpuectlr_el1", ""
diff --git a/lib/cpus/aarch64/cortex_a65ae.S b/lib/cpus/aarch64/cortex_a65ae.S
index 1cbb06a..f1a63b0 100644
--- a/lib/cpus/aarch64/cortex_a65ae.S
+++ b/lib/cpus/aarch64/cortex_a65ae.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,6 +11,7 @@
#include <cortex_a65ae.h>
#include <cpu_macros.S>
#include <plat_macros.S>
+#include <dsu_macros.S>
/* Hardware handled coherency */
#if !HW_ASSISTED_COHERENCY
@@ -22,15 +23,16 @@
#error "Cortex-A65AE supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
- /*
- * ERRATA_DSU_936184 :
- * The errata is defined in dsu_helpers.S but applies to cortex_a65ae
- * as well. Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_cortex_a65ae_936184, check_errata_dsu_936184
-.equ erratum_cortex_a65ae_936184_wa, errata_dsu_936184_wa
-add_erratum_entry cortex_a65ae, ERRATUM(936184), ERRATA_DSU_936184, APPLY_AT_RESET
+cpu_reset_prologue cortex_a65ae
+
+workaround_reset_start cortex_a65ae, ERRATUM(936184), ERRATA_DSU_936184
+ errata_dsu_936184_wa_impl
+workaround_reset_end cortex_a65ae, ERRATUM(936184)
+
+check_erratum_custom_start cortex_a65ae, ERRATUM(936184)
+ check_errata_dsu_936184_impl
+ ret
+check_erratum_custom_end cortex_a65ae, ERRATUM(936184)
cpu_reset_func_start cortex_a65ae
cpu_reset_func_end cortex_a65ae
diff --git a/lib/cpus/aarch64/cortex_a710.S b/lib/cpus/aarch64/cortex_a710.S
index 71ed6db..e8f5a80 100644
--- a/lib/cpus/aarch64/cortex_a710.S
+++ b/lib/cpus/aarch64/cortex_a710.S
@@ -9,6 +9,7 @@
#include <common/bl_common.h>
#include <cortex_a710.h>
#include <cpu_macros.S>
+#include <dsu_macros.S>
#include <plat_macros.S>
#include "wa_cve_2022_23960_bhb_vector.S"
@@ -28,6 +29,8 @@
wa_cve_2022_23960_bhb_vector_table CORTEX_A710_BHB_LOOP_COUNT, cortex_a710
#endif /* WORKAROUND_CVE_2022_23960 */
+cpu_reset_prologue cortex_a710
+
/* Disable hardware page aggregation. Enables mitigation for `CVE-2024-5660` */
workaround_reset_start cortex_a710, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
sysreg_bit_set CORTEX_A710_CPUECTLR_EL1, BIT(46)
@@ -164,21 +167,23 @@
check_erratum_ls cortex_a710, ERRATUM(2282622), CPU_REV(2, 1)
+.global erratum_cortex_a710_2291219_wa
workaround_runtime_start cortex_a710, ERRATUM(2291219), ERRATA_A710_2291219
- /* Set bit 36 in ACTLR2_EL1 */
- sysreg_bit_set CORTEX_A710_CPUACTLR2_EL1, CORTEX_A710_CPUACTLR2_EL1_BIT_36
+ /* Set/unset bit 36 in ACTLR2_EL1. The first call will set it, applying
+ * the workaround. Second call clears it to undo it. */
+ sysreg_bit_toggle CORTEX_A710_CPUACTLR2_EL1, CORTEX_A710_CPUACTLR2_EL1_BIT_36
workaround_runtime_end cortex_a710, ERRATUM(2291219), NO_ISB
check_erratum_ls cortex_a710, ERRATUM(2291219), CPU_REV(2, 0)
-/*
- * ERRATA_DSU_2313941 is defined in dsu_helpers.S but applies to Cortex-A710 as
- * well. Create a symbollic link to existing errata workaround to get them
- * registered under the Errata Framework.
- */
-.equ check_erratum_cortex_a710_2313941, check_errata_dsu_2313941
-.equ erratum_cortex_a710_2313941_wa, errata_dsu_2313941_wa
-add_erratum_entry cortex_a710, ERRATUM(2313941), ERRATA_DSU_2313941, APPLY_AT_RESET
+workaround_reset_start cortex_a710, ERRATUM(2313941), ERRATA_DSU_2313941
+ errata_dsu_2313941_wa_impl
+workaround_reset_end cortex_a710, ERRATUM(2313941)
+
+check_erratum_custom_start cortex_a710, ERRATUM(2313941)
+ check_errata_dsu_2313941_impl
+ ret
+check_erratum_custom_end cortex_a710, ERRATUM(2313941)
workaround_reset_start cortex_a710, ERRATUM(2371105), ERRATA_A710_2371105
/* Set bit 40 in CPUACTLR2_EL1 */
@@ -220,7 +225,7 @@
check_erratum_chosen cortex_a710, CVE(2022, 23960), WORKAROUND_CVE_2022_23960
-add_erratum_entry cortex_a710, ERRATUM(3701772), ERRATA_A710_3701772, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a710, ERRATUM(3701772), ERRATA_A710_3701772
check_erratum_ls cortex_a710, ERRATUM(3701772), CPU_REV(2, 1)
@@ -245,6 +250,7 @@
cpu_reset_func_start cortex_a710
/* Disable speculative loads */
msr SSBS, xzr
+ enable_mpmm
cpu_reset_func_end cortex_a710
/* ---------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a715.S b/lib/cpus/aarch64/cortex_a715.S
index fbc73ed..d9c0df2 100644
--- a/lib/cpus/aarch64/cortex_a715.S
+++ b/lib/cpus/aarch64/cortex_a715.S
@@ -28,6 +28,8 @@
wa_cve_2022_23960_bhb_vector_table CORTEX_A715_BHB_LOOP_COUNT, cortex_a715
#endif /* WORKAROUND_CVE_2022_23960 */
+cpu_reset_prologue cortex_a715
+
workaround_reset_start cortex_a715, ERRATUM(2331818), ERRATA_A715_2331818
sysreg_bit_set CORTEX_A715_CPUACTLR2_EL1, BIT(20)
workaround_reset_end cortex_a715, ERRATUM(2331818)
@@ -129,13 +131,14 @@
check_erratum_chosen cortex_a715, CVE(2022, 23960), WORKAROUND_CVE_2022_23960
-add_erratum_entry cortex_a715, ERRATUM(3699560), ERRATA_A715_3699560, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a715, ERRATUM(3699560), ERRATA_A715_3699560
check_erratum_ls cortex_a715, ERRATUM(3699560), CPU_REV(1, 3)
cpu_reset_func_start cortex_a715
/* Disable speculative loads */
msr SSBS, xzr
+ enable_mpmm
cpu_reset_func_end cortex_a715
/* ----------------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a72.S b/lib/cpus/aarch64/cortex_a72.S
index c300ea7..fee28ee 100644
--- a/lib/cpus/aarch64/cortex_a72.S
+++ b/lib/cpus/aarch64/cortex_a72.S
@@ -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
*/
@@ -15,6 +15,8 @@
wa_cve_2022_23960_bhb_vector_table CORTEX_A72_BHB_LOOP_COUNT, cortex_a72
#endif /* WORKAROUND_CVE_2022_23960 */
+cpu_reset_prologue cortex_a72
+
/* ---------------------------------------------
* Disable L1 data cache and unified L2 cache
* ---------------------------------------------
@@ -92,7 +94,7 @@
/* Due to the nature of the errata it is applied unconditionally when chosen */
check_erratum_chosen cortex_a72, ERRATUM(1319367), ERRATA_A72_1319367
/* erratum workaround is interleaved with generic code */
-add_erratum_entry cortex_a72, ERRATUM(1319367), ERRATA_A72_1319367, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a72, ERRATUM(1319367), ERRATA_A72_1319367
workaround_reset_start cortex_a72, CVE(2017, 5715), WORKAROUND_CVE_2017_5715
#if IMAGE_BL31
diff --git a/lib/cpus/aarch64/cortex_a720.S b/lib/cpus/aarch64/cortex_a720.S
index ab2c12f..e639996 100644
--- a/lib/cpus/aarch64/cortex_a720.S
+++ b/lib/cpus/aarch64/cortex_a720.S
@@ -22,6 +22,8 @@
#error "Cortex A720 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
+cpu_reset_prologue cortex_a720
+
.global check_erratum_cortex_a720_3699561
#if WORKAROUND_CVE_2022_23960
@@ -74,13 +76,14 @@
check_erratum_chosen cortex_a720, CVE(2022, 23960), WORKAROUND_CVE_2022_23960
-add_erratum_entry cortex_a720, ERRATUM(3699561), ERRATA_A720_3699561, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a720, ERRATUM(3699561), ERRATA_A720_3699561
check_erratum_ls cortex_a720, ERRATUM(3699561), CPU_REV(0, 2)
cpu_reset_func_start cortex_a720
/* Disable speculative loads */
msr SSBS, xzr
+ enable_mpmm
cpu_reset_func_end cortex_a720
/* ----------------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a720_ae.S b/lib/cpus/aarch64/cortex_a720_ae.S
index 57a5030..1d51c44 100644
--- a/lib/cpus/aarch64/cortex_a720_ae.S
+++ b/lib/cpus/aarch64/cortex_a720_ae.S
@@ -21,15 +21,18 @@
#error "Cortex-A720AE supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
+cpu_reset_prologue cortex_a720_ae
+
.global check_erratum_cortex_a720_ae_3699562
-add_erratum_entry cortex_a720_ae, ERRATUM(3699562), ERRATA_A720_AE_3699562, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a720_ae, ERRATUM(3699562), ERRATA_A720_AE_3699562
check_erratum_ls cortex_a720_ae, ERRATUM(3699562), CPU_REV(0, 0)
cpu_reset_func_start cortex_a720_ae
/* Disable speculative loads */
msr SSBS, xzr
+ enable_mpmm
cpu_reset_func_end cortex_a720_ae
/* ----------------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a725.S b/lib/cpus/aarch64/cortex_a725.S
index c4d6034..682ca45 100644
--- a/lib/cpus/aarch64/cortex_a725.S
+++ b/lib/cpus/aarch64/cortex_a725.S
@@ -21,15 +21,18 @@
#error "Cortex-A725 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
+cpu_reset_prologue cortex_a725
+
.global check_erratum_cortex_a725_3699564
-add_erratum_entry cortex_a725, ERRATUM(3699564), ERRATA_A725_3699564, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a725, ERRATUM(3699564), ERRATA_A725_3699564
check_erratum_ls cortex_a725, ERRATUM(3699564), CPU_REV(0, 1)
cpu_reset_func_start cortex_a725
/* Disable speculative loads */
msr SSBS, xzr
+ enable_mpmm
cpu_reset_func_end cortex_a725
/* ----------------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a73.S b/lib/cpus/aarch64/cortex_a73.S
index 2130ceb..d1fc6d4 100644
--- a/lib/cpus/aarch64/cortex_a73.S
+++ b/lib/cpus/aarch64/cortex_a73.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -10,6 +10,8 @@
#include <cpu_macros.S>
#include <plat_macros.S>
+cpu_reset_prologue cortex_a73
+
/* ---------------------------------------------
* Disable L1 data cache
* ---------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a75.S b/lib/cpus/aarch64/cortex_a75.S
index 152c81f..13599ca 100644
--- a/lib/cpus/aarch64/cortex_a75.S
+++ b/lib/cpus/aarch64/cortex_a75.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,6 +9,7 @@
#include <cortex_a75.h>
#include <cpuamu.h>
#include <cpu_macros.S>
+#include <dsu_macros.S>
.global check_erratum_cortex_a75_764081
@@ -17,6 +18,8 @@
#error "Cortex-A75 must be compiled with HW_ASSISTED_COHERENCY enabled"
#endif
+cpu_reset_prologue cortex_a75
+
workaround_reset_start cortex_a75, ERRATUM(764081), ERRATA_A75_764081
sysreg_bit_set sctlr_el3, SCTLR_IESB_BIT
workaround_reset_end cortex_a75, ERRATUM(764081)
@@ -29,23 +32,23 @@
check_erratum_ls cortex_a75, ERRATUM(790748), CPU_REV(0, 0)
-/* ERRATA_DSU_798953 :
- * The errata is defined in dsu_helpers.S but applies to cortex_a75
- * as well. Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_cortex_a75_798953, check_errata_dsu_798953
-.equ erratum_cortex_a75_798953_wa, errata_dsu_798953_wa
-add_erratum_entry cortex_a75, ERRATUM(798953), ERRATA_DSU_798953, APPLY_AT_RESET
+workaround_reset_start cortex_a75, ERRATUM(798953), ERRATA_DSU_798953
+ errata_dsu_798953_wa_impl
+workaround_reset_end cortex_a75, ERRATUM(798953)
-/* ERRATA_DSU_936184 :
- * The errata is defined in dsu_helpers.S but applies to cortex_a75
- * as well. Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_cortex_a75_936184, check_errata_dsu_936184
-.equ erratum_cortex_a75_936184_wa, errata_dsu_936184_wa
-add_erratum_entry cortex_a75, ERRATUM(936184), ERRATA_DSU_936184, APPLY_AT_RESET
+check_erratum_custom_start cortex_a75, ERRATUM(798953)
+ check_errata_dsu_798953_impl
+ ret
+check_erratum_custom_end cortex_a75, ERRATUM(798953)
+
+workaround_reset_start cortex_a75, ERRATUM(936184), ERRATA_DSU_936184
+ errata_dsu_936184_wa_impl
+workaround_reset_end cortex_a75, ERRATUM(936184)
+
+check_erratum_custom_start cortex_a75, ERRATUM(936184)
+ check_errata_dsu_936184_impl
+ ret
+check_erratum_custom_end cortex_a75, ERRATUM(936184)
workaround_reset_start cortex_a75, CVE(2017, 5715), WORKAROUND_CVE_2017_5715
#if IMAGE_BL31
diff --git a/lib/cpus/aarch64/cortex_a76.S b/lib/cpus/aarch64/cortex_a76.S
index 017086a..822ef05 100644
--- a/lib/cpus/aarch64/cortex_a76.S
+++ b/lib/cpus/aarch64/cortex_a76.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,6 +9,7 @@
#include <common/bl_common.h>
#include <cortex_a76.h>
#include <cpu_macros.S>
+#include <dsu_macros.S>
#include <plat_macros.S>
#include <services/arm_arch_svc.h>
#include "wa_cve_2022_23960_bhb.S"
@@ -29,6 +30,8 @@
#define ESR_EL3_A64_SMC0 0x5e000000
#define ESR_EL3_A32_SMC0 0x4e000000
+cpu_reset_prologue cortex_a76
+
#if DYNAMIC_WORKAROUND_CVE_2018_3639
/*
* This macro applies the mitigation for CVE-2018-3639.
@@ -344,11 +347,10 @@
check_erratum_custom_start cortex_a76, ERRATUM(1286807)
#if ERRATA_A76_1286807
mov x0, #ERRATA_APPLIES
- ret
#else
- mov x1, #0x30
- b cpu_rev_var_ls
+ cpu_rev_var_ls CPU_REV(3, 0)
#endif
+ ret
check_erratum_custom_end cortex_a76, ERRATUM(1286807)
workaround_reset_start cortex_a76, ERRATUM(1791580), ERRATA_A76_1791580
@@ -419,35 +421,34 @@
check_erratum_custom_start cortex_a76, ERRATUM(1165522)
#if ERRATA_A76_1165522
mov x0, #ERRATA_APPLIES
- ret
#else
- mov x1, #0x30
- b cpu_rev_var_ls
+ cpu_rev_var_ls CPU_REV(3, 0)
#endif
+ ret
check_erratum_custom_end cortex_a76, ERRATUM(1165522)
check_erratum_chosen cortex_a76, CVE(2022, 23960), WORKAROUND_CVE_2022_23960
/* erratum has no workaround in the cpu. Generic code must take care */
-add_erratum_entry cortex_a76, CVE(2022, 23960), WORKAROUND_CVE_2022_23960, NO_APPLY_AT_RESET
+add_erratum_entry cortex_a76, CVE(2022, 23960), WORKAROUND_CVE_2022_23960
-/* ERRATA_DSU_798953 :
- * The errata is defined in dsu_helpers.S but applies to cortex_a76
- * as well. Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_cortex_a76_798953, check_errata_dsu_798953
-.equ erratum_cortex_a76_798953_wa, errata_dsu_798953_wa
-add_erratum_entry cortex_a76, ERRATUM(798953), ERRATA_DSU_798953, APPLY_AT_RESET
+workaround_reset_start cortex_a76, ERRATUM(798953), ERRATA_DSU_798953
+ errata_dsu_798953_wa_impl
+workaround_reset_end cortex_a76, ERRATUM(798953)
-/* ERRATA_DSU_936184 :
- * The errata is defined in dsu_helpers.S but applies to cortex_a76
- * as well. Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_cortex_a76_936184, check_errata_dsu_936184
-.equ erratum_cortex_a76_936184_wa, errata_dsu_936184_wa
-add_erratum_entry cortex_a76, ERRATUM(936184), ERRATA_DSU_936184, APPLY_AT_RESET
+check_erratum_custom_start cortex_a76, ERRATUM(798953)
+ check_errata_dsu_798953_impl
+ ret
+check_erratum_custom_end cortex_a76, ERRATUM(798953)
+
+workaround_reset_start cortex_a76, ERRATUM(936184), ERRATA_DSU_936184
+ errata_dsu_936184_wa_impl
+workaround_reset_end cortex_a76, ERRATUM(936184)
+
+check_erratum_custom_start cortex_a76, ERRATUM(936184)
+ check_errata_dsu_936184_impl
+ ret
+check_erratum_custom_end cortex_a76, ERRATUM(936184)
cpu_reset_func_start cortex_a76
diff --git a/lib/cpus/aarch64/cortex_a76ae.S b/lib/cpus/aarch64/cortex_a76ae.S
index 2fe3dbc..54af9a0 100644
--- a/lib/cpus/aarch64/cortex_a76ae.S
+++ b/lib/cpus/aarch64/cortex_a76ae.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -21,6 +21,8 @@
#error "Cortex-A76AE supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
+cpu_reset_prologue cortex_a76ae
+
#if WORKAROUND_CVE_2022_23960
wa_cve_2022_23960_bhb_vector_table CORTEX_A76AE_BHB_LOOP_COUNT, cortex_a76ae
#endif /* WORKAROUND_CVE_2022_23960 */
diff --git a/lib/cpus/aarch64/cortex_a77.S b/lib/cpus/aarch64/cortex_a77.S
index 766bdc0..7fb964d 100644
--- a/lib/cpus/aarch64/cortex_a77.S
+++ b/lib/cpus/aarch64/cortex_a77.S
@@ -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
*/
@@ -17,6 +17,8 @@
#error "Cortex-A77 must be compiled with HW_ASSISTED_COHERENCY enabled"
#endif
+cpu_reset_prologue cortex_a77
+
/* 64-bit only core */
#if CTX_INCLUDE_AARCH32_REGS == 1
#error "Cortex-A77 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
@@ -36,8 +38,7 @@
workaround_reset_start cortex_a77, ERRATUM(1508412), ERRATA_A77_1508412
/* move cpu revision in again and compare against r0p0 */
mov x0, x7
- mov x1, #CPU_REV(0, 0)
- bl cpu_rev_var_ls
+ cpu_rev_var_ls CPU_REV(0, 0)
cbz x0, 1f
ldr x0, =0x0
diff --git a/lib/cpus/aarch64/cortex_a78.S b/lib/cpus/aarch64/cortex_a78.S
index 9f2ffdf..a66214b 100644
--- a/lib/cpus/aarch64/cortex_a78.S
+++ b/lib/cpus/aarch64/cortex_a78.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -24,6 +24,8 @@
wa_cve_2022_23960_bhb_vector_table CORTEX_A78_BHB_LOOP_COUNT, cortex_a78
#endif /* WORKAROUND_CVE_2022_23960 */
+cpu_reset_prologue cortex_a78
+
/* Disable hardware page aggregation.Enables mitigation for `CVE-2024-5660` */
workaround_reset_start cortex_a78, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
sysreg_bit_set CORTEX_A78_CPUECTLR_EL1, BIT(46)
diff --git a/lib/cpus/aarch64/cortex_a78_ae.S b/lib/cpus/aarch64/cortex_a78_ae.S
index 7fa1f9b..c537967 100644
--- a/lib/cpus/aarch64/cortex_a78_ae.S
+++ b/lib/cpus/aarch64/cortex_a78_ae.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2025, Arm Limited. All rights reserved.
* Copyright (c) 2021-2023, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -22,6 +22,8 @@
wa_cve_2022_23960_bhb_vector_table CORTEX_A78_AE_BHB_LOOP_COUNT, cortex_a78_ae
#endif /* WORKAROUND_CVE_2022_23960 */
+cpu_reset_prologue cortex_a78_ae
+
/* Disable hardware page aggregation. Enables mitigation for `CVE-2024-5660` */
workaround_reset_start cortex_a78_ae, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
sysreg_bit_set CORTEX_A78_AE_CPUECTLR_EL1, BIT(46)
diff --git a/lib/cpus/aarch64/cortex_a78c.S b/lib/cpus/aarch64/cortex_a78c.S
index 3f6944a..aba7d25 100644
--- a/lib/cpus/aarch64/cortex_a78c.S
+++ b/lib/cpus/aarch64/cortex_a78c.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -21,6 +21,8 @@
wa_cve_2022_23960_bhb_vector_table CORTEX_A78C_BHB_LOOP_COUNT, cortex_a78c
#endif /* WORKAROUND_CVE_2022_23960 */
+cpu_reset_prologue cortex_a78c
+
/* Disable hardware page aggregation. Enables mitigation for `CVE-2024-5660` */
workaround_reset_start cortex_a78c, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
sysreg_bit_set CORTEX_A78C_CPUECTLR_EL1, BIT(46)
diff --git a/lib/cpus/aarch64/cortex_alto.S b/lib/cpus/aarch64/cortex_alto.S
index c0815f9..69a630d 100644
--- a/lib/cpus/aarch64/cortex_alto.S
+++ b/lib/cpus/aarch64/cortex_alto.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -21,26 +21,19 @@
#error "Alto supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
+#if ERRATA_SME_POWER_DOWN == 0
+#error "Travis needs ERRATA_SME_POWER_DOWN=1 to powerdown correctly"
+#endif
+
+cpu_reset_prologue cortex_alto
+
cpu_reset_func_start cortex_alto
/* Disable speculative loads */
msr SSBS, xzr
+ enable_mpmm
cpu_reset_func_end cortex_alto
func cortex_alto_core_pwr_dwn
-#if ENABLE_SME_FOR_NS
- /* ---------------------------------------------------
- * Disable SME if enabled and supported
- * ---------------------------------------------------
- */
- mrs x0, ID_AA64PFR1_EL1
- ubfx x0, x0, #ID_AA64PFR1_EL1_SME_SHIFT, \
- #ID_AA64PFR1_EL1_SME_WIDTH
- cmp x0, #SME_NOT_IMPLEMENTED
- b.eq 1f
- msr CORTEX_ALTO_SVCRSM, xzr
- msr CORTEX_ALTO_SVCRZA, xzr
-1:
-#endif
/* ---------------------------------------------------
* Enable CPU power down bit in power control register
* ---------------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_arcadia.S b/lib/cpus/aarch64/cortex_arcadia.S
deleted file mode 100644
index c97d87d..0000000
--- a/lib/cpus/aarch64/cortex_arcadia.S
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2024, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <arch.h>
-#include <asm_macros.S>
-#include <common/bl_common.h>
-#include <cortex_arcadia.h>
-#include <cpu_macros.S>
-#include <plat_macros.S>
-
-/* Hardware handled coherency */
-#if HW_ASSISTED_COHERENCY == 0
-#error "Cortex-ARCADIA must be compiled with HW_ASSISTED_COHERENCY enabled"
-#endif
-
-/* 64-bit only core */
-#if CTX_INCLUDE_AARCH32_REGS == 1
-#error "Cortex-ARCADIA supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
-#endif
-
-cpu_reset_func_start cortex_arcadia
- /* Disable speculative loads */
- msr SSBS, xzr
-cpu_reset_func_end cortex_arcadia
-
- /* ----------------------------------------------------
- * HW will do the cache maintenance while powering down
- * ----------------------------------------------------
- */
-func cortex_arcadia_core_pwr_dwn
- /* ---------------------------------------------------
- * Enable CPU power down bit in power control register
- * ---------------------------------------------------
- */
- sysreg_bit_set CORTEX_ARCADIA_CPUPWRCTLR_EL1, CORTEX_ARCADIA_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
- isb
- ret
-endfunc cortex_arcadia_core_pwr_dwn
-
- /* ---------------------------------------------
- * This function provides Cortex-Arcadia specific
- * register information for crash reporting.
- * It needs to return with x6 pointing to
- * a list of register names in ascii and
- * x8 - x15 having values of registers to be
- * reported.
- * ---------------------------------------------
- */
-.section .rodata.cortex_arcadia_regs, "aS"
-cortex_arcadia_regs: /* The ascii list of register names to be reported */
- .asciz "cpuectlr_el1", ""
-
-func cortex_arcadia_cpu_reg_dump
- adr x6, cortex_arcadia_regs
- mrs x8, CORTEX_ARCADIA_CPUECTLR_EL1
- ret
-endfunc cortex_arcadia_cpu_reg_dump
-
-declare_cpu_ops cortex_arcadia, CORTEX_ARCADIA_MIDR, \
- cortex_arcadia_reset_func, \
- cortex_arcadia_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_gelas.S b/lib/cpus/aarch64/cortex_gelas.S
index 891e9a6..4cdec32 100644
--- a/lib/cpus/aarch64/cortex_gelas.S
+++ b/lib/cpus/aarch64/cortex_gelas.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -21,12 +21,26 @@
#error "Gelas supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
+#if FEAT_PABANDON == 0
+#error "Gelas must be compiled with FEAT_PABANDON enabled"
+#endif
+
+#if ERRATA_SME_POWER_DOWN == 0
+#error "Gelas needs ERRATA_SME_POWER_DOWN=1 to powerdown correctly"
+#endif
+
+cpu_reset_prologue cortex_gelas
+
cpu_reset_func_start cortex_gelas
/* ----------------------------------------------------
* Disable speculative loads
* ----------------------------------------------------
*/
msr SSBS, xzr
+ /* model bug: not cleared on reset */
+ sysreg_bit_clear CORTEX_GELAS_CPUPWRCTLR_EL1, \
+ CORTEX_GELAS_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
+ enable_mpmm
cpu_reset_func_end cortex_gelas
/* ----------------------------------------------------
@@ -34,25 +48,12 @@
* ----------------------------------------------------
*/
func cortex_gelas_core_pwr_dwn
-#if ENABLE_SME_FOR_NS
- /* ---------------------------------------------------
- * Disable SME if enabled and supported
- * ---------------------------------------------------
- */
- mrs x0, ID_AA64PFR1_EL1
- ubfx x0, x0, #ID_AA64PFR1_EL1_SME_SHIFT, \
- #ID_AA64PFR1_EL1_SME_WIDTH
- cmp x0, #SME_NOT_IMPLEMENTED
- b.eq 1f
- msr CORTEX_GELAS_SVCRSM, xzr
- msr CORTEX_GELAS_SVCRZA, xzr
-1:
-#endif
/* ---------------------------------------------------
- * Enable CPU power down bit in power control register
+ * Flip CPU power down bit in power control register.
+ * It will be set on powerdown and cleared on wakeup
* ---------------------------------------------------
*/
- sysreg_bit_set CORTEX_GELAS_CPUPWRCTLR_EL1, \
+ sysreg_bit_toggle CORTEX_GELAS_CPUPWRCTLR_EL1, \
CORTEX_GELAS_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
isb
ret
diff --git a/lib/cpus/aarch64/cortex_x1.S b/lib/cpus/aarch64/cortex_x1.S
index 5bd020c..27d181a 100644
--- a/lib/cpus/aarch64/cortex_x1.S
+++ b/lib/cpus/aarch64/cortex_x1.S
@@ -23,6 +23,8 @@
wa_cve_2022_23960_bhb_vector_table CORTEX_X1_BHB_LOOP_COUNT, cortex_x1
#endif /* WORKAROUND_CVE_2022_23960 */
+cpu_reset_prologue cortex_x1
+
/* Disable hardware page aggregation. Enables mitigation for `CVE-2024-5660` */
workaround_reset_start cortex_x1, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
sysreg_bit_set CORTEX_X1_CPUECTLR_EL1, BIT(46)
diff --git a/lib/cpus/aarch64/cortex_x2.S b/lib/cpus/aarch64/cortex_x2.S
index c18ce3c..b11c37d 100644
--- a/lib/cpus/aarch64/cortex_x2.S
+++ b/lib/cpus/aarch64/cortex_x2.S
@@ -9,6 +9,7 @@
#include <common/bl_common.h>
#include <cortex_x2.h>
#include <cpu_macros.S>
+#include <dsu_macros.S>
#include <plat_macros.S>
#include "wa_cve_2022_23960_bhb_vector.S"
@@ -24,7 +25,7 @@
.global check_erratum_cortex_x2_3701772
-add_erratum_entry cortex_x2, ERRATUM(3701772), ERRATA_X2_3701772, NO_APPLY_AT_RESET
+add_erratum_entry cortex_x2, ERRATUM(3701772), ERRATA_X2_3701772
check_erratum_ls cortex_x2, ERRATUM(3701772), CPU_REV(2, 1)
@@ -32,6 +33,8 @@
wa_cve_2022_23960_bhb_vector_table CORTEX_X2_BHB_LOOP_COUNT, cortex_x2
#endif /* WORKAROUND_CVE_2022_23960 */
+cpu_reset_prologue cortex_x2
+
/* Disable hardware page aggregation. Enables mitigation for `CVE-2024-5660` */
workaround_reset_start cortex_x2, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
sysreg_bit_set CORTEX_X2_CPUECTLR_EL1, BIT(46)
@@ -164,15 +167,14 @@
check_erratum_chosen cortex_x2, CVE(2022, 23960), WORKAROUND_CVE_2022_23960
-/*
- * ERRATA_DSU_2313941 :
- * The errata is defined in dsu_helpers.S but applies to cortex_x2
- * as well. Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_cortex_x2_2313941, check_errata_dsu_2313941
-.equ erratum_cortex_x2_2313941_wa, errata_dsu_2313941_wa
-add_erratum_entry cortex_x2, ERRATUM(2313941), ERRATA_DSU_2313941, APPLY_AT_RESET
+workaround_reset_start cortex_x2, ERRATUM(2313941), ERRATA_DSU_2313941
+ errata_dsu_2313941_wa_impl
+workaround_reset_end cortex_x2, ERRATUM(2313941)
+
+check_erratum_custom_start cortex_x2, ERRATUM(2313941)
+ check_errata_dsu_2313941_impl
+ ret
+check_erratum_custom_end cortex_x2, ERRATUM(2313941)
/* ----------------------------------------------------
* HW will do the cache maintenance while powering down
@@ -193,6 +195,7 @@
cpu_reset_func_start cortex_x2
/* Disable speculative loads */
msr SSBS, xzr
+ enable_mpmm
cpu_reset_func_end cortex_x2
/* ---------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_x3.S b/lib/cpus/aarch64/cortex_x3.S
index 24dbf9d..3d52dae 100644
--- a/lib/cpus/aarch64/cortex_x3.S
+++ b/lib/cpus/aarch64/cortex_x3.S
@@ -24,7 +24,7 @@
.global check_erratum_cortex_x3_3701769
-add_erratum_entry cortex_x3, ERRATUM(3701769), ERRATA_X3_3701769, NO_APPLY_AT_RESET
+add_erratum_entry cortex_x3, ERRATUM(3701769), ERRATA_X3_3701769
check_erratum_ls cortex_x3, ERRATUM(3701769), CPU_REV(1, 2)
@@ -32,6 +32,8 @@
wa_cve_2022_23960_bhb_vector_table CORTEX_X3_BHB_LOOP_COUNT, cortex_x3
#endif /* WORKAROUND_CVE_2022_23960 */
+cpu_reset_prologue cortex_x3
+
/* Disable hardware page aggregation. Enables mitigation for `CVE-2024-5660` */
workaround_reset_start cortex_x3, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
sysreg_bit_set CORTEX_X3_CPUECTLR_EL1, BIT(46)
@@ -52,14 +54,17 @@
check_erratum_ls cortex_x3, ERRATUM(2266875), CPU_REV(1, 0)
-workaround_runtime_start cortex_x3, ERRATUM(2302506), ERRATA_X3_2302506
+workaround_reset_start cortex_x3, ERRATUM(2302506), ERRATA_X3_2302506
sysreg_bit_set CORTEX_X3_CPUACTLR2_EL1, BIT(0)
-workaround_runtime_end cortex_x3, ERRATUM(2302506), NO_ISB
+workaround_reset_end cortex_x3, ERRATUM(2302506)
check_erratum_ls cortex_x3, ERRATUM(2302506), CPU_REV(1, 1)
+.global erratum_cortex_x3_2313909_wa
workaround_runtime_start cortex_x3, ERRATUM(2313909), ERRATA_X3_2313909
- sysreg_bit_set CORTEX_X3_CPUACTLR2_EL1, CORTEX_X3_CPUACTLR2_EL1_BIT_36
+ /* Set/unset bit 36 in ACTLR2_EL1. The first call will set it, applying
+ * the workaround. Second call clears it to undo it. */
+ sysreg_bit_toggle CORTEX_X3_CPUACTLR2_EL1, CORTEX_X3_CPUACTLR2_EL1_BIT_36
workaround_runtime_end cortex_x3, ERRATUM(2313909), NO_ISB
check_erratum_ls cortex_x3, ERRATUM(2313909), CPU_REV(1, 0)
@@ -81,9 +86,9 @@
check_erratum_ls cortex_x3, ERRATUM(2615812), CPU_REV(1, 1)
-workaround_runtime_start cortex_x3, ERRATUM(2641945), ERRATA_X3_2641945
+workaround_reset_start cortex_x3, ERRATUM(2641945), ERRATA_X3_2641945
sysreg_bit_set CORTEX_X3_CPUACTLR6_EL1, BIT(41)
-workaround_runtime_end cortex_x3, ERRATUM(2641945), NO_ISB
+workaround_reset_end cortex_x3, ERRATUM(2641945)
check_erratum_ls cortex_x3, ERRATUM(2641945), CPU_REV(1, 0)
@@ -131,6 +136,7 @@
cpu_reset_func_start cortex_x3
/* Disable speculative loads */
msr SSBS, xzr
+ enable_mpmm
cpu_reset_func_end cortex_x3
/* ----------------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_x4.S b/lib/cpus/aarch64/cortex_x4.S
index fded73f..c067981 100644
--- a/lib/cpus/aarch64/cortex_x4.S
+++ b/lib/cpus/aarch64/cortex_x4.S
@@ -22,6 +22,8 @@
#error "Cortex X4 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
+cpu_reset_prologue cortex_x4
+
.global check_erratum_cortex_x4_2726228
.global check_erratum_cortex_x4_3701758
@@ -29,23 +31,9 @@
wa_cve_2022_23960_bhb_vector_table CORTEX_X4_BHB_LOOP_COUNT, cortex_x4
#endif /* WORKAROUND_CVE_2022_23960 */
-workaround_runtime_start cortex_x4, ERRATUM(2726228), ERRATA_X4_2726228, CORTEX_X4_MIDR
-workaround_runtime_end cortex_x4, ERRATUM(2726228)
-
-check_erratum_custom_start cortex_x4, ERRATUM(2726228)
-
- /* This erratum needs to be enabled for r0p0 and r0p1.
- * Check if revision is less than or equal to r0p1.
- */
+add_erratum_entry cortex_x4, ERRATUM(2726228), ERRATA_X4_2726228
-#if ERRATA_X4_2726228
- mov x1, #1
- b cpu_rev_var_ls
-#else
- mov x0, #ERRATA_MISSING
-#endif
- ret
-check_erratum_custom_end cortex_x4, ERRATUM(2726228)
+check_erratum_ls cortex_x4, ERRATUM(2726228), CPU_REV(0, 1)
/* Disable hardware page aggregation. Enables mitigation for `CVE-2024-5660` */
workaround_reset_start cortex_x4, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
@@ -89,6 +77,21 @@
check_erratum_ls cortex_x4, ERRATUM(2923985), CPU_REV(0, 1)
+workaround_reset_start cortex_x4, ERRATUM(2957258), ERRATA_X4_2957258
+ /* Add ISB before MRS reads of MPIDR_EL1/MIDR_EL1 */
+ ldr x0, =0x1
+ msr S3_6_c15_c8_0, x0 /* msr CPUPSELR_EL3, X0 */
+ ldr x0, =0xd5380000
+ msr S3_6_c15_c8_2, x0 /* msr CPUPOR_EL3, X0 */
+ ldr x0, =0xFFFFFF40
+ msr S3_6_c15_c8_3,x0 /* msr CPUPMR_EL3, X0 */
+ ldr x0, =0x000080010033f
+ msr S3_6_c15_c8_1, x0 /* msr CPUPCR_EL3, X0 */
+ isb
+workaround_reset_end cortex_x4, ERRATUM(2957258)
+
+check_erratum_ls cortex_x4, ERRATUM(2957258), CPU_REV(0, 1)
+
workaround_reset_start cortex_x4, ERRATUM(3076789), ERRATA_X4_3076789
sysreg_bit_set CORTEX_X4_CPUACTLR3_EL1, BIT(14)
sysreg_bit_set CORTEX_X4_CPUACTLR3_EL1, BIT(13)
@@ -120,13 +123,14 @@
check_erratum_chosen cortex_x4, CVE(2024, 7881), WORKAROUND_CVE_2024_7881
-add_erratum_entry cortex_x4, ERRATUM(3701758), ERRATA_X4_3701758, NO_APPLY_AT_RESET
+add_erratum_entry cortex_x4, ERRATUM(3701758), ERRATA_X4_3701758
check_erratum_ls cortex_x4, ERRATUM(3701758), CPU_REV(0, 3)
cpu_reset_func_start cortex_x4
/* Disable speculative loads */
msr SSBS, xzr
+ enable_mpmm
cpu_reset_func_end cortex_x4
/* ----------------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_x925.S b/lib/cpus/aarch64/cortex_x925.S
index e2e70dd..093d91d 100644
--- a/lib/cpus/aarch64/cortex_x925.S
+++ b/lib/cpus/aarch64/cortex_x925.S
@@ -21,12 +21,27 @@
#error "Cortex-X925 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
-.global check_erratum_cortex_x925_3701747
+cpu_reset_prologue cortex_x925
-add_erratum_entry cortex_x925, ERRATUM(3701747), ERRATA_X925_3701747, NO_APPLY_AT_RESET
+add_erratum_entry cortex_x925, ERRATUM(3701747), ERRATA_X925_3701747
check_erratum_ls cortex_x925, ERRATUM(3701747), CPU_REV(0, 1)
+workaround_reset_start cortex_x925, ERRATUM(2963999), ERRATA_X925_2963999
+ /* Add ISB before MRS reads of MPIDR_EL1/MIDR_EL1 */
+ ldr x0, =0x0
+ msr S3_6_c15_c8_0, x0 /* msr CPUPSELR_EL3, X0 */
+ ldr x0, =0xd5380000
+ msr S3_6_c15_c8_2, x0 /* msr CPUPOR_EL3, X0 */
+ ldr x0, =0xFFFFFF40
+ msr S3_6_c15_c8_3,x0 /* msr CPUPMR_EL3, X0 */
+ ldr x0, =0x000080010033f
+ msr S3_6_c15_c8_1, x0 /* msr CPUPCR_EL3, X0 */
+ isb
+workaround_reset_end cortex_x925, ERRATUM(2963999)
+
+check_erratum_ls cortex_x925, ERRATUM(2963999), CPU_REV(0, 0)
+
/* Disable hardware page aggregation. Enables mitigation for `CVE-2024-5660` */
workaround_reset_start cortex_x925, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
sysreg_bit_set CORTEX_X925_CPUECTLR_EL1, BIT(46)
@@ -48,6 +63,7 @@
cpu_reset_func_start cortex_x925
/* Disable speculative loads */
msr SSBS, xzr
+ enable_mpmm
cpu_reset_func_end cortex_x925
/* ----------------------------------------------------
diff --git a/lib/cpus/aarch64/cpu_helpers.S b/lib/cpus/aarch64/cpu_helpers.S
index 0f9a3b8..e608422 100644
--- a/lib/cpus/aarch64/cpu_helpers.S
+++ b/lib/cpus/aarch64/cpu_helpers.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -14,47 +14,6 @@
#include <lib/cpus/errata.h>
#include <lib/el3_runtime/cpu_data.h>
- /* Reset fn is needed in BL at reset vector */
-#if defined(IMAGE_BL1) || defined(IMAGE_BL31) || \
- (defined(IMAGE_BL2) && RESET_TO_BL2)
- /*
- * The reset handler common to all platforms. After a matching
- * cpu_ops structure entry is found, the correponding reset_handler
- * in the cpu_ops is invoked.
- * Clobbers: x0 - x19, x30
- */
- .globl reset_handler
-func reset_handler
- mov x19, x30
-
- /* The plat_reset_handler can clobber x0 - x18, x30 */
- bl plat_reset_handler
-
- /* Get the matching cpu_ops pointer */
- bl get_cpu_ops_ptr
-
-#if ENABLE_ASSERTIONS
- /*
- * Assert if invalid cpu_ops obtained. If this is not valid, it may
- * suggest that the proper CPU file hasn't been included.
- */
- cmp x0, #0
- ASM_ASSERT(ne)
-#endif
-
- /* Get the cpu_ops reset handler */
- ldr x2, [x0, #CPU_RESET_FUNC]
- mov x30, x19
- cbz x2, 1f
-
- /* The cpu_ops reset handler can clobber x0 - x19, x30 */
- br x2
-1:
- ret
-endfunc reset_handler
-
-#endif
-
#ifdef IMAGE_BL31 /* The power down core and cluster is needed only in BL31 */
/*
* void prepare_cpu_pwr_dwn(unsigned int power_level)
@@ -213,83 +172,24 @@
b 1b
error_exit:
#endif
+#if ENABLE_ASSERTIONS
+ /*
+ * Assert if invalid cpu_ops obtained. If this is not valid, it may
+ * suggest that the proper CPU file hasn't been included.
+ */
+ cmp x0, #0
+ ASM_ASSERT(ne)
+#endif
ret
endfunc get_cpu_ops_ptr
-/*
- * Extract CPU revision and variant, and combine them into a single numeric for
- * easier comparison.
- */
.globl cpu_get_rev_var
func cpu_get_rev_var
- mrs x1, midr_el1
-
- /*
- * Extract the variant[23:20] and revision[3:0] from MIDR, and pack them
- * as variant[7:4] and revision[3:0] of x0.
- *
- * First extract x1[23:16] to x0[7:0] and zero fill the rest. Then
- * extract x1[3:0] into x0[3:0] retaining other bits.
- */
- ubfx x0, x1, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS)
- bfxil x0, x1, #MIDR_REV_SHIFT, #MIDR_REV_BITS
+ get_rev_var x0, x1
ret
endfunc cpu_get_rev_var
/*
- * Compare the CPU's revision-variant (x0) with a given value (x1), for errata
- * application purposes. If the revision-variant is less than or same as a given
- * value, indicates that errata applies; otherwise not.
- *
- * Shall clobber: x0-x3
- */
- .globl cpu_rev_var_ls
-func cpu_rev_var_ls
- mov x2, #ERRATA_APPLIES
- mov x3, #ERRATA_NOT_APPLIES
- cmp x0, x1
- csel x0, x2, x3, ls
- ret
-endfunc cpu_rev_var_ls
-
-/*
- * Compare the CPU's revision-variant (x0) with a given value (x1), for errata
- * application purposes. If the revision-variant is higher than or same as a
- * given value, indicates that errata applies; otherwise not.
- *
- * Shall clobber: x0-x3
- */
- .globl cpu_rev_var_hs
-func cpu_rev_var_hs
- mov x2, #ERRATA_APPLIES
- mov x3, #ERRATA_NOT_APPLIES
- cmp x0, x1
- csel x0, x2, x3, hs
- ret
-endfunc cpu_rev_var_hs
-
-/*
- * Compare the CPU's revision-variant (x0) with a given range (x1 - x2), for errata
- * application purposes. If the revision-variant is between or includes the given
- * values, this indicates that errata applies; otherwise not.
- *
- * Shall clobber: x0-x4
- */
- .globl cpu_rev_var_range
-func cpu_rev_var_range
- mov x3, #ERRATA_APPLIES
- mov x4, #ERRATA_NOT_APPLIES
- cmp x0, x1
- csel x1, x3, x4, hs
- cbz x1, 1f
- cmp x0, x2
- csel x1, x3, x4, ls
-1:
- mov x0, x1
- ret
-endfunc cpu_rev_var_range
-
-/*
* int check_wa_cve_2017_5715(void);
*
* This function returns:
diff --git a/lib/cpus/aarch64/denver.S b/lib/cpus/aarch64/denver.S
index ca250d3..64158e7 100644
--- a/lib/cpus/aarch64/denver.S
+++ b/lib/cpus/aarch64/denver.S
@@ -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.
* Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -13,6 +13,8 @@
#include <cpu_macros.S>
#include <plat_macros.S>
+cpu_reset_prologue denver
+
/* -------------------------------------------------
* CVE-2017-5715 mitigation
*
diff --git a/lib/cpus/aarch64/dsu_helpers.S b/lib/cpus/aarch64/dsu_helpers.S
deleted file mode 100644
index 3c5bf2e..0000000
--- a/lib/cpus/aarch64/dsu_helpers.S
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (c) 2019-2023, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <asm_macros.S>
-#include <dsu_def.h>
-#include <lib/cpus/errata.h>
-
- /* -----------------------------------------------------------------------
- * DSU erratum 798953 check function
- * Checks the DSU variant, revision and configuration to determine if
- * the erratum applies. Erratum applies on all configurations of the
- * DSU and if revision-variant is r0p0.
- *
- * The erratum was fixed in r0p1.
- *
- * This function is called from both assembly and C environment. So it
- * follows AAPCS.
- *
- * Clobbers: x0-x3
- * -----------------------------------------------------------------------
- */
- .globl check_errata_dsu_798953
- .globl errata_dsu_798953_wa
- .globl dsu_pwr_dwn
-
-func check_errata_dsu_798953
- mov x2, #ERRATA_APPLIES
- mov x3, #ERRATA_NOT_APPLIES
-
- /* Check if DSU is equal to r0p0 */
- mrs x1, CLUSTERIDR_EL1
-
- /* DSU variant and revision bitfields in CLUSTERIDR are adjacent */
- ubfx x0, x1, #CLUSTERIDR_REV_SHIFT,\
- #(CLUSTERIDR_REV_BITS + CLUSTERIDR_VAR_BITS)
- mov x1, #(0x0 << CLUSTERIDR_REV_SHIFT)
- cmp x0, x1
- csel x0, x2, x3, EQ
- ret
-endfunc check_errata_dsu_798953
-
- /* --------------------------------------------------
- * Errata Workaround for DSU erratum #798953.
- *
- * Can clobber only: x0-x8
- * --------------------------------------------------
- */
-func errata_dsu_798953_wa
- mov x8, x30
- bl check_errata_dsu_798953
- cbz x0, 1f
-
- /* If erratum applies, disable high-level clock gating */
- mrs x0, CLUSTERACTLR_EL1
- orr x0, x0, #CLUSTERACTLR_EL1_DISABLE_CLOCK_GATING
- msr CLUSTERACTLR_EL1, x0
- isb
-1:
- ret x8
-endfunc errata_dsu_798953_wa
-
- /* -----------------------------------------------------------------------
- * DSU erratum 936184 check function
- * Checks the DSU variant, revision and configuration to determine if
- * the erratum applies. Erratum applies if ACP interface is present
- * in the DSU and revision-variant < r2p0.
- *
- * The erratum was fixed in r2p0.
- *
- * This function is called from both assembly and C environment. So it
- * follows AAPCS.
- *
- * Clobbers: x0-x4
- * -----------------------------------------------------------------------
- */
- .globl check_errata_dsu_936184
- .globl errata_dsu_936184_wa
- .weak is_scu_present_in_dsu
-
- /* --------------------------------------------------------------------
- * Default behaviour respresents SCU is always present with DSU.
- * CPUs can override this definition if required.
- *
- * Can clobber only: x0-x3
- * --------------------------------------------------------------------
- */
-func is_scu_present_in_dsu
- mov x0, #1
- ret
-endfunc is_scu_present_in_dsu
-
-func check_errata_dsu_936184
- mov x4, x30
- bl is_scu_present_in_dsu
- cmp x0, xzr
- /* Default error status */
- mov x0, #ERRATA_NOT_APPLIES
-
- /* If SCU is not present, return without applying patch */
- b.eq 1f
-
- /* Erratum applies only if DSU has the ACP interface */
- mrs x1, CLUSTERCFR_EL1
- ubfx x1, x1, #CLUSTERCFR_ACP_SHIFT, #1
- cbz x1, 1f
-
- /* If ACP is present, check if DSU is older than r2p0 */
- mrs x1, CLUSTERIDR_EL1
-
- /* DSU variant and revision bitfields in CLUSTERIDR are adjacent */
- ubfx x2, x1, #CLUSTERIDR_REV_SHIFT,\
- #(CLUSTERIDR_REV_BITS + CLUSTERIDR_VAR_BITS)
- cmp x2, #(0x2 << CLUSTERIDR_VAR_SHIFT)
- b.hs 1f
- mov x0, #ERRATA_APPLIES
-1:
- ret x4
-endfunc check_errata_dsu_936184
-
- /* --------------------------------------------------
- * Errata Workaround for DSU erratum #936184.
- *
- * Can clobber only: x0-x8
- * --------------------------------------------------
- */
-func errata_dsu_936184_wa
- mov x8, x30
- bl check_errata_dsu_936184
- cbz x0, 1f
-
- /* If erratum applies, we set a mask to a DSU control register */
- mrs x0, CLUSTERACTLR_EL1
- ldr x1, =DSU_ERRATA_936184_MASK
- orr x0, x0, x1
- msr CLUSTERACTLR_EL1, x0
- isb
-1:
- ret x8
-endfunc errata_dsu_936184_wa
-
- /* -----------------------------------------------------------------------
- * DSU erratum 2313941 check function
- * Checks the DSU variant, revision and configuration to determine if
- * the erratum applies. Erratum applies on all configurations of the
- * DSU and if revision-variant is r0p0, r1p0, r2p0, r2p1, r3p0, r3p1.
- *
- * The erratum is still open.
- *
- * This function is called from both assembly and C environment. So it
- * follows AAPCS.
- *
- * Clobbers: x0-x4
- * -----------------------------------------------------------------------
- */
- .globl check_errata_dsu_2313941
- .globl errata_dsu_2313941_wa
-
-func check_errata_dsu_2313941
- mov x4, x30
- bl is_scu_present_in_dsu
- cmp x0, xzr
- /* Default error status */
- mov x0, #ERRATA_NOT_APPLIES
-
- /* If SCU is not present, return without applying patch */
- b.eq 1f
-
- mov x2, #ERRATA_APPLIES
- mov x3, #ERRATA_NOT_APPLIES
-
- /* Check if DSU version is less than or equal to r3p1 */
- mrs x1, CLUSTERIDR_EL1
-
- /* DSU variant and revision bitfields in CLUSTERIDR are adjacent */
- ubfx x0, x1, #CLUSTERIDR_REV_SHIFT,\
- #(CLUSTERIDR_REV_BITS + CLUSTERIDR_VAR_BITS)
- mov x1, #(0x31 << CLUSTERIDR_REV_SHIFT)
- cmp x0, x1
- csel x0, x2, x3, LS
-1:
- ret x4
-endfunc check_errata_dsu_2313941
-
- /* --------------------------------------------------
- * Errata Workaround for DSU erratum #2313941.
- *
- * Can clobber only: x0-x8
- * --------------------------------------------------
- */
-func errata_dsu_2313941_wa
- mov x8, x30
- bl check_errata_dsu_2313941
- cbz x0, 1f
-
- /* If erratum applies, disable high-level clock gating */
- mrs x0, CLUSTERACTLR_EL1
- orr x0, x0, #CLUSTERACTLR_EL1_DISABLE_SCLK_GATING
- msr CLUSTERACTLR_EL1, x0
- isb
-1:
- ret x8
-endfunc errata_dsu_2313941_wa
-
- /* ---------------------------------------------
- * controls power features of the cluster
- * 1. Cache portion power not request
- * 2. Disable the retention circuit
- * ---------------------------------------------
- */
-func dsu_pwr_dwn
- msr CLUSTERPWRCTLR_EL1, xzr
- isb
- ret
-endfunc dsu_pwr_dwn
diff --git a/lib/cpus/aarch64/generic.S b/lib/cpus/aarch64/generic.S
index 5d7a857..0a10eed 100644
--- a/lib/cpus/aarch64/generic.S
+++ b/lib/cpus/aarch64/generic.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,6 +11,8 @@
#include <cpu_macros.S>
#include <plat_macros.S>
+cpu_reset_prologue generic
+
/* ---------------------------------------------
* Disable L1 data cache and unified L2 cache
* ---------------------------------------------
@@ -80,7 +82,9 @@
* ---------------------------------------------
*/
.equ generic_cpu_reg_dump, 0
-.equ generic_reset_func, 0
+
+cpu_reset_func_start generic
+cpu_reset_func_end generic
declare_cpu_ops generic, AARCH64_GENERIC_MIDR, \
generic_reset_func, \
diff --git a/lib/cpus/aarch64/neoverse_e1.S b/lib/cpus/aarch64/neoverse_e1.S
index 4bc95d0..f37bb28 100644
--- a/lib/cpus/aarch64/neoverse_e1.S
+++ b/lib/cpus/aarch64/neoverse_e1.S
@@ -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
*/
@@ -7,6 +7,7 @@
#include <asm_macros.S>
#include <common/bl_common.h>
#include <common/debug.h>
+#include <dsu_macros.S>
#include <neoverse_e1.h>
#include <cpu_macros.S>
#include <plat_macros.S>
@@ -21,15 +22,18 @@
#error "Neoverse-E1 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
-/*
- * ERRATA_DSU_936184:
- * The errata is defined in dsu_helpers.S and applies to neoverse_e1.
- * Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_neoverse_e1_936184, check_errata_dsu_936184
-.equ erratum_neoverse_e1_936184_wa, errata_dsu_936184_wa
-add_erratum_entry neoverse_e1, ERRATUM(936184), ERRATA_DSU_936184, APPLY_AT_RESET
+cpu_reset_prologue neoverse_e1
+
+workaround_reset_start neoverse_e1, ERRATUM(936184), ERRATA_DSU_936184
+ errata_dsu_936184_wa_impl
+workaround_reset_end neoverse_e1, ERRATUM(936184)
+
+check_erratum_custom_start neoverse_e1, ERRATUM(936184)
+ branch_if_scu_not_present 2f /* label 1 is used in the macro */
+ check_errata_dsu_936184_impl
+ 2:
+ ret
+check_erratum_custom_end neoverse_e1, ERRATUM(936184)
cpu_reset_func_start neoverse_e1
cpu_reset_func_end neoverse_e1
diff --git a/lib/cpus/aarch64/neoverse_n1.S b/lib/cpus/aarch64/neoverse_n1.S
index f727226..1ad9557 100644
--- a/lib/cpus/aarch64/neoverse_n1.S
+++ b/lib/cpus/aarch64/neoverse_n1.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -8,6 +8,7 @@
#include <asm_macros.S>
#include <cpuamu.h>
#include <cpu_macros.S>
+#include <dsu_macros.S>
#include <neoverse_n1.h>
#include "wa_cve_2022_23960_bhb_vector.S"
@@ -27,15 +28,18 @@
wa_cve_2022_23960_bhb_vector_table NEOVERSE_N1_BHB_LOOP_COUNT, neoverse_n1
#endif /* WORKAROUND_CVE_2022_23960 */
-/*
- * ERRATA_DSU_936184:
- * The errata is defined in dsu_helpers.S and applies to Neoverse N1.
- * Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_neoverse_n1_936184, check_errata_dsu_936184
-.equ erratum_neoverse_n1_936184_wa, errata_dsu_936184_wa
-add_erratum_entry neoverse_n1, ERRATUM(936184), ERRATA_DSU_936184, APPLY_AT_RESET
+cpu_reset_prologue neoverse_n1
+
+workaround_reset_start neoverse_n1, ERRATUM(936184), ERRATA_DSU_936184
+ errata_dsu_936184_wa_impl
+workaround_reset_end neoverse_n1, ERRATUM(936184)
+
+check_erratum_custom_start neoverse_n1, ERRATUM(936184)
+ branch_if_scu_not_present 2f /* label 1 is used in the macro */
+ check_errata_dsu_936184_impl
+ 2:
+ ret
+check_erratum_custom_end neoverse_n1, ERRATUM(936184)
workaround_reset_start neoverse_n1, ERRATUM(1043202), ERRATA_N1_1043202
/* Apply instruction patching sequence */
diff --git a/lib/cpus/aarch64/neoverse_n2.S b/lib/cpus/aarch64/neoverse_n2.S
index 3df3839..9c6f01a 100644
--- a/lib/cpus/aarch64/neoverse_n2.S
+++ b/lib/cpus/aarch64/neoverse_n2.S
@@ -7,6 +7,7 @@
#include <arch.h>
#include <asm_macros.S>
#include <cpu_macros.S>
+#include <dsu_macros.S>
#include <neoverse_n2.h>
#include "wa_cve_2022_23960_bhb_vector.S"
@@ -22,7 +23,7 @@
.global check_erratum_neoverse_n2_3701773
-add_erratum_entry neoverse_n2, ERRATUM(3701773), ERRATA_N2_3701773, NO_APPLY_AT_RESET
+add_erratum_entry neoverse_n2, ERRATUM(3701773), ERRATA_N2_3701773
check_erratum_ls neoverse_n2, ERRATUM(3701773), CPU_REV(0, 3)
@@ -30,15 +31,18 @@
wa_cve_2022_23960_bhb_vector_table NEOVERSE_N2_BHB_LOOP_COUNT, neoverse_n2
#endif /* WORKAROUND_CVE_2022_23960 */
-/*
- * ERRATA_DSU_2313941:
- * The errata is defined in dsu_helpers.S and applies to Neoverse N2.
- * Henceforth creating symbolic names to the already existing errata
- * workaround functions to get them registered under the Errata Framework.
- */
-.equ check_erratum_neoverse_n2_2313941, check_errata_dsu_2313941
-.equ erratum_neoverse_n2_2313941_wa, errata_dsu_2313941_wa
-add_erratum_entry neoverse_n2, ERRATUM(2313941), ERRATA_DSU_2313941, APPLY_AT_RESET
+cpu_reset_prologue neoverse_n2
+
+workaround_reset_start neoverse_n2, ERRATUM(2313941), ERRATA_DSU_2313941
+ errata_dsu_2313941_wa_impl
+workaround_reset_end neoverse_n2, ERRATUM(2313941)
+
+check_erratum_custom_start neoverse_n2, ERRATUM(2313941)
+ branch_if_scu_not_present 2f /* label 1 is used in the macro */
+ check_errata_dsu_2313941_impl
+ 2:
+ ret
+check_erratum_custom_end neoverse_n2, ERRATUM(2313941)
/* Disable hardware page aggregation. Enables mitigation for `CVE-2024-5660` */
workaround_reset_start neoverse_n2, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
@@ -171,27 +175,29 @@
check_erratum_ls neoverse_n2, ERRATUM(2280757), CPU_REV(0, 0)
+.global erratum_neoverse_n2_2326639_wa
workaround_runtime_start neoverse_n2, ERRATUM(2326639), ERRATA_N2_2326639
- /* Set bit 36 in ACTLR2_EL1 */
- sysreg_bit_set NEOVERSE_N2_CPUACTLR2_EL1, NEOVERSE_N2_CPUACTLR2_EL1_BIT_36
+ /* Set/unset bit 36 in ACTLR2_EL1. The first call will set it, applying
+ * the workaround. Second call clears it to undo it. */
+ sysreg_bit_toggle NEOVERSE_N2_CPUACTLR2_EL1, NEOVERSE_N2_CPUACTLR2_EL1_BIT_36
workaround_runtime_end neoverse_n2, ERRATUM(2326639)
check_erratum_ls neoverse_n2, ERRATUM(2326639), CPU_REV(0, 0)
-workaround_runtime_start neoverse_n2, ERRATUM(2340933), ERRATA_N2_2340933
+workaround_reset_start neoverse_n2, ERRATUM(2340933), ERRATA_N2_2340933
/* Set bit 61 in CPUACTLR5_EL1 */
sysreg_bit_set NEOVERSE_N2_CPUACTLR5_EL1, BIT(61)
-workaround_runtime_end neoverse_n2, ERRATUM(2340933)
+workaround_reset_end neoverse_n2, ERRATUM(2340933)
check_erratum_ls neoverse_n2, ERRATUM(2340933), CPU_REV(0, 0)
-workaround_runtime_start neoverse_n2, ERRATUM(2346952), ERRATA_N2_2346952
+workaround_reset_start neoverse_n2, ERRATUM(2346952), ERRATA_N2_2346952
/* Set TXREQ to STATIC and full L2 TQ size */
mrs x1, NEOVERSE_N2_CPUECTLR2_EL1
mov x0, #CPUECTLR2_EL1_TXREQ_STATIC_FULL
bfi x1, x0, #CPUECTLR2_EL1_TXREQ_LSB, #CPUECTLR2_EL1_TXREQ_WIDTH
msr NEOVERSE_N2_CPUECTLR2_EL1, x1
-workaround_runtime_end neoverse_n2, ERRATUM(2346952)
+workaround_reset_end neoverse_n2, ERRATUM(2346952)
check_erratum_ls neoverse_n2, ERRATUM(2346952), CPU_REV(0, 2)
diff --git a/lib/cpus/aarch64/neoverse_n3.S b/lib/cpus/aarch64/neoverse_n3.S
index 8abcafe..1b7a3e1 100644
--- a/lib/cpus/aarch64/neoverse_n3.S
+++ b/lib/cpus/aarch64/neoverse_n3.S
@@ -21,9 +21,11 @@
#error "Neoverse-N3 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
+cpu_reset_prologue neoverse_n3
+
.global check_erratum_neoverse_n3_3699563
-add_erratum_entry neoverse_n3, ERRATUM(3699563), ERRATA_N3_3699563, NO_APPLY_AT_RESET
+add_erratum_entry neoverse_n3, ERRATUM(3699563), ERRATA_N3_3699563
check_erratum_ls neoverse_n3, ERRATUM(3699563), CPU_REV(0, 0)
diff --git a/lib/cpus/aarch64/neoverse_n_common.S b/lib/cpus/aarch64/neoverse_n_common.S
deleted file mode 100644
index b816342..0000000
--- a/lib/cpus/aarch64/neoverse_n_common.S
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <asm_macros.S>
-#include <neoverse_n_common.h>
-
- .global is_scu_present_in_dsu
-
-/*
- * Check if the SCU L3 Unit is present on the DSU
- * 1-> SCU present
- * 0-> SCU not present
- *
- * This function is implemented as weak on dsu_helpers.S and must be
- * overwritten for Neoverse Nx cores.
- */
-
-func is_scu_present_in_dsu
- mrs x0, CPUCFR_EL1
- ubfx x0, x0, #SCU_SHIFT, #1
- eor x0, x0, #1
- ret
-endfunc is_scu_present_in_dsu
diff --git a/lib/cpus/aarch64/neoverse_v1.S b/lib/cpus/aarch64/neoverse_v1.S
index d1a2c24..e1e8214 100644
--- a/lib/cpus/aarch64/neoverse_v1.S
+++ b/lib/cpus/aarch64/neoverse_v1.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -22,6 +22,8 @@
#error "Neoverse-V1 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
+cpu_reset_prologue neoverse_v1
+
#if WORKAROUND_CVE_2022_23960
wa_cve_2022_23960_bhb_vector_table NEOVERSE_V1_BHB_LOOP_COUNT, neoverse_v1
#endif /* WORKAROUND_CVE_2022_23960 */
@@ -203,10 +205,10 @@
check_erratum_ls neoverse_v1, ERRATUM(2294912), CPU_REV(1, 2)
-workaround_runtime_start neoverse_v1, ERRATUM(2348377), ERRATA_V1_2348377
+workaround_reset_start neoverse_v1, ERRATUM(2348377), ERRATA_V1_2348377
/* Set bit 61 in CPUACTLR5_EL1 */
sysreg_bit_set NEOVERSE_V1_ACTLR5_EL1, NEOVERSE_V1_ACTLR5_EL1_BIT_61
-workaround_runtime_end neoverse_v1, ERRATUM(2348377)
+workaround_reset_end neoverse_v1, ERRATUM(2348377)
check_erratum_ls neoverse_v1, ERRATUM(2348377), CPU_REV(1, 1)
diff --git a/lib/cpus/aarch64/neoverse_v2.S b/lib/cpus/aarch64/neoverse_v2.S
index b43f6dd..06521ec 100644
--- a/lib/cpus/aarch64/neoverse_v2.S
+++ b/lib/cpus/aarch64/neoverse_v2.S
@@ -22,6 +22,8 @@
#error "Neoverse V2 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
+cpu_reset_prologue neoverse_v2
+
/* Disable hardware page aggregation. Enables mitigation for `CVE-2024-5660` */
workaround_reset_start neoverse_v2, CVE(2024, 5660), WORKAROUND_CVE_2024_5660
sysreg_bit_set NEOVERSE_V2_CPUECTLR_EL1, BIT(46)
diff --git a/lib/cpus/aarch64/neoverse_v3.S b/lib/cpus/aarch64/neoverse_v3.S
index 7fe2d7f..29bfd0e 100644
--- a/lib/cpus/aarch64/neoverse_v3.S
+++ b/lib/cpus/aarch64/neoverse_v3.S
@@ -22,12 +22,29 @@
#error "Neoverse V3 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
+cpu_reset_prologue neoverse_v3
+
.global check_erratum_neoverse_v3_3701767
-add_erratum_entry neoverse_v3, ERRATUM(3701767), ERRATA_V3_3701767, NO_APPLY_AT_RESET
+add_erratum_entry neoverse_v3, ERRATUM(3701767), ERRATA_V3_3701767
check_erratum_ls neoverse_v3, ERRATUM(3701767), CPU_REV(0, 2)
+workaround_reset_start neoverse_v3, ERRATUM(2970647), ERRATA_V3_2970647
+ /* Add ISB before MRS reads of MPIDR_EL1/MIDR_EL1 */
+ ldr x0, =0x1
+ msr S3_6_c15_c8_0, x0 /* msr CPUPSELR_EL3, X0 */
+ ldr x0, =0xd5380000
+ msr S3_6_c15_c8_2, x0 /* msr CPUPOR_EL3, X0 */
+ ldr x0, =0xFFFFFF40
+ msr S3_6_c15_c8_3,x0 /* msr CPUPMR_EL3, X0 */
+ ldr x0, =0x000080010033f
+ msr S3_6_c15_c8_1, x0 /* msr CPUPCR_EL3, X0 */
+ isb
+workaround_reset_end neoverse_v3, ERRATUM(2970647)
+
+check_erratum_ls neoverse_v3, ERRATUM(2970647), CPU_REV(0, 0)
+
#if WORKAROUND_CVE_2022_23960
wa_cve_2022_23960_bhb_vector_table NEOVERSE_V3_BHB_LOOP_COUNT, neoverse_v3
#endif /* WORKAROUND_CVE_2022_23960 */
diff --git a/lib/cpus/aarch64/nevis.S b/lib/cpus/aarch64/nevis.S
index 0180ab7..b2aa26e 100644
--- a/lib/cpus/aarch64/nevis.S
+++ b/lib/cpus/aarch64/nevis.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -21,12 +21,15 @@
#error "Nevis supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
+cpu_reset_prologue nevis
+
cpu_reset_func_start nevis
/* ----------------------------------------------------
* Disable speculative loads
* ----------------------------------------------------
*/
msr SSBS, xzr
+ enable_mpmm
cpu_reset_func_end nevis
func nevis_core_pwr_dwn
diff --git a/lib/cpus/aarch64/qemu_max.S b/lib/cpus/aarch64/qemu_max.S
index fb03cf1..a727379 100644
--- a/lib/cpus/aarch64/qemu_max.S
+++ b/lib/cpus/aarch64/qemu_max.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -8,6 +8,8 @@
#include <cpu_macros.S>
#include <qemu_max.h>
+cpu_reset_prologue qemu_max
+
func qemu_max_core_pwr_dwn
/* ---------------------------------------------
* Disable the Data Cache.
@@ -47,6 +49,9 @@
b dcsw_op_all
endfunc qemu_max_cluster_pwr_dwn
+cpu_reset_func_start qemu_max
+cpu_reset_func_end qemu_max
+
/* ---------------------------------------------
* This function provides cpu specific
* register information for crash reporting.
@@ -67,6 +72,6 @@
/* cpu_ops for QEMU MAX */
-declare_cpu_ops qemu_max, QEMU_MAX_MIDR, CPU_NO_RESET_FUNC, \
+declare_cpu_ops qemu_max, QEMU_MAX_MIDR, qemu_max_reset_func, \
qemu_max_core_pwr_dwn, \
qemu_max_cluster_pwr_dwn
diff --git a/lib/cpus/aarch64/rainier.S b/lib/cpus/aarch64/rainier.S
index ea687be..9ad9362 100644
--- a/lib/cpus/aarch64/rainier.S
+++ b/lib/cpus/aarch64/rainier.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -21,6 +21,8 @@
#error "Rainier CPU supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
+cpu_reset_prologue rainier
+
/* --------------------------------------------------
* Disable speculative loads if Rainier supports
* SSBS.
diff --git a/lib/cpus/aarch64/travis.S b/lib/cpus/aarch64/travis.S
index e8b3860..d53e46f 100644
--- a/lib/cpus/aarch64/travis.S
+++ b/lib/cpus/aarch64/travis.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -21,34 +21,35 @@
#error "Travis supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
+#if FEAT_PABANDON == 0
+#error "Travis must be compiled with FEAT_PABANDON enabled"
+#endif
+
+#if ERRATA_SME_POWER_DOWN == 0
+#error "Travis needs ERRATA_SME_POWER_DOWN=1 to powerdown correctly"
+#endif
+
+cpu_reset_prologue travis
+
cpu_reset_func_start travis
/* ----------------------------------------------------
* Disable speculative loads
* ----------------------------------------------------
*/
msr SSBS, xzr
+ /* model bug: not cleared on reset */
+ sysreg_bit_clear TRAVIS_IMP_CPUPWRCTLR_EL1, \
+ TRAVIS_IMP_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT
+ enable_mpmm
cpu_reset_func_end travis
func travis_core_pwr_dwn
-#if ENABLE_SME_FOR_NS
- /* ---------------------------------------------------
- * Disable SME if enabled and supported
- * ---------------------------------------------------
- */
- mrs x0, ID_AA64PFR1_EL1
- ubfx x0, x0, #ID_AA64PFR1_EL1_SME_SHIFT, \
- #ID_AA64PFR1_EL1_SME_WIDTH
- cmp x0, #SME_NOT_IMPLEMENTED
- b.eq 1f
- msr TRAVIS_SVCRSM, xzr
- msr TRAVIS_SVCRZA, xzr
-1:
-#endif
/* ---------------------------------------------------
- * Enable CPU power down bit in power control register
+ * Flip CPU power down bit in power control register.
+ * It will be set on powerdown and cleared on wakeup
* ---------------------------------------------------
*/
- sysreg_bit_set TRAVIS_IMP_CPUPWRCTLR_EL1, \
+ sysreg_bit_toggle TRAVIS_IMP_CPUPWRCTLR_EL1, \
TRAVIS_IMP_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT
isb
ret
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 0db7e94..8136624 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -564,6 +564,10 @@
# still open.
CPU_FLAG_LIST += ERRATA_V1_2779461
+# Flag to apply erratum 2970647 workaround during reset. This erratum applies
+# to revisions r0p0 of the Neoverse V3 cpu and is fixed in r0p1.
+CPU_FLAG_LIST += ERRATA_V3_2970647
+
# Flag to apply erratum 3701767 workaround during context save/restore of
# ICH_VMCR_EL2 reg. This erratum applies to revisions r0p0, r0p1 and r0p2 of
# the Neoverse V3 cpu and is still open.
@@ -885,6 +889,12 @@
# to revisions r0p0 and r0p1 of the Cortex-X4 cpu. It is fixed in r0p2.
CPU_FLAG_LIST += ERRATA_X4_2923985
+# Flag to apply erratum 2957258 workaround to avoid incorrect virtualization of
+# MPIDR_EL1/VMPIDR_EL2 and MIDR_EL1/VPIDR_EL2 when reading in EL2/EL3. This
+# erratum applies to revisions r0p0, r0p1 of the Cortex-X4 cpu. It is fixed
+# in r0p2.
+CPU_FLAG_LIST += ERRATA_X4_2957258
+
# Flag to apply erratum 3076789 workaround on reset. This erratum applies
# to revisions r0p0 and r0p1 of the Cortex-X4 cpu. It is fixed in r0p2.
CPU_FLAG_LIST += ERRATA_X4_3076789
@@ -894,6 +904,10 @@
# of the Cortex-X4 cpu and is still open.
CPU_FLAG_LIST += ERRATA_X4_3701758
+# Flag to apply erratum 2963999 workaround during reset. This erratum applies
+# to revisions r0p0 of the Cortex-X925 cpu and is fixed in r0p1.
+CPU_FLAG_LIST += ERRATA_X925_2963999
+
# Flag to apply erratum 3701747 workaround during context save/restore of
# ICH_VMCR_EL2 reg. This erratum applies to revisions r0p0, r0p1 of the
# Cortex-X925 cpu and is still open.
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index fed24f0..1e6a42e 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -75,6 +75,9 @@
*/
#if CTX_INCLUDE_FPREGS
func fpregs_context_save
+ /* Save x0 and pass its original value to fpregs_state_save */
+ mov x1, x0
+
stp q0, q1, [x0], #32
stp q2, q3, [x0], #32
stp q4, q5, [x0], #32
@@ -92,7 +95,7 @@
stp q28, q29, [x0], #32
stp q30, q31, [x0], #32
- fpregs_state_save x0, x9
+ fpregs_state_save x1, x9
ret
endfunc fpregs_context_save
@@ -112,6 +115,9 @@
* ------------------------------------------------------------------
*/
func fpregs_context_restore
+ /* Save x0 and pass its original value to fpregs_state_restore */
+ mov x1, x0
+
ldp q0, q1, [x0], #32
ldp q2, q3, [x0], #32
ldp q4, q5, [x0], #32
@@ -129,7 +135,7 @@
ldp q28, q29, [x0], #32
ldp q30, q31, [x0], #32
- fpregs_state_restore x0, x9
+ fpregs_state_restore x1, x9
ret
endfunc fpregs_context_restore
@@ -203,19 +209,6 @@
*/
func sve_context_save
.arch_extension sve
- /* Temporarily enable SVE */
- mrs x10, cptr_el3
- orr x11, x10, #CPTR_EZ_BIT
- bic x11, x11, #TFP_BIT
- msr cptr_el3, x11
- isb
-
- /* zcr_el3 */
- mrs x12, S3_6_C1_C2_0
- mov x13, #((SVE_VECTOR_LEN >> 7) - 1)
- msr S3_6_C1_C2_0, x13
- isb
-
/* Predicate registers */
mov x13, #CTX_SIMD_PREDICATES
add x9, x0, x13
@@ -231,11 +224,6 @@
mov x13, #CTX_SIMD_VECTORS
add x9, x0, x13
sve_vectors_op str, x9
-
- /* Restore SVE enablement */
- msr S3_6_C1_C2_0, x12 /* zcr_el3 */
- msr cptr_el3, x10
- isb
.arch_extension nosve
/* Save FPSR, FPCR and FPEXC32 */
@@ -254,19 +242,6 @@
*/
func sve_context_restore
.arch_extension sve
- /* Temporarily enable SVE for EL3 */
- mrs x10, cptr_el3
- orr x11, x10, #CPTR_EZ_BIT
- bic x11, x11, #TFP_BIT
- msr cptr_el3, x11
- isb
-
- /* zcr_el3 */
- mrs x12, S3_6_C1_C2_0
- mov x13, #((SVE_VECTOR_LEN >> 7) - 1)
- msr S3_6_C1_C2_0, x13
- isb
-
/* Restore FFR register before predicates */
mov x13, #CTX_SIMD_FFR
add x9, x0, x13
@@ -282,11 +257,6 @@
mov x13, #CTX_SIMD_VECTORS
add x9, x0, x13
sve_vectors_op ldr, x9
-
- /* Restore SVE enablement */
- msr S3_6_C1_C2_0, x12 /* zcr_el3 */
- msr cptr_el3, x10
- isb
.arch_extension nosve
/* Restore FPSR, FPCR and FPEXC32 */
@@ -598,10 +568,7 @@
/* ----------------------------------------------------------
* Restore CPTR_EL3.
- * ZCR is only restored if SVE is supported and enabled.
- * Synchronization is required before zcr_el3 is addressed.
- * ----------------------------------------------------------
- */
+ * ---------------------------------------------------------- */
/* The address of the per_world context is stored in x9 */
get_per_world_context x9
@@ -610,13 +577,6 @@
msr cptr_el3, x19
#if IMAGE_BL31
- ands x19, x19, #CPTR_EZ_BIT
- beq sve_not_enabled
-
- isb
- msr S3_6_C1_C2_0, x20 /* zcr_el3 */
-sve_not_enabled:
-
restore_mpam3_el3
#endif /* IMAGE_BL31 */
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index f396752..e28e1c3 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -191,6 +191,19 @@
}
write_ctx_reg(state, CTX_SCR_EL3, scr_el3);
+
+ if (is_feat_fgt2_supported()) {
+ fgt2_enable(ctx);
+ }
+
+ if (is_feat_debugv8p9_supported()) {
+ debugv8p9_extended_bp_wp_enable(ctx);
+ }
+
+ if (is_feat_brbe_supported()) {
+ brbe_enable(ctx);
+ }
+
}
#endif /* ENABLE_RME */
@@ -648,13 +661,17 @@
/*******************************************************************************
* Enable architecture extensions for EL3 execution. This function only updates
* registers in-place which are expected to either never change or be
- * overwritten by el3_exit.
+ * overwritten by el3_exit. Expects the core_pos of the current core as argument.
******************************************************************************/
#if IMAGE_BL31
-void cm_manage_extensions_el3(void)
+void cm_manage_extensions_el3(unsigned int my_idx)
{
+ if (is_feat_sve_supported()) {
+ sve_init_el3();
+ }
+
if (is_feat_amu_supported()) {
- amu_init_el3();
+ amu_init_el3(my_idx);
}
if (is_feat_sme_supported()) {
@@ -790,6 +807,7 @@
static void manage_extensions_nonsecure(cpu_context_t *ctx)
{
#if IMAGE_BL31
+ /* NOTE: registers are not context switched */
if (is_feat_amu_supported()) {
amu_enable(ctx);
}
@@ -1511,6 +1529,10 @@
write_el2_ctx_sxpoe(el2_sysregs_ctx, por_el2, read_por_el2());
}
+ if (is_feat_brbe_supported()) {
+ write_el2_ctx_brbe(el2_sysregs_ctx, brbcr_el2, read_brbcr_el2());
+ }
+
if (is_feat_s2pie_supported()) {
write_el2_ctx_s2pie(el2_sysregs_ctx, s2pir_el2, read_s2pir_el2());
}
@@ -1614,6 +1636,10 @@
if (is_feat_sctlr2_supported()) {
write_sctlr2_el2(read_el2_ctx_sctlr2(el2_sysregs_ctx, sctlr2_el2));
}
+
+ if (is_feat_brbe_supported()) {
+ write_brbcr_el2(read_el2_ctx_brbe(el2_sysregs_ctx, brbcr_el2));
+ }
}
#endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
diff --git a/lib/el3_runtime/aarch64/cpu_data.S b/lib/el3_runtime/aarch64/cpu_data.S
index 313f882..02d9415 100644
--- a/lib/el3_runtime/aarch64/cpu_data.S
+++ b/lib/el3_runtime/aarch64/cpu_data.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,29 +7,9 @@
#include <asm_macros.S>
#include <lib/el3_runtime/cpu_data.h>
-.globl init_cpu_data_ptr
.globl _cpu_data_by_index
/* -----------------------------------------------------------------
- * void init_cpu_data_ptr(void)
- *
- * Initialise the TPIDR_EL3 register to refer to the cpu_data_t
- * for the calling CPU. This must be called before cm_get_cpu_data()
- *
- * This can be called without a valid stack. It assumes that
- * plat_my_core_pos() does not clobber register x10.
- * clobbers: x0, x1, x10
- * -----------------------------------------------------------------
- */
-func init_cpu_data_ptr
- mov x10, x30
- bl plat_my_core_pos
- bl _cpu_data_by_index
- msr tpidr_el3, x0
- ret x10
-endfunc init_cpu_data_ptr
-
-/* -----------------------------------------------------------------
* cpu_data_t *_cpu_data_by_index(uint32_t cpu_index)
*
* Return the cpu_data structure for the CPU with given linear index
diff --git a/lib/extensions/amu/aarch32/amu.c b/lib/extensions/amu/aarch32/amu.c
index 351a552..6faef87 100644
--- a/lib/extensions/amu/aarch32/amu.c
+++ b/lib/extensions/amu/aarch32/amu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -8,7 +8,6 @@
#include <cdefs.h>
#include <stdbool.h>
-#include "../amu_private.h"
#include <arch.h>
#include <arch_features.h>
#include <arch_helpers.h>
@@ -18,51 +17,7 @@
#include <plat/common/platform.h>
-struct amu_ctx {
- uint64_t group0_cnts[AMU_GROUP0_MAX_COUNTERS];
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- uint64_t group1_cnts[AMU_GROUP1_MAX_COUNTERS];
-#endif
-
- uint16_t group0_enable;
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- uint16_t group1_enable;
-#endif
-};
-
-static struct amu_ctx amu_ctxs_[PLATFORM_CORE_COUNT];
-
-CASSERT((sizeof(amu_ctxs_[0].group0_enable) * CHAR_BIT) <= AMU_GROUP0_MAX_COUNTERS,
- amu_ctx_group0_enable_cannot_represent_all_group0_counters);
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-CASSERT((sizeof(amu_ctxs_[0].group1_enable) * CHAR_BIT) <= AMU_GROUP1_MAX_COUNTERS,
- amu_ctx_group1_enable_cannot_represent_all_group1_counters);
-#endif
-
-static inline __unused void write_hcptr_tam(uint32_t value)
-{
- write_hcptr((read_hcptr() & ~TAM_BIT) |
- ((value << TAM_SHIFT) & TAM_BIT));
-}
-
-static inline __unused void write_amcr_cg1rz(uint32_t value)
-{
- write_amcr((read_amcr() & ~AMCR_CG1RZ_BIT) |
- ((value << AMCR_CG1RZ_SHIFT) & AMCR_CG1RZ_BIT));
-}
-
-static inline __unused uint32_t read_amcfgr_ncg(void)
-{
- return (read_amcfgr() >> AMCFGR_NCG_SHIFT) &
- AMCFGR_NCG_MASK;
-}
-
-static inline __unused uint32_t read_amcgcr_cg0nc(void)
-{
- return (read_amcgcr() >> AMCGCR_CG0NC_SHIFT) &
- AMCGCR_CG0NC_MASK;
-}
+amu_regs_t amu_ctx[PLATFORM_CORE_COUNT];
static inline __unused uint32_t read_amcgcr_cg1nc(void)
{
@@ -70,134 +25,31 @@
AMCGCR_CG1NC_MASK;
}
-static inline __unused uint32_t read_amcntenset0_px(void)
-{
- return (read_amcntenset0() >> AMCNTENSET0_Pn_SHIFT) &
- AMCNTENSET0_Pn_MASK;
-}
-
-static inline __unused uint32_t read_amcntenset1_px(void)
-{
- return (read_amcntenset1() >> AMCNTENSET1_Pn_SHIFT) &
- AMCNTENSET1_Pn_MASK;
-}
-
-static inline __unused void write_amcntenset0_px(uint32_t px)
-{
- uint32_t value = read_amcntenset0();
-
- value &= ~AMCNTENSET0_Pn_MASK;
- value |= (px << AMCNTENSET0_Pn_SHIFT) &
- AMCNTENSET0_Pn_MASK;
-
- write_amcntenset0(value);
-}
-
-static inline __unused void write_amcntenset1_px(uint32_t px)
-{
- uint32_t value = read_amcntenset1();
-
- value &= ~AMCNTENSET1_Pn_MASK;
- value |= (px << AMCNTENSET1_Pn_SHIFT) &
- AMCNTENSET1_Pn_MASK;
-
- write_amcntenset1(value);
-}
-
-static inline __unused void write_amcntenclr0_px(uint32_t px)
-{
- uint32_t value = read_amcntenclr0();
-
- value &= ~AMCNTENCLR0_Pn_MASK;
- value |= (px << AMCNTENCLR0_Pn_SHIFT) & AMCNTENCLR0_Pn_MASK;
-
- write_amcntenclr0(value);
-}
-
-static inline __unused void write_amcntenclr1_px(uint32_t px)
-{
- uint32_t value = read_amcntenclr1();
-
- value &= ~AMCNTENCLR1_Pn_MASK;
- value |= (px << AMCNTENCLR1_Pn_SHIFT) & AMCNTENCLR1_Pn_MASK;
-
- write_amcntenclr1(value);
-}
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-static __unused bool amu_group1_supported(void)
-{
- return read_amcfgr_ncg() > 0U;
-}
-#endif
-
/*
* Enable counters. This function is meant to be invoked by the context
* management library before exiting from EL3.
*/
void amu_enable(bool el2_unused)
{
- uint32_t amcfgr_ncg; /* Number of counter groups */
- uint32_t amcgcr_cg0nc; /* Number of group 0 counters */
-
- uint32_t amcntenset0_px = 0x0; /* Group 0 enable mask */
- uint32_t amcntenset1_px = 0x0; /* Group 1 enable mask */
-
if (el2_unused) {
/*
* HCPTR.TAM: Set to zero so any accesses to the Activity
* Monitor registers do not trap to EL2.
*/
- write_hcptr_tam(0U);
+ write_hcptr(read_hcptr() & ~TAM_BIT);
}
- /*
- * Retrieve the number of architected counters. All of these counters
- * are enabled by default.
- */
-
- amcgcr_cg0nc = read_amcgcr_cg0nc();
- amcntenset0_px = (UINT32_C(1) << (amcgcr_cg0nc)) - 1U;
-
- assert(amcgcr_cg0nc <= AMU_AMCGCR_CG0NC_MAX);
-
- /*
- * The platform may opt to enable specific auxiliary counters. This can
- * be done via the common FCONF getter, or via the platform-implemented
- * function.
- */
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- const struct amu_topology *topology;
-
-#if ENABLE_AMU_FCONF
- topology = FCONF_GET_PROPERTY(amu, config, topology);
-#else
- topology = plat_amu_topology();
-#endif /* ENABLE_AMU_FCONF */
+ /* Architecture is currently pinned to 4 */
+ assert((read_amcgcr() & AMCGCR_CG0NC_MASK) == CTX_AMU_GRP0_ALL);
- if (topology != NULL) {
+ /* Enable all architected counters by default */
+ write_amcntenset0(AMCNTENSET0_Pn_MASK);
+ if (is_feat_amu_aux_supported()) {
unsigned int core_pos = plat_my_core_pos();
- amcntenset1_el0_px = topology->cores[core_pos].enable;
- } else {
- ERROR("AMU: failed to generate AMU topology\n");
- }
-#endif /* ENABLE_AMU_AUXILIARY_COUNTERS */
-
- /*
- * Enable the requested counters.
- */
-
- write_amcntenset0_px(amcntenset0_px);
-
- amcfgr_ncg = read_amcfgr_ncg();
- if (amcfgr_ncg > 0U) {
- write_amcntenset1_px(amcntenset1_px);
-
-#if !ENABLE_AMU_AUXILIARY_COUNTERS
- VERBOSE("AMU: auxiliary counters detected but support is disabled\n");
-#endif
+ /* Something went wrong if we're trying to write higher bits */
+ assert((get_amu_aux_enables(core_pos) & ~AMCNTENSET1_Pn_MASK) == 0);
+ write_amcntenset1(get_amu_aux_enables(core_pos));
}
/* Bail out if FEAT_AMUv1p1 features are not present. */
@@ -214,180 +66,177 @@
* mapped view are unaffected.
*/
VERBOSE("AMU group 1 counter access restricted.\n");
- write_amcr_cg1rz(1U);
+ write_amcr(read_amcr() | 1U);
#else
- write_amcr_cg1rz(0U);
+ write_amcr(0);
#endif
}
-/* Read the group 0 counter identified by the given `idx`. */
-static uint64_t amu_group0_cnt_read(unsigned int idx)
-{
- assert(is_feat_amu_supported());
- assert(idx < read_amcgcr_cg0nc());
-
- return amu_group0_cnt_read_internal(idx);
-}
-
-/* Write the group 0 counter identified by the given `idx` with `val` */
-static void amu_group0_cnt_write(unsigned int idx, uint64_t val)
-{
- assert(is_feat_amu_supported());
- assert(idx < read_amcgcr_cg0nc());
-
- amu_group0_cnt_write_internal(idx, val);
- isb();
-}
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-/* Read the group 1 counter identified by the given `idx` */
-static uint64_t amu_group1_cnt_read(unsigned int idx)
-{
- assert(is_feat_amu_supported());
- assert(amu_group1_supported());
- assert(idx < read_amcgcr_cg1nc());
-
- return amu_group1_cnt_read_internal(idx);
-}
-
-/* Write the group 1 counter identified by the given `idx` with `val` */
-static void amu_group1_cnt_write(unsigned int idx, uint64_t val)
-{
- assert(is_feat_amu_supported());
- assert(amu_group1_supported());
- assert(idx < read_amcgcr_cg1nc());
-
- amu_group1_cnt_write_internal(idx, val);
- isb();
-}
-#endif
-
static void *amu_context_save(const void *arg)
{
- uint32_t i;
-
- unsigned int core_pos;
- struct amu_ctx *ctx;
-
- uint32_t amcgcr_cg0nc; /* Number of group 0 counters */
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- uint32_t amcfgr_ncg; /* Number of counter groups */
- uint32_t amcgcr_cg1nc; /* Number of group 1 counters */
-#endif
-
if (!is_feat_amu_supported()) {
return (void *)0;
}
- core_pos = plat_my_core_pos();
- ctx = &amu_ctxs_[core_pos];
-
- amcgcr_cg0nc = read_amcgcr_cg0nc();
+ unsigned int core_pos = *(unsigned int *)arg;
+ amu_regs_t *ctx = &amu_ctx[core_pos];
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- amcfgr_ncg = read_amcfgr_ncg();
- amcgcr_cg1nc = (amcfgr_ncg > 0U) ? read_amcgcr_cg1nc() : 0U;
-#endif
-
- /*
- * Disable all AMU counters.
- */
-
- ctx->group0_enable = read_amcntenset0_px();
- write_amcntenclr0_px(ctx->group0_enable);
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- if (amcfgr_ncg > 0U) {
- ctx->group1_enable = read_amcntenset1_px();
- write_amcntenclr1_px(ctx->group1_enable);
+ /* Disable all counters so we can write to them safely later */
+ write_amcntenclr0(AMCNTENCLR0_Pn_MASK);
+ if (is_feat_amu_aux_supported()) {
+ write_amcntenclr1(get_amu_aux_enables(core_pos));
}
-#endif
-
- /*
- * Save the counters to the local context.
- */
isb(); /* Ensure counters have been stopped */
- for (i = 0U; i < amcgcr_cg0nc; i++) {
- ctx->group0_cnts[i] = amu_group0_cnt_read(i);
- }
+ write_amu_grp0_ctx_reg(ctx, 0, read64_amevcntr00());
+ write_amu_grp0_ctx_reg(ctx, 1, read64_amevcntr01());
+ write_amu_grp0_ctx_reg(ctx, 2, read64_amevcntr02());
+ write_amu_grp0_ctx_reg(ctx, 3, read64_amevcntr03());
+
+ if (is_feat_amu_aux_supported()) {
+ uint8_t num_counters = read_amcgcr_cg1nc();
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- for (i = 0U; i < amcgcr_cg1nc; i++) {
- ctx->group1_cnts[i] = amu_group1_cnt_read(i);
+ switch (num_counters) {
+ case 0x10:
+ write_amu_grp1_ctx_reg(ctx, 0xf, read64_amevcntr1f());
+ __fallthrough;
+ case 0x0f:
+ write_amu_grp1_ctx_reg(ctx, 0xe, read64_amevcntr1e());
+ __fallthrough;
+ case 0x0e:
+ write_amu_grp1_ctx_reg(ctx, 0xd, read64_amevcntr1d());
+ __fallthrough;
+ case 0x0d:
+ write_amu_grp1_ctx_reg(ctx, 0xc, read64_amevcntr1c());
+ __fallthrough;
+ case 0x0c:
+ write_amu_grp1_ctx_reg(ctx, 0xb, read64_amevcntr1b());
+ __fallthrough;
+ case 0x0b:
+ write_amu_grp1_ctx_reg(ctx, 0xa, read64_amevcntr1a());
+ __fallthrough;
+ case 0x0a:
+ write_amu_grp1_ctx_reg(ctx, 0x9, read64_amevcntr19());
+ __fallthrough;
+ case 0x09:
+ write_amu_grp1_ctx_reg(ctx, 0x8, read64_amevcntr18());
+ __fallthrough;
+ case 0x08:
+ write_amu_grp1_ctx_reg(ctx, 0x7, read64_amevcntr17());
+ __fallthrough;
+ case 0x07:
+ write_amu_grp1_ctx_reg(ctx, 0x6, read64_amevcntr16());
+ __fallthrough;
+ case 0x06:
+ write_amu_grp1_ctx_reg(ctx, 0x5, read64_amevcntr15());
+ __fallthrough;
+ case 0x05:
+ write_amu_grp1_ctx_reg(ctx, 0x4, read64_amevcntr14());
+ __fallthrough;
+ case 0x04:
+ write_amu_grp1_ctx_reg(ctx, 0x3, read64_amevcntr13());
+ __fallthrough;
+ case 0x03:
+ write_amu_grp1_ctx_reg(ctx, 0x2, read64_amevcntr12());
+ __fallthrough;
+ case 0x02:
+ write_amu_grp1_ctx_reg(ctx, 0x1, read64_amevcntr11());
+ __fallthrough;
+ case 0x01:
+ write_amu_grp1_ctx_reg(ctx, 0x0, read64_amevcntr10());
+ __fallthrough;
+ case 0x00:
+ break;
+ default:
+ assert(0); /* something is wrong */
+ }
}
-#endif
return (void *)0;
}
static void *amu_context_restore(const void *arg)
{
- uint32_t i;
-
- unsigned int core_pos;
- struct amu_ctx *ctx;
-
- uint32_t amcfgr_ncg; /* Number of counter groups */
- uint32_t amcgcr_cg0nc; /* Number of group 0 counters */
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- uint32_t amcgcr_cg1nc; /* Number of group 1 counters */
-#endif
-
if (!is_feat_amu_supported()) {
return (void *)0;
}
- core_pos = plat_my_core_pos();
- ctx = &amu_ctxs_[core_pos];
-
- amcfgr_ncg = read_amcfgr_ncg();
- amcgcr_cg0nc = read_amcgcr_cg0nc();
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- amcgcr_cg1nc = (amcfgr_ncg > 0U) ? read_amcgcr_cg1nc() : 0U;
-#endif
-
- /*
- * Sanity check that all counters were disabled when the context was
- * previously saved.
- */
+ unsigned int core_pos = *(unsigned int *)arg;
+ amu_regs_t *ctx = &amu_ctx[core_pos];
- assert(read_amcntenset0_px() == 0U);
-
- if (amcfgr_ncg > 0U) {
- assert(read_amcntenset1_px() == 0U);
- }
-
- /*
- * Restore the counter values from the local context.
- */
+ write64_amevcntr00(read_amu_grp0_ctx_reg(ctx, 0));
+ write64_amevcntr01(read_amu_grp0_ctx_reg(ctx, 1));
+ write64_amevcntr02(read_amu_grp0_ctx_reg(ctx, 2));
+ write64_amevcntr03(read_amu_grp0_ctx_reg(ctx, 3));
- for (i = 0U; i < amcgcr_cg0nc; i++) {
- amu_group0_cnt_write(i, ctx->group0_cnts[i]);
- }
+ if (is_feat_amu_aux_supported()) {
+ uint8_t num_counters = read_amcgcr_cg1nc();
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- for (i = 0U; i < amcgcr_cg1nc; i++) {
- amu_group1_cnt_write(i, ctx->group1_cnts[i]);
+ switch (num_counters) {
+ case 0x10:
+ write64_amevcntr1f(read_amu_grp1_ctx_reg(ctx, 0xf));
+ __fallthrough;
+ case 0x0f:
+ write64_amevcntr1e(read_amu_grp1_ctx_reg(ctx, 0xe));
+ __fallthrough;
+ case 0x0e:
+ write64_amevcntr1d(read_amu_grp1_ctx_reg(ctx, 0xd));
+ __fallthrough;
+ case 0x0d:
+ write64_amevcntr1c(read_amu_grp1_ctx_reg(ctx, 0xc));
+ __fallthrough;
+ case 0x0c:
+ write64_amevcntr1b(read_amu_grp1_ctx_reg(ctx, 0xb));
+ __fallthrough;
+ case 0x0b:
+ write64_amevcntr1a(read_amu_grp1_ctx_reg(ctx, 0xa));
+ __fallthrough;
+ case 0x0a:
+ write64_amevcntr19(read_amu_grp1_ctx_reg(ctx, 0x9));
+ __fallthrough;
+ case 0x09:
+ write64_amevcntr18(read_amu_grp1_ctx_reg(ctx, 0x8));
+ __fallthrough;
+ case 0x08:
+ write64_amevcntr17(read_amu_grp1_ctx_reg(ctx, 0x7));
+ __fallthrough;
+ case 0x07:
+ write64_amevcntr16(read_amu_grp1_ctx_reg(ctx, 0x6));
+ __fallthrough;
+ case 0x06:
+ write64_amevcntr15(read_amu_grp1_ctx_reg(ctx, 0x5));
+ __fallthrough;
+ case 0x05:
+ write64_amevcntr14(read_amu_grp1_ctx_reg(ctx, 0x4));
+ __fallthrough;
+ case 0x04:
+ write64_amevcntr13(read_amu_grp1_ctx_reg(ctx, 0x3));
+ __fallthrough;
+ case 0x03:
+ write64_amevcntr12(read_amu_grp1_ctx_reg(ctx, 0x2));
+ __fallthrough;
+ case 0x02:
+ write64_amevcntr11(read_amu_grp1_ctx_reg(ctx, 0x1));
+ __fallthrough;
+ case 0x01:
+ write64_amevcntr10(read_amu_grp1_ctx_reg(ctx, 0x0));
+ __fallthrough;
+ case 0x00:
+ break;
+ default:
+ assert(0); /* something is wrong */
+ }
}
-#endif
-
- /*
- * Re-enable counters that were disabled during context save.
- */
- write_amcntenset0_px(ctx->group0_enable);
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- if (amcfgr_ncg > 0U) {
- write_amcntenset1_px(ctx->group1_enable);
+ /* now enable them again */
+ write_amcntenset0(AMCNTENSET0_Pn_MASK);
+ if (is_feat_amu_aux_supported()) {
+ write_amcntenset1(get_amu_aux_enables(core_pos));
}
-#endif
+ isb();
return (void *)0;
}
diff --git a/lib/extensions/amu/aarch32/amu_helpers.S b/lib/extensions/amu/aarch32/amu_helpers.S
deleted file mode 100644
index 7090b2d..0000000
--- a/lib/extensions/amu/aarch32/amu_helpers.S
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <arch.h>
-#include <assert_macros.S>
-#include <asm_macros.S>
-
- .globl amu_group0_cnt_read_internal
- .globl amu_group0_cnt_write_internal
- .globl amu_group1_cnt_read_internal
- .globl amu_group1_cnt_write_internal
- .globl amu_group1_set_evtype_internal
-
-/*
- * uint64_t amu_group0_cnt_read_internal(int idx);
- *
- * Given `idx`, read the corresponding AMU counter
- * and return it in `r0` and `r1`.
- */
-func amu_group0_cnt_read_internal
-#if ENABLE_ASSERTIONS
- /* `idx` should be between [0, 3] */
- mov r1, r0
- lsr r1, r1, #2
- cmp r1, #0
- ASM_ASSERT(eq)
-#endif
-
- /*
- * Given `idx` calculate address of ldcopr16/bx lr instruction pair
- * in the table below.
- */
- adr r1, 1f
- lsl r0, r0, #3 /* each ldcopr16/bx lr sequence is 8 bytes */
- add r1, r1, r0
- bx r1
-1:
- ldcopr16 r0, r1, AMEVCNTR00 /* index 0 */
- bx lr
- ldcopr16 r0, r1, AMEVCNTR01 /* index 1 */
- bx lr
- ldcopr16 r0, r1, AMEVCNTR02 /* index 2 */
- bx lr
- ldcopr16 r0, r1, AMEVCNTR03 /* index 3 */
- bx lr
-endfunc amu_group0_cnt_read_internal
-
-/*
- * void amu_group0_cnt_write_internal(int idx, uint64_t val);
- *
- * Given `idx`, write `val` to the corresponding AMU counter.
- * `idx` is passed in `r0` and `val` is passed in `r2` and `r3`.
- * `r1` is used as a scratch register.
- */
-func amu_group0_cnt_write_internal
-#if ENABLE_ASSERTIONS
- /* `idx` should be between [0, 3] */
- mov r1, r0
- lsr r1, r1, #2
- cmp r1, #0
- ASM_ASSERT(eq)
-#endif
-
- /*
- * Given `idx` calculate address of stcopr16/bx lr instruction pair
- * in the table below.
- */
- adr r1, 1f
- lsl r0, r0, #3 /* each stcopr16/bx lr sequence is 8 bytes */
- add r1, r1, r0
- bx r1
-
-1:
- stcopr16 r2, r3, AMEVCNTR00 /* index 0 */
- bx lr
- stcopr16 r2, r3, AMEVCNTR01 /* index 1 */
- bx lr
- stcopr16 r2, r3, AMEVCNTR02 /* index 2 */
- bx lr
- stcopr16 r2, r3, AMEVCNTR03 /* index 3 */
- bx lr
-endfunc amu_group0_cnt_write_internal
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-/*
- * uint64_t amu_group1_cnt_read_internal(int idx);
- *
- * Given `idx`, read the corresponding AMU counter
- * and return it in `r0` and `r1`.
- */
-func amu_group1_cnt_read_internal
-#if ENABLE_ASSERTIONS
- /* `idx` should be between [0, 15] */
- mov r1, r0
- lsr r1, r1, #4
- cmp r1, #0
- ASM_ASSERT(eq)
-#endif
-
- /*
- * Given `idx` calculate address of ldcopr16/bx lr instruction pair
- * in the table below.
- */
- adr r1, 1f
- lsl r0, r0, #3 /* each ldcopr16/bx lr sequence is 8 bytes */
- add r1, r1, r0
- bx r1
-
-1:
- ldcopr16 r0, r1, AMEVCNTR10 /* index 0 */
- bx lr
- ldcopr16 r0, r1, AMEVCNTR11 /* index 1 */
- bx lr
- ldcopr16 r0, r1, AMEVCNTR12 /* index 2 */
- bx lr
- ldcopr16 r0, r1, AMEVCNTR13 /* index 3 */
- bx lr
- ldcopr16 r0, r1, AMEVCNTR14 /* index 4 */
- bx lr
- ldcopr16 r0, r1, AMEVCNTR15 /* index 5 */
- bx lr
- ldcopr16 r0, r1, AMEVCNTR16 /* index 6 */
- bx lr
- ldcopr16 r0, r1, AMEVCNTR17 /* index 7 */
- bx lr
- ldcopr16 r0, r1, AMEVCNTR18 /* index 8 */
- bx lr
- ldcopr16 r0, r1, AMEVCNTR19 /* index 9 */
- bx lr
- ldcopr16 r0, r1, AMEVCNTR1A /* index 10 */
- bx lr
- ldcopr16 r0, r1, AMEVCNTR1B /* index 11 */
- bx lr
- ldcopr16 r0, r1, AMEVCNTR1C /* index 12 */
- bx lr
- ldcopr16 r0, r1, AMEVCNTR1D /* index 13 */
- bx lr
- ldcopr16 r0, r1, AMEVCNTR1E /* index 14 */
- bx lr
- ldcopr16 r0, r1, AMEVCNTR1F /* index 15 */
- bx lr
-endfunc amu_group1_cnt_read_internal
-
-/*
- * void amu_group1_cnt_write_internal(int idx, uint64_t val);
- *
- * Given `idx`, write `val` to the corresponding AMU counter.
- * `idx` is passed in `r0` and `val` is passed in `r2` and `r3`.
- * `r1` is used as a scratch register.
- */
-func amu_group1_cnt_write_internal
-#if ENABLE_ASSERTIONS
- /* `idx` should be between [0, 15] */
- mov r1, r0
- lsr r1, r1, #4
- cmp r1, #0
- ASM_ASSERT(eq)
-#endif
-
- /*
- * Given `idx` calculate address of ldcopr16/bx lr instruction pair
- * in the table below.
- */
- adr r1, 1f
- lsl r0, r0, #3 /* each stcopr16/bx lr sequence is 8 bytes */
- add r1, r1, r0
- bx r1
-
-1:
- stcopr16 r2, r3, AMEVCNTR10 /* index 0 */
- bx lr
- stcopr16 r2, r3, AMEVCNTR11 /* index 1 */
- bx lr
- stcopr16 r2, r3, AMEVCNTR12 /* index 2 */
- bx lr
- stcopr16 r2, r3, AMEVCNTR13 /* index 3 */
- bx lr
- stcopr16 r2, r3, AMEVCNTR14 /* index 4 */
- bx lr
- stcopr16 r2, r3, AMEVCNTR15 /* index 5 */
- bx lr
- stcopr16 r2, r3, AMEVCNTR16 /* index 6 */
- bx lr
- stcopr16 r2, r3, AMEVCNTR17 /* index 7 */
- bx lr
- stcopr16 r2, r3, AMEVCNTR18 /* index 8 */
- bx lr
- stcopr16 r2, r3, AMEVCNTR19 /* index 9 */
- bx lr
- stcopr16 r2, r3, AMEVCNTR1A /* index 10 */
- bx lr
- stcopr16 r2, r3, AMEVCNTR1B /* index 11 */
- bx lr
- stcopr16 r2, r3, AMEVCNTR1C /* index 12 */
- bx lr
- stcopr16 r2, r3, AMEVCNTR1D /* index 13 */
- bx lr
- stcopr16 r2, r3, AMEVCNTR1E /* index 14 */
- bx lr
- stcopr16 r2, r3, AMEVCNTR1F /* index 15 */
- bx lr
-endfunc amu_group1_cnt_write_internal
-
-/*
- * void amu_group1_set_evtype_internal(int idx, unsigned int val);
- *
- * Program the AMU event type register indexed by `idx`
- * with the value `val`.
- */
-func amu_group1_set_evtype_internal
-#if ENABLE_ASSERTIONS
- /* `idx` should be between [0, 15] */
- mov r2, r0
- lsr r2, r2, #4
- cmp r2, #0
- ASM_ASSERT(eq)
-
- /* val should be between [0, 65535] */
- mov r2, r1
- lsr r2, r2, #16
- cmp r2, #0
- ASM_ASSERT(eq)
-#endif
-
- /*
- * Given `idx` calculate address of stcopr/bx lr instruction pair
- * in the table below.
- */
- adr r2, 1f
- lsl r0, r0, #3 /* each stcopr/bx lr sequence is 8 bytes */
- add r2, r2, r0
- bx r2
-
-1:
- stcopr r1, AMEVTYPER10 /* index 0 */
- bx lr
- stcopr r1, AMEVTYPER11 /* index 1 */
- bx lr
- stcopr r1, AMEVTYPER12 /* index 2 */
- bx lr
- stcopr r1, AMEVTYPER13 /* index 3 */
- bx lr
- stcopr r1, AMEVTYPER14 /* index 4 */
- bx lr
- stcopr r1, AMEVTYPER15 /* index 5 */
- bx lr
- stcopr r1, AMEVTYPER16 /* index 6 */
- bx lr
- stcopr r1, AMEVTYPER17 /* index 7 */
- bx lr
- stcopr r1, AMEVTYPER18 /* index 8 */
- bx lr
- stcopr r1, AMEVTYPER19 /* index 9 */
- bx lr
- stcopr r1, AMEVTYPER1A /* index 10 */
- bx lr
- stcopr r1, AMEVTYPER1B /* index 11 */
- bx lr
- stcopr r1, AMEVTYPER1C /* index 12 */
- bx lr
- stcopr r1, AMEVTYPER1D /* index 13 */
- bx lr
- stcopr r1, AMEVTYPER1E /* index 14 */
- bx lr
- stcopr r1, AMEVTYPER1F /* index 15 */
- bx lr
-endfunc amu_group1_set_evtype_internal
-#endif
diff --git a/lib/extensions/amu/aarch64/amu.c b/lib/extensions/amu/aarch64/amu.c
index cb9a0f2..5f23c07 100644
--- a/lib/extensions/amu/aarch64/amu.c
+++ b/lib/extensions/amu/aarch64/amu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -10,183 +10,37 @@
#include <stdbool.h>
#include <stdint.h>
-#include "../amu_private.h"
#include <arch.h>
#include <arch_features.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <lib/el3_runtime/pubsub_events.h>
#include <lib/extensions/amu.h>
+#include <lib/utils_def.h>
+#include <platform_def.h>
-#include <plat/common/platform.h>
+amu_regs_t amu_ctx[PLATFORM_CORE_COUNT];
-#if ENABLE_AMU_FCONF
-# include <lib/fconf/fconf.h>
-# include <lib/fconf/fconf_amu_getter.h>
-#endif
-
-#if ENABLE_MPMM
-# include <lib/mpmm/mpmm.h>
-#endif
-
-struct amu_ctx {
- uint64_t group0_cnts[AMU_GROUP0_MAX_COUNTERS];
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- uint64_t group1_cnts[AMU_GROUP1_MAX_COUNTERS];
-#endif
-
- /* Architected event counter 1 does not have an offset register */
- uint64_t group0_voffsets[AMU_GROUP0_MAX_COUNTERS - 1U];
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- uint64_t group1_voffsets[AMU_GROUP1_MAX_COUNTERS];
-#endif
-
- uint16_t group0_enable;
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- uint16_t group1_enable;
-#endif
-};
-
-static struct amu_ctx amu_ctxs_[PLATFORM_CORE_COUNT];
-
-CASSERT((sizeof(amu_ctxs_[0].group0_enable) * CHAR_BIT) <= AMU_GROUP0_MAX_COUNTERS,
- amu_ctx_group0_enable_cannot_represent_all_group0_counters);
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-CASSERT((sizeof(amu_ctxs_[0].group1_enable) * CHAR_BIT) <= AMU_GROUP1_MAX_COUNTERS,
- amu_ctx_group1_enable_cannot_represent_all_group1_counters);
-#endif
-
-static inline __unused uint64_t read_hcr_el2_amvoffen(void)
-{
- return (read_hcr_el2() & HCR_AMVOFFEN_BIT) >>
- HCR_AMVOFFEN_SHIFT;
-}
-
-static inline __unused void write_cptr_el2_tam(uint64_t value)
-{
- write_cptr_el2((read_cptr_el2() & ~CPTR_EL2_TAM_BIT) |
- ((value << CPTR_EL2_TAM_SHIFT) & CPTR_EL2_TAM_BIT));
-}
-
-static inline __unused void ctx_write_scr_el3_amvoffen(cpu_context_t *ctx, uint64_t amvoffen)
-{
- uint64_t value = read_ctx_reg(get_el3state_ctx(ctx), CTX_SCR_EL3);
-
- value &= ~SCR_AMVOFFEN_BIT;
- value |= (amvoffen << SCR_AMVOFFEN_SHIFT) & SCR_AMVOFFEN_BIT;
-
- write_ctx_reg(get_el3state_ctx(ctx), CTX_SCR_EL3, value);
-}
-
-static inline __unused void write_hcr_el2_amvoffen(uint64_t value)
-{
- write_hcr_el2((read_hcr_el2() & ~HCR_AMVOFFEN_BIT) |
- ((value << HCR_AMVOFFEN_SHIFT) & HCR_AMVOFFEN_BIT));
-}
-
-static inline __unused void write_amcr_el0_cg1rz(uint64_t value)
-{
- write_amcr_el0((read_amcr_el0() & ~AMCR_CG1RZ_BIT) |
- ((value << AMCR_CG1RZ_SHIFT) & AMCR_CG1RZ_BIT));
-}
-
-static inline __unused uint64_t read_amcfgr_el0_ncg(void)
-{
- return (read_amcfgr_el0() >> AMCFGR_EL0_NCG_SHIFT) &
- AMCFGR_EL0_NCG_MASK;
-}
-
-static inline __unused uint64_t read_amcgcr_el0_cg0nc(void)
-{
- return (read_amcgcr_el0() >> AMCGCR_EL0_CG0NC_SHIFT) &
- AMCGCR_EL0_CG0NC_MASK;
-}
-
-static inline __unused uint64_t read_amcg1idr_el0_voff(void)
-{
- return (read_amcg1idr_el0() >> AMCG1IDR_VOFF_SHIFT) &
- AMCG1IDR_VOFF_MASK;
-}
-
-static inline __unused uint64_t read_amcgcr_el0_cg1nc(void)
+static inline uint8_t read_amcgcr_el0_cg1nc(void)
{
return (read_amcgcr_el0() >> AMCGCR_EL0_CG1NC_SHIFT) &
AMCGCR_EL0_CG1NC_MASK;
}
-static inline __unused uint64_t read_amcntenset0_el0_px(void)
-{
- return (read_amcntenset0_el0() >> AMCNTENSET0_EL0_Pn_SHIFT) &
- AMCNTENSET0_EL0_Pn_MASK;
-}
-
-static inline __unused uint64_t read_amcntenset1_el0_px(void)
-{
- return (read_amcntenset1_el0() >> AMCNTENSET1_EL0_Pn_SHIFT) &
- AMCNTENSET1_EL0_Pn_MASK;
-}
-
-static inline __unused void write_amcntenset0_el0_px(uint64_t px)
-{
- uint64_t value = read_amcntenset0_el0();
-
- value &= ~AMCNTENSET0_EL0_Pn_MASK;
- value |= (px << AMCNTENSET0_EL0_Pn_SHIFT) & AMCNTENSET0_EL0_Pn_MASK;
-
- write_amcntenset0_el0(value);
-}
-
-static inline __unused void write_amcntenset1_el0_px(uint64_t px)
-{
- uint64_t value = read_amcntenset1_el0();
-
- value &= ~AMCNTENSET1_EL0_Pn_MASK;
- value |= (px << AMCNTENSET1_EL0_Pn_SHIFT) & AMCNTENSET1_EL0_Pn_MASK;
-
- write_amcntenset1_el0(value);
-}
-
-static inline __unused void write_amcntenclr0_el0_px(uint64_t px)
-{
- uint64_t value = read_amcntenclr0_el0();
-
- value &= ~AMCNTENCLR0_EL0_Pn_MASK;
- value |= (px << AMCNTENCLR0_EL0_Pn_SHIFT) & AMCNTENCLR0_EL0_Pn_MASK;
-
- write_amcntenclr0_el0(value);
-}
-
-static inline __unused void write_amcntenclr1_el0_px(uint64_t px)
-{
- uint64_t value = read_amcntenclr1_el0();
-
- value &= ~AMCNTENCLR1_EL0_Pn_MASK;
- value |= (px << AMCNTENCLR1_EL0_Pn_SHIFT) & AMCNTENCLR1_EL0_Pn_MASK;
-
- write_amcntenclr1_el0(value);
-}
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-static __unused bool amu_group1_supported(void)
-{
- return read_amcfgr_el0_ncg() > 0U;
-}
-#endif
-
-/*
- * Enable counters. This function is meant to be invoked by the context
- * management library before exiting from EL3.
- */
void amu_enable(cpu_context_t *ctx)
{
/* Initialize FEAT_AMUv1p1 features if present. */
if (is_feat_amuv1p1_supported()) {
+ el3_state_t *state = get_el3state_ctx(ctx);
+ u_register_t reg;
+
/*
* Set SCR_EL3.AMVOFFEN to one so that accesses to virtual
* offset registers at EL2 do not trap to EL3
*/
- ctx_write_scr_el3_amvoffen(ctx, 1U);
+ reg = read_ctx_reg(state, CTX_SCR_EL3);
+ reg |= SCR_AMVOFFEN_BIT;
+ write_ctx_reg(state, CTX_SCR_EL3, reg);
}
}
@@ -202,46 +56,18 @@
per_world_ctx->ctx_cptr_el3 = cptr_el3;
}
-void amu_init_el3(void)
+void amu_init_el3(unsigned int core_pos)
{
- uint64_t group0_impl_ctr = read_amcgcr_el0_cg0nc();
- uint64_t group0_en_mask = (1 << (group0_impl_ctr)) - 1U;
- uint64_t num_ctr_groups = read_amcfgr_el0_ncg();
+ /* architecture is currently pinned to 4 */
+ assert((read_amcgcr_el0() & AMCGCR_EL0_CG0NC_MASK) == CTX_AMU_GRP0_ALL);
/* Enable all architected counters by default */
- write_amcntenset0_el0_px(group0_en_mask);
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- if (num_ctr_groups > 0U) {
- uint64_t amcntenset1_el0_px = 0x0; /* Group 1 enable mask */
- const struct amu_topology *topology;
-
- /*
- * The platform may opt to enable specific auxiliary counters.
- * This can be done via the common FCONF getter, or via the
- * platform-implemented function.
- */
-#if ENABLE_AMU_FCONF
- topology = FCONF_GET_PROPERTY(amu, config, topology);
-#else
- topology = plat_amu_topology();
-#endif /* ENABLE_AMU_FCONF */
-
- if (topology != NULL) {
- unsigned int core_pos = plat_my_core_pos();
-
- amcntenset1_el0_px = topology->cores[core_pos].enable;
- } else {
- ERROR("AMU: failed to generate AMU topology\n");
- }
-
- write_amcntenset1_el0_px(amcntenset1_el0_px);
- }
-#else /* ENABLE_AMU_AUXILIARY_COUNTERS */
- if (num_ctr_groups > 0U) {
- VERBOSE("AMU: auxiliary counters detected but support is disabled\n");
+ write_amcntenset0_el0(AMCNTENSET0_EL0_Pn_MASK);
+ if (is_feat_amu_aux_supported()) {
+ /* something went wrong if we're trying to write higher bits */
+ assert((get_amu_aux_enables(core_pos) & ~AMCNTENSET1_EL0_Pn_MASK) == 0);
+ write_amcntenset1_el0(get_amu_aux_enables(core_pos));
}
-#endif /* ENABLE_AMU_AUXILIARY_COUNTERS */
if (is_feat_amuv1p1_supported()) {
#if AMU_RESTRICT_COUNTERS
@@ -253,15 +79,12 @@
* zero. Reads from the memory mapped view are unaffected.
*/
VERBOSE("AMU group 1 counter access restricted.\n");
- write_amcr_el0_cg1rz(1U);
+ write_amcr_el0(AMCR_CG1RZ_BIT);
#else
- write_amcr_el0_cg1rz(0U);
+ /* HDBG = 0 in both cases */
+ write_amcr_el0(0);
#endif
}
-
-#if ENABLE_MPMM
- mpmm_enable();
-#endif
}
void amu_init_el2_unused(void)
@@ -270,230 +93,93 @@
* CPTR_EL2.TAM: Set to zero so any accesses to the Activity Monitor
* registers do not trap to EL2.
*/
- write_cptr_el2_tam(0U);
+ write_cptr_el2(read_cptr_el2() & ~CPTR_EL2_TAM_BIT);
- /* Initialize FEAT_AMUv1p1 features if present. */
if (is_feat_amuv1p1_supported()) {
- /* Make sure virtual offsets are disabled if EL2 not used. */
- write_hcr_el2_amvoffen(0U);
+ /* Make sure virtual offsets are disabled */
+ write_hcr_el2(read_hcr_el2() & ~HCR_AMVOFFEN_BIT);
}
}
-/* Read the group 0 counter identified by the given `idx`. */
-static uint64_t amu_group0_cnt_read(unsigned int idx)
-{
- assert(is_feat_amu_supported());
- assert(idx < read_amcgcr_el0_cg0nc());
-
- return amu_group0_cnt_read_internal(idx);
-}
-
-/* Write the group 0 counter identified by the given `idx` with `val` */
-static void amu_group0_cnt_write(unsigned int idx, uint64_t val)
-{
- assert(is_feat_amu_supported());
- assert(idx < read_amcgcr_el0_cg0nc());
-
- amu_group0_cnt_write_internal(idx, val);
- isb();
-}
-
-/*
- * Unlike with auxiliary counters, we cannot detect at runtime whether an
- * architected counter supports a virtual offset. These are instead fixed
- * according to FEAT_AMUv1p1, but this switch will need to be updated if later
- * revisions of FEAT_AMU add additional architected counters.
- */
-static bool amu_group0_voffset_supported(uint64_t idx)
-{
- switch (idx) {
- case 0U:
- case 2U:
- case 3U:
- return true;
-
- case 1U:
- return false;
-
- default:
- ERROR("AMU: can't set up virtual offset for unknown "
- "architected counter %" PRIu64 "!\n", idx);
-
- panic();
- }
-}
-
-/*
- * Read the group 0 offset register for a given index. Index must be 0, 2,
- * or 3, the register for 1 does not exist.
- *
- * Using this function requires FEAT_AMUv1p1 support.
- */
-static uint64_t amu_group0_voffset_read(unsigned int idx)
-{
- assert(is_feat_amuv1p1_supported());
- assert(idx < read_amcgcr_el0_cg0nc());
- assert(idx != 1U);
-
- return amu_group0_voffset_read_internal(idx);
-}
-
-/*
- * Write the group 0 offset register for a given index. Index must be 0, 2, or
- * 3, the register for 1 does not exist.
- *
- * Using this function requires FEAT_AMUv1p1 support.
- */
-static void amu_group0_voffset_write(unsigned int idx, uint64_t val)
-{
- assert(is_feat_amuv1p1_supported());
- assert(idx < read_amcgcr_el0_cg0nc());
- assert(idx != 1U);
-
- amu_group0_voffset_write_internal(idx, val);
- isb();
-}
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-/* Read the group 1 counter identified by the given `idx` */
-static uint64_t amu_group1_cnt_read(unsigned int idx)
-{
- assert(is_feat_amu_supported());
- assert(amu_group1_supported());
- assert(idx < read_amcgcr_el0_cg1nc());
-
- return amu_group1_cnt_read_internal(idx);
-}
-
-/* Write the group 1 counter identified by the given `idx` with `val` */
-static void amu_group1_cnt_write(unsigned int idx, uint64_t val)
-{
- assert(is_feat_amu_supported());
- assert(amu_group1_supported());
- assert(idx < read_amcgcr_el0_cg1nc());
-
- amu_group1_cnt_write_internal(idx, val);
- isb();
-}
-
-/*
- * Read the group 1 offset register for a given index.
- *
- * Using this function requires FEAT_AMUv1p1 support.
- */
-static uint64_t amu_group1_voffset_read(unsigned int idx)
-{
- assert(is_feat_amuv1p1_supported());
- assert(amu_group1_supported());
- assert(idx < read_amcgcr_el0_cg1nc());
- assert((read_amcg1idr_el0_voff() & (UINT64_C(1) << idx)) != 0U);
-
- return amu_group1_voffset_read_internal(idx);
-}
-
-/*
- * Write the group 1 offset register for a given index.
- *
- * Using this function requires FEAT_AMUv1p1 support.
- */
-static void amu_group1_voffset_write(unsigned int idx, uint64_t val)
-{
- assert(is_feat_amuv1p1_supported());
- assert(amu_group1_supported());
- assert(idx < read_amcgcr_el0_cg1nc());
- assert((read_amcg1idr_el0_voff() & (UINT64_C(1) << idx)) != 0U);
-
- amu_group1_voffset_write_internal(idx, val);
- isb();
-}
-#endif
-
static void *amu_context_save(const void *arg)
{
- uint64_t i, j;
-
- unsigned int core_pos;
- struct amu_ctx *ctx;
-
- uint64_t hcr_el2_amvoffen = 0; /* AMU virtual offsets enabled */
- uint64_t amcgcr_el0_cg0nc; /* Number of group 0 counters */
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- uint64_t amcg1idr_el0_voff; /* Auxiliary counters with virtual offsets */
- uint64_t amcfgr_el0_ncg; /* Number of counter groups */
- uint64_t amcgcr_el0_cg1nc; /* Number of group 1 counters */
-#endif
-
if (!is_feat_amu_supported()) {
return (void *)0;
}
-
- core_pos = plat_my_core_pos();
- ctx = &amu_ctxs_[core_pos];
-
- amcgcr_el0_cg0nc = read_amcgcr_el0_cg0nc();
- if (is_feat_amuv1p1_supported()) {
- hcr_el2_amvoffen = read_hcr_el2_amvoffen();
- }
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- amcfgr_el0_ncg = read_amcfgr_el0_ncg();
- amcgcr_el0_cg1nc = (amcfgr_el0_ncg > 0U) ? read_amcgcr_el0_cg1nc() : 0U;
- amcg1idr_el0_voff = (hcr_el2_amvoffen != 0U) ? read_amcg1idr_el0_voff() : 0U;
-#endif
-
- /*
- * Disable all AMU counters.
- */
-
- ctx->group0_enable = read_amcntenset0_el0_px();
- write_amcntenclr0_el0_px(ctx->group0_enable);
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- if (amcfgr_el0_ncg > 0U) {
- ctx->group1_enable = read_amcntenset1_el0_px();
- write_amcntenclr1_el0_px(ctx->group1_enable);
- }
-#endif
- /*
- * Save the counters to the local context.
- */
+ unsigned int core_pos = *(unsigned int *)arg;
+ amu_regs_t *ctx = &amu_ctx[core_pos];
- isb(); /* Ensure counters have been stopped */
-
- for (i = 0U; i < amcgcr_el0_cg0nc; i++) {
- ctx->group0_cnts[i] = amu_group0_cnt_read(i);
- }
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- for (i = 0U; i < amcgcr_el0_cg1nc; i++) {
- ctx->group1_cnts[i] = amu_group1_cnt_read(i);
+ /* disable all counters so we can write them safely later */
+ write_amcntenclr0_el0(AMCNTENCLR0_EL0_Pn_MASK);
+ if (is_feat_amu_aux_supported()) {
+ write_amcntenclr1_el0(get_amu_aux_enables(core_pos));
}
-#endif
- /*
- * Save virtual offsets for counters that offer them.
- */
-
- if (hcr_el2_amvoffen != 0U) {
- for (i = 0U, j = 0U; i < amcgcr_el0_cg0nc; i++) {
- if (!amu_group0_voffset_supported(i)) {
- continue; /* No virtual offset */
- }
+ isb();
- ctx->group0_voffsets[j++] = amu_group0_voffset_read(i);
- }
+ write_amu_grp0_ctx_reg(ctx, 0, read_amevcntr00_el0());
+ write_amu_grp0_ctx_reg(ctx, 1, read_amevcntr01_el0());
+ write_amu_grp0_ctx_reg(ctx, 2, read_amevcntr02_el0());
+ write_amu_grp0_ctx_reg(ctx, 3, read_amevcntr03_el0());
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- for (i = 0U, j = 0U; i < amcgcr_el0_cg1nc; i++) {
- if ((amcg1idr_el0_voff >> i) & 1U) {
- continue; /* No virtual offset */
- }
+ if (is_feat_amu_aux_supported()) {
+ uint8_t num_counters = read_amcgcr_el0_cg1nc();
- ctx->group1_voffsets[j++] = amu_group1_voffset_read(i);
+ switch (num_counters) {
+ case 0x10:
+ write_amu_grp1_ctx_reg(ctx, 0xf, read_amevcntr1f_el0());
+ __fallthrough;
+ case 0x0f:
+ write_amu_grp1_ctx_reg(ctx, 0xe, read_amevcntr1e_el0());
+ __fallthrough;
+ case 0x0e:
+ write_amu_grp1_ctx_reg(ctx, 0xd, read_amevcntr1d_el0());
+ __fallthrough;
+ case 0x0d:
+ write_amu_grp1_ctx_reg(ctx, 0xc, read_amevcntr1c_el0());
+ __fallthrough;
+ case 0x0c:
+ write_amu_grp1_ctx_reg(ctx, 0xb, read_amevcntr1b_el0());
+ __fallthrough;
+ case 0x0b:
+ write_amu_grp1_ctx_reg(ctx, 0xa, read_amevcntr1a_el0());
+ __fallthrough;
+ case 0x0a:
+ write_amu_grp1_ctx_reg(ctx, 0x9, read_amevcntr19_el0());
+ __fallthrough;
+ case 0x09:
+ write_amu_grp1_ctx_reg(ctx, 0x8, read_amevcntr18_el0());
+ __fallthrough;
+ case 0x08:
+ write_amu_grp1_ctx_reg(ctx, 0x7, read_amevcntr17_el0());
+ __fallthrough;
+ case 0x07:
+ write_amu_grp1_ctx_reg(ctx, 0x6, read_amevcntr16_el0());
+ __fallthrough;
+ case 0x06:
+ write_amu_grp1_ctx_reg(ctx, 0x5, read_amevcntr15_el0());
+ __fallthrough;
+ case 0x05:
+ write_amu_grp1_ctx_reg(ctx, 0x4, read_amevcntr14_el0());
+ __fallthrough;
+ case 0x04:
+ write_amu_grp1_ctx_reg(ctx, 0x3, read_amevcntr13_el0());
+ __fallthrough;
+ case 0x03:
+ write_amu_grp1_ctx_reg(ctx, 0x2, read_amevcntr12_el0());
+ __fallthrough;
+ case 0x02:
+ write_amu_grp1_ctx_reg(ctx, 0x1, read_amevcntr11_el0());
+ __fallthrough;
+ case 0x01:
+ write_amu_grp1_ctx_reg(ctx, 0x0, read_amevcntr10_el0());
+ __fallthrough;
+ case 0x00:
+ break;
+ default:
+ assert(0); /* something is wrong */
}
-#endif
}
return (void *)0;
@@ -501,94 +187,85 @@
static void *amu_context_restore(const void *arg)
{
- uint64_t i, j;
-
- unsigned int core_pos;
- struct amu_ctx *ctx;
-
- uint64_t hcr_el2_amvoffen = 0; /* AMU virtual offsets enabled */
-
- uint64_t amcgcr_el0_cg0nc; /* Number of group 0 counters */
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- uint64_t amcfgr_el0_ncg; /* Number of counter groups */
- uint64_t amcgcr_el0_cg1nc; /* Number of group 1 counters */
- uint64_t amcg1idr_el0_voff; /* Auxiliary counters with virtual offsets */
-#endif
-
if (!is_feat_amu_supported()) {
return (void *)0;
}
- core_pos = plat_my_core_pos();
- ctx = &amu_ctxs_[core_pos];
-
- amcgcr_el0_cg0nc = read_amcgcr_el0_cg0nc();
-
- if (is_feat_amuv1p1_supported()) {
- hcr_el2_amvoffen = read_hcr_el2_amvoffen();
- }
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- amcfgr_el0_ncg = read_amcfgr_el0_ncg();
- amcgcr_el0_cg1nc = (amcfgr_el0_ncg > 0U) ? read_amcgcr_el0_cg1nc() : 0U;
- amcg1idr_el0_voff = (hcr_el2_amvoffen != 0U) ? read_amcg1idr_el0_voff() : 0U;
-#endif
+ unsigned int core_pos = *(unsigned int *)arg;
+ amu_regs_t *ctx = &amu_ctx[core_pos];
- /*
- * Restore the counter values from the local context.
- */
+ write_amevcntr00_el0(read_amu_grp0_ctx_reg(ctx, 0));
+ write_amevcntr01_el0(read_amu_grp0_ctx_reg(ctx, 1));
+ write_amevcntr02_el0(read_amu_grp0_ctx_reg(ctx, 2));
+ write_amevcntr03_el0(read_amu_grp0_ctx_reg(ctx, 3));
- for (i = 0U; i < amcgcr_el0_cg0nc; i++) {
- amu_group0_cnt_write(i, ctx->group0_cnts[i]);
- }
+ if (is_feat_amu_aux_supported()) {
+ uint8_t num_counters = read_amcgcr_el0_cg1nc();
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- for (i = 0U; i < amcgcr_el0_cg1nc; i++) {
- amu_group1_cnt_write(i, ctx->group1_cnts[i]);
- }
-#endif
-
- /*
- * Restore virtual offsets for counters that offer them.
- */
-
- if (hcr_el2_amvoffen != 0U) {
- for (i = 0U, j = 0U; i < amcgcr_el0_cg0nc; i++) {
- if (!amu_group0_voffset_supported(i)) {
- continue; /* No virtual offset */
- }
-
- amu_group0_voffset_write(i, ctx->group0_voffsets[j++]);
- }
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- for (i = 0U, j = 0U; i < amcgcr_el0_cg1nc; i++) {
- if ((amcg1idr_el0_voff >> i) & 1U) {
- continue; /* No virtual offset */
- }
-
- amu_group1_voffset_write(i, ctx->group1_voffsets[j++]);
+ switch (num_counters) {
+ case 0x10:
+ write_amevcntr1f_el0(read_amu_grp1_ctx_reg(ctx, 0xf));
+ __fallthrough;
+ case 0x0f:
+ write_amevcntr1e_el0(read_amu_grp1_ctx_reg(ctx, 0xe));
+ __fallthrough;
+ case 0x0e:
+ write_amevcntr1d_el0(read_amu_grp1_ctx_reg(ctx, 0xd));
+ __fallthrough;
+ case 0x0d:
+ write_amevcntr1c_el0(read_amu_grp1_ctx_reg(ctx, 0xc));
+ __fallthrough;
+ case 0x0c:
+ write_amevcntr1b_el0(read_amu_grp1_ctx_reg(ctx, 0xb));
+ __fallthrough;
+ case 0x0b:
+ write_amevcntr1a_el0(read_amu_grp1_ctx_reg(ctx, 0xa));
+ __fallthrough;
+ case 0x0a:
+ write_amevcntr19_el0(read_amu_grp1_ctx_reg(ctx, 0x9));
+ __fallthrough;
+ case 0x09:
+ write_amevcntr18_el0(read_amu_grp1_ctx_reg(ctx, 0x8));
+ __fallthrough;
+ case 0x08:
+ write_amevcntr17_el0(read_amu_grp1_ctx_reg(ctx, 0x7));
+ __fallthrough;
+ case 0x07:
+ write_amevcntr16_el0(read_amu_grp1_ctx_reg(ctx, 0x6));
+ __fallthrough;
+ case 0x06:
+ write_amevcntr15_el0(read_amu_grp1_ctx_reg(ctx, 0x5));
+ __fallthrough;
+ case 0x05:
+ write_amevcntr14_el0(read_amu_grp1_ctx_reg(ctx, 0x4));
+ __fallthrough;
+ case 0x04:
+ write_amevcntr13_el0(read_amu_grp1_ctx_reg(ctx, 0x3));
+ __fallthrough;
+ case 0x03:
+ write_amevcntr12_el0(read_amu_grp1_ctx_reg(ctx, 0x2));
+ __fallthrough;
+ case 0x02:
+ write_amevcntr11_el0(read_amu_grp1_ctx_reg(ctx, 0x1));
+ __fallthrough;
+ case 0x01:
+ write_amevcntr10_el0(read_amu_grp1_ctx_reg(ctx, 0x0));
+ __fallthrough;
+ case 0x00:
+ break;
+ default:
+ assert(0); /* something is wrong */
}
-#endif
}
- /*
- * Re-enable counters that were disabled during context save.
- */
-
- write_amcntenset0_el0_px(ctx->group0_enable);
-#if ENABLE_AMU_AUXILIARY_COUNTERS
- if (amcfgr_el0_ncg > 0) {
- write_amcntenset1_el0_px(ctx->group1_enable);
+ /* now enable them again */
+ write_amcntenset0_el0(AMCNTENSET0_EL0_Pn_MASK);
+ if (is_feat_amu_aux_supported()) {
+ write_amcntenset1_el0(get_amu_aux_enables(core_pos));
}
-#endif
-#if ENABLE_MPMM
- mpmm_enable();
-#endif
-
+ isb();
return (void *)0;
}
diff --git a/lib/extensions/amu/aarch64/amu_helpers.S b/lib/extensions/amu/aarch64/amu_helpers.S
deleted file mode 100644
index 95d4ad6..0000000
--- a/lib/extensions/amu/aarch64/amu_helpers.S
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <arch.h>
-#include <assert_macros.S>
-#include <asm_macros.S>
-
- .globl amu_group0_cnt_read_internal
- .globl amu_group0_cnt_write_internal
- .globl amu_group1_cnt_read_internal
- .globl amu_group1_cnt_write_internal
- .globl amu_group1_set_evtype_internal
-
- /* FEAT_AMUv1p1 virtualisation offset register functions */
- .globl amu_group0_voffset_read_internal
- .globl amu_group0_voffset_write_internal
- .globl amu_group1_voffset_read_internal
- .globl amu_group1_voffset_write_internal
-
-/*
- * uint64_t amu_group0_cnt_read_internal(int idx);
- *
- * Given `idx`, read the corresponding AMU counter
- * and return it in `x0`.
- */
-func amu_group0_cnt_read_internal
- adr x1, 1f
-#if ENABLE_ASSERTIONS
- /*
- * It can be dangerous to call this function with an
- * out of bounds index. Ensure `idx` is valid.
- */
- tst x0, #~3
- ASM_ASSERT(eq)
-#endif
- /*
- * Given `idx` calculate address of mrs/ret instruction pair
- * in the table below.
- */
- add x1, x1, x0, lsl #3 /* each mrs/ret sequence is 8 bytes */
-#if ENABLE_BTI
- add x1, x1, x0, lsl #2 /* + "bti j" instruction */
-#endif
- br x1
-
-1: read AMEVCNTR00_EL0 /* index 0 */
- read AMEVCNTR01_EL0 /* index 1 */
- read AMEVCNTR02_EL0 /* index 2 */
- read AMEVCNTR03_EL0 /* index 3 */
-endfunc amu_group0_cnt_read_internal
-
-/*
- * void amu_group0_cnt_write_internal(int idx, uint64_t val);
- *
- * Given `idx`, write `val` to the corresponding AMU counter.
- */
-func amu_group0_cnt_write_internal
- adr x2, 1f
-#if ENABLE_ASSERTIONS
- /*
- * It can be dangerous to call this function with an
- * out of bounds index. Ensure `idx` is valid.
- */
- tst x0, #~3
- ASM_ASSERT(eq)
-#endif
- /*
- * Given `idx` calculate address of mrs/ret instruction pair
- * in the table below.
- */
- add x2, x2, x0, lsl #3 /* each msr/ret sequence is 8 bytes */
-#if ENABLE_BTI
- add x2, x2, x0, lsl #2 /* + "bti j" instruction */
-#endif
- br x2
-
-1: write AMEVCNTR00_EL0 /* index 0 */
- write AMEVCNTR01_EL0 /* index 1 */
- write AMEVCNTR02_EL0 /* index 2 */
- write AMEVCNTR03_EL0 /* index 3 */
-endfunc amu_group0_cnt_write_internal
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-/*
- * uint64_t amu_group1_cnt_read_internal(int idx);
- *
- * Given `idx`, read the corresponding AMU counter
- * and return it in `x0`.
- */
-func amu_group1_cnt_read_internal
- adr x1, 1f
-#if ENABLE_ASSERTIONS
- /*
- * It can be dangerous to call this function with an
- * out of bounds index. Ensure `idx` is valid.
- */
- tst x0, #~0xF
- ASM_ASSERT(eq)
-#endif
- /*
- * Given `idx` calculate address of mrs/ret instruction pair
- * in the table below.
- */
- add x1, x1, x0, lsl #3 /* each mrs/ret sequence is 8 bytes */
-#if ENABLE_BTI
- add x1, x1, x0, lsl #2 /* + "bti j" instruction */
-#endif
- br x1
-
-1: read AMEVCNTR10_EL0 /* index 0 */
- read AMEVCNTR11_EL0 /* index 1 */
- read AMEVCNTR12_EL0 /* index 2 */
- read AMEVCNTR13_EL0 /* index 3 */
- read AMEVCNTR14_EL0 /* index 4 */
- read AMEVCNTR15_EL0 /* index 5 */
- read AMEVCNTR16_EL0 /* index 6 */
- read AMEVCNTR17_EL0 /* index 7 */
- read AMEVCNTR18_EL0 /* index 8 */
- read AMEVCNTR19_EL0 /* index 9 */
- read AMEVCNTR1A_EL0 /* index 10 */
- read AMEVCNTR1B_EL0 /* index 11 */
- read AMEVCNTR1C_EL0 /* index 12 */
- read AMEVCNTR1D_EL0 /* index 13 */
- read AMEVCNTR1E_EL0 /* index 14 */
- read AMEVCNTR1F_EL0 /* index 15 */
-endfunc amu_group1_cnt_read_internal
-
-/*
- * void amu_group1_cnt_write_internal(int idx, uint64_t val);
- *
- * Given `idx`, write `val` to the corresponding AMU counter.
- */
-func amu_group1_cnt_write_internal
- adr x2, 1f
-#if ENABLE_ASSERTIONS
- /*
- * It can be dangerous to call this function with an
- * out of bounds index. Ensure `idx` is valid.
- */
- tst x0, #~0xF
- ASM_ASSERT(eq)
-#endif
- /*
- * Given `idx` calculate address of mrs/ret instruction pair
- * in the table below.
- */
- add x2, x2, x0, lsl #3 /* each msr/ret sequence is 8 bytes */
-#if ENABLE_BTI
- add x2, x2, x0, lsl #2 /* + "bti j" instruction */
-#endif
- br x2
-
-1: write AMEVCNTR10_EL0 /* index 0 */
- write AMEVCNTR11_EL0 /* index 1 */
- write AMEVCNTR12_EL0 /* index 2 */
- write AMEVCNTR13_EL0 /* index 3 */
- write AMEVCNTR14_EL0 /* index 4 */
- write AMEVCNTR15_EL0 /* index 5 */
- write AMEVCNTR16_EL0 /* index 6 */
- write AMEVCNTR17_EL0 /* index 7 */
- write AMEVCNTR18_EL0 /* index 8 */
- write AMEVCNTR19_EL0 /* index 9 */
- write AMEVCNTR1A_EL0 /* index 10 */
- write AMEVCNTR1B_EL0 /* index 11 */
- write AMEVCNTR1C_EL0 /* index 12 */
- write AMEVCNTR1D_EL0 /* index 13 */
- write AMEVCNTR1E_EL0 /* index 14 */
- write AMEVCNTR1F_EL0 /* index 15 */
-endfunc amu_group1_cnt_write_internal
-
-/*
- * void amu_group1_set_evtype_internal(int idx, unsigned int val);
- *
- * Program the AMU event type register indexed by `idx`
- * with the value `val`.
- */
-func amu_group1_set_evtype_internal
- adr x2, 1f
-#if ENABLE_ASSERTIONS
- /*
- * It can be dangerous to call this function with an
- * out of bounds index. Ensure `idx` is valid.
- */
- tst x0, #~0xF
- ASM_ASSERT(eq)
-
- /* val should be between [0, 65535] */
- tst x1, #~0xFFFF
- ASM_ASSERT(eq)
-#endif
- /*
- * Given `idx` calculate address of msr/ret instruction pair
- * in the table below.
- */
- add x2, x2, x0, lsl #3 /* each msr/ret sequence is 8 bytes */
-#if ENABLE_BTI
- add x2, x2, x0, lsl #2 /* + "bti j" instruction */
-#endif
- br x2
-
-1: write AMEVTYPER10_EL0 /* index 0 */
- write AMEVTYPER11_EL0 /* index 1 */
- write AMEVTYPER12_EL0 /* index 2 */
- write AMEVTYPER13_EL0 /* index 3 */
- write AMEVTYPER14_EL0 /* index 4 */
- write AMEVTYPER15_EL0 /* index 5 */
- write AMEVTYPER16_EL0 /* index 6 */
- write AMEVTYPER17_EL0 /* index 7 */
- write AMEVTYPER18_EL0 /* index 8 */
- write AMEVTYPER19_EL0 /* index 9 */
- write AMEVTYPER1A_EL0 /* index 10 */
- write AMEVTYPER1B_EL0 /* index 11 */
- write AMEVTYPER1C_EL0 /* index 12 */
- write AMEVTYPER1D_EL0 /* index 13 */
- write AMEVTYPER1E_EL0 /* index 14 */
- write AMEVTYPER1F_EL0 /* index 15 */
-endfunc amu_group1_set_evtype_internal
-#endif
-
-/*
- * Accessor functions for virtual offset registers added with FEAT_AMUv1p1
- */
-
-/*
- * uint64_t amu_group0_voffset_read_internal(int idx);
- *
- * Given `idx`, read the corresponding AMU virtual offset register
- * and return it in `x0`.
- */
-func amu_group0_voffset_read_internal
- adr x1, 1f
-#if ENABLE_ASSERTIONS
- /*
- * It can be dangerous to call this function with an
- * out of bounds index. Ensure `idx` is valid.
- */
- tst x0, #~3
- ASM_ASSERT(eq)
- /* Make sure idx != 1 since AMEVCNTVOFF01_EL2 does not exist */
- cmp x0, #1
- ASM_ASSERT(ne)
-#endif
- /*
- * Given `idx` calculate address of mrs/ret instruction pair
- * in the table below.
- */
- add x1, x1, x0, lsl #3 /* each mrs/ret sequence is 8 bytes */
-#if ENABLE_BTI
- add x1, x1, x0, lsl #2 /* + "bti j" instruction */
-#endif
- br x1
-
-1: read AMEVCNTVOFF00_EL2 /* index 0 */
- .skip 8 /* AMEVCNTVOFF01_EL2 does not exist */
-#if ENABLE_BTI
- .skip 4
-#endif
- read AMEVCNTVOFF02_EL2 /* index 2 */
- read AMEVCNTVOFF03_EL2 /* index 3 */
-endfunc amu_group0_voffset_read_internal
-
-/*
- * void amu_group0_voffset_write_internal(int idx, uint64_t val);
- *
- * Given `idx`, write `val` to the corresponding AMU virtual offset register.
- */
-func amu_group0_voffset_write_internal
- adr x2, 1f
-#if ENABLE_ASSERTIONS
- /*
- * It can be dangerous to call this function with an
- * out of bounds index. Ensure `idx` is valid.
- */
- tst x0, #~3
- ASM_ASSERT(eq)
- /* Make sure idx != 1 since AMEVCNTVOFF01_EL2 does not exist */
- cmp x0, #1
- ASM_ASSERT(ne)
-#endif
- /*
- * Given `idx` calculate address of mrs/ret instruction pair
- * in the table below.
- */
- add x2, x2, x0, lsl #3 /* each msr/ret sequence is 8 bytes */
-#if ENABLE_BTI
- add x2, x2, x0, lsl #2 /* + "bti j" instruction */
-#endif
- br x2
-
-1: write AMEVCNTVOFF00_EL2 /* index 0 */
- .skip 8 /* AMEVCNTVOFF01_EL2 does not exist */
-#if ENABLE_BTI
- .skip 4
-#endif
- write AMEVCNTVOFF02_EL2 /* index 2 */
- write AMEVCNTVOFF03_EL2 /* index 3 */
-endfunc amu_group0_voffset_write_internal
-
-#if ENABLE_AMU_AUXILIARY_COUNTERS
-/*
- * uint64_t amu_group1_voffset_read_internal(int idx);
- *
- * Given `idx`, read the corresponding AMU virtual offset register
- * and return it in `x0`.
- */
-func amu_group1_voffset_read_internal
- adr x1, 1f
-#if ENABLE_ASSERTIONS
- /*
- * It can be dangerous to call this function with an
- * out of bounds index. Ensure `idx` is valid.
- */
- tst x0, #~0xF
- ASM_ASSERT(eq)
-#endif
- /*
- * Given `idx` calculate address of mrs/ret instruction pair
- * in the table below.
- */
- add x1, x1, x0, lsl #3 /* each mrs/ret sequence is 8 bytes */
-#if ENABLE_BTI
- add x1, x1, x0, lsl #2 /* + "bti j" instruction */
-#endif
- br x1
-
-1: read AMEVCNTVOFF10_EL2 /* index 0 */
- read AMEVCNTVOFF11_EL2 /* index 1 */
- read AMEVCNTVOFF12_EL2 /* index 2 */
- read AMEVCNTVOFF13_EL2 /* index 3 */
- read AMEVCNTVOFF14_EL2 /* index 4 */
- read AMEVCNTVOFF15_EL2 /* index 5 */
- read AMEVCNTVOFF16_EL2 /* index 6 */
- read AMEVCNTVOFF17_EL2 /* index 7 */
- read AMEVCNTVOFF18_EL2 /* index 8 */
- read AMEVCNTVOFF19_EL2 /* index 9 */
- read AMEVCNTVOFF1A_EL2 /* index 10 */
- read AMEVCNTVOFF1B_EL2 /* index 11 */
- read AMEVCNTVOFF1C_EL2 /* index 12 */
- read AMEVCNTVOFF1D_EL2 /* index 13 */
- read AMEVCNTVOFF1E_EL2 /* index 14 */
- read AMEVCNTVOFF1F_EL2 /* index 15 */
-endfunc amu_group1_voffset_read_internal
-
-/*
- * void amu_group1_voffset_write_internal(int idx, uint64_t val);
- *
- * Given `idx`, write `val` to the corresponding AMU virtual offset register.
- */
-func amu_group1_voffset_write_internal
- adr x2, 1f
-#if ENABLE_ASSERTIONS
- /*
- * It can be dangerous to call this function with an
- * out of bounds index. Ensure `idx` is valid.
- */
- tst x0, #~0xF
- ASM_ASSERT(eq)
-#endif
- /*
- * Given `idx` calculate address of mrs/ret instruction pair
- * in the table below.
- */
- add x2, x2, x0, lsl #3 /* each msr/ret sequence is 8 bytes */
-#if ENABLE_BTI
- add x2, x2, x0, lsl #2 /* + "bti j" instruction */
-#endif
- br x2
-
-1: write AMEVCNTVOFF10_EL2 /* index 0 */
- write AMEVCNTVOFF11_EL2 /* index 1 */
- write AMEVCNTVOFF12_EL2 /* index 2 */
- write AMEVCNTVOFF13_EL2 /* index 3 */
- write AMEVCNTVOFF14_EL2 /* index 4 */
- write AMEVCNTVOFF15_EL2 /* index 5 */
- write AMEVCNTVOFF16_EL2 /* index 6 */
- write AMEVCNTVOFF17_EL2 /* index 7 */
- write AMEVCNTVOFF18_EL2 /* index 8 */
- write AMEVCNTVOFF19_EL2 /* index 9 */
- write AMEVCNTVOFF1A_EL2 /* index 10 */
- write AMEVCNTVOFF1B_EL2 /* index 11 */
- write AMEVCNTVOFF1C_EL2 /* index 12 */
- write AMEVCNTVOFF1D_EL2 /* index 13 */
- write AMEVCNTVOFF1E_EL2 /* index 14 */
- write AMEVCNTVOFF1F_EL2 /* index 15 */
-endfunc amu_group1_voffset_write_internal
-#endif
diff --git a/lib/extensions/amu/amu.mk b/lib/extensions/amu/amu.mk
index 868ab12..fba2c78 100644
--- a/lib/extensions/amu/amu.mk
+++ b/lib/extensions/amu/amu.mk
@@ -1,24 +1,13 @@
#
-# Copyright (c) 2021, Arm Limited. All rights reserved.
+# Copyright (c) 2021-2025, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
-include lib/fconf/fconf.mk
-
-AMU_SOURCES := lib/extensions/amu/${ARCH}/amu.c \
- lib/extensions/amu/${ARCH}/amu_helpers.S
+AMU_SOURCES := lib/extensions/amu/${ARCH}/amu.c
ifneq (${ENABLE_AMU_AUXILIARY_COUNTERS},0)
ifeq (${ENABLE_FEAT_AMU},0)
- $(error AMU auxiliary counter support (`ENABLE_AMU_AUXILIARY_COUNTERS`) requires AMU support (`ENABLE_FEAT_AMU`))
- endif
-endif
-
-ifneq (${ENABLE_AMU_FCONF},0)
- ifeq (${ENABLE_AMU_AUXILIARY_COUNTERS},0)
- $(error AMU FCONF support (`ENABLE_AMU_FCONF`) is not necessary when auxiliary counter support (`ENABLE_AMU_AUXILIARY_COUNTERS`) is disabled)
+ $(error "ENABLE_AMU_AUXILIARY_COUNTERS requires ENABLE_FEAT_AMU")
endif
-
- AMU_SOURCES += ${FCONF_AMU_SOURCES}
endif
diff --git a/lib/extensions/amu/amu_private.h b/lib/extensions/amu/amu_private.h
deleted file mode 100644
index a3b6845..0000000
--- a/lib/extensions/amu/amu_private.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef AMU_PRIVATE_H
-#define AMU_PRIVATE_H
-
-#include <stdint.h>
-
-#include <lib/cassert.h>
-#include <lib/extensions/amu.h>
-#include <lib/utils_def.h>
-
-#include <platform_def.h>
-
-#define AMU_GROUP0_MAX_COUNTERS U(16)
-#define AMU_GROUP1_MAX_COUNTERS U(16)
-
-#define AMU_AMCGCR_CG0NC_MAX U(16)
-
-uint64_t amu_group0_cnt_read_internal(unsigned int idx);
-void amu_group0_cnt_write_internal(unsigned int idx, uint64_t val);
-
-uint64_t amu_group1_cnt_read_internal(unsigned int idx);
-void amu_group1_cnt_write_internal(unsigned int idx, uint64_t val);
-void amu_group1_set_evtype_internal(unsigned int idx, unsigned int val);
-
-#if __aarch64__
-uint64_t amu_group0_voffset_read_internal(unsigned int idx);
-void amu_group0_voffset_write_internal(unsigned int idx, uint64_t val);
-
-uint64_t amu_group1_voffset_read_internal(unsigned int idx);
-void amu_group1_voffset_write_internal(unsigned int idx, uint64_t val);
-#endif
-
-#endif /* AMU_PRIVATE_H */
diff --git a/lib/extensions/sme/sme.c b/lib/extensions/sme/sme.c
index 98d57e9..e477da3 100644
--- a/lib/extensions/sme/sme.c
+++ b/lib/extensions/sme/sme.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -40,13 +40,8 @@
void sme_init_el3(void)
{
- u_register_t cptr_el3 = read_cptr_el3();
u_register_t smcr_el3;
- /* Set CPTR_EL3.ESM bit so we can access SMCR_EL3 without trapping. */
- write_cptr_el3(cptr_el3 | ESM_BIT);
- isb();
-
/*
* Set the max LEN value and FA64 bit. This register is set up per_world
* to be the least restrictive, then lower ELs can restrict as needed
@@ -69,10 +64,6 @@
smcr_el3 |= SMCR_ELX_EZT0_BIT;
}
write_smcr_el3(smcr_el3);
-
- /* Reset CPTR_EL3 value. */
- write_cptr_el3(cptr_el3);
- isb();
}
void sme_init_el2_unused(void)
diff --git a/lib/extensions/sve/sve.c b/lib/extensions/sve/sve.c
index 143717e..4e18cdf 100644
--- a/lib/extensions/sve/sve.c
+++ b/lib/extensions/sve/sve.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -22,6 +22,12 @@
*/
#define CONVERT_SVE_LENGTH(x) (((x / 128) - 1))
+void sve_init_el3(void)
+{
+ /* Restrict maximum SVE vector length (SVE_VECTOR_LEN+1) * 128. */
+ write_zcr_el3(ZCR_EL3_LEN_MASK & CONVERT_SVE_LENGTH(SVE_VECTOR_LEN));
+}
+
void sve_enable_per_world(per_world_context_t *per_world_ctx)
{
u_register_t cptr_el3;
@@ -30,9 +36,6 @@
cptr_el3 = per_world_ctx->ctx_cptr_el3;
cptr_el3 = (cptr_el3 | CPTR_EZ_BIT) & ~(TFP_BIT);
per_world_ctx->ctx_cptr_el3 = cptr_el3;
-
- /* Restrict maximum SVE vector length (SVE_VECTOR_LEN+1) * 128. */
- per_world_ctx->ctx_zcr_el3 = (ZCR_EL3_LEN_MASK & CONVERT_SVE_LENGTH(SVE_VECTOR_LEN));
}
void sve_init_el2_unused(void)
diff --git a/lib/fconf/fconf.mk b/lib/fconf/fconf.mk
index ff781aa..d24f86b 100644
--- a/lib/fconf/fconf.mk
+++ b/lib/fconf/fconf.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2019-2021, Arm Limited. All rights reserved.
+# Copyright (c) 2019-2024, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -11,9 +11,3 @@
FCONF_DYN_SOURCES := lib/fconf/fconf_dyn_cfg_getter.c
FCONF_DYN_SOURCES += ${FDT_WRAPPERS_SOURCES}
-
-FCONF_AMU_SOURCES := lib/fconf/fconf_amu_getter.c
-FCONF_AMU_SOURCES += ${FDT_WRAPPERS_SOURCES}
-
-FCONF_MPMM_SOURCES := lib/fconf/fconf_mpmm_getter.c
-FCONF_MPMM_SOURCES += ${FDT_WRAPPERS_SOURCES}
diff --git a/lib/fconf/fconf_amu_getter.c b/lib/fconf/fconf_amu_getter.c
deleted file mode 100644
index eff309c..0000000
--- a/lib/fconf/fconf_amu_getter.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <common/debug.h>
-#include <common/fdt_wrappers.h>
-#include <lib/fconf/fconf.h>
-#include <lib/fconf/fconf_amu_getter.h>
-#include <libfdt.h>
-
-#include <plat/common/platform.h>
-
-struct fconf_amu_config fconf_amu_config;
-static struct amu_topology fconf_amu_topology_;
-
-/*
- * Populate the core-specific AMU structure with information retrieved from a
- * device tree.
- *
- * Returns `0` on success, or a negative integer representing an error code.
- */
-static int fconf_populate_amu_cpu_amu(const void *fdt, int parent,
- struct amu_core *amu)
-{
- int ret = 0;
- int node = 0;
-
- fdt_for_each_subnode(node, fdt, parent) {
- const char *name;
- const char *value;
- int len;
-
- uintptr_t idx = 0U;
-
- name = fdt_get_name(fdt, node, &len);
- if (strncmp(name, "counter@", 8) != 0) {
- continue;
- }
-
- ret = fdt_get_reg_props_by_index(fdt, node, 0, &idx, NULL);
- if (ret < 0) {
- break;
- }
-
- value = fdt_getprop(fdt, node, "enable-at-el3", &len);
- if ((value == NULL) && (len != -FDT_ERR_NOTFOUND)) {
- break;
- }
-
- if (len != -FDT_ERR_NOTFOUND) {
- amu->enable |= (1 << idx);
- }
- }
-
- if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) {
- return node;
- }
-
- return ret;
-}
-
-/*
- * Within a `cpu` node, attempt to dereference the `amu` property, and populate
- * the AMU information for the core.
- *
- * Returns `0` on success, or a negative integer representing an error code.
- */
-static int fconf_populate_amu_cpu(const void *fdt, int node, uintptr_t mpidr)
-{
- int ret;
- int idx;
-
- uint32_t amu_phandle;
- struct amu_core *amu;
-
- ret = fdt_read_uint32(fdt, node, "amu", &amu_phandle);
- if (ret < 0) {
- if (ret == -FDT_ERR_NOTFOUND) {
- ret = 0;
- }
-
- return ret;
- }
-
- node = fdt_node_offset_by_phandle(fdt, amu_phandle);
- if (node < 0) {
- return node;
- }
-
- idx = plat_core_pos_by_mpidr(mpidr);
- if (idx < 0) {
- return -FDT_ERR_BADVALUE;
- }
-
- amu = &fconf_amu_topology_.cores[idx];
-
- return fconf_populate_amu_cpu_amu(fdt, node, amu);
-}
-
-/*
- * Populates the global `amu_topology` structure based on what's described by
- * the hardware configuration device tree blob.
- *
- * The device tree is expected to provide an `amu` property for each `cpu` node,
- * like so:
- *
- * cpu@0 {
- * amu = <&cpu0_amu>;
- * };
- *
- * amus {
- * cpu0_amu: amu-0 {
- * counters {
- * #address-cells = <2>;
- * #size-cells = <0>;
- *
- * counter@x,y {
- * reg = <x y>; // Group x, counter y
- * };
- * };
- * };
- * };
- */
-static int fconf_populate_amu(uintptr_t config)
-{
- int ret = fdtw_for_each_cpu(
- (const void *)config, fconf_populate_amu_cpu);
- if (ret == 0) {
- fconf_amu_config.topology = &fconf_amu_topology_;
- } else {
- ERROR("FCONF: failed to parse AMU information: %d\n", ret);
- }
-
- return ret;
-}
-
-FCONF_REGISTER_POPULATOR(HW_CONFIG, amu, fconf_populate_amu);
diff --git a/lib/fconf/fconf_mpmm_getter.c b/lib/fconf/fconf_mpmm_getter.c
deleted file mode 100644
index 02a566d..0000000
--- a/lib/fconf/fconf_mpmm_getter.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <common/debug.h>
-#include <common/fdt_wrappers.h>
-#include <lib/fconf/fconf.h>
-#include <lib/fconf/fconf_mpmm_getter.h>
-#include <libfdt.h>
-
-#include <plat/common/platform.h>
-
-struct fconf_mpmm_config fconf_mpmm_config;
-static struct mpmm_topology fconf_mpmm_topology;
-
-/*
- * Within a `cpu` node, determine support for MPMM via the `supports-mpmm`
- * property.
- *
- * Returns `0` on success, or a negative integer representing an error code.
- */
-static int fconf_populate_mpmm_cpu(const void *fdt, int off, uintptr_t mpidr)
-{
- int ret, len;
-
- int core_pos;
- struct mpmm_core *core;
-
- core_pos = plat_core_pos_by_mpidr(mpidr);
- if (core_pos < 0) {
- return -FDT_ERR_BADVALUE;
- }
-
- core = &fconf_mpmm_topology.cores[core_pos];
-
- fdt_getprop(fdt, off, "supports-mpmm", &len);
- if (len >= 0) {
- core->supported = true;
- ret = 0;
- } else {
- core->supported = false;
- ret = len;
- }
-
- return ret;
-}
-
-/*
- * Populates the global `fconf_mpmm_config` structure based on what's described
- * by the hardware configuration device tree blob.
- *
- * The device tree is expected to provide a `supports-mpmm` property for each
- * `cpu` node, like so:
- *
- * cpu@0 {
- * supports-mpmm;
- * };
- *
- * This property indicates whether the core implements MPMM, as we cannot detect
- * support for it dynamically.
- */
-static int fconf_populate_mpmm(uintptr_t config)
-{
- int ret = fdtw_for_each_cpu(
- (const void *)config, fconf_populate_mpmm_cpu);
- if (ret == 0) {
- fconf_mpmm_config.topology = &fconf_mpmm_topology;
- } else {
- ERROR("FCONF: failed to configure MPMM: %d\n", ret);
- }
-
- return ret;
-}
-
-FCONF_REGISTER_POPULATOR(HW_CONFIG, mpmm, fconf_populate_mpmm);
diff --git a/lib/gpt_rme/gpt_rme.c b/lib/gpt_rme/gpt_rme.c
index 79c4ea5..115f50d 100644
--- a/lib/gpt_rme/gpt_rme.c
+++ b/lib/gpt_rme/gpt_rme.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,14 +12,13 @@
#include <arch.h>
#include <arch_features.h>
-#include <arch_helpers.h>
#include <common/debug.h>
-#include "gpt_rme_private.h"
#include <lib/gpt_rme/gpt_rme.h>
#include <lib/smccc.h>
-#include <lib/spinlock.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
+#include "gpt_rme_private.h"
+
#if !ENABLE_RME
#error "ENABLE_RME must be enabled to use the GPT library"
#endif
@@ -123,25 +122,19 @@
#define GPT_L1_INDEX(_pa) \
(((_pa) >> (unsigned int)GPT_L1_IDX_SHIFT(gpt_config.p)) & gpt_l1_index_mask)
-/* These variables are used during initialization of the L1 tables */
+/* This variable is used during initialization of the L1 tables */
static uintptr_t gpt_l1_tbl;
-/* These variable is used during runtime */
+/* These variables are used during runtime */
#if (RME_GPT_BITLOCK_BLOCK == 0)
/*
* The GPTs are protected by a global spinlock to ensure
* that multiple CPUs do not attempt to change the descriptors at once.
*/
static spinlock_t gpt_lock;
-#else
-/* Bitlocks base address */
-static bitlock_t *gpt_bitlock_base;
-#endif
-
-/* Lock/unlock macros for GPT entries */
-#if (RME_GPT_BITLOCK_BLOCK == 0)
-/*
+/* Lock/unlock macros for GPT entries
+ *
* Access to GPT is controlled by a global lock to ensure
* that no more than one CPU is allowed to make changes at any
* given time.
@@ -149,13 +142,17 @@
#define GPT_LOCK spin_lock(&gpt_lock)
#define GPT_UNLOCK spin_unlock(&gpt_lock)
#else
+
+/* Base address of bitlocks array */
+static bitlock_t *gpt_bitlock;
+
/*
* Access to a block of memory is controlled by a bitlock.
* Size of block = RME_GPT_BITLOCK_BLOCK * 512MB.
*/
#define GPT_LOCK bit_lock(gpi_info.lock, gpi_info.mask)
#define GPT_UNLOCK bit_unlock(gpi_info.lock, gpi_info.mask)
-#endif
+#endif /* RME_GPT_BITLOCK_BLOCK */
static void tlbi_page_dsbosh(uintptr_t base)
{
@@ -494,8 +491,8 @@
* This function validates L0 initialization parameters.
*
* Parameters
- * l0_mem_base Base address of memory used for L0 tables.
- * l0_mem_size Size of memory available for L0 tables.
+ * l0_mem_base Base address of memory used for L0 table.
+ * l0_mem_size Size of memory available for L0 table.
*
* Return
* Negative Linux error code in the event of a failure, 0 for success.
@@ -503,7 +500,7 @@
static int validate_l0_params(gpccr_pps_e pps, uintptr_t l0_mem_base,
size_t l0_mem_size)
{
- size_t l0_alignment, locks_size = 0;
+ size_t l0_alignment;
/*
* Make sure PPS is valid and then store it since macros need this value
@@ -516,8 +513,8 @@
gpt_config.pps = pps;
gpt_config.t = gpt_t_lookup[pps];
- /* Alignment must be the greater of 4KB or l0 table size */
- l0_alignment = PAGE_SIZE_4KB;
+ /* Alignment must be the greater of 4KB or L0 table size */
+ l0_alignment = SZ_4K;
if (l0_alignment < GPT_L0_TABLE_SIZE(gpt_config.t)) {
l0_alignment = GPT_L0_TABLE_SIZE(gpt_config.t);
}
@@ -529,28 +526,11 @@
return -EFAULT;
}
-#if (RME_GPT_BITLOCK_BLOCK != 0)
- /*
- * Size of bitlocks in bytes for the protected address space
- * with RME_GPT_BITLOCK_BLOCK * 512MB per bitlock.
- */
- locks_size = GPT_PPS_ACTUAL_SIZE(gpt_config.t) /
- (RME_GPT_BITLOCK_BLOCK * SZ_512M * 8U);
-
- /*
- * If protected space size is less than the size covered
- * by 'bitlock' structure, check for a single bitlock.
- */
- if (locks_size < LOCK_SIZE) {
- locks_size = LOCK_SIZE;
- }
-#endif
- /* Check size for L0 tables and bitlocks */
- if (l0_mem_size < (GPT_L0_TABLE_SIZE(gpt_config.t) + locks_size)) {
+ /* Check memory size for L0 table */
+ if (l0_mem_size < GPT_L0_TABLE_SIZE(gpt_config.t)) {
ERROR("GPT: Inadequate L0 memory\n");
- ERROR(" Expected 0x%lx bytes, got 0x%lx bytes\n",
- GPT_L0_TABLE_SIZE(gpt_config.t) + locks_size,
- l0_mem_size);
+ ERROR(" Expected 0x%lx bytes, got 0x%lx\n",
+ GPT_L0_TABLE_SIZE(gpt_config.t), l0_mem_size);
return -ENOMEM;
}
@@ -600,7 +580,7 @@
if (l1_mem_size < l1_gpt_mem_sz) {
ERROR("%sL1 GPTs%s", (const char *)"GPT: Inadequate ",
(const char *)" memory\n");
- ERROR(" Expected 0x%lx bytes, got 0x%lx bytes\n",
+ ERROR(" Expected 0x%lx bytes, got 0x%lx\n",
l1_gpt_mem_sz, l1_mem_size);
return -ENOMEM;
}
@@ -623,7 +603,7 @@
unsigned long idx, end_idx;
uint64_t *l0_gpt_arr;
- assert(gpt_config.plat_gpt_l0_base != 0U);
+ assert(gpt_config.plat_gpt_l0_base != 0UL);
assert(pas != NULL);
/*
@@ -928,7 +908,7 @@
uint64_t *l1_gpt_arr;
unsigned int l0_idx, gpi;
- assert(gpt_config.plat_gpt_l0_base != 0U);
+ assert(gpt_config.plat_gpt_l0_base != 0UL);
assert(pas != NULL);
/*
@@ -1121,12 +1101,10 @@
size_t l0_mem_size)
{
uint64_t gpt_desc;
- size_t locks_size = 0;
- __unused bitlock_t *bit_locks;
int ret;
/* Ensure that MMU and Data caches are enabled */
- assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
+ assert((read_sctlr_el3() & SCTLR_C_BIT) != 0UL);
/* Validate other parameters */
ret = validate_l0_params(pps, l0_mem_base, l0_mem_size);
@@ -1141,32 +1119,9 @@
for (unsigned int i = 0U; i < GPT_L0_REGION_COUNT(gpt_config.t); i++) {
((uint64_t *)l0_mem_base)[i] = gpt_desc;
}
-
-#if (RME_GPT_BITLOCK_BLOCK != 0)
- /* Initialise bitlocks at the end of L0 table */
- bit_locks = (bitlock_t *)(l0_mem_base +
- GPT_L0_TABLE_SIZE(gpt_config.t));
-
- /* Size of bitlocks in bytes */
- locks_size = GPT_PPS_ACTUAL_SIZE(gpt_config.t) /
- (RME_GPT_BITLOCK_BLOCK * SZ_512M * 8U);
-
- /*
- * If protected space size is less than the size covered
- * by 'bitlock' structure, initialise a single bitlock.
- */
- if (locks_size < LOCK_SIZE) {
- locks_size = LOCK_SIZE;
- }
-
- for (size_t i = 0UL; i < (locks_size/LOCK_SIZE); i++) {
- bit_locks[i].lock = 0U;
- }
-#endif
- /* Flush updated L0 tables and bitlocks to memory */
- flush_dcache_range((uintptr_t)l0_mem_base,
- GPT_L0_TABLE_SIZE(gpt_config.t) + locks_size);
+ /* Flush updated L0 table to memory */
+ flush_dcache_range((uintptr_t)l0_mem_base, GPT_L0_TABLE_SIZE(gpt_config.t));
/* Stash the L0 base address once initial setup is complete */
gpt_config.plat_gpt_l0_base = l0_mem_base;
@@ -1202,7 +1157,7 @@
int l1_gpt_cnt, ret;
/* Ensure that MMU and Data caches are enabled */
- assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
+ assert((read_sctlr_el3() & SCTLR_C_BIT) != 0UL);
/* PGS is needed for validate_pas_mappings so check it now */
if (pgs > GPT_PGS_MAX) {
@@ -1213,7 +1168,7 @@
gpt_config.p = gpt_p_lookup[pgs];
/* Make sure L0 tables have been initialized */
- if (gpt_config.plat_gpt_l0_base == 0U) {
+ if (gpt_config.plat_gpt_l0_base == 0UL) {
ERROR("GPT: L0 tables must be initialized first!\n");
return -EPERM;
}
@@ -1295,18 +1250,23 @@
* initialization from a previous stage. Granule protection checks must be
* enabled already or this function will return an error.
*
+ * Parameters
+ * l1_bitlocks_base Base address of memory for L1 tables bitlocks.
+ * l1_bitlocks_size Total size of memory available for L1 tables bitlocks.
+ *
* Return
* Negative Linux error code in the event of a failure, 0 for success.
*/
-int gpt_runtime_init(void)
+int gpt_runtime_init(uintptr_t l1_bitlocks_base, size_t l1_bitlocks_size)
{
u_register_t reg;
+ __unused size_t locks_size;
/* Ensure that MMU and Data caches are enabled */
- assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U);
+ assert((read_sctlr_el3() & SCTLR_C_BIT) != 0UL);
/* Ensure GPC are already enabled */
- if ((read_gpccr_el3() & GPCCR_GPC_BIT) == 0U) {
+ if ((read_gpccr_el3() & GPCCR_GPC_BIT) == 0UL) {
ERROR("GPT: Granule protection checks are not enabled!\n");
return -EPERM;
}
@@ -1334,17 +1294,43 @@
gpt_l1_index_mask = GPT_L1_IDX_MASK(gpt_config.p);
#if (RME_GPT_BITLOCK_BLOCK != 0)
- /* Bitlocks at the end of L0 table */
- gpt_bitlock_base = (bitlock_t *)(gpt_config.plat_gpt_l0_base +
- GPT_L0_TABLE_SIZE(gpt_config.t));
-#endif
+ /*
+ * Size of GPT bitlocks in bytes for the protected address space
+ * with RME_GPT_BITLOCK_BLOCK * 512MB per bitlock.
+ */
+ locks_size = GPT_PPS_ACTUAL_SIZE(gpt_config.t) /
+ (RME_GPT_BITLOCK_BLOCK * SZ_512M * 8U);
+ /*
+ * If protected space size is less than the size covered
+ * by 'bitlock' structure, check for a single bitlock.
+ */
+ if (locks_size < LOCK_SIZE) {
+ locks_size = LOCK_SIZE;
+ /* Check bitlocks array size */
+ } else if (locks_size > l1_bitlocks_size) {
+ ERROR("GPT: Inadequate GPT bitlocks memory\n");
+ ERROR(" Expected 0x%lx bytes, got 0x%lx\n",
+ locks_size, l1_bitlocks_size);
+ return -ENOMEM;
+ }
+
+ gpt_bitlock = (bitlock_t *)l1_bitlocks_base;
+
+ /* Initialise GPT bitlocks */
+ (void)memset((void *)gpt_bitlock, 0, locks_size);
+
+ /* Flush GPT bitlocks to memory */
+ flush_dcache_range((uintptr_t)gpt_bitlock, locks_size);
+#endif /* RME_GPT_BITLOCK_BLOCK */
+
VERBOSE("GPT: Runtime Configuration\n");
VERBOSE(" PPS/T: 0x%x/%u\n", gpt_config.pps, gpt_config.t);
VERBOSE(" PGS/P: 0x%x/%u\n", gpt_config.pgs, gpt_config.p);
VERBOSE(" L0GPTSZ/S: 0x%x/%u\n", GPT_L0GPTSZ, GPT_S_VAL);
VERBOSE(" L0 base: 0x%"PRIxPTR"\n", gpt_config.plat_gpt_l0_base);
#if (RME_GPT_BITLOCK_BLOCK != 0)
- VERBOSE(" Bitlocks: 0x%"PRIxPTR"\n", (uintptr_t)gpt_bitlock_base);
+ VERBOSE(" Bitlocks: 0x%"PRIxPTR"/0x%lx\n", (uintptr_t)gpt_bitlock,
+ locks_size);
#endif
return 0;
}
@@ -1391,7 +1377,7 @@
block_idx = (unsigned int)(base / (RME_GPT_BITLOCK_BLOCK * SZ_512M));
/* Bitlock address and mask */
- gpi_info->lock = &gpt_bitlock_base[block_idx / LOCK_BITS];
+ gpi_info->lock = &gpt_bitlock[block_idx / LOCK_BITS];
gpi_info->mask = 1U << (block_idx & (LOCK_BITS - 1U));
#endif
return 0;
diff --git a/lib/gpt_rme/gpt_rme.mk b/lib/gpt_rme/gpt_rme.mk
index 7d6b61f..6878489 100644
--- a/lib/gpt_rme/gpt_rme.mk
+++ b/lib/gpt_rme/gpt_rme.mk
@@ -1,19 +1,24 @@
#
-# Copyright (c) 2021-2024, Arm Limited. All rights reserved.
+# Copyright (c) 2021-2025, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
+# RME_GPT_BITLOCK_BLOCK is the number of 512MB blocks
+# per bit and the value must be power of 2.
+BITLOCK_BLOCK_POWER_2=$(shell echo $$(( ${RME_GPT_BITLOCK_BLOCK} & (${RME_GPT_BITLOCK_BLOCK} - 1) )))
+
# Process RME_GPT_BITLOCK_BLOCK value
-ifeq ($(filter 0 1 2 4 8 16 32 64 128 256 512, ${RME_GPT_BITLOCK_BLOCK}),)
- $(error "Invalid value for RME_GPT_BITLOCK_BLOCK: ${RME_GPT_BITLOCK_BLOCK}")
+ifneq (${BITLOCK_BLOCK_POWER_2}, 0)
+ $(error "RME_GPT_BITLOCK_BLOCK must be power of 2. Invalid value ${RME_GPT_BITLOCK_BLOCK}.")
endif
ifeq (${RME_GPT_BITLOCK_BLOCK},0)
- $(warning "GPT library uses global spinlock")
+ $(info "GPT library uses global spinlock")
endif
-# Process RME_GPT_MAX_BLOCK value
+# Process the maximum size of supported contiguous blocks
+# RME_GPT_MAX_BLOCK
ifeq ($(filter 0 2 32 512, ${RME_GPT_MAX_BLOCK}),)
$(error "Invalid value for RME_GPT_MAX_BLOCK: ${RME_GPT_MAX_BLOCK}")
endif
diff --git a/lib/gpt_rme/gpt_rme_private.h b/lib/gpt_rme/gpt_rme_private.h
index 31dad20..78d1cec 100644
--- a/lib/gpt_rme/gpt_rme_private.h
+++ b/lib/gpt_rme/gpt_rme_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,9 +7,7 @@
#ifndef GPT_RME_PRIVATE_H
#define GPT_RME_PRIVATE_H
-#include <arch.h>
#include <lib/gpt_rme/gpt_rme.h>
-#include <lib/spinlock.h>
#include <lib/utils_def.h>
/******************************************************************************/
@@ -141,10 +139,6 @@
PGS_64KB_P = 16U
} gpt_p_val_e;
-#define LOCK_SIZE sizeof(((bitlock_t *)NULL)->lock)
-#define LOCK_TYPE typeof(((bitlock_t *)NULL)->lock)
-#define LOCK_BITS (LOCK_SIZE * 8U)
-
/*
* Internal structure to retrieve the values from get_gpi_params();
*/
diff --git a/lib/libc/libc_common.mk b/lib/libc/libc_common.mk
index 4879818..5f44bd5 100644
--- a/lib/libc/libc_common.mk
+++ b/lib/libc/libc_common.mk
@@ -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
#
@@ -17,6 +17,7 @@
printf.c \
putchar.c \
puts.c \
+ qsort.c \
snprintf.c \
strchr.c \
strcmp.c \
diff --git a/lib/libc/qsort.c b/lib/libc/qsort.c
new file mode 100644
index 0000000..40569f4
--- /dev/null
+++ b/lib/libc/qsort.c
@@ -0,0 +1,261 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(I_AM_QSORT_R)
+typedef int cmp_t(const void *, const void *, void *);
+#elif defined(I_AM_QSORT_R_COMPAT)
+typedef int cmp_t(void *, const void *, const void *);
+#elif defined(I_AM_QSORT_S)
+typedef int cmp_t(const void *, const void *, void *);
+#else
+typedef int cmp_t(const void *, const void *);
+#endif
+static inline char *med3(char *, char *, char *, cmp_t *, void *);
+
+#define MIN(a, b) ((a) < (b) ? a : b)
+
+/*
+ * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
+ */
+
+static inline void
+swapfunc(char *a, char *b, size_t es)
+{
+ char t;
+
+ do {
+ t = *a;
+ *a++ = *b;
+ *b++ = t;
+ } while (--es > 0);
+}
+
+#define vecswap(a, b, n) \
+ if ((n) > 0) swapfunc(a, b, n)
+
+#if defined(I_AM_QSORT_R)
+#define CMP(t, x, y) (cmp((x), (y), (t)))
+#elif defined(I_AM_QSORT_R_COMPAT)
+#define CMP(t, x, y) (cmp((t), (x), (y)))
+#elif defined(I_AM_QSORT_S)
+#define CMP(t, x, y) (cmp((x), (y), (t)))
+#else
+#define CMP(t, x, y) (cmp((x), (y)))
+#endif
+
+static inline char *
+med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk
+#if !defined(I_AM_QSORT_R) && !defined(I_AM_QSORT_R_COMPAT) && !defined(I_AM_QSORT_S)
+__unused
+#endif
+)
+{
+ return CMP(thunk, a, b) < 0 ?
+ (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a ))
+ :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c ));
+}
+
+/*
+ * The actual qsort() implementation is static to avoid preemptible calls when
+ * recursing. Also give them different names for improved debugging.
+ */
+#if defined(I_AM_QSORT_R)
+#define local_qsort local_qsort_r
+#elif defined(I_AM_QSORT_R_COMPAT)
+#define local_qsort local_qsort_r_compat
+#elif defined(I_AM_QSORT_S)
+#define local_qsort local_qsort_s
+#endif
+static void
+local_qsort(void *a, size_t n, size_t es, cmp_t *cmp, void *thunk)
+{
+ char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
+ size_t d1, d2;
+ int cmp_result;
+ int swap_cnt;
+
+ /* if there are less than 2 elements, then sorting is not needed */
+ if (__predict_false(n < 2))
+ return;
+loop:
+ swap_cnt = 0;
+ if (n < 7) {
+ for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
+ for (pl = pm;
+ pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
+ pl -= es)
+ swapfunc(pl, pl - es, es);
+ return;
+ }
+ pm = (char *)a + (n / 2) * es;
+ if (n > 7) {
+ pl = a;
+ pn = (char *)a + (n - 1) * es;
+ if (n > 40) {
+ size_t d = (n / 8) * es;
+
+ pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
+ pm = med3(pm - d, pm, pm + d, cmp, thunk);
+ pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
+ }
+ pm = med3(pl, pm, pn, cmp, thunk);
+ }
+ swapfunc(a, pm, es);
+ pa = pb = (char *)a + es;
+
+ pc = pd = (char *)a + (n - 1) * es;
+ for (;;) {
+ while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) {
+ if (cmp_result == 0) {
+ swap_cnt = 1;
+ swapfunc(pa, pb, es);
+ pa += es;
+ }
+ pb += es;
+ }
+ while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) {
+ if (cmp_result == 0) {
+ swap_cnt = 1;
+ swapfunc(pc, pd, es);
+ pd -= es;
+ }
+ pc -= es;
+ }
+ if (pb > pc)
+ break;
+ swapfunc(pb, pc, es);
+ swap_cnt = 1;
+ pb += es;
+ pc -= es;
+ }
+ if (swap_cnt == 0) { /* Switch to insertion sort */
+ for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
+ for (pl = pm;
+ pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
+ pl -= es)
+ swapfunc(pl, pl - es, es);
+ return;
+ }
+
+ pn = (char *)a + n * es;
+ d1 = MIN(pa - (char *)a, pb - pa);
+ vecswap(a, pb - d1, d1);
+ /*
+ * Cast es to preserve signedness of right-hand side of MIN()
+ * expression, to avoid sign ambiguity in the implied comparison. es
+ * is safely within [0, SSIZE_MAX].
+ */
+ d1 = MIN(pd - pc, pn - pd - (ssize_t)es);
+ vecswap(pb, pn - d1, d1);
+
+ d1 = pb - pa;
+ d2 = pd - pc;
+ if (d1 <= d2) {
+ /* Recurse on left partition, then iterate on right partition */
+ if (d1 > es) {
+ local_qsort(a, d1 / es, es, cmp, thunk);
+ }
+ if (d2 > es) {
+ /* Iterate rather than recurse to save stack space */
+ /* qsort(pn - d2, d2 / es, es, cmp); */
+ a = pn - d2;
+ n = d2 / es;
+ goto loop;
+ }
+ } else {
+ /* Recurse on right partition, then iterate on left partition */
+ if (d2 > es) {
+ local_qsort(pn - d2, d2 / es, es, cmp, thunk);
+ }
+ if (d1 > es) {
+ /* Iterate rather than recurse to save stack space */
+ /* qsort(a, d1 / es, es, cmp); */
+ n = d1 / es;
+ goto loop;
+ }
+ }
+}
+
+#if defined(I_AM_QSORT_R)
+void
+(qsort_r)(void *a, size_t n, size_t es, cmp_t *cmp, void *thunk)
+{
+ local_qsort_r(a, n, es, cmp, thunk);
+}
+#elif defined(I_AM_QSORT_R_COMPAT)
+void
+__qsort_r_compat(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp)
+{
+ local_qsort_r_compat(a, n, es, cmp, thunk);
+}
+#elif defined(I_AM_QSORT_S)
+errno_t
+qsort_s(void *a, rsize_t n, rsize_t es, cmp_t *cmp, void *thunk)
+{
+ if (n > RSIZE_MAX) {
+ __throw_constraint_handler_s("qsort_s : n > RSIZE_MAX", EINVAL);
+ return (EINVAL);
+ } else if (es > RSIZE_MAX) {
+ __throw_constraint_handler_s("qsort_s : es > RSIZE_MAX",
+ EINVAL);
+ return (EINVAL);
+ } else if (n != 0) {
+ if (a == NULL) {
+ __throw_constraint_handler_s("qsort_s : a == NULL",
+ EINVAL);
+ return (EINVAL);
+ } else if (cmp == NULL) {
+ __throw_constraint_handler_s("qsort_s : cmp == NULL",
+ EINVAL);
+ return (EINVAL);
+ } else if (es <= 0) {
+ __throw_constraint_handler_s("qsort_s : es <= 0",
+ EINVAL);
+ return (EINVAL);
+ }
+ }
+
+ local_qsort_s(a, n, es, cmp, thunk);
+ return (0);
+}
+#else
+void
+qsort(void *a, size_t n, size_t es, cmp_t *cmp)
+{
+ local_qsort(a, n, es, cmp, NULL);
+}
+#endif
diff --git a/lib/mpmm/mpmm.c b/lib/mpmm/mpmm.c
deleted file mode 100644
index dc61cf6..0000000
--- a/lib/mpmm/mpmm.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <stdbool.h>
-
-#include <common/debug.h>
-#include <lib/mpmm/mpmm.h>
-
-#include <plat/common/platform.h>
-
-#if ENABLE_MPMM_FCONF
-# include <lib/fconf/fconf.h>
-# include <lib/fconf/fconf_mpmm_getter.h>
-#endif
-
-static uint64_t read_cpuppmcr_el3_mpmmpinctl(void)
-{
- return (read_cpuppmcr_el3() >> CPUPPMCR_EL3_MPMMPINCTL_SHIFT) &
- CPUPPMCR_EL3_MPMMPINCTL_MASK;
-}
-
-static void write_cpumpmmcr_el3_mpmm_en(uint64_t mpmm_en)
-{
- uint64_t value = read_cpumpmmcr_el3();
-
- value &= ~(CPUMPMMCR_EL3_MPMM_EN_MASK << CPUMPMMCR_EL3_MPMM_EN_SHIFT);
- value |= (mpmm_en & CPUMPMMCR_EL3_MPMM_EN_MASK) <<
- CPUMPMMCR_EL3_MPMM_EN_SHIFT;
-
- write_cpumpmmcr_el3(value);
-}
-
-static bool mpmm_supported(void)
-{
- bool supported = false;
- const struct mpmm_topology *topology;
-
-#if ENABLE_MPMM_FCONF
- topology = FCONF_GET_PROPERTY(mpmm, config, topology);
-#else
- topology = plat_mpmm_topology();
-#endif /* ENABLE_MPMM_FCONF */
-
- /*
- * For the current core firstly try to find out if the platform
- * configuration has claimed support for MPMM, then make sure that MPMM
- * is controllable through the system registers.
- */
-
- if (topology != NULL) {
- unsigned int core_pos = plat_my_core_pos();
-
- supported = topology->cores[core_pos].supported &&
- (read_cpuppmcr_el3_mpmmpinctl() == 0U);
- } else {
- ERROR("MPMM: failed to generate MPMM topology\n");
- }
-
- return supported;
-}
-
-/* Defaults to false */
-static bool mpmm_disable_for_errata;
-
-void mpmm_enable(void)
-{
- if (mpmm_supported()) {
- if (mpmm_disable_for_errata) {
- WARN("MPMM: disabled by errata workaround\n");
- return;
- }
- write_cpumpmmcr_el3_mpmm_en(1U);
- }
-}
-
-/*
- * This function is called from assembly code very early in BL31 so it must be
- * small and simple.
- */
-void mpmm_errata_disable(void)
-{
- mpmm_disable_for_errata = true;
-}
diff --git a/lib/mpmm/mpmm.mk b/lib/mpmm/mpmm.mk
deleted file mode 100644
index 826f925..0000000
--- a/lib/mpmm/mpmm.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Copyright (c) 2021, Arm Limited. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-include lib/extensions/amu/amu.mk
-include lib/fconf/fconf.mk
-
-ifneq (${ENABLE_MPMM},0)
- ifneq ($(ARCH),aarch64)
- $(error MPMM support (`ENABLE_MPMM`) can only be enabled in AArch64 images (`ARCH`))
- endif
-
- ifeq (${ENABLE_AMU_AUXILIARY_COUNTERS},0) # For MPMM gear AMU counters
- $(error MPMM support (`ENABLE_MPM`) requires auxiliary AMU counter support (`ENABLE_AMU_AUXILIARY_COUNTERS`))
- endif
-endif
-
-MPMM_SOURCES := lib/mpmm/mpmm.c
-MPMM_SOURCES += ${AMU_SOURCES}
-
-ifneq (${ENABLE_MPMM_FCONF},0)
- ifeq (${ENABLE_MPMM},0)
- $(error MPMM FCONF support (`ENABLE_MPMM_FCONF`) requires MPMM support (`ENABLE_MPMM`))
- endif
-
- MPMM_SOURCES += ${FCONF_MPMM_SOURCES}
-endif
diff --git a/lib/psci/aarch64/psci_helpers.S b/lib/psci/aarch64/psci_helpers.S
index cca08c1..b297f9b 100644
--- a/lib/psci/aarch64/psci_helpers.S
+++ b/lib/psci/aarch64/psci_helpers.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -118,17 +118,24 @@
endfunc psci_do_pwrup_cache_maintenance
/* -----------------------------------------------------------------------
- * void psci_power_down_wfi(void);
- * This function is called to indicate to the power controller that it
- * is safe to power down this cpu. It should not exit the wfi and will
- * be released from reset upon power up.
+ * void psci_power_down_wfi(void); This function is called to indicate to the
+ * power controller that it is safe to power down this cpu. It may exit if the
+ * request was denied and reset did not occur
* -----------------------------------------------------------------------
*/
func psci_power_down_wfi
apply_erratum cortex_a510, ERRATUM(2684597), ERRATA_A510_2684597
dsb sy // ensure write buffer empty
-1:
wfi
- b 1b
+
+ /*
+ * in case the WFI wasn't terminal, we have to undo errata mitigations.
+ * These will be smart enough to handle being called the same way
+ */
+ apply_erratum cortex_a710, ERRATUM(2291219), ERRATA_A710_2291219
+ apply_erratum cortex_x3, ERRATUM(2313909), ERRATA_X3_2313909, NO_GET_CPU_REV
+ apply_erratum neoverse_n2, ERRATUM(2326639), ERRATA_N2_2326639, NO_GET_CPU_REV
+
+ ret
endfunc psci_power_down_wfi
diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c
index 93d71b8..4c2601e 100644
--- a/lib/psci/psci_common.c
+++ b/lib/psci/psci_common.c
@@ -972,7 +972,7 @@
psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} };
/* Init registers that never change for the lifetime of TF-A */
- cm_manage_extensions_el3();
+ cm_manage_extensions_el3(cpu_idx);
/*
* Verify that we have been explicitly turned ON or resumed from
@@ -1019,8 +1019,12 @@
*/
if (psci_get_aff_info_state() == AFF_STATE_ON_PENDING)
psci_cpu_on_finish(cpu_idx, &state_info);
- else
- psci_cpu_suspend_to_powerdown_finish(cpu_idx, &state_info);
+ else {
+ unsigned int max_off_lvl = psci_find_max_off_lvl(&state_info);
+
+ assert(max_off_lvl != PSCI_INVALID_PWR_LVL);
+ psci_cpu_suspend_to_powerdown_finish(cpu_idx, max_off_lvl, &state_info);
+ }
/*
* Generic management: Now we just need to retrieve the
@@ -1156,7 +1160,7 @@
* Initiate power down sequence, by calling power down operations registered for
* this CPU.
******************************************************************************/
-void psci_pwrdown_cpu(unsigned int power_level)
+void psci_pwrdown_cpu_start(unsigned int power_level)
{
#if ENABLE_RUNTIME_INSTRUMENTATION
@@ -1197,6 +1201,72 @@
}
/*******************************************************************************
+ * Finish a terminal power down sequence, ending with a wfi. In case of wakeup
+ * will retry the sleep and panic if it persists.
+ ******************************************************************************/
+void __dead2 psci_pwrdown_cpu_end_terminal(void)
+{
+#if ERRATA_SME_POWER_DOWN
+ /*
+ * force SME off to not get power down rejected. Getting here is
+ * terminal so we don't care if we lose context because of another
+ * wakeup
+ */
+ if (is_feat_sme_supported()) {
+ write_svcr(0);
+ isb();
+ }
+#endif /* ERRATA_SME_POWER_DOWN */
+
+ /*
+ * Execute a wfi which, in most cases, will allow the power controller
+ * to physically power down this cpu. Under some circumstances that may
+ * be denied. Hopefully this is transient, retrying a few times should
+ * power down.
+ */
+ for (int i = 0; i < 32; i++)
+ psci_power_down_wfi();
+
+ /* Wake up wasn't transient. System is probably in a bad state. */
+ ERROR("Could not power off CPU.\n");
+ panic();
+}
+
+/*******************************************************************************
+ * Finish a non-terminal power down sequence, ending with a wfi. In case of
+ * wakeup will unwind any CPU specific actions and return.
+ ******************************************************************************/
+
+void psci_pwrdown_cpu_end_wakeup(unsigned int power_level)
+{
+ /*
+ * Usually, will be terminal. In some circumstances the powerdown will
+ * be denied and we'll need to unwind
+ */
+ psci_power_down_wfi();
+
+ /*
+ * Waking up does not require hardware-assisted coherency, but that is
+ * the case for every core that can wake up. Untangling the cache
+ * coherency code from powerdown is a non-trivial effort which isn't
+ * needed for our purposes.
+ */
+#if !FEAT_PABANDON
+ ERROR("Systems without FEAT_PABANDON shouldn't wake up.\n");
+ panic();
+#else /* FEAT_PABANDON */
+
+ /*
+ * Begin unwinding. Everything can be shared with CPU_ON and co later,
+ * except the CPU specific bit. Cores that have hardware-assisted
+ * coherency don't have much to do so just calling the hook again is
+ * the simplest way to achieve this
+ */
+ prepare_cpu_pwr_dwn(power_level);
+#endif /* FEAT_PABANDON */
+}
+
+/*******************************************************************************
* This function invokes the callback 'stop_func()' with the 'mpidr' of each
* online PE. Caller can pass suitable method to stop a remote core.
*
diff --git a/lib/psci/psci_main.c b/lib/psci/psci_main.c
index 7ac0e02..45be63a 100644
--- a/lib/psci/psci_main.c
+++ b/lib/psci/psci_main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -8,6 +8,7 @@
#include <string.h>
#include <arch.h>
+#include <arch_features.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <lib/pmf/pmf.h>
@@ -64,6 +65,19 @@
plat_local_state_t prev[PLAT_MAX_PWR_LVL];
#endif
+#if ERRATA_SME_POWER_DOWN
+ /*
+ * If SME isn't off, attempting a real power down will only end up being
+ * rejected. If we got called with SME on, fall back to a normal
+ * suspend. We can't force SME off as in the event the power down is
+ * rejected for another reason (eg GIC) we'd lose the SME context.
+ */
+ if (is_feat_sme_supported() && read_svcr() != 0) {
+ power_state &= ~(PSTATE_TYPE_MASK << PSTATE_TYPE_SHIFT);
+ power_state &= ~(PSTATE_PWR_LVL_MASK << PSTATE_PWR_LVL_SHIFT);
+ }
+#endif /* ERRATA_SME_POWER_DOWN */
+
/* Validate the power_state parameter */
rc = psci_validate_power_state(power_state, &state_info);
if (rc != PSCI_E_SUCCESS) {
diff --git a/lib/psci/psci_off.c b/lib/psci/psci_off.c
index d40ee3f..577fdd7 100644
--- a/lib/psci/psci_off.c
+++ b/lib/psci/psci_off.c
@@ -93,7 +93,7 @@
*/
if ((psci_spd_pm != NULL) && (psci_spd_pm->svc_off != NULL)) {
rc = psci_spd_pm->svc_off(0);
- if (rc != 0)
+ if (rc != PSCI_E_SUCCESS)
goto exit;
}
@@ -115,7 +115,7 @@
/*
* Arch. management. Initiate power down sequence.
*/
- psci_pwrdown_cpu(psci_find_max_off_lvl(&state_info));
+ psci_pwrdown_cpu_start(psci_find_max_off_lvl(&state_info));
/*
* Plat. management: Perform platform specific actions to turn this
@@ -153,7 +153,6 @@
psci_inv_cpu_data(psci_svc_cpu_data.aff_info_state);
#if ENABLE_RUNTIME_INSTRUMENTATION
-
/*
* Update the timestamp with cache off. We assume this
* timestamp can only be read from the current CPU and the
@@ -164,17 +163,12 @@
RT_INSTR_ENTER_HW_LOW_PWR,
PMF_NO_CACHE_MAINT);
#endif
-
- if (psci_plat_pm_ops->pwr_domain_pwr_down_wfi != NULL) {
- /* This function must not return */
- psci_plat_pm_ops->pwr_domain_pwr_down_wfi(&state_info);
- } else {
- /*
- * Enter a wfi loop which will allow the power
- * controller to physically power down this cpu.
- */
- psci_power_down_wfi();
+ if (psci_plat_pm_ops->pwr_domain_pwr_down != NULL) {
+ /* This function may not return */
+ psci_plat_pm_ops->pwr_domain_pwr_down(&state_info);
}
+
+ psci_pwrdown_cpu_end_terminal();
}
return rc;
diff --git a/lib/psci/psci_private.h b/lib/psci/psci_private.h
index 6622755..49b19c9 100644
--- a/lib/psci/psci_private.h
+++ b/lib/psci/psci_private.h
@@ -349,7 +349,7 @@
psci_power_state_t *state_info,
unsigned int is_power_down_state);
-void psci_cpu_suspend_to_powerdown_finish(unsigned int cpu_idx, const psci_power_state_t *state_info);
+void psci_cpu_suspend_to_powerdown_finish(unsigned int cpu_idx, unsigned int max_off_lvl, const psci_power_state_t *state_info);
/* Private exported functions from psci_helpers.S */
void psci_do_pwrdown_cache_maintenance(unsigned int pwr_level);
diff --git a/lib/psci/psci_suspend.c b/lib/psci/psci_suspend.c
index 2aadbfd..0fb1ed3 100644
--- a/lib/psci/psci_suspend.c
+++ b/lib/psci/psci_suspend.c
@@ -25,8 +25,7 @@
* This function does generic and platform specific operations after a wake-up
* from standby/retention states at multiple power levels.
******************************************************************************/
-static void psci_cpu_suspend_to_standby_finish(unsigned int cpu_idx,
- unsigned int end_pwrlvl,
+static void psci_cpu_suspend_to_standby_finish(unsigned int end_pwrlvl,
psci_power_state_t *state_info)
{
/*
@@ -43,13 +42,13 @@
* This function does generic and platform specific suspend to power down
* operations.
******************************************************************************/
-static void psci_suspend_to_pwrdown_start(unsigned int end_pwrlvl,
+static void psci_suspend_to_pwrdown_start(unsigned int idx,
+ unsigned int end_pwrlvl,
+ unsigned int max_off_lvl,
const entry_point_info_t *ep,
const psci_power_state_t *state_info)
{
- unsigned int max_off_lvl = psci_find_max_off_lvl(state_info);
-
- PUBLISH_EVENT(psci_suspend_pwrdown_start);
+ PUBLISH_EVENT_ARG(psci_suspend_pwrdown_start, &idx);
#if PSCI_OS_INIT_MODE
#ifdef PLAT_MAX_CPU_SUSPEND_PWR_LVL
@@ -94,10 +93,8 @@
/*
* Arch. management. Initiate power down sequence.
- * TODO : Introduce a mechanism to query the cache level to flush
- * and the cpu-ops power down to perform from the platform.
*/
- psci_pwrdown_cpu(max_off_lvl);
+ psci_pwrdown_cpu_start(max_off_lvl);
}
/*******************************************************************************
@@ -125,8 +122,12 @@
unsigned int is_power_down_state)
{
int rc = PSCI_E_SUCCESS;
- bool skip_wfi = false;
unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0};
+ unsigned int max_off_lvl = 0;
+#if FEAT_PABANDON
+ cpu_context_t *ctx = cm_get_context(NON_SECURE);
+ cpu_context_t old_ctx;
+#endif
/*
* This function must only be called on platforms where the
@@ -151,7 +152,6 @@
* detection that a wake-up interrupt has fired.
*/
if (read_isr_el1() != 0U) {
- skip_wfi = true;
goto exit;
}
@@ -163,7 +163,6 @@
*/
rc = psci_validate_state_coordination(idx, end_pwrlvl, state_info);
if (rc != PSCI_E_SUCCESS) {
- skip_wfi = true;
goto exit;
}
} else {
@@ -182,7 +181,6 @@
if (psci_plat_pm_ops->pwr_domain_validate_suspend != NULL) {
rc = psci_plat_pm_ops->pwr_domain_validate_suspend(state_info);
if (rc != PSCI_E_SUCCESS) {
- skip_wfi = true;
goto exit;
}
}
@@ -196,8 +194,38 @@
psci_stats_update_pwr_down(idx, end_pwrlvl, state_info);
#endif
- if (is_power_down_state != 0U)
- psci_suspend_to_pwrdown_start(end_pwrlvl, ep, state_info);
+ if (is_power_down_state != 0U) {
+ /*
+ * WHen CTX_INCLUDE_EL2_REGS is usnet, we're probably runnig
+ * with some SPD that assumes the core is going off so it
+ * doesn't bother saving NS's context. Do that here until we
+ * figure out a way to make this coherent.
+ */
+#if FEAT_PABANDON
+#if !CTX_INCLUDE_EL2_REGS
+ cm_el1_sysregs_context_save(NON_SECURE);
+#endif
+ /*
+ * when the core wakes it expects its context to already be in
+ * place so we must overwrite it before powerdown. But if
+ * powerdown never happens we want the old context. Save it in
+ * case we wake up. EL2/El1 will not be touched by PSCI so don't
+ * copy */
+ memcpy(&ctx->gpregs_ctx, &old_ctx.gpregs_ctx, sizeof(gp_regs_t));
+ memcpy(&ctx->el3state_ctx, &old_ctx.el3state_ctx, sizeof(el3_state_t));
+#if DYNAMIC_WORKAROUND_CVE_2018_3639
+ memcpy(&ctx->cve_2018_3639_ctx, &old_ctx.cve_2018_3639_ctx, sizeof(cve_2018_3639_t));
+#endif
+#if ERRATA_SPECULATIVE_AT
+ memcpy(&ctx->errata_speculative_at_ctx, &old_ctx.errata_speculative_at_ctx, sizeof(errata_speculative_at_t));
+#endif
+#if CTX_INCLUDE_PAUTH_REGS
+ memcpy(&ctx->pauth_ctx, &old_ctx.pauth_ctx, sizeof(pauth_t));
+#endif
+#endif
+ max_off_lvl = psci_find_max_off_lvl(state_info);
+ psci_suspend_to_pwrdown_start(idx, end_pwrlvl, end_pwrlvl, ep, state_info);
+ }
/*
* Plat. management: Allow the platform to perform the
@@ -212,50 +240,39 @@
plat_psci_stat_accounting_start(state_info);
#endif
-exit:
/*
* Release the locks corresponding to each power level in the
* reverse order to which they were acquired.
*/
psci_release_pwr_domain_locks(end_pwrlvl, parent_nodes);
- if (skip_wfi) {
- return rc;
- }
-
- if (is_power_down_state != 0U) {
#if ENABLE_RUNTIME_INSTRUMENTATION
-
- /*
- * Update the timestamp with cache off. We assume this
- * timestamp can only be read from the current CPU and the
- * timestamp cache line will be flushed before return to
- * normal world on wakeup.
- */
- PMF_CAPTURE_TIMESTAMP(rt_instr_svc,
- RT_INSTR_ENTER_HW_LOW_PWR,
- PMF_NO_CACHE_MAINT);
-#endif
-
- /* The function calls below must not return */
- if (psci_plat_pm_ops->pwr_domain_pwr_down_wfi != NULL)
- psci_plat_pm_ops->pwr_domain_pwr_down_wfi(state_info);
- else
- psci_power_down_wfi();
- }
-
-#if ENABLE_RUNTIME_INSTRUMENTATION
+ /*
+ * Update the timestamp with cache off. We assume this
+ * timestamp can only be read from the current CPU and the
+ * timestamp cache line will be flushed before return to
+ * normal world on wakeup.
+ */
PMF_CAPTURE_TIMESTAMP(rt_instr_svc,
RT_INSTR_ENTER_HW_LOW_PWR,
PMF_NO_CACHE_MAINT);
#endif
- /*
- * We will reach here if only retention/standby states have been
- * requested at multiple power levels. This means that the cpu
- * context will be preserved.
- */
- wfi();
+ if (is_power_down_state != 0U) {
+ if (psci_plat_pm_ops->pwr_domain_pwr_down != NULL) {
+ /* This function may not return */
+ psci_plat_pm_ops->pwr_domain_pwr_down(state_info);
+ }
+
+ psci_pwrdown_cpu_end_wakeup(max_off_lvl);
+ } else {
+ /*
+ * We will reach here if only retention/standby states have been
+ * requested at multiple power levels. This means that the cpu
+ * context will be preserved.
+ */
+ wfi();
+ }
#if ENABLE_RUNTIME_INSTRUMENTATION
PMF_CAPTURE_TIMESTAMP(rt_instr_svc,
@@ -277,10 +294,32 @@
#endif
/*
- * After we wake up from context retaining suspend, call the
- * context retaining suspend finisher.
+ * Waking up means we've retained all context. Call the finishers to put
+ * the system back to a usable state.
*/
- psci_cpu_suspend_to_standby_finish(idx, end_pwrlvl, state_info);
+ if (is_power_down_state != 0U) {
+#if FEAT_PABANDON
+ psci_cpu_suspend_to_powerdown_finish(idx, max_off_lvl, state_info);
+
+ /* we overwrote context ourselves, put it back */
+ memcpy(&ctx->gpregs_ctx, &old_ctx.gpregs_ctx, sizeof(gp_regs_t));
+ memcpy(&ctx->el3state_ctx, &old_ctx.el3state_ctx, sizeof(el3_state_t));
+#if DYNAMIC_WORKAROUND_CVE_2018_3639
+ memcpy(&ctx->cve_2018_3639_ctx, &old_ctx.cve_2018_3639_ctx, sizeof(cve_2018_3639_t));
+#endif
+#if ERRATA_SPECULATIVE_AT
+ memcpy(&ctx->errata_speculative_at_ctx, &old_ctx.errata_speculative_at_ctx, sizeof(errata_speculative_at_t));
+#endif
+#if CTX_INCLUDE_PAUTH_REGS
+ memcpy(&ctx->pauth_ctx, &old_ctx.pauth_ctx, sizeof(pauth_t));
+#endif
+#if !CTX_INCLUDE_EL2_REGS
+ cm_el1_sysregs_context_restore(NON_SECURE);
+#endif
+#endif
+ } else {
+ psci_cpu_suspend_to_standby_finish(end_pwrlvl, state_info);
+ }
/*
* Set the requested and target state of this CPU and all the higher
@@ -288,6 +327,7 @@
*/
psci_set_pwr_domains_to_run(idx, end_pwrlvl);
+exit:
psci_release_pwr_domain_locks(end_pwrlvl, parent_nodes);
return rc;
@@ -298,10 +338,9 @@
* are called by the common finisher routine in psci_common.c. The `state_info`
* is the psci_power_state from which this CPU has woken up from.
******************************************************************************/
-void psci_cpu_suspend_to_powerdown_finish(unsigned int cpu_idx, const psci_power_state_t *state_info)
+void psci_cpu_suspend_to_powerdown_finish(unsigned int cpu_idx, unsigned int max_off_lvl, const psci_power_state_t *state_info)
{
unsigned int counter_freq;
- unsigned int max_off_lvl;
/* Ensure we have been woken up from a suspended state */
assert((psci_get_aff_info_state() == AFF_STATE_ON) &&
@@ -338,13 +377,11 @@
* error, it's expected to assert within
*/
if ((psci_spd_pm != NULL) && (psci_spd_pm->svc_suspend_finish != NULL)) {
- max_off_lvl = psci_find_max_off_lvl(state_info);
- assert(max_off_lvl != PSCI_INVALID_PWR_LVL);
psci_spd_pm->svc_suspend_finish(max_off_lvl);
}
/* This loses its meaning when not suspending, reset so it's correct for OFF */
psci_set_suspend_pwrlvl(PLAT_MAX_PWR_LVL);
- PUBLISH_EVENT(psci_suspend_pwrdown_finish);
+ PUBLISH_EVENT_ARG(psci_suspend_pwrdown_finish, &cpu_idx);
}
diff --git a/lib/psci/psci_system_off.c b/lib/psci/psci_system_off.c
index 002392c..b9418a3 100644
--- a/lib/psci/psci_system_off.c
+++ b/lib/psci/psci_system_off.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -30,7 +30,7 @@
/* Call the platform specific hook */
psci_plat_pm_ops->system_off();
- /* This function does not return. We should never get here */
+ psci_pwrdown_cpu_end_terminal();
}
void __dead2 psci_system_reset(void)
@@ -49,7 +49,7 @@
/* Call the platform specific hook */
psci_plat_pm_ops->system_reset();
- /* This function does not return. We should never get here */
+ psci_pwrdown_cpu_end_terminal();
}
u_register_t psci_system_reset2(uint32_t reset_type, u_register_t cookie)
@@ -79,7 +79,10 @@
}
console_flush();
- return (u_register_t)
- psci_plat_pm_ops->system_reset2((int) is_vendor, reset_type,
- cookie);
+ u_register_t ret =
+ (u_register_t) psci_plat_pm_ops->system_reset2((int) is_vendor, reset_type, cookie);
+ if (ret != PSCI_E_SUCCESS)
+ return ret;
+
+ psci_pwrdown_cpu_end_terminal();
}
diff --git a/lib/romlib/Makefile b/lib/romlib/Makefile
index 01a0395..71f4273 100644
--- a/lib/romlib/Makefile
+++ b/lib/romlib/Makefile
@@ -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
#
@@ -23,7 +23,14 @@
# Determine if mbedtls is needed
ifneq ($(filter $(CRYPTO_SUPPORT),1 2 3),)
PROCESSED_JMPTBL = $(BUILD_DIR)/jmptbl_processed.i
- $(shell mkdir -p $(BUILD_DIR) && cat ../../$(PLAT_DIR)/jmptbl.i ../../$(PLAT_DIR)/jmptbl_mbedtls.i > $(BUILD_DIR)/jmptbl_processed.i)
+ CRYPTO_JMPTBL = ../../$(PLAT_DIR)/jmptbl.i ../../$(PLAT_DIR)/jmptbl_mbedtls.i
+
+ ifeq (${PSA_CRYPTO},1)
+ CRYPTO_JMPTBL += ../../$(PLAT_DIR)/jmptbl_mbedtls_psa.i
+ endif # ifeq (${PSA_CRYPTO},1)
+
+ $(shell mkdir -p $(BUILD_DIR) && cat $(CRYPTO_JMPTBL) > $(PROCESSED_JMPTBL))
+
LIBS += $(LIB_DIR)/libmbedtls.a
endif
diff --git a/lib/transfer_list/transfer_list.c b/lib/transfer_list/transfer_list.c
index 07614a6..3817861 100644
--- a/lib/transfer_list/transfer_list.c
+++ b/lib/transfer_list/transfer_list.c
@@ -35,7 +35,15 @@
if (!te) {
break;
}
+
INFO("Entry %d:\n", i++);
+ transfer_entry_dump(te);
+ }
+}
+
+void transfer_entry_dump(struct transfer_list_entry *te)
+{
+ if (te) {
INFO("tag_id 0x%x\n", te->tag_id);
INFO("hdr_size 0x%x\n", te->hdr_size);
INFO("data_size 0x%x\n", te->data_size);
diff --git a/lib/xlat_tables_v2/xlat_tables_core.c b/lib/xlat_tables_v2/xlat_tables_core.c
index 971dba4..bd7f017 100644
--- a/lib/xlat_tables_v2/xlat_tables_core.c
+++ b/lib/xlat_tables_v2/xlat_tables_core.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -15,6 +15,7 @@
#include <arch_features.h>
#include <arch_helpers.h>
#include <common/debug.h>
+#include <lib/utils.h>
#include <lib/utils_def.h>
#include <lib/xlat_tables/xlat_tables_defs.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
@@ -1204,16 +1205,13 @@
xlat_mmap_print(mm);
/* All tables must be zeroed before mapping any region. */
+ zeromem(ctx->base_table, ctx->base_table_entries * sizeof(uint64_t));
- for (unsigned int i = 0U; i < ctx->base_table_entries; i++)
- ctx->base_table[i] = INVALID_DESC;
-
- for (int j = 0; j < ctx->tables_num; j++) {
#if PLAT_XLAT_TABLES_DYNAMIC
- ctx->tables_mapped_regions[j] = 0;
+ zeromem(ctx->tables_mapped_regions, ctx->tables_num * sizeof(uint32_t));
#endif
- for (unsigned int i = 0U; i < XLAT_TABLE_ENTRIES; i++)
- ctx->tables[j][i] = INVALID_DESC;
+ for (int i = 0; i < ctx->tables_num; i++) {
+ zeromem(ctx->tables[i], XLAT_TABLE_ENTRIES * sizeof(uint64_t));
}
while (mm->size != 0U) {
diff --git a/make_helpers/arch_features.mk b/make_helpers/arch_features.mk
index 3c9e136..8dec522 100644
--- a/make_helpers/arch_features.mk
+++ b/make_helpers/arch_features.mk
@@ -291,7 +291,6 @@
# Feature flags for supporting Activity monitor extensions.
ENABLE_FEAT_AMU ?= 0
ENABLE_AMU_AUXILIARY_COUNTERS ?= 0
-ENABLE_AMU_FCONF ?= 0
AMU_RESTRICT_COUNTERS ?= 1
# Build option to enable MPAM for lower ELs.
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index b1b299c..aa16751 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -604,6 +604,7 @@
$(DOBJ): $(DPRE) $(filter-out %.d,$(MAKEFILE_LIST)) | $$$$(@D)/
$$(s)echo " DTC $$<"
$$(q)$($(ARCH)-dtc) $$(DTC_FLAGS) -d $(DTBDEP) -o $$@ $$<
+ $$($$@-after)
-include $(DTBDEP)
-include $(DTSDEP)
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index b1cfda2..ec2aa1b 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -85,8 +85,8 @@
# Enable the Maximum Power Mitigation Mechanism on supporting cores.
ENABLE_MPMM := 0
-# Enable MPMM configuration via FCONF.
-ENABLE_MPMM_FCONF := 0
+# Enable support for powerdown abandons
+FEAT_PABANDON := 0
# Flag to Enable Position Independant support (PIE)
ENABLE_PIE := 0
@@ -348,6 +348,9 @@
# Select workaround for AT speculative behaviour.
ERRATA_SPECULATIVE_AT := 0
+# select workaround for SME aborting powerdown
+ERRATA_SME_POWER_DOWN := 0
+
# Trap RAS error record access from Non secure
RAS_TRAP_NS_ERR_REC_ACCESS := 0
diff --git a/plat/allwinner/common/sunxi_native_pm.c b/plat/allwinner/common/sunxi_native_pm.c
index 148f50e..558b0bb 100644
--- a/plat/allwinner/common/sunxi_native_pm.c
+++ b/plat/allwinner/common/sunxi_native_pm.c
@@ -49,6 +49,8 @@
sunxi_cpu_power_off_others();
sunxi_cpu_power_off_self();
psci_power_down_wfi();
+ /* should never reach here */
+ panic();
}
static void __dead2 sunxi_system_reset(void)
diff --git a/plat/allwinner/common/sunxi_scpi_pm.c b/plat/allwinner/common/sunxi_scpi_pm.c
index 6a0e967..8870a71 100644
--- a/plat/allwinner/common/sunxi_scpi_pm.c
+++ b/plat/allwinner/common/sunxi_scpi_pm.c
@@ -108,6 +108,8 @@
}
psci_power_down_wfi();
+ /* should never reach here */
+ panic();
}
static void __dead2 sunxi_system_reset(void)
@@ -123,6 +125,8 @@
}
psci_power_down_wfi();
+ /* should never reach here */
+ panic();
}
static int sunxi_system_reset2(int is_vendor, int reset_type, u_register_t cookie)
@@ -142,6 +146,8 @@
}
psci_power_down_wfi();
+ /* should never reach here */
+ panic();
/*
* Should not reach here.
diff --git a/plat/xilinx/common/include/plat_xfer_list.h b/plat/amd/common/include/plat_xfer_list.h
similarity index 64%
rename from plat/xilinx/common/include/plat_xfer_list.h
rename to plat/amd/common/include/plat_xfer_list.h
index cc79a2c..24a9c0c 100644
--- a/plat/xilinx/common/include/plat_xfer_list.h
+++ b/plat/amd/common/include/plat_xfer_list.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023-2024, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2023-2025, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,4 +12,7 @@
int32_t transfer_list_populate_ep_info(entry_point_info_t *bl32,
entry_point_info_t *bl33);
+void *transfer_list_retrieve_dt_address(void);
+bool populate_data_from_xfer_list(void);
+
#endif /* PLAT_XFER_LIST_H */
diff --git a/plat/amd/common/plat_fdt.c b/plat/amd/common/plat_fdt.c
new file mode 100644
index 0000000..e72c0dd
--- /dev/null
+++ b/plat/amd/common/plat_fdt.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2025, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <common/debug.h>
+#include <common/fdt_fixup.h>
+#include <common/fdt_wrappers.h>
+#include <libfdt.h>
+#include <platform_def.h>
+
+#include <plat_fdt.h>
+#include <plat_xfer_list.h>
+
+#define FIT_CONFS_PATH "/configurations"
+
+static bool is_fit_image(void *dtb)
+{
+ int64_t confs_noffset = 0;
+ bool status = true;
+
+ confs_noffset = fdt_path_offset(dtb, FIT_CONFS_PATH);
+
+ /* confs_noffset is only present on FIT image */
+ if (confs_noffset < 0) {
+ status = false;
+ }
+
+ return status;
+}
+
+int32_t is_valid_dtb(void *fdt)
+{
+ int32_t ret = 0;
+
+ ret = fdt_check_header(fdt);
+ if (ret != 0) {
+ ERROR("Can't read DT at %p\n", fdt);
+ goto error;
+ }
+
+ ret = fdt_open_into(fdt, fdt, XILINX_OF_BOARD_DTB_MAX_SIZE);
+ if (ret < 0) {
+ ERROR("Invalid Device Tree at %p: error %d\n", fdt, ret);
+ goto error;
+ }
+
+ if (is_fit_image(fdt)) {
+ WARN("FIT image detected, TF-A will not update DTB for DDR address space\n");
+ ret = -FDT_ERR_NOTFOUND;
+ }
+error:
+ return ret;
+}
+
+/* TODO: Reserve TFA memory in DT through custom TL entry */
+void prepare_dtb(void)
+{
+
+}
+
+uintptr_t plat_retrieve_dt_addr(void)
+{
+ void *dtb = NULL;
+
+ dtb = transfer_list_retrieve_dt_address();
+ if (dtb == NULL) {
+ WARN("TL header or DT entry is invalid\n");
+ }
+
+ return (uintptr_t)dtb;
+}
diff --git a/plat/amd/common/plat_xfer_list.c b/plat/amd/common/plat_xfer_list.c
new file mode 100644
index 0000000..7af6726
--- /dev/null
+++ b/plat/amd/common/plat_xfer_list.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2023-2025, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <stddef.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/transfer_list.h>
+#include <platform_def.h>
+
+
+static struct transfer_list_header *tl_hdr;
+static int32_t tl_ops_holder;
+
+bool populate_data_from_xfer_list(void)
+{
+ bool ret = true;
+
+ tl_hdr = (struct transfer_list_header *)FW_HANDOFF_BASE;
+ tl_ops_holder = transfer_list_check_header(tl_hdr);
+
+ if ((tl_ops_holder != TL_OPS_ALL) && (tl_ops_holder != TL_OPS_RO)) {
+ ret = false;
+ }
+
+ return ret;
+}
+
+int32_t transfer_list_populate_ep_info(entry_point_info_t *bl32,
+ entry_point_info_t *bl33)
+{
+ int32_t ret = tl_ops_holder;
+ struct transfer_list_entry *te = NULL;
+ struct entry_point_info *ep = NULL;
+
+ if ((tl_ops_holder == TL_OPS_ALL) || (tl_ops_holder == TL_OPS_RO)) {
+ transfer_list_dump(tl_hdr);
+ while ((te = transfer_list_next(tl_hdr, te)) != NULL) {
+ ep = transfer_list_entry_data(te);
+ if (te->tag_id == TL_TAG_EXEC_EP_INFO64) {
+ switch (GET_SECURITY_STATE(ep->h.attr)) {
+ case NON_SECURE:
+ *bl33 = *ep;
+ continue;
+ case SECURE:
+ *bl32 = *ep;
+ if (!transfer_list_set_handoff_args(tl_hdr, ep)) {
+ ERROR("Invalid transfer list\n");
+ }
+ continue;
+ default:
+ ERROR("Unrecognized Image Security State %lu\n",
+ GET_SECURITY_STATE(ep->h.attr));
+ ret = TL_OPS_NON;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+void *transfer_list_retrieve_dt_address(void)
+{
+ void *dtb = NULL;
+ struct transfer_list_entry *te = NULL;
+
+ if ((tl_ops_holder == TL_OPS_ALL) || (tl_ops_holder == TL_OPS_RO)) {
+ te = transfer_list_find(tl_hdr, TL_TAG_FDT);
+ if (te != NULL) {
+ dtb = transfer_list_entry_data(te);
+ }
+ }
+
+ return dtb;
+}
diff --git a/plat/amd/versal2/bl31_setup.c b/plat/amd/versal2/bl31_setup.c
index 1914830..3a856cb 100644
--- a/plat/amd/versal2/bl31_setup.c
+++ b/plat/amd/versal2/bl31_setup.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-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
*/
@@ -59,9 +59,11 @@
bl32_image_ep_info.pc = BL32_BASE;
bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry();
#if defined(SPD_opteed)
+#if (TRANSFER_LIST == 0)
/* NS dtb addr passed to optee_os */
bl32_image_ep_info.args.arg3 = XILINX_OF_BOARD_DTB_ADDR;
#endif
+#endif
bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
bl33_image_ep_info.spsr = (uint32_t)SPSR_64(MODE_EL2, MODE_SP_ELX,
DISABLE_ALL_EXCEPTIONS);
@@ -81,7 +83,10 @@
(void)arg2;
(void)arg3;
uint32_t uart_clock;
+#if (TRANSFER_LIST == 1)
int32_t rc;
+ bool tl_status = false;
+#endif
board_detection();
@@ -124,6 +129,12 @@
default:
panic();
}
+#if (TRANSFER_LIST == 1)
+ tl_status = populate_data_from_xfer_list();
+ if (tl_status != true) {
+ WARN("Invalid transfer list\n");
+ }
+#endif
uart_clock = get_uart_clk();
@@ -152,11 +163,15 @@
SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+#if (TRANSFER_LIST == 1)
rc = transfer_list_populate_ep_info(&bl32_image_ep_info, &bl33_image_ep_info);
if (rc == TL_OPS_NON || rc == TL_OPS_CUS) {
NOTICE("BL31: TL not found, using default config\n");
bl31_set_default_config();
}
+#else
+ bl31_set_default_config();
+#endif
long rev_var = cpu_get_rev_var();
diff --git a/plat/amd/versal2/include/plat_pm_common.h b/plat/amd/versal2/include/plat_pm_common.h
index 5e68472..c325d74 100644
--- a/plat/amd/versal2/include/plat_pm_common.h
+++ b/plat/amd/versal2/include/plat_pm_common.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 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
*/
@@ -22,4 +22,17 @@
#define NON_SECURE_FLAG 1U
#define SECURE_FLAG 0U
+/* Processor core device IDs */
+#define PM_DEV_CLUSTER0_ACPU_0 (0x1810C0AFU)
+#define PM_DEV_CLUSTER0_ACPU_1 (0x1810C0B0U)
+
+#define PM_DEV_CLUSTER1_ACPU_0 (0x1810C0B3U)
+#define PM_DEV_CLUSTER1_ACPU_1 (0x1810C0B4U)
+
+#define PM_DEV_CLUSTER2_ACPU_0 (0x1810C0B7U)
+#define PM_DEV_CLUSTER2_ACPU_1 (0x1810C0B8U)
+
+#define PM_DEV_CLUSTER3_ACPU_0 (0x1810C0BBU)
+#define PM_DEV_CLUSTER3_ACPU_1 (0x1810C0BCU)
+
#endif /* PLAT_PM_COMMON_H */
diff --git a/plat/amd/versal2/include/plat_private.h b/plat/amd/versal2/include/plat_private.h
index 4be2061..98f7e08 100644
--- a/plat/amd/versal2/include/plat_private.h
+++ b/plat/amd/versal2/include/plat_private.h
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2019, 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
*/
@@ -45,7 +45,7 @@
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,
- uint64_t x4, void *cookie, void *handle, uint64_t flags);
+ uint64_t x4, const void *cookie, void *handle, uint64_t flags);
int32_t sip_svc_setup_init(void);
/*
* Register handler to specific GIC entrance
diff --git a/plat/amd/versal2/include/platform_def.h b/plat/amd/versal2/include/platform_def.h
index 8f694f7..2b65363 100644
--- a/plat/amd/versal2/include/platform_def.h
+++ b/plat/amd/versal2/include/platform_def.h
@@ -11,6 +11,7 @@
#include <arch.h>
#include "def.h"
+#include <plat_common.h>
/*******************************************************************************
* Generic platform constants
@@ -122,6 +123,8 @@
#define PLAT_GICD_BASE_VALUE U(0xE2000000)
#define PLAT_GICR_BASE_VALUE U(0xE2060000)
+#define PLAT_ARM_GICR_BASE PLAT_GICR_BASE_VALUE
+#define PLAT_ARM_GICD_BASE PLAT_GICD_BASE_VALUE
/*
* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
@@ -138,6 +141,8 @@
#define PLAT_G0_IRQ_PROPS(grp) \
INTR_PROP_DESC(PLAT_VERSAL_IPI_IRQ, GIC_HIGHEST_SEC_PRIORITY, grp, \
GIC_INTR_CFG_EDGE), \
+ INTR_PROP_DESC(CPU_PWR_DOWN_REQ_INTR, GIC_HIGHEST_SEC_PRIORITY, grp, \
+ GIC_INTR_CFG_EDGE)
#define IRQ_MAX 200U
diff --git a/plat/amd/versal2/plat_psci.c b/plat/amd/versal2/plat_psci.c
index 55842cc..d53d751 100644
--- a/plat/amd/versal2/plat_psci.c
+++ b/plat/amd/versal2/plat_psci.c
@@ -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
*/
@@ -200,7 +200,7 @@
}
static uint64_t no_pm_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
- uint64_t x4, void *cookie, void *handle, uint64_t flags)
+ uint64_t x4, const void *cookie, void *handle, uint64_t flags)
{
int32_t ret;
uint32_t arg[4], api_id;
@@ -240,7 +240,7 @@
}
uint64_t smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4,
- void *cookie, void *handle, uint64_t flags)
+ const void *cookie, void *handle, uint64_t flags)
{
return no_pm_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags);
}
diff --git a/plat/amd/versal2/plat_psci_pm.c b/plat/amd/versal2/plat_psci_pm.c
new file mode 100644
index 0000000..50614d5
--- /dev/null
+++ b/plat/amd/versal2/plat_psci_pm.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/psci/psci.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <plat_arm.h>
+
+#include "def.h"
+#include <ipi.h>
+#include <plat_private.h>
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include <pm_common.h>
+#include "pm_defs.h"
+#include "pm_svc_main.h"
+
+static uintptr_t sec_entry;
+
+static int32_t versal2_pwr_domain_on(u_register_t mpidr)
+{
+ int32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
+ int32_t ret = (int32_t) PSCI_E_INTERN_FAIL;
+ enum pm_ret_status pm_ret;
+ const struct pm_proc *proc;
+
+ if (cpu_id != -1) {
+ proc = pm_get_proc((uint32_t)cpu_id);
+ if (proc != NULL) {
+ pm_ret = pm_req_wakeup(proc->node_id,
+ (uint32_t)
+ ((sec_entry & 0xFFFFFFFFU) | 0x1U),
+ sec_entry >> 32, 0, 0);
+
+ if (pm_ret == PM_RET_SUCCESS) {
+ /* Clear power down request */
+ pm_client_wakeup(proc);
+ ret = (int32_t) PSCI_E_SUCCESS;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * versal2_pwr_domain_off() - Turn off core.
+ * @target_state: Targeted state.
+ */
+static void versal2_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ const struct pm_proc *proc;
+ uint32_t cpu_id = plat_my_core_pos();
+ enum pm_ret_status pm_ret;
+ size_t i;
+
+ proc = pm_get_proc(cpu_id);
+ if (proc == NULL) {
+ ERROR("Failed to get proc %d\n", cpu_id);
+ goto err;
+ }
+
+ for (i = 0; i <= PLAT_MAX_PWR_LVL; i++) {
+ VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+ __func__, i, target_state->pwr_domain_state[i]);
+ }
+
+ plat_gic_cpuif_disable();
+ /*
+ * Send request to PMC to power down the appropriate APU CPU
+ * core.
+ * According to PSCI specification, CPU_off function does not
+ * have resume address and CPU core can only be woken up
+ * invoking CPU_on function, during which resume address will
+ * be set.
+ */
+ pm_ret = pm_self_suspend(proc->node_id, MAX_LATENCY, PM_STATE_CPU_IDLE, 0,
+ SECURE_FLAG);
+
+ if (pm_ret != PM_RET_SUCCESS) {
+ ERROR("Failed to power down CPU %d\n", cpu_id);
+ }
+err:
+ return;
+}
+
+/**
+ * versal2_system_reset() - Send the reset request to firmware for the
+ * system to reset. This function does not
+ * return as it resets system.
+ */
+static void __dead2 versal2_system_reset(void)
+{
+ uint32_t timeout = 10000U;
+ enum pm_ret_status pm_ret;
+ int32_t ret;
+
+ request_cpu_pwrdwn();
+
+ /*
+ * Send the system reset request to the firmware if power down request
+ * is not received from firmware.
+ */
+ if (pwrdwn_req_received == true) {
+ /*
+ * TODO: shutdown scope for this reset needs be revised once
+ * we have a clearer understanding of the overall reset scoping
+ * including the implementation of SYSTEM_RESET2.
+ */
+ pm_ret = pm_system_shutdown(XPM_SHUTDOWN_TYPE_RESET,
+ pm_get_shutdown_scope(), SECURE_FLAG);
+
+ if (pm_ret != PM_RET_SUCCESS) {
+ WARN("System shutdown failed\n");
+ }
+
+ /*
+ * Wait for system shutdown request completed and idle callback
+ * not received.
+ */
+ do {
+ ret = ipi_mb_enquire_status(primary_proc->ipi->local_ipi_id,
+ primary_proc->ipi->remote_ipi_id);
+ udelay(100);
+ timeout--;
+ } while ((ret != (int32_t)IPI_MB_STATUS_RECV_PENDING) && (timeout > 0U));
+ }
+
+ (void)psci_cpu_off();
+
+ while (true) {
+ wfi();
+ }
+}
+
+/**
+ * versal2_pwr_domain_suspend() - Send request to PMC to suspend core.
+ * @target_state: Targeted state.
+ */
+static void versal2_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+ const struct pm_proc *proc;
+ uint32_t cpu_id = plat_my_core_pos();
+ uint32_t state;
+ enum pm_ret_status ret;
+ size_t i;
+
+ proc = pm_get_proc(cpu_id);
+ if (proc == NULL) {
+ ERROR("Failed to get proc %d\n", cpu_id);
+ goto err;
+ }
+
+ for (i = 0; i <= PLAT_MAX_PWR_LVL; i++) {
+ VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+ __func__, i, target_state->pwr_domain_state[i]);
+ }
+
+ plat_gic_cpuif_disable();
+
+ if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
+ plat_gic_save();
+ }
+
+ state = (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) ?
+ PM_STATE_SUSPEND_TO_RAM : PM_STATE_CPU_IDLE;
+
+ /* Send request to PMC to suspend this core */
+ ret = pm_self_suspend(proc->node_id, MAX_LATENCY, state, sec_entry,
+ SECURE_FLAG);
+
+ if (ret != PM_RET_SUCCESS) {
+ ERROR("Failed to power down CPU %d\n", cpu_id);
+ }
+
+err:
+ return;
+}
+
+static void versal2_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+ (void)target_state;
+
+ /* Enable the gic cpu interface */
+ plat_gic_pcpu_init();
+
+ /* Program the gic per-cpu distributor or re-distributor interface */
+ plat_gic_cpuif_enable();
+}
+
+/**
+ * versal2_pwr_domain_suspend_finish() - Performs actions to finish
+ * suspend procedure.
+ * @target_state: Targeted state.
+ */
+static void versal2_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ const struct pm_proc *proc;
+ uint32_t cpu_id = plat_my_core_pos();
+ size_t i;
+
+ proc = pm_get_proc(cpu_id);
+ if (proc == NULL) {
+ ERROR("Failed to get proc %d\n", cpu_id);
+ goto err;
+ }
+
+ for (i = 0; i <= PLAT_MAX_PWR_LVL; i++) {
+ VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
+ __func__, i, target_state->pwr_domain_state[i]);
+ }
+
+ /* Clear the APU power control register for this cpu */
+ pm_client_wakeup(proc);
+
+ /* APU was turned off, so restore GIC context */
+ if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
+ plat_gic_resume();
+ }
+
+ plat_gic_cpuif_enable();
+
+err:
+ return;
+}
+
+/**
+ * versal2_system_off() - Send the system off request to firmware.
+ * This function does not return as it puts core into WFI
+ */
+static void __dead2 versal2_system_off(void)
+{
+ enum pm_ret_status ret;
+
+ /* Send the power down request to the PMC */
+ ret = pm_system_shutdown(XPM_SHUTDOWN_TYPE_SHUTDOWN,
+ pm_get_shutdown_scope(), SECURE_FLAG);
+
+ if (ret != PM_RET_SUCCESS) {
+ ERROR("System shutdown failed\n");
+ }
+
+ while (true) {
+ wfi();
+ }
+}
+
+/**
+ * versal2_validate_power_state() - Ensure that the power state
+ * parameter in request is valid.
+ * @power_state: Power state of core.
+ * @req_state: Requested state.
+ *
+ * Return: Returns status, either PSCI_E_SUCCESS or reason.
+ */
+static int32_t versal2_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ uint32_t pstate = psci_get_pstate_type(power_state);
+ int32_t ret = PSCI_E_SUCCESS;
+
+ VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
+
+ assert(req_state);
+
+ /* Sanity check the requested state */
+ if (pstate == PSTATE_TYPE_STANDBY) {
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE;
+ } else {
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE;
+ }
+
+ /* The 'state_id' is expected to be zero */
+ if (psci_get_pstate_id(power_state) != 0U) {
+ ret = PSCI_E_INVALID_PARAMS;
+ }
+
+ return ret;
+}
+
+/**
+ * versal2_get_sys_suspend_power_state() - Get power state for system
+ * suspend.
+ * @req_state: Requested state.
+ */
+static void versal2_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ uint64_t i;
+
+ for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) {
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+ }
+}
+
+/**
+ * Export the platform specific power ops.
+ */
+static const struct plat_psci_ops versal2_nopmc_psci_ops = {
+ .pwr_domain_on = versal2_pwr_domain_on,
+ .pwr_domain_off = versal2_pwr_domain_off,
+ .pwr_domain_on_finish = versal2_pwr_domain_on_finish,
+ .pwr_domain_suspend = versal2_pwr_domain_suspend,
+ .pwr_domain_suspend_finish = versal2_pwr_domain_suspend_finish,
+ .system_off = versal2_system_off,
+ .system_reset = versal2_system_reset,
+ .validate_power_state = versal2_validate_power_state,
+ .get_sys_suspend_power_state = versal2_get_sys_suspend_power_state,
+};
+
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
+ const struct plat_psci_ops **psci_ops)
+{
+ sec_entry = sec_entrypoint;
+
+ VERBOSE("Setting up entry point %lx\n", sec_entry);
+
+ *psci_ops = &versal2_nopmc_psci_ops;
+
+ return 0;
+}
+
+int32_t sip_svc_setup_init(void)
+{
+ return pm_setup();
+}
+
+uint64_t smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4,
+ const void *cookie, void *handle, uint64_t flags)
+{
+ return pm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags);
+}
diff --git a/plat/amd/versal2/platform.mk b/plat/amd/versal2/platform.mk
index 3114976..489a063 100644
--- a/plat/amd/versal2/platform.mk
+++ b/plat/amd/versal2/platform.mk
@@ -1,6 +1,6 @@
# Copyright (c) 2018-2022, 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
@@ -28,6 +28,9 @@
IPI_CRC_CHECK := 0
GIC_ENABLE_V4_EXTN := 0
GICV3_SUPPORT_GIC600 := 1
+TFA_NO_PM := 0
+CPU_PWRDWN_SGI ?= 6
+$(eval $(call add_define_val,CPU_PWR_DOWN_REQ_INTR,ARM_IRQ_SEC_SGI_${CPU_PWRDWN_SGI}))
override CTX_INCLUDE_AARCH32_REGS := 0
@@ -35,6 +38,10 @@
override PLAT_XLAT_TABLES_DYNAMIC := 1
$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC))
+ifdef TFA_NO_PM
+ $(eval $(call add_define,TFA_NO_PM))
+endif
+
ifdef MEM_BASE
$(eval $(call add_define,MEM_BASE))
@@ -86,13 +93,14 @@
endif
endif
-
-ifdef XILINX_OF_BOARD_DTB_ADDR
+ifeq (${TRANSFER_LIST},0)
+XILINX_OF_BOARD_DTB_ADDR ?= 0x1000000
$(eval $(call add_define,XILINX_OF_BOARD_DTB_ADDR))
endif
PLAT_INCLUDES := -Iinclude/plat/arm/common/ \
-Iplat/xilinx/common/include/ \
+ -Iplat/amd/common/include/ \
-Iplat/xilinx/common/ipi_mailbox_service/ \
-I${PLAT_PATH}/include/ \
-Iplat/xilinx/versal/pm_service/
@@ -128,11 +136,17 @@
drivers/scmi-msg/reset_domain.c \
${PLAT_PATH}/scmi.c
+ifeq ($(TFA_NO_PM), 0)
+BL31_SOURCES += plat/xilinx/common/pm_service/pm_api_sys.c \
+ plat/xilinx/common/pm_service/pm_ipi.c \
+ ${PLAT_PATH}/plat_psci_pm.c \
+ ${PLAT_PATH}/pm_service/pm_svc_main.c \
+ ${PLAT_PATH}/pm_service/pm_client.c
+else
BL31_SOURCES += ${PLAT_PATH}/plat_psci.c
+endif
-BL31_SOURCES += plat/xilinx/common/plat_fdt.c \
- common/fdt_wrappers.c \
- plat/xilinx/common/plat_fdt.c \
+BL31_SOURCES += common/fdt_wrappers.c \
plat/xilinx/common/plat_console.c \
plat/xilinx/common/plat_startup.c \
plat/xilinx/common/ipi.c \
@@ -153,7 +167,20 @@
endif
# Enable Handoff protocol using transfer lists
-TRANSFER_LIST := 1
+TRANSFER_LIST ?= 0
+ifeq (${TRANSFER_LIST},1)
include lib/transfer_list/transfer_list.mk
-BL31_SOURCES += plat/xilinx/common/plat_xfer_list.c
+BL31_SOURCES += plat/amd/common/plat_fdt.c
+BL31_SOURCES += plat/amd/common/plat_xfer_list.c
+else
+BL31_SOURCES += plat/xilinx/common/plat_fdt.c
+endif
+
+XLNX_DT_CFG ?= 1
+ifeq (${TRANSFER_LIST},0)
+ifndef XILINX_OF_BOARD_DTB_ADDR
+XLNX_DT_CFG := 0
+endif
+endif
+$(eval $(call add_define,XLNX_DT_CFG))
diff --git a/plat/amd/versal2/pm_service/pm_client.c b/plat/amd/versal2/pm_service/pm_client.c
new file mode 100644
index 0000000..8d6b9b1
--- /dev/null
+++ b/plat/amd/versal2/pm_service/pm_client.c
@@ -0,0 +1,387 @@
+/*
+ * Copyright (c) 2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * APU specific definition of processors in the subsystem as well as functions
+ * for getting information about and changing state of the APU.
+ */
+
+#include <assert.h>
+
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv3.h>
+#include <lib/bakery_lock.h>
+#include <lib/mmio.h>
+#include <lib/spinlock.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
+#include "def.h"
+#include <plat_ipi.h>
+#include "pm_api_sys.h"
+#include "pm_client.h"
+
+#define UNDEFINED_CPUID UINT32_MAX
+
+DEFINE_RENAME_SYSREG_RW_FUNCS(cpu_pwrctrl_val, S3_0_C15_C2_7)
+
+/*
+ * ARM v8.2, the cache will turn off automatically when cpu
+ * power down. Therefore, there is no doubt to use the spin_lock here.
+ */
+static spinlock_t pm_client_secure_lock;
+static inline void pm_client_lock_get(void)
+{
+ spin_lock(&pm_client_secure_lock);
+}
+
+static inline void pm_client_lock_release(void)
+{
+ spin_unlock(&pm_client_secure_lock);
+}
+
+static const struct pm_ipi apu_ipi = {
+ .local_ipi_id = IPI_LOCAL_ID,
+ .remote_ipi_id = IPI_REMOTE_ID,
+ .buffer_base = IPI_BUFFER_LOCAL_BASE,
+};
+
+/* Order in pm_procs_all array must match cpu ids */
+static const struct pm_proc pm_procs_all[] = {
+ {
+ .node_id = PM_DEV_CLUSTER0_ACPU_0,
+ .ipi = &apu_ipi,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER0_ACPU_1,
+ .ipi = &apu_ipi,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER1_ACPU_0,
+ .ipi = &apu_ipi,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER1_ACPU_1,
+ .ipi = &apu_ipi,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER2_ACPU_0,
+ .ipi = &apu_ipi,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER2_ACPU_1,
+ .ipi = &apu_ipi,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER3_ACPU_0,
+ .ipi = &apu_ipi,
+ },
+ {
+ .node_id = PM_DEV_CLUSTER3_ACPU_1,
+ .ipi = &apu_ipi,
+ },
+};
+
+const struct pm_proc *primary_proc = &pm_procs_all[0];
+
+/**
+ * pm_get_proc() - returns pointer to the proc structure.
+ * @cpuid: id of the cpu whose proc struct pointer should be returned.
+ *
+ * Return: Pointer to a proc structure if proc is found, otherwise NULL.
+ */
+const struct pm_proc *pm_get_proc(uint32_t cpuid)
+{
+ const struct pm_proc *proc = NULL;
+
+ if (cpuid < ARRAY_SIZE(pm_procs_all)) {
+ proc = &pm_procs_all[cpuid];
+ } else {
+ ERROR("cpuid: %d proc NULL\n", cpuid);
+ }
+
+ return proc;
+}
+
+/**
+ * irq_to_pm_node_idx - Get PM node index corresponding to the interrupt number.
+ * @irq: Interrupt number.
+ *
+ * Return: PM node index corresponding to the specified interrupt.
+ */
+enum pm_device_node_idx irq_to_pm_node_idx(uint32_t irq)
+{
+ enum pm_device_node_idx dev_idx = XPM_NODEIDX_DEV_MIN;
+
+ assert(irq <= IRQ_MAX);
+
+ switch (irq) {
+ case 11:
+ dev_idx = XPM_NODEIDX_DEV_I2C_2;
+ break;
+ case 12:
+ dev_idx = XPM_NODEIDX_DEV_I2C_3;
+ break;
+ case 13:
+ dev_idx = XPM_NODEIDX_DEV_I2C_4;
+ break;
+ case 20:
+ dev_idx = XPM_NODEIDX_DEV_GPIO;
+ break;
+ case 21:
+ dev_idx = XPM_NODEIDX_DEV_I2C_0;
+ break;
+ case 22:
+ dev_idx = XPM_NODEIDX_DEV_I2C_1;
+ break;
+ case 23:
+ dev_idx = XPM_NODEIDX_DEV_SPI_0;
+ break;
+ case 24:
+ dev_idx = XPM_NODEIDX_DEV_SPI_1;
+ break;
+ case 25:
+ dev_idx = XPM_NODEIDX_DEV_UART_0;
+ break;
+ case 26:
+ dev_idx = XPM_NODEIDX_DEV_UART_1;
+ break;
+ case 27:
+ dev_idx = XPM_NODEIDX_DEV_CAN_FD_0;
+ break;
+ case 28:
+ dev_idx = XPM_NODEIDX_DEV_CAN_FD_1;
+ break;
+ case 29:
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ case 98:
+ dev_idx = XPM_NODEIDX_DEV_USB_0;
+ break;
+ case 34:
+ case 35:
+ case 36:
+ case 37:
+ case 38:
+ case 99:
+ dev_idx = XPM_NODEIDX_DEV_USB_1;
+ break;
+ case 39:
+ case 40:
+ dev_idx = XPM_NODEIDX_DEV_GEM_0;
+ break;
+ case 41:
+ case 42:
+ dev_idx = XPM_NODEIDX_DEV_GEM_1;
+ break;
+ case 43:
+ dev_idx = XPM_NODEIDX_DEV_TTC_0;
+ break;
+ case 44:
+ dev_idx = XPM_NODEIDX_DEV_TTC_1;
+ break;
+ case 45:
+ dev_idx = XPM_NODEIDX_DEV_TTC_2;
+ break;
+ case 46:
+ dev_idx = XPM_NODEIDX_DEV_TTC_3;
+ break;
+ case 47:
+ dev_idx = XPM_NODEIDX_DEV_TTC_4;
+ break;
+ case 48:
+ dev_idx = XPM_NODEIDX_DEV_TTC_5;
+ break;
+ case 49:
+ dev_idx = XPM_NODEIDX_DEV_TTC_6;
+ break;
+ case 50:
+ dev_idx = XPM_NODEIDX_DEV_TTC_7;
+ break;
+ case 72:
+ dev_idx = XPM_NODEIDX_DEV_ADMA_0;
+ break;
+ case 73:
+ dev_idx = XPM_NODEIDX_DEV_ADMA_1;
+ break;
+ case 74:
+ dev_idx = XPM_NODEIDX_DEV_ADMA_2;
+ break;
+ case 75:
+ dev_idx = XPM_NODEIDX_DEV_ADMA_3;
+ break;
+ case 76:
+ dev_idx = XPM_NODEIDX_DEV_ADMA_4;
+ break;
+ case 77:
+ dev_idx = XPM_NODEIDX_DEV_ADMA_5;
+ break;
+ case 78:
+ dev_idx = XPM_NODEIDX_DEV_ADMA_6;
+ break;
+ case 79:
+ dev_idx = XPM_NODEIDX_DEV_ADMA_7;
+ break;
+ case 95:
+ dev_idx = XPM_NODEIDX_DEV_CAN_FD_2;
+ break;
+ case 96:
+ dev_idx = XPM_NODEIDX_DEV_CAN_FD_3;
+ break;
+ case 100:
+ dev_idx = XPM_NODEIDX_DEV_I2C_5;
+ break;
+ case 101:
+ dev_idx = XPM_NODEIDX_DEV_I2C_6;
+ break;
+ case 102:
+ dev_idx = XPM_NODEIDX_DEV_I2C_7;
+ break;
+ case 200:
+ dev_idx = XPM_NODEIDX_DEV_RTC;
+ break;
+ case 218:
+ dev_idx = XPM_NODEIDX_DEV_SDIO_0;
+ break;
+ case 220:
+ dev_idx = XPM_NODEIDX_DEV_SDIO_1;
+ break;
+ default:
+ dev_idx = XPM_NODEIDX_DEV_MIN;
+ break;
+ }
+
+ return dev_idx;
+}
+
+/**
+ * pm_client_suspend() - Client-specific suspend actions. This function
+ * perform actions required prior to sending suspend
+ * request.
+ * Actions taken depend on the state system is
+ * suspending to.
+ * @proc: processor which need to suspend.
+ * @state: desired suspend state.
+ */
+void pm_client_suspend(const struct pm_proc *proc, uint32_t state)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+ uintptr_t val;
+ /*
+ * Get the core index, use it calculate offset for secondary cores
+ * to match with register database
+ */
+ uint32_t core_index = cpu_id + ((cpu_id / 2U) * 2U);
+
+ pm_client_lock_get();
+
+ if (state == PM_STATE_SUSPEND_TO_RAM) {
+ pm_client_set_wakeup_sources((uint32_t)proc->node_id);
+ }
+
+ val = read_cpu_pwrctrl_val();
+ val |= CORE_PWRDN_EN_BIT_MASK;
+ write_cpu_pwrctrl_val(val);
+
+ isb();
+
+ /* Enable power down interrupt */
+ mmio_write_32(APU_PCIL_CORE_X_IEN_POWER_REG(core_index),
+ APU_PCIL_CORE_X_IEN_POWER_MASK);
+ /* Enable wake interrupt */
+ mmio_write_32(APU_PCIL_CORE_X_IEN_WAKE_REG(core_index),
+ APU_PCIL_CORE_X_IEN_WAKE_MASK);
+
+ pm_client_lock_release();
+}
+
+/**
+ * pm_get_cpuid() - get the local cpu ID for a global node ID.
+ * @nid: node id of the processor.
+ *
+ * Return: the cpu ID (starting from 0) for the subsystem.
+ */
+static uint32_t pm_get_cpuid(uint32_t nid)
+{
+ uint32_t ret = (uint32_t) UNDEFINED_CPUID;
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(pm_procs_all); i++) {
+ if (pm_procs_all[i].node_id == nid) {
+ ret = (uint32_t)i;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * pm_client_wakeup() - Client-specific wakeup actions.
+ * @proc: Processor which need to wakeup.
+ *
+ * This function should contain any PU-specific actions
+ * required for waking up another APU core.
+ */
+void pm_client_wakeup(const struct pm_proc *proc)
+{
+ uint32_t cpuid = pm_get_cpuid(proc->node_id);
+ uintptr_t val;
+
+ if (cpuid != (uint32_t) UNDEFINED_CPUID) {
+ pm_client_lock_get();
+
+ /* Clear powerdown request */
+ val = read_cpu_pwrctrl_val();
+ val &= ~CORE_PWRDN_EN_BIT_MASK;
+ write_cpu_pwrctrl_val(val);
+
+ isb();
+
+ /* Disabled power down interrupt */
+ mmio_write_32(APU_PCIL_CORE_X_IDS_POWER_REG(cpuid),
+ APU_PCIL_CORE_X_IDS_POWER_MASK);
+ /* Disable wake interrupt */
+ mmio_write_32(APU_PCIL_CORE_X_IDS_WAKE_REG(cpuid),
+ APU_PCIL_CORE_X_IDS_WAKE_MASK);
+
+ pm_client_lock_release();
+ }
+}
+
+/**
+ * pm_client_abort_suspend() - Client-specific abort-suspend actions.
+ *
+ * This function should contain any PU-specific actions
+ * required for aborting a prior suspend request.
+ */
+void pm_client_abort_suspend(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+ uintptr_t val;
+
+ /* Enable interrupts at processor level (for current cpu) */
+ gicv3_cpuif_enable(plat_my_core_pos());
+
+ pm_client_lock_get();
+
+ /* Clear powerdown request */
+ val = read_cpu_pwrctrl_val();
+ val &= ~CORE_PWRDN_EN_BIT_MASK;
+ write_cpu_pwrctrl_val(val);
+
+ isb();
+
+ /* Disabled power down interrupt */
+ mmio_write_32(APU_PCIL_CORE_X_IDS_POWER_REG(cpu_id),
+ APU_PCIL_CORE_X_IDS_POWER_MASK);
+
+ pm_client_lock_release();
+}
diff --git a/plat/amd/versal2/pm_service/pm_svc_main.c b/plat/amd/versal2/pm_service/pm_svc_main.c
new file mode 100644
index 0000000..88848e2
--- /dev/null
+++ b/plat/amd/versal2/pm_service/pm_svc_main.c
@@ -0,0 +1,529 @@
+/*
+ * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Top-level SMC handler for Versal2 power management calls and
+ * IPI setup functions for communication with PMC.
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+
+#include "../drivers/arm/gic/v3/gicv3_private.h"
+
+#include <common/runtime_svc.h>
+#include <drivers/arm/gicv3.h>
+#include <lib/psci/psci.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+
+#include <plat_private.h>
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "pm_ipi.h"
+#include "pm_svc_main.h"
+
+#define MODE 0x80000000U
+
+#define INVALID_SGI 0xFFU
+#define PM_INIT_SUSPEND_CB (30U)
+#define PM_NOTIFY_CB (32U)
+#define EVENT_CPU_PWRDWN (4U)
+#define MBOX_SGI_SHARED_IPI (7U)
+
+/**
+ * upper_32_bits - return bits 32-63 of a number
+ * @n: the number we're accessing
+ */
+#define upper_32_bits(n) ((uint32_t)((n) >> 32U))
+
+/**
+ * lower_32_bits - return bits 0-31 of a number
+ * @n: the number we're accessing
+ */
+#define lower_32_bits(n) ((uint32_t)((n) & 0xffffffffU))
+
+/**
+ * EXTRACT_SMC_ARGS - extracts 32-bit payloads from 64-bit SMC arguments
+ * @pm_arg: array of 32-bit payloads
+ * @x: array of 64-bit SMC arguments
+ */
+#define EXTRACT_ARGS(pm_arg, x) \
+ for (uint32_t i = 0U; i < (PAYLOAD_ARG_CNT - 1U); i++) { \
+ if ((i % 2U) != 0U) { \
+ pm_arg[i] = lower_32_bits(x[(i / 2U) + 1U]); \
+ } else { \
+ pm_arg[i] = upper_32_bits(x[i / 2U]); \
+ } \
+ }
+
+/* 1 sec of wait timeout for secondary core down */
+#define PWRDWN_WAIT_TIMEOUT (1000U)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_asgi1r_el1, S3_0_C12_C11_6)
+
+/* pm_up = true - UP, pm_up = false - DOWN */
+static bool pm_up;
+static uint32_t sgi = (uint32_t)INVALID_SGI;
+bool pwrdwn_req_received;
+
+static void notify_os(void)
+{
+ plat_ic_raise_ns_sgi((int)sgi, read_mpidr_el1());
+}
+
+static uint64_t cpu_pwrdwn_req_handler(uint32_t id, uint32_t flags,
+ void *handle, void *cookie)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ VERBOSE("Powering down CPU %d\n", cpu_id);
+
+ /* Deactivate CPU power down SGI */
+ plat_ic_end_of_interrupt(CPU_PWR_DOWN_REQ_INTR);
+
+ return (uint64_t) psci_cpu_off();
+}
+
+/**
+ * raise_pwr_down_interrupt() - Callback function to raise SGI.
+ * @mpidr: MPIDR for the target CPU.
+ *
+ * Raise SGI interrupt to trigger the CPU power down sequence on all the
+ * online secondary cores.
+ */
+static void raise_pwr_down_interrupt(u_register_t mpidr)
+{
+ plat_ic_raise_el3_sgi((int)CPU_PWR_DOWN_REQ_INTR, mpidr);
+}
+
+void request_cpu_pwrdwn(void)
+{
+ int ret;
+
+ VERBOSE("CPU power down request received\n");
+
+ /* Send powerdown request to online secondary core(s) */
+ ret = psci_stop_other_cores(plat_my_core_pos(), (unsigned int)PWRDWN_WAIT_TIMEOUT, raise_pwr_down_interrupt);
+ if (ret != (int)PSCI_E_SUCCESS) {
+ ERROR("Failed to powerdown secondary core(s)\n");
+ }
+
+ /* Clear IPI IRQ */
+ pm_ipi_irq_clear(primary_proc);
+
+ /* Deactivate IPI IRQ */
+ plat_ic_end_of_interrupt(PLAT_VERSAL_IPI_IRQ);
+}
+
+static uint64_t ipi_fiq_handler(uint32_t id, uint32_t flags, void *handle,
+ void *cookie)
+{
+ uint32_t payload[4] = {0};
+ enum pm_ret_status ret;
+ uint32_t ipi_status, i;
+
+ VERBOSE("Received IPI FIQ from firmware\n");
+
+ console_flush();
+ (void)plat_ic_acknowledge_interrupt();
+
+ /* Check status register for each IPI except PMC */
+ for (i = IPI_ID_APU; i <= IPI_ID_5; i++) {
+ ipi_status = (uint32_t)ipi_mb_enquire_status(IPI_ID_APU, i);
+
+ /* If any agent other than PMC has generated IPI FIQ then send SGI to mbox driver */
+ if ((ipi_status & (uint32_t)IPI_MB_STATUS_RECV_PENDING) > (uint32_t) 0) {
+ plat_ic_raise_ns_sgi((int)MBOX_SGI_SHARED_IPI, read_mpidr_el1());
+ break;
+ }
+ }
+
+ /* If PMC has not generated interrupt then end ISR */
+ ipi_status = (uint32_t)ipi_mb_enquire_status(IPI_ID_APU, IPI_ID_PMC);
+ if ((ipi_status & (uint32_t) IPI_MB_STATUS_RECV_PENDING) == (uint32_t) 0) {
+ plat_ic_end_of_interrupt(id);
+ goto end;
+ }
+
+ /* Handle PMC case */
+ ret = pm_get_callbackdata(payload, ARRAY_SIZE(payload), 0, 0);
+ if (ret != PM_RET_SUCCESS) {
+ payload[0] = (uint32_t) ret;
+ }
+
+ switch (payload[0]) {
+ case PM_INIT_SUSPEND_CB:
+ if (sgi != INVALID_SGI) {
+ notify_os();
+ }
+ break;
+ case PM_NOTIFY_CB:
+ if (sgi != INVALID_SGI) {
+ if (payload[2] == EVENT_CPU_PWRDWN) {
+ if (pwrdwn_req_received) {
+ pwrdwn_req_received = false;
+ request_cpu_pwrdwn();
+ (void)psci_cpu_off();
+ break;
+ } else {
+ /* No action needed, added for MISRA
+ * complaince
+ */
+ }
+ pwrdwn_req_received = true;
+
+ } else {
+ /* No action needed, added for MISRA
+ * complaince
+ */
+ }
+ notify_os();
+ } else if (payload[2] == EVENT_CPU_PWRDWN) {
+ request_cpu_pwrdwn();
+ (void)psci_cpu_off();
+ } else {
+ /* No action needed, added for MISRA
+ * complaince
+ */
+ }
+ break;
+ case (uint32_t) PM_RET_ERROR_INVALID_CRC:
+ pm_ipi_irq_clear(primary_proc);
+ WARN("Invalid CRC in the payload\n");
+ break;
+
+ default:
+ pm_ipi_irq_clear(primary_proc);
+ WARN("Invalid IPI payload\n");
+ break;
+ }
+
+ /* Clear FIQ */
+ plat_ic_end_of_interrupt(id);
+
+end:
+ return 0;
+}
+
+/**
+ * pm_register_sgi() - PM register the IPI interrupt.
+ * @sgi_num: SGI number to be used for communication.
+ * @reset: Reset to invalid SGI when reset=1.
+ *
+ * Return: On success, the initialization function must return 0.
+ * Any other return value will cause the framework to ignore
+ * the service.
+ *
+ * Update the SGI number to be used.
+ *
+ */
+int32_t pm_register_sgi(uint32_t sgi_num, uint32_t reset)
+{
+ int32_t ret;
+
+ if (reset == 1U) {
+ sgi = INVALID_SGI;
+ ret = 0;
+ goto end;
+ }
+
+ if (sgi != INVALID_SGI) {
+ ret = -EBUSY;
+ goto end;
+ }
+
+ if (sgi_num >= GICV3_MAX_SGI_TARGETS) {
+ ret = -EINVAL;
+ goto end;
+ }
+
+ sgi = (uint32_t)sgi_num;
+ ret = 0;
+end:
+ return ret;
+}
+
+/**
+ * pm_setup() - PM service setup.
+ *
+ * Return: On success, the initialization function must return 0.
+ * Any other return value will cause the framework to ignore
+ * the service.
+ *
+ * Initialization functions for Versal power management for
+ * communicaton with PMC.
+ *
+ * Called from sip_svc_setup initialization function with the
+ * rt_svc_init signature.
+ *
+ */
+int32_t pm_setup(void)
+{
+ int32_t ret = 0;
+
+ pm_ipi_init(primary_proc);
+ pm_up = true;
+
+ /* register SGI handler for CPU power down request */
+ ret = request_intr_type_el3(CPU_PWR_DOWN_REQ_INTR, cpu_pwrdwn_req_handler);
+ if (ret != 0) {
+ WARN("BL31: registering SGI interrupt failed\n");
+ }
+
+ /*
+ * Enable IPI IRQ
+ * assume the rich OS is OK to handle callback IRQs now.
+ * Even if we were wrong, it would not enable the IRQ in
+ * the GIC.
+ */
+ pm_ipi_irq_enable(primary_proc);
+
+ ret = request_intr_type_el3(PLAT_VERSAL_IPI_IRQ, ipi_fiq_handler);
+ if (ret != 0) {
+ WARN("BL31: registering IPI interrupt failed\n");
+ }
+
+ gicd_write_irouter(gicv3_driver_data->gicd_base, PLAT_VERSAL_IPI_IRQ, MODE);
+
+ /* Register for idle callback during force power down/restart */
+ ret = (int32_t)pm_register_notifier(primary_proc->node_id, EVENT_CPU_PWRDWN,
+ 0x0U, 0x1U, SECURE_FLAG);
+ if (ret != 0) {
+ WARN("BL31: registering idle callback for restart/force power down failed\n");
+ }
+
+ return ret;
+}
+
+/**
+ * eemi_psci_debugfs_handler() - EEMI API invoked from PSCI.
+ * @api_id: identifier for the API being called.
+ * @pm_arg: pointer to the argument data for the API call.
+ * @handle: Pointer to caller's context structure.
+ * @security_flag: SECURE_FLAG or NON_SECURE_FLAG.
+ *
+ * These EEMI APIs performs CPU specific power management tasks.
+ * These EEMI APIs are invoked either from PSCI or from debugfs in kernel.
+ * These calls require CPU specific processing before sending IPI request to
+ * Platform Management Controller. For example enable/disable CPU specific
+ * interrupts. This requires separate handler for these calls and may not be
+ * handled using common eemi handler.
+ *
+ * Return: If EEMI API found then, uintptr_t type address, else 0.
+ *
+ */
+static uintptr_t eemi_psci_debugfs_handler(uint32_t api_id, uint32_t *pm_arg,
+ void *handle, uint32_t security_flag)
+{
+ enum pm_ret_status ret;
+
+ switch (api_id) {
+
+ case (uint32_t)PM_SELF_SUSPEND:
+ ret = pm_self_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
+ pm_arg[3], security_flag);
+ SMC_RET1(handle, (u_register_t)ret);
+
+ case (uint32_t)PM_FORCE_POWERDOWN:
+ ret = pm_force_powerdown(pm_arg[0], (uint8_t)pm_arg[1], security_flag);
+ SMC_RET1(handle, (u_register_t)ret);
+
+ case (uint32_t)PM_REQ_SUSPEND:
+ ret = pm_req_suspend(pm_arg[0], (uint8_t)pm_arg[1], pm_arg[2],
+ pm_arg[3], security_flag);
+ SMC_RET1(handle, (u_register_t)ret);
+
+ case (uint32_t)PM_ABORT_SUSPEND:
+ ret = pm_abort_suspend(pm_arg[0], security_flag);
+ SMC_RET1(handle, (u_register_t)ret);
+
+ case (uint32_t)PM_SYSTEM_SHUTDOWN:
+ ret = pm_system_shutdown(pm_arg[0], pm_arg[1], security_flag);
+ SMC_RET1(handle, (u_register_t)ret);
+
+ default:
+ return (uintptr_t)0;
+ }
+}
+
+/**
+ * TF_A_specific_handler() - SMC handler for TF-A specific functionality.
+ * @api_id: identifier for the API being called.
+ * @pm_arg: pointer to the argument data for the API call.
+ * @handle: Pointer to caller's context structure.
+ * @security_flag: SECURE_FLAG or NON_SECURE_FLAG.
+ *
+ * These EEMI calls performs functionality that does not require
+ * IPI transaction. The handler ends in TF-A and returns requested data to
+ * kernel from TF-A.
+ *
+ * Return: If TF-A specific API found then, uintptr_t type address, else 0
+ *
+ */
+static uintptr_t TF_A_specific_handler(uint32_t api_id, uint32_t *pm_arg,
+ void *handle, uint32_t security_flag)
+{
+ switch (api_id) {
+
+ case TF_A_FEATURE_CHECK:
+ {
+ enum pm_ret_status ret;
+ uint32_t result[PAYLOAD_ARG_CNT] = {0U};
+
+ ret = eemi_feature_check(pm_arg[0], result);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U));
+ }
+
+ case TF_A_PM_REGISTER_SGI:
+ {
+ int32_t ret;
+
+ ret = pm_register_sgi(pm_arg[0], pm_arg[1]);
+ if (ret != 0) {
+ SMC_RET1(handle, (uint32_t)PM_RET_ERROR_ARGS);
+ }
+
+ SMC_RET1(handle, (uint32_t)PM_RET_SUCCESS);
+ }
+
+ case PM_GET_CALLBACK_DATA:
+ {
+ uint32_t result[4] = {0};
+ enum pm_ret_status ret;
+
+ ret = pm_get_callbackdata(result, ARRAY_SIZE(result), security_flag, 1U);
+ if (ret != PM_RET_SUCCESS) {
+ result[0] = (uint32_t) ret;
+ }
+
+ SMC_RET2(handle,
+ (uint64_t)result[0] | ((uint64_t)result[1] << 32U),
+ (uint64_t)result[2] | ((uint64_t)result[3] << 32U));
+ }
+
+ case PM_GET_TRUSTZONE_VERSION:
+ SMC_RET1(handle, ((uint64_t)PM_RET_SUCCESS) |
+ (((uint64_t)TZ_VERSION) << 32U));
+
+ default:
+ return (uintptr_t)0U;
+ }
+}
+
+/**
+ * eemi_api_handler() - Prepare EEMI payload and perform IPI transaction.
+ * @api_id: identifier for the API being called.
+ * @pm_arg: pointer to the argument data for the API call.
+ * @handle: Pointer to caller's context structure.
+ * @security_flag: SECURE_FLAG or NON_SECURE_FLAG.
+ *
+ * EEMI - Embedded Energy Management Interface is AMD-Xilinx proprietary
+ * protocol to allow communication between power management controller and
+ * different processing clusters.
+ *
+ * This handler prepares EEMI protocol payload received from kernel and performs
+ * IPI transaction.
+ *
+ * Return: If EEMI API found then, uintptr_t type address, else 0
+ */
+static uintptr_t eemi_api_handler(uint32_t api_id, const uint32_t *pm_arg,
+ void *handle, uint32_t security_flag)
+{
+ enum pm_ret_status ret;
+ uint32_t buf[RET_PAYLOAD_ARG_CNT] = {0U};
+ uint32_t payload[PAYLOAD_ARG_CNT] = {0U};
+ uint32_t module_id;
+
+ module_id = (api_id & MODULE_ID_MASK) >> 8U;
+
+ PM_PACK_PAYLOAD7(payload, module_id, security_flag, api_id,
+ pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3],
+ pm_arg[4], pm_arg[5]);
+
+ ret = pm_ipi_send_sync(primary_proc, payload, (uint32_t *)buf,
+ RET_PAYLOAD_ARG_CNT);
+
+ SMC_RET4(handle, (uint64_t)ret | ((uint64_t)buf[0] << 32U),
+ (uint64_t)buf[1] | ((uint64_t)buf[2] << 32U),
+ (uint64_t)buf[3] | ((uint64_t)buf[4] << 32U),
+ (uint64_t)buf[5]);
+}
+
+/**
+ * pm_smc_handler() - SMC handler for PM-API calls coming from EL1/EL2.
+ * @smc_fid: Function Identifier.
+ * @x1: SMC64 Arguments from kernel.
+ * @x2: SMC64 Arguments from kernel.
+ * @x3: SMC64 Arguments from kernel (upper 32-bits).
+ * @x4: Unused.
+ * @cookie: Unused.
+ * @handle: Pointer to caller's context structure.
+ * @flags: SECURE_FLAG or NON_SECURE_FLAG.
+ *
+ * Return: Unused.
+ *
+ * Determines that smc_fid is valid and supported PM SMC Function ID from the
+ * list of pm_api_ids, otherwise completes the request with
+ * the unknown SMC Function ID.
+ *
+ * The SMC calls for PM service are forwarded from SIP Service SMC handler
+ * function with rt_svc_handle signature.
+ *
+ */
+uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+ uint64_t x4, const void *cookie, void *handle, uint64_t flags)
+{
+ uintptr_t ret;
+ uint32_t pm_arg[PAYLOAD_ARG_CNT] = {0};
+ uint32_t security_flag = NON_SECURE_FLAG;
+ uint32_t api_id;
+ bool status = false, status_tmp = false;
+ uint64_t x[4] = {x1, x2, x3, x4};
+
+ /* Handle case where PM wasn't initialized properly */
+ if (pm_up == false) {
+ SMC_RET1(handle, SMC_UNK);
+ }
+
+ /*
+ * Mark BIT24 payload (i.e 1st bit of pm_arg[3] ) as secure (0)
+ * if smc called is secure
+ *
+ * Add redundant macro call to immune the code from glitches
+ */
+ SECURE_REDUNDANT_CALL(status, status_tmp, is_caller_secure, flags);
+ if ((status != false) && (status_tmp != false)) {
+ security_flag = SECURE_FLAG;
+ }
+
+ if ((smc_fid & FUNCID_NUM_MASK) == PASS_THROUGH_FW_CMD_ID) {
+ api_id = lower_32_bits(x[0]);
+
+ EXTRACT_ARGS(pm_arg, x);
+
+ return eemi_api_handler(api_id, pm_arg, handle, security_flag);
+ }
+
+ pm_arg[0] = (uint32_t)x1;
+ pm_arg[1] = (uint32_t)(x1 >> 32U);
+ pm_arg[2] = (uint32_t)x2;
+ pm_arg[3] = (uint32_t)(x2 >> 32U);
+ pm_arg[4] = (uint32_t)x3;
+ (void)(x4);
+ api_id = smc_fid & FUNCID_NUM_MASK;
+
+ ret = eemi_psci_debugfs_handler(api_id, pm_arg, handle, (uint32_t)flags);
+ if (ret != (uintptr_t)0)
+ goto error;
+
+ ret = TF_A_specific_handler(api_id, pm_arg, handle, security_flag);
+ if (ret != (uintptr_t)0)
+ goto error;
+
+error:
+ return ret;
+}
diff --git a/plat/amd/versal2/sip_svc_setup.c b/plat/amd/versal2/sip_svc_setup.c
index 4a1be3e..9e81af0 100644
--- a/plat/amd/versal2/sip_svc_setup.c
+++ b/plat/amd/versal2/sip_svc_setup.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-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
*/
@@ -27,7 +27,7 @@
/* SiP Service Calls version numbers */
#define SIP_SVC_VERSION_MAJOR (0U)
-#define SIP_SVC_VERSION_MINOR (1U)
+#define SIP_SVC_VERSION_MINOR (2U)
/* These macros are used to identify PM calls from the SMC function ID */
#define SIP_FID_MASK GENMASK(23, 16)
diff --git a/plat/amlogic/axg/axg_pm.c b/plat/amlogic/axg/axg_pm.c
index e67f263..8a1b5d2 100644
--- a/plat/amlogic/axg/axg_pm.c
+++ b/plat/amlogic/axg/axg_pm.c
@@ -152,7 +152,7 @@
.pwr_domain_on = axg_pwr_domain_on,
.pwr_domain_on_finish = axg_pwr_domain_on_finish,
.pwr_domain_off = axg_pwr_domain_off,
- .pwr_domain_pwr_down_wfi = axg_pwr_domain_pwr_down_wfi,
+ .pwr_domain_pwr_down = axg_pwr_domain_pwr_down_wfi,
.system_off = axg_system_off,
.system_reset = axg_system_reset
};
diff --git a/plat/amlogic/g12a/g12a_pm.c b/plat/amlogic/g12a/g12a_pm.c
index c9fe3e9..1203e3c 100644
--- a/plat/amlogic/g12a/g12a_pm.c
+++ b/plat/amlogic/g12a/g12a_pm.c
@@ -200,7 +200,7 @@
.pwr_domain_on = g12a_pwr_domain_on,
.pwr_domain_on_finish = g12a_pwr_domain_on_finish,
.pwr_domain_off = g12a_pwr_domain_off,
- .pwr_domain_pwr_down_wfi = g12a_pwr_domain_pwr_down_wfi,
+ .pwr_domain_pwr_down = g12a_pwr_domain_pwr_down_wfi,
.system_off = g12a_system_off,
.system_reset = g12a_system_reset
};
diff --git a/plat/amlogic/gxbb/gxbb_pm.c b/plat/amlogic/gxbb/gxbb_pm.c
index 48bff7b..eeebb41 100644
--- a/plat/amlogic/gxbb/gxbb_pm.c
+++ b/plat/amlogic/gxbb/gxbb_pm.c
@@ -176,7 +176,7 @@
.pwr_domain_on = gxbb_pwr_domain_on,
.pwr_domain_on_finish = gxbb_pwr_domain_on_finish,
.pwr_domain_off = gxbb_pwr_domain_off,
- .pwr_domain_pwr_down_wfi = gxbb_pwr_domain_pwr_down_wfi,
+ .pwr_domain_pwr_down = gxbb_pwr_domain_pwr_down_wfi,
.system_off = gxbb_system_off,
.system_reset = gxbb_system_reset,
};
diff --git a/plat/amlogic/gxl/gxl_pm.c b/plat/amlogic/gxl/gxl_pm.c
index 433140b..5af4932 100644
--- a/plat/amlogic/gxl/gxl_pm.c
+++ b/plat/amlogic/gxl/gxl_pm.c
@@ -199,7 +199,7 @@
.pwr_domain_on = gxl_pwr_domain_on,
.pwr_domain_on_finish = gxl_pwr_domain_on_finish,
.pwr_domain_off = gxl_pwr_domain_off,
- .pwr_domain_pwr_down_wfi = gxl_pwr_domain_pwr_down_wfi,
+ .pwr_domain_pwr_down = gxl_pwr_domain_pwr_down_wfi,
.system_off = gxl_system_off,
.system_reset = gxl_system_reset,
};
diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk
index 967bf21..31835f1 100644
--- a/plat/arm/board/arm_fpga/platform.mk
+++ b/plat/arm/board/arm_fpga/platform.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2021-2024, Arm Limited. All rights reserved.
+# Copyright (c) 2021-2025, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -78,7 +78,6 @@
lib/cpus/aarch64/cortex_a720.S \
lib/cpus/aarch64/cortex_x3.S \
lib/cpus/aarch64/cortex_x4.S \
- lib/cpus/aarch64/neoverse_n_common.S \
lib/cpus/aarch64/neoverse_n1.S \
lib/cpus/aarch64/neoverse_n2.S \
lib/cpus/aarch64/neoverse_v1.S \
diff --git a/plat/arm/board/automotive_rd/platform/rd1ae/platform.mk b/plat/arm/board/automotive_rd/platform/rd1ae/platform.mk
index 6773ae0..12b1e8c 100644
--- a/plat/arm/board/automotive_rd/platform/rd1ae/platform.mk
+++ b/plat/arm/board/automotive_rd/platform/rd1ae/platform.mk
@@ -1,4 +1,4 @@
-# Copyright (c) 2024, Arm Limited. All rights reserved.
+# Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -33,7 +33,7 @@
GICV3_SUPPORT_GIC600 := 1
HW_ASSISTED_COHERENCY := 1
NEED_BL32 := yes
-PLAT_MHU_VERSION := 1
+PLAT_MHU := MHUv1
RESET_TO_BL2 := 1
SVE_VECTOR_LEN := 128
USE_COHERENT_MEM := 0
diff --git a/plat/arm/board/common/board_common.mk b/plat/arm/board/common/board_common.mk
index 889b8b3..3a6637f 100644
--- a/plat/arm/board/common/board_common.mk
+++ b/plat/arm/board/common/board_common.mk
@@ -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
#
@@ -148,14 +148,14 @@
$(BUILD_PLAT)/bl2/arm_dev_swd_rotpk.o: $(ARM_SWD_ROTPK)
endif
-$(ARM_PROTPK): $(ARM_PROT_KEY)
+$(ARM_PROTPK): $(ARM_PROT_KEY) | $$(@D)/
ifndef ARM_PROT_KEY
$(error Cannot generate hash: no PROT_KEY defined)
endif
${OPENSSL_BIN_PATH}/openssl ${CRYPTO_ALG} -in ${ARM_PROT_KEY} -pubout -outform DER | \
${OPENSSL_BIN_PATH}/openssl dgst -${HASH_ALG} -binary -out $@
-$(ARM_SWD_ROTPK): $(ARM_SWD_ROT_KEY)
+$(ARM_SWD_ROTPK): $(ARM_SWD_ROT_KEY) | $$(@D)/
ifndef ARM_SWD_ROT_KEY
$(error Cannot generate hash: no SWD_KEY defined)
endif
diff --git a/plat/arm/board/corstone1000/common/corstone1000_pm.c b/plat/arm/board/corstone1000/common/corstone1000_pm.c
index bd3faec..5264187 100644
--- a/plat/arm/board/corstone1000/common/corstone1000_pm.c
+++ b/plat/arm/board/corstone1000/common/corstone1000_pm.c
@@ -14,7 +14,7 @@
* platform layer will take care of registering the handlers with PSCI.
******************************************************************************/
-static void __dead2 corstone1000_system_reset(void)
+static void corstone1000_system_reset(void)
{
uint32_t volatile * const watchdog_ctrl_reg = (uint32_t *) SECURE_WATCHDOG_ADDR_CTRL_REG;
@@ -31,9 +31,6 @@
*(watchdog_val_reg) = SECURE_WATCHDOG_COUNTDOWN_VAL;
*watchdog_ctrl_reg = SECURE_WATCHDOG_MASK_ENABLE;
- while (1) {
- wfi();
- }
}
#if defined(CORSTONE1000_FVP_MULTICORE)
diff --git a/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
index 43dc17b..662b8a4 100644
--- a/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
+++ b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -18,7 +18,8 @@
struct hw_topology_t soc_topology;
struct uart_serial_config_t uart_serial_config;
struct cpu_timer_t cpu_timer;
-struct ns_dram_layout dram_layout;
+struct dram_layout_t dram_layout;
+struct pci_props_t pci_props;
/*
* Each NS DRAM bank entry is 'reg' node property which is
@@ -27,6 +28,7 @@
#define DRAM_ENTRY_SIZE (4UL * sizeof(uint32_t))
CASSERT(ARM_DRAM_NUM_BANKS == 2UL, ARM_DRAM_NUM_BANKS_mismatch);
+CASSERT(ARM_PCI_NUM_REGIONS == 2UL, ARM_PCI_NUM_REGIONS_mismatch);
#define ILLEGAL_ADDR ULL(~0)
@@ -352,8 +354,98 @@
return 0;
}
+/*
+ * Each PCIe memory region entry is 'ranges' node property which is
+ * an arbitrary number of (child-bus-address, parent-bus-address, length)
+ * triplets. E.g. with
+ * #address-cells = <3>
+ * #size-cells = <2>
+ * parent's #address-cells = <2>
+ * each entry occupies 7 32-bit words.
+ */
+int fconf_populate_pci_props(uintptr_t config)
+{
+ int node, parent, len, err;
+ int parent_ac, ac, sc, entry_len;
+ const uint32_t *reg, *ranges;
+
+ /* Necessary to work with libfdt APIs */
+ const void *hw_config_dtb = (const void *)config;
+
+ /* Find 'pci' node */
+ node = fdt_node_offset_by_prop_value(hw_config_dtb, -1, "device_type",
+ "pci", sizeof("pci"));
+ if (node < 0) {
+ WARN("FCONF: Unable to locate 'pci' node\n");
+ pci_props.ecam_base = 0UL;
+ pci_props.size = 0UL;
+ pci_props.num_ncoh_regions = 0UL;
+ /* Don't return error code if 'pci' node not found */
+ return 0;
+ }
+
+ reg = fdt_getprop(hw_config_dtb, node, "reg", &len);
+ if (reg == NULL) {
+ ERROR("FCONF failed to read 'reg' property\n");
+ return len;
+ }
+
+ err = fdt_get_reg_props_by_index(hw_config_dtb, node, 0,
+ (uintptr_t *)&pci_props.ecam_base,
+ (size_t *)&pci_props.size);
+ if (err < 0) {
+ ERROR("FCONF: Failed to read 'reg' property of 'pci' node\n");
+ return err;
+ }
+
+ parent = fdt_parent_offset(hw_config_dtb, node);
+ if (parent < 0) {
+ return -FDT_ERR_BADOFFSET;
+ }
+
+ parent_ac = fdt_address_cells(hw_config_dtb, parent);
+ ac = fdt_address_cells(hw_config_dtb, node);
+ sc = fdt_size_cells(hw_config_dtb, node);
+
+ entry_len = parent_ac + ac + sc;
+
+ ranges = fdt_getprop(hw_config_dtb, node, "ranges", &len);
+ if (ranges == NULL) {
+ ERROR("FCONF failed to read 'ranges' property\n");
+ return len;
+ }
+
+ /* 'ranges' length in 32-bit words */
+ len /= sizeof(uint32_t);
+ if ((len % entry_len) != 0) {
+ return -FDT_ERR_BADVALUE;
+ }
+
+ pci_props.num_ncoh_regions = (uint64_t)(len / entry_len);
+
+ if (pci_props.num_ncoh_regions > ARM_PCI_NUM_REGIONS) {
+ WARN("FCONF: 'ranges' reports more memory regions than supported\n");
+ pci_props.num_ncoh_regions = ARM_PCI_NUM_REGIONS;
+ }
+
+ for (unsigned int i = 0U; i < (unsigned int)pci_props.num_ncoh_regions; i++) {
+ unsigned int cell = i * entry_len + ac;
+
+ /* Read CPU address (parent-bus-address) space */
+ pci_props.ncoh_regions[i].base =
+ fdt_read_prop_cells(&ranges[cell], ac);
+
+ /* Read CPU address size */
+ pci_props.ncoh_regions[i].size =
+ fdt_read_prop_cells(&ranges[cell + parent_ac], sc);
+ }
+
+ return 0;
+}
+
FCONF_REGISTER_POPULATOR(HW_CONFIG, gicv3_config, fconf_populate_gicv3_config);
FCONF_REGISTER_POPULATOR(HW_CONFIG, topology, fconf_populate_topology);
FCONF_REGISTER_POPULATOR(HW_CONFIG, uart_config, fconf_populate_uart_config);
FCONF_REGISTER_POPULATOR(HW_CONFIG, cpu_timer, fconf_populate_cpu_timer);
FCONF_REGISTER_POPULATOR(HW_CONFIG, dram_layout, fconf_populate_dram_layout);
+FCONF_REGISTER_POPULATOR(HW_CONFIG, pci_props, fconf_populate_pci_props);
diff --git a/plat/arm/board/fvp/fdts/fvp_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_fw_config.dts
index 5d58731..a11c1de 100644
--- a/plat/arm/board/fvp/fdts/fvp_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_fw_config.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,6 +7,10 @@
#include <common/tbbr/tbbr_img_def.h>
#include <platform_def.h>
+/* DTB load addresses */
+#define TB_SOC_FW_ADDR (ARM_BL_RAM_BASE + 0x300)
+#define TOS_FW_ADDR (ARM_BL_RAM_BASE + 0x500)
+
/dts-v1/;
/ {
@@ -14,7 +18,7 @@
compatible = "fconf,dyn_cfg-dtb_registry";
tb_fw-config {
- load-address = <0x0 0x4001300>;
+ load-address = <0x0 TB_SOC_FW_ADDR>;
max-size = <0x1800>;
id = <TB_FW_CONFIG_ID>;
};
@@ -33,7 +37,7 @@
* is loaded at base of DRAM.
*/
soc_fw-config {
- load-address = <0x0 0x04001300>;
+ load-address = <0x0 TB_SOC_FW_ADDR>;
max-size = <0x200>;
id = <SOC_FW_CONFIG_ID>;
};
@@ -41,8 +45,7 @@
/* If required, SPD should enable loading of trusted OS fw config */
#if defined(SPD_tspd) || defined(SPD_spmd)
tos_fw-config {
-
- load-address = <0x0 0x04001500>;
+ load-address = <0x0 TOS_FW_ADDR>;
#if ENABLE_RME
secondary-load-address = <0x0 0x7e00000>;
#endif /* ENABLE_RME */
@@ -50,7 +53,6 @@
id = <TOS_FW_CONFIG_ID>;
};
#endif
-
nt_fw-config {
load-address = <0x0 0x80000000>;
max-size = <0x200>;
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
index bf0e7f3..b62df1a 100644
--- a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
@@ -34,7 +34,7 @@
debug_name = "cactus-primary";
load_address = <0x7000000>;
vcpu_count = <8>;
- mem_size = <1048576>;
+ mem_size = <0x100000>;
/*
* Platform specific SiP SMC call handled at EL3. Used
* to pend an interrupt for testing purpose.
@@ -46,21 +46,21 @@
debug_name = "cactus-secondary";
load_address = <0x7100000>;
vcpu_count = <8>;
- mem_size = <1048576>;
+ mem_size = <0x100000>;
};
vm3 {
is_ffa_partition;
debug_name = "cactus-tertiary";
load_address = <0x7200000>;
vcpu_count = <1>;
- mem_size = <1048576>;
+ mem_size = <0x300000>;
};
vm4 {
is_ffa_partition;
debug_name = "ivy";
load_address = <0x7600000>;
vcpu_count = <1>;
- mem_size = <1048576>;
+ mem_size = <0x100000>;
};
};
diff --git a/plat/arm/board/fvp/fvp_bl2_setup.c b/plat/arm/board/fvp/fvp_bl2_setup.c
index 8dcdd62..90d9608 100644
--- a/plat/arm/board/fvp/fvp_bl2_setup.c
+++ b/plat/arm/board/fvp/fvp_bl2_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -30,21 +30,25 @@
ARM_PAS_SECURE,
ARM_PAS_REALM,
ARM_PAS_EL3_DRAM,
+#ifdef ARM_PAS_GPTS
ARM_PAS_GPTS,
- ARM_PAS_KERNEL_1
+#endif
+ ARM_PAS_KERNEL_1,
+ ARM_PAS_PCI_MEM_1,
+ ARM_PAS_PCI_MEM_2
};
static const arm_gpt_info_t arm_gpt_info = {
.pas_region_base = pas_regions,
.pas_region_count = (unsigned int)ARRAY_SIZE(pas_regions),
- .l0_base = (uintptr_t)ARM_L0_GPT_BASE,
- .l1_base = (uintptr_t)ARM_L1_GPT_BASE,
- .l0_size = (size_t)ARM_L0_GPT_SIZE,
- .l1_size = (size_t)ARM_L1_GPT_SIZE,
- .pps = GPCCR_PPS_64GB,
+ .l0_base = ARM_L0_GPT_BASE,
+ .l1_base = ARM_L1_GPT_BASE,
+ .l0_size = ARM_L0_GPT_SIZE,
+ .l1_size = ARM_L1_GPT_SIZE,
+ .pps = GPCCR_PPS_1TB,
.pgs = GPCCR_PGS_4K
};
-#endif
+#endif /* ENABLE_RME */
void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3)
{
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index bdc2cac..7d76814 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -34,12 +34,11 @@
#define FVP_GICV2 1
#define FVP_GICV3 2
-/* Defines for RMM Console*/
+/* Defines for RMM Console */
#define FVP_RMM_CONSOLE_BASE UL(0x1c0c0000)
#define FVP_RMM_CONSOLE_BAUD UL(115200)
#define FVP_RMM_CONSOLE_CLK_IN_HZ UL(14745600)
#define FVP_RMM_CONSOLE_NAME "pl011"
-
#define FVP_RMM_CONSOLE_COUNT UL(1)
/*******************************************************************************
@@ -53,7 +52,7 @@
#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \
DEVICE0_SIZE, \
- MT_DEVICE | MT_RW | MT_SECURE)
+ MT_DEVICE | MT_RW | EL3_PAS)
#define MAP_DEVICE1 MAP_REGION_FLAT(DEVICE1_BASE, \
DEVICE1_SIZE, \
@@ -591,11 +590,78 @@
return sum;
}
-
+/*
+ * Boot Manifest structure illustration, with two DRAM banks,
+ * a single console and one device memory with two PCIe device
+ * non-coherent address ranges.
+ *
+ * +--------------------------------------------------+
+ * | offset | field | comment |
+ * +--------+--------------------+--------------------+
+ * | 0 | version | 0x00000004 |
+ * +--------+--------------------+--------------------+
+ * | 4 | padding | 0x00000000 |
+ * +--------+--------------------+--------------------+
+ * | 8 | plat_data | NULL |
+ * +--------+--------------------+--------------------+
+ * | 16 | num_banks | |
+ * +--------+--------------------+ |
+ * | 24 | banks | plat_dram +--+
+ * +--------+--------------------+ | |
+ * | 32 | checksum | | |
+ * +--------+--------------------+--------------------+ |
+ * | 40 | num_consoles | | |
+ * +--------+--------------------+ | |
+ * | 48 | consoles | plat_console +--|--+
+ * +--------+--------------------+ | | |
+ * | 56 | checksum | | | |
+ * +--------+--------------------+--------------------+ | |
+ * | 64 | num_banks | | | |
+ * +--------+--------------------+ | | |
+ * | 72 | banks | plat_ncoh_region +--|--|--+
+ * +--------+--------------------+ | | | |
+ * | 80 | checksum | | | | |
+ * +--------+--------------------+--------------------+ | | |
+ * | 88 | num_banks | | | | |
+ * +--------+--------------------+ | | | |
+ * | 96 | banks | plat_coh_region | | | |
+ * +--------+--------------------+ | | | |
+ * | 104 | checksum | | | | |
+ * +--------+--------------------+--------------------+<-+ | |
+ * | 112 | base 0 | | | |
+ * +--------+--------------------+ mem_bank[0] | | |
+ * | 120 | size 0 | | | |
+ * +--------+--------------------+--------------------+ | |
+ * | 128 | base 1 | | | |
+ * +--------+--------------------+ mem_bank[1] | | |
+ * | 136 | size 1 | | | |
+ * +--------+--------------------+--------------------+<----+ |
+ * | 144 | base | | |
+ * +--------+--------------------+ | |
+ * | 152 | map_pages | | |
+ * +--------+--------------------+ | |
+ * | 160 | name | | |
+ * +--------+--------------------+ consoles[0] | |
+ * | 168 | clk_in_hz | | |
+ * +--------+--------------------+ | |
+ * | 176 | baud_rate | | |
+ * +--------+--------------------+ | |
+ * | 184 | flags | | |
+ * +--------+--------------------+--------------------+<-------+
+ * | 192 | base 0 | |
+ * +--------+--------------------+ ncoh_region[0] |
+ * | 200 | size 0 | |
+ * +--------+--------------------+--------------------+
+ * | 208 | base 1 | |
+ * +--------+--------------------+ ncoh_region[1] |
+ * | 216 | size 1 | |
+ * +--------+--------------------+--------------------+
+ */
int plat_rmmd_load_manifest(struct rmm_manifest *manifest)
{
uint64_t checksum, num_banks, num_consoles;
- struct ns_dram_bank *bank_ptr;
+ uint64_t num_ncoh_regions, num_coh_regions;
+ struct memory_bank *bank_ptr, *ncoh_region_ptr;
struct console_info *console_ptr;
assert(manifest != NULL);
@@ -607,71 +673,45 @@
/* Set number of consoles */
num_consoles = FVP_RMM_CONSOLE_COUNT;
+ /* Set number of device non-coherent address ranges based on DT */
+ num_ncoh_regions = FCONF_GET_PROPERTY(hw_config, pci_props, num_ncoh_regions);
+
manifest->version = RMMD_MANIFEST_VERSION;
manifest->padding = 0U; /* RES0 */
- manifest->plat_data = (uintptr_t)NULL;
+ manifest->plat_data = 0UL;
manifest->plat_dram.num_banks = num_banks;
manifest->plat_console.num_consoles = num_consoles;
+ manifest->plat_ncoh_region.num_banks = num_ncoh_regions;
- /*
- * Boot Manifest structure illustration, with two dram banks and
- * a single console.
- *
- * +----------------------------------------+
- * | offset | field | comment |
- * +--------+----------------+--------------+
- * | 0 | version | 0x00000003 |
- * +--------+----------------+--------------+
- * | 4 | padding | 0x00000000 |
- * +--------+----------------+--------------+
- * | 8 | plat_data | NULL |
- * +--------+----------------+--------------+
- * | 16 | num_banks | |
- * +--------+----------------+ |
- * | 24 | banks | plat_dram |
- * +--------+----------------+ |
- * | 32 | checksum | |
- * +--------+----------------+--------------+
- * | 40 | num_consoles | |
- * +--------+----------------+ |
- * | 48 | consoles | plat_console |
- * +--------+----------------+ |
- * | 56 | checksum | |
- * +--------+----------------+--------------+
- * | 64 | base 0 | |
- * +--------+----------------+ bank[0] |
- * | 72 | size 0 | |
- * +--------+----------------+--------------+
- * | 80 | base 1 | |
- * +--------+----------------+ bank[1] |
- * | 88 | size 1 | |
- * +--------+----------------+--------------+
- * | 96 | base | |
- * +--------+----------------+ |
- * | 104 | map_pages | |
- * +--------+----------------+ |
- * | 112 | name | |
- * +--------+----------------+ consoles[0] |
- * | 120 | clk_in_hz | |
- * +--------+----------------+ |
- * | 128 | baud_rate | |
- * +--------+----------------+ |
- * | 136 | flags | |
- * +--------+----------------+--------------+
- */
+ /* FVP does not support device coherent address ranges */
+ num_coh_regions = 0UL;
+ manifest->plat_coh_region.num_banks = num_coh_regions;
+ manifest->plat_coh_region.banks = NULL;
+ manifest->plat_coh_region.checksum = 0UL;
- bank_ptr = (struct ns_dram_bank *)
- (((uintptr_t)manifest) + sizeof(*manifest));
+ bank_ptr = (struct memory_bank *)
+ (((uintptr_t)manifest) + sizeof(struct rmm_manifest));
console_ptr = (struct console_info *)
- ((uintptr_t)bank_ptr + (num_banks * sizeof(*bank_ptr)));
-
+ ((uintptr_t)bank_ptr + (num_banks *
+ sizeof(struct memory_bank)));
+ ncoh_region_ptr = (struct memory_bank *)
+ ((uintptr_t)console_ptr + (num_consoles *
+ sizeof(struct console_info)));
manifest->plat_dram.banks = bank_ptr;
manifest->plat_console.consoles = console_ptr;
+ manifest->plat_ncoh_region.banks = ncoh_region_ptr;
/* Ensure the manifest is not larger than the shared buffer */
assert((sizeof(struct rmm_manifest) +
- (sizeof(struct console_info) * manifest->plat_console.num_consoles) +
- (sizeof(struct ns_dram_bank) * manifest->plat_dram.num_banks)) <= ARM_EL3_RMM_SHARED_SIZE);
+ (sizeof(struct memory_bank) *
+ manifest->plat_dram.num_banks) +
+ (sizeof(struct console_info) *
+ manifest->plat_console.num_consoles) +
+ (sizeof(struct memory_bank) *
+ manifest->plat_ncoh_region.num_banks) +
+ (sizeof(struct memory_bank) *
+ manifest->plat_coh_region.num_banks))
+ <= ARM_EL3_RMM_SHARED_SIZE);
/* Calculate checksum of plat_dram structure */
checksum = num_banks + (uint64_t)bank_ptr;
@@ -683,31 +723,56 @@
}
/* Update checksum */
- checksum += checksum_calc((uint64_t *)bank_ptr, sizeof(struct ns_dram_bank) * num_banks);
+ checksum += checksum_calc((uint64_t *)bank_ptr, sizeof(struct memory_bank) * num_banks);
/* Checksum must be 0 */
manifest->plat_dram.checksum = ~checksum + 1UL;
- /* Calculate the checksum of the plat_consoles structure */
+ /* Calculate the checksum of plat_consoles structure */
checksum = num_consoles + (uint64_t)console_ptr;
/* Zero out the console info struct */
- (void)memset((void *)console_ptr, '\0', sizeof(struct console_info) * num_consoles);
+ (void)memset((void *)console_ptr, '\0',
+ sizeof(struct console_info) * num_consoles);
console_ptr[0].base = FVP_RMM_CONSOLE_BASE;
console_ptr[0].map_pages = 1UL;
console_ptr[0].clk_in_hz = FVP_RMM_CONSOLE_CLK_IN_HZ;
console_ptr[0].baud_rate = FVP_RMM_CONSOLE_BAUD;
- (void)strlcpy(console_ptr[0].name, FVP_RMM_CONSOLE_NAME, RMM_CONSOLE_MAX_NAME_LEN - 1UL);
+ (void)strlcpy(console_ptr[0].name, FVP_RMM_CONSOLE_NAME,
+ RMM_CONSOLE_MAX_NAME_LEN - 1UL);
/* Update checksum */
checksum += checksum_calc((uint64_t *)console_ptr,
sizeof(struct console_info) * num_consoles);
-
/* Checksum must be 0 */
manifest->plat_console.checksum = ~checksum + 1UL;
+ /*
+ * Calculate the checksum of device non-coherent address ranges
+ * info structure
+ */
+ checksum = num_ncoh_regions + (uint64_t)ncoh_region_ptr;
+
+ /* Zero out the PCIe region info struct */
+ (void)memset((void *)ncoh_region_ptr, 0,
+ sizeof(struct memory_bank) * num_ncoh_regions);
+
+ for (unsigned long i = 0UL; i < num_ncoh_regions; i++) {
+ ncoh_region_ptr[i].base =
+ FCONF_GET_PROPERTY(hw_config, pci_props, ncoh_regions[i].base);
+ ncoh_region_ptr[i].size =
+ FCONF_GET_PROPERTY(hw_config, pci_props, ncoh_regions[i].size);
+ }
+
+ /* Update checksum */
+ checksum += checksum_calc((uint64_t *)ncoh_region_ptr,
+ sizeof(struct memory_bank) * num_ncoh_regions);
+
+ /* Checksum must be 0 */
+ manifest->plat_ncoh_region.checksum = ~checksum + 1UL;
+
return 0;
}
#endif /* ENABLE_RME */
diff --git a/plat/arm/board/fvp/fvp_drtm_stub.c b/plat/arm/board/fvp/fvp_drtm_stub.c
index e2bc516..238febd 100644
--- a/plat/arm/board/fvp/fvp_drtm_stub.c
+++ b/plat/arm/board/fvp/fvp_drtm_stub.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -33,3 +33,13 @@
{
return 0ULL;
}
+
+uint64_t plat_drtm_get_acpi_tables_region_size(void)
+{
+ return 0ULL;
+}
+
+uint64_t plat_drtm_get_dlme_img_auth_features(void)
+{
+ return 0ULL;
+}
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index 80dfd2a..2a0bb93 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -295,28 +295,22 @@
/*******************************************************************************
* FVP handlers to shutdown/reboot the system
******************************************************************************/
-static void __dead2 fvp_system_off(void)
+static void fvp_system_off(void)
{
/* Write the System Configuration Control Register */
mmio_write_32(V2M_SYSREGS_BASE + V2M_SYS_CFGCTRL,
V2M_CFGCTRL_START |
V2M_CFGCTRL_RW |
V2M_CFGCTRL_FUNC(V2M_FUNC_SHUTDOWN));
- wfi();
- ERROR("FVP System Off: operation not handled.\n");
- panic();
}
-static void __dead2 fvp_system_reset(void)
+static void fvp_system_reset(void)
{
/* Write the System Configuration Control Register */
mmio_write_32(V2M_SYSREGS_BASE + V2M_SYS_CFGCTRL,
V2M_CFGCTRL_START |
V2M_CFGCTRL_RW |
V2M_CFGCTRL_FUNC(V2M_FUNC_REBOOT));
- wfi();
- ERROR("FVP System Reset: operation not handled.\n");
- panic();
}
static int fvp_node_hw_state(u_register_t target_cpu,
diff --git a/plat/arm/board/fvp/include/fconf_hw_config_getter.h b/plat/arm/board/fvp/include/fconf_hw_config_getter.h
index b7a1247..351f13d 100644
--- a/plat/arm/board/fvp/include/fconf_hw_config_getter.h
+++ b/plat/arm/board/fvp/include/fconf_hw_config_getter.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -18,6 +18,7 @@
#define hw_config__uart_serial_config_getter(prop) uart_serial_config.prop
#define hw_config__cpu_timer_getter(prop) cpu_timer.prop
#define hw_config__dram_layout_getter(prop) dram_layout.prop
+#define hw_config__pci_props_getter(prop) pci_props.prop
struct gicv3_config_t {
uint64_t gicd_base;
@@ -40,21 +41,30 @@
uint32_t clock_freq;
};
-struct ns_dram_layout {
+struct dram_layout_t {
uint64_t num_banks;
- struct ns_dram_bank dram_bank[ARM_DRAM_NUM_BANKS];
+ struct memory_bank dram_bank[ARM_DRAM_NUM_BANKS];
};
+struct pci_props_t {
+ uint64_t ecam_base;
+ uint64_t size;
+ uint64_t num_ncoh_regions;
+ struct memory_bank ncoh_regions[ARM_PCI_NUM_REGIONS];
+};
+
int fconf_populate_gicv3_config(uintptr_t config);
int fconf_populate_topology(uintptr_t config);
int fconf_populate_uart_config(uintptr_t config);
int fconf_populate_cpu_timer(uintptr_t config);
int fconf_populate_dram_layout(uintptr_t config);
+int fconf_populate_pci_props(uintptr_t config);
extern struct gicv3_config_t gicv3_config;
extern struct hw_topology_t soc_topology;
extern struct uart_serial_config_t uart_serial_config;
extern struct cpu_timer_t cpu_timer;
-extern struct ns_dram_layout dram_layout;
+extern struct dram_layout_t dram_layout;
+extern struct pci_props_t pci_props;
#endif /* FCONF_HW_CONFIG_GETTER_H */
diff --git a/plat/arm/board/fvp/include/fvp_pas_def.h b/plat/arm/board/fvp/include/fvp_pas_def.h
index 4684387..6b97286 100644
--- a/plat/arm/board/fvp/include/fvp_pas_def.h
+++ b/plat/arm/board/fvp/include/fvp_pas_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2024, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2025, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -17,34 +17,37 @@
* The PA space is initially mapped in the GPT as follows:
*
* ============================================================================
- * Base Addr| Size |L? GPT|PAS |Content |Comment
+ * Base Addr | Size |L? GPT|PAS |Content |Comment
* ============================================================================
- * 0GB | 1GB |L0 GPT|ANY |TBROM (EL3 code) |Fixed mapping
- * | | | |TSRAM (EL3 data) |
- * 00000000 | | | |IO (incl.UARTs & GIC) |
+ * 0GB | 1GB |L0 GPT|ANY |TBROM (EL3 code) |Fixed mapping
+ * | | | |TSRAM (EL3 data) |
+ * 00000000 | 40000000 | | |IO (incl.UARTs & GIC) |
* ----------------------------------------------------------------------------
- * 1GB | 1GB |L0 GPT|ANY |IO |Fixed mapping
- * 40000000 | | | | |
+ * 1GB | 1GB |L0 GPT|ANY |IO |Fixed mapping
+ * 40000000 | 40000000 | | | |
* ----------------------------------------------------------------------------
- * 2GB |2GB-64MB |L1 GPT|NS |DRAM (NS Kernel) |Use T.Descrip
- * 80000000 | | | | |
+ * 1GB+256MB | 256MB |L1 GPT|NS |PCI Memory Region 1 |Use T.Descrip
+ * 50000000 | 10000000 | | | |
* ----------------------------------------------------------------------------
- * 4GB-64MB |64MB-32MB-4MB|L1 GPT|SECURE|DRAM TZC |Use T.Descrip
- * FC000000 | | | | |
+ * 2GB | 2GB-64MB |L1 GPT|NS |DRAM (NS Kernel) |Use T.Descrip
+ * 80000000 | 7C000000 | | | |
* ----------------------------------------------------------------------------
- * 4GB-32MB | | | | |
- * -3MB-1MB |32MB |L1 GPT|REALM |RMM |Use T.Descrip
- * FDC00000 | | | | |
+ * 4GB-64MB |64MB-32MB-4MB|L1 GPT|SECURE|DRAM TZC |Use T.Descrip
+ * FC000000 | 1C00000 | | | |
* ----------------------------------------------------------------------------
- * 4GB-3MB | | | | |
- * -1MB |3MB |L1 GPT|ROOT |EL3 DRAM data |Use T.Descrip
- * FFC00000 | | | | |
+ * 4GB-32MB | | | | |
+ * -3MB-1MB | 32MB |L1 GPT|REALM |RMM |Use T.Descrip
+ * FDC00000 | 2000000 | | | |
* ----------------------------------------------------------------------------
- * 4GB-1MB |1MB |L1 GPT|ROOT |DRAM (L1 GPTs, SCP TZC) |Fixed mapping
- * FFF00000 | | | | |
+ * 4GB-3MB | | | | |
+ * -1MB | 4MB |L1 GPT|ROOT |EL3 DRAM data, L1 GPTs, |Use T.Descrip
+ * FFC00000 | 400000 | | |SCP TZC |
* ----------------------------------------------------------------------------
- * 34GB |2GB |L1 GPT|NS |DRAM (NS Kernel) |Use T.Descrip
- * 880000000| | | | |
+ * 34GB | 2GB |L1 GPT|NS |DRAM (NS Kernel) |Use T.Descrip
+ * 880000000 | 80000000 | | | |
+ * ----------------------------------------------------------------------------
+ * 256GB | 3GB |L1 GPT|NS |PCI Memory Region 2 |Use T.Descrip
+ * 4000000000| C0000000 | | |(first 3GB only) |
* ============================================================================
*
* - 4KB of L0 GPT reside in TSRAM, on top of the CONFIG section.
@@ -61,7 +64,7 @@
/* Device memory 0 to 2GB */
#define ARM_PAS_1_BASE (U(0))
-#define ARM_PAS_1_SIZE ((ULL(1) << 31)) /* 2GB */
+#define ARM_PAS_1_SIZE (SZ_2G) /* 2GB */
/* NS memory 2GB to (end - 64MB) */
#define ARM_PAS_2_BASE (ARM_PAS_1_BASE + ARM_PAS_1_SIZE)
@@ -77,7 +80,7 @@
/* NS memory 2GB */
#define ARM_PAS_4_BASE ARM_DRAM2_BASE
-#define ARM_PAS_4_SIZE ((ULL(1) << 31)) /* 2GB */
+#define ARM_PAS_4_SIZE (SZ_2G) /* 2GB */
#define ARM_PAS_GPI_ANY MAP_GPT_REGION(ARM_PAS_1_BASE, \
ARM_PAS_1_SIZE, \
@@ -94,6 +97,14 @@
#define ARM_PAS_KERNEL_1 GPT_MAP_REGION_GRANULE(ARM_PAS_4_BASE, \
ARM_PAS_4_SIZE, \
GPT_GPI_NS)
+
+#define ARM_PAS_PCI_MEM_1 GPT_MAP_REGION_GRANULE(PLAT_ARM_PCI_MEM_1_BASE, \
+ PLAT_ARM_PCI_MEM_1_SIZE, \
+ GPT_GPI_NS)
+
+#define ARM_PAS_PCI_MEM_2 GPT_MAP_REGION_GRANULE(PLAT_ARM_PCI_MEM_2_BASE, \
+ PLAT_ARM_PCI_MEM_2_SIZE, \
+ GPT_GPI_NS)
/*
* REALM and Shared area share the same PAS, so consider them a single
* PAS region to configure in GPT.
@@ -102,7 +113,8 @@
(ARM_PAS_SHARED_SIZE + \
ARM_REALM_SIZE), \
GPT_GPI_REALM)
-
+/* Check if the EL3 TZC DRAM is contiguous with L1 GPT region. */
+#if (ARM_L1_GPT_BASE != (ARM_EL3_TZC_DRAM1_BASE + ARM_EL3_TZC_DRAM1_SIZE))
#define ARM_PAS_EL3_DRAM GPT_MAP_REGION_GRANULE(ARM_EL3_TZC_DRAM1_BASE, \
ARM_EL3_TZC_DRAM1_SIZE, \
GPT_GPI_ROOT)
@@ -110,6 +122,13 @@
#define ARM_PAS_GPTS GPT_MAP_REGION_GRANULE(ARM_L1_GPT_BASE, \
ARM_L1_GPT_SIZE, \
GPT_GPI_ROOT)
+#else
+/* Contiguous ROOT region */
+#define ARM_PAS_EL3_DRAM GPT_MAP_REGION_GRANULE(ARM_EL3_TZC_DRAM1_BASE, \
+ ARM_EL3_TZC_DRAM1_SIZE + \
+ ARM_L1_GPT_SIZE, \
+ GPT_GPI_ROOT)
+#endif
/* GPT Configuration options */
#define PLATFORM_L0GPTSZ GPCCR_L0GPTSZ_30BITS
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index df4be8f..f5be8f2 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -54,7 +54,10 @@
#if ENABLE_RME
#define PLAT_ARM_RMM_BASE (RMM_BASE)
#define PLAT_ARM_RMM_SIZE (RMM_LIMIT - RMM_BASE)
-#endif
+
+/* Protected physical address size */
+#define PLAT_ARM_PPS (SZ_1T)
+#endif /* ENABLE_RME */
/*
* Max size of SPMC is 2MB for fvp. With SPMD enabled this value corresponds to
@@ -65,7 +68,7 @@
#define PLAT_ARM_SPMC_SIZE UL(0x200000) /* 2 MB */
#endif
-/* virtual address used by dynamic mem_protect for chunk_base */
+/* Virtual address used by dynamic mem_protect for chunk_base */
#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000)
/* No SCP in FVP */
@@ -399,11 +402,22 @@
#define PLAT_ARM_CLUSTER_TO_CCN_ID_MAP 1, 5, 7, 11
/* System timer related constants */
-#define PLAT_ARM_NSTIMER_FRAME_ID U(1)
+#define PLAT_ARM_NSTIMER_FRAME_ID U(1)
/* Mailbox base address */
#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE
+/* PCIe memory region 1 (Base Platform RevC only) */
+#define PLAT_ARM_PCI_MEM_1_BASE (ULL(0x50000000))
+#define PLAT_ARM_PCI_MEM_1_SIZE (SZ_256M) /* 256MB */
+
+/*
+ * PCIe memory region 2 (Base Platform RevC only)
+ * The full size of the second PCI memory region is 256GB
+ * but for now we only allocate the L1 GPTs for the first 3GB.
+ */
+#define PLAT_ARM_PCI_MEM_2_BASE (ULL(0x4000000000))
+#define PLAT_ARM_PCI_MEM_2_SIZE (3 * SZ_1G) /* 3GB */
/* TrustZone controller related constants
*
diff --git a/plat/arm/board/fvp/jmptbl_mbedtls_psa.i b/plat/arm/board/fvp/jmptbl_mbedtls_psa.i
new file mode 100644
index 0000000..4eb707b
--- /dev/null
+++ b/plat/arm/board/fvp/jmptbl_mbedtls_psa.i
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2025, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# Platform-specific ROMLIB MbedTLS PSA Crypto functions can be added here.
+# During the build process, this file is appended to jmptbl.i
+# if MbedTLS support is required and PSA Crypto is supported.
+#
+# Format:
+# lib function [patch]
+# Example:
+# mbedtls psa_crypto_init
+
+mbedtls mbedtls_pk_get_psa_attributes
+mbedtls mbedtls_pk_import_into_psa
+mbedtls psa_crypto_init
+mbedtls psa_destroy_key
+mbedtls psa_verify_message
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index ce06146..7bd2a1d 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -29,9 +29,13 @@
endif
# fdts is wrong otherwise
-# Size (in kilobytes) of the Trusted SRAM region to utilize when building for
-# the FVP platform. This option defaults to 256.
+# Size (in kilobytes) of the Trusted SRAM region to utilize when building for
+# the FVP platform.
+ifeq (${ENABLE_RME},1)
+FVP_TRUSTED_SRAM_SIZE := 384
+else
FVP_TRUSTED_SRAM_SIZE := 256
+endif
# Macro to enable helpers for running SPM tests. Disabled by default.
PLAT_TEST_SPM := 0
@@ -206,7 +210,6 @@
lib/cpus/aarch64/cortex_a715.S \
lib/cpus/aarch64/cortex_a720.S \
lib/cpus/aarch64/cortex_a720_ae.S \
- lib/cpus/aarch64/neoverse_n_common.S \
lib/cpus/aarch64/neoverse_n1.S \
lib/cpus/aarch64/neoverse_n2.S \
lib/cpus/aarch64/neoverse_v1.S \
@@ -222,7 +225,8 @@
#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 \
+ FVP_CPU_LIBS += lib/cpus/aarch64/cortex_a320.S \
+ lib/cpus/aarch64/cortex_a510.S \
lib/cpus/aarch64/cortex_a520.S \
lib/cpus/aarch64/cortex_a725.S \
lib/cpus/aarch64/cortex_x1.S \
@@ -235,11 +239,12 @@
#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 \
- lib/cpus/aarch64/cortex_gelas.S \
+ # travis/gelas need these
+ FEAT_PABANDON := 1
+ ERRATA_SME_POWER_DOWN := 1
+ FVP_CPU_LIBS += lib/cpus/aarch64/cortex_gelas.S \
lib/cpus/aarch64/nevis.S \
lib/cpus/aarch64/travis.S \
- lib/cpus/aarch64/cortex_arcadia.S \
lib/cpus/aarch64/cortex_alto.S
endif
@@ -362,6 +367,19 @@
FDT_SOURCES += ${FVP_HW_CONFIG_DTS}
$(eval FVP_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb,$(FVP_HW_CONFIG_DTS)))
+HW_CONFIG := ${FVP_HW_CONFIG}
+
+# Set default initrd base 128MiB offset of the default kernel address in FVP
+INITRD_BASE ?= 0x90000000
+
+# Kernel base address supports Linux kernels before v5.7
+# DTB base 1MiB before normal base kernel address in FVP (0x88000000)
+ifeq (${ARM_LINUX_KERNEL_AS_BL33},1)
+ PRELOADED_BL33_BASE ?= 0x80080000
+ ifeq (${RESET_TO_BL31},1)
+ ARM_PRELOADED_DTB_BASE ?= 0x87F00000
+ endif
+endif
ifeq (${TRANSFER_LIST}, 0)
FDT_SOURCES += $(addprefix plat/arm/board/fvp/fdts/, \
@@ -414,7 +432,6 @@
include lib/transfer_list/transfer_list.mk
ifeq ($(RESET_TO_BL31), 1)
-HW_CONFIG := ${FVP_HW_CONFIG}
FW_HANDOFF_SIZE := 20000
TRANSFER_LIST_DTB_OFFSET := 0x20
diff --git a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
index 27ea7f7..d8d60ef 100644
--- a/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
+++ b/plat/arm/board/n1sdp/n1sdp_bl31_setup.c
@@ -17,6 +17,8 @@
#include "n1sdp_private.h"
#include <platform_def.h>
+#define RT_OWNER 0
+
/*
* Platform information structure stored in SDS.
* This structure holds information about platform's DDR
@@ -44,12 +46,16 @@
};
static struct gic600_multichip_data n1sdp_multichip_data __init = {
- .rt_owner_base = PLAT_ARM_GICD_BASE,
- .rt_owner = 0,
+ .base_addrs = {
+ PLAT_ARM_GICD_BASE
+ },
+ .rt_owner = RT_OWNER,
.chip_count = 1,
.chip_addrs = {
- PLAT_ARM_GICD_BASE >> 16,
- PLAT_ARM_GICD_BASE >> 16
+ [RT_OWNER] = {
+ PLAT_ARM_GICD_BASE >> 16,
+ PLAT_ARM_GICD_BASE >> 16
+ }
},
.spi_ids = {
{PLAT_ARM_GICD_BASE, 32, 511},
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 7fa2b77..4936344 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
@@ -507,8 +507,6 @@
#define ARM_L0_GPT_BASE NRD_CSS_SHARED_SRAM_SIZE - \
ARM_L0_GPT_SIZE
-#define ARM_L0_GPT_LIMIT (ARM_L0_GPT_BASE + ARM_L0_GPT_SIZE)
-
/*******************************************************************************
* Arm shared RAM specifics
******************************************************************************/
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 d3038ec..2dd8b45 100644
--- a/plat/arm/board/neoverse_rd/common/nrd_bl31_setup.c
+++ b/plat/arm/board/neoverse_rd/common/nrd_bl31_setup.c
@@ -154,6 +154,13 @@
nrd_plat_info.config_id = plat_arm_nrd_get_config_id();
nrd_plat_info.multi_chip_mode = plat_arm_nrd_get_multi_chip_mode();
+#if RESET_TO_BL31
+#if (ARM_ARCH_MAJOR > 7) || defined(ARMV7_SUPPORTS_GENERIC_TIMER)
+ /* Set the counter frequency for the generic timer */
+ write_cntfrq_el0(plat_get_syscnt_freq2());
+#endif
+#endif /* RESET_TO_BL31 */
+
/* Initialize generic timer */
generic_delay_timer_init();
diff --git a/plat/arm/board/neoverse_rd/common/ras/nrd_ras_cpu.c b/plat/arm/board/neoverse_rd/common/ras/nrd_ras_cpu.c
index dcee92c..19fb796 100644
--- a/plat/arm/board/neoverse_rd/common/ras/nrd_ras_cpu.c
+++ b/plat/arm/board/neoverse_rd/common/ras/nrd_ras_cpu.c
@@ -129,8 +129,7 @@
cpu_info->ErrCtxEl3Reg[0] = read_ctx_reg(get_el3state_ctx(ctx),
CTX_ELR_EL3);
- cpu_info->ErrCtxEl3Reg[1] = read_ctx_reg(get_el3state_ctx(ctx),
- CTX_ESR_EL3);
+ cpu_info->ErrCtxEl3Reg[1] = read_esr_el3();
cpu_info->ErrCtxEl3Reg[2] = read_far_el3();
cpu_info->ErrCtxEl3Reg[4] = read_mair_el3();
cpu_info->ErrCtxEl3Reg[5] = read_sctlr_el3();
diff --git a/plat/arm/board/neoverse_rd/platform/rdn1edge/rdn1edge_plat.c b/plat/arm/board/neoverse_rd/platform/rdn1edge/rdn1edge_plat.c
index ccabe22..5cbdd5f 100644
--- a/plat/arm/board/neoverse_rd/platform/rdn1edge/rdn1edge_plat.c
+++ b/plat/arm/board/neoverse_rd/platform/rdn1edge/rdn1edge_plat.c
@@ -11,6 +11,8 @@
#include <nrd_plat.h>
+#define RT_OWNER 0
+
#if defined(IMAGE_BL31)
static const mmap_region_t rdn1edge_dynamic_mmap[] = {
NRD_CSS_SHARED_RAM_MMAP(1),
@@ -19,12 +21,17 @@
};
static struct gic600_multichip_data rdn1e1_multichip_data __init = {
- .rt_owner_base = PLAT_ARM_GICD_BASE,
- .rt_owner = 0,
+ .base_addrs = {
+ PLAT_ARM_GICD_BASE
+ },
+ .rt_owner = RT_OWNER,
.chip_count = NRD_CHIP_COUNT,
.chip_addrs = {
- PLAT_ARM_GICD_BASE >> 16,
- (PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16
+ [RT_OWNER] = {
+ PLAT_ARM_GICD_BASE >> 16,
+ (PLAT_ARM_GICD_BASE
+ + NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16
+ }
},
.spi_ids = {
{PLAT_ARM_GICD_BASE,
diff --git a/plat/arm/board/neoverse_rd/platform/rdn2/rdn2_plat.c b/plat/arm/board/neoverse_rd/platform/rdn2/rdn2_plat.c
index b1046d6..cf820b8 100644
--- a/plat/arm/board/neoverse_rd/platform/rdn2/rdn2_plat.c
+++ b/plat/arm/board/neoverse_rd/platform/rdn2/rdn2_plat.c
@@ -13,6 +13,12 @@
#include <nrd_plat.h>
#include <rdn2_ras.h>
+#define RT_OWNER 0
+#define A4SID_CHIP_0 0x0
+#define A4SID_CHIP_1 0x1
+#define A4SID_CHIP_2 0x2
+#define A4SID_CHIP_3 0x3
+
#if defined(IMAGE_BL31)
#if (NRD_PLATFORM_VARIANT == 2)
static const mmap_region_t rdn2mc_dynamic_mmap[] = {
@@ -33,19 +39,50 @@
#if (NRD_PLATFORM_VARIANT == 2)
static struct gic600_multichip_data rdn2mc_multichip_data __init = {
- .rt_owner_base = PLAT_ARM_GICD_BASE,
- .rt_owner = 0,
+ .base_addrs = {
+ PLAT_ARM_GICD_BASE,
+#if NRD_CHIP_COUNT > 1
+ PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(1),
+#endif
+#if NRD_CHIP_COUNT > 2
+ PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(2),
+#endif
+#if NRD_CHIP_COUNT > 3
+ PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(3),
+#endif
+ },
+ .rt_owner = RT_OWNER,
.chip_count = NRD_CHIP_COUNT,
.chip_addrs = {
- PLAT_ARM_GICD_BASE >> 16,
+ {
+ A4SID_CHIP_0,
+ A4SID_CHIP_1,
+ A4SID_CHIP_2,
+ A4SID_CHIP_3
+ },
#if NRD_CHIP_COUNT > 1
- (PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
+ {
+ A4SID_CHIP_0,
+ A4SID_CHIP_1,
+ A4SID_CHIP_2,
+ A4SID_CHIP_3
+ },
#endif
#if NRD_CHIP_COUNT > 2
- (PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
+ {
+ A4SID_CHIP_0,
+ A4SID_CHIP_1,
+ A4SID_CHIP_2,
+ A4SID_CHIP_3
+ },
#endif
#if NRD_CHIP_COUNT > 3
- (PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
+ {
+ A4SID_CHIP_0,
+ A4SID_CHIP_1,
+ A4SID_CHIP_2,
+ A4SID_CHIP_3
+ }
#endif
},
.spi_ids = {
diff --git a/plat/arm/board/neoverse_rd/platform/rdv1mc/rdv1mc_plat.c b/plat/arm/board/neoverse_rd/platform/rdv1mc/rdv1mc_plat.c
index 5713cb9..0a40762 100644
--- a/plat/arm/board/neoverse_rd/platform/rdv1mc/rdv1mc_plat.c
+++ b/plat/arm/board/neoverse_rd/platform/rdv1mc/rdv1mc_plat.c
@@ -11,6 +11,8 @@
#include <nrd_plat.h>
+#define RT_OWNER 0
+
#if defined(IMAGE_BL31)
static const mmap_region_t rdv1mc_dynamic_mmap[] = {
NRD_CSS_SHARED_RAM_MMAP(1),
@@ -29,18 +31,25 @@
};
static struct gic600_multichip_data rdv1mc_multichip_data __init = {
- .rt_owner_base = PLAT_ARM_GICD_BASE,
- .rt_owner = 0,
+ .base_addrs = {
+ PLAT_ARM_GICD_BASE
+ },
+ .rt_owner = RT_OWNER,
.chip_count = NRD_CHIP_COUNT,
.chip_addrs = {
- PLAT_ARM_GICD_BASE >> 16,
- (PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
+ [RT_OWNER] = {
+ PLAT_ARM_GICD_BASE >> 16,
+ (PLAT_ARM_GICD_BASE
+ + NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
#if (NRD_CHIP_COUNT > 2)
- (PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
+ (PLAT_ARM_GICD_BASE
+ + NRD_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
#endif
#if (NRD_CHIP_COUNT > 3)
- (PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
+ (PLAT_ARM_GICD_BASE
+ + NRD_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
#endif
+ }
},
.spi_ids = {
{PLAT_ARM_GICD_BASE,
diff --git a/plat/arm/board/neoverse_rd/platform/rdv3/include/platform_def.h b/plat/arm/board/neoverse_rd/platform/rdv3/include/platform_def.h
index b55dbe8..0d0db77 100644
--- a/plat/arm/board/neoverse_rd/platform/rdv3/include/platform_def.h
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/include/platform_def.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
*/
@@ -48,4 +48,7 @@
*/
#define PLAT_RSE_COMMS_PAYLOAD_MAX_SIZE UL(0x1000)
+/* Protected physical address size */
+#define PLAT_ARM_PPS (256 * SZ_1T)
+
#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/neoverse_rd/platform/rdv3/platform.mk b/plat/arm/board/neoverse_rd/platform/rdv3/platform.mk
index 49b7cc3..1ddd0e4 100644
--- a/plat/arm/board/neoverse_rd/platform/rdv3/platform.mk
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/platform.mk
@@ -51,7 +51,7 @@
endif
# RD-V3 uses MHUv3
-PLAT_MHU_VERSION := 3
+PLAT_MHU := MHUv3
include plat/arm/board/neoverse_rd/common/nrd-common.mk
include drivers/arm/rse/rse_comms.mk
@@ -144,7 +144,7 @@
${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
+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
@@ -169,4 +169,14 @@
# FEAT_SVE related flags
override SVE_VECTOR_LEN := 128
-override CTX_INCLUDE_SVE_REGS := 1
+
+override CTX_INCLUDE_SVE_REGS := 1
+
+# Enabling CTX_INCLUDE_SVE_REGS along with SPMD_SPM_AT_SEL2=1 is a invalid
+# combination and will lead to build failure, use them only when SPMD_SPM_AT_SEL2=0
+# In this combination its SPMC responsbility to save SVE regs.
+ifeq (${SPD},spmd)
+ifeq (${SPMD_SPM_AT_SEL2},1)
+override CTX_INCLUDE_SVE_REGS := 0
+endif
+endif
diff --git a/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl31_setup.c b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl31_setup.c
index a5d687e..e32e761 100644
--- a/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl31_setup.c
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl31_setup.c
@@ -15,6 +15,15 @@
#include <nrd_variant.h>
#include <rdv3_rse_comms.h>
+#define RT_OWNER 0
+
+/*
+ * Base addr of the frame that allocated by the platform
+ * intended for remote gic to local gic interrupt
+ * message communication
+ */
+#define NRD_RGIC2LGIC_MESSREG_HNI_BASE UL(0x5FFF0000)
+
#if (NRD_PLATFORM_VARIANT == 2)
static const mmap_region_t rdv3mc_dynamic_mmap[] = {
#if NRD_CHIP_COUNT > 1
@@ -32,19 +41,62 @@
};
static struct gic600_multichip_data rdv3mc_multichip_data __init = {
- .rt_owner_base = PLAT_ARM_GICD_BASE,
- .rt_owner = 0,
+ .base_addrs = {
+ PLAT_ARM_GICD_BASE,
+#if NRD_CHIP_COUNT > 1
+ PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(1),
+#endif
+#if NRD_CHIP_COUNT > 2
+ PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(2),
+#endif
+#if NRD_CHIP_COUNT > 3
+ PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(3),
+#endif
+ },
+ .rt_owner = RT_OWNER,
.chip_count = NRD_CHIP_COUNT,
.chip_addrs = {
- PLAT_ARM_GICD_BASE >> 16,
+ {
+ NRD_RGIC2LGIC_MESSREG_HNI_BASE >> 16,
+ (NRD_RGIC2LGIC_MESSREG_HNI_BASE
+ + NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
+ (NRD_RGIC2LGIC_MESSREG_HNI_BASE
+ + NRD_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
+ (NRD_RGIC2LGIC_MESSREG_HNI_BASE
+ + NRD_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
+ },
#if NRD_CHIP_COUNT > 1
- (PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
+ {
+ NRD_RGIC2LGIC_MESSREG_HNI_BASE >> 16,
+ (NRD_RGIC2LGIC_MESSREG_HNI_BASE
+ + NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
+ (NRD_RGIC2LGIC_MESSREG_HNI_BASE
+ + NRD_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
+ (NRD_RGIC2LGIC_MESSREG_HNI_BASE
+ + NRD_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
+ },
#endif
#if NRD_CHIP_COUNT > 2
- (PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
+ {
+ NRD_RGIC2LGIC_MESSREG_HNI_BASE >> 16,
+ (NRD_RGIC2LGIC_MESSREG_HNI_BASE
+ + NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
+ (NRD_RGIC2LGIC_MESSREG_HNI_BASE
+ + NRD_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
+ (NRD_RGIC2LGIC_MESSREG_HNI_BASE
+ + NRD_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
+ },
#endif
#if NRD_CHIP_COUNT > 3
- (PLAT_ARM_GICD_BASE + NRD_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
+ {
+ NRD_RGIC2LGIC_MESSREG_HNI_BASE >> 16,
+ (NRD_RGIC2LGIC_MESSREG_HNI_BASE
+ + NRD_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
+ (NRD_RGIC2LGIC_MESSREG_HNI_BASE
+ + NRD_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
+ (NRD_RGIC2LGIC_MESSREG_HNI_BASE
+ + NRD_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
+ }
#endif
},
.spi_ids = {
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 3ef9681..364bce1 100644
--- a/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c
@@ -6,6 +6,7 @@
#include <common/debug.h>
#include <drivers/arm/gic600_multichip.h>
+#include <drivers/arm/mhu.h>
#include <drivers/arm/rse_comms.h>
#include <plat/arm/common/plat_arm.h>
#include <plat/common/platform.h>
@@ -64,7 +65,7 @@
int plat_rmmd_load_manifest(struct rmm_manifest *manifest)
{
uint64_t checksum, num_banks, num_consoles;
- struct ns_dram_bank *bank_ptr;
+ struct memory_bank *bank_ptr;
struct console_info *console_ptr;
assert(manifest != NULL);
@@ -129,7 +130,7 @@
* +--------+----------------+--------------+
*/
- bank_ptr = (struct ns_dram_bank *)
+ bank_ptr = (struct memory_bank *)
(((uintptr_t)manifest) + sizeof(*manifest));
console_ptr = (struct console_info *)
((uintptr_t)bank_ptr + (num_banks * sizeof(*bank_ptr)));
@@ -141,7 +142,7 @@
assert((sizeof(struct rmm_manifest) +
(sizeof(struct console_info) *
manifest->plat_console.num_consoles) +
- (sizeof(struct ns_dram_bank) * manifest->plat_dram.num_banks))
+ (sizeof(struct memory_bank) * manifest->plat_dram.num_banks))
<= ARM_EL3_RMM_SHARED_SIZE);
/* Calculate checksum of plat_dram structure */
@@ -156,7 +157,7 @@
/* Update checksum */
checksum += checksum_calc((uint64_t *)bank_ptr,
- sizeof(struct ns_dram_bank) * num_banks);
+ sizeof(struct memory_bank) * num_banks);
/* Checksum must be 0 */
manifest->plat_dram.checksum = ~checksum + 1UL;
@@ -188,15 +189,15 @@
int plat_rse_comms_init(void)
{
- uintptr_t snd_base, rcv_base;
+ struct mhu_addr mhu_addresses;
/* Get sender and receiver frames for AP-RSE communication */
- mhu_v3_get_secure_device_base(&snd_base, true);
- mhu_v3_get_secure_device_base(&rcv_base, false);
+ mhu_v3_get_secure_device_base(&mhu_addresses.sender_base, true);
+ mhu_v3_get_secure_device_base(&mhu_addresses.receiver_base, false);
VERBOSE("Initializing the rse_comms now\n");
/* Initialize the communication channel between AP and RSE */
- return rse_comms_init(snd_base, rcv_base);
+ return rse_mbx_init(&mhu_addresses);
}
int plat_spmd_handle_group0_interrupt(uint32_t intid)
diff --git a/plat/arm/board/tc/include/tc_rse_comms.h b/plat/arm/board/tc/include/tc_rse_comms.h
new file mode 100644
index 0000000..dc2000e
--- /dev/null
+++ b/plat/arm/board/tc/include/tc_rse_comms.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TC_RSE_COMMS_H
+#define TC_RSE_COMMS_H
+
+int plat_rse_comms_init(void);
+
+#endif /* TC_RSE_COMMS_H */
diff --git a/plat/arm/board/tc/nv_counter_test.c b/plat/arm/board/tc/nv_counter_test.c
index 9025569..94cba22 100644
--- a/plat/arm/board/tc/nv_counter_test.c
+++ b/plat/arm/board/tc/nv_counter_test.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,11 +7,11 @@
#include <stdint.h>
#include <stdio.h>
-#include <drivers/arm/rse_comms.h>
#include <plat/common/platform.h>
#include "rse_platform_api.h"
#include <platform_def.h>
+#include <tc_rse_comms.h>
int nv_counter_test(void)
{
@@ -20,7 +20,7 @@
uint32_t new_val;
uint32_t id;
- status = rse_comms_init(PLAT_RSE_AP_SND_MHU_BASE, PLAT_RSE_AP_RCV_MHU_BASE);
+ status = plat_rse_comms_init();
if (status != PSA_SUCCESS) {
printf("Failed to initialize RSE communication channel - psa_status = %d\n", status);
return -1;
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
index 21d7122..a056bc2 100644
--- a/plat/arm/board/tc/platform.mk
+++ b/plat/arm/board/tc/platform.mk
@@ -1,4 +1,4 @@
-# Copyright (c) 2021-2024, Arm Limited. All rights reserved.
+# Copyright (c) 2021-2025, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -32,10 +32,8 @@
ENABLE_TRBE_FOR_NS := 1
ENABLE_SYS_REG_TRACE_FOR_NS := 1
ENABLE_FEAT_AMU := 1
-ENABLE_AMU_FCONF := 1
ENABLE_AMU_AUXILIARY_COUNTERS := 1
ENABLE_MPMM := 1
-ENABLE_MPMM_FCONF := 1
ENABLE_FEAT_MTE2 := 2
ENABLE_SPE_FOR_NS := 3
ENABLE_FEAT_TCR2 := 3
@@ -112,9 +110,9 @@
# Specify MHU type based on platform
ifneq ($(filter ${TARGET_PLATFORM}, 2),)
- PLAT_MHU_VERSION := 2
+ PLAT_MHU := MHUv2
else
- PLAT_MHU_VERSION := 3
+ PLAT_MHU := MHUv3
endif
# Include GICv3 driver files
@@ -157,6 +155,9 @@
# CPU libraries for TARGET_PLATFORM=4
ifeq (${TARGET_PLATFORM}, 4)
+FEAT_PABANDON := 1
+# prevent CME related wakups
+ERRATA_SME_POWER_DOWN := 1
TC_CPU_SOURCES += lib/cpus/aarch64/cortex_gelas.S \
lib/cpus/aarch64/nevis.S \
lib/cpus/aarch64/travis.S
@@ -246,9 +247,12 @@
$(info Including rse_comms.mk)
include drivers/arm/rse/rse_comms.mk
-BL1_SOURCES += ${RSE_COMMS_SOURCES}
-BL2_SOURCES += ${RSE_COMMS_SOURCES}
+BL1_SOURCES += ${RSE_COMMS_SOURCES} \
+ plat/arm/board/tc/tc_rse_comms.c
+BL2_SOURCES += ${RSE_COMMS_SOURCES} \
+ plat/arm/board/tc/tc_rse_comms.c
BL31_SOURCES += ${RSE_COMMS_SOURCES} \
+ plat/arm/board/tc/tc_rse_comms.c \
lib/psa/rse_platform.c
# Include Measured Boot makefile before any Crypto library makefile.
diff --git a/plat/arm/board/tc/platform_test.mk b/plat/arm/board/tc/platform_test.mk
index 2ce6648..4afa30f 100644
--- a/plat/arm/board/tc/platform_test.mk
+++ b/plat/arm/board/tc/platform_test.mk
@@ -1,4 +1,4 @@
-# Copyright (c) 2022-2024, Arm Limited. All rights reserved.
+# Copyright (c) 2022-2025, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -9,7 +9,8 @@
include drivers/arm/rse/rse_comms.mk
# Test code.
- BL31_SOURCES += plat/arm/board/tc/nv_counter_test.c
+ BL31_SOURCES += plat/arm/board/tc/nv_counter_test.c \
+ plat/arm/board/tc/tc_rse_comms.c
# Code under testing.
BL31_SOURCES += lib/psa/rse_platform.c \
@@ -22,7 +23,8 @@
include drivers/arm/rse/rse_comms.mk
# Test code.
- BL31_SOURCES += plat/arm/board/tc/rotpk_test.c
+ BL31_SOURCES += plat/arm/board/tc/rotpk_test.c \
+ plat/arm/board/tc/tc_rse_comms.c
# Code under testing.
BL31_SOURCES += lib/psa/rse_platform.c \
@@ -75,6 +77,7 @@
${TC_BASE}/rse_ap_tests.c \
${TC_BASE}/rse_ap_testsuites.c \
${TC_BASE}/rse_ap_test_stubs.c \
+ ${TC_BASE}/tc_rse_comms.c \
$(TF_M_TESTS_PATH)/tests_reg/test/framework/test_framework.c \
$(MEASURED_BOOT_TESTS_PATH)/measured_boot_common.c \
$(MEASURED_BOOT_TESTS_PATH)/measured_boot_tests_common.c \
diff --git a/plat/arm/board/tc/rotpk_test.c b/plat/arm/board/tc/rotpk_test.c
index 2178f69..3d6c95d 100644
--- a/plat/arm/board/tc/rotpk_test.c
+++ b/plat/arm/board/tc/rotpk_test.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,10 +7,10 @@
#include <stdint.h>
#include <stdio.h>
-#include <drivers/arm/rse_comms.h>
#include <plat/common/platform.h>
#include <rse_platform_api.h>
#include <tc_plat.h>
+#include <tc_rse_comms.h>
static void print_hex(const char *key_id_name, size_t key_size, const uint8_t *key_buf)
{
@@ -33,9 +33,10 @@
{.key_id = RSE_BUILTIN_KEY_ID_HOST_CCA_ROTPK, .key_id_name = "CCA-ROTPK"}
};
- status = rse_comms_init(PLAT_RSE_AP_SND_MHU_BASE, PLAT_RSE_AP_RCV_MHU_BASE);
+ status = plat_rse_comms_init();
if (status != PSA_SUCCESS) {
- printf("Failed to initialize RSE communication channel - psa_status = %d\n", status);
+ printf("Failed to initialize RSE communication channel - psa_status = %d\n",
+ status);
return -1;
}
@@ -43,7 +44,8 @@
status = rse_platform_key_read(key_ids[i].key_id, key_buf,
sizeof(key_buf), &key_size);
if (status != PSA_SUCCESS) {
- printf("Failed to retrieve %s - psa_status = %d\n", key_ids[i].key_id_name, status);
+ printf("Failed to retrieve %s - psa_status = %d\n", key_ids[i].key_id_name,
+ status);
return -1;
}
print_hex(key_ids[i].key_id_name, key_size, key_buf);
diff --git a/plat/arm/board/tc/rse_ap_tests.c b/plat/arm/board/tc/rse_ap_tests.c
index 3ca628a..f8ee1c5 100644
--- a/plat/arm/board/tc/rse_ap_tests.c
+++ b/plat/arm/board/tc/rse_ap_tests.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Arm Ltd. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -10,9 +10,9 @@
#include <mbedtls_common.h>
#include <plat/common/platform.h>
#include <psa/crypto.h>
-#include <rse_comms.h>
#include "rse_ap_testsuites.h"
+#include <tc_rse_comms.h>
static struct test_suite_t test_suites[] = {
{.freg = register_testsuite_delegated_attest},
@@ -32,7 +32,7 @@
size_t i;
/* Initialize test environment. */
- rse_comms_init(PLAT_RSE_AP_SND_MHU_BASE, PLAT_RSE_AP_RCV_MHU_BASE);
+ plat_rse_comms_init();
mbedtls_init();
status = psa_crypto_init();
if (status != PSA_SUCCESS) {
diff --git a/plat/arm/board/tc/tc_bl1_dpe.c b/plat/arm/board/tc/tc_bl1_dpe.c
index de5702a..62e86f9 100644
--- a/plat/arm/board/tc/tc_bl1_dpe.c
+++ b/plat/arm/board/tc/tc_bl1_dpe.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -8,7 +8,6 @@
#include <common/debug.h>
#include <drivers/arm/css/sds.h>
-#include <drivers/arm/rse_comms.h>
#include <drivers/delay_timer.h>
#include <drivers/generic_delay_timer.h>
#include <drivers/measured_boot/metadata.h>
@@ -19,6 +18,7 @@
#include <tools_share/zero_oid.h>
#include "tc_dpe.h"
+#include <tc_rse_comms.h>
struct dpe_metadata tc_dpe_metadata[] = {
{
@@ -122,8 +122,7 @@
void bl1_plat_mboot_init(void)
{
/* Initialize the communication channel between AP and RSE */
- (void)rse_comms_init(PLAT_RSE_AP_SND_MHU_BASE,
- PLAT_RSE_AP_RCV_MHU_BASE);
+ (void)plat_rse_comms_init();
dpe_init(tc_dpe_metadata);
}
diff --git a/plat/arm/board/tc/tc_bl1_measured_boot.c b/plat/arm/board/tc/tc_bl1_measured_boot.c
index 28a1e31..b5617cc 100644
--- a/plat/arm/board/tc/tc_bl1_measured_boot.c
+++ b/plat/arm/board/tc/tc_bl1_measured_boot.c
@@ -1,18 +1,18 @@
/*
- * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
-#include <drivers/arm/rse_comms.h>
#include <drivers/measured_boot/metadata.h>
#include <drivers/measured_boot/rse/rse_measured_boot.h>
#include <tools_share/zero_oid.h>
#include <plat/arm/common/plat_arm.h>
#include <platform_def.h>
+#include <tc_rse_comms.h>
/* Table with platform specific image IDs and metadata. Intentionally not a
* const struct, some members might set by bootloaders during trusted boot.
@@ -47,8 +47,7 @@
void bl1_plat_mboot_init(void)
{
/* Initialize the communication channel between AP and RSE */
- (void)rse_comms_init(PLAT_RSE_AP_SND_MHU_BASE,
- PLAT_RSE_AP_RCV_MHU_BASE);
+ (void)plat_rse_comms_init();
rse_measured_boot_init(tc_rse_mboot_metadata);
}
diff --git a/plat/arm/board/tc/tc_bl2_dpe.c b/plat/arm/board/tc/tc_bl2_dpe.c
index 94fddd4..e2c3a38 100644
--- a/plat/arm/board/tc/tc_bl2_dpe.c
+++ b/plat/arm/board/tc/tc_bl2_dpe.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,7 +7,6 @@
#include <stdint.h>
#include <common/debug.h>
-#include <drivers/arm/rse_comms.h>
#include <drivers/measured_boot/metadata.h>
#include <drivers/measured_boot/rse/dice_prot_env.h>
#include <plat/arm/common/plat_arm.h>
@@ -16,6 +15,7 @@
#include <tools_share/tbbr_oid.h>
#include "tc_dpe.h"
+#include <tc_rse_comms.h>
/*
* The content and the values of this array depends on:
@@ -254,8 +254,7 @@
#endif
/* Initialize the communication channel between AP and RSE */
- (void)rse_comms_init(PLAT_RSE_AP_SND_MHU_BASE,
- PLAT_RSE_AP_RCV_MHU_BASE);
+ (void)plat_rse_comms_init();
dpe_init(tc_dpe_metadata);
}
diff --git a/plat/arm/board/tc/tc_bl2_measured_boot.c b/plat/arm/board/tc/tc_bl2_measured_boot.c
index 3957c90..8238b8b 100644
--- a/plat/arm/board/tc/tc_bl2_measured_boot.c
+++ b/plat/arm/board/tc/tc_bl2_measured_boot.c
@@ -1,18 +1,18 @@
/*
- * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
-#include <drivers/arm/rse_comms.h>
#include <drivers/measured_boot/metadata.h>
#include <drivers/measured_boot/rse/rse_measured_boot.h>
#include <tools_share/tbbr_oid.h>
#include <plat/common/common_def.h>
#include <platform_def.h>
+#include <tc_rse_comms.h>
/* TC specific table with image IDs and metadata. Intentionally not a
* const struct, some members might set by bootloaders during trusted boot.
@@ -53,8 +53,7 @@
void bl2_plat_mboot_init(void)
{
/* Initialize the communication channel between AP and RSE */
- (void)rse_comms_init(PLAT_RSE_AP_SND_MHU_BASE,
- PLAT_RSE_AP_RCV_MHU_BASE);
+ (void)plat_rse_comms_init();
rse_measured_boot_init(tc_rse_mboot_metadata);
}
diff --git a/plat/arm/board/tc/tc_bl31_setup.c b/plat/arm/board/tc/tc_bl31_setup.c
index 4e346ab..5d19aeb 100644
--- a/plat/arm/board/tc/tc_bl31_setup.c
+++ b/plat/arm/board/tc/tc_bl31_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-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
*/
@@ -27,8 +27,8 @@
#endif /* PLATFORM_TEST_TFM_TESTSUITE */
#include <psa/error.h>
-#include <drivers/arm/rse_comms.h>
#include <plat/common/platform.h>
+#include <tc_rse_comms.h>
#ifdef PLATFORM_TEST_TFM_TESTSUITE
/*
@@ -72,6 +72,18 @@
};
#endif
+/* the bottom 3 AMU group 1 counters */
+#define MPMM_GEARS ((1 << 0) | (1 << 1) | (1 << 2))
+
+uint16_t plat_amu_aux_enables[PLATFORM_CORE_COUNT] = {
+ MPMM_GEARS, MPMM_GEARS, MPMM_GEARS, MPMM_GEARS,
+ MPMM_GEARS, MPMM_GEARS, MPMM_GEARS, MPMM_GEARS,
+#if PLATFORM_CORE_COUNT == 14
+ MPMM_GEARS, MPMM_GEARS, MPMM_GEARS, MPMM_GEARS,
+ MPMM_GEARS, MPMM_GEARS
+#endif
+};
+
#if (TARGET_PLATFORM == 3) || (TARGET_PLATFORM == 4)
static void enable_ns_mcn_pmu(void)
{
@@ -126,7 +138,7 @@
#endif
/* Initialise RSE communication channel */
- status = rse_comms_init(PLAT_RSE_AP_SND_MHU_BASE, PLAT_RSE_AP_RCV_MHU_BASE);
+ status = plat_rse_comms_init();
if (status != PSA_SUCCESS) {
ERROR("Failed to initialize RSE communication channel - psa_status = %d\n", status);
}
diff --git a/plat/arm/board/tc/tc_rse_comms.c b/plat/arm/board/tc/tc_rse_comms.c
new file mode 100644
index 0000000..cbb0336
--- /dev/null
+++ b/plat/arm/board/tc/tc_rse_comms.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2022-2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/arm/mhu.h>
+#include <drivers/arm/rse_comms.h>
+#include <platform_def.h>
+#include <tc_rse_comms.h>
+
+static const struct mhu_addr mhu_addresses = {
+ PLAT_RSE_AP_SND_MHU_BASE,
+ PLAT_RSE_AP_RCV_MHU_BASE
+};
+
+int plat_rse_comms_init(void)
+{
+ VERBOSE("Initializing the rse_comms now\n");
+ /* Initialize the communication channel between AP and RSE */
+ return rse_mbx_init(&mhu_addresses);
+}
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index ce1545f..0503acf 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -34,9 +34,31 @@
*/
static entry_point_info_t bl32_image_ep_info;
static entry_point_info_t bl33_image_ep_info;
+
#if ENABLE_RME
static entry_point_info_t rmm_image_ep_info;
+#if (RME_GPT_BITLOCK_BLOCK == 0)
+#define BITLOCK_BASE UL(0)
+#define BITLOCK_SIZE UL(0)
+#else
+/*
+ * Number of bitlock_t entries in bitlocks array for PLAT_ARM_PPS
+ * with RME_GPT_BITLOCK_BLOCK * 512MB per bitlock.
+ */
+#if (PLAT_ARM_PPS > (RME_GPT_BITLOCK_BLOCK * SZ_512M * UL(8)))
+#define BITLOCKS_NUM (PLAT_ARM_PPS) / \
+ (RME_GPT_BITLOCK_BLOCK * SZ_512M * UL(8))
+#else
+#define BITLOCKS_NUM U(1)
#endif
+/*
+ * Bitlocks array
+ */
+static bitlock_t gpt_bitlock[BITLOCKS_NUM];
+#define BITLOCK_BASE (uintptr_t)gpt_bitlock
+#define BITLOCK_SIZE sizeof(gpt_bitlock)
+#endif /* RME_GPT_BITLOCK_BLOCK */
+#endif /* ENABLE_RME */
#if !RESET_TO_BL31
/*
@@ -551,7 +573,7 @@
* stage, so there is no need to provide any PAS here. This function
* sets up pointers to those tables.
*/
- if (gpt_runtime_init() < 0) {
+ if (gpt_runtime_init(BITLOCK_BASE, BITLOCK_SIZE) < 0) {
ERROR("gpt_runtime_init() failed!\n");
panic();
}
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 580ef5f..6d59bae 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -108,9 +108,6 @@
$(error ARM_LINUX_KERNEL_AS_BL33 is only available if RESET_TO_SP_MIN=1.)
endif
endif
- ifndef PRELOADED_BL33_BASE
- $(error PRELOADED_BL33_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used.)
- endif
ifeq (${RESET_TO_BL31},1)
ifndef ARM_PRELOADED_DTB_BASE
$(error ARM_PRELOADED_DTB_BASE must be set if ARM_LINUX_KERNEL_AS_BL33 is used with RESET_TO_BL31.)
diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c
index 498dedf..3e6c9f2 100644
--- a/plat/arm/common/arm_pm.c
+++ b/plat/arm/common/arm_pm.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
*/
@@ -56,6 +56,10 @@
if (psci_get_pstate_id(power_state) != 0U)
return PSCI_E_INVALID_PARAMS;
+#if PSCI_OS_INIT_MODE
+ req_state->last_at_pwrlvl = psci_get_pstate_pwrlvl(power_state);
+#endif /* __PSCI_OS_INIT_MODE__ */
+
return PSCI_E_SUCCESS;
}
diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c
index bfb6906..f8bc542 100644
--- a/plat/arm/css/common/css_pm.c
+++ b/plat/arm/css/common/css_pm.c
@@ -217,12 +217,12 @@
/*******************************************************************************
* Handlers to shutdown/reboot the system
******************************************************************************/
-void __dead2 css_system_off(void)
+void css_system_off(void)
{
css_scp_sys_shutdown();
}
-void __dead2 css_system_reset(void)
+void css_system_reset(void)
{
css_scp_sys_reboot();
}
@@ -364,11 +364,9 @@
plat_arm_gic_cpuif_disable();
plat_arm_gic_redistif_off();
- psci_pwrdown_cpu(PLAT_MAX_PWR_LVL);
+ psci_pwrdown_cpu_start(PLAT_MAX_PWR_LVL);
- dmbsy();
-
- wfi();
+ psci_pwrdown_cpu_end_terminal();
return 0;
}
diff --git a/plat/common/plat_psci_common.c b/plat/common/plat_psci_common.c
index c32e59f..4cea0b9 100644
--- a/plat/common/plat_psci_common.c
+++ b/plat/common/plat_psci_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2025, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -30,6 +30,12 @@
#define PSCI_STAT_ID_EXIT_LOW_PWR 1
#define PSCI_STAT_TOTAL_IDS 2
+#if HW_ASSISTED_COHERENCY
+#define CACHE_MAINTENANCE_ATTR PMF_NO_CACHE_MAINT
+#else
+#define CACHE_MAINTENANCE_ATTR PMF_CACHE_MAINT
+#endif
+
PMF_DECLARE_CAPTURE_TIMESTAMP(psci_svc)
PMF_DECLARE_GET_TIMESTAMP(psci_svc)
PMF_REGISTER_SERVICE(psci_svc, PMF_PSCI_STAT_SVC_ID, PSCI_STAT_TOTAL_IDS,
@@ -70,7 +76,7 @@
{
assert(state_info != NULL);
PMF_CAPTURE_TIMESTAMP(psci_svc, PSCI_STAT_ID_ENTER_LOW_PWR,
- PMF_CACHE_MAINT);
+ CACHE_MAINTENANCE_ATTR);
}
/*
@@ -82,7 +88,7 @@
{
assert(state_info != NULL);
PMF_CAPTURE_TIMESTAMP(psci_svc, PSCI_STAT_ID_EXIT_LOW_PWR,
- PMF_CACHE_MAINT);
+ CACHE_MAINTENANCE_ATTR);
}
/*
@@ -93,22 +99,27 @@
const psci_power_state_t *state_info,
unsigned int last_cpu_idx)
{
- plat_local_state_t state;
unsigned long long pwrup_ts = 0, pwrdn_ts = 0;
unsigned int pmf_flags;
assert((lvl >= PSCI_CPU_PWR_LVL) && (lvl <= PLAT_MAX_PWR_LVL));
- assert(state_info != NULL);
assert(last_cpu_idx <= PLATFORM_CORE_COUNT);
if (lvl == PSCI_CPU_PWR_LVL)
assert(last_cpu_idx == plat_my_core_pos());
+#if HW_ASSISTED_COHERENCY
+ /* HW coherency allows for the capture and access to happen with caches
+ * ON. So these timestamps don't need cache maintenance */
+ pmf_flags = PMF_NO_CACHE_MAINT;
+#else
/*
* If power down is requested, then timestamp capture will
* be with caches OFF. Hence we have to do cache maintenance
* when reading the timestamp.
*/
+ plat_local_state_t state;
+ assert(state_info != NULL);
state = state_info->pwr_domain_state[PSCI_CPU_PWR_LVL];
if (is_local_state_off(state) != 0) {
pmf_flags = PMF_CACHE_MAINT;
@@ -116,6 +127,7 @@
assert(is_local_state_retn(state) == 1);
pmf_flags = PMF_NO_CACHE_MAINT;
}
+#endif
PMF_GET_TIMESTAMP_BY_INDEX(psci_svc,
PSCI_STAT_ID_ENTER_LOW_PWR,
diff --git a/plat/imx/common/include/imx_sip_svc.h b/plat/imx/common/include/imx_sip_svc.h
index 404a829..ecb43c3 100644
--- a/plat/imx/common/include/imx_sip_svc.h
+++ b/plat/imx/common/include/imx_sip_svc.h
@@ -72,6 +72,8 @@
SMC_RET1(handle, SMC_UNK);
}
#endif
+int imx_hab_handler(uint32_t smc_fid, u_register_t x1,
+ u_register_t x2, u_register_t x3, u_register_t x4);
#endif
#if defined(PLAT_imx8mm) || defined(PLAT_imx8mn) || defined(PLAT_imx8mp)
int dram_dvfs_handler(uint32_t smc_fid, void *handle,
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_psci.c b/plat/imx/imx8m/imx8mm/imx8mm_psci.c
index 815d3a2..766c7b3 100644
--- a/plat/imx/imx8m/imx8mm/imx8mm_psci.c
+++ b/plat/imx/imx8m/imx8mm/imx8mm_psci.c
@@ -25,7 +25,7 @@
.cpu_standby = imx_cpu_standby,
.pwr_domain_suspend = imx_domain_suspend,
.pwr_domain_suspend_finish = imx_domain_suspend_finish,
- .pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi,
+ .pwr_domain_pwr_down = imx_pwr_domain_pwr_down_wfi,
.get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
.system_reset = imx_system_reset,
.system_reset2 = imx_system_reset2,
diff --git a/plat/imx/imx8m/imx8mn/imx8mn_psci.c b/plat/imx/imx8m/imx8mn/imx8mn_psci.c
index f541fc1..4947d66 100644
--- a/plat/imx/imx8m/imx8mn/imx8mn_psci.c
+++ b/plat/imx/imx8m/imx8mn/imx8mn_psci.c
@@ -25,7 +25,7 @@
.cpu_standby = imx_cpu_standby,
.pwr_domain_suspend = imx_domain_suspend,
.pwr_domain_suspend_finish = imx_domain_suspend_finish,
- .pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi,
+ .pwr_domain_pwr_down = imx_pwr_domain_pwr_down_wfi,
.get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
.system_reset = imx_system_reset,
.system_off = imx_system_off,
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_psci.c b/plat/imx/imx8m/imx8mp/imx8mp_psci.c
index bc7b246..0a8c351 100644
--- a/plat/imx/imx8m/imx8mp/imx8mp_psci.c
+++ b/plat/imx/imx8m/imx8mp/imx8mp_psci.c
@@ -25,7 +25,7 @@
.cpu_standby = imx_cpu_standby,
.pwr_domain_suspend = imx_domain_suspend,
.pwr_domain_suspend_finish = imx_domain_suspend_finish,
- .pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi,
+ .pwr_domain_pwr_down = imx_pwr_domain_pwr_down_wfi,
.get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
.system_reset = imx_system_reset,
.system_off = imx_system_off,
diff --git a/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c b/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
index 70c2def..fdaf9fd 100644
--- a/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
+++ b/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
@@ -52,6 +52,8 @@
MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW), /* GIC map */
MAP_REGION_FLAT(IMX_DDRPHY_BASE, IMX_DDR_IPS_SIZE, MT_DEVICE | MT_RW), /* DDRMIX map */
MAP_REGION_FLAT(IMX_DRAM_BASE, IMX_DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS),
+ MAP_REGION_FLAT(IMX_CAAM_RAM_BASE, IMX_CAAM_RAM_SIZE, MT_MEMORY | MT_RW), /* CAMM RAM */
+ MAP_REGION_FLAT(IMX_NS_OCRAM_BASE, IMX_NS_OCRAM_SIZE, MT_MEMORY | MT_RW), /* NS OCRAM */
{0},
};
@@ -207,13 +209,19 @@
MT_MEMORY | MT_RW | MT_SECURE),
MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE,
MT_MEMORY | MT_RO | MT_SECURE),
+#if SEPARATE_NOBITS_REGION
+ MAP_REGION_FLAT(BL_NOBITS_BASE, BL_NOBITS_END - BL_NOBITS_BASE,
+ MT_RW_DATA | MT_SECURE),
+#endif
#if USE_COHERENT_MEM
MAP_REGION_FLAT(BL_COHERENT_RAM_BASE,
BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
MT_DEVICE | MT_RW | MT_SECURE),
#endif
+#if defined(SPD_opteed) || defined(SPD_trusty)
/* Map TEE memory */
MAP_REGION_FLAT(BL32_BASE, BL32_SIZE, MT_MEMORY | MT_RW),
+#endif
{0},
};
diff --git a/plat/imx/imx8m/imx8mq/imx8mq_psci.c b/plat/imx/imx8m/imx8mq/imx8mq_psci.c
index 3375ce7..c023b55 100644
--- a/plat/imx/imx8m/imx8mq/imx8mq_psci.c
+++ b/plat/imx/imx8m/imx8mq/imx8mq_psci.c
@@ -137,7 +137,7 @@
.cpu_standby = imx_cpu_standby,
.pwr_domain_suspend = imx_domain_suspend,
.pwr_domain_suspend_finish = imx_domain_suspend_finish,
- .pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi,
+ .pwr_domain_pwr_down = imx_pwr_domain_pwr_down_wfi,
.get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
.system_reset = imx_system_reset,
.system_reset2 = imx_system_reset2,
diff --git a/plat/imx/imx8m/imx8mq/include/platform_def.h b/plat/imx/imx8m/imx8mq/include/platform_def.h
index 61c0e8e..34bd77e 100644
--- a/plat/imx/imx8m/imx8mq/include/platform_def.h
+++ b/plat/imx/imx8m/imx8mq/include/platform_def.h
@@ -10,7 +10,7 @@
#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
#define PLATFORM_LINKER_ARCH aarch64
-#define PLATFORM_STACK_SIZE 0x800
+#define PLATFORM_STACK_SIZE 0xb00
#define CACHE_WRITEBACK_GRANULE 64
#define PLAT_PRIMARY_CPU U(0x0)
@@ -37,6 +37,12 @@
#define BL31_SIZE SZ_64K
#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
+#define OCRAM_S_BASE U(0x180000)
+#define OCRAM_S_SIZE SZ_32K
+#define OCRAM_S_LIMIT (OCRAM_S_BASE + OCRAM_S_SIZE)
+#define BL31_NOBITS_BASE OCRAM_S_BASE
+#define BL31_NOBITS_LIMIT (BL31_NOBITS_BASE + SZ_32K)
+
/* non-secure uboot base */
#ifndef PLAT_NS_IMAGE_OFFSET
#define PLAT_NS_IMAGE_OFFSET U(0x40200000)
@@ -54,7 +60,7 @@
#define MAX_XLAT_TABLES 5
#define MAX_MMAP_REGIONS 15
#else
-#define MAX_XLAT_TABLES 4
+#define MAX_XLAT_TABLES 3
#define MAX_MMAP_REGIONS 14
#endif
@@ -93,7 +99,10 @@
#define IMX_DDR_IPS_SIZE U(0x1800000)
#define IMX_DRAM_BASE U(0x40000000)
#define IMX_DRAM_SIZE U(0xc0000000)
-
+#define IMX_NS_OCRAM_BASE U(0x900000)
+#define IMX_NS_OCRAM_SIZE U(0x20000)
+#define IMX_CAAM_RAM_BASE U(0x100000)
+#define IMX_CAAM_RAM_SIZE U(0x10000)
#define IMX_ROM_BASE U(0x00000000)
#define IMX_ROM_SIZE U(0x20000)
@@ -141,10 +150,6 @@
#define GPR_TZASC_EN BIT(0)
#define GPR_TZASC_EN_LOCK BIT(16)
-#define OCRAM_S_BASE U(0x00180000)
-#define OCRAM_S_SIZE U(0x8000)
-#define OCRAM_S_LIMIT (OCRAM_S_BASE + OCRAM_S_SIZE)
-
#define COUNTER_FREQUENCY 8333333 /* 25MHz / 3 */
#define IMX_WDOG_B_RESET
diff --git a/plat/imx/imx8m/imx8mq/platform.mk b/plat/imx/imx8m/imx8mq/platform.mk
index 73179dd..76fc071 100644
--- a/plat/imx/imx8m/imx8mq/platform.mk
+++ b/plat/imx/imx8m/imx8mq/platform.mk
@@ -29,6 +29,7 @@
plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c \
plat/imx/imx8m/imx8mq/imx8mq_psci.c \
plat/imx/imx8m/gpc_common.c \
+ plat/imx/imx8m/imx_hab.c \
plat/imx/imx8m/imx_aipstz.c \
plat/imx/imx8m/imx8m_caam.c \
plat/imx/imx8m/imx8m_ccm.c \
@@ -63,6 +64,8 @@
BL31_SOURCES += ${IMX_DRAM_SOURCES}
endif
+SEPARATE_NOBITS_REGION := 1
+
ifneq (${PRELOADED_BL33_BASE},)
$(eval $(call add_define_val,PLAT_NS_IMAGE_OFFSET,${PRELOADED_BL33_BASE}))
endif
diff --git a/plat/imx/imx8ulp/imx8ulp_psci.c b/plat/imx/imx8ulp/imx8ulp_psci.c
index 628acea..59af8be 100644
--- a/plat/imx/imx8ulp/imx8ulp_psci.c
+++ b/plat/imx/imx8ulp/imx8ulp_psci.c
@@ -538,7 +538,7 @@
.pwr_domain_suspend_finish = imx_domain_suspend_finish,
.get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
.validate_power_state = imx_validate_power_state,
- .pwr_domain_pwr_down_wfi = imx8ulp_pwr_domain_pwr_down_wfi,
+ .pwr_domain_pwr_down = imx8ulp_pwr_domain_pwr_down_wfi,
};
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
diff --git a/plat/intel/soc/agilex5/bl2_plat_setup.c b/plat/intel/soc/agilex5/bl2_plat_setup.c
index fe5dc6e..f4010f9 100644
--- a/plat/intel/soc/agilex5/bl2_plat_setup.c
+++ b/plat/intel/soc/agilex5/bl2_plat_setup.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
- * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -31,6 +31,8 @@
#include "nand/nand.h"
#include "qspi/cadence_qspi.h"
#include "sdmmc/sdmmc.h"
+/* TODO: DTB not available */
+// #include "socfpga_dt.h"
#include "socfpga_emac.h"
#include "socfpga_f2sdram_manager.h"
#include "socfpga_handoff.h"
@@ -138,6 +140,12 @@
/* DDR and IOSSM driver init */
agilex5_ddr_init(&reverse_handoff_ptr);
+ /* TODO: DTB not available */
+ // if (socfpga_dt_open_and_check(SOCFPGA_DTB_BASE, DT_COMPATIBLE_STR) < 0) {
+ // ERROR("SOCFPGA: Failed to open device tree\n");
+ // panic();
+ // }
+
if (combo_phy_init(&reverse_handoff_ptr) != 0) {
ERROR("SOCFPGA: Combo Phy initialization failed\n");
}
@@ -165,13 +173,13 @@
switch (boot_source) {
case BOOT_SOURCE_SDMMC:
- NOTICE("SDMMC boot\n");
+ NOTICE("SOCFPGA: SDMMC boot\n");
cdns_mmc_init(¶ms, &mmc_info);
socfpga_io_setup(boot_source, PLAT_SDMMC_DATA_BASE);
break;
case BOOT_SOURCE_QSPI:
- NOTICE("QSPI boot\n");
+ NOTICE("SOCFPGA: QSPI boot\n");
cad_qspi_init(0, QSPI_CONFIG_CPHA, QSPI_CONFIG_CPOL,
QSPI_CONFIG_CSDA, QSPI_CONFIG_CSDADS,
QSPI_CONFIG_CSEOT, QSPI_CONFIG_CSSOT, 0);
@@ -182,13 +190,13 @@
break;
case BOOT_SOURCE_NAND:
- NOTICE("NAND boot\n");
+ NOTICE("SOCFPGA: SOCFPGA: NAND boot\n");
nand_init(&reverse_handoff_ptr);
socfpga_io_setup(boot_source, PLAT_NAND_DATA_BASE);
break;
default:
- ERROR("Unsupported boot source\n");
+ ERROR("SOCFPGA: Unsupported boot source\n");
panic();
break;
}
@@ -230,7 +238,7 @@
ret = socfpga_vab_init(image_id);
if (ret < 0) {
- ERROR("SOCFPGA VAB Authentication failed\n");
+ ERROR("SOCFPGA: VAB Authentication failed\n");
wfi();
}
#endif
diff --git a/plat/intel/soc/agilex5/bl31_plat_setup.c b/plat/intel/soc/agilex5/bl31_plat_setup.c
index 03559e1..17d955a 100644
--- a/plat/intel/soc/agilex5/bl31_plat_setup.c
+++ b/plat/intel/soc/agilex5/bl31_plat_setup.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2019-2024, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
- * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -21,6 +21,7 @@
#include "agilex5_cache.h"
#include "agilex5_power_manager.h"
#include "ccu/ncore_ccu.h"
+#include "socfpga_dt.h"
#include "socfpga_mailbox.h"
#include "socfpga_private.h"
#include "socfpga_reset_manager.h"
@@ -146,7 +147,7 @@
PLAT_INTEL_SOCFPGA_G0_IRQ_PROPS(INTR_GROUP0)
};
-static const gicv3_driver_data_t plat_gicv3_gic_data = {
+gicv3_driver_data_t plat_gicv3_gic_data = {
.gicd_base = PLAT_INTEL_SOCFPGA_GICD_BASE,
.gicr_base = PLAT_INTEL_SOCFPGA_GICR_BASE,
.interrupt_props = agx5_interrupt_props,
@@ -162,6 +163,11 @@
{
socfpga_delay_timer_init();
+ /* TODO: DTB not available */
+ // socfpga_dt_populate_gicv3_config(SOCFPGA_DTB_BASE, &plat_gicv3_gic_data);
+ // NOTICE("SOCFPGA: GIC GICD base address 0x%lx\n", plat_gicv3_gic_data.gicd_base);
+ // NOTICE("SOCFPGA: GIC GICR base address 0x%lx\n", plat_gicv3_gic_data.gicr_base);
+
/* Initialize the gic cpu and distributor interfaces */
gicv3_driver_init(&plat_gicv3_gic_data);
gicv3_distif_init();
@@ -192,9 +198,9 @@
cpuid = MPIDR_AFFLVL1_VAL(read_mpidr());
boot_core = ((mmio_read_32(AGX5_PWRMGR(MPU_BOOTCONFIG)) & 0xC00) >> 10);
- NOTICE("BL31: Boot Core = %x\n", boot_core);
- NOTICE("BL31: CPU ID = %x\n", cpuid);
- INFO("BL31: Invalidate Data cache\n");
+ NOTICE("SOCFPGA: Boot Core = %x\n", boot_core);
+ NOTICE("SOCFPGA: CPU ID = %x\n", cpuid);
+ INFO("SOCFPGA: Invalidate Data cache\n");
invalidate_dcache_all();
/* Invalidate for NS EL2 and EL1 */
@@ -282,6 +288,11 @@
mmio_write_32(AGX5_PWRMGR(MPU_PCHCTLR), pch_cpu);
}
+void bl31_plat_runtime_setup(void)
+{
+ console_switch_state(CONSOLE_FLAG_RUNTIME|CONSOLE_FLAG_BOOT);
+}
+
void bl31_plat_enable_mmu(uint32_t flags)
{
/* TODO: Enable mmu when needed */
diff --git a/plat/intel/soc/agilex5/include/agilex5_system_manager.h b/plat/intel/soc/agilex5/include/agilex5_system_manager.h
index ac4bf12..8c86ab1 100644
--- a/plat/intel/soc/agilex5/include/agilex5_system_manager.h
+++ b/plat/intel/soc/agilex5/include/agilex5_system_manager.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
- * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -193,12 +193,12 @@
#define A5D0_JTAG_ID 0xD000
#define A5D4_JTAG_ID 0x4000D000
#define A5F0_JTAG_ID 0xC000
-#define A5F4_JTAG_ID 0x4000F000
+#define A5F4_JTAG_ID 0x4000C000
#define A510_JTAG_ID 0x1000
#define A514_JTAG_ID 0x40001000
#define A530_JTAG_ID 0x3000
#define A534_JTAG_ID 0x40003000
-#define JTAG_ID_MASK 0xC000F000
+#define JTAG_ID_MASK 0xF000F000
/* Field Masking */
#define SYSMGR_SDMMC_DRVSEL(x) (((x) & 0x7) << 0)
diff --git a/plat/intel/soc/agilex5/include/socfpga_plat_def.h b/plat/intel/soc/agilex5/include/socfpga_plat_def.h
index 282958a..42d8ccf 100644
--- a/plat/intel/soc/agilex5/include/socfpga_plat_def.h
+++ b/plat/intel/soc/agilex5/include/socfpga_plat_def.h
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
- * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -29,6 +29,8 @@
#define PLAT_L2_RESET_REQ 0xB007C0DE
#define PLAT_HANDOFF_OFFSET 0x0007F000
#define PLAT_TIMER_BASE_ADDR 0x10D01000
+#define SOCFPGA_DTB_BASE 0x80020000
+#define DT_COMPATIBLE_STR "arm,altera socfpga-agilex5"
/* System Counter */
/* TODO: Update back to 400MHz.
diff --git a/plat/intel/soc/agilex5/platform.mk b/plat/intel/soc/agilex5/platform.mk
index a831c39..58d4b2e 100644
--- a/plat/intel/soc/agilex5/platform.mk
+++ b/plat/intel/soc/agilex5/platform.mk
@@ -1,11 +1,12 @@
#
# Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
# Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
-# Copyright (c) 2024, Altera Corporation. All rights reserved.
+# Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
include lib/xlat_tables_v2/xlat_tables.mk
+include lib/libfdt/libfdt.mk
PLAT_INCLUDES := \
-Iplat/intel/soc/agilex5/include/ \
-Iplat/intel/soc/common/drivers/ \
@@ -22,6 +23,7 @@
PLAT_BL_COMMON_SOURCES := \
${AGX5_GICv3_SOURCES} \
+ common/fdt_wrappers.c \
drivers/cadence/combo_phy/cdns_combo_phy.c \
drivers/cadence/emmc/cdns_sdmmc.c \
drivers/cadence/nand/cdns_nand.c \
@@ -36,7 +38,8 @@
plat/intel/soc/common/drivers/ddr/ddr.c \
plat/intel/soc/common/drivers/nand/nand.c \
plat/intel/soc/common/lib/sha/sha.c \
- plat/intel/soc/common/socfpga_delay_timer.c
+ plat/intel/soc/common/socfpga_delay_timer.c \
+ plat/intel/soc/common/socfpga_dt.c
BL2_SOURCES += \
common/desc_image_load.c \
diff --git a/plat/intel/soc/common/fdts/agilex5_fdt.dts b/plat/intel/soc/common/fdts/agilex5_fdt.dts
new file mode 100644
index 0000000..e16034f
--- /dev/null
+++ b/plat/intel/soc/common/fdts/agilex5_fdt.dts
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2019-2024, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+/ {
+ model = "ALTERA SOCFPGA AGILEX5";
+ compatible = "arm,altera socfpga-agilex5";
+ owner = "jit.loon.lim@intel.com";
+ interrupt-parent = <&gic>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ psci {
+ compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci";
+ method = "smc";
+
+ cpu_on = <0xdeadc0de>;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ enable-method = "psci";
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a5";
+ reg = <0>;
+ };
+ cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a5";
+ reg = <1>;
+ };
+ cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a5";
+ reg = <2>;
+ };
+ cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a5";
+ reg = <3>;
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x90000000>;
+ };
+
+ gic: interrupt-controller@2c010000 {
+ compatible = "arm,gic-600", "arm,gic-v3";
+ #address-cells = <2>;
+ #interrupt-cells = <3>;
+ #size-cells = <1>;
+ #ranges;
+ interrupt-controller;
+ reg = <0x1D000000 0>, /* GICD */
+ <0x1D060000 0>; /* GICR */
+ interrupts = <0x1 0x9 0x4>;
+ };
+
+ serial0: uart@1a200000 {
+ compatible = "arm,console-16550";
+ reg = <0x10C02000 0x1000>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 8 0xf04>;
+ clock-frequency = <100000000>;
+ uart-baudrate = <115200>;
+ };
+
+ timer0: timer@1a040000 {
+ compatible = "arm,armv7-timer-mem";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ reg = <0x1a040000 0x1000>;
+ clock-frequency = <7500000>;
+
+ frame@1a050000 {
+ frame-number = <0>;
+ interrupts = <0 2 0xf04>;
+ reg = <0x1a050000 0x1000>;
+ };
+ };
+
+};
diff --git a/plat/intel/soc/common/include/socfpga_dt.h b/plat/intel/soc/common/include/socfpga_dt.h
new file mode 100644
index 0000000..3ff4cb7
--- /dev/null
+++ b/plat/intel/soc/common/include/socfpga_dt.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOCFPGA_DT_H
+#define SOCFPGA_DT_H
+
+
+#include <stdlib.h>
+#include <drivers/arm/gicv3.h>
+#include <drivers/delay_timer.h>
+/*
+ * This macro takes three arguments:
+ * config: Configuration identifier
+ * name: property namespace
+ * callback: populate() function
+ */
+#define SOCFPGA_REGISTER_POPULATOR(config, name, callback) \
+ __section(".socfpga_populator") __used \
+ static const struct socfpga_populator (name##__populator) = { \
+ .config_type = (#config), \
+ .info = (#name), \
+ .populate = (callback) \
+ }
+
+/*
+ * Populator callback
+ *
+ * This structure are used by the fconf_populate function and should only be
+ * defined by the SOCFPGA_REGISTER_POPULATOR macro.
+ */
+struct socfpga_populator {
+ /* Description of the data loaded by the callback */
+ const char *config_type;
+ const char *info;
+
+ /* Callback used by fconf_populate function with a provided config dtb.
+ * Return 0 on success, err_code < 0 otherwise.
+ */
+ int (*populate)(uintptr_t config);
+};
+
+/* Hardware Config related getter */
+#define hw_config__gicv3_config_getter(prop) plat_gicv3_gic_data.prop
+
+/* Function Definitions */
+int socfpga_dt_open_and_check(uintptr_t dt_addr, char *compatible_str);
+int socfpga_dt_populate_gicv3_config(uintptr_t dt_addr, gicv3_driver_data_t *plat_driver_data);
+int socfpga_dt_populate_dram_layout(uintptr_t dt_addr);
+
+#endif
diff --git a/plat/intel/soc/common/include/socfpga_system_manager.h b/plat/intel/soc/common/include/socfpga_system_manager.h
index 346cfe1..14e3804 100644
--- a/plat/intel/soc/common/include/socfpga_system_manager.h
+++ b/plat/intel/soc/common/include/socfpga_system_manager.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
- * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -36,5 +36,6 @@
/* Function Prototype */
uint32_t intel_hps_get_jtag_id(void);
bool is_agilex5_A5F0(void);
+bool is_agilex5_A5F4(void);
#endif /* SOCFPGA_SYSTEMMANAGER_H */
diff --git a/plat/intel/soc/common/soc/socfpga_system_manager.c b/plat/intel/soc/common/soc/socfpga_system_manager.c
index 4223b2b..789c2b6 100644
--- a/plat/intel/soc/common/soc/socfpga_system_manager.c
+++ b/plat/intel/soc/common/soc/socfpga_system_manager.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -15,7 +15,7 @@
uint32_t intel_hps_get_jtag_id(void)
{
- uint32_t jtag_id = 0x00;
+ uint32_t jtag_id;
jtag_id = (mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_4)));
@@ -29,3 +29,9 @@
{
return ((intel_hps_get_jtag_id() & JTAG_ID_MASK) == A5F0_JTAG_ID);
}
+
+/* Check for Agilex5 SM4 B0 */
+bool is_agilex5_A5F4(void)
+{
+ return ((intel_hps_get_jtag_id() & JTAG_ID_MASK) == A5F4_JTAG_ID);
+}
diff --git a/plat/intel/soc/common/socfpga_dt.c b/plat/intel/soc/common/socfpga_dt.c
new file mode 100644
index 0000000..0333b9b
--- /dev/null
+++ b/plat/intel/soc/common/socfpga_dt.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <common/fdt_wrappers.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gicv3.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <libfdt.h>
+#include <platform_def.h>
+#include <tools_share/firmware_image_package.h>
+
+#include "socfpga_dt.h"
+
+static const void *fdt;
+/*******************************************************************************
+ * This function checks device tree file with its header.
+ * Returns 0 on success and a negative FDT error code on failure.
+ ******************************************************************************/
+int socfpga_dt_open_and_check(uintptr_t dt_addr, char *compatible_str)
+{
+ int ret = 0;
+ int node = 1;
+
+ ret = fdt_check_header((void *)dt_addr);
+
+ if (ret != 0) {
+ ERROR("SOCFPGA: FDT Header invalid\n");
+ return ret;
+ }
+
+ fdt = (const void *)dt_addr;
+
+ /* As libfdt use void *, we can't avoid this cast */
+ const void *dtb = (void *)dt_addr;
+
+ /* Assert the node offset point to compatible property */
+ node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
+ if (node < 0) {
+ ERROR("SOCFPGA: Can't find `%s` compatible in dtb\n",
+ compatible_str);
+ return node;
+ }
+
+ NOTICE("SOCFPGA: Successfully open and check FDT\n");
+
+ return ret;
+}
+
+int socfpga_dt_populate_gicv3_config(uintptr_t dt_addr, gicv3_driver_data_t *plat_driver_data)
+{
+ int err;
+ int node;
+ uintptr_t addr;
+
+ /* Necessary to work with libfdt APIs */
+ const void *hw_config_dtb = (const void *)dt_addr;
+ /*
+ * Find the offset of the node containing "arm,gic-v3" compatible property.
+ * Populating fconf strucutures dynamically is not supported for legacy
+ * systems which use GICv2 IP. Simply skip extracting GIC properties.
+ */
+ node = fdt_node_offset_by_compatible(hw_config_dtb, -1, "arm,gic-v3");
+ if (node < 0) {
+ ERROR("SOCFPGA: Unable to locate node with arm,gic-v3 compatible property\n");
+ return 0;
+ }
+ /* The GICv3 DT binding holds at least two address/size pairs,
+ * the first describing the distributor, the second the redistributors.
+ * See: bindings/interrupt-controller/arm,gic-v3.yaml
+ */
+ err = fdt_get_reg_props_by_index(hw_config_dtb, node, 0, &addr, NULL);
+ if (err < 0) {
+ ERROR("SOCFPGA: Failed to read GICD reg property of GIC node\n");
+ } else {
+ plat_driver_data->gicd_base = addr;
+ }
+
+ err = fdt_get_reg_props_by_index(hw_config_dtb, node, 1, &addr, NULL);
+ if (err < 0) {
+ ERROR("SOCFPGA: Failed to read GICR reg property of GIC node\n");
+ } else {
+ plat_driver_data->gicr_base = addr;
+ }
+ return err;
+}
+
+int socfpga_dt_populate_dram_layout(uintptr_t dt_addr)
+{
+ int node;
+ uintptr_t addr;
+ size_t size;
+
+ /* Necessary to work with libfdt APIs */
+ const void *hw_config_dtb = (const void *)dt_addr;
+
+ /* Find 'memory' node */
+ node = fdt_node_offset_by_prop_value(hw_config_dtb, -1, "device_type",
+ "memory", sizeof("memory"));
+ if (node < 0) {
+ NOTICE("SOCFPGA: Unable to locate 'memory' node\n");
+ return node;
+ }
+
+ int err = fdt_get_reg_props_by_index(
+ hw_config_dtb, node, 0,
+ &addr, (size_t *)&size);
+
+ NOTICE("SOCFPGA: Mem base 0x%lx, Mem size 0x%lx\n", addr, size);
+ if (err < 0) {
+ ERROR("SOCFPGA: Failed to read 'reg' property of 'memory' node\n");
+ return err;
+ }
+
+ return 0;
+}
diff --git a/plat/intel/soc/common/socfpga_sip_svc.c b/plat/intel/soc/common/socfpga_sip_svc.c
index 71a626d..d64ead7 100644
--- a/plat/intel/soc/common/socfpga_sip_svc.c
+++ b/plat/intel/soc/common/socfpga_sip_svc.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2019-2023, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
- * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -790,7 +790,7 @@
int intel_smmu_hps_remapper_config(uint32_t remapper_bypass)
{
/* Read out the JTAG-ID from boot scratch register */
- if (is_agilex5_A5F0() != 0) {
+ if (is_agilex5_A5F0() || is_agilex5_A5F4()) {
if (remapper_bypass == 0x01) {
g_remapper_bypass = remapper_bypass;
mmio_write_32(SOCFPGA_SYSMGR(SDM_BE_ARADDR_REMAP), 0);
diff --git a/plat/marvell/armada/a3k/common/a3700_common.mk b/plat/marvell/armada/a3k/common/a3700_common.mk
index e8f892d..ac47ef5 100644
--- a/plat/marvell/armada/a3k/common/a3700_common.mk
+++ b/plat/marvell/armada/a3k/common/a3700_common.mk
@@ -74,6 +74,9 @@
BL31_SOURCES += $(PLAT_FAMILY_BASE)/$(PLAT)/board/pm_src.c
endif
+BUILD_UART := uart-images
+UART_IMAGE := $(BUILD_UART).tgz.bin
+
ifdef WTP
# Do not remove! Following checks are required to ensure correct TF-A builds, removing these checks leads to broken TF-A builds
@@ -82,9 +85,6 @@
TBB := $(WTP)/wtptp/src/TBB_Linux/release/TBB_linux
-BUILD_UART := uart-images
-UART_IMAGE := $(BUILD_UART).tgz.bin
-
ifeq ($(MARVELL_SECURE_BOOT),1)
TIM_CFG := $(BUILD_PLAT)/atf-tim.txt
TIM_UART_CFG := $(BUILD_PLAT)/$(BUILD_UART)/atf-tim.txt
diff --git a/plat/marvell/armada/a8k/common/plat_pm.c b/plat/marvell/armada/a8k/common/plat_pm.c
index f08f08a..ae3ee37 100644
--- a/plat/marvell/armada/a8k/common/plat_pm.c
+++ b/plat/marvell/armada/a8k/common/plat_pm.c
@@ -845,7 +845,7 @@
.pwr_domain_on_finish = a8k_pwr_domain_on_finish,
.get_sys_suspend_power_state = a8k_get_sys_suspend_power_state,
.pwr_domain_suspend_finish = a8k_pwr_domain_suspend_finish,
- .pwr_domain_pwr_down_wfi = a8k_pwr_domain_pwr_down_wfi,
+ .pwr_domain_pwr_down = a8k_pwr_domain_pwr_down_wfi,
.system_off = a8k_system_off,
.system_reset = a8k_system_reset,
.validate_power_state = a8k_validate_power_state,
diff --git a/plat/mediatek/drivers/apusys/mt8196/apusys_devapc_def.h b/plat/mediatek/drivers/apusys/mt8196/apusys_devapc_def.h
index af63c0c..7b57a70 100644
--- a/plat/mediatek/drivers/apusys/mt8196/apusys_devapc_def.h
+++ b/plat/mediatek/drivers/apusys/mt8196/apusys_devapc_def.h
@@ -139,6 +139,6 @@
#define APUSYS_CTRL_DAPC_RCX_SLAVE_NUM (95) /* 0~94 */
/* Dump Config */
-#define DUMP_CFG
+#undef DUMP_CFG
#endif
diff --git a/plat/mediatek/drivers/spm/mt8196/mt_spm.c b/plat/mediatek/drivers/spm/mt8196/mt_spm.c
index fee5b4c..2a82089 100644
--- a/plat/mediatek/drivers/spm/mt8196/mt_spm.c
+++ b/plat/mediatek/drivers/spm/mt8196/mt_spm.c
@@ -50,8 +50,6 @@
#define plat_spm_lock_init()
#endif
-uint32_t mt_spm_version;
-
static uint32_t spm_irq_num;
void spm_set_sysclk_settle(void)
@@ -429,12 +427,6 @@
}
#endif
-static void spm_gpio_init(void)
-{
- gpio_set_direction(EC_SUSPEND_PIN, GPIO_DIR_OUT);
- gpio_set_value(EC_SUSPEND_PIN, GPIO_LEVEL_HIGH);
-}
-
int spm_boot_init(void)
{
plat_spm_lock_init();
@@ -452,13 +444,9 @@
#if defined(MT_SPM_FEATURE_SUPPORT)
spm_hwreq_init();
#endif
- spm_gpio_init();
-
spm_irq_num = 0xFFFFFFFF;
- INFO("[%s:%d] - spm finished, version = %u, PC = 0x%x\n",
- __func__, __LINE__,
- mt_spm_version, mmio_read_32(MD32PCM_PC));
+ INFO("[%s], PC = 0x%x\n", __func__, mmio_read_32(MD32PCM_PC));
return 0;
}
MTK_PLAT_SETUP_1_INIT(spm_boot_init);
diff --git a/plat/mediatek/drivers/spm/mt8196/mt_spm.h b/plat/mediatek/drivers/spm/mt8196/mt_spm.h
index bc6fa44..bd5fd9c 100644
--- a/plat/mediatek/drivers/spm/mt8196/mt_spm.h
+++ b/plat/mediatek/drivers/spm/mt8196/mt_spm.h
@@ -28,9 +28,6 @@
#define MT_SPM_TIME_GET(tm) ({ (tm) = el3_uptime(); })
-#define MT_SPM_VERSION_ES 0x0
-#define MT_SPM_VERSION_CS 0x1
-
#define SPM_FW_NO_RESUME 1
#define MCUSYS_MTCMOS_ON 0
#define WAKEUP_LOG_ON 0
@@ -138,7 +135,6 @@
void mt_spm_set_common_sodi_pcm_flags(void);
int spm_boot_init(void);
void spm_dvfsfw_init(uint64_t boot_up_opp, uint64_t dram_issue);
-extern uint32_t mt_spm_version;
extern struct pwr_ctrl spm_init_ctrl;
/* Support by bl31_plat_setup.c */
uint32_t is_abnormal_boot(void);
diff --git a/plat/mediatek/drivers/spm/mt8196/mt_spm_conservation.c b/plat/mediatek/drivers/spm/mt8196/mt_spm_conservation.c
index 16d9f29..0365e83 100644
--- a/plat/mediatek/drivers/spm/mt8196/mt_spm_conservation.c
+++ b/plat/mediatek/drivers/spm/mt8196/mt_spm_conservation.c
@@ -58,14 +58,10 @@
#if defined(CONFIG_MTK_VCOREDVFS_SUPPORT)
__spm_sync_vcore_dvfs_power_control(pwrctrl, __spm_vcorefs.pwrctrl);
#endif
- if (mt_spm_version == MT_SPM_VERSION_ES)
- pwrctrl->pcm_flags |= (SPM_FLAG_ENABLE_MT8196_E1_WA |
- SPM_FLAG_ENABLE_MT8196_EMI_E1_WA);
#ifdef MTK_SPM_IVI_SUPPORT
pwrctrl->pcm_flags |= SPM_FLAG_ENABLE_MT8196_IVI;
#endif
-
__spm_set_pcm_flags(pwrctrl);
#ifdef HW_S1_DETECT
diff --git a/plat/mediatek/include/lib/pm/mtk_pm.h b/plat/mediatek/include/lib/pm/mtk_pm.h
index 14d005d..05293e9 100644
--- a/plat/mediatek/include/lib/pm/mtk_pm.h
+++ b/plat/mediatek/include/lib/pm/mtk_pm.h
@@ -78,7 +78,7 @@
psci_power_state_t *req_state);
void (*get_sys_suspend_power_state)(
psci_power_state_t *req_state);
- __dead2 void (*pwr_domain_pwr_down_wfi)(
+ void (*pwr_domain_pwr_down_wfi)(
const psci_power_state_t *req_state);
};
diff --git a/plat/mediatek/lib/pm/armv9_0/pwr_ctrl.c b/plat/mediatek/lib/pm/armv9_0/pwr_ctrl.c
index ace2700..19dcd33 100644
--- a/plat/mediatek/lib/pm/armv9_0/pwr_ctrl.c
+++ b/plat/mediatek/lib/pm/armv9_0/pwr_ctrl.c
@@ -379,7 +379,7 @@
}
#endif
-static void __dead2 pwr_domain_pwr_down_wfi(const psci_power_state_t *req_state)
+static void pwr_domain_pwr_down_wfi(const psci_power_state_t *req_state)
{
unsigned int cpu = plat_my_core_pos();
int ret = MTK_CPUPM_E_NOT_SUPPORT;
@@ -390,6 +390,8 @@
plat_panic_handler();
else
psci_power_down_wfi();
+ /* should never reach here */
+ panic();
}
static void pm_smp_init(unsigned int cpu_id, uintptr_t entry_point)
diff --git a/plat/mediatek/lib/pm/mtk_pm.c b/plat/mediatek/lib/pm/mtk_pm.c
index 772c2d7..553fad2 100644
--- a/plat/mediatek/lib/pm/mtk_pm.c
+++ b/plat/mediatek/lib/pm/mtk_pm.c
@@ -45,8 +45,8 @@
mtk_pm_ops.get_sys_suspend_power_state = ops->get_sys_suspend_power_state;
}
- if (!mtk_pm_ops.pwr_domain_pwr_down_wfi)
- mtk_pm_ops.pwr_domain_pwr_down_wfi = ops->pwr_domain_pwr_down_wfi;
+ if (!mtk_pm_ops.pwr_domain_pwr_down)
+ mtk_pm_ops.pwr_domain_pwr_down = ops->pwr_domain_pwr_down_wfi;
mtk_pm_status |= MTK_PM_ST_PWR_READY;
#endif
diff --git a/plat/mediatek/mt8196/drivers/gpio/mtgpio.c b/plat/mediatek/mt8196/drivers/gpio/mtgpio.c
index 6257159..a34f706 100644
--- a/plat/mediatek/mt8196/drivers/gpio/mtgpio.c
+++ b/plat/mediatek/mt8196/drivers/gpio/mtgpio.c
@@ -23,7 +23,8 @@
REG_11,
REG_12,
REG_13,
- REG_14
+ REG_14,
+ REG_15
} RegEnum;
uintptr_t mt_gpio_find_reg_addr(uint32_t pin)
@@ -37,48 +38,51 @@
switch (gpio_info.base & 0xF) {
case REG_0:
- reg_addr = IOCFG_RT_BASE;
+ reg_addr = GPIO_BASE;
break;
case REG_1:
- reg_addr = IOCFG_RM1_BASE;
+ reg_addr = IOCFG_RT_BASE;
break;
case REG_2:
- reg_addr = IOCFG_RM2_BASE;
+ reg_addr = IOCFG_RM1_BASE;
break;
case REG_3:
- reg_addr = IOCFG_RB_BASE;
+ reg_addr = IOCFG_RM2_BASE;
break;
case REG_4:
- reg_addr = IOCFG_BM1_BASE;
+ reg_addr = IOCFG_RB_BASE;
break;
case REG_5:
- reg_addr = IOCFG_BM2_BASE;
+ reg_addr = IOCFG_BM1_BASE;
break;
case REG_6:
- reg_addr = IOCFG_BM3_BASE;
+ reg_addr = IOCFG_BM2_BASE;
break;
case REG_7:
- reg_addr = IOCFG_LT_BASE;
+ reg_addr = IOCFG_BM3_BASE;
break;
case REG_8:
- reg_addr = IOCFG_LM1_BASE;
+ reg_addr = IOCFG_LT_BASE;
break;
case REG_9:
- reg_addr = IOCFG_LM2_BASE;
+ reg_addr = IOCFG_LM1_BASE;
break;
case REG_10:
- reg_addr = IOCFG_LB1_BASE;
+ reg_addr = IOCFG_LM2_BASE;
break;
case REG_11:
- reg_addr = IOCFG_LB2_BASE;
+ reg_addr = IOCFG_LB1_BASE;
break;
case REG_12:
- reg_addr = IOCFG_TM1_BASE;
+ reg_addr = IOCFG_LB2_BASE;
break;
case REG_13:
- reg_addr = IOCFG_TM2_BASE;
+ reg_addr = IOCFG_TM1_BASE;
break;
case REG_14:
+ reg_addr = IOCFG_TM2_BASE;
+ break;
+ case REG_15:
reg_addr = IOCFG_TM3_BASE;
break;
default:
diff --git a/plat/mediatek/mt8196/drivers/gpio/mtgpio.h b/plat/mediatek/mt8196/drivers/gpio/mtgpio.h
index a33bdad..ef8ee8c 100644
--- a/plat/mediatek/mt8196/drivers/gpio/mtgpio.h
+++ b/plat/mediatek/mt8196/drivers/gpio/mtgpio.h
@@ -50,131 +50,131 @@
} GPIO_PIN;
static const struct mt_pin_info mt_pin_infos[] = {
- PIN(0, 0, 0, 0x18, 0x90),
- PIN(1, 0, 1, 0x18, 0x90),
- PIN(2, 0, 1, 0x1b, 0x70),
- PIN(3, 0, 2, 0x1b, 0x70),
- PIN(4, 0, 3, 0x1b, 0x70),
- PIN(5, 0, 4, 0x1b, 0x70),
- PIN(6, 0, 5, 0x1b, 0x70),
- PIN(7, 0, 6, 0x1b, 0x70),
- PIN(8, 0, 7, 0x1b, 0x70),
- PIN(9, 0, 14, 0x29, 0xa0),
- PIN(10, 0, 12, 0x29, 0xa0),
- PIN(11, 0, 2, 0x18, 0x90),
- PIN(12, 0, 13, 0x29, 0xa0),
- PIN(13, 0, 1, 0x26, 0x90),
- PIN(14, 0, 0, 0x13, 0x80),
- PIN(15, 0, 2, 0x26, 0x90),
- PIN(16, 0, 3, 0x26, 0x90),
- PIN(17, 0, 4, 0x26, 0x90),
- PIN(18, 0, 5, 0x26, 0x90),
- PIN(19, 0, 6, 0x26, 0x90),
- PIN(20, 0, 1, 0x13, 0x80),
- PIN(21, 0, 3, 0x12, 0x80),
- PIN(22, 0, 4, 0x12, 0x80),
- PIN(23, 0, 5, 0x12, 0x80),
- PIN(24, 0, 6, 0x12, 0x80),
- PIN(25, 0, 7, 0x12, 0x80),
- PIN(26, 0, 8, 0x12, 0x80),
- PIN(27, 0, 9, 0x12, 0x80),
- PIN(28, 0, 10, 0x12, 0x80),
- PIN(29, 0, 11, 0x12, 0x80),
- PIN(30, 0, 12, 0x12, 0x80),
- PIN(31, 0, 13, 0x12, 0x80),
- PIN(32, 0, 8, 0x11, 0x80),
- PIN(33, 0, 9, 0x11, 0x80),
- PIN(34, 0, 10, 0x11, 0x80),
- PIN(35, 0, 11, 0x11, 0x80),
- PIN(36, 0, 12, 0x11, 0x80),
- PIN(37, 0, 13, 0x11, 0x80),
- PIN(38, 0, 14, 0x11, 0x80),
- PIN(39, 0, 6, 0x18, 0x90),
- PIN(40, 0, 3, 0x18, 0x90),
- PIN(41, 0, 5, 0x18, 0x90),
- PIN(42, 0, 4, 0x18, 0x90),
- PIN(43, 0, 7, 0x18, 0x90),
- PIN(44, 0, 8, 0x18, 0x90),
- PIN(45, 0, 9, 0x18, 0x90),
- PIN(46, 0, 10, 0x18, 0x90),
- PIN(47, 0, 13, 0x18, 0x90),
- PIN(48, 0, 11, 0x18, 0x90),
- PIN(49, 0, 14, 0x18, 0x90),
- PIN(50, 0, 12, 0x18, 0x90),
- PIN(51, 0, 15, 0x18, 0x90),
- PIN(52, 0, 7, 0x29, 0xa0),
- PIN(53, 0, 8, 0x29, 0xa0),
- PIN(54, 0, 2, 0x29, 0xa0),
- PIN(55, 0, 1, 0x29, 0xa0),
- PIN(56, 0, 5, 0x29, 0xa0),
- PIN(57, 0, 6, 0x29, 0xa0),
- PIN(58, 0, 3, 0x29, 0xa0),
- PIN(59, 0, 4, 0x29, 0xa0),
+ PIN(0, 0, 0, 0x18, 0xa0),
+ PIN(1, 0, 1, 0x18, 0xa0),
+ PIN(2, 0, 1, 0x1b, 0x80),
+ PIN(3, 0, 2, 0x1b, 0x80),
+ PIN(4, 0, 3, 0x1b, 0x80),
+ PIN(5, 0, 4, 0x1b, 0x80),
+ PIN(6, 0, 5, 0x1b, 0x80),
+ PIN(7, 0, 6, 0x1b, 0x80),
+ PIN(8, 0, 7, 0x1b, 0x80),
+ PIN(9, 0, 14, 0x29, 0xc0),
+ PIN(10, 0, 12, 0x29, 0xc0),
+ PIN(11, 0, 2, 0x18, 0xa0),
+ PIN(12, 0, 13, 0x29, 0xc0),
+ PIN(13, 0, 1, 0x26, 0xb0),
+ PIN(14, 0, 0, 0x13, 0x90),
+ PIN(15, 0, 2, 0x26, 0xb0),
+ PIN(16, 0, 3, 0x26, 0xb0),
+ PIN(17, 0, 4, 0x26, 0xb0),
+ PIN(18, 0, 5, 0x26, 0xb0),
+ PIN(19, 0, 6, 0x26, 0xb0),
+ PIN(20, 0, 1, 0x13, 0x90),
+ PIN(21, 0, 3, 0x12, 0x90),
+ PIN(22, 0, 4, 0x12, 0x90),
+ PIN(23, 0, 5, 0x12, 0x90),
+ PIN(24, 0, 6, 0x12, 0x90),
+ PIN(25, 0, 7, 0x12, 0x90),
+ PIN(26, 0, 8, 0x12, 0x90),
+ PIN(27, 0, 9, 0x12, 0x90),
+ PIN(28, 0, 10, 0x12, 0x90),
+ PIN(29, 0, 11, 0x12, 0x90),
+ PIN(30, 0, 12, 0x12, 0x90),
+ PIN(31, 0, 13, 0x12, 0x90),
+ PIN(32, 0, 8, 0x11, 0x90),
+ PIN(33, 0, 9, 0x11, 0x90),
+ PIN(34, 0, 10, 0x11, 0x90),
+ PIN(35, 0, 11, 0x11, 0x90),
+ PIN(36, 0, 12, 0x11, 0x90),
+ PIN(37, 0, 13, 0x11, 0x90),
+ PIN(38, 0, 14, 0x11, 0x90),
+ PIN(39, 0, 6, 0x18, 0xa0),
+ PIN(40, 0, 3, 0x18, 0xa0),
+ PIN(41, 0, 5, 0x18, 0xa0),
+ PIN(42, 0, 4, 0x18, 0xa0),
+ PIN(43, 0, 7, 0x18, 0xa0),
+ PIN(44, 0, 8, 0x18, 0xa0),
+ PIN(45, 0, 9, 0x18, 0xa0),
+ PIN(46, 0, 10, 0x18, 0xa0),
+ PIN(47, 0, 13, 0x18, 0xa0),
+ PIN(48, 0, 11, 0x18, 0xa0),
+ PIN(49, 0, 14, 0x18, 0xa0),
+ PIN(50, 0, 12, 0x18, 0xa0),
+ PIN(51, 0, 15, 0x18, 0xa0),
+ PIN(52, 0, 7, 0x29, 0xc0),
+ PIN(53, 0, 8, 0x29, 0xc0),
+ PIN(54, 0, 2, 0x29, 0xc0),
+ PIN(55, 0, 1, 0x29, 0xc0),
+ PIN(56, 0, 5, 0x29, 0xc0),
+ PIN(57, 0, 6, 0x29, 0xc0),
+ PIN(58, 0, 3, 0x29, 0xc0),
+ PIN(59, 0, 4, 0x29, 0xc0),
PIN(60, 1, 0, 0x29, 0xb0),
- PIN(61, 0, 10, 0x29, 0xa0),
- PIN(62, 0, 9, 0x29, 0xa0),
- PIN(63, 0, 18, 0x29, 0xa0),
- PIN(64, 0, 0, 0x29, 0xa0),
- PIN(65, 0, 11, 0x29, 0xa0),
- PIN(66, 0, 24, 0x29, 0xa0),
- PIN(67, 0, 21, 0x29, 0xa0),
- PIN(68, 0, 20, 0x29, 0xa0),
- PIN(69, 0, 25, 0x29, 0xa0),
- PIN(70, 0, 16, 0x29, 0xa0),
- PIN(71, 0, 15, 0x29, 0xa0),
- PIN(72, 0, 23, 0x29, 0xa0),
- PIN(73, 0, 19, 0x29, 0xa0),
- PIN(74, 0, 17, 0x29, 0xa0),
- PIN(75, 0, 2, 0x1a, 0x80),
- PIN(76, 0, 3, 0x1a, 0x80),
- PIN(77, 0, 4, 0x1a, 0x80),
- PIN(78, 0, 5, 0x1a, 0x80),
- PIN(79, 0, 0, 0x1a, 0x80),
- PIN(80, 0, 1, 0x1a, 0x80),
- PIN(81, 0, 9, 0x1b, 0x70),
- PIN(82, 0, 10, 0x1b, 0x70),
- PIN(83, 0, 12, 0x1b, 0x70),
- PIN(84, 0, 11, 0x1b, 0x70),
- PIN(85, 0, 13, 0x1b, 0x70),
- PIN(86, 0, 14, 0x1b, 0x70),
- PIN(87, 0, 16, 0x1b, 0x70),
- PIN(88, 0, 15, 0x1b, 0x70),
- PIN(89, 0, 0, 0x1b, 0x70),
- PIN(90, 0, 8, 0x1b, 0x70),
- PIN(91, 0, 6, 0x1c, 0x80),
- PIN(92, 0, 7, 0x1c, 0x80),
- PIN(93, 0, 8, 0x1c, 0x80),
- PIN(94, 0, 4, 0x1c, 0x80),
- PIN(95, 0, 1, 0x1c, 0x80),
- PIN(96, 0, 3, 0x1c, 0x80),
- PIN(97, 0, 2, 0x1c, 0x80),
- PIN(98, 0, 5, 0x1c, 0x80),
- PIN(99, 0, 9, 0x1c, 0x80),
- PIN(100, 0, 12, 0x1c, 0x80),
- PIN(101, 0, 10, 0x1c, 0x80),
- PIN(102, 0, 13, 0x1c, 0x80),
- PIN(103, 0, 0, 0x1c, 0x80),
- PIN(104, 0, 11, 0x1c, 0x80),
- PIN(105, 0, 14, 0x1c, 0x80),
- PIN(106, 0, 0, 0x15, 0x80),
- PIN(107, 0, 1, 0x15, 0x80),
- PIN(108, 0, 3, 0x15, 0x80),
- PIN(109, 0, 2, 0x15, 0x80),
- PIN(110, 0, 4, 0x15, 0x80),
- PIN(111, 0, 5, 0x15, 0x80),
- PIN(112, 0, 7, 0x15, 0x80),
- PIN(113, 0, 6, 0x15, 0x80),
- PIN(114, 0, 8, 0x15, 0x80),
- PIN(115, 0, 9, 0x15, 0x80),
- PIN(116, 0, 11, 0x15, 0x80),
- PIN(117, 0, 10, 0x15, 0x80),
- PIN(118, 0, 9, 0x26, 0x90),
- PIN(119, 0, 10, 0x26, 0x90),
- PIN(120, 0, 12, 0x26, 0x90),
- PIN(121, 0, 11, 0x26, 0x90),
- PIN(122, 0, 0, 0x26, 0x90),
- PIN(123, 0, 7, 0x26, 0x90),
- PIN(124, 0, 8, 0x26, 0x90),
+ PIN(61, 0, 10, 0x29, 0xc0),
+ PIN(62, 0, 9, 0x29, 0xc0),
+ PIN(63, 0, 18, 0x29, 0xc0),
+ PIN(64, 0, 0, 0x29, 0xc0),
+ PIN(65, 0, 11, 0x29, 0xc0),
+ PIN(66, 0, 24, 0x29, 0xc0),
+ PIN(67, 0, 21, 0x29, 0xc0),
+ PIN(68, 0, 20, 0x29, 0xc0),
+ PIN(69, 0, 25, 0x29, 0xc0),
+ PIN(70, 0, 16, 0x29, 0xc0),
+ PIN(71, 0, 15, 0x29, 0xc0),
+ PIN(72, 0, 23, 0x29, 0xc0),
+ PIN(73, 0, 19, 0x29, 0xc0),
+ PIN(74, 0, 17, 0x29, 0xc0),
+ PIN(75, 0, 2, 0x1a, 0x90),
+ PIN(76, 0, 3, 0x1a, 0x90),
+ PIN(77, 0, 4, 0x1a, 0x90),
+ PIN(78, 0, 5, 0x1a, 0x90),
+ PIN(79, 0, 0, 0x1a, 0x90),
+ PIN(80, 0, 1, 0x1a, 0x90),
+ PIN(81, 0, 9, 0x1b, 0x80),
+ PIN(82, 0, 10, 0x1b, 0x80),
+ PIN(83, 0, 12, 0x1b, 0x80),
+ PIN(84, 0, 11, 0x1b, 0x80),
+ PIN(85, 0, 13, 0x1b, 0x80),
+ PIN(86, 0, 14, 0x1b, 0x80),
+ PIN(87, 0, 16, 0x1b, 0x80),
+ PIN(88, 0, 15, 0x1b, 0x80),
+ PIN(89, 0, 0, 0x1b, 0x80),
+ PIN(90, 0, 8, 0x1b, 0x80),
+ PIN(91, 0, 6, 0x1c, 0x90),
+ PIN(92, 0, 7, 0x1c, 0x90),
+ PIN(93, 0, 8, 0x1c, 0x90),
+ PIN(94, 0, 4, 0x1c, 0x90),
+ PIN(95, 0, 1, 0x1c, 0x90),
+ PIN(96, 0, 3, 0x1c, 0x90),
+ PIN(97, 0, 2, 0x1c, 0x90),
+ PIN(98, 0, 5, 0x1c, 0x90),
+ PIN(99, 0, 9, 0x1c, 0x90),
+ PIN(100, 0, 12, 0x1c, 0x90),
+ PIN(101, 0, 10, 0x1c, 0x90),
+ PIN(102, 0, 13, 0x1c, 0x90),
+ PIN(103, 0, 0, 0x1c, 0x90),
+ PIN(104, 0, 11, 0x1c, 0x90),
+ PIN(105, 0, 14, 0x1c, 0x90),
+ PIN(106, 0, 0, 0x15, 0x90),
+ PIN(107, 0, 1, 0x15, 0x90),
+ PIN(108, 0, 3, 0x15, 0x90),
+ PIN(109, 0, 2, 0x15, 0x90),
+ PIN(110, 0, 4, 0x15, 0x90),
+ PIN(111, 0, 5, 0x15, 0x90),
+ PIN(112, 0, 7, 0x15, 0x90),
+ PIN(113, 0, 6, 0x15, 0x90),
+ PIN(114, 0, 8, 0x15, 0x90),
+ PIN(115, 0, 9, 0x15, 0x90),
+ PIN(116, 0, 11, 0x15, 0x90),
+ PIN(117, 0, 10, 0x15, 0x90),
+ PIN(118, 0, 9, 0x26, 0xb0),
+ PIN(119, 0, 10, 0x26, 0xb0),
+ PIN(120, 0, 12, 0x26, 0xb0),
+ PIN(121, 0, 11, 0x26, 0xb0),
+ PIN(122, 0, 0, 0x26, 0xb0),
+ PIN(123, 0, 7, 0x26, 0xb0),
+ PIN(124, 0, 8, 0x26, 0xb0),
PIN(125, 1, 0, 0x17, 0x80),
PIN(126, 1, 1, 0x17, 0x80),
PIN(127, 1, 2, 0x17, 0x80),
@@ -207,108 +207,108 @@
PIN(154, 1, 8, 0x14, 0x70),
PIN(155, 1, 18, 0x14, 0x70),
PIN(156, 1, 19, 0x14, 0x70),
- PIN(157, 0, 1, 0x12, 0x80),
- PIN(158, 0, 2, 0x12, 0x80),
- PIN(159, 0, 0, 0x12, 0x80),
- PIN(160, 0, 22, 0x13, 0x80),
- PIN(161, 0, 20, 0x13, 0x80),
- PIN(162, 0, 23, 0x13, 0x80),
- PIN(163, 0, 21, 0x13, 0x80),
- PIN(164, 0, 12, 0x13, 0x80),
- PIN(165, 0, 14, 0x13, 0x80),
- PIN(166, 0, 13, 0x13, 0x80),
- PIN(167, 0, 15, 0x13, 0x80),
- PIN(168, 0, 16, 0x13, 0x80),
- PIN(169, 0, 17, 0x13, 0x80),
- PIN(170, 0, 19, 0x13, 0x80),
- PIN(171, 0, 18, 0x13, 0x80),
- PIN(172, 0, 10, 0x13, 0x80),
- PIN(173, 0, 11, 0x13, 0x80),
- PIN(174, 0, 15, 0x11, 0x80),
- PIN(175, 0, 16, 0x11, 0x80),
- PIN(176, 0, 17, 0x11, 0x80),
- PIN(177, 0, 18, 0x11, 0x80),
- PIN(178, 0, 6, 0x11, 0x80),
- PIN(179, 0, 7, 0x11, 0x80),
- PIN(180, 0, 0, 0x11, 0x80),
- PIN(181, 0, 1, 0x11, 0x80),
- PIN(182, 0, 2, 0x11, 0x80),
- PIN(183, 0, 3, 0x11, 0x80),
- PIN(184, 0, 4, 0x11, 0x80),
- PIN(185, 0, 5, 0x11, 0x80),
- PIN(186, 0, 4, 0x1d, 0xc0),
- PIN(187, 0, 5, 0x1d, 0xc0),
- PIN(188, 0, 12, 0x1d, 0xc0),
- PIN(189, 0, 17, 0x1d, 0xc0),
- PIN(190, 0, 13, 0x1d, 0xc0),
- PIN(191, 0, 18, 0x1d, 0xc0),
- PIN(192, 0, 0, 0x1d, 0xc0),
- PIN(193, 0, 6, 0x1d, 0xc0),
- PIN(194, 0, 14, 0x1d, 0xc0),
- PIN(195, 0, 19, 0x1d, 0xc0),
- PIN(196, 0, 1, 0x1d, 0xc0),
- PIN(197, 0, 7, 0x1d, 0xc0),
- PIN(198, 0, 15, 0x1d, 0xc0),
- PIN(199, 0, 20, 0x1d, 0xc0),
- PIN(200, 0, 22, 0x1d, 0xc0),
- PIN(201, 0, 25, 0x1d, 0xc0),
- PIN(202, 0, 16, 0x1d, 0xc0),
- PIN(203, 0, 21, 0x1d, 0xc0),
- PIN(204, 0, 2, 0x1d, 0xc0),
- PIN(205, 0, 3, 0x1d, 0xc0),
- PIN(206, 0, 8, 0x1d, 0xc0),
- PIN(207, 0, 9, 0x1d, 0xc0),
- PIN(208, 0, 10, 0x1d, 0xc0),
- PIN(209, 0, 11, 0x1d, 0xc0),
- PIN(210, 0, 0, 0x2e, 0x90),
- PIN(211, 0, 1, 0x2e, 0x90),
- PIN(212, 0, 2, 0x2e, 0x90),
- PIN(213, 0, 3, 0x2e, 0x90),
- PIN(214, 0, 23, 0x1d, 0xc0),
- PIN(215, 0, 24, 0x1d, 0xc0),
- PIN(216, 0, 4, 0x2e, 0x90),
+ PIN(157, 0, 1, 0x12, 0x90),
+ PIN(158, 0, 2, 0x12, 0x90),
+ PIN(159, 0, 0, 0x12, 0x90),
+ PIN(160, 0, 22, 0x13, 0x90),
+ PIN(161, 0, 20, 0x13, 0x90),
+ PIN(162, 0, 23, 0x13, 0x90),
+ PIN(163, 0, 21, 0x13, 0x90),
+ PIN(164, 0, 12, 0x13, 0x90),
+ PIN(165, 0, 14, 0x13, 0x90),
+ PIN(166, 0, 13, 0x13, 0x90),
+ PIN(167, 0, 15, 0x13, 0x90),
+ PIN(168, 0, 16, 0x13, 0x90),
+ PIN(169, 0, 17, 0x13, 0x90),
+ PIN(170, 0, 19, 0x13, 0x90),
+ PIN(171, 0, 18, 0x13, 0x90),
+ PIN(172, 0, 10, 0x13, 0x90),
+ PIN(173, 0, 11, 0x13, 0x90),
+ PIN(174, 0, 15, 0x11, 0x90),
+ PIN(175, 0, 16, 0x11, 0x90),
+ PIN(176, 0, 17, 0x11, 0x90),
+ PIN(177, 0, 18, 0x11, 0x90),
+ PIN(178, 0, 6, 0x11, 0x90),
+ PIN(179, 0, 7, 0x11, 0x90),
+ PIN(180, 0, 0, 0x11, 0x90),
+ PIN(181, 0, 1, 0x11, 0x90),
+ PIN(182, 0, 2, 0x11, 0x90),
+ PIN(183, 0, 3, 0x11, 0x90),
+ PIN(184, 0, 4, 0x11, 0x90),
+ PIN(185, 0, 5, 0x11, 0x90),
+ PIN(186, 0, 4, 0x1d, 0xd0),
+ PIN(187, 0, 5, 0x1d, 0xd0),
+ PIN(188, 0, 12, 0x1d, 0xd0),
+ PIN(189, 0, 17, 0x1d, 0xd0),
+ PIN(190, 0, 13, 0x1d, 0xd0),
+ PIN(191, 0, 18, 0x1d, 0xd0),
+ PIN(192, 0, 0, 0x1d, 0xd0),
+ PIN(193, 0, 6, 0x1d, 0xd0),
+ PIN(194, 0, 14, 0x1d, 0xd0),
+ PIN(195, 0, 19, 0x1d, 0xd0),
+ PIN(196, 0, 1, 0x1d, 0xd0),
+ PIN(197, 0, 7, 0x1d, 0xd0),
+ PIN(198, 0, 15, 0x1d, 0xd0),
+ PIN(199, 0, 20, 0x1d, 0xd0),
+ PIN(200, 0, 22, 0x1d, 0xd0),
+ PIN(201, 0, 25, 0x1d, 0xd0),
+ PIN(202, 0, 16, 0x1d, 0xd0),
+ PIN(203, 0, 21, 0x1d, 0xd0),
+ PIN(204, 0, 2, 0x1d, 0xd0),
+ PIN(205, 0, 3, 0x1d, 0xd0),
+ PIN(206, 0, 8, 0x1d, 0xd0),
+ PIN(207, 0, 9, 0x1d, 0xd0),
+ PIN(208, 0, 10, 0x1d, 0xd0),
+ PIN(209, 0, 11, 0x1d, 0xd0),
+ PIN(210, 0, 0, 0x2e, 0xb0),
+ PIN(211, 0, 1, 0x2e, 0xb0),
+ PIN(212, 0, 2, 0x2e, 0xb0),
+ PIN(213, 0, 3, 0x2e, 0xb0),
+ PIN(214, 0, 23, 0x1d, 0xd0),
+ PIN(215, 0, 24, 0x1d, 0xd0),
+ PIN(216, 0, 4, 0x2e, 0xb0),
PIN(217, 1, 1, 0x2e, 0xa0),
PIN(218, 1, 2, 0x2e, 0xa0),
PIN(219, 1, 0, 0x2e, 0xa0),
- PIN(220, 0, 5, 0x2e, 0x90),
- PIN(221, 0, 6, 0x2e, 0x90),
- PIN(222, 0, 8, 0x2e, 0x90),
- PIN(223, 0, 7, 0x2e, 0x90),
+ PIN(220, 0, 5, 0x2e, 0xb0),
+ PIN(221, 0, 6, 0x2e, 0xb0),
+ PIN(222, 0, 8, 0x2e, 0xb0),
+ PIN(223, 0, 7, 0x2e, 0xb0),
PIN(224, 1, 3, 0x2e, 0xa0),
PIN(225, 1, 4, 0x2e, 0xa0),
PIN(226, 1, 5, 0x2e, 0xa0),
PIN(227, 1, 6, 0x2e, 0xa0),
PIN(228, 1, 7, 0x2e, 0xa0),
PIN(229, 1, 8, 0x2e, 0xa0),
- PIN(230, 0, 13, 0x2f, 0x70),
- PIN(231, 0, 14, 0x2f, 0x70),
- PIN(232, 0, 10, 0x2f, 0x70),
- PIN(233, 0, 0, 0x2f, 0x70),
- PIN(234, 0, 3, 0x2f, 0x70),
- PIN(235, 0, 1, 0x2f, 0x70),
- PIN(236, 0, 2, 0x2f, 0x70),
- PIN(237, 0, 6, 0x2f, 0x70),
- PIN(238, 0, 5, 0x2f, 0x70),
- PIN(239, 0, 19, 0x2f, 0x70),
- PIN(240, 0, 18, 0x2f, 0x70),
- PIN(241, 0, 16, 0x2f, 0x70),
- PIN(242, 0, 17, 0x2f, 0x70),
- PIN(243, 0, 15, 0x2f, 0x70),
- PIN(244, 0, 12, 0x2f, 0x70),
- PIN(245, 0, 9, 0x2f, 0x70),
- PIN(246, 0, 8, 0x2f, 0x70),
- PIN(247, 0, 7, 0x2f, 0x70),
- PIN(248, 0, 4, 0x2f, 0x70),
- PIN(249, 0, 20, 0x2f, 0x70),
- PIN(250, 0, 11, 0x2f, 0x70),
- PIN(251, 0, 2, 0x13, 0x80),
- PIN(252, 0, 3, 0x13, 0x80),
- PIN(253, 0, 4, 0x13, 0x80),
- PIN(254, 0, 5, 0x13, 0x80),
- PIN(255, 0, 6, 0x13, 0x80),
- PIN(256, 0, 7, 0x13, 0x80),
- PIN(257, 0, 8, 0x13, 0x80),
- PIN(258, 0, 9, 0x13, 0x80),
+ PIN(230, 0, 13, 0x2f, 0x90),
+ PIN(231, 0, 14, 0x2f, 0x90),
+ PIN(232, 0, 10, 0x2f, 0x90),
+ PIN(233, 0, 0, 0x2f, 0x90),
+ PIN(234, 0, 3, 0x2f, 0x90),
+ PIN(235, 0, 1, 0x2f, 0x90),
+ PIN(236, 0, 2, 0x2f, 0x90),
+ PIN(237, 0, 6, 0x2f, 0x90),
+ PIN(238, 0, 5, 0x2f, 0x90),
+ PIN(239, 0, 19, 0x2f, 0x90),
+ PIN(240, 0, 18, 0x2f, 0x90),
+ PIN(241, 0, 16, 0x2f, 0x90),
+ PIN(242, 0, 17, 0x2f, 0x90),
+ PIN(243, 0, 15, 0x2f, 0x90),
+ PIN(244, 0, 12, 0x2f, 0x90),
+ PIN(245, 0, 9, 0x2f, 0x90),
+ PIN(246, 0, 8, 0x2f, 0x90),
+ PIN(247, 0, 7, 0x2f, 0x90),
+ PIN(248, 0, 4, 0x2f, 0x90),
+ PIN(249, 0, 20, 0x2f, 0x90),
+ PIN(250, 0, 11, 0x2f, 0x90),
+ PIN(251, 0, 2, 0x13, 0x90),
+ PIN(252, 0, 3, 0x13, 0x90),
+ PIN(253, 0, 4, 0x13, 0x90),
+ PIN(254, 0, 5, 0x13, 0x90),
+ PIN(255, 0, 6, 0x13, 0x90),
+ PIN(256, 0, 7, 0x13, 0x90),
+ PIN(257, 0, 8, 0x13, 0x90),
+ PIN(258, 0, 9, 0x13, 0x90),
PIN(259, 1, 9, 0x2e, 0xa0),
PIN(260, 1, 10, 0x2e, 0xa0),
PIN(261, 1, 11, 0x2e, 0xa0),
diff --git a/plat/nuvoton/npcm845x/npcm845x_psci.c b/plat/nuvoton/npcm845x/npcm845x_psci.c
index a954265..6e9523e 100644
--- a/plat/nuvoton/npcm845x/npcm845x_psci.c
+++ b/plat/nuvoton/npcm845x/npcm845x_psci.c
@@ -384,7 +384,7 @@
/* For testing purposes only This PSCI states are not supported */
.pwr_domain_off = npcm845x_pwr_domain_off,
- .pwr_domain_pwr_down_wfi = npcm845x_pwr_down_wfi,
+ .pwr_domain_pwr_down = npcm845x_pwr_down_wfi,
};
/* For reference only
@@ -400,7 +400,7 @@
* const psci_power_state_t *target_state);
* void (*pwr_domain_suspend_finish)(
* const psci_power_state_t *target_state);
- * void __dead2 (*pwr_domain_pwr_down_wfi)(
+ * void __dead2 (*pwr_domain_pwr_down )(
* const psci_power_state_t *target_state);
* void __dead2 (*system_off)(void);
* void __dead2 (*system_reset)(void);
diff --git a/plat/nvidia/tegra/common/tegra_pm.c b/plat/nvidia/tegra/common/tegra_pm.c
index 8edb024..234cb6b 100644
--- a/plat/nvidia/tegra/common/tegra_pm.c
+++ b/plat/nvidia/tegra/common/tegra_pm.c
@@ -284,7 +284,7 @@
.pwr_domain_suspend = tegra_pwr_domain_suspend,
.pwr_domain_on_finish = tegra_pwr_domain_on_finish,
.pwr_domain_suspend_finish = tegra_pwr_domain_suspend_finish,
- .pwr_domain_pwr_down_wfi = tegra_pwr_domain_power_down_wfi,
+ .pwr_domain_pwr_down = tegra_pwr_domain_power_down_wfi,
.system_off = tegra_system_off,
.system_reset = tegra_system_reset,
.validate_power_state = tegra_validate_power_state,
diff --git a/plat/nxp/common/psci/plat_psci.c b/plat/nxp/common/psci/plat_psci.c
index f6dd7b3..c154a7f 100644
--- a/plat/nxp/common/psci/plat_psci.c
+++ b/plat/nxp/common/psci/plat_psci.c
@@ -433,7 +433,7 @@
.pwr_domain_off = _pwr_domain_off,
#endif
#if (SOC_CORE_OFF || SOC_CORE_PWR_DWN)
- .pwr_domain_pwr_down_wfi = _pwr_down_wfi,
+ .pwr_domain_pwr_down = _pwr_down_wfi,
#endif
#if (SOC_CORE_STANDBY || SOC_CORE_PWR_DWN)
/* cpu_suspend */
diff --git a/plat/qemu/common/common.mk b/plat/qemu/common/common.mk
index 5e3a61a..da981e5 100644
--- a/plat/qemu/common/common.mk
+++ b/plat/qemu/common/common.mk
@@ -23,7 +23,6 @@
lib/cpus/aarch64/cortex_a72.S \
lib/cpus/aarch64/cortex_a76.S \
lib/cpus/aarch64/cortex_a710.S \
- lib/cpus/aarch64/neoverse_n_common.S \
lib/cpus/aarch64/neoverse_n1.S \
lib/cpus/aarch64/neoverse_v1.S \
lib/cpus/aarch64/neoverse_n2.S \
@@ -153,4 +152,12 @@
PLAT_BL_COMMON_SOURCES += plat/arm/common/aarch64/arm_pauth.c
endif
+ifeq (${TRANSFER_LIST}, 1)
+include lib/transfer_list/transfer_list.mk
+endif
+
+ifeq (${HOB_LIST}, 1)
+include lib/hob/hob.mk
+endif
+
endif
diff --git a/plat/qemu/common/qemu_bl31_setup.c b/plat/qemu/common/qemu_bl31_setup.c
index 81ce102..1c5e0ea 100644
--- a/plat/qemu/common/qemu_bl31_setup.c
+++ b/plat/qemu/common/qemu_bl31_setup.c
@@ -46,6 +46,30 @@
MT_DEVICE | MT_RW | EL3_PAS)
#endif
+#if ENABLE_RME
+#if (RME_GPT_BITLOCK_BLOCK == 0)
+#define BITLOCK_BASE UL(0)
+#define BITLOCK_SIZE UL(0)
+#else
+
+/*
+ * Number of bitlock_t entries in the gpt_bitlock array for this platform's
+ * Protected Physical Size. One 8-bit bitlock_t entry covers
+ * 8 * RME_GPT_BITLOCK_BLOCK * 512MB.
+ */
+#if (PLAT_QEMU_PPS > (RME_GPT_BITLOCK_BLOCK * SZ_512M * UL(8)))
+#define BITLOCKS_NUM (PLAT_QEMU_PPS / \
+ (RME_GPT_BITLOCK_BLOCK * SZ_512M * UL(8)))
+#else
+#define BITLOCKS_NUM 1
+#endif
+
+static bitlock_t gpt_bitlock[BITLOCKS_NUM];
+#define BITLOCK_BASE (uintptr_t)gpt_bitlock
+#define BITLOCK_SIZE sizeof(gpt_bitlock)
+#endif /* RME_GPT_BITLOCK_BLOCK */
+#endif /* ENABLE_RME */
+
/*
* Placeholder variables for copying the arguments that have been passed to
* BL3-1 from BL2.
@@ -202,9 +226,8 @@
* 256TB of RAM (48-bit PA) would require a 2MB L0 region. At the
* moment we use a 8KB table, which covers 1TB of RAM (40-bit PA).
*/
- if (gpt_init_l0_tables(PLATFORM_GPCCR_PPS, PLAT_QEMU_L0_GPT_BASE,
- PLAT_QEMU_L0_GPT_SIZE +
- PLAT_QEMU_GPT_BITLOCK_SIZE) < 0) {
+ if (gpt_init_l0_tables(PLAT_QEMU_GPCCR_PPS, PLAT_QEMU_L0_GPT_BASE,
+ PLAT_QEMU_L0_GPT_SIZE) < 0) {
ERROR("gpt_init_l0_tables() failed!\n");
panic();
}
@@ -260,7 +283,7 @@
* stage, so there is no need to provide any PAS here. This function
* sets up pointers to those tables.
*/
- if (gpt_runtime_init() < 0) {
+ if (gpt_runtime_init(BITLOCK_BASE, BITLOCK_SIZE) < 0) {
ERROR("gpt_runtime_init() failed!\n");
panic();
}
diff --git a/plat/qemu/common/qemu_common.c b/plat/qemu/common/qemu_common.c
index 5dc39a1..a88297d 100644
--- a/plat/qemu/common/qemu_common.c
+++ b/plat/qemu/common/qemu_common.c
@@ -233,7 +233,7 @@
return 1;
}
-static void plat_get_memory_node(int index, struct ns_dram_bank *bank_ptr)
+static void plat_get_memory_node(int index, struct memory_bank *bank_ptr)
{
(void) index;
bank_ptr->base = NS_DRAM0_BASE;
@@ -245,7 +245,7 @@
return sbsa_platform_num_memnodes();
}
-static void plat_get_memory_node(int index, struct ns_dram_bank *bank_ptr)
+static void plat_get_memory_node(int index, struct memory_bank *bank_ptr)
{
struct platform_memory_data data = {0, 0, 0};
@@ -281,7 +281,7 @@
uint64_t checksum;
size_t num_banks = plat_get_num_memnodes();
size_t num_consoles = 1;
- struct ns_dram_bank *bank_ptr;
+ struct memory_bank *bank_ptr;
struct console_info *console_ptr;
assert(manifest != NULL);
@@ -333,7 +333,7 @@
* | 120 | flags | |
* +----------+--------------+--------------+
*/
- bank_ptr = (struct ns_dram_bank *)
+ bank_ptr = (struct memory_bank *)
(((uintptr_t)manifest) + sizeof(*manifest));
console_ptr = (struct console_info *)
@@ -345,7 +345,7 @@
/* Ensure the manifest is not larger than the shared buffer */
assert((sizeof(struct rmm_manifest) +
(sizeof(struct console_info) * num_consoles) +
- (sizeof(struct ns_dram_bank) * num_banks)) <= RMM_SHARED_SIZE);
+ (sizeof(struct memory_bank) * num_banks)) <= RMM_SHARED_SIZE);
/* Calculate checksum of plat_dram structure */
checksum = num_banks + (uint64_t)bank_ptr;
diff --git a/plat/qemu/common/qemu_pm.c b/plat/qemu/common/qemu_pm.c
index 5f64d70..7893c81 100644
--- a/plat/qemu/common/qemu_pm.c
+++ b/plat/qemu/common/qemu_pm.c
@@ -218,7 +218,7 @@
.cpu_standby = qemu_cpu_standby,
.pwr_domain_on = qemu_pwr_domain_on,
.pwr_domain_off = qemu_pwr_domain_off,
- .pwr_domain_pwr_down_wfi = qemu_pwr_domain_pwr_down_wfi,
+ .pwr_domain_pwr_down = qemu_pwr_domain_pwr_down_wfi,
.pwr_domain_suspend = qemu_pwr_domain_suspend,
.pwr_domain_on_finish = qemu_pwr_domain_on_finish,
.pwr_domain_suspend_finish = qemu_pwr_domain_suspend_finish,
diff --git a/plat/qemu/qemu/include/platform_def.h b/plat/qemu/qemu/include/platform_def.h
index 0c85b1e..7dd7dcd 100644
--- a/plat/qemu/qemu/include/platform_def.h
+++ b/plat/qemu/qemu/include/platform_def.h
@@ -342,22 +342,16 @@
* Tables
*/
#define PLAT_QEMU_L0_GPT_BASE (PLAT_QEMU_L1_GPT_BASE - \
- (PLAT_QEMU_L0_GPT_SIZE + \
- PLAT_QEMU_GPT_BITLOCK_SIZE))
-#define PLAT_QEMU_L0_GPT_SIZE (2 * PAGE_SIZE)
-/* Two pages so the L0 GPT is naturally aligned. */
-#define PLAT_QEMU_GPT_BITLOCK_SIZE (2 * PAGE_SIZE)
+ PLAT_QEMU_L0_GPT_SIZE)
+#define PLAT_QEMU_L0_GPT_SIZE SZ_8K
#define PLAT_QEMU_L1_GPT_BASE (SEC_DRAM_BASE + SEC_DRAM_SIZE - \
PLAT_QEMU_L1_GPT_SIZE)
-#define PLAT_QEMU_L1_GPT_END (PLAT_QEMU_L1_GPT_BASE + \
- PLAT_QEMU_L1_GPT_SIZE - 1U)
-#define PLAT_QEMU_L1_GPT_SIZE UL(0x00100000) /* 1MB */
+#define PLAT_QEMU_L1_GPT_SIZE SZ_1M
#define RME_GPT_DRAM_BASE PLAT_QEMU_L0_GPT_BASE
#define RME_GPT_DRAM_SIZE (PLAT_QEMU_L1_GPT_SIZE + \
- PLAT_QEMU_L0_GPT_SIZE + \
- PLAT_QEMU_GPT_BITLOCK_SIZE)
+ PLAT_QEMU_L0_GPT_SIZE)
#ifndef __ASSEMBLER__
/* L0 table greater than 4KB must be naturally aligned */
@@ -379,8 +373,7 @@
#define MAP_GPT_L0_REGION MAP_REGION_FLAT( \
PLAT_QEMU_L0_GPT_BASE, \
- PLAT_QEMU_L0_GPT_SIZE + \
- PLAT_QEMU_GPT_BITLOCK_SIZE, \
+ PLAT_QEMU_L0_GPT_SIZE, \
MT_MEMORY | MT_RW | EL3_PAS)
#define MAP_GPT_L1_REGION MAP_REGION_FLAT( \
diff --git a/plat/qemu/qemu/include/qemu_pas_def.h b/plat/qemu/qemu/include/qemu_pas_def.h
index 30934f0..379519f 100644
--- a/plat/qemu/qemu/include/qemu_pas_def.h
+++ b/plat/qemu/qemu/include/qemu_pas_def.h
@@ -103,7 +103,8 @@
GPT_GPI_REALM)
/* Cover 1TB with L0GTP */
-#define PLATFORM_GPCCR_PPS GPCCR_PPS_1TB
+#define PLAT_QEMU_GPCCR_PPS GPCCR_PPS_1TB
+#define PLAT_QEMU_PPS SZ_1T
/* GPT Configuration options */
#define PLATFORM_L0GPTSZ GPCCR_L0GPTSZ_30BITS
diff --git a/plat/qemu/qemu/platform.mk b/plat/qemu/qemu/platform.mk
index 70e9faf..bd75abc 100644
--- a/plat/qemu/qemu/platform.mk
+++ b/plat/qemu/qemu/platform.mk
@@ -39,10 +39,6 @@
add-lib-optee := yes
endif
-ifeq (${TRANSFER_LIST},1)
-include lib/transfer_list/transfer_list.mk
-endif
-
ifeq ($(NEED_BL32),yes)
$(eval $(call add_define,QEMU_LOAD_BL32))
endif
diff --git a/plat/qemu/qemu_sbsa/include/platform_def.h b/plat/qemu/qemu_sbsa/include/platform_def.h
index 06e8abf..85bd233 100644
--- a/plat/qemu/qemu_sbsa/include/platform_def.h
+++ b/plat/qemu/qemu_sbsa/include/platform_def.h
@@ -150,9 +150,19 @@
*/
#define BL31_SIZE 0x400000
#define BL31_BASE (BL31_LIMIT - BL31_SIZE)
-#define BL31_LIMIT (BL1_RW_BASE)
+#define BL31_LIMIT (BL1_RW_BASE - FW_HANDOFF_SIZE)
#define BL31_PROGBITS_LIMIT BL1_RW_BASE
+#if TRANSFER_LIST
+#define FW_HANDOFF_BASE BL31_LIMIT
+#define FW_HANDOFF_LIMIT (FW_HANDOFF_BASE + FW_HANDOFF_SIZE)
+#define FW_HANDOFF_SIZE 0x4000
+#else
+#define FW_HANDOFF_SIZE 0
+#endif
+#if TRANSFER_LIST
+#define FW_NS_HANDOFF_BASE (NS_IMAGE_OFFSET - FW_HANDOFF_SIZE)
+#endif
/*
* BL3-2 specific defines.
@@ -174,14 +184,14 @@
#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 42)
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 42)
#if SPM_MM
-#define MAX_MMAP_REGIONS 12
-#define MAX_XLAT_TABLES 12
+#define MAX_MMAP_REGIONS 13
+#define MAX_XLAT_TABLES 13
#elif ENABLE_RME
-#define MAX_MMAP_REGIONS 14
-#define MAX_XLAT_TABLES 14
+#define MAX_MMAP_REGIONS 15
+#define MAX_XLAT_TABLES 15
#else
-#define MAX_MMAP_REGIONS 11
-#define MAX_XLAT_TABLES 11
+#define MAX_MMAP_REGIONS 12
+#define MAX_XLAT_TABLES 12
#endif
#define MAX_IO_DEVICES 3
#define MAX_IO_HANDLES 4
@@ -405,24 +415,8 @@
*/
#define PLAT_QEMU_L0_GPT_SIZE (8 * PAGE_SIZE)
#define PLAT_QEMU_L0_GPT_BASE (PLAT_QEMU_L1_GPT_BASE - \
- (PLAT_QEMU_L0_GPT_SIZE + \
- PLAT_QEMU_GPT_BITLOCK_SIZE + \
- PLAT_QEMU_GPT_ALIGNMENT))
+ PLAT_QEMU_L0_GPT_SIZE)
-#if RME_GPT_BITLOCK_BLOCK
-/*
- * 4TB / (RME_GPT_BITLOCK_BLOCK * 512M * 8) == 1024
- */
-#define PLAT_QEMU_GPT_BITLOCK_SIZE (1 * PAGE_SIZE)
-/*
- * PLAT_QEMU_L0_GPT_SIZE is 8 pages and PLAT_QEMU_GPT_BITLOCK_SIZE
- * is 1 page. As such we need 7 pages to have an 8 page alignment.
- */
-#define PLAT_QEMU_GPT_ALIGNMENT (7 * PAGE_SIZE)
-#else /* RME_GPT_BITLOCK_BLOCK */
-#define PLAT_QEMU_GPT_BITLOCK_SIZE 0
-#define PLAT_QEMU_GPT_ALIGNMENT 0
-#endif /* RME_GPT_BITLOCK_BLOCK */
/*
* If we have 1TB of RAM and each L1GPT covers 1GB, we need 1024 L1GPTs. With
@@ -433,14 +427,10 @@
#define PLAT_QEMU_L1_GPT_SIZE UL(0x08020000)
#define PLAT_QEMU_L1_GPT_BASE (BL_RAM_BASE + BL_RAM_SIZE - \
PLAT_QEMU_L1_GPT_SIZE)
-#define PLAT_QEMU_L1_GPT_END (PLAT_QEMU_L1_GPT_BASE + \
- PLAT_QEMU_L1_GPT_SIZE - 1U)
#define RME_GPT_DRAM_BASE PLAT_QEMU_L0_GPT_BASE
#define RME_GPT_DRAM_SIZE (PLAT_QEMU_L1_GPT_SIZE + \
- PLAT_QEMU_L0_GPT_SIZE + \
- PLAT_QEMU_GPT_BITLOCK_SIZE + \
- PLAT_QEMU_GPT_ALIGNMENT)
+ PLAT_QEMU_L0_GPT_SIZE)
#ifndef __ASSEMBLER__
/* L0 table greater than 4KB must be naturally aligned */
@@ -462,9 +452,7 @@
#define MAP_GPT_L0_REGION MAP_REGION_FLAT( \
PLAT_QEMU_L0_GPT_BASE, \
- (PLAT_QEMU_L0_GPT_SIZE + \
- PLAT_QEMU_GPT_BITLOCK_SIZE + \
- PLAT_QEMU_GPT_ALIGNMENT), \
+ (PLAT_QEMU_L0_GPT_SIZE), \
MT_MEMORY | MT_RW | EL3_PAS)
#define MAP_GPT_L1_REGION MAP_REGION_FLAT( \
diff --git a/plat/qemu/qemu_sbsa/include/qemu_sbsa_pas_def.h b/plat/qemu/qemu_sbsa/include/qemu_sbsa_pas_def.h
index c73a162..cf43a78 100644
--- a/plat/qemu/qemu_sbsa/include/qemu_sbsa_pas_def.h
+++ b/plat/qemu/qemu_sbsa/include/qemu_sbsa_pas_def.h
@@ -58,7 +58,8 @@
GPT_GPI_REALM)
/* Cover 4TB with L0GTP */
-#define PLATFORM_GPCCR_PPS GPCCR_PPS_4TB
+#define PLAT_QEMU_GPCCR_PPS GPCCR_PPS_4TB
+#define PLAT_QEMU_PPS SZ_4T
/* GPT Configuration options */
#define PLATFORM_L0GPTSZ GPCCR_L0GPTSZ_30BITS
diff --git a/plat/qemu/qemu_sbsa/sbsa_pm.c b/plat/qemu/qemu_sbsa/sbsa_pm.c
index 8d1e1d4..7ce7beb 100644
--- a/plat/qemu/qemu_sbsa/sbsa_pm.c
+++ b/plat/qemu/qemu_sbsa/sbsa_pm.c
@@ -215,7 +215,7 @@
.cpu_standby = qemu_cpu_standby,
.pwr_domain_on = qemu_pwr_domain_on,
.pwr_domain_off = qemu_pwr_domain_off,
- .pwr_domain_pwr_down_wfi = qemu_pwr_domain_pwr_down_wfi,
+ .pwr_domain_pwr_down = qemu_pwr_domain_pwr_down_wfi,
.pwr_domain_suspend = qemu_pwr_domain_suspend,
.pwr_domain_on_finish = qemu_pwr_domain_on_finish,
.pwr_domain_suspend_finish = qemu_pwr_domain_suspend_finish,
diff --git a/plat/qti/common/src/qti_pm.c b/plat/qti/common/src/qti_pm.c
index 1113efc..2428126 100644
--- a/plat/qti/common/src/qti_pm.c
+++ b/plat/qti/common/src/qti_pm.c
@@ -217,6 +217,7 @@
/* For now just do WFI - add any target specific handling if needed */
psci_power_down_wfi();
/* We should never reach here */
+ panic();
}
static __dead2 void assert_ps_hold(void)
@@ -277,7 +278,7 @@
.pwr_domain_off = qti_node_power_off,
.pwr_domain_suspend = qti_node_suspend,
.pwr_domain_suspend_finish = qti_node_suspend_finish,
- .pwr_domain_pwr_down_wfi = qti_domain_power_down_wfi,
+ .pwr_domain_pwr_down = qti_domain_power_down_wfi,
.system_off = qti_system_off,
.system_reset = qti_system_reset,
.get_node_hw_state = NULL,
diff --git a/plat/renesas/common/plat_pm.c b/plat/renesas/common/plat_pm.c
index 9810596..871dddc 100644
--- a/plat/renesas/common/plat_pm.c
+++ b/plat/renesas/common/plat_pm.c
@@ -302,7 +302,7 @@
.system_off = rcar_system_off,
.system_reset = rcar_system_reset,
.validate_power_state = rcar_validate_power_state,
- .pwr_domain_pwr_down_wfi = rcar_pwr_domain_pwr_down_wfi,
+ .pwr_domain_pwr_down = rcar_pwr_domain_pwr_down_wfi,
#if RCAR_SYSTEM_SUSPEND
.get_sys_suspend_power_state = rcar_get_sys_suspend_power_state,
#endif
diff --git a/plat/rockchip/common/aarch64/platform_common.c b/plat/rockchip/common/aarch64/platform_common.c
index df51d89..e88855a 100644
--- a/plat/rockchip/common/aarch64/platform_common.c
+++ b/plat/rockchip/common/aarch64/platform_common.c
@@ -1,9 +1,10 @@
/*
- * Copyright (c) 2013-2023, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <assert.h>
#include <string.h>
#include <platform_def.h>
@@ -58,7 +59,18 @@
unsigned int plat_get_syscnt_freq2(void)
{
+#ifdef SYS_COUNTER_FREQ_IN_TICKS
return SYS_COUNTER_FREQ_IN_TICKS;
+#else
+ static int sys_counter_freq_in_hz;
+
+ if (sys_counter_freq_in_hz == 0)
+ sys_counter_freq_in_hz = read_cntfrq_el0();
+
+ assert(sys_counter_freq_in_hz != 0);
+
+ return sys_counter_freq_in_hz;
+#endif
}
void plat_cci_init(void)
diff --git a/plat/rockchip/common/include/plat_private.h b/plat/rockchip/common/include/plat_private.h
index 1e13a9e..6388c47 100644
--- a/plat/rockchip/common/include/plat_private.h
+++ b/plat/rockchip/common/include/plat_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2023, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -28,6 +28,9 @@
extern uint32_t __bl31_sram_data_start, __bl31_sram_data_end;
extern uint32_t __bl31_sram_stack_start, __bl31_sram_stack_end;
extern uint32_t __bl31_sram_text_real_end, __bl31_sram_data_real_end;
+extern uint32_t __bl31_pmusram_text_start, __bl31_pmusram_text_end;
+extern uint32_t __bl31_pmusram_data_start, __bl31_pmusram_data_end;
+extern uint32_t __bl31_pmusram_text_real_end, __bl31_pmusram_data_real_end;
extern uint32_t __sram_incbin_start, __sram_incbin_end;
extern uint32_t __sram_incbin_real_end;
diff --git a/plat/rockchip/common/params_setup.c b/plat/rockchip/common/params_setup.c
index 68054ad..a27c755 100644
--- a/plat/rockchip/common/params_setup.c
+++ b/plat/rockchip/common/params_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2025, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -37,7 +37,7 @@
static uint32_t rk_uart_base = PLAT_RK_UART_BASE;
static uint32_t rk_uart_baudrate = PLAT_RK_UART_BAUDRATE;
static uint32_t rk_uart_clock = PLAT_RK_UART_CLOCK;
-#define FDT_BUFFER_SIZE 0x20000
+#define FDT_BUFFER_SIZE 0x60000
static uint64_t fdt_buffer[FDT_BUFFER_SIZE / 8];
void *plat_get_fdt(void)
diff --git a/plat/rockchip/common/plat_pm.c b/plat/rockchip/common/plat_pm.c
index 6926887..df74033 100644
--- a/plat/rockchip/common/plat_pm.c
+++ b/plat/rockchip/common/plat_pm.c
@@ -118,11 +118,15 @@
const psci_power_state_t *target_state)
{
psci_power_down_wfi();
+ /* should never reach here */
+ panic();
}
void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void)
{
psci_power_down_wfi();
+ /* should never reach here */
+ panic();
}
/*******************************************************************************
@@ -391,7 +395,7 @@
.pwr_domain_suspend = rockchip_pwr_domain_suspend,
.pwr_domain_on_finish = rockchip_pwr_domain_on_finish,
.pwr_domain_suspend_finish = rockchip_pwr_domain_suspend_finish,
- .pwr_domain_pwr_down_wfi = rockchip_pd_pwr_down_wfi,
+ .pwr_domain_pwr_down = rockchip_pd_pwr_down_wfi,
.system_reset = rockchip_system_reset,
.system_off = rockchip_system_poweroff,
.validate_power_state = rockchip_validate_power_state,
diff --git a/plat/rockchip/common/scmi/rockchip_common_clock.c b/plat/rockchip/common/scmi/rockchip_common_clock.c
new file mode 100644
index 0000000..d77bde3
--- /dev/null
+++ b/plat/rockchip/common/scmi/rockchip_common_clock.c
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <drivers/scmi.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#include <plat_private.h>
+#include <scmi_clock.h>
+
+#define MUX_ADDR_INFO 0
+#define MUX_SHIFT_INFO 1
+#define MUX_WIDTH_INFO 2
+#define DIV_ADDR_INFO 3
+#define DIV_SHIFT_INFO 4
+#define DIV_WIDTH_INFO 5
+#define GATE_ADDR_INFO 6
+#define GATE_SHIFT_INFO 7
+
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+
+#define abs(x) ({ \
+ long ret; \
+ if (sizeof(x) == sizeof(long)) { \
+ long __x = (x); \
+ ret = (__x < 0) ? -__x : __x; \
+ } else { \
+ int __x = (x); \
+ ret = (__x < 0) ? -__x : __x; \
+ } \
+ ret; \
+ })
+
+static unsigned long clk_scmi_common_get_parent_rate(rk_scmi_clock_t *clock,
+ int id)
+{
+ rk_scmi_clock_t *p_clock;
+
+ if (clock->is_dynamic_prate != 0) {
+ p_clock = rockchip_scmi_get_clock(0, clock->parent_table[id]);
+ if (p_clock == NULL)
+ return 0;
+ if ((p_clock->clk_ops != NULL) && (p_clock->clk_ops->get_rate != NULL))
+ return p_clock->clk_ops->get_rate(p_clock);
+ else
+ return 0;
+ } else {
+ return clock->parent_table[id];
+ }
+}
+
+unsigned long clk_scmi_common_get_rate(rk_scmi_clock_t *clock)
+{
+ unsigned long parent_rate, sel, div;
+
+ sel = mmio_read_32(clock->info[MUX_ADDR_INFO]) >>
+ clock->info[MUX_SHIFT_INFO];
+ sel = sel & (BIT(clock->info[MUX_WIDTH_INFO]) - 1);
+ div = mmio_read_32(clock->info[DIV_ADDR_INFO]) >>
+ clock->info[DIV_SHIFT_INFO];
+ div = div & (BIT(clock->info[DIV_WIDTH_INFO]) - 1);
+ parent_rate = clk_scmi_common_get_parent_rate(clock, sel);
+
+ return parent_rate / (div + 1);
+}
+
+int clk_scmi_common_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ unsigned long parent_rate, now, best_rate = 0;
+ int i = 0, sel_mask, div_mask, best_sel = 0, best_div = 0, div;
+
+ if ((rate == 0) ||
+ (clock->info[MUX_WIDTH_INFO] == 0 && clock->info[DIV_WIDTH_INFO] == 0))
+ return SCMI_INVALID_PARAMETERS;
+
+ sel_mask = BIT(clock->info[MUX_WIDTH_INFO]) - 1;
+ div_mask = BIT(clock->info[DIV_WIDTH_INFO]) - 1;
+ if (clock->info[MUX_WIDTH_INFO] == 0) {
+ parent_rate = clk_scmi_common_get_parent_rate(clock, 0);
+ div = DIV_ROUND_UP(parent_rate, rate);
+ if (div > div_mask + 1)
+ div = div_mask + 1;
+ mmio_write_32(clock->info[DIV_ADDR_INFO],
+ BITS_WITH_WMASK(div - 1, div_mask,
+ clock->info[DIV_SHIFT_INFO]));
+ } else if (clock->info[DIV_WIDTH_INFO] == 0) {
+ for (i = 0; i <= sel_mask; i++) {
+ parent_rate = clk_scmi_common_get_parent_rate(clock, i);
+ now = parent_rate;
+ if (abs(rate - now) < abs(rate - best_rate)) {
+ best_rate = now;
+ best_sel = i;
+ }
+ }
+ if (best_rate == 0)
+ best_sel = 0;
+ mmio_write_32(clock->info[MUX_ADDR_INFO],
+ BITS_WITH_WMASK(best_sel, sel_mask,
+ clock->info[MUX_SHIFT_INFO]));
+ } else {
+ for (i = 0; i <= sel_mask; i++) {
+ parent_rate = clk_scmi_common_get_parent_rate(clock, i);
+ div = DIV_ROUND_UP(parent_rate, rate);
+ if (div > div_mask + 1)
+ div = div_mask + 1;
+ now = parent_rate / div;
+ if (abs(rate - now) < abs(rate - best_rate)) {
+ best_rate = now;
+ best_div = div;
+ best_sel = i;
+ }
+ }
+ if (best_rate == 0) {
+ best_div = div_mask + 1;
+ best_sel = 0;
+ }
+
+ mmio_write_32(clock->info[DIV_ADDR_INFO],
+ BITS_WITH_WMASK(div_mask, div_mask,
+ clock->info[DIV_SHIFT_INFO]));
+ mmio_write_32(clock->info[MUX_ADDR_INFO],
+ BITS_WITH_WMASK(best_sel, sel_mask,
+ clock->info[MUX_SHIFT_INFO]));
+ mmio_write_32(clock->info[DIV_ADDR_INFO],
+ BITS_WITH_WMASK(best_div - 1, div_mask,
+ clock->info[DIV_SHIFT_INFO]));
+ }
+ return 0;
+}
+
+int clk_scmi_common_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(clock->info[GATE_ADDR_INFO],
+ BITS_WITH_WMASK(!status, 0x1U,
+ clock->info[GATE_SHIFT_INFO]));
+
+ return 0;
+}
diff --git a/plat/rockchip/common/scmi/scmi_clock.h b/plat/rockchip/common/scmi/scmi_clock.h
index e640fe1..4b94adf 100644
--- a/plat/rockchip/common/scmi/scmi_clock.h
+++ b/plat/rockchip/common/scmi/scmi_clock.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ * Copyright (c) 2025, Rockchip, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -23,11 +23,14 @@
char name[SCMI_CLOCK_NAME_LENGTH_MAX];
uint8_t enable;
int8_t is_security;
+ int8_t is_dynamic_prate;
uint32_t id;
uint32_t rate_cnt;
uint64_t cur_rate;
uint32_t enable_count;
const struct rk_clk_ops *clk_ops;
+ const unsigned long *parent_table;
+ const uint32_t *info;
unsigned long *rate_table;
} rk_scmi_clock_t;
@@ -47,4 +50,7 @@
rk_scmi_clock_t *rockchip_scmi_get_clock(uint32_t agent_id,
uint32_t scmi_id);
+unsigned long clk_scmi_common_get_rate(rk_scmi_clock_t *clock);
+int clk_scmi_common_set_rate(rk_scmi_clock_t *clock, unsigned long rate);
+int clk_scmi_common_set_status(rk_scmi_clock_t *clock, bool status);
#endif /* RK_SCMI_CLOCK_H */
diff --git a/plat/rockchip/px30/drivers/pmu/pmu.c b/plat/rockchip/px30/drivers/pmu/pmu.c
index 0d8e8b6..6200cac 100644
--- a/plat/rockchip/px30/drivers/pmu/pmu.c
+++ b/plat/rockchip/px30/drivers/pmu/pmu.c
@@ -1000,6 +1000,8 @@
* so we do not hope the core to execute valid codes.
*/
psci_power_down_wfi();
+ /* should never reach here */
+ panic();
}
void __dead2 rockchip_soc_system_off(void)
@@ -1025,6 +1027,8 @@
* so we do not hope the core to execute valid codes.
*/
psci_power_down_wfi();
+ /* should never reach here */
+ panic();
}
void rockchip_plat_mmu_el3(void)
diff --git a/plat/rockchip/rk3328/drivers/pmu/pmu.c b/plat/rockchip/rk3328/drivers/pmu/pmu.c
index 597db97..41660e2 100644
--- a/plat/rockchip/rk3328/drivers/pmu/pmu.c
+++ b/plat/rockchip/rk3328/drivers/pmu/pmu.c
@@ -619,6 +619,8 @@
/* should never reach here */
psci_power_down_wfi();
+ /* should never reach here */
+ panic();
}
int rockchip_soc_sys_pwr_dm_suspend(void)
diff --git a/plat/rockchip/rk3399/rk3399_def.h b/plat/rockchip/rk3399/rk3399_def.h
index ba83242..8d6ecfb 100644
--- a/plat/rockchip/rk3399/rk3399_def.h
+++ b/plat/rockchip/rk3399/rk3399_def.h
@@ -17,7 +17,7 @@
/**************************************************************************
* UART related constants
**************************************************************************/
-#define RK3399_BAUDRATE 115200
+#define RK3399_BAUDRATE 1500000
#define RK3399_UART_CLOCK 24000000
/******************************************************************************
diff --git a/plat/rockchip/rk3576/drivers/dmc/dmc_rk3576.h b/plat/rockchip/rk3576/drivers/dmc/dmc_rk3576.h
new file mode 100644
index 0000000..d8c231c
--- /dev/null
+++ b/plat/rockchip/rk3576/drivers/dmc/dmc_rk3576.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#ifndef __PLAT_ROCKCHIP_DMC_RK3576_H__
+#define __PLAT_ROCKCHIP_DMC_RK3576_H__
+
+#define MAX_CH_NUM (2)
+#define CTL_PORT_NUM (5)
+
+/* DDR_GRF Register */
+#define GRF_CH_CON(ch, n) ((((ch) % 2) * 0x100) + ((n) * 4))
+#define DDR_GRF_CH_STATUS16(ch) (0x220 + ((ch) * 0x100))
+#define GRF_DDRPHY_CON(n) (0x530 + ((n) * 4))
+#define GRF_DDRPHY_CON0(ch) (0x530 + (((ch) % 2) * 0x4))
+#define DDR_GRF_COMMON_CON(n) (0x540 + ((n) * 4))
+
+/* PMUGRF Register */
+#define PMUGRF_OS_REG(n) (0x200 + ((n) * 4))
+
+struct low_power_st {
+ uint32_t pwrctl;
+ uint32_t clkgatectl;
+ uint32_t dfi_lp_mode_apb;
+ uint32_t grf_ddr_con0;
+ uint32_t grf_ddr_con1;
+ uint32_t grf_ddr_con6;
+ uint32_t grf_ddr_con7;
+ uint32_t grf_ddr_con9;
+ uint32_t grf_ddrphy_con0;
+ uint32_t hwlp_0;
+ uint32_t hwlp_c;
+ uint32_t pcl_pd;
+};
+
+struct rk3576_dmc_config {
+ struct low_power_st low_power[MAX_CH_NUM];
+};
+
+void dmc_save(void);
+void dmc_restore(void);
+
+#endif /* __PLAT_ROCKCHIP_DMC_RK3576_H__ */
diff --git a/plat/rockchip/rk3576/drivers/dmc/suspend.c b/plat/rockchip/rk3576/drivers/dmc/suspend.c
new file mode 100644
index 0000000..389cc1b
--- /dev/null
+++ b/plat/rockchip/rk3576/drivers/dmc/suspend.c
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <bl31/bl31.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+
+#include <dmc_rk3576.h>
+#include <rk3576_def.h>
+#include <soc.h>
+
+struct rk3576_dmc_config dmc_config;
+
+/* DDR_PHY */
+#define LP_CON0 0x0018
+#define DFI_LP_CON0 0x0e04
+/* DDR_CTL */
+#define DDRCTL_STAT 0x10014
+#define DDRCTL_PWRCTL 0x10180
+#define DDRCTL_CLKGATECTL 0x1018c
+
+/* LP_CON0 */
+#define DS_IO_PD BIT(14)
+#define SCHD_HW_CLOCK_GATING_DISABLE BIT(13)
+#define PCL_PD BIT(12)
+#define DQS_ENABLE BIT(10)
+#define WCK_ENABLE BIT(9)
+#define CTRL_DQS_DRV_OFF BIT(8)
+#define CTRL_SCHEDULER_EN BIT(6)
+
+/* DFI_LP_CON0 0x0e04 */
+#define DFI_LP_MODE_APB BIT(31)
+
+/* DDRCTL_STAT 0x10014 */
+#define CTL_SELFREF_STATE_SHIFT (12)
+#define CTL_SELFREF_STATE_MASK (0x7 << CTL_SELFREF_STATE_SHIFT)
+#define CTL_NOT_IN_SELF_REFRESH (0x0 << CTL_SELFREF_STATE_SHIFT)
+#define CTL_SELF_REFRESH_1 (0x1 << CTL_SELFREF_STATE_SHIFT)
+#define CTL_SELF_REFRESH_POWER_DOWN (0x2 << CTL_SELFREF_STATE_SHIFT)
+#define CTL_SELF_REFRESH_2 (0x3 << CTL_SELFREF_STATE_SHIFT)
+#define CTL_SELF_REFRESH_DEEP_SLEEP (0x4 << CTL_SELFREF_STATE_SHIFT)
+#define CTL_SELFREF_TYPE_SHIFT (4)
+#define CTL_SELFREF_TYPE_MASK (0x3 << CTL_SELFREF_TYPE_SHIFT)
+#define CTL_SELFREF_NOT_BY_PHY (0x1 << CTL_SELFREF_TYPE_SHIFT)
+#define CTL_SELFREF_NOT_BY_AUTO (0x2 << CTL_SELFREF_TYPE_SHIFT)
+#define CTL_SELFREF_BY_AUTO (0x3 << CTL_SELFREF_TYPE_SHIFT)
+#define CTL_OPERATING_MODE_MASK (0x7)
+#define CTL_OPERATING_MODE_INIT (0x0)
+#define CTL_OPERATING_MODE_NORMAL (0x1)
+#define CTL_OPERATING_MODE_PD (0x2)
+#define CTL_OPERATING_MODE_SR_SRPD (0x3)
+
+/* DDRCTL_PWRCTL 0x10180 */
+#define CTL_DSM_EN BIT(18)
+#define CTL_STAY_IN_SELFREF BIT(15)
+#define CTL_SELFREF_SW BIT(11)
+#define CTL_EN_DFI_DRAM_CLK_DISABLE BIT(9)
+#define CTL_POWERDOWN_EN_MASK (0xf)
+#define CTL_POWERDOWN_EN_SHIFT (4)
+#define CTL_SELFREF_EN_MASK (0xf)
+#define CTL_SELFREF_EN_SHIFT (0)
+
+#define SYS_REG_DEC_CHINFO(n, ch) (((n) >> (28 + (ch))) & 0x1)
+#define SYS_REG_DEC_CHINFO_V3(reg2, ch) SYS_REG_DEC_CHINFO(reg2, ch)
+
+#define SYS_REG_DEC_NUM_CH(n) (1 + (((n) >> 12) & 0x1))
+#define SYS_REG_DEC_NUM_CH_V3(reg2) SYS_REG_DEC_NUM_CH(reg2)
+
+static void exit_low_power(uint32_t ch, struct rk3576_dmc_config *configs)
+{
+ /* LP_CON0: [12]pcl_pd */
+ configs->low_power[ch].pcl_pd = mmio_read_32(DDRPHY_BASE_CH(0) + LP_CON0) & PCL_PD;
+ mmio_clrbits_32(DDRPHY_BASE_CH(ch) + LP_CON0, PCL_PD);
+
+ /* Disable low power activities */
+ configs->low_power[ch].pwrctl = mmio_read_32(UMCTL_BASE_CH(ch) + DDRCTL_PWRCTL);
+ mmio_clrbits_32(UMCTL_BASE_CH(ch) + DDRCTL_PWRCTL,
+ CTL_DSM_EN | (CTL_POWERDOWN_EN_MASK << CTL_POWERDOWN_EN_SHIFT) |
+ (CTL_SELFREF_EN_MASK << CTL_SELFREF_EN_SHIFT));
+ while ((mmio_read_32(UMCTL_BASE_CH(ch) + DDRCTL_STAT) & CTL_OPERATING_MODE_MASK) !=
+ CTL_OPERATING_MODE_NORMAL)
+ continue;
+
+ /* DDR_GRF_CHA_CON6: [6:0]rd_lat_delay, [14:8]wr_lat_delay, [15]cmd_dly_eq0_en */
+ configs->low_power[ch].grf_ddr_con6 =
+ mmio_read_32(DDR_GRF_BASE + GRF_CH_CON(ch, 6)) & 0xff7f;
+ mmio_write_32(DDR_GRF_BASE + GRF_CH_CON(ch, 6), (0x1ul << (15 + 16)));
+
+ /* DDR_GRF_CHA_CON0: [12:8]ddrctl_axi_cg_en */
+ configs->low_power[ch].grf_ddr_con0 =
+ mmio_read_32(DDR_GRF_BASE + GRF_CH_CON(ch, 0)) & 0x1f00;
+ mmio_write_32(DDR_GRF_BASE + GRF_CH_CON(ch, 0), 0x1f000000);
+
+ /*
+ * DDR_GRF_CHA_CON1:
+ * [15]ddrctl_apb_pclk_cg_en, [12]ddrmon_pclk_cg_en, [7]dfi_scramble_cg_en,
+ * [6]ddrctl_mem_cg_en, [5]bsm_clk_cg_en, [2]ddrctl_core_cg_en, [1]ddrctl_apb_cg_en
+ */
+ configs->low_power[ch].grf_ddr_con1 =
+ mmio_read_32(DDR_GRF_BASE + GRF_CH_CON(ch, 1)) & 0x90e6;
+ mmio_write_32(DDR_GRF_BASE + GRF_CH_CON(ch, 1), 0x90e60000);
+
+ configs->low_power[ch].hwlp_0 = mmio_read_32(HWLP_BASE_CH(ch) + 0x0);
+ mmio_write_32(HWLP_BASE_CH(ch) + 0x0, 0x0);
+ configs->low_power[ch].hwlp_c = mmio_read_32(HWLP_BASE_CH(ch) + 0xc);
+ mmio_write_32(HWLP_BASE_CH(ch) + 0xc, 0x0);
+
+ /* DDR_GRF_CHA_PHY_CON0: [14]ddrphy_pclk_cg_en */
+ configs->low_power[ch].grf_ddrphy_con0 =
+ mmio_read_32(DDR_GRF_BASE + GRF_DDRPHY_CON0(ch)) & BIT(14);
+ mmio_write_32(DDR_GRF_BASE + GRF_DDRPHY_CON0(ch), BIT(14 + 16));
+
+ /* CLKGATECTL: [5:0]bsm_clk_on */
+ configs->low_power[ch].clkgatectl =
+ mmio_read_32(UMCTL_BASE_CH(ch) + DDRCTL_CLKGATECTL) & 0x3f;
+ /* DFI_LP_CON0: [31]dfi_lp_mode_apb */
+ configs->low_power[ch].dfi_lp_mode_apb =
+ (mmio_read_32(DDRPHY_BASE_CH(ch) + DFI_LP_CON0) >> 31) & 0x1;
+}
+
+static void resume_low_power(uint32_t ch, struct rk3576_dmc_config *configs)
+{
+ /* DFI_LP_CON0: [31]dfi_lp_mode_apb */
+ if (configs->low_power[ch].dfi_lp_mode_apb != 0)
+ mmio_setbits_32(DDRPHY_BASE_CH(ch) + DFI_LP_CON0, DFI_LP_MODE_APB);
+
+ /* CLKGATECTL: [5:0]bsm_clk_on */
+ mmio_clrsetbits_32(UMCTL_BASE_CH(ch) + DDRCTL_CLKGATECTL,
+ 0x3f, configs->low_power[ch].clkgatectl & 0x3f);
+
+ /* DDR_GRF_CHA_CON6: [6:0]rd_lat_delay, [14:8]wr_lat_delay, [15]cmd_dly_eq0_en */
+ mmio_write_32(DDR_GRF_BASE + GRF_CH_CON(ch, 6),
+ (0xff7ful << 16) | configs->low_power[ch].grf_ddr_con6);
+
+ mmio_write_32(HWLP_BASE_CH(ch) + 0xc, configs->low_power[ch].hwlp_c);
+ mmio_write_32(HWLP_BASE_CH(ch) + 0x0, configs->low_power[ch].hwlp_0);
+
+ /* DDR_GRF_CHA_CON0: [12:8]ddrctl_axi_cg_en */
+ mmio_write_32(DDR_GRF_BASE + GRF_CH_CON(ch, 0),
+ (0x1f00ul << 16) | configs->low_power[ch].grf_ddr_con0);
+
+ /*
+ * DDR_GRF_CHA_CON1:
+ * [15]ddrctl_apb_pclk_cg_en, [12]ddrmon_pclk_cg_en, [7]dfi_scramble_cg_en,
+ * [6]ddrctl_mem_cg_en, [5]bsm_clk_cg_en, [2]ddrctl_core_cg_en, [1]ddrctl_apb_cg_en
+ */
+ mmio_write_32(DDR_GRF_BASE + GRF_CH_CON(ch, 1),
+ (0x90e6ul << 16) | configs->low_power[ch].grf_ddr_con1);
+
+ /* DDR_GRF_CHA_PHY_CON0: [14]ddrphy_pclk_cg_en */
+ mmio_write_32(DDR_GRF_BASE + GRF_DDRPHY_CON0(ch),
+ BIT(14 + 16) | configs->low_power[ch].grf_ddrphy_con0);
+
+ /* reset low power activities */
+ mmio_write_32(UMCTL_BASE_CH(ch) + DDRCTL_PWRCTL, configs->low_power[ch].pwrctl);
+
+ /* LP_CON0: [12]pcl_pd */
+ if (configs->low_power[ch].pcl_pd != 0)
+ mmio_setbits_32(DDRPHY_BASE_CH(ch) + LP_CON0, PCL_PD);
+}
+
+void dmc_save(void)
+{
+ uint32_t i, channel_num;
+
+ channel_num =
+ SYS_REG_DEC_NUM_CH_V3(mmio_read_32(PMU1_GRF_BASE + PMUGRF_OS_REG(2)));
+
+ for (i = 0; i < channel_num; i++)
+ exit_low_power(i, &dmc_config);
+}
+
+void dmc_restore(void)
+{
+ uint32_t i, channel_num;
+
+ channel_num = SYS_REG_DEC_NUM_CH_V3(mmio_read_32(PMU1_GRF_BASE + PMUGRF_OS_REG(2)));
+
+ for (i = 0; i < channel_num; i++)
+ resume_low_power(i, &dmc_config);
+}
diff --git a/plat/rockchip/rk3576/drivers/pmu/plat_pmu_macros.S b/plat/rockchip/rk3576/drivers/pmu/plat_pmu_macros.S
new file mode 100644
index 0000000..717b55c
--- /dev/null
+++ b/plat/rockchip/rk3576/drivers/pmu/plat_pmu_macros.S
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+.globl clst_warmboot_data
+
+.macro func_rockchip_clst_warmboot
+.endm
+
+.macro rockchip_clst_warmboot_data
+clst_warmboot_data:
+ .rept PLATFORM_CLUSTER_COUNT
+ .word 0
+ .endr
+.endm
diff --git a/plat/rockchip/rk3576/drivers/pmu/pm_pd_regs.c b/plat/rockchip/rk3576/drivers/pmu/pm_pd_regs.c
new file mode 100644
index 0000000..de5fa75
--- /dev/null
+++ b/plat/rockchip/rk3576/drivers/pmu/pm_pd_regs.c
@@ -0,0 +1,451 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <bl31/bl31.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <pmu.h>
+
+#include <plat_pm_helpers.h>
+#include <plat_private.h>
+#include <pm_pd_regs.h>
+#include <rk3576_clk.h>
+#include <soc.h>
+
+#define WMSK_VAL 0xffff0000
+
+static struct reg_region qos_reg_rgns[] = {
+ [qos_decom] = REG_REGION(0x08, 0x18, 4, 0x27f00000, 0),
+ [qos_dmac0] = REG_REGION(0x08, 0x18, 4, 0x27f00080, 0),
+ [qos_dmac1] = REG_REGION(0x08, 0x18, 4, 0x27f00100, 0),
+ [qos_dmac2] = REG_REGION(0x08, 0x18, 4, 0x27f00180, 0),
+ [qos_bus_mcu] = REG_REGION(0x08, 0x18, 4, 0x27f00200, 0),
+ [qos_can0] = REG_REGION(0x08, 0x18, 4, 0x27f00280, 0),
+ [qos_can1] = REG_REGION(0x08, 0x18, 4, 0x27f00300, 0),
+ [qos_cci_m0] = REG_REGION(0x08, 0x18, 4, 0x27f01000, 0),
+ [qos_cci_m1] = REG_REGION(0x08, 0x18, 4, 0x27f18880, 0),
+ [qos_cci_m2] = REG_REGION(0x08, 0x18, 4, 0x27f18900, 0),
+ [qos_dap_lite] = REG_REGION(0x08, 0x18, 4, 0x27f01080, 0),
+ [qos_hdcp1] = REG_REGION(0x08, 0x18, 4, 0x27f02000, 0),
+ [qos_ddr_mcu] = REG_REGION(0x08, 0x18, 4, 0x27f03000, 0),
+ [qos_fspi1] = REG_REGION(0x08, 0x18, 4, 0x27f04000, 0),
+ [qos_gmac0] = REG_REGION(0x08, 0x18, 4, 0x27f04080, 0),
+ [qos_gmac1] = REG_REGION(0x08, 0x18, 4, 0x27f04100, 0),
+ [qos_sdio] = REG_REGION(0x08, 0x18, 4, 0x27f04180, 0),
+ [qos_sdmmc] = REG_REGION(0x08, 0x18, 4, 0x27f04200, 0),
+ [qos_flexbus] = REG_REGION(0x08, 0x18, 4, 0x27f04280, 0),
+ [qos_gpu] = REG_REGION(0x08, 0x18, 4, 0x27f05000, 0),
+ [qos_vepu1] = REG_REGION(0x08, 0x18, 4, 0x27f06000, 0),
+ [qos_npu_mcu] = REG_REGION(0x08, 0x18, 4, 0x27f08000, 0),
+ [qos_npu_nsp0] = REG_REGION(0x08, 0x18, 4, 0x27f08080, 0),
+ [qos_npu_nsp1] = REG_REGION(0x08, 0x18, 4, 0x27f08100, 0),
+ [qos_npu_m0] = REG_REGION(0x08, 0x18, 4, 0x27f20000, 0),
+ [qos_npu_m1] = REG_REGION(0x08, 0x18, 4, 0x27f21000, 0),
+ [qos_npu_m0ro] = REG_REGION(0x08, 0x18, 4, 0x27f22080, 0),
+ [qos_npu_m1ro] = REG_REGION(0x08, 0x18, 4, 0x27f22100, 0),
+ [qos_emmc] = REG_REGION(0x08, 0x18, 4, 0x27f09000, 0),
+ [qos_fspi0] = REG_REGION(0x08, 0x18, 4, 0x27f09080, 0),
+ [qos_mmu0] = REG_REGION(0x08, 0x18, 4, 0x27f0a000, 0),
+ [qos_mmu1] = REG_REGION(0x08, 0x18, 4, 0x27f0a080, 0),
+ [qos_pmu_mcu] = REG_REGION(0x08, 0x18, 4, 0x27f0b000, 0),
+ [qos_rkvdec] = REG_REGION(0x08, 0x18, 4, 0x27f0c000, 0),
+ [qos_crypto] = REG_REGION(0x08, 0x18, 4, 0x27f0d000, 0),
+ [qos_mmu2] = REG_REGION(0x08, 0x18, 4, 0x27f0e000, 0),
+ [qos_ufshc] = REG_REGION(0x08, 0x18, 4, 0x27f0e080, 0),
+ [qos_vepu0] = REG_REGION(0x08, 0x18, 4, 0x27f0f000, 0),
+ [qos_isp_mro] = REG_REGION(0x08, 0x18, 4, 0x27f10000, 0),
+ [qos_isp_mwo] = REG_REGION(0x08, 0x18, 4, 0x27f10080, 0),
+ [qos_vicap_m0] = REG_REGION(0x08, 0x18, 4, 0x27f10100, 0),
+ [qos_vpss_mro] = REG_REGION(0x08, 0x18, 4, 0x27f10180, 0),
+ [qos_vpss_mwo] = REG_REGION(0x08, 0x18, 4, 0x27f10200, 0),
+ [qos_hdcp0] = REG_REGION(0x08, 0x18, 4, 0x27f11000, 0),
+ [qos_vop_m0] = REG_REGION(0x08, 0x18, 4, 0x27f12800, 0),
+ [qos_vop_m1ro] = REG_REGION(0x08, 0x18, 4, 0x27f12880, 0),
+ [qos_ebc] = REG_REGION(0x08, 0x18, 4, 0x27f13000, 0),
+ [qos_rga0] = REG_REGION(0x08, 0x18, 4, 0x27f13080, 0),
+ [qos_rga1] = REG_REGION(0x08, 0x18, 4, 0x27f13100, 0),
+ [qos_jpeg] = REG_REGION(0x08, 0x18, 4, 0x27f13180, 0),
+ [qos_vdpp] = REG_REGION(0x08, 0x18, 4, 0x27f13200, 0),
+ [qos_dma2ddr] = REG_REGION(0x08, 0x18, 4, 0x27f15880, 0),
+};
+
+static struct reg_region pd_bcore_reg_rgns[] = {
+ /* bcore cru */
+ /* REG_REGION(0x280, 0x280, 4, BIGCORE0CRU_BASE, WMSK_VAL), */
+ REG_REGION(0x300, 0x30c, 4, BIGCORE_CRU_BASE, WMSK_VAL),
+ REG_REGION(0x800, 0x804, 4, BIGCORE_CRU_BASE, WMSK_VAL),
+ REG_REGION(0xa00, 0xa0c, 4, BIGCORE_CRU_BASE, WMSK_VAL),
+ REG_REGION(0xcc0, 0xcc0, 4, BIGCORE_CRU_BASE, 0),
+ REG_REGION(0xf28, 0xf28, 8, BIGCORE_CRU_BASE, 0),
+ REG_REGION(0xf2c, 0xf2c, 8, BIGCORE_CRU_BASE, WMSK_VAL),
+
+ /* bcore_grf */
+ REG_REGION(0x34, 0x3c, 4, BIGCORE_GRF_BASE, WMSK_VAL),
+ REG_REGION(0x44, 0x44, 4, BIGCORE_GRF_BASE, WMSK_VAL),
+};
+
+static struct reg_region pd_core_reg_rgns[] = {
+ /* cci cru */
+ REG_REGION(0x310, 0x310, 4, CCI_CRU_BASE, WMSK_VAL),
+ REG_REGION(0x804, 0x808, 4, CCI_CRU_BASE, WMSK_VAL),
+ REG_REGION(0xa04, 0xa08, 4, CCI_CRU_BASE, WMSK_VAL),
+ REG_REGION(0xc50, 0xc58, 4, CCI_CRU_BASE, WMSK_VAL),
+ REG_REGION(0xd00, 0xd00, 8, CCI_CRU_BASE, 0),
+ REG_REGION(0xd04, 0xd04, 8, CCI_CRU_BASE, WMSK_VAL),
+ /* Restore lpll registers after clksel_* registers. Because lpll
+ * may be turned off during restoring, which cause cci_cru to lost clock.
+ */
+ REG_REGION(0x040, 0x044, 4, CCI_CRU_BASE, WMSK_VAL),
+ REG_REGION(0x048, 0x048, 4, CCI_CRU_BASE, 0),
+ REG_REGION(0x04c, 0x058, 4, CCI_CRU_BASE, WMSK_VAL),
+
+ /* lcore cru */
+ /* REG_REGION(0x280, 0x280, 4, BIGCORE1CRU_BASE, WMSK_VAL), */
+ REG_REGION(0x300, 0x30c, 4, LITTLE_CRU_BASE, WMSK_VAL),
+ REG_REGION(0x800, 0x804, 4, LITTLE_CRU_BASE, WMSK_VAL),
+ REG_REGION(0xa00, 0xa0c, 4, LITTLE_CRU_BASE, WMSK_VAL),
+ REG_REGION(0xcc0, 0xcc0, 4, LITTLE_CRU_BASE, 0),
+ REG_REGION(0xf38, 0xf38, 8, LITTLE_CRU_BASE, 0),
+ REG_REGION(0xf3c, 0xf3c, 8, LITTLE_CRU_BASE, WMSK_VAL),
+
+ /* bcore cru */
+ /* REG_REGION(0x280, 0x280, 4, BIGCORE0CRU_BASE, WMSK_VAL), */
+ REG_REGION(0x300, 0x30c, 4, BIGCORE_CRU_BASE, WMSK_VAL),
+ REG_REGION(0x800, 0x804, 4, BIGCORE_CRU_BASE, WMSK_VAL),
+ REG_REGION(0xa00, 0xa0c, 4, BIGCORE_CRU_BASE, WMSK_VAL),
+ REG_REGION(0xcc0, 0xcc0, 4, BIGCORE_CRU_BASE, 0),
+ REG_REGION(0xf28, 0xf28, 8, BIGCORE_CRU_BASE, 0),
+ REG_REGION(0xf2c, 0xf2c, 8, BIGCORE_CRU_BASE, WMSK_VAL),
+
+ /* cci grf */
+ REG_REGION(0x00, 0x10, 4, CCI_GRF_BASE, WMSK_VAL),
+ REG_REGION(0x54, 0x54, 4, CCI_GRF_BASE, WMSK_VAL),
+
+ /* lcore_grf */
+ REG_REGION(0x34, 0x3c, 4, LITCORE_GRF_BASE, WMSK_VAL),
+ REG_REGION(0x44, 0x44, 4, LITCORE_GRF_BASE, WMSK_VAL),
+
+ /* bcore_grf */
+ REG_REGION(0x34, 0x3c, 4, BIGCORE_GRF_BASE, WMSK_VAL),
+ REG_REGION(0x44, 0x44, 4, BIGCORE_GRF_BASE, WMSK_VAL),
+};
+
+static struct reg_region pd_php_reg_rgns[] = {
+ /* php_grf */
+ REG_REGION(0x004, 0x00c, 4, PHP_GRF_BASE, WMSK_VAL),
+ REG_REGION(0x010, 0x018, 4, PHP_GRF_BASE, 0),
+ REG_REGION(0x01c, 0x020, 4, PHP_GRF_BASE, WMSK_VAL),
+ REG_REGION(0x048, 0x048, 4, PHP_GRF_BASE, 0),
+};
+
+static struct reg_region pd_usb2phy_reg_rgns[] = {
+ /* usb */
+ REG_REGION(0x00, 0x14, 4, USB2PHY0_GRF_BASE, WMSK_VAL),
+ REG_REGION(0x40, 0x40, 4, USB2PHY0_GRF_BASE, WMSK_VAL),
+ REG_REGION(0x44, 0x50, 4, USB2PHY0_GRF_BASE, 0),
+ REG_REGION(0x00, 0x14, 4, USB2PHY1_GRF_BASE, WMSK_VAL),
+ REG_REGION(0x08, 0x08, 4, USBDPPHY_GRF_BASE, WMSK_VAL),
+};
+
+#define PLL_LOCKED_TIMEOUT 600000U
+
+static void pm_pll_wait_lock(uint32_t pll_base)
+{
+ int delay = PLL_LOCKED_TIMEOUT;
+
+ if ((mmio_read_32(pll_base + CRU_PLL_CON(1)) & CRU_PLLCON1_PWRDOWN) != 0)
+ return;
+
+ while (delay-- >= 0) {
+ if ((mmio_read_32(pll_base + CRU_PLL_CON(6)) & CRU_PLLCON6_LOCK_STATUS) != 0)
+ break;
+ udelay(1);
+ }
+
+ if (delay <= 0)
+ ERROR("Can't wait pll(0x%x) lock\n", pll_base);
+}
+
+void qos_save(void)
+{
+ uint32_t pmu_pd_st = mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST);
+
+ if ((pmu_pd_st & BIT(pmu_pd_nvm)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_emmc], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_fspi0], 1);
+ }
+
+ if ((pmu_pd_st & BIT(pmu_pd_sd_gmac)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_fspi1], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_gmac0], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_gmac1], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_sdio], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_sdmmc], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_flexbus], 1);
+ }
+
+ if ((pmu_pd_st & BIT(pmu_pd_php)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_mmu0], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_mmu1], 1);
+ }
+
+ if ((pmu_pd_st & BIT(pmu_pd_vop)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_vop_m0], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_vop_m1ro], 1);
+ }
+
+ if ((pmu_pd_st & BIT(pmu_pd_vo1)) == 0)
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_hdcp1], 1);
+
+ if ((pmu_pd_st & BIT(pmu_pd_vo0)) == 0)
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_hdcp0], 1);
+
+ if ((pmu_pd_st & BIT(pmu_pd_usb)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_mmu2], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_ufshc], 1);
+ }
+
+ if ((pmu_pd_st & BIT(pmu_pd_vi)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_isp_mro], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_isp_mwo], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_vicap_m0], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_vpss_mro], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_vpss_mwo], 1);
+ }
+
+ if ((pmu_pd_st & BIT(pmu_pd_vepu0)) == 0)
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_vepu0], 1);
+
+ if ((pmu_pd_st & BIT(pmu_pd_vepu1)) == 0)
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_vepu1], 1);
+
+ if ((pmu_pd_st & BIT(pmu_pd_vdec)) == 0)
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_rkvdec], 1);
+
+ if ((pmu_pd_st & BIT(pmu_pd_vpu)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_ebc], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_rga0], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_rga1], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_jpeg], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_vdpp], 1);
+ }
+
+ if ((pmu_pd_st & BIT(pmu_pd_nputop)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_npu_mcu], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_npu_nsp0], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_npu_nsp1], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_npu_m0ro], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_npu_m1ro], 1);
+ }
+
+ if ((pmu_pd_st & BIT(pmu_pd_npu0)) == 0)
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_npu_m0], 1);
+
+ if ((pmu_pd_st & BIT(pmu_pd_npu1)) == 0)
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_npu_m1], 1);
+
+ if ((pmu_pd_st & BIT(pmu_pd_gpu)) == 0)
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_gpu], 1);
+}
+
+void qos_restore(void)
+{
+ uint32_t pmu_pd_st = mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST);
+
+ if ((pmu_pd_st & BIT(pmu_pd_nvm)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_emmc], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_fspi0], 1);
+ }
+
+ if ((pmu_pd_st & BIT(pmu_pd_sd_gmac)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_fspi1], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_gmac0], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_gmac1], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_sdio], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_sdmmc], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_flexbus], 1);
+ }
+
+ if ((pmu_pd_st & BIT(pmu_pd_php)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_mmu0], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_mmu1], 1);
+ }
+
+ if ((pmu_pd_st & BIT(pmu_pd_vop)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_vop_m0], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_vop_m1ro], 1);
+ }
+
+ if ((pmu_pd_st & BIT(pmu_pd_vo1)) == 0)
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_hdcp1], 1);
+
+ if ((pmu_pd_st & BIT(pmu_pd_vo0)) == 0)
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_hdcp0], 1);
+
+ if ((pmu_pd_st & BIT(pmu_pd_usb)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_mmu2], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_ufshc], 1);
+ }
+
+ if ((pmu_pd_st & BIT(pmu_pd_vi)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_isp_mro], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_isp_mwo], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_vicap_m0], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_vpss_mro], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_vpss_mwo], 1);
+ }
+
+ if ((pmu_pd_st & BIT(pmu_pd_vepu0)) == 0)
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_vepu0], 1);
+
+ if ((pmu_pd_st & BIT(pmu_pd_vepu1)) == 0)
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_vepu1], 1);
+
+ if ((pmu_pd_st & BIT(pmu_pd_vdec)) == 0)
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_rkvdec], 1);
+
+ if ((pmu_pd_st & BIT(pmu_pd_vpu)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_ebc], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_rga0], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_rga1], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_jpeg], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_vdpp], 1);
+ }
+
+ if ((pmu_pd_st & BIT(pmu_pd_nputop)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_npu_mcu], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_npu_nsp0], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_npu_nsp1], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_npu_m0ro], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_npu_m1ro], 1);
+ }
+
+ if ((pmu_pd_st & BIT(pmu_pd_npu0)) == 0)
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_npu_m0], 1);
+
+ if ((pmu_pd_st & BIT(pmu_pd_npu1)) == 0)
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_npu_m1], 1);
+
+ if ((pmu_pd_st & BIT(pmu_pd_gpu)) == 0)
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_gpu], 1);
+}
+
+void pd_usb2phy_save(void)
+{
+ rockchip_reg_rgn_save(pd_usb2phy_reg_rgns, ARRAY_SIZE(pd_usb2phy_reg_rgns));
+}
+
+void pd_usb2phy_restore(void)
+{
+ rockchip_reg_rgn_restore(pd_usb2phy_reg_rgns, ARRAY_SIZE(pd_usb2phy_reg_rgns));
+}
+
+static uint32_t b_cru_mode, l_cru_mode;
+static uint32_t bcore_need_restore;
+
+void pd_bcore_save(void)
+{
+ pvtplls_cpub_suspend();
+
+ b_cru_mode = mmio_read_32(BIGCORE_CRU_BASE + 0x280);
+ rockchip_reg_rgn_save(pd_bcore_reg_rgns, ARRAY_SIZE(pd_bcore_reg_rgns));
+
+ bcore_need_restore = 1;
+}
+
+void pd_bcore_restore(void)
+{
+ if (bcore_need_restore == 0)
+ return;
+
+ /* slow mode */
+ mmio_write_32(BIGCORE_CRU_BASE + 0x280, 0x00030000);
+
+ rockchip_reg_rgn_restore(pd_bcore_reg_rgns, ARRAY_SIZE(pd_bcore_reg_rgns));
+
+ /* trigger lcore/bcore mem_cfg */
+ mmio_write_32(BIGCORE_GRF_BASE + 0x38, BITS_WITH_WMASK(1, 0x1, 1));
+ udelay(1);
+ mmio_write_32(BIGCORE_GRF_BASE + 0x38, BITS_WITH_WMASK(0, 0x1, 1));
+
+ /* restore mode */
+ mmio_write_32(BIGCORE_CRU_BASE + 0x280, WITH_16BITS_WMSK(b_cru_mode));
+
+ pvtplls_cpub_resume();
+
+ bcore_need_restore = 0;
+}
+
+void pd_core_save(void)
+{
+ pvtplls_suspend();
+
+ b_cru_mode = mmio_read_32(BIGCORE_CRU_BASE + 0x280);
+ l_cru_mode = mmio_read_32(LITTLE_CRU_BASE + 0x280);
+
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_cci_m0], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_cci_m1], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_cci_m2], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[qos_dap_lite], 1);
+
+ rockchip_reg_rgn_save(pd_core_reg_rgns, ARRAY_SIZE(pd_core_reg_rgns));
+}
+
+void pd_core_restore(void)
+{
+ /* slow mode */
+ mmio_write_32(BIGCORE_CRU_BASE + 0x280, 0x00030000);
+ mmio_write_32(LITTLE_CRU_BASE + 0x280, 0x00030000);
+
+ rockchip_reg_rgn_restore(pd_core_reg_rgns, ARRAY_SIZE(pd_core_reg_rgns));
+
+ /* trigger lcore/bcore mem_cfg */
+ mmio_write_32(LITCORE_GRF_BASE + 0x38, BITS_WITH_WMASK(1, 0x1, 1));
+ mmio_write_32(BIGCORE_GRF_BASE + 0x38, BITS_WITH_WMASK(1, 0x1, 1));
+ udelay(1);
+ mmio_write_32(LITCORE_GRF_BASE + 0x38, BITS_WITH_WMASK(0, 0x1, 1));
+ mmio_write_32(BIGCORE_GRF_BASE + 0x38, BITS_WITH_WMASK(0, 0x1, 1));
+
+ /* wait lock */
+ pm_pll_wait_lock(CCI_CRU_BASE + 0x40);
+
+ /* restore mode */
+ mmio_write_32(BIGCORE_CRU_BASE + 0x280, WITH_16BITS_WMSK(b_cru_mode));
+ mmio_write_32(LITTLE_CRU_BASE + 0x280, WITH_16BITS_WMSK(l_cru_mode));
+
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_cci_m0], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_cci_m1], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_cci_m2], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[qos_dap_lite], 1);
+
+ pvtplls_resume();
+}
+
+void pd_php_save(void)
+{
+ rockchip_reg_rgn_save(pd_php_reg_rgns, ARRAY_SIZE(pd_php_reg_rgns));
+}
+
+void pd_php_restore(void)
+{
+ rockchip_reg_rgn_restore(pd_php_reg_rgns, ARRAY_SIZE(pd_php_reg_rgns));
+}
+
+void pm_reg_rgns_init(void)
+{
+ rockchip_alloc_region_mem(qos_reg_rgns, ARRAY_SIZE(qos_reg_rgns));
+ rockchip_alloc_region_mem(pd_bcore_reg_rgns, ARRAY_SIZE(pd_bcore_reg_rgns));
+ rockchip_alloc_region_mem(pd_core_reg_rgns, ARRAY_SIZE(pd_core_reg_rgns));
+ rockchip_alloc_region_mem(pd_php_reg_rgns, ARRAY_SIZE(pd_php_reg_rgns));
+ rockchip_alloc_region_mem(pd_usb2phy_reg_rgns, ARRAY_SIZE(pd_usb2phy_reg_rgns));
+}
diff --git a/plat/rockchip/rk3576/drivers/pmu/pm_pd_regs.h b/plat/rockchip/rk3576/drivers/pmu/pm_pd_regs.h
new file mode 100644
index 0000000..5b4f624
--- /dev/null
+++ b/plat/rockchip/rk3576/drivers/pmu/pm_pd_regs.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#ifndef PM_PD_REGS_H
+#define PM_PD_REGS_H
+
+#include <stdint.h>
+
+void qos_save(void);
+void qos_restore(void);
+void pd_usb2phy_save(void);
+void pd_usb2phy_restore(void);
+void pd_secure_save(void);
+void pd_secure_restore(void);
+void pd_bcore_save(void);
+void pd_bcore_restore(void);
+void pd_core_save(void);
+void pd_core_restore(void);
+void pd_php_save(void);
+void pd_php_restore(void);
+void pd_center_save(void);
+void pd_center_restore(void);
+void pd_bus_save(void);
+void pd_bus_restore(void);
+void pd_pmu1_save(void);
+void pd_pmu1_restore_early(void);
+void pd_pmu1_restore(void);
+void pd_pmu0_save(void);
+void pd_pmu0_restore(void);
+
+void pm_reg_rgns_init(void);
+void pm_regs_rgn_dump(void);
+
+#endif
diff --git a/plat/rockchip/rk3576/drivers/pmu/pmu.c b/plat/rockchip/rk3576/drivers/pmu/pmu.c
new file mode 100644
index 0000000..c7db176
--- /dev/null
+++ b/plat/rockchip/rk3576/drivers/pmu/pmu.c
@@ -0,0 +1,1069 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <bl31/bl31.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <pmu.h>
+
+#include <cpus_on_fixed_addr.h>
+#include <dmc_rk3576.h>
+#include <plat_pm_helpers.h>
+#include <plat_private.h>
+#include <pm_pd_regs.h>
+#include <secure.h>
+#include <soc.h>
+
+static struct psram_data_t *psram_sleep_cfg =
+ (struct psram_data_t *)&sys_sleep_flag_sram;
+
+struct rk3576_sleep_ddr_data {
+ uint32_t cru_mode_con, secure_cru_mode;
+ uint32_t gpio0a_iomux_l, gpio0a_iomux_h, gpio0b_iomux_l;
+ uint32_t pmu2_bisr_glb_con;
+ uint32_t pmu2_c0_ack_sel_con0, pmu2_c1_ack_sel_con0, pmu2_c2_ack_sel_con0;
+ uint32_t pmu2_fast_pwr_con, pmu2_pwrgt_sft_con0;
+ uint32_t pmu0grf_soc_con0, pmu0grf_soc_con1, pmu0grf_soc_con5;
+ uint32_t pmu_pd_st, bus_idle_st;
+ uint32_t sys_sgrf_soc_con0;
+ uint32_t ddrgrf_cha_con2, ddrgrf_chb_con2;
+};
+
+static struct rk3576_sleep_ddr_data ddr_data;
+
+void rockchip_plat_mmu_el3(void)
+{
+#ifdef PLAT_EXTRA_LD_SCRIPT
+ size_t sram_size;
+
+ sram_size = (char *)&__bl31_pmusram_text_end -
+ (char *)PMUSRAM_BASE;
+ mmap_add_region(PMUSRAM_BASE, PMUSRAM_BASE,
+ sram_size, MT_MEMORY | MT_RO | MT_SECURE);
+
+ sram_size = (char *)&__bl31_pmusram_data_end -
+ (char *)&__bl31_pmusram_data_start;
+ mmap_add_region((unsigned long)&__bl31_pmusram_data_start,
+ (unsigned long)&__bl31_pmusram_data_start,
+ sram_size, MT_DEVICE | MT_RW | MT_SECURE);
+#endif
+}
+
+static int check_cpu_wfie(uint32_t cpu)
+{
+ uint32_t loop = 0;
+
+ while ((mmio_read_32(SYS_GRF_BASE + SYSGRF_STATUS0) & BIT(cpu + 12)) == 0 &&
+ (mmio_read_32(PMU_BASE + PMU2_CLUSTER_PWR_ST) & BIT(cpu)) == 0 &&
+ (loop < WFEI_CHECK_LOOP)) {
+ udelay(1);
+ loop++;
+ }
+
+ if (loop >= WFEI_CHECK_LOOP) {
+ WARN("%s: error, cpu%d (0x%x 0x%x)!\n", __func__, cpu,
+ mmio_read_32(SYS_GRF_BASE + SYSGRF_STATUS0),
+ mmio_read_32(PMU_BASE + PMU2_CLUSTER_PWR_ST));
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static inline uint32_t cpu_power_domain_st(uint32_t cpu)
+{
+ return !!(mmio_read_32(PMU_BASE + PMU2_CLUSTER_PWR_ST) &
+ BIT(cpu + 16));
+}
+
+static int cpu_power_domain_ctr(uint32_t cpu, uint32_t pd_state)
+{
+ uint32_t loop = 0;
+ int ret = 0;
+
+ mmio_write_32(PMU_BASE + PMU2_CPU_PWR_SFTCON(cpu),
+ BITS_WITH_WMASK(pd_state, 0x1, 0));
+
+ dsb();
+ while ((cpu_power_domain_st(cpu) != pd_state) && (loop < PD_CTR_LOOP)) {
+ udelay(1);
+ loop++;
+ }
+
+ if (cpu_power_domain_st(cpu) != pd_state) {
+ WARN("%s: %d, %d, error!\n", __func__, cpu, pd_state);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static inline uint32_t get_cpus_pwr_domain_cfg_info(uint32_t cpu_id)
+{
+ uint32_t val;
+
+ if ((mmio_read_32(PMU_BASE + PMU2_CPU_PWR_SFTCON(cpu_id)) & BIT(0)) != 0)
+ return core_pwr_pd;
+
+ val = mmio_read_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id));
+ if ((val & BIT(pmu_cpu_pm_en)) != 0) {
+ if ((val & BIT(core_pwr_wfi_int)) != 0)
+ return core_pwr_wfi_int;
+ else if ((val & BIT(pmu_cpu_pm_sft_wakeup_en)) != 0)
+ return core_pwr_wfi_reset;
+ else
+ return core_pwr_wfi;
+ } else {
+ return -1;
+ }
+}
+
+static inline void set_cpus_pwr_domain_cfg_info(uint32_t cpu_id, uint32_t value)
+{
+}
+
+static int cpus_power_domain_on(uint32_t cpu_id)
+{
+ uint32_t cfg_info;
+ /*
+ * There are two ways to powering on or off on core.
+ * 1) Control it power domain into on or off in PMU_PWRDN_CON reg
+ * 2) Enable the core power manage in PMU_CORE_PM_CON reg,
+ * then, if the core enter into wfi, it power domain will be
+ * powered off automatically.
+ */
+
+ cfg_info = get_cpus_pwr_domain_cfg_info(cpu_id);
+
+ if (cfg_info == core_pwr_pd) {
+ /* disable core_pm cfg */
+ mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id),
+ BITS_WITH_WMASK(0, 0xf, 0));
+ /* if the cores have be on, power off it firstly */
+ if (cpu_power_domain_st(cpu_id) == pmu_pd_on)
+ cpu_power_domain_ctr(cpu_id, pmu_pd_off);
+
+ cpu_power_domain_ctr(cpu_id, pmu_pd_on);
+ } else {
+ if (cpu_power_domain_st(cpu_id) == pmu_pd_on) {
+ WARN("%s: cpu%d is not in off,!\n", __func__, cpu_id);
+ return -EINVAL;
+ }
+
+ mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id),
+ BITS_WITH_WMASK(1, 0x1, pmu_cpu_pm_sft_wakeup_en));
+ dsb();
+ }
+
+ return 0;
+}
+
+static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg)
+{
+ uint32_t core_pm_value;
+
+ if (cpu_power_domain_st(cpu_id) == pmu_pd_off)
+ return 0;
+
+ if (pd_cfg == core_pwr_pd) {
+ if (check_cpu_wfie(cpu_id))
+ return -EINVAL;
+
+ /* disable core_pm cfg */
+ mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id),
+ BITS_WITH_WMASK(0, 0xf, 0));
+
+ set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg);
+ cpu_power_domain_ctr(cpu_id, pmu_pd_off);
+ } else {
+ set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg);
+
+ core_pm_value = BIT(pmu_cpu_pm_en) | BIT(pmu_cpu_pm_dis_int);
+ if (pd_cfg == core_pwr_wfi_int)
+ core_pm_value |= BIT(pmu_cpu_pm_int_wakeup_en);
+ else if (pd_cfg == core_pwr_wfi_reset)
+ core_pm_value |= BIT(pmu_cpu_pm_sft_wakeup_en);
+
+ mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id),
+ BITS_WITH_WMASK(core_pm_value, 0xf, 0));
+ dsb();
+ }
+
+ return 0;
+}
+
+int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint)
+{
+ uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
+
+ assert(cpu_id < PLATFORM_CORE_COUNT);
+ assert(cpuson_flags[cpu_id] == 0);
+ cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG;
+ cpuson_entry_point[cpu_id] = entrypoint;
+ dsb();
+
+ cpus_power_domain_on(cpu_id);
+
+ return PSCI_E_SUCCESS;
+}
+
+int rockchip_soc_cores_pwr_dm_off(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ cpus_power_domain_off(cpu_id, core_pwr_wfi);
+
+ return PSCI_E_SUCCESS;
+}
+
+int rockchip_soc_cores_pwr_dm_on_finish(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id),
+ BITS_WITH_WMASK(0, 0xf, 0));
+
+ return PSCI_E_SUCCESS;
+}
+
+int rockchip_soc_cores_pwr_dm_suspend(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ assert(cpu_id < PLATFORM_CORE_COUNT);
+ assert(cpuson_flags[cpu_id] == 0);
+ cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN;
+ cpuson_entry_point[cpu_id] = plat_get_sec_entrypoint();
+ dsb();
+
+ cpus_power_domain_off(cpu_id, core_pwr_wfi_int);
+
+ return PSCI_E_SUCCESS;
+}
+
+int rockchip_soc_cores_pwr_dm_resume(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ /* Disable core_pm */
+ mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id),
+ BITS_WITH_WMASK(0, 0xf, 0));
+
+ return PSCI_E_SUCCESS;
+}
+
+void nonboot_cpus_off(void)
+{
+ uint32_t boot_cpu, cpu;
+
+ boot_cpu = plat_my_core_pos();
+
+ /* turn off noboot cpus */
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) {
+ if (cpu == boot_cpu)
+ continue;
+
+ cpus_power_domain_off(cpu, core_pwr_pd);
+ }
+}
+
+static __pmusramfunc void ddr_resume(void)
+{
+ uint32_t key_upd_msk =
+ mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST) & BIT(pmu_pd_vop) ? 0x3 : 0x7;
+
+ /* hptimer is 24M here */
+ write_cntfrq_el0(24000000);
+
+ /* release cpu1~cpu7 to make pmu1_fsm exit */
+ mmio_write_32(CCI_GRF_BASE + CCIGRF_CON(4), 0xffffffff);
+ mmio_write_32(LITCORE_GRF_BASE + COREGRF_CPU_CON(1),
+ BITS_WITH_WMASK(0x77, 0xff, 4));
+
+ /* wait pmu1 fsm over */
+ while ((mmio_read_32(PMU_BASE + PMU1_PWR_FSM) & 0xf) != 0)
+ ;
+
+ /* SOC_CON19.vop/center/cci_ddr_hash_key_update_en */
+ mmio_write_32(SYS_SGRF_BASE + SYSSGRF_SOC_CON(19), 0x00070000);
+ dsb();
+
+ /* SOC_CON19.vop/center/cci_ddr_hash_key_update_en */
+ mmio_write_32(SYS_SGRF_BASE + SYSSGRF_SOC_CON(19), 0x00070000 | key_upd_msk);
+
+ /* SOC_STATUS.center/cci_ddr_hash_key_shift_ready */
+ while (((mmio_read_32(SYS_SGRF_BASE + SYSSGRF_SOC_STATUS) >> 12) & key_upd_msk) != key_upd_msk)
+ ;
+
+ /* CCI_BASE.ctrl_override_reg Attr:W1C addrmap strobe */
+ mmio_setbits_32(CCI_BASE + 0x0, 0x1 << 29);
+
+ /* SOC_CON19.vop/center/cci_ddr_hash_key_auto_update_en */
+ mmio_write_32(SYS_SGRF_BASE + SYSSGRF_SOC_CON(19), 0x00700070);
+}
+
+static uint32_t clk_save[CRU_CLKGATE_CON_CNT + PHP_CRU_CLKGATE_CON_CNT +
+ SECURE_CRU_CLKGATE_CON_CNT + SECURE_SCRU_CLKGATE_CON_CNT +
+ PMU1CRU_CLKGATE_CON_CNT + PMU1SCRU_CLKGATE_CON_CNT];
+
+void clk_gate_con_disable(void)
+{
+ int i;
+
+ for (i = 0; i < CRU_CLKGATE_CON_CNT; i++) {
+ /* Don't open wdt0 clk (cru_gate16[7:8] */
+ if (i == 16) {
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(i),
+ 0xfe7f0000);
+ } else {
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(i),
+ 0xffff0000);
+ }
+ }
+
+ for (i = 0; i < PHP_CRU_CLKGATE_CON_CNT; i++)
+ mmio_write_32(PHP_CRU_BASE + PHP_CRU_CLKGATE_CON(i), 0xffff0000);
+
+ for (i = 0; i < SECURE_CRU_CLKGATE_CON_CNT; i++)
+ mmio_write_32(SECURE_CRU_BASE + SECURE_CRU_CLKGATE_CON(i), 0xffff0000);
+
+ for (i = 0; i < SECURE_SCRU_CLKGATE_CON_CNT; i++)
+ mmio_write_32(SECURE_CRU_BASE + SECURE_SCRU_CLKGATE_CON(i), 0xffff0000);
+
+ for (i = 0; i < PMU1CRU_CLKGATE_CON_CNT; i++)
+ mmio_write_32(PMU1_CRU_BASE + PMU1CRU_CLKGATE_CON(i), 0xffff0000);
+
+ for (i = 0; i < PMU1SCRU_CLKGATE_CON_CNT; i++)
+ mmio_write_32(PMU1_CRU_BASE + PMU1SCRU_CLKGATE_CON(i), 0xffff0000);
+}
+
+void clk_gate_con_save(void)
+{
+ int i, j = 0;
+
+ for (i = 0; i < CRU_CLKGATE_CON_CNT; i++, j++)
+ clk_save[j] = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(i));
+
+ for (i = 0; i < PHP_CRU_CLKGATE_CON_CNT; i++, j++)
+ clk_save[j] = mmio_read_32(PHP_CRU_BASE + PHP_CRU_CLKGATE_CON(i));
+
+ for (i = 0; i < SECURE_CRU_CLKGATE_CON_CNT; i++, j++)
+ clk_save[j] = mmio_read_32(SECURE_CRU_BASE + SECURE_CRU_CLKGATE_CON(i));
+
+ for (i = 0; i < SECURE_SCRU_CLKGATE_CON_CNT; i++, j++)
+ clk_save[j] = mmio_read_32(SECURE_CRU_BASE + SECURE_SCRU_CLKGATE_CON(i));
+
+ for (i = 0; i < PMU1CRU_CLKGATE_CON_CNT; i++, j++)
+ clk_save[j] = mmio_read_32(PMU1_CRU_BASE + PMU1CRU_CLKGATE_CON(i));
+
+ for (i = 0; i < PMU1SCRU_CLKGATE_CON_CNT; i++, j++)
+ clk_save[j] = mmio_read_32(PMU1_CRU_BASE + PMU1SCRU_CLKGATE_CON(i));
+}
+
+void clk_gate_con_restore(void)
+{
+ int i, j = 0;
+
+ for (i = 0; i < CRU_CLKGATE_CON_CNT; i++, j++)
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(i),
+ WITH_16BITS_WMSK(clk_save[j]));
+
+ for (i = 0; i < PHP_CRU_CLKGATE_CON_CNT; i++, j++)
+ mmio_write_32(PHP_CRU_BASE + PHP_CRU_CLKGATE_CON(i),
+ WITH_16BITS_WMSK(clk_save[j]));
+
+ for (i = 0; i < SECURE_CRU_CLKGATE_CON_CNT; i++, j++)
+ mmio_write_32(SECURE_CRU_BASE + SECURE_CRU_CLKGATE_CON(i),
+ WITH_16BITS_WMSK(clk_save[j]));
+
+ for (i = 0; i < SECURE_SCRU_CLKGATE_CON_CNT; i++, j++)
+ mmio_write_32(SECURE_CRU_BASE + SECURE_SCRU_CLKGATE_CON(i),
+ WITH_16BITS_WMSK(clk_save[j]));
+
+ for (i = 0; i < PMU1CRU_CLKGATE_CON_CNT; i++, j++)
+ mmio_write_32(PMU1_CRU_BASE + PMU1CRU_CLKGATE_CON(i),
+ WITH_16BITS_WMSK(clk_save[j]));
+
+ for (i = 0; i < PMU1SCRU_CLKGATE_CON_CNT; i++, j++)
+ mmio_write_32(PMU1_CRU_BASE + PMU1SCRU_CLKGATE_CON(i),
+ WITH_16BITS_WMSK(clk_save[j]));
+}
+
+void pmu_bus_idle_req(uint32_t bus, uint32_t state)
+{
+ uint32_t wait_cnt = 0;
+
+ mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_SFTCON(bus / 16),
+ BITS_WITH_WMASK(state, 0x1, bus % 16));
+
+ while (pmu_bus_idle_st(bus) != state ||
+ pmu_bus_idle_ack(bus) != state) {
+ if (++wait_cnt > BUS_IDLE_LOOP)
+ break;
+ udelay(1);
+ }
+
+ if (wait_cnt > BUS_IDLE_LOOP)
+ WARN("%s: can't wait state %d for bus %d (0x%x)\n",
+ __func__, state, bus,
+ mmio_read_32(PMU_BASE + PMU2_BUS_IDLE_ST));
+}
+
+static inline uint32_t pmu_power_domain_st(uint32_t pd)
+{
+ return mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST) & BIT(pd) ?
+ pmu_pd_off :
+ pmu_pd_on;
+}
+
+int pmu_power_domain_ctr(uint32_t pd, uint32_t pd_state)
+{
+ uint32_t loop = 0;
+ int ret = 0;
+
+ mmio_write_32(PMU_BASE + PMU2_PWR_GATE_SFTCON(pd / 16),
+ BITS_WITH_WMASK(pd_state, 0x1, pd % 16));
+ dsb();
+
+ while ((pmu_power_domain_st(pd) != pd_state) && (loop < PD_CTR_LOOP)) {
+ udelay(1);
+ loop++;
+ }
+
+ if (pmu_power_domain_st(pd) != pd_state) {
+ WARN("%s: %d, %d, (0x%x) error!\n", __func__, pd, pd_state,
+ mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST));
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int pmu_set_power_domain(uint32_t pd_id, uint32_t pd_state)
+{
+ uint32_t state;
+
+ if (pmu_power_domain_st(pd_id) == pd_state)
+ goto out;
+
+ if (pd_state == pmu_pd_on)
+ pmu_power_domain_ctr(pd_id, pd_state);
+
+ state = (pd_state == pmu_pd_off) ? pmu_bus_idle : pmu_bus_active;
+
+ switch (pd_id) {
+ case pmu_pd_npu:
+ pmu_bus_idle_req(pmu_bus_id_npusys, state);
+ break;
+ case pmu_pd_secure:
+ pmu_bus_idle_req(pmu_bus_id_secure, state);
+ break;
+ case pmu_pd_nvm:
+ pmu_bus_idle_req(pmu_bus_id_nvm, state);
+ break;
+ case pmu_pd_sd_gmac:
+ pmu_bus_idle_req(pmu_bus_id_gmac, state);
+ break;
+ case pmu_pd_audio:
+ pmu_bus_idle_req(pmu_bus_id_audio, state);
+ break;
+ case pmu_pd_php:
+ pmu_bus_idle_req(pmu_bus_id_php, state);
+ break;
+ case pmu_pd_subphp:
+ break;
+ case pmu_pd_vop:
+ pmu_bus_idle_req(pmu_bus_id_vop, state);
+ break;
+ case pmu_pd_vop_smart:
+ break;
+ case pmu_pd_vop_clst:
+ break;
+ case pmu_pd_vo1:
+ pmu_bus_idle_req(pmu_bus_id_vo1, state);
+ break;
+ case pmu_pd_vo0:
+ pmu_bus_idle_req(pmu_bus_id_vo0, state);
+ break;
+ case pmu_pd_usb:
+ pmu_bus_idle_req(pmu_bus_id_usb, state);
+ break;
+ case pmu_pd_vi:
+ pmu_bus_idle_req(pmu_bus_id_vi, state);
+ break;
+ case pmu_pd_vepu0:
+ pmu_bus_idle_req(pmu_bus_id_vepu0, state);
+ break;
+ case pmu_pd_vepu1:
+ pmu_bus_idle_req(pmu_bus_id_vepu1, state);
+ break;
+ case pmu_pd_vdec:
+ pmu_bus_idle_req(pmu_bus_id_vdec, state);
+ break;
+ case pmu_pd_vpu:
+ pmu_bus_idle_req(pmu_bus_id_vpu, state);
+ break;
+ case pmu_pd_nputop:
+ pmu_bus_idle_req(pmu_bus_id_nputop, state);
+ break;
+ case pmu_pd_npu0:
+ pmu_bus_idle_req(pmu_bus_id_npu0, state);
+ break;
+ case pmu_pd_npu1:
+ pmu_bus_idle_req(pmu_bus_id_npu1, state);
+ break;
+ case pmu_pd_gpu:
+ pmu_bus_idle_req(pmu_bus_id_gpu, state);
+ break;
+ default:
+ break;
+ }
+
+ if (pd_state == pmu_pd_off)
+ pmu_power_domain_ctr(pd_id, pd_state);
+
+out:
+ return 0;
+}
+
+static void pmu_power_domains_suspend(void)
+{
+ ddr_data.pmu_pd_st = mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST);
+ ddr_data.bus_idle_st = mmio_read_32(PMU_BASE + PMU2_BUS_IDLE_ST);
+ ddr_data.pmu2_pwrgt_sft_con0 = mmio_read_32(PMU_BASE + PMU2_PWR_GATE_SFTCON(0));
+
+ qos_save();
+
+ pd_usb2phy_save();
+
+ if ((ddr_data.pmu_pd_st & BIT(pmu_pd_php)) == 0)
+ pd_php_save();
+}
+
+static void pmu_power_domains_resume(void)
+{
+ int i;
+
+ for (i = 0; i < pmu_pd_id_max; i++) {
+ /* vop smart/clst pd is not controlled by pmu */
+ if (i == pmu_pd_vop_smart || i == pmu_pd_vop_clst)
+ continue;
+
+ pmu_set_power_domain(i, !!(ddr_data.pmu_pd_st & BIT(i)));
+ }
+
+ /* restore vop smart/clst pd of pmu2_pwrgt_sft_con0 */
+ mmio_write_32(PMU_BASE + PMU2_PWR_GATE_SFTCON(0),
+ 0x30000000 | ddr_data.pmu2_pwrgt_sft_con0);
+
+ for (i = pmu_bus_id_max - 1; i >= 0; i--)
+ pmu_bus_idle_req(i, !!(ddr_data.bus_idle_st & BIT(i)));
+
+ if ((ddr_data.pmu_pd_st & BIT(pmu_pd_php)) == 0)
+ pd_php_restore();
+
+ pd_usb2phy_restore();
+
+ qos_restore();
+}
+
+static void ddr_sleep_config(void)
+{
+ ddr_data.ddrgrf_cha_con2 =
+ mmio_read_32(DDR_GRF_BASE + DDRGRF_CHA_CON(2));
+ ddr_data.ddrgrf_chb_con2 =
+ mmio_read_32(DDR_GRF_BASE + DDRGRF_CHB_CON(2));
+
+ mmio_write_32(DDR_GRF_BASE + DDRGRF_CHA_CON(2), 0x0a000a00);
+ mmio_write_32(DDR_GRF_BASE + DDRGRF_CHB_CON(2), 0x0a000a00);
+}
+
+static void ddr_sleep_config_restore(void)
+{
+ mmio_write_32(DDR_GRF_BASE + DDRGRF_CHA_CON(2),
+ WITH_16BITS_WMSK(ddr_data.ddrgrf_cha_con2));
+ mmio_write_32(DDR_GRF_BASE + DDRGRF_CHB_CON(2),
+ WITH_16BITS_WMSK(ddr_data.ddrgrf_chb_con2));
+}
+
+static void sleep_pin_config(void)
+{
+ /* pwr0 sleep: gpio0_a3 */
+ mmio_write_32(PMU0_GRF_BASE + PMU0GRF_SOC_CON(1),
+ BITS_WITH_WMASK(0x7, 0xf, 0));
+ mmio_write_32(PMU0_GRF_BASE + PMU0GRF_SOC_CON(0),
+ BITS_WITH_WMASK(0, 0x1, 7));
+ mmio_write_32(PMU0_IOC_BASE + PMUIO0_IOC_GPIO0A_IOMUX_SEL_L,
+ BITS_WITH_WMASK(9, 0xfu, 12));
+}
+
+static void pmu_sleep_config(void)
+{
+ uint32_t pmu1_wkup_int_con;
+ uint32_t pmu1_pwr_con, pmu1_ddr_pwr_con, pmu1cru_pwr_con, pmu1_pll_pd_con;
+ uint32_t pmu2_bus_idle_con[2], pmu2_pwr_gt_con[2];
+ uint32_t key_upd_msk = ddr_data.pmu_pd_st & BIT(pmu_pd_vop) ? 0x3 : 0x7;
+ uint32_t fw_lkp_upd_msk = ddr_data.pmu_pd_st & BIT(pmu_pd_npu) ? 0x3 : 0x7;
+ uint32_t fw_ddr_upd_msk = key_upd_msk;
+ uint32_t pmu_pd_st = mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST);
+ uint32_t bus_idle_st = mmio_read_32(PMU_BASE + PMU2_BUS_IDLE_ST);
+
+ ddr_data.pmu2_bisr_glb_con = mmio_read_32(PMU_BASE + PMU2_BISR_GLB_CON);
+
+ ddr_data.pmu2_fast_pwr_con =
+ mmio_read_32(PMU_BASE + PMU2_FAST_POWER_CON);
+
+ ddr_data.pmu2_c0_ack_sel_con0 =
+ mmio_read_32(PMU_BASE + PMU2_C0_PWRACK_BYPASS_CON(0));
+ ddr_data.pmu2_c1_ack_sel_con0 =
+ mmio_read_32(PMU_BASE + PMU2_C1_PWRACK_BYPASS_CON(0));
+ ddr_data.pmu2_c2_ack_sel_con0 =
+ mmio_read_32(PMU_BASE + PMU2_C2_PWRACK_BYPASS_CON(0));
+ ddr_data.pmu0grf_soc_con5 =
+ mmio_read_32(PMU0_GRF_BASE + PMU0GRF_SOC_CON(5));
+
+ /* set tsadc_shut_m0 pin iomux to gpio */
+ mmio_write_32(PMU0_IOC_BASE + PMUIO0_IOC_GPIO0A_IOMUX_SEL_L,
+ BITS_WITH_WMASK(0, 0xf, 4));
+
+ pmu1_wkup_int_con =
+ BIT(pmu_wkup_cpu0_int) |
+ BIT(pmu_wkup_gpio0_int);
+
+ pmu1_pwr_con =
+ BIT(pmu_powermode_en) |
+ /* BIT(pmu_scu0_byp) | */
+ /* BIT(pmu_scu1_byp) | */
+ /* BIT(pmu_cci_byp) | */
+ /* BIT(pmu_bus_byp) | */
+ /* BIT(pmu_ddr_byp) | */
+ /* BIT(pmu_pwrgt_byp) | */
+ /* BIT(pmu_cru_byp) | */
+ BIT(pmu_qch_byp) |
+ /* BIT(pmu_wfi_byp) | */
+ BIT(pmu_slp_cnt_en);
+
+ pmu1_ddr_pwr_con = 0;
+
+ pmu1_pll_pd_con =
+ BIT(pmu_bpll_pd_en) |
+ BIT(pmu_lpll_pd_en) |
+ BIT(pmu_spll_pd_en) |
+ BIT(pmu_gpll_pd_en) |
+ BIT(pmu_cpll_pd_en) |
+ BIT(pmu_ppll_pd_en) |
+ BIT(pmu_aupll_pd_en) |
+ BIT(pmu_vpll_pd_en);
+
+ pmu1cru_pwr_con =
+ BIT(pmu_alive_osc_mode_en) |
+ BIT(pmu_io_sleep_en) |
+ BIT(pmu_power_off_en);
+
+ pmu2_bus_idle_con[0] = 0xffff & ~(bus_idle_st & 0xffff);
+ pmu2_bus_idle_con[1] = 0x3fff & ~(bus_idle_st >> 16);
+
+ pmu2_pwr_gt_con[0] = 0xffff & ~(pmu_pd_st & 0xffff);
+ pmu2_pwr_gt_con[1] = 0x03ff & ~(pmu_pd_st >> 16);
+
+ pmu2_pwr_gt_con[0] &=
+ ~(BIT(pmu_pd_secure) |
+ BIT(pmu_pd_bus) |
+ BIT(pmu_pd_center) |
+ BIT(pmu_pd_ddr));
+
+ mmio_write_32(PMU_BASE + PMU2_BUS_IDLEACK_BYPASS_CON, 0x00030003);
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_KEYUPD_CON0, 0x03ff0000);
+
+ /* disable repair */
+ mmio_write_32(PMU_BASE + PMU2_BISR_GLB_CON, 0x00010000);
+
+ /* disable ddr_hash_key update.
+ * enable disable ddr_hash_key auto update.
+ * wait ddr_hash_key auto update.
+ */
+ mmio_write_32(SYS_SGRF_BASE + SYSSGRF_SOC_CON(19),
+ BITS_WITH_WMASK(key_upd_msk, 0x7, 8));
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_KEYUPD_CON1,
+ BITS_WITH_WMASK(fw_lkp_upd_msk, 0x7, 10));
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_KEYUPD_CON1,
+ BITS_WITH_WMASK(fw_ddr_upd_msk, 0x7u, 13));
+
+ mmio_write_32(PMU_BASE + PMU0_PMIC_STABLE_CNT_THRES, 24000 * 5);
+ mmio_write_32(PMU_BASE + PMU0_OSC_STABLE_CNT_THRES, 24000 * 5);
+
+ mmio_write_32(PMU_BASE + PMU1_OSC_STABLE_CNT_THRESH, 24000 * 5);
+ mmio_write_32(PMU_BASE + PMU1_STABLE_CNT_THRESH, 24000 * 5);
+
+ mmio_write_32(PMU_BASE + PMU1_SLEEP_CNT_THRESH, 24000 * 15);
+
+ /* Pmu's clk has switched to 24M back When pmu FSM counts
+ * the follow counters, so we should use 24M to calculate
+ * these counters.
+ */
+ mmio_write_32(PMU_BASE + PMU0_WAKEUP_RST_CLR_CNT_THRES, 12000);
+
+ mmio_write_32(PMU_BASE + PMU1_WAKEUP_RST_CLR_CNT_THRESH, 12000);
+ mmio_write_32(PMU_BASE + PMU1_PLL_LOCK_CNT_THRESH, 12000);
+ mmio_write_32(PMU_BASE + PMU1_PWM_SWITCH_CNT_THRESH,
+ 24000 * 2);
+
+ mmio_write_32(PMU_BASE + PMU2_SCU0_PWRUP_CNT_THRESH, 0);
+ mmio_write_32(PMU_BASE + PMU2_SCU0_PWRDN_CNT_THRESH, 0);
+ mmio_write_32(PMU_BASE + PMU2_SCU0_STABLE_CNT_THRESH, 0);
+
+ mmio_write_32(PMU_BASE + PMU2_FAST_PWRUP_CNT_THRESH_0, 0);
+ mmio_write_32(PMU_BASE + PMU2_FAST_PWRDN_CNT_THRESH_0, 0);
+ mmio_write_32(PMU_BASE + PMU2_FAST_PWRUP_CNT_THRESH_1, 0);
+ mmio_write_32(PMU_BASE + PMU2_FAST_PWRDN_CNT_THRESH_1, 0);
+ mmio_write_32(PMU_BASE + PMU2_FAST_PWRUP_CNT_THRESH_2, 0);
+ mmio_write_32(PMU_BASE + PMU2_FAST_PWRDN_CNT_THRESH_2, 0);
+ mmio_write_32(PMU_BASE + PMU2_FAST_POWER_CON, 0xffff0007);
+
+ /* pmu_clst_idle_con */
+ mmio_write_32(PMU_BASE + PMU2_CLUSTER0_IDLE_CON, 0xffff0007);
+ mmio_write_32(PMU_BASE + PMU2_CLUSTER1_IDLE_CON, 0xffff0007);
+
+ /* pmu_scu_pwr_con */
+ /* L2's flush and idle by hardware, so need to enable wfil2 bypass */
+ mmio_write_32(PMU_BASE + PMU2_SCU0_PWR_CON, 0xffff020f);
+ mmio_write_32(PMU_BASE + PMU2_SCU1_PWR_CON, 0xffff020f);
+ mmio_write_32(PMU_BASE + PMU2_SCU0_AUTO_PWR_CON, 0x00070000);
+ mmio_write_32(PMU_BASE + PMU2_SCU1_AUTO_PWR_CON, 0x00070000);
+
+ mmio_write_32(PMU_BASE + PMU2_CCI_PWR_CON, 0xffff0009);
+
+ /* pmu_int_msk_con */
+ /* mmio_write_32(PMU_BASE + PMU1_INT_MASK_CON, BITS_WITH_WMASK(1, 0x1, 0)); */
+
+ /* pmu_pwr_con */
+ mmio_write_32(PMU_BASE + PMU1_PWR_CON, WITH_16BITS_WMSK(pmu1_pwr_con));
+
+ /* pmu_cru_pwr_conx */
+ mmio_write_32(PMU_BASE + PMU1_CRU_PWR_CON(0), WITH_16BITS_WMSK(pmu1cru_pwr_con));
+
+ /* pmu_ddr_pwr_con */
+ mmio_write_32(PMU_BASE + PMU0_DDR_RET_CON(1), 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU1_DDR_PWR_CON(0), WITH_16BITS_WMSK(pmu1_ddr_pwr_con));
+ mmio_write_32(PMU_BASE + PMU1_DDR_PWR_CON(1), WITH_16BITS_WMSK(pmu1_ddr_pwr_con));
+ mmio_write_32(PMU_BASE + PMU1_DDR_AXIPWR_CON(0), 0x03ff03ff);
+ mmio_write_32(PMU_BASE + PMU1_DDR_AXIPWR_CON(1), 0x03ff03ff);
+
+ /* pll_pd */
+ mmio_write_32(PMU_BASE + PMU1_PLLPD_CON(0), WITH_16BITS_WMSK(pmu1_pll_pd_con));
+
+ /* bus idle */
+ mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_CON(0), WITH_16BITS_WMSK(pmu2_bus_idle_con[0]));
+ mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_CON(1), WITH_16BITS_WMSK(pmu2_bus_idle_con[1]));
+
+ /* power gate */
+ mmio_write_32(PMU_BASE + PMU2_PWR_GATE_CON(0), WITH_16BITS_WMSK(pmu2_pwr_gt_con[0]));
+ mmio_write_32(PMU_BASE + PMU2_PWR_GATE_CON(1), WITH_16BITS_WMSK(pmu2_pwr_gt_con[1]));
+
+ /* vol gate */
+ mmio_write_32(PMU_BASE + PMU2_VOL_GATE_SFTCON(0), 0xffff0031);
+ mmio_write_32(PMU_BASE + PMU2_VOL_GATE_SFTCON(1), 0xffff0200);
+
+ /* wakeup source */
+ mmio_write_32(PMU_BASE + PMU1_WAKEUP_INT_CON, pmu1_wkup_int_con);
+
+ /* ppll clamp */
+ mmio_write_32(PMU0_GRF_BASE + PMU0GRF_SOC_CON(5), 0x00400040);
+
+ /* usbphy clamp */
+ mmio_write_32(PMU0_GRF_BASE + PMU0GRF_SOC_CON(5),
+ BITS_WITH_WMASK(0x9, 0x9, 2));
+
+ /* big core pwr ack bypass */
+ mmio_write_32(PMU_BASE + PMU2_C0_PWRACK_BYPASS_CON(0), 0x01000100);
+ mmio_write_32(PMU_BASE + PMU2_C1_PWRACK_BYPASS_CON(0), 0x01000100);
+ mmio_write_32(PMU_BASE + PMU2_C2_PWRACK_BYPASS_CON(0), 0x01000100);
+}
+
+static void pmu_sleep_restore(void)
+{
+ mmio_write_32(PMU_BASE + PMU0_INFO_TX_CON, 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU2_DEBUG_INFO_SEL, 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU2_CLUSTER0_IDLE_CON, 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU2_SCU0_PWR_CON, 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU2_CCI_PWR_CON, 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU1_INT_MASK_CON, 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU1_PWR_CON, 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU1_CRU_PWR_CON(0), 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU1_DDR_PWR_CON(0), 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU1_DDR_PWR_CON(1), 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU1_DDR_AXIPWR_CON(0), 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU1_DDR_AXIPWR_CON(1), 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU1_PLLPD_CON(0), 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_CON(0), 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_CON(1), 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU2_PWR_GATE_CON(0), 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU2_PWR_GATE_CON(1), 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU2_VOL_GATE_SFTCON(0), 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU2_VOL_GATE_SFTCON(1), 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU2_BUS_IDLEACK_BYPASS_CON, 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU1_WAKEUP_INT_CON, 0);
+ mmio_write_32(PMU_BASE + PMU2_FAST_POWER_CON,
+ WITH_16BITS_WMSK(ddr_data.pmu2_fast_pwr_con));
+ mmio_write_32(PMU_BASE + PMU2_BISR_GLB_CON,
+ WITH_16BITS_WMSK(ddr_data.pmu2_bisr_glb_con));
+
+ mmio_write_32(PMU_BASE + PMU2_C0_PWRACK_BYPASS_CON(0),
+ WITH_16BITS_WMSK(ddr_data.pmu2_c0_ack_sel_con0));
+ mmio_write_32(PMU_BASE + PMU2_C1_PWRACK_BYPASS_CON(0),
+ WITH_16BITS_WMSK(ddr_data.pmu2_c1_ack_sel_con0));
+ mmio_write_32(PMU_BASE + PMU2_C2_PWRACK_BYPASS_CON(0),
+ WITH_16BITS_WMSK(ddr_data.pmu2_c2_ack_sel_con0));
+
+ mmio_write_32(PMU0_GRF_BASE + PMU0GRF_SOC_CON(5),
+ WITH_16BITS_WMSK(ddr_data.pmu0grf_soc_con5));
+}
+
+static void secure_watchdog_disable(void)
+{
+ ddr_data.sys_sgrf_soc_con0 =
+ mmio_read_32(SYS_SGRF_BASE + SYSSGRF_SOC_CON(0));
+
+ /* pause wdt_s */
+ mmio_write_32(SYS_SGRF_BASE + SYSSGRF_SOC_CON(0),
+ BITS_WITH_WMASK(1, 0x1, 14));
+}
+
+static void secure_watchdog_restore(void)
+{
+ mmio_write_32(SYS_SGRF_BASE + SYSSGRF_SOC_CON(0),
+ ddr_data.sys_sgrf_soc_con0 |
+ BITS_WMSK(0x1, 14));
+
+ if (mmio_read_32(WDT_S_BASE + WDT_CR) & WDT_EN)
+ mmio_write_32(WDT_S_BASE + WDT_CRR, 0x76);
+}
+
+static void soc_sleep_config(void)
+{
+ ddr_data.pmu0grf_soc_con0 =
+ mmio_read_32(PMU0_GRF_BASE + PMU0GRF_SOC_CON(0));
+ ddr_data.pmu0grf_soc_con1 =
+ mmio_read_32(PMU0_GRF_BASE + PMU0GRF_SOC_CON(1));
+
+ ddr_data.gpio0a_iomux_l =
+ mmio_read_32(PMU0_IOC_BASE + PMUIO0_IOC_GPIO0A_IOMUX_SEL_L);
+ ddr_data.gpio0a_iomux_h =
+ mmio_read_32(PMU0_IOC_BASE + PMUIO0_IOC_GPIO0A_IOMUX_SEL_H);
+ ddr_data.gpio0b_iomux_l =
+ mmio_read_32(PMU0_IOC_BASE + PMUIO0_IOC_GPIO0B_IOMUX_SEL_L);
+
+ sleep_pin_config();
+ pmu_sleep_config();
+ ddr_sleep_config();
+ secure_watchdog_disable();
+}
+
+static void soc_sleep_restore(void)
+{
+ secure_watchdog_restore();
+ ddr_sleep_config_restore();
+ pmu_sleep_restore();
+
+ mmio_write_32(PMU0_IOC_BASE + PMUIO0_IOC_GPIO0A_IOMUX_SEL_L,
+ WITH_16BITS_WMSK(ddr_data.gpio0a_iomux_l));
+ mmio_write_32(PMU0_IOC_BASE + PMUIO0_IOC_GPIO0A_IOMUX_SEL_H,
+ WITH_16BITS_WMSK(ddr_data.gpio0a_iomux_h));
+ mmio_write_32(PMU0_IOC_BASE + PMUIO0_IOC_GPIO0B_IOMUX_SEL_L,
+ WITH_16BITS_WMSK(ddr_data.gpio0b_iomux_l));
+
+ mmio_write_32(PMU0_GRF_BASE + PMU0GRF_SOC_CON(1),
+ WITH_16BITS_WMSK(ddr_data.pmu0grf_soc_con1));
+ mmio_write_32(PMU0_GRF_BASE + PMU0GRF_SOC_CON(0),
+ WITH_16BITS_WMSK(ddr_data.pmu0grf_soc_con0));
+}
+
+static void pm_pll_suspend(void)
+{
+ ddr_data.cru_mode_con = mmio_read_32(CRU_BASE + 0x280);
+ ddr_data.secure_cru_mode = mmio_read_32(SECURE_CRU_BASE + 0x4280);
+
+ /* bpll gpll vpll aupll cpll spll switch to slow mode */
+ mmio_write_32(CRU_BASE + 0x280, 0x03ff0000);
+ mmio_write_32(SECURE_CRU_BASE + 0x4280, 0x00030000);
+
+ /* hclk_pmu_cm0_root_i_sel to 24M */
+ mmio_write_32(PMU1_CRU_BASE + PMU1CRU_CLKSEL_CON(4),
+ BITS_WITH_WMASK(0x3, 0x3, 2));
+}
+
+static void pm_pll_restore(void)
+{
+ mmio_write_32(CRU_BASE + 0x280, WITH_16BITS_WMSK(ddr_data.cru_mode_con));
+ mmio_write_32(SECURE_CRU_BASE + 0x4280,
+ WITH_16BITS_WMSK(ddr_data.secure_cru_mode));
+}
+
+int rockchip_soc_sys_pwr_dm_suspend(void)
+{
+ psram_sleep_cfg->pm_flag &= ~PM_WARM_BOOT_BIT;
+
+ clk_gate_con_save();
+ clk_gate_con_disable();
+ dmc_save();
+ pmu_power_domains_suspend();
+ soc_sleep_config();
+ pm_pll_suspend();
+ pd_core_save();
+
+ return 0;
+}
+
+int rockchip_soc_sys_pwr_dm_resume(void)
+{
+ pd_core_restore();
+ pm_pll_restore();
+ soc_sleep_restore();
+ pmu_power_domains_resume();
+ plat_rockchip_gic_cpuif_enable();
+ dmc_restore();
+ clk_gate_con_restore();
+
+ psram_sleep_cfg->pm_flag |= PM_WARM_BOOT_BIT;
+
+ return 0;
+}
+
+void __dead2 rockchip_soc_cores_pd_pwr_dn_wfi(const
+ psci_power_state_t *target_state)
+{
+ psci_power_down_wfi();
+ /* should never reach here */
+ panic();
+}
+
+void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void)
+{
+ psci_power_down_wfi();
+ /* should never reach here */
+ panic();
+}
+
+static int rockchip_reboot_is_rbrom(void)
+{
+ return mmio_read_32(PMU0_GRF_BASE + PMU0GRF_OS_REG(16)) ==
+ BOOT_BROM_DOWNLOAD;
+}
+
+static void rockchip_soc_soft_reset_check_rstout(void)
+{
+ /*
+ * Maskrom enter maskrom-usb mode according to os_reg0 which
+ * will be reset by NPOR. So disable tsadc_shut_m0 if we want
+ * to maskrom-usb mode.
+ */
+ if (rockchip_reboot_is_rbrom() != 0) {
+ /* write BOOT_BROM_DOWNLOAD to os_reg0 */
+ mmio_write_32(PMU1_GRF_BASE + PMU1GRF_OS_REG(0), BOOT_BROM_DOWNLOAD);
+
+ /* disable first/tsadc/wdt reset output */
+ mmio_write_32(PMU1SGRF_BASE + PMU1SGRF_SOC_CON(0), 0x00070000);
+
+ /* clear reset hold */
+ mmio_write_32(PMU0SGRF_BASE + PMU0SGRF_SOC_CON(1), 0xffff0000);
+ mmio_write_32(PMU1SGRF_BASE + PMU1SGRF_SOC_CON(16), 0xffff0000);
+ mmio_write_32(PMU1SGRF_BASE + PMU1SGRF_SOC_CON(17), 0xffff0000);
+ }
+}
+
+void __dead2 rockchip_soc_soft_reset(void)
+{
+ rockchip_soc_soft_reset_check_rstout();
+
+ /* pll slow mode */
+ mmio_write_32(CRU_BASE + CRU_MODE_CON, 0x003f0000);
+
+ dsb();
+ isb();
+
+ INFO("system reset......\n");
+ mmio_write_32(CRU_BASE + CRU_GLB_SRST_FST, GLB_SRST_FST_CFG_VAL);
+
+ /*
+ * Maybe the HW needs some times to reset the system,
+ * so we do not hope the core to execute valid codes.
+ */
+ psci_power_down_wfi();
+ /* should never reach here */
+ panic();
+}
+
+void __dead2 rockchip_soc_system_off(void)
+{
+ INFO("system poweroff......\n");
+
+ /* gpio0_a3 config output */
+ mmio_write_32(GPIO0_BASE + GPIO_SWPORT_DDR_L,
+ BITS_WITH_WMASK(1, 0x1, 3));
+
+ /* gpio0_a3 config output high level */
+ mmio_write_32(GPIO0_BASE + GPIO_SWPORT_DR_L,
+ BITS_WITH_WMASK(1, 0x1, 3));
+ dsb();
+
+ /*
+ * Maybe the HW needs some times to reset the system,
+ * so we do not hope the core to execute valid codes.
+ */
+ psci_power_down_wfi();
+ /* should never reach here */
+ panic();
+}
+
+static void rockchip_pmu_pd_repair_init(void)
+{
+ INFO("enable memory repair\n");
+ /* Enable gpu and npu repair */
+ mmio_write_32(PMU_BASE + PMU2_BISR_PDGEN_CON(1),
+ BITS_WITH_WMASK(0xf, 0xf, 6));
+}
+
+void plat_rockchip_pmu_init(void)
+{
+ int cpu;
+
+ for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++)
+ cpuson_flags[cpu] = 0;
+
+ psram_sleep_cfg->sp = PSRAM_SP_TOP;
+ psram_sleep_cfg->ddr_func = (uint64_t)ddr_resume;
+ psram_sleep_cfg->ddr_data = 0;
+ psram_sleep_cfg->ddr_flag = 0;
+ psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff;
+ psram_sleep_cfg->pm_flag = PM_WARM_BOOT_BIT;
+
+ nonboot_cpus_off();
+
+ /*
+ * When perform idle operation, corresponding clock can be
+ * opened or gated automatically.
+ */
+ mmio_write_32(PMU_BASE + PMU2_NOC_AUTO_CON(0), 0xffffffff);
+ mmio_write_32(PMU_BASE + PMU2_NOC_AUTO_CON(1), 0xffffffff);
+
+ /* remap pmusram to 0x00000000 */
+ mmio_write_32(PMU0SGRF_BASE + PMU0SGRF_SOC_CON(2), BITS_WITH_WMASK(1, 0x3, 0));
+
+ /* enable power off VD_NPU by hrdware */
+ mmio_write_32(PMU_BASE + PMU2_VOL_GATE_SFTCON(0),
+ BITS_WITH_WMASK(0x1, 0x1, 0));
+
+ rockchip_pmu_pd_repair_init();
+
+ pm_reg_rgns_init();
+}
diff --git a/plat/rockchip/rk3576/drivers/pmu/pmu.h b/plat/rockchip/rk3576/drivers/pmu/pmu.h
new file mode 100644
index 0000000..6340e3f
--- /dev/null
+++ b/plat/rockchip/rk3576/drivers/pmu/pmu.h
@@ -0,0 +1,578 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#ifndef __PMU_H__
+#define __PMU_H__
+
+#include <assert.h>
+
+#include <mmio.h>
+
+/* PMU */
+#define PMU1_OFFSET 0x10000
+#define PMU2_OFFSET 0x20000
+
+#define PMU0_PWR_CON 0x0000
+#define PMU0_PWR_STATUS 0x0004
+#define PMU0_WAKEUP_INT_CON 0x0008
+#define PMU0_WAKEUP_INT_ST 0x000c
+#define PMU0_PMIC_STABLE_CNT_THRES 0x0010
+#define PMU0_WAKEUP_RST_CLR_CNT_THRES 0x0014
+#define PMU0_OSC_STABLE_CNT_THRES 0x0018
+#define PMU0_PWR_C0_STABLE_CON 0x001c
+#define PMU0_DDR_RET_CON(i) (0x0020 + (i) * 4)
+#define PMU0_INFO_TX_CON 0x0030
+
+#define PMU1_VERSION_ID (PMU1_OFFSET + 0x0000)
+#define PMU1_PWR_CON (PMU1_OFFSET + 0x0004)
+#define PMU1_PWR_FSM (PMU1_OFFSET + 0x0008)
+#define PMU1_INT_MASK_CON (PMU1_OFFSET + 0x000c)
+#define PMU1_WAKEUP_INT_CON (PMU1_OFFSET + 0x0010)
+#define PMU1_WAKEUP_INT_ST (PMU1_OFFSET + 0x0014)
+#define PMU1_DDR_PWR_CON(i) (PMU1_OFFSET + 0x0100 + (i) * 4)
+#define PMU1_DDR_PWR_SFTCON(i) (PMU1_OFFSET + 0x0110 + (i) * 4)
+#define PMU1_DDR_AXIPWR_CON(i) (PMU1_OFFSET + 0x0120 + (i) * 4)
+#define PMU1_DDR_AXIPWR_SFTCON(i) (PMU1_OFFSET + 0x0130 + (i) * 4)
+#define PMU1_DDR_PWR_FSM (PMU1_OFFSET + 0x0140)
+#define PMU1_DDR_PWR_ST (PMU1_OFFSET + 0x0144)
+#define PMU1_DDR_AXIPWR_ST (PMU1_OFFSET + 0x0148)
+#define PMU1_CRU_PWR_CON(i) (PMU1_OFFSET + 0x0200 + (i) * 4)
+#define PMU1_CRU_PWR_SFTCON(i) (PMU1_OFFSET + 0x0208 + (i) * 4)
+#define PMU1_CRU_PWR_FSM (PMU1_OFFSET + 0x0210)
+#define PMU1_PLLPD_CON(i) (PMU1_OFFSET + 0x0220 + (i) * 4)
+#define PMU1_PLLPD_SFTCON(i) (PMU1_OFFSET + 0x0228 + (i) * 4)
+#define PMU1_STABLE_CNT_THRESH (PMU1_OFFSET + 0x0300)
+#define PMU1_OSC_STABLE_CNT_THRESH (PMU1_OFFSET + 0x0304)
+#define PMU1_WAKEUP_RST_CLR_CNT_THRESH (PMU1_OFFSET + 0x0308)
+#define PMU1_PLL_LOCK_CNT_THRESH (PMU1_OFFSET + 0x030c)
+#define PMU1_WAKEUP_TIMEOUT_THRESH (PMU1_OFFSET + 0x0310)
+#define PMU1_PWM_SWITCH_CNT_THRESH (PMU1_OFFSET + 0x0314)
+#define PMU1_SLEEP_CNT_THRESH (PMU1_OFFSET + 0x0318)
+#define PMU1_INFO_TX_CON (PMU1_OFFSET + 0x0400)
+
+#define PMU2_SCU0_PWR_CON (PMU2_OFFSET + 0x0000)
+#define PMU2_SCU1_PWR_CON (PMU2_OFFSET + 0x0004)
+#define PMU2_SCU0_PWR_SFTCON (PMU2_OFFSET + 0x0008)
+#define PMU2_SCU1_PWR_SFTCON (PMU2_OFFSET + 0x000c)
+#define PMU2_SCU0_AUTO_PWR_CON (PMU2_OFFSET + 0x0010)
+#define PMU2_SCU1_AUTO_PWR_CON (PMU2_OFFSET + 0x0014)
+#define PMU2_SCU_PWR_FSM_STATUS (PMU2_OFFSET + 0x0018)
+#define PMU2_DBG_PWR_CON(i) (PMU2_OFFSET + 0x001c + (i) * 4)
+#define PMU2_CLUSTER_PWR_ST (PMU2_OFFSET + 0x0024)
+#define PMU2_CLUSTER0_IDLE_CON (PMU2_OFFSET + 0x0028)
+#define PMU2_CLUSTER1_IDLE_CON (PMU2_OFFSET + 0x002c)
+#define PMU2_CLUSTER0_IDLE_SFTCON (PMU2_OFFSET + 0x0030)
+#define PMU2_CLUSTER1_IDLE_SFTCON (PMU2_OFFSET + 0x0034)
+#define PMU2_CLUSTER_IDLE_ACK (PMU2_OFFSET + 0x0038)
+#define PMU2_CLUSTER_IDLE_ST (PMU2_OFFSET + 0x003c)
+#define PMU2_SCU0_PWRUP_CNT_THRESH (PMU2_OFFSET + 0x0040)
+#define PMU2_SCU0_PWRDN_CNT_THRESH (PMU2_OFFSET + 0x0044)
+#define PMU2_SCU0_STABLE_CNT_THRESH (PMU2_OFFSET + 0x0048)
+#define PMU2_SCU1_PWRUP_CNT_THRESH (PMU2_OFFSET + 0x004c)
+#define PMU2_SCU1_PWRDN_CNT_THRESH (PMU2_OFFSET + 0x0050)
+#define PMU2_SCU1_STABLE_CNT_THRESH (PMU2_OFFSET + 0x0054)
+#define PMU2_CPU_AUTO_PWR_CON(i) (PMU2_OFFSET + 0x0080 + ((i)) * 4)
+#define PMU2_CPU_PWR_SFTCON(i) (PMU2_OFFSET + 0x00a0 + ((i)) * 4)
+#define PMU2_CCI_PWR_CON (PMU2_OFFSET + 0x00e0)
+#define PMU2_CCI_PWR_SFTCON (PMU2_OFFSET + 0x00e4)
+#define PMU2_CCI_PWR_ST (PMU2_OFFSET + 0x00e8)
+#define PMU2_CCI_POWER_STATE (PMU2_OFFSET + 0x00ec)
+#define PMU2_BUS_IDLE_CON(i) (PMU2_OFFSET + 0x0100 + (i) * 4)
+#define PMU2_BUS_IDLE_SFTCON(i) (PMU2_OFFSET + 0x0110 + (i) * 4)
+#define PMU2_BUS_IDLE_ACK (PMU2_OFFSET + 0x0120)
+#define PMU2_BUS_IDLE_ST (PMU2_OFFSET + 0x0128)
+#define PMU2_NOC_AUTO_CON(i) (PMU2_OFFSET + 0x0130 + (i) * 4)
+#define PMU2_NOC_AUTO_SFTCON(i) (PMU2_OFFSET + 0x0140 + (i) * 4)
+#define PMU2_BUS_IDLEACK_BYPASS_CON (PMU2_OFFSET + 0x0150)
+#define PMU2_PWR_GATE_CON(i) (PMU2_OFFSET + 0x0200 + (i) * 4)
+#define PMU2_PWR_GATE_SFTCON(i) (PMU2_OFFSET + 0x0210 + (i) * 4)
+#define PMU2_VOL_GATE_SFTCON(i) (PMU2_OFFSET + 0x0220 + (i) * 4)
+#define PMU2_PWR_GATE_ST (PMU2_OFFSET + 0x0230)
+#define PMU2_PWR_GATE_FSM (PMU2_OFFSET + 0x0238)
+#define PMU2_PD_DWN_ACK_STATE(i) (PMU2_OFFSET + 0x0240 + (i) * 4)
+#define PMU2_PD_DWN_LC_ACK_STATE(i) (PMU2_OFFSET + 0x0248 + (i) * 4)
+#define PMU2_PD_DWN_MEM_ACK_STATE(i) (PMU2_OFFSET + 0x0250 + (i) * 4)
+#define PMU2_PWR_UP_C0_STABLE_CON(i) (PMU2_OFFSET + 0x0260 + (i) * 4)
+#define PMU2_PWR_DWN_C0_STABLE_CON(i) (PMU2_OFFSET + 0x0270 + (i) * 4)
+#define PMU2_PWR_STABLE_C0_CNT_THRES (PMU2_OFFSET + 0x027c)
+#define PMU2_FAST_POWER_CON (PMU2_OFFSET + 0x0284)
+#define PMU2_FAST_PWRUP_CNT_THRESH_0 (PMU2_OFFSET + 0x0288)
+#define PMU2_FAST_PWRDN_CNT_THRESH_0 (PMU2_OFFSET + 0x028c)
+#define PMU2_FAST_PWRUP_CNT_THRESH_1 (PMU2_OFFSET + 0x0290)
+#define PMU2_FAST_PWRDN_CNT_THRESH_1 (PMU2_OFFSET + 0x0294)
+#define PMU2_FAST_PWRUP_CNT_THRESH_2 (PMU2_OFFSET + 0x0298)
+#define PMU2_FAST_PWRDN_CNT_THRESH_2 (PMU2_OFFSET + 0x029c)
+#define PMU2_MEM_PWR_GATE_SFTCON(i) (PMU2_OFFSET + 0x0300)
+#define PMU2_SUBMEM_PWR_GATE_SFTCON(i) (PMU2_OFFSET + 0x0310)
+#define PMU2_SUBMEM_PWR_ACK_BYPASS_SFTCON(i) (PMU2_OFFSET + 0x0320)
+#define PMU2_SUBMEM_PWR_GATE_STATUS (PMU2_OFFSET + 0x0328)
+#define PMU2_QCHANNEL_PWR_CON0 (PMU2_OFFSET + 0x0400)
+#define PMU2_QCHANNEL_PWR_SFTCON0 (PMU2_OFFSET + 0x0404)
+#define PMU2_QCHANNEL_STATUS0 (PMU2_OFFSET + 0x0408)
+#define PMU2_C0_PWRACK_BYPASS_CON(i) (PMU2_OFFSET + 0x0380 + (i) * 4)
+#define PMU2_C1_PWRACK_BYPASS_CON(i) (PMU2_OFFSET + 0x0390 + (i) * 4)
+#define PMU2_C2_PWRACK_BYPASS_CON(i) (PMU2_OFFSET + 0x03a0 + (i) * 4)
+#define PMU2_DEBUG_INFO_SEL (PMU2_OFFSET + 0x03f0)
+#define PMU2_BISR_GLB_CON (PMU2_OFFSET + 0x500)
+#define PMU2_BISR_TIMEOUT_THRES (PMU2_OFFSET + 0x504)
+#define PMU2_BISR_PDGEN_CON(i) (PMU2_OFFSET + 0x510 + (i) * 4)
+#define PMU2_BISR_PDGEN_SFTCON(i) (PMU2_OFFSET + 0x520 + (i) * 4)
+#define PMU2_BISR_PDGDONE_CON(i) (PMU2_OFFSET + 0x530 + (i) * 4)
+#define PMU2_BISR_PDGINIT_CON(i) (PMU2_OFFSET + 0x540 + (i) * 4)
+#define PMU2_BISR_PDGDONE_STATUS(i) (PMU2_OFFSET + 0x550 + (i) * 4)
+#define PMU2_BISR_PDGCEDIS_STATUS(i) (PMU2_OFFSET + 0x560 + (i) * 4)
+#define PMU2_BISR_PWR_REPAIR_STATUS(i) (PMU2_OFFSET + 0x570 + (i) * 4)
+
+/* PMU1CRU */
+#define PMU1CRU_CLKSEL_CON(i) ((i) * 0x4 + 0x300)
+#define PMU1CRU_CLKSEL_CON_CNT 22
+#define PMU1CRU_CLKGATE_CON(i) ((i) * 0x4 + 0x800)
+#define PMU1CRU_CLKGATE_CON_CNT 8
+#define PMU1CRU_SOFTRST_CON(i) ((i) * 0x4 + 0xa00)
+#define PMU1CRU_SOFTRST_CON_CNT 8
+#define PMU1CRU_DEEPSLOW_DET_CON 0xb40
+#define PMU1CRU_DEEPSLOW_DET_ST 0xb44
+
+/* PMU1SCRU */
+#define PMU1SCRU_CLKSEL_CON(i) ((i) * 0x4 + 0x4000)
+#define PMU1SCRU_CLKSEL_CON_CNT 3
+#define PMU1SCRU_CLKGATE_CON(i) ((i) * 0x4 + 0x4028)
+#define PMU1SCRU_CLKGATE_CON_CNT 3
+#define PMU1SCRU_SOFTRST_CON(i) ((i) * 0x4 + 0x4050)
+#define PMU1SCRU_SOFTRST_CONCNT 3
+
+/* PMU0GRF */
+#define PMU0GRF_SOC_CON(i) ((i) * 4)
+#define PMU0GRF_IO_RET_CON(i) (0x20 + (i) * 4)
+#define PMU0GRF_OS_REG(i) ((i) * 4)
+
+/* PMU1GRF */
+#define PMU1GRF_SOC_CON(i) ((i) * 4)
+#define PMU1GRF_SOC_ST 0x60
+#define PMU1GRF_MEM_CON(i) (0x80 + (i) * 4)
+#define PMU1GRF_OS_REG(i) (0x200 + (i) * 4)
+
+#define PMU_MCU_HALT BIT(7)
+#define PMU_MCU_SLEEP BIT(9)
+#define PMU_MCU_DEEPSLEEP BIT(10)
+#define PMU_MCU_STOP_MSK \
+ (PMU_MCU_HALT | PMU_MCU_SLEEP | PMU_MCU_DEEPSLEEP)
+
+#define CORES_PM_DISABLE 0x0
+
+/* pmuioc */
+#define PMUIO0_IOC_GPIO0A_IOMUX_SEL_L 0x000
+#define PMUIO0_IOC_GPIO0A_IOMUX_SEL_H 0x004
+#define PMUIO0_IOC_GPIO0B_IOMUX_SEL_L 0x008
+
+#define PMUIO1_IOC_GPIO0B_IOMUX_SEL_H 0x000
+#define PMUIO1_IOC_GPIO0C_IOMUX_SEL_L 0x004
+#define PMUIO1_IOC_GPIO0C_IOMUX_SEL_H 0x008
+#define PMUIO1_IOC_GPIO0D_IOMUX_SEL_L 0x00c
+#define PMUIO1_IOC_GPIO0D_IOMUX_SEL_H 0x010
+
+/* PMU_PWR_CON */
+enum pmu0_pwr_con {
+ pmu_powermode0_en = 0,
+ pmu_pmu1_pd_byp = 1,
+ pmu_pmu1_bus_byp = 2,
+ pmu_pmu0_wkup_byp = 3,
+ pmu_pmu0_pmic_byp = 4,
+ pmu_pmu0_reset_byp = 5,
+ pmu_pmu0_freq_switch_byp = 6,
+ pmu_pmu0_osc_dis_byp = 7,
+ pmu_pmu1_pwrgt = 8,
+ pmu_pmu1_pwrgt_sft = 9,
+ pmu_pmu1_mempwr_sft_gt = 10,
+ pmu_pmu1_idle_en = 11,
+ pmu_pmu1_idle_sft_en = 12,
+ pmu_pmu1_noc_auto_en = 13,
+ pmu_pmu1_off_io_en = 14,
+};
+
+enum pmu1_pwr_con {
+ pmu_powermode_en = 0,
+ pmu_scu0_byp = 1,
+ pmu_scu1_byp = 2,
+ pmu_cci_byp = 3,
+ pmu_bus_byp = 4,
+ pmu_ddr_byp = 5,
+ pmu_pwrgt_byp = 6,
+ pmu_cru_byp = 7,
+ pmu_qch_byp = 8,
+ pmu_wfi_byp = 12,
+ pmu_slp_cnt_en = 13,
+};
+
+enum pmu_wakeup_int {
+ pmu_wkup_cpu0_int = 0,
+ pmu_wkup_cpu1_int = 1,
+ pmu_wkup_cpu2_int = 2,
+ pmu_wkup_cpu3_int = 3,
+ pmu_wkup_cpu4_int = 4,
+ pmu_wkup_cpu5_int = 5,
+ pmu_wkup_cpu6_int = 6,
+ pmu_wkup_cpu7_int = 7,
+ pmu_wkup_gpio0_int = 8,
+ pmu_wkup_sdmmc_int = 9,
+ pmu_wkup_sdio_int = 10,
+ pmu_wkup_usbdev_int = 11,
+ pmu_wkup_uart_int = 12,
+ pmu_wkup_mcu_int = 13,
+ pmu_wkup_timer_int = 14,
+ pmu_wkup_sys_int = 15,
+ pmu_wkup_pwm_int = 16,
+ pmu_wkup_tsadc_int = 17,
+ pmu_wkup_hptimer_int = 18,
+ pmu_wkup_saradc_int = 19,
+ pmu_wkup_timeout = 20,
+};
+
+/* PMU_DDR_PWR_CON */
+enum pmu_ddr_pwr_con {
+ pmu_ddr_sref_c_en = 0,
+ pmu_ddr_ioret_en = 1,
+ pmu_ddr_ioret_exit_en = 2,
+ pmu_ddr_rstiov_en = 3,
+ pmu_ddr_rstiov_exit_en = 4,
+ pmu_ddr_gating_c_en = 5,
+ pmu_ddr_gating_p_en = 6,
+};
+
+/* PMU_CRU_PWR_CON0 */
+enum pmu_cru_pwr_con0 {
+ pmu_alive_32k_en = 0,
+ pmu_osc_dis_en = 1,
+ pmu_wakeup_rst_en = 2,
+ pmu_input_clamp_en = 3,
+ pmu_alive_osc_mode_en = 4,
+ pmu_power_off_en = 5,
+ pmu_pwm_switch_en = 6,
+ pmu_pwm_gpio_ioe_en = 7,
+ pmu_pwm_switch_io = 8,
+ pmu_io_sleep_en = 9,
+};
+
+/* PMU_CRU_PWR_CON1 */
+enum pmu_cru_pwr_con1 {
+ pmu_bus_clksrc_gt_en = 0,
+ pmu_vpu_clksrc_gt_en = 1,
+ pmu_vo_clksrc_gt_en = 2,
+ pmu_gpu_clksrc_gt_en = 3,
+ pmu_rkenc_clksrc_gt_en = 4,
+ pmu_rkvdec_clksrc_gt_en = 5,
+ pmu_core_clksrc_gt_en = 6,
+ pmu_ddr_clksrc_gt_en = 7,
+};
+
+/* PMU_SCU_PWR_CON */
+enum pmu_scu_pwr_con {
+ pmu_l2_flush_en = 0,
+ pmu_l2_ilde_en = 1,
+ pmu_scu_pd_en = 2,
+ pmu_scu_pwroff_en = 3,
+ pmu_clst_cpu_pd_en = 5,
+ pmu_std_wfi_bypass = 8,
+ pmu_std_wfil2_bypass = 9,
+ pmu_scu_vol_gt_en = 10,
+};
+
+/* PMU_PLLPD_CON */
+enum pmu_pllpd_con {
+ pmu_d0apll_pd_en = 0,
+ pmu_d0bpll_pd_en = 1,
+ pmu_d1apll_pd_en = 2,
+ pmu_d1bpll_pd_en = 3,
+ pmu_bpll_pd_en = 4,
+ pmu_lpll_pd_en = 5,
+ pmu_spll_pd_en = 6,
+ pmu_gpll_pd_en = 7,
+ pmu_cpll_pd_en = 8,
+ pmu_ppll_pd_en = 9,
+ pmu_aupll_pd_en = 10,
+ pmu_vpll_pd_en = 11,
+};
+
+/* PMU_CLST_PWR_ST */
+enum pmu_clst_pwr_st {
+ pmu_cpu0_wfi = 0,
+ pmu_cpu1_wfi = 1,
+ pmu_cpu2_wfi = 2,
+ pmu_cpu3_wfi = 3,
+ pmu_cpu4_wfi = 4,
+ pmu_cpu5_wfi = 5,
+ pmu_cpu6_wfi = 6,
+ pmu_cpu7_wfi = 7,
+ pmu_scu0_standbywfil2 = 8,
+ pmu_scu1_standbywfil2 = 9,
+ pmu_scu0_l2flushdone = 10,
+ pmu_scu1_l2flushdone = 11,
+ pmu_cpu0_pd_st = 16,
+ pmu_cpu1_pd_st = 17,
+ pmu_cpu2_pd_st = 18,
+ pmu_cpu3_pd_st = 19,
+ pmu_cpu4_pd_st = 20,
+ pmu_cpu5_pd_st = 21,
+ pmu_cpu6_pd_st = 22,
+ pmu_cpu7_pd_st = 23,
+ pmu_scu0_pd_st = 24,
+ pmu_scu1_pd_st = 25,
+};
+
+/* PMU_CLST_IDLE_CON */
+enum pmu_clst_idle_con {
+ pmu_adb400s_idle_req = 0,
+ pmu_clst_biu_idle_req = 1,
+ pmu_clst_clk_gt_msk = 2,
+};
+
+enum cores_pm_ctr_mode {
+ core_pwr_pd = 0,
+ core_pwr_wfi = 1,
+ core_pwr_wfi_int = 2,
+ core_pwr_wfi_reset = 3,
+};
+
+/* PMU_CPUX_AUTO_PWR_CON */
+enum pmu_cpu_auto_pwr_con {
+ pmu_cpu_pm_en = 0,
+ pmu_cpu_pm_int_wakeup_en = 1,
+ pmu_cpu_pm_dis_int = 2,
+ pmu_cpu_pm_sft_wakeup_en = 3,
+};
+
+enum qos_id {
+ qos_decom = 0,
+ qos_dmac0 = 1,
+ qos_dmac1 = 2,
+ qos_dmac2 = 3,
+ qos_bus_mcu = 4,
+ qos_can0 = 5,
+ qos_can1 = 6,
+ qos_cci_m0 = 7,
+ qos_cci_m1 = 8,
+ qos_cci_m2 = 9,
+ qos_dap_lite = 10,
+ qos_hdcp1 = 11,
+ qos_ddr_mcu = 12,
+ qos_fspi1 = 13,
+ qos_gmac0 = 14,
+ qos_gmac1 = 15,
+ qos_sdio = 16,
+ qos_sdmmc = 17,
+ qos_flexbus = 18,
+ qos_gpu = 19,
+ qos_vepu1 = 20,
+ qos_npu_mcu = 21,
+ qos_npu_nsp0 = 22,
+ qos_npu_nsp1 = 23,
+ qos_npu_m0 = 24,
+ qos_npu_m1 = 25,
+ qos_npu_m0ro = 26,
+ qos_npu_m1ro = 27,
+ qos_emmc = 28,
+ qos_fspi0 = 29,
+ qos_mmu0 = 30,
+ qos_mmu1 = 31,
+ qos_pmu_mcu = 32,
+ qos_rkvdec = 33,
+ qos_crypto = 34,
+ qos_mmu2 = 35,
+ qos_ufshc = 36,
+ qos_vepu0 = 37,
+ qos_isp_mro = 38,
+ qos_isp_mwo = 39,
+ qos_vicap_m0 = 40,
+ qos_vpss_mro = 41,
+ qos_vpss_mwo = 42,
+ qos_hdcp0 = 43,
+ qos_vop_m0 = 44,
+ qos_vop_m1ro = 45,
+ qos_ebc = 46,
+ qos_rga0 = 47,
+ qos_rga1 = 48,
+ qos_jpeg = 49,
+ qos_vdpp = 50,
+ qos_dma2ddr = 51,
+};
+
+enum pmu_bus_id {
+ pmu_bus_id_gpu = 0,
+ pmu_bus_id_npu0 = 1,
+ pmu_bus_id_npu1 = 2,
+ pmu_bus_id_nputop = 3,
+ pmu_bus_id_npusys = 4,
+ pmu_bus_id_vpu = 5,
+ pmu_bus_id_vdec = 6,
+ pmu_bus_id_vepu0 = 7,
+ pmu_bus_id_vepu1 = 8,
+ pmu_bus_id_vi = 9,
+ pmu_bus_id_usb = 10,
+ pmu_bus_id_vo0 = 11,
+ pmu_bus_id_vo1 = 12,
+ pmu_bus_id_vop = 13,
+ pmu_bus_id_vop_nocddrsch = 14,
+ pmu_bus_id_php = 15,
+ pmu_bus_id_audio = 16,
+ pmu_bus_id_gmac = 17,
+ pmu_bus_id_nvm = 18,
+ pmu_bus_id_center_nocddrsch = 19,
+ pmu_bus_id_center_nocmain = 20,
+ pmu_bus_id_ddr = 21,
+ pmu_bus_id_ddrsch0 = 22,
+ pmu_bus_id_ddrsch1 = 23,
+ pmu_bus_id_bus = 24,
+ pmu_bus_id_secure = 25,
+ pmu_bus_id_top = 26,
+ pmu_bus_id_vo0vop_chn = 27,
+ pmu_bus_id_cci = 28,
+ pmu_bus_id_cci_nocddrsch = 29,
+ pmu_bus_id_max,
+};
+
+enum pmu_pd_id {
+ pmu_pd_npu = 0,
+ pmu_pd_bus = 1,
+ pmu_pd_secure = 2,
+ pmu_pd_center = 3,
+ pmu_pd_ddr = 4,
+ pmu_pd_cci = 5,
+ pmu_pd_nvm = 6,
+ pmu_pd_sd_gmac = 7,
+ pmu_pd_audio = 8,
+ pmu_pd_php = 9,
+ pmu_pd_subphp = 10,
+ pmu_pd_vop = 11,
+ pmu_pd_vop_smart = 12,
+ pmu_pd_vop_clst = 13,
+ pmu_pd_vo1 = 14,
+ pmu_pd_vo0 = 15,
+ pmu_pd_usb = 16,
+ pmu_pd_vi = 17,
+ pmu_pd_vepu0 = 18,
+ pmu_pd_vepu1 = 19,
+ pmu_pd_vdec = 20,
+ pmu_pd_vpu = 21,
+ pmu_pd_nputop = 22,
+ pmu_pd_npu0 = 23,
+ pmu_pd_npu1 = 24,
+ pmu_pd_gpu = 25,
+ pmu_pd_id_max,
+};
+
+enum pmu_vd_id {
+ pmu_vd_npu = 0,
+ pmu_vd_ddr = 1,
+ pmu_vd_cci = 2,
+ pmu_vd_gpu = 3,
+};
+
+enum pmu_bus_state {
+ pmu_bus_active = 0,
+ pmu_bus_idle = 1,
+};
+
+enum pmu_pd_state {
+ pmu_pd_on = 0,
+ pmu_pd_off = 1
+};
+
+enum pmu_scu_fsm_st {
+ pmu_scu_fsm_normal = 0,
+ pmu_scu_fsm_cpu_pwr_down = 1,
+ pmu_scu_fsm_l2_flush = 2,
+ pmu_scu_fsm_l2_idle = 3,
+ pmu_scu_fsm_clust_idle = 4,
+ pmu_scu_fsm_scu_pwr_down = 5,
+ pmu_scu_fsm_sleep = 6,
+ pmu_scu_fsm_wkup = 7,
+ pmu_scu_fsm_scu_pwr_up = 8,
+ pmu_scu_fsm_clust_resume = 9,
+ pmu_scu_fsm_cpu_pwr_up = 10,
+};
+
+#define MAX_MEM_OS_REG_NUM 32
+#define MEM_OS_REG_BASE \
+ (PMUSRAM_BASE + PMUSRAM_RSIZE - MAX_MEM_OS_REG_NUM * 4)
+
+#define PSRAM_SP_TOP MEM_OS_REG_BASE
+
+#define PD_CTR_LOOP 5000
+#define WFEI_CHECK_LOOP 5000
+#define BUS_IDLE_LOOP 1000
+#define NONBOOT_CPUS_OFF_LOOP 500000
+
+#define REBOOT_FLAG 0x5242C300
+#define BOOT_BROM_DOWNLOAD 0xef08a53c
+
+#define BOOTROM_SUSPEND_MAGIC 0x02468ace
+#define BOOTROM_RESUME_MAGIC 0x13579bdf
+#define WARM_BOOT_MAGIC 0x76543210
+#define VALID_GLB_RST_MSK 0xbfff
+
+#define DEFAULT_BOOT_CPU 0
+
+/*******************************************************
+ * sleep mode define
+ *******************************************************/
+#define SLP_ARMPD BIT(0)
+#define SLP_ARMOFF BIT(1)
+#define SLP_ARMOFF_DDRPD BIT(2)
+#define SLP_ARMOFF_LOGOFF BIT(3)
+#define SLP_ARMOFF_PMUOFF BIT(4)
+#define SLP_FROM_UBOOT BIT(5)
+
+/* all plls except ddr's pll*/
+#define SLP_PMU_HW_PLLS_PD BIT(8)
+#define SLP_PMU_PMUALIVE_32K BIT(9)
+#define SLP_PMU_DIS_OSC BIT(10)
+
+#define SLP_CLK_GT BIT(16)
+#define SLP_PMIC_LP BIT(17)
+
+#define SLP_32K_EXT BIT(24)
+#define SLP_TIME_OUT_WKUP BIT(25)
+#define SLP_PMU_DBG BIT(26)
+#define SLP_ARCH_TIMER_RESET BIT(27)
+
+#define PM_INVALID_GPIO 0xffff
+#define MAX_GPIO_POWER_CFG_CNT 10
+#define MAX_VIRTUAL_PWROFF_IRQ_CNT 20
+
+enum {
+ RK_PM_VIRT_PWROFF_EN = 0,
+ RK_PM_VIRT_PWROFF_IRQ_CFG = 1,
+ RK_PM_VIRT_PWROFF_MAX,
+};
+
+/* sleep pin */
+#define RKPM_SLEEP_PIN0_EN BIT(0) /* GPIO0_A3 */
+#define RKPM_SLEEP_PIN1_EN BIT(1) /* GPIO0_A4 */
+#define RKPM_SLEEP_PIN2_EN BIT(2) /* GPIO0_A5 */
+
+#define RKPM_SLEEP_PIN0_ACT_LOW BIT(0) /* GPIO0_A3 */
+#define RKPM_SLEEP_PIN1_ACT_LOW BIT(1) /* GPIO0_A4 */
+#define RKPM_SLEEP_PIN2_ACT_LOW BIT(2) /* GPIO0_A5 */
+
+#define pmu_bus_idle_st(id) \
+ (!!(mmio_read_32(PMU_BASE + PMU2_BUS_IDLE_ST) & BIT(id)))
+
+#define pmu_bus_idle_ack(id) \
+ (!!(mmio_read_32(PMU_BASE + PMU2_BUS_IDLE_ACK) & BIT(id)))
+
+static inline uint32_t read_mem_os_reg(uint32_t id)
+{
+ assert((id) < MAX_MEM_OS_REG_NUM);
+
+ return mmio_read_32(MEM_OS_REG_BASE + 4 * (id));
+}
+
+static inline void write_mem_os_reg(uint32_t id, uint32_t val)
+{
+ assert((id) < MAX_MEM_OS_REG_NUM);
+
+ mmio_write_32(MEM_OS_REG_BASE + 4 * (id), val);
+}
+#endif /* __PMU_H__ */
diff --git a/plat/rockchip/rk3576/drivers/secure/firewall.c b/plat/rockchip/rk3576/drivers/secure/firewall.c
new file mode 100644
index 0000000..5da9ea8
--- /dev/null
+++ b/plat/rockchip/rk3576/drivers/secure/firewall.c
@@ -0,0 +1,693 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#include <firewall.h>
+#include <soc.h>
+
+enum {
+ FW_NS_A_S_A = 0x0,
+ FW_NS_A_S_NA = 0x1,
+ FW_NS_NA_S_A = 0x2,
+ FW_NS_NA_S_NA = 0x3,
+};
+
+/* group type */
+enum {
+ FW_GRP_TYPE_INV = 0,
+ FW_GRP_TYPE_DDR_RGN = 1,
+ FW_GRP_TYPE_SYSMEM_RGN = 2,
+ FW_GRP_TYPE_CBUF_RGN = 3,
+ FW_GRP_TYPE_SLV = 4,
+ FW_GRP_TYPE_DM = 5,
+};
+
+enum {
+ FW_SLV_TYPE_INV = 0,
+ FW_MST_TYPE_INV = 0,
+ FW_SLV_TYPE_BUS = 1,
+ FW_SLV_TYPE_TOP = 2,
+ FW_SLV_TYPE_CENTER = 3,
+ FW_SLV_TYPE_CCI = 4,
+ FW_SLV_TYPE_PHP = 5,
+ FW_SLV_TYPE_GPU = 6,
+ FW_SLV_TYPE_NPU = 7,
+ FW_SLV_TYPE_PMU = 8,
+ FW_MST_TYPE_SYS = 9,
+ FW_MST_TYPE_PMU = 10,
+};
+
+#define FW_ID(type, id) \
+ ((((type) & 0xff) << 16) | ((id) & 0xffff))
+
+#define FW_MST_ID(type, id) FW_ID(type, id)
+#define FW_SLV_ID(type, id) FW_ID(type, id)
+#define FW_GRP_ID(type, id) FW_ID(type, id)
+
+/* group id */
+#define FW_GRP_ID_DDR_RGN(id) FW_GRP_ID(FW_GRP_TYPE_DDR_RGN, id)
+#define FW_GRP_ID_SYSMEM_RGN(id) FW_GRP_ID(FW_GRP_TYPE_SYSMEM_RGN, id)
+#define FW_GRP_ID_CBUF(id) FW_GRP_ID(FW_GRP_TYPE_CBUF_RGN, id)
+#define FW_GRP_ID_SLV(id) FW_GRP_ID(FW_GRP_TYPE_SLV, id)
+#define FW_GRP_ID_DM(id) FW_GRP_ID(FW_GRP_TYPE_DM, id)
+
+#define FW_GRP_ID_SLV_CNT 8
+#define FW_GRP_ID_DM_CNT 8
+
+#define FW_GET_ID(id) ((id) & 0xffff)
+#define FW_GET_TYPE(id) (((id) >> 16) & 0xff)
+
+#define FW_INVLID_MST_ID FW_MST_ID(FW_MST_TYPE_INV, 0)
+#define FW_INVLID_SLV_ID FW_SLV_ID(FW_SLV_TYPE_INV, 0)
+
+typedef struct {
+ uint32_t domain[FW_SGRF_MST_DOMAIN_CON_CNT];
+ uint32_t pmu_domain;
+ uint32_t bus_slv_grp[FW_SGRF_BUS_SLV_CON_CNT];
+ uint32_t top_slv_grp[FW_SGRF_TOP_SLV_CON_CNT];
+ uint32_t center_slv_grp[FW_SGRF_CENTER_SLV_CON_CNT];
+ uint32_t cci_slv_grp[FW_SGRF_CCI_SLV_CON_CNT];
+ uint32_t php_slv_grp[FW_SGRF_PHP_SLV_CON_CNT];
+ uint32_t gpu_slv_grp;
+ uint32_t npu_slv_grp[FW_SGRF_NPU_SLV_CON_CNT];
+ uint32_t pmu_slv_grp[FW_PMU_SGRF_SLV_CON_CNT];
+ uint32_t ddr_rgn[FW_SGRF_DDR_RGN_CNT];
+ uint32_t ddr_size;
+ uint32_t ddr_con;
+ uint32_t sysmem_rgn[FW_SGRF_SYSMEM_RGN_CNT];
+ uint32_t sysmem_con;
+ uint32_t cbuf_rgn[FW_SGRF_CBUF_RGN_CNT];
+ uint32_t cbuf_con;
+ uint32_t ddr_lookup[FW_SGRF_DDR_LOOKUP_CNT];
+ uint32_t sysmem_lookup[FW_SGRF_SYSMEM_LOOKUP_CNT];
+ uint32_t cbuf_lookup[FW_SGRF_CBUF_LOOKUP_CNT];
+ uint32_t slv_lookup[FW_SGRF_SLV_LOOKUP_CNT];
+ uint32_t pmu_slv_lookup[FW_PMU_SGRF_SLV_LOOKUP_CNT];
+} fw_config_t;
+
+static fw_config_t fw_config_buf;
+
+/****************************************************************************
+ * Access rights between domains and groups are as follows:
+ *
+ * 00: NS access, S access
+ * 01: NS access, S not access
+ * 10: NS not access, S access
+ * 11: NS not access, S not access
+ * |---------------------------------------------------------|
+ * | | d0 | d1 | d2 | d3 | d4 | d5 | d6 | d7 |
+ * |---------------------------------------------------------|
+ * | slave g0 | 00 | 00 | 11 | 11 | 11 | 11 | 11 | 00 |
+ * |---------------------------------------------------------|
+ * | slave g1 | 10 | 11 | 11 | 11 | 11 | 11 | 11 | 10 |
+ * |---------------------------------------------------------|
+ * | slave g2~7 | 11 | 11 | 11 | 11 | 11 | 11 | 11 | 11 |
+ * |---------------------------------------------------------|
+ * | ddr region 0~15 | 10 | 11 | 11 | 11 | 11 | 11 | 11 | 10 |
+ * |---------------------------------------------------------|
+ * | sram region 0~3 | 10 | 11 | 11 | 11 | 11 | 11 | 11 | 10 |
+ * |---------------------------------------------------------|
+ * | cbuf region 0~7 | 10 | 11 | 11 | 11 | 11 | 11 | 11 | 10 |
+ * |---------------------------------------------------------|
+ *
+ * PS:
+ * Domain 0/1/7 NS/S can access group 0.
+ * Domain 0/1/7 NS and Domain1 NS/S can't access group 1, domain 0/7 S can access.
+ * Other domains NS/S can't access all groups.
+ *
+ * Domain 0/7 NS can't access ddr/sram/cbuf region and Domain 0/7 S can access.
+ * Other domains NS/S can't access ddr/sram/cbuf region.
+ *
+ ******************************************************************************/
+
+/* Masters in dm1 */
+static const int dm1_mst[] = {
+ FW_MST_ID(FW_MST_TYPE_SYS, 1), /* keylad_apbm */
+ FW_MST_ID(FW_MST_TYPE_SYS, 2), /* dft2apbm */
+ FW_MST_ID(FW_MST_TYPE_SYS, 11), /* dma2ddr */
+ FW_MST_ID(FW_MST_TYPE_SYS, 12), /* dmac0 */
+ FW_MST_ID(FW_MST_TYPE_SYS, 13), /* dmac1 */
+ FW_MST_ID(FW_MST_TYPE_SYS, 14), /* dmac2 */
+ FW_MST_ID(FW_MST_TYPE_SYS, 19), /* gpu */
+ FW_MST_ID(FW_MST_TYPE_SYS, 31), /* vop_m0 */
+ FW_MST_ID(FW_MST_TYPE_SYS, 32), /* vop_m1 */
+ FW_MST_ID(FW_MST_TYPE_SYS, 36), /* bus_mcu */
+ FW_MST_ID(FW_MST_TYPE_SYS, 38), /* npu_mcu */
+ FW_MST_ID(FW_MST_TYPE_SYS, 56), /* dap_lite */
+
+ FW_INVLID_MST_ID
+};
+
+/* Slaves in group1 */
+static const int sec_slv[] = {
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 28), /* crypto_s */
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 29), /* keyladder_s */
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 30), /* rkrng_s */
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 33), /* jtag_lock */
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 34), /* otp_s */
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 35), /* otpmsk */
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 37), /* scru_s */
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 38), /* sys_sgrf */
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 39), /* bootrom */
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 41), /* wdts */
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 44), /* sevice_secure */
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 61), /* timers0_ch0~5 */
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 62),
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 63),
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 64),
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 65),
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 66),
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 67), /* timers1_ch0~5 */
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 68),
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 69),
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 70),
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 71),
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 72),
+ FW_SLV_ID(FW_SLV_TYPE_TOP, 73), /* sys_fw */
+
+ FW_SLV_ID(FW_SLV_TYPE_CENTER, 3), /* ddr grf */
+ FW_SLV_ID(FW_SLV_TYPE_CENTER, 4), /* ddr ctl0 */
+ FW_SLV_ID(FW_SLV_TYPE_CENTER, 5), /* ddr ctl1 */
+ FW_SLV_ID(FW_SLV_TYPE_CENTER, 6), /* ddr phy0 */
+ FW_SLV_ID(FW_SLV_TYPE_CENTER, 7), /* ddr0 cru */
+ FW_SLV_ID(FW_SLV_TYPE_CENTER, 8), /* ddr phy1 */
+ FW_SLV_ID(FW_SLV_TYPE_CENTER, 9), /* ddr1 cru */
+ FW_SLV_ID(FW_SLV_TYPE_CENTER, 15), /* ddr wdt */
+ FW_SLV_ID(FW_SLV_TYPE_CENTER, 19), /* service ddr */
+ FW_SLV_ID(FW_SLV_TYPE_CENTER, 58), /* ddr timer ch0 */
+ FW_SLV_ID(FW_SLV_TYPE_CENTER, 59), /* ddr timer ch1 */
+
+ FW_SLV_ID(FW_SLV_TYPE_PMU, 1), /* pmu mem */
+ FW_SLV_ID(FW_SLV_TYPE_PMU, 15), /* pmu1_scru */
+ FW_SLV_ID(FW_SLV_TYPE_PMU, 30), /* osc chk */
+ FW_SLV_ID(FW_SLV_TYPE_PMU, 31), /* pmu0_sgrf */
+ FW_SLV_ID(FW_SLV_TYPE_PMU, 32), /* pmu1_sgrf */
+ FW_SLV_ID(FW_SLV_TYPE_PMU, 34), /* scramble key */
+ FW_SLV_ID(FW_SLV_TYPE_PMU, 36), /* pmu remap */
+ FW_SLV_ID(FW_SLV_TYPE_PMU, 43), /* pmu fw */
+
+ FW_INVLID_SLV_ID
+};
+
+static void fw_buf_sys_mst_dm_cfg(int mst_id, uint32_t dm_id)
+{
+ int sft = (mst_id & 0x7) << 2;
+
+ fw_config_buf.domain[mst_id >> 3] &= ~(0xf << sft);
+ fw_config_buf.domain[mst_id >> 3] |= (dm_id & 0xf) << sft;
+}
+
+static void fw_buf_pmu_mst_dm_cfg(int mst_id, uint32_t dm_id)
+{
+ int sft = (mst_id & 0x7) << 2;
+
+ fw_config_buf.pmu_domain &= ~(0xf << sft);
+ fw_config_buf.pmu_domain |= (dm_id & 0xf) << sft;
+}
+
+void fw_buf_mst_dm_cfg(int mst_id, uint32_t dm_id)
+{
+ int type = FW_GET_TYPE(mst_id);
+
+ mst_id = FW_GET_ID(mst_id);
+
+ switch (type) {
+ case FW_MST_TYPE_SYS:
+ fw_buf_sys_mst_dm_cfg(mst_id, dm_id);
+ break;
+ case FW_MST_TYPE_PMU:
+ fw_buf_pmu_mst_dm_cfg(mst_id, dm_id);
+ break;
+
+ default:
+ ERROR("%s: unknown FW_DOMAIN_TYPE (0x%x)\n", __func__, type);
+ break;
+ }
+}
+
+static void fw_buf_ddr_lookup_cfg(int rgn_id, int dm_id, uint32_t priv)
+{
+ int sft = (dm_id << 1) + (rgn_id & 0x1) * 16;
+
+ fw_config_buf.ddr_lookup[rgn_id >> 1] &= ~(0x3 << sft);
+ fw_config_buf.ddr_lookup[rgn_id >> 1] |= (priv & 0x3) << sft;
+}
+
+static void fw_buf_sysmem_lookup_cfg(int rgn_id, int dm_id, uint32_t priv)
+{
+ int sft = (dm_id << 1) + (rgn_id & 0x1) * 16;
+
+ fw_config_buf.sysmem_lookup[rgn_id >> 1] &= ~(0x3 << sft);
+ fw_config_buf.sysmem_lookup[rgn_id >> 1] |= (priv & 0x3) << sft;
+}
+
+static void fw_buf_cbuf_lookup_cfg(int rgn_id, int dm_id, uint32_t priv)
+{
+ int sft = (dm_id << 1) + (rgn_id & 0x1) * 16;
+
+ fw_config_buf.cbuf_lookup[rgn_id >> 1] &= ~(0x3 << sft);
+ fw_config_buf.cbuf_lookup[rgn_id >> 1] |= (priv & 0x3) << sft;
+}
+
+static void fw_buf_slv_lookup_cfg(int grp_id, int dm_id, uint32_t priv)
+{
+ int sft = (dm_id << 1) + (grp_id & 0x1) * 16;
+
+ fw_config_buf.slv_lookup[grp_id >> 1] &= ~(0x3 << sft);
+ fw_config_buf.slv_lookup[grp_id >> 1] |= (priv & 0x3) << sft;
+}
+
+static void fw_buf_pmu_slv_lookup_cfg(int grp_id, int dm_id, uint32_t priv)
+{
+ int sft = (dm_id << 1) + (grp_id & 0x1) * 16;
+
+ fw_config_buf.pmu_slv_lookup[grp_id >> 1] &= ~(0x3 << sft);
+ fw_config_buf.pmu_slv_lookup[grp_id >> 1] |= (priv & 0x3) << sft;
+}
+
+void fw_buf_grp_lookup_cfg(int grp_id, int dm_id, uint32_t priv)
+{
+ uint32_t type = FW_GET_TYPE(grp_id);
+
+ grp_id = FW_GET_ID(grp_id);
+
+ switch (type) {
+ case FW_GRP_TYPE_DDR_RGN:
+ fw_buf_ddr_lookup_cfg(grp_id, dm_id, priv);
+ break;
+ case FW_GRP_TYPE_SYSMEM_RGN:
+ fw_buf_sysmem_lookup_cfg(grp_id, dm_id, priv);
+ break;
+ case FW_GRP_TYPE_CBUF_RGN:
+ fw_buf_cbuf_lookup_cfg(grp_id, dm_id, priv);
+ break;
+ case FW_GRP_TYPE_SLV:
+ fw_buf_slv_lookup_cfg(grp_id, dm_id, priv);
+ fw_buf_pmu_slv_lookup_cfg(grp_id, dm_id, priv);
+ break;
+
+ default:
+ ERROR("%s: unknown FW_LOOKUP_TYPE (0x%x)\n", __func__, type);
+ break;
+ }
+}
+
+static void fw_buf_bus_slv_grp_cfg(int slv_id, int grp_id)
+{
+ int sft = slv_id % 5 << 2;
+
+ fw_config_buf.bus_slv_grp[slv_id / 5] &= ~(0xf << sft);
+ fw_config_buf.bus_slv_grp[slv_id / 5] |= (grp_id & 0xf) << sft;
+}
+
+static void fw_buf_top_slv_grp_cfg(int slv_id, int grp_id)
+{
+ int sft = slv_id % 5 << 2;
+
+ fw_config_buf.top_slv_grp[slv_id / 5] &= ~(0xf << sft);
+ fw_config_buf.top_slv_grp[slv_id / 5] |= (grp_id & 0xf) << sft;
+}
+
+static void fw_buf_center_slv_grp_cfg(int slv_id, int grp_id)
+{
+ int sft = slv_id % 5 << 2;
+
+ fw_config_buf.center_slv_grp[slv_id / 5] &= ~(0xf << sft);
+ fw_config_buf.center_slv_grp[slv_id / 5] |= (grp_id & 0xf) << sft;
+}
+
+static void fw_buf_cci_slv_grp_cfg(int slv_id, int grp_id)
+{
+ int sft = slv_id % 5 << 2;
+
+ fw_config_buf.cci_slv_grp[slv_id / 5] &= ~(0xf << sft);
+ fw_config_buf.cci_slv_grp[slv_id / 5] |= (grp_id & 0xf) << sft;
+}
+
+static void fw_buf_php_slv_grp_cfg(int slv_id, int grp_id)
+{
+ int sft = slv_id % 5 << 2;
+
+ fw_config_buf.php_slv_grp[slv_id / 5] &= ~(0xf << sft);
+ fw_config_buf.php_slv_grp[slv_id / 5] |= (grp_id & 0xf) << sft;
+}
+
+static void fw_buf_gpu_slv_grp_cfg(int slv_id, int grp_id)
+{
+ int sft = slv_id % 5 << 2;
+
+ fw_config_buf.gpu_slv_grp &= ~(0xf << sft);
+ fw_config_buf.gpu_slv_grp |= (grp_id & 0xf) << sft;
+}
+
+static void fw_buf_npu_slv_grp_cfg(int slv_id, int grp_id)
+{
+ int sft = slv_id % 5 << 2;
+
+ fw_config_buf.npu_slv_grp[slv_id / 5] &= ~(0xf << sft);
+ fw_config_buf.npu_slv_grp[slv_id / 5] |= (grp_id & 0xf) << sft;
+}
+
+static void fw_buf_pmu_slv_grp_cfg(int slv_id, int grp_id)
+{
+ int sft = slv_id % 5 << 2;
+
+ fw_config_buf.pmu_slv_grp[slv_id / 5] &= ~(0xf << sft);
+ fw_config_buf.pmu_slv_grp[slv_id / 5] |= (grp_id & 0xf) << sft;
+}
+
+void fw_buf_slv_grp_cfg(int slv_id, int grp_id)
+{
+ int type = FW_GET_TYPE(slv_id);
+
+ slv_id = FW_GET_ID(slv_id);
+ grp_id = FW_GET_ID(grp_id);
+
+ switch (type) {
+ case FW_SLV_TYPE_BUS:
+ fw_buf_bus_slv_grp_cfg(slv_id, grp_id);
+ break;
+ case FW_SLV_TYPE_TOP:
+ fw_buf_top_slv_grp_cfg(slv_id, grp_id);
+ break;
+ case FW_SLV_TYPE_CENTER:
+ fw_buf_center_slv_grp_cfg(slv_id, grp_id);
+ break;
+ case FW_SLV_TYPE_CCI:
+ fw_buf_cci_slv_grp_cfg(slv_id, grp_id);
+ break;
+ case FW_SLV_TYPE_PHP:
+ fw_buf_php_slv_grp_cfg(slv_id, grp_id);
+ break;
+ case FW_SLV_TYPE_GPU:
+ fw_buf_gpu_slv_grp_cfg(slv_id, grp_id);
+ break;
+ case FW_SLV_TYPE_NPU:
+ fw_buf_npu_slv_grp_cfg(slv_id, grp_id);
+ break;
+ case FW_SLV_TYPE_PMU:
+ fw_buf_pmu_slv_grp_cfg(slv_id, grp_id);
+ break;
+
+ default:
+ ERROR("%s: unknown FW_SLV_TYPE (0x%x)\n", __func__, type);
+ break;
+ }
+}
+
+void fw_buf_add_msts(const int *mst_ids, int dm_id)
+{
+ int i;
+
+ for (i = 0; FW_GET_TYPE(mst_ids[i]) != FW_INVLID_SLV_ID; i++)
+ fw_buf_mst_dm_cfg(mst_ids[i], dm_id);
+}
+
+void fw_buf_add_slvs(const int *slv_ids, int grp_id)
+{
+ int i;
+
+ for (i = 0; FW_GET_TYPE(slv_ids[i]) != FW_INVLID_SLV_ID; i++)
+ fw_buf_slv_grp_cfg(slv_ids[i], grp_id);
+}
+
+/* unit: Mb */
+void fw_buf_ddr_size_cfg(uint64_t base_mb, uint64_t top_mb, int id)
+{
+ fw_config_buf.ddr_size = RG_MAP_SECURE(top_mb, base_mb);
+ fw_config_buf.ddr_con |= BIT(16);
+}
+
+/* unit: Mb */
+void fw_buf_ddr_rgn_cfg(uint64_t base_mb, uint64_t top_mb, int rgn_id)
+{
+ fw_config_buf.ddr_rgn[rgn_id] = RG_MAP_SECURE(top_mb, base_mb);
+ fw_config_buf.ddr_con |= BIT(rgn_id);
+}
+
+/* Unit: kb */
+void fw_buf_sysmem_rgn_cfg(uint64_t base_kb, uint64_t top_kb, int rgn_id)
+{
+ fw_config_buf.sysmem_rgn[rgn_id] = RG_MAP_SRAM_SECURE(top_kb, base_kb);
+ fw_config_buf.sysmem_con |= BIT(rgn_id);
+}
+
+static void fw_domain_init(void)
+{
+ int i;
+
+ /* select to domain0 by default */
+ for (i = 0; i < FW_SGRF_MST_DOMAIN_CON_CNT; i++)
+ fw_config_buf.domain[i] = 0x0;
+
+ /* select to domain0 by default */
+ fw_config_buf.pmu_domain = 0x0;
+}
+
+static void fw_slv_grp_init(void)
+{
+ int i;
+
+ /* select to group0 by default */
+ for (i = 0; i < FW_SGRF_BUS_SLV_CON_CNT; i++)
+ fw_config_buf.bus_slv_grp[i] = 0x0;
+
+ for (i = 0; i < FW_SGRF_TOP_SLV_CON_CNT; i++)
+ fw_config_buf.top_slv_grp[i] = 0x0;
+
+ for (i = 0; i < FW_SGRF_CENTER_SLV_CON_CNT; i++)
+ fw_config_buf.center_slv_grp[i] = 0x0;
+
+ for (i = 0; i < FW_SGRF_CCI_SLV_CON_CNT; i++)
+ fw_config_buf.cci_slv_grp[i] = 0x0;
+
+ for (i = 0; i < FW_SGRF_PHP_SLV_CON_CNT; i++)
+ fw_config_buf.php_slv_grp[i] = 0x0;
+
+ fw_config_buf.gpu_slv_grp = 0x0;
+
+ for (i = 0; i < FW_SGRF_NPU_SLV_CON_CNT; i++)
+ fw_config_buf.npu_slv_grp[i] = 0x0;
+}
+
+static void fw_region_init(void)
+{
+ /* Use FW_DDR_RGN0_REG to config 1024~1025M space to secure */
+ fw_buf_ddr_rgn_cfg(1024, 1025, 0);
+
+ /* Use FW_SYSMEM_RGN0_REG to config 0~32k space to secure */
+ fw_buf_sysmem_rgn_cfg(0, 32, 0);
+}
+
+static void fw_lookup_init(void)
+{
+ int i;
+
+ /*
+ * Domain 0/7 NS can't access ddr/sram/cbuf region and Domain 0/7 S can access.
+ * Other domains NS/S can't access ddr/sram/cbuf region.
+ */
+ for (i = 0; i < FW_SGRF_DDR_LOOKUP_CNT; i++)
+ fw_config_buf.ddr_lookup[i] = 0xbffebffe;
+
+ for (i = 0; i < FW_SGRF_SYSMEM_LOOKUP_CNT; i++)
+ fw_config_buf.sysmem_lookup[i] = 0xbffebffe;
+
+ for (i = 0; i < FW_SGRF_CBUF_LOOKUP_CNT; i++)
+ fw_config_buf.cbuf_lookup[i] = 0xbffebffe;
+
+ /*
+ * Domain 0/1/7 NS/S can access group 0.
+ * Domain 0/1/7 NS and Domain1 NS/S can't access group 1, domain 0/7 S can access.
+ * Other domains NS/S can't access all groups.
+ */
+ fw_config_buf.slv_lookup[0] = 0xbffe3ff0;
+ fw_config_buf.slv_lookup[1] = 0xffffffff;
+ fw_config_buf.slv_lookup[2] = 0xffffffff;
+ fw_config_buf.slv_lookup[3] = 0xffffffff;
+
+ /*
+ * Domain 0/1/7 NS/S can access group 0.
+ * Domain 0/1/7 NS and Domain1 NS/S can't access group 1, domain 0/7 S can access.
+ * Other domains NS/S can't access all groups.
+ */
+ fw_config_buf.pmu_slv_lookup[0] = 0xbffe3ff0;
+ fw_config_buf.pmu_slv_lookup[1] = 0xffffffff;
+ fw_config_buf.pmu_slv_lookup[2] = 0xffffffff;
+ fw_config_buf.pmu_slv_lookup[3] = 0xffffffff;
+}
+
+static void fw_config_buf_flush(void)
+{
+ int i;
+
+ /* domain */
+ for (i = 0; i < FW_SGRF_MST_DOMAIN_CON_CNT; i++)
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_MST_DOMAIN_CON(i),
+ fw_config_buf.domain[i]);
+
+ mmio_write_32(PMU1SGRF_FW_BASE + FW_PMU_SGRF_DOMAIN_CON,
+ fw_config_buf.pmu_domain);
+
+ /* slave group */
+ for (i = 0; i < FW_SGRF_BUS_SLV_CON_CNT; i++)
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_BUS_SLV_CON(i),
+ fw_config_buf.bus_slv_grp[i]);
+
+ for (i = 0; i < FW_SGRF_TOP_SLV_CON_CNT; i++)
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_TOP_SLV_CON(i),
+ fw_config_buf.top_slv_grp[i]);
+
+ for (i = 0; i < FW_SGRF_CENTER_SLV_CON_CNT; i++)
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_CENTER_SLV_CON(i),
+ fw_config_buf.center_slv_grp[i]);
+
+ for (i = 0; i < FW_SGRF_CCI_SLV_CON_CNT; i++)
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_CCI_SLV_CON(i),
+ fw_config_buf.cci_slv_grp[i]);
+
+ for (i = 0; i < FW_SGRF_PHP_SLV_CON_CNT; i++)
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_PHP_SLV_CON(i),
+ fw_config_buf.php_slv_grp[i]);
+
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_GPU_SLV_CON,
+ fw_config_buf.gpu_slv_grp);
+
+ for (i = 0; i < FW_SGRF_NPU_SLV_CON_CNT; i++)
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_NPU_SLV_CON(i),
+ fw_config_buf.npu_slv_grp[i]);
+
+ for (i = 0; i < FW_PMU_SGRF_SLV_CON_CNT; i++)
+ mmio_write_32(PMU1SGRF_FW_BASE + FW_PMU_SGRF_SLV_CON(i),
+ fw_config_buf.pmu_slv_grp[i]);
+
+ /* region */
+ for (i = 0; i < FW_SGRF_DDR_RGN_CNT; i++)
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_DDR_RGN(i),
+ fw_config_buf.ddr_rgn[i]);
+
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_DDR_SIZE, fw_config_buf.ddr_size);
+
+ for (i = 0; i < FW_SGRF_SYSMEM_RGN_CNT; i++)
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_SYSMEM_RGN(i),
+ fw_config_buf.sysmem_rgn[i]);
+
+ for (i = 0; i < FW_SGRF_CBUF_RGN_CNT; i++)
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_CBUF_RGN(i),
+ fw_config_buf.cbuf_rgn[i]);
+
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_DDR_CON, fw_config_buf.ddr_con);
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_SYSMEM_CON, fw_config_buf.sysmem_con);
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_CBUF_CON, fw_config_buf.cbuf_con);
+
+ dsb();
+ isb();
+
+ /* lookup */
+ for (i = 0; i < FW_SGRF_DDR_LOOKUP_CNT; i++)
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_DDR_LOOKUP(i),
+ fw_config_buf.ddr_lookup[i]);
+
+ for (i = 0; i < FW_SGRF_SYSMEM_LOOKUP_CNT; i++)
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_SYSMEM_LOOKUP(i),
+ fw_config_buf.sysmem_lookup[i]);
+
+ for (i = 0; i < FW_SGRF_CBUF_LOOKUP_CNT; i++)
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_CBUF_LOOKUP(i),
+ fw_config_buf.cbuf_lookup[i]);
+
+ for (i = 0; i < FW_SGRF_SLV_LOOKUP_CNT; i++)
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_SLV_LOOKUP(i),
+ fw_config_buf.slv_lookup[i]);
+
+ for (i = 0; i < FW_PMU_SGRF_SLV_LOOKUP_CNT; i++)
+ mmio_write_32(PMU1SGRF_FW_BASE + FW_PMU_SGRF_SLV_LOOKUP(i),
+ fw_config_buf.pmu_slv_lookup[i]);
+
+ dsb();
+ isb();
+}
+
+static __pmusramfunc void pmusram_udelay(uint32_t us)
+{
+ uint64_t orig;
+ uint64_t to_wait;
+
+ orig = read_cntpct_el0();
+ to_wait = read_cntfrq_el0() * us / 1000000;
+
+ while (read_cntpct_el0() - orig <= to_wait)
+ ;
+}
+
+__pmusramfunc void pmusram_fw_update_msk(uint32_t msk)
+{
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_KEYUPD_CON0,
+ BITS_WITH_WMASK(0, 0x3ff, 0));
+ dsb();
+
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_KEYUPD_CON0,
+ BITS_WITH_WMASK(msk, msk, 0));
+ dsb();
+ isb();
+ pmusram_udelay(20);
+ dsb();
+ isb();
+}
+
+__pmusramfunc void pmusram_all_fw_bypass(void)
+{
+ int i;
+
+ /* disable regions */
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_DDR_CON, 0);
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_SYSMEM_CON, 0);
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_CBUF_CON, 0);
+
+ for (i = 0; i < FW_SGRF_DDR_LOOKUP_CNT; i++)
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_DDR_LOOKUP(i), 0x0);
+
+ for (i = 0; i < FW_SGRF_SYSMEM_LOOKUP_CNT; i++)
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_SYSMEM_LOOKUP(i), 0x0);
+
+ for (i = 0; i < FW_SGRF_CBUF_LOOKUP_CNT; i++)
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_CBUF_LOOKUP(i), 0x0);
+
+ for (i = 0; i < FW_SGRF_SLV_LOOKUP_CNT; i++)
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_SLV_LOOKUP(i), 0x0);
+
+ for (i = 0; i < FW_PMU_SGRF_SLV_LOOKUP_CNT; i++)
+ mmio_write_32(PMU1SGRF_FW_BASE + FW_PMU_SGRF_SLV_LOOKUP(i), 0x0);
+
+ dsb();
+
+ pmusram_fw_update_msk(0x3ff);
+}
+
+void fw_init(void)
+{
+ /* Enable all fw auto-update */
+ mmio_write_32(SYS_SGRF_FW_BASE + FW_SGRF_KEYUPD_CON1, 0x03ff03ff);
+
+ pmusram_all_fw_bypass();
+
+ fw_domain_init();
+ fw_slv_grp_init();
+ fw_region_init();
+
+ fw_buf_add_slvs(sec_slv, 1);
+ fw_buf_add_msts(dm1_mst, 1);
+
+ fw_lookup_init();
+
+ fw_config_buf_flush();
+ pmusram_fw_update_msk(0x3ff);
+}
diff --git a/plat/rockchip/rk3576/drivers/secure/firewall.h b/plat/rockchip/rk3576/drivers/secure/firewall.h
new file mode 100644
index 0000000..7b13071
--- /dev/null
+++ b/plat/rockchip/rk3576/drivers/secure/firewall.h
@@ -0,0 +1,499 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#ifndef __FIREWALL_H__
+#define __FIREWALL_H__
+
+#include <plat_private.h>
+
+/* FW SGRF */
+#define FW_SGRF_MST_DOMAIN_CON(i) ((i) * 4)
+#define FW_SGRF_MST_DOMAIN_CON_CNT 8
+#define FW_SGRF_DDR_RGN(i) (0x0100 + (i) * 4)
+#define FW_SGRF_DDR_RGN_CNT 16
+#define FW_SGRF_DDR_LOOKUP(i) (0x0140 + (i) * 0x4)
+#define FW_SGRF_DDR_LOOKUP_CNT 8
+#define FW_SGRF_DDR_SIZE 0x0160
+#define FW_SGRF_DDR_CON 0x0168
+#define FW_SGRF_SYSMEM_RGN(i) (0x0200 + (i) * 4)
+#define FW_SGRF_SYSMEM_RGN_CNT 4
+#define FW_SGRF_SYSMEM_LOOKUP(i) (0x0210 + (i) * 4)
+#define FW_SGRF_SYSMEM_LOOKUP_CNT 2
+#define FW_SGRF_SYSMEM_CON 0x0218
+#define FW_SGRF_CBUF_RGN(i) (0x0300 + (i) * 4)
+#define FW_SGRF_CBUF_RGN_CNT 8
+#define FW_SGRF_CBUF_LOOKUP(i) (0x0320 + (i) * 4)
+#define FW_SGRF_CBUF_LOOKUP_CNT 4
+#define FW_SGRF_CBUF_CON 0x0330
+#define FW_SGRF_SLV_LOOKUP(i) (0x0400 + (i) * 4)
+#define FW_SGRF_SLV_LOOKUP_CNT 4
+#define FW_SGRF_BUS_SLV_CON(i) (0x0500 + (i) * 4)
+#define FW_SGRF_BUS_SLV_CON_CNT 25
+#define FW_SGRF_BUS_SLV_STAT 0x0580
+#define FW_SGRF_TOP_SLV_CON(i) (0x0600 + (i) * 4)
+#define FW_SGRF_TOP_SLV_CON_CNT 16
+#define FW_SGRF_TOP_SLV_STAT 0x0680
+#define FW_SGRF_CENTER_SLV_CON(i) (0x0700 + (i) * 4)
+#define FW_SGRF_CENTER_SLV_CON_CNT 13
+#define FW_SGRF_CCI_SLV_CON(i) (0x0800 + (i) * 4)
+#define FW_SGRF_CCI_SLV_CON_CNT 3
+#define FW_SGRF_PHP_SLV_CON(i) (0x0900 + (i) * 4)
+#define FW_SGRF_PHP_SLV_CON_CNT 4
+#define FW_SGRF_PHP_SLV_STAT 0x0940
+#define FW_SGRF_GPU_SLV_CON 0x0980
+#define FW_SGRF_NPU_SLV_CON(i) (0x09a0 + (i) * 4)
+#define FW_SGRF_NPU_SLV_CON_CNT 2
+#define FW_SGRF_STATCLR_CON0 0x0a00
+#define FW_SGRF_KEYUPD_CON0 0x0a80
+#define FW_SGRF_KEYUPD_CON1 0x0a84
+#define FW_SGRF_KEYUPD_STAT 0x0ab0
+
+/* FW PMUSGRF */
+#define FW_PMU_SGRF_SLV_CON(i) ((i) * 4)
+#define FW_PMU_SGRF_SLV_CON_CNT 9
+#define FW_PMU_SGRF_SLV_LOOKUP(i) (0x0080 + (i) * 0x4)
+#define FW_PMU_SGRF_SLV_LOOKUP_CNT 4
+#define FW_PMU_SGRF_DOMAIN_CON 0x00a0
+#define FW_PMU_SGRF_SLV_STAT 0x00c0
+
+/* master id */
+#define FW_MST_ID_USB0 FW_MST_ID(FW_MST_TYPE_SYS, 0)
+#define FW_MST_ID_KEYLAD_APB FW_MST_ID(FW_MST_TYPE_SYS, 1)
+#define FW_MST_ID_DFT2APB FW_MST_ID(FW_MST_TYPE_SYS, 2)
+#define FW_MST_ID_PCIE0 FW_MST_ID(FW_MST_TYPE_SYS, 3)
+#define FW_MST_ID_PCIE1 FW_MST_ID(FW_MST_TYPE_SYS, 4)
+#define FW_MST_ID_SATA0 FW_MST_ID(FW_MST_TYPE_SYS, 6)
+#define FW_MST_ID_SATA1 FW_MST_ID(FW_MST_TYPE_SYS, 7)
+#define FW_MST_ID_CRYPTO FW_MST_ID(FW_MST_TYPE_SYS, 8)
+#define FW_MST_ID_FLEXBUS FW_MST_ID(FW_MST_TYPE_SYS, 9)
+#define FW_MST_ID_DECOM FW_MST_ID(FW_MST_TYPE_SYS, 10)
+#define FW_MST_ID_DMA2DDR FW_MST_ID(FW_MST_TYPE_SYS, 11)
+#define FW_MST_ID_DMAC0 FW_MST_ID(FW_MST_TYPE_SYS, 12)
+#define FW_MST_ID_DMAC1 FW_MST_ID(FW_MST_TYPE_SYS, 13)
+#define FW_MST_ID_DMAC2 FW_MST_ID(FW_MST_TYPE_SYS, 14)
+#define FW_MST_ID_EBC FW_MST_ID(FW_MST_TYPE_SYS, 15)
+#define FW_MST_ID_EMMC FW_MST_ID(FW_MST_TYPE_SYS, 16)
+#define FW_MST_ID_GMAC0 FW_MST_ID(FW_MST_TYPE_SYS, 17)
+#define FW_MST_ID_GMAC1 FW_MST_ID(FW_MST_TYPE_SYS, 18)
+#define FW_MST_ID_GPU FW_MST_ID(FW_MST_TYPE_SYS, 19)
+#define FW_MST_ID_HDCP0 FW_MST_ID(FW_MST_TYPE_SYS, 20)
+#define FW_MST_ID_HDCP1 FW_MST_ID(FW_MST_TYPE_SYS, 21)
+#define FW_MST_ID_ISP FW_MST_ID(FW_MST_TYPE_SYS, 22)
+#define FW_MST_ID_RGA0 FW_MST_ID(FW_MST_TYPE_SYS, 23)
+#define FW_MST_ID_RGA1 FW_MST_ID(FW_MST_TYPE_SYS, 24)
+#define FW_MST_ID_JPEG FW_MST_ID(FW_MST_TYPE_SYS, 25)
+#define FW_MST_ID_RKVDEC FW_MST_ID(FW_MST_TYPE_SYS, 26)
+#define FW_MST_ID_VEPU0 FW_MST_ID(FW_MST_TYPE_SYS, 27)
+#define FW_MST_ID_UFSHC FW_MST_ID(FW_MST_TYPE_SYS, 28)
+#define FW_MST_ID_VDPP FW_MST_ID(FW_MST_TYPE_SYS, 29)
+#define FW_MST_ID_VICAP FW_MST_ID(FW_MST_TYPE_SYS, 30)
+#define FW_MST_ID_VOP_M0 FW_MST_ID(FW_MST_TYPE_SYS, 31)
+#define FW_MST_ID_VOP_M1 FW_MST_ID(FW_MST_TYPE_SYS, 32)
+#define FW_MST_ID_VPSS FW_MST_ID(FW_MST_TYPE_SYS, 33)
+#define FW_MST_ID_FSPI0 FW_MST_ID(FW_MST_TYPE_SYS, 34)
+#define FW_MST_ID_FSPI1 FW_MST_ID(FW_MST_TYPE_SYS, 35)
+#define FW_MST_ID_BUS_MCU FW_MST_ID(FW_MST_TYPE_SYS, 36)
+#define FW_MST_ID_DDR_MCU FW_MST_ID(FW_MST_TYPE_SYS, 37)
+#define FW_MST_ID_NPU_MCU FW_MST_ID(FW_MST_TYPE_SYS, 38)
+#define FW_MST_ID_CAN0 FW_MST_ID(FW_MST_TYPE_SYS, 39)
+#define FW_MST_ID_CAN1 FW_MST_ID(FW_MST_TYPE_SYS, 40)
+#define FW_MST_ID_SDIO FW_MST_ID(FW_MST_TYPE_SYS, 41)
+#define FW_MST_ID_SDMMC0 FW_MST_ID(FW_MST_TYPE_SYS, 42)
+#define FW_MST_ID_USB1 FW_MST_ID(FW_MST_TYPE_SYS, 43)
+#define FW_MST_ID_NPU_M0 FW_MST_ID(FW_MST_TYPE_SYS, 44)
+#define FW_MST_ID_NPU_M0RO FW_MST_ID(FW_MST_TYPE_SYS, 45)
+#define FW_MST_ID_NPU_M1 FW_MST_ID(FW_MST_TYPE_SYS, 46)
+#define FW_MST_ID_NPU_M1RO FW_MST_ID(FW_MST_TYPE_SYS, 47)
+#define FW_MST_ID_A53_0 FW_MST_ID(FW_MST_TYPE_SYS, 48)
+#define FW_MST_ID_A53_1 FW_MST_ID(FW_MST_TYPE_SYS, 49)
+#define FW_MST_ID_A53_2 FW_MST_ID(FW_MST_TYPE_SYS, 50)
+#define FW_MST_ID_A53_3 FW_MST_ID(FW_MST_TYPE_SYS, 51)
+#define FW_MST_ID_A72_0 FW_MST_ID(FW_MST_TYPE_SYS, 52)
+#define FW_MST_ID_A72_1 FW_MST_ID(FW_MST_TYPE_SYS, 53)
+#define FW_MST_ID_A72_2 FW_MST_ID(FW_MST_TYPE_SYS, 54)
+#define FW_MST_ID_A72_3 FW_MST_ID(FW_MST_TYPE_SYS, 55)
+#define FW_MST_ID_DAP_LITE FW_MST_ID(FW_MST_TYPE_SYS, 56)
+#define FW_MST_ID_VEPU1 FW_MST_ID(FW_MST_TYPE_SYS, 57)
+#define FW_MST_ID_SYS_CNT 64
+
+#define FW_MST_ID_PMU_MCU FW_MST_ID(FW_MST_TYPE_PMU, 0)
+#define FW_MST_ID_VDMA FW_MST_ID(FW_MST_TYPE_PMU, 1)
+#define FW_MST_ID_PMU_CNT 8
+
+/* slave id */
+#define FW_SLV_ID_CAN0 FW_SLV_ID(FW_SLV_TYPE_BUS, 0)
+#define FW_SLV_ID_CAN1 FW_SLV_ID(FW_SLV_TYPE_BUS, 1)
+#define FW_SLV_ID_I3C0 FW_SLV_ID(FW_SLV_TYPE_BUS, 2)
+#define FW_SLV_ID_I3C1 FW_SLV_ID(FW_SLV_TYPE_BUS, 3)
+#define FW_SLV_ID_BUS_IOC FW_SLV_ID(FW_SLV_TYPE_BUS, 4)
+#define FW_SLV_ID_COMBO_PIPE_PHY0 FW_SLV_ID(FW_SLV_TYPE_BUS, 5)
+#define FW_SLV_ID_COMBO_PIPE_PHY1 FW_SLV_ID(FW_SLV_TYPE_BUS, 6)
+#define FW_SLV_ID_CRU FW_SLV_ID(FW_SLV_TYPE_BUS, 7)
+#define FW_SLV_ID_DECOM FW_SLV_ID(FW_SLV_TYPE_BUS, 8)
+#define FW_SLV_ID_CRU_PVTPLL FW_SLV_ID(FW_SLV_TYPE_BUS, 9)
+#define FW_SLV_ID_I2C1 FW_SLV_ID(FW_SLV_TYPE_BUS, 13)
+#define FW_SLV_ID_I2C2 FW_SLV_ID(FW_SLV_TYPE_BUS, 14)
+#define FW_SLV_ID_I2C3 FW_SLV_ID(FW_SLV_TYPE_BUS, 15)
+#define FW_SLV_ID_I2C4 FW_SLV_ID(FW_SLV_TYPE_BUS, 16)
+#define FW_SLV_ID_I2C5 FW_SLV_ID(FW_SLV_TYPE_BUS, 17)
+#define FW_SLV_ID_I2C6 FW_SLV_ID(FW_SLV_TYPE_BUS, 18)
+#define FW_SLV_ID_I2C7 FW_SLV_ID(FW_SLV_TYPE_BUS, 19)
+#define FW_SLV_ID_I2C8 FW_SLV_ID(FW_SLV_TYPE_BUS, 20)
+#define FW_SLV_ID_I2C9 FW_SLV_ID(FW_SLV_TYPE_BUS, 21)
+#define FW_SLV_ID_INTMUX2BUS FW_SLV_ID(FW_SLV_TYPE_BUS, 22)
+#define FW_SLV_ID_INTMUX2DDR FW_SLV_ID(FW_SLV_TYPE_BUS, 23)
+#define FW_SLV_ID_INTMUX2PMU FW_SLV_ID(FW_SLV_TYPE_BUS, 24)
+#define FW_SLV_ID_PPLL_CRU FW_SLV_ID(FW_SLV_TYPE_BUS, 25)
+#define FW_SLV_ID_COMBO_PIPE_PHY0_GRF FW_SLV_ID(FW_SLV_TYPE_BUS, 26)
+#define FW_SLV_ID_COMBO_PIPE_PHY1_GRF FW_SLV_ID(FW_SLV_TYPE_BUS, 27)
+#define FW_SLV_ID_PMU2 FW_SLV_ID(FW_SLV_TYPE_BUS, 28)
+#define FW_SLV_ID_SARADC FW_SLV_ID(FW_SLV_TYPE_BUS, 32)
+#define FW_SLV_ID_SPI0 FW_SLV_ID(FW_SLV_TYPE_BUS, 33)
+#define FW_SLV_ID_SPI1 FW_SLV_ID(FW_SLV_TYPE_BUS, 34)
+#define FW_SLV_ID_SPI2 FW_SLV_ID(FW_SLV_TYPE_BUS, 35)
+#define FW_SLV_ID_SPI3 FW_SLV_ID(FW_SLV_TYPE_BUS, 36)
+#define FW_SLV_ID_SPI4 FW_SLV_ID(FW_SLV_TYPE_BUS, 37)
+#define FW_SLV_ID_SYS_GRF FW_SLV_ID(FW_SLV_TYPE_BUS, 38)
+#define FW_SLV_ID_TSADC FW_SLV_ID(FW_SLV_TYPE_BUS, 41)
+#define FW_SLV_ID_UART0 FW_SLV_ID(FW_SLV_TYPE_BUS, 42)
+#define FW_SLV_ID_UART10 FW_SLV_ID(FW_SLV_TYPE_BUS, 43)
+#define FW_SLV_ID_UART11 FW_SLV_ID(FW_SLV_TYPE_BUS, 44)
+#define FW_SLV_ID_UART2 FW_SLV_ID(FW_SLV_TYPE_BUS, 45)
+#define FW_SLV_ID_UART3 FW_SLV_ID(FW_SLV_TYPE_BUS, 46)
+#define FW_SLV_ID_UART4 FW_SLV_ID(FW_SLV_TYPE_BUS, 47)
+#define FW_SLV_ID_UART5 FW_SLV_ID(FW_SLV_TYPE_BUS, 48)
+#define FW_SLV_ID_UART6 FW_SLV_ID(FW_SLV_TYPE_BUS, 49)
+#define FW_SLV_ID_UART7 FW_SLV_ID(FW_SLV_TYPE_BUS, 50)
+#define FW_SLV_ID_UART8 FW_SLV_ID(FW_SLV_TYPE_BUS, 51)
+#define FW_SLV_ID_UART9 FW_SLV_ID(FW_SLV_TYPE_BUS, 52)
+#define FW_SLV_ID_VCCIO0_1_3_IOC FW_SLV_ID(FW_SLV_TYPE_BUS, 53)
+#define FW_SLV_ID_VCCIO2_4_5_IOC FW_SLV_ID(FW_SLV_TYPE_BUS, 54)
+#define FW_SLV_ID_BUS_WDT FW_SLV_ID(FW_SLV_TYPE_BUS, 55)
+#define FW_SLV_ID_WDT_NS FW_SLV_ID(FW_SLV_TYPE_BUS, 56)
+#define FW_SLV_ID_DMAC0_NS FW_SLV_ID(FW_SLV_TYPE_BUS, 57)
+#define FW_SLV_ID_DMAC1_NS FW_SLV_ID(FW_SLV_TYPE_BUS, 58)
+#define FW_SLV_ID_DMAC2_NS FW_SLV_ID(FW_SLV_TYPE_BUS, 59)
+#define FW_SLV_ID_DMAC0_S FW_SLV_ID(FW_SLV_TYPE_BUS, 60)
+#define FW_SLV_ID_DMAC1_S FW_SLV_ID(FW_SLV_TYPE_BUS, 61)
+#define FW_SLV_ID_DMAC2_S FW_SLV_ID(FW_SLV_TYPE_BUS, 62)
+#define FW_SLV_ID_GIC400 FW_SLV_ID(FW_SLV_TYPE_BUS, 63)
+#define FW_SLV_ID_SERVICE_BUS FW_SLV_ID(FW_SLV_TYPE_BUS, 64)
+#define FW_SLV_ID_SPINLOCK FW_SLV_ID(FW_SLV_TYPE_BUS, 65)
+#define FW_SLV_ID_MAILBOX_CH0 FW_SLV_ID(FW_SLV_TYPE_BUS, 66)
+#define FW_SLV_ID_MAILBOX_CH1 FW_SLV_ID(FW_SLV_TYPE_BUS, 67)
+#define FW_SLV_ID_MAILBOX_CH2 FW_SLV_ID(FW_SLV_TYPE_BUS, 68)
+#define FW_SLV_ID_MAILBOX_CH3 FW_SLV_ID(FW_SLV_TYPE_BUS, 69)
+#define FW_SLV_ID_MAILBOX_CH4 FW_SLV_ID(FW_SLV_TYPE_BUS, 70)
+#define FW_SLV_ID_MAILBOX_CH5 FW_SLV_ID(FW_SLV_TYPE_BUS, 71)
+#define FW_SLV_ID_MAILBOX_CH6 FW_SLV_ID(FW_SLV_TYPE_BUS, 72)
+#define FW_SLV_ID_MAILBOX_CH7 FW_SLV_ID(FW_SLV_TYPE_BUS, 73)
+#define FW_SLV_ID_MAILBOX_CH8 FW_SLV_ID(FW_SLV_TYPE_BUS, 74)
+#define FW_SLV_ID_MAILBOX_CH9 FW_SLV_ID(FW_SLV_TYPE_BUS, 75)
+#define FW_SLV_ID_MAILBOX_CH10 FW_SLV_ID(FW_SLV_TYPE_BUS, 76)
+#define FW_SLV_ID_MAILBOX_CH11 FW_SLV_ID(FW_SLV_TYPE_BUS, 77)
+#define FW_SLV_ID_MAILBOX_CH12 FW_SLV_ID(FW_SLV_TYPE_BUS, 78)
+#define FW_SLV_ID_MAILBOX_CH13 FW_SLV_ID(FW_SLV_TYPE_BUS, 79)
+#define FW_SLV_ID_PWM1_CH0 FW_SLV_ID(FW_SLV_TYPE_BUS, 82)
+#define FW_SLV_ID_PWM1_CH1 FW_SLV_ID(FW_SLV_TYPE_BUS, 83)
+#define FW_SLV_ID_PWM1_CH2 FW_SLV_ID(FW_SLV_TYPE_BUS, 84)
+#define FW_SLV_ID_PWM1_CH3 FW_SLV_ID(FW_SLV_TYPE_BUS, 85)
+#define FW_SLV_ID_PWM1_CH4 FW_SLV_ID(FW_SLV_TYPE_BUS, 86)
+#define FW_SLV_ID_PWM1_CH5 FW_SLV_ID(FW_SLV_TYPE_BUS, 87)
+#define FW_SLV_ID_PWM2_CH0 FW_SLV_ID(FW_SLV_TYPE_BUS, 88)
+#define FW_SLV_ID_PWM2_CH1 FW_SLV_ID(FW_SLV_TYPE_BUS, 89)
+#define FW_SLV_ID_PWM2_CH2 FW_SLV_ID(FW_SLV_TYPE_BUS, 90)
+#define FW_SLV_ID_PWM2_CH3 FW_SLV_ID(FW_SLV_TYPE_BUS, 91)
+#define FW_SLV_ID_PWM2_CH4 FW_SLV_ID(FW_SLV_TYPE_BUS, 92)
+#define FW_SLV_ID_PWM2_CH5 FW_SLV_ID(FW_SLV_TYPE_BUS, 93)
+#define FW_SLV_ID_PWM2_CH6 FW_SLV_ID(FW_SLV_TYPE_BUS, 94)
+#define FW_SLV_ID_PWM2_CH7 FW_SLV_ID(FW_SLV_TYPE_BUS, 95)
+#define FW_SLV_ID_TIMER_NS_0_CH0 FW_SLV_ID(FW_SLV_TYPE_BUS, 96)
+#define FW_SLV_ID_TIMER_NS_0_CH1 FW_SLV_ID(FW_SLV_TYPE_BUS, 97)
+#define FW_SLV_ID_TIMER_NS_0_CH2 FW_SLV_ID(FW_SLV_TYPE_BUS, 98)
+#define FW_SLV_ID_TIMER_NS_0_CH3 FW_SLV_ID(FW_SLV_TYPE_BUS, 99)
+#define FW_SLV_ID_TIMER_NS_0_CH4 FW_SLV_ID(FW_SLV_TYPE_BUS, 100)
+#define FW_SLV_ID_TIMER_NS_0_CH5 FW_SLV_ID(FW_SLV_TYPE_BUS, 101)
+#define FW_SLV_ID_TIMER_NS_1_CH0 FW_SLV_ID(FW_SLV_TYPE_BUS, 102)
+#define FW_SLV_ID_TIMER_NS_1_CH1 FW_SLV_ID(FW_SLV_TYPE_BUS, 103)
+#define FW_SLV_ID_TIMER_NS_1_CH2 FW_SLV_ID(FW_SLV_TYPE_BUS, 104)
+#define FW_SLV_ID_TIMER_NS_1_CH3 FW_SLV_ID(FW_SLV_TYPE_BUS, 105)
+#define FW_SLV_ID_TIMER_NS_1_CH4 FW_SLV_ID(FW_SLV_TYPE_BUS, 106)
+#define FW_SLV_ID_TIMER_NS_1_CH5 FW_SLV_ID(FW_SLV_TYPE_BUS, 107)
+#define FW_SLV_ID_GPIO1_CH0 FW_SLV_ID(FW_SLV_TYPE_BUS, 108)
+#define FW_SLV_ID_GPIO1_CH1 FW_SLV_ID(FW_SLV_TYPE_BUS, 109)
+#define FW_SLV_ID_GPIO1_CH2 FW_SLV_ID(FW_SLV_TYPE_BUS, 110)
+#define FW_SLV_ID_GPIO1_CH3 FW_SLV_ID(FW_SLV_TYPE_BUS, 111)
+#define FW_SLV_ID_GPIO2_CH0 FW_SLV_ID(FW_SLV_TYPE_BUS, 112)
+#define FW_SLV_ID_GPIO2_CH1 FW_SLV_ID(FW_SLV_TYPE_BUS, 113)
+#define FW_SLV_ID_GPIO2_CH2 FW_SLV_ID(FW_SLV_TYPE_BUS, 114)
+#define FW_SLV_ID_GPIO2_CH3 FW_SLV_ID(FW_SLV_TYPE_BUS, 115)
+#define FW_SLV_ID_GPIO3_CH0 FW_SLV_ID(FW_SLV_TYPE_BUS, 116)
+#define FW_SLV_ID_GPIO3_CH1 FW_SLV_ID(FW_SLV_TYPE_BUS, 117)
+#define FW_SLV_ID_GPIO3_CH2 FW_SLV_ID(FW_SLV_TYPE_BUS, 118)
+#define FW_SLV_ID_GPIO3_CH3 FW_SLV_ID(FW_SLV_TYPE_BUS, 119)
+#define FW_SLV_ID_GPIO4_CH0 FW_SLV_ID(FW_SLV_TYPE_BUS, 120)
+#define FW_SLV_ID_GPIO4_CH1 FW_SLV_ID(FW_SLV_TYPE_BUS, 121)
+#define FW_SLV_ID_GPIO4_CH2 FW_SLV_ID(FW_SLV_TYPE_BUS, 122)
+#define FW_SLV_ID_GPIO4_CH3 FW_SLV_ID(FW_SLV_TYPE_BUS, 123)
+#define FW_SLV_ID_BUS_CNT 125
+
+#define FW_SLV_ID_ACDCDIG_DSM FW_SLV_ID(FW_SLV_TYPE_TOP, 0)
+#define FW_SLV_ID_ASRC2CH_0 FW_SLV_ID(FW_SLV_TYPE_TOP, 1)
+#define FW_SLV_ID_ASRC2CH_1 FW_SLV_ID(FW_SLV_TYPE_TOP, 2)
+#define FW_SLV_ID_ASRC4CH_0 FW_SLV_ID(FW_SLV_TYPE_TOP, 3)
+#define FW_SLV_ID_ASRC4CH_1 FW_SLV_ID(FW_SLV_TYPE_TOP, 4)
+#define FW_SLV_ID_PDM1 FW_SLV_ID(FW_SLV_TYPE_TOP, 5)
+#define FW_SLV_ID_SAI0_8CH FW_SLV_ID(FW_SLV_TYPE_TOP, 6)
+#define FW_SLV_ID_SAI1_8CH FW_SLV_ID(FW_SLV_TYPE_TOP, 7)
+#define FW_SLV_ID_SAI2_8CH FW_SLV_ID(FW_SLV_TYPE_TOP, 8)
+#define FW_SLV_ID_SAI3_2CH FW_SLV_ID(FW_SLV_TYPE_TOP, 9)
+#define FW_SLV_ID_SAI4_2CH FW_SLV_ID(FW_SLV_TYPE_TOP, 10)
+#define FW_SLV_ID_SPDIF_RX0 FW_SLV_ID(FW_SLV_TYPE_TOP, 11)
+#define FW_SLV_ID_SPDIF_RX1 FW_SLV_ID(FW_SLV_TYPE_TOP, 12)
+#define FW_SLV_ID_SPDIF_TX0 FW_SLV_ID(FW_SLV_TYPE_TOP, 13)
+#define FW_SLV_ID_SPDIF_TX1 FW_SLV_ID(FW_SLV_TYPE_TOP, 14)
+#define FW_SLV_ID_DSMC_MEM FW_SLV_ID(FW_SLV_TYPE_TOP, 15)
+#define FW_SLV_ID_FSPI1 FW_SLV_ID(FW_SLV_TYPE_TOP, 16)
+#define FW_SLV_ID_FLEXBUS FW_SLV_ID(FW_SLV_TYPE_TOP, 17)
+#define FW_SLV_ID_SDIO FW_SLV_ID(FW_SLV_TYPE_TOP, 18)
+#define FW_SLV_ID_SDMMC FW_SLV_ID(FW_SLV_TYPE_TOP, 19)
+#define FW_SLV_ID_DSMC_CFG FW_SLV_ID(FW_SLV_TYPE_TOP, 20)
+#define FW_SLV_ID_GMAC0 FW_SLV_ID(FW_SLV_TYPE_TOP, 21)
+#define FW_SLV_ID_GMAC1 FW_SLV_ID(FW_SLV_TYPE_TOP, 22)
+#define FW_SLV_ID_SDGMAC_GRF FW_SLV_ID(FW_SLV_TYPE_TOP, 23)
+#define FW_SLV_ID_EMMC FW_SLV_ID(FW_SLV_TYPE_TOP, 24)
+#define FW_SLV_ID_FSPI0 FW_SLV_ID(FW_SLV_TYPE_TOP, 25)
+#define FW_SLV_ID_NSCRYPTO FW_SLV_ID(FW_SLV_TYPE_TOP, 26)
+#define FW_SLV_ID_RKRNG_NS FW_SLV_ID(FW_SLV_TYPE_TOP, 27)
+#define FW_SLV_ID_SCRYPTO FW_SLV_ID(FW_SLV_TYPE_TOP, 28)
+#define FW_SLV_ID_KEYLAD FW_SLV_ID(FW_SLV_TYPE_TOP, 29)
+#define FW_SLV_ID_RKRNG_S FW_SLV_ID(FW_SLV_TYPE_TOP, 30)
+#define FW_SLV_ID_OTPC_NS FW_SLV_ID(FW_SLV_TYPE_TOP, 31)
+#define FW_SLV_ID_JTAG_LOCK FW_SLV_ID(FW_SLV_TYPE_TOP, 33)
+#define FW_SLV_ID_OTPC_S FW_SLV_ID(FW_SLV_TYPE_TOP, 34)
+#define FW_SLV_ID_OTPMASK FW_SLV_ID(FW_SLV_TYPE_TOP, 35)
+#define FW_SLV_ID_SECURE_CRU FW_SLV_ID(FW_SLV_TYPE_TOP, 36)
+#define FW_SLV_ID_SECURE_CRU_S FW_SLV_ID(FW_SLV_TYPE_TOP, 37)
+#define FW_SLV_ID_SYS_SGRF FW_SLV_ID(FW_SLV_TYPE_TOP, 38)
+#define FW_SLV_ID_BOOTROM FW_SLV_ID(FW_SLV_TYPE_TOP, 39)
+#define FW_SLV_ID_WDT_S FW_SLV_ID(FW_SLV_TYPE_TOP, 41)
+#define FW_SLV_ID_SERVICE_GMAC FW_SLV_ID(FW_SLV_TYPE_TOP, 42)
+#define FW_SLV_ID_SERVICE_NVM FW_SLV_ID(FW_SLV_TYPE_TOP, 43)
+#define FW_SLV_ID_SERVICE_SECURE FW_SLV_ID(FW_SLV_TYPE_TOP, 44)
+#define FW_SLV_ID_SERVICE_VENC FW_SLV_ID(FW_SLV_TYPE_TOP, 45)
+#define FW_SLV_ID_SERVICE_VI FW_SLV_ID(FW_SLV_TYPE_TOP, 46)
+#define FW_SLV_ID_SERVICE_VPU FW_SLV_ID(FW_SLV_TYPE_TOP, 47)
+#define FW_SLV_ID_VEPU0 FW_SLV_ID(FW_SLV_TYPE_TOP, 48)
+#define FW_SLV_ID_ISP FW_SLV_ID(FW_SLV_TYPE_TOP, 49)
+#define FW_SLV_ID_VICAP FW_SLV_ID(FW_SLV_TYPE_TOP, 50)
+#define FW_SLV_ID_VPSS FW_SLV_ID(FW_SLV_TYPE_TOP, 51)
+#define FW_SLV_ID_CSIHOST0 FW_SLV_ID(FW_SLV_TYPE_TOP, 52)
+#define FW_SLV_ID_CSIHOST1 FW_SLV_ID(FW_SLV_TYPE_TOP, 53)
+#define FW_SLV_ID_CSIHOST2 FW_SLV_ID(FW_SLV_TYPE_TOP, 54)
+#define FW_SLV_ID_VI_GRF FW_SLV_ID(FW_SLV_TYPE_TOP, 55)
+#define FW_SLV_ID_EBC FW_SLV_ID(FW_SLV_TYPE_TOP, 56)
+#define FW_SLV_ID_JPEG FW_SLV_ID(FW_SLV_TYPE_TOP, 57)
+#define FW_SLV_ID_RGA0 FW_SLV_ID(FW_SLV_TYPE_TOP, 58)
+#define FW_SLV_ID_RGA1 FW_SLV_ID(FW_SLV_TYPE_TOP, 59)
+#define FW_SLV_ID_VDPP FW_SLV_ID(FW_SLV_TYPE_TOP, 60)
+#define FW_SLV_ID_TIMER_S_0_CH0 FW_SLV_ID(FW_SLV_TYPE_TOP, 61)
+#define FW_SLV_ID_TIMER_S_0_CH1 FW_SLV_ID(FW_SLV_TYPE_TOP, 62)
+#define FW_SLV_ID_TIMER_S_0_CH2 FW_SLV_ID(FW_SLV_TYPE_TOP, 63)
+#define FW_SLV_ID_TIMER_S_0_CH3 FW_SLV_ID(FW_SLV_TYPE_TOP, 64)
+#define FW_SLV_ID_TIMER_S_0_CH4 FW_SLV_ID(FW_SLV_TYPE_TOP, 65)
+#define FW_SLV_ID_TIMER_S_0_CH5 FW_SLV_ID(FW_SLV_TYPE_TOP, 66)
+#define FW_SLV_ID_TIMER_S_1_CH0 FW_SLV_ID(FW_SLV_TYPE_TOP, 67)
+#define FW_SLV_ID_TIMER_S_1_CH1 FW_SLV_ID(FW_SLV_TYPE_TOP, 68)
+#define FW_SLV_ID_TIMER_S_1_CH2 FW_SLV_ID(FW_SLV_TYPE_TOP, 69)
+#define FW_SLV_ID_TIMER_S_1_CH3 FW_SLV_ID(FW_SLV_TYPE_TOP, 70)
+#define FW_SLV_ID_TIMER_S_1_CH4 FW_SLV_ID(FW_SLV_TYPE_TOP, 71)
+#define FW_SLV_ID_TIMER_S_1_CH5 FW_SLV_ID(FW_SLV_TYPE_TOP, 72)
+#define FW_SLV_ID_SYS_FW FW_SLV_ID(FW_SLV_TYPE_TOP, 73)
+#define FW_SLV_ID_VEPU1 FW_SLV_ID(FW_SLV_TYPE_TOP, 75)
+#define FW_SLV_ID_SERVICE_VEPU1 FW_SLV_ID(FW_SLV_TYPE_TOP, 76)
+#define FW_SLV_ID_CSIHOST3 FW_SLV_ID(FW_SLV_TYPE_TOP, 77)
+#define FW_SLV_ID_CSIHOST4 FW_SLV_ID(FW_SLV_TYPE_TOP, 78)
+#define FW_SLV_ID_TOP_CNT 80
+
+#define FW_SLV_ID_CENTER_GRF FW_SLV_ID(FW_SLV_TYPE_CENTER, 0)
+#define FW_SLV_ID_DMA2DDR FW_SLV_ID(FW_SLV_TYPE_CENTER, 1)
+#define FW_SLV_ID_AHB2APB FW_SLV_ID(FW_SLV_TYPE_CENTER, 2)
+#define FW_SLV_ID_DDR_GRF FW_SLV_ID(FW_SLV_TYPE_CENTER, 3)
+#define FW_SLV_ID_DDRCTL0 FW_SLV_ID(FW_SLV_TYPE_CENTER, 4)
+#define FW_SLV_ID_DDRCTL_1 FW_SLV_ID(FW_SLV_TYPE_CENTER, 5)
+#define FW_SLV_ID_DDRPHY0 FW_SLV_ID(FW_SLV_TYPE_CENTER, 6)
+#define FW_SLV_ID_DDR0_CRU FW_SLV_ID(FW_SLV_TYPE_CENTER, 7)
+#define FW_SLV_ID_DDRPHY1 FW_SLV_ID(FW_SLV_TYPE_CENTER, 8)
+#define FW_SLV_ID_DDR1_CRU FW_SLV_ID(FW_SLV_TYPE_CENTER, 9)
+#define FW_SLV_ID_DDRMON0 FW_SLV_ID(FW_SLV_TYPE_CENTER, 10)
+#define FW_SLV_ID_DDRMON1 FW_SLV_ID(FW_SLV_TYPE_CENTER, 11)
+#define FW_SLV_ID_HWLP0 FW_SLV_ID(FW_SLV_TYPE_CENTER, 12)
+#define FW_SLV_ID_HWLP1 FW_SLV_ID(FW_SLV_TYPE_CENTER, 13)
+#define FW_SLV_ID_DDR_PVTPLL FW_SLV_ID(FW_SLV_TYPE_CENTER, 14)
+#define FW_SLV_ID_DDR_WDT FW_SLV_ID(FW_SLV_TYPE_CENTER, 15)
+#define FW_SLV_ID_RKVDEC FW_SLV_ID(FW_SLV_TYPE_CENTER, 16)
+#define FW_SLV_ID_SERVICE_CCI2 FW_SLV_ID(FW_SLV_TYPE_CENTER, 17)
+#define FW_SLV_ID_SERVICE_CENTER FW_SLV_ID(FW_SLV_TYPE_CENTER, 18)
+#define FW_SLV_ID_SERVICE_DDR FW_SLV_ID(FW_SLV_TYPE_CENTER, 19)
+#define FW_SLV_ID_SERVICE_RKVDEC FW_SLV_ID(FW_SLV_TYPE_CENTER, 20)
+#define FW_SLV_ID_SERVICE_USB FW_SLV_ID(FW_SLV_TYPE_CENTER, 21)
+#define FW_SLV_ID_SERVICE_VO0 FW_SLV_ID(FW_SLV_TYPE_CENTER, 22)
+#define FW_SLV_ID_SERVICE_VO1 FW_SLV_ID(FW_SLV_TYPE_CENTER, 23)
+#define FW_SLV_ID_SERVICE_VOP FW_SLV_ID(FW_SLV_TYPE_CENTER, 24)
+#define FW_SLV_ID_UFS_APBS FW_SLV_ID(FW_SLV_TYPE_CENTER, 25)
+#define FW_SLV_ID_UFS_AXIS FW_SLV_ID(FW_SLV_TYPE_CENTER, 26)
+#define FW_SLV_ID_USB0 FW_SLV_ID(FW_SLV_TYPE_CENTER, 27)
+#define FW_SLV_ID_MMU2 FW_SLV_ID(FW_SLV_TYPE_CENTER, 28)
+#define FW_SLV_ID_USB_GRF FW_SLV_ID(FW_SLV_TYPE_CENTER, 29)
+#define FW_SLV_ID_HDCP0_MMU FW_SLV_ID(FW_SLV_TYPE_CENTER, 30)
+#define FW_SLV_ID_SAI5_8CH FW_SLV_ID(FW_SLV_TYPE_CENTER, 31)
+#define FW_SLV_ID_SAI6_8CH FW_SLV_ID(FW_SLV_TYPE_CENTER, 32)
+#define FW_SLV_ID_SPDIF_RX2 FW_SLV_ID(FW_SLV_TYPE_CENTER, 33)
+#define FW_SLV_ID_SPDIF_TX2 FW_SLV_ID(FW_SLV_TYPE_CENTER, 34)
+#define FW_SLV_ID_HDCP0_KEY FW_SLV_ID(FW_SLV_TYPE_CENTER, 35)
+#define FW_SLV_ID_DSIHOST FW_SLV_ID(FW_SLV_TYPE_CENTER, 36)
+#define FW_SLV_ID_EDP0 FW_SLV_ID(FW_SLV_TYPE_CENTER, 37)
+#define FW_SLV_ID_HDCP0 FW_SLV_ID(FW_SLV_TYPE_CENTER, 38)
+#define FW_SLV_ID_HDCP0_TRNG FW_SLV_ID(FW_SLV_TYPE_CENTER, 39)
+#define FW_SLV_ID_HDMITX FW_SLV_ID(FW_SLV_TYPE_CENTER, 40)
+#define FW_SLV_ID_VO0_GRF FW_SLV_ID(FW_SLV_TYPE_CENTER, 41)
+#define FW_SLV_ID_EDP0_S FW_SLV_ID(FW_SLV_TYPE_CENTER, 42)
+#define FW_SLV_ID_HDCP1_MMU FW_SLV_ID(FW_SLV_TYPE_CENTER, 43)
+#define FW_SLV_ID_SAI7_8CH FW_SLV_ID(FW_SLV_TYPE_CENTER, 44)
+#define FW_SLV_ID_SPDIF_TX3 FW_SLV_ID(FW_SLV_TYPE_CENTER, 45)
+#define FW_SLV_ID_HDCP1_KEY FW_SLV_ID(FW_SLV_TYPE_CENTER, 46)
+#define FW_SLV_ID_DP FW_SLV_ID(FW_SLV_TYPE_CENTER, 47)
+#define FW_SLV_ID_HDCP1 FW_SLV_ID(FW_SLV_TYPE_CENTER, 48)
+#define FW_SLV_ID_HDCP1_TRNG FW_SLV_ID(FW_SLV_TYPE_CENTER, 49)
+#define FW_SLV_ID_VO1_GRF FW_SLV_ID(FW_SLV_TYPE_CENTER, 50)
+#define FW_SLV_ID_VOP_GRF FW_SLV_ID(FW_SLV_TYPE_CENTER, 52)
+#define FW_SLV_ID_UFS_GRF FW_SLV_ID(FW_SLV_TYPE_CENTER, 53)
+#define FW_SLV_ID_SPDIF_TX4 FW_SLV_ID(FW_SLV_TYPE_CENTER, 54)
+#define FW_SLV_ID_SPDIF_TX5 FW_SLV_ID(FW_SLV_TYPE_CENTER, 55)
+#define FW_SLV_ID_SAI8_8CH FW_SLV_ID(FW_SLV_TYPE_CENTER, 56)
+#define FW_SLV_ID_SAI9_8CH FW_SLV_ID(FW_SLV_TYPE_CENTER, 57)
+#define FW_SLV_ID_DDR_TIMER_CH0 FW_SLV_ID(FW_SLV_TYPE_CENTER, 58)
+#define FW_SLV_ID_DDR_TIMER_CH1 FW_SLV_ID(FW_SLV_TYPE_CENTER, 59)
+#define FW_SLV_ID_VOP_RGN0 FW_SLV_ID(FW_SLV_TYPE_CENTER, 60)
+#define FW_SLV_ID_VOP_RGN1 FW_SLV_ID(FW_SLV_TYPE_CENTER, 61)
+#define FW_SLV_ID_VOP_RGN2 FW_SLV_ID(FW_SLV_TYPE_CENTER, 62)
+#define FW_SLV_ID_VOP_RGN3 FW_SLV_ID(FW_SLV_TYPE_CENTER, 63)
+#define FW_SLV_ID_VOP_OTHERS FW_SLV_ID(FW_SLV_TYPE_CENTER, 64)
+#define FW_SLV_ID_CENTER_CNT 65
+
+#define FW_SLV_ID_BIGCORE_CRU FW_SLV_ID(FW_SLV_TYPE_CCI, 0)
+#define FW_SLV_ID_BIGCORE_GRF FW_SLV_ID(FW_SLV_TYPE_CCI, 1)
+#define FW_SLV_ID_CCI FW_SLV_ID(FW_SLV_TYPE_CCI, 2)
+#define FW_SLV_ID_CCI_CRU FW_SLV_ID(FW_SLV_TYPE_CCI, 3)
+#define FW_SLV_ID_CCI_PVTPLL FW_SLV_ID(FW_SLV_TYPE_CCI, 4)
+#define FW_SLV_ID_CCI_GRF FW_SLV_ID(FW_SLV_TYPE_CCI, 5)
+#define FW_SLV_ID_DAP_LITE_A53 FW_SLV_ID(FW_SLV_TYPE_CCI, 6)
+#define FW_SLV_ID_DAP_LITE_A72 FW_SLV_ID(FW_SLV_TYPE_CCI, 7)
+#define FW_SLV_ID_LITCORE_GRF FW_SLV_ID(FW_SLV_TYPE_CCI, 8)
+#define FW_SLV_ID_LITCORE_CRU FW_SLV_ID(FW_SLV_TYPE_CCI, 9)
+#define FW_SLV_ID_SERVICE_CCI FW_SLV_ID(FW_SLV_TYPE_CCI, 10)
+#define FW_SLV_ID_BIGCORE_PVTPLL FW_SLV_ID(FW_SLV_TYPE_CCI, 11)
+#define FW_SLV_ID_LITCORE_PVTPLL FW_SLV_ID(FW_SLV_TYPE_CCI, 12)
+#define FW_SLV_ID_CCI_CNT 15
+
+#define FW_SLV_ID_PCIE0_DBI FW_SLV_ID(FW_SLV_TYPE_PHP, 0)
+#define FW_SLV_ID_PCIE0_DBI_L FW_SLV_ID(FW_SLV_TYPE_PHP, 1)
+#define FW_SLV_ID_PCIE0_S FW_SLV_ID(FW_SLV_TYPE_PHP, 2)
+#define FW_SLV_ID_PCIE0_S_L FW_SLV_ID(FW_SLV_TYPE_PHP, 3)
+#define FW_SLV_ID_PCIE1_DBI FW_SLV_ID(FW_SLV_TYPE_PHP, 4)
+#define FW_SLV_ID_PCIE1_DBI_L FW_SLV_ID(FW_SLV_TYPE_PHP, 5)
+#define FW_SLV_ID_PCIE1_S FW_SLV_ID(FW_SLV_TYPE_PHP, 6)
+#define FW_SLV_ID_PCIE1_S_L FW_SLV_ID(FW_SLV_TYPE_PHP, 7)
+#define FW_SLV_ID_USB1 FW_SLV_ID(FW_SLV_TYPE_PHP, 8)
+#define FW_SLV_ID_PCIE0_APB FW_SLV_ID(FW_SLV_TYPE_PHP, 9)
+#define FW_SLV_ID_PCIE1_APB FW_SLV_ID(FW_SLV_TYPE_PHP, 10)
+#define FW_SLV_ID_PHP_GRF FW_SLV_ID(FW_SLV_TYPE_PHP, 11)
+#define FW_SLV_ID_SATA0 FW_SLV_ID(FW_SLV_TYPE_PHP, 12)
+#define FW_SLV_ID_SATA1 FW_SLV_ID(FW_SLV_TYPE_PHP, 13)
+#define FW_SLV_ID_SERVICE_PHP FW_SLV_ID(FW_SLV_TYPE_PHP, 14)
+#define FW_SLV_ID_MMU0 FW_SLV_ID(FW_SLV_TYPE_PHP, 15)
+#define FW_SLV_ID_MMU1 FW_SLV_ID(FW_SLV_TYPE_PHP, 16)
+#define FW_SLV_ID_PHP_CNT 20
+
+#define FW_SLV_ID_GPU_GRF FW_SLV_ID(FW_SLV_TYPE_GPU, 0)
+#define FW_SLV_ID_GPU FW_SLV_ID(FW_SLV_TYPE_GPU, 1)
+#define FW_SLV_ID_SERVICE_GPU FW_SLV_ID(FW_SLV_TYPE_GPU, 2)
+#define FW_SLV_ID_GPU_PVTPLL FW_SLV_ID(FW_SLV_TYPE_GPU, 3)
+#define FW_SLV_ID_GPU_CNT 5
+
+#define FW_SLV_ID_RKNN_TOP FW_SLV_ID(FW_SLV_TYPE_NPU, 0)
+#define FW_SLV_ID_SERVICE_NPU0 FW_SLV_ID(FW_SLV_TYPE_NPU, 1)
+#define FW_SLV_ID_SERVICE_NPU1 FW_SLV_ID(FW_SLV_TYPE_NPU, 2)
+#define FW_SLV_ID_SERVICE_NPUSUBSYS FW_SLV_ID(FW_SLV_TYPE_NPU, 3)
+#define FW_SLV_ID_RKNN_NSP FW_SLV_ID(FW_SLV_TYPE_NPU, 4)
+#define FW_SLV_ID_NPU_GRF FW_SLV_ID(FW_SLV_TYPE_NPU, 5)
+#define FW_SLV_ID_NPU_PVTPLL FW_SLV_ID(FW_SLV_TYPE_NPU, 6)
+#define FW_SLV_ID_NPU_WDT FW_SLV_ID(FW_SLV_TYPE_NPU, 7)
+#define FW_SLV_ID_NPU_TIMER_CH0 FW_SLV_ID(FW_SLV_TYPE_NPU, 8)
+#define FW_SLV_ID_NPU_TIMER_CH1 FW_SLV_ID(FW_SLV_TYPE_NPU, 9)
+#define FW_SLV_ID_NPU_CNT 10
+
+#define FW_SLV_ID_PDM0 FW_SLV_ID(FW_SLV_TYPE_PMU, 0)
+#define FW_SLV_ID_PMU_MEM FW_SLV_ID(FW_SLV_TYPE_PMU, 1)
+#define FW_SLV_ID_CSIDPHY_GRF FW_SLV_ID(FW_SLV_TYPE_PMU, 2)
+#define FW_SLV_ID_VDMA FW_SLV_ID(FW_SLV_TYPE_PMU, 3)
+#define FW_SLV_ID_HDPTXPHY FW_SLV_ID(FW_SLV_TYPE_PMU, 4)
+#define FW_SLV_ID_HDPTXPHY0_GRF FW_SLV_ID(FW_SLV_TYPE_PMU, 5)
+#define FW_SLV_ID_I2C0 FW_SLV_ID(FW_SLV_TYPE_PMU, 6)
+#define FW_SLV_ID_DCPHY FW_SLV_ID(FW_SLV_TYPE_PMU, 7)
+#define FW_SLV_ID_CSIDPHY0 FW_SLV_ID(FW_SLV_TYPE_PMU, 8)
+#define FW_SLV_ID_DCPHY_GRF FW_SLV_ID(FW_SLV_TYPE_PMU, 9)
+#define FW_SLV_ID_PMU0 FW_SLV_ID(FW_SLV_TYPE_PMU, 10)
+#define FW_SLV_ID_PMU0_GRF FW_SLV_ID(FW_SLV_TYPE_PMU, 11)
+#define FW_SLV_ID_PMU0_IOC FW_SLV_ID(FW_SLV_TYPE_PMU, 12)
+#define FW_SLV_ID_PMU1 FW_SLV_ID(FW_SLV_TYPE_PMU, 13)
+#define FW_SLV_ID_PMU1_CRU FW_SLV_ID(FW_SLV_TYPE_PMU, 14)
+#define FW_SLV_ID_PMU1_CRU_S FW_SLV_ID(FW_SLV_TYPE_PMU, 15)
+#define FW_SLV_ID_PMU1_GRF FW_SLV_ID(FW_SLV_TYPE_PMU, 16)
+#define FW_SLV_ID_PMU1_IOC FW_SLV_ID(FW_SLV_TYPE_PMU, 17)
+#define FW_SLV_ID_PWM0_CH0 FW_SLV_ID(FW_SLV_TYPE_PMU, 18)
+#define FW_SLV_ID_PWM0_CH1 FW_SLV_ID(FW_SLV_TYPE_PMU, 19)
+#define FW_SLV_ID_UART1 FW_SLV_ID(FW_SLV_TYPE_PMU, 20)
+#define FW_SLV_ID_MPHY_GRF FW_SLV_ID(FW_SLV_TYPE_PMU, 21)
+#define FW_SLV_ID_MPHY FW_SLV_ID(FW_SLV_TYPE_PMU, 22)
+#define FW_SLV_ID_USB2PHY0_GRF FW_SLV_ID(FW_SLV_TYPE_PMU, 23)
+#define FW_SLV_ID_USB2PHY1_GRF FW_SLV_ID(FW_SLV_TYPE_PMU, 24)
+#define FW_SLV_ID_USBDPPHY FW_SLV_ID(FW_SLV_TYPE_PMU, 25)
+#define FW_SLV_ID_USBDPPHY_GRF FW_SLV_ID(FW_SLV_TYPE_PMU, 26)
+#define FW_SLV_ID_VCCIO6_IOC FW_SLV_ID(FW_SLV_TYPE_PMU, 27)
+#define FW_SLV_ID_PMU_WDT FW_SLV_ID(FW_SLV_TYPE_PMU, 28)
+#define FW_SLV_ID_HPTIMER FW_SLV_ID(FW_SLV_TYPE_PMU, 29)
+#define FW_SLV_ID_OSC_CHK FW_SLV_ID(FW_SLV_TYPE_PMU, 30)
+#define FW_SLV_ID_PMU0_SGRF FW_SLV_ID(FW_SLV_TYPE_PMU, 31)
+#define FW_SLV_ID_PMU1_SGRF FW_SLV_ID(FW_SLV_TYPE_PMU, 32)
+#define FW_SLV_ID_PMU_PVTM FW_SLV_ID(FW_SLV_TYPE_PMU, 33)
+#define FW_SLV_ID_SCRAMBLE_KEY FW_SLV_ID(FW_SLV_TYPE_PMU, 34)
+#define FW_SLV_ID_SERVICE_PMU FW_SLV_ID(FW_SLV_TYPE_PMU, 35)
+#define FW_SLV_ID_PMU_SRAM_REMAP FW_SLV_ID(FW_SLV_TYPE_PMU, 36)
+#define FW_SLV_ID_PMU_TIMER_CH0 FW_SLV_ID(FW_SLV_TYPE_PMU, 37)
+#define FW_SLV_ID_PMU_TIMER_CH1 FW_SLV_ID(FW_SLV_TYPE_PMU, 38)
+#define FW_SLV_ID_GPIO0_CH0 FW_SLV_ID(FW_SLV_TYPE_PMU, 39)
+#define FW_SLV_ID_GPIO0_CH1 FW_SLV_ID(FW_SLV_TYPE_PMU, 40)
+#define FW_SLV_ID_GPIO0_CH2 FW_SLV_ID(FW_SLV_TYPE_PMU, 41)
+#define FW_SLV_ID_GPIO0_CH3 FW_SLV_ID(FW_SLV_TYPE_PMU, 42)
+#define FW_SLV_ID_PMU_FW FW_SLV_ID(FW_SLV_TYPE_PMU, 43)
+#define FW_SLV_ID_PMU_CNT 45
+
+#define PLAT_MAX_DDR_CAPACITY_MB 0x8000 /* for 32Gb */
+#define RG_MAP_SECURE(top, base) \
+ (((((top) - 1) & 0x7fff) << 16) | ((base) & 0x7fff))
+#define RG_MAP_SRAM_SECURE(top_kb, base_kb) \
+ (((((top_kb) / 4 - 1) & 0xff) << 8) | ((base_kb) / 4 & 0xff))
+#define RG_MAP_CBUF_SECURE(top_kb, base_kb) \
+ (((((top_kb) / 4 - 1) & 0xff) << 8) | ((base_kb) / 4 & 0xff))
+
+#define FW_UPDATE_WAIT_LOOP 500000
+
+__pmusramfunc void pmusram_fw_update_msk(uint32_t msk);
+__pmusramfunc void pmusram_all_fw_bypass(void);
+
+void fw_init(void);
+
+#endif /* __FIREWALL_H__ */
diff --git a/plat/rockchip/rk3576/drivers/secure/secure.c b/plat/rockchip/rk3576/drivers/secure/secure.c
new file mode 100644
index 0000000..55b8d93
--- /dev/null
+++ b/plat/rockchip/rk3576/drivers/secure/secure.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#include <assert.h>
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+
+#include <secure.h>
+#include <soc.h>
+
+static void secure_timer_init(void)
+{
+ /* gpu's cntvalue comes from stimer1 channel_5 */
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_CONTROL_REG,
+ TIMER_DIS);
+
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_LOAD_COUNT0, 0xffffffff);
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_LOAD_COUNT1, 0xffffffff);
+
+ /* auto reload & enable the timer */
+ mmio_write_32(STIMER1_CHN_BASE(5) + TIMER_CONTROL_REG,
+ TIMER_EN | TIMER_FMODE);
+}
+
+void secure_init(void)
+{
+ secure_timer_init();
+ fw_init();
+
+ /* crypto secure controlled by crypto */
+ mmio_write_32(SYS_SGRF_BASE + SYSSGRF_SOC_CON(0), BITS_WITH_WMASK(0, 0x1, 4));
+ mmio_write_32(SYS_SGRF_BASE + SYSSGRF_SOC_CON(0), BITS_WITH_WMASK(0, 0x1, 5));
+
+ /* disable DP encryption mode */
+ mmio_write_32(SYS_SGRF_BASE + SYSSGRF_SOC_CON(1), BITS_WITH_WMASK(1, 0x1, 14));
+}
diff --git a/plat/rockchip/rk3576/drivers/secure/secure.h b/plat/rockchip/rk3576/drivers/secure/secure.h
new file mode 100644
index 0000000..f00e519
--- /dev/null
+++ b/plat/rockchip/rk3576/drivers/secure/secure.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#ifndef SECURE_H
+#define SECURE_H
+
+#include <firewall.h>
+
+/* PMU0SGRF */
+#define PMU0SGRF_SOC_CON(i) ((i) * 4)
+
+ /* PMU1SGRF */
+#define PMU1SGRF_SOC_CON(i) ((i) * 4)
+
+ /* CCISGRF */
+#define CCISGRF_SOC_CON(i) (0x20 + (i) * 4)
+#define CCISGRF_DDR_HASH_CON(i) (0x40 + (i) * 4)
+
+ /* SGRF */
+#define SYSSGRF_DDR_BANK_MSK(i) (0x04 + (i) * 4)
+#define SYSSGRF_DDR_CH_MSK(i) (0x18 + (i) * 4)
+#define SYSSGRF_SOC_CON(i) (0x20 + (i) * 4)
+#define SYSSGRF_DMAC_CON(i) (0x80 + (i) * 4)
+#define SYSSGRF_SOC_STATUS 0x240
+
+void secure_init(void);
+
+#endif /* SECURE_H */
diff --git a/plat/rockchip/rk3576/drivers/soc/soc.c b/plat/rockchip/rk3576/drivers/soc/soc.c
new file mode 100644
index 0000000..a78e82e
--- /dev/null
+++ b/plat/rockchip/rk3576/drivers/soc/soc.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <bl31/bl31.h>
+#include <common/debug.h>
+#include <drivers/console.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_compat.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <pmu.h>
+
+#include <plat_private.h>
+#include <rk3576_clk.h>
+#include <secure.h>
+#include <soc.h>
+
+const mmap_region_t plat_rk_mmap[] = {
+ MAP_REGION_FLAT(RK3576_DEV_RNG0_BASE, RK3576_DEV_RNG0_SIZE,
+ MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DDR_SHARE_MEM, DDR_SHARE_SIZE,
+ MT_DEVICE | MT_RW | MT_NS),
+ { 0 }
+};
+
+/* The RockChip power domain tree descriptor */
+const unsigned char rockchip_power_domain_tree_desc[] = {
+ /* No of root nodes */
+ PLATFORM_SYSTEM_COUNT,
+ /* No of children for the root node */
+ PLATFORM_CLUSTER_COUNT,
+ /* No of children for the first cluster node */
+ PLATFORM_CLUSTER0_CORE_COUNT,
+ /* No of children for the second cluster node */
+ PLATFORM_CLUSTER1_CORE_COUNT
+};
+
+static void clear_glb_reset_status(void)
+{
+ uint32_t cru_sel55 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(55));
+
+ /* switch pclk_bus_root to 24M before writing CRU_GLB_RST_ST */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(55),
+ BITS_WITH_WMASK(2, 0x3, 2));
+ dsb();
+
+ mmio_write_32(CRU_BASE + CRU_GLB_RST_ST, 0xffff);
+ dsb();
+
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(55),
+ WITH_16BITS_WMSK(cru_sel55));
+}
+
+static void print_glb_reset_status(void)
+{
+ uint32_t glb_rst_st = 0, warm_boot = 0;
+
+ /* clear CRU_GLB_RST_ST_NCLR if cold boot */
+ if (mmio_read_32(PMU0_GRF_BASE + PMU0GRF_OS_REG(17)) == WARM_BOOT_MAGIC) {
+ /* ignore npu_wdt*/
+ glb_rst_st = mmio_read_32(CRU_BASE + CRU_GLB_RST_ST_NCLR) & VALID_GLB_RST_MSK;
+ warm_boot = 1;
+ } else {
+ mmio_write_32(PMU0_GRF_BASE + PMU0GRF_OS_REG(17), WARM_BOOT_MAGIC);
+ }
+
+ clear_glb_reset_status();
+
+ /* save glb_rst_st in mem_os_reg31 */
+ write_mem_os_reg(31, glb_rst_st);
+
+ if (warm_boot != 0)
+ INFO("soc warm boot, reset status: 0x%x\n", glb_rst_st);
+ else
+ INFO("soc cold boot\n");
+}
+
+static void system_reset_init(void)
+{
+ /*
+ * enable tsadc trigger global reset and select first reset.
+ * enable global reset and wdt trigger pmu reset.
+ * select first reset trigger pmu reset.
+ */
+ mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, 0xffdf);
+
+ /* enable wdt_s reset */
+ mmio_write_32(SYS_SGRF_BASE + SYSSGRF_SOC_CON(0), 0x20002000);
+
+ /* enable wdt_ns reset */
+ mmio_write_32(SYS_GRF_BASE + SYSGRF_SOC_CON(4), 0x01000100);
+
+ /* reset width = 0xffff */
+ mmio_write_32(PMU1_GRF_BASE + PMU1GRF_SOC_CON(6), 0xffffffff);
+
+ /* enable first/tsadc/wdt reset output */
+ mmio_write_32(PMU1SGRF_BASE + PMU1SGRF_SOC_CON(0), 0x00070007);
+
+ /* pmu0sgrf pmu0_ioc hold */
+ mmio_write_32(PMU0SGRF_BASE + PMU1SGRF_SOC_CON(0), 0xffff1800);
+
+ /* pmu1sgrf pmu1_grf hold */
+ mmio_write_32(PMU1SGRF_BASE + PMU1SGRF_SOC_CON(16), 0xffff8800);
+
+ /* select tsadc_shut_m0 ionmux*/
+ mmio_write_32(PMU0_IOC_BASE + 0x0, 0x00f00090);
+
+ print_glb_reset_status();
+}
+
+void plat_rockchip_soc_init(void)
+{
+ rockchip_clock_init();
+ system_reset_init();
+ secure_init();
+ rockchip_init_scmi_server();
+
+ /* release cpu1~cpu7 */
+ mmio_write_32(CCI_GRF_BASE + CCIGRF_CON(4), 0xffffffff);
+ mmio_write_32(LITCORE_GRF_BASE + COREGRF_CPU_CON(1),
+ BITS_WITH_WMASK(0x77, 0xff, 4));
+}
diff --git a/plat/rockchip/rk3576/drivers/soc/soc.h b/plat/rockchip/rk3576/drivers/soc/soc.h
new file mode 100644
index 0000000..f96a42d
--- /dev/null
+++ b/plat/rockchip/rk3576/drivers/soc/soc.h
@@ -0,0 +1,271 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#ifndef __SOC_H__
+#define __SOC_H__
+
+enum pll_id {
+ APLL_ID,
+ CPLL_ID,
+ DPLL_ID,
+ GPLL_ID,
+};
+
+enum cru_mode_con00 {
+ CLK_APLL,
+ CLK_CPLL,
+ CLK_GPLL,
+ CLK_DPLL,
+};
+
+#define KHz 1000
+#define MHz (1000 * KHz)
+#define OSC_HZ (24 * MHz)
+
+#define MCU_VALID_START_ADDRESS 0x800000
+
+/* CRU */
+#define GLB_SRST_FST_CFG_VAL 0xfdb9
+
+#define CRU_PLLS_CON(pll_id, i) ((pll_id) * 0x20 + (i) * 0x4)
+#define CRU_PLL_CON(i) ((i) * 0x4)
+#define CRU_MODE_CON 0x280
+#define CRU_CLKSEL_CON(i) ((i) * 0x4 + 0x300)
+#define CRU_CLKSEL_CON_CNT 181
+#define CRU_CLKGATE_CON(i) ((i) * 0x4 + 0x800)
+#define CRU_CLKGATE_CON_CNT 80
+#define CRU_SOFTRST_CON(i) ((i) * 0x4 + 0xa00)
+#define CRU_SOFTRST_CON_CNT 80
+
+#define CRU_GLB_CNT_TH 0xc00
+#define CRU_GLB_RST_ST 0xc04
+#define CRU_GLB_SRST_FST 0xc08
+#define CRU_GLB_SRST_SND 0xc0c
+#define CRU_GLB_RST_CON 0xc10
+#define CRU_GLB_RST_ST_NCLR 0xc14
+#define CRU_LITCOREWFI_CON0 0xc40
+#define CRU_BIGCOREWFI_CON0 0xc44
+#define CRU_NON_SECURE_GT_CON0 0xc48
+
+#define CRU_PLLCON0_M_MASK 0x3ff
+#define CRU_PLLCON0_M_SHIFT 0
+#define CRU_PLLCON1_P_MASK 0x3f
+#define CRU_PLLCON1_P_SHIFT 0
+#define CRU_PLLCON1_S_MASK 0x7
+#define CRU_PLLCON1_S_SHIFT 6
+#define CRU_PLLCON2_K_MASK 0xffff
+#define CRU_PLLCON2_K_SHIFT 0
+#define CRU_PLLCON1_PWRDOWN BIT(13)
+#define CRU_PLLCON6_LOCK_STATUS BIT(15)
+
+/* LCORE_CRU */
+#define LCORE_CRU_MODE_CON 0x280
+#define LCORE_CRU_CLKSEL_CON(i) ((i) * 0x4 + 0x300)
+#define LCORE_CRU_CLKSEL_CON_CNT 4
+#define LCORE_CRU_CLKGATE_CON(i) ((i) * 0x4 + 0x800)
+#define LCORE_CRU_CLKGATE_CON_CNT 2
+#define LCORE_CRU_SOFTRST_CON(i) ((i) * 0x4 + 0xa00)
+#define LCORE_CRU_SOFTRST_CON_CNT 4
+
+/* BCORE_CRU */
+#define BCORE_CRU_MODE_CON 0x280
+#define BCORE_CRU_CLKSEL_CON(i) ((i) * 0x4 + 0x300)
+#define BCORE_CRU_CLKSEL_CON_CNT 5
+#define BCORE_CRU_CLKGATE_CON(i) ((i) * 0x4 + 0x800)
+#define BCORE_CRU_CLKGATE_CON_CNT 3
+#define BCORE_CRU_SOFTRST_CON(i) ((i) * 0x4 + 0xa00)
+#define BCORE_CRU_SOFTRST_CON_CNT 4
+
+/* DDRCRU */
+#define DDRCRU_MODE_CON 0x280
+#define DDRCRU_CLKSEL_CON(i) ((i) * 0x4 + 0x300)
+#define DDRCRU_CLKGATE_CON(i) ((i) * 0x4 + 0x800)
+#define DDRCRU_SOFTRST_CON(i) ((i) * 0x4 + 0xa00)
+
+/* CCICRU */
+#define CCICRU_MODE_CON 0x280
+#define CCICRU_CLKSEL_CON(i) ((i) * 0x4 + 0x300)
+#define CCICRU_CLKSEL_CON_CNT 10
+#define CCICRU_CLKGATE_CON(i) ((i) * 0x4 + 0x800)
+#define CCICRU_CLKGATE_CON_CNT 7
+#define CCICRU_SOFTRST_CON(i) ((i) * 0x4 + 0xa00)
+#define CCICRU_SOFTRST_CON_CNT 7
+
+/* CRU AUTOCS */
+#define CRU_AUTOCS_CON(offset) (CRU_BASE + (offset))
+#define CRU_AUTOCS_SEC_CON(offset) (SECURE_CRU_BASE + (offset))
+#define CRU_AUTOCS_CCI_CON(offset) (CCI_CRU_BASE + (offset))
+#define AUTOCS_EN_BIT BIT(12)
+
+/* PHP_CRU */
+#define PHP_CRU_MODE_CON 0x280
+#define PHP_CRU_CLKSEL_CON(i) ((i) * 0x4 + 0x300)
+#define PHP_CRU_CLKSEL_CON_CNT 2
+#define PHP_CRU_CLKGATE_CON(i) ((i) * 0x4 + 0x800)
+#define PHP_CRU_CLKGATE_CON_CNT 2
+#define PHP_CRU_SOFTRST_CON(i) ((i) * 0x4 + 0xa00)
+#define PHP_CRU_SOFTRST_CON_CNT 2
+
+/* SECURE CRU */
+#define SECURE_CRU_CLKSEL_CON(i) ((i) * 0x4 + 0x300)
+#define SECURE_CRU_CLKSEL_CON_CNT 1
+#define SECURE_CRU_CLKGATE_CON(i) ((i) * 0x4 + 0x800)
+#define SECURE_CRU_CLKGATE_CON_CNT 1
+#define SECURE_CRU_SOFTRST_CON(i) ((i) * 0x4 + 0xa00)
+#define SECURE_CRU_SOFTRST_CON_CNT 1
+
+/* SECURE SCRU */
+#define SECURE_SCRU_CLKSEL_CON(i) ((i) * 0x4 + 0x4000)
+#define SECURE_SCRU_CLKSEL_CON_CNT 7
+#define SECURE_SCRU_CLKGATE_CON(i) ((i) * 0x4 + 0x4028)
+#define SECURE_SCRU_CLKGATE_CON_CNT 6
+#define SECURE_SCRU_SOFTRST_CON(i) ((i) * 0x4 + 0x4050)
+#define SECURE_SCRU_SOFTRST_CON_CNT 6
+#define SECURE_SCRU_MODE_CON 0x4280
+
+/* SYSGRF */
+#define SYSGRF_SOC_CON(i) ((i) * 4)
+#define SYSGRF_SOC_STATUS 0x30
+#define SYSGRF_NOC_CON(i) (0x40 + (i) * 4)
+#define SYSGRF_NOC_STATUS(i) (0x60 + (i) * 4)
+#define SYSGRF_MEM_CON(i) (0x80 + (i) * 4)
+#define SYSGRF_STATUS0 0x140
+#define SYSGRF_STATUS1 0x144
+
+/* COREGRF */
+#define COREGRF_SOC_STATUS(i) (0x2c + (i) * 4)
+#define COREGRF_CPU_CON(i) (0x34 + (i) * 4)
+
+/* DDRGRF */
+#define DDRGRF_CHA_CON(i) ((i) * 4)
+#define DDRGRF_CHB_CON(i) (0x100 + (i) * 4)
+#define DDRGRF_CHA_ST(i) (0x60 + (i) * 4)
+#define DDRGRF_CHB_ST(i) (0xb0 + (i) * 4)
+#define DDRGRF_CON(i) (0x140 + (i) * 4)
+
+/* CCIGRF */
+#define CCIGRF_CON(i) ((i) * 4)
+#define CCIGRF_STATUS(i) (0x34 + (i) * 4)
+
+/* IOC */
+#define VCCIO_IOC_MISC_CON(i) (0x400 + (i) * 4)
+
+/* pvtm */
+#define PVTM_CON(i) (0x4 + (i) * 4)
+#define PVTM_INTEN 0x70
+#define PVTM_INTSTS 0x74
+#define PVTM_STATUS(i) (0x80 + (i) * 4)
+#define PVTM_CALC_CNT 0x200
+
+enum pvtm_con0 {
+ pvtm_start = 0,
+ pvtm_osc_en = 1,
+ pvtm_osc_sel = 2,
+ pvtm_rnd_seed_en = 5,
+};
+
+/* WDT */
+#define WDT_CR 0x0
+#define WDT_TORR 0x4
+#define WDT_CCVR 0x8
+#define WDT_CRR 0xc
+#define WDT_STAT 0x10
+#define WDT_EOI 0x14
+
+#define WDT_EN BIT(0)
+#define WDT_RSP_MODE BIT(1)
+
+/* timer */
+#define TIMER_LOAD_COUNT0 0x00
+#define TIMER_LOAD_COUNT1 0x04
+#define TIMER_CURRENT_VALUE0 0x08
+#define TIMER_CURRENT_VALUE1 0x0c
+#define TIMER_CONTROL_REG 0x10
+#define TIMER_INTSTATUS 0x18
+
+#define TIMER_DIS 0x0
+#define TIMER_EN 0x1
+
+#define TIMER_FMODE (0x0 << 1)
+#define TIMER_RMODE (0x1 << 1)
+
+/* hp timer */
+#define TIMER_HP_REVISION 0x00
+#define TIMER_HP_CTRL 0x04
+#define TIMER_HP_INTR_EN 0x08
+#define TIMER_HP_T24_GCD 0x0c
+#define TIMER_HP_T32_GCD 0x10
+#define TIMER_HP_LOAD_COUNT0 0x14
+#define TIMER_HP_LOAD_COUNT1 0x18
+#define TIMER_HP_T24_DELAT_COUNT0 0x1c
+#define TIMER_HP_T24_DELAT_COUNT1 0x20
+#define TIMER_HP_CURR_32K_VALUE0 0x24
+#define TIMER_HP_CURR_32K_VALUE1 0x28
+#define TIMER_HP_CURR_TIMER_VALUE0 0x2c
+#define TIMER_HP_CURR_TIMER_VALUE1 0x30
+#define TIMER_HP_T24_32BEGIN0 0x34
+#define TIMER_HP_T24_32BEGIN1 0x38
+#define TIMER_HP_T32_24END0 0x3c
+#define TIMER_HP_T32_24END1 0x40
+#define TIMER_HP_BEGIN_END_VALID 0x44
+#define TIMER_HP_SYNC_REQ 0x48
+#define TIMER_HP_INTR_STATUS 0x4c
+#define TIMER_HP_UPD_EN 0x50
+
+ /* GPIO */
+#define GPIO_SWPORT_DR_L 0x0000
+#define GPIO_SWPORT_DR_H 0x0004
+#define GPIO_SWPORT_DDR_L 0x0008
+#define GPIO_SWPORT_DDR_H 0x000c
+#define GPIO_INT_EN_L 0x0010
+#define GPIO_INT_EN_H 0x0014
+#define GPIO_INT_MASK_L 0x0018
+#define GPIO_INT_MASK_H 0x001c
+#define GPIO_INT_TYPE_L 0x0020
+#define GPIO_INT_TYPE_H 0x0024
+#define GPIO_INT_POLARITY_L 0x0028
+#define GPIO_INT_POLARITY_H 0x002c
+#define GPIO_INT_BOTHEDGE_L 0x0030
+#define GPIO_INT_BOTHEDGE_H 0x0034
+#define GPIO_DEBOUNCE_L 0x0038
+#define GPIO_DEBOUNCE_H 0x003c
+#define GPIO_DBCLK_DIV_EN_L 0x0040
+#define GPIO_DBCLK_DIV_EN_H 0x0044
+#define GPIO_DBCLK_DIV_CON 0x0048
+#define GPIO_INT_STATUS 0x0050
+#define GPIO_INT_RAWSTATUS 0x0058
+#define GPIO_PORT_EOI_L 0x0060
+#define GPIO_PORT_EOI_H 0x0064
+#define GPIO_EXT_PORT 0x0070
+#define GPIO_VER_ID 0x0078
+#define GPIO_STORE_ST_L 0x0080
+#define GPIO_STORE_ST_H 0x0084
+#define GPIO_REG_GROUP_L 0x0100
+#define GPIO_REG_GROUP_H 0x0104
+#define GPIO_VIRTUAL_EN 0x0108
+#define GPIO_REG_GROUP1_L 0x0110
+#define GPIO_REG_GROUP1_H 0x0114
+#define GPIO_REG_GROUP2_L 0x0118
+#define GPIO_REG_GROUP2_H 0x011c
+#define GPIO_REG_GROUP3_L 0x0120
+#define GPIO_REG_GROUP3_H 0x0124
+
+/* PWM */
+#define PMW_PWRCAPTURE_VAL 0x15c
+
+#define SOC_RK3576A1 0x35760101
+#define SOC_RK3576J1 0x35760a01
+#define SOC_RK3576M1 0x35760d01
+#define SOC_RK3576S1 0x35761301
+#define SOC_UNKNOWN 0xeeee
+#define SOC_ROOT 0x0
+
+int rk_soc_is_(uint32_t soc_id);
+uint32_t timer_hp_get_freq(void);
+int soc_bus_div_sip_handler(uint32_t id, uint32_t cfg, uint32_t enable_msk);
+void autocs_suspend(void);
+void autocs_resume(void);
+
+#endif /* __SOC_H__ */
diff --git a/plat/rockchip/rk3576/include/plat.ld.S b/plat/rockchip/rk3576/include/plat.ld.S
new file mode 100644
index 0000000..4d0096f
--- /dev/null
+++ b/plat/rockchip/rk3576/include/plat.ld.S
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#ifndef ROCKCHIP_PLAT_LD_S
+#define ROCKCHIP_PLAT_LD_S
+
+MEMORY {
+ PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE
+}
+
+SECTIONS
+{
+ . = PMUSRAM_BASE;
+
+ /*
+ * pmu_cpuson_entrypoint request address
+ * align 64K when resume, so put it in the
+ * start of pmusram
+ */
+ .text_pmusram : {
+ ASSERT(. == ALIGN(64 * 1024),
+ ".pmusram.entry request 64K aligned.");
+ KEEP(*(.pmusram.entry))
+ __bl31_pmusram_text_start = .;
+ *(.pmusram.text)
+ *(.pmusram.rodata)
+ . = ALIGN(PAGE_SIZE);
+ __bl31_pmusram_text_end = .;
+ __bl31_pmusram_data_start = .;
+ *(.pmusram.data)
+ . = ALIGN(PAGE_SIZE);
+ __bl31_pmusram_data_end = .;
+
+ ASSERT(__bl31_pmusram_data_end <= PMUSRAM_BASE + PMUSRAM_RSIZE,
+ ".pmusram has exceeded its limit.");
+ } >PMUSRAM
+}
+#endif /* ROCKCHIP_PLAT_LD_S */
diff --git a/plat/rockchip/rk3576/include/plat_sip_calls.h b/plat/rockchip/rk3576/include/plat_sip_calls.h
new file mode 100644
index 0000000..c33f24f
--- /dev/null
+++ b/plat/rockchip/rk3576/include/plat_sip_calls.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#ifndef __PLAT_SIP_CALLS_H__
+#define __PLAT_SIP_CALLS_H__
+
+#define RK_PLAT_SIP_NUM_CALLS 0
+
+#endif /* __PLAT_SIP_CALLS_H__ */
diff --git a/plat/rockchip/rk3576/include/platform_def.h b/plat/rockchip/rk3576/include/platform_def.h
new file mode 100644
index 0000000..03a80b0
--- /dev/null
+++ b/plat/rockchip/rk3576/include/platform_def.h
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#include <arch.h>
+#include <common_def.h>
+#include <rk3576_def.h>
+
+#define DEBUG_XLAT_TABLE 0
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Size of cacheable stacks */
+#if DEBUG_XLAT_TABLE
+#define PLATFORM_STACK_SIZE 0x800
+#elif IMAGE_BL1
+#define PLATFORM_STACK_SIZE 0x440
+#elif IMAGE_BL2
+#define PLATFORM_STACK_SIZE 0x400
+#elif IMAGE_BL31
+#define PLATFORM_STACK_SIZE 0x800
+#elif IMAGE_BL32
+#define PLATFORM_STACK_SIZE 0x440
+#endif
+
+#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
+
+#define PLATFORM_SYSTEM_COUNT 1
+#define PLATFORM_CLUSTER_COUNT 2
+#define PLATFORM_CLUSTER0_CORE_COUNT 4
+#define PLATFORM_CLUSTER1_CORE_COUNT 4
+#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \
+ PLATFORM_CLUSTER0_CORE_COUNT)
+
+#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \
+ PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
+
+#define PLAT_RK_CLST_TO_CPUID_SHIFT 6
+
+/*
+ * This macro defines the deepest retention state possible. A higher state
+ * id will represent an invalid or a power down state.
+ */
+#define PLAT_MAX_RET_STATE 1
+
+/*
+ * This macro defines the deepest power down states possible. Any state ID
+ * higher than this is invalid.
+ */
+#define PLAT_MAX_OFF_STATE 2
+/*******************************************************************************
+ * Platform memory map related constants
+ ******************************************************************************/
+/* TF txet, ro, rw, Size: 512KB */
+#define TZRAM_BASE RK_DRAM_BASE
+#define TZRAM_SIZE 0x100000
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+/*
+ * Put BL3-1 at the top of the Trusted RAM
+ */
+#define BL31_BASE (TZRAM_BASE + 0x40000)
+#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE)
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
+
+#define ADDR_SPACE_SIZE (1ULL << 32)
+#define MAX_XLAT_TABLES 18
+#define MAX_MMAP_REGIONS 27
+
+/*******************************************************************************
+ * Declarations and constants to access the mailboxes safely. Each mailbox is
+ * aligned on the biggest cache line size in the platform. This is known only
+ * to the platform as it might have a combination of integrated and external
+ * caches. Such alignment ensures that two maiboxes do not sit on the same cache
+ * line at any cache level. They could belong to different cpus/clusters &
+ * get written while being protected by different locks causing corruption of
+ * a valid mailbox address.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * Define GICD and GICC and GICR base
+ */
+#define PLAT_RK_GICD_BASE PLAT_GICD_BASE
+#define PLAT_RK_GICC_BASE PLAT_GICC_BASE
+#define PLAT_RK_GICR_BASE PLAT_GICR_BASE
+
+#define PLAT_RK_UART_BASE RK_DBG_UART_BASE
+#define PLAT_RK_UART_CLOCK RK_DBG_UART_CLOCK
+#define PLAT_RK_UART_BAUDRATE RK_DBG_UART_BAUDRATE
+
+#define PLAT_RK_PRIMARY_CPU 0x0
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/rockchip/rk3576/plat_sip_calls.c b/plat/rockchip/rk3576/plat_sip_calls.c
new file mode 100644
index 0000000..b0ff5fb
--- /dev/null
+++ b/plat/rockchip/rk3576/plat_sip_calls.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <drivers/scmi-msg.h>
+
+#include <plat_sip_calls.h>
+#include <rockchip_sip_svc.h>
+
+uintptr_t rockchip_plat_sip_handler(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ switch (smc_fid) {
+ case RK_SIP_SCMI_AGENT0:
+ scmi_smt_fastcall_smc_entry(0);
+ SMC_RET1(handle, 0);
+
+ default:
+ ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
+ SMC_RET1(handle, SMC_UNK);
+ }
+}
diff --git a/plat/rockchip/rk3576/platform.mk b/plat/rockchip/rk3576/platform.mk
new file mode 100644
index 0000000..861cb4f
--- /dev/null
+++ b/plat/rockchip/rk3576/platform.mk
@@ -0,0 +1,115 @@
+#
+# Copyright (c) 2025, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+RK_PLAT := plat/rockchip
+RK_PLAT_SOC := ${RK_PLAT}/${PLAT}
+RK_PLAT_COMMON := ${RK_PLAT}/common
+
+DISABLE_BIN_GENERATION := 1
+
+include drivers/arm/gic/v2/gicv2.mk
+include lib/libfdt/libfdt.mk
+include lib/xlat_tables_v2/xlat_tables.mk
+
+PLAT_INCLUDES := -Idrivers/arm/gic/common/ \
+ -Idrivers/arm/gic/v2/ \
+ -Idrivers/scmi-msg/ \
+ -Iinclude/bl31 \
+ -Iinclude/common \
+ -Iinclude/drivers \
+ -Iinclude/drivers/arm \
+ -Iinclude/drivers/io \
+ -Iinclude/drivers/ti/uart \
+ -Iinclude/lib \
+ -Iinclude/lib/cpus/${ARCH} \
+ -Iinclude/lib/el3_runtime \
+ -Iinclude/lib/psci \
+ -Iinclude/plat/common \
+ -Iinclude/services \
+ -I${RK_PLAT_COMMON}/ \
+ -I${RK_PLAT_COMMON}/pmusram/ \
+ -I${RK_PLAT_COMMON}/include/ \
+ -I${RK_PLAT_COMMON}/drivers/pmu/ \
+ -I${RK_PLAT_COMMON}/drivers/parameter/ \
+ -I${RK_PLAT_COMMON}/scmi/ \
+ -I${RK_PLAT_SOC}/ \
+ -I${RK_PLAT_SOC}/drivers/dmc/ \
+ -I${RK_PLAT_SOC}/drivers/pmu/ \
+ -I${RK_PLAT_SOC}/drivers/secure/ \
+ -I${RK_PLAT_SOC}/drivers/soc/ \
+ -I${RK_PLAT_SOC}/include/ \
+ -I${RK_PLAT_SOC}/scmi/
+
+RK_GIC_SOURCES := ${GICV2_SOURCES} \
+ plat/common/plat_gicv2.c \
+ ${RK_PLAT}/common/rockchip_gicv2.c
+
+PLAT_BL_COMMON_SOURCES := ${XLAT_TABLES_LIB_SRCS} \
+ common/desc_image_load.c \
+ lib/bl_aux_params/bl_aux_params.c \
+ plat/common/aarch64/crash_console_helpers.S \
+ plat/common/plat_psci_common.c
+
+ifneq (${ENABLE_STACK_PROTECTOR},0)
+PLAT_BL_COMMON_SOURCES += ${RK_PLAT_COMMON}/rockchip_stack_protector.c
+endif
+
+BL31_SOURCES += ${RK_GIC_SOURCES} \
+ drivers/arm/cci/cci.c \
+ drivers/ti/uart/aarch64/16550_console.S \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ drivers/scmi-msg/base.c \
+ drivers/scmi-msg/clock.c \
+ drivers/scmi-msg/entry.c \
+ drivers/scmi-msg/reset_domain.c \
+ drivers/scmi-msg/smt.c \
+ lib/cpus/aarch64/cortex_a53.S \
+ lib/cpus/aarch64/cortex_a72.S \
+ $(LIBFDT_SRCS) \
+ ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \
+ ${RK_PLAT_COMMON}/aarch64/platform_common.c \
+ ${RK_PLAT_COMMON}/bl31_plat_setup.c \
+ ${RK_PLAT_COMMON}/plat_pm.c \
+ ${RK_PLAT_COMMON}/plat_pm_helpers.c \
+ ${RK_PLAT_COMMON}/plat_topology.c \
+ ${RK_PLAT_COMMON}/rockchip_sip_svc.c \
+ ${RK_PLAT_COMMON}/params_setup.c \
+ ${RK_PLAT_COMMON}/pmusram/cpus_on_fixed_addr.S \
+ ${RK_PLAT_COMMON}/rockchip_sip_svc.c \
+ ${RK_PLAT_COMMON}/scmi/rockchip_common_clock.c \
+ ${RK_PLAT_COMMON}/scmi/scmi.c \
+ ${RK_PLAT_COMMON}/scmi/scmi_clock.c \
+ ${RK_PLAT_COMMON}/scmi/scmi_rstd.c \
+ ${RK_PLAT_SOC}/scmi/rk3576_clk.c \
+ ${RK_PLAT_SOC}/plat_sip_calls.c \
+ ${RK_PLAT_SOC}/drivers/dmc/suspend.c \
+ ${RK_PLAT_SOC}/drivers/pmu/pmu.c \
+ ${RK_PLAT_SOC}/drivers/pmu/pm_pd_regs.c \
+ ${RK_PLAT_SOC}/drivers/secure/firewall.c \
+ ${RK_PLAT_SOC}/drivers/secure/secure.c \
+ ${RK_PLAT_SOC}/drivers/soc/soc.c
+
+# Enable workarounds for selected Cortex-A53 errata
+ERRATA_A53_835769 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 1
+ERRATA_A53_1530924 := 1
+
+ERRATA_A72_1319367 := 1
+
+ENABLE_PLAT_COMPAT := 0
+MULTI_CONSOLE_API := 1
+CTX_INCLUDE_EL2_REGS := 0
+GICV2_G0_FOR_EL3 := 1
+CTX_INCLUDE_AARCH32_REGS := 0
+
+# Do not enable SVE
+ENABLE_SVE_FOR_NS := 0
+
+WORKAROUND_CVE_2017_5715 := 0
+
+$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
diff --git a/plat/rockchip/rk3576/rk3576_def.h b/plat/rockchip/rk3576/rk3576_def.h
new file mode 100644
index 0000000..35f38ca
--- /dev/null
+++ b/plat/rockchip/rk3576/rk3576_def.h
@@ -0,0 +1,207 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#ifndef __PLAT_DEF_H__
+#define __PLAT_DEF_H__
+
+#define SIZE_K(n) ((n) * 1024)
+#define SIZE_M(n) ((n) * 1024 * 1024)
+
+#define WITH_16BITS_WMSK(bits) (0xffff0000 | (bits))
+#define BITS_WMSK(msk, shift) ((msk) << ((shift) + REG_MSK_SHIFT))
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+
+#define RK3576_DEV_RNG0_BASE 0x00000000
+#define RK3576_DEV_RNG0_SIZE 0x40000000
+
+#define RK_DRAM_BASE 0x40000000
+
+/* All slave base address declare below */
+#define MCU_TCM_BASE 0x23800000
+#define MCU_CACHE_BASE 0x23810000
+#define MCU_RAM_TEST_BASE 0x23820000
+#define MCU_BOOT_BASE 0x00000000
+#define MCU_MAIN_BASE 0x00010000
+#define PMU0SGRF_BASE 0x26000000
+#define PMU1SGRF_BASE 0x26002000
+#define PMU1SGRF_FW_BASE 0x26003000
+#define SYS_SGRF_BASE 0x26004000
+#define SYS_SGRF_FW_BASE 0x26005000
+#define SYS_GRF_BASE 0x2600a000
+#define BIGCORE_GRF_BASE 0x2600c000
+#define LITCORE_GRF_BASE 0x2600e000
+#define CCI_GRF_BASE 0x26010000
+#define DDR_GRF_BASE 0x26012000
+#define CENTER_GRF_BASE 0x26014000
+#define GPUGRF_BASE 0x26016000
+#define NPUGRF_BASE 0x26018000
+#define VO_GRF_BASE 0x2601a000
+#define VI_GRF_BASE 0x2601c000
+#define USB_GRF_BASE 0x2601e000
+#define PHP_GRF_BASE 0x26020000
+#define VOP_GRF_BASE 0x26022000
+#define PMU0_GRF_BASE 0x26024000
+#define PMU1_GRF_BASE 0x26026000
+#define USBDPPHY_GRF_BASE 0x2602c000
+#define USB2PHY0_GRF_BASE 0x2602e000
+#define USB2PHY1_GRF_BASE 0x26030000
+#define PMU0_IOC_BASE 0x26040000
+#define PMU1_IOC_BASE 0x26042000
+#define TOP_IOC_BASE 0x26044000
+#define VCCIO_IOC_BASE 0x26046000
+#define VCCIO6_IOC_BASE 0x2604a000
+#define VCCIO7_IOC_BASE 0x2604b000
+#define CRU_BASE 0x27200000
+#define PHP_CRU_BASE 0x27208000
+#define SECURE_CRU_BASE 0x27210000
+#define PMU1_CRU_BASE 0x27220000
+#define DDRPHY0_CRU_BASE 0x27228000
+#define DDRPHY1_CRU_BASE 0x27230000
+#define BIGCORE_CRU_BASE 0x27238000
+#define LITTLE_CRU_BASE 0x27240000
+#define CCI_CRU_BASE 0x27248000
+#define PVTPLL_CCI_BASE 0x27250000
+#define PVTPLL_BIGCORE_BASE 0x27258000
+#define PVTPLL_LITCORE_BASE 0x27260000
+#define PVTPLL_GPU_BASE 0x27268000
+#define PVTPLL_NPU_BASE 0x27270000
+#define PVTPLL_CRU_BASE 0x27278000
+#define I2C0_BASE 0x27300000
+#define UART1_BASE 0x27310000
+#define GPIO0_BASE 0x27320000
+#define PWM0_BASE 0x27330000
+#define WDT_PMU_BASE 0x27340000
+#define TIMER_PMU_BASE 0x27350000
+#define PMU_BASE 0x27360000
+#define PMU0_BASE 0x27360000
+#define PMU1_BASE 0x27370000
+#define PMU2_BASE 0x27380000
+#define PVTM_PMU_BASE 0x273f0000
+#define HPTIMER_BASE 0x27400000
+#define CCI_BASE 0x27500000
+#define VOP_BASE 0x27d00000
+#define INTERCONNECT_BASE 0x27f00000
+#define FW_CCI2DDR_BASE 0x27f80000
+#define FW_CENTER2DDR_BASE 0x27f90000
+#define FW_SYSMEM_BASE 0x27fa0000
+#define FW_VOP2DDR_BASE 0x27fb0000
+#define FW_CBUF_BASE 0x27fc0000
+#define FIREWALL_DDR_BASE 0x27f80000
+#define DDRCTL0_BASE 0x28000000
+#define DDRCTL1_BASE 0x29000000
+#define DDR_MONITOR0_BASE 0x2a000000
+#define DDR_MONITOR1_BASE 0x2a010000
+#define DDRPHY0_BASE 0x2a020000
+#define DDRPHY1_BASE 0x2a030000
+#define HWLP0_BASE 0x2a060000
+#define HWLP1_BASE 0x2a070000
+#define KEYLADDER_BASE 0x2a420000
+#define CRYPTO_S_BASE 0x2a430000
+#define OTP_S_BASE 0x2a480000
+#define DCF_BASE 0x2a490000
+#define STIMER0_BASE 0x2a4a0000
+#define STIMER1_BASE 0x2a4b0000
+#define WDT_S_BASE 0x2a4c0000
+#define OTP_MASK_BASE 0x2a4d0000
+#define OTP_NS_BASE 0x2a580000
+#define GIC400_BASE 0x2a700000
+#define I2C1_BASE 0x2ac40000
+#define NSTIMER0_BASE 0x2acc0000
+#define NSTIMER1_BASE 0x2acd0000
+#define WDT_NS_BASE 0x2ace0000
+#define UART0_BASE 0x2ad40000
+#define UART2_BASE 0x2ad50000
+#define UART3_BASE 0x2ad60000
+#define UART4_BASE 0x2ad70000
+#define UART5_BASE 0x2ad80000
+#define UART6_BASE 0x2ad90000
+#define UART7_BASE 0x2ada0000
+#define UART8_BASE 0x2adb0000
+#define UART9_BASE 0x2adc0000
+#define PWM1_BASE 0x2add0000
+#define PWM2_BASE 0x2ade0000
+#define PWM3_BASE 0x2adf0000
+#define GPIO1_BASE 0x2ae10000
+#define GPIO2_BASE 0x2ae20000
+#define GPIO3_BASE 0x2ae30000
+#define GPIO4_BASE 0x2ae40000
+#define TSADC_BASE 0x2ae70000
+
+#define PMUSRAM_BASE 0x3fe70000
+#define PMUSRAM_RSIZE SIZE_K(32)
+
+#define CBUF_BASE 0x3fe80000
+#define SRAM_BASE 0x3ff80000
+
+#define STIMER0_CHN_BASE(i) (STIMER0_BASE + 0x1000 * (i))
+#define STIMER1_CHN_BASE(i) (STIMER1_BASE + 0x1000 * (i))
+
+#define NSTIMER0_CHN_BASE(i) (NSTIMER0_BASE + 0x1000 * (i))
+#define NSTIMER1_CHN_BASE(i) (NSTIMER1_BASE + 0x1000 * (i))
+
+#define DDRPHY_BASE_CH(n) (DDRPHY0_BASE + ((n) * 0x10000))
+#define DDRPHY_CRU_BASE_CH(n) (DDRPHY0_CRU_BASE + ((n) * 0x8000))
+#define UMCTL_BASE_CH(n) (DDRCTL0_BASE + ((n) * 0x1000000))
+#define HWLP_BASE_CH(n) (HWLP0_BASE + ((n) * 0x10000))
+#define MAILBOX1_BASE (0x2ae50000 + 0xb000)
+
+#define CRYPTO_S_BY_KEYLAD_BASE CRYPTO_S_BASE
+
+#define DDR_SHARE_MEM (RK_DRAM_BASE + SIZE_K(1024))
+#define DDR_SHARE_SIZE SIZE_K(64)
+
+#define SHARE_MEM_BASE DDR_SHARE_MEM
+#define SHARE_MEM_PAGE_NUM 15
+#define SHARE_MEM_SIZE SIZE_K(SHARE_MEM_PAGE_NUM * 4)
+
+#define SCMI_SHARE_MEM_BASE (SHARE_MEM_BASE + SHARE_MEM_SIZE)
+#define SCMI_SHARE_MEM_SIZE SIZE_K(4)
+
+#define SMT_BUFFER_BASE SCMI_SHARE_MEM_BASE
+#define SMT_BUFFER0_BASE SMT_BUFFER_BASE
+
+#define ROCKCHIP_PM_REG_REGION_MEM_SIZE SIZE_K(8)
+
+/******************************************************************************
+ * sgi, ppi
+ ******************************************************************************/
+#define RK_IRQ_SEC_PHY_TIMER 29
+
+#define RK_IRQ_SEC_SGI_0 8
+#define RK_IRQ_SEC_SGI_1 9
+#define RK_IRQ_SEC_SGI_2 10
+#define RK_IRQ_SEC_SGI_3 11
+#define RK_IRQ_SEC_SGI_4 12
+#define RK_IRQ_SEC_SGI_5 13
+#define RK_IRQ_SEC_SGI_6 14
+#define RK_IRQ_SEC_SGI_7 15
+
+/*
+ * Define a list of Group 0 interrupts.
+ */
+#define PLAT_RK_GICV2_G0_IRQS \
+ INTR_PROP_DESC(RK_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), \
+ INTR_PROP_DESC(RK_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \
+ GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL)
+
+/* UART related constants */
+#define RK_DBG_UART_BASE UART0_BASE
+#define RK_DBG_UART_BAUDRATE 1500000
+#define RK_DBG_UART_CLOCK 24000000
+
+/* Base rk_platform compatible GIC memory map */
+#define PLAT_GICD_BASE (GIC400_BASE + 0x1000)
+#define PLAT_GICC_BASE (GIC400_BASE + 0x2000)
+#define PLAT_GICR_BASE 0
+
+/* CCI */
+#define PLAT_RK_CCI_BASE CCI_BASE
+#define PLAT_RK_CCI_CLUSTER0_SL_IFACE_IX 1
+#define PLAT_RK_CCI_CLUSTER1_SL_IFACE_IX 2
+
+#endif /* __PLAT_DEF_H__ */
diff --git a/plat/rockchip/rk3576/scmi/rk3576_clk.c b/plat/rockchip/rk3576/scmi/rk3576_clk.c
new file mode 100644
index 0000000..7b36a05
--- /dev/null
+++ b/plat/rockchip/rk3576/scmi/rk3576_clk.c
@@ -0,0 +1,1353 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <drivers/delay_timer.h>
+#include <drivers/scmi.h>
+#include <lib/mmio.h>
+#include <lib/spinlock.h>
+#include <platform_def.h>
+
+#include <plat_private.h>
+#include <rk3576_clk.h>
+#include <rockchip_sip_svc.h>
+#include <scmi_clock.h>
+#include <soc.h>
+
+enum pll_type_sel {
+ PLL_SEL_AUTO, /* all plls (normal pll or pvtpll) */
+ PLL_SEL_PVT,
+ PLL_SEL_NOR,
+ PLL_SEL_AUTO_NOR /* all normal plls (apll/gpll/npll) */
+};
+
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+
+#define RK3576_PVTPLL_RING_EN 0x00
+#define RK3576_PVTPLL_RING0_LENGTH 0x04
+#define RK3576_PVTPLL_RING1_LENGTH 0x08
+#define RK3576_PVTPLL_RING2_LENGTH 0x0c
+#define RK3576_PVTPLL_RING3_LENGTH 0x10
+#define RK3576_PVTPLL_GCK_CFG 0x20
+#define RK3576_PVTPLL_GCK_LEN 0x24
+#define RK3576_PVTPLL_GCK_DIV 0x28
+#define RK3576_PVTPLL_GCK_CAL_CNT 0x2c
+#define RK3576_PVTPLL_GCK_REF_VAL 0x30
+#define RK3576_PVTPLL_GCK_CFG_VAL 0x34
+#define RK3576_PVTPLL_GCK_THR 0x38
+#define RK3576_PVTPLL_GFREE_CON 0x3c
+#define RK3576_PVTPLL_ADC_CFG 0x40
+#define RK3576_PVTPLL_ADC_CAL_CNT 0x48
+#define RK3576_PVTPLL_GCK_CNT 0x50
+#define RK3576_PVTPLL_GCK_CNT_AVG 0x54
+#define RK3576_PVTPLL_GCK_STATE 0x5c
+#define RK3576_PVTPLL_ADC_CNT 0x60
+#define RK3576_PVTPLL_ADC_CNT_AVG 0x68
+#define RK3576_PVTPLL_VERSION 0x70
+#define RK3576_PVTPLL_MAX_LENGTH 0x3f
+
+#define GPLL_RATE 1188000000
+#define CPLL_RATE 1000000000
+#define SPLL_RATE 702000000
+#define AUPLL_RATE 786431952
+
+#define MAX_RATE_TABLE 16
+
+#define CLKDIV_6BITS_SHF(div, shift) BITS_WITH_WMASK(div, 0x3fU, shift)
+#define CLKDIV_5BITS_SHF(div, shift) BITS_WITH_WMASK(div, 0x1fU, shift)
+#define CLKDIV_4BITS_SHF(div, shift) BITS_WITH_WMASK(div, 0xfU, shift)
+#define CLKDIV_3BITS_SHF(div, shift) BITS_WITH_WMASK(div, 0x7U, shift)
+#define CLKDIV_2BITS_SHF(div, shift) BITS_WITH_WMASK(div, 0x3U, shift)
+#define CLKDIV_1BITS_SHF(div, shift) BITS_WITH_WMASK(div, 0x1U, shift)
+
+#define CPU_PLL_PATH_SLOWMODE BITS_WITH_WMASK(0U, 0x3U, 0)
+#define CPU_PLL_PATH_NORMAL BITS_WITH_WMASK(1U, 0x3U, 0)
+#define CPU_PLL_PATH_DEEP_SLOW BITS_WITH_WMASK(2U, 0x3U, 0)
+
+#define CRU_PLL_POWER_DOWN BIT_WITH_WMSK(13)
+#define CRU_PLL_POWER_UP WMSK_BIT(13)
+
+/* clk_core:
+ * from normal pll(core_i: gpll or apll) path or direct pass from apll
+ */
+
+/* cpul clk path */
+#define CPUL_CLK_PATH_NOR_GPLL BITS_WITH_WMASK(1U, 0x3U, 12)
+#define CPUL_CLK_PATH_NOR_LPLL BITS_WITH_WMASK(0U, 0x3U, 12)
+#define CPUL_CLK_PATH_NOR_PVTPLL BITS_WITH_WMASK(2U, 0x3U, 12)
+
+#define CPUL_CLK_PATH_LPLL BITS_WITH_WMASK(0U, 0x3U, 6)
+#define CPUL_CLK_PATH_DIR_LPLL BITS_WITH_WMASK(2U, 0x3U, 6)
+#define CPUL_CLK_PATH_PVTPLL BITS_WITH_WMASK(1U, 0x3U, 6)
+
+#define CPUL_PVTPLL_PATH_DEEP_SLOW BITS_WITH_WMASK(0U, 0x1U, 13)
+#define CPUL_PVTPLL_PATH_PVTPLL BITS_WITH_WMASK(0x1, 0x1U, 13)
+
+/* cpub clk path */
+#define CPUB_CLK_PATH_NOR_GPLL BITS_WITH_WMASK(1U, 0x3U, 12)
+#define CPUB_CLK_PATH_NOR_BPLL BITS_WITH_WMASK(0U, 0x3U, 12)
+#define CPUB_CLK_PATH_NOR_PVTPLL BITS_WITH_WMASK(2U, 0x3U, 12)
+
+#define CPUB_CLK_PATH_BPLL BITS_WITH_WMASK(0U, 0x3U, 14)
+#define CPUB_CLK_PATH_DIR_BPLL BITS_WITH_WMASK(2U, 0x3U, 14)
+#define CPUB_CLK_PATH_PVTPLL BITS_WITH_WMASK(1U, 0x3U, 14)
+
+#define CPUB_PVTPLL_PATH_DEEP_SLOW BITS_WITH_WMASK(0U, 0x1U, 5)
+#define CPUB_PVTPLL_PATH_PVTPLL BITS_WITH_WMASK(0x1, 0x1U, 5)
+
+#define CPUB_PCLK_PATH_100M BITS_WITH_WMASK(0U, 0x3U, 0)
+#define CPUB_PCLK_PATH_50M BITS_WITH_WMASK(1U, 0x3U, 0)
+#define CPUB_PCLK_PATH_24M BITS_WITH_WMASK(2U, 0x3U, 0)
+
+/* cci clk path */
+#define SCLK_CCI_PATH_XIN BITS_WITH_WMASK(0U, 0x3U, 12)
+#define SCLK_CCI_PATH_PVTPLL BITS_WITH_WMASK(1U, 0x3U, 12)
+#define SCLK_CCI_PATH_NOR_LPLL BITS_WITH_WMASK(3U, 0x3U, 12)
+#define SCLK_CCI_PATH_NOR_GPLL BITS_WITH_WMASK(2U, 0x3U, 12)
+
+#define CCI_PVTPLL_PATH_DEEP_SLOW BITS_WITH_WMASK(0U, 0x1U, 14)
+#define CCI_PVTPLL_PATH_PVTPLL BITS_WITH_WMASK(1U, 0x1U, 14)
+
+/* npu clk path */
+#define NPU_CLK_PATH_NOR_GPLL BITS_WITH_WMASK(0U, 0x7U, 7)
+#define NPU_CLK_PATH_NOR_CPLL BITS_WITH_WMASK(1U, 0x7U, 7)
+#define NPU_CLK_PATH_NOR_AUPLL BITS_WITH_WMASK(2U, 0x7U, 7)
+#define NPU_CLK_PATH_NOR_SPLL BITS_WITH_WMASK(3U, 0x7U, 7)
+
+#define NPU_CLK_PATH_NOR_PLL WMSK_BIT(15)
+#define NPU_CLK_PATH_PVTPLL BIT_WITH_WMSK(15)
+#define NPU_PVTPLL_PATH_DEEP_SLOW BITS_WITH_WMASK(0U, 0x1U, 9)
+#define NPU_PVTPLL_PATH_PVTPLL BITS_WITH_WMASK(1U, 0x1U, 9)
+
+/* gpu clk path */
+#define GPU_CLK_PATH_NOR_GPLL BITS_WITH_WMASK(0U, 0x7U, 5)
+#define GPU_CLK_PATH_NOR_CPLL BITS_WITH_WMASK(1U, 0x7U, 5)
+#define GPU_CLK_PATH_NOR_AUPLL BITS_WITH_WMASK(2U, 0x7U, 5)
+#define GPU_CLK_PATH_NOR_SPLL BITS_WITH_WMASK(3U, 0x7U, 5)
+#define GPU_CLK_PATH_NOR_LPLL BITS_WITH_WMASK(4U, 0x7U, 5)
+#define GPU_CLK_PATH_NOR_PLL WMSK_BIT(8)
+#define GPU_CLK_PATH_PVTPLL BIT_WITH_WMSK(8)
+#define GPU_PVTPLL_PATH_DEEP_SLOW BITS_WITH_WMASK(0U, 0x1U, 9)
+#define GPU_PVTPLL_PATH_PVTPLL BITS_WITH_WMASK(1U, 0x1U, 9)
+
+#define PVTPLL_NEED(type, length) (((type) == PLL_SEL_PVT || \
+ (type) == PLL_SEL_AUTO) && \
+ (length))
+/*
+ * [0]: set intermediate rate
+ * [1]: scaling up rate or scaling down rate
+ * [1]: add length for pvtpll
+ * [2:5]: length
+ * [2]: use low length for pvtpll
+ * [3:5]: reserved
+ */
+#define OPP_RATE_MASK 0x3f
+#define OPP_INTERMEDIATE_RATE BIT(0)
+#define OPP_SCALING_UP_RATE BIT(1)
+#define OPP_ADD_LENGTH BIT(1)
+#define OPP_LENGTH_MASK GENMASK_32(5, 2)
+#define OPP_LENGTH_SHIFT 2
+#define OPP_LENGTH_LOW BIT(2)
+
+#define PRATE(x) static const unsigned long const x[]
+#define PINFO(x) static const uint32_t const x[]
+
+PRATE(p_24m) = { OSC_HZ };
+PRATE(p_100m_24m) = { 100 * MHz, OSC_HZ };
+PRATE(p_350m_175m_116m_24m) = { 350 * MHz, 175 * MHz, 116 * MHz, OSC_HZ };
+PRATE(p_175m_116m_58m_24m) = { 175 * MHz, 116 * MHz, 58 * MHz, OSC_HZ };
+PRATE(p_116m_58m_24m) = { 116 * MHz, 58 * MHz, OSC_HZ };
+PRATE(p_pclk_secure_s) = { PCLK_SECURE_S };
+PRATE(p_hclk_secure_s) = { HCLK_SECURE_S };
+PRATE(p_aclk_secure_s) = { ACLK_SECURE_S };
+PRATE(p_hclk_vo0_s) = { HCLK_VO0_S };
+PRATE(p_pclk_vo0_s) = { PCLK_VO0_S };
+PRATE(p_hclk_vo1_s) = { HCLK_VO1_S };
+PRATE(p_pclk_vo1_s) = { PCLK_VO1_S };
+
+PINFO(clk_stimer0_root_info) = { 0x27214004, 6, 1, 0, 0, 0, 0x27214028, 9 };
+PINFO(clk_stimer1_root_info) = { 0x27214004, 7, 1, 0, 0, 0, 0x2721402c, 1 };
+PINFO(pclk_secure_s_info) = { 0x27214004, 4, 2, 0, 0, 0, 0x27214028, 2 };
+PINFO(hclk_secure_s_info) = { 0x27214004, 2, 2, 0, 0, 0, 0x27214028, 1 };
+PINFO(aclk_secure_s_info) = { 0x27214004, 0, 2, 0, 0, 0, 0x27214028, 0 };
+PINFO(clk_pka_crypto_s_info) = { 0x27214004, 11, 2, 0, 0, 0, 0x27214030, 11 };
+PINFO(hclk_vo1_s_info) = { 0x27214010, 0, 2, 0, 0, 0, 0x27214038, 1 };
+PINFO(pclk_vo1_s_info) = { 0x27214010, 2, 2, 0, 0, 0, 0x27214038, 4 };
+PINFO(hclk_vo0_s_info) = { 0x27214018, 0, 2, 0, 0, 0, 0x2721403c, 1 };
+PINFO(pclk_vo0_s_info) = { 0x27214018, 2, 2, 0, 0, 0, 0x2721403c, 4 };
+PINFO(pclk_klad_info) = { 0, 0, 0, 0, 0, 0, 0x27214030, 7 };
+PINFO(hclk_crypto_s_info) = { 0, 0, 0, 0, 0, 0, 0x27214030, 8 };
+PINFO(hclk_klad_info) = { 0, 0, 0, 0, 0, 0, 0x27214030, 9 };
+PINFO(aclk_crypto_s_info) = { 0, 0, 0, 0, 0, 0, 0x27214030, 12 };
+PINFO(hclk_trng_s_info) = { 0, 0, 0, 0, 0, 0, 0x27214034, 0 };
+PINFO(pclk_otpc_s_info) = { 0, 0, 0, 0, 0, 0, 0x27214034, 3 };
+PINFO(clk_otpc_s_info) = { 0, 0, 0, 0, 0, 0, 0x27214034, 4 };
+PINFO(pclk_wdt_s_info) = { 0, 0, 0, 0, 0, 0, 0x27214034, 9 };
+PINFO(tclk_wdt_s_info) = { 0, 0, 0, 0, 0, 0, 0x27214034, 10 };
+PINFO(pclk_hdcp1_trng_info) = { 0, 0, 0, 0, 0, 0, 0x27214038, 0 };
+PINFO(hclk_hdcp_key1_info) = { 0, 0, 0, 0, 0, 0, 0x27214038, 3 };
+PINFO(pclk_hdcp0_trng_info) = { 0, 0, 0, 0, 0, 0, 0x2721403c, 0 };
+PINFO(hclk_hdcp_key0_info) = { 0, 0, 0, 0, 0, 0, 0x2721403c, 3 };
+PINFO(pclk_edp_s_info) = { 0, 0, 0, 0, 0, 0, 0x2721403c, 5 };
+
+struct pvtpll_table {
+ unsigned int rate;
+ uint32_t length;
+ uint32_t length_frac;
+ uint32_t length_low;
+ uint32_t length_low_frac;
+ uint32_t ring_sel;
+ uint32_t volt_sel_thr;
+};
+
+struct sys_clk_info_t {
+ struct pvtpll_table *cpul_table;
+ struct pvtpll_table *cci_table;
+ struct pvtpll_table *cpub_table;
+ struct pvtpll_table *gpu_table;
+ struct pvtpll_table *npu_table;
+ unsigned int cpul_rate_count;
+ unsigned int cci_rate_count;
+ unsigned int cpub_rate_count;
+ unsigned int gpu_rate_count;
+ unsigned int npu_rate_count;
+ unsigned long cpul_rate;
+ unsigned long cci_rate;
+ unsigned long cpub_rate;
+ unsigned long gpu_rate;
+ unsigned long npu_rate;
+};
+
+struct otp_opp_info {
+ uint16_t min_freq;
+ uint16_t max_freq;
+ uint8_t volt;
+ uint8_t length;
+} __packed;
+
+#define RK3576_SCMI_CLOCK(_id, _name, _data, _table, _cnt, _is_s) \
+rk_scmi_clock_t _name = { \
+ .id = _id, \
+ .name = #_name, \
+ .clk_ops = _data, \
+ .rate_table = _table, \
+ .rate_cnt = _cnt, \
+ .is_security = _is_s, \
+}
+
+#define RK3576_SCMI_CLOCK_COM(_id, _name, _parent_table, _info, _data, \
+ _table, is_d, _is_s) \
+rk_scmi_clock_t _name = { \
+ .id = _id, \
+ .name = #_name, \
+ .parent_table = _parent_table, \
+ .info = _info, \
+ .clk_ops = _data, \
+ .rate_table = _table, \
+ .rate_cnt = ARRAY_SIZE(_table), \
+ .is_dynamic_prate = is_d, \
+ .is_security = _is_s, \
+}
+
+#define ROCKCHIP_PVTPLL(_rate, _sel, _len, _len_frac) \
+{ \
+ .rate = _rate##U, \
+ .ring_sel = _sel, \
+ .length = _len, \
+ .length_frac = _len_frac, \
+}
+
+static struct pvtpll_table rk3576_cpul_pvtpll_table[] = {
+ /* rate_hz, ring_sel, length, length_frac */
+ ROCKCHIP_PVTPLL(2016000000, 0, 6, 0),
+ ROCKCHIP_PVTPLL(1920000000, 0, 6, 1),
+ ROCKCHIP_PVTPLL(1800000000, 0, 6, 1),
+ ROCKCHIP_PVTPLL(1608000000, 0, 6, 1),
+ ROCKCHIP_PVTPLL(1416000000, 0, 8, 0),
+ ROCKCHIP_PVTPLL(1200000000, 0, 11, 0),
+ ROCKCHIP_PVTPLL(1008000000, 0, 17, 0),
+ ROCKCHIP_PVTPLL(816000000, 0, 26, 0),
+ ROCKCHIP_PVTPLL(600000000, 0, 0, 0),
+ ROCKCHIP_PVTPLL(408000000, 0, 0, 0),
+ { /* sentinel */ },
+};
+
+static struct pvtpll_table rk3576_cci_pvtpll_table[] = {
+ /* cpul_rate_hz, ring_sel, length, length_frac */
+ ROCKCHIP_PVTPLL(2016000000 / 2, 0, 27, 0),
+ ROCKCHIP_PVTPLL(1920000000 / 2, 0, 28, 0),
+ ROCKCHIP_PVTPLL(1800000000 / 2, 0, 28, 0),
+ ROCKCHIP_PVTPLL(1608000000 / 2, 0, 30, 0),
+ ROCKCHIP_PVTPLL(1416000000 / 2, 0, 34, 0),
+ ROCKCHIP_PVTPLL(1200000000 / 2, 0, 34, 0),
+ { /* sentinel */ },
+};
+
+static struct pvtpll_table rk3576_cpub_pvtpll_table[] = {
+ /* rate_hz, ring_sel, length, length_frac, length_low, length_low_frac */
+ ROCKCHIP_PVTPLL(2208000000, 0, 4, 3),
+ ROCKCHIP_PVTPLL(2112000000, 0, 5, 0),
+ ROCKCHIP_PVTPLL(2016000000, 0, 5, 0),
+ ROCKCHIP_PVTPLL(1800000000, 0, 5, 0),
+ ROCKCHIP_PVTPLL(1608000000, 0, 5, 0),
+ ROCKCHIP_PVTPLL(1416000000, 0, 7, 0),
+ ROCKCHIP_PVTPLL(1200000000, 0, 11, 0),
+ ROCKCHIP_PVTPLL(1008000000, 0, 17, 0),
+ ROCKCHIP_PVTPLL(816000000, 0, 26, 0),
+ ROCKCHIP_PVTPLL(600000000, 0, 0, 0),
+ ROCKCHIP_PVTPLL(408000000, 0, 0, 0),
+ { /* sentinel */ },
+};
+
+static struct pvtpll_table rk3576_gpu_pvtpll_table[] = {
+ /* rate_hz, ring_sel, length, length_frac, length_low, length_low_frac */
+ ROCKCHIP_PVTPLL(900000000, 0, 20, 0),
+ ROCKCHIP_PVTPLL(800000000, 0, 21, 0),
+ ROCKCHIP_PVTPLL(700000000, 0, 21, 0),
+ ROCKCHIP_PVTPLL(600000000, 0, 23, 0),
+ ROCKCHIP_PVTPLL(500000000, 0, 32, 0),
+ ROCKCHIP_PVTPLL(400000000, 0, 48, 0),
+ ROCKCHIP_PVTPLL(300000000, 0, 63, 0),
+ ROCKCHIP_PVTPLL(200000000, 0, 0, 0),
+ { /* sentinel */ },
+};
+
+static struct pvtpll_table rk3576_npu_pvtpll_table[] = {
+ /* rate_hz, ring_sel, length, length_frac, length_low, length_low_frac */
+ ROCKCHIP_PVTPLL(950000000, 0, 16, 0),
+ ROCKCHIP_PVTPLL(900000000, 0, 17, 0),
+ ROCKCHIP_PVTPLL(800000000, 0, 18, 0),
+ ROCKCHIP_PVTPLL(700000000, 0, 22, 0),
+ ROCKCHIP_PVTPLL(600000000, 0, 25, 0),
+ ROCKCHIP_PVTPLL(500000000, 0, 35, 0),
+ ROCKCHIP_PVTPLL(400000000, 0, 46, 0),
+ ROCKCHIP_PVTPLL(300000000, 0, 63, 0),
+ ROCKCHIP_PVTPLL(200000000, 0, 0, 0),
+ { /* sentinel */ },
+};
+
+static unsigned long rk3576_cpul_rates[] = {
+ 408000000, 600000000, 816000000, 1008000000,
+ 1200000000, 1416000000, 1608000000, 1800000000,
+ 2016000000, 2208000000, 2304000063
+};
+
+static unsigned long rk3576_cpub_rates[] = {
+ 408000000, 600000000, 816000000, 1008000000,
+ 1200000000, 1416000000, 1608000000, 1800000000,
+ 2016000000, 2208000000, 2304000000, 2400000063
+};
+
+static unsigned long rk3576_gpu_rates[] = {
+ 200000000, 300000000, 400000000, 500000000,
+ 600000000, 700000000, 800000000, 900000000,
+ 1000000063
+};
+
+static unsigned long rk3576_npu_rates[] = {
+ 200000000, 300000000, 400000000, 500000000,
+ 600000000, 700000000, 800000000, 900000000,
+ 1000000063
+};
+
+static unsigned long rk3576_common_rates[] = {
+ 400000, 24000000, 58000000, 100000000, 116000000, 175000000, 350000000,
+};
+
+static unsigned long rk3576_aclk_secure_s_rates[] = {
+ 116000000, 175000000, 350000000,
+};
+
+static int aclk_crypto_s_enable;
+static int aclk_klad_enable;
+static spinlock_t crypto_lock;
+static bool cpub_suspended;
+
+static struct sys_clk_info_t sys_clk_info;
+static int clk_scmi_cci_set_rate(rk_scmi_clock_t *clock, unsigned long rate);
+
+static struct pvtpll_table *rkclk_get_pvtpll_config(struct pvtpll_table *table,
+ unsigned int count,
+ unsigned int freq_hz)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if (freq_hz == table[i].rate)
+ return &table[i];
+ }
+ return NULL;
+}
+
+static int clk_scmi_set_low_length(struct pvtpll_table *pvtpll, unsigned int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if (pvtpll[i].length_low) {
+ pvtpll[i].length = pvtpll[i].length_low;
+ pvtpll[i].length_frac = pvtpll[i].length_low_frac;
+ }
+ }
+
+ return 0;
+}
+
+static int clk_cpul_set_rate(unsigned long rate, enum pll_type_sel type)
+{
+ struct pvtpll_table *pvtpll;
+ int div;
+
+ if (rate == 0)
+ return SCMI_INVALID_PARAMETERS;
+
+ pvtpll = rkclk_get_pvtpll_config(sys_clk_info.cpul_table,
+ sys_clk_info.cpul_rate_count, rate);
+ if (pvtpll == NULL)
+ return SCMI_INVALID_PARAMETERS;
+
+ /*
+ * |-\
+ * -----lpll-----| \
+ * | \ |-\
+ * -----gpll-----|mux|--litcore unclean src--[div]--[autocs]--| \
+ * | / | \
+ * --pvtpll src--| / --pvtpll src--|mux|--litcore--
+ * |-/ | /
+ * --litcore clean src--| /
+ * |-/
+ */
+ if (PVTPLL_NEED(type, pvtpll->length)) {
+ /* set ring sel and length */
+ mmio_write_32(PVTPLL_LITCORE_BASE + RK3576_PVTPLL_GCK_LEN,
+ 0x1dff0000 |
+ (pvtpll->ring_sel << 10) |
+ (pvtpll->length << 2) |
+ (pvtpll->length_frac));
+ /* set cal cnt = 24, T = 1us */
+ mmio_write_32(PVTPLL_LITCORE_BASE + RK3576_PVTPLL_GCK_CAL_CNT, 0x18);
+ /* enable pvtpll */
+ mmio_write_32(PVTPLL_LITCORE_BASE + RK3576_PVTPLL_GCK_CFG, 0x00220022);
+ /* start pvtpll */
+ mmio_write_32(PVTPLL_LITCORE_BASE + RK3576_PVTPLL_GCK_CFG, 0x00230023);
+
+ /* set pvtpll_src parent from 24MHz/32KHz to pvtpll */
+ mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(1),
+ CPUL_PVTPLL_PATH_PVTPLL);
+
+ /* set litcore unclean_src parent to pvtpll_src */
+ mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(0),
+ CPUL_CLK_PATH_NOR_PVTPLL);
+ /*
+ * set litcore parent from pvtpll_src to unclean_src,
+ * because autocs is on litcore unclean_src.
+ */
+ mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(1),
+ CPUL_CLK_PATH_LPLL);
+ /* set litcore unclean_src div to 0 */
+ mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(0),
+ CLKDIV_5BITS_SHF(0, 7));
+
+ return 0;
+ }
+ /* set litcore unclean_src div */
+ div = DIV_ROUND_UP(GPLL_RATE, rate) - 1;
+ mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(0),
+ CLKDIV_5BITS_SHF(div, 7));
+ /* set litcore unclean_src parent to gpll */
+ mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(0),
+ CPUL_CLK_PATH_NOR_GPLL);
+ /* set litcore parent to unclean_src */
+ mmio_write_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(1),
+ CPUL_CLK_PATH_LPLL);
+
+ return 0;
+}
+
+static int clk_scmi_cpul_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ int ret;
+
+ if (rate == 0)
+ return SCMI_INVALID_PARAMETERS;
+
+ ret = clk_cpul_set_rate(rate, PLL_SEL_AUTO);
+ if (ret == 0) {
+ sys_clk_info.cpul_rate = rate;
+ ret = clk_scmi_cci_set_rate(clock, rate / 2);
+ }
+
+ return ret;
+}
+
+static unsigned long rk3576_lpll_get_rate(void)
+{
+ unsigned int m, p, s, k;
+ uint64_t rate64 = 24000000, postdiv;
+ int mode;
+
+ mode = mmio_read_32(LITTLE_CRU_BASE + CRU_MODE_CON) &
+ 0x3;
+
+ if (mode == 0)
+ return rate64;
+
+ m = (mmio_read_32(CCI_CRU_BASE + CRU_PLL_CON(16)) >>
+ CRU_PLLCON0_M_SHIFT) &
+ CRU_PLLCON0_M_MASK;
+ p = (mmio_read_32(CCI_CRU_BASE + CRU_PLL_CON(17)) >>
+ CRU_PLLCON1_P_SHIFT) &
+ CRU_PLLCON1_P_MASK;
+ s = (mmio_read_32(CCI_CRU_BASE + CRU_PLL_CON(17)) >>
+ CRU_PLLCON1_S_SHIFT) &
+ CRU_PLLCON1_S_MASK;
+ k = (mmio_read_32(CCI_CRU_BASE + CRU_PLL_CON(18)) >>
+ CRU_PLLCON2_K_SHIFT) &
+ CRU_PLLCON2_K_MASK;
+
+ rate64 *= m;
+ rate64 = rate64 / p;
+
+ if (k != 0) {
+ /* fractional mode */
+ uint64_t frac_rate64 = 24000000 * k;
+
+ postdiv = p * 65536;
+ frac_rate64 = frac_rate64 / postdiv;
+ rate64 += frac_rate64;
+ }
+ rate64 = rate64 >> s;
+
+ return (unsigned long)rate64;
+}
+
+static unsigned long clk_scmi_cpul_get_rate(rk_scmi_clock_t *clock)
+{
+ int src, div;
+
+ src = mmio_read_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(1)) & 0x00c0;
+ src = src >> 6;
+ if (src == 1)
+ return sys_clk_info.cpul_rate;
+
+ src = mmio_read_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(0)) & 0x3000;
+ src = src >> 12;
+ div = mmio_read_32(LITTLE_CRU_BASE + LCORE_CRU_CLKSEL_CON(6)) & 0x0f80;
+ div = div >> 7;
+ switch (src) {
+ case 0:
+ return rk3576_lpll_get_rate();
+ case 1:
+ /* Make the return rate is equal to the set rate */
+ if (sys_clk_info.cpul_rate != 0)
+ return sys_clk_info.cpul_rate;
+ else
+ return GPLL_RATE / (div + 1);
+ case 2:
+ return sys_clk_info.cpul_rate;
+ default:
+ return 0;
+ }
+}
+
+static int clk_scmi_cpul_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ return 0;
+}
+
+static int clk_cpub_set_rate(unsigned long rate, enum pll_type_sel type)
+{
+ struct pvtpll_table *pvtpll;
+ int div;
+
+ if (rate == 0)
+ return SCMI_INVALID_PARAMETERS;
+
+ pvtpll = rkclk_get_pvtpll_config(sys_clk_info.cpub_table,
+ sys_clk_info.cpub_rate_count, rate);
+ if (pvtpll == NULL)
+ return SCMI_INVALID_PARAMETERS;
+
+ /*
+ * |-\
+ * -----bpll-----| \
+ * | \ |-\
+ * -----gpll-----|mux|--bigcore unclean src--[div]--[autocs]--| \
+ * | / | \
+ * --pvtpll src--| / --pvtpll src--|mux|--bigcore--
+ * |-/ | /
+ * --bigcore clean src--| /
+ * |-/
+ */
+ if (PVTPLL_NEED(type, pvtpll->length) != 0) {
+ /* set ring sel and length */
+ mmio_write_32(PVTPLL_BIGCORE_BASE + RK3576_PVTPLL_GCK_LEN,
+ 0x1dff0000 |
+ (pvtpll->ring_sel << 10) |
+ (pvtpll->length << 2) |
+ (pvtpll->length_frac));
+ /* set cal cnt = 24, T = 1us */
+ mmio_write_32(PVTPLL_BIGCORE_BASE + RK3576_PVTPLL_GCK_CAL_CNT, 0x18);
+ /* enable pvtpll */
+ mmio_write_32(PVTPLL_BIGCORE_BASE + RK3576_PVTPLL_GCK_CFG, 0x00220022);
+ /* start pvtpll */
+ mmio_write_32(PVTPLL_BIGCORE_BASE + RK3576_PVTPLL_GCK_CFG, 0x00230023);
+
+ /* set pvtpll_src parent from 24MHz/32KHz to pvtpll */
+ mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(2),
+ CPUB_PVTPLL_PATH_PVTPLL);
+
+ /* set bigcore unclean_src parent to pvtpll_src */
+ mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1),
+ CPUB_CLK_PATH_NOR_PVTPLL);
+ /*
+ * set bigcore parent from pvtpll_src to unclean_src,
+ * because autocs is on bigcore unclean_src.
+ */
+ mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1),
+ CPUB_CLK_PATH_BPLL);
+
+ /* set bigcore unclean_src div to 0 */
+ mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1),
+ CLKDIV_5BITS_SHF(0, 7));
+
+ return 0;
+ }
+
+ /* set bigcore unclean_src div */
+ div = DIV_ROUND_UP(GPLL_RATE, rate) - 1;
+ mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1),
+ CLKDIV_5BITS_SHF(div, 7));
+ /* set bigcore unclean_src parent to gpll */
+ mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1),
+ CPUB_CLK_PATH_NOR_GPLL);
+ /* set bigcore parent to unclean_src */
+ mmio_write_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1),
+ CPUB_CLK_PATH_BPLL);
+
+ return 0;
+}
+
+static int clk_scmi_cpub_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ int ret;
+
+ if (rate == 0)
+ return SCMI_INVALID_PARAMETERS;
+
+ if ((rate & OPP_LENGTH_LOW) != 0) {
+ clk_scmi_set_low_length(sys_clk_info.cpub_table,
+ sys_clk_info.cpub_rate_count);
+ return 0;
+ }
+
+ ret = clk_cpub_set_rate(rate, PLL_SEL_AUTO);
+ if (ret == 0)
+ sys_clk_info.cpub_rate = rate;
+
+ return ret;
+}
+
+static unsigned long rk3576_bpll_get_rate(void)
+{
+ unsigned int m, p, s, k;
+ uint64_t rate64 = 24000000, postdiv;
+ int mode;
+
+ mode = mmio_read_32(CRU_BASE + CRU_MODE_CON) &
+ 0x3;
+
+ if (mode == 0)
+ return rate64;
+
+ m = (mmio_read_32(CRU_BASE + CRU_PLL_CON(0)) >>
+ CRU_PLLCON0_M_SHIFT) &
+ CRU_PLLCON0_M_MASK;
+ p = (mmio_read_32(CRU_BASE + CRU_PLL_CON(1)) >>
+ CRU_PLLCON1_P_SHIFT) &
+ CRU_PLLCON1_P_MASK;
+ s = (mmio_read_32(CRU_BASE + CRU_PLL_CON(1)) >>
+ CRU_PLLCON1_S_SHIFT) &
+ CRU_PLLCON1_S_MASK;
+ k = (mmio_read_32(CRU_BASE + CRU_PLL_CON(2)) >>
+ CRU_PLLCON2_K_SHIFT) &
+ CRU_PLLCON2_K_MASK;
+
+ rate64 *= m;
+ rate64 = rate64 / p;
+
+ if (k != 0) {
+ /* fractional mode */
+ uint64_t frac_rate64 = 24000000 * k;
+
+ postdiv = p * 65536;
+ frac_rate64 = frac_rate64 / postdiv;
+ rate64 += frac_rate64;
+ }
+ rate64 = rate64 >> s;
+
+ return (unsigned long)rate64;
+}
+
+static unsigned long clk_scmi_cpub_get_rate(rk_scmi_clock_t *clock)
+{
+ int value, src, div;
+
+ if (cpub_suspended != 0)
+ return sys_clk_info.cpub_rate;
+
+ value = mmio_read_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1));
+ src = (value & 0xc000) >> 14;
+ if (src == 1)
+ return sys_clk_info.cpub_rate;
+
+ value = mmio_read_32(BIGCORE_CRU_BASE + BCORE_CRU_CLKSEL_CON(1));
+ src = (value & 0x3000) >> 12;
+ div = (value & 0x0f80) >> 7;
+ switch (src) {
+ case 0:
+ return rk3576_bpll_get_rate();
+ case 1:
+ /* Make the return rate is equal to the set rate */
+ if (sys_clk_info.cpub_rate != 0)
+ return sys_clk_info.cpub_rate;
+ else
+ return GPLL_RATE / (div + 1);
+ case 2:
+ return sys_clk_info.cpub_rate;
+ default:
+ return 0;
+ }
+}
+
+static int clk_scmi_cpub_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ return 0;
+}
+
+static unsigned long clk_scmi_cci_get_rate(rk_scmi_clock_t *clock)
+{
+ int src, div;
+
+ src = mmio_read_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4)) & 0x3000;
+ src = src >> 12;
+ if (src == 1)
+ return sys_clk_info.cci_rate;
+
+ div = mmio_read_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4)) & 0xf80;
+ div = div >> 7;
+ switch (src) {
+ case 0:
+ return OSC_HZ;
+ case 1:
+ return sys_clk_info.cci_rate;
+ case 2:
+ return GPLL_RATE / (div + 1);
+ case 3:
+ return rk3576_lpll_get_rate() / (div + 1);
+ default:
+ return 0;
+ }
+}
+
+static int clk_cci_set_rate(unsigned long rate, enum pll_type_sel type)
+{
+ struct pvtpll_table *pvtpll;
+ uint32_t pvtpll_en = 0;
+
+ if (rate == 0)
+ return SCMI_INVALID_PARAMETERS;
+
+ pvtpll = rkclk_get_pvtpll_config(sys_clk_info.cci_table,
+ sys_clk_info.cci_rate_count, rate);
+
+ /* set pvtpll */
+ if ((pvtpll != 0) && (PVTPLL_NEED(type, pvtpll->length) != 0)) {
+ /* set ring sel and length */
+ mmio_write_32(PVTPLL_CCI_BASE + RK3576_PVTPLL_GCK_LEN,
+ 0x1dff0000 |
+ (pvtpll->ring_sel << 10) |
+ (pvtpll->length << 2) |
+ (pvtpll->length_frac));
+ /* set cal cnt = 24, T = 1us */
+ mmio_write_32(PVTPLL_CCI_BASE + RK3576_PVTPLL_GCK_CAL_CNT, 0x18);
+ /* enable pvtpll */
+ pvtpll_en = mmio_read_32(PVTPLL_CCI_BASE + RK3576_PVTPLL_GCK_CFG);
+ if (pvtpll_en && 0x22 != 0x22)
+ mmio_write_32(PVTPLL_CCI_BASE + RK3576_PVTPLL_GCK_CFG, 0x00220022);
+ /* start pvtpll */
+ mmio_write_32(PVTPLL_CCI_BASE + RK3576_PVTPLL_GCK_CFG, 0x00230023);
+
+ /* set cci mux pvtpll */
+ mmio_write_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4),
+ CCI_PVTPLL_PATH_PVTPLL);
+ mmio_write_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4),
+ SCLK_CCI_PATH_PVTPLL);
+ mmio_write_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4),
+ CLKDIV_5BITS_SHF(0, 7));
+ sys_clk_info.cci_rate = rate;
+ return 0;
+ }
+ sys_clk_info.cci_rate = 594000000;
+ /* set cci div */
+ mmio_write_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4),
+ CLKDIV_5BITS_SHF(1, 7));
+ /* set cci mux gpll */
+ mmio_write_32(CCI_CRU_BASE + CCICRU_CLKSEL_CON(4),
+ SCLK_CCI_PATH_NOR_GPLL);
+
+ return 0;
+}
+
+static int clk_scmi_cci_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ if (rate == 0)
+ return SCMI_INVALID_PARAMETERS;
+
+ return clk_cci_set_rate(rate, PLL_SEL_AUTO);
+}
+
+static int clk_scmi_cci_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ return 0;
+}
+
+static unsigned long clk_scmi_gpu_get_rate(rk_scmi_clock_t *clock)
+{
+ int div, src;
+
+ if ((mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(165)) & 0x100) != 0)
+ return sys_clk_info.gpu_rate;
+
+ div = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(165)) & 0x1f;
+ src = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(165)) & 0x00e0;
+ src = src >> 5;
+ switch (src) {
+ case 0:
+ /* Make the return rate is equal to the set rate */
+ if (sys_clk_info.gpu_rate != 0)
+ return sys_clk_info.gpu_rate;
+ else
+ return GPLL_RATE / (div + 1);
+ case 1:
+ return CPLL_RATE / (div + 1);
+ case 2:
+ return AUPLL_RATE / (div + 1);
+ case 3:
+ return SPLL_RATE / (div + 1);
+ case 4:
+ return rk3576_lpll_get_rate() / (div + 1);
+ default:
+ return 0;
+ }
+}
+
+static int clk_gpu_set_rate(unsigned long rate, enum pll_type_sel type)
+{
+ struct pvtpll_table *pvtpll;
+ int div;
+
+ pvtpll = rkclk_get_pvtpll_config(sys_clk_info.gpu_table,
+ sys_clk_info.gpu_rate_count, rate);
+ if (pvtpll == NULL)
+ return SCMI_INVALID_PARAMETERS;
+
+ if (PVTPLL_NEED(type, pvtpll->length) != 0) {
+ /* set ring sel and length */
+ mmio_write_32(PVTPLL_GPU_BASE + RK3576_PVTPLL_GCK_LEN,
+ 0x1dff0000 |
+ (pvtpll->ring_sel << 10) |
+ (pvtpll->length << 2) |
+ (pvtpll->length_frac));
+ /* set cal cnt = 24, T = 1us */
+ mmio_write_32(PVTPLL_GPU_BASE + RK3576_PVTPLL_GCK_CAL_CNT, 0x18);
+ /* enable pvtpll */
+ mmio_write_32(PVTPLL_GPU_BASE + RK3576_PVTPLL_GCK_CFG, 0x00220022);
+ /* start pvtpll */
+ mmio_write_32(PVTPLL_GPU_BASE + RK3576_PVTPLL_GCK_CFG, 0x00230023);
+ /* set gpu mux pvtpll */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(165),
+ GPU_PVTPLL_PATH_PVTPLL);
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(165),
+ GPU_CLK_PATH_PVTPLL);
+ return 0;
+ }
+
+ /* set gpu div */
+ div = DIV_ROUND_UP(GPLL_RATE, rate);
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(165),
+ CLKDIV_5BITS_SHF(div - 1, 0));
+ /* set gpu mux gpll */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(165),
+ GPU_CLK_PATH_NOR_GPLL);
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(165),
+ GPU_CLK_PATH_NOR_PLL);
+
+ return 0;
+}
+
+static int clk_scmi_gpu_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ int ret;
+
+ if (rate == 0)
+ return SCMI_INVALID_PARAMETERS;
+
+ if ((rate & OPP_LENGTH_LOW) != 0) {
+ clk_scmi_set_low_length(sys_clk_info.gpu_table,
+ sys_clk_info.gpu_rate_count);
+ return 0;
+ }
+
+ ret = clk_gpu_set_rate(rate, PLL_SEL_AUTO);
+ if (ret == 0)
+ sys_clk_info.gpu_rate = rate;
+
+ return ret;
+}
+
+static int clk_scmi_gpu_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ return 0;
+}
+
+static unsigned long clk_scmi_npu_get_rate(rk_scmi_clock_t *clock)
+{
+ int div, src, div_src;
+
+ if ((mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(86)) & 0x8000) != 0)
+ return sys_clk_info.npu_rate;
+
+ div_src = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(86)) & 0x07c;
+ div_src = div_src >> 2;
+ src = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(86)) & 0x0180;
+ src = src >> 7;
+ div = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(86)) & 0x7c00;
+ div = div >> 10;
+ switch (src) {
+ case 0:
+ /* Make the return rate is equal to the set rate */
+ if (sys_clk_info.npu_rate != 0)
+ return sys_clk_info.npu_rate;
+ else
+ return GPLL_RATE / (div_src + 1) / (div + 1);
+ case 1:
+ return CPLL_RATE / (div_src + 1) / (div + 1);
+ case 2:
+ return AUPLL_RATE / (div_src + 1) / (div + 1);
+ case 3:
+ return SPLL_RATE / (div_src + 1) / (div + 1);
+ default:
+ return 0;
+ }
+}
+
+static int clk_npu_set_rate(unsigned long rate, enum pll_type_sel type)
+{
+ struct pvtpll_table *pvtpll;
+ int div;
+
+ pvtpll = rkclk_get_pvtpll_config(sys_clk_info.npu_table,
+ sys_clk_info.npu_rate_count, rate);
+ if (pvtpll == NULL)
+ return SCMI_INVALID_PARAMETERS;
+
+ if (PVTPLL_NEED(type, pvtpll->length) != 0) {
+ /* set ring sel and length */
+ mmio_write_32(PVTPLL_NPU_BASE + RK3576_PVTPLL_GCK_LEN,
+ 0x1dff0000 |
+ (pvtpll->ring_sel << 10) |
+ (pvtpll->length << 2) |
+ (pvtpll->length_frac));
+ /* set cal cnt = 24, T = 1us */
+ mmio_write_32(PVTPLL_NPU_BASE + RK3576_PVTPLL_GCK_CAL_CNT, 0x18);
+ /* enable pvtpll */
+ mmio_write_32(PVTPLL_NPU_BASE + RK3576_PVTPLL_GCK_CFG, 0x00220022);
+ /* start pvtpll */
+ mmio_write_32(PVTPLL_NPU_BASE + RK3576_PVTPLL_GCK_CFG, 0x00230023);
+ /* set npu mux pvtpll */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
+ NPU_PVTPLL_PATH_PVTPLL);
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
+ NPU_CLK_PATH_PVTPLL);
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
+ CLKDIV_5BITS_SHF(0, 10));
+ return 0;
+ }
+
+ /* set npu div */
+ div = DIV_ROUND_UP(GPLL_RATE, rate);
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
+ CLKDIV_5BITS_SHF(div - 1, 2));
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
+ CLKDIV_5BITS_SHF(0, 10));
+ /* set npu mux gpll */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
+ NPU_CLK_PATH_NOR_GPLL);
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(86),
+ NPU_CLK_PATH_NOR_PLL);
+
+ return 0;
+}
+
+static int clk_scmi_npu_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ int ret;
+
+ if (rate == 0)
+ return SCMI_INVALID_PARAMETERS;
+
+ if ((rate & OPP_LENGTH_LOW) != 0) {
+ clk_scmi_set_low_length(sys_clk_info.npu_table,
+ sys_clk_info.npu_rate_count);
+ return 0;
+ }
+
+ ret = clk_npu_set_rate(rate, PLL_SEL_AUTO);
+ if (ret == 0)
+ sys_clk_info.npu_rate = rate;
+
+ return ret;
+}
+
+static int clk_scmi_npu_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ return 0;
+}
+
+int clk_scmi_crypto_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ spin_lock(&crypto_lock);
+
+ if (clock->id == ACLK_CRYPTO_S)
+ aclk_crypto_s_enable = status;
+ else
+ aclk_klad_enable = status;
+
+ if ((aclk_crypto_s_enable != 0) || (aclk_klad_enable != 0))
+ clk_scmi_common_set_status(clock, 1);
+ else
+ clk_scmi_common_set_status(clock, 0);
+
+ spin_unlock(&crypto_lock);
+ return 0;
+}
+
+static int clk_scmi_common_set_status_critical(rk_scmi_clock_t *clock, bool status)
+{
+ return 0;
+}
+
+static const struct rk_clk_ops clk_scmi_cpul_ops = {
+ .get_rate = clk_scmi_cpul_get_rate,
+ .set_rate = clk_scmi_cpul_set_rate,
+ .set_status = clk_scmi_cpul_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_cci_ops = {
+ .get_rate = clk_scmi_cci_get_rate,
+ .set_rate = clk_scmi_cci_set_rate,
+ .set_status = clk_scmi_cci_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_cpub_ops = {
+ .get_rate = clk_scmi_cpub_get_rate,
+ .set_rate = clk_scmi_cpub_set_rate,
+ .set_status = clk_scmi_cpub_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_gpu_ops = {
+ .get_rate = clk_scmi_gpu_get_rate,
+ .set_rate = clk_scmi_gpu_set_rate,
+ .set_status = clk_scmi_gpu_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_npu_ops = {
+ .get_rate = clk_scmi_npu_get_rate,
+ .set_rate = clk_scmi_npu_set_rate,
+ .set_status = clk_scmi_npu_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_ops_com_critical = {
+ .get_rate = clk_scmi_common_get_rate,
+ .set_rate = clk_scmi_common_set_rate,
+ .set_status = clk_scmi_common_set_status_critical,
+};
+
+static const struct rk_clk_ops clk_scmi_ops_com = {
+ .get_rate = clk_scmi_common_get_rate,
+ .set_rate = clk_scmi_common_set_rate,
+ .set_status = clk_scmi_common_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_ops_gate = {
+ .get_rate = clk_scmi_common_get_rate,
+ .set_status = clk_scmi_common_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_ops_crypto = {
+ .get_rate = clk_scmi_common_get_rate,
+ .set_status = clk_scmi_crypto_set_status,
+};
+
+RK3576_SCMI_CLOCK(ARMCLK_L, scmi_armclkl, &clk_scmi_cpul_ops, rk3576_cpul_rates, ARRAY_SIZE(rk3576_cpul_rates), false);
+RK3576_SCMI_CLOCK(ACLK_CCI_ROOT, scmi_aclk_cci, &clk_scmi_cci_ops, rk3576_cpul_rates, ARRAY_SIZE(rk3576_cpul_rates), false);
+RK3576_SCMI_CLOCK(ARMCLK_B, scmi_armclkb, &clk_scmi_cpub_ops, rk3576_cpub_rates, ARRAY_SIZE(rk3576_cpub_rates), false);
+RK3576_SCMI_CLOCK(CLK_GPU, scmi_clk_gpu, &clk_scmi_gpu_ops, rk3576_gpu_rates, ARRAY_SIZE(rk3576_gpu_rates), false);
+RK3576_SCMI_CLOCK(CLK_RKNN_DSU0, scmi_clk_npu, &clk_scmi_npu_ops, rk3576_npu_rates, ARRAY_SIZE(rk3576_npu_rates), false);
+RK3576_SCMI_CLOCK_COM(CLK_STIMER0_ROOT, clk_stimer0_root, p_100m_24m, clk_stimer0_root_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
+RK3576_SCMI_CLOCK_COM(CLK_STIMER1_ROOT, clk_stimer1_root, p_100m_24m, clk_stimer1_root_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
+RK3576_SCMI_CLOCK_COM(PCLK_SECURE_S, pclk_secure_s, p_116m_58m_24m, pclk_secure_s_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
+RK3576_SCMI_CLOCK_COM(HCLK_SECURE_S, hclk_secure_s, p_175m_116m_58m_24m, hclk_secure_s_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
+RK3576_SCMI_CLOCK_COM(ACLK_SECURE_S, aclk_secure_s, p_350m_175m_116m_24m, aclk_secure_s_info, &clk_scmi_ops_com_critical, rk3576_aclk_secure_s_rates, false, false);
+RK3576_SCMI_CLOCK_COM(CLK_PKA_CRYPTO_S, clk_pka_crypto_s, p_350m_175m_116m_24m, clk_pka_crypto_s_info, &clk_scmi_ops_com, rk3576_common_rates, false, true);
+RK3576_SCMI_CLOCK_COM(HCLK_VO1_S, hclk_vo1_s, p_175m_116m_58m_24m, hclk_vo1_s_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
+RK3576_SCMI_CLOCK_COM(PCLK_VO1_S, pclk_vo1_s, p_116m_58m_24m, pclk_vo1_s_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
+RK3576_SCMI_CLOCK_COM(HCLK_VO0_S, hclk_vo0_s, p_175m_116m_58m_24m, hclk_vo0_s_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
+RK3576_SCMI_CLOCK_COM(PCLK_VO0_S, pclk_vo0_s, p_116m_58m_24m, pclk_vo0_s_info, &clk_scmi_ops_com_critical, rk3576_common_rates, false, true);
+RK3576_SCMI_CLOCK_COM(PCLK_KLAD, pclk_klad, p_pclk_secure_s, pclk_klad_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
+RK3576_SCMI_CLOCK_COM(HCLK_CRYPTO_S, hclk_crypto_s, p_hclk_secure_s, hclk_crypto_s_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
+RK3576_SCMI_CLOCK_COM(HCLK_KLAD, hclk_klad, p_hclk_secure_s, hclk_klad_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
+RK3576_SCMI_CLOCK_COM(ACLK_CRYPTO_S, aclk_crypto_s, p_aclk_secure_s, aclk_crypto_s_info, &clk_scmi_ops_crypto, rk3576_common_rates, true, true);
+RK3576_SCMI_CLOCK_COM(HCLK_TRNG_S, hclk_trng_s, p_hclk_secure_s, hclk_trng_s_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
+RK3576_SCMI_CLOCK_COM(PCLK_OTPC_S, plk_otpc_s, p_pclk_secure_s, pclk_otpc_s_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
+RK3576_SCMI_CLOCK_COM(CLK_OTPC_S, clk_otpc_s, p_24m, clk_otpc_s_info, &clk_scmi_ops_gate, rk3576_common_rates, false, true);
+RK3576_SCMI_CLOCK_COM(PCLK_WDT_S, pclk_wdt_s, p_pclk_secure_s, pclk_wdt_s_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
+RK3576_SCMI_CLOCK_COM(TCLK_WDT_S, tclk_wdt_s, p_24m, tclk_wdt_s_info, &clk_scmi_ops_gate, rk3576_common_rates, false, true);
+RK3576_SCMI_CLOCK_COM(PCLK_HDCP0_TRNG, pclk_hdcp0_trng, p_pclk_vo0_s, pclk_hdcp0_trng_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
+RK3576_SCMI_CLOCK_COM(PCLK_HDCP1_TRNG, pclk_hdcp1_trng, p_pclk_vo1_s, pclk_hdcp1_trng_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
+RK3576_SCMI_CLOCK_COM(HCLK_HDCP_KEY0, hclk_hdcp_key0, p_hclk_vo0_s, hclk_hdcp_key0_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
+RK3576_SCMI_CLOCK_COM(HCLK_HDCP_KEY1, hclk_hdcp_key1, p_hclk_vo1_s, hclk_hdcp_key1_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
+RK3576_SCMI_CLOCK_COM(PCLK_EDP_S, pclk_edp_s, p_pclk_vo0_s, pclk_edp_s_info, &clk_scmi_ops_gate, rk3576_common_rates, true, true);
+RK3576_SCMI_CLOCK_COM(ACLK_KLAD, aclk_klad, p_aclk_secure_s, aclk_crypto_s_info, &clk_scmi_ops_crypto, rk3576_common_rates, true, true);
+
+rk_scmi_clock_t *clock_table[] = {
+ [ARMCLK_L] = &scmi_armclkl,
+ [ACLK_CCI_ROOT] = &scmi_aclk_cci,
+ [ARMCLK_B] = &scmi_armclkb,
+ [CLK_GPU] = &scmi_clk_gpu,
+ [CLK_RKNN_DSU0] = &scmi_clk_npu,
+ [CLK_STIMER0_ROOT] = &clk_stimer0_root,
+ [CLK_STIMER1_ROOT] = &clk_stimer1_root,
+ [PCLK_SECURE_S] = &pclk_secure_s,
+ [HCLK_SECURE_S] = &hclk_secure_s,
+ [ACLK_SECURE_S] = &aclk_secure_s,
+ [CLK_PKA_CRYPTO_S] = &clk_pka_crypto_s,
+ [HCLK_VO1_S] = &hclk_vo1_s,
+ [PCLK_VO1_S] = &pclk_vo1_s,
+ [HCLK_VO0_S] = &hclk_vo0_s,
+ [PCLK_VO0_S] = &pclk_vo0_s,
+ [PCLK_KLAD] = &pclk_klad,
+ [HCLK_CRYPTO_S] = &hclk_crypto_s,
+ [HCLK_KLAD] = &hclk_klad,
+ [ACLK_CRYPTO_S] = &aclk_crypto_s,
+ [HCLK_TRNG_S] = &hclk_trng_s,
+ [PCLK_OTPC_S] = &plk_otpc_s,
+ [CLK_OTPC_S] = &clk_otpc_s,
+ [PCLK_WDT_S] = &pclk_wdt_s,
+ [TCLK_WDT_S] = &tclk_wdt_s,
+ [PCLK_HDCP0_TRNG] = &pclk_hdcp0_trng,
+ [PCLK_HDCP1_TRNG] = &pclk_hdcp1_trng,
+ [HCLK_HDCP_KEY0] = &hclk_hdcp_key0,
+ [HCLK_HDCP_KEY1] = &hclk_hdcp_key1,
+ [PCLK_EDP_S] = &pclk_edp_s,
+ [ACLK_KLAD] = &aclk_klad,
+};
+
+size_t rockchip_scmi_clock_count(unsigned int agent_id __unused)
+{
+ return CLK_NR_CLKS;
+}
+
+rk_scmi_clock_t *rockchip_scmi_get_clock(uint32_t agent_id __unused,
+ uint32_t clock_id)
+{
+ rk_scmi_clock_t *table = NULL;
+
+ if (clock_id < ARRAY_SIZE(clock_table)) {
+ table = clock_table[clock_id];
+ if (table == NULL)
+ return NULL;
+ }
+
+ if ((table != NULL) && (table->is_security == 0))
+ return table;
+ else
+ return NULL;
+
+ return NULL;
+}
+
+void pvtplls_cpub_suspend(void)
+{
+ clk_cpub_set_rate(408000000, PLL_SEL_NOR);
+ cpub_suspended = true;
+}
+
+void pvtplls_cpub_resume(void)
+{
+ cpub_suspended = false;
+ clk_cpub_set_rate(sys_clk_info.cpub_rate, PLL_SEL_AUTO);
+}
+
+void pvtplls_suspend(void)
+{
+ clk_cpul_set_rate(408000000, PLL_SEL_NOR);
+ clk_cci_set_rate(408000000, PLL_SEL_NOR);
+ clk_cpub_set_rate(408000000, PLL_SEL_NOR);
+}
+
+void pvtplls_resume(void)
+{
+ clk_cpul_set_rate(sys_clk_info.cpul_rate, PLL_SEL_AUTO);
+ clk_cci_set_rate(sys_clk_info.cci_rate, PLL_SEL_AUTO);
+ clk_cpub_set_rate(sys_clk_info.cpub_rate, PLL_SEL_AUTO);
+}
+
+void sys_reset_pvtplls_prepare(void)
+{
+ clk_gpu_set_rate(200000000, PLL_SEL_NOR);
+ clk_npu_set_rate(200000000, PLL_SEL_NOR);
+ clk_cpul_set_rate(408000000, PLL_SEL_NOR);
+ clk_cci_set_rate(408000000, PLL_SEL_NOR);
+ clk_cpub_set_rate(408000000, PLL_SEL_NOR);
+}
+
+int rockchip_opteed_clk_set_rate(uint64_t clk_idx, uint64_t rate)
+{
+ rk_scmi_clock_t *table;
+
+ if (clk_idx > CLK_NR_CLKS) {
+ INFO("%s: clk-%ld, %ld not supported\n", __func__, clk_idx, rate);
+ return SCMI_INVALID_PARAMETERS;
+ }
+
+ table = rockchip_scmi_get_clock(0, clk_idx);
+ if (table != NULL)
+ table->clk_ops->set_rate(table, rate);
+
+ return 0;
+}
+
+int rockchip_opteed_clk_get_rate(uint64_t clk_idx, uint64_t *rate)
+{
+ rk_scmi_clock_t *table;
+
+ if (clk_idx > CLK_NR_CLKS) {
+ INFO("%s: clk-%ld not supported\n", __func__, clk_idx);
+ return SCMI_INVALID_PARAMETERS;
+ }
+
+ table = rockchip_scmi_get_clock(0, clk_idx);
+ if (table != NULL)
+ *rate = (uint64_t)table->clk_ops->get_rate(table);
+ return 0;
+}
+
+int rockchip_opteed_clk_enable(uint64_t clk_idx, uint64_t enable)
+{
+ rk_scmi_clock_t *table;
+
+ if (clk_idx > CLK_NR_CLKS) {
+ INFO("%s: clk-%ld, %ld not supported\n", __func__, clk_idx, enable);
+ return SCMI_INVALID_PARAMETERS;
+ }
+
+ table = rockchip_scmi_get_clock(0, clk_idx);
+ if (table != NULL) {
+ if (enable != 0) {
+ table->clk_ops->set_status(table, enable);
+ table->enable_count++;
+ } else {
+ if (table->enable_count == 0)
+ return 0;
+ if (--table->enable_count > 0)
+ return 0;
+ table->clk_ops->set_status(table, enable);
+ }
+ }
+ return 0;
+}
+
+#define RK3576_CPUB_OPP_INFO_OFFSET 48
+#define RK3576_CPUL_OPP_INFO_OFFSET 54
+#define RK3576_CCI_OPP_INFO_OFFSET 60
+#define RK3576_NPU_OPP_INFO_OFFSET 66
+#define RK3576_GPU_OPP_INFO_OFFSET 72
+
+static void rockchip_init_pvtpll_table(void)
+{
+ sys_clk_info.cpul_table = rk3576_cpul_pvtpll_table;
+ sys_clk_info.cpul_rate_count = ARRAY_SIZE(rk3576_cpul_pvtpll_table);
+ sys_clk_info.cci_table = rk3576_cci_pvtpll_table;
+ sys_clk_info.cci_rate_count = ARRAY_SIZE(rk3576_cci_pvtpll_table);
+ sys_clk_info.cpub_table = rk3576_cpub_pvtpll_table;
+ sys_clk_info.cpub_rate_count = ARRAY_SIZE(rk3576_cpub_pvtpll_table);
+ sys_clk_info.gpu_table = rk3576_gpu_pvtpll_table;
+ sys_clk_info.gpu_rate_count = ARRAY_SIZE(rk3576_gpu_pvtpll_table);
+ sys_clk_info.npu_table = rk3576_npu_pvtpll_table;
+ sys_clk_info.npu_rate_count = ARRAY_SIZE(rk3576_npu_pvtpll_table);
+}
+
+void rockchip_clock_init(void)
+{
+ rockchip_init_pvtpll_table();
+}
+
+static int pvtpll_get_clk(uint64_t clock_id, struct pvtpll_table **table,
+ unsigned int *count)
+{
+ switch (clock_id) {
+ case ARMCLK_L:
+ *table = sys_clk_info.cpul_table;
+ *count = sys_clk_info.cpul_rate_count;
+ break;
+ case ARMCLK_B:
+ *table = sys_clk_info.cpub_table;
+ *count = sys_clk_info.cpub_rate_count;
+ break;
+ case CLK_GPU:
+ *table = sys_clk_info.gpu_table;
+ *count = sys_clk_info.gpu_rate_count;
+ break;
+ case CLK_RKNN_DSU0:
+ *table = sys_clk_info.npu_table;
+ *count = sys_clk_info.npu_rate_count;
+ break;
+ default:
+ return -1;
+ }
+
+ if ((*table == NULL) || (*count == 0))
+ return -1;
+
+ return 0;
+}
+
+int pvtpll_volt_sel_adjust(uint64_t clock_id, uint64_t volt_sel)
+{
+ struct pvtpll_table *table = NULL;
+ uint32_t delta_len = 0;
+ unsigned int count = 0;
+ int i;
+
+ if (pvtpll_get_clk(clock_id, &table, &count) != 0)
+ return -1;
+
+ for (i = 0; i < count; i++) {
+ if (table[i].volt_sel_thr == 0)
+ continue;
+ if (volt_sel >= table[i].volt_sel_thr) {
+ delta_len = volt_sel - table[i].volt_sel_thr + 1;
+ table[i].length += delta_len;
+ if (table[i].length > RK3576_PVTPLL_MAX_LENGTH)
+ table[i].length = RK3576_PVTPLL_MAX_LENGTH;
+ }
+ }
+
+ return 0;
+}
diff --git a/plat/rockchip/rk3576/scmi/rk3576_clk.h b/plat/rockchip/rk3576/scmi/rk3576_clk.h
new file mode 100644
index 0000000..b2c00b9
--- /dev/null
+++ b/plat/rockchip/rk3576/scmi/rk3576_clk.h
@@ -0,0 +1,1151 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
+ */
+
+#ifndef __CLOCK_H__
+#define __CLOCK_H__
+
+/* cru-clocks indices */
+
+/* cru plls */
+#define PLL_BPLL 1
+#define PLL_LPLL 3
+#define PLL_VPLL 4
+#define PLL_AUPLL 5
+#define PLL_CPLL 6
+#define PLL_GPLL 7
+#define PLL_PPLL 9
+#define ARMCLK_L 10
+#define ARMCLK_B 11
+
+/* cru clocks */
+#define CLK_CPLL_DIV20 15
+#define CLK_CPLL_DIV10 16
+#define CLK_GPLL_DIV8 17
+#define CLK_GPLL_DIV6 18
+#define CLK_CPLL_DIV4 19
+#define CLK_GPLL_DIV4 20
+#define CLK_SPLL_DIV2 21
+#define CLK_GPLL_DIV3 22
+#define CLK_CPLL_DIV2 23
+#define CLK_GPLL_DIV2 24
+#define CLK_SPLL_DIV1 25
+#define PCLK_TOP_ROOT 26
+#define ACLK_TOP 27
+#define HCLK_TOP 28
+#define CLK_AUDIO_FRAC_0 29
+#define CLK_AUDIO_FRAC_1 30
+#define CLK_AUDIO_FRAC_2 31
+#define CLK_AUDIO_FRAC_3 32
+#define CLK_UART_FRAC_0 33
+#define CLK_UART_FRAC_1 34
+#define CLK_UART_FRAC_2 35
+#define CLK_UART1_SRC_TOP 36
+#define CLK_AUDIO_INT_0 37
+#define CLK_AUDIO_INT_1 38
+#define CLK_AUDIO_INT_2 39
+#define CLK_PDM0_SRC_TOP 40
+#define CLK_PDM1_OUT 41
+#define CLK_GMAC0_125M_SRC 42
+#define CLK_GMAC1_125M_SRC 43
+#define LCLK_ASRC_SRC_0 44
+#define LCLK_ASRC_SRC_1 45
+#define REF_CLK0_OUT_PLL 46
+#define REF_CLK1_OUT_PLL 47
+#define REF_CLK2_OUT_PLL 48
+#define REFCLKO25M_GMAC0_OUT 49
+#define REFCLKO25M_GMAC1_OUT 50
+#define CLK_CIFOUT_OUT 51
+#define CLK_GMAC0_RMII_CRU 52
+#define CLK_GMAC1_RMII_CRU 53
+#define CLK_OTPC_AUTO_RD_G 54
+#define CLK_OTP_PHY_G 55
+#define CLK_MIPI_CAMERAOUT_M0 56
+#define CLK_MIPI_CAMERAOUT_M1 57
+#define CLK_MIPI_CAMERAOUT_M2 58
+#define MCLK_PDM0_SRC_TOP 59
+#define HCLK_AUDIO_ROOT 60
+#define HCLK_ASRC_2CH_0 61
+#define HCLK_ASRC_2CH_1 62
+#define HCLK_ASRC_4CH_0 63
+#define HCLK_ASRC_4CH_1 64
+#define CLK_ASRC_2CH_0 65
+#define CLK_ASRC_2CH_1 66
+#define CLK_ASRC_4CH_0 67
+#define CLK_ASRC_4CH_1 68
+#define MCLK_SAI0_8CH_SRC 69
+#define MCLK_SAI0_8CH 70
+#define HCLK_SAI0_8CH 71
+#define HCLK_SPDIF_RX0 72
+#define MCLK_SPDIF_RX0 73
+#define HCLK_SPDIF_RX1 74
+#define MCLK_SPDIF_RX1 75
+#define MCLK_SAI1_8CH_SRC 76
+#define MCLK_SAI1_8CH 77
+#define HCLK_SAI1_8CH 78
+#define MCLK_SAI2_2CH_SRC 79
+#define MCLK_SAI2_2CH 80
+#define HCLK_SAI2_2CH 81
+#define MCLK_SAI3_2CH_SRC 82
+#define MCLK_SAI3_2CH 83
+#define HCLK_SAI3_2CH 84
+#define MCLK_SAI4_2CH_SRC 85
+#define MCLK_SAI4_2CH 86
+#define HCLK_SAI4_2CH 87
+#define HCLK_ACDCDIG_DSM 88
+#define MCLK_ACDCDIG_DSM 89
+#define CLK_PDM1 90
+#define HCLK_PDM1 91
+#define MCLK_PDM1 92
+#define HCLK_SPDIF_TX0 93
+#define MCLK_SPDIF_TX0 94
+#define HCLK_SPDIF_TX1 95
+#define MCLK_SPDIF_TX1 96
+#define CLK_SAI1_MCLKOUT 97
+#define CLK_SAI2_MCLKOUT 98
+#define CLK_SAI3_MCLKOUT 99
+#define CLK_SAI4_MCLKOUT 100
+#define CLK_SAI0_MCLKOUT 101
+#define HCLK_BUS_ROOT 102
+#define PCLK_BUS_ROOT 103
+#define ACLK_BUS_ROOT 104
+#define HCLK_CAN0 105
+#define CLK_CAN0 106
+#define HCLK_CAN1 107
+#define CLK_CAN1 108
+#define CLK_KEY_SHIFT 109
+#define PCLK_I2C1 110
+#define PCLK_I2C2 111
+#define PCLK_I2C3 112
+#define PCLK_I2C4 113
+#define PCLK_I2C5 114
+#define PCLK_I2C6 115
+#define PCLK_I2C7 116
+#define PCLK_I2C8 117
+#define PCLK_I2C9 118
+#define PCLK_WDT_BUSMCU 119
+#define TCLK_WDT_BUSMCU 120
+#define ACLK_GIC 121
+#define CLK_I2C1 122
+#define CLK_I2C2 123
+#define CLK_I2C3 124
+#define CLK_I2C4 125
+#define CLK_I2C5 126
+#define CLK_I2C6 127
+#define CLK_I2C7 128
+#define CLK_I2C8 129
+#define CLK_I2C9 130
+#define PCLK_SARADC 131
+#define CLK_SARADC 132
+#define PCLK_TSADC 133
+#define CLK_TSADC 134
+#define PCLK_UART0 135
+#define PCLK_UART2 136
+#define PCLK_UART3 137
+#define PCLK_UART4 138
+#define PCLK_UART5 139
+#define PCLK_UART6 140
+#define PCLK_UART7 141
+#define PCLK_UART8 142
+#define PCLK_UART9 143
+#define PCLK_UART10 144
+#define PCLK_UART11 145
+#define SCLK_UART0 146
+#define SCLK_UART2 147
+#define SCLK_UART3 148
+#define SCLK_UART4 149
+#define SCLK_UART5 150
+#define SCLK_UART6 151
+#define SCLK_UART7 152
+#define SCLK_UART8 153
+#define SCLK_UART9 154
+#define SCLK_UART10 155
+#define SCLK_UART11 156
+#define PCLK_SPI0 157
+#define PCLK_SPI1 158
+#define PCLK_SPI2 159
+#define PCLK_SPI3 160
+#define PCLK_SPI4 161
+#define CLK_SPI0 162
+#define CLK_SPI1 163
+#define CLK_SPI2 164
+#define CLK_SPI3 165
+#define CLK_SPI4 166
+#define PCLK_WDT0 167
+#define TCLK_WDT0 168
+#define PCLK_PWM1 169
+#define CLK_PWM1 170
+#define CLK_OSC_PWM1 171
+#define CLK_RC_PWM1 172
+#define PCLK_BUSTIMER0 173
+#define PCLK_BUSTIMER1 174
+#define CLK_TIMER0_ROOT 175
+#define CLK_TIMER0 176
+#define CLK_TIMER1 177
+#define CLK_TIMER2 178
+#define CLK_TIMER3 179
+#define CLK_TIMER4 180
+#define CLK_TIMER5 181
+#define PCLK_MAILBOX0 182
+#define PCLK_GPIO1 183
+#define DBCLK_GPIO1 184
+#define PCLK_GPIO2 185
+#define DBCLK_GPIO2 186
+#define PCLK_GPIO3 187
+#define DBCLK_GPIO3 188
+#define PCLK_GPIO4 189
+#define DBCLK_GPIO4 190
+#define ACLK_DECOM 191
+#define PCLK_DECOM 192
+#define DCLK_DECOM 193
+#define CLK_TIMER1_ROOT 194
+#define CLK_TIMER6 195
+#define CLK_TIMER7 196
+#define CLK_TIMER8 197
+#define CLK_TIMER9 198
+#define CLK_TIMER10 199
+#define CLK_TIMER11 200
+#define ACLK_DMAC0 201
+#define ACLK_DMAC1 202
+#define ACLK_DMAC2 203
+#define ACLK_SPINLOCK 204
+#define HCLK_I3C0 205
+#define HCLK_I3C1 206
+#define HCLK_BUS_CM0_ROOT 207
+#define FCLK_BUS_CM0_CORE 208
+#define CLK_BUS_CM0_RTC 209
+#define PCLK_PMU2 210
+#define PCLK_PWM2 211
+#define CLK_PWM2 212
+#define CLK_RC_PWM2 213
+#define CLK_OSC_PWM2 214
+#define CLK_FREQ_PWM1 215
+#define CLK_COUNTER_PWM1 216
+#define SAI_SCLKIN_FREQ 217
+#define SAI_SCLKIN_COUNTER 218
+#define CLK_I3C0 219
+#define CLK_I3C1 220
+#define PCLK_CSIDPHY1 221
+#define PCLK_DDR_ROOT 222
+#define PCLK_DDR_MON_CH0 223
+#define TMCLK_DDR_MON_CH0 224
+#define ACLK_DDR_ROOT 225
+#define HCLK_DDR_ROOT 226
+#define FCLK_DDR_CM0_CORE 227
+#define CLK_DDR_TIMER_ROOT 228
+#define CLK_DDR_TIMER0 229
+#define CLK_DDR_TIMER1 230
+#define TCLK_WDT_DDR 231
+#define PCLK_WDT 232
+#define PCLK_TIMER 233
+#define CLK_DDR_CM0_RTC 234
+#define ACLK_RKNN0 235
+#define ACLK_RKNN1 236
+#define HCLK_RKNN_ROOT 237
+#define CLK_RKNN_DSU0 238
+#define PCLK_NPUTOP_ROOT 239
+#define PCLK_NPU_TIMER 240
+#define CLK_NPUTIMER_ROOT 241
+#define CLK_NPUTIMER0 242
+#define CLK_NPUTIMER1 243
+#define PCLK_NPU_WDT 244
+#define TCLK_NPU_WDT 245
+#define ACLK_RKNN_CBUF 246
+#define HCLK_NPU_CM0_ROOT 247
+#define FCLK_NPU_CM0_CORE 248
+#define CLK_NPU_CM0_RTC 249
+#define HCLK_RKNN_CBUF 250
+#define HCLK_NVM_ROOT 251
+#define ACLK_NVM_ROOT 252
+#define SCLK_FSPI_X2 253
+#define HCLK_FSPI 254
+#define CCLK_SRC_EMMC 255
+#define HCLK_EMMC 256
+#define ACLK_EMMC 257
+#define BCLK_EMMC 258
+#define TCLK_EMMC 259
+#define PCLK_PHP_ROOT 260
+#define ACLK_PHP_ROOT 261
+#define PCLK_PCIE0 262
+#define CLK_PCIE0_AUX 263
+#define ACLK_PCIE0_MST 264
+#define ACLK_PCIE0_SLV 265
+#define ACLK_PCIE0_DBI 266
+#define ACLK_USB3OTG1 267
+#define CLK_REF_USB3OTG1 268
+#define CLK_SUSPEND_USB3OTG1 269
+#define ACLK_MMU0 270
+#define ACLK_SLV_MMU0 271
+#define ACLK_MMU1 272
+#define ACLK_SLV_MMU1 273
+#define PCLK_PCIE1 275
+#define CLK_PCIE1_AUX 276
+#define ACLK_PCIE1_MST 277
+#define ACLK_PCIE1_SLV 278
+#define ACLK_PCIE1_DBI 279
+#define CLK_RXOOB0 280
+#define CLK_RXOOB1 281
+#define CLK_PMALIVE0 282
+#define CLK_PMALIVE1 283
+#define ACLK_SATA0 284
+#define ACLK_SATA1 285
+#define CLK_USB3OTG1_PIPE_PCLK 286
+#define CLK_USB3OTG1_UTMI 287
+#define CLK_USB3OTG0_PIPE_PCLK 288
+#define CLK_USB3OTG0_UTMI 289
+#define HCLK_SDGMAC_ROOT 290
+#define ACLK_SDGMAC_ROOT 291
+#define PCLK_SDGMAC_ROOT 292
+#define ACLK_GMAC0 293
+#define ACLK_GMAC1 294
+#define PCLK_GMAC0 295
+#define PCLK_GMAC1 296
+#define CCLK_SRC_SDIO 297
+#define HCLK_SDIO 298
+#define CLK_GMAC1_PTP_REF 299
+#define CLK_GMAC0_PTP_REF 300
+#define CLK_GMAC1_PTP_REF_SRC 301
+#define CLK_GMAC0_PTP_REF_SRC 302
+#define CCLK_SRC_SDMMC0 303
+#define HCLK_SDMMC0 304
+#define SCLK_FSPI1_X2 305
+#define HCLK_FSPI1 306
+#define ACLK_DSMC_ROOT 307
+#define ACLK_DSMC 308
+#define PCLK_DSMC 309
+#define CLK_DSMC_SYS 310
+#define HCLK_HSGPIO 311
+#define CLK_HSGPIO_TX 312
+#define CLK_HSGPIO_RX 313
+#define ACLK_HSGPIO 314
+#define PCLK_PHPPHY_ROOT 315
+#define PCLK_PCIE2_COMBOPHY0 316
+#define PCLK_PCIE2_COMBOPHY1 317
+#define CLK_PCIE_100M_SRC 318
+#define CLK_PCIE_100M_NDUTY_SRC 319
+#define CLK_REF_PCIE0_PHY 320
+#define CLK_REF_PCIE1_PHY 321
+#define CLK_REF_MPHY_26M 322
+#define HCLK_RKVDEC_ROOT 323
+#define ACLK_RKVDEC_ROOT 324
+#define HCLK_RKVDEC 325
+#define CLK_RKVDEC_HEVC_CA 326
+#define CLK_RKVDEC_CORE 327
+#define ACLK_UFS_ROOT 328
+#define ACLK_USB_ROOT 329
+#define PCLK_USB_ROOT 330
+#define ACLK_USB3OTG0 331
+#define CLK_REF_USB3OTG0 332
+#define CLK_SUSPEND_USB3OTG0 333
+#define ACLK_MMU2 334
+#define ACLK_SLV_MMU2 335
+#define ACLK_UFS_SYS 336
+#define ACLK_VPU_ROOT 337
+#define ACLK_VPU_MID_ROOT 338
+#define HCLK_VPU_ROOT 339
+#define ACLK_JPEG_ROOT 340
+#define ACLK_VPU_LOW_ROOT 341
+#define HCLK_RGA2E_0 342
+#define ACLK_RGA2E_0 342
+#define CLK_CORE_RGA2E_0 344
+#define ACLK_JPEG 345
+#define HCLK_JPEG 346
+#define HCLK_VDPP 347
+#define ACLK_VDPP 348
+#define CLK_CORE_VDPP 349
+#define HCLK_RGA2E_1 350
+#define ACLK_RGA2E_1 351
+#define CLK_CORE_RGA2E_1 352
+#define DCLK_EBC_FRAC_SRC 353
+#define HCLK_EBC 354
+#define ACLK_EBC 355
+#define DCLK_EBC 356
+#define HCLK_VEPU0_ROOT 357
+#define ACLK_VEPU0_ROOT 358
+#define HCLK_VEPU0 359
+#define ACLK_VEPU0 360
+#define CLK_VEPU0_CORE 361
+#define ACLK_VI_ROOT 362
+#define HCLK_VI_ROOT 363
+#define PCLK_VI_ROOT 364
+#define DCLK_VICAP 365
+#define ACLK_VICAP 366
+#define HCLK_VICAP 367
+#define CLK_ISP_CORE 368
+#define CLK_ISP_CORE_MARVIN 369
+#define CLK_ISP_CORE_VICAP 370
+#define ACLK_ISP 371
+#define HCLK_ISP 372
+#define ACLK_VPSS 373
+#define HCLK_VPSS 374
+#define CLK_CORE_VPSS 375
+#define PCLK_CSI_HOST_0 376
+#define PCLK_CSI_HOST_1 377
+#define PCLK_CSI_HOST_2 378
+#define PCLK_CSI_HOST_3 379
+#define PCLK_CSI_HOST_4 380
+#define ICLK_CSIHOST01 381
+#define ICLK_CSIHOST0 382
+#define CLK_ISP_PVTPLL_SRC 383
+#define ACLK_VI_ROOT_INTER 384
+#define CLK_VICAP_I0CLK 385
+#define CLK_VICAP_I1CLK 386
+#define CLK_VICAP_I2CLK 387
+#define CLK_VICAP_I3CLK 388
+#define CLK_VICAP_I4CLK 389
+#define ACLK_VOP_ROOT 390
+#define HCLK_VOP_ROOT 391
+#define PCLK_VOP_ROOT 392
+#define HCLK_VOP 393
+#define ACLK_VOP 394
+#define DCLK_VP0_SRC 395
+#define DCLK_VP1_SRC 396
+#define DCLK_VP2_SRC 397
+#define DCLK_VP0 398
+#define DCLK_VP1 400
+#define DCLK_VP2 401
+#define PCLK_VOPGRF 402
+#define ACLK_VO0_ROOT 403
+#define HCLK_VO0_ROOT 404
+#define PCLK_VO0_ROOT 405
+#define PCLK_VO0_GRF 406
+#define ACLK_HDCP0 407
+#define HCLK_HDCP0 408
+#define PCLK_HDCP0 409
+#define CLK_TRNG0_SKP 410
+#define PCLK_DSIHOST0 411
+#define CLK_DSIHOST0 412
+#define PCLK_HDMITX0 413
+#define CLK_HDMITX0_EARC 414
+#define CLK_HDMITX0_REF 415
+#define PCLK_EDP0 416
+#define CLK_EDP0_24M 417
+#define CLK_EDP0_200M 418
+#define MCLK_SAI5_8CH_SRC 419
+#define MCLK_SAI5_8CH 420
+#define HCLK_SAI5_8CH 421
+#define MCLK_SAI6_8CH_SRC 422
+#define MCLK_SAI6_8CH 423
+#define HCLK_SAI6_8CH 424
+#define HCLK_SPDIF_TX2 425
+#define MCLK_SPDIF_TX2 426
+#define HCLK_SPDIF_RX2 427
+#define MCLK_SPDIF_RX2 428
+#define HCLK_SAI8_8CH 429
+#define MCLK_SAI8_8CH_SRC 430
+#define MCLK_SAI8_8CH 431
+#define ACLK_VO1_ROOT 432
+#define HCLK_VO1_ROOT 433
+#define PCLK_VO1_ROOT 434
+#define MCLK_SAI7_8CH_SRC 435
+#define MCLK_SAI7_8CH 436
+#define HCLK_SAI7_8CH 437
+#define HCLK_SPDIF_TX3 438
+#define HCLK_SPDIF_TX4 439
+#define HCLK_SPDIF_TX5 440
+#define MCLK_SPDIF_TX3 441
+#define CLK_AUX16MHZ_0 442
+#define ACLK_DP0 443
+#define PCLK_DP0 444
+#define PCLK_VO1_GRF 445
+#define ACLK_HDCP1 446
+#define HCLK_HDCP1 447
+#define PCLK_HDCP1 448
+#define CLK_TRNG1_SKP 449
+#define HCLK_SAI9_8CH 450
+#define MCLK_SAI9_8CH_SRC 451
+#define MCLK_SAI9_8CH 452
+#define MCLK_SPDIF_TX4 453
+#define MCLK_SPDIF_TX5 454
+#define CLK_GPU_SRC_PRE 455
+#define CLK_GPU 456
+#define PCLK_GPU_ROOT 457
+#define ACLK_CENTER_ROOT 458
+#define ACLK_CENTER_LOW_ROOT 459
+#define HCLK_CENTER_ROOT 460
+#define PCLK_CENTER_ROOT 461
+#define ACLK_DMA2DDR 462
+#define ACLK_DDR_SHAREMEM 463
+#define PCLK_DMA2DDR 464
+#define PCLK_SHAREMEM 465
+#define HCLK_VEPU1_ROOT 466
+#define ACLK_VEPU1_ROOT 467
+#define HCLK_VEPU1 468
+#define ACLK_VEPU1 469
+#define CLK_VEPU1_CORE 470
+#define CLK_JDBCK_DAP 471
+#define PCLK_MIPI_DCPHY 472
+#define CLK_32K_USB2DEBUG 473
+#define PCLK_CSIDPHY 474
+#define PCLK_USBDPPHY 475
+#define CLK_PMUPHY_REF_SRC 476
+#define CLK_USBDP_COMBO_PHY_IMMORTAL 477
+#define CLK_HDMITXHPD 478
+#define PCLK_MPHY 479
+#define CLK_REF_OSC_MPHY 480
+#define CLK_REF_UFS_CLKOUT 481
+#define HCLK_PMU1_ROOT 482
+#define HCLK_PMU_CM0_ROOT 483
+#define CLK_200M_PMU_SRC 484
+#define CLK_100M_PMU_SRC 485
+#define CLK_50M_PMU_SRC 486
+#define FCLK_PMU_CM0_CORE 487
+#define CLK_PMU_CM0_RTC 488
+#define PCLK_PMU1 489
+#define CLK_PMU1 490
+#define PCLK_PMU1WDT 491
+#define TCLK_PMU1WDT 492
+#define PCLK_PMUTIMER 493
+#define CLK_PMUTIMER_ROOT 494
+#define CLK_PMUTIMER0 495
+#define CLK_PMUTIMER1 496
+#define PCLK_PMU1PWM 497
+#define CLK_PMU1PWM 498
+#define CLK_PMU1PWM_OSC 499
+#define PCLK_PMUPHY_ROOT 500
+#define PCLK_I2C0 501
+#define CLK_I2C0 502
+#define SCLK_UART1 503
+#define PCLK_UART1 504
+#define CLK_PMU1PWM_RC 505
+#define CLK_PDM0 506
+#define HCLK_PDM0 507
+#define MCLK_PDM0 508
+#define HCLK_VAD 509
+#define CLK_OSCCHK_PVTM 510
+#define CLK_PDM0_OUT 511
+#define CLK_HPTIMER_SRC 512
+#define PCLK_PMU0_ROOT 516
+#define PCLK_PMU0 517
+#define PCLK_GPIO0 518
+#define DBCLK_GPIO0 519
+#define CLK_OSC0_PMU1 520
+#define PCLK_PMU1_ROOT 521
+#define XIN_OSC0_DIV 522
+#define ACLK_USB 523
+#define ACLK_UFS 524
+#define ACLK_SDGMAC 525
+#define HCLK_SDGMAC 526
+#define PCLK_SDGMAC 527
+#define HCLK_VO1 528
+#define HCLK_VO0 529
+#define PCLK_CCI_ROOT 532
+#define ACLK_CCI_ROOT 533
+#define HCLK_VO0VOP_CHANNEL 534
+#define ACLK_VO0VOP_CHANNEL 535
+#define ACLK_TOP_MID 536
+#define ACLK_SECURE_HIGH 537
+#define CLK_USBPHY_REF_SRC 538
+#define CLK_PHY_REF_SRC 539
+#define CLK_CPLL_REF_SRC 540
+#define CLK_AUPLL_REF_SRC 541
+#define PCLK_SECURE_NS 542
+#define HCLK_SECURE_NS 543
+#define ACLK_SECURE_NS 544
+#define PCLK_OTPC_NS 545
+#define HCLK_CRYPTO_NS 546
+#define HCLK_TRNG_NS 547
+#define CLK_OTPC_NS 548
+#define SCLK_DSU 549
+#define SCLK_DDR 550
+#define ACLK_CRYPTO_NS 551
+#define CLK_PKA_CRYPTO_NS 552
+
+/* secure clk */
+#define CLK_STIMER0_ROOT 600
+#define CLK_STIMER1_ROOT 601
+#define PCLK_SECURE_S 602
+#define HCLK_SECURE_S 603
+#define ACLK_SECURE_S 604
+#define CLK_PKA_CRYPTO_S 605
+#define HCLK_VO1_S 606
+#define PCLK_VO1_S 607
+#define HCLK_VO0_S 608
+#define PCLK_VO0_S 609
+#define PCLK_KLAD 610
+#define HCLK_CRYPTO_S 611
+#define HCLK_KLAD 612
+#define ACLK_CRYPTO_S 613
+#define HCLK_TRNG_S 614
+#define PCLK_OTPC_S 615
+#define CLK_OTPC_S 616
+#define PCLK_WDT_S 617
+#define TCLK_WDT_S 618
+#define PCLK_HDCP0_TRNG 619
+#define PCLK_HDCP1_TRNG 620
+#define HCLK_HDCP_KEY0 621
+#define HCLK_HDCP_KEY1 622
+#define PCLK_EDP_S 623
+#define ACLK_KLAD 624
+
+#define CLK_NR_CLKS (ACLK_KLAD + 1)
+
+/********Name=SOFTRST_CON01,Offset=0xA04********/
+#define SRST_A_TOP_BIU 19
+#define SRST_P_TOP_BIU 21
+#define SRST_A_TOP_MID_BIU 22
+#define SRST_A_SECURE_HIGH_BIU 23
+#define SRST_H_TOP_BIU 30
+/********Name=SOFTRST_CON02,Offset=0xA08********/
+#define SRST_H_VO0VOP_CHANNEL_BIU 32
+#define SRST_A_VO0VOP_CHANNEL_BIU 33
+/********Name=SOFTRST_CON06,Offset=0xA18********/
+#define SRST_BISRINTF 98
+/********Name=SOFTRST_CON07,Offset=0xA1C********/
+#define SRST_H_AUDIO_BIU 114
+#define SRST_H_ASRC_2CH_0 115
+#define SRST_H_ASRC_2CH_1 116
+#define SRST_H_ASRC_4CH_0 117
+#define SRST_H_ASRC_4CH_1 118
+#define SRST_ASRC_2CH_0 119
+#define SRST_ASRC_2CH_1 120
+#define SRST_ASRC_4CH_0 121
+#define SRST_ASRC_4CH_1 122
+#define SRST_M_SAI0_8CH 124
+#define SRST_H_SAI0_8CH 125
+#define SRST_H_SPDIF_RX0 126
+#define SRST_M_SPDIF_RX0 127
+/********Name=SOFTRST_CON08,Offset=0xA20********/
+#define SRST_H_SPDIF_RX1 128
+#define SRST_M_SPDIF_RX1 129
+#define SRST_M_SAI1_8CH 133
+#define SRST_H_SAI1_8CH 134
+#define SRST_M_SAI2_2CH 136
+#define SRST_H_SAI2_2CH 138
+#define SRST_M_SAI3_2CH 140
+#define SRST_H_SAI3_2CH 142
+/********Name=SOFTRST_CON09,Offset=0xA24********/
+#define SRST_M_SAI4_2CH 144
+#define SRST_H_SAI4_2CH 146
+#define SRST_H_ACDCDIG_DSM 147
+#define SRST_M_ACDCDIG_DSM 148
+#define SRST_PDM1 149
+#define SRST_H_PDM1 151
+#define SRST_M_PDM1 152
+#define SRST_H_SPDIF_TX0 153
+#define SRST_M_SPDIF_TX0 154
+#define SRST_H_SPDIF_TX1 155
+#define SRST_M_SPDIF_TX1 156
+/********Name=SOFTRST_CON11,Offset=0xA2C********/
+#define SRST_A_BUS_BIU 179
+#define SRST_P_BUS_BIU 180
+#define SRST_P_CRU 181
+#define SRST_H_CAN0 182
+#define SRST_CAN0 183
+#define SRST_H_CAN1 184
+#define SRST_CAN1 185
+#define SRST_P_INTMUX2BUS 188
+#define SRST_P_VCCIO_IOC 189
+#define SRST_H_BUS_BIU 190
+#define SRST_KEY_SHIFT 191
+/********Name=SOFTRST_CON12,Offset=0xA30********/
+#define SRST_P_I2C1 192
+#define SRST_P_I2C2 193
+#define SRST_P_I2C3 194
+#define SRST_P_I2C4 195
+#define SRST_P_I2C5 196
+#define SRST_P_I2C6 197
+#define SRST_P_I2C7 198
+#define SRST_P_I2C8 199
+#define SRST_P_I2C9 200
+#define SRST_P_WDT_BUSMCU 201
+#define SRST_T_WDT_BUSMCU 202
+#define SRST_A_GIC 203
+#define SRST_I2C1 204
+#define SRST_I2C2 205
+#define SRST_I2C3 206
+#define SRST_I2C4 207
+/********Name=SOFTRST_CON13,Offset=0xA34********/
+#define SRST_I2C5 208
+#define SRST_I2C6 209
+#define SRST_I2C7 210
+#define SRST_I2C8 211
+#define SRST_I2C9 212
+#define SRST_P_SARADC 214
+#define SRST_SARADC 215
+#define SRST_P_TSADC 216
+#define SRST_TSADC 217
+#define SRST_P_UART0 218
+#define SRST_P_UART2 219
+#define SRST_P_UART3 220
+#define SRST_P_UART4 221
+#define SRST_P_UART5 222
+#define SRST_P_UART6 223
+/********Name=SOFTRST_CON14,Offset=0xA38********/
+#define SRST_P_UART7 224
+#define SRST_P_UART8 225
+#define SRST_P_UART9 226
+#define SRST_P_UART10 227
+#define SRST_P_UART11 228
+#define SRST_S_UART0 229
+#define SRST_S_UART2 230
+#define SRST_S_UART3 233
+#define SRST_S_UART4 236
+#define SRST_S_UART5 239
+/********Name=SOFTRST_CON15,Offset=0xA3C********/
+#define SRST_S_UART6 242
+#define SRST_S_UART7 245
+#define SRST_S_UART8 248
+#define SRST_S_UART9 249
+#define SRST_S_UART10 250
+#define SRST_S_UART11 251
+#define SRST_P_SPI0 253
+#define SRST_P_SPI1 254
+#define SRST_P_SPI2 255
+/********Name=SOFTRST_CON16,Offset=0xA40********/
+#define SRST_P_SPI3 256
+#define SRST_P_SPI4 257
+#define SRST_SPI0 258
+#define SRST_SPI1 259
+#define SRST_SPI2 260
+#define SRST_SPI3 261
+#define SRST_SPI4 262
+#define SRST_P_WDT0 263
+#define SRST_T_WDT0 264
+#define SRST_P_SYS_GRF 265
+#define SRST_P_PWM1 266
+#define SRST_PWM1 267
+
+/********Name=SOFTRST_CON17,Offset=0xA44********/
+#define SRST_P_BUSTIMER0 275
+#define SRST_P_BUSTIMER1 276
+#define SRST_TIMER0 278
+#define SRST_TIMER1 279
+#define SRST_TIMER2 280
+#define SRST_TIMER3 281
+#define SRST_TIMER4 282
+#define SRST_TIMER5 283
+#define SRST_P_BUSIOC 284
+#define SRST_P_MAILBOX0 285
+#define SRST_P_GPIO1 287
+/********Name=SOFTRST_CON18,Offset=0xA48********/
+#define SRST_GPIO1 288
+#define SRST_P_GPIO2 289
+#define SRST_GPIO2 290
+#define SRST_P_GPIO3 291
+#define SRST_GPIO3 292
+#define SRST_P_GPIO4 293
+#define SRST_GPIO4 294
+#define SRST_A_DECOM 295
+#define SRST_P_DECOM 296
+#define SRST_D_DECOM 297
+#define SRST_TIMER6 299
+#define SRST_TIMER7 300
+#define SRST_TIMER8 301
+#define SRST_TIMER9 302
+#define SRST_TIMER10 303
+/********Name=SOFTRST_CON19,Offset=0xA4C********/
+#define SRST_TIMER11 304
+#define SRST_A_DMAC0 305
+#define SRST_A_DMAC1 306
+#define SRST_A_DMAC2 307
+#define SRST_A_SPINLOCK 308
+#define SRST_REF_PVTPLL_BUS 309
+#define SRST_H_I3C0 311
+#define SRST_H_I3C1 313
+#define SRST_H_BUS_CM0_BIU 315
+#define SRST_F_BUS_CM0_CORE 316
+#define SRST_T_BUS_CM0_JTAG 317
+/********Name=SOFTRST_CON20,Offset=0xA50********/
+#define SRST_P_INTMUX2PMU 320
+#define SRST_P_INTMUX2DDR 321
+#define SRST_P_PVTPLL_BUS 323
+#define SRST_P_PWM2 324
+#define SRST_PWM2 325
+#define SRST_FREQ_PWM1 328
+#define SRST_COUNTER_PWM1 329
+#define SRST_I3C0 332
+#define SRST_I3C1 333
+/********Name=SOFTRST_CON21,Offset=0xA54********/
+#define SRST_P_DDR_MON_CH0 337
+#define SRST_P_DDR_BIU 338
+#define SRST_P_DDR_UPCTL_CH0 339
+#define SRST_TM_DDR_MON_CH0 340
+#define SRST_A_DDR_BIU 341
+#define SRST_DFI_CH0 342
+#define SRST_DDR_MON_CH0 346
+#define SRST_P_DDR_HWLP_CH0 349
+#define SRST_P_DDR_MON_CH1 350
+#define SRST_P_DDR_HWLP_CH1 351
+/********Name=SOFTRST_CON22,Offset=0xA58********/
+#define SRST_P_DDR_UPCTL_CH1 352
+#define SRST_TM_DDR_MON_CH1 353
+#define SRST_DFI_CH1 354
+#define SRST_A_DDR01_MSCH0 355
+#define SRST_A_DDR01_MSCH1 356
+#define SRST_DDR_MON_CH1 358
+#define SRST_DDR_SCRAMBLE_CH0 361
+#define SRST_DDR_SCRAMBLE_CH1 362
+#define SRST_P_AHB2APB 364
+#define SRST_H_AHB2APB 365
+#define SRST_H_DDR_BIU 366
+#define SRST_F_DDR_CM0_CORE 367
+/********Name=SOFTRST_CON23,Offset=0xA5C********/
+#define SRST_P_DDR01_MSCH0 369
+#define SRST_P_DDR01_MSCH1 370
+#define SRST_DDR_TIMER0 372
+#define SRST_DDR_TIMER1 373
+#define SRST_T_WDT_DDR 374
+#define SRST_P_WDT 375
+#define SRST_P_TIMER 376
+#define SRST_T_DDR_CM0_JTAG 377
+#define SRST_P_DDR_GRF 379
+/********Name=SOFTRST_CON25,Offset=0xA64********/
+#define SRST_DDR_UPCTL_CH0 401
+#define SRST_A_DDR_UPCTL_0_CH0 402
+#define SRST_A_DDR_UPCTL_1_CH0 403
+#define SRST_A_DDR_UPCTL_2_CH0 404
+#define SRST_A_DDR_UPCTL_3_CH0 405
+#define SRST_A_DDR_UPCTL_4_CH0 406
+/********Name=SOFTRST_CON26,Offset=0xA68********/
+#define SRST_DDR_UPCTL_CH1 417
+#define SRST_A_DDR_UPCTL_0_CH1 418
+#define SRST_A_DDR_UPCTL_1_CH1 419
+#define SRST_A_DDR_UPCTL_2_CH1 420
+#define SRST_A_DDR_UPCTL_3_CH1 421
+#define SRST_A_DDR_UPCTL_4_CH1 422
+/********Name=SOFTRST_CON27,Offset=0xA6C********/
+#define SRST_REF_PVTPLL_DDR 432
+#define SRST_P_PVTPLL_DDR 433
+
+/********Name=SOFTRST_CON28,Offset=0xA70********/
+#define SRST_A_RKNN0 457
+#define SRST_A_RKNN0_BIU 459
+#define SRST_L_RKNN0_BIU 460
+/********Name=SOFTRST_CON29,Offset=0xA74********/
+#define SRST_A_RKNN1 464
+#define SRST_A_RKNN1_BIU 466
+#define SRST_L_RKNN1_BIU 467
+/********Name=SOFTRST_CON31,Offset=0xA7C********/
+#define SRST_NPU_DAP 496
+#define SRST_L_NPUSUBSYS_BIU 497
+#define SRST_P_NPUTOP_BIU 505
+#define SRST_P_NPU_TIMER 506
+#define SRST_NPUTIMER0 508
+#define SRST_NPUTIMER1 509
+#define SRST_P_NPU_WDT 510
+#define SRST_T_NPU_WDT 511
+/********Name=SOFTRST_CON32,Offset=0xA80********/
+#define SRST_A_RKNN_CBUF 512
+#define SRST_A_RVCORE0 513
+#define SRST_P_NPU_GRF 514
+#define SRST_P_PVTPLL_NPU 515
+#define SRST_NPU_PVTPLL 516
+#define SRST_H_NPU_CM0_BIU 518
+#define SRST_F_NPU_CM0_CORE 519
+#define SRST_T_NPU_CM0_JTAG 520
+#define SRST_A_RKNNTOP_BIU 523
+#define SRST_H_RKNN_CBUF 524
+#define SRST_H_RKNNTOP_BIU 525
+/********Name=SOFTRST_CON33,Offset=0xA84********/
+#define SRST_H_NVM_BIU 530
+#define SRST_A_NVM_BIU 531
+#define SRST_S_FSPI 534
+#define SRST_H_FSPI 535
+#define SRST_C_EMMC 536
+#define SRST_H_EMMC 537
+#define SRST_A_EMMC 538
+#define SRST_B_EMMC 539
+#define SRST_T_EMMC 540
+/********Name=SOFTRST_CON34,Offset=0xA88********/
+#define SRST_P_GRF 545
+#define SRST_P_PHP_BIU 549
+#define SRST_A_PHP_BIU 553
+#define SRST_P_PCIE0 557
+#define SRST_PCIE0_POWER_UP 559
+/********Name=SOFTRST_CON35,Offset=0xA8C********/
+#define SRST_A_USB3OTG1 563
+#define SRST_A_MMU0 571
+#define SRST_A_SLV_MMU0 573
+#define SRST_A_MMU1 574
+/********Name=SOFTRST_CON36,Offset=0xA90********/
+#define SRST_A_SLV_MMU1 576
+#define SRST_P_PCIE1 583
+#define SRST_PCIE1_POWER_UP 585
+/********Name=SOFTRST_CON37,Offset=0xA94********/
+#define SRST_RXOOB0 592
+#define SRST_RXOOB1 593
+#define SRST_PMALIVE0 594
+#define SRST_PMALIVE1 595
+#define SRST_A_SATA0 596
+#define SRST_A_SATA1 597
+#define SRST_ASIC1 598
+#define SRST_ASIC0 599
+/********Name=SOFTRST_CON40,Offset=0xAA0********/
+#define SRST_P_CSIDPHY1 642
+#define SRST_SCAN_CSIDPHY1 643
+/********Name=SOFTRST_CON42,Offset=0xAA8********/
+#define SRST_P_SDGMAC_GRF 675
+#define SRST_P_SDGMAC_BIU 676
+#define SRST_A_SDGMAC_BIU 677
+#define SRST_H_SDGMAC_BIU 678
+#define SRST_A_GMAC0 679
+#define SRST_A_GMAC1 680
+#define SRST_P_GMAC0 681
+#define SRST_P_GMAC1 682
+#define SRST_H_SDIO 684
+/********Name=SOFTRST_CON43,Offset=0xAAC********/
+#define SRST_H_SDMMC0 690
+#define SRST_S_FSPI1 691
+#define SRST_H_FSPI1 692
+#define SRST_A_DSMC_BIU 694
+#define SRST_A_DSMC 695
+#define SRST_P_DSMC 696
+#define SRST_H_HSGPIO 698
+#define SRST_HSGPIO 699
+#define SRST_A_HSGPIO 701
+/********Name=SOFTRST_CON45,Offset=0xAB4********/
+#define SRST_H_RKVDEC 723
+#define SRST_H_RKVDEC_BIU 725
+#define SRST_A_RKVDEC_BIU 726
+#define SRST_RKVDEC_HEVC_CA 728
+#define SRST_RKVDEC_CORE 729
+/********Name=SOFTRST_CON47,Offset=0xABC********/
+#define SRST_A_USB_BIU 755
+#define SRST_P_USBUFS_BIU 756
+#define SRST_A_USB3OTG0 757
+#define SRST_A_UFS_BIU 762
+#define SRST_A_MMU2 764
+#define SRST_A_SLV_MMU2 765
+#define SRST_A_UFS_SYS 767
+/********Name=SOFTRST_CON48,Offset=0xAC0********/
+#define SRST_A_UFS 768
+#define SRST_P_USBUFS_GRF 769
+#define SRST_P_UFS_GRF 770
+/********Name=SOFTRST_CON49,Offset=0xAC4********/
+#define SRST_H_VPU_BIU 790
+#define SRST_A_JPEG_BIU 791
+#define SRST_A_RGA_BIU 794
+#define SRST_A_VDPP_BIU 795
+#define SRST_A_EBC_BIU 796
+#define SRST_H_RGA2E_0 797
+#define SRST_A_RGA2E_0 798
+#define SRST_CORE_RGA2E_0 799
+/********Name=SOFTRST_CON50,Offset=0xAC8********/
+#define SRST_A_JPEG 800
+#define SRST_H_JPEG 801
+#define SRST_H_VDPP 802
+#define SRST_A_VDPP 803
+#define SRST_CORE_VDPP 804
+#define SRST_H_RGA2E_1 805
+#define SRST_A_RGA2E_1 806
+#define SRST_CORE_RGA2E_1 807
+#define SRST_H_EBC 810
+#define SRST_A_EBC 811
+#define SRST_D_EBC 812
+/********Name=SOFTRST_CON51,Offset=0xACC********/
+#define SRST_H_VEPU0_BIU 818
+#define SRST_A_VEPU0_BIU 819
+#define SRST_H_VEPU0 820
+#define SRST_A_VEPU0 821
+#define SRST_VEPU0_CORE 822
+/********Name=SOFTRST_CON53,Offset=0xAD4********/
+#define SRST_A_VI_BIU 851
+#define SRST_H_VI_BIU 852
+#define SRST_P_VI_BIU 853
+#define SRST_D_VICAP 854
+#define SRST_A_VICAP 855
+#define SRST_H_VICAP 856
+#define SRST_ISP0 858
+#define SRST_ISP0_VICAP 859
+/********Name=SOFTRST_CON54,Offset=0xAD8********/
+#define SRST_CORE_VPSS 865
+#define SRST_P_CSI_HOST_0 868
+#define SRST_P_CSI_HOST_1 869
+#define SRST_P_CSI_HOST_2 870
+#define SRST_P_CSI_HOST_3 871
+#define SRST_P_CSI_HOST_4 872
+/********Name=SOFTRST_CON59,Offset=0xAEC********/
+#define SRST_CIFIN 944
+#define SRST_VICAP_I0CLK 945
+#define SRST_VICAP_I1CLK 946
+#define SRST_VICAP_I2CLK 947
+#define SRST_VICAP_I3CLK 948
+#define SRST_VICAP_I4CLK 949
+/********Name=SOFTRST_CON61,Offset=0xAF4********/
+#define SRST_A_VOP_BIU 980
+#define SRST_A_VOP2_BIU 981
+#define SRST_H_VOP_BIU 982
+#define SRST_P_VOP_BIU 983
+#define SRST_H_VOP 984
+#define SRST_A_VOP 985
+#define SRST_D_VP0 989
+/********Name=SOFTRST_CON62,Offset=0xAF8********/
+#define SRST_D_VP1 992
+#define SRST_D_VP2 993
+#define SRST_P_VOP2_BIU 994
+#define SRST_P_VOPGRF 995
+/********Name=SOFTRST_CON63,Offset=0xAFC********/
+#define SRST_H_VO0_BIU 1013
+#define SRST_P_VO0_BIU 1015
+#define SRST_A_HDCP0_BIU 1017
+#define SRST_P_VO0_GRF 1018
+#define SRST_A_HDCP0 1020
+#define SRST_H_HDCP0 1021
+#define SRST_HDCP0 1022
+/********Name=SOFTRST_CON64,Offset=0xB00********/
+#define SRST_P_DSIHOST0 1029
+#define SRST_DSIHOST0 1030
+#define SRST_P_HDMITX0 1031
+#define SRST_HDMITX0_REF 1033
+#define SRST_P_EDP0 1037
+#define SRST_EDP0_24M 1038
+/********Name=SOFTRST_CON65,Offset=0xB04********/
+#define SRST_M_SAI5_8CH 1044
+#define SRST_H_SAI5_8CH 1045
+#define SRST_M_SAI6_8CH 1048
+#define SRST_H_SAI6_8CH 1049
+#define SRST_H_SPDIF_TX2 1050
+#define SRST_M_SPDIF_TX2 1053
+#define SRST_H_SPDIF_RX2 1054
+#define SRST_M_SPDIF_RX2 1055
+/********Name=SOFTRST_CON66,Offset=0xB08********/
+#define SRST_H_SAI8_8CH 1056
+#define SRST_M_SAI8_8CH 1058
+/********Name=SOFTRST_CON67,Offset=0xB0C********/
+#define SRST_H_VO1_BIU 1077
+#define SRST_P_VO1_BIU 1078
+#define SRST_M_SAI7_8CH 1081
+#define SRST_H_SAI7_8CH 1082
+#define SRST_H_SPDIF_TX3 1083
+#define SRST_H_SPDIF_TX4 1084
+#define SRST_H_SPDIF_TX5 1085
+#define SRST_M_SPDIF_TX3 1086
+/********Name=SOFTRST_CON68,Offset=0xB10********/
+#define SRST_DP0 1088
+#define SRST_P_VO1_GRF 1090
+#define SRST_A_HDCP1_BIU 1091
+#define SRST_A_HDCP1 1092
+#define SRST_H_HDCP1 1093
+#define SRST_HDCP1 1094
+#define SRST_H_SAI9_8CH 1097
+#define SRST_M_SAI9_8CH 1099
+#define SRST_M_SPDIF_TX4 1100
+#define SRST_M_SPDIF_TX5 1101
+/********Name=SOFTRST_CON69,Offset=0xB14********/
+#define SRST_GPU 1107
+#define SRST_A_S_GPU_BIU 1110
+#define SRST_A_M0_GPU_BIU 1111
+#define SRST_P_GPU_BIU 1113
+#define SRST_P_GPU_GRF 1117
+#define SRST_GPU_PVTPLL 1118
+#define SRST_P_PVTPLL_GPU 1119
+/********Name=SOFTRST_CON72,Offset=0xB20********/
+#define SRST_A_CENTER_BIU 1156
+#define SRST_A_DMA2DDR 1157
+#define SRST_A_DDR_SHAREMEM 1158
+#define SRST_A_DDR_SHAREMEM_BIU 1159
+#define SRST_H_CENTER_BIU 1160
+#define SRST_P_CENTER_GRF 1161
+#define SRST_P_DMA2DDR 1162
+#define SRST_P_SHAREMEM 1163
+#define SRST_P_CENTER_BIU 1164
+/********Name=SOFTRST_CON75,Offset=0xB2C********/
+#define SRST_LINKSYM_HDMITXPHY0 1201
+/********Name=SOFTRST_CON78,Offset=0xB38********/
+#define SRST_DP0_PIXELCLK 1249
+#define SRST_PHY_DP0_TX 1250
+#define SRST_DP1_PIXELCLK 1251
+#define SRST_DP2_PIXELCLK 1252
+/********Name=SOFTRST_CON79,Offset=0xB3C********/
+#define SRST_H_VEPU1_BIU 1265
+#define SRST_A_VEPU1_BIU 1266
+#define SRST_H_VEPU1 1267
+#define SRST_A_VEPU1 1268
+#define SRST_VEPU1_CORE 1269
+
+/********Name=PHPPHYSOFTRST_CON00,Offset=0x8A00********/
+#define SRST_P_PHPPHY_CRU 131073
+#define SRST_P_APB2ASB_SLV_CHIP_TOP 131075
+#define SRST_P_PCIE2_COMBOPHY0 131077
+#define SRST_P_PCIE2_COMBOPHY0_GRF 131078
+#define SRST_P_PCIE2_COMBOPHY1 131079
+#define SRST_P_PCIE2_COMBOPHY1_GRF 131080
+/********Name=PHPPHYSOFTRST_CON01,Offset=0x8A04********/
+#define SRST_PCIE0_PIPE_PHY 131093
+#define SRST_PCIE1_PIPE_PHY 131096
+
+/********Name=SECURENSSOFTRST_CON00,Offset=0x10A00********/
+#define SRST_H_CRYPTO_NS 262147
+#define SRST_H_TRNG_NS 262148
+#define SRST_P_OTPC_NS 262152
+#define SRST_OTPC_NS 262153
+
+/********Name=PMU1SOFTRST_CON00,Offset=0x20A00********/
+#define SRST_P_HDPTX_GRF 524288
+#define SRST_P_HDPTX_APB 524289
+#define SRST_P_MIPI_DCPHY 524290
+#define SRST_P_DCPHY_GRF 524291
+#define SRST_P_BOT0_APB2ASB 524292
+#define SRST_P_BOT1_APB2ASB 524293
+#define SRST_USB2DEBUG 524294
+#define SRST_P_CSIPHY_GRF 524295
+#define SRST_P_CSIPHY 524296
+#define SRST_P_USBPHY_GRF_0 524297
+#define SRST_P_USBPHY_GRF_1 524298
+#define SRST_P_USBDP_GRF 524299
+#define SRST_P_USBDPPHY 524300
+#define SRST_USBDP_COMBO_PHY_INIT 524303
+/********Name=PMU1SOFTRST_CON01,Offset=0x20A04********/
+#define SRST_USBDP_COMBO_PHY_CMN 524304
+#define SRST_USBDP_COMBO_PHY_LANE 524305
+#define SRST_USBDP_COMBO_PHY_PCS 524306
+#define SRST_M_MIPI_DCPHY 524307
+#define SRST_S_MIPI_DCPHY 524308
+#define SRST_SCAN_CSIPHY 524309
+#define SRST_P_VCCIO6_IOC 524310
+#define SRST_OTGPHY_0 524311
+#define SRST_OTGPHY_1 524312
+#define SRST_HDPTX_INIT 524313
+#define SRST_HDPTX_CMN 524314
+#define SRST_HDPTX_LANE 524315
+#define SRST_HDMITXHPD 524317
+/********Name=PMU1SOFTRST_CON02,Offset=0x20A08********/
+#define SRST_MPHY_INIT 524320
+#define SRST_P_MPHY_GRF 524321
+#define SRST_P_VCCIO7_IOC 524323
+/********Name=PMU1SOFTRST_CON03,Offset=0x20A0C********/
+#define SRST_H_PMU1_BIU 524345
+#define SRST_P_PMU1_NIU 524346
+#define SRST_H_PMU_CM0_BIU 524347
+#define SRST_PMU_CM0_CORE 524348
+#define SRST_PMU_CM0_JTAG 524349
+/********Name=PMU1SOFTRST_CON04,Offset=0x20A10********/
+#define SRST_P_CRU_PMU1 524353
+#define SRST_P_PMU1_GRF 524355
+#define SRST_P_PMU1_IOC 524356
+#define SRST_P_PMU1WDT 524357
+#define SRST_T_PMU1WDT 524358
+#define SRST_P_PMUTIMER 524359
+#define SRST_PMUTIMER0 524361
+#define SRST_PMUTIMER1 524362
+#define SRST_P_PMU1PWM 524363
+#define SRST_PMU1PWM 524364
+/********Name=PMU1SOFTRST_CON05,Offset=0x20A14********/
+#define SRST_P_I2C0 524369
+#define SRST_I2C0 524371
+#define SRST_S_UART1 525373
+#define SRST_P_UART1 525374
+#define SRST_PDM0 524381
+#define SRST_H_PDM0 524383
+/********Name=PMU1SOFTRST_CON06,Offset=0xA18********/
+#define SRST_M_PDM0 524384
+#define SRST_H_VAD 524385
+/********Name=PMU1SOFTRST_CON07,Offset=0x20A1C********/
+#define SRST_P_PMU0GRF 524404
+#define SRST_P_PMU0IOC 524405
+#define SRST_P_GPIO0 524406
+#define SRST_DB_GPIO0 524407
+
+#define SRST_NR_RSTS (SRST_DB_GPIO0 + 1)
+
+void pvtplls_cpub_suspend(void);
+void pvtplls_cpub_resume(void);
+
+void pvtplls_suspend(void);
+void pvtplls_resume(void);
+
+void rockchip_clock_init(void);
+
+#endif
diff --git a/plat/rockchip/rk3588/drivers/pmu/pmu.c b/plat/rockchip/rk3588/drivers/pmu/pmu.c
index a4128b2..16436dd 100644
--- a/plat/rockchip/rk3588/drivers/pmu/pmu.c
+++ b/plat/rockchip/rk3588/drivers/pmu/pmu.c
@@ -1319,12 +1319,16 @@
psci_power_state_t *target_state)
{
psci_power_down_wfi();
+ /* should never reach here */
+ panic();
}
void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void)
{
cpus_pd_req_enter_wfi();
psci_power_down_wfi();
+ /* should never reach here */
+ panic();
}
void __dead2 rockchip_soc_soft_reset(void)
@@ -1352,6 +1356,8 @@
* so we do not hope the core to execute valid codes.
*/
psci_power_down_wfi();
+ /* should never reach here */
+ panic();
}
void __dead2 rockchip_soc_system_off(void)
@@ -1373,6 +1379,8 @@
* so we do not hope the core to execute valid codes.
*/
psci_power_down_wfi();
+ /* should never reach here */
+ panic();
}
static void rockchip_pmu_pd_init(void)
diff --git a/plat/rpi/common/rpi3_pm.c b/plat/rpi/common/rpi3_pm.c
index 456e160..4dfe8f0 100644
--- a/plat/rpi/common/rpi3_pm.c
+++ b/plat/rpi/common/rpi3_pm.c
@@ -272,7 +272,7 @@
.pwr_domain_off = rpi3_pwr_domain_off,
.pwr_domain_on = rpi3_pwr_domain_on,
.pwr_domain_on_finish = rpi3_pwr_domain_on_finish,
- .pwr_domain_pwr_down_wfi = rpi3_pwr_down_wfi,
+ .pwr_domain_pwr_down = rpi3_pwr_down_wfi,
.system_off = rpi3_system_off,
.system_reset = rpi3_system_reset,
.validate_power_state = rpi3_validate_power_state,
diff --git a/plat/socionext/uniphier/uniphier_psci.c b/plat/socionext/uniphier/uniphier_psci.c
index a371705..b009c5e 100644
--- a/plat/socionext/uniphier/uniphier_psci.c
+++ b/plat/socionext/uniphier/uniphier_psci.c
@@ -113,7 +113,7 @@
.pwr_domain_on = uniphier_psci_pwr_domain_on,
.pwr_domain_off = uniphier_psci_pwr_domain_off,
.pwr_domain_on_finish = uniphier_psci_pwr_domain_on_finish,
- .pwr_domain_pwr_down_wfi = uniphier_psci_pwr_domain_pwr_down_wfi,
+ .pwr_domain_pwr_down = uniphier_psci_pwr_domain_pwr_down_wfi,
.system_off = uniphier_psci_system_off,
.system_reset = uniphier_psci_system_reset,
};
diff --git a/plat/st/common/common_rules.mk b/plat/st/common/common_rules.mk
index 690507e..88c1087 100644
--- a/plat/st/common/common_rules.mk
+++ b/plat/st/common/common_rules.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2023-2024, STMicroelectronics - All Rights Reserved
+# Copyright (c) 2023-2025, STMicroelectronics - All Rights Reserved
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -41,7 +41,7 @@
# Create DTB file for BL2
${BUILD_PLAT}/fdts/%-bl2.dts: fdts/%.dts fdts/${BL2_DTSI} | $$(@D)/
- $(q)echo '#include "$(patsubst fdts/%,%,$<)"' > $@
+ $(q)echo '#include "$(patsubst %.dts,%$(SP_EXT).dts,$(patsubst fdts/%,%,$<))"' > $@
$(q)echo '#include "${BL2_DTSI}"' >> $@
${BUILD_PLAT}/fdts/%-bl2.dtb: ${BUILD_PLAT}/fdts/%-bl2.dts
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index 3d37738..e700823 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -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
#
@@ -105,8 +105,13 @@
ifeq ($(AARCH32_SP),sp_min)
BL32_DTSI := stm32mp15-bl32.dtsi
FDT_SOURCES += $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl32.dts,$(DTB_FILE_NAME)))
+ifneq (,$(wildcard $(patsubst %.dtb,fdts/%-sp_min.dts,$(DTB_FILE_NAME))))
+ifeq (,$(findstring -sp_min,$(DTB_FILE_NAME)))
+SP_EXT := -sp_min
endif
endif
+endif
+endif
# Macros and rules to build TF binary
STM32_TF_STM32 := $(addprefix ${BUILD_PLAT}/tf-a-, $(patsubst %.dtb,%.stm32,$(DTB_FILE_NAME)))
@@ -258,7 +263,7 @@
ifeq ($(AARCH32_SP),sp_min)
# Create DTB file for BL32
${BUILD_PLAT}/fdts/%-bl32.dts: fdts/%.dts fdts/${BL32_DTSI} | $$(@D)/
- $(q)echo '#include "$(patsubst fdts/%,%,$<)"' > $@
+ $(q)echo '#include "$(patsubst %.dts,%$(SP_EXT).dts,$(patsubst fdts/%,%,$<))"' > $@
$(q)echo '#include "${BL32_DTSI}"' >> $@
${BUILD_PLAT}/fdts/%-bl32.dtb: ${BUILD_PLAT}/fdts/%-bl32.dts | $$(@D)/
diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c
index 97e1ac6..7841022 100644
--- a/plat/st/stm32mp1/stm32mp1_pm.c
+++ b/plat/st/stm32mp1/stm32mp1_pm.c
@@ -215,7 +215,7 @@
.pwr_domain_suspend = stm32_pwr_domain_suspend,
.pwr_domain_on_finish = stm32_pwr_domain_on_finish,
.pwr_domain_suspend_finish = stm32_pwr_domain_suspend_finish,
- .pwr_domain_pwr_down_wfi = stm32_pwr_domain_pwr_down_wfi,
+ .pwr_domain_pwr_down = stm32_pwr_domain_pwr_down_wfi,
.system_off = stm32_system_off,
.system_reset = stm32_system_reset,
.validate_power_state = stm32_validate_power_state,
diff --git a/plat/st/stm32mp2/include/platform_def.h b/plat/st/stm32mp2/include/platform_def.h
index e720c02..523f9bb 100644
--- a/plat/st/stm32mp2/include/platform_def.h
+++ b/plat/st/stm32mp2/include/platform_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023-2024, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2023-2025, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -73,8 +73,15 @@
/*******************************************************************************
* BL31 specific defines.
******************************************************************************/
+#if ENABLE_PIE
#define BL31_BASE 0
-#define BL31_LIMIT (STM32MP_SEC_SYSRAM_SIZE / 2)
+#else
+#define BL31_BASE STM32MP_SYSRAM_BASE
+#endif
+
+#define BL31_LIMIT (BL31_BASE + (STM32MP_SYSRAM_SIZE / 2))
+
+#define BL31_PROGBITS_LIMIT (BL31_BASE + STM32MP_BL31_SIZE)
/*******************************************************************************
* BL33 specific defines.
diff --git a/plat/st/stm32mp2/platform.mk b/plat/st/stm32mp2/platform.mk
index a9f8d8f..d5e2785 100644
--- a/plat/st/stm32mp2/platform.mk
+++ b/plat/st/stm32mp2/platform.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2023-2024, STMicroelectronics - All Rights Reserved
+# Copyright (c) 2023-2025, STMicroelectronics - All Rights Reserved
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -11,9 +11,12 @@
include plat/st/common/common.mk
CRASH_REPORTING := 1
-ENABLE_PIE := 1
+# Disable PIE by default. To re-enable it, uncomment next line.
+#ENABLE_PIE := 1
PROGRAMMABLE_RESET_ADDRESS := 1
+ifeq ($(ENABLE_PIE),1)
BL2_IN_XIP_MEM := 1
+endif
STM32MP_BL33_EL1 ?= 1
ifeq ($(STM32MP_BL33_EL1),1)
diff --git a/plat/st/stm32mp2/stm32mp2_def.h b/plat/st/stm32mp2/stm32mp2_def.h
index b441502..3e60cad 100644
--- a/plat/st/stm32mp2/stm32mp2_def.h
+++ b/plat/st/stm32mp2/stm32mp2_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023-2024, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2023-2025, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -76,8 +76,6 @@
#define RETRAM_BASE U(0x0E080000)
#define RETRAM_SIZE U(0x00020000)
-#define STM32MP_SEC_SYSRAM_SIZE STM32MP_SYSRAM_SIZE
-
/* DDR configuration */
#define STM32MP_DDR_BASE U(0x80000000)
#define STM32MP_DDR_MAX_SIZE UL(0x100000000) /* Max 4GB */
@@ -113,11 +111,9 @@
#define STM32MP_BL2_SIZE U(0x00029000) /* 164 KB for BL2 */
/* Allocate remaining sysram to BL31 Binary only */
-#define STM32MP_BL31_SIZE (STM32MP_SEC_SYSRAM_SIZE - \
+#define STM32MP_BL31_SIZE (STM32MP_SYSRAM_SIZE - \
STM32MP_BL2_SIZE)
-#define BL31_PROGBITS_LIMIT STM32MP_BL31_SIZE
-
#define STM32MP_BL2_BASE (STM32MP_SYSRAM_BASE + \
STM32MP_SYSRAM_SIZE - \
STM32MP_BL2_SIZE)
diff --git a/plat/st/stm32mp2/stm32mp2_pm.c b/plat/st/stm32mp2/stm32mp2_pm.c
index 5bb381d..9be42c5 100644
--- a/plat/st/stm32mp2/stm32mp2_pm.c
+++ b/plat/st/stm32mp2/stm32mp2_pm.c
@@ -103,7 +103,7 @@
.pwr_domain_suspend = stm32_pwr_domain_suspend,
.pwr_domain_on_finish = stm32_pwr_domain_on_finish,
.pwr_domain_suspend_finish = stm32_pwr_domain_suspend_finish,
- .pwr_domain_pwr_down_wfi = stm32_pwr_domain_pwr_down_wfi,
+ .pwr_domain_pwr_down = stm32_pwr_domain_pwr_down_wfi,
.system_off = stm32_system_off,
.system_reset = stm32_system_reset,
.validate_power_state = stm32_validate_power_state,
diff --git a/plat/xilinx/common/include/plat_fdt.h b/plat/xilinx/common/include/plat_fdt.h
index 47a678c..48ffff3 100644
--- a/plat/xilinx/common/include/plat_fdt.h
+++ b/plat/xilinx/common/include/plat_fdt.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2023-2025, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -8,9 +8,7 @@
#define PLAT_FDT_H
void prepare_dtb(void);
-
-#if defined(XILINX_OF_BOARD_DTB_ADDR)
+uintptr_t plat_retrieve_dt_addr(void);
int32_t is_valid_dtb(void *fdt);
-#endif
#endif /* PLAT_FDT_H */
diff --git a/plat/xilinx/common/include/pm_node.h b/plat/xilinx/common/include/pm_node.h
index 46f6bcf..3ee55c2 100644
--- a/plat/xilinx/common/include/pm_node.h
+++ b/plat/xilinx/common/include/pm_node.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2019, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -132,6 +132,18 @@
XPM_NODEIDX_DEV_TTC_2 = 0x26,
XPM_NODEIDX_DEV_TTC_3 = 0x27,
XPM_NODEIDX_DEV_SWDT_LPD = 0x28,
+ XPM_NODEIDX_DEV_I2C_2 = 0x117,
+ XPM_NODEIDX_DEV_I2C_3 = 0x118,
+ XPM_NODEIDX_DEV_I2C_4 = 0x119,
+ XPM_NODEIDX_DEV_I2C_5 = 0x11A,
+ XPM_NODEIDX_DEV_I2C_6 = 0x11B,
+ XPM_NODEIDX_DEV_I2C_7 = 0x11C,
+ XPM_NODEIDX_DEV_CAN_FD_2 = 0x11D,
+ XPM_NODEIDX_DEV_CAN_FD_3 = 0x11E,
+ XPM_NODEIDX_DEV_TTC_4 = 0x11F,
+ XPM_NODEIDX_DEV_TTC_5 = 0x120,
+ XPM_NODEIDX_DEV_TTC_6 = 0x121,
+ XPM_NODEIDX_DEV_TTC_7 = 0x122,
/* FPD Peripheral devices */
XPM_NODEIDX_DEV_SWDT_FPD = 0x29,
@@ -237,6 +249,11 @@
XPM_NODEIDX_DEV_FPD_SWDT_2 = 0xDD,
XPM_NODEIDX_DEV_FPD_SWDT_3 = 0xDE,
#endif
+
+#if defined(PLAT_versal2)
+ XPM_NODEIDX_DEV_USB_1 = 0xD7,
+#endif
+
XPM_NODEIDX_DEV_MAX,
};
diff --git a/plat/xilinx/common/plat_console.c b/plat/xilinx/common/plat_console.c
index 681226f..617a345 100644
--- a/plat/xilinx/common/plat_console.c
+++ b/plat/xilinx/common/plat_console.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2023-2025, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -31,9 +31,7 @@
static console_holder rt_hd_console;
#endif
-#if ((CONSOLE_IS(dtb) || RT_CONSOLE_IS(dtb)) && defined(XILINX_OF_BOARD_DTB_ADDR)) && \
- (!defined(PLAT_zynqmp) || (defined(PLAT_zynqmp) && \
- !IS_TFA_IN_OCM(BL31_BASE)))
+#if ((CONSOLE_IS(dtb) || RT_CONSOLE_IS(dtb)) && (XLNX_DT_CFG == 1))
static dt_uart_info_t dt_uart_info;
#endif
@@ -78,9 +76,7 @@
console_set_scope(console, consoleh->console_scope);
}
-#if ((CONSOLE_IS(dtb) || RT_CONSOLE_IS(dtb)) && defined(XILINX_OF_BOARD_DTB_ADDR)) && \
- (!defined(PLAT_zynqmp) || (defined(PLAT_zynqmp) && \
- !IS_TFA_IN_OCM(BL31_BASE)))
+#if ((CONSOLE_IS(dtb) || RT_CONSOLE_IS(dtb)) && (XLNX_DT_CFG == 1))
/**
* get_baudrate() - Get the baudrate form DTB.
* @dtb: Address of the Device Tree Blob (DTB).
@@ -222,7 +218,7 @@
static int fdt_get_uart_info(dt_uart_info_t *info)
{
int node = 0, ret = 0;
- void *dtb = (void *)XILINX_OF_BOARD_DTB_ADDR;
+ void *dtb = (void *)plat_retrieve_dt_addr();
ret = is_valid_dtb(dtb);
if (ret < 0) {
@@ -259,9 +255,7 @@
/* For DT code decoding uncomment console registration below */
/* register_console(&boot_hd_console, &boot_console); */
-#if ((CONSOLE_IS(dtb) || RT_CONSOLE_IS(dtb)) && defined(XILINX_OF_BOARD_DTB_ADDR)) && \
- (!defined(PLAT_zynqmp) || (defined(PLAT_zynqmp) && \
- !IS_TFA_IN_OCM(BL31_BASE)))
+#if ((CONSOLE_IS(dtb) || RT_CONSOLE_IS(dtb)) && (XLNX_DT_CFG == 1))
/* Parse DTB console for UART information */
if (fdt_get_uart_info(&dt_uart_info) == 0) {
if (CONSOLE_IS(dtb)) {
@@ -280,16 +274,16 @@
INFO("BL31: Early console setup\n");
#ifdef CONSOLE_RUNTIME
-#if (RT_CONSOLE_IS(dtb) && defined(XILINX_OF_BOARD_DTB_ADDR)) && \
- (!defined(PLAT_zynqmp) || (defined(PLAT_zynqmp) && \
- !IS_TFA_IN_OCM(BL31_BASE)))
- rt_hd_console.base = dt_uart_info.base;
- rt_hd_console.baud_rate = dt_uart_info.baud_rate;
- rt_hd_console.console_type = dt_uart_info.console_type;
-#else
rt_hd_console.base = (uintptr_t)RT_UART_BASE;
rt_hd_console.baud_rate = (uint32_t)UART_BAUDRATE;
rt_hd_console.console_type = RT_UART_TYPE;
+
+#if (RT_CONSOLE_IS(dtb) && (XLNX_DT_CFG == 1))
+ if (dt_uart_info.base != 0U) {
+ rt_hd_console.base = dt_uart_info.base;
+ rt_hd_console.baud_rate = dt_uart_info.baud_rate;
+ rt_hd_console.console_type = dt_uart_info.console_type;
+ }
#endif
if ((rt_hd_console.console_type == boot_hd_console.console_type) &&
diff --git a/plat/xilinx/common/plat_fdt.c b/plat/xilinx/common/plat_fdt.c
index 4ad7b2d..62b46a9 100644
--- a/plat/xilinx/common/plat_fdt.c
+++ b/plat/xilinx/common/plat_fdt.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2023-2025, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -37,16 +37,15 @@
{
int32_t ret = 0;
- if (fdt_check_header(fdt) != 0) {
+ ret = fdt_check_header(fdt);
+ if (ret != 0) {
ERROR("Can't read DT at %p\n", fdt);
- ret = -FDT_ERR_NOTFOUND;
goto error;
}
ret = fdt_open_into(fdt, fdt, XILINX_OF_BOARD_DTB_MAX_SIZE);
if (ret < 0) {
ERROR("Invalid Device Tree at %p: error %d\n", fdt, ret);
- ret = -FDT_ERR_NOTFOUND;
goto error;
}
@@ -105,7 +104,7 @@
int map_ret = 0;
int ret = 0;
- dtb = (void *)XILINX_OF_BOARD_DTB_ADDR;
+ dtb = (void *)plat_retrieve_dt_addr();
if (!IS_TFA_IN_OCM(BL31_BASE)) {
@@ -156,4 +155,14 @@
}
}
#endif
+}
+
+uintptr_t plat_retrieve_dt_addr(void)
+{
+ void *dtb = NULL;
+
+#if defined(XILINX_OF_BOARD_DTB_ADDR)
+ dtb = (void *)XILINX_OF_BOARD_DTB_ADDR;
+#endif
+ return (uintptr_t)dtb;
}
diff --git a/plat/xilinx/common/plat_xfer_list.c b/plat/xilinx/common/plat_xfer_list.c
deleted file mode 100644
index eae7ce4..0000000
--- a/plat/xilinx/common/plat_xfer_list.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2023-2024, Advanced Micro Devices, Inc. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-#include <stddef.h>
-#include <arch_helpers.h>
-#include <common/debug.h>
-#include <lib/transfer_list.h>
-
-/*
- * FIXME: This address should come from firmware before TF-A runs
- * Having this to make sure the transfer list functionality works
- */
-#define FW_HANDOFF_BASE U(0x1200000)
-#define FW_HANDOFF_SIZE U(0x600000)
-
-static struct transfer_list_header *tl_hdr;
-
-int32_t transfer_list_populate_ep_info(entry_point_info_t *bl32,
- entry_point_info_t *bl33)
-{
- struct transfer_list_entry *te = NULL;
- struct entry_point_info *ep;
- int32_t ret;
-
- tl_hdr = (struct transfer_list_header *)FW_HANDOFF_BASE;
- ret = transfer_list_check_header(tl_hdr);
- if ((ret == TL_OPS_ALL) || (ret == TL_OPS_RO)) {
- transfer_list_dump(tl_hdr);
- while ((te = transfer_list_next(tl_hdr, te)) != NULL) {
- ep = transfer_list_entry_data(te);
- if (te->tag_id == TL_TAG_EXEC_EP_INFO64) {
- switch (GET_SECURITY_STATE(ep->h.attr)) {
- case NON_SECURE:
- *bl33 = *ep;
- continue;
- case SECURE:
- *bl32 = *ep;
- continue;
- default:
- ERROR("Unrecognized Image Security State %lu\n",
- GET_SECURITY_STATE(ep->h.attr));
- ret = TL_OPS_NON;
- }
- }
- }
- }
- return ret;
-}
diff --git a/plat/xilinx/versal/platform.mk b/plat/xilinx/versal/platform.mk
index 7c15be0..8be4be6 100644
--- a/plat/xilinx/versal/platform.mk
+++ b/plat/xilinx/versal/platform.mk
@@ -1,5 +1,5 @@
# Copyright (c) 2018-2021, Arm Limited and Contributors. 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
@@ -49,8 +49,12 @@
endif
ifdef XILINX_OF_BOARD_DTB_ADDR
+XLNX_DT_CFG := 1
$(eval $(call add_define,XILINX_OF_BOARD_DTB_ADDR))
+else
+XLNX_DT_CFG := 0
endif
+$(eval $(call add_define,XLNX_DT_CFG))
PLAT_XLAT_TABLES_DYNAMIC := 0
ifeq (${PLAT_XLAT_TABLES_DYNAMIC},1)
diff --git a/plat/xilinx/versal_net/platform.mk b/plat/xilinx/versal_net/platform.mk
index 9534118..25caab4 100644
--- a/plat/xilinx/versal_net/platform.mk
+++ b/plat/xilinx/versal_net/platform.mk
@@ -1,6 +1,6 @@
# Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
# Copyright (c) 2021-2022, Xilinx, Inc. All rights reserved.
-# Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+# Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
@@ -68,8 +68,12 @@
$(eval $(call add_define_val,VERSAL_NET_CONSOLE,VERSAL_NET_CONSOLE_ID_${VERSAL_NET_CONSOLE}))
ifdef XILINX_OF_BOARD_DTB_ADDR
+XLNX_DT_CFG := 1
$(eval $(call add_define,XILINX_OF_BOARD_DTB_ADDR))
+else
+XLNX_DT_CFG := 0
endif
+$(eval $(call add_define,XLNX_DT_CFG))
# Runtime console in default console in DEBUG build
ifeq ($(DEBUG), 1)
diff --git a/plat/xilinx/zynqmp/include/platform_def.h b/plat/xilinx/zynqmp/include/platform_def.h
index 0c83a56..9a9c8d1 100644
--- a/plat/xilinx/zynqmp/include/platform_def.h
+++ b/plat/xilinx/zynqmp/include/platform_def.h
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2014-2022, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -173,4 +173,10 @@
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, PLAT_SDEI_NORMAL_PRI, grp, \
GIC_INTR_CFG_EDGE)
+#if (defined(XILINX_OF_BOARD_DTB_ADDR) && !IS_TFA_IN_OCM(BL31_BASE))
+#define XLNX_DT_CFG 1
+#else
+#define XLNX_DT_CFG 0
+#endif
+
#endif /* PLATFORM_DEF_H */
diff --git a/poetry.lock b/poetry.lock
index 4127bcd..d05e199 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand.
[[package]]
name = "alabaster"
@@ -281,6 +281,17 @@
]
[[package]]
+name = "fdt"
+version = "0.3.3"
+description = "Flattened Device Tree Python Module"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "fdt-0.3.3-py3-none-any.whl", hash = "sha256:6b2fae2e8dfa38e9b0f9666aa001dd25be74e893d293a8d60001438f732e9e47"},
+ {file = "fdt-0.3.3.tar.gz", hash = "sha256:81a215930fef2ab8894913c4f474105bb53e14f07129fe07cb6eff2d5fdf26d2"},
+]
+
+[[package]]
name = "filelock"
version = "3.16.0"
description = "A platform independent file lock."
@@ -538,6 +549,25 @@
]
[[package]]
+name = "memory"
+version = "0.1.0"
+description = "A tool for analysis of static memory consumption by TF-A images"
+optional = false
+python-versions = "^3.8.0"
+files = []
+develop = true
+
+[package.dependencies]
+anytree = "^2.8.0"
+click = "^8.1.3"
+prettytable = "^3.5.0"
+pyelftools = "^0.29.0"
+
+[package.source]
+type = "directory"
+url = "tools/memory"
+
+[[package]]
name = "myst-parser"
version = "0.18.1"
description = "An extended commonmark compliant parser, with bridges to docutils & sphinx."
@@ -1147,7 +1177,7 @@
[package.dependencies]
click = "^8.1.7"
-jinja2 = "^3.1.4"
+jinja2 = "^3.1.5"
pyyaml = "^6.0.1"
rich = "^10.14.0"
tox = "^4.18.0"
@@ -1312,4 +1342,4 @@
[metadata]
lock-version = "2.0"
python-versions = "^3.8"
-content-hash = "6a6d2fe9390a4d7d1ecf808d5f303f2dc1eeb44736827b706a858046f3eea1db"
+content-hash = "c78729d7072714d77b4a69d6aabccab35dcf0548f08aa440ff178bc7bf2824be"
diff --git a/pyproject.toml b/pyproject.toml
index 62878b4..88c4753 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -5,16 +5,11 @@
authors = ["Arm Ltd."]
license = "BSD-3-Clause"
readme = "readme.rst"
-packages = [
- { include = "memory", from = "tools/memory"}
-]
-
-[tool.poetry.scripts]
-memory = "memory.memmap:main"
[tool.poetry.dependencies]
python = "^3.8"
cot-dt2c = {path = "tools/cot_dt2c", develop = true}
+memory = {path = "tools/memory", develop = true}
tlc = {path = "tools/tlc", develop = true}
[tool.poetry.group.docs]
@@ -30,9 +25,4 @@
[tool.poetry.group.ci.dependencies]
click = "^8.1.3"
-
-[tool.poetry.group.memory.dependencies]
-pyelftools = "^0.29"
-anytree = "^2.8.0"
-click = "^8.1.3"
-prettytable = "^3.5.0"
+fdt = "^0.3.0"
diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c
index f58f615..117934f 100644
--- a/services/std_svc/drtm/drtm_main.c
+++ b/services/std_svc/drtm/drtm_main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022-2024 Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -104,16 +104,18 @@
dlme_data_hdr_init.dlme_addr_map_size = drtm_get_address_map_size();
dlme_data_hdr_init.dlme_tcb_hashes_table_size =
plat_drtm_get_tcb_hash_table_size();
+ dlme_data_hdr_init.dlme_acpi_tables_region_size =
+ plat_drtm_get_acpi_tables_region_size();
dlme_data_hdr_init.dlme_impdef_region_size =
plat_drtm_get_imp_def_dlme_region_size();
- dlme_data_min_size += dlme_data_hdr_init.dlme_addr_map_size +
+ dlme_data_min_size += sizeof(struct_dlme_data_header) +
+ dlme_data_hdr_init.dlme_addr_map_size +
ARM_DRTM_MIN_EVENT_LOG_SIZE +
dlme_data_hdr_init.dlme_tcb_hashes_table_size +
+ dlme_data_hdr_init.dlme_acpi_tables_region_size +
dlme_data_hdr_init.dlme_impdef_region_size;
- dlme_data_min_size = page_align(dlme_data_min_size, UP)/PAGE_SIZE;
-
/* Fill out platform DRTM features structure */
/* Only support default PCR schema (0x1) in this implementation. */
ARM_DRTM_TPM_FEATURES_SET_PCR_SCHEMA(plat_drtm_features.tpm_features,
@@ -123,7 +125,7 @@
ARM_DRTM_TPM_FEATURES_SET_FW_HASH(plat_drtm_features.tpm_features,
plat_tpm_feat->firmware_hash_algorithm);
ARM_DRTM_MIN_MEM_REQ_SET_MIN_DLME_DATA_SIZE(plat_drtm_features.minimum_memory_requirement,
- dlme_data_min_size);
+ page_align(dlme_data_min_size, UP)/PAGE_SIZE);
ARM_DRTM_MIN_MEM_REQ_SET_DCE_SIZE(plat_drtm_features.minimum_memory_requirement,
plat_drtm_get_min_size_normal_world_dce());
ARM_DRTM_DMA_PROT_FEATURES_SET_MAX_REGIONS(plat_drtm_features.dma_prot_features,
@@ -132,6 +134,8 @@
plat_dma_prot_feat->dma_protection_support);
ARM_DRTM_TCB_HASH_FEATURES_SET_MAX_NUM_HASHES(plat_drtm_features.tcb_hash_features,
plat_drtm_get_tcb_hash_features());
+ ARM_DRTM_DLME_IMG_AUTH_SUPPORT(plat_drtm_features.dlme_image_auth_features,
+ plat_drtm_get_dlme_img_auth_features());
return 0;
}
@@ -173,6 +177,12 @@
plat_drtm_features.tcb_hash_features);
}
+static inline uint64_t drtm_features_dlme_img_auth_features(void *ctx)
+{
+ SMC_RET2(ctx, 1ULL, /* DLME Image auth is supported */
+ plat_drtm_features.dlme_image_auth_features);
+}
+
static enum drtm_retc drtm_dl_check_caller_el(void *ctx)
{
uint64_t spsr_el3 = read_ctx_reg(get_el3state_ctx(ctx), CTX_SPSR_EL3);
@@ -237,7 +247,7 @@
*/
if (dlme_data_max_size < dlme_data_min_size) {
ERROR("%s: assertion failed:"
- " dlme_data_max_size (%ld) < dlme_data_total_bytes_req (%ld)\n",
+ " dlme_data_max_size (%ld) < dlme_data_min_size (%ld)\n",
__func__, dlme_data_max_size, dlme_data_min_size);
panic();
}
@@ -787,6 +797,12 @@
return drtm_features_tcb_hashes(handle);
break; /* not reached */
+ case ARM_DRTM_FEATURES_DLME_IMG_AUTH:
+ INFO("++ DRTM service handler: "
+ "DLME Image authentication features\n");
+ return drtm_features_dlme_img_auth_features(handle);
+ break; /* not reached */
+
default:
ERROR("Unknown ARM DRTM service feature\n");
SMC_RET1(handle, NOT_SUPPORTED);
diff --git a/services/std_svc/drtm/drtm_main.h b/services/std_svc/drtm/drtm_main.h
index c105b56..44d0d2d 100644
--- a/services/std_svc/drtm/drtm_main.h
+++ b/services/std_svc/drtm/drtm_main.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022-2024 Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -45,7 +45,7 @@
* Range(Min/Max) of DRTM parameter structure versions supported
*/
#define ARM_DRTM_PARAMS_MIN_VERSION U(1)
-#define ARM_DRTM_PARAMS_MAX_VERSION U(1)
+#define ARM_DRTM_PARAMS_MAX_VERSION U(2)
enum drtm_dlme_el {
DLME_AT_EL1 = MODE_EL1,
@@ -74,6 +74,7 @@
uint64_t dma_prot_features;
uint64_t boot_pe_id;
uint64_t tcb_hash_features;
+ uint64_t dlme_image_auth_features;
} drtm_features_t;
struct __packed drtm_dl_args_v1 {
diff --git a/services/std_svc/drtm/drtm_measurements.c b/services/std_svc/drtm/drtm_measurements.c
index 8d514b7..d4f2b57 100644
--- a/services/std_svc/drtm/drtm_measurements.c
+++ b/services/std_svc/drtm/drtm_measurements.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -198,6 +198,10 @@
PCR_18);
CHECK_RC(rc,
drtm_event_log_measure_and_record(DRTM_EVENT_ARM_SEPARATOR));
+
+ /* Measure no Action event but not extend it in PCR */
+ CHECK_RC(rc,
+ drtm_event_log_measure_and_record(DRTM_EVENT_ARM_NO_ACTION));
/*
* If the DCE is unable to log a measurement because there is no available
* space in the event log region, the DCE must extend a hash of the value
diff --git a/services/std_svc/drtm/drtm_measurements.h b/services/std_svc/drtm/drtm_measurements.h
index 6d7a84e..f5a8c7c 100644
--- a/services/std_svc/drtm/drtm_measurements.h
+++ b/services/std_svc/drtm/drtm_measurements.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -25,6 +25,9 @@
#define DRTM_EVENT_ARM_DCE_SECONDARY DRTM_EVENT_TYPE(8)
#define DRTM_EVENT_ARM_TZFW DRTM_EVENT_TYPE(9)
#define DRTM_EVENT_ARM_SEPARATOR DRTM_EVENT_TYPE(10)
+#define DRTM_EVENT_ARM_DLME_PUBKEY DRTM_EVENT_TYPE(11)
+#define DRTM_EVENT_ARM_DLME_SVN DRTM_EVENT_TYPE(12)
+#define DRTM_EVENT_ARM_NO_ACTION DRTM_EVENT_TYPE(13)
#define CHECK_RC(rc, func_call) { \
if (rc != 0) { \
diff --git a/services/std_svc/drtm/drtm_res_address_map.c b/services/std_svc/drtm/drtm_res_address_map.c
index 8636706..52e6eab 100644
--- a/services/std_svc/drtm/drtm_res_address_map.c
+++ b/services/std_svc/drtm/drtm_res_address_map.c
@@ -1,10 +1,11 @@
/*
- * Copyright (c) 2022 Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
+#include <stdlib.h>
#include <plat/common/platform.h>
#include <services/drtm_svc.h>
@@ -23,6 +24,20 @@
static uint64_t drtm_address_map_size;
+static int compare_regions(const void *a, const void *b)
+{
+ const drtm_mem_region_t *region_a = (const drtm_mem_region_t *)a;
+ const drtm_mem_region_t *region_b = (const drtm_mem_region_t *)b;
+
+ if (region_a->region_address < region_b->region_address) {
+ return -1;
+ } else if (region_a->region_address > region_b->region_address) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
drtm_memory_region_descriptor_table_t *drtm_build_address_map(void)
{
/* Set up pointer to DRTM memory map. */
@@ -75,6 +90,9 @@
map->num_regions = i;
+ qsort(map->region, map->num_regions, sizeof(drtm_mem_region_t),
+ compare_regions);
+
/* Store total size of address map. */
drtm_address_map_size = sizeof(drtm_memory_region_descriptor_table_t);
drtm_address_map_size += (i * sizeof(drtm_mem_region_t));
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
index 4d82991..94634f2 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -1,5 +1,5 @@
/*
- * 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
*/
@@ -222,6 +222,7 @@
* in this scenario where execution was trapped to EL3 due to FIQ.
*/
simd_ctx_save(NON_SECURE, false);
+ simd_ctx_restore(SECURE);
#endif
#endif
@@ -238,14 +239,8 @@
/* Mark current core as handling a secure interrupt. */
ctx->secure_interrupt_ongoing = true;
-#if CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS
- simd_ctx_restore(SECURE);
-#endif
rc = spmd_spm_core_sync_entry(ctx);
-#if CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS
- simd_ctx_save(SECURE, false);
-#endif
if (rc != 0ULL) {
ERROR("%s failed (%" PRId64 ") on CPU%u\n", __func__, rc, plat_my_core_pos());
}
@@ -258,6 +253,7 @@
cm_el1_sysregs_context_restore(NON_SECURE);
#if CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS
+ simd_ctx_save(SECURE, false);
simd_ctx_restore(NON_SECURE);
#endif
#endif
diff --git a/tools/memory/__init__.py b/tools/memory/__init__.py
deleted file mode 100644
index 0b4c8d3..0000000
--- a/tools/memory/__init__.py
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env python3
-
-#
-# Copyright (c) 2023, Arm Limited. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
diff --git a/tools/memory/memory/__init__.py b/tools/memory/memory/__init__.py
deleted file mode 100644
index 0b4c8d3..0000000
--- a/tools/memory/memory/__init__.py
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env python3
-
-#
-# Copyright (c) 2023, Arm Limited. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
diff --git a/tools/memory/poetry.lock b/tools/memory/poetry.lock
new file mode 100644
index 0000000..2747479
--- /dev/null
+++ b/tools/memory/poetry.lock
@@ -0,0 +1,95 @@
+# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand.
+
+[[package]]
+name = "anytree"
+version = "2.12.1"
+description = "Powerful and Lightweight Python Tree Data Structure with various plugins"
+optional = false
+python-versions = ">=3.7.2,<4"
+files = [
+ {file = "anytree-2.12.1-py3-none-any.whl", hash = "sha256:5ea9e61caf96db1e5b3d0a914378d2cd83c269dfce1fb8242ce96589fa3382f0"},
+ {file = "anytree-2.12.1.tar.gz", hash = "sha256:244def434ccf31b668ed282954e5d315b4e066c4940b94aff4a7962d85947830"},
+]
+
+[package.dependencies]
+six = "*"
+
+[[package]]
+name = "click"
+version = "8.1.8"
+description = "Composable command line interface toolkit"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"},
+ {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
+
+[[package]]
+name = "prettytable"
+version = "3.11.0"
+description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "prettytable-3.11.0-py3-none-any.whl", hash = "sha256:aa17083feb6c71da11a68b2c213b04675c4af4ce9c541762632ca3f2cb3546dd"},
+ {file = "prettytable-3.11.0.tar.gz", hash = "sha256:7e23ca1e68bbfd06ba8de98bf553bf3493264c96d5e8a615c0471025deeba722"},
+]
+
+[package.dependencies]
+wcwidth = "*"
+
+[package.extras]
+tests = ["pytest", "pytest-cov", "pytest-lazy-fixtures"]
+
+[[package]]
+name = "pyelftools"
+version = "0.29"
+description = "Library for analyzing ELF files and DWARF debugging information"
+optional = false
+python-versions = "*"
+files = [
+ {file = "pyelftools-0.29-py2.py3-none-any.whl", hash = "sha256:519f38cf412f073b2d7393aa4682b0190fa901f7c3fa0bff2b82d537690c7fc1"},
+ {file = "pyelftools-0.29.tar.gz", hash = "sha256:ec761596aafa16e282a31de188737e5485552469ac63b60cfcccf22263fd24ff"},
+]
+
+[[package]]
+name = "six"
+version = "1.17.0"
+description = "Python 2 and 3 compatibility utilities"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
+files = [
+ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"},
+ {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"},
+]
+
+[[package]]
+name = "wcwidth"
+version = "0.2.13"
+description = "Measures the displayed width of unicode strings in a terminal"
+optional = false
+python-versions = "*"
+files = [
+ {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"},
+ {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"},
+]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.8.0"
+content-hash = "d7c185b3dbfc9bba145f12146e18ce501caf081d7762f138bc5a7fde99f40543"
diff --git a/tools/memory/pyproject.toml b/tools/memory/pyproject.toml
new file mode 100644
index 0000000..c2fdfcb
--- /dev/null
+++ b/tools/memory/pyproject.toml
@@ -0,0 +1,21 @@
+[tool.poetry]
+name = "memory"
+version = "0.1.0"
+description = "A tool for analysis of static memory consumption by TF-A images"
+authors = ["Chris Kay <chris.kay@arm.com>", "Harrison Mutai <harrison.mutai@arm.com>"]
+license = "BSD-3-Clause"
+packages = [{include = "memory", from = "src"}]
+
+[tool.poetry.dependencies]
+anytree = "^2.8.0"
+click = "^8.1.3"
+prettytable = "^3.5.0"
+pyelftools = "^0.29.0"
+python = "^3.8.0"
+
+[tool.poetry.scripts]
+memory = "memory.memmap:main"
+
+[build-system]
+requires = ["poetry-core"]
+build-backend = "poetry.core.masonry.api"
diff --git a/tools/memory/src/memory/__init__.py b/tools/memory/src/memory/__init__.py
new file mode 100644
index 0000000..8e0db6b
--- /dev/null
+++ b/tools/memory/src/memory/__init__.py
@@ -0,0 +1,5 @@
+#
+# Copyright (c) 2025, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
diff --git a/tools/memory/memory/buildparser.py b/tools/memory/src/memory/buildparser.py
similarity index 97%
rename from tools/memory/memory/buildparser.py
rename to tools/memory/src/memory/buildparser.py
index dedff79..ea417e1 100755
--- a/tools/memory/memory/buildparser.py
+++ b/tools/memory/src/memory/buildparser.py
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2023, Arm Limited. All rights reserved.
+# Copyright (c) 2023-2025, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
diff --git a/tools/memory/memory/elfparser.py b/tools/memory/src/memory/elfparser.py
similarity index 98%
rename from tools/memory/memory/elfparser.py
rename to tools/memory/src/memory/elfparser.py
index 2dd2513..e6581c9 100644
--- a/tools/memory/memory/elfparser.py
+++ b/tools/memory/src/memory/elfparser.py
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2023, Arm Limited. All rights reserved.
+# Copyright (c) 2023-2025, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
diff --git a/tools/memory/memory/mapparser.py b/tools/memory/src/memory/mapparser.py
similarity index 97%
rename from tools/memory/memory/mapparser.py
rename to tools/memory/src/memory/mapparser.py
index ce4cc31..1c28e71 100644
--- a/tools/memory/memory/mapparser.py
+++ b/tools/memory/src/memory/mapparser.py
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2023-2024, Arm Limited. All rights reserved.
+# Copyright (c) 2023-2025, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
diff --git a/tools/memory/memory/memmap.py b/tools/memory/src/memory/memmap.py
similarity index 97%
rename from tools/memory/memory/memmap.py
rename to tools/memory/src/memory/memmap.py
index 34f5069..f46db8c 100755
--- a/tools/memory/memory/memmap.py
+++ b/tools/memory/src/memory/memmap.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
#
-# Copyright (c) 2023-2024, Arm Limited. All rights reserved.
+# Copyright (c) 2023-2025, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
diff --git a/tools/memory/memory/printer.py b/tools/memory/src/memory/printer.py
similarity index 98%
rename from tools/memory/memory/printer.py
rename to tools/memory/src/memory/printer.py
index 4b18560..f797139 100755
--- a/tools/memory/memory/printer.py
+++ b/tools/memory/src/memory/printer.py
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2023, Arm Limited. All rights reserved.
+# Copyright (c) 2023-2025, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
diff --git a/tools/sptool/hob.py b/tools/sptool/hob.py
new file mode 100644
index 0000000..dced086
--- /dev/null
+++ b/tools/sptool/hob.py
@@ -0,0 +1,425 @@
+#!/usr/bin/python3
+# Copyright (c) 2025, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+import struct
+
+EFI_HOB_HANDOFF_TABLE_VERSION = 0x000A
+
+PAGE_SIZE_SHIFT = 12 # TODO assuming 4K page size
+
+# HobType values of EFI_HOB_GENERIC_HEADER.
+
+EFI_HOB_TYPE_HANDOFF = 0x0001
+EFI_HOB_TYPE_MEMORY_ALLOCATION = 0x0002
+EFI_HOB_TYPE_RESOURCE_DESCRIPTOR = 0x0003
+EFI_HOB_TYPE_GUID_EXTENSION = 0x0004
+EFI_HOB_TYPE_FV = 0x0005
+EFI_HOB_TYPE_CPU = 0x0006
+EFI_HOB_TYPE_MEMORY_POOL = 0x0007
+EFI_HOB_TYPE_FV2 = 0x0009
+EFI_HOB_TYPE_LOAD_PEIM_UNUSED = 0x000A
+EFI_HOB_TYPE_UEFI_CAPSULE = 0x000B
+EFI_HOB_TYPE_FV3 = 0x000C
+EFI_HOB_TYPE_UNUSED = 0xFFFE
+EFI_HOB_TYPE_END_OF_HOB_LIST = 0xFFFF
+
+# GUID values
+"""struct efi_guid {
+ uint32_t time_low;
+ uint16_t time_mid;
+ uint16_t time_hi_and_version;
+ uint8_t clock_seq_and_node[8];
+}"""
+
+MM_PEI_MMRAM_MEMORY_RESERVE_GUID = (
+ 0x0703F912,
+ 0xBF8D,
+ 0x4E2A,
+ (0xBE, 0x07, 0xAB, 0x27, 0x25, 0x25, 0xC5, 0x92),
+)
+MM_NS_BUFFER_GUID = (
+ 0xF00497E3,
+ 0xBFA2,
+ 0x41A1,
+ (0x9D, 0x29, 0x54, 0xC2, 0xE9, 0x37, 0x21, 0xC5),
+)
+
+# MMRAM states and capabilities
+# See UEFI Platform Initialization Specification Version 1.8, IV-5.3.5
+EFI_MMRAM_OPEN = 0x00000001
+EFI_MMRAM_CLOSED = 0x00000002
+EFI_MMRAM_LOCKED = 0x00000004
+EFI_CACHEABLE = 0x00000008
+EFI_ALLOCATED = 0x00000010
+EFI_NEEDS_TESTING = 0x00000020
+EFI_NEEDS_ECC_INITIALIZATION = 0x00000040
+
+EFI_SMRAM_OPEN = EFI_MMRAM_OPEN
+EFI_SMRAM_CLOSED = EFI_MMRAM_CLOSED
+EFI_SMRAM_LOCKED = EFI_MMRAM_LOCKED
+
+# EFI boot mode.
+EFI_BOOT_WITH_FULL_CONFIGURATION = 0x00
+EFI_BOOT_WITH_MINIMAL_CONFIGURATION = 0x01
+EFI_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES = 0x02
+EFI_BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS = 0x03
+EFI_BOOT_WITH_DEFAULT_SETTINGS = 0x04
+EFI_BOOT_ON_S4_RESUME = 0x05
+EFI_BOOT_ON_S5_RESUME = 0x06
+EFI_BOOT_WITH_MFG_MODE_SETTINGS = 0x07
+EFI_BOOT_ON_S2_RESUME = 0x10
+EFI_BOOT_ON_S3_RESUME = 0x11
+EFI_BOOT_ON_FLASH_UPDATE = 0x12
+EFI_BOOT_IN_RECOVERY_MODE = 0x20
+
+STMM_BOOT_MODE = EFI_BOOT_WITH_FULL_CONFIGURATION
+STMM_MMRAM_REGION_STATE_DEFAULT = EFI_CACHEABLE | EFI_ALLOCATED
+STMM_MMRAM_REGION_STATE_HEAP = EFI_CACHEABLE
+
+"""`struct` python module allows user to specify endianness.
+We are expecting FVP or STMM platform as target and that they will be
+little-endian. See `struct` python module documentation if other endianness is
+needed."""
+ENDIANNESS = "<"
+
+
+def struct_pack_with_endianness(format_str, *args):
+ return struct.pack((ENDIANNESS + format_str), *args)
+
+
+def struct_calcsize_with_endianness(format_str):
+ return struct.calcsize(ENDIANNESS + format_str)
+
+
+# Helper for fdt node property parsing
+def get_integer_property_value(fdt_node, name):
+ if fdt_node.exist_property(name):
+ p = fdt_node.get_property(name)
+
+ # <u32> Device Tree value
+ if len(p) == 1:
+ return p.value
+ # <u64> Device Tree value represented as two 32-bit values
+ if len(p) == 2:
+ msb = p[0]
+ lsb = p[1]
+ return lsb | (msb << 32)
+ return None
+
+
+class EfiGuid:
+ """Class representing EFI GUID (Globally Unique Identifier) as described by
+ the UEFI Specification v2.10"""
+
+ def __init__(self, time_low, time_mid, time_hi_and_version, clock_seq_and_node):
+ self.time_low = time_low
+ self.time_mid = time_mid
+ self.time_hi_and_version = time_hi_and_version
+ self.clock_seq_and_node = clock_seq_and_node
+ self.format_str = "IHH8B"
+
+ def pack(self):
+ return struct_pack_with_endianness(
+ self.format_str,
+ self.time_low,
+ self.time_mid,
+ self.time_hi_and_version,
+ *self.clock_seq_and_node,
+ )
+
+ def __str__(self):
+ return f"{hex(self.time_low)}, {hex(self.time_mid)}, \
+ {hex(self.time_hi_and_version)}, {[hex(i) for i in self.clock_seq_and_node]}"
+
+
+class HobGenericHeader:
+ """Class representing the Hob Generic Header data type as described
+ in the UEFI Platform Initialization Specification version 1.8.
+
+ Each HOB is required to contain this header specifying the type and length
+ of the HOB.
+ """
+
+ def __init__(self, hob_type, hob_length):
+ self.format_str = "HHI"
+ self.hob_type = hob_type
+ self.hob_length = struct_calcsize_with_endianness(self.format_str) + hob_length
+ self.reserved = 0
+
+ def pack(self):
+ return struct_pack_with_endianness(
+ self.format_str, self.hob_type, self.hob_length, self.reserved
+ )
+
+ def __str__(self):
+ return f"Hob Type: {self.hob_type} Hob Length: {self.hob_length}"
+
+
+class HobGuid:
+ """Class representing the Guid Extension HOB as described in the UEFI
+ Platform Initialization Specification version 1.8.
+
+ Allows the production of HOBs whose types are not defined by the
+ specification by generating a GUID for the HOB entry."""
+
+ def __init__(self, name: EfiGuid, data_format_str, data):
+ hob_length = struct_calcsize_with_endianness(
+ name.format_str
+ ) + struct_calcsize_with_endianness(data_format_str)
+ self.header = HobGenericHeader(EFI_HOB_TYPE_GUID_EXTENSION, hob_length)
+ self.name = name
+ self.data = data
+ self.data_format_str = data_format_str
+ self.format_str = (
+ self.header.format_str + self.name.format_str + data_format_str
+ )
+
+ def pack(self):
+ return (
+ self.header.pack()
+ + self.name.pack()
+ + struct_pack_with_endianness(self.data_format_str, *self.data)
+ )
+
+ def __str__(self):
+ return f"Header: {self.header}\n Name: {self.name}\n Data: {self.data}"
+
+
+class HandoffInfoTable:
+ """Class representing the Handoff Info Table HOB (also known as PHIT HOB)
+ as described in the UEFI Platform Initialization Specification version 1.8.
+
+ Must be the first HOB in the HOB list. Contains general state
+ information.
+
+ For an SP, the range `memory_bottom` to `memory_top` will be the memory
+ range for the SP starting at the load address. `free_memory_bottom` to
+ `free_memory_top` indicates space where more HOB's could be added to the
+ HOB List."""
+
+ def __init__(self, memory_base, memory_size, free_memory_base, free_memory_size):
+ # header,uint32t,uint32t, uint64_t * 5
+ self.format_str = "II5Q"
+ hob_length = struct_calcsize_with_endianness(self.format_str)
+ self.header = HobGenericHeader(EFI_HOB_TYPE_HANDOFF, hob_length)
+ self.version = EFI_HOB_HANDOFF_TABLE_VERSION
+ self.boot_mode = STMM_BOOT_MODE
+ self.memory_top = memory_base + memory_size
+ self.memory_bottom = memory_base
+ self.free_memory_top = free_memory_base + free_memory_size
+ self.free_memory_bottom = free_memory_base + self.header.hob_length
+ self.hob_end = None
+
+ def set_hob_end_addr(self, hob_end_addr):
+ self.hob_end = hob_end_addr
+
+ def set_free_memory_bottom_addr(self, addr):
+ self.free_memory_bottom = addr
+
+ def pack(self):
+ return self.header.pack() + struct_pack_with_endianness(
+ self.format_str,
+ self.version,
+ self.boot_mode,
+ self.memory_top,
+ self.memory_bottom,
+ self.free_memory_top,
+ self.free_memory_bottom,
+ self.hob_end,
+ )
+
+
+class FirmwareVolumeHob:
+ """Class representing the Firmware Volume HOB type as described in the
+ UEFI Platform Initialization Specification version 1.8.
+
+ For an SP this will detail where the SP binary is located.
+ """
+
+ def __init__(self, base_address, img_offset, img_size):
+ # header, uint64_t, uint64_t
+ self.data_format_str = "2Q"
+ hob_length = struct_calcsize_with_endianness(self.data_format_str)
+ self.header = HobGenericHeader(EFI_HOB_TYPE_FV, hob_length)
+ self.format_str = self.header.format_str + self.data_format_str
+ self.base_address = base_address + img_offset
+ self.length = img_size - img_offset
+
+ def pack(self):
+ return self.header.pack() + struct_pack_with_endianness(
+ self.data_format_str, self.base_address, self.length
+ )
+
+
+class EndOfHobListHob:
+ """Class representing the End of HOB List HOB type as described in the
+ UEFI Platform Initialization Specification version 1.8.
+
+ Must be the last entry in a HOB list.
+ """
+
+ def __init__(self):
+ self.header = HobGenericHeader(EFI_HOB_TYPE_END_OF_HOB_LIST, 0)
+ self.format_str = ""
+
+ def pack(self):
+ return self.header.pack()
+
+
+class HobList:
+ """Class representing a HOB (Handoff Block list) based on the UEFI Platform
+ Initialization Sepcification version 1.8"""
+
+ def __init__(self, phit: HandoffInfoTable):
+ if phit is None:
+ raise Exception("HobList must be initialized with valid PHIT HOB")
+ final_hob = EndOfHobListHob()
+ phit.hob_end = phit.free_memory_bottom
+ phit.free_memory_bottom += final_hob.header.hob_length
+ self.hob_list = [phit, final_hob]
+
+ def add(self, hob):
+ if hob is not None:
+ if hob.header.hob_length > (
+ self.get_phit().free_memory_top - self.get_phit().free_memory_bottom
+ ):
+ raise MemoryError(
+ f"Cannot add HOB of length {hob.header.hob_length}. \
+ Resulting table size would exceed max table size of \
+ {self.max_size}. Current table size: {self.size}."
+ )
+ self.hob_list.insert(-1, hob)
+ self.get_phit().hob_end += hob.header.hob_length
+ self.get_phit().free_memory_bottom += hob.header.hob_length
+
+ def get_list(self):
+ return self.hob_list
+
+ def get_phit(self):
+ if self.hob_list is not None:
+ if type(self.hob_list[0]) is not HandoffInfoTable:
+ raise Exception("First hob in list must be of type PHIT")
+ return self.hob_list[0]
+
+
+def generate_mmram_desc(base_addr, page_count, granule, region_state):
+ physical_size = page_count << (PAGE_SIZE_SHIFT + (granule << 1))
+ physical_start = base_addr
+ cpu_start = base_addr
+
+ return ("4Q", (physical_start, cpu_start, physical_size, region_state))
+
+
+def generate_stmm_region_descriptor(base_addr, physical_size):
+ region_state = STMM_MMRAM_REGION_STATE_DEFAULT
+ physical_start = base_addr
+ cpu_start = base_addr
+ return ("4Q", (physical_start, cpu_start, physical_size, region_state))
+
+
+def generate_ns_buffer_guid(mmram_desc):
+ return HobGuid(EfiGuid(*MM_NS_BUFFER_GUID), *mmram_desc)
+
+
+def generate_pei_mmram_memory_reserve_guid(regions):
+ # uint32t n_reserved regions, 4 bytes for padding so that array is aligned,
+ # array of mmram descriptors
+ format_str = "I4x"
+ data = [len(regions)]
+ for desc_format_str, mmram_desc in regions:
+ format_str += desc_format_str
+ data.extend(mmram_desc)
+ guid_data = (format_str, data)
+ return HobGuid(EfiGuid(*MM_PEI_MMRAM_MEMORY_RESERVE_GUID), *guid_data)
+
+
+def generate_hob_from_fdt_node(sp_fdt, hob_offset, hob_size=None):
+ """Create a HOB list binary from an SP FDT."""
+ fv_hob = None
+ ns_buffer_hob = None
+ mmram_reserve_hob = None
+ shared_buf_hob = None
+
+ load_address = get_integer_property_value(sp_fdt, "load-address")
+ img_size = get_integer_property_value(sp_fdt, "image-size")
+ entrypoint_offset = get_integer_property_value(sp_fdt, "entrypoint-offset")
+
+ if entrypoint_offset is None:
+ entrypoint_offset = 0x0
+ if hob_offset is None:
+ hob_offset = 0x0
+ if img_size is None:
+ img_size = 0x0
+
+ regions = []
+
+ # StMM requires the first memory region described in the
+ # MM_PEI_MMRAM_MEMORY_RESERVE_GUID describe the full partition layout.
+ regions.append(generate_stmm_region_descriptor(load_address, img_size))
+
+ if sp_fdt.exist_node("memory-regions"):
+ if sp_fdt.exist_property("xlat-granule"):
+ granule = int(sp_fdt.get_property("xlat-granule").value)
+ else:
+ # Default granule to 4K
+ granule = 0
+ memory_regions = sp_fdt.get_node("memory-regions")
+ for node in memory_regions.nodes:
+ base_addr = get_integer_property_value(node, "base-address")
+ page_count = get_integer_property_value(node, "pages-count")
+
+ if base_addr is None:
+ offset = get_integer_property_value(
+ node, "load-address-relative-offset"
+ )
+ if offset is None:
+ # Cannot create memory descriptor without base address, so skip
+ # node if base address cannot be defined
+ continue
+ else:
+ base_addr = load_address + offset
+
+ if node.name.strip() == "heap":
+ region_state = STMM_MMRAM_REGION_STATE_HEAP
+ else:
+ region_state = STMM_MMRAM_REGION_STATE_DEFAULT
+
+ mmram_desc = generate_mmram_desc(
+ base_addr, page_count, granule, region_state
+ )
+
+ if node.name.strip() == "ns_comm_buffer":
+ ns_buffer_hob = generate_ns_buffer_guid(mmram_desc)
+
+ regions.append(mmram_desc)
+
+ mmram_reserve_hob = generate_pei_mmram_memory_reserve_guid(regions)
+
+ fv_hob = FirmwareVolumeHob(load_address, entrypoint_offset, img_size)
+ hob_list_base = load_address + hob_offset
+
+ # TODO assuming default of 1 page allocated for HOB List
+ if hob_size is not None:
+ max_table_size = hob_size
+ else:
+ max_table_size = 1 << PAGE_SIZE_SHIFT
+ phit = HandoffInfoTable(
+ load_address, entrypoint_offset + img_size, hob_list_base, max_table_size
+ )
+
+ # Create a HobList containing only PHIT and EndofHobList HOBs.
+ hob_list = HobList(phit)
+
+ # Add HOBs to HOB list
+ if fv_hob is not None:
+ hob_list.add(fv_hob)
+ if ns_buffer_hob is not None:
+ hob_list.add(ns_buffer_hob)
+ if mmram_reserve_hob is not None:
+ hob_list.add(mmram_reserve_hob)
+ if shared_buf_hob is not None:
+ hob_list.add(shared_buf_hob)
+
+ return hob_list
diff --git a/tools/sptool/sp_mk_generator.py b/tools/sptool/sp_mk_generator.py
index f80050e..9a00c74 100644
--- a/tools/sptool/sp_mk_generator.py
+++ b/tools/sptool/sp_mk_generator.py
@@ -55,10 +55,15 @@
import re
import sys
import uuid
+import fdt
from spactions import SpSetupActions
+import hob
+import struct
+from hob import HobList
MAX_SP = 8
UUID_LEN = 4
+HOB_OFFSET_DEFAULT=0x2000
# Some helper functions to access args propagated to the action functions in
# SpSetupActions framework.
@@ -179,6 +184,28 @@
write_to_sp_mk_gen(f"FDT_SOURCES += {manifest_path}", args)
return args
+@SpSetupActions.sp_action(exec_order=1)
+def generate_hob_list(sp_layout, sp, args: dict):
+ '''
+ Generates a HOB file for the partition, if it requested it in its FF-A
+ manifest.
+ '''
+ with open(get_sp_manifest_full_path(sp_layout[sp], args), "r") as f:
+ sp_fdt = fdt.parse_dts(f.read())
+
+ if sp_fdt.exist_property('hob_list', '/boot-info'):
+ sp_hob_name = os.path.basename(sp + ".hob.bin")
+ sp_hob_name = os.path.join(args["out_dir"], f"{sp_hob_name}")
+
+ # Add to the args so it can be consumed by the TL pkg function.
+ sp_layout[sp]["hob_path"] = sp_hob_name
+ hob_list = hob.generate_hob_from_fdt_node(sp_fdt, HOB_OFFSET_DEFAULT)
+ with open(sp_hob_name, "wb") as h:
+ for block in hob_list.get_list():
+ h.write(block.pack())
+
+ return args
+
def generate_sp_pkg(sp_node, pkg, sp_img, sp_dtb):
''' Generates the rule in case SP is to be generated in an SP Pkg. '''
pm_offset = get_pm_offset(sp_node)
@@ -200,11 +227,12 @@
TE_SP_BINARY = 0x103
# TE Type for the HOB List.
TE_HOB_LIST = 0x3
- tlc_add_hob = f"\t$(Q)poetry run tlc add --entry {TE_HOB_LIST} {hob_path} {pkg}" if hob_path is not None else ""
+ tlc_add_hob = f"\t$(Q)$(TLCTOOL) add --entry {TE_HOB_LIST} {hob_path} {pkg}" if hob_path is not None else ""
return f'''
{pkg}: {sp_dtb} {sp_img}
\t$(Q)echo Generating {pkg}
\t$(Q)$(TLCTOOL) create --size {get_size(sp_node)} --entry {TE_FFA_MANIFEST} {sp_dtb} {pkg} --align 12
+{tlc_add_hob}
\t$(Q)$(TLCTOOL) add --entry {TE_SP_BINARY} {sp_img} {pkg}
'''
@@ -228,7 +256,10 @@
if package_type == "sp_pkg":
partition_pkg_rule = generate_sp_pkg(sp_layout[sp], pkg, sp_img, sp_dtb)
elif package_type == "tl_pkg":
- partition_pkg_rule = generate_tl_pkg(sp_layout[sp], pkg, sp_img, sp_dtb)
+ # Conditionally provide the Hob.
+ hob_path = sp_layout[sp]["hob_path"] if "hob_path" in sp_layout[sp] else None
+ partition_pkg_rule = generate_tl_pkg(
+ sp_layout[sp], pkg, sp_img, sp_dtb, hob_path)
else:
raise ValueError(f"Specified invalid pkg type {package_type}")