Merge "fix(checkpatch): detect issues in commit message" into integration
diff --git a/.ctags b/.ctags
new file mode 100644
index 0000000..5e608e4
--- /dev/null
+++ b/.ctags
@@ -0,0 +1,4 @@
+--regex-Asm=/^func[ \t]+([a-zA-Z_0-9]+)$/\1/l,function/
+--regex-Asm=/^.*\.macro[ \t]+([a-zA-Z_0-9]+)$/\1/m,macro/
+--regex-Asm=/^vector_entry[ \t]+([a-zA-Z_0-9]+)$/\1/l,function/
+--regex-Asm=/^.equ[ \t]+([a-zA-Z_0-9]+),/\1/l,name/
diff --git a/Makefile b/Makefile
index b440847..e157022 100644
--- a/Makefile
+++ b/Makefile
@@ -454,6 +454,9 @@
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)
@@ -972,25 +975,52 @@
endif
endif #(ENABLE_SME_FOR_SWD)
+# Enabling SVE for SWD requires enabling SVE for NWD due to ENABLE_FEAT
+# mechanism.
ifeq (${ENABLE_SVE_FOR_SWD},1)
- ifeq (${ENABLE_SVE_FOR_NS},0)
- $(error "ENABLE_SVE_FOR_SWD requires ENABLE_SVE_FOR_NS")
- endif
-endif #(ENABLE_SVE_FOR_SWD)
+ ifeq (${ENABLE_SVE_FOR_NS},0)
+ $(error "ENABLE_SVE_FOR_SWD requires ENABLE_SVE_FOR_NS")
+ endif
+endif
-# SVE and SME cannot be used with CTX_INCLUDE_FPREGS since secure manager does
-# its own context management including FPU registers.
-ifeq (${CTX_INCLUDE_FPREGS},1)
- ifneq (${ENABLE_SME_FOR_NS},0)
- $(error "ENABLE_SME_FOR_NS cannot be used with CTX_INCLUDE_FPREGS")
- endif
+# Enabling SVE for both the worlds typically requires the context
+# management of SVE registers. The only exception being SPMC at S-EL2.
+ifeq (${ENABLE_SVE_FOR_SWD}, 1)
+ ifneq (${ENABLE_SVE_FOR_NS}, 0)
+ ifeq (${CTX_INCLUDE_SVE_REGS}-$(SPMD_SPM_AT_SEL2),0-0)
+ $(warning "ENABLE_SVE_FOR_SWD and ENABLE_SVE_FOR_NS together require CTX_INCLUDE_SVE_REGS")
+ endif
+ endif
+endif
- ifeq (${ENABLE_SVE_FOR_NS},1)
- # Warning instead of error due to CI dependency on this
- $(warning "ENABLE_SVE_FOR_NS cannot be used with CTX_INCLUDE_FPREGS")
- $(warning "Forced ENABLE_SVE_FOR_NS=0")
- override ENABLE_SVE_FOR_NS := 0
- endif
+# Enabling SVE in either world while enabling CTX_INCLUDE_FPREGS requires
+# CTX_INCLUDE_SVE_REGS to be enabled due to architectural dependency between FP
+# and SVE registers.
+ifeq (${CTX_INCLUDE_FPREGS}, 1)
+ ifneq (${ENABLE_SVE_FOR_NS},0)
+ ifeq (${CTX_INCLUDE_SVE_REGS},0)
+ # Warning instead of error due to CI dependency on this
+ $(warning "CTX_INCLUDE_FPREGS and ENABLE_SVE_FOR_NS together require CTX_INCLUDE_SVE_REGS")
+ $(warning "Forced ENABLE_SVE_FOR_NS=0")
+ override ENABLE_SVE_FOR_NS := 0
+ endif
+ endif
+endif #(CTX_INCLUDE_FPREGS)
+
+# SVE context management is only required if secure world has access to SVE/FP
+# functionality.
+ifeq (${CTX_INCLUDE_SVE_REGS},1)
+ ifeq (${ENABLE_SVE_FOR_SWD},0)
+ $(error "CTX_INCLUDE_SVE_REGS requires ENABLE_SVE_FOR_SWD to also be enabled")
+ endif
+endif
+
+# SME cannot be used with CTX_INCLUDE_FPREGS since SPM does its own context
+# management including FPU registers.
+ifeq (${CTX_INCLUDE_FPREGS},1)
+ ifneq (${ENABLE_SME_FOR_NS},0)
+ $(error "ENABLE_SME_FOR_NS cannot be used with CTX_INCLUDE_FPREGS")
+ endif
endif #(CTX_INCLUDE_FPREGS)
ifeq ($(DRTM_SUPPORT),1)
@@ -1127,6 +1157,7 @@
CREATE_KEYS \
CTX_INCLUDE_AARCH32_REGS \
CTX_INCLUDE_FPREGS \
+ CTX_INCLUDE_SVE_REGS \
CTX_INCLUDE_EL2_REGS \
CTX_INCLUDE_MPAM_REGS \
DEBUG \
@@ -1165,6 +1196,7 @@
SEPARATE_CODE_AND_RODATA \
SEPARATE_BL2_NOLOAD_REGION \
SEPARATE_NOBITS_REGION \
+ SEPARATE_SIMD_SECTION \
SPIN_ON_BL1_EXIT \
SPM_MM \
SPMC_AT_EL3 \
@@ -1285,6 +1317,7 @@
COLD_BOOT_SINGLE_CPU \
CTX_INCLUDE_AARCH32_REGS \
CTX_INCLUDE_FPREGS \
+ CTX_INCLUDE_SVE_REGS \
CTX_INCLUDE_PAUTH_REGS \
CTX_INCLUDE_MPAM_REGS \
EL3_EXCEPTION_HANDLING \
@@ -1337,6 +1370,7 @@
SEPARATE_CODE_AND_RODATA \
SEPARATE_BL2_NOLOAD_REGION \
SEPARATE_NOBITS_REGION \
+ SEPARATE_SIMD_SECTION \
RECLAIM_INIT_CODE \
SPD_${SPD} \
SPIN_ON_BL1_EXIT \
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index 7e9fde3..336ad2b 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -42,10 +42,12 @@
bl31/bl31_context_mgmt.c \
bl31/bl31_traps.c \
common/runtime_svc.c \
+ lib/cpus/errata_common.c \
lib/cpus/aarch64/dsu_helpers.S \
plat/common/aarch64/platform_mp_stack.S \
services/arm_arch_svc/arm_arch_svc_setup.c \
services/std_svc/std_svc_setup.c \
+ lib/el3_runtime/simd_ctx.c \
${PSCI_LIB_SOURCES} \
${SPMD_SOURCES} \
${SPM_MM_SOURCES} \
@@ -109,6 +111,10 @@
BL31_SOURCES += lib/extensions/fgt/fgt2.c
endif
+ifneq (${ENABLE_FEAT_TCR2},0)
+BL31_SOURCES += lib/extensions/tcr/tcr2.c
+endif
+
ifeq (${ENABLE_MPMM},1)
BL31_SOURCES += ${MPMM_SOURCES}
endif
diff --git a/changelog.yaml b/changelog.yaml
index 2b760c7..d073a84 100644
--- a/changelog.yaml
+++ b/changelog.yaml
@@ -805,6 +805,9 @@
- title: RAS
scope: ras
+ - title: SIMD
+ scope: simd
+
- title: FCONF
scope: fconf
@@ -1402,6 +1405,7 @@
- git-hooks
- title: Tools
+ scope: tools
subsections:
- title: STM32 Image
@@ -1447,6 +1451,9 @@
- title: Transfer List Compiler
scope: tlc
+ - title: Chain of Trust device tree to C source file
+ scope: cot-dt2c
+
- title: Dependencies
scope: deps
diff --git a/common/fdt_fixup.c b/common/fdt_fixup.c
index 1bad74f..59b7543 100644
--- a/common/fdt_fixup.c
+++ b/common/fdt_fixup.c
@@ -197,6 +197,7 @@
uintptr_t base, size_t size)
{
int offs = fdt_path_offset(dtb, "/reserved-memory");
+ int node;
uint32_t addresses[4];
int ac, sc;
unsigned int idx = 0;
@@ -213,6 +214,24 @@
fdt_setprop(dtb, offs, "ranges", NULL, 0);
}
+ /* Check for existing regions */
+ fdt_for_each_subnode(node, dtb, offs) {
+ uintptr_t c_base;
+ size_t c_size;
+ int ret;
+
+ ret = fdt_get_reg_props_by_index(dtb, node, 0, &c_base, &c_size);
+ /* Ignore illegal subnodes */
+ if (ret != 0) {
+ continue;
+ }
+
+ /* existing region entirely contains the new region */
+ if (base >= c_base && (base + size) <= (c_base + c_size)) {
+ return 0;
+ }
+ }
+
if (ac > 1) {
addresses[idx] = cpu_to_fdt32(HIGH_BITS(base));
idx++;
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index cbed72f..8bb12ab 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -565,8 +565,8 @@
^^^^^^^^^^^^^^^^^^^^^^^^^^^
:|M|: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
:|G|: `abdellatif-elkhlifi`_
-:|M|: Xueliang Zhong <xueliang.zhong@arm.com>
-:|G|: `xueliang-zhong-arm`_
+:|M|: Hugues Kamba Mpiana <hugues.kambampiana@arm.com>
+:|G|: `hugues-kambampiana-arm`_
:|F|: plat/arm/board/corstone700
:|F|: plat/arm/board/a5ds
:|F|: plat/arm/board/corstone1000
@@ -858,8 +858,6 @@
:|G|: `rockchip-linux`_
:|M|: Heiko Stuebner <heiko@sntech.de>
:|G|: `mmind`_
-:|M|: Julius Werner <jwerner@chromium.org>
-:|G|: `jwerner-chromium`_
:|F|: plat/rockchip/
STMicroelectronics platform ports
@@ -1050,6 +1048,7 @@
.. _harrisonmutai-arm: https://github.com/harrisonmutai-arm
.. _hilamirandakuzi1: https://github.com/hilamirandakuzi1
.. _hzhuang1: https://github.com/hzhuang1
+.. _hugues-kambampiana-arm: https://github.com/hugueskamba
.. _JackyBai: https://github.com/JackyBai
.. _J-Alves: https://github.com/J-Alves
.. _jason-ch-chen: https://github.com/jason-ch-chen
@@ -1112,7 +1111,6 @@
.. _vijayenthiran-arm: https://github.com/vijayenthiran-arm
.. _vishnu-banavath: https://github.com/vishnu-banavath
.. _vwadekar: https://github.com/vwadekar
-.. _xueliang-zhong-arm: https://github.com/xueliang-zhong-arm
.. _Yann-lms: https://github.com/Yann-lms
--------------
diff --git a/docs/components/context-management-library.rst b/docs/components/context-management-library.rst
index 56ba2ec..266b82a 100644
--- a/docs/components/context-management-library.rst
+++ b/docs/components/context-management-library.rst
@@ -98,14 +98,15 @@
4. **Dynamic discovery of Feature enablement by EL3**
-TF-A supports three states for feature enablement at EL3, to make them available
+TF-A supports four states for feature enablement at EL3, to make them available
for lower exception levels.
.. code:: c
- #define FEAT_STATE_DISABLED 0
- #define FEAT_STATE_ENABLED 1
- #define FEAT_STATE_CHECK 2
+ #define FEAT_STATE_DISABLED 0
+ #define FEAT_STATE_ENABLED 1
+ #define FEAT_STATE_CHECK 2
+ #define FEAT_STATE_CHECK_ASYMMETRIC 3
A pattern is established for feature enablement behavior.
Each feature must support the 3 possible values with rigid semantics.
@@ -119,7 +120,26 @@
- **FEAT_STATE_CHECK** - same as ``FEAT_STATE_ALWAYS`` except that the feature's
existence will be checked at runtime. Default on dynamic platforms (example: FVP).
-.. note::
+- **FEAT_STATE_CHECK_ASYMMETRIC** - same as ``FEAT_STATE_CHECK`` except that the feature's
+ existence is asymmetric across cores, which requires the feature existence is checked
+ during warmboot path also. Note that only limited number of features can be asymmetric.
+
+ .. note::
+ Only limited number of features can be ``FEAT_STATE_CHECK_ASYMMETRIC`` this is due to
+ the fact that Operating systems are designed for SMP systems.
+ There are no clear guidelines what kind of mismatch is allowed but following pointers
+ can help making a decision
+
+ - All mandatory features must be symmetric.
+ - Any feature that impacts the generation of page tables must be symmetric.
+ - Any feature access which does not trap to EL3 should be symmetric.
+ - Features related with profiling, debug and trace could be asymmetric
+ - Migration of vCPU/tasks between CPUs should not cause an error
+
+ Whenever there is asymmetric feature support is added for a feature TF-A need to add
+ feature specific code in context management code.
+
+ .. note::
``FEAT_RAS`` is an exception here, as it impacts the execution of EL3 and
it is essential to know its presence at compile time. Refer to ``ENABLE_FEAT``
macro under :ref:`Build Options` section for more details.
@@ -498,4 +518,4 @@
.. |Context Init WarmBoot| image:: ../resources/diagrams/context_init_warmboot.png
.. _Trustzone for AArch64: https://developer.arm.com/documentation/102418/0101/TrustZone-in-the-processor/Switching-between-Security-states
.. _Security States with RME: https://developer.arm.com/documentation/den0126/0100/Security-states
-.. _lib/el3_runtime/(aarch32/aarch64): https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/lib/el3_runtime
\ No newline at end of file
+.. _lib/el3_runtime/(aarch32/aarch64): https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/lib/el3_runtime
diff --git a/docs/components/cot-binding.rst b/docs/components/cot-binding.rst
index 702bb56..5d9acdf 100644
--- a/docs/components/cot-binding.rst
+++ b/docs/components/cot-binding.rst
@@ -108,7 +108,7 @@
Usage:
This property provides the Object ID of public key
- provided in the certificate which the help of which
+ provided in the certificate with the help of which
public key information can be extracted.
Value type: <string>
@@ -122,7 +122,7 @@
Usage:
This property provides the Object ID of hash provided in
- the certificate which the help of which hash information
+ the certificate with the help of which hash information
can be extracted.
Value type: <string>
@@ -138,7 +138,7 @@
trusted-key-cert: trusted-key-cert {
root-certificate;
image-id = <TRUSTED_KEY_CERT_ID>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
trusted-world-pk: trusted-world-pk {
oid = TRUSTED_WORLD_PK_OID;
@@ -152,7 +152,7 @@
image-id = <SCP_FW_KEY_CERT_ID>;
parent = <&trusted-key-cert>;
signing-key = <&trusted_world_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
scp_fw_content_pk: scp_fw_content_pk {
oid = SCP_FW_CONTENT_CERT_PK_OID;
@@ -312,13 +312,13 @@
#address-cells = <1>;
#size-cells = <0>;
- trusted-nv-counter: trusted_nv_counter {
+ trusted_nv_ctr: trusted_nv_ctr {
id = <TRUSTED_NV_CTR_ID>;
reg = <TFW_NVCTR_BASE>;
oid = TRUSTED_FW_NVCOUNTER_OID;
};
- non_trusted_nv_counter: non_trusted_nv_counter {
+ non_trusted_nv_ctr: non_trusted_nv_ctr {
id = <NON_TRUSTED_NV_CTR_ID>;
reg = <NTFW_CTR_BASE>;
oid = NON_TRUSTED_FW_NVCOUNTER_OID;
diff --git a/docs/components/ffa-manifest-binding.rst b/docs/components/ffa-manifest-binding.rst
index ee322ac..29b89b2 100644
--- a/docs/components/ffa-manifest-binding.rst
+++ b/docs/components/ffa-manifest-binding.rst
@@ -1,5 +1,5 @@
FF-A manifest binding to device tree
-========================================
+====================================
This document defines the nodes and properties used to define a partition,
according to the FF-A specification.
@@ -82,7 +82,7 @@
the partition. Absence of this field indicates that the entry point is at
offset 0x0 from the base of the partition's binary.
-- xlat-granule [mandatory]
+- xlat-granule
- value type: <u32>
- Translation granule used with the partition:
@@ -91,10 +91,10 @@
- 0x2: 64k
- boot-order
- - value type: <u16>
+ - value type: <u32>
- A unique number amongst all partitions that specifies if this partition
must be booted before others. The partition with the smaller number will be
- booted first.
+ booted first. Highest vlue allowed for this field is 0xFFFF.
- rx-tx-buffer
- value type: "memory-regions" node
@@ -103,13 +103,15 @@
The "compatible" must be the string "arm,ffa-manifest-rx_tx-buffer".
- messaging-method [mandatory]
- - value type: <u8>
+ - value type: <u32>
- Specifies which messaging methods are supported by the partition, set bit
means the feature is supported, clear bit - not supported:
- - Bit[0]: partition can receive direct requests if set
- - Bit[1]: partition can send direct requests if set
+ - Bit[0]: partition can receive direct requests via FFA_MSG_SEND_DIRECT_REQ ABI if set
+ - Bit[1]: partition can send direct requests via FFA_MSG_SEND_DIRECT_REQ ABI if set
- Bit[2]: partition can send and receive indirect messages
+ - Bit[9]: partition can receive direct requests via FFA_MSG_SEND_DIRECT_REQ2 ABI if set
+ - Bit[10]: partition can send direct requests via FFA_MSG_SEND_DIRECT_REQ2 ABI if set
- managed-exit
- value type: <empty>
@@ -117,6 +119,11 @@
- This field is deprecated in favor of ns-interrupts-action field in the FF-A
v1.1 EAC0 spec.
+- managed-exit-virq
+ - value type: <empty>
+ - Indicates if the partition needs managed exit, if supported, to be signaled
+ through vFIQ signal.
+
- ns-interrupts-action [mandatory]
- value type: <u32>
- Specifies the action that the SPMC must take in response to a Non-secure
@@ -136,6 +143,12 @@
- 0x0: Other-Secure interrupt is queued
- 0x1: Other-Secure interrupt is signaled
+- runtime-model
+ - value type: <u32>
+ - Indicates whether the SP execution can be preempted.
+ - This field is deprecated in favor of other-s-interrupts-action and
+ ns-interrupts-action fields in the FF-A v1.1 spec.
+
- has-primary-scheduler
- value type: <empty>
- Presence of this field indicates that the partition implements the primary
@@ -157,11 +170,6 @@
the FF-A boot information blob to be passed in the specified general purpose
register.
-- stream-endpoint-ids
- - value type: <prop-encoded-array>
- - List of <u32> tuples, identifying the IDs this partition is acting as
- proxy for.
-
- power-management-messages
- value type: <u32>
- Specifies which power management messages a partition subscribes to.
@@ -172,6 +180,17 @@
- Bit[1]: CPU_SUSPEND
- Bit[2]: CPU_SUSPEND_RESUME
+- vm-availability-messages
+ - value type: <u32>
+ - Specifies which VM availability messages a partition subscribes to. A set
+ bit means the partition should be informed of the event, clear bit - should
+ not be informed of event:
+
+ - Bit[0]: VM created
+ - Bit[1]: VM destroyed
+
+.. _memory_region_node:
+
Memory Regions
--------------
@@ -209,6 +228,25 @@
then communicate the region properties (including the base address chosen
by the partition manager) to the partition.
+- stream-ids
+ - value type: <prop-encoded-array>
+ - List of IDs belonging to a DMA capable peripheral device that has access to
+ the memory region represented by current node.
+ - Each ID must have been declared in exactly one device region node.
+
+- smmu-id
+ - value type: <u32>
+ - Identifies the SMMU IP that enforces the access control for the DMA device
+ that owns the above stream-ids.
+
+- stream-ids-access-permissions
+ - value type: <prop-encoded-array>
+ - List of attributes representing the instruction and data access permissions
+ used by the DMA device streams to access the memory region represented by
+ current node.
+
+.. _device_region_node:
+
Device Regions
--------------
@@ -251,11 +289,10 @@
- stream-ids
- value type: <prop-encoded-array>
- - A list of (id, mem-manage) pair, where:
+ - List of IDs where an ID is a unique <u32> value amongst all devices assigned
+ to the partition.
- - id: A unique <u32> value amongst all devices assigned to the partition.
-
-- interrupts [mandatory]
+- interrupts
- value type: <prop-encoded-array>
- A list of (id, attributes) pair describing the device interrupts, where:
@@ -306,4 +343,4 @@
--------------
-*Copyright (c) 2019-2022, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2019-2024, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/components/romlib-design.rst b/docs/components/romlib-design.rst
index 62c173a..c0f3ed3 100644
--- a/docs/components/romlib-design.rst
+++ b/docs/components/romlib-design.rst
@@ -71,6 +71,15 @@
The "library at ROM" contains a necessary init function that initialises the
global variables defined by the functions inside "library at ROM".
+Wrapper functions are specified at the link stage of compilation and cannot
+interpose uppon functions within the same translation unit. For example, if
+function ``fn_a`` calls ``fn_b`` within translation unit ``functions.c`` and
+the romlib jump table includes an entry for ``fn_b``, ``fn_a`` will include
+a reference to ``fn_b``'s original program text instead of the wrapper. Thus
+the jumptable author must take care to include public entry points into
+translation units to avoid paying the program text cost twice, once in the
+original executable and once in romlib.
+
Script
~~~~~~
@@ -86,7 +95,7 @@
3. ``romlib_generator.py genwrappers [args]`` - Generates a wrapper function for
each entry in the index file except for the ones that contain the keyword
- ``patch``. The generated wrapper file is called ``<fn_name>.s``.
+ ``patch``. The generated wrapper file is called ``wrappers.s``.
4. ``romlib_generator.py pre [args]`` - Preprocesses the index file which means
it resolves all the include commands in the file recursively. It can also
diff --git a/docs/components/secure-partition-manager.rst b/docs/components/secure-partition-manager.rst
index b6f4219..220c3ce 100644
--- a/docs/components/secure-partition-manager.rst
+++ b/docs/components/secure-partition-manager.rst
@@ -10,42 +10,12 @@
========
+--------+--------------------------------------+
-| CoT | Chain of Trust |
-+--------+--------------------------------------+
-| DMA | Direct Memory Access |
-+--------+--------------------------------------+
-| DTB | Device Tree Blob |
-+--------+--------------------------------------+
| DTS | Device Tree Source |
+--------+--------------------------------------+
-| EC | Execution Context |
-+--------+--------------------------------------+
-| FIP | Firmware Image Package |
-+--------+--------------------------------------+
| FF-A | Firmware Framework for Arm A-profile |
+--------+--------------------------------------+
-| IPA | Intermediate Physical Address |
-+--------+--------------------------------------+
-| JOP | Jump-Oriented Programming |
-+--------+--------------------------------------+
| NWd | Normal World |
+--------+--------------------------------------+
-| ODM | Original Design Manufacturer |
-+--------+--------------------------------------+
-| OEM | Original Equipment Manufacturer |
-+--------+--------------------------------------+
-| PA | Physical Address |
-+--------+--------------------------------------+
-| PE | Processing Element |
-+--------+--------------------------------------+
-| PM | Power Management |
-+--------+--------------------------------------+
-| PVM | Primary VM |
-+--------+--------------------------------------+
-| ROP | Return-Oriented Programming |
-+--------+--------------------------------------+
-| SMMU | System Memory Management Unit |
-+--------+--------------------------------------+
| SP | Secure Partition |
+--------+--------------------------------------+
| SPD | Secure Payload Dispatcher |
@@ -56,16 +26,8 @@
+--------+--------------------------------------+
| SPMD | SPM Dispatcher |
+--------+--------------------------------------+
-| SiP | Silicon Provider |
-+--------+--------------------------------------+
| SWd | Secure World |
+--------+--------------------------------------+
-| TLV | Tag-Length-Value |
-+--------+--------------------------------------+
-| TOS | Trusted Operating System |
-+--------+--------------------------------------+
-| VM | Virtual Machine |
-+--------+--------------------------------------+
Foreword
========
@@ -74,34 +36,14 @@
codebase:
#. S-EL2 SPMC based on the FF-A specification `[1]`_, enabling virtualization in
- the secure world, managing multiple S-EL1 or S-EL0 partitions.
+ the secure world, managing multiple S-EL1 or S-EL0 partitions `[5]`_.
#. EL3 SPMC based on the FF-A specification, managing a single S-EL1 partition
- without virtualization in the secure world.
+ without virtualization in the secure world `[6]`_.
#. EL3 SPM based on the MM specification, legacy implementation managing a
single S-EL0 partition `[2]`_.
These implementations differ in their respective SW architecture and only one
-can be selected at build time. This document:
-
-- describes the implementation from bullet 1. when the SPMC resides at S-EL2.
-- is not an architecture specification and it might provide assumptions
- on sections mandated as implementation-defined in the specification.
-- covers the implications to TF-A used as a bootloader, and Hafnium used as a
- reference code base for an S-EL2/SPMC secure firmware on platforms
- implementing the FEAT_SEL2 architecture extension.
-
-Terminology
------------
-
-- The term Hypervisor refers to the NS-EL2 component managing Virtual Machines
- (or partitions) in the normal world.
-- The term SPMC refers to the S-EL2 component managing secure partitions in
- the secure world when the FEAT_SEL2 architecture extension is implemented.
-- Alternatively, SPMC can refer to an S-EL1 component, itself being a secure
- partition and implementing the FF-A ABI on platforms not implementing the
- FEAT_SEL2 architecture extension.
-- The term VM refers to a normal world Virtual Machine managed by an Hypervisor.
-- The term SP refers to a secure world "Virtual Machine" managed by an SPMC.
+can be selected at build time.
Support for legacy platforms
----------------------------
@@ -123,16 +65,6 @@
- S-EL2 SPMC for platforms implementing the FEAT_SEL2 architecture
extension. The SPMD relays the FF-A protocol from EL3 to S-EL2.
-Sample reference stack
-======================
-
-The following diagram illustrates a possible configuration when the
-FEAT_SEL2 architecture extension is implemented, showing the SPMD
-and SPMC, one or multiple secure partitions, with an optional
-Hypervisor:
-
-.. image:: ../resources/diagrams/ff-a-spm-sel2.png
-
TF-A build options
==================
@@ -147,16 +79,15 @@
level to being at S-EL2. It defaults to enabled (value 1) when
SPD=spmd is chosen.
- **SPMC_AT_EL3**: this option adjusts the SPMC exception level to being
- at EL3.
-- If neither ``SPMD_SPM_AT_SEL2`` or ``SPMC_AT_EL3`` are enabled the SPMC
- exception level is set to S-EL1.
+ at EL3. If neither ``SPMD_SPM_AT_SEL2`` or ``SPMC_AT_EL3`` are enabled the
+ SPMC exception level is set to S-EL1.
``SPMD_SPM_AT_SEL2`` is enabled. The context save/restore routine
and exhaustive list of registers is visible at `[4]`_.
- **SPMC_AT_EL3_SEL0_SP**: this option enables the support to load SEL0 SP
when SPMC at EL3 support is enabled.
- **SP_LAYOUT_FILE**: this option specifies a text description file
providing paths to SP binary images and manifests in DTS format
- (see `Describing secure partitions`_). It
+ (see `[3]`_). It
is required when ``SPMD_SPM_AT_SEL2`` is enabled hence when multiple
secure partitions are to be loaded by BL2 on behalf of the SPMC.
@@ -275,1358 +206,28 @@
PLAT=fvp \
all fip
-FVP model invocation
-====================
-
-The FVP command line needs the following options to exercise the S-EL2 SPMC:
-
-+---------------------------------------------------+------------------------------------+
-| - cluster0.has_arm_v8-5=1 | Implements FEAT_SEL2, FEAT_PAuth, |
-| - cluster1.has_arm_v8-5=1 | and FEAT_BTI. |
-+---------------------------------------------------+------------------------------------+
-| - pci.pci_smmuv3.mmu.SMMU_AIDR=2 | Parameters required for the |
-| - pci.pci_smmuv3.mmu.SMMU_IDR0=0x0046123B | SMMUv3.2 modeling. |
-| - pci.pci_smmuv3.mmu.SMMU_IDR1=0x00600002 | |
-| - pci.pci_smmuv3.mmu.SMMU_IDR3=0x1714 | |
-| - pci.pci_smmuv3.mmu.SMMU_IDR5=0xFFFF0472 | |
-| - pci.pci_smmuv3.mmu.SMMU_S_IDR1=0xA0000002 | |
-| - pci.pci_smmuv3.mmu.SMMU_S_IDR2=0 | |
-| - pci.pci_smmuv3.mmu.SMMU_S_IDR3=0 | |
-+---------------------------------------------------+------------------------------------+
-| - cluster0.has_branch_target_exception=1 | Implements FEAT_BTI. |
-| - cluster1.has_branch_target_exception=1 | |
-+---------------------------------------------------+------------------------------------+
-| - cluster0.has_pointer_authentication=2 | Implements FEAT_PAuth |
-| - cluster1.has_pointer_authentication=2 | |
-+---------------------------------------------------+------------------------------------+
-| - cluster0.memory_tagging_support_level=2 | Implements FEAT_MTE2 |
-| - cluster1.memory_tagging_support_level=2 | |
-| - bp.dram_metadata.is_enabled=1 | |
-+---------------------------------------------------+------------------------------------+
-
-Sample FVP command line invocation:
-
-.. code:: shell
-
- <path-to-fvp-model>/FVP_Base_RevC-2xAEMvA -C pctl.startup=0.0.0.0 \
- -C cluster0.NUM_CORES=4 -C cluster1.NUM_CORES=4 -C bp.secure_memory=1 \
- -C bp.secureflashloader.fname=trusted-firmware-a/build/fvp/debug/bl1.bin \
- -C bp.flashloader0.fname=trusted-firmware-a/build/fvp/debug/fip.bin \
- -C bp.pl011_uart0.out_file=fvp-uart0.log -C bp.pl011_uart1.out_file=fvp-uart1.log \
- -C bp.pl011_uart2.out_file=fvp-uart2.log \
- -C cluster0.has_arm_v8-5=1 -C cluster1.has_arm_v8-5=1 \
- -C cluster0.has_pointer_authentication=2 -C cluster1.has_pointer_authentication=2 \
- -C cluster0.has_branch_target_exception=1 -C cluster1.has_branch_target_exception=1 \
- -C cluster0.memory_tagging_support_level=2 -C cluster1.memory_tagging_support_level=2 \
- -C bp.dram_metadata.is_enabled=1 \
- -C pci.pci_smmuv3.mmu.SMMU_AIDR=2 -C pci.pci_smmuv3.mmu.SMMU_IDR0=0x0046123B \
- -C pci.pci_smmuv3.mmu.SMMU_IDR1=0x00600002 -C pci.pci_smmuv3.mmu.SMMU_IDR3=0x1714 \
- -C pci.pci_smmuv3.mmu.SMMU_IDR5=0xFFFF0472 -C pci.pci_smmuv3.mmu.SMMU_S_IDR1=0xA0000002 \
- -C pci.pci_smmuv3.mmu.SMMU_S_IDR2=0 -C pci.pci_smmuv3.mmu.SMMU_S_IDR3=0
-
Boot process
============
-Loading Hafnium and secure partitions in the secure world
----------------------------------------------------------
-
-TF-A BL2 is the bootlader for the SPMC and SPs in the secure world.
-
-SPs may be signed by different parties (SiP, OEM/ODM, TOS vendor, etc.).
-Thus they are supplied as distinct signed entities within the FIP flash
-image. The FIP image itself is not signed hence this provides the ability
-to upgrade SPs in the field.
-
-Booting through TF-A
---------------------
-
-SP manifests
-~~~~~~~~~~~~
-
-An SP manifest describes SP attributes as defined in `[1]`_
-(partition manifest at virtual FF-A instance) in DTS format. It is
-represented as a single file associated with the SP. A sample is
-provided by `[5]`_. A binding document is provided by `[6]`_.
-
-Secure Partition packages
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Secure partitions are bundled as independent package files consisting
-of:
-
-- a header
-- a DTB
-- an image payload
-
-The header starts with a magic value and offset values to SP DTB and
-image payload. Each SP package is loaded independently by BL2 loader
-and verified for authenticity and integrity.
-
-The SP package identified by its UUID (matching FF-A uuid property) is
-inserted as a single entry into the FIP at end of the TF-A build flow
-as shown:
-
-.. code:: shell
-
- Trusted Boot Firmware BL2: offset=0x1F0, size=0x8AE1, cmdline="--tb-fw"
- EL3 Runtime Firmware BL31: offset=0x8CD1, size=0x13000, cmdline="--soc-fw"
- Secure Payload BL32 (Trusted OS): offset=0x1BCD1, size=0x15270, cmdline="--tos-fw"
- Non-Trusted Firmware BL33: offset=0x30F41, size=0x92E0, cmdline="--nt-fw"
- HW_CONFIG: offset=0x3A221, size=0x2348, cmdline="--hw-config"
- TB_FW_CONFIG: offset=0x3C569, size=0x37A, cmdline="--tb-fw-config"
- SOC_FW_CONFIG: offset=0x3C8E3, size=0x48, cmdline="--soc-fw-config"
- TOS_FW_CONFIG: offset=0x3C92B, size=0x427, cmdline="--tos-fw-config"
- NT_FW_CONFIG: offset=0x3CD52, size=0x48, cmdline="--nt-fw-config"
- B4B5671E-4A90-4FE1-B81F-FB13DAE1DACB: offset=0x3CD9A, size=0xC168, cmdline="--blob"
- D1582309-F023-47B9-827C-4464F5578FC8: offset=0x48F02, size=0xC168, cmdline="--blob"
-
-.. uml:: ../resources/diagrams/plantuml/fip-secure-partitions.puml
-
-Describing secure partitions
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-A json-formatted description file is passed to the build flow specifying paths
-to the SP binary image and associated DTS partition manifest file. The latter
-is processed by the dtc compiler to generate a DTB fed into the SP package.
-Optionally, the partition's json description can contain offsets for both
-the image and partition manifest within the SP package. Both offsets need to be
-4KB aligned, because it is the translation granule supported by Hafnium SPMC.
-These fields can be leveraged to support SPs with S1 translation granules that
-differ from 4KB, and to configure the regions allocated within the SP package,
-as well as to comply with the requirements for the implementation of the boot
-information protocol (see `Passing boot data to the SP`_ for more details). In
-case the offsets are absent in their json node, they default to 0x1000 and
-0x4000 for the manifest offset and image offset respectively.
-This file also specifies the SP owner (as an optional field) identifying the
-signing domain in case of dual root CoT.
-The SP owner can either be the silicon or the platform provider. The
-corresponding "owner" field value can either take the value of "SiP" or "Plat".
-In absence of "owner" field, it defaults to "SiP" owner.
-The UUID of the partition can be specified as a field in the description file or
-if it does not exist there the UUID is extracted from the DTS partition
-manifest.
-
-.. code:: shell
-
- {
- "tee1" : {
- "image": "tee1.bin",
- "pm": "tee1.dts",
- "owner": "SiP",
- "uuid": "1b1820fe-48f7-4175-8999-d51da00b7c9f"
- },
-
- "tee2" : {
- "image": "tee2.bin",
- "pm": "tee2.dts",
- "owner": "Plat"
- },
-
- "tee3" : {
- "image": {
- "file": "tee3.bin",
- "offset":"0x2000"
- },
- "pm": {
- "file": "tee3.dts",
- "offset":"0x6000"
- },
- "owner": "Plat"
- },
- }
-
-SPMC manifest
-~~~~~~~~~~~~~
-
-This manifest contains the SPMC *attribute* node consumed by the SPMD at boot
-time. It implements `[1]`_ (SP manifest at physical FF-A instance) and serves
-two different cases:
-
-- The SPMC resides at S-EL1: the SPMC manifest is used by the SPMD to setup a
- SP that co-resides with the SPMC and executes at S-EL1 or Secure Supervisor
- mode.
-- The SPMC resides at S-EL2: the SPMC manifest is used by the SPMD to setup
- the environment required by the SPMC to run at S-EL2. SPs run at S-EL1 or
- S-EL0.
-
-.. code:: shell
-
- attribute {
- spmc_id = <0x8000>;
- maj_ver = <0x1>;
- min_ver = <0x1>;
- exec_state = <0x0>;
- load_address = <0x0 0x6000000>;
- entrypoint = <0x0 0x6000000>;
- binary_size = <0x60000>;
- };
-
-- *spmc_id* defines the endpoint ID value that SPMC can query through
- ``FFA_ID_GET``.
-- *maj_ver/min_ver*. SPMD checks provided version versus its internal
- version and aborts if not matching.
-- *exec_state* defines the SPMC execution state (AArch64 or AArch32).
- Notice Hafnium used as a SPMC only supports AArch64.
-- *load_address* and *binary_size* are mostly used to verify secondary
- entry points fit into the loaded binary image.
-- *entrypoint* defines the cold boot primary core entry point used by
- SPMD (currently matches ``BL32_BASE``) to enter the SPMC.
-
-Other nodes in the manifest are consumed by Hafnium in the secure world.
-A sample can be found at `[7]`_:
-
-- The *hypervisor* node describes SPs. *is_ffa_partition* boolean attribute
- indicates a FF-A compliant SP. The *load_address* field specifies the load
- address at which BL2 loaded the SP package.
-- *cpus* node provide the platform topology and allows MPIDR to VMPIDR mapping.
- Note the primary core is declared first, then secondary cores are declared
- in reverse order.
-- The *memory* nodes provide platform information on the ranges of memory
- available for use by SPs at runtime. These ranges relate to either
- secure or non-secure memory, depending on the *device_type* field.
- If the field specifies "memory" the range is secure, else if it specifies
- "ns-memory" the memory is non-secure. The system integrator must exclude
- the memory used by other components that are not SPs, such as the monitor,
- or the SPMC itself, the OS Kernel/Hypervisor, or other NWd VMs. The SPMC
- limits the SP's address space such that they do not access memory outside
- of those ranges.
+The boot process involving SPMC is highly dependent on the SPMC implementation.
+It is recommended to refer to corresponding SPMC documentation for further
+details. Some aspects of boot process are described here in the greater interest
+of the project.
SPMC boot
-~~~~~~~~~
+---------
-The SPMC is loaded by BL2 as the BL32 image.
+When SPMC resides at a lower EL i.e., S-EL1 or S-EL2, it is loaded by BL2 as the
+BL32 image. The SPMC manifest is loaded by BL2 as the ``TOS_FW_CONFIG`` image `[7]`_.
-The SPMC manifest is loaded by BL2 as the ``TOS_FW_CONFIG`` image `[9]`_.
-
-BL2 passes the SPMC manifest address to BL31 through a register.
-
-At boot time, the SPMD in BL31 runs from the primary core, initializes the core
-contexts and launches the SPMC (BL32) passing the following information through
-registers:
+BL2 passes the SPMC manifest address to BL31 through a register. At boot time,
+the SPMD in BL31 runs from the primary core, initializes the core contexts and
+launches the SPMC (BL32) passing the following information through registers:
- X0 holds the ``TOS_FW_CONFIG`` physical address (or SPMC manifest blob).
- X1 holds the ``HW_CONFIG`` physical address.
- X4 holds the currently running core linear id.
-Loading of SPs
-~~~~~~~~~~~~~~
-
-At boot time, BL2 loads SPs sequentially in addition to the SPMC as depicted
-below:
-
-.. uml:: ../resources/diagrams/plantuml/bl2-loading-sp.puml
-
-Note this boot flow is an implementation sample on Arm's FVP platform.
-Platforms not using TF-A's *Firmware CONFiguration* framework would adjust to a
-different boot flow. The flow restricts to a maximum of 8 secure partitions.
-
-Secure boot
-~~~~~~~~~~~
-
-The SP content certificate is inserted as a separate FIP item so that BL2 loads SPMC,
-SPMC manifest, secure partitions and verifies them for authenticity and integrity.
-Refer to TBBR specification `[3]`_.
-
-The multiple-signing domain feature (in current state dual signing domain `[8]`_) allows
-the use of two root keys namely S-ROTPK and NS-ROTPK:
-
-- SPMC (BL32) and SPMC manifest are signed by the SiP using the S-ROTPK.
-- BL33 may be signed by the OEM using NS-ROTPK.
-- An SP may be signed either by SiP (using S-ROTPK) or by OEM (using NS-ROTPK).
-- A maximum of 4 partitions can be signed with the S-ROTPK key and 4 partitions
- signed with the NS-ROTPK key.
-
-Also refer to `Describing secure partitions`_ and `TF-A build options`_ sections.
-
-Hafnium in the secure world
-===========================
-
-General considerations
-----------------------
-
-Build platform for the secure world
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-In the Hafnium reference implementation specific code parts are only relevant to
-the secure world. Such portions are isolated in architecture specific files
-and/or enclosed by a ``SECURE_WORLD`` macro.
-
-Secure partitions scheduling
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The FF-A specification `[1]`_ provides two ways to relinquinsh CPU time to
-secure partitions. For this a VM (Hypervisor or OS kernel), or SP invokes one of:
-
-- the FFA_MSG_SEND_DIRECT_REQ interface.
-- the FFA_RUN interface.
-
-Additionally a secure interrupt can pre-empt the normal world execution and give
-CPU cycles by transitioning to EL3 and S-EL2.
-
-Platform topology
-~~~~~~~~~~~~~~~~~
-
-The *execution-ctx-count* SP manifest field can take the value of one or the
-total number of PEs. The FF-A specification `[1]`_ recommends the
-following SP types:
-
-- Pinned MP SPs: an execution context matches a physical PE. MP SPs must
- implement the same number of ECs as the number of PEs in the platform.
-- Migratable UP SPs: a single execution context can run and be migrated on any
- physical PE. Such SP declares a single EC in its SP manifest. An UP SP can
- receive a direct message request originating from any physical core targeting
- the single execution context.
-
-Parsing SP partition manifests
-------------------------------
-
-Hafnium consumes SP manifests as defined in `[1]`_ and `SP manifests`_.
-Note the current implementation may not implement all optional fields.
-
-The SP manifest may contain memory and device regions nodes. In case of
-an S-EL2 SPMC:
-
-- Memory regions are mapped in the SP EL1&0 Stage-2 translation regime at
- load time (or EL1&0 Stage-1 for an S-EL1 SPMC). A memory region node can
- specify RX/TX buffer regions in which case it is not necessary for an SP
- to explicitly invoke the ``FFA_RXTX_MAP`` interface. The memory referred
- shall be contained within the memory ranges defined in SPMC manifest. The
- NS bit in the attributes field should be consistent with the security
- state of the range that it relates to. I.e. non-secure memory shall be
- part of a non-secure memory range, and secure memory shall be contained
- in a secure memory range of a given platform.
-- Device regions are mapped in the SP EL1&0 Stage-2 translation regime (or
- EL1&0 Stage-1 for an S-EL1 SPMC) as peripherals and possibly allocate
- additional resources (e.g. interrupts).
-
-For the S-EL2 SPMC, base addresses for memory and device region nodes are IPAs
-provided the SPMC identity maps IPAs to PAs within SP EL1&0 Stage-2 translation
-regime.
-
-Note: in the current implementation both VTTBR_EL2 and VSTTBR_EL2 point to the
-same set of page tables. It is still open whether two sets of page tables shall
-be provided per SP. The memory region node as defined in the specification
-provides a memory security attribute hinting to map either to the secure or
-non-secure EL1&0 Stage-2 table if it exists.
-
-Passing boot data to the SP
----------------------------
-
-In `[1]`_ , the section "Boot information protocol" defines a method for passing
-data to the SPs at boot time. It specifies the format for the boot information
-descriptor and boot information header structures, which describe the data to be
-exchanged between SPMC and SP.
-The specification also defines the types of data that can be passed.
-The aggregate of both the boot info structures and the data itself is designated
-the boot information blob, and is passed to a Partition as a contiguous memory
-region.
-
-Currently, the SPM implementation supports the FDT type which is used to pass the
-partition's DTB manifest.
-
-The region for the boot information blob is allocated through the SP package.
-
-.. image:: ../resources/diagrams/partition-package.png
-
-To adjust the space allocated for the boot information blob, the json description
-of the SP (see section `Describing secure partitions`_) shall be updated to contain
-the manifest offset. If no offset is provided the manifest offset defaults to 0x1000,
-which is the page size in the Hafnium SPMC.
-
-The configuration of the boot protocol is done in the SPs manifest. As defined by
-the specification, the manifest field 'gp-register-num' configures the GP register
-which shall be used to pass the address to the partitions boot information blob when
-booting the partition.
-In addition, the Hafnium SPMC implementation requires the boot information arguments
-to be listed in a designated DT node:
-
-.. code:: shell
-
- boot-info {
- compatible = "arm,ffa-manifest-boot-info";
- ffa_manifest;
- };
-
-The whole secure partition package image (see `Secure Partition packages`_) is
-mapped to the SP secure EL1&0 Stage-2 translation regime. As such, the SP can
-retrieve the address for the boot information blob in the designated GP register,
-process the boot information header and descriptors, access its own manifest
-DTB blob and extract its partition manifest properties.
-
-SP Boot order
--------------
-
-SP manifests provide an optional boot order attribute meant to resolve
-dependencies such as an SP providing a service required to properly boot
-another SP. SPMC boots the SPs in accordance to the boot order attribute,
-lowest to the highest value. If the boot order attribute is absent from the FF-A
-manifest, the SP is treated as if it had the highest boot order value
-(i.e. lowest booting priority).
-
-It is possible for an SP to call into another SP through a direct request
-provided the latter SP has already been booted.
-
-Boot phases
------------
-
-Primary core boot-up
-~~~~~~~~~~~~~~~~~~~~
-
-Upon boot-up, BL31 hands over to the SPMC (BL32) on the primary boot physical
-core. The SPMC performs its platform initializations and registers the SPMC
-secondary physical core entry point physical address by the use of the
-`FFA_SECONDARY_EP_REGISTER`_ interface (SMC invocation from the SPMC to the SPMD
-at secure physical FF-A instance).
-
-The SPMC then creates secure partitions based on SP packages and manifests. Each
-secure partition is launched in sequence (`SP Boot order`_) on their "primary"
-execution context. If the primary boot physical core linear id is N, an MP SP is
-started using EC[N] on PE[N] (see `Platform topology`_). If the partition is a
-UP SP, it is started using its unique EC0 on PE[N].
-
-The SP primary EC (or the EC used when the partition is booted as described
-above):
-
-- Performs the overall SP boot time initialization, and in case of a MP SP,
- prepares the SP environment for other execution contexts.
-- In the case of a MP SP, it invokes the FFA_SECONDARY_EP_REGISTER at secure
- virtual FF-A instance (SMC invocation from SP to SPMC) to provide the IPA
- entry point for other execution contexts.
-- Exits through ``FFA_MSG_WAIT`` to indicate successful initialization or
- ``FFA_ERROR`` in case of failure.
-
-Secondary cores boot-up
-~~~~~~~~~~~~~~~~~~~~~~~
-
-Once the system is started and NWd brought up, a secondary physical core is
-woken up by the ``PSCI_CPU_ON`` service invocation. The TF-A SPD hook mechanism
-calls into the SPMD on the newly woken up physical core. Then the SPMC is
-entered at the secondary physical core entry point.
-
-In the current implementation, the first SP is resumed on the coresponding EC
-(the virtual CPU which matches the physical core). The implication is that the
-first SP must be a MP SP.
-
-In a linux based system, once secure and normal worlds are booted but prior to
-a NWd FF-A driver has been loaded:
-
-- The first SP has initialized all its ECs in response to primary core boot up
- (at system initialization) and secondary core boot up (as a result of linux
- invoking PSCI_CPU_ON for all secondary cores).
-- Other SPs have their first execution context initialized as a result of secure
- world initialization on the primary boot core. Other ECs for those SPs have to
- be run first through ffa_run to complete their initialization (which results
- in the EC completing with FFA_MSG_WAIT).
-
-Refer to `Power management`_ for further details.
-
-Notifications
--------------
-
-The FF-A v1.1 specification `[1]`_ defines notifications as an asynchronous
-communication mechanism with non-blocking semantics. It allows for one FF-A
-endpoint to signal another for service provision, without hindering its current
-progress.
-
-Hafnium currently supports 64 notifications. The IDs of each notification define
-a position in a 64-bit bitmap.
-
-The signaling of notifications can interchangeably happen between NWd and SWd
-FF-A endpoints.
-
-The SPMC is in charge of managing notifications from SPs to SPs, from SPs to
-VMs, and from VMs to SPs. An hypervisor component would only manage
-notifications from VMs to VMs. Given the SPMC has no visibility of the endpoints
-deployed in NWd, the Hypervisor or OS kernel must invoke the interface
-FFA_NOTIFICATION_BITMAP_CREATE to allocate the notifications bitmap per FF-A
-endpoint in the NWd that supports it.
-
-A sender can signal notifications once the receiver has provided it with
-permissions. Permissions are provided by invoking the interface
-FFA_NOTIFICATION_BIND.
-
-Notifications are signaled by invoking FFA_NOTIFICATION_SET. Henceforth
-they are considered to be in a pending sate. The receiver can retrieve its
-pending notifications invoking FFA_NOTIFICATION_GET, which, from that moment,
-are considered to be handled.
-
-Per the FF-A v1.1 spec, each FF-A endpoint must be associated with a scheduler
-that is in charge of donating CPU cycles for notifications handling. The
-FF-A driver calls FFA_NOTIFICATION_INFO_GET to retrieve the information about
-which FF-A endpoints have pending notifications. The receiver scheduler is
-called and informed by the FF-A driver, and it should allocate CPU cycles to the
-receiver.
-
-There are two types of notifications supported:
-
-- Global, which are targeted to a FF-A endpoint and can be handled within any of
- its execution contexts, as determined by the scheduler of the system.
-- Per-vCPU, which are targeted to a FF-A endpoint and to be handled within a
- a specific execution context, as determined by the sender.
-
-The type of a notification is set when invoking FFA_NOTIFICATION_BIND to give
-permissions to the sender.
-
-Notification signaling resorts to two interrupts:
-
-- Schedule Receiver Interrupt: non-secure physical interrupt to be handled by
- the FF-A driver within the receiver scheduler. At initialization the SPMC
- donates a SGI ID chosen from the secure SGI IDs range and configures it as
- non-secure. The SPMC triggers this SGI on the currently running core when
- there are pending notifications, and the respective receivers need CPU cycles
- to handle them.
-- Notifications Pending Interrupt: virtual interrupt to be handled by the
- receiver of the notification. Set when there are pending notifications for the
- given secure partition. The NPI is pended when the NWd relinquishes CPU cycles
- to an SP.
-
-The notifications receipt support is enabled in the partition FF-A manifest.
-
-Mandatory interfaces
---------------------
-
-The following interfaces are exposed to SPs:
-
-- ``FFA_VERSION``
-- ``FFA_FEATURES``
-- ``FFA_RX_RELEASE``
-- ``FFA_RXTX_MAP``
-- ``FFA_RXTX_UNMAP``
-- ``FFA_PARTITION_INFO_GET``
-- ``FFA_ID_GET``
-- ``FFA_MSG_WAIT``
-- ``FFA_MSG_SEND_DIRECT_REQ``
-- ``FFA_MSG_SEND_DIRECT_RESP``
-- ``FFA_MEM_DONATE``
-- ``FFA_MEM_LEND``
-- ``FFA_MEM_SHARE``
-- ``FFA_MEM_RETRIEVE_REQ``
-- ``FFA_MEM_RETRIEVE_RESP``
-- ``FFA_MEM_RELINQUISH``
-- ``FFA_MEM_FRAG_RX``
-- ``FFA_MEM_FRAG_TX``
-- ``FFA_MEM_RECLAIM``
-- ``FFA_RUN``
-
-As part of the FF-A v1.1 support, the following interfaces were added:
-
- - ``FFA_NOTIFICATION_BITMAP_CREATE``
- - ``FFA_NOTIFICATION_BITMAP_DESTROY``
- - ``FFA_NOTIFICATION_BIND``
- - ``FFA_NOTIFICATION_UNBIND``
- - ``FFA_NOTIFICATION_SET``
- - ``FFA_NOTIFICATION_GET``
- - ``FFA_NOTIFICATION_INFO_GET``
- - ``FFA_SPM_ID_GET``
- - ``FFA_SECONDARY_EP_REGISTER``
- - ``FFA_MEM_PERM_GET``
- - ``FFA_MEM_PERM_SET``
- - ``FFA_MSG_SEND2``
- - ``FFA_RX_ACQUIRE``
-
-FFA_VERSION
-~~~~~~~~~~~
-
-``FFA_VERSION`` requires a *requested_version* parameter from the caller.
-The returned value depends on the caller:
-
-- Hypervisor or OS kernel in NS-EL1/EL2: the SPMD returns the SPMC version
- specified in the SPMC manifest.
-- SP: the SPMC returns its own implemented version.
-- SPMC at S-EL1/S-EL2: the SPMD returns its own implemented version.
-
-FFA_FEATURES
-~~~~~~~~~~~~
-
-FF-A features supported by the SPMC may be discovered by secure partitions at
-boot (that is prior to NWd is booted) or run-time.
-
-The SPMC calling FFA_FEATURES at secure physical FF-A instance always get
-FFA_SUCCESS from the SPMD.
-
-The request made by an Hypervisor or OS kernel is forwarded to the SPMC and
-the response relayed back to the NWd.
-
-FFA_RXTX_MAP/FFA_RXTX_UNMAP
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When invoked from a secure partition FFA_RXTX_MAP maps the provided send and
-receive buffers described by their IPAs to the SP EL1&0 Stage-2 translation
-regime as secure buffers in the MMU descriptors.
-
-When invoked from the Hypervisor or OS kernel, the buffers are mapped into the
-SPMC EL2 Stage-1 translation regime and marked as NS buffers in the MMU
-descriptors. The provided addresses may be owned by a VM in the normal world,
-which is expected to receive messages from the secure world. The SPMC will in
-this case allocate internal state structures to facilitate RX buffer access
-synchronization (through FFA_RX_ACQUIRE interface), and to permit SPs to send
-messages.
-
-The FFA_RXTX_UNMAP unmaps the RX/TX pair from the translation regime of the
-caller, either it being the Hypervisor or OS kernel, as well as a secure
-partition.
-
-FFA_PARTITION_INFO_GET
-~~~~~~~~~~~~~~~~~~~~~~
-
-Partition info get call can originate:
-
-- from SP to SPMC
-- from Hypervisor or OS kernel to SPMC. The request is relayed by the SPMD.
-
-FFA_ID_GET
-~~~~~~~~~~
-
-The FF-A id space is split into a non-secure space and secure space:
-
-- FF-A ID with bit 15 clear relates to VMs.
-- FF-A ID with bit 15 set related to SPs.
-- FF-A IDs 0, 0xffff, 0x8000 are assigned respectively to the Hypervisor, SPMD
- and SPMC.
-
-The SPMD returns:
-
-- The default zero value on invocation from the Hypervisor.
-- The ``spmc_id`` value specified in the SPMC manifest on invocation from
- the SPMC (see `SPMC manifest`_)
-
-This convention helps the SPMC to determine the origin and destination worlds in
-an FF-A ABI invocation. In particular the SPMC shall filter unauthorized
-transactions in its world switch routine. It must not be permitted for a VM to
-use a secure FF-A ID as origin world by spoofing:
-
-- A VM-to-SP direct request/response shall set the origin world to be non-secure
- (FF-A ID bit 15 clear) and destination world to be secure (FF-A ID bit 15
- set).
-- Similarly, an SP-to-SP direct request/response shall set the FF-A ID bit 15
- for both origin and destination IDs.
-
-An incoming direct message request arriving at SPMD from NWd is forwarded to
-SPMC without a specific check. The SPMC is resumed through eret and "knows" the
-message is coming from normal world in this specific code path. Thus the origin
-endpoint ID must be checked by SPMC for being a normal world ID.
-
-An SP sending a direct message request must have bit 15 set in its origin
-endpoint ID and this can be checked by the SPMC when the SP invokes the ABI.
-
-The SPMC shall reject the direct message if the claimed world in origin endpoint
-ID is not consistent:
-
-- It is either forwarded by SPMD and thus origin endpoint ID must be a "normal
- world ID",
-- or initiated by an SP and thus origin endpoint ID must be a "secure world ID".
-
-
-FFA_MSG_SEND_DIRECT_REQ/FFA_MSG_SEND_DIRECT_RESP
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This is a mandatory interface for secure partitions consisting in direct request
-and responses with the following rules:
-
-- An SP can send a direct request to another SP.
-- An SP can receive a direct request from another SP.
-- An SP can send a direct response to another SP.
-- An SP cannot send a direct request to an Hypervisor or OS kernel.
-- An Hypervisor or OS kernel can send a direct request to an SP.
-- An SP can send a direct response to an Hypervisor or OS kernel.
-
-FFA_NOTIFICATION_BITMAP_CREATE/FFA_NOTIFICATION_BITMAP_DESTROY
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The secure partitions notifications bitmap are statically allocated by the SPMC.
-Hence, this interface is not to be issued by secure partitions.
-
-At initialization, the SPMC is not aware of VMs/partitions deployed in the
-normal world. Hence, the Hypervisor or OS kernel must use both ABIs for SPMC
-to be prepared to handle notifications for the provided VM ID.
-
-FFA_NOTIFICATION_BIND/FFA_NOTIFICATION_UNBIND
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Pair of interfaces to manage permissions to signal notifications. Prior to
-handling notifications, an FF-A endpoint must allow a given sender to signal a
-bitmap of notifications.
-
-If the receiver doesn't have notification support enabled in its FF-A manifest,
-it won't be able to bind notifications, hence forbidding it to receive any
-notifications.
-
-FFA_NOTIFICATION_SET/FFA_NOTIFICATION_GET
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-FFA_NOTIFICATION_GET retrieves all pending global notifications and
-per-vCPU notifications targeted to the current vCPU.
-
-Hafnium maintains a global count of pending notifications which gets incremented
-and decremented when handling FFA_NOTIFICATION_SET and FFA_NOTIFICATION_GET
-respectively. A delayed SRI is triggered if the counter is non-zero when the
-SPMC returns to normal world.
-
-FFA_NOTIFICATION_INFO_GET
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Hafnium maintains a global count of pending notifications whose information
-has been retrieved by this interface. The count is incremented and decremented
-when handling FFA_NOTIFICATION_INFO_GET and FFA_NOTIFICATION_GET respectively.
-It also tracks notifications whose information has been retrieved individually,
-such that it avoids duplicating returned information for subsequent calls to
-FFA_NOTIFICATION_INFO_GET. For each notification, this state information is
-reset when receiver called FFA_NOTIFICATION_GET to retrieve them.
-
-FFA_SPM_ID_GET
-~~~~~~~~~~~~~~
-
-Returns the FF-A ID allocated to an SPM component which can be one of SPMD
-or SPMC.
-
-At initialization, the SPMC queries the SPMD for the SPMC ID, using the
-FFA_ID_GET interface, and records it. The SPMC can also query the SPMD ID using
-the FFA_SPM_ID_GET interface at the secure physical FF-A instance.
-
-Secure partitions call this interface at the virtual FF-A instance, to which
-the SPMC returns the priorly retrieved SPMC ID.
-
-The Hypervisor or OS kernel can issue the FFA_SPM_ID_GET call handled by the
-SPMD, which returns the SPMC ID.
-
-FFA_SECONDARY_EP_REGISTER
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When the SPMC boots, all secure partitions are initialized on their primary
-Execution Context.
-
-The FFA_SECONDARY_EP_REGISTER interface is to be used by a secure partition
-from its first execution context, to provide the entry point address for
-secondary execution contexts.
-
-A secondary EC is first resumed either upon invocation of PSCI_CPU_ON from
-the NWd or by invocation of FFA_RUN.
-
-FFA_RX_ACQUIRE/FFA_RX_RELEASE
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The RX buffers can be used to pass information to an FF-A endpoint in the
-following scenarios:
-
- - When it was targetted by a FFA_MSG_SEND2 invokation from another endpoint.
- - Return the result of calling ``FFA_PARTITION_INFO_GET``.
- - In a memory share operation, as part of the ``FFA_MEM_RETRIEVE_RESP``,
- with the memory descriptor of the shared memory.
-
-If a normal world VM is expected to exchange messages with secure world,
-its RX/TX buffer addresses are forwarded to the SPMC via FFA_RXTX_MAP ABI,
-and are from this moment owned by the SPMC.
-The hypervisor must call the FFA_RX_ACQUIRE interface before attempting
-to use the RX buffer, in any of the aforementioned scenarios. A successful
-call to FFA_RX_ACQUIRE transfers ownership of RX buffer to hypervisor, such
-that it can be safely used.
-
-The FFA_RX_RELEASE interface is used after the FF-A endpoint is done with
-processing the data received in its RX buffer. If the RX buffer has been
-acquired by the hypervisor, the FFA_RX_RELEASE call must be forwarded to
-the SPMC to reestablish SPMC's RX ownership.
-
-An attempt from an SP to send a message to a normal world VM whose RX buffer
-was acquired by the hypervisor fails with error code FFA_BUSY, to preserve
-the RX buffer integrity.
-The operation could then be conducted after FFA_RX_RELEASE.
-
-FFA_MSG_SEND2
-~~~~~~~~~~~~~
-
-Hafnium copies a message from the sender TX buffer into receiver's RX buffer.
-For messages from SPs to VMs, operation is only possible if the SPMC owns
-the receiver's RX buffer.
-
-Both receiver and sender need to enable support for indirect messaging,
-in their respective partition manifest. The discovery of support
-of such feature can be done via FFA_PARTITION_INFO_GET.
-
-On a successful message send, Hafnium pends an RX buffer full framework
-notification for the receiver, to inform it about a message in the RX buffer.
-
-The handling of framework notifications is similar to that of
-global notifications. Binding of these is not necessary, as these are
-reserved to be used by the hypervisor or SPMC.
-
-SPMC-SPMD direct requests/responses
------------------------------------
-
-Implementation-defined FF-A IDs are allocated to the SPMC and SPMD.
-Using those IDs in source/destination fields of a direct request/response
-permits SPMD to SPMC communication and either way.
-
-- SPMC to SPMD direct request/response uses SMC conduit.
-- SPMD to SPMC direct request/response uses ERET conduit.
-
-This is used in particular to convey power management messages.
-
-Memory Sharing
---------------
-
-Hafnium implements the following memory sharing interfaces:
-
- - ``FFA_MEM_SHARE`` - for shared access between lender and borrower.
- - ``FFA_MEM_LEND`` - borrower to obtain exclusive access, though lender
- retains ownership of the memory.
- - ``FFA_MEM_DONATE`` - lender permanently relinquishes ownership of memory
- to the borrower.
-
-The ``FFA_MEM_RETRIEVE_REQ`` interface is for the borrower to request the
-memory to be mapped into its address space: for S-EL1 partitions the SPM updates
-their stage 2 translation regime; for S-EL0 partitions the SPM updates their
-stage 1 translation regime. On a successful call, the SPMC responds back with
-``FFA_MEM_RETRIEVE_RESP``.
-
-The ``FFA_MEM_RELINQUISH`` interface is for when the borrower is done with using
-a memory region.
-
-The ``FFA_MEM_RECLAIM`` interface is for the owner of the memory to reestablish
-its ownership and exclusive access to the memory shared.
-
-The memory transaction descriptors are transmitted via RX/TX buffers. In
-situations where the size of the memory transaction descriptor exceeds the
-size of the RX/TX buffers, Hafnium provides support for fragmented transmission
-of the full transaction descriptor. The ``FFA_MEM_FRAG_RX`` and ``FFA_MEM_FRAG_TX``
-interfaces are for receiving and transmitting the next fragment, respectively.
-
-If lender and borrower(s) are SPs, all memory sharing operations are supported.
-
-Hafnium also supports memory sharing operations between the normal world and the
-secure world. If there is an SP involved, the SPMC allocates data to track the
-state of the operation.
-
-The SPMC is also the designated allocator for the memory handle. The hypervisor
-or OS kernel has the possibility to rely on the SPMC to maintain the state
-of the operation, thus saving memory.
-A lender SP can only donate NS memory to a borrower from the normal world.
-
-The SPMC supports the hypervisor retrieve request, as defined by the FF-A
-v1.1 EAC0 specification, in section 16.4.3. The intent is to aid with operations
-that the hypervisor must do for a VM retriever. For example, when handling
-an FFA_MEM_RECLAIM, if the hypervisor relies on SPMC to keep the state
-of the operation, the hypervisor retrieve request can be used to obtain
-that state information, do the necessary validations, and update stage 2
-memory translation.
-
-Hafnium also supports memory lend and share targetting multiple borrowers.
-This is the case for a lender SP to multiple SPs, and for a lender VM to
-multiple endpoints (from both secure world and normal world). If there is
-at least one borrower VM, the hypervisor is in charge of managing its
-stage 2 translation on a successful memory retrieve.
-The semantics of ``FFA_MEM_DONATE`` implies ownership transmission,
-which should target only one partition.
-
-The memory share interfaces are backwards compatible with memory transaction
-descriptors from FF-A v1.0. These get translated to FF-A v1.1 descriptors for
-Hafnium's internal processing of the operation. If the FF-A version of a
-borrower is v1.0, Hafnium provides FF-A v1.0 compliant memory transaction
-descriptors on memory retrieve response.
-
-PE MMU configuration
---------------------
-
-With secure virtualization enabled (``HCR_EL2.VM = 1``) and for S-EL1
-partitions, two IPA spaces (secure and non-secure) are output from the
-secure EL1&0 Stage-1 translation.
-The EL1&0 Stage-2 translation hardware is fed by:
-
-- A secure IPA when the SP EL1&0 Stage-1 MMU is disabled.
-- One of secure or non-secure IPA when the secure EL1&0 Stage-1 MMU is enabled.
-
-``VTCR_EL2`` and ``VSTCR_EL2`` provide configuration bits for controlling the
-NS/S IPA translations. The following controls are set up:
-``VSTCR_EL2.SW = 0`` , ``VSTCR_EL2.SA = 0``, ``VTCR_EL2.NSW = 0``,
-``VTCR_EL2.NSA = 1``:
-
-- Stage-2 translations for the NS IPA space access the NS PA space.
-- Stage-2 translation table walks for the NS IPA space are to the secure PA space.
-
-Secure and non-secure IPA regions (rooted to by ``VTTBR_EL2`` and ``VSTTBR_EL2``)
-use the same set of Stage-2 page tables within a SP.
-
-The ``VTCR_EL2/VSTCR_EL2/VTTBR_EL2/VSTTBR_EL2`` virtual address space
-configuration is made part of a vCPU context.
-
-For S-EL0 partitions with VHE enabled, a single secure EL2&0 Stage-1 translation
-regime is used for both Hafnium and the partition.
-
-Schedule modes and SP Call chains
----------------------------------
-
-An SP execution context is said to be in SPMC scheduled mode if CPU cycles are
-allocated to it by SPMC. Correspondingly, an SP execution context is said to be
-in Normal world scheduled mode if CPU cycles are allocated by the normal world.
-
-A call chain represents all SPs in a sequence of invocations of a direct message
-request. When execution on a PE is in the secure state, only a single call chain
-that runs in the Normal World scheduled mode can exist. FF-A v1.1 spec allows
-any number of call chains to run in the SPMC scheduled mode but the Hafnium
-SPMC restricts the number of call chains in SPMC scheduled mode to only one for
-keeping the implementation simple.
-
-Partition runtime models
-------------------------
-
-The runtime model of an endpoint describes the transitions permitted for an
-execution context between various states. These are the four partition runtime
-models supported (refer to `[1]`_ section 7):
-
- - RTM_FFA_RUN: runtime model presented to an execution context that is
- allocated CPU cycles through FFA_RUN interface.
- - RTM_FFA_DIR_REQ: runtime model presented to an execution context that is
- allocated CPU cycles through FFA_MSG_SEND_DIRECT_REQ interface.
- - RTM_SEC_INTERRUPT: runtime model presented to an execution context that is
- allocated CPU cycles by SPMC to handle a secure interrupt.
- - RTM_SP_INIT: runtime model presented to an execution context that is
- allocated CPU cycles by SPMC to initialize its state.
-
-If an endpoint execution context attempts to make an invalid transition or a
-valid transition that could lead to a loop in the call chain, SPMC denies the
-transition with the help of above runtime models.
-
-Interrupt management
---------------------
-
-GIC ownership
-~~~~~~~~~~~~~
-
-The SPMC owns the GIC configuration. Secure and non-secure interrupts are
-trapped at S-EL2. The SPMC manages interrupt resources and allocates interrupt
-IDs based on SP manifests. The SPMC acknowledges physical interrupts and injects
-virtual interrupts by setting the use of vIRQ/vFIQ bits before resuming a SP.
-
-Abbreviations:
-
- - NS-Int: A non-secure physical interrupt. It requires a switch to the normal
- world to be handled if it triggers while execution is in secure world.
- - Other S-Int: A secure physical interrupt targeted to an SP different from
- the one that is currently running.
- - Self S-Int: A secure physical interrupt targeted to the SP that is currently
- running.
-
-Non-secure interrupt handling
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This section documents the actions supported in SPMC in response to a non-secure
-interrupt as per the guidance provided by FF-A v1.1 EAC0 specification.
-An SP specifies one of the following actions in its partition manifest:
-
- - Non-secure interrupt is signaled.
- - Non-secure interrupt is signaled after a managed exit.
- - Non-secure interrupt is queued.
-
-An SP execution context in a call chain could specify a less permissive action
-than subsequent SP execution contexts in the same call chain. The less
-permissive action takes precedence over the more permissive actions specified
-by the subsequent execution contexts. Please refer to FF-A v1.1 EAC0 section
-8.3.1 for further explanation.
-
-Secure interrupt handling
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This section documents the support implemented for secure interrupt handling in
-SPMC as per the guidance provided by FF-A v1.1 EAC0 specification.
-The following assumptions are made about the system configuration:
-
- - In the current implementation, S-EL1 SPs are expected to use the para
- virtualized ABIs for interrupt management rather than accessing the virtual
- GIC interface.
- - Unless explicitly stated otherwise, this support is applicable only for
- S-EL1 SPs managed by SPMC.
- - Secure interrupts are configured as G1S or G0 interrupts.
- - All physical interrupts are routed to SPMC when running a secure partition
- execution context.
- - All endpoints with multiple execution contexts have their contexts pinned
- to corresponding CPUs. Hence, a secure virtual interrupt cannot be signaled
- to a target vCPU that is currently running or blocked on a different
- physical CPU.
-
-A physical secure interrupt could trigger while CPU is executing in normal world
-or secure world.
-The action of SPMC for a secure interrupt depends on: the state of the target
-execution context of the SP that is responsible for handling the interrupt;
-whether the interrupt triggered while execution was in normal world or secure
-world.
-
-Secure interrupt signaling mechanisms
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Signaling refers to the mechanisms used by SPMC to indicate to the SP execution
-context that it has a pending virtual interrupt and to further run the SP
-execution context, such that it can handle the virtual interrupt. SPMC uses
-either the FFA_INTERRUPT interface with ERET conduit or vIRQ signal for signaling
-to S-EL1 SPs. When normal world execution is preempted by a secure interrupt,
-the SPMD uses the FFA_INTERRUPT ABI with ERET conduit to signal interrupt to SPMC
-running in S-EL2.
-
-+-----------+---------+---------------+---------------------------------------+
-| SP State | Conduit | Interface and | Description |
-| | | parameters | |
-+-----------+---------+---------------+---------------------------------------+
-| WAITING | ERET, | FFA_INTERRUPT,| SPMC signals to SP the ID of pending |
-| | vIRQ | Interrupt ID | interrupt. It pends vIRQ signal and |
-| | | | resumes execution context of SP |
-| | | | through ERET. |
-+-----------+---------+---------------+---------------------------------------+
-| BLOCKED | ERET, | FFA_INTERRUPT | SPMC signals to SP that an interrupt |
-| | vIRQ | | is pending. It pends vIRQ signal and |
-| | | | resumes execution context of SP |
-| | | | through ERET. |
-+-----------+---------+---------------+---------------------------------------+
-| PREEMPTED | vIRQ | NA | SPMC pends the vIRQ signal but does |
-| | | | not resume execution context of SP. |
-+-----------+---------+---------------+---------------------------------------+
-| RUNNING | ERET, | NA | SPMC pends the vIRQ signal and resumes|
-| | vIRQ | | execution context of SP through ERET. |
-+-----------+---------+---------------+---------------------------------------+
-
-Secure interrupt completion mechanisms
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-A SP signals secure interrupt handling completion to the SPMC through the
-following mechanisms:
-
- - ``FFA_MSG_WAIT`` ABI if it was in WAITING state.
- - ``FFA_RUN`` ABI if its was in BLOCKED state.
-
-This is a remnant of SPMC implementation based on the FF-A v1.0 specification.
-In the current implementation, S-EL1 SPs use the para-virtualized HVC interface
-implemented by SPMC to perform priority drop and interrupt deactivation (SPMC
-configures EOImode = 0, i.e. priority drop and deactivation are done together).
-The SPMC performs checks to deny the state transition upon invocation of
-either FFA_MSG_WAIT or FFA_RUN interface if the SP didn't perform the
-deactivation of the secure virtual interrupt.
-
-If the current SP execution context was preempted by a secure interrupt to be
-handled by execution context of target SP, SPMC resumes current SP after signal
-completion by target SP execution context.
-
-Actions for a secure interrupt triggered while execution is in normal world
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-+-------------------+----------+-----------------------------------------------+
-| State of target | Action | Description |
-| execution context | | |
-+-------------------+----------+-----------------------------------------------+
-| WAITING | Signaled | This starts a new call chain in SPMC scheduled|
-| | | mode. |
-+-------------------+----------+-----------------------------------------------+
-| PREEMPTED | Queued | The target execution must have been preempted |
-| | | by a non-secure interrupt. SPMC queues the |
-| | | secure virtual interrupt now. It is signaled |
-| | | when the target execution context next enters |
-| | | the RUNNING state. |
-+-------------------+----------+-----------------------------------------------+
-| BLOCKED, RUNNING | NA | The target execution context is blocked or |
-| | | running on a different CPU. This is not |
-| | | supported by current SPMC implementation and |
-| | | execution hits panic. |
-+-------------------+----------+-----------------------------------------------+
-
-If normal world execution was preempted by a secure interrupt, SPMC uses
-FFA_NORMAL_WORLD_RESUME ABI to indicate completion of secure interrupt handling
-and further returns execution to normal world.
-
-The following figure describes interrupt handling flow when a secure interrupt
-triggers while execution is in normal world:
-
-.. image:: ../resources/diagrams/ffa-secure-interrupt-handling-nwd.png
-
-A brief description of the events:
-
- - 1) Secure interrupt triggers while normal world is running.
- - 2) FIQ gets trapped to EL3.
- - 3) SPMD signals secure interrupt to SPMC at S-EL2 using FFA_INTERRUPT ABI.
- - 4) SPMC identifies target vCPU of SP and injects virtual interrupt (pends
- vIRQ).
- - 5) Assuming SP1 vCPU is in WAITING state, SPMC signals virtual interrupt
- using FFA_INTERRUPT with interrupt id as an argument and resumes the SP1
- vCPU using ERET in SPMC scheduled mode.
- - 6) Execution traps to vIRQ handler in SP1 provided that the virtual
- interrupt is not masked i.e., PSTATE.I = 0
- - 7) SP1 queries for the pending virtual interrupt id using a paravirtualized
- HVC call. SPMC clears the pending virtual interrupt state management
- and returns the pending virtual interrupt id.
- - 8) SP1 services the virtual interrupt and invokes the paravirtualized
- de-activation HVC call. SPMC de-activates the physical interrupt,
- clears the fields tracking the secure interrupt and resumes SP1 vCPU.
- - 9) SP1 performs secure interrupt completion through FFA_MSG_WAIT ABI.
- - 10) SPMC returns control to EL3 using FFA_NORMAL_WORLD_RESUME.
- - 11) EL3 resumes normal world execution.
-
-Actions for a secure interrupt triggered while execution is in secure world
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-+-------------------+----------+------------------------------------------------+
-| State of target | Action | Description |
-| execution context | | |
-+-------------------+----------+------------------------------------------------+
-| WAITING | Signaled | This starts a new call chain in SPMC scheduled |
-| | | mode. |
-+-------------------+----------+------------------------------------------------+
-| PREEMPTED by Self | Signaled | The target execution context reenters the |
-| S-Int | | RUNNING state to handle the secure virtual |
-| | | interrupt. |
-+-------------------+----------+------------------------------------------------+
-| PREEMPTED by | Queued | SPMC queues the secure virtual interrupt now. |
-| NS-Int | | It is signaled when the target execution |
-| | | context next enters the RUNNING state. |
-+-------------------+----------+------------------------------------------------+
-| BLOCKED | Signaled | Both preempted and target execution contexts |
-| | | must have been part of the Normal world |
-| | | scheduled call chain. Refer scenario 1 of |
-| | | Table 8.4 in the FF-A v1.1 EAC0 spec. |
-+-------------------+----------+------------------------------------------------+
-| RUNNING | NA | The target execution context is running on a |
-| | | different CPU. This scenario is not supported |
-| | | by current SPMC implementation and execution |
-| | | hits panic. |
-+-------------------+----------+------------------------------------------------+
-
-The following figure describes interrupt handling flow when a secure interrupt
-triggers while execution is in secure world. We assume OS kernel sends a direct
-request message to SP1. Further, SP1 sends a direct request message to SP2. SP1
-enters BLOCKED state and SPMC resumes SP2.
-
-.. image:: ../resources/diagrams/ffa-secure-interrupt-handling-swd.png
-
-A brief description of the events:
-
- - 1) Secure interrupt triggers while SP2 is running.
- - 2) SP2 gets preempted and execution traps to SPMC as IRQ.
- - 3) SPMC finds the target vCPU of secure partition responsible for handling
- this secure interrupt. In this scenario, it is SP1.
- - 4) SPMC pends vIRQ for SP1 and signals through FFA_INTERRUPT interface.
- SPMC further resumes SP1 through ERET conduit. Note that SP1 remains in
- Normal world schedule mode.
- - 6) Execution traps to vIRQ handler in SP1 provided that the virtual
- interrupt is not masked i.e., PSTATE.I = 0
- - 7) SP1 queries for the pending virtual interrupt id using a paravirtualized
- HVC call. SPMC clears the pending virtual interrupt state management
- and returns the pending virtual interrupt id.
- - 8) SP1 services the virtual interrupt and invokes the paravirtualized
- de-activation HVC call. SPMC de-activates the physical interrupt and
- clears the fields tracking the secure interrupt and resumes SP1 vCPU.
- - 9) Since SP1 direct request completed with FFA_INTERRUPT, it resumes the
- direct request to SP2 by invoking FFA_RUN.
- - 9) SPMC resumes the pre-empted vCPU of SP2.
-
-EL3 interrupt handling
-~~~~~~~~~~~~~~~~~~~~~~
-
-In GICv3 based systems, EL3 interrupts are configured as Group0 secure
-interrupts. Execution traps to SPMC when a Group0 interrupt triggers while an
-SP is running. Further, SPMC running at S-EL2 uses FFA_EL3_INTR_HANDLE ABI to
-request EL3 platform firmware to handle a pending Group0 interrupt.
-Similarly, SPMD registers a handler with interrupt management framework to
-delegate handling of Group0 interrupt to the platform if the interrupt triggers
-in normal world.
-
- - Platform hook
-
- - plat_spmd_handle_group0_interrupt
-
- SPMD provides platform hook to handle Group0 secure interrupts. In the
- current design, SPMD expects the platform not to delegate handling to the
- NWd (such as through SDEI) while processing Group0 interrupts.
-
-Power management
-----------------
-
-In platforms with or without secure virtualization:
-
-- The NWd owns the platform PM policy.
-- The Hypervisor or OS kernel is the component initiating PSCI service calls.
-- The EL3 PSCI library is in charge of the PM coordination and control
- (eventually writing to platform registers).
-- While coordinating PM events, the PSCI library calls backs into the Secure
- Payload Dispatcher for events the latter has statically registered to.
-
-When using the SPMD as a Secure Payload Dispatcher:
-
-- A power management event is relayed through the SPD hook to the SPMC.
-- In the current implementation only cpu on (svc_on_finish) and cpu off
- (svc_off) hooks are registered.
-- The behavior for the cpu on event is described in `Secondary cores boot-up`_.
- The SPMC is entered through its secondary physical core entry point.
-- The cpu off event occurs when the NWd calls PSCI_CPU_OFF. The PM event is
- signaled to the SPMC through a power management framework message.
- It consists in a SPMD-to-SPMC direct request/response (`SPMC-SPMD direct
- requests/responses`_) conveying the event details and SPMC response.
- The SPMD performs a synchronous entry into the SPMC. The SPMC is entered and
- updates its internal state to reflect the physical core is being turned off.
- In the current implementation no SP is resumed as a consequence. This behavior
- ensures a minimal support for CPU hotplug e.g. when initiated by the NWd linux
- userspace.
-
-Arm architecture extensions for security hardening
-==================================================
-
-Hafnium supports the following architecture extensions for security hardening:
-
-- Pointer authentication (FEAT_PAuth): the extension permits detection of forged
- pointers used by ROP type of attacks through the signing of the pointer
- value. Hafnium is built with the compiler branch protection option to permit
- generation of a pointer authentication code for return addresses (pointer
- authentication for instructions). The APIA key is used while Hafnium runs.
- A random key is generated at boot time and restored upon entry into Hafnium
- at run-time. APIA and other keys (APIB, APDA, APDB, APGA) are saved/restored
- in vCPU contexts permitting to enable pointer authentication in VMs/SPs.
-- Branch Target Identification (FEAT_BTI): the extension permits detection of
- unexpected indirect branches used by JOP type of attacks. Hafnium is built
- with the compiler branch protection option, inserting land pads at function
- prologues that are reached by indirect branch instructions (BR/BLR).
- Hafnium code pages are marked as guarded in the EL2 Stage-1 MMU descriptors
- such that an indirect branch must always target a landpad. A fault is
- triggered otherwise. VMs/SPs can (independently) mark their code pages as
- guarded in the EL1&0 Stage-1 translation regime.
-- Memory Tagging Extension (FEAT_MTE): the option permits detection of out of
- bound memory array accesses or re-use of an already freed memory region.
- Hafnium enables the compiler option permitting to leverage MTE stack tagging
- applied to core stacks. Core stacks are marked as normal tagged memory in the
- EL2 Stage-1 translation regime. A synchronous data abort is generated upon tag
- check failure on load/stores. A random seed is generated at boot time and
- restored upon entry into Hafnium. MTE system registers are saved/restored in
- vCPU contexts permitting MTE usage from VMs/SPs.
-
-SMMUv3 support in Hafnium
-=========================
-
-An SMMU is analogous to an MMU in a CPU. It performs address translations for
-Direct Memory Access (DMA) requests from system I/O devices.
-The responsibilities of an SMMU include:
-
-- Translation: Incoming DMA requests are translated from bus address space to
- system physical address space using translation tables compliant to
- Armv8/Armv7 VMSA descriptor format.
-- Protection: An I/O device can be prohibited from read, write access to a
- memory region or allowed.
-- Isolation: Traffic from each individial device can be independently managed.
- The devices are differentiated from each other using unique translation
- tables.
-
-The following diagram illustrates a typical SMMU IP integrated in a SoC with
-several I/O devices along with Interconnect and Memory system.
-
-.. image:: ../resources/diagrams/MMU-600.png
-
-SMMU has several versions including SMMUv1, SMMUv2 and SMMUv3. Hafnium provides
-support for SMMUv3 driver in both normal and secure world. A brief introduction
-of SMMUv3 functionality and the corresponding software support in Hafnium is
-provided here.
-
-SMMUv3 features
----------------
-
-- SMMUv3 provides Stage1, Stage2 translation as well as nested (Stage1 + Stage2)
- translation support. It can either bypass or abort incoming translations as
- well.
-- Traffic (memory transactions) from each upstream I/O peripheral device,
- referred to as Stream, can be independently managed using a combination of
- several memory based configuration structures. This allows the SMMUv3 to
- support a large number of streams with each stream assigned to a unique
- translation context.
-- Support for Armv8.1 VMSA where the SMMU shares the translation tables with
- a Processing Element. AArch32(LPAE) and AArch64 translation table format
- are supported by SMMUv3.
-- SMMUv3 offers non-secure stream support with secure stream support being
- optional. Logically, SMMUv3 behaves as if there is an indepdendent SMMU
- instance for secure and non-secure stream support.
-- It also supports sub-streams to differentiate traffic from a virtualized
- peripheral associated with a VM/SP.
-- Additionally, SMMUv3.2 provides support for PEs implementing Armv8.4-A
- extensions. Consequently, SPM depends on Secure EL2 support in SMMUv3.2
- for providing Secure Stage2 translation support to upstream peripheral
- devices.
-
-SMMUv3 Programming Interfaces
------------------------------
-
-SMMUv3 has three software interfaces that are used by the Hafnium driver to
-configure the behaviour of SMMUv3 and manage the streams.
-
-- Memory based data strutures that provide unique translation context for
- each stream.
-- Memory based circular buffers for command queue and event queue.
-- A large number of SMMU configuration registers that are memory mapped during
- boot time by Hafnium driver. Except a few registers, all configuration
- registers have independent secure and non-secure versions to configure the
- behaviour of SMMUv3 for translation of secure and non-secure streams
- respectively.
-
-Peripheral device manifest
---------------------------
-
-Currently, SMMUv3 driver in Hafnium only supports dependent peripheral devices.
-These devices are dependent on PE endpoint to initiate and receive memory
-management transactions on their behalf. The acccess to the MMIO regions of
-any such device is assigned to the endpoint during boot. Moreover, SMMUv3 driver
-uses the same stage 2 translations for the device as those used by partition
-manager on behalf of the PE endpoint. This ensures that the peripheral device
-has the same visibility of the physical address space as the endpoint. The
-device node of the corresponding partition manifest (refer to `[1]`_ section 3.2
-) must specify these additional properties for each peripheral device in the
-system :
-
-- smmu-id: This field helps to identify the SMMU instance that this device is
- upstream of.
-- stream-ids: List of stream IDs assigned to this device.
-
-.. code:: shell
-
- smmuv3-testengine {
- base-address = <0x00000000 0x2bfe0000>;
- pages-count = <32>;
- attributes = <0x3>;
- smmu-id = <0>;
- stream-ids = <0x0 0x1>;
- interrupts = <0x2 0x3>, <0x4 0x5>;
- exclusive-access;
- };
-
-SMMUv3 driver limitations
--------------------------
-
-The primary design goal for the Hafnium SMMU driver is to support secure
-streams.
-
-- Currently, the driver only supports Stage2 translations. No support for
- Stage1 or nested translations.
-- Supports only AArch64 translation format.
-- No support for features such as PCI Express (PASIDs, ATS, PRI), MSI, RAS,
- Fault handling, Performance Monitor Extensions, Event Handling, MPAM.
-- No support for independent peripheral devices.
-
-S-EL0 Partition support
-=======================
-The SPMC (Hafnium) has limited capability to run S-EL0 FF-A partitions using
-FEAT_VHE (mandatory with ARMv8.1 in non-secure state, and in secure world
-with ARMv8.4 and FEAT_SEL2).
-
-S-EL0 partitions are useful for simple partitions that don't require full
-Trusted OS functionality. It is also useful to reduce jitter and cycle
-stealing from normal world since they are more lightweight than VMs.
-
-S-EL0 partitions are presented, loaded and initialized the same as S-EL1 VMs by
-the SPMC. They are differentiated primarily by the 'exception-level' property
-and the 'execution-ctx-count' property in the SP manifest. They are host apps
-under the single EL2&0 Stage-1 translation regime controlled by the SPMC and
-call into the SPMC through SVCs as opposed to HVCs and SMCs. These partitions
-can use FF-A defined services (FFA_MEM_PERM_*) to update or change permissions
-for memory regions.
-
-S-EL0 partitions are required by the FF-A specification to be UP endpoints,
-capable of migrating, and the SPMC enforces this requirement. The SPMC allows
-a S-EL0 partition to accept a direct message from secure world and normal world,
-and generate direct responses to them.
-All S-EL0 partitions must use AArch64. AArch32 S-EL0 partitions are not supported.
-
-Memory sharing, indirect messaging, and notifications functionality with S-EL0
-partitions is supported.
-
-Interrupt handling is not supported with S-EL0 partitions and is work in
-progress.
References
==========
@@ -1641,8 +242,7 @@
.. _[3]:
-[3] `Trusted Boot Board Requirements
-Client <https://developer.arm.com/documentation/den0006/d/>`__
+[3] https://hafnium.readthedocs.io/en/latest/secure-partition-manager/secure-partition-manager.html#secure-partitions-layout-file
.. _[4]:
@@ -1650,23 +250,15 @@
.. _[5]:
-[5] https://git.trustedfirmware.org/TF-A/tf-a-tests.git/tree/spm/cactus/plat/arm/fvp/fdts/cactus.dts
+[5] https://hafnium.readthedocs.io/en/latest/secure-partition-manager/index.html
.. _[6]:
-[6] https://trustedfirmware-a.readthedocs.io/en/latest/components/ffa-manifest-binding.html
+[6] :ref:`EL3 Secure Partition Manager<EL3 Secure Partition Manager>`
.. _[7]:
-[7] https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
-
-.. _[8]:
-
-[8] https://lists.trustedfirmware.org/archives/list/tf-a@lists.trustedfirmware.org/thread/CFQFGU6H2D5GZYMUYGTGUSXIU3OYZP6U/
-
-.. _[9]:
-
-[9] https://trustedfirmware-a.readthedocs.io/en/latest/design/firmware-design.html#dynamic-configuration-during-cold-boot
+[7] https://trustedfirmware-a.readthedocs.io/en/latest/design/firmware-design.html#dynamic-configuration-during-cold-boot
--------------
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index 6147c1f..e6ca542 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -826,6 +826,10 @@
feature is enabled and can assist the Kernel in the process of
mitigation of the erratum.
+- ``ERRATA_X4_2726228``: This applies erratum 2726228 workaround to Cortex-X4
+ CPU. This needs to be enabled for revisions r0p0 and r0p1. It is fixed in
+ r0p2.
+
- ``ERRATA_X4_2740089``: This applies errata 2740089 workaround to Cortex-X4
CPU. This needs to be enabled for revisions r0p0 and r0p1. It is fixed
in r0p2.
@@ -833,6 +837,9 @@
- ``ERRATA_X4_2763018``: This applies errata 2763018 workaround to Cortex-X4
CPU. This needs to be enabled for revisions r0p0 and r0p1. It is fixed in r0p2.
+- ``ERRATA_X4_2816013``: This applies errata 2816013 workaround to Cortex-X4
+ CPU. This needs to be enabled for revisions r0p0 and r0p1. It is fixed in r0p2.
+
For Cortex-A510, the following errata build flags are defined :
- ``ERRATA_A510_1922240``: This applies errata 1922240 workaround to
@@ -896,6 +903,10 @@
Cortex-A520 CPU. This needs to be enabled for revisions r0p0 and r0p1.
It is still open.
+- ``ERRATA_A520_2938996``: This applies errata 2938996 workaround to
+ Cortex-A520 CPU. This needs to be enabled for revisions r0p0 and r0p1.
+ It is fixed in r0p2.
+
For Cortex-A715, the following errata build flags are defined :
- ``ERRATA_A715_2331818``: This applies errata 2331818 workaround to
@@ -929,6 +940,14 @@
For Cortex-A720, the following errata build flags are defined :
+- ``ERRATA_A720_2792132``: This applies errata 2792132 workaround to
+ Cortex-A720 CPU. This needs to be enabled for revisions r0p0 and r0p1.
+ It is fixed in r0p2.
+
+- ``ERRATA_A720_2844092``: This applies errata 2844092 workaround to
+ Cortex-A720 CPU. This needs to be enabled for revisions r0p0 and r0p1.
+ It is fixed in r0p2.
+
- ``ERRATA_A720_2926083``: This applies errata 2926083 workaround to
Cortex-A720 CPU. This needs to be enabled for revisions r0p0 and r0p1.
It is fixed in r0p2.
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 4c070ed..203bf0f 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -99,6 +99,10 @@
file that contains the BL32 private key in PEM format or a PKCS11 URI. If
``SAVE_KEYS=1``, only a file is accepted and it will be used to save the key.
+- ``RMM``: This is an optional build option used when ``ENABLE_RME`` is set.
+ It specifies the path to RMM binary for the ``fip`` target. If the RMM option
+ is not specified, TF-A builds the TRP to load and run at R-EL2.
+
- ``BL33``: Path to BL33 image in the host file system. This is mandatory for
``fip`` target in case TF-A BL2 is used.
@@ -200,6 +204,13 @@
Note that Pointer Authentication is enabled for Non-secure world irrespective
of the value of this flag if the CPU supports it.
+- ``CTX_INCLUDE_SVE_REGS``: Boolean option that, when set to 1, will cause the
+ SVE registers to be included when saving and restoring the CPU context. Note
+ that this build option requires ``ENABLE_SVE_FOR_SWD`` to be enabled. In
+ general, it is recommended to perform SVE context management in lower ELs
+ and skip in EL3 due to the additional cost of maintaining large data
+ structures to track the SVE state. Hence, the default value is 0.
+
- ``DEBUG``: Chooses between a debug and release build. It can take either 0
(release) or 1 (debug) as values. 0 is the default.
@@ -501,21 +512,26 @@
- ``ENABLE_SVE_FOR_NS``: Numeric value to enable Scalable Vector Extension
(SVE) for the Non-secure world only. SVE is an optional architectural feature
- for AArch64. Note that when SVE is enabled for the Non-secure world, access
- to SIMD and floating-point functionality from the Secure world is disabled by
- default and controlled with ENABLE_SVE_FOR_SWD.
- This is to avoid corruption of the Non-secure world data in the Z-registers
- which are aliased by the SIMD and FP registers. The build option is not
- compatible with the ``CTX_INCLUDE_FPREGS`` build option, and will raise an
- assert on platforms where SVE is implemented and ``ENABLE_SVE_FOR_NS``
- enabled. This flag can take the values 0 to 2, to align with the
- ``ENABLE_FEAT`` mechanism. At this time, this build option cannot be
- used on systems that have SPM_MM enabled. The default is 1.
+ for AArch64. This flag can take the values 0 to 2, to align with the
+ ``ENABLE_FEAT`` mechanism. At this time, this build option cannot be used on
+ systems that have SPM_MM enabled. The default value is 2.
-- ``ENABLE_SVE_FOR_SWD``: Boolean option to enable SVE for the Secure world.
- SVE is an optional architectural feature for AArch64. Note that this option
- requires ENABLE_SVE_FOR_NS to be enabled. The default is 0 and it is
- automatically disabled when the target architecture is AArch32.
+ Note that when SVE is enabled for the Non-secure world, access
+ to SVE, SIMD and floating-point functionality from the Secure world is
+ independently controlled by build option ``ENABLE_SVE_FOR_SWD``. When enabling
+ ``CTX_INCLUDE_FPREGS`` and ``ENABLE_SVE_FOR_NS`` together, it is mandatory to
+ enable ``CTX_INCLUDE_SVE_REGS``. This is to avoid corruption of the Non-secure
+ world data in the Z-registers which are aliased by the SIMD and FP registers.
+
+- ``ENABLE_SVE_FOR_SWD``: Boolean option to enable SVE and FPU/SIMD functionality
+ for the Secure world. SVE is an optional architectural feature for AArch64.
+ The default is 0 and it is automatically disabled when the target architecture
+ is AArch32.
+
+ .. note::
+ This build flag requires ``ENABLE_SVE_FOR_NS`` to be enabled. When enabling
+ ``ENABLE_SVE_FOR_SWD``, a developer must carefully consider whether
+ ``CTX_INCLUDE_SVE_REGS`` is also needed.
- ``ENABLE_STACK_PROTECTOR``: String option to enable the stack protection
checks in GCC. Allowed values are "all", "strong", "default" and "none". The
@@ -832,7 +848,7 @@
- ``RME_GPT_MAX_BLOCK``: Numeric value in MB to define the maximum size of
supported contiguous blocks in GPT Library. This parameter can take the
values 0, 2, 32 and 512. Setting this value to 0 disables use of Contigious
- descriptors. Default value is 2.
+ descriptors. Default value is 512.
- ``ROT_KEY``: This option is used when ``GENERATE_COT=1``. It specifies a
file that contains the ROT private key in PEM format or a PKCS11 URI and
@@ -881,6 +897,11 @@
flag is disabled by default and NOLOAD sections are placed in RAM immediately
following the loaded firmware image.
+- ``SEPARATE_SIMD_SECTION``: Setting this option to ``1`` allows the SIMD context
+ data structures to be put in a dedicated memory region as decided by platform
+ integrator. Default value is ``0`` which means the SIMD context is put in BSS
+ section of EL3 firmware.
+
- ``SMC_PCI_SUPPORT``: This option allows platforms to handle PCI configuration
access requests via a standard SMCCC defined in `DEN0115`_. When combined with
UEFI+ACPI this can provide a certain amount of OS forward compatibility
diff --git a/docs/license.rst b/docs/license.rst
index 8996105..9e0298b 100644
--- a/docs/license.rst
+++ b/docs/license.rst
@@ -93,9 +93,27 @@
- ``include/lib/dice/dice.h``
+- Some source files originating from the `pydevicetree`_ project.
+ These files are licensed under the Apache License, Version 2.0, which is a
+ permissive license compatible with BSD-3-Clause. Any contributions to this
+ code must also be made under the terms of `Apache License 2.0`_.
+ These files are:
+
+ - ``tools/cot_dt2c/cot_dt2c/pydevicetree/ast/__init__.py``
+ - ``tools/cot_dt2c/cot_dt2c/pydevicetree/ast/directive.py``
+ - ``tools/cot_dt2c/cot_dt2c/pydevicetree/ast/helpers.py``
+ - ``tools/cot_dt2c/cot_dt2c/pydevicetree/ast/node.py``
+ - ``tools/cot_dt2c/cot_dt2c/pydevicetree/ast/property.py``
+ - ``tools/cot_dt2c/cot_dt2c/pydevicetree/ast/reference.py``
+ - ``tools/cot_dt2c/cot_dt2c/pydevicetree/source/__init__.py``
+ - ``tools/cot_dt2c/cot_dt2c/pydevicetree/source/grammar.py``
+ - ``tools/cot_dt2c/cot_dt2c/pydevicetree/source/parser.py``
+ - ``tools/cot_dt2c/cot_dt2c/pydevicetree/__init__.py``
+
+
.. _FreeBSD: http://www.freebsd.org
.. _Linux MIT license: https://raw.githubusercontent.com/torvalds/linux/master/LICENSES/preferred/MIT
.. _SCC: http://www.simple-cc.org/
.. _Open Profile for DICE: https://pigweed.googlesource.com/open-dice/
.. _Apache License 2.0: https://www.apache.org/licenses/LICENSE-2.0.txt
-
+.. _pydevicetree: https://pypi.org/project/pydevicetree/
diff --git a/docs/plat/rockchip.rst b/docs/plat/rockchip.rst
index 53f63b5..384cd73 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
+- rk3588: Octa-Core Cortex-A55/A76
Boot Sequence
diff --git a/docs/plat/xilinx-versal-net.rst b/docs/plat/xilinx-versal-net.rst
index e9dd772..d22a46d 100644
--- a/docs/plat/xilinx-versal-net.rst
+++ b/docs/plat/xilinx-versal-net.rst
@@ -75,7 +75,7 @@
| 0xc2001000-0xc2001FFF | Fast SMC64 SiP Service call range used for AMD-Xilinx IPI |
+---------------------------+-----------------------------------------------------------+
-PM SMC call ranges
+PM SMC call ranges for SiP SVC version 0.1
--------------------------------------------------------
+---------------------------+---------------------------------------------------------------------------+
@@ -84,6 +84,19 @@
| 0xc2000000-0xc2000FFF | Fast SMC64 SiP Service call range used for AMD-Xilinx Platform Management |
+---------------------------+---------------------------------------------------------------------------+
+PM SMC call ranges for SiP SVC version 0.2
+--------------------------------------------------------
+
++---------------------------+---------------------------------------------------------------------------+
+| SMC Function Identifier | Service type |
++---------------------------+---------------------------------------------------------------------------+
+| 0xc2000FFF | Fast SMC64 SiP Service call used for pass-through of AMD-Xilinx Platform |
+| | Management APIs to firmware |
++---------------------------+---------------------------------------------------------------------------+
+| 0xc2000A00-0xc2000AFF | Fast SMC64 SiP Service call range used for AMD-Xilinx Platform Management |
+| | specific TF-A APIs |
++---------------------------+---------------------------------------------------------------------------+
+
SMC function IDs for SiP Service queries
----------------------------------------------
diff --git a/docs/plat/xilinx-versal.rst b/docs/plat/xilinx-versal.rst
index 072329a..7185d91 100644
--- a/docs/plat/xilinx-versal.rst
+++ b/docs/plat/xilinx-versal.rst
@@ -14,11 +14,6 @@
make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal bl31
```
-To build ATF for different platform (supported are "silicon"(default) and "versal_virt")
-```bash
-make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal VERSAL_PLATFORM=versal_virt bl31
-```
-
To build bl32 TSP you have to rebuild bl31 too
```bash
make CROSS_COMPILE=aarch64-none-elf- PLAT=versal SPD=tspd RESET_TO_BL31=1 bl31 bl32
@@ -51,11 +46,6 @@
- `pl011`, `pl011_0`: ARM pl011 UART 0
- `pl011_1` : ARM pl011 UART 1
-* `VERSAL_PLATFORM`: Select the platform. Options:
- - `versal_virt` : Versal Virtual platform
- - `spp_itr6` : SPP ITR6
- - `emu_itr6` : EMU ITR6
-
* `CPU_PWRDWN_SGI`: Select the SGI for triggering CPU power down request to
secondary cores on receiving power down callback from
firmware. Options:
@@ -98,8 +88,8 @@
| 0xc2001000-0xc2001FFF | Fast SMC64 SiP Service call range used for AMD-Xilinx IPI |
+---------------------------+-----------------------------------------------------------+
-PM SMC call ranges
-------------------
+PM SMC call ranges for SiP SVC version 0.1
+--------------------------------------------------------
+---------------------------+---------------------------------------------------------------------------+
| SMC Function Identifier | Service type |
@@ -107,6 +97,19 @@
| 0xc2000000-0xc2000FFF | Fast SMC64 SiP Service call range used for AMD-Xilinx Platform Management |
+---------------------------+---------------------------------------------------------------------------+
+PM SMC call ranges for SiP SVC version 0.2
+--------------------------------------------------------
+
++---------------------------+---------------------------------------------------------------------------+
+| SMC Function Identifier | Service type |
++---------------------------+---------------------------------------------------------------------------+
+| 0xc2000FFF | Fast SMC64 SiP Service call used for pass-through of AMD-Xilinx Platform |
+| | Management APIs to firmware |
++---------------------------+---------------------------------------------------------------------------+
+| 0xc2000A00-0xc2000AFF | Fast SMC64 SiP Service call range used for AMD-Xilinx Platform Management |
+| | specific TF-A APIs |
++---------------------------+---------------------------------------------------------------------------+
+
SMC function IDs for SiP Service queries
----------------------------------------
diff --git a/docs/tools/cot-dt2c.rst b/docs/tools/cot-dt2c.rst
new file mode 100644
index 0000000..e8bb1ac
--- /dev/null
+++ b/docs/tools/cot-dt2c.rst
@@ -0,0 +1,119 @@
+TF-A CoT dt2c Tool
+==================
+
+This tool is used to automatically generate the corresponding c file for a
+CoT DT file. Since currently TF-A support two type of CoT file: static c file
+and CoT DT binding. This is error prone and hard to maintain, therefore this
+tool can generate the c file for the platform that does not support CoT DT
+binding, given the CoT DT file so the c file can be deprecated.
+
+Prerequisites
+~~~~~~~~~~~~~
+
+#. Python (3.8 or later)
+#. `Poetry`_ Python package manager
+
+Getting Started
+~~~~~~~~~~~~~~~
+
+``cot-dt2c`` is installed by default with TF-A's poetry environment. All of it's
+dependencies are listed in `tools/cot_dt2c/pyproject.toml`_.
+
+``cot-dt2c`` requires a standard DTS file without #ifdef, macros, or other
+preprocessor directives. Therefore, you need to provide a preprocessed device
+tree source(DTS) as input to the tool.
+
+#. Usage of the tool
+
+ .. code::
+
+ cot-dt2c
+
+ This command will output the following as usage for this command
+
+ .. code-block:: text
+
+ Usage: cot-dt2c [OPTIONS] COMMAND [ARGS]...
+
+ Options:
+ --version Show the version and exit.
+ --help Show this message and exit.
+
+ Commands:
+ convert-to-c
+ validate-cot
+ visualize-cot
+ validate-dt
+
+Convert CoT descriptors to C file
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To convert the CoT descriptors
+
+This command is for the platform that does not use CoT DT parser,
+which can generate the C file given the CoT descriptors. Before
+the conversion to C file, the tool will do an implicit checks on
+the validity of the CoT DT file.
+
+.. code::
+
+ cot-dt2c convert-to-c [INPUT DTS PATH] [OUTPUT C PATH]
+ cot-dt2c convert-to-c fdts/tbbr_cot_descriptors.dtsi test.c
+
+
+Validate CoT descriptors
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To validate the certificate
+
+The tests folder in the tool folder provides some bad-example of the
+DT file, and the tool will print out "not a valid CoT DT file" on console.
+
+The command will check the format of the CoT file
+
+#. The open bracket
+#. The open ifdef macro
+#. The missing mandatory attribute
+#. Malformed DT file (cert missing parent, missing root certs. etc.)
+
+Currently the validation is specifically for checking the CoT DT file
+
+.. code::
+
+ cot-dt2c validate-cot [INPUT DTS PATH]
+ cot-dt2c validate-cot fdts/tbbr_cot_descriptors.dtsi
+
+
+Visualize CoT descriptors
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This command create a HTML to visualize the relationship between
+the certificates and the image of a CoT DT file.
+
+.. code::
+
+ cot-dt2c visualize-cot [INPUT DTS PATH]
+ cot-dt2c visualize-cot fdts/tbbr_cot_descriptors.dtsi
+
+
+Validate Other DT files
+~~~~~~~~~~~~~~~~~~~~~~~
+
+The command will transform the dtsi/dts file into a more standard
+dtsi/dts file inside /tmp folder that can be used as input to dt-schema
+for further validation. Currently the tool will perform some basic validation
+for the file (syntax) and dt-schema can be used for advance checks. dt-schema
+is not installed along with the tool.
+
+.. code::
+
+ cot-dt2c validate-dt [INPUT DTS PATH or INPUT DTS folder]
+ cot-dt2c validate-dt fdts/
+ cot-dt2c validate-dt fdts/fvp-bsae-gicv3.dtsi
+
+--------------
+
+*Copyright (c) 2024, Arm Limited. All rights reserved.*
+
+.. _tools/cot_dt2c/pyproject.toml: https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/heads/integration/tools/cot_dt2c/pyproject.toml
+.. _Poetry: https://python-poetry.org/docs/
diff --git a/docs/tools/index.rst b/docs/tools/index.rst
index 91651bf..c0e214a 100644
--- a/docs/tools/index.rst
+++ b/docs/tools/index.rst
@@ -7,6 +7,7 @@
memory-layout-tool
transfer-list-compiler
+ cot-dt2c
--------------
diff --git a/drivers/arm/gic/v3/gicv3_main.c b/drivers/arm/gic/v3/gicv3_main.c
index 8ea164c..2be19db 100644
--- a/drivers/arm/gic/v3/gicv3_main.c
+++ b/drivers/arm/gic/v3/gicv3_main.c
@@ -686,6 +686,8 @@
gicr_write_ctlr(gicr_base,
rdist_ctx->gicr_ctlr & ~(GICR_CTLR_EN_LPIS_BIT));
+ gicr_wait_for_pending_write(gicr_base);
+
/* Restore registers' content */
gicr_write_propbaser(gicr_base, rdist_ctx->gicr_propbaser);
gicr_write_pendbaser(gicr_base, rdist_ctx->gicr_pendbaser);
diff --git a/drivers/auth/cca/bl1_cot.c b/drivers/auth/cca/bl1_cot.c
new file mode 100644
index 0000000..43cb18a
--- /dev/null
+++ b/drivers/auth/cca/bl1_cot.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <mbedtls/version.h>
+
+#include <common/tbbr/cot_def.h>
+#include <drivers/auth/auth_mod.h>
+#include <platform_def.h>
+#include <tools_share/cca_oid.h>
+
+/*
+ * Allocate static buffers to store the authentication parameters extracted from
+ * the certificates.
+ */
+static unsigned char fw_config_hash_buf[HASH_DER_LEN];
+static unsigned char tb_fw_hash_buf[HASH_DER_LEN];
+static unsigned char tb_fw_config_hash_buf[HASH_DER_LEN];
+
+/*
+ * Parameter type descriptors.
+ */
+static auth_param_type_desc_t cca_nv_ctr = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_NV_CTR, CCA_FW_NVCOUNTER_OID);
+static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, 0);
+static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_SIG, 0);
+static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_SIG_ALG, 0);
+static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_RAW_DATA, 0);
+
+static auth_param_type_desc_t tb_fw_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID);
+static auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID);
+static auth_param_type_desc_t fw_config_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, FW_CONFIG_HASH_OID);
+
+/* CCA Content Certificate */
+static const auth_img_desc_t cca_content_cert = {
+ .img_id = CCA_CONTENT_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &subject_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &cca_nv_ctr,
+ .plat_nv_ctr = &cca_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &tb_fw_hash,
+ .data = {
+ .ptr = (void *)tb_fw_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [1] = {
+ .type_desc = &tb_fw_config_hash,
+ .data = {
+ .ptr = (void *)tb_fw_config_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [2] = {
+ .type_desc = &fw_config_hash,
+ .data = {
+ .ptr = (void *)fw_config_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t bl2_image = {
+ .img_id = BL2_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &cca_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &tb_fw_hash
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t tb_fw_config = {
+ .img_id = TB_FW_CONFIG_ID,
+ .img_type = IMG_RAW,
+ .parent = &cca_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &tb_fw_config_hash
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t fw_config = {
+ .img_id = FW_CONFIG_ID,
+ .img_type = IMG_RAW,
+ .parent = &cca_content_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &fw_config_hash
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t * const cot_desc[] = {
+ [CCA_CONTENT_CERT_ID] = &cca_content_cert,
+ [BL2_IMAGE_ID] = &bl2_image,
+ [TB_FW_CONFIG_ID] = &tb_fw_config,
+ [FW_CONFIG_ID] = &fw_config,
+};
+
+REGISTER_COT(cot_desc);
diff --git a/drivers/auth/cca/cot.c b/drivers/auth/cca/cot.c
deleted file mode 100644
index 2a03604..0000000
--- a/drivers/auth/cca/cot.c
+++ /dev/null
@@ -1,679 +0,0 @@
-/*
- * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <stddef.h>
-
-#include <mbedtls/version.h>
-
-#include <common/tbbr/cot_def.h>
-#include <drivers/auth/auth_mod.h>
-#include <tools_share/cca_oid.h>
-
-#include <platform_def.h>
-
-/*
- * Allocate static buffers to store the authentication parameters extracted from
- * the certificates.
- */
-static unsigned char fw_config_hash_buf[HASH_DER_LEN];
-static unsigned char tb_fw_hash_buf[HASH_DER_LEN];
-static unsigned char tb_fw_config_hash_buf[HASH_DER_LEN];
-static unsigned char hw_config_hash_buf[HASH_DER_LEN];
-static unsigned char soc_fw_hash_buf[HASH_DER_LEN];
-static unsigned char soc_fw_config_hash_buf[HASH_DER_LEN];
-static unsigned char rmm_hash_buf[HASH_DER_LEN];
-
-#ifdef IMAGE_BL2
-static unsigned char nt_world_bl_hash_buf[HASH_DER_LEN];
-static unsigned char tos_fw_hash_buf[HASH_DER_LEN];
-static unsigned char tos_fw_config_hash_buf[HASH_DER_LEN];
-static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN];
-#if defined(SPD_spmd)
-static unsigned char sp_pkg_hash_buf[MAX_SP_IDS][HASH_DER_LEN];
-#endif /* SPD_spmd */
-
-static unsigned char core_swd_pk_buf[PK_DER_LEN];
-static unsigned char plat_pk_buf[PK_DER_LEN];
-#endif /* IMAGE_BL2 */
-
-/*
- * Parameter type descriptors.
- */
-static auth_param_type_desc_t cca_nv_ctr = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_NV_CTR, CCA_FW_NVCOUNTER_OID);
-static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, 0);
-static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_SIG, 0);
-static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_SIG_ALG, 0);
-static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_RAW_DATA, 0);
-
-static auth_param_type_desc_t tb_fw_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID);
-static auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID);
-static auth_param_type_desc_t hw_config_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, HW_CONFIG_HASH_OID);
-static auth_param_type_desc_t fw_config_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, FW_CONFIG_HASH_OID);
-static auth_param_type_desc_t soc_fw_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SOC_AP_FW_HASH_OID);
-static auth_param_type_desc_t soc_fw_config_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SOC_FW_CONFIG_HASH_OID);
-static auth_param_type_desc_t rmm_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, RMM_HASH_OID);
-
-#ifdef IMAGE_BL2
-static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID);
-static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID);
-
-static auth_param_type_desc_t prot_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, PROT_PK_OID);
-static auth_param_type_desc_t swd_rot_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, SWD_ROT_PK_OID);
-static auth_param_type_desc_t core_swd_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, CORE_SWD_PK_OID);
-static auth_param_type_desc_t plat_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, PLAT_PK_OID);
-
-static auth_param_type_desc_t tos_fw_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, TRUSTED_OS_FW_HASH_OID);
-static auth_param_type_desc_t tos_fw_config_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, TRUSTED_OS_FW_CONFIG_HASH_OID);
-static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID);
-static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID);
-#if defined(SPD_spmd)
-static auth_param_type_desc_t sp_pkg1_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG1_HASH_OID);
-static auth_param_type_desc_t sp_pkg2_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG2_HASH_OID);
-static auth_param_type_desc_t sp_pkg3_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG3_HASH_OID);
-static auth_param_type_desc_t sp_pkg4_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG4_HASH_OID);
-static auth_param_type_desc_t sp_pkg5_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG5_HASH_OID);
-static auth_param_type_desc_t sp_pkg6_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG6_HASH_OID);
-static auth_param_type_desc_t sp_pkg7_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG7_HASH_OID);
-static auth_param_type_desc_t sp_pkg8_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG8_HASH_OID);
-#endif /* SPD_spmd */
-#endif /* IMAGE_BL2 */
-
-/* CCA Content Certificate */
-static const auth_img_desc_t cca_content_cert = {
- .img_id = CCA_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = NULL,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &subject_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &cca_nv_ctr,
- .plat_nv_ctr = &cca_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &tb_fw_hash,
- .data = {
- .ptr = (void *)tb_fw_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &tb_fw_config_hash,
- .data = {
- .ptr = (void *)tb_fw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [2] = {
- .type_desc = &fw_config_hash,
- .data = {
- .ptr = (void *)fw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [3] = {
- .type_desc = &hw_config_hash,
- .data = {
- .ptr = (void *)hw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [4] = {
- .type_desc = &soc_fw_hash,
- .data = {
- .ptr = (void *)soc_fw_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [5] = {
- .type_desc = &soc_fw_config_hash,
- .data = {
- .ptr = (void *)soc_fw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [6] = {
- .type_desc = &rmm_hash,
- .data = {
- .ptr = (void *)rmm_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-#ifdef IMAGE_BL1
-static const auth_img_desc_t bl2_image = {
- .img_id = BL2_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &cca_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &tb_fw_hash
- }
- }
- }
-};
-
-static const auth_img_desc_t tb_fw_config = {
- .img_id = TB_FW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &cca_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &tb_fw_config_hash
- }
- }
- }
-};
-
-static const auth_img_desc_t fw_config = {
- .img_id = FW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &cca_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &fw_config_hash
- }
- }
- }
-};
-#endif /* IMAGE_BL1 */
-
-#ifdef IMAGE_BL2
-/* HW Config */
-static const auth_img_desc_t hw_config = {
- .img_id = HW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &cca_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &hw_config_hash
- }
- }
- }
-};
-
-/* BL31 */
-static const auth_img_desc_t bl31_image = {
- .img_id = BL31_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &cca_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &soc_fw_hash
- }
- }
- }
-};
-
-/* BL31 Config */
-static const auth_img_desc_t soc_fw_config = {
- .img_id = SOC_FW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &cca_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &soc_fw_config_hash
- }
- }
- }
-};
-
-/* RMM */
-static const auth_img_desc_t rmm_image = {
- .img_id = RMM_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &cca_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &rmm_hash
- }
- }
- }
-};
-
-/* Core SWD Key Certificate */
-static const auth_img_desc_t core_swd_key_cert = {
- .img_id = CORE_SWD_KEY_CERT_ID,
- .img_type = IMG_CERT,
- .parent = NULL, /* SWD ROOT CERT */
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &swd_rot_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &core_swd_pk,
- .data = {
- .ptr = (void *)core_swd_pk_buf,
- .len = (unsigned int)PK_DER_LEN
- }
- }
- }
-};
-
-/* SPMC Content Certificate */
-static const auth_img_desc_t trusted_os_fw_content_cert = {
- .img_id = TRUSTED_OS_FW_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &core_swd_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &core_swd_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &tos_fw_hash,
- .data = {
- .ptr = (void *)tos_fw_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &tos_fw_config_hash,
- .data = {
- .ptr = (void *)tos_fw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-/* SPMC */
-static const auth_img_desc_t bl32_image = {
- .img_id = BL32_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &trusted_os_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &tos_fw_hash
- }
- }
- }
-};
-
-/* SPM Config */
-static const auth_img_desc_t tos_fw_config = {
- .img_id = TOS_FW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &trusted_os_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &tos_fw_config_hash
- }
- }
- }
-};
-
-/* Platform Key Certificate */
-static const auth_img_desc_t plat_key_cert = {
- .img_id = PLAT_KEY_CERT_ID,
- .img_type = IMG_CERT,
- .parent = NULL, /* PLATFORM ROOT CERT */
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &prot_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &non_trusted_nv_ctr,
- .plat_nv_ctr = &non_trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &plat_pk,
- .data = {
- .ptr = (void *)plat_pk_buf,
- .len = (unsigned int)PK_DER_LEN
- }
- }
- }
-};
-
-/* Non-Trusted Firmware */
-static const auth_img_desc_t non_trusted_fw_content_cert = {
- .img_id = NON_TRUSTED_FW_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &plat_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &plat_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &non_trusted_nv_ctr,
- .plat_nv_ctr = &non_trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &nt_world_bl_hash,
- .data = {
- .ptr = (void *)nt_world_bl_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &nt_fw_config_hash,
- .data = {
- .ptr = (void *)nt_fw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-static const auth_img_desc_t bl33_image = {
- .img_id = BL33_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &non_trusted_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &nt_world_bl_hash
- }
- }
- }
-};
-
-/* NT FW Config */
-static const auth_img_desc_t nt_fw_config = {
- .img_id = NT_FW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &non_trusted_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &nt_fw_config_hash
- }
- }
- }
-};
-
-/*
- * Secure Partitions
- */
-#if defined(SPD_spmd)
-static const auth_img_desc_t sip_sp_content_cert = {
- .img_id = SIP_SP_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &core_swd_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &core_swd_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &sp_pkg1_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[0],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &sp_pkg2_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[1],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [2] = {
- .type_desc = &sp_pkg3_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[2],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [3] = {
- .type_desc = &sp_pkg4_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[3],
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-DEFINE_SIP_SP_PKG(1);
-DEFINE_SIP_SP_PKG(2);
-DEFINE_SIP_SP_PKG(3);
-DEFINE_SIP_SP_PKG(4);
-
-static const auth_img_desc_t plat_sp_content_cert = {
- .img_id = PLAT_SP_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &plat_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &plat_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &non_trusted_nv_ctr,
- .plat_nv_ctr = &non_trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &sp_pkg5_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[4],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &sp_pkg6_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[5],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [2] = {
- .type_desc = &sp_pkg7_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[6],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [3] = {
- .type_desc = &sp_pkg8_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[7],
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-DEFINE_PLAT_SP_PKG(5);
-DEFINE_PLAT_SP_PKG(6);
-DEFINE_PLAT_SP_PKG(7);
-DEFINE_PLAT_SP_PKG(8);
-#endif /* SPD_spmd */
-#endif /* IMAGE_BL2 */
-/*
- * Chain of trust definition
- */
-#ifdef IMAGE_BL1
-static const auth_img_desc_t * const cot_desc[] = {
- [CCA_CONTENT_CERT_ID] = &cca_content_cert,
- [BL2_IMAGE_ID] = &bl2_image,
- [TB_FW_CONFIG_ID] = &tb_fw_config,
- [FW_CONFIG_ID] = &fw_config,
-};
-#else /* IMAGE_BL2 */
-static const auth_img_desc_t * const cot_desc[] = {
- [CCA_CONTENT_CERT_ID] = &cca_content_cert,
- [HW_CONFIG_ID] = &hw_config,
- [BL31_IMAGE_ID] = &bl31_image,
- [SOC_FW_CONFIG_ID] = &soc_fw_config,
- [RMM_IMAGE_ID] = &rmm_image,
- [CORE_SWD_KEY_CERT_ID] = &core_swd_key_cert,
- [TRUSTED_OS_FW_CONTENT_CERT_ID] = &trusted_os_fw_content_cert,
- [BL32_IMAGE_ID] = &bl32_image,
- [TOS_FW_CONFIG_ID] = &tos_fw_config,
- [PLAT_KEY_CERT_ID] = &plat_key_cert,
- [NON_TRUSTED_FW_CONTENT_CERT_ID] = &non_trusted_fw_content_cert,
- [BL33_IMAGE_ID] = &bl33_image,
- [NT_FW_CONFIG_ID] = &nt_fw_config,
-#if defined(SPD_spmd)
- [SIP_SP_CONTENT_CERT_ID] = &sip_sp_content_cert,
- [PLAT_SP_CONTENT_CERT_ID] = &plat_sp_content_cert,
- [SP_PKG1_ID] = &sp_pkg1,
- [SP_PKG2_ID] = &sp_pkg2,
- [SP_PKG3_ID] = &sp_pkg3,
- [SP_PKG4_ID] = &sp_pkg4,
- [SP_PKG5_ID] = &sp_pkg5,
- [SP_PKG6_ID] = &sp_pkg6,
- [SP_PKG7_ID] = &sp_pkg7,
- [SP_PKG8_ID] = &sp_pkg8,
-#endif
-};
-#endif /* IMAGE_BL1 */
-
-/* Register the CoT in the authentication module */
-REGISTER_COT(cot_desc);
diff --git a/drivers/auth/dualroot/bl1_cot.c b/drivers/auth/dualroot/bl1_cot.c
new file mode 100644
index 0000000..a548170
--- /dev/null
+++ b/drivers/auth/dualroot/bl1_cot.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+
+#include <mbedtls/version.h>
+
+#include <common/tbbr/cot_def.h>
+#include <drivers/auth/auth_mod.h>
+#include <platform_def.h>
+#include <tools_share/dualroot_oid.h>
+
+/*
+ * Allocate static buffers to store the authentication parameters extracted from
+ * the certificates.
+ */
+static unsigned char fw_config_hash_buf[HASH_DER_LEN];
+static unsigned char tb_fw_hash_buf[HASH_DER_LEN];
+static unsigned char tb_fw_config_hash_buf[HASH_DER_LEN];
+static unsigned char scp_fw_hash_buf[HASH_DER_LEN];
+static unsigned char nt_world_bl_hash_buf[HASH_DER_LEN];
+
+/*
+ * Parameter type descriptors.
+ */
+static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID);
+static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_PUB_KEY, 0);
+static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_SIG, 0);
+static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_SIG_ALG, 0);
+static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_RAW_DATA, 0);
+
+static auth_param_type_desc_t tb_fw_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID);
+static auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID);
+static auth_param_type_desc_t fw_config_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, FW_CONFIG_HASH_OID);
+static auth_param_type_desc_t scp_bl2u_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, SCP_FWU_CFG_HASH_OID);
+static auth_param_type_desc_t bl2u_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, AP_FWU_CFG_HASH_OID);
+static auth_param_type_desc_t ns_bl2u_hash = AUTH_PARAM_TYPE_DESC(
+ AUTH_PARAM_HASH, FWU_HASH_OID);
+
+static const auth_img_desc_t trusted_boot_fw_cert = {
+ .img_id = TRUSTED_BOOT_FW_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &subject_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ },
+ [1] = {
+ .type = AUTH_METHOD_NV_CTR,
+ .param.nv_ctr = {
+ .cert_nv_ctr = &trusted_nv_ctr,
+ .plat_nv_ctr = &trusted_nv_ctr
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &tb_fw_hash,
+ .data = {
+ .ptr = (void *)tb_fw_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [1] = {
+ .type_desc = &tb_fw_config_hash,
+ .data = {
+ .ptr = (void *)tb_fw_config_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [2] = {
+ .type_desc = &fw_config_hash,
+ .data = {
+ .ptr = (void *)fw_config_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t bl2_image = {
+ .img_id = BL2_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &trusted_boot_fw_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &tb_fw_hash
+ }
+ }
+ }
+};
+
+/* TB FW Config */
+static const auth_img_desc_t tb_fw_config = {
+ .img_id = TB_FW_CONFIG_ID,
+ .img_type = IMG_RAW,
+ .parent = &trusted_boot_fw_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &tb_fw_config_hash
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t fw_config = {
+ .img_id = FW_CONFIG_ID,
+ .img_type = IMG_RAW,
+ .parent = &trusted_boot_fw_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &fw_config_hash
+ }
+ }
+ }
+};
+
+/* FWU auth descriptor */
+static const auth_img_desc_t fwu_cert = {
+ .img_id = FWU_CERT_ID,
+ .img_type = IMG_CERT,
+ .parent = NULL,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_SIG,
+ .param.sig = {
+ .pk = &subject_pk,
+ .sig = &sig,
+ .alg = &sig_alg,
+ .data = &raw_data
+ }
+ }
+ },
+ .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
+ [0] = {
+ .type_desc = &scp_bl2u_hash,
+ .data = {
+ .ptr = (void *)scp_fw_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [1] = {
+ .type_desc = &bl2u_hash,
+ .data = {
+ .ptr = (void *)tb_fw_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ },
+ [2] = {
+ .type_desc = &ns_bl2u_hash,
+ .data = {
+ .ptr = (void *)nt_world_bl_hash_buf,
+ .len = (unsigned int)HASH_DER_LEN
+ }
+ }
+ }
+};
+
+/* SCP_BL2U */
+static const auth_img_desc_t scp_bl2u_image = {
+ .img_id = SCP_BL2U_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &fwu_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &scp_bl2u_hash
+ }
+ }
+ }
+};
+
+/* BL2U */
+static const auth_img_desc_t bl2u_image = {
+ .img_id = BL2U_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &fwu_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &bl2u_hash
+ }
+ }
+ }
+};
+
+/* NS_BL2U */
+static const auth_img_desc_t ns_bl2u_image = {
+ .img_id = NS_BL2U_IMAGE_ID,
+ .img_type = IMG_RAW,
+ .parent = &fwu_cert,
+ .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
+ [0] = {
+ .type = AUTH_METHOD_HASH,
+ .param.hash = {
+ .data = &raw_data,
+ .hash = &ns_bl2u_hash
+ }
+ }
+ }
+};
+
+static const auth_img_desc_t * const cot_desc[] = {
+ [TRUSTED_BOOT_FW_CERT_ID] = &trusted_boot_fw_cert,
+ [BL2_IMAGE_ID] = &bl2_image,
+ [TB_FW_CONFIG_ID] = &tb_fw_config,
+ [FW_CONFIG_ID] = &fw_config,
+ [FWU_CERT_ID] = &fwu_cert,
+ [SCP_BL2U_IMAGE_ID] = &scp_bl2u_image,
+ [BL2U_IMAGE_ID] = &bl2u_image,
+ [NS_BL2U_IMAGE_ID] = &ns_bl2u_image
+};
+
+REGISTER_COT(cot_desc);
diff --git a/drivers/auth/dualroot/cot.c b/drivers/auth/dualroot/cot.c
deleted file mode 100644
index c89930c..0000000
--- a/drivers/auth/dualroot/cot.c
+++ /dev/null
@@ -1,962 +0,0 @@
-/*
- * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <stddef.h>
-
-#include <mbedtls/version.h>
-
-#include <common/tbbr/cot_def.h>
-#include <drivers/auth/auth_mod.h>
-
-#include <tools_share/dualroot_oid.h>
-
-#include <platform_def.h>
-
-/*
- * Allocate static buffers to store the authentication parameters extracted from
- * the certificates.
- */
-static unsigned char fw_config_hash_buf[HASH_DER_LEN];
-static unsigned char tb_fw_hash_buf[HASH_DER_LEN];
-static unsigned char tb_fw_config_hash_buf[HASH_DER_LEN];
-static unsigned char hw_config_hash_buf[HASH_DER_LEN];
-static unsigned char scp_fw_hash_buf[HASH_DER_LEN];
-static unsigned char nt_world_bl_hash_buf[HASH_DER_LEN];
-
-#ifdef IMAGE_BL2
-static unsigned char soc_fw_hash_buf[HASH_DER_LEN];
-static unsigned char tos_fw_hash_buf[HASH_DER_LEN];
-static unsigned char tos_fw_extra1_hash_buf[HASH_DER_LEN];
-static unsigned char tos_fw_extra2_hash_buf[HASH_DER_LEN];
-static unsigned char soc_fw_config_hash_buf[HASH_DER_LEN];
-static unsigned char tos_fw_config_hash_buf[HASH_DER_LEN];
-static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN];
-#if defined(SPD_spmd)
-static unsigned char sp_pkg_hash_buf[MAX_SP_IDS][HASH_DER_LEN];
-#endif /* SPD_spmd */
-
-static unsigned char trusted_world_pk_buf[PK_DER_LEN];
-static unsigned char content_pk_buf[PK_DER_LEN];
-#endif
-
-/*
- * Parameter type descriptors.
- */
-static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID);
-static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, 0);
-static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_SIG, 0);
-static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_SIG_ALG, 0);
-static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_RAW_DATA, 0);
-
-static auth_param_type_desc_t tb_fw_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID);
-static auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID);
-static auth_param_type_desc_t hw_config_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, HW_CONFIG_HASH_OID);
-static auth_param_type_desc_t fw_config_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, FW_CONFIG_HASH_OID);
-#ifdef IMAGE_BL1
-static auth_param_type_desc_t scp_bl2u_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SCP_FWU_CFG_HASH_OID);
-static auth_param_type_desc_t bl2u_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, AP_FWU_CFG_HASH_OID);
-static auth_param_type_desc_t ns_bl2u_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, FWU_HASH_OID);
-#endif /* IMAGE_BL1 */
-
-#ifdef IMAGE_BL2
-static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID);
-
-static auth_param_type_desc_t trusted_world_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, TRUSTED_WORLD_PK_OID);
-static auth_param_type_desc_t scp_fw_content_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, SCP_FW_CONTENT_CERT_PK_OID);
-static auth_param_type_desc_t soc_fw_content_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, SOC_FW_CONTENT_CERT_PK_OID);
-static auth_param_type_desc_t tos_fw_content_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, TRUSTED_OS_FW_CONTENT_CERT_PK_OID);
-static auth_param_type_desc_t prot_pk = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_PUB_KEY, PROT_PK_OID);
-
-static auth_param_type_desc_t scp_fw_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SCP_FW_HASH_OID);
-static auth_param_type_desc_t soc_fw_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SOC_AP_FW_HASH_OID);
-static auth_param_type_desc_t soc_fw_config_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SOC_FW_CONFIG_HASH_OID);
-static auth_param_type_desc_t tos_fw_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, TRUSTED_OS_FW_HASH_OID);
-static auth_param_type_desc_t tos_fw_config_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, TRUSTED_OS_FW_CONFIG_HASH_OID);
-static auth_param_type_desc_t tos_fw_extra1_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA1_HASH_OID);
-static auth_param_type_desc_t tos_fw_extra2_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA2_HASH_OID);
-static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID);
-static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID);
-#if defined(SPD_spmd)
-static auth_param_type_desc_t sp_pkg1_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG1_HASH_OID);
-static auth_param_type_desc_t sp_pkg2_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG2_HASH_OID);
-static auth_param_type_desc_t sp_pkg3_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG3_HASH_OID);
-static auth_param_type_desc_t sp_pkg4_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG4_HASH_OID);
-static auth_param_type_desc_t sp_pkg5_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG5_HASH_OID);
-static auth_param_type_desc_t sp_pkg6_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG6_HASH_OID);
-static auth_param_type_desc_t sp_pkg7_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG7_HASH_OID);
-static auth_param_type_desc_t sp_pkg8_hash = AUTH_PARAM_TYPE_DESC(
- AUTH_PARAM_HASH, SP_PKG8_HASH_OID);
-#endif /* SPD_spmd */
-#endif /* IMAGE_BL2 */
-
-
-/* BL2 */
-static const auth_img_desc_t trusted_boot_fw_cert = {
- .img_id = TRUSTED_BOOT_FW_CERT_ID,
- .img_type = IMG_CERT,
- .parent = NULL,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &subject_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &tb_fw_hash,
- .data = {
- .ptr = (void *)tb_fw_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &tb_fw_config_hash,
- .data = {
- .ptr = (void *)tb_fw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [2] = {
- .type_desc = &hw_config_hash,
- .data = {
- .ptr = (void *)hw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [3] = {
- .type_desc = &fw_config_hash,
- .data = {
- .ptr = (void *)fw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-#ifdef IMAGE_BL1
-static const auth_img_desc_t bl2_image = {
- .img_id = BL2_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &trusted_boot_fw_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &tb_fw_hash
- }
- }
- }
-};
-#endif /* IMAGE_BL1 */
-
-/* HW Config */
-static const auth_img_desc_t hw_config = {
- .img_id = HW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &trusted_boot_fw_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &hw_config_hash
- }
- }
- }
-};
-
-/* TB FW Config */
-#ifdef IMAGE_BL1
-static const auth_img_desc_t tb_fw_config = {
- .img_id = TB_FW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &trusted_boot_fw_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &tb_fw_config_hash
- }
- }
- }
-};
-
-static const auth_img_desc_t fw_config = {
- .img_id = FW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &trusted_boot_fw_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &fw_config_hash
- }
- }
- }
-};
-
-#endif /* IMAGE_BL1 */
-
-#ifdef IMAGE_BL2
-/* Trusted key certificate */
-static const auth_img_desc_t trusted_key_cert = {
- .img_id = TRUSTED_KEY_CERT_ID,
- .img_type = IMG_CERT,
- .parent = NULL,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &subject_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &trusted_world_pk,
- .data = {
- .ptr = (void *)trusted_world_pk_buf,
- .len = (unsigned int)PK_DER_LEN
- }
- },
- }
-};
-
-/* SCP Firmware */
-static const auth_img_desc_t scp_fw_key_cert = {
- .img_id = SCP_FW_KEY_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &trusted_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &trusted_world_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &scp_fw_content_pk,
- .data = {
- .ptr = (void *)content_pk_buf,
- .len = (unsigned int)PK_DER_LEN
- }
- }
- }
-};
-
-static const auth_img_desc_t scp_fw_content_cert = {
- .img_id = SCP_FW_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &scp_fw_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &scp_fw_content_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &scp_fw_hash,
- .data = {
- .ptr = (void *)scp_fw_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-static const auth_img_desc_t scp_bl2_image = {
- .img_id = SCP_BL2_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &scp_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &scp_fw_hash
- }
- }
- }
-};
-
-/* SoC Firmware */
-static const auth_img_desc_t soc_fw_key_cert = {
- .img_id = SOC_FW_KEY_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &trusted_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &trusted_world_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &soc_fw_content_pk,
- .data = {
- .ptr = (void *)content_pk_buf,
- .len = (unsigned int)PK_DER_LEN
- }
- }
- }
-};
-
-static const auth_img_desc_t soc_fw_content_cert = {
- .img_id = SOC_FW_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &soc_fw_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &soc_fw_content_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &soc_fw_hash,
- .data = {
- .ptr = (void *)soc_fw_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &soc_fw_config_hash,
- .data = {
- .ptr = (void *)soc_fw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-static const auth_img_desc_t bl31_image = {
- .img_id = BL31_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &soc_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &soc_fw_hash
- }
- }
- }
-};
-
-/* SOC FW Config */
-static const auth_img_desc_t soc_fw_config = {
- .img_id = SOC_FW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &soc_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &soc_fw_config_hash
- }
- }
- }
-};
-
-/* Trusted OS Firmware */
-static const auth_img_desc_t trusted_os_fw_key_cert = {
- .img_id = TRUSTED_OS_FW_KEY_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &trusted_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &trusted_world_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &tos_fw_content_pk,
- .data = {
- .ptr = (void *)content_pk_buf,
- .len = (unsigned int)PK_DER_LEN
- }
- }
- }
-};
-
-static const auth_img_desc_t trusted_os_fw_content_cert = {
- .img_id = TRUSTED_OS_FW_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &trusted_os_fw_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &tos_fw_content_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &tos_fw_hash,
- .data = {
- .ptr = (void *)tos_fw_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &tos_fw_extra1_hash,
- .data = {
- .ptr = (void *)tos_fw_extra1_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [2] = {
- .type_desc = &tos_fw_extra2_hash,
- .data = {
- .ptr = (void *)tos_fw_extra2_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [3] = {
- .type_desc = &tos_fw_config_hash,
- .data = {
- .ptr = (void *)tos_fw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-static const auth_img_desc_t bl32_image = {
- .img_id = BL32_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &trusted_os_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &tos_fw_hash
- }
- }
- }
-};
-
-static const auth_img_desc_t bl32_extra1_image = {
- .img_id = BL32_EXTRA1_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &trusted_os_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &tos_fw_extra1_hash
- }
- }
- }
-};
-
-static const auth_img_desc_t bl32_extra2_image = {
- .img_id = BL32_EXTRA2_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &trusted_os_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &tos_fw_extra2_hash
- }
- }
- }
-};
-
-/* TOS FW Config */
-static const auth_img_desc_t tos_fw_config = {
- .img_id = TOS_FW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &trusted_os_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &tos_fw_config_hash
- }
- }
- }
-};
-
-/* Non-Trusted Firmware */
-static const auth_img_desc_t non_trusted_fw_content_cert = {
- .img_id = NON_TRUSTED_FW_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = NULL, /* Root certificate. */
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &prot_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &non_trusted_nv_ctr,
- .plat_nv_ctr = &non_trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &nt_world_bl_hash,
- .data = {
- .ptr = (void *)nt_world_bl_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &nt_fw_config_hash,
- .data = {
- .ptr = (void *)nt_fw_config_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-static const auth_img_desc_t bl33_image = {
- .img_id = BL33_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &non_trusted_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &nt_world_bl_hash
- }
- }
- }
-};
-
-/* NT FW Config */
-static const auth_img_desc_t nt_fw_config = {
- .img_id = NT_FW_CONFIG_ID,
- .img_type = IMG_RAW,
- .parent = &non_trusted_fw_content_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &nt_fw_config_hash
- }
- }
- }
-};
-
-/*
- * Secure Partitions
- */
-#if defined(SPD_spmd)
-static const auth_img_desc_t sip_sp_content_cert = {
- .img_id = SIP_SP_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = &trusted_key_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &trusted_world_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &trusted_nv_ctr,
- .plat_nv_ctr = &trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &sp_pkg1_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[0],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &sp_pkg2_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[1],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [2] = {
- .type_desc = &sp_pkg3_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[2],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [3] = {
- .type_desc = &sp_pkg4_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[3],
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-DEFINE_SIP_SP_PKG(1);
-DEFINE_SIP_SP_PKG(2);
-DEFINE_SIP_SP_PKG(3);
-DEFINE_SIP_SP_PKG(4);
-
-static const auth_img_desc_t plat_sp_content_cert = {
- .img_id = PLAT_SP_CONTENT_CERT_ID,
- .img_type = IMG_CERT,
- .parent = NULL,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &prot_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- },
- [1] = {
- .type = AUTH_METHOD_NV_CTR,
- .param.nv_ctr = {
- .cert_nv_ctr = &non_trusted_nv_ctr,
- .plat_nv_ctr = &non_trusted_nv_ctr
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &sp_pkg5_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[4],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &sp_pkg6_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[5],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [2] = {
- .type_desc = &sp_pkg7_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[6],
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [3] = {
- .type_desc = &sp_pkg8_hash,
- .data = {
- .ptr = (void *)sp_pkg_hash_buf[7],
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-DEFINE_PLAT_SP_PKG(5);
-DEFINE_PLAT_SP_PKG(6);
-DEFINE_PLAT_SP_PKG(7);
-DEFINE_PLAT_SP_PKG(8);
-#endif /* SPD_spmd */
-
-#else /* IMAGE_BL2 */
-
-/* FWU auth descriptor */
-static const auth_img_desc_t fwu_cert = {
- .img_id = FWU_CERT_ID,
- .img_type = IMG_CERT,
- .parent = NULL,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_SIG,
- .param.sig = {
- .pk = &subject_pk,
- .sig = &sig,
- .alg = &sig_alg,
- .data = &raw_data
- }
- }
- },
- .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
- [0] = {
- .type_desc = &scp_bl2u_hash,
- .data = {
- .ptr = (void *)scp_fw_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [1] = {
- .type_desc = &bl2u_hash,
- .data = {
- .ptr = (void *)tb_fw_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- },
- [2] = {
- .type_desc = &ns_bl2u_hash,
- .data = {
- .ptr = (void *)nt_world_bl_hash_buf,
- .len = (unsigned int)HASH_DER_LEN
- }
- }
- }
-};
-
-/* SCP_BL2U */
-static const auth_img_desc_t scp_bl2u_image = {
- .img_id = SCP_BL2U_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &fwu_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &scp_bl2u_hash
- }
- }
- }
-};
-
-/* BL2U */
-static const auth_img_desc_t bl2u_image = {
- .img_id = BL2U_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &fwu_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &bl2u_hash
- }
- }
- }
-};
-
-/* NS_BL2U */
-static const auth_img_desc_t ns_bl2u_image = {
- .img_id = NS_BL2U_IMAGE_ID,
- .img_type = IMG_RAW,
- .parent = &fwu_cert,
- .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
- [0] = {
- .type = AUTH_METHOD_HASH,
- .param.hash = {
- .data = &raw_data,
- .hash = &ns_bl2u_hash
- }
- }
- }
-};
-#endif /* IMAGE_BL2 */
-
-/*
- * Chain of trust definition
- */
-#ifdef IMAGE_BL1
-static const auth_img_desc_t * const cot_desc[] = {
- [TRUSTED_BOOT_FW_CERT_ID] = &trusted_boot_fw_cert,
- [BL2_IMAGE_ID] = &bl2_image,
- [HW_CONFIG_ID] = &hw_config,
- [TB_FW_CONFIG_ID] = &tb_fw_config,
- [FW_CONFIG_ID] = &fw_config,
- [FWU_CERT_ID] = &fwu_cert,
- [SCP_BL2U_IMAGE_ID] = &scp_bl2u_image,
- [BL2U_IMAGE_ID] = &bl2u_image,
- [NS_BL2U_IMAGE_ID] = &ns_bl2u_image
-};
-#else /* IMAGE_BL2 */
-static const auth_img_desc_t * const cot_desc[] = {
- [TRUSTED_BOOT_FW_CERT_ID] = &trusted_boot_fw_cert,
- [HW_CONFIG_ID] = &hw_config,
- [TRUSTED_KEY_CERT_ID] = &trusted_key_cert,
- [SCP_FW_KEY_CERT_ID] = &scp_fw_key_cert,
- [SCP_FW_CONTENT_CERT_ID] = &scp_fw_content_cert,
- [SCP_BL2_IMAGE_ID] = &scp_bl2_image,
- [SOC_FW_KEY_CERT_ID] = &soc_fw_key_cert,
- [SOC_FW_CONTENT_CERT_ID] = &soc_fw_content_cert,
- [BL31_IMAGE_ID] = &bl31_image,
- [SOC_FW_CONFIG_ID] = &soc_fw_config,
- [TRUSTED_OS_FW_KEY_CERT_ID] = &trusted_os_fw_key_cert,
- [TRUSTED_OS_FW_CONTENT_CERT_ID] = &trusted_os_fw_content_cert,
- [BL32_IMAGE_ID] = &bl32_image,
- [BL32_EXTRA1_IMAGE_ID] = &bl32_extra1_image,
- [BL32_EXTRA2_IMAGE_ID] = &bl32_extra2_image,
- [TOS_FW_CONFIG_ID] = &tos_fw_config,
- [NON_TRUSTED_FW_CONTENT_CERT_ID] = &non_trusted_fw_content_cert,
- [BL33_IMAGE_ID] = &bl33_image,
- [NT_FW_CONFIG_ID] = &nt_fw_config,
-#if defined(SPD_spmd)
- [SIP_SP_CONTENT_CERT_ID] = &sip_sp_content_cert,
- [PLAT_SP_CONTENT_CERT_ID] = &plat_sp_content_cert,
- [SP_PKG1_ID] = &sp_pkg1,
- [SP_PKG2_ID] = &sp_pkg2,
- [SP_PKG3_ID] = &sp_pkg3,
- [SP_PKG4_ID] = &sp_pkg4,
- [SP_PKG5_ID] = &sp_pkg5,
- [SP_PKG6_ID] = &sp_pkg6,
- [SP_PKG7_ID] = &sp_pkg7,
- [SP_PKG8_ID] = &sp_pkg8,
-#endif
-};
-#endif
-
-/* Register the CoT in the authentication module */
-REGISTER_COT(cot_desc);
diff --git a/drivers/auth/mbedtls/mbedtls_common.mk b/drivers/auth/mbedtls/mbedtls_common.mk
index 55ab935..e925e14 100644
--- a/drivers/auth/mbedtls/mbedtls_common.mk
+++ b/drivers/auth/mbedtls/mbedtls_common.mk
@@ -118,6 +118,14 @@
TF_MBEDTLS_HASH_ALG_ID := TF_MBEDTLS_SHA256
endif
+ifeq (${MBOOT_EL_HASH_ALG}, sha256)
+ $(eval $(call add_define,TF_MBEDTLS_MBOOT_USE_SHA256))
+else ifeq (${MBOOT_EL_HASH_ALG}, sha384)
+ $(eval $(call add_define,TF_MBEDTLS_MBOOT_USE_SHA384))
+else ifeq (${MBOOT_EL_HASH_ALG}, sha512)
+ $(eval $(call add_define,TF_MBEDTLS_MBOOT_USE_SHA512))
+endif
+
ifeq (${TF_MBEDTLS_KEY_ALG},ecdsa)
TF_MBEDTLS_KEY_ALG_ID := TF_MBEDTLS_ECDSA
else ifeq (${TF_MBEDTLS_KEY_ALG},rsa)
diff --git a/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h b/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h
index 7205232..84e76f7 100644
--- a/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h
+++ b/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h
@@ -9,6 +9,9 @@
#define FXOSC_BASE_ADDR (0x40050000UL)
#define ARMPLL_BASE_ADDR (0x40038000UL)
+#define PERIPHPLL_BASE_ADDR (0x4003C000UL)
+#define ARM_DFS_BASE_ADDR (0x40054000UL)
+#define CGM0_BASE_ADDR (0x40030000UL)
#define CGM1_BASE_ADDR (0x40034000UL)
/* FXOSC */
@@ -83,4 +86,25 @@
#define MC_CGM_MUXn_CSS_SWIP BIT_32(16U)
#define MC_CGM_MUXn_CSS_SAFE_SW BIT_32(3U)
+/* DFS */
+#define DFS_PORTSR(DFS_ADDR) ((DFS_ADDR) + 0xCUL)
+#define DFS_PORTOLSR(DFS_ADDR) ((DFS_ADDR) + 0x10UL)
+#define DFS_PORTOLSR_LOL(N) (BIT_32(N) & GENMASK_32(5U, 0U))
+#define DFS_PORTRESET(DFS_ADDR) ((DFS_ADDR) + 0x14UL)
+#define DFS_PORTRESET_MASK GENMASK_32(5U, 0U)
+#define DFS_PORTRESET_SET(VAL) (((VAL) & DFS_PORTRESET_MASK))
+
+#define DFS_CTL(DFS_ADDR) ((DFS_ADDR) + 0x18UL)
+#define DFS_CTL_RESET BIT_32(1U)
+
+#define DFS_DVPORTn(DFS_ADDR, PORT) ((DFS_ADDR) + 0x1CUL + ((PORT) * 0x4UL))
+#define DFS_DVPORTn_MFI_MASK GENMASK_32(15U, 8U)
+#define DFS_DVPORTn_MFI_SHIFT 8U
+#define DFS_DVPORTn_MFN_MASK GENMASK_32(7U, 0U)
+#define DFS_DVPORTn_MFN_SHIFT 0U
+#define DFS_DVPORTn_MFI(MFI) (((MFI) & DFS_DVPORTn_MFI_MASK) >> DFS_DVPORTn_MFI_SHIFT)
+#define DFS_DVPORTn_MFN(MFN) (((MFN) & DFS_DVPORTn_MFN_MASK) >> DFS_DVPORTn_MFN_SHIFT)
+#define DFS_DVPORTn_MFI_SET(VAL) (((VAL) << DFS_DVPORTn_MFI_SHIFT) & DFS_DVPORTn_MFI_MASK)
+#define DFS_DVPORTn_MFN_SET(VAL) (((VAL) << DFS_DVPORTn_MFN_SHIFT) & DFS_DVPORTn_MFN_MASK)
+
#endif /* S32CC_CLK_REGS_H */
diff --git a/drivers/nxp/clk/s32cc/s32cc_clk_drv.c b/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
index 6f18dd3..fed16a7 100644
--- a/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
+++ b/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
@@ -22,6 +22,9 @@
struct s32cc_clk_drv {
uintptr_t fxosc_base;
uintptr_t armpll_base;
+ uintptr_t periphpll_base;
+ uintptr_t armdfs_base;
+ uintptr_t cgm0_base;
uintptr_t cgm1_base;
};
@@ -40,6 +43,9 @@
static struct s32cc_clk_drv driver = {
.fxosc_base = FXOSC_BASE_ADDR,
.armpll_base = ARMPLL_BASE_ADDR,
+ .periphpll_base = PERIPHPLL_BASE_ADDR,
+ .armdfs_base = ARM_DFS_BASE_ADDR,
+ .cgm0_base = CGM0_BASE_ADDR,
.cgm1_base = CGM1_BASE_ADDR,
};
@@ -87,6 +93,15 @@
case S32CC_ARM_PLL:
*base = drv->armpll_base;
break;
+ case S32CC_PERIPH_PLL:
+ *base = drv->periphpll_base;
+ break;
+ case S32CC_ARM_DFS:
+ *base = drv->armdfs_base;
+ break;
+ case S32CC_CGM0:
+ *base = drv->cgm0_base;
+ break;
case S32CC_CGM1:
*base = drv->cgm1_base;
break;
@@ -542,6 +557,9 @@
case S32CC_CGM1:
ret = enable_cgm_mux(mux, drv);
break;
+ case S32CC_CGM0:
+ ret = enable_cgm_mux(mux, drv);
+ break;
default:
ERROR("Unknown mux parent type: %d\n", mux->module);
ret = -EINVAL;
@@ -551,6 +569,199 @@
return ret;
}
+static int enable_dfs(const struct s32cc_clk_obj *module,
+ const struct s32cc_clk_drv *drv,
+ unsigned int *depth)
+{
+ int ret = 0;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct s32cc_dfs *get_div_dfs(const struct s32cc_dfs_div *dfs_div)
+{
+ const struct s32cc_clk_obj *parent = dfs_div->parent;
+
+ if (parent->type != s32cc_dfs_t) {
+ ERROR("DFS DIV doesn't have a DFS as parent\n");
+ return NULL;
+ }
+
+ return s32cc_obj2dfs(parent);
+}
+
+static struct s32cc_pll *dfsdiv2pll(const struct s32cc_dfs_div *dfs_div)
+{
+ const struct s32cc_clk_obj *parent;
+ const struct s32cc_dfs *dfs;
+
+ dfs = get_div_dfs(dfs_div);
+ if (dfs == NULL) {
+ return NULL;
+ }
+
+ parent = dfs->parent;
+ if (parent->type != s32cc_pll_t) {
+ return NULL;
+ }
+
+ return s32cc_obj2pll(parent);
+}
+
+static int get_dfs_mfi_mfn(unsigned long dfs_freq, const struct s32cc_dfs_div *dfs_div,
+ uint32_t *mfi, uint32_t *mfn)
+{
+ uint64_t factor64, tmp64, ofreq;
+ uint32_t factor32;
+
+ unsigned long in = dfs_freq;
+ unsigned long out = dfs_div->freq;
+
+ /**
+ * factor = (IN / OUT) / 2
+ * MFI = integer(factor)
+ * MFN = (factor - MFI) * 36
+ */
+ factor64 = ((((uint64_t)in) * FP_PRECISION) / ((uint64_t)out)) / 2ULL;
+ tmp64 = factor64 / FP_PRECISION;
+ if (tmp64 > UINT32_MAX) {
+ return -EINVAL;
+ }
+
+ factor32 = (uint32_t)tmp64;
+ *mfi = factor32;
+
+ tmp64 = ((factor64 - ((uint64_t)*mfi * FP_PRECISION)) * 36UL) / FP_PRECISION;
+ if (tmp64 > UINT32_MAX) {
+ return -EINVAL;
+ }
+
+ *mfn = (uint32_t)tmp64;
+
+ /* div_freq = in / (2 * (*mfi + *mfn / 36.0)) */
+ factor64 = (((uint64_t)*mfn) * FP_PRECISION) / 36ULL;
+ factor64 += ((uint64_t)*mfi) * FP_PRECISION;
+ factor64 *= 2ULL;
+ ofreq = (((uint64_t)in) * FP_PRECISION) / factor64;
+
+ if (ofreq != dfs_div->freq) {
+ ERROR("Failed to find MFI and MFN settings for DFS DIV freq %lu\n",
+ dfs_div->freq);
+ ERROR("Nearest freq = %" PRIx64 "\n", ofreq);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int init_dfs_port(uintptr_t dfs_addr, uint32_t port,
+ uint32_t mfi, uint32_t mfn)
+{
+ uint32_t portsr, portolsr;
+ uint32_t mask, old_mfi, old_mfn;
+ uint32_t dvport;
+ bool init_dfs;
+
+ dvport = mmio_read_32(DFS_DVPORTn(dfs_addr, port));
+
+ old_mfi = DFS_DVPORTn_MFI(dvport);
+ old_mfn = DFS_DVPORTn_MFN(dvport);
+
+ portsr = mmio_read_32(DFS_PORTSR(dfs_addr));
+ portolsr = mmio_read_32(DFS_PORTOLSR(dfs_addr));
+
+ /* Skip configuration if it's not needed */
+ if (((portsr & BIT_32(port)) != 0U) &&
+ ((portolsr & BIT_32(port)) == 0U) &&
+ (mfi == old_mfi) && (mfn == old_mfn)) {
+ return 0;
+ }
+
+ init_dfs = (portsr == 0U);
+
+ if (init_dfs) {
+ mask = DFS_PORTRESET_MASK;
+ } else {
+ mask = DFS_PORTRESET_SET(BIT_32(port));
+ }
+
+ mmio_write_32(DFS_PORTOLSR(dfs_addr), mask);
+ mmio_write_32(DFS_PORTRESET(dfs_addr), mask);
+
+ while ((mmio_read_32(DFS_PORTSR(dfs_addr)) & mask) != 0U) {
+ }
+
+ if (init_dfs) {
+ mmio_write_32(DFS_CTL(dfs_addr), DFS_CTL_RESET);
+ }
+
+ mmio_write_32(DFS_DVPORTn(dfs_addr, port),
+ DFS_DVPORTn_MFI_SET(mfi) | DFS_DVPORTn_MFN_SET(mfn));
+
+ if (init_dfs) {
+ /* DFS clk enable programming */
+ mmio_clrbits_32(DFS_CTL(dfs_addr), DFS_CTL_RESET);
+ }
+
+ mmio_clrbits_32(DFS_PORTRESET(dfs_addr), BIT_32(port));
+
+ while ((mmio_read_32(DFS_PORTSR(dfs_addr)) & BIT_32(port)) != BIT_32(port)) {
+ }
+
+ portolsr = mmio_read_32(DFS_PORTOLSR(dfs_addr));
+ if ((portolsr & DFS_PORTOLSR_LOL(port)) != 0U) {
+ ERROR("Failed to lock DFS divider\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int enable_dfs_div(const struct s32cc_clk_obj *module,
+ const struct s32cc_clk_drv *drv,
+ unsigned int *depth)
+{
+ const struct s32cc_dfs_div *dfs_div = s32cc_obj2dfsdiv(module);
+ const struct s32cc_pll *pll;
+ const struct s32cc_dfs *dfs;
+ uintptr_t dfs_addr = 0UL;
+ uint32_t mfi, mfn;
+ int ret = 0;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ dfs = get_div_dfs(dfs_div);
+ if (dfs == NULL) {
+ return -EINVAL;
+ }
+
+ pll = dfsdiv2pll(dfs_div);
+ if (pll == NULL) {
+ ERROR("Failed to identify DFS divider's parent\n");
+ return -EINVAL;
+ }
+
+ ret = get_base_addr(dfs->instance, drv, &dfs_addr);
+ if ((ret != 0) || (dfs_addr == 0UL)) {
+ return -EINVAL;
+ }
+
+ ret = get_dfs_mfi_mfn(pll->vco_freq, dfs_div, &mfi, &mfn);
+ if (ret != 0) {
+ return -EINVAL;
+ }
+
+ return init_dfs_port(dfs_addr, dfs_div->index, mfi, mfn);
+}
+
static int enable_module(const struct s32cc_clk_obj *module, unsigned int *depth)
{
const struct s32cc_clk_drv *drv = get_drv();
@@ -587,6 +798,12 @@
case s32cc_fixed_div_t:
ret = -ENOTSUP;
break;
+ case s32cc_dfs_t:
+ ret = enable_dfs(module, drv, depth);
+ break;
+ case s32cc_dfs_div_t:
+ ret = enable_dfs_div(module, drv, depth);
+ break;
default:
ret = -EINVAL;
break;
@@ -793,6 +1010,42 @@
return set_module_rate(&clk->desc, rate, orate, depth);
}
+static int set_dfs_div_freq(const struct s32cc_clk_obj *module, unsigned long rate,
+ unsigned long *orate, unsigned int *depth)
+{
+ struct s32cc_dfs_div *dfs_div = s32cc_obj2dfsdiv(module);
+ const struct s32cc_dfs *dfs;
+ int ret;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (dfs_div->parent == NULL) {
+ ERROR("Failed to identify DFS divider's parent\n");
+ return -EINVAL;
+ }
+
+ /* Sanity check */
+ dfs = s32cc_obj2dfs(dfs_div->parent);
+ if (dfs->parent == NULL) {
+ ERROR("Failed to identify DFS's parent\n");
+ return -EINVAL;
+ }
+
+ if ((dfs_div->freq != 0U) && (dfs_div->freq != rate)) {
+ ERROR("DFS DIV frequency was already set to %lu\n",
+ dfs_div->freq);
+ return -EINVAL;
+ }
+
+ dfs_div->freq = rate;
+ *orate = rate;
+
+ return ret;
+}
+
static int set_module_rate(const struct s32cc_clk_obj *module,
unsigned long rate, unsigned long *orate,
unsigned int *depth)
@@ -804,6 +1057,8 @@
return ret;
}
+ ret = -EINVAL;
+
switch (module->type) {
case s32cc_clk_t:
ret = set_clk_freq(module, rate, orate, depth);
@@ -826,8 +1081,13 @@
case s32cc_shared_clkmux_t:
ret = set_mux_freq(module, rate, orate, depth);
break;
+ case s32cc_dfs_t:
+ ERROR("Setting the frequency of a DFS is not allowed!");
+ break;
+ case s32cc_dfs_div_t:
+ ret = set_dfs_div_freq(module, rate, orate, depth);
+ break;
default:
- ret = -EINVAL;
break;
}
diff --git a/drivers/nxp/clk/s32cc/s32cc_clk_modules.c b/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
index 039db2a..45e2070 100644
--- a/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
+++ b/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
@@ -43,6 +43,60 @@
static struct s32cc_clk arm_pll_phi0_clk =
S32CC_FREQ_MODULE_CLK(arm_pll_phi0_div, 0, GHZ);
+/* ARM DFS */
+static struct s32cc_dfs armdfs =
+ S32CC_DFS_INIT(armpll, S32CC_ARM_DFS);
+static struct s32cc_dfs_div arm_dfs1_div =
+ S32CC_DFS_DIV_INIT(armdfs, 0);
+static struct s32cc_clk arm_dfs1_clk =
+ S32CC_FREQ_MODULE_CLK(arm_dfs1_div, 0, 800 * MHZ);
+
+/* MC_CGM0 */
+static struct s32cc_clkmux cgm0_mux0 =
+ S32CC_SHARED_CLKMUX_INIT(S32CC_CGM0, 0, 2,
+ S32CC_CLK_FIRC,
+ S32CC_CLK_ARM_PLL_DFS1, 0, 0, 0);
+static struct s32cc_clk cgm0_mux0_clk = S32CC_MODULE_CLK(cgm0_mux0);
+
+static struct s32cc_clkmux cgm0_mux8 =
+ S32CC_SHARED_CLKMUX_INIT(S32CC_CGM0, 8, 3,
+ S32CC_CLK_FIRC,
+ S32CC_CLK_PERIPH_PLL_PHI3,
+ S32CC_CLK_FXOSC, 0, 0);
+static struct s32cc_clk cgm0_mux8_clk = S32CC_MODULE_CLK(cgm0_mux8);
+
+/* XBAR */
+static struct s32cc_clk xbar_2x_clk =
+ S32CC_CHILD_CLK(cgm0_mux0_clk, 48 * MHZ, 800 * MHZ);
+static struct s32cc_fixed_div xbar_div2 =
+ S32CC_FIXED_DIV_INIT(cgm0_mux0_clk, 2);
+static struct s32cc_clk xbar_clk =
+ S32CC_FREQ_MODULE_CLK(xbar_div2, 24 * MHZ, 400 * MHZ);
+static struct s32cc_fixed_div xbar_div4 =
+ S32CC_FIXED_DIV_INIT(cgm0_mux0_clk, 4);
+static struct s32cc_clk xbar_div2_clk =
+ S32CC_FREQ_MODULE_CLK(xbar_div4, 12 * MHZ, 200 * MHZ);
+static struct s32cc_fixed_div xbar_div6 =
+ S32CC_FIXED_DIV_INIT(cgm0_mux0_clk, 6);
+static struct s32cc_clk xbar_div3_clk =
+ S32CC_FREQ_MODULE_CLK(xbar_div6, 8 * MHZ, 133333333);
+static struct s32cc_fixed_div xbar_div8 =
+ S32CC_FIXED_DIV_INIT(cgm0_mux0_clk, 8);
+static struct s32cc_clk xbar_div4_clk =
+ S32CC_FREQ_MODULE_CLK(xbar_div8, 6 * MHZ, 100 * MHZ);
+static struct s32cc_fixed_div xbar_div12 =
+ S32CC_FIXED_DIV_INIT(cgm0_mux0_clk, 12);
+static struct s32cc_clk xbar_div6_clk =
+ S32CC_FREQ_MODULE_CLK(xbar_div12, 4 * MHZ, 66666666);
+
+/* Linflex */
+static struct s32cc_clk linflex_baud_clk =
+ S32CC_CHILD_CLK(cgm0_mux8_clk, 19200, 133333333);
+static struct s32cc_fixed_div linflex_div =
+ S32CC_FIXED_DIV_INIT(linflex_baud_clk, 2);
+static struct s32cc_clk linflex_clk =
+ S32CC_FREQ_MODULE_CLK(linflex_div, 9600, 66666666);
+
/* MC_CGM1 */
static struct s32cc_clkmux cgm1_mux0 =
S32CC_SHARED_CLKMUX_INIT(S32CC_CGM1, 0, 3,
@@ -68,13 +122,34 @@
S32CC_FREQ_MODULE_CLK(a53_core_div10, S32CC_A53_MIN_FREQ / 10,
S32CC_A53_MAX_FREQ / 10);
-static struct s32cc_clk *s32cc_hw_clk_list[5] = {
+/* PERIPH PLL */
+static struct s32cc_clkmux periph_pll_mux =
+ S32CC_CLKMUX_INIT(S32CC_PERIPH_PLL, 0, 2,
+ S32CC_CLK_FIRC,
+ S32CC_CLK_FXOSC, 0, 0, 0);
+static struct s32cc_clk periph_pll_mux_clk =
+ S32CC_MODULE_CLK(periph_pll_mux);
+static struct s32cc_pll periphpll =
+ S32CC_PLL_INIT(periph_pll_mux_clk, S32CC_PERIPH_PLL, 2);
+static struct s32cc_clk periph_pll_vco_clk =
+ S32CC_FREQ_MODULE_CLK(periphpll, 1300 * MHZ, 2 * GHZ);
+
+static struct s32cc_pll_out_div periph_pll_phi3_div =
+ S32CC_PLL_OUT_DIV_INIT(periphpll, 3);
+static struct s32cc_clk periph_pll_phi3_clk =
+ S32CC_FREQ_MODULE_CLK(periph_pll_phi3_div, 0, 133333333);
+
+static struct s32cc_clk *s32cc_hw_clk_list[22] = {
/* Oscillators */
[S32CC_CLK_ID(S32CC_CLK_FIRC)] = &firc_clk,
[S32CC_CLK_ID(S32CC_CLK_SIRC)] = &sirc_clk,
[S32CC_CLK_ID(S32CC_CLK_FXOSC)] = &fxosc_clk,
/* ARM PLL */
[S32CC_CLK_ID(S32CC_CLK_ARM_PLL_PHI0)] = &arm_pll_phi0_clk,
+ /* ARM DFS */
+ [S32CC_CLK_ID(S32CC_CLK_ARM_PLL_DFS1)] = &arm_dfs1_clk,
+ /* PERIPH PLL */
+ [S32CC_CLK_ID(S32CC_CLK_PERIPH_PLL_PHI3)] = &periph_pll_phi3_clk,
};
static struct s32cc_clk_array s32cc_hw_clocks = {
@@ -83,16 +158,32 @@
.n_clks = ARRAY_SIZE(s32cc_hw_clk_list),
};
-static struct s32cc_clk *s32cc_arch_clk_list[6] = {
+static struct s32cc_clk *s32cc_arch_clk_list[18] = {
/* ARM PLL */
[S32CC_CLK_ID(S32CC_CLK_ARM_PLL_MUX)] = &arm_pll_mux_clk,
[S32CC_CLK_ID(S32CC_CLK_ARM_PLL_VCO)] = &arm_pll_vco_clk,
+ /* PERIPH PLL */
+ [S32CC_CLK_ID(S32CC_CLK_PERIPH_PLL_MUX)] = &periph_pll_mux_clk,
+ [S32CC_CLK_ID(S32CC_CLK_PERIPH_PLL_VCO)] = &periph_pll_vco_clk,
+ /* MC_CGM0 */
+ [S32CC_CLK_ID(S32CC_CLK_MC_CGM0_MUX0)] = &cgm0_mux0_clk,
+ [S32CC_CLK_ID(S32CC_CLK_MC_CGM0_MUX8)] = &cgm0_mux8_clk,
+ /* XBAR */
+ [S32CC_CLK_ID(S32CC_CLK_XBAR_2X)] = &xbar_2x_clk,
+ [S32CC_CLK_ID(S32CC_CLK_XBAR)] = &xbar_clk,
+ [S32CC_CLK_ID(S32CC_CLK_XBAR_DIV2)] = &xbar_div2_clk,
+ [S32CC_CLK_ID(S32CC_CLK_XBAR_DIV3)] = &xbar_div3_clk,
+ [S32CC_CLK_ID(S32CC_CLK_XBAR_DIV4)] = &xbar_div4_clk,
+ [S32CC_CLK_ID(S32CC_CLK_XBAR_DIV6)] = &xbar_div6_clk,
/* MC_CGM1 */
[S32CC_CLK_ID(S32CC_CLK_MC_CGM1_MUX0)] = &cgm1_mux0_clk,
/* A53 */
[S32CC_CLK_ID(S32CC_CLK_A53_CORE)] = &a53_core_clk,
[S32CC_CLK_ID(S32CC_CLK_A53_CORE_DIV2)] = &a53_core_div2_clk,
[S32CC_CLK_ID(S32CC_CLK_A53_CORE_DIV10)] = &a53_core_div10_clk,
+ /* Linflex */
+ [S32CC_CLK_ID(S32CC_CLK_LINFLEX)] = &linflex_clk,
+ [S32CC_CLK_ID(S32CC_CLK_LINFLEX_BAUD)] = &linflex_baud_clk,
};
static struct s32cc_clk_array s32cc_arch_clocks = {
diff --git a/drivers/nxp/clk/s32cc/s32cc_early_clks.c b/drivers/nxp/clk/s32cc/s32cc_early_clks.c
index 560f8bc..8c4a9e8 100644
--- a/drivers/nxp/clk/s32cc/s32cc_early_clks.c
+++ b/drivers/nxp/clk/s32cc/s32cc_early_clks.c
@@ -4,32 +4,41 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <drivers/clk.h>
+#include <platform_def.h>
#include <s32cc-clk-drv.h>
#include <s32cc-clk-ids.h>
#include <s32cc-clk-utils.h>
-#define S32CC_FXOSC_FREQ (40U * MHZ)
-#define S32CC_ARM_PLL_VCO_FREQ (2U * GHZ)
-#define S32CC_ARM_PLL_PHI0_FREQ (1U * GHZ)
-#define S32CC_A53_FREQ (1U * GHZ)
+#define S32CC_FXOSC_FREQ (40U * MHZ)
+#define S32CC_ARM_PLL_VCO_FREQ (2U * GHZ)
+#define S32CC_ARM_PLL_PHI0_FREQ (1U * GHZ)
+#define S32CC_A53_FREQ (1U * GHZ)
+#define S32CC_XBAR_2X_FREQ (800U * MHZ)
+#define S32CC_PERIPH_PLL_VCO_FREQ (2U * GHZ)
+#define S32CC_PERIPH_PLL_PHI3_FREQ UART_CLOCK_HZ
-int s32cc_init_early_clks(void)
+static int enable_fxosc_clk(void)
{
int ret;
- s32cc_clk_register_drv();
-
- ret = clk_set_parent(S32CC_CLK_ARM_PLL_MUX, S32CC_CLK_FXOSC);
+ ret = clk_set_rate(S32CC_CLK_FXOSC, S32CC_FXOSC_FREQ, NULL);
if (ret != 0) {
return ret;
}
- ret = clk_set_parent(S32CC_CLK_MC_CGM1_MUX0, S32CC_CLK_ARM_PLL_PHI0);
+ ret = clk_enable(S32CC_CLK_FXOSC);
if (ret != 0) {
return ret;
}
- ret = clk_set_rate(S32CC_CLK_FXOSC, S32CC_FXOSC_FREQ, NULL);
+ return ret;
+}
+
+static int enable_arm_pll(void)
+{
+ int ret;
+
+ ret = clk_set_parent(S32CC_CLK_ARM_PLL_MUX, S32CC_CLK_FXOSC);
if (ret != 0) {
return ret;
}
@@ -44,22 +53,61 @@
return ret;
}
- ret = clk_set_rate(S32CC_CLK_A53_CORE, S32CC_A53_FREQ, NULL);
+ ret = clk_enable(S32CC_CLK_ARM_PLL_VCO);
if (ret != 0) {
return ret;
}
- ret = clk_enable(S32CC_CLK_FXOSC);
+ ret = clk_enable(S32CC_CLK_ARM_PLL_PHI0);
if (ret != 0) {
return ret;
}
- ret = clk_enable(S32CC_CLK_ARM_PLL_VCO);
+ return ret;
+}
+
+static int enable_periph_pll(void)
+{
+ int ret;
+
+ ret = clk_set_parent(S32CC_CLK_PERIPH_PLL_MUX, S32CC_CLK_FXOSC);
if (ret != 0) {
return ret;
}
- ret = clk_enable(S32CC_CLK_ARM_PLL_PHI0);
+ ret = clk_set_rate(S32CC_CLK_PERIPH_PLL_VCO, S32CC_PERIPH_PLL_VCO_FREQ, NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_set_rate(S32CC_CLK_PERIPH_PLL_PHI3, S32CC_PERIPH_PLL_PHI3_FREQ, NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_enable(S32CC_CLK_PERIPH_PLL_VCO);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_enable(S32CC_CLK_PERIPH_PLL_PHI3);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return ret;
+}
+
+static int enable_a53_clk(void)
+{
+ int ret;
+
+ ret = clk_set_parent(S32CC_CLK_MC_CGM1_MUX0, S32CC_CLK_ARM_PLL_PHI0);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_set_rate(S32CC_CLK_A53_CORE, S32CC_A53_FREQ, NULL);
if (ret != 0) {
return ret;
}
@@ -71,3 +119,86 @@
return ret;
}
+
+static int enable_xbar_clk(void)
+{
+ int ret;
+
+ ret = clk_set_parent(S32CC_CLK_MC_CGM0_MUX0, S32CC_CLK_ARM_PLL_DFS1);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_set_rate(S32CC_CLK_XBAR_2X, S32CC_XBAR_2X_FREQ, NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_enable(S32CC_CLK_ARM_PLL_DFS1);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_enable(S32CC_CLK_XBAR_2X);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return ret;
+}
+
+static int enable_uart_clk(void)
+{
+ int ret;
+
+ ret = clk_set_parent(S32CC_CLK_MC_CGM0_MUX8, S32CC_CLK_PERIPH_PLL_PHI3);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_enable(S32CC_CLK_LINFLEX_BAUD);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return ret;
+}
+
+int s32cc_init_early_clks(void)
+{
+ int ret;
+
+ s32cc_clk_register_drv();
+
+ ret = enable_fxosc_clk();
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = enable_arm_pll();
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = enable_periph_pll();
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = enable_a53_clk();
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = enable_xbar_clk();
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = enable_uart_clk();
+ if (ret != 0) {
+ return ret;
+ }
+
+ return ret;
+}
diff --git a/drivers/nxp/console/linflex_console.S b/drivers/nxp/console/linflex_console.S
index abcbb59..d8c10ef 100644
--- a/drivers/nxp/console/linflex_console.S
+++ b/drivers/nxp/console/linflex_console.S
@@ -18,6 +18,7 @@
#define LINFLEX_LINSR (0x8)
#define LINSR_LINS_INITMODE (0x00001000)
+#define LINSR_LINS_RX_TX_MODE (0x00008000)
#define LINSR_LINS_MASK (0x0000F000)
#define LINFLEX_UARTCR (0x10)
@@ -48,9 +49,11 @@
*/
.globl console_linflex_core_init
.globl console_linflex_core_putc
+.globl console_linflex_core_flush
.globl console_linflex_register
.globl console_linflex_putc
+.globl console_linflex_flush
/**
* uint32_t get_ldiv_mult(uintptr_t baseaddr, uint32_t clock,
@@ -175,10 +178,29 @@
str x0, [x3, #CONSOLE_T_BASE]
mov x0, x3
- finish_console_register linflex, putc=1, getc=0, flush=0
+ finish_console_register linflex, putc=1, getc=0, flush=1
endfunc console_linflex_register
/**
+ * int console_linflex_core_flush(uintptr_t baseaddr);
+ *
+ * Loop while the TX fifo is not empty, depending on the selected UART mode.
+ *
+ * In: x0 - Linflex base address
+ * Clobber list : x0 - x1
+ */
+func console_linflex_core_flush
+wait_rx_tx:
+ ldr w1, [x0, LINFLEX_LINSR]
+ and w1, w1, #LINSR_LINS_MASK
+ cmp w1, #LINSR_LINS_RX_TX_MODE
+ b.eq wait_rx_tx
+
+ mov x0, #0
+ ret
+endfunc console_linflex_core_flush
+
+/**
* int console_linflex_core_putc(int c, uintptr_t baseaddr);
* Out: w0 - printed character on success, < 0 on error.
@@ -257,3 +279,21 @@
mov x0, #-EINVAL
ret
endfunc console_linflex_putc
+
+/**
+ * int console_linflex_flush(console_t *console);
+ *
+ * Function to wait for the TX FIFO to be cleared.
+ * In : x0 - pointer to console_t struct
+ * Out: x0 - return -1 on error else return 0.
+ * Clobber list : x0 - x1
+ */
+func console_linflex_flush
+ cbz x0, flush_error
+ ldr x0, [x0, #CONSOLE_T_BASE]
+
+ b console_linflex_core_flush
+flush_error:
+ mov x0, #-EINVAL
+ ret
+endfunc console_linflex_flush
diff --git a/drivers/rpi3/gpio/rpi3_gpio.c b/drivers/rpi3/gpio/rpi3_gpio.c
index 55a8832..460afe1 100644
--- a/drivers/rpi3/gpio/rpi3_gpio.c
+++ b/drivers/rpi3/gpio/rpi3_gpio.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2019, Linaro Limited
* Copyright (c) 2019, Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -120,7 +121,7 @@
int regN = gpio / 32;
int shift = gpio % 32;
uintptr_t reg_set = reg_base + RPI3_GPIO_GPSET(regN);
- uintptr_t reg_clr = reg_base + RPI3_GPIO_GPSET(regN);
+ uintptr_t reg_clr = reg_base + RPI3_GPIO_GPCLR(regN);
switch (value) {
case GPIO_LEVEL_LOW:
diff --git a/drivers/st/ddr/stm32mp2_ddr_helpers.c b/drivers/st/ddr/stm32mp2_ddr_helpers.c
new file mode 100644
index 0000000..e6be9dd
--- /dev/null
+++ b/drivers/st/ddr/stm32mp2_ddr_helpers.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2024, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+
+void ddr_sub_system_clk_init(void)
+{
+ mmio_write_32(stm32mp_rcc_base() + RCC_DDRCPCFGR,
+ RCC_DDRCPCFGR_DDRCPEN | RCC_DDRCPCFGR_DDRCPLPEN);
+}
diff --git a/fdts/cca_cot_descriptors.dtsi b/fdts/cca_cot_descriptors.dtsi
index 821f600..93d60ea 100644
--- a/fdts/cca_cot_descriptors.dtsi
+++ b/fdts/cca_cot_descriptors.dtsi
@@ -15,7 +15,7 @@
cca_content_cert: cca_content_cert {
root-certificate;
image-id =<CCA_CONTENT_CERT_ID>;
- antirollback-counter = <&cca_nv_counter>;
+ antirollback-counter = <&cca_nv_ctr>;
tb_fw_hash: tb_fw_hash {
oid = TRUSTED_BOOT_FW_HASH_OID;
@@ -44,7 +44,7 @@
root-certificate;
image-id = <CORE_SWD_KEY_CERT_ID>;
signing-key = <&swd_rot_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
core_swd_pk: core_swd_pk {
oid = CORE_SWD_PK_OID;
@@ -55,7 +55,7 @@
image-id = <TRUSTED_OS_FW_CONTENT_CERT_ID>;
parent = <&core_swd_key_cert>;
signing-key = <&core_swd_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
tos_fw_hash: tos_fw_hash {
oid = TRUSTED_OS_FW_HASH_OID;
@@ -69,7 +69,7 @@
root-certificate;
image-id = <PLAT_KEY_CERT_ID>;
signing-key = <&prot_pk>;
- antirollback-counter = <&non_trusted_nv_counter>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
plat_pk: plat_pk {
oid = PLAT_PK_OID;
@@ -80,7 +80,7 @@
image-id = <NON_TRUSTED_FW_CONTENT_CERT_ID>;
parent = <&plat_key_cert>;
signing-key = <&plat_pk>;
- antirollback-counter = <&non_trusted_nv_counter>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
nt_world_bl_hash: nt_world_bl_hash {
oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID;
@@ -95,7 +95,7 @@
image-id = <SIP_SP_CONTENT_CERT_ID>;
parent = <&core_swd_key_cert>;
signing-key = <&core_swd_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
sp_pkg1_hash: sp_pkg1_hash {
oid = SP_PKG1_HASH_OID;
@@ -115,7 +115,7 @@
image-id = <PLAT_SP_CONTENT_CERT_ID>;
parent = <&plat_key_cert>;
signing-key = <&plat_pk>;
- antirollback-counter = <&non_trusted_nv_counter>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
sp_pkg5_hash: sp_pkg5_hash {
oid = SP_PKG5_HASH_OID;
@@ -242,17 +242,17 @@
#address-cells = <1>;
#size-cells = <0>;
- cca_nv_counter: cca_nv_counter {
+ cca_nv_ctr: cca_nv_ctr {
id = <TRUSTED_NV_CTR_ID>;
oid = CCA_FW_NVCOUNTER_OID;
};
- trusted_nv_counter: trusted_nv_counter {
+ trusted_nv_ctr: trusted_nv_ctr {
id = <TRUSTED_NV_CTR_ID>;
oid = TRUSTED_FW_NVCOUNTER_OID;
};
- non_trusted_nv_counter: non_trusted_nv_counter {
+ non_trusted_nv_ctr: non_trusted_nv_ctr {
id = <NON_TRUSTED_NV_CTR_ID>;
oid = NON_TRUSTED_FW_NVCOUNTER_OID;
};
diff --git a/fdts/dualroot_cot_descriptors.dtsi b/fdts/dualroot_cot_descriptors.dtsi
index 459a1dd..bea7af5 100644
--- a/fdts/dualroot_cot_descriptors.dtsi
+++ b/fdts/dualroot_cot_descriptors.dtsi
@@ -15,7 +15,7 @@
trusted_boot_fw_cert: trusted_boot_fw_cert {
root-certificate;
image-id =<TRUSTED_BOOT_FW_CERT_ID>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
tb_fw_hash: tb_fw_hash {
oid = TRUSTED_BOOT_FW_HASH_OID;
@@ -34,7 +34,7 @@
trusted_key_cert: trusted_key_cert {
root-certificate;
image-id = <TRUSTED_KEY_CERT_ID>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
trusted_world_pk: trusted_world_pk {
oid = TRUSTED_WORLD_PK_OID;
@@ -45,7 +45,7 @@
image-id = <SCP_FW_KEY_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&trusted_world_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
scp_fw_content_pk: scp_fw_content_pk {
oid = SCP_FW_CONTENT_CERT_PK_OID;
@@ -56,7 +56,7 @@
image-id = <SCP_FW_CONTENT_CERT_ID>;
parent = <&scp_fw_key_cert>;
signing-key = <&scp_fw_content_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
scp_fw_hash: scp_fw_hash {
oid = SCP_FW_HASH_OID;
@@ -67,7 +67,7 @@
image-id = <SOC_FW_KEY_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&trusted_world_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
soc_fw_content_pk: soc_fw_content_pk {
oid = SOC_FW_CONTENT_CERT_PK_OID;
};
@@ -77,7 +77,7 @@
image-id = <SOC_FW_CONTENT_CERT_ID>;
parent = <&soc_fw_key_cert>;
signing-key = <&soc_fw_content_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
soc_fw_hash: soc_fw_hash {
oid = SOC_AP_FW_HASH_OID;
@@ -91,7 +91,7 @@
image-id = <TRUSTED_OS_FW_KEY_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&trusted_world_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
tos_fw_content_pk: tos_fw_content_pk {
oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID;
@@ -102,7 +102,7 @@
image-id = <TRUSTED_OS_FW_CONTENT_CERT_ID>;
parent = <&trusted_os_fw_key_cert>;
signing-key = <&tos_fw_content_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
tos_fw_hash: tos_fw_hash {
oid = TRUSTED_OS_FW_HASH_OID;
@@ -122,7 +122,7 @@
root-certificate;
image-id = <NON_TRUSTED_FW_CONTENT_CERT_ID>;
signing-key = <&prot_pk>;
- antirollback-counter = <&non_trusted_nv_counter>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
nt_world_bl_hash: nt_world_bl_hash {
oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID;
@@ -137,7 +137,7 @@
image-id = <SIP_SP_CONTENT_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&trusted_world_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
sp_pkg1_hash: sp_pkg1_hash {
oid = SP_PKG1_HASH_OID;
@@ -157,7 +157,7 @@
root-certificate;
image-id = <PLAT_SP_CONTENT_CERT_ID>;
signing-key = <&prot_pk>;
- antirollback-counter = <&non_trusted_nv_counter>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
sp_pkg5_hash: sp_pkg5_hash {
oid = SP_PKG5_HASH_OID;
@@ -296,12 +296,12 @@
#address-cells = <1>;
#size-cells = <0>;
- trusted_nv_counter: trusted_nv_counter {
+ trusted_nv_ctr: trusted_nv_ctr {
id = <TRUSTED_NV_CTR_ID>;
oid = TRUSTED_FW_NVCOUNTER_OID;
};
- non_trusted_nv_counter: non_trusted_nv_counter {
+ non_trusted_nv_ctr: non_trusted_nv_ctr {
id = <NON_TRUSTED_NV_CTR_ID>;
oid = NON_TRUSTED_FW_NVCOUNTER_OID;
};
diff --git a/fdts/stm32mp1-cot-descriptors.dtsi b/fdts/stm32mp1-cot-descriptors.dtsi
index eb632ff..05326be 100644
--- a/fdts/stm32mp1-cot-descriptors.dtsi
+++ b/fdts/stm32mp1-cot-descriptors.dtsi
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2022, ARM Limited. All rights reserved.
+ * Copyright (c) 2020-2024, ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -15,7 +15,7 @@
stm32mp_cfg_cert: stm32mp_cfg_cert {
root-certificate;
image-id = <STM32MP_CONFIG_CERT_ID>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
hw_config_hash: hw_config_hash {
oid = HW_CONFIG_HASH_OID;
@@ -29,7 +29,7 @@
trusted_key_cert: trusted_key_cert {
root-certificate;
image-id = <TRUSTED_KEY_CERT_ID>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
trusted_world_pk: trusted_world_pk {
oid = TRUSTED_WORLD_PK_OID;
@@ -43,7 +43,7 @@
image-id = <TRUSTED_OS_FW_KEY_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&trusted_world_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
tos_fw_content_pk: tos_fw_content_pk {
oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID;
@@ -54,7 +54,7 @@
image-id = <TRUSTED_OS_FW_CONTENT_CERT_ID>;
parent = <&trusted_os_fw_key_cert>;
signing-key = <&tos_fw_content_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
tos_fw_hash: tos_fw_hash {
oid = TRUSTED_OS_FW_HASH_OID;
@@ -74,7 +74,7 @@
image-id = <NON_TRUSTED_FW_KEY_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&non_trusted_world_pk>;
- antirollback-counter = <&non_trusted_nv_counter>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
nt_fw_content_pk: nt_fw_content_pk {
oid = NON_TRUSTED_FW_CONTENT_CERT_PK_OID;
@@ -85,7 +85,7 @@
image-id = <NON_TRUSTED_FW_CONTENT_CERT_ID>;
parent = <&non_trusted_fw_key_cert>;
signing-key = <&nt_fw_content_pk>;
- antirollback-counter = <&non_trusted_nv_counter>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
nt_world_bl_hash: nt_world_bl_hash {
oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID;
@@ -144,12 +144,12 @@
#address-cells = <1>;
#size-cells = <0>;
- trusted_nv_counter: trusted_nv_counter {
+ trusted_nv_ctr: trusted_nv_ctr {
id = <TRUSTED_NV_CTR_ID>;
oid = TRUSTED_FW_NVCOUNTER_OID;
};
- non_trusted_nv_counter: non_trusted_nv_counter {
+ non_trusted_nv_ctr: non_trusted_nv_ctr {
id = <NON_TRUSTED_NV_CTR_ID>;
oid = NON_TRUSTED_FW_NVCOUNTER_OID;
};
diff --git a/fdts/stm32mp25-bl2.dtsi b/fdts/stm32mp25-bl2.dtsi
index 438a58c..769aab2 100644
--- a/fdts/stm32mp25-bl2.dtsi
+++ b/fdts/stm32mp25-bl2.dtsi
@@ -1,4 +1,35 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause)
/*
- * Copyright (C) 2023, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2023-2024, STMicroelectronics - All Rights Reserved
*/
+
+/ {
+ soc@0 {
+#if !STM32MP_EMMC && !STM32MP_SDMMC
+ rifsc@42080000 {
+ /delete-node/ mmc@48220000;
+ /delete-node/ mmc@48230000;
+ };
+#endif
+ };
+
+ /*
+ * UUID's here are UUID RFC 4122 compliant meaning fieds are stored in
+ * network order (big endian)
+ */
+
+ st-io_policies {
+ fip-handles {
+ compatible = "st,io-fip-handle";
+ fw_cfg_uuid = "5807e16a-8459-47be-8ed5-648e8dddab0e";
+ bl31_uuid = "47d4086d-4cfe-9846-9b95-2950cbbd5a00";
+ bl32_uuid = "05d0e189-53dc-1347-8d2b-500a4b7a3e38";
+ bl32_extra1_uuid = "0b70c29b-2a5a-7840-9f65-0a5682738288";
+ bl32_extra2_uuid = "8ea87bb1-cfa2-3f4d-85fd-e7bba50220d9";
+ bl33_uuid = "d6d0eea7-fcea-d54b-9782-9934f234b6e4";
+ hw_cfg_uuid = "08b8f1d9-c9cf-9349-a962-6fbc6b7265cc";
+ tos_fw_cfg_uuid = "26257c1a-dbc6-7f47-8d96-c4c4b0248021";
+ nt_fw_cfg_uuid = "28da9815-93e8-7e44-ac66-1aaf801550f9";
+ };
+ };
+};
diff --git a/fdts/stm32mp25-fw-config.dtsi b/fdts/stm32mp25-fw-config.dtsi
new file mode 100644
index 0000000..b187ad2
--- /dev/null
+++ b/fdts/stm32mp25-fw-config.dtsi
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+/*
+ * Copyright (c) 2024, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common/tbbr/tbbr_img_def.h>
+
+#include <platform_def.h>
+
+/dts-v1/;
+
+/ {
+ dtb-registry {
+ compatible = "fconf,dyn_cfg-dtb_registry";
+
+ hw-config {
+ load-address = <0x0 STM32MP_HW_CONFIG_BASE>;
+ max-size = <STM32MP_HW_CONFIG_MAX_SIZE>;
+ id = <HW_CONFIG_ID>;
+ };
+
+ nt_fw {
+ load-address = <0x0 STM32MP_BL33_BASE>;
+ max-size = <STM32MP_BL33_MAX_SIZE>;
+ id = <BL33_IMAGE_ID>;
+ };
+
+ tos_fw {
+ id = <BL32_IMAGE_ID>;
+ };
+ };
+};
diff --git a/fdts/stm32mp25-pinctrl.dtsi b/fdts/stm32mp25-pinctrl.dtsi
index 05876a3..fb12808 100644
--- a/fdts/stm32mp25-pinctrl.dtsi
+++ b/fdts/stm32mp25-pinctrl.dtsi
@@ -1,12 +1,65 @@
// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause)
/*
- * Copyright (C) 2023, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2023-2024, STMicroelectronics - All Rights Reserved
* Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
*/
#include <dt-bindings/pinctrl/stm32-pinfunc.h>
&pinctrl {
/omit-if-no-ref/
+ sdmmc1_b4_pins_a: sdmmc1-b4-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('E', 4, AF10)>, /* SDMMC1_D0 */
+ <STM32_PINMUX('E', 5, AF10)>, /* SDMMC1_D1 */
+ <STM32_PINMUX('E', 0, AF10)>, /* SDMMC1_D2 */
+ <STM32_PINMUX('E', 1, AF10)>, /* SDMMC1_D3 */
+ <STM32_PINMUX('E', 2, AF10)>; /* SDMMC1_CMD */
+ slew-rate = <2>;
+ drive-push-pull;
+ bias-disable;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('E', 3, AF10)>; /* SDMMC1_CK */
+ slew-rate = <3>;
+ drive-push-pull;
+ bias-disable;
+ };
+ };
+
+ /omit-if-no-ref/
+ sdmmc2_b4_pins_a: sdmmc2-b4-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('E', 13, AF12)>, /* SDMMC2_D0 */
+ <STM32_PINMUX('E', 11, AF12)>, /* SDMMC2_D1 */
+ <STM32_PINMUX('E', 8, AF12)>, /* SDMMC2_D2 */
+ <STM32_PINMUX('E', 12, AF12)>, /* SDMMC2_D3 */
+ <STM32_PINMUX('E', 15, AF12)>; /* SDMMC2_CMD */
+ slew-rate = <2>;
+ drive-push-pull;
+ bias-pull-up;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('E', 14, AF12)>; /* SDMMC2_CK */
+ slew-rate = <3>;
+ drive-push-pull;
+ bias-pull-up;
+ };
+ };
+
+ /omit-if-no-ref/
+ sdmmc2_d47_pins_a: sdmmc2-d47-0 {
+ pins {
+ pinmux = <STM32_PINMUX('E', 10, AF12)>, /* SDMMC2_D4 */
+ <STM32_PINMUX('E', 9, AF12)>, /* SDMMC2_D5 */
+ <STM32_PINMUX('E', 6, AF12)>, /* SDMMC2_D6 */
+ <STM32_PINMUX('E', 7, AF12)>; /* SDMMC2_D7 */
+ slew-rate = <2>;
+ drive-push-pull;
+ bias-pull-up;
+ };
+ };
+
+ /omit-if-no-ref/
usart2_pins_a: usart2-0 {
pins1 {
pinmux = <STM32_PINMUX('A', 4, AF6)>; /* USART2_TX */
diff --git a/fdts/stm32mp251.dtsi b/fdts/stm32mp251.dtsi
index 6e262bb..6f39b5a 100644
--- a/fdts/stm32mp251.dtsi
+++ b/fdts/stm32mp251.dtsi
@@ -97,6 +97,32 @@
resets = <&rcc USART2_R>;
status = "disabled";
};
+
+ sdmmc1: mmc@48220000 {
+ compatible = "st,stm32mp25-sdmmc2", "arm,pl18x", "arm,primecell";
+ arm,primecell-periphid = <0x00353180>;
+ reg = <0x48220000 0x400>, <0x44230400 0x8>;
+ clocks = <&rcc CK_KER_SDMMC1>;
+ clock-names = "apb_pclk";
+ resets = <&rcc SDMMC1_R>;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ max-frequency = <120000000>;
+ status = "disabled";
+ };
+
+ sdmmc2: mmc@48230000 {
+ compatible = "st,stm32mp25-sdmmc2", "arm,pl18x", "arm,primecell";
+ arm,primecell-periphid = <0x00353180>;
+ reg = <0x48230000 0x400>, <0x44230800 0x8>;
+ clocks = <&rcc CK_KER_SDMMC2>;
+ clock-names = "apb_pclk";
+ resets = <&rcc SDMMC2_R>;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ max-frequency = <120000000>;
+ status = "disabled";
+ };
};
bsec: efuse@44000000 {
@@ -120,6 +146,9 @@
nand2_otp: otp20@50 {
reg = <0x50 0x4>;
};
+ rev_otp@198 {
+ reg = <0x198 0x4>;
+ };
package_otp: package-otp@1e8 {
reg = <0x1e8 0x1>;
};
@@ -176,7 +205,6 @@
#size-cells = <1>;
compatible = "st,stm32mp257-pinctrl";
ranges = <0 0x44240000 0xa0400>;
- pins-are-numbered;
gpioa: gpio@44240000 {
gpio-controller;
@@ -305,7 +333,6 @@
#size-cells = <1>;
compatible = "st,stm32mp257-z-pinctrl";
ranges = <0 0x46200000 0x400>;
- pins-are-numbered;
gpioz: gpio@46200000 {
gpio-controller;
diff --git a/fdts/stm32mp257f-ev1-ca35tdcid-fw-config.dtsi b/fdts/stm32mp257f-ev1-ca35tdcid-fw-config.dtsi
new file mode 100644
index 0000000..e41c6b9
--- /dev/null
+++ b/fdts/stm32mp257f-ev1-ca35tdcid-fw-config.dtsi
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2024 - All Rights Reserved
+ */
+
+/*
+ * STM32MP25 tf-a firmware config
+ * Project : open
+ * Generated by XLmx tool version 2.2 - 2/27/2024 11:46:17 AM
+ */
+
+/ {
+ dtb-registry {
+ tos_fw {
+ load-address = <0x0 0x82000000>;
+ max-size = <0x2000000>;
+ };
+ };
+};
diff --git a/fdts/stm32mp257f-ev1-ca35tdcid-rcc.dtsi b/fdts/stm32mp257f-ev1-ca35tdcid-rcc.dtsi
new file mode 100644
index 0000000..3e84df5
--- /dev/null
+++ b/fdts/stm32mp257f-ev1-ca35tdcid-rcc.dtsi
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2024 - All Rights Reserved
+ * Author: Loic Pallardy loic.pallardy@foss.st.com for STMicroelectronics.
+ */
+
+/*
+ * STM32MP25 Clock tree device tree configuration
+ * Project : open
+ * Generated by XLmx tool version 2.2 - 2/27/2024 11:46:16 AM
+ */
+
+&clk_hse {
+ clock-frequency = <40000000>;
+};
+
+&clk_hsi {
+ clock-frequency = <64000000>;
+};
+
+&clk_lse {
+ clock-frequency = <32768>;
+};
+
+&clk_lsi {
+ clock-frequency = <32000>;
+};
+
+&clk_msi {
+ clock-frequency = <16000000>;
+};
+
+&rcc {
+ st,busclk = <
+ DIV_CFG(DIV_LSMCU, 1)
+ DIV_CFG(DIV_APB1, 0)
+ DIV_CFG(DIV_APB2, 0)
+ DIV_CFG(DIV_APB3, 0)
+ DIV_CFG(DIV_APB4, 0)
+ DIV_CFG(DIV_APBDBG, 0)
+ >;
+
+ st,flexgen = <
+ FLEXGEN_CFG(0, XBAR_SRC_PLL4, 0, 2)
+ FLEXGEN_CFG(1, XBAR_SRC_PLL4, 0, 5)
+ FLEXGEN_CFG(2, XBAR_SRC_PLL4, 0, 1)
+ FLEXGEN_CFG(4, XBAR_SRC_PLL4, 0, 3)
+ FLEXGEN_CFG(5, XBAR_SRC_PLL4, 0, 2)
+ FLEXGEN_CFG(8, XBAR_SRC_HSI_KER, 0, 0)
+ FLEXGEN_CFG(48, XBAR_SRC_PLL5, 0, 3)
+ FLEXGEN_CFG(51, XBAR_SRC_PLL4, 0, 5)
+ FLEXGEN_CFG(52, XBAR_SRC_PLL4, 0, 5)
+ FLEXGEN_CFG(58, XBAR_SRC_HSE, 0, 1)
+ FLEXGEN_CFG(63, XBAR_SRC_PLL4, 0, 2)
+ >;
+
+ st,kerclk = <
+ MUX_CFG(MUX_USB2PHY1, MUX_USB2PHY1_FLEX57)
+ MUX_CFG(MUX_USB2PHY2, MUX_USB2PHY2_FLEX58)
+ >;
+
+ pll1: st,pll-1 {
+ st,pll = <&pll1_cfg_1200Mhz>;
+
+ pll1_cfg_1200Mhz: pll1-cfg-1200Mhz {
+ cfg = <30 1 1 1>;
+ src = <MUX_CFG(MUX_MUXSEL5, MUXSEL_HSE)>;
+ };
+ };
+
+ pll2: st,pll-2 {
+ st,pll = <&pll2_cfg_600Mhz>;
+
+ pll2_cfg_600Mhz: pll2-cfg-600Mhz {
+ cfg = <30 1 1 2>;
+ src = <MUX_CFG(MUX_MUXSEL6, MUXSEL_HSE)>;
+ };
+ };
+
+ pll4: st,pll-4 {
+ st,pll = <&pll4_cfg_1200Mhz>;
+
+ pll4_cfg_1200Mhz: pll4-cfg-1200Mhz {
+ cfg = <30 1 1 1>;
+ src = <MUX_CFG(MUX_MUXSEL0, MUXSEL_HSE)>;
+ };
+ };
+
+ pll5: st,pll-5 {
+ st,pll = <&pll5_cfg_532Mhz>;
+
+ pll5_cfg_532Mhz: pll5-cfg-532Mhz {
+ cfg = <133 5 1 2>;
+ src = <MUX_CFG(MUX_MUXSEL1, MUXSEL_HSE)>;
+ };
+ };
+};
diff --git a/fdts/stm32mp257f-ev1-fw-config.dts b/fdts/stm32mp257f-ev1-fw-config.dts
new file mode 100644
index 0000000..9424f49
--- /dev/null
+++ b/fdts/stm32mp257f-ev1-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+/*
+ * Copyright (c) 2024, STMicroelectronics - All Rights Reserved
+ */
+
+#include "stm32mp25-fw-config.dtsi"
+#include "stm32mp257f-ev1-ca35tdcid-fw-config.dtsi"
diff --git a/fdts/stm32mp257f-ev1.dts b/fdts/stm32mp257f-ev1.dts
index 09e83d8..6df1b30 100644
--- a/fdts/stm32mp257f-ev1.dts
+++ b/fdts/stm32mp257f-ev1.dts
@@ -6,8 +6,10 @@
/dts-v1/;
+#include <dt-bindings/clock/stm32mp25-clksrc.h>
#include "stm32mp257.dtsi"
#include "stm32mp25xf.dtsi"
+#include "stm32mp257f-ev1-ca35tdcid-rcc.dtsi"
#include "stm32mp25-pinctrl.dtsi"
#include "stm32mp25xxai-pinctrl.dtsi"
@@ -35,6 +37,25 @@
};
};
+&sdmmc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc1_b4_pins_a>;
+ st,neg-edge;
+ bus-width = <4>;
+ status = "okay";
+};
+
+&sdmmc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>;
+ non-removable;
+ no-sd;
+ no-sdio;
+ st,neg-edge;
+ bus-width = <8>;
+ status = "okay";
+};
+
&usart2 {
pinctrl-names = "default";
pinctrl-0 = <&usart2_pins_a>;
diff --git a/fdts/tbbr_cot_descriptors.dtsi b/fdts/tbbr_cot_descriptors.dtsi
index d11e2be..b3c0ca7 100644
--- a/fdts/tbbr_cot_descriptors.dtsi
+++ b/fdts/tbbr_cot_descriptors.dtsi
@@ -4,7 +4,12 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#if USE_TBBR_DEFS
#include <tools_share/tbbr_oid.h>
+#else
+#include <platform_oid.h>
+#endif
+
#include <common/tbbr/tbbr_img_def.h>
#include <common/nv_cntr_ids.h>
@@ -15,7 +20,7 @@
trusted_boot_fw_cert: trusted_boot_fw_cert {
root-certificate;
image-id =<TRUSTED_BOOT_FW_CERT_ID>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
tb_fw_hash: tb_fw_hash {
oid = TRUSTED_BOOT_FW_HASH_OID;
@@ -34,7 +39,7 @@
trusted_key_cert: trusted_key_cert {
root-certificate;
image-id = <TRUSTED_KEY_CERT_ID>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
trusted_world_pk: trusted_world_pk {
oid = TRUSTED_WORLD_PK_OID;
@@ -48,7 +53,7 @@
image-id = <SCP_FW_KEY_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&trusted_world_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
scp_fw_content_pk: scp_fw_content_pk {
oid = SCP_FW_CONTENT_CERT_PK_OID;
@@ -59,7 +64,7 @@
image-id = <SCP_FW_CONTENT_CERT_ID>;
parent = <&scp_fw_key_cert>;
signing-key = <&scp_fw_content_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
scp_fw_hash: scp_fw_hash {
oid = SCP_FW_HASH_OID;
@@ -70,7 +75,7 @@
image-id = <SOC_FW_KEY_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&trusted_world_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
soc_fw_content_pk: soc_fw_content_pk {
oid = SOC_FW_CONTENT_CERT_PK_OID;
};
@@ -80,7 +85,7 @@
image-id = <SOC_FW_CONTENT_CERT_ID>;
parent = <&soc_fw_key_cert>;
signing-key = <&soc_fw_content_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
soc_fw_hash: soc_fw_hash {
oid = SOC_AP_FW_HASH_OID;
@@ -94,7 +99,7 @@
image-id = <TRUSTED_OS_FW_KEY_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&trusted_world_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
tos_fw_content_pk: tos_fw_content_pk {
oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID;
@@ -105,7 +110,7 @@
image-id = <TRUSTED_OS_FW_CONTENT_CERT_ID>;
parent = <&trusted_os_fw_key_cert>;
signing-key = <&tos_fw_content_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
tos_fw_hash: tos_fw_hash {
oid = TRUSTED_OS_FW_HASH_OID;
@@ -125,7 +130,7 @@
image-id = <NON_TRUSTED_FW_KEY_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&non_trusted_world_pk>;
- antirollback-counter = <&non_trusted_nv_counter>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
nt_fw_content_pk: nt_fw_content_pk {
oid = NON_TRUSTED_FW_CONTENT_CERT_PK_OID;
@@ -136,7 +141,7 @@
image-id = <NON_TRUSTED_FW_CONTENT_CERT_ID>;
parent = <&non_trusted_fw_key_cert>;
signing-key = <&nt_fw_content_pk>;
- antirollback-counter = <&non_trusted_nv_counter>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
nt_world_bl_hash: nt_world_bl_hash {
oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID;
@@ -151,7 +156,7 @@
image-id = <SIP_SP_CONTENT_CERT_ID>;
parent = <&trusted_key_cert>;
signing-key = <&trusted_world_pk>;
- antirollback-counter = <&trusted_nv_counter>;
+ antirollback-counter = <&trusted_nv_ctr>;
sp_pkg1_hash: sp_pkg1_hash {
oid = SP_PKG1_HASH_OID;
@@ -302,12 +307,12 @@
#address-cells = <1>;
#size-cells = <0>;
- trusted_nv_counter: trusted_nv_counter {
+ trusted_nv_ctr: trusted_nv_ctr {
id = <TRUSTED_NV_CTR_ID>;
oid = TRUSTED_FW_NVCOUNTER_OID;
};
- non_trusted_nv_counter: non_trusted_nv_counter {
+ non_trusted_nv_ctr: non_trusted_nv_ctr {
id = <NON_TRUSTED_NV_CTR_ID>;
oid = NON_TRUSTED_FW_NVCOUNTER_OID;
};
diff --git a/fdts/tc-base.dtsi b/fdts/tc-base.dtsi
index fc6fe78..be0a9f6 100644
--- a/fdts/tc-base.dtsi
+++ b/fdts/tc-base.dtsi
@@ -437,9 +437,9 @@
};
- ethernet: ethernet@18000000 {
- reg = <0x0 0x18000000 0x0 0x10000>;
- interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH 0>;
+ ethernet: ethernet@ETHERNET_ADDR {
+ reg = <0x0 ADDRESSIFY(ETHERNET_ADDR) 0x0 0x10000>;
+ interrupts = <GIC_SPI ETHERNET_INT IRQ_TYPE_LEVEL_HIGH 0>;
reg-io-width = <2>;
smsc,irq-push-pull;
@@ -452,10 +452,9 @@
clock-output-names = "bp:clock24mhz";
};
-
- sysreg: sysreg@1c010000 {
+ sysreg: sysreg@SYS_REGS_ADDR {
compatible = "arm,vexpress-sysreg";
- reg = <0x0 0x001c010000 0x0 0x1000>;
+ reg = <0x0 ADDRESSIFY(SYS_REGS_ADDR) 0x0 0x1000>;
gpio-controller;
#gpio-cells = <2>;
};
@@ -468,11 +467,11 @@
regulator-always-on;
};
- mmci: mmci@1c050000 {
+ mmci: mmci@MMC_ADDR {
compatible = "arm,pl180", "arm,primecell";
- reg = <0x0 0x001c050000 0x0 0x1000>;
- interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH 0>;
+ reg = <0x0 ADDRESSIFY(MMC_ADDR) 0x0 0x1000>;
+ interrupts = <GIC_SPI MMC_INT_0 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI MMC_INT_1 IRQ_TYPE_LEVEL_HIGH 0>;
wp-gpios = <&sysreg 1 0>;
bus-width = <4>;
max-frequency = <25000000>;
@@ -496,10 +495,6 @@
gpu: gpu@2d000000 {
compatible = "arm,mali-midgard";
reg = <0x0 0x2d000000 0x0 0x200000>;
- interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH 0>,
- <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH 0>;
- interrupt-names = "JOB", "MMU", "GPU";
clocks = <&gpu_core_clk>;
clock-names = "shadercores";
#if TC_SCMI_PD_CTRL_EN
diff --git a/fdts/tc-fpga.dtsi b/fdts/tc-fpga.dtsi
index 73f4743..08b9ae5 100644
--- a/fdts/tc-fpga.dtsi
+++ b/fdts/tc-fpga.dtsi
@@ -25,12 +25,12 @@
stdout-path = "serial0:38400n8";
};
- ethernet: ethernet@18000000 {
+ ethernet: ethernet@ETHERNET_ADDR {
compatible = "smsc,lan9115";
phy-mode = "mii";
};
- mmci: mmci@1c050000 {
+ mmci: mmci@MMC_ADDR {
non-removable;
};
};
diff --git a/fdts/tc-fvp.dtsi b/fdts/tc-fvp.dtsi
index 1e14f0b..f57e21d 100644
--- a/fdts/tc-fvp.dtsi
+++ b/fdts/tc-fvp.dtsi
@@ -43,26 +43,26 @@
stdout-path = "serial0:115200n8";
};
- ethernet: ethernet@18000000 {
+ ethernet: ethernet@ETHERNET_ADDR {
compatible = "smsc,lan91c111";
};
- mmci: mmci@1c050000 {
+ mmci: mmci@MMC_ADDR {
cd-gpios = <&sysreg 0 0>;
};
- rtc@1c170000 {
+ rtc@RTC_ADDR {
compatible = "arm,pl031", "arm,primecell";
- reg = <0x0 0x1C170000 0x0 0x1000>;
- interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH 0>;
+ reg = <0x0 ADDRESSIFY(RTC_ADDR) 0x0 0x1000>;
+ interrupts = <GIC_SPI RTC_INT IRQ_TYPE_LEVEL_HIGH 0>;
clocks = <&soc_refclk>;
clock-names = "apb_pclk";
};
- kmi@1c060000 {
+ kmi@KMI_0_ADDR {
compatible = "arm,pl050", "arm,primecell";
- reg = <0x0 0x001c060000 0x0 0x1000>;
- interrupts = <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH 0>;
+ reg = <0x0 ADDRESSIFY(KMI_0_ADDR) 0x0 0x1000>;
+ interrupts = <GIC_SPI KMI_0_INT IRQ_TYPE_LEVEL_HIGH 0>;
clocks = <&bp_clock24mhz>, <&bp_clock24mhz>;
clock-names = "KMIREFCLK", "apb_pclk";
};
@@ -75,10 +75,10 @@
clock-names = "KMIREFCLK", "apb_pclk";
};
- virtio_block@1c130000 {
+ virtio_block@VIRTIO_BLOCK_ADDR {
compatible = "virtio,mmio";
- reg = <0x0 0x1c130000 0x0 0x200>;
+ reg = <0x0 ADDRESSIFY(VIRTIO_BLOCK_ADDR) 0x0 0x200>;
/* spec lists this wrong */
- interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupts = <GIC_SPI VIRTIO_BLOCK_INT IRQ_TYPE_LEVEL_HIGH 0>;
};
};
diff --git a/fdts/tc2.dts b/fdts/tc2.dts
index ae37ce3..c492274 100644
--- a/fdts/tc2.dts
+++ b/fdts/tc2.dts
@@ -41,6 +41,26 @@
#define DPU_ADDR 2cc00000
#define DPU_IRQ 69
+#define ETHERNET_ADDR 18000000
+#define ETHERNET_INT 109
+
+#define SYS_REGS_ADDR 1c010000
+
+#define MMC_ADDR 1c050000
+#define MMC_INT_0 107
+#define MMC_INT_1 108
+
+#define RTC_ADDR 1c170000
+#define RTC_INT 100
+
+#define KMI_0_ADDR 1c060000
+#define KMI_0_INT 197
+#define KMI_1_ADDR 1c070000
+#define KMI_1_INT 103
+
+#define VIRTIO_BLOCK_ADDR 1c130000
+#define VIRTIO_BLOCK_INT 204
+
#include "tc-common.dtsi"
#if TARGET_FLAVOUR_FVP
#include "tc-fvp.dtsi"
@@ -271,6 +291,10 @@
};
gpu: gpu@2d000000 {
+ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "JOB", "MMU", "GPU";
iommus = <&smmu_700 0x200>;
};
};
diff --git a/fdts/tc3-4-base.dtsi b/fdts/tc3-4-base.dtsi
new file mode 100644
index 0000000..169d68f
--- /dev/null
+++ b/fdts/tc3-4-base.dtsi
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#define LIT_CAPACITY 239
+#define MID_CAPACITY 686
+#define BIG_CAPACITY 1024
+
+#define MHU_TX_COMPAT "arm,mhuv3"
+#define MHU_TX_INT_NAME ""
+
+#define MHU_RX_COMPAT "arm,mhuv3"
+#define MHU_OFFSET 0x10000
+#define MHU_MBOX_CELLS 3
+#define MHU_RX_INT_NUM 300
+#define MHU_RX_INT_NAME "combined-mbx"
+
+#define MPAM_ADDR 0x0 0x5f010000 /* 0x5f01_0000 */
+#define UARTCLK_FREQ 3750000
+
+#if TARGET_FLAVOUR_FVP
+#define DPU_ADDR 4000000000
+#define DPU_IRQ 579
+#elif TARGET_FLAVOUR_FPGA
+#define DPU_ADDR 2cc00000
+#define DPU_IRQ 69
+#endif
+#include "tc-base.dtsi"
+
+/ {
+ cpus {
+ CPU2:cpu@200 {
+ clocks = <&scmi_dvfs 1>;
+ capacity-dmips-mhz = <MID_CAPACITY>;
+ };
+
+ CPU3:cpu@300 {
+ clocks = <&scmi_dvfs 1>;
+ capacity-dmips-mhz = <MID_CAPACITY>;
+ };
+
+ CPU6:cpu@600 {
+ clocks = <&scmi_dvfs 2>;
+ capacity-dmips-mhz = <BIG_CAPACITY>;
+ };
+
+ CPU7:cpu@700 {
+ clocks = <&scmi_dvfs 2>;
+ capacity-dmips-mhz = <BIG_CAPACITY>;
+ };
+ };
+
+ gic: interrupt-controller@GIC_CTRL_ADDR {
+ ppi-partitions {
+ ppi_partition_little: interrupt-partition-0 {
+ affinity = <&CPU0>, <&CPU1>;
+ };
+
+ ppi_partition_mid: interrupt-partition-1 {
+ affinity = <&CPU2>, <&CPU3>, <&CPU4>, <&CPU5>;
+ };
+
+ ppi_partition_big: interrupt-partition-2 {
+ affinity = <&CPU6>, <&CPU7>;
+ };
+ };
+ };
+
+ sram: sram@6000000 {
+ cpu_scp_scmi_p2a: scp-shmem@80 {
+ compatible = "arm,scmi-shmem";
+ reg = <0x80 0x80>;
+ };
+ };
+
+ firmware {
+ scmi {
+ mboxes = <&mbox_db_tx 0 0 0 &mbox_db_rx 0 0 0 &mbox_db_rx 0 0 1>;
+ shmem = <&cpu_scp_scmi_a2p &cpu_scp_scmi_p2a>;
+ };
+ };
+};
diff --git a/fdts/tc3.dts b/fdts/tc3.dts
index 58c8edc..ffe3b6d 100644
--- a/fdts/tc3.dts
+++ b/fdts/tc3.dts
@@ -10,35 +10,32 @@
#include <dt-bindings/interrupt-controller/irq.h>
#include <platform_def.h>
-#define LIT_CAPACITY 239
-#define MID_CAPACITY 686
-#define BIG_CAPACITY 1024
-
#define MHU_TX_ADDR 46040000 /* hex */
-#define MHU_TX_COMPAT "arm,mhuv3"
-#define MHU_TX_INT_NAME ""
-
#define MHU_RX_ADDR 46140000 /* hex */
-#define MHU_RX_COMPAT "arm,mhuv3"
-#define MHU_OFFSET 0x10000
-#define MHU_MBOX_CELLS 3
-#define MHU_RX_INT_NUM 300
-#define MHU_RX_INT_NAME "combined-mbx"
#define LIT_CPU_PMU_COMPATIBLE "arm,cortex-a520-pmu"
#define MID_CPU_PMU_COMPATIBLE "arm,cortex-a725-pmu"
#define BIG_CPU_PMU_COMPATIBLE "arm,cortex-x925-pmu"
-#define MPAM_ADDR 0x0 0x5f010000 /* 0x5f01_0000 */
-#define UARTCLK_FREQ 3750000
+#define ETHERNET_ADDR 18000000
+#define ETHERNET_INT 109
-#if TARGET_FLAVOUR_FVP
-#define DPU_ADDR 4000000000
-#define DPU_IRQ 579
-#elif TARGET_FLAVOUR_FPGA
-#define DPU_ADDR 2cc00000
-#define DPU_IRQ 69
-#endif
+#define SYS_REGS_ADDR 1c010000
+
+#define MMC_ADDR 1c050000
+#define MMC_INT_0 107
+#define MMC_INT_1 108
+
+#define RTC_ADDR 1c170000
+#define RTC_INT 100
+
+#define KMI_0_ADDR 1c060000
+#define KMI_0_INT 197
+#define KMI_1_ADDR 1c070000
+#define KMI_1_INT 103
+
+#define VIRTIO_BLOCK_ADDR 1c130000
+#define VIRTIO_BLOCK_INT 204
#include "tc-common.dtsi"
#if TARGET_FLAVOUR_FVP
@@ -46,31 +43,9 @@
#else
#include "tc-fpga.dtsi"
#endif /* TARGET_FLAVOUR_FVP */
-#include "tc-base.dtsi"
+#include "tc3-4-base.dtsi"
/ {
- cpus {
- CPU2:cpu@200 {
- clocks = <&scmi_dvfs 1>;
- capacity-dmips-mhz = <MID_CAPACITY>;
- };
-
- CPU3:cpu@300 {
- clocks = <&scmi_dvfs 1>;
- capacity-dmips-mhz = <MID_CAPACITY>;
- };
-
- CPU6:cpu@600 {
- clocks = <&scmi_dvfs 2>;
- capacity-dmips-mhz = <BIG_CAPACITY>;
- };
-
- CPU7:cpu@700 {
- clocks = <&scmi_dvfs 2>;
- capacity-dmips-mhz = <BIG_CAPACITY>;
- };
- };
-
cs-pmu@0 {
compatible = "arm,coresight-pmu";
reg = <0x0 MCN_PMU_ADDR(0) 0x0 0xffc>;
@@ -109,36 +84,6 @@
reg = <0x0 0x4f000000 0x0 0x4000000>;
};
- sram: sram@6000000 {
- cpu_scp_scmi_p2a: scp-shmem@80 {
- compatible = "arm,scmi-shmem";
- reg = <0x80 0x80>;
- };
- };
-
- firmware {
- scmi {
- mboxes = <&mbox_db_tx 0 0 0 &mbox_db_rx 0 0 0 &mbox_db_rx 0 0 1>;
- shmem = <&cpu_scp_scmi_a2p &cpu_scp_scmi_p2a>;
- };
- };
-
- gic: interrupt-controller@GIC_CTRL_ADDR {
- ppi-partitions {
- ppi_partition_little: interrupt-partition-0 {
- affinity = <&CPU0>, <&CPU1>;
- };
-
- ppi_partition_mid: interrupt-partition-1 {
- affinity = <&CPU2>, <&CPU3>, <&CPU4>, <&CPU5>;
- };
-
- ppi_partition_big: interrupt-partition-2 {
- affinity = <&CPU6>, <&CPU7>;
- };
- };
- };
-
#if TARGET_FLAVOUR_FVP
smmu_700: iommu@3f000000 {
status = "okay";
@@ -165,6 +110,10 @@
};
gpu: gpu@2d000000 {
+ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "JOB", "MMU", "GPU";
#if TARGET_FLAVOUR_FVP
iommus = <&smmu_700 0x200>;
#endif
diff --git a/fdts/tc4.dts b/fdts/tc4.dts
new file mode 100644
index 0000000..135d30a
--- /dev/null
+++ b/fdts/tc4.dts
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <platform_def.h>
+
+#define MHU_TX_ADDR 46240000 /* hex */
+#define MHU_RX_ADDR 46250000 /* hex */
+
+#define LIT_CPU_PMU_COMPATIBLE "arm,armv8-pmuv3"
+#define MID_CPU_PMU_COMPATIBLE "arm,armv8-pmuv3"
+#define BIG_CPU_PMU_COMPATIBLE "arm,armv8-pmuv3"
+
+#define ETHERNET_ADDR 64000000
+#define ETHERNET_INT 799
+
+#define SYS_REGS_ADDR 60080000
+
+#define MMC_ADDR 600b0000
+#define MMC_INT_0 778
+#define MMC_INT_1 779
+
+#define RTC_ADDR 600a0000
+#define RTC_INT 777
+
+#define KMI_0_ADDR 60100000
+#define KMI_0_INT 784
+#define KMI_1_ADDR 60110000
+#define KMI_1_INT 785
+
+#define VIRTIO_BLOCK_ADDR 60020000
+#define VIRTIO_BLOCK_INT 769
+
+#include "tc-common.dtsi"
+#if TARGET_FLAVOUR_FVP
+#include "tc-fvp.dtsi"
+#else
+#include "tc-fpga.dtsi"
+#endif /* TARGET_FLAVOUR_FVP */
+#include "tc3-4-base.dtsi"
+
+/ {
+ smmu_700: iommu@3f000000 {
+ status = "okay";
+ };
+
+ smmu_700_dpu: iommu@4002a00000 {
+ status = "okay";
+ };
+
+ dp0: display@DPU_ADDR {
+ iommus = <&smmu_700_dpu 0x000>, <&smmu_700_dpu 0x100>,
+ <&smmu_700_dpu 0x200>, <&smmu_700_dpu 0x600>;
+ };
+
+ gpu: gpu@2d000000 {
+ interrupts = <GIC_SPI 242 IRQ_TYPE_LEVEL_HIGH 0>;
+ interrupt-names = "IRQAW";
+ iommus = <&smmu_700 0x200>;
+ };
+};
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 52ed2b9..d8ad881 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -24,6 +24,9 @@
#define MIDR_PN_MASK U(0xfff)
#define MIDR_PN_SHIFT U(0x4)
+/* Extracts the CPU part number from MIDR for checking CPU match */
+#define EXTRACT_PARTNUM(x) ((x >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
+
/*******************************************************************************
* MPIDR macros
******************************************************************************/
diff --git a/include/common/feat_detect.h b/include/common/feat_detect.h
index 788dfb3..b85e1ce 100644
--- a/include/common/feat_detect.h
+++ b/include/common/feat_detect.h
@@ -11,8 +11,9 @@
void detect_arch_features(void);
/* Macro Definitions */
-#define FEAT_STATE_DISABLED 0
-#define FEAT_STATE_ALWAYS 1
-#define FEAT_STATE_CHECK 2
+#define FEAT_STATE_DISABLED 0
+#define FEAT_STATE_ALWAYS 1
+#define FEAT_STATE_CHECK 2
+#define FEAT_STATE_CHECK_ASYMMETRIC 3
#endif /* FEAT_DETECT_H */
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index ca46eb1..0e6137d 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.h
@@ -341,7 +341,7 @@
/* GITS_CTLR bit definitions */
#define GITS_CTLR_ENABLED_BIT BIT_32(0)
-#define GITS_CTLR_QUIESCENT_BIT BIT_32(1)
+#define GITS_CTLR_QUIESCENT_BIT BIT_32(31)
#define GITS_TYPER_VSGI BIT_64(39)
diff --git a/include/drivers/auth/mbedtls/mbedtls_config-3.h b/include/drivers/auth/mbedtls/mbedtls_config-3.h
index 37a9288..6ed9397 100644
--- a/include/drivers/auth/mbedtls/mbedtls_config-3.h
+++ b/include/drivers/auth/mbedtls/mbedtls_config-3.h
@@ -73,23 +73,17 @@
#define MBEDTLS_X509_RSASSA_PSS_SUPPORT
#endif
-/* The library does not currently support enabling SHA-256 without SHA-224. */
-#define MBEDTLS_SHA224_C
-#define MBEDTLS_SHA256_C
-/*
- * If either Trusted Boot or Measured Boot require a stronger algorithm than
- * SHA-256, pull in SHA-512 support. Library currently needs to have SHA_384
- * support when enabling SHA-512.
- */
-#if (TF_MBEDTLS_HASH_ALG_ID != TF_MBEDTLS_SHA256) /* TBB hash algo */
-#define MBEDTLS_SHA384_C
-#define MBEDTLS_SHA512_C
-#else
- /* TBB uses SHA-256, what about measured boot? */
-#if defined(TF_MBEDTLS_MBOOT_USE_SHA512)
-#define MBEDTLS_SHA384_C
-#define MBEDTLS_SHA512_C
+/* Enable hash algorithms based on TBB or Measured Boot */
+#if (TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA256) || defined(TF_MBEDTLS_MBOOT_USE_SHA256)
+ #define MBEDTLS_SHA256_C
#endif
+
+#if (TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA384) || defined(TF_MBEDTLS_MBOOT_USE_SHA384)
+ #define MBEDTLS_SHA384_C
+#endif
+
+#if (TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA512) || defined(TF_MBEDTLS_MBOOT_USE_SHA512)
+ #define MBEDTLS_SHA512_C
#endif
#define MBEDTLS_VERSION_C
@@ -104,7 +98,9 @@
#endif
/* MPI / BIGNUM options */
-#define MBEDTLS_MPI_WINDOW_SIZE 2
+
+/* Note: Lower numbers trade longer execution time for less RAM allocation */
+#define MBEDTLS_MPI_WINDOW_SIZE 1
#if TF_MBEDTLS_USE_RSA
#if TF_MBEDTLS_KEY_SIZE <= 2048
diff --git a/include/drivers/nxp/clk/s32cc/s32cc-clk-ids.h b/include/drivers/nxp/clk/s32cc/s32cc-clk-ids.h
index 633f173..de633ae 100644
--- a/include/drivers/nxp/clk/s32cc/s32cc-clk-ids.h
+++ b/include/drivers/nxp/clk/s32cc/s32cc-clk-ids.h
@@ -78,4 +78,21 @@
#define S32CC_CLK_A53_CORE_DIV2 S32CC_ARCH_CLK(4)
#define S32CC_CLK_A53_CORE_DIV10 S32CC_ARCH_CLK(5)
+/* XBAR clock*/
+#define S32CC_CLK_MC_CGM0_MUX0 S32CC_ARCH_CLK(6)
+#define S32CC_CLK_XBAR_2X S32CC_ARCH_CLK(7)
+#define S32CC_CLK_XBAR S32CC_ARCH_CLK(8)
+#define S32CC_CLK_XBAR_DIV2 S32CC_ARCH_CLK(9)
+#define S32CC_CLK_XBAR_DIV3 S32CC_ARCH_CLK(10)
+#define S32CC_CLK_XBAR_DIV4 S32CC_ARCH_CLK(11)
+#define S32CC_CLK_XBAR_DIV6 S32CC_ARCH_CLK(12)
+
+/* Periph PLL */
+#define S32CC_CLK_PERIPH_PLL_MUX S32CC_ARCH_CLK(13)
+#define S32CC_CLK_PERIPH_PLL_VCO S32CC_ARCH_CLK(14)
+
+#define S32CC_CLK_MC_CGM0_MUX8 S32CC_ARCH_CLK(15)
+#define S32CC_CLK_LINFLEX_BAUD S32CC_ARCH_CLK(16)
+#define S32CC_CLK_LINFLEX S32CC_ARCH_CLK(17)
+
#endif /* S32CC_CLK_IDS_H */
diff --git a/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h b/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h
index 41fc6f4..a6d58cc 100644
--- a/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h
+++ b/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h
@@ -17,6 +17,8 @@
s32cc_clk_t,
s32cc_pll_t,
s32cc_pll_out_div_t,
+ s32cc_dfs_t,
+ s32cc_dfs_div_t,
s32cc_clkmux_t,
s32cc_shared_clkmux_t,
s32cc_fixed_div_t,
@@ -27,6 +29,9 @@
S32CC_FXOSC,
S32CC_SIRC,
S32CC_ARM_PLL,
+ S32CC_ARM_DFS,
+ S32CC_PERIPH_PLL,
+ S32CC_CGM0,
S32CC_CGM1,
};
@@ -122,6 +127,38 @@
.index = (INDEX), \
}
+struct s32cc_dfs {
+ struct s32cc_clk_obj desc;
+ struct s32cc_clk_obj *parent;
+ enum s32cc_clk_source instance;
+ uintptr_t base;
+};
+
+#define S32CC_DFS_INIT(PARENT, INSTANCE) \
+{ \
+ .desc = { \
+ .type = s32cc_dfs_t, \
+ }, \
+ .parent = &(PARENT).desc, \
+ .instance = (INSTANCE), \
+}
+
+struct s32cc_dfs_div {
+ struct s32cc_clk_obj desc;
+ struct s32cc_clk_obj *parent;
+ uint32_t index;
+ unsigned long freq;
+};
+
+#define S32CC_DFS_DIV_INIT(PARENT, INDEX) \
+{ \
+ .desc = { \
+ .type = s32cc_dfs_div_t, \
+ }, \
+ .parent = &(PARENT).desc, \
+ .index = (INDEX), \
+}
+
struct s32cc_fixed_div {
struct s32cc_clk_obj desc;
struct s32cc_clk_obj *parent;
@@ -151,22 +188,26 @@
size_t n_clks;
};
-#define S32CC_FREQ_MODULE(PARENT_MODULE, MIN_F, MAX_F) \
-{ \
- .desc = { \
- .type = s32cc_clk_t, \
- }, \
- .module = &(PARENT_MODULE).desc, \
- .min_freq = (MIN_F), \
- .max_freq = (MAX_F), \
+#define S32CC_FREQ_CLK(PARENT_MODULE, PARENT, MIN_F, MAX_F) \
+{ \
+ .desc = { \
+ .type = s32cc_clk_t, \
+ }, \
+ .pclock = (PARENT), \
+ .module = (PARENT_MODULE), \
+ .min_freq = (MIN_F), \
+ .max_freq = (MAX_F), \
}
#define S32CC_FREQ_MODULE_CLK(PARENT_MODULE, MIN_F, MAX_F) \
- S32CC_FREQ_MODULE(PARENT_MODULE, MIN_F, MAX_F)
+ S32CC_FREQ_CLK(&(PARENT_MODULE).desc, NULL, MIN_F, MAX_F)
#define S32CC_MODULE_CLK(PARENT_MODULE) \
S32CC_FREQ_MODULE_CLK(PARENT_MODULE, 0, 0)
+#define S32CC_CHILD_CLK(PARENT, MIN_F, MAX_F) \
+ S32CC_FREQ_CLK(NULL, &(PARENT), MIN_F, MAX_F)
+
static inline struct s32cc_osc *s32cc_obj2osc(const struct s32cc_clk_obj *mod)
{
uintptr_t osc_addr;
@@ -237,4 +278,20 @@
return (struct s32cc_fixed_div *)fdiv_addr;
}
+static inline struct s32cc_dfs *s32cc_obj2dfs(const struct s32cc_clk_obj *mod)
+{
+ uintptr_t dfs_addr;
+
+ dfs_addr = ((uintptr_t)mod) - offsetof(struct s32cc_dfs, desc);
+ return (struct s32cc_dfs *)dfs_addr;
+}
+
+static inline struct s32cc_dfs_div *s32cc_obj2dfsdiv(const struct s32cc_clk_obj *mod)
+{
+ uintptr_t dfs_div_addr;
+
+ dfs_div_addr = ((uintptr_t)mod) - offsetof(struct s32cc_dfs_div, desc);
+ return (struct s32cc_dfs_div *)dfs_div_addr;
+}
+
#endif /* S32CC_CLK_MODULES_H */
diff --git a/include/drivers/st/stm32mp2_ddr_helpers.h b/include/drivers/st/stm32mp2_ddr_helpers.h
new file mode 100644
index 0000000..069fb83
--- /dev/null
+++ b/include/drivers/st/stm32mp2_ddr_helpers.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2024, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP2_DDR_HELPERS_H
+#define STM32MP2_DDR_HELPERS_H
+
+void ddr_sub_system_clk_init(void);
+
+#endif /* STM32MP2_DDR_HELPERS_H */
diff --git a/include/drivers/st/stm32mp2_pwr.h b/include/drivers/st/stm32mp2_pwr.h
new file mode 100644
index 0000000..356399a
--- /dev/null
+++ b/include/drivers/st/stm32mp2_pwr.h
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 2018-2024, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP2_PWR_H
+#define STM32MP2_PWR_H
+
+#include <lib/utils_def.h>
+
+#define PWR_CR1 U(0x00)
+#define PWR_CR2 U(0x04)
+#define PWR_CR3 U(0x08)
+#define PWR_CR4 U(0x0C)
+#define PWR_CR5 U(0x10)
+#define PWR_CR6 U(0x14)
+#define PWR_CR7 U(0x18)
+#define PWR_CR8 U(0x1C)
+#define PWR_CR9 U(0x20)
+#define PWR_CR10 U(0x24)
+#define PWR_CR11 U(0x28)
+#define PWR_CR12 U(0x2C)
+#define PWR_UCPDR U(0x30)
+#define PWR_BDCR1 U(0x38)
+#define PWR_BDCR2 U(0x3C)
+#define PWR_CPU1CR U(0x40)
+#define PWR_CPU2CR U(0x44)
+#define PWR_CPU3CR U(0x48)
+#define PWR_D1CR U(0x4C)
+#define PWR_D2CR U(0x50)
+#define PWR_D3CR U(0x54)
+#define PWR_WKUPCR1 U(0x60)
+#define PWR_WKUPCR2 U(0x64)
+#define PWR_WKUPCR3 U(0x68)
+#define PWR_WKUPCR4 U(0x6C)
+#define PWR_WKUPCR5 U(0x70)
+#define PWR_WKUPCR6 U(0x74)
+#define PWR_D3WKUPENR U(0x98)
+#define PWR_RSECCFGR U(0x100)
+#define PWR_RPRIVCFGR U(0x104)
+#define PWR_R0CIDCFGR U(0x108)
+#define PWR_R1CIDCFGR U(0x10C)
+#define PWR_R2CIDCFGR U(0x110)
+#define PWR_R3CIDCFGR U(0x114)
+#define PWR_R4CIDCFGR U(0x118)
+#define PWR_R5CIDCFGR U(0x11C)
+#define PWR_R6CIDCFGR U(0x120)
+#define PWR_WIOSECCFGR U(0x180)
+#define PWR_WIOPRIVCFGR U(0x184)
+#define PWR_WIO1CIDCFGR U(0x188)
+#define PWR_WIO1SEMCR U(0x18C)
+#define PWR_WIO2CIDCFGR U(0x190)
+#define PWR_WIO2SEMCR U(0x194)
+#define PWR_WIO3CIDCFGR U(0x198)
+#define PWR_WIO3SEMCR U(0x19C)
+#define PWR_WIO4CIDCFGR U(0x1A0)
+#define PWR_WIO4SEMCR U(0x1A4)
+#define PWR_WIO5CIDCFGR U(0x1A8)
+#define PWR_WIO5SEMCR U(0x1AC)
+#define PWR_WIO6CIDCFGR U(0x1B0)
+#define PWR_WIO6SEMCR U(0x1B4)
+#define PWR_CPU1D1SR U(0x200)
+#define PWR_CPU2D2SR U(0x204)
+#define PWR_CPU3D3SR U(0x208)
+#define PWR_DBGR U(0x308)
+#define PWR_VERR U(0x3F4)
+#define PWR_IPIDR U(0x3F8)
+#define PWR_SIDR U(0x3FC)
+
+/* PWR_CR1 register fields */
+#define PWR_CR1_VDDIO3VMEN BIT_32(0)
+#define PWR_CR1_VDDIO4VMEN BIT_32(1)
+#define PWR_CR1_USB33VMEN BIT_32(2)
+#define PWR_CR1_UCPDVMEN BIT_32(3)
+#define PWR_CR1_AVMEN BIT_32(4)
+#define PWR_CR1_VDDIO3SV BIT_32(8)
+#define PWR_CR1_VDDIO4SV BIT_32(9)
+#define PWR_CR1_USB33SV BIT_32(10)
+#define PWR_CR1_UCPDSV BIT_32(11)
+#define PWR_CR1_ASV BIT_32(12)
+#define PWR_CR1_VDDIO3RDY BIT_32(16)
+#define PWR_CR1_VDDIO4RDY BIT_32(17)
+#define PWR_CR1_USB33RDY BIT_32(18)
+#define PWR_CR1_UCPDRDY BIT_32(19)
+#define PWR_CR1_ARDY BIT_32(20)
+#define PWR_CR1_VDDIOVRSEL BIT_32(24)
+#define PWR_CR1_VDDIO3VRSEL BIT_32(25)
+#define PWR_CR1_VDDIO4VRSEL BIT_32(26)
+#define PWR_CR1_GPVMO BIT_32(31)
+
+/* PWR_CR2 register fields */
+#define PWR_CR2_MONEN BIT_32(0)
+#define PWR_CR2_VBATL BIT_32(8)
+#define PWR_CR2_VBATH BIT_32(9)
+#define PWR_CR2_TEMPL BIT_32(10)
+#define PWR_CR2_TEMPH BIT_32(11)
+
+/* PWR_CR3 register fields */
+#define PWR_CR3_PVDEN BIT_32(0)
+#define PWR_CR3_PVDO BIT_32(8)
+
+/* PWR_CR5 register fields */
+#define PWR_CR5_VCOREMONEN BIT_32(0)
+#define PWR_CR5_VCOREL BIT_32(8)
+#define PWR_CR5_VCOREH BIT_32(9)
+
+/* PWR_CR6 register fields */
+#define PWR_CR6_VCPUMONEN BIT_32(0)
+#define PWR_CR6_VCPULLS BIT_32(4)
+#define PWR_CR6_VCPUL BIT_32(8)
+#define PWR_CR6_VCPUH BIT_32(9)
+
+/* PWR_CR7 register fields */
+#define PWR_CR7_VDDIO2VMEN BIT_32(0)
+#define PWR_CR7_VDDIO2SV BIT_32(8)
+#define PWR_CR7_VDDIO2RDY BIT_32(16)
+#define PWR_CR7_VDDIO2VRSEL BIT_32(24)
+#define PWR_CR7_VDDIO2VRSTBY BIT_32(25)
+
+/* PWR_CR8 register fields */
+#define PWR_CR8_VDDIO1VMEN BIT_32(0)
+#define PWR_CR8_VDDIO1SV BIT_32(8)
+#define PWR_CR8_VDDIO1RDY BIT_32(16)
+#define PWR_CR8_VDDIO1VRSEL BIT_32(24)
+#define PWR_CR8_VDDIO1VRSTBY BIT_32(25)
+
+/* PWR_CR9 register fields */
+#define PWR_CR9_BKPRBSEN BIT_32(0)
+#define PWR_CR9_LPR1BSEN BIT_32(4)
+
+/* PWR_CR10 register fields */
+#define PWR_CR10_RETRBSEN_MASK GENMASK_32(1, 0)
+#define PWR_CR10_RETRBSEN_SHIFT U(0)
+
+/* PWR_CR11 register fields */
+#define PWR_CR11_DDRRETDIS BIT_32(0)
+
+/* PWR_CR12 register fields */
+#define PWR_CR12_GPUVMEN BIT_32(0)
+#define PWR_CR12_GPULVTEN BIT_32(1)
+#define PWR_CR12_GPUSV BIT_32(8)
+#define PWR_CR12_VDDGPURDY BIT_32(16)
+
+/* PWR_UCPDR register fields */
+#define PWR_UCPDR_UCPD_DBDIS BIT_32(0)
+#define PWR_UCPDR_UCPD_STBY BIT_32(1)
+
+/* PWR_BDCR1 register fields */
+#define PWR_BDCR1_DBD3P BIT_32(0)
+
+/* PWR_BDCR2 register fields */
+#define PWR_BDCR2_DBP BIT_32(0)
+
+/* PWR_CPU1CR register fields */
+#define PWR_CPU1CR_PDDS_D2 BIT_32(0)
+#define PWR_CPU1CR_PDDS_D1 BIT_32(1)
+#define PWR_CPU1CR_VBF BIT_32(4)
+#define PWR_CPU1CR_STOPF BIT_32(5)
+#define PWR_CPU1CR_SBF BIT_32(6)
+#define PWR_CPU1CR_SBF_D1 BIT_32(7)
+#define PWR_CPU1CR_SBF_D3 BIT_32(8)
+#define PWR_CPU1CR_CSSF BIT_32(9)
+#define PWR_CPU1CR_STANDBYWFIL2 BIT_32(15)
+#define PWR_CPU1CR_LPDS_D1 BIT_32(16)
+#define PWR_CPU1CR_LVDS_D1 BIT_32(17)
+
+/* PWR_CPU2CR register fields */
+#define PWR_CPU2CR_PDDS_D2 BIT_32(0)
+#define PWR_CPU2CR_VBF BIT_32(4)
+#define PWR_CPU2CR_STOPF BIT_32(5)
+#define PWR_CPU2CR_SBF BIT_32(6)
+#define PWR_CPU2CR_SBF_D2 BIT_32(7)
+#define PWR_CPU2CR_SBF_D3 BIT_32(8)
+#define PWR_CPU2CR_CSSF BIT_32(9)
+#define PWR_CPU2CR_DEEPSLEEP BIT_32(15)
+#define PWR_CPU2CR_LPDS_D2 BIT_32(16)
+#define PWR_CPU2CR_LVDS_D2 BIT_32(17)
+
+/* PWR_CPU3CR register fields */
+#define PWR_CPU3CR_VBF BIT_32(4)
+#define PWR_CPU3CR_SBF_D3 BIT_32(8)
+#define PWR_CPU3CR_CSSF BIT_32(9)
+#define PWR_CPU3CR_DEEPSLEEP BIT_32(15)
+
+/* PWR_D1CR register fields */
+#define PWR_D1CR_LPCFG_D1 BIT_32(0)
+#define PWR_D1CR_POPL_D1_MASK GENMASK_32(12, 8)
+#define PWR_D1CR_POPL_D1_SHIFT U(8)
+
+/* PWR_D2CR register fields */
+#define PWR_D2CR_LPCFG_D2 BIT_32(0)
+#define PWR_D2CR_POPL_D2_MASK GENMASK_32(12, 8)
+#define PWR_D2CR_POPL_D2_SHIFT U(8)
+#define PWR_D2CR_LPLVDLY_D2_MASK GENMASK_32(18, 16)
+#define PWR_D2CR_LPLVDLY_D2_SHIFT U(16)
+#define PWR_D2CR_PODH_D2_MASK GENMASK_32(27, 24)
+#define PWR_D2CR_PODH_D2_SHIFT U(24)
+
+/* PWR_D3CR register fields */
+#define PWR_D3CR_PDDS_D3 BIT_32(0)
+#define PWR_D3CR_D3RDY BIT_32(31)
+
+/* PWR_WKUPCR1 register fields */
+#define PWR_WKUPCR1_WKUPC BIT_32(0)
+#define PWR_WKUPCR1_WKUPP BIT_32(8)
+#define PWR_WKUPCR1_WKUPPUPD_MASK GENMASK_32(13, 12)
+#define PWR_WKUPCR1_WKUPPUPD_SHIFT U(12)
+#define PWR_WKUPCR1_WKUPENCPU1 BIT_32(16)
+#define PWR_WKUPCR1_WKUPENCPU2 BIT_32(17)
+#define PWR_WKUPCR1_WKUPF BIT_32(31)
+
+/* PWR_WKUPCR2 register fields */
+#define PWR_WKUPCR2_WKUPC BIT_32(0)
+#define PWR_WKUPCR2_WKUPP BIT_32(8)
+#define PWR_WKUPCR2_WKUPPUPD_MASK GENMASK_32(13, 12)
+#define PWR_WKUPCR2_WKUPPUPD_SHIFT U(12)
+#define PWR_WKUPCR2_WKUPENCPU1 BIT_32(16)
+#define PWR_WKUPCR2_WKUPENCPU2 BIT_32(17)
+#define PWR_WKUPCR2_WKUPF BIT_32(31)
+
+/* PWR_WKUPCR3 register fields */
+#define PWR_WKUPCR3_WKUPC BIT_32(0)
+#define PWR_WKUPCR3_WKUPP BIT_32(8)
+#define PWR_WKUPCR3_WKUPPUPD_MASK GENMASK_32(13, 12)
+#define PWR_WKUPCR3_WKUPPUPD_SHIFT U(12)
+#define PWR_WKUPCR3_WKUPENCPU1 BIT_32(16)
+#define PWR_WKUPCR3_WKUPENCPU2 BIT_32(17)
+#define PWR_WKUPCR3_WKUPF BIT_32(31)
+
+/* PWR_WKUPCR4 register fields */
+#define PWR_WKUPCR4_WKUPC BIT_32(0)
+#define PWR_WKUPCR4_WKUPP BIT_32(8)
+#define PWR_WKUPCR4_WKUPPUPD_MASK GENMASK_32(13, 12)
+#define PWR_WKUPCR4_WKUPPUPD_SHIFT U(12)
+#define PWR_WKUPCR4_WKUPENCPU1 BIT_32(16)
+#define PWR_WKUPCR4_WKUPENCPU2 BIT_32(17)
+#define PWR_WKUPCR4_WKUPF BIT_32(31)
+
+/* PWR_WKUPCR5 register fields */
+#define PWR_WKUPCR5_WKUPC BIT_32(0)
+#define PWR_WKUPCR5_WKUPP BIT_32(8)
+#define PWR_WKUPCR5_WKUPPUPD_MASK GENMASK_32(13, 12)
+#define PWR_WKUPCR5_WKUPPUPD_SHIFT U(12)
+#define PWR_WKUPCR5_WKUPENCPU1 BIT_32(16)
+#define PWR_WKUPCR5_WKUPENCPU2 BIT_32(17)
+#define PWR_WKUPCR5_WKUPF BIT_32(31)
+
+/* PWR_WKUPCR6 register fields */
+#define PWR_WKUPCR6_WKUPC BIT_32(0)
+#define PWR_WKUPCR6_WKUPP BIT_32(8)
+#define PWR_WKUPCR6_WKUPPUPD_MASK GENMASK_32(13, 12)
+#define PWR_WKUPCR6_WKUPPUPD_SHIFT U(12)
+#define PWR_WKUPCR6_WKUPENCPU1 BIT_32(16)
+#define PWR_WKUPCR6_WKUPENCPU2 BIT_32(17)
+#define PWR_WKUPCR6_WKUPF BIT_32(31)
+
+/* PWR_D3WKUPENR register fields */
+#define PWR_D3WKUPENR_TAMP_WKUPEN_D3 BIT_32(0)
+
+/* PWR_RSECCFGR register fields */
+#define PWR_RSECCFGR_RSEC0 BIT_32(0)
+#define PWR_RSECCFGR_RSEC1 BIT_32(1)
+#define PWR_RSECCFGR_RSEC2 BIT_32(2)
+#define PWR_RSECCFGR_RSEC3 BIT_32(3)
+#define PWR_RSECCFGR_RSEC4 BIT_32(4)
+#define PWR_RSECCFGR_RSEC5 BIT_32(5)
+#define PWR_RSECCFGR_RSEC6 BIT_32(6)
+
+/* PWR_RPRIVCFGR register fields */
+#define PWR_RPRIVCFGR_RPRIV0 BIT_32(0)
+#define PWR_RPRIVCFGR_RPRIV1 BIT_32(1)
+#define PWR_RPRIVCFGR_RPRIV2 BIT_32(2)
+#define PWR_RPRIVCFGR_RPRIV3 BIT_32(3)
+#define PWR_RPRIVCFGR_RPRIV4 BIT_32(4)
+#define PWR_RPRIVCFGR_RPRIV5 BIT_32(5)
+#define PWR_RPRIVCFGR_RPRIV6 BIT_32(6)
+
+/* PWR_R0CIDCFGR register fields */
+#define PWR_R0CIDCFGR_CFEN BIT_32(0)
+#define PWR_R0CIDCFGR_SCID_MASK GENMASK_32(6, 4)
+#define PWR_R0CIDCFGR_SCID_SHIFT U(4)
+
+/* PWR_R1CIDCFGR register fields */
+#define PWR_R1CIDCFGR_CFEN BIT_32(0)
+#define PWR_R1CIDCFGR_SCID_MASK GENMASK_32(6, 4)
+#define PWR_R1CIDCFGR_SCID_SHIFT U(4)
+
+/* PWR_R2CIDCFGR register fields */
+#define PWR_R2CIDCFGR_CFEN BIT_32(0)
+#define PWR_R2CIDCFGR_SCID_MASK GENMASK_32(6, 4)
+#define PWR_R2CIDCFGR_SCID_SHIFT U(4)
+
+/* PWR_R3CIDCFGR register fields */
+#define PWR_R3CIDCFGR_CFEN BIT_32(0)
+#define PWR_R3CIDCFGR_SCID_MASK GENMASK_32(6, 4)
+#define PWR_R3CIDCFGR_SCID_SHIFT U(4)
+
+/* PWR_R4CIDCFGR register fields */
+#define PWR_R4CIDCFGR_CFEN BIT_32(0)
+#define PWR_R4CIDCFGR_SCID_MASK GENMASK_32(6, 4)
+#define PWR_R4CIDCFGR_SCID_SHIFT U(4)
+
+/* PWR_R5CIDCFGR register fields */
+#define PWR_R5CIDCFGR_CFEN BIT_32(0)
+#define PWR_R5CIDCFGR_SCID_MASK GENMASK_32(6, 4)
+#define PWR_R5CIDCFGR_SCID_SHIFT U(4)
+
+/* PWR_R6CIDCFGR register fields */
+#define PWR_R6CIDCFGR_CFEN BIT_32(0)
+#define PWR_R6CIDCFGR_SCID_MASK GENMASK_32(6, 4)
+#define PWR_R6CIDCFGR_SCID_SHIFT U(4)
+
+/* PWR_WIOSECCFGR register fields */
+#define PWR_WIOSECCFGR_WIOSEC1 BIT_32(0)
+#define PWR_WIOSECCFGR_WIOSEC2 BIT_32(1)
+#define PWR_WIOSECCFGR_WIOSEC3 BIT_32(2)
+#define PWR_WIOSECCFGR_WIOSEC4 BIT_32(3)
+#define PWR_WIOSECCFGR_WIOSEC5 BIT_32(4)
+#define PWR_WIOSECCFGR_WIOSEC6 BIT_32(5)
+
+/* PWR_WIOPRIVCFGR register fields */
+#define PWR_WIOPRIVCFGR_WIOPRIV1 BIT_32(0)
+#define PWR_WIOPRIVCFGR_WIOPRIV2 BIT_32(1)
+#define PWR_WIOPRIVCFGR_WIOPRIV3 BIT_32(2)
+#define PWR_WIOPRIVCFGR_WIOPRIV4 BIT_32(3)
+#define PWR_WIOPRIVCFGR_WIOPRIV5 BIT_32(4)
+#define PWR_WIOPRIVCFGR_WIOPRIV6 BIT_32(5)
+
+/* PWR_WIO1CIDCFGR register fields */
+#define PWR_WIO1CIDCFGR_CFEN BIT_32(0)
+#define PWR_WIO1CIDCFGR_SEM_EN BIT_32(1)
+#define PWR_WIO1CIDCFGR_SCID_MASK GENMASK_32(6, 4)
+#define PWR_WIO1CIDCFGR_SCID_SHIFT U(4)
+#define PWR_WIO1CIDCFGR_SEMWLC0 BIT_32(16)
+#define PWR_WIO1CIDCFGR_SEMWLC1 BIT_32(17)
+#define PWR_WIO1CIDCFGR_SEMWLC2 BIT_32(18)
+#define PWR_WIO1CIDCFGR_SEMWLC3 BIT_32(19)
+#define PWR_WIO1CIDCFGR_SEMWLC4 BIT_32(20)
+#define PWR_WIO1CIDCFGR_SEMWLC5 BIT_32(21)
+#define PWR_WIO1CIDCFGR_SEMWLC6 BIT_32(22)
+#define PWR_WIO1CIDCFGR_SEMWLC7 BIT_32(23)
+
+/* PWR_WIO1SEMCR register fields */
+#define PWR_WIO1SEMCR_SEM_MUTEX BIT_32(0)
+#define PWR_WIO1SEMCR_SEMCID_MASK GENMASK_32(6, 4)
+#define PWR_WIO1SEMCR_SEMCID_SHIFT U(4)
+
+/* PWR_WIO2CIDCFGR register fields */
+#define PWR_WIO2CIDCFGR_CFEN BIT_32(0)
+#define PWR_WIO2CIDCFGR_SEM_EN BIT_32(1)
+#define PWR_WIO2CIDCFGR_SCID_MASK GENMASK_32(6, 4)
+#define PWR_WIO2CIDCFGR_SCID_SHIFT U(4)
+#define PWR_WIO2CIDCFGR_SEMWLC0 BIT_32(16)
+#define PWR_WIO2CIDCFGR_SEMWLC1 BIT_32(17)
+#define PWR_WIO2CIDCFGR_SEMWLC2 BIT_32(18)
+#define PWR_WIO2CIDCFGR_SEMWLC3 BIT_32(19)
+#define PWR_WIO2CIDCFGR_SEMWLC4 BIT_32(20)
+#define PWR_WIO2CIDCFGR_SEMWLC5 BIT_32(21)
+#define PWR_WIO2CIDCFGR_SEMWLC6 BIT_32(22)
+#define PWR_WIO2CIDCFGR_SEMWLC7 BIT_32(23)
+
+/* PWR_WIO2SEMCR register fields */
+#define PWR_WIO2SEMCR_SEM_MUTEX BIT_32(0)
+#define PWR_WIO2SEMCR_SEMCID_MASK GENMASK_32(6, 4)
+#define PWR_WIO2SEMCR_SEMCID_SHIFT U(4)
+
+/* PWR_WIO3CIDCFGR register fields */
+#define PWR_WIO3CIDCFGR_CFEN BIT_32(0)
+#define PWR_WIO3CIDCFGR_SEM_EN BIT_32(1)
+#define PWR_WIO3CIDCFGR_SCID_MASK GENMASK_32(6, 4)
+#define PWR_WIO3CIDCFGR_SCID_SHIFT U(4)
+#define PWR_WIO3CIDCFGR_SEMWLC0 BIT_32(16)
+#define PWR_WIO3CIDCFGR_SEMWLC1 BIT_32(17)
+#define PWR_WIO3CIDCFGR_SEMWLC2 BIT_32(18)
+#define PWR_WIO3CIDCFGR_SEMWLC3 BIT_32(19)
+#define PWR_WIO3CIDCFGR_SEMWLC4 BIT_32(20)
+#define PWR_WIO3CIDCFGR_SEMWLC5 BIT_32(21)
+#define PWR_WIO3CIDCFGR_SEMWLC6 BIT_32(22)
+#define PWR_WIO3CIDCFGR_SEMWLC7 BIT_32(23)
+
+/* PWR_WIO3SEMCR register fields */
+#define PWR_WIO3SEMCR_SEM_MUTEX BIT_32(0)
+#define PWR_WIO3SEMCR_SEMCID_MASK GENMASK_32(6, 4)
+#define PWR_WIO3SEMCR_SEMCID_SHIFT U(4)
+
+/* PWR_WIO4CIDCFGR register fields */
+#define PWR_WIO4CIDCFGR_CFEN BIT_32(0)
+#define PWR_WIO4CIDCFGR_SEM_EN BIT_32(1)
+#define PWR_WIO4CIDCFGR_SCID_MASK GENMASK_32(6, 4)
+#define PWR_WIO4CIDCFGR_SCID_SHIFT U(4)
+#define PWR_WIO4CIDCFGR_SEMWLC0 BIT_32(16)
+#define PWR_WIO4CIDCFGR_SEMWLC1 BIT_32(17)
+#define PWR_WIO4CIDCFGR_SEMWLC2 BIT_32(18)
+#define PWR_WIO4CIDCFGR_SEMWLC3 BIT_32(19)
+#define PWR_WIO4CIDCFGR_SEMWLC4 BIT_32(20)
+#define PWR_WIO4CIDCFGR_SEMWLC5 BIT_32(21)
+#define PWR_WIO4CIDCFGR_SEMWLC6 BIT_32(22)
+#define PWR_WIO4CIDCFGR_SEMWLC7 BIT_32(23)
+
+/* PWR_WIO4SEMCR register fields */
+#define PWR_WIO4SEMCR_SEM_MUTEX BIT_32(0)
+#define PWR_WIO4SEMCR_SEMCID_MASK GENMASK_32(6, 4)
+#define PWR_WIO4SEMCR_SEMCID_SHIFT U(4)
+
+/* PWR_WIO5CIDCFGR register fields */
+#define PWR_WIO5CIDCFGR_CFEN BIT_32(0)
+#define PWR_WIO5CIDCFGR_SEM_EN BIT_32(1)
+#define PWR_WIO5CIDCFGR_SCID_MASK GENMASK_32(6, 4)
+#define PWR_WIO5CIDCFGR_SCID_SHIFT U(4)
+#define PWR_WIO5CIDCFGR_SEMWLC0 BIT_32(16)
+#define PWR_WIO5CIDCFGR_SEMWLC1 BIT_32(17)
+#define PWR_WIO5CIDCFGR_SEMWLC2 BIT_32(18)
+#define PWR_WIO5CIDCFGR_SEMWLC3 BIT_32(19)
+#define PWR_WIO5CIDCFGR_SEMWLC4 BIT_32(20)
+#define PWR_WIO5CIDCFGR_SEMWLC5 BIT_32(21)
+#define PWR_WIO5CIDCFGR_SEMWLC6 BIT_32(22)
+#define PWR_WIO5CIDCFGR_SEMWLC7 BIT_32(23)
+
+/* PWR_WIO5SEMCR register fields */
+#define PWR_WIO5SEMCR_SEM_MUTEX BIT_32(0)
+#define PWR_WIO5SEMCR_SEMCID_MASK GENMASK_32(6, 4)
+#define PWR_WIO5SEMCR_SEMCID_SHIFT U(4)
+
+/* PWR_WIO6CIDCFGR register fields */
+#define PWR_WIO6CIDCFGR_CFEN BIT_32(0)
+#define PWR_WIO6CIDCFGR_SEM_EN BIT_32(1)
+#define PWR_WIO6CIDCFGR_SCID_MASK GENMASK_32(6, 4)
+#define PWR_WIO6CIDCFGR_SCID_SHIFT U(4)
+#define PWR_WIO6CIDCFGR_SEMWLC0 BIT_32(16)
+#define PWR_WIO6CIDCFGR_SEMWLC1 BIT_32(17)
+#define PWR_WIO6CIDCFGR_SEMWLC2 BIT_32(18)
+#define PWR_WIO6CIDCFGR_SEMWLC3 BIT_32(19)
+#define PWR_WIO6CIDCFGR_SEMWLC4 BIT_32(20)
+#define PWR_WIO6CIDCFGR_SEMWLC5 BIT_32(21)
+#define PWR_WIO6CIDCFGR_SEMWLC6 BIT_32(22)
+#define PWR_WIO6CIDCFGR_SEMWLC7 BIT_32(23)
+
+/* PWR_WIO6SEMCR register fields */
+#define PWR_WIO6SEMCR_SEM_MUTEX BIT_32(0)
+#define PWR_WIO6SEMCR_SEMCID_MASK GENMASK_32(6, 4)
+#define PWR_WIO6SEMCR_SEMCID_SHIFT U(4)
+
+/* PWR_CPU1D1SR register fields */
+#define PWR_CPU1D1SR_HOLD_BOOT BIT_32(0)
+#define PWR_CPU1D1SR_CSTATE_MASK GENMASK_32(3, 2)
+#define PWR_CPU1D1SR_CSTATE_SHIFT U(2)
+#define PWR_CPU1D1SR_DSTATE_MASK GENMASK_32(10, 8)
+#define PWR_CPU1D1SR_DSTATE_SHIFT U(8)
+
+/* PWR_CPU2D2SR register fields */
+#define PWR_CPU2D2SR_HOLD_BOOT BIT_32(0)
+#define PWR_CPU2D2SR_WFBEN BIT_32(1)
+#define PWR_CPU2D2SR_CSTATE_MASK GENMASK_32(3, 2)
+#define PWR_CPU2D2SR_CSTATE_SHIFT U(2)
+#define PWR_CPU2D2SR_DSTATE_MASK GENMASK_32(10, 8)
+#define PWR_CPU2D2SR_DSTATE_SHIFT U(8)
+
+/* PWR_CPU3D3SR register fields */
+#define PWR_CPU3D3SR_CSTATE_MASK GENMASK_32(3, 2)
+#define PWR_CPU3D3SR_CSTATE_SHIFT U(2)
+#define PWR_CPU3D3SR_DSTATE_MASK GENMASK_32(10, 8)
+#define PWR_CPU3D3SR_DSTATE_SHIFT U(8)
+
+/* PWR_DBGR register fields */
+#define PWR_DBGR_FD3S BIT_32(0)
+#define PWR_DBGR_VDDIOKRETRAM BIT_32(16)
+#define PWR_DBGR_VDDIOKBKPRAM BIT_32(17)
+#define PWR_DBGR_VDDIOKD3 BIT_32(18)
+#define PWR_DBGR_VDDIOKLPSRAM1 BIT_32(19)
+
+/* PWR_VERR register fields */
+#define PWR_VERR_MINREV_MASK GENMASK_32(3, 0)
+#define PWR_VERR_MINREV_SHIFT U(0)
+#define PWR_VERR_MAJREV_MASK GENMASK_32(7, 4)
+#define PWR_VERR_MAJREV_SHIFT U(4)
+
+#endif /* STM32MP2_PWR_H */
diff --git a/include/lib/cpus/aarch32/cpu_macros.S b/include/lib/cpus/aarch32/cpu_macros.S
index 096e0b1..cfa5831 100644
--- a/include/lib/cpus/aarch32/cpu_macros.S
+++ b/include/lib/cpus/aarch32/cpu_macros.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -115,11 +115,6 @@
.popsection
.endif
- /*
- * Mandatory errata status printing function for CPUs of
- * this class.
- */
- .word \_name\()_errata_report
.word \_name\()_cpu_str
#ifdef IMAGE_BL32
@@ -130,45 +125,6 @@
#endif
.endm
-#if REPORT_ERRATA
- /*
- * Print status of a CPU errata
- *
- * _chosen:
- * Identifier indicating whether or not a CPU errata has been
- * compiled in.
- * _cpu:
- * Name of the CPU
- * _id:
- * Errata identifier
- * _rev_var:
- * Register containing the combined value CPU revision and variant
- * - typically the return value of cpu_get_rev_var
- */
- .macro report_errata _chosen, _cpu, _id, _rev_var=r4
- /* Stash a string with errata ID */
- .pushsection .rodata
- \_cpu\()_errata_\_id\()_str:
- .asciz "\_id"
- .popsection
-
- /* Check whether errata applies */
- mov r0, \_rev_var
- bl check_errata_\_id
-
- .ifeq \_chosen
- /*
- * Errata workaround has not been compiled in. If the errata would have
- * applied had it been compiled in, print its status as missing.
- */
- cmp r0, #0
- movne r0, #ERRATA_MISSING
- .endif
- ldr r1, =\_cpu\()_cpu_str
- ldr r2, =\_cpu\()_errata_\_id\()_str
- bl errata_print_msg
- .endm
-#endif
/*
* Helper macro that reads the part number of the current CPU and jumps
* to the given label if it matches the CPU MIDR provided.
@@ -239,21 +195,4 @@
.popsection
.endm
-/*
- * Maintain compatibility with the old scheme of "each cpu has its own reporter".
- * TODO remove entirely once all cpus have been converted. This includes the
- * cpu_ops entry, as print_errata_status can call this directly for all cpus
- */
-.macro errata_report_shim _cpu:req
- #if REPORT_ERRATA
- func \_cpu\()_errata_report
- push {r12, lr}
-
- bl generic_errata_report
-
- pop {r12, lr}
- bx lr
- endfunc \_cpu\()_errata_report
- #endif
-.endm
#endif /* CPU_MACROS_S */
diff --git a/include/lib/cpus/aarch64/cortex_a520.h b/include/lib/cpus/aarch64/cortex_a520.h
index ed3401d..11ddea9 100644
--- a/include/lib/cpus/aarch64/cortex_a520.h
+++ b/include/lib/cpus/aarch64/cortex_a520.h
@@ -28,4 +28,15 @@
#define CORTEX_A520_CPUPWRCTLR_EL1 S3_0_C15_C2_7
#define CORTEX_A520_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1)
+#ifndef __ASSEMBLER__
+#if ERRATA_A520_2938996
+long check_erratum_cortex_a520_2938996(long cpu_rev);
+#else
+static inline long check_erratum_cortex_a520_2938996(long cpu_rev)
+{
+ return 0;
+}
+#endif /* ERRATA_A520_2938996 */
+#endif /* __ASSEMBLER__ */
+
#endif /* CORTEX_A520_H */
diff --git a/include/lib/cpus/aarch64/cortex_a720.h b/include/lib/cpus/aarch64/cortex_a720.h
index fb27f79..129c1ee 100644
--- a/include/lib/cpus/aarch64/cortex_a720.h
+++ b/include/lib/cpus/aarch64/cortex_a720.h
@@ -23,6 +23,11 @@
#define CORTEX_A720_CPUACTLR2_EL1 S3_0_C15_C1_1
/*******************************************************************************
+ * CPU Auxiliary Control register 4 specific definitions.
+ ******************************************************************************/
+#define CORTEX_A720_CPUACTLR4_EL1 S3_0_C15_C1_3
+
+/*******************************************************************************
* CPU Extended Control register specific definitions
******************************************************************************/
#define CORTEX_A720_CPUECTLR_EL1 S3_0_C15_C1_4
diff --git a/include/lib/cpus/aarch64/cortex_x4.h b/include/lib/cpus/aarch64/cortex_x4.h
index 433687b..4b6af8b 100644
--- a/include/lib/cpus/aarch64/cortex_x4.h
+++ b/include/lib/cpus/aarch64/cortex_x4.h
@@ -28,4 +28,21 @@
******************************************************************************/
#define CORTEX_X4_CPUACTLR3_EL1 S3_0_C15_C1_2
+/*******************************************************************************
+ * CPU Auxiliary control register 5 specific definitions
+ ******************************************************************************/
+#define CORTEX_X4_CPUACTLR5_EL1 S3_0_C15_C8_0
+#define CORTEX_X4_CPUACTLR5_EL1_BIT_14 (ULL(1) << 14)
+
+#ifndef __ASSEMBLER__
+#if ERRATA_X4_2726228
+long check_erratum_cortex_x4_2726228(long cpu_rev);
+#else
+static inline long check_erratum_cortex_x4_2726228(long cpu_rev)
+{
+ return 0;
+}
+#endif /* ERRATA_X4_2726228 */
+#endif /* __ASSEMBLER__ */
+
#endif /* CORTEX_X4_H */
diff --git a/include/lib/cpus/aarch64/cpu_macros.S b/include/lib/cpus/aarch64/cpu_macros.S
index d49d82e..98294b9 100644
--- a/include/lib/cpus/aarch64/cpu_macros.S
+++ b/include/lib/cpus/aarch64/cpu_macros.S
@@ -132,12 +132,6 @@
.popsection
.endif
-
- /*
- * Mandatory errata status printing function for CPUs of
- * this class.
- */
- .quad \_name\()_errata_report
.quad \_name\()_cpu_str
#ifdef IMAGE_BL31
@@ -171,49 +165,6 @@
\_extra1, \_extra2, \_extra3, 0, \_power_down_ops
.endm
-/* TODO can be deleted once all CPUs have been converted */
-#if REPORT_ERRATA
- /*
- * Print status of a CPU errata
- *
- * _chosen:
- * Identifier indicating whether or not a CPU errata has been
- * compiled in.
- * _cpu:
- * Name of the CPU
- * _id:
- * Errata identifier
- * _rev_var:
- * Register containing the combined value CPU revision and variant
- * - typically the return value of cpu_get_rev_var
- */
- .macro report_errata _chosen, _cpu, _id, _rev_var=x8
- /* Stash a string with errata ID */
- .pushsection .rodata
- \_cpu\()_errata_\_id\()_str:
- .asciz "\_id"
- .popsection
-
- /* Check whether errata applies */
- mov x0, \_rev_var
- /* Shall clobber: x0-x7 */
- bl check_errata_\_id
-
- .ifeq \_chosen
- /*
- * Errata workaround has not been compiled in. If the errata would have
- * applied had it been compiled in, print its status as missing.
- */
- cbz x0, 900f
- mov x0, #ERRATA_MISSING
- .endif
-900:
- adr x1, \_cpu\()_cpu_str
- adr x2, \_cpu\()_errata_\_id\()_str
- bl errata_print_msg
- .endm
-#endif
-
/*
* This macro is used on some CPUs to detect if they are vulnerable
* to CVE-2017-5715.
@@ -622,23 +573,4 @@
endfunc \_cpu\()_reset_func
.endm
-/*
- * Maintain compatibility with the old scheme of each cpu has its own reporting.
- * TODO remove entirely once all cpus have been converted. This includes the
- * cpu_ops entry, as print_errata_status can call this directly for all cpus
- */
-.macro errata_report_shim _cpu:req
- #if REPORT_ERRATA
- func \_cpu\()_errata_report
- /* normal stack frame for pretty debugging */
- stp x29, x30, [sp, #-16]!
- mov x29, sp
-
- bl generic_errata_report
-
- ldp x29, x30, [sp], #16
- ret
- endfunc \_cpu\()_errata_report
- #endif
-.endm
#endif /* CPU_MACROS_S */
diff --git a/include/lib/cpus/cpu_ops.h b/include/lib/cpus/cpu_ops.h
index 8b36ff1..0084189 100644
--- a/include/lib/cpus/cpu_ops.h
+++ b/include/lib/cpus/cpu_ops.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2023-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -57,7 +57,6 @@
#define CPU_ERRATA_LIST_END_SIZE CPU_WORD_SIZE
/* Fields required to print errata status */
#if REPORT_ERRATA
-#define CPU_ERRATA_FUNC_SIZE CPU_WORD_SIZE
#define CPU_CPU_STR_SIZE CPU_WORD_SIZE
/* BL1 doesn't require mutual exclusion and printed flag. */
#if defined(IMAGE_BL31) || defined(IMAGE_BL32)
@@ -68,7 +67,6 @@
#define CPU_ERRATA_PRINTED_SIZE 0
#endif /* defined(IMAGE_BL31) || defined(IMAGE_BL32) */
#else
-#define CPU_ERRATA_FUNC_SIZE 0
#define CPU_CPU_STR_SIZE 0
#define CPU_ERRATA_LOCK_SIZE 0
#define CPU_ERRATA_PRINTED_SIZE 0
@@ -98,8 +96,7 @@
#endif /* __aarch64__ */
#define CPU_ERRATA_LIST_START CPU_PWR_DWN_OPS + CPU_PWR_DWN_OPS_SIZE
#define CPU_ERRATA_LIST_END CPU_ERRATA_LIST_START + CPU_ERRATA_LIST_START_SIZE
-#define CPU_ERRATA_FUNC CPU_ERRATA_LIST_END + CPU_ERRATA_LIST_END_SIZE
-#define CPU_CPU_STR CPU_ERRATA_FUNC + CPU_ERRATA_FUNC_SIZE
+#define CPU_CPU_STR CPU_ERRATA_LIST_END + CPU_ERRATA_LIST_END_SIZE
#define CPU_ERRATA_LOCK CPU_CPU_STR + CPU_CPU_STR_SIZE
#define CPU_ERRATA_PRINTED CPU_ERRATA_LOCK + CPU_ERRATA_LOCK_SIZE
#if __aarch64__
@@ -130,7 +127,6 @@
void *errata_list_start;
void *errata_list_end;
#if REPORT_ERRATA
- void (*errata_func)(void);
char *cpu_str;
#if defined(IMAGE_BL31) || defined(IMAGE_BL32)
spinlock_t *errata_lock;
diff --git a/include/lib/cpus/errata.h b/include/lib/cpus/errata.h
index 2080898..ef1b02b 100644
--- a/include/lib/cpus/errata.h
+++ b/include/lib/cpus/errata.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -25,11 +25,19 @@
#define ERRATUM_MITIGATED ERRATUM_CHOSEN + ERRATUM_CHOSEN_SIZE
#define ERRATUM_ENTRY_SIZE ERRATUM_MITIGATED + ERRATUM_MITIGATED_SIZE
+/* Errata status */
+#define ERRATA_NOT_APPLIES 0
+#define ERRATA_APPLIES 1
+#define ERRATA_MISSING 2
+
#ifndef __ASSEMBLER__
#include <lib/cassert.h>
void print_errata_status(void);
-void errata_print_msg(unsigned int status, const char *cpu, const char *id);
+
+#if ERRATA_A520_2938996 || ERRATA_X4_2726228
+unsigned int check_if_affected_core(void);
+#endif
/*
* NOTE that this structure will be different on AArch32 and AArch64. The
@@ -74,11 +82,6 @@
#endif /* __ASSEMBLER__ */
-/* Errata status */
-#define ERRATA_NOT_APPLIES 0
-#define ERRATA_APPLIES 1
-#define ERRATA_MISSING 2
-
/* Macro to get CPU revision code for checking errata version compatibility. */
#define CPU_REV(r, p) ((r << 4) | p)
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index 7c10506..87f1541 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -7,9 +7,18 @@
#ifndef CONTEXT_H
#define CONTEXT_H
-#include <lib/el3_runtime/context_el1.h>
+#if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
#include <lib/el3_runtime/context_el2.h>
+#else
+/**
+ * El1 context is required either when:
+ * IMAGE_BL1 || ((!CTX_INCLUDE_EL2_REGS) && IMAGE_BL31)
+ */
+#include <lib/el3_runtime/context_el1.h>
+#endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
+
#include <lib/el3_runtime/cpu_data.h>
+#include <lib/el3_runtime/simd_ctx.h>
#include <lib/utils_def.h>
/*******************************************************************************
@@ -82,60 +91,11 @@
#define CTX_EL3STATE_END U(0x50) /* Align to the next 16 byte boundary */
#endif /* FFH_SUPPORT */
-/*******************************************************************************
- * Constants that allow assembler code to access members of and the 'fp_regs'
- * structure at their correct offsets.
- ******************************************************************************/
-# define CTX_FPREGS_OFFSET (CTX_EL3STATE_OFFSET + CTX_EL3STATE_END)
-#if CTX_INCLUDE_FPREGS
-#define CTX_FP_Q0 U(0x0)
-#define CTX_FP_Q1 U(0x10)
-#define CTX_FP_Q2 U(0x20)
-#define CTX_FP_Q3 U(0x30)
-#define CTX_FP_Q4 U(0x40)
-#define CTX_FP_Q5 U(0x50)
-#define CTX_FP_Q6 U(0x60)
-#define CTX_FP_Q7 U(0x70)
-#define CTX_FP_Q8 U(0x80)
-#define CTX_FP_Q9 U(0x90)
-#define CTX_FP_Q10 U(0xa0)
-#define CTX_FP_Q11 U(0xb0)
-#define CTX_FP_Q12 U(0xc0)
-#define CTX_FP_Q13 U(0xd0)
-#define CTX_FP_Q14 U(0xe0)
-#define CTX_FP_Q15 U(0xf0)
-#define CTX_FP_Q16 U(0x100)
-#define CTX_FP_Q17 U(0x110)
-#define CTX_FP_Q18 U(0x120)
-#define CTX_FP_Q19 U(0x130)
-#define CTX_FP_Q20 U(0x140)
-#define CTX_FP_Q21 U(0x150)
-#define CTX_FP_Q22 U(0x160)
-#define CTX_FP_Q23 U(0x170)
-#define CTX_FP_Q24 U(0x180)
-#define CTX_FP_Q25 U(0x190)
-#define CTX_FP_Q26 U(0x1a0)
-#define CTX_FP_Q27 U(0x1b0)
-#define CTX_FP_Q28 U(0x1c0)
-#define CTX_FP_Q29 U(0x1d0)
-#define CTX_FP_Q30 U(0x1e0)
-#define CTX_FP_Q31 U(0x1f0)
-#define CTX_FP_FPSR U(0x200)
-#define CTX_FP_FPCR U(0x208)
-#if CTX_INCLUDE_AARCH32_REGS
-#define CTX_FP_FPEXC32_EL2 U(0x210)
-#define CTX_FPREGS_END U(0x220) /* Align to the next 16 byte boundary */
-#else
-#define CTX_FPREGS_END U(0x210) /* Align to the next 16 byte boundary */
-#endif /* CTX_INCLUDE_AARCH32_REGS */
-#else
-#define CTX_FPREGS_END U(0)
-#endif /* CTX_INCLUDE_FPREGS */
/*******************************************************************************
* Registers related to CVE-2018-3639
******************************************************************************/
-#define CTX_CVE_2018_3639_OFFSET (CTX_FPREGS_OFFSET + CTX_FPREGS_END)
+#define CTX_CVE_2018_3639_OFFSET (CTX_EL3STATE_OFFSET + CTX_EL3STATE_END)
#define CTX_CVE_2018_3639_DISABLE U(0)
#define CTX_CVE_2018_3639_END U(0x10) /* Align to the next 16 byte boundary */
@@ -230,9 +190,6 @@
/* Constants to determine the size of individual context structures */
#define CTX_GPREG_ALL (CTX_GPREGS_END >> DWORD_SHIFT)
-#if CTX_INCLUDE_FPREGS
-# define CTX_FPREG_ALL (CTX_FPREGS_END >> DWORD_SHIFT)
-#endif
#define CTX_EL3STATE_ALL (CTX_EL3STATE_END >> DWORD_SHIFT)
#define CTX_CVE_2018_3639_ALL (CTX_CVE_2018_3639_END >> DWORD_SHIFT)
@@ -253,15 +210,6 @@
DEFINE_REG_STRUCT(gp_regs, CTX_GPREG_ALL);
/*
- * AArch64 floating point register context structure for preserving
- * the floating point state during switches from one security state to
- * another.
- */
-#if CTX_INCLUDE_FPREGS
-DEFINE_REG_STRUCT(fp_regs, CTX_FPREG_ALL);
-#endif
-
-/*
* Miscellaneous registers used by EL3 firmware to maintain its state
* across exception entries and exits
*/
@@ -300,9 +248,6 @@
gp_regs_t gpregs_ctx;
el3_state_t el3state_ctx;
-#if CTX_INCLUDE_FPREGS
- fp_regs_t fpregs_ctx;
-#endif
cve_2018_3639_t cve_2018_3639_ctx;
#if ERRATA_SPECULATIVE_AT
@@ -313,10 +258,16 @@
pauth_t pauth_ctx;
#endif
- el1_sysregs_t el1_sysregs_ctx;
-
-#if CTX_INCLUDE_EL2_REGS
+#if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
el2_sysregs_t el2_sysregs_ctx;
+#else
+ /* El1 context should be included only either for IMAGE_BL1,
+ * or for IMAGE_BL31 when CTX_INCLUDE_EL2_REGS=0:
+ * When SPMD_SPM_AT_SEL2=1, SPMC at S-EL2 takes care of saving
+ * and restoring EL1 registers. In this case, BL31 at EL3 can
+ * exclude save and restore of EL1 context registers.
+ */
+ el1_sysregs_t el1_sysregs_ctx;
#endif
} cpu_context_t;
@@ -335,13 +286,13 @@
/* Macros to access members of the 'cpu_context_t' structure */
#define get_el3state_ctx(h) (&((cpu_context_t *) h)->el3state_ctx)
-#if CTX_INCLUDE_FPREGS
-# define get_fpregs_ctx(h) (&((cpu_context_t *) h)->fpregs_ctx)
-#endif
+
+#if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
+#define get_el2_sysregs_ctx(h) (&((cpu_context_t *) h)->el2_sysregs_ctx)
+#else
#define get_el1_sysregs_ctx(h) (&((cpu_context_t *) h)->el1_sysregs_ctx)
-#if CTX_INCLUDE_EL2_REGS
-# define get_el2_sysregs_ctx(h) (&((cpu_context_t *) h)->el2_sysregs_ctx)
#endif
+
#define get_gpregs_ctx(h) (&((cpu_context_t *) h)->gpregs_ctx)
#define get_cve_2018_3639_ctx(h) (&((cpu_context_t *) h)->cve_2018_3639_ctx)
@@ -364,10 +315,6 @@
CASSERT(CTX_EL3STATE_OFFSET == __builtin_offsetof(cpu_context_t, el3state_ctx),
assert_core_context_el3state_offset_mismatch);
-#if CTX_INCLUDE_FPREGS
-CASSERT(CTX_FPREGS_OFFSET == __builtin_offsetof(cpu_context_t, fpregs_ctx),
- assert_core_context_fp_offset_mismatch);
-#endif /* CTX_INCLUDE_FPREGS */
CASSERT(CTX_CVE_2018_3639_OFFSET == __builtin_offsetof(cpu_context_t, cve_2018_3639_ctx),
assert_core_context_cve_2018_3639_offset_mismatch);
@@ -422,10 +369,73 @@
* Function prototypes
******************************************************************************/
#if CTX_INCLUDE_FPREGS
-void fpregs_context_save(fp_regs_t *regs);
-void fpregs_context_restore(fp_regs_t *regs);
+void fpregs_context_save(simd_regs_t *regs);
+void fpregs_context_restore(simd_regs_t *regs);
#endif
+/*******************************************************************************
+ * The next four inline functions are required for IMAGE_BL1, as well as for
+ * IMAGE_BL31 for the below combinations.
+ * ============================================================================
+ * | ERRATA_SPECULATIVE_AT| CTX_INCLUDE_EL2_REGS | Combination |
+ * ============================================================================
+ * | 0 | 0 | Valid (EL1 ctx) |
+ * |______________________|______________________|____________________________|
+ * | | | Invalid (No Errata/EL1 Ctx)|
+ * | 0 | 1 | Hence commented out. |
+ * |______________________|______________________|____________________________|
+ * | | | |
+ * | 1 | 0 | Valid (Errata ctx) |
+ * |______________________|______________________|____________________________|
+ * | | | |
+ * | 1 | 1 | Valid (Errata ctx) |
+ * |______________________|______________________|____________________________|
+ * ============================================================================
+ ******************************************************************************/
+#if (IMAGE_BL1 || ((ERRATA_SPECULATIVE_AT) || (!CTX_INCLUDE_EL2_REGS)))
+
+static inline void write_ctx_sctlr_el1_reg_errata(cpu_context_t *ctx, u_register_t val)
+{
+#if (ERRATA_SPECULATIVE_AT)
+ write_ctx_reg(get_errata_speculative_at_ctx(ctx),
+ CTX_ERRATA_SPEC_AT_SCTLR_EL1, val);
+#else
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), sctlr_el1, val);
+#endif /* ERRATA_SPECULATIVE_AT */
+}
+
+static inline void write_ctx_tcr_el1_reg_errata(cpu_context_t *ctx, u_register_t val)
+{
+#if (ERRATA_SPECULATIVE_AT)
+ write_ctx_reg(get_errata_speculative_at_ctx(ctx),
+ CTX_ERRATA_SPEC_AT_TCR_EL1, val);
+#else
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), tcr_el1, val);
+#endif /* ERRATA_SPECULATIVE_AT */
+}
+
+static inline u_register_t read_ctx_sctlr_el1_reg_errata(cpu_context_t *ctx)
+{
+#if (ERRATA_SPECULATIVE_AT)
+ return read_ctx_reg(get_errata_speculative_at_ctx(ctx),
+ CTX_ERRATA_SPEC_AT_SCTLR_EL1);
+#else
+ return read_el1_ctx_common(get_el1_sysregs_ctx(ctx), sctlr_el1);
+#endif /* ERRATA_SPECULATIVE_AT */
+}
+
+static inline u_register_t read_ctx_tcr_el1_reg_errata(cpu_context_t *ctx)
+{
+#if (ERRATA_SPECULATIVE_AT)
+ return read_ctx_reg(get_errata_speculative_at_ctx(ctx),
+ CTX_ERRATA_SPEC_AT_TCR_EL1);
+#else
+ return read_el1_ctx_common(get_el1_sysregs_ctx(ctx), tcr_el1);
+#endif /* ERRATA_SPECULATIVE_AT */
+}
+
+#endif /* (IMAGE_BL1 || ((ERRATA_SPECULATIVE_AT) || (!CTX_INCLUDE_EL2_REGS))) */
+
#endif /* __ASSEMBLER__ */
#endif /* CONTEXT_H */
diff --git a/include/lib/el3_runtime/context_el2.h b/include/lib/el3_runtime/context_el2.h
index ca1ea4e..14c1fb6 100644
--- a/include/lib/el3_runtime/context_el2.h
+++ b/include/lib/el3_runtime/context_el2.h
@@ -13,7 +13,6 @@
* AArch64 EL2 system register context structure for preserving the
* architectural state during world switches.
******************************************************************************/
-#if CTX_INCLUDE_EL2_REGS
typedef struct el2_common_regs {
uint64_t actlr_el2;
uint64_t afsr0_el2;
@@ -359,7 +358,6 @@
#define write_el2_ctx_mpam(ctx, reg, val)
#endif /* CTX_INCLUDE_MPAM_REGS */
-#endif /* CTX_INCLUDE_EL2_REGS */
/******************************************************************************/
#endif /* __ASSEMBLER__ */
diff --git a/include/lib/el3_runtime/context_mgmt.h b/include/lib/el3_runtime/context_mgmt.h
index 7451b85..70dbd46 100644
--- a/include/lib/el3_runtime/context_mgmt.h
+++ b/include/lib/el3_runtime/context_mgmt.h
@@ -44,15 +44,17 @@
void cm_manage_extensions_el3(void);
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);
#endif
-#if CTX_INCLUDE_EL2_REGS
+#if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
void cm_el2_sysregs_context_save(uint32_t security_state);
void cm_el2_sysregs_context_restore(uint32_t security_state);
-#endif
-
+#else
void cm_el1_sysregs_context_save(uint32_t security_state);
void cm_el1_sysregs_context_restore(uint32_t security_state);
+#endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
+
void cm_set_elr_el3(uint32_t security_state, uintptr_t entrypoint);
void cm_set_elr_spsr_el3(uint32_t security_state,
uintptr_t entrypoint, uint32_t spsr);
@@ -95,6 +97,7 @@
void cm_set_next_context(void *context);
static inline void cm_manage_extensions_el3(void) {}
static inline void manage_extensions_nonsecure_per_world(void) {}
+static inline void cm_handle_asymmetric_features(void) {}
#endif /* __aarch64__ */
#endif /* CONTEXT_MGMT_H */
diff --git a/include/lib/el3_runtime/simd_ctx.h b/include/lib/el3_runtime/simd_ctx.h
new file mode 100644
index 0000000..fdbe24f
--- /dev/null
+++ b/include/lib/el3_runtime/simd_ctx.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022, Google LLC. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SIMD_CTX_H
+#define SIMD_CTX_H
+
+/*******************************************************************************
+ * Constants that allow assembler code to access members of and the 'simd_context'
+ * structure at their correct offsets.
+ ******************************************************************************/
+
+#if CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS
+#if CTX_INCLUDE_SVE_REGS
+#define SIMD_VECTOR_LEN_BYTES (SVE_VECTOR_LEN / 8) /* Length of vector in bytes */
+#elif CTX_INCLUDE_FPREGS
+#define SIMD_VECTOR_LEN_BYTES U(16) /* 128 bits fixed vector length for FPU */
+#endif /* CTX_INCLUDE_SVE_REGS */
+
+#define CTX_SIMD_VECTORS U(0)
+/* there are 32 vector registers, each of size SIMD_VECTOR_LEN_BYTES */
+#define CTX_SIMD_FPSR (CTX_SIMD_VECTORS + (32 * SIMD_VECTOR_LEN_BYTES))
+#define CTX_SIMD_FPCR (CTX_SIMD_FPSR + 8)
+
+#if CTX_INCLUDE_FPREGS && CTX_INCLUDE_AARCH32_REGS
+#define CTX_SIMD_FPEXC32 (CTX_SIMD_FPCR + 8)
+#define CTX_SIMD_PREDICATES (CTX_SIMD_FPEXC32 + 16)
+#else
+#define CTX_SIMD_PREDICATES (CTX_SIMD_FPCR + 8)
+#endif /* CTX_INCLUDE_FPREGS && CTX_INCLUDE_AARCH32_REGS */
+
+/*
+ * Each predicate register is 1/8th the size of a vector register and there are 16
+ * predicate registers
+ */
+#define CTX_SIMD_FFR (CTX_SIMD_PREDICATES + (16 * (SIMD_VECTOR_LEN_BYTES / 8)))
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+#include <lib/cassert.h>
+
+/*
+ * Please don't change order of fields in this struct as that may violate
+ * alignment requirements and affect how assembly code accesses members of this
+ * struct.
+ */
+typedef struct {
+ uint8_t vectors[32][SIMD_VECTOR_LEN_BYTES];
+ uint8_t fpsr[8];
+ uint8_t fpcr[8];
+#if CTX_INCLUDE_FPREGS && CTX_INCLUDE_AARCH32_REGS
+ /* 16 bytes to align to next 16 byte boundary when CTX_INCLUDE_SVE_REGS is 0 */
+ uint8_t fpexc32_el2[16];
+#endif
+#if CTX_INCLUDE_SVE_REGS
+ /* FFR and each of predicates is one-eigth of the SVE vector length */
+ uint8_t predicates[16][SIMD_VECTOR_LEN_BYTES / 8];
+ uint8_t ffr[SIMD_VECTOR_LEN_BYTES / 8];
+ /* SMCCCv1.3 FID[16] hint bit state recorded on EL3 entry */
+ bool hint;
+#endif /* CTX_INCLUDE_SVE_REGS */
+} __aligned(16) simd_regs_t;
+
+CASSERT(CTX_SIMD_VECTORS == __builtin_offsetof(simd_regs_t, vectors),
+ assert_vectors_mismatch);
+
+CASSERT(CTX_SIMD_FPSR == __builtin_offsetof(simd_regs_t, fpsr),
+ assert_fpsr_mismatch);
+
+CASSERT(CTX_SIMD_FPCR == __builtin_offsetof(simd_regs_t, fpcr),
+ assert_fpcr_mismatch);
+
+#if CTX_INCLUDE_FPREGS && CTX_INCLUDE_AARCH32_REGS
+CASSERT(CTX_SIMD_FPEXC32 == __builtin_offsetof(simd_regs_t, fpexc32_el2),
+ assert_fpex32_mismtatch);
+#endif
+
+#if CTX_INCLUDE_SVE_REGS
+CASSERT(CTX_SIMD_PREDICATES == __builtin_offsetof(simd_regs_t, predicates),
+ assert_predicates_mismatch);
+
+CASSERT(CTX_SIMD_FFR == __builtin_offsetof(simd_regs_t, ffr),
+ assert_ffr_mismatch);
+#endif
+
+void simd_ctx_save(uint32_t security_state, bool hint_sve);
+void simd_ctx_restore(uint32_t security_state);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS */
+
+#endif /* SIMD_CTX_H */
diff --git a/include/lib/extensions/sve.h b/include/lib/extensions/sve.h
index 947c905..2979efb 100644
--- a/include/lib/extensions/sve.h
+++ b/include/lib/extensions/sve.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -10,6 +10,7 @@
#include <context.h>
#if (ENABLE_SME_FOR_NS || ENABLE_SVE_FOR_NS)
+
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);
@@ -25,4 +26,9 @@
}
#endif /* ( ENABLE_SME_FOR_NS | ENABLE_SVE_FOR_NS ) */
+#if CTX_INCLUDE_SVE_REGS
+void sve_context_save(simd_regs_t *regs);
+void sve_context_restore(simd_regs_t *regs);
+#endif
+
#endif /* SVE_H */
diff --git a/include/lib/extensions/tcr2.h b/include/lib/extensions/tcr2.h
new file mode 100644
index 0000000..08a2b08
--- /dev/null
+++ b/include/lib/extensions/tcr2.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TCR2_H
+#define TCR2_H
+
+#include <context.h>
+
+#if ENABLE_FEAT_TCR2
+void tcr2_enable(cpu_context_t *ctx);
+void tcr2_disable(cpu_context_t *ctx);
+#else
+static inline void tcr2_enable(cpu_context_t *ctx)
+{
+}
+static inline void tcr2_disable(cpu_context_t *ctx)
+{
+}
+#endif /* ENABLE_FEAT_TCR2 */
+
+#endif /* TCR2_H */
diff --git a/lib/cpus/aarch32/aem_generic.S b/lib/cpus/aarch32/aem_generic.S
index 9f45e38..f4dc0d1 100644
--- a/lib/cpus/aarch32/aem_generic.S
+++ b/lib/cpus/aarch32/aem_generic.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -40,14 +40,6 @@
b dcsw_op_all
endfunc aem_generic_cluster_pwr_dwn
-#if REPORT_ERRATA
-/*
- * Errata printing function for AEM. Must follow AAPCS.
- */
-func aem_generic_errata_report
- bx lr
-endfunc aem_generic_errata_report
-#endif
/* cpu_ops for Base AEM FVP */
declare_cpu_ops aem_generic, BASE_AEM_MIDR, CPU_NO_RESET_FUNC, \
diff --git a/lib/cpus/aarch32/cortex_a12.S b/lib/cpus/aarch32/cortex_a12.S
index 8eec27c..b95020e 100644
--- a/lib/cpus/aarch32/cortex_a12.S
+++ b/lib/cpus/aarch32/cortex_a12.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -73,8 +73,6 @@
b cortex_a12_disable_smp
endfunc cortex_a12_cluster_pwr_dwn
-errata_report_shim cortex_a12
-
declare_cpu_ops cortex_a12, CORTEX_A12_MIDR, \
cortex_a12_reset_func, \
cortex_a12_core_pwr_dwn, \
diff --git a/lib/cpus/aarch32/cortex_a15.S b/lib/cpus/aarch32/cortex_a15.S
index b41676d..53489ad 100644
--- a/lib/cpus/aarch32/cortex_a15.S
+++ b/lib/cpus/aarch32/cortex_a15.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -172,8 +172,6 @@
b cortex_a15_disable_smp
endfunc cortex_a15_cluster_pwr_dwn
-errata_report_shim cortex_a15
-
declare_cpu_ops cortex_a15, CORTEX_A15_MIDR, \
cortex_a15_reset_func, \
cortex_a15_core_pwr_dwn, \
diff --git a/lib/cpus/aarch32/cortex_a17.S b/lib/cpus/aarch32/cortex_a17.S
index 1877570..05e9616 100644
--- a/lib/cpus/aarch32/cortex_a17.S
+++ b/lib/cpus/aarch32/cortex_a17.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -106,8 +106,6 @@
add_erratum_entry cortex_a17, CVE(2017, 5715), WORKAROUND_CVE_2017_5715
-errata_report_shim cortex_a17
-
func cortex_a17_reset_func
mov r5, lr
bl cpu_get_rev_var
diff --git a/lib/cpus/aarch32/cortex_a32.S b/lib/cpus/aarch32/cortex_a32.S
index d08b4ff..c92a8c1 100644
--- a/lib/cpus/aarch32/cortex_a32.S
+++ b/lib/cpus/aarch32/cortex_a32.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -117,8 +117,6 @@
b cortex_a32_disable_smp
endfunc cortex_a32_cluster_pwr_dwn
-errata_report_shim cortex_a32
-
declare_cpu_ops cortex_a32, CORTEX_A32_MIDR, \
cortex_a32_reset_func, \
cortex_a32_core_pwr_dwn, \
diff --git a/lib/cpus/aarch32/cortex_a5.S b/lib/cpus/aarch32/cortex_a5.S
index 625ea7b..146eb9c 100644
--- a/lib/cpus/aarch32/cortex_a5.S
+++ b/lib/cpus/aarch32/cortex_a5.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -69,8 +69,6 @@
b cortex_a5_disable_smp
endfunc cortex_a5_cluster_pwr_dwn
-errata_report_shim cortex_a5
-
declare_cpu_ops cortex_a5, CORTEX_A5_MIDR, \
cortex_a5_reset_func, \
cortex_a5_core_pwr_dwn, \
diff --git a/lib/cpus/aarch32/cortex_a53.S b/lib/cpus/aarch32/cortex_a53.S
index 89b238a..60be2b3 100644
--- a/lib/cpus/aarch32/cortex_a53.S
+++ b/lib/cpus/aarch32/cortex_a53.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -297,8 +297,6 @@
b cortex_a53_disable_smp
endfunc cortex_a53_cluster_pwr_dwn
-errata_report_shim cortex_a53
-
declare_cpu_ops cortex_a53, CORTEX_A53_MIDR, \
cortex_a53_reset_func, \
cortex_a53_core_pwr_dwn, \
diff --git a/lib/cpus/aarch32/cortex_a57.S b/lib/cpus/aarch32/cortex_a57.S
index 1e5377b..d563482 100644
--- a/lib/cpus/aarch32/cortex_a57.S
+++ b/lib/cpus/aarch32/cortex_a57.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -606,8 +606,6 @@
b cortex_a57_disable_ext_debug
endfunc cortex_a57_cluster_pwr_dwn
-errata_report_shim cortex_a57
-
declare_cpu_ops cortex_a57, CORTEX_A57_MIDR, \
cortex_a57_reset_func, \
cortex_a57_core_pwr_dwn, \
diff --git a/lib/cpus/aarch32/cortex_a7.S b/lib/cpus/aarch32/cortex_a7.S
index 4842ca6..f99ae79 100644
--- a/lib/cpus/aarch32/cortex_a7.S
+++ b/lib/cpus/aarch32/cortex_a7.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -73,8 +73,6 @@
b cortex_a7_disable_smp
endfunc cortex_a7_cluster_pwr_dwn
-errata_report_shim cortex_a7
-
declare_cpu_ops cortex_a7, CORTEX_A7_MIDR, \
cortex_a7_reset_func, \
cortex_a7_core_pwr_dwn, \
diff --git a/lib/cpus/aarch32/cortex_a72.S b/lib/cpus/aarch32/cortex_a72.S
index 77cf84d..8d399fd 100644
--- a/lib/cpus/aarch32/cortex_a72.S
+++ b/lib/cpus/aarch32/cortex_a72.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -256,8 +256,6 @@
b cortex_a72_disable_ext_debug
endfunc cortex_a72_cluster_pwr_dwn
-errata_report_shim cortex_a72
-
declare_cpu_ops cortex_a72, CORTEX_A72_MIDR, \
cortex_a72_reset_func, \
cortex_a72_core_pwr_dwn, \
diff --git a/lib/cpus/aarch32/cortex_a9.S b/lib/cpus/aarch32/cortex_a9.S
index 1e9757a..dc5ff27 100644
--- a/lib/cpus/aarch32/cortex_a9.S
+++ b/lib/cpus/aarch32/cortex_a9.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -57,8 +57,6 @@
add_erratum_entry cortex_a9, CVE(2017, 5715), WORKAROUND_CVE_2017_5715
-errata_report_shim cortex_a9
-
func cortex_a9_reset_func
#if IMAGE_BL32 && WORKAROUND_CVE_2017_5715
ldr r0, =wa_cve_2017_5715_bpiall_vbar
diff --git a/lib/cpus/aarch64/a64fx.S b/lib/cpus/aarch64/a64fx.S
index 54c20c3..4893a44 100644
--- a/lib/cpus/aarch64/a64fx.S
+++ b/lib/cpus/aarch64/a64fx.S
@@ -16,15 +16,6 @@
func a64fx_cluster_pwr_dwn
endfunc a64fx_cluster_pwr_dwn
-#if REPORT_ERRATA
-/*
- * Errata printing function for A64FX. Must follow AAPCS.
- */
-func a64fx_errata_report
- ret
-endfunc a64fx_errata_report
-#endif
-
/* ---------------------------------------------
* This function provides cpu specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/aem_generic.S b/lib/cpus/aarch64/aem_generic.S
index d47279a..d5634cf 100644
--- a/lib/cpus/aarch64/aem_generic.S
+++ b/lib/cpus/aarch64/aem_generic.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -74,15 +74,6 @@
b dcsw_op_all
endfunc aem_generic_cluster_pwr_dwn
-#if REPORT_ERRATA
-/*
- * Errata printing function for AEM. Must follow AAPCS.
- */
-func aem_generic_errata_report
- ret
-endfunc aem_generic_errata_report
-#endif
-
/* ---------------------------------------------
* This function provides cpu specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/cortex_a35.S b/lib/cpus/aarch64/cortex_a35.S
index 6ffb944..c3d8c8d 100644
--- a/lib/cpus/aarch64/cortex_a35.S
+++ b/lib/cpus/aarch64/cortex_a35.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -111,8 +111,6 @@
b cortex_a35_disable_smp
endfunc cortex_a35_cluster_pwr_dwn
-errata_report_shim cortex_a35
-
/* ---------------------------------------------
* This function provides cortex_a35 specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/cortex_a510.S b/lib/cpus/aarch64/cortex_a510.S
index a59b92c..b49d45a 100644
--- a/lib/cpus/aarch64/cortex_a510.S
+++ b/lib/cpus/aarch64/cortex_a510.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -204,8 +204,6 @@
ret
endfunc cortex_a510_core_pwr_dwn
-errata_report_shim cortex_a510
-
cpu_reset_func_start cortex_a510
/* Disable speculative loads */
msr SSBS, xzr
diff --git a/lib/cpus/aarch64/cortex_a520.S b/lib/cpus/aarch64/cortex_a520.S
index 74ecbf7..811c836 100644
--- a/lib/cpus/aarch64/cortex_a520.S
+++ b/lib/cpus/aarch64/cortex_a520.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,6 +11,9 @@
#include <cpu_macros.S>
#include <plat_macros.S>
+/* .global erratum_cortex_a520_2938996_wa */
+.global check_erratum_cortex_a520_2938996
+
/* Hardware handled coherency */
#if HW_ASSISTED_COHERENCY == 0
#error "Cortex A520 must be compiled with HW_ASSISTED_COHERENCY enabled"
@@ -32,6 +35,25 @@
workaround_reset_end cortex_a520, ERRATUM(2858100)
check_erratum_ls cortex_a520, ERRATUM(2858100), CPU_REV(0, 1)
+
+workaround_runtime_start cortex_a520, ERRATUM(2938996), ERRATA_A520_2938996, CORTEX_A520_MIDR
+workaround_runtime_end cortex_a520, ERRATUM(2938996)
+
+check_erratum_custom_start cortex_a520, ERRATUM(2938996)
+
+ /* This erratum needs to be enabled for r0p0 and r0p1.
+ * Check if revision is less than or equal to r0p1.
+ */
+
+#if ERRATA_A520_2938996
+ mov x1, #1
+ b cpu_rev_var_ls
+#else
+ mov x0, #ERRATA_MISSING
+#endif
+ ret
+check_erratum_custom_end cortex_a520, ERRATUM(2938996)
+
/* ----------------------------------------------------
* HW will do the cache maintenance while powering down
* ----------------------------------------------------
@@ -46,8 +68,6 @@
ret
endfunc cortex_a520_core_pwr_dwn
-errata_report_shim cortex_a520
-
cpu_reset_func_start cortex_a520
/* Disable speculative loads */
msr SSBS, xzr
diff --git a/lib/cpus/aarch64/cortex_a53.S b/lib/cpus/aarch64/cortex_a53.S
index e6fb08a..4a5b318 100644
--- a/lib/cpus/aarch64/cortex_a53.S
+++ b/lib/cpus/aarch64/cortex_a53.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -199,8 +199,6 @@
b cortex_a53_disable_smp
endfunc cortex_a53_cluster_pwr_dwn
-errata_report_shim cortex_a53
-
/* ---------------------------------------------
* This function provides cortex_a53 specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/cortex_a55.S b/lib/cpus/aarch64/cortex_a55.S
index 712b6e0..d5a74e9 100644
--- a/lib/cpus/aarch64/cortex_a55.S
+++ b/lib/cpus/aarch64/cortex_a55.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -116,8 +116,6 @@
cpu_reset_func_start cortex_a55
cpu_reset_func_end cortex_a55
-errata_report_shim cortex_a55
-
/* ---------------------------------------------
* HW will do the cache maintenance while powering down
* ---------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a57.S b/lib/cpus/aarch64/cortex_a57.S
index 8fafaca..374cc5d 100644
--- a/lib/cpus/aarch64/cortex_a57.S
+++ b/lib/cpus/aarch64/cortex_a57.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -284,8 +284,6 @@
b cortex_a57_disable_ext_debug
endfunc cortex_a57_cluster_pwr_dwn
-errata_report_shim cortex_a57
-
/* ---------------------------------------------
* This function provides cortex_a57 specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/cortex_a65.S b/lib/cpus/aarch64/cortex_a65.S
index 666324c..3023ecb 100644
--- a/lib/cpus/aarch64/cortex_a65.S
+++ b/lib/cpus/aarch64/cortex_a65.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -45,26 +45,6 @@
ret
endfunc cortex_a65_cpu_pwr_dwn
-#if REPORT_ERRATA
-/*
- * Errata printing function for Cortex-A65. Must follow AAPCS.
- */
-func cortex_a65_errata_report
- stp x8, x30, [sp, #-16]!
-
- bl cpu_get_rev_var
- mov x8, x0
-
- /*
- * Report all errata. The revision-variant information is passed to
- * checking functions of each errata.
- */
- report_errata ERRATA_DSU_936184, cortex_a65, dsu_936184
-
- ldp x8, x30, [sp], #16
- ret
-endfunc cortex_a65_errata_report
-#endif
.section .rodata.cortex_a65_regs, "aS"
cortex_a65_regs: /* The ascii list of register names to be reported */
diff --git a/lib/cpus/aarch64/cortex_a65ae.S b/lib/cpus/aarch64/cortex_a65ae.S
index 85d1894..1cbb06a 100644
--- a/lib/cpus/aarch64/cortex_a65ae.S
+++ b/lib/cpus/aarch64/cortex_a65ae.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -41,8 +41,6 @@
ret
endfunc cortex_a65ae_cpu_pwr_dwn
-errata_report_shim cortex_a65ae
-
.section .rodata.cortex_a65ae_regs, "aS"
cortex_a65ae_regs: /* The ascii list of register names to be reported */
.asciz "cpuectlr_el1", ""
diff --git a/lib/cpus/aarch64/cortex_a710.S b/lib/cpus/aarch64/cortex_a710.S
index b99fbb3..4c33dda 100644
--- a/lib/cpus/aarch64/cortex_a710.S
+++ b/lib/cpus/aarch64/cortex_a710.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -229,8 +229,6 @@
ret
endfunc cortex_a710_core_pwr_dwn
-errata_report_shim cortex_a710
-
cpu_reset_func_start cortex_a710
/* Disable speculative loads */
msr SSBS, xzr
diff --git a/lib/cpus/aarch64/cortex_a715.S b/lib/cpus/aarch64/cortex_a715.S
index 16be161..8c9988d 100644
--- a/lib/cpus/aarch64/cortex_a715.S
+++ b/lib/cpus/aarch64/cortex_a715.S
@@ -148,8 +148,6 @@
ret
endfunc cortex_a715_core_pwr_dwn
-errata_report_shim cortex_a715
-
/* ---------------------------------------------
* This function provides Cortex-A715 specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/cortex_a72.S b/lib/cpus/aarch64/cortex_a72.S
index 997f261..c300ea7 100644
--- a/lib/cpus/aarch64/cortex_a72.S
+++ b/lib/cpus/aarch64/cortex_a72.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -271,8 +271,6 @@
b cortex_a72_disable_ext_debug
endfunc cortex_a72_cluster_pwr_dwn
-errata_report_shim cortex_a72
-
/* ---------------------------------------------
* This function provides cortex_a72 specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/cortex_a720.S b/lib/cpus/aarch64/cortex_a720.S
index 53a1b78..9befb36 100644
--- a/lib/cpus/aarch64/cortex_a720.S
+++ b/lib/cpus/aarch64/cortex_a720.S
@@ -26,6 +26,18 @@
wa_cve_2022_23960_bhb_vector_table CORTEX_A720_BHB_LOOP_COUNT, cortex_a720
#endif /* WORKAROUND_CVE_2022_23960 */
+workaround_reset_start cortex_a720, ERRATUM(2792132), ERRATA_A720_2792132
+ sysreg_bit_set CORTEX_A720_CPUACTLR2_EL1, BIT(26)
+workaround_reset_end cortex_a720, ERRATUM(2792132)
+
+check_erratum_ls cortex_a720, ERRATUM(2792132), CPU_REV(0, 1)
+
+workaround_reset_start cortex_a720, ERRATUM(2844092), ERRATA_A720_2844092
+ sysreg_bit_set CORTEX_A720_CPUACTLR4_EL1, BIT(11)
+workaround_reset_end cortex_a720, ERRATUM(2844092)
+
+check_erratum_ls cortex_a720, ERRATUM(2844092), CPU_REV(0, 1)
+
workaround_reset_start cortex_a720, ERRATUM(2926083), ERRATA_A720_2926083
/* Erratum 2926083 workaround is required only if SPE is enabled */
#if ENABLE_SPE_FOR_NS != 0
@@ -80,8 +92,6 @@
ret
endfunc cortex_a720_core_pwr_dwn
-errata_report_shim cortex_a720
-
/* ---------------------------------------------
* This function provides Cortex A720-specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/cortex_a725.S b/lib/cpus/aarch64/cortex_a725.S
index c08945f..af98d14 100644
--- a/lib/cpus/aarch64/cortex_a725.S
+++ b/lib/cpus/aarch64/cortex_a725.S
@@ -40,8 +40,6 @@
ret
endfunc cortex_a725_core_pwr_dwn
-errata_report_shim cortex_a725
-
/* ---------------------------------------------
* This function provides Cortex-A725 specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/cortex_a73.S b/lib/cpus/aarch64/cortex_a73.S
index 3a6b922..2130ceb 100644
--- a/lib/cpus/aarch64/cortex_a73.S
+++ b/lib/cpus/aarch64/cortex_a73.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -178,9 +178,6 @@
b cortex_a73_disable_smp
endfunc cortex_a73_cluster_pwr_dwn
-
-errata_report_shim cortex_a73
-
/* ---------------------------------------------
* This function provides cortex_a73 specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/cortex_a75.S b/lib/cpus/aarch64/cortex_a75.S
index c90be67..9115303 100644
--- a/lib/cpus/aarch64/cortex_a75.S
+++ b/lib/cpus/aarch64/cortex_a75.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -146,8 +146,6 @@
ret
endfunc cortex_a75_core_pwr_dwn
-errata_report_shim cortex_a75
-
/* ---------------------------------------------
* This function provides cortex_a75 specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/cortex_a76.S b/lib/cpus/aarch64/cortex_a76.S
index 8b3d730..97e036e 100644
--- a/lib/cpus/aarch64/cortex_a76.S
+++ b/lib/cpus/aarch64/cortex_a76.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -511,8 +511,6 @@
ret
endfunc cortex_a76_core_pwr_dwn
-errata_report_shim cortex_a76
-
/* ---------------------------------------------
* This function provides cortex_a76 specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/cortex_a76ae.S b/lib/cpus/aarch64/cortex_a76ae.S
index 08a6ef9..2fe3dbc 100644
--- a/lib/cpus/aarch64/cortex_a76ae.S
+++ b/lib/cpus/aarch64/cortex_a76ae.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -41,8 +41,6 @@
cpu_reset_func_start cortex_a76ae
cpu_reset_func_end cortex_a76ae
-errata_report_shim cortex_a76ae
-
/* ----------------------------------------------------
* HW will do the cache maintenance while powering down
* ----------------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a77.S b/lib/cpus/aarch64/cortex_a77.S
index 86c2561..d1fc41a 100644
--- a/lib/cpus/aarch64/cortex_a77.S
+++ b/lib/cpus/aarch64/cortex_a77.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -167,7 +167,6 @@
ret
endfunc cortex_a77_core_pwr_dwn
-errata_report_shim cortex_a77
/* ---------------------------------------------
* This function provides Cortex-A77 specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/cortex_a78.S b/lib/cpus/aarch64/cortex_a78.S
index b5c24e1..5a63e78 100644
--- a/lib/cpus/aarch64/cortex_a78.S
+++ b/lib/cpus/aarch64/cortex_a78.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -198,8 +198,6 @@
ret
endfunc cortex_a78_core_pwr_dwn
-errata_report_shim cortex_a78
-
/* ---------------------------------------------
* This function provides cortex_a78 specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/cortex_a78_ae.S b/lib/cpus/aarch64/cortex_a78_ae.S
index d3a3e5d..bc10186 100644
--- a/lib/cpus/aarch64/cortex_a78_ae.S
+++ b/lib/cpus/aarch64/cortex_a78_ae.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
* Copyright (c) 2021-2023, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -128,8 +128,6 @@
ret
endfunc cortex_a78_ae_core_pwr_dwn
-errata_report_shim cortex_a78_ae
-
/* -------------------------------------------------------
* This function provides cortex_a78_ae specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/cortex_a78c.S b/lib/cpus/aarch64/cortex_a78c.S
index 0dc34f7..97d5743 100644
--- a/lib/cpus/aarch64/cortex_a78c.S
+++ b/lib/cpus/aarch64/cortex_a78c.S
@@ -121,8 +121,6 @@
cpu_reset_func_start cortex_a78c
cpu_reset_func_end cortex_a78c
-errata_report_shim cortex_a78c
-
/* ----------------------------------------------------
* HW will do the cache maintenance while powering down
* ----------------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_gelas.S b/lib/cpus/aarch64/cortex_gelas.S
index 8870019..891e9a6 100644
--- a/lib/cpus/aarch64/cortex_gelas.S
+++ b/lib/cpus/aarch64/cortex_gelas.S
@@ -58,8 +58,6 @@
ret
endfunc cortex_gelas_core_pwr_dwn
-errata_report_shim cortex_gelas
-
/* ---------------------------------------------
* This function provides Gelas specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/cortex_x1.S b/lib/cpus/aarch64/cortex_x1.S
index 42634f1..ca6cac9 100644
--- a/lib/cpus/aarch64/cortex_x1.S
+++ b/lib/cpus/aarch64/cortex_x1.S
@@ -66,8 +66,6 @@
ret
endfunc cortex_x1_core_pwr_dwn
-errata_report_shim cortex_x1
-
/* ---------------------------------------------
* This function provides Cortex X1 specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/cortex_x2.S b/lib/cpus/aarch64/cortex_x2.S
index d018182..ab0b19d 100644
--- a/lib/cpus/aarch64/cortex_x2.S
+++ b/lib/cpus/aarch64/cortex_x2.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -182,8 +182,6 @@
ret
endfunc cortex_x2_core_pwr_dwn
-errata_report_shim cortex_x2
-
cpu_reset_func_start cortex_x2
/* Disable speculative loads */
msr SSBS, xzr
diff --git a/lib/cpus/aarch64/cortex_x3.S b/lib/cpus/aarch64/cortex_x3.S
index 49e9ad1..248f107 100644
--- a/lib/cpus/aarch64/cortex_x3.S
+++ b/lib/cpus/aarch64/cortex_x3.S
@@ -125,8 +125,6 @@
ret
endfunc cortex_x3_core_pwr_dwn
-errata_report_shim cortex_x3
-
/* ---------------------------------------------
* This function provides Cortex-X3-
* specific register information for crash
diff --git a/lib/cpus/aarch64/cortex_x4.S b/lib/cpus/aarch64/cortex_x4.S
index 20f1ae1..1220d38 100644
--- a/lib/cpus/aarch64/cortex_x4.S
+++ b/lib/cpus/aarch64/cortex_x4.S
@@ -22,10 +22,30 @@
#error "Cortex X4 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
+.global check_erratum_cortex_x4_2726228
+
#if WORKAROUND_CVE_2022_23960
wa_cve_2022_23960_bhb_vector_table CORTEX_X4_BHB_LOOP_COUNT, cortex_x4
#endif /* WORKAROUND_CVE_2022_23960 */
+workaround_runtime_start cortex_x4, ERRATUM(2726228), ERRATA_X4_2726228, CORTEX_X4_MIDR
+workaround_runtime_end cortex_x4, ERRATUM(2726228)
+
+check_erratum_custom_start cortex_x4, ERRATUM(2726228)
+
+ /* This erratum needs to be enabled for r0p0 and r0p1.
+ * Check if revision is less than or equal to r0p1.
+ */
+
+#if ERRATA_X4_2726228
+ mov x1, #1
+ b cpu_rev_var_ls
+#else
+ mov x0, #ERRATA_MISSING
+#endif
+ ret
+check_erratum_custom_end cortex_x4, ERRATUM(2726228)
+
workaround_runtime_start cortex_x4, ERRATUM(2740089), ERRATA_X4_2740089
/* dsb before isb of power down sequence */
dsb sy
@@ -39,6 +59,16 @@
check_erratum_ls cortex_x4, ERRATUM(2763018), CPU_REV(0, 1)
+workaround_reset_start cortex_x4, ERRATUM(2816013), ERRATA_X4_2816013
+ mrs x1, id_aa64pfr1_el1
+ ubfx x2, x1, ID_AA64PFR1_EL1_MTE_SHIFT, #4
+ cbz x2, #1f
+ sysreg_bit_set CORTEX_X4_CPUACTLR5_EL1, BIT(14)
+1:
+workaround_reset_end cortex_x4, ERRATUM(2816013)
+
+check_erratum_ls cortex_x4, ERRATUM(2816013), CPU_REV(0, 1)
+
workaround_reset_start cortex_x4, CVE(2022, 23960), WORKAROUND_CVE_2022_23960
#if IMAGE_BL31
/*
@@ -73,8 +103,6 @@
ret
endfunc cortex_x4_core_pwr_dwn
-errata_report_shim cortex_x4
-
/* ---------------------------------------------
* This function provides Cortex X4-specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/cortex_x925.S b/lib/cpus/aarch64/cortex_x925.S
index 36b442e..8109ffb 100644
--- a/lib/cpus/aarch64/cortex_x925.S
+++ b/lib/cpus/aarch64/cortex_x925.S
@@ -40,8 +40,6 @@
ret
endfunc cortex_x925_core_pwr_dwn
-errata_report_shim cortex_x925
-
/* ---------------------------------------------
* This function provides Cortex-X925 specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/denver.S b/lib/cpus/aarch64/denver.S
index 884281d..ca250d3 100644
--- a/lib/cpus/aarch64/denver.S
+++ b/lib/cpus/aarch64/denver.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -296,8 +296,6 @@
ret
endfunc denver_cluster_pwr_dwn
-errata_report_shim denver
-
/* ---------------------------------------------
* This function provides Denver specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/generic.S b/lib/cpus/aarch64/generic.S
index ef1f048..5d7a857 100644
--- a/lib/cpus/aarch64/generic.S
+++ b/lib/cpus/aarch64/generic.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -79,7 +79,6 @@
* Unimplemented functions.
* ---------------------------------------------
*/
-.equ generic_errata_report, 0
.equ generic_cpu_reg_dump, 0
.equ generic_reset_func, 0
diff --git a/lib/cpus/aarch64/neoverse_e1.S b/lib/cpus/aarch64/neoverse_e1.S
index 45bd8d3..4bc95d0 100644
--- a/lib/cpus/aarch64/neoverse_e1.S
+++ b/lib/cpus/aarch64/neoverse_e1.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -42,8 +42,6 @@
ret
endfunc neoverse_e1_cpu_pwr_dwn
-errata_report_shim neoverse_e1
-
.section .rodata.neoverse_e1_regs, "aS"
neoverse_e1_regs: /* The ascii list of register names to be reported */
.asciz "cpuectlr_el1", ""
diff --git a/lib/cpus/aarch64/neoverse_n1.S b/lib/cpus/aarch64/neoverse_n1.S
index 36a7ee7..50e1ae3 100644
--- a/lib/cpus/aarch64/neoverse_n1.S
+++ b/lib/cpus/aarch64/neoverse_n1.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -242,8 +242,6 @@
ret
endfunc neoverse_n1_core_pwr_dwn
-errata_report_shim neoverse_n1
-
/*
* Handle trap of EL0 IC IVAU instructions to EL3 by executing a TLB
* inner-shareable invalidation to an arbitrary address followed by a DSB.
diff --git a/lib/cpus/aarch64/neoverse_n2.S b/lib/cpus/aarch64/neoverse_n2.S
index a85d956..7d7cc44 100644
--- a/lib/cpus/aarch64/neoverse_n2.S
+++ b/lib/cpus/aarch64/neoverse_n2.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -282,8 +282,6 @@
ret
endfunc neoverse_n2_core_pwr_dwn
-errata_report_shim neoverse_n2
-
/* ---------------------------------------------
* This function provides Neoverse N2 specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/neoverse_n3.S b/lib/cpus/aarch64/neoverse_n3.S
index 0b33b7e..d96c9d4 100644
--- a/lib/cpus/aarch64/neoverse_n3.S
+++ b/lib/cpus/aarch64/neoverse_n3.S
@@ -45,8 +45,6 @@
ret
endfunc neoverse_n3_core_pwr_dwn
-errata_report_shim neoverse_n3
-
/* ---------------------------------------------
* This function provides Neoverse-N3 specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/neoverse_v1.S b/lib/cpus/aarch64/neoverse_v1.S
index c2fbb11..89299b7 100644
--- a/lib/cpus/aarch64/neoverse_v1.S
+++ b/lib/cpus/aarch64/neoverse_v1.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -259,8 +259,6 @@
ret
endfunc neoverse_v1_core_pwr_dwn
-errata_report_shim neoverse_v1
-
cpu_reset_func_start neoverse_v1
/* Disable speculative loads */
msr SSBS, xzr
diff --git a/lib/cpus/aarch64/neoverse_v2.S b/lib/cpus/aarch64/neoverse_v2.S
index 3179918..d8c32a4 100644
--- a/lib/cpus/aarch64/neoverse_v2.S
+++ b/lib/cpus/aarch64/neoverse_v2.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -116,7 +116,6 @@
#endif
cpu_reset_func_end neoverse_v2
-errata_report_shim neoverse_v2
/* ---------------------------------------------
* This function provides Neoverse V2-
* specific register information for crash
diff --git a/lib/cpus/aarch64/neoverse_v3.S b/lib/cpus/aarch64/neoverse_v3.S
index 67258c8..01ac38f 100644
--- a/lib/cpus/aarch64/neoverse_v3.S
+++ b/lib/cpus/aarch64/neoverse_v3.S
@@ -60,8 +60,6 @@
msr SSBS, xzr
cpu_reset_func_end neoverse_v3
-errata_report_shim neoverse_v3
-
/* ---------------------------------------------
* This function provides Neoverse V3 specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/nevis.S b/lib/cpus/aarch64/nevis.S
index 36830a9..0180ab7 100644
--- a/lib/cpus/aarch64/nevis.S
+++ b/lib/cpus/aarch64/nevis.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2023-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -40,8 +40,6 @@
ret
endfunc nevis_core_pwr_dwn
-errata_report_shim nevis
-
.section .rodata.nevis_regs, "aS"
nevis_regs: /* The ASCII list of register names to be reported */
.asciz "cpuectlr_el1", ""
diff --git a/lib/cpus/aarch64/qemu_max.S b/lib/cpus/aarch64/qemu_max.S
index 00963bc..fb03cf1 100644
--- a/lib/cpus/aarch64/qemu_max.S
+++ b/lib/cpus/aarch64/qemu_max.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -47,8 +47,6 @@
b dcsw_op_all
endfunc qemu_max_cluster_pwr_dwn
-errata_report_shim qemu_max
-
/* ---------------------------------------------
* This function provides cpu specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/rainier.S b/lib/cpus/aarch64/rainier.S
index c770f54..ea687be 100644
--- a/lib/cpus/aarch64/rainier.S
+++ b/lib/cpus/aarch64/rainier.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -80,8 +80,6 @@
ret
endfunc rainier_core_pwr_dwn
-errata_report_shim rainier
-
/* ---------------------------------------------
* This function provides Rainier specific
* register information for crash reporting.
diff --git a/lib/cpus/aarch64/travis.S b/lib/cpus/aarch64/travis.S
index ba06f55..e8b3860 100644
--- a/lib/cpus/aarch64/travis.S
+++ b/lib/cpus/aarch64/travis.S
@@ -54,8 +54,6 @@
ret
endfunc travis_core_pwr_dwn
-errata_report_shim travis
-
.section .rodata.travis_regs, "aS"
travis_regs: /* The ASCII list of register names to be reported */
.asciz "cpuectlr_el1", ""
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index f736b5a..c55597a 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -823,6 +823,10 @@
# cpu and is fixed in r0p1.
CPU_FLAG_LIST += ERRATA_X4_2701112
+# Flag to apply erratum 2726228 workaround during warmboot. This erratum
+# applies to all revisions <= r0p1 of the Cortex-X4 cpu, it is fixed in r0p2.
+CPU_FLAG_LIST += ERRATA_X4_2726228
+
# Flag to apply erratum 2740089 workaround during powerdown. This erratum
# applies to all revisions <= r0p1 of the Cortex-X4 cpu, it is fixed in r0p2.
CPU_FLAG_LIST += ERRATA_X4_2740089
@@ -831,6 +835,10 @@
# to revisions r0p0 and r0p1 of the Cortex-X4 cpu. It is fixed in r0p2.
CPU_FLAG_LIST += ERRATA_X4_2763018
+# Flag to apply erratum 2816013 workaround on reset. This erratum applies
+# to revisions r0p0 and r0p1 of the Cortex-X4 cpu. It is fixed in r0p2.
+CPU_FLAG_LIST += ERRATA_X4_2816013
+
# Flag to apply erratum 1922240 workaround during reset. This erratum applies
# to revision r0p0 of the Cortex-A510 cpu and is fixed in r0p1.
CPU_FLAG_LIST += ERRATA_A510_1922240
@@ -892,6 +900,10 @@
# applies to revision r0p0 and r0p1 of the Cortex-A520 cpu and is still open.
CPU_FLAG_LIST += ERRATA_A520_2858100
+# Flag to apply erratum 2938996 workaround during reset. This erratum
+# applies to revision r0p0 and r0p1 of the Cortex-A520 cpu and is fixed in r0p2.
+CPU_FLAG_LIST += ERRATA_A520_2938996
+
# Flag to apply erratum 2331132 workaround during reset. This erratum applies
# to revisions r0p0, r0p1 and r0p2. It is still open.
CPU_FLAG_LIST += ERRATA_V2_2331132
@@ -952,6 +964,14 @@
# only to revision r0p0, r1p0 and r1p1. It is fixed in r1p2.
CPU_FLAG_LIST += ERRATA_A715_2728106
+# Flag to apply erratum 2792132 workaround during reset. This erratum applies
+# to revisions r0p0 and r0p1. It is fixed in r0p2.
+CPU_FLAG_LIST += ERRATA_A720_2792132
+
+# Flag to apply erratum 2844092 workaround during reset. This erratum applies
+# to revisions r0p0 and r0p1. It is fixed in r0p2.
+CPU_FLAG_LIST += ERRATA_A720_2844092
+
# Flag to apply erratum 2926083 workaround during reset. This erratum applies
# to revisions r0p0 and r0p1. It is fixed in r0p2.
CPU_FLAG_LIST += ERRATA_A720_2926083
diff --git a/lib/cpus/errata_common.c b/lib/cpus/errata_common.c
new file mode 100644
index 0000000..9801245
--- /dev/null
+++ b/lib/cpus/errata_common.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Runtime C routines for errata workarounds and common routines */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <cortex_a520.h>
+#include <cortex_x4.h>
+#include <lib/cpus/cpu_ops.h>
+#include <lib/cpus/errata.h>
+
+#if ERRATA_A520_2938996 || ERRATA_X4_2726228
+unsigned int check_if_affected_core(void)
+{
+ uint32_t midr_val = read_midr();
+ long rev_var = cpu_get_rev_var();
+
+ if (EXTRACT_PARTNUM(midr_val) == EXTRACT_PARTNUM(CORTEX_A520_MIDR)) {
+ return check_erratum_cortex_a520_2938996(rev_var);
+ } else if (EXTRACT_PARTNUM(midr_val) == EXTRACT_PARTNUM(CORTEX_X4_MIDR)) {
+ return check_erratum_cortex_x4_2726228(rev_var);
+ }
+
+ return ERRATA_NOT_APPLIES;
+}
+#endif
diff --git a/lib/cpus/errata_report.c b/lib/cpus/errata_report.c
index 27cfc91..e0a9076 100644
--- a/lib/cpus/errata_report.c
+++ b/lib/cpus/errata_report.c
@@ -67,7 +67,7 @@
* save space. This functionality is only useful on development and platform
* bringup builds, when FEATURE_DETECTION should be used anyway
*/
-void __unused generic_errata_report(void)
+void generic_errata_report(void)
{
struct cpu_ops *cpu_ops = get_cpu_ops_ptr();
struct erratum_entry *entry = cpu_ops->errata_list_start;
@@ -159,70 +159,16 @@
*/
void print_errata_status(void)
{
- struct cpu_ops *cpu_ops;
#ifdef IMAGE_BL1
- /*
- * BL1 doesn't have per-CPU data. So retrieve the CPU operations
- * directly.
- */
- cpu_ops = get_cpu_ops_ptr();
-
- if (cpu_ops->errata_func != NULL) {
- cpu_ops->errata_func();
- }
+ generic_errata_report();
#else /* IMAGE_BL1 */
- cpu_ops = (void *) get_cpu_data(cpu_ops_ptr);
+ struct cpu_ops *cpu_ops = (void *) get_cpu_data(cpu_ops_ptr);
assert(cpu_ops != NULL);
- if (cpu_ops->errata_func == NULL) {
- return;
- }
-
if (errata_needs_reporting(cpu_ops->errata_lock, cpu_ops->errata_reported)) {
- cpu_ops->errata_func();
+ generic_errata_report();
}
#endif /* IMAGE_BL1 */
}
-
-/*
- * Old errata status message printer
- * TODO: remove once all cpus have been converted to the new printing method
- */
-void __unused errata_print_msg(unsigned int status, const char *cpu, const char *id)
-{
- /* Errata status strings */
- static const char *const errata_status_str[] = {
- [ERRATA_NOT_APPLIES] = "not applied",
- [ERRATA_APPLIES] = "applied",
- [ERRATA_MISSING] = "missing!"
- };
- static const char *const __unused bl_str = BL_STRING;
- const char *msg __unused;
-
-
- assert(status < ARRAY_SIZE(errata_status_str));
- assert(cpu != NULL);
- assert(id != NULL);
-
- msg = errata_status_str[status];
-
- switch (status) {
- case ERRATA_NOT_APPLIES:
- VERBOSE(ERRATA_FORMAT, bl_str, cpu, id, msg);
- break;
-
- case ERRATA_APPLIES:
- INFO(ERRATA_FORMAT, bl_str, cpu, id, msg);
- break;
-
- case ERRATA_MISSING:
- WARN(ERRATA_FORMAT, bl_str, cpu, id, msg);
- break;
-
- default:
- WARN(ERRATA_FORMAT, bl_str, cpu, id, "unknown");
- break;
- }
-}
#endif /* !REPORT_ERRATA */
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index 62895ff..ab9d4b6 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -9,12 +9,18 @@
#include <assert_macros.S>
#include <context.h>
#include <el3_common_macros.S>
+#include <platform_def.h>
#if CTX_INCLUDE_FPREGS
.global fpregs_context_save
.global fpregs_context_restore
#endif /* CTX_INCLUDE_FPREGS */
+#if CTX_INCLUDE_SVE_REGS
+ .global sve_context_save
+ .global sve_context_restore
+#endif /* CTX_INCLUDE_SVE_REGS */
+
#if ERRATA_SPECULATIVE_AT
.global save_and_update_ptw_el1_sys_regs
#endif /* ERRATA_SPECULATIVE_AT */
@@ -23,6 +29,36 @@
.global restore_gp_pmcr_pauth_regs
.global el3_exit
+/* Following macros will be used if any of CTX_INCLUDE_FPREGS or CTX_INCLUDE_SVE_REGS is enabled */
+#if CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS
+.macro fpregs_state_save base:req hold:req
+ mrs \hold, fpsr
+ str \hold, [\base, #CTX_SIMD_FPSR]
+
+ mrs \hold, fpcr
+ str \hold, [\base, #CTX_SIMD_FPCR]
+
+#if CTX_INCLUDE_AARCH32_REGS && CTX_INCLUDE_FPREGS
+ mrs \hold, fpexc32_el2
+ str \hold, [\base, #CTX_SIMD_FPEXC32]
+#endif
+.endm
+
+.macro fpregs_state_restore base:req hold:req
+ ldr \hold, [\base, #CTX_SIMD_FPSR]
+ msr fpsr, \hold
+
+ ldr \hold, [\base, #CTX_SIMD_FPCR]
+ msr fpcr, \hold
+
+#if CTX_INCLUDE_AARCH32_REGS && CTX_INCLUDE_FPREGS
+ ldr \hold, [\base, #CTX_SIMD_FPEXC32]
+ msr fpexc32_el2, \hold
+#endif
+.endm
+
+#endif /* CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS */
+
/* ------------------------------------------------------------------
* The following function follows the aapcs_64 strictly to use
* x9-x17 (temporary caller-saved registers according to AArch64 PCS)
@@ -39,33 +75,25 @@
*/
#if CTX_INCLUDE_FPREGS
func fpregs_context_save
- stp q0, q1, [x0, #CTX_FP_Q0]
- stp q2, q3, [x0, #CTX_FP_Q2]
- stp q4, q5, [x0, #CTX_FP_Q4]
- stp q6, q7, [x0, #CTX_FP_Q6]
- stp q8, q9, [x0, #CTX_FP_Q8]
- stp q10, q11, [x0, #CTX_FP_Q10]
- stp q12, q13, [x0, #CTX_FP_Q12]
- stp q14, q15, [x0, #CTX_FP_Q14]
- stp q16, q17, [x0, #CTX_FP_Q16]
- stp q18, q19, [x0, #CTX_FP_Q18]
- stp q20, q21, [x0, #CTX_FP_Q20]
- stp q22, q23, [x0, #CTX_FP_Q22]
- stp q24, q25, [x0, #CTX_FP_Q24]
- stp q26, q27, [x0, #CTX_FP_Q26]
- stp q28, q29, [x0, #CTX_FP_Q28]
- stp q30, q31, [x0, #CTX_FP_Q30]
+ stp q0, q1, [x0], #32
+ stp q2, q3, [x0], #32
+ stp q4, q5, [x0], #32
+ stp q6, q7, [x0], #32
+ stp q8, q9, [x0], #32
+ stp q10, q11, [x0], #32
+ stp q12, q13, [x0], #32
+ stp q14, q15, [x0], #32
+ stp q16, q17, [x0], #32
+ stp q18, q19, [x0], #32
+ stp q20, q21, [x0], #32
+ stp q22, q23, [x0], #32
+ stp q24, q25, [x0], #32
+ stp q26, q27, [x0], #32
+ stp q28, q29, [x0], #32
+ stp q30, q31, [x0], #32
- mrs x9, fpsr
- str x9, [x0, #CTX_FP_FPSR]
+ fpregs_state_save x0, x9
- mrs x10, fpcr
- str x10, [x0, #CTX_FP_FPCR]
-
-#if CTX_INCLUDE_AARCH32_REGS
- mrs x11, fpexc32_el2
- str x11, [x0, #CTX_FP_FPEXC32_EL2]
-#endif /* CTX_INCLUDE_AARCH32_REGS */
ret
endfunc fpregs_context_save
@@ -84,51 +112,196 @@
* ------------------------------------------------------------------
*/
func fpregs_context_restore
- ldp q0, q1, [x0, #CTX_FP_Q0]
- ldp q2, q3, [x0, #CTX_FP_Q2]
- ldp q4, q5, [x0, #CTX_FP_Q4]
- ldp q6, q7, [x0, #CTX_FP_Q6]
- ldp q8, q9, [x0, #CTX_FP_Q8]
- ldp q10, q11, [x0, #CTX_FP_Q10]
- ldp q12, q13, [x0, #CTX_FP_Q12]
- ldp q14, q15, [x0, #CTX_FP_Q14]
- ldp q16, q17, [x0, #CTX_FP_Q16]
- ldp q18, q19, [x0, #CTX_FP_Q18]
- ldp q20, q21, [x0, #CTX_FP_Q20]
- ldp q22, q23, [x0, #CTX_FP_Q22]
- ldp q24, q25, [x0, #CTX_FP_Q24]
- ldp q26, q27, [x0, #CTX_FP_Q26]
- ldp q28, q29, [x0, #CTX_FP_Q28]
- ldp q30, q31, [x0, #CTX_FP_Q30]
+ ldp q0, q1, [x0], #32
+ ldp q2, q3, [x0], #32
+ ldp q4, q5, [x0], #32
+ ldp q6, q7, [x0], #32
+ ldp q8, q9, [x0], #32
+ ldp q10, q11, [x0], #32
+ ldp q12, q13, [x0], #32
+ ldp q14, q15, [x0], #32
+ ldp q16, q17, [x0], #32
+ ldp q18, q19, [x0], #32
+ ldp q20, q21, [x0], #32
+ ldp q22, q23, [x0], #32
+ ldp q24, q25, [x0], #32
+ ldp q26, q27, [x0], #32
+ ldp q28, q29, [x0], #32
+ ldp q30, q31, [x0], #32
- ldr x9, [x0, #CTX_FP_FPSR]
- msr fpsr, x9
+ fpregs_state_restore x0, x9
- ldr x10, [x0, #CTX_FP_FPCR]
- msr fpcr, x10
+ ret
+endfunc fpregs_context_restore
+#endif /* CTX_INCLUDE_FPREGS */
+
+#if CTX_INCLUDE_SVE_REGS
+/*
+ * Helper macros for SVE predicates save/restore operations.
+ */
+.macro sve_predicate_op op:req reg:req
+ \op p0, [\reg, #0, MUL VL]
+ \op p1, [\reg, #1, MUL VL]
+ \op p2, [\reg, #2, MUL VL]
+ \op p3, [\reg, #3, MUL VL]
+ \op p4, [\reg, #4, MUL VL]
+ \op p5, [\reg, #5, MUL VL]
+ \op p6, [\reg, #6, MUL VL]
+ \op p7, [\reg, #7, MUL VL]
+ \op p8, [\reg, #8, MUL VL]
+ \op p9, [\reg, #9, MUL VL]
+ \op p10, [\reg, #10, MUL VL]
+ \op p11, [\reg, #11, MUL VL]
+ \op p12, [\reg, #12, MUL VL]
+ \op p13, [\reg, #13, MUL VL]
+ \op p14, [\reg, #14, MUL VL]
+ \op p15, [\reg, #15, MUL VL]
+.endm
-#if CTX_INCLUDE_AARCH32_REGS
- ldr x11, [x0, #CTX_FP_FPEXC32_EL2]
- msr fpexc32_el2, x11
-#endif /* CTX_INCLUDE_AARCH32_REGS */
+.macro sve_vectors_op op:req reg:req
+ \op z0, [\reg, #0, MUL VL]
+ \op z1, [\reg, #1, MUL VL]
+ \op z2, [\reg, #2, MUL VL]
+ \op z3, [\reg, #3, MUL VL]
+ \op z4, [\reg, #4, MUL VL]
+ \op z5, [\reg, #5, MUL VL]
+ \op z6, [\reg, #6, MUL VL]
+ \op z7, [\reg, #7, MUL VL]
+ \op z8, [\reg, #8, MUL VL]
+ \op z9, [\reg, #9, MUL VL]
+ \op z10, [\reg, #10, MUL VL]
+ \op z11, [\reg, #11, MUL VL]
+ \op z12, [\reg, #12, MUL VL]
+ \op z13, [\reg, #13, MUL VL]
+ \op z14, [\reg, #14, MUL VL]
+ \op z15, [\reg, #15, MUL VL]
+ \op z16, [\reg, #16, MUL VL]
+ \op z17, [\reg, #17, MUL VL]
+ \op z18, [\reg, #18, MUL VL]
+ \op z19, [\reg, #19, MUL VL]
+ \op z20, [\reg, #20, MUL VL]
+ \op z21, [\reg, #21, MUL VL]
+ \op z22, [\reg, #22, MUL VL]
+ \op z23, [\reg, #23, MUL VL]
+ \op z24, [\reg, #24, MUL VL]
+ \op z25, [\reg, #25, MUL VL]
+ \op z26, [\reg, #26, MUL VL]
+ \op z27, [\reg, #27, MUL VL]
+ \op z28, [\reg, #28, MUL VL]
+ \op z29, [\reg, #29, MUL VL]
+ \op z30, [\reg, #30, MUL VL]
+ \op z31, [\reg, #31, MUL VL]
+.endm
- /*
- * No explict ISB required here as ERET to
- * switch to secure EL1 or non-secure world
- * covers it
- */
+/* ------------------------------------------------------------------
+ * The following function follows the aapcs_64 strictly to use x9-x17
+ * (temporary caller-saved registers according to AArch64 PCS) to
+ * restore SVE register context. It assumes that 'x0' is
+ * pointing to a 'sve_regs_t' structure to which the register context
+ * will be saved.
+ * ------------------------------------------------------------------
+ */
+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
+ sve_predicate_op str, x9
+
+ /* Save FFR after predicates */
+ mov x13, #CTX_SIMD_FFR
+ add x9, x0, x13
+ rdffr p0.b
+ str p0, [x9]
+
+ /* Save vector registers */
+ 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 */
+ fpregs_state_save x0, x9
ret
-endfunc fpregs_context_restore
-#endif /* CTX_INCLUDE_FPREGS */
+endfunc sve_context_save
+
+/* ------------------------------------------------------------------
+ * The following function follows the aapcs_64 strictly to use x9-x17
+ * (temporary caller-saved registers according to AArch64 PCS) to
+ * restore SVE register context. It assumes that 'x0' is pointing to
+ * a 'sve_regs_t' structure from where the register context will be
+ * restored.
+ * ------------------------------------------------------------------
+ */
+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
+ ldr p0, [x9]
+ wrffr p0.b
+
+ /* Restore predicate registers */
+ mov x13, #CTX_SIMD_PREDICATES
+ add x9, x0, x13
+ sve_predicate_op ldr, x9
+
+ /* Restore vector registers */
+ 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 */
+ fpregs_state_restore x0, x9
+ ret
+endfunc sve_context_restore
+#endif /* CTX_INCLUDE_SVE_REGS */
/*
* Set SCR_EL3.EA bit to enable SErrors at EL3
*/
.macro enable_serror_at_el3
- mrs x8, scr_el3
- orr x8, x8, #SCR_EA_BIT
- msr scr_el3, x8
+ mrs x8, scr_el3
+ orr x8, x8, #SCR_EA_BIT
+ msr scr_el3, x8
.endm
/*
@@ -142,13 +315,13 @@
* always enable DIT in EL3
*/
#if ENABLE_FEAT_DIT
-#if ENABLE_FEAT_DIT == 2
+#if ENABLE_FEAT_DIT >= 2
mrs x8, id_aa64pfr0_el1
and x8, x8, #(ID_AA64PFR0_DIT_MASK << ID_AA64PFR0_DIT_SHIFT)
cbz x8, 1f
#endif
- mov x8, #DIT_BIT
- msr DIT, x8
+ mov x8, #DIT_BIT
+ msr DIT, x8
1:
#endif /* ENABLE_FEAT_DIT */
.endm /* set_unset_pstate_bits */
@@ -166,8 +339,7 @@
.macro restore_mpam3_el3
#if ENABLE_FEAT_MPAM
-#if ENABLE_FEAT_MPAM == 2
-
+#if ENABLE_FEAT_MPAM >= 2
mrs x8, id_aa64pfr0_el1
lsr x8, x8, #(ID_AA64PFR0_MPAM_SHIFT)
and x8, x8, #(ID_AA64PFR0_MPAM_MASK)
diff --git a/lib/el3_runtime/aarch64/context_debug.c b/lib/el3_runtime/aarch64/context_debug.c
index 9ffa297..b37bcb7 100644
--- a/lib/el3_runtime/aarch64/context_debug.c
+++ b/lib/el3_runtime/aarch64/context_debug.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2023-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -28,19 +28,11 @@
return state_names[security_state_idx];
}
-#if CTX_INCLUDE_EL2_REGS
#define PRINT_MEM_USAGE_SEPARATOR() \
do { \
printf("+-----------+-----------+-----------" \
- "+-----------+-----------+-----------+\n"); \
- } while (false)
-#else
-#define PRINT_MEM_USAGE_SEPARATOR() \
- do { \
- printf("+-----------+-----------" \
"+-----------+-----------+-----------+\n"); \
} while (false)
-#endif /* CTX_INCLUDE_EL2_REGS */
#define NAME_PLACEHOLDER_LEN 14
@@ -49,6 +41,11 @@
putchar('-'); \
}
+#define PRINT_SINGLE_MEM_USAGE_SEP_BLOCK() \
+ do { \
+ printf("+-----------"); \
+ } while (false)
+
/********************************************************************************
* This function prints the allocated memory for a specific security state.
* Values are grouped by exception level and core. The memory usage for the
@@ -57,64 +54,119 @@
static size_t report_allocated_memory(unsigned int security_state_idx)
{
size_t core_total = 0U;
+ size_t gp_total = 0U;
size_t el3_total = 0U;
-#if CTX_INCLUDE_EL2_REGS
- size_t el2_total = 0U;
-#endif /* CTX_INCLUDE_EL2_REGS */
- size_t el1_total = 0U;
size_t other_total = 0U;
size_t total = 0U;
size_t per_world_ctx_size = 0U;
+#if CTX_INCLUDE_EL2_REGS
+ size_t el2_total = 0U;
+#else
+ size_t el1_total = 0U;
+#endif /* CTX_INCLUDE_EL2_REGS */
+
+#if CTX_INCLUDE_PAUTH_REGS
+ size_t pauth_total = 0U;
+ PRINT_SINGLE_MEM_USAGE_SEP_BLOCK();
+#endif
+
PRINT_MEM_USAGE_SEPARATOR();
- printf("| Core | EL3 ");
+
+ printf("| Core | GP | EL3 ");
#if CTX_INCLUDE_EL2_REGS
printf("| EL2 ");
+#else
+ printf("| EL1 ");
#endif /* CTX_INCLUDE_EL2_REGS */
- printf("| EL1 | Other | Total |\n");
+
+#if CTX_INCLUDE_PAUTH_REGS
+ printf("| PAUTH ");
+#endif
+
+ printf("| Other | Total |\n");
/* Compute memory usage for each core's context */
for (unsigned int i = 0U; i < PLATFORM_CORE_COUNT; i++) {
size_t size_other = 0U;
size_t el3_size = 0U;
+ size_t gp_size = 0U;
#if CTX_INCLUDE_EL2_REGS
size_t el2_size = 0U;
-#endif /* CTX_INCLUDE_EL2_REGS */
+#else
size_t el1_size = 0U;
+#endif /* CTX_INCLUDE_EL2_REGS */
+
+#if CTX_INCLUDE_PAUTH_REGS
+ size_t pauth_size = 0U;
+ PRINT_SINGLE_MEM_USAGE_SEP_BLOCK();
+#endif
PRINT_MEM_USAGE_SEPARATOR();
+
cpu_context_t *ctx = (cpu_context_t *)cm_get_context_by_index(i,
security_state_idx);
core_total = sizeof(*ctx);
el3_size = sizeof(ctx->el3state_ctx);
-#if CTX_INCLUDE_EL2_REGS
- el2_size = sizeof(ctx->el2_sysregs_ctx);
-#endif /* CTX_INCLUDE_EL2_REGS */
- el1_size = sizeof(ctx->el1_sysregs_ctx);
+ gp_size = sizeof(ctx->gpregs_ctx);
+ size_other = core_total - (el3_size + gp_size);
+ printf("| %9u | %8luB | %8luB ", i, gp_size, el3_size);
- size_other = core_total - el3_size - el1_size;
- printf("| %9u | %8luB ", i, el3_size);
#if CTX_INCLUDE_EL2_REGS
+ el2_size = sizeof(ctx->el2_sysregs_ctx);
size_other -= el2_size;
+ el2_total += el2_size;
printf("| %8luB ", el2_size);
+#else
+ el1_size = sizeof(ctx->el1_sysregs_ctx);
+ size_other -= el1_size;
+ el1_total += el1_size;
+ printf("| %8luB ", el1_size);
#endif /* CTX_INCLUDE_EL2_REGS */
- printf("| %8luB | %8luB | %8luB |\n", el1_size, size_other, core_total);
+#if CTX_INCLUDE_PAUTH_REGS
+ pauth_size = sizeof(ctx->pauth_ctx);
+ size_other -= pauth_size;
+ pauth_total += pauth_size;
+ printf("| %8luB ", pauth_size);
+#endif
+ printf("| %8luB | %8luB |\n", size_other, core_total);
+
+ gp_total += gp_size;
el3_total += el3_size;
-#if CTX_INCLUDE_EL2_REGS
- el2_total += el2_size;
-#endif /* CTX_INCLUDE_EL2_REGS */
- el1_total += el1_size;
other_total += size_other;
total += core_total;
}
+
+#if CTX_INCLUDE_PAUTH_REGS
+ PRINT_SINGLE_MEM_USAGE_SEP_BLOCK();
+#endif
+
PRINT_MEM_USAGE_SEPARATOR();
+
+#if CTX_INCLUDE_PAUTH_REGS
+ PRINT_SINGLE_MEM_USAGE_SEP_BLOCK();
+#endif
+
PRINT_MEM_USAGE_SEPARATOR();
- printf("| All | %8luB ", el3_total);
+
+ printf("| All | %8luB | %8luB ", gp_total, el3_total);
+
#if CTX_INCLUDE_EL2_REGS
printf("| %8luB ", el2_total);
+#else
+ printf("| %8luB ", el1_total);
#endif /* CTX_INCLUDE_EL2_REGS */
- printf("| %8luB | %8luB | %8luB |\n", el1_total, other_total, total);
+
+#if CTX_INCLUDE_PAUTH_REGS
+ printf("| %8luB ", pauth_total);
+#endif
+
+ printf("| %8luB | %8luB |\n", other_total, total);
+
+#if CTX_INCLUDE_PAUTH_REGS
+ PRINT_SINGLE_MEM_USAGE_SEP_BLOCK();
+#endif
PRINT_MEM_USAGE_SEPARATOR();
printf("\n");
@@ -146,18 +198,10 @@
printf("Memory usage for %s:\n", context_name);
total += report_allocated_memory(i);
- printf("------------------------"
-#if CTX_INCLUDE_EL2_REGS
- "------"
-#endif /* CTX_INCLUDE_EL2_REGS */
- );
+ printf("------------------------");
len = NAME_PLACEHOLDER_LEN - printf("End %s", context_name);
PRINT_DASH(len);
- printf(
-#if CTX_INCLUDE_EL2_REGS
- "------"
-#endif /* CTX_INCLUDE_EL2_REGS */
- "-----------------------\n\n");
+ printf("-----------------------\n\n");
}
printf("Total context memory allocated: %luB\n\n", total);
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 15db9e5..218ad11 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -19,6 +19,8 @@
#include <common/debug.h>
#include <context.h>
#include <drivers/arm/gicv3.h>
+#include <lib/cpus/cpu_ops.h>
+#include <lib/cpus/errata.h>
#include <lib/el3_runtime/context_mgmt.h>
#include <lib/el3_runtime/cpu_data.h>
#include <lib/el3_runtime/pubsub_events.h>
@@ -32,6 +34,7 @@
#include <lib/extensions/spe.h>
#include <lib/extensions/sve.h>
#include <lib/extensions/sys_reg_trace.h>
+#include <lib/extensions/tcr2.h>
#include <lib/extensions/trbe.h>
#include <lib/extensions/trf.h>
#include <lib/utils.h>
@@ -49,6 +52,7 @@
static void manage_extensions_secure(cpu_context_t *ctx);
static void manage_extensions_secure_per_world(void);
+#if ((IMAGE_BL1) || (IMAGE_BL31 && (!CTX_INCLUDE_EL2_REGS)))
static void setup_el1_context(cpu_context_t *ctx, const struct entry_point_info *ep)
{
u_register_t sctlr_elx, actlr_elx;
@@ -94,11 +98,7 @@
#endif
/* Store the initialised SCTLR_EL1 value in the cpu_context */
-#if (ERRATA_SPECULATIVE_AT)
- write_ctx_reg(get_errata_speculative_at_ctx(ctx), CTX_ERRATA_SPEC_AT_SCTLR_EL1, sctlr_elx);
-#else
- write_el1_ctx_common(get_el1_sysregs_ctx(ctx), sctlr_el1, sctlr_elx);
-#endif /* ERRATA_SPECULATIVE_AT */
+ write_ctx_sctlr_el1_reg_errata(ctx, sctlr_elx);
/*
* Base the context ACTLR_EL1 on the current value, as it is
@@ -110,6 +110,7 @@
actlr_elx = read_actlr_el1();
write_el1_ctx_common(get_el1_sysregs_ctx(ctx), actlr_el1, actlr_elx);
}
+#endif /* (IMAGE_BL1) || (IMAGE_BL31 && (!CTX_INCLUDE_EL2_REGS)) */
/******************************************************************************
* This function performs initializations that are specific to SECURE state
@@ -142,7 +143,7 @@
* Initialize EL1 context registers unless SPMC is running
* at S-EL2.
*/
-#if !SPMD_SPM_AT_SEL2
+#if (!SPMD_SPM_AT_SEL2)
setup_el1_context(ctx, ep);
#endif
@@ -158,7 +159,6 @@
if (!has_secure_perworld_init) {
manage_extensions_secure_per_world();
}
-
}
#if ENABLE_RME
@@ -262,11 +262,8 @@
#endif
write_ctx_reg(state, CTX_SCR_EL3, scr_el3);
- /* Initialize EL1 context registers */
- setup_el1_context(ctx, ep);
-
/* Initialize EL2 context registers */
-#if CTX_INCLUDE_EL2_REGS
+#if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
/*
* Initialize SCTLR_EL2 context register with reset value.
@@ -299,8 +296,10 @@
write_el2_ctx_fgt(get_el2_sysregs_ctx(ctx), hfgwtr_el2,
HFGWTR_EL2_INIT_VAL);
}
-
-#endif /* CTX_INCLUDE_EL2_REGS */
+#else
+ /* Initialize EL1 context registers */
+ setup_el1_context(ctx, ep);
+#endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
manage_extensions_nonsecure(ctx);
}
@@ -331,7 +330,7 @@
* to boot correctly. However, there are very few registers where this
* is not true and some values need to be recreated.
*/
-#if CTX_INCLUDE_EL2_REGS
+#if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
el2_sysregs_t *el2_ctx = get_el2_sysregs_ctx(ctx);
/*
@@ -347,7 +346,7 @@
* and it may contain access control bits (e.g. CLUSTERPMUEN bit).
*/
write_el2_ctx_common(el2_ctx, actlr_el2, read_actlr_el2());
-#endif /* CTX_INCLUDE_EL2_REGS */
+#endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
/* Start with a clean SCR_EL3 copy as all relevant values are set */
scr_el3 = SCR_RESET_VAL;
@@ -1089,11 +1088,14 @@
}
}
}
+#if (!CTX_INCLUDE_EL2_REGS)
+ /* Restore EL1 system registers, only when CTX_INCLUDE_EL2_REGS=0 */
cm_el1_sysregs_context_restore(security_state);
+#endif
cm_set_next_eret_context(security_state);
}
-#if CTX_INCLUDE_EL2_REGS
+#if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
static void el2_sysregs_context_save_fgt(el2_sysregs_t *ctx)
{
@@ -1520,8 +1522,56 @@
write_gcscr_el2(read_el2_ctx_gcs(el2_sysregs_ctx, gcscr_el2));
write_gcspr_el2(read_el2_ctx_gcs(el2_sysregs_ctx, gcspr_el2));
}
+}
+#endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
+
+#if IMAGE_BL31
+/*********************************************************************************
+* This function allows Architecture features asymmetry among cores.
+* TF-A assumes that all the cores in the platform has architecture feature parity
+* and hence the context is setup on different core (e.g. primary sets up the
+* context for secondary cores).This assumption may not be true for systems where
+* cores are not conforming to same Arch version or there is CPU Erratum which
+* requires certain feature to be be disabled only on a given core.
+*
+* This function is called on secondary cores to override any disparity in context
+* setup by primary, this would be called during warmboot path.
+*********************************************************************************/
+void cm_handle_asymmetric_features(void)
+{
+ cpu_context_t *ctx __maybe_unused = cm_get_context(NON_SECURE);
+
+ assert(ctx != NULL);
+
+#if ENABLE_SPE_FOR_NS == FEAT_STATE_CHECK_ASYMMETRIC
+ if (is_feat_spe_supported()) {
+ spe_enable(ctx);
+ } else {
+ spe_disable(ctx);
+ }
+#endif
+
+#if ERRATA_A520_2938996 || ERRATA_X4_2726228
+ if (check_if_affected_core() == ERRATA_APPLIES) {
+ if (is_feat_trbe_supported()) {
+ trbe_disable(ctx);
+ }
+ }
+#endif
+
+#if ENABLE_FEAT_TCR2 == FEAT_STATE_CHECK_ASYMMETRIC
+ el3_state_t *el3_state = get_el3state_ctx(ctx);
+ u_register_t spsr = read_ctx_reg(el3_state, CTX_SPSR_EL3);
+
+ if (is_feat_tcr2_supported() && (GET_RW(spsr) == MODE_RW_64)) {
+ tcr2_enable(ctx);
+ } else {
+ tcr2_disable(ctx);
+ }
+#endif
+
}
-#endif /* CTX_INCLUDE_EL2_REGS */
+#endif
/*******************************************************************************
* This function is used to exit to Non-secure world. If CTX_INCLUDE_EL2_REGS
@@ -1531,7 +1581,19 @@
******************************************************************************/
void cm_prepare_el3_exit_ns(void)
{
-#if CTX_INCLUDE_EL2_REGS
+#if IMAGE_BL31
+ /*
+ * Check and handle Architecture feature asymmetry among cores.
+ *
+ * In warmboot path secondary cores context is initialized on core which
+ * did CPU_ON SMC call, if there is feature asymmetry in these cores handle
+ * it in this function call.
+ * For Symmetric cores this is an empty function.
+ */
+ cm_handle_asymmetric_features();
+#endif
+
+#if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
#if ENABLE_ASSERTIONS
cpu_context_t *ctx = cm_get_context(NON_SECURE);
assert(ctx != NULL);
@@ -1542,15 +1604,19 @@
(el_implemented(2U) != EL_IMPL_NONE));
#endif /* ENABLE_ASSERTIONS */
- /* Restore EL2 and EL1 sysreg contexts */
+ /* Restore EL2 sysreg contexts */
cm_el2_sysregs_context_restore(NON_SECURE);
- cm_el1_sysregs_context_restore(NON_SECURE);
cm_set_next_eret_context(NON_SECURE);
#else
cm_prepare_el3_exit(NON_SECURE);
-#endif /* CTX_INCLUDE_EL2_REGS */
+#endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
}
+#if ((IMAGE_BL1) || (IMAGE_BL31 && (!CTX_INCLUDE_EL2_REGS)))
+/*******************************************************************************
+ * The next set of six functions are used by runtime services to save and restore
+ * EL1 context on the 'cpu_context' structure for the specified security state.
+ ******************************************************************************/
static void el1_sysregs_context_save(el1_sysregs_t *ctx)
{
write_el1_ctx_common(ctx, spsr_el1, read_spsr_el1());
@@ -1742,9 +1808,8 @@
}
/*******************************************************************************
- * The next four functions are used by runtime services to save and restore
- * EL1 context on the 'cpu_context' structure for the specified security
- * state.
+ * The next couple of functions are used by runtime services to save and restore
+ * EL1 context on the 'cpu_context' structure for the specified security state.
******************************************************************************/
void cm_el1_sysregs_context_save(uint32_t security_state)
{
@@ -1780,6 +1845,8 @@
#endif
}
+#endif /* ((IMAGE_BL1) || (IMAGE_BL31 && (!CTX_INCLUDE_EL2_REGS))) */
+
/*******************************************************************************
* This function populates ELR_EL3 member of 'cpu_context' pertaining to the
* given security state with the given entrypoint
diff --git a/lib/el3_runtime/simd_ctx.c b/lib/el3_runtime/simd_ctx.c
new file mode 100644
index 0000000..f7a87df
--- /dev/null
+++ b/lib/el3_runtime/simd_ctx.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022, Google LLC. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <lib/el3_runtime/aarch64/context.h>
+#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/el3_runtime/cpu_data.h>
+#include <lib/el3_runtime/simd_ctx.h>
+#include <lib/extensions/sve.h>
+#include <plat/common/platform.h>
+
+#if CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS
+
+/* SIMD context managed for Secure and Normal Worlds. */
+#define SIMD_CTXT_COUNT 2
+
+#if SEPARATE_SIMD_SECTION
+__section(".simd_context")
+#else
+__section(".bss.simd_context")
+#endif
+static simd_regs_t simd_context[SIMD_CTXT_COUNT][PLATFORM_CORE_COUNT];
+
+void simd_ctx_save(uint32_t security_state, bool hint_sve)
+{
+ simd_regs_t *regs;
+
+ if (security_state != NON_SECURE && security_state != SECURE) {
+ ERROR("Unsupported security state specified for SIMD context: %u\n",
+ security_state);
+ panic();
+ }
+
+ regs = &simd_context[security_state][plat_my_core_pos()];
+
+#if CTX_INCLUDE_SVE_REGS
+ regs->hint = hint_sve;
+
+ if (hint_sve) {
+ /*
+ * Hint bit denoting absence of SVE live state. Hence, only
+ * save FP context.
+ */
+ fpregs_context_save(regs);
+ } else {
+ sve_context_save(regs);
+ }
+#elif CTX_INCLUDE_FPREGS
+ fpregs_context_save(regs);
+#endif
+}
+
+void simd_ctx_restore(uint32_t security_state)
+{
+ simd_regs_t *regs;
+
+ if (security_state != NON_SECURE && security_state != SECURE) {
+ ERROR("Unsupported security state specified for SIMD context: %u\n",
+ security_state);
+ panic();
+ }
+
+ regs = &simd_context[security_state][plat_my_core_pos()];
+
+#if CTX_INCLUDE_SVE_REGS
+ if (regs->hint) {
+ fpregs_context_restore(regs);
+ } else {
+ sve_context_restore(regs);
+ }
+#elif CTX_INCLUDE_FPREGS
+ fpregs_context_restore(regs);
+#endif
+}
+#endif /* CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS */
diff --git a/lib/extensions/pmuv3/aarch64/pmuv3.c b/lib/extensions/pmuv3/aarch64/pmuv3.c
index 71aa303..f9e32ca 100644
--- a/lib/extensions/pmuv3/aarch64/pmuv3.c
+++ b/lib/extensions/pmuv3/aarch64/pmuv3.c
@@ -23,13 +23,13 @@
void pmuv3_enable(cpu_context_t *ctx)
{
-#if CTX_INCLUDE_EL2_REGS
+#if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
u_register_t mdcr_el2_val;
mdcr_el2_val = read_el2_ctx_common(get_el2_sysregs_ctx(ctx), mdcr_el2);
mdcr_el2_val = init_mdcr_el2_hpmn(mdcr_el2_val);
write_el2_ctx_common(get_el2_sysregs_ctx(ctx), mdcr_el2, mdcr_el2_val);
-#endif /* CTX_INCLUDE_EL2_REGS */
+#endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
}
static u_register_t mtpmu_disable_el3(u_register_t mdcr_el3)
diff --git a/lib/extensions/tcr/tcr2.c b/lib/extensions/tcr/tcr2.c
new file mode 100644
index 0000000..70bc5f8
--- /dev/null
+++ b/lib/extensions/tcr/tcr2.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_features.h>
+#include <arch_helpers.h>
+#include <lib/extensions/tcr2.h>
+
+void tcr2_enable(cpu_context_t *ctx)
+{
+ u_register_t reg;
+ el3_state_t *state;
+
+ state = get_el3state_ctx(ctx);
+
+ /* Set the TCR2EN bit in SCR_EL3 to enable access to TCR2_EL1,
+ * and TCR2_EL2 registers .
+ */
+
+ reg = read_ctx_reg(state, CTX_SCR_EL3);
+ reg |= SCR_TCR2EN_BIT;
+ write_ctx_reg(state, CTX_SCR_EL3, reg);
+}
+
+void tcr2_disable(cpu_context_t *ctx)
+{
+ u_register_t reg;
+ el3_state_t *state;
+
+ state = get_el3state_ctx(ctx);
+
+ /* Clear the TCR2EN bit in SCR_EL3 to disable access to TCR2_EL1,
+ * and TCR2_EL2 registers .
+ */
+
+ reg = read_ctx_reg(state, CTX_SCR_EL3);
+ reg &= ~SCR_TCR2EN_BIT;
+ write_ctx_reg(state, CTX_SCR_EL3, reg);
+}
diff --git a/lib/romlib/Makefile b/lib/romlib/Makefile
index 9859ce1..29fbf78 100644
--- a/lib/romlib/Makefile
+++ b/lib/romlib/Makefile
@@ -45,7 +45,7 @@
.PHONY: all clean distclean
-all: $(BUILD_DIR)/romlib.bin $(LIB_DIR)/libwrappers.a
+all: $(BUILD_DIR)/romlib.bin $(BUILD_DIR)/romlib.ldflags $(LIB_DIR)/libwrappers.a
%.o: %.s | $$(@D)/
$(s)echo " AS $@"
@@ -89,6 +89,10 @@
$(s)echo " TBL $@"
$(q)$(ROMLIB_GEN) gentbl --output $@ --bti=$(ENABLE_BTI) $<
+$(BUILD_DIR)/romlib.ldflags: ../../$(PLAT_DIR)/jmptbl.i
+ $(s)echo " LDFLAGS $@"
+ $(q)$(ROMLIB_GEN) link-flags $< > $@
+
clean:
$(q)rm -f $(BUILD_DIR)/*
diff --git a/lib/romlib/romlib_generator.py b/lib/romlib/romlib_generator.py
index 0682dd4..8d2e88d 100755
--- a/lib/romlib/romlib_generator.py
+++ b/lib/romlib/romlib_generator.py
@@ -182,6 +182,22 @@
template_name = "jmptbl_entry_" + item["type"] + bti + ".S"
output_file.write(self.build_template(template_name, item, True))
+class LinkArgs(RomlibApplication):
+ """ Generates the link arguments to wrap functions. """
+
+ def __init__(self, prog):
+ RomlibApplication.__init__(self, prog)
+ self.args.add_argument("file", help="Input file")
+
+ def main(self):
+ index_file_parser = IndexFileParser()
+ index_file_parser.parse(self.config.file)
+
+ fns = [item["function_name"] for item in index_file_parser.items
+ if not item["patch"] and item["type"] != "reserved"]
+
+ print(" ".join("-Wl,--wrap " + f for f in fns))
+
class WrapperGenerator(RomlibApplication):
"""
Generates a wrapper function for each entry in the index file except for the ones that contain
@@ -214,21 +230,19 @@
if item["type"] == "reserved" or item["patch"]:
continue
- asm = self.config.b + "/" + item["function_name"] + ".s"
- if self.config.list:
- # Only listing files
- files.append(asm)
- else:
- with open(asm, "w") as asm_file:
- # The jump instruction is 4 bytes but BTI requires and extra instruction so
- # this makes it 8 bytes per entry.
- function_offset = item_index * (8 if self.config.bti else 4)
+ if not self.config.list:
+ # The jump instruction is 4 bytes but BTI requires and extra instruction so
+ # this makes it 8 bytes per entry.
+ function_offset = item_index * (8 if self.config.bti else 4)
- item["function_offset"] = function_offset
- asm_file.write(self.build_template("wrapper" + bti + ".S", item))
+ item["function_offset"] = function_offset
+ files.append(self.build_template("wrapper" + bti + ".S", item))
if self.config.list:
- print(" ".join(files))
+ print(self.config.b + "/wrappers.s")
+ else:
+ with open(self.config.b + "/wrappers.s", "w") as asm_file:
+ asm_file.write("\n".join(files))
class VariableGenerator(RomlibApplication):
""" Generates the jump table global variable with the absolute address in ROM. """
@@ -258,7 +272,8 @@
if __name__ == "__main__":
APPS = {"genvar": VariableGenerator, "pre": IndexPreprocessor,
- "gentbl": TableGenerator, "genwrappers": WrapperGenerator}
+ "gentbl": TableGenerator, "genwrappers": WrapperGenerator,
+ "link-flags": LinkArgs}
if len(sys.argv) < 2 or sys.argv[1] not in APPS:
print("usage: romlib_generator.py [%s] [args]" % "|".join(APPS.keys()), file=sys.stderr)
diff --git a/lib/romlib/templates/wrapper.S b/lib/romlib/templates/wrapper.S
index 734a68a..576474a 100644
--- a/lib/romlib/templates/wrapper.S
+++ b/lib/romlib/templates/wrapper.S
@@ -3,8 +3,9 @@
*
* SPDX-License-Identifier: BSD-3-Clause
*/
- .globl ${function_name}
-${function_name}:
+ .section .text.__wrap_${function_name}
+ .globl __wrap_${function_name}
+__wrap_${function_name}:
ldr x17, =jmptbl
mov x16, #${function_offset}
ldr x17, [x17]
diff --git a/lib/romlib/templates/wrapper_bti.S b/lib/romlib/templates/wrapper_bti.S
index ba9b11c..0dc316c 100644
--- a/lib/romlib/templates/wrapper_bti.S
+++ b/lib/romlib/templates/wrapper_bti.S
@@ -3,8 +3,9 @@
*
* SPDX-License-Identifier: BSD-3-Clause
*/
- .globl ${function_name}
-${function_name}:
+ .section .text.__wrap_${function_name}
+ .globl __wrap_${function_name}
+__wrap_${function_name}:
bti jc
ldr x17, =jmptbl
mov x16, #${function_offset}
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index 7050916..f523074 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -465,6 +465,10 @@
$(patsubst %.S,$(BUILD_DIR)/%,$(1))
endef
+ifeq ($(USE_ROMLIB),1)
+WRAPPER_FLAGS := @${BUILD_PLAT}/romlib/romlib.ldflags
+endif
+
# MAKE_BL macro defines the targets and options to build each BL image.
# Arguments:
# $(1) = BL stage
@@ -514,11 +518,11 @@
--map --list="$(MAPFILE)" --scatter=${PLAT_DIR}/scat/${1}.scat \
$(LDPATHS) $(LIBWRAPPER) $(LDLIBS) $(BL_LIBS) $(OBJS)
else ifeq ($($(ARCH)-ld-id),gnu-gcc)
- $$(q)$($(ARCH)-ld) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) $(BL_LDFLAGS) -Wl,-Map=$(MAPFILE) \
+ $$(q)$($(ARCH)-ld) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) $$(WRAPPER_FLAGS) $(BL_LDFLAGS) -Wl,-Map=$(MAPFILE) \
$(addprefix -Wl$(comma)--script$(comma),$(LINKER_SCRIPTS)) -Wl,--script,$(DEFAULT_LINKER_SCRIPT) \
$(OBJS) $(LDPATHS) $(LIBWRAPPER) $(LDLIBS) $(BL_LIBS)
else
- $$(q)$($(ARCH)-ld) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) $(BL_LDFLAGS) -Map=$(MAPFILE) \
+ $$(q)$($(ARCH)-ld) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) $$(WRAPPER_FLAGS) $(BL_LDFLAGS) -Map=$(MAPFILE) \
$(addprefix -T ,$(LINKER_SCRIPTS)) --script $(DEFAULT_LINKER_SCRIPT) \
$(OBJS) $(LDPATHS) $(LIBWRAPPER) $(LDLIBS) $(BL_LIBS)
endif
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 368d26d..8c884b4 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -63,6 +63,9 @@
# Include FP registers in cpu context
CTX_INCLUDE_FPREGS := 0
+# Include SVE registers in cpu context
+CTX_INCLUDE_SVE_REGS := 0
+
# Debug build
DEBUG := 0
@@ -143,7 +146,7 @@
RME_GPT_BITLOCK_BLOCK := 1
# Default maximum size of GPT contiguous block
-RME_GPT_MAX_BLOCK := 2
+RME_GPT_MAX_BLOCK := 512
# Hint platform interrupt control layer that Group 0 interrupts are for EL3. By
# default, they are for Secure EL1.
@@ -237,6 +240,10 @@
# region, platform Makefile is free to override this value.
SEPARATE_BL2_NOLOAD_REGION := 0
+# Put SIMD context data structures in a separate memory region. Platforms
+# have the choice to put it outside of default BSS region of EL3 firmware.
+SEPARATE_SIMD_SECTION := 0
+
# If the BL31 image initialisation code is recalimed after use for the secondary
# cores stack
RECLAIM_INIT_CODE := 0
diff --git a/make_helpers/toolchain.mk b/make_helpers/toolchain.mk
index 96e43a8..9a06a9c 100644
--- a/make_helpers/toolchain.mk
+++ b/make_helpers/toolchain.mk
@@ -289,7 +289,7 @@
guess-gnu-gcc-ld = $(1)
guess-gnu-gcc-oc = $(shell $(1) --print-prog-name objcopy 2>$(nul))
guess-gnu-gcc-od = $(shell $(1) --print-prog-name objdump 2>$(nul))
- guess-gnu-gcc-ar = $(call which,$(call decompat-path,$(patsubst %$(call file-name,$(1)),%$(subst gcc,gcc-ar,$(call file-name,$(1))),$(call compat-path,$(1)))))
+ guess-gnu-gcc-ar = $(shell $(1) --print-prog-name ar 2>$(nul))
define toolchain-warn-unrecognized
$$(warning )
diff --git a/plat/amd/versal2/include/def.h b/plat/amd/versal2/include/def.h
index a8cbaaf..67244a4 100644
--- a/plat/amd/versal2/include/def.h
+++ b/plat/amd/versal2/include/def.h
@@ -125,6 +125,10 @@
#define APU_CLUSTER_STEP U(0x100000)
#define SLCR_OSPI_QSPI_IOU_AXI_MUX_SEL U(0xF1060504)
+#define PMXC_IOU_SLCR_SRAM_CSR U(0xF106104C)
+#define PMXC_IOU_SLCR_PHY_RESET U(0xF1061050)
+#define PMXC_IOU_SLCR_TX_RX_CONFIG_RDY U(0xF1061054)
+#define PMXC_CRP_RST_UFS U(0xF1260340)
/*******************************************************************************
* IRQ constants
diff --git a/plat/amd/versal2/include/versal2-scmi.h b/plat/amd/versal2/include/versal2-scmi.h
index 4d581e4..c08b4b1 100644
--- a/plat/amd/versal2/include/versal2-scmi.h
+++ b/plat/amd/versal2/include/versal2-scmi.h
@@ -136,5 +136,9 @@
#define RESET_I3C6_0 32
#define RESET_I3C7_0 33
#define RESET_I3C8_0 34
+#define RESET_UFSPHY_0 35
+
+#define PD_USB0 0
+#define PD_USB1 1
#endif /* _VERSAL2_SCMI_H */
diff --git a/plat/amd/versal2/plat_psci.c b/plat/amd/versal2/plat_psci.c
index 4faa434..a55042d 100644
--- a/plat/amd/versal2/plat_psci.c
+++ b/plat/amd/versal2/plat_psci.c
@@ -161,12 +161,31 @@
static int32_t no_pm_ioctl(uint32_t device_id, uint32_t ioctl_id,
uint32_t arg1, uint32_t arg2)
{
+ int32_t ret = 0;
VERBOSE("%s: ioctl_id: %x, arg1: %x\n", __func__, ioctl_id, arg1);
- if (ioctl_id == IOCTL_OSPI_MUX_SELECT) {
+
+ switch (ioctl_id) {
+ case IOCTL_OSPI_MUX_SELECT:
mmio_write_32(SLCR_OSPI_QSPI_IOU_AXI_MUX_SEL, arg1);
- return 0;
+ break;
+ case IOCTL_UFS_TXRX_CFGRDY_GET:
+ ret = (int32_t) mmio_read_32(PMXC_IOU_SLCR_TX_RX_CONFIG_RDY);
+ break;
+ case IOCTL_UFS_SRAM_CSR_SEL:
+ if (arg1 == 1) {
+ ret = (int32_t) mmio_read_32(PMXC_IOU_SLCR_SRAM_CSR);
+ } else if (arg1 == 0) {
+ mmio_write_32(PMXC_IOU_SLCR_SRAM_CSR, arg2);
+ }
+ break;
+ case IOCTL_USB_SET_STATE:
+ break;
+ default:
+ ret = PM_RET_ERROR_NOFEATURE;
+ break;
}
- return PM_RET_ERROR_NOFEATURE;
+
+ return ret;
}
static uint64_t no_pm_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
@@ -187,7 +206,13 @@
case PM_IOCTL:
{
ret = no_pm_ioctl(arg[0], arg[1], arg[2], arg[3]);
- SMC_RET1(handle, (uint64_t)ret);
+ /* Firmware driver expects return code in upper 32 bits and
+ * status in lower 32 bits.
+ * status is always SUCCESS(0) for mmio low level register
+ * r/w calls and return value is the value returned from
+ * no_pm_ioctl
+ */
+ SMC_RET1(handle, ((uint64_t)ret << 32));
}
case PM_GET_CHIPID:
{
diff --git a/plat/amd/versal2/platform.mk b/plat/amd/versal2/platform.mk
index c07fc36..1c977a3 100644
--- a/plat/amd/versal2/platform.mk
+++ b/plat/amd/versal2/platform.mk
@@ -116,6 +116,7 @@
plat/xilinx/common/versal.c \
${PLAT_PATH}/bl31_setup.c \
common/fdt_fixup.c \
+ common/fdt_wrappers.c \
${LIBFDT_SRCS} \
${PLAT_PATH}/sip_svc_setup.c \
${PLAT_PATH}/gicv3.c
diff --git a/plat/amd/versal2/scmi.c b/plat/amd/versal2/scmi.c
index c3c517a..7f4b6df 100644
--- a/plat/amd/versal2/scmi.c
+++ b/plat/amd/versal2/scmi.c
@@ -10,6 +10,7 @@
#include <drivers/scmi-msg.h>
#include <drivers/scmi.h>
+#include <lib/mmio.h>
#include <lib/utils_def.h>
#include <platform_def.h>
#include <scmi.h>
@@ -179,14 +180,40 @@
RESET_CELL(RESET_I3C6_0, RESET_I3C6_0, "i3c6"),
RESET_CELL(RESET_I3C7_0, RESET_I3C7_0, "i3c7"),
RESET_CELL(RESET_I3C8_0, RESET_I3C8_0, "i3c8"),
+ RESET_CELL(RESET_UFSPHY_0, RESET_UFSPHY_0, "ufsphy0"),
};
+/**
+ * struct scmi_pd - Data for the exposed power domain controller
+ * @pd_id: pd identifier in RCC reset driver
+ * @name: pd string ID exposed to agent
+ * @state: keep state setting
+ */
+struct scmi_pd {
+ unsigned long pd_id;
+ const char *name;
+ unsigned int state;
+};
+
+#define PD_CELL(_scmi_id, _id, _name, _state) \
+ [_scmi_id] = { \
+ .pd_id = _id, \
+ .name = _name, \
+ .state = _state, \
+ }
+
+static struct scmi_pd scmi0_pd[] = {
+ PD_CELL(PD_USB0, PD_USB0, "usb0", 0),
+ PD_CELL(PD_USB1, PD_USB1, "usb1", 0),
+};
+
struct scmi_resources {
struct scmi_clk *clock;
size_t clock_count;
struct scmi_reset *reset;
size_t reset_count;
-
+ struct scmi_pd *pd;
+ size_t pd_count;
};
static const struct scmi_resources resources[] = {
@@ -195,6 +222,8 @@
.clock_count = ARRAY_SIZE(scmi0_clock),
.reset = scmi0_reset,
.reset_count = ARRAY_SIZE(scmi0_reset),
+ .pd = scmi0_pd,
+ .pd_count = ARRAY_SIZE(scmi0_pd),
},
};
@@ -433,14 +462,122 @@
if (assert_not_deassert) {
NOTICE("SCMI reset %lu/%s set\n",
reset->reset_id, plat_scmi_rstd_get_name(agent_id, scmi_id));
+
+ switch (scmi_id) {
+ case RESET_UFS0_0:
+ mmio_write_32(PMXC_CRP_RST_UFS, 1);
+ break;
+ case RESET_UFSPHY_0:
+ mmio_write_32(PMXC_IOU_SLCR_PHY_RESET, 1);
+ break;
+ default:
+ break;
+ }
} else {
NOTICE("SCMI reset %lu/%s release\n",
reset->reset_id, plat_scmi_rstd_get_name(agent_id, scmi_id));
+
+ switch (scmi_id) {
+ case RESET_UFS0_0:
+ mmio_write_32(PMXC_CRP_RST_UFS, 0);
+ break;
+ case RESET_UFSPHY_0:
+ mmio_write_32(PMXC_IOU_SLCR_PHY_RESET, 0);
+ break;
+ default:
+ break;
+ }
}
return SCMI_SUCCESS;
}
+/*
+ * Platform SCMI reset domains
+ */
+static struct scmi_pd *find_pd(unsigned int agent_id, unsigned int pd_id)
+{
+ const struct scmi_resources *resource = find_resource(agent_id);
+ size_t n;
+
+ if (resource != NULL) {
+ for (n = 0U; n < resource->pd_count; n++) {
+ if (n == pd_id) {
+ return &resource->pd[n];
+ }
+ }
+ }
+
+ return NULL;
+}
+
+size_t plat_scmi_pd_count(unsigned int agent_id)
+{
+ const struct scmi_resources *resource = find_resource(agent_id);
+ size_t ret;
+
+ if (resource == NULL) {
+ ret = 0U;
+ } else {
+ ret = resource->pd_count;
+
+ NOTICE("SCMI: PD: %d\n", (unsigned int)ret);
+ }
+ return ret;
+}
+
+const char *plat_scmi_pd_get_name(unsigned int agent_id, unsigned int pd_id)
+{
+ const struct scmi_pd *pd = find_pd(agent_id, pd_id);
+
+ if (pd == NULL) {
+ return NULL;
+ }
+
+ return pd->name;
+}
+
+unsigned int plat_scmi_pd_statistics(unsigned int agent_id, unsigned long *pd_id)
+{
+ return 0U;
+}
+
+unsigned int plat_scmi_pd_get_attributes(unsigned int agent_id, unsigned int pd_id)
+{
+ return 0U;
+}
+
+unsigned int plat_scmi_pd_get_state(unsigned int agent_id, unsigned int pd_id)
+{
+ const struct scmi_pd *pd = find_pd(agent_id, pd_id);
+
+ if (pd == NULL) {
+ return SCMI_NOT_SUPPORTED;
+ }
+
+ NOTICE("SCMI: PD: get id: %d, state: %x\n", pd_id, pd->state);
+
+ return pd->state;
+}
+
+int32_t plat_scmi_pd_set_state(unsigned int agent_id, unsigned int flags, unsigned int pd_id,
+ unsigned int state)
+{
+ struct scmi_pd *pd = find_pd(agent_id, pd_id);
+
+ if (pd == NULL) {
+ return SCMI_NOT_SUPPORTED;
+ }
+
+ NOTICE("SCMI: PD: set id: %d, orig state: %x, new state: %x, flags: %x\n",
+ pd_id, pd->state, state, flags);
+
+ pd->state = state;
+
+ return 0U;
+}
+
+
/* Currently only one channel is supported. Expectation is that channel 0 is used by NS SW */
static struct scmi_msg_channel scmi_channel[] = {
[0] = {
@@ -475,10 +612,8 @@
SCMI_PROTOCOL_ID_BASE,
SCMI_PROTOCOL_ID_CLOCK,
SCMI_PROTOCOL_ID_RESET_DOMAIN,
- /*
- *SCMI_PROTOCOL_ID_POWER_DOMAIN,
- *SCMI_PROTOCOL_ID_SENSOR,
- */
+ SCMI_PROTOCOL_ID_POWER_DOMAIN,
+ /* SCMI_PROTOCOL_ID_SENSOR, */
0U /* Null termination */
};
diff --git a/plat/arm/board/corstone1000/platform.mk b/plat/arm/board/corstone1000/platform.mk
index 9d44a14..dfde5aa 100644
--- a/plat/arm/board/corstone1000/platform.mk
+++ b/plat/arm/board/corstone1000/platform.mk
@@ -6,7 +6,7 @@
# Making sure the corstone1000 platform type is specified
ifeq ($(filter ${TARGET_PLATFORM}, fpga fvp),)
- $(error TARGET_PLATFORM must be fpga or fvp)
+ $(error TARGET_PLATFORM must be fpga or fvp)
endif
CORSTONE1000_CPU_LIBS +=lib/cpus/aarch64/cortex_a35.S
diff --git a/plat/arm/board/fvp/fdts/fvp_cactus_sp_manifest.dts b/plat/arm/board/fvp/fdts/fvp_cactus_sp_manifest.dts
new file mode 100644
index 0000000..de804e0
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_cactus_sp_manifest.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file is a Partition Manifest (PM) for a minimal Secure Partition (SP)
+ * that will be consumed by EL3 SPMC.
+ *
+ */
+
+/dts-v1/;
+
+/ {
+ compatible = "arm,ffa-manifest-1.0";
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ /* Properties */
+ ffa-version = <0x00010001>; /* 31:16 - Major, 15:0 - Minor */
+ id = <0x8001>;
+ uuid = <0x1e67b5b4 0xe14f904a 0x13fb1fb8 0xcbdae1da>;
+ messaging-method = <3>; /* Direct messaging only */
+ exception-level = <2>; /* S-EL1 */
+ execution-state = <0>; /* AARCH64 */
+ execution-ctx-count = <8>;
+ /* Boot protocol */
+ gp-register-num = <0>;
+};
diff --git a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
index 9fba4af..bf0e7f3 100644
--- a/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts
@@ -99,12 +99,17 @@
memory@2 {
device_type = "device-memory";
- reg = <0x0 0x1c090000 0x0 0x40000>, /* UART */
+ reg = <0x0 0x1c0b0000 0x0 0x20000>, /* UART 2-3 */
<0x0 0x2bfe0000 0x0 0x20000>, /* SMMUv3TestEngine */
<0x0 0x2a490000 0x0 0x20000>, /* SP805 Trusted Watchdog */
<0x0 0x1c130000 0x0 0x10000>; /* Virtio block device */
};
+ memory@3 {
+ device_type = "ns-device-memory";
+ reg = <0x0 0x1c090000 0x0 0x20000>; /* UART 0-1 */
+ };
+
#if MEASURED_BOOT
#include "event_log.dtsi"
diff --git a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
index b1d3bc1..f5d7f65 100644
--- a/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
+++ b/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts
@@ -117,16 +117,16 @@
#if defined(ARM_COT_cca)
/* FVP does not support the CCA NV Counter so use the Trusted one. */
-&cca_nv_counter {
+&cca_nv_ctr {
reg = <TFW_NVCTR_BASE>;
};
#endif
-&trusted_nv_counter {
+&trusted_nv_ctr {
reg = <TFW_NVCTR_BASE>;
};
-&non_trusted_nv_counter {
+&non_trusted_nv_ctr {
reg = <NTFW_CTR_BASE>;
};
#endif
diff --git a/plat/arm/board/fvp/include/plat.ld.S b/plat/arm/board/fvp/include/plat.ld.S
index 7c8bf06..2f99999 100644
--- a/plat/arm/board/fvp/include/plat.ld.S
+++ b/plat/arm/board/fvp/include/plat.ld.S
@@ -1,12 +1,38 @@
/*
- * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLAT_LD_S
#define PLAT_LD_S
-#include <plat/arm/common/arm_tzc_dram.ld.S>
+#include <lib/xlat_tables/xlat_tables_defs.h>
+
+MEMORY {
+ EL3_SEC_DRAM (rw): ORIGIN = ARM_EL3_TZC_DRAM1_BASE, LENGTH = ARM_EL3_TZC_DRAM1_SIZE
+}
+
+SECTIONS
+{
+ . = ARM_EL3_TZC_DRAM1_BASE;
+ ASSERT(. == ALIGN(PAGE_SIZE),
+ "ARM_EL3_TZC_DRAM_BASE address is not aligned on a page boundary.")
+ .el3_tzc_dram (NOLOAD) : ALIGN(PAGE_SIZE) {
+ __PLAT_SPMC_SHMEM_DATASTORE_START__ = .;
+ *(.arm_spmc_shmem_datastore)
+ __PLAT_SPMC_SHMEM_DATASTORE_END__ = .;
+ __EL3_SEC_DRAM_START__ = .;
+ *(.arm_el3_tzc_dram)
+#if SEPARATE_SIMD_SECTION
+ . = ALIGN(16);
+ *(.simd_context)
+#endif
+ __EL3_SEC_DRAM_UNALIGNED_END__ = .;
+
+ . = ALIGN(PAGE_SIZE);
+ __EL3_SEC_DRAM_END__ = .;
+ } >EL3_SEC_DRAM
+}
#if RECLAIM_INIT_CODE
#include <plat/arm/common/arm_reclaim_init.ld.S>
diff --git a/plat/arm/board/fvp/jmptbl.i b/plat/arm/board/fvp/jmptbl.i
index dc8032f..077283e 100644
--- a/plat/arm/board/fvp/jmptbl.i
+++ b/plat/arm/board/fvp/jmptbl.i
@@ -36,7 +36,6 @@
fdt fdt_get_name
fdt fdt_get_alias
fdt fdt_node_offset_by_phandle
-fdt fdt_subnode_offset
fdt fdt_add_subnode
mbedtls mbedtls_asn1_get_alg
mbedtls mbedtls_asn1_get_alg_null
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index cef7bdf..340eb38 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -47,6 +47,10 @@
ifeq (${CTX_INCLUDE_FPREGS}, 0)
ENABLE_SME_FOR_NS := 2
ENABLE_SME2_FOR_NS := 2
+else
+ ENABLE_SVE_FOR_NS := 0
+ ENABLE_SME_FOR_NS := 0
+ ENABLE_SME2_FOR_NS := 0
endif
endif
diff --git a/plat/arm/board/fvp_r/platform.mk b/plat/arm/board/fvp_r/platform.mk
index f14ea54..71cb9e2 100644
--- a/plat/arm/board/fvp_r/platform.mk
+++ b/plat/arm/board/fvp_r/platform.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -25,7 +25,7 @@
include plat/arm/board/common/board_common.mk
include plat/arm/common/arm_common.mk
-PLAT_INCLUDES := -Iplat/arm/board/fvp_r/include
+PLAT_INCLUDES += -Iplat/arm/board/fvp_r/include
FVP_R_BL_COMMON_SOURCES := plat/arm/board/fvp_r/fvp_r_common.c \
plat/arm/board/fvp_r/fvp_r_context_mgmt.c \
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 cf1eb6f..dcee92c 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
@@ -73,29 +73,14 @@
mair_el1);
cpu_info->ErrCtxEl1Reg[5] = read_midr_el1();
cpu_info->ErrCtxEl1Reg[6] = read_mpidr_el1();
-
-#if (ERRATA_SPECULATIVE_AT)
- cpu_info->ErrCtxEl1Reg[7] = read_ctx_reg(get_errata_speculative_at_ctx(ctx),
- CTX_ERRATA_SPEC_AT_SCTLR_EL1);
-#else
- cpu_info->ErrCtxEl1Reg[7] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
- sctlr_el1);
-#endif /* ERRATA_SPECULATIVE_AT */
-
+ cpu_info->ErrCtxEl1Reg[7] = read_ctx_sctlr_el1_reg_errata(ctx);
cpu_info->ErrCtxEl1Reg[8] = read_ctx_reg(get_gpregs_ctx(ctx),
CTX_GPREG_SP_EL0);
cpu_info->ErrCtxEl1Reg[9] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
sp_el1);
cpu_info->ErrCtxEl1Reg[10] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
spsr_el1);
-#if (ERRATA_SPECULATIVE_AT)
- cpu_info->ErrCtxEl1Reg[11] = read_ctx_reg(get_errata_speculative_at_ctx(ctx),
- CTX_ERRATA_SPEC_AT_TCR_EL1);
-#else
- cpu_info->ErrCtxEl1Reg[11] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
- tcr_el1);
-#endif /* ERRATA_SPECULATIVE_AT */
-
+ cpu_info->ErrCtxEl1Reg[11] = read_ctx_tcr_el1_reg_errata(ctx);
cpu_info->ErrCtxEl1Reg[12] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
tpidr_el0);
cpu_info->ErrCtxEl1Reg[13] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
@@ -107,7 +92,7 @@
cpu_info->ErrCtxEl1Reg[16] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
ttbr1_el1);
-#if CTX_INCLUDE_EL2_REGS
+#if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
cpu_info->ErrCtxEl2Reg[0] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
elr_el2);
cpu_info->ErrCtxEl2Reg[1] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
@@ -140,7 +125,7 @@
vttbr_el2);
cpu_info->ErrCtxEl2Reg[15] = read_el2_ctx_common(get_el2_sysregs_ctx(ctx),
esr_el2);
-#endif /* CTX_INCLUDE_EL2_REGS */
+#endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
cpu_info->ErrCtxEl3Reg[0] = read_ctx_reg(get_el3state_ctx(ctx),
CTX_ELR_EL3);
diff --git a/plat/arm/board/neoverse_rd/platform/rdv3/platform.mk b/plat/arm/board/neoverse_rd/platform/rdv3/platform.mk
index 7d770f5..98029bb 100644
--- a/plat/arm/board/neoverse_rd/platform/rdv3/platform.mk
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/platform.mk
@@ -21,12 +21,6 @@
override ARM_ARCH_MAJOR := 8
override ARM_ARCH_MINOR := 7
-# Image flags
-override NEED_BL1 := yes
-override NEED_BL2 := yes
-override NEED_BL32 := no
-override NEED_RMM := no
-
# Misc options
override CTX_INCLUDE_AARCH32_REGS := 0
@@ -137,3 +131,4 @@
override ENABLE_SVE_FOR_SWD := 1
override ENABLE_SVE_FOR_NS := 2
override ENABLE_FEAT_MTE2 := 2
+override CTX_INCLUDE_SVE_REGS := 1
diff --git a/plat/arm/board/tc/include/platform_def.h b/plat/arm/board/tc/include/platform_def.h
index 45d17ba..0652148 100644
--- a/plat/arm/board/tc/include/platform_def.h
+++ b/plat/arm/board/tc/include/platform_def.h
@@ -12,7 +12,21 @@
#include <lib/xlat_tables/xlat_tables_defs.h>
#include <plat/arm/board/common/board_css_def.h>
#include <plat/arm/board/common/v2m_def.h>
+
+/*
+ * arm_def.h depends on the platform system counter macros, so must define the
+ * platform macros before including arm_def.h.
+ */
+#if TARGET_PLATFORM == 4
+#ifdef ARM_SYS_CNTCTL_BASE
+#error "error: ARM_SYS_CNTCTL_BASE is defined prior to the PLAT_ARM_SYS_CNTCTL_BASE definition"
+#endif
+#define PLAT_ARM_SYS_CNTCTL_BASE UL(0x47000000)
+#define PLAT_ARM_SYS_CNTREAD_BASE UL(0x47010000)
+#endif
+
#include <plat/arm/common/arm_def.h>
+
#include <plat/arm/common/arm_spm_def.h>
#include <plat/arm/css/common/css_def.h>
#include <plat/arm/soc/common/soc_css_def.h>
@@ -230,9 +244,9 @@
#if TARGET_PLATFORM <= 2
#define PLAT_ARM_DRAM2_BASE ULL(0x8080000000)
-#elif TARGET_PLATFORM == 3
+#elif TARGET_PLATFORM >= 3
#define PLAT_ARM_DRAM2_BASE ULL(0x880000000)
-#endif /* TARGET_PLATFORM == 3 */
+#endif /* TARGET_PLATFORM >= 3 */
#define PLAT_ARM_DRAM2_SIZE ULL(0x180000000)
#define PLAT_ARM_DRAM2_END (PLAT_ARM_DRAM2_BASE + PLAT_ARM_DRAM2_SIZE - 1ULL)
@@ -294,9 +308,9 @@
/* Message Handling Unit (MHU) base addresses */
#if TARGET_PLATFORM <= 2
#define PLAT_CSS_MHU_BASE UL(0x45400000)
-#elif TARGET_PLATFORM == 3
+#elif TARGET_PLATFORM >= 3
#define PLAT_CSS_MHU_BASE UL(0x46000000)
-#endif /* TARGET_PLATFORM == 3 */
+#endif /* TARGET_PLATFORM >= 3 */
#define PLAT_MHUV2_BASE PLAT_CSS_MHU_BASE
/* AP<->RSS MHUs */
@@ -306,6 +320,9 @@
#elif TARGET_PLATFORM == 3
#define PLAT_RSE_AP_SND_MHU_BASE UL(0x49000000)
#define PLAT_RSE_AP_RCV_MHU_BASE UL(0x49100000)
+#elif TARGET_PLATFORM == 4
+#define PLAT_RSE_AP_SND_MHU_BASE UL(0x49000000)
+#define PLAT_RSE_AP_RCV_MHU_BASE UL(0x49010000)
#endif
#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2
diff --git a/plat/arm/board/tc/include/tc_helpers.S b/plat/arm/board/tc/include/tc_helpers.S
index 29130ea..9adf09a 100644
--- a/plat/arm/board/tc/include/tc_helpers.S
+++ b/plat/arm/board/tc/include/tc_helpers.S
@@ -81,6 +81,10 @@
ret
endfunc TC_HANDLER(3)
+func TC_HANDLER(4)
+ ret
+endfunc TC_HANDLER(4)
+
/* -----------------------------------------------------
* void plat_reset_handler(void);
* -----------------------------------------------------
diff --git a/plat/arm/board/tc/plat_tc_mbedtls_config.h b/plat/arm/board/tc/plat_tc_mbedtls_config.h
index de7b1aa..4fd8b6b 100644
--- a/plat/arm/board/tc/plat_tc_mbedtls_config.h
+++ b/plat/arm/board/tc/plat_tc_mbedtls_config.h
@@ -21,6 +21,20 @@
#endif
#endif /* TF_MBEDTLS_HEAP_SIZE */
+/**
+ * On Arm TC platforms, the ROTPK is always hashed using the SHA-256
+ * algorithm.
+ * TODO: Update to hash the ROTPK with the selected HASH_ALG to avoid
+ * the need for explicitly enabling the SHA-256 configuration in mbedTLS.
+ */
+#define MBEDTLS_SHA256_C
+
+/*
+ * Use an implementation of SHA-256 with a smaller memory footprint
+ * but reduced speed.
+ */
+#define MBEDTLS_SHA256_SMALLER
+
#define MBEDTLS_PSA_CRYPTO_C
#define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
#define MBEDTLS_ECP_C
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
index fb70500..3ef25de 100644
--- a/plat/arm/board/tc/platform.mk
+++ b/plat/arm/board/tc/platform.mk
@@ -26,6 +26,9 @@
ENABLE_FEAT_MPAM := 1 # default is 2, optimise
ENABLE_SVE_FOR_NS := 2 # to show we use it
ENABLE_SVE_FOR_SWD := 1
+ENABLE_SME_FOR_NS := 2
+ENABLE_SME2_FOR_NS := 2
+ENABLE_SME_FOR_SWD := 1
ENABLE_TRBE_FOR_NS := 1
ENABLE_SYS_REG_TRACE_FOR_NS := 1
ENABLE_FEAT_AMU := 1
@@ -33,7 +36,9 @@
ENABLE_AMU_AUXILIARY_COUNTERS := 1
ENABLE_MPMM := 1
ENABLE_MPMM_FCONF := 1
-ENABLE_FEAT_MTE2 := 2
+ENABLE_FEAT_MTE2 := 2
+ENABLE_SPE_FOR_NS := 3
+ENABLE_FEAT_TCR2 := 3
CTX_INCLUDE_AARCH32_REGS := 0
@@ -60,8 +65,8 @@
Some of the features might not work as expected)
endif
-ifeq ($(shell expr $(TARGET_PLATFORM) \<= 3), 0)
- $(error TARGET_PLATFORM must be less than or equal to 3)
+ifeq ($(shell expr $(TARGET_PLATFORM) \<= 4), 0)
+ $(error TARGET_PLATFORM must be less than or equal to 4)
endif
ifeq ($(filter ${TARGET_FLAVOUR}, fvp fpga),)
@@ -109,6 +114,9 @@
# CPU libraries for TARGET_PLATFORM=2
ifeq (${TARGET_PLATFORM}, 2)
+ERRATA_A520_2938996 := 1
+ERRATA_X4_2726228 := 1
+
TC_CPU_SOURCES += lib/cpus/aarch64/cortex_a520.S \
lib/cpus/aarch64/cortex_a720.S \
lib/cpus/aarch64/cortex_x4.S
@@ -116,11 +124,20 @@
# CPU libraries for TARGET_PLATFORM=3
ifeq (${TARGET_PLATFORM}, 3)
+ERRATA_A520_2938996 := 1
+
TC_CPU_SOURCES += lib/cpus/aarch64/cortex_a520.S \
lib/cpus/aarch64/cortex_a725.S \
lib/cpus/aarch64/cortex_x925.S
endif
+# CPU libraries for TARGET_PLATFORM=4
+ifeq (${TARGET_PLATFORM}, 4)
+TC_CPU_SOURCES += lib/cpus/aarch64/cortex_gelas.S \
+ lib/cpus/aarch64/nevis.S \
+ lib/cpus/aarch64/travis.S
+endif
+
INTERCONNECT_SOURCES := ${TC_BASE}/tc_interconnect.c \
plat/arm/common/arm_ni.c
diff --git a/plat/arm/board/tc/tc_bl31_setup.c b/plat/arm/board/tc/tc_bl31_setup.c
index 53404df..801872a 100644
--- a/plat/arm/board/tc/tc_bl31_setup.c
+++ b/plat/arm/board/tc/tc_bl31_setup.c
@@ -58,7 +58,7 @@
.db_modify_mask = 0x1,
.ring_doorbell = &mhuv2_ring_doorbell,
};
-#elif TARGET_PLATFORM == 3
+#elif TARGET_PLATFORM >= 3
static scmi_channel_plat_info_t tc_scmi_plat_info = {
.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
.db_reg_addr = PLAT_CSS_MHU_BASE + MHU_V3_SENDER_REG_SET(0),
@@ -66,7 +66,9 @@
.db_modify_mask = 0x1,
.ring_doorbell = &mhu_ring_doorbell,
};
+#endif
+#if TARGET_PLATFORM == 3
static void enable_ns_mcn_pmu(void)
{
/*
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 2c1888d..859791d 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -119,10 +119,6 @@
endif
endif
-# Use an implementation of SHA-256 with a smaller memory footprint but reduced
-# speed.
-$(eval $(call add_define,MBEDTLS_SHA256_SMALLER))
-
# Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images
# in the FIP if the platform requires.
ifneq ($(BL32_EXTRA1),)
@@ -364,6 +360,17 @@
BL31_SOURCES += plat/arm/common/arm_err.c
endif
+ifneq ($(filter 1,${MEASURED_BOOT} ${TRUSTED_BOARD_BOOT} ${DRTM_SUPPORT}),)
+ PLAT_INCLUDES += -Iplat/arm/common \
+ -Iinclude/drivers/auth/mbedtls
+ # Specify mbed TLS configuration file
+ ifeq (${PSA_CRYPTO},1)
+ MBEDTLS_CONFIG_FILE ?= "<plat_arm_psa_mbedtls_config.h>"
+ else
+ MBEDTLS_CONFIG_FILE ?= "<plat_arm_mbedtls_config.h>"
+ endif
+endif
+
ifneq (${TRUSTED_BOARD_BOOT},0)
# Include common TBB sources
@@ -377,30 +384,37 @@
ifneq (${COT_DESC_IN_DTB},0)
BL2_SOURCES += lib/fconf/fconf_cot_getter.c
else
- BL2_SOURCES += drivers/auth/tbbr/tbbr_cot_common.c
# Juno has its own TBBR CoT file for BL2
- ifneq (${PLAT},juno)
- BL2_SOURCES += drivers/auth/tbbr/tbbr_cot_bl2.c
+ ifeq (${PLAT},juno)
+ BL2_SOURCES += drivers/auth/tbbr/tbbr_cot_common.c
endif
endif
else ifeq (${COT},dualroot)
- BL1_SOURCES += drivers/auth/dualroot/cot.c
+ BL1_SOURCES += drivers/auth/dualroot/bl1_cot.c
ifneq (${COT_DESC_IN_DTB},0)
BL2_SOURCES += lib/fconf/fconf_cot_getter.c
- else
- BL2_SOURCES += drivers/auth/dualroot/cot.c
endif
else ifeq (${COT},cca)
- BL1_SOURCES += drivers/auth/cca/cot.c
+ BL1_SOURCES += drivers/auth/cca/bl1_cot.c
ifneq (${COT_DESC_IN_DTB},0)
BL2_SOURCES += lib/fconf/fconf_cot_getter.c
- else
- BL2_SOURCES += drivers/auth/cca/cot.c
endif
else
$(error Unknown chain of trust ${COT})
endif
+ ifeq (${COT_DESC_IN_DTB},0)
+ ifeq (${COT},dualroot)
+ COTDTPATH := fdts/dualroot_cot_descriptors.dtsi
+ else ifeq (${COT},cca)
+ COTDTPATH := fdts/cca_cot_descriptors.dtsi
+ else ifeq (${COT},tbbr)
+ ifneq (${PLAT},juno)
+ COTDTPATH := fdts/tbbr_cot_descriptors.dtsi
+ endif
+ endif
+ endif
+
BL1_SOURCES += ${AUTH_SOURCES} \
bl1/tbbr/tbbr_img_desc.c \
plat/arm/common/arm_bl1_fwu.c \
@@ -425,10 +439,6 @@
$(info Including ${MEASURED_BOOT_MK})
include ${MEASURED_BOOT_MK}
- ifneq (${MBOOT_EL_HASH_ALG}, sha256)
- $(eval $(call add_define,TF_MBEDTLS_MBOOT_USE_SHA512))
- endif
-
ifeq (${MEASURED_BOOT},1)
BL1_SOURCES += ${EVENT_LOG_SOURCES}
BL2_SOURCES += ${EVENT_LOG_SOURCES}
@@ -472,3 +482,24 @@
bl31: tl
endif
endif
+
+ifneq ($(COTDTPATH),)
+ cot-dt-defines = IMAGE_BL2 $(BL2_DEFINES) $(PLAT_BL_COMMON_DEFINES)
+ cot-dt-include-dirs = $(BL2_INCLUDE_DIRS) $(PLAT_BL_COMMON_INCLUDE_DIRS)
+
+ cot-dt-cpp-flags = $(cot-dt-defines:%=-D%)
+ cot-dt-cpp-flags += $(cot-dt-include-dirs:%=-I%)
+
+ cot-dt-cpp-flags += $(BL2_CPPFLAGS) $(PLAT_BL_COMMON_CPPFLAGS)
+ cot-dt-cpp-flags += $(CPPFLAGS) $(BL_CPPFLAGS) $(TF_CFLAGS_$(ARCH))
+ cot-dt-cpp-flags += -c -x assembler-with-cpp -E -P -o $@ $<
+
+ $(BUILD_PLAT)/$(COTDTPATH:.dtsi=.dts): $(COTDTPATH) | $$(@D)/
+ $(q)$($(ARCH)-cpp) $(cot-dt-cpp-flags)
+
+ $(BUILD_PLAT)/$(COTDTPATH:.dtsi=.c): $(BUILD_PLAT)/$(COTDTPATH:.dtsi=.dts) | $$(@D)/
+ $(q)poetry -q install
+ $(q)poetry run cot-dt2c convert-to-c $< $@
+
+ BL2_SOURCES += $(BUILD_PLAT)/$(COTDTPATH:.dtsi=.c)
+endif
diff --git a/plat/arm/common/plat_arm_mbedtls_config.h b/plat/arm/common/plat_arm_mbedtls_config.h
new file mode 100644
index 0000000..a5d0ec4
--- /dev/null
+++ b/plat/arm/common/plat_arm_mbedtls_config.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2024, Arm Ltd. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_ARM_MBEDTLS_CONFIG_H
+#define PLAT_ARM_MBEDTLS_CONFIG_H
+
+#include <mbedtls_config-3.h>
+
+/**
+ * On Arm platforms, the ROTPK is always hashed using the SHA-256
+ * algorithm.
+ * TODO: Update to hash the ROTPK with the selected HASH_ALG to avoid
+ * the need for explicitly enabling the SHA-256 configuration in mbedTLS.
+ */
+#define MBEDTLS_SHA256_C
+
+/*
+ * Use an implementation of SHA-256 with a smaller memory footprint
+ * but reduced speed.
+ */
+#define MBEDTLS_SHA256_SMALLER
+
+#endif /* PLAT_ARM_MBEDTLS_CONFIG_H */
diff --git a/plat/arm/common/plat_arm_psa_mbedtls_config.h b/plat/arm/common/plat_arm_psa_mbedtls_config.h
new file mode 100644
index 0000000..fd434c9
--- /dev/null
+++ b/plat/arm/common/plat_arm_psa_mbedtls_config.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2024, Arm Ltd. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_ARM_PSA_MBEDTLS_CONFIG_H
+#define PLAT_ARM_PSA_MBEDTLS_CONFIG_H
+
+#include "plat_arm_mbedtls_config.h"
+
+#define MBEDTLS_PSA_CRYPTO_C
+#define MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS
+
+/*
+ * Using PSA crypto API requires an RNG right now. If we don't define the macro
+ * below then we get build errors.
+ *
+ * This is a functionality gap in mbedTLS. The technical limitation is that
+ * psa_crypto_init() is all-or-nothing, and fixing that would require separate
+ * initialization of the keystore, the RNG, etc.
+ *
+ * By defining MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG, we pretend using an external
+ * RNG. As a result, the PSA crypto init code does nothing when it comes to
+ * initializing the RNG, as we are supposed to take care of that ourselves.
+ */
+#define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+
+#endif /* PLAT_ARM_PSA_MBEDTLS_CONFIG_H */
diff --git a/plat/hisilicon/poplar/include/hi3798cv200.h b/plat/hisilicon/poplar/include/hi3798cv200.h
index e31f4b3..802dec5 100644
--- a/plat/hisilicon/poplar/include/hi3798cv200.h
+++ b/plat/hisilicon/poplar/include/hi3798cv200.h
@@ -38,7 +38,11 @@
/* SCTL */
#define REG_BASE_SCTL (0xF8000000)
+#define REG_SC_SYSRES (0x0004)
#define REG_SC_GEN12 (0x00B0)
+#define REG_SC_LOCKEN (0x020C)
+
+#define SC_UNLOCK_MAGIC (0x4F50454E)
/* CRG */
#define REG_BASE_CRG (0xF8A22000)
diff --git a/plat/hisilicon/poplar/plat_pm.c b/plat/hisilicon/poplar/plat_pm.c
index 67ebca1..77fc532 100644
--- a/plat/hisilicon/poplar/plat_pm.c
+++ b/plat/hisilicon/poplar/plat_pm.c
@@ -92,14 +92,18 @@
static void __dead2 poplar_system_off(void)
{
ERROR("Poplar System Off: operation not handled.\n");
+ /* Turn off watchdog0 before panic() */
+ mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0xc00), 0x1ACCE551);
+ mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0x8), 0x00000000);
panic();
}
static void __dead2 poplar_system_reset(void)
{
- mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0xc00), 0x1ACCE551);
- mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0x0), 0x00000100);
- mmio_write_32((uintptr_t)(HISI_WDG0_BASE + 0x8), 0x00000003);
+ /* Unlock Sysctrl critical registers */
+ mmio_write_32((uintptr_t)(REG_BASE_SCTL + REG_SC_LOCKEN), SC_UNLOCK_MAGIC);
+ /* Assert system reset */
+ mmio_write_32((uintptr_t)(REG_BASE_SCTL + REG_SC_SYSRES), 0xfee1dead);
wfi();
ERROR("Poplar System Reset: operation not handled.\n");
diff --git a/plat/imx/imx8m/imx8mm/platform.mk b/plat/imx/imx8m/imx8mm/platform.mk
index f0cdb3e..d1c1259 100644
--- a/plat/imx/imx8m/imx8mm/platform.mk
+++ b/plat/imx/imx8m/imx8mm/platform.mk
@@ -188,10 +188,6 @@
$(info Including ${MEASURED_BOOT_MK})
include ${MEASURED_BOOT_MK}
-ifneq (${MBOOT_EL_HASH_ALG}, sha256)
- $(eval $(call add_define,TF_MBEDTLS_MBOOT_USE_SHA512))
-endif
-
BL2_SOURCES += plat/imx/imx8m/imx8m_measured_boot.c \
plat/imx/imx8m/imx8m_dyn_cfg_helpers.c \
${EVENT_LOG_SOURCES}
diff --git a/plat/intel/soc/agilex/bl2_plat_setup.c b/plat/intel/soc/agilex/bl2_plat_setup.c
index 61c0ef2..36820b2 100644
--- a/plat/intel/soc/agilex/bl2_plat_setup.c
+++ b/plat/intel/soc/agilex/bl2_plat_setup.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -30,6 +31,7 @@
#include "socfpga_reset_manager.h"
#include "socfpga_ros.h"
#include "socfpga_system_manager.h"
+#include "socfpga_vab.h"
#include "wdt/watchdog.h"
static struct mmc_device_info mmc_info;
@@ -112,7 +114,10 @@
setup_page_tables(bl_regions, agilex_plat_mmap);
- enable_mmu_el3(0);
+ /*
+ * TODO: mmu enable in latest phase
+ */
+ // enable_mmu_el3(0);
dw_mmc_params_t params = EMMC_INIT_PARAMS(0x100000, get_mmc_clk());
@@ -173,6 +178,20 @@
assert(bl_mem_params);
+#if SOCFPGA_SECURE_VAB_AUTH
+ /*
+ * VAB Authentication start here.
+ * If failed to authenticate, shall not proceed to process BL31 and hang.
+ */
+ int ret = 0;
+
+ ret = socfpga_vab_init(image_id);
+ if (ret < 0) {
+ ERROR("SOCFPGA VAB Authentication failed\n");
+ wfi();
+ }
+#endif
+
switch (image_id) {
case BL33_IMAGE_ID:
bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
@@ -191,4 +210,3 @@
void bl2_platform_setup(void)
{
}
-
diff --git a/plat/intel/soc/agilex/platform.mk b/plat/intel/soc/agilex/platform.mk
index 6780845..21cc6a3 100644
--- a/plat/intel/soc/agilex/platform.mk
+++ b/plat/intel/soc/agilex/platform.mk
@@ -1,6 +1,7 @@
#
# Copyright (c) 2019-2023, ARM Limited and Contributors. All rights reserved.
-# Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+# Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+# Copyright (c) 2024, Altera Corporation. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -27,6 +28,7 @@
plat/intel/soc/common/aarch64/platform_common.c \
plat/intel/soc/common/aarch64/plat_helpers.S \
plat/intel/soc/common/drivers/ccu/ncore_ccu.c \
+ plat/intel/soc/common/lib/sha/sha.c \
plat/intel/soc/common/socfpga_delay_timer.c
BL2_SOURCES += \
@@ -49,6 +51,7 @@
plat/intel/soc/common/socfpga_image_load.c \
plat/intel/soc/common/socfpga_ros.c \
plat/intel/soc/common/socfpga_storage.c \
+ plat/intel/soc/common/socfpga_vab.c \
plat/intel/soc/common/soc/socfpga_emac.c \
plat/intel/soc/common/soc/socfpga_firewall.c \
plat/intel/soc/common/soc/socfpga_handoff.c \
@@ -78,9 +81,20 @@
plat/intel/soc/common/soc/socfpga_mailbox.c \
plat/intel/soc/common/soc/socfpga_reset_manager.c
+# Don't have the Linux kernel as a BL33 image by default
+ARM_LINUX_KERNEL_AS_BL33 := 0
+$(eval $(call assert_boolean,ARM_LINUX_KERNEL_AS_BL33))
+$(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33))
$(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
+# Configs for VAB Authentication
+SOCFPGA_SECURE_VAB_AUTH := 0
+$(eval $(call assert_boolean,SOCFPGA_SECURE_VAB_AUTH))
+$(eval $(call add_define,SOCFPGA_SECURE_VAB_AUTH))
+
PROGRAMMABLE_RESET_ADDRESS := 0
RESET_TO_BL2 := 1
BL2_INV_DCACHE := 0
USE_COHERENT_MEM := 1
+
+HANDLE_EA_EL3_FIRST_NS := 1
\ No newline at end of file
diff --git a/plat/intel/soc/agilex5/bl2_plat_setup.c b/plat/intel/soc/agilex5/bl2_plat_setup.c
index c74d799..265ee57 100644
--- a/plat/intel/soc/agilex5/bl2_plat_setup.c
+++ b/plat/intel/soc/agilex5/bl2_plat_setup.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -35,6 +36,7 @@
#include "socfpga_private.h"
#include "socfpga_reset_manager.h"
#include "socfpga_ros.h"
+#include "socfpga_vab.h"
#include "wdt/watchdog.h"
@@ -165,6 +167,20 @@
assert(bl_mem_params);
+#if SOCFPGA_SECURE_VAB_AUTH
+ /*
+ * VAB Authentication start here.
+ * If failed to authenticate, shall not proceed to process BL31 and hang.
+ */
+ int ret = 0;
+
+ ret = socfpga_vab_init(image_id);
+ if (ret < 0) {
+ ERROR("SOCFPGA VAB Authentication failed\n");
+ wfi();
+ }
+#endif
+
switch (image_id) {
case BL33_IMAGE_ID:
bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
diff --git a/plat/intel/soc/agilex5/include/agilex5_system_manager.h b/plat/intel/soc/agilex5/include/agilex5_system_manager.h
index 46596bf..53dcd13 100644
--- a/plat/intel/soc/agilex5/include/agilex5_system_manager.h
+++ b/plat/intel/soc/agilex5/include/agilex5_system_manager.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -147,6 +148,7 @@
/* QSPI ECC from SDM register */
#define SOCFPGA_ECC_QSPI_CTRL 0x08
+#define SOCFPGA_ECC_QSPI_INITSTAT 0x0C
#define SOCFPGA_ECC_QSPI_ERRINTEN 0x10
#define SOCFPGA_ECC_QSPI_ERRINTENS 0x14
#define SOCFPGA_ECC_QSPI_ERRINTENR 0x18
diff --git a/plat/intel/soc/agilex5/include/socfpga_plat_def.h b/plat/intel/soc/agilex5/include/socfpga_plat_def.h
index acdbe17..9bfc304 100644
--- a/plat/intel/soc/agilex5/include/socfpga_plat_def.h
+++ b/plat/intel/soc/agilex5/include/socfpga_plat_def.h
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -21,7 +22,7 @@
#define PLAT_PRIMARY_CPU_A76 0x200
#define PLAT_CLUSTER_ID_MPIDR_AFF_SHIFT MPIDR_AFF2_SHIFT
#define PLAT_CPU_ID_MPIDR_AFF_SHIFT MPIDR_AFF1_SHIFT
-#define PLAT_L2_RESET_REQ 0xB007C0DE
+#define PLAT_L2_RESET_REQ 0xB007C0DE
/* System Counter */
/* TODO: Update back to 400MHz.
@@ -31,7 +32,7 @@
#define PLAT_SYS_COUNTER_FREQ_IN_MHZ (400)
/* FPGA config helpers */
-#define INTEL_SIP_SMC_FPGA_CONFIG_ADDR 0x400000
+#define INTEL_SIP_SMC_FPGA_CONFIG_ADDR 0x80400000
#define INTEL_SIP_SMC_FPGA_CONFIG_SIZE 0x2000000
/* QSPI Setting */
@@ -101,7 +102,7 @@
/*******************************************************************************
* WDT related constants
******************************************************************************/
-#define WDT_BASE (0x10D00200)
+#define WDT_BASE (0x10D00200)
/*******************************************************************************
* GIC related constants
@@ -116,13 +117,13 @@
/*******************************************************************************
* SDMMC related pointer function
******************************************************************************/
-#define SDMMC_READ_BLOCKS sdmmc_read_blocks
-#define SDMMC_WRITE_BLOCKS sdmmc_write_blocks
+#define SDMMC_READ_BLOCKS sdmmc_read_blocks
+#define SDMMC_WRITE_BLOCKS sdmmc_write_blocks
/*******************************************************************************
* sysmgr.boot_scratch_cold6 & 7 (64bit) are used to indicate L2 reset
* is done and HPS should trigger warm reset via RMR_EL3.
******************************************************************************/
-#define L2_RESET_DONE_REG 0x10D12218
+#define L2_RESET_DONE_REG 0x10D12218
#endif /* PLAT_SOCFPGA_DEF_H */
diff --git a/plat/intel/soc/agilex5/platform.mk b/plat/intel/soc/agilex5/platform.mk
index 7302164..409c7b1 100644
--- a/plat/intel/soc/agilex5/platform.mk
+++ b/plat/intel/soc/agilex5/platform.mk
@@ -1,6 +1,7 @@
#
# Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
# Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+# Copyright (c) 2024, Altera Corporation. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -8,6 +9,7 @@
PLAT_INCLUDES := \
-Iplat/intel/soc/agilex5/include/ \
-Iplat/intel/soc/common/drivers/ \
+ -Iplat/intel/soc/common/lib/sha/ \
-Iplat/intel/soc/common/include/
# GIC-600 configuration
@@ -33,6 +35,7 @@
plat/intel/soc/common/drivers/sdmmc/sdmmc.c \
plat/intel/soc/common/drivers/ddr/ddr.c \
plat/intel/soc/common/drivers/nand/nand.c \
+ plat/intel/soc/common/lib/sha/sha.c \
plat/intel/soc/common/socfpga_delay_timer.c
BL2_SOURCES += \
@@ -107,6 +110,11 @@
$(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33))
$(eval $(call add_define,ARM_PRELOADED_DTB_BASE))
+# Configs for VAB Authentication
+SOCFPGA_SECURE_VAB_AUTH := 0
+$(eval $(call assert_boolean,SOCFPGA_SECURE_VAB_AUTH))
+$(eval $(call add_define,SOCFPGA_SECURE_VAB_AUTH))
+
PROGRAMMABLE_RESET_ADDRESS := 0
RESET_TO_BL2 := 1
-BL2_INV_DCACHE := 0
+BL2_INV_DCACHE := 0
\ No newline at end of file
diff --git a/plat/intel/soc/common/drivers/sdmmc/sdmmc.c b/plat/intel/soc/common/drivers/sdmmc/sdmmc.c
index 8666f54..48f91eb 100644
--- a/plat/intel/soc/common/drivers/sdmmc/sdmmc.c
+++ b/plat/intel/soc/common/drivers/sdmmc/sdmmc.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2022-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -19,6 +20,7 @@
#include "agilex5_pinmux.h"
#include "sdmmc.h"
+#include "socfpga_mailbox.h"
static const struct mmc_ops *ops;
static unsigned int mmc_ocr_value;
@@ -518,7 +520,8 @@
return ret;
}
- memcpy(&mmc_csd, &resp_data, sizeof(resp_data));
+ memcpy_s(&mmc_csd, sizeof(mmc_csd) / MBOX_WORD_BYTE,
+ &resp_data, sizeof(resp_data) / MBOX_WORD_BYTE);
/* CMD7: Select Card */
ret = sdmmc_send_cmd(MMC_CMD(7), rca << RCA_SHIFT_OFFSET,
@@ -758,7 +761,8 @@
(params->bus_width == MMC_BUS_WIDTH_4) ||
(params->bus_width == MMC_BUS_WIDTH_8)));
- memcpy(&cdns_params, params, sizeof(struct cdns_sdmmc_params));
+ memcpy_s(&cdns_params, sizeof(struct cdns_sdmmc_params) / MBOX_WORD_BYTE,
+ params, sizeof(struct cdns_sdmmc_params) / MBOX_WORD_BYTE);
cdns_params.cdn_sdmmc_dev_type = info->mmc_dev_type;
cdns_params.cdn_sdmmc_dev_mode = SD_DS;
diff --git a/plat/intel/soc/common/include/socfpga_vab.h b/plat/intel/soc/common/include/socfpga_vab.h
index f6081df..4587d7f 100644
--- a/plat/intel/soc/common/include/socfpga_vab.h
+++ b/plat/intel/soc/common/include/socfpga_vab.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2020-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,10 +8,28 @@
#ifndef SOCFPGA_VAB_H
#define SOCFPGA_VAB_H
-
#include <stdlib.h>
#include "socfpga_fcs.h"
+/* Macros */
+#define IS_BYTE_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0)
+#define BYTE_ALIGN(x, a) __ALIGN_MASK((x), (typeof(x))(a)-1)
+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
+#define VAB_CERT_HEADER_SIZE sizeof(struct fcs_hps_vab_certificate_header)
+#define VAB_CERT_MAGIC_OFFSET offsetof(struct fcs_hps_vab_certificate_header, d)
+#define VAB_CERT_FIT_SHA384_OFFSET offsetof(struct fcs_hps_vab_certificate_data, fcs_sha384[0])
+#define SDM_CERT_MAGIC_NUM 0x25D04E7F
+#define CHUNKSZ_PER_WD_RESET (256 * 1024)
+#define CCERT_CMD_TEST_PGM_MASK 0x80000000 //TODO: ATF FDT location
+
+/* SHA related return Macro */
+#define ENOVABCERT 1 /* VAB certificate not available */
+#define EIMGERR 2 /* Image format/size not valid */
+#define ETIMEOUT 3 /* Execution timeout */
+#define EPROCESS 4 /* Process error */
+#define EKEYREJECTED 5 /* Key was rejected by service */
+#define EINITREJECTED 6 /* VAB init was rejected */
+
struct fcs_hps_vab_certificate_data {
uint32_t vab_cert_magic_num; /* offset 0x10 */
uint32_t flags;
@@ -27,28 +46,9 @@
/* keychain starts at offset 0x50 */
};
-/* Macros */
-#define IS_BYTE_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0)
-#define BYTE_ALIGN(x, a) __ALIGN_MASK((x), (typeof(x))(a)-1)
-#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
-#define VAB_CERT_HEADER_SIZE sizeof(struct fcs_hps_vab_certificate_header)
-#define VAB_CERT_MAGIC_OFFSET offsetof(struct fcs_hps_vab_certificate_header, d)
-#define VAB_CERT_FIT_SHA384_OFFSET offsetof(struct fcs_hps_vab_certificate_data, fcs_sha384[0])
-#define SDM_CERT_MAGIC_NUM 0x25D04E7F
-#define CHUNKSZ_PER_WD_RESET (256 * 1024)
-
-/* SHA related return Macro */
-#define ENOVABIMG 1 /* VAB certificate not available */
-#define EIMGERR 2 /* Image format/size not valid */
-#define ETIMEOUT 3 /* Execution timeout */
-#define EPROCESS 4 /* Process error */
-#define EKEYREJECTED 5/* Key was rejected by service */
-
/* Function Definitions */
-static size_t get_img_size(uint8_t *img_buf, size_t img_buf_sz);
-int socfpga_vendor_authentication(void **p_image, size_t *p_size);
-static uint32_t get_unaligned_le32(const void *p);
-void sha384_csum_wd(const unsigned char *input, unsigned int ilen,
-unsigned char *output, unsigned int chunk_sz);
-
+size_t get_img_size(uint8_t *img_buf, size_t img_buf_sz);
+uint32_t get_unaligned_le32(const void *p);
+int socfpga_vab_authentication(void **p_image, size_t *p_size);
+int socfpga_vab_init(unsigned int image_id);
#endif
diff --git a/plat/intel/soc/common/lib/sha/sha.c b/plat/intel/soc/common/lib/sha/sha.c
new file mode 100644
index 0000000..9a6adc6
--- /dev/null
+++ b/plat/intel/soc/common/lib/sha/sha.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include <arch_helpers.h>
+#include <common/bl_common.h>
+#include <common/debug.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <drivers/delay_timer.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+#include <tools_share/firmware_image_package.h>
+
+#include "sha.h"
+#include "wdt/watchdog.h"
+
+/* SHA384 certificate ID */
+#define SHA384_H0 0xcbbb9d5dc1059ed8ULL
+#define SHA384_H1 0x629a292a367cd507ULL
+#define SHA384_H2 0x9159015a3070dd17ULL
+#define SHA384_H3 0x152fecd8f70e5939ULL
+#define SHA384_H4 0x67332667ffc00b31ULL
+#define SHA384_H5 0x8eb44a8768581511ULL
+#define SHA384_H6 0xdb0c2e0d64f98fa7ULL
+#define SHA384_H7 0x47b5481dbefa4fa4ULL
+
+/* SHA512 certificate ID */
+#define SHA512_H0 0x6a09e667f3bcc908ULL
+#define SHA512_H1 0xbb67ae8584caa73bULL
+#define SHA512_H2 0x3c6ef372fe94f82bULL
+#define SHA512_H3 0xa54ff53a5f1d36f1ULL
+#define SHA512_H4 0x510e527fade682d1ULL
+#define SHA512_H5 0x9b05688c2b3e6c1fULL
+#define SHA512_H6 0x1f83d9abfb41bd6bULL
+#define SHA512_H7 0x5be0cd19137e2179ULL
+
+void sha384_init(sha512_context *ctx)
+{
+ ctx->state[0] = SHA384_H0;
+ ctx->state[1] = SHA384_H1;
+ ctx->state[2] = SHA384_H2;
+ ctx->state[3] = SHA384_H3;
+ ctx->state[4] = SHA384_H4;
+ ctx->state[5] = SHA384_H5;
+ ctx->state[6] = SHA384_H6;
+ ctx->state[7] = SHA384_H7;
+ ctx->count[0] = ctx->count[1] = 0;
+}
+
+void sha384_update(sha512_context *ctx, const uint8_t *input, uint32_t length)
+{
+ sha512_base_do_update(ctx, input, length);
+}
+
+void sha384_finish(sha512_context *ctx, uint8_t digest[SHA384_SUM_LEN])
+{
+ int i;
+
+ sha512_base_do_finalize(ctx);
+ for (i = 0; i < SHA384_SUM_LEN / sizeof(uint64_t); i++)
+ PUT_UINT64_BE(ctx->state[i], digest, i * 8);
+}
+
+void sha384_start(const unsigned char *input, unsigned int len,
+ unsigned char *output, unsigned int chunk_sz)
+{
+ /* TODO: Shall trigger watchdog for each chuck byte. */
+ sha512_context ctx;
+ const unsigned char *end;
+ unsigned char *curr;
+ int chunk;
+
+ sha384_init(&ctx);
+
+ curr = (unsigned char *)input;
+ end = input + len;
+ while (curr < end) {
+ chunk = end - curr;
+ if (chunk > chunk_sz) {
+ chunk = chunk_sz;
+ }
+ sha384_update(&ctx, curr, chunk);
+ curr += chunk;
+ watchdog_sw_rst();
+ }
+
+ sha384_finish(&ctx, output);
+}
+
+/* SHA512 Start Here */
+void sha512_init(sha512_context *ctx)
+{
+ ctx->state[0] = SHA512_H0;
+ ctx->state[1] = SHA512_H1;
+ ctx->state[2] = SHA512_H2;
+ ctx->state[3] = SHA512_H3;
+ ctx->state[4] = SHA512_H4;
+ ctx->state[5] = SHA512_H5;
+ ctx->state[6] = SHA512_H6;
+ ctx->state[7] = SHA512_H7;
+ ctx->count[0] = ctx->count[1] = 0;
+}
+
+void sha512_update(sha512_context *ctx, const uint8_t *input, uint32_t length)
+{
+ sha512_base_do_update(ctx, input, length);
+}
+
+void sha512_finish(sha512_context *ctx, uint8_t digest[SHA512_SUM_LEN])
+{
+ int i;
+
+ sha512_base_do_finalize(ctx);
+ for (i = 0; i < SHA512_SUM_LEN / sizeof(uint64_t); i++)
+ PUT_UINT64_BE(ctx->state[i], digest, i * 8);
+}
+
+void sha512_start(const unsigned char *input, unsigned int len, unsigned char *output)
+{
+ /* TODO: Shall trigger watchdog for each chuck byte. */
+ sha512_context ctx;
+
+ sha384_init(&ctx);
+ sha512_update(&ctx, input, len);
+ sha512_finish(&ctx, output);
+}
+
+void sha512_transform(uint64_t *state, const uint8_t *input)
+{
+ uint64_t a, b, c, d, e, f, g, h, t1, t2;
+
+ int i;
+ uint64_t W[16];
+
+ /* load the state into our registers */
+ a = state[0]; b = state[1]; c = state[2]; d = state[3];
+ e = state[4]; f = state[5]; g = state[6]; h = state[7];
+
+ /* now iterate */
+ for (i = 0 ; i < 80; i += 8) {
+ if (!(i & 8)) {
+ int j;
+
+ if (i < 16) {
+ /* load the input */
+ for (j = 0; j < 16; j++)
+ LOAD_OP(i + j, W, input);
+ } else {
+ for (j = 0; j < 16; j++) {
+ BLEND_OP(i + j, W);
+ }
+ }
+ }
+
+ t1 = h + e1(e) + Ch(e, f, g) + sha512_K[i] + W[(i & 15)];
+ t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2;
+ t1 = g + e1(d) + Ch(d, e, f) + sha512_K[i+1] + W[(i & 15) + 1];
+ t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2;
+ t1 = f + e1(c) + Ch(c, d, e) + sha512_K[i+2] + W[(i & 15) + 2];
+ t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2;
+ t1 = e + e1(b) + Ch(b, c, d) + sha512_K[i+3] + W[(i & 15) + 3];
+ t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2;
+ t1 = d + e1(a) + Ch(a, b, c) + sha512_K[i+4] + W[(i & 15) + 4];
+ t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2;
+ t1 = c + e1(h) + Ch(h, a, b) + sha512_K[i+5] + W[(i & 15) + 5];
+ t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2;
+ t1 = b + e1(g) + Ch(g, h, a) + sha512_K[i+6] + W[(i & 15) + 6];
+ t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2;
+ t1 = a + e1(f) + Ch(f, g, h) + sha512_K[i+7] + W[(i & 15) + 7];
+ t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2;
+ }
+
+ state[0] += a; state[1] += b; state[2] += c; state[3] += d;
+ state[4] += e; state[5] += f; state[6] += g; state[7] += h;
+
+ /* erase our data */
+ a = b = c = d = e = f = g = h = t1 = t2 = 0;
+}
+
+void sha512_block_fn(sha512_context *sst, const uint8_t *src,
+ int blocks)
+{
+ while (blocks--) {
+ sha512_transform(sst->state, src);
+ src += SHA512_BLOCK_SIZE;
+ }
+}
+
+
+void sha512_base_do_finalize(sha512_context *sctx)
+{
+ const int bit_offset = SHA512_BLOCK_SIZE - sizeof(uint64_t[2]);
+ uint64_t *bits = (uint64_t *)(sctx->buf + bit_offset);
+ unsigned int partial = sctx->count[0] % SHA512_BLOCK_SIZE;
+
+ sctx->buf[partial++] = 0x80;
+ if (partial > bit_offset) {
+ memset(sctx->buf + partial, 0x0, SHA512_BLOCK_SIZE - partial);
+ partial = 0;
+
+ sha512_block_fn(sctx, sctx->buf, 1);
+ }
+
+ memset(sctx->buf + partial, 0x0, bit_offset - partial);
+ bits[0] = cpu_to_be64(sctx->count[1] << 3 | sctx->count[0] >> 61);
+ bits[1] = cpu_to_be64(sctx->count[0] << 3);
+
+ sha512_block_fn(sctx, sctx->buf, 1);
+}
+
+void sha512_base_do_update(sha512_context *sctx,
+ const uint8_t *data,
+ unsigned int len)
+{
+ unsigned int partial = sctx->count[0] % SHA512_BLOCK_SIZE;
+
+ sctx->count[0] += len;
+ if (sctx->count[0] < len)
+ sctx->count[1]++;
+
+ if (((partial + len) >= SHA512_BLOCK_SIZE)) {
+ int blocks;
+
+ if (partial) {
+ int p = SHA512_BLOCK_SIZE - partial;
+
+ memcpy(sctx->buf + partial, data, p);
+ data += p;
+ len -= p;
+
+ sha512_block_fn(sctx, sctx->buf, 1);
+ }
+
+ blocks = len / SHA512_BLOCK_SIZE;
+ len %= SHA512_BLOCK_SIZE;
+
+ if (blocks) {
+ sha512_block_fn(sctx, data, blocks);
+ data += blocks * SHA512_BLOCK_SIZE;
+ }
+ partial = 0;
+ }
+ if (len)
+ memcpy(sctx->buf + partial, data, len);
+}
diff --git a/plat/intel/soc/common/lib/sha/sha.h b/plat/intel/soc/common/lib/sha/sha.h
new file mode 100644
index 0000000..41b5fa8
--- /dev/null
+++ b/plat/intel/soc/common/lib/sha/sha.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SOCFPGA_SHA_H
+#define SOCFPGA_SHA_H
+
+#include <stdlib.h>
+
+
+#define SHA384_SUM_LEN 48
+#define SHA384_DER_LEN 19
+#define SHA512_SUM_LEN 64
+#define SHA512_DER_LEN 19
+#define SHA512_BLOCK_SIZE 128
+
+
+/* MACRO Function */
+#define GET_UINT64_BE(n, b, i) { \
+ (n) = ((unsigned long long) (b)[(i)] << 56) |\
+ ((unsigned long long) (b)[(i) + 1] << 48) |\
+ ((unsigned long long) (b)[(i) + 2] << 40) |\
+ ((unsigned long long) (b)[(i) + 3] << 32) |\
+ ((unsigned long long) (b)[(i) + 4] << 24) |\
+ ((unsigned long long) (b)[(i) + 5] << 16) |\
+ ((unsigned long long) (b)[(i) + 6] << 8) |\
+ ((unsigned long long) (b)[(i) + 7]);\
+}
+
+#define PUT_UINT64_BE(n, b, i) { \
+ (b)[(i)] = (unsigned char) ((n) >> 56);\
+ (b)[(i) + 1] = (unsigned char) ((n) >> 48);\
+ (b)[(i) + 2] = (unsigned char) ((n) >> 40);\
+ (b)[(i) + 3] = (unsigned char) ((n) >> 32);\
+ (b)[(i) + 4] = (unsigned char) ((n) >> 24);\
+ (b)[(i) + 5] = (unsigned char) ((n) >> 16);\
+ (b)[(i) + 6] = (unsigned char) ((n) >> 8);\
+ (b)[(i) + 7] = (unsigned char) ((n));\
+}
+
+#define e0(x) (ror64(x, 28) ^ ror64(x, 34) ^ ror64(x, 39))
+#define e1(x) (ror64(x, 14) ^ ror64(x, 18) ^ ror64(x, 41))
+#define s0(x) (ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7))
+#define s1(x) (ror64(x, 19) ^ ror64(x, 61) ^ (x >> 6))
+
+/* Inline Function Definitions */
+/* ror64() to rotate its right in 64 bits. */
+static inline uint64_t ror64(uint64_t input, unsigned int shift)
+{
+ return (input >> (shift & 63)) | (input << ((-shift) & 63));
+}
+
+static inline uint64_t Ch(uint64_t x, uint64_t y, uint64_t z)
+{
+ return z ^ (x & (y ^ z));
+}
+
+static inline uint64_t Maj(uint64_t x, uint64_t y, uint64_t z)
+{
+ return (x & y) | (z & (x | y));
+}
+
+static inline void LOAD_OP(int I, uint64_t *W, const uint8_t *input)
+{
+ GET_UINT64_BE(W[I], input, I*8);
+}
+
+static inline void BLEND_OP(int I, uint64_t *W)
+{
+ W[I & 15] += s1(W[(I-2) & 15]) + W[(I-7) & 15] + s0(W[(I-15) & 15]);
+}
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+inline uint32_t le32_to_cpue(const uint32_t *p)
+{
+ return (uint32_t)*p;
+}
+#else
+inline uint32_t le32_to_cpue(const uint32_t *p)
+{
+ return swab32(*p);
+}
+#endif
+
+static const uint64_t sha512_K[80] = {
+ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
+ 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL,
+ 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL,
+ 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL,
+ 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL,
+ 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL,
+ 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL,
+ 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL,
+ 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL,
+ 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL,
+ 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL,
+ 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL,
+ 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL,
+ 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL,
+};
+
+#define __cpu_to_le64(x) ((__force __le64)(__u64)(x))
+
+#define _uswap_64(x, sfx) \
+ ((((x) & 0xff00000000000000##sfx) >> 56) |\
+ (((x) & 0x00ff000000000000##sfx) >> 40) |\
+ (((x) & 0x0000ff0000000000##sfx) >> 24) |\
+ (((x) & 0x000000ff00000000##sfx) >> 8) |\
+ (((x) & 0x00000000ff000000##sfx) << 8) |\
+ (((x) & 0x0000000000ff0000##sfx) << 24) |\
+ (((x) & 0x000000000000ff00##sfx) << 40) |\
+ (((x) & 0x00000000000000ff##sfx) << 56))
+
+#if defined(__GNUC__)
+#define uswap_64(x) _uswap_64(x, ull)
+#else
+#define uswap_64(x) _uswap_64(x)
+#endif
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define cpu_to_be64(x) uswap_64(x)
+#else
+#define cpu_to_be64(x) (x)
+#endif
+
+typedef struct {
+ uint64_t state[SHA512_SUM_LEN / 8];
+ uint64_t count[2];
+ uint8_t buf[SHA512_BLOCK_SIZE];
+} sha512_context;
+
+/* Function Definitions */
+/* SHA384 Start Here */
+void sha384_init(sha512_context *ctx);
+void sha384_update(sha512_context *ctx, const uint8_t *input, uint32_t length);
+void sha384_finish(sha512_context *ctx, uint8_t digest[SHA384_SUM_LEN]);
+void sha384_start(const unsigned char *input, unsigned int len,
+ unsigned char *output, unsigned int chunk_sz);
+/* SHA512 Start Here */
+void sha512_init(sha512_context *ctx);
+void sha512_update(sha512_context *ctx, const uint8_t *input, uint32_t length);
+void sha512_finish(sha512_context *ctx, uint8_t digest[SHA512_SUM_LEN]);
+void sha512_start(const unsigned char *input, unsigned int len,
+ unsigned char *output);
+void sha512_transform(uint64_t *state, const uint8_t *input);
+void sha512_block_fn(sha512_context *sst, const uint8_t *src, int blocks);
+void sha512_base_do_finalize(sha512_context *sctx);
+void sha512_base_do_update(sha512_context *sctx, const uint8_t *data,
+ unsigned int len);
+
+#endif
diff --git a/plat/intel/soc/common/sip/socfpga_sip_fcs.c b/plat/intel/soc/common/sip/socfpga_sip_fcs.c
index adeb069..91df934 100644
--- a/plat/intel/soc/common/sip/socfpga_sip_fcs.c
+++ b/plat/intel/soc/common/sip/socfpga_sip_fcs.c
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2020-2022, Intel Corporation. All rights reserved.
+ * Copyright (c) 2020-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -1164,8 +1165,8 @@
return INTEL_SIP_SMC_STATUS_REJECTED;
}
- memcpy((uint8_t *) &payload[i], (uint8_t *) mac_offset,
- src_size - data_size);
+ memcpy_s(&payload[i], (src_size - data_size) / MBOX_WORD_BYTE,
+ (void *) mac_offset, (src_size - data_size) / MBOX_WORD_BYTE);
i += (src_size - data_size) / MBOX_WORD_BYTE;
}
@@ -1298,8 +1299,8 @@
return INTEL_SIP_SMC_STATUS_REJECTED;
}
- memcpy((uint8_t *) &payload[i], (uint8_t *) mac_offset,
- src_size - data_size);
+ memcpy_s(&payload[i], (src_size - data_size) / MBOX_WORD_BYTE,
+ (void *) mac_offset, (src_size - data_size) / MBOX_WORD_BYTE);
memset((void *) dst_addr, 0, *dst_size);
@@ -1401,8 +1402,8 @@
return INTEL_SIP_SMC_STATUS_REJECTED;
}
- memcpy((uint8_t *) &payload[i], (uint8_t *) hash_data_addr,
- src_size);
+ memcpy_s(&payload[i], src_size / MBOX_WORD_BYTE,
+ (void *) hash_data_addr, src_size / MBOX_WORD_BYTE);
i += src_size / MBOX_WORD_BYTE;
@@ -1502,8 +1503,8 @@
return INTEL_SIP_SMC_STATUS_REJECTED;
}
- memcpy((uint8_t *) &payload[i],
- (uint8_t *) hash_sig_pubkey_addr, src_size);
+ memcpy_s(&payload[i], src_size / MBOX_WORD_BYTE,
+ (void *) hash_sig_pubkey_addr, src_size / MBOX_WORD_BYTE);
i += (src_size / MBOX_WORD_BYTE);
@@ -1839,8 +1840,8 @@
return INTEL_SIP_SMC_STATUS_REJECTED;
}
- memcpy((uint8_t *) &payload[i], (uint8_t *) sig_pubkey_offset,
- src_size - data_size);
+ memcpy_s(&payload[i], (src_size - data_size) / MBOX_WORD_BYTE,
+ (void *) sig_pubkey_offset, (src_size - data_size) / MBOX_WORD_BYTE);
i += (src_size - data_size) / MBOX_WORD_BYTE;
}
@@ -1971,8 +1972,8 @@
return INTEL_SIP_SMC_STATUS_REJECTED;
}
- memcpy((uint8_t *) &payload[i], (uint8_t *) sig_pubkey_offset,
- src_size - data_size);
+ memcpy_s(&payload[i], (src_size - data_size) / MBOX_WORD_BYTE,
+ (void *) sig_pubkey_offset, (src_size - data_size) / MBOX_WORD_BYTE);
memset((void *) dst_addr, 0, *dst_size);
@@ -2145,7 +2146,8 @@
return INTEL_SIP_SMC_STATUS_REJECTED;
}
- memcpy((uint8_t *) &payload[i], (uint8_t *) pubkey, src_size);
+ memcpy_s(&payload[i], src_size / MBOX_WORD_BYTE,
+ (void *) pubkey, src_size / MBOX_WORD_BYTE);
i += src_size / MBOX_WORD_BYTE;
status = mailbox_send_cmd(MBOX_JOB_ID, MBOX_FCS_ECDH_REQUEST,
@@ -2223,8 +2225,8 @@
fcs_aes_init_payload.param_size = param_size;
fcs_aes_init_payload.key_id = key_id;
- memcpy((uint8_t *) fcs_aes_init_payload.crypto_param,
- (uint8_t *) param_addr, param_size);
+ memcpy_s(fcs_aes_init_payload.crypto_param, param_size / MBOX_WORD_BYTE,
+ (void *) param_addr, param_size / MBOX_WORD_BYTE);
fcs_aes_init_payload.is_updated = 0;
@@ -2304,9 +2306,10 @@
return INTEL_SIP_SMC_STATUS_REJECTED;
}
- memcpy((uint8_t *) &fcs_aes_crypt_payload[i],
- (uint8_t *) fcs_aes_init_payload.crypto_param,
- fcs_aes_init_payload.param_size);
+ memcpy_s(&fcs_aes_crypt_payload[i],
+ fcs_aes_init_payload.param_size / MBOX_WORD_BYTE,
+ (void *) fcs_aes_init_payload.crypto_param,
+ fcs_aes_init_payload.param_size / MBOX_WORD_BYTE);
i += fcs_aes_init_payload.param_size / MBOX_WORD_BYTE;
}
diff --git a/plat/intel/soc/common/soc/socfpga_handoff.c b/plat/intel/soc/common/soc/socfpga_handoff.c
index 526c6e1..6974768 100644
--- a/plat/intel/soc/common/soc/socfpga_handoff.c
+++ b/plat/intel/soc/common/soc/socfpga_handoff.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -15,15 +16,21 @@
int socfpga_get_handoff(handoff *reverse_hoff_ptr)
{
int i;
+ int j;
uint32_t *buffer;
- handoff *handoff_ptr = (handoff *) PLAT_HANDOFF_OFFSET;
+ uint32_t *handoff_ptr = (uint32_t *) PLAT_HANDOFF_OFFSET;
+ uint32_t *reverse_hoff_ptr_dst = (uint32_t *) reverse_hoff_ptr;
if (sizeof(*handoff_ptr) > sizeof(handoff)) {
return -EOVERFLOW;
}
- memcpy(reverse_hoff_ptr, handoff_ptr, sizeof(handoff));
- buffer = (uint32_t *)reverse_hoff_ptr;
+ for (j = 0; j < sizeof(handoff) / 4; j++) {
+ memcpy_s((void *) (reverse_hoff_ptr_dst + j), 1,
+ (void *) (handoff_ptr + j), 1);
+ }
+
+ buffer = (uint32_t *)reverse_hoff_ptr_dst;
/* convert big endian to little endian */
for (i = 0; i < sizeof(handoff) / 4; i++)
diff --git a/plat/intel/soc/common/soc/socfpga_mailbox.c b/plat/intel/soc/common/soc/socfpga_mailbox.c
index b8e5cde..74ecc95 100644
--- a/plat/intel/soc/common/soc/socfpga_mailbox.c
+++ b/plat/intel/soc/common/soc/socfpga_mailbox.c
@@ -252,7 +252,7 @@
return MBOX_RET_ERROR;
}
- memcpy((uint8_t *) response,
+ memcpy_s((uint8_t *) response, *resp_len * MBOX_WORD_BYTE,
(uint8_t *) mailbox_resp_ctr.payload->data,
*resp_len * MBOX_WORD_BYTE);
}
diff --git a/plat/intel/soc/common/soc/socfpga_reset_manager.c b/plat/intel/soc/common/soc/socfpga_reset_manager.c
index 5c80798..535e68f 100644
--- a/plat/intel/soc/common/soc/socfpga_reset_manager.c
+++ b/plat/intel/soc/common/soc/socfpga_reset_manager.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -106,29 +107,9 @@
}
udelay(1000);
}
- return -ETIMEDOUT;
-}
-
-#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
-static int poll_idle_status_by_counter(uint32_t addr, uint32_t mask,
- uint32_t match, uint32_t delay_ms)
-{
- int time_out = delay_ms;
-
- while (time_out-- > 0) {
- if ((mmio_read_32(addr) & mask) == match) {
- return 0;
- }
-
- /* ToDo: Shall use udelay for product release */
- for (int i = 0; i < 2000; i++) {
- /* dummy delay */
- }
- }
return -ETIMEDOUT;
}
-#endif
#if PLATFORM_MODEL != PLAT_SOCFPGA_AGILEX5
static int poll_idle_status_by_clkcycles(uint32_t addr, uint32_t mask,
@@ -406,6 +387,7 @@
return ret;
}
+/* TODO: Function too long, shall refactor */
int socfpga_bridges_enable(uint32_t mask)
{
int ret = 0;
@@ -419,54 +401,79 @@
uint32_t f2s_respempty = 0;
uint32_t f2s_cmdidle = 0;
#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
- uint32_t delay = 0;
+ uint32_t brg_lst = 0;
#endif
/* Enable s2f bridge */
socfpga_s2f_bridge_mask(mask, &brg_mask, &noc_mask);
#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
- /* Enable SOC2FPGA bridge */
- if (brg_mask & RSTMGR_BRGMODRSTMASK_SOC2FPGA) {
+/**************** SOC2FPGA ****************/
+ brg_lst = mmio_read_32(SOCFPGA_RSTMGR(BRGMODRST));
+ if ((brg_mask & RSTMGR_BRGMODRSTMASK_SOC2FPGA)
+ && ((brg_lst & RSTMGR_BRGMODRSTMASK_SOC2FPGA) != 0)) {
/*
* To request handshake
* Write Reset Manager hdskreq[soc2fpga_flush_req] = 1
*/
VERBOSE("Set S2F hdskreq ...\n");
mmio_setbits_32(SOCFPGA_RSTMGR(HDSKREQ),
- RSTMGR_HDSKREQ_SOC2FPGAREQ);
+ ((~(brg_lst) << 9) & (RSTMGR_HDSKREQ_LWSOC2FPGAREQ
+ | RSTMGR_HDSKREQ_SOC2FPGAREQ))
+ | (RSTMGR_HDSKREQ_SOC2FPGAREQ));
+
+ udelay(1000);
/*
* To poll idle status
* Read Reset Manager hdskack[soc2fpga] = 1
*/
- ret = poll_idle_status_by_counter(SOCFPGA_RSTMGR(HDSKACK),
- RSTMGR_HDSKACK_SOC2FPGAACK, RSTMGR_HDSKACK_SOC2FPGAACK,
- 300);
+ if ((mmio_read_32(SOCFPGA_RSTMGR(BRGMODRST))
+ & RSTMGR_BRGMODRST_SOC2FPGA) == 0x00) {
+ ret = poll_idle_status(SOCFPGA_RSTMGR(HDSKACK),
+ RSTMGR_HDSKREQ_SOC2FPGAREQ, RSTMGR_HDSKREQ_SOC2FPGAREQ,
+ 300);
+ }
+
+ udelay(1000);
if (ret < 0) {
ERROR("S2F bridge enable: Timeout hdskack\n");
}
/*
+ * To assert reset
+ * Write Reset Manager hdskreq[soc2fpga_flush_req] = 0
+ */
+ VERBOSE("Assert S2F ...\n");
+ mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST),
+ (~brg_lst & 0x3) | RSTMGR_BRGMODRST_SOC2FPGA);
+
+ udelay(1000);
+
+ /*
* To clear idle request
* Write Reset Manager hdskreq[soc2fpga_flush_req] = 0
*/
VERBOSE("Clear S2F hdskreq ...\n");
mmio_clrbits_32(SOCFPGA_RSTMGR(HDSKREQ),
- RSTMGR_HDSKREQ_SOC2FPGAREQ);
+ ((~(brg_lst) << 9) & (RSTMGR_HDSKREQ_LWSOC2FPGAREQ
+ | RSTMGR_HDSKREQ_SOC2FPGAREQ))
+ | (RSTMGR_HDSKREQ_SOC2FPGAREQ));
+
+ udelay(1000);
/*
- * To assert reset
- * Write Reset Manager hdskreq[soc2fpga_flush_req] = 0
+ * To clear ack status
+ * Write Reset Manager hdskack[soc2fpga_flush_ack] = 1
+ * This bit is W1S/W1C
*/
- VERBOSE("Assert S2F ...\n");
- mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST),
- RSTMGR_BRGMODRST_SOC2FPGA);
+ VERBOSE("Clear S2F hdskack ...\n");
+ mmio_setbits_32(SOCFPGA_RSTMGR(HDSKACK),
+ ((~(brg_lst) << 9) & (RSTMGR_HDSKREQ_LWSOC2FPGAREQ
+ | RSTMGR_HDSKREQ_SOC2FPGAREQ))
+ | (RSTMGR_HDSKACK_SOC2FPGAACK));
- /* ToDo: Shall use udelay for product release */
- for (delay = 0; delay < 1000; delay++) {
- /* dummy delay */
- }
+ udelay(1000);
/*
* To deassert reset
@@ -474,51 +481,82 @@
*/
VERBOSE("Deassert S2F ...\n");
mmio_clrbits_32(SOCFPGA_RSTMGR(BRGMODRST),
- RSTMGR_BRGMODRST_SOC2FPGA);
+ (~brg_lst & (RSTMGR_BRGMODRST_SOC2FPGA
+ | RSTMGR_BRGMODRST_LWHPS2FPGA))
+ | RSTMGR_BRGMODRST_SOC2FPGA);
}
+/**************** LWSOCFPGA ****************/
+
/* Enable LWSOC2FPGA bridge */
- if (brg_mask & RSTMGR_BRGMODRSTMASK_LWHPS2FPGA) {
+ brg_lst = mmio_read_32(SOCFPGA_RSTMGR(BRGMODRST));
+ if ((brg_mask & RSTMGR_BRGMODRSTMASK_LWHPS2FPGA)
+ && ((brg_lst & RSTMGR_BRGMODRSTMASK_LWHPS2FPGA) != 0)) {
/*
* To request handshake
* Write Reset Manager hdskreq[lwsoc2fpga_flush_req] = 1
*/
VERBOSE("Set LWS2F hdskreq ...\n");
mmio_setbits_32(SOCFPGA_RSTMGR(HDSKREQ),
- RSTMGR_HDSKREQ_LWSOC2FPGAREQ);
+ ((~(brg_lst) << 9) & (RSTMGR_HDSKREQ_LWSOC2FPGAREQ
+ | RSTMGR_HDSKREQ_SOC2FPGAREQ))
+ | (RSTMGR_HDSKREQ_LWSOC2FPGAREQ));
+
+ udelay(1000);
/*
* To poll idle status
* Read Reset Manager hdskack[lwsoc2fpga] = 1
*/
- ret = poll_idle_status_by_counter(SOCFPGA_RSTMGR(HDSKACK),
- RSTMGR_HDSKACK_LWSOC2FPGAACK, RSTMGR_HDSKACK_LWSOC2FPGAACK,
- 300);
+ if ((mmio_read_32(SOCFPGA_RSTMGR(BRGMODRST))
+ & RSTMGR_BRGMODRST_LWHPS2FPGA) == 0x00) {
+ ret = poll_idle_status(SOCFPGA_RSTMGR(HDSKACK),
+ RSTMGR_HDSKREQ_LWSOC2FPGAREQ, RSTMGR_HDSKREQ_LWSOC2FPGAREQ,
+ 300);
+ }
+
+ udelay(1000);
if (ret < 0) {
ERROR("LWS2F bridge enable: Timeout hdskack\n");
}
/*
+ * To assert reset
+ * Write Reset Manager brgmodrst[lwsoc2fpga] = 1
+ */
+ VERBOSE("Assert LWS2F ...\n");
+ mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST),
+ (~brg_lst & (RSTMGR_BRGMODRST_SOC2FPGA
+ | RSTMGR_BRGMODRST_LWHPS2FPGA))
+ | RSTMGR_BRGMODRST_LWHPS2FPGA);
+
+ udelay(1000);
+
+ /*
* To clear idle request
* Write Reset Manager hdskreq[lwsoc2fpga_flush_req] = 0
*/
VERBOSE("Clear LWS2F hdskreq ...\n");
mmio_clrbits_32(SOCFPGA_RSTMGR(HDSKREQ),
- RSTMGR_HDSKREQ_LWSOC2FPGAREQ);
+ ((~(brg_lst) << 9) & (RSTMGR_HDSKREQ_LWSOC2FPGAREQ
+ | RSTMGR_HDSKREQ_SOC2FPGAREQ))
+ | (RSTMGR_HDSKREQ_LWSOC2FPGAREQ));
+
+ udelay(1000);
/*
- * To assert reset
- * Write Reset Manager brgmodrst[lwsoc2fpga] = 1
+ * To clear ack status
+ * Write Reset Manager hdskack[lwsoc2fpga_flush_ack] = 1
+ * This bit is W1S/W1C
*/
- VERBOSE("Assert LWS2F ...\n");
- mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST),
- RSTMGR_BRGMODRST_LWHPS2FPGA);
+ VERBOSE("Clear LWS2F hdskack ...\n");
+ mmio_setbits_32(SOCFPGA_RSTMGR(HDSKACK),
+ ((~(brg_lst) << 9) & (RSTMGR_HDSKREQ_LWSOC2FPGAREQ
+ | RSTMGR_HDSKREQ_SOC2FPGAREQ))
+ | (RSTMGR_HDSKACK_SOC2FPGAACK));
- /* ToDo: Shall use udelay for product release */
- for (delay = 0; delay < 1000; delay++) {
- /* dummy delay */
- }
+ udelay(1000);
/*
* To deassert reset
@@ -526,7 +564,9 @@
*/
VERBOSE("Deassert LWS2F ...\n");
mmio_clrbits_32(SOCFPGA_RSTMGR(BRGMODRST),
- RSTMGR_BRGMODRST_LWHPS2FPGA);
+ ((~brg_lst & (RSTMGR_BRGMODRST_SOC2FPGA
+ | RSTMGR_BRGMODRST_LWHPS2FPGA)))
+ | RSTMGR_BRGMODRST_LWHPS2FPGA);
}
#else
if (brg_mask != 0U) {
@@ -552,7 +592,9 @@
&f2s_idleack, &f2s_respempty, &f2s_cmdidle);
#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
/* Enable FPGA2SOC bridge */
- if (brg_mask & RSTMGR_BRGMODRSTMASK_FPGA2SOC) {
+
+ if ((brg_mask & RSTMGR_BRGMODRSTMASK_FPGA2SOC)
+ && ((brg_lst & RSTMGR_BRGMODRSTMASK_FPGA2SOC) != 0)) {
/*
* To request handshake
* Write Reset Manager hdsken[fpgahsen] = 1
@@ -572,9 +614,12 @@
* Read Reset Manager hdskack[fpgahsack] = 1
*/
VERBOSE("Get FPGA hdskack(fpgahsack) ...\n");
- ret = poll_idle_status_by_counter(SOCFPGA_RSTMGR(HDSKACK),
- RSTMGR_HDSKACK_FPGAHSACK, RSTMGR_HDSKACK_FPGAHSACK,
- 300);
+ if ((mmio_read_32(SOCFPGA_RSTMGR(BRGMODRST))
+ & RSTMGR_BRGMODRST_FPGA2SOC) == 0x00) {
+ ret = poll_idle_status(SOCFPGA_RSTMGR(HDSKACK),
+ RSTMGR_HDSKACK_FPGAHSACK, RSTMGR_HDSKACK_FPGAHSACK,
+ 300);
+ }
if (ret < 0) {
ERROR("FPGA bridge fpga handshake fpgahsreq: Timeout\n");
@@ -593,9 +638,12 @@
* Read Reset Manager hdskack[f2s_flush_ack] = 1
*/
VERBOSE("Get F2S hdskack(f2s_flush_ack) ...\n");
- ret = poll_idle_status_by_counter(SOCFPGA_RSTMGR(HDSKACK),
- RSTMGR_HDSKACK_FPGA2SOCACK, RSTMGR_HDSKACK_FPGA2SOCACK,
- 300);
+ if ((mmio_read_32(SOCFPGA_RSTMGR(BRGMODRST))
+ & RSTMGR_BRGMODRST_FPGA2SOC) == 0x00) {
+ ret = poll_idle_status(SOCFPGA_RSTMGR(HDSKACK),
+ RSTMGR_HDSKACK_FPGA2SOCACK, RSTMGR_HDSKACK_FPGA2SOCACK,
+ 300);
+ }
if (ret < 0) {
ERROR("F2S bridge fpga handshake f2sdram_flush_req: Timeout\n");
@@ -621,9 +669,12 @@
* Read Reset Manager hdskack[f2s_flush_ack] = 0
*/
VERBOSE("Get F2SDRAM hdskack(f2s_flush_ack) ...\n");
- ret = poll_idle_status_by_counter(SOCFPGA_RSTMGR(HDSKACK),
- RSTMGR_HDSKACK_FPGA2SOCACK, RSTMGR_HDSKACK_FPGA2SOCACK_DASRT,
- 300);
+ if ((mmio_read_32(SOCFPGA_RSTMGR(BRGMODRST))
+ & RSTMGR_BRGMODRST_FPGA2SOC) == 0x00) {
+ ret = poll_idle_status(SOCFPGA_RSTMGR(HDSKACK),
+ RSTMGR_HDSKACK_FPGA2SOCACK, RSTMGR_HDSKACK_FPGA2SOCACK_DASRT,
+ 300);
+ }
if (ret < 0) {
ERROR("F2S bridge fpga handshake f2s_flush_ack: Timeout\n");
@@ -634,9 +685,12 @@
* Read Reset Manager hdskack[fpgahsack] = 0
*/
VERBOSE("Get FPGA hdskack(fpgahsack) ...\n");
- ret = poll_idle_status_by_counter(SOCFPGA_RSTMGR(HDSKACK),
- RSTMGR_HDSKACK_FPGAHSACK, RSTMGR_HDSKACK_FPGAHSACK_DASRT,
- 300);
+ if ((mmio_read_32(SOCFPGA_RSTMGR(BRGMODRST))
+ & RSTMGR_BRGMODRST_FPGA2SOC) == 0x00) {
+ ret = poll_idle_status(SOCFPGA_RSTMGR(HDSKACK),
+ RSTMGR_HDSKACK_FPGAHSACK, RSTMGR_HDSKACK_FPGAHSACK_DASRT,
+ 300);
+ }
if (ret < 0) {
ERROR("F2S bridge fpga handshake fpgahsack: Timeout\n");
@@ -649,10 +703,7 @@
VERBOSE("Assert F2S ...\n");
mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST), RSTMGR_BRGMODRST_FPGA2SOC);
- /* ToDo: Shall use udelay for product release */
- for (delay = 0; delay < 1000; delay++) {
- /* dummy delay */
- }
+ udelay(1000);
/*
* To deassert reset
@@ -668,7 +719,8 @@
}
/* Enable FPGA2SDRAM bridge */
- if (brg_mask & RSTMGR_BRGMODRSTMASK_F2SDRAM0) {
+ if ((brg_mask & RSTMGR_BRGMODRSTMASK_F2SDRAM0)
+ && ((brg_lst & RSTMGR_BRGMODRSTMASK_F2SDRAM0) != 0)) {
/*
* To request handshake
* Write Reset Manager hdsken[fpgahsen] = 1
@@ -688,9 +740,12 @@
* Read Reset Manager hdskack[fpgahsack] = 1
*/
VERBOSE("Get F2SDRAM hdskack(fpgahsack) ...\n");
- ret = poll_idle_status_by_counter(SOCFPGA_RSTMGR(HDSKACK),
- RSTMGR_HDSKACK_FPGAHSACK, RSTMGR_HDSKACK_FPGAHSACK,
- 300);
+ if ((mmio_read_32(SOCFPGA_RSTMGR(BRGMODRST))
+ & RSTMGR_BRGMODRSTMASK_F2SDRAM0) == 0x00) {
+ ret = poll_idle_status(SOCFPGA_RSTMGR(HDSKACK),
+ RSTMGR_HDSKACK_FPGAHSACK, RSTMGR_HDSKACK_FPGAHSACK,
+ 300);
+ }
if (ret < 0) {
ERROR("F2SDRAM bridge fpga handshake fpgahsreq: Timeout\n");
@@ -709,9 +764,12 @@
* Read Reset Manager hdskack[f2sdram_flush_ack] = 1
*/
VERBOSE("Get F2SDRAM hdskack(f2sdram_flush_ack) ...\n");
- ret = poll_idle_status_by_counter(SOCFPGA_RSTMGR(HDSKACK),
- RSTMGR_HDSKACK_F2SDRAM0ACK, RSTMGR_HDSKACK_F2SDRAM0ACK,
- 300);
+ if ((mmio_read_32(SOCFPGA_RSTMGR(BRGMODRST))
+ & RSTMGR_BRGMODRSTMASK_F2SDRAM0) == 0x00) {
+ ret = poll_idle_status(SOCFPGA_RSTMGR(HDSKACK),
+ RSTMGR_HDSKACK_F2SDRAM0ACK, RSTMGR_HDSKACK_F2SDRAM0ACK,
+ 300);
+ }
if (ret < 0) {
ERROR("F2SDRAM bridge fpga handshake f2sdram_flush_req: Timeout\n");
@@ -736,9 +794,12 @@
* Read Reset Manager hdskack[f2sdram_flush_ack] = 0
*/
VERBOSE("Get F2SDRAM hdskack(f2sdram_flush_ack) ...\n");
- ret = poll_idle_status_by_counter(SOCFPGA_RSTMGR(HDSKACK),
- RSTMGR_HDSKACK_F2SDRAM0ACK, RSTMGR_HDSKACK_F2SDRAM0ACK_DASRT,
- 300);
+ if ((mmio_read_32(SOCFPGA_RSTMGR(BRGMODRST))
+ & RSTMGR_BRGMODRSTMASK_F2SDRAM0) == 0x00) {
+ ret = poll_idle_status(SOCFPGA_RSTMGR(HDSKACK),
+ RSTMGR_HDSKACK_F2SDRAM0ACK, RSTMGR_HDSKACK_F2SDRAM0ACK_DASRT,
+ 300);
+ }
if (ret < 0) {
ERROR("F2SDRAM bridge fpga handshake f2sdram_flush_ack: Timeout\n");
@@ -749,9 +810,12 @@
* Read Reset Manager hdskack[fpgahsack] = 0
*/
VERBOSE("Get F2SDRAM hdskack(fpgahsack) ...\n");
- ret = poll_idle_status_by_counter(SOCFPGA_RSTMGR(HDSKACK),
- RSTMGR_HDSKACK_FPGAHSACK, RSTMGR_HDSKACK_FPGAHSACK_DASRT,
- 300);
+ if ((mmio_read_32(SOCFPGA_RSTMGR(BRGMODRST))
+ & RSTMGR_BRGMODRSTMASK_F2SDRAM0) == 0x00) {
+ ret = poll_idle_status(SOCFPGA_RSTMGR(HDSKACK),
+ RSTMGR_HDSKACK_FPGAHSACK, RSTMGR_HDSKACK_FPGAHSACK_DASRT,
+ 300);
+ }
if (ret < 0) {
ERROR("F2SDRAM bridge fpga handshake fpgahsack: Timeout\n");
@@ -765,10 +829,7 @@
mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST),
RSTMGR_BRGMODRST_F2SSDRAM0);
- /* ToDo: Shall use udelay for product release */
- for (delay = 0; delay < 1000; delay++) {
- /* dummy delay */
- }
+ udelay(1000);
/*
* To deassert reset
@@ -863,10 +924,6 @@
uint32_t f2s_idleack = 0;
uint32_t f2s_respempty = 0;
uint32_t f2s_cmdidle = 0;
-#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
- uint32_t delay = 0;
-#endif
-
/* Disable s2f bridge */
socfpga_s2f_bridge_mask(mask, &brg_mask, &noc_mask);
@@ -885,7 +942,7 @@
* To poll idle status
* Read Reset Manager hdskack[soc2fpga] = 0
*/
- ret = poll_idle_status_by_counter(SOCFPGA_RSTMGR(HDSKACK),
+ ret = poll_idle_status(SOCFPGA_RSTMGR(HDSKACK),
RSTMGR_HDSKACK_SOC2FPGAACK, RSTMGR_HDSKACK_SOC2FPGAACK_DASRT,
300);
@@ -901,10 +958,7 @@
mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST),
RSTMGR_BRGMODRST_SOC2FPGA);
- /* ToDo: Shall use udelay for product release */
- for (delay = 0; delay < 1000; delay++) {
- /* dummy delay */
- }
+ udelay(1000);
}
/* Disable LWSOC2FPGA bridge */
@@ -921,7 +975,7 @@
* To poll idle status
* Read Reset Manager hdskack[lwsoc2fpga] = 0
*/
- ret = poll_idle_status_by_counter(SOCFPGA_RSTMGR(HDSKACK),
+ ret = poll_idle_status(SOCFPGA_RSTMGR(HDSKACK),
RSTMGR_HDSKACK_LWSOC2FPGAACK, RSTMGR_HDSKACK_LWSOC2FPGAACK_DASRT,
300);
@@ -937,10 +991,7 @@
mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST),
RSTMGR_BRGMODRST_LWHPS2FPGA);
- /* ToDo: Shall use udelay for product release */
- for (delay = 0; delay < 1000; delay++) {
- /* dummy delay */
- }
+ udelay(1000);
}
#else
if (brg_mask != 0U) {
@@ -1001,7 +1052,7 @@
* Read Reset Manager hdskack[f2s_flush_ack] = 0
*/
VERBOSE("Get F2SDRAM hdskack(f2s_flush_ack) ...\n");
- ret = poll_idle_status_by_counter(SOCFPGA_RSTMGR(HDSKACK),
+ ret = poll_idle_status(SOCFPGA_RSTMGR(HDSKACK),
RSTMGR_HDSKACK_FPGA2SOCACK, RSTMGR_HDSKACK_FPGA2SOCACK_DASRT,
300);
@@ -1014,7 +1065,7 @@
* Read Reset Manager hdskack[fpgahsack] = 0
*/
VERBOSE("Get FPGA hdskack(fpgahsack) ...\n");
- ret = poll_idle_status_by_counter(SOCFPGA_RSTMGR(HDSKACK),
+ ret = poll_idle_status(SOCFPGA_RSTMGR(HDSKACK),
RSTMGR_HDSKACK_FPGAHSACK, RSTMGR_HDSKACK_FPGAHSACK_DASRT,
300);
@@ -1029,10 +1080,7 @@
VERBOSE("Assert F2S ...\n");
mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST), RSTMGR_BRGMODRST_FPGA2SOC);
- /* ToDo: Shall use udelay for product release */
- for (delay = 0; delay < 1000; delay++) {
- /* dummy delay */
- }
+ udelay(1000);
/* Write System Manager f2s bridge control register[f2soc_enable] = 0 */
VERBOSE("Assert F2S f2soc_enable ...\n");
@@ -1068,7 +1116,7 @@
* Read Reset Manager hdskack[f2sdram_flush_ack] = 0
*/
VERBOSE("Get F2SDRAM hdskack(f2sdram_flush_ack) ...\n");
- ret = poll_idle_status_by_counter(SOCFPGA_RSTMGR(HDSKACK),
+ ret = poll_idle_status(SOCFPGA_RSTMGR(HDSKACK),
RSTMGR_HDSKACK_F2SDRAM0ACK, RSTMGR_HDSKACK_F2SDRAM0ACK_DASRT,
300);
@@ -1081,7 +1129,7 @@
* Read Reset Manager hdskack[fpgahsack] = 0
*/
VERBOSE("Get F2SDRAM hdskack(fpgahsack) ...\n");
- ret = poll_idle_status_by_counter(SOCFPGA_RSTMGR(HDSKACK),
+ ret = poll_idle_status(SOCFPGA_RSTMGR(HDSKACK),
RSTMGR_HDSKACK_FPGAHSACK, RSTMGR_HDSKACK_FPGAHSACK_DASRT,
300);
@@ -1097,10 +1145,7 @@
mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST),
RSTMGR_BRGMODRST_F2SSDRAM0);
- /* ToDo: Shall use udelay for product release */
- for (delay = 0; delay < 1000; delay++) {
- /* dummy delay */
- }
+ udelay(1000);
/*
* Assert fpga2sdram_manager_main_SidebandManager_FlagOutClr0
@@ -1139,7 +1184,7 @@
/* Bridge reset */
#if PLATFORM_MODEL == PLAT_SOCFPGA_STRATIX10
- /* Software must never write a 0x1 to FPGA2SOC_M0ASK bit */
+ /* Software must never write a 0x1 to FPGA2SOC_MASK bit */
mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST),
brg_mask & ~RSTMGR_FIELD(BRG, FPGA2SOC));
#else
diff --git a/plat/intel/soc/common/socfpga_psci.c b/plat/intel/soc/common/socfpga_psci.c
index c93e13f..623843e 100644
--- a/plat/intel/soc/common/socfpga_psci.c
+++ b/plat/intel/soc/common/socfpga_psci.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2019-2023, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -183,8 +184,9 @@
{
uint32_t addr_buf[2];
- memcpy(addr_buf, &intel_rsu_update_address,
- sizeof(intel_rsu_update_address));
+ memcpy_s(addr_buf, sizeof(intel_rsu_update_address),
+ &intel_rsu_update_address, sizeof(intel_rsu_update_address));
+
if (intel_rsu_update_address) {
mailbox_rsu_update(addr_buf);
} else {
diff --git a/plat/intel/soc/common/socfpga_sip_svc.c b/plat/intel/soc/common/socfpga_sip_svc.c
index 2f88c86..5dfbc14 100644
--- a/plat/intel/soc/common/socfpga_sip_svc.c
+++ b/plat/intel/soc/common/socfpga_sip_svc.c
@@ -419,6 +419,7 @@
case(SOCFPGA_MEMCTRL(DIAGINTTEST)): /* DIAGINTTEST */
case(SOCFPGA_MEMCTRL(DERRADDRA)): /* DERRADDRA */
+ case(SOCFPGA_ECC_QSPI(INITSTAT)): /* ECC_QSPI_INITSTAT */
case(SOCFPGA_SYSMGR(EMAC_0)): /* EMAC0 */
case(SOCFPGA_SYSMGR(EMAC_1)): /* EMAC1 */
case(SOCFPGA_SYSMGR(EMAC_2)): /* EMAC2 */
diff --git a/plat/intel/soc/common/socfpga_vab.c b/plat/intel/soc/common/socfpga_vab.c
index e16610c..969abb3 100644
--- a/plat/intel/soc/common/socfpga_vab.c
+++ b/plat/intel/soc/common/socfpga_vab.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -8,18 +9,23 @@
#include <assert.h>
#include <errno.h>
+#include "../lib/sha/sha.h"
+
#include <arch_helpers.h>
+#include <common/bl_common.h>
#include <common/debug.h>
+#include <common/desc_image_load.h>
#include <common/tbbr/tbbr_img_def.h>
#include <drivers/delay_timer.h>
#include <lib/mmio.h>
#include <lib/utils.h>
+#include <plat/common/platform.h>
#include <tools_share/firmware_image_package.h>
#include "socfpga_mailbox.h"
#include "socfpga_vab.h"
-static size_t get_img_size(uint8_t *img_buf, size_t img_buf_sz)
+size_t get_img_size(uint8_t *img_buf, size_t img_buf_sz)
{
uint8_t *img_buf_end = img_buf + img_buf_sz;
uint32_t cert_sz = get_unaligned_le32(img_buf_end - sizeof(uint32_t));
@@ -35,9 +41,33 @@
return 0;
}
+int socfpga_vab_init(unsigned int image_id)
+{
+ int ret = 0;
+ size_t image_size;
+ void *image_base_ptr;
+ /*
+ * Get information about the images to load.
+ */
+ bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+
+ assert(bl_mem_params);
+
+ if (bl_mem_params == NULL) {
+ ERROR("SOCFPGA VAB Init failed\n");
+ return -EINITREJECTED;
+ }
+
+ if ((image_id == BL31_IMAGE_ID) || (image_id == BL33_IMAGE_ID)) {
+ image_base_ptr = (void *)bl_mem_params->image_info.image_base;
+ image_size = bl_mem_params->image_info.image_size;
+ ret = socfpga_vab_authentication(&image_base_ptr, &image_size);
+ }
+ return ret;
+}
-int socfpga_vendor_authentication(void **p_image, size_t *p_size)
+int socfpga_vab_authentication(void **p_image, size_t *p_size)
{
int retry_count = 20;
uint8_t hash384[FCS_SHA384_WORD_SIZE];
@@ -46,51 +76,47 @@
uint8_t *cert_hash_ptr, *mbox_relocate_data_addr;
uint32_t resp = 0, resp_len = 1;
int ret = 0;
+ uint8_t u8_buf_static[MBOX_DATA_MAX_LEN];
+
+ mbox_relocate_data_addr = u8_buf_static;
img_addr = (uintptr_t)*p_image;
img_sz = get_img_size((uint8_t *)img_addr, *p_size);
if (!img_sz) {
- NOTICE("VAB certificate not found in image!\n");
- return -ENOVABIMG;
+ ERROR("VAB certificate not found in image!\n");
+ return -ENOVABCERT;
}
if (!IS_BYTE_ALIGNED(img_sz, sizeof(uint32_t))) {
- NOTICE("Image size (%d bytes) not aliged to 4 bytes!\n", img_sz);
+ ERROR("Image size (%d bytes) not aliged to 4 bytes!\n", img_sz);
return -EIMGERR;
}
/* Generate HASH384 from the image */
- /* TODO: This part need to cross check !!!!!! */
- sha384_csum_wd((uint8_t *)img_addr, img_sz, hash384, CHUNKSZ_PER_WD_RESET);
- cert_hash_ptr = (uint8_t *)(img_addr + img_sz +
- VAB_CERT_MAGIC_OFFSET + VAB_CERT_FIT_SHA384_OFFSET);
+ sha384_start((uint8_t *)img_addr, img_sz, hash384, CHUNKSZ_PER_WD_RESET);
+ cert_hash_ptr = (uint8_t *)(img_addr + img_sz + VAB_CERT_MAGIC_OFFSET +
+ VAB_CERT_FIT_SHA384_OFFSET);
/*
* Compare the SHA384 found in certificate against the SHA384
* calculated from image
*/
if (memcmp(hash384, cert_hash_ptr, FCS_SHA384_WORD_SIZE)) {
- NOTICE("SHA384 does not match!\n");
+ ERROR("SHA384 does not match!\n");
return -EKEYREJECTED;
}
-
mbox_data_addr = img_addr + img_sz - sizeof(uint32_t);
/* Size in word (32bits) */
mbox_data_sz = (BYTE_ALIGN(*p_size - img_sz, sizeof(uint32_t))) >> 2;
- NOTICE("mbox_data_addr = %lx mbox_data_sz = %d\n", mbox_data_addr, mbox_data_sz);
+ VERBOSE("mbox_data_addr = %lx mbox_data_sz = %d\n", mbox_data_addr, mbox_data_sz);
- /* TODO: This part need to cross check !!!!!! */
- // mbox_relocate_data_addr = (uint8_t *)malloc(mbox_data_sz * sizeof(uint32_t));
- // if (!mbox_relocate_data_addr) {
- // NOTICE("Cannot allocate memory for VAB certificate relocation!\n");
- // return -ENOMEM;
- // }
+ memcpy_s(mbox_relocate_data_addr, mbox_data_sz * sizeof(uint32_t),
+ (uint8_t *)mbox_data_addr, mbox_data_sz * sizeof(uint32_t));
- memcpy(mbox_relocate_data_addr, (uint8_t *)mbox_data_addr, mbox_data_sz * sizeof(uint32_t));
- *(uint32_t *)mbox_relocate_data_addr = 0;
+ *((unsigned int *)mbox_relocate_data_addr) = CCERT_CMD_TEST_PGM_MASK;
do {
/* Invoke SMC call to ATF to send the VAB certificate to SDM */
@@ -109,7 +135,6 @@
/* Free the relocate certificate memory space */
zeromem((void *)&mbox_relocate_data_addr, sizeof(uint32_t));
-
/* Exclude the size of the VAB certificate from image size */
*p_size = img_sz;
@@ -121,40 +146,32 @@
/* 0x85 = Not allowed under current security setting */
if (ret == MBOX_RESP_ERR(0x85)) {
/* SDM bypass authentication */
- NOTICE("Image Authentication bypassed at address\n");
+ ERROR("Image Authentication bypassed at address\n");
return 0;
}
- NOTICE("VAB certificate authentication failed in SDM\n");
+ ERROR("VAB certificate authentication failed in SDM\n");
/* 0x1FF = The device is busy */
if (ret == MBOX_RESP_ERR(0x1FF)) {
- NOTICE("Operation timed out\n");
+ ERROR("Operation timed out\n");
return -ETIMEOUT;
} else if (ret == MBOX_WRONG_ID) {
- NOTICE("No such process\n");
+ ERROR("No such process\n");
return -EPROCESS;
}
+ return -EAUTH;
} else {
/* If Certificate Process Status has error */
if (resp) {
- NOTICE("VAB certificate execution format error\n");
+ ERROR("VAB certificate execution format error\n");
return -EIMGERR;
}
}
- NOTICE("Image Authentication bypassed at address\n");
+ NOTICE("%s 0x%lx (%d bytes)\n", "Image Authentication passed at address", img_addr, img_sz);
return ret;
-
-}
-
-static uint32_t get_unaligned_le32(const void *p)
-{
- /* TODO: Temp for testing */
- //return le32_to_cpup((__le32 *)p);
- return 0;
}
-void sha384_csum_wd(const unsigned char *input, unsigned int ilen,
- unsigned char *output, unsigned int chunk_sz)
+uint32_t get_unaligned_le32(const void *p)
{
- /* TODO: Update sha384 start, update and finish */
+ return le32_to_cpue((uint32_t *)p);
}
diff --git a/plat/mediatek/common/mtk_smc_handlers.c b/plat/mediatek/common/mtk_smc_handlers.c
index 5a3ad1f..beb06da 100644
--- a/plat/mediatek/common/mtk_smc_handlers.c
+++ b/plat/mediatek/common/mtk_smc_handlers.c
@@ -99,13 +99,13 @@
{
const struct smc_descriptor *p_smc_desc;
- INFO("print smc descriptor pool\n");
+ VERBOSE("print smc descriptor pool\n");
for (p_smc_desc = &pool[0];
(char *)p_smc_desc < (char *)MTK_SMC_POOL_END_UNALIGNED;
p_smc_desc++) {
- INFO("descriptor name:%s\n", p_smc_desc->smc_name);
- INFO("descriptor index:%d\n", *p_smc_desc->smc_descriptor_index);
- INFO("smc id 32:0x%x, smc id 64:0x%x\n",
+ VERBOSE("descriptor name:%s\n", p_smc_desc->smc_name);
+ VERBOSE("descriptor index:%d\n", *p_smc_desc->smc_descriptor_index);
+ VERBOSE("smc id 32:0x%x, smc id 64:0x%x\n",
p_smc_desc->smc_id_aarch32, p_smc_desc->smc_id_aarch64);
}
}
diff --git a/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu.c b/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu.c
index efb70b7..c46cca8 100644
--- a/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu.c
+++ b/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu.c
@@ -120,13 +120,13 @@
{
uint64_t phys_addr = get_decoded_phys_addr(encoded_addr);
struct emi_region_info_t region_info;
- enum MPU_REQ_ORIGIN_ZONE_ID zone_id = get_decoded_zone_id(zone_info);
+ enum region_ids zone_id = get_decoded_zone_id(zone_info);
uint32_t is_set = get_decoded_set_clear_info(zone_info);
INFO("encoded_addr = 0x%lx, zone_size = 0x%lx, zone_info = 0x%lx\n",
encoded_addr, zone_size, zone_info);
- if (zone_id != MPU_REQ_ORIGIN_TEE_ZONE_SVP) {
+ if (zone_id < SVP_DRAM_REGION_ID_START || zone_id > SVP_DRAM_REGION_ID_END) {
ERROR("Invalid param %s, %d\n", __func__, __LINE__);
return MTK_SIP_E_INVALID_PARAM;
}
@@ -135,7 +135,7 @@
/* SVP DRAM */
region_info.start = phys_addr;
region_info.end = phys_addr + zone_size - 1;
- region_info.region = SVP_DRAM_REGION_ID;
+ region_info.region = zone_id;
SET_ACCESS_PERMISSION(region_info.apc, UNLOCK,
FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
@@ -144,7 +144,7 @@
emi_mpu_set_protection(®ion_info);
} else { /* clear region protection */
- emi_mpu_clear_protection(SVP_DRAM_REGION_ID);
+ emi_mpu_clear_protection(zone_id);
}
return 0;
diff --git a/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu_priv.h b/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu_priv.h
index 18acb9c..b64020d 100644
--- a/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu_priv.h
+++ b/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu_priv.h
@@ -56,13 +56,16 @@
#define APUSYS_SEC_BUF_PA (0x55000000)
#define APUSYS_SEC_BUF_SZ (0x100000)
+#define SVP_DRAM_REGION_COUNT (10)
+
enum region_ids {
BL31_EMI_REGION_ID = 0,
BL32_REGION_ID,
SCP_CORE0_REGION_ID,
SCP_CORE1_REGION_ID,
DSP_PROTECT_REGION_ID,
- SVP_DRAM_REGION_ID,
+ SVP_DRAM_REGION_ID_START = 5,
+ SVP_DRAM_REGION_ID_END = SVP_DRAM_REGION_ID_START + SVP_DRAM_REGION_COUNT - 1,
APUSYS_SEC_BUF_EMI_REGION_ID = 21,
diff --git a/plat/nxp/s32/s32g274ardb2/include/platform_def.h b/plat/nxp/s32/s32g274ardb2/include/platform_def.h
index bdfeee2..1a4c495 100644
--- a/plat/nxp/s32/s32g274ardb2/include/platform_def.h
+++ b/plat/nxp/s32/s32g274ardb2/include/platform_def.h
@@ -54,8 +54,7 @@
/* Console settings */
#define UART_BASE UL(0x401C8000)
#define UART_BAUDRATE U(115200)
-/* FIRC clock */
-#define UART_CLOCK_HZ U(48000000)
+#define UART_CLOCK_HZ U(125000000)
#define S32G_FIP_BASE UL(0x34100000)
#define S32G_FIP_SIZE UL(0x100000)
diff --git a/plat/nxp/s32/s32g274ardb2/plat_helpers.S b/plat/nxp/s32/s32g274ardb2/plat_helpers.S
index 193c884..10c0035 100644
--- a/plat/nxp/s32/s32g274ardb2/plat_helpers.S
+++ b/plat/nxp/s32/s32g274ardb2/plat_helpers.S
@@ -38,6 +38,8 @@
/* void plat_crash_console_flush(void); */
func plat_crash_console_flush
+ mov_imm x0, UART_BASE
+ b console_linflex_core_flush
ret
endfunc plat_crash_console_flush
diff --git a/plat/qemu/qemu/include/platform_def.h b/plat/qemu/qemu/include/platform_def.h
index db9d65a..f78be90 100644
--- a/plat/qemu/qemu/include/platform_def.h
+++ b/plat/qemu/qemu/include/platform_def.h
@@ -184,7 +184,7 @@
# define BL32_LIMIT (BL32_SRAM_LIMIT - FW_HANDOFF_SIZE)
#elif BL32_RAM_LOCATION_ID == SEC_DRAM_ID
# define BL32_MEM_BASE SEC_DRAM_BASE
-# define BL32_MEM_SIZE SEC_DRAM_SIZE
+# define BL32_MEM_SIZE (SEC_DRAM_SIZE - RME_GPT_DRAM_SIZE)
# define BL32_BASE BL32_DRAM_BASE
# define BL32_LIMIT (BL32_DRAM_LIMIT - FW_HANDOFF_SIZE)
#else
@@ -379,7 +379,8 @@
#define MAP_GPT_L0_REGION MAP_REGION_FLAT( \
PLAT_QEMU_L0_GPT_BASE, \
- PLAT_QEMU_L0_GPT_SIZE, \
+ PLAT_QEMU_L0_GPT_SIZE + \
+ PLAT_QEMU_GPT_BITLOCK_SIZE, \
MT_MEMORY | MT_RW | EL3_PAS)
#define MAP_GPT_L1_REGION MAP_REGION_FLAT( \
diff --git a/plat/qemu/qemu/platform.mk b/plat/qemu/qemu/platform.mk
index 066554a..cf1b3a8 100644
--- a/plat/qemu/qemu/platform.mk
+++ b/plat/qemu/qemu/platform.mk
@@ -96,10 +96,6 @@
$(info Including ${MEASURED_BOOT_MK})
include ${MEASURED_BOOT_MK}
- ifneq (${MBOOT_EL_HASH_ALG}, sha256)
- $(eval $(call add_define,TF_MBEDTLS_MBOOT_USE_SHA512))
- endif
-
BL2_SOURCES += plat/qemu/qemu/qemu_measured_boot.c \
plat/qemu/qemu/qemu_helpers.c \
${EVENT_LOG_SOURCES}
diff --git a/plat/qti/common/src/aarch64/qti_kryo4_gold.S b/plat/qti/common/src/aarch64/qti_kryo4_gold.S
index 9bcdf54..49b7cf0 100644
--- a/plat/qti/common/src/aarch64/qti_kryo4_gold.S
+++ b/plat/qti/common/src/aarch64/qti_kryo4_gold.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -41,16 +41,6 @@
ret
endfunc qti_kryo4_gold_cluster_pwr_dwn
-#if REPORT_ERRATA
-/*
- * Errata printing function for Kryo4 Gold. Must follow AAPCS.
- */
-func qti_kryo4_gold_errata_report
- /* TODO : Need to add support. Required only for debug bl31 image.*/
- ret
-endfunc qti_kryo4_gold_errata_report
-#endif
-
/* ---------------------------------------------
* This function provides kryo4_gold specific
* register information for crash reporting.
diff --git a/plat/qti/common/src/aarch64/qti_kryo4_silver.S b/plat/qti/common/src/aarch64/qti_kryo4_silver.S
index 36374b7..4a98912 100644
--- a/plat/qti/common/src/aarch64/qti_kryo4_silver.S
+++ b/plat/qti/common/src/aarch64/qti_kryo4_silver.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -35,17 +35,6 @@
ret
endfunc qti_kryo4_silver_cluster_pwr_dwn
-#if REPORT_ERRATA
-/*
- * Errata printing function for Kryo4 Silver. Must follow AAPCS.
- */
-func qti_kryo4_silver_errata_report
- /* TODO : Need to add support. Required only for debug bl31 image.*/
- ret
-endfunc qti_kryo4_silver_errata_report
-#endif
-
-
/* ---------------------------------------------
* This function provides kryo4_silver specific
* register information for crash reporting.
diff --git a/plat/qti/common/src/aarch64/qti_kryo6_gold.S b/plat/qti/common/src/aarch64/qti_kryo6_gold.S
index 577e7ff..5f9463f 100644
--- a/plat/qti/common/src/aarch64/qti_kryo6_gold.S
+++ b/plat/qti/common/src/aarch64/qti_kryo6_gold.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -41,16 +41,6 @@
ret
endfunc qti_kryo6_gold_cluster_pwr_dwn
-#if REPORT_ERRATA
-/*
- * Errata printing function for Kryo4 Gold. Must follow AAPCS.
- */
-func qti_kryo6_gold_errata_report
- /* TODO : Need to add support. Required only for debug bl31 image.*/
- ret
-endfunc qti_kryo6_gold_errata_report
-#endif
-
/* ---------------------------------------------
* This function provides kryo4_gold specific
* register information for crash reporting.
diff --git a/plat/qti/common/src/aarch64/qti_kryo6_silver.S b/plat/qti/common/src/aarch64/qti_kryo6_silver.S
index 6ad0bca..4a54a64 100644
--- a/plat/qti/common/src/aarch64/qti_kryo6_silver.S
+++ b/plat/qti/common/src/aarch64/qti_kryo6_silver.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -35,17 +35,6 @@
ret
endfunc qti_kryo6_silver_cluster_pwr_dwn
-#if REPORT_ERRATA
-/*
- * Errata printing function for Kryo4 Silver. Must follow AAPCS.
- */
-func qti_kryo6_silver_errata_report
- /* TODO : Need to add support. Required only for debug bl31 image.*/
- ret
-endfunc qti_kryo6_silver_errata_report
-#endif
-
-
/* ---------------------------------------------
* This function provides kryo4_silver specific
* register information for crash reporting.
diff --git a/plat/rockchip/common/include/plat_pm_helpers.h b/plat/rockchip/common/include/plat_pm_helpers.h
new file mode 100644
index 0000000..2204a65
--- /dev/null
+++ b/plat/rockchip/common/include/plat_pm_helpers.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_PM_HELPERS_H
+#define PLAT_PM_HELPERS_H
+
+#include <stdint.h>
+
+/**
+ * Use this macro to define a register region.
+ * start: start offset from the base address.
+ * end: end offset from the base address.
+ * stride: stride of registers in region.
+ * base: base address of registers in region.
+ * wmsk: write mask of registers in region.
+ */
+#define REG_REGION(_start, _end, _stride, _base, _wmsk) \
+{ \
+ .start = (_base) + (_start), \
+ .end = (_base) + (_end), \
+ .stride = _stride, \
+ .wmsk = _wmsk \
+}
+
+struct reg_region {
+ /* Start address of region */
+ uint32_t start;
+ /* End address of region */
+ uint32_t end;
+ /* Stride of registers in region */
+ uint32_t stride;
+ /* Write mask of registers in region */
+ uint32_t wmsk;
+ /* Buffer to save/restore registers in region */
+ uint32_t *buf;
+};
+
+void rockchip_alloc_region_mem(struct reg_region *rgns, uint32_t rgn_num);
+void rockchip_reg_rgn_save(struct reg_region *rgns, uint32_t rgn_num);
+void rockchip_reg_rgn_restore(struct reg_region *rgns, uint32_t rgn_num);
+void rockchip_reg_rgn_restore_reverse(struct reg_region *rgns, uint32_t rgn_num);
+void rockchip_regs_dump(uint32_t base,
+ uint32_t start_offset,
+ uint32_t end_offset,
+ uint32_t stride);
+void rockchip_dump_reg_rgns(struct reg_region *rgns, uint32_t rgn_num);
+
+#endif /* PLAT_PM_HELPERS_H */
diff --git a/plat/rockchip/common/include/plat_private.h b/plat/rockchip/common/include/plat_private.h
index 44a0c46..1e13a9e 100644
--- a/plat/rockchip/common/include/plat_private.h
+++ b/plat/rockchip/common/include/plat_private.h
@@ -141,6 +141,7 @@
uint32_t rockchip_get_uart_baudrate(void);
uint32_t rockchip_get_uart_clock(void);
+void rockchip_init_scmi_server(void);
#endif /* __ASSEMBLER__ */
/******************************************************************************
diff --git a/plat/rockchip/common/include/rockchip_sip_svc.h b/plat/rockchip/common/include/rockchip_sip_svc.h
index 340d653..8836f9b 100644
--- a/plat/rockchip/common/include/rockchip_sip_svc.h
+++ b/plat/rockchip/common/include/rockchip_sip_svc.h
@@ -11,6 +11,7 @@
#define SIP_SVC_CALL_COUNT 0x8200ff00
#define SIP_SVC_UID 0x8200ff01
#define SIP_SVC_VERSION 0x8200ff03
+#define RK_SIP_SCMI_AGENT0 0x82000010
/* rockchip SiP Service Calls version numbers */
#define RK_SIP_SVC_VERSION_MAJOR 0x0
diff --git a/plat/rockchip/common/plat_pm_helpers.c b/plat/rockchip/common/plat_pm_helpers.c
new file mode 100644
index 0000000..191b0ca
--- /dev/null
+++ b/plat/rockchip/common/plat_pm_helpers.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#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 <plat_pm_helpers.h>
+
+#define ROCKCHIP_PM_REG_REGION_MEM_LEN (ROCKCHIP_PM_REG_REGION_MEM_SIZE / sizeof(uint32_t))
+
+/* REG region */
+#define RGN_LEN(_rgn) (((_rgn)->end - (_rgn)->start) / (_rgn)->stride + 1)
+
+#ifndef ROCKCHIP_PM_REG_REGION_MEM_SIZE
+#define ROCKCHIP_PM_REG_REGION_MEM_SIZE 0
+#endif
+
+#ifdef ROCKCHIP_REG_RGN_MEM_BASE
+static uint32_t *region_mem = (uint32_t *)ROCKCHIP_REG_RGN_MEM_BASE;
+#else
+static uint32_t region_mem[ROCKCHIP_PM_REG_REGION_MEM_LEN];
+#endif
+
+static int region_mem_idx;
+
+static int alloc_region_mem(uint32_t *buf, int max_len,
+ struct reg_region *rgns, uint32_t rgn_num)
+{
+ int i;
+ int total_len = 0, len = 0;
+ struct reg_region *r = rgns;
+
+ assert(buf && rgns && rgn_num);
+
+ for (i = 0; i < rgn_num; i++, r++) {
+ if (total_len < max_len)
+ r->buf = &buf[total_len];
+
+ len = RGN_LEN(r);
+ total_len += len;
+ }
+
+ if (total_len > max_len) {
+ ERROR("%s The buffer remain length:%d is too small for region:0x%x, at least %d\n",
+ __func__, max_len, rgns[0].start, total_len);
+ panic();
+ }
+
+ return total_len;
+}
+
+/**
+ * Alloc memory to reg_region->buf from region_mem.
+ * @rgns - struct reg_region array.
+ * @rgn_num - struct reg_region array length.
+ */
+void rockchip_alloc_region_mem(struct reg_region *rgns, uint32_t rgn_num)
+{
+ int max_len = 0, len;
+
+ assert(rgns && rgn_num);
+
+ max_len = ROCKCHIP_PM_REG_REGION_MEM_LEN - region_mem_idx;
+
+ len = alloc_region_mem(region_mem + region_mem_idx, max_len,
+ rgns, rgn_num);
+
+ region_mem_idx += len;
+}
+
+/**
+ * Save (reg_region->start ~ reg_region->end) to reg_region->buf.
+ * @rgns - struct reg_region array.
+ * @rgn_num - struct reg_region array length.
+ */
+void rockchip_reg_rgn_save(struct reg_region *rgns, uint32_t rgn_num)
+{
+ struct reg_region *r;
+ uint32_t addr;
+ int i, j;
+
+ assert(rgns && rgn_num);
+
+ for (i = 0; i < rgn_num; i++) {
+ r = &rgns[i];
+ for (j = 0, addr = r->start; addr <= r->end; addr += r->stride, j++)
+ r->buf[j] = mmio_read_32(addr);
+ }
+}
+
+/**
+ * Restore reg_region->buf to (reg_region->start ~ reg_region->end).
+ * @rgns - struct reg_region array.
+ * @rgn_num - struct reg_region array length.
+ */
+void rockchip_reg_rgn_restore(struct reg_region *rgns, uint32_t rgn_num)
+{
+ struct reg_region *r;
+ uint32_t addr;
+ int i, j;
+
+ assert(rgns && rgn_num);
+
+ for (i = 0; i < rgn_num; i++) {
+ r = &rgns[i];
+ for (j = 0, addr = r->start; addr <= r->end; addr += r->stride, j++)
+ mmio_write_32(addr, r->buf[j] | r->wmsk);
+
+ dsb();
+ }
+}
+
+/**
+ * Restore reg_region->buf to (reg_region->start ~ reg_region->end) reversely.
+ * @rgns - struct reg_region array.
+ * @rgn_num - struct reg_region array length.
+ */
+void rockchip_reg_rgn_restore_reverse(struct reg_region *rgns, uint32_t rgn_num)
+{
+ struct reg_region *r;
+ uint32_t addr;
+ int i, j;
+
+ assert(rgns && rgn_num);
+
+ for (i = rgn_num - 1; i >= 0; i--) {
+ r = &rgns[i];
+ j = RGN_LEN(r) - 1;
+ for (addr = r->end; addr >= r->start; addr -= r->stride, j--)
+ mmio_write_32(addr, r->buf[j] | r->wmsk);
+
+ dsb();
+ }
+}
+
+static void rockchip_print_hex(uint32_t val)
+{
+ int i;
+ unsigned char tmp;
+
+ putchar('0');
+ putchar('x');
+ for (i = 0; i < 8; val <<= 4, ++i) {
+ tmp = (val & 0xf0000000) >> 28;
+ if (tmp < 10)
+ putchar('0' + tmp);
+ else
+ putchar('a' + tmp - 10);
+ }
+}
+
+/**
+ * Dump registers (base + start_offset ~ base + end_offset)
+ * @base - the base addr of the register.
+ * @start_offset - the start offset to dump.
+ * @end_offset - the end offset to dump.
+ * @stride - the stride of the registers.
+ */
+void rockchip_regs_dump(uint32_t base,
+ uint32_t start_offset,
+ uint32_t end_offset,
+ uint32_t stride)
+{
+ uint32_t i;
+
+ for (i = start_offset; i <= end_offset; i += stride) {
+ if ((i - start_offset) % 16 == 0) {
+ putchar('\n');
+ rockchip_print_hex(base + i);
+ putchar(':');
+ putchar(' ');
+ putchar(' ');
+ putchar(' ');
+ putchar(' ');
+ }
+ rockchip_print_hex(mmio_read_32(base + i));
+ putchar(' ');
+ putchar(' ');
+ putchar(' ');
+ putchar(' ');
+ }
+ putchar('\n');
+}
+
+/**
+ * Dump reg regions
+ * @rgns - struct reg_region array.
+ * @rgn_num - struct reg_region array length.
+ */
+void rockchip_dump_reg_rgns(struct reg_region *rgns, uint32_t rgn_num)
+{
+ struct reg_region *r;
+ int i;
+
+ assert(rgns && rgn_num);
+
+ for (i = 0; i < rgn_num; i++) {
+ r = &rgns[i];
+ rockchip_regs_dump(0x0, r->start, r->end, r->stride);
+ }
+}
diff --git a/plat/rockchip/common/scmi/scmi.c b/plat/rockchip/common/scmi/scmi.c
new file mode 100644
index 0000000..5c43c51
--- /dev/null
+++ b/plat/rockchip/common/scmi/scmi.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <platform_def.h>
+
+#include <drivers/scmi-msg.h>
+#include <drivers/scmi.h>
+#include <lib/utils.h>
+#include <lib/utils_def.h>
+
+#define MAX_PROTOCOL_IN_LIST 8U
+
+static const char vendor[] = "rockchip";
+static const char sub_vendor[] = "";
+
+#pragma weak rockchip_scmi_protocol_table
+
+const uint8_t rockchip_scmi_protocol_table[1][MAX_PROTOCOL_IN_LIST] = {
+ {
+ SCMI_PROTOCOL_ID_CLOCK,
+ SCMI_PROTOCOL_ID_RESET_DOMAIN,
+ 0
+ }
+};
+
+const char *plat_scmi_vendor_name(void)
+{
+ return vendor;
+}
+
+const char *plat_scmi_sub_vendor_name(void)
+{
+ return sub_vendor;
+}
+
+size_t plat_scmi_protocol_count(void)
+{
+ unsigned int count = 0U;
+ const uint8_t *protocol_list = rockchip_scmi_protocol_table[0];
+
+ while (protocol_list[count])
+ count++;
+
+ return count;
+}
+
+const uint8_t *plat_scmi_protocol_list(unsigned int agent_id)
+{
+ assert(agent_id < ARRAY_SIZE(rockchip_scmi_protocol_table));
+
+ return rockchip_scmi_protocol_table[agent_id];
+}
+
+static struct scmi_msg_channel scmi_channel[] = {
+ [0] = {
+ .shm_addr = SMT_BUFFER0_BASE,
+ .shm_size = SMT_BUF_SLOT_SIZE,
+ },
+
+#ifdef SMT_BUFFER1_BASE
+ [1] = {
+ .shm_addr = SMT_BUFFER1_BASE,
+ .shm_size = SMT_BUF_SLOT_SIZE,
+ },
+#endif
+};
+
+struct scmi_msg_channel *plat_scmi_get_channel(unsigned int agent_id)
+{
+ assert(agent_id < ARRAY_SIZE(scmi_channel));
+
+ return &scmi_channel[agent_id];
+}
+
+#pragma weak rockchip_init_scmi_server
+
+void rockchip_init_scmi_server(void)
+{
+ size_t i;
+
+ for (i = 0U; i < ARRAY_SIZE(scmi_channel); i++)
+ scmi_smt_init_agent_channel(&scmi_channel[i]);
+}
diff --git a/plat/rockchip/common/scmi/scmi_clock.c b/plat/rockchip/common/scmi/scmi_clock.c
new file mode 100644
index 0000000..d6d4b37
--- /dev/null
+++ b/plat/rockchip/common/scmi/scmi_clock.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/scmi-msg.h>
+#include <drivers/scmi.h>
+
+#include "scmi_clock.h"
+
+#pragma weak rockchip_scmi_clock_count
+#pragma weak rockchip_scmi_get_clock
+
+size_t rockchip_scmi_clock_count(unsigned int agent_id __unused)
+{
+ return 0;
+}
+
+rk_scmi_clock_t *rockchip_scmi_get_clock(uint32_t agent_id __unused,
+ uint32_t scmi_id __unused)
+{
+ return NULL;
+}
+
+size_t plat_scmi_clock_count(unsigned int agent_id)
+{
+ return rockchip_scmi_clock_count(agent_id);
+}
+
+const char *plat_scmi_clock_get_name(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ rk_scmi_clock_t *clock;
+
+ clock = rockchip_scmi_get_clock(agent_id, scmi_id);
+ if (clock == NULL)
+ return NULL;
+
+ return clock->name;
+}
+
+int32_t plat_scmi_clock_rates_array(unsigned int agent_id,
+ unsigned int scmi_id,
+ unsigned long *rates,
+ size_t *nb_elts,
+ uint32_t start_idx)
+{
+ uint32_t i;
+ unsigned long *rate_table;
+ rk_scmi_clock_t *clock;
+
+ clock = rockchip_scmi_get_clock(agent_id, scmi_id);
+ if (clock == NULL)
+ return SCMI_NOT_FOUND;
+
+ rate_table = clock->rate_table;
+ if (rate_table == NULL)
+ return SCMI_NOT_SUPPORTED;
+
+ if (rates == 0) {
+ *nb_elts = clock->rate_cnt;
+ goto out;
+ }
+
+ if (start_idx + *nb_elts > clock->rate_cnt)
+ return SCMI_OUT_OF_RANGE;
+
+ for (i = 0; i < *nb_elts; i++)
+ rates[i] = rate_table[start_idx + i];
+
+out:
+ return SCMI_SUCCESS;
+}
+
+int32_t plat_scmi_clock_rates_by_step(unsigned int agent_id __unused,
+ unsigned int scmi_id __unused,
+ unsigned long *steps __unused)
+{
+ return SCMI_NOT_SUPPORTED;
+}
+
+unsigned long plat_scmi_clock_get_rate(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ rk_scmi_clock_t *clock;
+ unsigned long rate = 0;
+
+ clock = rockchip_scmi_get_clock(agent_id, scmi_id);
+ if (clock == NULL)
+ return 0;
+
+ if (clock->clk_ops && clock->clk_ops->get_rate)
+ rate = clock->clk_ops->get_rate(clock);
+
+ /* return cur_rate if no get_rate ops or get_rate return 0 */
+ if (rate == 0)
+ rate = clock->cur_rate;
+
+ return rate;
+}
+
+int32_t plat_scmi_clock_set_rate(unsigned int agent_id,
+ unsigned int scmi_id,
+ unsigned long rate)
+{
+ rk_scmi_clock_t *clock;
+ int32_t status = 0;
+
+ clock = rockchip_scmi_get_clock(agent_id, scmi_id);
+ if (clock == NULL)
+ return SCMI_NOT_FOUND;
+
+ if (clock->clk_ops && clock->clk_ops->set_rate) {
+ status = clock->clk_ops->set_rate(clock, rate);
+ if (status == SCMI_SUCCESS)
+ clock->cur_rate = rate;
+ } else {
+ status = SCMI_NOT_SUPPORTED;
+ }
+
+ return status;
+}
+
+int32_t plat_scmi_clock_get_state(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ rk_scmi_clock_t *clock;
+
+ clock = rockchip_scmi_get_clock(agent_id, scmi_id);
+ if (clock == NULL)
+ return 0;
+
+ return clock->enable;
+}
+
+int32_t plat_scmi_clock_set_state(unsigned int agent_id,
+ unsigned int scmi_id,
+ bool enable_not_disable)
+{
+ rk_scmi_clock_t *clock;
+ int32_t status = 0;
+
+ clock = rockchip_scmi_get_clock(agent_id, scmi_id);
+ if (clock == NULL)
+ return SCMI_NOT_FOUND;
+
+ if (clock->clk_ops && clock->clk_ops->set_status) {
+ status = clock->clk_ops->set_status(clock, enable_not_disable);
+ if (status == SCMI_SUCCESS)
+ clock->enable = enable_not_disable;
+ } else {
+ status = SCMI_NOT_SUPPORTED;
+ }
+
+ return status;
+}
diff --git a/plat/rockchip/common/scmi/scmi_clock.h b/plat/rockchip/common/scmi/scmi_clock.h
new file mode 100644
index 0000000..e640fe1
--- /dev/null
+++ b/plat/rockchip/common/scmi/scmi_clock.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RK_SCMI_CLOCK_H
+#define RK_SCMI_CLOCK_H
+
+#include <stdint.h>
+
+#include <common.h>
+
+struct rk_scmi_clock;
+
+struct rk_clk_ops {
+ unsigned long (*get_rate)(struct rk_scmi_clock *clock);
+ int (*set_rate)(struct rk_scmi_clock *clock, unsigned long rate);
+ int (*set_status)(struct rk_scmi_clock *clock, bool status);
+};
+
+typedef struct rk_scmi_clock {
+ char name[SCMI_CLOCK_NAME_LENGTH_MAX];
+ uint8_t enable;
+ int8_t is_security;
+ uint32_t id;
+ uint32_t rate_cnt;
+ uint64_t cur_rate;
+ uint32_t enable_count;
+ const struct rk_clk_ops *clk_ops;
+ unsigned long *rate_table;
+} rk_scmi_clock_t;
+
+/*
+ * Return number of clock controllers for an agent
+ * @agent_id: SCMI agent ID
+ * Return number of clock controllers
+ */
+size_t rockchip_scmi_clock_count(unsigned int agent_id);
+
+/*
+ * Get rk_scmi_clock_t point
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI clock ID
+ * Return a rk_scmi_clock_t point
+ */
+rk_scmi_clock_t *rockchip_scmi_get_clock(uint32_t agent_id,
+ uint32_t scmi_id);
+
+#endif /* RK_SCMI_CLOCK_H */
diff --git a/plat/rockchip/common/scmi/scmi_rstd.c b/plat/rockchip/common/scmi/scmi_rstd.c
new file mode 100644
index 0000000..35c5e0b
--- /dev/null
+++ b/plat/rockchip/common/scmi/scmi_rstd.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/scmi-msg.h>
+#include <drivers/scmi.h>
+
+#include "scmi_rstd.h"
+
+#pragma weak rockchip_scmi_rstd_count
+#pragma weak rockchip_scmi_get_rstd
+
+size_t rockchip_scmi_rstd_count(unsigned int agent_id __unused)
+{
+ return 0U;
+}
+
+rk_scmi_rstd_t *rockchip_scmi_get_rstd(unsigned int agent_id __unused,
+ unsigned int scmi_id __unused)
+{
+ return NULL;
+}
+
+size_t plat_scmi_rstd_count(unsigned int agent_id)
+{
+ return rockchip_scmi_rstd_count(agent_id);
+}
+
+const char *plat_scmi_rstd_get_name(unsigned int agent_id,
+ unsigned int scmi_id)
+{
+ rk_scmi_rstd_t *rstd;
+
+ rstd = rockchip_scmi_get_rstd(agent_id, scmi_id);
+ if (rstd == NULL)
+ return NULL;
+
+ return rstd->name;
+}
+
+int32_t plat_scmi_rstd_autonomous(unsigned int agent_id,
+ unsigned int scmi_id,
+ unsigned int state)
+{
+ rk_scmi_rstd_t *rstd;
+
+ rstd = rockchip_scmi_get_rstd(agent_id, scmi_id);
+ if (rstd == NULL)
+ return SCMI_NOT_FOUND;
+
+ if ((rstd->rstd_ops && rstd->rstd_ops->reset_auto) != 0)
+ return rstd->rstd_ops->reset_auto(rstd, state);
+ else
+ return SCMI_NOT_SUPPORTED;
+}
+
+int32_t plat_scmi_rstd_set_state(unsigned int agent_id,
+ unsigned int scmi_id,
+ bool assert_not_deassert)
+{
+ rk_scmi_rstd_t *rstd;
+
+ rstd = rockchip_scmi_get_rstd(agent_id, scmi_id);
+ if (rstd == NULL)
+ return SCMI_NOT_FOUND;
+
+ if ((rstd->rstd_ops && rstd->rstd_ops->reset_explicit) != 0)
+ return rstd->rstd_ops->reset_explicit(rstd,
+ assert_not_deassert);
+ else
+ return SCMI_NOT_SUPPORTED;
+}
diff --git a/plat/rockchip/common/scmi/scmi_rstd.h b/plat/rockchip/common/scmi/scmi_rstd.h
new file mode 100644
index 0000000..1af5881
--- /dev/null
+++ b/plat/rockchip/common/scmi/scmi_rstd.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RK_SCMI_RESET_DOMAIN_H
+#define RK_SCMI_RESET_DOMAIN_H
+
+#include <stdint.h>
+
+#include <common.h>
+
+struct rk_scmi_rstd;
+
+struct rk_scmi_rstd_ops {
+ int (*reset_auto)(struct rk_scmi_rstd *rstd, uint32_t state);
+ int (*reset_explicit)(struct rk_scmi_rstd *rstd, bool assert_not_deassert);
+};
+
+typedef struct rk_scmi_rstd {
+ char name[SCMI_RESET_DOMAIN_ATTR_NAME_SZ];
+ uint32_t id;
+ uint32_t attribute;
+ uint32_t latency;
+ struct rk_scmi_rstd_ops *rstd_ops;
+} rk_scmi_rstd_t;
+
+/*
+ * Return number of reset domain for an agent
+ * @agent_id: SCMI agent ID
+ * Return number of reset domain
+ */
+size_t rockchip_scmi_rstd_count(unsigned int agent_id);
+
+/*
+ * Get rk_scmi_rstd_t point
+ * @agent_id: SCMI agent ID
+ * @scmi_id: SCMI rstd ID
+ * Return a rk_scmi_rstd_t point
+ */
+rk_scmi_rstd_t *rockchip_scmi_get_rstd(unsigned int agent_id,
+ unsigned int scmi_id);
+
+#endif /* RK_SCMI_RESET_DOMAIN_H */
diff --git a/plat/rockchip/rk3588/drivers/pmu/plat_pmu_macros.S b/plat/rockchip/rk3588/drivers/pmu/plat_pmu_macros.S
new file mode 100644
index 0000000..c278899
--- /dev/null
+++ b/plat/rockchip/rk3588/drivers/pmu/plat_pmu_macros.S
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#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/rk3588/drivers/pmu/pm_pd_regs.c b/plat/rockchip/rk3588/drivers/pmu/pm_pd_regs.c
new file mode 100644
index 0000000..78e8500
--- /dev/null
+++ b/plat/rockchip/rk3588/drivers/pmu/pm_pd_regs.c
@@ -0,0 +1,555 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#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 <soc.h>
+
+#define WMSK_VAL 0xffff0000
+
+static struct reg_region qos_reg_rgns[] = {
+ [QOS_ISP0_MWO] = REG_REGION(0x08, 0x18, 4, 0xfdf40500, 0),
+ [QOS_ISP0_MRO] = REG_REGION(0x08, 0x18, 4, 0xfdf40400, 0),
+ [QOS_ISP1_MWO] = REG_REGION(0x08, 0x18, 4, 0xfdf41000, 0),
+ [QOS_ISP1_MRO] = REG_REGION(0x08, 0x18, 4, 0xfdf41100, 0),
+ [QOS_VICAP_M0] = REG_REGION(0x08, 0x18, 4, 0xfdf40600, 0),
+ [QOS_VICAP_M1] = REG_REGION(0x08, 0x18, 4, 0xfdf40800, 0),
+ [QOS_FISHEYE0] = REG_REGION(0x08, 0x18, 4, 0xfdf40000, 0),
+ [QOS_FISHEYE1] = REG_REGION(0x08, 0x18, 4, 0xfdf40200, 0),
+ [QOS_VOP_M0] = REG_REGION(0x08, 0x18, 4, 0xfdf82000, 0),
+ [QOS_VOP_M1] = REG_REGION(0x08, 0x18, 4, 0xfdf82200, 0),
+ [QOS_RKVDEC0] = REG_REGION(0x08, 0x18, 4, 0xfdf62000, 0),
+ [QOS_RKVDEC1] = REG_REGION(0x08, 0x18, 4, 0xfdf63000, 0),
+ [QOS_AV1] = REG_REGION(0x08, 0x18, 4, 0xfdf64000, 0),
+ [QOS_RKVENC0_M0RO] = REG_REGION(0x08, 0x18, 4, 0xfdf60000, 0),
+ [QOS_RKVENC0_M1RO] = REG_REGION(0x08, 0x18, 4, 0xfdf60200, 0),
+ [QOS_RKVENC0_M2WO] = REG_REGION(0x08, 0x18, 4, 0xfdf60400, 0),
+ [QOS_RKVENC1_M0RO] = REG_REGION(0x08, 0x18, 4, 0xfdf61000, 0),
+ [QOS_RKVENC1_M1RO] = REG_REGION(0x08, 0x18, 4, 0xfdf61200, 0),
+ [QOS_RKVENC1_M2WO] = REG_REGION(0x08, 0x18, 4, 0xfdf61400, 0),
+ [QOS_DSU_M0] = REG_REGION(0x08, 0x18, 4, 0xfe008000, 0),
+ [QOS_DSU_M1] = REG_REGION(0x08, 0x18, 4, 0xfe008800, 0),
+ [QOS_DSU_MP] = REG_REGION(0x08, 0x18, 4, 0xfdf34200, 0),
+ [QOS_DEBUG] = REG_REGION(0x08, 0x18, 4, 0xfdf34400, 0),
+ [QOS_GPU_M0] = REG_REGION(0x08, 0x18, 4, 0xfdf35000, 0),
+ [QOS_GPU_M1] = REG_REGION(0x08, 0x18, 4, 0xfdf35200, 0),
+ [QOS_GPU_M2] = REG_REGION(0x08, 0x18, 4, 0xfdf35400, 0),
+ [QOS_GPU_M3] = REG_REGION(0x08, 0x18, 4, 0xfdf35600, 0),
+ [QOS_NPU1] = REG_REGION(0x08, 0x18, 4, 0xfdf70000, 0),
+ [QOS_NPU0_MRO] = REG_REGION(0x08, 0x18, 4, 0xfdf72200, 0),
+ [QOS_NPU2] = REG_REGION(0x08, 0x18, 4, 0xfdf71000, 0),
+ [QOS_NPU0_MWR] = REG_REGION(0x08, 0x18, 4, 0xfdf72000, 0),
+ [QOS_MCU_NPU] = REG_REGION(0x08, 0x18, 4, 0xfdf72400, 0),
+ [QOS_JPEG_DEC] = REG_REGION(0x08, 0x18, 4, 0xfdf66200, 0),
+ [QOS_JPEG_ENC0] = REG_REGION(0x08, 0x18, 4, 0xfdf66400, 0),
+ [QOS_JPEG_ENC1] = REG_REGION(0x08, 0x18, 4, 0xfdf66600, 0),
+ [QOS_JPEG_ENC2] = REG_REGION(0x08, 0x18, 4, 0xfdf66800, 0),
+ [QOS_JPEG_ENC3] = REG_REGION(0x08, 0x18, 4, 0xfdf66a00, 0),
+ [QOS_RGA2_MRO] = REG_REGION(0x08, 0x18, 4, 0xfdf66c00, 0),
+ [QOS_RGA2_MWO] = REG_REGION(0x08, 0x18, 4, 0xfdf66e00, 0),
+ [QOS_RGA3_0] = REG_REGION(0x08, 0x18, 4, 0xfdf67000, 0),
+ [QOS_RGA3_1] = REG_REGION(0x08, 0x18, 4, 0xfdf36000, 0),
+ [QOS_VDPU] = REG_REGION(0x08, 0x18, 4, 0xfdf67200, 0),
+ [QOS_IEP] = REG_REGION(0x08, 0x18, 4, 0xfdf66000, 0),
+ [QOS_HDCP0] = REG_REGION(0x08, 0x18, 4, 0xfdf80000, 0),
+ [QOS_HDCP1] = REG_REGION(0x08, 0x18, 4, 0xfdf81000, 0),
+ [QOS_HDMIRX] = REG_REGION(0x08, 0x18, 4, 0xfdf81200, 0),
+ [QOS_GIC600_M0] = REG_REGION(0x08, 0x18, 4, 0xfdf3a000, 0),
+ [QOS_GIC600_M1] = REG_REGION(0x08, 0x18, 4, 0xfdf3a200, 0),
+ [QOS_MMU600PCIE_TCU] = REG_REGION(0x08, 0x18, 4, 0xfdf3a400, 0),
+ [QOS_MMU600PHP_TBU] = REG_REGION(0x08, 0x18, 4, 0xfdf3a600, 0),
+ [QOS_MMU600PHP_TCU] = REG_REGION(0x08, 0x18, 4, 0xfdf3a800, 0),
+ [QOS_USB3_0] = REG_REGION(0x08, 0x18, 4, 0xfdf3e200, 0),
+ [QOS_USB3_1] = REG_REGION(0x08, 0x18, 4, 0xfdf3e000, 0),
+ [QOS_USBHOST_0] = REG_REGION(0x08, 0x18, 4, 0xfdf3e400, 0),
+ [QOS_USBHOST_1] = REG_REGION(0x08, 0x18, 4, 0xfdf3e600, 0),
+ [QOS_EMMC] = REG_REGION(0x08, 0x18, 4, 0xfdf38200, 0),
+ [QOS_FSPI] = REG_REGION(0x08, 0x18, 4, 0xfdf38000, 0),
+ [QOS_SDIO] = REG_REGION(0x08, 0x18, 4, 0xfdf39000, 0),
+ [QOS_DECOM] = REG_REGION(0x08, 0x18, 4, 0xfdf32000, 0),
+ [QOS_DMAC0] = REG_REGION(0x08, 0x18, 4, 0xfdf32200, 0),
+ [QOS_DMAC1] = REG_REGION(0x08, 0x18, 4, 0xfdf32400, 0),
+ [QOS_DMAC2] = REG_REGION(0x08, 0x18, 4, 0xfdf32600, 0),
+ [QOS_GIC600M] = REG_REGION(0x08, 0x18, 4, 0xfdf32800, 0),
+ [QOS_DMA2DDR] = REG_REGION(0x08, 0x18, 4, 0xfdf52000, 0),
+ [QOS_MCU_DDR] = REG_REGION(0x08, 0x18, 4, 0xfdf52200, 0),
+ [QOS_VAD] = REG_REGION(0x08, 0x18, 4, 0xfdf3b200, 0),
+ [QOS_MCU_PMU] = REG_REGION(0x08, 0x18, 4, 0xfdf3b000, 0),
+ [QOS_CRYPTOS] = REG_REGION(0x08, 0x18, 4, 0xfdf3d200, 0),
+ [QOS_CRYPTONS] = REG_REGION(0x08, 0x18, 4, 0xfdf3d000, 0),
+ [QOS_DCF] = REG_REGION(0x08, 0x18, 4, 0xfdf3d400, 0),
+ [QOS_SDMMC] = REG_REGION(0x08, 0x18, 4, 0xfdf3d800, 0),
+};
+
+static struct reg_region pd_crypto_reg_rgns[] = {
+ /* SECURE CRU */
+ REG_REGION(0x300, 0x30c, 4, SCRU_BASE, WMSK_VAL),
+ REG_REGION(0x800, 0x80c, 4, SCRU_BASE, WMSK_VAL),
+ REG_REGION(0xa00, 0xa0c, 4, SCRU_BASE, WMSK_VAL),
+ REG_REGION(0xd00, 0xd20, 8, SCRU_BASE, 0),
+ REG_REGION(0xd04, 0xd24, 8, SCRU_BASE, WMSK_VAL),
+
+ /* S TIMER0 6 channel */
+ REG_REGION(0x00, 0x04, 4, STIMER0_BASE + 0x00, 0),
+ REG_REGION(0x10, 0x10, 4, STIMER0_BASE + 0x00, 0),
+ REG_REGION(0x00, 0x04, 4, STIMER0_BASE + 0x20, 0),
+ REG_REGION(0x10, 0x10, 4, STIMER0_BASE + 0x20, 0),
+ REG_REGION(0x00, 0x04, 4, STIMER0_BASE + 0x40, 0),
+ REG_REGION(0x10, 0x10, 4, STIMER0_BASE + 0x40, 0),
+ REG_REGION(0x00, 0x04, 4, STIMER0_BASE + 0x60, 0),
+ REG_REGION(0x10, 0x10, 4, STIMER0_BASE + 0x60, 0),
+ REG_REGION(0x00, 0x04, 4, STIMER0_BASE + 0x80, 0),
+ REG_REGION(0x10, 0x10, 4, STIMER0_BASE + 0x80, 0),
+ REG_REGION(0x00, 0x04, 4, STIMER0_BASE + 0xa0, 0),
+ REG_REGION(0x10, 0x10, 4, STIMER0_BASE + 0xa0, 0),
+
+ /* S TIMER1 6 channel */
+ REG_REGION(0x00, 0x04, 4, STIMER1_BASE + 0x00, 0),
+ REG_REGION(0x10, 0x10, 4, STIMER1_BASE + 0x00, 0),
+ REG_REGION(0x00, 0x04, 4, STIMER1_BASE + 0x20, 0),
+ REG_REGION(0x10, 0x10, 4, STIMER1_BASE + 0x20, 0),
+ REG_REGION(0x00, 0x04, 4, STIMER1_BASE + 0x40, 0),
+ REG_REGION(0x10, 0x10, 4, STIMER1_BASE + 0x40, 0),
+ REG_REGION(0x00, 0x04, 4, STIMER1_BASE + 0x60, 0),
+ REG_REGION(0x10, 0x10, 4, STIMER1_BASE + 0x60, 0),
+ REG_REGION(0x00, 0x04, 4, STIMER1_BASE + 0x80, 0),
+ REG_REGION(0x10, 0x10, 4, STIMER1_BASE + 0x80, 0),
+ REG_REGION(0x00, 0x04, 4, STIMER1_BASE + 0xa0, 0),
+ REG_REGION(0x10, 0x10, 4, STIMER1_BASE + 0xa0, 0),
+
+ /* wdt_s */
+ REG_REGION(0x04, 0x04, 4, WDT_S_BASE, 0),
+ REG_REGION(0x00, 0x00, 4, WDT_S_BASE, 0),
+};
+
+static struct reg_region pd_dsu_reg_rgns[] = {
+ /* dsucru */
+ REG_REGION(0x040, 0x054, 4, DSUCRU_BASE, WMSK_VAL),
+ REG_REGION(0x300, 0x31c, 4, DSUCRU_BASE, WMSK_VAL),
+ REG_REGION(0x800, 0x80c, 4, DSUCRU_BASE, WMSK_VAL),
+ REG_REGION(0xa00, 0xa0c, 4, DSUCRU_BASE, WMSK_VAL),
+ REG_REGION(0xd00, 0xd20, 8, DSUCRU_BASE, 0),
+ REG_REGION(0xd04, 0xd24, 8, DSUCRU_BASE, WMSK_VAL),
+ REG_REGION(0xf00, 0xf00, 4, DSUCRU_BASE, WMSK_VAL),
+ REG_REGION(0xf10, 0xf1c, 4, DSUCRU_BASE, 0),
+
+ /* bcore0cru */
+ REG_REGION(0x000, 0x014, 4, BIGCORE0CRU_BASE, WMSK_VAL),
+ REG_REGION(0x300, 0x304, 4, BIGCORE0CRU_BASE, WMSK_VAL),
+ REG_REGION(0x800, 0x804, 4, BIGCORE0CRU_BASE, WMSK_VAL),
+ REG_REGION(0xa00, 0xa04, 4, BIGCORE0CRU_BASE, WMSK_VAL),
+ REG_REGION(0xcc0, 0xcc4, 4, BIGCORE0CRU_BASE, 0),
+ REG_REGION(0xd00, 0xd00, 4, BIGCORE0CRU_BASE, 0),
+ REG_REGION(0xd04, 0xd04, 4, BIGCORE0CRU_BASE, WMSK_VAL),
+
+ /* bcore1cru */
+ REG_REGION(0x020, 0x034, 4, BIGCORE1CRU_BASE, WMSK_VAL),
+ REG_REGION(0x300, 0x304, 4, BIGCORE1CRU_BASE, WMSK_VAL),
+ REG_REGION(0x800, 0x804, 4, BIGCORE1CRU_BASE, WMSK_VAL),
+ REG_REGION(0xa00, 0xa04, 4, BIGCORE1CRU_BASE, WMSK_VAL),
+ REG_REGION(0xcc0, 0xcc4, 4, BIGCORE1CRU_BASE, 0),
+ REG_REGION(0xd00, 0xd00, 4, BIGCORE1CRU_BASE, 0),
+ REG_REGION(0xd04, 0xd04, 4, BIGCORE1CRU_BASE, WMSK_VAL),
+
+ /* dsugrf */
+ REG_REGION(0x00, 0x18, 4, DSUGRF_BASE, WMSK_VAL),
+ REG_REGION(0x20, 0x20, 4, DSUGRF_BASE, WMSK_VAL),
+ REG_REGION(0x28, 0x30, 4, DSUGRF_BASE, WMSK_VAL),
+ REG_REGION(0x38, 0x38, 4, DSUGRF_BASE, WMSK_VAL),
+
+ /* lcore_grf */
+ REG_REGION(0x20, 0x20, 4, LITCOREGRF_BASE, WMSK_VAL),
+ REG_REGION(0x28, 0x30, 4, LITCOREGRF_BASE, WMSK_VAL),
+
+ /* bcore0_grf */
+ REG_REGION(0x20, 0x20, 4, BIGCORE0GRF_BASE, WMSK_VAL),
+ REG_REGION(0x28, 0x30, 4, BIGCORE0GRF_BASE, WMSK_VAL),
+
+ /* bcore1_grf */
+ REG_REGION(0x20, 0x20, 4, BIGCORE1GRF_BASE, WMSK_VAL),
+ REG_REGION(0x28, 0x28, 4, BIGCORE1GRF_BASE, WMSK_VAL),
+};
+
+static struct reg_region pd_php_reg_rgns[] = {
+ /* php_grf */
+ REG_REGION(0x000, 0x008, 4, PHPGRF_BASE, WMSK_VAL),
+ REG_REGION(0x014, 0x024, 4, PHPGRF_BASE, WMSK_VAL),
+ REG_REGION(0x028, 0x02c, 4, PHPGRF_BASE, 0),
+ REG_REGION(0x030, 0x03c, 4, PHPGRF_BASE, WMSK_VAL),
+ REG_REGION(0x05c, 0x060, 4, PHPGRF_BASE, WMSK_VAL),
+ REG_REGION(0x064, 0x068, 4, PHPGRF_BASE, 0),
+ REG_REGION(0x070, 0x070, 4, PHPGRF_BASE, WMSK_VAL),
+ REG_REGION(0x074, 0x0d0, 4, PHPGRF_BASE, 0),
+ REG_REGION(0x0d4, 0x0d4, 4, PHPGRF_BASE, WMSK_VAL),
+ REG_REGION(0x0e0, 0x0e0, 4, PHPGRF_BASE, 0),
+ REG_REGION(0x0e4, 0x0ec, 4, PHPGRF_BASE, WMSK_VAL),
+ REG_REGION(0x100, 0x104, 4, PHPGRF_BASE, WMSK_VAL),
+ REG_REGION(0x10c, 0x130, 4, PHPGRF_BASE, 0),
+ REG_REGION(0x138, 0x138, 4, PHPGRF_BASE, WMSK_VAL),
+ REG_REGION(0x144, 0x168, 4, PHPGRF_BASE, 0),
+ REG_REGION(0x16c, 0x174, 4, PHPGRF_BASE, WMSK_VAL),
+
+ /* php_cru */
+ REG_REGION(0x200, 0x218, 4, PHP_CRU_BASE, WMSK_VAL),
+ REG_REGION(0x800, 0x800, 4, PHP_CRU_BASE, WMSK_VAL),
+ REG_REGION(0xa00, 0xa00, 4, PHP_CRU_BASE, WMSK_VAL),
+
+ /* pcie3phy_grf_cmn_con0 */
+ REG_REGION(0x00, 0x00, 4, PCIE3PHYGRF_BASE, WMSK_VAL),
+};
+
+void qos_save(void)
+{
+ uint32_t pmu_pd_st0 = mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST(0));
+
+ if ((pmu_pd_st0 & BIT(PD_GPU)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_GPU_M0], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_GPU_M1], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_GPU_M2], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_GPU_M3], 1);
+ }
+
+ if ((pmu_pd_st0 & BIT(PD_NPU1)) == 0)
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_NPU1], 1);
+ if ((pmu_pd_st0 & BIT(PD_NPU2)) == 0)
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_NPU2], 1);
+ if ((pmu_pd_st0 & BIT(PD_NPUTOP)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_NPU0_MRO], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_NPU0_MWR], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_MCU_NPU], 1);
+ }
+
+ if ((pmu_pd_st0 & BIT(PD_RKVDEC1)) == 0)
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RKVDEC1], 1);
+ if ((pmu_pd_st0 & BIT(PD_RKVDEC0)) == 0)
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RKVDEC0], 1);
+
+ if ((pmu_pd_st0 & BIT(PD_VENC1)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RKVENC1_M0RO], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RKVENC1_M1RO], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RKVENC1_M2WO], 1);
+ }
+ if ((pmu_pd_st0 & BIT(PD_VENC0)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RKVENC0_M0RO], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RKVENC0_M1RO], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RKVENC0_M2WO], 1);
+ }
+
+ if ((pmu_pd_st0 & BIT(PD_RGA30)) == 0)
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RGA3_0], 1);
+ if ((pmu_pd_st0 & BIT(PD_AV1)) == 0)
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_AV1], 1);
+ if ((pmu_pd_st0 & BIT(PD_VDPU)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_JPEG_DEC], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_JPEG_ENC0], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_JPEG_ENC1], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_JPEG_ENC2], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_JPEG_ENC3], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RGA2_MRO], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RGA2_MWO], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_VDPU], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_IEP], 1);
+ }
+
+ if ((pmu_pd_st0 & BIT(PD_VO0)) == 0)
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_HDCP0], 1);
+ if ((pmu_pd_st0 & BIT(PD_VO1)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_HDCP1], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_HDMIRX], 1);
+ }
+ if ((pmu_pd_st0 & BIT(PD_VOP)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_VOP_M0], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_VOP_M1], 1);
+ }
+
+ if ((pmu_pd_st0 & BIT(PD_FEC)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_FISHEYE0], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_FISHEYE1], 1);
+ }
+ if ((pmu_pd_st0 & BIT(PD_ISP1)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_ISP1_MWO], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_ISP1_MRO], 1);
+ }
+ if ((pmu_pd_st0 & BIT(PD_VI)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_ISP0_MWO], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_ISP0_MRO], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_VICAP_M0], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_VICAP_M1], 1);
+ }
+
+ if ((pmu_pd_st0 & BIT(PD_RGA31)) == 0)
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_RGA3_1], 1);
+
+ if ((pmu_pd_st0 & BIT(PD_USB)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_USB3_0], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_USB3_1], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_USBHOST_0], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_USBHOST_1], 1);
+ }
+
+ if ((pmu_pd_st0 & BIT(PD_PHP)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_GIC600_M0], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_GIC600_M1], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_MMU600PCIE_TCU], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_MMU600PHP_TBU], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_MMU600PHP_TCU], 1);
+ }
+
+ if ((pmu_pd_st0 & BIT(PD_SDIO)) == 0)
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_SDIO], 1);
+ if ((pmu_pd_st0 & BIT(PD_NVM0)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_FSPI], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_EMMC], 1);
+ }
+
+ if ((pmu_pd_st0 & BIT(PD_SDMMC)) == 0)
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_SDMMC], 1);
+
+ if ((pmu_pd_st0 & BIT(PD_CRYPTO)) == 0) {
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_CRYPTONS], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_CRYPTOS], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_DCF], 1);
+ }
+
+ /* PD_DSU */
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_DSU_M0], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_DSU_M1], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_DSU_MP], 1);
+ rockchip_reg_rgn_save(&qos_reg_rgns[QOS_DEBUG], 1);
+}
+
+void qos_restore(void)
+{
+ uint32_t pmu_pd_st0 = mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST(0));
+
+ if ((pmu_pd_st0 & BIT(PD_GPU)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_GPU_M0], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_GPU_M1], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_GPU_M2], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_GPU_M3], 1);
+ }
+
+ if ((pmu_pd_st0 & BIT(PD_NPU1)) == 0)
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_NPU1], 1);
+ if ((pmu_pd_st0 & BIT(PD_NPU2)) == 0)
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_NPU2], 1);
+ if ((pmu_pd_st0 & BIT(PD_NPUTOP)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_NPU0_MRO], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_NPU0_MWR], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_MCU_NPU], 1);
+ }
+
+ if ((pmu_pd_st0 & BIT(PD_RKVDEC1)) == 0)
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RKVDEC1], 1);
+ if ((pmu_pd_st0 & BIT(PD_RKVDEC0)) == 0)
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RKVDEC0], 1);
+
+ if ((pmu_pd_st0 & BIT(PD_VENC1)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RKVENC1_M0RO], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RKVENC1_M1RO], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RKVENC1_M2WO], 1);
+ }
+ if ((pmu_pd_st0 & BIT(PD_VENC0)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RKVENC0_M0RO], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RKVENC0_M1RO], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RKVENC0_M2WO], 1);
+ }
+
+ if ((pmu_pd_st0 & BIT(PD_RGA30)) == 0)
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RGA3_0], 1);
+ if ((pmu_pd_st0 & BIT(PD_AV1)) == 0)
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_AV1], 1);
+ if ((pmu_pd_st0 & BIT(PD_VDPU)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_JPEG_DEC], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_JPEG_ENC0], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_JPEG_ENC1], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_JPEG_ENC2], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_JPEG_ENC3], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RGA2_MRO], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RGA2_MWO], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_VDPU], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_IEP], 1);
+ }
+
+ if ((pmu_pd_st0 & BIT(PD_VO0)) == 0)
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_HDCP0], 1);
+ if ((pmu_pd_st0 & BIT(PD_VO1)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_HDCP1], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_HDMIRX], 1);
+ }
+ if ((pmu_pd_st0 & BIT(PD_VOP)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_VOP_M0], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_VOP_M1], 1);
+ }
+
+ if ((pmu_pd_st0 & BIT(PD_FEC)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_FISHEYE0], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_FISHEYE1], 1);
+ }
+ if ((pmu_pd_st0 & BIT(PD_ISP1)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_ISP1_MWO], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_ISP1_MRO], 1);
+ }
+ if ((pmu_pd_st0 & BIT(PD_VI)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_ISP0_MWO], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_ISP0_MRO], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_VICAP_M0], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_VICAP_M1], 1);
+ }
+
+ if ((pmu_pd_st0 & BIT(PD_RGA31)) == 0)
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_RGA3_1], 1);
+
+ if ((pmu_pd_st0 & BIT(PD_USB)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_USB3_0], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_USB3_1], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_USBHOST_0], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_USBHOST_1], 1);
+ }
+
+ if ((pmu_pd_st0 & BIT(PD_PHP)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_GIC600_M0], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_GIC600_M1], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_MMU600PCIE_TCU], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_MMU600PHP_TBU], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_MMU600PHP_TCU], 1);
+ }
+
+ if ((pmu_pd_st0 & BIT(PD_SDIO)) == 0)
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_SDIO], 1);
+ if ((pmu_pd_st0 & BIT(PD_NVM0)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_FSPI], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_EMMC], 1);
+ }
+
+ if ((pmu_pd_st0 & BIT(PD_SDMMC)) == 0)
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_SDMMC], 1);
+
+ if ((pmu_pd_st0 & BIT(PD_CRYPTO)) == 0) {
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_CRYPTONS], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_CRYPTOS], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_DCF], 1);
+ }
+
+ /* PD_DSU */
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_DSU_M0], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_DSU_M1], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_DSU_MP], 1);
+ rockchip_reg_rgn_restore(&qos_reg_rgns[QOS_DEBUG], 1);
+}
+
+void pd_crypto_save(void)
+{
+ rockchip_reg_rgn_save(pd_crypto_reg_rgns, ARRAY_SIZE(pd_crypto_reg_rgns));
+}
+
+void pd_crypto_restore(void)
+{
+ rockchip_reg_rgn_restore(pd_crypto_reg_rgns, ARRAY_SIZE(pd_crypto_reg_rgns));
+}
+
+static uint32_t b0_cru_mode;
+static uint32_t b1_cru_mode;
+static uint32_t dsu_cru_mode;
+static uint32_t bcore0_cru_sel_con2, bcore1_cru_sel_con2;
+
+void pd_dsu_core_save(void)
+{
+ b0_cru_mode = mmio_read_32(BIGCORE0CRU_BASE + 0x280);
+ b1_cru_mode = mmio_read_32(BIGCORE1CRU_BASE + 0x280);
+ dsu_cru_mode = mmio_read_32(DSUCRU_BASE + 0x280);
+ bcore0_cru_sel_con2 = mmio_read_32(BIGCORE0CRU_BASE + CRU_CLKSEL_CON(2));
+ bcore1_cru_sel_con2 = mmio_read_32(BIGCORE1CRU_BASE + CRU_CLKSEL_CON(2));
+
+ rockchip_reg_rgn_save(pd_dsu_reg_rgns, ARRAY_SIZE(pd_dsu_reg_rgns));
+}
+
+void pd_dsu_core_restore(void)
+{
+ /* switch bcore0/1 pclk root to 24M */
+ mmio_write_32(BIGCORE0CRU_BASE + CRU_CLKSEL_CON(2),
+ BITS_WITH_WMASK(2, 0x3, 0));
+ mmio_write_32(BIGCORE1CRU_BASE + CRU_CLKSEL_CON(2),
+ BITS_WITH_WMASK(2, 0x3, 0));
+
+ /* slow mode */
+ mmio_write_32(BIGCORE0CRU_BASE + 0x280, 0x00030000);
+ mmio_write_32(BIGCORE1CRU_BASE + 0x280, 0x00030000);
+ mmio_write_32(DSUCRU_BASE + 0x280, 0x00030000);
+
+ rockchip_reg_rgn_restore(pd_dsu_reg_rgns, ARRAY_SIZE(pd_dsu_reg_rgns));
+
+ /* trigger dsu/lcore/bcore mem_cfg */
+ mmio_write_32(DSUGRF_BASE + 0x18, BITS_WITH_WMASK(1, 0x1, 14));
+ mmio_write_32(LITCOREGRF_BASE + 0x30, BITS_WITH_WMASK(1, 0x1, 5));
+ mmio_write_32(BIGCORE0GRF_BASE + 0x30, BITS_WITH_WMASK(1, 0x1, 5));
+ mmio_write_32(BIGCORE1GRF_BASE + 0x30, BITS_WITH_WMASK(1, 0x1, 5));
+ udelay(1);
+ mmio_write_32(DSUGRF_BASE + 0x18, BITS_WITH_WMASK(0, 0x1, 14));
+ mmio_write_32(LITCOREGRF_BASE + 0x30, BITS_WITH_WMASK(0, 0x1, 5));
+ mmio_write_32(BIGCORE0GRF_BASE + 0x30, BITS_WITH_WMASK(0, 0x1, 5));
+ mmio_write_32(BIGCORE1GRF_BASE + 0x30, BITS_WITH_WMASK(0, 0x1, 5));
+
+ /* wait lock */
+ pm_pll_wait_lock(BIGCORE0CRU_BASE + 0x00);
+ pm_pll_wait_lock(BIGCORE1CRU_BASE + 0x20);
+ pm_pll_wait_lock(DSUCRU_BASE + 0x40);
+
+ /* restore mode */
+ mmio_write_32(BIGCORE0CRU_BASE + 0x280, WITH_16BITS_WMSK(b0_cru_mode));
+ mmio_write_32(BIGCORE1CRU_BASE + 0x280, WITH_16BITS_WMSK(b1_cru_mode));
+ mmio_write_32(DSUCRU_BASE + 0x280, WITH_16BITS_WMSK(dsu_cru_mode));
+
+ mmio_write_32(BIGCORE0CRU_BASE + CRU_CLKSEL_CON(2),
+ WITH_16BITS_WMSK(bcore0_cru_sel_con2));
+ mmio_write_32(BIGCORE1CRU_BASE + CRU_CLKSEL_CON(2),
+ WITH_16BITS_WMSK(bcore1_cru_sel_con2));
+}
+
+static uint32_t php_ppll_con0;
+
+void pd_php_save(void)
+{
+ php_ppll_con0 = mmio_read_32(PHP_CRU_BASE + 0x200);
+
+ /* php_ppll bypass */
+ mmio_write_32(PHP_CRU_BASE + 0x200, BITS_WITH_WMASK(1u, 1u, 15));
+ dsb();
+ isb();
+ 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));
+
+ pm_pll_wait_lock(PHP_CRU_BASE + 0x200);
+
+ /* restore php_ppll bypass */
+ mmio_write_32(PHP_CRU_BASE + 0x200, WITH_16BITS_WMSK(php_ppll_con0));
+}
+
+void pm_reg_rgns_init(void)
+{
+ rockchip_alloc_region_mem(qos_reg_rgns, ARRAY_SIZE(qos_reg_rgns));
+ rockchip_alloc_region_mem(pd_crypto_reg_rgns, ARRAY_SIZE(pd_crypto_reg_rgns));
+ rockchip_alloc_region_mem(pd_dsu_reg_rgns, ARRAY_SIZE(pd_dsu_reg_rgns));
+ rockchip_alloc_region_mem(pd_php_reg_rgns, ARRAY_SIZE(pd_php_reg_rgns));
+}
diff --git a/plat/rockchip/rk3588/drivers/pmu/pm_pd_regs.h b/plat/rockchip/rk3588/drivers/pmu/pm_pd_regs.h
new file mode 100644
index 0000000..8baf69a
--- /dev/null
+++ b/plat/rockchip/rk3588/drivers/pmu/pm_pd_regs.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PM_PD_REGS_H
+#define PM_PD_REGS_H
+
+#include <stdint.h>
+
+void qos_save(void);
+void qos_restore(void);
+void pd_crypto_save(void);
+void pd_crypto_restore(void);
+void pd_dsu_core_save(void);
+void pd_dsu_core_restore(void);
+void pd_php_save(void);
+void pd_php_restore(void);
+
+void pm_reg_rgns_init(void);
+
+#endif
diff --git a/plat/rockchip/rk3588/drivers/pmu/pmu.c b/plat/rockchip/rk3588/drivers/pmu/pmu.c
new file mode 100644
index 0000000..83d6cad
--- /dev/null
+++ b/plat/rockchip/rk3588/drivers/pmu/pmu.c
@@ -0,0 +1,1439 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <arch_helpers.h>
+#include <bl31/bl31.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv3.h>
+#include <drivers/console.h>
+#include <drivers/delay_timer.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <lib/mmio.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <pmu.h>
+
+#include <cpus_on_fixed_addr.h>
+#include <plat_pm_helpers.h>
+#include <plat_private.h>
+#include <pm_pd_regs.h>
+#include <rk3588_clk.h>
+#include <rockchip_sip_svc.h>
+#include <secure.h>
+#include <soc.h>
+
+#define PSRAM_SP_TOP ((PMUSRAM_BASE + PMUSRAM_RSIZE) & ~0xf)
+#define NONBOOT_CPUS_OFF_LOOP (500000)
+
+#define DSUGRF_REG_CNT (0x78 / 4 + 1)
+#define BCORE_GRF_REG_CNT (0x30 / 4 + 1)
+#define LCORE_GRF_REG_CNT (0x30 / 4 + 1)
+
+#define CENTER_GRF_REG_CNT (0x20 / 4 + 1)
+
+static struct psram_data_t *psram_sleep_cfg =
+ (struct psram_data_t *)&sys_sleep_flag_sram;
+
+static int8_t pd_repair_map[] = {
+ [PD_GPU] = PD_RPR_GPU,
+ [PD_NPU] = -1,
+ [PD_VCODEC] = -1,
+ [PD_NPUTOP] = PD_RPR_NPUTOP,
+ [PD_NPU1] = PD_RPR_NPU1,
+ [PD_NPU2] = PD_RPR_NPU2,
+ [PD_VENC0] = PD_RPR_VENC0,
+ [PD_VENC1] = PD_RPR_VENC1,
+ [PD_RKVDEC0] = PD_RPR_RKVDEC0,
+ [PD_RKVDEC1] = PD_RPR_RKVDEC1,
+ [PD_VDPU] = PD_RPR_VDPU,
+ [PD_RGA30] = PD_RPR_RGA30,
+ [PD_AV1] = PD_RPR_AV1,
+ [PD_VI] = PD_RPR_VI,
+ [PD_FEC] = PD_RPR_FEC,
+ [PD_ISP1] = PD_RPR_ISP1,
+ [PD_RGA31] = PD_RPR_RGA31,
+ [PD_VOP] = PD_RPR_VOP,
+ [PD_VO0] = PD_RPR_VO0,
+ [PD_VO1] = PD_RPR_VO1,
+ [PD_AUDIO] = PD_RPR_AUDIO,
+ [PD_PHP] = PD_RPR_PHP,
+ [PD_GMAC] = PD_RPR_GMAC,
+ [PD_PCIE] = PD_RPR_PCIE,
+ [PD_NVM] = -1,
+ [PD_NVM0] = PD_RPR_NVM0,
+ [PD_SDIO] = PD_RPR_SDIO,
+ [PD_USB] = PD_RPR_USB,
+ [PD_SECURE] = -1,
+ [PD_SDMMC] = PD_RPR_SDMMC,
+ [PD_CRYPTO] = PD_RPR_CRYPTO,
+ [PD_CENTER] = PD_RPR_CENTER,
+ [PD_DDR01] = PD_RPR_DDR01,
+ [PD_DDR23] = PD_RPR_DDR23,
+};
+
+struct rk3588_sleep_ddr_data {
+ uint32_t gpio0a_iomux_l, gpio0a_iomux_h, gpio0b_iomux_l;
+ uint32_t pmu_pd_st0, bus_idle_st0, qch_pwr_st;
+ uint32_t pmu2_vol_gate_con[3], pmu2_submem_gate_sft_con0;
+ uint32_t pmu2_bisr_con0;
+ uint32_t cpll_con0;
+ uint32_t cru_mode_con, busscru_mode_con;
+ uint32_t bussgrf_soc_con7;
+ uint32_t pmu0grf_soc_con0, pmu0grf_soc_con1, pmu0grf_soc_con3;
+ uint32_t pmu1grf_soc_con2, pmu1grf_soc_con7, pmu1grf_soc_con8, pmu1grf_soc_con9;
+ uint32_t pmu0sgrf_soc_con1;
+ uint32_t pmu1sgrf_soc_con14;
+ uint32_t ddrgrf_chn_con0[4], ddrgrf_chn_con1[4],
+ ddrgrf_chn_con2[4], pmu1_ddr_pwr_sft_con[4];
+ uint32_t pmu1cru_clksel_con1;
+};
+
+static struct rk3588_sleep_ddr_data ddr_data;
+
+struct rk3588_sleep_pmusram_data {
+ uint32_t dsusgrf_soc_con[DSUSGRF_SOC_CON_CNT],
+ dsusgrf_ddr_hash_con[DSUSGRF_DDR_HASH_CON_CNT];
+ uint32_t dsu_ddr_fw_rgn_reg[FIREWALL_DSU_RGN_CNT],
+ dsu_ddr_fw_mst_reg[FIREWALL_DSU_MST_CNT],
+ dsu_ddr_fw_con_reg[FIREWALL_DSU_CON_CNT];
+ uint32_t busioc_gpio0b_iomux_h;
+};
+
+static __pmusramdata struct rk3588_sleep_pmusram_data pmusram_data;
+
+static __pmusramfunc void dsu_restore_early(void)
+{
+ int i;
+
+ /* dsusgrf */
+ for (i = 0; i < DSUSGRF_SOC_CON_CNT; i++)
+ mmio_write_32(DSUSGRF_BASE + DSUSGRF_SOC_CON(i),
+ WITH_16BITS_WMSK(pmusram_data.dsusgrf_soc_con[i]));
+
+ for (i = 0; i < DSUSGRF_DDR_HASH_CON_CNT; i++)
+ mmio_write_32(DSUSGRF_BASE + DSUSGRF_DDR_HASH_CON(i),
+ pmusram_data.dsusgrf_ddr_hash_con[i]);
+
+ /* dsu ddr firewall */
+ for (i = 0; i < FIREWALL_DSU_RGN_CNT; i++)
+ mmio_write_32(FIREWALL_DSU_BASE + FIREWALL_DSU_RGN(i),
+ pmusram_data.dsu_ddr_fw_rgn_reg[i]);
+
+ for (i = 0; i < FIREWALL_DSU_MST_CNT; i++)
+ mmio_write_32(FIREWALL_DSU_BASE + FIREWALL_DSU_MST(i),
+ pmusram_data.dsu_ddr_fw_mst_reg[i]);
+
+ for (i = 0; i < FIREWALL_DSU_CON_CNT; i++)
+ mmio_write_32(FIREWALL_DSU_BASE + FIREWALL_DSU_CON(i),
+ pmusram_data.dsu_ddr_fw_con_reg[i]);
+}
+
+static __pmusramfunc void ddr_resume(void)
+{
+ dsu_restore_early();
+}
+
+static void dsu_core_save(void)
+{
+ int i;
+
+ /* dsusgrf */
+ for (i = 0; i < DSUSGRF_SOC_CON_CNT; i++)
+ pmusram_data.dsusgrf_soc_con[i] =
+ mmio_read_32(DSUSGRF_BASE + DSUSGRF_SOC_CON(i));
+
+ for (i = 0; i < DSUSGRF_DDR_HASH_CON_CNT; i++)
+ pmusram_data.dsusgrf_ddr_hash_con[i] =
+ mmio_read_32(DSUSGRF_BASE + DSUSGRF_DDR_HASH_CON(i));
+
+ /* dsu ddr firewall */
+ for (i = 0; i < FIREWALL_DSU_RGN_CNT; i++)
+ pmusram_data.dsu_ddr_fw_rgn_reg[i] =
+ mmio_read_32(FIREWALL_DSU_BASE + FIREWALL_DSU_RGN(i));
+
+ for (i = 0; i < FIREWALL_DSU_MST_CNT; i++)
+ pmusram_data.dsu_ddr_fw_mst_reg[i] =
+ mmio_read_32(FIREWALL_DSU_BASE + FIREWALL_DSU_MST(i));
+
+ for (i = 0; i < FIREWALL_DSU_CON_CNT; i++)
+ pmusram_data.dsu_ddr_fw_con_reg[i] =
+ mmio_read_32(FIREWALL_DSU_BASE + FIREWALL_DSU_CON(i));
+
+ pvtplls_suspend();
+ pd_dsu_core_save();
+}
+
+static void dsu_core_restore(void)
+{
+ pd_dsu_core_restore();
+ pvtplls_resume();
+}
+
+static uint32_t clk_save[CRU_CLKGATE_CON_CNT + PHPCRU_CLKGATE_CON_CNT +
+ SECURECRU_CLKGATE_CON_CNT + PMU1CRU_CLKGATE_CON_CNT];
+
+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));
+
+ clk_save[j] = mmio_read_32(PHP_CRU_BASE + PHPCRU_CLKGATE_CON);
+
+ for (i = 0; i < SECURECRU_CLKGATE_CON_CNT; i++, j++)
+ clk_save[j] = mmio_read_32(SCRU_BASE + SECURECRU_CLKGATE_CON(i));
+
+ for (i = 0; i < PMU1CRU_CLKGATE_CON_CNT; i++, j++)
+ clk_save[j] = mmio_read_32(PMU1CRU_BASE + CRU_CLKGATE_CON(i));
+}
+
+void clk_gate_con_disable(void)
+{
+ int i;
+
+ for (i = 0; i < CRU_CLKGATE_CON_CNT; i++)
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(i), 0xffff0000);
+
+ mmio_write_32(PHP_CRU_BASE + PHPCRU_CLKGATE_CON, 0xffff0000);
+
+ for (i = 0; i < SECURECRU_CLKGATE_CON_CNT; i++)
+ mmio_write_32(SCRU_BASE + SECURECRU_CLKGATE_CON(i), 0xffff0000);
+
+ for (i = 0; i < PMU1CRU_CLKGATE_CON_CNT; i++)
+ mmio_write_32(PMU1CRU_BASE + CRU_CLKGATE_CON(i), 0xffff0000);
+}
+
+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]));
+
+ mmio_write_32(PHP_CRU_BASE + PHPCRU_CLKGATE_CON,
+ WITH_16BITS_WMSK(clk_save[j]));
+
+ for (i = 0; i < SECURECRU_CLKGATE_CON_CNT; i++, j++)
+ mmio_write_32(SCRU_BASE + SECURECRU_CLKGATE_CON(i),
+ WITH_16BITS_WMSK(clk_save[j]));
+
+ for (i = 0; i < PMU1CRU_CLKGATE_CON_CNT; i++, j++)
+ mmio_write_32(PMU1CRU_BASE + CRU_CLKGATE_CON(i),
+ WITH_16BITS_WMSK(clk_save[j]));
+}
+
+static 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(bus / 32)));
+}
+
+static void pmu_qch_pwr_ctlr(uint32_t msk, uint32_t state)
+{
+ uint32_t wait_cnt = 0;
+
+ if (state != 0)
+ state = msk;
+
+ mmio_write_32(PMU_BASE + PMU2_QCHANNEL_PWR_SFTCON,
+ BITS_WITH_WMASK(state, msk, 0));
+
+ while ((mmio_read_32(PMU_BASE + PMU2_QCHANNEL_STATUS) & msk) != state) {
+ if (++wait_cnt > QCH_PWR_LOOP)
+ break;
+ udelay(1);
+ }
+
+ if (wait_cnt > BUS_IDLE_LOOP)
+ WARN("%s: can't wait qch:0x%x to state:0x%x (0x%x)\n",
+ __func__, msk, state,
+ mmio_read_32(PMU_BASE + PMU2_QCHANNEL_STATUS));
+}
+
+static inline uint32_t pmu_power_domain_chain_st(uint32_t pd)
+{
+ return mmio_read_32(PMU_BASE + PMU2_PWR_CHAIN1_ST(pd / 32)) & BIT(pd % 32) ?
+ pmu_pd_on :
+ pmu_pd_off;
+}
+
+static inline uint32_t pmu_power_domain_mem_st(uint32_t pd)
+{
+ return mmio_read_32(PMU_BASE + PMU2_PWR_MEM_ST(pd / 32)) & BIT(pd % 32) ?
+ pmu_pd_off :
+ pmu_pd_on;
+}
+
+static inline uint32_t pmu_power_domain_st(uint32_t pd)
+{
+ int8_t pd_repair = pd_repair_map[pd];
+
+ if (pd_repair >= 0)
+ return mmio_read_32(PMU_BASE + PMU2_BISR_STATUS(4)) & BIT(pd_repair) ?
+ pmu_pd_on :
+ pmu_pd_off;
+ else
+ return mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST(pd / 32)) & BIT(pd % 32) ?
+ pmu_pd_off :
+ pmu_pd_on;
+}
+
+static int pmu_power_domain_pd_to_mem_st(uint32_t pd, uint32_t *pd_mem_st)
+{
+ uint32_t mem_st;
+
+ switch (pd) {
+ case PD_NPUTOP:
+ mem_st = PD_NPU_TOP_MEM_ST;
+ break;
+ case PD_NPU1:
+ mem_st = PD_NPU1_MEM_ST;
+ break;
+ case PD_NPU2:
+ mem_st = PD_NPU2_MEM_ST;
+ break;
+ case PD_VENC0:
+ mem_st = PD_VENC0_MEM_ST;
+ break;
+ case PD_VENC1:
+ mem_st = PD_VENC1_MEM_ST;
+ break;
+ case PD_RKVDEC0:
+ mem_st = PD_RKVDEC0_MEM_ST;
+ break;
+ case PD_RKVDEC1:
+ mem_st = PD_RKVDEC1_MEM_ST;
+ break;
+ case PD_RGA30:
+ mem_st = PD_RGA30_MEM_ST;
+ break;
+ case PD_AV1:
+ mem_st = PD_AV1_MEM_ST;
+ break;
+ case PD_VI:
+ mem_st = PD_VI_MEM_ST;
+ break;
+ case PD_FEC:
+ mem_st = PD_FEC_MEM_ST;
+ break;
+ case PD_ISP1:
+ mem_st = PD_ISP1_MEM_ST;
+ break;
+ case PD_RGA31:
+ mem_st = PD_RGA31_MEM_ST;
+ break;
+ case PD_VOP:
+ mem_st = PD_VOP_MEM_ST;
+ break;
+ case PD_VO0:
+ mem_st = PD_VO0_MEM_ST;
+ break;
+ case PD_VO1:
+ mem_st = PD_VO1_MEM_ST;
+ break;
+ case PD_AUDIO:
+ mem_st = PD_AUDIO_MEM_ST;
+ break;
+ case PD_PHP:
+ mem_st = PD_PHP_MEM_ST;
+ break;
+ case PD_GMAC:
+ mem_st = PD_GMAC_MEM_ST;
+ break;
+ case PD_PCIE:
+ mem_st = PD_PCIE_MEM_ST;
+ break;
+ case PD_NVM0:
+ mem_st = PD_NVM0_MEM_ST;
+ break;
+ case PD_SDIO:
+ mem_st = PD_SDIO_MEM_ST;
+ break;
+ case PD_USB:
+ mem_st = PD_USB_MEM_ST;
+ break;
+ case PD_SDMMC:
+ mem_st = PD_SDMMC_MEM_ST;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *pd_mem_st = mem_st;
+
+ return 0;
+}
+
+static int pmu_power_domain_reset_mem(uint32_t pd, uint32_t pd_mem_st)
+{
+ uint32_t loop = 0;
+ int ret = 0;
+
+ while (pmu_power_domain_chain_st(pd_mem_st) != pmu_pd_on) {
+ udelay(1);
+ loop++;
+ if (loop >= PD_CTR_LOOP) {
+ WARN("%s: %d chain up time out\n", __func__, pd);
+ ret = -EINVAL;
+ goto error;
+ }
+ }
+
+ udelay(60);
+
+ mmio_write_32(PMU_BASE + PMU2_MEMPWR_GATE_SFTCON(pd / 16),
+ BITS_WITH_WMASK(pmu_pd_off, 0x1, pd % 16));
+ dsb();
+
+ loop = 0;
+ while (pmu_power_domain_mem_st(pd_mem_st) != pmu_pd_off) {
+ udelay(1);
+ loop++;
+ if (loop >= PD_CTR_LOOP) {
+ WARN("%s: %d mem down time out\n", __func__, pd);
+ ret = -EINVAL;
+ goto error;
+ }
+ }
+
+ mmio_write_32(PMU_BASE + PMU2_MEMPWR_GATE_SFTCON(pd / 16),
+ BITS_WITH_WMASK(pmu_pd_on, 0x1, pd % 16));
+ dsb();
+
+ loop = 0;
+ while (pmu_power_domain_mem_st(pd_mem_st) != pmu_pd_on) {
+ udelay(1);
+ loop++;
+ if (loop >= PD_CTR_LOOP) {
+ WARN("%s: %d mem up time out\n", __func__, pd);
+ ret = -EINVAL;
+ goto error;
+ }
+ }
+
+ return 0;
+
+error:
+ return ret;
+}
+
+static int pmu_power_domain_ctr(uint32_t pd, uint32_t pd_state)
+{
+ uint32_t loop = 0;
+ uint32_t is_mem_on = pmu_pd_off;
+ uint32_t pd_mem_st;
+ int ret = 0;
+
+ if (pd_state == pmu_pd_on) {
+ ret = pmu_power_domain_pd_to_mem_st(pd, &pd_mem_st);
+ if (ret == 0) {
+ is_mem_on = pmu_power_domain_mem_st(pd_mem_st);
+ if (is_mem_on == pmu_pd_on)
+ WARN("%s: %d mem is up\n", __func__, pd);
+ }
+ }
+
+ mmio_write_32(PMU_BASE + PMU2_PWR_GATE_SFTCON(pd / 16),
+ BITS_WITH_WMASK(pd_state, 0x1, pd % 16));
+ dsb();
+
+ if (is_mem_on == pmu_pd_on) {
+ ret = pmu_power_domain_reset_mem(pd, pd_mem_st);
+ if (ret != 0)
+ goto out;
+ WARN("%s: %d mem reset ok\n", __func__, pd);
+ }
+
+ 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, 0x%x) error!\n", __func__, pd, pd_state,
+ mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST(0)),
+ mmio_read_32(PMU_BASE + PMU2_BISR_STATUS(4)));
+ ret = -EINVAL;
+ }
+
+out:
+ 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) ? bus_idle : bus_active;
+
+ switch (pd_id) {
+ case PD_GPU:
+ pmu_bus_idle_req(BUS_ID_GPU, state);
+ break;
+ case PD_NPUTOP:
+ pmu_bus_idle_req(BUS_ID_NPUTOP, state);
+ break;
+ case PD_NPU1:
+ pmu_bus_idle_req(BUS_ID_NPU1, state);
+ break;
+ case PD_NPU2:
+ pmu_bus_idle_req(BUS_ID_NPU2, state);
+ break;
+ case PD_VENC0:
+ pmu_bus_idle_req(BUS_ID_RKVENC0, state);
+ break;
+ case PD_VENC1:
+ pmu_bus_idle_req(BUS_ID_RKVENC1, state);
+ break;
+ case PD_RKVDEC0:
+ pmu_bus_idle_req(BUS_ID_RKVDEC0, state);
+ break;
+ case PD_RKVDEC1:
+ pmu_bus_idle_req(BUS_ID_RKVDEC1, state);
+ break;
+ case PD_VDPU:
+ pmu_bus_idle_req(BUS_ID_VDPU, state);
+ break;
+ case PD_AV1:
+ pmu_bus_idle_req(BUS_ID_AV1, state);
+ break;
+ case PD_VI:
+ pmu_bus_idle_req(BUS_ID_VI, state);
+ break;
+ case PD_ISP1:
+ pmu_bus_idle_req(BUS_ID_ISP, state);
+ break;
+ case PD_RGA31:
+ pmu_bus_idle_req(BUS_ID_RGA31, state);
+ break;
+ case PD_VOP:
+ pmu_bus_idle_req(BUS_ID_VOP_CHANNEL, state);
+ pmu_bus_idle_req(BUS_ID_VOP, state);
+ break;
+ case PD_VO0:
+ pmu_bus_idle_req(BUS_ID_VO0, state);
+ break;
+ case PD_VO1:
+ pmu_bus_idle_req(BUS_ID_VO1, state);
+ break;
+ case PD_AUDIO:
+ pmu_bus_idle_req(BUS_ID_AUDIO, state);
+ break;
+ case PD_PHP:
+ pmu_bus_idle_req(BUS_ID_PHP, state);
+ break;
+ case PD_NVM:
+ pmu_bus_idle_req(BUS_ID_NVM, state);
+ break;
+ case PD_SDIO:
+ pmu_bus_idle_req(BUS_ID_SDIO, state);
+ break;
+ case PD_USB:
+ pmu_bus_idle_req(BUS_ID_USB, state);
+ break;
+ case PD_SECURE:
+ pmu_bus_idle_req(BUS_ID_SECURE, 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.qch_pwr_st =
+ mmio_read_32(PMU_BASE + PMU2_QCHANNEL_STATUS) & PMU2_QCH_PWR_MSK;
+ ddr_data.pmu_pd_st0 = mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST(0));
+ ddr_data.bus_idle_st0 = mmio_read_32(PMU_BASE + PMU2_BUS_IDLE_ST(0));
+
+ qos_save();
+
+ if ((ddr_data.pmu_pd_st0 & BIT(PD_PHP)) == 0)
+ pd_php_save();
+
+ if ((ddr_data.pmu_pd_st0 & BIT(PD_CRYPTO)) == 0)
+ pd_crypto_save();
+
+ pmu_qch_pwr_ctlr(0x20, 1);
+ pmu_qch_pwr_ctlr(0x40, 1);
+ pmu_qch_pwr_ctlr(0x1, 1);
+ pmu_qch_pwr_ctlr(0x2, 1);
+ pmu_qch_pwr_ctlr(0x4, 1);
+ pmu_qch_pwr_ctlr(0x8, 1);
+ pmu_qch_pwr_ctlr(0x10, 1);
+
+ pmu_bus_idle_req(BUS_ID_VO1USBTOP, bus_idle);
+ pmu_bus_idle_req(BUS_ID_SECURE_VO1USB_CHANNEL, bus_idle);
+
+ pmu_bus_idle_req(BUS_ID_USB, bus_idle);
+
+ pmu_set_power_domain(PD_GPU, pmu_pd_off);
+
+ pmu_set_power_domain(PD_NPU1, pmu_pd_off);
+ pmu_set_power_domain(PD_NPU2, pmu_pd_off);
+ pmu_set_power_domain(PD_NPUTOP, pmu_pd_off);
+ pmu_set_power_domain(PD_NPU, pmu_pd_off);
+
+ pmu_set_power_domain(PD_RKVDEC1, pmu_pd_off);
+ pmu_set_power_domain(PD_RKVDEC0, pmu_pd_off);
+ pmu_set_power_domain(PD_VENC1, pmu_pd_off);
+ pmu_set_power_domain(PD_VENC0, pmu_pd_off);
+ pmu_set_power_domain(PD_VCODEC, pmu_pd_off);
+
+ pmu_set_power_domain(PD_RGA30, pmu_pd_off);
+ pmu_set_power_domain(PD_AV1, pmu_pd_off);
+ pmu_set_power_domain(PD_VDPU, pmu_pd_off);
+
+ pmu_set_power_domain(PD_VO0, pmu_pd_off);
+ pmu_set_power_domain(PD_VO1, pmu_pd_off);
+ pmu_set_power_domain(PD_VOP, pmu_pd_off);
+
+ pmu_set_power_domain(PD_FEC, pmu_pd_off);
+ pmu_set_power_domain(PD_ISP1, pmu_pd_off);
+ pmu_set_power_domain(PD_VI, pmu_pd_off);
+
+ pmu_set_power_domain(PD_RGA31, pmu_pd_off);
+
+ pmu_set_power_domain(PD_AUDIO, pmu_pd_off);
+
+ pmu_set_power_domain(PD_GMAC, pmu_pd_off);
+ pmu_set_power_domain(PD_PCIE, pmu_pd_off);
+ pmu_set_power_domain(PD_PHP, pmu_pd_off);
+
+ pmu_set_power_domain(PD_SDIO, pmu_pd_off);
+
+ pmu_set_power_domain(PD_NVM0, pmu_pd_off);
+ pmu_set_power_domain(PD_NVM, pmu_pd_off);
+
+ pmu_set_power_domain(PD_SDMMC, pmu_pd_off);
+ pmu_set_power_domain(PD_CRYPTO, pmu_pd_off);
+}
+
+static void pmu_power_domains_resume(void)
+{
+ int i;
+
+ pmu_set_power_domain(PD_CRYPTO, !!(ddr_data.pmu_pd_st0 & BIT(PD_CRYPTO)));
+ pmu_set_power_domain(PD_SDMMC, !!(ddr_data.pmu_pd_st0 & BIT(PD_SDMMC)));
+
+ pmu_set_power_domain(PD_NVM, !!(ddr_data.pmu_pd_st0 & BIT(PD_NVM)));
+ pmu_set_power_domain(PD_NVM0, !!(ddr_data.pmu_pd_st0 & BIT(PD_NVM0)));
+
+ pmu_set_power_domain(PD_SDIO, !!(ddr_data.pmu_pd_st0 & BIT(PD_SDIO)));
+
+ pmu_set_power_domain(PD_PHP, !!(ddr_data.pmu_pd_st0 & BIT(PD_PHP)));
+ pmu_set_power_domain(PD_PCIE, !!(ddr_data.pmu_pd_st0 & BIT(PD_PCIE)));
+ pmu_set_power_domain(PD_GMAC, !!(ddr_data.pmu_pd_st0 & BIT(PD_GMAC)));
+
+ pmu_set_power_domain(PD_AUDIO, !!(ddr_data.pmu_pd_st0 & BIT(PD_AUDIO)));
+
+ pmu_set_power_domain(PD_USB, !!(ddr_data.pmu_pd_st0 & BIT(PD_USB)));
+
+ pmu_set_power_domain(PD_RGA31, !!(ddr_data.pmu_pd_st0 & BIT(PD_RGA31)));
+
+ pmu_set_power_domain(PD_VI, !!(ddr_data.pmu_pd_st0 & BIT(PD_VI)));
+ pmu_set_power_domain(PD_ISP1, !!(ddr_data.pmu_pd_st0 & BIT(PD_ISP1)));
+ pmu_set_power_domain(PD_FEC, !!(ddr_data.pmu_pd_st0 & BIT(PD_FEC)));
+
+ pmu_set_power_domain(PD_VOP, !!(ddr_data.pmu_pd_st0 & BIT(PD_VOP)));
+
+ pmu_set_power_domain(PD_VO1, !!(ddr_data.pmu_pd_st0 & BIT(PD_VO1)));
+
+ pmu_set_power_domain(PD_VO0, !!(ddr_data.pmu_pd_st0 & BIT(PD_VO0)));
+
+ pmu_set_power_domain(PD_VDPU, !!(ddr_data.pmu_pd_st0 & BIT(PD_VDPU)));
+ pmu_set_power_domain(PD_AV1, !!(ddr_data.pmu_pd_st0 & BIT(PD_AV1)));
+ pmu_set_power_domain(PD_RGA30, !!(ddr_data.pmu_pd_st0 & BIT(PD_RGA30)));
+
+ pmu_set_power_domain(PD_VCODEC, !!(ddr_data.pmu_pd_st0 & BIT(PD_VCODEC)));
+ pmu_set_power_domain(PD_VENC0, !!(ddr_data.pmu_pd_st0 & BIT(PD_VENC0)));
+ pmu_set_power_domain(PD_VENC1, !!(ddr_data.pmu_pd_st0 & BIT(PD_VENC1)));
+ pmu_set_power_domain(PD_RKVDEC0, !!(ddr_data.pmu_pd_st0 & BIT(PD_RKVDEC0)));
+ pmu_set_power_domain(PD_RKVDEC1, !!(ddr_data.pmu_pd_st0 & BIT(PD_RKVDEC1)));
+
+ pmu_set_power_domain(PD_NPU, !!(ddr_data.pmu_pd_st0 & BIT(PD_NPU)));
+ pmu_set_power_domain(PD_NPUTOP, !!(ddr_data.pmu_pd_st0 & BIT(PD_NPUTOP)));
+ pmu_set_power_domain(PD_NPU2, !!(ddr_data.pmu_pd_st0 & BIT(PD_NPU2)));
+ pmu_set_power_domain(PD_NPU1, !!(ddr_data.pmu_pd_st0 & BIT(PD_NPU1)));
+
+ pmu_set_power_domain(PD_GPU, !!(ddr_data.pmu_pd_st0 & BIT(PD_GPU)));
+
+ for (i = 0; i < 32; i++)
+ pmu_bus_idle_req(i, !!(ddr_data.bus_idle_st0 & BIT(i)));
+
+ pmu_qch_pwr_ctlr(0x10, !!(ddr_data.qch_pwr_st & 0x10));
+ pmu_qch_pwr_ctlr(0x8, !!(ddr_data.qch_pwr_st & 0x8));
+ pmu_qch_pwr_ctlr(0x4, !!(ddr_data.qch_pwr_st & 0x4));
+ pmu_qch_pwr_ctlr(0x2, !!(ddr_data.qch_pwr_st & 0x2));
+ pmu_qch_pwr_ctlr(0x1, !!(ddr_data.qch_pwr_st & 0x1));
+ pmu_qch_pwr_ctlr(0x40, !!(ddr_data.qch_pwr_st & 0x40));
+ pmu_qch_pwr_ctlr(0x20, !!(ddr_data.qch_pwr_st & 0x20));
+
+ if ((ddr_data.pmu_pd_st0 & BIT(PD_CRYPTO)) == 0)
+ pd_crypto_restore();
+
+ if ((ddr_data.pmu_pd_st0 & BIT(PD_PHP)) == 0)
+ pd_php_restore();
+
+ qos_restore();
+}
+
+static int cpus_power_domain_on(uint32_t cpu_id)
+{
+ mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id),
+ BITS_WITH_WMASK(0, 0x1, core_pm_en));
+ mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id),
+ BITS_WITH_WMASK(1, 0x1, core_pm_sft_wakeup_en));
+ dsb();
+
+ return 0;
+}
+
+static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg)
+{
+ uint32_t apm_value = BIT(core_pm_en);
+
+ if (pd_cfg == core_pwr_wfi_int)
+ apm_value |= BIT(core_pm_int_wakeup_en);
+
+ mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id),
+ BITS_WITH_WMASK(apm_value, 0x3, 0));
+ dsb();
+
+ return 0;
+}
+
+static inline void cpus_pd_req_enter_wfi(void)
+{
+ /* CORTEX_A55_CPUACTLR_EL1 */
+ __asm__ volatile ("msr DBGPRCR_EL1, xzr\n"
+ "mrs x0, S3_0_C15_C2_7\n"
+ "orr x0, x0, #0x1\n"
+ "msr S3_0_C15_C2_7, x0\n"
+ "wfi_loop:\n"
+ "isb\n"
+ "wfi\n"
+ "b wfi_loop\n");
+}
+
+static void nonboot_cpus_off(void)
+{
+ uint32_t boot_cpu, cpu, tmp;
+ uint32_t exp_st;
+ uint32_t bcore0_rst_msk = 0, bcore1_rst_msk = 0;
+ int wait_cnt;
+
+ bcore0_rst_msk = CRU_BIGCPU02_RST_MSK | CRU_BIGCPU13_RST_MSK;
+ bcore1_rst_msk = CRU_BIGCPU02_RST_MSK | CRU_BIGCPU13_RST_MSK;
+
+ mmio_write_32(BIGCORE0CRU_BASE + 0xa00, BITS_WITH_WMASK(0, bcore0_rst_msk, 0));
+ mmio_write_32(BIGCORE1CRU_BASE + 0xa00, BITS_WITH_WMASK(0, bcore1_rst_msk, 0));
+
+ wait_cnt = NONBOOT_CPUS_OFF_LOOP;
+ exp_st = SYS_GRF_BIG_CPUS_WFE;
+ do {
+ wait_cnt--;
+ tmp = mmio_read_32(SYSGRF_BASE + SYS_GRF_SOC_STATUS(3));
+ tmp &= SYS_GRF_BIG_CPUS_WFE;
+ } while (tmp != exp_st && wait_cnt);
+
+ 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_wfi);
+ }
+
+ mmio_write_32(SRAM_BASE + 0x08, (uintptr_t)&cpus_pd_req_enter_wfi);
+ mmio_write_32(SRAM_BASE + 0x04, 0xdeadbeaf);
+
+ dsb();
+ isb();
+
+ sev();
+
+ wait_cnt = NONBOOT_CPUS_OFF_LOOP;
+ do {
+ wait_cnt--;
+ tmp = mmio_read_32(PMU_BASE + PMU2_CLUSTER_ST);
+ tmp &= CLUSTER_STS_NONBOOT_CPUS_DWN;
+ } while (tmp != CLUSTER_STS_NONBOOT_CPUS_DWN && wait_cnt);
+
+ if (tmp != CLUSTER_STS_NONBOOT_CPUS_DWN)
+ ERROR("nonboot cpus status(%x) error!\n", tmp);
+}
+
+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();
+
+ flush_dcache_range((uintptr_t)cpuson_flags, sizeof(cpuson_flags));
+ flush_dcache_range((uintptr_t)cpuson_entry_point,
+ sizeof(cpuson_entry_point));
+ dsb();
+ isb();
+
+ cpus_power_domain_on(cpu_id);
+
+ 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_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_suspend(void)
+{
+ uint32_t cpu_id = plat_my_core_pos();
+
+ assert(cpu_id < PLATFORM_CORE_COUNT);
+
+ cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN;
+ cpuson_entry_point[cpu_id] = plat_get_sec_entrypoint();
+ dsb();
+ flush_dcache_range((uintptr_t)cpuson_flags, sizeof(cpuson_flags));
+ flush_dcache_range((uintptr_t)cpuson_entry_point,
+ sizeof(cpuson_entry_point));
+ dsb();
+ isb();
+
+ cpus_power_domain_off(cpu_id, core_pwr_wfi_int);
+
+ __asm__ volatile ("msr DBGPRCR_EL1, xzr\n"
+ "mrs x0, S3_0_C15_C2_7\n"
+ "orr x0, x0, #0x1\n"
+ "msr S3_0_C15_C2_7, x0\n");
+
+ return PSCI_E_SUCCESS;
+}
+
+int rockchip_soc_cores_pwr_dm_resume(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, 0x3, 0));
+
+ dsb();
+
+ return PSCI_E_SUCCESS;
+}
+
+static void ddr_sleep_config(void)
+{
+ int i;
+
+ if (pmu_power_domain_st(PD_DDR01) == 0) {
+ ddr_data.ddrgrf_chn_con0[0] =
+ mmio_read_32(DDR01GRF_BASE + DDRGRF_CHA_CON(0));
+ ddr_data.ddrgrf_chn_con0[1] =
+ mmio_read_32(DDR01GRF_BASE + DDRGRF_CHB_CON(0));
+ ddr_data.ddrgrf_chn_con1[0] =
+ mmio_read_32(DDR01GRF_BASE + DDRGRF_CHA_CON(1));
+ ddr_data.ddrgrf_chn_con1[1] =
+ mmio_read_32(DDR01GRF_BASE + DDRGRF_CHB_CON(1));
+ ddr_data.ddrgrf_chn_con2[0] =
+ mmio_read_32(DDR01GRF_BASE + DDRGRF_CHA_CON(2));
+ ddr_data.ddrgrf_chn_con2[1] =
+ mmio_read_32(DDR01GRF_BASE + DDRGRF_CHB_CON(2));
+
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(2), 0x20002000);
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(2), 0x20002000);
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(2), 0x08000000);
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(2), 0x08000000);
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(0), 0x00200020);
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(0), 0x00200020);
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(1), 0x00400040);
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(1), 0x00400040);
+ }
+
+ if (pmu_power_domain_st(PD_DDR23) == 0) {
+ ddr_data.ddrgrf_chn_con0[2] =
+ mmio_read_32(DDR23GRF_BASE + DDRGRF_CHA_CON(0));
+ ddr_data.ddrgrf_chn_con0[3] =
+ mmio_read_32(DDR23GRF_BASE + DDRGRF_CHB_CON(0));
+ ddr_data.ddrgrf_chn_con1[2] =
+ mmio_read_32(DDR23GRF_BASE + DDRGRF_CHA_CON(1));
+ ddr_data.ddrgrf_chn_con1[3] =
+ mmio_read_32(DDR23GRF_BASE + DDRGRF_CHB_CON(1));
+ ddr_data.ddrgrf_chn_con2[2] =
+ mmio_read_32(DDR23GRF_BASE + DDRGRF_CHA_CON(2));
+ ddr_data.ddrgrf_chn_con2[3] =
+ mmio_read_32(DDR23GRF_BASE + DDRGRF_CHB_CON(2));
+
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(2), 0x20002000);
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(2), 0x20002000);
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(2), 0x08000000);
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(2), 0x08000000);
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(0), 0x00200020);
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(0), 0x00200020);
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(1), 0x00400040);
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(1), 0x00400040);
+ }
+
+ for (i = 0; i < DDR_CHN_CNT; i++) {
+ ddr_data.pmu1_ddr_pwr_sft_con[i] =
+ mmio_read_32(PMU_BASE + PMU1_DDR_PWR_SFTCON(i));
+ mmio_write_32(PMU_BASE + PMU1_DDR_PWR_SFTCON(i), 0x0fff0900);
+ }
+}
+
+static void ddr_sleep_config_restore(void)
+{
+ int i;
+
+ for (i = 0; i < DDR_CHN_CNT; i++) {
+ mmio_write_32(PMU_BASE + PMU1_DDR_PWR_SFTCON(i),
+ 0x0fff0000 | ddr_data.pmu1_ddr_pwr_sft_con[i]);
+ }
+
+ if (pmu_power_domain_st(PD_DDR01) == 0) {
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(1),
+ 0x00400000 | ddr_data.ddrgrf_chn_con1[0]);
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(1),
+ 0x00400000 | ddr_data.ddrgrf_chn_con1[1]);
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(0),
+ 0x00200000 | ddr_data.ddrgrf_chn_con0[0]);
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(0),
+ 0x00200000 | ddr_data.ddrgrf_chn_con0[1]);
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(2),
+ 0x28000000 | ddr_data.ddrgrf_chn_con2[0]);
+ mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(2),
+ 0x28000000 | ddr_data.ddrgrf_chn_con2[1]);
+ }
+
+ if (pmu_power_domain_st(PD_DDR23) == 0) {
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(1),
+ 0x00400000 | ddr_data.ddrgrf_chn_con1[2]);
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(1),
+ 0x00400000 | ddr_data.ddrgrf_chn_con1[3]);
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(0),
+ 0x00200000 | ddr_data.ddrgrf_chn_con0[2]);
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(0),
+ 0x00200000 | ddr_data.ddrgrf_chn_con0[3]);
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(2),
+ 0x28000000 | ddr_data.ddrgrf_chn_con2[2]);
+ mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(2),
+ 0x28000000 | ddr_data.ddrgrf_chn_con2[3]);
+ }
+}
+
+static void pmu_sleep_config(void)
+{
+ uint32_t pmu1_pwr_con, pmu1_wkup_int_con, pmu1_cru_pwr_con;
+ uint32_t pmu1_ddr_pwr_con, pmu1_pll_pd_con[2] = {0};
+ uint32_t pmu2_dsu_pwr_con, pmu2_core_pwr_con, pmu2_clst_idle_con;
+ uint32_t pmu2_bus_idle_con[3] = {0}, pmu2_pwr_gate_con[3] = {0};
+ uint32_t pmu2_vol_gate_con[3] = {0}, pmu2_qch_pwr_con = 0;
+ int i;
+
+ ddr_data.pmu1grf_soc_con7 = mmio_read_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(7));
+ ddr_data.pmu1grf_soc_con8 = mmio_read_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(8));
+ ddr_data.pmu1grf_soc_con9 = mmio_read_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(9));
+ ddr_data.pmu1sgrf_soc_con14 = mmio_read_32(PMU1SGRF_BASE + PMU1_SGRF_SOC_CON(14));
+ ddr_data.pmu0sgrf_soc_con1 = mmio_read_32(PMU0SGRF_BASE + PMU0_SGRF_SOC_CON(1));
+ ddr_data.pmu0grf_soc_con1 = mmio_read_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(1));
+
+ ddr_data.pmu2_vol_gate_con[0] = mmio_read_32(PMU_BASE + PMU2_VOL_GATE_CON(0));
+ ddr_data.pmu2_vol_gate_con[1] = mmio_read_32(PMU_BASE + PMU2_VOL_GATE_CON(1));
+ ddr_data.pmu2_vol_gate_con[2] = mmio_read_32(PMU_BASE + PMU2_VOL_GATE_CON(2));
+
+ ddr_data.pmu2_submem_gate_sft_con0 =
+ mmio_read_32(PMU_BASE + PMU2_MEMPWR_MD_GATE_SFTCON(0));
+
+ /* save pmic_sleep iomux gpio0_a4 */
+ ddr_data.gpio0a_iomux_l = mmio_read_32(PMU0IOC_BASE + 0);
+ ddr_data.gpio0a_iomux_h = mmio_read_32(PMU0IOC_BASE + 4);
+ ddr_data.pmu0grf_soc_con3 = mmio_read_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(3));
+
+ /* PMU1 repair disable */
+ mmio_write_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(0), 0x00010000);
+
+ /* set pmic_sleep iomux */
+ mmio_write_32(PMU0IOC_BASE + 0,
+ BITS_WITH_WMASK(1, 0xf, 8) |
+ BITS_WITH_WMASK(1, 0xfu, 12));
+
+ /* set tsadc_shut_m0 pin iomux to gpio */
+ mmio_write_32(PMU0IOC_BASE + 0,
+ BITS_WITH_WMASK(0, 0xf, 4));
+
+ /* set spi2_cs0/1 pin iomux to gpio */
+ mmio_write_32(PMU0IOC_BASE + 8,
+ BITS_WITH_WMASK(0, 0xff, 0));
+
+ /* sleep 1~2 src select */
+ mmio_write_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(3),
+ BITS_WITH_WMASK(0x8, 0xf, 0) |
+ BITS_WITH_WMASK(0x8, 0xf, 4) |
+ BITS_WITH_WMASK(0x0, 0x3, 8));
+
+ pmu1_wkup_int_con = BIT(WAKEUP_GPIO0_INT_EN) |
+ BIT(WAKEUP_CPU0_INT_EN);
+
+ pmu1_pwr_con = BIT(powermode_en);
+
+ pmu1_cru_pwr_con =
+ BIT(alive_osc_mode_en) |
+ BIT(power_off_en) |
+ BIT(pd_clk_src_gate_en);
+
+ pmu1_ddr_pwr_con = 0;
+
+ pmu2_dsu_pwr_con =
+ BIT(DSU_PWRDN_EN) |
+ BIT(DSU_PWROFF_EN);
+
+ pmu2_core_pwr_con = BIT(CORE_PWRDN_EN);
+
+ pmu2_clst_idle_con =
+ BIT(IDLE_REQ_BIGCORE0_EN) |
+ BIT(IDLE_REQ_BIGCORE1_EN) |
+ BIT(IDLE_REQ_DSU_EN) |
+ BIT(IDLE_REQ_LITDSU_EN) |
+ BIT(IDLE_REQ_ADB400_CORE_QCH_EN);
+
+ pmu1_pll_pd_con[0] =
+ BIT(B0PLL_PD_EN) |
+ BIT(B1PLL_PD_EN) |
+ BIT(LPLL_PD_EN) |
+ BIT(V0PLL_PD_EN) |
+ BIT(AUPLL_PD_EN) |
+ BIT(GPLL_PD_EN) |
+ BIT(CPLL_PD_EN) |
+ BIT(NPLL_PD_EN);
+
+ pmu1_pll_pd_con[1] =
+ BIT(PPLL_PD_EN) |
+ BIT(SPLL_PD_EN);
+
+ pmu2_bus_idle_con[0] = 0;
+
+ pmu2_bus_idle_con[1] =
+ BIT(BUS_ID_SECURE - 16) |
+ BIT(BUS_ID_SECURE_CENTER_CHANNEL - 16) |
+ BIT(BUS_ID_CENTER_CHANNEL - 16);
+
+ pmu2_bus_idle_con[2] =
+ BIT(BUS_ID_MSCH - 32) |
+ BIT(BUS_ID_BUS - 32) |
+ BIT(BUS_ID_TOP - 32);
+
+ pmu2_pwr_gate_con[0] = 0;
+ pmu2_pwr_gate_con[1] = BIT(PD_SECURE - 16);
+ pmu2_pwr_gate_con[2] = 0;
+
+ pmu2_qch_pwr_con = 0;
+
+ pmu2_vol_gate_con[0] = 0x7;
+ pmu2_vol_gate_con[2] = 0;
+
+ mmio_write_32(PMU_BASE + PMU2_CORE_AUTO_PWR_CON(0), 0x00030000);
+ mmio_write_32(PMU_BASE + PMU2_CORE_AUTO_PWR_CON(1), 0x00030000);
+ mmio_write_32(PMU_BASE + PMU2_CORE_PWR_CON(0),
+ WITH_16BITS_WMSK(pmu2_core_pwr_con));
+ mmio_write_32(PMU_BASE + PMU2_CORE_PWR_CON(1),
+ WITH_16BITS_WMSK(pmu2_core_pwr_con));
+ mmio_write_32(PMU_BASE + PMU2_CLUSTER_IDLE_CON,
+ WITH_16BITS_WMSK(pmu2_clst_idle_con));
+ mmio_write_32(PMU_BASE + PMU2_DSU_AUTO_PWR_CON, 0x00030000);
+ mmio_write_32(PMU_BASE + PMU2_DSU_PWR_CON,
+ WITH_16BITS_WMSK(pmu2_dsu_pwr_con));
+
+ mmio_write_32(PMU_BASE + PMU1_OSC_STABLE_CNT_THRESH, 24000);
+ mmio_write_32(PMU_BASE + PMU1_STABLE_CNT_THRESH, 24000);
+ mmio_write_32(PMU_BASE + PMU1_WAKEUP_RST_CLR_CNT_THRESH, 24000);
+ mmio_write_32(PMU_BASE + PMU1_PLL_LOCK_CNT_THRESH, 24000);
+ mmio_write_32(PMU_BASE + PMU1_PWM_SWITCH_CNT_THRESH, 24000);
+ mmio_write_32(PMU_BASE + PMU2_CORE0_STABLE_CNT_THRESH, 24000);
+ mmio_write_32(PMU_BASE + PMU2_CORE0_PWRUP_CNT_THRESH, 24000);
+ mmio_write_32(PMU_BASE + PMU2_CORE0_PWRDN_CNT_THRESH, 24000);
+ mmio_write_32(PMU_BASE + PMU2_CORE1_STABLE_CNT_THRESH, 24000);
+ mmio_write_32(PMU_BASE + PMU2_CORE1_PWRUP_CNT_THRESH, 24000);
+ mmio_write_32(PMU_BASE + PMU2_CORE1_PWRDN_CNT_THRESH, 24000);
+ mmio_write_32(PMU_BASE + PMU2_DSU_STABLE_CNT_THRESH, 24000);
+ mmio_write_32(PMU_BASE + PMU2_DSU_PWRUP_CNT_THRESH, 24000);
+ mmio_write_32(PMU_BASE + PMU2_DSU_PWRDN_CNT_THRESH, 24000);
+
+ /* Config pmu power mode and pmu wakeup source */
+ mmio_write_32(PMU_BASE + PMU1_INT_MASK_CON,
+ BITS_WITH_WMASK(1, 0x1, 0));
+
+ /* pmu1_pwr_con */
+ mmio_write_32(PMU_BASE + PMU1_PWR_CON,
+ WITH_16BITS_WMSK(pmu1_pwr_con));
+
+ /* cru_pwr_con */
+ mmio_write_32(PMU_BASE + PMU1_CRU_PWR_CON,
+ WITH_16BITS_WMSK(pmu1_cru_pwr_con));
+
+ /* wakeup source */
+ mmio_write_32(PMU_BASE + PMU1_WAKEUP_INT_CON, pmu1_wkup_int_con);
+
+ /* ddr pwr con */
+ for (i = 0; i < DDR_CHN_CNT; i++) {
+ mmio_write_32(PMU_BASE + PMU1_DDR_PWR_CON(i),
+ WITH_16BITS_WMSK(pmu1_ddr_pwr_con));
+ pmu2_bus_idle_con[1] |=
+ BIT(BUS_ID_MSCH0 - 16 + i);
+ }
+
+ /* pll_pd */
+ mmio_write_32(PMU_BASE + PMU1_PLLPD_CON(0),
+ WITH_16BITS_WMSK(pmu1_pll_pd_con[0]));
+ mmio_write_32(PMU_BASE + PMU1_PLLPD_CON(1),
+ WITH_16BITS_WMSK(pmu1_pll_pd_con[1]));
+
+ /* bypass cpu1~7*/
+ mmio_write_32(PMU_BASE + PMU2_PWR_CON1, 0x00ff00fe);
+
+ /* 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]));
+ mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_CON(2),
+ WITH_16BITS_WMSK(pmu2_bus_idle_con[2]));
+ mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_CON(2),
+ 0xf000f000);
+ /* power gate */
+ mmio_write_32(PMU_BASE + PMU2_PWR_GATE_CON(0),
+ WITH_16BITS_WMSK(pmu2_pwr_gate_con[0]));
+ mmio_write_32(PMU_BASE + PMU2_PWR_GATE_CON(1),
+ WITH_16BITS_WMSK(pmu2_pwr_gate_con[1]));
+ mmio_write_32(PMU_BASE + PMU2_PWR_GATE_CON(2),
+ WITH_16BITS_WMSK(pmu2_pwr_gate_con[2]));
+ /* vol gate */
+ mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(0),
+ BITS_WITH_WMASK(pmu2_vol_gate_con[0], 0x7, 0));
+ mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(1), 0);
+ mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(2),
+ BITS_WITH_WMASK(pmu2_vol_gate_con[2], 0x3, 0));
+ /* qch */
+ mmio_write_32(PMU_BASE + PMU2_QCHANNEL_PWR_CON,
+ BITS_WITH_WMASK(pmu2_qch_pwr_con, 0x7f, 0));
+
+ mmio_write_32(PMU_BASE + PMU2_MEMPWR_MD_GATE_SFTCON(0),
+ 0x000f000f);
+}
+
+static void pmu_sleep_restore(void)
+{
+ mmio_write_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(7),
+ WITH_16BITS_WMSK(ddr_data.pmu1grf_soc_con7));
+ mmio_write_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(8),
+ WITH_16BITS_WMSK(ddr_data.pmu1grf_soc_con8));
+ mmio_write_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(9),
+ WITH_16BITS_WMSK(ddr_data.pmu1grf_soc_con9));
+ mmio_write_32(PMU1SGRF_BASE + PMU1_SGRF_SOC_CON(14),
+ WITH_16BITS_WMSK(ddr_data.pmu1sgrf_soc_con14));
+
+ mmio_write_32(PMU0SGRF_BASE + PMU0_SGRF_SOC_CON(1),
+ WITH_16BITS_WMSK(ddr_data.pmu0sgrf_soc_con1));
+ mmio_write_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(1),
+ WITH_16BITS_WMSK(ddr_data.pmu0grf_soc_con1));
+
+ mmio_write_32(PMU_BASE + PMU2_CORE_PWR_CON(0), 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU2_CORE_PWR_CON(1), 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU2_CLUSTER_IDLE_CON, 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU2_DSU_PWR_CON, 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU2_PWR_CON1, 0xffff0000);
+
+ /* Must clear PMU1_WAKEUP_INT_CON because the wakeup source
+ * in PMU1_WAKEUP_INT_CON will wakeup cpus in cpu_auto_pd state.
+ */
+ mmio_write_32(PMU_BASE + PMU1_WAKEUP_INT_CON, 0);
+ mmio_write_32(PMU_BASE + PMU1_PWR_CON, 0xffff0000);
+ mmio_write_32(PMU_BASE + PMU1_INT_MASK_CON, 0x00010000);
+ mmio_write_32(PMU_BASE + PMU0_WAKEUP_INT_CON, 0x00010000);
+ mmio_write_32(PMU_BASE + PMU0_PWR_CON, 0xffff0000);
+
+ mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(0),
+ WITH_16BITS_WMSK(ddr_data.pmu2_vol_gate_con[0]));
+ mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(1),
+ WITH_16BITS_WMSK(ddr_data.pmu2_vol_gate_con[1]));
+ mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(2),
+ WITH_16BITS_WMSK(ddr_data.pmu2_vol_gate_con[2]));
+
+ mmio_write_32(PMU_BASE + PMU2_MEMPWR_MD_GATE_SFTCON(0),
+ WITH_16BITS_WMSK(ddr_data.pmu2_submem_gate_sft_con0));
+
+ mmio_write_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(3),
+ WITH_16BITS_WMSK(ddr_data.pmu0grf_soc_con3));
+ mmio_write_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(2),
+ WITH_16BITS_WMSK(ddr_data.pmu1grf_soc_con2));
+
+ mmio_write_32(PMU0IOC_BASE + 0x4,
+ WITH_16BITS_WMSK(ddr_data.gpio0a_iomux_h));
+ mmio_write_32(PMU0IOC_BASE + 0,
+ WITH_16BITS_WMSK(ddr_data.gpio0a_iomux_l));
+}
+
+static void soc_sleep_config(void)
+{
+ ddr_data.gpio0b_iomux_l = mmio_read_32(PMU0IOC_BASE + 0x8);
+
+ pmu_sleep_config();
+ ddr_sleep_config();
+}
+
+static void soc_sleep_restore(void)
+{
+ ddr_sleep_config_restore();
+ pmu_sleep_restore();
+
+ mmio_write_32(PMU0IOC_BASE + 0x8, WITH_16BITS_WMSK(ddr_data.gpio0b_iomux_l));
+}
+
+static void pm_pll_suspend(void)
+{
+ ddr_data.cru_mode_con = mmio_read_32(CRU_BASE + 0x280);
+ ddr_data.busscru_mode_con = mmio_read_32(BUSSCRU_BASE + 0x280);
+ ddr_data.pmu2_bisr_con0 = mmio_read_32(PMU_BASE + PMU2_BISR_CON(0));
+ ddr_data.cpll_con0 = mmio_read_32(CRU_BASE + CRU_PLLS_CON(2, 0));
+ ddr_data.pmu1cru_clksel_con1 = mmio_read_32(PMU1CRU_BASE + CRU_CLKSEL_CON(1));
+
+ /* disable bisr_init */
+ mmio_write_32(PMU_BASE + PMU2_BISR_CON(0), BITS_WITH_WMASK(0, 0x1, 0));
+ /* cpll bypass */
+ mmio_write_32(CRU_BASE + CRU_PLLS_CON(2, 0), BITS_WITH_WMASK(1u, 1u, 15));
+}
+
+static void pm_pll_restore(void)
+{
+ pm_pll_wait_lock(CRU_BASE + CRU_PLLS_CON(2, 0));
+
+ mmio_write_32(CRU_BASE + 0x280, WITH_16BITS_WMSK(ddr_data.cru_mode_con));
+ mmio_write_32(BUSSCRU_BASE + 0x280, WITH_16BITS_WMSK(ddr_data.busscru_mode_con));
+ mmio_write_32(CRU_BASE + CRU_PLLS_CON(2, 0), WITH_16BITS_WMSK(ddr_data.cpll_con0));
+ dsb();
+ isb();
+ mmio_write_32(PMU_BASE + PMU2_BISR_CON(0), WITH_16BITS_WMSK(ddr_data.pmu2_bisr_con0));
+}
+
+int rockchip_soc_sys_pwr_dm_suspend(void)
+{
+ clk_gate_con_save();
+ clk_gate_con_disable();
+
+ psram_sleep_cfg->pm_flag &= ~PM_WARM_BOOT_BIT;
+
+ pmu_power_domains_suspend();
+ soc_sleep_config();
+ dsu_core_save();
+ pm_pll_suspend();
+
+ return 0;
+}
+
+int rockchip_soc_sys_pwr_dm_resume(void)
+{
+ pm_pll_restore();
+ dsu_core_restore();
+ soc_sleep_restore();
+ pmu_power_domains_resume();
+ plat_rockchip_gic_cpuif_enable();
+
+ psram_sleep_cfg->pm_flag |= PM_WARM_BOOT_BIT;
+
+ clk_gate_con_restore();
+
+ return 0;
+}
+
+void __dead2 rockchip_soc_cores_pd_pwr_dn_wfi(const
+ psci_power_state_t *target_state)
+{
+ psci_power_down_wfi();
+}
+
+void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void)
+{
+ cpus_pd_req_enter_wfi();
+ psci_power_down_wfi();
+}
+
+void __dead2 rockchip_soc_soft_reset(void)
+{
+ /* pll slow mode */
+ mmio_write_32(CRU_BASE + 0x280, 0x03ff0000);
+ mmio_write_32(BIGCORE0CRU_BASE + 0x280, 0x00030000);
+ mmio_write_32(BIGCORE0CRU_BASE + 0x300, 0x60000000);
+ mmio_write_32(BIGCORE0CRU_BASE + 0x304, 0x00600000);
+ mmio_write_32(BIGCORE1CRU_BASE + 0x280, 0x00030000);
+ mmio_write_32(BIGCORE1CRU_BASE + 0x300, 0x60000000);
+ mmio_write_32(BIGCORE1CRU_BASE + 0x304, 0x00600000);
+ mmio_write_32(DSUCRU_BASE + 0x280, 0x00030000);
+ mmio_write_32(DSUCRU_BASE + 0x318, 0x30600000);
+ mmio_write_32(DSUCRU_BASE + 0x31c, 0x30600000);
+ mmio_write_32(DSUCRU_BASE + 0x304, 0x00010000);
+ mmio_write_32(BUSSCRU_BASE + 0x280, 0x0003000);
+ dsb();
+ isb();
+
+ 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();
+}
+
+void __dead2 rockchip_soc_system_off(void)
+{
+ /* set pmic_sleep pin(gpio0_a2) to gpio mode */
+ mmio_write_32(PMU0IOC_BASE + 0, BITS_WITH_WMASK(0, 0xf, 8));
+
+ /* config output */
+ mmio_write_32(GPIO0_BASE + GPIO_SWPORT_DDR_L,
+ BITS_WITH_WMASK(1, 0x1, 2));
+
+ /* config output high level */
+ mmio_write_32(GPIO0_BASE + GPIO_SWPORT_DR_L,
+ BITS_WITH_WMASK(1, 0x1, 2));
+ 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();
+}
+
+static void rockchip_pmu_pd_init(void)
+{
+ mmio_write_32(PMU_BASE + PMU2_BISR_CON(1), 0xffffffff);
+ mmio_write_32(PMU_BASE + PMU2_BISR_CON(2), 0xffffffff);
+ mmio_write_32(PMU_BASE + PMU2_BISR_CON(3), 0xffffffff);
+
+ pmu_set_power_domain(PD_PHP, pmu_pd_on);
+ pmu_set_power_domain(PD_PCIE, pmu_pd_on);
+ pmu_set_power_domain(PD_GMAC, pmu_pd_on);
+ pmu_set_power_domain(PD_SECURE, pmu_pd_on);
+ pmu_set_power_domain(PD_VOP, pmu_pd_on);
+ pmu_set_power_domain(PD_VO0, pmu_pd_on);
+ pmu_set_power_domain(PD_VO1, pmu_pd_on);
+}
+
+#define PLL_LOCKED_TIMEOUT 600000U
+
+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)
+ break;
+ udelay(1);
+ }
+
+ if (delay <= 0)
+ ERROR("Can't wait pll(0x%x) lock\n", pll_base);
+}
+
+void rockchip_plat_mmu_el3(void)
+{
+ /* Nothing todo */
+}
+
+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_BIU_AUTO_CON(0), 0xffffffff);
+ mmio_write_32(PMU_BASE + PMU2_BIU_AUTO_CON(1), 0xffffffff);
+ mmio_write_32(PMU_BASE + PMU2_BIU_AUTO_CON(2), 0x00070007);
+
+ rockchip_pmu_pd_init();
+
+ /* grf_con_pmic_sleep_sel
+ * pmic sleep function selection
+ * 1'b0: From reset pulse generator, can reset external PMIC
+ * 1'b1: From pmu block, only support sleep function for external PMIC
+ */
+ mmio_write_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(3), 0x03ff0000);
+
+ /* pmusram remap to 0xffff0000 */
+ mmio_write_32(PMU0SGRF_BASE + PMU0_SGRF_SOC_CON(2), 0x00030001);
+
+ pm_reg_rgns_init();
+}
diff --git a/plat/rockchip/rk3588/drivers/pmu/pmu.h b/plat/rockchip/rk3588/drivers/pmu/pmu.h
new file mode 100644
index 0000000..7d8288c
--- /dev/null
+++ b/plat/rockchip/rk3588/drivers/pmu/pmu.h
@@ -0,0 +1,589 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PMU_H__
+#define __PMU_H__
+
+#include <lib/mmio.h>
+
+#define PMU0_PWR_CON 0x0000
+#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_CHAIN_STABLE_CON 0x001c
+#define PMU0_DDR_RET_CON(i) (0x0020 + (i) * 4)
+#define PMU0_INFO_TX_CON 0x0030
+
+#define PMU1_VERSION_ID 0x4000
+#define PMU1_PWR_CON 0x4004
+#define PMU1_PWR_FSM 0x4008
+#define PMU1_INT_MASK_CON 0x400c
+#define PMU1_WAKEUP_INT_CON 0x4010
+#define PMU1_WAKEUP_INT_ST 0x4014
+#define PMU1_WAKEUP_EDGE_CON 0x4018
+#define PMU1_WAKEUP_EDGE_ST 0x401c
+#define PMU1_DDR_PWR_CON(i) (0x4020 + (i) * 4)
+#define PMU1_DDR_PWR_SFTCON(i) (0x4030 + (i) * 4)
+#define PMU1_DDR_PWR_FSM 0x4040
+#define PMU1_DDR_PWR_ST 0x4044
+#define PMU1_CRU_PWR_CON 0x4050
+#define PMU1_CRU_PWR_SFTCON 0x4054
+#define PMU1_CRU_PWR_FSM 0x4058
+#define PMU1_PLLPD_CON(i) (0x4060 + (i) * 4)
+#define PMU1_PLLPD_SFTCON(i) (0x4068 + (i) * 4)
+#define PMU1_STABLE_CNT_THRESH 0x4080
+#define PMU1_OSC_STABLE_CNT_THRESH 0x4084
+#define PMU1_WAKEUP_RST_CLR_CNT_THRESH 0x4088
+#define PMU1_PLL_LOCK_CNT_THRESH 0x408c
+#define PMU1_WAKEUP_TIMEOUT_THRESH 0x4094
+#define PMU1_PWM_SWITCH_CNT_THRESH 0x4098
+#define PMU1_SYS_REG(i) (0x4100 + (i) * 4)
+
+#define PMU2_PWR_CON1 0x8000
+#define PMU2_DSU_PWR_CON 0x8004
+#define PMU2_DSU_PWR_SFTCON 0x8008
+#define PMU2_DSU_AUTO_PWR_CON 0x800c
+#define PMU2_CPU_AUTO_PWR_CON(i) (0x8010 + (i) * 4)
+#define PMU2_CPU_PWR_SFTCON(i) (0x8030 + (i) * 4)
+#define PMU2_CORE_PWR_CON(i) (0x8050 + (i) * 4)
+#define PMU2_CORE_PWR_SFTCON(i) (0x8058 + (i) * 4)
+#define PMU2_CORE_AUTO_PWR_CON(i) (0x8060 + (i) * 4)
+#define PMU2_CLUSTER_NOC_AUTO_CON 0x8068
+#define PMU2_CLUSTER_DBG_PWR_CON 0x806c
+#define PMU2_CLUSTER_IDLE_CON 0x8070
+#define PMU2_CLUSTER_IDLE_SFTCON 0x8074
+#define PMU2_CLUSTER_IDLE_ACK 0x8078
+#define PMU2_CLUSTER_IDLE_ST 0x807c
+#define PMU2_CLUSTER_ST 0x8080
+#define PMU2_SCU_PWR_FSM_STATUS(i) (0x8084 + (i) * 4)
+#define PMU2_CORE_PCHANNEL_STATUS(i) (0x808c + (i) * 4)
+#define PMU2_CPU_PWR_CHAIN_STABLE_CON 0x8098
+#define PMU2_CLUSTER_MEMPWR_GATE_SFTCON 0x809c
+#define PMU2_DSU_STABLE_CNT_THRESH 0x80b0
+#define PMU2_DSU_PWRUP_CNT_THRESH 0x80b4
+#define PMU2_DSU_PWRDN_CNT_THRESH 0x80b8
+#define PMU2_CORE0_STABLE_CNT_THRESH 0x80bc
+#define PMU2_CORE0_PWRUP_CNT_THRESH 0x80c0
+#define PMU2_CORE0_PWRDN_CNT_THRESH 0x80c4
+#define PMU2_CORE1_STABLE_CNT_THRESH 0x80c8
+#define PMU2_CORE1_PWRUP_CNT_THRESH 0x80cc
+#define PMU2_CORE1_PWRDN_CNT_THRESH 0x80d0
+#define PMU2_DBG_RST_CNT_THRESH(i) (0x80d4 + (i) * 4)
+#define PMU2_BUS_IDLE_CON(i) (0x8100 + (i) * 4)
+#define PMU2_BUS_IDLE_SFTCON(i) (0x810c + (i) * 4)
+#define PMU2_BUS_IDLE_ACK(i) (0x8118 + (i) * 4)
+#define PMU2_BUS_IDLE_ST(i) (0x8120 + (i) * 4)
+#define PMU2_BIU_AUTO_CON(i) (0x8128 + (i) * 4)
+#define PMU2_PWR_GATE_CON(i) (0x8140 + (i) * 4)
+#define PMU2_PWR_GATE_SFTCON(i) (0x814c + (i) * 4)
+#define PMU2_VOL_GATE_CON(i) (0x8158 + (i) * 4)
+#define PMU2_PWR_UP_CHAIN_STABLE_CON(i) (0x8164 + (i) * 4)
+#define PMU2_PWR_DWN_CHAIN_STABLE_CON(i)(0x8170 + (i) * 4)
+#define PMU2_PWR_STABLE_CHAIN_CNT_THRES 0x817c
+#define PMU2_PWR_GATE_ST(i) (0x8180 + (i) * 4)
+#define PMU2_PWR_GATE_FSM 0x8188
+#define PMU2_VOL_GATE_FAST_CON 0x818c
+#define PMU2_GPU_PWRUP_CNT 0x8190
+#define PMU2_GPU_PWRDN_CNT 0x8194
+#define PMU2_NPU_PWRUP_CNT 0x8198
+#define PMU2_NPU_PWRDN_CNT 0x819c
+#define PMU2_MEMPWR_GATE_SFTCON(i) (0x81a0 + (i) * 4)
+#define PMU2_MEMPWR_MD_GATE_SFTCON(i) (0x81b0 + (i) * 4)
+#define PMU2_MEMPWR_MD_GATE_STATUS 0x81bc
+#define PMU2_SUBMEM_PWR_ACK_BYPASS(i) (0x81c0 + (i) * 4)
+#define PMU2_QCHANNEL_PWR_CON 0x81d0
+#define PMU2_QCHANNEL_PWR_SFTCON 0x81d4
+#define PMU2_QCHANNEL_STATUS 0x81d8
+#define PMU2_DEBUG_INFO_SEL 0x81e0
+#define PMU2_VOP_SUBPD_STATE 0x81e4
+#define PMU2_PWR_CHAIN0_ST(i) (0x81e8 + (i) * 4)
+#define PMU2_PWR_CHAIN1_ST(i) (0x81f0 + (i) * 4)
+#define PMU2_PWR_MEM_ST(i) (0x81f8 + (i) * 4)
+#define PMU2_BISR_CON(i) (0x8200 + (i) * 4)
+#define PMU2_BISR_STATUS(i) (0x8280 + (i) * 4)
+
+#define PMU2_QCH_PWR_MSK 0x7f
+
+#define PD_CTR_LOOP 500
+#define PD_CHECK_LOOP 500
+#define WFEI_CHECK_LOOP 500
+#define BUS_IDLE_LOOP 1000
+#define QCH_PWR_LOOP 5000
+
+/* PMU1SCRU */
+#define PMU1SCRU_GATE_CON(i) (0x800 + (i) * 4)
+
+/* PMU_GRF */
+#define PMU0_GRF_SOC_CON(i) ((i) * 4)
+#define PMU0_GRF_OS_REGS(i) (0x80 + ((i) - 8) * 4)
+#define PMU1_GRF_SOC_CON(i) ((i) * 4)
+#define PMU0_GRF_IO_RET_CON(i) (0x20 + (i) * 4)
+
+/* PMU_SGRF */
+#define PMU0_SGRF_SOC_CON(i) ((i) * 4)
+#define PMU1_SGRF_SOC_CON(i) ((i) * 4)
+
+/* sys grf */
+#define GRF_CPU_STATUS0 0x0420
+
+#define CORES_PM_DISABLE 0x0
+#define PD_CHECK_LOOP 500
+#define WFEI_CHECK_LOOP 500
+
+/* The ways of cores power domain contorlling */
+enum cores_pm_ctr_mode {
+ core_pwr_pd = 0,
+ core_pwr_wfi = 1,
+ core_pwr_wfi_int = 2
+};
+
+/* PMU0_PWR_CON */
+enum pmu0_pwr_con {
+ pmu0_powermode_en = 0,
+ pmu0_pmu1_pwr_bypass = 1,
+ pmu0_pmu1_bus_bypass = 2,
+ pmu0_wkup_bypass = 3,
+ pmu0_pmic_bypass = 4,
+ pmu0_reset_bypass = 5,
+ pmu0_freq_sw_bypass = 6,
+ pmu0_osc_dis_bypass = 7,
+ pmu0_pmu1_pwr_gt_en = 8,
+ pmu0_pmu1_pwr_gt_sft_en = 9,
+ pmu0_pmu1_mem_gt_sft_en = 10,
+ pmu0_pmu1_bus_idle_en = 11,
+ pmu0_pmu1_bus_idle_sft_en = 12,
+ pmu0_pmu1_biu_auto_en = 13,
+ pmu0_pwr_off_io_en = 14,
+};
+
+/* PMU1_PWR_CON */
+enum pmu1_pwr_con {
+ powermode_en = 0,
+ dsu_bypass = 1,
+ bus_bypass = 4,
+ ddr_bypass = 5,
+ pwrdn_bypass = 6,
+ cru_bypass = 7,
+ qch_bypass = 8,
+ core_bypass = 9,
+ cpu_sleep_wfi_dis = 12,
+};
+
+/* PMU1_DDR_PWR_CON */
+enum pmu1_ddr_pwr_con {
+ ddr_sref_en = 0,
+ ddr_sref_a_en = 1,
+ ddrio_ret_en = 2,
+ ddrio_ret_exit_en = 5,
+ ddrio_rstiov_en = 6,
+ ddrio_rstiov_exit_en = 7,
+ ddr_gating_a_en = 8,
+ ddr_gating_c_en = 9,
+ ddr_gating_p_en = 10,
+};
+
+/* PMU_CRU_PWR_CON */
+enum pmu1_cru_pwr_con {
+ alive_32k_en = 0,
+ osc_dis_en = 1,
+ wakeup_rst_en = 2,
+ input_clamp_en = 3,
+ alive_osc_mode_en = 4,
+ power_off_en = 5,
+ pwm_switch_en = 6,
+ pwm_gpio_ioe_en = 7,
+ pwm_switch_io = 8,
+ pd_clk_src_gate_en = 9,
+};
+
+/* PMU_PLLPD_CON */
+enum pmu1_pllpd_con {
+ B0PLL_PD_EN,
+ B1PLL_PD_EN,
+ LPLL_PD_EN,
+ D0APLL_PD_EN,
+ D0BPLL_PD_EN,
+ D1APLL_PD_EN,
+ D1BPLL_PD_EN,
+ D2APLL_PD_EN,
+ D2BPLL_PD_EN,
+ D3APLL_PD_EN,
+ D3BPLL_PD_EN,
+ V0PLL_PD_EN,
+ AUPLL_PD_EN,
+ GPLL_PD_EN,
+ CPLL_PD_EN,
+ NPLL_PD_EN,
+ PPLL_PD_EN = 0,
+ SPLL_PD_EN = 1,
+};
+
+enum pmu1_wakeup_int {
+ WAKEUP_CPU0_INT_EN,
+ WAKEUP_CPU1_INT_EN,
+ WAKEUP_CPU2_INT_EN,
+ WAKEUP_CPU3_INT_EN,
+ WAKEUP_CPU4_INT_EN,
+ WAKEUP_CPU5_INT_EN,
+ WAKEUP_CPU6_INT_EN,
+ WAKEUP_CPU7_INT_EN,
+ WAKEUP_GPIO0_INT_EN,
+ WAKEUP_SDMMC_EN,
+ WAKEUP_SDIO_EN,
+ WAKEUP_USBDEV_EN,
+ WAKEUP_UART0_EN,
+ WAKEUP_VAD_EN,
+ WAKEUP_TIMER_EN,
+ WAKEUP_SOC_INT_EN,
+ WAKEUP_TIMEROUT_EN,
+ WAKEUP_PMUMCU_CEC_EN = 20,
+};
+
+enum pmu2_dsu_auto_pwr_con {
+ dsu_pm_en = 0,
+ dsu_pm_int_wakeup_en = 1,
+ dsu_pm_sft_wakeup_en = 3,
+};
+
+enum pmu2_cpu_auto_pwr_con {
+ cpu_pm_en = 0,
+ cpu_pm_int_wakeup_en = 1,
+ cpu_pm_sft_wakeup_en = 3,
+};
+
+enum pmu2_core_auto_pwr_con {
+ core_pm_en = 0,
+ core_pm_int_wakeup_en = 1,
+ core_pm_int_wakeup_glb_msk = 2,
+ core_pm_sft_wakeup_en = 3,
+};
+
+enum pmu2_dsu_power_con {
+ DSU_PWRDN_EN,
+ DSU_PWROFF_EN,
+ BIT_FULL_EN,
+ DSU_RET_EN,
+ CLUSTER_CLK_SRC_GT_EN,
+};
+
+enum pmu2_core_power_con {
+ CORE_PWRDN_EN,
+ CORE_PWROFF_EN,
+ CORE_CPU_PWRDN_EN,
+ CORE_PWR_CNT_EN,
+};
+
+enum pmu2_cluster_idle_con {
+ IDLE_REQ_BIGCORE0_EN = 0,
+ IDLE_REQ_BIGCORE1_EN = 2,
+ IDLE_REQ_DSU_EN = 4,
+ IDLE_REQ_LITDSU_EN = 5,
+ IDLE_REQ_ADB400_CORE_QCH_EN = 6,
+};
+
+enum qos_id {
+ QOS_ISP0_MWO = 0,
+ QOS_ISP0_MRO = 1,
+ QOS_ISP1_MWO = 2,
+ QOS_ISP1_MRO = 3,
+ QOS_VICAP_M0 = 4,
+ QOS_VICAP_M1 = 5,
+ QOS_FISHEYE0 = 6,
+ QOS_FISHEYE1 = 7,
+ QOS_VOP_M0 = 8,
+ QOS_VOP_M1 = 9,
+ QOS_RKVDEC0 = 10,
+ QOS_RKVDEC1 = 11,
+ QOS_AV1 = 12,
+ QOS_RKVENC0_M0RO = 13,
+ QOS_RKVENC0_M1RO = 14,
+ QOS_RKVENC0_M2WO = 15,
+ QOS_RKVENC1_M0RO = 16,
+ QOS_RKVENC1_M1RO = 17,
+ QOS_RKVENC1_M2WO = 18,
+ QOS_DSU_M0 = 19,
+ QOS_DSU_M1 = 20,
+ QOS_DSU_MP = 21,
+ QOS_DEBUG = 22,
+ QOS_GPU_M0 = 23,
+ QOS_GPU_M1 = 24,
+ QOS_GPU_M2 = 25,
+ QOS_GPU_M3 = 26,
+ QOS_NPU1 = 27,
+ QOS_NPU0_MRO = 28,
+ QOS_NPU2 = 29,
+ QOS_NPU0_MWR = 30,
+ QOS_MCU_NPU = 31,
+ QOS_JPEG_DEC = 32,
+ QOS_JPEG_ENC0 = 33,
+ QOS_JPEG_ENC1 = 34,
+ QOS_JPEG_ENC2 = 35,
+ QOS_JPEG_ENC3 = 36,
+ QOS_RGA2_MRO = 37,
+ QOS_RGA2_MWO = 38,
+ QOS_RGA3_0 = 39,
+ QOS_RGA3_1 = 40,
+ QOS_VDPU = 41,
+ QOS_IEP = 42,
+ QOS_HDCP0 = 43,
+ QOS_HDCP1 = 44,
+ QOS_HDMIRX = 45,
+ QOS_GIC600_M0 = 46,
+ QOS_GIC600_M1 = 47,
+ QOS_MMU600PCIE_TCU = 48,
+ QOS_MMU600PHP_TBU = 49,
+ QOS_MMU600PHP_TCU = 50,
+ QOS_USB3_0 = 51,
+ QOS_USB3_1 = 52,
+ QOS_USBHOST_0 = 53,
+ QOS_USBHOST_1 = 54,
+ QOS_EMMC = 55,
+ QOS_FSPI = 56,
+ QOS_SDIO = 57,
+ QOS_DECOM = 58,
+ QOS_DMAC0 = 59,
+ QOS_DMAC1 = 60,
+ QOS_DMAC2 = 61,
+ QOS_GIC600M = 62,
+ QOS_DMA2DDR = 63,
+ QOS_MCU_DDR = 64,
+ QOS_VAD = 65,
+ QOS_MCU_PMU = 66,
+ QOS_CRYPTOS = 67,
+ QOS_CRYPTONS = 68,
+ QOS_DCF = 69,
+ QOS_SDMMC = 70,
+};
+
+enum pmu2_pdid {
+ PD_GPU = 0,
+ PD_NPU = 1,
+ PD_VCODEC = 2,
+ PD_NPUTOP = 3,
+ PD_NPU1 = 4,
+ PD_NPU2 = 5,
+ PD_VENC0 = 6,
+ PD_VENC1 = 7,
+ PD_RKVDEC0 = 8,
+ PD_RKVDEC1 = 9,
+ PD_VDPU = 10,
+ PD_RGA30 = 11,
+ PD_AV1 = 12,
+ PD_VI = 13,
+ PD_FEC = 14,
+ PD_ISP1 = 15,
+ PD_RGA31 = 16,
+ PD_VOP = 17,
+ PD_VO0 = 18,
+ PD_VO1 = 19,
+ PD_AUDIO = 20,
+ PD_PHP = 21,
+ PD_GMAC = 22,
+ PD_PCIE = 23,
+ PD_NVM = 24,
+ PD_NVM0 = 25,
+ PD_SDIO = 26,
+ PD_USB = 27,
+ PD_SECURE = 28,
+ PD_SDMMC = 29,
+ PD_CRYPTO = 30,
+ PD_CENTER = 31,
+ PD_DDR01 = 32,
+ PD_DDR23 = 33,
+};
+
+enum pmu2_pd_repair_id {
+ PD_RPR_PMU = 0,
+ PD_RPR_GPU = 1,
+ PD_RPR_NPUTOP = 2,
+ PD_RPR_NPU1 = 3,
+ PD_RPR_NPU2 = 4,
+ PD_RPR_VENC0 = 5,
+ PD_RPR_VENC1 = 6,
+ PD_RPR_RKVDEC0 = 7,
+ PD_RPR_RKVDEC1 = 8,
+ PD_RPR_VDPU = 9,
+ PD_RPR_RGA30 = 10,
+ PD_RPR_AV1 = 11,
+ PD_RPR_VI = 12,
+ PD_RPR_FEC = 13,
+ PD_RPR_ISP1 = 14,
+ PD_RPR_RGA31 = 15,
+ PD_RPR_VOP = 16,
+ PD_RPR_VO0 = 17,
+ PD_RPR_VO1 = 18,
+ PD_RPR_AUDIO = 19,
+ PD_RPR_PHP = 20,
+ PD_RPR_GMAC = 21,
+ PD_RPR_PCIE = 22,
+ PD_RPR_NVM0 = 23,
+ PD_RPR_SDIO = 24,
+ PD_RPR_USB = 25,
+ PD_RPR_SDMMC = 26,
+ PD_RPR_CRYPTO = 27,
+ PD_RPR_CENTER = 28,
+ PD_RPR_DDR01 = 29,
+ PD_RPR_DDR23 = 30,
+ PD_RPR_BUS = 31,
+};
+
+enum pmu2_bus_id {
+ BUS_ID_GPU = 0,
+ BUS_ID_NPUTOP = 1,
+ BUS_ID_NPU1 = 2,
+ BUS_ID_NPU2 = 3,
+ BUS_ID_RKVENC0 = 4,
+ BUS_ID_RKVENC1 = 5,
+ BUS_ID_RKVDEC0 = 6,
+ BUS_ID_RKVDEC1 = 7,
+ BUS_ID_VDPU = 8,
+ BUS_ID_AV1 = 9,
+ BUS_ID_VI = 10,
+ BUS_ID_ISP = 11,
+ BUS_ID_RGA31 = 12,
+ BUS_ID_VOP = 13,
+ BUS_ID_VOP_CHANNEL = 14,
+ BUS_ID_VO0 = 15,
+ BUS_ID_VO1 = 16,
+ BUS_ID_AUDIO = 17,
+ BUS_ID_NVM = 18,
+ BUS_ID_SDIO = 19,
+ BUS_ID_USB = 20,
+ BUS_ID_PHP = 21,
+ BUS_ID_VO1USBTOP = 22,
+ BUS_ID_SECURE = 23,
+ BUS_ID_SECURE_CENTER_CHANNEL = 24,
+ BUS_ID_SECURE_VO1USB_CHANNEL = 25,
+ BUS_ID_CENTER = 26,
+ BUS_ID_CENTER_CHANNEL = 27,
+ BUS_ID_MSCH0 = 28,
+ BUS_ID_MSCH1 = 29,
+ BUS_ID_MSCH2 = 30,
+ BUS_ID_MSCH3 = 31,
+ BUS_ID_MSCH = 32,
+ BUS_ID_BUS = 33,
+ BUS_ID_TOP = 34,
+};
+
+enum pmu2_mem_st {
+ PD_NPU_TOP_MEM_ST = 11,
+ PD_NPU1_MEM_ST = 12,
+ PD_NPU2_MEM_ST = 13,
+ PD_VENC0_MEM_ST = 14,
+ PD_VENC1_MEM_ST = 15,
+ PD_RKVDEC0_MEM_ST = 16,
+ PD_RKVDEC1_MEM_ST = 17,
+ PD_RGA30_MEM_ST = 19,
+ PD_AV1_MEM_ST = 20,
+ PD_VI_MEM_ST = 21,
+ PD_FEC_MEM_ST = 22,
+ PD_ISP1_MEM_ST = 23,
+ PD_RGA31_MEM_ST = 24,
+ PD_VOP_MEM_ST = 25,
+ PD_VO0_MEM_ST = 26,
+ PD_VO1_MEM_ST = 27,
+ PD_AUDIO_MEM_ST = 28,
+ PD_PHP_MEM_ST = 29,
+ PD_GMAC_MEM_ST = 30,
+ PD_PCIE_MEM_ST = 31,
+ PD_NVM0_MEM_ST = 33,
+ PD_SDIO_MEM_ST = 34,
+ PD_USB_MEM_ST = 35,
+ PD_SDMMC_MEM_ST = 37,
+};
+
+enum pmu2_qid {
+ QID_PHPMMU_TBU = 0,
+ QID_PHPMMU_TCU = 1,
+ QID_PCIEMMU_TBU0 = 2,
+ QID_PCIEMU_TCU = 3,
+ QID_PHP_GICITS = 4,
+ QID_BUS_GICITS0 = 5,
+ QID_BUS_GICITS1 = 6,
+};
+
+/* PMU_DSU_PWR_CON */
+enum pmu_dsu_pwr_con {
+ DSU_PWRDN_ENA = 2,
+ DSU_PWROFF_ENA,
+ DSU_RET_ENA = 6,
+ CLUSTER_CLK_SRC_GATE_ENA,
+ DSU_PWR_CON_END
+};
+
+enum cpu_power_state {
+ CPU_POWER_ON,
+ CPU_POWER_OFF,
+ CPU_EMULATION_OFF,
+ CPU_RETENTION,
+ CPU_DEBUG
+};
+
+enum dsu_power_state {
+ DSU_POWER_ON,
+ CLUSTER_TRANSFER_IDLE,
+ DSU_POWER_DOWN,
+ DSU_OFF,
+ DSU_WAKEUP,
+ DSU_POWER_UP,
+ CLUSTER_TRANSFER_RESUME,
+ DSU_FUNCTION_RETENTION
+};
+
+/* PMU2_CLUSTER_STS 0x8080 */
+enum pmu2_cluster_sts_bits {
+ pd_cpu0_dwn = 0,
+ pd_cpu1_dwn,
+ pd_cpu2_dwn,
+ pd_cpu3_dwn,
+ pd_cpu4_dwn,
+ pd_cpu5_dwn,
+ pd_cpu6_dwn,
+ pd_cpu7_dwn,
+ pd_core0_dwn,
+ pd_core1_dwn
+};
+
+#define CLUSTER_STS_NONBOOT_CPUS_DWN 0xfe
+
+enum cpu_off_trigger {
+ CPU_OFF_TRIGGER_WFE = 0,
+ CPU_OFF_TRIGGER_REQ_EML,
+ CPU_OFF_TRIGGER_REQ_WFI,
+ CPU_OFF_TRIGGER_REQ_WFI_NBT_CPU,
+ CPU_OFF_TRIGGER_REQ_WFI_NBT_CPU_SRAM
+};
+
+/*****************************************************************************
+ * power domain on or off
+ *****************************************************************************/
+enum pmu_pd_state {
+ pmu_pd_on = 0,
+ pmu_pd_off = 1
+};
+
+enum bus_state {
+ bus_active,
+ bus_idle,
+};
+
+#define RK_CPU_STATUS_OFF 0
+#define RK_CPU_STATUS_ON 1
+#define RK_CPU_STATUS_BUSY -1
+
+#define PD_CTR_LOOP 500
+#define MAX_WAIT_COUNT 500
+
+#define pmu_bus_idle_st(id) \
+ (!!(mmio_read_32(PMU_BASE + PMU2_BUS_IDLE_ST((id) / 32)) & BIT((id) % 32)))
+
+#define pmu_bus_idle_ack(id) \
+ (!!(mmio_read_32(PMU_BASE + PMU2_BUS_IDLE_ACK((id) / 32)) & BIT((id) % 32)))
+
+void pm_pll_wait_lock(uint32_t pll_base);
+#endif /* __PMU_H__ */
diff --git a/plat/rockchip/rk3588/drivers/scmi/rk3588_clk.c b/plat/rockchip/rk3588/drivers/scmi/rk3588_clk.c
new file mode 100644
index 0000000..ab3af5f
--- /dev/null
+++ b/plat/rockchip/rk3588/drivers/scmi/rk3588_clk.c
@@ -0,0 +1,2463 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <drivers/delay_timer.h>
+#include <drivers/scmi.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#include <plat_private.h>
+#include "rk3588_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 RK3588_CPUL_PVTPLL_CON0_L 0x40
+#define RK3588_CPUL_PVTPLL_CON0_H 0x44
+#define RK3588_CPUL_PVTPLL_CON1 0x48
+#define RK3588_CPUL_PVTPLL_CON2 0x4c
+#define RK3588_CPUB_PVTPLL_CON0_L 0x00
+#define RK3588_CPUB_PVTPLL_CON0_H 0x04
+#define RK3588_CPUB_PVTPLL_CON1 0x08
+#define RK3588_CPUB_PVTPLL_CON2 0x0c
+#define RK3588_DSU_PVTPLL_CON0_L 0x60
+#define RK3588_DSU_PVTPLL_CON0_H 0x64
+#define RK3588_DSU_PVTPLL_CON1 0x70
+#define RK3588_DSU_PVTPLL_CON2 0x74
+#define RK3588_GPU_PVTPLL_CON0_L 0x00
+#define RK3588_GPU_PVTPLL_CON0_H 0x04
+#define RK3588_GPU_PVTPLL_CON1 0x08
+#define RK3588_GPU_PVTPLL_CON2 0x0c
+#define RK3588_NPU_PVTPLL_CON0_L 0x0c
+#define RK3588_NPU_PVTPLL_CON0_H 0x10
+#define RK3588_NPU_PVTPLL_CON1 0x14
+#define RK3588_NPU_PVTPLL_CON2 0x18
+#define RK3588_PVTPLL_MAX_LENGTH 0x3f
+
+#define GPLL_RATE 1188000000
+#define CPLL_RATE 1500000000
+#define SPLL_RATE 702000000
+#define AUPLL_RATE 786431952
+#define NPLL_RATE 850000000
+
+#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)
+
+/* core_i: from gpll or apll */
+#define CLK_CORE_I_SEL_APLL WMSK_BIT(6)
+#define CLK_CORE_I_SEL_GPLL BIT_WITH_WMSK(6)
+
+/* clk_core:
+ * from normal pll(core_i: gpll or apll) path or direct pass from apll
+ */
+
+/* cpul clk path */
+#define CPUL_CLK_PATH_NOR_XIN BITS_WITH_WMASK(0U, 0x3U, 14)
+#define CPUL_CLK_PATH_NOR_GPLL BITS_WITH_WMASK(1U, 0x3U, 14)
+#define CPUL_CLK_PATH_NOR_LPLL BITS_WITH_WMASK(2U, 0x3U, 14)
+
+#define CPUL_CLK_PATH_LPLL (BITS_WITH_WMASK(0U, 0x3U, 5) | \
+ BITS_WITH_WMASK(0U, 0x3U, 12))
+#define CPUL_CLK_PATH_DIR_LPLL (BITS_WITH_WMASK(0x1, 0x3U, 5) | \
+ BITS_WITH_WMASK(1U, 0x3U, 12))
+#define CPUL_CLK_PATH_PVTPLL (BITS_WITH_WMASK(0x2, 0x3U, 5) | \
+ BITS_WITH_WMASK(2U, 0x3U, 12))
+
+#define CPUL_PVTPLL_PATH_DEEP_SLOW BITS_WITH_WMASK(0U, 0x1U, 14)
+#define CPUL_PVTPLL_PATH_PVTPLL BITS_WITH_WMASK(1U, 0x1U, 14)
+
+/* cpub01 clk path */
+#define CPUB01_CLK_PATH_NOR_XIN BITS_WITH_WMASK(0U, 0x3U, 6)
+#define CPUB01_CLK_PATH_NOR_GPLL BITS_WITH_WMASK(1U, 0x3U, 6)
+#define CPUB01_CLK_PATH_NOR_B0PLL BITS_WITH_WMASK(2U, 0x3U, 6)
+
+#define CPUB01_CLK_PATH_B0PLL BITS_WITH_WMASK(0U, 0x3U, 13)
+#define CPUB01_CLK_PATH_DIR_B0PLL BITS_WITH_WMASK(1U, 0x3U, 13)
+#define CPUB01_CLK_PATH_B0_PVTPLL BITS_WITH_WMASK(2U, 0x3U, 13)
+
+#define CPUB01_CLK_PATH_B1PLL BITS_WITH_WMASK(0U, 0x3U, 5)
+#define CPUB01_CLK_PATH_DIR_B1PLL BITS_WITH_WMASK(1U, 0x3U, 5)
+#define CPUB01_CLK_PATH_B1_PVTPLL BITS_WITH_WMASK(2U, 0x3U, 5)
+
+#define CPUB01_PVTPLL_PATH_DEEP_SLOW BITS_WITH_WMASK(0U, 0x1U, 2)
+#define CPUB01_PVTPLL_PATH_PVTPLL BITS_WITH_WMASK(1U, 0x1U, 2)
+
+#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)
+
+/* dsu clk path */
+#define SCLK_DSU_PATH_NOR_B0PLL BITS_WITH_WMASK(0U, 0x3U, 12)
+#define SCLK_DSU_PATH_NOR_B1PLL BITS_WITH_WMASK(1U, 0x3U, 12)
+#define SCLK_DSU_PATH_NOR_LPLL BITS_WITH_WMASK(2U, 0x3U, 12)
+#define SCLK_DSU_PATH_NOR_GPLL BITS_WITH_WMASK(3U, 0x3U, 12)
+
+#define DSU_PVTPLL_PATH_DEEP_SLOW BITS_WITH_WMASK(0U, 0x1U, 15)
+#define DSU_PVTPLL_PATH_PVTPLL BITS_WITH_WMASK(1U, 0x1U, 15)
+
+#define SCLK_DSU_PATH_NOR_PLL WMSK_BIT(0)
+#define SCLK_DSU_PATH_PVTPLL BIT_WITH_WMSK(0)
+
+/* 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_NPLL BITS_WITH_WMASK(3U, 0x7U, 7)
+#define NPU_CLK_PATH_NOR_SPLL BITS_WITH_WMASK(4U, 0x7U, 7)
+
+#define NPU_CLK_PATH_NOR_PLL WMSK_BIT(0)
+#define NPU_CLK_PATH_PVTPLL BIT_WITH_WMSK(0)
+
+/* 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_NPLL BITS_WITH_WMASK(3U, 0x7U, 5)
+#define GPU_CLK_PATH_NOR_SPLL BITS_WITH_WMASK(4U, 0x7U, 5)
+#define GPU_CLK_PATH_NOR_PLL WMSK_BIT(14)
+#define GPU_CLK_PATH_PVTPLL BIT_WITH_WMSK(14)
+
+#define PVTPLL_NEED(type, length) (((type) == PLL_SEL_PVT || \
+ (type) == PLL_SEL_AUTO) && \
+ (length))
+
+struct pvtpll_table {
+ unsigned int rate;
+ uint32_t length;
+ uint32_t ring_sel;
+};
+
+struct sys_clk_info_t {
+ struct pvtpll_table *cpul_table;
+ struct pvtpll_table *cpub01_table;
+ struct pvtpll_table *cpub23_table;
+ struct pvtpll_table *gpu_table;
+ struct pvtpll_table *npu_table;
+ unsigned int cpul_rate_count;
+ unsigned int cpub01_rate_count;
+ unsigned int cpub23_rate_count;
+ unsigned int gpu_rate_count;
+ unsigned int npu_rate_count;
+ unsigned long cpul_rate;
+ unsigned long dsu_rate;
+ unsigned long cpub01_rate;
+ unsigned long cpub23_rate;
+ unsigned long gpu_rate;
+ unsigned long npu_rate;
+};
+
+#define RK3588_SCMI_CLOCK(_id, _name, _data, _table, _cnt, _is_s) \
+{ \
+ .id = _id, \
+ .name = _name, \
+ .clk_ops = _data, \
+ .rate_table = _table, \
+ .rate_cnt = _cnt, \
+ .is_security = _is_s, \
+}
+
+#define ROCKCHIP_PVTPLL(_rate, _sel, _len) \
+{ \
+ .rate = _rate##U, \
+ .ring_sel = _sel, \
+ .length = _len, \
+}
+
+static struct pvtpll_table rk3588_cpul_pvtpll_table[] = {
+ /* rate_hz, ring_sel, length */
+ ROCKCHIP_PVTPLL(1800000000, 1, 15),
+ ROCKCHIP_PVTPLL(1704000000, 1, 15),
+ ROCKCHIP_PVTPLL(1608000000, 1, 15),
+ ROCKCHIP_PVTPLL(1416000000, 1, 15),
+ ROCKCHIP_PVTPLL(1200000000, 1, 17),
+ ROCKCHIP_PVTPLL(1008000000, 1, 22),
+ ROCKCHIP_PVTPLL(816000000, 1, 32),
+ ROCKCHIP_PVTPLL(600000000, 0, 0),
+ ROCKCHIP_PVTPLL(408000000, 0, 0),
+ { /* sentinel */ },
+};
+
+static struct pvtpll_table rk3588_cpub0_pvtpll_table[] = {
+ /* rate_hz, ring_sel, length */
+ ROCKCHIP_PVTPLL(2400000000, 1, 11),
+ ROCKCHIP_PVTPLL(2352000000, 1, 11),
+ ROCKCHIP_PVTPLL(2304000000, 1, 11),
+ ROCKCHIP_PVTPLL(2256000000, 1, 11),
+ ROCKCHIP_PVTPLL(2208000000, 1, 11),
+ ROCKCHIP_PVTPLL(2112000000, 1, 11),
+ ROCKCHIP_PVTPLL(2016000000, 1, 11),
+ ROCKCHIP_PVTPLL(1800000000, 1, 11),
+ ROCKCHIP_PVTPLL(1608000000, 1, 11),
+ ROCKCHIP_PVTPLL(1416000000, 1, 13),
+ ROCKCHIP_PVTPLL(1200000000, 1, 17),
+ ROCKCHIP_PVTPLL(1008000000, 1, 23),
+ ROCKCHIP_PVTPLL(816000000, 1, 33),
+ ROCKCHIP_PVTPLL(600000000, 0, 0),
+ ROCKCHIP_PVTPLL(408000000, 0, 0),
+ { /* sentinel */ },
+};
+
+static struct
+pvtpll_table rk3588_cpub1_pvtpll_table[ARRAY_SIZE(rk3588_cpub0_pvtpll_table)] = { 0 };
+
+static struct pvtpll_table rk3588_gpu_pvtpll_table[] = {
+ /* rate_hz, ring_sel, length */
+ ROCKCHIP_PVTPLL(1000000000, 1, 12),
+ ROCKCHIP_PVTPLL(900000000, 1, 12),
+ ROCKCHIP_PVTPLL(800000000, 1, 12),
+ ROCKCHIP_PVTPLL(700000000, 1, 13),
+ ROCKCHIP_PVTPLL(600000000, 1, 17),
+ ROCKCHIP_PVTPLL(500000000, 1, 25),
+ ROCKCHIP_PVTPLL(400000000, 1, 38),
+ ROCKCHIP_PVTPLL(300000000, 1, 55),
+ ROCKCHIP_PVTPLL(200000000, 0, 0),
+ { /* sentinel */ },
+};
+
+static struct pvtpll_table rk3588_npu_pvtpll_table[] = {
+ /* rate_hz, ring_sel, length */
+ ROCKCHIP_PVTPLL(1000000000, 1, 12),
+ ROCKCHIP_PVTPLL(900000000, 1, 12),
+ ROCKCHIP_PVTPLL(800000000, 1, 12),
+ ROCKCHIP_PVTPLL(700000000, 1, 13),
+ ROCKCHIP_PVTPLL(600000000, 1, 17),
+ ROCKCHIP_PVTPLL(500000000, 1, 25),
+ ROCKCHIP_PVTPLL(400000000, 1, 38),
+ ROCKCHIP_PVTPLL(300000000, 1, 55),
+ ROCKCHIP_PVTPLL(200000000, 0, 0),
+ { /* sentinel */ },
+};
+
+static unsigned long rk3588_cpul_rates[] = {
+ 408000000, 600000000, 816000000, 1008000000,
+ 1200000000, 1416000000, 1608000000, 1800000063,
+};
+
+static unsigned long rk3588_cpub_rates[] = {
+ 408000000, 816000000, 1008000000, 1200000000,
+ 1416000000, 1608000000, 1800000000, 2016000000,
+ 2208000000, 2304000000, 2400000063
+};
+
+static unsigned long rk3588_gpu_rates[] = {
+ 200000000, 300000000, 400000000, 500000000,
+ 600000000, 700000000, 800000000, 900000000,
+ 1000000063
+};
+
+static unsigned long rk3588_sbus_rates[] = {
+ 24000000, 50000000, 100000000, 150000000, 200000000,
+ 250000000, 350000000, 700000000
+};
+
+static unsigned long rk3588_sdmmc_rates[] = {
+ 400000, 24000000, 50000000, 100000000, 150000000, 200000000,
+ 300000000, 400000000, 600000000, 700000000
+};
+
+static struct sys_clk_info_t sys_clk_info;
+static int clk_scmi_dsu_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_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;
+
+ /* set lpll */
+ if (PVTPLL_NEED(type, pvtpll->length) != 0) {
+ /* set clock gating interval */
+ mmio_write_32(LITCOREGRF_BASE + RK3588_CPUL_PVTPLL_CON2,
+ 0x00040000);
+ /* set ring sel */
+ mmio_write_32(LITCOREGRF_BASE + RK3588_CPUL_PVTPLL_CON0_L,
+ 0x07000000 | (pvtpll->ring_sel << 8));
+ /* set length */
+ mmio_write_32(LITCOREGRF_BASE + RK3588_CPUL_PVTPLL_CON0_H,
+ 0x003f0000 | pvtpll->length);
+ /* set cal cnt = 24, T = 1us */
+ mmio_write_32(LITCOREGRF_BASE + RK3588_CPUL_PVTPLL_CON1,
+ 0x18);
+ /* enable pvtpll */
+ mmio_write_32(LITCOREGRF_BASE + RK3588_CPUL_PVTPLL_CON0_L,
+ 0x00020002);
+ /* start monitor */
+ mmio_write_32(LITCOREGRF_BASE + RK3588_CPUL_PVTPLL_CON0_L,
+ 0x00010001);
+ /* set corel mux pvtpll */
+ mmio_write_32(DSUCRU_BASE + CRU_CLKSEL_CON(7),
+ CPUL_PVTPLL_PATH_PVTPLL);
+ mmio_write_32(DSUCRU_BASE + CRU_CLKSEL_CON(6),
+ CPUL_CLK_PATH_PVTPLL);
+ mmio_write_32(DSUCRU_BASE + CRU_CLKSEL_CON(7),
+ CPUL_CLK_PATH_PVTPLL);
+ return 0;
+ }
+
+ /* set clk corel div */
+ div = DIV_ROUND_UP(GPLL_RATE, rate) - 1;
+ mmio_write_32(DSUCRU_BASE + CRU_CLKSEL_CON(6),
+ CLKDIV_5BITS_SHF(div, 0) | CLKDIV_5BITS_SHF(div, 7));
+ mmio_write_32(DSUCRU_BASE + CRU_CLKSEL_CON(7),
+ CLKDIV_5BITS_SHF(div, 0) | CLKDIV_5BITS_SHF(div, 7));
+ /* set corel mux gpll */
+ mmio_write_32(DSUCRU_BASE + CRU_CLKSEL_CON(5),
+ CPUL_CLK_PATH_NOR_GPLL);
+ mmio_write_32(DSUCRU_BASE + CRU_CLKSEL_CON(6),
+ CPUL_CLK_PATH_LPLL);
+ mmio_write_32(DSUCRU_BASE + CRU_CLKSEL_CON(7),
+ 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_dsu_set_rate(clock, rate);
+ }
+
+ return ret;
+}
+
+static unsigned long rk3588_lpll_get_rate(void)
+{
+ unsigned int m, p, s, k;
+ uint64_t rate64 = 24000000, postdiv;
+ int mode;
+
+ mode = (mmio_read_32(DSUCRU_BASE + CRU_CLKSEL_CON(5)) >> 14) &
+ 0x3;
+
+ if (mode == 0)
+ return rate64;
+
+ m = (mmio_read_32(DSUCRU_BASE + CRU_PLL_CON(16)) >>
+ CRU_PLLCON0_M_SHIFT) &
+ CRU_PLLCON0_M_MASK;
+ p = (mmio_read_32(DSUCRU_BASE + CRU_PLL_CON(17)) >>
+ CRU_PLLCON1_P_SHIFT) &
+ CRU_PLLCON1_P_MASK;
+ s = (mmio_read_32(DSUCRU_BASE + CRU_PLL_CON(17)) >>
+ CRU_PLLCON1_S_SHIFT) &
+ CRU_PLLCON1_S_MASK;
+ k = (mmio_read_32(DSUCRU_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 * 65535;
+ 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(DSUCRU_BASE + CRU_CLKSEL_CON(6)) & 0x0060;
+ src = src >> 5;
+ if (src == 2) {
+ return sys_clk_info.cpul_rate;
+ } else {
+ src = mmio_read_32(DSUCRU_BASE + CRU_CLKSEL_CON(5)) & 0xc000;
+ src = src >> 14;
+ div = mmio_read_32(DSUCRU_BASE + CRU_CLKSEL_CON(6)) & 0x1f;
+ switch (src) {
+ case 0:
+ return 24000000;
+ case 1:
+ /* Make the return rate is equal to the set rate */
+ if (sys_clk_info.cpul_rate)
+ return sys_clk_info.cpul_rate;
+ else
+ return GPLL_RATE / (div + 1);
+ case 2:
+ return rk3588_lpll_get_rate();
+ default:
+ return 0;
+ }
+ }
+}
+
+static int clk_scmi_cpul_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ return 0;
+}
+
+static void clk_scmi_b0pll_disable(void)
+{
+ static bool is_b0pll_disabled;
+
+ if (is_b0pll_disabled != 0)
+ return;
+
+ /* set coreb01 mux gpll */
+ mmio_write_32(BIGCORE0CRU_BASE + CRU_CLKSEL_CON(0),
+ CPUB01_CLK_PATH_NOR_GPLL);
+ /* pll enter slow mode */
+ mmio_write_32(BIGCORE0CRU_BASE + CRU_MODE_CON0, CPU_PLL_PATH_SLOWMODE);
+ /* set pll power down */
+ mmio_write_32(BIGCORE0CRU_BASE + CRU_PLL_CON(1), CRU_PLL_POWER_DOWN);
+
+ is_b0pll_disabled = true;
+}
+
+static int clk_cpub01_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.cpub01_table,
+ sys_clk_info.cpub01_rate_count, rate);
+ if (pvtpll == NULL)
+ return SCMI_INVALID_PARAMETERS;
+
+ /* set b0pll */
+ if (PVTPLL_NEED(type, pvtpll->length)) {
+ /* set clock gating interval */
+ mmio_write_32(BIGCORE0GRF_BASE + RK3588_CPUB_PVTPLL_CON2,
+ 0x00040000);
+ /* set ring sel */
+ mmio_write_32(BIGCORE0GRF_BASE + RK3588_CPUB_PVTPLL_CON0_L,
+ 0x07000000 | (pvtpll->ring_sel << 8));
+ /* set length */
+ mmio_write_32(BIGCORE0GRF_BASE + RK3588_CPUB_PVTPLL_CON0_H,
+ 0x003f0000 | pvtpll->length);
+ /* set cal cnt = 24, T = 1us */
+ mmio_write_32(BIGCORE0GRF_BASE + RK3588_CPUB_PVTPLL_CON1,
+ 0x18);
+ /* enable pvtpll */
+ mmio_write_32(BIGCORE0GRF_BASE + RK3588_CPUB_PVTPLL_CON0_L,
+ 0x00020002);
+ /* start monitor */
+ mmio_write_32(BIGCORE0GRF_BASE + RK3588_CPUB_PVTPLL_CON0_L,
+ 0x00010001);
+ /* set core mux pvtpll */
+ mmio_write_32(BIGCORE0CRU_BASE + CRU_CLKSEL_CON(2),
+ CPUB01_PVTPLL_PATH_PVTPLL);
+ mmio_write_32(BIGCORE0CRU_BASE + CRU_CLKSEL_CON(0),
+ CPUB01_CLK_PATH_B0_PVTPLL);
+ mmio_write_32(BIGCORE0CRU_BASE + CRU_CLKSEL_CON(1),
+ CPUB01_CLK_PATH_B1_PVTPLL);
+ goto out;
+ }
+
+ /* set clk coreb01 div */
+ div = DIV_ROUND_UP(GPLL_RATE, rate) - 1;
+ mmio_write_32(BIGCORE0CRU_BASE + CRU_CLKSEL_CON(0),
+ CLKDIV_5BITS_SHF(div, 8));
+ mmio_write_32(BIGCORE0CRU_BASE + CRU_CLKSEL_CON(1),
+ CLKDIV_5BITS_SHF(div, 0));
+ /* set coreb01 mux gpll */
+ mmio_write_32(BIGCORE0CRU_BASE + CRU_CLKSEL_CON(0),
+ CPUB01_CLK_PATH_NOR_GPLL);
+ mmio_write_32(BIGCORE0CRU_BASE + CRU_CLKSEL_CON(0),
+ CPUB01_CLK_PATH_B0PLL);
+ mmio_write_32(BIGCORE0CRU_BASE + CRU_CLKSEL_CON(1),
+ CPUB01_CLK_PATH_B1PLL);
+
+out:
+ clk_scmi_b0pll_disable();
+
+ return 0;
+}
+
+static int clk_scmi_cpub01_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ int ret;
+
+ if (rate == 0)
+ return SCMI_INVALID_PARAMETERS;
+
+ ret = clk_cpub01_set_rate(rate, PLL_SEL_AUTO);
+ if (ret == 0)
+ sys_clk_info.cpub01_rate = rate;
+
+ return ret;
+}
+
+static unsigned long rk3588_b0pll_get_rate(void)
+{
+ unsigned int m, p, s, k;
+ uint64_t rate64 = 24000000, postdiv;
+ int mode;
+
+ mode = (mmio_read_32(BIGCORE0CRU_BASE + CRU_CLKSEL_CON(0)) >> 6) &
+ 0x3;
+
+ if (mode == 0)
+ return rate64;
+
+ m = (mmio_read_32(BIGCORE0CRU_BASE + CRU_PLL_CON(0)) >>
+ CRU_PLLCON0_M_SHIFT) &
+ CRU_PLLCON0_M_MASK;
+ p = (mmio_read_32(BIGCORE0CRU_BASE + CRU_PLL_CON(1)) >>
+ CRU_PLLCON1_P_SHIFT) &
+ CRU_PLLCON1_P_MASK;
+ s = (mmio_read_32(BIGCORE0CRU_BASE + CRU_PLL_CON(1)) >>
+ CRU_PLLCON1_S_SHIFT) &
+ CRU_PLLCON1_S_MASK;
+ k = (mmio_read_32(BIGCORE0CRU_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 * 65535;
+ frac_rate64 = frac_rate64 / postdiv;
+ rate64 += frac_rate64;
+ }
+ rate64 = rate64 >> s;
+
+ return (unsigned long)rate64;
+}
+
+static unsigned long clk_scmi_cpub01_get_rate(rk_scmi_clock_t *clock)
+{
+ int value, src, div;
+
+ value = mmio_read_32(BIGCORE0CRU_BASE + CRU_CLKSEL_CON(0));
+ src = (value & 0x6000) >> 13;
+ if (src == 2) {
+ return sys_clk_info.cpub01_rate;
+ } else {
+ src = (value & 0x00c0) >> 6;
+ div = (value & 0x1f00) >> 8;
+ switch (src) {
+ case 0:
+ return 24000000;
+ case 1:
+ /* Make the return rate is equal to the set rate */
+ if (sys_clk_info.cpub01_rate)
+ return sys_clk_info.cpub01_rate;
+ else
+ return GPLL_RATE / (div + 1);
+ case 2:
+ return rk3588_b0pll_get_rate();
+ default:
+ return 0;
+ }
+ }
+}
+
+static int clk_scmi_cpub01_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ return 0;
+}
+
+static void clk_scmi_b1pll_disable(void)
+{
+ static bool is_b1pll_disabled;
+
+ if (is_b1pll_disabled != 0)
+ return;
+
+ /* set coreb23 mux gpll */
+ mmio_write_32(BIGCORE1CRU_BASE + CRU_CLKSEL_CON(0),
+ CPUB01_CLK_PATH_NOR_GPLL);
+ /* pll enter slow mode */
+ mmio_write_32(BIGCORE1CRU_BASE + CRU_MODE_CON0, CPU_PLL_PATH_SLOWMODE);
+ /* set pll power down */
+ mmio_write_32(BIGCORE1CRU_BASE + CRU_PLL_CON(9), CRU_PLL_POWER_DOWN);
+
+ is_b1pll_disabled = true;
+}
+
+static int clk_cpub23_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.cpub23_table,
+ sys_clk_info.cpub23_rate_count, rate);
+ if (pvtpll == NULL)
+ return SCMI_INVALID_PARAMETERS;
+
+ /* set b1pll */
+ if (PVTPLL_NEED(type, pvtpll->length)) {
+ /* set clock gating interval */
+ mmio_write_32(BIGCORE1GRF_BASE + RK3588_CPUB_PVTPLL_CON2,
+ 0x00040000);
+ /* set ring sel */
+ mmio_write_32(BIGCORE1GRF_BASE + RK3588_CPUB_PVTPLL_CON0_L,
+ 0x07000000 | (pvtpll->ring_sel << 8));
+ /* set length */
+ mmio_write_32(BIGCORE1GRF_BASE + RK3588_CPUB_PVTPLL_CON0_H,
+ 0x003f0000 | pvtpll->length);
+ /* set cal cnt = 24, T = 1us */
+ mmio_write_32(BIGCORE1GRF_BASE + RK3588_CPUB_PVTPLL_CON1,
+ 0x18);
+ /* enable pvtpll */
+ mmio_write_32(BIGCORE1GRF_BASE + RK3588_CPUB_PVTPLL_CON0_L,
+ 0x00020002);
+ /* start monitor */
+ mmio_write_32(BIGCORE1GRF_BASE + RK3588_CPUB_PVTPLL_CON0_L,
+ 0x00010001);
+ /* set core mux pvtpll */
+ mmio_write_32(BIGCORE1CRU_BASE + CRU_CLKSEL_CON(2),
+ CPUB01_PVTPLL_PATH_PVTPLL);
+ mmio_write_32(BIGCORE1CRU_BASE + CRU_CLKSEL_CON(0),
+ CPUB01_CLK_PATH_B0_PVTPLL);
+ mmio_write_32(BIGCORE1CRU_BASE + CRU_CLKSEL_CON(1),
+ CPUB01_CLK_PATH_B1_PVTPLL);
+ goto out;
+ }
+
+ /* set clk coreb23 div */
+ div = DIV_ROUND_UP(GPLL_RATE, rate) - 1;
+ mmio_write_32(BIGCORE1CRU_BASE + CRU_CLKSEL_CON(0),
+ CLKDIV_5BITS_SHF(div, 8));
+ mmio_write_32(BIGCORE1CRU_BASE + CRU_CLKSEL_CON(1),
+ CLKDIV_5BITS_SHF(div, 0));
+ /* set coreb23 mux gpll */
+ mmio_write_32(BIGCORE1CRU_BASE + CRU_CLKSEL_CON(0),
+ CPUB01_CLK_PATH_NOR_GPLL);
+ mmio_write_32(BIGCORE1CRU_BASE + CRU_CLKSEL_CON(0),
+ CPUB01_CLK_PATH_B0PLL);
+ mmio_write_32(BIGCORE1CRU_BASE + CRU_CLKSEL_CON(1),
+ CPUB01_CLK_PATH_B1PLL);
+
+out:
+ clk_scmi_b1pll_disable();
+
+ return 0;
+}
+
+static int clk_scmi_cpub23_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ int ret;
+
+ if (rate == 0)
+ return SCMI_INVALID_PARAMETERS;
+
+ ret = clk_cpub23_set_rate(rate, PLL_SEL_AUTO);
+ if (ret == 0)
+ sys_clk_info.cpub23_rate = rate;
+
+ return ret;
+}
+
+static unsigned long rk3588_b1pll_get_rate(void)
+{
+ unsigned int m, p, s, k;
+ uint64_t rate64 = 24000000, postdiv;
+ int mode;
+
+ mode = (mmio_read_32(BIGCORE1CRU_BASE + CRU_CLKSEL_CON(0)) >> 6) &
+ 0x3;
+
+ if (mode == 0)
+ return rate64;
+
+ m = (mmio_read_32(BIGCORE1CRU_BASE + CRU_PLL_CON(8)) >>
+ CRU_PLLCON0_M_SHIFT) &
+ CRU_PLLCON0_M_MASK;
+ p = (mmio_read_32(BIGCORE1CRU_BASE + CRU_PLL_CON(9)) >>
+ CRU_PLLCON1_P_SHIFT) &
+ CRU_PLLCON1_P_MASK;
+ s = (mmio_read_32(BIGCORE1CRU_BASE + CRU_PLL_CON(9)) >>
+ CRU_PLLCON1_S_SHIFT) &
+ CRU_PLLCON1_S_MASK;
+ k = (mmio_read_32(BIGCORE1CRU_BASE + CRU_PLL_CON(10)) >>
+ 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 * 65535;
+ frac_rate64 = frac_rate64 / postdiv;
+ rate64 += frac_rate64;
+ }
+ rate64 = rate64 >> s;
+
+ return (unsigned long)rate64;
+}
+
+static unsigned long clk_scmi_cpub23_get_rate(rk_scmi_clock_t *clock)
+{
+ int value, src, div;
+
+ value = mmio_read_32(BIGCORE1CRU_BASE + CRU_CLKSEL_CON(0));
+ src = (value & 0x6000) >> 13;
+ if (src == 2) {
+ return sys_clk_info.cpub23_rate;
+ } else {
+ src = (value & 0x00c0) >> 6;
+ div = (value & 0x1f00) >> 8;
+ switch (src) {
+ case 0:
+ return 24000000;
+ case 1:
+ /* Make the return rate is equal to the set rate */
+ if (sys_clk_info.cpub23_rate)
+ return sys_clk_info.cpub23_rate;
+ else
+ return GPLL_RATE / (div + 1);
+ case 2:
+ return rk3588_b1pll_get_rate();
+ default:
+ return 0;
+ }
+ }
+}
+
+static int clk_scmi_cpub23_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ return 0;
+}
+
+static unsigned long clk_scmi_dsu_get_rate(rk_scmi_clock_t *clock)
+{
+ int src, div;
+
+ src = mmio_read_32(DSUCRU_BASE + CRU_CLKSEL_CON(1)) & 0x1;
+ if (src != 0) {
+ return sys_clk_info.dsu_rate;
+ } else {
+ src = mmio_read_32(DSUCRU_BASE + CRU_CLKSEL_CON(0)) & 0x3000;
+ src = src >> 12;
+ div = mmio_read_32(DSUCRU_BASE + CRU_CLKSEL_CON(0)) & 0xf80;
+ div = div >> 7;
+ switch (src) {
+ case 0:
+ return rk3588_b0pll_get_rate() / (div + 1);
+ case 1:
+ return rk3588_b1pll_get_rate() / (div + 1);
+ case 2:
+ return rk3588_lpll_get_rate() / (div + 1);
+ case 3:
+ return GPLL_RATE / (div + 1);
+ default:
+ return 0;
+ }
+ }
+}
+
+static void clk_scmi_lpll_disable(void)
+{
+ static bool is_lpll_disabled;
+
+ if (is_lpll_disabled)
+ return;
+
+ /* set corel mux gpll */
+ mmio_write_32(DSUCRU_BASE + CRU_CLKSEL_CON(5),
+ CPUL_CLK_PATH_NOR_GPLL);
+ /* set dsu mux gpll */
+ mmio_write_32(DSUCRU_BASE + CRU_CLKSEL_CON(0),
+ SCLK_DSU_PATH_NOR_GPLL);
+ /* pll enter slow mode */
+ mmio_write_32(DSUCRU_BASE + CRU_MODE_CON0, CPU_PLL_PATH_SLOWMODE);
+ /* set pll power down */
+ mmio_write_32(DSUCRU_BASE + CRU_PLL_CON(17), CRU_PLL_POWER_DOWN);
+
+ is_lpll_disabled = true;
+}
+
+static int clk_dsu_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;
+
+ /* set pvtpll */
+ if (PVTPLL_NEED(type, pvtpll->length)) {
+ /* set clock gating interval */
+ mmio_write_32(DSUGRF_BASE + RK3588_DSU_PVTPLL_CON2,
+ 0x00040000);
+ /* set ring sel */
+ mmio_write_32(DSUGRF_BASE + RK3588_DSU_PVTPLL_CON0_L,
+ 0x07000000 | (pvtpll->ring_sel << 8));
+ /* set length */
+ mmio_write_32(DSUGRF_BASE + RK3588_DSU_PVTPLL_CON0_H,
+ 0x003f0000 | pvtpll->length);
+ /* set cal cnt = 24, T = 1us */
+ mmio_write_32(DSUGRF_BASE + RK3588_DSU_PVTPLL_CON1,
+ 0x18);
+ /* enable pvtpll */
+ mmio_write_32(DSUGRF_BASE + RK3588_DSU_PVTPLL_CON0_L,
+ 0x00020002);
+ /* start monitor */
+ mmio_write_32(DSUGRF_BASE + RK3588_DSU_PVTPLL_CON0_L,
+ 0x00010001);
+ /* set dsu mux pvtpll */
+ mmio_write_32(DSUCRU_BASE + CRU_CLKSEL_CON(7),
+ DSU_PVTPLL_PATH_PVTPLL);
+ mmio_write_32(DSUCRU_BASE + CRU_CLKSEL_CON(1),
+ SCLK_DSU_PATH_PVTPLL);
+ goto out;
+ }
+ /* set dsu div */
+ div = DIV_ROUND_UP(GPLL_RATE, rate) - 1;
+ mmio_write_32(DSUCRU_BASE + CRU_CLKSEL_CON(0),
+ CLKDIV_5BITS_SHF(div, 7));
+ /* set dsu mux gpll */
+ mmio_write_32(DSUCRU_BASE + CRU_CLKSEL_CON(0),
+ SCLK_DSU_PATH_NOR_GPLL);
+ mmio_write_32(DSUCRU_BASE + CRU_CLKSEL_CON(1),
+ SCLK_DSU_PATH_NOR_PLL);
+
+out:
+ clk_scmi_lpll_disable();
+
+ return 0;
+}
+
+static int clk_scmi_dsu_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ int ret;
+
+ if (rate == 0)
+ return SCMI_INVALID_PARAMETERS;
+
+ ret = clk_dsu_set_rate(rate, PLL_SEL_AUTO);
+
+ if (ret == 0)
+ sys_clk_info.dsu_rate = rate;
+ return ret;
+}
+
+static int clk_scmi_dsu_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(158)) & 0x4000) != 0) {
+ return sys_clk_info.gpu_rate;
+ } else {
+ div = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(158)) & 0x1f;
+ src = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(158)) & 0x00e0;
+ src = src >> 5;
+ switch (src) {
+ case 0:
+ /* Make the return rate is equal to the set rate */
+ if (sys_clk_info.gpu_rate)
+ 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 NPLL_RATE / (div + 1);
+ case 4:
+ return SPLL_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)) {
+ /* set clock gating interval */
+ mmio_write_32(GPUGRF_BASE + RK3588_GPU_PVTPLL_CON2,
+ 0x00040000);
+ /* set ring sel */
+ mmio_write_32(GPUGRF_BASE + RK3588_GPU_PVTPLL_CON0_L,
+ 0x07000000 | (pvtpll->ring_sel << 8));
+ /* set length */
+ mmio_write_32(GPUGRF_BASE + RK3588_GPU_PVTPLL_CON0_H,
+ 0x003f0000 | pvtpll->length);
+ /* set cal cnt = 24, T = 1us */
+ mmio_write_32(GPUGRF_BASE + RK3588_GPU_PVTPLL_CON1,
+ 0x18);
+ /* enable pvtpll */
+ mmio_write_32(GPUGRF_BASE + RK3588_GPU_PVTPLL_CON0_L,
+ 0x00020002);
+ /* start monitor */
+ mmio_write_32(GPUGRF_BASE + RK3588_GPU_PVTPLL_CON0_L,
+ 0x00010001);
+ /* set gpu mux pvtpll */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(158),
+ GPU_CLK_PATH_PVTPLL);
+ return 0;
+ }
+
+ /* set gpu div */
+ div = DIV_ROUND_UP(GPLL_RATE, rate);
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(158),
+ CLKDIV_5BITS_SHF(div - 1, 0));
+ /* set gpu mux gpll */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(158),
+ GPU_CLK_PATH_NOR_GPLL);
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(158),
+ 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;
+
+ 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;
+
+ if ((mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(74)) & 0x1) != 0) {
+ return sys_clk_info.npu_rate;
+ } else {
+ div = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(73)) & 0x007c;
+ div = div >> 2;
+ src = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(73)) & 0x0380;
+ src = src >> 7;
+ 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 + 1);
+ case 1:
+ return CPLL_RATE / (div + 1);
+ case 2:
+ return AUPLL_RATE / (div + 1);
+ case 3:
+ return NPLL_RATE / (div + 1);
+ case 4:
+ return SPLL_RATE / (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)) {
+ /* set clock gating interval */
+ mmio_write_32(NPUGRF_BASE + RK3588_NPU_PVTPLL_CON2,
+ 0x00040000);
+ /* set ring sel */
+ mmio_write_32(NPUGRF_BASE + RK3588_NPU_PVTPLL_CON0_L,
+ 0x07000000 | (pvtpll->ring_sel << 8));
+ /* set length */
+ mmio_write_32(NPUGRF_BASE + RK3588_NPU_PVTPLL_CON0_H,
+ 0x003f0000 | pvtpll->length);
+ /* set cal cnt = 24, T = 1us */
+ mmio_write_32(NPUGRF_BASE + RK3588_NPU_PVTPLL_CON1,
+ 0x18);
+ /* enable pvtpll */
+ mmio_write_32(NPUGRF_BASE + RK3588_NPU_PVTPLL_CON0_L,
+ 0x00020002);
+ /* start monitor */
+ mmio_write_32(NPUGRF_BASE + RK3588_NPU_PVTPLL_CON0_L,
+ 0x00010001);
+ /* set npu mux pvtpll */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(74),
+ NPU_CLK_PATH_PVTPLL);
+ return 0;
+ }
+
+ /* set npu div */
+ div = DIV_ROUND_UP(GPLL_RATE, rate);
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(73),
+ CLKDIV_5BITS_SHF(div - 1, 2));
+ /* set npu mux gpll */
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(73),
+ NPU_CLK_PATH_NOR_GPLL);
+ mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(74),
+ 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;
+
+ 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;
+}
+
+static unsigned long clk_scmi_sbus_get_rate(rk_scmi_clock_t *clock)
+{
+ int div;
+
+ if ((mmio_read_32(BUSSCRU_BASE + CRU_CLKSEL_CON(0)) & 0x0800) != 0) {
+ div = mmio_read_32(BUSSCRU_BASE + CRU_CLKSEL_CON(0));
+ div = (div & 0x03e0) >> 5;
+ return SPLL_RATE / (div + 1);
+ } else {
+ return OSC_HZ;
+ }
+}
+
+static int clk_scmi_sbus_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ int div;
+
+ if (rate == OSC_HZ) {
+ mmio_write_32(BUSSCRU_BASE + CRU_CLKSEL_CON(0),
+ WMSK_BIT(11));
+ return 0;
+ }
+
+ div = DIV_ROUND_UP(SPLL_RATE, rate);
+ mmio_write_32(BUSSCRU_BASE + CRU_CLKSEL_CON(0),
+ CLKDIV_5BITS_SHF(div - 1, 5));
+ mmio_write_32(BUSSCRU_BASE + CRU_CLKSEL_CON(0),
+ BIT_WITH_WMSK(11) | WMSK_BIT(10));
+ return 0;
+}
+
+static int clk_scmi_sbus_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ return 0;
+}
+
+static unsigned long clk_scmi_pclk_sbus_get_rate(rk_scmi_clock_t *clock)
+{
+ int div;
+
+ div = mmio_read_32(BUSSCRU_BASE + CRU_CLKSEL_CON(0));
+ div = div & 0x001f;
+ return SPLL_RATE / (div + 1);
+
+}
+
+static int clk_scmi_pclk_sbus_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ int div;
+
+ div = DIV_ROUND_UP(SPLL_RATE, rate);
+ mmio_write_32(BUSSCRU_BASE + CRU_CLKSEL_CON(0),
+ CLKDIV_5BITS_SHF(div - 1, 0));
+ return 0;
+}
+
+static int clk_scmi_pclk_sbus_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ return 0;
+}
+
+static unsigned long clk_scmi_cclk_sdmmc_get_rate(rk_scmi_clock_t *clock)
+{
+ int div;
+ uint32_t src;
+
+ src = mmio_read_32(SCRU_BASE + CRU_CLKSEL_CON(3)) & 0x3000;
+ src = src >> 12;
+ div = mmio_read_32(SCRU_BASE + CRU_CLKSEL_CON(3)) & 0x0fc0;
+ div = div >> 6;
+ if (src == 1) {
+ return SPLL_RATE / (div + 1);
+ } else if (src == 2) {
+ return OSC_HZ / (div + 1);
+ } else {
+ return GPLL_RATE / (div + 1);
+ }
+}
+
+static int clk_scmi_cclk_sdmmc_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ int div;
+
+ if ((OSC_HZ % rate) == 0) {
+ div = DIV_ROUND_UP(OSC_HZ, rate);
+ mmio_write_32(SCRU_BASE + CRU_CLKSEL_CON(3),
+ CLKDIV_6BITS_SHF(div - 1, 6) |
+ BITS_WITH_WMASK(2U, 0x3U, 12));
+ } else if ((SPLL_RATE % rate) == 0) {
+ div = DIV_ROUND_UP(SPLL_RATE, rate);
+ mmio_write_32(SCRU_BASE + CRU_CLKSEL_CON(3),
+ CLKDIV_6BITS_SHF(div - 1, 6) |
+ BITS_WITH_WMASK(1U, 0x3U, 12));
+ } else {
+ div = DIV_ROUND_UP(GPLL_RATE, rate);
+ mmio_write_32(SCRU_BASE + CRU_CLKSEL_CON(3),
+ CLKDIV_6BITS_SHF(div - 1, 6) |
+ BITS_WITH_WMASK(0U, 0x3U, 12));
+ }
+
+ return 0;
+}
+
+static int clk_scmi_cclk_sdmmc_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(3),
+ BITS_WITH_WMASK(!status, 0x1U, 4));
+ return 0;
+}
+
+static unsigned long clk_scmi_dclk_sdmmc_get_rate(rk_scmi_clock_t *clock)
+{
+ int div;
+ uint32_t src;
+
+ src = mmio_read_32(SCRU_BASE + CRU_CLKSEL_CON(3)) & 0x0020;
+ div = mmio_read_32(SCRU_BASE + CRU_CLKSEL_CON(3)) & 0x001f;
+ if (src != 0) {
+ return SPLL_RATE / (div + 1);
+ } else {
+ return GPLL_RATE / (div + 1);
+ }
+}
+
+static int clk_scmi_dclk_sdmmc_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ int div;
+
+ if ((SPLL_RATE % rate) == 0) {
+ div = DIV_ROUND_UP(SPLL_RATE, rate);
+ mmio_write_32(SCRU_BASE + CRU_CLKSEL_CON(3),
+ CLKDIV_5BITS_SHF(div - 1, 0) |
+ BITS_WITH_WMASK(1U, 0x1U, 5));
+ } else {
+ div = DIV_ROUND_UP(GPLL_RATE, rate);
+ mmio_write_32(SCRU_BASE + CRU_CLKSEL_CON(3),
+ CLKDIV_5BITS_SHF(div - 1, 0) |
+ BITS_WITH_WMASK(0U, 0x1U, 5));
+ }
+ return 0;
+}
+
+static int clk_scmi_dclk_sdmmc_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(3),
+ BITS_WITH_WMASK(!status, 0x1U, 1));
+ return 0;
+}
+
+static unsigned long clk_scmi_aclk_secure_ns_get_rate(rk_scmi_clock_t *clock)
+{
+ uint32_t src;
+
+ src = mmio_read_32(SCRU_BASE + CRU_CLKSEL_CON(1)) & 0x0003;
+ switch (src) {
+ case 0:
+ return 350 * MHz;
+ case 1:
+ return 200 * MHz;
+ case 2:
+ return 100 * MHz;
+ case 3:
+ return OSC_HZ;
+ default:
+ return 0;
+ }
+}
+
+static int clk_scmi_aclk_secure_ns_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ uint32_t src;
+
+ if (rate >= 350 * MHz)
+ src = 0;
+ else if (rate >= 200 * MHz)
+ src = 1;
+ else if (rate >= 100 * MHz)
+ src = 2;
+ else
+ src = 3;
+
+ mmio_write_32(SCRU_BASE + CRU_CLKSEL_CON(1),
+ BITS_WITH_WMASK(src, 0x3U, 0));
+
+ return 0;
+}
+
+static int clk_scmi_aclk_secure_ns_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ return 0;
+}
+
+static unsigned long clk_scmi_hclk_secure_ns_get_rate(rk_scmi_clock_t *clock)
+{
+ uint32_t src;
+
+ src = mmio_read_32(SCRU_BASE + CRU_CLKSEL_CON(1)) & 0x000c;
+ src = src >> 2;
+ switch (src) {
+ case 0:
+ return 150 * MHz;
+ case 1:
+ return 100 * MHz;
+ case 2:
+ return 50 * MHz;
+ case 3:
+ return OSC_HZ;
+ default:
+ return 0;
+ }
+}
+
+static int clk_scmi_hclk_secure_ns_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ uint32_t src;
+
+ if (rate >= 150 * MHz)
+ src = 0;
+ else if (rate >= 100 * MHz)
+ src = 1;
+ else if (rate >= 50 * MHz)
+ src = 2;
+ else
+ src = 3;
+
+ mmio_write_32(SCRU_BASE + CRU_CLKSEL_CON(1),
+ BITS_WITH_WMASK(src, 0x3U, 2));
+ return 0;
+}
+
+static int clk_scmi_hclk_secure_ns_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ return 0;
+}
+
+static unsigned long clk_scmi_tclk_wdt_get_rate(rk_scmi_clock_t *clock)
+{
+ return OSC_HZ;
+}
+
+static int clk_scmi_tclk_wdt_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(2),
+ BITS_WITH_WMASK(!status, 0x1U, 0));
+ return 0;
+}
+
+static unsigned long clk_scmi_keyladder_core_get_rate(rk_scmi_clock_t *clock)
+{
+ uint32_t src;
+
+ src = mmio_read_32(SCRU_BASE + CRU_CLKSEL_CON(2)) & 0x00c0;
+ src = src >> 6;
+ switch (src) {
+ case 0:
+ return 350 * MHz;
+ case 1:
+ return 233 * MHz;
+ case 2:
+ return 116 * MHz;
+ case 3:
+ return OSC_HZ;
+ default:
+ return 0;
+ }
+}
+
+static int clk_scmi_keyladder_core_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ uint32_t src;
+
+ if (rate >= 350 * MHz)
+ src = 0;
+ else if (rate >= 233 * MHz)
+ src = 1;
+ else if (rate >= 116 * MHz)
+ src = 2;
+ else
+ src = 3;
+
+ mmio_write_32(SCRU_BASE + CRU_CLKSEL_CON(2),
+ BITS_WITH_WMASK(src, 0x3U, 6));
+ return 0;
+}
+
+static int clk_scmi_keyladder_core_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(1),
+ BITS_WITH_WMASK(!status, 0x1U, 9));
+ return 0;
+}
+
+static unsigned long clk_scmi_keyladder_rng_get_rate(rk_scmi_clock_t *clock)
+{
+ uint32_t src;
+
+ src = mmio_read_32(SCRU_BASE + CRU_CLKSEL_CON(2)) & 0x0300;
+ src = src >> 8;
+ switch (src) {
+ case 0:
+ return 175 * MHz;
+ case 1:
+ return 116 * MHz;
+ case 2:
+ return 58 * MHz;
+ case 3:
+ return OSC_HZ;
+ default:
+ return 0;
+ }
+}
+
+static int clk_scmi_keyladder_rng_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ uint32_t src;
+
+ if (rate >= 175 * MHz)
+ src = 0;
+ else if (rate >= 116 * MHz)
+ src = 1;
+ else if (rate >= 58 * MHz)
+ src = 2;
+ else
+ src = 3;
+
+ mmio_write_32(SCRU_BASE + CRU_CLKSEL_CON(2),
+ BITS_WITH_WMASK(src, 0x3U, 8));
+ return 0;
+}
+
+static int clk_scmi_keyladder_rng_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(1),
+ BITS_WITH_WMASK(!status, 0x1U, 10));
+ return 0;
+}
+
+static unsigned long clk_scmi_aclk_secure_s_get_rate(rk_scmi_clock_t *clock)
+{
+ uint32_t src;
+
+ src = mmio_read_32(SCRU_BASE + CRU_CLKSEL_CON(1)) & 0x0030;
+ src = src >> 4;
+ switch (src) {
+ case 0:
+ return 350 * MHz;
+ case 1:
+ return 233 * MHz;
+ case 2:
+ return 116 * MHz;
+ case 3:
+ return OSC_HZ;
+ default:
+ return 0;
+ }
+}
+
+static int clk_scmi_aclk_secure_s_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ uint32_t src;
+
+ if (rate >= 350 * MHz)
+ src = 0;
+ else if (rate >= 233 * MHz)
+ src = 1;
+ else if (rate >= 116 * MHz)
+ src = 2;
+ else
+ src = 3;
+
+ mmio_write_32(SCRU_BASE + CRU_CLKSEL_CON(1),
+ BITS_WITH_WMASK(src, 0x3U, 4));
+ return 0;
+}
+
+static int clk_scmi_aclk_secure_s_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ return 0;
+}
+
+static unsigned long clk_scmi_hclk_secure_s_get_rate(rk_scmi_clock_t *clock)
+{
+ uint32_t src;
+
+ src = mmio_read_32(SCRU_BASE + CRU_CLKSEL_CON(1)) & 0x00c0;
+ src = src >> 6;
+ switch (src) {
+ case 0:
+ return 175 * MHz;
+ case 1:
+ return 116 * MHz;
+ case 2:
+ return 58 * MHz;
+ case 3:
+ return OSC_HZ;
+ default:
+ return 0;
+ }
+}
+
+static int clk_scmi_hclk_secure_s_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ uint32_t src;
+
+ if (rate >= 175 * MHz)
+ src = 0;
+ else if (rate >= 116 * MHz)
+ src = 1;
+ else if (rate >= 58 * MHz)
+ src = 2;
+ else
+ src = 3;
+
+ mmio_write_32(SCRU_BASE + CRU_CLKSEL_CON(1),
+ BITS_WITH_WMASK(src, 0x3U, 6));
+ return 0;
+}
+
+static int clk_scmi_hclk_secure_s_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ return 0;
+}
+
+static unsigned long clk_scmi_pclk_secure_s_get_rate(rk_scmi_clock_t *clock)
+{
+ uint32_t src;
+
+ src = mmio_read_32(SCRU_BASE + CRU_CLKSEL_CON(1)) & 0x0300;
+ src = src >> 8;
+ switch (src) {
+ case 0:
+ return 116 * MHz;
+ case 1:
+ return 58 * MHz;
+ case 2:
+ return OSC_HZ;
+ default:
+ return 0;
+ }
+}
+
+static int clk_scmi_pclk_secure_s_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ uint32_t src;
+
+ if (rate >= 116 * MHz)
+ src = 0;
+ else if (rate >= 58 * MHz)
+ src = 1;
+ else
+ src = 2;
+
+ mmio_write_32(SCRU_BASE + CRU_CLKSEL_CON(1),
+ BITS_WITH_WMASK(src, 0x3U, 8));
+ return 0;
+}
+
+static int clk_scmi_pclk_secure_s_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ return 0;
+}
+
+static unsigned long clk_scmi_crypto_rng_get_rate(rk_scmi_clock_t *clock)
+{
+ uint32_t src;
+
+ src = mmio_read_32(SCRU_BASE + CRU_CLKSEL_CON(1)) & 0xc000;
+ src = src >> 14;
+ switch (src) {
+ case 0:
+ return 175 * MHz;
+ case 1:
+ return 116 * MHz;
+ case 2:
+ return 58 * MHz;
+ case 3:
+ return OSC_HZ;
+ default:
+ return 0;
+ }
+}
+
+static int clk_scmi_crypto_rng_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ uint32_t src;
+
+ if (rate >= 175 * MHz)
+ src = 0;
+ else if (rate >= 116 * MHz)
+ src = 1;
+ else if (rate >= 58 * MHz)
+ src = 2;
+ else
+ src = 3;
+
+ mmio_write_32(SCRU_BASE + CRU_CLKSEL_CON(1),
+ BITS_WITH_WMASK(src, 0x3U, 14));
+ return 0;
+}
+
+static int clk_scmi_crypto_rng_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(1),
+ BITS_WITH_WMASK(!status, 0x1U, 1));
+
+ return 0;
+}
+
+static unsigned long clk_scmi_crypto_core_get_rate(rk_scmi_clock_t *clock)
+{
+ uint32_t src;
+
+ src = mmio_read_32(SCRU_BASE + CRU_CLKSEL_CON(1)) & 0x0c00;
+ src = src >> 10;
+ switch (src) {
+ case 0:
+ return 350 * MHz;
+ case 1:
+ return 233 * MHz;
+ case 2:
+ return 116 * MHz;
+ case 3:
+ return OSC_HZ;
+ default:
+ return 0;
+ }
+}
+
+static int clk_scmi_crypto_core_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ uint32_t src;
+
+ if (rate >= 350 * MHz)
+ src = 0;
+ else if (rate >= 233 * MHz)
+ src = 1;
+ else if (rate >= 116 * MHz)
+ src = 2;
+ else
+ src = 3;
+
+ mmio_write_32(SCRU_BASE + CRU_CLKSEL_CON(1),
+ BITS_WITH_WMASK(src, 0x3U, 10));
+ return 0;
+}
+
+static int clk_scmi_crypto_core_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(0),
+ BITS_WITH_WMASK(!status, 0x1U, 15));
+
+ return 0;
+}
+
+static unsigned long clk_scmi_crypto_pka_get_rate(rk_scmi_clock_t *clock)
+{
+ uint32_t src;
+
+ src = mmio_read_32(SCRU_BASE + CRU_CLKSEL_CON(1)) & 0x3000;
+ src = src >> 12;
+ switch (src) {
+ case 0:
+ return 350 * MHz;
+ case 1:
+ return 233 * MHz;
+ case 2:
+ return 116 * MHz;
+ case 3:
+ return OSC_HZ;
+ default:
+ return 0;
+ }
+}
+
+static int clk_scmi_crypto_pka_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ uint32_t src;
+
+ if (rate >= 350 * MHz)
+ src = 0;
+ else if (rate >= 233 * MHz)
+ src = 1;
+ else if (rate >= 116 * MHz)
+ src = 2;
+ else
+ src = 3;
+
+ mmio_write_32(SCRU_BASE + CRU_CLKSEL_CON(1),
+ BITS_WITH_WMASK(src, 0x3U, 12));
+ return 0;
+}
+
+static int clk_scmi_crypto_pka_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(1),
+ BITS_WITH_WMASK(!status, 0x1U, 0));
+
+ return 0;
+}
+
+static unsigned long clk_scmi_spll_get_rate(rk_scmi_clock_t *clock)
+{
+ uint32_t src;
+
+ src = mmio_read_32(BUSSCRU_BASE + CRU_MODE_CON0) & 0x3;
+ switch (src) {
+ case 0:
+ return OSC_HZ;
+ case 1:
+ return 702 * MHz;
+ case 2:
+ return 32768;
+ default:
+ return 0;
+ }
+}
+
+static int clk_scmi_spll_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ uint32_t src;
+
+ if (rate >= 700 * MHz)
+ src = 1;
+ else
+ src = 0;
+
+ mmio_write_32(BUSSCRU_BASE + CRU_MODE_CON0,
+ BITS_WITH_WMASK(0, 0x3U, 0));
+ mmio_write_32(BUSSCRU_BASE + CRU_PLL_CON(137),
+ BITS_WITH_WMASK(2, 0x7U, 6));
+
+ mmio_write_32(BUSSCRU_BASE + CRU_MODE_CON0,
+ BITS_WITH_WMASK(src, 0x3U, 0));
+ return 0;
+}
+
+static int clk_scmi_spll_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ return 0;
+}
+
+static unsigned long clk_scmi_hclk_sd_get_rate(rk_scmi_clock_t *clock)
+{
+ return clk_scmi_hclk_secure_ns_get_rate(clock);
+}
+
+static int clk_scmi_hclk_sd_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(3),
+ BITS_WITH_WMASK(!status, 0x1U, 2));
+ return 0;
+}
+
+static unsigned long clk_scmi_crypto_rng_s_get_rate(rk_scmi_clock_t *clock)
+{
+ uint32_t src;
+
+ src = mmio_read_32(SCRU_BASE + CRU_CLKSEL_CON(2)) & 0x0030;
+ src = src >> 4;
+ switch (src) {
+ case 0:
+ return 175 * MHz;
+ case 1:
+ return 116 * MHz;
+ case 2:
+ return 58 * MHz;
+ case 3:
+ return OSC_HZ;
+ default:
+ return 0;
+ }
+}
+
+static int clk_scmi_crypto_rng_s_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ uint32_t src;
+
+ if (rate >= 175 * MHz)
+ src = 0;
+ else if (rate >= 116 * MHz)
+ src = 1;
+ else if (rate >= 58 * MHz)
+ src = 2;
+ else
+ src = 3;
+
+ mmio_write_32(SCRU_BASE + CRU_CLKSEL_CON(2),
+ BITS_WITH_WMASK(src, 0x3U, 4));
+ return 0;
+}
+
+static int clk_scmi_crypto_rng_s_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(1),
+ BITS_WITH_WMASK(!status, 0x1U, 6));
+
+ return 0;
+}
+
+static unsigned long clk_scmi_crypto_core_s_get_rate(rk_scmi_clock_t *clock)
+{
+ uint32_t src;
+
+ src = mmio_read_32(SCRU_BASE + CRU_CLKSEL_CON(2)) & 0x3;
+ src = src >> 0;
+ switch (src) {
+ case 0:
+ return 350 * MHz;
+ case 1:
+ return 233 * MHz;
+ case 2:
+ return 116 * MHz;
+ case 3:
+ return OSC_HZ;
+ default:
+ return 0;
+ }
+}
+
+static int clk_scmi_crypto_core_s_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ uint32_t src;
+
+ if (rate >= 350 * MHz)
+ src = 0;
+ else if (rate >= 233 * MHz)
+ src = 1;
+ else if (rate >= 116 * MHz)
+ src = 2;
+ else
+ src = 3;
+
+ mmio_write_32(SCRU_BASE + CRU_CLKSEL_CON(2),
+ BITS_WITH_WMASK(src, 0x3U, 0));
+ return 0;
+}
+
+static int clk_scmi_crypto_core_s_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(1),
+ BITS_WITH_WMASK(!status, 0x1U, 4));
+
+ return 0;
+}
+
+static unsigned long clk_scmi_crypto_pka_s_get_rate(rk_scmi_clock_t *clock)
+{
+ uint32_t src;
+
+ src = mmio_read_32(SCRU_BASE + CRU_CLKSEL_CON(2)) & 0x000c;
+ src = src >> 2;
+ switch (src) {
+ case 0:
+ return 350 * MHz;
+ case 1:
+ return 233 * MHz;
+ case 2:
+ return 116 * MHz;
+ case 3:
+ return OSC_HZ;
+ default:
+ return 0;
+ }
+}
+
+static int clk_scmi_crypto_pka_s_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ uint32_t src;
+
+ if (rate >= 350 * MHz)
+ src = 0;
+ else if (rate >= 233 * MHz)
+ src = 1;
+ else if (rate >= 116 * MHz)
+ src = 2;
+ else
+ src = 3;
+
+ mmio_write_32(SCRU_BASE + CRU_CLKSEL_CON(2),
+ BITS_WITH_WMASK(src, 0x3U, 2));
+ return 0;
+}
+
+static int clk_scmi_crypto_pka_s_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(1),
+ BITS_WITH_WMASK(!status, 0x1U, 5));
+
+ return 0;
+}
+
+static unsigned long clk_scmi_a_crypto_s_get_rate(rk_scmi_clock_t *clock)
+{
+ return clk_scmi_aclk_secure_s_get_rate(clock);
+}
+
+static int clk_scmi_a_crypto_s_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ return clk_scmi_aclk_secure_s_set_rate(clock, rate);
+}
+
+static int clk_scmi_a_crypto_s_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(1),
+ BITS_WITH_WMASK(!status, 0x1U, 7));
+
+ return 0;
+}
+
+static unsigned long clk_scmi_h_crypto_s_get_rate(rk_scmi_clock_t *clock)
+{
+ return clk_scmi_hclk_secure_s_get_rate(clock);
+}
+
+static int clk_scmi_h_crypto_s_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ return clk_scmi_hclk_secure_s_set_rate(clock, rate);
+}
+
+static int clk_scmi_h_crypto_s_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(1),
+ BITS_WITH_WMASK(!status, 0x1U, 8));
+
+ return 0;
+}
+
+static unsigned long clk_scmi_p_crypto_s_get_rate(rk_scmi_clock_t *clock)
+{
+ return clk_scmi_pclk_secure_s_get_rate(clock);
+}
+
+static int clk_scmi_p_crypto_s_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ return clk_scmi_pclk_secure_s_set_rate(clock, rate);
+}
+
+static int clk_scmi_p_crypto_s_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(2),
+ BITS_WITH_WMASK(!status, 0x1U, 13));
+
+ return 0;
+}
+
+static unsigned long clk_scmi_a_keylad_s_get_rate(rk_scmi_clock_t *clock)
+{
+ return clk_scmi_aclk_secure_s_get_rate(clock);
+}
+
+static int clk_scmi_a_keylad_s_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ return clk_scmi_aclk_secure_s_set_rate(clock, rate);
+}
+
+static int clk_scmi_a_keylad_s_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(1),
+ BITS_WITH_WMASK(!status, 0x1U, 11));
+
+ return 0;
+}
+
+static unsigned long clk_scmi_h_keylad_s_get_rate(rk_scmi_clock_t *clock)
+{
+ return clk_scmi_hclk_secure_s_get_rate(clock);
+}
+
+static int clk_scmi_h_keylad_s_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ return clk_scmi_hclk_secure_s_set_rate(clock, rate);
+}
+
+static int clk_scmi_h_keylad_s_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(1),
+ BITS_WITH_WMASK(!status, 0x1U, 12));
+
+ return 0;
+}
+
+static unsigned long clk_scmi_p_keylad_s_get_rate(rk_scmi_clock_t *clock)
+{
+ return clk_scmi_pclk_secure_s_get_rate(clock);
+}
+
+static int clk_scmi_p_keylad_s_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ return clk_scmi_pclk_secure_s_set_rate(clock, rate);
+}
+
+static int clk_scmi_p_keylad_s_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(2),
+ BITS_WITH_WMASK(!status, 0x1U, 14));
+
+ return 0;
+}
+
+static unsigned long clk_scmi_trng_s_get_rate(rk_scmi_clock_t *clock)
+{
+ return clk_scmi_hclk_secure_s_get_rate(clock);
+}
+
+static int clk_scmi_trng_s_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ return clk_scmi_hclk_secure_s_set_rate(clock, rate);
+}
+
+static int clk_scmi_trng_s_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(3),
+ BITS_WITH_WMASK(!status, 0x1U, 6));
+
+ return 0;
+}
+
+static unsigned long clk_scmi_h_trng_s_get_rate(rk_scmi_clock_t *clock)
+{
+ return clk_scmi_hclk_secure_s_get_rate(clock);
+}
+
+static int clk_scmi_h_trng_s_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ return clk_scmi_hclk_secure_s_set_rate(clock, rate);
+}
+
+static int clk_scmi_h_trng_s_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(2),
+ BITS_WITH_WMASK(!status, 0x1U, 15));
+
+ return 0;
+}
+
+static unsigned long clk_scmi_p_otpc_s_get_rate(rk_scmi_clock_t *clock)
+{
+ return clk_scmi_pclk_secure_s_get_rate(clock);
+}
+
+static int clk_scmi_p_otpc_s_set_rate(rk_scmi_clock_t *clock, unsigned long rate)
+{
+ return clk_scmi_pclk_secure_s_set_rate(clock, rate);
+}
+
+static int clk_scmi_p_otpc_s_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(1),
+ BITS_WITH_WMASK(!status, 0x1U, 13));
+
+ return 0;
+}
+
+static unsigned long clk_scmi_otpc_s_get_rate(rk_scmi_clock_t *clock)
+{
+ return OSC_HZ;
+}
+
+static int clk_scmi_otpc_s_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(SCRU_BASE + CRU_CLKGATE_CON(1),
+ BITS_WITH_WMASK(!status, 0x1U, 14));
+ return 0;
+}
+
+static unsigned long clk_scmi_otp_phy_get_rate(rk_scmi_clock_t *clock)
+{
+ return OSC_HZ;
+}
+
+static int clk_scmi_otp_phy_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(18),
+ BITS_WITH_WMASK(!status, 0x1U, 13));
+ return 0;
+}
+
+static unsigned long clk_scmi_otpc_rd_get_rate(rk_scmi_clock_t *clock)
+{
+ return OSC_HZ;
+}
+
+static int clk_scmi_otpc_rd_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(18),
+ BITS_WITH_WMASK(!status, 0x1U, 12));
+ return 0;
+}
+
+static unsigned long clk_scmi_otpc_arb_get_rate(rk_scmi_clock_t *clock)
+{
+ return OSC_HZ;
+}
+
+static int clk_scmi_otpc_arb_set_status(rk_scmi_clock_t *clock, bool status)
+{
+ mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(18),
+ BITS_WITH_WMASK(!status, 0x1U, 11));
+ 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_dsu_ops = {
+ .get_rate = clk_scmi_dsu_get_rate,
+ .set_rate = clk_scmi_dsu_set_rate,
+ .set_status = clk_scmi_dsu_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_cpub01_ops = {
+ .get_rate = clk_scmi_cpub01_get_rate,
+ .set_rate = clk_scmi_cpub01_set_rate,
+ .set_status = clk_scmi_cpub01_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_cpub23_ops = {
+ .get_rate = clk_scmi_cpub23_get_rate,
+ .set_rate = clk_scmi_cpub23_set_rate,
+ .set_status = clk_scmi_cpub23_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_sbus_ops = {
+ .get_rate = clk_scmi_sbus_get_rate,
+ .set_rate = clk_scmi_sbus_set_rate,
+ .set_status = clk_scmi_sbus_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_pclk_sbus_ops = {
+ .get_rate = clk_scmi_pclk_sbus_get_rate,
+ .set_rate = clk_scmi_pclk_sbus_set_rate,
+ .set_status = clk_scmi_pclk_sbus_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_cclk_sdmmc_ops = {
+ .get_rate = clk_scmi_cclk_sdmmc_get_rate,
+ .set_rate = clk_scmi_cclk_sdmmc_set_rate,
+ .set_status = clk_scmi_cclk_sdmmc_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_dclk_sdmmc_ops = {
+ .get_rate = clk_scmi_dclk_sdmmc_get_rate,
+ .set_rate = clk_scmi_dclk_sdmmc_set_rate,
+ .set_status = clk_scmi_dclk_sdmmc_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_aclk_secure_ns_ops = {
+ .get_rate = clk_scmi_aclk_secure_ns_get_rate,
+ .set_rate = clk_scmi_aclk_secure_ns_set_rate,
+ .set_status = clk_scmi_aclk_secure_ns_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_hclk_secure_ns_ops = {
+ .get_rate = clk_scmi_hclk_secure_ns_get_rate,
+ .set_rate = clk_scmi_hclk_secure_ns_set_rate,
+ .set_status = clk_scmi_hclk_secure_ns_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_tclk_wdt_ops = {
+ .get_rate = clk_scmi_tclk_wdt_get_rate,
+ .set_status = clk_scmi_tclk_wdt_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_keyladder_core_ops = {
+ .get_rate = clk_scmi_keyladder_core_get_rate,
+ .set_rate = clk_scmi_keyladder_core_set_rate,
+ .set_status = clk_scmi_keyladder_core_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_keyladder_rng_ops = {
+ .get_rate = clk_scmi_keyladder_rng_get_rate,
+ .set_rate = clk_scmi_keyladder_rng_set_rate,
+ .set_status = clk_scmi_keyladder_rng_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_aclk_secure_s_ops = {
+ .get_rate = clk_scmi_aclk_secure_s_get_rate,
+ .set_rate = clk_scmi_aclk_secure_s_set_rate,
+ .set_status = clk_scmi_aclk_secure_s_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_hclk_secure_s_ops = {
+ .get_rate = clk_scmi_hclk_secure_s_get_rate,
+ .set_rate = clk_scmi_hclk_secure_s_set_rate,
+ .set_status = clk_scmi_hclk_secure_s_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_pclk_secure_s_ops = {
+ .get_rate = clk_scmi_pclk_secure_s_get_rate,
+ .set_rate = clk_scmi_pclk_secure_s_set_rate,
+ .set_status = clk_scmi_pclk_secure_s_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_crypto_rng_ops = {
+ .get_rate = clk_scmi_crypto_rng_get_rate,
+ .set_rate = clk_scmi_crypto_rng_set_rate,
+ .set_status = clk_scmi_crypto_rng_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_crypto_core_ops = {
+ .get_rate = clk_scmi_crypto_core_get_rate,
+ .set_rate = clk_scmi_crypto_core_set_rate,
+ .set_status = clk_scmi_crypto_core_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_crypto_pka_ops = {
+ .get_rate = clk_scmi_crypto_pka_get_rate,
+ .set_rate = clk_scmi_crypto_pka_set_rate,
+ .set_status = clk_scmi_crypto_pka_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_spll_ops = {
+ .get_rate = clk_scmi_spll_get_rate,
+ .set_rate = clk_scmi_spll_set_rate,
+ .set_status = clk_scmi_spll_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_hclk_sd_ops = {
+ .get_rate = clk_scmi_hclk_sd_get_rate,
+ .set_status = clk_scmi_hclk_sd_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_crypto_rng_s_ops = {
+ .get_rate = clk_scmi_crypto_rng_s_get_rate,
+ .set_rate = clk_scmi_crypto_rng_s_set_rate,
+ .set_status = clk_scmi_crypto_rng_s_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_crypto_core_s_ops = {
+ .get_rate = clk_scmi_crypto_core_s_get_rate,
+ .set_rate = clk_scmi_crypto_core_s_set_rate,
+ .set_status = clk_scmi_crypto_core_s_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_crypto_pka_s_ops = {
+ .get_rate = clk_scmi_crypto_pka_s_get_rate,
+ .set_rate = clk_scmi_crypto_pka_s_set_rate,
+ .set_status = clk_scmi_crypto_pka_s_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_a_crypto_s_ops = {
+ .get_rate = clk_scmi_a_crypto_s_get_rate,
+ .set_rate = clk_scmi_a_crypto_s_set_rate,
+ .set_status = clk_scmi_a_crypto_s_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_h_crypto_s_ops = {
+ .get_rate = clk_scmi_h_crypto_s_get_rate,
+ .set_rate = clk_scmi_h_crypto_s_set_rate,
+ .set_status = clk_scmi_h_crypto_s_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_p_crypto_s_ops = {
+ .get_rate = clk_scmi_p_crypto_s_get_rate,
+ .set_rate = clk_scmi_p_crypto_s_set_rate,
+ .set_status = clk_scmi_p_crypto_s_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_a_keylad_s_ops = {
+ .get_rate = clk_scmi_a_keylad_s_get_rate,
+ .set_rate = clk_scmi_a_keylad_s_set_rate,
+ .set_status = clk_scmi_a_keylad_s_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_h_keylad_s_ops = {
+ .get_rate = clk_scmi_h_keylad_s_get_rate,
+ .set_rate = clk_scmi_h_keylad_s_set_rate,
+ .set_status = clk_scmi_h_keylad_s_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_p_keylad_s_ops = {
+ .get_rate = clk_scmi_p_keylad_s_get_rate,
+ .set_rate = clk_scmi_p_keylad_s_set_rate,
+ .set_status = clk_scmi_p_keylad_s_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_trng_s_ops = {
+ .get_rate = clk_scmi_trng_s_get_rate,
+ .set_rate = clk_scmi_trng_s_set_rate,
+ .set_status = clk_scmi_trng_s_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_h_trng_s_ops = {
+ .get_rate = clk_scmi_h_trng_s_get_rate,
+ .set_rate = clk_scmi_h_trng_s_set_rate,
+ .set_status = clk_scmi_h_trng_s_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_p_otpc_s_ops = {
+ .get_rate = clk_scmi_p_otpc_s_get_rate,
+ .set_rate = clk_scmi_p_otpc_s_set_rate,
+ .set_status = clk_scmi_p_otpc_s_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_otpc_s_ops = {
+ .get_rate = clk_scmi_otpc_s_get_rate,
+ .set_status = clk_scmi_otpc_s_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_otp_phy_ops = {
+ .get_rate = clk_scmi_otp_phy_get_rate,
+ .set_status = clk_scmi_otp_phy_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_otpc_rd_ops = {
+ .get_rate = clk_scmi_otpc_rd_get_rate,
+ .set_status = clk_scmi_otpc_rd_set_status,
+};
+
+static const struct rk_clk_ops clk_scmi_otpc_arb_ops = {
+ .get_rate = clk_scmi_otpc_arb_get_rate,
+ .set_status = clk_scmi_otpc_arb_set_status,
+};
+
+rk_scmi_clock_t clock_table[] = {
+ RK3588_SCMI_CLOCK(SCMI_CLK_CPUL, "scmi_clk_cpul", &clk_scmi_cpul_ops, rk3588_cpul_rates, ARRAY_SIZE(rk3588_cpul_rates), false),
+ RK3588_SCMI_CLOCK(SCMI_CLK_DSU, "scmi_clk_dsu", &clk_scmi_dsu_ops, rk3588_cpul_rates, ARRAY_SIZE(rk3588_cpul_rates), false),
+ RK3588_SCMI_CLOCK(SCMI_CLK_CPUB01, "scmi_clk_cpub01", &clk_scmi_cpub01_ops, rk3588_cpub_rates, ARRAY_SIZE(rk3588_cpub_rates), false),
+ RK3588_SCMI_CLOCK(SCMI_CLK_CPUB23, "scmi_clk_cpub23", &clk_scmi_cpub23_ops, rk3588_cpub_rates, ARRAY_SIZE(rk3588_cpub_rates), false),
+ RK3588_SCMI_CLOCK(SCMI_CLK_DDR, "scmi_clk_ddr", NULL, NULL, 0, false),
+ RK3588_SCMI_CLOCK(SCMI_CLK_GPU, "scmi_clk_gpu", &clk_scmi_gpu_ops, rk3588_gpu_rates, ARRAY_SIZE(rk3588_gpu_rates), false),
+ RK3588_SCMI_CLOCK(SCMI_CLK_NPU, "scmi_clk_npu", &clk_scmi_npu_ops, rk3588_gpu_rates, ARRAY_SIZE(rk3588_gpu_rates), false),
+ RK3588_SCMI_CLOCK(SCMI_CLK_SBUS, "scmi_clk_sbus", &clk_scmi_sbus_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), true),
+ RK3588_SCMI_CLOCK(SCMI_PCLK_SBUS, "scmi_pclk_sbus", &clk_scmi_pclk_sbus_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), true),
+ RK3588_SCMI_CLOCK(SCMI_CCLK_SD, "scmi_cclk_sd", &clk_scmi_cclk_sdmmc_ops, rk3588_sdmmc_rates, ARRAY_SIZE(rk3588_sdmmc_rates), false),
+ RK3588_SCMI_CLOCK(SCMI_DCLK_SD, "scmi_dclk_sd", &clk_scmi_dclk_sdmmc_ops, rk3588_sdmmc_rates, ARRAY_SIZE(rk3588_sdmmc_rates), false),
+ RK3588_SCMI_CLOCK(SCMI_ACLK_SECURE_NS, "scmi_aclk_se_ns", &clk_scmi_aclk_secure_ns_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), false),
+ RK3588_SCMI_CLOCK(SCMI_HCLK_SECURE_NS, "scmi_hclk_se_ns", &clk_scmi_hclk_secure_ns_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), false),
+ RK3588_SCMI_CLOCK(SCMI_TCLK_WDT, "scmi_tclk_wdt", &clk_scmi_tclk_wdt_ops, NULL, 0, false),
+ RK3588_SCMI_CLOCK(SCMI_KEYLADDER_CORE, "scmi_keylad_c", &clk_scmi_keyladder_core_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), true),
+ RK3588_SCMI_CLOCK(SCMI_KEYLADDER_RNG, "scmi_keylad_r", &clk_scmi_keyladder_rng_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), true),
+ RK3588_SCMI_CLOCK(SCMI_ACLK_SECURE_S, "scmi_aclk_se_s", &clk_scmi_aclk_secure_s_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), true),
+ RK3588_SCMI_CLOCK(SCMI_HCLK_SECURE_S, "scmi_hclk_se_s", &clk_scmi_hclk_secure_s_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), true),
+ RK3588_SCMI_CLOCK(SCMI_PCLK_SECURE_S, "scmi_pclk_se_s", &clk_scmi_pclk_secure_s_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), true),
+ RK3588_SCMI_CLOCK(SCMI_CRYPTO_RNG, "scmi_crypto_r", &clk_scmi_crypto_rng_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), false),
+ RK3588_SCMI_CLOCK(SCMI_CRYPTO_CORE, "scmi_crypto_c", &clk_scmi_crypto_core_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), false),
+ RK3588_SCMI_CLOCK(SCMI_CRYPTO_PKA, "scmi_crypto_p", &clk_scmi_crypto_pka_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), false),
+ RK3588_SCMI_CLOCK(SCMI_SPLL, "scmi_spll", &clk_scmi_spll_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), false),
+ RK3588_SCMI_CLOCK(SCMI_HCLK_SD, "scmi_hclk_sd", &clk_scmi_hclk_sd_ops, NULL, 0, false),
+ RK3588_SCMI_CLOCK(SCMI_CRYPTO_RNG_S, "scmi_crypto_r_s", &clk_scmi_crypto_rng_s_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), true),
+ RK3588_SCMI_CLOCK(SCMI_CRYPTO_CORE_S, "scmi_crypto_c_s", &clk_scmi_crypto_core_s_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), true),
+ RK3588_SCMI_CLOCK(SCMI_CRYPTO_PKA_S, "scmi_crypto_p_s", &clk_scmi_crypto_pka_s_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), true),
+ RK3588_SCMI_CLOCK(SCMI_A_CRYPTO_S, "scmi_a_crypto_s", &clk_scmi_a_crypto_s_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), true),
+ RK3588_SCMI_CLOCK(SCMI_H_CRYPTO_S, "scmi_h_crypto_s", &clk_scmi_h_crypto_s_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), true),
+ RK3588_SCMI_CLOCK(SCMI_P_CRYPTO_S, "scmi_p_crypto_s", &clk_scmi_p_crypto_s_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), true),
+ RK3588_SCMI_CLOCK(SCMI_A_KEYLADDER_S, "scmi_a_keylad_s", &clk_scmi_a_keylad_s_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), true),
+ RK3588_SCMI_CLOCK(SCMI_H_KEYLADDER_S, "scmi_h_keylad_s", &clk_scmi_h_keylad_s_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), true),
+ RK3588_SCMI_CLOCK(SCMI_P_KEYLADDER_S, "scmi_p_keylad_s", &clk_scmi_p_keylad_s_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), true),
+ RK3588_SCMI_CLOCK(SCMI_TRNG_S, "scmi_trng_s", &clk_scmi_trng_s_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), true),
+ RK3588_SCMI_CLOCK(SCMI_H_TRNG_S, "scmi_h_trng_s", &clk_scmi_h_trng_s_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), true),
+ RK3588_SCMI_CLOCK(SCMI_P_OTPC_S, "scmi_p_otpc_s", &clk_scmi_p_otpc_s_ops, rk3588_sbus_rates, ARRAY_SIZE(rk3588_sbus_rates), true),
+ RK3588_SCMI_CLOCK(SCMI_OTPC_S, "scmi_otpc_s", &clk_scmi_otpc_s_ops, NULL, 0, true),
+ RK3588_SCMI_CLOCK(SCMI_OTP_PHY, "scmi_otp_phy", &clk_scmi_otp_phy_ops, NULL, 0, false),
+ RK3588_SCMI_CLOCK(SCMI_OTPC_AUTO_RD, "scmi_otpc_rd", &clk_scmi_otpc_rd_ops, NULL, 0, false),
+ RK3588_SCMI_CLOCK(SCMI_OTPC_ARB, "scmi_otpc_arb", &clk_scmi_otpc_arb_ops, NULL, 0, false),
+};
+
+size_t rockchip_scmi_clock_count(unsigned int agent_id __unused)
+{
+ return ARRAY_SIZE(clock_table);
+}
+
+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 && !table->is_security)
+ return table;
+ else
+ return NULL;
+}
+
+void pvtplls_suspend(void)
+{
+ clk_cpul_set_rate(408000000, PLL_SEL_NOR);
+ clk_dsu_set_rate(408000000, PLL_SEL_NOR);
+ clk_cpub01_set_rate(408000000, PLL_SEL_NOR);
+ clk_cpub23_set_rate(408000000, PLL_SEL_NOR);
+}
+
+void pvtplls_resume(void)
+{
+ clk_cpul_set_rate(sys_clk_info.cpul_rate, PLL_SEL_AUTO);
+ clk_dsu_set_rate(sys_clk_info.dsu_rate, PLL_SEL_AUTO);
+ clk_cpub01_set_rate(sys_clk_info.cpub01_rate, PLL_SEL_AUTO);
+ clk_cpub23_set_rate(sys_clk_info.cpub23_rate, PLL_SEL_AUTO);
+}
+
+void sys_reset_pvtplls_prepare(void)
+{
+ clk_gpu_set_rate(100000000, PLL_SEL_NOR);
+ clk_npu_set_rate(100000000, PLL_SEL_NOR);
+ clk_cpul_set_rate(408000000, PLL_SEL_NOR);
+ clk_cpub01_set_rate(408000000, PLL_SEL_NOR);
+ clk_cpub23_set_rate(408000000, PLL_SEL_NOR);
+ clk_dsu_set_rate(408000000, PLL_SEL_NOR);
+}
+
+void rockchip_clock_init(void)
+{
+ /* set gpll src div to 0 for cpul */
+ mmio_write_32(DSUCRU_BASE + CRU_CLKSEL_CON(5), CLKDIV_5BITS_SHF(0U, 9));
+ /* set gpll src div to 0 for cpub01 */
+ mmio_write_32(BIGCORE0CRU_BASE + CRU_CLKSEL_CON(0),
+ CLKDIV_5BITS_SHF(0U, 1));
+ /* set gpll src div to 0 for cpu23 */
+ mmio_write_32(BIGCORE1CRU_BASE + CRU_CLKSEL_CON(0),
+ CLKDIV_5BITS_SHF(0U, 1));
+
+ mmio_write_32(BIGCORE0CRU_BASE + CRU_CLKSEL_CON(2),
+ CPUB_PCLK_PATH_50M);
+ mmio_write_32(BIGCORE1CRU_BASE + CRU_CLKSEL_CON(2),
+ CPUB_PCLK_PATH_50M);
+
+ mmio_write_32(DSUCRU_BASE + DSUCRU_CLKSEL_CON(4),
+ CLKDIV_5BITS_SHF(5U, 0));
+ mmio_write_32(DSUCRU_BASE + DSUCRU_CLKSEL_CON(4),
+ BITS_WITH_WMASK(PCLK_DSU_ROOT_SEL_GPLL,
+ PCLK_DSU_ROOT_SEL_MASK,
+ PCLK_DSU_ROOT_SEL_SHIFT));
+
+ sys_clk_info.cpul_table = rk3588_cpul_pvtpll_table;
+ sys_clk_info.cpul_rate_count = ARRAY_SIZE(rk3588_cpul_pvtpll_table);
+ sys_clk_info.cpub01_table = rk3588_cpub0_pvtpll_table;
+ sys_clk_info.cpub01_rate_count = ARRAY_SIZE(rk3588_cpub0_pvtpll_table);
+ sys_clk_info.cpub23_table = rk3588_cpub1_pvtpll_table;
+ sys_clk_info.cpub23_rate_count = ARRAY_SIZE(rk3588_cpub1_pvtpll_table);
+ memcpy(sys_clk_info.cpub23_table, sys_clk_info.cpub01_table,
+ sys_clk_info.cpub01_rate_count * sizeof(*sys_clk_info.cpub01_table));
+ sys_clk_info.gpu_table = rk3588_gpu_pvtpll_table;
+ sys_clk_info.gpu_rate_count = ARRAY_SIZE(rk3588_gpu_pvtpll_table);
+ sys_clk_info.npu_table = rk3588_npu_pvtpll_table;
+ sys_clk_info.npu_rate_count = ARRAY_SIZE(rk3588_npu_pvtpll_table);
+}
diff --git a/plat/rockchip/rk3588/drivers/scmi/rk3588_clk.h b/plat/rockchip/rk3588/drivers/scmi/rk3588_clk.h
new file mode 100644
index 0000000..66fddaa
--- /dev/null
+++ b/plat/rockchip/rk3588/drivers/scmi/rk3588_clk.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __CLOCK_H__
+#define __CLOCK_H__
+
+/* scmi-clocks indices */
+
+#define SCMI_CLK_CPUL 0
+#define SCMI_CLK_DSU 1
+#define SCMI_CLK_CPUB01 2
+#define SCMI_CLK_CPUB23 3
+#define SCMI_CLK_DDR 4
+#define SCMI_CLK_GPU 5
+#define SCMI_CLK_NPU 6
+#define SCMI_CLK_SBUS 7
+#define SCMI_PCLK_SBUS 8
+#define SCMI_CCLK_SD 9
+#define SCMI_DCLK_SD 10
+#define SCMI_ACLK_SECURE_NS 11
+#define SCMI_HCLK_SECURE_NS 12
+#define SCMI_TCLK_WDT 13
+#define SCMI_KEYLADDER_CORE 14
+#define SCMI_KEYLADDER_RNG 15
+#define SCMI_ACLK_SECURE_S 16
+#define SCMI_HCLK_SECURE_S 17
+#define SCMI_PCLK_SECURE_S 18
+#define SCMI_CRYPTO_RNG 19
+#define SCMI_CRYPTO_CORE 20
+#define SCMI_CRYPTO_PKA 21
+#define SCMI_SPLL 22
+#define SCMI_HCLK_SD 23
+#define SCMI_CRYPTO_RNG_S 24
+#define SCMI_CRYPTO_CORE_S 25
+#define SCMI_CRYPTO_PKA_S 26
+#define SCMI_A_CRYPTO_S 27
+#define SCMI_H_CRYPTO_S 28
+#define SCMI_P_CRYPTO_S 29
+#define SCMI_A_KEYLADDER_S 30
+#define SCMI_H_KEYLADDER_S 31
+#define SCMI_P_KEYLADDER_S 32
+#define SCMI_TRNG_S 33
+#define SCMI_H_TRNG_S 34
+#define SCMI_P_OTPC_S 35
+#define SCMI_OTPC_S 36
+#define SCMI_OTP_PHY 37
+#define SCMI_OTPC_AUTO_RD 38
+#define SCMI_OTPC_ARB 39
+
+/******** DSUCRU **************************************/
+#define DSUCRU_CLKSEL_CON(n) (0x0300 + (n) * 4)
+
+/********Name=DSUCRU_CLKSEL_CON04,Offset=0x310********/
+#define PCLK_DSU_ROOT_SEL_SHIFT 5
+#define PCLK_DSU_ROOT_SEL_MASK 0x3
+#define PCLK_DSU_ROOT_SEL_GPLL 0x3
+
+/********Name=SECURE_SOFTRST_CON00,Offset=0xA00********/
+#define SRST_A_SECURE_NS_BIU 10
+#define SRST_H_SECURE_NS_BIU 11
+#define SRST_A_SECURE_S_BIU 12
+#define SRST_H_SECURE_S_BIU 13
+#define SRST_P_SECURE_S_BIU 14
+#define SRST_CRYPTO_CORE 15
+/********Name=SECURE_SOFTRST_CON01,Offset=0xA04********/
+#define SRST_CRYPTO_PKA 16
+#define SRST_CRYPTO_RNG 17
+#define SRST_A_CRYPTO 18
+#define SRST_H_CRYPTO 19
+#define SRST_KEYLADDER_CORE 25
+#define SRST_KEYLADDER_RNG 26
+#define SRST_A_KEYLADDER 27
+#define SRST_H_KEYLADDER 28
+#define SRST_P_OTPC_S 29
+#define SRST_OTPC_S 30
+#define SRST_WDT_S 31
+/********Name=SECURE_SOFTRST_CON02,Offset=0xA08********/
+#define SRST_T_WDT_S 32
+#define SRST_H_BOOTROM 33
+#define SRST_A_DCF 34
+#define SRST_P_DCF 35
+#define SRST_H_BOOTROM_NS 37
+#define SRST_P_KEYLADDER 46
+#define SRST_H_TRNG_S 47
+/********Name=SECURE_SOFTRST_CON03,Offset=0xA0C********/
+#define SRST_H_TRNG_NS 48
+#define SRST_D_SDMMC_BUFFER 49
+#define SRST_H_SDMMC 50
+#define SRST_H_SDMMC_BUFFER 51
+#define SRST_SDMMC 52
+#define SRST_P_TRNG_CHK 53
+#define SRST_TRNG_S 54
+
+#define SRST_INVALID 55
+
+void pvtplls_suspend(void);
+void pvtplls_resume(void);
+
+void rockchip_clock_init(void);
+
+#endif
diff --git a/plat/rockchip/rk3588/drivers/scmi/rk3588_rstd.c b/plat/rockchip/rk3588/drivers/scmi/rk3588_rstd.c
new file mode 100644
index 0000000..50b99e7
--- /dev/null
+++ b/plat/rockchip/rk3588/drivers/scmi/rk3588_rstd.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include <drivers/delay_timer.h>
+#include <drivers/scmi.h>
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#include <plat_private.h>
+#include "rk3588_clk.h"
+#include <scmi_rstd.h>
+#include <soc.h>
+
+#define DEFAULT_RESET_DOM_ATTRIBUTE 0
+
+#define RK3588_SCMI_RESET(_id, _name, _attribute, _ops) \
+{ \
+ .id = _id, \
+ .name = _name, \
+ .attribute = _attribute, \
+ .rstd_ops = _ops, \
+}
+
+static int rk3588_reset_explicit(rk_scmi_rstd_t *reset_domain,
+ bool assert_not_deassert)
+{
+ int bank = reset_domain->id / 16;
+ int offset = reset_domain->id % 16;
+
+ mmio_write_32(SCRU_BASE + CRU_SOFTRST_CON(bank),
+ BITS_WITH_WMASK(assert_not_deassert, 0x1U, offset));
+ return SCMI_SUCCESS;
+}
+
+static struct rk_scmi_rstd_ops rk3588_reset_domain_ops = {
+ .reset_explicit = rk3588_reset_explicit,
+};
+
+static rk_scmi_rstd_t rk3588_reset_domain_table[] = {
+ RK3588_SCMI_RESET(SRST_CRYPTO_CORE, "scmi_sr_cy_core", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_CRYPTO_PKA, "scmi_sr_cy_pka", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_CRYPTO_RNG, "scmi_sr_cy_rng", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_A_CRYPTO, "scmi_sr_a_cy", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_H_CRYPTO, "scmi_sr_h_cy", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_KEYLADDER_CORE, "scmi_sr_k_core", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_KEYLADDER_RNG, "scmi_sr_k_rng", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_P_OTPC_S, "scmi_sr_p_otp", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_OTPC_S, "scmi_sr_otp", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_WDT_S, "scmi_sr_wdt", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_T_WDT_S, "scmi_sr_t_wdt", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_H_BOOTROM, "scmi_sr_h_boot", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_P_KEYLADDER, "scmi_sr_p_ky", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_H_TRNG_S, "scmi_sr_h_trng", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_H_TRNG_NS, "scmi_sr_t_trng", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_D_SDMMC_BUFFER, "scmi_sr_d_sd", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_H_SDMMC, "scmi_sr_h_sd", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_H_SDMMC_BUFFER, "scmi_sr_h_sd_b", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_SDMMC, "scmi_sr_sd", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_P_TRNG_CHK, "scmi_sr_p_trng", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_TRNG_S, "scmi_sr_trng", DEFAULT_RESET_DOM_ATTRIBUTE, &rk3588_reset_domain_ops),
+ RK3588_SCMI_RESET(SRST_INVALID, "scmi_sr_invalid", DEFAULT_RESET_DOM_ATTRIBUTE, NULL),
+};
+
+static rk_scmi_rstd_t *
+rockchip_get_reset_domain_table(int id)
+{
+ rk_scmi_rstd_t *reset = rk3588_reset_domain_table;
+ int i = 0, cnt = ARRAY_SIZE(rk3588_reset_domain_table);
+
+ for (i = 0; i < cnt; i++) {
+ if (reset->id == id)
+ return &rk3588_reset_domain_table[i];
+ reset++;
+ }
+
+ return &rk3588_reset_domain_table[cnt - 1];
+}
+
+rk_scmi_rstd_t *rockchip_scmi_get_rstd(unsigned int agent_id,
+ unsigned int scmi_id)
+
+{
+ return rockchip_get_reset_domain_table(scmi_id);
+}
+
+size_t rockchip_scmi_rstd_count(unsigned int agent_id)
+{
+ return SRST_TRNG_S;
+}
+
diff --git a/plat/rockchip/rk3588/drivers/secure/secure.c b/plat/rockchip/rk3588/drivers/secure/secure.c
new file mode 100644
index 0000000..fc9f211
--- /dev/null
+++ b/plat/rockchip/rk3588/drivers/secure/secure.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <lib/mmio.h>
+
+#include <platform_def.h>
+
+#include <secure.h>
+#include <soc.h>
+
+static void secure_fw_master_init(void)
+{
+ uint32_t i;
+
+ /* ddr_mcu can access all ddr-regions */
+ mmio_write_32(FIREWALL_DDR_BASE + FIREWALL_DDR_MST(1), 0x0000ffff);
+ /* dcf/crypto_s can access all ddr-regions */
+ mmio_write_32(FIREWALL_DDR_BASE + FIREWALL_DDR_MST(14), 0x00000000);
+ /* dsu_mp_sec can access all ddr-regions.
+ * DSU access memory [f000_0000~ff00_0000] through MP in firewall_ddr.
+ */
+ mmio_write_32(FIREWALL_DDR_BASE + FIREWALL_DDR_MST(36), 0xffff0000);
+
+ /* all other ns-master can't access all ddr-regions */
+ for (i = 0; i < FIREWALL_DDR_MST_CNT; i++) {
+ if (i == 1 || i == 14 || i == 36)
+ continue;
+
+ mmio_write_32(FIREWALL_DDR_BASE + FIREWALL_DDR_MST(i), 0xffffffff);
+ }
+
+ /* mcu_pmu can access all sram-regions */
+ mmio_write_32(FIREWALL_SYSMEM_BASE + FIREWALL_SYSMEM_MST(19), 0x000000ff);
+ /* dsu mp-sec can access all sram-regions */
+ mmio_write_32(FIREWALL_SYSMEM_BASE + FIREWALL_SYSMEM_MST(38), 0x000000ff);
+ /* nsp_dsu2main_sec can access all sram-regions */
+ mmio_write_32(FIREWALL_SYSMEM_BASE + FIREWALL_SYSMEM_MST(41), 0x00000000);
+
+ /* all ns-master can't access all sram-regions */
+ for (i = 0; i < FIREWALL_SYSMEM_MST_CNT; i++) {
+ if (i == 19 || i == 38 || i == 41)
+ continue;
+
+ mmio_write_32(FIREWALL_SYSMEM_BASE + FIREWALL_SYSMEM_MST(i),
+ 0x00ff00ff);
+ }
+
+ /* dsu-ns can't access all ddr-regions, dsu-s can access all ddr-regions */
+ mmio_write_32(FIREWALL_DSU_BASE + FIREWALL_DSU_MST(0), 0xffffffff);
+ mmio_write_32(FIREWALL_DSU_BASE + FIREWALL_DSU_MST(1), 0x00000000);
+ dsb();
+ isb();
+}
+
+/* unit: Mb */
+static void dsu_fw_rgn_config(uint64_t base_mb, uint64_t top_mb, int rgn_id)
+{
+ int i;
+
+ if (rgn_id >= FIREWALL_DSU_RGN_CNT || rgn_id < 0) {
+ ERROR("%s regions-id:%d is invalid!\n", __func__, rgn_id);
+ panic();
+ }
+
+ mmio_write_32(FIREWALL_DSU_BASE + FIREWALL_DSU_RGN(rgn_id),
+ RG_MAP_SECURE(top_mb, base_mb));
+
+ for (i = 0; i < DDR_CHN_CNT; i++)
+ mmio_setbits_32(FIREWALL_DSU_BASE + FIREWALL_DSU_CON(i),
+ BIT(rgn_id));
+}
+
+/* unit: Mb */
+static void ddr_fw_rgn_config(uint64_t base_mb, uint64_t top_mb, int rgn_id)
+{
+ if (rgn_id >= FIREWALL_DDR_RGN_CNT || rgn_id < 0) {
+ ERROR("%s regions-id:%d is invalid!\n", __func__, rgn_id);
+ panic();
+ }
+
+ mmio_write_32(FIREWALL_DDR_BASE + FIREWALL_DDR_RGN(rgn_id),
+ RG_MAP_SECURE(top_mb, base_mb));
+
+ /* enable region */
+ mmio_setbits_32(FIREWALL_DDR_BASE + FIREWALL_DDR_CON,
+ BIT(rgn_id));
+}
+
+/* Unit: Kb */
+static void sram_fw_rgn_config(uint64_t base_kb, uint64_t top_kb, int rgn_id)
+{
+ if (rgn_id >= FIREWALL_SYSMEM_RGN_CNT || rgn_id < 0) {
+ ERROR("%s regions-id:%d is invalid!\n", __func__, rgn_id);
+ panic();
+ }
+
+ mmio_write_32(FIREWALL_SYSMEM_BASE + FIREWALL_SYSMEM_RGN(rgn_id),
+ RG_MAP_SRAM_SECURE(top_kb, base_kb));
+
+ /* enable region */
+ mmio_setbits_32(FIREWALL_SYSMEM_BASE + FIREWALL_SYSMEM_CON, BIT(rgn_id));
+}
+
+static void secure_region_init(void)
+{
+ uint32_t i;
+
+ /* disable all region first except region0 */
+ mmio_clrbits_32(FIREWALL_DDR_BASE + FIREWALL_DDR_CON, 0xfffe);
+ for (i = 0; i < FIREWALL_DSU_CON_CNT; i++)
+ mmio_clrbits_32(FIREWALL_DSU_BASE + FIREWALL_DSU_CON(i), 0xfffe);
+ mmio_clrbits_32(FIREWALL_SYSMEM_BASE + FIREWALL_SYSMEM_CON, 0xfe);
+
+ secure_fw_master_init();
+
+ /* Use FW_DDR_RGN0_REG to config 0~1M space to secure */
+ dsu_fw_rgn_config(0, 1, 0);
+ ddr_fw_rgn_config(0, 1, 0);
+
+ /* Use FIREWALL_SYSMEM_RGN0 to config SRAM_ENTRY code(0~4k of sram) to secure */
+ sram_fw_rgn_config(0, 4, 0);
+ /* For 0xffff0000~0xffffffff, use FIREWALL_SYSMEM_RGN7 to config
+ * 960~1024k of sram to secure.
+ */
+ sram_fw_rgn_config(960, 1024, 7);
+}
+
+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 sgrf_init(void)
+{
+ uint32_t i;
+
+ secure_region_init();
+
+ /* config master ddr_mcu_prot|dcf_wr|dcf_rd as secure */
+ mmio_write_32(BUSSGRF_BASE + SGRF_SOC_CON(14), 0x001f0011);
+ mmio_write_32(BUSSGRF_BASE + SGRF_SOC_CON(15), 0xffffffff);
+ mmio_write_32(BUSSGRF_BASE + SGRF_SOC_CON(16), 0x03ff03ff);
+
+ /* config slave mailbox_mcu_ddr as secure */
+ mmio_write_32(BUSSGRF_BASE + SGRF_FIREWALL_CON(4), 0xffff2000);
+ /* config slave int256mux4_mcu_ddr|int256mux4_mcu_pmu as secure */
+ mmio_write_32(BUSSGRF_BASE + SGRF_FIREWALL_CON(5), 0xffff0060);
+ /* config slave ddrgrf*|dma2ddr|ddrphy*_cru|umctl* as secure */
+ mmio_write_32(BUSSGRF_BASE + SGRF_FIREWALL_CON(24), 0xffff0fbf);
+ /* config slave ddrphy*|ddr_stanby*|ddr_mcu_timer|ddr_mcu_wdt as secure */
+ mmio_write_32(BUSSGRF_BASE + SGRF_FIREWALL_CON(25), 0xffff03ff);
+
+ /* config all other slave as ns */
+ for (i = 0; i < SGRF_FIREWALL_CON_CNT; i++) {
+ if (i == 4 || i == 5 || i == 24 || i == 25)
+ continue;
+
+ mmio_write_32(BUSSGRF_BASE + SGRF_FIREWALL_CON(i), 0xffff0000);
+ }
+
+ /* config vad_hprot non-secure, pmu_mcu_hprot as secure */
+ mmio_write_32(PMU1SGRF_BASE + PMU1SGRF_SOC_CON(0), 0x00180010);
+ /* config pmu1, pmu0, pmu_sram as secure */
+ mmio_write_32(PMU1SGRF_BASE + PMU1SGRF_SOC_CON(1), 0xefbe6020);
+ /* config remap_pmu_mem, h_pmu_mem as secure */
+ mmio_write_32(PMU1SGRF_BASE + PMU1SGRF_SOC_CON(2), 0x01f900c0);
+
+ /* disable dp encryption */
+ mmio_write_32(BUSSGRF_BASE + SGRF_SOC_CON(13), 0x00180018);
+
+ /* select grf config for pcie ats */
+ mmio_write_32(BUSSGRF_BASE + SGRF_SOC_CON(17), 0x11111111);
+ mmio_write_32(BUSSGRF_BASE + SGRF_SOC_CON(18), 0x11111111);
+ mmio_write_32(BUSSGRF_BASE + SGRF_SOC_CON(19), 0x00110011);
+}
diff --git a/plat/rockchip/rk3588/drivers/secure/secure.h b/plat/rockchip/rk3588/drivers/secure/secure.h
new file mode 100644
index 0000000..d9c234f
--- /dev/null
+++ b/plat/rockchip/rk3588/drivers/secure/secure.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef SECURE_H
+#define SECURE_H
+
+/* DSUSGRF */
+#define DSU_SGRF_SOC_CON(i) ((i) * 4)
+#define DSUSGRF_SOC_CON(i) ((i) * 4)
+#define DSUSGRF_SOC_CON_CNT 13
+#define DSUSGRF_DDR_HASH_CON(i) (0x240 + (i) * 4)
+#define DSUSGRF_DDR_HASH_CON_CNT 8
+
+/* PMUSGRF */
+#define PMU1SGRF_SOC_CON(n) ((n) * 4)
+
+/* SGRF */
+#define SGRF_SOC_CON(i) ((i) * 4)
+#define SGRF_FIREWALL_CON(i) (0x240 + (i) * 4)
+#define SGRF_FIREWALL_CON_CNT 32
+
+/* ddr firewall */
+#define FIREWALL_DDR_RGN(i) ((i) * 0x4)
+#define FIREWALL_DDR_RGN_CNT 16
+#define FIREWALL_DDR_MST(i) (0x40 + (i) * 0x4)
+#define FIREWALL_DDR_MST_CNT 42
+#define FIREWALL_DDR_CON 0xf0
+
+#define FIREWALL_SYSMEM_RGN(i) ((i) * 0x4)
+#define FIREWALL_SYSMEM_RGN_CNT 8
+#define FIREWALL_SYSMEM_MST(i) (0x40 + (i) * 0x4)
+#define FIREWALL_SYSMEM_MST_CNT 43
+#define FIREWALL_SYSMEM_CON 0xf0
+
+#define FIREWALL_DSU_RGN(i) ((i) * 0x4)
+#define FIREWALL_DSU_RGN_CNT 16
+#define FIREWALL_DSU_MST(i) (0x40 + (i) * 0x4)
+#define FIREWALL_DSU_MST_CNT 2
+#define FIREWALL_DSU_CON(i) (0xf0 + (i) * 4)
+#define FIREWALL_DSU_CON_CNT 4
+
+#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) << 16) | ((base_kb) / 4 & 0xff))
+
+void secure_timer_init(void);
+void sgrf_init(void);
+
+#endif /* SECURE_H */
diff --git a/plat/rockchip/rk3588/drivers/soc/soc.c b/plat/rockchip/rk3588/drivers/soc/soc.c
new file mode 100644
index 0000000..6db81ee
--- /dev/null
+++ b/plat/rockchip/rk3588/drivers/soc/soc.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#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 <rk3588_clk.h>
+#include <secure.h>
+#include <soc.h>
+
+#define RK3588_DEV_RNG0_BASE 0xf0000000
+#define RK3588_DEV_RNG0_SIZE 0x0ffff000
+
+const mmap_region_t plat_rk_mmap[] = {
+ MAP_REGION_FLAT(RK3588_DEV_RNG0_BASE, RK3588_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
+};
+
+void timer_hp_init(void)
+{
+ if ((mmio_read_32(TIMER_HP_BASE + TIMER_HP_CTRL) & 0x1) != 0)
+ return;
+
+ mmio_write_32(TIMER_HP_BASE + TIMER_HP_CTRL, 0x0);
+ dsb();
+ mmio_write_32(TIMER_HP_BASE + TIMER_HP_LOAD_COUNT0, 0xffffffff);
+ mmio_write_32(TIMER_HP_BASE + TIMER_HP_LOAD_COUNT1, 0xffffffff);
+ mmio_write_32(TIMER_HP_BASE + TIMER_HP_INT_EN, 0);
+ dsb();
+ mmio_write_32(TIMER_HP_BASE + TIMER_HP_CTRL, 0x1);
+}
+
+static void system_reset_init(void)
+{
+ /* enable wdt_ns0~4 trigger global reset and select first reset.
+ * enable tsadc trigger global reset and select first reset.
+ * enable global reset and wdt trigger pmu reset.
+ * select first reset trigger pmu reset.s
+ */
+ mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, 0xffdf);
+
+ /* enable wdt_s, wdt_ns reset */
+ mmio_write_32(BUSSGRF_BASE + SGRF_SOC_CON(2), 0x0c000c00);
+
+ /* reset width = 0xffff */
+ mmio_write_32(PMU1GRF_BASE + PMU1GRF_SOC_CON(1), 0xffffffff);
+
+ /* enable first/tsadc/wdt reset output */
+ mmio_write_32(PMU1SGRF_BASE + PMU1SGRF_SOC_CON(0), 0x00070007);
+
+ /* pmu1_grf pmu1_ioc hold */
+ mmio_write_32(PMU1GRF_BASE + PMU1GRF_SOC_CON(7), 0x30003000);
+
+ /* pmu1sgrf hold */
+ mmio_write_32(PMU1SGRF_BASE + PMU1SGRF_SOC_CON(14), 0x00200020);
+
+ /* select tsadc_shut_m0 ionmux*/
+ mmio_write_32(PMU0IOC_BASE + 0x0, 0x00f00020);
+}
+
+void plat_rockchip_soc_init(void)
+{
+ rockchip_clock_init();
+ secure_timer_init();
+ timer_hp_init();
+ system_reset_init();
+ sgrf_init();
+ rockchip_init_scmi_server();
+}
diff --git a/plat/rockchip/rk3588/drivers/soc/soc.h b/plat/rockchip/rk3588/drivers/soc/soc.h
new file mode 100644
index 0000000..9af179a
--- /dev/null
+++ b/plat/rockchip/rk3588/drivers/soc/soc.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SOC_H__
+#define __SOC_H__
+
+enum pll_id {
+ APLL_ID,
+ DPLL_ID,
+ GPLL_ID,
+ CPLL_ID,
+ NPLL_ID,
+ VPLL_ID,
+};
+
+enum pmu_pll_id {
+ PPLL_ID = 0,
+ HPLL_ID
+};
+
+enum cru_mode_con00 {
+ CLK_APLL,
+ CLK_DPLL,
+ CLK_CPLL,
+ CLK_GPLL,
+ CLK_REVSERVED,
+ CLK_NPLL,
+ CLK_VPLL,
+ CLK_USBPLL,
+};
+
+#define KHz 1000
+#define MHz (1000 * KHz)
+#define OSC_HZ (24 * MHz)
+
+/* CRU */
+#define GLB_SRST_FST_CFG_VAL 0xfdb9
+
+#define CRU_PLLS_CON(pll_id, i) (0x160 + (pll_id) * 0x20 + (i) * 0x4)
+#define CRU_PLL_CON(i) ((i) * 0x4)
+#define CRU_MODE_CON0 0x280
+#define CRU_CLKSEL_CON(i) ((i) * 0x4 + 0x300)
+#define CRU_CLKGATE_CON(i) ((i) * 0x4 + 0x800)
+#define CRU_CLKGATE_CON_CNT 78
+#define CRU_SOFTRST_CON(i) ((i) * 0x4 + 0xa00)
+#define CRU_GLB_CNT_TH 0xc00
+#define CRU_GLB_SRST_FST 0xc08
+#define CRU_GLB_SRST_SND 0xc0c
+#define CRU_GLB_RST_CON 0xc10
+#define CRU_GLB_RST_ST 0xc04
+#define CRU_SDIO_CON0 0xc24
+#define CRU_SDIO_CON1 0xc28
+#define CRU_SDMMC_CON0 0xc30
+#define CRU_SDMMC_CON1 0xc34
+#define CRU_AUTOCS_CON0(id) (0xd00 + (id) * 8)
+#define CRU_AUTOCS_CON1(id) (0xd04 + (id) * 8)
+
+#define CRU_AUTOCS_ID_CNT 74
+
+#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)
+
+#define CRU_BIGCPU02_RST_MSK 0x30
+#define CRU_BIGCPU13_RST_MSK 0x300
+
+#define PHPCRU_CLKGATE_CON 0x800
+#define PHPCRU_CLKGATE_CON_CNT 1
+
+#define SECURECRU_CLKGATE_CON(i) ((i) * 0x4 + 0x800)
+#define SECURECRU_CLKGATE_CON_CNT 4
+
+#define PMU1CRU_CLKGATE_CON_CNT 6
+
+/* CENTER GRF */
+#define CENTER_GRF_CON(i) ((i) * 4)
+
+/* PMU1GRF */
+#define PMU1GRF_SOC_CON(n) ((n) * 4)
+#define PMU1GRF_SOC_ST 0x60
+#define PMU1GRF_OS_REG(n) (0x200 + ((n) * 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)
+
+/* SYSGRF */
+#define SYS_GRF_NOC_CON(n) (0x100 + (n) * 4)
+#define SYS_GRF_SOC_CON(n) (0x300 + (n) * 4)
+#define SYS_GRF_SOC_STATUS(n) (0x380 + (n) * 4)
+
+#define SYS_GRF_LITTLE_CPUS_WFE 0xf
+#define SYS_GRF_CORE0_CPUS_WFE 0x30
+#define SYS_GRF_CORE1_CPUS_WFE 0xc0
+#define SYS_GRF_BIG_CPUS_WFE 0xf0
+#define SYS_GRF_LITTLE_CPUS_WFI 0xf00
+#define SYS_GRF_CORE0_CPUS_WFI 0x3000
+#define SYS_GRF_CORE1_CPUS_WFI 0xc000
+
+/* 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,
+};
+
+/* 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)
+
+#define STIMER0_CHN_BASE(n) (STIMER0_BASE + 0x20 * (n))
+#define STIMER1_CHN_BASE(n) (STIMER1_BASE + 0x20 * (n))
+
+/* cpu timer */
+#define TIMER_HP_REVISION 0x0
+#define TIMER_HP_CTRL 0x4
+#define TIMER_HP_INT_EN 0x8
+#define TIMER_HP_T24_GCD 0xc
+#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
+
+ /* 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
+
+/* DDRGRF */
+#define DDRGRF_CHA_CON(i) ((i) * 4)
+#define DDRGRF_CHB_CON(i) (0x30 + (i) * 4)
+
+#define DDR_CHN_CNT 4
+
+#endif /* __SOC_H__ */
diff --git a/plat/rockchip/rk3588/include/plat.ld.S b/plat/rockchip/rk3588/include/plat.ld.S
new file mode 100644
index 0000000..e3ea9cc
--- /dev/null
+++ b/plat/rockchip/rk3588/include/plat.ld.S
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#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/rk3588/include/plat_sip_calls.h b/plat/rockchip/rk3588/include/plat_sip_calls.h
new file mode 100644
index 0000000..bc4455f
--- /dev/null
+++ b/plat/rockchip/rk3588/include/plat_sip_calls.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#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/rk3588/include/platform_def.h b/plat/rockchip/rk3588/include/platform_def.h
new file mode 100644
index 0000000..5946af0
--- /dev/null
+++ b/plat/rockchip/rk3588/include/platform_def.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+#include <arch.h>
+#include <plat/common/common_def.h>
+
+#include <rk3588_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 1
+#define PLATFORM_CLUSTER0_CORE_COUNT 8
+#define PLATFORM_CLUSTER1_CORE_COUNT 0
+#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 8
+
+/*
+ * 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 (0x0)
+#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/rk3588/plat_sip_calls.c b/plat/rockchip/rk3588/plat_sip_calls.c
new file mode 100644
index 0000000..496e8d7
--- /dev/null
+++ b/plat/rockchip/rk3588/plat_sip_calls.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#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/rk3588/platform.mk b/plat/rockchip/rk3588/platform.mk
new file mode 100644
index 0000000..07eda40
--- /dev/null
+++ b/plat/rockchip/rk3588/platform.mk
@@ -0,0 +1,98 @@
+#
+# Copyright (c) 2024, Rockchip, Inc. 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 lib/libfdt/libfdt.mk
+include lib/xlat_tables_v2/xlat_tables.mk
+
+# GIC-600 configuration
+GICV3_IMPL := GIC600
+GICV3_SUPPORT_GIC600 := 1
+
+# Include GICv3 driver files
+include drivers/arm/gic/v3/gicv3.mk
+
+PLAT_INCLUDES := -Iinclude/plat/common \
+ -Idrivers/arm/gic/v3/ \
+ -Idrivers/scmi-msg/ \
+ -I${RK_PLAT_COMMON}/ \
+ -I${RK_PLAT_COMMON}/drivers/pmu/ \
+ -I${RK_PLAT_COMMON}/drivers/parameter/ \
+ -I${RK_PLAT_COMMON}/include/ \
+ -I${RK_PLAT_COMMON}/pmusram/ \
+ -I${RK_PLAT_COMMON}/scmi/ \
+ -I${RK_PLAT_SOC}/ \
+ -I${RK_PLAT_SOC}/drivers/pmu/ \
+ -I${RK_PLAT_SOC}/drivers/scmi/ \
+ -I${RK_PLAT_SOC}/drivers/secure/ \
+ -I${RK_PLAT_SOC}/drivers/soc/ \
+ -I${RK_PLAT_SOC}/include/
+
+RK_GIC_SOURCES := ${GICV3_SOURCES} \
+ plat/common/plat_gicv3.c \
+ ${RK_PLAT}/common/rockchip_gicv3.c
+
+PLAT_BL_COMMON_SOURCES := ${XLAT_TABLES_LIB_SRCS} \
+ common/desc_image_load.c \
+ plat/common/aarch64/crash_console_helpers.S \
+ lib/bl_aux_params/bl_aux_params.c \
+ 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/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_a55.S \
+ lib/cpus/aarch64/cortex_a76.S \
+ ${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}/params_setup.c \
+ ${RK_PLAT_COMMON}/pmusram/cpus_on_fixed_addr.S \
+ ${RK_PLAT_COMMON}/rockchip_sip_svc.c \
+ ${RK_PLAT_COMMON}/scmi/scmi.c \
+ ${RK_PLAT_COMMON}/scmi/scmi_clock.c \
+ ${RK_PLAT_COMMON}/scmi/scmi_rstd.c \
+ ${RK_PLAT_SOC}/plat_sip_calls.c \
+ ${RK_PLAT_SOC}/drivers/secure/secure.c \
+ ${RK_PLAT_SOC}/drivers/soc/soc.c \
+ ${RK_PLAT_SOC}/drivers/pmu/pmu.c \
+ ${RK_PLAT_SOC}/drivers/pmu/pm_pd_regs.c \
+ ${RK_PLAT_SOC}/drivers/scmi/rk3588_clk.c \
+ ${RK_PLAT_SOC}/drivers/scmi/rk3588_rstd.c
+
+CTX_INCLUDE_AARCH32_REGS := 0
+ENABLE_PLAT_COMPAT := 0
+MULTI_CONSOLE_API := 1
+ERRATA_A55_1530923 := 1
+
+# System coherency is managed in hardware
+HW_ASSISTED_COHERENCY := 1
+
+# When building for systems with hardware-assisted coherency, there's no need to
+# use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too.
+USE_COHERENT_MEM := 0
+
+ENABLE_SPE_FOR_LOWER_ELS := 0
+
+$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
+$(eval $(call add_define,PLAT_SKIP_DFS_TLB_DCACHE_MAINTENANCE))
diff --git a/plat/rockchip/rk3588/rk3588_def.h b/plat/rockchip/rk3588/rk3588_def.h
new file mode 100644
index 0000000..412495a
--- /dev/null
+++ b/plat/rockchip/rk3588/rk3588_def.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLAT_DEF_H__
+#define __PLAT_DEF_H__
+
+#define SIZE_K(n) ((n) * 1024)
+
+#define WITH_16BITS_WMSK(bits) (0xffff0000 | (bits))
+
+/* Special value used to verify platform parameters from BL2 to BL3-1 */
+#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL
+
+#define UMCTL0_BASE 0xf7000000
+#define UMCTL1_BASE 0xf8000000
+#define UMCTL2_BASE 0xf9000000
+#define UMCTL3_BASE 0xfa000000
+
+#define GIC600_BASE 0xfe600000
+#define GIC600_SIZE SIZE_K(64)
+
+#define DAPLITE_BASE 0xfd100000
+#define PMU0SGRF_BASE 0xfd580000
+#define PMU1SGRF_BASE 0xfd582000
+#define BUSSGRF_BASE 0xfd586000
+#define DSUSGRF_BASE 0xfd587000
+#define PMU0GRF_BASE 0xfd588000
+#define PMU1GRF_BASE 0xfd58a000
+
+#define SYSGRF_BASE 0xfd58c000
+#define BIGCORE0GRF_BASE 0xfd590000
+#define BIGCORE1GRF_BASE 0xfd592000
+#define LITCOREGRF_BASE 0xfd594000
+#define DSUGRF_BASE 0xfd598000
+#define DDR01GRF_BASE 0xfd59c000
+#define DDR23GRF_BASE 0xfd59d000
+#define CENTERGRF_BASE 0xfd59e000
+#define GPUGRF_BASE 0xfd5a0000
+#define NPUGRF_BASE 0xfd5a2000
+#define USBGRF_BASE 0xfd5ac000
+#define PHPGRF_BASE 0xfd5b0000
+#define PCIE3PHYGRF_BASE 0xfd5b8000
+#define USB2PHY0_GRF_BASE 0xfd5d0000
+#define USB2PHY1_GRF_BASE 0xfd5d4000
+#define USB2PHY2_GRF_BASE 0xfd5d8000
+#define USB2PHY3_GRF_BASE 0xfd5dc000
+
+#define PMU0IOC_BASE 0xfd5f0000
+#define PMU1IOC_BASE 0xfd5f4000
+#define BUSIOC_BASE 0xfd5f8000
+#define VCCIO1_4_IOC_BASE 0xfd5f9000
+#define VCCIO3_5_IOC_BASE 0xfd5fa000
+#define VCCIO2_IOC_BASE 0xfd5fb000
+#define VCCIO6_IOC_BASE 0xfd5fc000
+
+#define SRAM_BASE 0xff000000
+#define PMUSRAM_BASE 0xff100000
+#define PMUSRAM_SIZE SIZE_K(128)
+#define PMUSRAM_RSIZE SIZE_K(64)
+
+#define CRU_BASE 0xfd7c0000
+#define PHP_CRU_BASE 0xfd7c8000
+#define SCRU_BASE 0xfd7d0000
+#define BUSSCRU_BASE 0xfd7d8000
+#define PMU1SCRU_BASE 0xfd7e0000
+#define PMU1CRU_BASE 0xfd7f0000
+
+#define DDR0CRU_BASE 0xfd800000
+#define DDR1CRU_BASE 0xfd804000
+#define DDR2CRU_BASE 0xfd808000
+#define DDR3CRU_BASE 0xfd80c000
+
+#define BIGCORE0CRU_BASE 0xfd810000
+#define BIGCORE1CRU_BASE 0xfd812000
+#define LITCRU_BASE 0xfd814000
+#define DSUCRU_BASE 0xfd818000
+
+#define I2C0_BASE 0xfd880000
+#define UART0_BASE 0xfd890000
+#define GPIO0_BASE 0xfd8a0000
+#define PWM0_BASE 0xfd8b0000
+#define PMUPVTM_BASE 0xfd8c0000
+#define TIMER_HP_BASE 0xfd8c8000
+#define PMU0_BASE 0xfd8d0000
+#define PMU1_BASE 0xfd8d4000
+#define PMU2_BASE 0xfd8d8000
+#define PMU_BASE PMU0_BASE
+#define PMUWDT_BASE 0xfd8e0000
+#define PMUTIMER_BASE 0xfd8f0000
+#define OSC_CHK_BASE 0xfd9b0000
+#define VOP_BASE 0xfdd90000
+#define HDMIRX_BASE 0xfdee0000
+
+#define MSCH0_BASE 0xfe000000
+#define MSCH1_BASE 0xfe002000
+#define MSCH2_BASE 0xfe004000
+#define MSCH3_BASE 0xfe006000
+#define FIREWALL_DSU_BASE 0xfe010000
+#define FIREWALL_DDR_BASE 0xfe030000
+#define FIREWALL_SYSMEM_BASE 0xfe038000
+#define DDRPHY0_BASE 0xfe0c0000
+#define DDRPHY1_BASE 0xfe0d0000
+#define DDRPHY2_BASE 0xfe0e0000
+#define DDRPHY3_BASE 0xfe0f0000
+#define TIMER_DDR_BASE 0xfe118000
+#define KEYLADDER_BASE 0xfe380000
+#define CRYPTO_S_BASE 0xfe390000
+#define OTP_S_BASE 0xfe3a0000
+#define DCF_BASE 0xfe3c0000
+#define STIMER0_BASE 0xfe3d0000
+#define WDT_S_BASE 0xfe3e0000
+#define CRYPTO_S_BY_KEYLAD_BASE 0xfe420000
+#define NSTIMER0_BASE 0xfeae0000
+#define NSTIMER1_BASE 0xfeae8000
+#define WDT_NS_BASE 0xfeaf0000
+
+#define UART1_BASE 0xfeb40000
+#define UART2_BASE 0xfeb50000
+#define UART3_BASE 0xfeb60000
+#define UART4_BASE 0xfeb70000
+#define UART5_BASE 0xfeb80000
+#define UART6_BASE 0xfeb90000
+#define UART7_BASE 0xfeba0000
+#define UART8_BASE 0xfebb0000
+#define UART9_BASE 0xfebc0000
+
+#define GPIO1_BASE 0xfec20000
+#define GPIO2_BASE 0xfec30000
+#define GPIO3_BASE 0xfec40000
+#define GPIO4_BASE 0xfec50000
+
+#define MAILBOX1_BASE 0xfec70000
+#define OTP_NS_BASE 0xfecc0000
+#define INTMUX0_DDR_BASE 0Xfecf8000
+#define INTMUX1_DDR_BASE 0Xfecfc000
+#define STIMER1_BASE 0xfed30000
+
+/**************************************************************************
+ * sys sram allocation
+ **************************************************************************/
+#define SRAM_ENTRY_BASE SRAM_BASE
+#define SRAM_PMUM0_SHMEM_BASE (SRAM_ENTRY_BASE + SIZE_K(3))
+#define SRAM_LD_BASE (SRAM_ENTRY_BASE + SIZE_K(4))
+#define SRAM_LD_SIZE SIZE_K(64)
+
+#define SRAM_LD_SP (SRAM_LD_BASE + SRAM_LD_SIZE -\
+ 128)
+
+/**************************************************************************
+ * share mem region allocation: 1M~2M
+ **************************************************************************/
+#define DDR_SHARE_MEM 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
+
+/**************************************************************************
+ * UART related constants
+ **************************************************************************/
+#define RK_DBG_UART_BASE UART2_BASE
+#define RK_DBG_UART_BAUDRATE 1500000
+#define RK_DBG_UART_CLOCK 24000000
+
+/******************************************************************************
+ * System counter frequency related constants
+ ******************************************************************************/
+#define SYS_COUNTER_FREQ_IN_TICKS 24000000
+#define SYS_COUNTER_FREQ_IN_MHZ 24
+
+/******************************************************************************
+ * GIC-600 & interrupt handling related constants
+ ******************************************************************************/
+
+/* Base rk_platform compatible GIC memory map */
+#define PLAT_GICD_BASE GIC600_BASE
+#define PLAT_GICC_BASE 0
+#define PLAT_GICR_BASE (GIC600_BASE + 0x80000)
+#define PLAT_GICITS0_BASE 0xfe640000
+#define PLAT_GICITS1_BASE 0xfe660000
+
+/******************************************************************************
+ * sgi, ppi
+ ******************************************************************************/
+#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 RK_IRQ_SEC_PHY_TIMER 29
+
+/*
+ * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
+ * terminology. On a GICv2 system or mode, the lists will be merged and treated
+ * as Group 0 interrupts.
+ */
+
+#define PLAT_RK_GICV3_G1S_IRQS \
+ INTR_PROP_DESC(RK_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \
+ INTR_GROUP1S, GIC_INTR_CFG_LEVEL)
+
+#define PLAT_RK_GICV3_G0_IRQS \
+ INTR_PROP_DESC(RK_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \
+ INTR_GROUP0, GIC_INTR_CFG_LEVEL)
+
+/******************************************************************************
+ * pm reg region memory
+ ******************************************************************************/
+#define ROCKCHIP_PM_REG_REGION_MEM_SIZE SIZE_K(4)
+
+#endif /* __PLAT_DEF_H__ */
diff --git a/plat/rpi/rpi4/platform.mk b/plat/rpi/rpi4/platform.mk
index cbfa6f2..c39a587 100644
--- a/plat/rpi/rpi4/platform.mk
+++ b/plat/rpi/rpi4/platform.mk
@@ -31,6 +31,7 @@
plat/common/plat_psci_common.c \
plat/rpi/common/rpi3_topology.c \
common/fdt_fixup.c \
+ common/fdt_wrappers.c \
${LIBFDT_SRCS} \
${GICV2_SOURCES}
diff --git a/plat/st/stm32mp2/bl2_plat_setup.c b/plat/st/stm32mp2/bl2_plat_setup.c
index 724209a..edada72 100644
--- a/plat/st/stm32mp2/bl2_plat_setup.c
+++ b/plat/st/stm32mp2/bl2_plat_setup.c
@@ -4,30 +4,266 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <assert.h>
#include <cdefs.h>
#include <stdint.h>
#include <common/debug.h>
+#include <common/desc_image_load.h>
+#include <drivers/clk.h>
+#include <drivers/mmc.h>
+#include <drivers/st/regulator_fixed.h>
+#include <drivers/st/stm32mp2_ddr_helpers.h>
+#include <lib/fconf/fconf.h>
+#include <lib/fconf/fconf_dyn_cfg_getter.h>
+#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
#include <platform_def.h>
#include <stm32mp_common.h>
+#include <stm32mp_dt.h>
+
+#define BOOT_CTX_ADDR 0x0e000020UL
+
+static void print_reset_reason(void)
+{
+ uint32_t rstsr = mmio_read_32(stm32mp_rcc_base() + RCC_C1BOOTRSTSCLRR);
+
+ if (rstsr == 0U) {
+ WARN("Reset reason unknown\n");
+ return;
+ }
+
+ INFO("Reset reason (0x%x):\n", rstsr);
+
+ if ((rstsr & RCC_C1BOOTRSTSCLRR_PADRSTF) == 0U) {
+ if ((rstsr & RCC_C1BOOTRSTSCLRR_STBYC1RSTF) != 0U) {
+ INFO("System exits from Standby for CA35\n");
+ return;
+ }
+
+ if ((rstsr & RCC_C1BOOTRSTSCLRR_D1STBYRSTF) != 0U) {
+ INFO("D1 domain exits from DStandby\n");
+ return;
+ }
+ }
+
+ if ((rstsr & RCC_C1BOOTRSTSCLRR_PORRSTF) != 0U) {
+ INFO(" Power-on Reset (rst_por)\n");
+ return;
+ }
+
+ if ((rstsr & RCC_C1BOOTRSTSCLRR_BORRSTF) != 0U) {
+ INFO(" Brownout Reset (rst_bor)\n");
+ return;
+ }
+
+ if ((rstsr & RCC_C1BOOTRSTSSETR_SYSC2RSTF) != 0U) {
+ INFO(" System reset (SYSRST) by M33\n");
+ return;
+ }
+
+ if ((rstsr & RCC_C1BOOTRSTSSETR_SYSC1RSTF) != 0U) {
+ INFO(" System reset (SYSRST) by A35\n");
+ return;
+ }
+
+ if ((rstsr & RCC_C1BOOTRSTSCLRR_HCSSRSTF) != 0U) {
+ INFO(" Clock failure on HSE\n");
+ return;
+ }
+
+ if ((rstsr & RCC_C1BOOTRSTSCLRR_IWDG1SYSRSTF) != 0U) {
+ INFO(" IWDG1 system reset (rst_iwdg1)\n");
+ return;
+ }
+
+ if ((rstsr & RCC_C1BOOTRSTSCLRR_IWDG2SYSRSTF) != 0U) {
+ INFO(" IWDG2 system reset (rst_iwdg2)\n");
+ return;
+ }
+
+ if ((rstsr & RCC_C1BOOTRSTSCLRR_IWDG3SYSRSTF) != 0U) {
+ INFO(" IWDG3 system reset (rst_iwdg3)\n");
+ return;
+ }
+
+ if ((rstsr & RCC_C1BOOTRSTSCLRR_IWDG4SYSRSTF) != 0U) {
+ INFO(" IWDG4 system reset (rst_iwdg4)\n");
+ return;
+ }
+
+ if ((rstsr & RCC_C1BOOTRSTSCLRR_IWDG5SYSRSTF) != 0U) {
+ INFO(" IWDG5 system reset (rst_iwdg5)\n");
+ return;
+ }
+
+ if ((rstsr & RCC_C1BOOTRSTSCLRR_C1P1RSTF) != 0U) {
+ INFO(" A35 processor core 1 reset\n");
+ return;
+ }
+
+ if ((rstsr & RCC_C1BOOTRSTSCLRR_PADRSTF) != 0U) {
+ INFO(" Pad Reset from NRST\n");
+ return;
+ }
+
+ if ((rstsr & RCC_C1BOOTRSTSCLRR_VCORERSTF) != 0U) {
+ INFO(" Reset due to a failure of VDD_CORE\n");
+ return;
+ }
+
+ if ((rstsr & RCC_C1BOOTRSTSCLRR_C1RSTF) != 0U) {
+ INFO(" A35 processor reset\n");
+ return;
+ }
+
+ ERROR(" Unidentified reset reason\n");
+}
void bl2_el3_early_platform_setup(u_register_t arg0 __unused,
u_register_t arg1 __unused,
u_register_t arg2 __unused,
u_register_t arg3 __unused)
{
+ stm32mp_save_boot_ctx_address(BOOT_CTX_ADDR);
}
void bl2_platform_setup(void)
{
}
+static void reset_backup_domain(void)
+{
+ uintptr_t pwr_base = stm32mp_pwr_base();
+ uintptr_t rcc_base = stm32mp_rcc_base();
+
+ /*
+ * Disable the backup domain write protection.
+ * The protection is enable at each reset by hardware
+ * and must be disabled by software.
+ */
+ mmio_setbits_32(pwr_base + PWR_BDCR1, PWR_BDCR1_DBD3P);
+
+ while ((mmio_read_32(pwr_base + PWR_BDCR1) & PWR_BDCR1_DBD3P) == 0U) {
+ ;
+ }
+
+ /* Reset backup domain on cold boot cases */
+ if ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_RTCCKEN) == 0U) {
+ mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST);
+
+ while ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_VSWRST) == 0U) {
+ ;
+ }
+
+ mmio_clrbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST);
+ }
+}
+
void bl2_el3_plat_arch_setup(void)
{
+ const char *board_model;
+ boot_api_context_t *boot_context =
+ (boot_api_context_t *)stm32mp_get_boot_ctx_address();
+
if (stm32_otp_probe() != 0U) {
EARLY_ERROR("OTP probe failed\n");
panic();
}
+
+ mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
+ BL_CODE_END - BL_CODE_BASE,
+ MT_CODE | MT_SECURE);
+
+ configure_mmu();
+
+ if (dt_open_and_check(STM32MP_DTB_BASE) < 0) {
+ panic();
+ }
+
+ reset_backup_domain();
+
+ /*
+ * Initialize DDR sub-system clock. This needs to be done before enabling DDR PLL (PLL2),
+ * and so before stm32mp2_clk_init().
+ */
+ ddr_sub_system_clk_init();
+
+ if (stm32mp2_clk_init() < 0) {
+ panic();
+ }
+
+ stm32_save_boot_info(boot_context);
+
+ if (stm32mp_uart_console_setup() != 0) {
+ goto skip_console_init;
+ }
+
+ stm32mp_print_cpuinfo();
+
+ board_model = dt_get_board_model();
+ if (board_model != NULL) {
+ NOTICE("Model: %s\n", board_model);
+ }
+
+ stm32mp_print_boardinfo();
+
+ print_reset_reason();
+
+skip_console_init:
+ if (fixed_regulator_register() != 0) {
+ panic();
+ }
+
+ fconf_populate("TB_FW", STM32MP_DTB_BASE);
+
+ stm32mp_io_setup();
+}
+
+/*******************************************************************************
+ * This function can be used by the platforms to update/use image
+ * information for given `image_id`.
+ ******************************************************************************/
+int bl2_plat_handle_post_image_load(unsigned int image_id)
+{
+ int err = 0;
+ bl_mem_params_node_t *bl_mem_params __maybe_unused = get_bl_mem_params_node(image_id);
+
+ assert(bl_mem_params != NULL);
+
+#if STM32MP_SDMMC || STM32MP_EMMC
+ /*
+ * Invalidate remaining data read from MMC but not flushed by load_image_flush().
+ * We take the worst case which is 2 MMC blocks.
+ */
+ if ((image_id != FW_CONFIG_ID) &&
+ ((bl_mem_params->image_info.h.attr & IMAGE_ATTRIB_SKIP_LOADING) == 0U)) {
+ inv_dcache_range(bl_mem_params->image_info.image_base +
+ bl_mem_params->image_info.image_size,
+ 2U * MMC_BLOCK_SIZE);
+ }
+#endif /* STM32MP_SDMMC || STM32MP_EMMC */
+
+ switch (image_id) {
+ case FW_CONFIG_ID:
+ /* Set global DTB info for fixed fw_config information */
+ set_config_info(STM32MP_FW_CONFIG_BASE, ~0UL, STM32MP_FW_CONFIG_MAX_SIZE,
+ FW_CONFIG_ID);
+ fconf_populate("FW_CONFIG", STM32MP_FW_CONFIG_BASE);
+
+ /*
+ * After this step, the BL2 device tree area will be overwritten
+ * with BL31 binary, no other data should be read from BL2 DT.
+ */
+
+ break;
+
+ default:
+ /* Do nothing in default case */
+ break;
+ }
+
+ return err;
}
diff --git a/plat/st/stm32mp2/include/boot_api.h b/plat/st/stm32mp2/include/boot_api.h
index d3bed76..580a65b 100644
--- a/plat/st/stm32mp2/include/boot_api.h
+++ b/plat/st/stm32mp2/include/boot_api.h
@@ -86,7 +86,7 @@
/* Image Header related definitions */
/* Definition of header version */
-#define BOOT_API_HEADER_VERSION 0x00020000U
+#define BOOT_API_HEADER_VERSION 0x00020200U
/*
* Magic number used to detect header in memory
diff --git a/plat/st/stm32mp2/include/plat_tbbr_img_def.h b/plat/st/stm32mp2/include/plat_tbbr_img_def.h
new file mode 100644
index 0000000..5dfd41f
--- /dev/null
+++ b/plat/st/stm32mp2/include/plat_tbbr_img_def.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2024, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_TBBR_IMG_DEF_H
+#define PLAT_TBBR_IMG_DEF_H
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/* Undef the existing values */
+#undef BKUP_FWU_METADATA_IMAGE_ID
+#undef FWU_METADATA_IMAGE_ID
+#undef FW_CONFIG_ID
+#undef ENC_IMAGE_ID
+#undef GPT_IMAGE_ID
+#undef NT_FW_CONFIG_ID
+#undef SOC_FW_CONFIG_ID
+#undef TB_FW_CONFIG_ID
+#undef HW_CONFIG_ID
+#undef TRUSTED_BOOT_FW_CERT_ID
+#undef SOC_FW_CONTENT_CERT_ID
+#undef BL32_EXTRA1_IMAGE_ID
+#undef TOS_FW_CONFIG_ID
+
+/* Define the STM32MP2 used ID */
+#define FW_CONFIG_ID U(1)
+#define HW_CONFIG_ID U(2)
+#define ENC_IMAGE_ID U(6)
+#define BL32_EXTRA1_IMAGE_ID U(8)
+#define FWU_METADATA_IMAGE_ID U(12)
+#define BKUP_FWU_METADATA_IMAGE_ID U(13)
+#define TOS_FW_CONFIG_ID U(16)
+#define NT_FW_CONFIG_ID U(18)
+#define SOC_FW_CONFIG_ID U(19)
+#define TB_FW_CONFIG_ID U(20)
+#define TRUSTED_BOOT_FW_CERT_ID U(21)
+#define SOC_FW_CONTENT_CERT_ID U(23)
+#define STM32MP_CONFIG_CERT_ID U(24)
+#define GPT_IMAGE_ID U(25)
+
+/* Increase the MAX_NUMBER_IDS to match the authentication pool required */
+#define MAX_NUMBER_IDS U(26)
+
+#endif /* PLAT_TBBR_IMG_DEF_H */
+
diff --git a/plat/st/stm32mp2/include/platform_def.h b/plat/st/stm32mp2/include/platform_def.h
index 404c384..0f22a93 100644
--- a/plat/st/stm32mp2/include/platform_def.h
+++ b/plat/st/stm32mp2/include/platform_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2023-2024, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -61,6 +61,20 @@
#define BL2_LIMIT (STM32MP_BL2_BASE + \
STM32MP_BL2_SIZE)
+#define BL2_RO_BASE STM32MP_BL2_RO_BASE
+#define BL2_RO_LIMIT (STM32MP_BL2_RO_BASE + \
+ STM32MP_BL2_RO_SIZE)
+
+#define BL2_RW_BASE STM32MP_BL2_RW_BASE
+#define BL2_RW_LIMIT (STM32MP_BL2_RW_BASE + \
+ STM32MP_BL2_RW_SIZE)
+
+/*******************************************************************************
+ * BL31 specific defines.
+ ******************************************************************************/
+#define BL31_BASE 0
+#define BL31_LIMIT STM32MP_BL31_SIZE
+
/*******************************************************************************
* BL33 specific defines.
******************************************************************************/
diff --git a/plat/st/stm32mp2/include/stm32mp2_private.h b/plat/st/stm32mp2/include/stm32mp2_private.h
index e1403d2..2ab5001 100644
--- a/plat/st/stm32mp2/include/stm32mp2_private.h
+++ b/plat/st/stm32mp2/include/stm32mp2_private.h
@@ -7,6 +7,10 @@
#ifndef STM32MP2_PRIVATE_H
#define STM32MP2_PRIVATE_H
+void configure_mmu(void);
+
+uint32_t stm32mp_syscfg_get_chip_dev_id(void);
+
/* Wrappers for OTP / BSEC functions */
static inline uint32_t stm32_otp_probe(void)
{
diff --git a/plat/st/stm32mp2/plat_bl2_mem_params_desc.c b/plat/st/stm32mp2/plat_bl2_mem_params_desc.c
index 630cc84..0ef522e 100644
--- a/plat/st/stm32mp2/plat_bl2_mem_params_desc.c
+++ b/plat/st/stm32mp2/plat_bl2_mem_params_desc.c
@@ -1,10 +1,14 @@
/*
- * Copyright (c) 2023, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2023-2024, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <common/bl_common.h>
#include <common/desc_image_load.h>
+#include <plat/common/platform.h>
+
+#include <platform_def.h>
/*******************************************************************************
* Following descriptor provides BL image/ep information that gets used
@@ -15,6 +19,21 @@
* the next executable image id.
******************************************************************************/
static bl_mem_params_node_t bl2_mem_params_descs[] = {
+ /* Fill FW_CONFIG related information if it exists */
+ {
+ .image_id = FW_CONFIG_ID,
+ SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+ VERSION_2, entry_point_info_t,
+ SECURE | NON_EXECUTABLE),
+ SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+ VERSION_2, image_info_t,
+ IMAGE_ATTRIB_PLAT_SETUP),
+
+ .image_info.image_base = STM32MP_FW_CONFIG_BASE,
+ .image_info.image_max_size = STM32MP_FW_CONFIG_MAX_SIZE,
+
+ .next_handoff_image_id = INVALID_IMAGE_ID,
+ },
};
REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/st/stm32mp2/platform.mk b/plat/st/stm32mp2/platform.mk
index d9a4d79..eacbd96 100644
--- a/plat/st/stm32mp2/platform.mk
+++ b/plat/st/stm32mp2/platform.mk
@@ -13,6 +13,7 @@
CRASH_REPORTING := 1
ENABLE_PIE := 1
PROGRAMMABLE_RESET_ADDRESS := 1
+BL2_IN_XIP_MEM := 1
# Default Device tree
DTB_FILE_NAME ?= stm32mp257f-ev1.dtb
@@ -24,7 +25,7 @@
STM32_HEADER_VERSION_MINOR := 2
# Set load address for serial boot devices
-DWL_BUFFER_BASE ?= 0x87000000
+DWL_BUFFER_BASE ?= 0x87000000
# Device tree
BL2_DTSI := stm32mp25-bl2.dtsi
@@ -35,9 +36,32 @@
STM32_LD_FILE := plat/st/stm32mp2/${ARCH}/stm32mp2.ld.S
STM32_BINARY_MAPPING := plat/st/stm32mp2/${ARCH}/stm32mp2.S
+STM32MP_FW_CONFIG_NAME := $(patsubst %.dtb,%-fw-config.dtb,$(DTB_FILE_NAME))
+STM32MP_FW_CONFIG := ${BUILD_PLAT}/fdts/$(STM32MP_FW_CONFIG_NAME)
+FDT_SOURCES += $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(STM32MP_FW_CONFIG_NAME)))
+# Add the FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_FW_CONFIG},--fw-config))
+
+# Enable flags for C files
+$(eval $(call assert_booleans,\
+ $(sort \
+ STM32MP25 \
+)))
+
+$(eval $(call assert_numerics,\
+ $(sort \
+ PLAT_PARTITION_MAX_ENTRIES \
+ STM32_HEADER_VERSION_MAJOR \
+ STM32_TF_A_COPIES \
+)))
+
$(eval $(call add_defines,\
$(sort \
DWL_BUFFER_BASE \
+ PLAT_PARTITION_MAX_ENTRIES \
+ PLAT_TBBR_IMG_DEF \
+ STM32_TF_A_COPIES \
+ STM32MP25 \
)))
# STM32MP2x is based on Cortex-A35, which is Armv8.0, and does not support BTI
@@ -51,17 +75,28 @@
PLAT_BL_COMMON_SOURCES += drivers/st/uart/${ARCH}/stm32_console.S
PLAT_BL_COMMON_SOURCES += plat/st/stm32mp2/${ARCH}/stm32mp2_helper.S
+PLAT_BL_COMMON_SOURCES += plat/st/stm32mp2/stm32mp2_private.c
+
PLAT_BL_COMMON_SOURCES += drivers/st/bsec/bsec3.c \
- drivers/st/reset/stm32mp2_reset.c
+ drivers/st/reset/stm32mp2_reset.c \
+ plat/st/stm32mp2/stm32mp2_syscfg.c
PLAT_BL_COMMON_SOURCES += drivers/st/clk/clk-stm32-core.c \
drivers/st/clk/clk-stm32mp2.c
BL2_SOURCES += plat/st/stm32mp2/plat_bl2_mem_params_desc.c
+
BL2_SOURCES += plat/st/stm32mp2/bl2_plat_setup.c
+ifneq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC}),)
+BL2_SOURCES += drivers/st/mmc/stm32_sdmmc2.c
+endif
+
ifeq (${STM32MP_USB_PROGRAMMER},1)
BL2_SOURCES += plat/st/stm32mp2/stm32mp2_usb_dfu.c
endif
+BL2_SOURCES += drivers/st/ddr/stm32mp2_ddr_helpers.c
+
+# Compilation rules
include plat/st/common/common_rules.mk
diff --git a/plat/st/stm32mp2/stm32mp2_def.h b/plat/st/stm32mp2/stm32mp2_def.h
index d65fcea..81fdaae 100644
--- a/plat/st/stm32mp2/stm32mp2_def.h
+++ b/plat/st/stm32mp2/stm32mp2_def.h
@@ -12,6 +12,10 @@
#include <drivers/st/bsec.h>
#endif
#include <drivers/st/stm32mp25_rcc.h>
+#ifndef __ASSEMBLER__
+#include <drivers/st/stm32mp2_clk.h>
+#endif
+#include <drivers/st/stm32mp2_pwr.h>
#include <dt-bindings/clock/stm32mp25-clks.h>
#include <dt-bindings/clock/stm32mp25-clksrc.h>
#include <dt-bindings/gpio/stm32-gpio.h>
@@ -26,14 +30,48 @@
#endif
/*******************************************************************************
+ * CHIP ID
+ ******************************************************************************/
+#define STM32MP2_CHIP_ID U(0x505)
+
+#define STM32MP251A_PART_NB U(0x400B3E6D)
+#define STM32MP251C_PART_NB U(0x000B306D)
+#define STM32MP251D_PART_NB U(0xC00B3E6D)
+#define STM32MP251F_PART_NB U(0x800B306D)
+#define STM32MP253A_PART_NB U(0x400B3E0C)
+#define STM32MP253C_PART_NB U(0x000B300C)
+#define STM32MP253D_PART_NB U(0xC00B3E0C)
+#define STM32MP253F_PART_NB U(0x800B300C)
+#define STM32MP255A_PART_NB U(0x40082E00)
+#define STM32MP255C_PART_NB U(0x00082000)
+#define STM32MP255D_PART_NB U(0xC0082E00)
+#define STM32MP255F_PART_NB U(0x80082000)
+#define STM32MP257A_PART_NB U(0x40002E00)
+#define STM32MP257C_PART_NB U(0x00002000)
+#define STM32MP257D_PART_NB U(0xC0002E00)
+#define STM32MP257F_PART_NB U(0x80002000)
+
+#define STM32MP2_REV_A U(0x08)
+#define STM32MP2_REV_B U(0x10)
+#define STM32MP2_REV_X U(0x12)
+#define STM32MP2_REV_Y U(0x11)
+#define STM32MP2_REV_Z U(0x09)
+
+/*******************************************************************************
+ * PACKAGE ID
+ ******************************************************************************/
+#define STM32MP25_PKG_CUSTOM U(0)
+#define STM32MP25_PKG_AL_VFBGA361 U(1)
+#define STM32MP25_PKG_AK_VFBGA424 U(3)
+#define STM32MP25_PKG_AI_TFBGA436 U(5)
+#define STM32MP25_PKG_UNKNOWN U(7)
+
+/*******************************************************************************
* STM32MP2 memory map related constants
******************************************************************************/
#define STM32MP_SYSRAM_BASE U(0x0E000000)
#define STM32MP_SYSRAM_SIZE U(0x00040000)
-#define STM32MP_SEC_SYSRAM_BASE STM32MP_SYSRAM_BASE
-#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 */
@@ -49,28 +87,38 @@
/* Section used inside TF binaries */
#define STM32MP_PARAM_LOAD_SIZE U(0x00002400) /* 9 KB for param */
-/* 512 Octets reserved for header */
+/* 512 Bytes reserved for header */
#define STM32MP_HEADER_SIZE U(0x00000200)
-#define STM32MP_HEADER_BASE (STM32MP_SEC_SYSRAM_BASE + \
+#define STM32MP_HEADER_BASE (STM32MP_SYSRAM_BASE + \
STM32MP_PARAM_LOAD_SIZE)
/* round_up(STM32MP_PARAM_LOAD_SIZE + STM32MP_HEADER_SIZE, PAGE_SIZE) */
#define STM32MP_HEADER_RESERVED_SIZE U(0x3000)
-#define STM32MP_BINARY_BASE (STM32MP_SEC_SYSRAM_BASE + \
+#define STM32MP_BINARY_BASE (STM32MP_SYSRAM_BASE + \
STM32MP_PARAM_LOAD_SIZE + \
STM32MP_HEADER_SIZE)
-#define STM32MP_BINARY_SIZE (STM32MP_SEC_SYSRAM_SIZE - \
+#define STM32MP_BINARY_SIZE (STM32MP_SYSRAM_SIZE - \
(STM32MP_PARAM_LOAD_SIZE + \
STM32MP_HEADER_SIZE))
-#define STM32MP_BL2_SIZE U(0x0002A000) /* 168 KB for BL2 */
+#define STM32MP_BL2_RO_SIZE U(0x00020000) /* 128 KB */
+#define STM32MP_BL2_SIZE U(0x00029000) /* 164 KB for BL2 */
-#define STM32MP_BL2_BASE (STM32MP_SEC_SYSRAM_BASE + \
- STM32MP_SEC_SYSRAM_SIZE - \
+#define STM32MP_BL2_BASE (STM32MP_SYSRAM_BASE + \
+ STM32MP_SYSRAM_SIZE - \
STM32MP_BL2_SIZE)
+#define STM32MP_BL2_RO_BASE STM32MP_BL2_BASE
+
+#define STM32MP_BL2_RW_BASE (STM32MP_BL2_RO_BASE + \
+ STM32MP_BL2_RO_SIZE)
+
+#define STM32MP_BL2_RW_SIZE (STM32MP_SYSRAM_BASE + \
+ STM32MP_SYSRAM_SIZE - \
+ STM32MP_BL2_RW_BASE)
+
/* BL2 and BL32/sp_min require 4 tables */
#define MAX_XLAT_TABLES U(4) /* 16 KB for mapping */
@@ -81,13 +129,30 @@
#define MAX_MMAP_REGIONS 6
/* DTB initialization value */
-#define STM32MP_BL2_DTB_SIZE U(0x00005000) /* 20 KB for DTB */
+#define STM32MP_BL2_DTB_SIZE U(0x00006000) /* 24 KB for DTB */
#define STM32MP_BL2_DTB_BASE (STM32MP_BL2_BASE - \
STM32MP_BL2_DTB_SIZE)
+#if defined(IMAGE_BL2)
+#define STM32MP_DTB_SIZE STM32MP_BL2_DTB_SIZE
+#define STM32MP_DTB_BASE STM32MP_BL2_DTB_BASE
+#endif
+
+#define STM32MP_FW_CONFIG_MAX_SIZE PAGE_SIZE
+#define STM32MP_FW_CONFIG_BASE STM32MP_SYSRAM_BASE
+
#define STM32MP_BL33_BASE (STM32MP_DDR_BASE + U(0x04000000))
#define STM32MP_BL33_MAX_SIZE U(0x400000)
+#define STM32MP_HW_CONFIG_BASE (STM32MP_BL33_BASE + \
+ STM32MP_BL33_MAX_SIZE)
+#define STM32MP_HW_CONFIG_MAX_SIZE U(0x40000)
+
+/*******************************************************************************
+ * STM32MP2 device/io map related constants (used for MMU)
+ ******************************************************************************/
+#define STM32MP_DEVICE_BASE U(0x40000000)
+#define STM32MP_DEVICE_SIZE U(0x40000000)
/*******************************************************************************
* STM32MP2 RCC
@@ -172,6 +237,7 @@
/* OTP labels */
#define PART_NUMBER_OTP "part-number-otp"
+#define REVISION_OTP "rev_otp"
#define PACKAGE_OTP "package-otp"
#define HCONF1_OTP "otp124"
#define NAND_OTP "otp16"
@@ -314,6 +380,7 @@
#define DT_DDR_COMPAT "st,stm32mp2-ddr"
#define DT_PWR_COMPAT "st,stm32mp25-pwr"
#define DT_RCC_CLK_COMPAT "st,stm32mp25-rcc"
+#define DT_SDMMC2_COMPAT "st,stm32mp25-sdmmc2"
#define DT_UART_COMPAT "st,stm32h7-uart"
#endif /* STM32MP2_DEF_H */
diff --git a/plat/st/stm32mp2/stm32mp2_private.c b/plat/st/stm32mp2/stm32mp2_private.c
new file mode 100644
index 0000000..2801a7f
--- /dev/null
+++ b/plat/st/stm32mp2/stm32mp2_private.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2023-2024, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include <lib/xlat_tables/xlat_tables_v2.h>
+
+#include <platform_def.h>
+
+#define BKPR_BOOT_MODE 96U
+
+#define MAP_SYSRAM MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \
+ STM32MP_SYSRAM_SIZE, \
+ MT_MEMORY | \
+ MT_RW | \
+ MT_SECURE | \
+ MT_EXECUTE_NEVER)
+
+#define MAP_DEVICE MAP_REGION_FLAT(STM32MP_DEVICE_BASE, \
+ STM32MP_DEVICE_SIZE, \
+ MT_DEVICE | \
+ MT_RW | \
+ MT_SECURE | \
+ MT_EXECUTE_NEVER)
+
+#if defined(IMAGE_BL2)
+static const mmap_region_t stm32mp2_mmap[] = {
+ MAP_SYSRAM,
+ MAP_DEVICE,
+ {0}
+};
+#endif
+
+void configure_mmu(void)
+{
+ mmap_add(stm32mp2_mmap);
+ init_xlat_tables();
+
+ enable_mmu_el3(0);
+}
+
+uintptr_t stm32_get_gpio_bank_base(unsigned int bank)
+{
+ if (bank == GPIO_BANK_Z) {
+ return GPIOZ_BASE;
+ }
+
+ assert(bank <= GPIO_BANK_K);
+
+ return GPIOA_BASE + (bank * GPIO_BANK_OFFSET);
+}
+
+uint32_t stm32_get_gpio_bank_offset(unsigned int bank)
+{
+ if (bank == GPIO_BANK_Z) {
+ return 0;
+ }
+
+ assert(bank <= GPIO_BANK_K);
+
+ return bank * GPIO_BANK_OFFSET;
+}
+
+unsigned long stm32_get_gpio_bank_clock(unsigned int bank)
+{
+ if (bank == GPIO_BANK_Z) {
+ return CK_BUS_GPIOZ;
+ }
+
+ assert(bank <= GPIO_BANK_K);
+
+ return CK_BUS_GPIOA + (bank - GPIO_BANK_A);
+}
+
+uint32_t stm32mp_get_chip_version(void)
+{
+ static uint32_t rev;
+
+ if (rev != 0U) {
+ return rev;
+ }
+
+ if (stm32_get_otp_value(REVISION_OTP, &rev) != 0) {
+ panic();
+ }
+
+ return rev;
+}
+
+uint32_t stm32mp_get_chip_dev_id(void)
+{
+ return stm32mp_syscfg_get_chip_dev_id();
+}
+
+static uint32_t get_part_number(void)
+{
+ static uint32_t part_number;
+
+ if (part_number != 0U) {
+ return part_number;
+ }
+
+ if (stm32_get_otp_value(PART_NUMBER_OTP, &part_number) != 0) {
+ panic();
+ }
+
+ return part_number;
+}
+
+static uint32_t get_cpu_package(void)
+{
+ static uint32_t package = UINT32_MAX;
+
+ if (package == UINT32_MAX) {
+ if (stm32_get_otp_value(PACKAGE_OTP, &package) != 0) {
+ panic();
+ }
+ }
+
+ return (package & PACKAGE_OTP_PKG_MASK) >> PACKAGE_OTP_PKG_SHIFT;
+}
+
+void stm32mp_get_soc_name(char name[STM32_SOC_NAME_SIZE])
+{
+ char *cpu_s, *cpu_r, *pkg;
+
+ /* MPUs Part Numbers */
+ switch (get_part_number()) {
+ case STM32MP251A_PART_NB:
+ cpu_s = "251A";
+ break;
+ case STM32MP251C_PART_NB:
+ cpu_s = "251C";
+ break;
+ case STM32MP251D_PART_NB:
+ cpu_s = "251D";
+ break;
+ case STM32MP251F_PART_NB:
+ cpu_s = "251F";
+ break;
+ case STM32MP253A_PART_NB:
+ cpu_s = "253A";
+ break;
+ case STM32MP253C_PART_NB:
+ cpu_s = "253C";
+ break;
+ case STM32MP253D_PART_NB:
+ cpu_s = "253D";
+ break;
+ case STM32MP253F_PART_NB:
+ cpu_s = "253F";
+ break;
+ case STM32MP255A_PART_NB:
+ cpu_s = "255A";
+ break;
+ case STM32MP255C_PART_NB:
+ cpu_s = "255C";
+ break;
+ case STM32MP255D_PART_NB:
+ cpu_s = "255D";
+ break;
+ case STM32MP255F_PART_NB:
+ cpu_s = "255F";
+ break;
+ case STM32MP257A_PART_NB:
+ cpu_s = "257A";
+ break;
+ case STM32MP257C_PART_NB:
+ cpu_s = "257C";
+ break;
+ case STM32MP257D_PART_NB:
+ cpu_s = "257D";
+ break;
+ case STM32MP257F_PART_NB:
+ cpu_s = "257F";
+ break;
+ default:
+ cpu_s = "????";
+ break;
+ }
+
+ /* Package */
+ switch (get_cpu_package()) {
+ case STM32MP25_PKG_CUSTOM:
+ pkg = "XX";
+ break;
+ case STM32MP25_PKG_AL_VFBGA361:
+ pkg = "AL";
+ break;
+ case STM32MP25_PKG_AK_VFBGA424:
+ pkg = "AK";
+ break;
+ case STM32MP25_PKG_AI_TFBGA436:
+ pkg = "AI";
+ break;
+ default:
+ pkg = "??";
+ break;
+ }
+
+ /* REVISION */
+ switch (stm32mp_get_chip_version()) {
+ case STM32MP2_REV_A:
+ cpu_r = "A";
+ break;
+ case STM32MP2_REV_B:
+ cpu_r = "B";
+ break;
+ case STM32MP2_REV_X:
+ cpu_r = "X";
+ break;
+ case STM32MP2_REV_Y:
+ cpu_r = "Y";
+ break;
+ case STM32MP2_REV_Z:
+ cpu_r = "Z";
+ break;
+ default:
+ cpu_r = "?";
+ break;
+ }
+
+ snprintf(name, STM32_SOC_NAME_SIZE,
+ "STM32MP%s%s Rev.%s", cpu_s, pkg, cpu_r);
+}
+
+void stm32mp_print_cpuinfo(void)
+{
+ char name[STM32_SOC_NAME_SIZE];
+
+ stm32mp_get_soc_name(name);
+ NOTICE("CPU: %s\n", name);
+}
+
+void stm32mp_print_boardinfo(void)
+{
+ uint32_t board_id = 0U;
+
+ if (stm32_get_otp_value(BOARD_ID_OTP, &board_id) != 0) {
+ return;
+ }
+
+ if (board_id != 0U) {
+ stm32_display_board_info(board_id);
+ }
+}
+
+uintptr_t stm32_get_bkpr_boot_mode_addr(void)
+{
+ return tamp_bkpr(BKPR_BOOT_MODE);
+}
diff --git a/plat/st/stm32mp2/stm32mp2_syscfg.c b/plat/st/stm32mp2/stm32mp2_syscfg.c
new file mode 100644
index 0000000..46c75a6
--- /dev/null
+++ b/plat/st/stm32mp2/stm32mp2_syscfg.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2024, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+
+#include <platform_def.h>
+#include <stm32mp2_private.h>
+
+/*
+ * SYSCFG register offsets (base relative)
+ */
+#define SYSCFG_DEVICEID 0x6400U
+
+/*
+ * SYSCFG_DEVICEID Register
+ */
+#define SYSCFG_DEVICEID_DEV_ID_MASK GENMASK_32(11, 0)
+
+/*
+ * @brief Get device ID from SYSCFG registers.
+ * @retval device ID (DEV_ID).
+ */
+uint32_t stm32mp_syscfg_get_chip_dev_id(void)
+{
+ return mmio_read_32(SYSCFG_BASE + SYSCFG_DEVICEID) & SYSCFG_DEVICEID_DEV_ID_MASK;
+}
diff --git a/plat/xilinx/common/include/pm_api_sys.h b/plat/xilinx/common/include/pm_api_sys.h
index ffee805..029bb43 100644
--- a/plat/xilinx/common/include/pm_api_sys.h
+++ b/plat/xilinx/common/include/pm_api_sys.h
@@ -64,6 +64,7 @@
uint32_t wake, uint32_t enable,
uint32_t flag);
enum pm_ret_status pm_get_chipid(uint32_t *value);
+enum pm_ret_status eemi_feature_check(uint32_t api_id, uint32_t *ret_payload);
/*
* Assigning of argument values into array elements.
@@ -97,4 +98,9 @@
PM_PACK_PAYLOAD5(pl, (mid), (flag), (arg0), (arg1), (arg2), (arg3), (arg4)); \
}
+#define PM_PACK_PAYLOAD7(pl, mid, flag, arg0, arg1, arg2, arg3, arg4, arg5, arg6) { \
+ pl[6] = (uint32_t)(arg6); \
+ PM_PACK_PAYLOAD6(pl, (mid), (flag), (arg0), (arg1), (arg2), (arg3), (arg4), (arg5)); \
+}
+
#endif /* PM_API_SYS_H */
diff --git a/plat/xilinx/common/include/pm_common.h b/plat/xilinx/common/include/pm_common.h
index c0308ab..68d1db2 100644
--- a/plat/xilinx/common/include/pm_common.h
+++ b/plat/xilinx/common/include/pm_common.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2013-2018, Arm Limited and Contributors. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -24,8 +24,9 @@
#define CRC_ORDER 16U
#define CRC_POLYNOM 0x8005U
#else
-#define PAYLOAD_ARG_CNT 6U
+#define PAYLOAD_ARG_CNT 7U
#endif
+#define RET_PAYLOAD_ARG_CNT 6U
#define PAYLOAD_ARG_SIZE 4U /* size in bytes */
#define TZ_VERSION_MAJOR 1
diff --git a/plat/xilinx/common/include/pm_defs.h b/plat/xilinx/common/include/pm_defs.h
index 055fa3d..9920611 100644
--- a/plat/xilinx/common/include/pm_defs.h
+++ b/plat/xilinx/common/include/pm_defs.h
@@ -35,6 +35,7 @@
(uint32_t)XPM_NODESUBCL_DEV_PERIPH, \
(uint32_t)XPM_NODETYPE_DEV_PERIPH, (IDX))
+#define TF_A_FEATURE_CHECK 0xa00U
#define PM_GET_CALLBACK_DATA 0xa01U
#define PM_GET_TRUSTZONE_VERSION 0xa03U
#define TF_A_PM_REGISTER_SGI 0xa04U
@@ -95,6 +96,8 @@
IOCTL_GET_LAST_RESET_REASON = 23,
/* AI engine NPI ISR clear */
IOCTL_AIE_ISR_CLEAR = 24,
+ IOCTL_UFS_TXRX_CFGRDY_GET = 40,
+ IOCTL_UFS_SRAM_CSR_SEL = 41,
};
/**
diff --git a/plat/xilinx/common/include/pm_svc_main.h b/plat/xilinx/common/include/pm_svc_main.h
index 67fbeae..000f198 100644
--- a/plat/xilinx/common/include/pm_svc_main.h
+++ b/plat/xilinx/common/include/pm_svc_main.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,6 +12,8 @@
extern bool pwrdwn_req_received;
+#define PASS_THROUGH_FW_CMD_ID U(0xfff)
+
/******************************************************************************/
/**
* SECURE_REDUNDANT_CALL() - Adds redundancy to the function call. This is to
diff --git a/plat/xilinx/common/pm_service/pm_api_sys.c b/plat/xilinx/common/pm_service/pm_api_sys.c
index 0a6e810..e9c5f13 100644
--- a/plat/xilinx/common/pm_service/pm_api_sys.c
+++ b/plat/xilinx/common/pm_service/pm_api_sys.c
@@ -122,7 +122,7 @@
}
PM_PACK_PAYLOAD6(payload, module_id, flag, x0, x1, x2, x3, x4, x5);
- return pm_ipi_send_sync(primary_proc, payload, (uint32_t *)result, PAYLOAD_ARG_CNT);
+ return pm_ipi_send_sync(primary_proc, payload, (uint32_t *)result, RET_PAYLOAD_ARG_CNT);
}
/**
@@ -364,6 +364,37 @@
}
/**
+ * eemi_feature_check() - Returns the supported API version if supported.
+ * @api_id: API ID to check.
+ * @ret_payload: pointer to array of PAYLOAD_ARG_CNT number of
+ * words Returned supported API version
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status eemi_feature_check(uint32_t api_id, uint32_t *ret_payload)
+{
+ enum pm_ret_status ret;
+
+ /* Return version of API which are implemented in TF-A only */
+ switch (api_id) {
+ case PM_GET_CALLBACK_DATA:
+ case PM_GET_TRUSTZONE_VERSION:
+ ret_payload[0] = PM_API_VERSION_2;
+ ret = PM_RET_SUCCESS;
+ break;
+ case TF_A_PM_REGISTER_SGI:
+ case TF_A_FEATURE_CHECK:
+ ret_payload[0] = PM_API_BASE_VERSION;
+ ret = PM_RET_SUCCESS;
+ break;
+ default:
+ ret = PM_RET_ERROR_NO_FEATURE;
+ }
+
+ return ret;
+}
+
+/**
* pm_feature_check() - Returns the supported API version if supported.
* @api_id: API ID to check.
* @flag: 0 - Call from secure source.
@@ -406,7 +437,7 @@
PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag,
PM_FEATURE_CHECK, api_id);
- return pm_ipi_send_sync(primary_proc, payload, ret_payload, PAYLOAD_ARG_CNT);
+ return pm_ipi_send_sync(primary_proc, payload, ret_payload, RET_PAYLOAD_ARG_CNT);
}
/**
diff --git a/plat/xilinx/common/pm_service/pm_ipi.c b/plat/xilinx/common/pm_service/pm_ipi.c
index 56567dd..425fdcb 100644
--- a/plat/xilinx/common/pm_service/pm_ipi.c
+++ b/plat/xilinx/common/pm_service/pm_ipi.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -169,9 +169,7 @@
size_t i;
enum pm_ret_status ret;
#if IPI_CRC_CHECK
- uint32_t *payload_ptr = value;
- size_t j;
- uint32_t response_payload[PAYLOAD_ARG_CNT];
+ uint32_t crc;
#endif
uintptr_t buffer_base = proc->ipi->buffer_base +
IPI_BUFFER_TARGET_REMOTE_OFFSET +
@@ -184,27 +182,20 @@
* buf-2: unused
* buf-3: unused
*/
- for (i = 1; i <= count; i++) {
- *value = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
- value++;
+ for (i = 0U; i < count; i++) {
+ value[i] = mmio_read_32(buffer_base + ((i + 1U) * PAYLOAD_ARG_SIZE));
}
ret = mmio_read_32(buffer_base);
#if IPI_CRC_CHECK
- for (j = 0; j < PAYLOAD_ARG_CNT; j++) {
- response_payload[j] = mmio_read_32(buffer_base +
- (j * PAYLOAD_ARG_SIZE));
- }
-
- if (response_payload[PAYLOAD_CRC_POS] !=
- calculate_crc(response_payload, IPI_W0_TO_W6_SIZE)) {
- NOTICE("ERROR in CRC response payload value:0x%x\n",
- response_payload[PAYLOAD_CRC_POS]);
+ crc = mmio_read_32(buffer_base + (PAYLOAD_CRC_POS * PAYLOAD_ARG_SIZE));
+ if (crc != calculate_crc((uint32_t *)buffer_base, IPI_W0_TO_W6_SIZE)) {
+ NOTICE("ERROR in CRC response payload value:0x%x\n", crc);
ret = PM_RET_ERROR_INVALID_CRC;
/* Payload data is invalid as CRC validation failed
* Clear the payload to avoid leakage of data to upper layers
*/
- memset(payload_ptr, 0, count);
+ memset(value, 0, count);
}
#endif
@@ -227,9 +218,7 @@
{
size_t i;
#if IPI_CRC_CHECK
- uint32_t *payload_ptr = value;
- size_t j;
- unsigned int response_payload[PAYLOAD_ARG_CNT] = {0};
+ uint32_t crc;
#endif
uintptr_t buffer_base = IPI_BUFFER_REMOTE_BASE +
IPI_BUFFER_TARGET_LOCAL_OFFSET +
@@ -240,25 +229,18 @@
count = IPI_BUFFER_MAX_WORDS;
}
- for (i = 0; i <= count; i++) {
- *value = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
- value++;
+ for (i = 0; i < count; i++) {
+ value[i] = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
}
#if IPI_CRC_CHECK
- for (j = 0; j < PAYLOAD_ARG_CNT; j++) {
- response_payload[j] = mmio_read_32(buffer_base +
- (j * PAYLOAD_ARG_SIZE));
- }
-
- if (response_payload[PAYLOAD_CRC_POS] !=
- calculate_crc(response_payload, IPI_W0_TO_W6_SIZE)) {
- NOTICE("ERROR in CRC response payload value:0x%x\n",
- response_payload[PAYLOAD_CRC_POS]);
+ crc = mmio_read_32(buffer_base + (PAYLOAD_CRC_POS * PAYLOAD_ARG_SIZE));
+ if (crc != calculate_crc((uint32_t *)buffer_base, IPI_W0_TO_W6_SIZE)) {
+ NOTICE("ERROR in CRC response payload value:0x%x\n", crc);
ret = PM_RET_ERROR_INVALID_CRC;
/* Payload data is invalid as CRC validation failed
* Clear the payload to avoid leakage of data to upper layers
*/
- memset(payload_ptr, 0, count);
+ memset(value, 0, count);
}
#endif
return ret;
diff --git a/plat/xilinx/common/pm_service/pm_svc_main.c b/plat/xilinx/common/pm_service/pm_svc_main.c
index 7ac0ac1..193c5dc 100644
--- a/plat/xilinx/common/pm_service/pm_svc_main.c
+++ b/plat/xilinx/common/pm_service/pm_svc_main.c
@@ -36,6 +36,32 @@
#define EVENT_CPU_PWRDWN (4U)
#define MBOX_SGI_SHARED_IPI (7U)
+/**
+ * upper_32_bits - return bits 32-63 of a number
+ * @n: the number we're accessing
+ */
+#define upper_32_bits(n) ((uint32_t)((n) >> 32U))
+
+/**
+ * lower_32_bits - return bits 0-31 of a number
+ * @n: the number we're accessing
+ */
+#define lower_32_bits(n) ((uint32_t)((n) & 0xffffffffU))
+
+/**
+ * EXTRACT_SMC_ARGS - extracts 32-bit payloads from 64-bit SMC arguments
+ * @pm_arg: array of 32-bit payloads
+ * @x: array of 64-bit SMC arguments
+ */
+#define EXTRACT_ARGS(pm_arg, x) \
+ for (uint32_t i = 0U; i < (PAYLOAD_ARG_CNT - 1U); i++) { \
+ if ((i % 2U) != 0U) { \
+ pm_arg[i] = lower_32_bits(x[(i / 2U) + 1U]); \
+ } else { \
+ pm_arg[i] = upper_32_bits(x[i / 2U]); \
+ } \
+ }
+
/* 1 sec of wait timeout for secondary core down */
#define PWRDWN_WAIT_TIMEOUT (1000U)
DEFINE_RENAME_SYSREG_RW_FUNCS(icc_asgi1r_el1, S3_0_C12_C11_6)
@@ -278,7 +304,7 @@
case (uint32_t)PM_FEATURE_CHECK:
{
- uint32_t result[PAYLOAD_ARG_CNT] = {0U};
+ uint32_t result[RET_PAYLOAD_ARG_CNT] = {0U};
ret = pm_feature_check(pm_arg[0], result, security_flag);
SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U),
@@ -367,6 +393,15 @@
{
switch (api_id) {
+ case TF_A_FEATURE_CHECK:
+ {
+ enum pm_ret_status ret;
+ uint32_t result[PAYLOAD_ARG_CNT] = {0U};
+
+ ret = eemi_feature_check(pm_arg[0], result);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U));
+ }
+
case TF_A_PM_REGISTER_SGI:
{
int32_t ret;
@@ -424,7 +459,7 @@
void *handle, uint32_t security_flag)
{
enum pm_ret_status ret;
- uint32_t buf[PAYLOAD_ARG_CNT] = {0};
+ uint32_t buf[RET_PAYLOAD_ARG_CNT] = {0};
ret = pm_handle_eemi_call(security_flag, api_id, pm_arg[0], pm_arg[1],
pm_arg[2], pm_arg[3], pm_arg[4],
@@ -449,6 +484,45 @@
}
/**
+ * eemi_api_handler() - Prepare EEMI payload and perform IPI transaction.
+ * @api_id: identifier for the API being called.
+ * @pm_arg: pointer to the argument data for the API call.
+ * @handle: Pointer to caller's context structure.
+ * @security_flag: SECURE_FLAG or NON_SECURE_FLAG.
+ *
+ * EEMI - Embedded Energy Management Interface is AMD-Xilinx proprietary
+ * protocol to allow communication between power management controller and
+ * different processing clusters.
+ *
+ * This handler prepares EEMI protocol payload received from kernel and performs
+ * IPI transaction.
+ *
+ * Return: If EEMI API found then, uintptr_t type address, else 0
+ */
+static uintptr_t eemi_api_handler(uint32_t api_id, const uint32_t *pm_arg,
+ void *handle, uint32_t security_flag)
+{
+ enum pm_ret_status ret;
+ uint32_t buf[RET_PAYLOAD_ARG_CNT] = {0U};
+ uint32_t payload[PAYLOAD_ARG_CNT] = {0U};
+ uint32_t module_id;
+
+ module_id = (api_id & MODULE_ID_MASK) >> 8U;
+
+ PM_PACK_PAYLOAD7(payload, module_id, security_flag, api_id,
+ pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3],
+ pm_arg[4], pm_arg[5]);
+
+ ret = pm_ipi_send_sync(primary_proc, payload, (uint32_t *)buf,
+ RET_PAYLOAD_ARG_CNT);
+
+ SMC_RET4(handle, (uint64_t)ret | ((uint64_t)buf[0] << 32U),
+ (uint64_t)buf[1] | ((uint64_t)buf[2] << 32U),
+ (uint64_t)buf[3] | ((uint64_t)buf[4] << 32U),
+ (uint64_t)buf[5]);
+}
+
+/**
* pm_smc_handler() - SMC handler for PM-API calls coming from EL1/EL2.
* @smc_fid: Function Identifier.
* @x1: SMC64 Arguments from kernel.
@@ -477,6 +551,7 @@
uint32_t security_flag = NON_SECURE_FLAG;
uint32_t api_id;
bool status = false, status_tmp = false;
+ uint64_t x[4] = {x1, x2, x3, x4};
/* Handle case where PM wasn't initialized properly */
if (pm_up == false) {
@@ -494,6 +569,14 @@
security_flag = SECURE_FLAG;
}
+ if ((smc_fid & FUNCID_NUM_MASK) == PASS_THROUGH_FW_CMD_ID) {
+ api_id = lower_32_bits(x[0]);
+
+ EXTRACT_ARGS(pm_arg, x);
+
+ return eemi_api_handler(api_id, pm_arg, handle, security_flag);
+ }
+
pm_arg[0] = (uint32_t)x1;
pm_arg[1] = (uint32_t)(x1 >> 32U);
pm_arg[2] = (uint32_t)x2;
diff --git a/plat/xilinx/versal/aarch64/versal_common.c b/plat/xilinx/versal/aarch64/versal_common.c
index 772477f..9e8134a 100644
--- a/plat/xilinx/versal/aarch64/versal_common.c
+++ b/plat/xilinx/versal/aarch64/versal_common.c
@@ -1,12 +1,11 @@
/*
* Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
-#include <drivers/generic_delay_timer.h>
#include <lib/mmio.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
@@ -18,7 +17,7 @@
#include <versal_def.h>
uint32_t platform_id, platform_version;
-uint32_t cpu_clock = VERSAL_CPU_CLOCK;
+uint32_t cpu_clock;
/*
* Table of regions to map using the MMU.
@@ -39,19 +38,10 @@
return plat_versal_mmap;
}
-static void versal_print_platform_name(void)
-{
- NOTICE("TF-A running on %s\n", PLATFORM_NAME);
-}
-
void versal_config_setup(void)
{
/* Configure IPI data for versal */
versal_ipi_config_table_init();
-
- versal_print_platform_name();
-
- generic_delay_timer_init();
}
void board_detection(void)
@@ -70,7 +60,50 @@
platform_version = FIELD_GET(PLATFORM_VERSION_MASK, plat_info[1]);
}
+const char *board_name_decode(void)
+{
+ const char *platform;
+
+ switch (platform_id) {
+ case VERSAL_SPP:
+ platform = "IPP";
+ break;
+ case VERSAL_EMU:
+ platform = "EMU";
+ break;
+ case VERSAL_QEMU:
+ platform = "QEMU";
+ break;
+ case VERSAL_SILICON:
+ platform = "SILICON";
+ break;
+ default:
+ platform = "unknown";
+ }
+
+ return platform;
+}
+
uint32_t get_uart_clk(void)
{
- return UART_CLOCK;
+ uint32_t uart_clock;
+
+ switch (platform_id) {
+ case VERSAL_SPP:
+ uart_clock = 25000000;
+ break;
+ case VERSAL_EMU:
+ uart_clock = 212000;
+ break;
+ case VERSAL_QEMU:
+ uart_clock = 25000000;
+ break;
+ case VERSAL_SILICON:
+ uart_clock = 100000000;
+ break;
+ default:
+ panic();
+ }
+
+ return uart_clock;
}
diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c
index 594784f..0e4ec1c 100644
--- a/plat/xilinx/versal/bl31_versal_setup.c
+++ b/plat/xilinx/versal/bl31_versal_setup.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,6 +12,7 @@
#include <bl31/bl31.h>
#include <common/bl_common.h>
#include <common/debug.h>
+#include <drivers/generic_delay_timer.h>
#include <lib/mmio.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
@@ -73,22 +74,41 @@
enum pm_ret_status ret_status;
uint64_t addr[HANDOFF_PARAMS_MAX_SIZE];
- set_cnt_freq();
-
- setup_console();
-
- /* Initialize the platform config for future decision making */
- versal_config_setup();
-
- /* Get platform related information */
- board_detection();
-
/*
* Do initial security configuration to allow DRAM/device access. On
* Base VERSAL only DRAM security is programmable (via TrustZone), but
* other platforms might have more programmable security devices
* present.
*/
+ versal_config_setup();
+
+ /* Initialize the platform config for future decision making */
+ board_detection();
+
+ switch (platform_id) {
+ case VERSAL_SPP:
+ cpu_clock = 2720000;
+ break;
+ case VERSAL_EMU:
+ cpu_clock = 212000;
+ break;
+ case VERSAL_QEMU:
+ /* Random values now */
+ cpu_clock = 2720000;
+ break;
+ case VERSAL_SILICON:
+ cpu_clock = 100000000;
+ break;
+ default:
+ panic();
+ }
+ set_cnt_freq();
+
+ generic_delay_timer_init();
+
+ setup_console();
+
+ NOTICE("TF-A running on %s %d\n", board_name_decode(), platform_version);
/* Populate common information for BL32 and BL33 */
SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
diff --git a/plat/xilinx/versal/include/plat_private.h b/plat/xilinx/versal/include/plat_private.h
index 932c6de..4b2b6cf 100644
--- a/plat/xilinx/versal/include/plat_private.h
+++ b/plat/xilinx/versal/include/plat_private.h
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -25,6 +25,8 @@
extern uint32_t cpu_clock, platform_id, platform_version;
void board_detection(void);
+const char *board_name_decode(void);
+
void plat_versal_gic_driver_init(void);
void plat_versal_gic_init(void);
void plat_versal_gic_cpuif_enable(void);
diff --git a/plat/xilinx/versal/include/versal_def.h b/plat/xilinx/versal/include/versal_def.h
index f21d409..b7691ad 100644
--- a/plat/xilinx/versal/include/versal_def.h
+++ b/plat/xilinx/versal/include/versal_def.h
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -25,13 +25,11 @@
#define CONSOLE_IS(con) (VERSAL_CONSOLE_ID_ ## con == VERSAL_CONSOLE)
-/* List all supported platforms */
-#define VERSAL_PLATFORM_ID_versal_virt 1
-#define VERSAL_PLATFORM_ID_spp_itr6 2
-#define VERSAL_PLATFORM_ID_emu_itr6 3
-#define VERSAL_PLATFORM_ID_silicon 4
-
-#define VERSAL_PLATFORM_IS(con) (VERSAL_PLATFORM_ID_ ## con == VERSAL_PLATFORM)
+/* List of platforms */
+#define VERSAL_SILICON U(0)
+#define VERSAL_SPP U(1)
+#define VERSAL_EMU U(2)
+#define VERSAL_QEMU U(3)
/* Firmware Image Package */
#define VERSAL_PRIMARY_CPU 0
@@ -75,27 +73,7 @@
/*******************************************************************************
* Platform related constants
******************************************************************************/
-#if VERSAL_PLATFORM_IS(versal_virt)
-# define PLATFORM_NAME "Versal Virt"
-# define UART_CLOCK 25000000
-# define UART_BAUDRATE 115200
-# define VERSAL_CPU_CLOCK 2720000
-#elif VERSAL_PLATFORM_IS(silicon)
-# define PLATFORM_NAME "Versal Silicon"
-# define UART_CLOCK 100000000
-# define UART_BAUDRATE 115200
-# define VERSAL_CPU_CLOCK 100000000
-#elif VERSAL_PLATFORM_IS(spp_itr6)
-# define PLATFORM_NAME "SPP ITR6"
-# define UART_CLOCK 25000000
-# define UART_BAUDRATE 115200
-# define VERSAL_CPU_CLOCK 2720000
-#elif VERSAL_PLATFORM_IS(emu_itr6)
-# define PLATFORM_NAME "EMU ITR6"
-# define UART_CLOCK 212000
-# define UART_BAUDRATE 9600
-# define VERSAL_CPU_CLOCK 212000
-#endif
+#define UART_BAUDRATE 115200
/* Access control register defines */
#define ACTLR_EL3_L2ACTLR_BIT (1 << 6)
diff --git a/plat/xilinx/versal/plat_psci.c b/plat/xilinx/versal/plat_psci.c
index 4cf1ed1..74c5bf3 100644
--- a/plat/xilinx/versal/plat_psci.c
+++ b/plat/xilinx/versal/plat_psci.c
@@ -197,7 +197,7 @@
*/
static void versal_pwr_domain_off(const psci_power_state_t *target_state)
{
- uint32_t ret, fw_api_version, version[PAYLOAD_ARG_CNT] = {0U};
+ uint32_t ret, fw_api_version, version[RET_PAYLOAD_ARG_CNT] = {0U};
uint32_t cpu_id = plat_my_core_pos();
const struct pm_proc *proc = pm_get_proc(cpu_id);
diff --git a/plat/xilinx/versal/platform.mk b/plat/xilinx/versal/platform.mk
index 2f07996..6cc28e1 100644
--- a/plat/xilinx/versal/platform.mk
+++ b/plat/xilinx/versal/platform.mk
@@ -1,5 +1,5 @@
# Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
-# Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+# Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
@@ -44,8 +44,9 @@
$(eval $(call add_define,IPI_CRC_CHECK))
endif
-VERSAL_PLATFORM ?= silicon
-$(eval $(call add_define_val,VERSAL_PLATFORM,VERSAL_PLATFORM_ID_${VERSAL_PLATFORM}))
+ifdef VERSAL_PLATFORM
+ $(warning "VERSAL_PLATFORM has been deprecated")
+endif
ifdef XILINX_OF_BOARD_DTB_ADDR
$(eval $(call add_define,XILINX_OF_BOARD_DTB_ADDR))
diff --git a/plat/xilinx/versal/sip_svc_setup.c b/plat/xilinx/versal/sip_svc_setup.c
index 4441d3e..3c0bd63 100644
--- a/plat/xilinx/versal/sip_svc_setup.c
+++ b/plat/xilinx/versal/sip_svc_setup.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -22,7 +22,7 @@
/* SiP Service Calls version numbers */
#define SIP_SVC_VERSION_MAJOR U(0)
-#define SIP_SVC_VERSION_MINOR U(1)
+#define SIP_SVC_VERSION_MINOR U(2)
/* These macros are used to identify PM calls from the SMC function ID */
#define SIP_FID_MASK GENMASK(23, 16)
diff --git a/plat/xilinx/versal_net/plat_psci_pm.c b/plat/xilinx/versal_net/plat_psci_pm.c
index e5a5235..fb2005d 100644
--- a/plat/xilinx/versal_net/plat_psci_pm.c
+++ b/plat/xilinx/versal_net/plat_psci_pm.c
@@ -59,7 +59,7 @@
*/
static void versal_net_pwr_domain_off(const psci_power_state_t *target_state)
{
- uint32_t ret, fw_api_version, version[PAYLOAD_ARG_CNT] = {0U};
+ uint32_t ret, fw_api_version, version[RET_PAYLOAD_ARG_CNT] = {0U};
uint32_t cpu_id = plat_my_core_pos();
const struct pm_proc *proc = pm_get_proc(cpu_id);
diff --git a/plat/xilinx/versal_net/sip_svc_setup.c b/plat/xilinx/versal_net/sip_svc_setup.c
index 80d5a53..c974810 100644
--- a/plat/xilinx/versal_net/sip_svc_setup.c
+++ b/plat/xilinx/versal_net/sip_svc_setup.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -25,7 +25,7 @@
/* SiP Service Calls version numbers */
#define SIP_SVC_VERSION_MAJOR (0U)
-#define SIP_SVC_VERSION_MINOR (1U)
+#define SIP_SVC_VERSION_MINOR (2U)
/* These macros are used to identify PM calls from the SMC function ID */
#define SIP_FID_MASK GENMASK(23, 16)
diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk
index c340009..22eceb6 100644
--- a/plat/xilinx/zynqmp/platform.mk
+++ b/plat/xilinx/zynqmp/platform.mk
@@ -21,7 +21,7 @@
EL3_EXCEPTION_HANDLING := $(SDEI_SUPPORT)
# pncd SPD requires secure SGI to be handled at EL1
-ifeq (${SPD}, $(filter ${SPD},pncd tspd))
+ifeq (${SPD}, $(filter ${SPD},pncd tspd opteed))
ifeq (${ZYNQMP_WDT_RESTART},1)
$(error "Error: ZYNQMP_WDT_RESTART and SPD=pncd are incompatible")
endif
diff --git a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c
index 3d546b3..66f011a 100644
--- a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c
@@ -919,7 +919,7 @@
enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *version,
uint32_t *bit_mask, uint8_t len)
{
- uint32_t ret_payload[PAYLOAD_ARG_CNT] = {0U};
+ uint32_t ret_payload[RET_PAYLOAD_ARG_CNT] = {0U};
uint32_t status;
/* Get API version implemented in TF-A */
diff --git a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c
index 5a6a9f8..bf17ea4 100644
--- a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c
+++ b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c
@@ -285,7 +285,7 @@
uint32_t payload[PAYLOAD_ARG_CNT];
uint32_t pm_arg[5];
- uint32_t result[PAYLOAD_ARG_CNT] = {0};
+ uint32_t result[RET_PAYLOAD_ARG_CNT] = {0};
uint32_t api_id;
/* Handle case where PM wasn't initialized properly */
@@ -566,7 +566,7 @@
PM_PACK_PAYLOAD6(payload, api_id, pm_arg[0], pm_arg[1],
pm_arg[2], pm_arg[3], pm_arg[4]);
ret = pm_ipi_send_sync(primary_proc, payload, result,
- PAYLOAD_ARG_CNT);
+ RET_PAYLOAD_ARG_CNT);
SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U),
(uint64_t)result[1] | ((uint64_t)result[2] << 32U));
}
diff --git a/poetry.lock b/poetry.lock
index b465f48..9b98b18 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -217,6 +217,26 @@
test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"]
[[package]]
+name = "cot-dt2c"
+version = "0.1.0"
+description = "CoT-dt2c Tool is a python script to convert CoT DT file into corresponding C file"
+optional = false
+python-versions = "^3.8"
+files = []
+develop = true
+
+[package.dependencies]
+click = "^8.1.7"
+igraph = "^0.11.6"
+plotly = "^5.23.0"
+pydevicetree = "0.0.13"
+pyparsing = "^3.1.2"
+
+[package.source]
+type = "directory"
+url = "tools/cot_dt2c"
+
+[[package]]
name = "docutils"
version = "0.18.1"
description = "Docutils -- Python Documentation Utilities"
@@ -239,6 +259,66 @@
]
[[package]]
+name = "igraph"
+version = "0.11.6"
+description = "High performance graph data structures and algorithms"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "igraph-0.11.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3f8b837181e8e87676be3873ce87cc92cc234efd58a2da2f6b4e050db150fcf4"},
+ {file = "igraph-0.11.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:245c4b7d7657849eff80416f5df4525c8fc44c74a981ee4d44f0ef2612c3bada"},
+ {file = "igraph-0.11.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdb7be3d165073c0136295c0808e9edc57ba096cdb26e94086abb04561f7a292"},
+ {file = "igraph-0.11.6-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58974e20df2986a1ae52a16e51ecb387cc0cbeb41c5c0ddff4d373a1bbf1d9c5"},
+ {file = "igraph-0.11.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bef14de5e8ab70724a43808b1ed14aaa6fe1002f87e592289027a3827a8f44a"},
+ {file = "igraph-0.11.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:86c1e98de2e32d074df8510bf18abfa1f4c5fda4cb28a009985a5d746b0c0125"},
+ {file = "igraph-0.11.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ebc5b3d702158abeb2e4d2414374586a2b932e1a07e48352b470600e1733d528"},
+ {file = "igraph-0.11.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0efe6d0fb22d3987a800eb3857ed04df9eb4c5dddd0998be05232cb646f1c337"},
+ {file = "igraph-0.11.6-cp38-cp38-win32.whl", hash = "sha256:f4e68b27497b1c8ada2fb2bc35ef3fa7b0d72e84306b3d648d3de240fc618c32"},
+ {file = "igraph-0.11.6-cp38-cp38-win_amd64.whl", hash = "sha256:5665b33dfbfca5f54ce9b4fea6b97903bd0e99fb1b02acf5e57e600bdfa5a355"},
+ {file = "igraph-0.11.6-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:8aabef03d787b519d1075dfc0da4a1109fb113b941334883e3e7947ac30a459e"},
+ {file = "igraph-0.11.6-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:1f2cc4a518d99cdf6cae514f85e93e56852bc8c325b3abb96037d1d690b5975f"},
+ {file = "igraph-0.11.6-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1e859238be52ab8ccc614d18f9362942bc88ce543afc12548f81ae99b10801d"},
+ {file = "igraph-0.11.6-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d61fbe5e85eb4ae9efe08c461f9bdeedb02a2b5739fbc223d324a71f40a28be2"},
+ {file = "igraph-0.11.6-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6620ba39df29fd42151becf82309b54e57148233c9c3ef890eed62e25eed8a5"},
+ {file = "igraph-0.11.6-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:59666589bb3d07f310cda2c5106a8adeeb77c2ef27fecf1c6438b6091f4ca69d"},
+ {file = "igraph-0.11.6-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:8750b6d6caebf199cf7dc41c931f58e330153779707391e30f0a29f02666fb6e"},
+ {file = "igraph-0.11.6-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:967d6f2c30fe94317da15e459374d0fb8ca3e56020412f201ecd07dd5b5352f2"},
+ {file = "igraph-0.11.6-cp39-abi3-win32.whl", hash = "sha256:9744f95a67319eb6cb487ceabf30f5d7940de34bada51f0ba63adbd23e0f94ad"},
+ {file = "igraph-0.11.6-cp39-abi3-win_amd64.whl", hash = "sha256:b80e69eb11faa9c57330a9ffebdde5808966efe1c1f638d4d4827ea04df7aca8"},
+ {file = "igraph-0.11.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0329c16092e2ea7930d5f8368666ce7cb704900cc0ea04e4afe9ea1dd46e44af"},
+ {file = "igraph-0.11.6-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:21752313f449bd8688e5688e95ea7231cea5e9199c7162535029be0d9af848ac"},
+ {file = "igraph-0.11.6-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea25e136c6c4161f53ff58868b23ff6c845193050ab0e502236d68e5d4174e32"},
+ {file = "igraph-0.11.6-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac84433a03aef15e4b810010b08882b09854a3669450ccf31e392dbe295d2a66"},
+ {file = "igraph-0.11.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac697a44e3573169fa2b28c9c37dcf9cf01e0f558b845dd7123860d4c7c8fb89"},
+ {file = "igraph-0.11.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:bdeae8bf35316eb1fb27bf667dcf5ecf5fcfb0b8f51831bc1b00c39c09c2d73b"},
+ {file = "igraph-0.11.6-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ad7e4aa442935de72554b96733bf6d7f09eac5cee97988a2562bdd3ca173cfa3"},
+ {file = "igraph-0.11.6-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:8d2818780358a686178866d01568b9df1f29678581734ad7a78882bab54df004"},
+ {file = "igraph-0.11.6-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2352276a20d979f1dea360af4202bb9f0c9a7d2c77f51815c0e625165e82013d"},
+ {file = "igraph-0.11.6-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:687fdab543b507d622fa3043f4227e5b26dc61dcf8ff8c0919fccddcc655f8b8"},
+ {file = "igraph-0.11.6-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57f7f8214cd48c9a4d97f7346a4152ba2d4ac95fb5ee0df4ecf224fce4ba3d14"},
+ {file = "igraph-0.11.6-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:2b9cc69ede53f76ffae03b066609aa90184dd68ef15da8c104a97cebb9210838"},
+ {file = "igraph-0.11.6-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:591e1e447c3f0092daf7613a3eaedab83f9a0b0adbaf7702724c5117ded038a5"},
+ {file = "igraph-0.11.6-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ca558eb331bc687bc33e5cd23717e22676e9412f8cda3a31d30c996a0487610d"},
+ {file = "igraph-0.11.6-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf43c30e08debb087c9e3da69aa5cf1b6732968da34d55a614e3421b9a452146"},
+ {file = "igraph-0.11.6-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d38e8d7db72b187d9d2211d0d06b3271fa9f32b04d49d789e2859b5480db0d0"},
+ {file = "igraph-0.11.6-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a318b059051ff78144a1c3cb880f4d933c812bcdb3d833a49cd7168d0427672"},
+ {file = "igraph-0.11.6-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2c54027add809b3c5b6685b8deca4ea4763fd000b9ea45c7ee46b7c9d61ff15e"},
+ {file = "igraph-0.11.6.tar.gz", hash = "sha256:837f233256c3319f2a35a6a80d94eafe47b43791ef4c6f9e9871061341ac8e28"},
+]
+
+[package.dependencies]
+texttable = ">=1.6.2"
+
+[package.extras]
+cairo = ["cairocffi (>=1.2.0)"]
+doc = ["Sphinx (>=7.0.0)", "pydoctor (>=23.4.0)", "sphinx-gallery (>=0.14.0)", "sphinx-rtd-theme (>=1.3.0)"]
+matplotlib = ["matplotlib (>=3.6.0)"]
+plotly = ["plotly (>=5.3.0)"]
+plotting = ["cairocffi (>=1.2.0)"]
+test = ["Pillow (>=9)", "cairocffi (>=1.2.0)", "matplotlib (>=3.6.0)", "networkx (>=2.5)", "numpy (>=1.19.0)", "pandas (>=1.1.0)", "plotly (>=5.3.0)", "pytest (>=7.0.1)", "pytest-timeout (>=2.1.0)", "scipy (>=1.5.0)"]
+test-musl = ["cairocffi (>=1.2.0)", "networkx (>=2.5)", "pytest (>=7.0.1)", "pytest-timeout (>=2.1.0)"]
+
+[[package]]
name = "imagesize"
version = "1.4.1"
description = "Getting image size from png/jpeg/jpeg2000/gif file"
@@ -480,6 +560,21 @@
testing = ["flit-core (>=2,<4)", "poetry-core (>=1.0.0)", "pytest (>=7.2.0)", "pytest-rerunfailures", "pytest-xdist", "tomli-w"]
[[package]]
+name = "plotly"
+version = "5.23.0"
+description = "An open-source, interactive data visualization library for Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "plotly-5.23.0-py3-none-any.whl", hash = "sha256:76cbe78f75eddc10c56f5a4ee3e7ccaade7c0a57465546f02098c0caed6c2d1a"},
+ {file = "plotly-5.23.0.tar.gz", hash = "sha256:89e57d003a116303a34de6700862391367dd564222ab71f8531df70279fc0193"},
+]
+
+[package.dependencies]
+packaging = "*"
+tenacity = ">=6.2.0"
+
+[[package]]
name = "prettytable"
version = "3.10.2"
description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format"
@@ -497,6 +592,20 @@
tests = ["pytest", "pytest-cov", "pytest-lazy-fixtures"]
[[package]]
+name = "pydevicetree"
+version = "0.0.13"
+description = "A library for parsing Devicetree Source v1"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "pydevicetree-0.0.13-py3-none-any.whl", hash = "sha256:d61c695cec925b90a8b5740053f4b604e51154a9b36e62a2f12ed9ceaf2f8c38"},
+ {file = "pydevicetree-0.0.13.tar.gz", hash = "sha256:5700c05df89bad8fd729c11aa6f764a3323bcb3796f13b32481ae34445cfc1b7"},
+]
+
+[package.dependencies]
+pyparsing = "*"
+
+[[package]]
name = "pyelftools"
version = "0.29"
description = "Library for analyzing ELF files and DWARF debugging information"
@@ -522,6 +631,20 @@
windows-terminal = ["colorama (>=0.4.6)"]
[[package]]
+name = "pyparsing"
+version = "3.1.2"
+description = "pyparsing module - Classes and methods to define and execute parsing grammars"
+optional = false
+python-versions = ">=3.6.8"
+files = [
+ {file = "pyparsing-3.1.2-py3-none-any.whl", hash = "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742"},
+ {file = "pyparsing-3.1.2.tar.gz", hash = "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad"},
+]
+
+[package.extras]
+diagrams = ["jinja2", "railroad-diagrams"]
+
+[[package]]
name = "pyproject-hooks"
version = "1.1.0"
description = "Wrappers to call pyproject.toml-based build backend hooks."
@@ -883,6 +1006,32 @@
cairosvg = ["cairosvg (>=1.0)"]
[[package]]
+name = "tenacity"
+version = "9.0.0"
+description = "Retry code until it succeeds"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "tenacity-9.0.0-py3-none-any.whl", hash = "sha256:93de0c98785b27fcf659856aa9f54bfbd399e29969b0621bc7f762bd441b4539"},
+ {file = "tenacity-9.0.0.tar.gz", hash = "sha256:807f37ca97d62aa361264d497b0e31e92b8027044942bfa756160d908320d73b"},
+]
+
+[package.extras]
+doc = ["reno", "sphinx"]
+test = ["pytest", "tornado (>=4.5)", "typeguard"]
+
+[[package]]
+name = "texttable"
+version = "1.7.0"
+description = "module to create simple ASCII tables"
+optional = false
+python-versions = "*"
+files = [
+ {file = "texttable-1.7.0-py2.py3-none-any.whl", hash = "sha256:72227d592c82b3d7f672731ae73e4d1f88cd8e2ef5b075a7a7f01a23a3743917"},
+ {file = "texttable-1.7.0.tar.gz", hash = "sha256:2d2068fb55115807d3ac77a4ca68fa48803e84ebb0ee2340f858107a36522638"},
+]
+
+[[package]]
name = "tlc"
version = "0.9.0"
description = "Transfer List Compiler (TLC) is a Python-based CLI for efficiently handling transfer lists."
@@ -1005,4 +1154,4 @@
[metadata]
lock-version = "2.0"
python-versions = "^3.8"
-content-hash = "8798a2d1efd456c3b68ae464a216f015afaa1bbb653a905148bef17ab8ce278e"
+content-hash = "d893034cad02533bc86fb98c7d93a0eac6a755fea5efd553924e4762ed3f1fdb"
diff --git a/pyproject.toml b/pyproject.toml
index 03d898e..f0b3925 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -14,6 +14,7 @@
[tool.poetry.dependencies]
python = "^3.8"
+cot-dt2c = {path = "tools/cot_dt2c", develop = true}
tlc = {path = "tools/tlc"}
[tool.poetry.group.docs]
diff --git a/services/spd/pncd/pncd_common.c b/services/spd/pncd/pncd_common.c
index 6fdb629..8e89491 100644
--- a/services/spd/pncd/pncd_common.c
+++ b/services/spd/pncd/pncd_common.c
@@ -67,8 +67,9 @@
/* Apply the Secure EL1 system register context and switch to it */
assert(cm_get_context(SECURE) == &pnc_ctx->cpu_ctx);
cm_el1_sysregs_context_restore(SECURE);
+
#if CTX_INCLUDE_FPREGS
- fpregs_context_restore(get_fpregs_ctx(cm_get_context(SECURE)));
+ simd_ctx_restore(SECURE);
#endif
cm_set_next_eret_context(SECURE);
@@ -90,8 +91,9 @@
/* Save the Secure EL1 system register context */
assert(cm_get_context(SECURE) == &pnc_ctx->cpu_ctx);
cm_el1_sysregs_context_save(SECURE);
+
#if CTX_INCLUDE_FPREGS
- fpregs_context_save(get_fpregs_ctx(cm_get_context(SECURE)));
+ simd_ctx_save(SECURE, false);
#endif
assert(pnc_ctx->c_rt_ctx != 0);
diff --git a/services/spd/pncd/pncd_main.c b/services/spd/pncd/pncd_main.c
index 99c4aa1..cc1c1f2 100644
--- a/services/spd/pncd/pncd_main.c
+++ b/services/spd/pncd/pncd_main.c
@@ -55,8 +55,9 @@
assert(sec_state_is_valid(security_state));
cm_el1_sysregs_context_save((uint32_t) security_state);
+
#if CTX_INCLUDE_FPREGS
- fpregs_context_save(get_fpregs_ctx(cm_get_context(security_state)));
+ simd_ctx_save((uint32_t)security_state, false);
#endif
}
@@ -72,8 +73,9 @@
/* Restore state */
cm_el1_sysregs_context_restore((uint32_t) security_state);
+
#if CTX_INCLUDE_FPREGS
- fpregs_context_restore(get_fpregs_ctx(cm_get_context(security_state)));
+ simd_ctx_restore((uint32_t)security_state);
#endif
cm_set_next_eret_context((uint32_t) security_state);
diff --git a/services/spd/trusty/trusty.c b/services/spd/trusty/trusty.c
index f2048a3..aae2d9a 100644
--- a/services/spd/trusty/trusty.c
+++ b/services/spd/trusty/trusty.c
@@ -118,8 +118,10 @@
* when it's needed the PSCI caller has preserved FP context before
* going here.
*/
- if (r0 != SMC_FC_CPU_SUSPEND && r0 != SMC_FC_CPU_RESUME)
- fpregs_context_save(get_fpregs_ctx(cm_get_context(security_state)));
+ if (r0 != SMC_FC_CPU_SUSPEND && r0 != SMC_FC_CPU_RESUME) {
+ simd_ctx_save(security_state, false);
+ }
+
cm_el1_sysregs_context_save(security_state);
ctx->saved_security_state = security_state;
@@ -128,8 +130,9 @@
assert(ctx->saved_security_state == ((security_state == 0U) ? 1U : 0U));
cm_el1_sysregs_context_restore(security_state);
- if (r0 != SMC_FC_CPU_SUSPEND && r0 != SMC_FC_CPU_RESUME)
- fpregs_context_restore(get_fpregs_ctx(cm_get_context(security_state)));
+ if (r0 != SMC_FC_CPU_SUSPEND && r0 != SMC_FC_CPU_RESUME) {
+ simd_ctx_restore(security_state);
+ }
cm_set_next_eret_context(security_state);
@@ -320,7 +323,7 @@
ep_info = bl31_plat_get_next_image_ep_info(SECURE);
assert(ep_info != NULL);
- fpregs_context_save(get_fpregs_ctx(cm_get_context(NON_SECURE)));
+ simd_ctx_save(NON_SECURE, false);
cm_el1_sysregs_context_save(NON_SECURE);
cm_set_context(&ctx->cpu_ctx, SECURE);
@@ -337,7 +340,7 @@
}
cm_el1_sysregs_context_restore(SECURE);
- fpregs_context_restore(get_fpregs_ctx(cm_get_context(SECURE)));
+ simd_ctx_restore(SECURE);
cm_set_next_eret_context(SECURE);
ctx->saved_security_state = ~0U; /* initial saved state is invalid */
@@ -346,7 +349,7 @@
(void)trusty_context_switch_helper(&ctx->saved_sp, &zero_args);
cm_el1_sysregs_context_restore(NON_SECURE);
- fpregs_context_restore(get_fpregs_ctx(cm_get_context(NON_SECURE)));
+ simd_ctx_restore(NON_SECURE);
cm_set_next_eret_context(NON_SECURE);
return 1;
diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c
index b9c83fa..53afb17 100644
--- a/services/std_svc/drtm/drtm_main.c
+++ b/services/std_svc/drtm/drtm_main.c
@@ -808,12 +808,12 @@
case ARM_DRTM_SVC_GET_ERROR:
INFO("DRTM service handler: get error\n");
- drtm_get_error(handle);
+ return drtm_get_error(handle);
break; /* not reached */
case ARM_DRTM_SVC_SET_ERROR:
INFO("DRTM service handler: set error\n");
- drtm_set_error(x1, handle);
+ return drtm_set_error(x1, handle);
break; /* not reached */
case ARM_DRTM_SVC_SET_TCB_HASH:
diff --git a/services/std_svc/drtm/drtm_remediation.c b/services/std_svc/drtm/drtm_remediation.c
index 696b4ea..81d27ec 100644
--- a/services/std_svc/drtm/drtm_remediation.c
+++ b/services/std_svc/drtm/drtm_remediation.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022 Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2024 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -21,7 +21,7 @@
rc = plat_set_drtm_error(x1);
if (rc != 0) {
- SMC_RET1(ctx, INTERNAL_ERROR);
+ SMC_RET1(ctx, NOT_FOUND);
}
SMC_RET1(ctx, SUCCESS);
@@ -35,7 +35,7 @@
rc = plat_get_drtm_error(&error_code);
if (rc != 0) {
- SMC_RET1(ctx, INTERNAL_ERROR);
+ SMC_RET1(ctx, NOT_FOUND);
}
SMC_RET2(ctx, SUCCESS, error_code);
diff --git a/services/std_svc/errata_abi/cpu_errata_info.h b/services/std_svc/errata_abi/cpu_errata_info.h
index 61e1076..d688431 100644
--- a/services/std_svc/errata_abi/cpu_errata_info.h
+++ b/services/std_svc/errata_abi/cpu_errata_info.h
@@ -8,6 +8,7 @@
#define ERRATA_CPUSPEC_H
#include <stdint.h>
+#include <arch.h>
#include <arch_helpers.h>
#if __aarch64__
@@ -31,8 +32,6 @@
/* Default values for unused memory in the array */
#define UNDEF_ERRATA {UINT_MAX, UCHAR_MAX, UCHAR_MAX}
-#define EXTRACT_PARTNUM(x) ((x >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
-
#define RXPX_RANGE(x, y, z) (((x >= y) && (x <= z)) ? true : false)
/*
diff --git a/services/std_svc/sdei/sdei_main.c b/services/std_svc/sdei/sdei_main.c
index 59a1673..01cc131 100644
--- a/services/std_svc/sdei/sdei_main.c
+++ b/services/std_svc/sdei/sdei_main.c
@@ -744,7 +744,9 @@
return SDEI_ENOMEM;
/* The returned mapping must be dynamic */
- assert(is_map_dynamic(map));
+ if (!is_map_dynamic(map)) {
+ return SDEI_ENOMEM;
+ }
/*
* We cannot assert for bound maps here, as we might be racing
diff --git a/services/std_svc/spm/el3_spmc/spmc_setup.c b/services/std_svc/spm/el3_spmc/spmc_setup.c
index e8beae1..4360832 100644
--- a/services/std_svc/spm/el3_spmc/spmc_setup.c
+++ b/services/std_svc/spm/el3_spmc/spmc_setup.c
@@ -322,14 +322,7 @@
write_el1_ctx_common(get_el1_sysregs_ctx(ctx), mair_el1,
mmu_cfg_params[MMU_CFG_MAIR]);
- /* Store the initialised SCTLR_EL1 value in the cpu_context */
-#if (ERRATA_SPECULATIVE_AT)
- write_ctx_reg(get_errata_speculative_at_ctx(ctx),
- CTX_ERRATA_SPEC_AT_TCR_EL1, mmu_cfg_params[MMU_CFG_TCR]);
-#else
- write_el1_ctx_common(get_el1_sysregs_ctx(ctx), tcr_el1,
- mmu_cfg_params[MMU_CFG_TCR]);
-#endif /* ERRATA_SPECULATIVE_AT */
+ write_ctx_tcr_el1_reg_errata(ctx, mmu_cfg_params[MMU_CFG_TCR]);
write_el1_ctx_common(get_el1_sysregs_ctx(ctx), ttbr0_el1,
mmu_cfg_params[MMU_CFG_TTBR0]);
@@ -340,12 +333,7 @@
u_register_t sctlr_el1_val;
/* Setup SCTLR_EL1 */
-#if (ERRATA_SPECULATIVE_AT)
- sctlr_el1_val = read_ctx_reg(get_errata_speculative_at_ctx(ctx),
- CTX_ERRATA_SPEC_AT_SCTLR_EL1);
-#else
- sctlr_el1_val = read_el1_ctx_common(get_el1_sysregs_ctx(ctx), sctlr_el1);
-#endif /* ERRATA_SPECULATIVE_AT */
+ sctlr_el1_val = read_ctx_sctlr_el1_reg_errata(ctx);
sctlr_el1_val |=
/*SCTLR_EL1_RES1 |*/
@@ -381,12 +369,7 @@
);
/* Store the initialised SCTLR_EL1 value in the cpu_context */
-#if (ERRATA_SPECULATIVE_AT)
- write_ctx_reg(get_errata_speculative_at_ctx(ctx),
- CTX_ERRATA_SPEC_AT_SCTLR_EL1, sctlr_el1_val);
-#else
- write_el1_ctx_common(get_el1_sysregs_ctx(ctx), sctlr_el1, sctlr_el1_val);
-#endif /* ERRATA_SPECULATIVE_AT */
+ write_ctx_sctlr_el1_reg_errata(ctx, sctlr_el1_val);
}
static void spmc_el0_sp_setup_system_registers(struct secure_partition_desc *sp,
diff --git a/services/std_svc/spm/spm_mm/spm_mm_main.c b/services/std_svc/spm/spm_mm/spm_mm_main.c
index 1ff7bb7..34e2c00 100644
--- a/services/std_svc/spm/spm_mm/spm_mm_main.c
+++ b/services/std_svc/spm/spm_mm/spm_mm_main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,6 +13,7 @@
#include <common/debug.h>
#include <common/runtime_svc.h>
#include <lib/el3_runtime/context_mgmt.h>
+#include <lib/el3_runtime/simd_ctx.h>
#include <lib/smccc.h>
#include <lib/spinlock.h>
#include <lib/utils.h>
@@ -190,13 +191,13 @@
uint64_t rc;
sp_context_t *sp_ptr = &sp_ctx;
-#if CTX_INCLUDE_FPREGS
+#if CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS
/*
- * SP runs to completion, no need to restore FP registers of secure context.
- * Save FP registers only for non secure context.
+ * SP runs to completion, no need to restore FP/SVE registers of secure context.
+ * Save FP/SVE registers only for non secure context.
*/
- fpregs_context_save(get_fpregs_ctx(cm_get_context(NON_SECURE)));
-#endif
+ simd_ctx_save(NON_SECURE, false);
+#endif /* CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS */
/* Wait until the Secure Partition is idle and set it to busy. */
sp_state_wait_switch(sp_ptr, SP_STATE_IDLE, SP_STATE_BUSY);
@@ -216,13 +217,13 @@
assert(sp_ptr->state == SP_STATE_BUSY);
sp_state_set(sp_ptr, SP_STATE_IDLE);
-#if CTX_INCLUDE_FPREGS
+#if CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS
/*
- * SP runs to completion, no need to save FP registers of secure context.
- * Restore only non secure world FP registers.
+ * SP runs to completion, no need to save FP/SVE registers of secure context.
+ * Restore only non secure world FP/SVE registers.
*/
- fpregs_context_restore(get_fpregs_ctx(cm_get_context(NON_SECURE)));
-#endif
+ simd_ctx_restore(NON_SECURE);
+#endif /* CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS */
return rc;
}
diff --git a/services/std_svc/spm/spm_mm/spm_mm_setup.c b/services/std_svc/spm/spm_mm/spm_mm_setup.c
index bb9c7a9..de05459 100644
--- a/services/std_svc/spm/spm_mm/spm_mm_setup.c
+++ b/services/std_svc/spm/spm_mm/spm_mm_setup.c
@@ -124,26 +124,13 @@
write_el1_ctx_common(get_el1_sysregs_ctx(ctx), mair_el1,
mmu_cfg_params[MMU_CFG_MAIR]);
-
- /* Store the initialised SCTLR_EL1 value in the cpu_context */
-#if (ERRATA_SPECULATIVE_AT)
- write_ctx_reg(get_errata_speculative_at_ctx(ctx),
- CTX_ERRATA_SPEC_AT_TCR_EL1, mmu_cfg_params[MMU_CFG_TCR]);
-#else
- write_el1_ctx_common(get_el1_sysregs_ctx(ctx), tcr_el1,
- mmu_cfg_params[MMU_CFG_TCR]);
-#endif /* ERRATA_SPECULATIVE_AT */
+ write_ctx_tcr_el1_reg_errata(ctx, mmu_cfg_params[MMU_CFG_TCR]);
write_el1_ctx_common(get_el1_sysregs_ctx(ctx), ttbr0_el1,
mmu_cfg_params[MMU_CFG_TTBR0]);
/* Setup SCTLR_EL1 */
-#if (ERRATA_SPECULATIVE_AT)
- sctlr_el1_val = read_ctx_reg(get_errata_speculative_at_ctx(ctx),
- CTX_ERRATA_SPEC_AT_SCTLR_EL1);
-#else
- sctlr_el1_val = read_el1_ctx_common(get_el1_sysregs_ctx(ctx), sctlr_el1);
-#endif /* ERRATA_SPECULATIVE_AT */
+ sctlr_el1_val = read_ctx_sctlr_el1_reg_errata(ctx);
sctlr_el1_val |=
/*SCTLR_EL1_RES1 |*/
@@ -180,12 +167,7 @@
);
/* Store the initialised SCTLR_EL1 value in the cpu_context */
-#if (ERRATA_SPECULATIVE_AT)
- write_ctx_reg(get_errata_speculative_at_ctx(ctx),
- CTX_ERRATA_SPEC_AT_SCTLR_EL1, sctlr_el1_val);
-#else
- write_el1_ctx_common(get_el1_sysregs_ctx(ctx), sctlr_el1, sctlr_el1_val);
-#endif /* ERRATA_SPECULATIVE_AT */
+ write_ctx_sctlr_el1_reg_errata(ctx, sctlr_el1_val);
/*
* Setup other system registers
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
index e3d7fbd..3953b24 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -215,6 +215,14 @@
cm_el2_sysregs_context_save(NON_SECURE);
#else
cm_el1_sysregs_context_save(NON_SECURE);
+
+#if CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS
+ /*
+ * The hint bit denoting absence of SVE live state is effectively false
+ * in this scenario where execution was trapped to EL3 due to FIQ.
+ */
+ simd_ctx_save(NON_SECURE, false);
+#endif
#endif
/* Convey the event to the SPMC through the FFA_INTERRUPT interface. */
@@ -230,7 +238,14 @@
/* Mark current core as handling a secure interrupt. */
ctx->secure_interrupt_ongoing = true;
+#if CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS
+ simd_ctx_restore(SECURE);
+#endif
rc = spmd_spm_core_sync_entry(ctx);
+
+#if CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS
+ simd_ctx_save(SECURE, false);
+#endif
if (rc != 0ULL) {
ERROR("%s failed (%" PRId64 ") on CPU%u\n", __func__, rc, plat_my_core_pos());
}
@@ -241,6 +256,10 @@
cm_el2_sysregs_context_restore(NON_SECURE);
#else
cm_el1_sysregs_context_restore(NON_SECURE);
+
+#if CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS
+ simd_ctx_restore(NON_SECURE);
+#endif
#endif
cm_set_next_eret_context(NON_SECURE);
@@ -678,6 +697,10 @@
cm_el2_sysregs_context_save(secure_state_in);
#else
cm_el1_sysregs_context_save(secure_state_in);
+#if CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS
+ /* Forward the hint bit denoting the absence of SVE live state. */
+ simd_ctx_save(secure_state_in, (!secure_origin && (is_sve_hint_set(flags) == true)));
+#endif
#endif
/* Restore outgoing security state */
@@ -685,6 +708,9 @@
cm_el2_sysregs_context_restore(secure_state_out);
#else
cm_el1_sysregs_context_restore(secure_state_out);
+#if CTX_INCLUDE_FPREGS || CTX_INCLUDE_SVE_REGS
+ simd_ctx_restore(secure_state_out);
+#endif
#endif
cm_set_next_eret_context(secure_state_out);
@@ -783,19 +809,6 @@
&& (ffa_endpoint_source(ep) == spmc_attrs.spmc_id));
}
-/******************************************************************************
- * spmd_handle_spmc_message
- *****************************************************************************/
-static int spmd_handle_spmc_message(unsigned long long msg,
- unsigned long long parm1, unsigned long long parm2,
- unsigned long long parm3, unsigned long long parm4)
-{
- VERBOSE("%s %llx %llx %llx %llx %llx\n", __func__,
- msg, parm1, parm2, parm3, parm4);
-
- return -EINVAL;
-}
-
/*******************************************************************************
* This function forwards FF-A SMCs to either the main SPMD handler or the
* SPMC at EL3, depending on the origin security state, if enabled.
@@ -1097,6 +1110,7 @@
case FFA_MSG_SEND_DIRECT_REQ_SMC32:
case FFA_MSG_SEND_DIRECT_REQ_SMC64:
+ case FFA_MSG_SEND_DIRECT_REQ2_SMC64:
/*
* Regardless of secure_origin, SPMD logical partitions cannot
* handle direct messages. They can only initiate direct
@@ -1130,35 +1144,8 @@
}
}
if (secure_origin && spmd_is_spmc_message(x1)) {
- ret = spmd_handle_spmc_message(x3, x4,
- SMC_GET_GP(handle, CTX_GPREG_X5),
- SMC_GET_GP(handle, CTX_GPREG_X6),
- SMC_GET_GP(handle, CTX_GPREG_X7));
-
- SMC_RET8(handle, FFA_SUCCESS_SMC32,
- FFA_TARGET_INFO_MBZ, ret,
- FFA_PARAM_MBZ, FFA_PARAM_MBZ,
- FFA_PARAM_MBZ, FFA_PARAM_MBZ,
- FFA_PARAM_MBZ);
- } else {
- /* Forward direct message to the other world */
- return spmd_smc_forward(smc_fid, secure_origin,
- x1, x2, x3, x4, cookie,
- handle, flags);
- }
- break; /* Not reached */
-
- case FFA_MSG_SEND_DIRECT_REQ2_SMC64:
- if (!secure_origin) {
- /* Validate source endpoint is non-secure for non-secure caller. */
- if (ffa_is_secure_world_id(ffa_endpoint_source(x1))) {
return spmd_ffa_error_return(handle,
- FFA_ERROR_INVALID_PARAMETER);
- }
- }
- /* FFA_MSG_SEND_DIRECT_REQ2 not used for framework messages. */
- if (secure_origin && spmd_is_spmc_message(x1)) {
- return spmd_ffa_error_return(handle, FFA_ERROR_INVALID_PARAMETER);
+ FFA_ERROR_DENIED);
} else {
/* Forward direct message to the other world */
return spmd_smc_forward(smc_fid, secure_origin,
@@ -1169,6 +1156,7 @@
case FFA_MSG_SEND_DIRECT_RESP_SMC32:
case FFA_MSG_SEND_DIRECT_RESP_SMC64:
+ case FFA_MSG_SEND_DIRECT_RESP2_SMC64:
if (secure_origin && (spmd_is_spmc_message(x1) ||
is_spmd_logical_sp_dir_req_in_progress(ctx))) {
spmd_spm_core_sync_exit(0ULL);
@@ -1179,12 +1167,6 @@
handle, flags);
}
break; /* Not reached */
- case FFA_MSG_SEND_DIRECT_RESP2_SMC64:
- /* Forward direct message to the other world */
- return spmd_smc_forward(smc_fid, secure_origin,
- x1, x2, x3, x4, cookie,
- handle, flags);
- break; /* Not reached */
case FFA_RX_RELEASE:
case FFA_RXTX_MAP_SMC32:
case FFA_RXTX_MAP_SMC64:
diff --git a/tools/cert_create/include/key.h b/tools/cert_create/include/key.h
index e0ecdae..f7adfab 100644
--- a/tools/cert_create/include/key.h
+++ b/tools/cert_create/include/key.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -65,35 +65,35 @@
const char *desc; /* Key description (debug purposes) */
char *fn; /* Filename to load/store the key */
EVP_PKEY *key; /* Key container */
-} key_t;
+} cert_key_t;
/* Exported API */
int key_init(void);
-key_t *key_get_by_opt(const char *opt);
+cert_key_t *key_get_by_opt(const char *opt);
#if !USING_OPENSSL3
-int key_new(key_t *key);
+int key_new(cert_key_t *key);
#endif
-int key_create(key_t *key, int type, int key_bits);
-unsigned int key_load(key_t *key);
-int key_store(key_t *key);
+int key_create(cert_key_t *key, int type, int key_bits);
+unsigned int key_load(cert_key_t *key);
+int key_store(cert_key_t *key);
void key_cleanup(void);
/* Macro to register the keys used in the CoT */
#define REGISTER_KEYS(_keys) \
- key_t *def_keys = &_keys[0]; \
+ cert_key_t *def_keys = &_keys[0]; \
const unsigned int num_def_keys = sizeof(_keys)/sizeof(_keys[0])
/* Macro to register the platform defined keys used in the CoT */
#define PLAT_REGISTER_KEYS(_pdef_keys) \
- key_t *pdef_keys = &_pdef_keys[0]; \
+ cert_key_t *pdef_keys = &_pdef_keys[0]; \
const unsigned int num_pdef_keys = sizeof(_pdef_keys)/sizeof(_pdef_keys[0])
/* Exported variables */
-extern key_t *def_keys;
+extern cert_key_t *def_keys;
extern const unsigned int num_def_keys;
-extern key_t *pdef_keys;
+extern cert_key_t *pdef_keys;
extern const unsigned int num_pdef_keys;
-extern key_t *keys;
+extern cert_key_t *keys;
extern unsigned int num_keys;
#endif /* KEY_H */
diff --git a/tools/cert_create/src/cca/cot.c b/tools/cert_create/src/cca/cot.c
index 372d908..658b81c 100644
--- a/tools/cert_create/src/cca/cot.c
+++ b/tools/cert_create/src/cca/cot.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -410,7 +410,7 @@
REGISTER_EXTENSIONS(cot_ext);
/* Keys used to establish the chain of trust. */
-static key_t cot_keys[] = {
+static cert_key_t cot_keys[] = {
[ROT_KEY] = {
.id = ROT_KEY,
.opt = "rot-key",
diff --git a/tools/cert_create/src/dualroot/cot.c b/tools/cert_create/src/dualroot/cot.c
index 81a7d75..d2c15bf 100644
--- a/tools/cert_create/src/dualroot/cot.c
+++ b/tools/cert_create/src/dualroot/cot.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -536,7 +536,7 @@
/* Keys used to establish the chain of trust. */
-static key_t cot_keys[] = {
+static cert_key_t cot_keys[] = {
[ROT_KEY] = {
.id = ROT_KEY,
.opt = "rot-key",
diff --git a/tools/cert_create/src/key.c b/tools/cert_create/src/key.c
index f6ceeda..190c096 100644
--- a/tools/cert_create/src/key.c
+++ b/tools/cert_create/src/key.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -26,14 +26,14 @@
#define MAX_FILENAME_LEN 1024
-key_t *keys;
+cert_key_t *keys;
unsigned int num_keys;
#if !USING_OPENSSL3
/*
* Create a new key container
*/
-int key_new(key_t *key)
+int key_new(cert_key_t *key)
{
/* Create key pair container */
key->key = EVP_PKEY_new();
@@ -45,7 +45,7 @@
}
#endif
-static int key_create_rsa(key_t *key, int key_bits)
+static int key_create_rsa(cert_key_t *key, int key_bits)
{
#if USING_OPENSSL3
EVP_PKEY *rsa = EVP_RSA_gen(key_bits);
@@ -99,7 +99,7 @@
#ifndef OPENSSL_NO_EC
#if USING_OPENSSL3
-static int key_create_ecdsa(key_t *key, int key_bits, const char *curve)
+static int key_create_ecdsa(cert_key_t *key, int key_bits, const char *curve)
{
EVP_PKEY *ec = EVP_EC_gen(curve);
if (ec == NULL) {
@@ -111,7 +111,7 @@
return 1;
}
-static int key_create_ecdsa_nist(key_t *key, int key_bits)
+static int key_create_ecdsa_nist(cert_key_t *key, int key_bits)
{
if (key_bits == 384) {
return key_create_ecdsa(key, key_bits, "secp384r1");
@@ -121,17 +121,17 @@
}
}
-static int key_create_ecdsa_brainpool_r(key_t *key, int key_bits)
+static int key_create_ecdsa_brainpool_r(cert_key_t *key, int key_bits)
{
return key_create_ecdsa(key, key_bits, "brainpoolP256r1");
}
-static int key_create_ecdsa_brainpool_t(key_t *key, int key_bits)
+static int key_create_ecdsa_brainpool_t(cert_key_t *key, int key_bits)
{
return key_create_ecdsa(key, key_bits, "brainpoolP256t1");
}
#else
-static int key_create_ecdsa(key_t *key, int key_bits, const int curve_id)
+static int key_create_ecdsa(cert_key_t *key, int key_bits, const int curve_id)
{
EC_KEY *ec;
@@ -158,7 +158,7 @@
return 0;
}
-static int key_create_ecdsa_nist(key_t *key, int key_bits)
+static int key_create_ecdsa_nist(cert_key_t *key, int key_bits)
{
if (key_bits == 384) {
return key_create_ecdsa(key, key_bits, NID_secp384r1);
@@ -169,12 +169,12 @@
}
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
-static int key_create_ecdsa_brainpool_r(key_t *key, int key_bits)
+static int key_create_ecdsa_brainpool_r(cert_key_t *key, int key_bits)
{
return key_create_ecdsa(key, key_bits, NID_brainpoolP256r1);
}
-static int key_create_ecdsa_brainpool_t(key_t *key, int key_bits)
+static int key_create_ecdsa_brainpool_t(cert_key_t *key, int key_bits)
{
return key_create_ecdsa(key, key_bits, NID_brainpoolP256t1);
}
@@ -182,7 +182,7 @@
#endif /* USING_OPENSSL3 */
#endif /* OPENSSL_NO_EC */
-typedef int (*key_create_fn_t)(key_t *key, int key_bits);
+typedef int (*key_create_fn_t)(cert_key_t *key, int key_bits);
static const key_create_fn_t key_create_fn[KEY_ALG_MAX_NUM] = {
[KEY_ALG_RSA] = key_create_rsa,
#ifndef OPENSSL_NO_EC
@@ -194,7 +194,7 @@
#endif /* OPENSSL_NO_EC */
};
-int key_create(key_t *key, int type, int key_bits)
+int key_create(cert_key_t *key, int type, int key_bits)
{
if (type >= KEY_ALG_MAX_NUM) {
printf("Invalid key type\n");
@@ -243,7 +243,7 @@
}
-unsigned int key_load(key_t *key)
+unsigned int key_load(cert_key_t *key)
{
if (key->fn == NULL) {
VERBOSE("Key not specified\n");
@@ -273,7 +273,7 @@
return KEY_ERR_NONE;
}
-int key_store(key_t *key)
+int key_store(cert_key_t *key)
{
FILE *fp;
@@ -301,7 +301,7 @@
int key_init(void)
{
cmd_opt_t cmd_opt;
- key_t *key;
+ cert_key_t *key;
unsigned int i;
keys = malloc((num_def_keys * sizeof(def_keys[0]))
@@ -341,9 +341,9 @@
return 0;
}
-key_t *key_get_by_opt(const char *opt)
+cert_key_t *key_get_by_opt(const char *opt)
{
- key_t *key;
+ cert_key_t *key;
unsigned int i;
/* Sequential search. This is not a performance concern since the number
diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c
index edc2d68..aa21206 100644
--- a/tools/cert_create/src/main.c
+++ b/tools/cert_create/src/main.c
@@ -4,6 +4,8 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#define _POSIX_C_SOURCE 200809L
+
#include <assert.h>
#include <ctype.h>
#include <getopt.h>
@@ -69,16 +71,6 @@
static const char build_msg[] = "Built : " __TIME__ ", " __DATE__;
static const char platform_msg[] = PLAT_MSG;
-static char *strdup(const char *str)
-{
- int n = strlen(str) + 1;
- char *dup = malloc(n);
- if (dup) {
- strcpy(dup, str);
- }
- return dup;
-}
-
static const char *key_algs_str[] = {
[KEY_ALG_RSA] = "rsa",
#ifndef OPENSSL_NO_EC
@@ -178,7 +170,7 @@
{
cert_t *cert;
ext_t *ext;
- key_t *key;
+ cert_key_t *key;
int i, j;
bool valid_size;
@@ -303,7 +295,7 @@
STACK_OF(X509_EXTENSION) * sk;
X509_EXTENSION *cert_ext = NULL;
ext_t *ext;
- key_t *key;
+ cert_key_t *key;
cert_t *cert;
FILE *file;
int i, j, ext_nid, nvctr;
diff --git a/tools/cert_create/src/tbbr/tbb_key.c b/tools/cert_create/src/tbbr/tbb_key.c
index 5b84b6e..3d99067 100644
--- a/tools/cert_create/src/tbbr/tbb_key.c
+++ b/tools/cert_create/src/tbbr/tbb_key.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,7 +11,7 @@
*
* The order of the keys must follow the enumeration specified in tbb_key.h
*/
-static key_t tbb_keys[] = {
+static cert_key_t tbb_keys[] = {
[ROT_KEY] = {
.id = ROT_KEY,
.opt = "rot-key",
diff --git a/tools/cot_dt2c/.gitignore b/tools/cot_dt2c/.gitignore
new file mode 100644
index 0000000..ad4a1f1
--- /dev/null
+++ b/tools/cot_dt2c/.gitignore
@@ -0,0 +1,176 @@
+# Created by https://www.toptal.com/developers/gitignore/api/python
+# Edit at https://www.toptal.com/developers/gitignore?templates=python
+
+### Python ###
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+cover/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+.pybuilder/
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+# For a library or package, you might want to ignore these files since the code is
+# intended to run in multiple environments; otherwise, check them in:
+# .python-version
+
+# pipenv
+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+# However, in case of collaboration, if having platform-specific dependencies or dependencies
+# having no cross-platform support, pipenv may install dependencies that don't work, or not
+# install all needed dependencies.
+#Pipfile.lock
+
+# poetry
+# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
+# This is especially recommended for binary packages to ensure reproducibility, and is more
+# commonly ignored for libraries.
+# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
+#poetry.lock
+
+# pdm
+# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
+#pdm.lock
+# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
+# in version control.
+# https://pdm.fming.dev/#use-with-ide
+.pdm.toml
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# Cython debug symbols
+cython_debug/
+
+# PyCharm
+# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
+# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
+# and can be added to the global gitignore or merged into this file. For a more nuclear
+# option (not recommended) you can uncomment the following to ignore the entire idea folder.
+#.idea/
+
+### Python Patch ###
+# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
+poetry.toml
+
+# ruff
+.ruff_cache/
+
+# LSP config files
+pyrightconfig.json
+
+# End of https://www.toptal.com/developers/gitignore/api/python
diff --git a/tools/cot_dt2c/cot_dt2c/__init__.py b/tools/cot_dt2c/cot_dt2c/__init__.py
new file mode 100644
index 0000000..621c55a
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/__init__.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+# type: ignore[attr-defined]
+
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+import sys
+
+if sys.version_info >= (3, 8):
+ from importlib import metadata as importlib_metadata
+else:
+ import importlib_metadata
+
+
+def get_version() -> str:
+ try:
+ return importlib_metadata.version(__name__)
+ except importlib_metadata.PackageNotFoundError: # pragma: no cover
+ return "unknown"
+
+
+version: str = get_version()
diff --git a/tools/cot_dt2c/cot_dt2c/__main__.py b/tools/cot_dt2c/cot_dt2c/__main__.py
new file mode 100644
index 0000000..5aa4a92
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/__main__.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python3
+# type: ignore[attr-defined]
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+from cot_dt2c.cli import cli
+if __name__ == "__main__":
+ cli()
diff --git a/tools/cot_dt2c/cot_dt2c/cli.py b/tools/cot_dt2c/cot_dt2c/cli.py
new file mode 100644
index 0000000..d338430
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/cli.py
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+from pathlib import Path
+from cot_dt2c.cot_dt2c import generateMain
+from cot_dt2c.cot_dt2c import validateMain
+from cot_dt2c.cot_dt2c import visualizeMain
+from cot_dt2c.dt_validator import dtValidatorMain
+
+import click
+
+@click.group()
+@click.version_option()
+def cli():
+ pass
+
+@cli.command()
+@click.argument("inputfile", type=click.Path(dir_okay=True))
+@click.argument("outputfile", type=click.Path(dir_okay=True))
+def convert_to_c(inputfile, outputfile):
+ generateMain(inputfile, outputfile)
+
+@cli.command()
+@click.argument("inputfile", type=click.Path(dir_okay=True))
+def validate_cot(inputfile):
+ validateMain(inputfile)
+
+@cli.command()
+@click.argument("inputfile", type=click.Path(dir_okay=True))
+def visualize_cot(inputfile):
+ visualizeMain(inputfile)
+
+@cli.command()
+@click.argument("inputfiledir", type=click.Path(dir_okay=True))
+def validate_dt(inputfiledir):
+ dtValidatorMain(inputfiledir)
diff --git a/tools/cot_dt2c/cot_dt2c/cot_dt2c.py b/tools/cot_dt2c/cot_dt2c/cot_dt2c.py
new file mode 100644
index 0000000..4056aac
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/cot_dt2c.py
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+import sys
+from cot_dt2c.cot_parser import COT
+
+def generateMain(input, output=None):
+ cot = COT(input, output)
+ cot.generate_c_file()
+
+def validateMain(input):
+ cot = COT(input)
+ if not cot.validate_nodes():
+ print("not a valid CoT DT file")
+
+def visualizeMain(input):
+ cot = COT(input)
+ cot.tree_visualization()
+
+if __name__=="__main__":
+ if (len(sys.argv) < 2):
+ print("usage: python3 " + sys.argv[0] + " [dtsi file path] [optional output c file path]")
+ exit()
+ if len(sys.argv) == 3:
+ generateMain(sys.argv[1], sys.argv[2])
+ if len(sys.argv) == 2:
+ validateMain(sys.argv[1])
diff --git a/tools/cot_dt2c/cot_dt2c/cot_parser.py b/tools/cot_dt2c/cot_dt2c/cot_parser.py
new file mode 100644
index 0000000..39e51db
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/cot_parser.py
@@ -0,0 +1,673 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+import sys
+import re
+from pydevicetree.ast import CellArray, LabelReference
+from pydevicetree import Devicetree, Property, Node
+from pathlib import Path
+from typing import List, Optional
+
+class COT:
+ def __init__(self, inputfile: str, outputfile=None):
+ try:
+ self.tree = Devicetree.parseFile(inputfile)
+ except:
+ print("not a valid CoT DT file")
+ exit(1)
+
+ self.output = outputfile
+ self.input = inputfile
+ self.has_root = False
+
+ # edge cases
+ certs = self.get_all_certificates()
+ for c in certs:
+ if self.if_root(c):
+ if not c.get_fields("signing-key"):
+ c.properties.append(Property("signing-key", CellArray([LabelReference("subject_pk")])))
+
+ def print_cert_info(self, node:Node):
+ img_id = node.get_field("image-id").values[0].replace('"', "")
+ sign_key = self.get_sign_key(node)
+ nv = self.get_nv_ctr(node)
+
+ info = "<b>name:</b> {}<br><b>image-id:</b> {}<br>{}{}{}"\
+ .format(node.name, img_id, "<b>root-certificate</b><br>" if self.if_root(node) else "", \
+ "<b>signing-key:</b> " + self.extract_label(sign_key) + "<br>" if sign_key else "", \
+ "<b>nv counter:</b> " + self.extract_label(nv) + "<br>" if nv else "")
+ return info
+
+ def print_data_info(self, node:Node):
+ oid = node.get_field("oid")
+ info = "<b>name:</b> {}<br><b>oid:</b> {}<br>" \
+ .format(node.name, oid)
+
+ return info
+
+ def print_img_info(self, node:Node):
+ hash = self.extract_label(node.get_fields("hash"))
+ img_id = node.get_field("image-id").values[0].replace('"', "")
+ info = "<b>name:</b> {}<br><b>image-id:</b> {}<br><b>hash:</b> {}"\
+ .format(node.name, img_id, hash)
+
+ return info
+
+ def tree_width(self, parent_set, root):
+ ans = 1
+ stack = [root]
+
+ while stack:
+ tmp_stack = []
+ while stack:
+ cur_node = stack.pop()
+ child = parent_set[cur_node]
+ for c in child:
+ tmp_stack.append(c)
+
+ stack = tmp_stack.copy()
+ ans = max(ans, len(tmp_stack))
+
+ return ans
+
+ def resolve_lay(self, parent_set, lay, name_idx, root, bounds, break_name):
+ child = parent_set[root]
+
+ if len(child) == 0:
+ return
+
+ width = []
+ total_width = 0
+ for c in child:
+ w = self.tree_width(parent_set, c)
+ width.append(w)
+ total_width += w
+
+ allow_width = bounds[1] - bounds[0]
+ interval = allow_width / total_width
+ start = bounds[0]
+ for i, c in enumerate(child):
+ end = start + interval * width[i]
+ new_bounds = [start, end]
+ lay[name_idx[c]][0] = start + (end - start) / 2
+ if end - start < 0.28:
+ break_name.add(c)
+ start = end
+ self.resolve_lay(parent_set, lay, name_idx, c, new_bounds, break_name)
+
+ def tree_visualization(self):
+ import igraph
+ from igraph import Graph, EdgeSeq
+ import collections
+
+ cert = self.get_certificates()
+ pk = self.get_rot_keys()
+ nv = self.get_nv_counters()
+ image = self.get_images()
+
+ certs = cert.children
+ if pk:
+ pks = pk.children
+ else:
+ pks = []
+ nvs = nv.children
+ images = image.children
+
+ root_name = "CoT"
+
+ G = Graph()
+ detail = []
+ lay = []
+ name_idx = {}
+ parent_set = collections.defaultdict(list)
+
+ G.add_vertex(root_name)
+ detail.append("CoT Root")
+ name_idx[root_name] = len(lay)
+ lay.append([0,0])
+
+ G.add_vertex(cert.name)
+ G.add_edge(root_name, cert.name)
+ detail.append("All Certificates")
+ name_idx[cert.name] = len(lay)
+ lay.append([0, 1])
+ parent_set[root_name].append(cert.name)
+
+ if pk:
+ G.add_vertex(pk.name)
+ detail.append("All Public Trusted Key")
+ G.add_edge(root_name, pk.name)
+ name_idx[pk.name] = len(lay)
+ lay.append([-2.0, 1])
+ parent_set[root_name].append(pk.name)
+
+ G.add_vertex(nv.name)
+ detail.append("All NV Counters")
+ G.add_edge(root_name, nv.name)
+ name_idx[nv.name] = len(lay)
+ lay.append([2.0, 1])
+ parent_set[root_name].append(nv.name)
+
+ if pks:
+ for i, p in enumerate(pks):
+ G.add_vertex(p.name)
+ detail.append(self.print_data_info(p))
+ G.add_edge(pk.name, p.name)
+ name_idx[p.name] = len(lay)
+ parent_set[pk.name].append(p.name)
+ lay.append([0, lay[name_idx[pk.name]][1] + 1])
+
+ for c in certs:
+ G.add_vertex(c.name)
+ detail.append(self.print_cert_info(c))
+ name_idx[c.name] = len(lay)
+ if self.if_root(c):
+ G.add_edge(cert.name, c.name)
+ parent_set[cert.name].append(c.name)
+ lay.append([0, 2])
+ else:
+ parent = self.extract_label(c.get_fields("parent"))
+ G.add_edge(parent, c.name)
+ parent_set[parent].append(c.name)
+ lay.append([0, lay[name_idx[parent]][1] + 1])
+
+ for idx, i in enumerate(images):
+ G.add_vertex(i.name)
+ detail.append(self.print_img_info(i))
+ parent = self.extract_label(i.get_fields("parent"))
+ G.add_edge(parent, i.name)
+ parent_set[parent].append(i.name)
+ name_idx[i.name] = len(lay)
+ lay.append([0, lay[name_idx[parent]][1] + 1])
+
+ for i, n in enumerate(nvs):
+ G.add_vertex(n.name)
+ detail.append(self.print_data_info(n))
+ G.add_edge(nv.name, n.name)
+ name_idx[n.name] = len(lay)
+ parent_set[nv.name].append(n.name)
+ lay.append([0, lay[name_idx[nv.name]][1] + 1])
+
+ break_name = set()
+ self.resolve_lay(parent_set, lay, name_idx, root_name, [-3, 3], break_name)
+ #lay = G.layout('rt')
+
+ numVertex = len(G.get_vertex_dataframe())
+ vertices = G.get_vertex_dataframe()
+ v_label = []
+
+ for i in vertices['name']:
+ if i in break_name and len(i) > 10:
+ middle = len(i) // 2
+ v_label.append(i[:middle] + "<br>" + i[middle:])
+ else:
+ v_label.append(i)
+
+ position = {k: lay[k] for k in range(numVertex)}
+ Y = [lay[k][1] for k in range(numVertex)]
+ M = max(Y)
+
+ es = EdgeSeq(G) # sequence of edges
+ E = [e.tuple for e in G.es] # list of edges
+
+ L = len(position)
+ Xn = [position[k][0] for k in range(L)]
+ Yn = [2*M-position[k][1] for k in range(L)]
+ Xe = []
+ Ye = []
+ for edge in E:
+ Xe += [position[edge[0]][0], position[edge[1]][0], None]
+ Ye += [2*M-position[edge[0]][1], 2*M-position[edge[1]][1], None]
+
+ labels = v_label
+
+ import plotly.graph_objects as go
+ fig = go.Figure()
+ fig.add_trace(go.Scatter(x = Xe,
+ y = Ye,
+ mode = 'lines',
+ line = dict(color='rgb(210,210,210)', width=2),
+ hoverinfo = 'none'
+ ))
+ fig.add_trace(go.Scatter(x = Xn,
+ y = Yn,
+ mode = 'markers',
+ name = 'detail',
+ marker = dict(symbol = 'circle-dot',
+ size = 50,
+ color = 'rgba(135, 206, 250, 0.8)', #'#DB4551',
+ line = dict(color='MediumPurple', width=3)
+ ),
+ text=detail,
+ hoverinfo='text',
+ hovertemplate =
+ '<b>Detail</b><br>'
+ '%{text}',
+ opacity=0.8
+ ))
+
+ def make_annotations(pos, text, font_size=10, font_color='rgb(0,0,0)'):
+ L = len(pos)
+ if len(text) != L:
+ raise ValueError('The lists pos and text must have the same len')
+ annotations = []
+ for k in range(L):
+ annotations.append(
+ dict(
+ text = labels[k],
+ x = pos[k][0], y = 2*M-position[k][1],
+ xref = 'x1', yref = 'y1',
+ font = dict(color = font_color, size = font_size),
+ showarrow = False)
+ )
+ return annotations
+
+ axis = dict(showline=False, # hide axis line, grid, ticklabels and title
+ zeroline=False,
+ showgrid=False,
+ showticklabels=False,
+ )
+
+ fig.update_layout(title= 'CoT Device Tree',
+ annotations=make_annotations(position, v_label),
+ font_size=12,
+ showlegend=False,
+ xaxis=axis,
+ yaxis=axis,
+ margin=dict(l=40, r=40, b=85, t=100),
+ hovermode='closest',
+ plot_bgcolor='rgb(248,248,248)'
+ )
+
+ fig.show()
+
+ return
+
+ def if_root(self, node:Node) -> bool:
+ for p in node.properties:
+ if p.name == "root-certificate":
+ return True
+ return False
+
+ def get_sign_key(self, node:Node):
+ for p in node.properties:
+ if p.name == "signing-key":
+ return p.values
+
+ return None
+
+ def get_nv_ctr(self, node:Node):
+ for nv in node.properties:
+ if nv.name == "antirollback-counter":
+ return nv.values
+
+ return None
+
+ def extract_label(self, label) -> str:
+ if not label:
+ return label
+ return label[0].label.name
+
+ def get_auth_data(self, node:Node):
+ return node.children
+
+ def format_auth_data_val(self, node:Node, cert:Node):
+ type_desc = node.name
+ ptr = type_desc + "_buf"
+ len = "HASH_DER_LEN"
+ if re.search("_pk$", type_desc):
+ len = "PK_DER_LEN"
+
+ # edge case
+ if not self.if_root(cert) and "key_cert" in cert.name:
+ if "content_pk" in ptr:
+ ptr = "content_pk_buf"
+
+ return type_desc, ptr, len
+
+ def get_node(self, nodes: List[Node], name: str) -> Node:
+ for i in nodes:
+ if i.name == name:
+ return i
+
+ def get_certificates(self) -> Node:
+ children = self.tree.children
+ for i in children:
+ if i.name == "cot":
+ return self.get_node(i.children, "manifests")
+
+ def get_images(self)-> Node:
+ children = self.tree.children
+ for i in children:
+ if i.name == "cot":
+ return self.get_node(i.children, "images")
+
+ def get_nv_counters(self) -> Node:
+ children = self.tree.children
+ return self.get_node(children, "non_volatile_counters")
+
+ def get_rot_keys(self) -> Node:
+ children = self.tree.children
+ return self.get_node(children, "rot_keys")
+
+ def get_all_certificates(self) -> Node:
+ cert = self.get_certificates()
+ return cert.children
+
+ def get_all_images(self) -> Node:
+ image = self.get_images()
+ return image.children
+
+ def get_all_nv_counters(self) -> Node:
+ nv = self.get_nv_counters()
+ return nv.children
+
+ def get_all_pks(self) -> Node:
+ pk = self.get_rot_keys()
+ if not pk:
+ return []
+ return pk.children
+
+ def validate_cert(self, node:Node) -> bool:
+ valid = True
+ if not node.has_field("image-id"):
+ print("{} missing mandatory attribute image-id".format(node.name))
+ valid = False
+
+ if not node.has_field("root-certificate"):
+ if not node.has_field("parent"):
+ print("{} missing mandatory attribute parent".format(node.name))
+ valid = False
+ else:
+ # check if refer to non existing parent
+ certs = self.get_all_certificates()
+ found = False
+ for c in certs:
+ if c.name == self.extract_label(node.get_fields("parent")):
+ found = True
+
+ if not found:
+ print("{} refer to non existing parent".format(node.name))
+ valid = False
+
+ else:
+ self.has_root = True
+
+ child = node.children
+ if child:
+ for c in child:
+ if not c.has_field("oid"):
+ print("{} missing mandatory attribute oid".format(c.name))
+ valid = False
+
+ return valid
+
+ def validate_img(self, node:Node) -> bool:
+ valid = True
+ if not node.has_field("image-id"):
+ print("{} missing mandatory attribute image-id".format(node.name))
+ valid = False
+
+ if not node.has_field("parent"):
+ print("{} missing mandatory attribute parent".format(node.name))
+ valid = False
+
+ if not node.has_field("hash"):
+ print("{} missing mandatory attribute hash".format(node.name))
+ valid = False
+
+ # check if refer to non existing parent
+ certs = self.get_all_certificates()
+ found = False
+ for c in certs:
+ if c.name == self.extract_label(node.get_fields("parent")):
+ found = True
+
+ if not found:
+ print("{} refer to non existing parent".format(node.name))
+ valid = False
+
+ return valid
+
+ def validate_nodes(self) -> bool:
+ valid = True
+
+ certs = self.get_all_certificates()
+ images = self.get_all_images()
+
+ for n in certs:
+ node_valid = self.validate_cert(n)
+ valid = valid and node_valid
+
+ for i in images:
+ node_valid = self.validate_img(i)
+ valid = valid and node_valid
+
+ if not self.has_root:
+ print("missing root certificate")
+
+ return valid
+
+ def include_to_c(self, f):
+ f.write("#include <stddef.h>\n")
+ f.write("#include <mbedtls/version.h>\n")
+ f.write("#include <common/tbbr/cot_def.h>\n")
+ f.write("#include <drivers/auth/auth_mod.h>\n")
+ f.write("#include <platform_def.h>\n\n")
+ return
+
+ def generate_header(self, output):
+ self.include_to_c(output)
+
+ def all_cert_to_c(self, f):
+ certs = self.get_all_certificates()
+ for c in certs:
+ self.cert_to_c(c, f)
+
+ f.write("\n")
+
+ def cert_to_c(self, node: Node, f):
+ node_image_id: int = node.get_field("image-id")
+
+ f.write(f"static const auth_img_desc_t {node.name} = {{\n")
+ f.write(f"\t.img_id = {node_image_id},\n")
+ f.write("\t.img_type = IMG_CERT,\n")
+
+ if not self.if_root(node):
+ node_parent: Node = node.get_field("parent")
+
+ f.write(f"\t.parent = &{node_parent.label.name},\n")
+ else:
+ f.write("\t.parent = NULL,\n")
+
+ sign = self.get_sign_key(node)
+ nv_ctr = self.get_nv_ctr(node)
+
+ if sign or nv_ctr:
+ f.write("\t.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {\n")
+
+ if sign:
+ f.write("\t\t[0] = {\n")
+ f.write("\t\t\t.type = AUTH_METHOD_SIG,\n")
+ f.write("\t\t\t.param.sig = {\n")
+
+ f.write("\t\t\t\t.pk = &{},\n".format(self.extract_label(sign)))
+ f.write("\t\t\t\t.sig = &sig,\n")
+ f.write("\t\t\t\t.alg = &sig_alg,\n")
+ f.write("\t\t\t\t.data = &raw_data\n")
+ f.write("\t\t\t}\n")
+ f.write("\t\t}}{}\n".format("," if nv_ctr else ""))
+
+ if nv_ctr:
+ f.write("\t\t[1] = {\n")
+ f.write("\t\t\t.type = AUTH_METHOD_NV_CTR,\n")
+ f.write("\t\t\t.param.nv_ctr = {\n")
+
+ f.write("\t\t\t\t.cert_nv_ctr = &{},\n".format(self.extract_label(nv_ctr)))
+ f.write("\t\t\t\t.plat_nv_ctr = &{}\n".format(self.extract_label(nv_ctr)))
+
+ f.write("\t\t\t}\n")
+ f.write("\t\t}\n")
+
+ f.write("\t},\n")
+
+ auth_data = self.get_auth_data(node)
+ if auth_data:
+ f.write("\t.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {\n")
+
+ for i, d in enumerate(auth_data):
+ type_desc, ptr, data_len = self.format_auth_data_val(d, node)
+
+ f.write("\t\t[{}] = {{\n".format(i))
+ f.write("\t\t\t.type_desc = &{},\n".format(type_desc))
+ f.write("\t\t\t.data = {\n")
+
+ f.write("\t\t\t\t.ptr = (void *){},\n".format(ptr))
+
+ f.write("\t\t\t\t.len = (unsigned int){}\n".format(data_len))
+ f.write("\t\t\t}\n")
+
+ f.write("\t\t}}{}\n".format("," if i != len(auth_data) - 1 else ""))
+
+ f.write("\t}\n")
+
+ f.write("};\n\n")
+
+ return
+
+
+ def img_to_c(self, node:Node, f):
+ node_image_id: int = node.get_field("image-id")
+ node_parent: Node = node.get_field("parent")
+ node_hash: Node = node.get_field("hash")
+
+ f.write(f"static const auth_img_desc_t {node.name} = {{\n")
+ f.write(f"\t.img_id = {node_image_id},\n")
+ f.write("\t.img_type = IMG_RAW,\n")
+ f.write(f"\t.parent = &{node_parent.label.name},\n")
+ f.write("\t.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {\n")
+
+ f.write("\t\t[0] = {\n")
+ f.write("\t\t\t.type = AUTH_METHOD_HASH,\n")
+ f.write("\t\t\t.param.hash = {\n")
+ f.write("\t\t\t\t.data = &raw_data,\n")
+ f.write(f"\t\t\t\t.hash = &{node_hash.label.name}\n")
+ f.write("\t\t\t}\n")
+
+ f.write("\t\t}\n")
+ f.write("\t}\n")
+ f.write("};\n\n")
+
+ return
+
+ def all_img_to_c(self, f):
+ images = self.get_all_images()
+ for i in images:
+ self.img_to_c(i, f)
+
+ f.write("\n")
+
+ def nv_to_c(self, f):
+ nv_ctr = self.get_all_nv_counters()
+
+ for nv in nv_ctr:
+ nv_oid: str = nv.get_field("oid")
+
+ f.write(f"static auth_param_type_desc_t {nv.name} = "\
+ f"AUTH_PARAM_TYPE_DESC(AUTH_PARAM_NV_CTR, \"{nv_oid}\");\n")
+
+ f.write("\n")
+
+ return
+
+ def pk_to_c(self, f):
+ pks = self.get_all_pks()
+
+ for p in pks:
+ pk_oid: str = p.get_field("oid")
+
+ f.write(f"static auth_param_type_desc_t {p.name} = "\
+ f"AUTH_PARAM_TYPE_DESC(AUTH_PARAM_PUB_KEY, \"{pk_oid}\");\n")
+
+ f.write("\n")
+ return
+
+ def buf_to_c(self, f):
+ certs = self.get_all_certificates()
+
+ buffers = set()
+
+ for c in certs:
+ auth_data = self.get_auth_data(c)
+
+ for a in auth_data:
+ type_desc, ptr, data_len = self.format_auth_data_val(a, c)
+
+ if not ptr in buffers:
+ f.write(f"static unsigned char {ptr}[{data_len}];\n")
+ buffers.add(ptr)
+
+ f.write("\n")
+
+ def param_to_c(self, f):
+ f.write("static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(AUTH_PARAM_PUB_KEY, 0);\n")
+ f.write("static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(AUTH_PARAM_SIG, 0);\n")
+ f.write("static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(AUTH_PARAM_SIG_ALG, 0);\n")
+ f.write("static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(AUTH_PARAM_RAW_DATA, 0);\n")
+ f.write("\n")
+
+ certs = self.get_all_certificates()
+ for c in certs:
+ hash = c.children
+ for h in hash:
+ name = h.name
+ oid = h.get_field("oid")
+
+ if re.search("_pk$", name):
+ ty = "AUTH_PARAM_PUB_KEY"
+ elif re.search("_hash$", name):
+ ty = "AUTH_PARAM_HASH"
+
+ f.write(f"static auth_param_type_desc_t {name} = "\
+ f"AUTH_PARAM_TYPE_DESC({ty}, \"{oid}\");\n")
+
+ f.write("\n")
+
+ def cot_to_c(self, f):
+ certs = self.get_all_certificates()
+ images = self.get_all_images()
+
+ f.write("static const auth_img_desc_t * const cot_desc[] = {\n")
+
+ for i, c in enumerate(certs):
+ c_image_id: int = c.get_field("image-id")
+
+ f.write(f"\t[{c_image_id}] = &{c.name},\n")
+
+ for i, c in enumerate(images):
+ c_image_id: int = c.get_field("image-id")
+
+ f.write(f"\t[{c_image_id}] = &{c.name},\n")
+
+ f.write("};\n\n")
+ f.write("REGISTER_COT(cot_desc);\n")
+ return
+
+ def generate_c_file(self):
+ filename = Path(self.output)
+ filename.parent.mkdir(exist_ok=True, parents=True)
+
+ with open(self.output, 'w+') as output:
+ self.generate_header(output)
+ self.buf_to_c(output)
+ self.param_to_c(output)
+ self.nv_to_c(output)
+ self.pk_to_c(output)
+ self.all_cert_to_c(output)
+ self.all_img_to_c(output)
+ self.cot_to_c(output)
+
+ return
diff --git a/tools/cot_dt2c/cot_dt2c/dt_validator.py b/tools/cot_dt2c/cot_dt2c/dt_validator.py
new file mode 100644
index 0000000..ade037c
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/dt_validator.py
@@ -0,0 +1,130 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+import sys
+from os import path, walk, mkdir
+import subprocess
+from pydevicetree import Devicetree
+
+class bcolors:
+ HEADER = '\033[95m'
+ OKBLUE = '\033[94m'
+ OKCYAN = '\033[96m'
+ OKGREEN = '\033[92m'
+ WARNING = '\033[93m'
+ FAIL = '\033[91m'
+ ENDC = '\033[0m'
+ BOLD = '\033[1m'
+ UNDERLINE = '\033[4m'
+
+class DTTree:
+ def __init__(self, input):
+ self.input = input
+ self.test_dir = "./tmp"
+ self.logging_file = self.test_dir + "/result.log"
+
+ def dtValidate(self):
+ subprocess.run(["rm", "-rf", self.test_dir])
+
+ if not path.exists(self.test_dir):
+ mkdir(self.test_dir)
+
+ if path.isfile(self.input):
+ self.dtValidateFile(self.input, printInfo=True)
+ return
+
+ if path.isdir(self.input):
+ self.dtValidateFiles()
+ return
+
+ def dtValidateFile(self, input, printInfo=False):
+ valid, tree = self.dtParseFile(input, printInfo)
+
+ if not valid:
+ return False
+
+ if input.rfind("/") != -1:
+ filename = self.test_dir + input[input.rfind("/"):]
+ else:
+ filename = self.test_dir + "/" + input
+
+ f = open(filename, "w+")
+ if "/dts-v1/;" not in str(tree):
+ f.write("/dts-v1/;\n\n")
+ f.write(str(tree))
+ f.close()
+
+ if str(tree) == "":
+ return valid
+
+ return valid
+
+ def dtParseFile(self, input, printInfo=False):
+ with open(input, 'r') as f:
+ contents = f.read()
+
+ pos = contents.find("/ {")
+ if pos != -1:
+ contents = contents[pos:]
+
+ try:
+ tree = Devicetree.parseStr(contents)
+ if printInfo:
+ print(bcolors.OKGREEN + "{} parse tree successfully".format(input) + bcolors.ENDC)
+ except Exception as e:
+ if printInfo:
+ print(bcolors.FAIL + "{} parse tree failed:\t{}".format(input, str(e)) + bcolors.ENDC)
+ else:
+ f = open(self.logging_file, "a")
+ f.write("=====================================================================================\n")
+ f.write("{} result:\n".format(input))
+ f.write("{} INVALID:\t{}\n".format(input, str(e)))
+ f.close()
+ return False, None
+
+ return True, tree
+
+ def dtValidateFiles(self):
+ f = []
+ for (dirpath, dirnames, filenames) in walk(self.input):
+ f.extend(filenames)
+
+ allFile = len(f)
+ dtsiFile = 0
+ validFile = 0
+ invalidFile = 0
+
+ for i in f:
+ if (".dtsi" in i or ".dts" in i) and "cot" not in i and "fw-config" not in i:
+ dtsiFile += 1
+ valid = True
+
+ if self.input[-1] == "/":
+ valid = self.dtValidateFile(self.input + i)
+ else:
+ valid = self.dtValidateFile(self.input + "/" + i)
+
+ if valid:
+ validFile += 1
+ else:
+ invalidFile += 1
+
+ print("=====================================================")
+ print("Total File: " + str(allFile))
+ print("Total DT File: " + str(dtsiFile))
+ print("Total Valid File: " + str(validFile))
+ print("Total Invalid File: " + str(invalidFile))
+
+def dtValidatorMain(input):
+ dt = DTTree(input)
+ dt.dtValidate()
+
+if __name__=="__main__":
+ if (len(sys.argv) < 2):
+ print("usage: python3 " + sys.argv[0] + " [dtsi file path] or [dtsi folder path]")
+ exit()
+ if len(sys.argv) == 2:
+ dtValidatorMain(sys.argv[1])
diff --git a/tools/cot_dt2c/poetry.lock b/tools/cot_dt2c/poetry.lock
new file mode 100644
index 0000000..df58d54
--- /dev/null
+++ b/tools/cot_dt2c/poetry.lock
@@ -0,0 +1,334 @@
+# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
+
+[[package]]
+name = "atomicwrites"
+version = "1.4.1"
+description = "Atomic file writes."
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+ {file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"},
+]
+
+[[package]]
+name = "attrs"
+version = "24.2.0"
+description = "Classes Without Boilerplate"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"},
+ {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"},
+]
+
+[package.extras]
+benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
+tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"]
+
+[[package]]
+name = "click"
+version = "8.1.7"
+description = "Composable command line interface toolkit"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
+ {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
+
+[[package]]
+name = "igraph"
+version = "0.11.6"
+description = "High performance graph data structures and algorithms"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "igraph-0.11.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3f8b837181e8e87676be3873ce87cc92cc234efd58a2da2f6b4e050db150fcf4"},
+ {file = "igraph-0.11.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:245c4b7d7657849eff80416f5df4525c8fc44c74a981ee4d44f0ef2612c3bada"},
+ {file = "igraph-0.11.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdb7be3d165073c0136295c0808e9edc57ba096cdb26e94086abb04561f7a292"},
+ {file = "igraph-0.11.6-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58974e20df2986a1ae52a16e51ecb387cc0cbeb41c5c0ddff4d373a1bbf1d9c5"},
+ {file = "igraph-0.11.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bef14de5e8ab70724a43808b1ed14aaa6fe1002f87e592289027a3827a8f44a"},
+ {file = "igraph-0.11.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:86c1e98de2e32d074df8510bf18abfa1f4c5fda4cb28a009985a5d746b0c0125"},
+ {file = "igraph-0.11.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ebc5b3d702158abeb2e4d2414374586a2b932e1a07e48352b470600e1733d528"},
+ {file = "igraph-0.11.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0efe6d0fb22d3987a800eb3857ed04df9eb4c5dddd0998be05232cb646f1c337"},
+ {file = "igraph-0.11.6-cp38-cp38-win32.whl", hash = "sha256:f4e68b27497b1c8ada2fb2bc35ef3fa7b0d72e84306b3d648d3de240fc618c32"},
+ {file = "igraph-0.11.6-cp38-cp38-win_amd64.whl", hash = "sha256:5665b33dfbfca5f54ce9b4fea6b97903bd0e99fb1b02acf5e57e600bdfa5a355"},
+ {file = "igraph-0.11.6-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:8aabef03d787b519d1075dfc0da4a1109fb113b941334883e3e7947ac30a459e"},
+ {file = "igraph-0.11.6-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:1f2cc4a518d99cdf6cae514f85e93e56852bc8c325b3abb96037d1d690b5975f"},
+ {file = "igraph-0.11.6-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1e859238be52ab8ccc614d18f9362942bc88ce543afc12548f81ae99b10801d"},
+ {file = "igraph-0.11.6-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d61fbe5e85eb4ae9efe08c461f9bdeedb02a2b5739fbc223d324a71f40a28be2"},
+ {file = "igraph-0.11.6-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6620ba39df29fd42151becf82309b54e57148233c9c3ef890eed62e25eed8a5"},
+ {file = "igraph-0.11.6-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:59666589bb3d07f310cda2c5106a8adeeb77c2ef27fecf1c6438b6091f4ca69d"},
+ {file = "igraph-0.11.6-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:8750b6d6caebf199cf7dc41c931f58e330153779707391e30f0a29f02666fb6e"},
+ {file = "igraph-0.11.6-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:967d6f2c30fe94317da15e459374d0fb8ca3e56020412f201ecd07dd5b5352f2"},
+ {file = "igraph-0.11.6-cp39-abi3-win32.whl", hash = "sha256:9744f95a67319eb6cb487ceabf30f5d7940de34bada51f0ba63adbd23e0f94ad"},
+ {file = "igraph-0.11.6-cp39-abi3-win_amd64.whl", hash = "sha256:b80e69eb11faa9c57330a9ffebdde5808966efe1c1f638d4d4827ea04df7aca8"},
+ {file = "igraph-0.11.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0329c16092e2ea7930d5f8368666ce7cb704900cc0ea04e4afe9ea1dd46e44af"},
+ {file = "igraph-0.11.6-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:21752313f449bd8688e5688e95ea7231cea5e9199c7162535029be0d9af848ac"},
+ {file = "igraph-0.11.6-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea25e136c6c4161f53ff58868b23ff6c845193050ab0e502236d68e5d4174e32"},
+ {file = "igraph-0.11.6-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac84433a03aef15e4b810010b08882b09854a3669450ccf31e392dbe295d2a66"},
+ {file = "igraph-0.11.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac697a44e3573169fa2b28c9c37dcf9cf01e0f558b845dd7123860d4c7c8fb89"},
+ {file = "igraph-0.11.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:bdeae8bf35316eb1fb27bf667dcf5ecf5fcfb0b8f51831bc1b00c39c09c2d73b"},
+ {file = "igraph-0.11.6-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ad7e4aa442935de72554b96733bf6d7f09eac5cee97988a2562bdd3ca173cfa3"},
+ {file = "igraph-0.11.6-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:8d2818780358a686178866d01568b9df1f29678581734ad7a78882bab54df004"},
+ {file = "igraph-0.11.6-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2352276a20d979f1dea360af4202bb9f0c9a7d2c77f51815c0e625165e82013d"},
+ {file = "igraph-0.11.6-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:687fdab543b507d622fa3043f4227e5b26dc61dcf8ff8c0919fccddcc655f8b8"},
+ {file = "igraph-0.11.6-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57f7f8214cd48c9a4d97f7346a4152ba2d4ac95fb5ee0df4ecf224fce4ba3d14"},
+ {file = "igraph-0.11.6-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:2b9cc69ede53f76ffae03b066609aa90184dd68ef15da8c104a97cebb9210838"},
+ {file = "igraph-0.11.6-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:591e1e447c3f0092daf7613a3eaedab83f9a0b0adbaf7702724c5117ded038a5"},
+ {file = "igraph-0.11.6-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ca558eb331bc687bc33e5cd23717e22676e9412f8cda3a31d30c996a0487610d"},
+ {file = "igraph-0.11.6-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf43c30e08debb087c9e3da69aa5cf1b6732968da34d55a614e3421b9a452146"},
+ {file = "igraph-0.11.6-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d38e8d7db72b187d9d2211d0d06b3271fa9f32b04d49d789e2859b5480db0d0"},
+ {file = "igraph-0.11.6-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a318b059051ff78144a1c3cb880f4d933c812bcdb3d833a49cd7168d0427672"},
+ {file = "igraph-0.11.6-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2c54027add809b3c5b6685b8deca4ea4763fd000b9ea45c7ee46b7c9d61ff15e"},
+ {file = "igraph-0.11.6.tar.gz", hash = "sha256:837f233256c3319f2a35a6a80d94eafe47b43791ef4c6f9e9871061341ac8e28"},
+]
+
+[package.dependencies]
+texttable = ">=1.6.2"
+
+[package.extras]
+cairo = ["cairocffi (>=1.2.0)"]
+doc = ["Sphinx (>=7.0.0)", "pydoctor (>=23.4.0)", "sphinx-gallery (>=0.14.0)", "sphinx-rtd-theme (>=1.3.0)"]
+matplotlib = ["matplotlib (>=3.6.0)"]
+plotly = ["plotly (>=5.3.0)"]
+plotting = ["cairocffi (>=1.2.0)"]
+test = ["Pillow (>=9)", "cairocffi (>=1.2.0)", "matplotlib (>=3.6.0)", "networkx (>=2.5)", "numpy (>=1.19.0)", "pandas (>=1.1.0)", "plotly (>=5.3.0)", "pytest (>=7.0.1)", "pytest-timeout (>=2.1.0)", "scipy (>=1.5.0)"]
+test-musl = ["cairocffi (>=1.2.0)", "networkx (>=2.5)", "pytest (>=7.0.1)", "pytest-timeout (>=2.1.0)"]
+
+[[package]]
+name = "iniconfig"
+version = "2.0.0"
+description = "brain-dead simple config-ini parsing"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
+ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
+]
+
+[[package]]
+name = "mypy"
+version = "0.910"
+description = "Optional static typing for Python"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "mypy-0.910-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:a155d80ea6cee511a3694b108c4494a39f42de11ee4e61e72bc424c490e46457"},
+ {file = "mypy-0.910-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b94e4b785e304a04ea0828759172a15add27088520dc7e49ceade7834275bedb"},
+ {file = "mypy-0.910-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:088cd9c7904b4ad80bec811053272986611b84221835e079be5bcad029e79dd9"},
+ {file = "mypy-0.910-cp35-cp35m-win_amd64.whl", hash = "sha256:adaeee09bfde366d2c13fe6093a7df5df83c9a2ba98638c7d76b010694db760e"},
+ {file = "mypy-0.910-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ecd2c3fe726758037234c93df7e98deb257fd15c24c9180dacf1ef829da5f921"},
+ {file = "mypy-0.910-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d9dd839eb0dc1bbe866a288ba3c1afc33a202015d2ad83b31e875b5905a079b6"},
+ {file = "mypy-0.910-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:3e382b29f8e0ccf19a2df2b29a167591245df90c0b5a2542249873b5c1d78212"},
+ {file = "mypy-0.910-cp36-cp36m-win_amd64.whl", hash = "sha256:53fd2eb27a8ee2892614370896956af2ff61254c275aaee4c230ae771cadd885"},
+ {file = "mypy-0.910-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b6fb13123aeef4a3abbcfd7e71773ff3ff1526a7d3dc538f3929a49b42be03f0"},
+ {file = "mypy-0.910-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e4dab234478e3bd3ce83bac4193b2ecd9cf94e720ddd95ce69840273bf44f6de"},
+ {file = "mypy-0.910-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:7df1ead20c81371ccd6091fa3e2878559b5c4d4caadaf1a484cf88d93ca06703"},
+ {file = "mypy-0.910-cp37-cp37m-win_amd64.whl", hash = "sha256:0aadfb2d3935988ec3815952e44058a3100499f5be5b28c34ac9d79f002a4a9a"},
+ {file = "mypy-0.910-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ec4e0cd079db280b6bdabdc807047ff3e199f334050db5cbb91ba3e959a67504"},
+ {file = "mypy-0.910-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:119bed3832d961f3a880787bf621634ba042cb8dc850a7429f643508eeac97b9"},
+ {file = "mypy-0.910-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:866c41f28cee548475f146aa4d39a51cf3b6a84246969f3759cb3e9c742fc072"},
+ {file = "mypy-0.910-cp38-cp38-win_amd64.whl", hash = "sha256:ceb6e0a6e27fb364fb3853389607cf7eb3a126ad335790fa1e14ed02fba50811"},
+ {file = "mypy-0.910-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a85e280d4d217150ce8cb1a6dddffd14e753a4e0c3cf90baabb32cefa41b59e"},
+ {file = "mypy-0.910-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:42c266ced41b65ed40a282c575705325fa7991af370036d3f134518336636f5b"},
+ {file = "mypy-0.910-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:3c4b8ca36877fc75339253721f69603a9c7fdb5d4d5a95a1a1b899d8b86a4de2"},
+ {file = "mypy-0.910-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:c0df2d30ed496a08de5daed2a9ea807d07c21ae0ab23acf541ab88c24b26ab97"},
+ {file = "mypy-0.910-cp39-cp39-win_amd64.whl", hash = "sha256:c6c2602dffb74867498f86e6129fd52a2770c48b7cd3ece77ada4fa38f94eba8"},
+ {file = "mypy-0.910-py3-none-any.whl", hash = "sha256:ef565033fa5a958e62796867b1df10c40263ea9ded87164d67572834e57a174d"},
+ {file = "mypy-0.910.tar.gz", hash = "sha256:704098302473cb31a218f1775a873b376b30b4c18229421e9e9dc8916fd16150"},
+]
+
+[package.dependencies]
+mypy-extensions = ">=0.4.3,<0.5.0"
+toml = "*"
+typing-extensions = ">=3.7.4"
+
+[package.extras]
+dmypy = ["psutil (>=4.0)"]
+python2 = ["typed-ast (>=1.4.0,<1.5.0)"]
+
+[[package]]
+name = "mypy-extensions"
+version = "0.4.4"
+description = "Experimental type system extensions for programs checked with the mypy typechecker."
+optional = false
+python-versions = ">=2.7"
+files = [
+ {file = "mypy_extensions-0.4.4.tar.gz", hash = "sha256:c8b707883a96efe9b4bb3aaf0dcc07e7e217d7d8368eec4db4049ee9e142f4fd"},
+]
+
+[[package]]
+name = "packaging"
+version = "24.1"
+description = "Core utilities for Python packages"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"},
+ {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"},
+]
+
+[[package]]
+name = "plotly"
+version = "5.23.0"
+description = "An open-source, interactive data visualization library for Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "plotly-5.23.0-py3-none-any.whl", hash = "sha256:76cbe78f75eddc10c56f5a4ee3e7ccaade7c0a57465546f02098c0caed6c2d1a"},
+ {file = "plotly-5.23.0.tar.gz", hash = "sha256:89e57d003a116303a34de6700862391367dd564222ab71f8531df70279fc0193"},
+]
+
+[package.dependencies]
+packaging = "*"
+tenacity = ">=6.2.0"
+
+[[package]]
+name = "pluggy"
+version = "1.5.0"
+description = "plugin and hook calling mechanisms for python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"},
+ {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"},
+]
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
+
+[[package]]
+name = "py"
+version = "1.11.0"
+description = "library with cross-python path, ini-parsing, io, code, log facilities"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+files = [
+ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
+ {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
+]
+
+[[package]]
+name = "pydevicetree"
+version = "0.0.13"
+description = "A library for parsing Devicetree Source v1"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "pydevicetree-0.0.13-py3-none-any.whl", hash = "sha256:d61c695cec925b90a8b5740053f4b604e51154a9b36e62a2f12ed9ceaf2f8c38"},
+ {file = "pydevicetree-0.0.13.tar.gz", hash = "sha256:5700c05df89bad8fd729c11aa6f764a3323bcb3796f13b32481ae34445cfc1b7"},
+]
+
+[package.dependencies]
+pyparsing = "*"
+
+[[package]]
+name = "pyparsing"
+version = "3.1.2"
+description = "pyparsing module - Classes and methods to define and execute parsing grammars"
+optional = false
+python-versions = ">=3.6.8"
+files = [
+ {file = "pyparsing-3.1.2-py3-none-any.whl", hash = "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742"},
+ {file = "pyparsing-3.1.2.tar.gz", hash = "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad"},
+]
+
+[package.extras]
+diagrams = ["jinja2", "railroad-diagrams"]
+
+[[package]]
+name = "pytest"
+version = "6.2.5"
+description = "pytest: simple powerful testing with Python"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"},
+ {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"},
+]
+
+[package.dependencies]
+atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
+attrs = ">=19.2.0"
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+iniconfig = "*"
+packaging = "*"
+pluggy = ">=0.12,<2.0"
+py = ">=1.8.2"
+toml = "*"
+
+[package.extras]
+testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
+
+[[package]]
+name = "tenacity"
+version = "9.0.0"
+description = "Retry code until it succeeds"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "tenacity-9.0.0-py3-none-any.whl", hash = "sha256:93de0c98785b27fcf659856aa9f54bfbd399e29969b0621bc7f762bd441b4539"},
+ {file = "tenacity-9.0.0.tar.gz", hash = "sha256:807f37ca97d62aa361264d497b0e31e92b8027044942bfa756160d908320d73b"},
+]
+
+[package.extras]
+doc = ["reno", "sphinx"]
+test = ["pytest", "tornado (>=4.5)", "typeguard"]
+
+[[package]]
+name = "texttable"
+version = "1.7.0"
+description = "module to create simple ASCII tables"
+optional = false
+python-versions = "*"
+files = [
+ {file = "texttable-1.7.0-py2.py3-none-any.whl", hash = "sha256:72227d592c82b3d7f672731ae73e4d1f88cd8e2ef5b075a7a7f01a23a3743917"},
+ {file = "texttable-1.7.0.tar.gz", hash = "sha256:2d2068fb55115807d3ac77a4ca68fa48803e84ebb0ee2340f858107a36522638"},
+]
+
+[[package]]
+name = "toml"
+version = "0.10.2"
+description = "Python Library for Tom's Obvious, Minimal Language"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+files = [
+ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
+ {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.12.2"
+description = "Backported and Experimental Type Hints for Python 3.8+"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
+ {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
+]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.8"
+content-hash = "afa5cb49be96467a848bab753a630c6f5ec42d6750d67d29920c3e3971774e36"
diff --git a/tools/cot_dt2c/pyproject.toml b/tools/cot_dt2c/pyproject.toml
new file mode 100644
index 0000000..73251d7
--- /dev/null
+++ b/tools/cot_dt2c/pyproject.toml
@@ -0,0 +1,63 @@
+# Poetry pyproject.toml: https://python-poetry.org/docs/pyproject/
+[build-system]
+requires = ["poetry_core>=1.0.0"]
+build-backend = "poetry.core.masonry.api"
+
+[tool.poetry]
+name = "cot_dt2c"
+version = "0.1.0"
+description = "CoT-dt2c Tool is a python script to convert CoT DT file into corresponding C file"
+authors = ["Arm Ltd <tf-a@lists.trustedfirmware.org>"]
+license = "BSD-3"
+repository = "https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/"
+homepage = "https://trustedfirmware-a.readthedocs.io/en/latest/index.html"
+
+# Pypi classifiers: https://pypi.org/classifiers/
+classifiers = [
+ "Development Status :: 3 - Alpha",
+ "Intended Audience :: Developers",
+ "Operating System :: OS Independent",
+ "Topic :: Software Development :: Libraries :: Python Modules",
+ "License :: OSI Approved :: BSD License",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
+]
+
+
+[tool.poetry.dependencies]
+python = "^3.8"
+click = "^8.1.7"
+plotly = "^5.23.0"
+pydevicetree = "0.0.13"
+igraph = "^0.11.6"
+pyparsing = "^3.1.2"
+
+[tool.poetry.group.dev]
+optional = true
+
+[tool.poetry.group.dev.dependencies]
+mypy = "^0.910"
+pytest = "^6.2.5"
+
+[tool.mypy]
+# https://mypy.readthedocs.io/en/latest/config_file.html#using-a-pyproject-toml-file
+python_version = "3.8"
+pretty = true
+show_traceback = true
+color_output = true
+
+[[tool.mypy.overrides]]
+module = ["igraph", "pydevicetree", "pydevicetree.ast", "plotly", "plotly.graph_objects"]
+ignore_missing_imports = true
+
+[tool.coverage.run]
+source = ["tests"]
+
+[tool.coverage.paths]
+source = "cot_dt2c"
+
+[tool.poetry.scripts]
+# Entry points for the package https://python-poetry.org/docs/pyproject/#scripts
+# "cot-dt2c" = "cot_dt2c.__main__:cli"
+"cot-dt2c" = "cot_dt2c.__main__:cli"
diff --git a/tools/cot_dt2c/tests/test.dtsi b/tools/cot_dt2c/tests/test.dtsi
new file mode 100644
index 0000000..ee744e6
--- /dev/null
+++ b/tools/cot_dt2c/tests/test.dtsi
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file provide a valid CoT DT file
+ *
+ */
+
+#include <example/example.h>
+#include <example/example/example.h>
+
+cot {
+ manifests {
+ compatible = "arm, cert-descs";
+
+#if defined(test)
+ example_cert: example_cert {
+ root-certificate;
+ image-id =<EXAMPLE_ID>;
+ antirollback-counter = <&example_ctr>;
+
+ example_hash: example_hash
+ {
+ oid = EXAMPLE_HASH_ID;
+ };
+ };
+#endif
+ };
+
+ images {
+ compatible = "arm, img-descs";
+
+ example {
+ image-id = <EXAMPLE_ID>;
+ parent = <&example_cert>;
+ hash = <&example_hash>;
+ };
+ };
+};
+
+non_volatile_counters: non_volatile_counters {
+ compatible = "arm, non-volatile-counter";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ example_ctr: example_ctr {
+ id = <TRUSTED_NV_CTR_ID>;
+ oid = CCA_FW_NVCOUNTER_OID;
+ };
+};
+
+rot_keys {
+ example_pk: example_pk {
+ oid = EXAMPLE_PK_OID;
+ };
+};
diff --git a/tools/cot_dt2c/tests/test2.dtsi b/tools/cot_dt2c/tests/test2.dtsi
new file mode 100644
index 0000000..c4dbf83
--- /dev/null
+++ b/tools/cot_dt2c/tests/test2.dtsi
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file provide a valid CoT DT file
+ *
+ */
+
+#if test
+#include <example/example.h>
+#include <example/example/example.h>
+#endif
+
+cot
+{
+ manifests
+ {
+ compatible = "arm, cert-descs";
+#if defined (test)
+ example_cert: example_cert
+ {
+ root-certificate;
+ image-id =<EXAMPLE_ID>;
+ antirollback-counter = <&example_ctr>;
+
+ example_hash: example_hash
+ {
+ oid = EXAMPLE_HASH_ID;
+ };
+
+ };
+#endif
+ };
+
+ images
+ {
+ compatible = "arm, img-descs";
+
+ example
+ {
+ image-id = <EXAMPLE_ID>;
+ parent = <&example_cert>;
+ hash = <&example_hash>;
+ };
+ };
+};
+
+non_volatile_counters: non_volatile_counters
+{
+ compatible = "arm, non-volatile-counter";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ example_ctr: example_ctr
+ {
+ id = <TRUSTED_NV_CTR_ID>;
+ oid = CCA_FW_NVCOUNTER_OID;
+ };
+};
+
+rot_keys
+{
+ example_pk: example_pk
+ {
+ oid = EXAMPLE_PK_OID;
+ };
+};
diff --git a/tools/cot_dt2c/tests/test_invalid_bracket.dtsi b/tools/cot_dt2c/tests/test_invalid_bracket.dtsi
new file mode 100644
index 0000000..9752ecf
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_invalid_bracket.dtsi
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file provide a malformed CoT DT file that there is
+ * unmatching bracket
+ *
+ */
+
+cot {
+ manifests {
+ compatible = "arm, cert-descs";
+
+ example_cert: example_cert {
+ root-certificate;
+ image-id =<2>;
+ antirollback-counter = <&example_ctr>;
+
+ example_hash: example_hash
+ {
+ oid = "1.3.6.1.4.1.4128.2100.101";
+ };
+
+ };
+ };
+
+ images {
+ compatible = "arm, img-descs";
+
+ example {
+ image-id = <2>;
+ parent = <&example_cert>;
+ hash = <&example_hash>;
+ };
+};
+
+non_volatile_counters: non_volatile_counters {
+ compatible = "arm, non-volatile-counter";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ example_ctr: example_ctr {
+ id = <0>;
+ oid = "1.3.6.1.4.1.4128.2100.3";
+ };
+};
+
+rot_keys {
+ example_pk: example_pk {
+ oid = "1.3.6.1.4.1.4128.2100.101";
+ };
+};
diff --git a/tools/cot_dt2c/tests/test_invalid_missing_attribute.dtsi b/tools/cot_dt2c/tests/test_invalid_missing_attribute.dtsi
new file mode 100644
index 0000000..e35ab73
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_invalid_missing_attribute.dtsi
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file provide a malformed CoT DT file that there
+ * are image/certificate that missing mandantory attributes
+ *
+ */
+
+cot {
+ manifests {
+ compatible = "arm, cert-descs";
+
+ cca_content_cert: cca_content_cert {
+ root-certificate;
+ antirollback-counter = <&cca_nv_ctr>;
+
+ hw_config_hash: hw_config_hash {
+ };
+
+ soc_fw_config_hash: soc_fw_config_hash {
+ oid = "1.3.6.1.4.1.4128.2100.604";
+ };
+ };
+
+ plat_key_cert: plat_key_cert {
+ root-certificate;
+ image-id = <38>;
+ signing-key = <&prot_pk>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
+
+ plat_pk: plat_pk {
+ oid = "1.3.6.1.4.1.4128.2100.1105";
+ };
+ };
+
+ non_trusted_fw_content_cert: non_trusted_fw_content_cert {
+ image-id = <15>;
+ signing-key = <&plat_pk>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
+
+ nt_world_bl_hash: nt_world_bl_hash {
+ oid = "1.3.6.1.4.1.4128.2100.1201";
+ };
+ nt_fw_config_hash: nt_fw_config_hash {
+ oid = "1.3.6.1.4.1.4128.2100.1202";
+ };
+ };
+
+ images {
+ compatible = "arm, img-descs";
+
+ hw_config {
+ image-id = <23>;
+ hash = <&hw_config_hash>;
+ };
+
+ soc_fw_config {
+ image-id = <25>;
+ parent = <&cca_content_cert>;
+ hash = <&soc_fw_config_hash>;
+ };
+
+ bl33_image {
+ image-id = <5>;
+ parent = <&non_trusted_fw_content_cert>;
+ hash = <&nt_world_bl_hash>;
+ };
+
+ nt_fw_config {
+ image-id = <27>;
+ parent = <&non_trusted_fw_content_cert>;
+ hash = <&nt_fw_config_hash>;
+ };
+ };
+};
+
+non_volatile_counters: non_volatile_counters {
+ compatible = "arm, non-volatile-counter";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cca_nv_ctr: cca_nv_ctr {
+ id = <0>;
+ oid = "1.3.6.1.4.1.4128.2100.3";
+ };
+
+ trusted_nv_ctr: trusted_nv_ctr {
+ id = <0>;
+ oid = "1.3.6.1.4.1.4128.2100.1";
+ };
+
+ non_trusted_nv_ctr: non_trusted_nv_ctr {
+ id = <1>;
+ oid = "1.3.6.1.4.1.4128.2100.2";
+ };
+};
+
+rot_keys {
+ swd_rot_pk: swd_rot_pk {
+ oid = "1.3.6.1.4.1.4128.2100.1103";
+ };
+ prot_pk: prot_pk {
+ oid = "1.3.6.1.4.1.4128.2100.1102";
+ };
+};
diff --git a/tools/cot_dt2c/tests/test_invalid_missing_ctr.dtsi b/tools/cot_dt2c/tests/test_invalid_missing_ctr.dtsi
new file mode 100644
index 0000000..c572b1a
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_invalid_missing_ctr.dtsi
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file provide a malformed CoT DT file that there
+ * are image/certificate that missing definition of
+ * nv counters
+ *
+ */
+
+cot {
+ manifests {
+ compatible = "arm, cert-descs";
+
+ example_cert: example_cert {
+ root-certificate;
+ image-id =<2>;
+ signing-key = <&swd_rot_pk>;
+ antirollback-counter = <&example_ctr>;
+
+ example_hash: example_hash
+ {
+ oid = "1.3.6.1.4.1.4128.2100.104";
+ };
+
+ };
+ };
+
+ images {
+ compatible = "arm, img-descs";
+
+ example {
+ image-id = <2>;
+ parent = <&example_cert>;
+ hash = <&example_hash>;
+ };
+ };
+};
+
+non_volatile_counters: non_volatile_counters {
+ compatible = "arm, non-volatile-counter";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+};
+
+rot_keys {
+ example_pk: example_pk {
+ oid = "1.3.6.1.4.1.4128.2100.104";
+ };
+};
diff --git a/tools/cot_dt2c/tests/test_invalid_missing_root.dtsi b/tools/cot_dt2c/tests/test_invalid_missing_root.dtsi
new file mode 100644
index 0000000..465a4c6
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_invalid_missing_root.dtsi
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file provide a malformed CoT DT file that there
+ * are image/certificate that missing root certificate
+ *
+ */
+
+#include <tools_share/cca_oid.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <common/nv_cntr_ids.h>
+
+cot {
+ manifests {
+ compatible = "arm, cert-descs";
+
+ core_swd_key_cert: core_swd_key_cert {
+ image-id = <CORE_SWD_KEY_CERT_ID>;
+ signing-key = <&swd_rot_pk>;
+ antirollback-counter = <&trusted_nv_ctr>;
+
+ core_swd_pk: core_swd_pk {
+ oid = CORE_SWD_PK_OID;
+ };
+ };
+
+ trusted_os_fw_content_cert: trusted_os_fw_content_cert {
+ image-id = <TRUSTED_OS_FW_CONTENT_CERT_ID>;
+ parent = <&core_swd_key_cert>;
+ signing-key = <&core_swd_pk>;
+ antirollback-counter = <&trusted_nv_ctr>;
+
+ tos_fw_hash: tos_fw_hash {
+ oid = TRUSTED_OS_FW_HASH_OID;
+ };
+ tos_fw_config_hash: tos_fw_config_hash {
+ oid = TRUSTED_OS_FW_CONFIG_HASH_OID;
+ };
+ };
+
+ plat_key_cert: plat_key_cert {
+ image-id = <PLAT_KEY_CERT_ID>;
+ signing-key = <&prot_pk>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
+
+ plat_pk: plat_pk {
+ oid = PLAT_PK_OID;
+ };
+ };
+
+ non_trusted_fw_content_cert: non_trusted_fw_content_cert {
+ image-id = <NON_TRUSTED_FW_CONTENT_CERT_ID>;
+ parent = <&plat_key_cert>;
+ signing-key = <&plat_pk>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
+
+ nt_world_bl_hash: nt_world_bl_hash {
+ oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID;
+ };
+ nt_fw_config_hash: nt_fw_config_hash {
+ oid = NON_TRUSTED_FW_CONFIG_HASH_OID;
+ };
+ };
+
+#if defined(SPD_spmd)
+ sip_sp_content_cert: sip_sp_content_cert {
+ image-id = <SIP_SP_CONTENT_CERT_ID>;
+ parent = <&core_swd_key_cert>;
+ signing-key = <&core_swd_pk>;
+ antirollback-counter = <&trusted_nv_ctr>;
+
+ sp_pkg1_hash: sp_pkg1_hash {
+ oid = SP_PKG1_HASH_OID;
+ };
+ sp_pkg2_hash: sp_pkg2_hash {
+ oid = SP_PKG2_HASH_OID;
+ };
+ sp_pkg3_hash: sp_pkg3_hash {
+ oid = SP_PKG3_HASH_OID;
+ };
+ sp_pkg4_hash: sp_pkg4_hash {
+ oid = SP_PKG4_HASH_OID;
+ };
+ };
+
+ plat_sp_content_cert: plat_sp_content_cert {
+ image-id = <PLAT_SP_CONTENT_CERT_ID>;
+ parent = <&plat_key_cert>;
+ signing-key = <&plat_pk>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
+
+ sp_pkg5_hash: sp_pkg5_hash {
+ oid = SP_PKG5_HASH_OID;
+ };
+ sp_pkg6_hash: sp_pkg6_hash {
+ oid = SP_PKG6_HASH_OID;
+ };
+ sp_pkg7_hash: sp_pkg7_hash {
+ oid = SP_PKG7_HASH_OID;
+ };
+ sp_pkg8_hash: sp_pkg8_hash {
+ oid = SP_PKG8_HASH_OID;
+ };
+ };
+#endif
+ };
+
+ images {
+ compatible = "arm, img-descs";
+
+ hw_config {
+ image-id = <HW_CONFIG_ID>;
+ parent = <&cca_content_cert>;
+ hash = <&hw_config_hash>;
+ };
+
+ bl31_image {
+ image-id = <BL31_IMAGE_ID>;
+ parent = <&cca_content_cert>;
+ hash = <&soc_fw_hash>;
+ };
+
+ soc_fw_config {
+ image-id = <SOC_FW_CONFIG_ID>;
+ parent = <&cca_content_cert>;
+ hash = <&soc_fw_config_hash>;
+ };
+
+ rmm_image {
+ image-id = <RMM_IMAGE_ID>;
+ parent = <&cca_content_cert>;
+ hash = <&rmm_hash>;
+ };
+
+ bl32_image {
+ image-id = <BL32_IMAGE_ID>;
+ parent = <&trusted_os_fw_content_cert>;
+ hash = <&tos_fw_hash>;
+ };
+
+ tos_fw_config {
+ image-id = <TOS_FW_CONFIG_ID>;
+ parent = <&trusted_os_fw_content_cert>;
+ hash = <&tos_fw_config_hash>;
+ };
+
+ bl33_image {
+ image-id = <BL33_IMAGE_ID>;
+ parent = <&non_trusted_fw_content_cert>;
+ hash = <&nt_world_bl_hash>;
+ };
+
+ nt_fw_config {
+ image-id = <NT_FW_CONFIG_ID>;
+ parent = <&non_trusted_fw_content_cert>;
+ hash = <&nt_fw_config_hash>;
+ };
+
+#if defined(SPD_spmd)
+ sp_pkg1 {
+ image-id = <SP_PKG1_ID>;
+ parent = <&sip_sp_content_cert>;
+ hash = <&sp_pkg1_hash>;
+ };
+
+ sp_pkg2 {
+ image-id = <SP_PKG2_ID>;
+ parent = <&sip_sp_content_cert>;
+ hash = <&sp_pkg2_hash>;
+ };
+
+ sp_pkg3 {
+ image-id = <SP_PKG3_ID>;
+ parent = <&sip_sp_content_cert>;
+ hash = <&sp_pkg3_hash>;
+ };
+
+ sp_pkg4 {
+ image-id = <SP_PKG4_ID>;
+ parent = <&sip_sp_content_cert>;
+ hash = <&sp_pkg4_hash>;
+ };
+
+ sp_pkg5 {
+ image-id = <SP_PKG5_ID>;
+ parent = <&plat_sp_content_cert>;
+ hash = <&sp_pkg5_hash>;
+ };
+
+ sp_pkg6 {
+ image-id = <SP_PKG6_ID>;
+ parent = <&plat_sp_content_cert>;
+ hash = <&sp_pkg6_hash>;
+ };
+
+ sp_pkg7 {
+ image-id = <SP_PKG7_ID>;
+ parent = <&plat_sp_content_cert>;
+ hash = <&sp_pkg7_hash>;
+ };
+
+ sp_pkg8 {
+ image-id = <SP_PKG8_ID>;
+ parent = <&plat_sp_content_cert>;
+ hash = <&sp_pkg8_hash>;
+ };
+#endif
+ };
+};
+
+non_volatile_counters: non_volatile_counters {
+ compatible = "arm, non-volatile-counter";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cca_nv_ctr: cca_nv_ctr {
+ id = <TRUSTED_NV_CTR_ID>;
+ oid = CCA_FW_NVCOUNTER_OID;
+ };
+
+ trusted_nv_ctr: trusted_nv_ctr {
+ id = <TRUSTED_NV_CTR_ID>;
+ oid = TRUSTED_FW_NVCOUNTER_OID;
+ };
+
+ non_trusted_nv_ctr: non_trusted_nv_ctr {
+ id = <NON_TRUSTED_NV_CTR_ID>;
+ oid = NON_TRUSTED_FW_NVCOUNTER_OID;
+ };
+};
+
+rot_keys {
+ swd_rot_pk: swd_rot_pk {
+ oid = SWD_ROT_PK_OID;
+ };
+ prot_pk: prot_pk {
+ oid = PROT_PK_OID;
+ };
+};
diff --git a/tools/cot_dt2c/tests/test_invalid_undefined_parent.dtsi b/tools/cot_dt2c/tests/test_invalid_undefined_parent.dtsi
new file mode 100644
index 0000000..b6056ca
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_invalid_undefined_parent.dtsi
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This file provide a malformed CoT DT file that there
+ * are image/certificate that points to invalid parent
+ *
+ */
+
+cot {
+ manifests {
+ compatible = "arm, cert-descs";
+
+ cca_content_cert: cca_content_cert {
+ root-certificate;
+ image-id =<36>;
+ antirollback-counter = <&cca_nv_ctr>;
+
+ hw_config_hash: hw_config_hash {
+ oid = "1.3.6.1.4.1.4128.2100.203";
+ };
+ soc_fw_config_hash: soc_fw_config_hash {
+ oid = "1.3.6.1.4.1.4128.2100.604";
+ };
+ };
+
+ plat_key_cert: plat_key_cert {
+ root-certificate;
+ image-id = <38>;
+ signing-key = <&prot_pk>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
+
+ plat_pk: plat_pk {
+ oid = "1.3.6.1.4.1.4128.2100.1105";
+ };
+ };
+
+ non_trusted_fw_content_cert: non_trusted_fw_content_cert {
+ image-id = <NON_TRUSTED_FW_CONTENT_CERT_ID>;
+ parent = <&wrong_parent>;
+ signing-key = <&plat_pk>;
+ antirollback-counter = <&non_trusted_nv_ctr>;
+
+ nt_world_bl_hash: nt_world_bl_hash {
+ oid = "1.3.6.1.4.1.4128.2100.1201";
+ };
+ nt_fw_config_hash: nt_fw_config_hash {
+ oid = "1.3.6.1.4.1.4128.2100.1202";
+ };
+ };
+
+ };
+
+ images {
+ compatible = "arm, img-descs";
+
+ hw_config {
+ image-id = <23>;
+ parent = <&cca_content_cert>;
+ hash = <&hw_config_hash>;
+ };
+
+ soc_fw_config {
+ image-id = <25>;
+ parent = <&cca_content_cert>;
+ hash = <&soc_fw_config_hash>;
+ };
+
+ bl33_image {
+ image-id = <5>;
+ parent = <&non_trusted_fw_content_cert>;
+ hash = <&nt_world_bl_hash>;
+ };
+
+ nt_fw_config {
+ image-id = <27>;
+ hash = <&nt_fw_config_hash>;
+ };
+ };
+};
+
+non_volatile_counters: non_volatile_counters {
+ compatible = "arm, non-volatile-counter";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cca_nv_ctr: cca_nv_ctr {
+ id = <0>;
+ oid = "1.3.6.1.4.1.4128.2100.3";
+ };
+
+ trusted_nv_ctr: trusted_nv_ctr {
+ id = <0>;
+ oid = "1.3.6.1.4.1.4128.2100.1";
+ };
+
+ non_trusted_nv_ctr: non_trusted_nv_ctr {
+ id = <1>;
+ oid = "1.3.6.1.4.1.4128.2100.2";
+ };
+};
+
+rot_keys {
+ swd_rot_pk: swd_rot_pk {
+ oid = "1.3.6.1.4.1.4128.2100.1103";
+ };
+
+ prot_pk: prot_pk {
+ oid = "1.3.6.1.4.1.4128.2100.1102";
+ };
+};
diff --git a/tools/cot_dt2c/tests/test_util.py b/tools/cot_dt2c/tests/test_util.py
new file mode 100644
index 0000000..b8e44d4
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_util.py
@@ -0,0 +1,33 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+import os
+import sys
+
+from cot_dt2c.cli import *
+from click.testing import CliRunner
+
+def get_script_path():
+ return os.path.dirname(os.path.realpath(sys.argv[0]))
+
+def test_convert():
+ runner = CliRunner()
+ test_file = get_script_path() + "/test.dtsi"
+ test_output = get_script_path() + "/test.c"
+
+ result = runner.invoke(convert_to_c, [test_file, test_output])
+ try:
+ assert result.output == ""
+ except:
+ print("test convert fail")
+
+ try:
+ os.remove(test_output)
+ except OSError:
+ pass
+
+if __name__=="__main__":
+ test_convert()
diff --git a/tools/fiptool/fiptool.c b/tools/fiptool/fiptool.c
index 6c566ef..27119a1 100644
--- a/tools/fiptool/fiptool.c
+++ b/tools/fiptool/fiptool.c
@@ -1,12 +1,13 @@
/*
- * Copyright (c) 2016-2023, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
-#ifndef _MSC_VER
+#ifdef __linux__
#include <sys/mount.h>
#endif
+
#include <sys/types.h>
#include <sys/stat.h>
diff --git a/tools/nxp/cert_create_helper/src/pdef_tbb_key.c b/tools/nxp/cert_create_helper/src/pdef_tbb_key.c
index cf2ebda..cd48866 100644
--- a/tools/nxp/cert_create_helper/src/pdef_tbb_key.c
+++ b/tools/nxp/cert_create_helper/src/pdef_tbb_key.c
@@ -6,7 +6,7 @@
#include <pdef_tbb_key.h>
-static key_t pdef_tbb_keys[] = {
+static cert_key_t pdef_tbb_keys[] = {
[DDR_FW_CONTENT_KEY - DDR_FW_CONTENT_KEY] = {
.id = DDR_FW_CONTENT_KEY,
.opt = "ddr-fw-key",