Merge "fix(poplar): shutdown wdt0 before powering off" into integration
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
index 7b6a1f5..2d1afab 100644
--- a/.readthedocs.yaml
+++ b/.readthedocs.yaml
@@ -1,4 +1,4 @@
-# Copyright (c) 2023, Arm Limited. All rights reserved
+# Copyright (c) 2023-2024, Arm Limited. All rights reserved
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -19,9 +19,8 @@
jobs:
post_create_environment:
- pip install poetry=="1.3.2"
- - poetry config virtualenvs.create false
post_install:
- - poetry install --with doc
+ - VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH poetry install --with docs
sphinx:
configuration: docs/conf.py
diff --git a/Makefile b/Makefile
index bbde1a7..64bccbc 100644
--- a/Makefile
+++ b/Makefile
@@ -24,6 +24,7 @@
MAKE_HELPERS_DIRECTORY := make_helpers/
include ${MAKE_HELPERS_DIRECTORY}build_macros.mk
include ${MAKE_HELPERS_DIRECTORY}build_env.mk
+include ${MAKE_HELPERS_DIRECTORY}build-rules.mk
include ${MAKE_HELPERS_DIRECTORY}common.mk
################################################################################
@@ -120,6 +121,9 @@
SP_MK_GEN ?= ${SPTOOLPATH}/sp_mk_generator.py
SP_DTS_LIST_FRAGMENT ?= ${BUILD_PLAT}/sp_list_fragment.dts
+# Variables for use with Certificate Conversion (cot-dt2c) Tool
+CERTCONVPATH ?= tools/cot_dt2c
+
# Variables for use with ROMLIB
ROMLIBPATH ?= lib/romlib
@@ -453,6 +457,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)
@@ -690,8 +697,6 @@
FFH_SUPPORT := 0
endif
-$(eval $(call MAKE_PREREQ_DIR,${BUILD_PLAT}))
-
ifeq (${ARM_ARCH_MAJOR},7)
include make_helpers/armv7-a-cpus.mk
endif
@@ -973,27 +978,54 @@
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)
$(info DRTM_SUPPORT is an experimental feature)
endif
@@ -1128,6 +1160,7 @@
CREATE_KEYS \
CTX_INCLUDE_AARCH32_REGS \
CTX_INCLUDE_FPREGS \
+ CTX_INCLUDE_SVE_REGS \
CTX_INCLUDE_EL2_REGS \
CTX_INCLUDE_MPAM_REGS \
DEBUG \
@@ -1166,6 +1199,7 @@
SEPARATE_CODE_AND_RODATA \
SEPARATE_BL2_NOLOAD_REGION \
SEPARATE_NOBITS_REGION \
+ SEPARATE_SIMD_SECTION \
SPIN_ON_BL1_EXIT \
SPM_MM \
SPMC_AT_EL3 \
@@ -1227,9 +1261,11 @@
ENABLE_FEAT_AMUv1p1 \
ENABLE_FEAT_CSV2_2 \
ENABLE_FEAT_CSV2_3 \
+ ENABLE_FEAT_DEBUGV8P9 \
ENABLE_FEAT_DIT \
ENABLE_FEAT_ECV \
ENABLE_FEAT_FGT \
+ ENABLE_FEAT_FGT2 \
ENABLE_FEAT_HCX \
ENABLE_FEAT_MTE2 \
ENABLE_FEAT_PAN \
@@ -1284,6 +1320,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 \
@@ -1297,6 +1334,7 @@
AMU_RESTRICT_COUNTERS \
ENABLE_ASSERTIONS \
ENABLE_BTI \
+ ENABLE_FEAT_DEBUGV8P9 \
ENABLE_FEAT_MPAM \
ENABLE_PAUTH \
ENABLE_PIE \
@@ -1335,6 +1373,7 @@
SEPARATE_CODE_AND_RODATA \
SEPARATE_BL2_NOLOAD_REGION \
SEPARATE_NOBITS_REGION \
+ SEPARATE_SIMD_SECTION \
RECLAIM_INIT_CODE \
SPD_${SPD} \
SPIN_ON_BL1_EXIT \
@@ -1381,6 +1420,7 @@
ENABLE_MPMM \
ENABLE_MPMM_FCONF \
ENABLE_FEAT_FGT \
+ ENABLE_FEAT_FGT2 \
ENABLE_FEAT_ECV \
ENABLE_FEAT_AMUv1p1 \
ENABLE_FEAT_SEL2 \
@@ -1476,7 +1516,6 @@
endif
endif #(!ERROR_DEPRECATED)
-$(eval $(call MAKE_LIB_DIRS))
$(eval $(call MAKE_LIB,c))
# Expand build macros for the different images
@@ -1560,7 +1599,7 @@
# Add Secure Partition packages
ifeq (${NEED_SP_PKG},yes)
-$(BUILD_PLAT)/sp_gen.mk: ${SP_MK_GEN} ${SP_LAYOUT_FILE} | ${BUILD_PLAT}
+$(BUILD_PLAT)/sp_gen.mk: ${SP_MK_GEN} ${SP_LAYOUT_FILE} | $$(@D)/
$(q)${PYTHON} "$<" "$@" $(filter-out $<,$^) $(BUILD_PLAT) ${COT} ${SP_DTS_LIST_FRAGMENT}
sp: $(DTBS) $(BUILD_PLAT)/sp_gen.mk $(SP_PKGS)
$(s)echo
@@ -1580,6 +1619,7 @@
clean:
$(s)echo " CLEAN"
$(call SHELL_REMOVE_DIR,${BUILD_PLAT})
+ $(q)${MAKE} -C ${CERTCONVPATH} clean
ifdef UNIX_MK
$(q)${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
else
@@ -1595,6 +1635,7 @@
$(s)echo " REALCLEAN"
$(call SHELL_REMOVE_DIR,${BUILD_BASE})
$(call SHELL_DELETE_ALL, ${CURDIR}/cscope.*)
+ $(q)${MAKE} -C ${CERTCONVPATH} clean
ifdef UNIX_MK
$(q)${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean
else
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index 40add91..7dc71a2 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} \
@@ -105,6 +107,10 @@
BL31_SOURCES += ${AMU_SOURCES}
endif
+ifneq (${ENABLE_FEAT_FGT2},0)
+BL31_SOURCES += lib/extensions/fgt/fgt2.c
+endif
+
ifeq (${ENABLE_MPMM},1)
BL31_SOURCES += ${MPMM_SOURCES}
endif
@@ -120,6 +126,10 @@
BL31_SOURCES += lib/extensions/mpam/mpam.c
endif
+ifneq (${ENABLE_FEAT_DEBUGV8P9},0)
+BL31_SOURCES += lib/extensions/debug/debugv8p9.c
+endif
+
ifneq (${ENABLE_TRBE_FOR_NS},0)
BL31_SOURCES += lib/extensions/trbe/trbe.c
endif
diff --git a/changelog.yaml b/changelog.yaml
index 6a235cd..df0476f 100644
--- a/changelog.yaml
+++ b/changelog.yaml
@@ -104,9 +104,15 @@
- title: Extended Translation Control Register (FEAT_TCR2).
scope: tcr2
+ - title: Fine-grained Traps 2 (FEAT_FGT2).
+ scope: fgt2
+
- title: CPU feature / ID register handling in general
scope: cpufeat
+ - title: Debug Extension (FEAT_Debugv8p9)
+ scope: debugv8p9
+
- title: Guarded Control Stack (FEAT_GCS)
scope: gcs
@@ -241,8 +247,8 @@
- title: RD-N2
scope: rdn2
- - title: RD-Fremont
- scope: rdfremont
+ - title: RD-V3
+ scope: rdv3
deprecated:
- board/rdn2
@@ -799,6 +805,9 @@
- title: RAS
scope: ras
+ - title: SIMD
+ scope: simd
+
- title: FCONF
scope: fconf
@@ -1428,6 +1437,19 @@
- title: Marvell Tools
scope: marvell-tools
+ - title: Renesas Tools
+ scope: renesas-tools
+
+ subsections:
+ - title: R-Car Layout Tool
+ scope: rcar-layout
+
+ - title: R/ZG Layout Tool
+ scope: rzg-layout
+
+ - title: Transfer List Compiler
+ scope: tlc
+
- title: Dependencies
scope: deps
diff --git a/common/feat_detect.c b/common/feat_detect.c
index 8e3e3dd..9b9f7b4 100644
--- a/common/feat_detect.c
+++ b/common/feat_detect.c
@@ -94,6 +94,12 @@
ID_AA64PFR0_CSV2_MASK);
}
+static unsigned int read_feat_debugv8p9_id_field(void)
+{
+ return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_DEBUGVER_SHIFT,
+ ID_AA64DFR0_DEBUGVER_MASK);
+}
+
static unsigned int read_feat_pmuv3_id_field(void)
{
return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_PMUVER_SHIFT,
@@ -328,7 +334,8 @@
/* v8.6 features */
check_feature(ENABLE_FEAT_AMUv1p1, read_feat_amu_id_field(),
"AMUv1p1", 2, 2);
- check_feature(ENABLE_FEAT_FGT, read_feat_fgt_id_field(), "FGT", 1, 1);
+ check_feature(ENABLE_FEAT_FGT, read_feat_fgt_id_field(), "FGT", 1, 2);
+ check_feature(ENABLE_FEAT_FGT2, read_feat_fgt_id_field(), "FGT2", 2, 2);
check_feature(ENABLE_FEAT_ECV, read_feat_ecv_id_field(), "ECV", 1, 2);
check_feature(ENABLE_FEAT_TWED, read_feat_twed_id_field(),
"TWED", 1, 1);
@@ -356,6 +363,8 @@
"S1POE", 1, 1);
check_feature(ENABLE_FEAT_CSV2_3, read_feat_csv2_id_field(),
"CSV2_3", 3, 3);
+ check_feature(ENABLE_FEAT_DEBUGV8P9, read_feat_debugv8p9_id_field(),
+ "DEBUGV8P9", 11, 11);
/* v9.0 features */
check_feature(ENABLE_BRBE_FOR_NS, read_feat_brbe_id_field(),
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index cbed72f..8ac09ae 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
@@ -1050,6 +1050,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 +1113,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..1d31e3d 100644
--- a/docs/components/cot-binding.rst
+++ b/docs/components/cot-binding.rst
@@ -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 52a9317..be38e15 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -23,8 +23,9 @@
is expected to contain a makefile called ``<aarch32_sp-value>.mk``.
- ``AMU_RESTRICT_COUNTERS``: Register reads to the group 1 counters will return
- zero at all but the highest implemented exception level. Reads from the
- memory mapped view are unaffected by this control.
+ zero at all but the highest implemented exception level. External
+ memory-mapped debug accesses are unaffected by this control.
+ The default value is 1 for all platforms.
- ``ARCH`` : Choose the target build architecture for TF-A. It can take either
``aarch64`` or ``aarch32`` as values. By default, it is defined to
@@ -98,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.
@@ -199,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.
@@ -320,6 +332,12 @@
The flag can take values 0 to 2, to align with the ``ENABLE_FEAT``
mechanism. Default value is ``0``.
+- ``ENABLE_FEAT_DEBUGV8P9``: Numeric value to enable ``FEAT_DEBUGV8P9``
+ extension which allows the ability to implement more than 16 breakpoints
+ and/or watchpoints. This feature is mandatory from v8.9 and is optional
+ from v8.8. This flag can take the values of 0 to 2, to align with the
+ ``ENABLE_FEAT`` mechanism. Default value is ``0``.
+
- ``ENABLE_FEAT_DIT``: Numeric value to enable ``FEAT_DIT`` (Data Independent
Timing) extension. It allows setting the ``DIT`` bit of PSTATE in EL3.
``FEAT_DIT`` is a mandatory architectural feature and is enabled from v8.4
@@ -340,6 +358,13 @@
This flag can take the values 0 to 2, to align with the ``ENABLE_FEAT``
mechanism. Default value is ``0``.
+- ``ENABLE_FEAT_FGT2``: Numeric value to enable support for FGT2
+ (Fine Grain Traps 2) feature allowing for access to Fine-grained trap 2 registers
+ during EL2 to EL3 context save/restore operations.
+ Its an optional architectural feature and is available from v8.8 and upwards.
+ This flag can take the values 0 to 2, to align with the ``ENABLE_FEAT``
+ mechanism. Default value is ``0``.
+
- ``ENABLE_FEAT_HCX``: Numeric value to set the bit SCR_EL3.HXEn in EL3 to
allow access to HCRX_EL2 (extended hypervisor control register) from EL2 as
well as adding HCRX_EL2 to the EL2 context save/restore operations. Its a
@@ -487,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
@@ -867,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/mt8195.rst b/docs/plat/mt8195.rst
index b2aeea2..9810f9e 100644
--- a/docs/plat/mt8195.rst
+++ b/docs/plat/mt8195.rst
@@ -2,8 +2,8 @@
=============
MediaTek 8195 (MT8195) is a 64-bit ARM SoC introduced by MediaTek in 2021.
-The chip incorporates eight cores - four Cortex-A55 little cores and Cortex-A76.
-Cortex-A76 can operate at up to 2.2 GHz.
+The chip incorporates eight cores - four Cortex-A55 little cores and Cortex-A78.
+Cortex-A78 can operate at up to 2.6 GHz.
Cortex-A55 can operate at up to 2.0 GHz.
Boot Sequence
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..7b7e56f
--- /dev/null
+++ b/docs/tools/cot-dt2c.rst
@@ -0,0 +1,149 @@
+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
+~~~~~~~~~~~~~~~
+
+#. Install the tool
+
+ .. code::
+
+ make install
+
+
+#. Verify that the tool runs correctly
+
+ .. code::
+
+ make test
+
+
+#. 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
+
+#. Uninstall the tool
+ .. code::
+
+ make uninstall
+
+ This command will uninstall the tool
+
+
+#. Uninstall the tool and clean all the build file
+ .. code::
+
+ make clean
+
+ This command will clean all the build file and implicitly uninstall the tool
+
+
+#. Call the make file from TF-A root directory
+ .. code::
+
+ make -C tools/cot-dt2c install
+ make -C tools/cot-dt2c uninstall
+ make -C tools/cot-dt2c clean
+
+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 DTB 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 DTB 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 DTB 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.*
+
+.. _Poetry: https://python-poetry.org/docs/
diff --git a/docs/tools/index.rst b/docs/tools/index.rst
index 2dee2c0..c0e214a 100644
--- a/docs/tools/index.rst
+++ b/docs/tools/index.rst
@@ -6,7 +6,9 @@
:caption: Contents
memory-layout-tool
+ transfer-list-compiler
+ cot-dt2c
--------------
-*Copyright (c) 2023, Arm Limited. All rights reserved.*
+*Copyright (c) 2023-2024, Arm Limited. All rights reserved.*
diff --git a/docs/tools/transfer-list-compiler.rst b/docs/tools/transfer-list-compiler.rst
new file mode 100644
index 0000000..fa660dc
--- /dev/null
+++ b/docs/tools/transfer-list-compiler.rst
@@ -0,0 +1,311 @@
+Transfer List Compiler
+======================
+
+The Transfer List Compiler (tlc) is a host tool used by TF-A to generate transfer
+lists compliant with the v0.9 of the `Firmware Handoff specification`_. It enables
+developers to statically generate transfer list blobs containing any number of
+transfer entries.
+
+Getting Started
+~~~~~~~~~~~~~~~
+
+``tlc`` is installed by default with TF-A's poetry environment. All of it's
+dependencies are listed in `tools/tlc/pyproject.toml`_.
+
+To install ``tlc`` seperately, run the following command:
+
+.. code::
+
+ make -C tools/tlc install
+
+Creating a Transfer List
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+To create an empty TL, you can use the ``create`` command.
+
+.. code::
+
+ tlc create tl.bin
+
+This commands generates a binary blob representing an empty TL, shown in the
+hexdump below.
+
+.. code::
+
+ $ hexdump tl.bin | head
+ 0000000 b10b 4a0f 01a6 0318 0018 0000 1000 0000
+ 0000010 0001 0000 0000 0000
+
+A common use-case this tool supports is the addition of TE's via the option
+``--entry``. This takes as input the tag ID and path to a binary blob to be
+included in the transfer list. The snippet below shows how to include an FDT in
+the TL.
+
+.. code::
+
+ tlc create --entry 1 fdt.dtb tl.bin
+
+Alternatively, addition of a device tree is supported through the option
+``--fdt``. This has the same effect as passing the device tree and it's tag ID
+through the ``--entry`` option.
+
+.. code::
+
+ tlc create --fdt fdt.dtb tl.bin
+
+.. note::
+
+ ``tlc`` makes no effort to verify the contents of a binary blob against the
+ provided tag ID. It only checks that the tags provided as input are within
+ range and that there is sufficient memory to include their TE's.
+
+You can also create a TL from a YAML config file.
+
+.. code ::
+
+ tlc create --from-yaml config.yaml tl.bin
+
+Printing the contents of a TL
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Support is provided for dumping the contents of a TL via the ``info`` command.
+This prints the header of the TL and all included TE's.
+
+.. code::
+
+ $ tlc info tl.bin
+ signature 0x4a0fb10b
+ checksum 0xe1
+ version 0x1
+ hdr_size 0x18
+ alignment 0x3
+ size 0x2a6f
+ total_size 0x4e20
+ flags 0x1
+ ----
+ id 0x1
+ data_size 0x2a47
+ hdr_size 0x8
+ offset 0x18
+ ----
+ id 0x0
+ data_size 0x0
+ hdr_size 0x8
+ offset 0x2a68
+
+The example above shows the dump produced by ``tlc`` for a 20Kb TL containing a
+device tree (tag_id=1) and a NULL entry (tag_id=0).
+
+Modifying the contents of an existing TL
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+`tlc` supports removal of one or more entries from a TL through the ``remove``
+command. It takes as argument the filename, and one or more tag ID's, passed
+through the ``--tags`` option. It produces a valid TL blob without those
+entries.
+
+
+For example, using the same blob as in the section above, we can remove the FDT
+TE with the command.
+
+.. code::
+
+ $ tlc remove --tags 1 tl.bin
+
+Using the ``info`` command, shows the the TE has been remove:
+
+.. code::
+
+ $ tlc info tl.bin
+
+ signature 0x4a0fb10b
+ checksum 0x38
+ version 0x1
+ hdr_size 0x18
+ alignment 0x3
+ size 0x20
+ total_size 0x4e20
+ flags 0x1
+ ----
+ id 0x0
+ data_size 0x0
+ hdr_size 0x8
+ offset 0x18
+
+Note that more than one entry can be removed at a time. The ``--tags`` option
+accepts multiple tag ID's.
+
+Conversely, TE's can be added to an existing TL. This is achieved through the
+`add` command.
+
+.. code::
+
+ $ tlc add --entry 1 fdt.dtb tl.bin
+
+
+The result of this modification is shown below:
+
+.. code::
+
+ $ tlc info tl.bin
+
+ signature 0x4a0fb10b
+ checksum 0xe1
+ version 0x1
+ hdr_size 0x18
+ alignment 0x3
+ size 0x2a6f
+ total_size 0x4e20
+ flags 0x1
+ ----
+ id 0x0
+ data_size 0x0
+ hdr_size 0x8
+ offset 0x18
+ ----
+ id 0x1
+ data_size 0x2a47
+ hdr_size 0x8
+ offset 0x20
+
+Unpacking a Transfer List
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Given a transfer list, ``tlc`` also provides a mechanism for extracting TE data.
+Running the command ``unpack``, yields binary files containing data from all the TE's.
+
+.. code::
+
+ $ tlc create --size 20000 --fdt build/fvp/debug/fdts/fvp-base-gicv3-psci.dtb tl.bin
+ $ tlc unpack tl.bin
+ $ file te_1.bin
+ te_1.bin: Device Tree Blob version 17, size=10823, boot CPU=0, string block size=851, DT structure block size=9900
+
+Validate a Transfer List
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+``tlc validate`` provides a quick and simple mechanism for checking wether the TL
+is compliant with version of the specification supported by the tool. It
+performs the following checks:
+
+#. Validates the signature.
+#. Ensures that the specified version is greater than or equal to the tool’s current version.
+#. Verifies alignment criteria for all TE’s.
+
+YAML Config File Format
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Example YAML config file:
+
+.. code::
+
+ execution_state: aarch32
+ has_checksum: true
+ max_size: 4096
+ entries:
+ - tag_id: 258 # entry point info
+ ep_info:
+ args:
+ - 67112968
+ - 67112960
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ h:
+ attr: 8
+ type: 1
+ version: 2
+ pc: 67239936
+ spsr: 467
+ - tag_id: 3 # memory layout
+ addr: 8
+ size: 8
+ - tag_id: 1, # fdt
+ blob_file_path: "fdt.bin",
+
+`max_size` defaults to `0x1000`, `execution_state` defaults to `aarch64`, and `has_checksum`
+defaults to `true`.
+
+The fields of the YAML file should match the fields in the specification for the transfer list. You
+don't need to give the hdr_size or data_size fields. For example, a memory layout entry would have
+an entry like:
+
+.. code::
+
+ tag_id: 3
+ addr: 8
+ size: 8
+
+You can input blob files by giving paths to the current working directory. You can do this for any
+TE type. For example, an FDT layout would have an entry like:
+
+.. code::
+
+ tag_id: 1,
+ blob_file_path: "fdt.bin",
+
+You can input C-types by giving its fields. For example, an entry point
+info entry would have an entry like:
+
+.. code::
+
+ tag_id: 258
+ ep_info:
+ args:
+ - 67112968
+ - 67112960
+ - 0
+ - 0
+ h:
+ attr: 8
+ type: 1
+ version: 2
+ lr_svc: 0
+ pc: 67239936
+ spsr: 467
+
+You can give the name of the tag instead of the tag id number. The valid tag names are in the
+`transfer_entry_formats` dict in `tools/tlc/tlc/tl.py`_. Some examples are:
+
+* empty
+* fdt
+* hob_block
+* hob_list
+
+You can input the attr field of entry_point_info as a string of flag
+names separated by `|`. The names are taken from ep_info_exp.h in TF-A.
+For example:
+
+.. code::
+
+ has_checksum: true
+ max_size: 4096
+ entries:
+ - tag_id: 0x102
+ ep_info:
+ args:
+ - 67112976
+ - 67112960
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ - 0
+ h:
+ attr: EP_NON_SECURE | EP_ST_ENABLE
+ type: 1
+ version: 2
+ pc: 67239936
+ spsr: 965
+
+--------------
+
+*Copyright (c) 2024, Arm Limited. All rights reserved.*
+
+.. _Firmware Handoff specification: https://github.com/FirmwareHandoff/firmware_handoff/
+.. _tools/tlc/pyproject.toml: https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/heads/master/tools/tlc/pyproject.toml
+.. _tools/tlc/tlc/tl.py: https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/heads/master/tools/tlc/tlc/tl.py
diff --git a/drivers/arm/gic/v3/arm_gicv3_common.c b/drivers/arm/gic/v3/arm_gicv3_common.c
index 4489892..cc82ddb 100644
--- a/drivers/arm/gic/v3/arm_gicv3_common.c
+++ b/drivers/arm/gic/v3/arm_gicv3_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -28,10 +28,13 @@
void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num)
{
uintptr_t gicr_base = 0;
+ unsigned int typer_reg;
assert(gicv3_driver_data);
assert(gicv3_driver_data->rdistif_base_addrs);
+ assert(gicv3_driver_data->gicd_base != 0U);
+ typer_reg = gicd_read_typer(gicv3_driver_data->gicd_base);
/*
* The GICR_WAKER.Sleep bit should be set only when both
* GICR_WAKER.ChildrenAsleep and GICR_WAKER.ProcessorSleep are set on
@@ -60,9 +63,14 @@
*/
gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_SL_BIT);
- /* Wait until the GICR_WAKER.Quiescent bit is set */
- while (!(gicr_read_waker(gicr_base) & WAKER_QSC_BIT))
- ;
+ /*
+ * If LPIs are supported, wait until the GICR_WAKER.Quiescent bit is
+ * set.
+ */
+ if ((typer_reg & TYPER_LPIS) != 0U) {
+ while (!(gicr_read_waker(gicr_base) & WAKER_QSC_BIT))
+ ;
+ }
}
/*
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_psa_crypto.c b/drivers/auth/mbedtls/mbedtls_psa_crypto.c
index 2da97dc..53f8adf 100644
--- a/drivers/auth/mbedtls/mbedtls_psa_crypto.c
+++ b/drivers/auth/mbedtls/mbedtls_psa_crypto.c
@@ -104,242 +104,84 @@
#if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
-static void construct_psa_key_alg_and_type(mbedtls_pk_type_t pk_alg,
- mbedtls_md_type_t md_alg,
- psa_ecc_family_t psa_ecc_family,
- psa_algorithm_t *psa_alg,
- psa_key_type_t *psa_key_type)
-{
- psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg);
-
- switch (pk_alg) {
- case MBEDTLS_PK_RSASSA_PSS:
- *psa_alg = PSA_ALG_RSA_PSS(psa_md_alg);
- *psa_key_type = PSA_KEY_TYPE_RSA_PUBLIC_KEY;
- break;
- case MBEDTLS_PK_ECDSA:
- *psa_alg = PSA_ALG_ECDSA(psa_md_alg);
- *psa_key_type = PSA_KEY_TYPE_ECC_PUBLIC_KEY(psa_ecc_family);
- break;
- default:
- *psa_alg = PSA_ALG_NONE;
- *psa_key_type = PSA_KEY_TYPE_NONE;
- break;
- }
-}
-
-
-#if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \
-TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA
-
/*
- * This is a helper function to detect padding byte (if the MSB bit of the
- * first data byte is set to 1, for example 0x80) and on detection, ignore the
- * padded byte(0x00) and increase the buffer pointer beyond padded byte and
- * decrease the length of the buffer by 1.
- *
- * On Success returns 0, error otherwise.
- **/
-static inline int ignore_asn1_int_padding_byte(unsigned char **buf_start,
- size_t *buf_len)
-{
- unsigned char *local_buf = *buf_start;
-
- /* Check for negative number */
- if ((local_buf[0] & 0x80U) != 0U) {
- return -1;
- }
-
- if ((local_buf[0] == 0U) && (local_buf[1] > 0x7FU) &&
- (*buf_len > 1U)) {
- *buf_start = &local_buf[1];
- (*buf_len)--;
- }
-
- return 0;
-}
+ * NOTE: This has been made internal in mbedtls 3.6.0 and the mbedtls team has
+ * advised that it's better to copy out the declaration than it would be to
+ * update to 3.5.2, where this function is exposed.
+ */
+int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid,
+ const mbedtls_x509_buf *sig_params,
+ mbedtls_md_type_t *md_alg,
+ mbedtls_pk_type_t *pk_alg,
+ void **sig_opts);
/*
- * This is a helper function that gets a pointer to the encoded ECDSA publicKey
- * and its length (as per RFC5280) and returns corresponding decoded publicKey
- * and its length. As well, it retrieves the family of ECC key in the PSA
- * format.
- *
- * This function returns error(CRYPTO_ERR_SIGNATURE) on ASN.1 parsing failure,
- * otherwise success(0).
- **/
-static int get_ecdsa_pkinfo_from_asn1(unsigned char **pk_start,
- unsigned int *pk_len,
- psa_ecc_family_t *psa_ecc_family)
+ * This is a helper function which parses a SignatureAlgorithm OID.
+ * It extracts the pk algorithm and constructs a psa_algorithm_t object
+ * to be used by PSA calls.
+ */
+static int construct_psa_alg(void *sig_alg, unsigned int sig_alg_len,
+ mbedtls_pk_type_t *pk_alg, psa_algorithm_t *psa_alg)
{
- mbedtls_asn1_buf alg_oid, alg_params;
- mbedtls_ecp_group_id grp_id;
int rc;
- unsigned char *pk_end;
- size_t len;
- size_t curve_bits;
- unsigned char *pk_ptr = *pk_start;
+ mbedtls_md_type_t md_alg;
+ void *sig_opts = NULL;
+ mbedtls_asn1_buf sig_alg_oid, params;
+ unsigned char *p = (unsigned char *) sig_alg;
+ unsigned char *end = (unsigned char *) sig_alg + sig_alg_len;
- pk_end = pk_ptr + *pk_len;
- rc = mbedtls_asn1_get_tag(&pk_ptr, pk_end, &len,
- MBEDTLS_ASN1_CONSTRUCTED |
- MBEDTLS_ASN1_SEQUENCE);
+ rc = mbedtls_asn1_get_alg(&p, end, &sig_alg_oid, ¶ms);
if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
+ rc = CRYPTO_ERR_SIGNATURE;
+ goto end;
}
- pk_end = pk_ptr + len;
- rc = mbedtls_asn1_get_alg(&pk_ptr, pk_end, &alg_oid, &alg_params);
+ rc = mbedtls_x509_get_sig_alg(&sig_alg_oid, ¶ms, &md_alg, pk_alg, &sig_opts);
if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
+ rc = CRYPTO_ERR_SIGNATURE;
+ goto end;
}
- if (alg_params.tag == MBEDTLS_ASN1_OID) {
- if (mbedtls_oid_get_ec_grp(&alg_params, &grp_id) != 0) {
- return CRYPTO_ERR_SIGNATURE;
- }
- *psa_ecc_family = mbedtls_ecc_group_to_psa(grp_id,
- &curve_bits);
- } else {
- return CRYPTO_ERR_SIGNATURE;
- }
+ psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg);
- pk_end = pk_ptr + len - (alg_oid.len + alg_params.len +
- 2 * (SIZE_OF_ASN1_LEN + SIZE_OF_ASN1_TAG));
- rc = mbedtls_asn1_get_bitstring_null(&pk_ptr, pk_end, &len);
- if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
+ switch (*pk_alg) {
+ case MBEDTLS_PK_RSASSA_PSS:
+ *psa_alg = PSA_ALG_RSA_PSS(psa_md_alg);
+ rc = CRYPTO_SUCCESS;
+ break;
+ case MBEDTLS_PK_ECDSA:
+ *psa_alg = PSA_ALG_ECDSA(psa_md_alg);
+ rc = CRYPTO_SUCCESS;
+ break;
+ default:
+ *psa_alg = PSA_ALG_NONE;
+ rc = CRYPTO_ERR_SIGNATURE;
+ break;
}
- *pk_start = pk_ptr;
- *pk_len = len;
-
+end:
+ mbedtls_free(sig_opts);
return rc;
}
/*
- * Ecdsa-Sig-Value ::= SEQUENCE {
- * r INTEGER,
- * s INTEGER
- * }
- *
- * This helper function that gets a pointer to the encoded ECDSA signature and
- * its length (as per RFC5280) and returns corresponding decoded signature
- * (R_S pair) and its size.
- *
- * This function returns error(CRYPTO_ERR_SIGNATURE) on ASN.1 parsing failure,
- * otherwise success(0).
- **/
-static int get_ecdsa_signature_from_asn1(unsigned char *sig_ptr,
- size_t *sig_len,
- unsigned char *r_s_pair)
+ * Helper functions for mbedtls PK contexts.
+ */
+static void initialize_pk_context(mbedtls_pk_context *pk, bool *pk_initialized)
{
- int rc;
- unsigned char *sig_end;
- size_t len, r_len, s_len;
-
- sig_end = sig_ptr + *sig_len;
- rc = mbedtls_asn1_get_tag(&sig_ptr, sig_end, &len,
- MBEDTLS_ASN1_CONSTRUCTED |
- MBEDTLS_ASN1_SEQUENCE);
- if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
- }
-
- sig_end = sig_ptr + len;
- rc = mbedtls_asn1_get_tag(&sig_ptr, sig_end, &r_len,
- MBEDTLS_ASN1_INTEGER);
- if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
- }
-
- if (ignore_asn1_int_padding_byte(&sig_ptr, &r_len) != 0) {
- return CRYPTO_ERR_SIGNATURE;
- }
-
- (void)memcpy((void *)&r_s_pair[0], (const void *)sig_ptr, r_len);
-
- sig_ptr = sig_ptr + r_len;
- sig_end = sig_ptr + len - (r_len + (SIZE_OF_ASN1_LEN +
- SIZE_OF_ASN1_TAG));
- rc = mbedtls_asn1_get_tag(&sig_ptr, sig_end, &s_len,
- MBEDTLS_ASN1_INTEGER);
- if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
- }
-
- if (ignore_asn1_int_padding_byte(&sig_ptr, &s_len) != 0) {
- return CRYPTO_ERR_SIGNATURE;
- }
-
- (void)memcpy((void *)&r_s_pair[r_len], (const void *)sig_ptr, s_len);
-
- *sig_len = s_len + r_len;
-
- return 0;
+ mbedtls_pk_init(pk);
+ *pk_initialized = true;
}
-#endif /*
- * TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \
- * TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA
- **/
-/*
- * This is a helper function that adjusts the start of the pk_start to point to
- * the subjectPublicKey bytes within the SubjectPublicKeyInfo block.
- *
- * SubjectPublicKeyInfo ::= SEQUENCE {
- * algorithm AlgorithmIdentifier,
- * subjectPublicKey BIT STRING }
- *
- * This function returns error(CRYPTO_ERR_SIGNATURE) on ASN.1 parsing failure,
- * otherwise success(0).
- **/
-static int pk_bytes_from_subpubkey(unsigned char **pk_start,
- unsigned int *pk_len)
+static void cleanup_pk_context(mbedtls_pk_context *pk, bool *pk_initialized)
{
- mbedtls_asn1_buf alg_oid, alg_params;
- int rc;
- unsigned char *pk_end;
- size_t len;
- unsigned char *pk_ptr = *pk_start;
-
- pk_end = pk_ptr + *pk_len;
- rc = mbedtls_asn1_get_tag(&pk_ptr, pk_end, &len,
- MBEDTLS_ASN1_CONSTRUCTED |
- MBEDTLS_ASN1_SEQUENCE);
- if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
- }
-
- pk_end = pk_ptr + len;
- rc = mbedtls_asn1_get_alg(&pk_ptr, pk_end, &alg_oid, &alg_params);
- if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
+ if (*pk_initialized) {
+ mbedtls_pk_free(pk);
+ *pk_initialized = false;
}
- pk_end = pk_ptr + len - (alg_oid.len + alg_params.len +
- 2 * (SIZE_OF_ASN1_LEN + SIZE_OF_ASN1_TAG));
- rc = mbedtls_asn1_get_bitstring_null(&pk_ptr, pk_end, &len);
- if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
- }
-
- *pk_start = pk_ptr;
- *pk_len = len;
-
- return rc;
}
/*
- * NOTE: This has been made internal in mbedtls 3.6.0 and the mbedtls team has
- * advised that it's better to copy out the declaration than it would be to
- * update to 3.5.2, where this function is exposed.
- */
-int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid,
- const mbedtls_x509_buf *sig_params,
- mbedtls_md_type_t *md_alg,
- mbedtls_pk_type_t *pk_alg,
- void **sig_opts);
-/*
* Verify a signature.
*
* Parameters are passed using the DER encoding format following the ASN.1
@@ -350,141 +192,99 @@
void *sig_alg, unsigned int sig_alg_len,
void *pk_ptr, unsigned int pk_len)
{
- mbedtls_asn1_buf sig_oid, sig_params;
- mbedtls_asn1_buf signature;
- mbedtls_md_type_t md_alg;
- mbedtls_pk_type_t pk_alg;
- int rc;
- void *sig_opts = NULL;
unsigned char *p, *end;
+ mbedtls_pk_context pk;
+ bool pk_initialized = false;
+ int rc = CRYPTO_ERR_SIGNATURE;
+ psa_status_t psa_status = PSA_ERROR_CORRUPTION_DETECTED;
+ psa_key_attributes_t psa_key_attr = PSA_KEY_ATTRIBUTES_INIT;
+ psa_key_id_t psa_key_id;
+ mbedtls_pk_type_t pk_alg;
+ psa_algorithm_t psa_alg;
+ __unused unsigned char reformatted_sig[MAX_ECDSA_R_S_PAIR_LEN] = {0};
unsigned char *local_sig_ptr;
size_t local_sig_len;
- psa_ecc_family_t psa_ecc_family = 0U;
- __unused unsigned char reformatted_sig[MAX_ECDSA_R_S_PAIR_LEN] = {0};
- /* construct PSA key algo and type */
- psa_status_t status = PSA_SUCCESS;
- psa_key_attributes_t psa_key_attr = PSA_KEY_ATTRIBUTES_INIT;
- psa_key_id_t psa_key_id = PSA_KEY_ID_NULL;
- psa_key_type_t psa_key_type;
- psa_algorithm_t psa_alg;
+ /* Load the key into the PSA key store. */
+ initialize_pk_context(&pk, &pk_initialized);
- /* Get pointers to signature OID and parameters */
- p = (unsigned char *)sig_alg;
- end = (unsigned char *)(p + sig_alg_len);
- rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params);
+ p = (unsigned char *) pk_ptr;
+ end = p + pk_len;
+ rc = mbedtls_pk_parse_subpubkey(&p, end, &pk);
if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
+ rc = CRYPTO_ERR_SIGNATURE;
+ goto end2;
}
- /* Get the actual signature algorithm (MD + PK) */
- rc = mbedtls_x509_get_sig_alg(&sig_oid, &sig_params, &md_alg, &pk_alg, &sig_opts);
+ rc = mbedtls_pk_get_psa_attributes(&pk, PSA_KEY_USAGE_VERIFY_MESSAGE, &psa_key_attr);
if (rc != 0) {
- return CRYPTO_ERR_SIGNATURE;
+ rc = CRYPTO_ERR_SIGNATURE;
+ goto end2;
+ }
+
+ rc = construct_psa_alg(sig_alg, sig_alg_len, &pk_alg, &psa_alg);
+ if (rc != CRYPTO_SUCCESS) {
+ goto end2;
}
+ psa_set_key_algorithm(&psa_key_attr, psa_alg);
- /* Get the signature (bitstring) */
- p = (unsigned char *)sig_ptr;
- end = (unsigned char *)(p + sig_len);
- signature.tag = *p;
- rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len);
- if ((rc != 0) || ((size_t)(end - p) != signature.len)) {
+ rc = mbedtls_pk_import_into_psa(&pk, &psa_key_attr, &psa_key_id);
+ if (rc != 0) {
rc = CRYPTO_ERR_SIGNATURE;
goto end2;
}
+ /* Optimize mbedtls heap usage by freeing the pk context now. */
+ cleanup_pk_context(&pk, &pk_initialized);
+
+ /* Extract the signature from sig_ptr. */
+ p = (unsigned char *) sig_ptr;
+ end = p + sig_len;
+ rc = mbedtls_asn1_get_bitstring_null(&p, end, &local_sig_len);
+ if (rc != 0) {
+ rc = CRYPTO_ERR_SIGNATURE;
+ goto end1;
+ }
local_sig_ptr = p;
- local_sig_len = signature.len;
#if TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \
TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA
if (pk_alg == MBEDTLS_PK_ECDSA) {
- rc = get_ecdsa_signature_from_asn1(local_sig_ptr,
- &local_sig_len,
- reformatted_sig);
- if (rc != 0) {
- goto end2;
- }
-
- local_sig_ptr = reformatted_sig;
+ /* Convert the DER ASN.1 signature to raw format. */
+ size_t key_bits = psa_get_key_bits(&psa_key_attr);
- rc = get_ecdsa_pkinfo_from_asn1((unsigned char **)&pk_ptr,
- &pk_len,
- &psa_ecc_family);
+ rc = mbedtls_ecdsa_der_to_raw(key_bits, p, local_sig_len,
+ reformatted_sig, MAX_ECDSA_R_S_PAIR_LEN,
+ &local_sig_len);
if (rc != 0) {
- goto end2;
+ rc = CRYPTO_ERR_SIGNATURE;
+ goto end1;
}
+ local_sig_ptr = reformatted_sig;
}
#endif /*
* TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA || \
* TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA
**/
- /* Convert this pk_alg and md_alg to PSA key type and key algorithm */
- construct_psa_key_alg_and_type(pk_alg, md_alg, psa_ecc_family,
- &psa_alg, &psa_key_type);
-
-
- if ((psa_alg == PSA_ALG_NONE) || (psa_key_type == PSA_KEY_TYPE_NONE)) {
- rc = CRYPTO_ERR_SIGNATURE;
- goto end2;
- }
-
- /* filled-in key_attributes */
- psa_set_key_algorithm(&psa_key_attr, psa_alg);
- psa_set_key_type(&psa_key_attr, psa_key_type);
- psa_set_key_usage_flags(&psa_key_attr, PSA_KEY_USAGE_VERIFY_MESSAGE);
-
- /*
- * Note: In the implementation of the psa_import_key function in
- * version 3.6.0, the function expects the starting pointer of the
- * subject public key instead of the starting point of
- * SubjectPublicKeyInfo.
- * This is only needed while dealing with RSASSA_PSS (RSA Signature
- * scheme with Appendix based on Probabilistic Signature Scheme)
- * algorithm.
- */
- if (pk_alg == MBEDTLS_PK_RSASSA_PSS) {
- rc = pk_bytes_from_subpubkey((unsigned char **) &pk_ptr, &pk_len);
- if (rc != 0) {
- goto end2;
- }
- }
-
- /* Get the key_id using import API */
- status = psa_import_key(&psa_key_attr,
- pk_ptr,
- (size_t)pk_len,
- &psa_key_id);
-
- if (status != PSA_SUCCESS) {
- rc = CRYPTO_ERR_SIGNATURE;
- goto end2;
- }
-
- /*
- * Hash calculation and Signature verification of the given data payload
- * is wrapped under the psa_verify_message function.
- */
- status = psa_verify_message(psa_key_id, psa_alg,
+ /* Verify the signature. */
+ psa_status = psa_verify_message(psa_key_id, psa_alg,
data_ptr, data_len,
local_sig_ptr, local_sig_len);
-
- if (status != PSA_SUCCESS) {
+ if (psa_status == PSA_SUCCESS) {
+ /* The signature has been successfully verified. */
+ rc = CRYPTO_SUCCESS;
+ } else {
rc = CRYPTO_ERR_SIGNATURE;
- goto end1;
}
- /* Signature verification success */
- rc = CRYPTO_SUCCESS;
-
end1:
- /*
- * Destroy the key if it is created successfully
- */
+ /* Destroy the key from the PSA subsystem. */
psa_destroy_key(psa_key_id);
end2:
- mbedtls_free(sig_opts);
+ /* Free the pk context, if it is initialized. */
+ cleanup_pk_context(&pk, &pk_initialized);
+
return rc;
}
diff --git a/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h b/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h
new file mode 100644
index 0000000..84e76f7
--- /dev/null
+++ b/drivers/nxp/clk/s32cc/include/s32cc-clk-regs.h
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright 2020-2021, 2023-2024 NXP
+ */
+#ifndef S32CC_CLK_REGS_H
+#define S32CC_CLK_REGS_H
+
+#include <lib/utils_def.h>
+
+#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 */
+#define FXOSC_CTRL(FXOSC) ((FXOSC) + 0x0UL)
+#define FXOSC_CTRL_OSC_BYP BIT_32(31U)
+#define FXOSC_CTRL_COMP_EN BIT_32(24U)
+#define FXOSC_CTRL_EOCV_OFFSET 16U
+#define FXOSC_CTRL_EOCV_MASK GENMASK_32(23U, FXOSC_CTRL_EOCV_OFFSET)
+#define FXOSC_CTRL_EOCV(VAL) (FXOSC_CTRL_EOCV_MASK & \
+ ((uint32_t)(VAL) << FXOSC_CTRL_EOCV_OFFSET))
+#define FXOSC_CTRL_GM_SEL_OFFSET 4U
+#define FXOSC_CTRL_GM_SEL_MASK GENMASK_32(7U, FXOSC_CTRL_GM_SEL_OFFSET)
+#define FXOSC_CTRL_GM_SEL(VAL) (FXOSC_CTRL_GM_SEL_MASK & \
+ ((uint32_t)(VAL) << FXOSC_CTRL_GM_SEL_OFFSET))
+#define FXOSC_CTRL_OSCON BIT_32(0U)
+
+#define FXOSC_STAT(FXOSC) ((FXOSC) + 0x4UL)
+#define FXOSC_STAT_OSC_STAT BIT_32(31U)
+
+/* PLL */
+#define PLLDIG_PLLCR(PLL) ((PLL) + 0x0UL)
+#define PLLDIG_PLLCR_PLLPD BIT_32(31U)
+
+#define PLLDIG_PLLSR(PLL) ((PLL) + 0x4UL)
+#define PLLDIG_PLLSR_LOCK BIT_32(2U)
+
+#define PLLDIG_PLLDV(PLL) ((PLL) + 0x8UL)
+#define PLLDIG_PLLDV_RDIV_OFFSET 12U
+#define PLLDIG_PLLDV_RDIV_MASK GENMASK_32(14U, PLLDIG_PLLDV_RDIV_OFFSET)
+#define PLLDIG_PLLDV_RDIV_SET(VAL) (PLLDIG_PLLDV_RDIV_MASK & \
+ ((VAL) << PLLDIG_PLLDV_RDIV_OFFSET))
+#define PLLDIG_PLLDV_MFI_MASK GENMASK_32(7U, 0U)
+#define PLLDIG_PLLDV_MFI(DIV) (PLLDIG_PLLDV_MFI_MASK & (DIV))
+
+#define PLLDIG_PLLFD(PLL) ((PLL) + 0x10UL)
+#define PLLDIG_PLLFD_SMDEN BIT_32(30U)
+#define PLLDIG_PLLFD_MFN_MASK GENMASK_32(14U, 0U)
+#define PLLDIG_PLLFD_MFN_SET(VAL) (PLLDIG_PLLFD_MFN_MASK & (VAL))
+
+#define PLLDIG_PLLCLKMUX(PLL) ((PLL) + 0x20UL)
+
+#define PLLDIG_PLLODIV(PLL, N) ((PLL) + 0x80UL + ((N) * 0x4UL))
+#define PLLDIG_PLLODIV_DE BIT_32(31U)
+#define PLLDIG_PLLODIV_DIV_OFFSET 16U
+#define PLLDIG_PLLODIV_DIV_MASK GENMASK_32(23U, PLLDIG_PLLODIV_DIV_OFFSET)
+#define PLLDIG_PLLODIV_DIV(VAL) (((VAL) & PLLDIG_PLLODIV_DIV_MASK) >> \
+ PLLDIG_PLLODIV_DIV_OFFSET)
+#define PLLDIG_PLLODIV_DIV_SET(VAL) (PLLDIG_PLLODIV_DIV_MASK & ((VAL) << \
+ PLLDIG_PLLODIV_DIV_OFFSET))
+
+/* MMC_CGM */
+#define CGM_MUXn_CSC(CGM_ADDR, MUX) ((CGM_ADDR) + 0x300UL + ((MUX) * 0x40UL))
+#define MC_CGM_MUXn_CSC_SELCTL_OFFSET 24U
+#define MC_CGM_MUXn_CSC_SELCTL_MASK GENMASK_32(29U, MC_CGM_MUXn_CSC_SELCTL_OFFSET)
+#define MC_CGM_MUXn_CSC_SELCTL(val) (MC_CGM_MUXn_CSC_SELCTL_MASK & ((val) \
+ << MC_CGM_MUXn_CSC_SELCTL_OFFSET))
+#define MC_CGM_MUXn_CSC_CLK_SW BIT_32(2U)
+#define MC_CGM_MUXn_CSC_SAFE_SW BIT_32(3U)
+
+#define CGM_MUXn_CSS(CGM_ADDR, MUX) ((CGM_ADDR) + 0x304UL + ((MUX) * 0x40UL))
+#define MC_CGM_MUXn_CSS_SELSTAT_OFFSET 24U
+#define MC_CGM_MUXn_CSS_SELSTAT_MASK GENMASK_32(29U, MC_CGM_MUXn_CSS_SELSTAT_OFFSET)
+#define MC_CGM_MUXn_CSS_SELSTAT(css) ((MC_CGM_MUXn_CSS_SELSTAT_MASK & (css))\
+ >> MC_CGM_MUXn_CSS_SELSTAT_OFFSET)
+#define MC_CGM_MUXn_CSS_SWTRG(css) ((MC_CGM_MUXn_CSS_SWTRG_MASK & (css)) \
+ >> MC_CGM_MUXn_CSS_SWTRG_OFFSET)
+#define MC_CGM_MUXn_CSS_SWTRG_OFFSET 17U
+#define MC_CGM_MUXn_CSS_SWTRG_MASK GENMASK_32(19U, MC_CGM_MUXn_CSS_SWTRG_OFFSET)
+#define MC_CGM_MUXn_CSS_SWTRG_SUCCESS 0x1U
+#define MC_CGM_MUXn_CSS_SWTRG_SAFE_CLK 0x4U
+#define MC_CGM_MUXn_CSS_SWTRG_SAFE_CLK_INACTIVE 0x5U
+#define MC_CGM_MUXn_CSS_SWIP BIT_32(16U)
+#define MC_CGM_MUXn_CSS_SAFE_SW BIT_32(3U)
+
+/* 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.mk b/drivers/nxp/clk/s32cc/s32cc_clk.mk
index f5279d3..7a65ea6 100644
--- a/drivers/nxp/clk/s32cc/s32cc_clk.mk
+++ b/drivers/nxp/clk/s32cc/s32cc_clk.mk
@@ -6,6 +6,7 @@
PLAT_INCLUDES += \
-I${PLAT_DRIVERS_INCLUDE_PATH}/clk/s32cc \
+ -I${PLAT_DRIVERS_PATH}/clk/s32cc/include \
CLK_SOURCES := \
${PLAT_DRIVERS_PATH}/clk/s32cc/s32cc_clk_drv.c \
diff --git a/drivers/nxp/clk/s32cc/s32cc_clk_drv.c b/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
index e6653bd..fed16a7 100644
--- a/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
+++ b/drivers/nxp/clk/s32cc/s32cc_clk_drv.c
@@ -5,26 +5,824 @@
*/
#include <errno.h>
+#include <s32cc-clk-regs.h>
+
#include <common/debug.h>
#include <drivers/clk.h>
+#include <lib/mmio.h>
+#include <s32cc-clk-ids.h>
#include <s32cc-clk-modules.h>
#include <s32cc-clk-utils.h>
+#define MAX_STACK_DEPTH (15U)
+
+/* This is used for floating-point precision calculations. */
+#define FP_PRECISION (100000000UL)
+
+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;
+};
+
+static int update_stack_depth(unsigned int *depth)
+{
+ if (*depth == 0U) {
+ return -ENOMEM;
+ }
+
+ (*depth)--;
+ return 0;
+}
+
+static struct s32cc_clk_drv *get_drv(void)
+{
+ 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,
+ };
+
+ return &driver;
+}
+
+static int enable_module(const struct s32cc_clk_obj *module, unsigned int *depth);
+
+static int enable_clk_module(const struct s32cc_clk_obj *module,
+ const struct s32cc_clk_drv *drv,
+ unsigned int *depth)
+{
+ const struct s32cc_clk *clk = s32cc_obj2clk(module);
+ int ret;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (clk == NULL) {
+ return -EINVAL;
+ }
+
+ if (clk->module != NULL) {
+ return enable_module(clk->module, depth);
+ }
+
+ if (clk->pclock != NULL) {
+ return enable_clk_module(&clk->pclock->desc, drv, depth);
+ }
+
+ return -EINVAL;
+}
+
+static int get_base_addr(enum s32cc_clk_source id, const struct s32cc_clk_drv *drv,
+ uintptr_t *base)
+{
+ int ret = 0;
+
+ switch (id) {
+ case S32CC_FXOSC:
+ *base = drv->fxosc_base;
+ break;
+ 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;
+ case S32CC_FIRC:
+ break;
+ case S32CC_SIRC:
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ if (ret != 0) {
+ ERROR("Unknown clock source id: %u\n", id);
+ }
+
+ return ret;
+}
+
+static void enable_fxosc(const struct s32cc_clk_drv *drv)
+{
+ uintptr_t fxosc_base = drv->fxosc_base;
+ uint32_t ctrl;
+
+ ctrl = mmio_read_32(FXOSC_CTRL(fxosc_base));
+ if ((ctrl & FXOSC_CTRL_OSCON) != U(0)) {
+ return;
+ }
+
+ ctrl = FXOSC_CTRL_COMP_EN;
+ ctrl &= ~FXOSC_CTRL_OSC_BYP;
+ ctrl |= FXOSC_CTRL_EOCV(0x1);
+ ctrl |= FXOSC_CTRL_GM_SEL(0x7);
+ mmio_write_32(FXOSC_CTRL(fxosc_base), ctrl);
+
+ /* Switch ON the crystal oscillator. */
+ mmio_setbits_32(FXOSC_CTRL(fxosc_base), FXOSC_CTRL_OSCON);
+
+ /* Wait until the clock is stable. */
+ while ((mmio_read_32(FXOSC_STAT(fxosc_base)) & FXOSC_STAT_OSC_STAT) == U(0)) {
+ }
+}
+
+static int enable_osc(const struct s32cc_clk_obj *module,
+ const struct s32cc_clk_drv *drv,
+ unsigned int *depth)
+{
+ const struct s32cc_osc *osc = s32cc_obj2osc(module);
+ int ret = 0;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ switch (osc->source) {
+ case S32CC_FXOSC:
+ enable_fxosc(drv);
+ break;
+ /* FIRC and SIRC oscillators are enabled by default */
+ case S32CC_FIRC:
+ break;
+ case S32CC_SIRC:
+ break;
+ default:
+ ERROR("Invalid oscillator %d\n", osc->source);
+ ret = -EINVAL;
+ break;
+ };
+
+ return ret;
+}
+
+static int get_pll_mfi_mfn(unsigned long pll_vco, unsigned long ref_freq,
+ uint32_t *mfi, uint32_t *mfn)
+
+{
+ unsigned long vco;
+ unsigned long mfn64;
+
+ /* FRAC-N mode */
+ *mfi = (uint32_t)(pll_vco / ref_freq);
+
+ /* MFN formula : (double)(pll_vco % ref_freq) / ref_freq * 18432.0 */
+ mfn64 = pll_vco % ref_freq;
+ mfn64 *= FP_PRECISION;
+ mfn64 /= ref_freq;
+ mfn64 *= 18432UL;
+ mfn64 /= FP_PRECISION;
+
+ if (mfn64 > UINT32_MAX) {
+ return -EINVAL;
+ }
+
+ *mfn = (uint32_t)mfn64;
+
+ vco = ((unsigned long)*mfn * FP_PRECISION) / 18432UL;
+ vco += (unsigned long)*mfi * FP_PRECISION;
+ vco *= ref_freq;
+ vco /= FP_PRECISION;
+
+ if (vco != pll_vco) {
+ ERROR("Failed to find MFI and MFN settings for PLL freq %lu. Nearest freq = %lu\n",
+ pll_vco, vco);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct s32cc_clkmux *get_pll_mux(const struct s32cc_pll *pll)
+{
+ const struct s32cc_clk_obj *source = pll->source;
+ const struct s32cc_clk *clk;
+
+ if (source == NULL) {
+ ERROR("Failed to identify PLL's parent\n");
+ return NULL;
+ }
+
+ if (source->type != s32cc_clk_t) {
+ ERROR("The parent of the PLL isn't a clock\n");
+ return NULL;
+ }
+
+ clk = s32cc_obj2clk(source);
+
+ if (clk->module == NULL) {
+ ERROR("The clock isn't connected to a module\n");
+ return NULL;
+ }
+
+ source = clk->module;
+
+ if ((source->type != s32cc_clkmux_t) &&
+ (source->type != s32cc_shared_clkmux_t)) {
+ ERROR("The parent of the PLL isn't a MUX\n");
+ return NULL;
+ }
+
+ return s32cc_obj2clkmux(source);
+}
+
+static void disable_odiv(uintptr_t pll_addr, uint32_t div_index)
+{
+ mmio_clrbits_32(PLLDIG_PLLODIV(pll_addr, div_index), PLLDIG_PLLODIV_DE);
+}
+
+static void enable_odiv(uintptr_t pll_addr, uint32_t div_index)
+{
+ mmio_setbits_32(PLLDIG_PLLODIV(pll_addr, div_index), PLLDIG_PLLODIV_DE);
+}
+
+static void disable_odivs(uintptr_t pll_addr, uint32_t ndivs)
+{
+ uint32_t i;
+
+ for (i = 0; i < ndivs; i++) {
+ disable_odiv(pll_addr, i);
+ }
+}
+
+static void enable_pll_hw(uintptr_t pll_addr)
+{
+ /* Enable the PLL. */
+ mmio_write_32(PLLDIG_PLLCR(pll_addr), 0x0);
+
+ /* Poll until PLL acquires lock. */
+ while ((mmio_read_32(PLLDIG_PLLSR(pll_addr)) & PLLDIG_PLLSR_LOCK) == 0U) {
+ }
+}
+
+static void disable_pll_hw(uintptr_t pll_addr)
+{
+ mmio_write_32(PLLDIG_PLLCR(pll_addr), PLLDIG_PLLCR_PLLPD);
+}
+
+static int program_pll(const struct s32cc_pll *pll, uintptr_t pll_addr,
+ const struct s32cc_clk_drv *drv, uint32_t sclk_id,
+ unsigned long sclk_freq)
+{
+ uint32_t rdiv = 1, mfi, mfn;
+ int ret;
+
+ ret = get_pll_mfi_mfn(pll->vco_freq, sclk_freq, &mfi, &mfn);
+ if (ret != 0) {
+ return -EINVAL;
+ }
+
+ /* Disable ODIVs*/
+ disable_odivs(pll_addr, pll->ndividers);
+
+ /* Disable PLL */
+ disable_pll_hw(pll_addr);
+
+ /* Program PLLCLKMUX */
+ mmio_write_32(PLLDIG_PLLCLKMUX(pll_addr), sclk_id);
+
+ /* Program VCO */
+ mmio_clrsetbits_32(PLLDIG_PLLDV(pll_addr),
+ PLLDIG_PLLDV_RDIV_MASK | PLLDIG_PLLDV_MFI_MASK,
+ PLLDIG_PLLDV_RDIV_SET(rdiv) | PLLDIG_PLLDV_MFI(mfi));
+
+ mmio_write_32(PLLDIG_PLLFD(pll_addr),
+ PLLDIG_PLLFD_MFN_SET(mfn) | PLLDIG_PLLFD_SMDEN);
+
+ enable_pll_hw(pll_addr);
+
+ return ret;
+}
+
+static int enable_pll(const struct s32cc_clk_obj *module,
+ const struct s32cc_clk_drv *drv,
+ unsigned int *depth)
+{
+ const struct s32cc_pll *pll = s32cc_obj2pll(module);
+ const struct s32cc_clkmux *mux;
+ uintptr_t pll_addr = UL(0x0);
+ unsigned long sclk_freq;
+ uint32_t sclk_id;
+ int ret;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ mux = get_pll_mux(pll);
+ if (mux == NULL) {
+ return -EINVAL;
+ }
+
+ if (pll->instance != mux->module) {
+ ERROR("MUX type is not in sync with PLL ID\n");
+ return -EINVAL;
+ }
+
+ ret = get_base_addr(pll->instance, drv, &pll_addr);
+ if (ret != 0) {
+ ERROR("Failed to detect PLL instance\n");
+ return ret;
+ }
+
+ switch (mux->source_id) {
+ case S32CC_CLK_FIRC:
+ sclk_freq = 48U * MHZ;
+ sclk_id = 0;
+ break;
+ case S32CC_CLK_FXOSC:
+ sclk_freq = 40U * MHZ;
+ sclk_id = 1;
+ break;
+ default:
+ ERROR("Invalid source selection for PLL 0x%lx\n",
+ pll_addr);
+ return -EINVAL;
+ };
+
+ return program_pll(pll, pll_addr, drv, sclk_id, sclk_freq);
+}
+
+static inline struct s32cc_pll *get_div_pll(const struct s32cc_pll_out_div *pdiv)
+{
+ const struct s32cc_clk_obj *parent;
+
+ parent = pdiv->parent;
+ if (parent == NULL) {
+ ERROR("Failed to identify PLL divider's parent\n");
+ return NULL;
+ }
+
+ if (parent->type != s32cc_pll_t) {
+ ERROR("The parent of the divider is not a PLL instance\n");
+ return NULL;
+ }
+
+ return s32cc_obj2pll(parent);
+}
+
+static void config_pll_out_div(uintptr_t pll_addr, uint32_t div_index, uint32_t dc)
+{
+ uint32_t pllodiv;
+ uint32_t pdiv;
+
+ pllodiv = mmio_read_32(PLLDIG_PLLODIV(pll_addr, div_index));
+ pdiv = PLLDIG_PLLODIV_DIV(pllodiv);
+
+ if (((pdiv + 1U) == dc) && ((pllodiv & PLLDIG_PLLODIV_DE) != 0U)) {
+ return;
+ }
+
+ if ((pllodiv & PLLDIG_PLLODIV_DE) != 0U) {
+ disable_odiv(pll_addr, div_index);
+ }
+
+ pllodiv = PLLDIG_PLLODIV_DIV_SET(dc - 1U);
+ mmio_write_32(PLLDIG_PLLODIV(pll_addr, div_index), pllodiv);
+
+ enable_odiv(pll_addr, div_index);
+}
+
+static int enable_pll_div(const struct s32cc_clk_obj *module,
+ const struct s32cc_clk_drv *drv,
+ unsigned int *depth)
+{
+ const struct s32cc_pll_out_div *pdiv = s32cc_obj2plldiv(module);
+ uintptr_t pll_addr = 0x0ULL;
+ const struct s32cc_pll *pll;
+ uint32_t dc;
+ int ret;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ pll = get_div_pll(pdiv);
+ if (pll == NULL) {
+ ERROR("The parent of the PLL DIV is invalid\n");
+ return 0;
+ }
+
+ ret = get_base_addr(pll->instance, drv, &pll_addr);
+ if (ret != 0) {
+ ERROR("Failed to detect PLL instance\n");
+ return -EINVAL;
+ }
+
+ dc = (uint32_t)(pll->vco_freq / pdiv->freq);
+
+ config_pll_out_div(pll_addr, pdiv->index, dc);
+
+ return 0;
+}
+
+static int cgm_mux_clk_config(uintptr_t cgm_addr, uint32_t mux, uint32_t source,
+ bool safe_clk)
+{
+ uint32_t css, csc;
+
+ css = mmio_read_32(CGM_MUXn_CSS(cgm_addr, mux));
+
+ /* Already configured */
+ if ((MC_CGM_MUXn_CSS_SELSTAT(css) == source) &&
+ (MC_CGM_MUXn_CSS_SWTRG(css) == MC_CGM_MUXn_CSS_SWTRG_SUCCESS) &&
+ ((css & MC_CGM_MUXn_CSS_SWIP) == 0U) && !safe_clk) {
+ return 0;
+ }
+
+ /* Ongoing clock switch? */
+ while ((mmio_read_32(CGM_MUXn_CSS(cgm_addr, mux)) &
+ MC_CGM_MUXn_CSS_SWIP) != 0U) {
+ }
+
+ csc = mmio_read_32(CGM_MUXn_CSC(cgm_addr, mux));
+
+ /* Clear previous source. */
+ csc &= ~(MC_CGM_MUXn_CSC_SELCTL_MASK);
+
+ if (!safe_clk) {
+ /* Select the clock source and trigger the clock switch. */
+ csc |= MC_CGM_MUXn_CSC_SELCTL(source) | MC_CGM_MUXn_CSC_CLK_SW;
+ } else {
+ /* Switch to safe clock */
+ csc |= MC_CGM_MUXn_CSC_SAFE_SW;
+ }
+
+ mmio_write_32(CGM_MUXn_CSC(cgm_addr, mux), csc);
+
+ /* Wait for configuration bit to auto-clear. */
+ while ((mmio_read_32(CGM_MUXn_CSC(cgm_addr, mux)) &
+ MC_CGM_MUXn_CSC_CLK_SW) != 0U) {
+ }
+
+ /* Is the clock switch completed? */
+ while ((mmio_read_32(CGM_MUXn_CSS(cgm_addr, mux)) &
+ MC_CGM_MUXn_CSS_SWIP) != 0U) {
+ }
+
+ /*
+ * Check if the switch succeeded.
+ * Check switch trigger cause and the source.
+ */
+ css = mmio_read_32(CGM_MUXn_CSS(cgm_addr, mux));
+ if (!safe_clk) {
+ if ((MC_CGM_MUXn_CSS_SWTRG(css) == MC_CGM_MUXn_CSS_SWTRG_SUCCESS) &&
+ (MC_CGM_MUXn_CSS_SELSTAT(css) == source)) {
+ return 0;
+ }
+
+ ERROR("Failed to change the source of mux %" PRIu32 " to %" PRIu32 " (CGM=%lu)\n",
+ mux, source, cgm_addr);
+ } else {
+ if (((MC_CGM_MUXn_CSS_SWTRG(css) == MC_CGM_MUXn_CSS_SWTRG_SAFE_CLK) ||
+ (MC_CGM_MUXn_CSS_SWTRG(css) == MC_CGM_MUXn_CSS_SWTRG_SAFE_CLK_INACTIVE)) &&
+ ((MC_CGM_MUXn_CSS_SAFE_SW & css) != 0U)) {
+ return 0;
+ }
+
+ ERROR("The switch of mux %" PRIu32 " (CGM=%lu) to safe clock failed\n",
+ mux, cgm_addr);
+ }
+
+ return -EINVAL;
+}
+
+static int enable_cgm_mux(const struct s32cc_clkmux *mux,
+ const struct s32cc_clk_drv *drv)
+{
+ uintptr_t cgm_addr = UL(0x0);
+ uint32_t mux_hw_clk;
+ int ret;
+
+ ret = get_base_addr(mux->module, drv, &cgm_addr);
+ if (ret != 0) {
+ return ret;
+ }
+
+ mux_hw_clk = (uint32_t)S32CC_CLK_ID(mux->source_id);
+
+ return cgm_mux_clk_config(cgm_addr, mux->index,
+ mux_hw_clk, false);
+}
+
+static int enable_mux(const struct s32cc_clk_obj *module,
+ const struct s32cc_clk_drv *drv,
+ unsigned int *depth)
+{
+ const struct s32cc_clkmux *mux = s32cc_obj2clkmux(module);
+ const struct s32cc_clk *clk;
+ int ret = 0;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (mux == NULL) {
+ return -EINVAL;
+ }
+
+ clk = s32cc_get_arch_clk(mux->source_id);
+ if (clk == NULL) {
+ ERROR("Invalid parent (%lu) for mux %" PRIu8 "\n",
+ mux->source_id, mux->index);
+ return -EINVAL;
+ }
+
+ switch (mux->module) {
+ /* PLL mux will be enabled by PLL setup */
+ case S32CC_ARM_PLL:
+ break;
+ 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;
+ break;
+ };
+
+ return ret;
+}
+
-#define MAX_STACK_DEPTH (15U)
+static int enable_dfs(const struct s32cc_clk_obj *module,
+ const struct s32cc_clk_drv *drv,
+ unsigned int *depth)
+{
+ int ret = 0;
-static int update_stack_depth(unsigned int *depth)
+ 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)
{
- if (*depth == 0U) {
- return -ENOMEM;
+ 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;
}
- (*depth)--;
+ 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();
+ int ret = 0;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (drv == NULL) {
+ return -EINVAL;
+ }
+
+ switch (module->type) {
+ case s32cc_osc_t:
+ ret = enable_osc(module, drv, depth);
+ break;
+ case s32cc_clk_t:
+ ret = enable_clk_module(module, drv, depth);
+ break;
+ case s32cc_pll_t:
+ ret = enable_pll(module, drv, depth);
+ break;
+ case s32cc_pll_out_div_t:
+ ret = enable_pll_div(module, drv, depth);
+ break;
+ case s32cc_clkmux_t:
+ ret = enable_mux(module, drv, depth);
+ break;
+ case s32cc_shared_clkmux_t:
+ ret = enable_mux(module, drv, depth);
+ break;
+ 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;
+ }
+
+ return ret;
+}
+
static int s32cc_clk_enable(unsigned long id)
{
- return -ENOTSUP;
+ unsigned int depth = MAX_STACK_DEPTH;
+ const struct s32cc_clk *clk;
+
+ clk = s32cc_get_arch_clk(id);
+ if (clk == NULL) {
+ return -EINVAL;
+ }
+
+ return enable_module(&clk->desc, &depth);
}
static void s32cc_clk_disable(unsigned long id)
@@ -97,6 +895,157 @@
return -EINVAL;
}
+static int set_pll_freq(const struct s32cc_clk_obj *module, unsigned long rate,
+ unsigned long *orate, unsigned int *depth)
+{
+ struct s32cc_pll *pll = s32cc_obj2pll(module);
+ int ret;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if ((pll->vco_freq != 0UL) && (pll->vco_freq != rate)) {
+ ERROR("PLL frequency was already set\n");
+ return -EINVAL;
+ }
+
+ pll->vco_freq = rate;
+ *orate = pll->vco_freq;
+
+ return 0;
+}
+
+static int set_pll_div_freq(const struct s32cc_clk_obj *module, unsigned long rate,
+ unsigned long *orate, unsigned int *depth)
+{
+ struct s32cc_pll_out_div *pdiv = s32cc_obj2plldiv(module);
+ const struct s32cc_pll *pll;
+ unsigned long prate, dc;
+ int ret;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (pdiv->parent == NULL) {
+ ERROR("Failed to identify PLL divider's parent\n");
+ return -EINVAL;
+ }
+
+ pll = s32cc_obj2pll(pdiv->parent);
+ if (pll == NULL) {
+ ERROR("The parent of the PLL DIV is invalid\n");
+ return -EINVAL;
+ }
+
+ prate = pll->vco_freq;
+
+ /**
+ * The PLL is not initialized yet, so let's take a risk
+ * and accept the proposed rate.
+ */
+ if (prate == 0UL) {
+ pdiv->freq = rate;
+ *orate = rate;
+ return 0;
+ }
+
+ /* Decline in case the rate cannot fit PLL's requirements. */
+ dc = prate / rate;
+ if ((prate / dc) != rate) {
+ return -EINVAL;
+ }
+
+ pdiv->freq = rate;
+ *orate = pdiv->freq;
+
+ return 0;
+}
+
+static int set_fixed_div_freq(const struct s32cc_clk_obj *module, unsigned long rate,
+ unsigned long *orate, unsigned int *depth)
+{
+ const struct s32cc_fixed_div *fdiv = s32cc_obj2fixeddiv(module);
+ int ret;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (fdiv->parent == NULL) {
+ ERROR("The divider doesn't have a valid parent\b");
+ return -EINVAL;
+ }
+
+ ret = set_module_rate(fdiv->parent, rate * fdiv->rate_div, orate, depth);
+
+ /* Update the output rate based on the parent's rate */
+ *orate /= fdiv->rate_div;
+
+ return ret;
+}
+
+static int set_mux_freq(const struct s32cc_clk_obj *module, unsigned long rate,
+ unsigned long *orate, unsigned int *depth)
+{
+ const struct s32cc_clkmux *mux = s32cc_obj2clkmux(module);
+ const struct s32cc_clk *clk = s32cc_get_arch_clk(mux->source_id);
+ int ret;
+
+ ret = update_stack_depth(depth);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (clk == NULL) {
+ ERROR("Mux (id:%" PRIu8 ") without a valid source (%lu)\n",
+ mux->index, mux->source_id);
+ return -EINVAL;
+ }
+
+ return 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)
@@ -108,6 +1057,8 @@
return ret;
}
+ ret = -EINVAL;
+
switch (module->type) {
case s32cc_clk_t:
ret = set_clk_freq(module, rate, orate, depth);
@@ -115,8 +1066,28 @@
case s32cc_osc_t:
ret = set_osc_freq(module, rate, orate, depth);
break;
+ case s32cc_pll_t:
+ ret = set_pll_freq(module, rate, orate, depth);
+ break;
+ case s32cc_pll_out_div_t:
+ ret = set_pll_div_freq(module, rate, orate, depth);
+ break;
+ case s32cc_fixed_div_t:
+ ret = set_fixed_div_freq(module, rate, orate, depth);
+ break;
+ case s32cc_clkmux_t:
+ ret = set_mux_freq(module, rate, orate, depth);
+ break;
+ 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;
}
@@ -151,7 +1122,49 @@
static int s32cc_clk_set_parent(unsigned long id, unsigned long parent_id)
{
- return -ENOTSUP;
+ const struct s32cc_clk *parent;
+ const struct s32cc_clk *clk;
+ bool valid_source = false;
+ struct s32cc_clkmux *mux;
+ uint8_t i;
+
+ clk = s32cc_get_arch_clk(id);
+ if (clk == NULL) {
+ return -EINVAL;
+ }
+
+ parent = s32cc_get_arch_clk(parent_id);
+ if (parent == NULL) {
+ return -EINVAL;
+ }
+
+ if (!is_s32cc_clk_mux(clk)) {
+ ERROR("Clock %lu is not a mux\n", id);
+ return -EINVAL;
+ }
+
+ mux = s32cc_clk2mux(clk);
+ if (mux == NULL) {
+ ERROR("Failed to cast clock %lu to clock mux\n", id);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < mux->nclks; i++) {
+ if (mux->clkids[i] == parent_id) {
+ valid_source = true;
+ break;
+ }
+ }
+
+ if (!valid_source) {
+ ERROR("Clock %lu is not a valid clock for mux %lu\n",
+ parent_id, id);
+ return -EINVAL;
+ }
+
+ mux->source_id = parent_id;
+
+ return 0;
}
void s32cc_clk_register_drv(void)
diff --git a/drivers/nxp/clk/s32cc/s32cc_clk_modules.c b/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
index f8fc52f..45e2070 100644
--- a/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
+++ b/drivers/nxp/clk/s32cc/s32cc_clk_modules.c
@@ -7,6 +7,9 @@
#include <s32cc-clk-modules.h>
#include <s32cc-clk-utils.h>
+#define S32CC_A53_MIN_FREQ (48UL * MHZ)
+#define S32CC_A53_MAX_FREQ (1000UL * MHZ)
+
/* Oscillators */
static struct s32cc_osc fxosc =
S32CC_OSC_INIT(S32CC_FXOSC);
@@ -23,11 +26,130 @@
static struct s32cc_clk sirc_clk =
S32CC_MODULE_CLK(sirc);
+/* ARM PLL */
+static struct s32cc_clkmux arm_pll_mux =
+ S32CC_CLKMUX_INIT(S32CC_ARM_PLL, 0, 2,
+ S32CC_CLK_FIRC,
+ S32CC_CLK_FXOSC, 0, 0, 0);
+static struct s32cc_clk arm_pll_mux_clk =
+ S32CC_MODULE_CLK(arm_pll_mux);
+static struct s32cc_pll armpll =
+ S32CC_PLL_INIT(arm_pll_mux_clk, S32CC_ARM_PLL, 2);
+static struct s32cc_clk arm_pll_vco_clk =
+ S32CC_FREQ_MODULE_CLK(armpll, 1400 * MHZ, 2000 * MHZ);
+
+static struct s32cc_pll_out_div arm_pll_phi0_div =
+ S32CC_PLL_OUT_DIV_INIT(armpll, 0);
+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);
+
-static struct s32cc_clk *s32cc_hw_clk_list[3] = {
+/* MC_CGM1 */
+static struct s32cc_clkmux cgm1_mux0 =
+ S32CC_SHARED_CLKMUX_INIT(S32CC_CGM1, 0, 3,
+ S32CC_CLK_FIRC,
+ S32CC_CLK_ARM_PLL_PHI0,
+ S32CC_CLK_ARM_PLL_DFS2, 0, 0);
+static struct s32cc_clk cgm1_mux0_clk = S32CC_MODULE_CLK(cgm1_mux0);
+
+/* A53_CORE */
+static struct s32cc_clk a53_core_clk =
+ S32CC_FREQ_MODULE_CLK(cgm1_mux0_clk, S32CC_A53_MIN_FREQ,
+ S32CC_A53_MAX_FREQ);
+/* A53_CORE_DIV2 */
+static struct s32cc_fixed_div a53_core_div2 =
+ S32CC_FIXED_DIV_INIT(cgm1_mux0_clk, 2);
+static struct s32cc_clk a53_core_div2_clk =
+ S32CC_FREQ_MODULE_CLK(a53_core_div2, S32CC_A53_MIN_FREQ / 2,
+ S32CC_A53_MAX_FREQ / 2);
+/* A53_CORE_DIV10 */
+static struct s32cc_fixed_div a53_core_div10 =
+ S32CC_FIXED_DIV_INIT(cgm1_mux0_clk, 10);
+static struct s32cc_clk a53_core_div10_clk =
+ S32CC_FREQ_MODULE_CLK(a53_core_div10, S32CC_A53_MIN_FREQ / 10,
+ S32CC_A53_MAX_FREQ / 10);
+
+/* 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 = {
@@ -36,10 +158,45 @@
.n_clks = ARRAY_SIZE(s32cc_hw_clk_list),
};
+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 = {
+ .type_mask = S32CC_CLK_TYPE(S32CC_CLK_ARM_PLL_MUX),
+ .clks = &s32cc_arch_clk_list[0],
+ .n_clks = ARRAY_SIZE(s32cc_arch_clk_list),
+};
+
struct s32cc_clk *s32cc_get_arch_clk(unsigned long id)
{
- static const struct s32cc_clk_array *clk_table[1] = {
+ static const struct s32cc_clk_array *clk_table[2] = {
&s32cc_hw_clocks,
+ &s32cc_arch_clocks,
};
return s32cc_get_clk_from_table(clk_table, ARRAY_SIZE(clk_table), id);
diff --git a/drivers/nxp/clk/s32cc/s32cc_early_clks.c b/drivers/nxp/clk/s32cc/s32cc_early_clks.c
index fc1dc02..8c4a9e8 100644
--- a/drivers/nxp/clk/s32cc/s32cc_early_clks.c
+++ b/drivers/nxp/clk/s32cc/s32cc_early_clks.c
@@ -4,11 +4,165 @@
* 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_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
+
+static int enable_fxosc_clk(void)
+{
+ int ret;
+
+ ret = clk_set_rate(S32CC_CLK_FXOSC, S32CC_FXOSC_FREQ, NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_enable(S32CC_CLK_FXOSC);
+ if (ret != 0) {
+ return ret;
+ }
+
+ 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;
+ }
+
+ ret = clk_set_rate(S32CC_CLK_ARM_PLL_VCO, S32CC_ARM_PLL_VCO_FREQ, NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_set_rate(S32CC_CLK_ARM_PLL_PHI0, S32CC_ARM_PLL_PHI0_FREQ, NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_enable(S32CC_CLK_ARM_PLL_VCO);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = clk_enable(S32CC_CLK_ARM_PLL_PHI0);
+ if (ret != 0) {
+ return ret;
+ }
+
+ 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_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;
+ }
+
+ ret = clk_enable(S32CC_CLK_A53_CORE);
+ if (ret != 0) {
+ return ret;
+ }
+
+ 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)
{
@@ -16,7 +170,32 @@
s32cc_clk_register_drv();
- ret = clk_set_rate(S32CC_CLK_FXOSC, S32CC_FXOSC_FREQ, NULL);
+ 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;
}
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/nxp/gpio/nxp_gpio.c b/drivers/nxp/gpio/nxp_gpio.c
index 28c9db9..b477b79 100644
--- a/drivers/nxp/gpio/nxp_gpio.c
+++ b/drivers/nxp/gpio/nxp_gpio.c
@@ -28,8 +28,8 @@
ERROR("GPIO is not initialized.\n");
return GPIO_FAILURE;
}
-
- gpdir = gpio_base_addr + GPDIR_REG_OFFSET;
+ /* Divide by 4 since we're operating on 32-bit pointer addresses. */
+ gpdir = gpio_base_addr + (GPDIR_REG_OFFSET >> 2);
gpdat = gpio_base_addr + (GPDAT_REG_OFFSET >> 2);
/*
@@ -67,8 +67,9 @@
return GPIO_FAILURE;
}
- gpdir = gpio_base_addr + GPDIR_REG_OFFSET;
- gpdat = gpio_base_addr + GPDAT_REG_OFFSET;
+ /* Divide by 4 since we're operating on 32-bit pointer addresses. */
+ gpdir = gpio_base_addr + (GPDIR_REG_OFFSET >> 2);
+ gpdat = gpio_base_addr + (GPDAT_REG_OFFSET >> 2);
/*
* Reset the corresponding bit in direction and data register
diff --git a/drivers/st/clk/clk-stm32mp2.c b/drivers/st/clk/clk-stm32mp2.c
new file mode 100644
index 0000000..12839f1
--- /dev/null
+++ b/drivers/st/clk/clk-stm32mp2.c
@@ -0,0 +1,2357 @@
+/*
+ * Copyright (C) 2024, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+
+#include "clk-stm32-core.h"
+#include <common/fdt_wrappers.h>
+#include <drivers/clk.h>
+#include <drivers/delay_timer.h>
+#include <drivers/generic_delay_timer.h>
+#include <drivers/st/stm32mp2_clk.h>
+#include <drivers/st/stm32mp_clkfunc.h>
+#include <lib/mmio.h>
+#include <lib/spinlock.h>
+#include <lib/utils_def.h>
+#include <libfdt.h>
+
+#include <platform_def.h>
+
+struct stm32_osci_dt_cfg {
+ unsigned long freq;
+ uint32_t drive;
+ bool bypass;
+ bool digbyp;
+ bool css;
+};
+
+struct stm32_pll_dt_cfg {
+ uint32_t src;
+ uint32_t frac;
+ uint32_t cfg[PLLCFG_NB];
+ uint32_t csg[PLLCSG_NB];
+ bool csg_enabled;
+ bool enabled;
+};
+
+struct stm32_clk_platdata {
+ uintptr_t rcc_base;
+ uint32_t nosci;
+ struct stm32_osci_dt_cfg *osci;
+ uint32_t npll;
+ struct stm32_pll_dt_cfg *pll;
+ uint32_t nflexgen;
+ uint32_t *flexgen;
+ uint32_t nbusclk;
+ uint32_t *busclk;
+ uint32_t nkernelclk;
+ uint32_t *kernelclk;
+};
+
+/* A35 Sub-System which manages its own PLL (PLL1) */
+#define A35_SS_CHGCLKREQ 0x0000
+#define A35_SS_PLL_FREQ1 0x0080
+#define A35_SS_PLL_FREQ2 0x0090
+#define A35_SS_PLL_ENABLE 0x00a0
+
+#define A35_SS_CHGCLKREQ_ARM_CHGCLKREQ BIT(0)
+#define A35_SS_CHGCLKREQ_ARM_CHGCLKACK BIT(1)
+
+#define A35_SS_PLL_FREQ1_FBDIV_MASK GENMASK(11, 0)
+#define A35_SS_PLL_FREQ1_FBDIV_SHIFT 0
+#define A35_SS_PLL_FREQ1_REFDIV_MASK GENMASK(21, 16)
+#define A35_SS_PLL_FREQ1_REFDIV_SHIFT 16
+
+#define A35_SS_PLL_FREQ2_POSTDIV1_MASK GENMASK(2, 0)
+#define A35_SS_PLL_FREQ2_POSTDIV1_SHIFT 0
+#define A35_SS_PLL_FREQ2_POSTDIV2_MASK GENMASK(5, 3)
+#define A35_SS_PLL_FREQ2_POSTDIV2_SHIFT 3
+
+#define A35_SS_PLL_ENABLE_PD BIT(0)
+#define A35_SS_PLL_ENABLE_LOCKP BIT(1)
+#define A35_SS_PLL_ENABLE_NRESET_SWPLL_FF BIT(2)
+
+#define TIMEOUT_US_200MS U(200000)
+#define TIMEOUT_US_1S U(1000000)
+
+#define PLLRDY_TIMEOUT TIMEOUT_US_200MS
+#define CLKSRC_TIMEOUT TIMEOUT_US_200MS
+#define CLKDIV_TIMEOUT TIMEOUT_US_200MS
+#define OSCRDY_TIMEOUT TIMEOUT_US_1S
+
+/* PLL minimal frequencies for clock sources */
+#define PLL_REFCLK_MIN UL(5000000)
+#define PLL_FRAC_REFCLK_MIN UL(10000000)
+
+#define XBAR_CHANNEL_NB 64
+
+/* Warning, should be start to 1 */
+enum clock {
+ _CK_0_MHZ,
+
+ /* ROOT CLOCKS */
+ _CK_HSI,
+ _CK_HSE,
+ _CK_MSI,
+ _CK_LSI,
+ _CK_LSE,
+ _I2SCKIN,
+ _SPDIFSYMB,
+ _CK_PLL1,
+ _CK_PLL2,
+ _CK_PLL3,
+ _CK_PLL4,
+ _CK_PLL5,
+ _CK_PLL6,
+ _CK_PLL7,
+ _CK_PLL8,
+ _CK_HSE_RTC,
+ _CK_RTCCK,
+ _CK_ICN_HS_MCU,
+ _CK_ICN_SDMMC,
+ _CK_ICN_DDR,
+ _CK_ICN_HSL,
+ _CK_ICN_NIC,
+ _CK_ICN_LS_MCU,
+ _CK_FLEXGEN_07,
+ _CK_FLEXGEN_08,
+ _CK_FLEXGEN_09,
+ _CK_FLEXGEN_10,
+ _CK_FLEXGEN_11,
+ _CK_FLEXGEN_12,
+ _CK_FLEXGEN_13,
+ _CK_FLEXGEN_14,
+ _CK_FLEXGEN_15,
+ _CK_FLEXGEN_16,
+ _CK_FLEXGEN_17,
+ _CK_FLEXGEN_18,
+ _CK_FLEXGEN_19,
+ _CK_FLEXGEN_20,
+ _CK_FLEXGEN_21,
+ _CK_FLEXGEN_22,
+ _CK_FLEXGEN_23,
+ _CK_FLEXGEN_24,
+ _CK_FLEXGEN_25,
+ _CK_FLEXGEN_26,
+ _CK_FLEXGEN_27,
+ _CK_FLEXGEN_28,
+ _CK_FLEXGEN_29,
+ _CK_FLEXGEN_30,
+ _CK_FLEXGEN_31,
+ _CK_FLEXGEN_32,
+ _CK_FLEXGEN_33,
+ _CK_FLEXGEN_34,
+ _CK_FLEXGEN_35,
+ _CK_FLEXGEN_36,
+ _CK_FLEXGEN_37,
+ _CK_FLEXGEN_38,
+ _CK_FLEXGEN_39,
+ _CK_FLEXGEN_40,
+ _CK_FLEXGEN_41,
+ _CK_FLEXGEN_42,
+ _CK_FLEXGEN_43,
+ _CK_FLEXGEN_44,
+ _CK_FLEXGEN_45,
+ _CK_FLEXGEN_46,
+ _CK_FLEXGEN_47,
+ _CK_FLEXGEN_48,
+ _CK_FLEXGEN_49,
+ _CK_FLEXGEN_50,
+ _CK_FLEXGEN_51,
+ _CK_FLEXGEN_52,
+ _CK_FLEXGEN_53,
+ _CK_FLEXGEN_54,
+ _CK_FLEXGEN_55,
+ _CK_FLEXGEN_56,
+ _CK_FLEXGEN_57,
+ _CK_FLEXGEN_58,
+ _CK_FLEXGEN_59,
+ _CK_FLEXGEN_60,
+ _CK_FLEXGEN_61,
+ _CK_FLEXGEN_62,
+ _CK_FLEXGEN_63,
+ _CK_ICN_APB1,
+ _CK_ICN_APB2,
+ _CK_ICN_APB3,
+ _CK_ICN_APB4,
+ _CK_ICN_APBDBG,
+ _CK_BKPSRAM,
+ _CK_BSEC,
+ _CK_CRC,
+ _CK_CRYP1,
+ _CK_CRYP2,
+ _CK_DDR,
+ _CK_DDRCAPB,
+ _CK_DDRCP,
+ _CK_DDRPHYC,
+ _CK_FMC,
+ _CK_GPIOA,
+ _CK_GPIOB,
+ _CK_GPIOC,
+ _CK_GPIOD,
+ _CK_GPIOE,
+ _CK_GPIOF,
+ _CK_GPIOG,
+ _CK_GPIOH,
+ _CK_GPIOI,
+ _CK_GPIOJ,
+ _CK_GPIOK,
+ _CK_GPIOZ,
+ _CK_HASH,
+ _CK_I2C1,
+ _CK_I2C2,
+ _CK_I2C3,
+ _CK_I2C4,
+ _CK_I2C5,
+ _CK_I2C6,
+ _CK_I2C7,
+ _CK_I2C8,
+ _CK_IWDG1,
+ _CK_IWDG2,
+ _CK_OSPI1,
+ _CK_OSPI2,
+ _CK_OSPIIOM,
+ _CK_PKA,
+ _CK_RETRAM,
+ _CK_RNG,
+ _CK_RTC,
+ _CK_SAES,
+ _CK_SDMMC1,
+ _CK_SDMMC2,
+ _CK_SRAM1,
+ _CK_SRAM2,
+ _CK_STGEN,
+ _CK_SYSCPU1,
+ _CK_SYSRAM,
+ _CK_UART4,
+ _CK_UART5,
+ _CK_UART7,
+ _CK_UART8,
+ _CK_UART9,
+ _CK_USART1,
+ _CK_USART2,
+ _CK_USART3,
+ _CK_USART6,
+ _CK_USB2EHCI,
+ _CK_USB2OHCI,
+ _CK_USB2PHY1,
+ _CK_USB2PHY2,
+ _CK_USB3DR,
+ _CK_USB3PCIEPHY,
+ _CK_USBTC,
+
+ CK_LAST
+};
+
+static const uint16_t muxsel_src[] = {
+ _CK_HSI, _CK_HSE, _CK_MSI, _CK_0_MHZ
+};
+
+static const uint16_t xbarsel_src[] = {
+ _CK_PLL4, _CK_PLL5, _CK_PLL6, _CK_PLL7, _CK_PLL8,
+ _CK_HSI, _CK_HSE, _CK_MSI, _CK_HSI, _CK_HSE, _CK_MSI,
+ _SPDIFSYMB, _I2SCKIN, _CK_LSI, _CK_LSE
+};
+
+static const uint16_t rtc_src[] = {
+ _CK_0_MHZ, _CK_LSE, _CK_LSI, _CK_HSE_RTC
+};
+
+static const uint16_t usb2phy1_src[] = {
+ _CK_FLEXGEN_57, _CK_HSE
+};
+
+static const uint16_t usb2phy2_src[] = {
+ _CK_FLEXGEN_58, _CK_HSE
+};
+
+static const uint16_t usb3pciphy_src[] = {
+ _CK_FLEXGEN_34, _CK_HSE
+};
+
+static const uint16_t d3per_src[] = {
+ _CK_MSI, _CK_LSI, _CK_LSE
+};
+
+#define MUX_CONF(id, src, _offset, _shift, _witdh)[id] = {\
+ .id_parents = src,\
+ .num_parents = ARRAY_SIZE(src),\
+ .mux = &(struct mux_cfg) {\
+ .offset = (_offset),\
+ .shift = (_shift),\
+ .width = (_witdh),\
+ .bitrdy = UINT8_MAX,\
+ },\
+}
+
+static const struct parent_cfg parent_mp25[] = {
+ MUX_CONF(MUX_MUXSEL0, muxsel_src, RCC_MUXSELCFGR, 0, 2),
+ MUX_CONF(MUX_MUXSEL1, muxsel_src, RCC_MUXSELCFGR, 4, 2),
+ MUX_CONF(MUX_MUXSEL2, muxsel_src, RCC_MUXSELCFGR, 8, 2),
+ MUX_CONF(MUX_MUXSEL3, muxsel_src, RCC_MUXSELCFGR, 12, 2),
+ MUX_CONF(MUX_MUXSEL4, muxsel_src, RCC_MUXSELCFGR, 16, 2),
+ MUX_CONF(MUX_MUXSEL5, muxsel_src, RCC_MUXSELCFGR, 20, 2),
+ MUX_CONF(MUX_MUXSEL6, muxsel_src, RCC_MUXSELCFGR, 24, 2),
+ MUX_CONF(MUX_MUXSEL7, muxsel_src, RCC_MUXSELCFGR, 28, 2),
+ MUX_CONF(MUX_XBARSEL, xbarsel_src, RCC_XBAR0CFGR, 0, 4),
+ MUX_CONF(MUX_RTC, rtc_src, RCC_BDCR, 16, 2),
+ MUX_CONF(MUX_USB2PHY1, usb2phy1_src, RCC_USB2PHY1CFGR, 15, 1),
+ MUX_CONF(MUX_USB2PHY2, usb2phy2_src, RCC_USB2PHY2CFGR, 15, 1),
+ MUX_CONF(MUX_USB3PCIEPHY, usb3pciphy_src, RCC_USB3PCIEPHYCFGR, 15, 1),
+ MUX_CONF(MUX_D3PER, d3per_src, RCC_D3DCR, 16, 2),
+};
+
+/* GATES */
+enum enum_gate_cfg {
+ GATE_ZERO, /* reserved for no gate */
+ GATE_LSE,
+ GATE_RTCCK,
+ GATE_LSI,
+ GATE_HSI,
+ GATE_MSI,
+ GATE_HSE,
+ GATE_LSI_RDY,
+ GATE_MSI_RDY,
+ GATE_LSE_RDY,
+ GATE_HSE_RDY,
+ GATE_HSI_RDY,
+ GATE_SYSRAM,
+ GATE_RETRAM,
+ GATE_SRAM1,
+ GATE_SRAM2,
+
+ GATE_DDRPHYC,
+ GATE_SYSCPU1,
+ GATE_CRC,
+ GATE_OSPIIOM,
+ GATE_BKPSRAM,
+ GATE_HASH,
+ GATE_RNG,
+ GATE_CRYP1,
+ GATE_CRYP2,
+ GATE_SAES,
+ GATE_PKA,
+
+ GATE_GPIOA,
+ GATE_GPIOB,
+ GATE_GPIOC,
+ GATE_GPIOD,
+ GATE_GPIOE,
+ GATE_GPIOF,
+ GATE_GPIOG,
+ GATE_GPIOH,
+ GATE_GPIOI,
+ GATE_GPIOJ,
+ GATE_GPIOK,
+ GATE_GPIOZ,
+ GATE_RTC,
+
+ GATE_DDRCP,
+
+ /* WARNING 2 CLOCKS FOR ONE GATE */
+ GATE_USB2OHCI,
+ GATE_USB2EHCI,
+
+ GATE_USB3DR,
+
+ GATE_BSEC,
+ GATE_IWDG1,
+ GATE_IWDG2,
+
+ GATE_DDRCAPB,
+ GATE_DDR,
+
+ GATE_USART2,
+ GATE_UART4,
+ GATE_USART3,
+ GATE_UART5,
+ GATE_I2C1,
+ GATE_I2C2,
+ GATE_I2C3,
+ GATE_I2C5,
+ GATE_I2C4,
+ GATE_I2C6,
+ GATE_I2C7,
+ GATE_USART1,
+ GATE_USART6,
+ GATE_UART7,
+ GATE_UART8,
+ GATE_UART9,
+ GATE_STGEN,
+ GATE_USB3PCIEPHY,
+ GATE_USBTC,
+ GATE_I2C8,
+ GATE_OSPI1,
+ GATE_OSPI2,
+ GATE_FMC,
+ GATE_SDMMC1,
+ GATE_SDMMC2,
+ GATE_USB2PHY1,
+ GATE_USB2PHY2,
+ LAST_GATE
+};
+
+#define GATE_CFG(id, _offset, _bit_idx, _offset_clr)[id] = {\
+ .offset = (_offset),\
+ .bit_idx = (_bit_idx),\
+ .set_clr = (_offset_clr),\
+}
+
+static const struct gate_cfg gates_mp25[LAST_GATE] = {
+ GATE_CFG(GATE_LSE, RCC_BDCR, 0, 0),
+ GATE_CFG(GATE_LSI, RCC_BDCR, 9, 0),
+ GATE_CFG(GATE_RTCCK, RCC_BDCR, 20, 0),
+ GATE_CFG(GATE_HSI, RCC_OCENSETR, 0, 1),
+ GATE_CFG(GATE_HSE, RCC_OCENSETR, 8, 1),
+ GATE_CFG(GATE_MSI, RCC_D3DCR, 0, 0),
+
+ GATE_CFG(GATE_LSI_RDY, RCC_BDCR, 10, 0),
+ GATE_CFG(GATE_LSE_RDY, RCC_BDCR, 2, 0),
+ GATE_CFG(GATE_MSI_RDY, RCC_D3DCR, 2, 0),
+ GATE_CFG(GATE_HSE_RDY, RCC_OCRDYR, 8, 0),
+ GATE_CFG(GATE_HSI_RDY, RCC_OCRDYR, 0, 0),
+ GATE_CFG(GATE_SYSRAM, RCC_SYSRAMCFGR, 1, 0),
+ GATE_CFG(GATE_RETRAM, RCC_RETRAMCFGR, 1, 0),
+ GATE_CFG(GATE_SRAM1, RCC_SRAM1CFGR, 1, 0),
+ GATE_CFG(GATE_SRAM2, RCC_SRAM2CFGR, 1, 0),
+ GATE_CFG(GATE_DDRPHYC, RCC_DDRPHYCAPBCFGR, 1, 0),
+ GATE_CFG(GATE_SYSCPU1, RCC_SYSCPU1CFGR, 1, 0),
+ GATE_CFG(GATE_CRC, RCC_CRCCFGR, 1, 0),
+ GATE_CFG(GATE_OSPIIOM, RCC_OSPIIOMCFGR, 1, 0),
+ GATE_CFG(GATE_BKPSRAM, RCC_BKPSRAMCFGR, 1, 0),
+ GATE_CFG(GATE_HASH, RCC_HASHCFGR, 1, 0),
+ GATE_CFG(GATE_RNG, RCC_RNGCFGR, 1, 0),
+ GATE_CFG(GATE_CRYP1, RCC_CRYP1CFGR, 1, 0),
+ GATE_CFG(GATE_CRYP2, RCC_CRYP2CFGR, 1, 0),
+ GATE_CFG(GATE_SAES, RCC_SAESCFGR, 1, 0),
+ GATE_CFG(GATE_PKA, RCC_PKACFGR, 1, 0),
+ GATE_CFG(GATE_GPIOA, RCC_GPIOACFGR, 1, 0),
+ GATE_CFG(GATE_GPIOB, RCC_GPIOBCFGR, 1, 0),
+ GATE_CFG(GATE_GPIOC, RCC_GPIOCCFGR, 1, 0),
+ GATE_CFG(GATE_GPIOD, RCC_GPIODCFGR, 1, 0),
+ GATE_CFG(GATE_GPIOE, RCC_GPIOECFGR, 1, 0),
+ GATE_CFG(GATE_GPIOF, RCC_GPIOFCFGR, 1, 0),
+ GATE_CFG(GATE_GPIOG, RCC_GPIOGCFGR, 1, 0),
+ GATE_CFG(GATE_GPIOH, RCC_GPIOHCFGR, 1, 0),
+ GATE_CFG(GATE_GPIOI, RCC_GPIOICFGR, 1, 0),
+ GATE_CFG(GATE_GPIOJ, RCC_GPIOJCFGR, 1, 0),
+ GATE_CFG(GATE_GPIOK, RCC_GPIOKCFGR, 1, 0),
+ GATE_CFG(GATE_GPIOZ, RCC_GPIOZCFGR, 1, 0),
+ GATE_CFG(GATE_RTC, RCC_RTCCFGR, 1, 0),
+ GATE_CFG(GATE_DDRCP, RCC_DDRCPCFGR, 1, 0),
+
+ /* WARNING 2 CLOCKS FOR ONE GATE */
+ GATE_CFG(GATE_USB2OHCI, RCC_USB2CFGR, 1, 0),
+ GATE_CFG(GATE_USB2EHCI, RCC_USB2CFGR, 1, 0),
+ GATE_CFG(GATE_USB3DR, RCC_USB3DRCFGR, 1, 0),
+ GATE_CFG(GATE_BSEC, RCC_BSECCFGR, 1, 0),
+ GATE_CFG(GATE_IWDG1, RCC_IWDG1CFGR, 1, 0),
+ GATE_CFG(GATE_IWDG2, RCC_IWDG2CFGR, 1, 0),
+ GATE_CFG(GATE_DDRCAPB, RCC_DDRCAPBCFGR, 1, 0),
+ GATE_CFG(GATE_DDR, RCC_DDRCFGR, 1, 0),
+ GATE_CFG(GATE_USART2, RCC_USART2CFGR, 1, 0),
+ GATE_CFG(GATE_UART4, RCC_UART4CFGR, 1, 0),
+ GATE_CFG(GATE_USART3, RCC_USART3CFGR, 1, 0),
+ GATE_CFG(GATE_UART5, RCC_UART5CFGR, 1, 0),
+ GATE_CFG(GATE_I2C1, RCC_I2C1CFGR, 1, 0),
+ GATE_CFG(GATE_I2C2, RCC_I2C2CFGR, 1, 0),
+ GATE_CFG(GATE_I2C3, RCC_I2C3CFGR, 1, 0),
+ GATE_CFG(GATE_I2C5, RCC_I2C5CFGR, 1, 0),
+ GATE_CFG(GATE_I2C4, RCC_I2C4CFGR, 1, 0),
+ GATE_CFG(GATE_I2C6, RCC_I2C6CFGR, 1, 0),
+ GATE_CFG(GATE_I2C7, RCC_I2C7CFGR, 1, 0),
+ GATE_CFG(GATE_USART1, RCC_USART1CFGR, 1, 0),
+ GATE_CFG(GATE_USART6, RCC_USART6CFGR, 1, 0),
+ GATE_CFG(GATE_UART7, RCC_UART7CFGR, 1, 0),
+ GATE_CFG(GATE_UART8, RCC_UART8CFGR, 1, 0),
+ GATE_CFG(GATE_UART9, RCC_UART9CFGR, 1, 0),
+ GATE_CFG(GATE_STGEN, RCC_STGENCFGR, 1, 0),
+ GATE_CFG(GATE_USB3PCIEPHY, RCC_USB3PCIEPHYCFGR, 1, 0),
+ GATE_CFG(GATE_USBTC, RCC_USBTCCFGR, 1, 0),
+ GATE_CFG(GATE_I2C8, RCC_I2C8CFGR, 1, 0),
+ GATE_CFG(GATE_OSPI1, RCC_OSPI1CFGR, 1, 0),
+ GATE_CFG(GATE_OSPI2, RCC_OSPI2CFGR, 1, 0),
+ GATE_CFG(GATE_FMC, RCC_FMCCFGR, 1, 0),
+ GATE_CFG(GATE_SDMMC1, RCC_SDMMC1CFGR, 1, 0),
+ GATE_CFG(GATE_SDMMC2, RCC_SDMMC2CFGR, 1, 0),
+ GATE_CFG(GATE_USB2PHY1, RCC_USB2PHY1CFGR, 1, 0),
+ GATE_CFG(GATE_USB2PHY2, RCC_USB2PHY2CFGR, 1, 0),
+};
+
+static const struct clk_div_table apb_div_table[] = {
+ { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 }, { 4, 16 },
+ { 5, 16 }, { 6, 16 }, { 7, 16 }, { 0 },
+};
+
+#undef DIV_CFG
+#define DIV_CFG(id, _offset, _shift, _width, _flags, _table, _bitrdy)[id] = {\
+ .offset = _offset,\
+ .shift = _shift,\
+ .width = _width,\
+ .flags = _flags,\
+ .table = _table,\
+ .bitrdy = _bitrdy,\
+}
+
+static const struct div_cfg dividers_mp25[] = {
+ DIV_CFG(DIV_APB1, RCC_APB1DIVR, 0, 3, 0, apb_div_table, 31),
+ DIV_CFG(DIV_APB2, RCC_APB2DIVR, 0, 3, 0, apb_div_table, 31),
+ DIV_CFG(DIV_APB3, RCC_APB3DIVR, 0, 3, 0, apb_div_table, 31),
+ DIV_CFG(DIV_APB4, RCC_APB4DIVR, 0, 3, 0, apb_div_table, 31),
+ DIV_CFG(DIV_APBDBG, RCC_APBDBGDIVR, 0, 3, 0, apb_div_table, 31),
+ DIV_CFG(DIV_LSMCU, RCC_LSMCUDIVR, 0, 1, 0, NULL, 31),
+ DIV_CFG(DIV_RTC, RCC_RTCDIVR, 0, 6, 0, NULL, 0),
+};
+
+enum stm32_osc {
+ OSC_HSI,
+ OSC_HSE,
+ OSC_MSI,
+ OSC_LSI,
+ OSC_LSE,
+ OSC_I2SCKIN,
+ OSC_SPDIFSYMB,
+ NB_OSCILLATOR
+};
+
+static struct clk_oscillator_data stm32mp25_osc_data[] = {
+ OSCILLATOR(OSC_HSI, _CK_HSI, "clk-hsi", GATE_HSI, GATE_HSI_RDY,
+ NULL, NULL, NULL),
+
+ OSCILLATOR(OSC_LSI, _CK_LSI, "clk-lsi", GATE_LSI, GATE_LSI_RDY,
+ NULL, NULL, NULL),
+
+ OSCILLATOR(OSC_MSI, _CK_MSI, "clk-msi", GATE_MSI, GATE_MSI_RDY,
+ NULL, NULL, NULL),
+
+ OSCILLATOR(OSC_HSE, _CK_HSE, "clk-hse", GATE_HSE, GATE_HSE_RDY,
+ BYPASS(RCC_OCENSETR, 10, 7),
+ CSS(RCC_OCENSETR, 11),
+ NULL),
+
+ OSCILLATOR(OSC_LSE, _CK_LSE, "clk-lse", GATE_LSE, GATE_LSE_RDY,
+ BYPASS(RCC_BDCR, 1, 3),
+ CSS(RCC_BDCR, 8),
+ DRIVE(RCC_BDCR, 4, 2, 2)),
+
+ OSCILLATOR(OSC_I2SCKIN, _I2SCKIN, "i2s_ckin", NO_GATE, NO_GATE,
+ NULL, NULL, NULL),
+
+ OSCILLATOR(OSC_SPDIFSYMB, _SPDIFSYMB, "spdif_symb", NO_GATE, NO_GATE,
+ NULL, NULL, NULL),
+};
+
+#ifdef IMAGE_BL2
+static const char *clk_stm32_get_oscillator_name(enum stm32_osc id)
+{
+ if (id < NB_OSCILLATOR) {
+ return stm32mp25_osc_data[id].name;
+ }
+
+ return NULL;
+}
+#endif
+
+enum pll_id {
+ _PLL1,
+ _PLL2,
+ _PLL3,
+ _PLL4,
+ _PLL5,
+ _PLL6,
+ _PLL7,
+ _PLL8,
+ _PLL_NB
+};
+
+/* PLL configuration registers offsets from RCC_PLLxCFGR1 */
+#define RCC_OFFSET_PLLXCFGR1 0x00
+#define RCC_OFFSET_PLLXCFGR2 0x04
+#define RCC_OFFSET_PLLXCFGR3 0x08
+#define RCC_OFFSET_PLLXCFGR4 0x0C
+#define RCC_OFFSET_PLLXCFGR5 0x10
+#define RCC_OFFSET_PLLXCFGR6 0x18
+#define RCC_OFFSET_PLLXCFGR7 0x1C
+
+struct stm32_clk_pll {
+ uint16_t clk_id;
+ uint16_t reg_pllxcfgr1;
+};
+
+#define CLK_PLL_CFG(_idx, _clk_id, _reg)\
+ [(_idx)] = {\
+ .clk_id = (_clk_id),\
+ .reg_pllxcfgr1 = (_reg),\
+ }
+
+static const struct stm32_clk_pll stm32mp25_clk_pll[_PLL_NB] = {
+ CLK_PLL_CFG(_PLL1, _CK_PLL1, A35_SS_CHGCLKREQ),
+ CLK_PLL_CFG(_PLL2, _CK_PLL2, RCC_PLL2CFGR1),
+ CLK_PLL_CFG(_PLL3, _CK_PLL3, RCC_PLL3CFGR1),
+ CLK_PLL_CFG(_PLL4, _CK_PLL4, RCC_PLL4CFGR1),
+ CLK_PLL_CFG(_PLL5, _CK_PLL5, RCC_PLL5CFGR1),
+ CLK_PLL_CFG(_PLL6, _CK_PLL6, RCC_PLL6CFGR1),
+ CLK_PLL_CFG(_PLL7, _CK_PLL7, RCC_PLL7CFGR1),
+ CLK_PLL_CFG(_PLL8, _CK_PLL8, RCC_PLL8CFGR1),
+};
+
+static const struct stm32_clk_pll *clk_stm32_pll_data(unsigned int idx)
+{
+ return &stm32mp25_clk_pll[idx];
+}
+
+static unsigned long clk_get_pll_fvco(struct stm32_clk_priv *priv,
+ const struct stm32_clk_pll *pll,
+ unsigned long prate)
+{
+ unsigned long refclk, fvco;
+ uint32_t fracin, fbdiv, refdiv;
+ uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
+ uintptr_t pllxcfgr2 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR2;
+ uintptr_t pllxcfgr3 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR3;
+
+ refclk = prate;
+
+ fracin = mmio_read_32(pllxcfgr3) & RCC_PLLxCFGR3_FRACIN_MASK;
+ fbdiv = (mmio_read_32(pllxcfgr2) & RCC_PLLxCFGR2_FBDIV_MASK) >>
+ RCC_PLLxCFGR2_FBDIV_SHIFT;
+ refdiv = mmio_read_32(pllxcfgr2) & RCC_PLLxCFGR2_FREFDIV_MASK;
+
+ if (fracin != 0U) {
+ uint64_t numerator, denominator;
+
+ numerator = ((uint64_t)fbdiv << 24) + fracin;
+ numerator = refclk * numerator;
+ denominator = (uint64_t)refdiv << 24;
+ fvco = (unsigned long)(numerator / denominator);
+ } else {
+ fvco = (unsigned long)(refclk * fbdiv / refdiv);
+ }
+
+ return fvco;
+}
+
+struct stm32_pll_cfg {
+ uint16_t pll_id;
+};
+
+static bool _clk_stm32_pll_is_enabled(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll)
+{
+ uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
+
+ return ((mmio_read_32(pllxcfgr1) & RCC_PLLxCFGR1_PLLEN) != 0U);
+}
+
+static void _clk_stm32_pll_set_on(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll)
+{
+ uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
+
+ mmio_setbits_32(pllxcfgr1, RCC_PLLxCFGR1_PLLEN);
+}
+
+static void _clk_stm32_pll_set_off(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll)
+{
+ uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
+
+ /* Stop PLL */
+ mmio_clrbits_32(pllxcfgr1, RCC_PLLxCFGR1_PLLEN);
+}
+
+static int _clk_stm32_pll_wait_ready_on(struct stm32_clk_priv *priv,
+ const struct stm32_clk_pll *pll)
+{
+ uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
+ uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT);
+
+ /* Wait PLL lock */
+ while ((mmio_read_32(pllxcfgr1) & RCC_PLLxCFGR1_PLLRDY) == 0U) {
+ if (timeout_elapsed(timeout)) {
+ ERROR("PLL%d start failed @ 0x%x: 0x%x\n",
+ pll->clk_id - _CK_PLL1 + 1, pll->reg_pllxcfgr1,
+ mmio_read_32(pllxcfgr1));
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
+static int _clk_stm32_pll_wait_ready_off(struct stm32_clk_priv *priv,
+ const struct stm32_clk_pll *pll)
+{
+ uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
+ uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT);
+
+ /* Wait PLL stopped */
+ while ((mmio_read_32(pllxcfgr1) & RCC_PLLxCFGR1_PLLRDY) != 0U) {
+ if (timeout_elapsed(timeout)) {
+ ERROR("PLL%d stop failed @ 0x%lx: 0x%x\n",
+ pll->clk_id - _CK_PLL1 + 1, pllxcfgr1, mmio_read_32(pllxcfgr1));
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
+static int _clk_stm32_pll_enable(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll)
+{
+ if (_clk_stm32_pll_is_enabled(priv, pll)) {
+ return 0;
+ }
+
+ _clk_stm32_pll_set_on(priv, pll);
+
+ return _clk_stm32_pll_wait_ready_on(priv, pll);
+}
+
+static void _clk_stm32_pll_disable(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll)
+{
+ if (!_clk_stm32_pll_is_enabled(priv, pll)) {
+ return;
+ }
+
+ _clk_stm32_pll_set_off(priv, pll);
+
+ _clk_stm32_pll_wait_ready_off(priv, pll);
+}
+
+static bool clk_stm32_pll_is_enabled(struct stm32_clk_priv *priv, int id)
+{
+ const struct clk_stm32 *clk = _clk_get(priv, id);
+ struct stm32_pll_cfg *pll_cfg = clk->clock_cfg;
+ const struct stm32_clk_pll *pll = clk_stm32_pll_data(pll_cfg->pll_id);
+
+ return _clk_stm32_pll_is_enabled(priv, pll);
+}
+
+static int clk_stm32_pll_enable(struct stm32_clk_priv *priv, int id)
+{
+ const struct clk_stm32 *clk = _clk_get(priv, id);
+ struct stm32_pll_cfg *pll_cfg = clk->clock_cfg;
+ const struct stm32_clk_pll *pll = clk_stm32_pll_data(pll_cfg->pll_id);
+
+ return _clk_stm32_pll_enable(priv, pll);
+}
+
+static void clk_stm32_pll_disable(struct stm32_clk_priv *priv, int id)
+{
+ const struct clk_stm32 *clk = _clk_get(priv, id);
+ struct stm32_pll_cfg *pll_cfg = clk->clock_cfg;
+ const struct stm32_clk_pll *pll = clk_stm32_pll_data(pll_cfg->pll_id);
+
+ _clk_stm32_pll_disable(priv, pll);
+}
+
+static unsigned long clk_stm32_pll_recalc_rate(struct stm32_clk_priv *priv, int id,
+ unsigned long prate)
+{
+ const struct clk_stm32 *clk = _clk_get(priv, id);
+ struct stm32_pll_cfg *pll_cfg = clk->clock_cfg;
+ const struct stm32_clk_pll *pll = clk_stm32_pll_data(pll_cfg->pll_id);
+ uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
+ uintptr_t pllxcfgr4 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR4;
+ uintptr_t pllxcfgr6 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR6;
+ uintptr_t pllxcfgr7 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR7;
+ unsigned long dfout;
+ uint32_t postdiv1, postdiv2;
+
+ postdiv1 = mmio_read_32(pllxcfgr6) & RCC_PLLxCFGR6_POSTDIV1_MASK;
+ postdiv2 = mmio_read_32(pllxcfgr7) & RCC_PLLxCFGR7_POSTDIV2_MASK;
+
+ if ((mmio_read_32(pllxcfgr4) & RCC_PLLxCFGR4_BYPASS) != 0U) {
+ dfout = prate;
+ } else {
+ if ((postdiv1 == 0U) || (postdiv2 == 0U)) {
+ dfout = prate;
+ } else {
+ dfout = clk_get_pll_fvco(priv, pll, prate) / (postdiv1 * postdiv2);
+ }
+ }
+
+ return dfout;
+}
+
+static const struct stm32_clk_ops clk_stm32_pll_ops = {
+ .recalc_rate = clk_stm32_pll_recalc_rate,
+ .enable = clk_stm32_pll_enable,
+ .disable = clk_stm32_pll_disable,
+ .is_enabled = clk_stm32_pll_is_enabled,
+};
+
+#define CLK_PLL(idx, _idx, _parent, _pll_id, _flags)[idx] = {\
+ .binding = _idx,\
+ .parent = _parent,\
+ .flags = (_flags),\
+ .clock_cfg = &(struct stm32_pll_cfg) {\
+ .pll_id = _pll_id,\
+ },\
+ .ops = STM32_PLL_OPS,\
+}
+
+static unsigned long clk_get_pll1_fvco(unsigned long refclk)
+{
+ uintptr_t pll_freq1_reg = A35SSC_BASE + A35_SS_PLL_FREQ1;
+ uint32_t reg, fbdiv, refdiv;
+
+ reg = mmio_read_32(pll_freq1_reg);
+
+ fbdiv = (reg & A35_SS_PLL_FREQ1_FBDIV_MASK) >> A35_SS_PLL_FREQ1_FBDIV_SHIFT;
+ refdiv = (reg & A35_SS_PLL_FREQ1_REFDIV_MASK) >> A35_SS_PLL_FREQ1_REFDIV_SHIFT;
+
+ return (unsigned long)(refclk * fbdiv / refdiv);
+}
+
+static unsigned long clk_stm32_pll1_recalc_rate(struct stm32_clk_priv *priv,
+ int id, unsigned long prate)
+{
+ uintptr_t pll_freq2_reg = A35SSC_BASE + A35_SS_PLL_FREQ2;
+ uint32_t postdiv1, postdiv2;
+ unsigned long dfout;
+
+ postdiv1 = (mmio_read_32(pll_freq2_reg) & A35_SS_PLL_FREQ2_POSTDIV1_MASK) >>
+ A35_SS_PLL_FREQ2_POSTDIV1_SHIFT;
+ postdiv2 = (mmio_read_32(pll_freq2_reg) & A35_SS_PLL_FREQ2_POSTDIV2_MASK) >>
+ A35_SS_PLL_FREQ2_POSTDIV2_SHIFT;
+
+ if ((postdiv1 == 0U) || (postdiv2 == 0U)) {
+ dfout = prate;
+ } else {
+ dfout = clk_get_pll1_fvco(prate) / (postdiv1 * postdiv2);
+ }
+
+ return dfout;
+}
+
+static const struct stm32_clk_ops clk_stm32_pll1_ops = {
+ .recalc_rate = clk_stm32_pll1_recalc_rate,
+};
+
+#define CLK_PLL1(idx, _idx, _parent, _pll_id, _flags)[idx] = {\
+ .binding = _idx,\
+ .parent = _parent,\
+ .flags = (_flags),\
+ .clock_cfg = &(struct stm32_pll_cfg) {\
+ .pll_id = _pll_id,\
+ },\
+ .ops = STM32_PLL1_OPS,\
+}
+
+struct stm32_clk_flexgen_cfg {
+ uint8_t id;
+};
+
+static unsigned long clk_flexgen_recalc(struct stm32_clk_priv *priv, int idx,
+ unsigned long prate)
+{
+ const struct clk_stm32 *clk = _clk_get(priv, idx);
+ struct stm32_clk_flexgen_cfg *cfg = clk->clock_cfg;
+ uintptr_t rcc_base = priv->base;
+ uint32_t prediv, findiv;
+ uint8_t channel = cfg->id;
+ unsigned long freq = prate;
+
+ prediv = mmio_read_32(rcc_base + RCC_PREDIV0CFGR + (0x4U * channel)) &
+ RCC_PREDIVxCFGR_PREDIVx_MASK;
+ findiv = mmio_read_32(rcc_base + RCC_FINDIV0CFGR + (0x4U * channel)) &
+ RCC_FINDIVxCFGR_FINDIVx_MASK;
+
+ if (freq == 0UL) {
+ return 0U;
+ }
+
+ switch (prediv) {
+ case 0x0:
+ case 0x1:
+ case 0x3:
+ case 0x3FF:
+ break;
+
+ default:
+ ERROR("Unsupported PREDIV value (%x)\n", prediv);
+ panic();
+ break;
+ }
+
+ freq /= (prediv + 1U);
+ freq /= (findiv + 1U);
+
+ return freq;
+}
+
+static int clk_flexgen_get_parent(struct stm32_clk_priv *priv, int idx)
+{
+ const struct clk_stm32 *clk = _clk_get(priv, idx);
+ struct stm32_clk_flexgen_cfg *cfg = clk->clock_cfg;
+ uint32_t sel;
+ uint32_t address;
+ uintptr_t rcc_base = priv->base;
+
+ address = RCC_XBAR0CFGR + (cfg->id * 4);
+
+ sel = mmio_read_32(rcc_base + address) & RCC_XBARxCFGR_XBARxSEL_MASK;
+
+ return sel;
+}
+
+static int clk_flexgen_gate_enable(struct stm32_clk_priv *priv, int idx)
+{
+ const struct clk_stm32 *clk = _clk_get(priv, idx);
+ struct stm32_clk_flexgen_cfg *cfg = clk->clock_cfg;
+ uintptr_t rcc_base = priv->base;
+ uint8_t channel = cfg->id;
+
+ mmio_setbits_32(rcc_base + RCC_FINDIV0CFGR + (0x4U * channel),
+ RCC_FINDIVxCFGR_FINDIVxEN);
+
+ return 0;
+}
+
+static void clk_flexgen_gate_disable(struct stm32_clk_priv *priv, int id)
+{
+ const struct clk_stm32 *clk = _clk_get(priv, id);
+ struct stm32_clk_flexgen_cfg *cfg = clk->clock_cfg;
+ uintptr_t rcc_base = priv->base;
+ uint8_t channel = cfg->id;
+
+ mmio_clrbits_32(rcc_base + RCC_FINDIV0CFGR + (0x4U * channel),
+ RCC_FINDIVxCFGR_FINDIVxEN);
+}
+
+static bool clk_flexgen_gate_is_enabled(struct stm32_clk_priv *priv, int id)
+{
+ const struct clk_stm32 *clk = _clk_get(priv, id);
+ struct stm32_clk_flexgen_cfg *cfg = clk->clock_cfg;
+ uintptr_t rcc_base = priv->base;
+ uint8_t channel = cfg->id;
+
+ return !!(mmio_read_32(rcc_base + RCC_FINDIV0CFGR + (0x4U * channel)) &
+ RCC_FINDIVxCFGR_FINDIVxEN);
+}
+
+static const struct stm32_clk_ops clk_stm32_flexgen_ops = {
+ .recalc_rate = clk_flexgen_recalc,
+ .get_parent = clk_flexgen_get_parent,
+ .enable = clk_flexgen_gate_enable,
+ .disable = clk_flexgen_gate_disable,
+ .is_enabled = clk_flexgen_gate_is_enabled,
+};
+
+#define FLEXGEN(idx, _idx, _flags, _id)[idx] = {\
+ .binding = _idx,\
+ .parent = MUX(MUX_XBARSEL),\
+ .flags = (_flags),\
+ .clock_cfg = &(struct stm32_clk_flexgen_cfg) {\
+ .id = _id,\
+ },\
+ .ops = STM32_FLEXGEN_OPS,\
+}
+
+#define RCC_0_MHZ UL(0)
+#define RCC_4_MHZ UL(4000000)
+#define RCC_16_MHZ UL(16000000)
+
+#ifdef IMAGE_BL2
+static int clk_stm32_osc_msi_set_rate(struct stm32_clk_priv *priv, int id, unsigned long rate,
+ unsigned long prate)
+{
+ uintptr_t address = priv->base + RCC_BDCR;
+ uint32_t mask = RCC_BDCR_MSIFREQSEL;
+ int ret = -1;
+
+ switch (rate) {
+ case RCC_4_MHZ:
+ mmio_clrbits_32(address, mask);
+ ret = 0;
+ break;
+
+ case RCC_16_MHZ:
+ mmio_setbits_32(address, mask);
+ ret = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+#endif /* IMAGE_BL2 */
+
+static unsigned long clk_stm32_osc_msi_recalc_rate(struct stm32_clk_priv *priv,
+ int id __unused,
+ unsigned long prate __unused)
+{
+ uintptr_t address = priv->base + RCC_BDCR;
+
+ if ((mmio_read_32(address) & RCC_BDCR_MSIFREQSEL) == 0U) {
+ return RCC_4_MHZ;
+ } else {
+ return RCC_16_MHZ;
+ }
+}
+
+static const struct stm32_clk_ops clk_stm32_osc_msi_ops = {
+ .recalc_rate = clk_stm32_osc_msi_recalc_rate,
+ .is_enabled = clk_stm32_osc_gate_is_enabled,
+ .enable = clk_stm32_osc_gate_enable,
+ .disable = clk_stm32_osc_gate_disable,
+ .init = clk_stm32_osc_init,
+};
+
+#define CLK_OSC_MSI(idx, _idx, _parent, _osc_id) \
+ [(idx)] = (struct clk_stm32){ \
+ .binding = (_idx),\
+ .parent = (_parent),\
+ .flags = CLK_IS_CRITICAL,\
+ .clock_cfg = &(struct stm32_osc_cfg){\
+ .osc_id = (_osc_id),\
+ },\
+ .ops = STM32_OSC_MSI_OPS,\
+ }
+
+static const struct stm32_clk_ops clk_stm32_rtc_ops = {
+ .enable = clk_stm32_gate_enable,
+ .disable = clk_stm32_gate_disable,
+ .is_enabled = clk_stm32_gate_is_enabled,
+};
+
+#define CLK_RTC(idx, _binding, _parent, _flags, _gate_id)[idx] = {\
+ .binding = (_binding),\
+ .parent = (_parent),\
+ .flags = (_flags),\
+ .clock_cfg = &(struct clk_stm32_gate_cfg) {\
+ .id = (_gate_id),\
+ },\
+ .ops = STM32_RTC_OPS,\
+}
+
+enum {
+ STM32_PLL_OPS = STM32_LAST_OPS,
+ STM32_PLL1_OPS,
+ STM32_FLEXGEN_OPS,
+ STM32_OSC_MSI_OPS,
+ STM32_RTC_OPS,
+
+ MP25_LAST_OPS
+};
+
+static const struct stm32_clk_ops *ops_array_mp25[MP25_LAST_OPS] = {
+ [NO_OPS] = NULL,
+ [FIXED_FACTOR_OPS] = &clk_fixed_factor_ops,
+ [GATE_OPS] = &clk_gate_ops,
+ [STM32_MUX_OPS] = &clk_mux_ops,
+ [STM32_DIVIDER_OPS] = &clk_stm32_divider_ops,
+ [STM32_GATE_OPS] = &clk_stm32_gate_ops,
+ [STM32_TIMER_OPS] = &clk_timer_ops,
+ [STM32_FIXED_RATE_OPS] = &clk_stm32_fixed_rate_ops,
+ [STM32_OSC_OPS] = &clk_stm32_osc_ops,
+ [STM32_OSC_NOGATE_OPS] = &clk_stm32_osc_nogate_ops,
+
+ [STM32_PLL_OPS] = &clk_stm32_pll_ops,
+ [STM32_PLL1_OPS] = &clk_stm32_pll1_ops,
+ [STM32_FLEXGEN_OPS] = &clk_stm32_flexgen_ops,
+ [STM32_OSC_MSI_OPS] = &clk_stm32_osc_msi_ops,
+ [STM32_RTC_OPS] = &clk_stm32_rtc_ops
+};
+
+static const struct clk_stm32 stm32mp25_clk[CK_LAST] = {
+ CLK_FIXED_RATE(_CK_0_MHZ, _NO_ID, RCC_0_MHZ),
+
+ /* ROOT CLOCKS */
+ CLK_OSC(_CK_HSE, HSE_CK, CLK_IS_ROOT, OSC_HSE),
+ CLK_OSC(_CK_LSE, LSE_CK, CLK_IS_ROOT, OSC_LSE),
+ CLK_OSC(_CK_HSI, HSI_CK, CLK_IS_ROOT, OSC_HSI),
+ CLK_OSC(_CK_LSI, LSI_CK, CLK_IS_ROOT, OSC_LSI),
+ CLK_OSC_MSI(_CK_MSI, MSI_CK, CLK_IS_ROOT, OSC_MSI),
+
+ CLK_OSC_FIXED(_I2SCKIN, _NO_ID, CLK_IS_ROOT, OSC_I2SCKIN),
+ CLK_OSC_FIXED(_SPDIFSYMB, _NO_ID, CLK_IS_ROOT, OSC_SPDIFSYMB),
+
+ STM32_DIV(_CK_HSE_RTC, _NO_ID, _CK_HSE, 0, DIV_RTC),
+
+ CLK_RTC(_CK_RTCCK, RTC_CK, MUX(MUX_RTC), 0, GATE_RTCCK),
+
+ CLK_PLL1(_CK_PLL1, PLL1_CK, MUX(MUX_MUXSEL5), _PLL1, 0),
+
+ CLK_PLL(_CK_PLL2, PLL2_CK, MUX(MUX_MUXSEL6), _PLL2, 0),
+ CLK_PLL(_CK_PLL3, PLL3_CK, MUX(MUX_MUXSEL7), _PLL3, 0),
+ CLK_PLL(_CK_PLL4, PLL4_CK, MUX(MUX_MUXSEL0), _PLL4, 0),
+ CLK_PLL(_CK_PLL5, PLL5_CK, MUX(MUX_MUXSEL1), _PLL5, 0),
+ CLK_PLL(_CK_PLL6, PLL6_CK, MUX(MUX_MUXSEL2), _PLL6, 0),
+ CLK_PLL(_CK_PLL7, PLL7_CK, MUX(MUX_MUXSEL3), _PLL7, 0),
+ CLK_PLL(_CK_PLL8, PLL8_CK, MUX(MUX_MUXSEL4), _PLL8, 0),
+
+ FLEXGEN(_CK_ICN_HS_MCU, CK_ICN_HS_MCU, CLK_IS_CRITICAL, 0),
+ FLEXGEN(_CK_ICN_SDMMC, CK_ICN_SDMMC, CLK_IS_CRITICAL, 1),
+ FLEXGEN(_CK_ICN_DDR, CK_ICN_DDR, CLK_IS_CRITICAL, 2),
+ FLEXGEN(_CK_ICN_HSL, CK_ICN_HSL, CLK_IS_CRITICAL, 4),
+ FLEXGEN(_CK_ICN_NIC, CK_ICN_NIC, CLK_IS_CRITICAL, 5),
+
+ STM32_DIV(_CK_ICN_LS_MCU, CK_ICN_LS_MCU, _CK_ICN_HS_MCU, 0, DIV_LSMCU),
+
+ FLEXGEN(_CK_FLEXGEN_07, CK_FLEXGEN_07, 0, 7),
+ FLEXGEN(_CK_FLEXGEN_08, CK_FLEXGEN_08, 0, 8),
+ FLEXGEN(_CK_FLEXGEN_09, CK_FLEXGEN_09, 0, 9),
+ FLEXGEN(_CK_FLEXGEN_10, CK_FLEXGEN_10, 0, 10),
+ FLEXGEN(_CK_FLEXGEN_11, CK_FLEXGEN_11, 0, 11),
+ FLEXGEN(_CK_FLEXGEN_12, CK_FLEXGEN_12, 0, 12),
+ FLEXGEN(_CK_FLEXGEN_13, CK_FLEXGEN_13, 0, 13),
+ FLEXGEN(_CK_FLEXGEN_14, CK_FLEXGEN_14, 0, 14),
+ FLEXGEN(_CK_FLEXGEN_15, CK_FLEXGEN_15, 0, 15),
+ FLEXGEN(_CK_FLEXGEN_16, CK_FLEXGEN_16, 0, 16),
+ FLEXGEN(_CK_FLEXGEN_17, CK_FLEXGEN_17, 0, 17),
+ FLEXGEN(_CK_FLEXGEN_18, CK_FLEXGEN_18, 0, 18),
+ FLEXGEN(_CK_FLEXGEN_19, CK_FLEXGEN_19, 0, 19),
+ FLEXGEN(_CK_FLEXGEN_20, CK_FLEXGEN_20, 0, 20),
+ FLEXGEN(_CK_FLEXGEN_21, CK_FLEXGEN_21, 0, 21),
+ FLEXGEN(_CK_FLEXGEN_22, CK_FLEXGEN_22, 0, 22),
+ FLEXGEN(_CK_FLEXGEN_23, CK_FLEXGEN_23, 0, 23),
+ FLEXGEN(_CK_FLEXGEN_24, CK_FLEXGEN_24, 0, 24),
+ FLEXGEN(_CK_FLEXGEN_25, CK_FLEXGEN_25, 0, 25),
+ FLEXGEN(_CK_FLEXGEN_26, CK_FLEXGEN_26, 0, 26),
+ FLEXGEN(_CK_FLEXGEN_27, CK_FLEXGEN_27, 0, 27),
+ FLEXGEN(_CK_FLEXGEN_28, CK_FLEXGEN_28, 0, 28),
+ FLEXGEN(_CK_FLEXGEN_29, CK_FLEXGEN_29, 0, 29),
+ FLEXGEN(_CK_FLEXGEN_30, CK_FLEXGEN_30, 0, 30),
+ FLEXGEN(_CK_FLEXGEN_31, CK_FLEXGEN_31, 0, 31),
+ FLEXGEN(_CK_FLEXGEN_32, CK_FLEXGEN_32, 0, 32),
+ FLEXGEN(_CK_FLEXGEN_33, CK_FLEXGEN_33, 0, 33),
+ FLEXGEN(_CK_FLEXGEN_34, CK_FLEXGEN_34, 0, 34),
+ FLEXGEN(_CK_FLEXGEN_35, CK_FLEXGEN_35, 0, 35),
+ FLEXGEN(_CK_FLEXGEN_36, CK_FLEXGEN_36, 0, 36),
+ FLEXGEN(_CK_FLEXGEN_37, CK_FLEXGEN_37, 0, 37),
+ FLEXGEN(_CK_FLEXGEN_38, CK_FLEXGEN_38, 0, 38),
+ FLEXGEN(_CK_FLEXGEN_39, CK_FLEXGEN_39, 0, 39),
+ FLEXGEN(_CK_FLEXGEN_40, CK_FLEXGEN_40, 0, 40),
+ FLEXGEN(_CK_FLEXGEN_41, CK_FLEXGEN_41, 0, 41),
+ FLEXGEN(_CK_FLEXGEN_42, CK_FLEXGEN_42, 0, 42),
+ FLEXGEN(_CK_FLEXGEN_43, CK_FLEXGEN_43, 0, 43),
+ FLEXGEN(_CK_FLEXGEN_44, CK_FLEXGEN_44, 0, 44),
+ FLEXGEN(_CK_FLEXGEN_45, CK_FLEXGEN_45, 0, 45),
+ FLEXGEN(_CK_FLEXGEN_46, CK_FLEXGEN_46, 0, 46),
+ FLEXGEN(_CK_FLEXGEN_47, CK_FLEXGEN_47, 0, 47),
+ FLEXGEN(_CK_FLEXGEN_48, CK_FLEXGEN_48, 0, 48),
+ FLEXGEN(_CK_FLEXGEN_49, CK_FLEXGEN_49, 0, 49),
+ FLEXGEN(_CK_FLEXGEN_50, CK_FLEXGEN_50, 0, 50),
+ FLEXGEN(_CK_FLEXGEN_51, CK_FLEXGEN_51, 0, 51),
+ FLEXGEN(_CK_FLEXGEN_52, CK_FLEXGEN_52, 0, 52),
+ FLEXGEN(_CK_FLEXGEN_53, CK_FLEXGEN_53, 0, 53),
+ FLEXGEN(_CK_FLEXGEN_54, CK_FLEXGEN_54, 0, 54),
+ FLEXGEN(_CK_FLEXGEN_55, CK_FLEXGEN_55, 0, 55),
+ FLEXGEN(_CK_FLEXGEN_56, CK_FLEXGEN_56, 0, 56),
+ FLEXGEN(_CK_FLEXGEN_57, CK_FLEXGEN_57, 0, 57),
+ FLEXGEN(_CK_FLEXGEN_58, CK_FLEXGEN_58, 0, 58),
+ FLEXGEN(_CK_FLEXGEN_59, CK_FLEXGEN_59, 0, 59),
+ FLEXGEN(_CK_FLEXGEN_60, CK_FLEXGEN_60, 0, 60),
+ FLEXGEN(_CK_FLEXGEN_61, CK_FLEXGEN_61, 0, 61),
+ FLEXGEN(_CK_FLEXGEN_62, CK_FLEXGEN_62, 0, 62),
+ FLEXGEN(_CK_FLEXGEN_63, CK_FLEXGEN_63, 0, 63),
+
+ STM32_DIV(_CK_ICN_APB1, CK_ICN_APB1, _CK_ICN_LS_MCU, 0, DIV_APB1),
+ STM32_DIV(_CK_ICN_APB2, CK_ICN_APB2, _CK_ICN_LS_MCU, 0, DIV_APB2),
+ STM32_DIV(_CK_ICN_APB3, CK_ICN_APB3, _CK_ICN_LS_MCU, 0, DIV_APB3),
+ STM32_DIV(_CK_ICN_APB4, CK_ICN_APB4, _CK_ICN_LS_MCU, 0, DIV_APB4),
+ STM32_DIV(_CK_ICN_APBDBG, CK_ICN_APBDBG, _CK_ICN_LS_MCU, 0, DIV_APBDBG),
+
+ /* KERNEL CLOCK */
+ STM32_GATE(_CK_SYSRAM, CK_BUS_SYSRAM, _CK_ICN_HS_MCU, 0, GATE_SYSRAM),
+ STM32_GATE(_CK_RETRAM, CK_BUS_RETRAM, _CK_ICN_HS_MCU, 0, GATE_RETRAM),
+ STM32_GATE(_CK_SRAM1, CK_BUS_SRAM1, _CK_ICN_HS_MCU, CLK_IS_CRITICAL, GATE_SRAM1),
+ STM32_GATE(_CK_SRAM2, CK_BUS_SRAM2, _CK_ICN_HS_MCU, CLK_IS_CRITICAL, GATE_SRAM2),
+
+ STM32_GATE(_CK_DDRPHYC, CK_BUS_DDRPHYC, _CK_ICN_LS_MCU, 0, GATE_DDRPHYC),
+ STM32_GATE(_CK_SYSCPU1, CK_BUS_SYSCPU1, _CK_ICN_LS_MCU, 0, GATE_SYSCPU1),
+ STM32_GATE(_CK_CRC, CK_BUS_CRC, _CK_ICN_LS_MCU, 0, GATE_CRC),
+ STM32_GATE(_CK_OSPIIOM, CK_BUS_OSPIIOM, _CK_ICN_LS_MCU, 0, GATE_OSPIIOM),
+ STM32_GATE(_CK_BKPSRAM, CK_BUS_BKPSRAM, _CK_ICN_LS_MCU, 0, GATE_BKPSRAM),
+ STM32_GATE(_CK_HASH, CK_BUS_HASH, _CK_ICN_LS_MCU, 0, GATE_HASH),
+ STM32_GATE(_CK_RNG, CK_BUS_RNG, _CK_ICN_LS_MCU, 0, GATE_RNG),
+ STM32_GATE(_CK_CRYP1, CK_BUS_CRYP1, _CK_ICN_LS_MCU, 0, GATE_CRYP1),
+ STM32_GATE(_CK_CRYP2, CK_BUS_CRYP2, _CK_ICN_LS_MCU, 0, GATE_CRYP2),
+ STM32_GATE(_CK_SAES, CK_BUS_SAES, _CK_ICN_LS_MCU, 0, GATE_SAES),
+ STM32_GATE(_CK_PKA, CK_BUS_PKA, _CK_ICN_LS_MCU, 0, GATE_PKA),
+
+ STM32_GATE(_CK_GPIOA, CK_BUS_GPIOA, _CK_ICN_LS_MCU, 0, GATE_GPIOA),
+ STM32_GATE(_CK_GPIOB, CK_BUS_GPIOB, _CK_ICN_LS_MCU, 0, GATE_GPIOB),
+ STM32_GATE(_CK_GPIOC, CK_BUS_GPIOC, _CK_ICN_LS_MCU, 0, GATE_GPIOC),
+ STM32_GATE(_CK_GPIOD, CK_BUS_GPIOD, _CK_ICN_LS_MCU, 0, GATE_GPIOD),
+ STM32_GATE(_CK_GPIOE, CK_BUS_GPIOE, _CK_ICN_LS_MCU, 0, GATE_GPIOE),
+ STM32_GATE(_CK_GPIOF, CK_BUS_GPIOF, _CK_ICN_LS_MCU, 0, GATE_GPIOF),
+ STM32_GATE(_CK_GPIOG, CK_BUS_GPIOG, _CK_ICN_LS_MCU, 0, GATE_GPIOG),
+ STM32_GATE(_CK_GPIOH, CK_BUS_GPIOH, _CK_ICN_LS_MCU, 0, GATE_GPIOH),
+ STM32_GATE(_CK_GPIOI, CK_BUS_GPIOI, _CK_ICN_LS_MCU, 0, GATE_GPIOI),
+ STM32_GATE(_CK_GPIOJ, CK_BUS_GPIOJ, _CK_ICN_LS_MCU, 0, GATE_GPIOJ),
+ STM32_GATE(_CK_GPIOK, CK_BUS_GPIOK, _CK_ICN_LS_MCU, 0, GATE_GPIOK),
+ STM32_GATE(_CK_GPIOZ, CK_BUS_GPIOZ, _CK_ICN_LS_MCU, 0, GATE_GPIOZ),
+ STM32_GATE(_CK_RTC, CK_BUS_RTC, _CK_ICN_LS_MCU, 0, GATE_RTC),
+
+ STM32_GATE(_CK_DDRCP, CK_BUS_DDR, _CK_ICN_DDR, 0, GATE_DDRCP),
+
+ /* WARNING 2 CLOCKS FOR ONE GATE */
+ STM32_GATE(_CK_USB2OHCI, CK_BUS_USB2OHCI, _CK_ICN_HSL, 0, GATE_USB2OHCI),
+ STM32_GATE(_CK_USB2EHCI, CK_BUS_USB2EHCI, _CK_ICN_HSL, 0, GATE_USB2EHCI),
+
+ STM32_GATE(_CK_USB3DR, CK_BUS_USB3DR, _CK_ICN_HSL, 0, GATE_USB3DR),
+
+ STM32_GATE(_CK_BSEC, CK_BUS_BSEC, _CK_ICN_APB3, 0, GATE_BSEC),
+ STM32_GATE(_CK_IWDG1, CK_BUS_IWDG1, _CK_ICN_APB3, 0, GATE_IWDG1),
+ STM32_GATE(_CK_IWDG2, CK_BUS_IWDG2, _CK_ICN_APB3, 0, GATE_IWDG2),
+
+ STM32_GATE(_CK_DDRCAPB, CK_BUS_DDRC, _CK_ICN_APB4, 0, GATE_DDRCAPB),
+ STM32_GATE(_CK_DDR, CK_BUS_DDRCFG, _CK_ICN_APB4, 0, GATE_DDR),
+
+ STM32_GATE(_CK_USART2, CK_KER_USART2, _CK_FLEXGEN_08, 0, GATE_USART2),
+ STM32_GATE(_CK_UART4, CK_KER_UART4, _CK_FLEXGEN_08, 0, GATE_UART4),
+ STM32_GATE(_CK_USART3, CK_KER_USART3, _CK_FLEXGEN_09, 0, GATE_USART3),
+ STM32_GATE(_CK_UART5, CK_KER_UART5, _CK_FLEXGEN_09, 0, GATE_UART5),
+ STM32_GATE(_CK_I2C1, CK_KER_I2C1, _CK_FLEXGEN_12, 0, GATE_I2C1),
+ STM32_GATE(_CK_I2C2, CK_KER_I2C2, _CK_FLEXGEN_12, 0, GATE_I2C2),
+ STM32_GATE(_CK_I2C3, CK_KER_I2C3, _CK_FLEXGEN_13, 0, GATE_I2C3),
+ STM32_GATE(_CK_I2C5, CK_KER_I2C5, _CK_FLEXGEN_13, 0, GATE_I2C5),
+ STM32_GATE(_CK_I2C4, CK_KER_I2C4, _CK_FLEXGEN_14, 0, GATE_I2C4),
+ STM32_GATE(_CK_I2C6, CK_KER_I2C6, _CK_FLEXGEN_14, 0, GATE_I2C6),
+ STM32_GATE(_CK_I2C7, CK_KER_I2C7, _CK_FLEXGEN_15, 0, GATE_I2C7),
+ STM32_GATE(_CK_USART1, CK_KER_USART1, _CK_FLEXGEN_19, 0, GATE_USART1),
+ STM32_GATE(_CK_USART6, CK_KER_USART6, _CK_FLEXGEN_20, 0, GATE_USART6),
+ STM32_GATE(_CK_UART7, CK_KER_UART7, _CK_FLEXGEN_21, 0, GATE_UART7),
+ STM32_GATE(_CK_UART8, CK_KER_UART8, _CK_FLEXGEN_21, 0, GATE_UART8),
+ STM32_GATE(_CK_UART9, CK_KER_UART9, _CK_FLEXGEN_22, 0, GATE_UART9),
+ STM32_GATE(_CK_STGEN, CK_KER_STGEN, _CK_FLEXGEN_33, 0, GATE_STGEN),
+ STM32_GATE(_CK_USB3PCIEPHY, CK_KER_USB3PCIEPHY, _CK_FLEXGEN_34, 0, GATE_USB3PCIEPHY),
+ STM32_GATE(_CK_USBTC, CK_KER_USBTC, _CK_FLEXGEN_35, 0, GATE_USBTC),
+ STM32_GATE(_CK_I2C8, CK_KER_I2C8, _CK_FLEXGEN_38, 0, GATE_I2C8),
+ STM32_GATE(_CK_OSPI1, CK_KER_OSPI1, _CK_FLEXGEN_48, 0, GATE_OSPI1),
+ STM32_GATE(_CK_OSPI2, CK_KER_OSPI2, _CK_FLEXGEN_49, 0, GATE_OSPI2),
+ STM32_GATE(_CK_FMC, CK_KER_FMC, _CK_FLEXGEN_50, 0, GATE_FMC),
+ STM32_GATE(_CK_SDMMC1, CK_KER_SDMMC1, _CK_FLEXGEN_51, 0, GATE_SDMMC1),
+ STM32_GATE(_CK_SDMMC2, CK_KER_SDMMC2, _CK_FLEXGEN_52, 0, GATE_SDMMC2),
+ STM32_GATE(_CK_USB2PHY1, CK_KER_USB2PHY1, _CK_FLEXGEN_57, 0, GATE_USB2PHY1),
+ STM32_GATE(_CK_USB2PHY2, CK_KER_USB2PHY2, _CK_FLEXGEN_58, 0, GATE_USB2PHY2),
+};
+
+enum clksrc_id {
+ CLKSRC_CA35SS,
+ CLKSRC_PLL1,
+ CLKSRC_PLL2,
+ CLKSRC_PLL3,
+ CLKSRC_PLL4,
+ CLKSRC_PLL5,
+ CLKSRC_PLL6,
+ CLKSRC_PLL7,
+ CLKSRC_PLL8,
+ CLKSRC_XBAR_CHANNEL0,
+ CLKSRC_XBAR_CHANNEL1,
+ CLKSRC_XBAR_CHANNEL2,
+ CLKSRC_XBAR_CHANNEL3,
+ CLKSRC_XBAR_CHANNEL4,
+ CLKSRC_XBAR_CHANNEL5,
+ CLKSRC_XBAR_CHANNEL6,
+ CLKSRC_XBAR_CHANNEL7,
+ CLKSRC_XBAR_CHANNEL8,
+ CLKSRC_XBAR_CHANNEL9,
+ CLKSRC_XBAR_CHANNEL10,
+ CLKSRC_XBAR_CHANNEL11,
+ CLKSRC_XBAR_CHANNEL12,
+ CLKSRC_XBAR_CHANNEL13,
+ CLKSRC_XBAR_CHANNEL14,
+ CLKSRC_XBAR_CHANNEL15,
+ CLKSRC_XBAR_CHANNEL16,
+ CLKSRC_XBAR_CHANNEL17,
+ CLKSRC_XBAR_CHANNEL18,
+ CLKSRC_XBAR_CHANNEL19,
+ CLKSRC_XBAR_CHANNEL20,
+ CLKSRC_XBAR_CHANNEL21,
+ CLKSRC_XBAR_CHANNEL22,
+ CLKSRC_XBAR_CHANNEL23,
+ CLKSRC_XBAR_CHANNEL24,
+ CLKSRC_XBAR_CHANNEL25,
+ CLKSRC_XBAR_CHANNEL26,
+ CLKSRC_XBAR_CHANNEL27,
+ CLKSRC_XBAR_CHANNEL28,
+ CLKSRC_XBAR_CHANNEL29,
+ CLKSRC_XBAR_CHANNEL30,
+ CLKSRC_XBAR_CHANNEL31,
+ CLKSRC_XBAR_CHANNEL32,
+ CLKSRC_XBAR_CHANNEL33,
+ CLKSRC_XBAR_CHANNEL34,
+ CLKSRC_XBAR_CHANNEL35,
+ CLKSRC_XBAR_CHANNEL36,
+ CLKSRC_XBAR_CHANNEL37,
+ CLKSRC_XBAR_CHANNEL38,
+ CLKSRC_XBAR_CHANNEL39,
+ CLKSRC_XBAR_CHANNEL40,
+ CLKSRC_XBAR_CHANNEL41,
+ CLKSRC_XBAR_CHANNEL42,
+ CLKSRC_XBAR_CHANNEL43,
+ CLKSRC_XBAR_CHANNEL44,
+ CLKSRC_XBAR_CHANNEL45,
+ CLKSRC_XBAR_CHANNEL46,
+ CLKSRC_XBAR_CHANNEL47,
+ CLKSRC_XBAR_CHANNEL48,
+ CLKSRC_XBAR_CHANNEL49,
+ CLKSRC_XBAR_CHANNEL50,
+ CLKSRC_XBAR_CHANNEL51,
+ CLKSRC_XBAR_CHANNEL52,
+ CLKSRC_XBAR_CHANNEL53,
+ CLKSRC_XBAR_CHANNEL54,
+ CLKSRC_XBAR_CHANNEL55,
+ CLKSRC_XBAR_CHANNEL56,
+ CLKSRC_XBAR_CHANNEL57,
+ CLKSRC_XBAR_CHANNEL58,
+ CLKSRC_XBAR_CHANNEL59,
+ CLKSRC_XBAR_CHANNEL60,
+ CLKSRC_XBAR_CHANNEL61,
+ CLKSRC_XBAR_CHANNEL62,
+ CLKSRC_XBAR_CHANNEL63,
+ CLKSRC_RTC,
+ CLKSRC_MCO1,
+ CLKSRC_MCO2,
+ CLKSRC_NB
+};
+
+static void stm32mp2_a35_ss_on_hsi(void)
+{
+ uintptr_t a35_ss_address = A35SSC_BASE;
+ uintptr_t chgclkreq_reg = a35_ss_address + A35_SS_CHGCLKREQ;
+ uintptr_t pll_enable_reg = a35_ss_address + A35_SS_PLL_ENABLE;
+ uint64_t timeout;
+
+ if ((mmio_read_32(chgclkreq_reg) & A35_SS_CHGCLKREQ_ARM_CHGCLKACK) ==
+ A35_SS_CHGCLKREQ_ARM_CHGCLKACK) {
+ /* Nothing to do, clock source is already set on bypass clock */
+ return;
+ }
+
+ mmio_setbits_32(chgclkreq_reg, A35_SS_CHGCLKREQ_ARM_CHGCLKREQ);
+
+ timeout = timeout_init_us(CLKSRC_TIMEOUT);
+ while ((mmio_read_32(chgclkreq_reg) & A35_SS_CHGCLKREQ_ARM_CHGCLKACK) !=
+ A35_SS_CHGCLKREQ_ARM_CHGCLKACK) {
+ if (timeout_elapsed(timeout)) {
+ EARLY_ERROR("Cannot switch A35 to bypass clock\n");
+ panic();
+ }
+ }
+
+ mmio_clrbits_32(pll_enable_reg, A35_SS_PLL_ENABLE_NRESET_SWPLL_FF);
+}
+
+#ifdef IMAGE_BL2
+static void stm32mp2_clk_muxsel_on_hsi(struct stm32_clk_priv *priv)
+{
+ mmio_clrbits_32(priv->base + RCC_MUXSELCFGR,
+ RCC_MUXSELCFGR_MUXSEL0_MASK |
+ RCC_MUXSELCFGR_MUXSEL1_MASK |
+ RCC_MUXSELCFGR_MUXSEL2_MASK |
+ RCC_MUXSELCFGR_MUXSEL3_MASK |
+ RCC_MUXSELCFGR_MUXSEL4_MASK |
+ RCC_MUXSELCFGR_MUXSEL5_MASK |
+ RCC_MUXSELCFGR_MUXSEL6_MASK |
+ RCC_MUXSELCFGR_MUXSEL7_MASK);
+}
+
+static void stm32mp2_clk_xbar_on_hsi(struct stm32_clk_priv *priv)
+{
+ uintptr_t xbar0cfgr = priv->base + RCC_XBAR0CFGR;
+ uint32_t i;
+
+ for (i = 0; i < XBAR_CHANNEL_NB; i++) {
+ mmio_clrsetbits_32(xbar0cfgr + (0x4 * i),
+ RCC_XBAR0CFGR_XBAR0SEL_MASK,
+ XBAR_SRC_HSI);
+ }
+}
+
+static int stm32mp2_a35_pll1_start(void)
+{
+ uintptr_t a35_ss_address = A35SSC_BASE;
+ uintptr_t pll_enable_reg = a35_ss_address + A35_SS_PLL_ENABLE;
+ uintptr_t chgclkreq_reg = a35_ss_address + A35_SS_CHGCLKREQ;
+ uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT);
+
+ mmio_setbits_32(pll_enable_reg, A35_SS_PLL_ENABLE_PD);
+
+ /* Wait PLL lock */
+ while ((mmio_read_32(pll_enable_reg) & A35_SS_PLL_ENABLE_LOCKP) == 0U) {
+ if (timeout_elapsed(timeout)) {
+ EARLY_ERROR("PLL1 start failed @ 0x%lx: 0x%x\n",
+ pll_enable_reg, mmio_read_32(pll_enable_reg));
+ return -ETIMEDOUT;
+ }
+ }
+
+ /* De-assert reset on PLL output clock path */
+ mmio_setbits_32(pll_enable_reg, A35_SS_PLL_ENABLE_NRESET_SWPLL_FF);
+
+ /* Switch CPU clock to PLL clock */
+ mmio_clrbits_32(chgclkreq_reg, A35_SS_CHGCLKREQ_ARM_CHGCLKREQ);
+
+ /* Wait for clock change acknowledge */
+ timeout = timeout_init_us(CLKSRC_TIMEOUT);
+ while ((mmio_read_32(chgclkreq_reg) & A35_SS_CHGCLKREQ_ARM_CHGCLKACK) != 0U) {
+ if (timeout_elapsed(timeout)) {
+ EARLY_ERROR("CA35SS switch to PLL1 failed @ 0x%lx: 0x%x\n",
+ chgclkreq_reg, mmio_read_32(chgclkreq_reg));
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
+static void stm32mp2_a35_pll1_config(uint32_t fbdiv, uint32_t refdiv, uint32_t postdiv1,
+ uint32_t postdiv2)
+{
+ uintptr_t a35_ss_address = A35SSC_BASE;
+ uintptr_t pll_freq1_reg = a35_ss_address + A35_SS_PLL_FREQ1;
+ uintptr_t pll_freq2_reg = a35_ss_address + A35_SS_PLL_FREQ2;
+
+ mmio_clrsetbits_32(pll_freq1_reg, A35_SS_PLL_FREQ1_REFDIV_MASK,
+ (refdiv << A35_SS_PLL_FREQ1_REFDIV_SHIFT) &
+ A35_SS_PLL_FREQ1_REFDIV_MASK);
+
+ mmio_clrsetbits_32(pll_freq1_reg, A35_SS_PLL_FREQ1_FBDIV_MASK,
+ (fbdiv << A35_SS_PLL_FREQ1_FBDIV_SHIFT) &
+ A35_SS_PLL_FREQ1_FBDIV_MASK);
+
+ mmio_clrsetbits_32(pll_freq2_reg, A35_SS_PLL_FREQ2_POSTDIV1_MASK,
+ (postdiv1 << A35_SS_PLL_FREQ2_POSTDIV1_SHIFT) &
+ A35_SS_PLL_FREQ2_POSTDIV1_MASK);
+
+ mmio_clrsetbits_32(pll_freq2_reg, A35_SS_PLL_FREQ2_POSTDIV2_MASK,
+ (postdiv2 << A35_SS_PLL_FREQ2_POSTDIV2_SHIFT) &
+ A35_SS_PLL_FREQ2_POSTDIV2_MASK);
+}
+
+static int clk_stm32_pll_config_output(struct stm32_clk_priv *priv,
+ const struct stm32_clk_pll *pll,
+ uint32_t *pllcfg,
+ uint32_t fracv)
+{
+ uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
+ uintptr_t pllxcfgr2 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR2;
+ uintptr_t pllxcfgr3 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR3;
+ uintptr_t pllxcfgr4 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR4;
+ uintptr_t pllxcfgr6 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR6;
+ uintptr_t pllxcfgr7 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR7;
+ unsigned long refclk;
+
+ refclk = _clk_stm32_get_parent_rate(priv, pll->clk_id);
+
+ if (fracv == 0U) {
+ /* PLL in integer mode */
+
+ /*
+ * No need to check max clock, as oscillator reference clocks
+ * will always be less than 1.2GHz
+ */
+ if (refclk < PLL_REFCLK_MIN) {
+ panic();
+ }
+
+ mmio_clrbits_32(pllxcfgr3, RCC_PLLxCFGR3_FRACIN_MASK);
+ mmio_clrbits_32(pllxcfgr4, RCC_PLLxCFGR4_DSMEN);
+ mmio_clrbits_32(pllxcfgr3, RCC_PLLxCFGR3_DACEN);
+ mmio_setbits_32(pllxcfgr3, RCC_PLLxCFGR3_SSCGDIS);
+ mmio_setbits_32(pllxcfgr1, RCC_PLLxCFGR1_SSMODRST);
+ } else {
+ /* PLL in frac mode */
+
+ /*
+ * No need to check max clock, as oscillator reference clocks
+ * will always be less than 1.2GHz
+ */
+ if (refclk < PLL_FRAC_REFCLK_MIN) {
+ panic();
+ }
+
+ mmio_clrsetbits_32(pllxcfgr3, RCC_PLLxCFGR3_FRACIN_MASK,
+ fracv & RCC_PLLxCFGR3_FRACIN_MASK);
+ mmio_setbits_32(pllxcfgr3, RCC_PLLxCFGR3_SSCGDIS);
+ mmio_setbits_32(pllxcfgr4, RCC_PLLxCFGR4_DSMEN);
+ }
+
+ assert(pllcfg[REFDIV] != 0U);
+
+ mmio_clrsetbits_32(pllxcfgr2, RCC_PLLxCFGR2_FBDIV_MASK,
+ (pllcfg[FBDIV] << RCC_PLLxCFGR2_FBDIV_SHIFT) &
+ RCC_PLLxCFGR2_FBDIV_MASK);
+ mmio_clrsetbits_32(pllxcfgr2, RCC_PLLxCFGR2_FREFDIV_MASK,
+ pllcfg[REFDIV] & RCC_PLLxCFGR2_FREFDIV_MASK);
+ mmio_clrsetbits_32(pllxcfgr6, RCC_PLLxCFGR6_POSTDIV1_MASK,
+ pllcfg[POSTDIV1] & RCC_PLLxCFGR6_POSTDIV1_MASK);
+ mmio_clrsetbits_32(pllxcfgr7, RCC_PLLxCFGR7_POSTDIV2_MASK,
+ pllcfg[POSTDIV2] & RCC_PLLxCFGR7_POSTDIV2_MASK);
+
+ if ((pllcfg[POSTDIV1] == 0U) || (pllcfg[POSTDIV2] == 0U)) {
+ /* Bypass mode */
+ mmio_setbits_32(pllxcfgr4, RCC_PLLxCFGR4_BYPASS);
+ mmio_clrbits_32(pllxcfgr4, RCC_PLLxCFGR4_FOUTPOSTDIVEN);
+ } else {
+ mmio_clrbits_32(pllxcfgr4, RCC_PLLxCFGR4_BYPASS);
+ mmio_setbits_32(pllxcfgr4, RCC_PLLxCFGR4_FOUTPOSTDIVEN);
+ }
+
+ return 0;
+}
+
+static void clk_stm32_pll_config_csg(struct stm32_clk_priv *priv,
+ const struct stm32_clk_pll *pll,
+ uint32_t *csg)
+{
+ uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
+ uintptr_t pllxcfgr3 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR3;
+ uintptr_t pllxcfgr4 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR4;
+ uintptr_t pllxcfgr5 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR5;
+
+
+ mmio_clrsetbits_32(pllxcfgr5, RCC_PLLxCFGR5_DIVVAL_MASK,
+ csg[DIVVAL] & RCC_PLLxCFGR5_DIVVAL_MASK);
+ mmio_clrsetbits_32(pllxcfgr5, RCC_PLLxCFGR5_SPREAD_MASK,
+ (csg[SPREAD] << RCC_PLLxCFGR5_SPREAD_SHIFT) &
+ RCC_PLLxCFGR5_SPREAD_MASK);
+
+ if (csg[DOWNSPREAD] != 0) {
+ mmio_setbits_32(pllxcfgr3, RCC_PLLxCFGR3_DOWNSPREAD);
+ } else {
+ mmio_clrbits_32(pllxcfgr3, RCC_PLLxCFGR3_DOWNSPREAD);
+ }
+
+ mmio_clrbits_32(pllxcfgr3, RCC_PLLxCFGR3_SSCGDIS);
+
+ mmio_clrbits_32(pllxcfgr1, RCC_PLLxCFGR1_PLLEN);
+ udelay(1);
+
+ mmio_setbits_32(pllxcfgr4, RCC_PLLxCFGR4_DSMEN);
+ mmio_setbits_32(pllxcfgr3, RCC_PLLxCFGR3_DACEN);
+}
+
+static int stm32_clk_configure_mux(struct stm32_clk_priv *priv, uint32_t data);
+
+static inline struct stm32_pll_dt_cfg *clk_stm32_pll_get_pdata(int pll_idx)
+{
+ struct stm32_clk_priv *priv = clk_stm32_get_priv();
+ struct stm32_clk_platdata *pdata = priv->pdata;
+
+ return &pdata->pll[pll_idx];
+}
+
+static int _clk_stm32_pll1_init(struct stm32_clk_priv *priv, int pll_idx,
+ struct stm32_pll_dt_cfg *pll_conf)
+{
+ const struct stm32_clk_pll *pll = clk_stm32_pll_data(pll_idx);
+ unsigned long refclk;
+ int ret = 0;
+
+ stm32mp2_a35_ss_on_hsi();
+
+ ret = stm32_clk_configure_mux(priv, pll_conf->src);
+ if (ret != 0) {
+ panic();
+ }
+
+ refclk = _clk_stm32_get_parent_rate(priv, pll->clk_id);
+
+ /*
+ * No need to check max clock, as oscillator reference clocks will
+ * always be less than 1.2 GHz
+ */
+ if (refclk < PLL_REFCLK_MIN) {
+ EARLY_ERROR("%s: %d\n", __func__, __LINE__);
+ panic();
+ }
+
+ stm32mp2_a35_pll1_config(pll_conf->cfg[FBDIV], pll_conf->cfg[REFDIV],
+ pll_conf->cfg[POSTDIV1], pll_conf->cfg[POSTDIV2]);
+
+ ret = stm32mp2_a35_pll1_start();
+ if (ret != 0) {
+ panic();
+ }
+
+ return 0;
+}
+
+static int clk_stm32_pll_wait_mux_ready(struct stm32_clk_priv *priv,
+ const struct stm32_clk_pll *pll)
+{
+ uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
+ uint64_t timeout = timeout_init_us(CLKSRC_TIMEOUT);
+
+ while ((mmio_read_32(pllxcfgr1) & RCC_PLLxCFGR1_CKREFST) !=
+ RCC_PLLxCFGR1_CKREFST) {
+ if (timeout_elapsed(timeout)) {
+ EARLY_ERROR("PLL%d ref clock not started\n", pll->clk_id - _CK_PLL1 + 1);
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
+static int _clk_stm32_pll_init(struct stm32_clk_priv *priv, int pll_idx,
+ struct stm32_pll_dt_cfg *pll_conf)
+{
+ const struct stm32_clk_pll *pll = clk_stm32_pll_data(pll_idx);
+ uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
+ bool spread_spectrum = false;
+ int ret = 0;
+
+ _clk_stm32_pll_disable(priv, pll);
+
+ ret = stm32_clk_configure_mux(priv, pll_conf->src);
+ if (ret != 0) {
+ panic();
+ }
+
+ ret = clk_stm32_pll_wait_mux_ready(priv, pll);
+ if (ret != 0) {
+ panic();
+ }
+
+ ret = clk_stm32_pll_config_output(priv, pll, pll_conf->cfg, pll_conf->frac);
+ if (ret != 0) {
+ panic();
+ }
+
+ if (pll_conf->csg_enabled) {
+ clk_stm32_pll_config_csg(priv, pll, pll_conf->csg);
+ spread_spectrum = true;
+ }
+
+ _clk_stm32_pll_enable(priv, pll);
+
+ if (spread_spectrum) {
+ mmio_clrbits_32(pllxcfgr1, RCC_PLLxCFGR1_SSMODRST);
+ }
+
+ return 0;
+}
+
+static int clk_stm32_pll_init(struct stm32_clk_priv *priv, int pll_idx)
+{
+ struct stm32_pll_dt_cfg *pll_conf = clk_stm32_pll_get_pdata(pll_idx);
+
+ if (pll_conf->enabled) {
+ if (pll_idx == _PLL1) {
+ return _clk_stm32_pll1_init(priv, pll_idx, pll_conf);
+ } else {
+ return _clk_stm32_pll_init(priv, pll_idx, pll_conf);
+ }
+ }
+
+ return 0;
+}
+
+static int stm32mp2_clk_pll_configure(struct stm32_clk_priv *priv)
+{
+ enum pll_id i;
+ int err;
+
+ for (i = _PLL1; i < _PLL_NB; i++) {
+ err = clk_stm32_pll_init(priv, i);
+ if (err) {
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int wait_predivsr(uint16_t channel)
+{
+ struct stm32_clk_priv *priv = clk_stm32_get_priv();
+ uintptr_t rcc_base = priv->base;
+ uintptr_t previvsr;
+ uint32_t channel_bit;
+ uint64_t timeout;
+
+ if (channel < __WORD_BIT) {
+ previvsr = rcc_base + RCC_PREDIVSR1;
+ channel_bit = BIT(channel);
+ } else {
+ previvsr = rcc_base + RCC_PREDIVSR2;
+ channel_bit = BIT(channel - __WORD_BIT);
+ }
+
+ timeout = timeout_init_us(CLKDIV_TIMEOUT);
+ while ((mmio_read_32(previvsr) & channel_bit) != 0U) {
+ if (timeout_elapsed(timeout)) {
+ EARLY_ERROR("Pre divider status: %x\n",
+ mmio_read_32(previvsr));
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
+static int wait_findivsr(uint16_t channel)
+{
+ struct stm32_clk_priv *priv = clk_stm32_get_priv();
+ uintptr_t rcc_base = priv->base;
+ uintptr_t finvivsr;
+ uint32_t channel_bit;
+ uint64_t timeout;
+
+ if (channel < __WORD_BIT) {
+ finvivsr = rcc_base + RCC_FINDIVSR1;
+ channel_bit = BIT(channel);
+ } else {
+ finvivsr = rcc_base + RCC_FINDIVSR2;
+ channel_bit = BIT(channel - __WORD_BIT);
+ }
+
+ timeout = timeout_init_us(CLKDIV_TIMEOUT);
+ while ((mmio_read_32(finvivsr) & channel_bit) != 0U) {
+ if (timeout_elapsed(timeout)) {
+ EARLY_ERROR("Final divider status: %x\n",
+ mmio_read_32(finvivsr));
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
+static int wait_xbar_sts(uint16_t channel)
+{
+ struct stm32_clk_priv *priv = clk_stm32_get_priv();
+ uintptr_t rcc_base = priv->base;
+ uintptr_t xbar_cfgr = rcc_base + RCC_XBAR0CFGR + (0x4U * channel);
+ uint64_t timeout;
+
+ timeout = timeout_init_us(CLKDIV_TIMEOUT);
+ while ((mmio_read_32(xbar_cfgr) & RCC_XBAR0CFGR_XBAR0STS) != 0U) {
+ if (timeout_elapsed(timeout)) {
+ EARLY_ERROR("XBAR%uCFGR: %x\n", channel,
+ mmio_read_32(xbar_cfgr));
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
+static void flexclkgen_config_channel(uint16_t channel, unsigned int clk_src,
+ unsigned int prediv, unsigned int findiv)
+{
+ struct stm32_clk_priv *priv = clk_stm32_get_priv();
+ uintptr_t rcc_base = priv->base;
+
+ if (wait_predivsr(channel) != 0) {
+ panic();
+ }
+
+ mmio_clrsetbits_32(rcc_base + RCC_PREDIV0CFGR + (0x4U * channel),
+ RCC_PREDIV0CFGR_PREDIV0_MASK,
+ prediv);
+
+ if (wait_predivsr(channel) != 0) {
+ panic();
+ }
+
+ if (wait_findivsr(channel) != 0) {
+ panic();
+ }
+
+ mmio_clrsetbits_32(rcc_base + RCC_FINDIV0CFGR + (0x4U * channel),
+ RCC_FINDIV0CFGR_FINDIV0_MASK,
+ findiv);
+
+ if (wait_findivsr(channel) != 0) {
+ panic();
+ }
+
+ if (wait_xbar_sts(channel) != 0) {
+ panic();
+ }
+
+ mmio_clrsetbits_32(rcc_base + RCC_XBAR0CFGR + (0x4U * channel),
+ RCC_XBARxCFGR_XBARxSEL_MASK,
+ clk_src);
+ mmio_setbits_32(rcc_base + RCC_XBAR0CFGR + (0x4U * channel),
+ RCC_XBARxCFGR_XBARxEN);
+
+ if (wait_xbar_sts(channel) != 0) {
+ panic();
+ }
+}
+
+static int stm32mp2_clk_flexgen_configure(struct stm32_clk_priv *priv)
+{
+ struct stm32_clk_platdata *pdata = priv->pdata;
+ uint32_t i;
+
+ for (i = 0U; i < pdata->nflexgen; i++) {
+ uint32_t val = pdata->flexgen[i];
+ uint32_t cmd, cmd_data;
+ unsigned int channel, clk_src, pdiv, fdiv;
+
+ cmd = (val & CMD_MASK) >> CMD_SHIFT;
+ cmd_data = val & ~CMD_MASK;
+
+ if (cmd != CMD_FLEXGEN) {
+ continue;
+ }
+
+ channel = (cmd_data & FLEX_ID_MASK) >> FLEX_ID_SHIFT;
+ clk_src = (cmd_data & FLEX_SEL_MASK) >> FLEX_SEL_SHIFT;
+ pdiv = (cmd_data & FLEX_PDIV_MASK) >> FLEX_PDIV_SHIFT;
+ fdiv = (cmd_data & FLEX_FDIV_MASK) >> FLEX_FDIV_SHIFT;
+
+ switch (channel) {
+ case 33U: /* STGEN */
+ break;
+
+ default:
+ flexclkgen_config_channel(channel, clk_src, pdiv, fdiv);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static void stm32_enable_oscillator_hse(struct stm32_clk_priv *priv)
+{
+ struct stm32_clk_platdata *pdata = priv->pdata;
+ struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_HSE];
+ bool digbyp = osci->digbyp;
+ bool bypass = osci->bypass;
+ bool css = osci->css;
+
+ if (_clk_stm32_get_rate(priv, _CK_HSE) == 0U) {
+ return;
+ }
+
+ clk_oscillator_set_bypass(priv, _CK_HSE, digbyp, bypass);
+
+ _clk_stm32_enable(priv, _CK_HSE);
+
+ clk_oscillator_set_css(priv, _CK_HSE, css);
+}
+
+static void stm32_enable_oscillator_lse(struct stm32_clk_priv *priv)
+{
+ struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, _CK_LSE);
+ struct stm32_clk_platdata *pdata = priv->pdata;
+ struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSE];
+ bool digbyp = osci->digbyp;
+ bool bypass = osci->bypass;
+ uint8_t drive = osci->drive;
+
+ if (_clk_stm32_get_rate(priv, _CK_LSE) == 0U) {
+ return;
+ }
+
+ /* Do not reconfigure LSE if already enabled */
+ if (_clk_stm32_gate_is_enabled(priv, osc_data->gate_id)) {
+ return;
+ }
+
+ clk_oscillator_set_bypass(priv, _CK_LSE, digbyp, bypass);
+
+ clk_oscillator_set_drive(priv, _CK_LSE, drive);
+
+ _clk_stm32_gate_enable(priv, osc_data->gate_id);
+}
+
+static int stm32mp2_clk_switch_to_hsi(struct stm32_clk_priv *priv)
+{
+ stm32mp2_a35_ss_on_hsi();
+ stm32mp2_clk_muxsel_on_hsi(priv);
+ stm32mp2_clk_xbar_on_hsi(priv);
+
+ return 0;
+}
+
+static int stm32_clk_oscillators_wait_lse_ready(struct stm32_clk_priv *priv)
+{
+ int ret = 0;
+
+ if (_clk_stm32_get_rate(priv, _CK_LSE) != 0U) {
+ ret = clk_oscillator_wait_ready_on(priv, _CK_LSE);
+ }
+
+ return ret;
+}
+
+static void stm32_enable_oscillator_msi(struct stm32_clk_priv *priv)
+{
+ struct stm32_clk_platdata *pdata = priv->pdata;
+ struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_MSI];
+ int err;
+
+ err = clk_stm32_osc_msi_set_rate(priv, _CK_MSI, osci->freq, 0);
+ if (err != 0) {
+ EARLY_ERROR("Invalid rate %lu MHz for MSI ! (4 or 16 only)\n",
+ osci->freq / 1000000U);
+ panic();
+ }
+
+ _clk_stm32_enable(priv, _CK_MSI);
+}
+
+static void stm32_clk_oscillators_enable(struct stm32_clk_priv *priv)
+{
+ stm32_enable_oscillator_hse(priv);
+ stm32_enable_oscillator_lse(priv);
+ stm32_enable_oscillator_msi(priv);
+ _clk_stm32_enable(priv, _CK_LSI);
+}
+
+static int stm32_clk_configure_div(struct stm32_clk_priv *priv, uint32_t data)
+{
+ int div_id = (data & DIV_ID_MASK) >> DIV_ID_SHIFT;
+ int div_n = (data & DIV_DIVN_MASK) >> DIV_DIVN_SHIFT;
+
+ return clk_stm32_set_div(priv, div_id, div_n);
+}
+
+static int stm32_clk_configure_mux(struct stm32_clk_priv *priv, uint32_t data)
+{
+ int mux_id = (data & MUX_ID_MASK) >> MUX_ID_SHIFT;
+ int sel = (data & MUX_SEL_MASK) >> MUX_SEL_SHIFT;
+
+ return clk_mux_set_parent(priv, mux_id, sel);
+}
+
+static int stm32_clk_configure_clk_get_binding_id(struct stm32_clk_priv *priv, uint32_t data)
+{
+ unsigned long binding_id = ((unsigned long)data & CLK_ID_MASK) >> CLK_ID_SHIFT;
+
+ return clk_get_index(priv, binding_id);
+}
+
+static int stm32_clk_configure_clk(struct stm32_clk_priv *priv, uint32_t data)
+{
+ int sel = (data & CLK_SEL_MASK) >> CLK_SEL_SHIFT;
+ bool enable = ((data & CLK_ON_MASK) >> CLK_ON_SHIFT) != 0U;
+ int clk_id = 0;
+ int ret = 0;
+
+ clk_id = stm32_clk_configure_clk_get_binding_id(priv, data);
+ if (clk_id < 0) {
+ return clk_id;
+ }
+
+ if (sel != CLK_NOMUX) {
+ ret = _clk_stm32_set_parent_by_index(priv, clk_id, sel);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+
+ if (enable) {
+ clk_stm32_enable_call_ops(priv, clk_id);
+ } else {
+ clk_stm32_disable_call_ops(priv, clk_id);
+ }
+
+ return 0;
+}
+
+static int stm32_clk_configure(struct stm32_clk_priv *priv, uint32_t val)
+{
+ uint32_t cmd = (val & CMD_MASK) >> CMD_SHIFT;
+ uint32_t cmd_data = val & ~CMD_MASK;
+ int ret = -1;
+
+ switch (cmd) {
+ case CMD_DIV:
+ ret = stm32_clk_configure_div(priv, cmd_data);
+ break;
+
+ case CMD_MUX:
+ ret = stm32_clk_configure_mux(priv, cmd_data);
+ break;
+
+ case CMD_CLK:
+ ret = stm32_clk_configure_clk(priv, cmd_data);
+ break;
+
+ default:
+ EARLY_ERROR("%s: cmd unknown ! : 0x%x\n", __func__, val);
+ break;
+ }
+
+ return ret;
+}
+
+static int stm32_clk_bus_configure(struct stm32_clk_priv *priv)
+{
+ struct stm32_clk_platdata *pdata = priv->pdata;
+ uint32_t i;
+
+ for (i = 0; i < pdata->nbusclk; i++) {
+ int ret;
+
+ ret = stm32_clk_configure(priv, pdata->busclk[i]);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int stm32_clk_kernel_configure(struct stm32_clk_priv *priv)
+{
+ struct stm32_clk_platdata *pdata = priv->pdata;
+ uint32_t i;
+
+ for (i = 0U; i < pdata->nkernelclk; i++) {
+ int ret;
+
+ ret = stm32_clk_configure(priv, pdata->kernelclk[i]);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int stm32mp2_init_clock_tree(void)
+{
+ struct stm32_clk_priv *priv = clk_stm32_get_priv();
+ int ret;
+
+ /* Set timer with STGEN without changing its clock source */
+ stm32mp_stgen_restore_rate();
+ generic_delay_timer_init();
+
+ stm32_clk_oscillators_enable(priv);
+
+ /* Come back to HSI */
+ ret = stm32mp2_clk_switch_to_hsi(priv);
+ if (ret != 0) {
+ panic();
+ }
+
+ ret = stm32mp2_clk_pll_configure(priv);
+ if (ret != 0) {
+ panic();
+ }
+
+ /* Wait LSE ready before to use it */
+ ret = stm32_clk_oscillators_wait_lse_ready(priv);
+ if (ret != 0) {
+ panic();
+ }
+
+ ret = stm32mp2_clk_flexgen_configure(priv);
+ if (ret != 0) {
+ panic();
+ }
+
+ ret = stm32_clk_bus_configure(priv);
+ if (ret != 0) {
+ panic();
+ }
+
+ ret = stm32_clk_kernel_configure(priv);
+ if (ret != 0) {
+ panic();
+ }
+
+ return 0;
+}
+
+static int clk_stm32_parse_oscillator_fdt(void *fdt, int node, const char *name,
+ struct stm32_osci_dt_cfg *osci)
+{
+ int subnode = 0;
+
+ /* Default value oscillator not found, freq=0 */
+ osci->freq = 0;
+
+ fdt_for_each_subnode(subnode, fdt, node) {
+ const char *cchar = NULL;
+ const fdt32_t *cuint = NULL;
+ int ret = 0;
+
+ cchar = fdt_get_name(fdt, subnode, &ret);
+ if (cchar == NULL) {
+ return ret;
+ }
+
+ if (strncmp(cchar, name, (size_t)ret) ||
+ fdt_get_status(subnode) == DT_DISABLED) {
+ continue;
+ }
+
+ cuint = fdt_getprop(fdt, subnode, "clock-frequency", &ret);
+ if (cuint == NULL) {
+ return ret;
+ }
+
+ osci->freq = fdt32_to_cpu(*cuint);
+
+ if (fdt_getprop(fdt, subnode, "st,bypass", NULL) != NULL) {
+ osci->bypass = true;
+ }
+
+ if (fdt_getprop(fdt, subnode, "st,digbypass", NULL) != NULL) {
+ osci->digbyp = true;
+ }
+
+ if (fdt_getprop(fdt, subnode, "st,css", NULL) != NULL) {
+ osci->css = true;
+ }
+
+ osci->drive = fdt_read_uint32_default(fdt, subnode, "st,drive", LSEDRV_MEDIUM_HIGH);
+
+ return 0;
+ }
+
+ return 0;
+}
+
+static int stm32_clk_parse_fdt_all_oscillator(void *fdt, struct stm32_clk_platdata *pdata)
+{
+ int fdt_err = 0;
+ uint32_t i = 0;
+ int node = 0;
+
+ node = fdt_path_offset(fdt, "/clocks");
+ if (node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ for (i = 0; i < pdata->nosci; i++) {
+ const char *name = NULL;
+
+ name = clk_stm32_get_oscillator_name((enum stm32_osc)i);
+ if (name == NULL) {
+ continue;
+ }
+
+ fdt_err = clk_stm32_parse_oscillator_fdt(fdt, node, name, &pdata->osci[i]);
+ if (fdt_err < 0) {
+ panic();
+ }
+ }
+
+ return 0;
+}
+
+static int clk_stm32_parse_pll_fdt(void *fdt, int subnode, struct stm32_pll_dt_cfg *pll)
+{
+ const fdt32_t *cuint = NULL;
+ int subnode_pll = 0;
+ uint32_t val = 0;
+ int err = 0;
+
+ cuint = fdt_getprop(fdt, subnode, "st,pll", NULL);
+ if (!cuint) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ subnode_pll = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
+ if (subnode_pll < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ err = fdt_read_uint32_array(fdt, subnode_pll, "cfg", (int)PLLCFG_NB, pll->cfg);
+ if (err != 0) {
+ return err;
+ }
+
+ err = fdt_read_uint32_array(fdt, subnode_pll, "csg", (int)PLLCSG_NB, pll->csg);
+
+ pll->csg_enabled = (err == 0);
+
+ if (err == -FDT_ERR_NOTFOUND) {
+ err = 0;
+ }
+
+ if (err != 0) {
+ return err;
+ }
+
+ pll->enabled = true;
+
+ pll->frac = fdt_read_uint32_default(fdt, subnode_pll, "frac", 0);
+
+ pll->src = UINT32_MAX;
+
+ err = fdt_read_uint32(fdt, subnode_pll, "src", &val);
+ if (err == 0) {
+ pll->src = val;
+ }
+
+ return 0;
+}
+
+#define RCC_PLL_NAME_SIZE 12
+
+static int stm32_clk_parse_fdt_all_pll(void *fdt, int node, struct stm32_clk_platdata *pdata)
+{
+ unsigned int i = 0;
+
+ for (i = _PLL1; i < pdata->npll; i++) {
+ struct stm32_pll_dt_cfg *pll = pdata->pll + i;
+ char name[RCC_PLL_NAME_SIZE];
+ int subnode = 0;
+ int err = 0;
+
+ snprintf(name, sizeof(name), "st,pll-%u", i + 1);
+
+ subnode = fdt_subnode_offset(fdt, node, name);
+ if (!fdt_check_node(subnode)) {
+ continue;
+ }
+
+ err = clk_stm32_parse_pll_fdt(fdt, subnode, pll);
+ if (err != 0) {
+ panic();
+ }
+ }
+
+ return 0;
+}
+
+static int stm32_clk_parse_fdt(struct stm32_clk_platdata *pdata)
+{
+ void *fdt = NULL;
+ int node;
+ int err;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -ENOENT;
+ }
+
+ node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT);
+ if (node < 0) {
+ panic();
+ }
+
+ err = stm32_clk_parse_fdt_all_oscillator(fdt, pdata);
+ if (err != 0) {
+ return err;
+ }
+
+ err = stm32_clk_parse_fdt_all_pll(fdt, node, pdata);
+ if (err != 0) {
+ return err;
+ }
+
+ err = stm32_clk_parse_fdt_by_name(fdt, node, "st,busclk", pdata->busclk, &pdata->nbusclk);
+ if (err != 0) {
+ return err;
+ }
+
+ err = stm32_clk_parse_fdt_by_name(fdt, node, "st,flexgen", pdata->flexgen,
+ &pdata->nflexgen);
+ if (err != 0) {
+ return err;
+ }
+
+ err = stm32_clk_parse_fdt_by_name(fdt, node, "st,kerclk", pdata->kernelclk,
+ &pdata->nkernelclk);
+ if (err != 0) {
+ return err;
+ }
+
+ return 0;
+}
+#endif /* IMAGE_BL2 */
+
+static struct stm32_osci_dt_cfg mp25_osci[NB_OSCILLATOR];
+
+static struct stm32_pll_dt_cfg mp25_pll[_PLL_NB];
+
+#define DT_FLEXGEN_CLK_MAX 64
+static uint32_t mp25_flexgen[DT_FLEXGEN_CLK_MAX];
+
+#define DT_BUS_CLK_MAX 6
+static uint32_t mp25_busclk[DT_BUS_CLK_MAX];
+
+#define DT_KERNEL_CLK_MAX 20
+static uint32_t mp25_kernelclk[DT_KERNEL_CLK_MAX];
+
+static struct stm32_clk_platdata stm32mp25_pdata = {
+ .osci = mp25_osci,
+ .nosci = NB_OSCILLATOR,
+ .pll = mp25_pll,
+ .npll = _PLL_NB,
+ .flexgen = mp25_flexgen,
+ .nflexgen = DT_FLEXGEN_CLK_MAX,
+ .busclk = mp25_busclk,
+ .nbusclk = DT_BUS_CLK_MAX,
+ .kernelclk = mp25_kernelclk,
+ .nkernelclk = DT_KERNEL_CLK_MAX,
+};
+
+static uint8_t refcounts_mp25[CK_LAST];
+
+static struct stm32_clk_priv stm32mp25_clock_data = {
+ .base = RCC_BASE,
+ .num = ARRAY_SIZE(stm32mp25_clk),
+ .clks = stm32mp25_clk,
+ .parents = parent_mp25,
+ .nb_parents = ARRAY_SIZE(parent_mp25),
+ .gates = gates_mp25,
+ .nb_gates = ARRAY_SIZE(gates_mp25),
+ .div = dividers_mp25,
+ .nb_div = ARRAY_SIZE(dividers_mp25),
+ .osci_data = stm32mp25_osc_data,
+ .nb_osci_data = ARRAY_SIZE(stm32mp25_osc_data),
+ .gate_refcounts = refcounts_mp25,
+ .pdata = &stm32mp25_pdata,
+ .ops_array = ops_array_mp25,
+};
+
+int stm32mp2_clk_init(void)
+{
+ uintptr_t base = RCC_BASE;
+ int ret;
+
+#ifdef IMAGE_BL2
+ ret = stm32_clk_parse_fdt(&stm32mp25_pdata);
+ if (ret != 0) {
+ return ret;
+ }
+#endif
+
+ ret = clk_stm32_init(&stm32mp25_clock_data, base);
+ if (ret != 0) {
+ return ret;
+ }
+
+#ifdef IMAGE_BL2
+ ret = stm32mp2_init_clock_tree();
+ if (ret != 0) {
+ return ret;
+ }
+
+ clk_stm32_enable_critical_clocks();
+#endif
+
+ return 0;
+}
+
+int stm32mp2_pll1_disable(void)
+{
+#ifdef IMAGE_BL2
+ return -EPERM;
+#else
+ uintptr_t a35_ss_address = A35SSC_BASE;
+ uintptr_t pll_enable_reg = a35_ss_address + A35_SS_PLL_ENABLE;
+
+ stm32mp2_a35_ss_on_hsi();
+
+ mmio_clrbits_32(pll_enable_reg, A35_SS_PLL_ENABLE_PD);
+
+ return 0;
+#endif
+}
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/drivers/st/reset/stm32mp1_reset.c b/drivers/st/reset/stm32mp1_reset.c
index 98c8dcf..8b828a1 100644
--- a/drivers/st/reset/stm32mp1_reset.c
+++ b/drivers/st/reset/stm32mp1_reset.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2018-2024, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,8 +7,6 @@
#include <errno.h>
#include <limits.h>
-#include <platform_def.h>
-
#include <common/bl_common.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
@@ -16,6 +14,8 @@
#include <lib/mmio.h>
#include <lib/utils_def.h>
+#include <platform_def.h>
+
static uint32_t id2reg_offset(unsigned int reset_id)
{
return ((reset_id & GENMASK(31, 5)) >> 5) * sizeof(uint32_t);
@@ -67,3 +67,16 @@
return 0;
}
+
+void __dead2 stm32mp_system_reset(void)
+{
+ uintptr_t rcc_base = stm32mp_rcc_base();
+
+ mmio_setbits_32(rcc_base + RCC_MP_GRSTCSETR,
+ RCC_MP_GRSTCSETR_MPSYSRST);
+
+ /* Loop in case system reset is not immediately caught */
+ while (true) {
+ wfi();
+ }
+}
diff --git a/drivers/st/reset/stm32mp2_reset.c b/drivers/st/reset/stm32mp2_reset.c
new file mode 100644
index 0000000..0918df5
--- /dev/null
+++ b/drivers/st/reset/stm32mp2_reset.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2024, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <drivers/st/stm32mp_reset.h>
+#include <lib/mmio.h>
+#include <lib/utils_def.h>
+
+#include <platform_def.h>
+
+static uint32_t id2reg_offset(unsigned int reset_id)
+{
+ return ((reset_id & GENMASK(31, 5)) >> 5) * sizeof(uint32_t);
+}
+
+static uint8_t id2reg_bit_pos(unsigned int reset_id)
+{
+ return (uint8_t)(reset_id & GENMASK(4, 0));
+}
+
+static int reset_toggle(uint32_t id, unsigned int to_us, bool reset_status)
+{
+ uint32_t offset = id2reg_offset(id);
+ uint32_t bitmsk = BIT(id2reg_bit_pos(id));
+ uint32_t bit_check;
+ uintptr_t rcc_base = stm32mp_rcc_base();
+
+ if (reset_status) {
+ mmio_setbits_32(rcc_base + offset, bitmsk);
+ bit_check = bitmsk;
+ } else {
+ mmio_clrbits_32(rcc_base + offset, bitmsk);
+ bit_check = 0U;
+ }
+
+ if (to_us != 0U) {
+ uint64_t timeout_ref = timeout_init_us(to_us);
+
+ while ((mmio_read_32(rcc_base + offset) & bitmsk) != bit_check) {
+ if (timeout_elapsed(timeout_ref)) {
+ return -ETIMEDOUT;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int stm32mp_reset_assert(uint32_t id, unsigned int to_us)
+{
+ return reset_toggle(id, to_us, true);
+}
+
+int stm32mp_reset_deassert(uint32_t id, unsigned int to_us)
+{
+ return reset_toggle(id, to_us, false);
+}
+
+void __dead2 stm32mp_system_reset(void)
+{
+ uintptr_t rcc_base = stm32mp_rcc_base();
+
+ mmio_setbits_32(rcc_base + RCC_GRSTCSETR, RCC_GRSTCSETR_SYSRST);
+
+ /* Loop in case system reset is not immediately caught */
+ while (true) {
+ wfi();
+ }
+}
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 2e03be2..fc6fe78 100644
--- a/fdts/tc-base.dtsi
+++ b/fdts/tc-base.dtsi
@@ -265,9 +265,22 @@
method = "smc";
};
- cpu-pmu {
- compatible = "arm,armv8-pmuv3";
- interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ cpu-pmu-little {
+ compatible = LIT_CPU_PMU_COMPATIBLE;
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH &ppi_partition_little>;
+ status = "okay";
+ };
+
+ cpu-pmu-mid {
+ compatible = MID_CPU_PMU_COMPATIBLE;
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH &ppi_partition_mid>;
+ status = "okay";
+ };
+
+ cpu-pmu-big {
+ compatible = BIG_CPU_PMU_COMPATIBLE;
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH &ppi_partition_big>;
+ status = "okay";
};
sram: sram@6000000 {
@@ -290,7 +303,7 @@
clocks = <&soc_refclk>;
clock-names = "apb_pclk";
#mbox-cells = <MHU_MBOX_CELLS>;
- interrupts = <GIC_SPI MHU_RX_INT_NUM IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI MHU_RX_INT_NUM IRQ_TYPE_LEVEL_HIGH 0>;
interrupt-names = MHU_RX_INT_NAME;
};
@@ -332,23 +345,35 @@
gic: interrupt-controller@GIC_CTRL_ADDR {
compatible = "arm,gic-v3";
#address-cells = <2>;
- #interrupt-cells = <3>;
+ #interrupt-cells = <4>;
#size-cells = <2>;
ranges;
interrupt-controller;
reg = <0x0 0x30000000 0 0x10000>, /* GICD */
<0x0 0x30080000 0 GIC_GICR_OFFSET>; /* GICR */
- interrupts = <GIC_PPI 0x9 IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <GIC_PPI 0x9 IRQ_TYPE_LEVEL_LOW 0>;
};
timer {
compatible = "arm,armv8-timer";
- interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
- <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
- <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
- <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW 0>,
+ <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW 0>,
+ <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW 0>,
+ <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW 0>;
};
+ spe-pmu-mid {
+ compatible = "arm,statistical-profiling-extension-v1";
+ interrupts = <GIC_PPI 1 IRQ_TYPE_LEVEL_HIGH &ppi_partition_mid>;
+ status = "disabled";
+ };
+
+ spe-pmu-big {
+ compatible = "arm,statistical-profiling-extension-v1";
+ interrupts = <GIC_PPI 1 IRQ_TYPE_LEVEL_HIGH &ppi_partition_big>;
+ status = "disabled";
+ };
+
soc_refclk: refclk {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -374,7 +399,7 @@
os_uart: serial@2a400000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0x2A400000 0x0 UART_OFFSET>;
- interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH 0>;
clocks = <&soc_uartclk>, <&soc_refclk>;
clock-names = "uartclk", "apb_pclk";
status = "okay";
@@ -414,7 +439,7 @@
ethernet: ethernet@18000000 {
reg = <0x0 0x18000000 0x0 0x10000>;
- interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH 0>;
reg-io-width = <2>;
smsc,irq-push-pull;
@@ -446,8 +471,8 @@
mmci: mmci@1c050000 {
compatible = "arm,pl180", "arm,primecell";
reg = <0x0 0x001c050000 0x0 0x1000>;
- interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH 0>,
+ <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH 0>;
wp-gpios = <&sysreg 1 0>;
bus-width = <4>;
max-frequency = <25000000>;
@@ -471,9 +496,9 @@
gpu: gpu@2d000000 {
compatible = "arm,mali-midgard";
reg = <0x0 0x2d000000 0x0 0x200000>;
- interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+ 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";
@@ -507,10 +532,10 @@
smmu_600: smmu@2ce00000 {
compatible = "arm,smmu-v3";
reg = <0 0x2ce00000 0 0x20000>;
- interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 74 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 76 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 77 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 74 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 76 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 77 IRQ_TYPE_EDGE_RISING 0>;
interrupt-names = "eventq", "priq", "cmdq-sync", "gerror";
#iommu-cells = <1>;
status = "disabled";
@@ -520,9 +545,9 @@
#iommu-cells = <1>;
compatible = "arm,smmu-v3";
reg = <0x0 0x3f000000 0x0 0x5000000>;
- interrupts = <GIC_SPI 228 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 229 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 230 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <GIC_SPI 228 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 229 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 230 IRQ_TYPE_EDGE_RISING 0>;
interrupt-names = "eventq", "cmdq-sync", "gerror";
dma-coherent;
status = "disabled";
@@ -532,9 +557,9 @@
#iommu-cells = <1>;
compatible = "arm,smmu-v3";
reg = <HI(0x4002a00000) LO(0x4002a00000) 0x0 0x5000000>;
- interrupts = <GIC_SPI 481 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 482 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 483 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <GIC_SPI 481 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 482 IRQ_TYPE_EDGE_RISING 0>,
+ <GIC_SPI 483 IRQ_TYPE_EDGE_RISING 0>;
interrupt-names = "eventq", "cmdq-sync", "gerror";
dma-coherent;
status = "disabled";
@@ -545,7 +570,7 @@
#size-cells = <0>;
compatible = "arm,mali-d71";
reg = <HI(ADDRESSIFY(DPU_ADDR)) LO(ADDRESSIFY(DPU_ADDR)) 0 0x20000>;
- interrupts = <GIC_SPI DPU_IRQ IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI DPU_IRQ IRQ_TYPE_LEVEL_HIGH 0>;
interrupt-names = "DPU";
DPU_CLK_ATTR1;
@@ -630,7 +655,7 @@
trbe {
compatible = "arm,trace-buffer-extension";
- interrupts = <GIC_PPI 2 IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <GIC_PPI 2 IRQ_TYPE_LEVEL_LOW 0>;
};
trusty {
diff --git a/fdts/tc-fvp.dtsi b/fdts/tc-fvp.dtsi
index 9f3a9ac..1e14f0b 100644
--- a/fdts/tc-fvp.dtsi
+++ b/fdts/tc-fvp.dtsi
@@ -54,7 +54,7 @@
rtc@1c170000 {
compatible = "arm,pl031", "arm,primecell";
reg = <0x0 0x1C170000 0x0 0x1000>;
- interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH 0>;
clocks = <&soc_refclk>;
clock-names = "apb_pclk";
};
@@ -62,7 +62,7 @@
kmi@1c060000 {
compatible = "arm,pl050", "arm,primecell";
reg = <0x0 0x001c060000 0x0 0x1000>;
- interrupts = <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH 0>;
clocks = <&bp_clock24mhz>, <&bp_clock24mhz>;
clock-names = "KMIREFCLK", "apb_pclk";
};
@@ -70,7 +70,7 @@
kmi@1c070000 {
compatible = "arm,pl050", "arm,primecell";
reg = <0x0 0x001c070000 0x0 0x1000>;
- interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH 0>;
clocks = <&bp_clock24mhz>, <&bp_clock24mhz>;
clock-names = "KMIREFCLK", "apb_pclk";
};
@@ -79,6 +79,6 @@
compatible = "virtio,mmio";
reg = <0x0 0x1c130000 0x0 0x200>;
/* spec lists this wrong */
- interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH 0>;
};
};
diff --git a/fdts/tc2.dts b/fdts/tc2.dts
index 4946aca..ae37ce3 100644
--- a/fdts/tc2.dts
+++ b/fdts/tc2.dts
@@ -31,6 +31,10 @@
#define MHU_RX_INT_NUM 317
#define MHU_RX_INT_NAME "mhu_rx"
+#define LIT_CPU_PMU_COMPATIBLE "arm,cortex-a520-pmu"
+#define MID_CPU_PMU_COMPATIBLE "arm,cortex-a720-pmu"
+#define BIG_CPU_PMU_COMPATIBLE "arm,cortex-x4-pmu"
+
#define MPAM_ADDR 0x1 0x00010000 /* 0x1_0001_0000 */
#define UARTCLK_FREQ 5000000
@@ -193,22 +197,10 @@
};
#endif /* TARGET_FLAVOUR_FPGA */
- cpu-pmu {
-#if TARGET_FLAVOUR_FPGA
- interrupt-affinity = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>,
- <&CPU4>, <&CPU5>, <&CPU6>, <&CPU7>,
- <&CPU8>, <&CPU9>, <&CPU10>, <&CPU11>,
- <&CPU12>, <&CPU13>;
-#else
- interrupt-affinity = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>,
- <&CPU4>, <&CPU5>, <&CPU6>, <&CPU7>;
-#endif
- };
-
cmn-pmu {
compatible = "arm,ci-700";
reg = <0x0 0x50000000 0x0 0x10000000>;
- interrupts = <GIC_SPI 460 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 460 IRQ_TYPE_LEVEL_HIGH 0>;
};
mbox_db_rx: mhu@MHU_RX_ADDR {
@@ -237,6 +229,36 @@
};
};
+ gic: interrupt-controller@GIC_CTRL_ADDR {
+ ppi-partitions {
+ ppi_partition_little: interrupt-partition-0 {
+ affinity = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>;
+ };
+
+#if TARGET_FLAVOUR_FVP
+ ppi_partition_mid: interrupt-partition-1 {
+ affinity = <&CPU4>, <&CPU5>, <&CPU6>;
+ };
+
+ ppi_partition_big: interrupt-partition-2 {
+ affinity = <&CPU7>;
+ };
+#elif TARGET_FLAVOUR_FPGA
+ ppi_partition_mid: interrupt-partition-1 {
+ affinity = <&CPU4>, <&CPU5>, <&CPU6>, <&CPU7>, <&CPU8>;
+ };
+
+ ppi_partition_big: interrupt-partition-2 {
+ affinity = <&CPU9>, <&CPU10>, <&CPU11>, <&CPU12>, <&CPU13>;
+ };
+#endif
+ };
+ };
+
+ spe-pmu-big {
+ status = "okay";
+ };
+
smmu_700: iommu@3f000000 {
status = "okay";
};
diff --git a/fdts/tc3.dts b/fdts/tc3.dts
index c741be0..58c8edc 100644
--- a/fdts/tc3.dts
+++ b/fdts/tc3.dts
@@ -25,6 +25,10 @@
#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
@@ -67,11 +71,6 @@
};
};
- cpu-pmu {
- interrupt-affinity = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>,
- <&CPU4>, <&CPU5>, <&CPU6>, <&CPU7>;
- };
-
cs-pmu@0 {
compatible = "arm,coresight-pmu";
reg = <0x0 MCN_PMU_ADDR(0) 0x0 0xffc>;
@@ -92,6 +91,24 @@
reg = <0x0 MCN_PMU_ADDR(3) 0x0 0xffc>;
};
+ spe-pmu-mid {
+ status = "okay";
+ };
+
+ spe-pmu-big {
+ status = "okay";
+ };
+
+ dsu-pmu {
+ compatible = "arm,dsu-pmu";
+ cpus = <&CPU0>, <&CPU1>, <&CPU2>, <&CPU3>, <&CPU4>, <&CPU5>, <&CPU6>, <&CPU7>;
+ };
+
+ ni-pmu {
+ compatible = "arm,ni-tower";
+ reg = <0x0 0x4f000000 0x0 0x4000000>;
+ };
+
sram: sram@6000000 {
cpu_scp_scmi_p2a: scp-shmem@80 {
compatible = "arm,scmi-shmem";
@@ -106,6 +123,22 @@
};
};
+ 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";
diff --git a/include/arch/aarch32/arch_features.h b/include/arch/aarch32/arch_features.h
index 8e39529..abe34a4 100644
--- a/include/arch/aarch32/arch_features.h
+++ b/include/arch/aarch32/arch_features.h
@@ -16,6 +16,7 @@
((unsigned int)(((reg) >> (feat)) & mask))
#define CREATE_FEATURE_SUPPORTED(name, read_func, guard) \
+__attribute__((always_inline)) \
static inline bool is_ ## name ## _supported(void) \
{ \
if ((guard) == FEAT_STATE_DISABLED) { \
@@ -28,6 +29,7 @@
}
#define CREATE_FEATURE_PRESENT(name, idreg, idfield, mask, idval) \
+__attribute__((always_inline)) \
static inline bool is_ ## name ## _present(void) \
{ \
return (ISOLATE_FIELD(read_ ## idreg(), idfield, mask) >= idval) \
@@ -68,6 +70,7 @@
*/
/* GENTIMER */
+__attribute__((always_inline))
static inline bool is_armv7_gentimer_present(void)
{
return ISOLATE_FIELD(read_id_pfr1(), ID_PFR1_GENTIMER_SHIFT,
@@ -111,6 +114,7 @@
ID_DFR0_PERFMON_MASK, 3U)
/* FEAT_MTPMU */
+__attribute__((always_inline))
static inline bool is_feat_mtpmu_present(void)
{
unsigned int mtpmu = ISOLATE_FIELD(read_id_dfr1(), ID_DFR1_MTPMU_SHIFT,
@@ -124,39 +128,71 @@
* code. In fact, EL2 context switching is only needed for AArch64 (since
* there is no secure AArch32 EL2), so just disable these features here.
*/
+__attribute__((always_inline))
static inline bool is_feat_twed_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_ecv_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_ecv_v2_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_csv2_2_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_csv2_3_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_ras_supported(void) { return false; }
/* The following features are supported in AArch64 only. */
+__attribute__((always_inline))
static inline bool is_feat_vhe_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_sel2_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_fgt_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_tcr2_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_spe_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_rng_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_gcs_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_mte2_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_mpam_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_hcx_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_sve_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_brbe_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_trbe_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_nv2_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_sme_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_sme2_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_s2poe_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_s1poe_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_sxpoe_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_s2pie_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_s1pie_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_sxpie_supported(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_uao_present(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_nmi_present(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_ebep_present(void) { return false; }
+__attribute__((always_inline))
static inline bool is_feat_sebep_present(void) { return false; }
#endif /* ARCH_FEATURES_H */
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index df0dcc3..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
******************************************************************************/
@@ -114,9 +117,14 @@
* Definitions for EL2 system registers for save/restore routine
******************************************************************************/
#define CNTPOFF_EL2 S3_4_C14_C0_6
-#define HAFGRTR_EL2 S3_4_C3_C1_6
+#define HDFGRTR2_EL2 S3_4_C3_C1_0
+#define HDFGWTR2_EL2 S3_4_C3_C1_1
+#define HFGRTR2_EL2 S3_4_C3_C1_2
+#define HFGWTR2_EL2 S3_4_C3_C1_3
#define HDFGRTR_EL2 S3_4_C3_C1_4
#define HDFGWTR_EL2 S3_4_C3_C1_5
+#define HAFGRTR_EL2 S3_4_C3_C1_6
+#define HFGITR2_EL2 S3_4_C3_C1_7
#define HFGITR_EL2 S3_4_C1_C1_6
#define HFGRTR_EL2 S3_4_C1_C1_4
#define HFGWTR_EL2 S3_4_C1_C1_5
@@ -224,6 +232,11 @@
#define EL_IMPL_A64ONLY ULL(1)
#define EL_IMPL_A64_A32 ULL(2)
+/* ID_AA64DFR0_EL1.DebugVer definitions */
+#define ID_AA64DFR0_DEBUGVER_SHIFT U(0)
+#define ID_AA64DFR0_DEBUGVER_MASK ULL(0xf)
+#define DEBUGVER_V8P9_IMPLEMENTED ULL(0xb)
+
/* ID_AA64DFR0_EL1.TraceVer definitions */
#define ID_AA64DFR0_TRACEVER_SHIFT U(4)
#define ID_AA64DFR0_TRACEVER_MASK ULL(0xf)
@@ -326,6 +339,7 @@
#define ID_AA64MMFR0_EL1_FGT_SHIFT U(56)
#define ID_AA64MMFR0_EL1_FGT_MASK ULL(0xf)
+#define FGT2_IMPLEMENTED ULL(0x2)
#define FGT_IMPLEMENTED ULL(0x1)
#define FGT_NOT_IMPLEMENTED ULL(0x0)
@@ -569,6 +583,7 @@
/* SCR definitions */
#define SCR_RES1_BITS ((U(1) << 4) | (U(1) << 5))
#define SCR_NSE_SHIFT U(62)
+#define SCR_FGTEN2_BIT (UL(1) << 59)
#define SCR_NSE_BIT (ULL(1) << SCR_NSE_SHIFT)
#define SCR_GPF_BIT (UL(1) << 48)
#define SCR_TWEDEL_SHIFT U(30)
@@ -607,6 +622,7 @@
#define SCR_RESET_VAL SCR_RES1_BITS
/* MDCR_EL3 definitions */
+#define MDCR_EBWE_BIT (ULL(1) << 43)
#define MDCR_EnPMSN_BIT (ULL(1) << 36)
#define MDCR_MPMX_BIT (ULL(1) << 35)
#define MDCR_MCCD_BIT (ULL(1) << 34)
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index ddc1c80..f03c9d5 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -16,6 +16,7 @@
((unsigned int)(((reg) >> (feat)) & mask))
#define CREATE_FEATURE_SUPPORTED(name, read_func, guard) \
+__attribute__((always_inline)) \
static inline bool is_ ## name ## _supported(void) \
{ \
if ((guard) == FEAT_STATE_DISABLED) { \
@@ -28,6 +29,7 @@
}
#define CREATE_FEATURE_PRESENT(name, idreg, idfield, mask, idval) \
+__attribute__((always_inline)) \
static inline bool is_ ## name ## _present(void) \
{ \
return (ISOLATE_FIELD(read_ ## idreg(), idfield, mask) >= idval) \
@@ -130,8 +132,11 @@
* +----------------------------+
* | FEAT_MTPMU |
* +----------------------------+
+ * | FEAT_FGT2 |
+ * +----------------------------+
*/
+__attribute__((always_inline))
static inline bool is_armv7_gentimer_present(void)
{
/* The Generic Timer is always present in an ARMv8-A implementation */
@@ -160,6 +165,7 @@
(ID_AA64ISAR2_APA3_MASK << ID_AA64ISAR2_APA3_SHIFT)), 1U)
/* PAUTH */
+__attribute__((always_inline))
static inline bool is_armv8_3_pauth_present(void)
{
uint64_t mask_id_aa64isar1 =
@@ -216,6 +222,10 @@
CREATE_FEATURE_FUNCS(feat_fgt, id_aa64mmfr0_el1, ID_AA64MMFR0_EL1_FGT_SHIFT,
ID_AA64MMFR0_EL1_FGT_MASK, 1U, ENABLE_FEAT_FGT)
+/* FEAT_FGT2: Fine-grained traps extended */
+CREATE_FEATURE_FUNCS(feat_fgt2, id_aa64mmfr0_el1, ID_AA64MMFR0_EL1_FGT_SHIFT,
+ ID_AA64MMFR0_EL1_FGT_MASK, FGT2_IMPLEMENTED, ENABLE_FEAT_FGT2)
+
/* FEAT_ECV: Enhanced Counter Virtualization */
CREATE_FEATURE_FUNCS(feat_ecv, id_aa64mmfr0_el1, ID_AA64MMFR0_EL1_ECV_SHIFT,
ID_AA64MMFR0_EL1_ECV_MASK, 1U, ENABLE_FEAT_ECV)
@@ -238,6 +248,7 @@
CREATE_FEATURE_FUNCS(feat_s1poe, id_aa64mmfr3_el1, ID_AA64MMFR3_EL1_S1POE_SHIFT,
ID_AA64MMFR3_EL1_S1POE_MASK, 1U, ENABLE_FEAT_S1POE)
+__attribute__((always_inline))
static inline bool is_feat_sxpoe_supported(void)
{
return is_feat_s1poe_supported() || is_feat_s2poe_supported();
@@ -251,6 +262,7 @@
CREATE_FEATURE_FUNCS(feat_s1pie, id_aa64mmfr3_el1, ID_AA64MMFR3_EL1_S1PIE_SHIFT,
ID_AA64MMFR3_EL1_S1PIE_MASK, 1U, ENABLE_FEAT_S1PIE)
+__attribute__((always_inline))
static inline bool is_feat_sxpie_supported(void)
{
return is_feat_s1pie_supported() || is_feat_s2pie_supported();
@@ -277,6 +289,7 @@
* 0x11: v1.1 Armv8.4 or later
*
*/
+__attribute__((always_inline))
static inline bool is_feat_mpam_present(void)
{
unsigned int ret = (unsigned int)((((read_id_aa64pfr0_el1() >>
@@ -288,6 +301,23 @@
CREATE_FEATURE_SUPPORTED(feat_mpam, is_feat_mpam_present, ENABLE_FEAT_MPAM)
+/*
+ * FEAT_DebugV8P9: Debug extension. This function checks the field 3:0 of
+ * ID_AA64DFR0 Aarch64 Debug Feature Register 0 for the version of
+ * Feat_Debug supported. The value of the field determines feature presence
+ *
+ * 0b0110 - Arm v8.0 debug
+ * 0b0111 - Arm v8.0 debug architecture with Virtualization host extensions
+ * 0x1000 - FEAT_Debugv8p2 is supported
+ * 0x1001 - FEAT_Debugv8p4 is supported
+ * 0x1010 - FEAT_Debugv8p8 is supported
+ * 0x1011 - FEAT_Debugv8p9 is supported
+ *
+ */
+CREATE_FEATURE_FUNCS(feat_debugv8p9, id_aa64dfr0_el1, ID_AA64DFR0_DEBUGVER_SHIFT,
+ ID_AA64DFR0_DEBUGVER_MASK, DEBUGVER_V8P9_IMPLEMENTED,
+ ENABLE_FEAT_DEBUGV8P9)
+
/* FEAT_HCX: Extended Hypervisor Configuration Register */
CREATE_FEATURE_FUNCS(feat_hcx, id_aa64mmfr1_el1, ID_AA64MMFR1_EL1_HCX_SHIFT,
ID_AA64MMFR1_EL1_HCX_MASK, 1U, ENABLE_FEAT_HCX)
@@ -375,6 +405,7 @@
* Function to get hardware granularity support
******************************************************************************/
+__attribute__((always_inline))
static inline bool is_feat_tgran4K_present(void)
{
unsigned int tgranx = ISOLATE_FIELD(read_id_aa64mmfr0_el1(),
@@ -385,6 +416,7 @@
CREATE_FEATURE_PRESENT(feat_tgran16K, id_aa64mmfr0_el1, ID_AA64MMFR0_EL1_TGRAN16_SHIFT,
ID_AA64MMFR0_EL1_TGRAN16_MASK, TGRAN16_IMPLEMENTED)
+__attribute__((always_inline))
static inline bool is_feat_tgran64K_present(void)
{
unsigned int tgranx = ISOLATE_FIELD(read_id_aa64mmfr0_el1(),
@@ -397,6 +429,7 @@
ID_AA64DFR0_PMUVER_MASK, 1U)
/* FEAT_MTPMU */
+__attribute__((always_inline))
static inline bool is_feat_mtpmu_present(void)
{
unsigned int mtpmu = ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_MTPMU_SHIFT,
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 1e2f84b..a892654 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -639,6 +639,13 @@
/* Armv8.9 system registers */
DEFINE_RENAME_IDREG_READ_FUNC(id_aa64mmfr3_el1, ID_AA64MMFR3_EL1)
+/* Armv8.9 FEAT_FGT2 Registers */
+DEFINE_RENAME_SYSREG_RW_FUNCS(hdfgrtr2_el2, HDFGRTR2_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(hdfgwtr2_el2, HDFGWTR2_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(hfgitr2_el2, HFGITR2_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(hfgrtr2_el2, HFGRTR2_EL2)
+DEFINE_RENAME_SYSREG_RW_FUNCS(hfgwtr2_el2, HFGWTR2_EL2)
+
/* FEAT_TCR2 Register */
DEFINE_RENAME_SYSREG_RW_FUNCS(tcr2_el1, TCR2_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(tcr2_el2, TCR2_EL2)
diff --git a/include/arch/aarch64/el2_common_macros.S b/include/arch/aarch64/el2_common_macros.S
index 9f82399..b9b0e3d 100644
--- a/include/arch/aarch64/el2_common_macros.S
+++ b/include/arch/aarch64/el2_common_macros.S
@@ -408,7 +408,7 @@
* -----------------------------------------------------------
*/
isb
- ldp x28, x29, [sp, #CTX_EL1_SYSREGS_OFFSET + CTX_SCTLR_EL1]
+ ldp x28, x29, [sp, #CTX_ERRATA_SPEC_AT_OFFSET + CTX_ERRATA_SPEC_AT_SCTLR_EL1]
msr sctlr_el1, x28
isb
msr tcr_el1, x29
diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S
index b4c5c1b..60c5a0c 100644
--- a/include/arch/aarch64/el3_common_macros.S
+++ b/include/arch/aarch64/el3_common_macros.S
@@ -437,7 +437,7 @@
* -----------------------------------------------------------
*/
isb
- ldp x28, x29, [sp, #CTX_EL1_SYSREGS_OFFSET + CTX_SCTLR_EL1]
+ ldp x28, x29, [sp, #CTX_ERRATA_SPEC_AT_OFFSET + CTX_ERRATA_SPEC_AT_SCTLR_EL1]
msr sctlr_el1, x28
isb
msr tcr_el1, x29
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 bfda31b..ca46eb1 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.h
@@ -150,6 +150,7 @@
/* GICD_TYPER shifts and masks */
#define TYPER_ESPI U(1 << 8)
#define TYPER_DVIS U(1 << 18)
+#define TYPER_LPIS U(1 << 17)
#define TYPER_ESPI_RANGE_MASK U(0x1f)
#define TYPER_ESPI_RANGE_SHIFT U(27)
#define TYPER_ESPI_RANGE U(TYPER_ESPI_MASK << TYPER_ESPI_SHIFT)
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 9524f72..a6d58cc 100644
--- a/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h
+++ b/include/drivers/nxp/clk/s32cc/s32cc-clk-modules.h
@@ -6,6 +6,7 @@
#define S32CC_CLK_MODULES_H
#include <inttypes.h>
+#include <stdbool.h>
#include <stddef.h>
#define MHZ UL(1000000)
@@ -14,12 +15,24 @@
enum s32cc_clkm_type {
s32cc_osc_t,
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,
};
enum s32cc_clk_source {
S32CC_FIRC,
S32CC_FXOSC,
S32CC_SIRC,
+ S32CC_ARM_PLL,
+ S32CC_ARM_DFS,
+ S32CC_PERIPH_PLL,
+ S32CC_CGM0,
+ S32CC_CGM1,
};
struct s32cc_clk_obj {
@@ -42,6 +55,125 @@
.source = (SOURCE), \
}
+struct s32cc_clkmux {
+ struct s32cc_clk_obj desc;
+ enum s32cc_clk_source module;
+ uint8_t index; /* Mux index in parent module */
+ unsigned long source_id; /* Selected source */
+ uint8_t nclks; /* Number of input clocks */
+ unsigned long clkids[5]; /* IDs of the input clocks */
+};
+
+#define S32CC_CLKMUX_TYPE_INIT(TYPE, MODULE, INDEX, NCLKS, ...) \
+{ \
+ .desc = { \
+ .type = (TYPE), \
+ }, \
+ .module = (MODULE), \
+ .index = (INDEX), \
+ .nclks = (NCLKS), \
+ .clkids = {__VA_ARGS__}, \
+}
+
+#define S32CC_CLKMUX_INIT(MODULE, INDEX, NCLKS, ...) \
+ S32CC_CLKMUX_TYPE_INIT(s32cc_clkmux_t, MODULE, \
+ INDEX, NCLKS, __VA_ARGS__)
+
+#define S32CC_SHARED_CLKMUX_INIT(MODULE, INDEX, NCLKS, ...) \
+ S32CC_CLKMUX_TYPE_INIT(s32cc_shared_clkmux_t, MODULE, \
+ INDEX, NCLKS, __VA_ARGS__)
+
+struct s32cc_pll {
+ struct s32cc_clk_obj desc;
+ struct s32cc_clk_obj *source;
+ enum s32cc_clk_source instance;
+ unsigned long vco_freq;
+ uint32_t ndividers;
+ uintptr_t base;
+};
+
+#define S32CC_PLL_INIT(PLL_MUX_CLK, INSTANCE, NDIVIDERS) \
+{ \
+ .desc = { \
+ .type = s32cc_pll_t, \
+ }, \
+ .source = &(PLL_MUX_CLK).desc, \
+ .instance = (INSTANCE), \
+ .ndividers = (NDIVIDERS), \
+}
+
+struct s32cc_pll_out_div {
+ struct s32cc_clk_obj desc;
+ struct s32cc_clk_obj *parent;
+ uint32_t index;
+ unsigned long freq;
+};
+
+#define S32CC_PLL_OUT_DIV_INIT(PARENT, INDEX) \
+{ \
+ .desc = { \
+ .type = s32cc_pll_out_div_t, \
+ }, \
+ .parent = &(PARENT).desc, \
+ .index = (INDEX), \
+}
+
+#define S32CC_PLL_OUT_DIV_INIT(PARENT, INDEX) \
+{ \
+ .desc = { \
+ .type = s32cc_pll_out_div_t, \
+ }, \
+ .parent = &(PARENT).desc, \
+ .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;
+ uint32_t rate_div;
+};
+
+#define S32CC_FIXED_DIV_INIT(PARENT, RATE_DIV) \
+{ \
+ .desc = { \
+ .type = s32cc_fixed_div_t, \
+ }, \
+ .parent = &(PARENT).desc, \
+ .rate_div = (RATE_DIV), \
+}
+
struct s32cc_clk {
struct s32cc_clk_obj desc;
struct s32cc_clk_obj *module;
@@ -56,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;
@@ -88,4 +224,74 @@
return (struct s32cc_clk *)clk_addr;
}
+static inline bool is_s32cc_clk_mux(const struct s32cc_clk *clk)
+{
+ const struct s32cc_clk_obj *module;
+
+ module = clk->module;
+ if (module == NULL) {
+ return false;
+ }
+
+ return (module->type == s32cc_clkmux_t) ||
+ (module->type == s32cc_shared_clkmux_t);
+}
+
+static inline struct s32cc_clkmux *s32cc_obj2clkmux(const struct s32cc_clk_obj *mod)
+{
+ uintptr_t cmux_addr;
+
+ cmux_addr = ((uintptr_t)mod) - offsetof(struct s32cc_clkmux, desc);
+ return (struct s32cc_clkmux *)cmux_addr;
+}
+
+static inline struct s32cc_clkmux *s32cc_clk2mux(const struct s32cc_clk *clk)
+{
+ if (!is_s32cc_clk_mux(clk)) {
+ return NULL;
+ }
+
+ return s32cc_obj2clkmux(clk->module);
+}
+
+static inline struct s32cc_pll *s32cc_obj2pll(const struct s32cc_clk_obj *mod)
+{
+ uintptr_t pll_addr;
+
+ pll_addr = ((uintptr_t)mod) - offsetof(struct s32cc_pll, desc);
+ return (struct s32cc_pll *)pll_addr;
+}
+
+static inline struct s32cc_pll_out_div *s32cc_obj2plldiv(const struct s32cc_clk_obj *mod)
+{
+ uintptr_t plldiv_addr;
+
+ plldiv_addr = ((uintptr_t)mod) - offsetof(struct s32cc_pll_out_div, desc);
+ return (struct s32cc_pll_out_div *)plldiv_addr;
+}
+
+static inline struct s32cc_fixed_div *s32cc_obj2fixeddiv(const struct s32cc_clk_obj *mod)
+{
+ uintptr_t fdiv_addr;
+
+ fdiv_addr = ((uintptr_t)mod) - offsetof(struct s32cc_fixed_div, desc);
+ 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/stm32mp25_rcc.h b/include/drivers/st/stm32mp25_rcc.h
index 9dd25f3..d5d228c 100644
--- a/include/drivers/st/stm32mp25_rcc.h
+++ b/include/drivers/st/stm32mp25_rcc.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
*/
@@ -426,7 +426,7 @@
#define RCC_USB2CFGR U(0x7FC)
#define RCC_USB2PHY1CFGR U(0x800)
#define RCC_USB2PHY2CFGR U(0x804)
-#define RCC_USB3DRDCFGR U(0x808)
+#define RCC_USB3DRCFGR U(0x808)
#define RCC_USB3PCIEPHYCFGR U(0x80C)
#define RCC_PCIECFGR U(0x810)
#define RCC_USBTCCFGR U(0x814)
@@ -459,7 +459,6 @@
#define RCC_IWDG5CFGR U(0x898)
#define RCC_WWDG1CFGR U(0x89C)
#define RCC_WWDG2CFGR U(0x8A0)
-#define RCC_BUSPERFMCFGR U(0x8A4)
#define RCC_VREFCFGR U(0x8A8)
#define RCC_TMPSENSCFGR U(0x8AC)
#define RCC_CRCCFGR U(0x8B4)
@@ -2352,11 +2351,13 @@
/* RCC_C1SREQSETR register fields */
#define RCC_C1SREQSETR_STPREQ_P0 BIT(0)
#define RCC_C1SREQSETR_STPREQ_P1 BIT(1)
+#define RCC_C1SREQSETR_STPREQ_MASK GENMASK_32(1, 0)
#define RCC_C1SREQSETR_ESLPREQ BIT(16)
/* RCC_C1SREQCLRR register fields */
#define RCC_C1SREQCLRR_STPREQ_P0 BIT(0)
#define RCC_C1SREQCLRR_STPREQ_P1 BIT(1)
+#define RCC_C1SREQCLRR_STPREQ_MASK GENMASK_32(1, 0)
#define RCC_C1SREQCLRR_ESLPREQ BIT(16)
/* RCC_CPUBOOTCR register fields */
@@ -2401,12 +2402,12 @@
#define RCC_BDCR_LSEDRV_WIDTH 2
/* RCC_D3DCR register fields */
-#define RCC_D3DCR_CSION BIT(0)
-#define RCC_D3DCR_CSIKERON BIT(1)
-#define RCC_D3DCR_CSIRDY BIT(2)
+#define RCC_D3DCR_MSION BIT(0)
+#define RCC_D3DCR_MSIKERON BIT(1)
+#define RCC_D3DCR_MSIRDY BIT(2)
#define RCC_D3DCR_D3PERCKSEL_MASK GENMASK_32(17, 16)
#define RCC_D3DCR_D3PERCKSEL_SHIFT 16
-#define RCC_D3DCR_CSIRDY_BIT 2
+#define RCC_D3DCR_MSIRDY_BIT 2
/* RCC_D3DSR register fields */
#define RCC_D3DSR_D3STATE_MASK GENMASK_32(1, 0)
@@ -3458,11 +3459,11 @@
#define RCC_USB2PHYxCFGR_USB2PHY1STPEN BIT(4)
#define RCC_USB2PHYxCFGR_USB2PHY1CKREFSEL BIT(15)
-/* RCC_USB3DRDCFGR register fields */
-#define RCC_USB3DRDCFGR_USB3DRDRST BIT(0)
-#define RCC_USB3DRDCFGR_USB3DRDEN BIT(1)
-#define RCC_USB3DRDCFGR_USB3DRDLPEN BIT(2)
-#define RCC_USB3DRDCFGR_USB3DRDSTPEN BIT(4)
+/* RCC_USB3DRCFGR register fields */
+#define RCC_USB3DRCFGR_USB3DRRST BIT(0)
+#define RCC_USB3DRCFGR_USB3DREN BIT(1)
+#define RCC_USB3DRCFGR_USB3DRLPEN BIT(2)
+#define RCC_USB3DRCFGR_USB3DRSTPEN BIT(4)
/* RCC_USB3PCIEPHYCFGR register fields */
#define RCC_USB3PCIEPHYCFGR_USB3PCIEPHYRST BIT(0)
@@ -3647,11 +3648,6 @@
#define RCC_WWDG2CFGR_WWDG2LPEN BIT(2)
#define RCC_WWDG2CFGR_WWDG2AMEN BIT(3)
-/* RCC_BUSPERFMCFGR register fields */
-#define RCC_BUSPERFMCFGR_BUSPERFMRST BIT(0)
-#define RCC_BUSPERFMCFGR_BUSPERFMEN BIT(1)
-#define RCC_BUSPERFMCFGR_BUSPERFMLPEN BIT(2)
-
/* RCC_VREFCFGR register fields */
#define RCC_VREFCFGR_VREFRST BIT(0)
#define RCC_VREFCFGR_VREFEN BIT(1)
diff --git a/include/drivers/st/stm32mp2_clk.h b/include/drivers/st/stm32mp2_clk.h
new file mode 100644
index 0000000..b9226cd
--- /dev/null
+++ b/include/drivers/st/stm32mp2_clk.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STM32MP2_CLK_H
+#define STM32MP2_CLK_H
+
+#include <platform_def.h>
+
+enum stm32mp_osc_id {
+ _HSI,
+ _HSE,
+ _CSI,
+ _LSI,
+ _LSE,
+ _I2S_CKIN,
+ _SPDIF_SYMB,
+ NB_OSC,
+ _UNKNOWN_OSC_ID = 0xFF
+};
+
+extern const char *stm32mp_osc_node_label[NB_OSC];
+
+enum pll_cfg {
+ FBDIV,
+ REFDIV,
+ POSTDIV1,
+ POSTDIV2,
+ PLLCFG_NB
+};
+
+enum pll_csg {
+ DIVVAL,
+ SPREAD,
+ DOWNSPREAD,
+ PLLCSG_NB
+};
+
+int stm32mp2_clk_init(void);
+int stm32mp2_pll1_disable(void);
+
+#endif /* STM32MP2_CLK_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/drivers/st/stm32mp_reset.h b/include/drivers/st/stm32mp_reset.h
index 8444805..a8648b4 100644
--- a/include/drivers/st/stm32mp_reset.h
+++ b/include/drivers/st/stm32mp_reset.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2018-2024, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -47,4 +47,9 @@
(void)stm32mp_reset_deassert(reset_id, 0U);
}
+/*
+ * Manage system reset control
+ */
+void __dead2 stm32mp_system_reset(void);
+
#endif /* STM32MP_RESET_H */
diff --git a/include/dt-bindings/clock/stm32mp25-clks.h b/include/dt-bindings/clock/stm32mp25-clks.h
index c4ff9cf..e7ab5b0 100644
--- a/include/dt-bindings/clock/stm32mp25-clks.h
+++ b/include/dt-bindings/clock/stm32mp25-clks.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause */
/*
- * Copyright (C) 2023, STMicroelectronics - All Rights Reserved
- * Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics.
+ * Copyright (C) 2023-2024, STMicroelectronics - All Rights Reserved
+ * Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com>
*/
#ifndef _DT_BINDINGS_STM32MP25_CLKS_H_
@@ -109,7 +109,7 @@
/* LOW SPEED MCU CLOCK */
#define CK_ICN_LS_MCU 88
-#define CK_BUS_STM500 89
+#define CK_BUS_STM 89
#define CK_BUS_FMC 90
#define CK_BUS_GPU 91
#define CK_BUS_ETH1 92
@@ -233,7 +233,6 @@
#define CK_BUS_DDRCFG 210
#define CK_BUS_GICV2M 211
#define CK_BUS_USBTC 212
-#define CK_BUS_BUSPERFM 213
#define CK_BUS_USB3PCIEPHY 214
#define CK_BUS_STGEN 215
#define CK_BUS_VDEC 216
@@ -272,7 +271,7 @@
#define CK_BUS_RISAF4 249
#define CK_BUS_USB2OHCI 250
#define CK_BUS_USB2EHCI 251
-#define CK_BUS_USB3DRD 252
+#define CK_BUS_USB3DR 252
#define CK_KER_LPTIM1 253
#define CK_KER_LPTIM2 254
#define CK_KER_USART2 255
@@ -364,8 +363,10 @@
#define CK_BUS_ETHSWACMCFG 341
#define CK_BUS_ETHSWACMMSG 342
#define HSE_DIV2_CK 343
+#define CK_KER_ETR 344
+#define CK_KER_STM 345
-#define STM32MP25_LAST_CLK 344
+#define STM32MP25_LAST_CLK 346
#define CK_SCMI_ICN_HS_MCU 0
#define CK_SCMI_ICN_SDMMC 1
@@ -453,8 +454,7 @@
#define CK_SCMI_TIMG2 83
#define CK_SCMI_BKPSRAM 84
#define CK_SCMI_BSEC 85
-#define CK_SCMI_BUSPERFM 86
-#define CK_SCMI_ETR 87
+#define CK_SCMI_BUS_ETR 87
#define CK_SCMI_FMC 88
#define CK_SCMI_GPIOA 89
#define CK_SCMI_GPIOB 90
@@ -489,6 +489,8 @@
#define CK_SCMI_SYSDBG 119
#define CK_SCMI_SYSATB 120
#define CK_SCMI_TSDBG 121
-#define CK_SCMI_STM500 122
+#define CK_SCMI_BUS_STM 122
+#define CK_SCMI_KER_STM 123
+#define CK_SCMI_KER_ETR 124
#endif /* _DT_BINDINGS_STM32MP25_CLKS_H_ */
diff --git a/include/dt-bindings/clock/stm32mp25-clksrc.h b/include/dt-bindings/clock/stm32mp25-clksrc.h
index e6f7154..319fd82 100644
--- a/include/dt-bindings/clock/stm32mp25-clksrc.h
+++ b/include/dt-bindings/clock/stm32mp25-clksrc.h
@@ -1,6 +1,6 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */
+/* SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause */
/*
- * Copyright (C) 2023, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2023-2024, STMicroelectronics - All Rights Reserved
*/
#ifndef _DT_BINDINGS_CLOCK_STM32MP25_CLKSRC_H_
@@ -108,9 +108,8 @@
#define MUX_DSIPHY 18
#define MUX_LVDSPHY 19
#define MUX_DTS 20
-#define MUX_CPU1 21
-#define MUX_D3PER 22
-#define MUX_NB 23
+#define MUX_D3PER 21
+#define MUX_NB 22
#define MUXSEL_HSI 0
#define MUXSEL_HSE 1
@@ -144,7 +143,7 @@
#define MUX_USB3PCIEPHY_FLEX34 0x0
#define MUX_USB3PCIEPHY_HSE 0x1
-#define MUX_DSIBLANE_FLEX28 0x0
+#define MUX_DSIBLANE_DSIPHY 0x0
#define MUX_DSIBLANE_FLEX27 0x1
#define MUX_DSIPHY_FLEX28 0x0
@@ -219,8 +218,8 @@
/* define for st,drive */
#define LSEDRV_LOWEST 0
-#define LSEDRV_MEDIUM_LOW 1
-#define LSEDRV_MEDIUM_HIGH 2
+#define LSEDRV_MEDIUM_LOW 2
+#define LSEDRV_MEDIUM_HIGH 1
#define LSEDRV_HIGHEST 3
#endif /* _DT_BINDINGS_CLOCK_STM32MP25_CLKSRC_H_ */
diff --git a/include/dt-bindings/reset/stm32mp25-resets.h b/include/dt-bindings/reset/stm32mp25-resets.h
index c34fe2a..99b8058 100644
--- a/include/dt-bindings/reset/stm32mp25-resets.h
+++ b/include/dt-bindings/reset/stm32mp25-resets.h
@@ -1,6 +1,6 @@
/* 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(s): Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics.
*/
@@ -14,16 +14,16 @@
#define C2_R 8288
#define C2_HOLDBOOT_R 8608
#define C1_HOLDBOOT_R 8609
-#define VSW_R 8703
-#define C1MS_R 8808
-#define IWDG2_KER_R 9074
-#define IWDG4_KER_R 9202
-#define C3_R 9312
-#define DDRCP_R 9856
-#define DDRCAPB_R 9888
-#define DDRPHYCAPB_R 9920
-#define DDRCFG_R 9984
-#define DDR_R 10016
+#define VSW_R 8735
+#define C1MS_R 8840
+#define IWDG2_KER_R 9106
+#define IWDG4_KER_R 9234
+#define C3_R 9344
+#define DDRCP_R 9888
+#define DDRCAPB_R 9920
+#define DDRPHYCAPB_R 9952
+#define DDRCFG_R 10016
+#define DDR_R 10048
#define OSPI1_R 10400
#define OSPI1DLL_R 10416
#define OSPI2_R 10432
@@ -115,7 +115,7 @@
#define USB2_R 16352
#define USB2PHY1_R 16384
#define USB2PHY2_R 16416
-#define USB3DRD_R 16448
+#define USB3DR_R 16448
#define USB3PCIEPHY_R 16480
#define PCIE_R 16512
#define USBTC_R 16544
@@ -143,7 +143,6 @@
#define CRYP2_R 17440
#define WWDG1_R 17632
#define WWDG2_R 17664
-#define BUSPERFM_R 17696
#define VREF_R 17728
#define DTS_R 17760
#define CRC_R 17824
@@ -159,6 +158,9 @@
#define RST_SCMI_C1_HOLDBOOT_R 2
#define RST_SCMI_C2_HOLDBOOT_R 3
#define RST_SCMI_FMC 4
-#define RST_SCMI_PCIE 5
+#define RST_SCMI_OSPI1 5
+#define RST_SCMI_OSPI1DLL 6
+#define RST_SCMI_OSPI2 7
+#define RST_SCMI_OSPI2DLL 8
#endif /* _DT_BINDINGS_STM32MP25_RESET_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 619a15d..11ddea9 100644
--- a/include/lib/cpus/aarch64/cortex_a520.h
+++ b/include/lib/cpus/aarch64/cortex_a520.h
@@ -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
*/
@@ -15,6 +15,7 @@
#define CORTEX_A520_CPUACTLR_EL1 S3_0_C15_C1_0
#define CORTEX_A520_CPUECTLR_EL1 S3_0_C15_C1_4
+#define CORTEX_A520_CPUECTLR_EL1_EXTLLC_BIT U(0)
/*******************************************************************************
* CPU Auxiliary Control register 1 specific definitions.
@@ -27,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_a725.h b/include/lib/cpus/aarch64/cortex_a725.h
index 123c5ab..cb1c099 100644
--- a/include/lib/cpus/aarch64/cortex_a725.h
+++ b/include/lib/cpus/aarch64/cortex_a725.h
@@ -13,6 +13,7 @@
* CPU Extended Control register specific definitions
******************************************************************************/
#define CORTEX_A725_CPUECTLR_EL1 S3_0_C15_C1_4
+#define CORTEX_A725_CPUECTLR_EL1_EXTLLC_BIT U(0)
/*******************************************************************************
* CPU Power Control register specific definitions
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/cortex_x925.h b/include/lib/cpus/aarch64/cortex_x925.h
index 38aafcf..b0d0ca4 100644
--- a/include/lib/cpus/aarch64/cortex_x925.h
+++ b/include/lib/cpus/aarch64/cortex_x925.h
@@ -13,6 +13,7 @@
* CPU Extended Control register specific definitions
******************************************************************************/
#define CORTEX_X925_CPUECTLR_EL1 S3_0_C15_C1_4
+#define CORTEX_X925_CPUECTLR_EL1_EXTLLC_BIT U(0)
/*******************************************************************************
* CPU Power Control register specific definitions
diff --git a/include/lib/cpus/aarch64/cpu_macros.S b/include/lib/cpus/aarch64/cpu_macros.S
index 6faef5d..98294b9 100644
--- a/include/lib/cpus/aarch64/cpu_macros.S
+++ b/include/lib/cpus/aarch64/cpu_macros.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
*/
@@ -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.
@@ -456,6 +407,14 @@
msr \_reg, x0
.endm
+.macro sysreg_bitfield_insert_from_gpr _reg:req, _gpr:req, _lsb:req, _width:req
+ /* Source value in register for BFI */
+ mov x1, \_gpr
+ mrs x0, \_reg
+ bfi x0, x1, #\_lsb, #\_width
+ msr \_reg, x0
+.endm
+
/*
* Apply erratum
*
@@ -614,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 acf111b..87f1541 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -7,8 +7,18 @@
#ifndef CONTEXT_H
#define CONTEXT_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>
/*******************************************************************************
@@ -81,208 +91,62 @@
#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
- * 'el1_sys_regs' structure at their correct offsets. Note that some of the
- * registers are only 32-bits wide but are stored as 64-bit values for
- * convenience
- ******************************************************************************/
-#define CTX_EL1_SYSREGS_OFFSET (CTX_EL3STATE_OFFSET + CTX_EL3STATE_END)
-#define CTX_SPSR_EL1 U(0x0)
-#define CTX_ELR_EL1 U(0x8)
-#define CTX_SCTLR_EL1 U(0x10)
-#define CTX_TCR_EL1 U(0x18)
-#define CTX_CPACR_EL1 U(0x20)
-#define CTX_CSSELR_EL1 U(0x28)
-#define CTX_SP_EL1 U(0x30)
-#define CTX_ESR_EL1 U(0x38)
-#define CTX_TTBR0_EL1 U(0x40)
-#define CTX_TTBR1_EL1 U(0x48)
-#define CTX_MAIR_EL1 U(0x50)
-#define CTX_AMAIR_EL1 U(0x58)
-#define CTX_ACTLR_EL1 U(0x60)
-#define CTX_TPIDR_EL1 U(0x68)
-#define CTX_TPIDR_EL0 U(0x70)
-#define CTX_TPIDRRO_EL0 U(0x78)
-#define CTX_PAR_EL1 U(0x80)
-#define CTX_FAR_EL1 U(0x88)
-#define CTX_AFSR0_EL1 U(0x90)
-#define CTX_AFSR1_EL1 U(0x98)
-#define CTX_CONTEXTIDR_EL1 U(0xa0)
-#define CTX_VBAR_EL1 U(0xa8)
-#define CTX_MDCCINT_EL1 U(0xb0)
-#define CTX_MDSCR_EL1 U(0xb8)
-
-#define CTX_AARCH64_END U(0xc0) /* Align to the next 16 byte boundary */
-
-/*
- * If the platform is AArch64-only, there is no need to save and restore these
- * AArch32 registers.
- */
-#if CTX_INCLUDE_AARCH32_REGS
-#define CTX_SPSR_ABT (CTX_AARCH64_END + U(0x0))
-#define CTX_SPSR_UND (CTX_AARCH64_END + U(0x8))
-#define CTX_SPSR_IRQ (CTX_AARCH64_END + U(0x10))
-#define CTX_SPSR_FIQ (CTX_AARCH64_END + U(0x18))
-#define CTX_DACR32_EL2 (CTX_AARCH64_END + U(0x20))
-#define CTX_IFSR32_EL2 (CTX_AARCH64_END + U(0x28))
-#define CTX_AARCH32_END (CTX_AARCH64_END + U(0x30)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_AARCH32_END CTX_AARCH64_END
-#endif /* CTX_INCLUDE_AARCH32_REGS */
-
-/*
- * If the timer registers aren't saved and restored, we don't have to reserve
- * space for them in the context
- */
-#if NS_TIMER_SWITCH
-#define CTX_CNTP_CTL_EL0 (CTX_AARCH32_END + U(0x0))
-#define CTX_CNTP_CVAL_EL0 (CTX_AARCH32_END + U(0x8))
-#define CTX_CNTV_CTL_EL0 (CTX_AARCH32_END + U(0x10))
-#define CTX_CNTV_CVAL_EL0 (CTX_AARCH32_END + U(0x18))
-#define CTX_CNTKCTL_EL1 (CTX_AARCH32_END + U(0x20))
-#define CTX_TIMER_SYSREGS_END (CTX_AARCH32_END + U(0x30)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_TIMER_SYSREGS_END CTX_AARCH32_END
-#endif /* NS_TIMER_SWITCH */
-
-#if ENABLE_FEAT_MTE2
-#define CTX_TFSRE0_EL1 (CTX_TIMER_SYSREGS_END + U(0x0))
-#define CTX_TFSR_EL1 (CTX_TIMER_SYSREGS_END + U(0x8))
-#define CTX_RGSR_EL1 (CTX_TIMER_SYSREGS_END + U(0x10))
-#define CTX_GCR_EL1 (CTX_TIMER_SYSREGS_END + U(0x18))
-#define CTX_MTE_REGS_END (CTX_TIMER_SYSREGS_END + U(0x20)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_MTE_REGS_END CTX_TIMER_SYSREGS_END
-#endif /* ENABLE_FEAT_MTE2 */
-
-#if ENABLE_FEAT_RAS
-#define CTX_DISR_EL1 (CTX_MTE_REGS_END + U(0x0))
-#define CTX_RAS_REGS_END (CTX_MTE_REGS_END + U(0x10)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_RAS_REGS_END CTX_MTE_REGS_END
-#endif /* ENABLE_FEAT_RAS */
-
-#if ENABLE_FEAT_S1PIE
-#define CTX_PIRE0_EL1 (CTX_RAS_REGS_END + U(0x0))
-#define CTX_PIR_EL1 (CTX_RAS_REGS_END + U(0x8))
-#define CTX_S1PIE_REGS_END (CTX_RAS_REGS_END + U(0x10)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_S1PIE_REGS_END CTX_RAS_REGS_END
-#endif /* ENABLE_FEAT_S1PIE */
-
-#if ENABLE_FEAT_S1POE
-#define CTX_POR_EL1 (CTX_S1PIE_REGS_END + U(0x0))
-#define CTX_S1POE_REGS_END (CTX_S1PIE_REGS_END + U(0x10)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_S1POE_REGS_END CTX_S1PIE_REGS_END
-#endif /* ENABLE_FEAT_S1POE */
-
-#if ENABLE_FEAT_S2POE
-#define CTX_S2POR_EL1 (CTX_S1POE_REGS_END + U(0x0))
-#define CTX_S2POE_REGS_END (CTX_S1POE_REGS_END + U(0x10)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_S2POE_REGS_END CTX_S1POE_REGS_END
-#endif /* ENABLE_FEAT_S2POE */
-
-#if ENABLE_FEAT_TCR2
-#define CTX_TCR2_EL1 (CTX_S2POE_REGS_END + U(0x0))
-#define CTX_TCR2_REGS_END (CTX_S2POE_REGS_END + U(0x10)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_TCR2_REGS_END CTX_S2POE_REGS_END
-#endif /* ENABLE_FEAT_TCR2 */
-
-#if ENABLE_TRF_FOR_NS
-#define CTX_TRFCR_EL1 (CTX_TCR2_REGS_END + U(0x0))
-#define CTX_TRF_REGS_END (CTX_TCR2_REGS_END + U(0x10)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_TRF_REGS_END CTX_TCR2_REGS_END
-#endif /* ENABLE_TRF_FOR_NS */
-
-#if ENABLE_FEAT_CSV2_2
-#define CTX_SCXTNUM_EL0 (CTX_TRF_REGS_END + U(0x0))
-#define CTX_SCXTNUM_EL1 (CTX_TRF_REGS_END + U(0x8))
-#define CTX_CSV2_2_REGS_END (CTX_TRF_REGS_END + U(0x10)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_CSV2_2_REGS_END CTX_TRF_REGS_END
-#endif /* ENABLE_FEAT_CSV2_2 */
-
-#if ENABLE_FEAT_GCS
-#define CTX_GCSCR_EL1 (CTX_CSV2_2_REGS_END + U(0x0))
-#define CTX_GCSCRE0_EL1 (CTX_CSV2_2_REGS_END + U(0x8))
-#define CTX_GCSPR_EL1 (CTX_CSV2_2_REGS_END + U(0x10))
-#define CTX_GCSPR_EL0 (CTX_CSV2_2_REGS_END + U(0x18))
-#define CTX_GCS_REGS_END (CTX_CSV2_2_REGS_END + U(0x20)) /* Align to the next 16 byte boundary */
-#else
-#define CTX_GCS_REGS_END CTX_CSV2_2_REGS_END
-#endif /* ENABLE_FEAT_GCS */
-
-/*
- * End of EL1 system registers.
- */
-#define CTX_EL1_SYSREGS_END CTX_GCS_REGS_END
/*******************************************************************************
- * Constants that allow assembler code to access members of and the 'fp_regs'
- * structure at their correct offsets.
- ******************************************************************************/
-# define CTX_FPREGS_OFFSET (CTX_EL1_SYSREGS_OFFSET + CTX_EL1_SYSREGS_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 */
/*******************************************************************************
+ * Registers related to ERRATA_SPECULATIVE_AT
+ *
+ * This is essential as with EL1 and EL2 context registers being decoupled,
+ * both will not be present for a given build configuration.
+ * As ERRATA_SPECULATIVE_AT errata requires SCTLR_EL1 and TCR_EL1 registers
+ * independent of the above logic, we need explicit context entries to be
+ * reserved for these registers.
+ *
+ * NOTE: Based on this we end up with following different configurations depending
+ * on the presence of errata and inclusion of EL1 or EL2 context.
+ *
+ * ============================================================================
+ * | ERRATA_SPECULATIVE_AT | EL1 context| Memory allocation(Sctlr_el1,Tcr_el1)|
+ * ============================================================================
+ * | 0 | 0 | None |
+ * | 0 | 1 | EL1 C-Context structure |
+ * | 1 | 0 | Errata Context Offset Entries |
+ * | 1 | 1 | Errata Context Offset Entries |
+ * ============================================================================
+ *
+ * In the above table, when ERRATA_SPECULATIVE_AT=1, EL1_Context=0, it implies
+ * there is only EL2 context and memory for SCTLR_EL1 and TCR_EL1 registers is
+ * reserved explicitly under ERRATA_SPECULATIVE_AT build flag here.
+ *
+ * In situations when EL1_Context=1 and ERRATA_SPECULATIVE_AT=1, since SCTLR_EL1
+ * and TCR_EL1 registers will be modified under errata and it happens at the
+ * early in the codeflow prior to el1 context (save and restore operations),
+ * context memory still will be reserved under the errata logic here explicitly.
+ * These registers will not be part of EL1 context save & restore routines.
+ *
+ * Only when ERRATA_SPECULATIVE_AT=0, EL1_Context=1, for this combination,
+ * SCTLR_EL1 and TCR_EL1 will be part of EL1 context structure (context_el1.h)
+ * -----------------------------------------------------------------------------
+ ******************************************************************************/
+#define CTX_ERRATA_SPEC_AT_OFFSET (CTX_CVE_2018_3639_OFFSET + CTX_CVE_2018_3639_END)
+#if ERRATA_SPECULATIVE_AT
+#define CTX_ERRATA_SPEC_AT_SCTLR_EL1 U(0x0)
+#define CTX_ERRATA_SPEC_AT_TCR_EL1 U(0x8)
+#define CTX_ERRATA_SPEC_AT_END U(0x10) /* Align to the next 16 byte boundary */
+#else
+#define CTX_ERRATA_SPEC_AT_END U(0x0)
+#endif /* ERRATA_SPECULATIVE_AT */
+
+/*******************************************************************************
* Registers related to ARMv8.3-PAuth.
******************************************************************************/
-#define CTX_PAUTH_REGS_OFFSET (CTX_CVE_2018_3639_OFFSET + CTX_CVE_2018_3639_END)
+#define CTX_PAUTH_REGS_OFFSET (CTX_ERRATA_SPEC_AT_OFFSET + CTX_ERRATA_SPEC_AT_END)
#if CTX_INCLUDE_PAUTH_REGS
#define CTX_PACIAKEY_LO U(0x0)
#define CTX_PACIAKEY_HI U(0x8)
@@ -325,13 +189,13 @@
/* Constants to determine the size of individual context structures */
#define CTX_GPREG_ALL (CTX_GPREGS_END >> DWORD_SHIFT)
-#define CTX_EL1_SYSREGS_ALL (CTX_EL1_SYSREGS_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)
+
+#if ERRATA_SPECULATIVE_AT
+#define CTX_ERRATA_SPEC_AT_ALL (CTX_ERRATA_SPEC_AT_END >> DWORD_SHIFT)
+#endif
#if CTX_INCLUDE_PAUTH_REGS
# define CTX_PAUTH_REGS_ALL (CTX_PAUTH_REGS_END >> DWORD_SHIFT)
#endif
@@ -346,21 +210,6 @@
DEFINE_REG_STRUCT(gp_regs, CTX_GPREG_ALL);
/*
- * AArch64 EL1 system register context structure for preserving the
- * architectural state during world switches.
- */
-DEFINE_REG_STRUCT(el1_sysregs, CTX_EL1_SYSREGS_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
*/
@@ -369,6 +218,11 @@
/* Function pointer used by CVE-2018-3639 dynamic mitigation */
DEFINE_REG_STRUCT(cve_2018_3639, CTX_CVE_2018_3639_ALL);
+/* Registers associated to Errata_Speculative */
+#if ERRATA_SPECULATIVE_AT
+DEFINE_REG_STRUCT(errata_speculative_at, CTX_ERRATA_SPEC_AT_ALL);
+#endif
+
/* Registers associated to ARMv8.3-PAuth */
#if CTX_INCLUDE_PAUTH_REGS
DEFINE_REG_STRUCT(pauth, CTX_PAUTH_REGS_ALL);
@@ -393,19 +247,27 @@
typedef struct cpu_context {
gp_regs_t gpregs_ctx;
el3_state_t el3state_ctx;
- el1_sysregs_t el1_sysregs_ctx;
-#if CTX_INCLUDE_FPREGS
- fp_regs_t fpregs_ctx;
-#endif
cve_2018_3639_t cve_2018_3639_ctx;
+#if ERRATA_SPECULATIVE_AT
+ errata_speculative_at_t errata_speculative_at_ctx;
+#endif
+
#if CTX_INCLUDE_PAUTH_REGS
pauth_t pauth_ctx;
#endif
-#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;
@@ -424,15 +286,20 @@
/* 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)
+
+#if ERRATA_SPECULATIVE_AT
+#define get_errata_speculative_at_ctx(h) (&((cpu_context_t *) h)->errata_speculative_at_ctx)
+#endif
+
#if CTX_INCLUDE_PAUTH_REGS
# define get_pauth_ctx(h) (&((cpu_context_t *) h)->pauth_ctx)
#endif
@@ -448,17 +315,15 @@
CASSERT(CTX_EL3STATE_OFFSET == __builtin_offsetof(cpu_context_t, el3state_ctx),
assert_core_context_el3state_offset_mismatch);
-CASSERT(CTX_EL1_SYSREGS_OFFSET == __builtin_offsetof(cpu_context_t, el1_sysregs_ctx),
- assert_core_context_el1_sys_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);
+#if ERRATA_SPECULATIVE_AT
+CASSERT(CTX_ERRATA_SPEC_AT_OFFSET == __builtin_offsetof(cpu_context_t, errata_speculative_at_ctx),
+ assert_core_context_errata_speculative_at_offset_mismatch);
+#endif
+
#if CTX_INCLUDE_PAUTH_REGS
CASSERT(CTX_PAUTH_REGS_OFFSET == __builtin_offsetof(cpu_context_t, pauth_ctx),
assert_core_context_pauth_offset_mismatch);
@@ -504,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_el1.h b/include/lib/el3_runtime/context_el1.h
new file mode 100644
index 0000000..038de25
--- /dev/null
+++ b/include/lib/el3_runtime/context_el1.h
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CONTEXT_EL1_H
+#define CONTEXT_EL1_H
+
+#ifndef __ASSEMBLER__
+
+/*******************************************************************************
+ * EL1 Registers:
+ * AArch64 EL1 system register context structure for preserving the
+ * architectural state during world switches.
+ ******************************************************************************/
+
+typedef struct el1_common_regs {
+ uint64_t spsr_el1;
+ uint64_t elr_el1;
+
+#if (!ERRATA_SPECULATIVE_AT)
+ uint64_t sctlr_el1;
+ uint64_t tcr_el1;
+#endif /* ERRATA_SPECULATIVE_AT=0 */
+
+ uint64_t cpacr_el1;
+ uint64_t csselr_el1;
+ uint64_t sp_el1;
+ uint64_t esr_el1;
+ uint64_t ttbr0_el1;
+ uint64_t ttbr1_el1;
+ uint64_t mair_el1;
+ uint64_t amair_el1;
+ uint64_t actlr_el1;
+ uint64_t tpidr_el1;
+ uint64_t tpidr_el0;
+ uint64_t tpidrro_el0;
+ uint64_t par_el1;
+ uint64_t far_el1;
+ uint64_t afsr0_el1;
+ uint64_t afsr1_el1;
+ uint64_t contextidr_el1;
+ uint64_t vbar_el1;
+ uint64_t mdccint_el1;
+ uint64_t mdscr_el1;
+} el1_common_regs_t;
+
+typedef struct el1_aarch32_regs {
+ uint64_t spsr_abt;
+ uint64_t spsr_und;
+ uint64_t spsr_irq;
+ uint64_t spsr_fiq;
+ uint64_t dacr32_el2;
+ uint64_t ifsr32_el2;
+} el1_aarch32_regs_t;
+
+typedef struct el1_arch_timer_regs {
+ uint64_t cntp_ctl_el0;
+ uint64_t cntp_cval_el0;
+ uint64_t cntv_ctl_el0;
+ uint64_t cntv_cval_el0;
+ uint64_t cntkctl_el1;
+} el1_arch_timer_regs_t;
+
+typedef struct el1_mte2_regs {
+ uint64_t tfsre0_el1;
+ uint64_t tfsr_el1;
+ uint64_t rgsr_el1;
+ uint64_t gcr_el1;
+} el1_mte2_regs_t;
+
+typedef struct el1_ras_regs {
+ uint64_t disr_el1;
+} el1_ras_regs_t;
+
+typedef struct el1_s1pie_regs {
+ uint64_t pire0_el1;
+ uint64_t pir_el1;
+} el1_s1pie_regs_t;
+
+typedef struct el1_s1poe_regs {
+ uint64_t por_el1;
+} el1_s1poe_regs_t;
+
+typedef struct el1_s2poe_regs {
+ uint64_t s2por_el1;
+} el1_s2poe_regs_t;
+
+typedef struct el1_tcr2_regs {
+ uint64_t tcr2_el1;
+} el1_tcr2_regs_t;
+
+typedef struct el1_trf_regs {
+ uint64_t trfcr_el1;
+} el1_trf_regs_t;
+
+typedef struct el1_csv2_2_regs {
+ uint64_t scxtnum_el0;
+ uint64_t scxtnum_el1;
+} el1_csv2_2_regs_t;
+
+typedef struct el1_gcs_regs {
+ uint64_t gcscr_el1;
+ uint64_t gcscre0_el1;
+ uint64_t gcspr_el1;
+ uint64_t gcspr_el0;
+} el1_gcs_regs_t;
+
+typedef struct el1_sysregs {
+
+ el1_common_regs_t common;
+
+#if CTX_INCLUDE_AARCH32_REGS
+ el1_aarch32_regs_t el1_aarch32;
+#endif
+
+#if NS_TIMER_SWITCH
+ el1_arch_timer_regs_t arch_timer;
+#endif
+
+#if ENABLE_FEAT_MTE2
+ el1_mte2_regs_t mte2;
+#endif
+
+#if ENABLE_FEAT_RAS
+ el1_ras_regs_t ras;
+#endif
+
+#if ENABLE_FEAT_S1PIE
+ el1_s1pie_regs_t s1pie;
+#endif
+
+#if ENABLE_FEAT_S1POE
+ el1_s1poe_regs_t s1poe;
+#endif
+
+#if ENABLE_FEAT_S2POE
+ el1_s2poe_regs_t s2poe;
+#endif
+
+#if ENABLE_FEAT_TCR2
+ el1_tcr2_regs_t tcr2;
+#endif
+
+#if ENABLE_TRF_FOR_NS
+ el1_trf_regs_t trf;
+#endif
+
+#if ENABLE_FEAT_CSV2_2
+ el1_csv2_2_regs_t csv2_2;
+#endif
+
+#if ENABLE_FEAT_GCS
+ el1_gcs_regs_t gcs;
+#endif
+
+} el1_sysregs_t;
+
+
+/*
+ * Macros to access members related to individual features of the el1_sysregs_t
+ * structures.
+ */
+
+#define read_el1_ctx_common(ctx, reg) (((ctx)->common).reg)
+
+#define write_el1_ctx_common(ctx, reg, val) ((((ctx)->common).reg) \
+ = (uint64_t) (val))
+
+#if NS_TIMER_SWITCH
+#define read_el1_ctx_arch_timer(ctx, reg) (((ctx)->arch_timer).reg)
+#define write_el1_ctx_arch_timer(ctx, reg, val) ((((ctx)->arch_timer).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_arch_timer(ctx, reg) ULL(0)
+#define write_el1_ctx_arch_timer(ctx, reg, val)
+#endif /* NS_TIMER_SWITCH */
+
+#if CTX_INCLUDE_AARCH32_REGS
+#define read_el1_ctx_aarch32(ctx, reg) (((ctx)->el1_aarch32).reg)
+#define write_el1_ctx_aarch32(ctx, reg, val) ((((ctx)->el1_aarch32).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_aarch32(ctx, reg) ULL(0)
+#define write_el1_ctx_aarch32(ctx, reg, val)
+#endif /* CTX_INCLUDE_AARCH32_REGS */
+
+#if ENABLE_FEAT_MTE2
+#define read_el1_ctx_mte2(ctx, reg) (((ctx)->mte2).reg)
+#define write_el1_ctx_mte2(ctx, reg, val) ((((ctx)->mte2).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_mte2(ctx, reg) ULL(0)
+#define write_el1_ctx_mte2(ctx, reg, val)
+#endif /* ENABLE_FEAT_MTE2 */
+
+#if ENABLE_FEAT_RAS
+#define read_el1_ctx_ras(ctx, reg) (((ctx)->ras).reg)
+#define write_el1_ctx_ras(ctx, reg, val) ((((ctx)->ras).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_ras(ctx, reg) ULL(0)
+#define write_el1_ctx_ras(ctx, reg, val)
+#endif /* ENABLE_FEAT_RAS */
+
+#if ENABLE_FEAT_S1PIE
+#define read_el1_ctx_s1pie(ctx, reg) (((ctx)->s1pie).reg)
+#define write_el1_ctx_s1pie(ctx, reg, val) ((((ctx)->s1pie).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_s1pie(ctx, reg) ULL(0)
+#define write_el1_ctx_s1pie(ctx, reg, val)
+#endif /* ENABLE_FEAT_S1PIE */
+
+#if ENABLE_FEAT_S1POE
+#define read_el1_ctx_s1poe(ctx, reg) (((ctx)->s1poe).reg)
+#define write_el1_ctx_s1poe(ctx, reg, val) ((((ctx)->s1poe).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_s1poe(ctx, reg) ULL(0)
+#define write_el1_ctx_s1poe(ctx, reg, val)
+#endif /* ENABLE_FEAT_S1POE */
+
+#if ENABLE_FEAT_S2POE
+#define read_el1_ctx_s2poe(ctx, reg) (((ctx)->s2poe).reg)
+#define write_el1_ctx_s2poe(ctx, reg, val) ((((ctx)->s2poe).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_s2poe(ctx, reg) ULL(0)
+#define write_el1_ctx_s2poe(ctx, reg, val)
+#endif /* ENABLE_FEAT_S2POE */
+
+#if ENABLE_FEAT_TCR2
+#define read_el1_ctx_tcr2(ctx, reg) (((ctx)->tcr2).reg)
+#define write_el1_ctx_tcr2(ctx, reg, val) ((((ctx)->tcr2).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_tcr2(ctx, reg) ULL(0)
+#define write_el1_ctx_tcr2(ctx, reg, val)
+#endif /* ENABLE_FEAT_TCR2 */
+
+#if ENABLE_TRF_FOR_NS
+#define read_el1_ctx_trf(ctx, reg) (((ctx)->trf).reg)
+#define write_el1_ctx_trf(ctx, reg, val) ((((ctx)->trf).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_trf(ctx, reg) ULL(0)
+#define write_el1_ctx_trf(ctx, reg, val)
+#endif /* ENABLE_TRF_FOR_NS */
+
+#if ENABLE_FEAT_CSV2_2
+#define read_el1_ctx_csv2_2(ctx, reg) (((ctx)->csv2_2).reg)
+#define write_el1_ctx_csv2_2(ctx, reg, val) ((((ctx)->csv2_2).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_csv2_2(ctx, reg) ULL(0)
+#define write_el1_ctx_csv2_2(ctx, reg, val)
+#endif /* ENABLE_FEAT_CSV2_2 */
+
+#if ENABLE_FEAT_GCS
+#define read_el1_ctx_gcs(ctx, reg) (((ctx)->gcs).reg)
+#define write_el1_ctx_gcs(ctx, reg, val) ((((ctx)->gcs).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el1_ctx_gcs(ctx, reg) ULL(0)
+#define write_el1_ctx_gcs(ctx, reg, val)
+#endif /* ENABLE_FEAT_GCS */
+/******************************************************************************/
+#endif /* __ASSEMBLER__ */
+
+#endif /* CONTEXT_EL1_H */
diff --git a/include/lib/el3_runtime/context_el2.h b/include/lib/el3_runtime/context_el2.h
index d25ab81..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;
@@ -62,6 +61,14 @@
uint64_t hfgwtr_el2;
} el2_fgt_regs_t;
+typedef struct el2_fgt2_regs {
+ uint64_t hdfgrtr2_el2;
+ uint64_t hdfgwtr2_el2;
+ uint64_t hfgitr2_el2;
+ uint64_t hfgrtr2_el2;
+ uint64_t hfgwtr2_el2;
+} el2_fgt2_regs_t;
+
typedef struct el2_ecv_regs {
uint64_t cntpoff_el2;
} el2_ecv_regs_t;
@@ -140,6 +147,10 @@
el2_fgt_regs_t fgt;
#endif
+#if ENABLE_FEAT_FGT2
+ el2_fgt2_regs_t fgt2;
+#endif
+
#if ENABLE_FEAT_ECV
el2_ecv_regs_t ecv;
#endif
@@ -221,6 +232,15 @@
#define write_el2_ctx_fgt(ctx, reg, val)
#endif /* ENABLE_FEAT_FGT */
+#if ENABLE_FEAT_FGT2
+#define read_el2_ctx_fgt2(ctx, reg) (((ctx)->fgt2).reg)
+#define write_el2_ctx_fgt2(ctx, reg, val) ((((ctx)->fgt2).reg) \
+ = (uint64_t) (val))
+#else
+#define read_el2_ctx_fgt2(ctx, reg) ULL(0)
+#define write_el2_ctx_fgt2(ctx, reg, val)
+#endif /* ENABLE_FEAT_FGT */
+
#if ENABLE_FEAT_ECV
#define read_el2_ctx_ecv(ctx, reg) (((ctx)->ecv).reg)
#define write_el2_ctx_ecv(ctx, reg, val) ((((ctx)->ecv).reg) \
@@ -338,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/debug_v8p9.h b/include/lib/extensions/debug_v8p9.h
new file mode 100644
index 0000000..d72c9ea
--- /dev/null
+++ b/include/lib/extensions/debug_v8p9.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DEBUG_V8P9_H
+#define DEBUG_V8P9_H
+
+#include <context.h>
+
+#if ENABLE_FEAT_DEBUGV8P9
+void debugv8p9_extended_bp_wp_enable(cpu_context_t *ctx);
+#else
+static inline void debugv8p9_extended_bp_wp_enable(cpu_context_t *ctx)
+{
+}
+#endif /* ENABLE_FEAT_DEBUGV8P9 */
+
+#endif /* DEBUG_V8P9_H */
diff --git a/include/lib/extensions/fgt2.h b/include/lib/extensions/fgt2.h
new file mode 100644
index 0000000..0388d18
--- /dev/null
+++ b/include/lib/extensions/fgt2.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FGT2_H
+#define FGT2_H
+
+#include <context.h>
+
+#if ENABLE_FEAT_FGT2
+void fgt2_enable(cpu_context_t *ctx);
+#else
+static inline void fgt2_enable(cpu_context_t *ctx)
+{
+}
+#endif /* ENABLE_FEAT_FGT2 */
+
+#endif /* FGT2_H */
diff --git a/include/lib/extensions/spe.h b/include/lib/extensions/spe.h
index c6e44f9..4801a22 100644
--- a/include/lib/extensions/spe.h
+++ b/include/lib/extensions/spe.h
@@ -12,16 +12,20 @@
#if ENABLE_SPE_FOR_NS
void spe_enable(cpu_context_t *ctx);
+void spe_disable(cpu_context_t *ctx);
void spe_init_el2_unused(void);
-void spe_disable(void);
+void spe_stop(void);
#else
static inline void spe_enable(cpu_context_t *ctx)
{
}
+static inline void spe_disable(cpu_context_t *ctx)
+{
+}
static inline void spe_init_el2_unused(void)
{
}
-static inline void spe_disable(void)
+static inline void spe_stop(void)
{
}
#endif /* ENABLE_SPE_FOR_NS */
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/trbe.h b/include/lib/extensions/trbe.h
index 5db3316..2c488e0 100644
--- a/include/lib/extensions/trbe.h
+++ b/include/lib/extensions/trbe.h
@@ -10,9 +10,13 @@
#include <context.h>
#if ENABLE_TRBE_FOR_NS
+void trbe_disable(cpu_context_t *ctx);
void trbe_enable(cpu_context_t *ctx);
void trbe_init_el2_unused(void);
#else
+static inline void trbe_disable(cpu_context_t *ctx)
+{
+}
static inline void trbe_enable(cpu_context_t *ctx)
{
}
diff --git a/include/lib/psa/rse_crypto_defs.h b/include/lib/psa/rse_crypto_defs.h
index 44936b8..b94664f 100644
--- a/include/lib/psa/rse_crypto_defs.h
+++ b/include/lib/psa/rse_crypto_defs.h
@@ -16,7 +16,7 @@
* to the corresponding API implementation in the Crypto service backend.
*
*/
-#define RSE_CRYPTO_EXPORT_PUBLIC_KEY_SID (uint16_t)(0x701)
+#define RSE_CRYPTO_EXPORT_PUBLIC_KEY_SID (uint16_t)(0x206)
/*
* The persistent key identifiers for RSE builtin keys.
diff --git a/include/lib/transfer_list.h b/include/lib/transfer_list.h
index 5bea270..1b5ec2d 100644
--- a/include/lib/transfer_list.h
+++ b/include/lib/transfer_list.h
@@ -29,7 +29,22 @@
* Version of the register convention used.
* Set to 1 for both AArch64 and AArch32 according to fw handoff spec v0.9
*/
-#define REGISTER_CONVENTION_VERSION_MASK (1 << 24)
+#define REGISTER_CONVENTION_VERSION_SHIFT_64 UL(32)
+#define REGISTER_CONVENTION_VERSION_SHIFT_32 UL(24)
+#define REGISTER_CONVENTION_VERSION_MASK UL(0xff)
+#define REGISTER_CONVENTION_VERSION UL(1)
+
+#define TRANSFER_LIST_HANDOFF_X1_VALUE(__version) \
+ ((TRANSFER_LIST_SIGNATURE & \
+ ((1UL << REGISTER_CONVENTION_VERSION_SHIFT_64) - 1)) | \
+ (((__version) & REGISTER_CONVENTION_VERSION_MASK) << \
+ REGISTER_CONVENTION_VERSION_SHIFT_64))
+
+#define TRANSFER_LIST_HANDOFF_R1_VALUE(__version) \
+ ((TRANSFER_LIST_SIGNATURE & \
+ ((1UL << REGISTER_CONVENTION_VERSION_SHIFT_32) - 1)) | \
+ (((__version) & REGISTER_CONVENTION_VERSION_MASK) << \
+ REGISTER_CONVENTION_VERSION_SHIFT_32))
#ifndef __ASSEMBLER__
diff --git a/include/lib/xlat_tables/xlat_tables_defs.h b/include/lib/xlat_tables/xlat_tables_defs.h
index 2d0949b..5434a9a 100644
--- a/include/lib/xlat_tables/xlat_tables_defs.h
+++ b/include/lib/xlat_tables/xlat_tables_defs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -171,8 +171,10 @@
#define SHAREABILITY_SHIFT 8
/* The Access Flag, AF. */
#define ACCESS_FLAG_SHIFT 10
-/* The not global bit, nG. */
+/* The not global bit, nG */
#define NOT_GLOBAL_SHIFT 11
+/* The Non-secure Extension bit, NSE */
+#define NSE_SHIFT 11
/* Contiguous hint bit. */
#define CONT_HINT_SHIFT 52
/* Execute-never bits, XN. */
diff --git a/include/plat/arm/board/common/v2m_def.h b/include/plat/arm/board/common/v2m_def.h
index cb11dac..43a77e3 100644
--- a/include/plat/arm/board/common/v2m_def.h
+++ b/include/plat/arm/board/common/v2m_def.h
@@ -17,6 +17,7 @@
/* V2M motherboard system registers & offsets */
#define V2M_SYSREGS_BASE UL(0x1c010000)
+#define V2M_SYSREGS_SIZE UL(0x00010000)
#define V2M_SYS_ID UL(0x0)
#define V2M_SYS_SWITCH UL(0x4)
#define V2M_SYS_LED UL(0x8)
@@ -78,6 +79,8 @@
/* NOR Flash */
#define V2M_FLASH0_BASE (V2M_OFFSET + UL(0x08000000))
#define V2M_FLASH0_SIZE UL(0x04000000)
+#define V2M_FLASH1_BASE (V2M_OFFSET + UL(0x0c000000))
+#define V2M_FLASH1_SIZE UL(0x04000000)
#define V2M_FLASH_BLOCK_SIZE UL(0x00040000) /* 256 KB */
#define V2M_IOFPGA_BASE (V2M_OFFSET + UL(0x1c000000))
@@ -126,6 +129,14 @@
V2M_FLASH0_SIZE, \
MT_RO_DATA | MT_SECURE)
+#define V2M_MAP_FLASH1_RW MAP_REGION_FLAT(V2M_FLASH1_BASE,\
+ V2M_FLASH1_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE)
+
+#define V2M_MAP_FLASH1_RO MAP_REGION_FLAT(V2M_FLASH1_BASE,\
+ V2M_FLASH1_SIZE, \
+ MT_RO_DATA | MT_SECURE)
+
#define V2M_MAP_IOFPGA MAP_REGION_FLAT(V2M_IOFPGA_BASE,\
V2M_IOFPGA_SIZE, \
MT_DEVICE | MT_RW | MT_SECURE)
@@ -136,5 +147,19 @@
V2M_IOFPGA_SIZE, \
MT_DEVICE | MT_RW | MT_SECURE | MT_USER)
+#define V2M_MAP_SECURE_SYSTEMREG_EL0 MAP_REGION_FLAT( \
+ V2M_SYSREGS_BASE, \
+ V2M_SYSREGS_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE | MT_USER)
+
+#define V2M_MAP_FLASH0_RW_EL0 MAP_REGION_FLAT( \
+ V2M_FLASH0_BASE, \
+ V2M_FLASH0_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE | MT_USER)
+
+#define V2M_MAP_FLASH1_RW_EL0 MAP_REGION_FLAT( \
+ V2M_FLASH1_BASE, \
+ V2M_FLASH1_SIZE, \
+ MT_DEVICE | MT_RW | MT_SECURE | MT_USER)
#endif /* V2M_DEF_H */
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index ba8df2a..83a5cd2 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -284,10 +284,7 @@
/* Firmware Handoff utility functions */
void arm_transfer_list_dyn_cfg_init(struct transfer_list_header *secure_tl);
void arm_transfer_list_populate_ep_info(bl_mem_params_node_t *next_param_node,
- struct transfer_list_header *secure_tl,
- struct transfer_list_header *ns_tl);
-void arm_transfer_list_copy_hw_config(struct transfer_list_header *secure_tl,
- struct transfer_list_header *ns_tl);
+ struct transfer_list_header *secure_tl);
/* TSP utility functions */
void arm_tsp_early_platform_setup(void);
@@ -365,6 +362,7 @@
void plat_arm_interconnect_exit_coherency(void);
void plat_arm_program_trusted_mailbox(uintptr_t address);
bool plat_arm_bl1_fwu_needed(void);
+int plat_arm_ni_setup(uintptr_t global_cfg);
__dead2 void plat_arm_error_handler(int err);
__dead2 void plat_arm_system_reset(void);
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 4e9bdfc..e0a9076 100644
--- a/lib/cpus/errata_report.c
+++ b/lib/cpus/errata_report.c
@@ -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
*/
@@ -51,9 +51,9 @@
}
} else {
if (cve) {
- VERBOSE(CVE_FORMAT, BL_STRING, cpu_str, cve, id, "not applied");
+ VERBOSE(CVE_FORMAT, BL_STRING, cpu_str, cve, id, "not applicable");
} else {
- VERBOSE(ERRATUM_FORMAT, BL_STRING, cpu_str, id, "not applied");
+ VERBOSE(ERRATUM_FORMAT, BL_STRING, cpu_str, id, "not applicable");
}
}
}
@@ -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 1fce1bf..ab9d4b6 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -9,16 +9,56 @@
#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 */
+
.global prepare_el3_entry
.global restore_gp_pmcr_pauth_regs
- .global save_and_update_ptw_el1_sys_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)
@@ -35,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]
-
- mrs x9, fpsr
- str x9, [x0, #CTX_FP_FPSR]
+ 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 x10, fpcr
- str x10, [x0, #CTX_FP_FPCR]
+ fpregs_state_save x0, x9
-#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
@@ -80,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_AARCH32_REGS
- ldr x11, [x0, #CTX_FP_FPEXC32_EL2]
- msr fpexc32_el2, x11
-#endif /* CTX_INCLUDE_AARCH32_REGS */
+#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
- /*
- * No explict ISB required here as ERET to
- * switch to secure EL1 or non-secure world
- * covers it
- */
+.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
+
+/* ------------------------------------------------------------------
+ * 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
/*
@@ -138,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 */
@@ -162,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)
@@ -329,10 +505,12 @@
ret
endfunc restore_gp_pmcr_pauth_regs
-/*
+#if ERRATA_SPECULATIVE_AT
+/* --------------------------------------------------------------------
* In case of ERRATA_SPECULATIVE_AT, save SCTLR_EL1 and TCR_EL1
* registers and update EL1 registers to disable stage1 and stage2
- * page table walk
+ * page table walk.
+ * --------------------------------------------------------------------
*/
func save_and_update_ptw_el1_sys_regs
/* ----------------------------------------------------------
@@ -340,9 +518,9 @@
* ----------------------------------------------------------
*/
mrs x29, sctlr_el1
- str x29, [sp, #(CTX_EL1_SYSREGS_OFFSET + CTX_SCTLR_EL1)]
+ str x29, [sp, #(CTX_ERRATA_SPEC_AT_OFFSET + CTX_ERRATA_SPEC_AT_SCTLR_EL1)]
mrs x29, tcr_el1
- str x29, [sp, #(CTX_EL1_SYSREGS_OFFSET + CTX_TCR_EL1)]
+ str x29, [sp, #(CTX_ERRATA_SPEC_AT_OFFSET + CTX_ERRATA_SPEC_AT_TCR_EL1)]
/* ------------------------------------------------------------
* Must follow below order in order to disable page table
@@ -367,10 +545,11 @@
orr x29, x29, #SCTLR_M_BIT
msr sctlr_el1, x29
isb
-
ret
endfunc save_and_update_ptw_el1_sys_regs
+#endif /* ERRATA_SPECULATIVE_AT */
+
/* -----------------------------------------------------------------
* The below macro returns the address of the per_world context for
* the security state, retrieved through "get_security_state" macro.
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 981fddc..6f3b51a 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -19,11 +19,15 @@
#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>
#include <lib/extensions/amu.h>
#include <lib/extensions/brbe.h>
+#include <lib/extensions/debug_v8p9.h>
+#include <lib/extensions/fgt2.h>
#include <lib/extensions/mpam.h>
#include <lib/extensions/pmuv3.h>
#include <lib/extensions/sme.h>
@@ -47,6 +51,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;
@@ -90,8 +95,9 @@
*/
sctlr_elx |= SCTLR_IESB_BIT;
#endif
+
/* Store the initialised SCTLR_EL1 value in the cpu_context */
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_elx);
+ write_ctx_sctlr_el1_reg_errata(ctx, sctlr_elx);
/*
* Base the context ACTLR_EL1 on the current value, as it is
@@ -101,8 +107,9 @@
* be zero.
*/
actlr_elx = read_actlr_el1();
- write_ctx_reg((get_el1_sysregs_ctx(ctx)), (CTX_ACTLR_EL1), (actlr_elx));
+ 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
@@ -135,7 +142,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
@@ -151,7 +158,6 @@
if (!has_secure_perworld_init) {
manage_extensions_secure_per_world();
}
-
}
#if ENABLE_RME
@@ -255,11 +261,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.
@@ -292,8 +295,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);
}
@@ -324,7 +329,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);
/*
@@ -334,7 +339,13 @@
u_register_t icc_sre_el2_val = ICC_SRE_DIB_BIT | ICC_SRE_DFB_BIT |
ICC_SRE_EN_BIT | ICC_SRE_SRE_BIT;
write_el2_ctx_common(el2_ctx, icc_sre_el2, icc_sre_el2_val);
-#endif /* CTX_INCLUDE_EL2_REGS */
+
+ /*
+ * The actlr_el2 register can be initialized in platform's reset handler
+ * 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 && IMAGE_BL31) */
/* Start with a clean SCR_EL3 copy as all relevant values are set */
scr_el3 = SCR_RESET_VAL;
@@ -736,7 +747,7 @@
if (is_feat_trbe_supported()) {
/*
- * Enable FEAT_SPE for Non-Secure and prohibit for Secure and
+ * Enable FEAT_TRBE for Non-Secure and prohibit for Secure and
* Realm state.
*/
trbe_enable(ctx);
@@ -744,14 +755,14 @@
if (is_feat_trf_supported()) {
/*
- * Enable FEAT_SPE for Non-Secure and prohibit for Secure state.
+ * Enable FEAT_TRF for Non-Secure and prohibit for Secure state.
*/
trf_enable(ctx);
}
if (is_feat_brbe_supported()) {
/*
- * Enable FEAT_SPE for Non-Secure and prohibit for Secure state.
+ * Enable FEAT_BRBE for Non-Secure and prohibit for Secure state.
*/
brbe_enable(ctx);
}
@@ -772,6 +783,14 @@
sme_enable(ctx);
}
+ if (is_feat_fgt2_supported()) {
+ fgt2_enable(ctx);
+ }
+
+ if (is_feat_debugv8p9_supported()) {
+ debugv8p9_extended_bp_wp_enable(ctx);
+ }
+
pmuv3_enable(ctx);
#endif /* IMAGE_BL31 */
}
@@ -1068,11 +1087,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)
{
@@ -1098,6 +1120,24 @@
write_hfgwtr_el2(read_el2_ctx_fgt(ctx, hfgwtr_el2));
}
+static void el2_sysregs_context_save_fgt2(el2_sysregs_t *ctx)
+{
+ write_el2_ctx_fgt2(ctx, hdfgrtr2_el2, read_hdfgrtr2_el2());
+ write_el2_ctx_fgt2(ctx, hdfgwtr2_el2, read_hdfgwtr2_el2());
+ write_el2_ctx_fgt2(ctx, hfgitr2_el2, read_hfgitr2_el2());
+ write_el2_ctx_fgt2(ctx, hfgrtr2_el2, read_hfgrtr2_el2());
+ write_el2_ctx_fgt2(ctx, hfgwtr2_el2, read_hfgwtr2_el2());
+}
+
+static void el2_sysregs_context_restore_fgt2(el2_sysregs_t *ctx)
+{
+ write_hdfgrtr2_el2(read_el2_ctx_fgt2(ctx, hdfgrtr2_el2));
+ write_hdfgwtr2_el2(read_el2_ctx_fgt2(ctx, hdfgwtr2_el2));
+ write_hfgitr2_el2(read_el2_ctx_fgt2(ctx, hfgitr2_el2));
+ write_hfgrtr2_el2(read_el2_ctx_fgt2(ctx, hfgrtr2_el2));
+ write_hfgwtr2_el2(read_el2_ctx_fgt2(ctx, hfgwtr2_el2));
+}
+
static void el2_sysregs_context_save_mpam(el2_sysregs_t *ctx)
{
u_register_t mpam_idr = read_mpamidr_el1();
@@ -1337,6 +1377,10 @@
el2_sysregs_context_save_fgt(el2_sysregs_ctx);
}
+ if (is_feat_fgt2_supported()) {
+ el2_sysregs_context_save_fgt2(el2_sysregs_ctx);
+ }
+
if (is_feat_ecv_v2_supported()) {
write_el2_ctx_ecv(el2_sysregs_ctx, cntpoff_el2, read_cntpoff_el2());
}
@@ -1420,6 +1464,10 @@
el2_sysregs_context_restore_fgt(el2_sysregs_ctx);
}
+ if (is_feat_fgt2_supported()) {
+ el2_sysregs_context_restore_fgt2(el2_sysregs_ctx);
+ }
+
if (is_feat_ecv_v2_supported()) {
write_cntpoff_el2(read_el2_ctx_ecv(el2_sysregs_ctx, cntpoff_el2));
}
@@ -1473,8 +1521,47 @@
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)
+{
+#if ENABLE_SPE_FOR_NS == FEAT_STATE_CHECK_ASYMMETRIC
+ cpu_context_t *spe_ctx = cm_get_context(NON_SECURE);
+
+ assert(spe_ctx != NULL);
+
+ if (is_feat_spe_supported()) {
+ spe_enable(spe_ctx);
+ } else {
+ spe_disable(spe_ctx);
+ }
+#endif
+#if ERRATA_A520_2938996 || ERRATA_X4_2726228
+ cpu_context_t *trbe_ctx = cm_get_context(NON_SECURE);
+
+ assert(trbe_ctx != NULL);
+
+ if (check_if_affected_core() == ERRATA_APPLIES) {
+ if (is_feat_trbe_supported()) {
+ trbe_disable(trbe_ctx);
+ }
+ }
+#endif
}
-#endif /* CTX_INCLUDE_EL2_REGS */
+#endif
/*******************************************************************************
* This function is used to exit to Non-secure world. If CTX_INCLUDE_EL2_REGS
@@ -1484,7 +1571,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);
@@ -1495,237 +1594,212 @@
(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_ctx_reg(ctx, CTX_SPSR_EL1, read_spsr_el1());
- write_ctx_reg(ctx, CTX_ELR_EL1, read_elr_el1());
+ write_el1_ctx_common(ctx, spsr_el1, read_spsr_el1());
+ write_el1_ctx_common(ctx, elr_el1, read_elr_el1());
-#if !ERRATA_SPECULATIVE_AT
- write_ctx_reg(ctx, CTX_SCTLR_EL1, read_sctlr_el1());
- write_ctx_reg(ctx, CTX_TCR_EL1, read_tcr_el1());
+#if (!ERRATA_SPECULATIVE_AT)
+ write_el1_ctx_common(ctx, sctlr_el1, read_sctlr_el1());
+ write_el1_ctx_common(ctx, tcr_el1, read_tcr_el1());
#endif /* (!ERRATA_SPECULATIVE_AT) */
- write_ctx_reg(ctx, CTX_CPACR_EL1, read_cpacr_el1());
- write_ctx_reg(ctx, CTX_CSSELR_EL1, read_csselr_el1());
- write_ctx_reg(ctx, CTX_SP_EL1, read_sp_el1());
- write_ctx_reg(ctx, CTX_ESR_EL1, read_esr_el1());
- write_ctx_reg(ctx, CTX_TTBR0_EL1, read_ttbr0_el1());
- write_ctx_reg(ctx, CTX_TTBR1_EL1, read_ttbr1_el1());
- write_ctx_reg(ctx, CTX_MAIR_EL1, read_mair_el1());
- write_ctx_reg(ctx, CTX_AMAIR_EL1, read_amair_el1());
- write_ctx_reg(ctx, CTX_ACTLR_EL1, read_actlr_el1());
- write_ctx_reg(ctx, CTX_TPIDR_EL1, read_tpidr_el1());
- write_ctx_reg(ctx, CTX_TPIDR_EL0, read_tpidr_el0());
- write_ctx_reg(ctx, CTX_TPIDRRO_EL0, read_tpidrro_el0());
- write_ctx_reg(ctx, CTX_PAR_EL1, read_par_el1());
- write_ctx_reg(ctx, CTX_FAR_EL1, read_far_el1());
- write_ctx_reg(ctx, CTX_AFSR0_EL1, read_afsr0_el1());
- write_ctx_reg(ctx, CTX_AFSR1_EL1, read_afsr1_el1());
- write_ctx_reg(ctx, CTX_CONTEXTIDR_EL1, read_contextidr_el1());
- write_ctx_reg(ctx, CTX_VBAR_EL1, read_vbar_el1());
- write_ctx_reg(ctx, CTX_MDCCINT_EL1, read_mdccint_el1());
- write_ctx_reg(ctx, CTX_MDSCR_EL1, read_mdscr_el1());
+ write_el1_ctx_common(ctx, cpacr_el1, read_cpacr_el1());
+ write_el1_ctx_common(ctx, csselr_el1, read_csselr_el1());
+ write_el1_ctx_common(ctx, sp_el1, read_sp_el1());
+ write_el1_ctx_common(ctx, esr_el1, read_esr_el1());
+ write_el1_ctx_common(ctx, ttbr0_el1, read_ttbr0_el1());
+ write_el1_ctx_common(ctx, ttbr1_el1, read_ttbr1_el1());
+ write_el1_ctx_common(ctx, mair_el1, read_mair_el1());
+ write_el1_ctx_common(ctx, amair_el1, read_amair_el1());
+ write_el1_ctx_common(ctx, actlr_el1, read_actlr_el1());
+ write_el1_ctx_common(ctx, tpidr_el1, read_tpidr_el1());
+ write_el1_ctx_common(ctx, tpidr_el0, read_tpidr_el0());
+ write_el1_ctx_common(ctx, tpidrro_el0, read_tpidrro_el0());
+ write_el1_ctx_common(ctx, par_el1, read_par_el1());
+ write_el1_ctx_common(ctx, far_el1, read_far_el1());
+ write_el1_ctx_common(ctx, afsr0_el1, read_afsr0_el1());
+ write_el1_ctx_common(ctx, afsr1_el1, read_afsr1_el1());
+ write_el1_ctx_common(ctx, contextidr_el1, read_contextidr_el1());
+ write_el1_ctx_common(ctx, vbar_el1, read_vbar_el1());
+ write_el1_ctx_common(ctx, mdccint_el1, read_mdccint_el1());
+ write_el1_ctx_common(ctx, mdscr_el1, read_mdscr_el1());
-#if CTX_INCLUDE_AARCH32_REGS
- write_ctx_reg(ctx, CTX_SPSR_ABT, read_spsr_abt());
- write_ctx_reg(ctx, CTX_SPSR_UND, read_spsr_und());
- write_ctx_reg(ctx, CTX_SPSR_IRQ, read_spsr_irq());
- write_ctx_reg(ctx, CTX_SPSR_FIQ, read_spsr_fiq());
- write_ctx_reg(ctx, CTX_DACR32_EL2, read_dacr32_el2());
- write_ctx_reg(ctx, CTX_IFSR32_EL2, read_ifsr32_el2());
-#endif /* CTX_INCLUDE_AARCH32_REGS */
+ if (CTX_INCLUDE_AARCH32_REGS) {
+ /* Save Aarch32 registers */
+ write_el1_ctx_aarch32(ctx, spsr_abt, read_spsr_abt());
+ write_el1_ctx_aarch32(ctx, spsr_und, read_spsr_und());
+ write_el1_ctx_aarch32(ctx, spsr_irq, read_spsr_irq());
+ write_el1_ctx_aarch32(ctx, spsr_fiq, read_spsr_fiq());
+ write_el1_ctx_aarch32(ctx, dacr32_el2, read_dacr32_el2());
+ write_el1_ctx_aarch32(ctx, ifsr32_el2, read_ifsr32_el2());
+ }
-#if NS_TIMER_SWITCH
- write_ctx_reg(ctx, CTX_CNTP_CTL_EL0, read_cntp_ctl_el0());
- write_ctx_reg(ctx, CTX_CNTP_CVAL_EL0, read_cntp_cval_el0());
- write_ctx_reg(ctx, CTX_CNTV_CTL_EL0, read_cntv_ctl_el0());
- write_ctx_reg(ctx, CTX_CNTV_CVAL_EL0, read_cntv_cval_el0());
- write_ctx_reg(ctx, CTX_CNTKCTL_EL1, read_cntkctl_el1());
-#endif /* NS_TIMER_SWITCH */
+ if (NS_TIMER_SWITCH) {
+ /* Save NS Timer registers */
+ write_el1_ctx_arch_timer(ctx, cntp_ctl_el0, read_cntp_ctl_el0());
+ write_el1_ctx_arch_timer(ctx, cntp_cval_el0, read_cntp_cval_el0());
+ write_el1_ctx_arch_timer(ctx, cntv_ctl_el0, read_cntv_ctl_el0());
+ write_el1_ctx_arch_timer(ctx, cntv_cval_el0, read_cntv_cval_el0());
+ write_el1_ctx_arch_timer(ctx, cntkctl_el1, read_cntkctl_el1());
+ }
-#if ENABLE_FEAT_MTE2
- write_ctx_reg(ctx, CTX_TFSRE0_EL1, read_tfsre0_el1());
- write_ctx_reg(ctx, CTX_TFSR_EL1, read_tfsr_el1());
- write_ctx_reg(ctx, CTX_RGSR_EL1, read_rgsr_el1());
- write_ctx_reg(ctx, CTX_GCR_EL1, read_gcr_el1());
-#endif /* ENABLE_FEAT_MTE2 */
+ if (is_feat_mte2_supported()) {
+ write_el1_ctx_mte2(ctx, tfsre0_el1, read_tfsre0_el1());
+ write_el1_ctx_mte2(ctx, tfsr_el1, read_tfsr_el1());
+ write_el1_ctx_mte2(ctx, rgsr_el1, read_rgsr_el1());
+ write_el1_ctx_mte2(ctx, gcr_el1, read_gcr_el1());
+ }
-#if ENABLE_FEAT_RAS
if (is_feat_ras_supported()) {
- write_ctx_reg(ctx, CTX_DISR_EL1, read_disr_el1());
+ write_el1_ctx_ras(ctx, disr_el1, read_disr_el1());
}
-#endif
-#if ENABLE_FEAT_S1PIE
if (is_feat_s1pie_supported()) {
- write_ctx_reg(ctx, CTX_PIRE0_EL1, read_pire0_el1());
- write_ctx_reg(ctx, CTX_PIR_EL1, read_pir_el1());
+ write_el1_ctx_s1pie(ctx, pire0_el1, read_pire0_el1());
+ write_el1_ctx_s1pie(ctx, pir_el1, read_pir_el1());
}
-#endif
-#if ENABLE_FEAT_S1POE
if (is_feat_s1poe_supported()) {
- write_ctx_reg(ctx, CTX_POR_EL1, read_por_el1());
+ write_el1_ctx_s1poe(ctx, por_el1, read_por_el1());
}
-#endif
-#if ENABLE_FEAT_S2POE
if (is_feat_s2poe_supported()) {
- write_ctx_reg(ctx, CTX_S2POR_EL1, read_s2por_el1());
+ write_el1_ctx_s2poe(ctx, s2por_el1, read_s2por_el1());
}
-#endif
-#if ENABLE_FEAT_TCR2
if (is_feat_tcr2_supported()) {
- write_ctx_reg(ctx, CTX_TCR2_EL1, read_tcr2_el1());
+ write_el1_ctx_tcr2(ctx, tcr2_el1, read_tcr2_el1());
}
-#endif
-#if ENABLE_TRF_FOR_NS
if (is_feat_trf_supported()) {
- write_ctx_reg(ctx, CTX_TRFCR_EL1, read_trfcr_el1());
+ write_el1_ctx_trf(ctx, trfcr_el1, read_trfcr_el1());
}
-#endif
-#if ENABLE_FEAT_CSV2_2
if (is_feat_csv2_2_supported()) {
- write_ctx_reg(ctx, CTX_SCXTNUM_EL0, read_scxtnum_el0());
- write_ctx_reg(ctx, CTX_SCXTNUM_EL1, read_scxtnum_el1());
+ write_el1_ctx_csv2_2(ctx, scxtnum_el0, read_scxtnum_el0());
+ write_el1_ctx_csv2_2(ctx, scxtnum_el1, read_scxtnum_el1());
}
-#endif
-#if ENABLE_FEAT_GCS
if (is_feat_gcs_supported()) {
- write_ctx_reg(ctx, CTX_GCSCR_EL1, read_gcscr_el1());
- write_ctx_reg(ctx, CTX_GCSCRE0_EL1, read_gcscre0_el1());
- write_ctx_reg(ctx, CTX_GCSPR_EL1, read_gcspr_el1());
- write_ctx_reg(ctx, CTX_GCSPR_EL0, read_gcspr_el0());
+ write_el1_ctx_gcs(ctx, gcscr_el1, read_gcscr_el1());
+ write_el1_ctx_gcs(ctx, gcscre0_el1, read_gcscre0_el1());
+ write_el1_ctx_gcs(ctx, gcspr_el1, read_gcspr_el1());
+ write_el1_ctx_gcs(ctx, gcspr_el0, read_gcspr_el0());
}
-#endif
}
static void el1_sysregs_context_restore(el1_sysregs_t *ctx)
{
- write_spsr_el1(read_ctx_reg(ctx, CTX_SPSR_EL1));
- write_elr_el1(read_ctx_reg(ctx, CTX_ELR_EL1));
+ write_spsr_el1(read_el1_ctx_common(ctx, spsr_el1));
+ write_elr_el1(read_el1_ctx_common(ctx, elr_el1));
-#if !ERRATA_SPECULATIVE_AT
- write_sctlr_el1(read_ctx_reg(ctx, CTX_SCTLR_EL1));
- write_tcr_el1(read_ctx_reg(ctx, CTX_TCR_EL1));
+#if (!ERRATA_SPECULATIVE_AT)
+ write_sctlr_el1(read_el1_ctx_common(ctx, sctlr_el1));
+ write_tcr_el1(read_el1_ctx_common(ctx, tcr_el1));
#endif /* (!ERRATA_SPECULATIVE_AT) */
- write_cpacr_el1(read_ctx_reg(ctx, CTX_CPACR_EL1));
- write_csselr_el1(read_ctx_reg(ctx, CTX_CSSELR_EL1));
- write_sp_el1(read_ctx_reg(ctx, CTX_SP_EL1));
- write_esr_el1(read_ctx_reg(ctx, CTX_ESR_EL1));
- write_ttbr0_el1(read_ctx_reg(ctx, CTX_TTBR0_EL1));
- write_ttbr1_el1(read_ctx_reg(ctx, CTX_TTBR1_EL1));
- write_mair_el1(read_ctx_reg(ctx, CTX_MAIR_EL1));
- write_amair_el1(read_ctx_reg(ctx, CTX_AMAIR_EL1));
- write_actlr_el1(read_ctx_reg(ctx, CTX_ACTLR_EL1));
- write_tpidr_el1(read_ctx_reg(ctx, CTX_TPIDR_EL1));
- write_tpidr_el0(read_ctx_reg(ctx, CTX_TPIDR_EL0));
- write_tpidrro_el0(read_ctx_reg(ctx, CTX_TPIDRRO_EL0));
- write_par_el1(read_ctx_reg(ctx, CTX_PAR_EL1));
- write_far_el1(read_ctx_reg(ctx, CTX_FAR_EL1));
- write_afsr0_el1(read_ctx_reg(ctx, CTX_AFSR0_EL1));
- write_afsr1_el1(read_ctx_reg(ctx, CTX_AFSR1_EL1));
- write_contextidr_el1(read_ctx_reg(ctx, CTX_CONTEXTIDR_EL1));
- write_vbar_el1(read_ctx_reg(ctx, CTX_VBAR_EL1));
- write_mdccint_el1(read_ctx_reg(ctx, CTX_MDCCINT_EL1));
- write_mdscr_el1(read_ctx_reg(ctx, CTX_MDSCR_EL1));
+ write_cpacr_el1(read_el1_ctx_common(ctx, cpacr_el1));
+ write_csselr_el1(read_el1_ctx_common(ctx, csselr_el1));
+ write_sp_el1(read_el1_ctx_common(ctx, sp_el1));
+ write_esr_el1(read_el1_ctx_common(ctx, esr_el1));
+ write_ttbr0_el1(read_el1_ctx_common(ctx, ttbr0_el1));
+ write_ttbr1_el1(read_el1_ctx_common(ctx, ttbr1_el1));
+ write_mair_el1(read_el1_ctx_common(ctx, mair_el1));
+ write_amair_el1(read_el1_ctx_common(ctx, amair_el1));
+ write_actlr_el1(read_el1_ctx_common(ctx, actlr_el1));
+ write_tpidr_el1(read_el1_ctx_common(ctx, tpidr_el1));
+ write_tpidr_el0(read_el1_ctx_common(ctx, tpidr_el0));
+ write_tpidrro_el0(read_el1_ctx_common(ctx, tpidrro_el0));
+ write_par_el1(read_el1_ctx_common(ctx, par_el1));
+ write_far_el1(read_el1_ctx_common(ctx, far_el1));
+ write_afsr0_el1(read_el1_ctx_common(ctx, afsr0_el1));
+ write_afsr1_el1(read_el1_ctx_common(ctx, afsr1_el1));
+ write_contextidr_el1(read_el1_ctx_common(ctx, contextidr_el1));
+ write_vbar_el1(read_el1_ctx_common(ctx, vbar_el1));
+ write_mdccint_el1(read_el1_ctx_common(ctx, mdccint_el1));
+ write_mdscr_el1(read_el1_ctx_common(ctx, mdscr_el1));
-#if CTX_INCLUDE_AARCH32_REGS
- write_spsr_abt(read_ctx_reg(ctx, CTX_SPSR_ABT));
- write_spsr_und(read_ctx_reg(ctx, CTX_SPSR_UND));
- write_spsr_irq(read_ctx_reg(ctx, CTX_SPSR_IRQ));
- write_spsr_fiq(read_ctx_reg(ctx, CTX_SPSR_FIQ));
- write_dacr32_el2(read_ctx_reg(ctx, CTX_DACR32_EL2));
- write_ifsr32_el2(read_ctx_reg(ctx, CTX_IFSR32_EL2));
-#endif /* CTX_INCLUDE_AARCH32_REGS */
+ if (CTX_INCLUDE_AARCH32_REGS) {
+ /* Restore Aarch32 registers */
+ write_spsr_abt(read_el1_ctx_aarch32(ctx, spsr_abt));
+ write_spsr_und(read_el1_ctx_aarch32(ctx, spsr_und));
+ write_spsr_irq(read_el1_ctx_aarch32(ctx, spsr_irq));
+ write_spsr_fiq(read_el1_ctx_aarch32(ctx, spsr_fiq));
+ write_dacr32_el2(read_el1_ctx_aarch32(ctx, dacr32_el2));
+ write_ifsr32_el2(read_el1_ctx_aarch32(ctx, ifsr32_el2));
+ }
-#if NS_TIMER_SWITCH
- write_cntp_ctl_el0(read_ctx_reg(ctx, CTX_CNTP_CTL_EL0));
- write_cntp_cval_el0(read_ctx_reg(ctx, CTX_CNTP_CVAL_EL0));
- write_cntv_ctl_el0(read_ctx_reg(ctx, CTX_CNTV_CTL_EL0));
- write_cntv_cval_el0(read_ctx_reg(ctx, CTX_CNTV_CVAL_EL0));
- write_cntkctl_el1(read_ctx_reg(ctx, CTX_CNTKCTL_EL1));
-#endif /* NS_TIMER_SWITCH */
+ if (NS_TIMER_SWITCH) {
+ /* Restore NS Timer registers */
+ write_cntp_ctl_el0(read_el1_ctx_arch_timer(ctx, cntp_ctl_el0));
+ write_cntp_cval_el0(read_el1_ctx_arch_timer(ctx, cntp_cval_el0));
+ write_cntv_ctl_el0(read_el1_ctx_arch_timer(ctx, cntv_ctl_el0));
+ write_cntv_cval_el0(read_el1_ctx_arch_timer(ctx, cntv_cval_el0));
+ write_cntkctl_el1(read_el1_ctx_arch_timer(ctx, cntkctl_el1));
+ }
-#if ENABLE_FEAT_MTE2
- write_tfsre0_el1(read_ctx_reg(ctx, CTX_TFSRE0_EL1));
- write_tfsr_el1(read_ctx_reg(ctx, CTX_TFSR_EL1));
- write_rgsr_el1(read_ctx_reg(ctx, CTX_RGSR_EL1));
- write_gcr_el1(read_ctx_reg(ctx, CTX_GCR_EL1));
-#endif /* ENABLE_FEAT_MTE2 */
+ if (is_feat_mte2_supported()) {
+ write_tfsre0_el1(read_el1_ctx_mte2(ctx, tfsre0_el1));
+ write_tfsr_el1(read_el1_ctx_mte2(ctx, tfsr_el1));
+ write_rgsr_el1(read_el1_ctx_mte2(ctx, rgsr_el1));
+ write_gcr_el1(read_el1_ctx_mte2(ctx, gcr_el1));
+ }
-#if ENABLE_FEAT_RAS
if (is_feat_ras_supported()) {
- write_disr_el1(read_ctx_reg(ctx, CTX_DISR_EL1));
+ write_disr_el1(read_el1_ctx_ras(ctx, disr_el1));
}
-#endif
-#if ENABLE_FEAT_S1PIE
if (is_feat_s1pie_supported()) {
- write_pire0_el1(read_ctx_reg(ctx, CTX_PIRE0_EL1));
- write_pir_el1(read_ctx_reg(ctx, CTX_PIR_EL1));
+ write_pire0_el1(read_el1_ctx_s1pie(ctx, pire0_el1));
+ write_pir_el1(read_el1_ctx_s1pie(ctx, pir_el1));
}
-#endif
-#if ENABLE_FEAT_S1POE
if (is_feat_s1poe_supported()) {
- write_por_el1(read_ctx_reg(ctx, CTX_POR_EL1));
+ write_por_el1(read_el1_ctx_s1poe(ctx, por_el1));
}
-#endif
-#if ENABLE_FEAT_S2POE
if (is_feat_s2poe_supported()) {
- write_s2por_el1(read_ctx_reg(ctx, CTX_S2POR_EL1));
+ write_s2por_el1(read_el1_ctx_s2poe(ctx, s2por_el1));
}
-#endif
-#if ENABLE_FEAT_TCR2
if (is_feat_tcr2_supported()) {
- write_tcr2_el1(read_ctx_reg(ctx, CTX_TCR2_EL1));
+ write_tcr2_el1(read_el1_ctx_tcr2(ctx, tcr2_el1));
}
-#endif
-#if ENABLE_TRF_FOR_NS
if (is_feat_trf_supported()) {
- write_trfcr_el1(read_ctx_reg(ctx, CTX_TRFCR_EL1));
+ write_trfcr_el1(read_el1_ctx_trf(ctx, trfcr_el1));
}
-#endif
-#if ENABLE_FEAT_CSV2_2
if (is_feat_csv2_2_supported()) {
- write_scxtnum_el0(read_ctx_reg(ctx, CTX_SCXTNUM_EL0));
- write_scxtnum_el1(read_ctx_reg(ctx, CTX_SCXTNUM_EL1));
+ write_scxtnum_el0(read_el1_ctx_csv2_2(ctx, scxtnum_el0));
+ write_scxtnum_el1(read_el1_ctx_csv2_2(ctx, scxtnum_el1));
}
-#endif
-#if ENABLE_FEAT_GCS
if (is_feat_gcs_supported()) {
- write_gcscr_el1(read_ctx_reg(ctx, CTX_GCSCR_EL1));
- write_gcscre0_el1(read_ctx_reg(ctx, CTX_GCSCRE0_EL1));
- write_gcspr_el1(read_ctx_reg(ctx, CTX_GCSPR_EL1));
- write_gcspr_el0(read_ctx_reg(ctx, CTX_GCSPR_EL0));
+ write_gcscr_el1(read_el1_ctx_gcs(ctx, gcscr_el1));
+ write_gcscre0_el1(read_el1_ctx_gcs(ctx, gcscre0_el1));
+ write_gcspr_el1(read_el1_ctx_gcs(ctx, gcspr_el1));
+ write_gcspr_el0(read_el1_ctx_gcs(ctx, gcspr_el0));
}
-#endif
}
/*******************************************************************************
- * 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)
{
@@ -1761,6 +1835,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/debug/debugv8p9.c b/lib/extensions/debug/debugv8p9.c
new file mode 100644
index 0000000..f3cffa7
--- /dev/null
+++ b/lib/extensions/debug/debugv8p9.c
@@ -0,0 +1,26 @@
+/*
+ * 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/debug_v8p9.h>
+
+void debugv8p9_extended_bp_wp_enable(cpu_context_t *ctx)
+{
+ el3_state_t *state = get_el3state_ctx(ctx);
+ u_register_t mdcr_el3_val = read_ctx_reg(state, CTX_MDCR_EL3);
+
+ /* When FEAT_Debugv8p9 is implemented:
+ *
+ * MDCR_EL3.EBWE: Set to 0b1
+ * Enables use of additional breakpoints or watchpoints,
+ * and disables trap to EL3 on accesses to debug register.
+ */
+
+ mdcr_el3_val |= MDCR_EBWE_BIT;
+ write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
+}
diff --git a/lib/extensions/fgt/fgt2.c b/lib/extensions/fgt/fgt2.c
new file mode 100644
index 0000000..78f1a82
--- /dev/null
+++ b/lib/extensions/fgt/fgt2.c
@@ -0,0 +1,27 @@
+/*
+ * 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/fgt2.h>
+
+void fgt2_enable(cpu_context_t *context)
+{
+ u_register_t reg;
+ el3_state_t *state;
+
+ state = get_el3state_ctx(context);
+
+ /* Set the FGTEN2 bit in SCR_EL3 to enable access to HFGITR2_EL2,
+ * HFGRTR2_EL2, HFGWTR_EL2, HDFGRTR2_EL2, and HDFGWTR2_EL2.
+ */
+
+ reg = read_ctx_reg(state, CTX_SCR_EL3);
+ reg |= SCR_FGTEN2_BIT;
+ write_ctx_reg(state, CTX_SCR_EL3, reg);
+}
+
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/spe/spe.c b/lib/extensions/spe/spe.c
index c6076fe..d653222 100644
--- a/lib/extensions/spe/spe.c
+++ b/lib/extensions/spe/spe.c
@@ -52,6 +52,27 @@
write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
}
+void spe_disable(cpu_context_t *ctx)
+{
+ el3_state_t *state = get_el3state_ctx(ctx);
+ u_register_t mdcr_el3_val = read_ctx_reg(state, CTX_MDCR_EL3);
+
+ /*
+ * MDCR_EL3.NSPB: Clear these bits to disable SPE feature, as it was enabled
+ * for Non-secure state only. After clearing these bits Secure state owns
+ * the Profiling Buffer and accesses to Statistical Profiling and Profiling
+ * Buffer control registers at EL2 and EL1 generate Trap exceptions to EL3
+ *
+ * MDCR_EL3.NSPBE: Don't care as it was cleared during spe_enable and setting
+ * this to 1 does not make sense as NSPBE{1} and NSPB{0b0x} is RESERVED.
+ *
+ * MDCR_EL3.EnPMSN (ARM v8.7): Clear the bit to trap access of PMSNEVFR_EL1
+ * from EL2/EL1 to EL3.
+ */
+ mdcr_el3_val &= ~(MDCR_NSPB(MDCR_NSPB_EL1) | MDCR_EnPMSN_BIT);
+ write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
+}
+
void spe_init_el2_unused(void)
{
uint64_t v;
@@ -70,7 +91,7 @@
write_mdcr_el2(v);
}
-void spe_disable(void)
+void spe_stop(void)
{
uint64_t v;
diff --git a/lib/extensions/trbe/trbe.c b/lib/extensions/trbe/trbe.c
index 9157734..8c1c421 100644
--- a/lib/extensions/trbe/trbe.c
+++ b/lib/extensions/trbe/trbe.c
@@ -39,6 +39,25 @@
write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
}
+void trbe_disable(cpu_context_t *ctx)
+{
+ el3_state_t *state = get_el3state_ctx(ctx);
+ u_register_t mdcr_el3_val = read_ctx_reg(state, CTX_MDCR_EL3);
+
+ /*
+ * MDCR_EL3.NSTBE = 0b0
+ * Trace Buffer owning Security state is secure state. If FEAT_RME
+ * is not implemented, this field is RES0.
+ *
+ * MDCR_EL3.NSTB = 0b00
+ * Clear these bits to disable access of trace buffer control registers
+ * from lower ELs in any security state.
+ */
+ mdcr_el3_val &= ~(MDCR_NSTB(MDCR_NSTB_EL1));
+ mdcr_el3_val &= ~(MDCR_NSTBE_BIT);
+ write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
+}
+
void trbe_init_el2_unused(void)
{
/*
diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c
index 60449f6..375cdba 100644
--- a/lib/psci/psci_common.c
+++ b/lib/psci/psci_common.c
@@ -182,9 +182,9 @@
}
my_idx = plat_my_core_pos();
-
- for (lvl = PSCI_CPU_PWR_LVL; lvl <= end_pwrlvl; lvl++) {
- parent_idx = psci_cpu_pd_nodes[my_idx].parent_node;
+ parent_idx = psci_cpu_pd_nodes[my_idx].parent_node;
+ for (lvl = PSCI_CPU_PWR_LVL + U(1); lvl < end_pwrlvl; lvl++) {
+ parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node;
}
cpu_start_idx = psci_non_cpu_pd_nodes[parent_idx].cpu_start_idx;
@@ -1303,7 +1303,7 @@
* before exiting coherency.
*/
if (is_feat_spe_supported()) {
- spe_disable();
+ spe_stop();
}
}
diff --git a/lib/romlib/Makefile b/lib/romlib/Makefile
index 9ade331..29fbf78 100644
--- a/lib/romlib/Makefile
+++ b/lib/romlib/Makefile
@@ -10,6 +10,7 @@
toolchains := aarch64
endif
+include ../../make_helpers/build-rules.mk
include ../../make_helpers/common.mk
include ../../make_helpers/toolchain.mk
@@ -44,50 +45,54 @@
.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
+%.o: %.s | $$(@D)/
$(s)echo " AS $@"
$(q)$(aarch64-as) -c $(ASFLAGS) -o $@ $<
-$(BUILD_DIR)/%.o: %.s
+$(BUILD_DIR)/%.o: %.s | $$(@D)/
$(s)echo " AS $@"
$(q)$(aarch64-as) -c $(ASFLAGS) -o $@ $<
-$(BUILD_DIR)/romlib.ld: romlib.ld.S
+$(BUILD_DIR)/romlib.ld: romlib.ld.S | $$(@D)/
$(s)echo " PP $@"
$(q)$(aarch64-cpp) -E $(PPFLAGS) -o $@ romlib.ld.S
-$(BUILD_DIR)/romlib.elf: $(OBJS) $(BUILD_DIR)/romlib.ld
+$(BUILD_DIR)/romlib.elf: $(OBJS) $(BUILD_DIR)/romlib.ld | $$(@D)/
$(s)echo " LD $@"
$(q)$(aarch64-ld) -T $(BUILD_DIR)/romlib.ld -L$(LIB_DIR) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
-$(BUILD_DIR)/romlib.bin: $(BUILD_DIR)/romlib.elf
+$(BUILD_DIR)/romlib.bin: $(BUILD_DIR)/romlib.elf | $$(@D)/
$(s)echo " BIN $@"
$(q)$(aarch64-oc) -O binary $(BUILD_DIR)/romlib.elf $@
-$(WRAPPER_DIR)/jmpvar.s: $(BUILD_DIR)/romlib.elf
+$(WRAPPER_DIR)/jmpvar.s: $(BUILD_DIR)/romlib.elf | $$(@D)/
$(s)echo " VAR $@"
$(q)$(ROMLIB_GEN) genvar --output $@ $<
-$(LIB_DIR)/libwrappers.a: $(WRAPPER_DIR)/jmpvar.o $(WRAPPER_OBJS)
+$(LIB_DIR)/libwrappers.a: $(WRAPPER_DIR)/jmpvar.o $(WRAPPER_OBJS) | $$(@D)/
$(s)echo " AR $@"
$(q)$(aarch64-ar) -rc $@ $(WRAPPER_DIR)/jmpvar.o $(WRAPPER_OBJS)
-$(BUILD_DIR)/jmptbl.i: ../../$(PLAT_DIR)/jmptbl.i
+$(BUILD_DIR)/jmptbl.i: ../../$(PLAT_DIR)/jmptbl.i | $$(@D)/
$(s)echo " PRE $@"
$(q)$(ROMLIB_GEN) pre --output $@ --deps $(BUILD_DIR)/jmptbl.d $<
-$(WRAPPER_SOURCES) &: $(BUILD_DIR)/jmptbl.i
+$(WRAPPER_SOURCES) &: $(BUILD_DIR)/jmptbl.i | $$(@D)/
$(s)echo " WRP $<"
$(q)$(ROMLIB_GEN) genwrappers --bti=$(ENABLE_BTI) -b $(WRAPPER_DIR) $<
-$(WRAPPER_OBJS): $(WRAPPER_DIR)/%.o: $(WRAPPER_DIR)/%.s
+$(WRAPPER_OBJS): $(WRAPPER_DIR)/%.o: $(WRAPPER_DIR)/%.s | $$(@D)/
-$(BUILD_DIR)/jmptbl.s: $(BUILD_DIR)/jmptbl.i
+$(BUILD_DIR)/jmptbl.s: $(BUILD_DIR)/jmptbl.i | $$(@D)/
$(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/lib/transfer_list/transfer_list.c b/lib/transfer_list/transfer_list.c
index b7fedfa..8d82d25 100644
--- a/lib/transfer_list/transfer_list.c
+++ b/lib/transfer_list/transfer_list.c
@@ -63,20 +63,21 @@
te = transfer_list_find(tl, TL_TAG_FDT);
dt = transfer_list_entry_data(te);
- ep_info->args.arg1 = TRANSFER_LIST_SIGNATURE |
- REGISTER_CONVENTION_VERSION_MASK;
- ep_info->args.arg3 = (uintptr_t)tl;
-
- if (GET_RW(ep_info->spsr) == MODE_RW_32) {
- /* aarch32 */
- ep_info->args.arg0 = 0;
- ep_info->args.arg2 = (uintptr_t)dt;
- } else {
- /* aarch64 */
+#ifdef __aarch64__
+ if (GET_RW(ep_info->spsr) == MODE_RW_64) {
ep_info->args.arg0 = (uintptr_t)dt;
+ ep_info->args.arg1 = TRANSFER_LIST_HANDOFF_X1_VALUE(REGISTER_CONVENTION_VERSION);
ep_info->args.arg2 = 0;
+ } else
+#endif
+ {
+ ep_info->args.arg0 = 0;
+ ep_info->args.arg1 = TRANSFER_LIST_HANDOFF_R1_VALUE(REGISTER_CONVENTION_VERSION);
+ ep_info->args.arg2 = (uintptr_t)dt;
}
+ ep_info->args.arg3 = (uintptr_t)tl;
+
return ep_info;
}
diff --git a/lib/xlat_tables_v2/xlat_tables_utils.c b/lib/xlat_tables_v2/xlat_tables_utils.c
index f3a53cc..a3b913c 100644
--- a/lib/xlat_tables_v2/xlat_tables_utils.c
+++ b/lib/xlat_tables_v2/xlat_tables_utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2021, 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 <platform_def.h>
+#include <arch_features.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <lib/utils_def.h>
@@ -419,10 +420,59 @@
*attributes |= MT_USER;
}
- uint64_t ns_bit = (desc >> NS_SHIFT) & 1U;
+ uint64_t ns_bit = (desc >> NS_SHIFT) & 1ULL;
- if (ns_bit == 1U)
+#if ENABLE_RME
+ uint64_t nse_bit = (desc >> NSE_SHIFT) & 1ULL;
+ uint32_t sec_state = (uint32_t)(ns_bit | (nse_bit << 1ULL));
+
+/*
+ * =========================================================
+ * NSE NS | Output PA space
+ * =========================================================
+ * 0 0 | Secure (if S-EL2 is present, else invalid)
+ * 0 1 | Non-secure
+ * 1 0 | Root
+ * 1 1 | Realm
+ *==========================================================
+ */
+ switch (sec_state) {
+ case 0U:
+ /*
+ * We expect to get Secure mapping on an RME system only if
+ * S-EL2 is enabled.
+ * Hence panic() if we hit the case without EEL2 being enabled.
+ */
+ if ((read_scr_el3() & SCR_EEL2_BIT) == 0ULL) {
+ ERROR("A secure descriptor is not supported when"
+ "FEAT_RME is implemented and FEAT_SEL2 is"
+ "not enabled\n");
+ panic();
+ } else {
+ *attributes |= MT_SECURE;
+ }
+ break;
+ case 1U:
*attributes |= MT_NS;
+ break;
+ case 2U:
+ *attributes |= MT_ROOT;
+ break;
+ case 3U:
+ *attributes |= MT_REALM;
+ break;
+ default:
+ /* unreachable code */
+ assert(false);
+ break;
+ }
+#else /* !ENABLE_RME */
+ if (ns_bit == 1ULL) {
+ *attributes |= MT_NS;
+ } else {
+ *attributes |= MT_SECURE;
+ }
+#endif /* ENABLE_RME */
uint64_t xn_mask = xlat_arch_regime_get_xn_desc(ctx->xlat_regime);
diff --git a/make_helpers/arch_features.mk b/make_helpers/arch_features.mk
index ac47960..ceff4ba 100644
--- a/make_helpers/arch_features.mk
+++ b/make_helpers/arch_features.mk
@@ -90,7 +90,7 @@
# Enable the features which are mandatory from ARCH version 8.9 and upwards.
ifeq "8.9" "$(word 1, $(sort 8.9 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))"
-armv8-9-a-feats := ENABLE_FEAT_TCR2
+armv8-9-a-feats := ENABLE_FEAT_TCR2 ENABLE_FEAT_DEBUGV8P9
# 8.8 Compliant
armv8-9-a-feats += ${armv8-8-a-feats}
FEAT_LIST := ${armv8-9-a-feats}
@@ -280,7 +280,7 @@
ENABLE_FEAT_AMU ?= 0
ENABLE_AMU_AUXILIARY_COUNTERS ?= 0
ENABLE_AMU_FCONF ?= 0
-AMU_RESTRICT_COUNTERS ?= 0
+AMU_RESTRICT_COUNTERS ?= 1
# Build option to enable MPAM for lower ELs.
# Enabling it by default
@@ -337,6 +337,9 @@
# Disable MTPMU if FEAT_MTPMU is supported.
DISABLE_MTPMU ?= 0
+# Flag to enable FEAT_FGT2 (Fine Granular Traps 2)
+ENABLE_FEAT_FGT2 ?= 0
+
#----
# 8.9
#----
@@ -353,6 +356,9 @@
# Flag to enable access to Stage 1 Permission Overlay (FEAT_S1POE).
ENABLE_FEAT_S1POE ?= 0
+# Flag to enable access to Arm v8.9 Debug extension
+ENABLE_FEAT_DEBUGV8P9 ?= 0
+
#----
# 9.0
#----
diff --git a/make_helpers/build-rules.mk b/make_helpers/build-rules.mk
new file mode 100644
index 0000000..d325b3a
--- /dev/null
+++ b/make_helpers/build-rules.mk
@@ -0,0 +1,18 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+ifndef build-rules-mk
+ build-rules-mk := $(lastword $(MAKEFILE_LIST))
+
+ include $(dir $(build-rules-mk))common.mk
+ include $(dir $(build-rules-mk))utilities.mk
+
+ .SECONDEXPANSION:
+
+ %/:
+ $(s)echo ' MD '$(call escape-shell,$(abspath $@))
+ $(q)mkdir -p $(call escape-shell,$@)
+endif
diff --git a/make_helpers/build_env.mk b/make_helpers/build_env.mk
index a545cd0..13acaae 100644
--- a/make_helpers/build_env.mk
+++ b/make_helpers/build_env.mk
@@ -15,8 +15,6 @@
COPY := $$(error "Replace COPY with call to SHELL_COPY or SHELL_COPY_TREE.")
CP := $$(error "Replace CP with call to SHELL_COPY or SHELL_COPY_TREE.")
DEL := $$(error "Replace DEL with call to SHELL_DELETE.")
- MD := $$(error "Replace MD with call to MAKE_PREREQ_DIR.")
- MKDIR := $$(error "Replace MKDIR with call to MAKE_PREREQ_DIR.")
RD := $$(error "Replace RD with call to SHELL_REMOVE_DIR.")
RM := $$(error "Replace RM with call to SHELL_DELETE.")
RMDIR := $$(error "Replace RMDIR with call to SHELL_REMOVE_DIR.")
@@ -62,9 +60,6 @@
ifndef SHELL_DELETE
$(error "SHELL_DELETE not defined for build environment.")
endif
- ifndef MAKE_PREREQ_DIR
- $(error "MAKE_PREREQ_DIR not defined for build environment.")
- endif
ifndef SHELL_REMOVE_DIR
$(error "SHELL_REMOVE_DIR not defined for build environment.")
endif
diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk
index d27408c..f523074 100644
--- a/make_helpers/build_macros.mk
+++ b/make_helpers/build_macros.mk
@@ -289,7 +289,7 @@
$(eval DEP := $(patsubst %.o,%.d,$(OBJ)))
$(eval LIB := $(call uppercase, $(notdir $(1))))
-$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | lib$(3)_dirs
+$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $$$$(@D)/
$$(s)echo " CC $$<"
$$(q)$($(ARCH)-cc) $$($(LIB)_CFLAGS) $$(TF_CFLAGS) $$(CFLAGS) $(MAKE_DEP) -c $$< -o $$@
@@ -305,7 +305,7 @@
$(eval OBJ := $(1)/$(patsubst %.S,%.o,$(notdir $(2))))
$(eval DEP := $(patsubst %.o,%.d,$(OBJ)))
-$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | lib$(3)_dirs
+$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $$$$(@D)/
$$(s)echo " AS $$<"
$$(q)$($(ARCH)-as) -x assembler-with-cpp $$(TF_CFLAGS_$(ARCH)) $$(ASFLAGS) $(MAKE_DEP) -c $$< -o $$@
@@ -328,7 +328,7 @@
$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) $(addprefix -D,$(BL_DEFINES)) $(addprefix -I,$(BL_INCLUDE_DIRS)) $(PLAT_BL_COMMON_CPPFLAGS))
$(eval BL_CFLAGS := $($(call uppercase,$(3))_CFLAGS) $(PLAT_BL_COMMON_CFLAGS))
-$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs
+$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $$$$(@D)/
$$(s)echo " CC $$<"
$$(q)$($(ARCH)-cc) $$(LTO_CFLAGS) $$(TF_CFLAGS) $$(CFLAGS) $(BL_CPPFLAGS) $(BL_CFLAGS) $(MAKE_DEP) -c $$< -o $$@
@@ -351,7 +351,7 @@
$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) $(addprefix -D,$(BL_DEFINES)) $(addprefix -I,$(BL_INCLUDE_DIRS)) $(PLAT_BL_COMMON_CPPFLAGS))
$(eval BL_ASFLAGS := $($(call uppercase,$(3))_ASFLAGS) $(PLAT_BL_COMMON_ASFLAGS))
-$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs
+$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $$$$(@D)/
$$(s)echo " AS $$<"
$$(q)$($(ARCH)-as) -x assembler-with-cpp $$(TF_CFLAGS_$(ARCH)) $$(ASFLAGS) $(BL_CPPFLAGS) $(BL_ASFLAGS) $(MAKE_DEP) -c $$< -o $$@
@@ -372,7 +372,7 @@
$(eval BL_INCLUDE_DIRS := $($(call uppercase,$(3))_INCLUDE_DIRS) $(PLAT_BL_COMMON_INCLUDE_DIRS))
$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) $(addprefix -D,$(BL_DEFINES)) $(addprefix -I,$(BL_INCLUDE_DIRS)) $(PLAT_BL_COMMON_CPPFLAGS))
-$(1): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs
+$(1): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $$$$(@D)/
$$(s)echo " PP $$<"
$$(q)$($(ARCH)-cpp) -E $$(CPPFLAGS) $(BL_CPPFLAGS) $(TF_CFLAGS_$(ARCH)) -P -x assembler-with-cpp -D__LINKER__ $(MAKE_DEP) -o $$@ $$<
@@ -424,17 +424,6 @@
.PHONY: libraries
-# MAKE_LIB_DIRS macro defines the target for the directory where
-# libraries are created
-define MAKE_LIB_DIRS
- $(eval LIB_DIR := ${BUILD_PLAT}/lib)
- $(eval ROMLIB_DIR := ${BUILD_PLAT}/romlib)
- $(eval LIBWRAPPER_DIR := ${BUILD_PLAT}/libwrapper)
- $(eval $(call MAKE_PREREQ_DIR,${LIB_DIR},${BUILD_PLAT}))
- $(eval $(call MAKE_PREREQ_DIR,${ROMLIB_DIR},${BUILD_PLAT}))
- $(eval $(call MAKE_PREREQ_DIR,${LIBWRAPPER_DIR},${BUILD_PLAT}))
-endef
-
# MAKE_LIB macro defines the targets and options to build each BL image.
# Arguments:
# $(1) = Library name
@@ -445,11 +434,8 @@
$(eval SOURCES := $(LIB$(call uppercase,$(1))_SRCS))
$(eval OBJS := $(addprefix $(BUILD_DIR)/,$(call SOURCES_TO_OBJS,$(SOURCES))))
-$(eval $(call MAKE_PREREQ_DIR,${BUILD_DIR},${BUILD_PLAT}))
$(eval $(call MAKE_LIB_OBJS,$(BUILD_DIR),$(SOURCES),$(1)))
-.PHONY : lib${1}_dirs
-lib${1}_dirs: | ${BUILD_DIR} ${LIB_DIR} ${ROMLIB_DIR} ${LIBWRAPPER_DIR}
libraries: ${LIB_DIR}/lib$(1).a
ifeq ($($(ARCH)-ld-id),arm-link)
LDPATHS = --userlibpath=${LIB_DIR}
@@ -465,7 +451,7 @@
all: ${LIB_DIR}/lib$(1).a
-${LIB_DIR}/lib$(1).a: $(OBJS)
+${LIB_DIR}/lib$(1).a: $(OBJS) | $$$$(@D)/
$$(s)echo " AR $$@"
$$(q)$($(ARCH)-ar) cr $$@ $$?
endef
@@ -479,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
@@ -503,26 +493,6 @@
$(eval LINKER_SCRIPT_SOURCES := $($(call uppercase,$(1))_LINKER_SCRIPT_SOURCES))
$(eval LINKER_SCRIPTS := $(call linker_script_path,$(LINKER_SCRIPT_SOURCES)))
- # We use sort only to get a list of unique object directory names.
- # ordering is not relevant but sort removes duplicates.
- $(eval TEMP_OBJ_DIRS := $(sort $(dir ${OBJS} ${DEFAULT_LINKER_SCRIPT} ${LINKER_SCRIPTS})))
- # The $(dir ) function leaves a trailing / on the directory names
- # Rip off the / to match directory names with make rule targets.
- $(eval OBJ_DIRS := $(patsubst %/,%,$(TEMP_OBJ_DIRS)))
-
-# Create generators for object directory structure
-
-$(eval $(call MAKE_PREREQ_DIR,${BUILD_DIR},${BUILD_PLAT}))
-
-$(eval $(foreach objd,${OBJ_DIRS},
- $(call MAKE_PREREQ_DIR,${objd},${BUILD_DIR})))
-
-.PHONY : ${1}_dirs
-
-# We use order-only prerequisites to ensure that directories are created,
-# but do not cause re-builds every time a file is written.
-${1}_dirs: | ${OBJ_DIRS}
-
$(eval $(call MAKE_OBJS,$(BUILD_DIR),$(SOURCES),$(1)))
# Generate targets to preprocess each required linker script
@@ -532,14 +502,14 @@
$(eval BL_LDFLAGS := $($(call uppercase,$(1))_LDFLAGS))
ifeq ($(USE_ROMLIB),1)
-$(ELF): romlib.bin
+$(ELF): romlib.bin | $$$$(@D)/
endif
# MODULE_OBJS can be assigned by vendors with different compiled
# object file path, and prebuilt object file path.
$(eval OBJS += $(MODULE_OBJS))
-$(ELF): $(OBJS) $(DEFAULT_LINKER_SCRIPT) $(LINKER_SCRIPTS) | $(1)_dirs libraries $(BL_LIBS)
+$(ELF): $(OBJS) $(DEFAULT_LINKER_SCRIPT) $(LINKER_SCRIPTS) | $$$$(@D)/ libraries $(BL_LIBS)
$$(s)echo " LD $$@"
ifeq ($($(ARCH)-ld-id),arm-link)
$$(q)$($(ARCH)-ld) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) $(BL_LDFLAGS) --entry=${1}_entrypoint \
@@ -548,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
@@ -562,11 +532,11 @@
$(s)echo
endif
-$(DUMP): $(ELF)
+$(DUMP): $(ELF) | $$$$(@D)/
$$(s)echo " OD $$@"
$$(q)$($(ARCH)-od) -dx $$< > $$@
-$(BIN): $(ELF)
+$(BIN): $(ELF) | $$$$(@D)/
$$(s)echo " BIN $$@"
$$(q)$($(ARCH)-oc) -O binary $$< $$@
$(s)echo
@@ -598,22 +568,6 @@
$(notdir $(patsubst %.dts,%.dtb,$(filter %.dts,$(1))))
endef
-# MAKE_FDT_DIRS macro creates the prerequisite directories that host the
-# FDT binaries
-# $(1) = output directory
-# $(2) = input dts
-define MAKE_FDT_DIRS
- $(eval DTBS := $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2))))
- $(eval TEMP_DTB_DIRS := $(sort $(dir ${DTBS})))
- # The $(dir ) function leaves a trailing / on the directory names
- # Rip off the / to match directory names with make rule targets.
- $(eval DTB_DIRS := $(patsubst %/,%,$(TEMP_DTB_DIRS)))
-
-$(eval $(foreach objd,${DTB_DIRS},$(call MAKE_PREREQ_DIR,${objd},${BUILD_DIR})))
-
-fdt_dirs: ${DTB_DIRS}
-endef
-
# MAKE_DTB generate the Flattened device tree binary
# $(1) = output directory
# $(2) = input dts
@@ -628,12 +582,12 @@
# Dependencies of the DT compilation on its pre-compiled DTS
$(eval DTBDEP := $(patsubst %.dtb,%.d,$(DOBJ)))
-$(DPRE): $(2) | fdt_dirs
+$(DPRE): $(2) | $$$$(@D)/
$$(s)echo " CPP $$<"
$(eval DTBS := $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2))))
$$(q)$($(ARCH)-cpp) -E $$(TF_CFLAGS_$(ARCH)) $$(DTC_CPPFLAGS) -MT $(DTBS) -MMD -MF $(DTSDEP) -o $(DPRE) $$<
-$(DOBJ): $(DPRE) $(filter-out %.d,$(MAKEFILE_LIST)) | fdt_dirs
+$(DOBJ): $(DPRE) $(filter-out %.d,$(MAKEFILE_LIST)) | $$$$(@D)/
$$(s)echo " DTC $$<"
$$(q)$($(ARCH)-dtc) $$(DTC_FLAGS) -d $(DTBDEP) -o $$@ $$<
@@ -651,8 +605,6 @@
$(and $(REMAIN),$(error FDT_SOURCES contain non-DTS files: $(REMAIN)))
$(eval $(foreach obj,$(DOBJS),$(call MAKE_DTB,$(1),$(obj))))
- $(eval $(call MAKE_FDT_DIRS,$(1),$(2)))
-
-dtbs: $(DTBS)
+dtbs: $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2)))
all: dtbs
endef
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 368d26d..290a6fe 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
@@ -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/unix.mk b/make_helpers/unix.mk
index 4fd819a..fa7722a 100644
--- a/make_helpers/unix.mk
+++ b/make_helpers/unix.mk
@@ -38,18 +38,6 @@
-$(q)rm -rf ${1}
endef
- # ${1} is the directory to be generated.
- # ${2} is optional, and allows a prerequisite to be specified.
- # Do nothing if $1 == $2, to ignore self dependencies.
- define MAKE_PREREQ_DIR
- ifneq (${1},${2})
-
-${1} : ${2}
- $(q)mkdir -p "${1}"
-
- endif
- endef
-
define SHELL_REMOVE_DIR
-$(q)rm -rf "${1}"
endef
diff --git a/make_helpers/windows.mk b/make_helpers/windows.mk
index 2f5d51b..c24aa08 100644
--- a/make_helpers/windows.mk
+++ b/make_helpers/windows.mk
@@ -47,19 +47,6 @@
$(eval $(foreach filename,$(wildcard ${1}),$(call DELETE_IF_THERE,${filename})))
endef
- # ${1} is the directory to be generated.
- # ${2} is optional, and allows prerequisites to be specified.
- # Do nothing if $1 == $2, to ignore self dependencies.
- define MAKE_PREREQ_DIR
- ifneq (${1},${2})
-
-${1} : ${2}
- $(eval tmp_dir:=$(subst /,\,${1}))
- -@if not exist "$(tmp_dir)" mkdir "${tmp_dir}"
-
- endif
- endef
-
# ${1} is the directory to be removed.
define SHELL_REMOVE_DIR
$(eval tmp_dir:=$(subst /,\,${1}))
diff --git a/package-lock.json b/package-lock.json
index a6bb905..26caae4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1172,12 +1172,12 @@
}
},
"node_modules/braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"dependencies": {
- "fill-range": "^7.0.1"
+ "fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
@@ -2395,9 +2395,9 @@
}
},
"node_modules/fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
@@ -4903,7 +4903,7 @@
}
},
"tools/conventional-changelog-tf-a": {
- "version": "2.10.0",
+ "version": "2.11.0",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
diff --git a/plat/allwinner/common/include/sunxi_private.h b/plat/allwinner/common/include/sunxi_private.h
index 6a38657..b9ca3f6 100644
--- a/plat/allwinner/common/include/sunxi_private.h
+++ b/plat/allwinner/common/include/sunxi_private.h
@@ -58,4 +58,12 @@
}
#endif
+#ifdef PLAT_sun50i_h616
+void sunxi_soc_fdt_fixup(void *dtb);
+#else
+static inline void sunxi_soc_fdt_fixup(void *dtb)
+{
+}
+#endif
+
#endif /* SUNXI_PRIVATE_H */
diff --git a/plat/allwinner/common/sunxi_prepare_dtb.c b/plat/allwinner/common/sunxi_prepare_dtb.c
index 66af35a..0f68974 100644
--- a/plat/allwinner/common/sunxi_prepare_dtb.c
+++ b/plat/allwinner/common/sunxi_prepare_dtb.c
@@ -34,6 +34,8 @@
}
#endif
+ sunxi_soc_fdt_fixup(fdt);
+
if (sunxi_psci_is_scpi()) {
ret = fdt_add_cpu_idle_states(fdt, sunxi_idle_states);
if (ret < 0) {
diff --git a/plat/allwinner/sun50i_h616/platform.mk b/plat/allwinner/sun50i_h616/platform.mk
index de494a2..6f44e8c 100644
--- a/plat/allwinner/sun50i_h616/platform.mk
+++ b/plat/allwinner/sun50i_h616/platform.mk
@@ -18,5 +18,8 @@
$(error "H616 does not support SCPI PSCI ops")
endif
-BL31_SOURCES += drivers/allwinner/axp/axp805.c \
+BL31_SOURCES += common/fdt_wrappers.c \
+ drivers/allwinner/axp/axp805.c \
drivers/allwinner/sunxi_rsb.c \
+ drivers/mentor/i2c/mi2cv.c \
+ ${AW_PLAT}/${PLAT}/sunxi_h616_dtb.c
diff --git a/plat/allwinner/sun50i_h616/sunxi_h616_dtb.c b/plat/allwinner/sun50i_h616/sunxi_h616_dtb.c
new file mode 100644
index 0000000..58bad53
--- /dev/null
+++ b/plat/allwinner/sun50i_h616/sunxi_h616_dtb.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2024, ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Amend the device tree to adjust the L2 cache size, which is different
+ * between the revisions of the H616 chips: earlier versions have 256 KB of L2,
+ * later versions 1 MB.
+ * Read the cache ID registers and adjust the size and number of sets entries
+ * in the L2 cache DT node.
+ */
+
+#include <common/fdt_wrappers.h>
+#include <lib/utils_def.h>
+#include <libfdt.h>
+
+#define CACHE_L1D 0x0
+#define CACHE_L1I 0x1
+#define CACHE_L2U 0x2
+
+#define CCSIDR_SETS_SHIFT 13
+#define CCSIDR_SETS_MASK GENMASK(14, 0)
+#define CCSIDR_ASSOC_SHIFT 3
+#define CCSIDR_ASSOC_MASK GENMASK(9, 0)
+#define CCSIDR_LSIZE_SHIFT 0
+#define CCSIDR_LSIZE_MASK GENMASK(2, 0)
+
+static uint32_t armv8_get_ccsidr(unsigned int sel)
+{
+ uint32_t reg;
+
+ __asm__ volatile ("msr CSSELR_EL1, %0\n" :: "r" (sel));
+ __asm__ volatile ("mrs %0, CCSIDR_EL1\n" : "=r" (reg));
+
+ return reg;
+}
+
+void sunxi_soc_fdt_fixup(void *dtb)
+{
+ int node = fdt_path_offset(dtb, "/cpus/cpu@0");
+ uint32_t phandle, ccsidr, cell;
+ int sets, line_size, assoc;
+ int ret;
+
+ if (node < 0) {
+ return;
+ }
+
+ ret = fdt_read_uint32(dtb, node, "next-level-cache", &phandle);
+ if (ret != 0) {
+ return;
+ }
+
+ node = fdt_node_offset_by_phandle(dtb, phandle);
+ if (node < 0) {
+ return;
+ }
+
+ ccsidr = armv8_get_ccsidr(CACHE_L2U);
+ sets = ((ccsidr >> CCSIDR_SETS_SHIFT) & CCSIDR_SETS_MASK) + 1;
+ line_size = 16U << ((ccsidr >> CCSIDR_LSIZE_SHIFT) & CCSIDR_LSIZE_MASK);
+ assoc = ((ccsidr >> CCSIDR_ASSOC_SHIFT) & CCSIDR_ASSOC_MASK) + 1;
+
+ cell = cpu_to_fdt32(sets);
+ fdt_setprop(dtb, node, "cache-sets", &cell, sizeof(cell));
+
+ cell = cpu_to_fdt32(line_size);
+ fdt_setprop(dtb, node, "cache-line-size", &cell, sizeof(cell));
+
+ cell = cpu_to_fdt32(sets * assoc * line_size);
+ fdt_setprop(dtb, node, "cache-size", &cell, sizeof(cell));
+}
diff --git a/plat/allwinner/sun50i_h616/sunxi_power.c b/plat/allwinner/sun50i_h616/sunxi_power.c
index dd6ebba..cab7e46 100644
--- a/plat/allwinner/sun50i_h616/sunxi_power.c
+++ b/plat/allwinner/sun50i_h616/sunxi_power.c
@@ -10,97 +10,254 @@
#include <arch_helpers.h>
#include <common/debug.h>
+#include <common/fdt_wrappers.h>
#include <drivers/allwinner/axp.h>
#include <drivers/allwinner/sunxi_rsb.h>
+#include <drivers/mentor/mi2cv.h>
#include <lib/mmio.h>
+#include <libfdt.h>
#include <sunxi_cpucfg.h>
#include <sunxi_def.h>
#include <sunxi_mmap.h>
#include <sunxi_private.h>
-#define AXP305_I2C_ADDR 0x36
-#define AXP305_HW_ADDR 0x745
-#define AXP305_RT_ADDR 0x3a
+static uint16_t pmic_bus_addr;
+static uint8_t rsb_rt_addr;
+
+static bool is_using_rsb(void)
+{
+ return rsb_rt_addr != 0;
+}
static enum pmic_type {
UNKNOWN,
AXP305,
+ AXP313,
+ AXP717,
} pmic;
+static uint8_t get_rsb_rt_address(uint16_t hw_addr)
+{
+ switch (hw_addr) {
+ case 0x3a3: return 0x2d;
+ case 0x745: return 0x3a;
+ }
+
+ return 0;
+}
+
int axp_read(uint8_t reg)
{
- return rsb_read(AXP305_RT_ADDR, reg);
+ uint8_t val;
+ int ret;
+
+ if (is_using_rsb()) {
+ return rsb_read(rsb_rt_addr, reg);
+ }
+
+ ret = i2c_write(pmic_bus_addr, 0, 0, ®, 1);
+ if (ret == 0) {
+ ret = i2c_read(pmic_bus_addr, 0, 0, &val, 1);
+ }
+ if (ret) {
+ ERROR("PMIC: Cannot read PMIC register %02x\n", reg);
+ return ret;
+ }
+
+ return val;
}
int axp_write(uint8_t reg, uint8_t val)
{
- return rsb_write(AXP305_RT_ADDR, reg, val);
+ int ret;
+
+ if (is_using_rsb()) {
+ return rsb_write(rsb_rt_addr, reg, val);
+ }
+
+ ret = i2c_write(pmic_bus_addr, reg, 1, &val, 1);
+ if (ret) {
+ ERROR("PMIC: Cannot write PMIC register %02x\n", reg);
+ }
+
+ return ret;
}
-static int rsb_init(void)
+static int rsb_init(int rsb_hw_addr)
{
int ret;
ret = rsb_init_controller();
- if (ret)
+ if (ret) {
return ret;
+ }
/* Switch to the recommended 3 MHz bus clock. */
ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
- if (ret)
+ if (ret) {
return ret;
+ }
/* Initiate an I2C transaction to switch the PMIC to RSB mode. */
ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8);
- if (ret)
+ if (ret) {
return ret;
+ }
/* Associate the 8-bit runtime address with the 12-bit bus address. */
- ret = rsb_assign_runtime_address(AXP305_HW_ADDR, AXP305_RT_ADDR);
- if (ret)
+ ret = rsb_assign_runtime_address(rsb_hw_addr, rsb_rt_addr);
+ if (ret) {
return ret;
+ }
- return axp_check_id();
+ return 0;
}
-int sunxi_pmic_setup(uint16_t socid, const void *fdt)
+static int pmic_bus_init(uint16_t socid, uint16_t rsb_hw_addr)
{
int ret;
- INFO("PMIC: Probing AXP305 on RSB\n");
-
- ret = sunxi_init_platform_r_twi(socid, true);
+ ret = sunxi_init_platform_r_twi(socid, is_using_rsb());
if (ret) {
INFO("Could not init platform bus: %d\n", ret);
+ pmic = UNKNOWN;
return ret;
}
+ if (is_using_rsb()) {
+ ret = rsb_init(rsb_hw_addr);
+ if (ret) {
+ pmic = UNKNOWN;
+ return ret;
+ }
+ } else {
+ /* initialise mi2cv driver */
+ i2c_init((void *)SUNXI_R_I2C_BASE);
+ }
+
+ return 0;
+}
+
+int sunxi_pmic_setup(uint16_t socid, const void *fdt)
+{
+ int node, parent, ret;
+ uint32_t reg;
+
+ node = fdt_node_offset_by_compatible(fdt, 0, "x-powers,axp806");
+ if (node >= 0) {
+ pmic = AXP305;
+ }
+
+ if (pmic == UNKNOWN) {
+ node = fdt_node_offset_by_compatible(fdt, 0, "x-powers,axp313a");
+ if (node >= 0) {
+ pmic = AXP313;
+ }
+ }
+
+ if (pmic == UNKNOWN) {
+ node = fdt_node_offset_by_compatible(fdt, 0, "x-powers,axp717");
+ if (node >= 0) {
+ pmic = AXP717;
+ }
+ }
+
+ if (pmic == UNKNOWN) {
+ INFO("PMIC: No known PMIC in DT, skipping setup.\n");
+ return -ENODEV;
+ }
+
- ret = rsb_init();
+ if (fdt_read_uint32(fdt, node, "reg", ®)) {
+ ERROR("PMIC: PMIC DT node does not contain reg property.\n");
+ return -EINVAL;
+ }
+
+ pmic_bus_addr = reg;
+ parent = fdt_parent_offset(fdt, node);
+ ret = fdt_node_check_compatible(fdt, parent, "allwinner,sun8i-a23-rsb");
+ if (ret == 0) {
+ rsb_rt_addr = get_rsb_rt_address(pmic_bus_addr);
+ if (rsb_rt_addr == 0) {
+ ERROR("PMIC: no mapping for RSB address 0x%x\n",
+ pmic_bus_addr);
+ return -EINVAL;
+ }
+ }
+
+ INFO("Probing for PMIC on %s:\n", is_using_rsb() ? "RSB" : "I2C");
+
+ ret = pmic_bus_init(socid, pmic_bus_addr);
if (ret) {
- INFO("Could not init RSB: %d\n", ret);
return ret;
}
- pmic = AXP305;
- axp_setup_regulators(fdt);
+ ret = axp_read(0x03);
+ switch (ret & 0xcf) {
+ case 0x40: /* AXP305 */
+ if (pmic == AXP305) {
+ INFO("PMIC: found AXP305, setting up regulators\n");
+ axp_setup_regulators(fdt);
+ } else {
+ pmic = UNKNOWN;
+ }
+ break;
+ case 0x48: /* AXP1530 */
+ case 0x4b: /* AXP313A */
+ case 0x4c: /* AXP313B */
+ if (pmic == AXP313) {
+ INFO("PMIC: found AXP313\n");
+ /* no regulators to set up */
+ } else {
+ pmic = UNKNOWN;
+ }
+ break;
+ case 0xcf: /* version reg not implemented on AXP717 */
+ if (pmic == AXP717) {
+ INFO("PMIC: found AXP717\n");
+ /* no regulators to set up, U-Boot takes care of this */
+ } else {
+ pmic = UNKNOWN;
+ }
+ break;
+ }
- /* Switch the PMIC back to I2C mode. */
- ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C);
- if (ret)
- return ret;
+ if (is_using_rsb()) {
+ /* Switch the PMIC back to I2C mode. */
+ return rsb_write(rsb_rt_addr, AXP20X_MODE_REG, AXP20X_MODE_I2C);
+ }
+
+ if (pmic == UNKNOWN) {
+ INFO("Incompatible or unknown PMIC found.\n");
+ return -ENODEV;
+ }
return 0;
}
void sunxi_power_down(void)
{
+ int ret;
+
+ if (pmic == UNKNOWN) {
+ return;
+ }
+
+ /* Re-initialise after rich OS might have used it. */
+ ret = pmic_bus_init(SUNXI_SOC_H616, pmic_bus_addr);
+ if (ret) {
+ return;
+ }
+
switch (pmic) {
case AXP305:
- /* Re-initialise after rich OS might have used it. */
- sunxi_init_platform_r_twi(SUNXI_SOC_H616, true);
- rsb_init();
- axp_power_off();
+ axp_setbits(0x32, BIT(7));
+ break;
+ case AXP313:
+ axp_setbits(0x1a, BIT(7));
+ break;
+ case AXP717:
+ axp_setbits(0x27, BIT(0));
break;
default:
break;
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..6f0cbcb 100644
--- a/plat/amd/versal2/plat_psci.c
+++ b/plat/amd/versal2/plat_psci.c
@@ -161,12 +161,29 @@
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;
+ 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 +204,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/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/common/corstone1000_bl2_mem_params_desc.c b/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c
index 457d181..de6a15a 100644
--- a/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c
+++ b/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2022, 2024 ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -77,7 +77,8 @@
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE),
.ep_info.pc = BL33_BASE,
-
+ .ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
+ DISABLE_ALL_EXCEPTIONS),
SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
VERSION_2, image_info_t, 0),
.image_info.image_base = BL33_BASE,
diff --git a/plat/arm/board/corstone1000/common/corstone1000_plat.c b/plat/arm/board/corstone1000/common/corstone1000_plat.c
index ed3801c..e388c82 100644
--- a/plat/arm/board/corstone1000/common/corstone1000_plat.c
+++ b/plat/arm/board/corstone1000/common/corstone1000_plat.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -23,7 +23,6 @@
const mmap_region_t plat_arm_mmap[] = {
ARM_MAP_SHARED_RAM,
- ARM_MAP_NS_SHARED_RAM,
ARM_MAP_NS_DRAM1,
CORSTONE1000_MAP_DEVICE,
CORSTONE1000_EXTERNAL_FLASH,
diff --git a/plat/arm/board/corstone1000/common/corstone1000_pm.c b/plat/arm/board/corstone1000/common/corstone1000_pm.c
index ee07605..bd3faec 100644
--- a/plat/arm/board/corstone1000/common/corstone1000_pm.c
+++ b/plat/arm/board/corstone1000/common/corstone1000_pm.c
@@ -7,6 +7,8 @@
#include <lib/psci/psci.h>
#include <plat/arm/common/plat_arm.h>
#include <platform_def.h>
+#include <plat/common/platform.h>
+#include <drivers/arm/gicv2.h>
/*******************************************************************************
* Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
* platform layer will take care of registering the handlers with PSCI.
@@ -18,6 +20,15 @@
uint32_t volatile * const watchdog_ctrl_reg = (uint32_t *) SECURE_WATCHDOG_ADDR_CTRL_REG;
uint32_t volatile * const watchdog_val_reg = (uint32_t *) SECURE_WATCHDOG_ADDR_VAL_REG;
+ /*
+ * Disable GIC CPU interface to prevent pending interrupt
+ * from waking up the AP from WFI.
+ */
+ gicv2_cpuif_disable();
+
+ /* Flush and invalidate data cache */
+ dcsw_op_all(DCCISW);
+
*(watchdog_val_reg) = SECURE_WATCHDOG_COUNTDOWN_VAL;
*watchdog_ctrl_reg = SECURE_WATCHDOG_MASK_ENABLE;
while (1) {
diff --git a/plat/arm/board/corstone1000/common/include/platform_def.h b/plat/arm/board/corstone1000/common/include/platform_def.h
index e3f3268..caf3d46 100644
--- a/plat/arm/board/corstone1000/common/include/platform_def.h
+++ b/plat/arm/board/corstone1000/common/include/platform_def.h
@@ -55,42 +55,42 @@
/* Memory related constants */
-/* SRAM (CVM) memory layout
+/* Memory mappings of where the BLs in the FIP are copied to
*
- * <ARM_TRUSTED_SRAM_BASE>
+ * <ARM_TRUSTED_SRAM_BASE> = 0x02000000
* partition size: sizeof(meminfo_t) = 16 bytes
* content: memory info area used by the next BL
*
- * <ARM_FW_CONFIG_BASE>
+ * <ARM_FW_CONFIG_BASE> = 0x02000010
* partition size: 4080 bytes
*
- * <ARM_BL2_MEM_DESC_BASE>
+ * <ARM_BL2_MEM_DESC_BASE> = 0x02001000
* partition size: 4 KB
* content: Area where BL2 copies the images descriptors
*
- * <ARM_BL_RAM_BASE> = <BL32_BASE>
- * partition size: 688 KB
+ * <ARM_BL_RAM_BASE> = <BL32_BASE> = 0x02002000
+ * partition size: 3752 KB
* content: BL32 (optee-os)
*
- * <CORSTONE1000_TOS_FW_CONFIG_BASE> = 0x20ae000
+ * <CORSTONE1000_TOS_FW_CONFIG_BASE> = 0x023AC000
* partition size: 8 KB
* content: BL32 config (TOS_FW_CONFIG)
*
- * <BL31_BASE>
+ * <BL31_BASE> = 0x023AE000
* partition size: 140 KB
* content: BL31
*
- * <BL2_SIGNATURE_BASE>
+ * <BL2_SIGNATURE_BASE> = 0x023D1000
* partition size: 4 KB
* content: MCUBOOT data needed to verify TF-A BL2
*
- * <BL2_BASE>
+ * <BL2_BASE> = 0x023D2000
* partition size: 176 KB
* content: BL2
*
- * <ARM_NS_SHARED_RAM_BASE> = <ARM_TRUSTED_SRAM_BASE> + 1 MB
- * partition size: 512 KB
- * content: BL33 (u-boot)
+ * <BL33_BASE> = 0x80000000
+ * partition size: 12 MB
+ * content: BL33 (U-Boot)
*/
/* DDR memory */
@@ -115,11 +115,8 @@
/* The remaining Trusted SRAM is used to load the BL images */
#define TOTAL_SRAM_SIZE (SZ_4M) /* 4 MB */
-/* Last 512KB of CVM is allocated for shared RAM as an example openAMP */
-#define ARM_NS_SHARED_RAM_SIZE (512 * SZ_1K)
#define PLAT_ARM_TRUSTED_SRAM_SIZE (TOTAL_SRAM_SIZE - \
- ARM_NS_SHARED_RAM_SIZE - \
ARM_SHARED_RAM_SIZE)
#define PLAT_ARM_MAX_BL2_SIZE (180 * SZ_1K) /* 180 KB */
@@ -158,11 +155,6 @@
/* NS memory */
-/* The last 512KB of the SRAM is allocated as shared memory */
-#define ARM_NS_SHARED_RAM_BASE (ARM_TRUSTED_SRAM_BASE + TOTAL_SRAM_SIZE - \
- (PLAT_ARM_MAX_BL31_SIZE + \
- PLAT_ARM_MAX_BL32_SIZE))
-
#define BL33_BASE ARM_DRAM1_BASE
#define PLAT_ARM_MAX_BL33_SIZE (12 * SZ_1M) /* 12 MB*/
#define BL33_LIMIT (ARM_DRAM1_BASE + PLAT_ARM_MAX_BL33_SIZE)
@@ -277,7 +269,7 @@
#define PLAT_ARM_NSTIMER_FRAME_ID U(1)
-#define PLAT_ARM_NS_IMAGE_BASE (ARM_NS_SHARED_RAM_BASE)
+#define PLAT_ARM_NS_IMAGE_BASE (BL33_BASE)
#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
@@ -306,11 +298,6 @@
ARM_SHARED_RAM_SIZE, \
MT_MEMORY | MT_RW | MT_SECURE)
-#define ARM_MAP_NS_SHARED_RAM MAP_REGION_FLAT( \
- ARM_NS_SHARED_RAM_BASE, \
- ARM_NS_SHARED_RAM_SIZE, \
- MT_MEMORY | MT_RW | MT_NS)
-
#define ARM_MAP_NS_DRAM1 MAP_REGION_FLAT( \
ARM_NS_DRAM1_BASE, \
ARM_NS_DRAM1_SIZE, \
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_el1_optee_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_el1_optee_manifest.dts
new file mode 100644
index 0000000..36a22a1
--- /dev/null
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_el1_optee_manifest.dts
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ */
+
+/dts-v1/;
+
+/ {
+ compatible = "arm,ffa-core-manifest-1.0";
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ attribute {
+ spmc_id = <0x8000>;
+ maj_ver = <0x1>;
+ min_ver = <0x1>;
+ exec_state = <0x0>;
+ load_address = <0x0 0x6000000>;
+ entrypoint = <0x0 0x6000000>;
+ binary_size = <0x80000>;
+ };
+};
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_spmc_optee_sp_manifest.dts b/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts
index d90544b..234ab58 100644
--- a/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts
+++ b/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts
@@ -35,7 +35,7 @@
debug_name = "op-tee";
load_address = <0x6280000>;
vcpu_count = <8>;
- mem_size = <1048576>;
+ mem_size = <0xd80000>;
};
};
@@ -63,10 +63,11 @@
reg = <0x0 0x6000000 0x0 0x2000000>; /* Trusted DRAM */
};
- memory@1 {
+ memory@80000000 {
device_type = "ns-memory";
- reg = <0x00008800 0x80000000 0x0 0x7f000000>,
- <0x0 0x88000000 0x0 0x10000000>;
+ reg = <0x0 0x80000000 0x0 0x7c000000>,
+ <0x8 0x80000000 0x1 0x80000000>,
+ <0x00008800 0x80000000 0x0 0x7f000000>;
};
memory@0 {
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/fdts/optee_sp_manifest.dts b/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
index 27f4724..4611f80 100644
--- a/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
+++ b/plat/arm/board/fvp/fdts/optee_sp_manifest.dts
@@ -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,23 +15,30 @@
/* Properties */
description = "op-tee";
- ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */
+ ffa-version = <0x00010001>; /* 31:16 - Major, 15:0 - Minor */
uuid = <0xe0786148 0xe311f8e7 0x02005ebc 0x1bc5d5a5>;
id = <1>;
execution-ctx-count = <8>;
exception-level = <2>; /* S-EL1 */
execution-state = <0>; /* AARCH64 */
load-address = <0x6280000>;
+ mem-size = <0xd80000>; /* OP-TEE specific extension */
entrypoint-offset = <0x4000>;
xlat-granule = <0>; /* 4KiB */
boot-order = <0>;
messaging-method = <0x3>; /* Direct request/response supported. */
- managed-exit;
+ ns-interrupts-action = <1>; /* NS_ACTION_ME */
run-time-model = <1>; /* SP pre-emptible. */
/* Boot protocol */
gp-register-num = <0x0>;
+ /* Boot Info */
+ boot-info {
+ compatible = "arm,ffa-manifest-boot-info";
+ ffa_manifest;
+ };
+
device-regions {
compatible = "arm,ffa-manifest-device-regions";
@@ -39,6 +46,7 @@
base-address = <0x00000000 0x1c0a0000>;
pages-count = <1>;
attributes = <0x3>; /* read-write */
+ interrupts = <38 0x900>;
};
};
};
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index 5557d59..0c5a76c 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -210,7 +210,7 @@
#ifdef MAP_FW_NS_HANDOFF
MAP_FW_NS_HANDOFF,
#endif
-#ifdef MAP_EL3_FW_HANDOFF
+#if defined(MAP_EL3_FW_HANDOFF) && !RESET_TO_BL31
MAP_EL3_FW_HANDOFF,
#endif
{ 0 }
@@ -219,6 +219,11 @@
#if defined(IMAGE_BL31) && SPM_MM
const mmap_region_t plat_arm_secure_partition_mmap[] = {
V2M_MAP_IOFPGA_EL0, /* for the UART */
+ V2M_MAP_SECURE_SYSTEMREG_EL0, /* for initializing flash */
+#if PSA_FWU_SUPPORT
+ V2M_MAP_FLASH0_RW_EL0, /* for firmware update service in standalone mm */
+#endif
+ V2M_MAP_FLASH1_RW_EL0, /* for secure variable service in standalone mm */
MAP_REGION_FLAT(DEVICE0_BASE,
DEVICE0_SIZE,
MT_DEVICE | MT_RO | MT_SECURE | MT_USER),
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 af2b78d..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
@@ -57,6 +61,7 @@
ENABLE_SYS_REG_TRACE_FOR_NS := 2
ENABLE_FEAT_CSV2_2 := 2
ENABLE_FEAT_CSV2_3 := 2
+ENABLE_FEAT_DEBUGV8P9 := 2
ENABLE_FEAT_DIT := 2
ENABLE_FEAT_PAN := 2
ENABLE_FEAT_VHE := 2
@@ -65,6 +70,7 @@
ENABLE_TRF_FOR_NS := 2
ENABLE_FEAT_ECV := 2
ENABLE_FEAT_FGT := 2
+ENABLE_FEAT_FGT2 := 2
ENABLE_FEAT_TCR2 := 2
ENABLE_FEAT_S2PIE := 2
ENABLE_FEAT_S1PIE := 2
@@ -321,10 +327,6 @@
BL31_SOURCES += drivers/delay_timer/generic_delay_timer.c
endif
-ifeq (${TRANSFER_LIST}, 1)
-include lib/transfer_list/transfer_list.mk
-endif
-
# Add the FDT_SOURCES and options for Dynamic Config (only for Unix env)
ifdef UNIX_MK
FVP_TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
@@ -384,6 +386,17 @@
$(eval $(call TOOL_ADD_PAYLOAD,${FVP_HW_CONFIG},--hw-config,${FVP_HW_CONFIG}))
endif
+ifeq (${TRANSFER_LIST}, 1)
+include lib/transfer_list/transfer_list.mk
+
+ifeq ($(RESET_TO_BL31), 1)
+HW_CONFIG := ${FVP_HW_CONFIG}
+FW_HANDOFF_SIZE := 20000
+
+$(eval $(call add_define,ARM_PRELOADED_DTB_OFFSET))
+endif
+endif
+
# Enable dynamic mitigation support by default
DYNAMIC_WORKAROUND_CVE_2018_3639 := 1
diff --git a/plat/arm/board/fvp_ve/fvp_ve_def.h b/plat/arm/board/fvp_ve/fvp_ve_def.h
index 98de5f6..cb4b74c 100644
--- a/plat/arm/board/fvp_ve/fvp_ve_def.h
+++ b/plat/arm/board/fvp_ve/fvp_ve_def.h
@@ -70,15 +70,4 @@
#define FVP_VE_IRQ_TZ_WDOG 56
#define FVP_VE_IRQ_SEC_SYS_TIMER 57
-#define V2M_FLASH1_BASE UL(0x0C000000)
-#define V2M_FLASH1_SIZE UL(0x04000000)
-
-#define V2M_MAP_FLASH1_RW MAP_REGION_FLAT(V2M_FLASH1_BASE,\
- V2M_FLASH1_SIZE, \
- MT_DEVICE | MT_RW | MT_SECURE)
-
-#define V2M_MAP_FLASH1_RO MAP_REGION_FLAT(V2M_FLASH1_BASE,\
- V2M_FLASH1_SIZE, \
- MT_RO_DATA | MT_SECURE)
-
#endif /* FVP_VE_DEF_H */
diff --git a/plat/arm/board/neoverse_rd/common/include/nrd_variant.h b/plat/arm/board/neoverse_rd/common/include/nrd_variant.h
index 391c68c..86d82e2 100644
--- a/plat/arm/board/neoverse_rd/common/include/nrd_variant.h
+++ b/plat/arm/board/neoverse_rd/common/include/nrd_variant.h
@@ -28,13 +28,13 @@
#define RD_V2_SID_VER_PART_NUM 0x07F2
#define RD_V2_CONFIG_ID 0x1
-/* SID Version values for RD-Fremont */
-#define RD_FREMONT_SID_VER_PART_NUM 0x07EE
-#define RD_FREMONT_CONFIG_ID 0x0
+/* SID Version values for RD-V3 */
+#define RD_V3_SID_VER_PART_NUM 0x07EE
+#define RD_V3_CONFIG_ID 0x0
-/* SID Version values for RD-Fremont variants */
-#define RD_FREMONT_CFG1_SID_VER_PART_NUM 0x07F9
-#define RD_FREMONT_CFG2_SID_VER_PART_NUM 0x07EE
+/* SID Version values for RD-V3 variants */
+#define RD_V3_CFG1_SID_VER_PART_NUM 0x07F9
+#define RD_V3_CFG2_SID_VER_PART_NUM 0x07EE
/* Structure containing Neoverse RD platform variant information */
typedef struct nrd_platform_info {
diff --git a/plat/arm/board/neoverse_rd/common/nrd_bl31_setup.c b/plat/arm/board/neoverse_rd/common/nrd_bl31_setup.c
index 5a7dfb1..18aa2fb 100644
--- a/plat/arm/board/neoverse_rd/common/nrd_bl31_setup.c
+++ b/plat/arm/board/neoverse_rd/common/nrd_bl31_setup.c
@@ -131,9 +131,9 @@
panic();
}
return &plat_rd_scmi_info[channel_id];
- } else if (nrd_plat_info.platform_id == RD_FREMONT_SID_VER_PART_NUM ||
- nrd_plat_info.platform_id == RD_FREMONT_CFG1_SID_VER_PART_NUM ||
- nrd_plat_info.platform_id == RD_FREMONT_CFG2_SID_VER_PART_NUM) {
+ } else if (nrd_plat_info.platform_id == RD_V3_SID_VER_PART_NUM ||
+ nrd_plat_info.platform_id == RD_V3_CFG1_SID_VER_PART_NUM ||
+ nrd_plat_info.platform_id == RD_V3_CFG2_SID_VER_PART_NUM) {
if (channel_id >= ARRAY_SIZE(plat3_rd_scmi_info)) {
panic();
}
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 371bde6..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
@@ -62,39 +62,37 @@
cpu_info->SecurityState = security_state;
/* populate CPU EL1 context information. */
- cpu_info->ErrCtxEl1Reg[0] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_ELR_EL1);
- cpu_info->ErrCtxEl1Reg[1] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_ESR_EL1);
- cpu_info->ErrCtxEl1Reg[2] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_FAR_EL1);
+ cpu_info->ErrCtxEl1Reg[0] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
+ elr_el1);
+ cpu_info->ErrCtxEl1Reg[1] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
+ esr_el1);
+ cpu_info->ErrCtxEl1Reg[2] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
+ far_el1);
cpu_info->ErrCtxEl1Reg[3] = read_isr_el1();
- cpu_info->ErrCtxEl1Reg[4] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_MAIR_EL1);
+ cpu_info->ErrCtxEl1Reg[4] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
+ mair_el1);
cpu_info->ErrCtxEl1Reg[5] = read_midr_el1();
cpu_info->ErrCtxEl1Reg[6] = read_mpidr_el1();
- cpu_info->ErrCtxEl1Reg[7] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_SCTLR_EL1);
+ 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_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_SP_EL1);
- cpu_info->ErrCtxEl1Reg[10] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_SPSR_EL1);
- cpu_info->ErrCtxEl1Reg[11] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_TCR_EL1);
- cpu_info->ErrCtxEl1Reg[12] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_TPIDR_EL0);
- cpu_info->ErrCtxEl1Reg[13] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_TPIDR_EL1);
- cpu_info->ErrCtxEl1Reg[14] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_TPIDRRO_EL0);
- cpu_info->ErrCtxEl1Reg[15] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_TTBR0_EL1);
- cpu_info->ErrCtxEl1Reg[16] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_TTBR1_EL1);
+ 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);
+ 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),
+ tpidr_el1);
+ cpu_info->ErrCtxEl1Reg[14] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
+ tpidrro_el0);
+ cpu_info->ErrCtxEl1Reg[15] = read_el1_ctx_common(get_el1_sysregs_ctx(ctx),
+ ttbr0_el1);
+ 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),
@@ -127,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/rdfremont/fdts/rdfremont_fw_config.dts b/plat/arm/board/neoverse_rd/platform/rdv3/fdts/rdv3_fw_config.dts
similarity index 100%
rename from plat/arm/board/neoverse_rd/platform/rdfremont/fdts/rdfremont_fw_config.dts
rename to plat/arm/board/neoverse_rd/platform/rdv3/fdts/rdv3_fw_config.dts
diff --git a/plat/arm/board/neoverse_rd/platform/rdfremont/fdts/rdfremont_nt_fw_config.dts b/plat/arm/board/neoverse_rd/platform/rdv3/fdts/rdv3_nt_fw_config.dts
similarity index 92%
rename from plat/arm/board/neoverse_rd/platform/rdfremont/fdts/rdfremont_nt_fw_config.dts
rename to plat/arm/board/neoverse_rd/platform/rdv3/fdts/rdv3_nt_fw_config.dts
index 62cad39..941d4a0 100644
--- a/plat/arm/board/neoverse_rd/platform/rdfremont/fdts/rdfremont_nt_fw_config.dts
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/fdts/rdv3_nt_fw_config.dts
@@ -7,7 +7,7 @@
/dts-v1/;
/ {
/* compatible string */
- compatible = "arm,rd-fremont";
+ compatible = "arm,rd-v3";
/*
* Place holder for system-id node with default values. The
diff --git a/plat/arm/board/neoverse_rd/platform/rdfremont/fdts/rdfremont_tb_fw_config.dts b/plat/arm/board/neoverse_rd/platform/rdv3/fdts/rdv3_tb_fw_config.dts
similarity index 100%
rename from plat/arm/board/neoverse_rd/platform/rdfremont/fdts/rdfremont_tb_fw_config.dts
rename to plat/arm/board/neoverse_rd/platform/rdv3/fdts/rdv3_tb_fw_config.dts
diff --git a/plat/arm/board/neoverse_rd/platform/rdfremont/include/platform_def.h b/plat/arm/board/neoverse_rd/platform/rdv3/include/platform_def.h
similarity index 100%
rename from plat/arm/board/neoverse_rd/platform/rdfremont/include/platform_def.h
rename to plat/arm/board/neoverse_rd/platform/rdv3/include/platform_def.h
diff --git a/plat/arm/board/neoverse_rd/platform/rdfremont/include/rdfremont_mhuv3.h b/plat/arm/board/neoverse_rd/platform/rdv3/include/rdv3_mhuv3.h
similarity index 69%
rename from plat/arm/board/neoverse_rd/platform/rdfremont/include/rdfremont_mhuv3.h
rename to plat/arm/board/neoverse_rd/platform/rdv3/include/rdv3_mhuv3.h
index 400dcc5..fa64963 100644
--- a/plat/arm/board/neoverse_rd/platform/rdfremont/include/rdfremont_mhuv3.h
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/include/rdv3_mhuv3.h
@@ -4,9 +4,9 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#ifndef RDFREMONT_MHUV3_H
-#define RDFREMONT_MHUV3_H
+#ifndef RDV3_MHUV3_H
+#define RDV3_MHUV3_H
void mhu_v3_get_secure_device_base(uintptr_t *base, bool sender);
-#endif /* RDFREMONT_MHUV3_H */
+#endif /* RDV3_MHUV3_H */
diff --git a/plat/arm/board/neoverse_rd/platform/rdfremont/include/rdfremont_rse_comms.h b/plat/arm/board/neoverse_rd/platform/rdv3/include/rdv3_rse_comms.h
similarity index 62%
rename from plat/arm/board/neoverse_rd/platform/rdfremont/include/rdfremont_rse_comms.h
rename to plat/arm/board/neoverse_rd/platform/rdv3/include/rdv3_rse_comms.h
index ad1bc23..cb8e786 100644
--- a/plat/arm/board/neoverse_rd/platform/rdfremont/include/rdfremont_rse_comms.h
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/include/rdv3_rse_comms.h
@@ -4,9 +4,9 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#ifndef RDFREMONT_RSE_COMMS_H
-#define RDFREMONT_RSE_COMMS_H
+#ifndef RDV3_RSE_COMMS_H
+#define RDV3_RSE_COMMS_H
int plat_rse_comms_init(void);
-#endif /* RDFREMONT_RSE_COMMS_H */
+#endif /* RDV3_RSE_COMMS_H */
diff --git a/plat/arm/board/neoverse_rd/platform/rdfremont/platform.mk b/plat/arm/board/neoverse_rd/platform/rdv3/platform.mk
similarity index 64%
rename from plat/arm/board/neoverse_rd/platform/rdfremont/platform.mk
rename to plat/arm/board/neoverse_rd/platform/rdv3/platform.mk
index bca6172..da96730 100644
--- a/plat/arm/board/neoverse_rd/platform/rdfremont/platform.mk
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/platform.mk
@@ -3,16 +3,16 @@
# SPDX-License-Identifier: BSD-3-Clause
#
-RD_FREMONT_VARIANTS := 0 1 2
+RD_V3_VARIANTS := 0 1 2
ifneq ($(NRD_PLATFORM_VARIANT), \
- $(filter $(NRD_PLATFORM_VARIANT),$(RD_FREMONT_VARIANTS)))
- $(error "NRD_PLATFORM_VARIANT for RD-FREMONT should be 0, 1, or 2,"
+ $(filter $(NRD_PLATFORM_VARIANT),$(RD_V3_VARIANTS)))
+ $(error "NRD_PLATFORM_VARIANT for RD-V3 should be 0, 1, or 2,"
"currently set to ${NRD_PLATFORM_VARIANT}.")
endif
$(eval $(call CREATE_SEQ,SEQ,4))
ifneq ($(NRD_CHIP_COUNT),$(filter $(NRD_CHIP_COUNT),$(SEQ)))
- $(error "Chip count for RD-Fremont-MC should be either $(SEQ) \
+ $(error "Chip count for RD-V3-MC should be either $(SEQ) \
currently it is set to ${NRD_CHIP_COUNT}.")
endif
@@ -21,16 +21,10 @@
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
-# RD-Fremont platform uses GIC-700 which is based on GICv4.1
+# RD-V3 platform uses GIC-700 which is based on GICv4.1
GIC_ENABLE_V4_EXTN := 1
# Enable GIC multichip extension only for multichip platforms
@@ -38,7 +32,7 @@
GICV3_IMPL_GIC600_MULTICHIP := 1
endif
-# RD-Fremont uses MHUv3
+# RD-V3 uses MHUv3
PLAT_MHU_VERSION := 3
include plat/arm/board/neoverse_rd/common/nrd-common.mk
@@ -48,58 +42,58 @@
include drivers/measured_boot/rse/rse_measured_boot.mk
endif
-RDFREMONT_BASE = plat/arm/board/neoverse_rd/platform/rdfremont
+RDV3_BASE = plat/arm/board/neoverse_rd/platform/rdv3
PLAT_INCLUDES += -I${NRD_COMMON_BASE}/include/nrd3/ \
- -I${RDFREMONT_BASE}/include/ \
+ -I${RDV3_BASE}/include/ \
-Iinclude/lib/psa
NRD_CPU_SOURCES := lib/cpus/aarch64/neoverse_v3.S
-# Source files for RD-Fremont variants
+# Source files for RD-V3 variants
PLAT_BL_COMMON_SOURCES \
+= ${NRD_COMMON_BASE}/nrd_plat3.c \
- ${RDFREMONT_BASE}/rdfremont_common.c
+ ${RDV3_BASE}/rdv3_common.c
PLAT_MEASURED_BOOT_SOURCES \
:= ${MEASURED_BOOT_SOURCES} \
${RSE_COMMS_SOURCES} \
- ${RDFREMONT_BASE}/rdfremont_common_measured_boot.c \
+ ${RDV3_BASE}/rdv3_common_measured_boot.c \
lib/psa/measured_boot.c
BL1_SOURCES += ${NRD_CPU_SOURCES} \
- ${RDFREMONT_BASE}/rdfremont_err.c \
- ${RDFREMONT_BASE}/rdfremont_mhuv3.c
+ ${RDV3_BASE}/rdv3_err.c \
+ ${RDV3_BASE}/rdv3_mhuv3.c
ifeq (${TRUSTED_BOARD_BOOT}, 1)
-BL1_SOURCES += ${RDFREMONT_BASE}/rdfremont_trusted_boot.c
+BL1_SOURCES += ${RDV3_BASE}/rdv3_trusted_boot.c
endif
ifeq (${MEASURED_BOOT},1)
BL1_SOURCES += ${PLAT_MEASURED_BOOT_SOURCES} \
- ${RDFREMONT_BASE}/rdfremont_bl1_measured_boot.c
+ ${RDV3_BASE}/rdv3_bl1_measured_boot.c
endif
-BL2_SOURCES += ${RDFREMONT_BASE}/rdfremont_bl2_setup.c \
- ${RDFREMONT_BASE}/rdfremont_err.c \
- ${RDFREMONT_BASE}/rdfremont_mhuv3.c \
- ${RDFREMONT_BASE}/rdfremont_security.c \
+BL2_SOURCES += ${RDV3_BASE}/rdv3_bl2_setup.c \
+ ${RDV3_BASE}/rdv3_err.c \
+ ${RDV3_BASE}/rdv3_mhuv3.c \
+ ${RDV3_BASE}/rdv3_security.c \
lib/utils/mem_region.c \
plat/arm/common/arm_nor_psci_mem_protect.c
ifeq (${TRUSTED_BOARD_BOOT}, 1)
-BL2_SOURCES += ${RDFREMONT_BASE}/rdfremont_trusted_boot.c
+BL2_SOURCES += ${RDV3_BASE}/rdv3_trusted_boot.c
endif
ifeq (${MEASURED_BOOT},1)
BL2_SOURCES += ${PLAT_MEASURED_BOOT_SOURCES} \
- ${RDFREMONT_BASE}/rdfremont_bl2_measured_boot.c
+ ${RDV3_BASE}/rdv3_bl2_measured_boot.c
endif
BL31_SOURCES += ${NRD_CPU_SOURCES} \
${MBEDTLS_SOURCES} \
${RSE_COMMS_SOURCES} \
- ${RDFREMONT_BASE}/rdfremont_bl31_setup.c \
- ${RDFREMONT_BASE}/rdfremont_mhuv3.c \
- ${RDFREMONT_BASE}/rdfremont_topology.c \
- ${RDFREMONT_BASE}/rdfremont_plat_attest_token.c \
- ${RDFREMONT_BASE}/rdfremont_realm_attest_key.c \
+ ${RDV3_BASE}/rdv3_bl31_setup.c \
+ ${RDV3_BASE}/rdv3_mhuv3.c \
+ ${RDV3_BASE}/rdv3_topology.c \
+ ${RDV3_BASE}/rdv3_plat_attest_token.c \
+ ${RDV3_BASE}/rdv3_realm_attest_key.c \
drivers/arm/smmu/smmu_v3.c \
drivers/cfi/v2m/v2m_flash.c \
lib/psa/cca_attestation.c \
@@ -111,14 +105,14 @@
BL31_SOURCES += drivers/arm/gic/v3/gic600_multichip.c
endif
-# XLAT options for RD-Fremont variants
+# XLAT options for RD-V3 variants
BL31_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
BL2_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC
# Add the FDT_SOURCES and options for Dynamic Config
-FDT_SOURCES += ${RDFREMONT_BASE}/fdts/${PLAT}_fw_config.dts \
- ${RDFREMONT_BASE}/fdts/${PLAT}_tb_fw_config.dts \
- ${RDFREMONT_BASE}/fdts/${PLAT}_nt_fw_config.dts
+FDT_SOURCES += ${RDV3_BASE}/fdts/${PLAT}_fw_config.dts \
+ ${RDV3_BASE}/fdts/${PLAT}_tb_fw_config.dts \
+ ${RDV3_BASE}/fdts/${PLAT}_nt_fw_config.dts
FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
TB_FW_CONFIG := ${BUILD_PLAT}/fdts/${PLAT}_tb_fw_config.dtb
@@ -131,7 +125,7 @@
# Add the NT_FW_CONFIG to FIP and specify the same to certtool
$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config))
-# Features for RD-Fremont variants
+# Features for RD-V3 variants
override ENABLE_FEAT_MPAM := 2
override ENABLE_FEAT_AMU := 2
override ENABLE_SVE_FOR_SWD := 1
diff --git a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_bl1_measured_boot.c b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl1_measured_boot.c
similarity index 88%
rename from plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_bl1_measured_boot.c
rename to plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl1_measured_boot.c
index 92e96c2..4db9a11 100644
--- a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_bl1_measured_boot.c
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl1_measured_boot.c
@@ -13,13 +13,13 @@
#include <platform_def.h>
#include <nrd_plat.h>
-#include <rdfremont_rse_comms.h>
+#include <rdv3_rse_comms.h>
/*
* Platform specific table with image IDs and metadata. Intentionally not a
* const struct, some members might set by bootloaders during trusted boot.
*/
-struct rse_mboot_metadata rdfremont_rse_mboot_metadata[] = {
+struct rse_mboot_metadata rdv3_rse_mboot_metadata[] = {
{
.id = FW_CONFIG_ID,
.slot = U(8),
@@ -51,7 +51,7 @@
/* Initialize the communication channel between AP and RSE */
(void)plat_rse_comms_init();
- rse_measured_boot_init(rdfremont_rse_mboot_metadata);
+ rse_measured_boot_init(rdv3_rse_mboot_metadata);
}
void bl1_plat_mboot_finish(void)
diff --git a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_bl2_measured_boot.c b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl2_measured_boot.c
similarity index 90%
rename from plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_bl2_measured_boot.c
rename to plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl2_measured_boot.c
index 570c33a..1b94427 100644
--- a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_bl2_measured_boot.c
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl2_measured_boot.c
@@ -13,13 +13,13 @@
#include <platform_def.h>
#include <nrd_plat.h>
-#include <rdfremont_rse_comms.h>
+#include <rdv3_rse_comms.h>
/*
* Platform specific table with image IDs and metadata. Intentionally not a
* const struct, some members might set by bootloaders during trusted boot.
*/
-struct rse_mboot_metadata rdfremont_rse_mboot_metadata[] = {
+struct rse_mboot_metadata rdv3_rse_mboot_metadata[] = {
{
.id = BL31_IMAGE_ID,
.slot = U(11),
@@ -60,7 +60,7 @@
/* Initialize the communication channel between AP and RSE */
(void)plat_rse_comms_init();
- rse_measured_boot_init(rdfremont_rse_mboot_metadata);
+ rse_measured_boot_init(rdv3_rse_mboot_metadata);
}
void bl2_plat_mboot_finish(void)
diff --git a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_bl2_setup.c b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl2_setup.c
similarity index 100%
rename from plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_bl2_setup.c
rename to plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl2_setup.c
diff --git a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_bl31_setup.c b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl31_setup.c
similarity index 80%
rename from plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_bl31_setup.c
rename to plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl31_setup.c
index 8544930..21675f6 100644
--- a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_bl31_setup.c
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_bl31_setup.c
@@ -13,10 +13,10 @@
#include <plat/common/platform.h>
#include <nrd_plat.h>
#include <nrd_variant.h>
-#include <rdfremont_rse_comms.h>
+#include <rdv3_rse_comms.h>
#if (NRD_PLATFORM_VARIANT == 2)
-static const mmap_region_t rdfremontmc_dynamic_mmap[] = {
+static const mmap_region_t rdv3mc_dynamic_mmap[] = {
#if NRD_CHIP_COUNT > 1
NRD_CSS_SHARED_RAM_MMAP(1),
NRD_CSS_PERIPH_MMAP(1),
@@ -31,7 +31,7 @@
#endif
};
-static struct gic600_multichip_data rdfremontmc_multichip_data __init = {
+static struct gic600_multichip_data rdv3mc_multichip_data __init = {
.rt_owner_base = PLAT_ARM_GICD_BASE,
.rt_owner = 0,
.chip_count = NRD_CHIP_COUNT,
@@ -61,7 +61,7 @@
}
};
-static uintptr_t rdfremontmc_multichip_gicr_frames[] = {
+static uintptr_t rdv3mc_multichip_gicr_frames[] = {
/* Chip 0's GICR Base */
PLAT_ARM_GICR_BASE,
#if NRD_CHIP_COUNT > 1
@@ -84,7 +84,7 @@
{
/*
* Perform SMMUv3 GPT configuration for the GPC SMMU present in system
- * control block on RD-Fremont platforms. This SMMUv3 initialization is
+ * control block on RD-V3 platforms. This SMMUv3 initialization is
* not fatal.
*
* Don't perform smmuv3_security_init() for this instance of SMMUv3 as
@@ -104,14 +104,14 @@
NRD_CHIP_COUNT);
panic();
} else {
- INFO("Enabling multi-chip support for RD-Fremont variant\n");
+ INFO("Enabling multi-chip support for RD-V3 variant\n");
- for (i = 0; i < ARRAY_SIZE(rdfremontmc_dynamic_mmap); i++) {
+ for (i = 0; i < ARRAY_SIZE(rdv3mc_dynamic_mmap); i++) {
ret = mmap_add_dynamic_region(
- rdfremontmc_dynamic_mmap[i].base_pa,
- rdfremontmc_dynamic_mmap[i].base_va,
- rdfremontmc_dynamic_mmap[i].size,
- rdfremontmc_dynamic_mmap[i].attr);
+ rdv3mc_dynamic_mmap[i].base_pa,
+ rdv3mc_dynamic_mmap[i].base_va,
+ rdv3mc_dynamic_mmap[i].size,
+ rdv3mc_dynamic_mmap[i].attr);
if (ret != 0) {
ERROR("Failed to add entry i: %d (ret=%d)\n",
i, ret);
@@ -120,8 +120,8 @@
}
plat_arm_override_gicr_frames(
- rdfremontmc_multichip_gicr_frames);
- gic600_multichip_init(&rdfremontmc_multichip_data);
+ rdv3mc_multichip_gicr_frames);
+ gic600_multichip_init(&rdv3mc_multichip_data);
}
#endif /* NRD_PLATFORM_VARIANT == 2 */
nrd_bl31_common_platform_setup();
diff --git a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_common.c b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c
similarity index 98%
rename from plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_common.c
rename to plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c
index 31cc2a0..10fe666 100644
--- a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_common.c
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c
@@ -11,8 +11,8 @@
#include <plat/common/platform.h>
#include <platform_def.h>
#include <nrd_plat.h>
-#include <rdfremont_mhuv3.h>
-#include <rdfremont_rse_comms.h>
+#include <rdv3_mhuv3.h>
+#include <rdv3_rse_comms.h>
unsigned int plat_arm_nrd_get_platform_id(void)
{
diff --git a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_common_measured_boot.c b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common_measured_boot.c
similarity index 76%
rename from plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_common_measured_boot.c
rename to plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common_measured_boot.c
index e95c544..f5160ce 100644
--- a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_common_measured_boot.c
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common_measured_boot.c
@@ -10,11 +10,11 @@
#include <common/desc_image_load.h>
#include <drivers/measured_boot/rse/rse_measured_boot.h>
-extern struct rse_mboot_metadata rdfremont_rse_mboot_metadata[];
+extern struct rse_mboot_metadata rdv3_rse_mboot_metadata[];
struct rse_mboot_metadata *plat_rse_mboot_get_metadata(void)
{
- return rdfremont_rse_mboot_metadata;
+ return rdv3_rse_mboot_metadata;
}
int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data)
@@ -22,7 +22,7 @@
int err;
/* Calculate image hash and record data in RSE */
- err = rse_mboot_measure_and_record(rdfremont_rse_mboot_metadata,
+ err = rse_mboot_measure_and_record(rdv3_rse_mboot_metadata,
image_data->image_base,
image_data->image_size,
image_id);
@@ -36,6 +36,6 @@
int plat_mboot_measure_key(void *pk_oid, void *pk_ptr, unsigned int pk_len)
{
- return rse_mboot_set_signer_id(rdfremont_rse_mboot_metadata, pk_oid,
+ return rse_mboot_set_signer_id(rdv3_rse_mboot_metadata, pk_oid,
pk_ptr, pk_len);
}
diff --git a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_err.c b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_err.c
similarity index 89%
rename from plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_err.c
rename to plat/arm/board/neoverse_rd/platform/rdv3/rdv3_err.c
index de6cc68..270febf 100644
--- a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_err.c
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_err.c
@@ -7,7 +7,7 @@
#include <plat/arm/common/plat_arm.h>
/*
- * rdfremont error handler
+ * rdv3 error handler
*/
void __dead2 plat_arm_error_handler(int err)
{
diff --git a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_mhuv3.c b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_mhuv3.c
similarity index 92%
rename from plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_mhuv3.c
rename to plat/arm/board/neoverse_rd/platform/rdv3/rdv3_mhuv3.c
index 41332cc..738f753 100644
--- a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_mhuv3.c
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_mhuv3.c
@@ -11,7 +11,7 @@
#include <nrd_css_def3.h>
#include <nrd_plat.h>
-#include <rdfremont_mhuv3.h>
+#include <rdv3_mhuv3.h>
void mhu_v3_get_secure_device_base(uintptr_t *base, bool sender)
{
diff --git a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_plat_attest_token.c b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_plat_attest_token.c
similarity index 100%
rename from plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_plat_attest_token.c
rename to plat/arm/board/neoverse_rd/platform/rdv3/rdv3_plat_attest_token.c
diff --git a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_realm_attest_key.c b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_realm_attest_key.c
similarity index 100%
rename from plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_realm_attest_key.c
rename to plat/arm/board/neoverse_rd/platform/rdv3/rdv3_realm_attest_key.c
diff --git a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_security.c b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_security.c
similarity index 100%
rename from plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_security.c
rename to plat/arm/board/neoverse_rd/platform/rdv3/rdv3_security.c
diff --git a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_topology.c b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_topology.c
similarity index 97%
rename from plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_topology.c
rename to plat/arm/board/neoverse_rd/platform/rdv3/rdv3_topology.c
index e7931d4..6eb5002 100644
--- a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_topology.c
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_topology.c
@@ -10,7 +10,7 @@
/******************************************************************************
* The power domain tree descriptor.
******************************************************************************/
-const unsigned char rd_fremont_pd_tree_desc[] = {
+const unsigned char rd_v3_pd_tree_desc[] = {
(PLAT_ARM_CLUSTER_COUNT) * (NRD_CHIP_COUNT),
NRD_MAX_CPUS_PER_CLUSTER,
NRD_MAX_CPUS_PER_CLUSTER,
@@ -44,7 +44,7 @@
******************************************************************************/
const unsigned char *plat_get_power_domain_tree_desc(void)
{
- return rd_fremont_pd_tree_desc;
+ return rd_v3_pd_tree_desc;
}
/*******************************************************************************
diff --git a/plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_trusted_boot.c b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_trusted_boot.c
similarity index 100%
rename from plat/arm/board/neoverse_rd/platform/rdfremont/rdfremont_trusted_boot.c
rename to plat/arm/board/neoverse_rd/platform/rdv3/rdv3_trusted_boot.c
diff --git a/plat/arm/board/tc/include/platform_def.h b/plat/arm/board/tc/include/platform_def.h
index 38413ef..45d17ba 100644
--- a/plat/arm/board/tc/include/platform_def.h
+++ b/plat/arm/board/tc/include/platform_def.h
@@ -7,6 +7,7 @@
#ifndef PLATFORM_DEF_H
#define PLATFORM_DEF_H
+#include <cortex_a520.h>
#include <lib/utils_def.h>
#include <lib/xlat_tables/xlat_tables_defs.h>
#include <plat/arm/board/common/board_css_def.h>
@@ -333,6 +334,7 @@
*/
#define PLAT_CSS_MAX_SCP_BL2U_SIZE 0x20000
+#if TARGET_PLATFORM <= 2
/* TZC Related Constants */
#define PLAT_ARM_TZC_BASE UL(0x25000000)
#define PLAT_ARM_TZC_FILTERS TZC_400_REGION_ATTR_FILTER_BIT(0)
@@ -360,6 +362,7 @@
PLAT_ARM_TZC_NS_DEV_ACCESS}, \
{PLAT_ARM_DRAM2_BASE, PLAT_ARM_DRAM2_END, \
ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS}
+#endif
/* virtual address used by dynamic mem_protect for chunk_base */
#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000)
@@ -444,6 +447,21 @@
#define SLC_DONT_ALLOC 0
#define SLC_ALWAYS_ALLOC 1
#define SLC_ALLOC_BUS_SIGNAL_ATTR 2
+
+#define MCN_CONFIG_OFFSET 0x204
+#define MCN_CONFIG_ADDR (MCN_BASE_ADDR + MCN_CONFIG_OFFSET)
+#define MCN_CONFIG_SLC_PRESENT_BIT 3
+
+/*
+ * TC3 CPUs have the same definitions for:
+ * CORTEX_{A520|A725|X925}_CPUECTLR_EL1
+ * CORTEX_{A520|A725|X925}_CPUECTLR_EL1_EXTLLC_BIT
+ * Define the common macros for easier using.
+ */
+#define CPUECTLR_EL1 CORTEX_A520_CPUECTLR_EL1
+#define CPUECTLR_EL1_EXTLLC_BIT CORTEX_A520_CPUECTLR_EL1_EXTLLC_BIT
#endif /* TARGET_PLATFORM == 3 */
+#define CPUACTLR_CLUSTERPMUEN (ULL(1) << 12)
+
#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/tc/include/tc_helpers.S b/plat/arm/board/tc/include/tc_helpers.S
index 5f54856..29130ea 100644
--- a/plat/arm/board/tc/include/tc_helpers.S
+++ b/plat/arm/board/tc/include/tc_helpers.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,6 +9,9 @@
#include <platform_def.h>
#include <cpu_macros.S>
+#define TC_HANDLER(rev) plat_reset_handler_tc##rev
+#define PLAT_RESET_HANDLER(rev) TC_HANDLER(rev)
+
.globl plat_arm_calc_core_pos
.globl plat_reset_handler
@@ -49,13 +52,42 @@
ret
endfunc plat_arm_calc_core_pos
+func mark_extllc_presence
+#ifdef MCN_CONFIG_ADDR
+ mov_imm x0, (MCN_CONFIG_ADDR)
+ ldr w1, [x0]
+ ubfx x1, x1, #MCN_CONFIG_SLC_PRESENT_BIT, #1
+ sysreg_bitfield_insert_from_gpr CPUECTLR_EL1, x1, \
+ CPUECTLR_EL1_EXTLLC_BIT, 1
+#endif
+ ret
+endfunc mark_extllc_presence
+
+func enable_dsu_pmu_el1_access
+ sysreg_bit_set actlr_el2, CPUACTLR_CLUSTERPMUEN
+ sysreg_bit_set actlr_el3, CPUACTLR_CLUSTERPMUEN
+ ret
+endfunc enable_dsu_pmu_el1_access
+
+func TC_HANDLER(2)
+ ret
+endfunc TC_HANDLER(2)
+
+func TC_HANDLER(3)
+ mov x9, lr
+ bl mark_extllc_presence
+ bl enable_dsu_pmu_el1_access
+ mov lr, x9
+ ret
+endfunc TC_HANDLER(3)
+
/* -----------------------------------------------------
* void plat_reset_handler(void);
- *
- * Determine the CPU MIDR and disable power down bit for
- * that CPU.
* -----------------------------------------------------
*/
func plat_reset_handler
+ mov x8, lr
+ bl PLAT_RESET_HANDLER(TARGET_PLATFORM)
+ mov lr, x8
ret
endfunc plat_reset_handler
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
index 28b98c2..1a7289a 100644
--- a/plat/arm/board/tc/platform.mk
+++ b/plat/arm/board/tc/platform.mk
@@ -33,12 +33,13 @@
ENABLE_AMU_AUXILIARY_COUNTERS := 1
ENABLE_MPMM := 1
ENABLE_MPMM_FCONF := 1
+ENABLE_FEAT_MTE2 := 2
+ENABLE_SPE_FOR_NS := 3
CTX_INCLUDE_AARCH32_REGS := 0
ifeq (${SPD},spmd)
SPMD_SPM_AT_SEL2 := 1
- ENABLE_FEAT_MTE2 := 1
CTX_INCLUDE_PAUTH_REGS := 1
endif
@@ -109,6 +110,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,12 +120,15 @@
# 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
-INTERCONNECT_SOURCES := ${TC_BASE}/tc_interconnect.c
+INTERCONNECT_SOURCES := ${TC_BASE}/tc_interconnect.c \
+ plat/arm/common/arm_ni.c
PLAT_BL_COMMON_SOURCES += ${TC_BASE}/tc_plat.c \
${TC_BASE}/include/tc_helpers.S
@@ -129,6 +136,7 @@
BL1_SOURCES += ${INTERCONNECT_SOURCES} \
${TC_CPU_SOURCES} \
${TC_BASE}/tc_trusted_boot.c \
+ ${TC_BASE}/tc_bl1_setup.c \
${TC_BASE}/tc_err.c \
drivers/arm/sbsa/sbsa.c
@@ -138,9 +146,12 @@
${TC_BASE}/tc_bl2_setup.c \
lib/utils/mem_region.c \
drivers/arm/tzc/tzc400.c \
- plat/arm/common/arm_tzc400.c \
plat/arm/common/arm_nor_psci_mem_protect.c
+ifeq ($(shell test $(TARGET_PLATFORM) -le 2; echo $$?),0)
+BL2_SOURCES += plat/arm/common/arm_tzc400.c
+endif
+
BL31_SOURCES += ${INTERCONNECT_SOURCES} \
${TC_CPU_SOURCES} \
${ENT_GIC_SOURCES} \
@@ -258,5 +269,4 @@
include plat/arm/common/arm_common.mk
include plat/arm/css/common/css_common.mk
-include plat/arm/soc/common/soc_css.mk
include plat/arm/board/common/board_common.mk
diff --git a/plat/arm/board/tc/tc_bl1_setup.c b/plat/arm/board/tc/tc_bl1_setup.c
new file mode 100644
index 0000000..aedc94f
--- /dev/null
+++ b/plat/arm/board/tc/tc_bl1_setup.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*******************************************************************************
+ * Perform any BL1 specific platform actions.
+ ******************************************************************************/
+
+void soc_css_init_nic400(void)
+{
+}
+
+void soc_css_init_pcie(void)
+{
+}
diff --git a/plat/arm/board/tc/tc_bl31_setup.c b/plat/arm/board/tc/tc_bl31_setup.c
index 7d1bc9c..53404df 100644
--- a/plat/arm/board/tc/tc_bl31_setup.c
+++ b/plat/arm/board/tc/tc_bl31_setup.c
@@ -110,6 +110,7 @@
#if TARGET_PLATFORM == 3
enable_ns_mcn_pmu();
set_mcn_slc_alloc_mode();
+ plat_arm_ni_setup(NCI_BASE_ADDR);
#endif
}
diff --git a/plat/arm/board/tc/tc_security.c b/plat/arm/board/tc/tc_security.c
index 6a34501..7c7a1a1 100644
--- a/plat/arm/board/tc/tc_security.c
+++ b/plat/arm/board/tc/tc_security.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,17 +7,21 @@
#include <plat/arm/common/plat_arm.h>
#include <platform_def.h>
+#if (TARGET_PLATFORM <= 2)
static const arm_tzc_regions_info_t tzc_regions[] = {
TC_TZC_REGIONS_DEF,
{}
};
+#endif
/* Initialize the secure environment */
void plat_arm_security_setup(void)
{
+#if (TARGET_PLATFORM <= 2)
unsigned int i;
for (i = 0U; i < TZC400_COUNT; i++) {
arm_tzc400_setup(TZC400_BASE(i), tzc_regions);
}
+#endif
}
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 58a14ab..b5a7db1 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -162,16 +162,6 @@
#if defined(PLAT_ARM_MEM_PROT_ADDR)
arm_nor_psci_do_static_mem_protect();
#endif
-
-#if TRANSFER_LIST
- ns_tl = transfer_list_init((void *)FW_NS_HANDOFF_BASE,
- PLAT_ARM_FW_HANDOFF_SIZE);
-
- if (ns_tl == NULL) {
- ERROR("Non-secure transfer list initialisation failed!");
- panic();
- }
-#endif
}
void bl2_platform_setup(void)
@@ -326,7 +316,8 @@
#if TRANSFER_LIST
if (image_id == HW_CONFIG_ID) {
- arm_transfer_list_copy_hw_config(secure_tl, ns_tl);
+ /* Refresh the now stale checksum following loading of HW_CONFIG into the TL. */
+ transfer_list_update_checksum(secure_tl);
}
#endif /* TRANSFER_LIST */
@@ -335,8 +326,10 @@
void arm_bl2_setup_next_ep_info(bl_mem_params_node_t *next_param_node)
{
- assert(transfer_list_set_handoff_args(
- secure_tl, &next_param_node->ep_info) != NULL);
+ entry_point_info_t *ep __unused;
+ ep = transfer_list_set_handoff_args(secure_tl,
+ &next_param_node->ep_info);
+ assert(ep != NULL);
- arm_transfer_list_populate_ep_info(next_param_node, secure_tl, ns_tl);
+ arm_transfer_list_populate_ep_info(next_param_node, secure_tl);
}
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index b7941ec..e91746b 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -25,6 +25,8 @@
#include <platform_def.h>
static struct transfer_list_header *secure_tl __unused;
+static struct transfer_list_header *ns_tl __unused;
+
/*
* Placeholder variables for copying the arguments that have been passed to
* BL31 from BL2.
@@ -95,7 +97,12 @@
assert(sec_state_is_valid(type));
if (type == NON_SECURE) {
+#if TRANSFER_LIST && !RESET_TO_BL31
+ next_image_info = transfer_list_set_handoff_args(
+ ns_tl, &bl33_image_ep_info);
+#else
next_image_info = &bl33_image_ep_info;
+#endif
}
#if ENABLE_RME
else if (type == REALM) {
@@ -128,6 +135,24 @@
void __init arm_bl31_early_platform_setup(u_register_t arg0, u_register_t arg1,
u_register_t arg2, u_register_t arg3)
{
+#if RESET_TO_BL31
+ /* Populate entry point information for BL33 */
+ SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
+ /*
+ * Tell BL31 where the non-trusted software image
+ * is located and the entry state information
+ */
+ bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+
+ bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry();
+ SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
+
+ bl33_image_ep_info.args.arg0 =
+ FW_NS_HANDOFF_BASE + ARM_PRELOADED_DTB_OFFSET;
+ bl33_image_ep_info.args.arg1 =
+ TRANSFER_LIST_HANDOFF_X1_VALUE(REGISTER_CONVENTION_VERSION);
+ bl33_image_ep_info.args.arg3 = FW_NS_HANDOFF_BASE;
+#else
struct transfer_list_entry *te = NULL;
struct entry_point_info *ep;
@@ -160,6 +185,7 @@
}
}
}
+#endif /* RESET_TO_BL31 */
}
#else
void __init arm_bl31_early_platform_setup(void *from_bl2, uintptr_t soc_fw_config,
@@ -338,6 +364,28 @@
******************************************************************************/
void arm_bl31_platform_setup(void)
{
+ struct transfer_list_entry *te __unused;
+
+#if TRANSFER_LIST && !RESET_TO_BL31
+ /* Initialise the non-secure world tl, BL31 may modify the HW_CONFIG so defer
+ * copying it until later.
+ */
+ ns_tl = transfer_list_init((void *)FW_NS_HANDOFF_BASE,
+ PLAT_ARM_FW_HANDOFF_SIZE);
+
+ if (ns_tl == NULL) {
+ ERROR("Non-secure transfer list initialisation failed!");
+ panic();
+ }
+
+#if !RESET_TO_BL2
+ te = transfer_list_find(secure_tl, TL_TAG_FDT);
+ assert(te != NULL);
+
+ fconf_populate("HW_CONFIG", (uintptr_t)transfer_list_entry_data(te));
+#endif /* !(RESET_TO_BL2 && RESET_TO_BL31) */
+#endif /* TRANSFER_LIST */
+
/* Initialize the GIC driver, cpu and distributor interfaces */
plat_arm_gic_driver_init();
plat_arm_gic_init();
@@ -380,9 +428,26 @@
******************************************************************************/
void arm_bl31_plat_runtime_setup(void)
{
+ struct transfer_list_entry *te __unused;
/* Initialize the runtime console */
arm_console_runtime_init();
+#if TRANSFER_LIST && !RESET_TO_BL31
+ te = transfer_list_find(secure_tl, TL_TAG_FDT);
+ assert(te != NULL);
+
+ te = transfer_list_add(ns_tl, TL_TAG_FDT, te->data_size,
+ transfer_list_entry_data(te));
+ assert(te != NULL);
+
+ /*
+ * We assume BL31 has added all TE's required by BL33 at this stage, ensure
+ * that data is visible to all observers by performing a flush operation, so
+ * they can access the updated data even if caching is not enabled.
+ */
+ flush_dcache_range((uintptr_t)ns_tl, ns_tl->size);
+#endif /* TRANSFER_LIST && !(RESET_TO_BL2 || RESET_TO_BL31) */
+
#if RECLAIM_INIT_CODE
arm_free_init_memory();
#endif
@@ -497,15 +562,5 @@
void __init bl31_plat_arch_setup(void)
{
- struct transfer_list_entry *te __unused;
-
arm_bl31_plat_arch_setup();
-
-#if TRANSFER_LIST && !RESET_TO_BL2
- te = transfer_list_find(secure_tl, TL_TAG_FDT);
- assert(te != NULL);
-
- /* Populate HW_CONFIG device tree with the mapped address */
- fconf_populate("HW_CONFIG", (uintptr_t)transfer_list_entry_data(te));
-#endif
}
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index f5919ab..dff0135 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -377,30 +377,38 @@
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
+ bl2: cot-dt2c
+ endif
+
BL1_SOURCES += ${AUTH_SOURCES} \
bl1/tbbr/tbbr_img_desc.c \
plat/arm/common/arm_bl1_fwu.c \
@@ -458,3 +466,31 @@
$(error To reclaim init code xlat tables v2 must be used)
endif
endif
+
+TRANSFER_LIST_BIN := ${BUILD_PLAT}/tl.bin
+
+.PHONY: tl
+tl: ${HW_CONFIG}
+ @echo " TLC ${TRANSFER_LIST_BIN}"
+ $(Q)${PYTHON} -m tools.tlc.tlc create --fdt ${HW_CONFIG} -s ${FW_HANDOFF_SIZE} ${TRANSFER_LIST_BIN}
+ $(Q)$(eval ARM_PRELOADED_DTB_OFFSET := `tlc info --fdt-offset ${TRANSFER_LIST_BIN}`)
+
+ifeq (${TRANSFER_LIST}, 1)
+ ifeq (${RESET_TO_BL31}, 1)
+ bl31: tl
+ endif
+endif
+
+cot-dt2c:
+ifneq ($(COTDTPATH),)
+ $(info COT CONVERSION FOR ${COTDTPATH})
+ toolpath := $(shell which cot-dt2c)
+ ifeq (${toolpath},)
+ output := $(shell make -C ./${CERTCONVPATH} install)
+ $(info install output ${output})
+ toolpath := $(shell which cot-dt2c)
+ endif
+ output := $(shell ${toolpath} convert-to-c ${COTDTPATH} ${BUILD_PLAT}/bl2_cot.c)
+ $(info ${output})
+ BL2_SOURCES += ${BUILD_PLAT}/bl2_cot.c
+endif
diff --git a/plat/arm/common/arm_io_storage.c b/plat/arm/common/arm_io_storage.c
index 19ee1b0..5a3d27a 100644
--- a/plat/arm/common/arm_io_storage.c
+++ b/plat/arm/common/arm_io_storage.c
@@ -124,6 +124,7 @@
const struct plat_io_policy *policy;
policy = FCONF_GET_PROPERTY(arm, io_policies, image_id);
+ assert(policy->check != NULL);
result = policy->check(policy->image_spec);
if (result == 0) {
*image_spec = policy->image_spec;
diff --git a/plat/arm/common/arm_ni.c b/plat/arm/common/arm_ni.c
new file mode 100644
index 0000000..b3ad8b3
--- /dev/null
+++ b/plat/arm/common/arm_ni.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2024, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <common/debug.h>
+#include <plat/arm/common/plat_arm.h>
+#include <platform_def.h>
+
+#define NI_CHILD_NODE_COUNT 4
+#define NI_CHILD_POINTERS_START 8
+
+#define NI_PMU_SECURE_CTRL 0x100
+#define NI_PMU_SECURE_EVENT_OBSERVATION 0x108
+#define NI_PMU_DEBUG_ENABLE 0x110
+#define NI_COMP_NUM_SUBFEATURES 0x100
+#define NI_COMP_SUBFEATURE_TYPE_START 0x108
+#define NI_COMP_SUBFEATURE_SECURE_CTRL_START 0x308
+
+#define SECURE_OVERRIDE_DEFAULT BIT(0)
+#define SECURE_EVENT_ENABLE BIT(2)
+#define NA_EVENT_ENABLE BIT(3)
+#define PMU_ENABLE BIT(0)
+
+#define NI_NODE_MASK 0x0000ffff
+#define NI_NODE_TYPE(node_info) (node_info & NI_NODE_MASK)
+#define NI_CHILD_POINTER(i) (NI_CHILD_POINTERS_START + (i * 4))
+#define NI_COMP_SUBFEATURE_TYPE(i) (NI_COMP_SUBFEATURE_TYPE_START + (i * 8))
+#define NI_COMP_SUBFEATURE_SECURE_CTRL(i) (NI_COMP_SUBFEATURE_SECURE_CTRL_START + (i * 8))
+
+#define NI_PERIPHERAL_ID0 0xfe0
+#define NI_PIDR0_PART_MASK 0xff
+#define NI_PERIPHERAL_ID1 0xfe4
+#define NI_PIDR1_PART_MASK 0xf
+#define NI_PIDR1_PART_SHIFT 8
+
+enum ni_part {
+ NI_700 = 0x43b,
+ NI_710AE = 0x43d,
+ NI_TOWER = 0x43f,
+};
+
+enum ni_node_type {
+ NI_INVALID_NODE = 0,
+ NI_VOLTAGE_DOMAIN = 1,
+ NI_POWER_DOMAIN = 2,
+ NI_CLOCK_DOMAIN = 3,
+ NI_ASNI = 4,
+ NI_AMNI = 5,
+ NI_PMU = 6,
+ NI_HSNI = 7,
+ NI_HMNI = 8,
+ NI_PMNI = 9,
+ NI_CMNI = 14,
+ NI_CFGNI = 15
+};
+
+enum ni_subfeature_type {
+ NI_SUBFEATURE_APU = 0,
+ NI_SUBFEATURE_ADDR_MAP = 1,
+ NI_SUBFEATURE_FCU = 2,
+ NI_SUBFEATURE_IDM = 3
+};
+
+static void ni_enable_pmu(uintptr_t pmu_addr)
+{
+ mmio_setbits_32(pmu_addr + NI_PMU_DEBUG_ENABLE, PMU_ENABLE);
+}
+
+static void ni_enable_fcu_ns_access(uintptr_t comp_addr)
+{
+ uint32_t subfeature_type;
+ uint32_t subfeature_count;
+ uint32_t subfeature_secure_ctrl;
+
+ subfeature_count = mmio_read_32(comp_addr + NI_COMP_NUM_SUBFEATURES);
+ for (uint32_t i = 0U; i < subfeature_count; i++) {
+ subfeature_type =
+ NI_NODE_TYPE(mmio_read_32(comp_addr + NI_COMP_SUBFEATURE_TYPE(i)));
+ if (subfeature_type == NI_SUBFEATURE_FCU) {
+ subfeature_secure_ctrl = comp_addr + NI_COMP_SUBFEATURE_SECURE_CTRL(i);
+ mmio_setbits_32(subfeature_secure_ctrl, SECURE_OVERRIDE_DEFAULT);
+ }
+ }
+}
+
+static void ni_enable_pmu_ns_access(uintptr_t comp_addr)
+{
+ mmio_setbits_32(comp_addr + NI_PMU_SECURE_CTRL, SECURE_OVERRIDE_DEFAULT);
+ mmio_setbits_32(comp_addr + NI_PMU_SECURE_EVENT_OBSERVATION,
+ SECURE_EVENT_ENABLE | NA_EVENT_ENABLE);
+}
+
+static void ni_setup_component(uintptr_t comp_addr)
+{
+ uint32_t node_info;
+
+ node_info = mmio_read_32(comp_addr);
+
+ switch (NI_NODE_TYPE(node_info)) {
+ case NI_ASNI:
+ case NI_AMNI:
+ case NI_HSNI:
+ case NI_HMNI:
+ case NI_PMNI:
+ ni_enable_fcu_ns_access(comp_addr);
+ break;
+ case NI_PMU:
+ ni_enable_pmu_ns_access(comp_addr);
+ ni_enable_pmu(comp_addr);
+ break;
+ default:
+ return;
+ }
+}
+
+int plat_arm_ni_setup(uintptr_t global_cfg)
+{
+ uintptr_t vd_addr;
+ uintptr_t pd_addr;
+ uintptr_t cd_addr;
+ uintptr_t comp_addr;
+ uint32_t vd_count;
+ uint32_t pd_count;
+ uint32_t cd_count;
+ uint32_t comp_count;
+ uint32_t part;
+ uint32_t reg;
+
+ reg = mmio_read_32(global_cfg + NI_PERIPHERAL_ID0);
+ part = reg & NI_PIDR0_PART_MASK;
+ reg = mmio_read_32(global_cfg + NI_PERIPHERAL_ID1);
+ part |= ((reg & NI_PIDR1_PART_MASK) << NI_PIDR1_PART_SHIFT);
+
+ if (part != NI_TOWER) {
+ ERROR("0x%x is not supported\n", part);
+ return -EINVAL;
+ }
+
+ vd_count = mmio_read_32(global_cfg + NI_CHILD_NODE_COUNT);
+
+ for (uint32_t i = 0U; i < vd_count; i++) {
+ vd_addr = global_cfg + mmio_read_32(global_cfg + NI_CHILD_POINTER(i));
+ pd_count = mmio_read_32(vd_addr + NI_CHILD_NODE_COUNT);
+
+ for (uint32_t j = 0U; j < pd_count; j++) {
+ pd_addr = global_cfg + mmio_read_32(vd_addr + NI_CHILD_POINTER(j));
+ cd_count = mmio_read_32(pd_addr + NI_CHILD_NODE_COUNT);
+
+ for (uint32_t k = 0U; k < cd_count; k++) {
+ cd_addr = global_cfg + mmio_read_32(pd_addr + NI_CHILD_POINTER(k));
+ comp_count = mmio_read_32(cd_addr + NI_CHILD_NODE_COUNT);
+
+ for (uint32_t l = 0U; l < comp_count; l++) {
+ comp_addr = global_cfg +
+ mmio_read_32(cd_addr + NI_CHILD_POINTER(l));
+ ni_setup_component(comp_addr);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/plat/arm/common/arm_transfer_list.c b/plat/arm/common/arm_transfer_list.c
index d144bbb..59fb039 100644
--- a/plat/arm/common/arm_transfer_list.c
+++ b/plat/arm/common/arm_transfer_list.c
@@ -30,8 +30,7 @@
}
void arm_transfer_list_populate_ep_info(bl_mem_params_node_t *next_param_node,
- struct transfer_list_header *secure_tl,
- struct transfer_list_header *ns_tl)
+ struct transfer_list_header *secure_tl)
{
uint32_t next_exe_img_id;
entry_point_info_t *ep;
@@ -53,10 +52,7 @@
ep = transfer_list_entry_data(te);
- if (next_exe_img_id == BL33_IMAGE_ID) {
- ep = transfer_list_set_handoff_args(ns_tl, ep);
- assert(ep != NULL);
- } else if ((next_exe_img_id == BL32_IMAGE_ID) && SPMC_AT_EL3) {
+ if ((next_exe_img_id == BL32_IMAGE_ID) && SPMC_AT_EL3) {
/*
* Populate the BL32 image base, size and max limit in
* the entry point information, since there is no
@@ -78,19 +74,3 @@
flush_dcache_range((uintptr_t)secure_tl, secure_tl->size);
}
-
-void arm_transfer_list_copy_hw_config(struct transfer_list_header *secure_tl,
- struct transfer_list_header *ns_tl)
-{
- struct transfer_list_entry *te =
- transfer_list_find(secure_tl, TL_TAG_FDT);
- assert(te != NULL);
-
- /* Refresh the now stale checksum following loading of HW_CONFIG into the TL. */
- transfer_list_update_checksum(secure_tl);
-
- /* Copy the hardware configuration to the non-secure TL. */
- te = transfer_list_add(ns_tl, TL_TAG_FDT, te->data_size,
- transfer_list_entry_data(te));
- assert(te != NULL);
-}
diff --git a/plat/aspeed/ast2700/plat_bl31_setup.c b/plat/aspeed/ast2700/plat_bl31_setup.c
index 9fec3e8..087b479 100644
--- a/plat/aspeed/ast2700/plat_bl31_setup.c
+++ b/plat/aspeed/ast2700/plat_bl31_setup.c
@@ -174,7 +174,7 @@
break;
}
} else {
- if (pll_reg.b.bypass != 0U) {
+ if (pll_reg.b.bypass == 0U) {
if (pll_idx == PLAT_CLK_MPLL) {
/* F = 25Mhz * [M / (n + 1)] / (p + 1) */
mul = (pll_reg.b.m) / ((pll_reg.b.n + 1));
diff --git a/plat/imx/imx7/common/imx7.mk b/plat/imx/imx7/common/imx7.mk
index 950d8fd..2bda3a5 100644
--- a/plat/imx/imx7/common/imx7.mk
+++ b/plat/imx/imx7/common/imx7.mk
@@ -71,7 +71,6 @@
ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin
$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
-$(eval $(call MAKE_LIB_DIRS))
$(BUILD_PLAT)/bl2/imx7_rotpk.o: $(ROTPK_HASH)
diff --git a/plat/imx/imx8m/imx8mm/platform.mk b/plat/imx/imx8m/imx8mm/platform.mk
index 40554c3..f0cdb3e 100644
--- a/plat/imx/imx8m/imx8mm/platform.mk
+++ b/plat/imx/imx8m/imx8mm/platform.mk
@@ -127,7 +127,6 @@
ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin
$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
-$(eval $(call MAKE_LIB_DIRS))
$(BUILD_PLAT)/bl2/imx8mm_rotpk.o: $(ROTPK_HASH)
diff --git a/plat/imx/imx8m/imx8mp/platform.mk b/plat/imx/imx8m/imx8mp/platform.mk
index 5f4ddee..5df598c 100644
--- a/plat/imx/imx8m/imx8mp/platform.mk
+++ b/plat/imx/imx8m/imx8mp/platform.mk
@@ -124,7 +124,6 @@
ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin
$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
-$(eval $(call MAKE_LIB_DIRS))
$(BUILD_PLAT)/bl2/imx8mp_rotpk.o: $(ROTPK_HASH)
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/qspi/cadence_qspi.c b/plat/intel/soc/common/drivers/qspi/cadence_qspi.c
index 6d8825f..18aa48e 100644
--- a/plat/intel/soc/common/drivers/qspi/cadence_qspi.c
+++ b/plat/intel/soc/common/drivers/qspi/cadence_qspi.c
@@ -14,6 +14,7 @@
#include "cadence_qspi.h"
#include "socfpga_plat_def.h"
+#include "wdt/watchdog.h"
#define LESS(a, b) (((a) < (b)) ? (a) : (b))
#define MORE(a, b) (((a) > (b)) ? (a) : (b))
@@ -654,6 +655,9 @@
read_count += level * sizeof(uint8_t);
count++;
+#if ARM_LINUX_KERNEL_AS_BL33
+ watchdog_sw_rst();
+#endif
} while (level > 0);
}
diff --git a/plat/intel/soc/common/include/socfpga_mailbox.h b/plat/intel/soc/common/include/socfpga_mailbox.h
index 3e44833..fcee101 100644
--- a/plat/intel/soc/common/include/socfpga_mailbox.h
+++ b/plat/intel/soc/common/include/socfpga_mailbox.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
*/
@@ -75,6 +76,7 @@
#define MBOX_RSU_STATUS 0x5B
#define MBOX_RSU_UPDATE 0x5C
#define MBOX_HPS_STAGE_NOTIFY 0x5D
+#define MBOX_RSU_GET_DEVICE_INFO 0x74
/* FCS Command */
#define MBOX_FCS_GET_PROVISION 0x7B
@@ -249,6 +251,7 @@
int mailbox_rsu_get_spt_offset(uint32_t *resp_buf, uint32_t resp_buf_len);
int mailbox_rsu_status(uint32_t *resp_buf, uint32_t resp_buf_len);
+int mailbox_rsu_get_device_info(uint32_t *resp_buf, uint32_t resp_buf_len);
int mailbox_rsu_update(uint32_t *flash_offset);
int mailbox_hps_stage_notify(uint32_t execution_stage);
int mailbox_hwmon_readtemp(uint32_t chan, uint32_t *resp_buf);
diff --git a/plat/intel/soc/common/include/socfpga_sip_svc.h b/plat/intel/soc/common/include/socfpga_sip_svc.h
index d45ab11..d2eceb9 100644
--- a/plat/intel/soc/common/include/socfpga_sip_svc.h
+++ b/plat/intel/soc/common/include/socfpga_sip_svc.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
*/
@@ -64,6 +65,7 @@
#define INTEL_SIP_SMC_RSU_COPY_MAX_RETRY 0xC2000013
#define INTEL_SIP_SMC_RSU_DCMF_STATUS 0xC2000014
#define INTEL_SIP_SMC_RSU_COPY_DCMF_STATUS 0xC2000015
+#define INTEL_SIP_SMC_RSU_GET_DEVICE_INFO 0xC2000016
/* Hardware monitor */
#define INTEL_SIP_SMC_HWMON_READTEMP 0xC2000020
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/soc/socfpga_mailbox.c b/plat/intel/soc/common/soc/socfpga_mailbox.c
index e2a25ea..b8e5cde 100644
--- a/plat/intel/soc/common/soc/socfpga_mailbox.c
+++ b/plat/intel/soc/common/soc/socfpga_mailbox.c
@@ -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
*/
@@ -578,6 +579,13 @@
return ret;
}
+int mailbox_rsu_get_device_info(uint32_t *resp_buf, unsigned int resp_buf_len)
+{
+ return mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_GET_DEVICE_INFO, NULL, 0U,
+ CMD_CASUAL, resp_buf,
+ &resp_buf_len);
+}
+
int mailbox_rsu_update(uint32_t *flash_offset)
{
return mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_UPDATE,
diff --git a/plat/intel/soc/common/soc/socfpga_reset_manager.c b/plat/intel/soc/common/soc/socfpga_reset_manager.c
index 5204146..5c80798 100644
--- a/plat/intel/soc/common/soc/socfpga_reset_manager.c
+++ b/plat/intel/soc/common/soc/socfpga_reset_manager.c
@@ -777,14 +777,6 @@
VERBOSE("Deassert F2SDRAM ...\n");
mmio_clrbits_32(SOCFPGA_RSTMGR(BRGMODRST),
RSTMGR_BRGMODRST_F2SSDRAM0);
-
- /*
- * Clear fpga2sdram_manager_main_SidebandManager_FlagOutClr0
- * f2s_ready_latency_enable
- */
- VERBOSE("Clear F2SDRAM f2s_ready_latency_enable ...\n");
- mmio_setbits_32(SOCFPGA_F2SDRAMMGR(SIDEBANDMGR_FLAGOUTCLR0),
- FLAGOUTCLR0_F2SDRAM0_ENABLE);
}
#else
if (brg_mask != 0U) {
diff --git a/plat/intel/soc/common/socfpga_sip_svc.c b/plat/intel/soc/common/socfpga_sip_svc.c
index f68dc29..5dfbc14 100644
--- a/plat/intel/soc/common/socfpga_sip_svc.c
+++ b/plat/intel/soc/common/socfpga_sip_svc.c
@@ -1,5 +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
*/
@@ -417,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 */
@@ -507,6 +510,16 @@
return INTEL_SIP_SMC_STATUS_OK;
}
+static uint32_t intel_rsu_get_device_info(uint32_t *respbuf,
+ unsigned int respbuf_sz)
+{
+ if (mailbox_rsu_get_device_info((uint32_t *)respbuf, respbuf_sz) < 0) {
+ return INTEL_SIP_SMC_RSU_ERROR;
+ }
+
+ return INTEL_SIP_SMC_STATUS_OK;
+}
+
uint32_t intel_rsu_update(uint64_t update_address)
{
if (update_address > SIZE_MAX) {
@@ -878,6 +891,16 @@
status = intel_rsu_copy_dcmf_version(x1, x2);
SMC_RET1(handle, status);
+ case INTEL_SIP_SMC_RSU_GET_DEVICE_INFO:
+ status = intel_rsu_get_device_info((uint32_t *)rsu_respbuf,
+ ARRAY_SIZE(rsu_respbuf));
+ if (status) {
+ SMC_RET1(handle, status);
+ } else {
+ SMC_RET5(handle, status, rsu_respbuf[0], rsu_respbuf[1],
+ rsu_respbuf[2], rsu_respbuf[3]);
+ }
+
case INTEL_SIP_SMC_RSU_DCMF_STATUS:
SMC_RET2(handle, INTEL_SIP_SMC_STATUS_OK,
((uint64_t)rsu_dcmf_stat[3] << 48) |
diff --git a/plat/intel/soc/common/socfpga_vab.c b/plat/intel/soc/common/socfpga_vab.c
index e16610c..d1734c8 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,46 @@
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);
-
- /* 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;
- // }
+ VERBOSE("mbox_data_addr = %lx mbox_data_sz = %d\n", mbox_data_addr, mbox_data_sz);
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 +134,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 +145,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/marvell/armada/a3k/common/a3700_common.mk b/plat/marvell/armada/a3k/common/a3700_common.mk
index 18f5430..e8f892d 100644
--- a/plat/marvell/armada/a3k/common/a3700_common.mk
+++ b/plat/marvell/armada/a3k/common/a3700_common.mk
@@ -167,10 +167,9 @@
$(if $(shell git -C $(value MV_DDR_PATH) rev-parse --show-cdup 2>&1),$(error "'MV_DDR_PATH=$(value MV_DDR_PATH)' was specified, but '$(value MV_DDR_PATH)' does not contain valid mv-ddr-marvell git repository"))
$(q)$(MAKE) --no-print-directory -C $(WTP) MV_DDR_PATH=$(MV_DDR_PATH) DDR_TOPOLOGY=$(DDR_TOPOLOGY) mv_ddr
-$(BUILD_PLAT)/$(UART_IMAGE): $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/wtmi.bin $(TBB) $(TIMBUILD) $(TIMDDRTOOL)
+$(BUILD_PLAT)/$(UART_IMAGE): $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/wtmi.bin $(TBB) $(TIMBUILD) $(TIMDDRTOOL) | $(BUILD_PLAT)/$(BUILD_UART)/ $$(@D)/
$(s)echo
$(s)echo "Building uart images"
- $(q)mkdir -p $(BUILD_PLAT)/$(BUILD_UART)
$(q)cp -a $(BUILD_PLAT)/wtmi.bin $(BUILD_PLAT)/$(BUILD_UART)/wtmi.bin
$(q)cp -a $(BUILD_PLAT)/$(BOOT_IMAGE) $(BUILD_PLAT)/$(BUILD_UART)/$(BOOT_IMAGE)
$(q)cd $(BUILD_PLAT)/$(BUILD_UART) && $(TIMBUILD) $(TIMBLDUARTARGS)
diff --git a/plat/mediatek/build_helpers/mtk_build_helpers.mk b/plat/mediatek/build_helpers/mtk_build_helpers.mk
index 87a7db4..0cb2014 100644
--- a/plat/mediatek/build_helpers/mtk_build_helpers.mk
+++ b/plat/mediatek/build_helpers/mtk_build_helpers.mk
@@ -29,7 +29,7 @@
ifdef $(1)
ifeq ($(strip $(value $(1))),y)
DEFINES += -D$(1)$(if $(value $(1)),=1,)
-else
+else ifneq ($(strip $(value $(1))),n)
DEFINES += -D$(1)$(if $(value $(1)),=$(value $(1)),)
endif
endif
@@ -71,15 +71,6 @@
$(eval SOURCES := $(2))
$(eval OBJS_TEMP := $(addprefix $(BUILD_DIR)/$(MODULE)/,$(call SOURCES_TO_OBJS,$(SOURCES))))
$(eval MODULE_OBJS += $(OBJS_TEMP))
- # We use sort only to get a list of unique object directory names.
- # ordering is not relevant but sort removes duplicates.
- $(eval TEMP_OBJ_DIRS := $(sort $(dir ${OBJS_TEMP} ${LINKERFILE})))
- # The $(dir ) function leaves a trailing / on the directory names
- # Rip off the / to match directory names with make rule targets.
- $(eval OBJ_DIRS := $(patsubst %/,%,$(TEMP_OBJ_DIRS)))
-
-$(eval $(foreach objd,${OBJ_DIRS},$(call MAKE_PREREQ_DIR,${objd},${BUILD_DIR})))
-${3}_dirs: | ${OBJ_DIRS}
$(eval $(call MAKE_OBJS,$(BUILD_DIR)/$(MODULE),$(SOURCES),${3}))
diff --git a/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu.c b/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu.c
index f7ed5e6..c46cca8 100644
--- a/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu.c
+++ b/plat/mediatek/drivers/emi_mpu/mt8188/emi_mpu.c
@@ -25,6 +25,7 @@
FORBIDDEN, FORBIDDEN, FORBIDDEN, SEC_RW);
emi_mpu_set_protection(®ion_info);
+#ifndef SPD_NONE
/* BL32 address */
region_info.start = BL32_REGION_BASE;
region_info.end = BL32_REGION_BASE + BL32_REGION_SIZE - 1;
@@ -35,6 +36,7 @@
FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
FORBIDDEN, FORBIDDEN, SEC_RW, SEC_RW);
emi_mpu_set_protection(®ion_info);
+#endif
/* SCP core0 DRAM */
region_info.start = SCP_CORE0_REGION_BASE;
@@ -118,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;
}
@@ -133,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,
@@ -142,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/nvidia/tegra/common/tegra_fiq_glue.c b/plat/nvidia/tegra/common/tegra_fiq_glue.c
index 5309d98..4ff9888 100644
--- a/plat/nvidia/tegra/common/tegra_fiq_glue.c
+++ b/plat/nvidia/tegra/common/tegra_fiq_glue.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -142,7 +142,7 @@
val = read_ctx_reg((gpregs_ctx), (uint32_t)(CTX_GPREG_SP_EL0));
write_ctx_reg((gpregs_ctx), (uint32_t)(CTX_GPREG_X2), (val));
- val = read_ctx_reg((el1state_ctx), (uint32_t)(CTX_SP_EL1));
+ val = read_el1_ctx_common(el1state_ctx, sp_el1);
write_ctx_reg((gpregs_ctx), (uint32_t)(CTX_GPREG_X3), (val));
return 0;
diff --git a/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
index 83d815a..8232883 100644
--- a/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c
@@ -356,10 +356,10 @@
* will re-init this info from non-secure software when the
* core come online.
*/
- actlr_elx = read_ctx_reg((get_el1_sysregs_ctx(ctx)), (CTX_ACTLR_EL1));
+ actlr_elx = read_el1_ctx_common((get_el1_sysregs_ctx(ctx)), actlr_el1);
actlr_elx &= ~DENVER_CPU_PMSTATE_MASK;
actlr_elx |= DENVER_CPU_PMSTATE_C1;
- write_ctx_reg((get_el1_sysregs_ctx(ctx)), (CTX_ACTLR_EL1), (actlr_elx));
+ write_el1_ctx_common((get_el1_sysregs_ctx(ctx)), actlr_el1, actlr_elx);
/*
* Check if we are exiting from deep sleep and restore SE
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/nxp/soc-lx2160a/ddr_fip.mk b/plat/nxp/soc-lx2160a/ddr_fip.mk
index e717cbc..c303ced 100644
--- a/plat/nxp/soc-lx2160a/ddr_fip.mk
+++ b/plat/nxp/soc-lx2160a/ddr_fip.mk
@@ -38,8 +38,6 @@
DDR_DMEM_RDIMM_2D := ${DDR_PHY_BIN_PATH}/ddr4_rdimm2d_pmu_train_dmem.bin
endif
-$(shell mkdir -p '${BUILD_PLAT}')
-
ifeq (${DDR_FIP_NAME},)
ifeq (${TRUSTED_BOARD_BOOT},1)
DDR_FIP_NAME := ddr_fip_sec.bin
diff --git a/plat/nxp/soc-lx2160a/ddr_tbbr.mk b/plat/nxp/soc-lx2160a/ddr_tbbr.mk
index deb475b..836a431 100644
--- a/plat/nxp/soc-lx2160a/ddr_tbbr.mk
+++ b/plat/nxp/soc-lx2160a/ddr_tbbr.mk
@@ -39,8 +39,6 @@
# Pass the non-volatile counters to the cert_create tool
$(eval $(call CERT_ADD_CMD_OPT,${TFW_NVCTR_VAL},--tfw-nvctr,DDR_))
-$(shell mkdir -p '${BUILD_PLAT}')
-
ifeq (${DDR_KEY},)
DDR_KEY=${BUILD_PLAT}/ddr.pem
endif
diff --git a/plat/qemu/common/qemu_bl2_setup.c b/plat/qemu/common/qemu_bl2_setup.c
index d752b6c..c96e4b9 100644
--- a/plat/qemu/common/qemu_bl2_setup.c
+++ b/plat/qemu/common/qemu_bl2_setup.c
@@ -357,12 +357,20 @@
case BL31_IMAGE_ID:
/*
* arg0 is a bl_params_t reserved for bl31_early_platform_setup2
- * we just need arg1 and arg3 for BL31 to update th TL from S
+ * we just need arg1 and arg3 for BL31 to update the TL from S
* to NS memory before it exits
*/
- bl_mem_params->ep_info.args.arg1 =
- TRANSFER_LIST_SIGNATURE |
- REGISTER_CONVENTION_VERSION_MASK;
+#ifdef __aarch64__
+ if (GET_RW(bl_mem_params->ep_info.spsr) == MODE_RW_64) {
+ bl_mem_params->ep_info.args.arg1 =
+ TRANSFER_LIST_HANDOFF_X1_VALUE(REGISTER_CONVENTION_VERSION);
+ } else
+#endif
+ {
+ bl_mem_params->ep_info.args.arg1 =
+ TRANSFER_LIST_HANDOFF_R1_VALUE(REGISTER_CONVENTION_VERSION);
+ }
+
bl_mem_params->ep_info.args.arg3 = (uintptr_t)bl2_tl;
break;
#endif
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/qti/qtiseclib/src/qtiseclib_cb_interface.c b/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c
index c4cd259..804ad42 100644
--- a/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c
+++ b/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c
@@ -142,10 +142,10 @@
qti_ns_ctx->elr_el3 = read_ctx_reg(get_el3state_ctx(ctx), CTX_ELR_EL3);
qti_ns_ctx->spsr_el1 =
- read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SPSR_EL1);
+ read_el1_ctx_common(get_el1_sysregs_ctx(ctx), spsr_el1);
qti_ns_ctx->elr_el1 =
- read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_ELR_EL1);
- qti_ns_ctx->sp_el1 = read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SP_EL1);
+ read_el1_ctx_common(get_el1_sysregs_ctx(ctx), elr_el1);
+ qti_ns_ctx->sp_el1 = read_el1_ctx_common(get_el1_sysregs_ctx(ctx), sp_el1);
qti_ns_ctx->x0 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X0);
qti_ns_ctx->x1 = read_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X1);
diff --git a/plat/renesas/common/include/rcar_def.h b/plat/renesas/common/include/rcar_def.h
index f1c2553..8676444 100644
--- a/plat/renesas/common/include/rcar_def.h
+++ b/plat/renesas/common/include/rcar_def.h
@@ -310,4 +310,31 @@
#define LOSSY_FMT2 LOSSY_FMT_YUV422INTLV
#define LOSSY_ENA_DIS2 LOSSY_DISABLE
+#define RCAR_CC63_BASE 0xE6600000U
+#define CC63_TRNG_ISR_REG_ADDR 0x104U
+#define CC63_TRNG_ISR_REG_EHR_VALID BIT_32(0)
+#define CC63_TRNG_ISR_REG_AUTOCORR_ERR BIT_32(1)
+#define CC63_TRNG_ICR_REG_ADDR 0x108U
+#define CC63_TRNG_CONFIG_REG_ADDR 0x10CU
+#define CC63_TRNG_CONFIG_REG_ROSC_MAX_LENGTH 3
+#define CC63_TRNG_VALID_REG_ADDR 0x110U
+#define CC63_TRNG_VALID_REG_EHR_NOT_READY 0x0
+#define CC63_TRNG_EHR_DATA_ADDR_0_REG_ADDR 0x114U
+#define CC63_TRNG_SOURCE_ENABLE_REG_ADDR 0x12CU
+#define CC63_TRNG_SOURCE_ENABLE_REG_SET 0x1
+#define CC63_TRNG_SOURCE_ENABLE_REG_CLR 0x0
+#define CC63_TRNG_SAMPLE_CNT1_REG_ADDR 0x130U
+#define CC63_TRNG_SAMPLE_CNT1_REG_SAMPLE_COUNT 100
+#define CC63_TRNG_DEBUG_CONTROL_REG_ADDR 0x138U
+#define CC63_TRNG_DEBUG_CONTROL_REG_VNC_BYPASS BIT_32(1)
+#define CC63_TRNG_DEBUG_CONTROL_REG_AUTOCORR_BYPASS BIT_32(3)
+#define CC63_TRNG_DEBUG_CONTROL_REG_80090B \
+ (CC63_TRNG_DEBUG_CONTROL_REG_VNC_BYPASS | \
+ CC63_TRNG_DEBUG_CONTROL_REG_AUTOCORR_BYPASS)
+#define CC63_TRNG_SW_RESET_REG_ADDR 0x140U
+#define CC63_TRNG_SW_RESET_REG_SET 0x1
+#define CC63_TRNG_VERSION_REG_ADDR 0x1C0U
+#define CC63_TRNG_CLK_ENABLE_REG_ADDR 0x1C4U
+#define CC63_TRNG_CLK_ENABLE_REG_SET 0x1
+
#endif /* RCAR_DEF_H */
diff --git a/plat/renesas/rcar/bl2_plat_setup.c b/plat/renesas/rcar/bl2_plat_setup.c
index 41031d6..c548240 100644
--- a/plat/renesas/rcar/bl2_plat_setup.c
+++ b/plat/renesas/rcar/bl2_plat_setup.c
@@ -756,6 +756,69 @@
#endif
}
+static void bl2_add_kaslr_seed(void)
+{
+ uint32_t cnt, isr, prr;
+ uint64_t seed;
+ int ret, node;
+
+ /* SCEG is only available on H3/M3-W/M3-N */
+ prr = mmio_read_32(RCAR_PRR);
+ switch (prr & PRR_PRODUCT_MASK) {
+ case PRR_PRODUCT_H3:
+ case PRR_PRODUCT_M3:
+ case PRR_PRODUCT_M3N:
+ break;
+ default:
+ return;
+ }
+
+ mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_SW_RESET_REG_ADDR,
+ CC63_TRNG_SW_RESET_REG_SET);
+
+ do {
+ mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_CLK_ENABLE_REG_ADDR,
+ CC63_TRNG_CLK_ENABLE_REG_SET);
+ mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_SAMPLE_CNT1_REG_ADDR,
+ CC63_TRNG_SAMPLE_CNT1_REG_SAMPLE_COUNT);
+ cnt = mmio_read_32(RCAR_CC63_BASE + CC63_TRNG_SAMPLE_CNT1_REG_ADDR);
+ } while (cnt != CC63_TRNG_SAMPLE_CNT1_REG_SAMPLE_COUNT);
+
+ mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_CONFIG_REG_ADDR,
+ CC63_TRNG_CONFIG_REG_ROSC_MAX_LENGTH);
+ mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_DEBUG_CONTROL_REG_ADDR,
+ CC63_TRNG_DEBUG_CONTROL_REG_80090B);
+ mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_SOURCE_ENABLE_REG_ADDR,
+ CC63_TRNG_SOURCE_ENABLE_REG_SET);
+
+ do {
+ isr = mmio_read_32(RCAR_CC63_BASE + CC63_TRNG_ISR_REG_ADDR);
+ if ((isr & CC63_TRNG_ISR_REG_AUTOCORR_ERR) != 0U) {
+ panic();
+ }
+ } while ((isr & CC63_TRNG_ISR_REG_EHR_VALID) == 0U);
+
+ mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_ICR_REG_ADDR, UINT32_MAX);
+ seed = mmio_read_64(RCAR_CC63_BASE + CC63_TRNG_EHR_DATA_ADDR_0_REG_ADDR);
+ mmio_write_32(RCAR_CC63_BASE + CC63_TRNG_SOURCE_ENABLE_REG_ADDR,
+ CC63_TRNG_SOURCE_ENABLE_REG_CLR);
+
+ node = ret = fdt_add_subnode(fdt, 0, "chosen");
+ if (ret < 0) {
+ goto err;
+ }
+
+ ret = fdt_setprop_u64(fdt, node, "kaslr-seed", seed);
+ if (ret < 0) {
+ goto err;
+ }
+
+ return;
+err:
+ NOTICE("BL2: Cannot add KASLR seed to FDT (ret=%i)\n", ret);
+ panic();
+}
+
static void bl2_add_dram_entry(uint64_t start, uint64_t size)
{
char nodename[32] = { 0 };
@@ -1215,6 +1278,9 @@
/* Print DRAM layout */
bl2_advertise_dram_size(product);
+ /* Add KASLR seed */
+ bl2_add_kaslr_seed();
+
if (boot_dev == MODEMR_BOOT_DEV_EMMC_25X1 ||
boot_dev == MODEMR_BOOT_DEV_EMMC_50X8) {
if (rcar_emmc_init() != EMMC_SUCCESS) {
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/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk
index 2394dce..9d0e215 100644
--- a/plat/rockchip/rk3399/platform.mk
+++ b/plat/rockchip/rk3399/platform.mk
@@ -104,9 +104,8 @@
${BUILD_PLAT}/bl31/pmu_fw.o: CCACHE_EXTRAFILES=$(RK3399M0FW):$(RK3399M0PMUFW)
${RK_PLAT_SOC}/drivers/pmu/pmu_fw.S: $(RK3399M0FW)
-$(eval $(call MAKE_PREREQ_DIR,${BUILD_M0},${BUILD_PLAT}))
.PHONY: $(RK3399M0FW)
-$(RK3399M0FW): | ${BUILD_M0}
+$(RK3399M0FW): | $$(@D)/
$(MAKE) -C ${RK_PLAT_SOC}/drivers/m0 BUILD=$(abspath ${BUILD_PLAT}/m0)
# Do not enable SVE
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/st/common/common_rules.mk b/plat/st/common/common_rules.mk
index 8b81c7f..fba7783 100644
--- a/plat/st/common/common_rules.mk
+++ b/plat/st/common/common_rules.mk
@@ -41,7 +41,7 @@
fi
# Create DTB file for BL2
-${BUILD_PLAT}/fdts/%-bl2.dts: fdts/%.dts fdts/${BL2_DTSI} | ${BUILD_PLAT} fdt_dirs
+${BUILD_PLAT}/fdts/%-bl2.dts: fdts/%.dts fdts/${BL2_DTSI} | $$(@D)/
$(q)echo '#include "$(patsubst fdts/%,%,$<)"' > $@
$(q)echo '#include "${BL2_DTSI}"' >> $@
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index 2ade242..9da311e 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -331,7 +331,7 @@
print_pmic_info_and_debug();
}
- stm32mp1_syscfg_init();
+ stm32mp_syscfg_init();
if (stm32_iwdg_init() < 0) {
panic();
@@ -365,7 +365,7 @@
}
#endif
- stm32mp1_syscfg_enable_io_compensation_finish();
+ stm32mp_syscfg_enable_io_compensation_finish();
fconf_populate("TB_FW", STM32MP_DTB_BASE);
@@ -461,7 +461,8 @@
break;
case BL32_IMAGE_ID:
- if (optee_header_is_valid(bl_mem_params->image_info.image_base)) {
+ if ((bl_mem_params->image_info.image_base != 0UL) &&
+ (optee_header_is_valid(bl_mem_params->image_info.image_base))) {
image_info_t *paged_image_info = NULL;
/* BL32 is OP-TEE header */
diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h
index f6e5a8f..55227fb 100644
--- a/plat/st/stm32mp1/include/stm32mp1_private.h
+++ b/plat/st/stm32mp1/include/stm32mp1_private.h
@@ -14,19 +14,19 @@
void stm32mp1_arch_security_setup(void);
void stm32mp1_security_setup(void);
-void stm32mp1_syscfg_init(void);
-void stm32mp1_syscfg_enable_io_compensation_start(void);
-void stm32mp1_syscfg_enable_io_compensation_finish(void);
-void stm32mp1_syscfg_disable_io_compensation(void);
-uint32_t stm32mp1_syscfg_get_chip_version(void);
-uint32_t stm32mp1_syscfg_get_chip_dev_id(void);
+void stm32mp_syscfg_init(void);
+void stm32mp_syscfg_enable_io_compensation_start(void);
+void stm32mp_syscfg_enable_io_compensation_finish(void);
+void stm32mp_syscfg_disable_io_compensation(void);
+uint32_t stm32mp_syscfg_get_chip_version(void);
+uint32_t stm32mp_syscfg_get_chip_dev_id(void);
#if STM32MP13
-void stm32mp1_syscfg_boot_mode_enable(void);
-void stm32mp1_syscfg_boot_mode_disable(void);
+void stm32mp_syscfg_boot_mode_enable(void);
+void stm32mp_syscfg_boot_mode_disable(void);
#endif
#if STM32MP15
-static inline void stm32mp1_syscfg_boot_mode_enable(void){}
-static inline void stm32mp1_syscfg_boot_mode_disable(void){}
+static inline void stm32mp_syscfg_boot_mode_enable(void){}
+static inline void stm32mp_syscfg_boot_mode_disable(void){}
#endif
void stm32mp1_deconfigure_uart_pins(void);
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index a1f44e8..138f16c 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -255,11 +255,11 @@
ifeq ($(AARCH32_SP),sp_min)
# Create DTB file for BL32
-${BUILD_PLAT}/fdts/%-bl32.dts: fdts/%.dts fdts/${BL32_DTSI} | ${BUILD_PLAT} fdt_dirs
+${BUILD_PLAT}/fdts/%-bl32.dts: fdts/%.dts fdts/${BL32_DTSI} | $$(@D)/
$(q)echo '#include "$(patsubst fdts/%,%,$<)"' > $@
$(q)echo '#include "${BL32_DTSI}"' >> $@
-${BUILD_PLAT}/fdts/%-bl32.dtb: ${BUILD_PLAT}/fdts/%-bl32.dts
+${BUILD_PLAT}/fdts/%-bl32.dtb: ${BUILD_PLAT}/fdts/%-bl32.dts | $$(@D)/
endif
include plat/st/common/common_rules.mk
diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c
index ff2218f..97e1ac6 100644
--- a/plat/st/stm32mp1/stm32mp1_pm.c
+++ b/plat/st/stm32mp1/stm32mp1_pm.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
*/
@@ -13,6 +13,7 @@
#include <drivers/arm/gic_common.h>
#include <drivers/arm/gicv2.h>
#include <drivers/clk.h>
+#include <drivers/st/stm32mp_reset.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
#include <lib/mmio.h>
#include <lib/psci/psci.h>
@@ -149,13 +150,7 @@
static void __dead2 stm32_system_reset(void)
{
- mmio_setbits_32(stm32mp_rcc_base() + RCC_MP_GRSTCSETR,
- RCC_MP_GRSTCSETR_MPSYSRST);
-
- /* Loop in case system reset is not immediately caught */
- for ( ; ; ) {
- ;
- }
+ stm32mp_system_reset();
}
static int stm32_validate_power_state(unsigned int power_state,
diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c
index 189f83d..32de391 100644
--- a/plat/st/stm32mp1/stm32mp1_private.c
+++ b/plat/st/stm32mp1/stm32mp1_private.c
@@ -280,7 +280,7 @@
uint32_t stm32mp_get_chip_version(void)
{
#if STM32MP13
- return stm32mp1_syscfg_get_chip_version();
+ return stm32mp_syscfg_get_chip_version();
#endif
#if STM32MP15
uint32_t version = 0U;
@@ -297,7 +297,7 @@
uint32_t stm32mp_get_chip_dev_id(void)
{
#if STM32MP13
- return stm32mp1_syscfg_get_chip_dev_id();
+ return stm32mp_syscfg_get_chip_dev_id();
#endif
#if STM32MP15
uint32_t dev_id;
diff --git a/plat/st/stm32mp1/stm32mp1_syscfg.c b/plat/st/stm32mp1/stm32mp1_syscfg.c
index 75dd709..199bdc9 100644
--- a/plat/st/stm32mp1/stm32mp1_syscfg.c
+++ b/plat/st/stm32mp1/stm32mp1_syscfg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2019-2024, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -261,7 +261,7 @@
#endif
}
-static void stm32mp1_syscfg_set_hslv(void)
+static void stm32mp_syscfg_set_hslv(void)
{
uint32_t otp_value;
uint32_t vdd_voltage;
@@ -310,7 +310,7 @@
}
}
-void stm32mp1_syscfg_init(void)
+void stm32mp_syscfg_init(void)
{
#if STM32MP15
uint32_t bootr;
@@ -328,12 +328,12 @@
bootr << SYSCFG_BOOTR_BOOTPD_SHIFT);
#endif
- stm32mp1_syscfg_set_hslv();
+ stm32mp_syscfg_set_hslv();
- stm32mp1_syscfg_enable_io_compensation_start();
+ stm32mp_syscfg_enable_io_compensation_start();
}
-void stm32mp1_syscfg_enable_io_compensation_start(void)
+void stm32mp_syscfg_enable_io_compensation_start(void)
{
/*
* Activate automatic I/O compensation.
@@ -353,7 +353,7 @@
#endif
}
-void stm32mp1_syscfg_enable_io_compensation_finish(void)
+void stm32mp_syscfg_enable_io_compensation_finish(void)
{
enable_io_comp_cell_finish(SYSCFG_CMPCR);
#if STM32MP13
@@ -362,7 +362,7 @@
#endif
}
-void stm32mp1_syscfg_disable_io_compensation(void)
+void stm32mp_syscfg_disable_io_compensation(void)
{
clk_enable(SYSCFG);
@@ -385,7 +385,7 @@
* @brief Get silicon revision from SYSCFG registers.
* @retval chip version (REV_ID).
*/
-uint32_t stm32mp1_syscfg_get_chip_version(void)
+uint32_t stm32mp_syscfg_get_chip_version(void)
{
return (mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) &
SYSCFG_IDC_REV_ID_MASK) >> SYSCFG_IDC_REV_ID_SHIFT;
@@ -395,18 +395,18 @@
* @brief Get device ID from SYSCFG registers.
* @retval device ID (DEV_ID).
*/
-uint32_t stm32mp1_syscfg_get_chip_dev_id(void)
+uint32_t stm32mp_syscfg_get_chip_dev_id(void)
{
return mmio_read_32(SYSCFG_BASE + SYSCFG_IDC) & SYSCFG_IDC_DEV_ID_MASK;
}
#if STM32MP13
-void stm32mp1_syscfg_boot_mode_enable(void)
+void stm32mp_syscfg_boot_mode_enable(void)
{
mmio_setbits_32(SYSCFG_BASE + SYSCFG_BOOTCR, SYSCFG_BOOTCR_BMEN);
}
-void stm32mp1_syscfg_boot_mode_disable(void)
+void stm32mp_syscfg_boot_mode_disable(void)
{
mmio_clrbits_32(SYSCFG_BASE + SYSCFG_BOOTCR, SYSCFG_BOOTCR_BMEN);
}
diff --git a/plat/st/stm32mp2/bl2_plat_setup.c b/plat/st/stm32mp2/bl2_plat_setup.c
index 724209a..96ac68b 100644
--- a/plat/st/stm32mp2/bl2_plat_setup.c
+++ b/plat/st/stm32mp2/bl2_plat_setup.c
@@ -4,30 +4,268 @@
* 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();
+
+ /* Prevent corruption of preloaded Device Tree */
+ mmap_add_dynamic_region(DTB_BASE, DTB_BASE,
+ DTB_LIMIT - DTB_BASE,
+ MT_RO_DATA | MT_SECURE);
+
+ 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);
+
+ mmap_remove_dynamic_region(DTB_BASE, DTB_LIMIT - DTB_BASE);
+
+ 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..2f7570d 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,12 +61,33 @@
#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.
******************************************************************************/
#define BL33_BASE STM32MP_BL33_BASE
/*******************************************************************************
+ * DTB specific defines.
+ ******************************************************************************/
+#define DTB_BASE STM32MP_DTB_BASE
+#define DTB_LIMIT (STM32MP_DTB_BASE + \
+ STM32MP_DTB_SIZE)
+
+/*******************************************************************************
* Platform specific page table and MMU setup constants
******************************************************************************/
#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 33)
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 11b1138..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,13 +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 += drivers/st/bsec/bsec3.c
+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 \
+ 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 e3662ad..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,15 +129,32 @@
#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
******************************************************************************/
#define RCC_BASE U(0x44200000)
@@ -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"
@@ -293,6 +359,11 @@
#define SYSCFG_BASE U(0x44230000)
/*******************************************************************************
+ * STM32MP CA35SSC
+ ******************************************************************************/
+#define A35SSC_BASE U(0x48800000)
+
+/*******************************************************************************
* REGULATORS
******************************************************************************/
/* 3 PWR + 1 VREFBUF + 14 PMIC regulators + 1 FIXED */
@@ -309,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..205877c 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
*/
@@ -164,15 +164,10 @@
*
*/
static enum pm_ret_status pm_ipi_buff_read(const struct pm_proc *proc,
- uint32_t *value, size_t count)
+ uint32_t value[PAYLOAD_ARG_CNT])
{
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];
-#endif
uintptr_t buffer_base = proc->ipi->buffer_base +
IPI_BUFFER_TARGET_REMOTE_OFFSET +
IPI_BUFFER_RESP_OFFSET;
@@ -184,27 +179,21 @@
* 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 = 0; i < PAYLOAD_ARG_CNT; i++) {
+ value[i] = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
}
- ret = mmio_read_32(buffer_base);
+ ret = value[0];
#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)) {
+ if (value[PAYLOAD_CRC_POS] !=
+ calculate_crc(value, IPI_W0_TO_W6_SIZE)) {
NOTICE("ERROR in CRC response payload value:0x%x\n",
- response_payload[PAYLOAD_CRC_POS]);
+ value[PAYLOAD_CRC_POS]);
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, PAYLOAD_ARG_CNT);
}
#endif
@@ -240,7 +229,7 @@
count = IPI_BUFFER_MAX_WORDS;
}
- for (i = 0; i <= count; i++) {
+ for (i = 0; i < count; i++) {
*value = mmio_read_32(buffer_base + (i * PAYLOAD_ARG_SIZE));
value++;
}
@@ -282,6 +271,7 @@
uint32_t *value, size_t count)
{
enum pm_ret_status ret;
+ uint32_t i, ret_payload[PAYLOAD_ARG_CNT] = {0U};
pm_ipi_lock_get();
@@ -290,7 +280,12 @@
goto unlock;
}
+ ret = ERROR_CODE_MASK & (pm_ipi_buff_read(proc, ret_payload));
+
- ret = ERROR_CODE_MASK & (pm_ipi_buff_read(proc, value, count));
+ for (i = 1U; i <= count; i++) {
+ *value = ret_payload[i];
+ value++;
+ }
unlock:
pm_ipi_lock_release();
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/aarch64/zynqmp_common.c b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
index dba1734..b0bd8a1 100644
--- a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
+++ b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2013-2022, 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
*/
@@ -12,7 +12,7 @@
#include <drivers/generic_delay_timer.h>
#include <lib/mmio.h>
#include <lib/smccc.h>
-#include <lib/xlat_tables/xlat_tables.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
#include <services/arm_arch_svc.h>
@@ -28,9 +28,9 @@
* configure_mmu_elx() will give the available subset of that,
*/
const mmap_region_t plat_zynqmp_mmap[] = {
- { DEVICE0_BASE, DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
- { DEVICE1_BASE, DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
- { CRF_APB_BASE, CRF_APB_BASE, CRF_APB_SIZE, MT_DEVICE | MT_RW | MT_SECURE },
+ MAP_REGION_FLAT(DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
+ MAP_REGION_FLAT(CRF_APB_BASE, CRF_APB_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
{0}
};
diff --git a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
index 0a34f72..50d4240 100644
--- a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
+++ b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
- * Copyright (c) 2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2023-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -14,6 +14,7 @@
#include <common/fdt_fixup.h>
#include <common/fdt_wrappers.h>
#include <lib/mmio.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
#include <libfdt.h>
#include <plat/arm/common/plat_arm.h>
#include <plat/common/platform.h>
@@ -220,5 +221,5 @@
custom_mmap_add();
setup_page_tables(bl_regions, plat_get_mmap());
- enable_mmu_el3(0);
+ enable_mmu(0);
}
diff --git a/plat/xilinx/zynqmp/include/plat_private.h b/plat/xilinx/zynqmp/include/plat_private.h
index afa102d..1b41b7c 100644
--- a/plat/xilinx/zynqmp/include/plat_private.h
+++ b/plat/xilinx/zynqmp/include/plat_private.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2014-2020, Arm Limited and Contributors. All rights reserved.
- * Copyright (c) 2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2023-2024, Advanced Micro Devices, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,7 +13,7 @@
#include <bl31/interrupt_mgmt.h>
#include <common/bl_common.h>
#include <drivers/cadence/cdns_uart.h>
-#include <lib/xlat_tables/xlat_tables.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
void zynqmp_config_setup(void);
diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk
index 3a752b2..c340009 100644
--- a/plat/xilinx/zynqmp/platform.mk
+++ b/plat/xilinx/zynqmp/platform.mk
@@ -35,10 +35,6 @@
WORKAROUND_CVE_2017_5715 := 0
-ARM_XLAT_TABLES_LIB_V1 := 1
-$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1))
-$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1))
-
ifdef ZYNQMP_ATF_MEM_BASE
$(eval $(call add_define,ZYNQMP_ATF_MEM_BASE))
@@ -96,10 +92,9 @@
include lib/libfdt/libfdt.mk
# Include GICv2 driver files
include drivers/arm/gic/v2/gicv2.mk
+include lib/xlat_tables_v2/xlat_tables.mk
-PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \
- lib/xlat_tables/aarch64/xlat_tables.c \
- drivers/arm/dcc/dcc_console.c \
+PLAT_BL_COMMON_SOURCES := drivers/arm/dcc/dcc_console.c \
drivers/delay_timer/delay_timer.c \
drivers/delay_timer/generic_delay_timer.c \
${GICV2_SOURCES} \
@@ -112,7 +107,8 @@
plat/xilinx/zynqmp/zynqmp_ipi.c \
plat/common/aarch64/crash_console_helpers.S \
plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S \
- plat/xilinx/zynqmp/aarch64/zynqmp_common.c
+ plat/xilinx/zynqmp/aarch64/zynqmp_common.c \
+ ${XLAT_TABLES_LIB_SRCS}
ZYNQMP_CONSOLE ?= cadence
ifeq (${ZYNQMP_CONSOLE}, $(filter ${ZYNQMP_CONSOLE},cadence cadence0 cadence1 dcc))
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 08b2b37..b465f48 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
[[package]]
name = "alabaster"
@@ -13,163 +13,179 @@
[[package]]
name = "anytree"
-version = "2.8.0"
-description = "Powerful and Lightweight Python Tree Data Structure.."
+version = "2.12.1"
+description = "Powerful and Lightweight Python Tree Data Structure with various plugins"
optional = false
-python-versions = "*"
+python-versions = ">=3.7.2,<4"
files = [
- {file = "anytree-2.8.0-py2.py3-none-any.whl", hash = "sha256:14c55ac77492b11532395049a03b773d14c7e30b22aa012e337b1e983de31521"},
- {file = "anytree-2.8.0.tar.gz", hash = "sha256:3f0f93f355a91bc3e6245319bf4c1d50e3416cc7a35cc1133c1ff38306bbccab"},
+ {file = "anytree-2.12.1-py3-none-any.whl", hash = "sha256:5ea9e61caf96db1e5b3d0a914378d2cd83c269dfce1fb8242ce96589fa3382f0"},
+ {file = "anytree-2.12.1.tar.gz", hash = "sha256:244def434ccf31b668ed282954e5d315b4e066c4940b94aff4a7962d85947830"},
]
[package.dependencies]
-six = ">=1.9.0"
-
-[package.extras]
-dev = ["check-manifest"]
-test = ["coverage"]
+six = "*"
[[package]]
name = "babel"
-version = "2.12.1"
+version = "2.15.0"
description = "Internationalization utilities"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "Babel-2.12.1-py3-none-any.whl", hash = "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610"},
- {file = "Babel-2.12.1.tar.gz", hash = "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"},
+ {file = "Babel-2.15.0-py3-none-any.whl", hash = "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb"},
+ {file = "babel-2.15.0.tar.gz", hash = "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413"},
]
[package.dependencies]
pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""}
+[package.extras]
+dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"]
+
[[package]]
name = "build"
-version = "0.10.0"
+version = "1.2.1"
description = "A simple, correct Python build frontend"
optional = false
-python-versions = ">= 3.7"
+python-versions = ">=3.8"
files = [
- {file = "build-0.10.0-py3-none-any.whl", hash = "sha256:af266720050a66c893a6096a2f410989eeac74ff9a68ba194b3f6473e8e26171"},
- {file = "build-0.10.0.tar.gz", hash = "sha256:d5b71264afdb5951d6704482aac78de887c80691c52b88a9ad195983ca2c9269"},
+ {file = "build-1.2.1-py3-none-any.whl", hash = "sha256:75e10f767a433d9a86e50d83f418e83efc18ede923ee5ff7df93b6cb0306c5d4"},
+ {file = "build-1.2.1.tar.gz", hash = "sha256:526263f4870c26f26c433545579475377b2b7588b6f1eac76a001e873ae3e19d"},
]
[package.dependencies]
colorama = {version = "*", markers = "os_name == \"nt\""}
-packaging = ">=19.0"
+importlib-metadata = {version = ">=4.6", markers = "python_full_version < \"3.10.2\""}
+packaging = ">=19.1"
pyproject_hooks = "*"
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
[package.extras]
-docs = ["furo (>=2021.08.31)", "sphinx (>=4.0,<5.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)"]
-test = ["filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "toml (>=0.10.0)", "wheel (>=0.36.0)"]
-typing = ["importlib-metadata (>=5.1)", "mypy (==0.991)", "tomli", "typing-extensions (>=3.7.4.3)"]
+docs = ["furo (>=2023.08.17)", "sphinx (>=7.0,<8.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)", "sphinx-issues (>=3.0.0)"]
+test = ["build[uv,virtualenv]", "filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "setuptools (>=56.0.0)", "setuptools (>=67.8.0)", "wheel (>=0.36.0)"]
+typing = ["build[uv]", "importlib-metadata (>=5.1)", "mypy (>=1.9.0,<1.10.0)", "tomli", "typing-extensions (>=3.7.4.3)"]
+uv = ["uv (>=0.1.18)"]
virtualenv = ["virtualenv (>=20.0.35)"]
[[package]]
name = "certifi"
-version = "2023.7.22"
+version = "2024.7.4"
description = "Python package for providing Mozilla's CA Bundle."
optional = false
python-versions = ">=3.6"
files = [
- {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"},
- {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"},
+ {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"},
+ {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"},
]
[[package]]
name = "charset-normalizer"
-version = "3.1.0"
+version = "3.3.2"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
optional = false
python-versions = ">=3.7.0"
files = [
- {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"},
- {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"},
+ {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"},
+ {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
]
[[package]]
name = "click"
-version = "8.1.3"
+version = "8.1.7"
description = "Composable command line interface toolkit"
optional = false
python-versions = ">=3.7"
files = [
- {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
- {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
+ {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
+ {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
]
[package.dependencies]
@@ -187,6 +203,20 @@
]
[[package]]
+name = "commonmark"
+version = "0.9.1"
+description = "Python parser for the CommonMark Markdown spec"
+optional = false
+python-versions = "*"
+files = [
+ {file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"},
+ {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"},
+]
+
+[package.extras]
+test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"]
+
+[[package]]
name = "docutils"
version = "0.18.1"
description = "Docutils -- Python Documentation Utilities"
@@ -199,13 +229,13 @@
[[package]]
name = "idna"
-version = "3.4"
+version = "3.7"
description = "Internationalized Domain Names in Applications (IDNA)"
optional = false
python-versions = ">=3.5"
files = [
- {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
- {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
+ {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"},
+ {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"},
]
[[package]]
@@ -221,32 +251,32 @@
[[package]]
name = "importlib-metadata"
-version = "6.6.0"
+version = "8.2.0"
description = "Read metadata from Python packages"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = "sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"},
- {file = "importlib_metadata-6.6.0.tar.gz", hash = "sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"},
+ {file = "importlib_metadata-8.2.0-py3-none-any.whl", hash = "sha256:11901fa0c2f97919b288679932bb64febaeacf289d18ac84dd68cb2e74213369"},
+ {file = "importlib_metadata-8.2.0.tar.gz", hash = "sha256:72e8d4399996132204f9a16dcc751af254a48f8d1b20b9ff0f98d4a8f901e73d"},
]
[package.dependencies]
zipp = ">=0.5"
[package.extras]
-docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
+doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
perf = ["ipython"]
-testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"]
+test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"]
[[package]]
name = "jinja2"
-version = "3.1.2"
+version = "3.1.4"
description = "A very fast and expressive template engine."
optional = false
python-versions = ">=3.7"
files = [
- {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
- {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
+ {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"},
+ {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"},
]
[package.dependencies]
@@ -281,61 +311,71 @@
[[package]]
name = "markupsafe"
-version = "2.1.2"
+version = "2.1.5"
description = "Safely add untrusted strings to HTML/XML markup."
optional = false
python-versions = ">=3.7"
files = [
- {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-win32.whl", hash = "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-win32.whl", hash = "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-win32.whl", hash = "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-win32.whl", hash = "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-win32.whl", hash = "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed"},
- {file = "MarkupSafe-2.1.2.tar.gz", hash = "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"},
+ {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"},
]
[[package]]
@@ -396,35 +436,35 @@
[[package]]
name = "packaging"
-version = "23.1"
+version = "24.1"
description = "Core utilities for Python packages"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"},
- {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
+ {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"},
+ {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"},
]
[[package]]
name = "pip"
-version = "23.1.2"
+version = "24.2"
description = "The PyPA recommended tool for installing Python packages."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "pip-23.1.2-py3-none-any.whl", hash = "sha256:3ef6ac33239e4027d9a5598a381b9d30880a1477e50039db2eac6e8a8f6d1b18"},
- {file = "pip-23.1.2.tar.gz", hash = "sha256:0e7c86f486935893c708287b30bd050a36ac827ec7fe5e43fe7cb198dd835fba"},
+ {file = "pip-24.2-py3-none-any.whl", hash = "sha256:2cd581cf58ab7fcfca4ce8efa6dcacd0de5bf8d0a3eb9ec927e07405f4d9e2a2"},
+ {file = "pip-24.2.tar.gz", hash = "sha256:5b5e490b5e9cb275c879595064adce9ebd31b854e3e803740b72f9ccf34a45b8"},
]
[[package]]
name = "pip-tools"
-version = "6.13.0"
+version = "6.14.0"
description = "pip-tools keeps your pinned dependencies fresh."
optional = false
python-versions = ">=3.7"
files = [
- {file = "pip-tools-6.13.0.tar.gz", hash = "sha256:61d46bd2eb8016ed4a924e196e6e5b0a268cd3babd79e593048720db23522bb1"},
- {file = "pip_tools-6.13.0-py3-none-any.whl", hash = "sha256:50943f151d87e752abddec8158622c34ad7f292e193836e90e30d87da60b19d9"},
+ {file = "pip-tools-6.14.0.tar.gz", hash = "sha256:06366be0e08d86b416407333e998b4d305d5bd925151b08942ed149380ba3e47"},
+ {file = "pip_tools-6.14.0-py3-none-any.whl", hash = "sha256:c5ad042cd27c0b343b10db1db7f77a7d087beafbec59ae6df1bba4d3368dfe8c"},
]
[package.dependencies]
@@ -432,28 +472,29 @@
click = ">=8"
pip = ">=22.2"
setuptools = "*"
+tomli = {version = "*", markers = "python_version < \"3.11\""}
wheel = "*"
[package.extras]
-coverage = ["pytest-cov"]
-testing = ["flit-core (>=2,<4)", "poetry-core (>=1.0.0)", "pytest (>=7.2.0)", "pytest-rerunfailures", "pytest-xdist"]
+coverage = ["covdefaults", "pytest-cov"]
+testing = ["flit-core (>=2,<4)", "poetry-core (>=1.0.0)", "pytest (>=7.2.0)", "pytest-rerunfailures", "pytest-xdist", "tomli-w"]
[[package]]
name = "prettytable"
-version = "3.7.0"
+version = "3.10.2"
description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "prettytable-3.7.0-py3-none-any.whl", hash = "sha256:f4aaf2ed6e6062a82fd2e6e5289bbbe705ec2788fe401a3a1f62a1cea55526d2"},
- {file = "prettytable-3.7.0.tar.gz", hash = "sha256:ef8334ee40b7ec721651fc4d37ecc7bb2ef55fde5098d994438f0dfdaa385c0c"},
+ {file = "prettytable-3.10.2-py3-none-any.whl", hash = "sha256:1cbfdeb4bcc73976a778a0fb33cb6d752e75396f16574dcb3e2d6332fd93c76a"},
+ {file = "prettytable-3.10.2.tar.gz", hash = "sha256:29ec6c34260191d42cd4928c28d56adec360ac2b1208a26c7e4f14b90cc8bc84"},
]
[package.dependencies]
wcwidth = "*"
[package.extras]
-tests = ["pytest", "pytest-cov", "pytest-lazy-fixture"]
+tests = ["pytest", "pytest-cov", "pytest-lazy-fixtures"]
[[package]]
name = "pyelftools"
@@ -468,101 +509,109 @@
[[package]]
name = "pygments"
-version = "2.15.1"
+version = "2.18.0"
description = "Pygments is a syntax highlighting package written in Python."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"},
- {file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"},
+ {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"},
+ {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"},
]
[package.extras]
-plugins = ["importlib-metadata"]
+windows-terminal = ["colorama (>=0.4.6)"]
[[package]]
name = "pyproject-hooks"
-version = "1.0.0"
+version = "1.1.0"
description = "Wrappers to call pyproject.toml-based build backend hooks."
optional = false
python-versions = ">=3.7"
files = [
- {file = "pyproject_hooks-1.0.0-py3-none-any.whl", hash = "sha256:283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8"},
- {file = "pyproject_hooks-1.0.0.tar.gz", hash = "sha256:f271b298b97f5955d53fb12b72c1fb1948c22c1a6b70b315c54cedaca0264ef5"},
+ {file = "pyproject_hooks-1.1.0-py3-none-any.whl", hash = "sha256:7ceeefe9aec63a1064c18d939bdc3adf2d8aa1988a510afec15151578b232aa2"},
+ {file = "pyproject_hooks-1.1.0.tar.gz", hash = "sha256:4b37730834edbd6bd37f26ece6b44802fb1c1ee2ece0e54ddff8bfc06db86965"},
]
-[package.dependencies]
-tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
-
[[package]]
name = "pytz"
-version = "2023.3"
+version = "2024.1"
description = "World timezone definitions, modern and historical"
optional = false
python-versions = "*"
files = [
- {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"},
- {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"},
+ {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"},
+ {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"},
]
[[package]]
name = "pyyaml"
-version = "6.0"
+version = "6.0.1"
description = "YAML parser and emitter for Python"
optional = false
python-versions = ">=3.6"
files = [
- {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
- {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"},
- {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"},
- {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"},
- {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"},
- {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"},
- {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"},
- {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"},
- {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"},
- {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"},
- {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"},
- {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"},
- {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"},
- {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"},
- {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"},
- {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"},
- {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"},
- {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"},
- {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"},
- {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"},
- {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"},
- {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"},
- {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"},
- {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"},
- {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"},
- {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"},
- {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"},
- {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"},
- {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"},
- {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"},
- {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"},
- {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"},
- {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"},
- {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"},
- {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"},
- {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"},
- {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"},
- {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"},
- {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
- {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
+ {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
+ {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
+ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
+ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
+ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
+ {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
+ {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
+ {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
+ {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
+ {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
+ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
+ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
+ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
+ {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
+ {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
+ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
+ {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
+ {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
+ {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
+ {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
+ {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
+ {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
+ {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"},
+ {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"},
+ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
+ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
+ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
+ {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
+ {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
+ {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
+ {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
+ {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"},
+ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
+ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
+ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
+ {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
+ {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
+ {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
+ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
]
[[package]]
name = "requests"
-version = "2.31.0"
+version = "2.32.3"
description = "Python HTTP for Humans."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"},
- {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},
+ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
+ {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
]
[package.dependencies]
@@ -576,22 +625,52 @@
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
+name = "rich"
+version = "10.16.2"
+description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
+optional = false
+python-versions = ">=3.6.2,<4.0.0"
+files = [
+ {file = "rich-10.16.2-py3-none-any.whl", hash = "sha256:c59d73bd804c90f747c8d7b1d023b88f2a9ac2454224a4aeaf959b21eeb42d03"},
+ {file = "rich-10.16.2.tar.gz", hash = "sha256:720974689960e06c2efdb54327f8bf0cdbdf4eae4ad73b6c94213cad405c371b"},
+]
+
+[package.dependencies]
+colorama = ">=0.4.0,<0.5.0"
+commonmark = ">=0.9.0,<0.10.0"
+pygments = ">=2.6.0,<3.0.0"
+
+[package.extras]
+jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"]
+
+[[package]]
name = "setuptools"
-version = "67.7.2"
+version = "72.1.0"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "setuptools-67.7.2-py3-none-any.whl", hash = "sha256:23aaf86b85ca52ceb801d32703f12d77517b2556af839621c641fca11287952b"},
- {file = "setuptools-67.7.2.tar.gz", hash = "sha256:f104fa03692a2602fa0fec6c6a9e63b6c8a968de13e17c026957dd1f53d80990"},
+ {file = "setuptools-72.1.0-py3-none-any.whl", hash = "sha256:5a03e1860cf56bb6ef48ce186b0e557fdba433237481a9a625176c2831be15d1"},
+ {file = "setuptools-72.1.0.tar.gz", hash = "sha256:8d243eff56d095e5817f796ede6ae32941278f542e0f941867cc05ae52b162ec"},
]
[package.extras]
-docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
-testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
-testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
+core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "ordered-set (>=3.1.1)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
+doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
+test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.11.*)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
[[package]]
+name = "shellingham"
+version = "1.5.4"
+description = "Tool to Detect Surrounding Shell"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"},
+ {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"},
+]
+
+[[package]]
name = "six"
version = "1.16.0"
description = "Python 2 and 3 compatibility utilities"
@@ -650,19 +729,19 @@
[[package]]
name = "sphinx-rtd-theme"
-version = "1.2.0"
+version = "1.3.0"
description = "Read the Docs theme for Sphinx"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
files = [
- {file = "sphinx_rtd_theme-1.2.0-py2.py3-none-any.whl", hash = "sha256:f823f7e71890abe0ac6aaa6013361ea2696fc8d3e1fa798f463e82bdb77eeff2"},
- {file = "sphinx_rtd_theme-1.2.0.tar.gz", hash = "sha256:a0d8bd1a2ed52e0b338cbe19c4b2eef3c5e7a048769753dac6a9f059c7b641b8"},
+ {file = "sphinx_rtd_theme-1.3.0-py2.py3-none-any.whl", hash = "sha256:46ddef89cc2416a81ecfbeaceab1881948c014b1b6e4450b815311a89fb977b0"},
+ {file = "sphinx_rtd_theme-1.3.0.tar.gz", hash = "sha256:590b030c7abb9cf038ec053b95e5380b5c70d61591eb0b552063fbe7c41f0931"},
]
[package.dependencies]
docutils = "<0.19"
-sphinx = ">=1.6,<7"
-sphinxcontrib-jquery = {version = ">=2.0.0,<3.0.0 || >3.0.0", markers = "python_version > \"3\""}
+sphinx = ">=1.6,<8"
+sphinxcontrib-jquery = ">=4,<5"
[package.extras]
dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"]
@@ -804,6 +883,25 @@
cairosvg = ["cairosvg (>=1.0)"]
[[package]]
+name = "tlc"
+version = "0.9.0"
+description = "Transfer List Compiler (TLC) is a Python-based CLI for efficiently handling transfer lists."
+optional = false
+python-versions = "^3.8"
+files = []
+develop = false
+
+[package.dependencies]
+click = "^8.1.7"
+pyyaml = "^6.0.1"
+rich = "^10.14.0"
+typer = {version = "^0.4.0", extras = ["all"]}
+
+[package.source]
+type = "directory"
+url = "tools/tlc"
+
+[[package]]
name = "tomli"
version = "2.0.1"
description = "A lil' TOML parser"
@@ -815,74 +913,96 @@
]
[[package]]
+name = "typer"
+version = "0.4.2"
+description = "Typer, build great CLIs. Easy to code. Based on Python type hints."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "typer-0.4.2-py3-none-any.whl", hash = "sha256:023bae00d1baf358a6cc7cea45851639360bb716de687b42b0a4641cd99173f1"},
+ {file = "typer-0.4.2.tar.gz", hash = "sha256:b8261c6c0152dd73478b5ba96ba677e5d6948c715c310f7c91079f311f62ec03"},
+]
+
+[package.dependencies]
+click = ">=7.1.1,<9.0.0"
+colorama = {version = ">=0.4.3,<0.5.0", optional = true, markers = "extra == \"all\""}
+shellingham = {version = ">=1.3.0,<2.0.0", optional = true, markers = "extra == \"all\""}
+
+[package.extras]
+all = ["colorama (>=0.4.3,<0.5.0)", "shellingham (>=1.3.0,<2.0.0)"]
+dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"]
+doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)"]
+test = ["black (>=22.3.0,<23.0.0)", "coverage (>=5.2,<6.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<5.4.0)", "pytest-cov (>=2.10.0,<3.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<2.0.0)", "shellingham (>=1.3.0,<2.0.0)"]
+
+[[package]]
name = "typing-extensions"
-version = "4.5.0"
-description = "Backported and Experimental Type Hints for Python 3.7+"
+version = "4.12.2"
+description = "Backported and Experimental Type Hints for Python 3.8+"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"},
- {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"},
+ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
+ {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
]
[[package]]
name = "urllib3"
-version = "2.0.2"
+version = "2.2.2"
description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "urllib3-2.0.2-py3-none-any.whl", hash = "sha256:d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"},
- {file = "urllib3-2.0.2.tar.gz", hash = "sha256:61717a1095d7e155cdb737ac7bb2f4324a858a1e2e6466f6d03ff630ca68d3cc"},
+ {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"},
+ {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"},
]
[package.extras]
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
-secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"]
+h2 = ["h2 (>=4,<5)"]
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
zstd = ["zstandard (>=0.18.0)"]
[[package]]
name = "wcwidth"
-version = "0.2.6"
+version = "0.2.13"
description = "Measures the displayed width of unicode strings in a terminal"
optional = false
python-versions = "*"
files = [
- {file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"},
- {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"},
+ {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"},
+ {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"},
]
[[package]]
name = "wheel"
-version = "0.40.0"
+version = "0.43.0"
description = "A built-package format for Python"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "wheel-0.40.0-py3-none-any.whl", hash = "sha256:d236b20e7cb522daf2390fa84c55eea81c5c30190f90f29ae2ca1ad8355bf247"},
- {file = "wheel-0.40.0.tar.gz", hash = "sha256:cd1196f3faee2b31968d626e1731c94f99cbdb67cf5a46e4f5656cbee7738873"},
+ {file = "wheel-0.43.0-py3-none-any.whl", hash = "sha256:55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81"},
+ {file = "wheel-0.43.0.tar.gz", hash = "sha256:465ef92c69fa5c5da2d1cf8ac40559a8c940886afcef87dcf14b9470862f1d85"},
]
[package.extras]
-test = ["pytest (>=6.0.0)"]
+test = ["pytest (>=6.0.0)", "setuptools (>=65)"]
[[package]]
name = "zipp"
-version = "3.15.0"
+version = "3.19.2"
description = "Backport of pathlib-compatible object wrapper for zip files"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"},
- {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"},
+ {file = "zipp-3.19.2-py3-none-any.whl", hash = "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c"},
+ {file = "zipp-3.19.2.tar.gz", hash = "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19"},
]
[package.extras]
-docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
-testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
+doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
+test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"]
[metadata]
lock-version = "2.0"
python-versions = "^3.8"
-content-hash = "62d9ce9ca1c9f4669c7b40724acfc93968cde31c0460d1d7515d289739dc9464"
+content-hash = "8798a2d1efd456c3b68ae464a216f015afaa1bbb653a905148bef17ab8ce278e"
diff --git a/pyproject.toml b/pyproject.toml
index 7814497..03d898e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -14,8 +14,12 @@
[tool.poetry.dependencies]
python = "^3.8"
+tlc = {path = "tools/tlc"}
+
+[tool.poetry.group.docs]
+optional = true
-[tool.poetry.group.doc.dependencies]
+[tool.poetry.group.docs.dependencies]
sphinx = "^5.3.0"
myst-parser = "^0.18.1"
sphinxcontrib-plantuml = "^0.24.1"
diff --git a/services/spd/opteed/opteed_main.c b/services/spd/opteed/opteed_main.c
index d6c0040..9e83848 100644
--- a/services/spd/opteed/opteed_main.c
+++ b/services/spd/opteed/opteed_main.c
@@ -552,13 +552,14 @@
if (opteed_rw == OPTEE_AARCH64) {
arg0 = (uint64_t)dt;
+ arg1 = TRANSFER_LIST_HANDOFF_X1_VALUE(REGISTER_CONVENTION_VERSION);
arg2 = 0;
} else {
- arg2 = (uint64_t)dt;
arg0 = 0;
+ arg1 = TRANSFER_LIST_HANDOFF_R1_VALUE(REGISTER_CONVENTION_VERSION);
+ arg2 = (uint64_t)dt;
}
- arg1 = TRANSFER_LIST_SIGNATURE |
- REGISTER_CONVENTION_VERSION_MASK;
+
arg3 = (uint64_t)bl31_tl;
} else {
/* Default handoff arguments */
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 7daebcd..aae2d9a 100644
--- a/services/spd/trusty/trusty.c
+++ b/services/spd/trusty/trusty.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -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);
@@ -160,9 +163,9 @@
(void)memcpy(&ctx->fiq_gpregs, get_gpregs_ctx(handle), sizeof(ctx->fiq_gpregs));
ctx->fiq_pc = SMC_GET_EL3(handle, CTX_ELR_EL3);
ctx->fiq_cpsr = SMC_GET_EL3(handle, CTX_SPSR_EL3);
- ctx->fiq_sp_el1 = read_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1);
+ ctx->fiq_sp_el1 = read_el1_ctx_common(get_el1_sysregs_ctx(handle), sp_el1);
- write_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1, ctx->fiq_handler_sp);
+ write_el1_ctx_common(get_el1_sysregs_ctx(handle), sp_el1, ctx->fiq_handler_sp);
cm_set_elr_spsr_el3(NON_SECURE, ctx->fiq_handler_pc, (uint32_t)ctx->fiq_handler_cpsr);
SMC_RET0(handle);
@@ -221,7 +224,7 @@
*/
(void)memcpy(get_gpregs_ctx(handle), &ctx->fiq_gpregs, sizeof(ctx->fiq_gpregs));
ctx->fiq_handler_active = 0;
- write_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1, ctx->fiq_sp_el1);
+ write_el1_ctx_common(get_el1_sysregs_ctx(handle), sp_el1, ctx->fiq_sp_el1);
cm_set_elr_spsr_el3(NON_SECURE, ctx->fiq_pc, (uint32_t)ctx->fiq_cpsr);
SMC_RET0(handle);
@@ -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/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/rmmd/rmmd_main.c b/services/std_svc/rmmd/rmmd_main.c
index 6ccb003..15b3724 100644
--- a/services/std_svc/rmmd/rmmd_main.c
+++ b/services/std_svc/rmmd/rmmd_main.c
@@ -202,19 +202,23 @@
int rc;
/* Make sure RME is supported. */
- assert(is_feat_rme_present());
+ if (is_feat_rme_present() == 0U) {
+ /* Mark the RMM boot as failed for all the CPUs */
+ rmm_boot_failed = true;
+ return -ENOTSUP;
+ }
rmm_ep_info = bl31_plat_get_next_image_ep_info(REALM);
- if (rmm_ep_info == NULL) {
+ if ((rmm_ep_info == NULL) || (rmm_ep_info->pc == 0)) {
WARN("No RMM image provided by BL2 boot loader, Booting "
"device without RMM initialization. SMCs destined for "
"RMM will return SMC_UNK\n");
+
+ /* Mark the boot as failed for all the CPUs */
+ rmm_boot_failed = true;
return -ENOENT;
}
- /* Under no circumstances will this parameter be 0 */
- assert(rmm_ep_info->pc == RMM_BASE);
-
/* Initialise an entrypoint to set up the CPU context */
ep_attr = EP_REALM;
if ((read_sctlr_el3() & SCTLR_EE_BIT) != 0U) {
@@ -239,6 +243,8 @@
rc = plat_rmmd_load_manifest(manifest);
if (rc != 0) {
ERROR("Error loading RMM Boot Manifest (%i)\n", rc);
+ /* Mark the boot as failed for all the CPUs */
+ rmm_boot_failed = true;
return rc;
}
flush_dcache_range((uintptr_t)shared_buf_base, shared_buf_size);
diff --git a/services/std_svc/spm/el3_spmc/spmc_setup.c b/services/std_svc/spm/el3_spmc/spmc_setup.c
index 609d968..4360832 100644
--- a/services/std_svc/spm/el3_spmc/spmc_setup.c
+++ b/services/std_svc/spm/el3_spmc/spmc_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -319,24 +319,23 @@
xlat_ctx->pa_max_address, xlat_ctx->va_max_address,
EL1_EL0_REGIME);
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_MAIR_EL1,
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), mair_el1,
mmu_cfg_params[MMU_CFG_MAIR]);
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TCR_EL1,
- mmu_cfg_params[MMU_CFG_TCR]);
+ write_ctx_tcr_el1_reg_errata(ctx, mmu_cfg_params[MMU_CFG_TCR]);
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TTBR0_EL1,
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), ttbr0_el1,
mmu_cfg_params[MMU_CFG_TTBR0]);
}
static void spmc_el0_sp_setup_sctlr_el1(cpu_context_t *ctx)
{
- u_register_t sctlr_el1;
+ u_register_t sctlr_el1_val;
/* Setup SCTLR_EL1 */
- sctlr_el1 = read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1);
+ sctlr_el1_val = read_ctx_sctlr_el1_reg_errata(ctx);
- sctlr_el1 |=
+ sctlr_el1_val |=
/*SCTLR_EL1_RES1 |*/
/* Don't trap DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU */
SCTLR_UCI_BIT |
@@ -357,7 +356,7 @@
/* Enable MMU. */
SCTLR_M_BIT;
- sctlr_el1 &= ~(
+ sctlr_el1_val &= ~(
/* Explicit data accesses at EL0 are little-endian. */
SCTLR_E0E_BIT |
/*
@@ -369,7 +368,8 @@
SCTLR_UMA_BIT
);
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1);
+ /* Store the initialised SCTLR_EL1 value in the cpu_context */
+ write_ctx_sctlr_el1_reg_errata(ctx, sctlr_el1_val);
}
static void spmc_el0_sp_setup_system_registers(struct secure_partition_desc *sp,
@@ -383,10 +383,10 @@
/* Setup other system registers. */
/* Shim Exception Vector Base Address */
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_VBAR_EL1,
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), vbar_el1,
SPM_SHIM_EXCEPTIONS_PTR);
#if NS_TIMER_SWITCH
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CNTKCTL_EL1,
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), cntkctl_el1,
EL0PTEN_BIT | EL0VTEN_BIT | EL0PCTEN_BIT | EL0VCTEN_BIT);
#endif
@@ -397,7 +397,7 @@
* TTA: Enable access to trace registers.
* ZEN (v8.2): Trap SVE instructions and access to SVE registers.
*/
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CPACR_EL1,
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), cpacr_el1,
CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE));
}
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 4e65c9c..de05459 100644
--- a/services/std_svc/spm/spm_mm/spm_mm_setup.c
+++ b/services/std_svc/spm/spm_mm/spm_mm_setup.c
@@ -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.
* Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -27,7 +27,7 @@
void spm_sp_setup(sp_context_t *sp_ctx)
{
cpu_context_t *ctx = &(sp_ctx->cpu_ctx);
-
+ u_register_t sctlr_el1_val;
/* Pointer to the MP information from the platform port. */
const spm_mm_boot_info_t *sp_boot_info =
plat_get_secure_partition_boot_info(NULL);
@@ -122,19 +122,17 @@
xlat_ctx->pa_max_address, xlat_ctx->va_max_address,
EL1_EL0_REGIME);
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_MAIR_EL1,
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), mair_el1,
mmu_cfg_params[MMU_CFG_MAIR]);
+ write_ctx_tcr_el1_reg_errata(ctx, mmu_cfg_params[MMU_CFG_TCR]);
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TCR_EL1,
- mmu_cfg_params[MMU_CFG_TCR]);
-
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TTBR0_EL1,
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), ttbr0_el1,
mmu_cfg_params[MMU_CFG_TTBR0]);
/* Setup SCTLR_EL1 */
- u_register_t sctlr_el1 = read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1);
+ sctlr_el1_val = read_ctx_sctlr_el1_reg_errata(ctx);
- sctlr_el1 |=
+ sctlr_el1_val |=
/*SCTLR_EL1_RES1 |*/
/* Don't trap DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU */
SCTLR_UCI_BIT |
@@ -156,7 +154,7 @@
SCTLR_M_BIT
;
- sctlr_el1 &= ~(
+ sctlr_el1_val &= ~(
/* Explicit data accesses at EL0 are little-endian. */
SCTLR_E0E_BIT |
/*
@@ -168,7 +166,8 @@
SCTLR_UMA_BIT
);
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1);
+ /* Store the initialised SCTLR_EL1 value in the cpu_context */
+ write_ctx_sctlr_el1_reg_errata(ctx, sctlr_el1_val);
/*
* Setup other system registers
@@ -176,10 +175,10 @@
*/
/* Shim Exception Vector Base Address */
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_VBAR_EL1,
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), vbar_el1,
SPM_SHIM_EXCEPTIONS_PTR);
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CNTKCTL_EL1,
+ write_el1_ctx_arch_timer(get_el1_sysregs_ctx(ctx), cntkctl_el1,
EL0PTEN_BIT | EL0VTEN_BIT | EL0PCTEN_BIT | EL0VCTEN_BIT);
/*
@@ -189,7 +188,7 @@
* TTA: Enable access to trace registers.
* ZEN (v8.2): Trap SVE instructions and access to SVE registers.
*/
- write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CPACR_EL1,
+ write_el1_ctx_common(get_el1_sysregs_ctx(ctx), cpacr_el1,
CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE));
/*
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
index 0715b13..0a246f3 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -52,26 +52,11 @@
static entry_point_info_t *spmc_ep_info;
/*******************************************************************************
- * SPM Core context on CPU based on mpidr.
- ******************************************************************************/
-spmd_spm_core_context_t *spmd_get_context_by_mpidr(uint64_t mpidr)
-{
- int core_idx = plat_core_pos_by_mpidr(mpidr);
-
- if (core_idx < 0) {
- ERROR("Invalid mpidr: %" PRIx64 ", returned ID: %d\n", mpidr, core_idx);
- panic();
- }
-
- return &spm_core_context[core_idx];
-}
-
-/*******************************************************************************
* SPM Core context on current CPU get helper.
******************************************************************************/
spmd_spm_core_context_t *spmd_get_context(void)
{
- return spmd_get_context_by_mpidr(read_mpidr());
+ return &spm_core_context[plat_my_core_pos()];
}
/*******************************************************************************
@@ -217,7 +202,6 @@
{
spmd_spm_core_context_t *ctx = spmd_get_context();
gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx);
- unsigned int linear_id = plat_my_core_pos();
int64_t rc;
/* Sanity check the security state when the exception was generated */
@@ -231,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. */
@@ -246,9 +238,16 @@
/* 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, linear_id);
+ ERROR("%s failed (%" PRId64 ") on CPU%u\n", __func__, rc, plat_my_core_pos());
}
ctx->secure_interrupt_ongoing = false;
@@ -257,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);
@@ -677,6 +680,7 @@
{
unsigned int secure_state_in = (secure_origin) ? SECURE : NON_SECURE;
unsigned int secure_state_out = (!secure_origin) ? SECURE : NON_SECURE;
+ void *ctx_out;
#if SPMD_SPM_AT_SEL2
if ((secure_state_out == SECURE) && (is_sve_hint_set(flags) == true)) {
@@ -693,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 */
@@ -700,9 +708,13 @@
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);
+ ctx_out = cm_get_context(secure_state_out);
#if SPMD_SPM_AT_SEL2
/*
* If SPMC is at SEL2, save additional registers x8-x17, which may
@@ -715,7 +727,7 @@
* preserved, so the SPMD passes through these registers and expects the
* SPMC to save and restore (potentially also modify) them.
*/
- SMC_RET18(cm_get_context(secure_state_out), smc_fid, x1, x2, x3, x4,
+ SMC_RET18(ctx_out, smc_fid, x1, x2, x3, x4,
SMC_GET_GP(handle, CTX_GPREG_X5),
SMC_GET_GP(handle, CTX_GPREG_X6),
SMC_GET_GP(handle, CTX_GPREG_X7),
@@ -732,7 +744,7 @@
);
#else
- SMC_RET8(cm_get_context(secure_state_out), smc_fid, x1, x2, x3, x4,
+ SMC_RET8(ctx_out, smc_fid, x1, x2, x3, x4,
SMC_GET_GP(handle, CTX_GPREG_X5),
SMC_GET_GP(handle, CTX_GPREG_X6),
SMC_GET_GP(handle, CTX_GPREG_X7));
@@ -852,7 +864,6 @@
void *handle,
uint64_t flags)
{
- unsigned int linear_id = plat_my_core_pos();
spmd_spm_core_context_t *ctx = spmd_get_context();
bool secure_origin;
int ret;
@@ -863,7 +874,7 @@
VERBOSE("SPM(%u): 0x%x 0x%" PRIx64 " 0x%" PRIx64 " 0x%" PRIx64 " 0x%" PRIx64
" 0x%" PRIx64 " 0x%" PRIx64 " 0x%" PRIx64 "\n",
- linear_id, smc_fid, x1, x2, x3, x4,
+ plat_my_core_pos(), smc_fid, x1, x2, x3, x4,
SMC_GET_GP(handle, CTX_GPREG_X5),
SMC_GET_GP(handle, CTX_GPREG_X6),
SMC_GET_GP(handle, CTX_GPREG_X7));
diff --git a/services/std_svc/std_svc_setup.c b/services/std_svc/std_svc_setup.c
index e782d09..5cfe5f9 100644
--- a/services/std_svc/std_svc_setup.c
+++ b/services/std_svc/std_svc_setup.c
@@ -66,7 +66,7 @@
#if ENABLE_RME
if (rmmd_setup() != 0) {
- ret = 1;
+ WARN("RMMD setup failed. Continuing boot.\n");
}
#endif
diff --git a/tools/cot_dt2c/Makefile b/tools/cot_dt2c/Makefile
new file mode 100644
index 0000000..ad8d9f5
--- /dev/null
+++ b/tools/cot_dt2c/Makefile
@@ -0,0 +1,68 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+##* Variables
+SHELL := /usr/bin/env bash
+PYTHON := python
+PYTHONPATH := `pwd`
+
+.PHONY: dist
+dist: clean
+ poetry build
+
+#* Installation
+.PHONY: dev-install
+dev-install:
+ pip3 install mypy
+ pip3 install pytest
+ pip install -r requirements.txt
+ poetry lock -n && poetry export --without-hashes > requirements.txt
+ poetry install -n
+ -poetry run mypy --install-types --non-interactive ./
+
+.PHONY: install
+install: dist
+ pip install mypy
+ pip install pytest
+ pip install -r requirements.txt
+ pip install dist/*.whl
+
+clean-test: ## remove test and coverage artifacts
+ rm -fr .tox/
+ rm -f .coverage
+ rm -fr htmlcov/
+
+clean-pyc: ## remove Python file artifacts
+ find . -name '*.pyc' -exec rm -f {} +
+ find . -name '*.pyo' -exec rm -f {} +
+ find . -name '*~' -exec rm -f {} +
+ find . -name '__pycache__' -exec rm -fr {} +
+ find . | grep -E ".pytest_cache" | xargs rm -rf
+ find . | grep -E ".mypy_cache" | xargs rm -rf
+
+
+clean-build: ## remove build artifacts
+ rm -fr build/
+ rm -fr dist/
+ rm -fr .eggs/
+ find . -name '*.egg-info' -exec rm -fr {} +
+ find . -name '*.egg' -exec rm -f {} +
+
+clean-tmp:
+ rm -rf ./tmp
+
+#* Cleaning
+.PHONY: clean clean-build clean-pyc clean-test
+clean: uninstall clean-build clean-pyc clean-test clean-tmp ## remove all build, test, coverage and Python artifacts
+
+uninstall:
+ pip uninstall -y cot-dt2c
+
+.PHONY: reinstall
+reinstall: clean install
+
+.PHONY: test
+test:
+ PYTHONPATH=$(PYTHONPATH) poetry run pytest -c pyproject.toml tests/
diff --git a/tools/cot_dt2c/cot_dt2c/LICENSE b/tools/cot_dt2c/cot_dt2c/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
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..c1d53e2
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/cot_parser.py
@@ -0,0 +1,804 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+import sys
+import re
+from cot_dt2c.pydevicetree.source.parser import ifdef_stack
+from cot_dt2c.pydevicetree.ast import CellArray, LabelReference
+from cot_dt2c.pydevicetree import *
+from pathlib import Path
+
+def extractNumber(s):
+ for i in s:
+ if i.isdigit():
+ return (int)(i)
+
+ return -1
+
+def removeNumber(s):
+ result = ''.join([i for i in s if not i.isdigit()])
+ return result
+
+class COT:
+ def __init__(self, inputfile: str, outputfile=None):
+ with open(inputfile, 'r') as f:
+ contents = f.read()
+ pos = contents.find("cot")
+ if pos == -1:
+ print("not a valid CoT DT file")
+ exit(1)
+
+ contents = contents[pos:]
+
+ try:
+ self.tree = Devicetree.parseStr(contents)
+ 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
+ if "sp_pkg" in type_desc:
+ ptr = removeNumber(type_desc) + "_buf"
+ else:
+ ptr = type_desc + "_buf"
+ len = "(unsigned int)HASH_DER_LEN"
+ if "pk" in type_desc:
+ len = "(unsigned int)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
+
+ if ifdef_stack:
+ print("invalid ifdef macro")
+ valid = False
+
+ 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 extract_licence(self, f):
+ licence = []
+
+ licencereg = re.compile(r'/\*')
+ licenceendReg = re.compile(r'\*/')
+
+ licencePre = False
+
+ for line in f:
+ match = licencereg.search(line)
+ if match != None:
+ licence.append(line)
+ licencePre = True
+ continue
+
+ match = licenceendReg.search(line)
+ if match != None:
+ licence.append(line)
+ licencePre = False
+ return licence
+
+ if licencePre:
+ licence.append(line)
+ else:
+ return licence
+
+ return licence
+
+ def licence_to_c(self, licence, f):
+ if len(licence) != 0:
+ for i in licence:
+ f.write(i)
+
+ f.write("\n")
+ return
+
+ def extract_include(self, f):
+ include = []
+
+ for line in f:
+ if "cot" in line:
+ return include
+
+ if line != "" and "common" not in line and line != "\n":
+ include.append(line)
+
+ return include
+
+ def include_to_c(self, include, 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("\n")
+ for i in include:
+ f.write(i)
+ f.write("\n")
+ f.write("#include <platform_def.h>\n\n")
+ return
+
+ def generate_header(self, input, output):
+ licence = self.extract_licence(input)
+ include = self.extract_include(input)
+ self.licence_to_c(licence, output)
+ self.include_to_c(include, 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):
+ ifdef = node.get_fields("ifdef")
+ if ifdef:
+ for i in ifdef:
+ f.write("{}\n".format(i))
+
+ f.write("static const auth_img_desc_t {} = {{\n".format(node.name))
+ f.write("\t.img_id = {},\n".format(node.get_field("image-id").values[0].replace('"', "")))
+ f.write("\t.img_type = IMG_CERT,\n")
+
+ if not self.if_root(node):
+ f.write("\t.parent = &{},\n".format(node.get_field("parent").label.name))
+ 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")
+
+ n = extractNumber(type_desc)
+ if "pkg" not in type_desc or n == -1:
+ f.write("\t\t\t\t.ptr = (void *){},\n".format(ptr))
+ else:
+ f.write("\t\t\t\t.ptr = (void *){}[{}],\n".format(ptr, n-1))
+
+ f.write("\t\t\t\t.len = {}\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")
+
+ if ifdef:
+ for i in ifdef:
+ f.write("#endif\n")
+ f.write("\n")
+
+ return
+
+
+ def img_to_c(self, node:Node, f):
+ ifdef = node.get_fields("ifdef")
+ if ifdef:
+ for i in ifdef:
+ f.write("{}\n".format(i))
+
+ f.write("static const auth_img_desc_t {} = {{\n".format(node.name))
+ f.write("\t.img_id = {},\n".format(node.get_field("image-id").values[0].replace('"', "")))
+ f.write("\t.img_type = IMG_RAW,\n")
+ f.write("\t.parent = &{},\n".format(node.get_field("parent").label.name))
+ 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("\t\t\t\t.hash = &{}\n".format(node.get_field("hash").label.name))
+ f.write("\t\t\t}\n")
+
+ f.write("\t\t}\n")
+ f.write("\t}\n")
+ f.write("};\n\n")
+
+ if ifdef:
+ for i in ifdef:
+ f.write("#endif\n")
+ f.write("\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:
+ f.write("static auth_param_type_desc_t {} = AUTH_PARAM_TYPE_DESC(AUTH_PARAM_NV_CTR, {});\n".format(nv.name, nv.get_field("oid")))
+
+ f.write("\n")
+
+ return
+
+ def pk_to_c(self, f):
+ pks = self.get_all_pks()
+
+ for p in pks:
+ f.write("static auth_param_type_desc_t {} = AUTH_PARAM_TYPE_DESC(AUTH_PARAM_PUB_KEY, {});\n".format(p.name, p.get_field("oid")))
+
+ f.write("\n")
+ return
+
+ def buf_to_c(self, f):
+ certs = self.get_all_certificates()
+
+ buffers = {}
+
+ 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 ptr not in buffers:
+ buffers[ptr] = c.get_fields("ifdef")
+
+ for key, values in buffers.items():
+ if values:
+ for i in values:
+ f.write("{}\n".format(i))
+
+ if "sp_pkg_hash_buf" in key:
+ f.write("static unsigned char {}[MAX_SP_IDS][HASH_DER_LEN];\n".format(key))
+ elif "pk" in key:
+ f.write("static unsigned char {}[PK_DER_LEN];\n".format(key))
+ else:
+ f.write("static unsigned char {}[HASH_DER_LEN];\n".format(key))
+
+ if values:
+ for i in values:
+ f.write("#endif\n")
+
+ 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:
+ ifdef = c.get_fields("ifdef")
+ if ifdef:
+ for i in ifdef:
+ f.write("{}\n".format(i))
+
+ hash = c.children
+ for h in hash:
+ name = h.name
+ oid = h.get_field("oid")
+
+ if "pk" in name and "pkg" not in name:
+ f.write("static auth_param_type_desc_t {} = "\
+ "AUTH_PARAM_TYPE_DESC(AUTH_PARAM_PUB_KEY, {});\n".format(name, oid))
+ elif "hash" in name:
+ f.write("static auth_param_type_desc_t {} = "\
+ "AUTH_PARAM_TYPE_DESC(AUTH_PARAM_HASH, {});\n".format(name, oid))
+ elif "ctr" in name:
+ f.write("static auth_param_type_desc_t {} = "\
+ "AUTH_PARAM_TYPE_DESC(AUTH_PARAM_NV_CTR, {});\n".format(name, oid))
+
+ if ifdef:
+ for i in ifdef:
+ f.write("#endif\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):
+ ifdef = c.get_fields("ifdef")
+ if ifdef:
+ for i in ifdef:
+ f.write("{}\n".format(i))
+
+ f.write("\t[{}] = &{}{}\n".format(c.get_field("image-id").values[0], c.name, ","))
+
+ if ifdef:
+ for i in ifdef:
+ f.write("#endif\n")
+
+ for i, c in enumerate(images):
+ ifdef = c.get_fields("ifdef")
+ if ifdef:
+ for i in ifdef:
+ f.write("{}\n".format(i))
+
+ f.write("\t[{}] = &{}{}\n".format(c.get_field("image-id").values[0], c.name, "," if i != len(images) - 1 else ""))
+
+ if ifdef:
+ for i in ifdef:
+ f.write("#endif\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)
+ output = open(self.output, 'w+')
+ input = open(self.input, "r")
+
+ self.generate_header(input, 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..65e8ca2
--- /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 cot_dt2c.pydevicetree import *
+
+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/cot_dt2c/pydevicetree/__init__.py b/tools/cot_dt2c/cot_dt2c/pydevicetree/__init__.py
new file mode 100644
index 0000000..49595a7
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/pydevicetree/__init__.py
@@ -0,0 +1,5 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 SiFive Inc.
+# SPDX-License-Identifier: Apache-2.0
+
+from cot_dt2c.pydevicetree.ast import Devicetree, Node, Property, Directive, CellArray, LabelReference
diff --git a/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/__init__.py b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/__init__.py
new file mode 100644
index 0000000..f30d897
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/__init__.py
@@ -0,0 +1,9 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 SiFive Inc.
+# SPDX-License-Identifier: Apache-2.0
+
+from cot_dt2c.pydevicetree.ast.directive import Directive
+from cot_dt2c.pydevicetree.ast.node import Node, NodeReference, Devicetree
+from cot_dt2c.pydevicetree.ast.property import PropertyValues, Bytestring, CellArray, StringList, Property, \
+ RegArray, OneString
+from cot_dt2c.pydevicetree.ast.reference import Label, Path, Reference, LabelReference, PathReference
diff --git a/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/directive.py b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/directive.py
new file mode 100644
index 0000000..fdd6f0e
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/directive.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 SiFive Inc.
+# SPDX-License-Identifier: Apache-2.0
+
+from typing import Any
+
+from cot_dt2c.pydevicetree.ast.helpers import formatLevel, wrapStrings
+
+class Directive:
+ """Represents a Devicetree directive
+
+ Directives in Devicetree source are statements of the form
+
+ /directive-name/ [option1 [option2 [...]]];
+
+ Common directive examples include:
+
+ /dts-v1/;
+ /include/ "overlay.dtsi";
+ /delete-node/ &uart0;
+ /delete-property/ status;
+
+ Their semantic meaning depends on the directive name, their location in the Devicetree,
+ and their options.
+ """
+ def __init__(self, directive: str, option: Any = None):
+ """Create a directive object"""
+ self.directive = directive
+ self.option = option
+
+ def __repr__(self) -> str:
+ return "<Directive %s>" % self.directive
+
+ def __str__(self) -> str:
+ return self.to_dts()
+
+ def to_dts(self, level: int = 0) -> str:
+ """Format the Directive in Devicetree Source format"""
+ if isinstance(self.option, list):
+ return formatLevel(level, "%s %s;\n" % (self.directive,
+ wrapStrings(self.option)))
+ if isinstance(self.option, str):
+ if self.directive == "/include/":
+ return formatLevel(level, "%s \"%s\"\n" % (self.directive, self.option))
+ return formatLevel(level, "%s \"%s\";\n" % (self.directive, self.option))
+ return formatLevel(level, "%s;\n" % self.directive)
diff --git a/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/helpers.py b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/helpers.py
new file mode 100644
index 0000000..30c54dc
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/helpers.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 SiFive Inc.
+# SPDX-License-Identifier: Apache-2.0
+
+from typing import List, Any
+
+from cot_dt2c.pydevicetree.ast.reference import Reference
+
+def formatLevel(level: int, s: str) -> str:
+ """Helper to indent a string with a number of tabs"""
+ return "\t" * level + s
+
+def wrapStrings(values: List[Any], formatHex: bool = False) -> List[Any]:
+ """Helper to wrap strings in quotes where appropriate"""
+ wrapped = []
+ for v in values:
+ if isinstance(v, Reference):
+ wrapped.append(v.to_dts())
+ elif isinstance(v, str):
+ wrapped.append("\"%s\"" % v)
+ elif isinstance(v, int):
+ if formatHex:
+ wrapped.append("0x%x" % v)
+ else:
+ wrapped.append(str(v))
+ else:
+ wrapped.append(str(v))
+ return wrapped
diff --git a/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/node.py b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/node.py
new file mode 100644
index 0000000..d203af8
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/node.py
@@ -0,0 +1,514 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 SiFive Inc.
+# SPDX-License-Identifier: Apache-2.0
+
+import re
+import os
+from typing import List, Union, Optional, Iterable, Callable, Any, cast, Pattern
+
+from cot_dt2c.pydevicetree.ast.helpers import formatLevel
+from cot_dt2c.pydevicetree.ast.property import Property, PropertyValues, RegArray, RangeArray
+from cot_dt2c.pydevicetree.ast.directive import Directive
+from cot_dt2c.pydevicetree.ast.reference import Label, Path, Reference, LabelReference, PathReference
+
+# Type signature for elements passed to Devicetree constructor
+ElementList = Iterable[Union['Node', Property, Directive]]
+
+# Callback type signatures for Devicetree.match() and Devicetree.chosen()
+MatchFunc = Callable[['Node'], bool]
+MatchCallback = Optional[Callable[['Node'], None]]
+ChosenCallback = Optional[Callable[[PropertyValues], None]]
+
+class Node:
+ """Represents a Devicetree Node
+
+ A Devicetree Node generally takes the form
+
+ [label:] node-name@unit-address {
+ [directives]
+ [properties]
+ [child nodes]
+ };
+
+ The structure formed by creating trees of Nodes is the bulk of any Devicetree. As the naming
+ system implies, then, each node roughly corresponds to some conceptual device, subsystem of
+ devices, bus, etc.
+
+ Devices can be referenced by label or by path, and are generally uniquely identified by a
+ collection of string identifiers assigned to the "compatible" property.
+
+ For instance, a UART device might look like
+
+ uart0: uart@10013000 {
+ compatible = "sifive,uart0";
+ reg = <0x10013000 0x1000>;
+ reg-names = "control";
+ interrupt-parent = <&plic>;
+ interrupts = <3>;
+ clocks = <&busclk>;
+ status = "okay";
+ };
+
+ This node can be identified in the following ways:
+
+ - By label: uart0
+ - By path: /path/to/uart@10013000
+ - By name: uart@10013000 (for example when referenced in a /delete-node/ directive)
+ """
+ # pylint: disable=too-many-arguments
+ def __init__(self, name: str, label: Optional[str], address: Optional[int],
+ properties: List[Property], directives: List[Directive],
+ children: List['Node']):
+ """Initializes a Devicetree Node
+
+ Also evaluates the /delete-node/ and /delete-property/ directives found in the node
+ and deletes the respective nodes and properties.
+ """
+ self.name = name
+ self.parent = None # type: Optional['Node']
+
+ self.label = label
+ self.address = address
+ self.properties = properties
+ self.directives = directives
+ self.children = children
+ self.ifdef = []
+
+ for d in self.directives:
+ if d.directive == "/delete-node/":
+ if isinstance(d.option, LabelReference):
+ node = self.get_by_reference(d.option)
+ elif isinstance(d.option, str):
+ node = self.__get_child_by_handle(d.option)
+ if node:
+ self.remove_child(node)
+ elif d.directive == "/delete-property/":
+ # pylint: disable=cell-var-from-loop
+ properties = list(filter(lambda p: p.name == d.option, self.properties))
+ if properties:
+ del self.properties[self.properties.index(properties[0])]
+
+ def __repr__(self) -> str:
+ if self.address:
+ return "<Node %s@%x>" % (self.name, self.address)
+ return "<Node %s>" % self.name
+
+ def __str__(self) -> str:
+ return self.to_dts()
+
+ def __eq__(self, other) -> bool:
+ return self.name == other.name and self.address == other.address
+
+ def __hash__(self):
+ return hash((self.name, self.address))
+
+ @staticmethod
+ def from_dts(source: str) -> 'Node':
+ """Create a node from Devicetree Source"""
+ # pylint: disable=import-outside-toplevel,cyclic-import
+ from pydevicetree.source import parseNode
+ return parseNode(source)
+
+ def add_child(self, node: 'Node', merge: bool = True):
+ """Add a child node and merge it into the tree"""
+ node.parent = self
+ self.children.append(node)
+ if merge:
+ self.merge_tree()
+
+ def to_dts(self, level: int = 0) -> str:
+ """Format the subtree starting at the node as Devicetree Source"""
+ out = ""
+ if isinstance(self.address, int) and self.label:
+ out += formatLevel(level,
+ "%s: %s@%x {\n" % (self.label, self.name, self.address))
+ elif isinstance(self.address, int):
+ out += formatLevel(level, "%s@%x {\n" % (self.name, self.address))
+ elif self.label:
+ out += formatLevel(level, "%s: %s {\n" % (self.label, self.name))
+ elif self.name != "":
+ out += formatLevel(level, "%s {\n" % self.name)
+
+ for d in self.directives:
+ out += d.to_dts(level + 1)
+ for p in self.properties:
+ out += p.to_dts(level + 1)
+ for c in self.children:
+ out += c.to_dts(level + 1)
+
+ if self.name != "":
+ out += formatLevel(level, "};\n")
+
+ return out
+
+ def merge_tree(self):
+ """Recursively merge child nodes into a single tree
+
+ Parsed Devicetrees can describe the same tree multiple times, adding nodes and properties
+ each time. After parsing, this method is called to recursively merge the tree.
+ """
+ partitioned_children = []
+ for n in self.children:
+ partitioned_children.append([e for e in self.children if e == n])
+
+ new_children = []
+ for part in partitioned_children:
+ first = part[0]
+ rest = part[1:]
+ if first not in new_children:
+ for n in rest:
+ first.merge(n)
+ new_children.append(first)
+
+ self.children = new_children
+
+ for n in self.children:
+ n.parent = self
+ n.merge_tree()
+
+ def merge(self, other: 'Node'):
+ """Merge the contents of a node into this node.
+
+ Used by Node.merge_trees()
+ """
+ if not self.label and other.label:
+ self.label = other.label
+ self.properties += other.properties
+ self.directives += other.directives
+ self.children += other.children
+ self.ifdef += other.ifdef
+
+ def get_path(self, includeAddress: bool = True) -> str:
+ """Get the path of a node (ex. /cpus/cpu@0)"""
+ if self.name == "/":
+ return ""
+ if self.parent is None:
+ return "/" + self.name
+ if isinstance(self.address, int) and includeAddress:
+ return self.parent.get_path() + "/" + self.name + "@" + ("%x" % self.address)
+ return self.parent.get_path() + "/" + self.name
+
+ def get_by_reference(self, reference: Reference) -> Optional['Node']:
+ """Get a node from the subtree by reference (ex. &label, &{/path/to/node})"""
+ if isinstance(reference, LabelReference):
+ return self.get_by_label(reference.label)
+ if isinstance(reference, PathReference):
+ return self.get_by_path(reference.path)
+
+ return None
+
+ def get_by_label(self, label: Union[Label, str]) -> Optional['Node']:
+ """Get a node from the subtree by label"""
+ matching_nodes = list(filter(lambda n: n.label == label, self.child_nodes()))
+ if len(matching_nodes) != 0:
+ return matching_nodes[0]
+ return None
+
+ def __get_child_by_handle(self, handle: str) -> Optional['Node']:
+ """Get a child node by name or name and unit address"""
+ if '@' in handle:
+ name, addr_s = handle.split('@')
+ address = int(addr_s, base=16)
+ nodes = list(filter(lambda n: n.name == name and n.address == address, self.children))
+ else:
+ name = handle
+ nodes = list(filter(lambda n: n.name == name, self.children))
+
+ if not nodes:
+ return None
+ if len(nodes) > 1:
+ raise Exception("Handle %s is ambiguous!" % handle)
+ return nodes[0]
+
+ def get_by_path(self, path: Union[Path, str]) -> Optional['Node']:
+ """Get a node in the subtree by path"""
+ matching_nodes = list(filter(lambda n: path == n.get_path(includeAddress=True), \
+ self.child_nodes()))
+ if len(matching_nodes) != 0:
+ return matching_nodes[0]
+
+ matching_nodes = list(filter(lambda n: path == n.get_path(includeAddress=False), \
+ self.child_nodes()))
+ if len(matching_nodes) != 0:
+ return matching_nodes[0]
+ return None
+
+ def filter(self, matchFunc: MatchFunc, cbFunc: MatchCallback = None) -> List['Node']:
+ """Filter all child nodes by matchFunc
+
+ If cbFunc is provided, this method will iterate over the Nodes selected by matchFunc
+ and call cbFunc on each Node
+
+ Returns a list of all matching Nodes
+ """
+ nodes = list(filter(matchFunc, self.child_nodes()))
+
+ if cbFunc is not None:
+ for n in nodes:
+ cbFunc(n)
+
+ return nodes
+
+ def match(self, compatible: Pattern, func: MatchCallback = None) -> List['Node']:
+ """Get a node from the subtree by compatible string
+
+ Accepts a regular expression to match one of the strings in the compatible property.
+ """
+ regex = re.compile(compatible)
+
+ def match_compat(node: Node) -> bool:
+ compatibles = node.get_fields("compatible")
+ if compatibles is not None:
+ return any(regex.match(c) for c in compatibles)
+ return False
+
+ return self.filter(match_compat, func)
+
+ def child_nodes(self) -> Iterable['Node']:
+ """Get an iterable over all the nodes in the subtree"""
+ for n in self.children:
+ yield n
+ for m in n.child_nodes():
+ yield m
+
+ def remove_child(self, node):
+ """Remove a child node"""
+ del self.children[self.children.index(node)]
+
+ def get_fields(self, field_name: str) -> Optional[PropertyValues]:
+ """Get all the values of a property"""
+ for p in self.properties:
+ if p.name == field_name:
+ return p.values
+ return None
+
+ def has_field(self, field_name: str) -> bool:
+ for p in self.properties:
+ if p.name == field_name:
+ return True
+ return False
+
+ def get_field(self, field_name: str) -> Any:
+ """Get the first value of a property"""
+ fields = self.get_fields(field_name)
+ if fields is not None:
+ if len(cast(PropertyValues, fields)) != 0:
+ return fields[0]
+ return None
+
+ def get_reg(self) -> Optional[RegArray]:
+ """If the node defines a `reg` property, return a RegArray for easier querying"""
+ reg = self.get_fields("reg")
+ reg_names = self.get_fields("reg-names")
+ if reg is not None:
+ if reg_names is not None:
+ return RegArray(reg.values, self.address_cells(), self.size_cells(),
+ reg_names.values)
+ return RegArray(reg.values, self.address_cells(), self.size_cells())
+ return None
+
+ def get_ranges(self) -> Optional[RangeArray]:
+ """If the node defines a `ranges` property, return a RangeArray for easier querying"""
+ ranges = self.get_fields("ranges")
+ child_address_cells = self.get_field("#address-cells")
+ parent_address_cells = self.address_cells()
+ size_cells = self.get_field("#size-cells")
+ if ranges is not None:
+ return RangeArray(ranges.values, child_address_cells, parent_address_cells, size_cells)
+ return None
+
+ def address_cells(self):
+ """Get the number of address cells
+
+ The #address-cells property is defined by the parent of a node and describes how addresses
+ are encoded in cell arrays. If no property is defined, the default value is 2.
+ """
+ if self.parent is not None:
+ cells = self.parent.get_field("#address-cells")
+ if cells is not None:
+ return cells
+ return 2
+ return 2
+
+ def size_cells(self):
+ """Get the number of size cells
+
+ The #size-cells property is defined by the parent of a node and describes how addresses
+ are encoded in cell arrays. If no property is defined, the default value is 1.
+ """
+ if self.parent is not None:
+ cells = self.parent.get_field("#size-cells")
+ if cells is not None:
+ return cells
+ return 1
+ return 1
+
+class NodeReference(Node):
+ """A NodeReference is used to extend the definition of a previously-defined Node
+
+ NodeReferences are commonly used by Devicetree "overlays" to extend the properties of a node
+ or add child devices, such as to a bus like I2C.
+ """
+ def __init__(self, reference: Reference, properties: List[Property],
+ directives: List[Directive], children: List[Node]):
+ """Instantiate a Node identified by reference to another node"""
+ self.reference = reference
+ Node.__init__(self, label=None, name="", address=None, properties=properties,
+ directives=directives, children=children)
+
+ def __repr__(self) -> str:
+ return "<NodeReference %s>" % self.reference.to_dts()
+
+ def resolve_reference(self, tree: 'Devicetree') -> Node:
+ """Given the full tree, get the node being referenced"""
+ node = tree.get_by_reference(self.reference)
+ if node is None:
+ raise Exception("Node reference %s cannot be resolved" % self.reference.to_dts())
+ return cast(Node, node)
+
+ def to_dts(self, level: int = 0) -> str:
+ out = formatLevel(level, self.reference.to_dts() + " {\n")
+
+ for d in self.directives:
+ out += d.to_dts(level + 1)
+ for p in self.properties:
+ out += p.to_dts(level + 1)
+ for c in self.children:
+ out += c.to_dts(level + 1)
+
+ out += formatLevel(level, "};\n")
+
+ return out
+
+
+class Devicetree(Node):
+ """A Devicetree object describes the full Devicetree tree
+
+ This class encapsulates both the tree itself (starting at the root node /) and any Directives
+ or nodes which exist at the top level of the Devicetree Source files.
+
+ Devicetree Source files can be parsed by calling Devicetree.parseFile().
+ """
+ def __init__(self, elements: ElementList):
+ """Instantiate a Devicetree with the list of parsed elements
+
+ Resolves all reference nodes and merges the tree to combine all identical nodes.
+ """
+ properties = [] # type: List[Property]
+ directives = [] # type: List[Directive]
+ children = [] # type: List[Node]
+
+ for e in elements:
+ if isinstance(e, Node):
+ children.append(cast(Node, e))
+ elif isinstance(e, Property):
+ properties.append(cast(Property, e))
+ elif isinstance(e, Directive):
+ directives.append(cast(Directive, e))
+
+ Node.__init__(self, label=None, name="", address=None,
+ properties=properties, directives=directives, children=children)
+
+ for node in self.children:
+ node.parent = self
+
+ reference_nodes = self.filter(lambda n: isinstance(n, NodeReference))
+ for refnode in reference_nodes:
+ refnode = cast(NodeReference, refnode)
+
+ node = refnode.resolve_reference(self)
+
+ if refnode.parent:
+ cast(Node, refnode.parent).remove_child(refnode)
+
+ node.properties += refnode.properties
+ node.directives += refnode.directives
+ node.children += refnode.children
+
+ self.merge_tree()
+
+ def __repr__(self) -> str:
+ name = self.root().get_field("compatible")
+ return "<Devicetree %s>" % name
+
+ def to_dts(self, level: int = 0) -> str:
+ """Convert the tree back to Devicetree Source"""
+ out = ""
+
+ for d in self.directives:
+ out += d.to_dts()
+ for p in self.properties:
+ out += p.to_dts()
+ for c in self.children:
+ out += c.to_dts()
+
+ return out
+
+ def get_by_path(self, path: Union[Path, str]) -> Optional[Node]:
+ """Get a node in the tree by path (ex. /cpus/cpu@0)"""
+
+ # Find and replace all aliases in the path
+ aliases = self.aliases()
+ if aliases:
+ for prop in aliases.properties:
+ if prop.name in path and len(prop.values) > 0:
+ path = path.replace(prop.name, prop.values[0])
+
+ return self.root().get_by_path(path)
+
+ @staticmethod
+ # pylint: disable=arguments-differ
+ def from_dts(dts: str) -> 'Devicetree':
+ """Parse a string and return a Devicetree object"""
+ # pylint: disable=import-outside-toplevel,cyclic-import
+ from pydevicetree.source import parseTree
+ return parseTree(dts)
+
+ @staticmethod
+ def parseFile(filename: str, followIncludes: bool = False) -> 'Devicetree':
+ """Parse a file and return a Devicetree object"""
+ # pylint: disable=import-outside-toplevel,cyclic-import
+ from cot_dt2c.pydevicetree.source.parser import parseTree
+ with open(filename, 'r') as f:
+ contents = f.read()
+ dirname = os.path.dirname(filename)
+ if dirname != "":
+ dirname += "/"
+ return parseTree(contents, dirname, followIncludes)
+
+ @staticmethod
+ def parseStr(input: str, followIncludes: bool = False) -> 'Devicetree':
+ from cot_dt2c.pydevicetree.source.parser import parseTree
+ return parseTree(input, "", followIncludes)
+
+ def all_nodes(self) -> Iterable[Node]:
+ """Get an iterable over all nodes in the tree"""
+ return self.child_nodes()
+
+ def root(self) -> Node:
+ """Get the root node of the tree"""
+ for n in self.all_nodes():
+ if n.name == "/":
+ return n
+ raise Exception("Devicetree has no root node!")
+
+ def aliases(self) -> Optional[Node]:
+ """Get the aliases node of the tree if it exists"""
+ for n in self.all_nodes():
+ if n.name == "aliases":
+ return n
+ return None
+
+ def chosen(self, property_name: str, func: ChosenCallback = None) -> Optional[PropertyValues]:
+ """Get the values associated with one of the properties in the chosen node"""
+ def match_chosen(node: Node) -> bool:
+ return node.name == "chosen"
+
+ for n in filter(match_chosen, self.all_nodes()):
+ for p in n.properties:
+ if p.name == property_name:
+ if func is not None:
+ func(p.values)
+ return p.values
+
+ return None
diff --git a/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/property.py b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/property.py
new file mode 100644
index 0000000..d5fb687
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/property.py
@@ -0,0 +1,278 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 SiFive Inc.
+# SPDX-License-Identifier: Apache-2.0
+
+from typing import List, Any, cast, Tuple, Optional, Iterable
+from itertools import zip_longest
+
+from cot_dt2c.pydevicetree.ast.helpers import wrapStrings, formatLevel
+
+class PropertyValues:
+ """PropertyValues is the parent class of all values which can be assigned to a Property
+
+ Child classes include
+
+ Bytestring
+ CellArray
+ StringList
+ """
+ def __init__(self, values: List[Any]):
+ """Create a PropertyValue"""
+ self.values = values
+
+ def __repr__(self) -> str:
+ return "<PropertyValues " + self.values.__repr__() + ">"
+
+ def __str__(self) -> str:
+ return self.to_dts()
+
+ def __iter__(self):
+ return iter(self.values)
+
+ def __len__(self) -> int:
+ return len(self.values)
+
+ def to_dts(self, formatHex: bool = False) -> str:
+ """Format the values in Devicetree Source format"""
+ return ", ".join(wrapStrings(self.values, formatHex))
+
+ def __getitem__(self, key) -> Any:
+ return self.values[key]
+
+ def __eq__(self, other) -> bool:
+ if isinstance(other, PropertyValues):
+ return self.values == other.values
+ return self.values == other
+
+class Bytestring(PropertyValues):
+ """A Bytestring is a sequence of bytes
+
+ In Devicetree, Bytestrings are represented as a sequence of two-digit hexadecimal integers,
+ optionally space-separated, enclosed by square brackets:
+
+ [de ad be eef]
+ """
+ def __init__(self, bytelist: List[int]):
+ """Create a Bytestring object"""
+ PropertyValues.__init__(self, cast(List[Any], bytearray(bytelist)))
+
+ def __repr__(self) -> str:
+ return "<Bytestring " + str(self.values) + ">"
+
+ def to_dts(self, formatHex: bool = False) -> str:
+ """Format the bytestring in Devicetree Source format"""
+ return "[" + " ".join("%02x" % v for v in self.values) + "]"
+
+class CellArray(PropertyValues):
+ """A CellArray is an array of integer values
+
+ CellArrays are commonly used as the value of Devicetree properties like `reg` and `interrupts`.
+ The interpretation of each element of a CellArray is device-dependent. For example, the `reg`
+ property encodes a CellArray as a list of tuples (base address, size), while the `interrupts`
+ property encodes a CellArray as simply a list of interrupt line numbers.
+ """
+ def __init__(self, cells: List[Any]):
+ """Create a CellArray object"""
+ PropertyValues.__init__(self, cells)
+
+ def __repr__(self) -> str:
+ return "<CellArray " + self.values.__repr__() + ">"
+
+ def to_dts(self, formatHex: bool = False) -> str:
+ """Format the cell array in Devicetree Source format"""
+ dtsValues = []
+ for i in self.values:
+ if not isinstance(i, OneString) and not isinstance(i, str):
+ dtsValues.append(i)
+ return "<" + " ".join(wrapStrings(dtsValues, formatHex)) + ">"
+
+class RegArray(CellArray):
+ """A RegArray is the CellArray assigned to the reg property"""
+ def __init__(self, cells: List[int],
+ address_cells: int, size_cells: int,
+ names: Optional[List[str]] = None):
+ """Create a RegArray from a list of ints"""
+ # pylint: disable=too-many-locals
+ CellArray.__init__(self, cells)
+ self.address_cells = address_cells
+ self.size_cells = size_cells
+
+ self.tuples = [] # type: List[Tuple[int, int, Optional[str]]]
+
+ group_size = self.address_cells + self.size_cells
+
+ if len(cells) % group_size != 0:
+ raise Exception("CellArray does not contain enough cells")
+
+ grouped_cells = [cells[i:i+group_size] for i in range(0, len(cells), group_size)]
+
+ if not names:
+ names = []
+
+ for group, name in zip_longest(grouped_cells, cast(Iterable[Any], names)):
+ address = 0
+ a_cells = list(reversed(group[:self.address_cells]))
+ for a, i in zip(a_cells, range(len(a_cells))):
+ address += (1 << (32 * i)) * a
+
+ size = 0
+ s_cells = list(reversed(group[self.address_cells:]))
+ for s, i in zip(s_cells, range(len(s_cells))):
+ size += (1 << (32 * i)) * s
+
+ self.tuples.append(cast(Tuple[int, int, Optional[str]], tuple([address, size, name])))
+
+ def get_by_name(self, name: str) -> Optional[Tuple[int, int]]:
+ """Returns the (address, size) tuple with a given name"""
+ for t in self.tuples:
+ if t[2] == name:
+ return cast(Tuple[int, int], tuple(t[:2]))
+ return None
+
+ def __repr__(self) -> str:
+ return "<RegArray " + self.values.__repr__() + ">"
+
+ def __iter__(self) -> Iterable[Tuple[int, int]]:
+ return cast(Iterable[Tuple[int, int]], map(lambda t: tuple(t[:2]), self.tuples))
+
+ def __len__(self) -> int:
+ return len(self.tuples)
+
+ def __getitem__(self, key) -> Optional[Tuple[int, int]]:
+ return list(self.__iter__())[key]
+
+class RangeArray(CellArray):
+ """A RangeArray is the CellArray assigned to the range property"""
+ def __init__(self, cells: List[int], child_address_cells: int,
+ parent_address_cells: int, size_cells: int):
+ """Create a RangeArray from a list of ints"""
+ # pylint: disable=too-many-locals
+ CellArray.__init__(self, cells)
+ self.child_address_cells = child_address_cells
+ self.parent_address_cells = parent_address_cells
+ self.size_cells = size_cells
+
+ self.tuples = [] # type: List[Tuple[int, int, int]]
+
+ group_size = self.child_address_cells + self.parent_address_cells + self.size_cells
+
+ if len(cells) % group_size != 0:
+ raise Exception("CellArray does not contain enough cells")
+
+ grouped_cells = [cells[i:i+group_size] for i in range(0, len(cells), group_size)]
+
+ def sum_cells(cells: List[int]):
+ value = 0
+ for cell, index in zip(list(reversed(cells)), range(len(cells))):
+ value += (1 << (32 * index)) * cell
+ return value
+
+ for group in grouped_cells:
+ child_address = sum_cells(group[:self.child_address_cells])
+ parent_address = sum_cells(group[self.child_address_cells: \
+ self.child_address_cells + self.parent_address_cells])
+ size = sum_cells(group[self.child_address_cells + self.parent_address_cells:])
+
+ self.tuples.append(cast(Tuple[int, int, int],
+ tuple([child_address, parent_address, size])))
+
+ def __repr__(self) -> str:
+ return "<RangeArray " + self.values.__repr__() + ">"
+
+ def __iter__(self):
+ return iter(self.tuples)
+
+ def __len__(self) -> int:
+ return len(self.tuples)
+
+ def __getitem__(self, key) -> Any:
+ return self.tuples[key]
+
+class StringList(PropertyValues):
+ """A StringList is a list of null-terminated strings
+
+ The most common use of a StringList in Devicetree is to describe the `compatible` property.
+ """
+ def __init__(self, strings: List[str]):
+ """Create a StringList object"""
+ PropertyValues.__init__(self, strings)
+
+ def __repr__(self) -> str:
+ return "<StringList " + self.values.__repr__() + ">"
+
+ def to_dts(self, formatHex: bool = False) -> str:
+ """Format the list of strings in Devicetree Source format"""
+ return ", ".join(wrapStrings(self.values))
+
+class OneString(PropertyValues):
+ def __init__(self, string: str):
+ PropertyValues.__init__(self, string)
+
+ def __repr__(self) -> str:
+ return self.values.__repr__()
+
+ def to_dts(self, formatHex: bool = False) -> str:
+ return super().to_dts(formatHex)
+
+class Property:
+ """A Property is a key-value pair for a Devicetree Node
+
+ Properties are used to describe Nodes in the tree. There are many common properties, like
+
+ - compatible
+ - reg
+ - reg-names
+ - ranges
+ - interrupt-controller
+ - interrupts
+ - interrupt-parent
+ - clocks
+ - status
+
+ Which might commonly describe many or all nodes in a tree, and there are device, vendor,
+ operating system, runtime-specific properties.
+
+ Properties can possess no value, conveing meaning solely by their presence:
+
+ interrupt-controller;
+
+ Properties can also possess values such as an array of cells, a list of strings, etc.
+
+ reg = <0x10013000 0x1000>;
+ compatible = "sifive,rocket0", "riscv";
+
+ And properties can posses arbitrarily complex values, such as the following from the
+ Devicetree specification:
+
+ example = <0xf00f0000 19>, "a strange property format";
+ """
+ def __init__(self, name: str, values: PropertyValues):
+ """Create a Property object"""
+ self.name = name
+ self.values = values
+
+ def __repr__(self) -> str:
+ return "<Property %s>" % self.name
+
+ def __str__(self) -> str:
+ return self.to_dts()
+
+ @staticmethod
+ def from_dts(dts: str) -> 'Property':
+ """Parse a file and return a Devicetree object"""
+ # pylint: disable=import-outside-toplevel,cyclic-import
+ from pydevicetree.source import parseProperty
+ return parseProperty(dts)
+
+ def to_dts(self, level: int = 0) -> str:
+ """Format the Property assignment in Devicetree Source format"""
+ if self.name in ["reg", "ranges"]:
+ value = self.values.to_dts(formatHex=True)
+ else:
+ value = self.values.to_dts(formatHex=False)
+
+ if value != "":
+ return formatLevel(level, "%s = %s;\n" % (self.name, value))
+ if self.name == "ifdef":
+ return ""
+ return formatLevel(level, "%s;\n" % self.name)
diff --git a/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/reference.py b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/reference.py
new file mode 100644
index 0000000..54b2d28
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/pydevicetree/ast/reference.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 SiFive Inc.
+# SPDX-License-Identifier: Apache-2.0
+
+from typing import Union, Iterator
+
+class Label:
+ """A Label is a unique identifier for a Node
+
+ For example, the following node has the label "uart0":
+
+ uart0: uart@10013000 {
+ ...
+ };
+ """
+ def __init__(self, name: str):
+ """Create a Label"""
+ self.name = name
+
+ def __repr__(self) -> str:
+ return "<Label " + self.name + ">"
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, Label):
+ return self.name == other.name
+ if isinstance(other, str):
+ return self.name == other
+ return False
+
+ def to_dts(self) -> str:
+ """Format the label in Devicetree Source format"""
+ return self.name + ":"
+
+class Path:
+ """A Path uniquely identifies a Node by its parents and (optionally) unit address"""
+ def __init__(self, path: str):
+ """Create a path out of a string"""
+ self.path = path
+
+ def to_dts(self) -> str:
+ """Format the Path in Devicetree Source format"""
+ return self.path
+
+ def __repr__(self) -> str:
+ return "<Path " + self.to_dts() + ">"
+
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, Path):
+ return self.to_dts() == other.to_dts()
+ if isinstance(other, str):
+ return self.to_dts() == other
+ return False
+
+ def __iter__(self) -> Iterator[str]:
+ return iter(self.path.split("/"))
+
+ def replace(self, old: str, new: str) -> 'Path':
+ """Replace any elements of the path which match 'old' with a new element 'new'"""
+ return Path(self.path.replace(old, new))
+
+class Reference:
+ """A Reference is a Devicetree construct which points to a Node in the tree
+
+ The following are types of references:
+
+ - A reference to a label:
+
+ &my-label;
+
+ - A reference to a node by path:
+
+ &{/path/to/node@deadbeef}
+
+ This is the parent class for both types of references, LabelReference and PathReference
+ """
+ # pylint: disable=no-self-use
+ def to_dts(self, formatHex: bool = False) -> str:
+ """Format the Reference in Devicetree Source format"""
+ return ""
+
+class LabelReference(Reference):
+ """A LabelReference is a reference to a Node by label"""
+ def __init__(self, label: Union[Label, str]):
+ """Create a LabelReference from a Label or string"""
+ if isinstance(label, Label):
+ self.label = label
+ elif isinstance(label, str):
+ self.label = Label(label)
+
+ def __repr__(self) -> str:
+ return "<LabelReference " + self.to_dts() + ">"
+
+ def to_dts(self, formatHex: bool = False) -> str:
+ """Format the LabelReference in Devicetree Source format"""
+ return "&" + self.label.name
+
+class PathReference(Reference):
+ """A PathReference is a reference to a Node by path"""
+ def __init__(self, path: Union[Path, str]):
+ """Create a PathReference from a Path or string"""
+ if isinstance(path, Path):
+ self.path = path
+ elif isinstance(path, str):
+ self.path = Path(path)
+
+ def __repr__(self) -> str:
+ return "<PathReference " + self.to_dts() + ">"
+
+ def to_dts(self, formatHex: bool = False) -> str:
+ """Format the PathReference in Devicetree Source format"""
+ return "&{" + self.path.to_dts() + "}"
diff --git a/tools/cot_dt2c/cot_dt2c/pydevicetree/source/__init__.py b/tools/cot_dt2c/cot_dt2c/pydevicetree/source/__init__.py
new file mode 100644
index 0000000..96768b3
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/pydevicetree/source/__init__.py
@@ -0,0 +1,5 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 SiFive Inc.
+# SPDX-License-Identifier: Apache-2.0
+
+from cot_dt2c.pydevicetree.source.parser import parseTree, parseNode, parseProperty
diff --git a/tools/cot_dt2c/cot_dt2c/pydevicetree/source/grammar.py b/tools/cot_dt2c/cot_dt2c/pydevicetree/source/grammar.py
new file mode 100644
index 0000000..fb165e1
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/pydevicetree/source/grammar.py
@@ -0,0 +1,95 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 SiFive Inc.
+# SPDX-License-Identifier: Apache-2.0
+
+import os
+import sys
+
+import pyparsing as p # type: ignore
+
+ENV_CACHE_OPTION = "PYDEVICETREE_CACHE_SIZE_BOUND"
+
+cache_bound = None
+if ENV_CACHE_OPTION in os.environ:
+ option = os.environ[ENV_CACHE_OPTION]
+ if option != "None":
+ try:
+ cache_bound = int(option)
+ except ValueError:
+ print("%s requires a valid integer" % ENV_CACHE_OPTION, file=sys.stderr)
+p.ParserElement.enablePackrat(cache_bound)
+
+node_name = p.Word(p.alphanums + ",.-+_") ^ p.Literal("/")
+integer = p.pyparsing_common.integer ^ (p.Literal("0x").suppress() + p.pyparsing_common.hex_integer)
+unit_address = p.pyparsing_common.hex_integer
+unit_addresses = p.delimitedList(unit_address("address"), delim=",")
+node_handle = node_name("node_name") + p.Optional(p.Literal("@") + unit_addresses)
+property_name = p.Word(p.alphanums + ",.-_+?#")
+label = p.Word(p.alphanums + "_").setResultsName("label")
+label_creation = p.Combine(label + p.Literal(":"))
+string = p.QuotedString(quoteChar='"')
+stringlist = p.delimitedList(string)
+node_path = p.Combine(p.Literal("/") + \
+ p.delimitedList(node_handle, delim="/", combine=True)).setResultsName("path")
+path_reference = p.Literal("&{").suppress() + node_path + p.Literal("}").suppress()
+label_reference = p.Literal("&").suppress() + label
+label_raw = p.Word(p.alphanums + "_")
+reference = path_reference ^ label_reference ^ label_raw
+include_directive = p.Literal("/include/") + p.QuotedString(quoteChar='"')
+generic_directive = p.QuotedString(quoteChar="/", unquoteResults=False) + \
+ p.Optional(string ^ property_name ^ node_name ^ reference ^ (integer * 2)) + \
+ p.Literal(";").suppress()
+directive = include_directive ^ generic_directive
+
+operator = p.oneOf("~ ! * / + - << >> < <= > >= == != & ^ | && ||")
+arith_expr = p.Forward()
+ternary_element = arith_expr ^ integer
+ternary_expr = ternary_element + p.Literal("?") + ternary_element + p.Literal(":") + ternary_element
+arith_expr = p.nestedExpr(content=(p.OneOrMore(operator ^ integer) ^ ternary_expr))
+arth_str = p.Forward()
+arith_str_expr = p.nestedExpr(content=(p.OneOrMore(operator ^ integer ^ label_raw ^ p.Literal(",")) ^ ternary_expr))
+
+label_list = p.OneOrMore(p.Combine(label + p.Literal("\n")))
+
+cell_array = p.Literal("<").suppress() + \
+ p.ZeroOrMore(integer ^ arith_expr ^ arith_str_expr ^ label_list ^ string ^ reference ^ label_creation.suppress()) + \
+ p.Literal(">").suppress()
+bytestring = p.Literal("[").suppress() + \
+ (p.OneOrMore(p.Word(p.hexnums, exact=2) ^ label_creation.suppress())) + \
+ p.Literal("]").suppress()
+property_values = p.Forward()
+property_values = p.delimitedList(property_values ^ cell_array ^ bytestring ^ stringlist ^ \
+ reference ^ label_raw)
+property_assignment = property_name("property_name") + p.Optional(p.Literal("=").suppress() + \
+ (property_values)).setResultsName("value") + p.Optional(p.Literal(";").suppress())
+
+ifdef_label = p.ZeroOrMore(p.Word(p.alphanums + " _|//*=/(/)"))
+ifdef_define = p.Combine(p.Keyword("#if") + ifdef_label)
+ifdef_end = p.Combine(p.Keyword("#endif") + ifdef_label)
+ifdef_define_values = p.Forward()
+ifdef_define_values = p.ZeroOrMore(ifdef_define)
+ifdef_end_values = p.Forward()
+ifdef_end_values = p.ZeroOrMore(ifdef_end)
+
+node_opener = ifdef_define_values + p.Optional(label_creation) + node_handle + p.Literal("{").suppress()
+node_reference_opener = reference + p.Literal("{").suppress()
+node_closer = p.Literal("}").suppress() + p.Literal(";").suppress() + ifdef_end_values
+node_definition = p.Forward()
+# pylint: disable=expression-not-assigned
+node_definition << (node_opener ^ node_reference_opener) + \
+ p.ZeroOrMore(property_assignment ^ directive ^ node_definition ^ ifdef_define ^ ifdef_end) + \
+ node_closer
+
+devicetree = p.ZeroOrMore(directive ^ node_definition)
+
+devicetree.ignore(p.cStyleComment)
+devicetree.ignore("//" + p.SkipTo(p.lineEnd))
+devicetree.ignore("#include" + p.SkipTo(p.lineEnd))
+devicetree.ignore("#define" + p.SkipTo(p.lineEnd))
+devicetree.ignore("#else" + p.SkipTo(p.lineEnd))
+devicetree.ignore("#error" + p.SkipTo(p.lineEnd))
+devicetree.ignore("#ifndef" + p.SkipTo(p.lineEnd))
+
+if __name__ == "__main__":
+ if len(sys.argv) > 1:
+ devicetree.parseFile(sys.argv[1]).pprint()
diff --git a/tools/cot_dt2c/cot_dt2c/pydevicetree/source/parser.py b/tools/cot_dt2c/cot_dt2c/pydevicetree/source/parser.py
new file mode 100644
index 0000000..0692482
--- /dev/null
+++ b/tools/cot_dt2c/cot_dt2c/pydevicetree/source/parser.py
@@ -0,0 +1,238 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 SiFive Inc.
+# SPDX-License-Identifier: Apache-2.0
+
+from itertools import chain
+
+from cot_dt2c.pydevicetree.source import grammar
+from cot_dt2c.pydevicetree.ast import *
+
+ifdef_stack = []
+
+def transformNode(string, location, tokens):
+ """Transforms a ParseResult into a Node"""
+ properties = [e for e in tokens.asList() if isinstance(e, Property)]
+ directives = [e for e in tokens.asList() if isinstance(e, Directive)]
+ children = [e for e in tokens.asList() if isinstance(e, Node)]
+
+ if isinstance(tokens[0], Reference):
+ return NodeReference(tokens[0], properties=properties,
+ directives=directives, children=children)
+ return Node(tokens.node_name, tokens.label, tokens.address, properties=properties,
+ directives=directives, children=children)
+
+def transformPropertyAssignment(string, location, tokens):
+ """Transforms a ParseResult into a Property"""
+ for v in tokens.value:
+ if isinstance(v, PropertyValues):
+ return Property(tokens.property_name, v)
+ if isinstance(v, CellArray):
+ return Property(tokens.property_name, v)
+ if isinstance(v, StringList):
+ return Property(tokens.property_name, v)
+ if isinstance(v, Reference):
+ return Property(tokens.property_name, v)
+
+ return Property(tokens.property_name, PropertyValues([]))
+
+def transformDirective(string, location, tokens):
+ """Transforms a ParseResult into a Directive"""
+ if len(tokens.asList()) > 1:
+ return Directive(tokens[0], tokens[1])
+ return Directive(tokens[0])
+
+def evaluateArithExpr(string, location, tokens):
+ """Evaluates a ParseResult as a python expression"""
+ flat_tokens = list(chain.from_iterable(tokens.asList()))
+ expr = " ".join(str(t) for t in flat_tokens)
+ # pylint: disable=eval-used
+ return eval(expr)
+
+def transformTernary(string, location, tokens):
+ """Evaluates a ParseResult as a ternary expression"""
+ # pylint: disable=eval-used
+ return eval(str(tokens[2]) +" if " + str(tokens[0]) + " else " + str(tokens[4]))
+
+def transformPropertyValues(string, location, tokens):
+ """Transforms a ParseResult into a PropertyValues"""
+ if len(tokens.asList()) == 1:
+ return tokens.asList()[0]
+ return PropertyValues(tokens.asList())
+
+def transformStringList(string, location, tokens):
+ """Transforms a ParseResult into a StringList"""
+ return StringList(tokens.asList())
+
+def transformString(string, location, token):
+ return OneString(token)
+
+def transformIfdefMacro(string, location, tokens):
+ tokenlist = tokens.asList()
+ for t in tokenlist:
+ ifdef_stack.append(t)
+ return Property("ifdef", PropertyValues(ifdef_stack.copy()))
+
+def transformIfdefEnd(string, location, tokens):
+ tokenlist = tokens.asList()
+ for t in tokenlist:
+ ifdef_stack.pop()
+
+def transformIfdef(string, location, tokens):
+ return Property("ifdef", PropertyValues(tokens))
+
+def evaluateStrArithExpr(string, location, tokens):
+ """Evaluates a ParseResult as a python expression"""
+ flat_tokens = list(chain.from_iterable(tokens.asList()))
+ for i, t in enumerate(flat_tokens):
+ if isinstance(t, int):
+ flat_tokens[i] = "(" + str(t) + ")"
+ expr = " ".join(str(t) for t in flat_tokens)
+ # pylint: disable=eval-used
+ return expr
+
+def transformBytestring(string, location, tokens):
+ """Transforms a ParseResult into a Bytestring"""
+ inttokens = []
+ for t in tokens.asList():
+ if all(c in "0123456789abcdefABCDEF" for c in t):
+ inttokens.append(int(t, base=16))
+ return Bytestring(inttokens)
+
+def transformCellArray(string, location, tokens):
+ """Transforms a ParseResult into a CellArray"""
+ return CellArray(tokens.asList())
+
+def transformLabel(string, location, tokens):
+ """Transforms a ParseResult into a Label"""
+ return Label(tokens.label)
+
+def transformPath(string, location, tokens):
+ """Transforms a ParseResult into a Path"""
+ path = ""
+ for handle in tokens.path[0].split("/"):
+ if "@" in handle:
+ node, address = handle.split("@")
+ path += "/%s@%x" % (node, int(address))
+ elif handle != "":
+ path += "/" + handle
+ return Path(path)
+
+def transformPathReference(string, location, tokens):
+ """Transforms a ParseResult into a PathReference"""
+ return PathReference(tokens[0])
+
+def transformLabelReference(string, location, tokens):
+ """Transforms a ParseResult into a LabelReference"""
+ return LabelReference(tokens[0])
+
+def transformReference(string, location, tokens):
+ """Transforms a ParseResult into a Reference"""
+ if isinstance(tokens[0], Reference):
+ return tokens[0]
+ return None
+
+grammar.label.setParseAction(transformLabel)
+grammar.node_path.setParseAction(transformPath)
+grammar.path_reference.setParseAction(transformPathReference)
+grammar.label_reference.setParseAction(transformLabelReference)
+grammar.reference.setParseAction(transformReference)
+grammar.node_definition.setParseAction(transformNode)
+grammar.property_assignment.setParseAction(transformPropertyAssignment)
+grammar.directive.setParseAction(transformDirective)
+grammar.arith_expr.setParseAction(evaluateArithExpr)
+grammar.ternary_expr.setParseAction(transformTernary)
+grammar.stringlist.setParseAction(transformStringList)
+grammar.bytestring.setParseAction(transformBytestring)
+grammar.cell_array.setParseAction(transformCellArray)
+grammar.property_values.setParseAction(transformPropertyValues)
+grammar.label_raw.setParseAction(transformString)
+grammar.ifdef_define_values.setParseAction(transformIfdefMacro)
+grammar.ifdef_end_values.setParseAction(transformIfdefEnd)
+grammar.arith_str_expr.setParseAction(transformPropertyValues)
+
+def printTree(tree, level=0):
+ """Helper function to print a bunch of elements as a tree"""
+ def printlevel(level, s):
+ print(" " * level + s)
+
+ for item in tree:
+ if isinstance(item, Node):
+ if item.address:
+ printlevel(level, "Node %s@%x" % (item.name, item.address))
+ else:
+ printlevel(level, "Node %s" % item.name)
+
+ if item.label:
+ printlevel(level, " Label: %s" % item.label)
+
+ if item.parent:
+ printlevel(level, " Parent: %s" % item.parent)
+
+ printTree(item.properties, level=(level + 1))
+
+ printTree(item.children, level=(level + 1))
+ elif isinstance(item, Property):
+ if item.values:
+ printlevel(level, "Property %s: %s" % (item.name, item.values))
+ else:
+ printlevel(level, "Property %s" % item.name)
+ elif isinstance(item, Directive):
+ if item.options:
+ printlevel(level, "Directive %s: %s" % (item.directive, item.options))
+ else:
+ printlevel(level, "Directive %s" % item.directive)
+
+def parentNodes(tree, parent=None):
+ """Walks a tree and sets Nodes' parent field to point at their parent"""
+ for item in tree:
+ if isinstance(item, Node):
+ item.parent = parent
+ parentNodes(item.children, item)
+
+def recurseIncludeFiles(elements, pwd):
+ """Recursively follows and parses /include/ directives an a tree"""
+ for e in elements:
+ if isinstance(e, Directive):
+ if e.directive == "/include/":
+ # Prefix with current directory if path is not absolute
+ if e.option[0] != '/':
+ e.option = pwd + e.option
+
+ with open(e.option, 'r') as f:
+ contents = f.read()
+
+ elements += parseElements(contents)
+
+ del elements[elements.asList().index(e)]
+
+def parseElements(dts, pwd="", followIncludes=False):
+ """Parses a string into a list of elements"""
+ elements = grammar.devicetree.parseString(dts, parseAll=True)
+ parentNodes(elements)
+ if followIncludes:
+ recurseIncludeFiles(elements, pwd)
+ return elements
+
+def parseTree(dts, pwd="", followIncludes=False):
+ """Parses a string into a full Devicetree"""
+ return Devicetree(parseElements(dts, pwd, followIncludes))
+
+def parseNode(dts):
+ """Parses a string into a Devictreee Node"""
+ return grammar.node_definition.parseString(dts, parseAll=True)[0]
+
+def parseProperty(dts):
+ """Parses a string into a Devicetree Property"""
+ return grammar.property_assignment.parseString(dts, parseAll=True)[0]
+
+if __name__ == "__main__":
+ import sys
+ if len(sys.argv) > 1:
+ with open(sys.argv[1], 'r') as f:
+ dts = f.read()
+ tree = parseTree(dts)
+ printTree(tree)
+ print(tree)
+ else:
+ print("Please pass the devicetree source file as an argument")
+ sys.exit(1)
diff --git a/tools/cot_dt2c/pyproject.toml b/tools/cot_dt2c/pyproject.toml
new file mode 100644
index 0000000..d383924
--- /dev/null
+++ b/tools/cot_dt2c/pyproject.toml
@@ -0,0 +1,60 @@
+# 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"
+pyparsing = "^2.4.7"
+plotly = "^5.23.0"
+pandas = "^2.2.2"
+igraph = "^0.11.6"
+
+[tool.poetry.dev-dependencies]
+mypy = "^0.910"
+pytest = "^6.2.5"
+pyparsing = "^2.4.7"
+plotly = "^5.23.0"
+pandas = "^2.2.2"
+igraph = "^0.11.6"
+
+[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.coverage.run]
+source = ["tests"]
+
+[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/requirements.txt b/tools/cot_dt2c/requirements.txt
new file mode 100644
index 0000000..246b81d
--- /dev/null
+++ b/tools/cot_dt2c/requirements.txt
@@ -0,0 +1,6 @@
+mypy
+pylint
+pyparsing
+igraph
+pandas
+plotly
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..ec5f9c7
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_invalid_bracket.dtsi
@@ -0,0 +1,57 @@
+/*
+ * 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
+ *
+ */
+
+#include <example/example.h>
+#include <example/example/example.h>
+
+cot {
+ manifests {
+ compatible = "arm, cert-descs";
+
+ example_cert: example_cert {
+ root-certificate;
+ image-id =<EXAMPLE_ID>;
+ antirollback-counter = <&example_ctr>;
+
+ example_hash: example_hash
+ {
+ oid = EXAMPLE_HASH_ID;
+ };
+
+ };
+ };
+
+ 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_ifdef.dtsi b/tools/cot_dt2c/tests/test_invalid_ifdef.dtsi
new file mode 100644
index 0000000..5bc6bb9
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_invalid_ifdef.dtsi
@@ -0,0 +1,59 @@
+/*
+ * 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 ifdef macro
+ *
+ */
+
+#include <example/example.h>
+#include <example/example/example.h>
+
+cot {
+ manifests {
+ compatible = "arm, cert-descs";
+
+ example_cert: example_cert {
+ root-certificate;
+ image-id =<EXAMPLE_ID>;
+ antirollback-counter = <&example_ctr>;
+
+ example_hash: example_hash
+ {
+ oid = EXAMPLE_HASH_ID;
+ };
+
+ };
+ };
+
+#if defined(test)
+ 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_ifdef2.dtsi b/tools/cot_dt2c/tests/test_invalid_ifdef2.dtsi
new file mode 100644
index 0000000..c915168
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_invalid_ifdef2.dtsi
@@ -0,0 +1,61 @@
+/*
+ * 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 ifdef macro
+ *
+ */
+
+#include <example/example.h>
+#include <example/example/example.h>
+
+cot {
+ manifests {
+ compatible = "arm, cert-descs";
+
+ example_cert: example_cert {
+ root-certificate;
+ image-id =<EXAMPLE_ID>;
+ antirollback-counter = <&example_ctr>;
+
+ example_hash: example_hash
+ {
+ oid = EXAMPLE_HASH_ID;
+ };
+
+ };
+ };
+
+#if defined(test)
+ images {
+ compatible = "arm, img-descs";
+
+ example {
+ image-id = <EXAMPLE_ID>;
+ parent = <&example_cert>;
+ hash = <&example_hash>;
+ };
+ };
+#endif
+#endif
+};
+
+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_missing_attribute.dtsi b/tools/cot_dt2c/tests/test_invalid_missing_attribute.dtsi
new file mode 100644
index 0000000..9c0a5f2
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_invalid_missing_attribute.dtsi
@@ -0,0 +1,267 @@
+/*
+ * 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
+ *
+ */
+
+#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";
+
+ cca_content_cert: cca_content_cert {
+ root-certificate;
+ antirollback-counter = <&cca_nv_ctr>;
+
+ tb_fw_hash: tb_fw_hash {
+ oid = TRUSTED_BOOT_FW_HASH_OID;
+ };
+ tb_fw_config_hash: tb_fw_config_hash {
+ oid = TRUSTED_BOOT_FW_CONFIG_HASH_OID;
+ };
+ hw_config_hash: hw_config_hash {
+ };
+ fw_config_hash: fw_config_hash {
+ oid = FW_CONFIG_HASH_OID;
+ };
+ soc_fw_hash: soc_fw_hash {
+ oid = SOC_AP_FW_HASH_OID;
+ };
+ soc_fw_config_hash: soc_fw_config_hash {
+ oid = SOC_FW_CONFIG_HASH_OID;
+ };
+ rmm_hash: rmm_hash {
+ oid = RMM_HASH_OID;
+ };
+ };
+
+ core_swd_key_cert: core_swd_key_cert {
+ root-certificate;
+ 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 {
+ root-certificate;
+ 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 {
+ 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>;
+ 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 {
+ 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_missing_attribute2.dtsi b/tools/cot_dt2c/tests/test_invalid_missing_attribute2.dtsi
new file mode 100644
index 0000000..01b2597
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_invalid_missing_attribute2.dtsi
@@ -0,0 +1,269 @@
+/*
+ * 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
+ *
+ */
+
+#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";
+
+ cca_content_cert: cca_content_cert {
+ root-certificate;
+ image-id =<CCA_CONTENT_CERT_ID>;
+ antirollback-counter = <&cca_nv_ctr>;
+
+ tb_fw_hash: tb_fw_hash {
+ oid = TRUSTED_BOOT_FW_HASH_OID;
+ };
+ tb_fw_config_hash: tb_fw_config_hash {
+ oid = TRUSTED_BOOT_FW_CONFIG_HASH_OID;
+ };
+ hw_config_hash: hw_config_hash {
+ oid = HW_CONFIG_HASH_OID;
+ };
+ fw_config_hash: fw_config_hash {
+ oid = FW_CONFIG_HASH_OID;
+ };
+ soc_fw_hash: soc_fw_hash {
+ oid = SOC_AP_FW_HASH_OID;
+ };
+ soc_fw_config_hash: soc_fw_config_hash {
+ oid = SOC_FW_CONFIG_HASH_OID;
+ };
+ rmm_hash: rmm_hash {
+ oid = RMM_HASH_OID;
+ };
+ };
+
+ core_swd_key_cert: core_swd_key_cert {
+ root-certificate;
+ 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 {
+ root-certificate;
+ 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 = <&cca_content_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 = <&cca_content_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>;
+ 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>;
+ hash = <&nt_fw_config_hash>;
+ };
+
+#if defined(SPD_spmd)
+ sp_pkg1 {
+ image-id = <SP_PKG1_ID>;
+ 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 = <&wrong_parent>;
+ 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_missing_ctr.dtsi b/tools/cot_dt2c/tests/test_invalid_missing_ctr.dtsi
new file mode 100644
index 0000000..5958f5d
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_invalid_missing_ctr.dtsi
@@ -0,0 +1,56 @@
+/*
+ * 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
+ *
+ */
+
+#include <example/example.h>
+#include <example/example/example.h>
+
+cot {
+ manifests {
+ compatible = "arm, cert-descs";
+
+ example_cert: example_cert {
+ root-certificate;
+ image-id =<EXAMPLE_ID>;
+ signing-key = <&swd_rot_pk>;
+ antirollback-counter = <&example_ctr>;
+
+ example_hash: example_hash
+ {
+ oid = EXAMPLE_HASH_ID;
+ };
+
+ };
+ };
+
+ 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>;
+
+};
+
+rot_keys {
+ example_pk: example_pk {
+ oid = EXAMPLE_PK_OID;
+ };
+};
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..b761beb
--- /dev/null
+++ b/tools/cot_dt2c/tests/test_invalid_undefined_parent.dtsi
@@ -0,0 +1,269 @@
+/*
+ * 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
+ *
+ */
+
+#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";
+
+ cca_content_cert: cca_content_cert {
+ root-certificate;
+ image-id =<CCA_CONTENT_CERT_ID>;
+ antirollback-counter = <&cca_nv_ctr>;
+
+ tb_fw_hash: tb_fw_hash {
+ oid = TRUSTED_BOOT_FW_HASH_OID;
+ };
+ tb_fw_config_hash: tb_fw_config_hash {
+ oid = TRUSTED_BOOT_FW_CONFIG_HASH_OID;
+ };
+ hw_config_hash: hw_config_hash {
+ oid = HW_CONFIG_HASH_OID;
+ };
+ fw_config_hash: fw_config_hash {
+ oid = FW_CONFIG_HASH_OID;
+ };
+ soc_fw_hash: soc_fw_hash {
+ oid = SOC_AP_FW_HASH_OID;
+ };
+ soc_fw_config_hash: soc_fw_config_hash {
+ oid = SOC_FW_CONFIG_HASH_OID;
+ };
+ rmm_hash: rmm_hash {
+ oid = RMM_HASH_OID;
+ };
+ };
+
+ core_swd_key_cert: core_swd_key_cert {
+ root-certificate;
+ 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 {
+ root-certificate;
+ 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 = <&wrong_parent>;
+ 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 = <&wrong_parent>;
+ 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>;
+ 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>;
+ hash = <&nt_fw_config_hash>;
+ };
+
+#if defined(SPD_spmd)
+ sp_pkg1 {
+ image-id = <SP_PKG1_ID>;
+ 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 = <&wrong_parent>;
+ 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_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/renesas/rcar_layout_create/makefile b/tools/renesas/rcar_layout_create/makefile
index 8c2c054..7a64b19 100644
--- a/tools/renesas/rcar_layout_create/makefile
+++ b/tools/renesas/rcar_layout_create/makefile
@@ -1,4 +1,5 @@
#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
# Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
@@ -6,6 +7,7 @@
toolchains := aarch64
+include ../../../make_helpers/build-rules.mk
include ../../../make_helpers/common.mk
include ../../../make_helpers/toolchain.mk
@@ -85,33 +87,37 @@
# command
.PHONY: all
-all: $(OUTPUT_FILE_SA0) $(OUTPUT_FILE_SA6)
+
+all: $(FILE_NAME_SA0).srec $(FILE_NAME_SA0).bin
+all: $(FILE_NAME_SA6).srec $(FILE_NAME_SA6).bin
+
###################################################
# Linker
###################################################
-$(OUTPUT_FILE_SA0) : $(MEMORY_DEF_SA0) $(OBJ_FILE_SA0)
- $(aarch64-ld) $(OBJ_FILE_SA0) -nostdlib \
- -T $(MEMORY_DEF_SA0) \
- -o $(OUTPUT_FILE_SA0) \
- -Wl,-Map $(FILE_NAME_SA0).map \
+
+$(FILE_NAME_SA0).srec: $(OUTPUT_FILE_SA0) | $$(@D)/
+ $(aarch64-oc) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).srec
- $(aarch64-oc) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).srec
- $(aarch64-oc) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).bin
+$(FILE_NAME_SA0).bin: $(OUTPUT_FILE_SA0) | $$(@D)/
+ $(aarch64-oc) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).bin
-$(OUTPUT_FILE_SA6) : $(MEMORY_DEF_SA6) $(OBJ_FILE_SA6)
- $(aarch64-ld) $(OBJ_FILE_SA6) -nostdlib \
- -T $(MEMORY_DEF_SA6) \
- -o $(OUTPUT_FILE_SA6) \
- -Wl,-Map $(FILE_NAME_SA6).map \
+$(OUTPUT_FILE_SA0): $(MEMORY_DEF_SA0) $(OBJ_FILE_SA0) | $$(@D)/
+ $(aarch64-ld) $(OBJ_FILE_SA0) -nostdlib -T $(MEMORY_DEF_SA0) -o $(OUTPUT_FILE_SA0) -Wl,-Map $(FILE_NAME_SA0).map
- $(aarch64-oc) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).srec
- $(aarch64-oc) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).bin
+$(FILE_NAME_SA6).srec: $(OUTPUT_FILE_SA6) | $$(@D)/
+ $(aarch64-oc) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).srec
+
+$(FILE_NAME_SA6).bin: $(OUTPUT_FILE_SA6) | $$(@D)/
+ $(aarch64-oc) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).bin
+
+$(OUTPUT_FILE_SA6): $(MEMORY_DEF_SA6) $(OBJ_FILE_SA6) | $$(@D)/
+ $(aarch64-ld) $(OBJ_FILE_SA6) -nostdlib -T $(MEMORY_DEF_SA6) -o $(OUTPUT_FILE_SA6) -Wl,-Map $(FILE_NAME_SA6).map
###################################################
# Compile
###################################################
-%.o: %.c
+%.o: %.c | $$(@D)/
$(aarch64-cc) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
.PHONY: clean
diff --git a/tools/renesas/rzg_layout_create/makefile b/tools/renesas/rzg_layout_create/makefile
index d2a54ea..936420d 100644
--- a/tools/renesas/rzg_layout_create/makefile
+++ b/tools/renesas/rzg_layout_create/makefile
@@ -1,4 +1,5 @@
#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
# Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
@@ -6,6 +7,7 @@
toolchains := aarch64
+include ../../../make_helpers/build-rules.mk
include ../../../make_helpers/common.mk
include ../../../make_helpers/toolchain.mk
@@ -82,33 +84,37 @@
# command
.PHONY: all
-all: $(OUTPUT_FILE_SA0) $(OUTPUT_FILE_SA6)
+
+all: $(FILE_NAME_SA0).srec $(FILE_NAME_SA0).bin
+all: $(FILE_NAME_SA6).srec $(FILE_NAME_SA6).bin
+
###################################################
# Linker
###################################################
-$(OUTPUT_FILE_SA0) : $(MEMORY_DEF_SA0) $(OBJ_FILE_SA0)
- $(aarch64-ld) $(OBJ_FILE_SA0) -nostdlib \
- -T $(MEMORY_DEF_SA0) \
- -o $(OUTPUT_FILE_SA0) \
- -Wl,-Map $(FILE_NAME_SA0).map \
+
+$(FILE_NAME_SA0).srec: $(OUTPUT_FILE_SA0) | $$(@D)/
+ $(aarch64-oc) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).srec
- $(aarch64-oc) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).srec
- $(aarch64-oc) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).bin
+$(FILE_NAME_SA0).bin: $(OUTPUT_FILE_SA0) | $$(@D)/
+ $(aarch64-oc) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).bin
-$(OUTPUT_FILE_SA6) : $(MEMORY_DEF_SA6) $(OBJ_FILE_SA6)
- $(aarch64-ld) $(OBJ_FILE_SA6) -nostdlib \
- -T $(MEMORY_DEF_SA6) \
- -o $(OUTPUT_FILE_SA6) \
- -Wl,-Map $(FILE_NAME_SA6).map \
+$(OUTPUT_FILE_SA0): $(MEMORY_DEF_SA0) $(OBJ_FILE_SA0) | $$(@D)/
+ $(aarch64-ld) $(OBJ_FILE_SA0) -nostdlib -T $(MEMORY_DEF_SA0) -o $(OUTPUT_FILE_SA0) -Wl,-Map $(FILE_NAME_SA0).map
- $(aarch64-oc) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).srec
- $(aarch64-oc) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).bin
+$(FILE_NAME_SA6).srec: $(OUTPUT_FILE_SA6) | $$(@D)/
+ $(aarch64-oc) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).srec
+
+$(FILE_NAME_SA6).bin: $(OUTPUT_FILE_SA6) | $$(@D)/
+ $(aarch64-oc) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).bin
+
+$(OUTPUT_FILE_SA6): $(MEMORY_DEF_SA6) $(OBJ_FILE_SA6) | $$(@D)/
+ $(aarch64-ld) $(OBJ_FILE_SA6) -nostdlib -T $(MEMORY_DEF_SA6) -o $(OUTPUT_FILE_SA6) -Wl,-Map $(FILE_NAME_SA6).map
###################################################
# Compile
###################################################
-%.o: %.c
+%.o: %.c | $$(@D)/
$(aarch64-cc) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
.PHONY: clean
diff --git a/tools/tlc/Makefile b/tools/tlc/Makefile
new file mode 100644
index 0000000..e50b9dd
--- /dev/null
+++ b/tools/tlc/Makefile
@@ -0,0 +1,109 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+##* Variables
+SHELL := /usr/bin/env bash
+PYTHON := python
+PYTHONPATH := `pwd`
+
+#* Docker variables
+IMAGE := tlc
+VERSION := latest
+
+#* Installation
+.PHONY: dist
+dist: clean
+ poetry build
+
+.PHONY: dev-install
+dev-install:
+ poetry lock -n --no-update && poetry export --without-hashes > requirements.txt
+ poetry install -n
+ -poetry run mypy --install-types --non-interactive ./
+
+.PHONY: install
+install: dist
+ pip install dist/*.whl
+
+.PHONY: pre-commit-install
+pre-commit-install:
+ poetry run pre-commit install
+
+#* Formatters
+.PHONY: codestyle
+codestyle:
+ poetry run pyupgrade --exit-zero-even-if-changed --py38-plus **/*.py
+ poetry run isort --settings-path pyproject.toml ./
+ poetry run black --config pyproject.toml ./
+
+.PHONY: formatting
+formatting: codestyle
+
+#* Linting
+.PHONY: test
+test:
+ PYTHONPATH=$(PYTHONPATH) poetry run pytest -c pyproject.toml --cov-report=html --cov=tlc tests/
+ poetry run coverage-badge -o assets/images/coverage.svg -f
+
+.PHONY: check-codestyle
+check-codestyle:
+ poetry run isort --diff --check-only --settings-path pyproject.toml ./
+ poetry run black --diff --check --config pyproject.toml ./
+ poetry run darglint --verbosity 2 tlc tests
+
+.PHONY: mypy
+mypy:
+ poetry run mypy --config-file pyproject.toml ./
+
+.PHONY: check-safety
+check-safety:
+ poetry check
+ poetry run safety check --full-report
+ poetry run bandit -ll --recursive tlc tests
+
+.PHONY: lint
+lint: test check-codestyle mypy check-safety
+
+.PHONY: update-dev-deps
+update-dev-deps:
+ poetry add -D bandit@latest darglint@latest "isort[colors]@latest" mypy@latest pre-commit@latest pydocstyle@latest pylint@latest pytest@latest pyupgrade@latest safety@latest coverage@latest coverage-badge@latest pytest-html@latest pytest-cov@latest
+ poetry add -D --allow-prereleases black@latest
+
+#* Docker
+.PHONY: docker-build docker-remove
+docker-build:
+ @echo Building docker $(IMAGE):$(VERSION) ...
+ docker build \
+ -t $(IMAGE):$(VERSION) . \
+ -f ./docker/Dockerfile --no-cache
+
+docker-remove:
+ @echo Removing docker $(IMAGE):$(VERSION) ...
+ docker rmi -f $(IMAGE):$(VERSION)
+
+
+#* Cleaning
+.PHONY: clean .clean-build clean-pyc clean-test
+clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts
+
+clean-build: ## remove build artifacts
+ rm -fr build/
+ rm -fr dist/
+ rm -fr .eggs/
+ find . -name '*.egg-info' -exec rm -fr {} +
+ find . -name '*.egg' -exec rm -f {} +
+
+clean-pyc: ## remove Python file artifacts
+ find . -name '*.pyc' -exec rm -f {} +
+ find . -name '*.pyo' -exec rm -f {} +
+ find . -name '*~' -exec rm -f {} +
+ find . -name '__pycache__' -exec rm -fr {} +
+ find . | grep -E ".pytest_cache" | xargs rm -rf
+ find . | grep -E ".mypy_cache" | xargs rm -rf
+
+clean-test: ## remove test and coverage artifacts
+ rm -fr .tox/
+ rm -f .coverage
+ rm -fr htmlcov/
diff --git a/tools/tlc/assets/images/coverage.svg b/tools/tlc/assets/images/coverage.svg
new file mode 100644
index 0000000..b6c4e36
--- /dev/null
+++ b/tools/tlc/assets/images/coverage.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="99" height="20">
+ <linearGradient id="b" x2="0" y2="100%">
+ <stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
+ <stop offset="1" stop-opacity=".1"/>
+ </linearGradient>
+ <mask id="a">
+ <rect width="99" height="20" rx="3" fill="#fff"/>
+ </mask>
+ <g mask="url(#a)">
+ <path fill="#555" d="M0 0h63v20H0z"/>
+ <path fill="#4c1" d="M63 0h36v20H63z"/>
+ <path fill="url(#b)" d="M0 0h99v20H0z"/>
+ </g>
+ <g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
+ <text x="31.5" y="15" fill="#010101" fill-opacity=".3">coverage</text>
+ <text x="31.5" y="14">coverage</text>
+ <text x="80" y="15" fill="#010101" fill-opacity=".3">95%</text>
+ <text x="80" y="14">95%</text>
+ </g>
+</svg>
diff --git a/tools/tlc/poetry.lock b/tools/tlc/poetry.lock
new file mode 100644
index 0000000..839f236
--- /dev/null
+++ b/tools/tlc/poetry.lock
@@ -0,0 +1,1356 @@
+# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
+
+[[package]]
+name = "astroid"
+version = "2.15.8"
+description = "An abstract syntax tree for Python with inference support."
+optional = false
+python-versions = ">=3.7.2"
+files = [
+ {file = "astroid-2.15.8-py3-none-any.whl", hash = "sha256:1aa149fc5c6589e3d0ece885b4491acd80af4f087baafa3fb5203b113e68cd3c"},
+ {file = "astroid-2.15.8.tar.gz", hash = "sha256:6c107453dffee9055899705de3c9ead36e74119cee151e5a9aaf7f0b0e020a6a"},
+]
+
+[package.dependencies]
+lazy-object-proxy = ">=1.4.0"
+typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""}
+wrapt = [
+ {version = ">=1.11,<2", markers = "python_version < \"3.11\""},
+ {version = ">=1.14,<2", markers = "python_version >= \"3.11\""},
+]
+
+[[package]]
+name = "bandit"
+version = "1.7.9"
+description = "Security oriented static analyser for python code."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "bandit-1.7.9-py3-none-any.whl", hash = "sha256:52077cb339000f337fb25f7e045995c4ad01511e716e5daac37014b9752de8ec"},
+ {file = "bandit-1.7.9.tar.gz", hash = "sha256:7c395a436743018f7be0a4cbb0a4ea9b902b6d87264ddecf8cfdc73b4f78ff61"},
+]
+
+[package.dependencies]
+colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""}
+PyYAML = ">=5.3.1"
+rich = "*"
+stevedore = ">=1.20.0"
+
+[package.extras]
+baseline = ["GitPython (>=3.1.30)"]
+sarif = ["jschema-to-python (>=1.2.3)", "sarif-om (>=1.0.4)"]
+test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)"]
+toml = ["tomli (>=1.1.0)"]
+yaml = ["PyYAML"]
+
+[[package]]
+name = "black"
+version = "24.4.2"
+description = "The uncompromising code formatter."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "black-24.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce"},
+ {file = "black-24.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021"},
+ {file = "black-24.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063"},
+ {file = "black-24.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:7768a0dbf16a39aa5e9a3ded568bb545c8c2727396d063bbaf847df05b08cd96"},
+ {file = "black-24.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474"},
+ {file = "black-24.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c"},
+ {file = "black-24.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb"},
+ {file = "black-24.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1"},
+ {file = "black-24.4.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:accf49e151c8ed2c0cdc528691838afd217c50412534e876a19270fea1e28e2d"},
+ {file = "black-24.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:88c57dc656038f1ab9f92b3eb5335ee9b021412feaa46330d5eba4e51fe49b04"},
+ {file = "black-24.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be8bef99eb46d5021bf053114442914baeb3649a89dc5f3a555c88737e5e98fc"},
+ {file = "black-24.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:415e686e87dbbe6f4cd5ef0fbf764af7b89f9057b97c908742b6008cc554b9c0"},
+ {file = "black-24.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bf10f7310db693bb62692609b397e8d67257c55f949abde4c67f9cc574492cc7"},
+ {file = "black-24.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:98e123f1d5cfd42f886624d84464f7756f60ff6eab89ae845210631714f6db94"},
+ {file = "black-24.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48a85f2cb5e6799a9ef05347b476cce6c182d6c71ee36925a6c194d074336ef8"},
+ {file = "black-24.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:b1530ae42e9d6d5b670a34db49a94115a64596bc77710b1d05e9801e62ca0a7c"},
+ {file = "black-24.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:37aae07b029fa0174d39daf02748b379399b909652a806e5708199bd93899da1"},
+ {file = "black-24.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:da33a1a5e49c4122ccdfd56cd021ff1ebc4a1ec4e2d01594fef9b6f267a9e741"},
+ {file = "black-24.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e"},
+ {file = "black-24.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:b9176b9832e84308818a99a561e90aa479e73c523b3f77afd07913380ae2eab7"},
+ {file = "black-24.4.2-py3-none-any.whl", hash = "sha256:d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c"},
+ {file = "black-24.4.2.tar.gz", hash = "sha256:c872b53057f000085da66a19c55d68f6f8ddcac2642392ad3a355878406fbd4d"},
+]
+
+[package.dependencies]
+click = ">=8.0.0"
+mypy-extensions = ">=0.4.3"
+packaging = ">=22.0"
+pathspec = ">=0.9.0"
+platformdirs = ">=2"
+tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
+typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""}
+
+[package.extras]
+colorama = ["colorama (>=0.4.3)"]
+d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"]
+jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
+uvloop = ["uvloop (>=0.15.2)"]
+
+[[package]]
+name = "certifi"
+version = "2024.7.4"
+description = "Python package for providing Mozilla's CA Bundle."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"},
+ {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"},
+]
+
+[[package]]
+name = "cfgv"
+version = "3.4.0"
+description = "Validate configuration and produce human readable error messages."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"},
+ {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
+]
+
+[[package]]
+name = "charset-normalizer"
+version = "3.3.2"
+description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
+optional = false
+python-versions = ">=3.7.0"
+files = [
+ {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"},
+ {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
+]
+
+[[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 = "commonmark"
+version = "0.9.1"
+description = "Python parser for the CommonMark Markdown spec"
+optional = false
+python-versions = "*"
+files = [
+ {file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"},
+ {file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"},
+]
+
+[package.extras]
+test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"]
+
+[[package]]
+name = "coverage"
+version = "6.5.0"
+description = "Code coverage measurement for Python"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "coverage-6.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53"},
+ {file = "coverage-6.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660"},
+ {file = "coverage-6.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4"},
+ {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:83516205e254a0cb77d2d7bb3632ee019d93d9f4005de31dca0a8c3667d5bc04"},
+ {file = "coverage-6.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0"},
+ {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:97117225cdd992a9c2a5515db1f66b59db634f59d0679ca1fa3fe8da32749cae"},
+ {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a1170fa54185845505fbfa672f1c1ab175446c887cce8212c44149581cf2d466"},
+ {file = "coverage-6.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a"},
+ {file = "coverage-6.5.0-cp310-cp310-win32.whl", hash = "sha256:5dbec3b9095749390c09ab7c89d314727f18800060d8d24e87f01fb9cfb40b32"},
+ {file = "coverage-6.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:59f53f1dc5b656cafb1badd0feb428c1e7bc19b867479ff72f7a9dd9b479f10e"},
+ {file = "coverage-6.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795"},
+ {file = "coverage-6.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75"},
+ {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33a7da4376d5977fbf0a8ed91c4dffaaa8dbf0ddbf4c8eea500a2486d8bc4d7b"},
+ {file = "coverage-6.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91"},
+ {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a6b7d95969b8845250586f269e81e5dfdd8ff828ddeb8567a4a2eaa7313460c4"},
+ {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1ef221513e6f68b69ee9e159506d583d31aa3567e0ae84eaad9d6ec1107dddaa"},
+ {file = "coverage-6.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cca4435eebea7962a52bdb216dec27215d0df64cf27fc1dd538415f5d2b9da6b"},
+ {file = "coverage-6.5.0-cp311-cp311-win32.whl", hash = "sha256:98e8a10b7a314f454d9eff4216a9a94d143a7ee65018dd12442e898ee2310578"},
+ {file = "coverage-6.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:bc8ef5e043a2af066fa8cbfc6e708d58017024dc4345a1f9757b329a249f041b"},
+ {file = "coverage-6.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4433b90fae13f86fafff0b326453dd42fc9a639a0d9e4eec4d366436d1a41b6d"},
+ {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4f05d88d9a80ad3cac6244d36dd89a3c00abc16371769f1340101d3cb899fc3"},
+ {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94e2565443291bd778421856bc975d351738963071e9b8839ca1fc08b42d4bef"},
+ {file = "coverage-6.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79"},
+ {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:255758a1e3b61db372ec2736c8e2a1fdfaf563977eedbdf131de003ca5779b7d"},
+ {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:851cf4ff24062c6aec510a454b2584f6e998cada52d4cb58c5e233d07172e50c"},
+ {file = "coverage-6.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:12adf310e4aafddc58afdb04d686795f33f4d7a6fa67a7a9d4ce7d6ae24d949f"},
+ {file = "coverage-6.5.0-cp37-cp37m-win32.whl", hash = "sha256:b5604380f3415ba69de87a289a2b56687faa4fe04dbee0754bfcae433489316b"},
+ {file = "coverage-6.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4a8dbc1f0fbb2ae3de73eb0bdbb914180c7abfbf258e90b311dcd4f585d44bd2"},
+ {file = "coverage-6.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c"},
+ {file = "coverage-6.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba"},
+ {file = "coverage-6.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e"},
+ {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20c8ac5386253717e5ccc827caad43ed66fea0efe255727b1053a8154d952398"},
+ {file = "coverage-6.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b"},
+ {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dbdb91cd8c048c2b09eb17713b0c12a54fbd587d79adcebad543bc0cd9a3410b"},
+ {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:de3001a203182842a4630e7b8d1a2c7c07ec1b45d3084a83d5d227a3806f530f"},
+ {file = "coverage-6.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e07f4a4a9b41583d6eabec04f8b68076ab3cd44c20bd29332c6572dda36f372e"},
+ {file = "coverage-6.5.0-cp38-cp38-win32.whl", hash = "sha256:6d4817234349a80dbf03640cec6109cd90cba068330703fa65ddf56b60223a6d"},
+ {file = "coverage-6.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:7ccf362abd726b0410bf8911c31fbf97f09f8f1061f8c1cf03dfc4b6372848f6"},
+ {file = "coverage-6.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745"},
+ {file = "coverage-6.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc"},
+ {file = "coverage-6.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe"},
+ {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:265de0fa6778d07de30bcf4d9dc471c3dc4314a23a3c6603d356a3c9abc2dfcf"},
+ {file = "coverage-6.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5"},
+ {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7b6be138d61e458e18d8e6ddcddd36dd96215edfe5f1168de0b1b32635839b62"},
+ {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42eafe6778551cf006a7c43153af1211c3aaab658d4d66fa5fcc021613d02518"},
+ {file = "coverage-6.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:723e8130d4ecc8f56e9a611e73b31219595baa3bb252d539206f7bbbab6ffc1f"},
+ {file = "coverage-6.5.0-cp39-cp39-win32.whl", hash = "sha256:d9ecf0829c6a62b9b573c7bb6d4dcd6ba8b6f80be9ba4fc7ed50bf4ac9aecd72"},
+ {file = "coverage-6.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc2af30ed0d5ae0b1abdb4ebdce598eafd5b35397d4d75deb341a614d333d987"},
+ {file = "coverage-6.5.0-pp36.pp37.pp38-none-any.whl", hash = "sha256:1431986dac3923c5945271f169f59c45b8802a114c8f548d611f2015133df77a"},
+ {file = "coverage-6.5.0.tar.gz", hash = "sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84"},
+]
+
+[package.dependencies]
+tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
+
+[package.extras]
+toml = ["tomli"]
+
+[[package]]
+name = "coverage-badge"
+version = "1.1.1"
+description = "Generate coverage badges for Coverage.py."
+optional = false
+python-versions = "*"
+files = [
+ {file = "coverage-badge-1.1.1.tar.gz", hash = "sha256:42252df917404af6147380861228a4ace3d9a29804df8fc2d34a22b2bc4f45b6"},
+ {file = "coverage_badge-1.1.1-py2.py3-none-any.whl", hash = "sha256:1d8e566ad47c37910fa2bbc74ea19972b171b5b4e40624b31b3e2f2d93680266"},
+]
+
+[package.dependencies]
+coverage = "*"
+
+[[package]]
+name = "darglint"
+version = "1.8.1"
+description = "A utility for ensuring Google-style docstrings stay up to date with the source code."
+optional = false
+python-versions = ">=3.6,<4.0"
+files = [
+ {file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"},
+ {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"},
+]
+
+[[package]]
+name = "dill"
+version = "0.3.8"
+description = "serialize all of Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "dill-0.3.8-py3-none-any.whl", hash = "sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7"},
+ {file = "dill-0.3.8.tar.gz", hash = "sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca"},
+]
+
+[package.extras]
+graph = ["objgraph (>=1.7.2)"]
+profile = ["gprof2dot (>=2022.7.29)"]
+
+[[package]]
+name = "distlib"
+version = "0.3.8"
+description = "Distribution utilities"
+optional = false
+python-versions = "*"
+files = [
+ {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"},
+ {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"},
+]
+
+[[package]]
+name = "dparse"
+version = "0.6.3"
+description = "A parser for Python dependency files"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "dparse-0.6.3-py3-none-any.whl", hash = "sha256:0d8fe18714056ca632d98b24fbfc4e9791d4e47065285ab486182288813a5318"},
+ {file = "dparse-0.6.3.tar.gz", hash = "sha256:27bb8b4bcaefec3997697ba3f6e06b2447200ba273c0b085c3d012a04571b528"},
+]
+
+[package.dependencies]
+packaging = "*"
+tomli = {version = "*", markers = "python_version < \"3.11\""}
+
+[package.extras]
+conda = ["pyyaml"]
+pipenv = ["pipenv (<=2022.12.19)"]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.2.2"
+description = "Backport of PEP 654 (exception groups)"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"},
+ {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"},
+]
+
+[package.extras]
+test = ["pytest (>=6)"]
+
+[[package]]
+name = "filelock"
+version = "3.15.4"
+description = "A platform independent file lock."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "filelock-3.15.4-py3-none-any.whl", hash = "sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7"},
+ {file = "filelock-3.15.4.tar.gz", hash = "sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb"},
+]
+
+[package.extras]
+docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"]
+testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-asyncio (>=0.21)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)", "virtualenv (>=20.26.2)"]
+typing = ["typing-extensions (>=4.8)"]
+
+[[package]]
+name = "identify"
+version = "2.6.0"
+description = "File identification library for Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "identify-2.6.0-py2.py3-none-any.whl", hash = "sha256:e79ae4406387a9d300332b5fd366d8994f1525e8414984e1a59e058b2eda2dd0"},
+ {file = "identify-2.6.0.tar.gz", hash = "sha256:cb171c685bdc31bcc4c1734698736a7d5b6c8bf2e0c15117f4d469c8640ae5cf"},
+]
+
+[package.extras]
+license = ["ukkonen"]
+
+[[package]]
+name = "idna"
+version = "3.7"
+description = "Internationalized Domain Names in Applications (IDNA)"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"},
+ {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"},
+]
+
+[[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 = "isort"
+version = "5.13.2"
+description = "A Python utility / library to sort Python imports."
+optional = false
+python-versions = ">=3.8.0"
+files = [
+ {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"},
+ {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"},
+]
+
+[package.dependencies]
+colorama = {version = ">=0.4.6", optional = true, markers = "extra == \"colors\""}
+
+[package.extras]
+colors = ["colorama (>=0.4.6)"]
+
+[[package]]
+name = "jinja2"
+version = "3.1.4"
+description = "A very fast and expressive template engine."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"},
+ {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"},
+]
+
+[package.dependencies]
+MarkupSafe = ">=2.0"
+
+[package.extras]
+i18n = ["Babel (>=2.7)"]
+
+[[package]]
+name = "lazy-object-proxy"
+version = "1.10.0"
+description = "A fast and thorough lazy object proxy."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "lazy-object-proxy-1.10.0.tar.gz", hash = "sha256:78247b6d45f43a52ef35c25b5581459e85117225408a4128a3daf8bf9648ac69"},
+ {file = "lazy_object_proxy-1.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:855e068b0358ab916454464a884779c7ffa312b8925c6f7401e952dcf3b89977"},
+ {file = "lazy_object_proxy-1.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab7004cf2e59f7c2e4345604a3e6ea0d92ac44e1c2375527d56492014e690c3"},
+ {file = "lazy_object_proxy-1.10.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc0d2fc424e54c70c4bc06787e4072c4f3b1aa2f897dfdc34ce1013cf3ceef05"},
+ {file = "lazy_object_proxy-1.10.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e2adb09778797da09d2b5ebdbceebf7dd32e2c96f79da9052b2e87b6ea495895"},
+ {file = "lazy_object_proxy-1.10.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b1f711e2c6dcd4edd372cf5dec5c5a30d23bba06ee012093267b3376c079ec83"},
+ {file = "lazy_object_proxy-1.10.0-cp310-cp310-win32.whl", hash = "sha256:76a095cfe6045c7d0ca77db9934e8f7b71b14645f0094ffcd842349ada5c5fb9"},
+ {file = "lazy_object_proxy-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:b4f87d4ed9064b2628da63830986c3d2dca7501e6018347798313fcf028e2fd4"},
+ {file = "lazy_object_proxy-1.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fec03caabbc6b59ea4a638bee5fce7117be8e99a4103d9d5ad77f15d6f81020c"},
+ {file = "lazy_object_proxy-1.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02c83f957782cbbe8136bee26416686a6ae998c7b6191711a04da776dc9e47d4"},
+ {file = "lazy_object_proxy-1.10.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:009e6bb1f1935a62889ddc8541514b6a9e1fcf302667dcb049a0be5c8f613e56"},
+ {file = "lazy_object_proxy-1.10.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:75fc59fc450050b1b3c203c35020bc41bd2695ed692a392924c6ce180c6f1dc9"},
+ {file = "lazy_object_proxy-1.10.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:782e2c9b2aab1708ffb07d4bf377d12901d7a1d99e5e410d648d892f8967ab1f"},
+ {file = "lazy_object_proxy-1.10.0-cp311-cp311-win32.whl", hash = "sha256:edb45bb8278574710e68a6b021599a10ce730d156e5b254941754a9cc0b17d03"},
+ {file = "lazy_object_proxy-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:e271058822765ad5e3bca7f05f2ace0de58a3f4e62045a8c90a0dfd2f8ad8cc6"},
+ {file = "lazy_object_proxy-1.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e98c8af98d5707dcdecc9ab0863c0ea6e88545d42ca7c3feffb6b4d1e370c7ba"},
+ {file = "lazy_object_proxy-1.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:952c81d415b9b80ea261d2372d2a4a2332a3890c2b83e0535f263ddfe43f0d43"},
+ {file = "lazy_object_proxy-1.10.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80b39d3a151309efc8cc48675918891b865bdf742a8616a337cb0090791a0de9"},
+ {file = "lazy_object_proxy-1.10.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e221060b701e2aa2ea991542900dd13907a5c90fa80e199dbf5a03359019e7a3"},
+ {file = "lazy_object_proxy-1.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:92f09ff65ecff3108e56526f9e2481b8116c0b9e1425325e13245abfd79bdb1b"},
+ {file = "lazy_object_proxy-1.10.0-cp312-cp312-win32.whl", hash = "sha256:3ad54b9ddbe20ae9f7c1b29e52f123120772b06dbb18ec6be9101369d63a4074"},
+ {file = "lazy_object_proxy-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:127a789c75151db6af398b8972178afe6bda7d6f68730c057fbbc2e96b08d282"},
+ {file = "lazy_object_proxy-1.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9e4ed0518a14dd26092614412936920ad081a424bdcb54cc13349a8e2c6d106a"},
+ {file = "lazy_object_proxy-1.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ad9e6ed739285919aa9661a5bbed0aaf410aa60231373c5579c6b4801bd883c"},
+ {file = "lazy_object_proxy-1.10.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fc0a92c02fa1ca1e84fc60fa258458e5bf89d90a1ddaeb8ed9cc3147f417255"},
+ {file = "lazy_object_proxy-1.10.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0aefc7591920bbd360d57ea03c995cebc204b424524a5bd78406f6e1b8b2a5d8"},
+ {file = "lazy_object_proxy-1.10.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5faf03a7d8942bb4476e3b62fd0f4cf94eaf4618e304a19865abf89a35c0bbee"},
+ {file = "lazy_object_proxy-1.10.0-cp38-cp38-win32.whl", hash = "sha256:e333e2324307a7b5d86adfa835bb500ee70bfcd1447384a822e96495796b0ca4"},
+ {file = "lazy_object_proxy-1.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:cb73507defd385b7705c599a94474b1d5222a508e502553ef94114a143ec6696"},
+ {file = "lazy_object_proxy-1.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:366c32fe5355ef5fc8a232c5436f4cc66e9d3e8967c01fb2e6302fd6627e3d94"},
+ {file = "lazy_object_proxy-1.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2297f08f08a2bb0d32a4265e98a006643cd7233fb7983032bd61ac7a02956b3b"},
+ {file = "lazy_object_proxy-1.10.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18dd842b49456aaa9a7cf535b04ca4571a302ff72ed8740d06b5adcd41fe0757"},
+ {file = "lazy_object_proxy-1.10.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:217138197c170a2a74ca0e05bddcd5f1796c735c37d0eee33e43259b192aa424"},
+ {file = "lazy_object_proxy-1.10.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9a3a87cf1e133e5b1994144c12ca4aa3d9698517fe1e2ca82977781b16955658"},
+ {file = "lazy_object_proxy-1.10.0-cp39-cp39-win32.whl", hash = "sha256:30b339b2a743c5288405aa79a69e706a06e02958eab31859f7f3c04980853b70"},
+ {file = "lazy_object_proxy-1.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:a899b10e17743683b293a729d3a11f2f399e8a90c73b089e29f5d0fe3509f0dd"},
+ {file = "lazy_object_proxy-1.10.0-pp310.pp311.pp312.pp38.pp39-none-any.whl", hash = "sha256:80fa48bd89c8f2f456fc0765c11c23bf5af827febacd2f523ca5bc1893fcc09d"},
+]
+
+[[package]]
+name = "markupsafe"
+version = "2.1.5"
+description = "Safely add untrusted strings to HTML/XML markup."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"},
+ {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"},
+ {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"},
+ {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"},
+ {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"},
+ {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"},
+ {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"},
+ {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"},
+]
+
+[[package]]
+name = "mccabe"
+version = "0.7.0"
+description = "McCabe checker, plugin for flake8"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"},
+ {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"},
+]
+
+[[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 = "nodeenv"
+version = "1.9.1"
+description = "Node.js virtual environment builder"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"},
+ {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"},
+]
+
+[[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 = "pathspec"
+version = "0.12.1"
+description = "Utility library for gitignore style pattern matching of file paths."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
+ {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
+]
+
+[[package]]
+name = "pbr"
+version = "6.0.0"
+description = "Python Build Reasonableness"
+optional = false
+python-versions = ">=2.6"
+files = [
+ {file = "pbr-6.0.0-py2.py3-none-any.whl", hash = "sha256:4a7317d5e3b17a3dccb6a8cfe67dab65b20551404c52c8ed41279fa4f0cb4cda"},
+ {file = "pbr-6.0.0.tar.gz", hash = "sha256:d1377122a5a00e2f940ee482999518efe16d745d423a670c27773dfbc3c9a7d9"},
+]
+
+[[package]]
+name = "platformdirs"
+version = "4.2.2"
+description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"},
+ {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"},
+]
+
+[package.extras]
+docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"]
+test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"]
+type = ["mypy (>=1.8)"]
+
+[[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 = "pre-commit"
+version = "2.21.0"
+description = "A framework for managing and maintaining multi-language pre-commit hooks."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pre_commit-2.21.0-py2.py3-none-any.whl", hash = "sha256:e2f91727039fc39a92f58a588a25b87f936de6567eed4f0e673e0507edc75bad"},
+ {file = "pre_commit-2.21.0.tar.gz", hash = "sha256:31ef31af7e474a8d8995027fefdfcf509b5c913ff31f2015b4ec4beb26a6f658"},
+]
+
+[package.dependencies]
+cfgv = ">=2.0.0"
+identify = ">=1.0.0"
+nodeenv = ">=0.11.1"
+pyyaml = ">=5.1"
+virtualenv = ">=20.10.0"
+
+[[package]]
+name = "pydocstyle"
+version = "6.3.0"
+description = "Python docstring style checker"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019"},
+ {file = "pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1"},
+]
+
+[package.dependencies]
+snowballstemmer = ">=2.2.0"
+
+[package.extras]
+toml = ["tomli (>=1.2.3)"]
+
+[[package]]
+name = "pygments"
+version = "2.18.0"
+description = "Pygments is a syntax highlighting package written in Python."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"},
+ {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"},
+]
+
+[package.extras]
+windows-terminal = ["colorama (>=0.4.6)"]
+
+[[package]]
+name = "pylint"
+version = "2.17.7"
+description = "python code static checker"
+optional = false
+python-versions = ">=3.7.2"
+files = [
+ {file = "pylint-2.17.7-py3-none-any.whl", hash = "sha256:27a8d4c7ddc8c2f8c18aa0050148f89ffc09838142193fdbe98f172781a3ff87"},
+ {file = "pylint-2.17.7.tar.gz", hash = "sha256:f4fcac7ae74cfe36bc8451e931d8438e4a476c20314b1101c458ad0f05191fad"},
+]
+
+[package.dependencies]
+astroid = ">=2.15.8,<=2.17.0-dev0"
+colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
+dill = [
+ {version = ">=0.2", markers = "python_version < \"3.11\""},
+ {version = ">=0.3.6", markers = "python_version >= \"3.11\""},
+]
+isort = ">=4.2.5,<6"
+mccabe = ">=0.6,<0.8"
+platformdirs = ">=2.2.0"
+tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
+tomlkit = ">=0.10.1"
+typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""}
+
+[package.extras]
+spelling = ["pyenchant (>=3.2,<4.0)"]
+testutils = ["gitpython (>3)"]
+
+[[package]]
+name = "pytest"
+version = "7.4.4"
+description = "pytest: simple powerful testing with Python"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"},
+ {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
+iniconfig = "*"
+packaging = "*"
+pluggy = ">=0.12,<2.0"
+tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
+
+[package.extras]
+testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
+
+[[package]]
+name = "pytest-cov"
+version = "3.0.0"
+description = "Pytest plugin for measuring coverage."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"},
+ {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"},
+]
+
+[package.dependencies]
+coverage = {version = ">=5.2.1", extras = ["toml"]}
+pytest = ">=4.6"
+
+[package.extras]
+testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"]
+
+[[package]]
+name = "pytest-html"
+version = "4.1.1"
+description = "pytest plugin for generating HTML reports"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pytest_html-4.1.1-py3-none-any.whl", hash = "sha256:c8152cea03bd4e9bee6d525573b67bbc6622967b72b9628dda0ea3e2a0b5dd71"},
+ {file = "pytest_html-4.1.1.tar.gz", hash = "sha256:70a01e8ae5800f4a074b56a4cb1025c8f4f9b038bba5fe31e3c98eb996686f07"},
+]
+
+[package.dependencies]
+jinja2 = ">=3.0.0"
+pytest = ">=7.0.0"
+pytest-metadata = ">=2.0.0"
+
+[package.extras]
+docs = ["pip-tools (>=6.13.0)"]
+test = ["assertpy (>=1.1)", "beautifulsoup4 (>=4.11.1)", "black (>=22.1.0)", "flake8 (>=4.0.1)", "pre-commit (>=2.17.0)", "pytest-mock (>=3.7.0)", "pytest-rerunfailures (>=11.1.2)", "pytest-xdist (>=2.4.0)", "selenium (>=4.3.0)", "tox (>=3.24.5)"]
+
+[[package]]
+name = "pytest-metadata"
+version = "3.1.1"
+description = "pytest plugin for test session metadata"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pytest_metadata-3.1.1-py3-none-any.whl", hash = "sha256:c8e0844db684ee1c798cfa38908d20d67d0463ecb6137c72e91f418558dd5f4b"},
+ {file = "pytest_metadata-3.1.1.tar.gz", hash = "sha256:d2a29b0355fbc03f168aa96d41ff88b1a3b44a3b02acbe491801c98a048017c8"},
+]
+
+[package.dependencies]
+pytest = ">=7.0.0"
+
+[package.extras]
+test = ["black (>=22.1.0)", "flake8 (>=4.0.1)", "pre-commit (>=2.17.0)", "tox (>=3.24.5)"]
+
+[[package]]
+name = "pyupgrade"
+version = "2.38.4"
+description = "A tool to automatically upgrade syntax for newer versions."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pyupgrade-2.38.4-py2.py3-none-any.whl", hash = "sha256:944ff993c396ddc2b9012eb3de4cda138eb4c149b22c6c560d4c8bfd0e180982"},
+ {file = "pyupgrade-2.38.4.tar.gz", hash = "sha256:1eb43a49f416752929741ba4d706bf3f33593d3cac9bdc217fc1ef55c047c1f4"},
+]
+
+[package.dependencies]
+tokenize-rt = "<5"
+
+[[package]]
+name = "pyyaml"
+version = "6.0.1"
+description = "YAML parser and emitter for Python"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
+ {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
+ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
+ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
+ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
+ {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
+ {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
+ {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
+ {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
+ {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
+ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
+ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
+ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
+ {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
+ {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
+ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
+ {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
+ {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
+ {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
+ {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
+ {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
+ {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
+ {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"},
+ {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"},
+ {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"},
+ {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"},
+ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
+ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
+ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
+ {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
+ {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
+ {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
+ {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
+ {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"},
+ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
+ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
+ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
+ {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
+ {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
+ {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
+ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
+]
+
+[[package]]
+name = "requests"
+version = "2.32.3"
+description = "Python HTTP for Humans."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
+ {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
+]
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+charset-normalizer = ">=2,<4"
+idna = ">=2.5,<4"
+urllib3 = ">=1.21.1,<3"
+
+[package.extras]
+socks = ["PySocks (>=1.5.6,!=1.5.7)"]
+use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
+
+[[package]]
+name = "rich"
+version = "10.16.2"
+description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
+optional = false
+python-versions = ">=3.6.2,<4.0.0"
+files = [
+ {file = "rich-10.16.2-py3-none-any.whl", hash = "sha256:c59d73bd804c90f747c8d7b1d023b88f2a9ac2454224a4aeaf959b21eeb42d03"},
+ {file = "rich-10.16.2.tar.gz", hash = "sha256:720974689960e06c2efdb54327f8bf0cdbdf4eae4ad73b6c94213cad405c371b"},
+]
+
+[package.dependencies]
+colorama = ">=0.4.0,<0.5.0"
+commonmark = ">=0.9.0,<0.10.0"
+pygments = ">=2.6.0,<3.0.0"
+
+[package.extras]
+jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"]
+
+[[package]]
+name = "ruamel-yaml"
+version = "0.18.6"
+description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "ruamel.yaml-0.18.6-py3-none-any.whl", hash = "sha256:57b53ba33def16c4f3d807c0ccbc00f8a6081827e81ba2491691b76882d0c636"},
+ {file = "ruamel.yaml-0.18.6.tar.gz", hash = "sha256:8b27e6a217e786c6fbe5634d8f3f11bc63e0f80f6a5890f28863d9c45aac311b"},
+]
+
+[package.dependencies]
+"ruamel.yaml.clib" = {version = ">=0.2.7", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.13\""}
+
+[package.extras]
+docs = ["mercurial (>5.7)", "ryd"]
+jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"]
+
+[[package]]
+name = "ruamel-yaml-clib"
+version = "0.2.8"
+description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b42169467c42b692c19cf539c38d4602069d8c1505e97b86387fcf7afb766e1d"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:07238db9cbdf8fc1e9de2489a4f68474e70dffcb32232db7c08fa61ca0c7c462"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fff3573c2db359f091e1589c3d7c5fc2f86f5bdb6f24252c2d8e539d4e45f412"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:aa2267c6a303eb483de8d02db2871afb5c5fc15618d894300b88958f729ad74f"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:840f0c7f194986a63d2c2465ca63af8ccbbc90ab1c6001b1978f05119b5e7334"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:024cfe1fc7c7f4e1aff4a81e718109e13409767e4f871443cbff3dba3578203d"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win32.whl", hash = "sha256:c69212f63169ec1cfc9bb44723bf2917cbbd8f6191a00ef3410f5a7fe300722d"},
+ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win_amd64.whl", hash = "sha256:cabddb8d8ead485e255fe80429f833172b4cadf99274db39abc080e068cbcc31"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bef08cd86169d9eafb3ccb0a39edb11d8e25f3dae2b28f5c52fd997521133069"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:b16420e621d26fdfa949a8b4b47ade8810c56002f5389970db4ddda51dbff248"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:25c515e350e5b739842fc3228d662413ef28f295791af5e5110b543cf0b57d9b"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_24_aarch64.whl", hash = "sha256:1707814f0d9791df063f8c19bb51b0d1278b8e9a2353abbb676c2f685dee6afe"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:46d378daaac94f454b3a0e3d8d78cafd78a026b1d71443f4966c696b48a6d899"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:09b055c05697b38ecacb7ac50bdab2240bfca1a0c4872b0fd309bb07dc9aa3a9"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win32.whl", hash = "sha256:53a300ed9cea38cf5a2a9b069058137c2ca1ce658a874b79baceb8f892f915a7"},
+ {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win_amd64.whl", hash = "sha256:c2a72e9109ea74e511e29032f3b670835f8a59bbdc9ce692c5b4ed91ccf1eedb"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ebc06178e8821efc9692ea7544aa5644217358490145629914d8020042c24aa1"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:edaef1c1200c4b4cb914583150dcaa3bc30e592e907c01117c08b13a07255ec2"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d176b57452ab5b7028ac47e7b3cf644bcfdc8cacfecf7e71759f7f51a59e5c92"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_24_aarch64.whl", hash = "sha256:1dc67314e7e1086c9fdf2680b7b6c2be1c0d8e3a8279f2e993ca2a7545fecf62"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3213ece08ea033eb159ac52ae052a4899b56ecc124bb80020d9bbceeb50258e9"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aab7fd643f71d7946f2ee58cc88c9b7bfc97debd71dcc93e03e2d174628e7e2d"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win32.whl", hash = "sha256:5c365d91c88390c8d0a8545df0b5857172824b1c604e867161e6b3d59a827eaa"},
+ {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win_amd64.whl", hash = "sha256:1758ce7d8e1a29d23de54a16ae867abd370f01b5a69e1a3ba75223eaa3ca1a1b"},
+ {file = "ruamel.yaml.clib-0.2.8-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a5aa27bad2bb83670b71683aae140a1f52b0857a2deff56ad3f6c13a017a26ed"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c58ecd827313af6864893e7af0a3bb85fd529f862b6adbefe14643947cfe2942"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f481f16baec5290e45aebdc2a5168ebc6d35189ae6fea7a58787613a25f6e875"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:77159f5d5b5c14f7c34073862a6b7d34944075d9f93e681638f6d753606c6ce6"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7f67a1ee819dc4562d444bbafb135832b0b909f81cc90f7aa00260968c9ca1b3"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4ecbf9c3e19f9562c7fdd462e8d18dd902a47ca046a2e64dba80699f0b6c09b7"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:87ea5ff66d8064301a154b3933ae406b0863402a799b16e4a1d24d9fbbcbe0d3"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win32.whl", hash = "sha256:75e1ed13e1f9de23c5607fe6bd1aeaae21e523b32d83bb33918245361e9cc51b"},
+ {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win_amd64.whl", hash = "sha256:3f215c5daf6a9d7bbed4a0a4f760f3113b10e82ff4c5c44bec20a68c8014f675"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1b617618914cb00bf5c34d4357c37aa15183fa229b24767259657746c9077615"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:a6a9ffd280b71ad062eae53ac1659ad86a17f59a0fdc7699fd9be40525153337"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:305889baa4043a09e5b76f8e2a51d4ffba44259f6b4c72dec8ca56207d9c6fe1"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:700e4ebb569e59e16a976857c8798aee258dceac7c7d6b50cab63e080058df91"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e2b4c44b60eadec492926a7270abb100ef9f72798e18743939bdbf037aab8c28"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e79e5db08739731b0ce4850bed599235d601701d5694c36570a99a0c5ca41a9d"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win32.whl", hash = "sha256:955eae71ac26c1ab35924203fda6220f84dce57d6d7884f189743e2abe3a9fbe"},
+ {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win_amd64.whl", hash = "sha256:56f4252222c067b4ce51ae12cbac231bce32aee1d33fbfc9d17e5b8d6966c312"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03d1162b6d1df1caa3a4bd27aa51ce17c9afc2046c31b0ad60a0a96ec22f8001"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba64af9fa9cebe325a62fa398760f5c7206b215201b0ec825005f1b18b9bccf"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:a1a45e0bb052edf6a1d3a93baef85319733a888363938e1fc9924cb00c8df24c"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:da09ad1c359a728e112d60116f626cc9f29730ff3e0e7db72b9a2dbc2e4beed5"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:184565012b60405d93838167f425713180b949e9d8dd0bbc7b49f074407c5a8b"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a75879bacf2c987c003368cf14bed0ffe99e8e85acfa6c0bfffc21a090f16880"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win32.whl", hash = "sha256:84b554931e932c46f94ab306913ad7e11bba988104c5cff26d90d03f68258cd5"},
+ {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win_amd64.whl", hash = "sha256:25ac8c08322002b06fa1d49d1646181f0b2c72f5cbc15a85e80b4c30a544bb15"},
+ {file = "ruamel.yaml.clib-0.2.8.tar.gz", hash = "sha256:beb2e0404003de9a4cab9753a8805a8fe9320ee6673136ed7f04255fe60bb512"},
+]
+
+[[package]]
+name = "safety"
+version = "2.3.4"
+description = "Checks installed dependencies for known vulnerabilities and licenses."
+optional = false
+python-versions = "*"
+files = [
+ {file = "safety-2.3.4-py3-none-any.whl", hash = "sha256:6224dcd9b20986a2b2c5e7acfdfba6bca42bb11b2783b24ed04f32317e5167ea"},
+ {file = "safety-2.3.4.tar.gz", hash = "sha256:b9e74e794e82f54d11f4091c5d820c4d2d81de9f953bf0b4f33ac8bc402ae72c"},
+]
+
+[package.dependencies]
+Click = ">=8.0.2"
+dparse = ">=0.6.2"
+packaging = ">=21.0"
+requests = "*"
+"ruamel.yaml" = ">=0.17.21"
+setuptools = ">=19.3"
+
+[package.extras]
+github = ["jinja2 (>=3.1.0)", "pygithub (>=1.43.3)"]
+gitlab = ["python-gitlab (>=1.3.0)"]
+
+[[package]]
+name = "setuptools"
+version = "72.1.0"
+description = "Easily download, build, install, upgrade, and uninstall Python packages"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "setuptools-72.1.0-py3-none-any.whl", hash = "sha256:5a03e1860cf56bb6ef48ce186b0e557fdba433237481a9a625176c2831be15d1"},
+ {file = "setuptools-72.1.0.tar.gz", hash = "sha256:8d243eff56d095e5817f796ede6ae32941278f542e0f941867cc05ae52b162ec"},
+]
+
+[package.extras]
+core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "ordered-set (>=3.1.1)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
+doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
+test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.11.*)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (<0.4)", "pytest-ruff (>=0.2.1)", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
+
+[[package]]
+name = "shellingham"
+version = "1.5.4"
+description = "Tool to Detect Surrounding Shell"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"},
+ {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"},
+]
+
+[[package]]
+name = "snowballstemmer"
+version = "2.2.0"
+description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms."
+optional = false
+python-versions = "*"
+files = [
+ {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"},
+ {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"},
+]
+
+[[package]]
+name = "stevedore"
+version = "5.2.0"
+description = "Manage dynamic plugins for Python applications"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "stevedore-5.2.0-py3-none-any.whl", hash = "sha256:1c15d95766ca0569cad14cb6272d4d31dae66b011a929d7c18219c176ea1b5c9"},
+ {file = "stevedore-5.2.0.tar.gz", hash = "sha256:46b93ca40e1114cea93d738a6c1e365396981bb6bb78c27045b7587c9473544d"},
+]
+
+[package.dependencies]
+pbr = ">=2.0.0,<2.1.0 || >2.1.0"
+
+[[package]]
+name = "tokenize-rt"
+version = "4.2.1"
+description = "A wrapper around the stdlib `tokenize` which roundtrips."
+optional = false
+python-versions = ">=3.6.1"
+files = [
+ {file = "tokenize_rt-4.2.1-py2.py3-none-any.whl", hash = "sha256:08a27fa032a81cf45e8858d0ac706004fcd523e8463415ddf1442be38e204ea8"},
+ {file = "tokenize_rt-4.2.1.tar.gz", hash = "sha256:0d4f69026fed520f8a1e0103aa36c406ef4661417f20ca643f913e33531b3b94"},
+]
+
+[[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 = "tomli"
+version = "2.0.1"
+description = "A lil' TOML parser"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
+ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
+]
+
+[[package]]
+name = "tomlkit"
+version = "0.13.0"
+description = "Style preserving TOML library"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "tomlkit-0.13.0-py3-none-any.whl", hash = "sha256:7075d3042d03b80f603482d69bf0c8f345c2b30e41699fd8883227f89972b264"},
+ {file = "tomlkit-0.13.0.tar.gz", hash = "sha256:08ad192699734149f5b97b45f1f18dad7eb1b6d16bc72ad0c2335772650d7b72"},
+]
+
+[[package]]
+name = "typer"
+version = "0.4.2"
+description = "Typer, build great CLIs. Easy to code. Based on Python type hints."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "typer-0.4.2-py3-none-any.whl", hash = "sha256:023bae00d1baf358a6cc7cea45851639360bb716de687b42b0a4641cd99173f1"},
+ {file = "typer-0.4.2.tar.gz", hash = "sha256:b8261c6c0152dd73478b5ba96ba677e5d6948c715c310f7c91079f311f62ec03"},
+]
+
+[package.dependencies]
+click = ">=7.1.1,<9.0.0"
+colorama = {version = ">=0.4.3,<0.5.0", optional = true, markers = "extra == \"all\""}
+shellingham = {version = ">=1.3.0,<2.0.0", optional = true, markers = "extra == \"all\""}
+
+[package.extras]
+all = ["colorama (>=0.4.3,<0.5.0)", "shellingham (>=1.3.0,<2.0.0)"]
+dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"]
+doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)"]
+test = ["black (>=22.3.0,<23.0.0)", "coverage (>=5.2,<6.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<5.4.0)", "pytest-cov (>=2.10.0,<3.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<2.0.0)", "shellingham (>=1.3.0,<2.0.0)"]
+
+[[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"},
+]
+
+[[package]]
+name = "urllib3"
+version = "2.2.2"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"},
+ {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"},
+]
+
+[package.extras]
+brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
+h2 = ["h2 (>=4,<5)"]
+socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
+zstd = ["zstandard (>=0.18.0)"]
+
+[[package]]
+name = "virtualenv"
+version = "20.26.3"
+description = "Virtual Python Environment builder"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "virtualenv-20.26.3-py3-none-any.whl", hash = "sha256:8cc4a31139e796e9a7de2cd5cf2489de1217193116a8fd42328f1bd65f434589"},
+ {file = "virtualenv-20.26.3.tar.gz", hash = "sha256:4c43a2a236279d9ea36a0d76f98d84bd6ca94ac4e0f4a3b9d46d05e10fea542a"},
+]
+
+[package.dependencies]
+distlib = ">=0.3.7,<1"
+filelock = ">=3.12.2,<4"
+platformdirs = ">=3.9.1,<5"
+
+[package.extras]
+docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
+test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"]
+
+[[package]]
+name = "wrapt"
+version = "1.16.0"
+description = "Module for decorators, wrappers and monkey patching."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"},
+ {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"},
+ {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"},
+ {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"},
+ {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"},
+ {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"},
+ {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"},
+ {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"},
+ {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"},
+ {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"},
+ {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"},
+ {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"},
+ {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"},
+ {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"},
+ {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"},
+ {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"},
+ {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"},
+ {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"},
+ {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"},
+ {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"},
+ {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"},
+ {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"},
+ {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"},
+ {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"},
+ {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"},
+ {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"},
+ {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"},
+ {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"},
+ {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"},
+ {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"},
+ {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"},
+ {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"},
+ {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"},
+ {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"},
+ {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"},
+ {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"},
+ {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"},
+ {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"},
+ {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"},
+ {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"},
+ {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"},
+ {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"},
+ {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"},
+ {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"},
+ {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"},
+ {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"},
+ {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"},
+ {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"},
+ {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"},
+ {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"},
+ {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"},
+ {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"},
+ {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"},
+ {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"},
+ {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"},
+ {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"},
+ {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"},
+ {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"},
+ {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"},
+ {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"},
+ {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"},
+ {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"},
+ {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"},
+ {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"},
+ {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"},
+ {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"},
+ {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"},
+ {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"},
+ {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"},
+ {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"},
+]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.8"
+content-hash = "cfcb196cda412f6139302937640455aa8154d7979c69017fe45ddd528e4a1bf2"
diff --git a/tools/tlc/pyproject.toml b/tools/tlc/pyproject.toml
new file mode 100644
index 0000000..5661abf
--- /dev/null
+++ b/tools/tlc/pyproject.toml
@@ -0,0 +1,147 @@
+# 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 = "tlc"
+version = "0.9.0"
+description = "Transfer List Compiler (TLC) is a Python-based CLI for efficiently handling transfer lists."
+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"
+
+# Keywords description https://python-poetry.org/docs/pyproject/#keywords
+keywords = [] #! Update me
+
+# 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.scripts]
+# Entry points for the package https://python-poetry.org/docs/pyproject/#scripts
+"tlc" = "tlc.__main__:cli"
+
+[tool.poetry.dependencies]
+python = "^3.8"
+
+typer = {extras = ["all"], version = "^0.4.0"}
+rich = "^10.14.0"
+click = "^8.1.7"
+pyyaml = "^6.0.1"
+
+[tool.poetry.dev-dependencies]
+bandit = "^1.7.1"
+darglint = "^1.8.1"
+black = "^24.4.2"
+isort = {extras = ["colors"], version = "^5.10.1"}
+mypy = "^0.910"
+mypy-extensions = "^0.4.3"
+pre-commit = "^2.15.0"
+pydocstyle = "^6.1.1"
+pylint = "^2.11.1"
+pytest = "^7.0.0"
+pyupgrade = "^2.29.1"
+safety = "^2.2.0"
+coverage = "^6.1.2"
+coverage-badge = "^1.1.0"
+pytest-html = "^4.1.1"
+pytest-cov = "^3.0.0"
+
+[tool.black]
+# https://github.com/psf/black
+target-version = ["py38"]
+line-length = 88
+color = true
+
+exclude = '''
+/(
+ \.git
+ | \.hg
+ | \.mypy_cache
+ | \.tox
+ | \.venv
+ | _build
+ | buck-out
+ | build
+ | dist
+ | env
+ | venv
+)/
+'''
+
+[tool.isort]
+# https://github.com/timothycrosley/isort/
+py_version = 38
+line_length = 88
+
+known_typing = ["typing", "types", "typing_extensions", "mypy", "mypy_extensions"]
+sections = ["FUTURE", "TYPING", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"]
+include_trailing_comma = true
+profile = "black"
+multi_line_output = 3
+indent = 4
+color_output = true
+
+[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
+
+allow_redefinition = false
+check_untyped_defs = true
+disallow_any_generics = true
+disallow_incomplete_defs = true
+ignore_missing_imports = true
+implicit_reexport = false
+no_implicit_optional = true
+show_column_numbers = true
+show_error_codes = true
+show_error_context = true
+strict_equality = true
+strict_optional = true
+warn_no_return = true
+warn_redundant_casts = true
+warn_return_any = true
+warn_unreachable = true
+warn_unused_configs = true
+warn_unused_ignores = true
+
+
+[tool.pytest.ini_options]
+# https://docs.pytest.org/en/6.2.x/customize.html#pyproject-toml
+# Directories that are not visited by pytest collector:
+norecursedirs =["hooks", "*.egg", ".eggs", "dist", "build", "docs", ".tox", ".git", "__pycache__"]
+doctest_optionflags = ["NUMBER", "NORMALIZE_WHITESPACE", "IGNORE_EXCEPTION_DETAIL"]
+
+# Extra options:
+addopts = [
+ "--strict-markers",
+ "--tb=short",
+ "--doctest-modules",
+ "--doctest-continue-on-failure",
+]
+
+[tool.coverage.run]
+source = ["tests"]
+
+[coverage.paths]
+source = "tlc"
+
+[coverage.run]
+branch = true
+
+[coverage.report]
+fail_under = 50
+show_missing = true
diff --git a/tools/tlc/setup.cfg b/tools/tlc/setup.cfg
new file mode 100644
index 0000000..3c46a08
--- /dev/null
+++ b/tools/tlc/setup.cfg
@@ -0,0 +1,4 @@
+[darglint]
+# https://github.com/terrencepreilly/darglint
+strictness = long
+docstring_style = google
diff --git a/tools/tlc/tests/conftest.py b/tools/tlc/tests/conftest.py
new file mode 100644
index 0000000..b8f88b5
--- /dev/null
+++ b/tools/tlc/tests/conftest.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python3
+# type: ignore[attr-defined]
+
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+""" Common configurations and fixtures for test environment."""
+
+import pytest
+import yaml
+from click.testing import CliRunner
+
+from tlc.cli import cli
+
+
+@pytest.fixture
+def tmptlstr(tmpdir):
+ return tmpdir.join("tl.bin").strpath
+
+
+@pytest.fixture
+def tmpyamlconfig(tmpdir):
+ return tmpdir.join("config.yaml").strpath
+
+
+@pytest.fixture
+def tmpfdt(tmpdir):
+ fdt = tmpdir.join("fdt.dtb")
+ fdt.write_binary(b"\x00" * 100)
+ return fdt
+
+
+@pytest.fixture(params=[1, 2, 3, 4, 5, 0x100, 0x101, 0x102, 0x104])
+def non_empty_tag_id(request):
+ return request.param
+
+
+@pytest.fixture
+def tmpyamlconfig_blob_file(tmpdir, tmpfdt, non_empty_tag_id):
+ config_path = tmpdir.join("config.yaml")
+
+ config = {
+ "has_checksum": True,
+ "max_size": 0x1000,
+ "entries": [
+ {
+ "tag_id": non_empty_tag_id,
+ "blob_file_path": tmpfdt.strpath,
+ },
+ ],
+ }
+
+ with open(config_path, "w") as f:
+ yaml.safe_dump(config, f)
+
+ return config_path
+
+
+@pytest.fixture
+def tlcrunner(tmptlstr):
+ runner = CliRunner()
+ with runner.isolated_filesystem():
+ runner.invoke(cli, ["create", tmptlstr])
+ return runner
+
+
+@pytest.fixture
+def tlc_entries(tmpfdt):
+ return [(0, "/dev/null"), (1, tmpfdt.strpath), (0x102, tmpfdt.strpath)]
diff --git a/tools/tlc/tests/test_cli.py b/tools/tlc/tests/test_cli.py
new file mode 100644
index 0000000..99b5816
--- /dev/null
+++ b/tools/tlc/tests/test_cli.py
@@ -0,0 +1,413 @@
+#!/usr/bin/env python3
+# type: ignore[attr-defined]
+
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+"""Contains unit tests for the CLI functionality."""
+
+from pathlib import Path
+from unittest import mock
+from math import log2, ceil
+
+import pytest
+import pytest
+import yaml
+from click.testing import CliRunner
+
+from tlc.cli import cli
+from tlc.te import TransferEntry
+from tlc.tl import TransferList
+
+
+def test_create_empty_tl(tmpdir):
+ runner = CliRunner()
+ test_file = tmpdir.join("tl.bin")
+
+ result = runner.invoke(cli, ["create", test_file.strpath])
+ assert result.exit_code == 0
+ assert TransferList.fromfile(test_file) is not None
+
+
+def test_create_with_fdt(tmpdir):
+ runner = CliRunner()
+ fdt = tmpdir.join("fdt.dtb")
+ fdt.write_binary(b"\x00" * 100)
+
+ result = runner.invoke(
+ cli,
+ [
+ "create",
+ "--fdt",
+ fdt.strpath,
+ "--size",
+ "1000",
+ tmpdir.join("tl.bin").strpath,
+ ],
+ )
+ assert result.exit_code == 0
+
+
+def test_add_single_entry(tlcrunner, tmptlstr):
+ tlcrunner.invoke(cli, ["add", "--entry", "0", "/dev/null", tmptlstr])
+
+ tl = TransferList.fromfile(tmptlstr)
+ assert tl is not None
+ assert len(tl.entries) == 1
+ assert tl.entries[0].id == 0
+
+
+def test_add_multiple_entries(tlcrunner, tlc_entries, tmptlstr):
+ for id, path in tlc_entries:
+ tlcrunner.invoke(cli, ["add", "--entry", id, path, tmptlstr])
+
+ tl = TransferList.fromfile(tmptlstr)
+ assert tl is not None
+ assert len(tl.entries) == len(tlc_entries)
+
+
+def test_info(tlcrunner, tmptlstr, tmpfdt):
+ tlcrunner.invoke(cli, ["add", "--entry", "0", "/dev/null", tmptlstr])
+ tlcrunner.invoke(cli, ["add", "--fdt", tmpfdt.strpath, tmptlstr])
+
+ result = tlcrunner.invoke(cli, ["info", tmptlstr])
+ assert result.exit_code == 0
+ assert "signature" in result.stdout
+ assert "id" in result.stdout
+
+ result = tlcrunner.invoke(cli, ["info", "--header", tmptlstr])
+ assert result.exit_code == 0
+ assert "signature" in result.stdout
+ assert "id" not in result.stdout
+
+ result = tlcrunner.invoke(cli, ["info", "--entries", tmptlstr])
+ assert result.exit_code == 0
+ assert "signature" not in result.stdout
+ assert "id" in result.stdout
+
+
+def test_raises_max_size_error(tmptlstr, tmpfdt):
+ tmpfdt.write_binary(bytes(6000))
+
+ runner = CliRunner()
+ result = runner.invoke(cli, ["create", "--fdt", tmpfdt, tmptlstr])
+
+ assert result.exception
+ assert isinstance(result.exception, MemoryError)
+ assert "TL max size exceeded, consider increasing with the option -s" in str(
+ result.exception
+ )
+ assert "TL size has exceeded the maximum allocation" in str(
+ result.exception.__cause__
+ )
+
+
+def test_info_get_fdt_offset(tmptlstr, tmpfdt):
+ runner = CliRunner()
+ with runner.isolated_filesystem():
+ runner.invoke(cli, ["create", "--size", "1000", tmptlstr])
+ runner.invoke(cli, ["add", "--entry", "1", tmpfdt.strpath, tmptlstr])
+ result = runner.invoke(cli, ["info", "--fdt-offset", tmptlstr])
+
+ assert result.exit_code == 0
+ assert result.output.strip("\n").isdigit()
+
+
+def test_remove_tag(tlcrunner, tmptlstr):
+ tlcrunner.invoke(cli, ["add", "--entry", "0", "/dev/null", tmptlstr])
+ result = tlcrunner.invoke(cli, ["info", tmptlstr])
+
+ assert result.exit_code == 0
+ assert "signature" in result.stdout
+
+ tlcrunner.invoke(cli, ["remove", "--tags", "0", tmptlstr])
+ tl = TransferList.fromfile(tmptlstr)
+
+ assert result.exit_code == 0
+ assert len(tl.entries) == 0
+
+
+def test_unpack_tl(tlcrunner, tmptlstr, tmpfdt, tmpdir):
+ with tlcrunner.isolated_filesystem(temp_dir=tmpdir):
+ tlcrunner.invoke(cli, ["add", "--entry", 1, tmpfdt.strpath, tmptlstr])
+ tlcrunner.invoke(cli, ["unpack", tmptlstr])
+ assert Path("te_0_1.bin").exists()
+
+
+def test_unpack_multiple_tes(tlcrunner, tlc_entries, tmptlstr, tmpdir):
+ with tlcrunner.isolated_filesystem(temp_dir=tmpdir):
+ for id, path in tlc_entries:
+ tlcrunner.invoke(cli, ["add", "--entry", id, path, tmptlstr])
+
+ assert all(
+ filter(
+ lambda te: (Path(tmpdir.strpath) / f"te_{te[0]}.bin").exists(), tlc_entries
+ )
+ )
+
+
+def test_unpack_into_dir(tlcrunner, tmpdir, tmptlstr, tmpfdt):
+ tlcrunner.invoke(cli, ["add", "--entry", 1, tmpfdt.strpath, tmptlstr])
+ tlcrunner.invoke(cli, ["unpack", "-C", tmpdir.strpath, tmptlstr])
+
+ assert (Path(tmpdir.strpath) / "te_0_1.bin").exists()
+
+
+def test_unpack_into_dir_with_conflicting_tags(tlcrunner, tmpdir, tmptlstr, tmpfdt):
+ tlcrunner.invoke(cli, ["add", "--entry", 1, tmpfdt.strpath, tmptlstr])
+ tlcrunner.invoke(cli, ["add", "--entry", 1, tmpfdt.strpath, tmptlstr])
+ tlcrunner.invoke(cli, ["unpack", "-C", tmpdir.strpath, tmptlstr])
+
+ assert (Path(tmpdir.strpath) / "te_0_1.bin").exists()
+ assert (Path(tmpdir.strpath) / "te_1_1.bin").exists()
+
+
+def test_validate_invalid_signature(tmptlstr, tlcrunner, monkeypatch):
+ tl = TransferList()
+ tl.signature = 0xDEADBEEF
+
+ mock_open = lambda tmptlstr, mode: mock.mock_open(read_data=tl.header_to_bytes())()
+ monkeypatch.setattr("builtins.open", mock_open)
+
+ result = tlcrunner.invoke(cli, ["validate", tmptlstr])
+ assert result.exit_code != 0
+
+
+def test_validate_misaligned_entries(tmptlstr, tlcrunner, monkeypatch):
+ """Base address of a TE must be 8-byte aligned."""
+ mock_open = lambda tmptlstr, mode: mock.mock_open(
+ read_data=TransferList().header_to_bytes()
+ + bytes(5)
+ + TransferEntry(0, 0, bytes(0)).header_to_bytes
+ )()
+ monkeypatch.setattr("builtins.open", mock_open)
+
+ result = tlcrunner.invoke(cli, ["validate", tmptlstr])
+
+ assert result.exit_code == 1
+
+
+@pytest.mark.parametrize(
+ "version", [0, TransferList.version, TransferList.version + 1, 1 << 8]
+)
+def test_validate_unsupported_version(version, tmptlstr, tlcrunner, monkeypatch):
+ tl = TransferList()
+ tl.version = version
+
+ mock_open = lambda tmptlstr, mode: mock.mock_open(read_data=tl.header_to_bytes())()
+ monkeypatch.setattr("builtins.open", mock_open)
+
+ result = tlcrunner.invoke(cli, ["validate", tmptlstr])
+
+ if version >= TransferList.version and version <= 0xFF:
+ assert result.exit_code == 0
+ else:
+ assert result.exit_code == 1
+
+
+def test_create_entry_from_yaml_and_blob_file(
+ tlcrunner, tmpyamlconfig_blob_file, tmptlstr, non_empty_tag_id
+):
+ tlcrunner.invoke(
+ cli,
+ [
+ "create",
+ "--from-yaml",
+ tmpyamlconfig_blob_file.strpath,
+ tmptlstr,
+ ],
+ )
+
+ tl = TransferList.fromfile(tmptlstr)
+ assert tl is not None
+ assert len(tl.entries) == 1
+ assert tl.entries[0].id == non_empty_tag_id
+
+
+@pytest.mark.parametrize(
+ "entry",
+ [
+ {"tag_id": 0},
+ {
+ "tag_id": 0x104,
+ "addr": 0x0400100000000010,
+ "size": 0x0003300000000000,
+ },
+ {
+ "tag_id": 0x100,
+ "pp_addr": 100,
+ },
+ {
+ "tag_id": "optee_pageable_part",
+ "pp_addr": 100,
+ },
+ ],
+)
+def test_create_from_yaml_check_sum_bytes(tlcrunner, tmpyamlconfig, tmptlstr, entry):
+ """Test creating a TL from a yaml file, but only check that the sum of the
+ data in the yaml file matches the sum of the data in the TL. This means
+ you don't have to type the exact sequence of expected bytes. All the data
+ in the yaml file must be integers (except for the tag IDs, which can be
+ strings).
+ """
+ # create yaml config file
+ config = {
+ "has_checksum": True,
+ "max_size": 0x1000,
+ "entries": [entry],
+ }
+ with open(tmpyamlconfig, "w") as f:
+ yaml.safe_dump(config, f)
+
+ # invoke TLC
+ tlcrunner.invoke(
+ cli,
+ [
+ "create",
+ "--from-yaml",
+ tmpyamlconfig,
+ tmptlstr,
+ ],
+ )
+
+ # open created TL, and check
+ tl = TransferList.fromfile(tmptlstr)
+ assert tl is not None
+ assert len(tl.entries) == 1
+
+ # Check that the sum of all the data in the transfer entry in the yaml file
+ # is the same as the sum of all the data in the transfer list. Don't count
+ # the tag id or the TE headers.
+
+ # every item in the entry dict must be an integer
+ yaml_total = 0
+ for key, data in iter_nested_dict(entry):
+ if key != "tag_id":
+ num_bytes = ceil(log2(data + 1) / 8)
+ yaml_total += sum(data.to_bytes(num_bytes, "little"))
+
+ tl_total = sum(tl.entries[0].data)
+
+ assert tl_total == yaml_total
+
+
+@pytest.mark.parametrize(
+ "entry,expected",
+ [
+ (
+ {
+ "tag_id": 0x102,
+ "ep_info": {
+ "h": {
+ "type": 0x01,
+ "version": 0x02,
+ "attr": 8,
+ },
+ "pc": 67239936,
+ "spsr": 965,
+ "args": [67112976, 67112960, 0, 0, 0, 0, 0, 0],
+ },
+ },
+ (
+ "0x00580201 0x00000008 0x04020000 0x00000000 "
+ "0x000003C5 0x00000000 0x04001010 0x00000000 "
+ "0x04001000 0x00000000 0x00000000 0x00000000 "
+ "0x00000000 0x00000000 0x00000000 0x00000000 "
+ "0x00000000 0x00000000 0x00000000 0x00000000 "
+ "0x00000000 0x00000000"
+ ),
+ ),
+ (
+ {
+ "tag_id": 0x102,
+ "ep_info": {
+ "h": {
+ "type": 0x01,
+ "version": 0x02,
+ "attr": "EP_NON_SECURE | EP_ST_ENABLE",
+ },
+ "pc": 67239936,
+ "spsr": 965,
+ "args": [67112976, 67112960, 0, 0, 0, 0, 0, 0],
+ },
+ },
+ (
+ "0x00580201 0x00000005 0x04020000 0x00000000 "
+ "0x000003C5 0x00000000 0x04001010 0x00000000 "
+ "0x04001000 0x00000000 0x00000000 0x00000000 "
+ "0x00000000 0x00000000 0x00000000 0x00000000 "
+ "0x00000000 0x00000000 0x00000000 0x00000000 "
+ "0x00000000 0x00000000"
+ ),
+ ),
+ ],
+)
+def test_create_from_yaml_check_exact_data(
+ tlcrunner, tmpyamlconfig, tmptlstr, entry, expected
+):
+ """Test creating a TL from a yaml file, checking the exact sequence of
+ bytes. This is useful for checking that the alignment is correct. You can
+ get the expected sequence of bytes by copying it from the ArmDS debugger.
+ """
+ # create yaml config file
+ config = {
+ "has_checksum": True,
+ "max_size": 0x1000,
+ "entries": [entry],
+ }
+ with open(tmpyamlconfig, "w") as f:
+ yaml.safe_dump(config, f)
+
+ # invoke TLC
+ tlcrunner.invoke(
+ cli,
+ [
+ "create",
+ "--from-yaml",
+ tmpyamlconfig,
+ tmptlstr,
+ ],
+ )
+
+ # open TL and check
+ tl = TransferList.fromfile(tmptlstr)
+ assert tl is not None
+ assert len(tl.entries) == 1
+
+ # check expected and actual data
+ actual = tl.entries[0].data
+ actual = bytes_to_hex(actual)
+
+ assert actual == expected
+
+
+def bytes_to_hex(data: bytes) -> str:
+ """Convert bytes to a hex string in the same format as the debugger in
+ ArmDS
+
+ You can copy data from the debugger in Arm Development Studio and put it
+ into a unit test. You can then run this function on the output from tlc,
+ and compare it to the data you copied.
+
+ The format is groups of 4 bytes with 0x prefixes separated by spaces.
+ Little endian is used.
+ """
+ words_hex = []
+ for i in range(0, len(data), 4):
+ word = data[i : i + 4]
+ word_int = int.from_bytes(word, "little")
+ word_hex = "0x" + f"{word_int:0>8x}".upper()
+ words_hex.append(word_hex)
+
+ return " ".join(words_hex)
+
+
+def iter_nested_dict(dictionary: dict):
+ for key, value in dictionary.items():
+ if isinstance(value, dict):
+ yield from iter_nested_dict(value)
+ else:
+ yield key, value
diff --git a/tools/tlc/tests/test_transfer_list.py b/tools/tlc/tests/test_transfer_list.py
new file mode 100644
index 0000000..e8c430e
--- /dev/null
+++ b/tools/tlc/tests/test_transfer_list.py
@@ -0,0 +1,234 @@
+#!/usr/bin/env python3
+
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+"""Contains unit tests for the types TransferEntry and TransferList."""
+
+import math
+
+import pytest
+
+from tlc.te import TransferEntry
+from tlc.tl import TransferList
+
+large_data = 0xDEADBEEF.to_bytes(4, "big")
+small_data = 0x1234.to_bytes(3, "big")
+test_entries = [
+ (0, b""),
+ (1, small_data),
+ (1, large_data),
+ (0xFFFFFF, small_data),
+ (0xFFFFFF, large_data),
+]
+
+
+@pytest.mark.parametrize(
+ "size,csum",
+ [
+ (-1, None),
+ (0x18, 0x9E),
+ (0x1000, 0xA6),
+ (0x2000, 0x96),
+ (0x4000, 0x76),
+ ],
+)
+def test_make_transfer_list(size, csum):
+ if size < 8:
+ with pytest.raises(AssertionError):
+ tl = TransferList(size)
+ else:
+ tl = TransferList(size)
+
+ assert tl.signature == 0x4A0FB10B
+ assert not tl.entries
+ assert tl.sum_of_bytes() == 0
+ assert tl.checksum == csum
+
+
+@pytest.mark.parametrize(("tag_id", "data"), test_entries)
+def test_add_transfer_entry(tag_id, data):
+ tl = TransferList(0x1000)
+ te = TransferEntry(tag_id, len(data), data)
+
+ tl.add_transfer_entry(tag_id, data)
+
+ assert te in tl.entries
+ assert tl.size == TransferList.hdr_size + te.size
+
+
+@pytest.mark.parametrize(
+ ("tag_id", "data"),
+ [
+ (-1, None), # tag out of range
+ (1, None), # no data provided
+ (1, bytes(8000)), # very large data > total size
+ (0x100000, b"0dd0edfe"), # tag out of range
+ ],
+)
+def test_add_out_of_range_transfer_entry(tag_id, data):
+ tl = TransferList()
+
+ with pytest.raises(Exception):
+ tl.add_transfer_entry(tag_id, data)
+
+
+@pytest.mark.parametrize(("tag_id", "data"), test_entries)
+def test_calculate_te_sum_of_bytes(tag_id, data):
+ te = TransferEntry(tag_id, len(data), data)
+ csum = (
+ sum(data)
+ + sum(len(data).to_bytes(4, "big"))
+ + te.hdr_size
+ + sum(tag_id.to_bytes(4, "big"))
+ ) % 256
+ assert te.sum_of_bytes == csum
+
+
+@pytest.mark.parametrize(("tag_id", "data"), test_entries)
+def test_calculate_tl_checksum(tag_id, data):
+ tl = TransferList(0x1000)
+
+ tl.add_transfer_entry(tag_id, data)
+ assert tl.sum_of_bytes() == 0
+
+
+def test_empty_transfer_list_blob(tmpdir):
+ """Check that we can correctly create a transfer list header."""
+ test_file = tmpdir.join("test_tl_blob.bin")
+ tl = TransferList()
+ tl.write_to_file(test_file)
+
+ with open(test_file, "rb") as f:
+ assert f.read(tl.hdr_size) == tl.header_to_bytes()
+
+
+@pytest.mark.parametrize(("tag_id", "data"), test_entries)
+def test_single_te_transfer_list(tag_id, data, tmpdir):
+ """Check that we can create a complete TL with a single TE."""
+ test_file = tmpdir.join("test_tl_blob.bin")
+ tl = TransferList(0x1000)
+
+ tl.add_transfer_entry(tag_id, data)
+ tl.write_to_file(test_file)
+
+ te = tl.entries[0]
+
+ with open(test_file, "rb") as f:
+ assert f.read(tl.hdr_size) == tl.header_to_bytes()
+ assert int.from_bytes(f.read(3), "little") == te.id
+ assert int.from_bytes(f.read(1), "little") == te.hdr_size
+ assert int.from_bytes(f.read(4), "little") == te.data_size
+ assert f.read(te.data_size) == te.data
+
+
+def test_multiple_te_transfer_list(tmpdir):
+ """Check that we can create a TL with multiple TE's."""
+ test_file = tmpdir.join("test_tl_blob.bin")
+ tl = TransferList(0x1000)
+
+ for tag_id, data in test_entries:
+ tl.add_transfer_entry(tag_id, data)
+
+ tl.write_to_file(test_file)
+
+ with open(test_file, "rb") as f:
+ assert f.read(tl.hdr_size) == tl.header_to_bytes()
+ # Ensure that TE's have the correct alignment
+ for tag_id, data in test_entries:
+ f.seek(int(math.ceil(f.tell() / 2**tl.alignment) * 2**tl.alignment))
+ print(f.tell())
+ assert int.from_bytes(f.read(3), "little") == tag_id
+ assert int.from_bytes(f.read(1), "little") == TransferEntry.hdr_size
+ # Make sure the data in the TE matches the data in the original case
+ data_size = int.from_bytes(f.read(4), "little")
+ assert f.read(data_size) == data
+
+
+def test_read_empty_transfer_list_from_file(tmpdir):
+ test_file = tmpdir.join("test_tl_blob.bin")
+ original_tl = TransferList(0x1000)
+ original_tl.write_to_file(test_file)
+
+ # Read the contents of the file we just wrote
+ tl = TransferList.fromfile(test_file)
+ assert tl.header_to_bytes() == original_tl.header_to_bytes()
+ assert tl.sum_of_bytes() == 0
+
+
+def test_read_single_transfer_list_from_file(tmpdir):
+ test_file = tmpdir.join("test_tl_blob.bin")
+ original_tl = TransferList(0x1000)
+
+ original_tl.add_transfer_entry(test_entries[0][0], test_entries[0][1])
+ original_tl.write_to_file(test_file)
+
+ # Read the contents of the file we just wrote
+ tl = TransferList.fromfile(test_file)
+ assert tl.entries
+
+ te = tl.entries[0]
+ assert te.id == test_entries[0][0]
+ assert te.data == test_entries[0][1]
+ assert tl.sum_of_bytes() == 0
+
+
+def test_read_multiple_transfer_list_from_file(tmpdir):
+ test_file = tmpdir.join("test_tl_blob.bin")
+ original_tl = TransferList(0x1000)
+
+ for tag_id, data in test_entries:
+ original_tl.add_transfer_entry(tag_id, data)
+
+ original_tl.write_to_file(test_file)
+
+ # Read the contents of the file we just wrote
+ tl = TransferList.fromfile(test_file)
+
+ # The TE we derive from the file might have a an associated offset, compare
+ # the TE's based on the header in bytes, which doesn't account for this.
+ for te0, te1 in zip(tl.entries, original_tl.entries):
+ assert te0.header_to_bytes() == te1.header_to_bytes()
+
+ assert tl.sum_of_bytes() == 0
+
+
+@pytest.mark.parametrize("tag", [tag for tag, _ in test_entries])
+def test_remove_tag_from_file(tag):
+ tl = TransferList(0x1000)
+
+ for tag_id, data in test_entries:
+ tl.add_transfer_entry(tag_id, data)
+
+ removed_entries = list(filter(lambda te: te.id == tag, tl.entries))
+ original_size = tl.size
+ tl.remove_tag(tag)
+
+ assert not any(tag == te.id for te in tl.entries)
+ assert tl.size == original_size - sum(map(lambda te: te.size, removed_entries))
+
+
+def test_get_fdt_offset(tmpdir):
+ tl = TransferList(0x1000)
+ tl.add_transfer_entry(1, 0xEDFE0DD0.to_bytes(4, "big"))
+ f = tmpdir.join("blob.bin")
+
+ tl.write_to_file(f)
+
+ blob_tl = TransferList.fromfile(f)
+
+ assert blob_tl.hdr_size + TransferEntry.hdr_size == blob_tl.get_entry_data_offset(1)
+
+
+def test_get_missing_fdt_offset(tmpdir):
+ tl = TransferList(0x1000)
+ f = tmpdir.join("blob.bin")
+
+ tl.write_to_file(f)
+ blob_tl = TransferList.fromfile(f)
+
+ with pytest.raises(ValueError):
+ blob_tl.get_entry_data_offset(1)
diff --git a/tools/tlc/tlc/__init__.py b/tools/tlc/tlc/__init__.py
new file mode 100644
index 0000000..82f5f5b
--- /dev/null
+++ b/tools/tlc/tlc/__init__.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python3
+# type: ignore[attr-defined]
+
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+"""Transfer List Compiler (TLC) is a Python-based CLI for efficiently handling transfer lists."""
+
+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/tlc/tlc/__main__.py b/tools/tlc/tlc/__main__.py
new file mode 100644
index 0000000..03ffa0e
--- /dev/null
+++ b/tools/tlc/tlc/__main__.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env python3
+# type: ignore[attr-defined]
+
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+from tlc.cli import cli
+
+if __name__ == "__main__":
+ cli()
diff --git a/tools/tlc/tlc/cli.py b/tools/tlc/tlc/cli.py
new file mode 100644
index 0000000..1d4949d
--- /dev/null
+++ b/tools/tlc/tlc/cli.py
@@ -0,0 +1,172 @@
+#!/usr/bin/env python3
+# type: ignore[attr-defined]
+
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+"""Module defining the Transfer List Compiler (TLC) command line interface."""
+
+from pathlib import Path
+
+import click
+import yaml
+
+from tlc.tl import *
+
+
+@click.group()
+@click.version_option()
+def cli():
+ pass
+
+
+@cli.command()
+@click.argument("filename", type=click.Path(dir_okay=False))
+@click.option(
+ "-s", "--size", default=0x1000, type=int, help="Maximum size of the Transfer List"
+)
+@click.option(
+ "--fdt",
+ type=click.Path(exists=True),
+ help="Path to flattened device tree (FDT).",
+)
+@click.option(
+ "--entry",
+ type=(int, click.Path(exists=True)),
+ multiple=True,
+ help="A tag ID and the corresponding path to a binary blob in the form <id> <path-to-blob>.",
+)
+@click.option(
+ "--flags",
+ default=TRANSFER_LIST_ENABLE_CHECKSUM,
+ show_default=True,
+ help="Settings for the TL's properties.",
+)
+@click.option(
+ "--from-yaml",
+ type=click.Path(exists=True),
+ help="Create the transfer list from a YAML config file.",
+)
+def create(filename, size, fdt, entry, flags, from_yaml):
+ """Create a new Transfer List."""
+ try:
+ if from_yaml:
+ with open(from_yaml, "r") as f:
+ config = yaml.safe_load(f)
+
+ tl = TransferList.from_dict(config)
+ else:
+ tl = TransferList(size)
+
+ entry = (*entry, (1, fdt)) if fdt else entry
+
+ for id, path in entry:
+ tl.add_transfer_entry_from_file(id, path)
+ except MemoryError as mem_excp:
+ raise MemoryError(
+ "TL max size exceeded, consider increasing with the option -s"
+ ) from mem_excp
+
+ tl.write_to_file(filename)
+
+
+@cli.command()
+@click.argument("filename", type=click.Path(exists=True, dir_okay=False))
+@click.option(
+ "--fdt-offset",
+ is_flag=True,
+ help="Returns the offset of FDT in the TL if it is present.",
+)
+@click.option(
+ "--header",
+ is_flag=True,
+ help="Print the Transfer List header.",
+)
+@click.option(
+ "--entries",
+ is_flag=True,
+ help="Print the Transfer List entries.",
+)
+def info(filename, fdt_offset, header, entries):
+ """Print the contents of an existing Transfer List.
+
+ This command allows you to extract the data stored in a binary blob
+ representing a transfer list (TL). The transfer list must comply with the
+ version of the firmware handoff specification supported by this tool.
+ """
+ tl = TransferList.fromfile(filename)
+
+ if fdt_offset:
+ return print(tl.get_entry_data_offset(1))
+
+ if header and entries or not (header or entries):
+ print(tl, sep="")
+ if tl.entries:
+ print("----", tl.get_transfer_entries_str(), sep="\n")
+ elif entries:
+ print(tl.get_transfer_entries_str())
+ elif header:
+ print(tl)
+
+
+@cli.command()
+@click.argument("filename", type=click.Path(exists=True, dir_okay=False))
+@click.option(
+ "--tags",
+ type=int,
+ multiple=True,
+ help="Tags to be removed from TL.",
+)
+def remove(filename, tags):
+ """Remove Transfer Entries with given tags.
+
+ Remove Transfer Entries with given tags from a Transfer List."""
+ tl = TransferList.fromfile(filename)
+
+ for tag in tags:
+ tl.remove_tag(tag)
+ tl.write_to_file(filename)
+
+
+@cli.command()
+@click.argument("filename", type=click.Path(exists=True, dir_okay=False))
+@click.option(
+ "--entry",
+ type=(int, click.Path(exists=True)),
+ multiple=True,
+ help="A tag ID and the corresponding path to a binary blob in the form <id> <path-to-blob>.",
+)
+def add(filename, entry):
+ """Update an existing Transfer List with given images."""
+ tl = TransferList.fromfile(filename)
+
+ for id, path in entry:
+ tl.add_transfer_entry_from_file(id, path)
+
+ tl.write_to_file(filename)
+
+
+@cli.command()
+@click.argument("filename", type=click.Path(exists=True, dir_okay=False))
+@click.option(
+ "-C", type=click.Path(exists=True), help="Output directory for extracted images."
+)
+def unpack(filename, c):
+ """Unpack images from a Transfer List."""
+ tl = TransferList.fromfile(filename)
+ pwd = Path(".") if not c else Path(c)
+
+ for i, te in enumerate(tl.entries):
+ with open(pwd / f"te_{i}_{te.id}.bin", "wb") as f:
+ f.write(te.data)
+
+
+@cli.command()
+@click.argument("filename", type=click.Path(exists=True, dir_okay=False))
+def validate(filename):
+ """Validate the contents of an existing Transfer List."""
+ TransferList.fromfile(filename)
+ print("Valid TL!")
diff --git a/tools/tlc/tlc/te.py b/tools/tlc/tlc/te.py
new file mode 100644
index 0000000..cf7aa67
--- /dev/null
+++ b/tools/tlc/tlc/te.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python3
+
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+"""Module containing definitions pertaining to the 'Transfer Entry' (TE) type."""
+
+from typing import ClassVar
+
+import struct
+from dataclasses import dataclass
+
+
+@dataclass
+class TransferEntry:
+ """Class representing a Transfer Entry."""
+
+ id: int
+ data_size: int
+ data: bytes
+ hdr_size: int = 8
+ offset: int = 0
+ # Header encoding, with little-endian byte order.
+ encoding: ClassVar[str] = "<BI"
+
+ def __post_init__(self):
+ if self.id < 0 or self.id > 0xFFFFFF:
+ raise ValueError(
+ f"Out of bounds tag ID: {self.id:x}.\n"
+ f"Valid range is from 0 to 0xFFFFFF. Please ensure the tag ID is within this range."
+ )
+
+ def __str__(self) -> str:
+ return "\n".join(
+ [
+ f"{k:<10} {hex(v)}"
+ for k, v in vars(self).items()
+ if not isinstance(v, bytes)
+ ]
+ )
+
+ @property
+ def size(self) -> int:
+ return self.hdr_size + len(self.data)
+
+ @property
+ def sum_of_bytes(self) -> int:
+ return (sum(self.header_to_bytes()) + sum(self.data)) % 256
+
+ def header_to_bytes(self) -> bytes:
+ return self.id.to_bytes(3, "little") + struct.pack(
+ self.encoding, self.hdr_size, self.data_size
+ )
diff --git a/tools/tlc/tlc/tl.py b/tools/tlc/tlc/tl.py
new file mode 100644
index 0000000..3f0065d
--- /dev/null
+++ b/tools/tlc/tlc/tl.py
@@ -0,0 +1,353 @@
+#!/usr/bin/env python3
+
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+"""Module containing definitions pertaining to the 'Transfer List' (TL) type."""
+
+import typing
+
+import math
+import struct
+from dataclasses import dataclass
+from functools import reduce
+from pathlib import Path
+
+from tlc.te import TransferEntry
+
+TRANSFER_LIST_ENABLE_CHECKSUM = 0b1
+
+# Description of each TE type. For each TE, there is a tag ID, a format (to be
+# used in struct.pack to encode the TE), and a list of field names that can
+# appear in the yaml file for that TE. Some fields are missing, if that TE has
+# to be processed differently, or if it can only be added with a blob file.
+transfer_entry_formats = {
+ 0: {
+ "tag_name": "empty",
+ "format": "4x",
+ "fields": [],
+ },
+ 1: {
+ "tag_name": "fdt",
+ },
+ 2: {
+ "tag_name": "hob_block",
+ },
+ 3: {
+ "tag_name": "hob_list",
+ },
+ 4: {
+ "tag_name": "acpi_table_aggregate",
+ },
+ 5: {
+ "tag_name": "tpm_event_log_table",
+ "fields": ["event_log", "flags"],
+ },
+ 6: {
+ "tag_name": "tpm_crb_base_address_table",
+ "format": "QI",
+ "fields": ["crb_base_address", "crb_size"],
+ },
+ 0x100: {
+ "tag_name": "optee_pageable_part",
+ "format": "Q",
+ "fields": ["pp_addr"],
+ },
+ 0x101: {
+ "tag_name": "dt_spmc_manifest",
+ },
+ 0x102: {
+ "tag_name": "exec_ep_info",
+ "format": "2BHIQI4x8Q",
+ "fields": ["ep_info"],
+ },
+ 0x104: {
+ "tag_name": "sram_layout",
+ "format": "2Q",
+ "fields": ["addr", "size"],
+ },
+}
+tag_name_to_tag_id = {
+ te["tag_name"]: tag_id for tag_id, te in transfer_entry_formats.items()
+}
+
+
+class TransferList:
+ """Class representing a Transfer List based on version 1.0 of the Firmware Handoff specification."""
+
+ # Header encoding, with little-endian byte order.
+ encoding = "<I4B4I"
+ hdr_size = 0x18
+ signature = 0x4A0FB10B
+ version = 1
+
+ def __init__(
+ self, max_size: int = hdr_size, flags: int = TRANSFER_LIST_ENABLE_CHECKSUM
+ ) -> None:
+ assert max_size >= self.hdr_size
+ self.checksum: int = 0
+ self.alignment: int = 3
+ self.size = self.hdr_size
+ self.total_size = max_size
+ self.flags = flags
+ self.entries: typing.List["TransferEntry"] = []
+ self.update_checksum()
+
+ def __str__(self) -> str:
+ return "\n".join(
+ [
+ f"{k:<10} {hex(v)}"
+ for k, v in vars(self).items()
+ if not isinstance(v, list)
+ ]
+ )
+
+ def get_transfer_entries_str(self):
+ return "\n----\n".join([str(te) for _, te in enumerate(self.entries)])
+
+ @classmethod
+ def fromfile(cls, filepath: Path) -> "TransferList":
+ tl = cls()
+
+ with open(filepath, "rb") as f:
+ (
+ tl.signature,
+ tl.checksum,
+ tl.version,
+ tl.hdr_size,
+ tl.alignment,
+ used_size,
+ tl.total_size,
+ tl.flags,
+ _,
+ ) = struct.unpack(
+ cls.encoding,
+ f.read(tl.hdr_size),
+ )
+
+ if tl.signature != TransferList.signature:
+ raise ValueError(f"Invalid TL signature 0x{tl.signature:x}!")
+ elif tl.version == 0 or tl.version > 0xFF:
+ raise ValueError(f"Invalid TL version 0x{tl.version:x}!")
+ else:
+ while tl.size < used_size:
+ # We add an extra padding byte into the header so we can extract
+ # the 3-byte wide ID as a 4-byte uint, shift out this padding
+ # once we have the id.
+ te_base = f.tell()
+ (id, hdr_size, data_size) = struct.unpack(
+ TransferEntry.encoding[0] + "I" + TransferEntry.encoding[1:],
+ b"\x00" + f.read(TransferEntry.hdr_size),
+ )
+
+ id >>= 8
+
+ te = tl.add_transfer_entry(id, f.read(data_size))
+ te.offset = te_base
+ f.seek(align(te_base + hdr_size + data_size, 2**tl.alignment))
+
+ return tl
+
+ @classmethod
+ def from_dict(cls, config: dict):
+ """Create a TL from data in a dictionary
+
+ The dictionary should have the same format as the yaml config files.
+ See the readme for more detail.
+
+ :param config: Dictionary containing the data described above.
+ """
+ # get settings from config and set defaults
+ max_size = config.get("max_size", 0x1000)
+ has_checksum = config.get("has_checksum", True)
+
+ flags = TRANSFER_LIST_ENABLE_CHECKSUM if has_checksum else 0
+
+ tl = cls(max_size, flags)
+
+ for entry in config["entries"]:
+ tl.add_transfer_entry_from_dict(entry)
+
+ return tl
+
+ def header_to_bytes(self) -> bytes:
+ return struct.pack(
+ self.encoding,
+ self.signature,
+ self.checksum,
+ self.version,
+ self.hdr_size,
+ self.alignment,
+ self.size,
+ self.total_size,
+ self.flags,
+ 0,
+ )
+
+ def update_checksum(self) -> None:
+ """Calculates the checksum based on the sum of bytes."""
+ self.checksum = 256 - ((self.sum_of_bytes() - self.checksum) % 256)
+
+ def sum_of_bytes(self) -> int:
+ """Sum of all bytes between the base address and the end of that last TE (modulo 0xff)."""
+ return (
+ sum(self.header_to_bytes()) + sum(te.sum_of_bytes for te in self.entries)
+ ) % 256
+
+ def get_entry_data_offset(self, tag_id: int) -> int:
+ """Returns offset of data of a TE from the base of the TL."""
+ for te in self.entries:
+ if te.id == tag_id:
+ return te.offset + te.hdr_size
+
+ raise ValueError(f"Tag {tag_id} not found in TL!")
+
+ def add_transfer_entry(self, tag_id: int, data: bytes) -> "TransferEntry":
+ """Appends a TransferEntry into the internal list of TE's."""
+ if not (self.total_size >= self.size + TransferEntry.hdr_size + len(data)):
+ raise MemoryError(
+ f"TL size has exceeded the maximum allocation {self.total_size}."
+ )
+ else:
+ te = TransferEntry(tag_id, len(data), data)
+ self.entries.append(te)
+ self.size += te.size
+ self.update_checksum()
+ return te
+
+ def add_transfer_entry_from_struct_format(
+ self, tag_id: int, struct_format: str, *args
+ ):
+ struct_format = "<" + struct_format
+ data = struct.pack(struct_format, *args)
+ return self.add_transfer_entry(tag_id, data)
+
+ def add_entry_point_info_transfer_entry(self, entry: dict) -> "TransferEntry":
+ """Add entry_point_info transfer entry
+
+ :param entry: Dictionary of the transfer entry, in the same format as
+ the YAML file.
+ """
+ ep_info = entry["ep_info"]
+ header = ep_info["h"]
+
+ # size of the entry_point_info struct
+ entry_point_size = 88
+
+ attr = header["attr"]
+ if type(attr) is str:
+ # convert string of flags names to an integer
+
+ # bit number | 0 | 1 |
+ # ------------|-----------------------|----------------------|
+ # 0 | secure | non-secure |
+ # 1 | little endian | big-endian |
+ # 2 | disable secure timer | enable secure timer |
+ # 3 | executable | non-executable |
+ # 4 | first exe | not first exe |
+ #
+ # Bit 5 and bit 0 are used to determine the security state.
+
+ flag_names = {
+ "EP_SECURE": 0x0,
+ "EP_NON_SECURE": 0x1,
+ "EP_REALM": 0x21,
+ "EP_EE_LITTLE": 0x0,
+ "EP_EE_BIG": 0x2,
+ "EP_ST_DISABLE": 0x0,
+ "EP_ST_ENABLE": 0x4,
+ "EP_NON_EXECUTABLE": 0x0,
+ "EP_EXECUTABLE": 0x8,
+ "EP_FIRST_EXE": 0x10,
+ }
+
+ # create list of integer flags, then bitwise-or them together
+ flags = [flag_names[f.strip()] for f in attr.split("|")]
+ attr = reduce(lambda x, y: x | y, flags)
+
+ return self.add_transfer_entry_from_struct_format(
+ 0x102,
+ transfer_entry_formats[0x102]["format"],
+ header["type"],
+ header["version"],
+ entry_point_size,
+ attr,
+ ep_info["pc"],
+ ep_info["spsr"],
+ *ep_info["args"],
+ )
+
+ def add_transfer_entry_from_dict(
+ self,
+ entry: dict,
+ ) -> "TransferEntry":
+ """Add a transfer entry from data in a dictionary
+
+ The dictionary should have the same format as the entries in the yaml
+ config files. See the readme for more detail.
+
+ :param entry: Dictionary containing the data described above.
+ """
+ # Tag_id is either a tag name or a tag id. Use it to get the TE format.
+ tag_id = entry["tag_id"]
+ if tag_id in tag_name_to_tag_id:
+ tag_id = tag_name_to_tag_id[tag_id]
+ te_format = transfer_entry_formats[tag_id]
+ tag_name = te_format["tag_name"]
+
+ if "blob_file_path" in entry:
+ return self.add_transfer_entry_from_file(tag_id, entry["blob_file_path"])
+ elif tag_name == "tpm_event_log_table":
+ with open(entry["event_log"], "rb") as f:
+ event_log_data = f.read()
+
+ flags_bytes = entry["flags"].to_bytes(4, "little")
+ data = flags_bytes + event_log_data
+
+ return self.add_transfer_entry(tag_id, data)
+ elif tag_name == "exec_ep_info":
+ return self.add_entry_point_info_transfer_entry(entry)
+ elif "format" in te_format and "fields" in te_format:
+ fields = [entry[field] for field in te_format["fields"]]
+ return self.add_transfer_entry_from_struct_format(
+ tag_id, te_format["format"], *fields
+ )
+ else:
+ raise ValueError(f"Invalid transfer entry {entry}.")
+
+ def add_transfer_entry_from_file(self, tag_id: int, path: Path) -> "TransferEntry":
+ with open(path, "rb") as f:
+ return self.add_transfer_entry(tag_id, f.read())
+
+ def write_to_file(self, file: Path) -> None:
+ """Write the contents of the TL to a file."""
+ with open(file, "wb") as f:
+ f.write(self.header_to_bytes())
+ for te in self.entries:
+ assert f.tell() + te.hdr_size + te.data_size < self.total_size
+ te_base = f.tell()
+ f.write(te.header_to_bytes())
+ f.write(te.data)
+ # Ensure the next TE has the correct alignment
+ f.write(
+ bytes(
+ (
+ align(
+ te_base + te.hdr_size + te.data_size, 2**self.alignment
+ )
+ - f.tell()
+ )
+ )
+ )
+
+ def remove_tag(self, tag: int) -> None:
+ self.entries = list(filter(lambda te: te.id != tag, self.entries))
+ self.size = self.hdr_size + sum(map(lambda te: te.size, self.entries))
+ self.update_checksum()
+
+
+def align(n, alignment):
+ return int(math.ceil(n / alignment) * alignment)