Merge "feat(rcar3): change CAM setting to improve bus latency of R-Car Gen3" into integration
diff --git a/Makefile b/Makefile
index 800346a..7058d57 100644
--- a/Makefile
+++ b/Makefile
@@ -1221,7 +1221,6 @@
ENABLE_FEAT_ECV \
ENABLE_FEAT_FGT \
ENABLE_FEAT_HCX \
- ENABLE_FEAT_MTE \
ENABLE_FEAT_MTE2 \
ENABLE_FEAT_PAN \
ENABLE_FEAT_RNG \
@@ -1235,7 +1234,6 @@
ENABLE_FEAT_S1POE \
ENABLE_FEAT_GCS \
ENABLE_FEAT_VHE \
- ENABLE_FEAT_MTE_PERM \
ENABLE_FEAT_MPAM \
ENABLE_RME \
ENABLE_SPE_FOR_NS \
@@ -1384,9 +1382,7 @@
ENABLE_FEAT_S2POE \
ENABLE_FEAT_S1POE \
ENABLE_FEAT_GCS \
- ENABLE_FEAT_MTE \
ENABLE_FEAT_MTE2 \
- ENABLE_FEAT_MTE_PERM \
FEATURE_DETECTION \
TWED_DELAY \
ENABLE_FEAT_TWED \
diff --git a/bl31/bl31_traps.c b/bl31/bl31_traps.c
index f1b1fa6..474b4d5 100644
--- a/bl31/bl31_traps.c
+++ b/bl31/bl31_traps.c
@@ -165,7 +165,7 @@
/* If FEAT_MTE2 is implemented mask tag faults by setting TCO bit */
new_spsr |= old_spsr & SPSR_TCO_BIT_AARCH64;
- if (read_feat_mte_id_field() >= MTE_IMPLEMENTED_ELX) {
+ if (is_feat_mte2_present()) {
new_spsr |= SPSR_TCO_BIT_AARCH64;
}
diff --git a/bl32/tsp/tsp_main.c b/bl32/tsp/tsp_main.c
index d8031f9..805575a 100644
--- a/bl32/tsp/tsp_main.c
+++ b/bl32/tsp/tsp_main.c
@@ -239,10 +239,10 @@
service_arg1 = (uint64_t)(service_args >> 64U);
/*
- * Write a dummy value to an MTE register, to simulate usage in the
+ * Write a dummy value to an MTE2 register, to simulate usage in the
* secure world
*/
- if (is_feat_mte_supported()) {
+ if (is_feat_mte2_supported()) {
write_gcr_el1(0x99);
}
diff --git a/changelog.yaml b/changelog.yaml
index 7f0c1ec..b7f281c 100644
--- a/changelog.yaml
+++ b/changelog.yaml
@@ -116,8 +116,11 @@
- title: Memory Partitioning and Monitoring (MPAM) Extension (FEAT_MPAM)
scope: mpam
- - title: Memory Tagging Extension
- scope: mte
+ - title: Memory Tagging Extension2
+ scope: mte2
+
+ deprecated:
+ - mte
- title: Pointer Authentication Extension
scope: pauth
@@ -544,6 +547,9 @@
- title: Raspberry Pi 4
scope: rpi4
+ - title: Raspberry Pi 5
+ scope: rpi5
+
- title: Renesas
scope: renesas
diff --git a/common/feat_detect.c b/common/feat_detect.c
index 7a2f0d7..7f01037 100644
--- a/common/feat_detect.c
+++ b/common/feat_detect.c
@@ -167,9 +167,7 @@
"TRF", 1, 1);
/* v8.5 features */
- check_feature(ENABLE_FEAT_MTE, read_feat_mte_id_field(), "MTE",
- MTE_IMPLEMENTED_EL0, MTE_IMPLEMENTED_ASY);
- check_feature(ENABLE_FEAT_MTE2, read_feat_mte_id_field(), "MTE2",
+ check_feature(ENABLE_FEAT_MTE2, get_armv8_5_mte_support(), "MTE2",
MTE_IMPLEMENTED_ELX, MTE_IMPLEMENTED_ASY);
check_feature(ENABLE_FEAT_RNG, read_feat_rng_id_field(), "RNG", 1, 1);
read_feat_bti();
@@ -204,8 +202,6 @@
"S2POE", 1, 1);
check_feature(ENABLE_FEAT_S1POE, read_feat_s1poe_id_field(),
"S1POE", 1, 1);
- check_feature(ENABLE_FEAT_MTE_PERM, read_feat_mte_perm_id_field(),
- "MTE_PERM", 1, 1);
check_feature(ENABLE_FEAT_CSV2_3, read_feat_csv2_id_field(),
"CSV2_3", 3, 3);
diff --git a/docs/components/secure-partition-manager.rst b/docs/components/secure-partition-manager.rst
index 4834d3a..b6f4219 100644
--- a/docs/components/secure-partition-manager.rst
+++ b/docs/components/secure-partition-manager.rst
@@ -215,7 +215,7 @@
ARM_ARCH_MINOR=5 \
BRANCH_PROTECTION=1 \
CTX_INCLUDE_PAUTH_REGS=1 \
- ENABLE_FEAT_MTE=1 \
+ ENABLE_FEAT_MTE2=1 \
BL32=<path-to-hafnium-binary> \
BL33=<path-to-bl33-binary> \
SP_LAYOUT_FILE=sp_layout.json \
@@ -233,7 +233,7 @@
ARM_ARCH_MINOR=5 \
BRANCH_PROTECTION=1 \
CTX_INCLUDE_PAUTH_REGS=1 \
- ENABLE_FEAT_MTE=1 \
+ ENABLE_FEAT_MTE2=1 \
BL32=<path-to-hafnium-binary> \
BL33=<path-to-bl33-binary> \
SP_LAYOUT_FILE=sp_layout.json \
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index 97e164d..5733214 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -793,7 +793,7 @@
- ``ERRATA_X3_2615812``: This applies errata 2615812 workaround to Cortex-X3
CPU. This needs to be enabled only for revisions r0p0, r1p0 and r1p1 of the
- CPU, it is still open.
+ CPU, it is fixed in r1p2.
- ``ERRATA_X3_2641945``: This applies errata 2641945 workaround to Cortex-X3
CPU. This needs to be enabled only for revisions r0p0 and r1p0 of the CPU.
@@ -916,6 +916,15 @@
Cortex-A715 CPU. This needs to be enabled only for revision r1p0.
It is fixed in r1p1.
+For Cortex-A720, the following errata build flags are defined :
+
+- ``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.
+
+- ``ERRATA_A720_2940794``: This applies errata 2940794 workaround to
+ Cortex-A720 CPU. This needs to be enabled for revisions r0p0 and r0p1.
+ It is fixed in r0p2.
DSU Errata Workarounds
----------------------
diff --git a/docs/design/firmware-design.rst b/docs/design/firmware-design.rst
index fa06c8e..2ba54ea 100644
--- a/docs/design/firmware-design.rst
+++ b/docs/design/firmware-design.rst
@@ -2800,9 +2800,11 @@
- Branch Target Identification feature is selected by ``BRANCH_PROTECTION``
option set to 1. This option defaults to 0.
-- Memory Tagging Extension feature is unconditionally enabled for both worlds.
- To enable MTE at EL0 use ``ENABLE_FEAT_MTE`` is required and to enable MTE at
- ELX ``ENABLE_FEAT_MTE2`` is required.
+- Memory Tagging Extension feature has few variants but not all of them require
+ enablement from EL3 to be used at lower EL. e.g. Memory tagging only at
+ EL0(MTE) does not require EL3 configuration however memory tagging at
+ EL2/EL1 (MTE2) does require EL3 enablement and we need to set this option
+ ``ENABLE_FEAT_MTE2`` to 1. This option defaults to 0.
Armv7-A
~~~~~~~
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index f817da0..c18c155 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -340,23 +340,11 @@
flag can take the values 0 to 2, to align with the ``ENABLE_FEAT``
mechanism. Default value is ``0``.
-- ``ENABLE_FEAT_MTE``: Numeric value to enable Memory Tagging Extension
- if the platform wants to use this feature at EL0 ``ENABLE_FEAT_MTE`` is
- required. This flag can take values 0 to 2, to align with the ``ENABLE_FEAT``
- feature detection mechanism. Default value is ``0``.
-
- ``ENABLE_FEAT_MTE2``: Numeric value to enable Memory Tagging Extension2
if the platform wants to use this feature and MTE2 is enabled at ELX.
This flag can take values 0 to 2, to align with the ``ENABLE_FEAT``
mechanism. Default value is ``0``.
-- ``ENABLE_FEAT_MTE_PERM``: Numeric value to enable support for
- ``FEAT_MTE_PERM``, which introduces Allocation tag access permission to
- memory region attributes. ``FEAT_MTE_PERM`` is a optional architectural
- feature available from v8.9 and upwards. This flag can take the values 0 to
- 2, to align with the ``ENABLE_FEAT`` mechanism. Default value is
- ``0``.
-
- ``ENABLE_FEAT_PAN``: Numeric value to enable the ``FEAT_PAN`` (Privileged
Access Never) extension. ``FEAT_PAN`` adds a bit to PSTATE, generating a
permission fault for any privileged data access from EL1/EL2 to virtual
diff --git a/docs/plat/index.rst b/docs/plat/index.rst
index 43f4898..35cc27d 100644
--- a/docs/plat/index.rst
+++ b/docs/plat/index.rst
@@ -38,6 +38,7 @@
qti-msm8916
rpi3
rpi4
+ rpi5
rcar-gen3
rz-g2
rockchip
diff --git a/docs/plat/rpi5.rst b/docs/plat/rpi5.rst
new file mode 100644
index 0000000..f2e1b9f
--- /dev/null
+++ b/docs/plat/rpi5.rst
@@ -0,0 +1,78 @@
+Raspberry Pi 5
+==============
+
+The `Raspberry Pi 5`_ is a single-board computer that contains four
+Arm Cortex-A76 cores.
+
+This port is a minimal BL31 implementation capable of booting 64-bit EL2
+payloads such as Linux and EDK2.
+
+**IMPORTANT NOTE**: This port isn't secure. All of the memory used is DRAM,
+which is available from both the Non-secure and Secure worlds. The SoC does
+not seem to feature a secure memory controller of any kind, so portions of
+DRAM can't be protected properly from the Non-secure world.
+
+Build
+------------------
+
+To build this platform, run:
+
+.. code:: shell
+
+ CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi5 DEBUG=1
+
+The firmware will be generated at ``build/rpi5/debug/bl31.bin``.
+
+The following build options are supported:
+
+- ``RPI3_DIRECT_LINUX_BOOT``: Enabled by default. Allows direct boot of the Linux
+ kernel from the firmware.
+
+- ``PRELOADED_BL33_BASE``: Used to specify the fixed address of a BL33 binary
+ that has been preloaded by earlier boot stages (VPU). Useful for bundling
+ BL31 and BL33 in the same ``armstub`` image (e.g. TF-A + EDK2).
+
+- ``RPI3_PRELOADED_DTB_BASE``: This option allows to specify the fixed address of
+ a DTB in memory. Can only be used if ``device_tree_address=`` is present in
+ config.txt.
+
+- ``RPI3_RUNTIME_UART``: Indicates whether TF-A should use the debug UART for
+ runtime messages or not. ``-1`` (default) disables the option, any other value
+ enables it.
+
+Usage
+------------------
+
+Copy the firmware binary to the first FAT32 partition of a supported boot media
+(SD, USB) and append ``armstub=bl31.bin`` to config.txt, or just rename the
+file to ``armstub8-2712.bin``.
+
+No other config options or files are required by the firmware alone, this will
+depend on the payload you intend to run.
+
+For Linux, you must also place an appropriate DTB and kernel in the boot
+partition. This has been validated with a copy of Raspberry Pi OS.
+
+The VPU will preload a BL33 AArch64 image named either ``kernel_2712.img`` or
+``kernel8.img``, which can be overridden by adding a ``kernel=filename`` option
+to config.txt.
+
+Kernel and DTB load addresses are also chosen by the VPU and can be changed with
+``kernel_address=`` and ``device_tree_address=`` in config.txt. If TF-A was built
+with ``PRELOADED_BL33_BASE`` or ``RPI3_PRELOADED_DTB_BASE``, setting those config
+options may be necessary.
+
+By default, all boot stages print messages to the dedicated UART debug port.
+Configuration is ``115200 8n1``.
+
+Design
+------------------
+
+This port is largely based on the RPi 4 one.
+
+The boot process is essentially the same, the only notable difference being that
+all VPU blobs have been moved into EEPROM (former start4.elf & fixup4.dat). There's
+also a custom BL31 TF-A armstub included for PSCI, which can be replaced with this
+port.
+
+.. _Raspberry Pi 5: https://www.raspberrypi.com/products/raspberry-pi-5/
diff --git a/docs/plat/st/stm32mp1.rst b/docs/plat/st/stm32mp1.rst
index b6e4b0d..39a43ee 100644
--- a/docs/plat/st/stm32mp1.rst
+++ b/docs/plat/st/stm32mp1.rst
@@ -115,8 +115,9 @@
make stm32mp15_trusted_defconfig
make DEVICE_TREE=stm32mp157c-ev1 all
-OP-TEE (optional)
-_________________
+OP-TEE (recommended)
+____________________
+OP-TEE is the default BL32 supported for STMicroelectronics platforms.
.. code:: bash
@@ -125,9 +126,10 @@
CFG_EMBED_DTB_SOURCE_FILE=stm32mp157c-ev1.dts
-TF-A BL32 (SP_min)
-__________________
+TF-A BL32 (SP_min) (not recommended)
+____________________________________
If you choose not to use OP-TEE, you can use TF-A SP_min.
+This is not the recommended BL32 to use, and will have very limited support.
To build TF-A BL32, and its device tree file:
.. code:: bash
@@ -217,4 +219,4 @@
.. _STM32MP1 Series: https://www.st.com/en/microcontrollers-microprocessors/stm32mp1-series.html
.. _STM32MP1 part number codification: https://wiki.st.com/stm32mpu/wiki/STM32MP15_microprocessor#Part_number_codification
-*Copyright (c) 2023, STMicroelectronics - All Rights Reserved*
+*Copyright (c) 2023-2024, STMicroelectronics - All Rights Reserved*
diff --git a/docs/plat/st/stm32mpus.rst b/docs/plat/st/stm32mpus.rst
index 931dd57..ab6d8fe 100644
--- a/docs/plat/st/stm32mpus.rst
+++ b/docs/plat/st/stm32mpus.rst
@@ -45,6 +45,8 @@
- ``STM32MP_UART_PROGRAMMER``
- ``STM32MP_USB_PROGRAMMER``
+Only one storage or serial device should be selected in the build command line,
+to save space and not overflow SYSRAM size, or else the platform won't build or boot.
Other configuration flags:
@@ -75,4 +77,4 @@
--------------
-*Copyright (c) 2023, STMicroelectronics - All Rights Reserved*
+*Copyright (c) 2023-2024, STMicroelectronics - All Rights Reserved*
diff --git a/docs/security_advisories/security-advisory-tfv-9.rst b/docs/security_advisories/security-advisory-tfv-9.rst
index 762801d..014221e 100644
--- a/docs/security_advisories/security-advisory-tfv-9.rst
+++ b/docs/security_advisories/security-advisory-tfv-9.rst
@@ -87,7 +87,7 @@
+----------------------+
| Neoverse-V2 |
+----------------------+
-| Neoverse-Poseidon |
+| Neoverse-V3 |
+----------------------+
For all other cores impacted by Spectre-BHB, some of which that do not implement
diff --git a/drivers/arm/gic/v3/gic600_multichip.c b/drivers/arm/gic/v3/gic600_multichip.c
index a4786bb..5e44aa9 100644
--- a/drivers/arm/gic/v3/gic600_multichip.c
+++ b/drivers/arm/gic/v3/gic600_multichip.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
* Copyright (c) 2022-2023, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -75,7 +75,7 @@
panic();
}
- /* Poll till PUP is zero before intiating write */
+ /* Poll till PUP is zero before initiating write */
gicd_dchipr_wait_for_power_update_progress(base);
write_gicd_dchipr(base, read_gicd_dchipr(base) |
diff --git a/drivers/arm/mhu/mhu_v3_x.c b/drivers/arm/mhu/mhu_v3_x.c
new file mode 100644
index 0000000..118c608
--- /dev/null
+++ b/drivers/arm/mhu/mhu_v3_x.c
@@ -0,0 +1,475 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "mhu_v3_x.h"
+
+#include "mhu_v3_x_private.h"
+
+/*
+ * Get the device base from the device struct. Return an error if the dev is
+ * invalid.
+ */
+static enum mhu_v3_x_error_t get_dev_base(const struct mhu_v3_x_dev_t *dev,
+ union _mhu_v3_x_frame_t **base)
+{
+ if (dev == NULL) {
+ return MHU_V_3_X_ERR_INVALID_PARAM;
+ }
+
+ /* Ensure driver has been initialized */
+ if (dev->is_initialized == false) {
+ return MHU_V_3_X_ERR_NOT_INIT;
+ }
+
+ *base = (union _mhu_v3_x_frame_t *)dev->base;
+
+ return MHU_V_3_X_ERR_NONE;
+}
+
+enum mhu_v3_x_error_t mhu_v3_x_driver_init(struct mhu_v3_x_dev_t *dev)
+{
+ uint32_t aidr = 0;
+ uint8_t mhu_major_rev;
+ union _mhu_v3_x_frame_t *p_mhu;
+
+ if (dev == NULL) {
+ return MHU_V_3_X_ERR_INVALID_PARAM;
+ }
+
+ /* Return if already initialized */
+ if (dev->is_initialized == true) {
+ return MHU_V_3_X_ERR_NONE;
+ }
+
+ p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
+
+ /* Read revision from MHU hardware */
+ if (dev->frame == MHU_V3_X_PBX_FRAME) {
+ aidr = p_mhu->pbx_frame.pbx_ctrl_page.pbx_aidr;
+ } else if (dev->frame == MHU_V3_X_MBX_FRAME) {
+ aidr = p_mhu->mbx_frame.mbx_ctrl_page.mbx_aidr;
+ } else {
+ /* Only PBX and MBX frames are supported. */
+ return MHU_V_3_X_ERR_UNSUPPORTED;
+ }
+
+ /* Read the MHU Architecture Major Revision */
+ mhu_major_rev =
+ ((aidr & MHU_ARCH_MAJOR_REV_MASK) >> MHU_ARCH_MAJOR_REV_OFF);
+
+ /* Return error if the MHU major revision is not 3 */
+ if (mhu_major_rev != MHU_MAJOR_REV_V3) {
+ /* Unsupported MHU version */
+ return MHU_V_3_X_ERR_UNSUPPORTED_VERSION;
+ }
+
+ /* Read the MHU Architecture Minor Revision */
+ dev->subversion =
+ ((aidr & MHU_ARCH_MINOR_REV_MASK) >> MHU_ARCH_MINOR_REV_MASK);
+
+ /* Return error if the MHU minor revision is not 0 */
+ if (dev->subversion != MHU_MINOR_REV_3_0) {
+ /* Unsupported subversion */
+ return MHU_V_3_X_ERR_UNSUPPORTED_VERSION;
+ }
+
+ /* Initialize the Postbox/Mailbox to remain in operational state */
+ if (dev->frame == MHU_V3_X_PBX_FRAME) {
+ p_mhu->pbx_frame.pbx_ctrl_page.pbx_ctrl |= MHU_V3_OP_REQ;
+ } else if (dev->frame == MHU_V3_X_MBX_FRAME) {
+ p_mhu->mbx_frame.mbx_ctrl_page.mbx_ctrl |= MHU_V3_OP_REQ;
+ } else {
+ /* Only PBX and MBX frames are supported. */
+ return MHU_V_3_X_ERR_UNSUPPORTED;
+ }
+
+ dev->is_initialized = true;
+
+ return MHU_V_3_X_ERR_NONE;
+}
+
+enum mhu_v3_x_error_t mhu_v3_x_get_num_channel_implemented(
+ const struct mhu_v3_x_dev_t *dev,
+ enum mhu_v3_x_channel_type_t ch_type, uint8_t *num_ch)
+{
+ enum mhu_v3_x_error_t status;
+ union _mhu_v3_x_frame_t *p_mhu;
+
+ if (num_ch == NULL) {
+ return MHU_V_3_X_ERR_INVALID_PARAM;
+ }
+
+ /* Get dev->base if it is valid or return an error if dev is not */
+ status = get_dev_base(dev, &p_mhu);
+ if (status != MHU_V_3_X_ERR_NONE) {
+ return status;
+ }
+
+ /* Only doorbell channel is supported */
+ if (ch_type != MHU_V3_X_CHANNEL_TYPE_DBCH) {
+ return MHU_V_3_X_ERR_UNSUPPORTED;
+ }
+
+ /* Read the number of channels implemented in the MHU */
+ if (dev->frame == MHU_V3_X_PBX_FRAME) {
+ *num_ch = (p_mhu->pbx_frame.pbx_ctrl_page.pbx_dbch_cfg0 + 1);
+ } else if (dev->frame == MHU_V3_X_MBX_FRAME) {
+ *num_ch = (p_mhu->mbx_frame.mbx_ctrl_page.mbx_dbch_cfg0 + 1);
+ } else {
+ /* Only PBX and MBX frames are supported. */
+ return MHU_V_3_X_ERR_UNSUPPORTED;
+ }
+
+ return MHU_V_3_X_ERR_NONE;
+}
+
+enum mhu_v3_x_error_t mhu_v3_x_doorbell_clear(const struct mhu_v3_x_dev_t *dev,
+ const uint32_t channel, uint32_t flags)
+{
+ union _mhu_v3_x_frame_t *p_mhu;
+ struct _mhu_v3_x_mdbcw_reg_t *mdbcw_reg;
+ enum mhu_v3_x_error_t status;
+
+ /* Get dev->base if it is valid or return an error if dev is not */
+ status = get_dev_base(dev, &p_mhu);
+ if (status != MHU_V_3_X_ERR_NONE) {
+ return status;
+ }
+
+ /* Only MBX can clear the Doorbell channel */
+ if (dev->frame != MHU_V3_X_MBX_FRAME) {
+ return MHU_V_3_X_ERR_INVALID_PARAM;
+ }
+
+ p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
+ mdbcw_reg = (struct _mhu_v3_x_mdbcw_reg_t *)
+ &(p_mhu->mbx_frame.mdbcw_page);
+
+ /* Clear the bits in the doorbell channel */
+ mdbcw_reg[channel].mdbcw_clr |= flags;
+
+ return MHU_V_3_X_ERR_NONE;
+}
+
+enum mhu_v3_x_error_t mhu_v3_x_doorbell_write(const struct mhu_v3_x_dev_t *dev,
+ const uint32_t channel, uint32_t flags)
+{
+ union _mhu_v3_x_frame_t *p_mhu;
+ struct _mhu_v3_x_pdbcw_reg_t *pdbcw_reg;
+ enum mhu_v3_x_error_t status;
+
+ /* Get dev->base if it is valid or return an error if dev is not */
+ status = get_dev_base(dev, &p_mhu);
+ if (status != MHU_V_3_X_ERR_NONE) {
+ return status;
+ }
+
+ /* Only PBX can set the Doorbell channel value */
+ if (dev->frame != MHU_V3_X_PBX_FRAME) {
+ return MHU_V_3_X_ERR_INVALID_PARAM;
+ }
+
+ p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
+
+ pdbcw_reg = (struct _mhu_v3_x_pdbcw_reg_t *)
+ &(p_mhu->pbx_frame.pdbcw_page);
+
+ /* Write the value to the doorbell channel */
+ pdbcw_reg[channel].pdbcw_set |= flags;
+
+ return MHU_V_3_X_ERR_NONE;
+}
+
+enum mhu_v3_x_error_t mhu_v3_x_doorbell_read(const struct mhu_v3_x_dev_t *dev,
+ const uint32_t channel, uint32_t *flags)
+{
+ union _mhu_v3_x_frame_t *p_mhu;
+ enum mhu_v3_x_error_t status;
+ struct _mhu_v3_x_mdbcw_reg_t *mdbcw_reg;
+ struct _mhu_v3_x_pdbcw_reg_t *pdbcw_reg;
+
+ if (flags == NULL) {
+ return MHU_V_3_X_ERR_INVALID_PARAM;
+ }
+
+ /* Get dev->base if it is valid or return an error if dev is not */
+ status = get_dev_base(dev, &p_mhu);
+ if (status != MHU_V_3_X_ERR_NONE) {
+ return status;
+ }
+
+ p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
+
+ if (dev->frame == MHU_V3_X_PBX_FRAME) {
+ pdbcw_reg = (struct _mhu_v3_x_pdbcw_reg_t *)
+ &(p_mhu->pbx_frame.pdbcw_page);
+
+ /* Read the value from Postbox Doorbell status register */
+ *flags = pdbcw_reg[channel].pdbcw_st;
+ } else if (dev->frame == MHU_V3_X_MBX_FRAME) {
+ mdbcw_reg = (struct _mhu_v3_x_mdbcw_reg_t *)
+ &(p_mhu->mbx_frame.mdbcw_page);
+
+ /* Read the value from Mailbox Doorbell status register */
+ *flags = mdbcw_reg[channel].mdbcw_st;
+ } else {
+ /* Only PBX and MBX frames are supported. */
+ return MHU_V_3_X_ERR_UNSUPPORTED;
+ }
+
+ return MHU_V_3_X_ERR_NONE;
+}
+
+enum mhu_v3_x_error_t mhu_v3_x_doorbell_mask_set(
+ const struct mhu_v3_x_dev_t *dev, const uint32_t channel,
+ uint32_t flags)
+{
+ union _mhu_v3_x_frame_t *p_mhu;
+ struct _mhu_v3_x_mdbcw_reg_t *mdbcw_reg;
+ enum mhu_v3_x_error_t status;
+
+ /* Get dev->base if it is valid or return an error if dev is not */
+ status = get_dev_base(dev, &p_mhu);
+ if (status != MHU_V_3_X_ERR_NONE) {
+ return status;
+ }
+
+ /* Doorbell channel mask is not applicable for PBX */
+ if (dev->frame != MHU_V3_X_MBX_FRAME) {
+ return MHU_V_3_X_ERR_INVALID_PARAM;
+ }
+
+ p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
+
+ mdbcw_reg = (struct _mhu_v3_x_mdbcw_reg_t *)
+ &(p_mhu->mbx_frame.mdbcw_page);
+
+ /* Set the Doorbell channel mask */
+ mdbcw_reg[channel].mdbcw_msk_set |= flags;
+
+ return MHU_V_3_X_ERR_NONE;
+}
+
+enum mhu_v3_x_error_t mhu_v3_x_doorbell_mask_clear(
+ const struct mhu_v3_x_dev_t *dev, const uint32_t channel,
+ uint32_t flags)
+{
+ union _mhu_v3_x_frame_t *p_mhu;
+ struct _mhu_v3_x_mdbcw_reg_t *mdbcw_reg;
+ enum mhu_v3_x_error_t status;
+
+ /* Get dev->base if it is valid or return an error if dev is not */
+ status = get_dev_base(dev, &p_mhu);
+ if (status != MHU_V_3_X_ERR_NONE) {
+ return status;
+ }
+
+ /* Doorbell channel mask is not applicable for PBX */
+ if (dev->frame != MHU_V3_X_MBX_FRAME) {
+ return MHU_V_3_X_ERR_INVALID_PARAM;
+ }
+
+ p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
+
+ mdbcw_reg = (struct _mhu_v3_x_mdbcw_reg_t *)
+ &(p_mhu->mbx_frame.mdbcw_page);
+
+ /* Clear the Doorbell channel mask */
+ mdbcw_reg[channel].mdbcw_msk_clr = flags;
+
+ return MHU_V_3_X_ERR_NONE;
+}
+
+enum mhu_v3_x_error_t mhu_v3_x_doorbell_mask_get(
+ const struct mhu_v3_x_dev_t *dev, const uint32_t channel,
+ uint32_t *flags)
+{
+ union _mhu_v3_x_frame_t *p_mhu;
+ struct _mhu_v3_x_mdbcw_reg_t *mdbcw_reg;
+ enum mhu_v3_x_error_t status;
+
+ if (flags == NULL) {
+ return MHU_V_3_X_ERR_INVALID_PARAM;
+ }
+
+ /* Get dev->base if it is valid or return an error if dev is not */
+ status = get_dev_base(dev, &p_mhu);
+ if (status != MHU_V_3_X_ERR_NONE) {
+ return status;
+ }
+
+ /* Doorbell channel mask is not applicable for PBX */
+ if (dev->frame != MHU_V3_X_MBX_FRAME) {
+ return MHU_V_3_X_ERR_INVALID_PARAM;
+ }
+
+ p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
+
+ mdbcw_reg = (struct _mhu_v3_x_mdbcw_reg_t *)
+ &(p_mhu->mbx_frame.mdbcw_page);
+
+ /* Save the Doorbell channel mask status */
+ *flags = mdbcw_reg[channel].mdbcw_msk_st;
+
+ return MHU_V_3_X_ERR_NONE;
+}
+
+enum mhu_v3_x_error_t mhu_v3_x_channel_interrupt_enable(
+ const struct mhu_v3_x_dev_t *dev, const uint32_t channel,
+ enum mhu_v3_x_channel_type_t ch_type)
+{
+ enum mhu_v3_x_error_t status;
+
+ union _mhu_v3_x_frame_t *p_mhu;
+ struct _mhu_v3_x_pdbcw_reg_t *pdbcw_reg;
+ struct _mhu_v3_x_mdbcw_reg_t *mdbcw_reg;
+
+ /* Get dev->base if it is valid or return an error if dev is not */
+ status = get_dev_base(dev, &p_mhu);
+ if (status != MHU_V_3_X_ERR_NONE) {
+ return status;
+ }
+
+ /* Only doorbell channel is supported */
+ if (ch_type != MHU_V3_X_CHANNEL_TYPE_DBCH) {
+ return MHU_V_3_X_ERR_UNSUPPORTED;
+ }
+
+ p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
+
+ if (dev->frame == MHU_V3_X_PBX_FRAME) {
+ pdbcw_reg = (struct _mhu_v3_x_pdbcw_reg_t *)
+ &(p_mhu->pbx_frame.pdbcw_page);
+
+ /*
+ * Enable this doorbell channel to generate interrupts for
+ * transfer acknowledge events.
+ */
+ pdbcw_reg[channel].pdbcw_int_en = MHU_V3_X_PDBCW_INT_X_TFR_ACK;
+
+ /*
+ * Enable this doorbell channel to contribute to the PBX
+ * combined interrupt.
+ */
+ pdbcw_reg[channel].pdbcw_ctrl = MHU_V3_X_PDBCW_CTRL_PBX_COMB_EN;
+ } else if (dev->frame == MHU_V3_X_MBX_FRAME) {
+ mdbcw_reg = (struct _mhu_v3_x_mdbcw_reg_t *)
+ &(p_mhu->mbx_frame.mdbcw_page);
+
+ /*
+ * Enable this doorbell channel to contribute to the MBX
+ * combined interrupt.
+ */
+ mdbcw_reg[channel].mdbcw_ctrl = MHU_V3_X_MDBCW_CTRL_MBX_COMB_EN;
+ } else {
+ /* Only PBX and MBX frames are supported. */
+ return MHU_V_3_X_ERR_UNSUPPORTED;
+ }
+
+ return MHU_V_3_X_ERR_NONE;
+}
+
+enum mhu_v3_x_error_t mhu_v3_x_channel_interrupt_disable(
+ const struct mhu_v3_x_dev_t *dev, const uint32_t channel,
+ enum mhu_v3_x_channel_type_t ch_type)
+{
+ enum mhu_v3_x_error_t status;
+
+ union _mhu_v3_x_frame_t *p_mhu;
+ struct _mhu_v3_x_pdbcw_reg_t *pdbcw_reg;
+ struct _mhu_v3_x_mdbcw_reg_t *mdbcw_reg;
+
+ /* Get dev->base if it is valid or return an error if dev is not */
+ status = get_dev_base(dev, &p_mhu);
+ if (status != MHU_V_3_X_ERR_NONE) {
+ return status;
+ }
+
+ /* Only doorbell channel is supported */
+ if (ch_type != MHU_V3_X_CHANNEL_TYPE_DBCH) {
+ return MHU_V_3_X_ERR_UNSUPPORTED;
+ }
+
+ p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
+
+ if (dev->frame == MHU_V3_X_PBX_FRAME) {
+ pdbcw_reg = (struct _mhu_v3_x_pdbcw_reg_t *)
+ &(p_mhu->pbx_frame.pdbcw_page);
+
+ /* Clear channel transfer acknowledge event interrupt */
+ pdbcw_reg[channel].pdbcw_int_clr = MHU_V3_X_PDBCW_INT_X_TFR_ACK;
+
+ /* Disable channel transfer acknowledge event interrupt */
+ pdbcw_reg[channel].pdbcw_int_en &=
+ ~(MHU_V3_X_PDBCW_INT_X_TFR_ACK);
+
+ /*
+ * Disable this doorbell channel from contributing to the PBX
+ * combined interrupt.
+ */
+ pdbcw_reg[channel].pdbcw_ctrl &=
+ ~(MHU_V3_X_PDBCW_CTRL_PBX_COMB_EN);
+ } else if (dev->frame == MHU_V3_X_MBX_FRAME) {
+ mdbcw_reg = (struct _mhu_v3_x_mdbcw_reg_t *)
+ &(p_mhu->mbx_frame.mdbcw_page);
+
+ /*
+ * Disable this doorbell channel from contributing to the MBX
+ * combined interrupt.
+ */
+ mdbcw_reg[channel].mdbcw_ctrl &=
+ ~(MHU_V3_X_MDBCW_CTRL_MBX_COMB_EN);
+ } else {
+ /* Only PBX and MBX frames are supported. */
+ return MHU_V_3_X_ERR_UNSUPPORTED;
+ }
+
+ return MHU_V_3_X_ERR_NONE;
+}
+
+enum mhu_v3_x_error_t mhu_v3_x_channel_interrupt_clear(
+ const struct mhu_v3_x_dev_t *dev, const uint32_t channel,
+ enum mhu_v3_x_channel_type_t ch_type)
+{
+ enum mhu_v3_x_error_t status;
+ union _mhu_v3_x_frame_t *p_mhu;
+ struct _mhu_v3_x_pdbcw_reg_t *pdbcw_reg;
+
+ /* Get dev->base if it is valid or return an error if dev is not */
+ status = get_dev_base(dev, &p_mhu);
+ if (status != MHU_V_3_X_ERR_NONE) {
+ return status;
+ }
+
+ /* Only doorbell channel is supported */
+ if (ch_type != MHU_V3_X_CHANNEL_TYPE_DBCH) {
+ return MHU_V_3_X_ERR_UNSUPPORTED;
+ }
+
+ /*
+ * Only postbox doorbell channel transfer acknowledge interrupt can be
+ * cleared manually.
+ *
+ * To clear MBX interrupt the unmasked status must be cleared using
+ * mhu_v3_x_doorbell_clear.
+ */
+ if (dev->frame != MHU_V3_X_PBX_FRAME) {
+ return MHU_V_3_X_ERR_INVALID_PARAM;
+ }
+
+ p_mhu = (union _mhu_v3_x_frame_t *)dev->base;
+ pdbcw_reg = (struct _mhu_v3_x_pdbcw_reg_t *)&(
+ p_mhu->pbx_frame.pdbcw_page);
+
+ /* Clear channel transfer acknowledge event interrupt */
+ pdbcw_reg[channel].pdbcw_int_clr |= 0x1;
+
+ return MHU_V_3_X_ERR_NONE;
+}
diff --git a/drivers/arm/mhu/mhu_v3_x.h b/drivers/arm/mhu/mhu_v3_x.h
new file mode 100644
index 0000000..a3a1950
--- /dev/null
+++ b/drivers/arm/mhu/mhu_v3_x.h
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MHU_V3_X_H
+#define MHU_V3_X_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+/* MHU Architecture Major Revision 3 */
+#define MHU_MAJOR_REV_V3 U(0x2)
+/* MHU Architecture Minor Revision 0 */
+#define MHU_MINOR_REV_3_0 U(0x0)
+
+/* MHU Architecture Major Revision offset */
+#define MHU_ARCH_MAJOR_REV_OFF U(0x4)
+/* MHU Architecture Major Revision mask */
+#define MHU_ARCH_MAJOR_REV_MASK (U(0xf) << MHU_ARCH_MAJOR_REV_OFF)
+
+/* MHU Architecture Minor Revision offset */
+#define MHU_ARCH_MINOR_REV_OFF U(0x0)
+/* MHU Architecture Minor Revision mask */
+#define MHU_ARCH_MINOR_REV_MASK (U(0xf) << MHU_ARCH_MINOR_REV_OFF)
+
+/* MHUv3 PBX/MBX Operational Request offset */
+#define MHU_V3_OP_REQ_OFF U(0)
+/* MHUv3 PBX/MBX Operational Request */
+#define MHU_V3_OP_REQ (U(1) << MHU_V3_OP_REQ_OFF)
+
+/**
+ * MHUv3 error enumeration types
+ */
+enum mhu_v3_x_error_t {
+ /* No error */
+ MHU_V_3_X_ERR_NONE,
+ /* MHU driver not initialized */
+ MHU_V_3_X_ERR_NOT_INIT,
+ /* MHU driver alreary initialized */
+ MHU_V_3_X_ERR_ALREADY_INIT,
+ /* MHU Revision not supported error */
+ MHU_V_3_X_ERR_UNSUPPORTED_VERSION,
+ /* Operation not supported */
+ MHU_V_3_X_ERR_UNSUPPORTED,
+ /* Invalid parameter */
+ MHU_V_3_X_ERR_INVALID_PARAM,
+ /* General MHU driver error */
+ MHU_V_3_X_ERR_GENERAL,
+};
+
+/**
+ * MHUv3 channel types
+ */
+enum mhu_v3_x_channel_type_t {
+ /* Doorbell channel */
+ MHU_V3_X_CHANNEL_TYPE_DBCH,
+ /* Channel type count */
+ MHU_V3_X_CHANNEL_TYPE_COUNT,
+};
+
+/**
+ * MHUv3 frame types
+ */
+enum mhu_v3_x_frame_t {
+ /* MHUv3 postbox frame */
+ MHU_V3_X_PBX_FRAME,
+ /* MHUv3 mailbox frame */
+ MHU_V3_X_MBX_FRAME,
+};
+
+/**
+ * MHUv3 device structure
+ */
+struct mhu_v3_x_dev_t {
+ /* Base address of the MHUv3 frame */
+ uintptr_t base;
+ /* Type of the MHUv3 frame */
+ enum mhu_v3_x_frame_t frame;
+ /* Minor revision of the MHUv3 */
+ uint32_t subversion;
+ /* Flag to indicate if the MHUv3 is initialized */
+ bool is_initialized;
+};
+
+/**
+ * Initializes the MHUv3
+ *
+ * dev MHU device struct mhu_v3_x_dev_t
+ *
+ * Returns mhu_v3_x_error_t error code
+ */
+enum mhu_v3_x_error_t mhu_v3_x_driver_init(struct mhu_v3_x_dev_t *dev);
+
+/**
+ * Returns the number of channels implemented
+ *
+ * dev MHU device struct mhu_v3_x_dev_t
+ * ch_type MHU channel type mhu_v3_x_channel_type_t
+ * num_ch Pointer to the variable that will store the value
+ *
+ * Returns mhu_v3_x_error_t error code
+ */
+enum mhu_v3_x_error_t mhu_v3_x_get_num_channel_implemented(
+ const struct mhu_v3_x_dev_t *dev, enum mhu_v3_x_channel_type_t ch_type,
+ uint8_t *num_ch);
+
+/**
+ * Clear flags from a doorbell channel
+ *
+ * dev MHU device struct mhu_v3_x_dev_t
+ * channel Doorbell channel number
+ * flags Flags to be cleared from the channel
+ *
+ * Returns mhu_v3_x_error_t error code
+ */
+enum mhu_v3_x_error_t mhu_v3_x_doorbell_clear(const struct mhu_v3_x_dev_t *dev,
+ const uint32_t channel, uint32_t flags);
+
+/**
+ * Write flags to a doorbell channel
+ *
+ * dev MHU device struct mhu_v3_x_dev_t
+ * channel Doorbell channel number
+ * flags Flags to be written to the channel
+ *
+ * Returns mhu_v3_x_error_t error code
+ */
+enum mhu_v3_x_error_t mhu_v3_x_doorbell_write(const struct mhu_v3_x_dev_t *dev,
+ const uint32_t channel, uint32_t flags);
+
+/**
+ * Read value from a doorbell channel
+ *
+ * dev MHU device struct mhu_v3_x_dev_t
+ * channel Doorbell channel number
+ * flags Pointer to the variable that will store the flags read from the
+ * channel
+ *
+ * Returns mhu_v3_x_error_t error code
+ */
+enum mhu_v3_x_error_t mhu_v3_x_doorbell_read(const struct mhu_v3_x_dev_t *dev,
+ const uint32_t channel, uint32_t *flags);
+
+/**
+ * Set bits in a doorbell channel mask which is used to disable interrupts for
+ * received flags corresponding to the mask
+ *
+ * dev MHU device struct mhu_v3_x_dev_t
+ * channel Doorbell channel number
+ * flags Flags to set mask bits in this doorbell channel
+ *
+ * Returns mhu_v3_x_error_t error code
+ */
+enum mhu_v3_x_error_t mhu_v3_x_doorbell_mask_set(
+ const struct mhu_v3_x_dev_t *dev, const uint32_t channel,
+ uint32_t flags);
+
+/**
+ * Clear bits in a doorbell channel mask which is used to disable interrupts
+ * for received flags corresponding to the mask
+ *
+ * dev MHU device struct mhu_v3_x_dev_t
+ * channel Doorbell channel number
+ * flags Flags to clear mask bits in this doorbell channel
+ *
+ * Returns mhu_v3_x_error_t error code
+ */
+enum mhu_v3_x_error_t mhu_v3_x_doorbell_mask_clear(
+ const struct mhu_v3_x_dev_t *dev, const uint32_t channel, uint32_t flags);
+
+/**
+ * Get the mask of a doorbell channel which is used to disable interrupts for
+ * received flags corresponding to the mask
+ *
+ * dev MHU device struct mhu_v3_x_dev_t
+ * channel Doorbell channel number
+ * flags Pointer to the variable that will store the flags read from the
+ * mask value
+ *
+ * Returns mhu_v3_x_error_t error code
+ */
+enum mhu_v3_x_error_t mhu_v3_x_doorbell_mask_get(
+ const struct mhu_v3_x_dev_t *dev, const uint32_t channel, uint32_t *flags);
+
+/**
+ * Enable the channel interrupt
+ *
+ * dev MHU device struct mhu_v3_x_dev_t
+ * channel Doorbell channel number
+ * ch_type MHU channel type mhu_v3_x_channel_type_t
+ *
+ * Returns mhu_v3_x_error_t error code
+ */
+enum mhu_v3_x_error_t mhu_v3_x_channel_interrupt_enable(
+ const struct mhu_v3_x_dev_t *dev, const uint32_t channel,
+ enum mhu_v3_x_channel_type_t ch_type);
+
+/**
+ * Disable the channel interrupt
+ *
+ * dev MHU device struct mhu_v3_x_dev_t
+ * channel Doorbell channel number
+ * ch_type MHU channel type mhu_v3_x_channel_type_t
+ *
+ * Returns mhu_v3_x_error_t error code
+ */
+enum mhu_v3_x_error_t mhu_v3_x_channel_interrupt_disable(
+ const struct mhu_v3_x_dev_t *dev, const uint32_t channel,
+ enum mhu_v3_x_channel_type_t ch_type);
+
+/**
+ * Clear the channel interrupt
+ *
+ * dev MHU device struct mhu_v3_x_dev_t
+ * channel Doorbell channel number
+ * ch_type MHU channel type mhu_v3_x_channel_type_t
+ *
+ * Returns mhu_v3_x_error_t error code
+ */
+enum mhu_v3_x_error_t mhu_v3_x_channel_interrupt_clear(
+ const struct mhu_v3_x_dev_t *dev, const uint32_t channel,
+ enum mhu_v3_x_channel_type_t ch_type);
+
+#endif /* MHU_V3_X_H */
diff --git a/drivers/arm/mhu/mhu_v3_x_private.h b/drivers/arm/mhu/mhu_v3_x_private.h
new file mode 100644
index 0000000..9594a2a
--- /dev/null
+++ b/drivers/arm/mhu/mhu_v3_x_private.h
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MHU_V3_X_PRIVATE_H
+#define MHU_V3_X_PRIVATE_H
+
+#include <stdint.h>
+
+/* Flag for PDBCW Interrupt Transfer Acknowledgment */
+#define MHU_V3_X_PDBCW_INT_X_TFR_ACK 0x1
+
+/* Flag for PDBCW CTRL Postbox combined interrupts enable */
+#define MHU_V3_X_PDBCW_CTRL_PBX_COMB_EN 0x1
+
+/* Flag for MDBCW CTRL Mailbox combined interrupts enable */
+#define MHU_V3_X_MDBCW_CTRL_MBX_COMB_EN 0x1
+
+/**
+ * Postbox control page structure
+ */
+struct _mhu_v3_x_pbx_ctrl_reg_t {
+ /* Offset: 0x000 (R/ ) Postbox Block Identifier */
+ const volatile uint32_t pbx_blk_id;
+ /* Offset: 0x004 (R/ ) Reserved */
+ const volatile uint8_t reserved_0[0x10 - 0x04];
+ /* Offset: 0x010 (R/ ) Postbox Feature Support 0 */
+ const volatile uint32_t pbx_feat_spt0;
+ /* Offset: 0x014 (R/ ) Postbox Feature Support 1 */
+ const volatile uint32_t pbx_feat_spt1;
+ /* Offset: 0x018 (R/ ) Reserved */
+ const volatile uint8_t reserved_1[0x20 - 0x18];
+ /* Offset: 0x020 (R/ ) Postbox Doorbell Channel Configuration 0 */
+ const volatile uint32_t pbx_dbch_cfg0;
+ /* Offset: 0x024 (R/ ) Reserved */
+ const volatile uint8_t reserved_2[0x30 - 0x24];
+ /* Offset: 0x030 (R/ ) Postbox FIFO Channel Configuration 0 */
+ const volatile uint32_t pbx_ffch_cfg0;
+ /* Offset: 0x034 (R/ ) Reserved */
+ const volatile uint8_t reserved_3[0x40 - 0x34];
+ /* Offset: 0x040 (R/ ) Postbox Fast Channel Configuration 0 */
+ const volatile uint32_t pbx_fch_cfg0;
+ /* Offset: 0x044 (R/ ) Reserved */
+ const volatile uint8_t reserved_4[0x100 - 0x44];
+ /* Offset: 0x100 (R/W) Postbox control */
+ volatile uint32_t pbx_ctrl;
+ /* Offset: 0x164 (R/ ) Reserved */
+ const volatile uint8_t reserved_5[0x400 - 0x104];
+ /*
+ * Offset: 0x400 (R/ ) Postbox Doorbell Channel Interrupt Status n,
+ * where n is 0 - 3.
+ */
+ const volatile uint32_t pbx_dbch_int_st[4];
+ /*
+ * Offset: 0x410 (R/ ) Postbox FIFO Channel <n> Interrupt Status n,
+ * where n is 0 - 1.
+ */
+ const volatile uint32_t pbx_ffch_int_st[2];
+ /* Offset: 0x418 (R/ ) Reserved */
+ const uint8_t reserved_6[0xFC8 - 0x418];
+ /* Offset: 0xFC8 (R/ ) Postbox Implementer Identification Register */
+ const volatile uint32_t pbx_iidr;
+ /* Offset: 0xFCC (R/ ) Postbox Architecture Identification Register */
+ const volatile uint32_t pbx_aidr;
+ /*
+ * Offset: 0xFD0 (R/ ) Postbox Implementation Defined Identification
+ * Register n, where n is 0 - 11.
+ */
+ const volatile uint32_t impl_def_id[12];
+};
+
+/**
+ * Postbox doorbell channel window page structure
+ */
+struct _mhu_v3_x_pdbcw_reg_t {
+ /* Offset: 0x000 (R/ ) Postbox Doorbell Channel Window Status */
+ const volatile uint32_t pdbcw_st;
+ /* Offset: 0x004 (R/ ) Reserved */
+ const uint8_t reserved_0[0xC - 0x4];
+ /* Offset: 0x00C ( /W) Postbox Doorbell Channel Window Set */
+ volatile uint32_t pdbcw_set;
+ /*
+ * Offset: 0x010 (R/ ) Postbox Doorbell Channel Window Interrupt Status
+ */
+ const volatile uint32_t pdbcw_int_st;
+ /*
+ * Offset: 0x014 ( /W) Postbox Doorbell Channel Window Interrupt Clear
+ */
+ volatile uint32_t pdbcw_int_clr;
+ /*
+ * Offset: 0x018 (R/W) Postbox Doorbell Channel Window Interrupt Enable
+ */
+ volatile uint32_t pdbcw_int_en;
+ /* Offset: 0x01C (R/W) Postbox Doorbell Channel Window Control */
+ volatile uint32_t pdbcw_ctrl;
+};
+
+/**
+ * Postbox structure
+ */
+struct _mhu_v3_x_pbx {
+ /* Postbox Control */
+ struct _mhu_v3_x_pbx_ctrl_reg_t pbx_ctrl_page;
+ /* Postbox Doorbell Channel Window */
+ struct _mhu_v3_x_pdbcw_reg_t pdbcw_page;
+};
+
+/**
+ * Mailbox control page structure
+ */
+struct _mhu_v3_x_mbx_ctrl_reg_t {
+ /* Offset: 0x000 (R/ ) Mailbox Block Identifier */
+ const volatile uint32_t mbx_blk_id;
+ /* Offset: 0x004 (R/ ) Reserved */
+ const volatile uint8_t reserved_0[0x10 - 0x04];
+ /* Offset: 0x010 (R/ ) Mailbox Feature Support 0 */
+ const volatile uint32_t mbx_feat_spt0;
+ /* Offset: 0x014 (R/ ) Mailbox Feature Support 1 */
+ const volatile uint32_t mbx_feat_spt1;
+ /* Offset: 0x018 (R/ ) Reserved */
+ const volatile uint8_t reserved_1[0x20 - 0x18];
+ /* Offset: 0x020 (R/ ) Mailbox Doorbell Channel Configuration 0 */
+ const volatile uint32_t mbx_dbch_cfg0;
+ /* Offset: 0x024 (R/ ) Reserved */
+ const volatile uint8_t reserved_2[0x30 - 0x24];
+ /* Offset: 0x030 (R/ ) Mailbox FIFO Channel Configuration 0 */
+ const volatile uint32_t mbx_ffch_cfg0;
+ /* Offset: 0x034 (R/ ) Reserved */
+ const volatile uint8_t reserved_4[0x40 - 0x34];
+ /* Offset: 0x040 (R/ ) Mailbox Fast Channel Configuration 0 */
+ const volatile uint32_t mbx_fch_cfg0;
+ /* Offset: 0x044 (R/ ) Reserved */
+ const volatile uint8_t reserved_5[0x100 - 0x44];
+ /* Offset: 0x100 (R/W) Mailbox control */
+ volatile uint32_t mbx_ctrl;
+ /* Offset: 0x104 (R/ ) Reserved */
+ const volatile uint8_t reserved_6[0x140 - 0x104];
+ /* Offset: 0x140 (R/W) Mailbox Fast Channel control */
+ volatile uint32_t mbx_fch_ctrl;
+ /* Offset: 0x144 (R/W) Mailbox Fast Channel Group Interrupt Enable */
+ volatile uint32_t mbx_fcg_int_en;
+ /* Offset: 0x148 (R/ ) Reserved */
+ const volatile uint8_t reserved_7[0x400 - 0x148];
+ /*
+ * Offset: 0x400 (R/ ) Mailbox Doorbell Channel Interrupt Status n,
+ * where n = 0 - 3.
+ */
+ const volatile uint32_t mbx_dbch_int_st[4];
+ /*
+ * Offset: 0x410 (R/ ) Mailbox FIFO Channel Interrupt Status n, where
+ * n = 0 - 1.
+ */
+ const volatile uint32_t mbx_ffch_int_st[2];
+ /* Offset: 0x418 (R/ ) Reserved */
+ const volatile uint8_t reserved_8[0x470 - 0x418];
+ /* Offset: 0x470 (R/ ) Mailbox Fast Channel Group Interrupt Status */
+ const volatile uint32_t mbx_fcg_int_st;
+ /* Offset: 0x474 (R/ ) Reserved */
+ const volatile uint8_t reserved_9[0x480 - 0x474];
+ /*
+ * Offset: 0x480 (R/ ) Mailbox Fast Channel Group <n> Interrupt Status,
+ * where n = 0 - 31.
+ */
+ const volatile uint32_t mbx_fch_grp_int_st[32];
+ /* Offset: 0x500 (R/ ) Reserved */
+ const volatile uint8_t reserved_10[0xFC8 - 0x500];
+ /* Offset: 0xFC8 (R/ ) Mailbox Implementer Identification Register */
+ const volatile uint32_t mbx_iidr;
+ /* Offset: 0xFCC (R/ ) Mailbox Architecture Identification Register */
+ const volatile uint32_t mbx_aidr;
+ /*
+ * Offset: 0xFD0 (R/ ) Mailbox Implementation Defined Identification
+ * Register n, where n is 0 - 11.
+ */
+ const volatile uint32_t impl_def_id[12];
+};
+
+/**
+ * Mailbox doorbell channel window page structure
+ */
+struct _mhu_v3_x_mdbcw_reg_t {
+ /* Offset: 0x000 (R/ ) Mailbox Doorbell Channel Window Status */
+ const volatile uint32_t mdbcw_st;
+ /* Offset: 0x004 (R/ ) Mailbox Doorbell Channel Window Status Masked */
+ const volatile uint32_t mdbcw_st_msk;
+ /* Offset: 0x008 ( /W) Mailbox Doorbell Channel Window Clear */
+ volatile uint32_t mdbcw_clr;
+ /* Offset: 0x00C (R/ ) Reserved */
+ const volatile uint8_t reserved_0[0x10 - 0x0C];
+ /* Offset: 0x010 (R/ ) Mailbox Doorbell Channel Window Mask Status */
+ const volatile uint32_t mdbcw_msk_st;
+ /* Offset: 0x014 ( /W) Mailbox Doorbell Channel Window Mask Set */
+ volatile uint32_t mdbcw_msk_set;
+ /* Offset: 0x018 ( /W) Mailbox Doorbell Channel Window Mask Clear */
+ volatile uint32_t mdbcw_msk_clr;
+ /* Offset: 0x01C (R/W) Mailbox Doorbell Channel Window Control */
+ volatile uint32_t mdbcw_ctrl;
+};
+
+/**
+ * Mailbox structure
+ */
+struct _mhu_v3_x_mbx {
+ /* Mailbox control */
+ struct _mhu_v3_x_mbx_ctrl_reg_t mbx_ctrl_page;
+ /* Mailbox Doorbell Channel Window */
+ struct _mhu_v3_x_mdbcw_reg_t mdbcw_page;
+};
+
+/**
+ * MHUv3 frame type
+ */
+union _mhu_v3_x_frame_t {
+ /* Postbox Frame */
+ struct _mhu_v3_x_pbx pbx_frame;
+ /* Mailbox Frame */
+ struct _mhu_v3_x_mbx mbx_frame;
+};
+
+#endif /* MHU_V3_X_PRIVATE_H */
diff --git a/drivers/arm/mhu/mhu_wrapper_v3_x.c b/drivers/arm/mhu/mhu_wrapper_v3_x.c
new file mode 100644
index 0000000..b3d51e3
--- /dev/null
+++ b/drivers/arm/mhu/mhu_wrapper_v3_x.c
@@ -0,0 +1,462 @@
+/*
+ * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <drivers/arm/mhu.h>
+
+#include "mhu_v3_x.h"
+
+#define MHU_NOTIFY_VALUE U(1234)
+
+#ifndef ALIGN_UP
+#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
+#endif
+
+/*
+ * MHUv3 Wrapper utility macros
+ */
+#define IS_ALIGNED(val, align) (val == ALIGN_UP(val, align))
+
+/*
+ * MHU devices for host:
+ * HSE: Host to Secure Enclave (sender device)
+ * SEH: Secure Enclave to Host (receiver device)
+ */
+struct mhu_v3_x_dev_t mhu_hse_dev = {0, MHU_V3_X_PBX_FRAME};
+struct mhu_v3_x_dev_t mhu_seh_dev = {0, MHU_V3_X_MBX_FRAME};
+
+/* MHUv3 driver error to MHUv3 wrapper error mapping */
+static enum mhu_error_t error_mapping_to_mhu_error_t(enum mhu_v3_x_error_t err)
+{
+ switch (err) {
+ case MHU_V_3_X_ERR_NONE:
+ return MHU_ERR_NONE;
+
+ case MHU_V_3_X_ERR_NOT_INIT:
+ return MHU_ERR_NOT_INIT;
+
+ case MHU_V_3_X_ERR_UNSUPPORTED_VERSION:
+ return MHU_ERR_UNSUPPORTED_VERSION;
+
+ case MHU_V_3_X_ERR_UNSUPPORTED:
+ return MHU_ERR_UNSUPPORTED;
+
+ case MHU_V_3_X_ERR_INVALID_PARAM:
+ return MHU_ERR_INVALID_ARG;
+
+ default:
+ return MHU_ERR_GENERAL;
+ }
+}
+
+static enum mhu_error_t signal_and_wait_for_clear(
+ void *mhu_sender_dev, uint32_t value)
+{
+ enum mhu_v3_x_error_t err;
+ struct mhu_v3_x_dev_t *dev;
+ uint8_t num_channels;
+ uint32_t read_val;
+
+ dev = (struct mhu_v3_x_dev_t *)mhu_sender_dev;
+
+ if ((dev == NULL) || (dev->base == 0)) {
+ return MHU_ERR_INVALID_ARG;
+ }
+
+ err = mhu_v3_x_get_num_channel_implemented(dev,
+ MHU_V3_X_CHANNEL_TYPE_DBCH, &num_channels);
+ if (err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+
+ /* Wait for any pending acknowledgment from transmitter side */
+ do {
+ err = mhu_v3_x_doorbell_read(dev, num_channels - 1, &read_val);
+ if (err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+ } while ((read_val & value) == value);
+
+ /* Use the last channel to notify that a transfer is ready */
+ err = mhu_v3_x_doorbell_write(dev, num_channels - 1, value);
+ if (err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+
+ /* Wait until receiver side acknowledges the transfer */
+ do {
+ err = mhu_v3_x_doorbell_read(dev, num_channels - 1, &read_val);
+ if (err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+ } while ((read_val & value) == value);
+
+ return error_mapping_to_mhu_error_t(MHU_V_3_X_ERR_NONE);
+}
+
+static enum mhu_error_t wait_for_signal(
+ void *mhu_receiver_dev, uint32_t value)
+{
+ enum mhu_v3_x_error_t err;
+ struct mhu_v3_x_dev_t *dev;
+ uint32_t read_val;
+ uint8_t num_channels;
+
+ dev = (struct mhu_v3_x_dev_t *)mhu_receiver_dev;
+
+ if ((dev == NULL) || (dev->base == 0)) {
+ return MHU_ERR_INVALID_ARG;
+ }
+
+ err = mhu_v3_x_get_num_channel_implemented(dev,
+ MHU_V3_X_CHANNEL_TYPE_DBCH, &num_channels);
+ if (err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+
+ do {
+ err = mhu_v3_x_doorbell_read(dev, num_channels - 1, &read_val);
+ if (err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+ } while (read_val != value);
+
+ return error_mapping_to_mhu_error_t(err);
+}
+
+static enum mhu_error_t clear_and_wait_for_signal(
+ void *mhu_receiver_dev, uint32_t value)
+{
+ enum mhu_v3_x_error_t err;
+ struct mhu_v3_x_dev_t *dev;
+ uint8_t num_channels;
+
+ dev = (struct mhu_v3_x_dev_t *)mhu_receiver_dev;
+
+ if ((dev == NULL) || (dev->base == 0)) {
+ return MHU_ERR_INVALID_ARG;
+ }
+
+ err = mhu_v3_x_get_num_channel_implemented(dev,
+ MHU_V3_X_CHANNEL_TYPE_DBCH, &num_channels);
+ if (err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+
+ /* Clear all channels */
+ for (int i = 0; i < num_channels; i++) {
+ err = mhu_v3_x_doorbell_clear(dev, i, UINT32_MAX);
+ if (err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+ }
+
+ return wait_for_signal(mhu_receiver_dev, value);
+}
+
+static enum mhu_error_t validate_buffer_params(uintptr_t buf_addr)
+{
+ if ((buf_addr == 0) || (!IS_ALIGNED(buf_addr, sizeof(uint32_t)))) {
+ return MHU_ERR_INVALID_ARG;
+ }
+
+ return MHU_ERR_NONE;
+}
+
+enum mhu_error_t mhu_init_sender(uintptr_t mhu_sender_base)
+{
+ enum mhu_v3_x_error_t err;
+ struct mhu_v3_x_dev_t *dev;
+ uint8_t num_ch;
+ uint32_t ch;
+
+ assert(mhu_sender_base != (uintptr_t)NULL);
+
+ mhu_hse_dev.base = mhu_sender_base;
+ dev = (struct mhu_v3_x_dev_t *)&mhu_hse_dev;
+
+ /* Initialize MHUv3 */
+ err = mhu_v3_x_driver_init(dev);
+ if (err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+
+ /* Read the number of doorbell channels implemented in the MHU */
+ err = mhu_v3_x_get_num_channel_implemented(
+ dev, MHU_V3_X_CHANNEL_TYPE_DBCH, &num_ch);
+ if (err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ } else if (num_ch < 2) {
+ /* This wrapper requires at least two channels implemented */
+ return MHU_ERR_UNSUPPORTED;
+ }
+
+ /*
+ * The sender polls the postbox doorbell channel window status register
+ * to get notified about successful transfer. So, disable the doorbell
+ * channel's contribution to postbox combined interrupt.
+ *
+ * Also, clear and disable the postbox doorbell channel transfer
+ * acknowledge interrupt.
+ */
+ for (ch = 0; ch < num_ch; ch++) {
+ err = mhu_v3_x_channel_interrupt_disable(
+ dev, ch, MHU_V3_X_CHANNEL_TYPE_DBCH);
+ if (err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+ }
+
+ return MHU_ERR_NONE;
+}
+
+enum mhu_error_t mhu_init_receiver(uintptr_t mhu_receiver_base)
+{
+ enum mhu_v3_x_error_t err;
+ struct mhu_v3_x_dev_t *dev;
+ uint32_t ch;
+ uint8_t num_ch;
+
+ assert(mhu_receiver_base != (uintptr_t)NULL);
+
+ mhu_seh_dev.base = mhu_receiver_base;
+ dev = (struct mhu_v3_x_dev_t *)&mhu_seh_dev;
+
+ /* Initialize MHUv3 */
+ err = mhu_v3_x_driver_init(dev);
+ if (err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+
+ /* Read the number of doorbell channels implemented in the MHU */
+ err = mhu_v3_x_get_num_channel_implemented(
+ dev, MHU_V3_X_CHANNEL_TYPE_DBCH, &num_ch);
+ if (err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ } else if (num_ch < 2) {
+ /* This wrapper requires at least two channels implemented */
+ return MHU_ERR_UNSUPPORTED;
+ }
+
+ /* Mask all channels except the notifying channel */
+ for (ch = 0; ch < (num_ch - 1); ch++) {
+ /* Mask interrupts on channels used for data */
+ err = mhu_v3_x_doorbell_mask_set(dev, ch, UINT32_MAX);
+ if (err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+ }
+
+ /* Unmask doorbell notification channel interrupt */
+ err = mhu_v3_x_doorbell_mask_clear(dev, (num_ch - 1), UINT32_MAX);
+ if (err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+
+ /*
+ * Enable the doorbell channel's contribution to mailbox combined
+ * interrupt.
+ */
+ err = mhu_v3_x_channel_interrupt_enable(dev, (num_ch - 1),
+ MHU_V3_X_CHANNEL_TYPE_DBCH);
+ if (err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(err);
+ }
+
+ return MHU_ERR_NONE;
+}
+
+/*
+ * Public function. See mhu.h
+ *
+ * The basic steps of transferring a message:
+ * 1. Send the size of the payload on Channel 0. It is the very first Bytes of
+ * the transfer. Continue with Channel 1.
+ * 2. Send the payload, writing the channels one after the other (4 Bytes
+ * each). The last available channel is reserved for controlling the
+ * transfer. When the last channel is reached or no more data is left, STOP.
+ * 3. Notify the receiver using the last channel and wait for acknowledge. If
+ * there is still data to transfer, jump to step 2. Otherwise, proceed.
+ *
+ */
+enum mhu_error_t mhu_send_data(const uint8_t *send_buffer, size_t size)
+{
+ enum mhu_error_t mhu_err;
+ enum mhu_v3_x_error_t mhu_v3_err;
+ uint8_t num_channels;
+ uint8_t chan;
+ uint32_t *buffer;
+ struct mhu_v3_x_dev_t *dev;
+
+ if (size == 0) {
+ return MHU_ERR_NONE;
+ }
+
+ dev = (struct mhu_v3_x_dev_t *)&mhu_hse_dev;
+ chan = 0;
+
+ if ((dev == NULL) || (dev->base == 0)) {
+ return MHU_ERR_INVALID_ARG;
+ }
+
+ mhu_err = validate_buffer_params((uintptr_t)send_buffer);
+ if (mhu_err != MHU_ERR_NONE) {
+ return mhu_err;
+ }
+
+ mhu_v3_err = mhu_v3_x_get_num_channel_implemented(dev,
+ MHU_V3_X_CHANNEL_TYPE_DBCH, &num_channels);
+ if (mhu_v3_err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(mhu_v3_err);
+ }
+
+ /* First send the size of the actual message. */
+ mhu_v3_err = mhu_v3_x_doorbell_write(dev, chan, (uint32_t)size);
+ if (mhu_v3_err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(mhu_v3_err);
+ }
+ chan++;
+
+ buffer = (uint32_t *)send_buffer;
+ for (size_t i = 0; i < size; i += 4) {
+ mhu_v3_err = mhu_v3_x_doorbell_write(dev, chan, *buffer++);
+ if (mhu_v3_err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(mhu_v3_err);
+ }
+
+ if (++chan == (num_channels - 1)) {
+ /* Use the last channel to notify transfer complete */
+ mhu_err = signal_and_wait_for_clear(
+ dev, MHU_NOTIFY_VALUE);
+ if (mhu_err != MHU_ERR_NONE) {
+ return mhu_err;
+ }
+ chan = 0;
+ }
+ }
+
+ if (chan != 0) {
+ /* Use the last channel to notify transfer complete */
+ mhu_err = signal_and_wait_for_clear(dev, MHU_NOTIFY_VALUE);
+ if (mhu_err != MHU_ERR_NONE) {
+ return mhu_err;
+ }
+ }
+
+ return MHU_ERR_NONE;
+}
+
+/*
+ * Public function. See mhu.h
+ *
+ * The basic steps of receiving a message:
+ * 1. Read the size of the payload from Channel 0. It is the very first
+ * 4 Bytes of the transfer. Continue with Channel 1.
+ * 2. Receive the payload, read the channels one after the other
+ * (4 Bytes each). The last available channel is reserved for controlling
+ * the transfer.
+ * When the last channel is reached clear all the channels
+ * (also sending an acknowledge on the last channel).
+ * 3. If there is still data to receive wait for a notification on the last
+ * channel and jump to step 2 as soon as it arrived. Otherwise, proceed.
+ *
+ */
+enum mhu_error_t mhu_receive_data(uint8_t *receive_buffer, size_t *size)
+{
+ enum mhu_error_t mhu_err;
+ enum mhu_v3_x_error_t mhu_v3_err;
+ uint32_t msg_len;
+ uint8_t num_channels;
+ uint8_t chan;
+ uint32_t *buffer;
+ struct mhu_v3_x_dev_t *dev;
+
+ dev = (struct mhu_v3_x_dev_t *)&mhu_seh_dev;
+ chan = 0;
+
+ mhu_err = validate_buffer_params((uintptr_t)receive_buffer);
+ if (mhu_err != MHU_ERR_NONE) {
+ return mhu_err;
+ }
+
+ mhu_v3_err = mhu_v3_x_get_num_channel_implemented(dev,
+ MHU_V3_X_CHANNEL_TYPE_DBCH, &num_channels);
+ if (mhu_v3_err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(mhu_v3_err);
+ }
+
+ /* Busy wait for incoming reply */
+ mhu_err = wait_for_signal(dev, MHU_NOTIFY_VALUE);
+ if (mhu_err != MHU_ERR_NONE) {
+ return mhu_err;
+ }
+
+ /* The first word is the length of the actual message. */
+ mhu_v3_err = mhu_v3_x_doorbell_read(dev, chan, &msg_len);
+ if (mhu_v3_err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(mhu_v3_err);
+ }
+ chan++;
+
+ if (*size < msg_len) {
+ /* Message buffer too small */
+ *size = msg_len;
+ return MHU_ERR_BUFFER_TOO_SMALL;
+ }
+
+ buffer = (uint32_t *)receive_buffer;
+ for (size_t i = 0; i < msg_len; i += 4) {
+ mhu_v3_err = mhu_v3_x_doorbell_read(dev, chan, buffer++);
+ if (mhu_v3_err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(mhu_v3_err);
+ }
+
+ /* Only wait for next transfer if still missing data. */
+ if (++chan == (num_channels - 1) && (msg_len - i) > 4) {
+ /* Busy wait for next transfer */
+ mhu_err = clear_and_wait_for_signal(
+ dev, MHU_NOTIFY_VALUE);
+ if (mhu_err != MHU_ERR_NONE) {
+ return mhu_err;
+ }
+ chan = 0;
+ }
+ }
+
+ /* Clear all channels */
+ for (uint8_t i = U(0); i < num_channels; i++) {
+ mhu_v3_err = mhu_v3_x_doorbell_clear(dev, i, UINT32_MAX);
+ if (mhu_v3_err != MHU_V_3_X_ERR_NONE) {
+ return error_mapping_to_mhu_error_t(mhu_v3_err);
+ }
+ }
+
+ *size = msg_len;
+
+ return MHU_ERR_NONE;
+}
+
+size_t mhu_get_max_message_size(void)
+{
+ enum mhu_v3_x_error_t err;
+ uint8_t num_channels;
+
+ err = mhu_v3_x_get_num_channel_implemented(&mhu_seh_dev,
+ MHU_V3_X_CHANNEL_TYPE_DBCH, &num_channels);
+
+ assert(err == MHU_V_3_X_ERR_NONE);
+ assert(num_channels != U(0));
+ /*
+ * Returns only usable size of memory. As one channel is specifically
+ * used to inform about the size of payload, discard it from available
+ * memory size.
+ */
+ return (num_channels - 1) * sizeof(uint32_t);
+}
diff --git a/drivers/arm/rss/rss_comms.mk b/drivers/arm/rss/rss_comms.mk
index c1c994b..0d1e308 100644
--- a/drivers/arm/rss/rss_comms.mk
+++ b/drivers/arm/rss/rss_comms.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2022, Arm Limited. All rights reserved.
+# Copyright (c) 2022-2024, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -13,10 +13,22 @@
rss_comms_protocol_pointer_access.c \
)
+# Default to MHUv2 if PLAT_MHU_VERSION undefined
+PLAT_MHU_VERSION ?= 2
+
+ifeq (${PLAT_MHU_VERSION}, 3)
+RSS_COMMS_SOURCES += $(addprefix drivers/arm/mhu/, \
+ mhu_v3_x.c \
+ mhu_wrapper_v3_x.c \
+ )
+else ifeq (${PLAT_MHU_VERSION}, 2)
RSS_COMMS_SOURCES += $(addprefix drivers/arm/mhu/, \
mhu_v2_x.c \
mhu_wrapper_v2_x.c \
)
+else
+$(error Unsupported MHU version)
+endif
PLAT_INCLUDES += -Idrivers/arm/rss \
-Idrivers/arm/mhu
diff --git a/drivers/rpi3/rng/rpi3_rng.c b/drivers/rpi3/rng/rpi3_rng.c
index b6bf005..16733e1 100644
--- a/drivers/rpi3/rng/rpi3_rng.c
+++ b/drivers/rpi3/rng/rpi3_rng.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -11,6 +11,19 @@
#include <rpi_hw.h>
+#define RPI3_RNG_CTRL_OFFSET ULL(0x00000000)
+#define RPI3_RNG_STATUS_OFFSET ULL(0x00000004)
+#define RPI3_RNG_DATA_OFFSET ULL(0x00000008)
+#define RPI3_RNG_INT_MASK_OFFSET ULL(0x00000010)
+/* Enable/disable RNG */
+#define RPI3_RNG_CTRL_ENABLE U(0x1)
+#define RPI3_RNG_CTRL_DISABLE U(0x0)
+/* Number of currently available words */
+#define RPI3_RNG_STATUS_NUM_WORDS_SHIFT U(24)
+#define RPI3_RNG_STATUS_NUM_WORDS_MASK U(0xFF)
+/* Value to mask interrupts caused by the RNG */
+#define RPI3_RNG_INT_MASK_DISABLE U(0x1)
+
/* Initial amount of values to discard */
#define RNG_WARMUP_COUNT U(0x40000)
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
index c9c3c5f..818fd85 100644
--- a/drivers/st/clk/stm32mp1_clk.c
+++ b/drivers/st/clk/stm32mp1_clk.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2018-2024, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
*/
@@ -2326,6 +2326,17 @@
}
#endif /* STM32MP_SHARED_RESOURCES */
+void stm32mp1_clk_mcuss_protect(bool enable)
+{
+ uintptr_t rcc_base = stm32mp_rcc_base();
+
+ if (enable) {
+ mmio_setbits_32(rcc_base + RCC_TZCR, RCC_TZCR_MCKPROT);
+ } else {
+ mmio_clrbits_32(rcc_base + RCC_TZCR, RCC_TZCR_MCKPROT);
+ }
+}
+
static void sync_earlyboot_clocks_state(void)
{
unsigned int idx;
diff --git a/include/arch/aarch32/arch_features.h b/include/arch/aarch32/arch_features.h
index 734a6b5..b52e4d0 100644
--- a/include/arch/aarch32/arch_features.h
+++ b/include/arch/aarch32/arch_features.h
@@ -159,7 +159,6 @@
static inline bool is_feat_spe_supported(void) { return false; }
static inline bool is_feat_rng_supported(void) { return false; }
static inline bool is_feat_gcs_supported(void) { return false; }
-static inline bool is_feat_mte_supported(void) { return false; }
static inline bool is_feat_mte2_supported(void) { return false; }
static inline bool is_feat_mpam_supported(void) { return false; }
static inline bool is_feat_hcx_supported(void) { return false; }
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index de59d45..7582fc6 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -105,6 +105,10 @@
return ((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_MTE_SHIFT) &
ID_AA64PFR1_EL1_MTE_MASK);
}
+static inline unsigned int is_feat_mte2_present(void)
+{
+ return get_armv8_5_mte_support() >= MTE_IMPLEMENTED_ELX;
+}
static inline bool is_feat_ssbs_present(void)
{
@@ -136,18 +140,14 @@
ID_AA64DFR0_SEBEP_MASK) == SEBEP_IMPLEMENTED;
}
-CREATE_FEATURE_FUNCS(feat_mte, id_aa64pfr1_el1, ID_AA64PFR1_EL1_MTE_SHIFT,
- ENABLE_FEAT_MTE)
-CREATE_FEATURE_FUNCS_VER(feat_mte2, read_feat_mte_id_field, MTE_IMPLEMENTED_ELX,
- ENABLE_FEAT_MTE2)
+CREATE_FEATURE_FUNCS_VER(feat_mte2, get_armv8_5_mte_support, MTE_IMPLEMENTED_ELX,
+ ENABLE_FEAT_MTE2)
CREATE_FEATURE_FUNCS(feat_sel2, id_aa64pfr0_el1, ID_AA64PFR0_SEL2_SHIFT,
ENABLE_FEAT_SEL2)
CREATE_FEATURE_FUNCS(feat_twed, id_aa64mmfr1_el1, ID_AA64MMFR1_EL1_TWED_SHIFT,
ENABLE_FEAT_TWED)
CREATE_FEATURE_FUNCS(feat_fgt, id_aa64mmfr0_el1, ID_AA64MMFR0_EL1_FGT_SHIFT,
ENABLE_FEAT_FGT)
-CREATE_FEATURE_FUNCS(feat_mte_perm, id_aa64pfr2_el1,
- ID_AA64PFR2_EL1_MTEPERM_SHIFT, ENABLE_FEAT_MTE_PERM)
CREATE_FEATURE_FUNCS(feat_ecv, id_aa64mmfr0_el1, ID_AA64MMFR0_EL1_ECV_SHIFT,
ENABLE_FEAT_ECV)
CREATE_FEATURE_FUNCS_VER(feat_ecv_v2, read_feat_ecv_id_field,
diff --git a/include/drivers/rpi3/mailbox/rpi3_mbox.h b/include/drivers/rpi3/mailbox/rpi3_mbox.h
index c107440..33458e3 100644
--- a/include/drivers/rpi3/mailbox/rpi3_mbox.h
+++ b/include/drivers/rpi3/mailbox/rpi3_mbox.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -16,6 +16,22 @@
uint32_t tags[0];
} rpi3_mbox_request_t;
+/* VideoCore -> ARM */
+#define RPI3_MBOX0_READ_OFFSET ULL(0x00000000)
+#define RPI3_MBOX0_PEEK_OFFSET ULL(0x00000010)
+#define RPI3_MBOX0_SENDER_OFFSET ULL(0x00000014)
+#define RPI3_MBOX0_STATUS_OFFSET ULL(0x00000018)
+#define RPI3_MBOX0_CONFIG_OFFSET ULL(0x0000001C)
+/* ARM -> VideoCore */
+#define RPI3_MBOX1_WRITE_OFFSET ULL(0x00000020)
+#define RPI3_MBOX1_PEEK_OFFSET ULL(0x00000030)
+#define RPI3_MBOX1_SENDER_OFFSET ULL(0x00000034)
+#define RPI3_MBOX1_STATUS_OFFSET ULL(0x00000038)
+#define RPI3_MBOX1_CONFIG_OFFSET ULL(0x0000003C)
+/* Mailbox status constants */
+#define RPI3_MBOX_STATUS_FULL_MASK U(0x80000000) /* Set if full */
+#define RPI3_MBOX_STATUS_EMPTY_MASK U(0x40000000) /* Set if empty */
+
#define RPI3_MBOX_BUFFER_SIZE U(256)
/* Constants to perform a request/check the status of a request. */
diff --git a/include/drivers/st/stm32mp1_clk.h b/include/drivers/st/stm32mp1_clk.h
index e2395bc..93ec1c5 100644
--- a/include/drivers/st/stm32mp1_clk.h
+++ b/include/drivers/st/stm32mp1_clk.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2022, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2018-2024, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -32,6 +32,8 @@
void stm32mp1_clk_rcc_regs_lock(void);
void stm32mp1_clk_rcc_regs_unlock(void);
+void stm32mp1_clk_mcuss_protect(bool enable);
+
#ifdef STM32MP_SHARED_RESOURCES
void stm32mp1_register_clock_parents_secure(unsigned long id);
#endif
diff --git a/include/lib/cpus/aarch64/cortex_a720.h b/include/lib/cpus/aarch64/cortex_a720.h
index 47bbbc0..fb27f79 100644
--- a/include/lib/cpus/aarch64/cortex_a720.h
+++ b/include/lib/cpus/aarch64/cortex_a720.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
*/
@@ -13,6 +13,16 @@
#define CORTEX_A720_BHB_LOOP_COUNT U(132)
/*******************************************************************************
+ * CPU Auxiliary Control register 1 specific definitions.
+ ******************************************************************************/
+#define CORTEX_A720_CPUACTLR_EL1 S3_0_C15_C1_0
+
+/*******************************************************************************
+ * CPU Auxiliary Control register 2 specific definitions.
+ ******************************************************************************/
+#define CORTEX_A720_CPUACTLR2_EL1 S3_0_C15_C1_1
+
+/*******************************************************************************
* CPU Extended Control register specific definitions
******************************************************************************/
#define CORTEX_A720_CPUECTLR_EL1 S3_0_C15_C1_4
diff --git a/include/lib/cpus/aarch64/neoverse_poseidon.h b/include/lib/cpus/aarch64/neoverse_poseidon.h
deleted file mode 100644
index 117826d..0000000
--- a/include/lib/cpus/aarch64/neoverse_poseidon.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef NEOVERSE_POSEIDON_H
-#define NEOVERSE_POSEIDON_H
-
-
-#define NEOVERSE_POSEIDON_VNAE_MIDR U(0x410FD830)
-#define NEOVERSE_POSEIDON_V_MIDR U(0x410FD840)
-
-/* Neoverse Poseidon loop count for CVE-2022-23960 mitigation */
-#define NEOVERSE_POSEIDON_BHB_LOOP_COUNT U(132)
-
-/*******************************************************************************
- * CPU Extended Control register specific definitions.
- ******************************************************************************/
-#define NEOVERSE_POSEIDON_CPUECTLR_EL1 S3_0_C15_C1_4
-
-/*******************************************************************************
- * CPU Power Control register specific definitions
- ******************************************************************************/
-#define NEOVERSE_POSEIDON_CPUPWRCTLR_EL1 S3_0_C15_C2_7
-#define NEOVERSE_POSEIDON_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1)
-
-#endif /* NEOVERSE_POSEIDON_H */
diff --git a/include/lib/cpus/aarch64/neoverse_v3.h b/include/lib/cpus/aarch64/neoverse_v3.h
new file mode 100644
index 0000000..e5f75ba
--- /dev/null
+++ b/include/lib/cpus/aarch64/neoverse_v3.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef NEOVERSE_V3_H
+#define NEOVERSE_V3_H
+
+
+#define NEOVERSE_V3_VNAE_MIDR U(0x410FD830)
+#define NEOVERSE_V3_MIDR U(0x410FD840)
+
+/* Neoverse V3 loop count for CVE-2022-23960 mitigation */
+#define NEOVERSE_V3_BHB_LOOP_COUNT U(132)
+
+/*******************************************************************************
+ * CPU Extended Control register specific definitions.
+ ******************************************************************************/
+#define NEOVERSE_V3_CPUECTLR_EL1 S3_0_C15_C1_4
+
+/*******************************************************************************
+ * CPU Power Control register specific definitions
+ ******************************************************************************/
+#define NEOVERSE_V3_CPUPWRCTLR_EL1 S3_0_C15_C2_7
+#define NEOVERSE_V3_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1)
+
+#endif /* NEOVERSE_V3_H */
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index 44efee5..fbaa008 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -141,7 +141,7 @@
#define CTX_TIMER_SYSREGS_END CTX_AARCH32_END
#endif /* NS_TIMER_SWITCH */
-#if ENABLE_FEAT_MTE
+#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))
@@ -151,7 +151,7 @@
#define CTX_MTE_REGS_END (CTX_TIMER_SYSREGS_END + U(0x20))
#else
#define CTX_MTE_REGS_END CTX_TIMER_SYSREGS_END
-#endif /* ENABLE_FEAT_MTE */
+#endif /* ENABLE_FEAT_MTE2 */
/*
* End of system registers.
diff --git a/include/plat/nuvoton/common/npcm845x_arm_def.h b/include/plat/nuvoton/common/npcm845x_arm_def.h
index 5a44907..df3ad24 100644
--- a/include/plat/nuvoton/common/npcm845x_arm_def.h
+++ b/include/plat/nuvoton/common/npcm845x_arm_def.h
@@ -149,7 +149,16 @@
ARM_AP_TZC_DRAM1_SIZE - 1U)
/* Define the Access permissions for Secure peripherals to NS_DRAM */
+#if ARM_CRYPTOCELL_INTEG
+/*
+ * Allow Secure peripheral to read NS DRAM when integrated with CryptoCell.
+ * This is required by CryptoCell to authenticate BL33 which is loaded
+ * into the Non Secure DDR.
+ */
+#define ARM_TZC_NS_DRAM_S_ACCESS TZC_REGION_S_RD
+#else
#define ARM_TZC_NS_DRAM_S_ACCESS TZC_REGION_S_NONE
+#endif /* ARM_CRYPTOCELL_INTEG */
#ifdef SPD_opteed
/*
@@ -310,7 +319,7 @@
BL_RO_DATA_END - BL_RO_DATA_BASE, \
MT_RO_DATA | EL3_PAS)
#else
-#define ARM_MAP_BL_RO MAP_REGION_FLAT( \
+#define ARM_MAP_BL_RO_NOT_USED MAP_REGION_FLAT( \
BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE, \
MT_CODE | EL3_PAS)
#endif /* SEPARATE_CODE_AND_RODATA */
@@ -474,9 +483,9 @@
#define NEW_SRAM_ALLOCATION
#ifdef NEW_SRAM_ALLOCATION
- #define BL31_BASE 0x20001000
+ #define BL31_BASE 0x02000000
#else
- #define BL31_BASE 0x20001000
+ #define BL31_BASE 0x02001000
#endif /* NEW_SRAM_ALLOCATION */
#define BL31_LIMIT BL2_BASE /* PLAT_ARM_MAX_BL31_SIZE */
@@ -502,6 +511,7 @@
* no SPD and no SPM-MM, as they are the only ones that can be used as BL32.
*/
#if defined(SPD_none) && !SPM_MM
+#error BL32_BASE is not defined
#undef BL32_BASE
#endif /* SPD_none && !SPM_MM */
diff --git a/include/plat/nuvoton/common/plat_macros.S b/include/plat/nuvoton/common/plat_macros.S
index 08f9feb..549db39 100644
--- a/include/plat/nuvoton/common/plat_macros.S
+++ b/include/plat/nuvoton/common/plat_macros.S
@@ -41,7 +41,8 @@
* BL31.
*/
.macro plat_crash_print_regs
- /* TODO */
+plat_print_gic_regs
+/*print_cci_regs*/
.endm
#endif /* PLAT_MACROS_S */
diff --git a/lib/cpus/aarch64/cortex_a715.S b/lib/cpus/aarch64/cortex_a715.S
index abd649c..a5be22d 100644
--- a/lib/cpus/aarch64/cortex_a715.S
+++ b/lib/cpus/aarch64/cortex_a715.S
@@ -60,15 +60,18 @@
check_erratum_ls cortex_a715, ERRATUM(2344187), CPU_REV(1, 0)
-/* Errata applies only when Static profiling extension is enabled. */
workaround_reset_start cortex_a715, ERRATUM(2413290), ERRATA_A715_2413290
- /* Apply the workaround by setting CPUACTLR_EL1[58:57] = 0b11. */
+/* Erratum 2413290 workaround is required only if SPE is enabled */
+#if ENABLE_SPE_FOR_NS != 0
+ /* Check if Static profiling extension is implemented or present. */
mrs x1, id_aa64dfr0_el1
ubfx x0, x1, ID_AA64DFR0_PMS_SHIFT, #4
cbz x0, 1f
+ /* Apply the workaround by setting CPUACTLR_EL1[58:57] = 0b11. */
sysreg_bit_set CORTEX_A715_CPUACTLR_EL1, BIT(57)
sysreg_bit_set CORTEX_A715_CPUACTLR_EL1, BIT(58)
1:
+#endif
workaround_reset_end cortex_a715, ERRATUM(2413290)
check_erratum_range cortex_a715, ERRATUM(2413290), CPU_REV(1,0), CPU_REV(1, 0)
diff --git a/lib/cpus/aarch64/cortex_a720.S b/lib/cpus/aarch64/cortex_a720.S
index 4b28fdb..53a1b78 100644
--- a/lib/cpus/aarch64/cortex_a720.S
+++ b/lib/cpus/aarch64/cortex_a720.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
*/
@@ -26,6 +26,28 @@
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(2926083), ERRATA_A720_2926083
+/* Erratum 2926083 workaround is required only if SPE is enabled */
+#if ENABLE_SPE_FOR_NS != 0
+ /* Check if Static profiling extension is implemented or present. */
+ mrs x1, id_aa64dfr0_el1
+ ubfx x0, x1, ID_AA64DFR0_PMS_SHIFT, #4
+ cbz x0, 1f
+ /* Apply the workaround by setting CPUACTLR_EL1[58:57] = 0b11. */
+ sysreg_bit_set CORTEX_A720_CPUACTLR_EL1, BIT(57)
+ sysreg_bit_set CORTEX_A720_CPUACTLR_EL1, BIT(58)
+1:
+#endif
+workaround_reset_end cortex_a720, ERRATUM(2926083)
+
+check_erratum_ls cortex_a720, ERRATUM(2926083), CPU_REV(0, 1)
+
+workaround_reset_start cortex_a720, ERRATUM(2940794), ERRATA_A720_2940794
+ sysreg_bit_set CORTEX_A720_CPUACTLR2_EL1, BIT(37)
+workaround_reset_end cortex_a720, ERRATUM(2940794)
+
+check_erratum_ls cortex_a720, ERRATUM(2940794), CPU_REV(0, 1)
+
workaround_reset_start cortex_a720, CVE(2022, 23960), WORKAROUND_CVE_2022_23960
#if IMAGE_BL31
/*
diff --git a/lib/cpus/aarch64/neoverse_poseidon.S b/lib/cpus/aarch64/neoverse_poseidon.S
deleted file mode 100644
index 54c2ff9..0000000
--- a/lib/cpus/aarch64/neoverse_poseidon.S
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <arch.h>
-#include <asm_macros.S>
-#include <common/bl_common.h>
-#include <neoverse_poseidon.h>
-#include <cpu_macros.S>
-#include <plat_macros.S>
-#include "wa_cve_2022_23960_bhb_vector.S"
-
-/* Hardware handled coherency */
-#if HW_ASSISTED_COHERENCY == 0
-#error "Neoverse Poseidon must be compiled with HW_ASSISTED_COHERENCY enabled"
-#endif
-
-/* 64-bit only core */
-#if CTX_INCLUDE_AARCH32_REGS == 1
-#error "Neoverse Poseidon supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
-#endif
-
-#if WORKAROUND_CVE_2022_23960
- wa_cve_2022_23960_bhb_vector_table NEOVERSE_POSEIDON_BHB_LOOP_COUNT, neoverse_poseidon
-#endif /* WORKAROUND_CVE_2022_23960 */
-
-workaround_reset_start neoverse_poseidon, CVE(2022,23960), WORKAROUND_CVE_2022_23960
-#if IMAGE_BL31
- /*
- * The Neoverse-poseidon generic vectors are overridden to apply errata
- * mitigation on exception entry from lower ELs.
- */
- override_vector_table wa_cve_vbar_neoverse_poseidon
-
-#endif /* IMAGE_BL31 */
-workaround_reset_end neoverse_poseidon, CVE(2022,23960)
-
-check_erratum_chosen neoverse_poseidon, CVE(2022, 23960), WORKAROUND_CVE_2022_23960
-
- /* ---------------------------------------------
- * HW will do the cache maintenance while powering down
- * ---------------------------------------------
- */
-func neoverse_poseidon_core_pwr_dwn
- /* ---------------------------------------------
- * Enable CPU power down bit in power control register
- * ---------------------------------------------
- */
- sysreg_bit_set NEOVERSE_POSEIDON_CPUPWRCTLR_EL1, \
- NEOVERSE_POSEIDON_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
-
- isb
- ret
-endfunc neoverse_poseidon_core_pwr_dwn
-
-cpu_reset_func_start neoverse_poseidon
- /* Disable speculative loads */
- msr SSBS, xzr
-cpu_reset_func_end neoverse_poseidon
-
-errata_report_shim neoverse_poseidon
-
- /* ---------------------------------------------
- * This function provides Neoverse-Poseidon specific
- * register information for crash reporting.
- * It needs to return with x6 pointing to
- * a list of register names in ascii and
- * x8 - x15 having values of registers to be
- * reported.
- * ---------------------------------------------
- */
-.section .rodata.neoverse_poseidon_regs, "aS"
-neoverse_poseidon_regs: /* The ascii list of register names to be reported */
- .asciz "cpuectlr_el1", ""
-
-func neoverse_poseidon_cpu_reg_dump
- adr x6, neoverse_poseidon_regs
- mrs x8, NEOVERSE_POSEIDON_CPUECTLR_EL1
- ret
-endfunc neoverse_poseidon_cpu_reg_dump
-
-declare_cpu_ops neoverse_poseidon, NEOVERSE_POSEIDON_VNAE_MIDR, \
- neoverse_poseidon_reset_func, \
- neoverse_poseidon_core_pwr_dwn
-
-declare_cpu_ops neoverse_poseidon, NEOVERSE_POSEIDON_V_MIDR, \
- neoverse_poseidon_reset_func, \
- neoverse_poseidon_core_pwr_dwn
diff --git a/lib/cpus/aarch64/neoverse_v3.S b/lib/cpus/aarch64/neoverse_v3.S
new file mode 100644
index 0000000..67258c8
--- /dev/null
+++ b/lib/cpus/aarch64/neoverse_v3.S
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <neoverse_v3.h>
+#include <cpu_macros.S>
+#include <plat_macros.S>
+#include "wa_cve_2022_23960_bhb_vector.S"
+
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "Neoverse V3 must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
+/* 64-bit only core */
+#if CTX_INCLUDE_AARCH32_REGS == 1
+#error "Neoverse V3 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
+#endif
+
+#if WORKAROUND_CVE_2022_23960
+ wa_cve_2022_23960_bhb_vector_table NEOVERSE_V3_BHB_LOOP_COUNT, neoverse_v3
+#endif /* WORKAROUND_CVE_2022_23960 */
+
+workaround_reset_start neoverse_v3, CVE(2022,23960), WORKAROUND_CVE_2022_23960
+#if IMAGE_BL31
+ /*
+ * The Neoverse V3 generic vectors are overridden to apply errata
+ * mitigation on exception entry from lower ELs.
+ */
+ override_vector_table wa_cve_vbar_neoverse_v3
+
+#endif /* IMAGE_BL31 */
+workaround_reset_end neoverse_v3, CVE(2022,23960)
+
+check_erratum_chosen neoverse_v3, CVE(2022, 23960), WORKAROUND_CVE_2022_23960
+
+ /* ---------------------------------------------
+ * HW will do the cache maintenance while powering down
+ * ---------------------------------------------
+ */
+func neoverse_v3_core_pwr_dwn
+ /* ---------------------------------------------
+ * Enable CPU power down bit in power control register
+ * ---------------------------------------------
+ */
+ sysreg_bit_set NEOVERSE_V3_CPUPWRCTLR_EL1, \
+ NEOVERSE_V3_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
+
+ isb
+ ret
+endfunc neoverse_v3_core_pwr_dwn
+
+cpu_reset_func_start neoverse_v3
+ /* Disable speculative loads */
+ 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.
+ * It needs to return with x6 pointing to
+ * a list of register names in ascii and
+ * x8 - x15 having values of registers to be
+ * reported.
+ * ---------------------------------------------
+ */
+.section .rodata.neoverse_v3_regs, "aS"
+neoverse_v3_regs: /* The ascii list of register names to be reported */
+ .asciz "cpuectlr_el1", ""
+
+func neoverse_v3_cpu_reg_dump
+ adr x6, neoverse_v3_regs
+ mrs x8, NEOVERSE_V3_CPUECTLR_EL1
+ ret
+endfunc neoverse_v3_cpu_reg_dump
+
+declare_cpu_ops neoverse_v3, NEOVERSE_V3_VNAE_MIDR, \
+ neoverse_v3_reset_func, \
+ neoverse_v3_core_pwr_dwn
+
+declare_cpu_ops neoverse_v3, NEOVERSE_V3_MIDR, \
+ neoverse_v3_reset_func, \
+ neoverse_v3_core_pwr_dwn
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index f5997ae..872f6c7 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -795,7 +795,7 @@
CPU_FLAG_LIST += ERRATA_X3_2372204
# Flag to apply erratum 2615812 workaround on powerdown. This erratum applies
-# to revisions r0p0, r1p0, r1p1 of the Cortex-X3 cpu, it is still open.
+# to revisions r0p0, r1p0, r1p1 of the Cortex-X3 cpu, it is fixed in r1p2.
CPU_FLAG_LIST += ERRATA_X3_2615812
# Flag to apply erratum 2641945 workaround on reset. This erratum applies
@@ -940,6 +940,14 @@
# only to revision r1p0. It is fixed in r1p1.
CPU_FLAG_LIST += ERRATA_A715_2561034
+# 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
+
+# Flag to apply erratum 2940794 workaround during reset. This erratum applies
+# to revisions r0p0 and r0p1. It is fixed in r0p2.
+CPU_FLAG_LIST += ERRATA_A720_2940794
+
# Flag to apply DSU erratum 798953. This erratum applies to DSUs revision r0p0.
# Applying the workaround results in higher DSU power consumption on idle.
CPU_FLAG_LIST += ERRATA_DSU_798953
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 5c8f03c..7a00e47 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -123,8 +123,8 @@
scr_el3 |= get_scr_el3_from_routing_model(SECURE);
#endif
- /* Allow access to Allocation Tags when mte is set*/
- if (is_feat_mte_supported()) {
+ /* Allow access to Allocation Tags when FEAT_MTE2 is implemented and enabled. */
+ if (is_feat_mte2_supported()) {
scr_el3 |= SCR_ATA_BIT;
}
@@ -193,8 +193,10 @@
/* SCR_NS: Set the NS bit */
scr_el3 |= SCR_NS_BIT;
- /* Allow access to Allocation Tags when MTE is implemented. */
- scr_el3 |= SCR_ATA_BIT;
+ /* Allow access to Allocation Tags when FEAT_MTE2 is implemented and enabled. */
+ if (is_feat_mte2_supported()) {
+ scr_el3 |= SCR_ATA_BIT;
+ }
#if !CTX_INCLUDE_PAUTH_REGS
/*
@@ -959,8 +961,8 @@
scr_el3 = read_ctx_reg(get_el3state_ctx(ctx),
CTX_SCR_EL3);
- if (((scr_el3 & SCR_HCE_BIT) != 0U)
- || (el2_implemented != EL_IMPL_NONE)) {
+ if (el2_implemented != EL_IMPL_NONE) {
+
/*
* If context is not being used for EL2, initialize
* HCRX_EL2 with its init value here.
@@ -986,28 +988,32 @@
write_hfgrtr_el2(HFGRTR_EL2_INIT_VAL);
write_hfgwtr_el2(HFGWTR_EL2_INIT_VAL);
}
- }
- if ((scr_el3 & SCR_HCE_BIT) != 0U) {
- /* Use SCTLR_EL1.EE value to initialise sctlr_el2 */
- sctlr_elx = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_SCTLR_EL1);
- sctlr_elx &= SCTLR_EE_BIT;
- sctlr_elx |= SCTLR_EL2_RES1;
+ /* Condition to ensure EL2 is being used. */
+ if ((scr_el3 & SCR_HCE_BIT) != 0U) {
+ /* Use SCTLR_EL1.EE value to initialise sctlr_el2 */
+ sctlr_elx = read_ctx_reg(get_el1_sysregs_ctx(ctx),
+ CTX_SCTLR_EL1);
+ sctlr_elx &= SCTLR_EE_BIT;
+ sctlr_elx |= SCTLR_EL2_RES1;
#if ERRATA_A75_764081
- /*
- * If workaround of errata 764081 for Cortex-A75 is used
- * then set SCTLR_EL2.IESB to enable Implicit Error
- * Synchronization Barrier.
- */
- sctlr_elx |= SCTLR_IESB_BIT;
-#endif
- write_sctlr_el2(sctlr_elx);
- } else if (el2_implemented != EL_IMPL_NONE) {
- init_nonsecure_el2_unused(ctx);
+ /*
+ * If workaround of errata 764081 for Cortex-A75
+ * is used then set SCTLR_EL2.IESB to enable
+ * Implicit Error Synchronization Barrier.
+ */
+ sctlr_elx |= SCTLR_IESB_BIT;
+#endif /* ERRATA_A75_764081 */
+ write_sctlr_el2(sctlr_elx);
+ } else {
+ /*
+ * (scr_el3 & SCR_HCE_BIT==0)
+ * EL2 implemented but unused.
+ */
+ init_nonsecure_el2_unused(ctx);
+ }
}
}
-
cm_el1_sysregs_context_restore(security_state);
cm_set_next_eret_context(security_state);
}
@@ -1271,7 +1277,7 @@
el2_sysregs_context_save_common(el2_sysregs_ctx);
el2_sysregs_context_save_gic(el2_sysregs_ctx);
- if (is_feat_mte_supported()) {
+ if (is_feat_mte2_supported()) {
write_el2_ctx_mte(el2_sysregs_ctx, tfsr_el2, read_tfsr_el2());
}
@@ -1357,7 +1363,7 @@
el2_sysregs_context_restore_common(el2_sysregs_ctx);
el2_sysregs_context_restore_gic(el2_sysregs_ctx);
- if (is_feat_mte_supported()) {
+ if (is_feat_mte2_supported()) {
write_tfsr_el2(read_el2_ctx_mte(el2_sysregs_ctx, tfsr_el2));
}
@@ -1502,12 +1508,12 @@
write_ctx_reg(ctx, CTX_CNTKCTL_EL1, read_cntkctl_el1());
#endif /* NS_TIMER_SWITCH */
-#if ENABLE_FEAT_MTE
+#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_MTE */
+#endif /* ENABLE_FEAT_MTE2 */
}
@@ -1557,12 +1563,12 @@
write_cntkctl_el1(read_ctx_reg(ctx, CTX_CNTKCTL_EL1));
#endif /* NS_TIMER_SWITCH */
-#if ENABLE_FEAT_MTE
+#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_MTE */
+#endif /* ENABLE_FEAT_MTE2 */
}
diff --git a/make_helpers/arch_features.mk b/make_helpers/arch_features.mk
index 643d550..ac47960 100644
--- a/make_helpers/arch_features.mk
+++ b/make_helpers/arch_features.mk
@@ -307,27 +307,16 @@
# registers, by setting SCR_EL3.TRNDR.
ENABLE_FEAT_RNG_TRAP ?= 0
-# Enable Memory Tagging Extension. This must be set to 1 if the platform wants
-# to use this feature in the Secure world and MTE is enabled at ELX.
ifeq ($(CTX_INCLUDE_MTE_REGS),1)
- $(warning CTX_INCLUDE_MTE_REGS option is deprecated use ENABLE_FEAT_MTE, Enabling ENABLE_FEAT_MTE)
- ENABLE_FEAT_MTE ?= 1
+ $(warning CTX_INCLUDE_MTE_REGS option is deprecated, Check ENABLE_FEAT_MTE2 usage)
endif
-ifeq (${ARCH},aarch32)
- ifneq ($(or $(ENABLE_FEAT_MTE),0),0)
- $(error ENABLE_FEAT_MTE is not supported for AArch32)
- endif
+ifeq ($(ENABLE_FEAT_MTE),1)
+ $(warning ENABLE_FEAT_MTE option is deprecated, Check ENABLE_FEAT_MTE2 usage)
endif
-ENABLE_FEAT_MTE ?= 0
-ENABLE_FEAT_MTE2 ?= 0
-
-# Add a error message to indicate incorrect MTE2 selection without MTE enabled.
-ifneq ($(ENABLE_FEAT_MTE2),0)
- ifeq ($(ENABLE_FEAT_MTE),0)
- $(error ENABLE_FEAT_MTE2 is not supported without enabling ENABLE_FEAT_MTE)
- endif
-endif
+# Enable FEAT_MTE2. This must be set to 1 if the platform wants
+# to use this feature and is enabled at ELX.
+ENABLE_FEAT_MTE2 ?= 0
#----
# 8.6
@@ -352,9 +341,6 @@
# 8.9
#----
-# Flag to enable NoTagAccess memory region attribute for stage 2 of translation.
-ENABLE_FEAT_MTE_PERM ?= 0
-
# Flag to enable access to Stage 2 Permission Indirection (FEAT_S2PIE).
ENABLE_FEAT_S2PIE ?= 0
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 569ac3f..6b995af 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -76,7 +76,6 @@
ENABLE_FEAT_CSV2_3 := 2
ENABLE_FEAT_DIT := 2
ENABLE_FEAT_PAN := 2
-ENABLE_FEAT_MTE_PERM := 2
ENABLE_FEAT_VHE := 2
CTX_INCLUDE_NEVE_REGS := 2
ENABLE_FEAT_SEL2 := 2
@@ -205,6 +204,7 @@
lib/cpus/aarch64/cortex_a78c.S \
lib/cpus/aarch64/cortex_a710.S \
lib/cpus/aarch64/cortex_a715.S \
+ lib/cpus/aarch64/cortex_a720.S \
lib/cpus/aarch64/neoverse_n_common.S \
lib/cpus/aarch64/neoverse_n1.S \
lib/cpus/aarch64/neoverse_n2.S \
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
index 2f23d80..b30e40c 100644
--- a/plat/arm/board/tc/platform.mk
+++ b/plat/arm/board/tc/platform.mk
@@ -40,7 +40,6 @@
ifeq (${SPD},spmd)
SPMD_SPM_AT_SEL2 := 1
- ENABLE_FEAT_MTE := 1
CTX_INCLUDE_PAUTH_REGS := 1
endif
diff --git a/plat/common/aarch64/crash_console_helpers.S b/plat/common/aarch64/crash_console_helpers.S
index 75b4208..1a50091 100644
--- a/plat/common/aarch64/crash_console_helpers.S
+++ b/plat/common/aarch64/crash_console_helpers.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2024, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -100,7 +100,7 @@
* int plat_crash_console_putc(char c)
* Prints the character on all consoles registered with the console
* framework that have CONSOLE_FLAG_CRASH set. Note that this is only
- * helpful for crashes that occur after the platform intialization code
+ * helpful for crashes that occur after the platform initialization code
* has registered a console. Platforms using this implementation need to
* ensure that all console drivers they use that have the CRASH flag set
* support this (i.e. are written in assembly and comply to the register
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
index dc9dd59..bff8fb4 100644
--- a/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
+++ b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
@@ -77,11 +77,31 @@
static const struct imx_csu_cfg csu_cfg[] = {
/* peripherals csl setting */
- CSU_CSLx(0x1, CSU_SEC_LEVEL_0, UNLOCKED),
+ CSU_CSLx(CSU_CSL_RDC, CSU_SEC_LEVEL_3, LOCKED),
+ CSU_CSLx(CSU_CSL_TZASC, CSU_SEC_LEVEL_5, LOCKED),
+ CSU_CSLx(CSU_CSL_CSU, CSU_SEC_LEVEL_5, LOCKED),
/* master HP0~1 */
/* SA setting */
+ CSU_SA(CSU_SA_M4, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_SDMA1, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_PCIE_CTRL1, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_USB1, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_USB2, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_VPU, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_GPU, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_APBHDMA, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_ENET, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_USDHC1, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_USDHC2, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_USDHC3, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_HUGO, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_DAP, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_SDMA2, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_SDMA3, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_LCDIF, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_CSI, NON_SEC_ACCESS, LOCKED),
/* HP control setting */
diff --git a/plat/imx/imx8m/imx8mm/include/imx_sec_def.h b/plat/imx/imx8m/imx8mm/include/imx_sec_def.h
index 6215983..d53c922 100644
--- a/plat/imx/imx8m/imx8mm/include/imx_sec_def.h
+++ b/plat/imx/imx8m/imx8mm/include/imx_sec_def.h
@@ -213,4 +213,26 @@
CSU_CSL_CAAM = 114,
};
+enum csu_sa_idx {
+ CSU_SA_M4 = 1,
+ CSU_SA_SDMA1 = 2,
+ CSU_SA_PCIE_CTRL1 = 3,
+ CSU_SA_USB1 = 4,
+ CSU_SA_USB2 = 5,
+ CSU_SA_VPU = 6,
+ CSU_SA_GPU = 7,
+ CSU_SA_APBHDMA = 8,
+ CSU_SA_ENET = 9,
+ CSU_SA_USDHC1 = 10,
+ CSU_SA_USDHC2 = 11,
+ CSU_SA_USDHC3 = 12,
+ CSU_SA_HUGO = 13,
+ CSU_SA_DAP = 14,
+ CSU_SA_SDMA2 = 15,
+ CSU_SA_CAAM = 16,
+ CSU_SA_SDMA3 = 17,
+ CSU_SA_LCDIF = 18,
+ CSU_SA_CSI = 19,
+};
+
#endif /* IMX_SEC_DEF_H */
diff --git a/plat/imx/imx8m/imx8mn/include/imx_sec_def.h b/plat/imx/imx8m/imx8mn/include/imx_sec_def.h
index 0ef14a9..83c5fa9 100644
--- a/plat/imx/imx8m/imx8mn/include/imx_sec_def.h
+++ b/plat/imx/imx8m/imx8mn/include/imx_sec_def.h
@@ -207,4 +207,23 @@
CSU_CSL_OCRAM_S = 119,
};
+enum csu_sa_idx {
+ CSU_SA_M7 = 1,
+ CSU_SA_SDMA1 = 2,
+ CSU_SA_USB1 = 4,
+ CSU_SA_GPU = 7,
+ CSU_SA_APBHDMA = 8,
+ CSU_SA_ENET1 = 9,
+ CSU_SA_USDHC1 = 10,
+ CSU_SA_USDHC2 = 11,
+ CSU_SA_USDHC3 = 12,
+ CSU_SA_HUGO = 13,
+ CSU_SA_DAP = 14,
+ CSU_SA_SDMA2 = 15,
+ CSU_SA_CAAM = 16,
+ CSU_SA_SDMA3 = 17,
+ CSU_SA_LCDIF = 18,
+ CSU_SA_ISI = 19,
+};
+
#endif /* IMX_SEC_DEF_H */
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c b/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c
index 43fa064..8e35219 100644
--- a/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c
+++ b/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c
@@ -63,12 +63,45 @@
static const struct imx_csu_cfg csu_cfg[] = {
/* peripherals csl setting */
- CSU_CSLx(CSU_CSL_OCRAM, CSU_SEC_LEVEL_2, UNLOCKED),
- CSU_CSLx(CSU_CSL_OCRAM_S, CSU_SEC_LEVEL_2, UNLOCKED),
+ CSU_CSLx(CSU_CSL_OCRAM, CSU_SEC_LEVEL_2, LOCKED),
+ CSU_CSLx(CSU_CSL_OCRAM_S, CSU_SEC_LEVEL_2, LOCKED),
+ CSU_CSLx(CSU_CSL_RDC, CSU_SEC_LEVEL_3, LOCKED),
+ CSU_CSLx(CSU_CSL_TZASC, CSU_SEC_LEVEL_5, LOCKED),
+ CSU_CSLx(CSU_CSL_CSU, CSU_SEC_LEVEL_5, LOCKED),
/* master HP0~1 */
/* SA setting */
+ CSU_SA(CSU_SA_M7, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_SDMA1, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_PCIE_CTRL1, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_USB1, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_USB2, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_APB_HDMA, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_ENET1, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_USDHC1, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_USDHC2, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_USDHC3, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_HUGO, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_DAP, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_SDMA2, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_SDMA3, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_LCDIF1, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_ISI, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_NPU, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_LCDIF2, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_HDMI_TX, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_ENET2, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_GPU3D, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_GPU2D, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_VPU_G1, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_VPU_G2, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_VPU_VC8000E, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_AUDIO_EDMA, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_ISP1, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_ISP2, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_DEWARP, NON_SEC_ACCESS, LOCKED),
+ CSU_SA(CSU_SA_GIC500, NON_SEC_ACCESS, LOCKED),
/* HP control setting */
diff --git a/plat/imx/imx8m/imx8mp/include/imx_sec_def.h b/plat/imx/imx8m/imx8mp/include/imx_sec_def.h
index ba248b5..1ba3033 100644
--- a/plat/imx/imx8m/imx8mp/include/imx_sec_def.h
+++ b/plat/imx/imx8m/imx8mp/include/imx_sec_def.h
@@ -269,6 +269,41 @@
CSU_CSL_OCRAM_A = 113,
CSU_CSL_OCRAM = 118,
CSU_CSL_OCRAM_S = 119,
+ CSU_CSL_VPU = 120,
+};
+
+enum csu_sa_idx {
+ CSU_SA_M7 = 1,
+ CSU_SA_SDMA1 = 2,
+ CSU_SA_PCIE_CTRL1 = 3,
+ CSU_SA_USB1 = 4,
+ CSU_SA_USB2 = 6,
+ CSU_SA_APB_HDMA = 8,
+ CSU_SA_ENET1 = 9,
+ CSU_SA_USDHC1 = 10,
+ CSU_SA_USDHC2 = 11,
+ CSU_SA_USDHC3 = 12,
+ CSU_SA_HUGO = 13,
+ CSU_SA_DAP = 14,
+ CSU_SA_SDMA2 = 15,
+ CSU_SA_CAAM = 16,
+ CSU_SA_SDMA3 = 17,
+ CSU_SA_LCDIF1 = 18,
+ CSU_SA_ISI = 19,
+ CSU_SA_NPU = 20,
+ CSU_SA_LCDIF2 = 21,
+ CSU_SA_HDMI_TX = 22,
+ CSU_SA_ENET2 = 23,
+ CSU_SA_GPU3D = 24,
+ CSU_SA_GPU2D = 25,
+ CSU_SA_VPU_G1 = 26,
+ CSU_SA_VPU_G2 = 27,
+ CSU_SA_VPU_VC8000E = 28,
+ CSU_SA_AUDIO_EDMA = 29,
+ CSU_SA_ISP1 = 30,
+ CSU_SA_ISP2 = 31,
+ CSU_SA_DEWARP = 32,
+ CSU_SA_GIC500 = 33,
};
#endif /* IMX_SEC_DEF_H */
diff --git a/plat/imx/imx8m/include/imx8m_csu.h b/plat/imx/imx8m/include/imx8m_csu.h
index dc634ed..3851e91 100644
--- a/plat/imx/imx8m/include/imx8m_csu.h
+++ b/plat/imx/imx8m/include/imx8m_csu.h
@@ -20,6 +20,9 @@
#define CSU_SEC_LEVEL_6 0x03
#define CSU_SEC_LEVEL_7 0x0
+#define SEC_ACCESS 0x0
+#define NON_SEC_ACCESS 0x1
+
#define LOCKED 0x1
#define UNLOCKED 0x0
@@ -27,11 +30,11 @@
#define CSLx_LOCK(x) ((0x1 << (((x) % 2) * 16 + 8)))
#define CSLx_CFG(x, n) ((x) << (((n) % 2) * 16))
-#define CSU_HP_REG(x) (IMX_CSU_BASE + ((x) / 16) * 4 + 0x200)
+#define CSU_HP_REG(x) (IMX_CSU_BASE + (((x) / 16) * 4) + 0x200)
#define CSU_HP_LOCK(x) ((0x1 << (((x) % 16) * 2 + 1)))
#define CSU_HP_CFG(x, n) ((x) << (((n) % 16) * 2))
-#define CSU_SA_REG(x) (IMX_CSU_BASE + 0x218)
+#define CSU_SA_REG(x) (IMX_CSU_BASE + (((x) / 16) * 4) + 0x218)
#define CSU_SA_LOCK(x) ((0x1 << (((x) % 16) * 2 + 1)))
#define CSU_SA_CFG(x, n) ((x) << (((n) % 16) * 2))
diff --git a/plat/imx/imx8ulp/xrdc/xrdc_config.h b/plat/imx/imx8ulp/xrdc/xrdc_config.h
index 25edd37..d2af55c 100644
--- a/plat/imx/imx8ulp/xrdc/xrdc_config.h
+++ b/plat/imx/imx8ulp/xrdc/xrdc_config.h
@@ -116,13 +116,15 @@
struct xrdc_pac_msc_config imx8ulp_pdac[] = {
{ 0, PAC_SLOT_ALL, {0, 7, 0, 0, 0, 0, 0, 7} }, /* PAC0 */
+ { 0, 44, {0, 7, 7, 0, 0, 0, 0, 7} }, /* PAC0 slot 44 for CGC1 */
{ 0, 36, {0, 0, 0, 0, 0, 0, 7, 7} }, /* PAC0 slot 36 for CMC1 */
{ 0, 41, {0, 0, 0, 0, 0, 0, 7, 7} }, /* PAC0 slot 41 for SIM_AD */
{ 1, PAC_SLOT_ALL, {0, 7, 0, 0, 0, 0, 0, 7} }, /* PAC1 */
- { 1, 0, {0, 7, 0, 0, 0, 0, 7, 7} }, /* PAC1 slot 0 for PCC4 */
+ { 1, 0, {0, 7, 7, 0, 0, 0, 7, 7} }, /* PAC1 slot 0 for PCC4 */
{ 1, 6, {0, 7, 7, 0, 0, 0, 0, 7} }, /* PAC1 slot 6 for LPUART6 */
+ { 1, 7, {0, 7, 7, 0, 0, 0, 0, 7} }, /* PAC1 slot 7 for LPUART7 */
{ 1, 9, {0, 7, 7, 7, 0, 0, 0, 7} }, /* SAI5 for HIFI4 and eDMA2 */
- { 1, 12, {0, 7, 0, 0, 0, 0, 7, 7} }, /* PAC1 slot 12 for IOMUXC1 */
+ { 1, 12, {0, 7, 7, 0, 0, 0, 7, 7} }, /* PAC1 slot 12 for IOMUXC1 */
{ 2, PAC_SLOT_ALL, {7, 7, 7, 7, 0, 0, 7, 7} }, /* PAC2 */
};
diff --git a/plat/intel/soc/agilex5/bl31_plat_setup.c b/plat/intel/soc/agilex5/bl31_plat_setup.c
index 0d4f2cc..8d3928f 100644
--- a/plat/intel/soc/agilex5/bl31_plat_setup.c
+++ b/plat/intel/soc/agilex5/bl31_plat_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2024, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -182,7 +182,7 @@
/*******************************************************************************
* Perform the very early platform specific architectural setup here. At the
- * moment this is only intializes the mmu in a quick and dirty way.
+ * moment this is only initializes the mmu in a quick and dirty way.
******************************************************************************/
void bl31_plat_arch_setup(void)
{
diff --git a/plat/nuvoton/common/nuvoton_helpers.S b/plat/nuvoton/common/nuvoton_helpers.S
index 09035a1..9c78815 100644
--- a/plat/nuvoton/common/nuvoton_helpers.S
+++ b/plat/nuvoton/common/nuvoton_helpers.S
@@ -151,9 +151,9 @@
*/
bl plat_my_core_pos
lsl x0, x0, #3
- mov x8, x0
mov_imm x2, PLAT_NPCM_TM_HOLD_BASE
add x0, x0, x2
+ mov x8, x0
mov_imm x2, PLAT_NPCM_TRUSTED_NOTIFICATION_BASE
add x8, x8, x2
/*
diff --git a/plat/nuvoton/npcm845x/npcm845x_bl31_setup.c b/plat/nuvoton/npcm845x/npcm845x_bl31_setup.c
index 08448db..b8371d8 100644
--- a/plat/nuvoton/npcm845x/npcm845x_bl31_setup.c
+++ b/plat/nuvoton/npcm845x/npcm845x_bl31_setup.c
@@ -47,6 +47,20 @@
BL31_END - BL31_START, \
MT_MEMORY | MT_RW | EL3_PAS)
+#if RECLAIM_INIT_CODE
+IMPORT_SYM(unsigned long, __INIT_CODE_START__, BL_INIT_CODE_BASE);
+IMPORT_SYM(unsigned long, __INIT_CODE_END__, BL_CODE_END_UNALIGNED);
+
+#define BL_INIT_CODE_END ((BL_CODE_END_UNALIGNED + PAGE_SIZE - 1) & \
+ ~(PAGE_SIZE - 1))
+
+#define MAP_BL_INIT_CODE MAP_REGION_FLAT( \
+ BL_INIT_CODE_BASE, \
+ BL_INIT_CODE_END - \
+ BL_INIT_CODE_BASE, \
+ MT_CODE | MT_SECURE)
+#endif /* RECLAIM_INIT_CODE */
+
#if SEPARATE_NOBITS_REGION
#define MAP_BL31_NOBITS MAP_REGION_FLAT( \
BL31_NOBITS_BASE, \
@@ -117,6 +131,7 @@
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
u_register_t arg2, u_register_t arg3)
{
+ arg0 = arg1 = arg2 = arg3 = 0;
#if RESET_TO_BL31
void *from_bl2 = (void *)arg0;
void *plat_params_from_bl2 = (void *)arg3;
@@ -309,26 +324,23 @@
{
const mmap_region_t bl_regions[] = {
MAP_BL31_TOTAL,
-#if SEPARATE_NOBITS_REGION
- MAP_BL31_NOBITS,
-#endif /* SEPARATE_NOBITS_REGION */
+#if RECLAIM_INIT_CODE
+ MAP_BL_INIT_CODE_NOT_USED,
+#endif /* RECLAIM_INIT_CODE */
ARM_MAP_BL_RO,
-#if USE_ROMLIB
- ARM_MAP_ROMLIB_CODE,
- ARM_MAP_ROMLIB_DATA,
-#endif /* USE_ROMLIB */
#if USE_COHERENT_MEM
ARM_MAP_BL_COHERENT_RAM,
#endif /* USE_COHERENT_MEM */
ARM_MAP_SHARED_RAM,
#ifdef SECONDARY_BRINGUP
- ARM_MAP_NS_DRAM1,
+ ARM_MAP_NS_DRAM1_NO_USED,
#ifdef BL32_BASE
- ARM_MAP_BL32_CORE_MEM
+ ARM_MAP_BL32_CORE_MEM_NO_USED
#endif /* BL32_BASE */
#endif /* SECONDARY_BRINGUP */
{0}
};
setup_page_tables(bl_regions, plat_arm_get_mmap());
enable_mmu_el3(0U);
+ NOTICE("Done enabling MMU\n");
}
diff --git a/plat/nuvoton/npcm845x/platform.mk b/plat/nuvoton/npcm845x/platform.mk
index 92c7e2f..1959aac 100644
--- a/plat/nuvoton/npcm845x/platform.mk
+++ b/plat/nuvoton/npcm845x/platform.mk
@@ -12,6 +12,7 @@
SPMD_SPM_AT_SEL2 := 0
#temporary until the RAM size is reduced
USE_COHERENT_MEM := 1
+INIT_UNUSED_NS_EL2 := 1
$(eval $(call add_define,RESET_TO_BL31))
@@ -21,12 +22,29 @@
# Trusted DRAM (if available) or the TZC secured area of DRAM.
# TZC secured DRAM is the default.
+ARM_TSP_RAM_LOCATION ?= dram
+
+ifeq (${ARM_TSP_RAM_LOCATION}, tsram)
+ARM_TSP_RAM_LOCATION_ID = ARM_TRUSTED_SRAM_ID
+else ifeq (${ARM_TSP_RAM_LOCATION}, tdram)
+ARM_TSP_RAM_LOCATION_ID = ARM_TRUSTED_DRAM_ID
+else ifeq (${ARM_TSP_RAM_LOCATION}, dram)
+ARM_TSP_RAM_LOCATION_ID = ARM_DRAM_ID
+else
+$(error "Unsupported ARM_TSP_RAM_LOCATION value")
+endif
+
+# Process flags
# Process ARM_BL31_IN_DRAM flag
ARM_BL31_IN_DRAM := 0
$(eval $(call assert_boolean,ARM_BL31_IN_DRAM))
$(eval $(call add_define,ARM_BL31_IN_DRAM))
+else
+ARM_TSP_RAM_LOCATION_ID = ARM_TRUSTED_SRAM_ID
endif
+$(eval $(call add_define,ARM_TSP_RAM_LOCATION_ID))
+
# For the original power-state parameter format, the State-ID can be encoded
# according to the recommended encoding or zero. This flag determines which
# State-ID encoding to be parsed.
@@ -140,11 +158,25 @@
endif
endif
+# Disable ARM Cryptocell by default
+ARM_CRYPTOCELL_INTEG := 0
+$(eval $(call assert_boolean,ARM_CRYPTOCELL_INTEG))
+$(eval $(call add_define,ARM_CRYPTOCELL_INTEG))
+
# Enable PIE support for RESET_TO_BL31 case
ifeq (${RESET_TO_BL31},1)
ENABLE_PIE := 1
endif
+# CryptoCell integration relies on coherent buffers for passing data from
+# the AP CPU to the CryptoCell
+
+ifeq (${ARM_CRYPTOCELL_INTEG},1)
+ifeq (${USE_COHERENT_MEM},0)
+$(error "ARM_CRYPTOCELL_INTEG needs USE_COHERENT_MEM to be set.")
+endif
+endif
+
PLAT_INCLUDES := -Iinclude/plat/nuvoton/npcm845x \
-Iinclude/plat/nuvoton/common \
-Iinclude/drivers/nuvoton/npcm845x \
@@ -287,7 +319,8 @@
# Pointer Authentication sources
ifeq (${ENABLE_PAUTH}, 1)
-PLAT_BL_COMMON_SOURCES += plat/arm/common/aarch64/arm_pauth.c
+PLAT_BL_COMMON_SOURCES += plat/arm/common/aarch64/arm_pauth.c \
+ lib/extensions/pauth/pauth_helpers.S
endif
ifeq (${SPD},spmd)
@@ -325,7 +358,11 @@
$(eval $(call TOOL_ADD_IMG,ns_bl2u,--fwu,FWU_))
# We expect to locate the *.mk files under the directories specified below
+ifeq (${ARM_CRYPTOCELL_INTEG},0)
CRYPTO_LIB_MK := drivers/auth/mbedtls/mbedtls_crypto.mk
+else
+CRYPTO_LIB_MK := drivers/auth/cryptocell/cryptocell_crypto.mk
+endif
IMG_PARSER_LIB_MK := drivers/auth/mbedtls/mbedtls_x509.mk
@@ -336,6 +373,12 @@
include ${IMG_PARSER_LIB_MK}
endif
+ifeq (${RECLAIM_INIT_CODE}, 1)
+ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1)
+$(error "To reclaim init code xlat tables v2 must be used")
+endif
+endif
+
ifeq (${MEASURED_BOOT},1)
MEASURED_BOOT_MK := drivers/measured_boot/measured_boot.mk
$(info Including ${MEASURED_BOOT_MK})
@@ -352,3 +395,6 @@
DEBUG_CONSOLE ?= 0
$(eval $(call add_define,DEBUG_CONSOLE))
+
+$(eval $(call add_define,ARM_TSP_RAM_LOCATION_ID))
+
diff --git a/plat/rpi/rpi4/aarch64/armstub8_header.S b/plat/rpi/common/aarch64/armstub8_header.S
similarity index 89%
rename from plat/rpi/rpi4/aarch64/armstub8_header.S
rename to plat/rpi/common/aarch64/armstub8_header.S
index 246358d..dc1e54e 100644
--- a/plat/rpi/rpi4/aarch64/armstub8_header.S
+++ b/plat/rpi/common/aarch64/armstub8_header.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
diff --git a/plat/rpi/common/aarch64/plat_helpers.S b/plat/rpi/common/aarch64/plat_helpers.S
index f045e21..18873af 100644
--- a/plat/rpi/common/aarch64/plat_helpers.S
+++ b/plat/rpi/common/aarch64/plat_helpers.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -27,10 +27,19 @@
*
* This function uses the plat_rpi3_calc_core_pos()
* definition to get the index of the calling CPU.
+ *
+ * When MT is set, lowest affinity represents the thread ID.
+ * Since we only support one thread per core, discard this field
+ * so cluster and core IDs go back into Aff1 and Aff0 respectively.
+ * The upper bits are also affected, but plat_rpi3_calc_core_pos()
+ * does not use them.
* -----------------------------------------------------
*/
func plat_my_core_pos
mrs x0, mpidr_el1
+ tst x0, #MPIDR_MT_MASK
+ lsr x1, x0, #MPIDR_AFFINITY_BITS
+ csel x0, x1, x0, ne
b plat_rpi3_calc_core_pos
endfunc plat_my_core_pos
@@ -164,10 +173,16 @@
* ---------------------------------------------
*/
func plat_crash_console_init
- mov_imm x0, PLAT_RPI_MINI_UART_BASE
+ mov_imm x0, PLAT_RPI_CRASH_UART_BASE
+#if PLAT_RPI_CRASH_UART_BASE == PLAT_RPI_PL011_UART_BASE
+ mov_imm x1, RPI4_PL011_UART_CLOCK
+ mov_imm x2, PLAT_RPI_UART_BAUDRATE
+ b console_pl011_core_init
+#else
mov x1, xzr
mov x2, xzr
b console_16550_core_init
+#endif
endfunc plat_crash_console_init
/* ---------------------------------------------
@@ -178,8 +193,12 @@
* ---------------------------------------------
*/
func plat_crash_console_putc
- mov_imm x1, PLAT_RPI_MINI_UART_BASE
+ mov_imm x1, PLAT_RPI_CRASH_UART_BASE
+#if PLAT_RPI_CRASH_UART_BASE == PLAT_RPI_PL011_UART_BASE
+ b console_pl011_core_putc
+#else
b console_16550_core_putc
+#endif
endfunc plat_crash_console_putc
/* ---------------------------------------------
@@ -191,8 +210,12 @@
* ---------------------------------------------
*/
func plat_crash_console_flush
- mov_imm x0, PLAT_RPI_MINI_UART_BASE
+ mov_imm x0, PLAT_RPI_CRASH_UART_BASE
+#if PLAT_RPI_CRASH_UART_BASE == PLAT_RPI_PL011_UART_BASE
+ b console_pl011_core_flush
+#else
b console_16550_core_flush
+#endif
endfunc plat_crash_console_flush
/* ---------------------------------------------
diff --git a/plat/rpi/rpi4/include/plat_macros.S b/plat/rpi/common/include/plat_macros.S
similarity index 87%
rename from plat/rpi/rpi4/include/plat_macros.S
rename to plat/rpi/common/include/plat_macros.S
index 6007d03..576d0ff 100644
--- a/plat/rpi/rpi4/include/plat_macros.S
+++ b/plat/rpi/common/include/plat_macros.S
@@ -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.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
diff --git a/plat/rpi/common/include/rpi_shared.h b/plat/rpi/common/include/rpi_shared.h
index ddf239e..8562c3d 100644
--- a/plat/rpi/common/include/rpi_shared.h
+++ b/plat/rpi/common/include/rpi_shared.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,14 +7,20 @@
#ifndef RPI_SHARED_H
#define RPI_SHARED_H
+#include <stddef.h>
#include <stdint.h>
+#include <drivers/console.h>
+
/*******************************************************************************
* Function and variable prototypes
******************************************************************************/
-/* Utility functions */
+/* Serial console functions */
void rpi3_console_init(void);
+int rpi3_register_used_uart(console_t *console);
+
+/* Utility functions */
void rpi3_setup_page_tables(uintptr_t total_base, size_t total_size,
uintptr_t code_start, uintptr_t code_limit,
uintptr_t rodata_start, uintptr_t rodata_limit
@@ -23,6 +29,8 @@
#endif
);
+uintptr_t rpi4_get_dtb_address(void);
+
/* Optional functions required in the Raspberry Pi 3 port */
unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr);
@@ -38,4 +46,10 @@
int plat_rpi_get_model(void);
+/*******************************************************************************
+ * Platform implemented functions
+ ******************************************************************************/
+
+void plat_rpi_bl31_custom_setup(void);
+
#endif /* RPI3_PRIVATE_H */
diff --git a/plat/rpi/common/rpi3_common.c b/plat/rpi/common/rpi3_common.c
index ef88bf1..8976496 100644
--- a/plat/rpi/common/rpi3_common.c
+++ b/plat/rpi/common/rpi3_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2019, 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,9 +13,6 @@
#include <common/debug.h>
#include <bl31/interrupt_mgmt.h>
#include <drivers/console.h>
-#include <drivers/rpi3/gpio/rpi3_gpio.h>
-#include <drivers/ti/uart/uart_16550.h>
-#include <drivers/arm/pl011.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <rpi_hw.h>
@@ -106,12 +103,6 @@
******************************************************************************/
static console_t rpi3_console;
-
-static bool rpi3_use_mini_uart(void)
-{
- return rpi3_gpio_get_select(14) == RPI3_GPIO_FUNC_ALT5;
-}
-
void rpi3_console_init(void)
{
int console_scope = CONSOLE_FLAG_BOOT;
@@ -120,18 +111,7 @@
if (RPI3_RUNTIME_UART != -1)
console_scope |= CONSOLE_FLAG_RUNTIME;
- rpi3_gpio_init();
-
- if (rpi3_use_mini_uart())
- rc = console_16550_register(PLAT_RPI_MINI_UART_BASE,
- 0,
- PLAT_RPI_UART_BAUDRATE,
- &rpi3_console);
- else
- rc = console_pl011_register(PLAT_RPI_PL011_UART_BASE,
- PLAT_RPI_PL011_UART_CLOCK,
- PLAT_RPI_UART_BAUDRATE,
- &rpi3_console);
+ rc = rpi3_register_used_uart(&rpi3_console);
if (rc == 0) {
/*
diff --git a/plat/rpi/common/rpi3_console_dual.c b/plat/rpi/common/rpi3_console_dual.c
new file mode 100644
index 0000000..15ee3e7
--- /dev/null
+++ b/plat/rpi/common/rpi3_console_dual.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024, Mario Bălănică <mariobalanica02@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/pl011.h>
+#include <drivers/console.h>
+#include <drivers/rpi3/gpio/rpi3_gpio.h>
+#include <drivers/ti/uart/uart_16550.h>
+#include <platform_def.h>
+
+#include <rpi_shared.h>
+
+static bool rpi3_use_mini_uart(void)
+{
+ return rpi3_gpio_get_select(14) == RPI3_GPIO_FUNC_ALT5;
+}
+
+int rpi3_register_used_uart(console_t *console)
+{
+ rpi3_gpio_init();
+
+ if (rpi3_use_mini_uart())
+ return console_16550_register(PLAT_RPI_MINI_UART_BASE,
+ 0,
+ PLAT_RPI_UART_BAUDRATE,
+ console);
+ else
+ return console_pl011_register(PLAT_RPI_PL011_UART_BASE,
+ PLAT_RPI_PL011_UART_CLOCK,
+ PLAT_RPI_UART_BAUDRATE,
+ console);
+}
diff --git a/plat/rpi/common/rpi3_console_pl011.c b/plat/rpi/common/rpi3_console_pl011.c
new file mode 100644
index 0000000..6ab7209
--- /dev/null
+++ b/plat/rpi/common/rpi3_console_pl011.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024, Mario Bălănică <mariobalanica02@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <drivers/arm/pl011.h>
+#include <drivers/console.h>
+#include <platform_def.h>
+
+#include <rpi_shared.h>
+
+int rpi3_register_used_uart(console_t *console)
+{
+ return console_pl011_register(PLAT_RPI_PL011_UART_BASE,
+ PLAT_RPI_PL011_UART_CLOCK,
+ PLAT_RPI_UART_BAUDRATE,
+ console);
+}
diff --git a/plat/rpi/common/rpi3_pm.c b/plat/rpi/common/rpi3_pm.c
index d98ac66..456e160 100644
--- a/plat/rpi/common/rpi3_pm.c
+++ b/plat/rpi/common/rpi3_pm.c
@@ -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.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -21,6 +21,22 @@
#include <drivers/arm/gicv2.h>
#endif
+/* Registers on top of RPI3_PM_BASE. */
+#define RPI3_PM_RSTC_OFFSET ULL(0x0000001C)
+#define RPI3_PM_RSTS_OFFSET ULL(0x00000020)
+#define RPI3_PM_WDOG_OFFSET ULL(0x00000024)
+/* Watchdog constants */
+#define RPI3_PM_PASSWORD U(0x5A000000)
+#define RPI3_PM_RSTC_WRCFG_MASK U(0x00000030)
+#define RPI3_PM_RSTC_WRCFG_FULL_RESET U(0x00000020)
+/*
+ * The RSTS register is used by the VideoCore firmware when booting the
+ * Raspberry Pi to know which partition to boot from. The partition value is
+ * formed by bits 0, 2, 4, 6, 8 and 10. Partition 63 is used by said firmware
+ * to indicate halt.
+ */
+#define RPI3_PM_RSTS_WRCFG_HALT U(0x00000555)
+
/* Make composite power state parameter till power level 0 */
#if PSCI_EXTENDED_STATE_ID
diff --git a/plat/rpi/common/rpi3_topology.c b/plat/rpi/common/rpi3_topology.c
index 3747287..5fef777 100644
--- a/plat/rpi/common/rpi3_topology.c
+++ b/plat/rpi/common/rpi3_topology.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -39,12 +39,27 @@
unsigned int cluster_id, cpu_id;
mpidr &= MPIDR_AFFINITY_MASK;
+
+ /*
+ * When MT is set, lowest affinity represents the thread ID.
+ * Since we only support one thread per core, discard this field
+ * so cluster and core IDs go back into Aff1 and Aff0 respectively.
+ * The upper bits are also affected, but plat_rpi3_calc_core_pos()
+ * does not use them.
+ */
+ if ((read_mpidr() & MPIDR_MT_MASK) != 0) {
+ if (MPIDR_AFFLVL0_VAL(mpidr) != 0) {
+ return -1;
+ }
+ mpidr >>= MPIDR_AFFINITY_BITS;
+ }
+
if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) {
return -1;
}
- cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
- cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
+ cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+ cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
if (cluster_id >= PLATFORM_CLUSTER_COUNT) {
return -1;
diff --git a/plat/rpi/rpi4/rpi4_bl31_setup.c b/plat/rpi/common/rpi4_bl31_setup.c
similarity index 67%
rename from plat/rpi/rpi4/rpi4_bl31_setup.c
rename to plat/rpi/common/rpi4_bl31_setup.c
index 2fb4d3d..a7228fd 100644
--- a/plat/rpi/rpi4/rpi4_bl31_setup.c
+++ b/plat/rpi/common/rpi4_bl31_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -8,21 +8,15 @@
#include <inttypes.h>
#include <stdint.h>
-#include <libfdt.h>
-
-#include <platform_def.h>
#include <arch_helpers.h>
#include <common/bl_common.h>
+#include <drivers/arm/gicv2.h>
#include <lib/mmio.h>
#include <lib/xlat_tables/xlat_mmu_helpers.h>
#include <lib/xlat_tables/xlat_tables_defs.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
-#include <common/fdt_fixup.h>
-#include <common/fdt_wrappers.h>
-#include <libfdt.h>
-
-#include <drivers/arm/gicv2.h>
+#include <platform_def.h>
#include <rpi_shared.h>
@@ -85,7 +79,7 @@
#endif
}
-static uintptr_t rpi4_get_dtb_address(void)
+uintptr_t rpi4_get_dtb_address(void)
{
#ifdef RPI3_PRELOADED_DTB_BASE
return RPI3_PRELOADED_DTB_BASE;
@@ -151,7 +145,7 @@
* r1 = machine type number, optional in DT-only platforms (~0 if so)
* r2 = Physical address of the device tree blob
*/
- VERBOSE("rpi4: Preparing to boot 32-bit Linux kernel\n");
+ VERBOSE("rpi: Preparing to boot 32-bit Linux kernel\n");
bl33_image_ep_info.args.arg0 = 0U;
bl33_image_ep_info.args.arg1 = ~0U;
bl33_image_ep_info.args.arg2 = rpi4_get_dtb_address();
@@ -162,7 +156,7 @@
* tree blob (DTB) in x0, while x1-x3 are reserved for future use and
* must be 0.
*/
- VERBOSE("rpi4: Preparing to boot 64-bit Linux kernel\n");
+ VERBOSE("rpi: Preparing to boot 64-bit Linux kernel\n");
bl33_image_ep_info.args.arg0 = rpi4_get_dtb_address();
bl33_image_ep_info.args.arg1 = 0ULL;
bl33_image_ep_info.args.arg2 = 0ULL;
@@ -203,102 +197,13 @@
enable_mmu_el3(0);
}
-/*
- * Remove the FDT /memreserve/ entry that covers the region at the very
- * beginning of memory (if that exists). This is where the secondaries
- * originally spin, but we pull them out there.
- * Having overlapping /reserved-memory and /memreserve/ regions confuses
- * the Linux kernel, so we need to get rid of this one.
- */
-static void remove_spintable_memreserve(void *dtb)
-{
- uint64_t addr, size;
- int regions = fdt_num_mem_rsv(dtb);
- int i;
-
- for (i = 0; i < regions; i++) {
- if (fdt_get_mem_rsv(dtb, i, &addr, &size) != 0) {
- return;
- }
- if (size == 0U) {
- return;
- }
- /* We only look for the region at the beginning of DRAM. */
- if (addr != 0U) {
- continue;
- }
- /*
- * Currently the region in the existing DTs is exactly 4K
- * in size. Should this value ever change, there is probably
- * a reason for that, so inform the user about this.
- */
- if (size == 4096U) {
- fdt_del_mem_rsv(dtb, i);
- return;
- }
- WARN("Keeping unknown /memreserve/ region at 0, size: %" PRId64 "\n",
- size);
- }
-}
-
-static void rpi4_prepare_dtb(void)
-{
- void *dtb = (void *)rpi4_get_dtb_address();
- uint32_t gic_int_prop[3];
- int ret, offs;
-
- /* Return if no device tree is detected */
- if (fdt_check_header(dtb) != 0)
- return;
-
- ret = fdt_open_into(dtb, dtb, 0x100000);
- if (ret < 0) {
- ERROR("Invalid Device Tree at %p: error %d\n", dtb, ret);
- return;
- }
-
- if (dt_add_psci_node(dtb)) {
- ERROR("Failed to add PSCI Device Tree node\n");
- return;
- }
-
- if (dt_add_psci_cpu_enable_methods(dtb)) {
- ERROR("Failed to add PSCI cpu enable methods in Device Tree\n");
- return;
- }
-
- /*
- * Remove the original reserved region (used for the spintable), and
- * replace it with a region describing the whole of Trusted Firmware.
- */
- remove_spintable_memreserve(dtb);
- if (fdt_add_reserved_memory(dtb, "atf@0", 0, 0x80000))
- WARN("Failed to add reserved memory nodes to DT.\n");
-
- offs = fdt_node_offset_by_compatible(dtb, 0, "arm,gic-400");
- gic_int_prop[0] = cpu_to_fdt32(1); // PPI
- gic_int_prop[1] = cpu_to_fdt32(9); // PPI #9
- gic_int_prop[2] = cpu_to_fdt32(0x0f04); // all cores, level high
- fdt_setprop(dtb, offs, "interrupts", gic_int_prop, 12);
-
- offs = fdt_path_offset(dtb, "/chosen");
- fdt_setprop_string(dtb, offs, "stdout-path", "serial0");
-
- ret = fdt_pack(dtb);
- if (ret < 0)
- ERROR("Failed to pack Device Tree at %p: error %d\n", dtb, ret);
-
- clean_dcache_range((uintptr_t)dtb, fdt_blob_size(dtb));
- INFO("Changed device tree to advertise PSCI.\n");
-}
-
void bl31_platform_setup(void)
{
- rpi4_prepare_dtb();
-
/* Configure the interrupt controller */
gicv2_driver_init(&rpi4_gic_data);
gicv2_distif_init();
gicv2_pcpu_distif_init();
gicv2_cpuif_enable();
+
+ plat_rpi_bl31_custom_setup();
}
diff --git a/plat/rpi/rpi3/include/plat_macros.S b/plat/rpi/rpi3/include/plat_macros.S
deleted file mode 100644
index c0c3967..0000000
--- a/plat/rpi/rpi3/include/plat_macros.S
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-#ifndef PLAT_MACROS_S
-#define PLAT_MACROS_S
-
- /* ---------------------------------------------
- * The below required platform porting macro
- * prints out relevant platform registers
- * whenever an unhandled exception is taken in
- * BL31.
- * Clobbers: x0 - x10, x16, x17, sp
- * ---------------------------------------------
- */
- .macro plat_crash_print_regs
- .endm
-
-#endif /* PLAT_MACROS_S */
diff --git a/plat/rpi/rpi3/include/platform_def.h b/plat/rpi/rpi3/include/platform_def.h
index f44d1f5..757c64a 100644
--- a/plat/rpi/rpi3/include/platform_def.h
+++ b/plat/rpi/rpi3/include/platform_def.h
@@ -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.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -254,6 +254,7 @@
#define PLAT_RPI_PL011_UART_BASE RPI3_PL011_UART_BASE
#define PLAT_RPI_PL011_UART_CLOCK RPI3_PL011_UART_CLOCK
#define PLAT_RPI_UART_BAUDRATE ULL(115200)
+#define PLAT_RPI_CRASH_UART_BASE PLAT_RPI_MINI_UART_BASE
/*
* System counter
diff --git a/plat/rpi/rpi3/include/rpi_hw.h b/plat/rpi/rpi3/include/rpi_hw.h
index 2aecab3..dec5963 100644
--- a/plat/rpi/rpi3/include/rpi_hw.h
+++ b/plat/rpi/rpi3/include/rpi_hw.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -21,60 +21,18 @@
*/
#define RPI3_MBOX_OFFSET ULL(0x0000B880)
#define RPI3_MBOX_BASE (RPI_IO_BASE + RPI3_MBOX_OFFSET)
-/* VideoCore -> ARM */
-#define RPI3_MBOX0_READ_OFFSET ULL(0x00000000)
-#define RPI3_MBOX0_PEEK_OFFSET ULL(0x00000010)
-#define RPI3_MBOX0_SENDER_OFFSET ULL(0x00000014)
-#define RPI3_MBOX0_STATUS_OFFSET ULL(0x00000018)
-#define RPI3_MBOX0_CONFIG_OFFSET ULL(0x0000001C)
-/* ARM -> VideoCore */
-#define RPI3_MBOX1_WRITE_OFFSET ULL(0x00000020)
-#define RPI3_MBOX1_PEEK_OFFSET ULL(0x00000030)
-#define RPI3_MBOX1_SENDER_OFFSET ULL(0x00000034)
-#define RPI3_MBOX1_STATUS_OFFSET ULL(0x00000038)
-#define RPI3_MBOX1_CONFIG_OFFSET ULL(0x0000003C)
-/* Mailbox status constants */
-#define RPI3_MBOX_STATUS_FULL_MASK U(0x80000000) /* Set if full */
-#define RPI3_MBOX_STATUS_EMPTY_MASK U(0x40000000) /* Set if empty */
/*
* Power management, reset controller, watchdog.
*/
#define RPI3_IO_PM_OFFSET ULL(0x00100000)
#define RPI3_PM_BASE (RPI_IO_BASE + RPI3_IO_PM_OFFSET)
-/* Registers on top of RPI3_PM_BASE. */
-#define RPI3_PM_RSTC_OFFSET ULL(0x0000001C)
-#define RPI3_PM_RSTS_OFFSET ULL(0x00000020)
-#define RPI3_PM_WDOG_OFFSET ULL(0x00000024)
-/* Watchdog constants */
-#define RPI3_PM_PASSWORD U(0x5A000000)
-#define RPI3_PM_RSTC_WRCFG_MASK U(0x00000030)
-#define RPI3_PM_RSTC_WRCFG_FULL_RESET U(0x00000020)
-/*
- * The RSTS register is used by the VideoCore firmware when booting the
- * Raspberry Pi to know which partition to boot from. The partition value is
- * formed by bits 0, 2, 4, 6, 8 and 10. Partition 63 is used by said firmware
- * to indicate halt.
- */
-#define RPI3_PM_RSTS_WRCFG_HALT U(0x00000555)
/*
* Hardware random number generator.
*/
#define RPI3_IO_RNG_OFFSET ULL(0x00104000)
#define RPI3_RNG_BASE (RPI_IO_BASE + RPI3_IO_RNG_OFFSET)
-#define RPI3_RNG_CTRL_OFFSET ULL(0x00000000)
-#define RPI3_RNG_STATUS_OFFSET ULL(0x00000004)
-#define RPI3_RNG_DATA_OFFSET ULL(0x00000008)
-#define RPI3_RNG_INT_MASK_OFFSET ULL(0x00000010)
-/* Enable/disable RNG */
-#define RPI3_RNG_CTRL_ENABLE U(0x1)
-#define RPI3_RNG_CTRL_DISABLE U(0x0)
-/* Number of currently available words */
-#define RPI3_RNG_STATUS_NUM_WORDS_SHIFT U(24)
-#define RPI3_RNG_STATUS_NUM_WORDS_MASK U(0xFF)
-/* Value to mask interrupts caused by the RNG */
-#define RPI3_RNG_INT_MASK_DISABLE U(0x1)
/*
* Serial ports:
diff --git a/plat/rpi/rpi3/platform.mk b/plat/rpi/rpi3/platform.mk
index 26a3268..8034fa4 100644
--- a/plat/rpi/rpi3/platform.mk
+++ b/plat/rpi/rpi3/platform.mk
@@ -17,6 +17,7 @@
drivers/rpi3/gpio/rpi3_gpio.c \
plat/rpi/common/aarch64/plat_helpers.S \
plat/rpi/common/rpi3_common.c \
+ plat/rpi/common/rpi3_console_dual.c \
${XLAT_TABLES_LIB_SRCS}
BL1_SOURCES += drivers/io/io_fip.c \
diff --git a/plat/rpi/rpi4/include/platform_def.h b/plat/rpi/rpi4/include/platform_def.h
index 6787ebf..b72aedc 100644
--- a/plat/rpi/rpi4/include/platform_def.h
+++ b/plat/rpi/rpi4/include/platform_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -131,6 +131,7 @@
#define PLAT_RPI_PL011_UART_BASE RPI4_PL011_UART_BASE
#define PLAT_RPI_PL011_UART_CLOCK RPI4_PL011_UART_CLOCK
#define PLAT_RPI_UART_BAUDRATE ULL(115200)
+#define PLAT_RPI_CRASH_UART_BASE PLAT_RPI_MINI_UART_BASE
/*
* System counter
diff --git a/plat/rpi/rpi4/include/rpi_hw.h b/plat/rpi/rpi4/include/rpi_hw.h
index 0430d46..8162492 100644
--- a/plat/rpi/rpi4/include/rpi_hw.h
+++ b/plat/rpi/rpi4/include/rpi_hw.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -23,60 +23,18 @@
*/
#define RPI3_MBOX_OFFSET ULL(0x0000B880)
#define RPI3_MBOX_BASE (RPI_LEGACY_BASE + RPI3_MBOX_OFFSET)
-/* VideoCore -> ARM */
-#define RPI3_MBOX0_READ_OFFSET ULL(0x00000000)
-#define RPI3_MBOX0_PEEK_OFFSET ULL(0x00000010)
-#define RPI3_MBOX0_SENDER_OFFSET ULL(0x00000014)
-#define RPI3_MBOX0_STATUS_OFFSET ULL(0x00000018)
-#define RPI3_MBOX0_CONFIG_OFFSET ULL(0x0000001C)
-/* ARM -> VideoCore */
-#define RPI3_MBOX1_WRITE_OFFSET ULL(0x00000020)
-#define RPI3_MBOX1_PEEK_OFFSET ULL(0x00000030)
-#define RPI3_MBOX1_SENDER_OFFSET ULL(0x00000034)
-#define RPI3_MBOX1_STATUS_OFFSET ULL(0x00000038)
-#define RPI3_MBOX1_CONFIG_OFFSET ULL(0x0000003C)
-/* Mailbox status constants */
-#define RPI3_MBOX_STATUS_FULL_MASK U(0x80000000) /* Set if full */
-#define RPI3_MBOX_STATUS_EMPTY_MASK U(0x40000000) /* Set if empty */
/*
* Power management, reset controller, watchdog.
*/
#define RPI3_IO_PM_OFFSET ULL(0x00100000)
#define RPI3_PM_BASE (RPI_LEGACY_BASE + RPI3_IO_PM_OFFSET)
-/* Registers on top of RPI3_PM_BASE. */
-#define RPI3_PM_RSTC_OFFSET ULL(0x0000001C)
-#define RPI3_PM_RSTS_OFFSET ULL(0x00000020)
-#define RPI3_PM_WDOG_OFFSET ULL(0x00000024)
-/* Watchdog constants */
-#define RPI3_PM_PASSWORD U(0x5A000000)
-#define RPI3_PM_RSTC_WRCFG_MASK U(0x00000030)
-#define RPI3_PM_RSTC_WRCFG_FULL_RESET U(0x00000020)
-/*
- * The RSTS register is used by the VideoCore firmware when booting the
- * Raspberry Pi to know which partition to boot from. The partition value is
- * formed by bits 0, 2, 4, 6, 8 and 10. Partition 63 is used by said firmware
- * to indicate halt.
- */
-#define RPI3_PM_RSTS_WRCFG_HALT U(0x00000555)
/*
* Hardware random number generator.
*/
#define RPI3_IO_RNG_OFFSET ULL(0x00104000)
#define RPI3_RNG_BASE (RPI_LEGACY_BASE + RPI3_IO_RNG_OFFSET)
-#define RPI3_RNG_CTRL_OFFSET ULL(0x00000000)
-#define RPI3_RNG_STATUS_OFFSET ULL(0x00000004)
-#define RPI3_RNG_DATA_OFFSET ULL(0x00000008)
-#define RPI3_RNG_INT_MASK_OFFSET ULL(0x00000010)
-/* Enable/disable RNG */
-#define RPI3_RNG_CTRL_ENABLE U(0x1)
-#define RPI3_RNG_CTRL_DISABLE U(0x0)
-/* Number of currently available words */
-#define RPI3_RNG_STATUS_NUM_WORDS_SHIFT U(24)
-#define RPI3_RNG_STATUS_NUM_WORDS_MASK U(0xFF)
-/* Value to mask interrupts caused by the RNG */
-#define RPI3_RNG_INT_MASK_DISABLE U(0x1)
/*
* Serial ports:
diff --git a/plat/rpi/rpi4/platform.mk b/plat/rpi/rpi4/platform.mk
index 42a5416..f17911f 100644
--- a/plat/rpi/rpi4/platform.mk
+++ b/plat/rpi/rpi4/platform.mk
@@ -15,16 +15,18 @@
PLAT_BL_COMMON_SOURCES := drivers/ti/uart/aarch64/16550_console.S \
drivers/arm/pl011/aarch64/pl011_console.S \
plat/rpi/common/rpi3_common.c \
+ plat/rpi/common/rpi3_console_dual.c \
${XLAT_TABLES_LIB_SRCS}
BL31_SOURCES += lib/cpus/aarch64/cortex_a72.S \
plat/rpi/common/aarch64/plat_helpers.S \
- plat/rpi/rpi4/aarch64/armstub8_header.S \
+ plat/rpi/common/aarch64/armstub8_header.S \
drivers/delay_timer/delay_timer.c \
drivers/gpio/gpio.c \
drivers/rpi3/gpio/rpi3_gpio.c \
plat/common/plat_gicv2.c \
- plat/rpi/rpi4/rpi4_bl31_setup.c \
+ plat/rpi/common/rpi4_bl31_setup.c \
+ plat/rpi/rpi4/rpi4_setup.c \
plat/rpi/common/rpi3_pm.c \
plat/common/plat_psci_common.c \
plat/rpi/common/rpi3_topology.c \
diff --git a/plat/rpi/rpi4/rpi4_setup.c b/plat/rpi/rpi4/rpi4_setup.c
new file mode 100644
index 0000000..82200b9
--- /dev/null
+++ b/plat/rpi/rpi4/rpi4_setup.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdint.h>
+
+#include <arch_helpers.h>
+#include <common/fdt_fixup.h>
+#include <common/fdt_wrappers.h>
+
+#include <rpi_shared.h>
+
+/*
+ * Remove the FDT /memreserve/ entry that covers the region at the very
+ * beginning of memory (if that exists). This is where the secondaries
+ * originally spin, but we pull them out there.
+ * Having overlapping /reserved-memory and /memreserve/ regions confuses
+ * the Linux kernel, so we need to get rid of this one.
+ */
+static void remove_spintable_memreserve(void *dtb)
+{
+ uint64_t addr, size;
+ int regions = fdt_num_mem_rsv(dtb);
+ int i;
+
+ for (i = 0; i < regions; i++) {
+ if (fdt_get_mem_rsv(dtb, i, &addr, &size) != 0) {
+ return;
+ }
+ if (size == 0U) {
+ return;
+ }
+ /* We only look for the region at the beginning of DRAM. */
+ if (addr != 0U) {
+ continue;
+ }
+ /*
+ * Currently the region in the existing DTs is exactly 4K
+ * in size. Should this value ever change, there is probably
+ * a reason for that, so inform the user about this.
+ */
+ if (size == 4096U) {
+ fdt_del_mem_rsv(dtb, i);
+ return;
+ }
+ WARN("Keeping unknown /memreserve/ region at 0, size: %" PRId64 "\n",
+ size);
+ }
+}
+
+static void rpi4_prepare_dtb(void)
+{
+ void *dtb = (void *)rpi4_get_dtb_address();
+ uint32_t gic_int_prop[3];
+ int ret, offs;
+
+ /* Return if no device tree is detected */
+ if (fdt_check_header(dtb) != 0)
+ return;
+
+ ret = fdt_open_into(dtb, dtb, 0x100000);
+ if (ret < 0) {
+ ERROR("Invalid Device Tree at %p: error %d\n", dtb, ret);
+ return;
+ }
+
+ if (dt_add_psci_node(dtb)) {
+ ERROR("Failed to add PSCI Device Tree node\n");
+ return;
+ }
+
+ if (dt_add_psci_cpu_enable_methods(dtb)) {
+ ERROR("Failed to add PSCI cpu enable methods in Device Tree\n");
+ return;
+ }
+
+ /*
+ * Remove the original reserved region (used for the spintable), and
+ * replace it with a region describing the whole of Trusted Firmware.
+ */
+ remove_spintable_memreserve(dtb);
+ if (fdt_add_reserved_memory(dtb, "atf@0", 0, 0x80000))
+ WARN("Failed to add reserved memory nodes to DT.\n");
+
+ offs = fdt_node_offset_by_compatible(dtb, 0, "arm,gic-400");
+ gic_int_prop[0] = cpu_to_fdt32(1); // PPI
+ gic_int_prop[1] = cpu_to_fdt32(9); // PPI #9
+ gic_int_prop[2] = cpu_to_fdt32(0x0f04); // all cores, level high
+ fdt_setprop(dtb, offs, "interrupts", gic_int_prop, 12);
+
+ offs = fdt_path_offset(dtb, "/chosen");
+ fdt_setprop_string(dtb, offs, "stdout-path", "serial0");
+
+ ret = fdt_pack(dtb);
+ if (ret < 0)
+ ERROR("Failed to pack Device Tree at %p: error %d\n", dtb, ret);
+
+ clean_dcache_range((uintptr_t)dtb, fdt_blob_size(dtb));
+ INFO("Changed device tree to advertise PSCI.\n");
+}
+
+void plat_rpi_bl31_custom_setup(void)
+{
+ rpi4_prepare_dtb();
+}
diff --git a/plat/rpi/rpi5/include/plat.ld.S b/plat/rpi/rpi5/include/plat.ld.S
new file mode 100644
index 0000000..961c630
--- /dev/null
+++ b/plat/rpi/rpi5/include/plat.ld.S
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2019-2024, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Stub linker script to provide the armstub8.bin header before the actual
+ * code. If the GPU firmware finds a magic value at offset 240 in
+ * armstub8.bin, it will put the DTB and kernel load address in subsequent
+ * words. We can then read those values to find the proper NS entry point
+ * and find our DTB more flexibly.
+ */
+
+MEMORY {
+ PRERAM (rwx): ORIGIN = 0, LENGTH = 4096
+}
+
+SECTIONS
+{
+ .armstub8 . : {
+ *armstub8_header.o(.text*)
+ KEEP(*(.armstub8))
+ } >PRERAM
+}
diff --git a/plat/rpi/rpi5/include/platform_def.h b/plat/rpi/rpi5/include/platform_def.h
new file mode 100644
index 0000000..a4c2f5b
--- /dev/null
+++ b/plat/rpi/rpi5/include/platform_def.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024, Mario Bălănică <mariobalanica02@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <arch.h>
+#include <common/tbbr/tbbr_img_def.h>
+#include <lib/utils_def.h>
+#include <plat/common/common_def.h>
+
+#include "rpi_hw.h"
+
+/* Special value used to verify platform parameters from BL2 to BL31 */
+#define RPI3_BL31_PLAT_PARAM_VAL ULL(0x0F1E2D3C4B5A6978)
+
+#define PLATFORM_STACK_SIZE ULL(0x1000)
+
+#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
+#define PLATFORM_CLUSTER_COUNT U(1)
+#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
+#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT
+
+#define RPI_PRIMARY_CPU U(0)
+
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_MAX_RET_STATE U(1)
+#define PLAT_MAX_OFF_STATE U(2)
+
+/* Local power state for power domains in Run state. */
+#define PLAT_LOCAL_STATE_RUN U(0)
+/* Local power state for retention. Valid only for CPU power domains */
+#define PLAT_LOCAL_STATE_RET U(1)
+/*
+ * Local power state for OFF/power-down. Valid for CPU and cluster power
+ * domains.
+ */
+#define PLAT_LOCAL_STATE_OFF U(2)
+
+/*
+ * Macros used to parse state information from State-ID if it is using the
+ * recommended encoding for State-ID.
+ */
+#define PLAT_LOCAL_PSTATE_WIDTH U(4)
+#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1)
+
+/*
+ * Some data must be 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.
+ */
+#define CACHE_WRITEBACK_SHIFT U(6)
+#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT)
+
+/*
+ * I/O registers.
+ */
+#define DEVICE0_BASE RPI_IO_BASE
+#define DEVICE0_SIZE RPI_IO_SIZE
+
+/*
+ * Mailbox to control the secondary cores. All secondary cores are held in a
+ * wait loop in cold boot. To release them perform the following steps (plus
+ * any additional barriers that may be needed):
+ *
+ * uint64_t *entrypoint = (uint64_t *)PLAT_RPI3_TM_ENTRYPOINT;
+ * *entrypoint = ADDRESS_TO_JUMP_TO;
+ *
+ * uint64_t *mbox_entry = (uint64_t *)PLAT_RPI3_TM_HOLD_BASE;
+ * mbox_entry[cpu_id] = PLAT_RPI3_TM_HOLD_STATE_GO;
+ *
+ * sev();
+ */
+/* The secure entry point to be used on warm reset by all CPUs. */
+#define PLAT_RPI3_TM_ENTRYPOINT 0x100
+#define PLAT_RPI3_TM_ENTRYPOINT_SIZE ULL(8)
+
+/* Hold entries for each CPU. */
+#define PLAT_RPI3_TM_HOLD_BASE (PLAT_RPI3_TM_ENTRYPOINT + \
+ PLAT_RPI3_TM_ENTRYPOINT_SIZE)
+#define PLAT_RPI3_TM_HOLD_ENTRY_SIZE ULL(8)
+#define PLAT_RPI3_TM_HOLD_SIZE (PLAT_RPI3_TM_HOLD_ENTRY_SIZE * \
+ PLATFORM_CORE_COUNT)
+
+#define PLAT_RPI3_TRUSTED_MAILBOX_SIZE (PLAT_RPI3_TM_ENTRYPOINT_SIZE + \
+ PLAT_RPI3_TM_HOLD_SIZE)
+
+#define PLAT_RPI3_TM_HOLD_STATE_WAIT ULL(0)
+#define PLAT_RPI3_TM_HOLD_STATE_GO ULL(1)
+#define PLAT_RPI3_TM_HOLD_STATE_BSP_OFF ULL(2)
+
+/*
+ * BL31 specific defines.
+ *
+ * Put BL31 at the top of the Trusted SRAM. BL31_BASE is calculated using the
+ * current BL31 debug size plus a little space for growth.
+ */
+#define PLAT_MAX_BL31_SIZE ULL(0x80000)
+
+#define BL31_BASE ULL(0x1000)
+#define BL31_LIMIT ULL(0x80000)
+#define BL31_PROGBITS_LIMIT ULL(0x80000)
+
+#define SEC_SRAM_ID 0
+#define SEC_DRAM_ID 1
+
+/*
+ * Other memory-related defines.
+ */
+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 40)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 40)
+
+#define MAX_MMAP_REGIONS 8
+#define MAX_XLAT_TABLES 4
+
+#define MAX_IO_DEVICES U(3)
+#define MAX_IO_HANDLES U(4)
+
+#define MAX_IO_BLOCK_DEVICES U(1)
+
+/*
+ * Serial-related constants.
+ */
+#define PLAT_RPI_PL011_UART_BASE RPI4_PL011_UART_BASE
+#define PLAT_RPI_PL011_UART_CLOCK RPI4_PL011_UART_CLOCK
+#define PLAT_RPI_UART_BAUDRATE ULL(115200)
+#define PLAT_RPI_CRASH_UART_BASE PLAT_RPI_PL011_UART_BASE
+
+/*
+ * System counter
+ */
+#define SYS_COUNTER_FREQ_IN_TICKS ULL(54000000)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/rpi/rpi5/include/rpi_hw.h b/plat/rpi/rpi5/include/rpi_hw.h
new file mode 100644
index 0000000..384542e
--- /dev/null
+++ b/plat/rpi/rpi5/include/rpi_hw.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024, Mario Bălănică <mariobalanica02@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RPI_HW_H
+#define RPI_HW_H
+
+#include <lib/utils_def.h>
+
+/*
+ * Peripherals
+ */
+
+#define RPI_IO_BASE ULL(0x1000000000)
+#define RPI_IO_SIZE ULL(0x1000000000)
+
+/*
+ * ARM <-> VideoCore mailboxes
+ */
+#define RPI3_MBOX_BASE (RPI_IO_BASE + ULL(0x7c013880))
+
+/*
+ * Power management, reset controller, watchdog.
+ */
+#define RPI3_PM_BASE (RPI_IO_BASE + ULL(0x7d200000))
+
+/*
+ * Hardware random number generator.
+ */
+#define RPI3_RNG_BASE (RPI_IO_BASE + ULL(0x7d208000))
+
+/*
+ * PL011 system serial port
+ */
+#define RPI4_PL011_UART_BASE (RPI_IO_BASE + ULL(0x7d001000))
+#define RPI4_PL011_UART_CLOCK ULL(44000000)
+
+/*
+ * GIC interrupt controller
+ */
+#define RPI_HAVE_GIC
+#define RPI4_GIC_GICD_BASE (RPI_IO_BASE + ULL(0x7fff9000))
+#define RPI4_GIC_GICC_BASE (RPI_IO_BASE + ULL(0x7fffa000))
+
+#define RPI4_LOCAL_CONTROL_BASE_ADDRESS (RPI_IO_BASE + ULL(0x7c280000))
+#define RPI4_LOCAL_CONTROL_PRESCALER (RPI_IO_BASE + ULL(0x7c280008))
+
+#endif /* RPI_HW_H */
diff --git a/plat/rpi/rpi5/platform.mk b/plat/rpi/rpi5/platform.mk
new file mode 100644
index 0000000..81b7ded
--- /dev/null
+++ b/plat/rpi/rpi5/platform.mk
@@ -0,0 +1,107 @@
+#
+# Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2024, Mario Bălănică <mariobalanica02@gmail.com>
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include lib/xlat_tables_v2/xlat_tables.mk
+
+include drivers/arm/gic/v2/gicv2.mk
+
+PLAT_INCLUDES := -Iplat/rpi/common/include \
+ -Iplat/rpi/rpi5/include
+
+PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/aarch64/pl011_console.S \
+ plat/rpi/common/rpi3_common.c \
+ plat/rpi/common/rpi3_console_pl011.c \
+ ${XLAT_TABLES_LIB_SRCS}
+
+BL31_SOURCES += lib/cpus/aarch64/cortex_a76.S \
+ plat/rpi/common/aarch64/plat_helpers.S \
+ plat/rpi/common/aarch64/armstub8_header.S \
+ drivers/delay_timer/delay_timer.c \
+ plat/common/plat_gicv2.c \
+ plat/rpi/common/rpi4_bl31_setup.c \
+ plat/rpi/rpi5/rpi5_setup.c \
+ plat/rpi/common/rpi3_pm.c \
+ plat/common/plat_psci_common.c \
+ plat/rpi/common/rpi3_topology.c \
+ ${GICV2_SOURCES}
+
+# For now we only support BL31, using the kernel loaded by the GPU firmware.
+RESET_TO_BL31 := 1
+
+# All CPUs enter armstub8.bin.
+COLD_BOOT_SINGLE_CPU := 0
+
+# Tune compiler for Cortex-A76
+ifeq ($(notdir $(CC)),armclang)
+ TF_CFLAGS_aarch64 += -mcpu=cortex-a76
+else ifneq ($(findstring clang,$(notdir $(CC))),)
+ TF_CFLAGS_aarch64 += -mcpu=cortex-a76
+else
+ TF_CFLAGS_aarch64 += -mtune=cortex-a76
+endif
+
+# Add support for platform supplied linker script for BL31 build
+$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT))
+
+# Enable all errata workarounds for Cortex-A76 r4p1
+ERRATA_A76_1946160 := 1
+ERRATA_A76_2743102 := 1
+
+# Add new default target when compiling this platform
+all: bl31
+
+# Build config flags
+# ------------------
+
+# Disable stack protector by default
+ENABLE_STACK_PROTECTOR := 0
+
+# Have different sections for code and rodata
+SEPARATE_CODE_AND_RODATA := 1
+
+# Hardware-managed coherency
+HW_ASSISTED_COHERENCY := 1
+USE_COHERENT_MEM := 0
+
+# Cortex-A76 is 64-bit only
+CTX_INCLUDE_AARCH32_REGS := 0
+
+# Platform build flags
+# --------------------
+
+# There is not much else than a Linux kernel to load at the moment.
+RPI3_DIRECT_LINUX_BOOT := 1
+
+# BL33 images can only be AArch64 on this platform.
+RPI3_BL33_IN_AARCH32 := 0
+
+# UART to use at runtime. -1 means the runtime UART is disabled.
+# Any other value means the default UART will be used.
+RPI3_RUNTIME_UART := 0
+
+# Use normal memory mapping for ROM, FIP, SRAM and DRAM
+RPI3_USE_UEFI_MAP := 0
+
+# Process platform flags
+# ----------------------
+
+$(eval $(call add_define,RPI3_BL33_IN_AARCH32))
+$(eval $(call add_define,RPI3_DIRECT_LINUX_BOOT))
+ifdef RPI3_PRELOADED_DTB_BASE
+$(eval $(call add_define,RPI3_PRELOADED_DTB_BASE))
+endif
+$(eval $(call add_define,RPI3_RUNTIME_UART))
+$(eval $(call add_define,RPI3_USE_UEFI_MAP))
+
+ifeq (${ARCH},aarch32)
+ $(error Error: AArch32 not supported on rpi5)
+endif
+
+ifneq ($(ENABLE_STACK_PROTECTOR), 0)
+PLAT_BL_COMMON_SOURCES += drivers/rpi3/rng/rpi3_rng.c \
+ plat/rpi/common/rpi3_stack_protector.c
+endif
diff --git a/plat/rpi/rpi5/rpi5_setup.c b/plat/rpi/rpi5/rpi5_setup.c
new file mode 100644
index 0000000..de82300
--- /dev/null
+++ b/plat/rpi/rpi5/rpi5_setup.c
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2024, Mario Bălănică <mariobalanica02@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <rpi_shared.h>
+
+void plat_rpi_bl31_custom_setup(void)
+{
+ /* Nothing to do here yet. */
+}
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index fd86020..798c033 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -255,11 +255,6 @@
mmio_clrbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST);
}
-#if STM32MP15
- /* Disable MCKPROT */
- mmio_clrbits_32(rcc_base + RCC_TZCR, RCC_TZCR_MCKPROT);
-#endif
-
/*
* Set minimum reset pulse duration to 31ms for discrete power
* supplied boards.
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
index b46f4af..245b2d3 100644
--- a/plat/st/stm32mp1/sp_min/sp_min_setup.c
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.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
*/
@@ -182,6 +182,9 @@
stm32mp_gic_init();
+ /* Disable MCU subsystem protection */
+ stm32mp1_clk_mcuss_protect(false);
+
if (stm32_iwdg_init() < 0) {
panic();
}