Merge "feat(handoff): add transfer entry printer" into integration
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 3f1fff2..decb2f9 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -42,7 +42,7 @@
groups:
dev-deps:
patterns: ["*"]
- update-types: ["major", "minor", "patch"]
+ update-types: ["minor", "patch"]
- target-branch: "lts-v2.10"
package-ecosystem: "pip"
diff --git a/Makefile b/Makefile
index 5682f93..413ce46 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 \
@@ -1252,7 +1256,6 @@
PSA_FWU_METADATA_FW_STORE_DESC \
ENABLE_MPMM \
FEAT_PABANDON \
- ENABLE_MPMM_FCONF \
FEATURE_DETECTION \
TRNG_SUPPORT \
ENABLE_ERRATA_ALL \
@@ -1361,7 +1364,6 @@
DISABLE_MTPMU \
ENABLE_FEAT_AMU \
ENABLE_AMU_AUXILIARY_COUNTERS \
- ENABLE_AMU_FCONF \
AMU_RESTRICT_COUNTERS \
ENABLE_ASSERTIONS \
ENABLE_BTI \
@@ -1454,7 +1456,6 @@
ENABLE_FEAT_HCX \
ENABLE_MPMM \
FEAT_PABANDON \
- ENABLE_MPMM_FCONF \
ENABLE_FEAT_FGT \
ENABLE_FEAT_FGT2 \
ENABLE_FEAT_FPMR \
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 9b2b139..e390915 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -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)
@@ -114,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/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/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/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 8840e7f..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
@@ -532,10 +528,6 @@
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_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.
-
- ``ENABLE_PIE``: Boolean option to enable Position Independent Executable(PIE)
support within generic code in TF-A. This option is currently only supported
in BL2, BL31, and BL32 (TSP) for AARCH64 binaries, and
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 9ca2aa9..d06d153 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()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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/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 b1d1f09..85b33aa 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -1560,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 abe379d..f85da97 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -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)
diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S
index 4864596..2f2aeaf 100644
--- a/include/arch/aarch64/el3_common_macros.S
+++ b/include/arch/aarch64/el3_common_macros.S
@@ -454,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.
* ---------------------------------------------------------------------
@@ -473,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/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_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/cpu_macros.S b/include/lib/cpus/aarch64/cpu_macros.S
index f3df595..a43746f 100644
--- a/include/lib/cpus/aarch64/cpu_macros.S
+++ b/include/lib/cpus/aarch64/cpu_macros.S
@@ -631,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/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_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/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/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/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/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/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_a510.S b/lib/cpus/aarch64/cortex_a510.S
index cbeeb2b..81a227b 100644
--- a/lib/cpus/aarch64/cortex_a510.S
+++ b/lib/cpus/aarch64/cortex_a510.S
@@ -111,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)
@@ -209,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 6714a53..ac8019e 100644
--- a/lib/cpus/aarch64/cortex_a520.S
+++ b/lib/cpus/aarch64/cortex_a520.S
@@ -58,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_a710.S b/lib/cpus/aarch64/cortex_a710.S
index cb24aa1..e8f5a80 100644
--- a/lib/cpus/aarch64/cortex_a710.S
+++ b/lib/cpus/aarch64/cortex_a710.S
@@ -250,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 e50764d..d9c0df2 100644
--- a/lib/cpus/aarch64/cortex_a715.S
+++ b/lib/cpus/aarch64/cortex_a715.S
@@ -138,6 +138,7 @@
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_a720.S b/lib/cpus/aarch64/cortex_a720.S
index 2991f93..e639996 100644
--- a/lib/cpus/aarch64/cortex_a720.S
+++ b/lib/cpus/aarch64/cortex_a720.S
@@ -83,6 +83,7 @@
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 c72a29e..1d51c44 100644
--- a/lib/cpus/aarch64/cortex_a720_ae.S
+++ b/lib/cpus/aarch64/cortex_a720_ae.S
@@ -32,6 +32,7 @@
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 a8c0db2..682ca45 100644
--- a/lib/cpus/aarch64/cortex_a725.S
+++ b/lib/cpus/aarch64/cortex_a725.S
@@ -32,6 +32,7 @@
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_alto.S b/lib/cpus/aarch64/cortex_alto.S
index 97192a6..69a630d 100644
--- a/lib/cpus/aarch64/cortex_alto.S
+++ b/lib/cpus/aarch64/cortex_alto.S
@@ -30,6 +30,7 @@
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
diff --git a/lib/cpus/aarch64/cortex_arcadia.S b/lib/cpus/aarch64/cortex_arcadia.S
deleted file mode 100644
index ae8eb91..0000000
--- a/lib/cpus/aarch64/cortex_arcadia.S
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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_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_prologue cortex_arcadia
-
-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 cdf6284..4cdec32 100644
--- a/lib/cpus/aarch64/cortex_gelas.S
+++ b/lib/cpus/aarch64/cortex_gelas.S
@@ -40,6 +40,7 @@
/* 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
/* ----------------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_x2.S b/lib/cpus/aarch64/cortex_x2.S
index 549beec..b11c37d 100644
--- a/lib/cpus/aarch64/cortex_x2.S
+++ b/lib/cpus/aarch64/cortex_x2.S
@@ -195,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 da9e306..3d52dae 100644
--- a/lib/cpus/aarch64/cortex_x3.S
+++ b/lib/cpus/aarch64/cortex_x3.S
@@ -136,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 53461c6..c067981 100644
--- a/lib/cpus/aarch64/cortex_x4.S
+++ b/lib/cpus/aarch64/cortex_x4.S
@@ -130,6 +130,7 @@
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 7dec375..093d91d 100644
--- a/lib/cpus/aarch64/cortex_x925.S
+++ b/lib/cpus/aarch64/cortex_x925.S
@@ -63,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/nevis.S b/lib/cpus/aarch64/nevis.S
index 0d04e65..b2aa26e 100644
--- a/lib/cpus/aarch64/nevis.S
+++ b/lib/cpus/aarch64/nevis.S
@@ -29,6 +29,7 @@
* ----------------------------------------------------
*/
msr SSBS, xzr
+ enable_mpmm
cpu_reset_func_end nevis
func nevis_core_pwr_dwn
diff --git a/lib/cpus/aarch64/travis.S b/lib/cpus/aarch64/travis.S
index 0a95e80..d53e46f 100644
--- a/lib/cpus/aarch64/travis.S
+++ b/lib/cpus/aarch64/travis.S
@@ -40,6 +40,7 @@
/* 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
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index 6415cb3..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
*/
@@ -209,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
@@ -237,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 */
@@ -260,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
@@ -288,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 */
@@ -604,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
@@ -616,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 dfd14b6..e28e1c3 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -661,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()) {
@@ -803,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);
}
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/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/psci_common.c b/lib/psci/psci_common.c
index 4bb23af..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
diff --git a/lib/psci/psci_suspend.c b/lib/psci/psci_suspend.c
index 05bbe39..0fb1ed3 100644
--- a/lib/psci/psci_suspend.c
+++ b/lib/psci/psci_suspend.c
@@ -42,12 +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)
{
- 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
@@ -223,7 +224,7 @@
#endif
#endif
max_off_lvl = psci_find_max_off_lvl(state_info);
- psci_suspend_to_pwrdown_start(end_pwrlvl, max_off_lvl, ep, state_info);
+ psci_suspend_to_pwrdown_start(idx, end_pwrlvl, end_pwrlvl, ep, state_info);
}
/*
@@ -382,5 +383,5 @@
/* 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/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/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/defaults.mk b/make_helpers/defaults.mk
index d514933..ec2aa1b 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -88,9 +88,6 @@
# Enable support for powerdown abandons
FEAT_PABANDON := 0
-# Enable MPMM configuration via FCONF.
-ENABLE_MPMM_FCONF := 0
-
# Flag to Enable Position Independant support (PIE)
ENABLE_PIE := 0
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/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 7bd3e74..1dd0b49 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -225,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 \
@@ -241,11 +242,9 @@
# travis/gelas need these
FEAT_PABANDON := 1
ERRATA_SME_POWER_DOWN := 1
- FVP_CPU_LIBS += lib/cpus/aarch64/neoverse_n3.S \
- lib/cpus/aarch64/cortex_gelas.S \
+ 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
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/rdv3/platform.mk b/plat/arm/board/neoverse_rd/platform/rdv3/platform.mk
index 245d930..1ddd0e4 100644
--- a/plat/arm/board/neoverse_rd/platform/rdv3/platform.mk
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/platform.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/tc/platform.mk b/plat/arm/board/tc/platform.mk
index 1e12a12..a056bc2 100644
--- a/plat/arm/board/tc/platform.mk
+++ b/plat/arm/board/tc/platform.mk
@@ -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
diff --git a/plat/arm/board/tc/tc_bl31_setup.c b/plat/arm/board/tc/tc_bl31_setup.c
index c5ebfde..5d19aeb 100644
--- a/plat/arm/board/tc/tc_bl31_setup.c
+++ b/plat/arm/board/tc/tc_bl31_setup.c
@@ -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)
{
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/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/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/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/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/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/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c
index 37f2a2f..117934f 100644
--- a/services/std_svc/drtm/drtm_main.c
+++ b/services/std_svc/drtm/drtm_main.c
@@ -104,12 +104,16 @@
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;
/* Fill out platform DRTM features structure */
@@ -130,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;
}
@@ -171,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);
@@ -785,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) { \