diff --git a/CHANGELOG.md b/CHANGELOG.md
index 44f5f99b49b7c5fa2792fa30084e2e65b7aeaa79..0b42b334fab680edb83c9bb400d51b9ad902578e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,33 @@
+# OP-TEE - version 4.1.0 (2024-01-19)
+
+- Links to the release pages, commits and pull requests merged into this release for:
+  - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_4_1], [commits][OP_TEE_optee_os_commits_4_1] and [pull requests][OP_TEE_optee_os_pr_4_1]
+  - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_4_1], [commits][OP_TEE_optee_client_commits_4_1] and [pull requests][OP_TEE_optee_client_pr_4_1]
+  - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_4_1], [commits][OP_TEE_optee_test_commits_4_1] and [pull requests][OP_TEE_optee_test_pr_4_1]
+  - OP-TEE/build: [release page][OP_TEE_build_release_4_1], [commits][OP_TEE_build_commits_4_1] and [pull requests][OP_TEE_build_pr_4_1]
+  - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_4_1], [commits][linaro_swg_optee_examples_commits_4_1] and [pull requests][linaro_swg_optee_examples_pr_4_1]
+
+
+[OP_TEE_optee_os_release_4_1]: https://github.com/OP-TEE/optee_os/releases/tag/4.1.0
+[OP_TEE_optee_os_commits_4_1]: https://github.com/OP-TEE/optee_os/compare/4.0.0...4.1.0
+[OP_TEE_optee_os_pr_4_1]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-10-20..2024-01-19
+
+[OP_TEE_optee_client_release_4_1]: https://github.com/OP-TEE/optee_client/releases/tag/4.1.0
+[OP_TEE_optee_client_commits_4_1]: https://github.com/OP-TEE/optee_client/compare/4.0.0...4.1.0
+[OP_TEE_optee_client_pr_4_1]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-10-20..2024-01-19
+
+[OP_TEE_optee_test_release_4_1]: https://github.com/OP-TEE/optee_test/releases/tag/4.1.0
+[OP_TEE_optee_test_commits_4_1]: https://github.com/OP-TEE/optee_test/compare/4.0.0...4.1.0
+[OP_TEE_optee_test_pr_4_1]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-10-20..2024-01-19
+
+[OP_TEE_build_release_4_1]: https://github.com/OP-TEE/build/releases/tag/4.1.0
+[OP_TEE_build_commits_4_1]: https://github.com/OP-TEE/build/compare/4.0.0...4.1.0
+[OP_TEE_build_pr_4_1]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-10-20..2024-01-19
+
+[linaro_swg_optee_examples_release_4_1]: https://github.com/linaro-swg/optee_examples/releases/tag/4.1.0
+[linaro_swg_optee_examples_commits_4_1]: https://github.com/linaro-swg/optee_examples/compare/4.0.0...4.1.0
+[linaro_swg_optee_examples_pr_4_1]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-10-20..2024-01-19
+
 # OP-TEE - version 4.0.0 (2023-10-20)
 
 - Links to the release pages, commits and pull requests merged into this release for:
@@ -10,25 +40,25 @@
 
 [OP_TEE_optee_os_release_4_0]: https://github.com/OP-TEE/optee_os/releases/tag/4.0.0
 [OP_TEE_optee_os_commits_4_0]: https://github.com/OP-TEE/optee_os/compare/3.22.0...4.0.0
-[OP_TEE_optee_os_pr_4_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A..2023-10-20
+[OP_TEE_optee_os_pr_4_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-07-07..2023-10-20
 
 [OP_TEE_optee_client_release_4_0]: https://github.com/OP-TEE/optee_client/releases/tag/4.0.0
 [OP_TEE_optee_client_commits_4_0]: https://github.com/OP-TEE/optee_client/compare/3.22.0...4.0.0
-[OP_TEE_optee_client_pr_4_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A..2023-10-20
+[OP_TEE_optee_client_pr_4_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-07-07..2023-10-20
 
 [OP_TEE_optee_test_release_4_0]: https://github.com/OP-TEE/optee_test/releases/tag/4.0.0
 [OP_TEE_optee_test_commits_4_0]: https://github.com/OP-TEE/optee_test/compare/3.22.0...4.0.0
-[OP_TEE_optee_test_pr_4_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A..2023-10-20
+[OP_TEE_optee_test_pr_4_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-07-07..2023-10-20
 
 [OP_TEE_build_release_4_0]: https://github.com/OP-TEE/build/releases/tag/4.0.0
 [OP_TEE_build_commits_4_0]: https://github.com/OP-TEE/build/compare/3.22.0...4.0.0
-[OP_TEE_build_pr_4_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A..2023-10-20
+[OP_TEE_build_pr_4_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-07-07..2023-10-20
 
 [linaro_swg_optee_examples_release_4_0]: https://github.com/linaro-swg/optee_examples/releases/tag/4.0.0
 [linaro_swg_optee_examples_commits_4_0]: https://github.com/linaro-swg/optee_examples/compare/3.22.0...4.0.0
-[linaro_swg_optee_examples_pr_4_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A..2023-10-20
+[linaro_swg_optee_examples_pr_4_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-07-07..2023-10-20
 
-# OP-TEE - version 3.22 (2023-07-07)
+# OP-TEE - version 3.22.0 (2023-07-07)
 
 - Links to the release pages, commits and pull requests merged into this release for:
   - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_22], [commits][OP_TEE_optee_os_commits_3_22] and [pull requests][OP_TEE_optee_os_pr_3_22]
@@ -38,25 +68,25 @@
   - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_22], [commits][linaro_swg_optee_examples_commits_3_22] and [pull requests][linaro_swg_optee_examples_pr_3_22]
 
 
-[OP_TEE_optee_os_release_3_22]: https://github.com/OP-TEE/optee_os/releases/tag/3.22
-[OP_TEE_optee_os_commits_3_22]: https://github.com/OP-TEE/optee_os/compare/3.21...3.22
-[OP_TEE_optee_os_pr_3_22]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A..2023-07-07
+[OP_TEE_optee_os_release_3_22]: https://github.com/OP-TEE/optee_os/releases/tag/3.22.0
+[OP_TEE_optee_os_commits_3_22]: https://github.com/OP-TEE/optee_os/compare/3.21.0...3.22.0
+[OP_TEE_optee_os_pr_3_22]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-04-14..2023-07-07
 
-[OP_TEE_optee_client_release_3_22]: https://github.com/OP-TEE/optee_client/releases/tag/3.22
-[OP_TEE_optee_client_commits_3_22]: https://github.com/OP-TEE/optee_client/compare/3.21...3.22
-[OP_TEE_optee_client_pr_3_22]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A..2023-07-07
+[OP_TEE_optee_client_release_3_22]: https://github.com/OP-TEE/optee_client/releases/tag/3.22.0
+[OP_TEE_optee_client_commits_3_22]: https://github.com/OP-TEE/optee_client/compare/3.21.0...3.22.0
+[OP_TEE_optee_client_pr_3_22]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-04-14..2023-07-07
 
-[OP_TEE_optee_test_release_3_22]: https://github.com/OP-TEE/optee_test/releases/tag/3.22
-[OP_TEE_optee_test_commits_3_22]: https://github.com/OP-TEE/optee_test/compare/3.21...3.22
-[OP_TEE_optee_test_pr_3_22]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A..2023-07-07
+[OP_TEE_optee_test_release_3_22]: https://github.com/OP-TEE/optee_test/releases/tag/3.22.0
+[OP_TEE_optee_test_commits_3_22]: https://github.com/OP-TEE/optee_test/compare/3.21.0...3.22.0
+[OP_TEE_optee_test_pr_3_22]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-04-14..2023-07-07
 
-[OP_TEE_build_release_3_22]: https://github.com/OP-TEE/build/releases/tag/3.22
-[OP_TEE_build_commits_3_22]: https://github.com/OP-TEE/build/compare/3.21...3.22
-[OP_TEE_build_pr_3_22]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A..2023-07-07
+[OP_TEE_build_release_3_22]: https://github.com/OP-TEE/build/releases/tag/3.22.0
+[OP_TEE_build_commits_3_22]: https://github.com/OP-TEE/build/compare/3.21.0...3.22.0
+[OP_TEE_build_pr_3_22]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-04-14..2023-07-07
 
-[linaro_swg_optee_examples_release_3_22]: https://github.com/linaro-swg/optee_examples/releases/tag/3.22
-[linaro_swg_optee_examples_commits_3_22]: https://github.com/linaro-swg/optee_examples/compare/3.21...3.22
-[linaro_swg_optee_examples_pr_3_22]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A..2023-07-07
+[linaro_swg_optee_examples_release_3_22]: https://github.com/linaro-swg/optee_examples/releases/tag/3.22.0
+[linaro_swg_optee_examples_commits_3_22]: https://github.com/linaro-swg/optee_examples/compare/3.21.0...3.22.0
+[linaro_swg_optee_examples_pr_3_22]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-04-14..2023-07-07
 
 # OP-TEE - version 3.21.0 (2023-04-14)
 
diff --git a/MAINTAINERS b/MAINTAINERS
index b4805295ec6225c573f2cd31d08c9a33ebb4f8e0..095165b2f032fc625d9cfaa1493a939ce48811fd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -32,6 +32,11 @@ basis (R:).
 
 ----------
 
+AOSP build
+R:	Tadd Kao <tadd.kao@mediatek.com> [@taddk]
+S:	Maintained
+F:	mk/aosp_optee.mk
+
 ARM Foundation FVP
 R:	Jens Wiklander <jens.wiklander@linaro.org> [@jenswi-linaro]
 S:	Maintained
@@ -267,14 +272,25 @@ R:	Etienne Carriere <etienne.carriere@foss.st.com> [@etienne-lms]
 S:	Maintained
 F:	core/arch/arm/plat-stm/
 
+STMicroelectronics drivers
+R:	Etienne Carriere <etienne.carriere@foss.st.com> [@etienne-lms]
+R:	Gatien Chevallier <gatien.chevallier@foss.st.com> [@GseoC]
+S:	Maintained
+F:	core/drivers/stm32_*
+
 STMicroelectronics stm32mp1
 R:	Etienne Carriere <etienne.carriere@foss.st.com> [@etienne-lms]
 S:	Maintained
 F:	core/arch/arm/plat-stm32mp1/
-F:	core/drivers/stm32_*
 F:	core/drivers/stm32mp15_huk.c
 F:	core/drivers/stpmic1.c
 
+STMicroelectronics stm32mp2
+R:	Etienne Carriere <etienne.carriere@foss.st.com> [@etienne-lms]
+R:	Gatien Chevallier <gatien.chevallier@foss.st.com> [@GseoC]
+S:	Maintained
+F:	core/arch/arm/plat-stm32mp2/*
+
 Texas Instruments AM43xx, AM57xx, DRA7xx, AM65x, J721E, J784S4, AM64x, AM62x
 R:	Andrew Davis <afd@ti.com> [@glneo]
 S:	Maintained
diff --git a/Makefile b/Makefile
index 8db66780f52110e85ff9801ffe1cc76d45dae13c..8908849d50fbcdebc24ae314b05fd052e9324ebe 100644
--- a/Makefile
+++ b/Makefile
@@ -109,6 +109,7 @@ clean:
 	${q}dirs="$(call cleandirs-for-rmdir)"; if [ "$$dirs" ]; then $(RMDIR) $$dirs; fi
 	@if [ "$(out-dir)" != "$(O)" ]; then $(cmd-echo-silent) '  CLEAN   $(O)'; fi
 	${q}if [ -d "$(O)" ]; then $(RMDIR) $(O); fi
+	${q}rm -f compile_commands.json
 
 .PHONY: cscope
 cscope:
diff --git a/core/arch/arm/arm.mk b/core/arch/arm/arm.mk
index 706556b94128b07dd9738e5333306691a91070d8..34f5a633b3026cb16337558085663c9d116c938c 100644
--- a/core/arch/arm/arm.mk
+++ b/core/arch/arm/arm.mk
@@ -129,6 +129,9 @@ ifeq ($(CFG_CORE_FFA),y)
 ifneq ($(CFG_DT),y)
 $(error CFG_CORE_FFA depends on CFG_DT)
 endif
+ifneq ($(CFG_ARM64_core),y)
+$(error CFG_CORE_FFA depends on CFG_ARM64_core)
+endif
 endif
 
 ifeq ($(CFG_CORE_PHYS_RELOCATABLE)-$(CFG_WITH_PAGER),y-y)
@@ -179,7 +182,8 @@ CFG_SM_NO_CYCLE_COUNTING ?= y
 # CFG_CORE_ASYNC_NOTIF_GIC_INTID is defined by the platform to some free
 # interrupt. Setting it to a non-zero number enables support for using an
 # Arm-GIC to notify normal world. This config variable should use a value
-# larger the 32 to make it of the type SPI.
+# larger or equal to 24 to make it of the type SPI or PPI (secure PPI
+# only).
 # Note that asynchronous notifactions must be enabled with
 # CFG_CORE_ASYNC_NOTIF=y for this variable to be used.
 CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 0
diff --git a/core/arch/arm/dts/sama5d2.dtsi b/core/arch/arm/dts/sama5d2.dtsi
index 1a0429287a98a41edd9f57da899f06aa88221548..56c4dd5ca971b4154cba0d137e3e833bce3915ce 100644
--- a/core/arch/arm/dts/sama5d2.dtsi
+++ b/core/arch/arm/dts/sama5d2.dtsi
@@ -737,6 +737,16 @@
 				secure-status = "okay";
 			};
 
+			sfc: sfc@f804c000 {
+				compatible = "atmel,sama5d2-sfc";
+				reg = <0xf804c000 0x64>;
+				read-only;
+				status = "disabled";
+				secure-status = "okay";
+				#address-cells = <1>;
+				#size-cells = <1>;
+			};
+
 			i2s0: i2s@f8050000 {
 				compatible = "atmel,sama5d2-i2s";
 				reg = <0xf8050000 0x100>;
diff --git a/core/arch/arm/dts/stm32mp131.dtsi b/core/arch/arm/dts/stm32mp131.dtsi
index fb13a53df5d953e0338a14fc1ea5e19890b41a57..3ddfaab8ce23365b2dd7779c4e43b44d7cb63f2c 100644
--- a/core/arch/arm/dts/stm32mp131.dtsi
+++ b/core/arch/arm/dts/stm32mp131.dtsi
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2021-2022 - All Rights Reserved
+ * Copyright (C) STMicroelectronics 2021-2023 - All Rights Reserved
  * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
  */
 
@@ -83,6 +83,18 @@
 
 	};
 
+	sdmmc1_io: sdmmc1_io {
+		compatible = "st,stm32mp13-iod";
+		regulator-name = "sdmmc1_io";
+		regulator-always-on;
+	};
+
+	sdmmc2_io: sdmmc2_io {
+		compatible = "st,stm32mp13-iod";
+		regulator-name = "sdmmc2_io";
+		regulator-always-on;
+	};
+
 	soc {
 		compatible = "simple-bus";
 		#address-cells = <1>;
diff --git a/core/arch/arm/dts/stm32mp135f-dk.dts b/core/arch/arm/dts/stm32mp135f-dk.dts
index af22a610366418ecb4c3c68058845ef278ce4739..7357601bac99d47039438ab454f13ab51e15c28f 100644
--- a/core/arch/arm/dts/stm32mp135f-dk.dts
+++ b/core/arch/arm/dts/stm32mp135f-dk.dts
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2021-2022 - All Rights Reserved
+ * Copyright (C) STMicroelectronics 2021-2023 - All Rights Reserved
  * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
  */
 
@@ -8,6 +8,7 @@
 
 #include <dt-bindings/clock/stm32mp13-clksrc.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/gpio/stm32mp_gpio.h>
 #include <dt-bindings/regulator/st,stm32mp13-regulator.h>
 #include "stm32mp135.dtsi"
 #include "stm32mp13xf.dtsi"
@@ -82,6 +83,18 @@
 	};
 };
 
+&gpiob {
+	st,protreg = <TZPROT(9)>;
+};
+
+&gpiod {
+	st,protreg = <TZPROT(7)>;
+};
+
+&gpioe {
+	st,protreg = <TZPROT(15)>;
+};
+
 &i2c4 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&i2c4_pins_a>;
@@ -446,6 +459,14 @@
 	status = "okay";
 };
 
+&sdmmc1_io {
+	vddsd1-supply = <&vdd>;
+};
+
+&sdmmc2_io {
+	vddsd2-supply = <&vdd>;
+};
+
 &uart4 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart4_pins_a>;
diff --git a/core/arch/arm/dts/stm32mp151.dtsi b/core/arch/arm/dts/stm32mp151.dtsi
index dce40957d7b1e185507fe7038cc249128dde76e8..d6729c8c1fd1e237e7269c0ed8f2f63260b60799 100644
--- a/core/arch/arm/dts/stm32mp151.dtsi
+++ b/core/arch/arm/dts/stm32mp151.dtsi
@@ -1839,8 +1839,8 @@
 			reg = <0x10000000 0x40000>,
 			      <0x30000000 0x40000>,
 			      <0x38000000 0x10000>;
-			resets = <&rcc MCU_R>;
-			st,syscfg-holdboot = <&rcc 0x10C 0x1>;
+			resets = <&rcc MCU_R>, <&rcc MCU_HOLD_BOOT_R>;
+			reset-names = "mcu_rst", "hold_boot";
 			st,syscfg-tz = <&rcc 0x000 0x1>;
 			st,syscfg-pdds = <&pwr_mcu 0x0 0x1>;
 			st,syscfg-rsc-tbl = <&tamp 0x144 0xFFFFFFFF>;
diff --git a/core/arch/arm/dts/stm32mp157a-dk1-scmi.dts b/core/arch/arm/dts/stm32mp157a-dk1-scmi.dts
new file mode 100644
index 0000000000000000000000000000000000000000..8236375389bf0e088aee2dd3eaa6fc8625e9b429
--- /dev/null
+++ b/core/arch/arm/dts/stm32mp157a-dk1-scmi.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2023
+ */
+
+/dts-v1/;
+
+#include "stm32mp157a-dk1.dts"
+
+/ {
+	model = "STMicroelectronics STM32MP157A-DK1 SCMI Discovery Board";
+	compatible = "st,stm32mp157a-dk1-scmi", "st,stm32mp157";
+};
+
+&rcc {
+	compatible = "st,stm32mp1-rcc-secure";
+	status = "okay";
+};
diff --git a/core/arch/arm/dts/stm32mp157a-dk1.dts b/core/arch/arm/dts/stm32mp157a-dk1.dts
index 7ba971e5b2a3fa2b621f0cd17efb57588754d1f4..294746da4ff279e66f3d390458ad777332cc190e 100644
--- a/core/arch/arm/dts/stm32mp157a-dk1.dts
+++ b/core/arch/arm/dts/stm32mp157a-dk1.dts
@@ -36,7 +36,3 @@
 		reg = <0xf0 0x10>;
 	};
 };
-
-&rcc {
-	status = "okay";
-};
diff --git a/core/arch/arm/dts/stm32mp157c-dk2-scmi.dts b/core/arch/arm/dts/stm32mp157c-dk2-scmi.dts
new file mode 100644
index 0000000000000000000000000000000000000000..e80e2a47c1e3ede6fe99bbc067b6596eea9aa737
--- /dev/null
+++ b/core/arch/arm/dts/stm32mp157c-dk2-scmi.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2023
+ */
+
+/dts-v1/;
+
+#include "stm32mp157c-dk2.dts"
+
+/ {
+	model = "STMicroelectronics STM32MP157C-DK2 SCMI Discovery Board";
+	compatible = "st,stm32mp157c-dk2-scmi", "st,stm32mp157";
+};
+
+&rcc {
+	compatible = "st,stm32mp1-rcc-secure";
+	status = "okay";
+};
diff --git a/core/arch/arm/dts/stm32mp157c-dk2.dts b/core/arch/arm/dts/stm32mp157c-dk2.dts
index b82730cbcbec4a1403009afed411504bda5548f5..dfb8f9830fd61235084ec7e285792d0788eaac80 100644
--- a/core/arch/arm/dts/stm32mp157c-dk2.dts
+++ b/core/arch/arm/dts/stm32mp157c-dk2.dts
@@ -98,10 +98,6 @@
 	};
 };
 
-&rcc {
-	status = "okay";
-};
-
 &usart2 {
 	pinctrl-names = "default", "sleep", "idle";
 	pinctrl-0 = <&usart2_pins_c>;
diff --git a/core/arch/arm/dts/stm32mp157c-ed1-scmi.dts b/core/arch/arm/dts/stm32mp157c-ed1-scmi.dts
new file mode 100644
index 0000000000000000000000000000000000000000..19cf9bc6b9368a5ec5c3c1f1fd4da979639e367c
--- /dev/null
+++ b/core/arch/arm/dts/stm32mp157c-ed1-scmi.dts
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2023
+ */
+/dts-v1/;
+
+#include "stm32mp157c-ed1.dts"
+
+/ {
+	model = "STMicroelectronics STM32MP157C SCMI eval daughter";
+	compatible = "st,stm32mp157c-ed1-scmi", "st,stm32mp157";
+};
+
+&iwdg1 {
+	timeout-sec = <32>;
+};
+
+&iwdg2 {
+	timeout-sec = <32>;
+	status = "okay";
+	secure-status = "disabled";
+};
+
+&rcc {
+	compatible = "st,stm32mp1-rcc-secure";
+	status = "okay";
+};
diff --git a/core/arch/arm/dts/stm32mp157c-ed1.dts b/core/arch/arm/dts/stm32mp157c-ed1.dts
index 1c5ab2d49868bb4999478b19ac11897830f09667..c0b4e1a294d69e8b8b1da94de7cdb51d666c4742 100644
--- a/core/arch/arm/dts/stm32mp157c-ed1.dts
+++ b/core/arch/arm/dts/stm32mp157c-ed1.dts
@@ -54,6 +54,12 @@
 			no-map;
 		};
 
+		ipc_shmem: ipc-shmem@1004f000 {
+			compatible = "shared-dma-pool";
+			reg = <0x10048000 0x8000>;
+			no-map;
+		};
+
 		mcuram: mcuram@30000000 {
 			compatible = "shared-dma-pool";
 			reg = <0x30000000 0x40000>;
@@ -253,6 +259,7 @@
 			vdd_usb: ldo4 {
 				regulator-name = "vdd_usb";
 				interrupts = <IT_CURLIM_LDO4 0>;
+				regulator-always-on;
 			};
 
 			vdd_sd: ldo5 {
@@ -313,17 +320,17 @@
 
 &iwdg1 {
 	timeout-sec = <32>;
+	status = "okay";
 };
 
 &iwdg2 {
 	timeout-sec = <32>;
-	status = "okay";
-	secure-status = "disabled";
+	status = "disabled";
 };
 
 &m4_rproc {
 	memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>,
-			<&vdev0vring1>, <&vdev0buffer>;
+			<&vdev0vring1>, <&vdev0buffer>, <&ipc_shmem>;
 	mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>, <&ipcc 3>;
 	mbox-names = "vq0", "vq1", "shutdown", "detach";
 	interrupt-parent = <&exti>;
@@ -337,6 +344,7 @@
 };
 
 &rcc {
+	compatible = "st,stm32mp1-rcc";
 	status = "okay";
 };
 
diff --git a/core/arch/arm/dts/stm32mp157c-ev1-scmi.dts b/core/arch/arm/dts/stm32mp157c-ev1-scmi.dts
new file mode 100644
index 0000000000000000000000000000000000000000..5474c9af46bc61068fe8d3ab5db0b1937c8365fb
--- /dev/null
+++ b/core/arch/arm/dts/stm32mp157c-ev1-scmi.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2023
+ */
+/dts-v1/;
+
+#include "stm32mp157c-ev1.dts"
+
+/ {
+	model = "STMicroelectronics STM32MP157C SCMI eval daughter on eval mother";
+	compatible = "st,stm32mp157c-ev1-scmi", "st,stm32mp157c-ed1-scmi", "st,stm32mp157";
+};
+
+&rcc {
+	compatible = "st,stm32mp1-rcc-secure";
+	status = "okay";
+};
diff --git a/core/arch/arm/dts/stm32mp15xx-dkx.dtsi b/core/arch/arm/dts/stm32mp15xx-dkx.dtsi
index cb4b6ac7d49244eaabbd10dc13d84c031ea3aa61..af5a0534455a43ba0f30232150ff6a2d5f55a497 100644
--- a/core/arch/arm/dts/stm32mp15xx-dkx.dtsi
+++ b/core/arch/arm/dts/stm32mp15xx-dkx.dtsi
@@ -42,6 +42,12 @@
 			no-map;
 		};
 
+		ipc_shmem: ipc-shmem@1004f000 {
+			compatible = "shared-dma-pool";
+			reg = <0x10048000 0x8000>;
+			no-map;
+		};
+
 		mcuram: mcuram@30000000 {
 			compatible = "shared-dma-pool";
 			reg = <0x30000000 0x40000>;
@@ -360,6 +366,7 @@
 			vdd_usb: ldo4 {
 				regulator-name = "vdd_usb";
 				interrupts = <IT_CURLIM_LDO4 0>;
+				regulator-always-on;
 			};
 
 			vdda: ldo5 {
@@ -451,12 +458,12 @@
 
 &iwdg1 {
 	timeout-sec = <32>;
+	status = "okay";
 };
 
 &iwdg2 {
 	timeout-sec = <32>;
-	status = "okay";
-	secure-status = "disabled";
+	status = "disabled";
 };
 
 &ltdc {
@@ -475,7 +482,7 @@
 
 &m4_rproc {
 	memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>,
-			<&vdev0vring1>, <&vdev0buffer>;
+			<&vdev0vring1>, <&vdev0buffer>, <&ipc_shmem>;
 	mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>, <&ipcc 3>;
 	mbox-names = "vq0", "vq1", "shutdown", "detach";
 	interrupt-parent = <&exti>;
@@ -488,6 +495,11 @@
 	vdd_3v3_usbfs-supply = <&vdd_usb>;
 };
 
+&rcc {
+	compatible = "st,stm32mp1-rcc";
+	status = "okay";
+};
+
 &rng1 {
 	status = "okay";
 };
diff --git a/core/arch/arm/dts/stm32mp25-pinctrl.dtsi b/core/arch/arm/dts/stm32mp25-pinctrl.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..5bd27767fbf5974dcbd14dd25e0aa8e167b975eb
--- /dev/null
+++ b/core/arch/arm/dts/stm32mp25-pinctrl.dtsi
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2023 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
+ */
+#include <dt-bindings/pinctrl/stm32-pinfunc.h>
+
diff --git a/core/arch/arm/dts/stm32mp251.dtsi b/core/arch/arm/dts/stm32mp251.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..edbf84679c5a646d97cd2328e6c3fe28b87d449c
--- /dev/null
+++ b/core/arch/arm/dts/stm32mp251.dtsi
@@ -0,0 +1,242 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2023 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			compatible = "arm,cortex-a35";
+			device_type = "cpu";
+			reg = <0>;
+			enable-method = "psci";
+		};
+	};
+
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
+	intc: interrupt-controller@4ac00000 {
+		compatible = "arm,cortex-a7-gic";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0x0 0x4ac10000 0x0 0x1000>,
+		      <0x0 0x4ac20000 0x0 0x2000>,
+		      <0x0 0x4ac40000 0x0 0x2000>,
+		      <0x0 0x4ac60000 0x0 0x2000>;
+		#address-cells = <1>;
+	};
+
+	clocks {
+		clk_hse: clk-hse {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <24000000>;
+		};
+
+		clk_hsi: clk-hsi {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <64000000>;
+		};
+
+		clk_lse: clk-lse {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		clk_lsi: clk-lsi {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <32000>;
+		};
+
+		clk_msi: clk-msi {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <4000000>;
+		};
+
+		clk_i2sin: clk-i2sin {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <0>;
+		};
+
+		clocks {
+			clk_rcbsec: clk-rcbsec {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <64000000>;
+			};
+		};
+	};
+
+	soc@0 {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		interrupt-parent = <&intc>;
+		ranges = <0x0 0x0 0x0 0x80000000>;
+
+		rifsc: rifsc@42080000 {
+			reg = <0x42080000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			usart2: serial@400e0000 {
+				reg = <0x400e0000 0x400>;
+				status = "disabled";
+			};
+		};
+
+		pinctrl: pinctrl@44240000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "st,stm32mp257-pinctrl";
+			ranges = <0 0x44240000 0xa0400>;
+			pins-are-numbered;
+
+			gpioa: gpio@44240000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x0 0x400>;
+				st,bank-name = "GPIOA";
+				status = "disabled";
+			};
+
+			gpiob: gpio@44250000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x10000 0x400>;
+				st,bank-name = "GPIOB";
+				status = "disabled";
+			};
+
+			gpioc: gpio@44260000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x20000 0x400>;
+				st,bank-name = "GPIOC";
+				status = "disabled";
+			};
+
+			gpiod: gpio@44270000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x30000 0x400>;
+				st,bank-name = "GPIOD";
+				status = "disabled";
+			};
+
+			gpioe: gpio@44280000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x40000 0x400>;
+				st,bank-name = "GPIOE";
+				status = "disabled";
+			};
+
+			gpiof: gpio@44290000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x50000 0x400>;
+				st,bank-name = "GPIOF";
+				status = "disabled";
+			};
+
+			gpiog: gpio@442a0000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x60000 0x400>;
+				st,bank-name = "GPIOG";
+				status = "disabled";
+			};
+
+			gpioh: gpio@442b0000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x70000 0x400>;
+				st,bank-name = "GPIOH";
+				status = "disabled";
+			};
+
+			gpioi: gpio@442c0000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x80000 0x400>;
+				st,bank-name = "GPIOI";
+				status = "disabled";
+			};
+
+			gpioj: gpio@442d0000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x90000 0x400>;
+				st,bank-name = "GPIOJ";
+				status = "disabled";
+			};
+
+			gpiok: gpio@442e0000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0xa0000 0x400>;
+				st,bank-name = "GPIOK";
+				status = "disabled";
+			};
+		};
+
+		pinctrl_z: pinctrl-z@46200000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "st,stm32mp257-z-pinctrl";
+			ranges = <0 0x46200000 0x400>;
+			pins-are-numbered;
+
+			gpioz: gpio@46200000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0 0x400>;
+				st,bank-name = "GPIOZ";
+				st,bank-ioport = <11>;
+				status = "disabled";
+			};
+		};
+	};
+};
diff --git a/core/arch/arm/dts/stm32mp253.dtsi b/core/arch/arm/dts/stm32mp253.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..93b7ab8dbc8fecb4193610216610659d33c90835
--- /dev/null
+++ b/core/arch/arm/dts/stm32mp253.dtsi
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2023 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
+ */
+#include "stm32mp251.dtsi"
+
+/ {
+	cpus {
+		cpu1: cpu@1 {
+			compatible = "arm,cortex-a35";
+			device_type = "cpu";
+			reg = <1>;
+			enable-method = "psci";
+		};
+	};
+};
diff --git a/core/arch/arm/dts/stm32mp255.dtsi b/core/arch/arm/dts/stm32mp255.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..e6fa596211f5c0aa5f5b8e338fd354e5ae0ee213
--- /dev/null
+++ b/core/arch/arm/dts/stm32mp255.dtsi
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2023 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
+ */
+#include "stm32mp253.dtsi"
+
+/ {
+};
diff --git a/core/arch/arm/dts/stm32mp257.dtsi b/core/arch/arm/dts/stm32mp257.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..5c5000d3d9dbc2064c3f3aad3a349403a64027f4
--- /dev/null
+++ b/core/arch/arm/dts/stm32mp257.dtsi
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2023 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
+ */
+#include "stm32mp255.dtsi"
+
+/ {
+};
diff --git a/core/arch/arm/dts/stm32mp257f-ev1.dts b/core/arch/arm/dts/stm32mp257f-ev1.dts
new file mode 100644
index 0000000000000000000000000000000000000000..3219c1e12f8d1495442ce7c220b917064699d854
--- /dev/null
+++ b/core/arch/arm/dts/stm32mp257f-ev1.dts
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2023 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
+ */
+
+/dts-v1/;
+
+#include "stm32mp25-pinctrl.dtsi"
+#include "stm32mp257.dtsi"
+#include "stm32mp25xf.dtsi"
+#include "stm32mp25xxai-pinctrl.dtsi"
+
+/ {
+	model = "STMicroelectronics STM32MP257F-EV1 Evaluation Board";
+	compatible = "st,stm32mp257f-ev1", "st,stm32mp257";
+
+	aliases {
+		serial0 = &usart2;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x0 0x80000000 0x1 0x00000000>;
+	};
+};
diff --git a/core/arch/arm/dts/stm32mp25xc.dtsi b/core/arch/arm/dts/stm32mp25xc.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..5e83a6926485f82c911b5553c42927ea5b7b8a0a
--- /dev/null
+++ b/core/arch/arm/dts/stm32mp25xc.dtsi
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2023 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
+ */
+
+/ {
+};
diff --git a/core/arch/arm/dts/stm32mp25xf.dtsi b/core/arch/arm/dts/stm32mp25xf.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..5e83a6926485f82c911b5553c42927ea5b7b8a0a
--- /dev/null
+++ b/core/arch/arm/dts/stm32mp25xf.dtsi
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2023 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
+ */
+
+/ {
+};
diff --git a/core/arch/arm/dts/stm32mp25xxai-pinctrl.dtsi b/core/arch/arm/dts/stm32mp25xxai-pinctrl.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..4fb8920114e8e6069b2fa9f14fc3ee86a68b08b0
--- /dev/null
+++ b/core/arch/arm/dts/stm32mp25xxai-pinctrl.dtsi
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2023 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
+ */
+
+&pinctrl {
+	gpioa: gpio@44240000 {
+		status = "okay";
+		ngpios = <16>;
+		gpio-ranges = <&pinctrl 0 0 16>;
+	};
+
+	gpiob: gpio@44250000 {
+		status = "okay";
+		ngpios = <16>;
+		gpio-ranges = <&pinctrl 0 16 16>;
+	};
+
+	gpioc: gpio@44260000 {
+		status = "okay";
+		ngpios = <14>;
+		gpio-ranges = <&pinctrl 0 32 14>;
+	};
+
+	gpiod: gpio@44270000 {
+		status = "okay";
+		ngpios = <16>;
+		gpio-ranges = <&pinctrl 0 48 16>;
+	};
+
+	gpioe: gpio@44280000 {
+		status = "okay";
+		ngpios = <16>;
+		gpio-ranges = <&pinctrl 0 64 16>;
+	};
+
+	gpiof: gpio@44290000 {
+		status = "okay";
+		ngpios = <16>;
+		gpio-ranges = <&pinctrl 0 80 16>;
+	};
+
+	gpiog: gpio@442a0000 {
+		status = "okay";
+		ngpios = <16>;
+		gpio-ranges = <&pinctrl 0 96 16>;
+	};
+
+	gpioh: gpio@442b0000 {
+		status = "okay";
+		ngpios = <12>;
+		gpio-ranges = <&pinctrl 2 114 12>;
+	};
+
+	gpioi: gpio@442c0000 {
+		status = "okay";
+		ngpios = <16>;
+		gpio-ranges = <&pinctrl 0 128 16>;
+	};
+
+	gpioj: gpio@442d0000 {
+		status = "okay";
+		ngpios = <16>;
+		gpio-ranges = <&pinctrl 0 144 16>;
+	};
+
+	gpiok: gpio@442e0000 {
+		status = "okay";
+		ngpios = <8>;
+		gpio-ranges = <&pinctrl 0 160 8>;
+	};
+};
+
+&pinctrl_z {
+	gpioz: gpio@46200000 {
+		status = "okay";
+		ngpios = <10>;
+		gpio-ranges = <&pinctrl_z 0 400 10>;
+	};
+};
diff --git a/core/arch/arm/dts/stm32mp25xxak-pinctrl.dtsi b/core/arch/arm/dts/stm32mp25xxak-pinctrl.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..b758b2ceee21e0b13356af737535e30b6cf0744f
--- /dev/null
+++ b/core/arch/arm/dts/stm32mp25xxak-pinctrl.dtsi
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2023 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
+ */
+
+&pinctrl {
+	gpioa: gpio@44240000 {
+		status = "okay";
+		ngpios = <16>;
+		gpio-ranges = <&pinctrl 0 0 16>;
+	};
+
+	gpiob: gpio@44250000 {
+		status = "okay";
+		ngpios = <16>;
+		gpio-ranges = <&pinctrl 0 16 16>;
+	};
+
+	gpioc: gpio@44260000 {
+		status = "okay";
+		ngpios = <14>;
+		gpio-ranges = <&pinctrl 0 32 14>;
+	};
+
+	gpiod: gpio@44270000 {
+		status = "okay";
+		ngpios = <16>;
+		gpio-ranges = <&pinctrl 0 48 16>;
+	};
+
+	gpioe: gpio@44280000 {
+		status = "okay";
+		ngpios = <16>;
+		gpio-ranges = <&pinctrl 0 64 16>;
+	};
+
+	gpiof: gpio@44290000 {
+		status = "okay";
+		ngpios = <16>;
+		gpio-ranges = <&pinctrl 0 80 16>;
+	};
+
+	gpiog: gpio@442a0000 {
+		status = "okay";
+		ngpios = <16>;
+		gpio-ranges = <&pinctrl 0 96 16>;
+	};
+
+	gpioh: gpio@442b0000 {
+		status = "okay";
+		ngpios = <12>;
+		gpio-ranges = <&pinctrl 2 114 12>;
+	};
+
+	gpioi: gpio@442c0000 {
+		status = "okay";
+		ngpios = <12>;
+		gpio-ranges = <&pinctrl 0 128 12>;
+	};
+};
+
+&pinctrl_z {
+	gpioz: gpio@46200000 {
+		status = "okay";
+		ngpios = <10>;
+		gpio-ranges = <&pinctrl_z 0 400 10>;
+	};
+};
diff --git a/core/arch/arm/dts/stm32mp25xxal-pinctrl.dtsi b/core/arch/arm/dts/stm32mp25xxal-pinctrl.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..b758b2ceee21e0b13356af737535e30b6cf0744f
--- /dev/null
+++ b/core/arch/arm/dts/stm32mp25xxal-pinctrl.dtsi
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2023 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
+ */
+
+&pinctrl {
+	gpioa: gpio@44240000 {
+		status = "okay";
+		ngpios = <16>;
+		gpio-ranges = <&pinctrl 0 0 16>;
+	};
+
+	gpiob: gpio@44250000 {
+		status = "okay";
+		ngpios = <16>;
+		gpio-ranges = <&pinctrl 0 16 16>;
+	};
+
+	gpioc: gpio@44260000 {
+		status = "okay";
+		ngpios = <14>;
+		gpio-ranges = <&pinctrl 0 32 14>;
+	};
+
+	gpiod: gpio@44270000 {
+		status = "okay";
+		ngpios = <16>;
+		gpio-ranges = <&pinctrl 0 48 16>;
+	};
+
+	gpioe: gpio@44280000 {
+		status = "okay";
+		ngpios = <16>;
+		gpio-ranges = <&pinctrl 0 64 16>;
+	};
+
+	gpiof: gpio@44290000 {
+		status = "okay";
+		ngpios = <16>;
+		gpio-ranges = <&pinctrl 0 80 16>;
+	};
+
+	gpiog: gpio@442a0000 {
+		status = "okay";
+		ngpios = <16>;
+		gpio-ranges = <&pinctrl 0 96 16>;
+	};
+
+	gpioh: gpio@442b0000 {
+		status = "okay";
+		ngpios = <12>;
+		gpio-ranges = <&pinctrl 2 114 12>;
+	};
+
+	gpioi: gpio@442c0000 {
+		status = "okay";
+		ngpios = <12>;
+		gpio-ranges = <&pinctrl 0 128 12>;
+	};
+};
+
+&pinctrl_z {
+	gpioz: gpio@46200000 {
+		status = "okay";
+		ngpios = <10>;
+		gpio-ranges = <&pinctrl_z 0 400 10>;
+	};
+};
diff --git a/core/arch/arm/include/arm.h b/core/arch/arm/include/arm.h
index 0eea4385665c13b6373723f5b9df4da3d8c7ce35..43504ba5b05ab501b0c8817c676497c8b8786f4d 100644
--- a/core/arch/arm/include/arm.h
+++ b/core/arch/arm/include/arm.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2015, Linaro Limited
  * Copyright (c) 2019-2023, Arm Limited. All rights reserved.
  */
-#ifndef ARM_H
-#define ARM_H
+#ifndef __ARM_H
+#define __ARM_H
 
 #include <stdbool.h>
 #include <stdint.h>
@@ -200,4 +200,4 @@ static inline bool feat_pauth_is_implemented(void)
 
 #endif
 
-#endif /*ARM_H*/
+#endif /*__ARM_H*/
diff --git a/core/arch/arm/include/arm32.h b/core/arch/arm/include/arm32.h
index 253b197ff1fa410deaf99d8c6bf50acc0310be60..ef729d492dbced44ac4e19d71552fdbc3394285b 100644
--- a/core/arch/arm/include/arm32.h
+++ b/core/arch/arm/include/arm32.h
@@ -4,8 +4,8 @@
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
-#ifndef ARM32_H
-#define ARM32_H
+#ifndef __ARM32_H
+#define __ARM32_H
 
 #include <compiler.h>
 #include <sys/cdefs.h>
@@ -278,4 +278,4 @@ static __always_inline __noprof uint32_t read_r7(void)
 
 #endif /*__ASSEMBLER__*/
 
-#endif /*ARM32_H*/
+#endif /*__ARM32_H*/
diff --git a/core/arch/arm/include/arm64.h b/core/arch/arm/include/arm64.h
index 8c210b3fa4ee42f407389d9f81f6c62db5ed9073..23a21c41c42e6b86a941b2b05515dadf9b09f4f8 100644
--- a/core/arch/arm/include/arm64.h
+++ b/core/arch/arm/include/arm64.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2015, Linaro Limited
  * Copyright (c) 2023, Arm Limited
  */
-#ifndef ARM64_H
-#define ARM64_H
+#ifndef __ARM64_H
+#define __ARM64_H
 
 #include <compiler.h>
 #include <sys/cdefs.h>
@@ -240,6 +240,8 @@
 #define FEAT_MTE2_IMPLEMENTED		U(0x2)
 #define FEAT_MTE3_IMPLEMENTED		U(0x3)
 
+#define ID_AA64MMFR0_EL1_PARANGE_MASK	UL(0xf)
+
 #define ID_AA64MMFR1_EL1_PAN_MASK	UL(0xf)
 #define ID_AA64MMFR1_EL1_PAN_SHIFT	U(20)
 #define FEAT_PAN_NOT_IMPLEMENTED	U(0x0)
@@ -371,6 +373,19 @@ static inline void write_64bit_pair(uint64_t dst, uint64_t hi, uint64_t lo)
 		      "r" (hi), "r" (lo), "r" (dst) : "memory");
 }
 
+static inline void read_64bit_pair(uint64_t src, uint64_t *hi, uint64_t *lo)
+{
+	uint64_t tmp0 = 0;
+	uint64_t tmp1 = 0;
+
+	/* 128bits should be read from hardware at one time */
+	asm volatile ("ldp %0, %1, [%2]\n" : "=&r"(tmp0), "=&r"(tmp1) :
+		      "r"(src) : "memory");
+
+	*lo = tmp0;
+	*hi = tmp1;
+}
+
 /*
  * Templates for register read/write functions based on mrs/msr
  */
@@ -455,6 +470,7 @@ DEFINE_U64_REG_READ_FUNC(par_el1)
 
 DEFINE_U64_REG_WRITE_FUNC(mair_el1)
 
+DEFINE_U64_REG_READ_FUNC(id_aa64mmfr0_el1)
 DEFINE_U64_REG_READ_FUNC(id_aa64mmfr1_el1)
 DEFINE_U64_REG_READ_FUNC(id_aa64pfr1_el1)
 DEFINE_U64_REG_READ_FUNC(id_aa64isar0_el1)
@@ -504,5 +520,5 @@ static inline void write_pan_disable(void)
 
 #endif /*__ASSEMBLER__*/
 
-#endif /*ARM64_H*/
+#endif /*__ARM64_H*/
 
diff --git a/core/arch/arm/include/crypto/ghash-ce-core.h b/core/arch/arm/include/crypto/ghash-ce-core.h
index b0f9f5457f988492c5726e89849087dbb973280f..e2be237f8baa81a00929387e0792334d956b1e31 100644
--- a/core/arch/arm/include/crypto/ghash-ce-core.h
+++ b/core/arch/arm/include/crypto/ghash-ce-core.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2017-2020, Linaro Limited
  */
 
-#ifndef __GHASH_CE_CORE_H
-#define __GHASH_CE_CORE_H
+#ifndef __CRYPTO_GHASH_CE_CORE_H
+#define __CRYPTO_GHASH_CE_CORE_H
 
 #include <inttypes.h>
 
@@ -40,4 +40,4 @@ uint32_t pmull_gcm_aes_sub(uint32_t input);
 
 void pmull_gcm_encrypt_block(uint8_t dst[], const uint8_t src[], int rounds);
 
-#endif /*__GHASH_CE_CORE_H*/
+#endif /*__CRYPTO_GHASH_CE_CORE_H*/
diff --git a/core/arch/arm/include/ffa.h b/core/arch/arm/include/ffa.h
index c54479b663eec27721fcf64c5590f8d9febedfe4..1a7baccfb1f21c4dcacdb73a3f14a196f2498c0f 100644
--- a/core/arch/arm/include/ffa.h
+++ b/core/arch/arm/include/ffa.h
@@ -92,6 +92,9 @@
 #define FFA_CONSOLE_LOG_32		U(0x8400008A)
 #define FFA_CONSOLE_LOG_64		U(0xC400008A)
 
+#define FFA_FEATURES_FUNC_ID_MASK	BIT32(31)
+#define FFA_FEATURES_FEATURE_ID_MASK	GENMASK_32(7, 0)
+
 #define FFA_FEATURE_NOTIF_PEND_INTR	U(0x1)
 #define FFA_FEATURE_SCHEDULE_RECV_INTR	U(0x2)
 #define FFA_FEATURE_MANAGED_EXIT_INTR	U(0x3)
diff --git a/core/arch/arm/include/kernel/misc_arch.h b/core/arch/arm/include/kernel/misc_arch.h
index 0653119d569171e967ef60444f0467f8c3a0b157..992c75f7c8cf107a302bd02e3e0f23a81f916975 100644
--- a/core/arch/arm/include/kernel/misc_arch.h
+++ b/core/arch/arm/include/kernel/misc_arch.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
-#ifndef KERNEL_MISC_ARCH_H
-#define KERNEL_MISC_ARCH_H
+#ifndef __KERNEL_MISC_ARCH_H
+#define __KERNEL_MISC_ARCH_H
 
 #include <arm.h>
 #include <kernel/thread.h>
@@ -17,4 +17,4 @@ uint32_t read_mode_lr(int cpu_mode);
 
 void wait_cycles(unsigned long cycles);
 
-#endif /*KERNEL_MISC_ARCH_H*/
+#endif /*__KERNEL_MISC_ARCH_H*/
diff --git a/core/arch/arm/include/kernel/tee_l2cc_mutex.h b/core/arch/arm/include/kernel/tee_l2cc_mutex.h
index 1011fced92ff0c58bde220b6a94a46df3d147d3d..7fb5af3e2872aa39fb438560e8c7c36b3b1a227f 100644
--- a/core/arch/arm/include/kernel/tee_l2cc_mutex.h
+++ b/core/arch/arm/include/kernel/tee_l2cc_mutex.h
@@ -2,8 +2,9 @@
 /*
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
-#ifndef TEE_L2CC_MUTEX_H
-#define TEE_L2CC_MUTEX_H
+#ifndef __KERNEL_TEE_L2CC_MUTEX_H
+#define __KERNEL_TEE_L2CC_MUTEX_H
+
 #include <inttypes.h>
 #include <tee_api_types.h>
 #include <tee_api_defines.h>
@@ -47,4 +48,4 @@ static inline TEE_Result tee_set_l2cc_mutex(paddr_t *mutex __unused)
 }
 #endif
 
-#endif /* TEE_L2CC_MUTEX_H */
+#endif /* __KERNEL_TEE_L2CC_MUTEX_H */
diff --git a/core/arch/arm/include/kernel/thread_spmc.h b/core/arch/arm/include/kernel/thread_spmc.h
index ffef0903633f2f8bd8dcf0ba262749c14ee58eb2..672bc2cc82ebfb5c80f18d223fbf6cbdab6cc7e9 100644
--- a/core/arch/arm/include/kernel/thread_spmc.h
+++ b/core/arch/arm/include/kernel/thread_spmc.h
@@ -1,11 +1,14 @@
 /* SPDX-License-Identifier: BSD-2-Clause */
 /*
  * Copyright (c) 2021, Arm Limited.
+ * Copyright (c) 2023, Linaro Limited
  */
 #ifndef __KERNEL_THREAD_SPMC_H
 #define __KERNEL_THREAD_SPMC_H
 
+#include <compiler.h>
 #include <ffa.h>
+#include <kernel/panic.h>
 #include <kernel/thread.h>
 
 /* FF-A endpoint base ID when OP-TEE is used as a S-EL1 endpoint */
@@ -37,7 +40,14 @@ TEE_Result spmc_fill_partition_entry(uint32_t ffa_vers, void *buf, size_t blen,
 int spmc_read_mem_transaction(uint32_t ffa_vers, void *buf, size_t blen,
 			      struct ffa_mem_transaction_x *trans);
 
-#if !defined(CFG_CORE_SEL1_SPMC)
+#if defined(CFG_CORE_SEL1_SPMC)
+void thread_spmc_set_async_notif_intid(int intid);
+#else
+static inline void __noreturn
+thread_spmc_set_async_notif_intid(int intid __unused)
+{
+	panic();
+}
 struct mobj_ffa *thread_spmc_populate_mobj_from_rx(uint64_t cookie);
 void thread_spmc_relinquish(uint64_t memory_region_handle);
 #endif
diff --git a/core/arch/arm/include/kernel/tlb_helpers.h b/core/arch/arm/include/kernel/tlb_helpers.h
index 36a9af396cd2c89ded256a55cad0a9dd8a214f88..92d596aeedacf3ed9d3ed8379c5867aacb09a4cb 100644
--- a/core/arch/arm/include/kernel/tlb_helpers.h
+++ b/core/arch/arm/include/kernel/tlb_helpers.h
@@ -4,8 +4,8 @@
  * Copyright (c) 2017, Linaro Limited
  */
 
-#ifndef TLB_HELPERS_H
-#define TLB_HELPERS_H
+#ifndef __KERNEL_TLB_HELPERS_H
+#define __KERNEL_TLB_HELPERS_H
 
 #include <arm.h>
 
@@ -48,4 +48,4 @@ static inline void tlbi_va_asid(vaddr_t va, uint32_t asid)
 }
 #endif /*!__ASSEMBLER__*/
 
-#endif /* TLB_HELPERS_H */
+#endif /* __KERNEL_TLB_HELPERS_H */
diff --git a/core/arch/arm/include/kernel/tz_proc_def.h b/core/arch/arm/include/kernel/tz_proc_def.h
index 6e9097dfe072f561d8ec087624d59d4674003a6e..2d69b853e00f9492ac2852ee7e25de873254ccb0 100644
--- a/core/arch/arm/include/kernel/tz_proc_def.h
+++ b/core/arch/arm/include/kernel/tz_proc_def.h
@@ -3,6 +3,9 @@
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
+#ifndef __KERNEL_TZ_PROC_DEF_H
+#define __KERNEL_TZ_PROC_DEF_H
+
 #include <stdint.h>
 
 /*
@@ -89,3 +92,5 @@
 #define LINE_FIELD_OVERFLOW      U(13)
 /* start of way number field offset in way/index format */
 #define WAY_FIELD_OFFSET         U(30)
+
+#endif /*__KERNEL_TZ_PROC_DEF_H*/
diff --git a/core/arch/arm/include/kernel/tz_ssvce_def.h b/core/arch/arm/include/kernel/tz_ssvce_def.h
index 25215b537f7cd3a12f2ca465a7c06d540ca2fb9d..e69e81b7a9017d291d2adde2994557bbb0c884cc 100644
--- a/core/arch/arm/include/kernel/tz_ssvce_def.h
+++ b/core/arch/arm/include/kernel/tz_ssvce_def.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
-#ifndef TZ_SSVCE_DEF_H
-#define TZ_SSVCE_DEF_H
+#ifndef __KERNEL_TZ_SSVCE_DEF_H
+#define __KERNEL_TZ_SSVCE_DEF_H
 
 #include <stdint.h>
 #include <util.h>
@@ -125,4 +125,4 @@
  */
 #define CORE_ICC_ICCPMR	U(0x0004)
 
-#endif /* TZ_SSVCE_DEF_H */
+#endif /* __KERNEL_TZ_SSVCE_DEF_H */
diff --git a/core/arch/arm/include/kernel/tz_ssvce_pl310.h b/core/arch/arm/include/kernel/tz_ssvce_pl310.h
index 2bcd26ebe757f31467349301ce6255ab7b89107b..7112c095eed7f063760242847bf9cb2639fdba24 100644
--- a/core/arch/arm/include/kernel/tz_ssvce_pl310.h
+++ b/core/arch/arm/include/kernel/tz_ssvce_pl310.h
@@ -3,14 +3,16 @@
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
-#ifndef TZ_SSVCE_PL310_H
-#define TZ_SSVCE_PL310_H
+#ifndef __KERNEL_TZ_SSVCE_PL310_H
+#define __KERNEL_TZ_SSVCE_PL310_H
 
 #include <util.h>
 #include <kernel/tz_ssvce_def.h>
 #include <types_ext.h>
 
 vaddr_t pl310_base(void);
+vaddr_t pl310_nsbase(void);
+
 /*
  * End address is included in the range (last address in range)
  */
@@ -21,4 +23,4 @@ void arm_cl2_cleanbypa(vaddr_t pl310_base, paddr_t start, paddr_t end);
 void arm_cl2_invbypa(vaddr_t pl310_base, paddr_t start, paddr_t end);
 void arm_cl2_cleaninvbypa(vaddr_t pl310_base, paddr_t start, paddr_t end);
 
-#endif /* TZ_SSVCE_PL310_H */
+#endif /* __KERNEL_TZ_SSVCE_PL310_H */
diff --git a/core/arch/arm/include/kernel/vfp.h b/core/arch/arm/include/kernel/vfp.h
index 49c0d736ce7506db989bccb8d5a6fca50271008d..f42ca9795f7e08ecd6f9a512d488c40b63140116 100644
--- a/core/arch/arm/include/kernel/vfp.h
+++ b/core/arch/arm/include/kernel/vfp.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2015, Linaro Limited
  */
 
-#ifndef KERNEL_VFP_H
-#define KERNEL_VFP_H
+#ifndef __KERNEL_VFP_H
+#define __KERNEL_VFP_H
 
 #include <types_ext.h>
 #include <compiler.h>
@@ -103,4 +103,4 @@ void vfp_lazy_save_state_final(struct vfp_state *state, bool force_save);
  */
 void vfp_lazy_restore_state(struct vfp_state *state, bool full_state);
 
-#endif /*KERNEL_VFP_H*/
+#endif /*__KERNEL_VFP_H*/
diff --git a/core/arch/arm/include/mm/core_mmu_arch.h b/core/arch/arm/include/mm/core_mmu_arch.h
index 42f382fd5c26090e99c3d6f1ef06477b771f60f8..d8154d7efdff7e44ca5a6e50748c6c875882e90f 100644
--- a/core/arch/arm/include/mm/core_mmu_arch.h
+++ b/core/arch/arm/include/mm/core_mmu_arch.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2016, Linaro Limited
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
-#ifndef __CORE_MMU_ARCH_H
-#define __CORE_MMU_ARCH_H
+#ifndef __MM_CORE_MMU_ARCH_H
+#define __MM_CORE_MMU_ARCH_H
 
 #ifndef __ASSEMBLER__
 #include <arm.h>
@@ -175,10 +175,14 @@ static inline TEE_Result cache_op_outer(enum cache_op op __unused,
 /* Do section mapping, not support on LPAE */
 void map_memarea_sections(const struct tee_mmap_region *mm, uint32_t *ttb);
 
+#if defined(ARM64)
+unsigned int core_mmu_arm64_get_pa_width(void);
+#endif
+
 static inline bool core_mmu_check_max_pa(paddr_t pa __maybe_unused)
 {
 #if defined(ARM64)
-	return pa <= (BIT64(CFG_CORE_ARM64_PA_BITS) - 1);
+	return pa <= (BIT64(core_mmu_arm64_get_pa_width()) - 1);
 #elif defined(CFG_CORE_LARGE_PHYS_ADDR)
 	return pa <= (BIT64(40) - 1);
 #else
@@ -223,4 +227,4 @@ static inline bool core_mmu_level_in_range(unsigned int level)
 
 #endif /*__ASSEMBLER__*/
 
-#endif /* CORE_MMU_H */
+#endif /* __MM_CORE_MMU_ARCH_H */
diff --git a/core/arch/arm/include/mm/generic_ram_layout.h b/core/arch/arm/include/mm/generic_ram_layout.h
index b3e0ac393b3dda2da0ec6f6fa3ce73318d501c8e..367dd35760d16e9edefd72fcd8836f76ac159b5f 100644
--- a/core/arch/arm/include/mm/generic_ram_layout.h
+++ b/core/arch/arm/include/mm/generic_ram_layout.h
@@ -133,7 +133,7 @@
 #endif
 #endif
 
-#if defined(CFG_TZSRAM_START)
+#if defined(CFG_WITH_PAGER) && defined(CFG_TZSRAM_START)
 #define TZSRAM_BASE		CFG_TZSRAM_START
 #define TZSRAM_SIZE		CFG_TZSRAM_SIZE
 #endif
diff --git a/core/arch/arm/include/optee_ffa.h b/core/arch/arm/include/optee_ffa.h
index 8f1603946bf4a8590c1da37d2e7a5e42b23faad2..8db02650be578b26141d302bd2338b853020851d 100644
--- a/core/arch/arm/include/optee_ffa.h
+++ b/core/arch/arm/include/optee_ffa.h
@@ -74,7 +74,7 @@
  *
  * Call register usage:
  * w3:    Service ID, OPTEE_FFA_EXCHANGE_CAPABILITIES
- * w4-w7: Note used (MBZ)
+ * w4-w7: Not used (MBZ)
  *
  * Return register usage:
  * w3:    Error code, 0 on success
@@ -82,15 +82,17 @@
  *                   as the second MSG arg struct for
  *                   OPTEE_FFA_YIELDING_CALL_WITH_ARG.
  *        Bit[31:8]: Reserved (MBZ)
- * w5:	  Bitfield of secure world capabilities OPTEE_FFA_SEC_CAP_* below,
- *	  unused bits MBZ.
- * w6-w7: Not used (MBZ)
+ * w5:	  Bitfield of OP-TEE capabilities OPTEE_FFA_SEC_CAP_*
+ * w6:	  The maximum secure world notification number
+ * w7:	  Not used (MBZ)
  */
 /*
  * Secure world supports using an offset into the argument shared memory
  * object, see also OPTEE_FFA_YIELDING_CALL_WITH_ARG
  */
 #define OPTEE_FFA_SEC_CAP_ARG_OFFSET	BIT(0)
+/* OP-TEE supports asynchronous notification via FF-A */
+#define OPTEE_FFA_SEC_CAP_ASYNC_NOTIF	BIT(1)
 
 #define OPTEE_FFA_EXCHANGE_CAPABILITIES OPTEE_FFA_BLOCKING_CALL(2)
 
@@ -109,6 +111,21 @@
  */
 #define OPTEE_FFA_UNREGISTER_SHM	OPTEE_FFA_BLOCKING_CALL(3)
 
+/*
+ * Inform OP-TEE that normal world is able to receive asynchronous
+ * notifications.
+ *
+ * Call register usage:
+ * w3:    Service ID, OPTEE_FFA_ENABLE_ASYNC_NOTIF
+ * w4:	  Notification value to request bottom half processing
+ * w5-w7: Not used (MBZ)
+ *
+ * Return register usage:
+ * w3:    Error code, 0 on success
+ * w4-w7: Not used (MBZ)
+ */
+#define OPTEE_FFA_ENABLE_ASYNC_NOTIF	OPTEE_FFA_BLOCKING_CALL(5)
+
 /*
  * Call with struct optee_msg_arg as argument in the supplied shared memory
  * with a zero internal offset and normal cached memory attributes.
diff --git a/core/arch/arm/include/scmi/scmi_server.h b/core/arch/arm/include/scmi/scmi_server.h
index a28fd667f11daec57fdc46fee1c3a4e40d2acda3..d969e238d118660ca5a54886979ad42d91af7a99 100644
--- a/core/arch/arm/include/scmi/scmi_server.h
+++ b/core/arch/arm/include/scmi/scmi_server.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2019-2022, Linaro Limited
  */
-#ifndef SCMI_SERVER_H
-#define SCMI_SERVER_H
+#ifndef __SCMI_SCMI_SERVER_H
+#define __SCMI_SCMI_SERVER_H
 
 #include <tee_api_types.h>
 #include <types_ext.h>
@@ -70,4 +70,4 @@ static inline int scmi_server_get_channels_count(void)
 	return 0;
 }
 #endif /* CFG_SCMI_SCPFW */
-#endif /* SCMI_SERVER_H */
+#endif /* __SCMI_SCMI_SERVER_H */
diff --git a/core/arch/arm/include/sm/optee_smc.h b/core/arch/arm/include/sm/optee_smc.h
index 04a3839a2c183d4abd18b5da525208fd9bc5fd65..fe9aff0e1fc29135c7dda790d6372bcba324b7b8 100644
--- a/core/arch/arm/include/sm/optee_smc.h
+++ b/core/arch/arm/include/sm/optee_smc.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2015-2021, Linaro Limited
  */
-#ifndef OPTEE_SMC_H
-#define OPTEE_SMC_H
+#ifndef __SM_OPTEE_SMC_H
+#define __SM_OPTEE_SMC_H
 
 #include <stdint.h>
 
@@ -705,4 +705,4 @@
 	((((ret) & OPTEE_SMC_RETURN_RPC_PREFIX_MASK) == \
 		OPTEE_SMC_RETURN_RPC_PREFIX)))
 
-#endif /* OPTEE_SMC_H */
+#endif /* __SM_OPTEE_SMC_H */
diff --git a/core/arch/arm/include/sm/pm.h b/core/arch/arm/include/sm/pm.h
index 939f966e896b2765eb32bf1beac0932739bbfd96..351095a9bffc66d75fbc764a08a6eb52c455a9f7 100644
--- a/core/arch/arm/include/sm/pm.h
+++ b/core/arch/arm/include/sm/pm.h
@@ -26,8 +26,8 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef SM_PM_H
-#define SM_PM_H
+#ifndef __SM_PM_H
+#define __SM_PM_H
 #include <stdint.h>
 #include <types_ext.h>
 
diff --git a/core/arch/arm/include/sm/psci.h b/core/arch/arm/include/sm/psci.h
index b992e60ae62607764c078a10f71d7de0e33b4033..95ccdfa4c2149c67bf81d28066974c58978933d3 100644
--- a/core/arch/arm/include/sm/psci.h
+++ b/core/arch/arm/include/sm/psci.h
@@ -1,3 +1,10 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2017-2023, Linaro Limited
+ */
+#ifndef __SM_PSCI_H
+#define __SM_PSCI_H
+
 #include <kernel/thread.h>
 #include <sm/sm.h>
 #include <stdint.h>
@@ -79,3 +86,4 @@ int psci_stat_count(uint32_t cpu_id, uint32_t power_state);
 void tee_psci_handler(struct thread_smc_args *args, struct sm_nsec_ctx *nsec);
 
 void psci_armv7_cpu_off(void);
+#endif /* __SM_PSCI_H */
diff --git a/core/arch/arm/include/sm/sm.h b/core/arch/arm/include/sm/sm.h
index d33c5fc5ce29fb40664b8887a43ee5e430af9b82..9e7b9879149c3a15117257d4f2176390dffd60cc 100644
--- a/core/arch/arm/include/sm/sm.h
+++ b/core/arch/arm/include/sm/sm.h
@@ -4,8 +4,8 @@
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
-#ifndef SM_SM_H
-#define SM_SM_H
+#ifndef __SM_SM_H
+#define __SM_SM_H
 
 #ifndef __ASSEMBLER__
 
@@ -142,4 +142,4 @@ void vector_fiq_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3,
 #define SM_EXIT_TO_NON_SECURE		0
 #define SM_EXIT_TO_SECURE		1
 
-#endif /*SM_SM_H*/
+#endif /*__SM_SM_H*/
diff --git a/core/arch/arm/include/sm/std_smc.h b/core/arch/arm/include/sm/std_smc.h
index ce8606dcfdd711747c9b8de31c3e5bb57e4810e7..80e71a83107ea091c4dbed94b3656b813a2738c3 100644
--- a/core/arch/arm/include/sm/std_smc.h
+++ b/core/arch/arm/include/sm/std_smc.h
@@ -1,5 +1,9 @@
-#ifndef __STD_SMC_H__
-#define __STD_SMC_H__
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2017-2023, Linaro Limited
+ */
+#ifndef __SM_STD_SMC_H__
+#define __SM_STD_SMC_H__
 
 #include <sm/sm.h>
 
diff --git a/core/arch/arm/include/sm/teesmc_opteed.h b/core/arch/arm/include/sm/teesmc_opteed.h
index 41e7204d7fabf7f562177397dc8c1cfbf3e07d43..7213531aae270d6040a33f20d2229ae797ce5b17 100644
--- a/core/arch/arm/include/sm/teesmc_opteed.h
+++ b/core/arch/arm/include/sm/teesmc_opteed.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2014, Linaro Limited
  */
 
-#ifndef TEESMC_OPTEED_H
-#define TEESMC_OPTEED_H
+#ifndef __SM_TEESMC_OPTEED_H
+#define __SM_TEESMC_OPTEED_H
 
 /*
  * This file specify SMC function IDs used when returning from TEE to the
@@ -117,4 +117,4 @@
 #define TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE \
 	TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE)
 
-#endif /*TEESMC_OPTEED_H*/
+#endif /*__SM_TEESMC_OPTEED_H*/
diff --git a/core/arch/arm/include/sm/teesmc_opteed_macros.h b/core/arch/arm/include/sm/teesmc_opteed_macros.h
index fcc84b72f5bb8da35008c060e2b3c2b9bb4350b3..2171c62839a46edc960dcf1132812af5228dc367 100644
--- a/core/arch/arm/include/sm/teesmc_opteed_macros.h
+++ b/core/arch/arm/include/sm/teesmc_opteed_macros.h
@@ -3,11 +3,11 @@
  * Copyright (c) 2014, Linaro Limited
  */
 
-#ifndef TEESMC_OPTEED_MACROS_H
-#define TEESMC_OPTEED_MACROS_H
+#ifndef __SM_TEESMC_OPTEED_MACROS_H
+#define __SM_TEESMC_OPTEED_MACROS_H
 
 #define TEESMC_OPTEED_RV(func_num) \
 	OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_FAST_CALL, \
 			   OPTEE_SMC_OWNER_TRUSTED_OS_OPTEED, (func_num))
 
-#endif /*TEESMC_OPTEED_MACROS_H*/
+#endif /*__SM_TEESMC_OPTEED_MACROS_H*/
diff --git a/core/arch/arm/include/sm/watchdog_smc.h b/core/arch/arm/include/sm/watchdog_smc.h
index b8b55a489334f716f01e991fdaf0ba0522bee13c..555d519f79093f214cfa33009bd7ef9ada509241 100644
--- a/core/arch/arm/include/sm/watchdog_smc.h
+++ b/core/arch/arm/include/sm/watchdog_smc.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (C) STMicroelectronics 2023
  */
-#ifndef SM_WATCHDOG_SMC_H
-#define SM_WATCHDOG_SMC_H
+#ifndef __SM_WATCHDOG_SMC_H
+#define __SM_WATCHDOG_SMC_H
 
 /*
  * This file describes the secure watchdog management service.
@@ -78,4 +78,4 @@
  * a7		Hypervisor Client ID register
  */
 
-#endif /* SM_WATCHDOG_SMC_H */
+#endif /* __SM_WATCHDOG_SMC_H */
diff --git a/core/arch/arm/include/tee/entry_fast.h b/core/arch/arm/include/tee/entry_fast.h
index 0f6fef8cc75f866acfcaa8d8cd6488919963b0d9..b6e77dabfaae0ba721722cd82140ec5c93429111 100644
--- a/core/arch/arm/include/tee/entry_fast.h
+++ b/core/arch/arm/include/tee/entry_fast.h
@@ -4,8 +4,8 @@
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
-#ifndef TEE_ENTRY_FAST_H
-#define TEE_ENTRY_FAST_H
+#ifndef __TEE_ENTRY_FAST_H
+#define __TEE_ENTRY_FAST_H
 
 #include <kernel/thread.h>
 
@@ -30,4 +30,4 @@ size_t tee_entry_generic_get_api_call_count(void);
 void tee_entry_fast(struct thread_smc_args *args);
 void __tee_entry_fast(struct thread_smc_args *args);
 
-#endif /* TEE_ENTRY_FAST_H */
+#endif /* __TEE_ENTRY_FAST_H */
diff --git a/core/arch/arm/kernel/boot.c b/core/arch/arm/kernel/boot.c
index 9a132240eb213a9244060a04b62216101385eaa7..275eb8cfb242b0a69bf8d5172abe5e30144ce232 100644
--- a/core/arch/arm/kernel/boot.c
+++ b/core/arch/arm/kernel/boot.c
@@ -15,6 +15,7 @@
 #include <ffa.h>
 #include <initcall.h>
 #include <inttypes.h>
+#include <io.h>
 #include <keep.h>
 #include <kernel/asan.h>
 #include <kernel/boot.h>
@@ -25,6 +26,7 @@
 #include <kernel/tee_misc.h>
 #include <kernel/thread.h>
 #include <kernel/tpm.h>
+#include <kernel/transfer_list.h>
 #include <libfdt.h>
 #include <malloc.h>
 #include <memtag.h>
@@ -78,9 +80,12 @@ uint32_t sem_cpu_sync[CFG_TEE_CORE_NB_CORE];
 DECLARE_KEEP_PAGER(sem_cpu_sync);
 #endif
 
-#ifdef CFG_CORE_FFA
 static void *manifest_dt __nex_bss;
-#endif
+static unsigned long boot_arg_fdt __nex_bss;
+static unsigned long boot_arg_nsec_entry __nex_bss;
+static unsigned long boot_arg_pageable_part __nex_bss;
+static unsigned long boot_arg_transfer_list __nex_bss;
+static struct transfer_list_header *mapped_tl __nex_bss;
 
 #ifdef CFG_SECONDARY_INIT_CNTFRQ
 static uint32_t cntfrq;
@@ -673,7 +678,8 @@ static int add_optee_dt_node(struct dt_descriptor *dt)
 		uint32_t val[3] = { };
 
 		/* PPI are visible only in current CPU cluster */
-		static_assert(!CFG_CORE_ASYNC_NOTIF_GIC_INTID ||
+		static_assert(IS_ENABLED(CFG_CORE_FFA) ||
+			      !CFG_CORE_ASYNC_NOTIF_GIC_INTID ||
 			      (CFG_CORE_ASYNC_NOTIF_GIC_INTID >=
 			       GIC_SPI_BASE) ||
 			      ((CFG_TEE_CORE_NB_CORE <= 8) &&
@@ -973,8 +979,9 @@ void *get_manifest_dt(void)
 	return manifest_dt;
 }
 
-static void init_manifest_dt(unsigned long pa)
+static void reinit_manifest_dt(void)
 {
+	paddr_t pa = (unsigned long)manifest_dt;
 	void *fdt = NULL;
 	int ret = 0;
 
@@ -1018,7 +1025,7 @@ void *get_manifest_dt(void)
 	return NULL;
 }
 
-static void init_manifest_dt(unsigned long pa __unused)
+static void reinit_manifest_dt(void)
 {
 }
 #endif /*CFG_CORE_FFA*/
@@ -1170,17 +1177,21 @@ static bool cpu_nmfi_enabled(void)
  * Note: this function is weak just to make it possible to exclude it from
  * the unpaged area.
  */
-void __weak boot_init_primary_late(unsigned long fdt,
-				   unsigned long manifest)
+void __weak boot_init_primary_late(unsigned long fdt __unused,
+				   unsigned long manifest __unused)
 {
-	init_external_dt(fdt);
-	/*
-	 * With an SPMC at S-EL2 we have saved the physical fdt address
-	 * from the passed boot info.
-	 */
-	if (IS_ENABLED(CFG_CORE_SEL2_SPMC))
-		manifest = (unsigned long)get_manifest_dt();
-	init_manifest_dt(manifest);
+	size_t fdt_size = CFG_DTB_MAX_SIZE;
+
+	if (IS_ENABLED(CFG_TRANSFER_LIST) && mapped_tl) {
+		struct transfer_list_entry *tl_e = NULL;
+
+		tl_e = transfer_list_find(mapped_tl, TL_TAG_FDT);
+		if (tl_e)
+			fdt_size = tl_e->data_size;
+	}
+
+	init_external_dt(boot_arg_fdt, fdt_size);
+	reinit_manifest_dt();
 #ifdef CFG_CORE_SEL1_SPMC
 	tpm_map_log_area(get_manifest_dt());
 #else
@@ -1191,7 +1202,7 @@ void __weak boot_init_primary_late(unsigned long fdt,
 	configure_console_from_dt();
 
 	IMSG("OP-TEE version: %s", core_v_str);
-	if (IS_ENABLED(CFG_WARN_INSECURE)) {
+	if (IS_ENABLED(CFG_INSECURE)) {
 		IMSG("WARNING: This OP-TEE configuration might be insecure!");
 		IMSG("WARNING: Please check https://optee.readthedocs.io/en/latest/architecture/porting_guidelines.html");
 	}
@@ -1252,18 +1263,78 @@ static void init_secondary_helper(unsigned long nsec_entry)
  * Note: this function is weak just to make it possible to exclude it from
  * the unpaged area so that it lies in the init area.
  */
-void __weak boot_init_primary_early(unsigned long pageable_part,
-				    unsigned long nsec_entry __maybe_unused)
+void __weak boot_init_primary_early(void)
 {
+	unsigned long pageable_part = 0;
 	unsigned long e = PADDR_INVALID;
+	struct transfer_list_entry *tl_e = NULL;
 
-#if !defined(CFG_WITH_ARM_TRUSTED_FW)
-	e = nsec_entry;
-#endif
+	if (!IS_ENABLED(CFG_WITH_ARM_TRUSTED_FW))
+		e = boot_arg_nsec_entry;
+
+	if (IS_ENABLED(CFG_TRANSFER_LIST) && boot_arg_transfer_list) {
+		/* map and save the TL */
+		mapped_tl = transfer_list_map(boot_arg_transfer_list);
+		if (!mapped_tl)
+			panic("Failed to map transfer list");
+
+		transfer_list_dump(mapped_tl);
+		tl_e = transfer_list_find(mapped_tl, TL_TAG_FDT);
+		if (tl_e) {
+			/*
+			 * Expand the data size of the DTB entry to the maximum
+			 * allocable mapped memory to reserve sufficient space
+			 * for inserting new nodes, avoid potentially corrupting
+			 * next entries.
+			 */
+			uint32_t dtb_max_sz = mapped_tl->max_size -
+					      mapped_tl->size + tl_e->data_size;
+
+			if (!transfer_list_set_data_size(mapped_tl, tl_e,
+							 dtb_max_sz)) {
+				EMSG("Failed to extend DTB size to %#"PRIx32,
+				     dtb_max_sz);
+				panic();
+			}
+		}
+		tl_e = transfer_list_find(mapped_tl, TL_TAG_OPTEE_PAGABLE_PART);
+	}
+
+	if (IS_ENABLED(CFG_WITH_PAGER)) {
+		if (IS_ENABLED(CFG_TRANSFER_LIST) && tl_e)
+			pageable_part =
+				get_le64(transfer_list_entry_data(tl_e));
+		else
+			pageable_part = boot_arg_pageable_part;
+	}
 
 	init_primary(pageable_part, e);
 }
 
+static void boot_save_transfer_list(unsigned long zero_reg,
+				    unsigned long transfer_list,
+				    unsigned long fdt)
+{
+	struct transfer_list_header *tl = (void *)transfer_list;
+	struct transfer_list_entry *tl_e = NULL;
+
+	if (zero_reg != 0)
+		panic("Incorrect transfer list register convention");
+
+	if (!IS_ALIGNED_WITH_TYPE(transfer_list, struct transfer_list_header) ||
+	    !IS_ALIGNED(transfer_list, TL_ALIGNMENT_FROM_ORDER(tl->alignment)))
+		panic("Transfer list base address is not aligned");
+
+	if (transfer_list_check_header(tl) == TL_OPS_NONE)
+		panic("Invalid transfer list");
+
+	tl_e = transfer_list_find(tl, TL_TAG_FDT);
+	if (fdt != (unsigned long)transfer_list_entry_data(tl_e))
+		panic("DT does not match to the DT entry of the TL");
+
+	boot_arg_transfer_list = transfer_list;
+}
+
 #if defined(CFG_WITH_ARM_TRUSTED_FW)
 unsigned long boot_cpu_on_handler(unsigned long a0 __maybe_unused,
 				  unsigned long a1 __unused)
@@ -1321,13 +1392,17 @@ struct ns_entry_context *boot_core_hpen(void)
 
 #if defined(CFG_CORE_ASLR)
 #if defined(CFG_DT)
-unsigned long __weak get_aslr_seed(void *fdt)
+unsigned long __weak get_aslr_seed(void)
 {
+	void *fdt = NULL;
 	int rc = 0;
 	const uint64_t *seed = NULL;
 	int offs = 0;
 	int len = 0;
 
+	if (!IS_ENABLED(CFG_CORE_SEL2_SPMC))
+		fdt = (void *)boot_arg_fdt;
+
 	if (!fdt) {
 		DMSG("No fdt");
 		goto err;
@@ -1357,7 +1432,7 @@ err:
 	return plat_get_aslr_seed();
 }
 #else /*!CFG_DT*/
-unsigned long __weak get_aslr_seed(void *fdt __unused)
+unsigned long __weak get_aslr_seed(void)
 {
 	/* Try platform implementation */
 	return plat_get_aslr_seed();
@@ -1365,7 +1440,6 @@ unsigned long __weak get_aslr_seed(void *fdt __unused)
 #endif /*!CFG_DT*/
 #endif /*CFG_CORE_ASLR*/
 
-#if defined(CFG_CORE_FFA)
 static void *get_fdt_from_boot_info(struct ffa_boot_info_header_1_1 *hdr)
 {
 	struct ffa_boot_info_1_1 *desc = NULL;
@@ -1441,16 +1515,136 @@ static void get_sec_mem_from_manifest(void *fdt, paddr_t *base, size_t *size)
 	*size = num;
 }
 
-void __weak boot_save_boot_info(void *boot_info)
+void __weak boot_save_args(unsigned long a0, unsigned long a1,
+			   unsigned long a2, unsigned long a3,
+			   unsigned long a4 __maybe_unused)
 {
-	paddr_t base = 0;
-	size_t size = 0;
+	/*
+	 * Register use:
+	 *
+	 * Scenario A: Default arguments
+	 * a0   - CFG_CORE_FFA=y && CFG_CORE_SEL2_SPMC=n:
+	 *        if non-NULL holds the TOS FW config [1] address
+	 *      - CFG_CORE_FFA=y &&
+		  (CFG_CORE_SEL2_SPMC=y || CFG_CORE_EL3_SPMC=y):
+	 *        address of FF-A Boot Information Blob
+	 *      - CFG_CORE_FFA=n:
+	 *        if non-NULL holds the pagable part address
+	 * a1	- CFG_WITH_ARM_TRUSTED_FW=n (Armv7):
+	 *	  Armv7 standard bootarg #1 (kept track of in entry_a32.S)
+	 * a2   - CFG_CORE_SEL2_SPMC=n:
+	 *        if non-NULL holds the system DTB address
+	 *	- CFG_WITH_ARM_TRUSTED_FW=n (Armv7):
+	 *	  Armv7 standard bootarg #2 (system DTB address, kept track
+	 *	  of in entry_a32.S)
+	 * a3	- Not used
+	 * a4	- CFG_WITH_ARM_TRUSTED_FW=n:
+	 *	  Non-secure entry address
+	 *
+	 * [1] A TF-A concept: TOS_FW_CONFIG - Trusted OS Firmware
+	 * configuration file. Used by Trusted OS (BL32), that is, OP-TEE
+	 * here. This is also called Manifest DT, related to the Manifest DT
+	 * passed in the FF-A Boot Information Blob, but with a different
+	 * compatible string.
+
+	 * Scenario B: FW Handoff via Transfer List
+	 * Note: FF-A and non-secure entry are not yet supported with
+	 *       Transfer List
+	 * a0	- DTB address or 0 (AArch64)
+	 *	- must be 0 (AArch32)
+	 * a1	- TRANSFER_LIST_SIGNATURE | REG_CONVENTION_VER_MASK
+	 * a2	- must be 0 (AArch64)
+	 *	- DTB address or 0 (AArch32)
+	 * a3	- Transfer list base address
+	 * a4	- Not used
+	 */
 
-	manifest_dt = get_fdt_from_boot_info(boot_info);
-	if (IS_ENABLED(CFG_CORE_SEL2_SPMC) &&
-	    IS_ENABLED(CFG_CORE_PHYS_RELOCATABLE)) {
-		get_sec_mem_from_manifest(manifest_dt, &base, &size);
-		core_mmu_set_secure_memory(base, size);
+	if (IS_ENABLED(CFG_TRANSFER_LIST) &&
+	    a1 == (TRANSFER_LIST_SIGNATURE | REG_CONVENTION_VER_MASK)) {
+		if (IS_ENABLED(CFG_ARM64_core)) {
+			boot_save_transfer_list(a2, a3, a0);
+			boot_arg_fdt = a0;
+		} else {
+			boot_save_transfer_list(a0, a3, a2);
+			boot_arg_fdt = a2;
+		}
+		return;
+	}
+
+	if (!IS_ENABLED(CFG_CORE_SEL2_SPMC)) {
+#if defined(CFG_DT_ADDR)
+		boot_arg_fdt = CFG_DT_ADDR;
+#else
+		boot_arg_fdt = a2;
+#endif
+	}
+
+	if (IS_ENABLED(CFG_CORE_FFA)) {
+		if (IS_ENABLED(CFG_CORE_SEL2_SPMC) ||
+		    IS_ENABLED(CFG_CORE_EL3_SPMC))
+			manifest_dt = get_fdt_from_boot_info((void *)a0);
+		else
+			manifest_dt = (void *)a0;
+		if (IS_ENABLED(CFG_CORE_SEL2_SPMC) &&
+		    IS_ENABLED(CFG_CORE_PHYS_RELOCATABLE)) {
+			paddr_t base = 0;
+			size_t size = 0;
+
+			get_sec_mem_from_manifest(manifest_dt, &base, &size);
+			core_mmu_set_secure_memory(base, size);
+		}
+	} else {
+		if (IS_ENABLED(CFG_WITH_PAGER)) {
+#if defined(CFG_PAGEABLE_ADDR)
+			boot_arg_pageable_part = CFG_PAGEABLE_ADDR;
+#else
+			boot_arg_pageable_part = a0;
+#endif
+		}
+		if (!IS_ENABLED(CFG_WITH_ARM_TRUSTED_FW)) {
+#if defined(CFG_NS_ENTRY_ADDR)
+			boot_arg_nsec_entry = CFG_NS_ENTRY_ADDR;
+#else
+			boot_arg_nsec_entry = a4;
+#endif
+		}
 	}
 }
-#endif /*CFG_CORE_FFA*/
+
+#if defined(CFG_TRANSFER_LIST)
+static TEE_Result release_transfer_list(void)
+{
+	struct dt_descriptor *dt = get_external_dt_desc();
+
+	if (!mapped_tl)
+		return TEE_SUCCESS;
+
+	if (dt) {
+		int ret = 0;
+		struct transfer_list_entry *tl_e = NULL;
+
+		/*
+		 * Pack the DTB and update the transfer list before un-mapping
+		 */
+		ret = fdt_pack(dt->blob);
+		if (ret < 0) {
+			EMSG("Failed to pack Device Tree at 0x%" PRIxPA
+			     ": error %d", virt_to_phys(dt->blob), ret);
+			panic();
+		}
+
+		tl_e = transfer_list_find(mapped_tl, TL_TAG_FDT);
+		assert(dt->blob == transfer_list_entry_data(tl_e));
+		transfer_list_set_data_size(mapped_tl, tl_e,
+					    fdt_totalsize(dt->blob));
+		dt->blob = NULL;
+	}
+
+	transfer_list_unmap_sync(mapped_tl);
+	mapped_tl = NULL;
+
+	return TEE_SUCCESS;
+}
+
+boot_final(release_transfer_list);
+#endif
diff --git a/core/arch/arm/kernel/entry_a32.S b/core/arch/arm/kernel/entry_a32.S
index 2ef44c3d0d8aee3ea212a43c2fe4ffced400c433..a43d36afb7c81030acce22a66e2ea6895832bef1 100644
--- a/core/arch/arm/kernel/entry_a32.S
+++ b/core/arch/arm/kernel/entry_a32.S
@@ -163,51 +163,6 @@ END_FUNC reset_vect_table
 		write_sctlr r0
 	.endm
 
-#if defined(CFG_CORE_SEL1_SPMC) && defined(CFG_WITH_ARM_TRUSTED_FW)
-	/*
-	 * With OP-TEE as SPMC at S-EL1 the SPMD (SPD_spmd) in TF-A passes
-	 * the DTB in r0, pagable part in r1, and the rest of the registers
-	 * are unused
-	 *
-	 * Save boot arguments passed
-	 * entry r0, saved r6: device tree address
-	 * entry r1, saved r4: pagestore
-	 * saved r5, r7: Zero
-	 */
-	.macro bootargs_entry
-	mov	r6, r0
-	mov	r4, r1
-	mov	r5, #0
-	mov	r7, #0
-	.endm
-#else
-	/*
-	 * Save boot arguments
-	 * entry r0, saved r4: pagestore
-	 * entry r1, saved r7: (ARMv7 standard bootarg #1)
-	 * entry r2, saved r6: device tree address, (ARMv7 standard bootarg #2)
-	 * entry lr, saved r5: non-secure entry address (ARMv7 bootarg #0)
-	 */
-	.macro bootargs_entry
-#if defined(CFG_NS_ENTRY_ADDR)
-	ldr	r5, =CFG_NS_ENTRY_ADDR
-#else
-	mov	r5, lr
-#endif
-#if defined(CFG_PAGEABLE_ADDR)
-	ldr	r4, =CFG_PAGEABLE_ADDR
-#else
-	mov	r4, r0
-#endif
-#if defined(CFG_DT_ADDR)
-	ldr	r6, =CFG_DT_ADDR
-#else
-	mov	r6, r2
-#endif
-	mov	r7, r1
-	.endm
-#endif
-
 	.macro maybe_init_spectre_workaround
 #if !defined(CFG_WITH_ARM_TRUSTED_FW) && \
     (defined(CFG_CORE_WORKAROUND_SPECTRE_BP) || \
@@ -239,8 +194,15 @@ END_FUNC reset_vect_table
 
 FUNC _start , :
 UNWIND(	.cantunwind)
-
-	bootargs_entry
+	/*
+	 * Temporary copy of boot argument registers, will be passed to
+	 * boot_save_args() further down.
+	 */
+	mov	r4, r0
+	mov	r5, r1
+	mov	r6, r2
+	mov	r7, r3
+	mov	r8, lr
 
 	/*
 	 * 32bit entry is expected to execute Supervisor mode,
@@ -365,7 +327,7 @@ DECLARE_KEEP_INIT _start
 LOCAL_FUNC reset_primary , : , .identity_map
 UNWIND(	.cantunwind)
 
-	/* preserve r4-r7: bootargs */
+	/* preserve r4-r8: bootargs */
 
 #ifdef CFG_WITH_PAGER
 	/*
@@ -390,8 +352,8 @@ UNWIND(	.cantunwind)
 	str	r0, cached_mem_end
 	ldr	r2, =__init_start
 copy_init:
-	ldmdb	r1!, {r3, r8-r12}
-	stmdb	r0!, {r3, r8-r12}
+	ldmdb	r1!, {r3, r9-r12}
+	stmdb	r0!, {r3, r9-r12}
 	cmp	r0, r2
 	bgt	copy_init
 #else
@@ -411,8 +373,8 @@ copy_init:
 	ldr	r2, =__end
 
 copy_init:
-	ldmdb	r1!, {r3, r8-r12}
-	stmdb	r0!, {r3, r8-r12}
+	ldmdb	r1!, {r3, r9-r12}
+	stmdb	r0!, {r3, r9-r12}
 	cmp	r0, r2
 	bgt	copy_init
 #endif
@@ -480,6 +442,16 @@ shadow_stack_access_ok:
 	/* Enable Console */
 	bl	console_init
 
+	mov	r0, r8
+	mov	r1, #0
+	push	{r0, r1}
+	mov	r0, r4
+	mov	r1, r5
+	mov	r2, r6
+	mov	r3, r7
+	bl	boot_save_args
+	add	sp, sp, #(2 * 4)
+
 #ifdef CFG_PL310
 	bl	pl310_base
 	bl	arm_cl2_config
@@ -500,7 +472,6 @@ shadow_stack_access_ok:
 #endif
 
 #ifdef CFG_CORE_ASLR
-	mov	r0, r6
 	bl	get_aslr_seed
 #else
 	mov	r0, #0
@@ -547,8 +518,6 @@ shadow_stack_access_ok:
 	bl	core_mmu_set_default_prtn_tbl
 #endif
 
-	mov	r0, r4		/* pageable part address */
-	mov	r1, r5		/* ns-entry address */
 	bl	boot_init_primary_early
 #ifndef CFG_NS_VIRTUALIZATION
 	mov	r9, sp
@@ -560,8 +529,6 @@ shadow_stack_access_ok:
 	mov	r0, #0
 	str	r0, [r8, #THREAD_CORE_LOCAL_FLAGS]
 #endif
-	mov	r0, r6		/* DT address */
-	mov	r1, #0		/* unused */
 	bl	boot_init_primary_late
 #ifndef CFG_NS_VIRTUALIZATION
 	mov	r0, #THREAD_CLF_TMP
@@ -633,10 +600,10 @@ shadow_stack_access_ok:
 	/* Pass the vector address returned from main_init */
 	sub	r1, r1, r0
 #else
-	/* realy standard bootarg #1 and #2 to non secure entry */
+	/* Relay standard bootarg #1 and #2 to non-secure entry */
 	mov	r4, #0
 	mov	r3, r6		/* std bootarg #2 for register R2 */
-	mov	r2, r7		/* std bootarg #1 for register R1 */
+	mov	r2, r5		/* std bootarg #1 for register R1 */
 	mov	r1, #0
 #endif /* CFG_WITH_ARM_TRUSTED_FW */
 
@@ -913,7 +880,7 @@ UNWIND(	.cantunwind)
 	bl	boot_core_hpen
 	ldm	r0, {r0, r6}
 #else
-	mov	r0, r5		/* ns-entry address */
+	mov	r0, r8		/* ns-entry address */
 	mov	r6, #0
 #endif
 	bl	boot_init_secondary
diff --git a/core/arch/arm/kernel/entry_a64.S b/core/arch/arm/kernel/entry_a64.S
index dd82e7106cb3e7a6a0b7cae74d452a21127f6a09..480ba7060046d7dc79dd3680a46605e8fce0e3b0 100644
--- a/core/arch/arm/kernel/entry_a64.S
+++ b/core/arch/arm/kernel/entry_a64.S
@@ -161,29 +161,13 @@
 
 FUNC _start , :
 	/*
-	 * Register use:
-	 * x0	- CFG_CORE_FFA=y && CFG_CORE_SEL2_SPMC=n:
-	 *	  if non-NULL holds the TOS FW config [1] address
-	 *	- CFG_CORE_FFA=y && CFG_CORE_SEL2_SPMC=y:
-	 *	  address of FF-A Boot Information Blob
-	 *	- CFG_CORE_FFA=n:
-	 *	  if non-NULL holds the pagable part address
-	 * x2	- CFG_CORE_SEL2_SPMC=n:
-	 *	  if non-NULL holds the system DTB address
-	 *
-	 * x19 - saved x0
-	 * x20 - saved x2
-	 *
-	 * [1] A TF-A concept: TOS_FW_CONFIG - Trusted OS Firmware
-	 * configuration file. Used by Trusted OS (BL32), that is, OP-TEE
-	 * here.
+	 * Temporary copy of boot argument registers, will be passed to
+	 * boot_save_args() further down.
 	 */
 	mov	x19, x0
-#if defined(CFG_DT_ADDR)
-	ldr     x20, =CFG_DT_ADDR
-#else
-	mov	x20, x2		/* Save DT address */
-#endif
+	mov	x20, x1
+	mov	x21, x2
+	mov	x22, x3
 
 	adr	x0, reset_vect_table
 	msr	vbar_el1, x0
@@ -312,10 +296,12 @@ clear_nex_bss:
 	/* Enable Console */
 	bl	console_init
 
-#if defined(CFG_CORE_SEL2_SPMC)
-	mov	x0, x19		/* boot info */
-	bl	boot_save_boot_info
-#endif
+	mov	x0, x19
+	mov	x1, x20
+	mov	x2, x21
+	mov	x3, x22
+	mov	x4, xzr
+	bl	boot_save_args
 
 #ifdef CFG_MEMTAG
 	/*
@@ -327,7 +313,6 @@ clear_nex_bss:
 #endif
 
 #ifdef CFG_CORE_ASLR
-	mov	x0, x20		/* DT address */
 	bl	get_aslr_seed
 #else
 	mov	x0, #0
@@ -376,12 +361,6 @@ clear_nex_bss:
 	bl	core_mmu_set_default_prtn_tbl
 #endif
 
-#ifdef CFG_CORE_SEL1_SPMC
-	mov	x0, xzr		/* pager not used */
-#else
-	mov	x0, x19		/* pagable part address */
-#endif
-	mov	x1, #-1
 	bl	boot_init_primary_early
 
 #ifdef CFG_MEMTAG
@@ -389,19 +368,13 @@ clear_nex_bss:
 #endif
 
 #ifndef CFG_NS_VIRTUALIZATION
-	mov	x21, sp
+	mov	x23, sp
 	adr_l	x0, threads
 	ldr	x0, [x0, #THREAD_CTX_STACK_VA_END]
 	mov	sp, x0
 	bl	thread_get_core_local
-	mov	x22, x0
-	str	wzr, [x22, #THREAD_CORE_LOCAL_FLAGS]
-#endif
-	mov	x0, x20		/* DT address also known as HW_CONFIG */
-#ifdef CFG_CORE_SEL1_SPMC
-	mov	x1, x19		/* TOS_FW_CONFIG DT address */
-#else
-	mov	x1, xzr		/* unused */
+	mov	x24, x0
+	str	wzr, [x24, #THREAD_CORE_LOCAL_FLAGS]
 #endif
 	bl	boot_init_primary_late
 #ifdef CFG_CORE_PAUTH
@@ -410,8 +383,8 @@ clear_nex_bss:
 
 #ifndef CFG_NS_VIRTUALIZATION
 	mov	x0, #THREAD_CLF_TMP
-	str     w0, [x22, #THREAD_CORE_LOCAL_FLAGS]
-	mov	sp, x21
+	str     w0, [x24, #THREAD_CORE_LOCAL_FLAGS]
+	mov	sp, x23
 #endif
 
 #ifdef _CFG_CORE_STACK_PROTECTOR
diff --git a/core/arch/arm/kernel/link_dummies_init.c b/core/arch/arm/kernel/link_dummies_init.c
index 5c90271f785d6aec828c1fdf666096810427fcc3..c3617b2a8086d0cbcf71e641984178806588bba9 100644
--- a/core/arch/arm/kernel/link_dummies_init.c
+++ b/core/arch/arm/kernel/link_dummies_init.c
@@ -7,12 +7,14 @@
 #include <mm/core_mmu.h>
 
 void __section(".text.dummy.boot_save_boot_info")
-boot_save_boot_info(void *boot_info __unused)
+boot_save_args(unsigned long a0 __unused, unsigned long a1 __unused,
+	       unsigned long a2 __unused, unsigned long a3 __unused,
+	       unsigned long a4 __unused)
 {
 }
 
 unsigned long __section(".text.dummy.get_aslr_seed")
-get_aslr_seed(void *fdt __unused)
+get_aslr_seed(void)
 {
 	return 0;
 }
@@ -24,7 +26,6 @@ core_init_mmu_map(unsigned long seed __unused,
 }
 
 void __section(".text.dummy.boot_init_primary_early")
-boot_init_primary_early(unsigned long pageable_part __unused,
-			unsigned long nsec_entry __unused)
+boot_init_primary_early(void)
 {
 }
diff --git a/core/arch/arm/kernel/link_dummies_paged.c b/core/arch/arm/kernel/link_dummies_paged.c
index d6d65c648fb52aebe77c1cca4c4d145e57c67969..4e9f090d019c16ba76f40a39ad7f9832a9ee23f2 100644
--- a/core/arch/arm/kernel/link_dummies_paged.c
+++ b/core/arch/arm/kernel/link_dummies_paged.c
@@ -29,7 +29,7 @@ void __section(".text.dummy.call_finalcalls") call_finalcalls(void)
 
 void __section(".text.dummy.boot_init_primary_late")
 boot_init_primary_late(unsigned long fdt __unused,
-		       unsigned long manifest_dt __unused)
+		       unsigned long manifest __unused)
 {
 }
 
diff --git a/core/arch/arm/kernel/spmc_sp_handler.c b/core/arch/arm/kernel/spmc_sp_handler.c
index 87f9772191465724594e1dae25f6ca7343f2116a..65e0a82cbd36354c130c446c6ed661dad93355fb 100644
--- a/core/arch/arm/kernel/spmc_sp_handler.c
+++ b/core/arch/arm/kernel/spmc_sp_handler.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright (c) 2021-2023, Arm Limited
+ * Copyright (c) 2021-2024, Arm Limited
  */
 #include <assert.h>
 #include <bench.h>
@@ -500,6 +500,8 @@ static void create_retrieve_response(uint32_t ffa_vers, void *dst_buffer,
 	if (ffa_vers <= FFA_VERSION_1_0) {
 		struct ffa_mem_transaction_1_0 *d_ds = dst_buffer;
 
+		memset(d_ds, 0, sizeof(*d_ds));
+
 		off = sizeof(*d_ds);
 		mem_acc = d_ds->mem_access_array;
 
@@ -512,6 +514,8 @@ static void create_retrieve_response(uint32_t ffa_vers, void *dst_buffer,
 	} else {
 		struct ffa_mem_transaction_1_1 *d_ds = dst_buffer;
 
+		memset(d_ds, 0, sizeof(*d_ds));
+
 		off = sizeof(*d_ds);
 		mem_acc = (void *)(d_ds + 1);
 
@@ -533,6 +537,7 @@ static void create_retrieve_response(uint32_t ffa_vers, void *dst_buffer,
 	       sizeof(struct ffa_mem_access_perm));
 
 	/* Copy the mem_region_descr */
+	memset(dst_region, 0, sizeof(*dst_region));
 	dst_region->address_range_count = 0;
 	dst_region->total_page_count = 0;
 
diff --git a/core/arch/arm/kernel/stmm_sp.c b/core/arch/arm/kernel/stmm_sp.c
index 691bae845839be73fec48dea0449faadad790a63..6d991a3068abafe299c79478c4e75b620af2af67 100644
--- a/core/arch/arm/kernel/stmm_sp.c
+++ b/core/arch/arm/kernel/stmm_sp.c
@@ -663,7 +663,7 @@ static TEE_Result sec_storage_obj_read(unsigned long storage_id, char *obj_id,
 	sess = ts_get_current_session();
 
 	res = tee_pobj_get(&sess->ctx->uuid, obj_id, obj_id_len, flags,
-			   false, fops, &po);
+			   TEE_POBJ_USAGE_OPEN, fops, &po);
 	if (res != TEE_SUCCESS)
 		return res;
 
@@ -714,7 +714,7 @@ static TEE_Result sec_storage_obj_write(unsigned long storage_id, char *obj_id,
 	sess = ts_get_current_session();
 
 	res = tee_pobj_get(&sess->ctx->uuid, obj_id, obj_id_len, flags,
-			   false, fops, &po);
+			   TEE_POBJ_USAGE_OPEN, fops, &po);
 	if (res != TEE_SUCCESS)
 		return res;
 
diff --git a/core/arch/arm/kernel/sub.mk b/core/arch/arm/kernel/sub.mk
index 49c5927c3d500910fc18981324836bf669d28a92..c95c0bda34ccfece19d9bc1dbf07dbc6b5743992 100644
--- a/core/arch/arm/kernel/sub.mk
+++ b/core/arch/arm/kernel/sub.mk
@@ -24,7 +24,6 @@ endif
 ifeq ($(CFG_CORE_FFA),y)
 srcs-y += thread_spmc.c
 cppflags-thread_spmc.c-y += -DTEE_IMPL_GIT_SHA1=$(TEE_IMPL_GIT_SHA1)
-srcs-$(CFG_ARM32_core) += thread_spmc_a32.S
 srcs-$(CFG_ARM64_core) += thread_spmc_a64.S
 else
 srcs-y += thread_optee_smc.c
diff --git a/core/arch/arm/kernel/thread.c b/core/arch/arm/kernel/thread.c
index 66833b3a08645f24e30d682d313a7c27b31b482d..0dd9007ba63864289750f62dd2315a630c62084b 100644
--- a/core/arch/arm/kernel/thread.c
+++ b/core/arch/arm/kernel/thread.c
@@ -14,6 +14,7 @@
 #include <keep.h>
 #include <kernel/asan.h>
 #include <kernel/boot.h>
+#include <kernel/interrupt.h>
 #include <kernel/linker.h>
 #include <kernel/lockdep.h>
 #include <kernel/misc.h>
diff --git a/core/arch/arm/kernel/thread_optee_smc.c b/core/arch/arm/kernel/thread_optee_smc.c
index bc69d8beac25f8ddd8b7804211232a4bdcf2d186..c1fcc23b36cdb7f5f41f84fd63dceab9ef8fe438 100644
--- a/core/arch/arm/kernel/thread_optee_smc.c
+++ b/core/arch/arm/kernel/thread_optee_smc.c
@@ -681,26 +681,21 @@ struct mobj *thread_rpc_alloc_payload(size_t size)
 
 struct mobj *thread_rpc_alloc_kernel_payload(size_t size)
 {
-	/*
-	 * Error out early since kernel private dynamic shared memory
-	 * allocations don't currently use the `OPTEE_MSG_ATTR_NONCONTIG` bit
-	 * and therefore cannot be larger than a page.
-	 */
-	if (IS_ENABLED(CFG_CORE_DYN_SHM) && size > SMALL_PAGE_SIZE)
-		return NULL;
-
 	return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_KERNEL);
 }
 
 void thread_rpc_free_kernel_payload(struct mobj *mobj)
 {
-	thread_rpc_free(OPTEE_RPC_SHM_TYPE_KERNEL, mobj_get_cookie(mobj), mobj);
+	if (mobj)
+		thread_rpc_free(OPTEE_RPC_SHM_TYPE_KERNEL,
+				mobj_get_cookie(mobj), mobj);
 }
 
 void thread_rpc_free_payload(struct mobj *mobj)
 {
-	thread_rpc_free(OPTEE_RPC_SHM_TYPE_APPL, mobj_get_cookie(mobj),
-			mobj);
+	if (mobj)
+		thread_rpc_free(OPTEE_RPC_SHM_TYPE_APPL, mobj_get_cookie(mobj),
+				mobj);
 }
 
 struct mobj *thread_rpc_alloc_global_payload(size_t size)
diff --git a/core/arch/arm/kernel/thread_spmc.c b/core/arch/arm/kernel/thread_spmc.c
index 59cdb51b14df27a5c1b5fc54c116e3e761190bcb..dd63f82575ff91131e3f86cd96c0361458c96dca 100644
--- a/core/arch/arm/kernel/thread_spmc.c
+++ b/core/arch/arm/kernel/thread_spmc.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright (c) 2020-2021, Linaro Limited.
+ * Copyright (c) 2020-2023, Linaro Limited.
  * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
  */
 
@@ -9,6 +9,7 @@
 #include <initcall.h>
 #include <io.h>
 #include <kernel/interrupt.h>
+#include <kernel/notif.h>
 #include <kernel/panic.h>
 #include <kernel/secure_partition.h>
 #include <kernel/spinlock.h>
@@ -46,6 +47,11 @@ struct mem_frag_state {
 };
 #endif
 
+static unsigned int spmc_notif_lock = SPINLOCK_UNLOCK;
+static int do_bottom_half_value = -1;
+static uint16_t notif_vm_id;
+static bool spmc_notif_is_ready;
+
 /* Initialized in spmc_init() below */
 static uint16_t my_endpoint_id __nex_bss;
 #ifdef CFG_CORE_SEL1_SPMC
@@ -96,6 +102,11 @@ static bool is_nw_buf(struct ffa_rxtx *rxtx)
 
 static SLIST_HEAD(mem_frag_state_head, mem_frag_state) frag_state_head =
 	SLIST_HEAD_INITIALIZER(&frag_state_head);
+
+static uint64_t notif_pending_bitmap;
+static uint64_t notif_bound_bitmap;
+static bool notif_vm_id_valid;
+static int notif_intid = -1;
 #else
 static uint8_t __rx_buf[SMALL_PAGE_SIZE] __aligned(SMALL_PAGE_SIZE);
 static uint8_t __tx_buf[SMALL_PAGE_SIZE] __aligned(SMALL_PAGE_SIZE);
@@ -146,10 +157,17 @@ uint32_t spmc_exchange_version(uint32_t vers, struct ffa_rxtx *rxtx)
 #if defined(CFG_CORE_SEL1_SPMC)
 static void handle_features(struct thread_smc_args *args)
 {
-	uint32_t ret_fid = 0;
-	uint32_t ret_w2 = FFA_PARAM_MBZ;
+	uint32_t ret_fid = FFA_ERROR;
+	uint32_t ret_w2 = FFA_NOT_SUPPORTED;
 
 	switch (args->a1) {
+	case FFA_FEATURE_SCHEDULE_RECV_INTR:
+		if (spmc_notif_is_ready) {
+			ret_fid = FFA_SUCCESS_32;
+			ret_w2 = notif_intid;
+		}
+		break;
+
 #ifdef ARM64
 	case FFA_RXTX_MAP_64:
 #endif
@@ -187,11 +205,20 @@ static void handle_features(struct thread_smc_args *args)
 	case FFA_RXTX_UNMAP:
 	case FFA_RX_RELEASE:
 	case FFA_FEATURE_MANAGED_EXIT_INTR:
+	case FFA_NOTIFICATION_BITMAP_CREATE:
+	case FFA_NOTIFICATION_BITMAP_DESTROY:
+	case FFA_NOTIFICATION_BIND:
+	case FFA_NOTIFICATION_UNBIND:
+	case FFA_NOTIFICATION_SET:
+	case FFA_NOTIFICATION_GET:
+	case FFA_NOTIFICATION_INFO_GET_32:
+#ifdef ARM64
+	case FFA_NOTIFICATION_INFO_GET_64:
+#endif
 		ret_fid = FFA_SUCCESS_32;
+		ret_w2 = FFA_PARAM_MBZ;
 		break;
 	default:
-		ret_fid = FFA_ERROR;
-		ret_w2 = FFA_NOT_SUPPORTED;
 		break;
 	}
 
@@ -474,6 +501,7 @@ void spmc_handle_partition_info_get(struct thread_smc_args *args,
 {
 	TEE_Result res = TEE_SUCCESS;
 	uint32_t ret_fid = FFA_ERROR;
+	uint32_t fpi_size = 0;
 	uint32_t rc = 0;
 	bool count_only = args->a5 & FFA_PARTITION_INFO_GET_COUNT_FLAG;
 
@@ -547,7 +575,11 @@ void spmc_handle_partition_info_get(struct thread_smc_args *args,
 	ret_fid = FFA_SUCCESS_32;
 
 out:
-	spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, rc, FFA_PARAM_MBZ,
+	if (ret_fid == FFA_SUCCESS_32 && !count_only &&
+	    rxtx->ffa_vers >= FFA_VERSION_1_1)
+		fpi_size = sizeof(struct ffa_partition_info_x) + FFA_UUID_SIZE;
+
+	spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, rc, fpi_size,
 		      FFA_PARAM_MBZ, FFA_PARAM_MBZ);
 	if (!count_only) {
 		rxtx->tx_is_mine = false;
@@ -582,6 +614,30 @@ out:
 }
 #endif /*CFG_CORE_SEL1_SPMC*/
 
+static uint32_t spmc_enable_async_notif(uint32_t bottom_half_value,
+					uint16_t vm_id)
+{
+	uint32_t old_itr_status = 0;
+
+	if (!spmc_notif_is_ready) {
+		/*
+		 * This should never happen, not if normal world respects the
+		 * exchanged capabilities.
+		 */
+		EMSG("Asynchronous notifications are not ready");
+		return TEE_ERROR_NOT_IMPLEMENTED;
+	}
+
+	old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock);
+	do_bottom_half_value = bottom_half_value;
+	if (!IS_ENABLED(CFG_CORE_SEL1_SPMC))
+		notif_vm_id = vm_id;
+	cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status);
+
+	notif_deliver_atomic_event(NOTIF_EVENT_STARTED);
+	return TEE_SUCCESS;
+}
+
 static void handle_yielding_call(struct thread_smc_args *args,
 				 uint32_t direct_resp_fid)
 {
@@ -630,6 +686,8 @@ static uint32_t handle_unregister_shm(uint32_t a4, uint32_t a5)
 static void handle_blocking_call(struct thread_smc_args *args,
 				 uint32_t direct_resp_fid)
 {
+	uint32_t sec_caps = 0;
+
 	switch (args->a3) {
 	case OPTEE_FFA_GET_API_VERSION:
 		spmc_set_args(args, direct_resp_fid, swap_src_dst(args->a1), 0,
@@ -642,14 +700,24 @@ static void handle_blocking_call(struct thread_smc_args *args,
 			      CFG_OPTEE_REVISION_MINOR, TEE_IMPL_GIT_SHA1);
 		break;
 	case OPTEE_FFA_EXCHANGE_CAPABILITIES:
-		spmc_set_args(args, direct_resp_fid, swap_src_dst(args->a1), 0,
-			      0, THREAD_RPC_MAX_NUM_PARAMS,
-			      OPTEE_FFA_SEC_CAP_ARG_OFFSET);
+		sec_caps = OPTEE_FFA_SEC_CAP_ARG_OFFSET;
+		if (spmc_notif_is_ready)
+			sec_caps |= OPTEE_FFA_SEC_CAP_ASYNC_NOTIF;
+		spmc_set_args(args, direct_resp_fid,
+			      swap_src_dst(args->a1), 0, 0,
+			      THREAD_RPC_MAX_NUM_PARAMS, sec_caps);
 		break;
 	case OPTEE_FFA_UNREGISTER_SHM:
 		spmc_set_args(args, direct_resp_fid, swap_src_dst(args->a1), 0,
 			      handle_unregister_shm(args->a4, args->a5), 0, 0);
 		break;
+	case OPTEE_FFA_ENABLE_ASYNC_NOTIF:
+		spmc_set_args(args, direct_resp_fid,
+			      swap_src_dst(args->a1), 0,
+			      spmc_enable_async_notif(args->a4,
+						      FFA_SRC(args->a1)),
+			      0, 0);
+		break;
 	default:
 		EMSG("Unhandled blocking service ID %#"PRIx32,
 		     (uint32_t)args->a3);
@@ -1302,7 +1370,223 @@ static void handle_mem_reclaim(struct thread_smc_args *args)
 	virt_unset_guest();
 
 out:
-	spmc_set_args(args, ret_fid, ret_val, 0, 0, 0, 0);
+	spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0);
+}
+
+static void handle_notification_bitmap_create(struct thread_smc_args *args)
+{
+	uint32_t ret_val = FFA_INVALID_PARAMETERS;
+	uint32_t ret_fid = FFA_ERROR;
+	uint32_t old_itr_status = 0;
+
+	if (!FFA_TARGET_INFO_GET_SP_ID(args->a1) && !args->a3 && !args->a4 &&
+	    !args->a5 && !args->a6 && !args->a7) {
+		uint16_t vm_id = args->a1;
+
+		old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock);
+
+		if (notif_vm_id_valid) {
+			if (vm_id == notif_vm_id)
+				ret_val = FFA_DENIED;
+			else
+				ret_val = FFA_NO_MEMORY;
+		} else {
+			notif_vm_id = vm_id;
+			notif_vm_id_valid = true;
+			ret_val = FFA_OK;
+			ret_fid = FFA_SUCCESS_32;
+		}
+
+		cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status);
+	}
+
+	spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0);
+}
+
+static void handle_notification_bitmap_destroy(struct thread_smc_args *args)
+{
+	uint32_t ret_val = FFA_INVALID_PARAMETERS;
+	uint32_t ret_fid = FFA_ERROR;
+	uint32_t old_itr_status = 0;
+
+	if (!FFA_TARGET_INFO_GET_SP_ID(args->a1) && !args->a3 && !args->a4 &&
+	    !args->a5 && !args->a6 && !args->a7) {
+		uint16_t vm_id = args->a1;
+
+		old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock);
+
+		if (notif_vm_id_valid && vm_id == notif_vm_id) {
+			if (notif_pending_bitmap || notif_bound_bitmap) {
+				ret_val = FFA_DENIED;
+			} else {
+				notif_vm_id_valid = false;
+				ret_val = FFA_OK;
+				ret_fid = FFA_SUCCESS_32;
+			}
+		}
+
+		cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status);
+	}
+
+	spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0);
+}
+
+static void handle_notification_bind(struct thread_smc_args *args)
+{
+	uint32_t ret_val = FFA_INVALID_PARAMETERS;
+	uint32_t ret_fid = FFA_ERROR;
+	uint32_t old_itr_status = 0;
+	uint64_t bitmap = 0;
+	uint16_t vm_id = 0;
+
+	if (args->a5 || args->a6 || args->a7)
+		goto out;
+	if (args->a2) {
+		/* We only deal with global notifications for now */
+		ret_val = FFA_NOT_SUPPORTED;
+		goto out;
+	}
+
+	/* The destination of the eventual notification */
+	vm_id = FFA_DST(args->a1);
+	bitmap = reg_pair_to_64(args->a4, args->a3);
+
+	old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock);
+
+	if (notif_vm_id_valid && vm_id == notif_vm_id) {
+		if (bitmap & notif_bound_bitmap) {
+			ret_val = FFA_DENIED;
+		} else {
+			notif_bound_bitmap |= bitmap;
+			ret_val = FFA_OK;
+			ret_fid = FFA_SUCCESS_32;
+		}
+	}
+
+	cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status);
+out:
+	spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0);
+}
+
+static void handle_notification_unbind(struct thread_smc_args *args)
+{
+	uint32_t ret_val = FFA_INVALID_PARAMETERS;
+	uint32_t ret_fid = FFA_ERROR;
+	uint32_t old_itr_status = 0;
+	uint64_t bitmap = 0;
+	uint16_t vm_id = 0;
+
+	if (args->a2 || args->a5 || args->a6 || args->a7)
+		goto out;
+
+	/* The destination of the eventual notification */
+	vm_id = FFA_DST(args->a1);
+	bitmap = reg_pair_to_64(args->a4, args->a3);
+
+	old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock);
+
+	if (notif_vm_id_valid && vm_id == notif_vm_id) {
+		/*
+		 * Spec says:
+		 * At least one notification is bound to another Sender or
+		 * is currently pending.
+		 *
+		 * Not sure what the intention is.
+		 */
+		if (bitmap & notif_pending_bitmap) {
+			ret_val = FFA_DENIED;
+		} else {
+			notif_bound_bitmap &= ~bitmap;
+			ret_val = FFA_OK;
+			ret_fid = FFA_SUCCESS_32;
+		}
+	}
+
+	cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status);
+out:
+	spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0);
+}
+
+static void handle_notification_get(struct thread_smc_args *args)
+{
+	uint32_t w2 = FFA_INVALID_PARAMETERS;
+	uint32_t ret_fid = FFA_ERROR;
+	uint32_t old_itr_status = 0;
+	uint16_t vm_id = 0;
+	uint32_t w3 = 0;
+
+	if (args->a5 || args->a6 || args->a7)
+		goto out;
+	if (!(args->a2 & 0x1)) {
+		ret_fid = FFA_SUCCESS_32;
+		w2 = 0;
+		goto out;
+	}
+	vm_id = FFA_DST(args->a1);
+
+	old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock);
+
+	if (notif_vm_id_valid && vm_id == notif_vm_id) {
+		reg_pair_from_64(notif_pending_bitmap, &w3, &w2);
+		notif_pending_bitmap = 0;
+		ret_fid = FFA_SUCCESS_32;
+	}
+
+	cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status);
+out:
+	spmc_set_args(args, ret_fid, 0, w2, w3, 0, 0);
+}
+
+static void handle_notification_info_get(struct thread_smc_args *args)
+{
+	uint32_t w2 = FFA_INVALID_PARAMETERS;
+	uint32_t ret_fid = FFA_ERROR;
+
+	if (args->a1 || args->a2 || args->a3 || args->a4 || args->a5 ||
+	    args->a6 || args->a7)
+		goto out;
+
+	if (OPTEE_SMC_IS_64(args->a0))
+		ret_fid = FFA_SUCCESS_64;
+	else
+		ret_fid = FFA_SUCCESS_32;
+
+	/*
+	 * Note, we're only supporting physical OS kernel in normal world
+	 * with Global Notifications.
+	 * So one list of ID list registers (BIT[11:7])
+	 * and one count of IDs (BIT[13:12] + 1)
+	 * and the VM is always 0.
+	 */
+	w2 = SHIFT_U32(1, 7);
+out:
+	spmc_set_args(args, ret_fid, 0, w2, 0, 0, 0);
+}
+
+void thread_spmc_set_async_notif_intid(int intid)
+{
+	assert(interrupt_can_raise_sgi(interrupt_get_main_chip()));
+	notif_intid = intid;
+	spmc_notif_is_ready = true;
+	DMSG("Asynchronous notifications are ready");
+}
+
+void notif_send_async(uint32_t value)
+{
+	uint32_t old_itr_status = 0;
+
+	old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock);
+	assert(value == NOTIF_VALUE_DO_BOTTOM_HALF && spmc_notif_is_ready &&
+	       do_bottom_half_value >= 0 && notif_intid >= 0);
+	notif_pending_bitmap |= BIT64(do_bottom_half_value);
+	interrupt_raise_sgi(interrupt_get_main_chip(), notif_intid,
+			    ITR_CPU_MASK_TO_THIS_CPU);
+	cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status);
+}
+#else
+void __noreturn notif_send_async(uint32_t value __unused)
+{
+	panic();
 }
 #endif
 
@@ -1367,7 +1651,40 @@ void thread_spmc_msg_recv(struct thread_smc_args *args)
 	case FFA_MEM_FRAG_TX:
 		handle_mem_frag_tx(args, &my_rxtx);
 		break;
+	case FFA_NOTIFICATION_BITMAP_CREATE:
+		handle_notification_bitmap_create(args);
+		break;
+	case FFA_NOTIFICATION_BITMAP_DESTROY:
+		handle_notification_bitmap_destroy(args);
+		break;
+	case FFA_NOTIFICATION_BIND:
+		handle_notification_bind(args);
+		break;
+	case FFA_NOTIFICATION_UNBIND:
+		handle_notification_unbind(args);
+		break;
+	case FFA_NOTIFICATION_GET:
+		handle_notification_get(args);
+		break;
+#ifdef ARM64
+	case FFA_NOTIFICATION_INFO_GET_64:
+#endif
+	case FFA_NOTIFICATION_INFO_GET_32:
+		handle_notification_info_get(args);
+		break;
 #endif /*CFG_CORE_SEL1_SPMC*/
+	case FFA_ERROR:
+		EMSG("Cannot handle FFA_ERROR(%d)", (int)args->a2);
+		if (!IS_ENABLED(CFG_CORE_SEL1_SPMC)) {
+			/*
+			 * The SPMC will return an FFA_ERROR back so better
+			 * panic() now than flooding the log.
+			 */
+			panic("FFA_ERROR from SPMC is fatal");
+		}
+		spmc_set_args(args, FFA_ERROR, FFA_PARAM_MBZ, FFA_NOT_SUPPORTED,
+			      FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ);
+		break;
 	default:
 		EMSG("Unhandled FFA function ID %#"PRIx32, (uint32_t)args->a0);
 		spmc_set_args(args, FFA_ERROR, FFA_PARAM_MBZ, FFA_NOT_SUPPORTED,
@@ -1654,13 +1971,16 @@ struct mobj *thread_rpc_alloc_kernel_payload(size_t size)
 
 void thread_rpc_free_kernel_payload(struct mobj *mobj)
 {
-	thread_rpc_free(OPTEE_RPC_SHM_TYPE_KERNEL, mobj_get_cookie(mobj), mobj);
+	if (mobj)
+		thread_rpc_free(OPTEE_RPC_SHM_TYPE_KERNEL,
+				mobj_get_cookie(mobj), mobj);
 }
 
 void thread_rpc_free_payload(struct mobj *mobj)
 {
-	thread_rpc_free(OPTEE_RPC_SHM_TYPE_APPL, mobj_get_cookie(mobj),
-			mobj);
+	if (mobj)
+		thread_rpc_free(OPTEE_RPC_SHM_TYPE_APPL, mobj_get_cookie(mobj),
+				mobj);
 }
 
 struct mobj *thread_rpc_alloc_global_payload(size_t size)
@@ -1670,8 +1990,9 @@ struct mobj *thread_rpc_alloc_global_payload(size_t size)
 
 void thread_rpc_free_global_payload(struct mobj *mobj)
 {
-	thread_rpc_free(OPTEE_RPC_SHM_TYPE_GLOBAL, mobj_get_cookie(mobj),
-			mobj);
+	if (mobj)
+		thread_rpc_free(OPTEE_RPC_SHM_TYPE_GLOBAL,
+				mobj_get_cookie(mobj), mobj);
 }
 
 void thread_spmc_register_secondary_ep(vaddr_t ep)
diff --git a/core/arch/arm/kernel/thread_spmc_a32.S b/core/arch/arm/kernel/thread_spmc_a32.S
deleted file mode 100644
index 7a8d9da988066f8122adbd54d12f4718303c0644..0000000000000000000000000000000000000000
--- a/core/arch/arm/kernel/thread_spmc_a32.S
+++ /dev/null
@@ -1,136 +0,0 @@
-/* SPDX-License-Identifier: BSD-2-Clause */
-/*
- * Copyright (c) 2020, Linaro Limited
- */
-
-#include <platform_config.h>
-
-#include <arm32_macros.S>
-#include <arm.h>
-#include <asm.S>
-#include <ffa.h>
-#include <generated/asm-defines.h>
-#include <kernel/thread.h>
-#include <optee_ffa.h>
-
-FUNC thread_ffa_msg_wait , :
-	mov_imm	r0, FFA_MSG_WAIT		/* FID */
-	mov	r1, #FFA_TARGET_INFO_MBZ	/* Target info MBZ */
-	mov	r2, #FFA_PARAM_MBZ		/* Param MBZ */
-	mov	r3, #FFA_PARAM_MBZ		/* Param MBZ */
-	mov	r4, #FFA_PARAM_MBZ		/* Param MBZ */
-	mov	r5, #FFA_PARAM_MBZ		/* Param MBZ */
-	mov	r6, #FFA_PARAM_MBZ		/* Param MBZ */
-	mov	r7, #FFA_PARAM_MBZ		/* Param MBZ */
-	b	.ffa_msg_loop
-END_FUNC thread_ffa_msg_wait
-
-	/* Caller provides r1, r3-r7 params */
-LOCAL_FUNC ffa_msg_send_direct_resp , :
-	ldr	r0, =FFA_MSG_SEND_DIRECT_RESP_32	/* FID */
-	mov	r2, #FFA_PARAM_MBZ			/* RES MBZ */
-
-.ffa_msg_loop:
-	/* Invoke SMC with caller provided parameters */
-	smc	#0
-
-	/* Store the parameters as struct thread_smc_args on stack */
-	push	{r0-r7}
-	mov	r0, sp
-
-	/* parse and handle message */
-	bl	thread_spmc_msg_recv
-
-	/* Load struct thread_smc_args into registers */
-	pop	{r0-r7}
-	b	.ffa_msg_loop
-END_FUNC ffa_msg_send_direct_resp
-
-FUNC thread_std_smc_entry , :
-UNWIND(	.cantunwind)
-
-	push	{r4, r5} /* Pass these following the arm32 calling convention */
-	ror	r4, r0, #16 /* Save target info with src and dst swapped */
-	bl	__thread_std_smc_entry
-	add	sp, sp, #8 /* There's nothing return, just restore the sp */
-	mov	r5, r0	/* Save return value */
-
-	/* Mask all maskable exceptions before switching to temporary stack */
-	cpsid	aif
-	bl	thread_get_tmp_sp
-	mov	sp, r0
-
-	bl	thread_state_free
-
-	mov	r1, r4				/* Target info */
-	mov	r3, r5				/* Return value */
-	mov	r4, #FFA_PARAM_MBZ		/* Unused parameter */
-	mov	r5, #FFA_PARAM_MBZ		/* Unused parameter */
-	mov	r6, #FFA_PARAM_MBZ		/* Unused parameter */
-	mov	r7, #FFA_PARAM_MBZ		/* Unused parameter */
-	b	ffa_msg_send_direct_resp
-END_FUNC thread_std_smc_entry
-
-/* void thread_rpc(struct thread_rpc_arg *rpc_arg) */
-FUNC thread_rpc , :
-	push	{r0, lr}
-UNWIND(	.save	{r0, lr})
-
-	bl	thread_save_state
-	mov	r4, r0			/* Save original CPSR */
-
-	/*
-	 * Switch to temporary stack and SVC mode. Save CPSR to resume into.
-	 */
-	bl	thread_get_tmp_sp
-	ldr	r8, [sp]		/* Get pointer to rv[] */
-	cps	#CPSR_MODE_SVC		/* Change to SVC mode */
-	mov	sp, r0			/* Switch to tmp stack */
-
-	mov	r0, #THREAD_FLAGS_COPY_ARGS_ON_RETURN
-	mov	r1, r4			/* CPSR to restore */
-	ldr	r2, =.thread_rpc_return
-	bl	thread_state_suspend
-	mov	r7, r0			/* Supply thread index */
-	ldr	r0, =FFA_MSG_SEND_DIRECT_RESP_32
-	mov	r2, #FFA_PARAM_MBZ
-	mov	r3, #0			/* Error code = 0 */
-	ldm	r8, {r1, r4-r6}		/* Load rv[] into r1,r4-r6 */
-	b	ffa_msg_send_direct_resp
-
-.thread_rpc_return:
-	/*
-	 * At this point has the stack pointer been restored to the value
-	 * it had when thread_save_state() was called above.
-	 *
-	 * Jumps here from thread_resume above when RPC has returned. The
-	 * IRQ and FIQ bits are restored to what they where when this
-	 * function was originally entered.
-	 */
-	pop	{r12, lr}		/* Get pointer to rv[] */
-	stm	r12, {r0-r3}		/* Store r0-r3 into rv[] */
-	bx	lr
-END_FUNC thread_rpc
-
-/*
- * void thread_foreign_intr_exit(uint32_t thread_index)
- *
- * This function is jumped to at the end of macro foreign_intr_handler().
- * The current thread as indicated by @thread_index has just been
- * suspended.  The job here is just to inform normal world the thread id to
- * resume when returning.
- */
-FUNC thread_foreign_intr_exit , :
-	/* load threads[r0].tsd.rpc_target_info into r1 */
-	mov	r1, #THREAD_CTX_SIZE
-	ldr	r2, =threads
-	mla	r1, r1, r0, r2
-	ldr	r1, [r1, #THREAD_CTX_TSD_RPC_TARGET_INFO]
-	mov	r2, #FFA_PARAM_MBZ
-	mov	r3, #FFA_PARAM_MBZ
-	mov	r4, #OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT
-	mov	r5, #FFA_PARAM_MBZ
-	mov	r6, #FFA_PARAM_MBZ
-	mov	r7, r0
-	b	ffa_msg_send_direct_resp
-END_FUNC thread_foreign_intr_exit
diff --git a/core/arch/arm/kernel/thread_spmc_a64.S b/core/arch/arm/kernel/thread_spmc_a64.S
index 8ea2bce5f520eea722f7cac12f97cb571d144476..46f241c9f0571e67474b6d58338aa20de94d7136 100644
--- a/core/arch/arm/kernel/thread_spmc_a64.S
+++ b/core/arch/arm/kernel/thread_spmc_a64.S
@@ -14,7 +14,7 @@
 #include <kernel/thread.h>
 #include <optee_ffa.h>
 
-#if CFG_SECURE_PARTITION
+#ifdef CFG_SECURE_PARTITION
 LOCAL_FUNC thread_ffa_interrupt , :
 	mov_imm	x0, FFA_INTERRUPT		/* FID */
 	/* X1: Endpoint/vCPU IDs is set by caller */
@@ -197,7 +197,7 @@ FUNC thread_foreign_intr_exit , :
 	adr_l	x2, threads
 	madd	x2, x1, x0, x2
 	ldr	w1, [x2, #THREAD_CTX_TSD_RPC_TARGET_INFO]
-#if CFG_SECURE_PARTITION
+#ifdef CFG_SECURE_PARTITION
 	/* load threads[w0].flags into w2 */
 	ldr	w2, [x2, #THREAD_CTX_FLAGS]
 	and     w2, w2, #THREAD_FLAGS_FFA_ONLY
diff --git a/core/arch/arm/kernel/tz_ssvce_pl310_a32.S b/core/arch/arm/kernel/tz_ssvce_pl310_a32.S
index b3f85cc168c0a6e814c39e84f01438f53b8bdb3a..c5c94e7817d7eeda026055364479756eaed4d055 100644
--- a/core/arch/arm/kernel/tz_ssvce_pl310_a32.S
+++ b/core/arch/arm/kernel/tz_ssvce_pl310_a32.S
@@ -222,3 +222,14 @@ FUNC arm_cl2_cleaninvbypa , :
 	b	_arm_cl2_xxxbypa
 END_FUNC arm_cl2_cleaninvbypa
 
+/*
+ * __weak vaddr_t pl310_nsbase(void);
+ * return the non-secure PL310 base address
+ *
+ * Weak implementation to preserve the previous behavior where only the
+ * secure PL310 base address was returned. Up to the platform to map
+ * and return non-secure PL310 base address.
+ */
+WEAK_FUNC pl310_nsbase , :
+	b	pl310_base
+END_FUNC pl310_nsbase
diff --git a/core/arch/arm/mm/core_mmu.c b/core/arch/arm/mm/core_mmu.c
index e25f5cc510eeedd7976d80fba3ff85cc89830745..0b6af6ad06388ed12da7ec4a25754e6aceb8777a 100644
--- a/core/arch/arm/mm/core_mmu.c
+++ b/core/arch/arm/mm/core_mmu.c
@@ -14,6 +14,7 @@
 #include <kernel/tee_misc.h>
 #include <kernel/tlb_helpers.h>
 #include <kernel/tz_ssvce_pl310.h>
+#include <mm/core_memprot.h>
 #include <mm/core_mmu.h>
 #include <platform_config.h>
 #include <trace.h>
@@ -99,6 +100,26 @@ TEE_Result cache_op_outer(enum cache_op op, paddr_t pa, size_t len)
 {
 	TEE_Result ret = TEE_SUCCESS;
 	uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR);
+	vaddr_t pl310_base_pa_op = 0;
+
+	/*
+	 * According the ARM PL310 documentation, if the operation is specific
+	 * to the PA, the behavior is presented in the following manner:
+	 * - Secure access: The data in the cache is only affected by the
+	 * operation if it is secure.
+	 * - Non-secure access: The data in the cache is only affected by the
+	 * operation if it is non-secure.
+	 *
+	 * https://developer.arm.com/documentation/ddi0246/a/programmer-s-model/register-descriptions/register-7--cache-maintenance-operations
+	 *
+	 * Depending on the buffer location, use the secure or non-secure PL310
+	 * base address to do physical address based cache operation on the
+	 * buffer.
+	 */
+	if (tee_pbuf_is_sec(pa, len))
+		pl310_base_pa_op = pl310_base();
+	else
+		pl310_base_pa_op = pl310_nsbase();
 
 	tee_l2cc_mutex_lock();
 	switch (op) {
@@ -107,21 +128,22 @@ TEE_Result cache_op_outer(enum cache_op op, paddr_t pa, size_t len)
 		break;
 	case DCACHE_AREA_INVALIDATE:
 		if (len)
-			arm_cl2_invbypa(pl310_base(), pa, pa + len - 1);
+			arm_cl2_invbypa(pl310_base_pa_op, pa, pa + len - 1);
 		break;
 	case DCACHE_CLEAN:
 		arm_cl2_cleanbyway(pl310_base());
 		break;
 	case DCACHE_AREA_CLEAN:
 		if (len)
-			arm_cl2_cleanbypa(pl310_base(), pa, pa + len - 1);
+			arm_cl2_cleanbypa(pl310_base_pa_op, pa, pa + len - 1);
 		break;
 	case DCACHE_CLEAN_INV:
 		arm_cl2_cleaninvbyway(pl310_base());
 		break;
 	case DCACHE_AREA_CLEAN_INV:
 		if (len)
-			arm_cl2_cleaninvbypa(pl310_base(), pa, pa + len - 1);
+			arm_cl2_cleaninvbypa(pl310_base_pa_op, pa,
+					     pa + len - 1);
 		break;
 	default:
 		ret = TEE_ERROR_NOT_IMPLEMENTED;
diff --git a/core/arch/arm/mm/core_mmu_lpae.c b/core/arch/arm/mm/core_mmu_lpae.c
index 7e79f780ad28984a6ec1f46e44457367fb5c72b3..dffbda8d094f615d27882ee306468d8cf174b647 100644
--- a/core/arch/arm/mm/core_mmu_lpae.c
+++ b/core/arch/arm/mm/core_mmu_lpae.c
@@ -141,6 +141,7 @@
 #define TCR_PS_BITS_4TB		(0x3)
 #define TCR_PS_BITS_16TB	(0x4)
 #define TCR_PS_BITS_256TB	(0x5)
+#define TCR_PS_BITS_4PB		(0x6)
 
 #define UNSET_DESC		((uint64_t)-1)
 
@@ -866,7 +867,7 @@ void core_init_mmu_regs(struct core_mmu_config *cfg)
 #endif /*ARM32*/
 
 #ifdef ARM64
-static unsigned int get_physical_addr_size_bits(void)
+static unsigned int get_hard_coded_pa_size_bits(void)
 {
 	/*
 	 * Intermediate Physical Address Size.
@@ -876,10 +877,10 @@ static unsigned int get_physical_addr_size_bits(void)
 	 * 0b011      42 bits, 4TB.
 	 * 0b100      44 bits, 16TB.
 	 * 0b101      48 bits, 256TB.
-	 * 0b110      52 bits, 4PB (not supported)
+	 * 0b110      52 bits, 4PB
 	 */
-
-	COMPILE_TIME_ASSERT(CFG_CORE_ARM64_PA_BITS >= 32);
+	static_assert(CFG_CORE_ARM64_PA_BITS >= 32);
+	static_assert(CFG_CORE_ARM64_PA_BITS <= 52);
 
 	if (CFG_CORE_ARM64_PA_BITS <= 32)
 		return TCR_PS_BITS_4GB;
@@ -896,10 +897,34 @@ static unsigned int get_physical_addr_size_bits(void)
 	if (CFG_CORE_ARM64_PA_BITS <= 44)
 		return TCR_PS_BITS_16TB;
 
-	/* Physical address can't exceed 48 bits */
-	COMPILE_TIME_ASSERT(CFG_CORE_ARM64_PA_BITS <= 48);
+	if (CFG_CORE_ARM64_PA_BITS <= 48)
+		return TCR_PS_BITS_256TB;
+
 	/* CFG_CORE_ARM64_PA_BITS <= 48 */
-	return TCR_PS_BITS_256TB;
+	return TCR_PS_BITS_4PB;
+}
+
+static unsigned int get_physical_addr_size_bits(void)
+{
+	const unsigned int size_bits = read_id_aa64mmfr0_el1() &
+				       ID_AA64MMFR0_EL1_PARANGE_MASK;
+	unsigned int b = 0;
+
+	if (IS_ENABLED(CFG_AUTO_MAX_PA_BITS))
+		return size_bits;
+
+	b = get_hard_coded_pa_size_bits();
+	assert(b <= size_bits);
+	return b;
+}
+
+unsigned int core_mmu_arm64_get_pa_width(void)
+{
+	const uint8_t map[] = { 32, 36, 40, 42, 44, 48, 52, };
+	unsigned int size_bits = get_physical_addr_size_bits();
+
+	size_bits = MIN(size_bits, ARRAY_SIZE(map) - 1);
+	return map[size_bits];
 }
 
 void core_init_mmu_regs(struct core_mmu_config *cfg)
diff --git a/core/arch/arm/mm/mobj_ffa.c b/core/arch/arm/mm/mobj_ffa.c
index e57c95ac83cd718168f0ba2efeb7e49cb43e6bc5..8d3d71447fe2399176e09551fa7718920e26a7d2 100644
--- a/core/arch/arm/mm/mobj_ffa.c
+++ b/core/arch/arm/mm/mobj_ffa.c
@@ -423,7 +423,17 @@ TEE_Result mobj_ffa_unregister_by_cookie(uint64_t cookie)
 	}
 #if defined(CFG_CORE_SEL1_SPMC)
 	if (!mf->registered_by_cookie) {
-		EMSG("cookie %#"PRIx64" not registered", cookie);
+		/*
+		 * This is expected behaviour if the normal world has
+		 * registered the memory but OP-TEE has not yet used the
+		 * corresponding cookie with mobj_ffa_get_by_cookie(). It
+		 * can be non-trivial for the normal world to predict if
+		 * the cookie really has been used or not. So even if we
+		 * return it as an error it will be ignored by
+		 * handle_unregister_shm().
+		 */
+		EMSG("cookie %#"PRIx64" not registered refs %u:%u",
+		     cookie, refcount_val(&mf->mobj.refc), mf->inactive_refs);
 		res = TEE_ERROR_ITEM_NOT_FOUND;
 		goto out;
 	}
diff --git a/core/arch/arm/plat-aspeed/conf.mk b/core/arch/arm/plat-aspeed/conf.mk
index a45ccca95ac6bf970b4ce9207f9a0e8ea9c4a4fc..d3249e2e3200e5c07213a9882b29304a33ade0a8 100644
--- a/core/arch/arm/plat-aspeed/conf.mk
+++ b/core/arch/arm/plat-aspeed/conf.mk
@@ -18,6 +18,8 @@ CFG_TZDRAM_START ?= 0xb0000000
 CFG_TZDRAM_SIZE ?= 0x1000000
 
 CFG_CORE_RESERVED_SHM ?= n
+
+arm32-platform-cflags += -mfpu=vfpv3-d16
 else ifeq ($(PLATFORM_FLAVOR),ast2700)
 include core/arch/arm/cpu/cortex-armv8-0.mk
 
diff --git a/core/arch/arm/plat-aspeed/platform_ast2600.c b/core/arch/arm/plat-aspeed/platform_ast2600.c
index f8b359c8060df2c352f201dd65ed2fda72e34255..b6132c0229b3ef28ed12e7377fe04fe0ec95cdf6 100644
--- a/core/arch/arm/plat-aspeed/platform_ast2600.c
+++ b/core/arch/arm/plat-aspeed/platform_ast2600.c
@@ -67,7 +67,7 @@ void boot_primary_init_intc(void)
 
 void boot_secondary_init_intc(void)
 {
-	gic_cpu_init();
+	gic_init_per_cpu();
 }
 
 void console_init(void)
diff --git a/core/arch/arm/plat-aspeed/platform_ast2700.c b/core/arch/arm/plat-aspeed/platform_ast2700.c
index a1b3ac42c0e859c320048a7e5eb533e7bef6fe36..106c88df173c4bd7fdc582a34df2b26ae7cbcb73 100644
--- a/core/arch/arm/plat-aspeed/platform_ast2700.c
+++ b/core/arch/arm/plat-aspeed/platform_ast2700.c
@@ -13,6 +13,7 @@
 
 register_phys_mem(MEM_AREA_IO_SEC, UART_BASE, SMALL_PAGE_SIZE);
 register_phys_mem(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE);
+register_phys_mem(MEM_AREA_IO_SEC, GICR_BASE, GICR_SIZE);
 
 register_ddr(CFG_DRAM_BASE, CFG_DRAM_SIZE);
 
@@ -20,12 +21,12 @@ static struct serial8250_uart_data console_data;
 
 void boot_primary_init_intc(void)
 {
-	gic_init(0, GICD_BASE);
+	gic_init_v3(0, GICD_BASE, GICR_BASE);
 }
 
 void boot_secondary_init_intc(void)
 {
-	gic_cpu_init();
+	gic_init_per_cpu();
 }
 
 void console_init(void)
diff --git a/core/arch/arm/plat-aspeed/platform_config.h b/core/arch/arm/plat-aspeed/platform_config.h
index 69f26793db29ba925a4631345b5cb5bcdc392492..c6b322fac16bfb46e6a6e5c53f6a4e1f96d6df81 100644
--- a/core/arch/arm/plat-aspeed/platform_config.h
+++ b/core/arch/arm/plat-aspeed/platform_config.h
@@ -26,6 +26,7 @@
 #elif defined(PLATFORM_FLAVOR_ast2700)
 #define GICD_BASE		0x12200000
 #define GICR_BASE		0x12280000
+#define GICR_SIZE		0x100000
 
 #define UART_BASE		0x14c33000
 #define UART12_BASE		(UART_BASE + 0xb00)
diff --git a/core/arch/arm/plat-corstone1000/main.c b/core/arch/arm/plat-corstone1000/main.c
index 846b60116a850d3eee9990c2dab2210b4e743e91..b3861c4c88f7049cb537ace23446251a64c9832d 100644
--- a/core/arch/arm/plat-corstone1000/main.c
+++ b/core/arch/arm/plat-corstone1000/main.c
@@ -28,7 +28,7 @@ void boot_primary_init_intc(void)
 
 void boot_secondary_init_intc(void)
 {
-	gic_cpu_init();
+	gic_init_per_cpu();
 }
 
 void console_init(void)
diff --git a/core/arch/arm/plat-d06/conf.mk b/core/arch/arm/plat-d06/conf.mk
index 98a8fa01bbe74e04598901cb86fc3eefb8242d1c..7c250a7c30465687c271a5881f752fcc720e7530 100644
--- a/core/arch/arm/plat-d06/conf.mk
+++ b/core/arch/arm/plat-d06/conf.mk
@@ -5,9 +5,10 @@ CFG_NUM_THREADS ?= 96
 CFG_CRYPTO_WITH_CE ?= y
 
 CFG_WITH_PAGER ?= n
-CFG_WITH_SOFTWARE_PRNG ?= y
+CFG_WITH_SOFTWARE_PRNG ?= n
 CFG_WITH_STATS ?= y
 CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= y
+CFG_HISILICON_CRYPTO_DRIVER ?= y
 
 $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y)
 $(call force,CFG_WITH_ARM_TRUSTED_FW,y)
@@ -26,3 +27,4 @@ CFG_TZDRAM_START ?=    0x20C0000000
 CFG_TZDRAM_SIZE ?=     0x32000000
 CFG_SHMEM_START ?=     0x50000000
 CFG_SHMEM_SIZE ?=      0x04000000
+
diff --git a/core/arch/arm/plat-d06/platform_config.h b/core/arch/arm/plat-d06/platform_config.h
index 81979bdc478cae37c772a61b0bff2341ff8a38b3..3ca0a0f49543239e98b9ca1d0b5761c6b7870a78 100644
--- a/core/arch/arm/plat-d06/platform_config.h
+++ b/core/arch/arm/plat-d06/platform_config.h
@@ -17,4 +17,8 @@
 #define CONSOLE_BAUDRATE	115200
 #define CONSOLE_UART_CLK_IN_HZ	200
 
+/* HISI_TRNG */
+#define HISI_TRNG_BASE		0x2010C0000
+#define HISI_TRNG_SIZE		0x100
+
 #endif /* PLATFORM_CONFIG_H */
diff --git a/core/arch/arm/plat-hikey/main.c b/core/arch/arm/plat-hikey/main.c
index 9e0543a7ceb37c4098f0b9b487f535a0ea2d12d8..239072db5bc86c8c4593a3de3e6b2050994b729d 100644
--- a/core/arch/arm/plat-hikey/main.c
+++ b/core/arch/arm/plat-hikey/main.c
@@ -60,14 +60,14 @@ void spi_init(void)
 	vaddr_t pmx1_base = core_mmu_get_va(PMX1_BASE, MEM_AREA_IO_NSEC,
 					    PMX1_REG_SIZE);
 
-	DMSG("take SPI0 out of reset\n");
+	DMSG("take SPI0 out of reset");
 	shifted_val = PERI_RST3_SSP;
 	/*
 	 * no need to read PERI_SC_PERIPH_RSTDIS3 first
 	 * as all the bits are processed and cleared after writing
 	 */
 	io_write32(peri_base + PERI_SC_PERIPH_RSTDIS3, shifted_val);
-	DMSG("PERI_SC_PERIPH_RSTDIS3: 0x%x\n",
+	DMSG("PERI_SC_PERIPH_RSTDIS3: 0x%x",
 		io_read32(peri_base + PERI_SC_PERIPH_RSTDIS3));
 
 	/*
@@ -77,19 +77,19 @@ void spi_init(void)
 	do {
 		read_val = io_read32(peri_base + PERI_SC_PERIPH_RSTSTAT3);
 	} while (read_val & shifted_val);
-	DMSG("PERI_SC_PERIPH_RSTSTAT3: 0x%x\n", read_val);
+	DMSG("PERI_SC_PERIPH_RSTSTAT3: 0x%x", read_val);
 
-	DMSG("enable SPI clock\n");
+	DMSG("enable SPI clock");
 	/*
 	 * no need to read PERI_SC_PERIPH_CLKEN3 first
 	 * as all the bits are processed and cleared after writing
 	 */
 	shifted_val = PERI_CLK3_SSP;
 	io_write32(peri_base + PERI_SC_PERIPH_CLKEN3, shifted_val);
-	DMSG("PERI_SC_PERIPH_CLKEN3: 0x%x\n",
+	DMSG("PERI_SC_PERIPH_CLKEN3: 0x%x",
 		io_read32(peri_base + PERI_SC_PERIPH_CLKEN3));
 
-	DMSG("PERI_SC_PERIPH_CLKSTAT3: 0x%x\n",
+	DMSG("PERI_SC_PERIPH_CLKSTAT3: 0x%x",
 		io_read32(peri_base + PERI_SC_PERIPH_CLKSTAT3));
 
 	/*
@@ -101,13 +101,13 @@ void spi_init(void)
 	 * transfer.
 	 * ref: http://infocenter.arm.com/help/topic/com.arm.doc.ddi0194h/CJACFAFG.html
 	 */
-	DMSG("configure gpio6 pins 0-3 as SPI\n");
+	DMSG("configure gpio6 pins 0-3 as SPI");
 	io_write32(pmx0_base + PMX0_IOMG104, PINMUX_SPI);
 	io_write32(pmx0_base + PMX0_IOMG105, PINMUX_SPI);
 	io_write32(pmx0_base + PMX0_IOMG106, PINMUX_SPI);
 	io_write32(pmx0_base + PMX0_IOMG107, PINMUX_SPI);
 
-	DMSG("configure gpio6 pins 0-3 as nopull\n");
+	DMSG("configure gpio6 pins 0-3 as nopull");
 	io_write32(pmx1_base + PMX1_IOCG104, PINCFG_NOPULL);
 	io_write32(pmx1_base + PMX1_IOCG105, PINCFG_NOPULL);
 	io_write32(pmx1_base + PMX1_IOCG106, PINCFG_NOPULL);
@@ -124,7 +124,7 @@ static TEE_Result peripherals_init(void)
 	vaddr_t pmussi_base = core_mmu_get_va(PMUSSI_BASE, MEM_AREA_IO_NSEC,
 					      PMUSSI_REG_SIZE);
 
-	DMSG("enable LD021_1V8 source (pin 35) on LS connector\n");
+	DMSG("enable LD021_1V8 source (pin 35) on LS connector");
 	/*
 	 * Mezzanine cards usually use this to source level shifters for
 	 * UART, GPIO, SPI, I2C, etc so if not enabled, connected
diff --git a/core/arch/arm/plat-hikey/spi_test.c b/core/arch/arm/plat-hikey/spi_test.c
index ea7ec25875ab9c2b439546b31b647819d29febc7..5b43da64b679b0be33a2b1e7e6d4f0dd2d5d9132 100644
--- a/core/arch/arm/plat-hikey/spi_test.c
+++ b/core/arch/arm/plat-hikey/spi_test.c
@@ -80,7 +80,7 @@ static void spi_test_with_manual_cs_control(void)
 	DMSG("Set CS callback");
 	pd.cs_control = PL022_CS_CTRL_MANUAL;
 
-	DMSG("spi_base: 0x%" PRIxVA "\n", spi_base);
+	DMSG("spi_base: 0x%" PRIxVA, spi_base);
 	DMSG("Configure SPI");
 	pd.base = spi_base;
 	pd.clk_hz = SPI_CLK_HZ;
@@ -170,7 +170,7 @@ static void spi_test_with_registered_cs_cb(void)
 	pd.cs_data.cs_cb = spi_cs_callback;
 	pd.cs_control = PL022_CS_CTRL_CB;
 
-	DMSG("spi_base: 0x%" PRIxVA "\n", spi_base);
+	DMSG("spi_base: 0x%" PRIxVA, spi_base);
 	DMSG("Configure SPI");
 	pd.base = spi_base;
 	pd.clk_hz = SPI_CLK_HZ;
@@ -215,7 +215,7 @@ static void spi_test_with_builtin_cs_control(void)
 
 	spi_set_cs_mux(PINMUX_GPIO);
 
-	DMSG("gpio6_base: 0x%" PRIxVA "\n", gpio6_base);
+	DMSG("gpio6_base: 0x%" PRIxVA, gpio6_base);
 	DMSG("Configure GPIO");
 	pl061_init(&pd061);
 	pl061_register(gpio6_base, 6);
@@ -226,7 +226,7 @@ static void spi_test_with_builtin_cs_control(void)
 	pd022.cs_data.gpio_data.pin_num = GPIO6_2;
 	pd022.cs_control = PL022_CS_CTRL_AUTO_GPIO;
 
-	DMSG("spi_base: 0x%" PRIxVA "\n", spi_base);
+	DMSG("spi_base: 0x%" PRIxVA, spi_base);
 	DMSG("Configure SPI");
 	pd022.base = spi_base;
 	pd022.clk_hz = SPI_CLK_HZ;
diff --git a/core/arch/arm/plat-imx/conf.mk b/core/arch/arm/plat-imx/conf.mk
index 4e85e52cc8911b2eb628ed769f520cfe8be38f96..85bbfe5032a95f8aae2020921a97d2944ca58b27 100644
--- a/core/arch/arm/plat-imx/conf.mk
+++ b/core/arch/arm/plat-imx/conf.mk
@@ -78,6 +78,7 @@ mx8qm-flavorlist = \
 
 mx8qx-flavorlist = \
 	mx8qxpmek \
+	mx8dxmek \
 
 mx8dxl-flavorlist = \
 	mx8dxlevk \
@@ -216,7 +217,7 @@ CFG_TEE_CORE_NB_CORE ?= 2
 $(call force,CFG_NXP_SNVS,n)
 $(call force,CFG_IMX_OCOTP,n)
 CFG_IMX_MU ?= y
-CFG_IMX_ELE ?= y
+CFG_IMX_ELE ?= n
 else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx93-flavorlist)))
 $(call force,CFG_MX93,y)
 $(call force,CFG_ARM64_core,y)
@@ -229,7 +230,7 @@ $(call force,CFG_TZC380,n)
 $(call force,CFG_CRYPTO_DRIVER,n)
 $(call force,CFG_NXP_CAAM,n)
 CFG_IMX_MU ?= y
-CFG_IMX_ELE ?= y
+CFG_IMX_ELE ?= n
 else
 $(error Unsupported PLATFORM_FLAVOR "$(PLATFORM_FLAVOR)")
 endif
@@ -398,6 +399,12 @@ CFG_NSEC_DDR_1_SIZE  ?= 0x380000000UL
 CFG_CORE_ARM64_PA_BITS ?= 40
 endif
 
+ifneq (,$(filter $(PLATFORM_FLAVOR),mx8dxmek))
+CFG_DDR_SIZE ?= 0x40000000
+CFG_UART_BASE ?= UART0_BASE
+$(call force,CFG_MX8DX,y)
+endif
+
 ifneq (,$(filter $(PLATFORM_FLAVOR),mx8dxlevk))
 CFG_DDR_SIZE ?= 0x40000000
 CFG_UART_BASE ?= UART0_BASE
diff --git a/core/arch/arm/plat-imx/imx_pl310.c b/core/arch/arm/plat-imx/imx_pl310.c
index 202d64b3ec274623130f2469e5c71991f5e4c489..ddf355e4c9bde09e8899504c72e684cc19946569 100644
--- a/core/arch/arm/plat-imx/imx_pl310.c
+++ b/core/arch/arm/plat-imx/imx_pl310.c
@@ -23,6 +23,7 @@
 #define PL310_PREFETCH_DOUBLE_LINEFILL		BIT(30)
 
 register_phys_mem_pgdir(MEM_AREA_IO_SEC, PL310_BASE, CORE_MMU_PGDIR_SIZE);
+register_phys_mem_pgdir(MEM_AREA_IO_NSEC, PL310_BASE, CORE_MMU_PGDIR_SIZE);
 
 void arm_cl2_config(vaddr_t pl310_base)
 {
@@ -83,6 +84,11 @@ vaddr_t pl310_base(void)
 	return core_mmu_get_va(PL310_BASE, MEM_AREA_IO_SEC, 1);
 }
 
+vaddr_t pl310_nsbase(void)
+{
+	return core_mmu_get_va(PL310_BASE, MEM_AREA_IO_NSEC, 1);
+}
+
 #ifdef CFG_PL310_SIP_PROTOCOL
 uint32_t pl310_enable(void)
 {
diff --git a/core/arch/arm/plat-imx/main.c b/core/arch/arm/plat-imx/main.c
index 1a7087dd67711cc35e42dd12de4dbecc8cff5136..9ae1c7ce53181f7f2e0ed2ebecba079f95b04ea4 100644
--- a/core/arch/arm/plat-imx/main.c
+++ b/core/arch/arm/plat-imx/main.c
@@ -117,6 +117,6 @@ void boot_primary_init_intc(void)
 #if CFG_TEE_CORE_NB_CORE > 1
 void boot_secondary_init_intc(void)
 {
-	gic_cpu_init();
+	gic_init_per_cpu();
 }
 #endif
diff --git a/core/arch/arm/plat-k3/drivers/sa2ul_rng.c b/core/arch/arm/plat-k3/drivers/sa2ul_rng.c
index 1684bff501a272fb36fc0d429ca4e9fea753ba1a..bbbaeacdf519dd8a477979a41d37bc3e60e28ffc 100644
--- a/core/arch/arm/plat-k3/drivers/sa2ul_rng.c
+++ b/core/arch/arm/plat-k3/drivers/sa2ul_rng.c
@@ -61,12 +61,38 @@
 
 register_phys_mem_pgdir(MEM_AREA_IO_SEC, RNG_BASE, RNG_REG_SIZE);
 
-static unsigned int rng_lock = SPINLOCK_UNLOCK;
+static struct mutex fifo_lock = MUTEX_INITIALIZER;
 static vaddr_t rng;
 
+static bool sa2ul_rng_is_enabled(void)
+{
+	return io_read32(rng + RNG_CONTROL) & ENABLE_TRNG;
+}
+
+static void sa2ul_rng_init_seq(void)
+{
+	uint32_t val = 0;
+
+	/* Ensure initial latency */
+	val |= RNG_CONFIG_MIN_REFIL_CYCLES << RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT;
+	val |= RNG_CONFIG_MAX_REFIL_CYCLES << RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT;
+	io_write32(rng + RNG_CONFIG, val);
+
+	/* Configure the desired FROs */
+	io_write32(rng + RNG_FRODETUNE, 0x0);
+
+	/* Enable all FROs */
+	io_write32(rng + RNG_FROENABLE, 0xffffff);
+
+	io_write32(rng + RNG_CONTROL, ENABLE_TRNG);
+}
+
 static void sa2ul_rng_read128(uint32_t *word0, uint32_t *word1,
 			      uint32_t *word2, uint32_t *word3)
 {
+	if (!sa2ul_rng_is_enabled())
+		sa2ul_rng_init_seq();
+
 	/* Is the result ready (available)? */
 	while (!(io_read32(rng + RNG_STATUS) & RNG_READY)) {
 		/* Is the shutdown threshold reached? */
@@ -107,7 +133,7 @@ TEE_Result hw_get_random_bytes(void *buf, size_t len)
 	size_t buffer_pos = 0;
 
 	while (buffer_pos < len) {
-		uint32_t exceptions = cpu_spin_lock_xsave(&rng_lock);
+		mutex_lock(&fifo_lock);
 
 		/* Refill our FIFO */
 		if (fifo_pos == 0)
@@ -117,7 +143,7 @@ TEE_Result hw_get_random_bytes(void *buf, size_t len)
 		buffer[buffer_pos++] = fifo.byte[fifo_pos++];
 		fifo_pos %= 16;
 
-		cpu_spin_unlock_xrestore(&rng_lock, exceptions);
+		mutex_unlock(&fifo_lock);
 	}
 
 	return TEE_SUCCESS;
@@ -125,22 +151,9 @@ TEE_Result hw_get_random_bytes(void *buf, size_t len)
 
 TEE_Result sa2ul_rng_init(void)
 {
-	uint32_t val = 0;
-
 	rng = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC, RNG_REG_SIZE);
 
-	/* Ensure initial latency */
-	val |= RNG_CONFIG_MIN_REFIL_CYCLES << RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT;
-	val |= RNG_CONFIG_MAX_REFIL_CYCLES << RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT;
-	io_write32(rng + RNG_CONFIG, val);
-
-	/* Configure the desired FROs */
-	io_write32(rng + RNG_FRODETUNE, 0x0);
-
-	/* Enable all FROs */
-	io_write32(rng + RNG_FROENABLE, 0xffffff);
-
-	io_write32(rng + RNG_CONTROL, ENABLE_TRNG);
+	sa2ul_rng_init_seq();
 
 	IMSG("SA2UL TRNG initialized");
 
diff --git a/core/arch/arm/plat-k3/main.c b/core/arch/arm/plat-k3/main.c
index 531da533e4a172b5034d7262ae9dd1d574da72ab..e029554412f422a166c809b9f725a8c03b51e487 100644
--- a/core/arch/arm/plat-k3/main.c
+++ b/core/arch/arm/plat-k3/main.c
@@ -39,7 +39,7 @@ void boot_primary_init_intc(void)
 
 void boot_secondary_init_intc(void)
 {
-	gic_cpu_init();
+	gic_init_per_cpu();
 }
 
 void console_init(void)
diff --git a/core/arch/arm/plat-ls/main.c b/core/arch/arm/plat-ls/main.c
index 3aa97ba9fb59d52fec9b92cb6b84e11fbd43c1f3..8358bc133649722efc0503d4ed2103617a7b2dc1 100644
--- a/core/arch/arm/plat-ls/main.c
+++ b/core/arch/arm/plat-ls/main.c
@@ -215,9 +215,7 @@ void boot_primary_init_intc(void)
 	gic_init(gic_base + gicc_offset, gic_base + gicd_offset);
 }
 
-#if !defined(CFG_WITH_ARM_TRUSTED_FW)
 void boot_secondary_init_intc(void)
 {
-	gic_cpu_init();
+	gic_init_per_cpu();
 }
-#endif
diff --git a/core/arch/arm/plat-mediatek/main.c b/core/arch/arm/plat-mediatek/main.c
index 2470def4183300e7d54b26fd4d2da57e6b247458..de7e06344fbef635e0659c5952f5f64d8b83dbb1 100644
--- a/core/arch/arm/plat-mediatek/main.c
+++ b/core/arch/arm/plat-mediatek/main.c
@@ -12,8 +12,10 @@
 #include <platform_config.h>
 #include <stdint.h>
 
+#if (CFG_TEE_CORE_LOG_LEVEL != 0)
 register_phys_mem_pgdir(MEM_AREA_IO_NSEC,
 			CONSOLE_UART_BASE, SERIAL8250_UART_REG_SIZE);
+#endif
 
 static struct serial8250_uart_data console_data;
 
@@ -33,7 +35,9 @@ void boot_primary_init_intc(void)
 
 void console_init(void)
 {
-	serial8250_uart_init(&console_data, CONSOLE_UART_BASE,
-			     CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
-	register_serial_console(&console_data.chip);
+	if (CFG_TEE_CORE_LOG_LEVEL != 0) {
+		serial8250_uart_init(&console_data, CONSOLE_UART_BASE,
+				     CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
+		register_serial_console(&console_data.chip);
+	}
 }
diff --git a/core/arch/arm/plat-nuvoton/main.c b/core/arch/arm/plat-nuvoton/main.c
index 933fb2dd1a5af0be1865230b33bbbb060b784475..88db73db1d49f314cf5602e4eca92fed1535c2d6 100644
--- a/core/arch/arm/plat-nuvoton/main.c
+++ b/core/arch/arm/plat-nuvoton/main.c
@@ -26,8 +26,8 @@
 #define COLOR_WHITE	"\x1B[37m"
 
 #define NPCM_MEASURE_BASE	0xF0848000
-#define NPCM_MEASURE_DME	0x0E0
-#define NPCM_MEASURE_SIZE	64
+#define NPCM_MEASURE_UUID	0xC50
+#define NPCM_MEASURE_SIZE	5
 
 static struct ns16550_data console_data __nex_bss;
 
@@ -76,7 +76,7 @@ TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
 	if (npcm_hwkey.ready)
 		goto out;
 
-	vaddr = phys_to_virt(NPCM_MEASURE_BASE + NPCM_MEASURE_DME,
+	vaddr = phys_to_virt(NPCM_MEASURE_BASE + NPCM_MEASURE_UUID,
 			     MEM_AREA_RAM_NSEC, NPCM_MEASURE_SIZE);
 	if (!vaddr) {
 		EMSG("Not enough memory mapped");
diff --git a/core/arch/arm/plat-rcar/conf.mk b/core/arch/arm/plat-rcar/conf.mk
index 0de4143dfeda44ccf1a7b154d93fb6c25c107af3..c810dfeb8385025a0f24eea44370bd1282d3e81f 100644
--- a/core/arch/arm/plat-rcar/conf.mk
+++ b/core/arch/arm/plat-rcar/conf.mk
@@ -24,12 +24,15 @@ CFG_TEE_RAM_VA_SIZE ?= 0x100000
 supported-ta-targets = ta_arm64
 
 ifeq ($(CFG_RCAR_GEN3), y)
+CFG_DT ?= y
+ifeq ($(CFG_RCAR_GEN3_HWRNG), y)
+$(warning "Warning: Use of HWRNG can cause crashes on some Renesas SoCs")
 CFG_WITH_SOFTWARE_PRNG ?= n
 CFG_HWRNG_QUALITY ?= 1024
 CFG_HWRNG_PTA ?= y
-CFG_DT ?= y
 $(call force,CFG_RCAR_ROMAPI, y)
 endif
+endif
 
 ifeq ($(CFG_RCAR_GEN4), y)
 # 1xx - for SCIFxx
diff --git a/core/arch/arm/plat-rcar/main.c b/core/arch/arm/plat-rcar/main.c
index 9b443f9abae2c1b0495edab23443499fe4f884e3..452e05e97091217977934ea1afb660a7706f0257 100644
--- a/core/arch/arm/plat-rcar/main.c
+++ b/core/arch/arm/plat-rcar/main.c
@@ -94,5 +94,5 @@ void boot_primary_init_intc(void)
 
 void boot_secondary_init_intc(void)
 {
-	gic_cpu_init();
+	gic_init_per_cpu();
 }
diff --git a/core/arch/arm/plat-rcar/romapi.c b/core/arch/arm/plat-rcar/romapi.c
index ad0a0d95dc336b6536ae42d65d3e6c4b6401b2cc..19c2045f729e45bfdbb143a59a386a1ecdb7acd3 100644
--- a/core/arch/arm/plat-rcar/romapi.c
+++ b/core/arch/arm/plat-rcar/romapi.c
@@ -121,6 +121,7 @@ uint32_t plat_rom_getrndvector(uint8_t rndbuff[PLAT_RND_VECTOR_SZ],
 			       uint8_t *scratch, uint32_t scratch_sz)
 {
 	uint32_t ret = -1;
+	int try = 0;
 	paddr_t func_addr = romapi_getrndvector[get_api_table_index()];
 	paddr_t rndbuff_pa = va2pa(rndbuff);
 	paddr_t scratch_pa = va2pa(scratch);
@@ -129,7 +130,13 @@ uint32_t plat_rom_getrndvector(uint8_t rndbuff[PLAT_RND_VECTOR_SZ],
 	assert(rndbuff_pa % RCAR_CACHE_LINE_SZ == 0);
 	assert(scratch_pa % RCAR_CACHE_LINE_SZ == 0);
 
-	ret = plat_call_romapi(func_addr, rndbuff_pa, scratch_pa, scratch_sz);
+	while (try++ < 3) {
+		ret = plat_call_romapi(func_addr, rndbuff_pa, scratch_pa,
+				       scratch_sz);
+		if (ret == 0)
+			break;
+		IMSG("ROM_GetRndVector() returned "PRIx32, ret);
+	}
 
 	/*
 	 * ROM code is called with MMU turned off, so any accesses to rndbuff
diff --git a/core/arch/arm/plat-rockchip/main.c b/core/arch/arm/plat-rockchip/main.c
index b7501ddd6b36d83775dac39869e214b641222a61..a85900fa31434c7a39f93878b62e7aee9d6e5c93 100644
--- a/core/arch/arm/plat-rockchip/main.c
+++ b/core/arch/arm/plat-rockchip/main.c
@@ -29,7 +29,7 @@ void boot_primary_init_intc(void)
 
 void boot_secondary_init_intc(void)
 {
-	gic_cpu_init();
+	gic_init_per_cpu();
 }
 
 void console_init(void)
diff --git a/core/arch/arm/plat-rockchip/platform.c b/core/arch/arm/plat-rockchip/platform.c
index 96c343f02dfe14550af0cb5e42e9877509c56418..8028f2c13d1fbae88d2dceac9f0af31c61bd8648 100644
--- a/core/arch/arm/plat-rockchip/platform.c
+++ b/core/arch/arm/plat-rockchip/platform.c
@@ -19,7 +19,7 @@ int __weak platform_secure_ddr_region(int rgn __maybe_unused,
 				      paddr_t st __maybe_unused,
 				      size_t sz __maybe_unused)
 {
-	MSG("Not protecting region %d: 0x%lx-0x%lx\n", rgn, st, st + sz);
+	MSG("Not protecting region %d: 0x%lx-0x%lx", rgn, st, st + sz);
 
 	return 0;
 }
diff --git a/core/arch/arm/plat-rockchip/platform_px30.c b/core/arch/arm/plat-rockchip/platform_px30.c
index 8327ca929e27715bdf5a570859de233d74f63191..08cd4906243f81311a7a0c68c12e551c8a7b4554 100644
--- a/core/arch/arm/plat-rockchip/platform_px30.c
+++ b/core/arch/arm/plat-rockchip/platform_px30.c
@@ -38,7 +38,7 @@ int platform_secure_ddr_region(int rgn, paddr_t st, size_t sz)
 	assert(st % SIZE_M(1) == 0);
 	assert(ed % SIZE_M(1) == 0);
 
-	DMSG("protecting region %d: 0x%lx-0x%lx\n", rgn, st, ed);
+	DMSG("protecting region %d: 0x%lx-0x%lx", rgn, st, ed);
 
 	/* Map top and base */
 	io_write32(fw_base + FIREWALL_DDR_FW_DDR_RGN(rgn),
diff --git a/core/arch/arm/plat-rockchip/platform_rk3399.c b/core/arch/arm/plat-rockchip/platform_rk3399.c
index 053f566e65295ce0288f63b3cf33b6b67e2c5b65..1ff72cee1c4c5eb984ad4760008dd5ae33dbe2cf 100644
--- a/core/arch/arm/plat-rockchip/platform_rk3399.c
+++ b/core/arch/arm/plat-rockchip/platform_rk3399.c
@@ -32,7 +32,7 @@ int platform_secure_ddr_region(int rgn, paddr_t st, size_t sz)
 	assert(st % SIZE_M(1) == 0);
 	assert(ed % SIZE_M(1) == 0);
 
-	DMSG("protecting region %d: 0x%lx-0x%lx\n", rgn, st, ed);
+	DMSG("protecting region %d: 0x%lx-0x%lx", rgn, st, ed);
 
 	/* Set ddr region addr start */
 	io_write32(sgrf_base + SGRF_DDRRGN_CON0_16(rgn),
diff --git a/core/arch/arm/plat-rzn1/main.c b/core/arch/arm/plat-rzn1/main.c
index ac6d88f8edb23b663a0676a04fa6061cf27083d8..bed02b80f74bad1714683622cf01482922439b50 100644
--- a/core/arch/arm/plat-rzn1/main.c
+++ b/core/arch/arm/plat-rzn1/main.c
@@ -47,7 +47,7 @@ void boot_primary_init_intc(void)
 
 void boot_secondary_init_intc(void)
 {
-	gic_cpu_init();
+	gic_init_per_cpu();
 }
 
 static TEE_Result rzn1_tz_init(void)
diff --git a/core/arch/arm/plat-sam/conf.mk b/core/arch/arm/plat-sam/conf.mk
index d546cbc6af70c1ee5f6db3e61c8d4a76ac383926..feef98c0ee5da03a4b976e8f90b6523ab3200493 100644
--- a/core/arch/arm/plat-sam/conf.mk
+++ b/core/arch/arm/plat-sam/conf.mk
@@ -39,6 +39,9 @@ $(call force,CFG_CORE_HAS_GENERIC_TIMER,n)
 $(call force,CFG_TZDRAM_START,0x20000000)
 $(call force,CFG_TZDRAM_SIZE,0x800000)
 
+# This value is forced because this feature isn't used by SAM platforms.
+$(call force,CFG_EXTERNAL_DT,n)
+
 CFG_MMAP_REGIONS ?= 24
 
 CFG_SHMEM_START  ?= 0x21000000
@@ -108,3 +111,6 @@ $(call force,CFG_SCMI_MSG_CLOCK,y)
 $(call force,CFG_SCMI_MSG_USE_CLK,y)
 $(call force,CFG_SCMI_MSG_SMT_FASTCALL_ENTRY,y)
 endif
+
+CFG_DRIVERS_NVMEM ?= y
+CFG_ATMEL_SFC ?= y
diff --git a/core/arch/arm/plat-sam/main.c b/core/arch/arm/plat-sam/main.c
index 503ab0dbd5706a03f45e8787e2256667cc6edbee..1fffce5884fbbb2d826ca99dcf49224650131faf 100644
--- a/core/arch/arm/plat-sam/main.c
+++ b/core/arch/arm/plat-sam/main.c
@@ -44,6 +44,457 @@
 #include <sm/optee_smc.h>
 #include <tz_matrix.h>
 
+#define MATRIX_AXIMX   1
+#define MATRIX_H64MX   2
+#define MATRIX_H32MX   3
+
+static struct matrix matrixes[] = {
+	{
+		.matrix = MATRIX_H64MX,
+		.p = { .pa = AT91C_BASE_MATRIX64 }
+	},
+	{
+		.matrix = MATRIX_H32MX,
+		.p = { .pa = AT91C_BASE_MATRIX32, }
+	}
+};
+
+static struct peri_security peri_security_array[] = {
+	{
+		.peri_id = AT91C_ID_PMC,
+		.matrix = MATRIX_H64MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_PMC,
+	},
+	{
+		.peri_id = AT91C_ID_ARM,
+		.matrix = MATRIX_H64MX,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = AT91C_ID_PIT,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_PITC,
+	},
+	{
+		.peri_id = AT91C_ID_WDT,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_WDT,
+	},
+	{
+		.peri_id = AT91C_ID_GMAC,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_GMAC,
+	},
+	{
+		.peri_id = AT91C_ID_XDMAC0,
+		.matrix = MATRIX_H64MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_XDMAC0,
+	},
+	{
+		.peri_id = AT91C_ID_XDMAC1,
+		.matrix = MATRIX_H64MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_XDMAC1,
+	},
+	{
+		.peri_id = AT91C_ID_ICM,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_ICM,
+	},
+	{
+		.peri_id = AT91C_ID_AES,
+		.matrix = MATRIX_H64MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_AES,
+	},
+	{
+		.peri_id = AT91C_ID_AESB,
+		.matrix = MATRIX_H64MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_AESB,
+	},
+	{
+		.peri_id = AT91C_ID_TDES,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_TDES,
+	},
+	{
+		.peri_id = AT91C_ID_SHA,
+		.matrix = MATRIX_H64MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_SHA,
+	},
+	{
+		.peri_id = AT91C_ID_MPDDRC,
+		.matrix = MATRIX_H64MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_MPDDRC,
+	},
+	{
+		.peri_id = AT91C_ID_MATRIX1,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = AT91C_BASE_MATRIX32,
+	},
+	{
+		.peri_id = AT91C_ID_MATRIX0,
+		.matrix = MATRIX_H64MX,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = AT91C_BASE_MATRIX64,
+	},
+	{
+		.peri_id = AT91C_ID_SECUMOD,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = AT91C_BASE_SECUMOD,
+	},
+	{
+		.peri_id = AT91C_ID_HSMC,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_HSMC,
+	},
+	{
+		.peri_id = AT91C_ID_PIOA,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = AT91C_BASE_PIOA,
+	},
+	{
+		.peri_id = AT91C_ID_FLEXCOM0,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_FLEXCOM0,
+	},
+	{
+		.peri_id = AT91C_ID_FLEXCOM1,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_FLEXCOM1,
+	},
+	{
+		.peri_id = AT91C_ID_FLEXCOM2,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_FLEXCOM2,
+	},
+	{
+		.peri_id = AT91C_ID_FLEXCOM3,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_FLEXCOM3,
+	},
+	{
+		.peri_id = AT91C_ID_FLEXCOM4,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_FLEXCOM4,
+	},
+	{
+		.peri_id = AT91C_ID_UART0,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_UART0,
+	},
+	{
+		.peri_id = AT91C_ID_UART1,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_UART1,
+	},
+	{
+		.peri_id = AT91C_ID_UART2,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_UART2,
+	},
+	{
+		.peri_id = AT91C_ID_UART3,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_UART3,
+	},
+	{
+		.peri_id = AT91C_ID_UART4,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_UART4,
+	},
+	{
+		.peri_id = AT91C_ID_TWI0,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_TWI0,
+	},
+	{
+		.peri_id = AT91C_ID_TWI1,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_TWI1,
+	},
+	{
+		.peri_id = AT91C_ID_SDMMC0,
+		.matrix = MATRIX_H64MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_SDHC0,
+	},
+	{
+		.peri_id = AT91C_ID_SDMMC1,
+		.matrix = MATRIX_H64MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_SDHC1,
+	},
+	{
+		.peri_id = AT91C_ID_SPI0,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_SPI0,
+	},
+	{
+		.peri_id = AT91C_ID_SPI1,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_SPI1,
+	},
+	{
+		.peri_id = AT91C_ID_TC0,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_TC0,
+	},
+	{
+		.peri_id = AT91C_ID_TC1,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_TC1,
+	},
+	{
+		.peri_id = AT91C_ID_PWM,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_PWMC,
+	},
+	{
+		.peri_id = AT91C_ID_ADC,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_ADC,
+	},
+	{
+		.peri_id = AT91C_ID_UHPHS,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = AT91C_ID_UDPHS,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_UDPHS,
+	},
+	{
+		.peri_id = AT91C_ID_SSC0,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_SSC0,
+	},
+	{
+		.peri_id = AT91C_ID_SSC1,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_SSC1,
+	},
+	{
+		.peri_id = AT91C_ID_LCDC,
+		.matrix = MATRIX_H64MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_LCDC,
+	},
+	{
+		.peri_id = AT91C_ID_ISI,
+		.matrix = MATRIX_H64MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_HXISI,
+	},
+	{
+		.peri_id = AT91C_ID_TRNG,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_TRNG,
+	},
+	{
+		.peri_id = AT91C_ID_PDMIC,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_PDMIC,
+	},
+	{
+		.peri_id = AT91C_ID_IRQ,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_NS,
+	},
+	{
+		.peri_id = AT91C_ID_SFC,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_SFC,
+	},
+	{
+		.peri_id = AT91C_ID_SECURAM,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = AT91C_BASE_SECURAM,
+	},
+	{
+		.peri_id = AT91C_ID_QSPI0,
+		.matrix = MATRIX_H64MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_QSPI0,
+	},
+	{
+		.peri_id = AT91C_ID_QSPI1,
+		.matrix = MATRIX_H64MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_QSPI1,
+	},
+	{
+		.peri_id = AT91C_ID_I2SC0,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_I2SC0,
+	},
+	{
+		.peri_id = AT91C_ID_I2SC1,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_I2SC1,
+	},
+	{
+		.peri_id = AT91C_ID_CAN0_INT0,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = AT91C_ID_CAN1_INT0,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = AT91C_ID_CLASSD,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_CLASSD,
+	},
+	{
+		.peri_id = AT91C_ID_SFR,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_SFR,
+	},
+	{
+		.peri_id = AT91C_ID_SAIC,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = AT91C_BASE_SAIC,
+	},
+	{
+		.peri_id = AT91C_ID_AIC,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_NS,
+		.addr = AT91C_BASE_AIC,
+	},
+	{
+		.peri_id = AT91C_ID_L2CC,
+		.matrix = MATRIX_H64MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_L2CC,
+	},
+	{
+		.peri_id = AT91C_ID_CAN0_INT1,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = AT91C_ID_CAN1_INT1,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = AT91C_ID_GMAC_Q1,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = AT91C_ID_GMAC_Q2,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = AT91C_ID_PIOB,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = AT91C_BASE_PIOB,
+	},
+	{
+		.peri_id = AT91C_ID_PIOC,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = AT91C_BASE_PIOC,
+	},
+	{
+		.peri_id = AT91C_ID_PIOD,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = AT91C_BASE_PIOD,
+	},
+	{
+		.peri_id = AT91C_ID_SDMMC0_TIMER,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = AT91C_ID_SDMMC1_TIMER,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = AT91C_ID_SYS,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_SYSC,
+	},
+	{
+		.peri_id = AT91C_ID_ACC,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_ACC,
+	},
+	{
+		.peri_id = AT91C_ID_RXLP,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_RXLP,
+	},
+	{
+		.peri_id = AT91C_ID_SFRBU,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_SFRBU,
+	},
+	{
+		.peri_id = AT91C_ID_CHIPID,
+		.matrix = MATRIX_H32MX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AT91C_BASE_CHIPID,
+	},
+};
+
 static struct atmel_uart_data console_data;
 register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE,
 			CORE_MMU_PGDIR_SIZE);
@@ -59,30 +510,24 @@ register_phys_mem_pgdir(MEM_AREA_IO_SEC, AT91C_BASE_MATRIX32,
 register_phys_mem_pgdir(MEM_AREA_IO_SEC, AT91C_BASE_MATRIX64,
 			CORE_MMU_PGDIR_SIZE);
 
-vaddr_t matrix32_base(void)
+struct peri_security *peri_security_get(unsigned int idx)
 {
-	static void *va;
+	struct peri_security *p = NULL;
 
-	if (cpu_mmu_enabled()) {
-		if (!va)
-			va = phys_to_virt(AT91C_BASE_MATRIX32, MEM_AREA_IO_SEC,
-					  1);
-		return (vaddr_t)va;
-	}
-	return AT91C_BASE_MATRIX32;
+	if (idx < ARRAY_SIZE(peri_security_array))
+		p = &peri_security_array[idx];
+
+	return p;
 }
 
-vaddr_t matrix64_base(void)
+struct matrix *matrix_get(unsigned int idx)
 {
-	static void *va;
+	struct matrix *pmatrix = NULL;
 
-	if (cpu_mmu_enabled()) {
-		if (!va)
-			va = phys_to_virt(AT91C_BASE_MATRIX64, MEM_AREA_IO_SEC,
-					  1);
-		return (vaddr_t)va;
-	}
-	return AT91C_BASE_MATRIX64;
+	if (idx < ARRAY_SIZE(matrixes))
+		pmatrix = &matrixes[idx];
+
+	return pmatrix;
 }
 
 static void matrix_configure_slave_h64mx(void)
@@ -108,7 +553,7 @@ static void matrix_configure_slave_h64mx(void)
 			| MATRIX_RDNSECH_NS(2)
 			| MATRIX_WRNSECH_NS(1)
 			| MATRIX_WRNSECH_NS(2));
-	matrix_configure_slave_security(matrix64_base(),
+	matrix_configure_slave_security(matrix_base(MATRIX_H64MX),
 					H64MX_SLAVE_PERI_BRIDGE,
 					srtop_setting,
 					sasplit_setting,
@@ -142,11 +587,11 @@ static void matrix_configure_slave_h64mx(void)
 			| MATRIX_WRNSECH_NS(3));
 	/* DDR port 0 not used from NWd */
 	for (ddr_port = 1; ddr_port < 8; ddr_port++) {
-		matrix_configure_slave_security(matrix64_base(),
-					(H64MX_SLAVE_DDR2_PORT_0 + ddr_port),
-					srtop_setting,
-					sasplit_setting,
-					ssr_setting);
+		matrix_configure_slave_security(matrix_base(MATRIX_H64MX),
+						H64MX_SLAVE_DDR2_PORT_0 +
+						ddr_port, srtop_setting,
+						sasplit_setting,
+						ssr_setting);
 	}
 
 	/*
@@ -158,7 +603,7 @@ static void matrix_configure_slave_h64mx(void)
 	sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SRTOP_VALUE_64K);
 	ssr_setting = (MATRIX_LANSECH_S(0) | MATRIX_RDNSECH_S(0) |
 		       MATRIX_WRNSECH_S(0));
-	matrix_configure_slave_security(matrix64_base(),
+	matrix_configure_slave_security(matrix_base(MATRIX_H64MX),
 					H64MX_SLAVE_INTERNAL_SRAM,
 					srtop_setting, sasplit_setting,
 					ssr_setting);
@@ -172,10 +617,12 @@ static void matrix_configure_slave_h64mx(void)
 	ssr_setting = MATRIX_LANSECH_NS(0) | MATRIX_RDNSECH_NS(0) |
 		      MATRIX_WRNSECH_NS(0);
 
-	matrix_configure_slave_security(matrix64_base(), H64MX_SLAVE_QSPI0,
+	matrix_configure_slave_security(matrix_base(MATRIX_H64MX),
+					H64MX_SLAVE_QSPI0,
 					srtop_setting, sasplit_setting,
 					ssr_setting);
-	matrix_configure_slave_security(matrix64_base(), H64MX_SLAVE_QSPI1,
+	matrix_configure_slave_security(matrix_base(MATRIX_H64MX),
+					H64MX_SLAVE_QSPI1,
 					srtop_setting, sasplit_setting,
 					ssr_setting);
 	/* 14:  AESB: Default */
@@ -210,7 +657,7 @@ static void matrix_configure_slave_h32mx(void)
 	ssr_setting |= (MATRIX_LANSECH_NS(7)
 			| MATRIX_RDNSECH_NS(7)
 			| MATRIX_WRNSECH_NS(7));
-	matrix_configure_slave_security(matrix32_base(),
+	matrix_configure_slave_security(matrix_base(MATRIX_H32MX),
 					H32MX_EXTERNAL_EBI,
 					srtop_setting,
 					sasplit_setting,
@@ -222,7 +669,7 @@ static void matrix_configure_slave_h32mx(void)
 	ssr_setting = (MATRIX_LANSECH_NS(0)
 			| MATRIX_RDNSECH_NS(0)
 			| MATRIX_WRNSECH_NS(0));
-	matrix_configure_slave_security(matrix32_base(),
+	matrix_configure_slave_security(matrix_base(MATRIX_H32MX),
 					H32MX_NFC_SRAM,
 					srtop_setting,
 					sasplit_setting,
@@ -248,7 +695,7 @@ static void matrix_configure_slave_h32mx(void)
 			| MATRIX_WRNSECH_NS(0)
 			| MATRIX_WRNSECH_NS(1)
 			| MATRIX_WRNSECH_NS(2));
-	matrix_configure_slave_security(matrix32_base(),
+	matrix_configure_slave_security(matrix_base(MATRIX_H32MX),
 					H32MX_USB,
 					srtop_setting,
 					sasplit_setting,
@@ -323,8 +770,8 @@ static unsigned int security_ps_peri_id[] = {
 
 static int matrix_init(void)
 {
-	matrix_write_protect_disable(matrix64_base());
-	matrix_write_protect_disable(matrix32_base());
+	matrix_write_protect_disable(matrix_base(MATRIX_H64MX));
+	matrix_write_protect_disable(matrix_base(MATRIX_H32MX));
 
 	matrix_configure_slave_h64mx();
 	matrix_configure_slave_h32mx();
diff --git a/core/arch/arm/plat-sam/matrix.c b/core/arch/arm/plat-sam/matrix.c
index c0a39e57b1d3e5464ec9fcc4af8771d9477212c4..f897e069523feeab507b8426ecb6f9acef04bf2f 100644
--- a/core/arch/arm/plat-sam/matrix.c
+++ b/core/arch/arm/plat-sam/matrix.c
@@ -32,469 +32,16 @@
 #include <kernel/pm.h>
 #include <kernel/panic.h>
 #include <matrix.h>
+#include <mm/core_memprot.h>
+#include <mm/core_mmu.h>
 #include <platform_config.h>
-#include <sama5d2.h>
 #include <stdint.h>
 #include <tz_matrix.h>
 #include <trace.h>
 
-#define MATRIX_AXIMX	1
-#define MATRIX_H64MX	2
-#define MATRIX_H32MX	3
-
-#define SECURITY_TYPE_AS	1
-#define SECURITY_TYPE_NS	2
-#define SECURITY_TYPE_PS	3
-
 #define WORLD_NON_SECURE	0
 #define WORLD_SECURE		1
 
-#define MATRIX_SPSELR_COUNT	3
-#define MATRIX_SLAVE_COUNT	15
-
-struct peri_security {
-	unsigned int peri_id;
-	unsigned int matrix;
-	unsigned int security_type;
-	paddr_t addr;
-};
-
-static const struct peri_security peri_security_array[] = {
-	{
-		.peri_id = AT91C_ID_PMC,
-		.matrix = MATRIX_H64MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_PMC,
-	},
-	{
-		.peri_id = AT91C_ID_ARM,
-		.matrix = MATRIX_H64MX,
-		.security_type = SECURITY_TYPE_PS,
-	},
-	{
-		.peri_id = AT91C_ID_PIT,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_PITC,
-	},
-	{
-		.peri_id = AT91C_ID_WDT,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_WDT,
-	},
-	{
-		.peri_id = AT91C_ID_GMAC,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_GMAC,
-	},
-	{
-		.peri_id = AT91C_ID_XDMAC0,
-		.matrix = MATRIX_H64MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_XDMAC0,
-	},
-	{
-		.peri_id = AT91C_ID_XDMAC1,
-		.matrix = MATRIX_H64MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_XDMAC1,
-	},
-	{
-		.peri_id = AT91C_ID_ICM,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_ICM,
-	},
-	{
-		.peri_id = AT91C_ID_AES,
-		.matrix = MATRIX_H64MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_AES,
-	},
-	{
-		.peri_id = AT91C_ID_AESB,
-		.matrix = MATRIX_H64MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_AESB,
-	},
-	{
-		.peri_id = AT91C_ID_TDES,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_TDES,
-	},
-	{
-		.peri_id = AT91C_ID_SHA,
-		.matrix = MATRIX_H64MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_SHA,
-	},
-	{
-		.peri_id = AT91C_ID_MPDDRC,
-		.matrix = MATRIX_H64MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_MPDDRC,
-	},
-	{
-		.peri_id = AT91C_ID_MATRIX1,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_AS,
-		.addr = AT91C_BASE_MATRIX32,
-	},
-	{
-		.peri_id = AT91C_ID_MATRIX0,
-		.matrix = MATRIX_H64MX,
-		.security_type = SECURITY_TYPE_AS,
-		.addr = AT91C_BASE_MATRIX64,
-	},
-	{
-		.peri_id = AT91C_ID_SECUMOD,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_AS,
-		.addr = AT91C_BASE_SECUMOD,
-	},
-	{
-		.peri_id = AT91C_ID_HSMC,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_HSMC,
-	},
-	{
-		.peri_id = AT91C_ID_PIOA,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_AS,
-		.addr = AT91C_BASE_PIOA,
-	},
-	{
-		.peri_id = AT91C_ID_FLEXCOM0,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_FLEXCOM0,
-	},
-	{
-		.peri_id = AT91C_ID_FLEXCOM1,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_FLEXCOM1,
-	},
-	{
-		.peri_id = AT91C_ID_FLEXCOM2,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_FLEXCOM2,
-	},
-	{
-		.peri_id = AT91C_ID_FLEXCOM3,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_FLEXCOM3,
-	},
-	{
-		.peri_id = AT91C_ID_FLEXCOM4,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_FLEXCOM4,
-	},
-	{
-		.peri_id = AT91C_ID_UART0,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_UART0,
-	},
-	{
-		.peri_id = AT91C_ID_UART1,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_UART1,
-	},
-	{
-		.peri_id = AT91C_ID_UART2,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_UART2,
-	},
-	{
-		.peri_id = AT91C_ID_UART3,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_UART3,
-	},
-	{
-		.peri_id = AT91C_ID_UART4,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_UART4,
-	},
-	{
-		.peri_id = AT91C_ID_TWI0,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_TWI0,
-	},
-	{
-		.peri_id = AT91C_ID_TWI1,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_TWI1,
-	},
-	{
-		.peri_id = AT91C_ID_SDMMC0,
-		.matrix = MATRIX_H64MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_SDHC0,
-	},
-	{
-		.peri_id = AT91C_ID_SDMMC1,
-		.matrix = MATRIX_H64MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_SDHC1,
-	},
-	{
-		.peri_id = AT91C_ID_SPI0,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_SPI0,
-	},
-	{
-		.peri_id = AT91C_ID_SPI1,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_SPI1,
-	},
-	{
-		.peri_id = AT91C_ID_TC0,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_TC0,
-	},
-	{
-		.peri_id = AT91C_ID_TC1,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_TC1,
-	},
-	{
-		.peri_id = AT91C_ID_PWM,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_PWMC,
-	},
-	{
-		.peri_id = AT91C_ID_ADC,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_ADC,
-	},
-	{
-		.peri_id = AT91C_ID_UHPHS,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-	},
-	{
-		.peri_id = AT91C_ID_UDPHS,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_UDPHS,
-	},
-	{
-		.peri_id = AT91C_ID_SSC0,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_SSC0,
-	},
-	{
-		.peri_id = AT91C_ID_SSC1,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_SSC1,
-	},
-	{
-		.peri_id = AT91C_ID_LCDC,
-		.matrix = MATRIX_H64MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_LCDC,
-	},
-	{
-		.peri_id = AT91C_ID_ISI,
-		.matrix = MATRIX_H64MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_HXISI,
-	},
-	{
-		.peri_id = AT91C_ID_TRNG,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_TRNG,
-	},
-	{
-		.peri_id = AT91C_ID_PDMIC,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_PDMIC,
-	},
-	{
-		.peri_id = AT91C_ID_IRQ,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_NS,
-	},
-	{
-		.peri_id = AT91C_ID_SFC,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_SFC,
-	},
-	{
-		.peri_id = AT91C_ID_SECURAM,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_AS,
-		.addr = AT91C_BASE_SECURAM,
-	},
-	{
-		.peri_id = AT91C_ID_QSPI0,
-		.matrix = MATRIX_H64MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_QSPI0,
-	},
-	{
-		.peri_id = AT91C_ID_QSPI1,
-		.matrix = MATRIX_H64MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_QSPI1,
-	},
-	{
-		.peri_id = AT91C_ID_I2SC0,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_I2SC0,
-	},
-	{
-		.peri_id = AT91C_ID_I2SC1,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_I2SC1,
-	},
-	{
-		.peri_id = AT91C_ID_CAN0_INT0,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-	},
-	{
-		.peri_id = AT91C_ID_CAN1_INT0,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-	},
-	{
-		.peri_id = AT91C_ID_CLASSD,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_CLASSD,
-	},
-	{
-		.peri_id = AT91C_ID_SFR,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_SFR,
-	},
-	{
-		.peri_id = AT91C_ID_SAIC,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_AS,
-		.addr = AT91C_BASE_SAIC,
-	},
-	{
-		.peri_id = AT91C_ID_AIC,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_NS,
-		.addr = AT91C_BASE_AIC,
-	},
-	{
-		.peri_id = AT91C_ID_L2CC,
-		.matrix = MATRIX_H64MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_L2CC,
-	},
-	{
-		.peri_id = AT91C_ID_CAN0_INT1,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-	},
-	{
-		.peri_id = AT91C_ID_CAN1_INT1,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-	},
-	{
-		.peri_id = AT91C_ID_GMAC_Q1,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-	},
-	{
-		.peri_id = AT91C_ID_GMAC_Q2,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-	},
-	{
-		.peri_id = AT91C_ID_PIOB,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_AS,
-		.addr = AT91C_BASE_PIOB,
-	},
-	{
-		.peri_id = AT91C_ID_PIOC,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_AS,
-		.addr = AT91C_BASE_PIOC,
-	},
-	{
-		.peri_id = AT91C_ID_PIOD,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_AS,
-		.addr = AT91C_BASE_PIOD,
-	},
-	{
-		.peri_id = AT91C_ID_SDMMC0_TIMER,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-	},
-	{
-		.peri_id = AT91C_ID_SDMMC1_TIMER,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-	},
-	{
-		.peri_id = AT91C_ID_SYS,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_SYSC,
-	},
-	{
-		.peri_id = AT91C_ID_ACC,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_ACC,
-	},
-	{
-		.peri_id = AT91C_ID_RXLP,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_RXLP,
-	},
-	{
-		.peri_id = AT91C_ID_SFRBU,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_SFRBU,
-	},
-	{
-		.peri_id = AT91C_ID_CHIPID,
-		.matrix = MATRIX_H32MX,
-		.security_type = SECURITY_TYPE_PS,
-		.addr = AT91C_BASE_CHIPID,
-	},
-};
-
 static void matrix_write(unsigned int base,
 			 unsigned int offset,
 			 const unsigned int value)
@@ -507,10 +54,24 @@ static unsigned int matrix_read(int base, unsigned int offset)
 	return io_read32(offset + base);
 }
 
+vaddr_t matrix_base(unsigned int matrix)
+{
+	unsigned int i = 0;
+	struct matrix *pmatrix = NULL;
+
+	do {
+		pmatrix = matrix_get(i++);
+		if (!pmatrix)
+			panic("Invalid matrix");
+	} while (pmatrix->matrix != matrix);
+
+	return io_pa_or_va_secure(&pmatrix->p, CORE_MMU_PGDIR_SIZE);
+}
+
 void matrix_write_protect_enable(unsigned int matrix_base)
 {
 	matrix_write(matrix_base, MATRIX_WPMR,
-		    (MATRIX_WPMR_WPKEY_PASSWD | MATRIX_WPMR_WPEN_ENABLE));
+		     MATRIX_WPMR_WPKEY_PASSWD | MATRIX_WPMR_WPEN_ENABLE);
 }
 
 void matrix_write_protect_disable(unsigned int matrix_base)
@@ -531,37 +92,29 @@ void matrix_configure_slave_security(unsigned int matrix_base,
 
 static const struct peri_security *get_peri_security(unsigned int peri_id)
 {
-	unsigned int i;
+	unsigned int i = 0;
+	struct peri_security *p = NULL;
 
-	for (i = 0; i < ARRAY_SIZE(peri_security_array); i++) {
-		if (peri_id == peri_security_array[i].peri_id)
-			return &peri_security_array[i];
-	}
+	do {
+		p = peri_security_get(i++);
+		if (p && peri_id == p->peri_id)
+			break;
+	} while (p);
 
-	return NULL;
+	return p;
 }
 
 static int matrix_set_periph_world(unsigned int matrix, unsigned int peri_id,
 				   unsigned int world)
 {
-	unsigned int base;
-	unsigned int spselr;
-	unsigned int idx;
-	unsigned int bit;
+	unsigned int spselr = 0;
+	unsigned int idx = peri_id / 32;
+	unsigned int bit = 0x01 << (peri_id % 32);
+	unsigned int base = matrix_base(matrix);
 
-	idx = peri_id / 32;
 	if (idx > 3)
 		return -1;
 
-	bit = (0x01 << (peri_id % 32));
-
-	if (matrix == MATRIX_H32MX)
-		base = matrix32_base();
-	else if (matrix == MATRIX_H64MX)
-		base = matrix64_base();
-	else
-		return -1;
-
 	spselr = matrix_read(base, MATRIX_SPSELR(idx));
 	if (world == WORLD_SECURE)
 		spselr &= ~bit;
@@ -576,17 +129,19 @@ TEE_Result matrix_dt_get_id(const void *fdt, int node, unsigned int *id)
 {
 	unsigned int i = 0;
 	paddr_t pbase = 0;
+	struct peri_security *p = NULL;
 
 	pbase = fdt_reg_base_address(fdt, node);
 	if (pbase == DT_INFO_INVALID_REG)
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	for (i = 0; i < ARRAY_SIZE(peri_security_array); i++) {
-		if (peri_security_array[i].addr == pbase) {
-			*id = peri_security_array[i].peri_id;
+	do {
+		p = peri_security_get(i++);
+		if (p && p->addr == pbase) {
+			*id = p->peri_id;
 			return TEE_SUCCESS;
 		}
-	}
+	} while (p);
 
 	return TEE_ERROR_ITEM_NOT_FOUND;
 }
@@ -605,17 +160,16 @@ int matrix_configure_periph_secure(unsigned int peri_id)
 int matrix_configure_periph_non_secure(unsigned int *peri_id_array,
 				       unsigned int size)
 {
-	unsigned int i;
-	unsigned int *peri_id_p;
-	unsigned int matrix;
-	unsigned int peri_id;
-	const struct peri_security *peripheral_sec;
-	int ret;
+	unsigned int i = 0;
+	unsigned int *peri_id_p = peri_id_array;
+	unsigned int matrix = 0;
+	unsigned int peri_id = 0;
+	const struct peri_security *peripheral_sec = NULL;
+	int ret = 0;
 
 	if (!peri_id_array || !size)
 		return -1;
 
-	peri_id_p = peri_id_array;
 	for (i = 0; i < size; i++) {
 		peripheral_sec = get_peri_security(*peri_id_p);
 		if (!peripheral_sec)
@@ -638,17 +192,6 @@ int matrix_configure_periph_non_secure(unsigned int *peri_id_array,
 }
 
 #ifdef CFG_PM_ARM32
-struct matrix_state {
-	uint32_t spselr[MATRIX_SPSELR_COUNT];
-	uint32_t ssr[MATRIX_SLAVE_COUNT];
-	uint32_t srtsr[MATRIX_SLAVE_COUNT];
-	uint32_t sassr[MATRIX_SLAVE_COUNT];
-	uint32_t meier;
-	uint32_t meimr;
-};
-
-static struct matrix_state matrix32_state;
-static struct matrix_state matrix64_state;
 
 static void matrix_save_regs(vaddr_t base, struct matrix_state *state)
 {
@@ -669,8 +212,11 @@ static void matrix_save_regs(vaddr_t base, struct matrix_state *state)
 
 static void matrix_suspend(void)
 {
-	matrix_save_regs(matrix32_base(), &matrix32_state);
-	matrix_save_regs(matrix64_base(), &matrix64_state);
+	unsigned int i = 0;
+	struct matrix *pmatrix = NULL;
+
+	for (pmatrix = matrix_get(i++); pmatrix; pmatrix = matrix_get(i++))
+		matrix_save_regs(matrix_base(pmatrix->matrix), &pmatrix->state);
 }
 
 static void matrix_restore_regs(vaddr_t base, struct matrix_state *state)
@@ -694,8 +240,12 @@ static void matrix_restore_regs(vaddr_t base, struct matrix_state *state)
 
 static void matrix_resume(void)
 {
-	matrix_restore_regs(matrix32_base(), &matrix32_state);
-	matrix_restore_regs(matrix64_base(), &matrix64_state);
+	unsigned int i = 0;
+	struct matrix *pmatrix = NULL;
+
+	for (pmatrix = matrix_get(i++); pmatrix; pmatrix = matrix_get(i++))
+		matrix_restore_regs(matrix_base(pmatrix->matrix),
+				    &pmatrix->state);
 }
 
 static TEE_Result matrix_pm(enum pm_op op, uint32_t pm_hint __unused,
diff --git a/core/arch/arm/plat-sam/matrix.h b/core/arch/arm/plat-sam/matrix.h
index 216905720dcd6156455126e19b698ee53b8174d9..eefe2d1828a7dd1ffdb840b7aaabffa4e5566b70 100644
--- a/core/arch/arm/plat-sam/matrix.h
+++ b/core/arch/arm/plat-sam/matrix.h
@@ -29,22 +29,58 @@
 #ifndef MATRIX_H
 #define MATRIX_H
 
+#include <mm/core_memprot.h>
+#include <stdint.h>
 #include <tee_api_types.h>
 
-extern void matrix_write_protect_enable(unsigned int matrix_base);
-extern void matrix_write_protect_disable(unsigned int matrix_base);
-extern void matrix_configure_slave_security(unsigned int matrix_base,
-				unsigned int slave,
-				unsigned int srtop_setting,
-				unsigned int srsplit_setting,
-				unsigned int ssr_setting);
+#define SECURITY_TYPE_AS	1
+#define SECURITY_TYPE_NS	2
+#define SECURITY_TYPE_PS	3
+
+#define MATRIX_SPSELR_COUNT	3
+#define MATRIX_SLAVE_COUNT	15
+
+#ifdef CFG_PM_ARM32
+struct matrix_state {
+	uint32_t spselr[MATRIX_SPSELR_COUNT];
+	uint32_t ssr[MATRIX_SLAVE_COUNT];
+	uint32_t srtsr[MATRIX_SLAVE_COUNT];
+	uint32_t sassr[MATRIX_SLAVE_COUNT];
+	uint32_t meier;
+	uint32_t meimr;
+};
+#endif
+
+struct matrix {
+	unsigned int matrix;
+	struct io_pa_va p;
+#ifdef CFG_PM_ARM32
+	struct matrix_state state;
+#endif
+};
+
+struct peri_security {
+	unsigned int peri_id;
+	unsigned int matrix;
+	unsigned int security_type;
+	paddr_t addr;
+};
+
+struct peri_security *peri_security_get(unsigned int idx);
+struct matrix *matrix_get(unsigned int idx);
+vaddr_t matrix_base(unsigned int matrix);
+
+void matrix_write_protect_enable(unsigned int matrix_base);
+void matrix_write_protect_disable(unsigned int matrix_base);
+void matrix_configure_slave_security(unsigned int matrix_base,
+				     unsigned int slave,
+				     unsigned int srtop_setting,
+				     unsigned int srsplit_setting,
+				     unsigned int ssr_setting);
 
 int matrix_configure_periph_non_secure(unsigned int *peri_id_array,
 				       unsigned int size);
 int matrix_configure_periph_secure(unsigned int peri_id);
 TEE_Result matrix_dt_get_id(const void *fdt, int node, unsigned int *id);
 
-vaddr_t matrix32_base(void);
-vaddr_t matrix64_base(void);
-
 #endif /* #ifndef MATRIX_H */
diff --git a/core/arch/arm/plat-sam/platform_config.h b/core/arch/arm/plat-sam/platform_config.h
index 9742c6115653b4968ea191fb1e77b94a3ca995c1..d7f1f5bda811954521a28a5d91ffa95b5bd6578f 100644
--- a/core/arch/arm/plat-sam/platform_config.h
+++ b/core/arch/arm/plat-sam/platform_config.h
@@ -30,7 +30,11 @@
 #define PLATFORM_CONFIG_H
 
 #include <mm/generic_ram_layout.h>
+#if defined(PLATFORM_FLAVOR_sama7g54_ek)
+#include <sama7g5.h>
+#else
 #include <sama5d2.h>
+#endif
 
 #define STACK_ALIGNMENT       64
 
@@ -41,6 +45,23 @@
 #error "LPAE not supported"
 #endif
 
+#if defined(PLATFORM_FLAVOR_sama7g54_ek)
+#define CONSOLE_UART_BASE   (FLEXCOM3_BASE_ADDRESS + 0x200)
+#define SFR_BASE            SFR_BASE_ADDRESS
+#define AT91C_BASE_TC0      TC0_BASE_ADDRESS
+#define AT91C_ID_TC0        ID_TC0_CHANNEL0
+#define AT91C_ID_TC1        ID_TC1_CHANNEL0
+#define AT91C_ID_SYS        ID_RSTC
+#define AT91C_ID_PIOA       ID_PIOA
+#define AT91C_ID_PIOB       ID_PIOB
+#define AT91C_ID_PIOC       ID_PIOC
+#define AT91C_ID_PIOD       ID_PIOD
+#define AT91C_ID_WDT        ID_DWDT_SW
+#define AT91C_ID_TRNG       ID_TRNG
+#define AT91C_ID_SECUMOD    ID_SECUMOD
+#define AT91C_ID_SFR        ID_SFR
+#define AT91C_ID_SFRBU      ID_SFRBU
+#else
 #if defined(PLATFORM_FLAVOR_sama5d27_wlsom1_ek)
 #define CONSOLE_UART_BASE     AT91C_BASE_UART0
 #else
@@ -49,6 +70,7 @@
 
 #define PL310_BASE          (AT91C_BASE_L2CC)
 #define SFR_BASE            (AT91C_BASE_SFR)
+#endif
 
 /*
  * PL310 Auxiliary Control Register
diff --git a/core/arch/arm/plat-sam/sama7g5.h b/core/arch/arm/plat-sam/sama7g5.h
new file mode 100644
index 0000000000000000000000000000000000000000..46f6bd28b631b0299f9dff7568738f2049d428bd
--- /dev/null
+++ b/core/arch/arm/plat-sam/sama7g5.h
@@ -0,0 +1,338 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Header file for ATSAMA7G54
+ *
+ * Copyright (c) 2023 Microchip Technology Inc. and its subsidiaries.
+ */
+
+#ifndef _SAMA7G54_H_
+#define _SAMA7G54_H_
+
+/*
+ * SAMA7G54 definitions
+ * This file defines all structures and symbols for SAMA7G54:
+ *   - registers and bitfields
+ *   - peripheral base address
+ *   - peripheral ID
+ *   - PIO definitions
+ */
+
+#define GIC_DISTRIBUTOR_BASE 0xE8C11000 /* Base for GIC distributor interface */
+#define GIC_INTERFACE_BASE   0xE8C12000 /* Base address for GIC CPU interface */
+#define GICC_SIZE            0x1000
+#define GICD_SIZE            0x1000
+
+/* ************************************************************************** */
+/*  PERIPHERAL ID DEFINITIONS FOR SAMA7G54                                    */
+/* ************************************************************************** */
+#define ID_DWDT_SW         0 /* Dual Watchdog Timer, Secure World (DWDT_SW) */
+#define ID_DWDT_NSW        1 /* DWDT Non Secure World, interrupt (DWDT_NSW) */
+#define ID_DWDT_NSW_ALARM  2 /* DWDT Non Secure World Alarm, interrupt */
+#define ID_SCKC            4 /* Slow Clock Controller (SCKC) */
+#define ID_SHDWC           5 /* SHutDoWn Controller (SHDWC) */
+#define ID_RSTC            6 /* Reset Controller (RSTC) */
+#define ID_RTC             7 /* Real-Time Clock (RTC) */
+#define ID_RTT             8 /* Real-Time Timer (RTT) */
+#define ID_CHIPID          9 /* Chip Identifier (CHIPID) */
+#define ID_PMC            10 /* Power Management Controller (PMC) */
+#define ID_PIOA           11 /* For PIO 0 to 31 (PIOA) */
+#define ID_PIOB           12 /* For PIO 32 to 63, interrupt (PIOB) */
+#define ID_PIOC           13 /* For PIO 64 to 95, interrupt (PIOC) */
+#define ID_PIOD           14 /* For PIO 96 to 127, interrupt (PIOD) */
+#define ID_PIOE           15 /* For PIO 128 to 136, interrupt (PIOE) */
+#define ID_SECUMOD        17 /* Security Module (SECUMOD) */
+#define ID_SECURAM        18 /* Secret RAM (SECURAM) */
+#define ID_SFR            19 /* Special Function Register (SFR) */
+#define ID_SFRBU          20 /* Special Function Register in BackUp zone */
+#define ID_HSMC           21 /* Static Memory Controller - NAND (HSMC) */
+#define ID_XDMAC0         22 /* DMA 0, mem to periph, 32 Channels (XDMAC0) */
+#define ID_XDMAC1         23 /* DMA 1, mem to periph, 32 Channels (XDMAC1) */
+#define ID_XDMAC2         24 /* DMA 2, mem to mem, 4 Channels (XDMAC2) */
+#define ID_ACC            25 /* Analog Comparator Controller (ACC) */
+#define ID_ADC            26 /* Analog-to-Digital Converter (ADC) */
+#define ID_AES            27 /* Advanced Encryption Standard (AES) */
+#define ID_TZAESBASC      28 /* TZ AES Bridge - Address Space Controlller */
+#define ID_ASRC           30 /* Asynchronous Sample Rate Converter (ASRC) */
+#define ID_CPKCC          32 /* Classic Public Key Cryptography Controller */
+#define ID_CSI            33 /* CSI 2 between ISC and MIPI PHY (CSI) */
+#define ID_CSI2DC         34 /* CSI to Demultiplexer Controller (CSI2DC) */
+#define ID_DDRPUBL        35 /* DDR SDRAM PHY Utility Block "Lite" aka PUBL */
+#define ID_DDRUMCTL       36 /* Universal DDR-SDRAM Memory Controller */
+#define ID_EIC            37 /* External  Interrupt Controller (EIC) */
+#define ID_FLEXCOM0       38 /* Flexcom 0 (FLEXCOM0) */
+#define ID_FLEXCOM1       39 /* Flexcom 1 (FLEXCOM1) */
+#define ID_FLEXCOM2       40 /* Flexcom 2 (FLEXCOM2) */
+#define ID_FLEXCOM3       41 /* Flexcom 3 (FLEXCOM3) */
+#define ID_FLEXCOM4       42 /* Flexcom 4 (FLEXCOM4) */
+#define ID_FLEXCOM5       43 /* Flexcom 5 (FLEXCOM5) */
+#define ID_FLEXCOM6       44 /* Flexcom 6 (FLEXCOM6) */
+#define ID_FLEXCOM7       45 /* Flexcom 7 (FLEXCOM7) */
+#define ID_FLEXCOM8       46 /* Flexcom 8 (FLEXCOM8) */
+#define ID_FLEXCOM9       47 /* Flexcom 9 (FLEXCOM9) */
+#define ID_FLEXCOM10      48 /* Flexcom 10 (FLEXCOM10) */
+#define ID_FLEXCOM11      49 /* Flexcom 11 (FLEXCOM11) */
+#define ID_GMAC0          51 /* Gigabit Ethernet MAC (GMAC0) */
+#define ID_GMAC1          52 /* Ethernet MAC (GMAC1) */
+#define ID_GMAC0_TSU      53 /* GMAC - TSU Generic Clock - No Interrupt */
+#define ID_GMAC1_TSU      54 /* EMAC - TSU Generic Clock - No Interrupt */
+#define ID_ICM            55 /* Integrity Check Monitor (ICM) */
+#define ID_ISC            56 /* Camera Interface (ISC) */
+#define ID_I2SMCC0        57 /* Inter-IC Sound Controller 0 (I2SMCC0) */
+#define ID_I2SMCC1        58 /* Inter-IC Sound Controller 1 (I2SMCC1) */
+#define ID_MATRIX         60 /* HSS AHB Matrix (MATRIX) */
+#define ID_MCAN0          61 /* Master CAN 0 (MCAN0) */
+#define ID_MCAN1          62 /* Master CAN 1 (MCAN1) */
+#define ID_MCAN2          63 /* Master CAN 2 (MCAN2) */
+#define ID_MCAN3          64 /* Master CAN 3 (MCAN3) */
+#define ID_MCAN4          65 /* Master CAN 4 (MCAN4) */
+#define ID_MCAN5          66 /* Master CAN 5 (MCAN5) */
+#define ID_OTPC           67 /* One Time Programmable memory Controller */
+#define ID_PDMC0          68 /* Pulse Density Modulation Controller 0 */
+#define ID_PDMC1          69 /* Pulse Density Modulation Controller 1 */
+#define ID_PIT64B0        70 /* 64-bit Periodic Interval Timer 0 (PIT64B0) */
+#define ID_PIT64B1        71 /* 64-bit Periodic Interval Timer 1 (PIT64B1) */
+#define ID_PIT64B2        72 /* 64-bit Periodic Interval Timer 2 (PIT64B2) */
+#define ID_PIT64B3        73 /* 64-bit Periodic Interval Timer 3 (PIT64B3) */
+#define ID_PIT64B4        74 /* 64-bit Periodic Interval Timer 4 (PIT64B4) */
+#define ID_PIT64B5        75 /* 64-bit Periodic Interval Timer 5 (PIT64B5) */
+#define ID_PWM            77 /* Pulse Width Modulation (PWM) */
+#define ID_QSPI0          78 /* Quad IO Serial Peripheral Interface 0 */
+#define ID_QSPI1          79 /* Quad IO Serial Peripheral Interface 1 */
+#define ID_SDMMC0         80 /* Ultra HS SD Host controller 0 (eMMC 5.1) */
+#define ID_SDMMC1         81 /* Ultra HS SD Host controller 1 (eMMC 4.51) */
+#define ID_SDMMC2         82 /* Ultra HS SD Host controller 2 (eMMC 4.51) */
+#define ID_SHA            83 /* Secure Hash Algorithm (SHA) */
+#define ID_SPDIFRX        84 /* Sony Philips Digital Interface RX (SPDIFRX) */
+#define ID_SPDIFTX        85 /* Sony Philips Digital Interface TX (SPDIFTX) */
+#define ID_SSC0           86 /* Synchronous Serial Interface 0 (SSC0) */
+#define ID_SSC1           87 /* Synchronous Serial Interface 1 (SSC1) */
+#define ID_TC0_CHANNEL0   88 /* 32-bit Timer Counter 0 Channel 0 */
+#define ID_TC0_CHANNEL1   89 /* 32-bit Timer Counter 0 Channel 1 interrupt */
+#define ID_TC0_CHANNEL2   90 /* 32-bit Timer Counter 0 Channel 2 interrupt */
+#define ID_TC1_CHANNEL0   91 /* 32-bit Timer Counter 1 Channel 0 */
+#define ID_TC1_CHANNEL1   92 /* 32-bit Timer Counter 1 Channel 1 interrupt */
+#define ID_TC1_CHANNEL2   93 /* 32-bit Timer Counter 1 Channel 2 interrupt */
+#define ID_TCPCA          94 /* USB Type-C Port Controller A (TCPCA) */
+#define ID_TCPCB          95 /* USB Type-C Port Controller B (TCPCB) */
+#define ID_TDES           96 /* Triple Data Encryption System (TDES) */
+#define ID_TRNG           97 /* True Random Number Generator (TRNG) */
+#define ID_TZAESB_NS      98 /* TZAESB Non-Secure (Clocks & Interrupt) */
+#define ID_TZAESB_NS_SINT 99 /* TZAESB Non-Secure (Interrupt only) */
+#define ID_TZAESB_S      100 /* TZAESB Secure */
+#define ID_TZAESB_S_SINT 101 /* TZAESB Secure (Interrupt only) */
+#define ID_TZC           102 /* TrustZone Address Space Controller (TZC400) */
+#define ID_TZPM          103 /* TrustZone Peripheral Manager (TZPM) */
+#define ID_UDPHSA        104 /* USB Device High Speed A (UDPHSA) */
+#define ID_UDPHSB        105 /* USB Device High Speed B (UDPHSB) */
+#define ID_UHPHS         106 /* USB Host Controller High Speed (UHPHS) */
+#define ID_XDMAC0_SINT   112 /* DMA 0, mem to periph, 32 CH, Secure INT */
+#define ID_XDMAC1_SINT   113 /* DMA 1, mem to periph, 32 CH, Secure INT */
+#define ID_XDMAC2_SINT   114 /* DMA 2, mem to mem, 4 Channels, Secure INT */
+#define ID_AES_SINT      115 /* Advanced Encryption Standard, Secure INT */
+#define ID_GMAC0_Q1      116 /* GMAC0 Queue 1 */
+#define ID_GMAC0_Q2      117 /* GMAC0 Queue 2 */
+#define ID_GMAC0_Q3      118 /* GMAC0 Queue 3 */
+#define ID_GMAC0_Q4      119 /* GMAC0 Queue 4 */
+#define ID_GMAC0_Q5      120 /* GMAC0 Queue 5 */
+#define ID_GMAC1_Q1      121 /* GMAC1 Queue 1 */
+#define ID_ICM_SINT      122 /* Integrity Check Monitor, Secure INTerrupt */
+#define ID_MCAN0_INT1    123 /* MCAN0 interrupt1 (MCAN0_INT1) */
+#define ID_MCAN1_INT1    124 /* MCAN1 interrupt1 (MCAN1_INT1) */
+#define ID_MCAN2_INT1    125 /* MCAN2 interrupt1 (MCAN2_INT1) */
+#define ID_MCAN3_INT1    126 /* MCAN3 interrupt1 (MCAN3_INT1) */
+#define ID_MCAN4_INT1    127 /* MCAN4 interrupt1 (MCAN4_INT1) */
+#define ID_MCAN5_INT1    128 /* MCAN5 interrupt1 (MCAN5_INT1) */
+#define ID_PIOA_SINT     129 /* For PIO 0 to 31, Secure INTerrupt */
+#define ID_PIOB_SINT     130 /* For PIO 32 to 63, Secure INTerrupt */
+#define ID_PIOC_SINT     131 /* For PIO 64 to 95, Secure INTerrupt */
+#define ID_PIOD_SINT     132 /* For PIO 96 to 127, Secure INTerrupt */
+#define ID_PIOE_SINT     133 /* For PIO 128 to 136, Secure INTerrupt */
+#define ID_PIT64B0_SINT  135 /* 64-bit PIT 0, Secure INTerrupt */
+#define ID_PIT64B1_SINT  136 /* 64-bit PIT 1, Secure INTerrupt */
+#define ID_PIT64B2_SINT  137 /* 64-bit PIT 2, Secure INTerrupt */
+#define ID_PIT64B3_SINT  138 /* 64-bit PIT 3, Secure INTerrupt */
+#define ID_PIT64B4_SINT  139 /* 64-bit PIT 4, Secure INTerrupt */
+#define ID_PIT64B5_SINT  140 /* 64-bit PIT 5, Secure INTerrupt */
+#define ID_SDMMC0_TIMER  141 /* SD Host controller 0 (eMMC 5.1) Timer int */
+#define ID_SDMMC1_TIMER  142 /* SD Host controller 1 (eMMC 4.51) Timer int */
+#define ID_SDMMC2_TIMER  143 /* SD Host controller 2 (eMMC 4.51) Timer int */
+#define ID_SHA_SINT      144 /* Secure Hash Algorithm, Secure INTerrupt */
+#define ID_TC0_SINT0     145 /* 32-bit TC 0 Channel 0, Secure INTerrupt */
+#define ID_TC0_SINT1     146 /* 32-bit TC 0 Channel 1, Secure INTerrupt */
+#define ID_TC0_SINT2     147 /* 32-bit TC 0 Channel 2 (TC0_SINT2) */
+#define ID_TC1_SINT0     148 /* 32-bit TC 1 Channel 0, Secure INTerrupt */
+#define ID_TC1_SINT1     149 /* 32-bit TC 1 Channel 1, Secure INTerrupt */
+#define ID_TC1_SINT2     150 /* 32-bit TC 1 Channel 2, Secure INTerrupt */
+#define ID_TDES_SINT     151 /* Triple Data Encryption System, Secure INT */
+#define ID_TRNG_SINT     152 /* True Random Number Generator, Secure INT */
+#define ID_EXT_IRQ0      153 /* External  Interrupt ID0 (FIQ) (EXT_IRQ0) */
+#define ID_EXT_IRQ1      154 /* External  Interrupt ID1 (IRQ) (EXT_IRQ1) */
+
+#define ID_PERIPH_MAX    154 /* Number of peripheral IDs */
+
+/* ************************************************************************** */
+/*   BASE ADDRESS DEFINITIONS FOR SAMA7G54                                    */
+/* ************************************************************************** */
+#define ACC_BASE_ADDRESS                 0xe1600000
+#define ADC_BASE_ADDRESS                 0xe1000000
+#define AES_BASE_ADDRESS                 0xe1810000
+#define ASRC_BASE_ADDRESS                0xe1610000
+#define BSC_BASE_ADDRESS                 0xe001d054
+#define CHIPID_BASE_ADDRESS              0xe0020000
+#define CSI_BASE_ADDRESS                 0xe1400000
+#define CPKCC_BASE_ADDRESS               0xe000c000
+#define CSI2DC_BASE_ADDRESS              0xe1404000
+#define DDRPUBL_BASE_ADDRESS             0xe3804000
+#define DWDT_BASE_ADDRESS                0xe001c000
+#define EIC_BASE_ADDRESS                 0xe1628000
+#define FLEXCOM0_BASE_ADDRESS            0xe1818000
+#define FLEXCOM1_BASE_ADDRESS            0xe181c000
+#define FLEXCOM2_BASE_ADDRESS            0xe1820000
+#define FLEXCOM3_BASE_ADDRESS            0xe1824000
+#define FLEXCOM4_BASE_ADDRESS            0xe2018000
+#define FLEXCOM5_BASE_ADDRESS            0xe201c000
+#define FLEXCOM6_BASE_ADDRESS            0xe2020000
+#define FLEXCOM7_BASE_ADDRESS            0xe2024000
+#define FLEXCOM8_BASE_ADDRESS            0xe2818000
+#define FLEXCOM9_BASE_ADDRESS            0xe281c000
+#define FLEXCOM10_BASE_ADDRESS           0xe2820000
+#define FLEXCOM11_BASE_ADDRESS           0xe2824000
+#define GMAC0_BASE_ADDRESS               0xe2800000
+#define GMAC1_BASE_ADDRESS               0xe2804000
+#define GPBR_BASE_ADDRESS                0xe001d060
+#define I2SMCC0_BASE_ADDRESS             0xe161c000
+#define I2SMCC1_BASE_ADDRESS             0xe1620000
+#define ICM_BASE_ADDRESS                 0xe081c000
+#define ISC_BASE_ADDRESS                 0xe1408000
+#define MATRIX_BASE_ADDRESS              0xe0804000
+#define MCAN0_BASE_ADDRESS               0xe0828000
+#define MCAN1_BASE_ADDRESS               0xe082c000
+#define MCAN2_BASE_ADDRESS               0xe0830000
+#define MCAN3_BASE_ADDRESS               0xe0834000
+#define MCAN4_BASE_ADDRESS               0xe0838000
+#define MCAN5_BASE_ADDRESS               0xe083c000
+#define NICGPV_BASE_ADDRESS              0xe8b00000
+#define OTPC_BASE_ADDRESS                0xe8c00000
+#define PDMC0_BASE_ADDRESS               0xe1608000
+#define PDMC1_BASE_ADDRESS               0xe160c000
+#define PIO_BASE_ADDRESS                 0xe0014000
+#define PIT64B0_BASE_ADDRESS             0xe1800000
+#define PIT64B1_BASE_ADDRESS             0xe1804000
+#define PIT64B2_BASE_ADDRESS             0xe1808000
+#define PIT64B3_BASE_ADDRESS             0xe2004000
+#define PIT64B4_BASE_ADDRESS             0xe2008000
+#define PIT64B5_BASE_ADDRESS             0xe2810000
+#define PMC_BASE_ADDRESS                 0xe0018000
+#define PWM_BASE_ADDRESS                 0xe1604000
+#define QSPI0_BASE_ADDRESS               0xe080c000
+#define QSPI1_BASE_ADDRESS               0xe0810000
+#define RSTC_BASE_ADDRESS                0xe001d000
+#define RTC_BASE_ADDRESS                 0xe001d0a8
+#define RTT_BASE_ADDRESS                 0xe001d020
+#define SCKC_BASE_ADDRESS                0xe001d050
+#define SDMMC0_BASE_ADDRESS              0xe1204000
+#define SDMMC1_BASE_ADDRESS              0xe1208000
+#define SDMMC2_BASE_ADDRESS              0xe120c000
+#define SECUMOD_BASE_ADDRESS             0xe0004000
+#define SFR_BASE_ADDRESS                 0xe1624000
+#define SFRBU_BASE_ADDRESS               0xe0008000
+#define SHA_BASE_ADDRESS                 0xe1814000
+#define SHDWC_BASE_ADDRESS               0xe001d010
+#define HSMC_BASE_ADDRESS                0xe0808000
+#define SPDIFRX_BASE_ADDRESS             0xe1614000
+#define SPDIFTX_BASE_ADDRESS             0xe1618000
+#define SSC0_BASE_ADDRESS                0xe180c000
+#define SSC1_BASE_ADDRESS                0xe200c000
+#define SYSCWP_BASE_ADDRESS              0xe001d0dc
+#define TC0_BASE_ADDRESS                 0xe2814000
+#define TC1_BASE_ADDRESS                 0xe0800000
+#define TCPCA_BASE_ADDRESS               0xe0840000
+#define TCPCB_BASE_ADDRESS               0xe0844000
+#define TDES_BASE_ADDRESS                0xe2014000
+#define TRNG_BASE_ADDRESS                0xe2010000
+#define TZAESBNS_BASE_ADDRESS            0xe0820000
+#define TZAESBS_BASE_ADDRESS             0xe0824000
+#define TZAESBASC_BASE_ADDRESS           0xe2000000
+#define TZC_BASE_ADDRESS                 0xe3000000
+#define TZPM_BASE_ADDRESS                0xe0010000
+#define DDRUMCTL_BASE_ADDRESS            0xe3800000
+#define UDPHSA_BASE_ADDRESS              0xe0814000
+#define UDPHSB_BASE_ADDRESS              0xe0818000
+#define UHPHS_OHCI_BASE_ADDRESS          0x00400000
+#define UHPHS_EHCI_BASE_ADDRESS          0x00500000
+#define XDMAC0_BASE_ADDRESS              0xe2808000
+#define XDMAC1_BASE_ADDRESS              0xe280c000
+#define XDMAC2_BASE_ADDRESS              0xe1200000
+
+/* ************************************************************************** */
+/*   MEMORY MAPPING DEFINITIONS FOR SAMA7G54                                  */
+/* ************************************************************************** */
+#define IROM_SIZE                      0x00014000
+#define ECC_ROM_SIZE                   0x00018000
+#define CPKCC_ROM_SIZE                 0x00010000
+#define CPKCC_RAM_SIZE                 0x00001000
+#define IRAM_SIZE                      0x00020000
+#define UDPHS_RAMA_SIZE                0x00100000
+#define UDPHS_RAMB_SIZE                0x00100000
+#define UHPHS_OHCI_SIZE                0x00001000
+#define UHPHS_EHCI_SIZE                0x00100000
+#define NFC_RAM_SIZE                   0x00003000
+#define NFC_SIZE                       0x08000000
+#define QSPIMEM0_SIZE                  0x10000000
+#define QSPIMEM1_SIZE                  0x10000000
+#define EBI_CS0_SIZE                   0x08000000
+#define EBI_CS1_SIZE                   0x08000000
+#define EBI_CS2_SIZE                   0x08000000
+#define EBI_CS3_SIZE                   0x08000000
+#define DDR_CS_SIZE                    0x80000000
+#define SECURAM_SIZE                   0x00004000
+#define SDMMC0_SIZE                    0x00004000
+#define SDMMC1_SIZE                    0x00004000
+#define SDMMC2_SIZE                    0x00004000
+#define APB_DBG_S_SIZE                 0x00060000
+#define APB_DBG_SIZE                   0x00001000
+#define NICGPV_SIZE                    0x00100000
+#define OTPC_SIZE                      0x00001000
+#define CSI2DC_META_SIZE               0x00002000
+#define ARM_PERIPH_SIZE                0x00008000
+#define PERIPHERALS_SIZE               0x10000000
+
+#define IROM_ADDR                      0x00000000
+#define ECC_ROM_ADDR                   0x00020000
+#define CPKCC_ROM_ADDR                 0x00040000
+#define CPKCC_RAM_ADDR                 0x00051000
+#define IRAM_ADDR                      0x00100000
+#define UDPHS_RAMA_ADDR                0x00200000
+#define UDPHS_RAMB_ADDR                0x00300000
+#define UHPHS_OHCI_ADDR                0x00400000
+#define UHPHS_EHCI_ADDR                0x00500000
+#define NFC_RAM_ADDR                   0x00600000
+#define NFC_ADDR                       0x10000000
+#define QSPIMEM0_ADDR                  0x20000000
+#define QSPIMEM1_ADDR                  0x30000000
+#define EBI_CS0_ADDR                   0x40000000
+#define EBI_CS1_ADDR                   0x48000000
+#define EBI_CS2_ADDR                   0x50000000
+#define EBI_CS3_ADDR                   0x58000000
+#define DDR_CS_ADDR                    0x60000000
+#define SECURAM_ADDR                   0xe0000000
+#define SDMMC0_ADDR                    0xe1204000
+#define SDMMC1_ADDR                    0xe1208000
+#define SDMMC2_ADDR                    0xe120c000
+#define APB_DBG_S_ADDR                 0xe8800000
+#define APB_DBG_ADDR                   0xe8900000
+#define NICGPV_ADDR                    0xe8b00000
+#define OTPC_ADDR                      0xe8c00000
+#define CSI2DC_META_ADDR               0xe8c02000
+#define ARM_PERIPH_ADDR                0xe8c10000
+#define PERIPHERALS_ADDR               0xe0000000
+
+/* ************************************************************************** */
+/*   DEVICE SIGNATURES FOR SAMA7G54                                           */
+/* ************************************************************************** */
+#define CHIP_JTAGID                    0X05B4203F
+#define CHIP_CIDR                      0X80162110
+#define CHIP_EXID                      0X00000000
+
+#endif /* _SAMA7G54_H_ */
+
diff --git a/core/arch/arm/plat-stm/main.c b/core/arch/arm/plat-stm/main.c
index c2bc86897cac74b44c983412707dca98b040a1f1..f0657cb83080ead1cb4dc294b54ab5776a7f615b 100644
--- a/core/arch/arm/plat-stm/main.c
+++ b/core/arch/arm/plat-stm/main.c
@@ -139,5 +139,5 @@ void boot_primary_init_intc(void)
 
 void boot_secondary_init_intc(void)
 {
-	gic_cpu_init();
+	gic_init_per_cpu();
 }
diff --git a/core/arch/arm/plat-stm32mp1/conf.mk b/core/arch/arm/plat-stm32mp1/conf.mk
index 058199a489c6af644d959ae11eb20c3c3bae76ef..a629c0803b298e79b099b6fd523f45c39bf47b5f 100644
--- a/core/arch/arm/plat-stm32mp1/conf.mk
+++ b/core/arch/arm/plat-stm32mp1/conf.mk
@@ -5,17 +5,25 @@ flavor_dts_file-157C_DHCOM_PDK2 = stm32mp157c-dhcom-pdk2.dts
 flavor_dts_file-157C_DK2 = stm32mp157c-dk2.dts
 flavor_dts_file-157C_ED1 = stm32mp157c-ed1.dts
 flavor_dts_file-157C_EV1 = stm32mp157c-ev1.dts
+flavor_dts_file-157A_DK1_SCMI = stm32mp157a-dk1-scmi.dts
+flavor_dts_file-157C_DK2_SCMI = stm32mp157c-dk2-scmi.dts
+flavor_dts_file-157C_ED1_SCMI = stm32mp157c-ed1-scmi.dts
+flavor_dts_file-157C_EV1_SCMI = stm32mp157c-ev1-scmi.dts
 
 flavor_dts_file-135F_DK = stm32mp135f-dk.dts
 
 flavorlist-cryp-512M = $(flavor_dts_file-157C_DK2) \
+		       $(flavor_dts_file-157C_DK2_SCMI) \
 		       $(flavor_dts_file-135F_DK)
 
-flavorlist-no_cryp-512M = $(flavor_dts_file-157A_DK1)
+flavorlist-no_cryp-512M = $(flavor_dts_file-157A_DK1) \
+			  $(flavor_dts_file-157A_DK1_SCMI)
 
 flavorlist-cryp-1G = $(flavor_dts_file-157C_DHCOM_PDK2) \
 		     $(flavor_dts_file-157C_ED1) \
-		     $(flavor_dts_file-157C_EV1)
+		     $(flavor_dts_file-157C_EV1) \
+		     $(flavor_dts_file-157C_ED1_SCMI) \
+		     $(flavor_dts_file-157C_EV1_SCMI)
 
 flavorlist-no_cryp-1G = $(flavor_dts_file-157A_DHCOR_AVENGER96)
 
@@ -31,14 +39,22 @@ flavorlist-1G = $(flavorlist-cryp-1G) \
 flavorlist-MP15-HUK-DT = $(flavor_dts_file-157A_DK1) \
 			 $(flavor_dts_file-157C_DK2) \
 			 $(flavor_dts_file-157C_ED1) \
-			 $(flavor_dts_file-157C_EV1)
+			 $(flavor_dts_file-157C_EV1) \
+			 $(flavor_dts_file-157A_DK1_SCMI) \
+			 $(flavor_dts_file-157C_DK2_SCMI) \
+			 $(flavor_dts_file-157C_ED1_SCMI) \
+			 $(flavor_dts_file-157C_EV1_SCMI)
 
 flavorlist-MP15 = $(flavor_dts_file-157A_DHCOR_AVENGER96) \
 		  $(flavor_dts_file-157A_DK1) \
 		  $(flavor_dts_file-157C_DHCOM_PDK2) \
 		  $(flavor_dts_file-157C_DK2) \
 		  $(flavor_dts_file-157C_ED1) \
-		  $(flavor_dts_file-157C_EV1)
+		  $(flavor_dts_file-157C_EV1) \
+		  $(flavor_dts_file-157A_DK1_SCMI) \
+		  $(flavor_dts_file-157C_DK2_SCMI) \
+		  $(flavor_dts_file-157C_ED1_SCMI) \
+		  $(flavor_dts_file-157C_EV1_SCMI)
 
 flavorlist-MP13 = $(flavor_dts_file-135F_DK)
 
@@ -99,13 +115,15 @@ $(call force,CFG_DRIVERS_REGULATOR,y)
 $(call force,CFG_GIC,y)
 $(call force,CFG_INIT_CNTVOFF,y)
 $(call force,CFG_PSCI_ARM32,y)
+$(call force,CFG_REGULATOR_FIXED,y)
 $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y)
 $(call force,CFG_SM_PLATFORM_HANDLER,y)
 $(call force,CFG_STM32_SHARED_IO,y)
-$(call force,CFG_REGULATOR_FIXED,y)
 
 ifeq ($(CFG_STM32MP13),y)
 $(call force,CFG_BOOT_SECONDARY_REQUEST,n)
+$(call force,CFG_CORE_ASYNC_NOTIF,y)
+$(call force,CFG_CORE_ASYNC_NOTIF_GIC_INTID,31)
 $(call force,CFG_CORE_RESERVED_SHM,n)
 $(call force,CFG_DRIVERS_CLK_FIXED,y)
 $(call force,CFG_SECONDARY_INIT_CNTFRQ,n)
@@ -114,22 +132,24 @@ $(call force,CFG_STM32_VREFBUF,y)
 $(call force,CFG_STM32MP_CLK_CORE,y)
 $(call force,CFG_STM32MP1_SHARED_RESOURCES,n)
 $(call force,CFG_STM32MP13_CLK,y)
+$(call force,CFG_STM32MP13_REGULATOR_IOD,y)
 $(call force,CFG_TEE_CORE_NB_CORE,1)
 $(call force,CFG_WITH_NSEC_GPIOS,n)
 CFG_EXTERNAL_DT ?= n
 CFG_STM32MP_OPP_COUNT ?= 2
-CFG_STM32MP1_SCMI_SHM_SYSRAM ?= y
 CFG_WITH_PAGER ?= n
 endif # CFG_STM32MP13
 
 ifeq ($(CFG_STM32MP15),y)
 $(call force,CFG_BOOT_SECONDARY_REQUEST,y)
 $(call force,CFG_DRIVERS_CLK_FIXED,n)
+$(call force,CFG_HALT_CORES_ON_PANIC_SGI,15)
 $(call force,CFG_SECONDARY_INIT_CNTFRQ,y)
 $(call force,CFG_STM32MP1_SHARED_RESOURCES,y)
 $(call force,CFG_STM32_SAES,n)
 $(call force,CFG_STM32MP15_CLK,y)
-CFG_CORE_RESERVED_SHM ?= y
+CFG_CORE_RESERVED_SHM ?= n
+CFG_HALT_CORES_ON_PANIC ?= y
 CFG_EXTERNAL_DT ?= y
 CFG_STM32_BSEC_SIP ?= y
 CFG_TEE_CORE_NB_CORE ?= 2
@@ -145,6 +165,16 @@ CFG_MMAP_REGIONS ?= 23
 CFG_DTB_MAX_SIZE ?= (256 * 1024)
 CFG_CORE_ASLR ?= n
 
+CFG_STM32MP_REMOTEPROC ?= n
+CFG_DRIVERS_REMOTEPROC ?= $(CFG_STM32MP_REMOTEPROC)
+CFG_REMOTEPROC_PTA ?= $(CFG_STM32MP_REMOTEPROC)
+ifeq ($(CFG_REMOTEPROC_PTA),y)
+# Remoteproc early TA for coprocessor firmware management in boot stages
+CFG_IN_TREE_EARLY_TAS += remoteproc/80a4c275-0a47-4905-8285-1486a9771a08
+# Embed public part of this key in OP-TEE OS
+RPROC_SIGN_KEY ?= keys/default.pem
+endif
+
 ifneq ($(CFG_WITH_LPAE),y)
 # Without LPAE, default TEE virtual address range is 1MB, we need at least 2MB.
 CFG_TEE_RAM_VA_SIZE ?= 0x00200000
@@ -207,6 +237,7 @@ CFG_STPMIC1 ?= y
 CFG_TZC400 ?= y
 
 CFG_DRIVERS_I2C ?= $(CFG_STM32_I2C)
+CFG_REGULATOR_GPIO ?= $(CFG_STM32_GPIO)
 
 CFG_WITH_SOFTWARE_PRNG ?= n
 ifneq ($(CFG_WITH_SOFTWARE_PRNG),y)
@@ -227,6 +258,8 @@ CFG_DRIVERS_RSTCTRL ?= $(CFG_STM32_RSTCTRL)
 $(eval $(call cfg-depends-all,CFG_STM32_RSTCTRL,CFG_DRIVERS_RSTCTRL))
 
 CFG_WDT ?= $(CFG_STM32_IWDG)
+CFG_WDT_SM_HANDLER ?= $(CFG_WDT)
+CFG_WDT_SM_HANDLER_ID ?= 0xbc000000
 
 # Platform specific configuration
 CFG_STM32MP_PANIC_ON_TZC_PERM_VIOLATION ?= y
diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c
index 893e5dcfa632f6cf6f828b8c1f0930a75b0c1d9a..42735b8985e54c341f10af00f8c9ae3076d63b3d 100644
--- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c
+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c
@@ -47,12 +47,14 @@ static_assert(PMIC_REGU_FLAG_COUNT <= UINT_MAX);
  * struct pmic_regulator_data - Platform specific data
  * @flags: Flags for platform property to apply
  * @regu_name: Regulator name ID in stpmic1 driver
- * @supported_voltages: Supported levels description or NULL is not yet built
+ * @voltages_desc: Supported levels description
+ * @voltages_level: Pointer to supported levels or NULL if not yet allocated
  */
 struct pmic_regulator_data {
 	unsigned int flags;
 	char *regu_name;
-	struct regulator_voltages *voltages;
+	struct regulator_voltages_desc voltages_desc;
+	int *voltages_level;
 };
 
 /* Expect a single PMIC instance */
@@ -395,10 +397,9 @@ static int cmp_int_value(const void *a, const void *b)
 	return CMP_TRILEAN(*ia, *ib);
 }
 
-static size_t refine_levels_array(struct regulator_voltages *voltages)
+static size_t refine_levels_array(size_t count, int *levels_uv,
+				  int min_uv, int max_uv)
 {
-	int *levels_uv = voltages->entries;
-	size_t count = voltages->num_levels;
 	size_t n = 0;
 	size_t m = 0;
 
@@ -413,20 +414,34 @@ static size_t refine_levels_array(struct regulator_voltages *voltages)
 			m++;
 		}
 	}
+	count = m + 1;
 
-	return m + 1;
+	for (n = count; n; n--)
+		if (levels_uv[n - 1] <= max_uv)
+			break;
+	count = n;
+
+	for (n = 0; n < count; n++)
+		if (levels_uv[n] >= min_uv)
+			break;
+	count -= n;
+
+	memmove(levels_uv, levels_uv + n, count * sizeof(*levels_uv));
+
+	return count;
 }
 
 static TEE_Result pmic_list_voltages(struct regulator *regulator,
-				     struct regulator_voltages **out_voltages)
+				     struct regulator_voltages_desc **out_desc,
+				     const int **out_levels)
 {
 	struct pmic_regulator_data *priv = regulator->priv;
 
-	if (!priv->voltages) {
-		struct regulator_voltages *voltages_s = NULL;
-		struct regulator_voltages *voltages = NULL;
+	if (!priv->voltages_level) {
 		const uint16_t *level_ref = NULL;
 		size_t level_count = 0;
+		int *levels2 = NULL;
+		int *levels = NULL;
 		size_t n = 0;
 
 		/*
@@ -436,30 +451,30 @@ static TEE_Result pmic_list_voltages(struct regulator *regulator,
 		stpmic1_regulator_levels_mv(priv->regu_name, &level_ref,
 					    &level_count);
 
-		voltages = calloc(1, sizeof(*voltages) +
-				     sizeof(*voltages->entries) * level_count);
-		if (!voltages)
+		levels = calloc(level_count, sizeof(*levels));
+		if (!levels)
 			return TEE_ERROR_OUT_OF_MEMORY;
 		for (n = 0; n < level_count; n++)
-			voltages->entries[n] = level_ref[n] * 1000;
+			levels[n] = level_ref[n] * 1000;
 
-		voltages->num_levels = level_count;
-		level_count = refine_levels_array(voltages);
+		level_count = refine_levels_array(level_count, levels,
+						  regulator->min_uv,
+						  regulator->max_uv);
 
-		voltages_s = realloc(voltages,
-				     sizeof(*voltages) +
-				     sizeof(*voltages->entries) * level_count);
-		if (!voltages_s) {
-			free(voltages);
+		/* Shrink levels array to not waste heap memory */
+		levels2 = realloc(levels, sizeof(*levels) * level_count);
+		if (!levels2) {
+			free(levels);
 			return TEE_ERROR_OUT_OF_MEMORY;
 		}
 
-		voltages_s->type = VOLTAGE_TYPE_FULL_LIST;
-		voltages_s->num_levels = level_count;
-		priv->voltages = voltages_s;
+		priv->voltages_desc.type = VOLTAGE_TYPE_FULL_LIST;
+		priv->voltages_desc.num_levels = level_count;
+		priv->voltages_level = levels2;
 	}
 
-	*out_voltages = priv->voltages;
+	*out_desc = &priv->voltages_desc;
+	*out_levels = priv->voltages_level;
 
 	return TEE_SUCCESS;
 }
@@ -535,8 +550,8 @@ static TEE_Result release_voltage_lists(void)
 	for (n = 0; n < ARRAY_SIZE(pmic_regulators); n++) {
 		struct pmic_regulator_data *priv = pmic_regulators[n].priv;
 
-		if (priv && priv->voltages)
-			free(priv->voltages);
+		if (priv && priv->voltages_level)
+			free(priv->voltages_level);
 	}
 
 	return TEE_SUCCESS;
diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c
index 4785c9db1cb7ae4cb7a7b4f58018c30b0a6be66d..e06e2a2b1fe0e64b7b667b36fafe4f8e179c31a0 100644
--- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c
+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c
@@ -6,11 +6,14 @@
 #include <assert.h>
 #include <drivers/regulator.h>
 #include <drivers/stm32_shared_io.h>
+#include <drivers/stm32_bsec.h>
 #include <drivers/stm32mp1_pwr.h>
+#include <drivers/stm32mp1_syscfg.h>
 #include <io.h>
 #include <kernel/delay.h>
 #include <kernel/dt_driver.h>
 #include <kernel/panic.h>
+#include <kernel/pm.h>
 #include <libfdt.h>
 #include <mm/core_memprot.h>
 #include <platform_config.h>
@@ -24,6 +27,8 @@
 
 #define TIMEOUT_US_10MS		U(10000)
 
+#define VOLTAGE_2V7_THREDSHOLD_UV	2700000
+
 struct pwr_regu_desc {
 	unsigned int level_mv;
 	uint32_t cr3_enable_mask;
@@ -100,19 +105,17 @@ static TEE_Result stm32mp1_pwr_regu_set_state(struct regulator *regu,
 {
 	const struct pwr_regu_desc *desc = regu->priv;
 	uintptr_t cr3 = stm32_pwr_base() + PWR_CR3_OFF;
-	uint64_t to = 0;
 
 	assert(desc);
 
 	if (enable) {
-		io_setbits32_stm32shregs(cr3, desc->cr3_enable_mask);
+		uint32_t value = 0;
 
-		to = timeout_init_us(TIMEOUT_US_10MS);
-		while (!timeout_elapsed(to))
-			if (io_read32(cr3) & desc->cr3_ready_mask)
-				break;
+		io_setbits32_stm32shregs(cr3, desc->cr3_enable_mask);
 
-		if (!(io_read32(cr3) & desc->cr3_ready_mask))
+		if (IO_READ32_POLL_TIMEOUT(cr3, value,
+					   value & desc->cr3_ready_mask,
+					   0, TIMEOUT_US_10MS))
 			return TEE_ERROR_GENERIC;
 	} else {
 		io_clrbits32_stm32shregs(cr3, desc->cr3_enable_mask);
@@ -178,13 +181,81 @@ struct regulator *stm32mp1_pwr_get_regulator(enum pwr_regulator id)
 	return NULL;
 }
 
+static TEE_Result vdd_hslv_pm(enum pm_op op, uint32_t pm_hint __unused,
+			      const struct pm_callback_handle *pm_hdl __unused)
+{
+	if (op == PM_OP_RESUME)
+		stm32mp_enable_fixed_vdd_hslv();
+
+	return TEE_SUCCESS;
+}
+DECLARE_KEEP_PAGER(vdd_hslv_pm);
+
+static TEE_Result set_fixed_vdd_hslv_mode(struct regulator *vdd_supply)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	bool product_below_2v5 = false;
+	uint32_t otp_value = 0;
+	uint32_t otp_id = 0;
+
+	/*
+	 * High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
+	 * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
+	 * It could be disabled for low frequencies or if AFMUX is selected
+	 * but the function is not used, typically for TRACE.
+	 * If high speed low voltage pad mode is enabled, platform will
+	 * over consume.
+	 *
+	 * WARNING:
+	 *   Enabling High Speed mode while Vdd > 2.7V
+	 *   with the OTP product_below_2v5 (OTP 18, BIT 13)
+	 *   erroneously set to 1 can damage the SoC.
+	 */
+	res = stm32_bsec_find_otp_in_nvmem_layout("hw2_otp", &otp_id,
+						  NULL, NULL);
+	if (res)
+		panic();
+
+	res = stm32_bsec_read_otp(&otp_value, otp_id);
+	if (res)
+		panic();
+
+	if (otp_value & HW2_OTP_PRODUCT_BELOW_2V5)
+		product_below_2v5 = true;
+
+	if (regulator_get_voltage(vdd_supply) < VOLTAGE_2V7_THREDSHOLD_UV) {
+		if (!product_below_2v5) {
+			DMSG("Vdd domains HSLV protected by HW");
+		} else {
+			stm32mp_enable_fixed_vdd_hslv();
+			register_pm_driver_cb(vdd_hslv_pm, NULL,
+					      "stm32mp1-pwr-hslv");
+		}
+	} else if (product_below_2v5) {
+		panic("Vdd too high for related IO domains");
+	}
+
+	return TEE_SUCCESS;
+}
+
 static TEE_Result stm32mp1_pwr_regu_probe(const void *fdt, int node,
 					  const void *compat_data __unused)
 {
 	TEE_Result res = TEE_ERROR_GENERIC;
 	const struct regu_dt_desc *dt_desc = stm32mp1_pwr_regu_dt_desc;
+	struct regulator *vdd_supply = NULL;
 	int subnode = 0;
 
+	/* Setup High Speed Low Voltage mode for fixed VDD domain */
+	res = regulator_dt_get_supply(fdt, node, "vdd", &vdd_supply);
+	if (res)
+		return res;
+
+	res = set_fixed_vdd_hslv_mode(vdd_supply);
+	if (res)
+		return res;
+
+	/* Register PWR regulators */
 	fdt_for_each_subnode(subnode, fdt, node) {
 		const char *node_name = fdt_get_name(fdt, subnode, NULL);
 		unsigned int n = 0;
@@ -198,14 +269,10 @@ static TEE_Result stm32mp1_pwr_regu_probe(const void *fdt, int node,
 			panic();
 		}
 
-		if (IS_ENABLED(CFG_DRIVERS_REGULATOR)) {
-			res = regulator_dt_register(fdt, subnode, node,
-						    dt_desc + n);
-			if (res) {
-				EMSG("Can't register %s: %#"PRIx32, node_name,
-				     res);
-				panic();
-			}
+		res = regulator_dt_register(fdt, subnode, node, dt_desc + n);
+		if (res) {
+			EMSG("Can't register %s: %#"PRIx32, node_name, res);
+			panic();
 		}
 	}
 
diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h
index 65718a05a6ffe5d7468dd4f126e99ca6491803de..d6dc5de21c9454f3d05dd72fa974a7139f150b8d 100644
--- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h
+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause */
 /*
- * Copyright (c) 2018-2019, STMicroelectronics
+ * Copyright (c) 2018-2023, STMicroelectronics
  */
 
 #ifndef __STM32MP1_PWR_H
@@ -17,6 +17,14 @@
 #define PWR_WKUPCR_OFF		0x20
 #define PWR_MPUWKUPENR_OFF	0x28
 
+/* CR3 register bitfield for STM32MP13 variants */
+#define PWR_CR3_VDDSD1EN	BIT(13)
+#define PWR_CR3_VDDSD1RDY	BIT(14)
+#define PWR_CR3_VDDSD2EN	BIT(15)
+#define PWR_CR3_VDDSD2RDY	BIT(16)
+#define PWR_CR3_VDDSD1VALID	BIT(22)
+#define PWR_CR3_VDDSD2VALID	BIT(23)
+
 #define PWR_OFFSET_MASK		0x3fUL
 
 enum pwr_regulator {
diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c
index 281ae7caae55cc389deba717a93025ba75a940db..1b2ecbcffab37d3450c56c8a000b4358de016b12 100644
--- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c
+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c
@@ -1,10 +1,12 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright (c) 2019-2022, STMicroelectronics
+ * Copyright (c) 2019-2023, STMicroelectronics
  */
 
+#include <config.h>
 #include <drivers/clk.h>
 #include <drivers/stm32mp_dt_bindings.h>
+#include <drivers/stm32mp1_syscfg.h>
 #include <initcall.h>
 #include <kernel/delay.h>
 #include <mm/core_memprot.h>
@@ -16,8 +18,22 @@
 /*
  * SYSCFG register offsets (base relative)
  */
-#define SYSCFG_CMPCR				0x20U
-#define SYSCFG_CMPENSETR			0x24U
+#define SYSCFG_IOCTRLSETR			U(0x18)
+#define SYSCFG_CMPCR				U(0x20)
+#define SYSCFG_CMPENSETR			U(0x24)
+#define SYSCFG_CMPSD1CR				U(0x30)
+#define SYSCFG_CMPSD2CR				U(0x40)
+#define SYSCFG_HSLVEN0R				U(0x50)
+#define SYSCFG_IOSIZE				U(0x400)
+
+/*
+ * SYSCFG_IOCTRLSETR Register for STM32MP15 variants
+ */
+#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE		BIT(0)
+#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI	BIT(1)
+#define SYSCFG_IOCTRLSETR_HSLVEN_ETH		BIT(2)
+#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC		BIT(3)
+#define SYSCFG_IOCTRLSETR_HSLVEN_SPI		BIT(4)
 
 /*
  * SYSCFG_CMPCR Register
@@ -25,78 +41,159 @@
 #define SYSCFG_CMPCR_SW_CTRL			BIT(1)
 #define SYSCFG_CMPCR_READY			BIT(8)
 #define SYSCFG_CMPCR_RANSRC			GENMASK_32(19, 16)
-#define SYSCFG_CMPCR_RANSRC_SHIFT		16
+#define SYSCFG_CMPCR_RANSRC_SHIFT		U(16)
 #define SYSCFG_CMPCR_RAPSRC			GENMASK_32(23, 20)
-#define SYSCFG_CMPCR_ANSRC_SHIFT		24
+#define SYSCFG_CMPCR_ANSRC_SHIFT		U(24)
 
-#define SYSCFG_CMPCR_READY_TIMEOUT_US		1000U
+#define SYSCFG_CMPCR_READY_TIMEOUT_US		U(1000)
+
+#define CMPENSETR_OFFSET			U(0x4)
+#define CMPENCLRR_OFFSET			U(0x8)
 
 /*
  * SYSCFG_CMPENSETR Register
  */
 #define SYSCFG_CMPENSETR_MPU_EN			BIT(0)
 
+/*
+ * HSLV definitions
+ */
+#define SYSCFG_HSLV_MASK			GENMASK_32(15, 0)
+#define SYSCFG_HSLV_KEY				U(0x1018)
+
 static vaddr_t get_syscfg_base(void)
 {
-	struct io_pa_va base = { .pa = SYSCFG_BASE };
+	static struct io_pa_va base = { .pa = SYSCFG_BASE };
 
-	return io_pa_or_va(&base, 1);
+	return io_pa_or_va(&base, SYSCFG_IOSIZE);
 }
 
-void stm32mp_syscfg_enable_io_compensation(void)
+static void enable_io_compensation(int cmpcr_offset)
 {
-	vaddr_t syscfg_base = get_syscfg_base();
-	uint64_t timeout_ref = 0;
+	vaddr_t cmpcr_va = get_syscfg_base() + cmpcr_offset;
+	uint32_t value = 0;
+
+	if (io_read32(cmpcr_va) & SYSCFG_CMPCR_READY)
+		return;
+
+	io_setbits32(cmpcr_va + CMPENSETR_OFFSET, SYSCFG_CMPENSETR_MPU_EN);
+
+	if (IO_READ32_POLL_TIMEOUT(cmpcr_va, value, value & SYSCFG_CMPCR_READY,
+				   0, SYSCFG_CMPCR_READY_TIMEOUT_US)) {
+		/* Allow an almost silent failure here */
+		EMSG("IO compensation cell not ready");
+	}
+
+	io_clrbits32(cmpcr_va, SYSCFG_CMPCR_SW_CTRL);
+
+	DMSG("SYSCFG.cmpcr = %#"PRIx32, io_read32(cmpcr_va));
+}
+
+static __maybe_unused void disable_io_compensation(int cmpcr_offset)
+{
+	vaddr_t cmpcr_base = get_syscfg_base() + cmpcr_offset;
+	uint32_t value_cmpcr = 0;
+	uint32_t apsrc_ansrc = 0;
+	uint32_t value_cmpcr2 = 0;
+
+	value_cmpcr = io_read32(cmpcr_base);
+	value_cmpcr2 = io_read32(cmpcr_base + CMPENSETR_OFFSET);
+	if (!(value_cmpcr & SYSCFG_CMPCR_READY &&
+	      value_cmpcr2 & SYSCFG_CMPENSETR_MPU_EN))
+		return;
+
+	/* Copy APSRC (resp. ANSRC) in RAPSRC (resp. RANSRC) */
+	apsrc_ansrc = value_cmpcr >> SYSCFG_CMPCR_ANSRC_SHIFT;
+	value_cmpcr &= ~(SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC);
+	value_cmpcr |= SHIFT_U32(apsrc_ansrc, SYSCFG_CMPCR_RANSRC_SHIFT);
+
+	io_write32(cmpcr_base, value_cmpcr | SYSCFG_CMPCR_SW_CTRL);
+
+	io_setbits32(cmpcr_base + CMPENCLRR_OFFSET, SYSCFG_CMPENSETR_MPU_EN);
 
+	DMSG("SYSCFG.cmpcr = %#"PRIx32, io_read32(cmpcr_base));
+}
+
+static TEE_Result stm32mp1_iocomp(void)
+{
 	if (clk_enable(stm32mp_rcc_clock_id_to_clk(CK_CSI)) ||
 	    clk_enable(stm32mp_rcc_clock_id_to_clk(SYSCFG)))
 		panic();
 
-	io_setbits32(syscfg_base + SYSCFG_CMPENSETR, SYSCFG_CMPENSETR_MPU_EN);
+	enable_io_compensation(SYSCFG_CMPCR);
 
-	timeout_ref = timeout_init_us(SYSCFG_CMPCR_READY_TIMEOUT_US);
+	return TEE_SUCCESS;
+}
 
-	while (!(io_read32(syscfg_base + SYSCFG_CMPCR) & SYSCFG_CMPCR_READY)) {
-		if (timeout_elapsed(timeout_ref)) {
-			EMSG("IO compensation cell not ready");
-			/* Allow an almost silent failure here */
-			break;
-		}
-	}
+driver_init(stm32mp1_iocomp);
 
-	io_clrbits32(syscfg_base + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
+#ifdef CFG_STM32MP13
+void stm32mp_set_vddsd_comp_state(enum stm32mp13_vddsd_comp_id id, bool enable)
+{
+	int cmpcr_offset = 0;
+
+	switch (id) {
+	case SYSCFG_IO_COMP_IDX_SD1:
+		cmpcr_offset = SYSCFG_CMPSD1CR;
+		break;
+	case SYSCFG_IO_COMP_IDX_SD2:
+		cmpcr_offset = SYSCFG_CMPSD2CR;
+		break;
+	default:
+		panic();
+	}
 
-	DMSG("SYSCFG.cmpcr = %#"PRIx32, io_read32(syscfg_base + SYSCFG_CMPCR));
+	if (enable)
+		enable_io_compensation(cmpcr_offset);
+	else
+		disable_io_compensation(cmpcr_offset);
 }
 
-void stm32mp_syscfg_disable_io_compensation(void)
+void stm32mp_set_hslv_state(enum stm32mp13_hslv_id id, bool enable)
 {
-	vaddr_t syscfg_base = get_syscfg_base();
-	uint32_t value = 0;
+	size_t hslvenxr_offset = 0;
+	uint32_t hlvs_value = 0;
 
-	value = io_read32(syscfg_base + SYSCFG_CMPCR) >>
-		SYSCFG_CMPCR_ANSRC_SHIFT;
+	assert(id < SYSCFG_HSLV_COUNT);
 
-	io_clrbits32(syscfg_base + SYSCFG_CMPCR,
-		     SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC);
+	if (enable)
+		hlvs_value = SYSCFG_HSLV_KEY;
 
-	value = io_read32(syscfg_base + SYSCFG_CMPCR) |
-		(value << SYSCFG_CMPCR_RANSRC_SHIFT);
+	/* IDs are indices of SYSCFG_HSLVENxR registers */
+	hslvenxr_offset = SYSCFG_HSLVEN0R + id * sizeof(uint32_t);
 
-	io_write32(syscfg_base + SYSCFG_CMPCR, value | SYSCFG_CMPCR_SW_CTRL);
+	io_write32(get_syscfg_base() + hslvenxr_offset, hlvs_value);
 
-	DMSG("SYSCFG.cmpcr = %#"PRIx32, io_read32(syscfg_base + SYSCFG_CMPCR));
+	/* Value read shall be 1 on enable and 0 on disable */
+	hlvs_value = io_read32(get_syscfg_base() + hslvenxr_offset) &
+		     SYSCFG_HSLV_MASK;
+	if (enable != hlvs_value)
+		panic();
+}
+
+void stm32mp_enable_fixed_vdd_hslv(void)
+{
+	enum stm32mp13_hslv_id id = SYSCFG_HSLV_COUNT;
 
-	io_clrbits32(syscfg_base + SYSCFG_CMPENSETR, SYSCFG_CMPENSETR_MPU_EN);
+	for (id = SYSCFG_HSLV_IDX_TPIU; id < SYSCFG_HSLV_COUNT; id++) {
+		/* SDMMCs domains may not be supplied by VDD */
+		if (id == SYSCFG_HSLV_IDX_SDMMC1 ||
+		    id == SYSCFG_HSLV_IDX_SDMMC2)
+			continue;
 
-	clk_disable(stm32mp_rcc_clock_id_to_clk(CK_CSI));
-	clk_disable(stm32mp_rcc_clock_id_to_clk(SYSCFG));
+		stm32mp_set_hslv_state(id, true);
+	}
 }
+#endif /* CFG_STM32MP13 */
 
-static TEE_Result stm32mp1_iocomp(void)
+#ifdef CFG_STM32MP15
+void stm32mp_enable_fixed_vdd_hslv(void)
 {
-	stm32mp_syscfg_enable_io_compensation();
-
-	return TEE_SUCCESS;
+	io_write32(get_syscfg_base() + SYSCFG_IOCTRLSETR,
+		   SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
+		   SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
+		   SYSCFG_IOCTRLSETR_HSLVEN_ETH |
+		   SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
+		   SYSCFG_IOCTRLSETR_HSLVEN_SPI);
 }
-driver_init(stm32mp1_iocomp);
+#endif
diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.h b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.h
new file mode 100644
index 0000000000000000000000000000000000000000..575f147be1fe3e1f5ec022443c43b50aafdb5388
--- /dev/null
+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2023, STMicroelectronics
+ */
+
+#ifndef __DRIVERS_STM32MP1_SYSCFG_H
+#define __DRIVERS_STM32MP1_SYSCFG_H
+
+/* High Speed Low Voltage domains IDs for STM32MP13 variants */
+enum stm32mp13_hslv_id {
+	SYSCFG_HSLV_IDX_TPIU = 0,
+	SYSCFG_HSLV_IDX_QSPI,
+	SYSCFG_HSLV_IDX_ETH1,
+	SYSCFG_HSLV_IDX_ETH2,
+	SYSCFG_HSLV_IDX_SDMMC1,
+	SYSCFG_HSLV_IDX_SDMMC2,
+	SYSCFG_HSLV_IDX_SPI1,
+	SYSCFG_HSLV_IDX_SPI2,
+	SYSCFG_HSLV_IDX_SPI3,
+	SYSCFG_HSLV_IDX_SPI4,
+	SYSCFG_HSLV_IDX_SPI5,
+	SYSCFG_HSLV_IDX_LTDC,
+	SYSCFG_HSLV_COUNT
+};
+
+/* IO compensation domains IDs for STM32MP13 variants */
+enum stm32mp13_vddsd_comp_id {
+	SYSCFG_IO_COMP_IDX_SD1,
+	SYSCFG_IO_COMP_IDX_SD2,
+	SYSCFG_IO_COMP_COUNT
+};
+
+#ifdef CFG_STM32MP13
+/*
+ * Enable or disable IO compensation for a VDDSD IO domains
+ * @id: VDDSD domain ID
+ * @enable: True to enable IO compensation, false to disable
+ */
+void stm32mp_set_vddsd_comp_state(enum stm32mp13_vddsd_comp_id id, bool enable);
+
+/*
+ * Enable or disable High Speed Low Voltage mode of an IO domain
+ * @index: HSLV IO domain ID
+ * @enable: True to enable IO compensation, false to disable
+ */
+void stm32mp_set_hslv_state(enum stm32mp13_hslv_id id, bool enable);
+#endif /*CFG_STM32MP13*/
+
+/* Enable High Speed Low Voltage mode for domains fixed supplied VDD */
+void stm32mp_enable_fixed_vdd_hslv(void);
+#endif /*__DRIVERS_STM32MP1_SYSCFG_H*/
diff --git a/core/arch/arm/plat-stm32mp1/main.c b/core/arch/arm/plat-stm32mp1/main.c
index eebf0bd5e505f1651cc68364d05246ffa3ca51af..eed6b77c238350f917253f9af9f4fda63cdc2dcd 100644
--- a/core/arch/arm/plat-stm32mp1/main.c
+++ b/core/arch/arm/plat-stm32mp1/main.c
@@ -160,7 +160,7 @@ void boot_primary_init_intc(void)
 
 void boot_secondary_init_intc(void)
 {
-	gic_cpu_init();
+	gic_init_per_cpu();
 
 	stm32mp_register_online_cpu();
 }
@@ -500,16 +500,6 @@ static bool __maybe_unused bank_is_valid(unsigned int bank)
 	panic();
 }
 
-unsigned int stm32_get_gpio_bank_offset(unsigned int bank)
-{
-	assert(bank_is_valid(bank));
-
-	if (bank == GPIO_BANK_Z)
-		return 0;
-
-	return bank * GPIO_BANK_OFFSET;
-}
-
 #ifdef CFG_STM32_IWDG
 TEE_Result stm32_get_iwdg_otp_config(paddr_t pbase,
 				     struct stm32_iwdg_otp_data *otp_data)
@@ -563,7 +553,7 @@ static TEE_Result init_debug(void)
 		return res;
 
 	if (state != BSEC_STATE_SEC_CLOSED && conf) {
-		if (IS_ENABLED(CFG_WARN_INSECURE))
+		if (IS_ENABLED(CFG_INSECURE))
 			IMSG("WARNING: All debug accesses are allowed");
 
 		res = stm32_bsec_write_debug_conf(conf | BSEC_DEBUG_ALL);
diff --git a/core/arch/arm/plat-stm32mp1/plat_tzc400.c b/core/arch/arm/plat-stm32mp1/plat_tzc400.c
index 55f6d41d5a3b3b3ec7a601c6173cb6f345da2982..25c75b93c0ef931114a4bc7a829746c9030c1f52 100644
--- a/core/arch/arm/plat-stm32mp1/plat_tzc400.c
+++ b/core/arch/arm/plat-stm32mp1/plat_tzc400.c
@@ -40,11 +40,12 @@ static struct itr_handler tzc_itr_handler = {
 };
 DECLARE_KEEP_PAGER(tzc_itr_handler);
 
-static bool tzc_region_is_non_secure(unsigned int i, vaddr_t base, size_t size)
+static bool tzc_region_is_non_secure(unsigned int i, uint64_t pa, size_t size)
 {
 	struct tzc_region_config region_cfg = { };
 	uint32_t ns_cpu_mask = TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID);
 	uint32_t filters_mask = TZC_FILTERS_MASK;
+	vaddr_t base = pa;
 
 	if (tzc_get_region_config(i, &region_cfg))
 		panic();
@@ -71,6 +72,7 @@ static bool tzc_region_is_secure(unsigned int i, vaddr_t base, size_t size)
 
 static TEE_Result init_stm32mp1_tzc(void)
 {
+	TEE_Result res = TEE_ERROR_GENERIC;
 	void *base = phys_to_virt(TZC_BASE, MEM_AREA_IO_SEC, 1);
 	unsigned int region_index = 1;
 	const uint64_t dram_start = DDR_BASE;
@@ -108,8 +110,12 @@ static TEE_Result init_stm32mp1_tzc(void)
 			panic("Unexpected TZC area on non-secure region");
 	}
 
-	itr_add(&tzc_itr_handler);
-	itr_enable(tzc_itr_handler.it);
+	res = interrupt_add_handler_with_chip(interrupt_get_main_chip(),
+					      &tzc_itr_handler);
+	if (res)
+		panic();
+
+	interrupt_enable(tzc_itr_handler.chip, tzc_itr_handler.it);
 	tzc_set_action(TZC_ACTION_INT);
 
 	return TEE_SUCCESS;
diff --git a/core/arch/arm/plat-stm32mp1/platform_config.h b/core/arch/arm/plat-stm32mp1/platform_config.h
index 3c87a37abfda1112b4682ce102f3e0eb6bc075d1..c3867fc8ed212cd6f5402c015a5d70cebe6d674e 100644
--- a/core/arch/arm/plat-stm32mp1/platform_config.h
+++ b/core/arch/arm/plat-stm32mp1/platform_config.h
@@ -135,6 +135,8 @@
 #define HW2_OTP_IWDG_FZ_STOP_SHIFT	U(5)
 #define HW2_OTP_IWDG_FZ_STANDBY_SHIFT	U(7)
 
+#define HW2_OTP_PRODUCT_BELOW_2V5	BIT(13)
+
 /* GIC resources */
 #define GIC_SIZE			0x2000
 #define GICC_OFFSET			0x1000
diff --git a/core/arch/arm/plat-stm32mp1/pm/psci.c b/core/arch/arm/plat-stm32mp1/pm/psci.c
index f39c032b2f41e9024b2070f34ef2a7a68125bf05..bb206808df14ed9a2b9dc12fc42d7378b7968a55 100644
--- a/core/arch/arm/plat-stm32mp1/pm/psci.c
+++ b/core/arch/arm/plat-stm32mp1/pm/psci.c
@@ -132,6 +132,8 @@ static void raise_sgi0_as_secure(void)
 
 static void release_secondary_early_hpen(size_t __unused pos)
 {
+	struct itr_chip *itr_chip = interrupt_get_main_chip();
+
 	/* Need to send SIG#0 over Group0 after individual core 1 reset */
 	raise_sgi0_as_secure();
 	udelay(20);
@@ -142,7 +144,7 @@ static void release_secondary_early_hpen(size_t __unused pos)
 		   BOOT_API_A7_CORE1_MAGIC_NUMBER);
 
 	dsb_ishst();
-	itr_raise_sgi(GIC_SEC_SGI_0, TARGET_CPU1_GIC_MASK);
+	interrupt_raise_sgi(itr_chip, GIC_SEC_SGI_0, TARGET_CPU1_GIC_MASK);
 }
 
 /* Override default psci_cpu_on() with platform specific sequence */
diff --git a/core/arch/arm/plat-stm32mp1/scmi_server.c b/core/arch/arm/plat-stm32mp1/scmi_server.c
index 857809e774ca0f117ecdfbc43897af0e3e39b0b1..b0cc34b5d858f8ad23cdaa0b5794a1c399656314 100644
--- a/core/arch/arm/plat-stm32mp1/scmi_server.c
+++ b/core/arch/arm/plat-stm32mp1/scmi_server.c
@@ -14,6 +14,7 @@
 #include <drivers/stm32_vrefbuf.h>
 #include <drivers/stm32mp1_pmic.h>
 #include <drivers/stm32mp1_pwr.h>
+#include <drivers/stm32mp13_regulator_iod.h>
 #include <drivers/stpmic1.h>
 #include <drivers/stpmic1_regulator.h>
 #include <drivers/stm32mp_dt_bindings.h>
@@ -63,21 +64,22 @@ enum voltd_device {
 	VOLTD_PWR,
 	VOLTD_PMIC,
 	VOLTD_VREFBUF,
-	/* Stub regulator until regulator framework is merged */
-	VOLTD_STUB,
+	VOLTD_IOD,
 };
 
 /*
  * struct stm32_scmi_voltd - Data for the exposed voltage domains
  * @name: Power regulator string ID exposed to channel
- * @priv_id: Internal string ID for the regulator
+ * @priv_name: Internal string ID for the PMIC regulators
+ * @priv_id: Internal ID for the regulator aside PMIC ones
  * @priv_dev: Internal ID for the device implementing the regulator
  * @regulator: Regulator controller device
  * @state: State of the SCMI voltage domain (true: enable, false: disable)
  */
 struct stm32_scmi_voltd {
 	const char *name;
-	const char *priv_id;
+	const char *priv_name;
+	unsigned int priv_id;
 	enum voltd_device priv_dev;
 	struct regulator *regulator;
 	bool state;
@@ -109,13 +111,26 @@ register_phys_mem(MEM_AREA_IO_NSEC, CFG_STM32MP1_SCMI_SHM_BASE,
 		.name = (_name), \
 	}
 
-#define VOLTD_CELL(_scmi_id, _dev_id, _priv_id, _name) \
+#define VOLTD_CELL(_scmi_id, _dev_id, _priv_id, _priv_name, _name) \
 	[(_scmi_id)] = { \
+		.priv_name = (_priv_name), \
 		.priv_id = (_priv_id), \
 		.priv_dev = (_dev_id), \
 		.name = (_name), \
 	}
 
+#define VOLTD_CELL_PWR(_scmi_id, _priv_id, _name) \
+	VOLTD_CELL((_scmi_id), VOLTD_PWR, (_priv_id), NULL, (_name))
+
+#define VOLTD_CELL_IOD(_scmi_id, _priv_id, _name) \
+	VOLTD_CELL((_scmi_id), VOLTD_IOD, (_priv_id), NULL, (_name))
+
+#define VOLTD_CELL_VREFBUF(_scmi_id, _name) \
+	VOLTD_CELL((_scmi_id), VOLTD_VREFBUF, 0, NULL, (_name))
+
+#define VOLTD_CELL_PMIC(_scmi_id, _priv_name, _name) \
+	VOLTD_CELL((_scmi_id), VOLTD_PMIC, 0, (_priv_name), (_name))
+
 #ifdef CFG_STM32MP13
 static struct stm32_scmi_clk stm32_scmi_clock[] = {
 	CLOCK_CELL(CK_SCMI_HSE, CK_HSE, "ck_hse", true),
@@ -201,65 +216,50 @@ static struct stm32_scmi_rd stm32_scmi_reset_domain[] = {
 };
 #endif
 
-#define PWR_REG11_NAME_ID		"0"
-#define PWR_REG18_NAME_ID		"1"
-#define PWR_USB33_NAME_ID		"2"
-
-#define STUB_SDMMC1_IO_NAME_ID		"sdmmc1"
-#define STUB_SDMMC2_IO_NAME_ID		"sdmmc2"
-
 #ifdef CFG_STM32MP13
 struct stm32_scmi_voltd scmi_voltage_domain[] = {
-	VOLTD_CELL(VOLTD_SCMI_REG11, VOLTD_PWR, PWR_REG11_NAME_ID, "reg11"),
-	VOLTD_CELL(VOLTD_SCMI_REG18, VOLTD_PWR, PWR_REG18_NAME_ID, "reg18"),
-	VOLTD_CELL(VOLTD_SCMI_USB33, VOLTD_PWR, PWR_USB33_NAME_ID, "usb33"),
-	VOLTD_CELL(VOLTD_SCMI_SDMMC1_IO, VOLTD_STUB, STUB_SDMMC1_IO_NAME_ID,
-		   "sdmmc1"),
-	VOLTD_CELL(VOLTD_SCMI_SDMMC2_IO, VOLTD_STUB, STUB_SDMMC2_IO_NAME_ID,
-		   "sdmmc2"),
-	VOLTD_CELL(VOLTD_SCMI_VREFBUF, VOLTD_VREFBUF, "vrefbuf", "vrefbuf"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK1, VOLTD_PMIC, "buck1", "buck1"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK2, VOLTD_PMIC, "buck2", "buck2"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK3, VOLTD_PMIC, "buck3", "buck3"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK4, VOLTD_PMIC, "buck4", "buck4"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO1, VOLTD_PMIC, "ldo1", "ldo1"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO2, VOLTD_PMIC, "ldo2", "ldo2"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO3, VOLTD_PMIC, "ldo3", "ldo3"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO4, VOLTD_PMIC, "ldo4", "ldo4"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO5, VOLTD_PMIC, "ldo5", "ldo5"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO6, VOLTD_PMIC, "ldo6", "ldo6"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_VREFDDR, VOLTD_PMIC, "vref_ddr",
-		   "vref_ddr"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_BOOST, VOLTD_PMIC, "boost", "bst_out"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_PWR_SW1, VOLTD_PMIC, "pwr_sw1",
-		   "pwr_sw1"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_PWR_SW2, VOLTD_PMIC, "pwr_sw2",
-		   "pwr_sw2"),
+	VOLTD_CELL_PWR(VOLTD_SCMI_REG11, PWR_REG11, "reg11"),
+	VOLTD_CELL_PWR(VOLTD_SCMI_REG18, PWR_REG18, "reg18"),
+	VOLTD_CELL_PWR(VOLTD_SCMI_USB33, PWR_USB33, "usb33"),
+	VOLTD_CELL_IOD(VOLTD_SCMI_SDMMC1_IO, IOD_SDMMC1, "sdmmc1"),
+	VOLTD_CELL_IOD(VOLTD_SCMI_SDMMC2_IO, IOD_SDMMC2, "sdmmc2"),
+	VOLTD_CELL_VREFBUF(VOLTD_SCMI_VREFBUF, "vrefbuf"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK1, "buck1", "buck1"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK2, "buck2", "buck2"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK3, "buck3", "buck3"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK4, "buck4", "buck4"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO1, "ldo1", "ldo1"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO2, "ldo2", "ldo2"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO3, "ldo3", "ldo3"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO4, "ldo4", "ldo4"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO5, "ldo5", "ldo5"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO6, "ldo6", "ldo6"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_VREFDDR, "vref_ddr", "vref_ddr"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BOOST, "boost", "bst_out"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_PWR_SW1, "pwr_sw1", "pwr_sw1"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_PWR_SW2, "pwr_sw2", "pwr_sw2"),
 };
 #endif
 
 #ifdef CFG_STM32MP15
 struct stm32_scmi_voltd scmi_voltage_domain[] = {
-	VOLTD_CELL(VOLTD_SCMI_REG11, VOLTD_PWR, PWR_REG11_NAME_ID, "reg11"),
-	VOLTD_CELL(VOLTD_SCMI_REG18, VOLTD_PWR, PWR_REG18_NAME_ID, "reg18"),
-	VOLTD_CELL(VOLTD_SCMI_USB33, VOLTD_PWR, PWR_USB33_NAME_ID, "usb33"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK1, VOLTD_PMIC, "buck1", "vddcore"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK2, VOLTD_PMIC, "buck2", "vdd_ddr"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK3, VOLTD_PMIC, "buck3", "vdd"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_BUCK4, VOLTD_PMIC, "buck4", "v3v3"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO1, VOLTD_PMIC, "ldo1", "v1v8_audio"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO2, VOLTD_PMIC, "ldo2", "v3v3_hdmi"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO3, VOLTD_PMIC, "ldo3", "vtt_ddr"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO4, VOLTD_PMIC, "ldo4", "vdd_usb"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO5, VOLTD_PMIC, "ldo5", "vdda"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_LDO6, VOLTD_PMIC, "ldo6", "v1v2_hdmi"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_VREFDDR, VOLTD_PMIC, "vref_ddr",
-		   "vref_ddr"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_BOOST, VOLTD_PMIC, "boost", "bst_out"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_PWR_SW1, VOLTD_PMIC, "pwr_sw1",
-		   "vbus_otg"),
-	VOLTD_CELL(VOLTD_SCMI_STPMIC1_PWR_SW2, VOLTD_PMIC, "pwr_sw2",
-		   "vbus_sw"),
+	VOLTD_CELL_PWR(VOLTD_SCMI_REG11, PWR_REG11, "reg11"),
+	VOLTD_CELL_PWR(VOLTD_SCMI_REG18, PWR_REG18, "reg18"),
+	VOLTD_CELL_PWR(VOLTD_SCMI_USB33, PWR_USB33, "usb33"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK1, "buck1", "vddcore"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK2, "buck2", "vdd_ddr"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK3, "buck3", "vdd"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK4, "buck4", "v3v3"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO1, "ldo1", "v1v8_audio"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO2, "ldo2", "v3v3_hdmi"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO3, "ldo3", "vtt_ddr"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO4, "ldo4", "vdd_usb"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO5, "ldo5", "vdda"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO6, "ldo6", "v1v2_hdmi"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_VREFDDR, "vref_ddr", "vref_ddr"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BOOST, "boost", "bst_out"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_PWR_SW1, "pwr_sw1", "vbus_otg"),
+	VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_PWR_SW2, "pwr_sw2", "vbus_sw"),
 };
 #endif
 
@@ -624,48 +624,9 @@ const char *plat_scmi_voltd_get_name(unsigned int channel_id,
 	return voltd->name;
 }
 
-static enum pwr_regulator pwr_scmi_to_regu_id(struct stm32_scmi_voltd *voltd)
-{
-	if (!strcmp(voltd->priv_id, PWR_REG11_NAME_ID))
-		return PWR_REG11;
-	if (!strcmp(voltd->priv_id, PWR_REG18_NAME_ID))
-		return PWR_REG18;
-	if (!strcmp(voltd->priv_id, PWR_USB33_NAME_ID))
-		return PWR_USB33;
-
-	panic();
-}
-
-static long stub_get_level_uv(struct stm32_scmi_voltd *voltd)
-{
-	if (!strcmp(voltd->priv_id, STUB_SDMMC1_IO_NAME_ID) ||
-	    !strcmp(voltd->priv_id, STUB_SDMMC2_IO_NAME_ID))
-		return 3300000;
-
-	panic();
-}
-
-static int32_t stub_describe_levels(struct stm32_scmi_voltd *voltd __unused,
-				    size_t start_index, long *microvolt,
-				    size_t *nb_elts)
-{
-	if (start_index)
-		return SCMI_INVALID_PARAMETERS;
-
-	if (!microvolt || !*nb_elts) {
-		*nb_elts = 1;
-		return SCMI_SUCCESS;
-	}
-
-	microvolt[0] = stub_get_level_uv(voltd);
-	*nb_elts = 1;
-
-	return SCMI_SUCCESS;
-}
-
 int32_t plat_scmi_voltd_levels_array(unsigned int channel_id,
 				     unsigned int scmi_id, size_t start_index,
-				     long *levels, size_t *nb_elts)
+				     long *out_levels, size_t *nb_elts)
 
 {
 	struct stm32_scmi_voltd *voltd = find_voltd(channel_id, scmi_id);
@@ -674,18 +635,18 @@ int32_t plat_scmi_voltd_levels_array(unsigned int channel_id,
 		return SCMI_NOT_FOUND;
 
 	if (voltd->regulator) {
-		struct regulator_voltages *voltages = NULL;
+		struct regulator_voltages_desc *desc = NULL;
 		TEE_Result res = TEE_ERROR_GENERIC;
-		int *ref = NULL;
-		size_t ref_count = 0;
+		const int *levels = NULL;
 		size_t n = 0;
 
-		res = regulator_supported_voltages(voltd->regulator, &voltages);
+		res = regulator_supported_voltages(voltd->regulator, &desc,
+						   &levels);
 		if (res == TEE_ERROR_NOT_SUPPORTED)
 			return SCMI_NOT_SUPPORTED;
 		if (res)
 			return SCMI_GENERIC_ERROR;
-		if (!voltages || voltages->type != VOLTAGE_TYPE_FULL_LIST) {
+		if (!desc || desc->type != VOLTAGE_TYPE_FULL_LIST) {
 			/*
 			 * Triplet min/max/step description. Caller should use
 			 * plat_scmi_voltd_levels_by_step().
@@ -693,44 +654,22 @@ int32_t plat_scmi_voltd_levels_array(unsigned int channel_id,
 			return SCMI_NOT_SUPPORTED;
 		}
 
-		ref = voltages->entries;
-		ref_count = voltages->num_levels;
-
-		/* Bound according to regulator registered min/max levels */
-		for (n = ref_count; n > 0; n--)
-			if (voltages->entries[n - 1] > voltd->regulator->max_uv)
-				ref_count--;
-		for (n = 0; n < ref_count; n++)
-			if (voltages->entries[n] >= voltd->regulator->min_uv)
-				break;
-
-		if (n == ref_count) {
-			DMSG("Voltage list out of regulator %s level bounds",
-			     regulator_name(voltd->regulator));
-			return SCMI_GENERIC_ERROR;
-		}
-
-		if (start_index >= ref_count)
+		if (start_index >= desc->num_levels)
 			return SCMI_OUT_OF_RANGE;
 
 		if (!*nb_elts) {
-			*nb_elts = ref_count - start_index;
+			*nb_elts = desc->num_levels - start_index;
 			return SCMI_SUCCESS;
 		}
 
+		*nb_elts = MIN(*nb_elts, desc->num_levels - start_index);
 		for (n = 0; n < *nb_elts; n++)
-			levels[n] = ref[start_index + n];
+			out_levels[n] = levels[start_index + n];
 
 		return SCMI_SUCCESS;
 	}
 
-	switch (voltd->priv_dev) {
-	case VOLTD_STUB:
-		return stub_describe_levels(voltd, start_index, levels,
-					    nb_elts);
-	default:
-		return SCMI_DENIED;
-	}
+	return SCMI_DENIED;
 }
 
 int32_t plat_scmi_voltd_levels_by_step(unsigned int channel_id,
@@ -742,18 +681,17 @@ int32_t plat_scmi_voltd_levels_by_step(unsigned int channel_id,
 		return SCMI_NOT_FOUND;
 
 	if (voltd->regulator) {
-		struct regulator_voltages *voltages = NULL;
+		struct regulator_voltages_desc *desc = NULL;
 		TEE_Result res = TEE_ERROR_GENERIC;
-		int ref_min = 0;
-		int ref_max = 0;
-		int ref_step = 0;
+		const int *levels = NULL;
 
-		res = regulator_supported_voltages(voltd->regulator, &voltages);
+		res = regulator_supported_voltages(voltd->regulator, &desc,
+						   &levels);
 		if (res == TEE_ERROR_NOT_SUPPORTED)
 			return SCMI_NOT_SUPPORTED;
 		if (res)
 			return SCMI_GENERIC_ERROR;
-		if (!voltages || voltages->type != VOLTAGE_TYPE_INCREMENT) {
+		if (!desc || desc->type != VOLTAGE_TYPE_INCREMENT) {
 			/*
 			 * Triplet min/max/step description. Caller should use
 			 * plat_scmi_voltd_levels_by_step().
@@ -761,27 +699,9 @@ int32_t plat_scmi_voltd_levels_by_step(unsigned int channel_id,
 			return SCMI_NOT_SUPPORTED;
 		}
 
-		ref_min = voltages->entries[0];
-		ref_max = voltages->entries[1];
-		ref_step = voltages->entries[2];
-
-		if (ref_min < voltd->regulator->min_uv) {
-			int diff = voltd->regulator->min_uv - ref_min;
-			int incr = DIV_ROUND_UP(diff, ref_step);
-
-			ref_min += ref_step * incr;
-		}
-
-		if (ref_max > voltd->regulator->max_uv) {
-			int diff = ref_max - voltd->regulator->max_uv;
-			int decr = diff / ref_step;
-
-			ref_max -= ref_step * decr;
-		}
-
-		min_max_step[0] = ref_min;
-		min_max_step[1] = ref_max;
-		min_max_step[2] = ref_step;
+		min_max_step[0] = levels[0];
+		min_max_step[1] = levels[1];
+		min_max_step[2] = levels[2];
 
 		return SCMI_SUCCESS;
 	}
@@ -802,13 +722,7 @@ int32_t plat_scmi_voltd_get_level(unsigned int channel_id, unsigned int scmi_id,
 		return SCMI_SUCCESS;
 	}
 
-	switch (voltd->priv_dev) {
-	case VOLTD_STUB:
-		*level_uv = stub_get_level_uv(voltd);
-		return SCMI_SUCCESS;
-	default:
-		return SCMI_DENIED;
-	}
+	return SCMI_DENIED;
 }
 
 int32_t plat_scmi_voltd_set_level(unsigned int channel_id, unsigned int scmi_id,
@@ -832,12 +746,7 @@ int32_t plat_scmi_voltd_set_level(unsigned int channel_id, unsigned int scmi_id,
 			return SCMI_SUCCESS;
 	}
 
-	switch (voltd->priv_dev) {
-	case VOLTD_STUB:
-		return SCMI_SUCCESS;
-	default:
-		return SCMI_DENIED;
-	}
+	return SCMI_DENIED;
 }
 
 int32_t plat_scmi_voltd_get_config(unsigned int channel_id,
@@ -857,13 +766,7 @@ int32_t plat_scmi_voltd_get_config(unsigned int channel_id,
 		return SCMI_SUCCESS;
 	}
 
-	switch (voltd->priv_dev) {
-	case VOLTD_STUB:
-		*config = SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_ON;
-		return SCMI_SUCCESS;
-	default:
-		return SCMI_DENIED;
-	}
+	return SCMI_DENIED;
 }
 
 int32_t plat_scmi_voltd_set_config(unsigned int channel_id,
@@ -875,52 +778,47 @@ int32_t plat_scmi_voltd_set_config(unsigned int channel_id,
 		return SCMI_NOT_FOUND;
 
 	if (voltd->regulator) {
-		TEE_Result res = TEE_ERROR_GENERIC;
+		switch (config) {
+		case SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_ON:
+			if (!voltd->state) {
+				if (regulator_enable(voltd->regulator))
+					return SCMI_GENERIC_ERROR;
 
-		if (config == SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_ON &&
-		    !voltd->state) {
-			res = regulator_enable(voltd->regulator);
-			if (!res)
 				voltd->state = true;
-		} else if (config == SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_OFF &&
-			 voltd->state) {
-			res = regulator_disable(voltd->regulator);
-			if (!res)
+			}
+			break;
+		case SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_OFF:
+			if (voltd->state) {
+				if (regulator_disable(voltd->regulator))
+					return SCMI_GENERIC_ERROR;
+
 				voltd->state = false;
-		} else {
-			res = TEE_ERROR_GENERIC;
+			}
+			break;
+		default:
+			return SCMI_INVALID_PARAMETERS;
 		}
 
-		if (res)
-			return SCMI_GENERIC_ERROR;
-		else
-			return SCMI_SUCCESS;
-	}
-
-	switch (voltd->priv_dev) {
-	case VOLTD_STUB:
 		return SCMI_SUCCESS;
-	default:
-		return SCMI_DENIED;
 	}
+
+	return SCMI_DENIED;
 }
 
 static void get_voltd_regulator(struct stm32_scmi_voltd *voltd)
 {
-	enum pwr_regulator regu_id = PWR_REGU_COUNT;
-
 	switch (voltd->priv_dev) {
 	case VOLTD_PWR:
-		regu_id = pwr_scmi_to_regu_id(voltd);
-		voltd->regulator = stm32mp1_pwr_get_regulator(regu_id);
+		voltd->regulator = stm32mp1_pwr_get_regulator(voltd->priv_id);
 		break;
 	case VOLTD_PMIC:
-		voltd->regulator = stm32mp_pmic_get_regulator(voltd->priv_id);
+		voltd->regulator = stm32mp_pmic_get_regulator(voltd->priv_name);
 		break;
 	case VOLTD_VREFBUF:
 		voltd->regulator = stm32_vrefbuf_regulator();
 		break;
-	case VOLTD_STUB:
+	case VOLTD_IOD:
+		voltd->regulator = stm32mp1_get_iod_regulator(voltd->priv_id);
 		break;
 	default:
 		break;
diff --git a/core/arch/arm/plat-stm32mp1/shared_resources.c b/core/arch/arm/plat-stm32mp1/shared_resources.c
index b85a1304af62a3290d9f8e25c38f276514222e25..76ce6485918bff8f9257e8b06a1cf38b21a2a484 100644
--- a/core/arch/arm/plat-stm32mp1/shared_resources.c
+++ b/core/arch/arm/plat-stm32mp1/shared_resources.c
@@ -692,8 +692,12 @@ static void check_rcc_secure_configuration(void)
 		}
 	}
 
-	if (have_error)
-		panic();
+	if (have_error) {
+		if (IS_ENABLED(CFG_INSECURE))
+			EMSG("WARNING: CFG_INSECURE allows insecure RCC configuration");
+		else
+			panic();
+	}
 }
 
 static void set_gpio_secure_configuration(void)
diff --git a/core/arch/arm/plat-stm32mp1/stm32_util.h b/core/arch/arm/plat-stm32mp1/stm32_util.h
index 4ec59339aa2d8a426013b216310d4752e5ee620c..627933e4ad6a4155c01f4babc252077a6ff045bb 100644
--- a/core/arch/arm/plat-stm32mp1/stm32_util.h
+++ b/core/arch/arm/plat-stm32mp1/stm32_util.h
@@ -18,34 +18,12 @@
 /* Backup registers and RAM utils */
 vaddr_t stm32mp_bkpreg(unsigned int idx);
 
-/*
- * SYSCFG IO compensation.
- * These functions assume non-secure world is suspended.
- */
-void stm32mp_syscfg_enable_io_compensation(void);
-void stm32mp_syscfg_disable_io_compensation(void);
-
 /* Platform util for the RCC drivers */
 vaddr_t stm32_rcc_base(void);
 
 /* Platform util for the GIC */
 vaddr_t get_gicd_base(void);
 
-/*
- * Platform util functions for the GPIO driver
- * @bank: Target GPIO bank ID as per DT bindings
- *
- * Platform shall implement these functions to provide to stm32_gpio
- * driver the resource reference for a target GPIO bank. That are
- * memory mapped interface base address, interface offset (see below)
- * and clock identifier.
- *
- * stm32_get_gpio_bank_offset() returns a bank offset that is used to
- * check DT configuration matches platform implementation of the banks
- * description.
- */
-unsigned int stm32_get_gpio_bank_offset(unsigned int bank);
-
 /* Platform util for PMIC support */
 bool stm32mp_with_pmic(void);
 
diff --git a/core/arch/arm/plat-stm32mp2/conf.mk b/core/arch/arm/plat-stm32mp2/conf.mk
new file mode 100644
index 0000000000000000000000000000000000000000..76dda579739873cdcad1851f08c613b2424a1303
--- /dev/null
+++ b/core/arch/arm/plat-stm32mp2/conf.mk
@@ -0,0 +1,61 @@
+flavor_dts_file-257F_EV1 = stm32mp257f-ev1.dts
+
+flavorlist-MP25 = $(flavor_dts_file-257F_EV1)
+
+ifneq ($(PLATFORM_FLAVOR),)
+ifeq ($(flavor_dts_file-$(PLATFORM_FLAVOR)),)
+$(error Invalid platform flavor $(PLATFORM_FLAVOR))
+endif
+CFG_EMBED_DTB_SOURCE_FILE ?= $(flavor_dts_file-$(PLATFORM_FLAVOR))
+endif
+CFG_EMBED_DTB_SOURCE_FILE ?= stm32mp257f-ev1.dts
+
+ifneq ($(filter $(CFG_EMBED_DTB_SOURCE_FILE),$(flavorlist-MP25)),)
+$(call force,CFG_STM32MP25,y)
+endif
+
+ifneq ($(CFG_STM32MP25),y)
+$(error STM32 Platform must be defined)
+endif
+
+include core/arch/arm/cpu/cortex-armv8-0.mk
+supported-ta-targets ?= ta_arm64
+
+$(call force,CFG_ARM64_core,y)
+$(call force,CFG_DRIVERS_CLK,y)
+$(call force,CFG_DRIVERS_CLK_DT,y)
+$(call force,CFG_DRIVERS_GPIO,y)
+$(call force,CFG_DRIVERS_PINCTRL,y)
+$(call force,CFG_DT,y)
+$(call force,CFG_GIC,y)
+$(call force,CFG_HALT_CORES_ON_PANIC_SGI,15)
+$(call force,CFG_INIT_CNTVOFF,y)
+$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y)
+$(call force,CFG_WITH_ARM_TRUSTED_FW,y)
+$(call force,CFG_WITH_LPAE,y)
+
+CFG_TZDRAM_START ?= 0x82000000
+CFG_TZDRAM_SIZE  ?= 0x02000000
+
+CFG_CORE_HEAP_SIZE ?= 262144
+CFG_CORE_RESERVED_SHM ?= n
+CFG_DTB_MAX_SIZE ?= 262144
+CFG_HALT_CORES_ON_PANIC ?= y
+CFG_MMAP_REGIONS ?= 30
+CFG_NUM_THREADS ?= 5
+CFG_TEE_CORE_NB_CORE ?= 2
+
+CFG_STM32_GPIO ?= y
+CFG_STM32_UART ?= y
+
+# Default enable some test facitilites
+CFG_WITH_STATS ?= y
+
+# Default disable ASLR
+CFG_CORE_ASLR ?= n
+
+# UART instance used for early console (0 disables early console)
+CFG_STM32_EARLY_CONSOLE_UART ?= 2
+
+# Default disable external DT support
+CFG_EXTERNAL_DT ?= n
diff --git a/core/arch/arm/plat-stm32mp2/main.c b/core/arch/arm/plat-stm32mp2/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..81366e60d247c11049fe47505eb0d26fe8cc34e8
--- /dev/null
+++ b/core/arch/arm/plat-stm32mp2/main.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2023, STMicroelectronics
+ */
+
+#include <config.h>
+#include <console.h>
+#include <drivers/gic.h>
+#include <drivers/stm32_uart.h>
+#include <initcall.h>
+#include <kernel/boot.h>
+#include <kernel/dt.h>
+#include <kernel/interrupt.h>
+#include <kernel/misc.h>
+#include <kernel/spinlock.h>
+#include <mm/core_memprot.h>
+#include <platform_config.h>
+#include <stm32_util.h>
+#include <trace.h>
+
+register_phys_mem_pgdir(MEM_AREA_IO_NSEC, APB1_BASE, APB1_SIZE);
+
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB1_BASE, APB1_SIZE);
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB2_BASE, APB2_SIZE);
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB3_BASE, APB3_SIZE);
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB4_BASE, APB4_SIZE);
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB2_BASE, AHB2_SIZE);
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB3_BASE, AHB3_SIZE);
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB4_BASE, AHB4_SIZE);
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB5_BASE, AHB5_SIZE);
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, SAPB_BASE, SAPB_SIZE);
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, SAHB_BASE, SAHB_SIZE);
+
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, GIC_SIZE);
+
+#define _ID2STR(id)		(#id)
+#define ID2STR(id)		_ID2STR(id)
+
+static TEE_Result platform_banner(void)
+{
+	IMSG("Platform stm32mp2: flavor %s - DT %s", ID2STR(PLATFORM_FLAVOR),
+	     ID2STR(CFG_EMBED_DTB_SOURCE_FILE));
+
+	return TEE_SUCCESS;
+}
+
+service_init(platform_banner);
+
+/*
+ * Console
+ *
+ * CFG_STM32_EARLY_CONSOLE_UART specifies the ID of the UART used for
+ * trace console. Value 0 disables the early console.
+ *
+ * We cannot use the generic serial_console support since probing
+ * the console requires the platform clock driver to be already
+ * up and ready which is done only once service_init are completed.
+ */
+static struct stm32_uart_pdata console_data;
+
+void console_init(void)
+{
+#ifdef CFG_STM32_UART
+	/* Early console initialization before MMU setup */
+	struct uart {
+		paddr_t pa;
+		bool secure;
+	} uarts[] = {
+		[0] = { .pa = 0 },
+		[1] = { .pa = USART1_BASE, .secure = true, },
+		[2] = { .pa = USART2_BASE, .secure = false, },
+		[3] = { .pa = USART3_BASE, .secure = false, },
+		[4] = { .pa = UART4_BASE, .secure = false, },
+		[5] = { .pa = UART5_BASE, .secure = false, },
+		[6] = { .pa = USART6_BASE, .secure = false, },
+		[7] = { .pa = UART7_BASE, .secure = false, },
+		[8] = { .pa = UART8_BASE, .secure = false, },
+		[9] = { .pa = UART9_BASE, .secure = false, },
+	};
+
+	static_assert(ARRAY_SIZE(uarts) > CFG_STM32_EARLY_CONSOLE_UART);
+
+	if (!uarts[CFG_STM32_EARLY_CONSOLE_UART].pa)
+		return;
+
+	/* No clock yet bound to the UART console */
+	console_data.clock = NULL;
+	console_data.secure = uarts[CFG_STM32_EARLY_CONSOLE_UART].secure;
+	stm32_uart_init(&console_data, uarts[CFG_STM32_EARLY_CONSOLE_UART].pa);
+	register_serial_console(&console_data.chip);
+
+	IMSG("Early console on UART#%u", CFG_STM32_EARLY_CONSOLE_UART);
+#endif
+}
+
+#ifdef CFG_STM32_UART
+static TEE_Result init_console_from_dt(void)
+{
+	struct stm32_uart_pdata *pd = NULL;
+	void *fdt = NULL;
+	int node = 0;
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	fdt = get_embedded_dt();
+	res = get_console_node_from_dt(fdt, &node, NULL, NULL);
+	if (res == TEE_ERROR_ITEM_NOT_FOUND) {
+		fdt = get_external_dt();
+		res = get_console_node_from_dt(fdt, &node, NULL, NULL);
+		if (res == TEE_ERROR_ITEM_NOT_FOUND)
+			return TEE_SUCCESS;
+		if (res != TEE_SUCCESS)
+			return res;
+	}
+
+	pd = stm32_uart_init_from_dt_node(fdt, node);
+	if (!pd) {
+		IMSG("DTB disables console");
+		register_serial_console(NULL);
+		return TEE_SUCCESS;
+	}
+
+	/* Replace early console with the new one */
+	console_flush();
+	console_data = *pd;
+	register_serial_console(&console_data.chip);
+	IMSG("DTB enables console (%ssecure)", pd->secure ? "" : "non-");
+	free(pd);
+
+	return TEE_SUCCESS;
+}
+
+/* Probe console from DT once clock inits (service init level) are completed */
+service_init_late(init_console_from_dt);
+#endif /*STM32_UART*/
+
+void boot_primary_init_intc(void)
+{
+	gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET);
+}
+
+void boot_secondary_init_intc(void)
+{
+	gic_init_per_cpu();
+}
diff --git a/core/arch/arm/plat-stm32mp2/platform_config.h b/core/arch/arm/plat-stm32mp2/platform_config.h
new file mode 100644
index 0000000000000000000000000000000000000000..4d7af4a8c82b72f3a1dd6b6e5ae8c0bf8347cc1a
--- /dev/null
+++ b/core/arch/arm/plat-stm32mp2/platform_config.h
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2023, STMicroelectronics
+ */
+
+#ifndef PLATFORM_CONFIG_H
+#define PLATFORM_CONFIG_H
+
+#include <mm/generic_ram_layout.h>
+
+/* Make stacks aligned to data cache line length */
+#define STACK_ALIGNMENT			32
+
+/* SoC interface registers base address ranges */
+#define APB1_BASE			0x40000000
+#define APB1_SIZE			0x00200000
+#define APB2_BASE			0x40200000
+#define APB2_SIZE			0x00040000
+#define AHB2_BASE			0x40400000
+#define AHB2_SIZE			0x01c00000
+#define AHB3_BASE			0x42000000
+#define AHB3_SIZE			0x02000000
+#define APB3_BASE			0x44000000
+#define APB3_SIZE			0x001f0000
+#define AHB4_BASE			0x44200000
+#define AHB4_SIZE			0x01e00000
+#define SAPB_BASE			0x46000000
+#define SAPB_SIZE			0x00200000
+#define SAHB_BASE			0x46200000
+#define SAHB_SIZE			0x01e00000
+#define APB4_BASE			0x48000000
+#define APB4_SIZE			0x00200000
+#define AHB5_BASE			0x48200000
+#define AHB5_SIZE			0x01e00000
+
+/* SoC interface registers base address */
+#define UART2_BASE			0x400e0000
+#define UART3_BASE			0x400f0000
+#define UART4_BASE			0x40100000
+#define UART5_BASE			0x40110000
+#define I2C4_BASE			0x40150000
+#define I2C6_BASE			0x40170000
+#define UART6_BASE			0x40220000
+#define UART9_BASE			0x402c0000
+#define UART1_BASE			0x40330000
+#define SPI6_BASE			0x40350000
+#define UART7_BASE			0x40370000
+#define UART8_BASE			0x40380000
+#define OSPI1_BASE			0x40430000
+#define OSPI2_BASE			0x40440000
+#define HASH1_BASE			0x42010000
+#define RNG1_BASE			0x42020000
+#define CRYP1_BASE			0x42030000
+#define SAES_BASE			0x42050000
+#define PKA_BASE			0x42060000
+#define RIFSC_BASE			0x42080000
+#define RISAF5_BASE			0x420e0000
+#define RISAB6_BASE			0x42140000
+#define BSEC3_BASE			0x44000000
+#define IWDG2_BASE			0x44002000
+#define IWDG1_BASE			0x44010000
+#define RCC_BASE			0x44200000
+#define PWR_BASE			0x44210000
+#define SYSCFG_BASE			0x44230000
+#define GPIOA_BASE			0x44240000
+#define GPIOB_BASE			0x44250000
+#define GPIOC_BASE			0x44260000
+#define GPIOD_BASE			0x44270000
+#define GPIOE_BASE			0x44280000
+#define GPIOF_BASE			0x44290000
+#define GPIOG_BASE			0x442a0000
+#define GPIOH_BASE			0x442b0000
+#define GPIOI_BASE			0x442c0000
+#define GPIOJ_BASE			0x442d0000
+#define GPIOK_BASE			0x442e0000
+#define RTC_BASE			0x46000000
+#define TAMP_BASE			0x46010000
+#define GPIOZ_BASE			0x46200000
+#define STGEN_BASE			0x48080000
+#define FMC_BASE			0x48200000
+#define PCIE_BASE			0x48400000
+#define A35SSC_BASE			0x48800000
+#define GIC_BASE			0x4ac00000
+#define DDR_BASE			UL(0x80000000)
+
+#define SYSRAM_BASE			0x0e000000
+
+#define SRAM1_BASE			0x0e040000
+
+/* GIC resources */
+#define GIC_SIZE			0x80000
+#define GICC_OFFSET			0x20000
+#define GICD_OFFSET			0x10000
+
+/* Console configuration */
+#define GIC_SPI_UART4			126
+
+#define TARGET_CPU0_GIC_MASK		BIT(0)
+#define TARGET_CPU1_GIC_MASK		BIT(1)
+#define TARGET_CPUS_GIC_MASK		GENMASK_32(CFG_TEE_CORE_NB_CORE - 1, 0)
+
+/* USART/UART resources */
+#define USART1_BASE			UART1_BASE
+#define USART2_BASE			UART2_BASE
+#define USART3_BASE			UART3_BASE
+#define USART6_BASE			UART6_BASE
+
+#endif /*PLATFORM_CONFIG_H*/
diff --git a/core/arch/arm/plat-stm32mp2/stm32_util.h b/core/arch/arm/plat-stm32mp2/stm32_util.h
new file mode 100644
index 0000000000000000000000000000000000000000..2575f0a5c1cf8a35980fde4fa9a283a6069a013c
--- /dev/null
+++ b/core/arch/arm/plat-stm32mp2/stm32_util.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 2023, STMicroelectronics
+ */
+
+#ifndef __STM32_UTIL_H__
+#define __STM32_UTIL_H__
+
+#include <kernel/spinlock.h>
+#include <stdint.h>
+#include <types_ext.h>
+
+static inline void stm32mp_register_secure_periph_iomem(vaddr_t base __unused)
+{
+}
+
+static inline void stm32mp_register_non_secure_periph_iomem(vaddr_t base
+							    __unused) { }
+
+static inline void stm32mp_register_gpioz_pin_count(size_t count __unused) { }
+
+#define may_spin_lock(lock)		  cpu_spin_lock_xsave(lock)
+#define may_spin_unlock(lock, exceptions) cpu_spin_unlock_xrestore(lock, \
+								   exceptions)
+#endif /*__STM32_UTIL_H__*/
diff --git a/core/arch/arm/plat-stm32mp2/sub.mk b/core/arch/arm/plat-stm32mp2/sub.mk
new file mode 100644
index 0000000000000000000000000000000000000000..b5d5551e7f46aac78b063f67bd05d84f4980fcfd
--- /dev/null
+++ b/core/arch/arm/plat-stm32mp2/sub.mk
@@ -0,0 +1,3 @@
+global-incdirs-y += .
+
+srcs-y += main.c
diff --git a/core/arch/arm/plat-sunxi/main.c b/core/arch/arm/plat-sunxi/main.c
index 7f4215a194f4973fd89970c6801051f5634f9f5d..b0f80484f218b43cab87818522d02b2cd0c8648a 100644
--- a/core/arch/arm/plat-sunxi/main.c
+++ b/core/arch/arm/plat-sunxi/main.c
@@ -130,7 +130,7 @@ void boot_primary_init_intc(void)
 
 void boot_secondary_init_intc(void)
 {
-	gic_cpu_init();
+	gic_init_per_cpu();
 }
 #endif
 
diff --git a/core/arch/arm/plat-synquacer/main.c b/core/arch/arm/plat-synquacer/main.c
index d94aff33175610a11dafe8800a1dc02e7e655fe6..2ba622f1edce3ef7c1483620609321e0f88c01c2 100644
--- a/core/arch/arm/plat-synquacer/main.c
+++ b/core/arch/arm/plat-synquacer/main.c
@@ -59,8 +59,11 @@ static struct itr_handler timer_itr = {
 
 static TEE_Result init_timer_itr(void)
 {
-	itr_add(&timer_itr);
-	itr_enable(IT_SEC_TIMER);
+	if (interrupt_add_handler_with_chip(interrupt_get_main_chip(),
+					    &timer_itr))
+		panic();
+
+	interrupt_enable(timer_itr.chip, timer_itr.it);
 
 	/* Enable timer FIQ to fetch entropy required during boot */
 	generic_timer_start(TIMER_PERIOD_MS);
diff --git a/core/arch/arm/plat-ti/main.c b/core/arch/arm/plat-ti/main.c
index 9d9e75dd1f375d2ec30e47769a38cbd7dfb5970e..5b132ae7ec13bcb67b04364288471ff82425b924 100644
--- a/core/arch/arm/plat-ti/main.c
+++ b/core/arch/arm/plat-ti/main.c
@@ -41,7 +41,7 @@ void boot_primary_init_intc(void)
 
 void boot_secondary_init_intc(void)
 {
-	gic_cpu_init();
+	gic_init_per_cpu();
 }
 
 struct plat_nsec_ctx {
diff --git a/core/arch/arm/plat-vexpress/conf.mk b/core/arch/arm/plat-vexpress/conf.mk
index 94a4e62742144b39a6f44578da0b82985ed650a0..eefe1e520393c3f50246be48e708b8597d24d842 100644
--- a/core/arch/arm/plat-vexpress/conf.mk
+++ b/core/arch/arm/plat-vexpress/conf.mk
@@ -63,7 +63,8 @@ $(call force,CFG_GIC,y)
 endif
 
 ifeq ($(PLATFORM_FLAVOR),fvp)
-CFG_TEE_CORE_NB_CORE = 8
+CFG_HALT_CORES_ON_PANIC ?= y
+CFG_TEE_CORE_NB_CORE ?= 8
 ifeq ($(CFG_CORE_SEL2_SPMC),y)
 CFG_TZDRAM_START ?= 0x06281000
 CFG_TZDRAM_SIZE  ?= 0x01D80000
@@ -76,13 +77,18 @@ CFG_SHMEM_SIZE   ?= 0x00200000
 # DRAM1 is defined above 4G
 $(call force,CFG_CORE_LARGE_PHYS_ADDR,y)
 $(call force,CFG_CORE_ARM64_PA_BITS,36)
+CFG_AUTO_MAX_PA_BITS ?= y
 ifeq ($(CFG_SCMI_SCPFW),y)
 $(call force,CFG_SCMI_SCPFW_PRODUCT,optee-fvp)
 endif
+ifeq ($(CFG_CORE_SEL1_SPMC),y)
+CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 9
+endif
 endif
 
 ifeq ($(PLATFORM_FLAVOR),juno)
-CFG_TEE_CORE_NB_CORE = 6
+CFG_HALT_CORES_ON_PANIC ?= y
+CFG_TEE_CORE_NB_CORE ?= 6
 CFG_TZDRAM_START ?= 0xff000000
 CFG_TZDRAM_SIZE  ?= 0x00ff8000
 CFG_SHMEM_START  ?= 0xfee00000
@@ -96,7 +102,8 @@ CFG_WITH_SOFTWARE_PRNG ?= n
 endif
 
 ifeq ($(PLATFORM_FLAVOR),qemu_virt)
-CFG_TEE_CORE_NB_CORE = 4
+CFG_HALT_CORES_ON_PANIC ?= y
+CFG_TEE_CORE_NB_CORE ?= 4
 # [0e00.0000 0e0f.ffff] is reserved to early boot
 CFG_TZDRAM_START ?= 0x0e100000
 CFG_TZDRAM_SIZE  ?= 0x00f00000
@@ -112,7 +119,7 @@ ifeq ($(CFG_CORE_SANITIZE_KADDRESS),y)
 # This is unfortunately currently not possible to do in make so we have to
 # calculate it offline, there's some asserts in
 # core/arch/arm/kernel/generic_boot.c to check that we got it right
-CFG_ASAN_SHADOW_OFFSET = 0xc6a71c0
+CFG_ASAN_SHADOW_OFFSET ?= 0xc6a71c0
 endif
 $(call force,CFG_BOOT_SECONDARY_REQUEST,y)
 $(call force,CFG_PSCI_ARM32,y)
@@ -123,7 +130,9 @@ CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 219
 endif
 
 ifeq ($(PLATFORM_FLAVOR),qemu_armv8a)
-CFG_TEE_CORE_NB_CORE = 4
+CFG_HALT_CORES_ON_PANIC ?= y
+CFG_TEE_CORE_NB_CORE ?= 4
+CFG_AUTO_MAX_PA_BITS ?= y
 ifneq ($(CFG_CORE_SEL2_SPMC),y)
 # [0e00.0000 0e0f.ffff] is reserved to early boot
 CFG_TZDRAM_START ?= 0x0e100000
@@ -136,7 +145,7 @@ CFG_SHMEM_SIZE  ?= 0x00200000
 CFG_TEE_SDP_MEM_SIZE ?= 0x00400000
 ifeq ($(CFG_CORE_SANITIZE_KADDRESS),y)
 # See comment above
-CFG_ASAN_SHADOW_OFFSET = 0xc6a71c0
+CFG_ASAN_SHADOW_OFFSET ?= 0xc6a71c0
 endif
 endif
 $(call force,CFG_DT,y)
@@ -144,7 +153,14 @@ CFG_DTB_MAX_SIZE ?= 0x100000
 ifeq ($(CFG_SCMI_SCPFW),y)
 $(call force,CFG_SCMI_SCPFW_PRODUCT,optee-fvp)
 endif
+
+CFG_CORE_ASYNC_NOTIF ?= y
+ifeq ($(CFG_CORE_SEL1_SPMC),y)
+CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 8
+else ifneq ($(CFG_CORE_SEL2_SPMC),y)
+CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 219
 endif
+endif #PLATFORM_FLAVOR==qemu_armv8a
 
 ifneq (,$(filter $(PLATFORM_FLAVOR),qemu_virt qemu_armv8a))
 CFG_DT_DRIVER_EMBEDDED_TEST ?= y
diff --git a/core/arch/arm/plat-vexpress/main.c b/core/arch/arm/plat-vexpress/main.c
index d2ab712d39b48705b68b8f50f954dd9a7888b257..63be30aa13839ac342ce315967dbfee063816752 100644
--- a/core/arch/arm/plat-vexpress/main.c
+++ b/core/arch/arm/plat-vexpress/main.c
@@ -1,10 +1,11 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright (c) 2016-2020, Linaro Limited
+ * Copyright (c) 2016-2023, Linaro Limited
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
 #include <arm.h>
+#include <config.h>
 #include <console.h>
 #include <drivers/gic.h>
 #include <drivers/hfic.h>
@@ -19,6 +20,7 @@
 #include <kernel/panic.h>
 #include <kernel/spinlock.h>
 #include <kernel/tee_time.h>
+#include <kernel/thread_spmc.h>
 #include <mm/core_memprot.h>
 #include <mm/core_mmu.h>
 #include <platform_config.h>
@@ -44,20 +46,34 @@ register_ddr(DRAM1_BASE, DRAM1_SIZE);
 #endif
 
 #ifdef CFG_GIC
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GIC_CPU_REG_SIZE);
 register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE);
-register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GIC_DIST_REG_SIZE);
+#ifdef GIC_REDIST_BASE
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_REDIST_BASE, GIC_REDIST_SIZE);
+#endif
 
 void boot_primary_init_intc(void)
 {
+#ifdef GIC_REDIST_BASE
+	gic_init_v3(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET,
+		    GIC_REDIST_BASE);
+#else
 	gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET);
+#endif
+	if (IS_ENABLED(CFG_CORE_SEL1_SPMC) &&
+	    IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) {
+		size_t it = CFG_CORE_ASYNC_NOTIF_GIC_INTID;
+
+		if (it >= GIC_SGI_SEC_BASE && it <= GIC_SGI_SEC_MAX)
+			gic_init_donate_sgi_to_ns(it);
+		thread_spmc_set_async_notif_intid(it);
+	}
 }
 
-#if !defined(CFG_WITH_ARM_TRUSTED_FW)
 void boot_secondary_init_intc(void)
 {
-	gic_cpu_init();
+	gic_init_per_cpu();
 }
-#endif
 #endif /*CFG_GIC*/
 
 #ifdef CFG_CORE_HAFNIUM_INTC
@@ -101,14 +117,14 @@ static void read_console(void)
 	}
 }
 
-static enum itr_return console_itr_cb(struct itr_handler *h __maybe_unused)
+static enum itr_return console_itr_cb(struct itr_handler *hdl)
 {
 	if (notif_async_is_started()) {
 		/*
 		 * Asynchronous notifications are enabled, lets read from
 		 * uart in the bottom half instead.
 		 */
-		itr_disable(IT_CONSOLE_UART);
+		interrupt_disable(hdl->chip, hdl->it);
 		notif_send_async(NOTIF_VALUE_DO_BOTTOM_HALF);
 	} else {
 		read_console();
@@ -136,11 +152,11 @@ static void yielding_console_notif(struct notif_driver *ndrv __unused,
 	switch (ev) {
 	case NOTIF_EVENT_DO_BOTTOM_HALF:
 		read_console();
-		itr_enable(IT_CONSOLE_UART);
+		interrupt_enable(console_itr.chip, console_itr.it);
 		break;
 	case NOTIF_EVENT_STOPPED:
 		DMSG("Asynchronous notifications stopped");
-		itr_enable(IT_CONSOLE_UART);
+		interrupt_enable(console_itr.chip, console_itr.it);
 		break;
 	default:
 		EMSG("Unknown event %d", (int)ev);
@@ -154,8 +170,15 @@ struct notif_driver console_notif = {
 
 static TEE_Result init_console_itr(void)
 {
-	itr_add(&console_itr);
-	itr_enable(IT_CONSOLE_UART);
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	res = interrupt_add_handler_with_chip(interrupt_get_main_chip(),
+					      &console_itr);
+	if (res)
+		return res;
+
+	interrupt_enable(console_itr.chip, console_itr.it);
+
 	if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF))
 		notif_register_driver(&console_notif);
 	return TEE_SUCCESS;
diff --git a/core/arch/arm/plat-vexpress/platform_config.h b/core/arch/arm/plat-vexpress/platform_config.h
index 206885c0f287d818aeb05d0949252c5a5c4c1cb6..21aa40acdcf7f6d6071098c6b6e06fec1e0fc6f7 100644
--- a/core/arch/arm/plat-vexpress/platform_config.h
+++ b/core/arch/arm/plat-vexpress/platform_config.h
@@ -96,6 +96,10 @@
 
 #define GICC_OFFSET		0x0
 #define GICD_OFFSET		0x3000000
+#ifdef CFG_ARM_GICV3
+#define GIC_REDIST_BASE		0x2F100000
+#define GIC_REDIST_SIZE		0x00100000
+#endif
 
 #elif defined(PLATFORM_FLAVOR_juno)
 /*
@@ -126,15 +130,17 @@
 
 #define GICD_OFFSET		0
 #define GICC_OFFSET		0x10000
+#ifdef CFG_ARM_GICV3
+#define GIC_REDIST_BASE		0x080A0000
+#define GIC_REDIST_SIZE		0x00F60000
+#endif
 
 #else
 #error "Unknown platform flavor"
 #endif
 
-#ifdef GIC_BASE
 #define GICD_BASE		(GIC_BASE + GICD_OFFSET)
 #define GICC_BASE		(GIC_BASE + GICC_OFFSET)
-#endif
 
 #ifndef UART_BAUDRATE
 #define UART_BAUDRATE		115200
diff --git a/core/arch/arm/plat-zynq7k/main.c b/core/arch/arm/plat-zynq7k/main.c
index 19f40c92f5e57a7da902c8de506d96b24e1e7e70..08af994fd03ce42ca1943f8a039df5601ea57bcf 100644
--- a/core/arch/arm/plat-zynq7k/main.c
+++ b/core/arch/arm/plat-zynq7k/main.c
@@ -148,7 +148,7 @@ void boot_primary_init_intc(void)
 
 void boot_secondary_init_intc(void)
 {
-	gic_cpu_init();
+	gic_init_per_cpu();
 }
 
 static vaddr_t slcr_access_range[] = {
diff --git a/core/arch/riscv/include/kernel/misc_arch.h b/core/arch/riscv/include/kernel/misc_arch.h
index 208e358f5fa1e51f4fbac4349a8aee15548baca3..c48c7d9a8f1b08c1b8fcefcf6ed94a70f9e8a5a9 100644
--- a/core/arch/riscv/include/kernel/misc_arch.h
+++ b/core/arch/riscv/include/kernel/misc_arch.h
@@ -3,7 +3,7 @@
  * Copyright 2022 NXP
  */
 
-#ifndef KERNEL_MISC_ARCH_H
-#define KERNEL_MISC_ARCH_H
+#ifndef __KERNEL_MISC_ARCH_H
+#define __KERNEL_MISC_ARCH_H
 
-#endif /*KERNEL_MISC_ARCH_H*/
+#endif /*__KERNEL_MISC_ARCH_H*/
diff --git a/core/arch/riscv/include/kernel/tee_l2cc_mutex.h b/core/arch/riscv/include/kernel/tee_l2cc_mutex.h
index 12b914780d64d714fadc5429aaf112d24e2a2854..9dc873a8ec24968a5c7f3da3277bfb66e37a0dda 100644
--- a/core/arch/riscv/include/kernel/tee_l2cc_mutex.h
+++ b/core/arch/riscv/include/kernel/tee_l2cc_mutex.h
@@ -2,7 +2,7 @@
 /*
  * Copyright 2022 NXP
  */
-#ifndef TEE_L2CC_MUTEX_H
-#define TEE_L2CC_MUTEX_H
+#ifndef __KERNEL_TEE_L2CC_MUTEX_H
+#define __KERNEL_TEE_L2CC_MUTEX_H
 
-#endif /* TEE_L2CC_MUTEX_H */
+#endif /* __KERNEL_TEE_L2CC_MUTEX_H */
diff --git a/core/arch/riscv/include/kernel/thread_arch.h b/core/arch/riscv/include/kernel/thread_arch.h
index e150fa10e86a5de25e32a9f268d53a78ad96ec50..1e2da17b726f8bf631cbe78a1a59d96ee4a0aeb5 100644
--- a/core/arch/riscv/include/kernel/thread_arch.h
+++ b/core/arch/riscv/include/kernel/thread_arch.h
@@ -32,6 +32,9 @@ struct thread_core_local {
 #ifdef CFG_CORE_DEBUG_CHECK_STACKS
 	bool stackcheck_recursion;
 #endif
+#ifdef CFG_FAULT_MITIGATION
+	struct ftmn_func_arg *ftmn_arg;
+#endif
 } THREAD_CORE_LOCAL_ALIGNED;
 
 struct thread_user_vfp_state {
diff --git a/core/arch/riscv/include/kernel/tlb_helpers.h b/core/arch/riscv/include/kernel/tlb_helpers.h
index ad82024ab283bdcc9c5701641c55061ec8e4c2da..d81766b9d64d10c1a95469b853198c8b3ab384ba 100644
--- a/core/arch/riscv/include/kernel/tlb_helpers.h
+++ b/core/arch/riscv/include/kernel/tlb_helpers.h
@@ -3,8 +3,8 @@
  * Copyright 2022 NXP
  */
 
-#ifndef TLB_HELPERS_H
-#define TLB_HELPERS_H
+#ifndef __KERNEL_TLB_HELPERS_H
+#define __KERNEL_TLB_HELPERS_H
 
 #ifndef __ASSEMBLER__
 
@@ -15,4 +15,4 @@ void tlbi_va_asid(vaddr_t va, uint32_t asid);
 
 #endif /*!__ASSEMBLER__*/
 
-#endif /* TLB_HELPERS_H */
+#endif /* __KERNEL_TLB_HELPERS_H */
diff --git a/core/arch/riscv/include/mm/core_mmu_arch.h b/core/arch/riscv/include/mm/core_mmu_arch.h
index 1284d47428361bfec40368d8b4bb1ad847f6bc5d..cc9aa798f2765b695d66635662f33e68ea7d6949 100644
--- a/core/arch/riscv/include/mm/core_mmu_arch.h
+++ b/core/arch/riscv/include/mm/core_mmu_arch.h
@@ -2,8 +2,8 @@
 /*
  * Copyright 2022-2023 NXP
  */
-#ifndef __CORE_MMU_ARCH_H
-#define __CORE_MMU_ARCH_H
+#ifndef __MM_CORE_MMU_ARCH_H
+#define __MM_CORE_MMU_ARCH_H
 
 #ifndef __ASSEMBLER__
 #include <assert.h>
@@ -150,4 +150,4 @@ static inline bool core_mmu_level_in_range(unsigned int level)
 }
 #endif /*__ASSEMBLER__*/
 
-#endif /* __CORE_MMU_ARCH_H */
+#endif /* __MM_CORE_MMU_ARCH_H */
diff --git a/core/arch/riscv/include/riscv.h b/core/arch/riscv/include/riscv.h
index ecaba09b5b2225b89ff29364b431569e9b0db07d..59fb0c37c105aa635b1730f23ad358869cd23dae 100644
--- a/core/arch/riscv/include/riscv.h
+++ b/core/arch/riscv/include/riscv.h
@@ -3,8 +3,8 @@
  * Copyright 2022-2023 NXP
  */
 
-#ifndef RISCV_H
-#define RISCV_H
+#ifndef __RISCV_H
+#define __RISCV_H
 
 #include <compiler.h>
 #include <encoding.h>
@@ -117,7 +117,7 @@ static inline __noprof void mb(void)
 
 static inline __noprof unsigned long read_tp(void)
 {
-	unsigned long tp;
+	unsigned long tp = 0;
 
 	asm volatile("mv %0, tp" : "=&r"(tp));
 	return tp;
@@ -389,4 +389,4 @@ static inline __noprof uint32_t read_cntfrq(void)
 
 #endif /*__ASSEMBLER__*/
 
-#endif /*RISCV_H*/
+#endif /*__RISCV_H*/
diff --git a/core/arch/riscv/include/sbi.h b/core/arch/riscv/include/sbi.h
index 6ea6064d823d9130c9f2c138baf1c23ee4e7ceea..8b73edee938a6dca8f639c79cfc31c25c9e7d630 100644
--- a/core/arch/riscv/include/sbi.h
+++ b/core/arch/riscv/include/sbi.h
@@ -3,8 +3,8 @@
  * Copyright 2022 NXP
  */
 
-#ifndef SBI_H
-#define SBI_H
+#ifndef __SBI_H
+#define __SBI_H
 
 #if defined(CFG_RISCV_SBI)
 
@@ -44,4 +44,4 @@ int sbi_boot_hart(uint32_t hart_id, paddr_t start_addr, unsigned long arg);
 
 #endif /*__ASSEMBLER__*/
 #endif /*defined(CFG_RISCV_SBI)*/
-#endif /*SBI_H*/
+#endif /*__SBI_H*/
diff --git a/core/arch/riscv/include/tee/entry_fast.h b/core/arch/riscv/include/tee/entry_fast.h
index 08ca181f492202ec250ef42bdfb0ed20d80469a4..b3f1f81b77e5a16f9e0322886a569928c8233ae5 100644
--- a/core/arch/riscv/include/tee/entry_fast.h
+++ b/core/arch/riscv/include/tee/entry_fast.h
@@ -5,8 +5,8 @@
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
-#ifndef TEE_ENTRY_FAST_H
-#define TEE_ENTRY_FAST_H
+#ifndef __TEE_ENTRY_FAST_H
+#define __TEE_ENTRY_FAST_H
 
 #include <kernel/thread.h>
 
@@ -31,4 +31,4 @@ size_t tee_entry_generic_get_api_call_count(void);
 void tee_entry_fast(struct thread_abi_args *args);
 void __tee_entry_fast(struct thread_abi_args *args);
 
-#endif /* TEE_ENTRY_FAST_H */
+#endif /* __TEE_ENTRY_FAST_H */
diff --git a/core/arch/riscv/include/tee/optee_abi.h b/core/arch/riscv/include/tee/optee_abi.h
index e65bebcac1a3a820d5d4094a4bc8742f2ab0d7e9..8528b34cac784d00a713c59edfd26c94c6b1eba1 100644
--- a/core/arch/riscv/include/tee/optee_abi.h
+++ b/core/arch/riscv/include/tee/optee_abi.h
@@ -3,8 +3,8 @@
  * Copyright 2023 NXP
  * Copyright (c) 2015-2021, Linaro Limited
  */
-#ifndef OPTEE_ABI_H
-#define OPTEE_ABI_H
+#ifndef __TEE_OPTEE_ABI_H
+#define __TEE_OPTEE_ABI_H
 
 #include <stdint.h>
 
@@ -702,4 +702,4 @@
 	((((ret) & OPTEE_ABI_RETURN_RPC_PREFIX_MASK) == \
 		OPTEE_ABI_RETURN_RPC_PREFIX))); })
 
-#endif /* OPTEE_ABI_H */
+#endif /* __TEE_OPTEE_ABI_H */
diff --git a/core/arch/riscv/include/tee/teeabi_opteed.h b/core/arch/riscv/include/tee/teeabi_opteed.h
index 50f846548bdf840e3e509a16488d8a3ac0e4cb4c..05c6aabb8d77a91940b818755305cbc481b2da2e 100644
--- a/core/arch/riscv/include/tee/teeabi_opteed.h
+++ b/core/arch/riscv/include/tee/teeabi_opteed.h
@@ -4,8 +4,8 @@
  * Copyright (c) 2014, Linaro Limited
  */
 
-#ifndef TEEABI_OPTEED_H
-#define TEEABI_OPTEED_H
+#ifndef __TEE_TEEABI_OPTEED_H
+#define __TEE_TEEABI_OPTEED_H
 
 /*
  * This file specify ABI function IDs used when returning from TEE to the
@@ -108,4 +108,4 @@
 #define TEEABI_OPTEED_RETURN_SYSTEM_RESET_DONE \
 	TEEABI_OPTEED_RV(TEEABI_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE)
 
-#endif /*TEEABI_OPTEED_H*/
+#endif /*__TEE_TEEABI_OPTEED_H*/
diff --git a/core/arch/riscv/include/tee/teeabi_opteed_macros.h b/core/arch/riscv/include/tee/teeabi_opteed_macros.h
index 6345bd613a659f181d487b999dbcc0a00a85348c..911821d5b1fbe4c0f203271dd9d67ff241d0476f 100644
--- a/core/arch/riscv/include/tee/teeabi_opteed_macros.h
+++ b/core/arch/riscv/include/tee/teeabi_opteed_macros.h
@@ -4,11 +4,11 @@
  * Copyright (c) 2014, Linaro Limited
  */
 
-#ifndef TEEABI_OPTEED_MACROS_H
-#define TEEABI_OPTEED_MACROS_H
+#ifndef __TEE_TEEABI_OPTEED_MACROS_H
+#define __TEE_TEEABI_OPTEED_MACROS_H
 
 #define TEEABI_OPTEED_RV(func_num) \
 	OPTEE_ABI_CALL_VAL(OPTEE_ABI_32, OPTEE_ABI_FAST_CALL, \
 			   OPTEE_ABI_OWNER_TRUSTED_OS_OPTEED, (func_num))
 
-#endif /*TEEABI_OPTEED_MACROS_H*/
+#endif /*__TEE_TEEABI_OPTEED_MACROS_H*/
diff --git a/core/arch/riscv/kernel/boot.c b/core/arch/riscv/kernel/boot.c
index 16c424cefa4d5676ab002e5cefb920596d156062..6530a8b5cb7d5d9120d7a2d3b5ecea5a0138a389 100644
--- a/core/arch/riscv/kernel/boot.c
+++ b/core/arch/riscv/kernel/boot.c
@@ -124,8 +124,7 @@ __weak void boot_secondary_init_intc(void)
 {
 }
 
-void boot_init_primary_early(unsigned long pageable_part __unused,
-			     unsigned long nsec_entry __unused)
+void boot_init_primary_early(void)
 {
 	unsigned long e = PADDR_INVALID;
 
@@ -135,11 +134,11 @@ void boot_init_primary_early(unsigned long pageable_part __unused,
 void boot_init_primary_late(unsigned long fdt,
 			    unsigned long tos_fw_config __unused)
 {
-	init_external_dt(fdt);
+	init_external_dt(fdt, CFG_DTB_MAX_SIZE);
 	update_external_dt();
 
 	IMSG("OP-TEE version: %s", core_v_str);
-	if (IS_ENABLED(CFG_WARN_INSECURE)) {
+	if (IS_ENABLED(CFG_INSECURE)) {
 		IMSG("WARNING: This OP-TEE configuration might be insecure!");
 		IMSG("WARNING: Please check https://optee.readthedocs.io/en/latest/architecture/porting_guidelines.html");
 	}
diff --git a/core/arch/riscv/kernel/thread_arch.c b/core/arch/riscv/kernel/thread_arch.c
index 9f40ad4e3461dbb887bc1596b692d58adebe4d6e..38299a6138411b89dab45313242539a80a21adf4 100644
--- a/core/arch/riscv/kernel/thread_arch.c
+++ b/core/arch/riscv/kernel/thread_arch.c
@@ -14,6 +14,7 @@
 #include <keep.h>
 #include <kernel/asan.h>
 #include <kernel/boot.h>
+#include <kernel/interrupt.h>
 #include <kernel/linker.h>
 #include <kernel/lockdep.h>
 #include <kernel/misc.h>
diff --git a/core/arch/riscv/plat-spike/conf.mk b/core/arch/riscv/plat-spike/conf.mk
index 27108ac696fdbff6bf052c25264b6bd0c59849c5..2047341dbb59ad1a27d2408c3e514356d341fb44 100644
--- a/core/arch/riscv/plat-spike/conf.mk
+++ b/core/arch/riscv/plat-spike/conf.mk
@@ -67,7 +67,7 @@ $(call force,CFG_SECSTOR_TA,n)
 $(call force,CFG_SHOW_CONF_ON_BOOT,n)
 $(call force,CFG_SYSCALL_WRAPPERS_MCOUNT,n)
 $(call force,CFG_BOOT_SYNC_CPU,y)
-$(call force,CFG_WARN_INSECURE,y)
+$(call force,CFG_INSECURE,y)
 $(call force,CFG_RISCV_TIME_SOURCE_RDTIME,y)
 CFG_RISCV_MTIME_RATE ?= 10000000
 CFG_TDDRAM_START ?= 0xbdb00000
diff --git a/core/arch/riscv/plat-virt/conf.mk b/core/arch/riscv/plat-virt/conf.mk
index 98b703f6cbed8c45a6d10737e1959f9832a2d580..15bc09267947a4ad84f40dc2ad144c2c46d58518 100644
--- a/core/arch/riscv/plat-virt/conf.mk
+++ b/core/arch/riscv/plat-virt/conf.mk
@@ -4,6 +4,8 @@ $(call force,CFG_CORE_LARGE_PHYS_ADDR,y)
 $(call force,CFG_TEE_CORE_DEBUG,n)
 $(call force,CFG_CORE_DYN_SHM,n)
 
+CFG_DT ?= y
+
 # Crypto flags
 $(call force,CFG_WITH_SOFTWARE_PRNG,y)
 
@@ -13,18 +15,21 @@ $(call force,CFG_WITH_STACK_CANARIES,n)
 $(call force,CFG_CORE_SANITIZE_KADDRESS,n)
 
 # Hart-related flags
-$(call force,CFG_TEE_CORE_NB_CORE,1)
-$(call force,CFG_NUM_THREADS,1)
+CFG_TEE_CORE_NB_CORE ?= 1
+CFG_NUM_THREADS ?= 1
 $(call force,CFG_BOOT_SYNC_CPU,y)
 
 # RISC-V-specific flags
 rv64-platform-isa ?= rv64imafdc_zicsr_zifencei
 
+$(call force,CFG_RISCV_M_MODE,n)
+$(call force,CFG_RISCV_S_MODE,y)
 $(call force,CFG_RISCV_PLIC,y)
 $(call force,CFG_SBI_CONSOLE,n)
 $(call force,CFG_16550_UART,y)
 $(call force,CFG_RISCV_TIME_SOURCE_RDTIME,y)
 CFG_RISCV_MTIME_RATE ?= 10000000
+CFG_RISCV_SBI ?= y
 
 # TA-related flags
 supported-ta-targets = ta_rv64
diff --git a/core/core.mk b/core/core.mk
index b023e46ac43ecfe384becfdceeaed7ac7879f95b..71c4699860a6d19a213b051defc760320f06aea4 100644
--- a/core/core.mk
+++ b/core/core.mk
@@ -15,6 +15,7 @@ PLATFORM_$(PLATFORM) := y
 PLATFORM_FLAVOR_$(PLATFORM_FLAVOR) := y
 
 $(eval $(call cfg-depends-all,CFG_PAGED_USER_TA,CFG_WITH_PAGER CFG_WITH_USER_TA))
+_CFG_CORE_ASYNC_NOTIF_DEFAULT_IMPL ?= $(CFG_CORE_ASYNC_NOTIF)
 include core/crypto.mk
 
 ifeq ($(CFG_SCMI_SCPFW),y)
diff --git a/core/crypto/cbc-mac.c b/core/crypto/cbc-mac.c
index c38b0581d146cf4cc035d3673bb4428863a0c3df..7fdcecd832827c8d7dd49dfdca218929a1c955ce 100644
--- a/core/crypto/cbc-mac.c
+++ b/core/crypto/cbc-mac.c
@@ -83,7 +83,7 @@ static TEE_Result crypto_cbc_mac_update(struct crypto_mac_ctx *ctx,
 	nblocks = MIN(len / mc->block_len,
 		      (size_t)CFG_CRYPTO_CBC_MAC_BUNDLE_BLOCKS);
 	if (nblocks > 1)
-		out_tmp = malloc(nblocks * mc->block_len);
+		out_tmp = calloc(nblocks, mc->block_len);
 
 	while (len >= mc->block_len) {
 		nblocks = MIN(len / mc->block_len,
diff --git a/core/crypto/sm3.c b/core/crypto/sm3.c
index 26bba100364fd025737a96bd9697c5484e87389a..b0d9a8e49db2e3d375efd6aef83dc773ec2cae73 100644
--- a/core/crypto/sm3.c
+++ b/core/crypto/sm3.c
@@ -50,6 +50,20 @@ void sm3_init(struct sm3_context *ctx)
 	ctx->state[7] = 0xB0FB0E4E;
 }
 
+#define SHL(x, n)	((x) << (n))
+
+static uint32_t rotl(uint32_t val, int shift)
+{
+	shift &= 0x1F;
+
+	if (shift == 0)
+		return val;
+
+	return SHL(val, shift) | (val >> (32 - shift));
+}
+
+#define ROTL(x, n)	rotl((x), (n))
+
 static void __maybe_unused sm3_process(struct sm3_context *ctx,
 				       const uint8_t data[64])
 {
@@ -87,9 +101,6 @@ static void __maybe_unused sm3_process(struct sm3_context *ctx,
 #define GG0(x, y, z)	((x) ^ (y) ^ (z))
 #define GG1(x, y, z)	(((x) & (y)) | ((~(x)) & (z)))
 
-#define SHL(x, n)	((x) << (n))
-#define ROTL(x, n)	(SHL((x), (n) & 0x1F) | ((x) >> (32 - ((n) & 0x1F))))
-
 #define P0(x)	((x) ^ ROTL((x), 9) ^ ROTL((x), 17))
 #define P1(x)	((x) ^ ROTL((x), 15) ^ ROTL((x), 23))
 
diff --git a/core/drivers/atmel_piobu.c b/core/drivers/atmel_piobu.c
index 1f6aa115f8f4e04815bdddda37f79867d9f5cb54..df06620a616ca521fd0ab859174012d0ea5df002 100644
--- a/core/drivers/atmel_piobu.c
+++ b/core/drivers/atmel_piobu.c
@@ -13,6 +13,7 @@
 #include <kernel/boot.h>
 #include <kernel/dt.h>
 #include <kernel/dt_driver.h>
+#include <kernel/interrupt.h>
 #include <kernel/pm.h>
 #include <libfdt.h>
 #include <mm/core_memprot.h>
@@ -267,8 +268,16 @@ static struct itr_handler secumod_itr_handler = {
 
 static void secumod_interrupt_init(void)
 {
-	itr_add_type_prio(&secumod_itr_handler, IRQ_TYPE_LEVEL_HIGH, 7);
-	itr_enable(secumod_itr_handler.it);
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	secumod_itr_handler.chip = interrupt_get_main_chip();
+
+	res = interrupt_add_configure_handler(&secumod_itr_handler,
+					      IRQ_TYPE_LEVEL_HIGH, 7);
+	if (res)
+		panic();
+
+	interrupt_enable(secumod_itr_handler.chip, secumod_itr_handler.it);
 }
 
 static void secumod_cfg_input_pio(uint8_t gpio_pin, uint32_t config)
diff --git a/core/drivers/atmel_saic.c b/core/drivers/atmel_saic.c
index 5989056ffda314b791de7689dfe193e040b8f879..32aa8676a1a9121907362596c377799c5374b0a1 100644
--- a/core/drivers/atmel_saic.c
+++ b/core/drivers/atmel_saic.c
@@ -269,7 +269,7 @@ TEE_Result atmel_saic_setup(void)
 
 	ret = dt_map_dev(fdt, node, &saic.base, &size, DT_MAP_AUTO);
 	if (ret) {
-		EMSG("Failed to map SAIC\n");
+		EMSG("Failed to map SAIC");
 		return TEE_ERROR_GENERIC;
 	}
 
diff --git a/core/drivers/atmel_wdt.c b/core/drivers/atmel_wdt.c
index b2aa5458d176a8cc4fbcb1dbde678111783e037e..9f1aa3047052b4172282b83fc42b69cc0e24e6be 100644
--- a/core/drivers/atmel_wdt.c
+++ b/core/drivers/atmel_wdt.c
@@ -11,8 +11,10 @@
 #include <kernel/delay.h>
 #include <kernel/dt.h>
 #include <kernel/dt_driver.h>
+#include <kernel/interrupt.h>
 #include <kernel/pm.h>
 #include <matrix.h>
+#include <mm/core_mmu.h>
 #include <sama5d2.h>
 #include <tee_api_types.h>
 
@@ -229,7 +231,8 @@ static TEE_Result wdt_node_probe(const void *fdt, int node,
 	uint32_t irq_type = 0;
 	uint32_t irq_prio = 0;
 	int it = DT_INFO_INVALID_INTERRUPT;
-	struct itr_handler *it_hdlr;
+	struct itr_handler *it_hdlr = NULL;
+	TEE_Result res = TEE_ERROR_GENERIC;
 
 	if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC)
 		return TEE_ERROR_BAD_PARAMETERS;
@@ -244,28 +247,37 @@ static TEE_Result wdt_node_probe(const void *fdt, int node,
 
 	it = dt_get_irq_type_prio(fdt, node, &irq_type, &irq_prio);
 	if (it == DT_INFO_INVALID_INTERRUPT)
-		goto err_free_wdt;
+		goto err_free;
 
-	it_hdlr = itr_alloc_add_type_prio(it, &atmel_wdt_itr_cb, 0, wdt,
-					  irq_type, irq_prio);
-	if (!it_hdlr)
-		goto err_free_wdt;
+	res = interrupt_alloc_add_conf_handler(interrupt_get_main_chip(),
+					       it, atmel_wdt_itr_cb, 0, wdt,
+					       irq_type, irq_prio, &it_hdlr);
+	if (res)
+		goto err_free;
 
 	if (dt_map_dev(fdt, node, &wdt->base, &size, DT_MAP_AUTO) < 0)
-		goto err_free_itr_handler;
+		goto err_remove_handler;
 
 	/* Get current state of the watchdog */
 	wdt->mr = io_read32(wdt->base + WDT_MR) & WDT_MR_WDDIS;
 
 	atmel_wdt_init_hw(wdt);
-	itr_enable(it);
+	interrupt_enable(it_hdlr->chip, it_hdlr->it);
+
+	res = watchdog_register(&wdt->chip);
+	if (res)
+		goto err_disable_unmap;
+
 	atmel_wdt_register_pm(wdt);
 
-	return watchdog_register(&wdt->chip);
+	return TEE_SUCCESS;
 
-err_free_itr_handler:
-	itr_free(it_hdlr);
-err_free_wdt:
+err_disable_unmap:
+	interrupt_disable(it_hdlr->chip, it_hdlr->it);
+	core_mmu_remove_mapping(MEM_AREA_IO_SEC, (void *)wdt->base, size);
+err_remove_handler:
+	interrupt_remove_free_handler(it_hdlr);
+err_free:
 	free(wdt);
 
 	return TEE_ERROR_GENERIC;
diff --git a/core/drivers/bcm_hwrng.c b/core/drivers/bcm_hwrng.c
index d9351c1c1a6fa6e20ee3c2dae6493b2ea45c3c3a..96e3097c38baeabb630237b1a25890d38f54ccad 100644
--- a/core/drivers/bcm_hwrng.c
+++ b/core/drivers/bcm_hwrng.c
@@ -76,7 +76,7 @@ static TEE_Result bcm_hwrng_init(void)
 
 	bcm_hwrng_reset();
 
-	DMSG("bcm_hwrng init done\n");
+	DMSG("bcm_hwrng init done");
 	return TEE_SUCCESS;
 }
 
diff --git a/core/drivers/clk/clk.c b/core/drivers/clk/clk.c
index 00cb57e267884f5cdb2bbec408fd751e187f7129..8f5a6a5d28b22c86a50af8816548f978eef79e5c 100644
--- a/core/drivers/clk/clk.c
+++ b/core/drivers/clk/clk.c
@@ -1,8 +1,10 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
  * Copyright (c) 2021, Bootlin
+ * Copyright (c) 2023, STMicroelectronics
  */
 
+#include <config.h>
 #include <drivers/clk.h>
 #include <kernel/boot.h>
 #include <kernel/panic.h>
@@ -10,10 +12,15 @@
 #include <libfdt.h>
 #include <malloc.h>
 #include <stddef.h>
+#include <stdio.h>
 
 /* Global clock tree lock */
 static unsigned int clk_lock = SPINLOCK_UNLOCK;
 
+#ifdef CFG_DRIVERS_CLK_PRINT_TREE
+static SLIST_HEAD(, clk) clock_list = SLIST_HEAD_INITIALIZER(clock_list);
+#endif
+
 struct clk *clk_alloc(const char *name, const struct clk_ops *ops,
 		      struct clk **parent_clks, size_t parent_count)
 {
@@ -42,7 +49,7 @@ void clk_free(struct clk *clk)
 
 static bool __maybe_unused clk_check(struct clk *clk)
 {
-	if (!clk->ops)
+	if (!clk || !clk->ops)
 		return false;
 
 	if (clk->ops->set_parent && !clk->ops->get_parent)
@@ -101,6 +108,10 @@ TEE_Result clk_register(struct clk *clk)
 	clk_init_parent(clk);
 	clk_compute_rate_no_lock(clk);
 
+#ifdef CFG_DRIVERS_CLK_PRINT_TREE
+	SLIST_INSERT_HEAD(&clock_list, clk, link);
+#endif
+
 	DMSG("Registered clock %s, freq %lu", clk->name, clk_get_rate(clk));
 
 	return TEE_SUCCESS;
@@ -310,3 +321,169 @@ TEE_Result clk_get_rates_array(struct clk *clk, size_t start_index,
 
 	return clk->ops->get_rates_array(clk, start_index, rates, nb_elts);
 }
+
+/* Return updated message buffer position of NULL on failure */
+static __printf(3, 4) char *add_msg(char *cur, char *end, const char *fmt, ...)
+{
+	va_list ap = { };
+	int max_len = end - cur;
+	int ret = 0;
+
+	va_start(ap, fmt);
+	ret = vsnprintf(cur, max_len, fmt, ap);
+	va_end(ap);
+
+	if (ret < 0 || ret >= max_len)
+		return NULL;
+
+	return cur + ret;
+}
+
+static struct clk *find_next_clk(struct clk *parent __maybe_unused,
+				 struct clk *sibling __maybe_unused)
+{
+	struct clk *clk = NULL;
+
+#ifdef CFG_DRIVERS_CLK_PRINT_TREE
+	if (sibling)
+		clk = SLIST_NEXT(sibling, link);
+	else
+		clk = SLIST_FIRST(&clock_list);
+
+	while (clk && clk->parent != parent)
+		clk = SLIST_NEXT(clk, link);
+#endif
+
+	return clk;
+}
+
+static bool clk_is_parent_last_child(struct clk *clk)
+{
+	return !find_next_clk(clk->parent, clk);
+}
+
+static bool indent_last_node_already_found(struct clk *node_clk,
+					   int node_indent, int cur_indent)
+{
+	struct clk *clk = node_clk;
+	int n = 0;
+
+	/* Find parent clock at level @node_indent - @cur_indent - 1 */
+	for (n = 0; n < node_indent - cur_indent - 1; n++)
+		clk = clk->parent;
+
+	return clk_is_parent_last_child(clk);
+}
+
+static void __maybe_unused print_clk(struct clk *clk, int indent)
+{
+	static const char * const rate_unit[] = { "Hz", "kHz", "MHz", "GHz" };
+	int max_unit = ARRAY_SIZE(rate_unit);
+	unsigned long rate = 0;
+	char msg_buf[128] = { };
+	char *msg_end = msg_buf + sizeof(msg_buf);
+	char *msg = msg_buf;
+	int n = 0;
+
+	/*
+	 * Currently prints the clock state based on the clock refcount.
+	 * A future change could print the hardware clock state when
+	 * related clock driver provides a struct clk_ops::is_enabled handler
+	 */
+
+	if (indent) {
+		/* Indent for root clock level */
+		msg = add_msg(msg, msg_end, "   ");
+		if (!msg)
+			goto out;
+
+		/* Indent for root parent to clock parent levels */
+		for (n = 0; n < indent - 1; n++) {
+			if (indent_last_node_already_found(clk, indent, n))
+				msg = add_msg(msg, msg_end, "    ");
+			else
+				msg = add_msg(msg, msg_end, "|   ");
+
+			if (!msg)
+				goto out;
+		}
+
+		/* Clock indentation */
+		if (clk_is_parent_last_child(clk))
+			msg = add_msg(msg, msg_end, "`-- ");
+		else
+			msg = add_msg(msg, msg_end, "|-- ");
+	} else {
+		/* Root clock indentation */
+		msg = add_msg(msg, msg_end, "o- ");
+	}
+	if (!msg)
+		goto out;
+
+	rate = clk_get_rate(clk);
+	for (n = 1; rate && !(rate % 1000) && n < max_unit; n++)
+		rate /= 1000;
+
+	msg = add_msg(msg, msg_end, "%s \t(%3s / refcnt %u / %ld %s)",
+		      clk_get_name(clk),
+		      refcount_val(&clk->enabled_count) ? "on " : "off",
+		      refcount_val(&clk->enabled_count),
+		      rate, rate_unit[n - 1]);
+	if (!msg)
+		goto out;
+
+out:
+	if (!msg)
+		snprintf(msg_end - 4, 4, "...");
+
+	DMSG("%s", msg_buf);
+}
+
+static void print_tree(void)
+{
+	struct clk *clk = NULL;
+	struct clk *parent = NULL;
+	struct clk *next = NULL;
+	int indent = -1;
+
+#ifdef CFG_DRIVERS_CLK_PRINT_TREE
+	if (SLIST_EMPTY(&clock_list)) {
+		DMSG("-- No registered clock");
+		return;
+	}
+#endif
+
+	while (true) {
+		next = find_next_clk(parent, clk);
+		if (next) {
+			print_clk(next, indent + 1);
+			/* Enter the subtree of the next clock */
+			parent = next;
+			indent++;
+			clk = NULL;
+		} else {
+			/*
+			 * We've processed all children at this level.
+			 * If parent is NULL we're at the top and are done.
+			 */
+			if (!parent)
+				break;
+			/*
+			 * Move up one level to resume with the next
+			 * child clock of the parent.
+			 */
+			clk = parent;
+			parent = clk->parent;
+			indent--;
+		}
+	}
+}
+
+void clk_print_tree(void)
+{
+	if (IS_ENABLED(CFG_DRIVERS_CLK_PRINT_TREE) &&
+	    TRACE_LEVEL >= TRACE_DEBUG) {
+		DMSG("Clock tree summary (informative):");
+		print_tree();
+	}
+}
diff --git a/core/drivers/crypto/caam/acipher/caam_dsa.c b/core/drivers/crypto/caam/acipher/caam_dsa.c
index d60bb8e89e3b2ff537fc8b3d3b506ff53e294db3..8c0dbf055e213ac7da0c410b177c67db1533d069 100644
--- a/core/drivers/crypto/caam/acipher/caam_dsa.c
+++ b/core/drivers/crypto/caam/acipher/caam_dsa.c
@@ -579,7 +579,7 @@ static TEE_Result do_sign(struct drvcrypt_sign_data *sdata, size_t l_bytes,
 	/* Message length */
 	caam_desc_add_word(desc, sdata->message.length);
 
-	caam_desc_add_word(desc, DSA_SIGN(DL));
+	caam_desc_add_word(desc, DSA_SIGN(DL, HASHED));
 
 	desclen = caam_desc_get_len(desc);
 	caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
@@ -721,7 +721,7 @@ static TEE_Result do_verify(struct drvcrypt_sign_data *sdata, size_t l_bytes,
 	/* Message length */
 	caam_desc_add_word(desc, sdata->message.length);
 
-	caam_desc_add_word(desc, DSA_VERIFY(DL));
+	caam_desc_add_word(desc, DSA_VERIFY(DL, HASHED));
 	desclen = caam_desc_get_len(desc);
 	caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
 
diff --git a/core/drivers/crypto/caam/acipher/caam_ecc.c b/core/drivers/crypto/caam/acipher/caam_ecc.c
index 62c113c409f4639995ded2f683c6fc8e1636e45b..b9c2cde8817dc64f9ce667718c8dc7b32cf957f4 100644
--- a/core/drivers/crypto/caam/acipher/caam_ecc.c
+++ b/core/drivers/crypto/caam/acipher/caam_ecc.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright 2018-2021 NXP
+ * Copyright 2018-2021, 2024 NXP
  *
  * Implementation of ECC functions
  */
@@ -322,6 +322,63 @@ out:
 	return ret;
 }
 
+/*
+ * Check if MES_REP to be sent in descriptor is 00.
+ * Only required in case message length and key size is more than 40bytes
+ * because of limitation of Class 2 context register size on i.MX8M series.
+ * Example case below:
+ * When we try to do signature with P384-SHA384, in this case the key size
+ * will be 48bytes and Message size will also be 48bytes.
+ * This will work only when we set MES_REP = 0 in descriptor,
+ * but in this case, we don't need the padding to be done on the message.
+ *
+ * @msg_length: Message Length in bytes
+ * @key_size: Key size in bytes
+ */
+static bool msg_mes_rep(size_t msg_length, size_t key_size)
+{
+	return IS_ENABLED(CFG_NXP_CAAM_C2_CTX_REG_WA) && msg_length > 40 &&
+	       key_size > 40;
+}
+
+/*
+ * Check if padding is required on message to make it of same length
+ * as that of key size.
+ * Only required in case message length and key size is more than 40bytes
+ * because of limitation of Class 2 context register size on i.MX8M series.
+ * So this will be applicable on P384 and P521 ECC curves because these
+ * curves have key_size more than 40bytes.
+ *
+ * @msg_length: Message Length in bytes
+ * @key_size: Key size in bytes
+ */
+static bool padding_required(size_t msg_length, size_t key_size)
+{
+	return msg_mes_rep(msg_length, key_size) && msg_length < key_size;
+}
+
+/*
+ * Add padding of 00s in start of message
+ *
+ * @buf: Buffer in which padded message will be placed.
+ * @data: Original message
+ * @msg_length: Message Length in bytes
+ * @key_size: Key Size in bytes
+ */
+static TEE_Result add_padding(struct caambuf *buf, uint8_t *data,
+			      size_t msg_length, size_t key_size)
+{
+	enum caam_status retstatus = CAAM_FAILURE;
+
+	retstatus = caam_calloc_align_buf(buf, key_size);
+	if (retstatus != CAAM_NO_ERROR)
+		return caam_status_to_tee_result(retstatus);
+
+	memcpy(buf->data + key_size - msg_length, data, msg_length);
+
+	return TEE_SUCCESS;
+}
+
 /*
  * Signature of ECC message
  * Note the message to sign is already hashed
@@ -343,6 +400,7 @@ static TEE_Result do_sign(struct drvcrypt_sign_data *sdata)
 	struct caamdmaobj sign_c = { };
 	struct caamdmaobj sign_d = { };
 	uint32_t pdb_sgt_flags = 0;
+	struct caambuf caambuf_msg = { };
 
 	ECC_TRACE("ECC Signature");
 
@@ -365,19 +423,35 @@ static TEE_Result do_sign(struct drvcrypt_sign_data *sdata)
 		goto out;
 	}
 
-	/* Prepare the input message CAAM Descriptor entry */
-	ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data,
-				       sdata->message.length);
-	if (ret)
-		goto out;
+	ECC_DUMPBUF("Message", sdata->message.data, sdata->message.length);
+
+	if (padding_required(sdata->message.length, sdata->size_sec)) {
+		ret = add_padding(&caambuf_msg, sdata->message.data,
+				  sdata->message.length, sdata->size_sec);
+		if (ret)
+			goto out;
+
+		/* Prepare the input message CAAM Descriptor entry */
+		ret = caam_dmaobj_input_sgtbuf(&msg, caambuf_msg.data,
+					       caambuf_msg.length);
+		if (ret)
+			goto out;
+
+		ECC_DUMPBUF("Padded Message", caambuf_msg.data,
+			    caambuf_msg.length);
+	} else {
+		/* Prepare the input message CAAM Descriptor entry */
+		ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data,
+					       sdata->message.length);
+		if (ret)
+			goto out;
+	}
 
 	if (msg.sgtbuf.sgt_type)
 		pdb_sgt_flags |= PDB_SGT_PKSIGN_MSG;
 
 	caam_dmaobj_cache_push(&msg);
 
-	ECC_DUMPBUF("Message", sdata->message.data, sdata->message.length);
-
 	/*
 	 * ReAllocate the signature result buffer with a maximum size
 	 * of the roundup to 16 bytes of the secure size in bytes if
@@ -420,10 +494,15 @@ static TEE_Result do_sign(struct drvcrypt_sign_data *sdata)
 	caam_desc_add_ptr(desc, sign_c.sgtbuf.paddr);
 	/* Signature 2nd part */
 	caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr);
-	/* Message length */
-	caam_desc_add_word(desc, sdata->message.length);
 
-	caam_desc_add_word(desc, DSA_SIGN(ECC));
+	if (msg_mes_rep(sdata->message.length, sdata->size_sec)) {
+		caam_desc_add_word(desc, DSA_SIGN(ECC, MES_REP));
+	} else {
+		/* Message length */
+		caam_desc_add_word(desc, sdata->message.length);
+
+		caam_desc_add_word(desc, DSA_SIGN(ECC, HASHED));
+	}
 
 	desclen = caam_desc_get_len(desc);
 	caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
@@ -452,6 +531,7 @@ out:
 	caam_dmaobj_free(&msg);
 	caam_dmaobj_free(&sign_d);
 	caam_dmaobj_free(&sign_c);
+	caam_free_buf(&caambuf_msg);
 
 	return ret;
 }
@@ -477,6 +557,7 @@ static TEE_Result do_verify(struct drvcrypt_sign_data *sdata)
 	struct caamdmaobj sign_c = { };
 	struct caamdmaobj sign_d = { };
 	uint32_t pdb_sgt_flags = 0;
+	struct caambuf caambuf_msg = { };
 
 	ECC_TRACE("ECC Verify");
 
@@ -499,11 +580,24 @@ static TEE_Result do_verify(struct drvcrypt_sign_data *sdata)
 		goto out;
 	}
 
-	/* Prepare the input message CAAM Descriptor entry */
-	ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data,
-				       sdata->message.length);
-	if (ret)
-		goto out;
+	if (padding_required(sdata->message.length, sdata->size_sec)) {
+		ret = add_padding(&caambuf_msg, sdata->message.data,
+				  sdata->message.length, sdata->size_sec);
+		if (ret)
+			goto out;
+
+		/* Prepare the input message CAAM Descriptor entry */
+		ret = caam_dmaobj_input_sgtbuf(&msg, caambuf_msg.data,
+					       caambuf_msg.length);
+		if (ret)
+			goto out;
+	} else {
+		/* Prepare the input message CAAM Descriptor entry */
+		ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data,
+					       sdata->message.length);
+		if (ret)
+			goto out;
+	}
 
 	if (msg.sgtbuf.sgt_type)
 		pdb_sgt_flags |= PDB_SGT_PKVERIF_MSG;
@@ -556,10 +650,16 @@ static TEE_Result do_verify(struct drvcrypt_sign_data *sdata)
 	caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr);
 	/* Temporary buffer */
 	caam_desc_add_ptr(desc, tmp.paddr);
-	/* Message length */
-	caam_desc_add_word(desc, sdata->message.length);
 
-	caam_desc_add_word(desc, DSA_VERIFY(ECC));
+	if (msg_mes_rep(sdata->message.length, sdata->size_sec)) {
+		caam_desc_add_word(desc, DSA_VERIFY(ECC, MES_REP));
+	} else {
+		/* Message length */
+		caam_desc_add_word(desc, sdata->message.length);
+
+		caam_desc_add_word(desc, DSA_VERIFY(ECC, HASHED));
+	}
+
 	desclen = caam_desc_get_len(desc);
 	caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
 
@@ -587,6 +687,7 @@ out:
 	caam_dmaobj_free(&msg);
 	caam_dmaobj_free(&sign_c);
 	caam_dmaobj_free(&sign_d);
+	caam_free_buf(&caambuf_msg);
 
 	return ret;
 }
diff --git a/core/drivers/crypto/caam/caam_jr.c b/core/drivers/crypto/caam/caam_jr.c
index eeb64f02f8fe4b7481b2095d2bd84925733a7d99..a3bf68a329e5d14defc07b59335b9a5fc231717d 100644
--- a/core/drivers/crypto/caam/caam_jr.c
+++ b/core/drivers/crypto/caam/caam_jr.c
@@ -159,7 +159,7 @@ end_alloc:
 static enum itr_return caam_jr_irqhandler(struct itr_handler *handler)
 {
 	JR_TRACE("Disable the interrupt");
-	itr_disable(handler->it);
+	interrupt_disable(handler->chip, handler->it);
 
 	/* Send a signal to exit WFE loop */
 	sev();
@@ -582,13 +582,17 @@ enum caam_status caam_jr_init(struct caam_jrcfg *jrcfg)
 	 * Prepare the interrupt handler to secure the interrupt even
 	 * if the interrupt is not used
 	 */
+	jr_privdata->it_handler.chip = interrupt_get_main_chip();
 	jr_privdata->it_handler.it = jrcfg->it_num;
 	jr_privdata->it_handler.flags = ITRF_TRIGGER_LEVEL;
 	jr_privdata->it_handler.handler = caam_jr_irqhandler;
 	jr_privdata->it_handler.data = jr_privdata;
 
 #if defined(CFG_NXP_CAAM_RUNTIME_JR) && defined(CFG_CAAM_ITR)
-	itr_add(&jr_privdata->it_handler);
+	if (interrupt_add_handler(&jr_privdata->it_handler)) {
+		retstatus = CAAM_FAILURE;
+		goto end_init;
+	}
 #endif
 	caam_hal_jr_enable_itr(jr_privdata->baseaddr);
 
diff --git a/core/drivers/crypto/caam/caam_rng.c b/core/drivers/crypto/caam/caam_rng.c
index fa81c222f38bd673a163e3c5eb42bf4ed8fb2eac..a2a8fdd71e945001bc5c00beb31c7a680ccb6eb9 100644
--- a/core/drivers/crypto/caam/caam_rng.c
+++ b/core/drivers/crypto/caam/caam_rng.c
@@ -60,6 +60,7 @@ struct rngdata {
 struct rng_privdata {
 	vaddr_t baseaddr;                       /* RNG base address */
 	bool instantiated;                      /* RNG instantiated */
+	bool pr_enabled;			/* RNG prediction resistance */
 	struct rngdata databuf[RNG_DATABUF_NB]; /* RNG Data generation */
 	uint8_t dataidx;                        /* Current RNG Data buffer */
 };
@@ -158,6 +159,10 @@ static enum caam_status prepare_gen_desc(struct rngdata *rng)
 {
 	paddr_t paddr = 0;
 	uint32_t *desc = NULL;
+	uint32_t op = RNG_GEN_DATA;
+
+	if (rng_privdata->pr_enabled)
+		op |= ALGO_RNG_PR;
 
 	/* Convert the buffer virtual address to physical address */
 	paddr = virt_to_phys(rng->data);
@@ -168,7 +173,7 @@ static enum caam_status prepare_gen_desc(struct rngdata *rng)
 
 	caam_desc_init(desc);
 	caam_desc_add_word(desc, DESC_HEADER(0));
-	caam_desc_add_word(desc, RNG_GEN_DATA);
+	caam_desc_add_word(desc, op);
 	caam_desc_add_word(desc, FIFO_ST(RNG_TO_MEM, rng->size));
 	caam_desc_add_ptr(desc, paddr);
 
@@ -523,8 +528,14 @@ enum caam_status caam_rng_instantiation(void)
 	} while (retstatus == CAAM_NO_ERROR);
 
 end_inst:
-	if (retstatus == CAAM_NO_ERROR)
+	if (retstatus == CAAM_NO_ERROR) {
 		rng_privdata->instantiated = true;
+		rng_privdata->pr_enabled =
+			caam_hal_rng_pr_enabled(rng_privdata->baseaddr);
+
+		RNG_TRACE("RNG prediction resistance is %sabled",
+			  rng_privdata->pr_enabled ? "en" : "dis");
+	}
 
 	caam_free_desc(&desc);
 
@@ -556,6 +567,27 @@ enum caam_status caam_rng_init(vaddr_t ctrl_addr)
 }
 
 #ifdef CFG_NXP_CAAM_RNG_DRV
+#ifdef CFG_WITH_SOFTWARE_PRNG
+void plat_rng_init(void)
+{
+	TEE_Result res = TEE_SUCCESS;
+	uint8_t buf[64] = { };
+
+	res = do_rng_read(buf, sizeof(buf));
+	if (res) {
+		EMSG("Failed to read RNG: %#" PRIx32, res);
+		panic();
+	}
+
+	res = crypto_rng_init(buf, sizeof(buf));
+	if (res) {
+		EMSG("Failed to initialize RNG: %#" PRIx32, res);
+		panic();
+	}
+
+	RNG_TRACE("PRNG seeded from CAAM");
+}
+#else /* !CFG_WITH_SOFTWARE_PRNG */
 TEE_Result hw_get_random_bytes(void *buf, size_t blen)
 {
 	if (!buf)
@@ -567,4 +599,5 @@ TEE_Result hw_get_random_bytes(void *buf, size_t blen)
 void plat_rng_init(void)
 {
 }
-#endif
+#endif /* CFG_WITH_SOFTWARE_PRNG */
+#endif /* CFG_NXP_CAAM_RNG_DRV */
diff --git a/core/drivers/crypto/caam/crypto.mk b/core/drivers/crypto/caam/crypto.mk
index 8483680fd164fae798fc454da767a58253647f56..13f8e4cc070e93b079829dd799f3e4e60a8d5770 100644
--- a/core/drivers/crypto/caam/crypto.mk
+++ b/core/drivers/crypto/caam/crypto.mk
@@ -71,8 +71,8 @@ caam-crypto-drivers += RSA DSA ECC DH MATH
 else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8dxl-flavorlist)))
 $(call force, CFG_CAAM_SIZE_ALIGN,4)
 $(call force, CFG_JR_BLOCK_SIZE,0x10000)
-$(call force, CFG_JR_INDEX,2)
-$(call force, CFG_JR_INT,355)
+$(call force, CFG_JR_INDEX,3)
+$(call force, CFG_JR_INT,356)
 $(call force, CFG_NXP_CAAM_SGT_V1,y)
 $(call force, CFG_CAAM_JR_DISABLE_NODE,n)
 caam-crypto-drivers += RSA DSA ECC DH MATH
@@ -83,6 +83,11 @@ $(call force, CFG_JR_INDEX,2)
 $(call force, CFG_JR_INT,146)
 $(call force, CFG_NXP_CAAM_SGT_V1,y)
 $(call force, CFG_JR_HAB_INDEX,0)
+# There is a limitation on i.MX8M platforms regarding ECDSA Sign/Verify
+# Size of Class 2 Context register is 40bytes, because of which sign/verify
+# of a hash of more than 40bytes fails. So a workaround is implemented for
+# this issue, controlled by CFG_NXP_CAAM_C2_CTX_REG_WA flag.
+$(call force, CFG_NXP_CAAM_C2_CTX_REG_WA,y)
 caam-drivers += MP DEK
 caam-crypto-drivers += RSA DSA ECC DH MATH
 else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8ulp-flavorlist)))
@@ -143,9 +148,9 @@ CFG_CAAM_JR_DISABLE_NODE ?= y
 # Enable CAAM non-crypto drivers
 $(foreach drv, $(caam-drivers), $(eval CFG_NXP_CAAM_$(drv)_DRV ?= y))
 
-# Disable software RNG if CAAM RNG driver is enabled
+# Prefer CAAM HWRNG over PRNG seeded by CAAM
 ifeq ($(CFG_NXP_CAAM_RNG_DRV), y)
-$(call force, CFG_WITH_SOFTWARE_PRNG,n,Mandated by CFG_NXP_CAAM_RNG_DRV)
+CFG_WITH_SOFTWARE_PRNG ?= n
 endif
 
 # DEK driver requires the SM driver to be enabled
diff --git a/core/drivers/crypto/caam/hal/common/hal_jr.c b/core/drivers/crypto/caam/hal/common/hal_jr.c
index 1d344b48bf0d80034bd93471368744e16c01fd01..3fab56535f0d9927e6e4fda4a4601e859d8e789b 100644
--- a/core/drivers/crypto/caam/hal/common/hal_jr.c
+++ b/core/drivers/crypto/caam/hal/common/hal_jr.c
@@ -50,7 +50,7 @@ enum caam_status caam_hal_jr_reset(vaddr_t baseaddr)
 	} while ((reg_val == JRINTR_HALT_ONGOING) && --timeout);
 
 	if (!timeout || reg_val != JRINTR_HALT_DONE) {
-		EMSG("Failed to flush job ring\n");
+		EMSG("Failed to flush job ring");
 		return CAAM_FAILURE;
 	}
 
@@ -63,7 +63,7 @@ enum caam_status caam_hal_jr_reset(vaddr_t baseaddr)
 	} while ((reg_val & JRX_JRCR_RESET) && --timeout);
 
 	if (!timeout) {
-		EMSG("Failed to reset job ring\n");
+		EMSG("Failed to reset job ring");
 		return CAAM_FAILURE;
 	}
 
diff --git a/core/drivers/crypto/caam/hal/common/hal_rng.c b/core/drivers/crypto/caam/hal/common/hal_rng.c
index c98ee4d7769c8b358371b2dfa7891f66d8723b10..5f8f0afc2910bc8e51f136c68169e1d1b60c8a0d 100644
--- a/core/drivers/crypto/caam/hal/common/hal_rng.c
+++ b/core/drivers/crypto/caam/hal/common/hal_rng.c
@@ -62,6 +62,16 @@ bool caam_hal_rng_key_loaded(vaddr_t baseaddr)
 	return io_caam_read32(baseaddr + RNG_STA) & RNG_STA_SKVN;
 }
 
+bool caam_hal_rng_pr_enabled(vaddr_t baseaddr)
+{
+	uint32_t bitmask = RNG_STA_PR0;
+
+	if (caam_hal_rng_get_nb_sh(baseaddr) > 1)
+		bitmask |= RNG_STA_PR1;
+
+	return (io_caam_read32(baseaddr + RNG_STA) & bitmask) == bitmask;
+}
+
 enum caam_status caam_hal_rng_kick(vaddr_t baseaddr, uint32_t inc_delay)
 {
 	uint32_t val = 0;
diff --git a/core/drivers/crypto/caam/hal/common/registers/rng_regs.h b/core/drivers/crypto/caam/hal/common/registers/rng_regs.h
index f96aceee16303fdf34ae3d6ec95895825d05b8ed..260fef5f5db0e3c704a9ef8a9bff604575b5383b 100644
--- a/core/drivers/crypto/caam/hal/common/registers/rng_regs.h
+++ b/core/drivers/crypto/caam/hal/common/registers/rng_regs.h
@@ -115,5 +115,7 @@
 #define RNG_STA_SKVN		BIT32(30)
 #define RNG_STA_IF1			BIT32(1)
 #define RNG_STA_IF0			BIT32(0)
+#define RNG_STA_PR0			BIT32(4)
+#define RNG_STA_PR1			BIT32(5)
 
 #endif /* __RNG_REGS_H__ */
diff --git a/core/drivers/crypto/caam/include/caam_desc_defines.h b/core/drivers/crypto/caam/include/caam_desc_defines.h
index c6f8f1d603c797e95a4cc94d25bfdd8a0390ff82..f9b6349fdfcd2c26004cc96c47737b729749fbc2 100644
--- a/core/drivers/crypto/caam/include/caam_desc_defines.h
+++ b/core/drivers/crypto/caam/include/caam_desc_defines.h
@@ -329,6 +329,7 @@
  * ECC Protocol Information
  */
 #define PROT_PK_MSG(type)	SHIFT_U32(PROT_PK_MSG_##type, 10)
+#define PROT_PK_MSG_MES_REP	0
 #define PROT_PK_MSG_HASHED	2
 #define PROT_PK_TYPE(type)	SHIFT_U32(PROT_PK_##type, 1)
 #define PROT_PK_DL		0
diff --git a/core/drivers/crypto/caam/include/caam_desc_helper.h b/core/drivers/crypto/caam/include/caam_desc_helper.h
index bf0de2c90943274eef2a90c41099477380eb7205..ca71cdcf3ddcd8d53a81a4f231210a5ee8b2b7b0 100644
--- a/core/drivers/crypto/caam/include/caam_desc_helper.h
+++ b/core/drivers/crypto/caam/include/caam_desc_helper.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: BSD-2-Clause */
 /*
- * Copyright 2018-2021 NXP
+ * Copyright 2018-2021, 2024 NXP
  *
  * Brief   CAAM Descriptor interface.
  */
@@ -494,18 +494,18 @@ static inline void dump_desc(uint32_t *desc)
 	(CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(PKKEY) | PROT_PK_TYPE(type))
 
 /*
- * DSA/ECDSA signature of message hashed
+ * DSA/ECDSA signature of message of msg_type
  */
-#define DSA_SIGN(type)                                                         \
-	(CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(DSASIGN) | PROT_PK_MSG(HASHED) |  \
-	 PROT_PK_TYPE(type))
+#define DSA_SIGN(type, msg_type)                        \
+	(CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(DSASIGN) | \
+	 PROT_PK_MSG(msg_type) | PROT_PK_TYPE(type))
 
 /*
- * DSA/ECDSA signature verify message hashed
+ * DSA/ECDSA signature verify message of msg_type
  */
-#define DSA_VERIFY(type)                                                       \
-	(CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(DSAVERIFY) |                      \
-	 PROT_PK_MSG(HASHED) | PROT_PK_TYPE(type))
+#define DSA_VERIFY(type, msg_type)                        \
+	(CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(DSAVERIFY) | \
+	 PROT_PK_MSG(msg_type) | PROT_PK_TYPE(type))
 
 /*
  * DH/ECC Shared Secret
diff --git a/core/drivers/crypto/caam/include/caam_hal_rng.h b/core/drivers/crypto/caam/include/caam_hal_rng.h
index 9b87215a828e084775d99c1aaa00cb041f812e52..ef5e19aeb72ddb657fed02d823e43cf426ef5ce9 100644
--- a/core/drivers/crypto/caam/include/caam_hal_rng.h
+++ b/core/drivers/crypto/caam/include/caam_hal_rng.h
@@ -39,6 +39,13 @@ uint32_t caam_hal_rng_get_sh_status(vaddr_t baseaddr);
  */
 bool caam_hal_rng_key_loaded(vaddr_t baseaddr);
 
+/*
+ * Returns true if the RNG was initialized for prediction resistance
+ *
+ * @baseaddr  RNG Base Address
+ */
+bool caam_hal_rng_pr_enabled(vaddr_t baseaddr);
+
 /*
  * Configures the RNG entropy delay
  *
diff --git a/core/drivers/crypto/caam/include/caam_sm.h b/core/drivers/crypto/caam/include/caam_sm.h
index 20acc487b5aeb74dc30fa7a3ec0ceb3293fb5e02..5dee43300856df9d85bd82b0b9968afef572e5b5 100644
--- a/core/drivers/crypto/caam/include/caam_sm.h
+++ b/core/drivers/crypto/caam/include/caam_sm.h
@@ -61,7 +61,8 @@ caam_sm_set_access_perm(const struct caam_sm_page_desc *page_desc,
  *
  * @sm_page_descriptor    Secure Memory page
  */
-TEE_Result caam_sm_free(const struct caam_sm_page_desc *sm_page_descriptor);
+enum caam_status
+caam_sm_free(const struct caam_sm_page_desc *sm_page_descriptor);
 
 #else
 static inline enum caam_status caam_sm_init(struct caam_jrcfg *jrcfg __unused)
diff --git a/core/drivers/crypto/hisilicon/hisi_qm.c b/core/drivers/crypto/hisilicon/hisi_qm.c
new file mode 100644
index 0000000000000000000000000000000000000000..daf7901a857fd67433258ca14c9c5f42d99eecda
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/hisi_qm.c
@@ -0,0 +1,884 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright 2022-2023 HiSilicon Limited.
+ * Kunpeng hardware accelerator queue management module.
+ */
+#include "hisi_qm.h"
+
+#define QM_FVT_CFG_RDY_BIT	0x1
+/* Doorbell */
+#define QM_DOORBELL_SQ_CQ_BASE	0x1000
+#define QM_DB_CMD_SHIFT		12
+#define QM_DB_RAND_DATA_SHIFT	16
+#define QM_DB_INDEX_SHIFT	32
+#define QM_DB_PRIORITY_SHIFT	48
+#define QM_DB_RAND_DATA		0x5a
+#define QM_DOORBELL_CMD_SQ	0
+#define QM_DOORBELL_CMD_CQ	1
+/* Mailbox */
+#define QM_MAILBOX_BASE		0x300
+#define QM_MAILBOX_DATA_ADDR_L	0x304
+#define QM_MAILBOX_DATA_ADDR_H	0x308
+#define QM_MB_BUSY_SHIFT	13
+#define QM_MB_BUSY_BIT		BIT32(QM_MB_BUSY_SHIFT)
+#define QM_MB_OP_SHIFT		14
+#define QM_MB_OP_WR		0
+#define QM_MB_OP_RD		1
+#define QM_MB_STATUS_MASK	GENMASK_32(12, 9)
+#define QM_MB_WAIT_READY_CNT	10
+#define QM_MB_WAIT_MAX_CNT	21000
+#define QM_MB_WAIT_PERIOD	200
+/* XQC_VFT */
+#define QM_VFT_CFG_OP_ENABLE	0x100054
+#define QM_VFT_CFG_OP_WR	0x100058
+#define QM_VFT_CFG_TYPE		0x10005c
+#define QM_VFT_CFG_ADDRESS	0x100060
+#define QM_VFT_CFG_DATA_L	0x100064
+#define QM_VFT_CFG_DATA_H	0x100068
+#define QM_VFT_CFG_RDY		0x10006c
+#define QM_SQC_VFT		0
+#define QM_CQC_VFT		1
+#define QM_SQC_VFT_START_SQN_SHIFT 28
+#define QM_SQC_VFT_VALID	BIT64(44)
+#define QM_SQC_VFT_SQ_NUM_SHIFT 45
+#define QM_CQC_VFT_VALID	BIT(28)
+#define QM_VFT_WRITE		0
+#define QM_VFT_READ		1
+#define QM_SQC_VFT_BASE_MASK	0x3ff
+#define QM_SQC_VFT_NUM_MASK	0x3ff
+/* QM INIT */
+#define QM_MEM_START_INIT	0x100040
+#define QM_MEM_INIT_DONE	0x100044
+#define QM_VF_AEQ_INT_MASK	0x4
+#define QM_VF_AEQ_INT_MASK_EN	0x1
+#define QM_VF_EQ_INT_MASK	0xc
+#define QM_VF_EQ_INT_MASK_EN	0x1
+#define QM_ARUSER_M_CFG_1	0x100088
+#define QM_ARUSER_M_CFG_ENABLE	0x100090
+#define QM_AWUSER_M_CFG_1	0x100098
+#define QM_AWUSER_M_CFG_ENABLE	0x1000a0
+#define QM_AXUSER_CFG		0x40001070
+#define AXUSER_M_CFG_ENABLE	0x7ffffc
+#define QM_AXI_M_CFG		0x1000ac
+#define AXI_M_CFG		0xffff
+#define QM_PEH_AXUSER_CFG	0x1000cc
+#define PEH_AXUSER_CFG		0x400801
+#define QM_CACHE_CTL		0x100050
+#define QM_CACHE_CFG		0x4893
+#define QM_CACHE_WB_START	0x204
+#define QM_CACHE_WB_DONE	0x208
+/* XQC shift */
+#define QM_SQ_SQE_SIZE_SHIFT	12
+#define QM_SQ_ORDER_SHIFT	4
+#define QM_SQ_TYPE_SHIFT	8
+#define QM_CQE_SIZE		4
+#define QM_CQ_CQE_SIZE_SHIFT	12
+/* CQE */
+#define QM_CQE_PHASE(cqe) (((cqe)->w7) & QM_FVT_CFG_RDY_BIT)
+
+enum qm_mailbox_common_cmd {
+	QM_MB_CMD_SQC = 0x0,
+	QM_MB_CMD_CQC,
+	QM_MB_CMD_EQC,
+	QM_MB_CMD_AEQC,
+	QM_MB_CMD_SQC_BT,
+	QM_MB_CMD_CQC_BT,
+	QM_MB_CMD_SQC_VFT,
+};
+
+enum qm_mailbox_cmd_v3 {
+	QM_MB_CM_CLOSE_QM = 0x7,
+	QM_MB_CMD_CLOSE_QP,
+	QM_MB_CMD_FLUSH_QM,
+	QM_MB_CMD_FLUSH_QP,
+	QM_MB_CMD_SRC = 0xc,
+	QM_MB_CMD_DST,
+	QM_MB_CMD_STOP_QM,
+};
+
+struct qm_mailbox {
+	union {
+		struct {
+			uint16_t w0;
+			uint16_t queue;
+			uint32_t base_l;
+			uint32_t base_h;
+			uint32_t token;
+		};
+		uint64_t x[2];
+	};
+};
+
+struct qm_dfx_registers {
+	const char *reg_name;
+	uint32_t reg_offset;
+};
+
+static const struct qm_dfx_registers qm_dfx_regs[] = {
+	{ .reg_name = "QM_ECC_1BIT_CNT           ", .reg_offset = 0x104000 },
+	{ .reg_name = "QM_ECC_MBIT_CNT           ", .reg_offset = 0x104008 },
+	{ .reg_name = "QM_DFX_MB_CNT             ", .reg_offset = 0x104018 },
+	{ .reg_name = "QM_DFX_DB_CNT             ", .reg_offset = 0x104028 },
+	{ .reg_name = "QM_DFX_SQE_CNT            ", .reg_offset = 0x104038 },
+	{ .reg_name = "QM_DFX_CQE_CNT            ", .reg_offset = 0x104048 },
+	{ .reg_name = "QM_DFX_SEND_SQE_TO_ACC_CNT", .reg_offset = 0x104050 },
+	{ .reg_name = "QM_DFX_WB_SQE_FROM_ACC_CNT", .reg_offset = 0x104058 },
+	{ .reg_name = "QM_DFX_ACC_FINISH_CNT     ", .reg_offset = 0x104060 },
+	{ .reg_name = "QM_DFX_CQE_ERR_CNT        ", .reg_offset = 0x1040b4 },
+	{ }
+};
+
+void hisi_qm_get_version(struct hisi_qm *qm)
+{
+	qm->version = io_read32(qm->io_base + HISI_QM_REVISON_ID_BASE) &
+		      HISI_QM_REVISON_ID_MASK;
+}
+
+static void qm_db(struct hisi_qm *qm, uint16_t qn, uint8_t cmd, uint16_t index,
+		  uint8_t priority)
+{
+	uint64_t doorbell = 0;
+
+	doorbell = qn | SHIFT_U64(cmd, QM_DB_CMD_SHIFT) |
+		   SHIFT_U64(QM_DB_RAND_DATA, QM_DB_RAND_DATA_SHIFT) |
+		   SHIFT_U64(index, QM_DB_INDEX_SHIFT) |
+		   SHIFT_U64(priority, QM_DB_PRIORITY_SHIFT);
+
+	io_write64(qm->io_base + QM_DOORBELL_SQ_CQ_BASE, doorbell);
+}
+
+static void qm_mb_write(struct hisi_qm *qm, struct qm_mailbox *mb)
+{
+	vaddr_t dst = qm->io_base + QM_MAILBOX_BASE;
+
+	write_64bit_pair(dst, mb->x[1], mb->x[0]);
+	dsb_osh();
+}
+
+static void qm_mb_read(struct hisi_qm *qm, struct qm_mailbox *mb)
+{
+	vaddr_t mb_base = qm->io_base + QM_MAILBOX_BASE;
+
+	read_64bit_pair(mb_base, mb->x + 1, mb->x);
+	dsb_osh();
+}
+
+static enum hisi_drv_status qm_wait_mb_ready(struct hisi_qm *qm)
+{
+	struct qm_mailbox mb = { };
+	uint32_t timeout = 0;
+
+	timeout = timeout_init_us(QM_MB_WAIT_PERIOD * QM_MB_WAIT_READY_CNT);
+	while (!timeout_elapsed(timeout)) {
+		/* 128 bits should be read from hardware at one time*/
+		qm_mb_read(qm, &mb);
+		if (!(mb.w0 & QM_MB_BUSY_BIT))
+			return HISI_QM_DRVCRYPT_NO_ERR;
+	}
+
+	EMSG("QM mailbox is busy to start!");
+
+	return HISI_QM_DRVCRYPT_EBUSY;
+}
+
+static enum hisi_drv_status qm_wait_mb_finish(struct hisi_qm *qm,
+					      struct qm_mailbox *mb)
+{
+	uint32_t timeout = 0;
+
+	timeout = timeout_init_us(QM_MB_WAIT_PERIOD * QM_MB_WAIT_MAX_CNT);
+	while (!timeout_elapsed(timeout)) {
+		qm_mb_read(qm, mb);
+		if (!(mb->w0 & QM_MB_BUSY_BIT)) {
+			if (mb->w0 & QM_MB_STATUS_MASK) {
+				EMSG("QM mailbox operation failed!");
+				return HISI_QM_DRVCRYPT_EIO;
+			} else {
+				return HISI_QM_DRVCRYPT_NO_ERR;
+			}
+		}
+	}
+
+	return HISI_QM_DRVCRYPT_ETMOUT;
+}
+
+static void qm_mb_init(struct qm_mailbox *mb, uint8_t cmd, uint64_t base,
+		       uint16_t qnum, uint8_t op)
+{
+	mb->w0 = cmd | SHIFT_U32(op, QM_MB_OP_SHIFT) |  QM_MB_BUSY_BIT;
+	mb->queue = qnum;
+	reg_pair_from_64(base, &mb->base_h, &mb->base_l);
+	mb->token = 0;
+}
+
+static enum hisi_drv_status qm_mb_nolock(struct hisi_qm *qm,
+					 struct qm_mailbox *mb)
+{
+	if (qm_wait_mb_ready(qm))
+		return HISI_QM_DRVCRYPT_EBUSY;
+
+	qm_mb_write(qm, mb);
+
+	return qm_wait_mb_finish(qm, mb);
+}
+
+static enum hisi_drv_status hisi_qm_mb_write(struct hisi_qm *qm, uint8_t cmd,
+					     uintptr_t dma_addr, uint16_t qnum)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+	struct qm_mailbox mb = { };
+
+	qm_mb_init(&mb, cmd, dma_addr, qnum, QM_MB_OP_WR);
+	mutex_lock(&qm->mailbox_lock);
+	ret = qm_mb_nolock(qm, &mb);
+	mutex_unlock(&qm->mailbox_lock);
+
+	return ret;
+}
+
+static enum hisi_drv_status hisi_qm_mb_read(struct hisi_qm *qm, uint64_t *base,
+					    uint8_t cmd, uint16_t qnum)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+	struct qm_mailbox mb = { };
+
+	qm_mb_init(&mb, cmd, 0, qnum, QM_MB_OP_RD);
+	mutex_lock(&qm->mailbox_lock);
+	ret = qm_mb_nolock(qm, &mb);
+	mutex_unlock(&qm->mailbox_lock);
+	if (ret)
+		return ret;
+
+	reg_pair_from_64(*base, &mb.base_h, &mb.base_l);
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static void qm_cfg_vft_data(struct hisi_qm *qm, uint8_t vft_type,
+			    uint32_t base, uint32_t number)
+{
+	uint32_t data_h = 0;
+	uint32_t data_l = 0;
+	uint64_t data = 0;
+
+	switch (vft_type) {
+	case QM_SQC_VFT:
+		data = SHIFT_U64(base, QM_SQC_VFT_START_SQN_SHIFT) |
+			QM_SQC_VFT_VALID |
+			SHIFT_U64((number - 1), QM_SQC_VFT_SQ_NUM_SHIFT);
+		break;
+	case QM_CQC_VFT:
+		data = QM_CQC_VFT_VALID;
+		break;
+	default:
+		panic("Invalid vft type");
+	}
+
+	reg_pair_from_64(data, &data_h, &data_l);
+	io_write32(qm->io_base + QM_VFT_CFG_DATA_L, data_l);
+	io_write32(qm->io_base + QM_VFT_CFG_DATA_H, data_h);
+}
+
+static enum hisi_drv_status qm_set_vft_common(struct hisi_qm *qm,
+					      uint8_t vft_type,
+					      uint32_t function,
+					      uint32_t base,
+					      uint32_t num)
+{
+	uint32_t val = 0;
+
+	if (IO_READ32_POLL_TIMEOUT(qm->io_base + QM_VFT_CFG_RDY, val,
+				   val & QM_FVT_CFG_RDY_BIT, POLL_PERIOD,
+				   POLL_TIMEOUT)) {
+		EMSG("QM VFT is not ready");
+		return HISI_QM_DRVCRYPT_EBUSY;
+	}
+
+	io_write32(qm->io_base + QM_VFT_CFG_OP_WR, QM_VFT_WRITE);
+	io_write32(qm->io_base + QM_VFT_CFG_TYPE, vft_type);
+	io_write32(qm->io_base + QM_VFT_CFG_ADDRESS, function);
+	qm_cfg_vft_data(qm, vft_type, base, num);
+	io_write32(qm->io_base + QM_VFT_CFG_RDY, 0x0);
+	io_write32(qm->io_base + QM_VFT_CFG_OP_ENABLE, QM_FVT_CFG_RDY_BIT);
+
+	if (IO_READ32_POLL_TIMEOUT(qm->io_base + QM_VFT_CFG_RDY, val,
+				   val & QM_FVT_CFG_RDY_BIT, POLL_PERIOD,
+				   POLL_TIMEOUT)) {
+		EMSG("QM VFT is not ready");
+		return HISI_QM_DRVCRYPT_EBUSY;
+	}
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status qm_set_xqc_vft(struct hisi_qm *qm,
+					   uint32_t function,
+					   uint32_t base, uint32_t num)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+	int i = 0;
+
+	if (!num) {
+		EMSG("Invalid sq num");
+		return HISI_QM_DRVCRYPT_EINVAL;
+	}
+
+	for (i = QM_SQC_VFT; i <= QM_CQC_VFT; i++) {
+		ret = qm_set_vft_common(qm, i, function, base, num);
+		if (ret) {
+			EMSG("QM set type %d fail", i);
+			return ret;
+		}
+	}
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status qm_get_vft(struct hisi_qm *qm, uint32_t *base,
+				       uint32_t *num)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+	uint64_t sqc_vft = 0;
+
+	ret = hisi_qm_mb_read(qm, &sqc_vft, QM_MB_CMD_SQC_VFT, 0);
+	if (ret)
+		return ret;
+
+	*base = (sqc_vft >> QM_SQC_VFT_START_SQN_SHIFT) & QM_SQC_VFT_BASE_MASK;
+	*num = ((sqc_vft >> QM_SQC_VFT_SQ_NUM_SHIFT) & QM_SQC_VFT_NUM_MASK) + 1;
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static void qp_free(struct hisi_qm *qm, uint32_t id)
+{
+	struct hisi_qp *qp = &qm->qp_array[id];
+
+	free(qp->sqe);
+	free(qp->cqe);
+}
+
+static enum hisi_drv_status qp_alloc(struct hisi_qm *qm, uint32_t id)
+{
+	size_t sq_size = qm->sqe_size * HISI_QM_Q_DEPTH;
+	size_t cq_size = sizeof(struct qm_cqe) * HISI_QM_Q_DEPTH;
+	struct hisi_qp *qp = &qm->qp_array[id];
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	qp->sqe = memalign(HISI_QM_ALIGN128, sq_size);
+	if (!qp->sqe) {
+		EMSG("Fail to malloc sq[%"PRIu32"]", id);
+		return HISI_QM_DRVCRYPT_ENOMEM;
+	}
+	qp->sqe_dma = virt_to_phys(qp->sqe);
+	qp->cqe = memalign(HISI_QM_ALIGN32, cq_size);
+	if (!qp->cqe) {
+		EMSG("Fail to malloc cq[%"PRIu32"]", id);
+		ret = HISI_QM_DRVCRYPT_ENOMEM;
+		goto free_sqe;
+	}
+	qp->cqe_dma = virt_to_phys(qp->cqe);
+
+	qp->qp_id = id;
+	qp->qm = qm;
+	return HISI_QM_DRVCRYPT_NO_ERR;
+
+free_sqe:
+	free(qp->sqe);
+	return ret;
+}
+
+static void hisi_qm_free_xqc(struct qm_xqc *xqc)
+{
+	free(xqc->cqc);
+	free(xqc->sqc);
+}
+
+static void qm_free(struct hisi_qm *qm)
+{
+	unsigned int i = 0;
+
+	for (i = 0; i < qm->qp_num; i++)
+		qp_free(qm, i);
+
+	free(qm->qp_array);
+	hisi_qm_free_xqc(&qm->xqc);
+	hisi_qm_free_xqc(&qm->cfg_xqc);
+}
+
+static enum hisi_drv_status hisi_qm_alloc_xqc(struct qm_xqc *xqc,
+					      uint32_t qp_num)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+	size_t sqc_size = 0;
+	size_t cqc_size = 0;
+
+	sqc_size = sizeof(struct qm_sqc) * qp_num;
+	cqc_size = sizeof(struct qm_cqc) * qp_num;
+
+	xqc->sqc = memalign(HISI_QM_ALIGN32, sqc_size);
+	if (!xqc->sqc) {
+		EMSG("Fail to malloc sqc");
+		return HISI_QM_DRVCRYPT_ENOMEM;
+	}
+	memset(xqc->sqc, 0, sqc_size);
+	xqc->sqc_dma = virt_to_phys(xqc->sqc);
+
+	xqc->cqc = memalign(HISI_QM_ALIGN32, cqc_size);
+	if (!xqc->cqc) {
+		EMSG("Fail to malloc cqc");
+		ret = HISI_QM_DRVCRYPT_ENOMEM;
+		goto free_sqc;
+	}
+	memset(xqc->cqc, 0, cqc_size);
+	xqc->cqc_dma = virt_to_phys(xqc->cqc);
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+
+	free(xqc->cqc);
+free_sqc:
+	free(xqc->sqc);
+	return ret;
+}
+
+static enum hisi_drv_status qm_alloc(struct hisi_qm *qm)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+	int32_t j;
+	uint32_t i;
+
+	ret = hisi_qm_alloc_xqc(&qm->xqc, qm->qp_num);
+	if (ret)
+		return ret;
+
+	ret = hisi_qm_alloc_xqc(&qm->cfg_xqc, 1);
+	if (ret)
+		goto free_xqc;
+
+	qm->qp_array = calloc(qm->qp_num, sizeof(struct hisi_qp));
+	if (!qm->qp_array) {
+		EMSG("Fail to malloc qp_array");
+		ret = HISI_QM_DRVCRYPT_ENOMEM;
+		goto free_cfg_xqc;
+	}
+
+	for (i = 0; i < qm->qp_num; i++) {
+		ret = qp_alloc(qm, i);
+		if (ret)
+			goto free_qp_mem;
+	}
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+
+free_qp_mem:
+	for (j = (int)i - 1; j >= 0; j--)
+		qp_free(qm, j);
+	free(qm->qp_array);
+free_cfg_xqc:
+	hisi_qm_free_xqc(&qm->cfg_xqc);
+free_xqc:
+	hisi_qm_free_xqc(&qm->xqc);
+	return ret;
+}
+
+enum hisi_drv_status hisi_qm_init(struct hisi_qm *qm)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	if (qm->fun_type == HISI_QM_HW_VF) {
+		ret = qm_get_vft(qm, &qm->qp_base, &qm->qp_num);
+		if (ret) {
+			EMSG("Fail to get function vft config");
+			return ret;
+		}
+	}
+
+	if (!qm->qp_num || !qm->sqe_size) {
+		EMSG("Invalid QM parameters");
+		return HISI_QM_DRVCRYPT_EINVAL;
+	}
+
+	ret = qm_alloc(qm);
+	if (ret)
+		return ret;
+
+	qm->qp_in_used = 0;
+	qm->qp_idx = 0;
+	mutex_init(&qm->qp_lock);
+	mutex_init(&qm->mailbox_lock);
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static void qm_cache_writeback(struct hisi_qm *qm)
+{
+	uint32_t val = 0;
+
+	io_write32(qm->io_base + QM_CACHE_WB_START, QM_FVT_CFG_RDY_BIT);
+
+	if (IO_READ32_POLL_TIMEOUT(qm->io_base + QM_CACHE_WB_DONE, val,
+				   val & QM_FVT_CFG_RDY_BIT, POLL_PERIOD,
+				   POLL_TIMEOUT))
+		panic("QM writeback sqc cache fail");
+}
+
+void hisi_qm_uninit(struct hisi_qm *qm)
+{
+	qm_cache_writeback(qm);
+	qm_free(qm);
+	mutex_destroy(&qm->qp_lock);
+	mutex_destroy(&qm->mailbox_lock);
+}
+
+static enum hisi_drv_status qm_hw_mem_reset(struct hisi_qm *qm)
+{
+	uint32_t val = 0;
+
+	io_write32(qm->io_base + QM_MEM_START_INIT, QM_FVT_CFG_RDY_BIT);
+
+	if (IO_READ32_POLL_TIMEOUT(qm->io_base + QM_MEM_INIT_DONE, val,
+				   val & QM_FVT_CFG_RDY_BIT, POLL_PERIOD,
+				   POLL_TIMEOUT))
+		return HISI_QM_DRVCRYPT_EBUSY;
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status qm_func_vft_cfg(struct hisi_qm *qm)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+	uint32_t q_base = qm->qp_num;
+	uint32_t act_q_num = 0;
+	unsigned int i = 0;
+	unsigned int j = 0;
+
+	if (!qm->vfs_num)
+		return HISI_QM_DRVCRYPT_NO_ERR;
+
+	if (qm->vfs_num > HISI_QM_MAX_VFS_NUM) {
+		EMSG("Invalid QM vfs_num");
+		return HISI_QM_DRVCRYPT_EINVAL;
+	}
+
+	for (i = 1; i <= qm->vfs_num; i++) {
+		act_q_num = HISI_QM_VF_Q_NUM;
+		ret = qm_set_xqc_vft(qm, i, q_base, act_q_num);
+		if (ret) {
+			for (j = 1; j < i; j++)
+				(void)qm_set_xqc_vft(qm, j, 0, 0);
+			return ret;
+		}
+		q_base += act_q_num;
+	}
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+enum hisi_drv_status hisi_qm_start(struct hisi_qm *qm)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	if (qm->fun_type == HISI_QM_HW_PF) {
+		ret = qm_hw_mem_reset(qm);
+		if (ret) {
+			EMSG("Fail to reset QM hardware mem");
+			return ret;
+		}
+
+		ret = qm_set_xqc_vft(qm, 0, qm->qp_base, qm->qp_num);
+		if (ret) {
+			EMSG("Fail to set PF xqc_vft");
+			return ret;
+		}
+
+		ret = qm_func_vft_cfg(qm);
+		if (ret) {
+			EMSG("Fail to set VF xqc_vft");
+			return ret;
+		}
+	}
+
+	ret = hisi_qm_mb_write(qm, QM_MB_CMD_SQC_BT, qm->xqc.sqc_dma, 0);
+	if (ret) {
+		EMSG("Fail to set sqc_bt");
+		return ret;
+	}
+
+	ret = hisi_qm_mb_write(qm, QM_MB_CMD_CQC_BT, qm->xqc.cqc_dma, 0);
+	if (ret) {
+		EMSG("Fail to set cqc_bt");
+		return ret;
+	}
+
+	/* Security mode does not support msi */
+	io_write32(qm->io_base + QM_VF_AEQ_INT_MASK, QM_VF_AEQ_INT_MASK_EN);
+	io_write32(qm->io_base + QM_VF_EQ_INT_MASK, QM_VF_EQ_INT_MASK_EN);
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+void hisi_qm_dev_init(struct hisi_qm *qm)
+{
+	if (qm->fun_type == HISI_QM_HW_VF)
+		return;
+
+	/* QM user domain */
+	io_write32(qm->io_base + QM_ARUSER_M_CFG_1, QM_AXUSER_CFG);
+	io_write32(qm->io_base + QM_ARUSER_M_CFG_ENABLE, AXUSER_M_CFG_ENABLE);
+	io_write32(qm->io_base + QM_AWUSER_M_CFG_1, QM_AXUSER_CFG);
+	io_write32(qm->io_base + QM_AWUSER_M_CFG_ENABLE, AXUSER_M_CFG_ENABLE);
+	/* QM cache */
+	io_write32(qm->io_base + QM_AXI_M_CFG, AXI_M_CFG);
+
+	if (qm->version == HISI_QM_HW_V2) {
+		/* Disable FLR triggered by BME(bus master enable) */
+		io_write32(qm->io_base + QM_PEH_AXUSER_CFG, PEH_AXUSER_CFG);
+		/* Set sec sqc and cqc cache wb threshold 4 */
+		io_write32(qm->io_base + QM_CACHE_CTL, QM_CACHE_CFG);
+	}
+	/* Disable QM ras */
+	io_write32(qm->io_base + HISI_QM_ABNML_INT_MASK,
+		   HISI_QM_ABNML_INT_MASK_CFG);
+}
+
+static enum hisi_drv_status qm_sqc_cfg(struct hisi_qp *qp)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+	struct hisi_qm *qm = qp->qm;
+	struct qm_sqc *sqc = qm->cfg_xqc.sqc;
+	struct qm_mailbox mb = { };
+
+	mutex_lock(&qm->mailbox_lock);
+	memset(sqc, 0, sizeof(struct qm_sqc));
+	reg_pair_from_64(qp->sqe_dma, &sqc->base_h, &sqc->base_l);
+	sqc->dw3 = (HISI_QM_Q_DEPTH - 1) |
+		    SHIFT_U32(qm->sqe_log2_size, QM_SQ_SQE_SIZE_SHIFT);
+	sqc->rand_data = QM_DB_RAND_DATA;
+	sqc->cq_num = qp->qp_id;
+	sqc->w13 = BIT32(QM_SQ_ORDER_SHIFT) |
+		   SHIFT_U32(qp->sq_type, QM_SQ_TYPE_SHIFT);
+
+	qm_mb_init(&mb, QM_MB_CMD_SQC, qm->cfg_xqc.sqc_dma, qp->qp_id,
+		   QM_MB_OP_WR);
+	ret = qm_mb_nolock(qm, &mb);
+	mutex_unlock(&qm->mailbox_lock);
+
+	return ret;
+}
+
+static enum hisi_drv_status qm_cqc_cfg(struct hisi_qp *qp)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+	struct hisi_qm *qm = qp->qm;
+	struct qm_cqc *cqc = qm->cfg_xqc.cqc;
+	struct qm_mailbox mb = { };
+
+	mutex_lock(&qm->mailbox_lock);
+	memset(cqc, 0, sizeof(struct qm_cqc));
+	reg_pair_from_64(qp->cqe_dma, &cqc->base_h, &cqc->base_l);
+	cqc->dw3 = (HISI_QM_Q_DEPTH - 1) |
+		    SHIFT_U32(QM_CQE_SIZE, QM_CQ_CQE_SIZE_SHIFT);
+	cqc->rand_data = QM_DB_RAND_DATA;
+	cqc->dw6 = PHASE_DEFAULT_VAL;
+
+	qm_mb_init(&mb, QM_MB_CMD_CQC, qm->cfg_xqc.cqc_dma, qp->qp_id,
+		   QM_MB_OP_WR);
+	ret = qm_mb_nolock(qm, &mb);
+	mutex_unlock(&qm->mailbox_lock);
+
+	return ret;
+}
+
+struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, uint8_t sq_type)
+{
+	struct hisi_qp *qp = NULL;
+	int cur_idx = 0;
+	uint32_t i = 0;
+
+	mutex_lock(&qm->qp_lock);
+	if (qm->qp_in_used == qm->qp_num) {
+		EMSG("All %"PRIu32" queues of QM are busy", qm->qp_num);
+		goto err_proc;
+	}
+
+	for (i = 0; i < qm->qp_num; i++) {
+		cur_idx = (qm->qp_idx + i) % qm->qp_num;
+		if (!qm->qp_array[cur_idx].used) {
+			qm->qp_array[cur_idx].used = true;
+			qm->qp_idx = cur_idx + 1;
+			break;
+		}
+	}
+
+	qp = qm->qp_array + cur_idx;
+	memset(qp->cqe, 0, sizeof(struct qm_cqe) * HISI_QM_Q_DEPTH);
+	qp->sq_type = sq_type;
+	qp->sq_tail = 0;
+	qp->cq_head = 0;
+	qp->cqc_phase = true;
+
+	if (qm_sqc_cfg(qp)) {
+		EMSG("Fail to set qp[%"PRIu32"] sqc", qp->qp_id);
+		goto err_proc;
+	}
+
+	if (qm_cqc_cfg(qp)) {
+		EMSG("Fail to set qp[%"PRIu32"] cqc", qp->qp_id);
+		goto err_proc;
+	}
+
+	qm->qp_in_used++;
+	mutex_unlock(&qm->qp_lock);
+	return qp;
+
+err_proc:
+	qp->sq_type = 0;
+	qp->cqc_phase = false;
+	mutex_unlock(&qm->qp_lock);
+	return NULL;
+}
+
+void hisi_qm_release_qp(struct hisi_qp *qp)
+{
+	struct hisi_qm *qm = NULL;
+
+	if (!qp) {
+		EMSG("QP is NULL");
+		return;
+	}
+
+	qm = qp->qm;
+	mutex_lock(&qm->qp_lock);
+	qm->qp_in_used--;
+	qp->used = false;
+	mutex_unlock(&qm->qp_lock);
+}
+
+static void qm_sq_tail_update(struct hisi_qp *qp)
+{
+	if (qp->sq_tail == HISI_QM_Q_DEPTH - 1)
+		qp->sq_tail = 0;
+	else
+		qp->sq_tail++;
+}
+
+/*
+ * One task thread will just bind to one hardware queue, and
+ * hardware does not support msi. So we have no lock here.
+ */
+enum hisi_drv_status hisi_qp_send(struct hisi_qp *qp, void *msg)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+	struct hisi_qm *qm = NULL;
+	void *sqe = NULL;
+
+	if (!qp) {
+		EMSG("QP is NULL");
+		return HISI_QM_DRVCRYPT_EINVAL;
+	}
+
+	qm = qp->qm;
+	ret = qm->dev_status_check(qm);
+	if (ret)
+		return ret;
+
+	sqe = (void *)((vaddr_t)qp->sqe + qm->sqe_size * qp->sq_tail);
+	memset(sqe, 0, qm->sqe_size);
+
+	ret = qp->fill_sqe(sqe, msg);
+	if (ret) {
+		EMSG("Fail to fill sqe");
+		return ret;
+	}
+
+	qm_sq_tail_update(qp);
+
+	dsb();
+	qm_db(qm, qp->qp_id, QM_DOORBELL_CMD_SQ, qp->sq_tail, 0);
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static void qm_cq_head_update(struct hisi_qp *qp)
+{
+	if (qp->cq_head == HISI_QM_Q_DEPTH - 1) {
+		qp->cqc_phase = !qp->cqc_phase;
+		qp->cq_head = 0;
+	} else {
+		qp->cq_head++;
+	}
+}
+
+static enum hisi_drv_status hisi_qp_recv(struct hisi_qp *qp, void *msg)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+	struct hisi_qm *qm = qp->qm;
+	struct qm_cqe *cqe = NULL;
+	void *sqe = NULL;
+
+	ret = qm->dev_status_check(qm);
+	if (ret)
+		return ret;
+
+	cqe = qp->cqe + qp->cq_head;
+	if (QM_CQE_PHASE(cqe) == qp->cqc_phase) {
+		dsb_osh();
+		sqe = (void *)((vaddr_t)qp->sqe + qm->sqe_size * cqe->sq_head);
+		ret = qp->parse_sqe(sqe, msg);
+		qm_cq_head_update(qp);
+		qm_db(qm, qp->qp_id, QM_DOORBELL_CMD_CQ, qp->cq_head, 0);
+		if (ret) {
+			EMSG("Fail to parse sqe");
+			return ret;
+		}
+	} else {
+		return HISI_QM_DRVCRYPT_NO_ERR;
+	}
+
+	return HISI_QM_DRVCRYPT_RECV_DONE;
+}
+
+static void qm_dfx_dump(struct hisi_qm *qm)
+{
+	const struct qm_dfx_registers *regs = qm_dfx_regs;
+	__maybe_unused uint32_t val = 0;
+
+	if (qm->fun_type == HISI_QM_HW_VF)
+		return;
+
+	while (regs->reg_name) {
+		val = io_read32(qm->io_base + regs->reg_offset);
+		EMSG("%s= 0x%" PRIx32, regs->reg_name, val);
+		regs++;
+	}
+}
+
+enum hisi_drv_status hisi_qp_recv_sync(struct hisi_qp *qp, void *msg)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+	uint32_t timeout = 0;
+
+	if (!qp) {
+		EMSG("QP is NULL");
+		return HISI_QM_DRVCRYPT_EINVAL;
+	}
+
+	timeout = timeout_init_us(QM_SINGLE_WAIT_TIME *
+				  HISI_QM_RECV_SYNC_TIMEOUT);
+	while (!timeout_elapsed(timeout)) {
+		ret = hisi_qp_recv(qp, msg);
+		if (ret) {
+			if (ret != HISI_QM_DRVCRYPT_RECV_DONE) {
+				EMSG("QM recv task error");
+				qm_dfx_dump(qp->qm);
+				return ret;
+			} else {
+				return HISI_QM_DRVCRYPT_NO_ERR;
+			}
+		}
+	}
+
+	EMSG("QM recv task timeout");
+	qm_dfx_dump(qp->qm);
+	return HISI_QM_DRVCRYPT_ETMOUT;
+}
diff --git a/core/drivers/crypto/hisilicon/include/hisi_qm.h b/core/drivers/crypto/hisilicon/include/hisi_qm.h
new file mode 100644
index 0000000000000000000000000000000000000000..8ea1f6fc1d0146d9ccbabeb46800a5d56f4c47d8
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/include/hisi_qm.h
@@ -0,0 +1,271 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2022-2023, Huawei Technologies Co., Ltd
+ */
+#ifndef __HISI_QM_H__
+#define __HISI_QM_H__
+
+#include <io.h>
+#include <kernel/delay.h>
+#include <kernel/mutex.h>
+#include <kernel/panic.h>
+#include <mm/core_memprot.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string_ext.h>
+#include <sys/queue.h>
+
+#define HISI_QM_HW_V2 0x21
+#define HISI_QM_HW_V3 0x30
+#define HISI_QM_MAX_VFS_NUM 63
+#define HISI_QM_PF_Q_BASE 0
+#define HISI_QM_PF_Q_NUM 64
+#define HISI_QM_VF_Q_NUM 15
+#define HISI_QM_Q_DEPTH 8
+#define PHASE_DEFAULT_VAL 0x1
+
+#define HISI_QM_ABNML_INT_MASK 0x100004
+#define HISI_QM_ABNML_INT_MASK_CFG 0x7fff
+#define HISI_QM_ABNML_INT_SRC 0x100000
+#define HISI_QM_HPRE_NFE_INT_MASK 0x6fb7
+#define HISI_QM_SEC_NFE_INT_MASK 0x6ff7
+#define HISI_QM_INVALID_DB BIT(12)
+#define HISI_QM_REVISON_ID_BASE 0x1000dc
+#define HISI_QM_REVISON_ID_MASK GENMASK_32(7, 0)
+#define POLL_PERIOD 10
+#define POLL_TIMEOUT 1000
+#define HISI_QM_RECV_SYNC_TIMEOUT 0xfffff
+#define HISI_QM_ALIGN128 128
+#define HISI_QM_ALIGN32 32
+#define QM_SINGLE_WAIT_TIME 5
+#define ADDR_U64(upper, lower) ((uint64_t)(upper) << 32 | (lower))
+
+enum qm_fun_type {
+	HISI_QM_HW_PF,
+	HISI_QM_HW_VF,
+};
+
+enum qm_sq_type {
+	HISI_QM_CHANNEL_TYPE0 = 0,
+	HISI_QM_CHANNEL_TYPE1,
+	HISI_QM_CHANNEL_TYPE2,
+};
+
+struct qm_sqc {
+	uint16_t head;
+	uint16_t tail;
+	uint32_t base_l;
+	uint32_t base_h;
+	/*
+	 * qes : 12
+	 * sqe : 4
+	 * rsv(stash_nid/stash_en) : 16
+	 */
+	uint32_t dw3;
+	uint16_t rand_data;
+	uint16_t rsv0;
+	uint16_t pasid;
+	/*
+	 * rsv : 5
+	 * head_sig : 1
+	 * tail_sig : 1
+	 * pasid_en : 1
+	 * rsv : 8
+	 */
+	uint16_t w11;
+	uint16_t cq_num;
+	/*
+	 * priority(Credit): 4
+	 * order(order/fc/close/rsv) : 4
+	 * type : 4
+	 * rsv : 4
+	 */
+	uint16_t w13;
+	uint32_t rsv1;
+};
+
+struct qm_cqc {
+	uint16_t head;
+	uint16_t tail;
+	uint32_t base_l;
+	uint32_t base_h;
+	/*
+	 * qes : 12
+	 * cqe_size : 4
+	 * rsv(stash_nid/stash_en) : 16
+	 */
+	uint32_t dw3;
+	uint16_t rand_data;
+	uint16_t rsv0;
+	uint16_t pasid;
+	/*
+	 * pasid_en : 1
+	 * rsv : 4
+	 * head_sig : 1
+	 * tail_sig : 1
+	 * rsv : 9
+	 */
+	uint16_t w11;
+	/*
+	 * phase : 1
+	 * c_flag : 1
+	 * stash_vld : 1
+	 */
+	uint32_t dw6;
+	uint32_t rsv1;
+};
+
+struct qm_cqe {
+	uint32_t rsv0;
+	uint16_t cmd_id;
+	uint16_t rsv1;
+	uint16_t sq_head;
+	uint16_t sq_id;
+	uint16_t rsv2;
+	/*
+	 * p : 1
+	 * status : 15
+	 */
+	uint16_t w7;
+};
+
+struct hisi_qp {
+	struct hisi_qm *qm;
+	uint32_t qp_id;
+	uint8_t sq_type;
+	uint16_t sq_tail;
+	uint16_t cq_head;
+	bool cqc_phase;
+	bool used;
+
+	void *sqe;
+	struct qm_cqe *cqe;
+	paddr_t sqe_dma;
+	paddr_t cqe_dma;
+
+	enum hisi_drv_status (*fill_sqe)(void *sqe, void *msg);
+	enum hisi_drv_status (*parse_sqe)(void *sqe, void *msg);
+};
+
+struct qm_xqc {
+	struct qm_sqc *sqc;
+	struct qm_cqc *cqc;
+	paddr_t sqc_dma;
+	paddr_t cqc_dma;
+};
+
+struct hisi_qm {
+	enum qm_fun_type fun_type;
+	vaddr_t io_base;
+	uint32_t io_size;
+	uint32_t vfs_num;
+	uint32_t version;
+
+	struct qm_xqc xqc;
+	struct qm_xqc cfg_xqc;
+	uint32_t sqe_size;
+	uint32_t sqe_log2_size;
+	uint32_t qp_base;
+	uint32_t qp_num;
+	uint32_t qp_in_used;
+	uint32_t qp_idx;
+	struct hisi_qp *qp_array;
+	struct mutex qp_lock; /* protect the qp instance */
+	struct mutex mailbox_lock;
+
+	enum hisi_drv_status (*dev_status_check)(struct hisi_qm *qm);
+};
+
+enum hisi_drv_status {
+	HISI_QM_DRVCRYPT_NO_ERR = 0,
+	HISI_QM_DRVCRYPT_FAIL = 1,
+	HISI_QM_DRVCRYPT_EIO = 5,
+	HISI_QM_DRVCRYPT_EAGAIN = 11,
+	HISI_QM_DRVCRYPT_ENOMEM = 12,
+	HISI_QM_DRVCRYPT_EFAULT = 14,
+	HISI_QM_DRVCRYPT_EBUSY = 16,
+	HISI_QM_DRVCRYPT_ENODEV = 19,
+	HISI_QM_DRVCRYPT_EINVAL = 22,
+	HISI_QM_DRVCRYPT_ETMOUT = 110,
+	HISI_QM_DRVCRYPT_RECV_DONE = 175,
+	HISI_QM_DRVCRYPT_ENOPROC,
+	HISI_QM_DRVCRYPT_IN_EPARA,
+	HISI_QM_DRVCRYPT_VERIFY_ERR,
+	HISI_QM_DRVCRYPT_HW_EACCESS,
+};
+
+struct acc_device {
+	struct hisi_qm qm;
+	vaddr_t io_base;
+	uint32_t io_size;
+	uint32_t vfs_num;
+	uint32_t endian;
+	enum qm_fun_type fun_type;
+	SLIST_ENTRY(acc_device) link;
+};
+
+/**
+ * @Description: Get the version information of QM hardware
+ * @param qm: Handle of Queue Management module
+ */
+void hisi_qm_get_version(struct hisi_qm *qm);
+
+/**
+ * @Description: Init QM for Kunpeng drv
+ * @param qm: Handle of Queue Management module
+ * @return success: HISI_QM_DRVCRYPT_NO_ERR,
+ * fail: HISI_QM_DRVCRYPT_EBUSY/HISI_QM_DRVCRYPT_EINVAL
+ */
+enum hisi_drv_status hisi_qm_init(struct hisi_qm *qm);
+
+/**
+ * @Description:deinit QM for Kunpeng drv
+ * @param qm: Handle of Queue Management module
+ */
+void hisi_qm_uninit(struct hisi_qm *qm);
+
+/**
+ * @Description: Start QM for Kunpeng drv
+ * @param qm: Handle of Queue Management module
+ */
+enum hisi_drv_status hisi_qm_start(struct hisi_qm *qm);
+
+/**
+ * @Description: Config QM for Kunpeng drv
+ * @param qm: Handle of Queue Management module
+ */
+void hisi_qm_dev_init(struct hisi_qm *qm);
+
+/**
+ * @Description: Create Queue Pair, allocated to PF/VF for configure
+ * and service use. Each QP includes one SQ and one CQ
+ * @param qm: Handle of Queue Management module
+ * @param sq_type: Accelerator specific algorithm type in sqc
+ * @return success: Handle of QP,fail: NULL
+ */
+struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, uint8_t sq_type);
+
+/**
+ * @Description:Release Queue Pair
+ * @param qp: Handle of Queue Pair
+ */
+void hisi_qm_release_qp(struct hisi_qp *qp);
+
+/**
+ * @Description: Send SQE(Submmision Queue Element) to Kunpeng dev
+ * @param qp: Handle of Queue Pair
+ * @param msg: The message
+ * @return success: HISI_QM_DRVCRYPT_NO_ERR,fail: HISI_QM_DRVCRYPT_EINVAL
+ */
+enum hisi_drv_status hisi_qp_send(struct hisi_qp *qp, void *msg);
+
+/**
+ * @Description: Recevice result from Kunpeng dev
+ * @param qp: Handle of Queue Pair
+ * @param msg: The message
+ * @return success: HISI_QM_DRVCRYPT_NO_ERR
+ * fail: HISI_QM_DRVCRYPT_EINVAL/ETMOUT
+ */
+enum hisi_drv_status hisi_qp_recv_sync(struct hisi_qp *qp, void *msg);
+
+#endif
diff --git a/core/drivers/crypto/hisilicon/sub.mk b/core/drivers/crypto/hisilicon/sub.mk
new file mode 100644
index 0000000000000000000000000000000000000000..9a1747084ffdebe8fa20127a387a4d1824f23bdb
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/sub.mk
@@ -0,0 +1,3 @@
+incdirs-y += include
+
+srcs-y += hisi_qm.c
diff --git a/core/drivers/crypto/sub.mk b/core/drivers/crypto/sub.mk
index 3c26eda79a25f0723729beaa6f637d0f04d170c3..71cb6bd6905aa3e0b1233e3314a32c071acf8e78 100644
--- a/core/drivers/crypto/sub.mk
+++ b/core/drivers/crypto/sub.mk
@@ -11,3 +11,5 @@ subdirs-$(CFG_STM32_CRYPTO_DRIVER) += stm32
 subdirs-$(CFG_ASPEED_CRYPTO_DRIVER) += aspeed
 
 subdirs-$(CFG_VERSAL_CRYPTO_DRIVER) += versal
+
+subdirs-$(CFG_HISILICON_CRYPTO_DRIVER) += hisilicon
diff --git a/core/drivers/dra7_rng.c b/core/drivers/dra7_rng.c
index c3af33594a818553746d89e364d35b9c176a3d86..caea21ea1646ec1e6e15f0a70910aa09f526c6c1 100644
--- a/core/drivers/dra7_rng.c
+++ b/core/drivers/dra7_rng.c
@@ -92,7 +92,7 @@ static void dra7_rng_read64(uint32_t *low_word, uint32_t *high_word)
 			/* Clear the shutdown overflow event */
 			io_write32(rng + RNG_INTACK, SHUTDOWN_OFLO);
 
-			DMSG("Fixed FRO shutdown\n");
+			DMSG("Fixed FRO shutdown");
 		}
 	}
 	/* Read random value */
diff --git a/core/drivers/gic.c b/core/drivers/gic.c
index 6d5b7777c52184b578c35e449178655c2da1b778..e751ae4e5c56c9840297c996cd0f66d963aebcc7 100644
--- a/core/drivers/gic.c
+++ b/core/drivers/gic.c
@@ -1,24 +1,27 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright (c) 2016-2017, Linaro Limited
+ * Copyright (c) 2016-2017, 2023 Linaro Limited
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
 #include <arm.h>
 #include <assert.h>
-#include <config.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <compiler.h>
+#include <config.h>
 #include <drivers/gic.h>
+#include <io.h>
 #include <keep.h>
 #include <kernel/dt.h>
+#include <kernel/dt_driver.h>
 #include <kernel/interrupt.h>
+#include <kernel/misc.h>
 #include <kernel/panic.h>
+#include <libfdt.h>
 #include <mm/core_memprot.h>
 #include <mm/core_mmu.h>
-#include <libfdt.h>
-#include <util.h>
-#include <io.h>
 #include <trace.h>
+#include <util.h>
 
 /* Offsets from gic.gicc_base */
 #define GICC_CTLR		(0x000)
@@ -28,7 +31,6 @@
 
 #define GICC_CTLR_ENABLEGRP0	(1 << 0)
 #define GICC_CTLR_ENABLEGRP1	(1 << 1)
-#define GICD_CTLR_ENABLEGRP1S	(1 << 2)
 #define GICC_CTLR_FIQEN		(1 << 3)
 
 /* Offsets from gic.gicd_base */
@@ -44,8 +46,39 @@
 #define GICD_IGROUPMODR(n)	(0xd00 + (n) * 4)
 #define GICD_SGIR		(0xF00)
 
-#define GICD_CTLR_ENABLEGRP0	(1 << 0)
-#define GICD_CTLR_ENABLEGRP1	(1 << 1)
+#ifdef CFG_ARM_GICV3
+#define GICD_PIDR2		(0xFFE8)
+#else
+/* Called ICPIDR2 in GICv2 specification */
+#define GICD_PIDR2		(0xFE8)
+#endif
+
+#define GICD_CTLR_ENABLEGRP0	BIT32(0)
+#define GICD_CTLR_ENABLEGRP1NS	BIT32(1)
+#define GICD_CTLR_ENABLEGRP1S	BIT32(2)
+#define GICD_CTLR_ARE_S		BIT32(4)
+#define GICD_CTLR_ARE_NS	BIT32(5)
+
+/* Offsets from gic.gicr_base[core_pos] */
+#define GICR_V3_PCPUBASE_SIZE	(2 * 64 * 1024)
+#define GICR_SGI_BASE_OFFSET	(64 * 1024)
+#define GICR_CTLR		(0x00)
+#define GICR_TYPER		(0x08)
+
+#define GICR_IGROUPR0		(GICR_SGI_BASE_OFFSET + 0x080)
+#define GICR_IGRPMODR0		(GICR_SGI_BASE_OFFSET + 0xD00)
+#define GICR_ICENABLER0		(GICR_SGI_BASE_OFFSET + 0x180)
+#define GICR_ICPENDR0		(GICR_SGI_BASE_OFFSET + 0x280)
+
+#define GICR_TYPER_LAST		BIT64(4)
+#define GICR_TYPER_AFF3_SHIFT	56
+#define GICR_TYPER_AFF2_SHIFT	48
+#define GICR_TYPER_AFF1_SHIFT	40
+#define GICR_TYPER_AFF0_SHIFT	32
+
+/* GICD IDR2 name differs on GICv3 and GICv2 but uses same bit map */
+#define GICD_PIDR2_ARCHREV_SHIFT	4
+#define GICD_PIDR2_ARCHREV_MASK		0xF
 
 /* Number of Private Peripheral Interrupt */
 #define NUM_PPI	32
@@ -71,10 +104,27 @@
 #define GICC_IAR_CPU_ID_MASK	0x7
 #define GICC_IAR_CPU_ID_SHIFT	10
 
+#define GICC_SGI_IRM_BIT	40
+#define GICC_SGI_AFF1_SHIFT	16
+#define GICC_SGI_AFF2_SHIFT	32
+#define GICC_SGI_AFF3_SHIFT	48
+
+#define GICD_SGIR_SIGINTID_MASK			0xf
+#define GICD_SGIR_TO_OTHER_CPUS			0x1
+#define GICD_SGIR_TO_THIS_CPU			0x2
+#define GICD_SGIR_TARGET_LIST_FILTER_SHIFT	24
+#define GICD_SGIR_NSATT_SHIFT			15
+#define GICD_SGIR_CPU_TARGET_LIST_SHIFT		16
+
 struct gic_data {
 	vaddr_t gicc_base;
 	vaddr_t gicd_base;
+#if defined(CFG_ARM_GICV3)
+	vaddr_t gicr_base[CFG_TEE_CORE_NB_CORE];
+#endif
 	size_t max_it;
+	uint32_t per_cpu_group_status;
+	uint32_t per_cpu_group_modifier;
 	struct itr_chip chip;
 };
 
@@ -86,7 +136,7 @@ static void gic_op_enable(struct itr_chip *chip, size_t it);
 static void gic_op_disable(struct itr_chip *chip, size_t it);
 static void gic_op_raise_pi(struct itr_chip *chip, size_t it);
 static void gic_op_raise_sgi(struct itr_chip *chip, size_t it,
-			uint8_t cpu_mask);
+			     uint32_t cpu_mask);
 static void gic_op_set_affinity(struct itr_chip *chip, size_t it,
 			uint8_t cpu_mask);
 
@@ -102,6 +152,21 @@ static const struct itr_ops gic_ops = {
 };
 DECLARE_KEEP_PAGER(gic_ops);
 
+static vaddr_t __maybe_unused get_gicr_base(struct gic_data *gd __maybe_unused)
+{
+#if defined(CFG_ARM_GICV3)
+	return gd->gicr_base[get_core_pos()];
+#else
+	return 0;
+#endif
+}
+
+static bool affinity_routing_is_enabled(struct gic_data *gd)
+{
+	return IS_ENABLED(CFG_ARM_GICV3) &&
+	       io_read32(gd->gicd_base + GICD_CTLR) & GICD_CTLR_ARE_S;
+}
+
 static size_t probe_max_it(vaddr_t gicc_base __maybe_unused, vaddr_t gicd_base)
 {
 	int i;
@@ -145,24 +210,95 @@ out:
 	return ret;
 }
 
-void gic_cpu_init(void)
+static void gicv3_sync_sgi_config(struct gic_data *gd)
 {
-	struct gic_data *gd = &gic_data;
-
-#if defined(CFG_ARM_GICV3)
-	assert(gd->gicd_base);
-#else
-	assert(gd->gicd_base && gd->gicc_base);
-#endif
+	vaddr_t gicr_base = get_gicr_base(gd);
+	bool need_sync = false;
+	uint32_t gmod0 = 0;
+	uint32_t grp0 = 0;
+	size_t n = 0;
 
-	/* per-CPU interrupts config:
-	 * ID0-ID7(SGI)   for Non-secure interrupts
-	 * ID8-ID15(SGI)  for Secure interrupts.
-	 * All PPI config as Non-secure interrupts.
+	/*
+	 * If gicr_base isn't available there's no need to synchronize SGI
+	 * configuration since gic_init_donate_sgi_to_ns() would panic.
 	 */
-	io_write32(gd->gicd_base + GICD_IGROUPR(0), 0xffff00ff);
+	if (!gicr_base)
+		return;
+
+	grp0 = io_read32(gicr_base + GICR_IGROUPR0);
+	gmod0 = io_read32(gicr_base + GICR_IGRPMODR0);
+	for (n = GIC_SGI_SEC_BASE; n <= GIC_SGI_SEC_MAX; n++) {
+		/* Ignore matching bits */
+		if (!(BIT32(n) & (grp0 ^ gd->per_cpu_group_status)) &&
+		    !(BIT32(n) & (gmod0 ^ gd->per_cpu_group_modifier)))
+			continue;
+		/*
+		 * SGI-n differs from primary CPU configuration,
+		 * let's sync up.
+		 */
+		need_sync = true;
+
+		/* Disable interrupt */
+		io_write32(gicr_base + GICR_ICENABLER0, BIT32(n));
+
+		/* Make interrupt non-pending */
+		io_write32(gicr_base + GICR_ICPENDR0, BIT32(n));
+
+		if (BIT32(n) & gd->per_cpu_group_status)
+			grp0 |= BIT32(n);
+		else
+			grp0 &= ~BIT32(n);
+		if (BIT32(n) & gd->per_cpu_group_modifier)
+			gmod0 |= BIT32(n);
+		else
+			gmod0 &= ~BIT32(n);
+	}
 
-	/* Set the priority mask to permit Non-secure interrupts, and to
+	if (need_sync) {
+		io_write32(gicr_base + GICR_IGROUPR0, grp0);
+		io_write32(gicr_base + GICR_IGRPMODR0, gmod0);
+	}
+}
+
+static void gic_legacy_sync_sgi_config(struct gic_data *gd)
+{
+	bool need_sync = false;
+	uint32_t grp0 = 0;
+	size_t n = 0;
+
+	grp0 = io_read32(gd->gicd_base + GICD_IGROUPR(0));
+	for (n = GIC_SGI_SEC_BASE; n <= GIC_SGI_SEC_MAX; n++) {
+		/* Ignore matching bits */
+		if (!(BIT32(n) & (grp0 ^ gd->per_cpu_group_status)))
+			continue;
+		/*
+		 * SGI-n differs from primary CPU configuration,
+		 * let's sync up.
+		 */
+		need_sync = true;
+
+		/* Disable interrupt */
+		io_write32(gd->gicd_base + GICD_ICENABLER(0), BIT(n));
+
+		/* Make interrupt non-pending */
+		io_write32(gd->gicd_base + GICD_ICPENDR(0), BIT(n));
+
+		if (BIT32(n) & gd->per_cpu_group_status)
+			grp0 |= BIT32(n);
+		else
+			grp0 &= ~BIT32(n);
+	}
+
+	if (need_sync)
+		io_write32(gd->gicd_base + GICD_IGROUPR(0), grp0);
+}
+
+static void init_gic_per_cpu(struct gic_data *gd)
+{
+	io_write32(gd->gicd_base + GICD_IGROUPR(0), gd->per_cpu_group_status);
+
+	/*
+	 * Set the priority mask to permit Non-secure interrupts, and to
 	 * allow the Non-secure world to adjust the priority mask itself
 	 */
 #if defined(CFG_ARM_GICV3)
@@ -178,6 +314,76 @@ void gic_cpu_init(void)
 #endif
 }
 
+void gic_init_per_cpu(void)
+{
+	struct gic_data *gd = &gic_data;
+
+#if defined(CFG_ARM_GICV3)
+	assert(gd->gicd_base);
+#else
+	assert(gd->gicd_base && gd->gicc_base);
+#endif
+
+	if (IS_ENABLED(CFG_WITH_ARM_TRUSTED_FW)) {
+		/*
+		 * GIC is already initialized by TF-A, we only need to
+		 * handle eventual SGI configuration changes.
+		 */
+		if (affinity_routing_is_enabled(gd))
+			gicv3_sync_sgi_config(gd);
+		else
+			gic_legacy_sync_sgi_config(gd);
+	} else {
+		/*
+		 * Non-TF-A case where all CPU specific configuration
+		 * of GIC must be done here.
+		 */
+		init_gic_per_cpu(gd);
+	}
+}
+
+void gic_init_donate_sgi_to_ns(size_t it)
+{
+	struct gic_data *gd = &gic_data;
+
+	assert(it >= GIC_SGI_SEC_BASE && it <= GIC_SGI_SEC_MAX);
+
+	/* Assert it's secure to start with. */
+	assert(!(gd->per_cpu_group_status & BIT32(it)) &&
+	       (gd->per_cpu_group_modifier & BIT32(it)));
+
+	gd->per_cpu_group_modifier &= ~BIT32(it);
+	gd->per_cpu_group_status |= BIT32(it);
+
+	if (affinity_routing_is_enabled(gd)) {
+		vaddr_t gicr_base = get_gicr_base(gd);
+
+		if (!gicr_base)
+			panic("GICR_BASE missing");
+
+		/* Disable interrupt */
+		io_write32(gicr_base + GICR_ICENABLER0, BIT32(it));
+
+		/* Make interrupt non-pending */
+		io_write32(gicr_base + GICR_ICPENDR0, BIT32(it));
+
+		/* Make it to non-secure */
+		io_write32(gicr_base + GICR_IGROUPR0, gd->per_cpu_group_status);
+		io_write32(gicr_base + GICR_IGRPMODR0,
+			   gd->per_cpu_group_modifier);
+	} else {
+		/* Disable interrupt */
+		io_write32(gd->gicd_base + GICD_ICENABLER(0), BIT(it));
+
+		/* Make interrupt non-pending */
+		io_write32(gd->gicd_base + GICD_ICPENDR(0), BIT(it));
+
+		/* Make it to non-secure */
+		io_write32(gd->gicd_base + GICD_IGROUPR(0),
+			   gd->per_cpu_group_status);
+	}
+}
+
 static int gic_dt_get_irq(const uint32_t *properties, int count, uint32_t *type,
 			  uint32_t *prio)
 {
@@ -195,10 +401,10 @@ static int gic_dt_get_irq(const uint32_t *properties, int count, uint32_t *type,
 	it_num = fdt32_to_cpu(properties[1]);
 
 	switch (fdt32_to_cpu(properties[0])) {
-	case 1:
+	case GIC_PPI:
 		it_num += 16;
 		break;
-	case 0:
+	case GIC_SPI:
 		it_num += 32;
 		break;
 	default:
@@ -208,11 +414,54 @@ static int gic_dt_get_irq(const uint32_t *properties, int count, uint32_t *type,
 	return it_num;
 }
 
-static void gic_init_base_addr(paddr_t gicc_base_pa, paddr_t gicd_base_pa)
+static void __maybe_unused probe_redist_base_addrs(vaddr_t *gicr_base_addrs,
+						   paddr_t gicr_base_pa)
+{
+	size_t sz = GICR_V3_PCPUBASE_SIZE;
+	paddr_t pa = gicr_base_pa;
+	size_t core_pos = 0;
+	uint64_t mt_bit = 0;
+	uint64_t mpidr = 0;
+	uint64_t tv = 0;
+	vaddr_t va = 0;
+
+#ifdef ARM64
+	mt_bit = read_mpidr_el1() & MPIDR_MT_MASK;
+#endif
+	do {
+		va = core_mmu_get_va(pa, MEM_AREA_IO_SEC, sz);
+		if (!va)
+			panic();
+		tv = io_read64(va + GICR_TYPER);
+
+		/*
+		 * Extract an mpidr from the Type register to calculate the
+		 * core position of this redistributer instance.
+		 */
+		mpidr = mt_bit;
+		mpidr |= SHIFT_U64((tv >> GICR_TYPER_AFF3_SHIFT) &
+				   MPIDR_AFFLVL_MASK, MPIDR_AFF3_SHIFT);
+		mpidr |= (tv >> GICR_TYPER_AFF0_SHIFT) &
+			 (MPIDR_AFF0_MASK | MPIDR_AFF1_MASK | MPIDR_AFF2_MASK);
+		core_pos = get_core_pos_mpidr(mpidr);
+		if (core_pos < CFG_TEE_CORE_NB_CORE) {
+			DMSG("GICR_BASE[%zu] at %#"PRIxVA, core_pos, va);
+			gicr_base_addrs[core_pos] = va;
+		} else {
+			EMSG("Skipping too large core_pos %zu from GICR_TYPER",
+			     core_pos);
+		}
+		pa += sz;
+	} while (!(tv & GICR_TYPER_LAST));
+}
+
+static void gic_init_base_addr(paddr_t gicc_base_pa, paddr_t gicd_base_pa,
+			       paddr_t gicr_base_pa __maybe_unused)
 {
 	struct gic_data *gd = &gic_data;
 	vaddr_t gicc_base = 0;
 	vaddr_t gicd_base = 0;
+	uint32_t vers __maybe_unused = 0;
 
 	assert(cpu_mmu_enabled());
 
@@ -221,7 +470,14 @@ static void gic_init_base_addr(paddr_t gicc_base_pa, paddr_t gicd_base_pa)
 	if (!gicd_base)
 		panic();
 
-	if (!IS_ENABLED(CFG_ARM_GICV3)) {
+	vers = io_read32(gicd_base + GICD_PIDR2);
+	vers >>= GICD_PIDR2_ARCHREV_SHIFT;
+	vers &= GICD_PIDR2_ARCHREV_MASK;
+
+	if (IS_ENABLED(CFG_ARM_GICV3)) {
+		assert(vers == 3);
+	} else {
+		assert(vers == 2 || vers == 1);
 		gicc_base = core_mmu_get_va(gicc_base_pa, MEM_AREA_IO_SEC,
 					    GIC_CPU_REG_SIZE);
 		if (!gicc_base)
@@ -231,21 +487,52 @@ static void gic_init_base_addr(paddr_t gicc_base_pa, paddr_t gicd_base_pa)
 	gd->gicc_base = gicc_base;
 	gd->gicd_base = gicd_base;
 	gd->max_it = probe_max_it(gicc_base, gicd_base);
+#if defined(CFG_ARM_GICV3)
+	if (affinity_routing_is_enabled(gd) && gicr_base_pa)
+		probe_redist_base_addrs(gd->gicr_base, gicr_base_pa);
+#endif
 	gd->chip.ops = &gic_ops;
 
 	if (IS_ENABLED(CFG_DT))
 		gd->chip.dt_get_irq = gic_dt_get_irq;
 }
 
-void gic_init(paddr_t gicc_base_pa, paddr_t gicd_base_pa)
+void gic_init_v3(paddr_t gicc_base_pa, paddr_t gicd_base_pa,
+		 paddr_t gicr_base_pa)
 {
 	struct gic_data __maybe_unused *gd = &gic_data;
 	size_t __maybe_unused n = 0;
 
-	gic_init_base_addr(gicc_base_pa, gicd_base_pa);
+	gic_init_base_addr(gicc_base_pa, gicd_base_pa, gicr_base_pa);
 
+#if defined(CFG_WITH_ARM_TRUSTED_FW)
 	/* GIC configuration is initialized from TF-A when embedded */
-#ifndef CFG_WITH_ARM_TRUSTED_FW
+	if (affinity_routing_is_enabled(gd)) {
+		/* Secure affinity routing enabled */
+		vaddr_t gicr_base = get_gicr_base(gd);
+
+		if (gicr_base) {
+			gd->per_cpu_group_status = io_read32(gicr_base +
+							     GICR_IGROUPR0);
+			gd->per_cpu_group_modifier = io_read32(gicr_base +
+							       GICR_IGRPMODR0);
+		} else {
+			IMSG("GIC redistributor base address not provided");
+			IMSG("Assuming default GIC group status and modifier");
+			gd->per_cpu_group_status = 0xffff00ff;
+			gd->per_cpu_group_modifier = ~gd->per_cpu_group_status;
+		}
+	} else {
+		/* Legacy operation with secure affinity routing disabled */
+		gd->per_cpu_group_status = io_read32(gd->gicd_base +
+						     GICD_IGROUPR(0));
+		gd->per_cpu_group_modifier = ~gd->per_cpu_group_status;
+	}
+#else /*!CFG_WITH_ARM_TRUSTED_FW*/
+	/*
+	 * Without TF-A, GIC is always configured in for legacy operation
+	 * with secure affinity routing disabled.
+	 */
 	for (n = 0; n <= gd->max_it / NUM_INTS_PER_REG; n++) {
 		/* Disable interrupts */
 		io_write32(gd->gicd_base + GICD_ICENABLER(n), 0xffffffff);
@@ -260,7 +547,10 @@ void gic_init(paddr_t gicc_base_pa, paddr_t gicd_base_pa)
 			 * ID8-ID15(SGI)  for Secure interrupts.
 			 * All PPI config as Non-secure interrupts.
 			 */
-			io_write32(gd->gicd_base + GICD_IGROUPR(n), 0xffff00ff);
+			gd->per_cpu_group_status = 0xffff00ff;
+			gd->per_cpu_group_modifier = ~gd->per_cpu_group_status;
+			io_write32(gd->gicd_base + GICD_IGROUPR(n),
+				   gd->per_cpu_group_status);
 		} else {
 			io_write32(gd->gicd_base + GICD_IGROUPR(n), 0xffffffff);
 		}
@@ -280,9 +570,9 @@ void gic_init(paddr_t gicc_base_pa, paddr_t gicd_base_pa)
 	io_write32(gd->gicc_base + GICC_CTLR, GICC_CTLR_FIQEN |
 		   GICC_CTLR_ENABLEGRP0 | GICC_CTLR_ENABLEGRP1);
 	io_setbits32(gd->gicd_base + GICD_CTLR,
-		     GICD_CTLR_ENABLEGRP0 | GICD_CTLR_ENABLEGRP1);
+		     GICD_CTLR_ENABLEGRP0 | GICD_CTLR_ENABLEGRP1NS);
 #endif
-#endif /*CFG_WITH_ARM_TRUSTED_FW*/
+#endif /*!CFG_WITH_ARM_TRUSTED_FW*/
 
 	interrupt_main_init(&gic_data.chip);
 }
@@ -389,34 +679,74 @@ static void gic_it_set_pending(struct gic_data *gd, size_t it)
 	io_write32(gd->gicd_base + GICD_ISPENDR(idx), mask);
 }
 
+static void assert_cpu_mask_is_valid(uint32_t cpu_mask)
+{
+	bool __maybe_unused to_others = cpu_mask & ITR_CPU_MASK_TO_OTHER_CPUS;
+	bool __maybe_unused to_current = cpu_mask & ITR_CPU_MASK_TO_THIS_CPU;
+	bool __maybe_unused to_list = cpu_mask & 0xff;
+
+	/* One and only one of the bit fields shall be non-zero */
+	assert(to_others + to_current + to_list == 1);
+}
+
 static void gic_it_raise_sgi(struct gic_data *gd __maybe_unused, size_t it,
-			     uint8_t cpu_mask, uint8_t group)
+			     uint32_t cpu_mask, bool ns)
 {
 #if defined(CFG_ARM_GICV3)
-	/* Only support sending SGI to the cores in the same cluster now */
 	uint32_t mask_id = it & 0xf;
-	uint32_t mask_cpu = cpu_mask & 0xff;
-	uint64_t mpidr = read_mpidr();
-	uint64_t mask_aff1 = (mpidr & MPIDR_AFF1_MASK) >> MPIDR_AFF1_SHIFT;
-	uint64_t mask_aff2 = (mpidr & MPIDR_AFF2_MASK) >> MPIDR_AFF2_SHIFT;
-	uint64_t mask_aff3 = (mpidr & MPIDR_AFF3_MASK) >> MPIDR_AFF3_SHIFT;
-	uint64_t mask = (mask_cpu |
-			SHIFT_U64(mask_aff1, 16) |
-			SHIFT_U64(mask_id, 24)   |
-			SHIFT_U64(mask_aff2, 32) |
-			SHIFT_U64(mask_aff3, 48));
+	uint64_t mask = SHIFT_U64(mask_id, 24);
+
+	assert_cpu_mask_is_valid(cpu_mask);
+
+	if (cpu_mask & ITR_CPU_MASK_TO_OTHER_CPUS) {
+		mask |= BIT64(GICC_SGI_IRM_BIT);
+	} else {
+		uint64_t mpidr = read_mpidr();
+		uint64_t mask_aff1 = (mpidr & MPIDR_AFF1_MASK) >>
+				     MPIDR_AFF1_SHIFT;
+		uint64_t mask_aff2 = (mpidr & MPIDR_AFF2_MASK) >>
+				     MPIDR_AFF2_SHIFT;
+		uint64_t mask_aff3 = (mpidr & MPIDR_AFF3_MASK) >>
+				     MPIDR_AFF3_SHIFT;
+
+		mask |= SHIFT_U64(mask_aff1, GICC_SGI_AFF1_SHIFT);
+		mask |= SHIFT_U64(mask_aff2, GICC_SGI_AFF2_SHIFT);
+		mask |= SHIFT_U64(mask_aff3, GICC_SGI_AFF3_SHIFT);
+
+		if (cpu_mask & ITR_CPU_MASK_TO_THIS_CPU) {
+			mask |= BIT32(mpidr & 0xf);
+		} else {
+			/*
+			 * Only support sending SGI to the cores in the
+			 * same cluster now.
+			 */
+			mask |= cpu_mask & 0xff;
+		}
+	}
 
 	/* Raise the interrupt */
-	if (group)
+	if (ns)
 		write_icc_asgi1r(mask);
 	else
 		write_icc_sgi1r(mask);
 #else
-	uint32_t mask_id = it & 0xf;
-	uint32_t mask_group = group & 0x1;
-	uint32_t mask_cpu = cpu_mask & 0xff;
-	uint32_t mask = (mask_id | SHIFT_U32(mask_group, 15) |
-		SHIFT_U32(mask_cpu, 16));
+	uint32_t mask_id = it & GICD_SGIR_SIGINTID_MASK;
+	uint32_t mask_group = ns;
+	uint32_t mask = mask_id;
+
+	assert_cpu_mask_is_valid(cpu_mask);
+
+	mask |= SHIFT_U32(mask_group, GICD_SGIR_NSATT_SHIFT);
+	if (cpu_mask & ITR_CPU_MASK_TO_OTHER_CPUS) {
+		mask |= SHIFT_U32(GICD_SGIR_TO_OTHER_CPUS,
+				  GICD_SGIR_TARGET_LIST_FILTER_SHIFT);
+	} else if (cpu_mask & ITR_CPU_MASK_TO_THIS_CPU) {
+		mask |= SHIFT_U32(GICD_SGIR_TO_THIS_CPU,
+				  GICD_SGIR_TARGET_LIST_FILTER_SHIFT);
+	} else {
+		mask |= SHIFT_U32(cpu_mask & 0xff,
+				  GICD_SGIR_CPU_TARGET_LIST_SHIFT);
+	}
 
 	/* Raise the interrupt */
 	io_write32(gd->gicd_base + GICD_SGIR, mask);
@@ -574,22 +904,18 @@ static void gic_op_raise_pi(struct itr_chip *chip, size_t it)
 }
 
 static void gic_op_raise_sgi(struct itr_chip *chip, size_t it,
-			uint8_t cpu_mask)
+			     uint32_t cpu_mask)
 {
 	struct gic_data *gd = container_of(chip, struct gic_data, chip);
+	bool ns = false;
 
 	assert(gd == &gic_data);
 
 	/* Should be Software Generated Interrupt */
 	assert(it < NUM_SGI);
 
-	if (it > gd->max_it)
-		panic();
-
-	if (it < NUM_NS_SGI)
-		gic_it_raise_sgi(gd, it, cpu_mask, 1);
-	else
-		gic_it_raise_sgi(gd, it, cpu_mask, 0);
+	ns = BIT32(it) & gd->per_cpu_group_status;
+	gic_it_raise_sgi(gd, it, cpu_mask, ns);
 }
 
 static void gic_op_set_affinity(struct itr_chip *chip, size_t it,
@@ -604,3 +930,64 @@ static void gic_op_set_affinity(struct itr_chip *chip, size_t it,
 
 	gic_it_set_cpu_mask(gd, it, cpu_mask);
 }
+
+#ifdef CFG_DT
+/* Callback for "interrupts" and "interrupts-extended" DT node properties */
+static TEE_Result dt_get_gic_chip_cb(struct dt_pargs *arg, void *priv_data,
+				     struct itr_desc *itr_desc)
+{
+	int itr_num = DT_INFO_INVALID_INTERRUPT;
+	struct itr_chip *chip = priv_data;
+	uint32_t phandle_args[2] = { };
+	uint32_t type = 0;
+	uint32_t prio = 0;
+
+	assert(arg && itr_desc);
+
+	/*
+	 * gic_dt_get_irq() expects phandle arguments passed are still in DT
+	 * format (big-endian) whereas struct dt_pargs carries converted
+	 * formats. Therefore swap again phandle arguments. gic_dt_get_irq()
+	 * consumes only the 2 first arguments.
+	 */
+	if (arg->args_count < 2)
+		return TEE_ERROR_GENERIC;
+	phandle_args[0] = cpu_to_fdt32(arg->args[0]);
+	phandle_args[1] = cpu_to_fdt32(arg->args[1]);
+
+	itr_num = gic_dt_get_irq((const void *)phandle_args, 2, &type, &prio);
+	if (itr_num == DT_INFO_INVALID_INTERRUPT)
+		return TEE_ERROR_GENERIC;
+
+	gic_op_add(chip, itr_num, type, prio);
+
+	itr_desc->chip = chip;
+	itr_desc->itr_num = itr_num;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result gic_probe(const void *fdt, int offs, const void *cd __unused)
+{
+	if (interrupt_register_provider(fdt, offs, dt_get_gic_chip_cb,
+					&gic_data.chip))
+		panic();
+
+	return TEE_SUCCESS;
+}
+
+static const struct dt_device_match gic_match_table[] = {
+	{ .compatible = "arm,cortex-a15-gic" },
+	{ .compatible = "arm,cortex-a7-gic" },
+	{ .compatible = "arm,cortex-a5-gic" },
+	{ .compatible = "arm,cortex-a9-gic" },
+	{ .compatible = "arm,gic-400" },
+	{ }
+};
+
+DEFINE_DT_DRIVER(gic_dt_driver) = {
+	.name = "gic",
+	.match_table = gic_match_table,
+	.probe = gic_probe,
+};
+#endif /*CFG_DT*/
diff --git a/core/drivers/gpio/gpio.c b/core/drivers/gpio/gpio.c
index a3e4f23155da42e246a8dd8b3c6d91b151ff49f8..457599ecd1464e1090c3bbd2c00dbfdf7c3558d0 100644
--- a/core/drivers/gpio/gpio.c
+++ b/core/drivers/gpio/gpio.c
@@ -32,14 +32,19 @@ TEE_Result gpio_dt_alloc_pin(struct dt_pargs *pargs, struct gpio **out_gpio)
 
 static char *gpio_get_dt_prop_name(const char *gpio_name)
 {
+	int ret = 0;
 	char *prop_name = NULL;
-	int max_len = strlen(gpio_name) + strlen("-gpios") + 1;
+	size_t max_len = strlen(gpio_name) + strlen("-gpios") + 1;
 
 	prop_name = calloc(1, max_len);
 	if (!prop_name)
 		return NULL;
 
-	snprintf(prop_name, max_len, "%s-gpios", gpio_name);
+	ret = snprintf(prop_name, max_len, "%s-gpios", gpio_name);
+	if (ret < 0 || (size_t)ret >= max_len) {
+		free(prop_name);
+		return NULL;
+	}
 
 	return prop_name;
 }
diff --git a/core/drivers/hisi_trng.c b/core/drivers/hisi_trng.c
new file mode 100644
index 0000000000000000000000000000000000000000..3d865e40a85ccac675ddebe6db0bcb2a63c64d19
--- /dev/null
+++ b/core/drivers/hisi_trng.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2023 HiSilicon Limited. */
+
+#include <initcall.h>
+#include <io.h>
+#include <kernel/spinlock.h>
+#include <malloc.h>
+#include <mm/core_memprot.h>
+#include <platform_config.h>
+#include <rng_support.h>
+#include <string.h>
+
+#define HTRNG_RANDATA_REG 0xF0
+#define HTRNG_BYTES 4U
+
+#define POLL_PERIOD 10
+#define POLL_TIMEOUT 1000
+
+struct hisi_trng {
+	vaddr_t base;
+};
+
+static unsigned int trng_lock = SPINLOCK_UNLOCK;
+static struct hisi_trng *trng_dev;
+
+static TEE_Result trng_read(uint32_t *val)
+{
+	TEE_Result ret = TEE_SUCCESS;
+	uint32_t exceptions = 0;
+
+	exceptions = cpu_spin_lock_xsave(&trng_lock);
+	if (IO_READ32_POLL_TIMEOUT(trng_dev->base + HTRNG_RANDATA_REG,
+				   *val, *val, POLL_PERIOD, POLL_TIMEOUT)) {
+		EMSG("Hardware busy");
+		ret = TEE_ERROR_BUSY;
+	}
+	cpu_spin_unlock_xrestore(&trng_lock, exceptions);
+
+	return ret;
+}
+
+TEE_Result hw_get_random_bytes(void *buf, size_t len)
+{
+	TEE_Result ret = TEE_ERROR_GENERIC;
+	size_t current_len = 0;
+	uint32_t val = 0;
+	size_t size = 0;
+
+	if (!trng_dev) {
+		EMSG("No valid TRNG device");
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+
+	if (!buf || !len) {
+		EMSG("Invalid input parameter");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	while (current_len < len) {
+		ret = trng_read(&val);
+		if (ret)
+			return TEE_ERROR_BUSY;
+
+		size = MIN(HTRNG_BYTES, len - current_len);
+		memcpy((uint8_t *)buf + current_len, &val, size);
+		current_len += size;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result trng_init(void)
+{
+	DMSG("TRNG driver init start");
+	trng_dev = calloc(1, sizeof(struct hisi_trng));
+	if (!trng_dev) {
+		EMSG("Fail to calloc trng device");
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	trng_dev->base = (vaddr_t)phys_to_virt_io(HISI_TRNG_BASE,
+						  HISI_TRNG_SIZE);
+	if (!trng_dev->base) {
+		EMSG("Fail to get trng io_base");
+		free(trng_dev);
+		trng_dev = NULL;
+		return TEE_ERROR_ACCESS_DENIED;
+	}
+
+	DMSG("TRNG driver init done");
+
+	return TEE_SUCCESS;
+}
+
+early_init(trng_init);
diff --git a/core/drivers/imx_wdog.c b/core/drivers/imx_wdog.c
index f1642a238aa7eccdb7b18433ec0675b14c163fae..bdd5f3963e56e919432d3dc64a43685d6de8f540 100644
--- a/core/drivers/imx_wdog.c
+++ b/core/drivers/imx_wdog.c
@@ -47,7 +47,7 @@ void imx_wdog_restart(bool external_reset __maybe_unused)
 	uint32_t val = 0;
 
 	if (!wdog_base) {
-		EMSG("No wdog mapped\n");
+		EMSG("No wdog mapped");
 		panic();
 	}
 
@@ -67,7 +67,7 @@ void imx_wdog_restart(bool external_reset __maybe_unused)
 	else
 		val = 0x24;
 
-	DMSG("val %x\n", val);
+	DMSG("val %x", val);
 
 	io_write16(wdog_base + WDT_WCR, val);
 	dsb();
@@ -105,7 +105,7 @@ static TEE_Result imx_wdog_base(vaddr_t *wdog_vbase)
 
 	fdt = get_dt();
 	if (!fdt) {
-		EMSG("No DTB\n");
+		EMSG("No DTB");
 		return TEE_ERROR_NOT_SUPPORTED;
 	}
 
@@ -131,7 +131,7 @@ static TEE_Result imx_wdog_base(vaddr_t *wdog_vbase)
 	}
 
 	if (!found_off) {
-		EMSG("No Watchdog found in DTB\n");
+		EMSG("No Watchdog found in DTB");
 		return TEE_ERROR_ITEM_NOT_FOUND;
 	}
 
@@ -139,7 +139,7 @@ static TEE_Result imx_wdog_base(vaddr_t *wdog_vbase)
 					"fsl,ext-reset-output");
 
 	if (dt_map_dev(fdt, found_off, &vbase, &sz, DT_MAP_AUTO) < 0) {
-		EMSG("Failed to map Watchdog\n");
+		EMSG("Failed to map Watchdog");
 		return TEE_ERROR_ITEM_NOT_FOUND;
 	}
 
diff --git a/core/drivers/ls_dspi.c b/core/drivers/ls_dspi.c
index a7055e09dd85e5aee044fd885f88287da0a09e98..23942aa0adcffc7ccd6a503b0489f191cdfca42e 100644
--- a/core/drivers/ls_dspi.c
+++ b/core/drivers/ls_dspi.c
@@ -547,7 +547,7 @@ static TEE_Result get_info_from_device_tree(struct ls_dspi_data *dspi_data)
 	 */
 	fdt = get_dt();
 	if (!fdt) {
-		EMSG("Unable to get DTB, DSPI init failed\n");
+		EMSG("Unable to get DTB, DSPI init failed");
 		return TEE_ERROR_ITEM_NOT_FOUND;
 	}
 
diff --git a/core/drivers/ls_gpio.c b/core/drivers/ls_gpio.c
index 5d4a297dcd9312b48c5873c144e8258c79830bef..27a735207f9d88da903e3c91b23c82a5f7c6d3ef 100644
--- a/core/drivers/ls_gpio.c
+++ b/core/drivers/ls_gpio.c
@@ -187,7 +187,7 @@ static TEE_Result get_info_from_device_tree(struct ls_gpio_chip_data *gpio_data)
 	 */
 	fdt = get_embedded_dt();
 	if (!fdt) {
-		EMSG("Unable to get the Embedded DTB, GPIO init failed\n");
+		EMSG("Unable to get the Embedded DTB, GPIO init failed");
 		return TEE_ERROR_GENERIC;
 	}
 
diff --git a/core/drivers/ls_i2c.c b/core/drivers/ls_i2c.c
index 87d73815fe8fcd9d66d19ee376d1b5986ccb98dc..91df01385a16cede3d55885812f6771950ad827b 100644
--- a/core/drivers/ls_i2c.c
+++ b/core/drivers/ls_i2c.c
@@ -132,7 +132,7 @@ TEE_Result i2c_init(struct ls_i2c_data *i2c_data)
 	 */
 	fdt = get_embedded_dt();
 	if (!fdt) {
-		EMSG("Unable to get the Embedded DTB, I2C init failed\n");
+		EMSG("Unable to get the Embedded DTB, I2C init failed");
 		return TEE_ERROR_GENERIC;
 	}
 
diff --git a/core/drivers/nvmem/atmel_sfc.c b/core/drivers/nvmem/atmel_sfc.c
new file mode 100644
index 0000000000000000000000000000000000000000..e034aa706201e2bb3ad0a7dbf9e05f653e61db46
--- /dev/null
+++ b/core/drivers/nvmem/atmel_sfc.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2021, Microchip
+ */
+
+#include <drivers/nvmem.h>
+#include <io.h>
+#include <kernel/dt_driver.h>
+#include <malloc.h>
+#include <matrix.h>
+#include <sama5d2.h>
+#include <string.h>
+#include <tee_api_defines.h>
+#include <tee_api_types.h>
+#include <types_ext.h>
+
+#define ATMEL_SFC_KR		0x0
+#define ATMEL_SFC_SR		0x1C
+#define ATMEL_SFC_SR_PGMC	BIT(0)
+#define ATMEL_SFC_SR_PGMF	BIT(1)
+#define ATMEL_SFC_DR		0x20
+
+#define ATMEL_SFC_CELLS_32	17
+#define ATMEL_SFC_CELLS_8	(ATMEL_SFC_CELLS_32 * sizeof(uint32_t))
+
+struct atmel_sfc {
+	vaddr_t base;
+	uint8_t fuses[ATMEL_SFC_CELLS_8];
+};
+
+static TEE_Result atmel_sfc_read_cell(struct nvmem_cell *cell, uint8_t *data)
+{
+	struct atmel_sfc *atmel_sfc = cell->drv_data;
+
+	memcpy(data, &atmel_sfc->fuses[cell->offset], cell->len);
+
+	return TEE_SUCCESS;
+}
+
+static void atmel_sfc_put_cell(struct nvmem_cell *cell)
+{
+	free(cell);
+}
+
+static const struct nvmem_ops atmel_sfc_nvmem_ops = {
+	.read_cell = atmel_sfc_read_cell,
+	.put_cell = atmel_sfc_put_cell,
+};
+
+static TEE_Result atmel_sfc_dt_get(struct dt_pargs *args,
+				   void *data, struct nvmem_cell **out_cell)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct nvmem_cell *cell = NULL;
+
+	/* Freed from atmel_sfc_put_cell() */
+	cell = calloc(1, sizeof(*cell));
+	if (!cell)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	res = nvmem_cell_parse_dt(args->fdt, args->phandle_node, cell);
+	if (res)
+		goto out_free;
+
+	if (cell->offset + cell->len > ATMEL_SFC_CELLS_8) {
+		res = TEE_ERROR_GENERIC;
+		goto out_free;
+	}
+
+	cell->ops = &atmel_sfc_nvmem_ops;
+	cell->drv_data = data;
+	*out_cell = cell;
+
+	return TEE_SUCCESS;
+
+out_free:
+	free(cell);
+
+	return res;
+}
+
+static void atmel_sfc_read_fuse(struct atmel_sfc *atmel_sfc)
+{
+	size_t i = 0;
+	uint32_t val = 0;
+
+	for (i = 0; i < ATMEL_SFC_CELLS_32; i++) {
+		val = io_read32(atmel_sfc->base + ATMEL_SFC_DR + i * 4);
+		memcpy(&atmel_sfc->fuses[i * 4], &val, sizeof(val));
+	}
+}
+
+static TEE_Result atmel_sfc_probe(const void *fdt, int node,
+				  const void *compat_data __unused)
+{
+	vaddr_t base = 0;
+	size_t size = 0;
+	struct atmel_sfc *atmel_sfc = NULL;
+
+	if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC)
+		return TEE_ERROR_NODE_DISABLED;
+
+	matrix_configure_periph_secure(AT91C_ID_SFC);
+
+	if (dt_map_dev(fdt, node, &base, &size, DT_MAP_AUTO) < 0)
+		return TEE_ERROR_GENERIC;
+
+	atmel_sfc = calloc(1, sizeof(*atmel_sfc));
+	if (!atmel_sfc)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	atmel_sfc->base = base;
+
+	atmel_sfc_read_fuse(atmel_sfc);
+
+	return nvmem_register_provider(fdt, node, atmel_sfc_dt_get, atmel_sfc);
+}
+
+static const struct dt_device_match atmel_sfc_match_table[] = {
+	{ .compatible = "atmel,sama5d2-sfc" },
+	{ }
+};
+
+DEFINE_DT_DRIVER(atmel_sfc_dt_driver) = {
+	.name = "atmel_sfc",
+	.type = DT_DRIVER_NVMEM,
+	.match_table = atmel_sfc_match_table,
+	.probe = atmel_sfc_probe,
+};
diff --git a/core/drivers/nvmem/nvmem.c b/core/drivers/nvmem/nvmem.c
new file mode 100644
index 0000000000000000000000000000000000000000..7d30c2c166d69c10862625a24a6880bc7dc9a88b
--- /dev/null
+++ b/core/drivers/nvmem/nvmem.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2023, Microchip
+ */
+
+#include <drivers/nvmem.h>
+#include <kernel/dt.h>
+#include <libfdt.h>
+
+TEE_Result nvmem_cell_parse_dt(const void *fdt, int nodeoffset,
+			       struct nvmem_cell *cell)
+{
+	size_t buf_len = 0;
+	paddr_t offset = 0;
+
+	buf_len = fdt_reg_size(fdt, nodeoffset);
+	if (buf_len == DT_INFO_INVALID_REG_SIZE)
+		return TEE_ERROR_GENERIC;
+
+	offset = fdt_reg_base_address(fdt, nodeoffset);
+	if (offset == DT_INFO_INVALID_REG)
+		return TEE_ERROR_GENERIC;
+
+	cell->len = buf_len;
+	cell->offset = offset;
+
+	return TEE_SUCCESS;
+}
+
+TEE_Result nvmem_get_cell_by_name(const void *fdt, int nodeoffset,
+				  const char *name, struct nvmem_cell **cell)
+{
+	int index = 0;
+
+	index = fdt_stringlist_search(fdt, nodeoffset, "nvmem-cell-names",
+				      name);
+	if (index < 0)
+		return TEE_ERROR_ITEM_NOT_FOUND;
+
+	return nvmem_get_cell_by_index(fdt, nodeoffset, index, cell);
+}
+
+TEE_Result nvmem_get_cell_by_index(const void *fdt,
+				   int nodeoffset,
+				   unsigned int index,
+				   struct nvmem_cell **out_cell)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	void *cell = NULL;
+
+	res = dt_driver_device_from_node_idx_prop("nvmem-cells", fdt,
+						  nodeoffset, index,
+						  DT_DRIVER_NVMEM, &cell);
+	if (!res)
+		*out_cell = cell;
+
+	return res;
+}
+
+TEE_Result nvmem_cell_malloc_and_read(struct nvmem_cell *cell,
+				      uint8_t **out_data)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	if (!cell->ops->read_cell)
+		return TEE_ERROR_NOT_SUPPORTED;
+
+	*out_data = malloc(cell->len);
+	if (!out_data)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	res = cell->ops->read_cell(cell, *out_data);
+	if (res)
+		free(*out_data);
+
+	return res;
+}
diff --git a/core/drivers/nvmem/sub.mk b/core/drivers/nvmem/sub.mk
new file mode 100644
index 0000000000000000000000000000000000000000..cec703b14ffb8e49c21ae4e282197c72ede540e9
--- /dev/null
+++ b/core/drivers/nvmem/sub.mk
@@ -0,0 +1,2 @@
+srcs-y += nvmem.c
+srcs-$(CFG_ATMEL_SFC) += atmel_sfc.c
diff --git a/core/drivers/plic.c b/core/drivers/plic.c
index be14656f08c65e78bfb8ad7cd67a4e06472f5f5b..3356dacb8feef97e5b602becee80288dc698504d 100644
--- a/core/drivers/plic.c
+++ b/core/drivers/plic.c
@@ -197,7 +197,7 @@ static void plic_op_raise_pi(struct itr_chip *chip, size_t it)
 }
 
 static void plic_op_raise_sgi(struct itr_chip *chip __unused,
-			      size_t it __unused, uint8_t cpu_mask __unused)
+			      size_t it __unused, uint32_t cpu_mask __unused)
 {
 }
 
@@ -275,7 +275,7 @@ void plic_it_handle(void)
 	struct plic_data *pd = &plic_data;
 	uint32_t id = plic_claim_interrupt(pd);
 
-	if (id <= pd->max_it)
+	if (id > 0 && id <= pd->max_it)
 		interrupt_call_handlers(&pd->chip, id);
 	else
 		DMSG("ignoring interrupt %" PRIu32, id);
diff --git a/core/drivers/regulator/regulator.c b/core/drivers/regulator/regulator.c
index 247e2313dc8e7fca7b19c4370d173d439fd6c7fb..4691913062b6dd41ab797afeeab6bb53cbc01b51 100644
--- a/core/drivers/regulator/regulator.c
+++ b/core/drivers/regulator/regulator.c
@@ -213,21 +213,29 @@ TEE_Result regulator_set_voltage(struct regulator *regulator, int level_uv)
 }
 
 TEE_Result regulator_supported_voltages(struct regulator *regulator,
-					struct regulator_voltages **voltages)
+					struct regulator_voltages_desc **desc,
+					const int **levels)
 {
-	assert(regulator && voltages);
+	assert(regulator && desc && levels);
 
 	if (regulator->ops->supported_voltages) {
 		TEE_Result res = TEE_ERROR_GENERIC;
 
-		res = regulator->ops->supported_voltages(regulator, voltages);
-		if (res == TEE_SUCCESS)
-			return TEE_SUCCESS;
+		res = regulator->ops->supported_voltages(regulator, desc,
+							 levels);
 		if (res != TEE_ERROR_NOT_SUPPORTED)
 			return res;
+	} else {
+		*desc = &regulator->voltages_fallback.desc;
+		*levels = regulator->voltages_fallback.levels;
 	}
 
-	*voltages = &regulator->voltages_fallback.desc;
+	assert(((*desc)->type == VOLTAGE_TYPE_FULL_LIST &&
+		(*levels)[0] >= regulator->min_uv && (*desc)->num_levels &&
+		(*levels)[(*desc)->num_levels - 1] <= regulator->max_uv) ||
+	       ((*desc)->type == VOLTAGE_TYPE_INCREMENT &&
+		(*levels)[0] >= regulator->min_uv &&
+		(*levels)[1] <= regulator->max_uv));
 
 	return TEE_SUCCESS;
 }
@@ -287,26 +295,6 @@ TEE_Result regulator_register(struct regulator *regulator)
 	return TEE_SUCCESS;
 }
 
-/*
- * Log regulators state
- */
-void regulator_print_state(const char *message __maybe_unused)
-{
-	struct regulator *regulator = NULL;
-
-	DMSG("Regulator state: %s", message);
-	DMSG("name     use\ten\tuV\tmin\tmax\tflags\tsupply");
-
-	SLIST_FOREACH(regulator, &regulator_device_list, link)
-		DMSG("%8s %u\t%d\t%d\t%d\t%d\t%#x\t%s\n",
-		     regulator->name, regulator->refcount,
-		     regulator_is_enabled(regulator),
-		     regulator_get_voltage(regulator),
-		     regulator->min_uv, regulator->max_uv, regulator->flags,
-		     regulator->supply ? regulator_name(regulator->supply) :
-		     "<none>");
-}
-
 /*
  * Clean-up regulators that are not used.
  */
@@ -323,9 +311,187 @@ static TEE_Result regulator_core_cleanup(void)
 		}
 	}
 
-	regulator_print_state(__func__);
+	regulator_print_tree();
 
 	return TEE_SUCCESS;
 }
 
 release_init_resource(regulator_core_cleanup);
+
+/* Return updated message buffer position of NULL on failure */
+static __printf(3, 4) char *add_msg(char *cur, char *end, const char *fmt, ...)
+{
+	va_list ap = { };
+	int max_len = end - cur;
+	int ret = 0;
+
+	va_start(ap, fmt);
+	ret = vsnprintf(cur, max_len, fmt, ap);
+	va_end(ap);
+
+	if (ret < 0 || ret >= max_len)
+		return NULL;
+
+	return cur + ret;
+}
+
+static struct regulator *find_next_regulator(struct regulator *parent,
+					     struct regulator *sibling)
+{
+	struct regulator *regulator = NULL;
+
+	if (sibling)
+		regulator = SLIST_NEXT(sibling, link);
+	else
+		regulator = SLIST_FIRST(&regulator_device_list);
+
+	while (regulator && regulator->supply != parent)
+		regulator = SLIST_NEXT(regulator, link);
+
+	return regulator;
+}
+
+/* Regulator is the last supplied one by its supply in the registered list */
+static bool regulator_is_supply_last_supplied(struct regulator *regulator)
+{
+	return !find_next_regulator(regulator->supply, regulator);
+}
+
+/* Supply last node may already be printed for indentation level @cur_indent */
+static bool indent_with_empty_string(struct regulator *node_regulator,
+				     int node_indent, int cur_indent)
+{
+	struct regulator *r = node_regulator;
+	int n = 0;
+
+	/* Find supply at indentation level @node_indent - @cur_indent - 1 */
+	for (n = 0; n < node_indent - cur_indent - 1; n++)
+		r = r->supply;
+
+	return regulator_is_supply_last_supplied(r);
+}
+
+static void __maybe_unused print_regulator(struct regulator *regulator,
+					   int indent)
+{
+	static const char * const level_unit[] = { "uV", "mV", "V" };
+	int max_unit = ARRAY_SIZE(level_unit);
+	int level_max = 0;
+	int level_min = 0;
+	int level_cur = 0;
+	char msg_buf[128] = { };
+	char *msg_end = msg_buf + sizeof(msg_buf);
+	char *msg = msg_buf;
+	int n_max = 0;
+	int n_min = 0;
+	int n_cur = 0;
+	int n = 0;
+
+	if (indent) {
+		/* Indent for root clock level */
+		msg = add_msg(msg, msg_end, "   ");
+		if (!msg)
+			goto out;
+
+		/* Indent for root supply to regulator supply levels */
+		for (n = 0; n < indent - 1; n++) {
+			if (indent_with_empty_string(regulator, indent, n))
+				msg = add_msg(msg, msg_end, "    ");
+			else
+				msg = add_msg(msg, msg_end, "|   ");
+			if (!msg)
+				goto out;
+		}
+
+		/* Regulator indentation */
+		if (regulator_is_supply_last_supplied(regulator))
+			msg = add_msg(msg, msg_end, "`-- ");
+		else
+			msg = add_msg(msg, msg_end, "|-- ");
+
+		if (!msg)
+			goto out;
+	} else {
+		/* Root supply indentation */
+		msg = add_msg(msg, msg_end, "o- ");
+	}
+
+	regulator_get_range(regulator, &level_min, &level_max);
+	level_cur = regulator_get_voltage(regulator);
+
+	for (n_cur = 1; !(level_cur % 1000) && n_cur < max_unit; n_cur++)
+		level_cur /= 1000;
+	for (n_max = 1; !(level_max % 1000) && n_max < max_unit; n_max++)
+		level_max /= 1000;
+	for (n_min = 1; !(level_min % 1000) && n_min < max_unit; n_min++)
+		level_min /= 1000;
+
+	msg = add_msg(msg, msg_end, "%s \t(%3s / refcnt %u / flags %#"PRIx32
+		      " / %d %s ", regulator_name(regulator),
+		      regulator_is_enabled(regulator) ? "on " : "off",
+		      regulator->refcount, regulator->flags,
+		      level_cur, level_unit[n_cur - 1]);
+	if (!msg)
+		goto out;
+
+	if (level_min == level_max)
+		msg = add_msg(msg, msg_end, "fixed)");
+	else if (level_max == INT_MAX)
+		msg = add_msg(msg, msg_end, "[%d %s .. MAX])",
+			      level_min, level_unit[n_min - 1]);
+	else
+		msg = add_msg(msg, msg_end, "[%d %s .. %d %s])",
+			      level_min, level_unit[n_min - 1],
+			      level_max, level_unit[n_max - 1]);
+
+out:
+	if (!msg)
+		snprintf(msg_end - 4, 4, "...");
+
+	DMSG("%s", msg_buf);
+}
+
+static void print_tree(void)
+{
+	struct regulator *regulator = NULL;
+	struct regulator *parent = NULL;
+	struct regulator *next = NULL;
+	int indent = -1;
+
+	while (true) {
+		next = find_next_regulator(parent, regulator);
+		if (next) {
+			print_regulator(next, indent + 1);
+			/* Enter the subtree of the next regulator */
+			parent = next;
+			indent++;
+			regulator = NULL;
+		} else {
+			/*
+			 * We've processed all children at this level.
+			 * If parent is NULL we're at the top and are done.
+			 */
+			if (!parent)
+				break;
+			/*
+			 * Move up one level to resume with the next
+			 * regulator of the parent.
+			 */
+			regulator = parent;
+			parent = regulator->supply;
+			indent--;
+		}
+	}
+}
+
+void regulator_print_tree(void)
+{
+	if (IS_ENABLED(CFG_DRIVERS_REGULATOR_PRINT_TREE) &&
+	    TRACE_LEVEL >= TRACE_DEBUG) {
+		DMSG("Regulator tree summary");
+		if (SLIST_EMPTY(&regulator_device_list))
+			DMSG("-- No registered regulator");
+		else
+			print_tree();
+	}
+}
diff --git a/core/drivers/regulator/regulator_gpio.c b/core/drivers/regulator/regulator_gpio.c
new file mode 100644
index 0000000000000000000000000000000000000000..a5fa4c28ebbfe32ff477eb3d993bc418037ed5d1
--- /dev/null
+++ b/core/drivers/regulator/regulator_gpio.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2023, STMicroelectronics
+ */
+
+#include <assert.h>
+#include <compiler.h>
+#include <drivers/gpio.h>
+#include <drivers/regulator.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <kernel/delay.h>
+#include <libfdt.h>
+#include <trace.h>
+
+static_assert(GPIO_LEVEL_HIGH == 1 && GPIO_LEVEL_LOW == 0);
+
+/*
+ * struct regulator_gpio - GPIO controlled regulator
+ * @regulator: Preallocated regulator instance
+ * @enable_gpio: GPIO for the enable state of the regulator or NULL if always on
+ * @enable_delay: Time (in microsecond) for the regulator to get enabled
+ * @voltage_gpio: GPIO for the voltage level selection
+ * @voltage_levels_uv: 2 cells array supported voltage levels, increasing order
+ * @voltage_level_high: True if higher voltage level relates to active high GPIO
+ */
+struct regulator_gpio {
+	struct regulator regulator;
+	struct gpio *enable_gpio;
+	unsigned int enable_delay;
+	struct gpio *voltage_gpio;
+	int voltage_levels_uv[2];
+	bool voltage_level_high;
+};
+
+static struct regulator_gpio *regulator_priv(struct regulator *regulator)
+{
+	return container_of(regulator, struct regulator_gpio, regulator);
+}
+
+static TEE_Result regulator_gpio_set_state(struct regulator *regulator,
+					   bool enabled)
+{
+	struct regulator_gpio *regu = regulator_priv(regulator);
+
+	if (regu->enable_gpio) {
+		if (enabled) {
+			gpio_set_value(regu->enable_gpio, GPIO_LEVEL_HIGH);
+			if (regu->enable_delay)
+				udelay(regu->enable_delay);
+		} else {
+			gpio_set_value(regu->enable_gpio, GPIO_LEVEL_LOW);
+		}
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result regulator_gpio_read_state(struct regulator *regulator,
+					    bool *enabled)
+{
+	struct regulator_gpio *regu = regulator_priv(regulator);
+
+	if (regu->enable_gpio)
+		*enabled = gpio_get_value(regu->enable_gpio);
+	else
+		*enabled = true;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result regulator_gpio_set_voltage(struct regulator *regulator,
+					     int level_uv)
+{
+	struct regulator_gpio *regu = regulator_priv(regulator);
+
+	if (level_uv == regu->voltage_levels_uv[0])
+		gpio_set_value(regu->voltage_gpio, GPIO_LEVEL_LOW);
+	else if (level_uv == regu->voltage_levels_uv[1])
+		gpio_set_value(regu->voltage_gpio, GPIO_LEVEL_HIGH);
+	else
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result regulator_gpio_read_voltage(struct regulator *regulator,
+					      int *level_uv)
+{
+	struct regulator_gpio *regu = regulator_priv(regulator);
+
+	*level_uv = regu->voltage_levels_uv[gpio_get_value(regu->voltage_gpio)];
+
+	return TEE_SUCCESS;
+}
+
+static const struct regulator_ops regulator_gpio_ops = {
+	.set_state = regulator_gpio_set_state,
+	.get_state = regulator_gpio_read_state,
+	.set_voltage = regulator_gpio_set_voltage,
+	.get_voltage = regulator_gpio_read_voltage,
+};
+
+static TEE_Result get_enable_gpio(const void *fdt, int node,
+				  struct regulator_gpio *regu)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	const fdt32_t *cuint = NULL;
+	struct gpio *gpio = NULL;
+
+	res = gpio_dt_get_by_index(fdt, node, 0, "enable", &gpio);
+	if (res == TEE_ERROR_ITEM_NOT_FOUND) {
+		regu->enable_gpio = NULL;
+
+		return TEE_SUCCESS;
+	}
+	if (res)
+		return res;
+
+	/* Override active level phandle flag, as per DT bindings */
+	if (dt_have_prop(fdt, node, "enable-active-high"))
+		gpio->dt_flags &= ~GPIO_ACTIVE_LOW;
+	else
+		gpio->dt_flags |= GPIO_ACTIVE_LOW;
+
+	/* Override open drain/open source phandle flag, as per DT bindings */
+	if (dt_have_prop(fdt, node, "gpio-open-drain"))
+		gpio->dt_flags |= GPIO_LINE_OPEN_DRAIN;
+	else
+		gpio->dt_flags &= ~GPIO_LINE_OPEN_DRAIN;
+
+	cuint = fdt_getprop(fdt, node, "startup-delay-us", NULL);
+	if (cuint)
+		regu->enable_delay = fdt32_to_cpu(*cuint);
+
+	gpio_set_direction(gpio, GPIO_DIR_OUT);
+
+	regu->enable_gpio = gpio;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result get_voltage_level_gpio(const void *fdt, int node,
+					 struct regulator_gpio *regu)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	const fdt32_t *cuint = NULL;
+	struct gpio *gpio = NULL;
+	void *gpio_ref = &gpio;
+	int len = 0;
+
+	res = dt_driver_device_from_node_idx_prop("gpios", fdt, node, 0,
+						  DT_DRIVER_GPIO, gpio_ref);
+	if (res)
+		return res;
+
+	/*
+	 * DT bindings allows more than 1 GPIO to control more than
+	 * 2 voltage levels. As it's not used so far in known platforms
+	 * this implementation is simplified to support only 2 voltage
+	 * levels controlled with a single GPIO.
+	 */
+	if (dt_driver_device_from_node_idx_prop("gpios", fdt, node, 1,
+						DT_DRIVER_GPIO, gpio_ref) !=
+	    TEE_ERROR_ITEM_NOT_FOUND) {
+		EMSG("Multiple GPIOs not supported for level control");
+		return TEE_ERROR_GENERIC;
+	}
+
+	cuint = fdt_getprop(fdt, node, "states", &len);
+	if (!cuint || len != 4 * sizeof(fdt32_t)) {
+		EMSG("Node %s expects 2 levels from property \"states\"",
+		     fdt_get_name(fdt, node, NULL));
+		return TEE_ERROR_GENERIC;
+	}
+
+	if (fdt32_to_cpu(*(cuint + 1))) {
+		assert(!fdt32_to_cpu(*(cuint + 3)));
+		regu->voltage_levels_uv[0] = fdt32_to_cpu(*(cuint + 2));
+		regu->voltage_levels_uv[1] = fdt32_to_cpu(*(cuint));
+	} else {
+		assert(fdt32_to_cpu(*(cuint + 3)) == 1);
+		regu->voltage_levels_uv[0] = fdt32_to_cpu(*(cuint));
+		regu->voltage_levels_uv[1] = fdt32_to_cpu(*(cuint + 2));
+		regu->voltage_level_high = true;
+	}
+
+	gpio_set_direction(gpio, GPIO_DIR_OUT);
+
+	regu->voltage_gpio = gpio;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result regulator_gpio_probe(const void *fdt, int node,
+				       const void *compat_data __unused)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct regulator_gpio *regu = NULL;
+	struct regu_dt_desc desc = { };
+	const char *supply_name = NULL;
+	const char *type = NULL;
+	char *regu_name = NULL;
+
+	regu_name = (char *)fdt_get_name(fdt, node, NULL);
+
+	type = fdt_getprop(fdt, node, "regulator-type", NULL);
+	if (type && strcmp(type, "voltage")) {
+		EMSG("Regulator node %s: type \"%s\" not supported",
+		     regu_name, type);
+		res = TEE_ERROR_GENERIC;
+		goto err;
+	}
+
+	regu = calloc(1, sizeof(*regu));
+	if (!regu) {
+		res = TEE_ERROR_OUT_OF_MEMORY;
+		goto err;
+	}
+
+	res = get_enable_gpio(fdt, node, regu);
+	if (res)
+		goto err;
+
+	res = get_voltage_level_gpio(fdt, node, regu);
+	if (res)
+		goto err;
+
+	if (fdt_getprop(fdt, node, "vin-supply", NULL))
+		supply_name = "vin";
+
+	desc = (struct regu_dt_desc){
+		.name = regu_name,
+		.ops = &regulator_gpio_ops,
+		.supply_name = supply_name,
+		.regulator = &regu->regulator,
+	};
+
+	res = regulator_dt_register(fdt, node, node, &desc);
+	if (res) {
+		EMSG("Can't register regulator %s: %#"PRIx32, regu_name, res);
+		goto err;
+	}
+
+	return TEE_SUCCESS;
+
+err:
+	free(regu);
+
+	return res;
+}
+
+static const struct dt_device_match regulator_gpio_match_table[] = {
+	{ .compatible = "regulator-gpio" },
+	{ }
+};
+
+DEFINE_DT_DRIVER(regulator_gpio_dt_driver) = {
+	.name = "regulator-gpio",
+	.match_table = regulator_gpio_match_table,
+	.probe = regulator_gpio_probe,
+};
diff --git a/core/drivers/regulator/stm32_vrefbuf.c b/core/drivers/regulator/stm32_vrefbuf.c
index fc2b6387db2fda5d18ae5fbe4c4d28d2d32def3f..18ccb099b014239954bccd8fb0e2dd77f85f1c7b 100644
--- a/core/drivers/regulator/stm32_vrefbuf.c
+++ b/core/drivers/regulator/stm32_vrefbuf.c
@@ -49,7 +49,8 @@ struct vrefbuf_compat {
  * @regulator: Preallocated instance for the regulator
  * @compat: Compatibility data
  * @voltages_desc: Supported voltage level description
- * @voltages_level: Supplorted levels, must follow @voltages_desc
+ * @voltages_level: Supplorted levels description
+ * @voltages_start_index: start index in compat for supported levels
  */
 struct vrefbuf_regul {
 	vaddr_t base;
@@ -57,8 +58,8 @@ struct vrefbuf_regul {
 	uint64_t disable_timeout;
 	struct regulator regulator;
 	const struct vrefbuf_compat *compat;
-	struct regulator_voltages voltages_desc;
-	int supported_levels[VREFBUF_LEVELS_COUNT];
+	struct regulator_voltages_desc voltages_desc;
+	size_t voltages_start_index;
 };
 
 static const struct vrefbuf_compat stm32mp15_vrefbuf_compat = {
@@ -207,41 +208,47 @@ static TEE_Result vrefbuf_set_voltage(struct regulator *regulator, int level_uv)
 }
 
 static TEE_Result vrefbuf_list_voltages(struct regulator *regulator __unused,
-					struct regulator_voltages **voltages)
+					struct regulator_voltages_desc **desc,
+					const int **levels)
 {
 	struct vrefbuf_regul *vr = regulator_to_vr(regulator);
+	const int *levels_ref = vr->compat->voltages;
 
-	if (!vr->voltages_desc.type) {
-		size_t num_levels = ARRAY_SIZE(vr->compat->voltages);
-		unsigned int index_high = num_levels - 1;
-		unsigned int index_low = 0;
-		unsigned int count = 0;
-		unsigned int n = 0;
-
-		for (n = 0; n <= index_high; n++)
-			if (vr->compat->voltages[n] >= regulator->min_uv)
-				break;
-		if (n > index_high)
-			return TEE_ERROR_GENERIC;
-		index_low = n;
+	*desc = &vr->voltages_desc;
+	*levels = levels_ref + vr->voltages_start_index;
 
-		for (n = index_high; n >= index_low; n--)
-			if (vr->compat->voltages[n] <= regulator->max_uv)
-				break;
-		if (n < index_low)
-			return TEE_ERROR_GENERIC;
-		index_high = n;
+	return TEE_SUCCESS;
+}
 
-		count = index_high - index_low + 1;
+static TEE_Result set_voltages_desc(struct regulator *regulator)
+{
+	struct vrefbuf_regul *vr = regulator_to_vr(regulator);
+	size_t num_levels = ARRAY_SIZE(vr->compat->voltages);
+	int index_high = num_levels - 1;
+	int index_low = 0;
+	int n = 0;
 
-		vr->voltages_desc.type = VOLTAGE_TYPE_FULL_LIST;
-		vr->voltages_desc.num_levels = count;
-		for (n = 0; n < count; n++)
-			vr->supported_levels[n] =
-				vr->compat->voltages[index_low + n];
-	}
+	vr->voltages_desc.type = VOLTAGE_TYPE_FULL_LIST;
 
-	*voltages = &vr->voltages_desc;
+	for (n = 0; n <= index_high; n++)
+		if (vr->compat->voltages[n] >= regulator->min_uv)
+			break;
+	if (n > index_high)
+		return TEE_ERROR_GENERIC;
+	index_low = n;
+
+	for (n = index_high; n >= index_low; n--)
+		if (vr->compat->voltages[n] <= regulator->max_uv)
+			break;
+	if (n < index_low)
+		return TEE_ERROR_GENERIC;
+	index_high = n;
+
+	assert(index_high - index_low + 1 >= 0 && index_low >= 0);
+
+	vr->voltages_desc.type = VOLTAGE_TYPE_FULL_LIST;
+	vr->voltages_desc.num_levels = index_high - index_low + 1;
+	vr->voltages_start_index = index_low;
 
 	return TEE_SUCCESS;
 }
@@ -289,6 +296,12 @@ static TEE_Result stm32_vrefbuf_init(struct regulator *regulator,
 				     const void *fdt __unused,
 				     int node __unused)
 {
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	res = set_voltages_desc(regulator);
+	if (res)
+		return res;
+
 	register_pm_driver_cb(stm32_vrefbuf_pm, regulator, "stm32-vrefbuf");
 
 	return TEE_SUCCESS;
diff --git a/core/drivers/regulator/stm32mp13_regulator_iod.c b/core/drivers/regulator/stm32mp13_regulator_iod.c
new file mode 100644
index 0000000000000000000000000000000000000000..a678d51468dc46d4f15c1dccfd9de07027c57332
--- /dev/null
+++ b/core/drivers/regulator/stm32mp13_regulator_iod.c
@@ -0,0 +1,297 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2021-2023, STMicroelectronics
+ */
+
+#include <assert.h>
+#include <compiler.h>
+#include <drivers/regulator.h>
+#include <drivers/stm32mp1_pwr.h>
+#include <drivers/stm32mp1_syscfg.h>
+#include <drivers/stm32mp13_regulator_iod.h>
+#include <initcall.h>
+#include <io.h>
+#include <kernel/boot.h>
+#include <kernel/dt.h>
+#include <kernel/panic.h>
+#include <kernel/pm.h>
+#include <libfdt.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stm32_util.h>
+#include <trace.h>
+
+#define TIMEOUT_US_10MS		U(10000)
+
+#define IO_VOLTAGE_THRESHOLD_UV	2700000
+
+/*
+ * struct iod_regul - IO domain regulator instance
+ *
+ * @enable_reg: PWR register offset for the IO domain
+ * @enable_mask: Domain enable register bit mask in PWR register
+ * @ready_mask: Domain ready bit mask in PWR register
+ * @valid_mask: Domain valid bit mask in PWR register
+ * @hslv_id: ID of the related HSLV domain
+ * @io_comp_id: ID of the related IO compensation domain
+ * @suspend_state: True if regulator is enabled before suspend, false otherwise
+ * @suspend_level_uv: Voltage level before suspend, in microvolts
+ */
+struct iod_regul {
+	uint32_t enable_reg;
+	uint32_t enable_mask;
+	uint32_t ready_mask;
+	uint32_t valid_mask;
+	enum stm32mp13_hslv_id hslv_id;
+	enum stm32mp13_vddsd_comp_id io_comp_id;
+	bool suspend_state;
+	int suspend_level_uv;
+};
+
+static struct iod_regul iod_regulator_priv[IOD_REGU_COUNT] = {
+	 [IOD_SDMMC1] = {
+		.enable_reg = PWR_CR3_OFF,
+		.enable_mask = PWR_CR3_VDDSD1EN,
+		.ready_mask = PWR_CR3_VDDSD1RDY,
+		.valid_mask = PWR_CR3_VDDSD1VALID,
+		.hslv_id = SYSCFG_HSLV_IDX_SDMMC1,
+		.io_comp_id = SYSCFG_IO_COMP_IDX_SD1,
+	 },
+	 [IOD_SDMMC2] = {
+		.enable_reg = PWR_CR3_OFF,
+		.enable_mask = PWR_CR3_VDDSD2EN,
+		.ready_mask = PWR_CR3_VDDSD2RDY,
+		.valid_mask = PWR_CR3_VDDSD2VALID,
+		.hslv_id = SYSCFG_HSLV_IDX_SDMMC2,
+		.io_comp_id = SYSCFG_IO_COMP_IDX_SD2,
+	 },
+};
+
+static struct regulator *iod_regulator[IOD_REGU_COUNT];
+
+struct regulator *stm32mp1_get_iod_regulator(enum iod_regulator_id index)
+{
+	assert(index >= IOD_SDMMC1 && index < IOD_REGU_COUNT);
+
+	return iod_regulator[index];
+}
+
+static TEE_Result iod_set_state(struct regulator *regu, bool enable)
+{
+	struct iod_regul *iod = regu->priv;
+	uintptr_t pwr_reg = stm32_pwr_base() + iod->enable_reg;
+
+	FMSG("%s: set state %u", regulator_name(regu), enable);
+
+	if (enable) {
+		uint32_t value = 0;
+
+		io_setbits32(pwr_reg, iod->enable_mask);
+
+		if (IO_READ32_POLL_TIMEOUT(pwr_reg, value,
+					   value & iod->ready_mask,
+					   0, TIMEOUT_US_10MS))
+			return TEE_ERROR_GENERIC;
+
+		io_setbits32(pwr_reg, iod->valid_mask);
+		io_clrbits32(pwr_reg, iod->enable_mask);
+
+		stm32mp_set_vddsd_comp_state(iod->io_comp_id, true);
+	} else {
+		stm32mp_set_vddsd_comp_state(iod->io_comp_id, false);
+
+		io_clrbits32(pwr_reg, iod->enable_mask | iod->valid_mask);
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result iod_get_state(struct regulator *regu, bool *enabled)
+{
+	struct iod_regul *iod = regu->priv;
+	uintptr_t pwr_reg = stm32_pwr_base() + iod->enable_reg;
+
+	*enabled = io_read32(pwr_reg) & (iod->enable_mask | iod->valid_mask);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result iod_get_voltage(struct regulator *regu, int *level_uv)
+{
+	*level_uv = regulator_get_voltage(regu->supply);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result iod_set_voltage(struct regulator *regu, int level_uv)
+{
+	struct iod_regul *iod = regu->priv;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	bool iod_enabled = false;
+
+	FMSG("%s: set voltage level to %duV", regulator_name(regu), level_uv);
+
+	res = iod_get_state(regu, &iod_enabled);
+	if (res)
+		return res;
+
+	/* Isolate IOs and disable IOs compensation when changing voltage */
+	if (iod_enabled) {
+		res = iod_set_state(regu, false);
+		if (res)
+			return res;
+	}
+
+	/*
+	 * Set IO to low speed.
+	 * Setting high voltage with IOs in high speed mode may damage the IOs.
+	 */
+	stm32mp_set_hslv_state(iod->hslv_id, false);
+
+	/* Forward set voltage request to the power supply */
+	res = regulator_set_voltage(regu->supply, level_uv);
+	if (res) {
+		EMSG("regulator %s set voltage failed: %#"PRIx32,
+		     regulator_name(regu), res);
+
+		/* Ensure IO domain consistency for current voltage level */
+		level_uv = regulator_get_voltage(regu->supply);
+	}
+
+	if (level_uv <= IO_VOLTAGE_THRESHOLD_UV)
+		stm32mp_set_hslv_state(iod->hslv_id, true);
+
+	if (iod_enabled) {
+		TEE_Result res2 = TEE_ERROR_GENERIC;
+
+		res2 = iod_set_state(regu, true);
+		if (res2)
+			return res2;
+	}
+
+	return res;
+}
+
+static TEE_Result iod_list_voltages(struct regulator *regu,
+				    struct regulator_voltages_desc **desc,
+				    const int **levels)
+{
+	/* Return supply voltage list */
+	return regulator_supported_voltages(regu->supply, desc, levels);
+}
+
+/*
+ * To protect the IOs, we disable High Speed Low Voltage mode before
+ * entering suspend state and restore the configuration when resuming.
+ */
+static TEE_Result iod_pm(enum pm_op op, unsigned int pm_hint __unused,
+			 const struct pm_callback_handle *hdl)
+{
+	struct regulator *regu = hdl->handle;
+	struct iod_regul *iod = regu->priv;
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	assert(op == PM_OP_SUSPEND || op == PM_OP_RESUME);
+
+	if (op == PM_OP_SUSPEND) {
+		FMSG("%s: suspend", regulator_name(regu));
+
+		res = iod_get_state(regu, &iod->suspend_state);
+		if (res)
+			return res;
+
+		res = iod_get_voltage(regu, &iod->suspend_level_uv);
+		if (res)
+			return res;
+
+		stm32mp_set_hslv_state(iod->hslv_id, false);
+	} else {
+		FMSG("%s: resume", regulator_name(regu));
+
+		res = iod_set_voltage(regu, iod->suspend_level_uv);
+		if (res)
+			return res;
+
+		res = iod_set_state(regu, iod->suspend_state);
+		if (res)
+			return res;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result iod_supplied_init(struct regulator *regu,
+				    const void *fdt __unused, int node __unused)
+{
+	struct iod_regul *iod = regu->priv;
+	int index = iod - iod_regulator_priv;
+
+	assert(index >= 0 && index < IOD_REGU_COUNT);
+
+	if (regulator_get_voltage(regu) < IO_VOLTAGE_THRESHOLD_UV)
+		stm32mp_set_hslv_state(iod->hslv_id, true);
+
+	/* Save regulator reference */
+	iod_regulator[index] = regu;
+
+	register_pm_driver_cb(iod_pm, regu, "iod-regulator");
+
+	FMSG("IOD regulator %s intiialized", regulator_name(regu));
+
+	return TEE_SUCCESS;
+}
+
+static const struct regulator_ops iod_ops = {
+	.set_state = iod_set_state,
+	.get_state = iod_get_state,
+	.set_voltage = iod_set_voltage,
+	.get_voltage = iod_get_voltage,
+	.supported_voltages = iod_list_voltages,
+	.supplied_init = iod_supplied_init,
+};
+
+#define DEFINE_REG(_id, _name, _supply_name) { \
+	.name = (_name), \
+	.ops = &iod_ops, \
+	.priv = iod_regulator_priv + (_id), \
+	.supply_name = (_supply_name), \
+}
+
+static struct regu_dt_desc iod_regul_desc[IOD_REGU_COUNT] = {
+	[IOD_SDMMC1] = DEFINE_REG(IOD_SDMMC1, "sdmmc1_io", "vddsd1"),
+	[IOD_SDMMC2] = DEFINE_REG(IOD_SDMMC2, "sdmmc2_io", "vddsd2"),
+};
+
+static TEE_Result iod_regulator_probe(const void *fdt, int node,
+				      const void *compat_data __unused)
+{
+	const char *node_name = NULL;
+	size_t i = 0;
+
+	node_name = fdt_get_name(fdt, node, NULL);
+
+	FMSG("iod probe node '%s'", node_name);
+
+	/* Look up matching regulator name defined in SoC DTSI file */
+	for (i = 0; i < IOD_REGU_COUNT; i++)
+		if (!strcmp(iod_regul_desc[i].name, node_name))
+			break;
+
+	if (i == IOD_REGU_COUNT) {
+		EMSG("Unexpected IO domain node name '%s'", node_name);
+		return TEE_ERROR_GENERIC;
+	}
+
+	return regulator_dt_register(fdt, node, node, iod_regul_desc + i);
+}
+
+static const struct dt_device_match iod_regulator_match_table[] = {
+	{ .compatible = "st,stm32mp13-iod" },
+	{ }
+};
+
+DEFINE_DT_DRIVER(stm32mp13_regulator_iod_dt_driver) = {
+	.name = "stm32mp13-iod-regulator",
+	.match_table = iod_regulator_match_table,
+	.probe = iod_regulator_probe,
+};
diff --git a/core/drivers/regulator/sub.mk b/core/drivers/regulator/sub.mk
index 1562241c794192408024657f130871fbf5244095..82d839a436c773fea20a81af66d13084525af902 100644
--- a/core/drivers/regulator/sub.mk
+++ b/core/drivers/regulator/sub.mk
@@ -1,4 +1,6 @@
 srcs-y += regulator.c
 srcs-$(CFG_DT) += regulator_dt.c
 srcs-$(CFG_REGULATOR_FIXED) += regulator_fixed.c
+srcs-$(CFG_REGULATOR_GPIO) += regulator_gpio.c
 srcs-$(CFG_STM32_VREFBUF) += stm32_vrefbuf.c
+srcs-$(CFG_STM32MP13_REGULATOR_IOD) += stm32mp13_regulator_iod.c
diff --git a/core/drivers/remoteproc/stm32_remoteproc.c b/core/drivers/remoteproc/stm32_remoteproc.c
new file mode 100644
index 0000000000000000000000000000000000000000..e4cd6c8b10ec00eb76530f8cfdd4622f8c6ca986
--- /dev/null
+++ b/core/drivers/remoteproc/stm32_remoteproc.c
@@ -0,0 +1,388 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2023, STMicroelectronics
+ */
+
+#include <assert.h>
+#include <config.h>
+#include <drivers/rstctrl.h>
+#include <drivers/stm32_remoteproc.h>
+#include <kernel/cache_helpers.h>
+#include <kernel/dt_driver.h>
+#include <kernel/tee_misc.h>
+#include <libfdt.h>
+#include <mm/core_memprot.h>
+#include <mm/core_mmu.h>
+
+#define TIMEOUT_US_1MS	U(1000)
+
+/**
+ * struct stm32_rproc_mem - Memory regions used by the remote processor
+ *
+ * @addr:	physical base address from the CPU space perspective
+ * @da:		device address corresponding to the physical base address
+ *		from remote processor space perspective
+ * @size:	size of the region
+ */
+struct stm32_rproc_mem {
+	paddr_t addr;
+	paddr_t da;
+	size_t size;
+};
+
+/**
+ * struct stm32_rproc_instance - rproc instance context
+ *
+ * @cdata:	pointer to the device compatible data
+ * @link:	the node in the rproc_list
+ * @n_regions:	number of memory regions
+ * @regions:	memory regions used
+ * @mcu_rst:	remote processor reset control
+ * @hold_boot:	remote processor hold boot control
+ */
+struct stm32_rproc_instance {
+	const struct stm32_rproc_compat_data *cdata;
+	SLIST_ENTRY(stm32_rproc_instance) link;
+	size_t n_regions;
+	struct stm32_rproc_mem *regions;
+	struct rstctrl *mcu_rst;
+	struct rstctrl *hold_boot;
+};
+
+/**
+ * struct stm32_rproc_compat_data - rproc associated data for compatible list
+ *
+ * @rproc_id:	identifies the remote processor
+ */
+struct stm32_rproc_compat_data {
+	uint32_t rproc_id;
+};
+
+static SLIST_HEAD(, stm32_rproc_instance) rproc_list =
+		SLIST_HEAD_INITIALIZER(rproc_list);
+
+void *stm32_rproc_get(uint32_t rproc_id)
+{
+	struct stm32_rproc_instance *rproc = NULL;
+
+	SLIST_FOREACH(rproc, &rproc_list, link)
+		if (rproc->cdata->rproc_id == rproc_id)
+			break;
+
+	return rproc;
+}
+
+TEE_Result stm32_rproc_start(uint32_t rproc_id)
+{
+	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	if (!rproc || !rproc->hold_boot)
+		return TEE_ERROR_GENERIC;
+
+	/*
+	 * The firmware is started by de-asserting the hold boot and
+	 * asserting it back to avoid auto restart on a crash.
+	 * No need to release the MCU reset as it is automatically released by
+	 * the hardware.
+	 */
+	res = rstctrl_deassert_to(rproc->hold_boot, TIMEOUT_US_1MS);
+	if (!res)
+		res = rstctrl_assert_to(rproc->hold_boot, TIMEOUT_US_1MS);
+
+	return res;
+}
+
+static TEE_Result rproc_stop(struct stm32_rproc_instance *rproc)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	if (!rproc->hold_boot || !rproc->mcu_rst)
+		return TEE_ERROR_GENERIC;
+
+	res = rstctrl_assert_to(rproc->hold_boot, TIMEOUT_US_1MS);
+	if (!res)
+		res = rstctrl_assert_to(rproc->mcu_rst, TIMEOUT_US_1MS);
+
+	return res;
+}
+
+TEE_Result stm32_rproc_stop(uint32_t rproc_id)
+{
+	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
+
+	if (!rproc)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	return rproc_stop(rproc);
+}
+
+TEE_Result stm32_rproc_da_to_pa(uint32_t rproc_id, paddr_t da, size_t size,
+				paddr_t *pa)
+{
+	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
+	struct stm32_rproc_mem *mems = NULL;
+	unsigned int i = 0;
+
+	if (!rproc)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	mems = rproc->regions;
+
+	for (i = 0; i < rproc->n_regions; i++) {
+		if (core_is_buffer_inside(da, size, mems[i].da, mems[i].size)) {
+			/*
+			 * A match between the requested DA memory area and the
+			 * registered regions has been found.
+			 * The PA is the reserved-memory PA address plus the
+			 * delta between the requested DA and the
+			 * reserved-memory DA address.
+			 */
+			*pa = mems[i].addr + da - mems[i].da;
+			return TEE_SUCCESS;
+		}
+	}
+
+	return TEE_ERROR_ACCESS_DENIED;
+}
+
+TEE_Result stm32_rproc_map(uint32_t rproc_id, paddr_t pa, size_t size,
+			   void **va)
+{
+	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
+	struct stm32_rproc_mem *mems = NULL;
+	unsigned int i = 0;
+
+	if (!rproc)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	mems = rproc->regions;
+
+	for (i = 0; i < rproc->n_regions; i++) {
+		if (!core_is_buffer_inside(pa, size, mems[i].addr,
+					   mems[i].size))
+			continue;
+		*va = core_mmu_add_mapping(MEM_AREA_RAM_NSEC, pa, size);
+		if (!*va) {
+			EMSG("Can't map region %#"PRIxPA" size %zu", pa, size);
+			return TEE_ERROR_GENERIC;
+		}
+
+		return TEE_SUCCESS;
+	}
+
+	return TEE_ERROR_ACCESS_DENIED;
+}
+
+TEE_Result stm32_rproc_unmap(uint32_t rproc_id, void *va, size_t size)
+{
+	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
+	struct stm32_rproc_mem *mems = NULL;
+	paddr_t pa = virt_to_phys(va);
+	unsigned int i = 0;
+
+	if (!rproc || !pa)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	mems = rproc->regions;
+
+	for (i = 0; i < rproc->n_regions; i++) {
+		if (!core_is_buffer_inside(pa, size, mems[i].addr,
+					   mems[i].size))
+			continue;
+
+		/* Flush the cache before unmapping the memory */
+		dcache_clean_range(va, size);
+
+		if (core_mmu_remove_mapping(MEM_AREA_RAM_NSEC, va, size)) {
+			EMSG("Can't unmap region %#"PRIxPA" size %zu",
+			     pa, size);
+			return TEE_ERROR_GENERIC;
+		}
+
+		return TEE_SUCCESS;
+	}
+
+	return TEE_ERROR_ACCESS_DENIED;
+}
+
+static TEE_Result stm32_rproc_get_dma_range(struct stm32_rproc_mem *region,
+					    const void *fdt, int node)
+{
+	const fdt32_t *list = NULL;
+	int ahb_node = 0;
+	int len = 0;
+	int nranges = 0;
+	int i = 0;
+
+	/*
+	 * The match between local and remote processor memory mapping is
+	 * described in the dma-ranges defined by the bus parent node.
+	 */
+	ahb_node = fdt_parent_offset(fdt, node);
+
+	list = fdt_getprop(fdt, ahb_node, "dma-ranges", &len);
+	if (!list) {
+		if (len != -FDT_ERR_NOTFOUND)
+			return TEE_ERROR_GENERIC;
+		/* Same memory mapping */
+		DMSG("No dma-ranges found in DT");
+		region->da = region->addr;
+		return TEE_SUCCESS;
+	}
+
+	if ((len % (sizeof(uint32_t) * 3)))
+		return TEE_ERROR_GENERIC;
+
+	nranges = len / sizeof(uint32_t);
+
+	for (i = 0; i < nranges; i += 3) {
+		uint32_t da = fdt32_to_cpu(list[i]);
+		uint32_t pa = fdt32_to_cpu(list[i + 1]);
+		uint32_t size = fdt32_to_cpu(list[i + 2]);
+
+		if (core_is_buffer_inside(region->addr, region->size,
+					  pa, size)) {
+			region->da = da + (region->addr - pa);
+			return TEE_SUCCESS;
+		}
+	}
+
+	return TEE_ERROR_BAD_PARAMETERS;
+}
+
+/* Get device tree memory regions reserved for the Cortex-M and the IPC */
+static TEE_Result stm32_rproc_parse_mems(struct stm32_rproc_instance *rproc,
+					 const void *fdt, int node)
+{
+	const fdt32_t *list = NULL;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct stm32_rproc_mem *regions = NULL;
+	int len = 0;
+	int n_regions = 0;
+	int i = 0;
+
+	list = fdt_getprop(fdt, node, "memory-region", &len);
+	if (!list) {
+		EMSG("No memory regions found in DT");
+		return TEE_ERROR_GENERIC;
+	}
+
+	n_regions = len / sizeof(uint32_t);
+
+	regions = calloc(n_regions, sizeof(*regions));
+	if (!regions)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	for (i = 0; i < n_regions; i++) {
+		int pnode = 0;
+
+		pnode = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(list[i]));
+		if (pnode < 0) {
+			res = TEE_ERROR_GENERIC;
+			goto err;
+		}
+
+		regions[i].addr = fdt_reg_base_address(fdt, pnode);
+		regions[i].size = fdt_reg_size(fdt, pnode);
+
+		if (regions[i].addr <= 0 || regions[i].size <= 0) {
+			res = TEE_ERROR_GENERIC;
+			goto err;
+		}
+
+		res = stm32_rproc_get_dma_range(&regions[i], fdt, node);
+		if (res)
+			goto err;
+
+		if (!regions[i].addr || !regions[i].size) {
+			res = TEE_ERROR_BAD_PARAMETERS;
+			goto err;
+		}
+
+		DMSG("register region %#"PRIxPA" size %#zx",
+		     regions[i].addr, regions[i].size);
+	}
+
+	rproc->n_regions = n_regions;
+	rproc->regions = regions;
+
+	return TEE_SUCCESS;
+
+err:
+	free(regions);
+
+	return res;
+}
+
+static void stm32_rproc_cleanup(struct stm32_rproc_instance *rproc)
+{
+	free(rproc->regions);
+	free(rproc);
+}
+
+static TEE_Result stm32_rproc_probe(const void *fdt, int node,
+				    const void *comp_data)
+{
+	struct stm32_rproc_instance *rproc = NULL;
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	rproc = calloc(1, sizeof(*rproc));
+	if (!rproc)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	rproc->cdata = comp_data;
+
+	res = stm32_rproc_parse_mems(rproc, fdt, node);
+	if (res)
+		goto err;
+
+	res = rstctrl_dt_get_by_name(fdt, node, "mcu_rst", &rproc->mcu_rst);
+	if (res)
+		goto err;
+
+	res = rstctrl_dt_get_by_name(fdt, node, "hold_boot", &rproc->hold_boot);
+	if (res)
+		goto err;
+
+	/* Ensure that the MCU is HOLD */
+	if (rproc->mcu_rst) {
+		res = rproc_stop(rproc);
+		if (res)
+			goto err;
+	}
+
+	/*
+	 * The memory management should be enhance with firewall
+	 * mechanism to map the memory in secure area for the firmware
+	 * loading and then to give exclusive access right to the
+	 * coprocessor (except for the shared memory).
+	 */
+	IMSG("Warning: the remoteproc memories are not protected by firewall");
+
+	SLIST_INSERT_HEAD(&rproc_list, rproc, link);
+
+	return TEE_SUCCESS;
+
+err:
+	stm32_rproc_cleanup(rproc);
+	return res;
+}
+
+static const struct stm32_rproc_compat_data stm32_rproc_m4_compat = {
+	.rproc_id = STM32_M4_RPROC_ID,
+};
+
+static const struct dt_device_match stm32_rproc_match_table[] = {
+	{
+		.compatible = "st,stm32mp1-m4-tee",
+		.compat_data = &stm32_rproc_m4_compat,
+	},
+	{ }
+};
+
+DEFINE_DT_DRIVER(stm32_rproc_dt_driver) = {
+	.name = "stm32-rproc",
+	.match_table = stm32_rproc_match_table,
+	.probe = &stm32_rproc_probe,
+};
diff --git a/core/drivers/remoteproc/sub.mk b/core/drivers/remoteproc/sub.mk
new file mode 100644
index 0000000000000000000000000000000000000000..4eb5ca3f29fb4d4ade31e4c828189362eaf20650
--- /dev/null
+++ b/core/drivers/remoteproc/sub.mk
@@ -0,0 +1 @@
+srcs-$(CFG_STM32MP_REMOTEPROC) += stm32_remoteproc.c
diff --git a/core/drivers/smccc_trng.c b/core/drivers/smccc_trng.c
index 4d28ff0af750e3d8f32e5a494f4a4cc1141471f5..4cb5112d3e2bb254264f5b8b6685ef388535d096 100644
--- a/core/drivers/smccc_trng.c
+++ b/core/drivers/smccc_trng.c
@@ -184,7 +184,7 @@ static void __maybe_unused smccc_trng_print_info(void)
 	thread_smccc(&args);
 	assert(args.a0 != ARM_SMCCC_RET_TRNG_NOT_SUPPORTED);
 
-	DMSG("SMCCC TRNG v%u.%u, UUID %08lx-%04lx-%04lx-%04lx-%04lx%08lx\n",
+	DMSG("SMCCC TRNG v%u.%u, UUID %08lx-%04lx-%04lx-%04lx-%04lx%08lx",
 	     major, minor, (unsigned long)args.a0, (unsigned long)args.a1 >> 16,
 	     (unsigned long)args.a1 & GENMASK_32(16, 0),
 	     (unsigned long)args.a2 >> 16,
diff --git a/core/drivers/sp805_wdt.c b/core/drivers/sp805_wdt.c
index 048620cde893e7fc83450e99786bbce2638999a8..cd4624fea97d82e52af1791349b5c684c729caea 100644
--- a/core/drivers/sp805_wdt.c
+++ b/core/drivers/sp805_wdt.c
@@ -102,19 +102,21 @@ TEE_Result sp805_register_itr_handler(struct sp805_wdt_data *pd,
 				      uint32_t itr_num, uint32_t itr_flags,
 				      sp805_itr_handler_func_t itr_handler)
 {
-	struct itr_handler *wdt_itr;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct itr_handler *wdt_itr = NULL;
 
 	assert(!pd->chip.wdt_itr);
 
-	wdt_itr = itr_alloc_add(itr_num, wdt_itr_cb,
-				itr_flags, &pd->chip);
-	if (!wdt_itr)
-		return TEE_ERROR_OUT_OF_MEMORY;
+	res = interrupt_alloc_add_handler(interrupt_get_main_chip(), itr_num,
+					  wdt_itr_cb, itr_flags,
+					  &pd->chip, &wdt_itr);
+	if (res)
+		return res;
 
 	pd->itr_handler = itr_handler;
 	pd->chip.wdt_itr = wdt_itr;
 
-	itr_enable(wdt_itr->it);
+	interrupt_enable(wdt_itr->chip, wdt_itr->it);
 
 	return TEE_SUCCESS;
 }
diff --git a/core/drivers/stm32_gpio.c b/core/drivers/stm32_gpio.c
index 6450c6fc02dd29df3bb2b8edece4869697f3b176..40f1ccb71768cc206fd6b0f2cedf268dcd563595 100644
--- a/core/drivers/stm32_gpio.c
+++ b/core/drivers/stm32_gpio.c
@@ -12,6 +12,7 @@
 #include <drivers/gpio.h>
 #include <drivers/pinctrl.h>
 #include <drivers/stm32_gpio.h>
+#include <dt-bindings/gpio/stm32mp_gpio.h>
 #include <io.h>
 #include <kernel/dt.h>
 #include <kernel/boot.h>
@@ -32,27 +33,27 @@
 
 #define GPIO_PIN_MAX		15
 
-#define GPIO_MODER_OFFSET	0x00
-#define GPIO_OTYPER_OFFSET	0x04
-#define GPIO_OSPEEDR_OFFSET	0x08
-#define GPIO_PUPDR_OFFSET	0x0c
-#define GPIO_IDR_OFFSET		0x10
-#define GPIO_ODR_OFFSET		0x14
-#define GPIO_BSRR_OFFSET	0x18
-#define GPIO_AFRL_OFFSET	0x20
-#define GPIO_AFRH_OFFSET	0x24
-#define GPIO_SECR_OFFSET	0x30
+#define GPIO_MODER_OFFSET	U(0x00)
+#define GPIO_OTYPER_OFFSET	U(0x04)
+#define GPIO_OSPEEDR_OFFSET	U(0x08)
+#define GPIO_PUPDR_OFFSET	U(0x0c)
+#define GPIO_IDR_OFFSET		U(0x10)
+#define GPIO_ODR_OFFSET		U(0x14)
+#define GPIO_BSRR_OFFSET	U(0x18)
+#define GPIO_AFRL_OFFSET	U(0x20)
+#define GPIO_AFRH_OFFSET	U(0x24)
+#define GPIO_SECR_OFFSET	U(0x30)
 
-#define GPIO_ALT_LOWER_LIMIT	0x8
+#define GPIO_ALT_LOWER_LIMIT	U(0x8)
 
 #define GPIO_MODE_MASK		GENMASK_32(1, 0)
 #define GPIO_OSPEED_MASK	GENMASK_32(1, 0)
 #define GPIO_PUPD_PULL_MASK	GENMASK_32(1, 0)
 #define GPIO_ALTERNATE_MASK	GENMASK_32(3, 0)
 
-#define DT_GPIO_BANK_SHIFT	12
+#define DT_GPIO_BANK_SHIFT	U(12)
 #define DT_GPIO_BANK_MASK	GENMASK_32(16, 12)
-#define DT_GPIO_PIN_SHIFT	8
+#define DT_GPIO_PIN_SHIFT	U(8)
 #define DT_GPIO_PIN_MASK	GENMASK_32(11, 8)
 #define DT_GPIO_MODE_MASK	GENMASK_32(7, 0)
 
@@ -131,7 +132,6 @@ struct stm32_pinctrl_array {
  * @bank_id: Id of the bank.
  * @lock: lock protecting the GPIO bank access.
  * @sec_support: True if bank supports pin security protection, otherwise false
- * @seccfgr: Secure configuration register value.
  * @link: Link in bank list
  */
 struct stm32_gpio_bank {
@@ -141,15 +141,19 @@ struct stm32_gpio_bank {
 	unsigned int ngpios;
 	unsigned int bank_id;
 	unsigned int lock;
+	bool sec_support;
 	STAILQ_ENTRY(stm32_gpio_bank) link;
 };
 
-/*
+/**
  * Compatibility information of supported banks
- * @gpioz True if bank is a GPIOZ bank
+ *
+ * @gpioz: True if bank is a GPIOZ bank
+ * @secure_control: Identify GPIO security bank capability.
  */
 struct bank_compat {
 	bool gpioz;
+	bool secure_control;
 };
 
 static unsigned int gpio_lock;
@@ -645,10 +649,15 @@ static TEE_Result dt_stm32_gpio_bank(const void *fdt, int node,
 		panic("missing reg size property");
 
 	DMSG("Bank name %s", fdt_get_name(fdt, node, NULL));
-	bank->base = io_pa_or_va_secure(&pa_va, blen);
 	bank->bank_id = dt_get_bank_id(fdt, node);
 	bank->clock = clk;
 	bank->gpio_chip.ops = &stm32_gpio_ops;
+	bank->sec_support = compat->secure_control;
+	if (bank->sec_support)
+		bank->base = io_pa_or_va_secure(&pa_va, blen);
+	else
+		bank->base = io_pa_or_va_nsec(&pa_va, blen);
+	assert(bank->base);
 
 	/* Parse gpio-ranges with its 4 parameters */
 	cuint = fdt_getprop(fdt, node, "gpio-ranges", &len);
@@ -675,11 +684,11 @@ static void set_bank_gpio_non_secure(struct stm32_gpio_bank *bank)
 {
 	unsigned int pin = 0;
 
-	for (pin = 0; pin <= bank->ngpios; pin++)
+	for (pin = 0; pin < bank->ngpios; pin++)
 		stm32_gpio_set_secure_cfg(bank->bank_id, pin, false);
 }
 
-/* Parse a pinctrl node to register the GPIO banks it describes */
+/* Parse a pinctrl node to register and configure the GPIO banks it describes */
 static TEE_Result dt_stm32_gpio_pinctrl(const void *fdt, int node,
 					const void *compat_data)
 {
@@ -725,8 +734,30 @@ static TEE_Result dt_stm32_gpio_pinctrl(const void *fdt, int node,
 
 			STAILQ_INSERT_TAIL(&bank_list, bank, link);
 
-			if (IS_ENABLED(CFG_STM32MP13))
-				set_bank_gpio_non_secure(bank);
+			DMSG("Registered GPIO bank %c (%d pins) @%#"PRIxVA,
+			     bank->bank_id + 'A', bank->ngpios, bank->base);
+
+			assert(bank->ngpios <= GPIO_PIN_MAX + 1);
+
+			if (bank->sec_support) {
+				uint32_t seccfgr = 0;
+				unsigned int i = 0;
+				int lenp = 0;
+
+				cuint = fdt_getprop(fdt, b_node, "st,protreg",
+						    &lenp);
+				if (!cuint) {
+					set_bank_gpio_non_secure(bank);
+					continue;
+				}
+
+				seccfgr = fdt32_to_cpu(*cuint);
+				for (i = 0; i < bank->ngpios; i++)
+					stm32_gpio_set_secure_cfg(bank->bank_id,
+								  i,
+								  seccfgr &
+								  TZPROT(i));
+			}
 		} else {
 			if (len != -FDT_ERR_NOTFOUND)
 				panic();
@@ -736,33 +767,6 @@ static TEE_Result dt_stm32_gpio_pinctrl(const void *fdt, int node,
 	return TEE_SUCCESS;
 }
 
-
-int stm32_get_gpio_count(void *fdt, int pinctrl_node, unsigned int bank)
-{
-	int node = 0;
-	const fdt32_t *cuint = NULL;
-
-	fdt_for_each_subnode(node, fdt, pinctrl_node) {
-		if (!fdt_getprop(fdt, node, "gpio-controller", NULL))
-			continue;
-
-		cuint = fdt_getprop(fdt, node, "reg", NULL);
-		if (!cuint)
-			continue;
-
-		if (fdt32_to_cpu(*cuint) != stm32_get_gpio_bank_offset(bank))
-			continue;
-
-		cuint = fdt_getprop(fdt, node, "ngpios", NULL);
-		if (!cuint)
-			panic();
-
-		return (int)fdt32_to_cpu(*cuint);
-	}
-
-	return -1;
-}
-
 void stm32_gpio_set_secure_cfg(unsigned int bank_id, unsigned int pin,
 			       bool secure)
 {
@@ -778,6 +782,8 @@ void stm32_gpio_set_secure_cfg(unsigned int bank_id, unsigned int pin,
 	else
 		io_clrbits32(bank->base + GPIO_SECR_OFFSET, BIT(pin));
 
+	FMSG("Set secure GPIO: bank %c pin %u", bank->bank_id + 'A', pin);
+
 	cpu_spin_unlock_xrestore(&gpio_lock, exceptions);
 	clk_disable(bank->clock);
 }
@@ -950,16 +956,22 @@ static TEE_Result stm32_pinctrl_probe(const void *fdt, int node,
 static const struct dt_device_match stm32_pinctrl_match_table[] = {
 	{
 		.compatible = "st,stm32mp135-pinctrl",
-		.compat_data = &(struct bank_compat){ },
-
+		.compat_data = &(struct bank_compat){
+			.secure_control = true,
+		},
 	},
 	{
 		.compatible = "st,stm32mp157-pinctrl",
-		.compat_data = &(struct bank_compat){ },
+		.compat_data = &(struct bank_compat){
+			.secure_control = false,
+		},
 	},
 	{
 		.compatible = "st,stm32mp157-z-pinctrl",
-		.compat_data = &(struct bank_compat){ .gpioz = true, },
+		.compat_data = &(struct bank_compat){
+			.gpioz = true,
+			.secure_control = true,
+		},
 	},
 	{ }
 };
diff --git a/core/drivers/stm32_iwdg.c b/core/drivers/stm32_iwdg.c
index fd2899f9a02cb35ad213b1a153f5cb6834a28739..c7b7ae86bc43433e5f1b92a556cee88e117b2cc9 100644
--- a/core/drivers/stm32_iwdg.c
+++ b/core/drivers/stm32_iwdg.c
@@ -73,7 +73,7 @@
 /*
  * IWDG watch instance data
  * @base - IWDG interface IOMEM base address
- * @clock - Bus clock
+ * @clk_pclk - Bus clock
  * @clk_lsi - IWDG source clock
  * @flags - Property flags for the IWDG instance
  * @timeout - Watchdog elaspure timeout
@@ -82,7 +82,7 @@
  */
 struct stm32_iwdg_device {
 	struct io_pa_va base;
-	struct clk *clock;
+	struct clk *clk_pclk;
 	struct clk *clk_lsi;
 	uint32_t flags;
 	unsigned long timeout;
@@ -90,8 +90,6 @@ struct stm32_iwdg_device {
 	SLIST_ENTRY(stm32_iwdg_device) link;
 };
 
-static unsigned int iwdg_lock = SPINLOCK_UNLOCK;
-
 static SLIST_HEAD(iwdg_dev_list_head, stm32_iwdg_device) iwdg_dev_list =
 	SLIST_HEAD_INITIALIZER(iwdg_dev_list_head);
 
@@ -105,7 +103,12 @@ static bool is_assigned_to_nsec(struct stm32_iwdg_device *iwdg)
 	return iwdg->flags & IWDG_FLAGS_NON_SECURE;
 }
 
-static bool is_enable(struct stm32_iwdg_device *iwdg)
+static void iwdg_wdt_set_enabled(struct stm32_iwdg_device *iwdg)
+{
+	iwdg->flags |= IWDG_FLAGS_ENABLED;
+}
+
+static bool iwdg_wdt_is_enabled(struct stm32_iwdg_device *iwdg)
 {
 	return iwdg->flags & IWDG_FLAGS_ENABLED;
 }
@@ -134,7 +137,7 @@ static TEE_Result iwdg_wait_sync(struct stm32_iwdg_device *iwdg)
 		if (timeout_elapsed(timeout_ref))
 			break;
 
-	if (!(io_read32(iwdg_base + IWDG_SR_OFFSET) & IWDG_SR_UPDATE_MASK))
+	if (io_read32(iwdg_base + IWDG_SR_OFFSET) & IWDG_SR_UPDATE_MASK)
 		return TEE_ERROR_GENERIC;
 
 	return TEE_SUCCESS;
@@ -146,14 +149,12 @@ static TEE_Result configure_timeout(struct stm32_iwdg_device *iwdg)
 	vaddr_t iwdg_base = get_base(iwdg);
 	uint32_t rlr_value = 0;
 
-	assert(is_enable(iwdg));
+	assert(iwdg_wdt_is_enabled(iwdg));
 
 	rlr_value = iwdg_timeout_cnt(iwdg, iwdg->timeout);
 	if (!rlr_value)
 		return TEE_ERROR_GENERIC;
 
-	clk_enable(iwdg->clock);
-
 	io_write32(iwdg_base + IWDG_KR_OFFSET, IWDG_KR_ACCESS_KEY);
 	io_write32(iwdg_base + IWDG_PR_OFFSET, IWDG_PR_DIV_256);
 	io_write32(iwdg_base + IWDG_RLR_OFFSET, rlr_value);
@@ -161,25 +162,19 @@ static TEE_Result configure_timeout(struct stm32_iwdg_device *iwdg)
 
 	res = iwdg_wait_sync(iwdg);
 
-	clk_disable(iwdg->clock);
-
 	return res;
 }
 
 static void iwdg_start(struct stm32_iwdg_device *iwdg)
 {
-	clk_enable(iwdg->clock);
 	io_write32(get_base(iwdg) + IWDG_KR_OFFSET, IWDG_KR_START_KEY);
-	clk_disable(iwdg->clock);
 
-	iwdg->flags |= IWDG_FLAGS_ENABLED;
+	iwdg_wdt_set_enabled(iwdg);
 }
 
 static void iwdg_refresh(struct stm32_iwdg_device *iwdg)
 {
-	clk_enable(iwdg->clock);
 	io_write32(get_base(iwdg) + IWDG_KR_OFFSET, IWDG_KR_RELOAD_KEY);
-	clk_disable(iwdg->clock);
 }
 
 /* Operators for watchdog OP-TEE interface */
@@ -188,6 +183,23 @@ static struct stm32_iwdg_device *wdt_chip_to_iwdg(struct wdt_chip *chip)
 	return container_of(chip, struct stm32_iwdg_device, wdt_chip);
 }
 
+static TEE_Result iwdg_wdt_init(struct wdt_chip *chip,
+				unsigned long *min_timeout,
+				unsigned long *max_timeout)
+{
+	struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip);
+	unsigned long rate = clk_get_rate(iwdg->clk_lsi);
+
+	if (!rate)
+		return TEE_ERROR_GENERIC;
+
+	/* Be safe and expect any counter to be above 2 */
+	*min_timeout = 3 * IWDG_PRESCALER_256 / rate;
+	*max_timeout = (IWDG_CNT_MASK + 1) * IWDG_PRESCALER_256 / rate;
+
+	return TEE_SUCCESS;
+}
+
 static void iwdg_wdt_start(struct wdt_chip *chip)
 {
 	struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip);
@@ -215,7 +227,7 @@ static TEE_Result iwdg_wdt_set_timeout(struct wdt_chip *chip,
 
 	iwdg->timeout = timeout;
 
-	if (is_enable(iwdg)) {
+	if (iwdg_wdt_is_enabled(iwdg)) {
 		TEE_Result res = TEE_ERROR_GENERIC;
 
 		res = configure_timeout(iwdg);
@@ -227,24 +239,13 @@ static TEE_Result iwdg_wdt_set_timeout(struct wdt_chip *chip,
 }
 
 static const struct wdt_ops stm32_iwdg_ops = {
+	.init = iwdg_wdt_init,
 	.start = iwdg_wdt_start,
 	.ping = iwdg_wdt_refresh,
 	.set_timeout = iwdg_wdt_set_timeout,
 };
 DECLARE_KEEP_PAGER(stm32_iwdg_ops);
 
-/* Refresh all registered watchdogs */
-void stm32_iwdg_refresh(void)
-{
-	struct stm32_iwdg_device *iwdg = NULL;
-	uint32_t exceptions = cpu_spin_lock_xsave(&iwdg_lock);
-
-	SLIST_FOREACH(iwdg, &iwdg_dev_list, link)
-		iwdg_refresh(iwdg);
-
-	cpu_spin_unlock_xrestore(&iwdg_lock, exceptions);
-}
-
 /* Driver initialization */
 static TEE_Result stm32_iwdg_parse_fdt(struct stm32_iwdg_device *iwdg,
 				       const void *fdt, int node)
@@ -259,7 +260,7 @@ static TEE_Result stm32_iwdg_parse_fdt(struct stm32_iwdg_device *iwdg,
 	    dt_info.reg_size == DT_INFO_INVALID_REG_SIZE)
 		panic();
 
-	res = clk_dt_get_by_name(fdt, node, "pclk", &iwdg->clock);
+	res = clk_dt_get_by_name(fdt, node, "pclk", &iwdg->clk_pclk);
 	if (res)
 		return res;
 
@@ -336,8 +337,9 @@ static TEE_Result stm32_iwdg_setup(struct stm32_iwdg_device *iwdg,
 	if (otp_data.disable_on_standby)
 		iwdg->flags |= IWDG_FLAGS_DISABLE_ON_STANDBY;
 
-	/* Enable watchdog source clock once for all */
+	/* Enable watchdog source and bus clocks once for all */
 	clk_enable(iwdg->clk_lsi);
+	clk_enable(iwdg->clk_pclk);
 
 	if (otp_data.hw_enabled) {
 		iwdg->flags |= IWDG_FLAGS_ENABLED;
diff --git a/core/drivers/stm32_rng.c b/core/drivers/stm32_rng.c
index ef0f36278714e6faafa3ced59ae649f349225381..af234fa9a589ce5c64b9296499ae582a514e78a7 100644
--- a/core/drivers/stm32_rng.c
+++ b/core/drivers/stm32_rng.c
@@ -279,9 +279,15 @@ static TEE_Result init_rng(void)
 		io_clrsetbits32(rng_base + RNG_CR, RNG_CR_CLKDIV,
 				clock_div << RNG_CR_CLKDIV_SHIFT);
 
-		/* No need to wait for RNG_CR_CONDRST toggle as we enable clk */
 		io_clrsetbits32(rng_base + RNG_CR, RNG_CR_CONDRST,
 				RNG_CR_RNGEN);
+
+		timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US);
+		while (io_read32(rng_base + RNG_CR) & RNG_CR_CONDRST)
+			if (timeout_elapsed(timeout_ref))
+				break;
+		if (io_read32(rng_base + RNG_CR) & RNG_CR_CONDRST)
+			panic();
 	} else {
 		io_setbits32(rng_base + RNG_CR, RNG_CR_RNGEN | cr_ced_mask);
 	}
@@ -312,7 +318,10 @@ static TEE_Result stm32_rng_read(uint8_t *out, size_t size)
 		return TEE_ERROR_NOT_SUPPORTED;
 	}
 
-	clk_enable(stm32_rng->clock);
+	rc = clk_enable(stm32_rng->clock);
+	if (rc)
+		return rc;
+
 	rng_base = get_base();
 
 	/* Arm timeout */
@@ -388,14 +397,24 @@ static TEE_Result stm32_rng_pm_resume(uint32_t pm_cr)
 	io_write32(base + RNG_SR, 0);
 
 	if (stm32_rng->ddata->has_cond_reset) {
+		uint64_t timeout_ref = 0;
+
 		/*
-		 * Correct configuration in bits [29:4] must be set in the same
-		 * access that set RNG_CR_CONDRST bit. Else config setting is
-		 * not taken into account.
+		 * Configuration must be set in the same access that sets
+		 * RNG_CR_CONDRST bit. Otherwise, the configuration setting is
+		 * not taken into account. CONFIGLOCK bit is always cleared in
+		 * this configuration.
 		 */
 		io_write32(base + RNG_CR, pm_cr | RNG_CR_CONDRST);
 
 		io_clrsetbits32(base + RNG_CR, RNG_CR_CONDRST, RNG_CR_RNGEN);
+
+		timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US);
+		while (io_read32(base + RNG_CR) & RNG_CR_CONDRST)
+			if (timeout_elapsed(timeout_ref))
+				break;
+		if (io_read32(base + RNG_CR) & RNG_CR_CONDRST)
+			panic();
 	} else {
 		io_write32(base + RNG_CR, RNG_CR_RNGEN | pm_cr);
 	}
@@ -460,7 +479,7 @@ static TEE_Result stm32_rng_parse_fdt(const void *fdt, int node)
 }
 
 static TEE_Result stm32_rng_probe(const void *fdt, int offs,
-				  const void *compat_data __unused)
+				  const void *compat_data)
 {
 	TEE_Result res = TEE_ERROR_GENERIC;
 
diff --git a/core/drivers/stm32_uart.c b/core/drivers/stm32_uart.c
index 3862b607cc13ccd1cacecffe857b6c93a4da69d2..f7375256fe20d201a92840b63d7ff6f294705e8e 100644
--- a/core/drivers/stm32_uart.c
+++ b/core/drivers/stm32_uart.c
@@ -8,6 +8,7 @@
 #include <drivers/clk.h>
 #include <drivers/clk_dt.h>
 #include <drivers/serial.h>
+#include <drivers/stm32_gpio.h>
 #include <drivers/stm32_uart.h>
 #include <io.h>
 #include <keep.h>
@@ -38,12 +39,12 @@
  * Bit 5 RXNE: Read data register not empty/RXFIFO not empty
  * Bit 6 TC: Transmission complete
  * Bit 7 TXE/TXFNF: Transmit data register empty/TXFIFO not full
- * Bit 27 TXFE: TXFIFO threshold reached
+ * Bit 23 TXFE: TXFIFO empty
  */
 #define USART_ISR_RXNE_RXFNE		BIT(5)
 #define USART_ISR_TC			BIT(6)
 #define USART_ISR_TXE_TXFNF		BIT(7)
-#define USART_ISR_TXFE			BIT(27)
+#define USART_ISR_TXFE			BIT(23)
 
 static vaddr_t loc_chip_to_base(struct serial_chip *chip)
 {
@@ -110,22 +111,31 @@ void stm32_uart_init(struct stm32_uart_pdata *pd, vaddr_t base)
 
 static void register_secure_uart(struct stm32_uart_pdata *pd)
 {
-	size_t __maybe_unused n = 0;
-
+#ifndef CFG_STM32MP25
 	stm32mp_register_secure_periph_iomem(pd->base.pa);
 	stm32mp_register_secure_pinctrl(pd->pinctrl);
 	if (pd->pinctrl_sleep)
 		stm32mp_register_secure_pinctrl(pd->pinctrl_sleep);
+#else
+	stm32_pinctrl_set_secure_cfg(pd->pinctrl, true);
+	if (pd->pinctrl_sleep)
+		stm32_pinctrl_set_secure_cfg(pd->pinctrl, true);
+#endif
 }
 
 static void register_non_secure_uart(struct stm32_uart_pdata *pd)
 {
-	size_t __maybe_unused n = 0;
-
+#ifndef CFG_STM32MP25
 	stm32mp_register_non_secure_periph_iomem(pd->base.pa);
 	stm32mp_register_non_secure_pinctrl(pd->pinctrl);
 	if (pd->pinctrl_sleep)
 		stm32mp_register_non_secure_pinctrl(pd->pinctrl_sleep);
+#else
+	stm32_pinctrl_set_secure_cfg(pd->pinctrl, false);
+	if (pd->pinctrl_sleep)
+		stm32_pinctrl_set_secure_cfg(pd->pinctrl, false);
+#endif
+
 }
 
 struct stm32_uart_pdata *stm32_uart_init_from_dt_node(void *fdt, int node)
diff --git a/core/drivers/sub.mk b/core/drivers/sub.mk
index 9e7625ae50d8661f9feeada43b8feda75bc04465..0bd5bc242290dee0ad3193b622a38e7def399a3c 100644
--- a/core/drivers/sub.mk
+++ b/core/drivers/sub.mk
@@ -77,14 +77,17 @@ srcs-$(CFG_VERSAL_PUF) += versal_puf.c
 srcs-$(CFG_VERSAL_HUK) += versal_huk.c
 srcs-$(CFG_CBMEM_CONSOLE) += cbmem_console.c
 srcs-$(CFG_RISCV_PLIC) += plic.c
+srcs-$(CFG_HISILICON_CRYPTO_DRIVER) += hisi_trng.c
 subdirs-y += crypto
 subdirs-$(CFG_BNXT_FW) += bnxt
 subdirs-$(CFG_DRIVERS_CLK) += clk
 subdirs-$(CFG_DRIVERS_GPIO) += gpio
 subdirs-$(CFG_DRIVERS_I2C) += i2c
+subdirs-$(CFG_DRIVERS_NVMEM) += nvmem
 subdirs-$(CFG_DRIVERS_PINCTRL) += pinctrl
 subdirs-$(CFG_DRIVERS_REGULATOR) += regulator
 subdirs-$(CFG_DRIVERS_RSTCTRL) += rstctrl
+subdirs-$(CFG_DRIVERS_REMOTEPROC) += remoteproc
 subdirs-$(CFG_SCMI_MSG_DRIVERS) += scmi-msg
 subdirs-y += imx
 subdirs-y += pm
diff --git a/core/drivers/xiphera_trng.c b/core/drivers/xiphera_trng.c
index 9786c19a474f18c7fd75ceb60bf22d500293d9e9..970acf527df4ed17d25c08b47a7d3e6491ab8885 100644
--- a/core/drivers/xiphera_trng.c
+++ b/core/drivers/xiphera_trng.c
@@ -134,7 +134,7 @@ static TEE_Result xiphera_trng_probe(const void *fdt, int node,
 		udelay(200);
 		status = io_read32(xiphera_trng_base + STATUS_REG);
 		if (status != TRNG_ACK_RESET) {
-			EMSG("Failed to reset TRNG\n");
+			EMSG("Failed to reset TRNG");
 			return TEE_ERROR_GENERIC;
 		}
 	}
@@ -159,17 +159,17 @@ static TEE_Result xiphera_trng_probe(const void *fdt, int node,
 		 * in debugging TRNG implementation in FPGA
 		 */
 		if (status == TRNG_FAILED_STARTUP) {
-			EMSG("Startup tests have failed\n");
+			EMSG("Startup tests have failed");
 			return TEE_ERROR_GENERIC;
 		}
 
-		EMSG("Startup tests yielded no response -> TRNG stuck\n");
+		EMSG("Startup tests yielded no response -> TRNG stuck");
 		return TEE_ERROR_GENERIC;
 	}
 
 	io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ACK_ZEROIZE);
 
-	DMSG("TRNG initialized\n");
+	DMSG("TRNG initialized");
 
 	return TEE_SUCCESS;
 }
diff --git a/core/include/bench.h b/core/include/bench.h
index cdff5773418ec12a3a126e7ef4a975c02ca89527..d9f3cdd3f2285f74baa7a512bbe471325baee6cb 100644
--- a/core/include/bench.h
+++ b/core/include/bench.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2017, Linaro Limited
  */
 
-#ifndef BENCH_H
-#define BENCH_H
+#ifndef __BENCH_H
+#define __BENCH_H
 
 #include <inttypes.h>
 #include <mm/core_memprot.h>
@@ -57,4 +57,4 @@ void bm_timestamp(void);
 static inline void bm_timestamp(void) {}
 #endif /* CFG_TEE_BENCHMARK */
 
-#endif /* BENCH_H */
+#endif /* __BENCH_H */
diff --git a/core/include/console.h b/core/include/console.h
index f2e57fb7d0a02f8d4b628d00eb0a2b08e56132b4..f9cfaca5133fcd48bfee530be33b1c2fa833e925 100644
--- a/core/include/console.h
+++ b/core/include/console.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2014, Linaro Limited
  */
 
-#ifndef CONSOLE_H
-#define CONSOLE_H
+#ifndef __CONSOLE_H
+#define __CONSOLE_H
 
 #include <compiler.h>
 #include <tee_api_types.h>
@@ -51,5 +51,5 @@ static inline void configure_console_from_dt(void)
 {}
 #endif /* !CFG_DT */
 
-#endif /* CONSOLE_H */
+#endif /* __CONSOLE_H */
 
diff --git a/core/include/crypto/crypto_se.h b/core/include/crypto/crypto_se.h
index eb7452faa2ef5ead7589a31825a2d2b2c00f749b..d8471e51a5be518bf5e249764e179f8a137a7a6b 100644
--- a/core/include/crypto/crypto_se.h
+++ b/core/include/crypto/crypto_se.h
@@ -10,8 +10,8 @@
   * These requests shall be handled in the secure element normally placed on
   * a serial communication bus (SPI, I2C).
   */
-#ifndef __CRYPTO_SE_H
-#define __CRYPTO_SE_H
+#ifndef __CRYPTO_CRYPTO_SE_H
+#define __CRYPTO_CRYPTO_SE_H
 
 #include <tee_api_types.h>
 
diff --git a/core/include/crypto/sm2-kdf.h b/core/include/crypto/sm2-kdf.h
index 5a012c0d959628fa786f44bf2fa10197afe044e5..4ac246bbc882fb63eac4620e6c56f13d920cda03 100644
--- a/core/include/crypto/sm2-kdf.h
+++ b/core/include/crypto/sm2-kdf.h
@@ -3,11 +3,11 @@
  * Copyright (c) 2020-2021, Huawei Technologies Co., Ltd
  */
 
-#ifndef CRYPTO_SM2_KDF_H
-#define CRYPTO_SM2_KDF_H
+#ifndef __CRYPTO_SM2_KDF_H
+#define __CRYPTO_SM2_KDF_H
 
 #include <stdint.h>
 #include <tee_api_types.h>
 
 TEE_Result sm2_kdf(const uint8_t *Z, size_t Z_len, uint8_t *t, size_t tlen);
-#endif /* CRYPTO_SM2_KDF_H */
+#endif /* __CRYPTO_SM2_KDF_H */
diff --git a/core/include/drivers/amlogic_uart.h b/core/include/drivers/amlogic_uart.h
index 97b55f226b0cda0de36fde5b19474b166d81fb3b..e575afeabf036ffd45e7e7ad3e4376bc7a93e844 100644
--- a/core/include/drivers/amlogic_uart.h
+++ b/core/include/drivers/amlogic_uart.h
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: BSD-2-Clause */
 
-#ifndef AMLOGIC_UART_H
-#define AMLOGIC_UART_H
+#ifndef __DRIVERS_AMLOGIC_UART_H
+#define __DRIVERS_AMLOGIC_UART_H
 
 #include <types_ext.h>
 #include <drivers/serial.h>
@@ -13,4 +13,4 @@ struct amlogic_uart_data {
 
 void amlogic_uart_init(struct amlogic_uart_data *pd, paddr_t base);
 
-#endif /* AMLOGIC_UART_H */
+#endif /* __DRIVERS_AMLOGIC_UART_H */
diff --git a/core/include/drivers/atmel_uart.h b/core/include/drivers/atmel_uart.h
index aa5563f709d173e69211ebe7757e059680873164..2639fce72499e43305bfe19f879ba44d254122d3 100644
--- a/core/include/drivers/atmel_uart.h
+++ b/core/include/drivers/atmel_uart.h
@@ -25,8 +25,8 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
-#ifndef ATMEL_UART_H
-#define ATMEL_UART_H
+#ifndef __DRIVERS_ATMEL_UART_H
+#define __DRIVERS_ATMEL_UART_H
 
 #include <types_ext.h>
 #include <drivers/serial.h>
@@ -38,4 +38,4 @@ struct atmel_uart_data {
 
 void atmel_uart_init(struct atmel_uart_data *pd, paddr_t base);
 
-#endif /* ATMEL_UART_H */
+#endif /* __DRIVERS_ATMEL_UART_H */
diff --git a/core/include/drivers/bcm/bnxt.h b/core/include/drivers/bcm/bnxt.h
index 7136c7efa99b139b8a4c0e305665bf9a5b4e177a..51aae18d9ce93bfc0a56de043f2d25cbb6a32548 100644
--- a/core/include/drivers/bcm/bnxt.h
+++ b/core/include/drivers/bcm/bnxt.h
@@ -3,8 +3,8 @@
  * Copyright 2019 Broadcom.
  */
 
-#ifndef BNXT_H
-#define BNXT_H
+#ifndef __DRIVERS_BCM_BNXT_H
+#define __DRIVERS_BCM_BNXT_H
 
 #include <compiler.h>
 #include <io.h>
diff --git a/core/include/drivers/bcm_gpio.h b/core/include/drivers/bcm_gpio.h
index 6606656bf76a1ed9c1dab8f71c64fad729102c13..7d5e408af0a566444060f8f4c5f38bb343465cc6 100644
--- a/core/include/drivers/bcm_gpio.h
+++ b/core/include/drivers/bcm_gpio.h
@@ -3,8 +3,8 @@
  * Copyright 2019 Broadcom.
  */
 
-#ifndef BCM_GPIO_H
-#define BCM_GPIO_H
+#ifndef __DRIVERS_BCM_GPIO_H
+#define __DRIVERS_BCM_GPIO_H
 
 #include <drivers/gpio.h>
 #include <stdlib.h>
@@ -30,4 +30,4 @@ struct bcm_gpio_chip {
 struct bcm_gpio_chip *bcm_gpio_pin_to_chip(unsigned int pin);
 /* Set gpiopin as secure */
 void iproc_gpio_set_secure(int gpiopin);
-#endif	/* BCM_GPIO_H */
+#endif	/* __DRIVERS_BCM_GPIO_H */
diff --git a/core/include/drivers/bcm_hwrng.h b/core/include/drivers/bcm_hwrng.h
index abf213df6d396d844211274ef0941f39900c6649..b4d84f967d4d672b04f5a7d7a397dbc67a8eff29 100644
--- a/core/include/drivers/bcm_hwrng.h
+++ b/core/include/drivers/bcm_hwrng.h
@@ -3,11 +3,11 @@
  * Copyright 2019 Broadcom.
  */
 
-#ifndef BCM_HWRNG_H
-#define BCM_HWRNG_H
+#ifndef __DRIVERS_BCM_HWRNG_H
+#define __DRIVERS_BCM_HWRNG_H
 
 #include <stdlib.h>
 
 uint32_t bcm_hwrng_read_rng(uint32_t *p_out, uint32_t words_to_read);
 
-#endif /* BCM_HWRNG_H */
+#endif /* __DRIVERS_BCM_HWRNG_H */
diff --git a/core/include/drivers/bcm_sotp.h b/core/include/drivers/bcm_sotp.h
index 2476004251484e53ca1718dccb26026a6dd747a2..aa13270434a1171e22464d9cde4fa291eef6339d 100644
--- a/core/include/drivers/bcm_sotp.h
+++ b/core/include/drivers/bcm_sotp.h
@@ -3,8 +3,8 @@
  * Copyright 2019 Broadcom.
  */
 
-#ifndef BCM_SOTP_H
-#define BCM_SOTP_H
+#ifndef __DRIVERS_BCM_SOTP_H
+#define __DRIVERS_BCM_SOTP_H
 
 #include <stdint.h>
 #include <tee_api.h>
diff --git a/core/include/drivers/caam_extension.h b/core/include/drivers/caam_extension.h
index d0232176ee15885631694e1ba8427fed8ec5812f..41ccec05605ba042bcb9391b9a8480b44d4e4fb7 100644
--- a/core/include/drivers/caam_extension.h
+++ b/core/include/drivers/caam_extension.h
@@ -52,4 +52,4 @@ TEE_Result caam_mp_sign(uint8_t *data, size_t *data_size, uint8_t *sig,
 TEE_Result caam_dek_generate(const uint8_t *payload, size_t payload_size,
 			     uint8_t *dek, size_t dek_size);
 #endif /* CFG_NXP_CAAM_DEK_DRV */
-#endif /* __CAAM_EXTENSION_H__ */
+#endif /* __DRIVERS_CAAM_EXTENSION_H__ */
diff --git a/core/include/drivers/cbmem_console.h b/core/include/drivers/cbmem_console.h
index c8234d3b6f1080bd394986d5a164a5323c18b20c..a8b695a932d8d56c28bd4610afe0d11df59a2b08 100644
--- a/core/include/drivers/cbmem_console.h
+++ b/core/include/drivers/cbmem_console.h
@@ -2,12 +2,12 @@
 /*
  * Copyright (c) 2023, Google Limited
  */
-#ifndef DRIVERS_CBMEM_CONSOLE_H
-#define DRIVERS_CBMEM_CONSOLE_H
+#ifndef __DRIVERS_CBMEM_CONSOLE_H
+#define __DRIVERS_CBMEM_CONSOLE_H
 
 #include <stdbool.h>
 
 bool cbmem_console_init_from_dt(void *fdt);
 
-#endif /* DRIVERS_CBMEM_CONSOLE_H */
+#endif /* __DRIVERS_CBMEM_CONSOLE_H */
 
diff --git a/core/include/drivers/cdns_uart.h b/core/include/drivers/cdns_uart.h
index 19516ff8681b8681e2656137856b1876638147e8..b5ee11234e60ec97bca28d43bd9ae809e1f5f7ed 100644
--- a/core/include/drivers/cdns_uart.h
+++ b/core/include/drivers/cdns_uart.h
@@ -26,8 +26,8 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
-#ifndef CDNS_UART_H
-#define CDNS_UART_H
+#ifndef __DRIVERS_CDNS_UART_H
+#define __DRIVERS_CDNS_UART_H
 
 #include <types_ext.h>
 #include <drivers/serial.h>
@@ -40,4 +40,4 @@ struct cdns_uart_data {
 void cdns_uart_init(struct cdns_uart_data *pd, paddr_t base, uint32_t uart_clk,
 		uint32_t baud_rate);
 
-#endif /* CDNS_UART_H */
+#endif /* __DRIVERS_CDNS_UART_H */
diff --git a/core/include/drivers/clk.h b/core/include/drivers/clk.h
index 13cc9faee679b1dbf739626c1d285efc1292d67a..20b7d54052a0d29a249fe99e10544266dc2b5b17 100644
--- a/core/include/drivers/clk.h
+++ b/core/include/drivers/clk.h
@@ -8,6 +8,7 @@
 
 #include <kernel/refcount.h>
 #include <stdint.h>
+#include <sys/queue.h>
 #include <tee_api_types.h>
 
 /* Flags for clock */
@@ -26,6 +27,7 @@
  * @enabled_count: Enable/disable reference counter
  * @num_parents: Number of parents
  * @parents: Array of possible parents of the clock
+ * @link: Link the clock list
  */
 struct clk {
 	const char *name;
@@ -35,6 +37,9 @@ struct clk {
 	unsigned long rate;
 	unsigned int flags;
 	struct refcount enabled_count;
+#ifdef CFG_DRIVERS_CLK_PRINT_TREE
+	SLIST_ENTRY(clk) link;
+#endif
 	size_t num_parents;
 	struct clk *parents[];
 };
@@ -194,4 +199,12 @@ TEE_Result clk_set_parent(struct clk *clk, struct clk *parent);
 TEE_Result clk_get_rates_array(struct clk *clk, size_t start_index,
 			       unsigned long *rates, size_t *nb_elts);
 
+/* Print current clock tree summary to output console with debug trace level */
+#ifdef CFG_DRIVERS_CLK
+void clk_print_tree(void);
+#else
+static inline void clk_print_tree(void)
+{
+}
+#endif /* CFG_DRIVERS_CLK */
 #endif /* __DRIVERS_CLK_H */
diff --git a/core/include/drivers/clk_dt.h b/core/include/drivers/clk_dt.h
index eb164acb8934b627df5f61d9ceef371273ff445d..5ea10ade83395dc88a474f9f9ebcb976c3aba512 100644
--- a/core/include/drivers/clk_dt.h
+++ b/core/include/drivers/clk_dt.h
@@ -6,6 +6,7 @@
 #ifndef __DRIVERS_CLK_DT_H
 #define __DRIVERS_CLK_DT_H
 
+#include <drivers/clk.h>
 #include <kernel/dt_driver.h>
 #include <scattered_array.h>
 #include <stdint.h>
diff --git a/core/include/drivers/gic.h b/core/include/drivers/gic.h
index cb580ec1cfd1c6fe5c6401704a7f2a700642b12c..498e3c8a78a87f8b9fd11224b4d93e5c1a762330 100644
--- a/core/include/drivers/gic.h
+++ b/core/include/drivers/gic.h
@@ -25,15 +25,34 @@
 #define GIC_SPI_TO_ITNUM(x)	((x) + GIC_SPI_BASE)
 
 /*
- * The two gic_init_* functions initializes the struct gic_data which is
- * then used by the other functions.
+ * Default lowest ID for secure SGIs, note that this does not account for
+ * interrupts donated to non-secure world with gic_init_donate_sgi_to_ns().
  */
+#define GIC_SGI_SEC_BASE	8
+/* Max ID for secure SGIs */
+#define GIC_SGI_SEC_MAX		15
 
-/* Initialize GIC */
-void gic_init(paddr_t gicc_base_pa, paddr_t gicd_base_pa);
+/*
+ * The two gic_init() and gic_init_v3() functions initializes the struct
+ * gic_data which is then used by the other functions. These two functions
+ * also initializes the GIC and are only supposed to be called from the
+ * primary boot CPU.
+ */
+void gic_init_v3(paddr_t gicc_base_pa, paddr_t gicd_base_pa,
+		 paddr_t gicr_base_pa);
+static inline void gic_init(paddr_t gicc_base_pa, paddr_t gicd_base_pa)
+{
+	gic_init_v3(gicc_base_pa, gicd_base_pa, 0);
+}
+
+/* Donates one of the secure SGIs to normal world */
+void gic_init_donate_sgi_to_ns(size_t it);
 
-/* Only initialize CPU GIC interface, mainly use for secondary CPUs */
-void gic_cpu_init(void);
+/*
+ * Does per-CPU specific GIC initialization, should be called by all
+ * secondary CPUs when booting.
+ */
+void gic_init_per_cpu(void);
 
 /* Print GIC state to console */
 void gic_dump_state(void);
diff --git a/core/include/drivers/gpio.h b/core/include/drivers/gpio.h
index 7ce00e1f93f2d54462e2693e1c2288a525669acd..b6406d45e9ce317efb619446b201aad461d295a4 100644
--- a/core/include/drivers/gpio.h
+++ b/core/include/drivers/gpio.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2016, Linaro Limited
  */
 
-#ifndef DRIVERS_GPIO_H
-#define DRIVERS_GPIO_H
+#ifndef __DRIVERS_GPIO_H
+#define __DRIVERS_GPIO_H
 
 #include <assert.h>
 #include <dt-bindings/gpio/gpio.h>
@@ -219,4 +219,4 @@ static inline TEE_Result gpio_register_provider(const void *fdt, int nodeoffset,
 					   data, DT_DRIVER_GPIO);
 }
 
-#endif	/* DRIVERS_GPIO_H */
+#endif	/* __DRIVERS_GPIO_H */
diff --git a/core/include/drivers/hi16xx_uart.h b/core/include/drivers/hi16xx_uart.h
index 83413fc0e20e0a6baba2f4d4eb7c6c2caf12d700..9fb11a4f5d35b461373491f19a745298e605a3f2 100644
--- a/core/include/drivers/hi16xx_uart.h
+++ b/core/include/drivers/hi16xx_uart.h
@@ -7,8 +7,8 @@
  * UART driver for Hisilicon Hi16xx and Phosphor V660 (hip05) SoCs
  */
 
-#ifndef HI16XX_UART_H
-#define HI16XX_UART_H
+#ifndef __DRIVERS_HI16XX_UART_H
+#define __DRIVERS_HI16XX_UART_H
 
 #include <types_ext.h>
 #include <drivers/serial.h>
@@ -23,4 +23,4 @@ struct hi16xx_uart_data {
 void hi16xx_uart_init(struct hi16xx_uart_data *pd, paddr_t base,
 		      uint32_t uart_clk, uint32_t baud_rate);
 
-#endif /* HI16XX_UART_H */
+#endif /* __DRIVERS_HI16XX_UART_H */
diff --git a/core/include/drivers/imx/dcp.h b/core/include/drivers/imx/dcp.h
index a01ae3011e4bd8c910859e8596909d48152df42a..28ff0803101bfe6fb72c7e7d59593079e680543d 100644
--- a/core/include/drivers/imx/dcp.h
+++ b/core/include/drivers/imx/dcp.h
@@ -2,8 +2,8 @@
 /*
  * Copyright 2020 NXP
  */
-#ifndef __IMX_DCP_H__
-#define __IMX_DCP_H__
+#ifndef __DRIVERS_IMX_DCP_H
+#define __DRIVERS_IMX_DCP_H
 
 #include <compiler.h>
 #include <tee_api_types.h>
@@ -192,4 +192,4 @@ static inline TEE_Result dcp_vbase(vaddr_t *base __unused)
 }
 #endif /* CFG_DT */
 
-#endif /* __IMX_DCP_H__ */
+#endif /* __DRIVERS_IMX_DCP_H */
diff --git a/core/include/drivers/imx_ocotp.h b/core/include/drivers/imx_ocotp.h
index 72d4b79609faac6e397a7bee71c803091f31a6f1..d10013515d025f4844d914dce35359f285de12a3 100644
--- a/core/include/drivers/imx_ocotp.h
+++ b/core/include/drivers/imx_ocotp.h
@@ -3,8 +3,8 @@
  * Copyright 2021 NXP
  */
 
-#ifndef _IMX_OCOTP_H
-#define _IMX_OCOTP_H
+#ifndef __DRIVERS_IMX_OCOTP_H
+#define __DRIVERS_IMX_OCOTP_H
 
 #include <tee_api_types.h>
 
@@ -19,4 +19,4 @@
  * @[out]val Shadow register value
  */
 TEE_Result imx_ocotp_read(unsigned int bank, unsigned int word, uint32_t *val);
-#endif /* _IMX_OCOTP_H */
+#endif /* __DRIVERS_IMX_OCOTP_H */
diff --git a/core/include/drivers/imx_uart.h b/core/include/drivers/imx_uart.h
index b9df517e5e8ba2da7fafe9f61ca4c56d7c9175d7..a62bd17a26f85d68286fbfafb41a17c69c95cc18 100644
--- a/core/include/drivers/imx_uart.h
+++ b/core/include/drivers/imx_uart.h
@@ -26,8 +26,8 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
-#ifndef IMX_UART_H
-#define IMX_UART_H
+#ifndef __DRIVERS_IMX_UART_H
+#define __DRIVERS_IMX_UART_H
 
 #include <types_ext.h>
 #include <drivers/serial.h>
@@ -39,4 +39,4 @@ struct imx_uart_data {
 
 void imx_uart_init(struct imx_uart_data *pd, paddr_t base);
 
-#endif /* IMX_UART_H */
+#endif /* __DRIVERS_IMX_UART_H */
diff --git a/core/include/drivers/imx_wdog.h b/core/include/drivers/imx_wdog.h
index 2c7607335c068821947a14b0f0a0a203d67e4741..7df879aab4a76953ce95da78d5308d36d8b48eba 100644
--- a/core/include/drivers/imx_wdog.h
+++ b/core/include/drivers/imx_wdog.h
@@ -25,8 +25,8 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef __IMX_WDOG_H
-#define __IMX_WDOG_H
+#ifndef __DRIVERS_IMX_WDOG_H
+#define __DRIVERS_IMX_WDOG_H
 
 #include <compiler.h>
 
diff --git a/core/include/drivers/lpc_uart.h b/core/include/drivers/lpc_uart.h
index 3e235b4e2c54909939f2dd5a45ec55b27ceaee97..e219a90b2d5c4e8cc706097100fcf108f6e181e3 100644
--- a/core/include/drivers/lpc_uart.h
+++ b/core/include/drivers/lpc_uart.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2022, HiSilicon Limited
  */
 
-#ifndef LPC_UART_H
-#define LPC_UART_H
+#ifndef __DRIVERS_LPC_UART_H
+#define __DRIVERS_LPC_UART_H
 
 #include <types_ext.h>
 #include <drivers/serial.h>
@@ -50,4 +50,4 @@ struct lpc_uart_data {
 void lpc_uart_init(struct lpc_uart_data *pd, paddr_t base,
 		   uint32_t uart_clk, uint32_t baud_rate);
 
-#endif /* LPC_UART_H */
+#endif /* __DRIVERS_LPC_UART_H */
diff --git a/core/include/drivers/mvebu_uart.h b/core/include/drivers/mvebu_uart.h
index fed9ac8b6192cfba69a194a460820d29f05c8571..a3934287508e797bd80f683ef9edbfc2d5b761bb 100644
--- a/core/include/drivers/mvebu_uart.h
+++ b/core/include/drivers/mvebu_uart.h
@@ -25,8 +25,8 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
-#ifndef MVEBU_UART_H
-#define MVEBU_UART_H
+#ifndef __DRIVERS_MVEBU_UART_H
+#define __DRIVERS_MVEBU_UART_H
 
 #include <types_ext.h>
 #include <drivers/serial.h>
@@ -39,4 +39,4 @@ struct mvebu_uart_data {
 void mvebu_uart_init(struct mvebu_uart_data *pd, paddr_t pbase,
 		uint32_t uart_clk, uint32_t baud_rate);
 
-#endif /* MVEBU_UART_H */
+#endif /* __DRIVERS_MVEBU_UART_H */
diff --git a/core/include/drivers/ns16550.h b/core/include/drivers/ns16550.h
index de0be9eb3704d077535af2e839f91e21c76c14a3..60d3671291f8932260e0a569aab58a821767ff7e 100644
--- a/core/include/drivers/ns16550.h
+++ b/core/include/drivers/ns16550.h
@@ -26,8 +26,8 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
-#ifndef NS16550_H
-#define NS16550_H
+#ifndef __DRIVERS_NS16550_H
+#define __DRIVERS_NS16550_H
 
 #include <drivers/serial.h>
 #include <io.h>
@@ -64,4 +64,4 @@ static inline void serial_out(vaddr_t addr, uint8_t io_width, int ch)
 void ns16550_init(struct ns16550_data *pd, paddr_t base, uint8_t io_width,
 		  uint8_t reg_shift);
 
-#endif /* NS16550_H */
+#endif /* __DRIVERS_NS16550_H */
diff --git a/core/include/drivers/nvmem.h b/core/include/drivers/nvmem.h
new file mode 100644
index 0000000000000000000000000000000000000000..5db573d1f0c492e3575a80a3d75cb302360bb244
--- /dev/null
+++ b/core/include/drivers/nvmem.h
@@ -0,0 +1,193 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2023, Microchip
+ */
+
+#ifndef __DRIVERS_NVMEM_H
+#define __DRIVERS_NVMEM_H
+
+#include <kernel/dt_driver.h>
+#include <tee_api_defines.h>
+#include <tee_api_types.h>
+#include <types_ext.h>
+
+struct nvmem_cell;
+
+/*
+ * struct nvmem_ops - NVMEM device driver operations
+ * @read_cell: Allocate @data in the heap and load @len bytes to from an
+ * NVMEM cell
+ * @put_cell: Release resources allocated from nvmem_dt_get_func callback
+ * function
+ */
+struct nvmem_ops {
+	/*
+	 * Read data from an NVMEM cell.
+	 * @cell: Cell to read data from
+	 * @data: Output buffer of size greater or equal to @cell->size
+	 */
+	TEE_Result (*read_cell)(struct nvmem_cell *cell, uint8_t *data);
+	void (*put_cell)(struct nvmem_cell *cell);
+};
+
+/*
+ * struct nvmem_cell - Description of an NVMEM cell
+ * @offset: Cell byte offset in the NVMEM device
+ * @len: Cell byte size
+ * @ops: NVMEM device driver operation handlers
+ * @drv_data: NVMEM device driver private data
+ */
+struct nvmem_cell {
+	paddr_t offset;
+	size_t len;
+	const struct nvmem_ops *ops;
+	void *drv_data;
+};
+
+/*
+ * nvmem_dt_get_func - Typedef of handlers to get an NVMEM cell from a npode
+ * @args: Reference to phandle arguments
+ * @data: Pointer to data given at nvmem_dt_get_func() call
+ * @cell: Output reference to cell instance upon success
+ *
+ * Return TEE_SUCCESS in case of success.
+ * Return TEE_ERROR_DEFER_DRIVER_INIT if NVMEM driver is not initialized
+ * Return another TEE_Result compliant code otherwise.
+ */
+typedef TEE_Result (*nvmem_dt_get_func)(struct dt_pargs *args,
+					void *data, struct nvmem_cell **cell);
+
+#ifdef CFG_DRIVERS_NVMEM
+/**
+ * nvmem_register_provider() - Register a NVMEM controller
+ *
+ * @fdt: Device tree to work on
+ * @nodeoffset: Node offset of NVMEM cell consumer
+ * @get_dt_nvmem: Callback to match the devicetree NVMEM reference with
+ * nvmem_cell
+ * @data: Data which will be passed to the get_dt_nvmem callback
+ * Return a TEE_Result compliant value
+ */
+static inline TEE_Result nvmem_register_provider(const void *fdt,
+						 int nodeoffset,
+						 nvmem_dt_get_func get_dt_nvmem,
+						 void *data)
+{
+	return dt_driver_register_provider(fdt, nodeoffset,
+					   (get_of_device_func)get_dt_nvmem,
+					   data, DT_DRIVER_NVMEM);
+}
+
+/**
+ * nvmem_get_cell_by_name() - Obtain a NVMEM cell from its name in the DT node
+ *
+ * @fdt: Device tree to work on
+ * @nodeoffset: Node offset of NVMEM cell consumer
+ * @name: name of the NVMEM cell defined by property nvmem-cell-names to obtain
+ * from the device tree
+ * @cell: Pointer filled with the retrieved cell, must be freed after use
+   using nvmem_put_cell()
+ * Return a TEE_Result compliant value
+ */
+TEE_Result nvmem_get_cell_by_name(const void *fdt, int nodeoffset,
+				  const char *name, struct nvmem_cell **cell);
+
+/**
+ * nvmem_get_cell_by_index() - Obtain a NVMEM cell from property nvmem-cells
+ *
+ * @fdt: Device tree to work on
+ * @nodeoffset: Node offset of NVMEM cell consumer
+ * @index: Index of the NVMEM cell to obtain from device-tree
+ * @out_cell: Pointer filled with the retrieved cell, must be freed after use
+ * using nvmem_put_cell()
+ * Return a TEE_Result compliant value
+ */
+TEE_Result nvmem_get_cell_by_index(const void *fdt,
+				   int nodeoffset,
+				   unsigned int index,
+				   struct nvmem_cell **out_cell);
+
+/**
+ * nvmem_cell_parse_dt() - Parse device-tree information to fill a NVMEM cell
+ *
+ * @fdt: Device tree to work on
+ * @nodeoffset: Node offset of the NVMEM cell controller
+ * @cell: Pointer to cell that will be filled
+ */
+TEE_Result nvmem_cell_parse_dt(const void *fdt, int nodeoffset,
+			       struct nvmem_cell *cell);
+
+/**
+ * nvmem_put_cell() - Free resource allocated from nvmem_get_cell_by_*()
+ *
+ * @cell: Cell to be freed
+ */
+static inline void nvmem_put_cell(struct nvmem_cell *cell)
+{
+	if (cell->ops->put_cell)
+		cell->ops->put_cell(cell);
+}
+
+/*
+ * nvmem_cell_read() - Read data from a NVMEM cell
+ * @cell: Cell to read from NVMEM
+ * @data: Output data read from the cell upon success, byte size >= @cell->size
+ */
+static inline TEE_Result nvmem_cell_read(struct nvmem_cell *cell,
+					 uint8_t *data)
+{
+	if (!cell->ops->read_cell)
+		return TEE_ERROR_NOT_SUPPORTED;
+
+	return cell->ops->read_cell(cell, data);
+}
+
+/*
+ * nvmem_cell_malloc_and_read() - Allocate and read data from a NVMEM cell
+ * @cell: Cell to read from NVMEM
+ * @data: Output allocated buffer where NVMEM cell data are stored upon success
+ *
+ * Upon success, the output buffer is allocated with malloc(). Caller is
+ * responsible for freeing the buffer with free() if needed.
+ */
+TEE_Result nvmem_cell_malloc_and_read(struct nvmem_cell *cell,
+				      uint8_t **out_data);
+
+#else /* CFG_DRIVERS_NVMEM */
+static inline TEE_Result nvmem_register_provider(const void *fdt __unused,
+						 int nodeoffset __unused,
+						 nvmem_dt_get_func fn __unused,
+						 void *data __unused)
+{
+	return TEE_ERROR_NOT_SUPPORTED;
+}
+
+static inline TEE_Result nvmem_get_cell_by_name(const void *fdt __unused,
+						int nodeoffset __unused,
+						const char *name __unused,
+						struct nvmem_cell **c __unused)
+{
+	return TEE_ERROR_NOT_SUPPORTED;
+}
+
+static inline
+TEE_Result nvmem_get_cell_by_index(const void *fdt __unused,
+				   int nodeoffset __unused,
+				   unsigned int index __unused,
+				   struct nvmem_cell **cell __unused)
+{
+	return TEE_ERROR_NOT_SUPPORTED;
+}
+
+static inline TEE_Result nvmem_cell_parse_dt(const void *fdt __unused,
+					     int nodeoffset __unused,
+					     struct nvmem_cell *cell __unused)
+{
+	return TEE_ERROR_NOT_SUPPORTED;
+}
+
+static inline void nvmem_put_cell(struct nvmem_cell *cell __unused)
+{
+}
+#endif /* CFG_DRIVERS_NVMEM */
+#endif /* __DRIVERS_NVMEM_H */
diff --git a/core/include/drivers/pl011.h b/core/include/drivers/pl011.h
index b46880eebe8dcfdf5fb5f6c0342ad4be96a8151d..59475c1c20b638d24c0591aa0ea86fa12c51954e 100644
--- a/core/include/drivers/pl011.h
+++ b/core/include/drivers/pl011.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2014, Linaro Limited
  */
-#ifndef PL011_H
-#define PL011_H
+#ifndef __DRIVERS_PL011_H
+#define __DRIVERS_PL011_H
 
 #include <types_ext.h>
 #include <drivers/serial.h>
@@ -18,4 +18,4 @@ struct pl011_data {
 void pl011_init(struct pl011_data *pd, paddr_t pbase, uint32_t uart_clk,
 		uint32_t baud_rate);
 
-#endif /* PL011_H */
+#endif /* __DRIVERS_PL011_H */
diff --git a/core/include/drivers/pl022_spi.h b/core/include/drivers/pl022_spi.h
index c20b01be2b28622db627d5258c7defda64929219..0ccef78a20b0c73ab009c2a3aef5fefceca00328 100644
--- a/core/include/drivers/pl022_spi.h
+++ b/core/include/drivers/pl022_spi.h
@@ -4,8 +4,8 @@
  *
  */
 
-#ifndef __PL022_SPI_H__
-#define __PL022_SPI_H__
+#ifndef __DRIVERS_PL022_SPI_H
+#define __DRIVERS_PL022_SPI_H
 
 #include <drivers/gpio.h>
 #include <spi.h>
@@ -42,5 +42,5 @@ struct pl022_data {
 
 void pl022_init(struct pl022_data *pd);
 
-#endif	/* __PL022_SPI_H__ */
+#endif	/* __DRIVERS_PL022_SPI_H */
 
diff --git a/core/include/drivers/pl061_gpio.h b/core/include/drivers/pl061_gpio.h
index 1676b2f22b74fb753f07ad4f3d231cdd86e48251..d6a36c41e2abce7c84a369b2bbcf0e10620ac9e7 100644
--- a/core/include/drivers/pl061_gpio.h
+++ b/core/include/drivers/pl061_gpio.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2016, Linaro Limited
  */
 
-#ifndef __PL061_GPIO_H__
-#define __PL061_GPIO_H__
+#ifndef __DRIVERS_PL061_GPIO_H
+#define __DRIVERS_PL061_GPIO_H
 
 #include <drivers/gpio.h>
 #include <types_ext.h>
@@ -26,4 +26,4 @@ enum pl061_mode_control pl061_get_mode_control(unsigned int gpio_pin);
 void pl061_set_mode_control(unsigned int gpio_pin,
 	enum pl061_mode_control hw_sw);
 
-#endif	/* __PL061_GPIO_H__ */
+#endif	/* __DRIVERS_PL061_GPIO_H */
diff --git a/core/include/drivers/plic.h b/core/include/drivers/plic.h
index 148fc1e97a99b95b8839f1b1da83c42f4405e3c4..f1f260430175945c9e429988f5f02fba383435b2 100644
--- a/core/include/drivers/plic.h
+++ b/core/include/drivers/plic.h
@@ -3,8 +3,8 @@
  * Copyright 2022-2023 NXP
  */
 
-#ifndef DRIVERS_PLIC_H
-#define DRIVERS_PLIC_H
+#ifndef __DRIVERS_PLIC_H
+#define __DRIVERS_PLIC_H
 
 #include <kernel/interrupt.h>
 #include <kernel/misc.h>
@@ -15,4 +15,4 @@ void plic_hart_init(void);
 void plic_it_handle(void);
 void plic_dump_state(void);
 
-#endif /*DRIVERS_PLIC_H*/
+#endif /*__DRIVERS_PLIC_H*/
diff --git a/core/include/drivers/regulator.h b/core/include/drivers/regulator.h
index e7c52a7b3eddbf95da2b1eb011cb8008f6161501..c9266bf323c6dfce501b6f8a0e8691199068b3b4 100644
--- a/core/include/drivers/regulator.h
+++ b/core/include/drivers/regulator.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2023, STMicroelectronics
  */
-#ifndef DRIVERS_REGULATOR_H
-#define DRIVERS_REGULATOR_H
+#ifndef __DRIVERS_REGULATOR_H
+#define __DRIVERS_REGULATOR_H
 
 #include <assert.h>
 #include <bitstring.h>
@@ -67,16 +67,14 @@ enum voltage_type {
 };
 
 /*
- * struct regulator_voltages - Voltage levels description
+ * struct regulator_voltages_desc - Voltage levels description
  * @type: Type of level description
- * @num_levels: Number of cells of @entries when @type is VOLTAGE_TYPE_FULL_LIST
- * @entries: Voltage level information in uV
+ * @num_levels: Number of voltage levels when @type is VOLTAGE_TYPE_FULL_LIST
  *
  */
-struct regulator_voltages {
+struct regulator_voltages_desc {
 	enum voltage_type type;
 	size_t num_levels;
-	int entries[];
 };
 
 /*
@@ -108,7 +106,7 @@ struct regulator {
 	unsigned int refcount;
 	struct mutex lock;	/* Concurrent access protection */
 	struct voltages_fallback {
-		struct regulator_voltages desc;
+		struct regulator_voltages_desc desc;
 		int levels[3];
 	} voltages_fallback;
 	size_t levels_count_fallback;
@@ -131,7 +129,8 @@ struct regulator_ops {
 	TEE_Result (*set_voltage)(struct regulator *r, int level_uv);
 	TEE_Result (*get_voltage)(struct regulator *r, int *level_uv);
 	TEE_Result (*supported_voltages)(struct regulator *r,
-					 struct regulator_voltages **voltages);
+					 struct regulator_voltages_desc **desc,
+					 const int **levels);
 	TEE_Result (*supplied_init)(struct regulator *r, const void *fdt,
 				    int node);
 };
@@ -311,8 +310,25 @@ static inline void regulator_get_range(struct regulator *regulator, int *min_uv,
 /*
  * regulator_supported_voltages() - Get regulator supported levels in microvolt
  * @regulator: Regulator reference
- * @voltages: Output description supported voltage levels
+ * @desc: Output reference to supported voltage levels description
+ * @levels: Output reference to voltage level array, in microvolts
+ *
+ * When @desc->type is VOLTAGE_TYPE_FULL_LIST, number of cells of @*levels
+ * is defined by @desc->num_levels, each cell being a level in microvolts (uV).
+ * When @desc->type is VOLTAGE_TYPE_INCREMENT, @levels has 3 cells:
+ * @levels[0] is the min voltage level, @levels[1] is the max level, @levels[2]
+ * is the incremental level step, all in microvolts (uV).
  */
 TEE_Result regulator_supported_voltages(struct regulator *regulator,
-					struct regulator_voltages **voltages);
-#endif /* DRIVERS_REGULATOR_H */
+					struct regulator_voltages_desc **desc,
+					const int **levels);
+
+/* Print current regulator tree summary to console with debug trace level */
+#ifdef CFG_DRIVERS_REGULATOR
+void regulator_print_tree(void);
+#else
+static inline void regulator_print_tree(void)
+{
+}
+#endif /* CFG_DRIVERS_REGULATOR */
+#endif /* __DRIVERS_REGULATOR_H */
diff --git a/core/include/drivers/rtc.h b/core/include/drivers/rtc.h
index c7f05be598b1314e19e071e933d594bb1866f17f..1e0df82034f3274c36ae5462c6a0f1831c9e7d0f 100644
--- a/core/include/drivers/rtc.h
+++ b/core/include/drivers/rtc.h
@@ -3,8 +3,8 @@
  * Copyright 2022 Microchip.
  */
 
-#ifndef DRIVERS_RTC_H
-#define DRIVERS_RTC_H
+#ifndef __DRIVERS_RTC_H
+#define __DRIVERS_RTC_H
 
 #include <tee_api_types.h>
 #include <util.h>
@@ -127,4 +127,4 @@ static inline TEE_Result rtc_set_offset(long offset __unused)
 	return TEE_ERROR_NOT_SUPPORTED;
 }
 #endif
-#endif /* DRIVERS_RTC_H */
+#endif /* __DRIVERS_RTC_H */
diff --git a/core/include/drivers/sam/at91_ddr.h b/core/include/drivers/sam/at91_ddr.h
index 84e13e630ac584d5a01dbc33d58278da08a4c65a..5424303ba132e2030f1f426755fa82236dff0ea6 100644
--- a/core/include/drivers/sam/at91_ddr.h
+++ b/core/include/drivers/sam/at91_ddr.h
@@ -6,8 +6,8 @@
  *	Nicolas Ferre <nicolas.ferre@atmel.com>
  */
 
-#ifndef AT91_DDRSDR_H
-#define AT91_DDRSDR_H
+#ifndef __DRIVERS_SAM_AT91_DDRSDR_H
+#define __DRIVERS_SAM_AT91_DDRSDR_H
 
 /* Mode Register */
 #define AT91_DDRSDRC_MR				0x00
diff --git a/core/include/drivers/scif.h b/core/include/drivers/scif.h
index fe818715943b5d9b2a55b8fff69522a4cf2505dc..7cb3ac015627489f1508d137c581206f2854fea3 100644
--- a/core/include/drivers/scif.h
+++ b/core/include/drivers/scif.h
@@ -26,8 +26,8 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
-#ifndef SCIF_H
-#define SCIF_H
+#ifndef __DRIVERS_SCIF_H
+#define __DRIVERS_SCIF_H
 
 #include <types_ext.h>
 #include <drivers/serial.h>
@@ -41,4 +41,4 @@ struct scif_uart_data {
 
 void scif_uart_init(struct scif_uart_data *pd, paddr_t base);
 
-#endif /* SCIF */
+#endif /* __DRIVERS_SCIF_H */
diff --git a/core/include/drivers/scmi-msg.h b/core/include/drivers/scmi-msg.h
index 08dd31c674fa74015072bf466d5c16786fa8bd31..c276ea853ce580b0aba64e7273adaab2380cee28 100644
--- a/core/include/drivers/scmi-msg.h
+++ b/core/include/drivers/scmi-msg.h
@@ -4,8 +4,8 @@
  * Copyright (c) 2019-2021, Linaro Limited
  */
 
-#ifndef SCMI_MSG_H
-#define SCMI_MSG_H
+#ifndef __DRIVERS_SCMI_MSG_H
+#define __DRIVERS_SCMI_MSG_H
 
 #include <compiler.h>
 #include <kernel/panic.h>
@@ -334,7 +334,7 @@ int32_t plat_scmi_rd_set_state(unsigned int channel_id, unsigned int scmi_id,
 size_t plat_scmi_voltd_count(unsigned int channel_id);
 
 /*
- * Get clock controller string ID (aka name)
+ * Get voltage domain string ID (aka name)
  * @channel_id: SCMI channel ID
  * @scmi_id: SCMI voltage domain ID
  * Return pointer to name or NULL
@@ -381,7 +381,7 @@ int32_t plat_scmi_voltd_get_level(unsigned int channel_id, unsigned int scmi_id,
 /*
  * Set voltage domain level voltage domain
  * @channel_id: SCMI channel ID
- * @scmi_id: SCMI clock ID
+ * @scmi_id: SCMI voltage domain ID
  * @level: Target voltage domain level in microvolt
  * Return a compliant SCMI error code
  */
@@ -408,4 +408,4 @@ int32_t plat_scmi_voltd_get_config(unsigned int channel_id,
 int32_t plat_scmi_voltd_set_config(unsigned int channel_id,
 				   unsigned int scmi_id, uint32_t config);
 
-#endif /* SCMI_MSG_H */
+#endif /* __DRIVERS_SCMI_MSG_H */
diff --git a/core/include/drivers/scmi.h b/core/include/drivers/scmi.h
index 9497206b31985a1e632bc2b35387d352b4787ab9..1e43bac6c5ede15560e9f6af8082e9c15304740b 100644
--- a/core/include/drivers/scmi.h
+++ b/core/include/drivers/scmi.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.
  */
-#ifndef SCMI_MSG_SCMI_H
-#define SCMI_MSG_SCMI_H
+#ifndef __DRIVERS_SCMI_MSG_SCMI_H
+#define __DRIVERS_SCMI_MSG_SCMI_H
 
 #define SCMI_PROTOCOL_ID_BASE			0x10
 #define SCMI_PROTOCOL_ID_POWER_DOMAIN		0x11
@@ -27,4 +27,4 @@
 #define SCMI_HARDWARE_ERROR		(-9)
 #define SCMI_PROTOCOL_ERROR		(-10)
 
-#endif /* SCMI_MSG_SCMI_H */
+#endif /* __DRIVERS_SCMI_MSG_SCMI_H */
diff --git a/core/include/drivers/serial8250_uart.h b/core/include/drivers/serial8250_uart.h
index 40816c9b97e21d66bcdcff4842589485fb47f4da..e56811fb4a7eec6bd886aa0cf24efc49fb3c7e71 100644
--- a/core/include/drivers/serial8250_uart.h
+++ b/core/include/drivers/serial8250_uart.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2015, Linaro Limited
  */
-#ifndef SERIAL8250_UART_H
-#define SERIAL8250_UART_H
+#ifndef __DRIVERS_SERIAL8250_UART_H
+#define __DRIVERS_SERIAL8250_UART_H
 
 #include <types_ext.h>
 #include <drivers/serial.h>
@@ -18,5 +18,5 @@ struct serial8250_uart_data {
 void serial8250_uart_init(struct serial8250_uart_data *pd, paddr_t base,
 			  uint32_t uart_clk, uint32_t baud_rate);
 
-#endif /* SERIAL8250_UART_H */
+#endif /* __DRIVERS_SERIAL8250_UART_H */
 
diff --git a/core/include/drivers/sp805_wdt.h b/core/include/drivers/sp805_wdt.h
index 0d5d3133bc564e9761eb30597648692d6613486a..a8f8f457366fb262e7d5e46c52495ec39f184a1a 100644
--- a/core/include/drivers/sp805_wdt.h
+++ b/core/include/drivers/sp805_wdt.h
@@ -3,8 +3,8 @@
  * Copyright 2019 Broadcom.
  */
 
-#ifndef SP805_WDT_H
-#define SP805_WDT_H
+#ifndef __DRIVERS_SP805_WDT_H
+#define __DRIVERS_SP805_WDT_H
 
 #include <drivers/wdt.h>
 #include <kernel/interrupt.h>
@@ -66,4 +66,4 @@ TEE_Result sp805_register_itr_handler(struct sp805_wdt_data *pd,
 				      uint32_t itr_num, uint32_t itr_flag,
 				      sp805_itr_handler_func_t itr_handler);
 
-#endif /* SP805_WDT_H */
+#endif /* __DRIVERS_SP805_WDT_H */
diff --git a/core/include/drivers/sprd_uart.h b/core/include/drivers/sprd_uart.h
index 64826222d6cb08a677990922dfa1c05868c9c0de..8c12c39559b272af33f789a8aa20acb81469b28b 100644
--- a/core/include/drivers/sprd_uart.h
+++ b/core/include/drivers/sprd_uart.h
@@ -26,8 +26,8 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
-#ifndef SPRD_UART_H
-#define SPRD_UART_H
+#ifndef __DRIVERS_SPRD_UART_H
+#define __DRIVERS_SPRD_UART_H
 
 #include <types_ext.h>
 #include <drivers/serial.h>
@@ -39,5 +39,5 @@ struct sprd_uart_data {
 
 void sprd_uart_init(struct sprd_uart_data *pd, paddr_t base);
 
-#endif /* SPRD_UART_H */
+#endif /* __DRIVERS_SPRD_UART_H */
 
diff --git a/core/include/drivers/stih_asc.h b/core/include/drivers/stih_asc.h
index 21e829766b503578d2b768bd886d2f01f8430657..79df157b83ccf7bc49428a14c614511f436f46ef 100644
--- a/core/include/drivers/stih_asc.h
+++ b/core/include/drivers/stih_asc.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2017, Linaro Limited
  */
-#ifndef STIH_ASC_H
-#define STIH_ASC_H
+#ifndef __DRIVERS_STIH_ASC_H
+#define __DRIVERS_STIH_ASC_H
 
 #include <drivers/serial.h>
 #include <types_ext.h>
@@ -17,5 +17,5 @@ struct stih_asc_pd {
 
 void stih_asc_init(struct stih_asc_pd *pb, vaddr_t base);
 
-#endif /* STIH_ASC_H */
+#endif /* __DRIVERS_STIH_ASC_H */
 
diff --git a/core/include/drivers/stm32_bsec.h b/core/include/drivers/stm32_bsec.h
index a5984258230407cafbe8b47ea7d13d1c79e0e899..f0577bc8b104a3ebae2a1dd1337b9d74e5407609 100644
--- a/core/include/drivers/stm32_bsec.h
+++ b/core/include/drivers/stm32_bsec.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2017-2022, STMicroelectronics
  */
 
-#ifndef __STM32_BSEC_H
-#define __STM32_BSEC_H
+#ifndef __DRIVERS_STM32_BSEC_H
+#define __DRIVERS_STM32_BSEC_H
 
 #include <compiler.h>
 #include <stdint.h>
@@ -199,4 +199,4 @@ TEE_Result stm32_bsec_find_otp_by_phandle(const uint32_t phandle,
  */
 TEE_Result stm32_bsec_get_state(enum stm32_bsec_sec_state *sec_state);
 
-#endif /*__STM32_BSEC_H*/
+#endif /*__DRIVERS_STM32_BSEC_H*/
diff --git a/core/include/drivers/stm32_etzpc.h b/core/include/drivers/stm32_etzpc.h
index 3a87ff45a1114bada503fdddc25e6db996028c47..48f0385a34747d285bfa4040628785839bb252d0 100644
--- a/core/include/drivers/stm32_etzpc.h
+++ b/core/include/drivers/stm32_etzpc.h
@@ -4,8 +4,8 @@
  * Copyright (c) 2018-2019, STMicroelectronics
  */
 
-#ifndef __STM32_ETZPC_H__
-#define __STM32_ETZPC_H__
+#ifndef __DRIVERS_STM32_ETZPC_H
+#define __DRIVERS_STM32_ETZPC_H
 
 #include <util.h>
 #include <types_ext.h>
@@ -74,4 +74,4 @@ void etzpc_lock_tzma(uint32_t tzma_id);
  * Return true if TZMA is locked, false otherwise
  */
 bool etzpc_get_lock_tzma(uint32_t tzma_id);
-#endif /*__STM32_ETZPC_H__*/
+#endif /*__DRIVERS_STM32_ETZPC_H*/
diff --git a/core/include/drivers/stm32_gpio.h b/core/include/drivers/stm32_gpio.h
index adc85358c218516795868804222768c6f0621d07..883888171f3cd58009e4c141c371693453d40170 100644
--- a/core/include/drivers/stm32_gpio.h
+++ b/core/include/drivers/stm32_gpio.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2017-2023, STMicroelectronics
  */
 
-#ifndef DRIVERS_STM32_GPIO_H
-#define DRIVERS_STM32_GPIO_H
+#ifndef __DRIVERS_STM32_GPIO_H
+#define __DRIVERS_STM32_GPIO_H
 
 #include <assert.h>
 #include <drivers/pinctrl.h>
@@ -26,16 +26,6 @@ struct stm32_pinctrl;
 void stm32_gpio_set_secure_cfg(unsigned int bank, unsigned int pin,
 			       bool secure);
 
-/*
- * Get the number of GPIO pins supported by a target GPIO bank
- *
- * @fdt: device tree reference
- * @pinctrl_node: pinctrl node which GPIO bank node belongs to
- * @bank: target GPIO bank ID
- * Return number of GPIO pins (>= 0) or a negative value on error
- */
-int stm32_get_gpio_count(void *fdt, int pinctrl_node, unsigned int bank);
-
 /*
  * Configure pin muxing access permission: can be secure or not
  *
@@ -68,4 +58,4 @@ static inline void stm32_gpio_pinctrl_bank_pin(struct pinctrl_state *p __unused,
 {
 }
 #endif /*CFG_STM32_GPIO*/
-#endif /*DRIVERS_STM32_GPIO_H*/
+#endif /*__DRIVERS_STM32_GPIO_H*/
diff --git a/core/include/drivers/stm32_i2c.h b/core/include/drivers/stm32_i2c.h
index a1c83482c98f17d46693ac8bf68fc4ed5fe3e95f..0c955ade2b8b8aa8f3f68f12ac2dfa847820d57c 100644
--- a/core/include/drivers/stm32_i2c.h
+++ b/core/include/drivers/stm32_i2c.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2017-2023, STMicroelectronics
  */
 
-#ifndef DRIVERS_STM32_I2C_H
-#define DRIVERS_STM32_I2C_H
+#ifndef __DRIVERS_STM32_I2C_H
+#define __DRIVERS_STM32_I2C_H
 
 #include <drivers/clk.h>
 #include <drivers/i2c.h>
@@ -278,4 +278,4 @@ static inline bool i2c_is_secure(struct i2c_handle_s *hi2c)
 	return hi2c->dt_status == DT_STATUS_OK_SEC;
 }
 
-#endif /* DRIVERS_STM32_I2C_H*/
+#endif /* __DRIVERS_STM32_I2C_H*/
diff --git a/core/include/drivers/stm32_iwdg.h b/core/include/drivers/stm32_iwdg.h
index f1ad7345346de0ac0c15478954f5070e8a4bc7cb..a575a199daaefba66211afec219fe30ceba2b622 100644
--- a/core/include/drivers/stm32_iwdg.h
+++ b/core/include/drivers/stm32_iwdg.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2018-2022, STMicroelectronics - All Rights Reserved
  */
 
-#ifndef DRIVERS_STM32_IWDG_H
-#define DRIVERS_STM32_IWDG_H
+#ifndef __DRIVERS_STM32_IWDG_H
+#define __DRIVERS_STM32_IWDG_H
 
 #include <stdbool.h>
 
@@ -26,8 +26,4 @@ struct stm32_iwdg_otp_data {
  */
 TEE_Result stm32_get_iwdg_otp_config(paddr_t pbase,
 				     struct stm32_iwdg_otp_data *otp_data);
-
-/* Refresh all registered IWDG watchdog instance */
-void stm32_iwdg_refresh(void);
-
-#endif /*DRIVERS_STM32_IWDG_H*/
+#endif /*__DRIVERS_STM32_IWDG_H*/
diff --git a/core/include/drivers/stm32_remoteproc.h b/core/include/drivers/stm32_remoteproc.h
new file mode 100644
index 0000000000000000000000000000000000000000..8cb1efd863ccecc0f1ddab2fea72739bce9a8b6e
--- /dev/null
+++ b/core/include/drivers/stm32_remoteproc.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2023, STMicroelectronics - All Rights Reserved
+ */
+
+#ifndef __DRIVERS_STM32_REMOTEPROC_H
+#define __DRIVERS_STM32_REMOTEPROC_H
+
+#include <stdint.h>
+#include <tee_api_types.h>
+#include <types_ext.h>
+
+/* IDs of the supported remote processors*/
+#define STM32_M4_RPROC_ID 0
+
+/*
+ * stm32_rproc_get() - get the rproc handle associated to a remote processor ID
+ * @rproc_id unique identifier of the remote processor
+ * Return a pointer to the rproc firmware handle related to @rproc_id or NULL.
+ */
+void *stm32_rproc_get(uint32_t rproc_id);
+
+/*
+ * stm32_rproc_da_to_pa() - Convert the coprocessor device address to a CPU
+ *                          physical address.
+ * @rproc_id	unique identifier of the remote processor
+ * @da		device memory address from the remote processor space
+ *		perspective.
+ * @size	size of the memory
+ * @pa		Output CPU physical address associated to @da.
+ * Return TEE_SUCCESS or appropriate error.
+ */
+TEE_Result stm32_rproc_da_to_pa(uint32_t rproc_id, paddr_t da, size_t size,
+				paddr_t *pa);
+
+/*
+ * stm32_rproc_map() - map the physical address if valid
+ * @rproc_id	unique identifier of the remote processor
+ * @pa		physical address from the CPU space perspective
+ * @size	size of the memory
+ * @va		Output CPU virtual address associated to @pa.
+ * Return TEE_SUCCESS or appropriate error.
+ */
+TEE_Result stm32_rproc_map(uint32_t rproc_id, paddr_t pa, size_t size,
+			   void **va);
+
+/*
+ * stm32_rproc_unmap() - ummap the virtual address mapped with stm32_rproc_map
+ * @rproc_id	unique identifier of the remote processor
+ * @va		virtual address
+ * @size	size of the memory
+ * Return TEE_SUCCESS or appropriate error.
+ */
+TEE_Result stm32_rproc_unmap(uint32_t rproc_id, void *va, size_t size);
+
+/*
+ * stm32_rproc_start() - start the remote processor core
+ * @rproc_id	unique identifier of the remote processor
+ * Return TEE_SUCCESS or appropriate error.
+ */
+TEE_Result stm32_rproc_start(uint32_t rproc_id);
+
+/*
+ * stm32_rproc_stop() - stop the remote processor core
+ * @rproc_id	unique identifier of the remote processor
+ * Return TEE_SUCCESS or appropriate error.
+ */
+TEE_Result stm32_rproc_stop(uint32_t rproc_id);
+
+#endif /* __DRIVERS_STM32_REMOTEPROC_H */
diff --git a/core/include/drivers/stm32_uart.h b/core/include/drivers/stm32_uart.h
index 250737f339f81a3c5f7181275863a40f16777b06..6054df72c513f57ebfd02cebca7a1a79b2dd935c 100644
--- a/core/include/drivers/stm32_uart.h
+++ b/core/include/drivers/stm32_uart.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2017-2023, STMicroelectronics
  */
 
-#ifndef DRIVERS_STM32_UART_H
-#define DRIVERS_STM32_UART_H
+#ifndef __DRIVERS_STM32_UART_H
+#define __DRIVERS_STM32_UART_H
 
 #include <drivers/clk.h>
 #include <drivers/pinctrl.h>
@@ -42,4 +42,4 @@ void stm32_uart_init(struct stm32_uart_pdata *pd, vaddr_t base);
  */
 struct stm32_uart_pdata *stm32_uart_init_from_dt_node(void *fdt, int node);
 
-#endif /*DRIVERS_STM32_UART_H*/
+#endif /*__DRIVERS_STM32_UART_H*/
diff --git a/core/include/drivers/stm32mp13_regulator_iod.h b/core/include/drivers/stm32mp13_regulator_iod.h
new file mode 100644
index 0000000000000000000000000000000000000000..9cd70e37235ccb5ff4cd44291cd0cf578ad457ba
--- /dev/null
+++ b/core/include/drivers/stm32mp13_regulator_iod.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2021-2023, STMicroelectronics
+ */
+
+#ifndef __DRIVERS_STM32MP13_REGULATOR_IOD_H
+#define __DRIVERS_STM32MP13_REGULATOR_IOD_H
+
+#include <drivers/regulator.h>
+
+enum iod_regulator_id {
+	IOD_SDMMC1,
+	IOD_SDMMC2,
+	IOD_REGU_COUNT
+};
+
+#ifdef CFG_STM32MP13_REGULATOR_IOD
+struct regulator *stm32mp1_get_iod_regulator(enum iod_regulator_id index);
+#else
+static inline struct regulator *
+stm32mp1_get_iod_regulator(enum iod_regulator_id id __unused) { return NULL; }
+#endif /* CFG_STM32MP13_REGULATOR_IOD */
+#endif /* __DRIVERS_STM32MP13_REGULATOR_IOD_H */
diff --git a/core/include/drivers/stm32mp_dt_bindings.h b/core/include/drivers/stm32mp_dt_bindings.h
index 2d7a27cf2da5b6375dbc3aaf6985c0c5a547e30b..1c438ecefa4d4b178cb3263f18bd1a8defe26c61 100644
--- a/core/include/drivers/stm32mp_dt_bindings.h
+++ b/core/include/drivers/stm32mp_dt_bindings.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2022, STMicroelectronics
  */
-#ifndef STM32MP_DT_BINDINGS_H
-#define STM32MP_DT_BINDINGS_H
+#ifndef __DRIVERS_STM32MP_DT_BINDINGS_H
+#define __DRIVERS_STM32MP_DT_BINDINGS_H
 
 #ifdef CFG_STM32MP13
 #include <dt-bindings/clock/stm32mp13-clks.h>
@@ -18,4 +18,4 @@
 #include <dt-bindings/reset/stm32mp1-resets.h>
 #endif
 
-#endif /* STM32MP_DT_BINDINGS_H */
+#endif /* __DRIVERS_STM32MP_DT_BINDINGS_H */
diff --git a/core/include/drivers/stpmic1.h b/core/include/drivers/stpmic1.h
index 0d020caedbb7c6b60945a6b33580c349ade14a3d..13539c6587c64edd5514bb55bd706b94d6561688 100644
--- a/core/include/drivers/stpmic1.h
+++ b/core/include/drivers/stpmic1.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
  */
 
-#ifndef __STPMIC1_H__
-#define __STPMIC1_H__
+#ifndef __DRIVERS_STPMIC1_H
+#define __DRIVERS_STPMIC1_H
 
 #include <drivers/stm32_i2c.h>
 #include <util.h>
@@ -241,4 +241,4 @@ int stpmic1_lp_voltage_cfg(const char *name, uint16_t millivolts,
 			   struct stpmic1_lp_cfg *cfg);
 int stpmic1_lp_voltage_unpg(struct stpmic1_lp_cfg *cfg);
 
-#endif /*__STPMIC1_H__*/
+#endif /*__DRIVERS_STPMIC1_H*/
diff --git a/core/include/drivers/wdt.h b/core/include/drivers/wdt.h
index b07152e7b80724b63322a739f3a3eb60b1260bcc..8a22b5eb4de58fe5f73efaf5d501363b029aab3e 100644
--- a/core/include/drivers/wdt.h
+++ b/core/include/drivers/wdt.h
@@ -3,8 +3,8 @@
  * Copyright 2019 Broadcom.
  */
 
-#ifndef DRIVERS_WDT_H
-#define DRIVERS_WDT_H
+#ifndef __DRIVERS_WDT_H
+#define __DRIVERS_WDT_H
 
 #include <assert.h>
 #include <kernel/interrupt.h>
@@ -117,4 +117,4 @@ enum sm_handler_ret wdt_sm_handler(struct thread_smc_args *args __unused)
 }
 #endif
 
-#endif /* DRIVERS_WDT_H */
+#endif /* __DRIVERS_WDT_H */
diff --git a/core/include/dt-bindings/gpio/stm32mp_gpio.h b/core/include/dt-bindings/gpio/stm32mp_gpio.h
new file mode 100644
index 0000000000000000000000000000000000000000..3afcf415824620394a826730e396681dbedc0f7d
--- /dev/null
+++ b/core/include/dt-bindings/gpio/stm32mp_gpio.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) */
+/*
+ * Copyright (C) STMicroelectronics 2023 - All Rights Reserved
+ */
+
+#ifndef _DT_BINDINGS_GPIO_STM32MP_GPIO_H
+#define _DT_BINDINGS_GPIO_STM32MP_GPIO_H
+
+#include <dt-bindings/gpio/gpio.h>
+
+/* Macro to define the security for GPIO */
+#ifdef __ASSEMBLER__
+#define TZPROT(id)	(1 << (id))
+#else
+#define TZPROT(id)	(UINT32_C(1) << (id))
+#endif
+
+#endif
diff --git a/core/include/gen-asm-defines.h b/core/include/gen-asm-defines.h
index ebf330f2092dfce4ec6b3ef64e3014aba43c4e28..8b612a539f0d3513f00114a5c2d86b132c18aa38 100644
--- a/core/include/gen-asm-defines.h
+++ b/core/include/gen-asm-defines.h
@@ -1,12 +1,12 @@
 /* SPDX-License-Identifier: BSD-2-Clause */
 /* Copyright (c) 2018, Linaro Limited */
 
-#ifndef GEN_ASM_DEFINES_H
-#define GEN_ASM_DEFINES_H
+#ifndef __GEN_ASM_DEFINES_H
+#define __GEN_ASM_DEFINES_H
 
 #define DEFINES void __defines(void); void __defines(void)
 
 #define DEFINE(def, val) \
 	asm volatile("\n.ascii \"==>" #def " %c0 " #val "\"" : : "i" (val));
 
-#endif /*GEN_ASM_DEFINES_H*/
+#endif /*__GEN_ASM_DEFINES_H*/
diff --git a/core/include/initcall.h b/core/include/initcall.h
index 28aa5ea75a1ad74af992964979f91076c3ecaa56..db3d95e2179139e4342d04c847dab71feb145aa8 100644
--- a/core/include/initcall.h
+++ b/core/include/initcall.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2014, Linaro Limited
  */
 
-#ifndef INITCALL_H
-#define INITCALL_H
+#ifndef __INITCALL_H
+#define __INITCALL_H
 
 #include <scattered_array.h>
 #include <tee_api_types.h>
diff --git a/core/include/io.h b/core/include/io.h
index 85365ce7ac9de96d21f12496b5cbc2c081c3e23e..0ef91907b3423cd85da30449db9d31f50c6fecb0 100644
--- a/core/include/io.h
+++ b/core/include/io.h
@@ -2,10 +2,11 @@
 /*
  * Copyright (c) 2014-2019, Linaro Limited
  */
-#ifndef IO_H
-#define IO_H
+#ifndef __IO_H
+#define __IO_H
 
 #include <compiler.h>
+#include <kernel/delay.h>
 #include <stdint.h>
 #include <types_ext.h>
 #include <utee_defines.h>
@@ -300,4 +301,4 @@ static inline void io_clrsetbits8(vaddr_t addr, uint8_t clear_mask,
 		!(_cond); \
 	})
 
-#endif /*IO_H*/
+#endif /*__IO_H*/
diff --git a/core/include/keep.h b/core/include/keep.h
index 0dbe91005fc7018610dc365fa8c791158273e4f9..622d1d65bbfc024d90c6b5e5e6864dd3302b0182 100644
--- a/core/include/keep.h
+++ b/core/include/keep.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2015, Linaro Limited
  */
-#ifndef KEEP_H
-#define KEEP_H
+#ifndef __KEEP_H
+#define __KEEP_H
 
 #ifdef __ASSEMBLER__
 
@@ -45,4 +45,4 @@
 
 #endif /* __ASSEMBLER__ */
 
-#endif /*KEEP_H*/
+#endif /*__KEEP_H*/
diff --git a/core/include/kernel/abort.h b/core/include/kernel/abort.h
index ed0e5c0ca4b1000dd8a84393e04202abcb422764..4a0f5270d2c1ca58f479b9992de4054fcbdfeb4e 100644
--- a/core/include/kernel/abort.h
+++ b/core/include/kernel/abort.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2015-2021, Linaro Limited
  */
 
-#ifndef KERNEL_ABORT_H
-#define KERNEL_ABORT_H
+#ifndef __KERNEL_ABORT_H
+#define __KERNEL_ABORT_H
 
 #define ABORT_TYPE_UNDEF		0
 #define ABORT_TYPE_PREFETCH		1
@@ -40,5 +40,5 @@ bool abort_is_write_fault(struct abort_info *ai);
 void abort_print_current_ts(void);
 
 #endif /*__ASSEMBLER__*/
-#endif /*KERNEL_ABORT_H*/
+#endif /*__KERNEL_ABORT_H*/
 
diff --git a/core/include/kernel/boot.h b/core/include/kernel/boot.h
index 14025b30cc2c774ab66952627ef51d2ba810c06c..bf78d5c3808fffef1911b27388cb0a50d7f28c01 100644
--- a/core/include/kernel/boot.h
+++ b/core/include/kernel/boot.h
@@ -42,12 +42,11 @@ struct boot_embdata {
 
 extern const struct core_mmu_config boot_mmu_config;
 
-/* @nsec_entry is unused if using CFG_WITH_ARM_TRUSTED_FW */
-void boot_init_primary_early(unsigned long pageable_part,
-			     unsigned long nsec_entry);
+void boot_init_primary_early(void);
 void boot_init_primary_late(unsigned long fdt, unsigned long manifest);
 void boot_init_memtag(void);
-void boot_save_boot_info(void *boot_info);
+void boot_save_args(unsigned long a0, unsigned long a1, unsigned long a2,
+		    unsigned long a3, unsigned long a4);
 
 void __panic_at_smc_return(void) __noreturn;
 
@@ -96,10 +95,9 @@ void *get_manifest_dt(void);
 
 /*
  * get_aslr_seed() - return a random seed for core ASLR
- * @fdt:	Pointer to a device tree if CFG_DT_ADDR=y
  *
  * This function has a __weak default implementation.
  */
-unsigned long get_aslr_seed(void *fdt);
+unsigned long get_aslr_seed(void);
 
 #endif /* __KERNEL_BOOT_H */
diff --git a/core/include/kernel/chip_services.h b/core/include/kernel/chip_services.h
index a22237ce1987e7e47dd6436b29d42bf4d1cd2265..c051078f15c43a229036e336ad3e493d9ad277e2 100644
--- a/core/include/kernel/chip_services.h
+++ b/core/include/kernel/chip_services.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
-#ifndef CHIP_SERVICES_H
-#define CHIP_SERVICES_H
+#ifndef __KERNEL_CHIP_SERVICES_H
+#define __KERNEL_CHIP_SERVICES_H
 
 /* Die ID */
 #define FVR_DIE_ID_NUM_REGS                 3
diff --git a/core/include/kernel/dt.h b/core/include/kernel/dt.h
index 7a7bd9afdccb0957cce95f50ae2656a99c7064ad..ad5cde23ab97bcbf2d9c36d654f4dfc615eafdf9 100644
--- a/core/include/kernel/dt.h
+++ b/core/include/kernel/dt.h
@@ -3,11 +3,10 @@
  * Copyright (c) 2016-2021, Linaro Limited
  */
 
-#ifndef KERNEL_DT_H
-#define KERNEL_DT_H
+#ifndef __KERNEL_DT_H
+#define __KERNEL_DT_H
 
 #include <compiler.h>
-#include <kernel/interrupt.h>
 #include <kernel/panic.h>
 #include <scattered_array.h>
 #include <stdint.h>
@@ -267,13 +266,14 @@ struct dt_descriptor *get_external_dt_desc(void);
 /*
  * init_external_dt() - Initialize the external DTB located at given address.
  * @phys_dt:	Physical address where the external DTB located.
+ * @dt_sz:	Maximum size of the external DTB.
  *
  * Initialize the external DTB.
  *
  * 1. Add MMU mapping of the external DTB,
  * 2. Initialize device tree overlay
  */
-void init_external_dt(unsigned long phys_dt);
+void init_external_dt(unsigned long phys_dt, size_t dt_sz);
 
 /* Returns external DTB if present, otherwise NULL */
 void *get_external_dt(void);
@@ -420,7 +420,8 @@ static inline struct dt_descriptor *get_external_dt_desc(void)
 	return NULL;
 }
 
-static inline void init_external_dt(unsigned long phys_dt __unused)
+static inline void init_external_dt(unsigned long phys_dt __unused,
+				    size_t dt_sz __unused)
 {
 }
 
@@ -445,4 +446,4 @@ static inline int add_res_mem_dt_node(struct dt_descriptor *dt __unused,
 }
 
 #endif /* !CFG_DT */
-#endif /* KERNEL_DT_H */
+#endif /* __KERNEL_DT_H */
diff --git a/core/include/kernel/dt_driver.h b/core/include/kernel/dt_driver.h
index 38a934ad17e2840be7f482560b383ad8f839be1e..f73f30073acff86a635330e3788b8d985f9e406b 100644
--- a/core/include/kernel/dt_driver.h
+++ b/core/include/kernel/dt_driver.h
@@ -5,8 +5,8 @@
  * Copyright (c) 2021, STMicroelectronics
  */
 
-#ifndef __DT_DRIVER_H
-#define __DT_DRIVER_H
+#ifndef __KERNEL_DT_DRIVER_H
+#define __KERNEL_DT_DRIVER_H
 
 #include <kernel/dt.h>
 #include <stdint.h>
@@ -25,6 +25,7 @@
  * DT_DRIVER_PINCTRL Pin controller using generic reset DT bindings
  * DT_DRIVER_INTERRUPT Interrupt controller using generic DT bindings
  * DT_DRIVER_REGULATOR Voltage regulator controller using generic DT bindings
+ * DT_DRIVER_NVMEM NVMEM controller using generic NVMEM DT bindings
  */
 enum dt_driver_type {
 	DT_DRIVER_NOTYPE,
@@ -36,6 +37,7 @@ enum dt_driver_type {
 	DT_DRIVER_PINCTRL,
 	DT_DRIVER_INTERRUPT,
 	DT_DRIVER_REGULATOR,
+	DT_DRIVER_NVMEM,
 };
 
 /*
@@ -102,16 +104,16 @@ struct dt_pargs {
  *
  * @parg: phandle argument(s) referencing the device in the FDT.
  * @data: driver private data registered in struct dt_driver.
- * @res: Output result code of the operation:
- *	TEE_SUCCESS in case of success
- *	TEE_ERROR_DEFER_DRIVER_INIT if device driver is not yet initialized
- *	Any TEE_Result compliant code in case of error.
+ * @device_ref: output device reference upon success, e.g. a struct clk
+ *	pointer for a clock driver.
  *
- * Return a device opaque reference, e.g. a struct clk pointer for a clock
- * driver, or NULL if not found in which case @res provides the error code.
+ * Return code:
+ * TEE_SUCCESS in case of success
+ * TEE_ERROR_DEFER_DRIVER_INIT if device driver is not yet initialized
+ * Any TEE_Result compliant code in case of error.
  */
 typedef TEE_Result (*get_of_device_func)(struct dt_pargs *parg, void *data,
-					 void **out_device);
+					 void *device_ref);
 
 /**
  * dt_driver_register_provider - Register a driver provider
@@ -139,7 +141,7 @@ TEE_Result dt_driver_register_provider(const void *fdt, int nodeoffset,
  * @nodeoffset: node offset in the FDT
  * @prop_idx: index of the phandle data in the property
  * @type: Driver type
- * @out_device: output device opaque reference upon support, for example
+ * @device_ref: output device opaque reference upon support, for example
  *	a struct clk pointer for a clock driver.
 
  * Return code:
@@ -153,7 +155,7 @@ TEE_Result dt_driver_device_from_node_idx_prop(const char *prop_name,
 					       const void *fdt, int nodeoffset,
 					       unsigned int prop_idx,
 					       enum dt_driver_type type,
-					       void **out_device);
+					       void *device_ref);
 
 /*
  * dt_driver_device_from_parent - Return a device instance based on the parent.
@@ -163,7 +165,7 @@ TEE_Result dt_driver_device_from_node_idx_prop(const char *prop_name,
  * @fdt: FDT base address
  * @nodeoffset: node offset in the FDT
  * @type: Driver type
- * @dout_device: output device opaque reference upon success, for example
+ * @device_ref: output device opaque reference upon success, for example
  *	a struct i2c_dev pointer for a I2C bus driver
  *
  * Return code:
@@ -173,7 +175,7 @@ TEE_Result dt_driver_device_from_node_idx_prop(const char *prop_name,
  */
 TEE_Result dt_driver_device_from_parent(const void *fdt, int nodeoffset,
 					enum dt_driver_type type,
-					void **out_device);
+					void *device_ref);
 
 /*
  * dt_driver_device_from_node_idx_prop_phandle() - Same as
@@ -190,7 +192,7 @@ TEE_Result dt_driver_device_from_node_idx_prop_phandle(const char *prop_name,
 						       unsigned int prop_index,
 						       enum dt_driver_type type,
 						       uint32_t phandle,
-						       void **out_device);
+						       void *device_ref);
 
 /*
  * dt_driver_get_crypto() - Request crypto support for driver initialization
@@ -278,5 +280,4 @@ static inline TEE_Result dt_driver_test_status(void)
 	return TEE_ERROR_NOT_IMPLEMENTED;
 }
 #endif
-
-#endif /* __DT_DRIVER_H */
+#endif /* __KERNEL_DT_DRIVER_H */
diff --git a/core/include/kernel/early_ta.h b/core/include/kernel/early_ta.h
index b7f9f38a696e1d5883b886d4f2cd043948c11b6d..8ad12e596385e2c6cd0d7b8f03e15e450d8ca4e2 100644
--- a/core/include/kernel/early_ta.h
+++ b/core/include/kernel/early_ta.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2017, 2020, Linaro Limited
  * Copyright (c) 2020, Arm Limited.
  */
-#ifndef KERNEL_EARLY_TA_H
-#define KERNEL_EARLY_TA_H
+#ifndef __KERNEL_EARLY_TA_H
+#define __KERNEL_EARLY_TA_H
 
 #include <kernel/embedded_ts.h>
 #include <scattered_array.h>
@@ -14,5 +14,5 @@
 #define for_each_early_ta(_ta) \
 	SCATTERED_ARRAY_FOREACH(_ta, early_tas, struct embedded_ts)
 
-#endif /* KERNEL_EARLY_TA_H */
+#endif /* __KERNEL_EARLY_TA_H */
 
diff --git a/core/include/kernel/embedded_ts.h b/core/include/kernel/embedded_ts.h
index d2ae758b5b7a3213d3014c573f2ef2d4d0166206..aeaabffa215b5300d60bbde398b7af5f5619305f 100644
--- a/core/include/kernel/embedded_ts.h
+++ b/core/include/kernel/embedded_ts.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2017, Linaro Limited
  * Copyright (c) 2020, Arm Limited.
  */
-#ifndef KERNEL_EMBEDDED_TS_H
-#define KERNEL_EMBEDDED_TS_H
+#ifndef __KERNEL_EMBEDDED_TS_H
+#define __KERNEL_EMBEDDED_TS_H
 
 #include <compiler.h>
 #include <kernel/linker.h>
@@ -33,5 +33,5 @@ TEE_Result emb_ts_open(const TEE_UUID *uuid,
 TEE_Result emb_ts_get_size(const struct ts_store_handle *h, size_t *size);
 TEE_Result emb_ts_get_tag(const struct ts_store_handle *h,
 			  uint8_t *tag, unsigned int *tag_len);
-#endif /* KERNEL_EMBEDDED_TS_H */
+#endif /* __KERNEL_EMBEDDED_TS_H */
 
diff --git a/core/include/kernel/handle.h b/core/include/kernel/handle.h
index eb4375dd3cf3a9149e09f89b6efbe468c1e5c4ac..9a7504d5c249d89c7905861f26224507fb1cc062 100644
--- a/core/include/kernel/handle.h
+++ b/core/include/kernel/handle.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2014, Linaro Limited
  * Copyright (c) 2020, Arm Limited
  */
-#ifndef KERNEL_HANDLE_H
-#define KERNEL_HANDLE_H
+#ifndef __KERNEL_HANDLE_H
+#define __KERNEL_HANDLE_H
 
 #include <stdbool.h>
 #include <stdint.h>
@@ -49,4 +49,4 @@ void *handle_put(struct handle_db *db, int handle);
  */
 void *handle_lookup(struct handle_db *db, int handle);
 
-#endif /*KERNEL_HANDLE_H*/
+#endif /*__KERNEL_HANDLE_H*/
diff --git a/core/include/kernel/interrupt.h b/core/include/kernel/interrupt.h
index c5b66a9b83a5731434fe181705e43dfbb4dce7c7..22a7a044945b5c353e1e18ff25a0b8f20997ef91 100644
--- a/core/include/kernel/interrupt.h
+++ b/core/include/kernel/interrupt.h
@@ -6,6 +6,7 @@
 #define __KERNEL_INTERRUPT_H
 
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <kernel/dt_driver.h>
 #include <mm/core_memprot.h>
 #include <sys/queue.h>
 #include <tee_api_types.h>
@@ -15,6 +16,11 @@
 #define ITRF_TRIGGER_LEVEL	BIT(0)
 #define ITRF_SHARED		BIT(1)
 
+/* Forward the interrupt only to the current CPU */
+#define ITR_CPU_MASK_TO_THIS_CPU	BIT(31)
+/* Forward the interrupt to all CPUs except the current CPU */
+#define ITR_CPU_MASK_TO_OTHER_CPUS	BIT(30)
+
 struct itr_handler;
 
 /*
@@ -65,11 +71,25 @@ struct itr_ops {
 	void (*unmask)(struct itr_chip *chip, size_t it);
 	void (*raise_pi)(struct itr_chip *chip, size_t it);
 	void (*raise_sgi)(struct itr_chip *chip, size_t it,
-		uint8_t cpu_mask);
+			  uint32_t cpu_mask);
 	void (*set_affinity)(struct itr_chip *chip, size_t it,
 		uint8_t cpu_mask);
 };
 
+/*
+ * struct itr_desc - Interrupt description
+ * @chip	Interrupt controller reference
+ * @itr_num	Interrupt number
+ *
+ * This struct is used for binding interrupt device data between
+ * drivers when using DT_DRIVERS means. See itr_dt_get_func type
+ * definition.
+ */
+struct itr_desc {
+	struct itr_chip *chip;
+	size_t itr_num;
+};
+
 /* Interrupt handler return value */
 enum itr_return {
 	ITRR_NONE,
@@ -130,6 +150,8 @@ void interrupt_main_init(struct itr_chip *data);
 
 /* Retrieve main interrupt controller reference */
 struct itr_chip *interrupt_get_main_chip(void);
+/* Retrieve main interrupt controller reference, or NULL on failure */
+struct itr_chip *interrupt_get_main_chip_may_fail(void);
 
 #ifdef CFG_DT
 /*
@@ -158,27 +180,6 @@ static inline int dt_get_irq(const void *fdt, int node)
 }
 #endif
 
-struct itr_handler *itr_alloc_add_type_prio(size_t it, itr_handler_t handler,
-					    uint32_t flags, void *data,
-					    uint32_t type, uint32_t prio);
-void itr_free(struct itr_handler *hdl);
-void itr_add_type_prio(struct itr_handler *handler, uint32_t type,
-		       uint32_t prio);
-void itr_enable(size_t it);
-void itr_disable(size_t it);
-/* raise the Peripheral Interrupt corresponding to the interrupt ID */
-void itr_raise_pi(size_t it);
-/*
- * raise the Software Generated Interrupt corresponding to the interrupt ID,
- * the cpu_mask represents which cpu interface to forward.
- */
-void itr_raise_sgi(size_t it, uint8_t cpu_mask);
-/*
- * let corresponding interrupt forward to the cpu interface
- * according to the cpu_mask.
- */
-void itr_set_affinity(size_t it, uint8_t cpu_mask);
-
 /*
  * __weak overridable function which is called when a secure interrupt is
  * received. The default function calls panic() immediately, platforms which
@@ -186,19 +187,6 @@ void itr_set_affinity(size_t it, uint8_t cpu_mask);
  */
 void interrupt_main_handler(void);
 
-static inline void itr_add(struct itr_handler *handler)
-{
-	itr_add_type_prio(handler, IRQ_TYPE_NONE, 0);
-}
-
-static inline struct itr_handler *itr_alloc_add(size_t it,
-						itr_handler_t handler,
-						uint32_t flags, void *data)
-{
-	return itr_alloc_add_type_prio(it, handler, flags, data, IRQ_TYPE_NONE,
-				       0);
-}
-
 /*
  * Interrupt controller chip API functions
  */
@@ -300,10 +288,12 @@ static inline void interrupt_raise_pi(struct itr_chip *chip, size_t itr_num)
  * interrupt_raise_sgi() - Raise a software generiated interrupt of a controller
  * @chip	Interrupt controller
  * @itr_num	Interrupt number to raise
- * @cpu_mask	Mask of the CPUs targeted by the interrupt
+ * @cpu_mask:	A bitfield of CPUs to forward the interrupt to, unless
+ *		ITR_CPU_MASK_TO_THIS_CPU or ITR_CPU_MASK_TO_OTHER_CPUS
+ *		(mutually exclusive) are set.
  */
 static inline void interrupt_raise_sgi(struct itr_chip *chip, size_t itr_num,
-				       uint8_t cpu_mask)
+				       uint32_t cpu_mask)
 {
 	assert(interrupt_can_raise_sgi(chip));
 	chip->ops->raise_sgi(chip, itr_num, cpu_mask);
@@ -357,6 +347,25 @@ static inline TEE_Result interrupt_add_handler(struct itr_handler *hdl)
 	return interrupt_add_configure_handler(hdl, IRQ_TYPE_NONE, 0);
 }
 
+/*
+ * interrupt_create_handler() - Allocate/register an interrupt callback handler
+ * @itr_chip Interrupt chip obtained from dt_get_interrupt_by_*()
+ * @itr_num Interrupt number obtained from dt_get_interrupt_by_*()
+ * @callback Callback handler function
+ * @priv Private dat to pssa to @callback
+ * @flags INTERRUPT_FLAGS_* or 0
+ * @out_hdl Output allocated and registered handler or NULL
+ *
+ * This function  differs from interrupt_add_handler() in that the
+ * interrupt is not reconfigured. interrupt_create_handler() expects
+ * @itr_desc was obtained from a call to dt_get_interrupt_by_index()
+ * or dt_get_interrupt_by_name(). That call configured the interrupt.
+ */
+TEE_Result interrupt_create_handler(struct itr_chip *itr_chip, size_t itr_num,
+				    itr_handler_t callback, void *priv,
+				    uint32_t flags,
+				    struct itr_handler **out_hdl);
+
 /*
  * interrupt_add_handler_with_chip() - Register an interrupt handler providing
  *	the interrupt chip reference in specific argument @chip.
@@ -426,4 +435,110 @@ static inline TEE_Result interrupt_alloc_add_handler(struct itr_chip *chip,
  * This function may panic on non-NULL invalid @hdl reference.
  */
 void interrupt_remove_free_handler(struct itr_handler *hdl);
+
+/*
+ * itr_dt_get_func - Typedef of function to get an interrupt in DT node
+ *
+ * @args	Reference to phandle arguments
+ * @data	Pointer to data given at interrupt_register_provider() call
+ * @itr_desc_p	Pointer to the struct itr_desc to fill
+ * Return TEE_SUCCESS in case of success.
+ * Return TEE_ERROR_DEFER_DRIVER_INIT if controller is not initialized.
+ * Return another TEE_Result code otherwise.
+ *
+ * Upon success, the interrupt is configured and consumer can add a handler
+ * function to the interrupt. Yet, the interrupt is not enabled until consumer
+ * calls interrupt_enable().
+ */
+typedef TEE_Result (*itr_dt_get_func)(struct dt_pargs *args, void *data,
+				      struct itr_desc *itr_desc_p);
+
+#ifdef CFG_DT
+/**
+ * interrupt_register_provider() - Register an interrupt provider
+ *
+ * @fdt		Device tree to work on
+ * @node	Node offset of the interrupt controller in the DT
+ * @dt_get_itr	Callback to match the devicetree interrupt reference with
+ * @data	Data which will be passed to the get_dt_its callback
+ */
+TEE_Result interrupt_register_provider(const void *fdt, int node,
+				       itr_dt_get_func dt_get_itr, void *data);
+
+/**
+ * interrupt_dt_get_by_index() - Get an interrupt from DT by interrupt index
+ *
+ * Interrupt index (@index) refers to the index of the target interrupt to be
+ * retrieved as DT binding property "interrupts" may define several
+ * interrupts.
+ *
+ * @fdt		Device tree to work on
+ * @node	Node offset of the subnode containing interrupt(s) references
+ * @index	Index in "interrupts" or "extended-interrupts" property list
+ * @chip	Output interrupt controller reference upon success
+ * @itr_num	Output interrupt number upon success
+ *
+ * Return TEE_SUCCESS in case of success
+ * Return TEE_ERROR_DEFER_DRIVER_INIT if interrupt driver is not yet initialized
+ * Return TEE_ERROR_ITEM_NOT_FOUND if the DT does not reference target interrupt
+ * Return any other TEE_Result compliant code in case of error
+ */
+TEE_Result interrupt_dt_get_by_index(const void *fdt, int node,
+				     unsigned int index, struct itr_chip **chip,
+				     size_t *itr_num);
+
+/**
+ * interrupt_dt_get_by_name() - Get an interrupt from DT by interrupt name
+ *
+ * @fdt		Device tree to work on
+ * @node	Node offset of the subnode containing interrupt(s) references
+ * @name	Name identifier used in "interrupt-names" property
+ * @chip	Output interrupt controller reference upon success
+ * @itr_num	Output interrupt number upon success
+ *
+ * Return TEE_SUCCESS in case of success
+ * Return TEE_ERROR_DEFER_DRIVER_INIT if interrupt driver is not yet initialized
+ * Return TEE_ERROR_ITEM_NOT_FOUND if the DT does not reference target interrupt
+ * Return any other TEE_Result compliant code in case of error
+ */
+TEE_Result interrupt_dt_get_by_name(const void *fdt, int node, const char *name,
+				    struct itr_chip **chip, size_t *itr_num);
+#else
+static inline TEE_Result interrupt_register_provider(const void *dt __unused,
+						     int node __unused,
+						     itr_dt_get_func f __unused,
+						     void *data __unused)
+{
+	return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+static inline TEE_Result interrupt_dt_get_by_index(const void *fdt __unused,
+						   int node __unused,
+						   unsigned int index __unused,
+						   struct itr_chip **c __unused,
+						   size_t *itr_num __unused)
+{
+	return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+static inline TEE_Result interrupt_dt_get_by_name(const void *fdt __unused,
+						  int node __unused,
+						  const char *name __unused,
+						  struct itr_chip **ch __unused,
+						  size_t *itr_num __unused)
+{
+	return TEE_ERROR_NOT_IMPLEMENTED;
+}
+#endif /*CFG_DT*/
+
+/*
+ * Helper function for when caller retrieves the first interrupt defined
+ * in "interrupts" or "extended-interrupts" DT binding property list.
+ */
+static inline TEE_Result interrupt_dt_get(const void *fdt, int node,
+					  struct itr_chip **chip,
+					  size_t *itr_num)
+{
+	return interrupt_dt_get_by_index(fdt, node, 0, chip, itr_num);
+}
 #endif /*__KERNEL_INTERRUPT_H*/
diff --git a/core/include/kernel/ldelf_loader.h b/core/include/kernel/ldelf_loader.h
index 4d5e92c6f8f94b7ba1f5f3524df782bdfe05ee96..fef590cd0f75ecc896d926921c60c76e5ab296cd 100644
--- a/core/include/kernel/ldelf_loader.h
+++ b/core/include/kernel/ldelf_loader.h
@@ -7,8 +7,8 @@
 #include <kernel/user_mode_ctx.h>
 #include <tee_api_types.h>
 
-#ifndef KERNEL_LDELF_LOADER_H
-#define KERNEL_LDELF_LOADER_H
+#ifndef __KERNEL_LDELF_LOADER_H
+#define __KERNEL_LDELF_LOADER_H
 
 TEE_Result ldelf_load_ldelf(struct user_mode_ctx *uctx);
 TEE_Result ldelf_init_with_ldelf(struct ts_session *sess,
@@ -21,4 +21,4 @@ TEE_Result ldelf_dlopen(struct user_mode_ctx *uctx, TEE_UUID *uuid,
 TEE_Result ldelf_dlsym(struct user_mode_ctx *uctx, TEE_UUID *uuid,
 		       const char *sym, size_t symlen, vaddr_t *val);
 
-#endif /* KERNEL_LDELF_LOADER_H */
+#endif /* __KERNEL_LDELF_LOADER_H */
diff --git a/core/include/kernel/ldelf_syscalls.h b/core/include/kernel/ldelf_syscalls.h
index 5dd89a7f23dccf7d365f10b7733b1f271b7eb4ce..62b410ad78a92cabec1edc588ff689366afe4b18 100644
--- a/core/include/kernel/ldelf_syscalls.h
+++ b/core/include/kernel/ldelf_syscalls.h
@@ -11,8 +11,8 @@
 #include <tee_api_types.h>
 #include <types_ext.h>
 
-#ifndef KERNEL_LDELF_SYSCALLS_H
-#define KERNEL_LDELF_SYSCALLS_H
+#ifndef __KERNEL_LDELF_SYSCALLS_H
+#define __KERNEL_LDELF_SYSCALLS_H
 
 struct system_ctx {
 	struct handle_db db;
@@ -39,4 +39,4 @@ TEE_Result ldelf_syscall_remap(unsigned long old_va, vaddr_t *new_va,
 TEE_Result ldelf_syscall_gen_rnd_num(void *buf, size_t num_bytes);
 void ldelf_sess_cleanup(struct ts_session *sess);
 
-#endif /* KERNEL_LDELF_SYSCALLS_H */
+#endif /* __KERNEL_LDELF_SYSCALLS_H */
diff --git a/core/include/kernel/misc.h b/core/include/kernel/misc.h
index 35cfa5f133ab6b39e268b8c3c1b63a090e05f941..d204a3ae7a626a8e203bc4fac8ea1000566d4678 100644
--- a/core/include/kernel/misc.h
+++ b/core/include/kernel/misc.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
-#ifndef KERNEL_MISC_H
-#define KERNEL_MISC_H
+#ifndef __KERNEL_MISC_H
+#define __KERNEL_MISC_H
 
 #include <assert.h>
 #include <kernel/misc_arch.h>
@@ -23,4 +23,4 @@ static inline size_t __noprof get_core_pos(void)
 	return __get_core_pos();
 }
 
-#endif /*KERNEL_MISC_H*/
+#endif /*__KERNEL_MISC_H*/
diff --git a/core/include/kernel/msg_param.h b/core/include/kernel/msg_param.h
index 841c3bfa4e7742df6e7a7a7e4d4ecb3535c9bb2a..2cf3da657d39901a4c7dcfca241bb8a3feb5d5b7 100644
--- a/core/include/kernel/msg_param.h
+++ b/core/include/kernel/msg_param.h
@@ -26,8 +26,8 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef KERNEL_MSG_PARAM_H
-#define KERNEL_MSG_PARAM_H
+#ifndef __KERNEL_MSG_PARAM_H
+#define __KERNEL_MSG_PARAM_H
 
 #include <compiler.h>
 #include <kernel/msg_param.h>
@@ -81,4 +81,4 @@ static inline bool msg_param_attr_is_tmem(uint64_t attr)
 	}
 }
 
-#endif	/*KERNEL_MSG_PARAM_H*/
+#endif	/*__KERNEL_MSG_PARAM_H*/
diff --git a/core/include/kernel/mutex.h b/core/include/kernel/mutex.h
index e4c470b0f15f837857c410964dbde6be57f270bc..c701188d79c274ceb7185f76443d86253baf43fd 100644
--- a/core/include/kernel/mutex.h
+++ b/core/include/kernel/mutex.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2014-2017, Linaro Limited
  */
-#ifndef KERNEL_MUTEX_H
-#define KERNEL_MUTEX_H
+#ifndef __KERNEL_MUTEX_H
+#define __KERNEL_MUTEX_H
 
 #include <kernel/refcount.h>
 #include <kernel/wait_queue.h>
@@ -101,5 +101,5 @@ void condvar_broadcast(struct condvar *cv);
 void condvar_wait(struct condvar *cv, struct mutex *m);
 #endif
 
-#endif /*KERNEL_MUTEX_H*/
+#endif /*__KERNEL_MUTEX_H*/
 
diff --git a/core/include/kernel/panic.h b/core/include/kernel/panic.h
index 9dc38dce13f7faf4e00f66ab887476b42008b713..3d4fa55b248a8873b0011c518dfa1bd0a28feeab 100644
--- a/core/include/kernel/panic.h
+++ b/core/include/kernel/panic.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
-#ifndef KERNEL_PANIC_H
-#define KERNEL_PANIC_H
+#ifndef __KERNEL_PANIC_H
+#define __KERNEL_PANIC_H
 
 #include <compiler.h>
 
@@ -39,4 +39,4 @@ void __do_panic(const char *file, const int line, const char *func,
  */
 void cpu_idle(void);
 
-#endif /*KERNEL_PANIC_H*/
+#endif /*__KERNEL_PANIC_H*/
diff --git a/core/include/kernel/pseudo_ta.h b/core/include/kernel/pseudo_ta.h
index 132c59f11e4201e01d0e528ab4a8c408f757045a..965ca0d4364d4bfcdfa25f5fa96149907460b71a 100644
--- a/core/include/kernel/pseudo_ta.h
+++ b/core/include/kernel/pseudo_ta.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2015, Linaro Limited
  */
-#ifndef KERNEL_PSEUDO_TA_H
-#define KERNEL_PSEUDO_TA_H
+#ifndef __KERNEL_PSEUDO_TA_H
+#define __KERNEL_PSEUDO_TA_H
 
 #include <assert.h>
 #include <compiler.h>
@@ -95,5 +95,5 @@ TEE_Result from_bounce_params(uint32_t param_types,
 			      TEE_Param bparams[TEE_NUM_PARAMS],
 			      TEE_Param *eparams);
 
-#endif /* KERNEL_PSEUDO_TA_H */
+#endif /* __KERNEL_PSEUDO_TA_H */
 
diff --git a/core/include/kernel/rpc_io_i2c.h b/core/include/kernel/rpc_io_i2c.h
index 50ddbcd4dd2f32a5d153f2aadfbc2ddae601e388..fe9f6b8e6726eec3a17db7ea8bdae28c1ca58863 100644
--- a/core/include/kernel/rpc_io_i2c.h
+++ b/core/include/kernel/rpc_io_i2c.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2020 Foundries Ltd <jorge@foundries.io>
  */
 
-#ifndef __RPC_IO_I2C_H
-#define __RPC_IO_I2C_H
+#ifndef __KERNEL_RPC_IO_I2C_H
+#define __KERNEL_RPC_IO_I2C_H
 
 #include <optee_rpc_cmd.h>
 #include <tee_api_types.h>
@@ -35,4 +35,4 @@ struct rpc_i2c_request {
 
 TEE_Result rpc_io_i2c_transfer(struct rpc_i2c_request *p, size_t *bytes);
 
-#endif /* __RPC_IO_I2C_H */
+#endif /* __KERNEL_RPC_IO_I2C_H */
diff --git a/core/include/kernel/spinlock.h b/core/include/kernel/spinlock.h
index fc3e2e474f82e5245133d38ac8ac71dc62dbd62c..e7a84d32b678f404e81d0ee726803457a17118df 100644
--- a/core/include/kernel/spinlock.h
+++ b/core/include/kernel/spinlock.h
@@ -4,8 +4,8 @@
  * Copyright (c) 2016, Linaro Limited
  */
 
-#ifndef KERNEL_SPINLOCK_H
-#define KERNEL_SPINLOCK_H
+#ifndef __KERNEL_SPINLOCK_H
+#define __KERNEL_SPINLOCK_H
 
 #define SPINLOCK_LOCK       1
 #define SPINLOCK_UNLOCK     0
@@ -129,4 +129,4 @@ static inline void cpu_spin_unlock_xrestore(unsigned int *lock,
 }
 #endif /* __ASSEMBLER__ */
 
-#endif /* KERNEL_SPINLOCK_H */
+#endif /* __KERNEL_SPINLOCK_H */
diff --git a/core/include/kernel/tee_common.h b/core/include/kernel/tee_common.h
index 5c5da2d6e4c5c86e6391f856f697c795faa3a61d..d4b0672107b8f7b640bff2a11189cebebd220ea5 100644
--- a/core/include/kernel/tee_common.h
+++ b/core/include/kernel/tee_common.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
-#ifndef TEE_COMMON_H
-#define TEE_COMMON_H
+#ifndef __KERNEL_TEE_COMMON_H
+#define __KERNEL_TEE_COMMON_H
 
 #include <stdlib.h>
 
@@ -35,4 +35,4 @@ void tee_mtime_perftest(void);
 #define tee_mtime_perftest()  do { } while (0)
 #endif
 
-#endif /* TEE_COMMON_H */
+#endif /* __KERNEL_TEE_COMMON_H */
diff --git a/core/include/kernel/tee_common_otp.h b/core/include/kernel/tee_common_otp.h
index 2b0d3a3a209d9020c13eb989bb3c05e01b9f07f4..cc1f0a88bb3457f960545949d6034ad6dbeefd54 100644
--- a/core/include/kernel/tee_common_otp.h
+++ b/core/include/kernel/tee_common_otp.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
-#ifndef TEE_COMMON_OTP_H
-#define TEE_COMMON_OTP_H
+#ifndef __KERNEL_TEE_COMMON_OTP_H
+#define __KERNEL_TEE_COMMON_OTP_H
 
 #include <stddef.h>
 #include <stdint.h>
@@ -20,4 +20,4 @@ int tee_otp_get_die_id(uint8_t *buffer, size_t len);
 TEE_Result tee_otp_get_ta_enc_key(uint32_t key_type, uint8_t *buffer,
 				  size_t len);
 
-#endif /* TEE_COMMON_OTP_H */
+#endif /* __KERNEL_TEE_COMMON_OTP_H */
diff --git a/core/include/kernel/tee_misc.h b/core/include/kernel/tee_misc.h
index 035acd37f6b38765637ee318635d708410b94fa8..66552520247c37924103a478c9513bfaa06a1c11 100644
--- a/core/include/kernel/tee_misc.h
+++ b/core/include/kernel/tee_misc.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
-#ifndef TEE_MISC_H
-#define TEE_MISC_H
+#ifndef __KERNEL_TEE_MISC_H
+#define __KERNEL_TEE_MISC_H
 
 #include <types_ext.h>
 
@@ -68,4 +68,4 @@ bool core_is_buffer_intersect(paddr_t b, paddr_size_t bl,
  */
 void *alloc_cache_aligned(size_t size);
 
-#endif /* TEE_MISC_H */
+#endif /* __KERNEL_TEE_MISC_H */
diff --git a/core/include/kernel/tee_ta_manager.h b/core/include/kernel/tee_ta_manager.h
index ef689b5205406592d53fb8f48c2a95eff5d5afb6..8cae35002e19df258cd6613860dfeb5e688703ca 100644
--- a/core/include/kernel/tee_ta_manager.h
+++ b/core/include/kernel/tee_ta_manager.h
@@ -5,8 +5,8 @@
  * Copyright (c) 2020, Arm Limited
  */
 
-#ifndef TEE_TA_MANAGER_H
-#define TEE_TA_MANAGER_H
+#ifndef __KERNEL_TEE_TA_MANAGER_H
+#define __KERNEL_TEE_TA_MANAGER_H
 
 #include <assert.h>
 #include <kernel/mutex.h>
diff --git a/core/include/kernel/tee_time.h b/core/include/kernel/tee_time.h
index 396155104725c52c151fdad126121dd5faf550c2..28b41545c4e5dcdddb7801ed75c9d25a34f8555f 100644
--- a/core/include/kernel/tee_time.h
+++ b/core/include/kernel/tee_time.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
-#ifndef TEE_TIME_H
-#define TEE_TIME_H
+#ifndef __KERNEL_TEE_TIME_H
+#define __KERNEL_TEE_TIME_H
 
 #include "tee_api_types.h"
 
diff --git a/core/include/kernel/thread.h b/core/include/kernel/thread.h
index 022aeec58f09b85ba08dfd75e97cd38fd1602687..b7f497e1091188582bb56493eaa1077831e25ab5 100644
--- a/core/include/kernel/thread.h
+++ b/core/include/kernel/thread.h
@@ -5,8 +5,8 @@
  * Copyright (c) 2020-2021, Arm Limited
  */
 
-#ifndef KERNEL_THREAD_H
-#define KERNEL_THREAD_H
+#ifndef __KERNEL_THREAD_H
+#define __KERNEL_THREAD_H
 
 #ifndef __ASSEMBLER__
 #include <types_ext.h>
@@ -396,4 +396,4 @@ void *thread_rpc_shm_cache_alloc(enum thread_shm_cache_user user,
 
 #endif /*__ASSEMBLER__*/
 
-#endif /*KERNEL_THREAD_H*/
+#endif /*__KERNEL_THREAD_H*/
diff --git a/core/include/kernel/time_source.h b/core/include/kernel/time_source.h
index fce5391a0ff8e0ef55ab71f97c9bb09c278bf9bc..e02f98432a320f2012315ac6ab9ea7d2838f0ef2 100644
--- a/core/include/kernel/time_source.h
+++ b/core/include/kernel/time_source.h
@@ -2,6 +2,8 @@
 /*
  * Copyright (c) 2014, Linaro Limited
  */
+#ifndef __KERNEL_TIME_SOURCE_H
+#define __KERNEL_TIME_SOURCE_H
 
 #include <kernel/tee_time.h>
 
@@ -18,3 +20,4 @@ void time_source_init(void);
 	}
 
 extern struct time_source _time_source;
+#endif /*__KERNEL_TIME_SOURCE_H*/
diff --git a/core/include/kernel/timer.h b/core/include/kernel/timer.h
index 8aaca449a6d7777d803798f7ec9a033974f7f0d7..19abd115bd376a91dbd9620fc0f1b91b787cbb49 100644
--- a/core/include/kernel/timer.h
+++ b/core/include/kernel/timer.h
@@ -3,8 +3,8 @@
  * Copyright (C) 2018, Linaro Limited
  */
 
-#ifndef __TIMER_H
-#define __TIMER_H
+#ifndef __KERNEL_TIMER_H
+#define __KERNEL_TIMER_H
 
 void generic_timer_start(uint32_t time_ms);
 void generic_timer_stop(void);
@@ -12,4 +12,4 @@ void generic_timer_stop(void);
 /* Handler for timer expiry interrupt */
 void generic_timer_handler(uint32_t time_ms);
 
-#endif /* __TIMER_H */
+#endif /* __KERNEL_TIMER_H */
diff --git a/core/include/kernel/trace_ta.h b/core/include/kernel/trace_ta.h
index 44644e660bd6946ac9a656d85d6187b000fa215c..96ced9f375f18cb6651a7f48940fc6bafb43e379 100644
--- a/core/include/kernel/trace_ta.h
+++ b/core/include/kernel/trace_ta.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2014, Linaro Limited
  */
-#ifndef TRACE_TA_H
-#define TRACE_TA_H
+#ifndef __KERNEL_TRACE_TA_H
+#define __KERNEL_TRACE_TA_H
 
 #include <trace.h>
 
@@ -16,5 +16,5 @@
 #define TAMSG_RAW(...)
 #endif
 
-#endif /*TRACE_TA_H*/
+#endif /*__KERNEL_TRACE_TA_H*/
 
diff --git a/core/include/kernel/transfer_list.h b/core/include/kernel/transfer_list.h
new file mode 100644
index 0000000000000000000000000000000000000000..ed813979f289ede1a78218a25c2fa10eb463b374
--- /dev/null
+++ b/core/include/kernel/transfer_list.h
@@ -0,0 +1,157 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#ifndef __KERNEL_TRANSFER_LIST_H
+#define __KERNEL_TRANSFER_LIST_H
+
+#define TRANSFER_LIST_SIGNATURE		U(0x4a0fb10b)
+#define TRANSFER_LIST_VERSION		U(0x0001)
+
+/*
+ * Init value of maximum alignment required by any transfer entry data in the TL
+ * specified as a power of two
+ */
+#define TRANSFER_LIST_INIT_MAX_ALIGN	U(3)
+
+/* Alignment required by transfer entry header start address, in bytes */
+#define TRANSFER_LIST_GRANULE		U(8)
+
+/*
+ * Version of the register convention used.
+ * Set to 1 for both AArch64 and AArch32 according to fw handoff spec v0.9
+ */
+#define REG_CONVENTION_VER_MASK BIT(24)
+
+#define TL_FLAGS_HAS_CHECKSUM BIT(0)
+
+/* Transfer list operation codes */
+#define TL_OPS_NONE	U(0) /* invalid for any operation */
+#define TL_OPS_ALL	U(1) /* valid for all operations */
+#define TL_OPS_RO	U(2) /* valid for read only */
+#define TL_OPS_CUS	U(3) /* either abort or special code to interpret */
+
+#ifndef __ASSEMBLER__
+
+#include <types_ext.h>
+
+/* Get alignment from a value specified as power of two */
+#define TL_ALIGNMENT_FROM_ORDER(a) BIT(a)
+
+enum transfer_list_tag_id {
+	TL_TAG_EMPTY = 0,
+	TL_TAG_FDT = 1,
+	TL_TAG_HOB_BLOCK = 2,
+	TL_TAG_HOB_LIST = 3,
+	TL_TAG_ACPI_TABLE_AGGREGATE = 4,
+	TL_TAG_OPTEE_PAGABLE_PART = 0x100,
+};
+
+struct transfer_list_header {
+	uint32_t signature;
+	uint8_t checksum;
+	uint8_t version;
+	uint8_t hdr_size;
+	uint8_t alignment;	/* max alignment of transfer entry data */
+	uint32_t size;		/* TL header + all transfer entries */
+	uint32_t max_size;
+	uint32_t flags;
+	uint32_t reserved;	/* spare bytes */
+	/*
+	 * Commented out element used to visualize dynamic part of the
+	 * data structure.
+	 *
+	 * Note that struct transfer_list_entry also is dynamic in size
+	 * so the elements can't be indexed directly but instead must be
+	 * traversed in order
+	 *
+	 * struct transfer_list_entry entries[];
+	 */
+};
+
+struct transfer_list_entry {
+	uint16_t tag_id;
+	uint8_t reserved0;	/* place holder for tag ID 3rd byte (MSB) */
+	uint8_t hdr_size;
+	uint32_t data_size;
+	/*
+	 * Commented out element used to visualize dynamic part of the
+	 * data structure.
+	 *
+	 * Note that padding is added at the end of @data to make it reach
+	 * a 8-byte boundary.
+	 *
+	 * uint8_t	data[ROUNDUP(data_size, 8)];
+	 */
+};
+
+struct transfer_list_header *transfer_list_map(paddr_t pa);
+void transfer_list_unmap_sync(struct transfer_list_header *tl);
+void transfer_list_unmap_nosync(struct transfer_list_header *tl);
+
+void transfer_list_dump(struct transfer_list_header *tl);
+struct transfer_list_header *transfer_list_init(paddr_t pa, size_t max_size);
+
+struct transfer_list_header *
+transfer_list_relocate(struct transfer_list_header *tl, paddr_t pa,
+		       size_t max_size);
+
+#if defined(CFG_TRANSFER_LIST)
+
+int transfer_list_check_header(const struct transfer_list_header *tl);
+
+struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl,
+					       uint16_t tag_id);
+
+void *transfer_list_entry_data(struct transfer_list_entry *tl_e);
+
+#else /* CFG_TRANSFER_LIST */
+
+static inline int
+transfer_list_check_header(const struct transfer_list_header *tl __unused)
+{
+	return TL_OPS_NONE;
+}
+
+static inline struct transfer_list_entry *
+transfer_list_find(struct transfer_list_header *tl __unused,
+		   uint16_t tag_id __unused)
+{
+	return NULL;
+}
+
+static inline void *
+transfer_list_entry_data(struct transfer_list_entry *tl_e __unused)
+{
+	return NULL;
+}
+
+#endif /* CFG_TRANSFER_LIST */
+
+void transfer_list_update_checksum(struct transfer_list_header *tl);
+bool transfer_list_verify_checksum(const struct transfer_list_header *tl);
+
+bool transfer_list_set_data_size(struct transfer_list_header *tl,
+				 struct transfer_list_entry *tl_e,
+				 uint32_t new_data_size);
+
+bool transfer_list_rem(struct transfer_list_header *tl,
+		       struct transfer_list_entry *tl_e);
+
+struct transfer_list_entry *transfer_list_add(struct transfer_list_header *tl,
+					      uint16_t tag_id,
+					      uint32_t data_size,
+					      const void *data);
+
+struct transfer_list_entry *
+transfer_list_add_with_align(struct transfer_list_header *tl, uint16_t tag_id,
+			     uint32_t data_size, const void *data,
+			     uint8_t alignment);
+
+struct transfer_list_entry *
+transfer_list_next(struct transfer_list_header *tl,
+		   struct transfer_list_entry *last);
+
+#endif /*__ASSEMBLER__*/
+#endif /*__TRANSFER_LIST_H*/
diff --git a/core/include/kernel/unwind.h b/core/include/kernel/unwind.h
index 9a01b4613c8781afe00c9881e5dcf1a7dd07ab7b..8ecf3435940676af4f07874ef846c875ee3c7aa1 100644
--- a/core/include/kernel/unwind.h
+++ b/core/include/kernel/unwind.h
@@ -4,8 +4,8 @@
  * Copyright (c) 2020, Huawei Technologies Co., Ltd
  */
 
-#ifndef KERNEL_UNWIND
-#define KERNEL_UNWIND
+#ifndef __KERNEL_UNWIND
+#define __KERNEL_UNWIND
 
 #include <types_ext.h>
 
@@ -27,4 +27,4 @@ static inline void *unw_get_kernel_stack(void)
 }
 #endif /* CFG_UNWIND  */
 
-#endif /*KERNEL_UNWIND*/
+#endif /*__KERNEL_UNWIND*/
diff --git a/core/include/kernel/user_ta.h b/core/include/kernel/user_ta.h
index 942c948f6704527942d54b167e297a7f1aebbd24..667122b5c675a2d09eaa1f91c248e3bc3a5f54cd 100644
--- a/core/include/kernel/user_ta.h
+++ b/core/include/kernel/user_ta.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2015, Linaro Limited
  * Copyright (c) 2020, Arm Limited
  */
-#ifndef KERNEL_USER_TA_H
-#define KERNEL_USER_TA_H
+#ifndef __KERNEL_USER_TA_H
+#define __KERNEL_USER_TA_H
 
 #include <assert.h>
 #include <kernel/tee_ta_manager.h>
@@ -70,4 +70,4 @@ static inline TEE_Result tee_ta_init_user_ta_session(
 #endif
 
 
-#endif /*KERNEL_USER_TA_H*/
+#endif /*__KERNEL_USER_TA_H*/
diff --git a/core/include/kernel/virtualization.h b/core/include/kernel/virtualization.h
index c4a7f69fe7ed0c04f2744d2d15faa6442870fc9f..f14904e564d474e704356326a4fd29d49653c935 100644
--- a/core/include/kernel/virtualization.h
+++ b/core/include/kernel/virtualization.h
@@ -1,8 +1,8 @@
 /* SPDX-License-Identifier: BSD-2-Clause */
 /* Copyright (c) 2018, EPAM Systems. All rights reserved. */
 
-#ifndef KERNEL_VIRTUALIZATION_H
-#define KERNEL_VIRTUALIZATION_H
+#ifndef __KERNEL_VIRTUALIZATION_H
+#define __KERNEL_VIRTUALIZATION_H
 
 #include <mm/core_mmu.h>
 #include <stdbool.h>
@@ -135,4 +135,4 @@ static inline uint16_t virt_find_guest_by_cookie(uint64_t cookie __unused)
 { return 0; }
 #endif
 
-#endif	/* KERNEL_VIRTUALIZATION_H */
+#endif	/* __KERNEL_VIRTUALIZATION_H */
diff --git a/core/include/kernel/wait_queue.h b/core/include/kernel/wait_queue.h
index a13c02b6c65198c38c23a47b84191ee3dc9e2850..20691e7fee0d17a05e92b9f0ada54293226177a4 100644
--- a/core/include/kernel/wait_queue.h
+++ b/core/include/kernel/wait_queue.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2015, Linaro Limited
  */
-#ifndef KERNEL_WAIT_QUEUE_H
-#define KERNEL_WAIT_QUEUE_H
+#ifndef __KERNEL_WAIT_QUEUE_H
+#define __KERNEL_WAIT_QUEUE_H
 
 #include <types_ext.h>
 #include <sys/queue.h>
@@ -60,5 +60,5 @@ void wq_promote_condvar(struct wait_queue *wq, struct condvar *cv,
 			int lineno);
 bool wq_have_condvar(struct wait_queue *wq, struct condvar *cv);
 
-#endif /*KERNEL_WAIT_QUEUE_H*/
+#endif /*__KERNEL_WAIT_QUEUE_H*/
 
diff --git a/core/include/mm/core_memprot.h b/core/include/mm/core_memprot.h
index d809ad30593efecfe3b5f9bb1e27df9b7fd57d6b..428c827b270bbe9da0912829f2614381128c1df5 100644
--- a/core/include/mm/core_memprot.h
+++ b/core/include/mm/core_memprot.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2016, Linaro Limited
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
-#ifndef CORE_MEMPROT_H
-#define CORE_MEMPROT_H
+#ifndef __MM_CORE_MEMPROT_H
+#define __MM_CORE_MEMPROT_H
 
 #include <mm/core_mmu.h>
 #include <types_ext.h>
@@ -115,4 +115,4 @@ vaddr_t io_pa_or_va_secure(struct io_pa_va *p, size_t len);
 vaddr_t io_pa_or_va_nsec(struct io_pa_va *p, size_t len);
 vaddr_t io_pa_or_va(struct io_pa_va *p, size_t len);
 
-#endif /* CORE_MEMPROT_H */
+#endif /* __MM_CORE_MEMPROT_H */
diff --git a/core/include/mm/core_mmu.h b/core/include/mm/core_mmu.h
index c6f258631256e3a71d43c0299a2fc4e406e84c4d..b239c6fbf65b9f62f79f976054962be31efc4a47 100644
--- a/core/include/mm/core_mmu.h
+++ b/core/include/mm/core_mmu.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2016, Linaro Limited
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
-#ifndef CORE_MMU_H
-#define CORE_MMU_H
+#ifndef __MM_CORE_MMU_H
+#define __MM_CORE_MMU_H
 
 #ifndef __ASSEMBLER__
 #include <assert.h>
@@ -73,10 +73,12 @@
  * MEM_AREA_NEX_NSEC_SHM: nexus non-secure shared RAM between NSec and TEE.
  * MEM_AREA_RAM_NSEC: NonSecure RAM storing data
  * MEM_AREA_RAM_SEC:  Secure RAM storing some secrets
+ * MEM_AREA_ROM_SEC:  Secure read only memory storing some secrets
  * MEM_AREA_IO_NSEC:  NonSecure HW mapped registers
  * MEM_AREA_IO_SEC:   Secure HW mapped registers
  * MEM_AREA_EXT_DT:   Memory loads external device tree
  * MEM_AREA_MANIFEST_DT: Memory loads manifest device tree
+ * MEM_AREA_TRANSFER_LIST: Memory area mapped for Transfer List
  * MEM_AREA_RES_VASPACE: Reserved virtual memory space
  * MEM_AREA_SHM_VASPACE: Virtual memory space for dynamic shared memory buffers
  * MEM_AREA_TS_VASPACE: TS va space, only used with phys_to_virt()
@@ -102,10 +104,12 @@ enum teecore_memtypes {
 	MEM_AREA_NEX_NSEC_SHM,
 	MEM_AREA_RAM_NSEC,
 	MEM_AREA_RAM_SEC,
+	MEM_AREA_ROM_SEC,
 	MEM_AREA_IO_NSEC,
 	MEM_AREA_IO_SEC,
 	MEM_AREA_EXT_DT,
 	MEM_AREA_MANIFEST_DT,
+	MEM_AREA_TRANSFER_LIST,
 	MEM_AREA_RES_VASPACE,
 	MEM_AREA_SHM_VASPACE,
 	MEM_AREA_TS_VASPACE,
@@ -136,10 +140,12 @@ static inline const char *teecore_memtype_name(enum teecore_memtypes type)
 		[MEM_AREA_NEX_NSEC_SHM] = "NEX_NSEC_SHM",
 		[MEM_AREA_RAM_NSEC] = "RAM_NSEC",
 		[MEM_AREA_RAM_SEC] = "RAM_SEC",
+		[MEM_AREA_ROM_SEC] = "ROM_SEC",
 		[MEM_AREA_IO_NSEC] = "IO_NSEC",
 		[MEM_AREA_IO_SEC] = "IO_SEC",
 		[MEM_AREA_EXT_DT] = "EXT_DT",
 		[MEM_AREA_MANIFEST_DT] = "MANIFEST_DT",
+		[MEM_AREA_TRANSFER_LIST] = "TRANSFER_LIST",
 		[MEM_AREA_RES_VASPACE] = "RES_VASPACE",
 		[MEM_AREA_SHM_VASPACE] = "SHM_VASPACE",
 		[MEM_AREA_TS_VASPACE] = "TS_VASPACE",
@@ -689,4 +695,4 @@ void core_mmu_get_ta_range(paddr_t *base, size_t *size);
 
 #endif /*__ASSEMBLER__*/
 
-#endif /* CORE_MMU_H */
+#endif /* __MM_CORE_MMU_H */
diff --git a/core/include/mm/pgt_cache.h b/core/include/mm/pgt_cache.h
index 13cd9b2104ea2b4807e19965e4120fe402e9f24b..4f3e37e26c81974881de7494c8627d4f00344629 100644
--- a/core/include/mm/pgt_cache.h
+++ b/core/include/mm/pgt_cache.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2016, Linaro Limited
  */
-#ifndef MM_PGT_CACHE_H
-#define MM_PGT_CACHE_H
+#ifndef __MM_PGT_CACHE_H
+#define __MM_PGT_CACHE_H
 
 #ifdef CFG_WITH_LPAE
 #define PGT_SIZE	(4 * 1024)
@@ -136,4 +136,4 @@ static inline void pgt_set_used_entries(struct pgt *pgt __unused,
 
 #endif
 
-#endif /*MM_PGT_CACHE_H*/
+#endif /*__MM_PGT_CACHE_H*/
diff --git a/core/include/mm/tee_mm.h b/core/include/mm/tee_mm.h
index 481f583754d0098d0708cbaa15ef7b979e91e45c..aae35f8717acc6b13f856f34367f21d838fe562d 100644
--- a/core/include/mm/tee_mm.h
+++ b/core/include/mm/tee_mm.h
@@ -3,10 +3,11 @@
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
-#ifndef TEE_MM_H
-#define TEE_MM_H
+#ifndef __MM_TEE_MM_H
+#define __MM_TEE_MM_H
 
 #include <malloc.h>
+#include <pta_stats.h>
 #include <types_ext.h>
 
 /* Define to indicate default pool initiation */
@@ -112,7 +113,7 @@ bool tee_mm_addr_is_within_range(const tee_mm_pool_t *pool, paddr_t addr);
 bool tee_mm_is_empty(tee_mm_pool_t *pool);
 
 #ifdef CFG_WITH_STATS
-void tee_mm_get_pool_stats(tee_mm_pool_t *pool, struct malloc_stats *stats,
+void tee_mm_get_pool_stats(tee_mm_pool_t *pool, struct pta_stats_alloc *stats,
 			   bool reset);
 #endif
 
diff --git a/core/include/mm/tee_mmu_types.h b/core/include/mm/tee_mmu_types.h
index e643d27f44227e737fe6d3b572f9325dedf512cd..2f495910f0eceb20c134459e20e948f3cfefc780 100644
--- a/core/include/mm/tee_mmu_types.h
+++ b/core/include/mm/tee_mmu_types.h
@@ -4,8 +4,8 @@
  * Copyright (c) 2021, Linaro Limited
  * Copyright (c) 2022, Arm Limited.
  */
-#ifndef TEE_MMU_TYPES_H
-#define TEE_MMU_TYPES_H
+#ifndef __MM_TEE_MMU_TYPES_H
+#define __MM_TEE_MMU_TYPES_H
 
 #include <stdint.h>
 #include <sys/queue.h>
diff --git a/core/include/mm/tee_pager.h b/core/include/mm/tee_pager.h
index 4e42e64eb5e7de02f18e8ad9a33594216b716db6..3c5b63017470000ea7627d8061bd79ec9f5f385d 100644
--- a/core/include/mm/tee_pager.h
+++ b/core/include/mm/tee_pager.h
@@ -4,8 +4,8 @@
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
-#ifndef MM_TEE_PAGER_H
-#define MM_TEE_PAGER_H
+#ifndef __MM_TEE_PAGER_H
+#define __MM_TEE_PAGER_H
 
 #include <kernel/abort.h>
 #include <kernel/panic.h>
diff --git a/core/include/mm/vm.h b/core/include/mm/vm.h
index f1509ba5d8a6712fcbcf052b69aa4b1541d4c296..16bafe8f0043f475ffc526c594fc07e6778d1c11 100644
--- a/core/include/mm/vm.h
+++ b/core/include/mm/vm.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
-#ifndef TEE_MMU_H
-#define TEE_MMU_H
+#ifndef __MM_VM_H
+#define __MM_VM_H
 
 #include <tee_api_types.h>
 #include <kernel/tee_ta_manager.h>
@@ -97,4 +97,4 @@ void vm_set_ctx(struct ts_ctx *ctx);
 
 struct mobj *vm_get_mobj(struct user_mode_ctx *uctx, vaddr_t va, size_t *len,
 			 uint16_t *prot, size_t *offs);
-#endif /*TEE_MMU_H*/
+#endif /*__MM_VM_H*/
diff --git a/core/include/optee_msg.h b/core/include/optee_msg.h
index 7cc795d746e04dce3c1492bcf09d79acf67e5137..5fa626b0eb6a77186330c3f70712fde4bb426b54 100644
--- a/core/include/optee_msg.h
+++ b/core/include/optee_msg.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2015-2020, Linaro Limited
  */
-#ifndef _OPTEE_MSG_H
-#define _OPTEE_MSG_H
+#ifndef __OPTEE_MSG_H
+#define __OPTEE_MSG_H
 
 #include <compiler.h>
 #include <types_ext.h>
@@ -342,4 +342,4 @@ struct optee_msg_arg {
 #define OPTEE_MSG_CMD_STOP_ASYNC_NOTIF	U(7)
 #define OPTEE_MSG_FUNCID_CALL_WITH_ARG	U(0x0004)
 
-#endif /* _OPTEE_MSG_H */
+#endif /* __OPTEE_MSG_H */
diff --git a/core/include/signed_hdr.h b/core/include/signed_hdr.h
index edeb446cc233fe418e3a36d3671a8e32d30e5476..0aacd8feea294ac5b9c3ae6d13286c411504c5ac 100644
--- a/core/include/signed_hdr.h
+++ b/core/include/signed_hdr.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2015, Linaro Limited
  */
-#ifndef SIGNED_HDR_H
-#define SIGNED_HDR_H
+#ifndef __SIGNED_HDR_H
+#define __SIGNED_HDR_H
 
 #include <inttypes.h>
 #include <stdlib.h>
@@ -225,4 +225,4 @@ TEE_Result shdr_verify_signature2(struct shdr_pub_key *key,
  */
 TEE_Result shdr_verify_signature(const struct shdr *shdr);
 
-#endif /*SIGNED_HDR_H*/
+#endif /*__SIGNED_HDR_H*/
diff --git a/core/include/ta_pub_key.h b/core/include/ta_pub_key.h
index 1259e014d6060496d9ed41e61e4776711eab4569..dc02a6f17f7e4a1f8cf067021e5dde1192b1fe9e 100644
--- a/core/include/ta_pub_key.h
+++ b/core/include/ta_pub_key.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2015, Linaro Limited
  */
-#ifndef KERNEL_TA_PUB_KEY_H
-#define KERNEL_TA_PUB_KEY_H
+#ifndef __TA_PUB_KEY_H
+#define __TA_PUB_KEY_H
 
 #include <types_ext.h>
 
@@ -11,5 +11,5 @@ extern const uint32_t ta_pub_key_exponent;
 extern const uint8_t ta_pub_key_modulus[];
 extern const size_t ta_pub_key_modulus_size;
 
-#endif /*KERNEL_TA_PUB_KEY_H*/
+#endif /*__TA_PUB_KEY_H*/
 
diff --git a/core/include/tee/cache.h b/core/include/tee/cache.h
index 568b2515ed7dbca9ee47e1f2819f91b5d75771d2..cb412104e66e448124aa69574ffb6de6e2059c03 100644
--- a/core/include/tee/cache.h
+++ b/core/include/tee/cache.h
@@ -2,11 +2,11 @@
 /*
  * Copyright (c) 2015, Linaro Limited
  */
-#ifndef TEE_CACHE_H
-#define TEE_CACHE_H
+#ifndef __TEE_CACHE_H
+#define __TEE_CACHE_H
 
 #include <utee_types.h>
 
 TEE_Result cache_operation(enum utee_cache_operation op, void *va, size_t len);
 
-#endif /* TEE_CACHE_H */
+#endif /* __TEE_CACHE_H */
diff --git a/core/include/tee/entry_std.h b/core/include/tee/entry_std.h
index d228badeba6167e893ece6d74ca6dee35c9d1492..d9ddb6200a949e81f957e393d79f5799e21f7a58 100644
--- a/core/include/tee/entry_std.h
+++ b/core/include/tee/entry_std.h
@@ -4,8 +4,8 @@
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
-#ifndef TEE_ENTRY_STD_H
-#define TEE_ENTRY_STD_H
+#ifndef __TEE_ENTRY_STD_H
+#define __TEE_ENTRY_STD_H
 
 #include <kernel/thread.h>
 #include <optee_msg.h>
@@ -23,4 +23,4 @@ TEE_Result __tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params);
 /* Get list head for sessions opened from non-secure */
 void nsec_sessions_list_head(struct tee_ta_session_head **open_sessions);
 
-#endif /* TEE_ENTRY_STD_H */
+#endif /* __TEE_ENTRY_STD_H */
diff --git a/core/include/tee/svc_cache.h b/core/include/tee/svc_cache.h
index a2bccde371c570f7f12243c780ef33e67ac2a09b..56321edd912c884473a5e11331f081f745316966 100644
--- a/core/include/tee/svc_cache.h
+++ b/core/include/tee/svc_cache.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2015, Linaro Limited
  */
-#ifndef SVC_CACHE_H
-#define SVC_CACHE_H
+#ifndef __TEE_SVC_CACHE_H
+#define __TEE_SVC_CACHE_H
 
 #include <types_ext.h>
 #include <tee_api_types.h>
@@ -14,4 +14,4 @@ TEE_Result syscall_cache_operation(void *va, size_t len, unsigned long op);
 #define  syscall_cache_operation syscall_not_supported
 #endif
 
-#endif /*SVC_CACHE_H*/
+#endif /*__TEE_SVC_CACHE_H*/
diff --git a/core/include/tee/tee_cryp_concat_kdf.h b/core/include/tee/tee_cryp_concat_kdf.h
index 49d3348f5b4628301365e42914d71aee8cfcb39f..dbcca313531f58f92346b19b0a4f3e286419064d 100644
--- a/core/include/tee/tee_cryp_concat_kdf.h
+++ b/core/include/tee/tee_cryp_concat_kdf.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2014, Linaro Limited
  */
 
-#ifndef TEE_CRYP_CONCAT_KDF_H
-#define TEE_CRYP_CONCAT_KDF_H
+#ifndef __TEE_TEE_CRYP_CONCAT_KDF_H
+#define __TEE_TEE_CRYP_CONCAT_KDF_H
 
 #include <tee_api_types.h>
 
@@ -14,4 +14,4 @@ TEE_Result tee_cryp_concat_kdf(uint32_t hash_id, const uint8_t *shared_secret,
 			       size_t other_info_len, uint8_t *derived_key,
 			       size_t derived_key_len);
 
-#endif /* TEE_CRYP_CONCAT_KDF_H */
+#endif /* __TEE_TEE_CRYP_CONCAT_KDF_H */
diff --git a/core/include/tee/tee_cryp_hkdf.h b/core/include/tee/tee_cryp_hkdf.h
index be0703e42080d1038c0f1742f00e8209badaf7f8..adce9d893057335dd11d42dbdd6ebf958d6d518d 100644
--- a/core/include/tee/tee_cryp_hkdf.h
+++ b/core/include/tee/tee_cryp_hkdf.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2014, Linaro Limited
  */
 
-#ifndef TEE_CRYP_HKDF_H
-#define TEE_CRYP_HKDF_H
+#ifndef __TEE_TEE_CRYP_HKDF_H
+#define __TEE_TEE_CRYP_HKDF_H
 
 #include <tee_api_types.h>
 
@@ -13,4 +13,4 @@ TEE_Result tee_cryp_hkdf(uint32_t hash_id, const uint8_t *ikm, size_t ikm_len,
 			 const uint8_t *info, size_t info_len, uint8_t *okm,
 			 size_t okm_len);
 
-#endif /* TEE_CRYP_HKDF_H */
+#endif /* __TEE_TEE_CRYP_HKDF_H */
diff --git a/core/include/tee/tee_cryp_pbkdf2.h b/core/include/tee/tee_cryp_pbkdf2.h
index 81b7beb1af35c3b43dd707fc260fd449a2fe05e2..d141032647fcb19d17210e00c3b072b257ddcb32 100644
--- a/core/include/tee/tee_cryp_pbkdf2.h
+++ b/core/include/tee/tee_cryp_pbkdf2.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2014, Linaro Limited
  */
 
-#ifndef TEE_CRYP_PBKDF2_H
-#define TEE_CRYP_PBKDF2_H
+#ifndef __TEE_TEE_CRYP_PBKDF2_H
+#define __TEE_TEE_CRYP_PBKDF2_H
 
 #include <tee_api_types.h>
 
@@ -13,4 +13,4 @@ TEE_Result tee_cryp_pbkdf2(uint32_t hash_id, const uint8_t *password,
 			   size_t salt_len, uint32_t iteration_count,
 			   uint8_t *derived_key, size_t derived_key_len);
 
-#endif /* TEE_CRYP_PBKDF2_H */
+#endif /* __TEE_TEE_CRYP_PBKDF2_H */
diff --git a/core/include/tee/tee_cryp_utl.h b/core/include/tee/tee_cryp_utl.h
index 98a694a0510ef319c9fac5595ea8187783aace42..7259cc3d6e93ef8fe55f6ac4ad18b2a631d09508 100644
--- a/core/include/tee/tee_cryp_utl.h
+++ b/core/include/tee/tee_cryp_utl.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2014, Linaro Limited
  */
 
-#ifndef TEE_CRYP_UTL_H
-#define TEE_CRYP_UTL_H
+#ifndef __TEE_TEE_CRYP_UTL_H
+#define __TEE_TEE_CRYP_UTL_H
 
 #include <tee_api_types.h>
 #include <crypto/crypto.h>
diff --git a/core/include/tee/tee_fs.h b/core/include/tee/tee_fs.h
index 1b632d7ad4b0d80f1eb47bbce5f67839bcbb9af4..fce494c6bea3571b71d9bf6a71e5a192c00996cb 100644
--- a/core/include/tee/tee_fs.h
+++ b/core/include/tee/tee_fs.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
-#ifndef TEE_FS_H
-#define TEE_FS_H
+#ifndef __TEE_TEE_FS_H
+#define __TEE_TEE_FS_H
 
 #include <stddef.h>
 #include <stdint.h>
@@ -99,4 +99,4 @@ tee_svc_storage_file_ops(uint32_t storage_id)
 	}
 }
 
-#endif /*TEE_FS_H*/
+#endif /*__TEE_TEE_FS_H*/
diff --git a/core/include/tee/tee_fs_key_manager.h b/core/include/tee/tee_fs_key_manager.h
index ac5763043556d5d20e7c2df409e695f23affacfd..736dedf55e484fc18bf4d011de15e614d827c288 100644
--- a/core/include/tee/tee_fs_key_manager.h
+++ b/core/include/tee/tee_fs_key_manager.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2015, Linaro Limited
  */
 
-#ifndef TEE_FS_KEY_MANAGER_H
-#define TEE_FS_KEY_MANAGER_H
+#ifndef __TEE_TEE_FS_KEY_MANAGER_H
+#define __TEE_TEE_FS_KEY_MANAGER_H
 
 #include <tee_api_types.h>
 #include <utee_defines.h>
diff --git a/core/include/tee/tee_fs_rpc.h b/core/include/tee/tee_fs_rpc.h
index ae49682c9ca7e3a5752f14d1ff80ccf260634683..88132952c2072d6d8dcfca27b08240b07384209a 100644
--- a/core/include/tee/tee_fs_rpc.h
+++ b/core/include/tee/tee_fs_rpc.h
@@ -7,8 +7,8 @@
  * Interface with tee-supplicant for file operations
  */
 
-#ifndef TEE_FS_RPC_H
-#define TEE_FS_RPC_H
+#ifndef __TEE_TEE_FS_RPC_H
+#define __TEE_TEE_FS_RPC_H
 
 #include <stdbool.h>
 #include <stddef.h>
@@ -46,4 +46,4 @@ TEE_Result tee_fs_rpc_write_final(struct tee_fs_rpc_operation *op);
 TEE_Result tee_fs_rpc_truncate(uint32_t id, int fd, size_t len);
 TEE_Result tee_fs_rpc_remove_dfh(uint32_t id,
 				 const struct tee_fs_dirfile_fileh *dfh);
-#endif /* TEE_FS_RPC_H */
+#endif /* __TEE_TEE_FS_RPC_H */
diff --git a/core/include/tee/tee_obj.h b/core/include/tee/tee_obj.h
index adbe543157daf33148a29377af1c5f65ffab0ed5..1c23dc065c17b0a89b9fdc43f0da5a7d5769eaa4 100644
--- a/core/include/tee/tee_obj.h
+++ b/core/include/tee/tee_obj.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
-#ifndef TEE_OBJ_H
-#define TEE_OBJ_H
+#ifndef __TEE_TEE_OBJ_H
+#define __TEE_TEE_OBJ_H
 
 #include <kernel/tee_ta_manager.h>
 #include <sys/queue.h>
diff --git a/core/include/tee/tee_pobj.h b/core/include/tee/tee_pobj.h
index bd05da4edffa84b9bc8b6311325e7544ea9970aa..8fcd792acc76f675389fb9502beeebb31005a502 100644
--- a/core/include/tee/tee_pobj.h
+++ b/core/include/tee/tee_pobj.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
-#ifndef TEE_POBJ_H
-#define TEE_POBJ_H
+#ifndef __TEE_TEE_POBJ_H
+#define __TEE_TEE_POBJ_H
 
 #include <stdint.h>
 #include <sys/queue.h>
@@ -18,6 +18,7 @@ struct tee_pobj {
 	void *obj_id;
 	uint32_t obj_id_len;
 	uint32_t flags;
+	uint32_t obj_info_usage;
 	bool temporary;	/* can be changed while creating == true */
 	bool creating;	/* can only be changed with mutex held */
 	/* Filesystem handling this object */
@@ -43,4 +44,11 @@ TEE_Result tee_pobj_release(struct tee_pobj *obj);
 TEE_Result tee_pobj_rename(struct tee_pobj *obj, void *obj_id,
 			   uint32_t obj_id_len);
 
+/*
+ * Locks and unlocks a mutex intended to protect the obj_info_usage field
+ * in struct tee_pobj.
+ */
+void tee_pobj_lock_usage(struct tee_pobj *obj);
+void tee_pobj_unlock_usage(struct tee_pobj *obj);
+
 #endif
diff --git a/core/include/tee/tee_supp_plugin_rpc.h b/core/include/tee/tee_supp_plugin_rpc.h
index 2d725c9d0651963cb26f1fcceab61f06ddfb54bc..5e4688a2457ddab057cdc8ddf22ea4d2390f858a 100644
--- a/core/include/tee/tee_supp_plugin_rpc.h
+++ b/core/include/tee/tee_supp_plugin_rpc.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2020, Open Mobile Platform LLC
  */
 
-#ifndef TEE_SUPP_PLUGIN_RPC_H
-#define TEE_SUPP_PLUGIN_RPC_H
+#ifndef __TEE_TEE_SUPP_PLUGIN_RPC_H
+#define __TEE_TEE_SUPP_PLUGIN_RPC_H
 
 #include <stdint.h>
 #include <stdbool.h>
@@ -15,4 +15,4 @@ TEE_Result tee_invoke_supp_plugin_rpc(const TEE_UUID *uuid, uint32_t cmd,
 				      void *buf_user, size_t len,
 				      size_t *outlen);
 
-#endif /* TEE_SUPP_PLUGIN_RPC_H */
+#endif /* __TEE_TEE_SUPP_PLUGIN_RPC_H */
diff --git a/core/include/tee/tee_svc.h b/core/include/tee/tee_svc.h
index 27a04c05dd1b363ecf10c56f47943592ac81307b..7c1476567faef20c6a434e13f29a77c8a7c8651b 100644
--- a/core/include/tee/tee_svc.h
+++ b/core/include/tee/tee_svc.h
@@ -2,8 +2,8 @@
 /*
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
-#ifndef TEE_SVC_H
-#define TEE_SVC_H
+#ifndef __TEE_TEE_SVC_H
+#define __TEE_TEE_SVC_H
 
 #include <kernel/ts_manager.h>
 #include <stdint.h>
@@ -74,4 +74,4 @@ TEE_Result syscall_wait(unsigned long timeout);
 TEE_Result syscall_get_time(unsigned long cat, TEE_Time *time);
 TEE_Result syscall_set_ta_time(const TEE_Time *time);
 
-#endif /* TEE_SVC_H */
+#endif /* __TEE_TEE_SVC_H */
diff --git a/core/include/tee/tee_svc_cryp.h b/core/include/tee/tee_svc_cryp.h
index 3932cdf6aa7d84ce72d04b29afbf996602797abe..526d6e69842f244f50591e591d1e9e196511ec86 100644
--- a/core/include/tee/tee_svc_cryp.h
+++ b/core/include/tee/tee_svc_cryp.h
@@ -2,8 +2,8 @@
 /*
 * Copyright (c) 2014, STMicroelectronics International N.V.
 */
-#ifndef TEE_SVC_CRYP_H
-#define TEE_SVC_CRYP_H
+#ifndef __TEE_TEE_SVC_CRYP_H
+#define __TEE_TEE_SVC_CRYP_H
 
 #include <tee_api_types.h>
 #include <utee_types.h>
@@ -93,4 +93,4 @@ TEE_Result tee_obj_attr_from_binary(struct tee_obj *o, const void *data,
 				    size_t data_len);
 TEE_Result tee_obj_attr_copy_from(struct tee_obj *o, const struct tee_obj *src);
 
-#endif /* TEE_SVC_CRYP_H */
+#endif /* __TEE_TEE_SVC_CRYP_H */
diff --git a/core/include/tee/tee_svc_storage.h b/core/include/tee/tee_svc_storage.h
index c5d763ade40375917ad2c06c5e577f2ad11b850c..d30fce96ddf0bc14926b80dfe78f21ee79c7c7cd 100644
--- a/core/include/tee/tee_svc_storage.h
+++ b/core/include/tee/tee_svc_storage.h
@@ -1,14 +1,16 @@
 /* SPDX-License-Identifier: BSD-2-Clause */
 /*
  * Copyright (c) 2014, STMicroelectronics International N.V.
+ * Copyright (c) 2023, Linaro Limited
  */
 
-#ifndef TEE_SVC_STORAGE_H
-#define TEE_SVC_STORAGE_H
+#ifndef __TEE_TEE_SVC_STORAGE_H
+#define __TEE_TEE_SVC_STORAGE_H
 
-#include <tee_api_types.h>
 #include <kernel/tee_ta_manager.h>
+#include <tee_api_types.h>
 #include <tee/tee_fs.h>
+#include <tee/tee_obj.h>
 
 /*
  * Persistant Object Functions
@@ -58,7 +60,8 @@ TEE_Result syscall_storage_obj_seek(unsigned long obj, int32_t offset,
 				    unsigned long whence);
 
 void tee_svc_storage_close_all_enum(struct user_ta_ctx *utc);
+TEE_Result tee_svc_storage_write_usage(struct tee_obj *o, uint32_t usage);
 
 void tee_svc_storage_init(void);
 
-#endif /* TEE_SVC_STORAGE_H */
+#endif /* __TEE_TEE_SVC_STORAGE_H */
diff --git a/core/include/tee/tee_ta_enc_manager.h b/core/include/tee/tee_ta_enc_manager.h
index 5e1b2e5c98f8ec47a71a3e331ccf8c3e831901a1..e258679d37c71eb82209b611acd3dc053539c3fe 100644
--- a/core/include/tee/tee_ta_enc_manager.h
+++ b/core/include/tee/tee_ta_enc_manager.h
@@ -3,8 +3,8 @@
  * Copyright (c) 2019, Linaro Limited
  */
 
-#ifndef TEE_TA_ENC_MANAGER_H
-#define TEE_TA_ENC_MANAGER_H
+#ifndef __TEE_TEE_TA_ENC_MANAGER_H
+#define __TEE_TEE_TA_ENC_MANAGER_H
 
 #include <signed_hdr.h>
 #include <tee_api_types.h>
diff --git a/core/kernel/dt.c b/core/kernel/dt.c
index 299aba110175c2a7191b470453e4bf60632c03ab..722fabb7d2fd6b61f79f2c0ecb8c7e8ad07c0cb7 100644
--- a/core/kernel/dt.c
+++ b/core/kernel/dt.c
@@ -544,16 +544,16 @@ struct dt_descriptor *get_external_dt_desc(void)
 	return &external_dt;
 }
 
-void init_external_dt(unsigned long phys_dt)
+void init_external_dt(unsigned long phys_dt, size_t dt_sz)
 {
 	struct dt_descriptor *dt = &external_dt;
-	void *fdt = NULL;
 	int ret = 0;
+	enum teecore_memtypes mtype = MEM_AREA_MAXTYPE;
 
 	if (!IS_ENABLED(CFG_EXTERNAL_DT))
 		return;
 
-	if (!phys_dt) {
+	if (!phys_dt || !dt_sz) {
 		/*
 		 * No need to panic as we're not using the DT in OP-TEE
 		 * yet, we're only adding some nodes for normal world use.
@@ -566,20 +566,31 @@ void init_external_dt(unsigned long phys_dt)
 		return;
 	}
 
-	fdt = core_mmu_add_mapping(MEM_AREA_EXT_DT, phys_dt, CFG_DTB_MAX_SIZE);
-	if (!fdt)
-		panic("Failed to map external DTB");
-
-	dt->blob = fdt;
+	mtype = core_mmu_get_type_by_pa(phys_dt);
+	if (mtype == MEM_AREA_MAXTYPE) {
+		/* Map the DTB if it is not yet mapped */
+		dt->blob = core_mmu_add_mapping(MEM_AREA_EXT_DT, phys_dt,
+						dt_sz);
+		if (!dt->blob)
+			panic("Failed to map external DTB");
+	} else {
+		/* Get the DTB address if already mapped in a memory area */
+		dt->blob = phys_to_virt(phys_dt, mtype, dt_sz);
+		if (!dt->blob) {
+			EMSG("Failed to get a mapped external DTB for PA %#lx",
+			     phys_dt);
+			panic();
+		}
+	}
 
-	ret = init_dt_overlay(dt, CFG_DTB_MAX_SIZE);
+	ret = init_dt_overlay(dt, dt_sz);
 	if (ret < 0) {
 		EMSG("Device Tree Overlay init fail @ %#lx: error %d", phys_dt,
 		     ret);
 		panic();
 	}
 
-	ret = fdt_open_into(fdt, fdt, CFG_DTB_MAX_SIZE);
+	ret = fdt_open_into(dt->blob, dt->blob, dt_sz);
 	if (ret < 0) {
 		EMSG("Invalid Device Tree at %#lx: error %d", phys_dt, ret);
 		panic();
@@ -600,6 +611,7 @@ void *get_external_dt(void)
 static TEE_Result release_external_dt(void)
 {
 	int ret = 0;
+	paddr_t pa_dt = 0;
 
 	if (!IS_ENABLED(CFG_EXTERNAL_DT))
 		return TEE_SUCCESS;
@@ -607,6 +619,14 @@ static TEE_Result release_external_dt(void)
 	if (!external_dt.blob)
 		return TEE_SUCCESS;
 
+	pa_dt = virt_to_phys(external_dt.blob);
+	/*
+	 * Skip packing and un-mapping operations if the external DTB is mapped
+	 * in a different memory area
+	 */
+	if (core_mmu_get_type_by_pa(pa_dt) != MEM_AREA_EXT_DT)
+		return TEE_SUCCESS;
+
 	ret = fdt_pack(external_dt.blob);
 	if (ret < 0) {
 		EMSG("Failed to pack Device Tree at 0x%" PRIxPA ": error %d",
diff --git a/core/kernel/dt_driver.c b/core/kernel/dt_driver.c
index 256aefa9058f9f1a0cc7eeafd9930bd8002e1481..4597bf221a716139173525c271d894aac3818890 100644
--- a/core/kernel/dt_driver.c
+++ b/core/kernel/dt_driver.c
@@ -111,6 +111,7 @@ static void assert_type_is_valid(enum dt_driver_type type)
 	case DT_DRIVER_PINCTRL:
 	case DT_DRIVER_INTERRUPT:
 	case DT_DRIVER_REGULATOR:
+	case DT_DRIVER_NVMEM:
 		return;
 	default:
 		assert(0);
@@ -163,6 +164,7 @@ static bool dt_driver_use_parent_controller(enum dt_driver_type type)
 {
 	switch (type) {
 	case DT_DRIVER_PINCTRL:
+	case DT_DRIVER_NVMEM:
 		return true;
 	default:
 		return false;
@@ -249,7 +251,8 @@ dt_driver_get_provider_by_phandle(uint32_t phandle, enum dt_driver_type type)
 
 static TEE_Result device_from_provider_prop(struct dt_driver_provider *prv,
 					    const void *fdt, int phandle_node,
-					    const uint32_t *prop, void **device)
+					    const uint32_t *prop,
+					    void *device_ref)
 {
 	TEE_Result res = TEE_ERROR_GENERIC;
 	struct dt_pargs *pargs = NULL;
@@ -264,9 +267,9 @@ static TEE_Result device_from_provider_prop(struct dt_driver_provider *prv,
 	pargs->phandle_node = phandle_node;
 	pargs->args_count = prv->provider_cells;
 	for (n = 0; n < prv->provider_cells; n++)
-		pargs->args[n] = fdt32_to_cpu(prop[n + 1]);
+		pargs->args[n] = fdt32_to_cpu(prop[n]);
 
-	res = prv->get_of_device(pargs, prv->priv_data, device);
+	res = prv->get_of_device(pargs, prv->priv_data, device_ref);
 
 	free(pargs);
 
@@ -274,7 +277,8 @@ static TEE_Result device_from_provider_prop(struct dt_driver_provider *prv,
 }
 
 TEE_Result dt_driver_device_from_parent(const void *fdt, int nodeoffset,
-					enum dt_driver_type type, void **device)
+					enum dt_driver_type type,
+					void *device_ref)
 {
 	int parent = -1;
 	struct dt_driver_provider *prv = NULL;
@@ -291,7 +295,8 @@ TEE_Result dt_driver_device_from_parent(const void *fdt, int nodeoffset,
 		return TEE_ERROR_DEFER_DRIVER_INIT;
 	}
 
-	return device_from_provider_prop(prv, fdt, nodeoffset, NULL, device);
+	return device_from_provider_prop(prv, fdt, nodeoffset, NULL,
+					 device_ref);
 }
 
 TEE_Result dt_driver_device_from_node_idx_prop_phandle(const char *prop_name,
@@ -300,7 +305,7 @@ TEE_Result dt_driver_device_from_node_idx_prop_phandle(const char *prop_name,
 						       unsigned int prop_index,
 						       enum dt_driver_type type,
 						       uint32_t phandle,
-						       void **device)
+						       void *device_ref)
 {
 	int len = 0;
 	const uint32_t *prop = NULL;
@@ -328,14 +333,14 @@ TEE_Result dt_driver_device_from_node_idx_prop_phandle(const char *prop_name,
 		return TEE_ERROR_ITEM_NOT_FOUND;
 
 	return device_from_provider_prop(prv, fdt, phandle_node_unused,
-					 prop + prop_index, device);
+					 prop + prop_index, device_ref);
 }
 
 TEE_Result dt_driver_device_from_node_idx_prop(const char *prop_name,
 					       const void *fdt, int nodeoffset,
 					       unsigned int prop_idx,
 					       enum dt_driver_type type,
-					       void **device)
+					       void *device_ref)
 {
 	int len = 0;
 	int idx = 0;
@@ -380,23 +385,50 @@ TEE_Result dt_driver_device_from_node_idx_prop(const char *prop_name,
 				return TEE_ERROR_GENERIC;
 
 			prv = dt_driver_get_provider_by_node(nodeoffset, type);
-			if (!prv)
-				return TEE_ERROR_DEFER_DRIVER_INIT;
 		} else {
 			prv = dt_driver_get_provider_by_phandle(phandle, type);
-			if (!prv)
-				return TEE_ERROR_DEFER_DRIVER_INIT;
 		}
 
-		prv_cells = dt_driver_provider_cells(prv);
+		if (prv) {
+			prv_cells = dt_driver_provider_cells(prv);
+		} else if (prop_idx) {
+			/*
+			 * When we need to skip another provider phandle
+			 * arguments cells (aka when prop_idx != 0), we don't
+			 * really need the skipped provider to be already
+			 * registered, we can look straight in its DT node.
+			 */
+			phandle_node = fdt_node_offset_by_phandle(fdt, phandle);
+			if (phandle_node < 0) {
+				DMSG("Can't find node for phandle %"PRIu32,
+				     phandle);
+				return TEE_ERROR_GENERIC;
+			}
+
+			prv_cells = fdt_get_dt_driver_cells(fdt, phandle_node,
+							    type);
+			if (prv_cells < 0) {
+				DMSG("Can't find cells count on node %s: %d",
+				     fdt_get_name(fdt, phandle_node, NULL),
+				     prv_cells);
+				return TEE_ERROR_GENERIC;
+			}
+		}
+
 		if (prop_idx) {
 			prop_idx--;
 			idx += sizeof(phandle) + prv_cells * sizeof(uint32_t);
 			continue;
 		}
 
+		if (!prv)
+			return TEE_ERROR_DEFER_DRIVER_INIT;
+
+		/* Skip property cell with the phandle, already handled */
+		idx32++;
+
 		return device_from_provider_prop(prv, fdt, phandle_node,
-						 prop + idx32, device);
+						 prop + idx32, device_ref);
 	}
 
 	return TEE_ERROR_ITEM_NOT_FOUND;
@@ -654,7 +686,7 @@ static TEE_Result add_node_to_probe(const void *fdt, int node,
 	if (!elt)
 		return TEE_ERROR_OUT_OF_MEMORY;
 
-	DMSG("element: %s on node %s", node_name, drv_name);
+	DMSG("element: %s on node %s", drv_name, node_name);
 
 	memcpy(elt, &elt_new, sizeof(*elt));
 
diff --git a/core/kernel/interrupt.c b/core/kernel/interrupt.c
index 9fbc9b2b0099c6f8380352482ab6eb4772adb682..4fe92bd552322ab18f7b64fccfc2a6b78bf5c6de 100644
--- a/core/kernel/interrupt.c
+++ b/core/kernel/interrupt.c
@@ -46,6 +46,11 @@ struct itr_chip *interrupt_get_main_chip(void)
 	return itr_main_chip;
 }
 
+struct itr_chip *interrupt_get_main_chip_may_fail(void)
+{
+	return itr_main_chip;
+}
+
 #ifdef CFG_DT
 int dt_get_irq_type_prio(const void *fdt, int node, uint32_t *type,
 			 uint32_t *prio)
@@ -65,72 +70,6 @@ int dt_get_irq_type_prio(const void *fdt, int node, uint32_t *type,
 }
 #endif
 
-struct itr_handler *itr_alloc_add_type_prio(size_t it, itr_handler_t handler,
-					    uint32_t flags, void *data,
-					    uint32_t type, uint32_t prio)
-{
-	struct itr_handler *hdl = calloc(1, sizeof(*hdl));
-
-	if (hdl) {
-		hdl->it = it;
-		hdl->handler = handler;
-		hdl->flags = flags;
-		hdl->data = data;
-		itr_add_type_prio(hdl, type, prio);
-	}
-
-	return hdl;
-}
-
-void itr_free(struct itr_handler *hdl)
-{
-	if (!hdl)
-		return;
-
-	itr_main_chip->ops->disable(itr_main_chip, hdl->it);
-
-	SLIST_REMOVE(&itr_main_chip->handlers, hdl, itr_handler, link);
-	free(hdl);
-}
-
-void itr_add_type_prio(struct itr_handler *h, uint32_t type, uint32_t prio)
-{
-	struct itr_handler __maybe_unused *hdl = NULL;
-
-	SLIST_FOREACH(hdl, &itr_main_chip->handlers, link)
-		if (hdl->it == h->it)
-			assert((hdl->flags & ITRF_SHARED) &&
-			       (h->flags & ITRF_SHARED));
-
-	itr_main_chip->ops->add(itr_main_chip, h->it, type, prio);
-	SLIST_INSERT_HEAD(&itr_main_chip->handlers, h, link);
-}
-
-void itr_enable(size_t it)
-{
-	itr_main_chip->ops->enable(itr_main_chip, it);
-}
-
-void itr_disable(size_t it)
-{
-	itr_main_chip->ops->disable(itr_main_chip, it);
-}
-
-void itr_raise_pi(size_t it)
-{
-	itr_main_chip->ops->raise_pi(itr_main_chip, it);
-}
-
-void itr_raise_sgi(size_t it, uint8_t cpu_mask)
-{
-	itr_main_chip->ops->raise_sgi(itr_main_chip, it, cpu_mask);
-}
-
-void itr_set_affinity(size_t it, uint8_t cpu_mask)
-{
-	itr_main_chip->ops->set_affinity(itr_main_chip, it, cpu_mask);
-}
-
 /* This function is supposed to be overridden in platform specific code */
 void __weak __noreturn interrupt_main_handler(void)
 {
@@ -170,8 +109,9 @@ TEE_Result interrupt_configure(struct itr_chip *chip, size_t itr_num,
 	return TEE_SUCCESS;
 }
 
-TEE_Result interrupt_add_configure_handler(struct itr_handler *hdl,
-					   uint32_t type, uint32_t prio)
+static TEE_Result add_configure_handler(struct itr_handler *hdl,
+					uint32_t type, uint32_t prio,
+					bool configure)
 {
 	struct itr_handler *h = NULL;
 
@@ -188,13 +128,52 @@ TEE_Result interrupt_add_configure_handler(struct itr_handler *hdl,
 		}
 	}
 
-	interrupt_configure(hdl->chip, hdl->it, type, prio);
+	if (configure)
+		interrupt_configure(hdl->chip, hdl->it, type, prio);
 
 	SLIST_INSERT_HEAD(&hdl->chip->handlers, hdl, link);
 
 	return TEE_SUCCESS;
 }
 
+TEE_Result interrupt_add_configure_handler(struct itr_handler *hdl,
+					   uint32_t type, uint32_t prio)
+{
+	return add_configure_handler(hdl, type, prio, true /* configure */);
+}
+
+TEE_Result interrupt_create_handler(struct itr_chip *itr_chip, size_t itr_num,
+				    itr_handler_t callback, void *priv,
+				    uint32_t flags,
+				    struct itr_handler **out_hdl)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct itr_handler *itr_hdl = NULL;
+
+	itr_hdl = calloc(1, sizeof(*itr_hdl));
+	if (!itr_hdl)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	*itr_hdl = (struct itr_handler){
+		.chip = itr_chip,
+		.it = itr_num,
+		.flags = flags,
+		.handler = callback,
+		.data = priv,
+	};
+
+	res = add_configure_handler(itr_hdl, 0, 0, false /* configure */);
+	if (res) {
+		free(itr_hdl);
+		return res;
+	}
+
+	if (out_hdl)
+		*out_hdl = itr_hdl;
+
+	return TEE_SUCCESS;
+}
+
 void interrupt_remove_handler(struct itr_handler *hdl)
 {
 	struct itr_handler *h = NULL;
@@ -262,3 +241,112 @@ void interrupt_remove_free_handler(struct itr_handler *hdl)
 		free(hdl);
 	}
 }
+
+#ifdef CFG_DT
+TEE_Result interrupt_register_provider(const void *fdt, int node,
+				       itr_dt_get_func dt_get_itr, void *data)
+{
+	return dt_driver_register_provider(fdt, node,
+					   (get_of_device_func)dt_get_itr,
+					   data, DT_DRIVER_INTERRUPT);
+}
+
+/*
+ * Fills an itr_desc reference based on "interrupts" property bindings.
+ * May return TEE_ERROR_DEFER_DRIVER_INIT if parent controller is found but
+ * not yet initialized.
+ */
+static TEE_Result get_legacy_interrupt_by_index(const void *fdt, int node,
+						unsigned int index,
+						struct itr_desc *itr_desc)
+{
+	const uint32_t *prop = NULL;
+	uint32_t phandle = 0;
+	int pnode = 0;
+	int len = 0;
+
+	prop = fdt_getprop(fdt, node, "interrupts", &len);
+	if (!prop)
+		return TEE_ERROR_ITEM_NOT_FOUND;
+
+	/* Find "interrupt-parent" in node or its parents */
+	pnode = node;
+	prop = fdt_getprop(fdt, pnode, "interrupt-parent", &len);
+
+	while (!prop) {
+		pnode = fdt_parent_offset(fdt, pnode);
+		if (pnode < 0)
+			break;
+
+		prop = fdt_getprop(fdt, pnode, "interrupt-parent", &len);
+		if (!prop && len != -FDT_ERR_NOTFOUND)
+			break;
+	}
+	if (!prop) {
+		DMSG("No interrupt parent for node %s",
+		     fdt_get_name(fdt, node, NULL));
+		return TEE_ERROR_GENERIC;
+	}
+
+	/* "interrupt-parent" provides interrupt controller phandle */
+	phandle = fdt32_to_cpu(prop[0]);
+
+	/* Get interrupt chip/number from phandle and "interrupts" property */
+	return dt_driver_device_from_node_idx_prop_phandle("interrupts", fdt,
+							   node, index,
+							   DT_DRIVER_INTERRUPT,
+							   phandle,
+							   itr_desc);
+}
+
+/*
+ * Fills an itr_desc based on "interrupts-extended" property bindings.
+ * May return TEE_ERROR_DEFER_DRIVER_INIT if parent controller is found
+ * but not yet initialized.
+ */
+static TEE_Result get_extended_interrupt_by_index(const void *fdt, int node,
+						  unsigned int index,
+						  struct itr_desc *itr_desc)
+{
+	return dt_driver_device_from_node_idx_prop("interrupts-extended",
+						   fdt, node, index,
+						   DT_DRIVER_INTERRUPT,
+						   itr_desc);
+}
+
+TEE_Result interrupt_dt_get_by_index(const void *fdt, int node,
+				     unsigned int index, struct itr_chip **chip,
+				     size_t *itr_num)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct itr_desc desc = { };
+
+	assert(chip && itr_num);
+
+	/* "interrupts-extended" takes precedence over "interrupts" */
+	if (fdt_getprop(fdt, node, "interrupts-extended", NULL))
+		res = get_extended_interrupt_by_index(fdt, node, index, &desc);
+	else
+		res = get_legacy_interrupt_by_index(fdt, node, index, &desc);
+
+	if (!res) {
+		assert(desc.chip);
+		*chip = desc.chip;
+		*itr_num = desc.itr_num;
+	}
+
+	return res;
+}
+
+TEE_Result interrupt_dt_get_by_name(const void *fdt, int node, const char *name,
+				    struct itr_chip **chip, size_t *itr_num)
+{
+	int idx = 0;
+
+	idx = fdt_stringlist_search(fdt, node, "interrupt-names", name);
+	if (idx < 0)
+		return TEE_ERROR_GENERIC;
+
+	return interrupt_dt_get_by_index(fdt, node, idx, chip, itr_num);
+}
+#endif /*CFG_DT*/
diff --git a/core/kernel/notif.c b/core/kernel/notif.c
index 7ecc246fdf57f013299bb9e2faedcf6c1f12eaaa..d23b4fcd816b65ac471ade4da1575e716d5788ff 100644
--- a/core/kernel/notif.c
+++ b/core/kernel/notif.c
@@ -1,11 +1,8 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright (c) 2021, Linaro Limited
+ * Copyright (c) 2021-2023, Linaro Limited
  */
 
-#include <bitstring.h>
-#include <drivers/gic.h>
-#include <kernel/interrupt.h>
 #include <kernel/mutex.h>
 #include <kernel/notif.h>
 #include <kernel/spinlock.h>
@@ -16,95 +13,12 @@
 #if defined(CFG_CORE_ASYNC_NOTIF)
 static struct mutex notif_mutex = MUTEX_INITIALIZER;
 static unsigned int notif_lock = SPINLOCK_UNLOCK;
+static bool notif_started;
 
 SLIST_HEAD(notif_driver_head, notif_driver);
 static struct notif_driver_head notif_driver_head =
 	SLIST_HEAD_INITIALIZER(&notif_driver_head);
 
-static bitstr_t bit_decl(notif_values, NOTIF_ASYNC_VALUE_MAX + 1);
-static bitstr_t bit_decl(notif_alloc_values, NOTIF_ASYNC_VALUE_MAX + 1);
-static bool notif_started;
-
-TEE_Result notif_alloc_async_value(uint32_t *val)
-{
-	static bool alloc_values_inited;
-	uint32_t old_itr_status = 0;
-	int bit = 0;
-
-	old_itr_status = cpu_spin_lock_xsave(&notif_lock);
-
-	if (!alloc_values_inited) {
-		bit_set(notif_alloc_values, NOTIF_VALUE_DO_BOTTOM_HALF);
-		alloc_values_inited = true;
-	}
-
-	bit_ffc(notif_alloc_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit);
-	if (bit >= 0) {
-		*val = bit;
-		bit_set(notif_alloc_values, bit);
-	}
-
-	cpu_spin_unlock_xrestore(&notif_lock, old_itr_status);
-
-	if (bit < 0)
-		return TEE_ERROR_OUT_OF_MEMORY;
-
-	return TEE_SUCCESS;
-}
-
-void notif_free_async_value(uint32_t val)
-{
-	uint32_t old_itr_status = 0;
-
-	old_itr_status = cpu_spin_lock_xsave(&notif_lock);
-
-	assert(val < NOTIF_ASYNC_VALUE_MAX);
-	assert(bit_test(notif_alloc_values, val));
-	bit_clear(notif_alloc_values, val);
-
-	cpu_spin_unlock_xrestore(&notif_lock, old_itr_status);
-}
-
-uint32_t notif_get_value(bool *value_valid, bool *value_pending)
-{
-	uint32_t old_itr_status = 0;
-	uint32_t res = 0;
-	int bit = 0;
-
-	old_itr_status = cpu_spin_lock_xsave(&notif_lock);
-
-	bit_ffs(notif_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit);
-	*value_valid = (bit >= 0);
-	if (!*value_valid) {
-		*value_pending = false;
-		goto out;
-	}
-
-	res = bit;
-	bit_clear(notif_values, res);
-	bit_ffs(notif_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit);
-	*value_pending = (bit >= 0);
-out:
-	cpu_spin_unlock_xrestore(&notif_lock, old_itr_status);
-
-	return res;
-}
-
-void notif_send_async(uint32_t value)
-{
-	uint32_t old_itr_status = 0;
-
-	static_assert(CFG_CORE_ASYNC_NOTIF_GIC_INTID >= GIC_PPI_BASE);
-
-	assert(value <= NOTIF_ASYNC_VALUE_MAX);
-	old_itr_status = cpu_spin_lock_xsave(&notif_lock);
-
-	DMSG("0x%"PRIx32, value);
-	bit_set(notif_values, value);
-	itr_raise_pi(CFG_CORE_ASYNC_NOTIF_GIC_INTID);
-
-	cpu_spin_unlock_xrestore(&notif_lock, old_itr_status);
-}
 
 bool notif_async_is_started(void)
 {
diff --git a/core/kernel/notif_default.c b/core/kernel/notif_default.c
new file mode 100644
index 0000000000000000000000000000000000000000..85b156867d660116dd39736966bb634502ff1dbd
--- /dev/null
+++ b/core/kernel/notif_default.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2021-2023, Linaro Limited
+ */
+
+#include <assert.h>
+#include <bitstring.h>
+#include <kernel/interrupt.h>
+#include <kernel/notif.h>
+#include <kernel/spinlock.h>
+#include <trace.h>
+#include <types_ext.h>
+
+static bitstr_t bit_decl(notif_values, NOTIF_ASYNC_VALUE_MAX + 1);
+static bitstr_t bit_decl(notif_alloc_values, NOTIF_ASYNC_VALUE_MAX + 1);
+static unsigned int notif_default_lock = SPINLOCK_UNLOCK;
+
+TEE_Result notif_alloc_async_value(uint32_t *val)
+{
+	static bool alloc_values_inited;
+	uint32_t old_itr_status = 0;
+	int bit = 0;
+
+	assert(interrupt_can_raise_pi(interrupt_get_main_chip()));
+
+	old_itr_status = cpu_spin_lock_xsave(&notif_default_lock);
+
+	if (!alloc_values_inited) {
+		bit_set(notif_alloc_values, NOTIF_VALUE_DO_BOTTOM_HALF);
+		alloc_values_inited = true;
+	}
+
+	bit_ffc(notif_alloc_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit);
+	if (bit >= 0) {
+		*val = bit;
+		bit_set(notif_alloc_values, bit);
+	}
+
+	cpu_spin_unlock_xrestore(&notif_default_lock, old_itr_status);
+
+	if (bit < 0)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	return TEE_SUCCESS;
+}
+
+void notif_free_async_value(uint32_t val)
+{
+	uint32_t old_itr_status = 0;
+
+	old_itr_status = cpu_spin_lock_xsave(&notif_default_lock);
+
+	assert(val < NOTIF_ASYNC_VALUE_MAX);
+	assert(bit_test(notif_alloc_values, val));
+	bit_clear(notif_alloc_values, val);
+
+	cpu_spin_unlock_xrestore(&notif_default_lock, old_itr_status);
+}
+
+uint32_t notif_get_value(bool *value_valid, bool *value_pending)
+{
+	uint32_t old_itr_status = 0;
+	uint32_t res = 0;
+	int bit = 0;
+
+	old_itr_status = cpu_spin_lock_xsave(&notif_default_lock);
+
+	bit_ffs(notif_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit);
+	*value_valid = (bit >= 0);
+	if (!*value_valid) {
+		*value_pending = false;
+		goto out;
+	}
+
+	res = bit;
+	bit_clear(notif_values, res);
+	bit_ffs(notif_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit);
+	*value_pending = (bit >= 0);
+out:
+	cpu_spin_unlock_xrestore(&notif_default_lock, old_itr_status);
+
+	return res;
+}
+
+void notif_send_async(uint32_t value)
+{
+	uint32_t old_itr_status = 0;
+	struct itr_chip *itr_chip = interrupt_get_main_chip();
+
+	assert(value <= NOTIF_ASYNC_VALUE_MAX);
+	old_itr_status = cpu_spin_lock_xsave(&notif_default_lock);
+
+	DMSG("0x%"PRIx32, value);
+	bit_set(notif_values, value);
+	interrupt_raise_pi(itr_chip, CFG_CORE_ASYNC_NOTIF_GIC_INTID);
+
+	cpu_spin_unlock_xrestore(&notif_default_lock, old_itr_status);
+}
diff --git a/core/kernel/panic.c b/core/kernel/panic.c
index 18028fbfd3c7f47e8dfb5c45b3c80aca37693e95..9edef97d81b52cb76e179807f24d871c2a86e14d 100644
--- a/core/kernel/panic.c
+++ b/core/kernel/panic.c
@@ -4,11 +4,62 @@
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
+#include <initcall.h>
+#include <kernel/interrupt.h>
+#include <kernel/misc.h>
 #include <kernel/panic.h>
 #include <kernel/thread.h>
 #include <kernel/unwind.h>
 #include <trace.h>
 
+/* SGI number chosen to halt other cores must be in the secure SGI range */
+static_assert(!IS_ENABLED(CFG_HALT_CORES_ON_PANIC) ||
+	      (CFG_HALT_CORES_ON_PANIC_SGI >= 8 &&
+	       CFG_HALT_CORES_ON_PANIC_SGI < 16));
+
+static enum itr_return __noreturn
+multi_core_panic_it_handler(struct itr_handler *hdl __unused)
+{
+	IMSG("Halting CPU %zu", get_core_pos());
+
+	while (true)
+		cpu_idle();
+}
+
+static struct itr_handler multi_core_panic_handler = {
+	.it = CFG_HALT_CORES_ON_PANIC_SGI,
+	.handler = multi_core_panic_it_handler,
+};
+DECLARE_KEEP_PAGER(multi_core_panic_handler);
+
+static void notify_other_cores(void)
+{
+	struct itr_chip *chip = interrupt_get_main_chip_may_fail();
+
+	if (chip)
+		interrupt_raise_sgi(chip, CFG_HALT_CORES_ON_PANIC_SGI,
+				    ITR_CPU_MASK_TO_OTHER_CPUS);
+	else
+		EMSG("Can't notify other cores, main interrupt chip not set");
+}
+
+static TEE_Result init_multi_core_panic_handler(void)
+{
+	if (!IS_ENABLED(CFG_HALT_CORES_ON_PANIC) || CFG_TEE_CORE_NB_CORE == 1)
+		return TEE_SUCCESS;
+
+	if (interrupt_add_handler_with_chip(interrupt_get_main_chip(),
+					    &multi_core_panic_handler))
+		panic();
+
+	interrupt_enable(interrupt_get_main_chip(),
+			 multi_core_panic_handler.it);
+
+	return TEE_SUCCESS;
+}
+
+boot_final(init_multi_core_panic_handler);
+
 void __do_panic(const char *file __maybe_unused,
 		const int line __maybe_unused,
 		const char *func __maybe_unused,
@@ -17,8 +68,6 @@ void __do_panic(const char *file __maybe_unused,
 	/* disable prehemption */
 	(void)thread_mask_exceptions(THREAD_EXCP_ALL);
 
-	/* TODO: notify other cores */
-
 	/* trace: Panic ['panic-string-message' ]at FILE:LINE [<FUNCTION>]" */
 	if (!file && !func && !msg)
 		EMSG_RAW("Panic");
@@ -29,6 +78,10 @@ void __do_panic(const char *file __maybe_unused,
 			 func ? "<" : "", func ? func : "", func ? ">" : "");
 
 	print_kernel_stack();
+
+	if (IS_ENABLED(CFG_HALT_CORES_ON_PANIC) && CFG_TEE_CORE_NB_CORE > 1)
+		notify_other_cores();
+
 	/* abort current execution */
 	while (1)
 		cpu_idle();
diff --git a/core/kernel/sub.mk b/core/kernel/sub.mk
index 75d3368651425756755ab5bda7bcec12824a47db..3e81d5f8f124d914955d38e0d258cf71fac7a090 100644
--- a/core/kernel/sub.mk
+++ b/core/kernel/sub.mk
@@ -39,6 +39,7 @@ srcs-y += mutex.c
 srcs-$(CFG_LOCKDEP) += mutex_lockdep.c
 srcs-y += wait_queue.c
 srcs-y += notif.c
+srcs-$(_CFG_CORE_ASYNC_NOTIF_DEFAULT_IMPL) += notif_default.c
 srcs-y += thread.c
 
 ifeq ($(CFG_WITH_USER_TA),y)
@@ -51,6 +52,8 @@ endif
 srcs-$(CFG_EMBEDDED_TS) += embedded_ts.c
 srcs-y += pseudo_ta.c
 
+srcs-$(CFG_TRANSFER_LIST) += transfer_list.c
+
 ifeq ($(CFG_SYSCALL_FTRACE),y)
 # We would not like to profile spin_lock_debug.c file as it provides
 # common APIs that are needed for ftrace framework to trace syscalls.
diff --git a/core/kernel/tee_ta_manager.c b/core/kernel/tee_ta_manager.c
index 97dee430c30b247f91d7c0eec5e8b92e37ba6fcf..6117c3a01f5cb7105232653921975ee73afaa4f1 100644
--- a/core/kernel/tee_ta_manager.c
+++ b/core/kernel/tee_ta_manager.c
@@ -21,6 +21,7 @@
 #include <mm/core_mmu.h>
 #include <mm/mobj.h>
 #include <mm/vm.h>
+#include <pta_stats.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -37,12 +38,6 @@
 
 #if defined(CFG_TA_STATS)
 #define MAX_DUMP_SESS_NUM	(16)
-struct tee_ta_dump_stats {
-	TEE_UUID uuid;
-	uint32_t panicked;	/* True if TA has panicked */
-	uint32_t sess_num;	/* Number of opened session */
-	struct malloc_stats heap;
-};
 
 struct tee_ta_dump_ctx {
 	TEE_UUID uuid;
@@ -740,7 +735,7 @@ TEE_Result tee_ta_open_session(TEE_ErrorOrigin *err,
 	if (!res)
 		*sess = s;
 	else
-		EMSG("Failed. Return error 0x%x", res);
+		EMSG("Failed for TA %pUl. Return error %#"PRIx32, uuid, res);
 
 	return res;
 }
@@ -879,7 +874,7 @@ static void init_dump_ctx(struct tee_ta_dump_ctx *dump_ctx)
 }
 
 static TEE_Result dump_ta_stats(struct tee_ta_dump_ctx *dump_ctx,
-				struct tee_ta_dump_stats *dump_stats,
+				struct pta_stats_ta *dump_stats,
 				size_t ta_count)
 {
 	TEE_Result res = TEE_SUCCESS;
@@ -892,7 +887,7 @@ static TEE_Result dump_ta_stats(struct tee_ta_dump_ctx *dump_ctx,
 	nsec_sessions_list_head(&open_sessions);
 
 	for (i = 0; i < ta_count; i++) {
-		struct tee_ta_dump_stats *stats = &dump_stats[i];
+		struct pta_stats_ta *stats = &dump_stats[i];
 
 		memcpy(&stats->uuid, &dump_ctx[i].uuid,
 		       sizeof(dump_ctx[i].uuid));
@@ -932,7 +927,7 @@ static TEE_Result dump_ta_stats(struct tee_ta_dump_ctx *dump_ctx,
 TEE_Result tee_ta_instance_stats(void *buf, size_t *buf_size)
 {
 	TEE_Result res = TEE_SUCCESS;
-	struct tee_ta_dump_stats *dump_stats = NULL;
+	struct pta_stats_ta *dump_stats = NULL;
 	struct tee_ta_dump_ctx *dump_ctx = NULL;
 	struct tee_ta_ctx *ctx = NULL;
 	size_t sz = 0;
@@ -948,7 +943,7 @@ TEE_Result tee_ta_instance_stats(void *buf, size_t *buf_size)
 		if (is_user_ta_ctx(&ctx->ts_ctx))
 			ta_count++;
 
-	sz = sizeof(struct tee_ta_dump_stats) * ta_count;
+	sz = sizeof(struct pta_stats_ta) * ta_count;
 	if (!sz) {
 		/* sz = 0 means there is no UTA, return no item found. */
 		res = TEE_ERROR_ITEM_NOT_FOUND;
@@ -964,7 +959,7 @@ TEE_Result tee_ta_instance_stats(void *buf, size_t *buf_size)
 		DMSG("Data alignment");
 		res = TEE_ERROR_BAD_PARAMETERS;
 	} else {
-		dump_stats = (struct tee_ta_dump_stats *)buf;
+		dump_stats = (struct pta_stats_ta *)buf;
 		dump_ctx = malloc(sizeof(struct tee_ta_dump_ctx) * ta_count);
 		if (!dump_ctx)
 			res = TEE_ERROR_OUT_OF_MEMORY;
diff --git a/core/kernel/tpm.c b/core/kernel/tpm.c
index 4091a3ed60abc7cc24ec5179777042162efb9f5b..f9abf267e9e8d987452e939ec56b710eb8a34054 100644
--- a/core/kernel/tpm.c
+++ b/core/kernel/tpm.c
@@ -51,7 +51,7 @@ static int read_dt_tpm_log_info(void *fdt, int node, paddr_t *buf,
 		err = fdt_setprop(fdt, node, dt_tpm_event_log_addr, &zero_addr,
 				  sizeof(uint32_t) * 2);
 		if (err < 0) {
-			EMSG("Error setting property DTB to zero\n");
+			EMSG("Error setting property DTB to zero");
 			return err;
 		}
 	}
diff --git a/core/kernel/trace_ext.c b/core/kernel/trace_ext.c
index 6ed3bf94cce4f7995fc5989bf83699ac9d1e770b..007d6c30500ad1ab7cb90b946a833fc9a883ab6a 100644
--- a/core/kernel/trace_ext.c
+++ b/core/kernel/trace_ext.c
@@ -8,6 +8,7 @@
 #include <kernel/misc.h>
 #include <kernel/spinlock.h>
 #include <kernel/thread.h>
+#include <kernel/virtualization.h>
 #include <mm/core_mmu.h>
 
 const char trace_ext_prefix[] = "TC";
@@ -61,3 +62,8 @@ int trace_ext_get_core_id(void)
 	else
 		return -1;
 }
+
+int trace_ext_get_guest_id(void)
+{
+	return virt_get_current_guest_id();
+}
diff --git a/core/kernel/transfer_list.c b/core/kernel/transfer_list.c
new file mode 100644
index 0000000000000000000000000000000000000000..1be1b849cf91dd68782536f3b868e5fe71092598
--- /dev/null
+++ b/core/kernel/transfer_list.c
@@ -0,0 +1,591 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+/*******************************************************************************
+ * Transfer list library compliant with the Firmware Handoff specification at:
+ * https://github.com/FirmwareHandoff/firmware_handoff
+ ******************************************************************************/
+
+#include <kernel/cache_helpers.h>
+#include <kernel/panic.h>
+#include <kernel/transfer_list.h>
+#include <mm/core_memprot.h>
+#include <mm/core_mmu.h>
+#include <string.h>
+#include <util.h>
+
+/*******************************************************************************
+ * Adapt a physical address to match the maximum transfer entry data alignment
+ * required by an existing transfer list.
+ * Compliant with 2.4.6 of Firmware Handoff specification (v0.9).
+ * @pa: Physical address for adapting.
+ * @tl: Pointer to the existing transfer list.
+ * Return the adapted physical address.
+ ******************************************************************************/
+static paddr_t get_align_base_addr(paddr_t pa,
+				   struct transfer_list_header *tl)
+{
+	paddr_t align_mask = TL_ALIGNMENT_FROM_ORDER(tl->alignment) - 1;
+	paddr_t align_off = (paddr_t)tl & align_mask;
+	paddr_t new_addr = (pa & ~align_mask) + align_off;
+
+	if (new_addr < pa)
+		new_addr += TL_ALIGNMENT_FROM_ORDER(tl->alignment);
+
+	return new_addr;
+}
+
+static void unmap_list(struct transfer_list_header *tl, size_t sz)
+{
+	if (core_mmu_remove_mapping(MEM_AREA_TRANSFER_LIST, tl, sz))
+		panic("Failed to remove transfer list mapping");
+}
+
+struct transfer_list_header *transfer_list_map(paddr_t pa)
+{
+	struct transfer_list_header *tl = NULL;
+	size_t sz = SMALL_PAGE_SIZE;
+	size_t old_sz = 0;
+
+	while (true) {
+		tl = core_mmu_add_mapping(MEM_AREA_TRANSFER_LIST, pa, sz);
+		if (!tl) {
+			EMSG("Failed to map TL with PA %#"PRIxPA", size %#zx",
+			     pa, sz);
+			return NULL;
+		}
+		old_sz = sz;
+
+		if (transfer_list_check_header(tl) == TL_OPS_NONE) {
+			unmap_list(tl, sz);
+			return NULL;
+		}
+
+		if (tl->max_size <= sz)
+			return tl;
+
+		sz = ROUNDUP(tl->max_size, SMALL_PAGE_SIZE);
+		unmap_list(tl, old_sz);
+	}
+}
+
+void transfer_list_unmap_sync(struct transfer_list_header *tl)
+{
+	size_t sz = tl->max_size;
+
+	transfer_list_update_checksum(tl);
+	dcache_cleaninv_range(tl, sz);
+	unmap_list(tl, sz);
+}
+
+void transfer_list_unmap_nosync(struct transfer_list_header *tl)
+{
+	unmap_list(tl, tl->max_size);
+}
+
+void transfer_list_dump(struct transfer_list_header *tl)
+{
+	struct transfer_list_entry *tl_e = NULL;
+	int i __maybe_unused = 0;
+
+	if (!tl)
+		return;
+
+	DMSG("Dump transfer list:");
+	DMSG("signature  %#"PRIx32, tl->signature);
+	DMSG("checksum   %#"PRIx8, tl->checksum);
+	DMSG("version    %#"PRIx8, tl->version);
+	DMSG("hdr_size   %#"PRIx8, tl->hdr_size);
+	DMSG("alignment  %#"PRIx8, tl->alignment);
+	DMSG("size       %#"PRIx32, tl->size);
+	DMSG("max_size   %#"PRIx32, tl->max_size);
+	DMSG("flags      %#"PRIx32, tl->flags);
+	while (true) {
+		tl_e = transfer_list_next(tl, tl_e);
+		if (!tl_e)
+			break;
+
+		DMSG("Entry %d:", i++);
+		DMSG("tag_id     %#"PRIx16, tl_e->tag_id);
+		DMSG("hdr_size   %#"PRIx8, tl_e->hdr_size);
+		DMSG("data_size  %#"PRIx32, tl_e->data_size);
+		DMSG("data_addr  %#"PRIxVA,
+		     (vaddr_t)transfer_list_entry_data(tl_e));
+	}
+}
+
+/*******************************************************************************
+ * Creating a transfer list in a specified reserved memory region.
+ * Compliant with 2.4.5 of Firmware Handoff specification (v0.9).
+ * @pa: Physical address for residing the new transfer list.
+ * @max_size: Maximum size of the new transfer list.
+ * Return pointer to the created transfer list or NULL on error.
+ ******************************************************************************/
+struct transfer_list_header *transfer_list_init(paddr_t pa, size_t max_size)
+{
+	struct transfer_list_header *tl = NULL;
+	int align = TL_ALIGNMENT_FROM_ORDER(TRANSFER_LIST_INIT_MAX_ALIGN);
+
+	if (!pa || !max_size)
+		return NULL;
+
+	if (!IS_ALIGNED(pa, align) || !IS_ALIGNED(max_size, align) ||
+	    max_size < sizeof(*tl))
+		return NULL;
+
+	tl = core_mmu_add_mapping(MEM_AREA_TRANSFER_LIST, pa, max_size);
+	if (!tl)
+		return NULL;
+
+	memset(tl, 0, max_size);
+	tl->signature = TRANSFER_LIST_SIGNATURE;
+	tl->version = TRANSFER_LIST_VERSION;
+	tl->hdr_size = sizeof(*tl);
+	tl->alignment = TRANSFER_LIST_INIT_MAX_ALIGN; /* initial max align */
+	tl->size = sizeof(*tl); /* initial size is the size of header */
+	tl->max_size = max_size;
+	tl->flags = TL_FLAGS_HAS_CHECKSUM;
+
+	transfer_list_update_checksum(tl);
+
+	return tl;
+}
+
+/*******************************************************************************
+ * Relocating a transfer list to a specified reserved memory region.
+ * Compliant with 2.4.6 of Firmware Handoff specification (v0.9).
+ * @tl: Pointer to the transfer list for relocating.
+ * @pa: Physical address for relocating the transfer list.
+ * @max_size: Maximum size of the transfer list after relocating
+ * Return pointer to the relocated transfer list or NULL on error.
+ ******************************************************************************/
+struct transfer_list_header *
+transfer_list_relocate(struct transfer_list_header *tl, paddr_t pa,
+		       size_t max_size)
+{
+	paddr_t new_addr = 0;
+	struct transfer_list_header *new_tl = NULL;
+	size_t new_max_size = 0;
+
+	if (!tl || !pa || !max_size)
+		return NULL;
+
+	new_addr = get_align_base_addr(pa, tl);
+	new_max_size = max_size - (new_addr - pa);
+
+	/* The new space is not sufficient for the TL */
+	if (tl->size > new_max_size)
+		return NULL;
+
+	new_tl = core_mmu_add_mapping(MEM_AREA_TRANSFER_LIST, new_addr,
+				      new_max_size);
+	if (!new_tl)
+		return NULL;
+
+	memmove(new_tl, tl, tl->size);
+	new_tl->max_size = new_max_size;
+
+	transfer_list_update_checksum(new_tl);
+	transfer_list_unmap_nosync(tl);
+
+	return new_tl;
+}
+
+/*******************************************************************************
+ * Verifying the header of a transfer list.
+ * Compliant with 2.4.1 of Firmware Handoff specification (v0.9).
+ * @tl: Pointer to the transfer list.
+ * Return transfer list operation status code.
+ ******************************************************************************/
+int transfer_list_check_header(const struct transfer_list_header *tl)
+{
+	if (!tl)
+		return TL_OPS_NONE;
+
+	if (tl->signature != TRANSFER_LIST_SIGNATURE) {
+		EMSG("Bad transfer list signature %#"PRIx32, tl->signature);
+		return TL_OPS_NONE;
+	}
+
+	if (!tl->max_size) {
+		EMSG("Bad transfer list max size %#"PRIx32, tl->max_size);
+		return TL_OPS_NONE;
+	}
+
+	if (tl->size > tl->max_size) {
+		EMSG("Bad transfer list size %#"PRIx32, tl->size);
+		return TL_OPS_NONE;
+	}
+
+	if (tl->hdr_size != sizeof(struct transfer_list_header)) {
+		EMSG("Bad transfer list header size %#"PRIx8, tl->hdr_size);
+		return TL_OPS_NONE;
+	}
+
+	if (!transfer_list_verify_checksum(tl)) {
+		EMSG("Bad transfer list checksum %#"PRIx8, tl->checksum);
+		return TL_OPS_NONE;
+	}
+
+	if (tl->version == 0) {
+		EMSG("Transfer list version is invalid");
+		return TL_OPS_NONE;
+	} else if (tl->version == TRANSFER_LIST_VERSION) {
+		DMSG("Transfer list version is valid for all operations");
+		return TL_OPS_ALL;
+	} else if (tl->version > TRANSFER_LIST_VERSION) {
+		DMSG("Transfer list version is valid for read-only");
+		return TL_OPS_RO;
+	}
+
+	DMSG("Old transfer list version is detected");
+	return TL_OPS_CUS;
+}
+
+/*******************************************************************************
+ * Enumerate the next transfer entry.
+ * @tl: Pointer to the transfer list.
+ * @cur: Pointer to the current transfer entry where we want to search for the
+ *       next one.
+ * Return pointer to the next transfer entry or NULL on error or if @cur is the
+ * last entry.
+ ******************************************************************************/
+struct transfer_list_entry *transfer_list_next(struct transfer_list_header *tl,
+					       struct transfer_list_entry *cur)
+{
+	struct transfer_list_entry *tl_e = NULL;
+	vaddr_t tl_ev = 0;
+	vaddr_t va = 0;
+	vaddr_t ev = 0;
+	size_t sz = 0;
+
+	if (!tl)
+		return NULL;
+
+	tl_ev = (vaddr_t)tl + tl->size;
+
+	if (cur) {
+		va = (vaddr_t)cur;
+		/* check if the total size overflow */
+		if (ADD_OVERFLOW(cur->hdr_size, cur->data_size, &sz))
+			return NULL;
+		/* roundup to the next entry */
+		if (ADD_OVERFLOW(va, sz, &va) ||
+		    ROUNDUP_OVERFLOW(va, TRANSFER_LIST_GRANULE, &va))
+			return NULL;
+	} else {
+		va = (vaddr_t)tl + tl->hdr_size;
+	}
+
+	tl_e = (struct transfer_list_entry *)va;
+
+	if (va + sizeof(*tl_e) > tl_ev || tl_e->hdr_size < sizeof(*tl_e) ||
+	    ADD_OVERFLOW(tl_e->hdr_size, tl_e->data_size, &sz) ||
+	    ADD_OVERFLOW(va, sz, &ev) || ev > tl_ev)
+		return NULL;
+
+	return tl_e;
+}
+
+/*******************************************************************************
+ * Calculate the byte sum (modulo 256) of a transfer list.
+ * @tl: Pointer to the transfer list.
+ * Return byte sum of the transfer list.
+ ******************************************************************************/
+static uint8_t calc_byte_sum(const struct transfer_list_header *tl)
+{
+	uint8_t *b = (uint8_t *)tl;
+	uint8_t cs = 0;
+	size_t n = 0;
+
+	for (n = 0; n < tl->size; n++)
+		cs += b[n];
+
+	return cs;
+}
+
+/*******************************************************************************
+ * Update the checksum of a transfer list.
+ * @tl: Pointer to the transfer list.
+ * Return updated checksum of the transfer list.
+ ******************************************************************************/
+void transfer_list_update_checksum(struct transfer_list_header *tl)
+{
+	uint8_t cs = 0;
+
+	if (!tl || !(tl->flags & TL_FLAGS_HAS_CHECKSUM))
+		return;
+
+	cs = calc_byte_sum(tl);
+	cs -= tl->checksum;
+	cs = 256 - cs;
+	tl->checksum = cs;
+	assert(transfer_list_verify_checksum(tl));
+}
+
+/*******************************************************************************
+ * Verify the checksum of a transfer list.
+ * @tl: Pointer to the transfer list.
+ * Return true if verified or false if not.
+ ******************************************************************************/
+bool transfer_list_verify_checksum(const struct transfer_list_header *tl)
+{
+	if (!tl)
+		return false;
+
+	if (!(tl->flags & TL_FLAGS_HAS_CHECKSUM))
+		return true;
+
+	return !calc_byte_sum(tl);
+}
+
+/*******************************************************************************
+ * Update the data size of a transfer entry.
+ * @tl: Pointer to the transfer list.
+ * @tl_e: Pointer to the transfer entry.
+ * @new_data_size: New data size of the transfer entry.
+ * Return true on success or false on error.
+ ******************************************************************************/
+bool transfer_list_set_data_size(struct transfer_list_header *tl,
+				 struct transfer_list_entry *tl_e,
+				 uint32_t new_data_size)
+{
+	vaddr_t tl_old_ev = 0;
+	vaddr_t new_ev = 0;
+	vaddr_t old_ev = 0;
+	vaddr_t r_new_ev = 0;
+	struct transfer_list_entry *dummy_te = NULL;
+	size_t gap = 0;
+	size_t mov_dis = 0;
+	size_t sz = 0;
+
+	if (!tl || !tl_e)
+		return false;
+
+	tl_old_ev = (vaddr_t)tl + tl->size;
+
+	/*
+	 * Calculate the old and new end of transfer entry
+	 * both must be roundup to align with TRANSFER_LIST_GRANULE
+	 */
+	if (ADD_OVERFLOW(tl_e->hdr_size, tl_e->data_size, &sz) ||
+	    ADD_OVERFLOW((vaddr_t)tl_e, sz, &old_ev) ||
+	    ROUNDUP_OVERFLOW(old_ev, TRANSFER_LIST_GRANULE, &old_ev))
+		return false;
+
+	if (ADD_OVERFLOW(tl_e->hdr_size, new_data_size, &sz) ||
+	    ADD_OVERFLOW((vaddr_t)tl_e, sz, &new_ev) ||
+	    ROUNDUP_OVERFLOW(new_ev, TRANSFER_LIST_GRANULE, &new_ev))
+		return false;
+
+	if (new_ev > old_ev) {
+		/*
+		 * Move distance should be rounded up to match the entry data
+		 * alignment.
+		 * Ensure that the increased size doesn't exceed the max size
+		 * of TL
+		 */
+		mov_dis = new_ev - old_ev;
+		if (ROUNDUP_OVERFLOW(mov_dis,
+				     TL_ALIGNMENT_FROM_ORDER(tl->alignment),
+				     &mov_dis) ||
+		    tl->size + mov_dis > tl->max_size) {
+			return false;
+		}
+		r_new_ev = old_ev + mov_dis;
+		tl->size += mov_dis;
+	} else {
+		/*
+		 * Move distance should be rounded down to match the entry data
+		 * alignment.
+		 */
+		mov_dis = ROUNDDOWN(old_ev - new_ev,
+				    TL_ALIGNMENT_FROM_ORDER(tl->alignment));
+		r_new_ev = old_ev - mov_dis;
+		tl->size -= mov_dis;
+	}
+	/* Move all following entries to fit in the expanded or shrunk space */
+	memmove((void *)r_new_ev, (void *)old_ev, tl_old_ev - old_ev);
+
+	/*
+	 * Fill the gap due to round up/down with a void entry if the size of
+	 * the gap is more than an entry header.
+	 */
+	gap = r_new_ev - new_ev;
+	if (gap >= sizeof(*dummy_te)) {
+		/* Create a dummy transfer entry to fill up the gap */
+		dummy_te = (struct transfer_list_entry *)new_ev;
+		dummy_te->tag_id = TL_TAG_EMPTY;
+		dummy_te->reserved0 = 0;
+		dummy_te->hdr_size = sizeof(*dummy_te);
+		dummy_te->data_size = gap - sizeof(*dummy_te);
+	}
+
+	tl_e->data_size = new_data_size;
+
+	transfer_list_update_checksum(tl);
+	return true;
+}
+
+/*******************************************************************************
+ * Remove a specified transfer entry from a transfer list.
+ * @tl: Pointer to the transfer list.
+ * @tl_e: Pointer to the transfer entry.
+ * Return true on success or false on error.
+ ******************************************************************************/
+bool transfer_list_rem(struct transfer_list_header *tl,
+		       struct transfer_list_entry *tl_e)
+{
+	if (!tl || !tl_e || (vaddr_t)tl_e > (vaddr_t)tl + tl->size)
+		return false;
+
+	tl_e->tag_id = TL_TAG_EMPTY;
+	tl_e->reserved0 = 0;
+	transfer_list_update_checksum(tl);
+	return true;
+}
+
+/*******************************************************************************
+ * Add a new transfer entry into a transfer list.
+ * Compliant with 2.4.3 of Firmware Handoff specification (v0.9).
+ * @tl: Pointer to the transfer list.
+ * @tag_id: Tag ID for the new transfer entry.
+ * @data_size: Data size of the new transfer entry.
+ * @data: Pointer to the data for the new transfer entry.
+ *        NULL to skip data copying.
+ * Return pointer to the added transfer entry or NULL on error.
+ ******************************************************************************/
+struct transfer_list_entry *transfer_list_add(struct transfer_list_header *tl,
+					      uint16_t tag_id,
+					      uint32_t data_size,
+					      const void *data)
+{
+	vaddr_t max_tl_ev = 0;
+	vaddr_t tl_ev = 0;
+	vaddr_t ev = 0;
+	struct transfer_list_entry *tl_e = NULL;
+	size_t sz = 0;
+
+	if (!tl)
+		return NULL;
+
+	max_tl_ev = (vaddr_t)tl + tl->max_size;
+	tl_ev = (vaddr_t)tl + tl->size;
+	ev = tl_ev;
+
+	/*
+	 * Skip the step 1 (optional step).
+	 * New transfer entry will be added into the tail
+	 */
+	if (ADD_OVERFLOW(sizeof(*tl_e), data_size, &sz) ||
+	    ADD_OVERFLOW(ev, sz, &ev) ||
+	    ROUNDUP_OVERFLOW(ev, TRANSFER_LIST_GRANULE, &ev) ||
+	    ev > max_tl_ev) {
+		return NULL;
+	}
+
+	tl_e = (struct transfer_list_entry *)tl_ev;
+	*tl_e = (struct transfer_list_entry){
+		.tag_id = tag_id,
+		.hdr_size = sizeof(*tl_e),
+		.data_size = data_size,
+	};
+
+	tl->size += ev - tl_ev;
+
+	if (data)
+		memmove(tl_e + tl_e->hdr_size, data, data_size);
+
+	transfer_list_update_checksum(tl);
+
+	return tl_e;
+}
+
+/*******************************************************************************
+ * Add a new transfer entry into a transfer list with specified new data
+ * alignment requirement.
+ * Compliant with 2.4.4 of Firmware Handoff specification (v0.9).
+ * @tl: Pointer to the transfer list.
+ * @tag_id: Tag ID for the new transfer entry.
+ * @data_size: Data size of the new transfer entry.
+ * @data: Pointer to the data for the new transfer entry.
+ * @alignment: New data alignment specified as a power of two.
+ * Return pointer to the added transfer entry or NULL on error.
+ ******************************************************************************/
+struct transfer_list_entry *
+transfer_list_add_with_align(struct transfer_list_header *tl, uint16_t tag_id,
+			     uint32_t data_size, const void *data,
+			     uint8_t alignment)
+{
+	struct transfer_list_entry *tl_e = NULL;
+	vaddr_t tl_ev = 0;
+	vaddr_t ev = 0;
+	vaddr_t new_tl_ev = 0;
+	size_t dummy_te_data_sz = 0;
+
+	if (!tl)
+		return NULL;
+
+	tl_ev = (vaddr_t)tl + tl->size;
+	ev = tl_ev + sizeof(struct transfer_list_entry);
+
+	if (!IS_ALIGNED(ev, TL_ALIGNMENT_FROM_ORDER(alignment))) {
+		/*
+		 * Transfer entry data address is not aligned to the new
+		 * alignment. Fill the gap with an empty transfer entry as a
+		 * placeholder before adding the desired transfer entry
+		 */
+		new_tl_ev = ROUNDUP(ev, TL_ALIGNMENT_FROM_ORDER(alignment)) -
+			    sizeof(struct transfer_list_entry);
+		assert(new_tl_ev - tl_ev > sizeof(struct transfer_list_entry));
+		dummy_te_data_sz = new_tl_ev - tl_ev -
+				   sizeof(struct transfer_list_entry);
+		if (!transfer_list_add(tl, TL_TAG_EMPTY, dummy_te_data_sz,
+				       NULL)) {
+			return NULL;
+		}
+	}
+
+	tl_e = transfer_list_add(tl, tag_id, data_size, data);
+
+	if (alignment > tl->alignment) {
+		tl->alignment = alignment;
+		transfer_list_update_checksum(tl);
+	}
+
+	return tl_e;
+}
+
+/*******************************************************************************
+ * Search for an existing transfer entry with the specified tag id from a
+ * transfer list.
+ * @tl: Pointer to the transfer list.
+ * @tag_id: Tag ID to match a transfer entry.
+ * Return pointer to the found transfer entry or NULL if not found.
+ ******************************************************************************/
+struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl,
+					       uint16_t tag_id)
+{
+	struct transfer_list_entry *tl_e = NULL;
+
+	do {
+		tl_e = transfer_list_next(tl, tl_e);
+	} while (tl_e && tl_e->tag_id != tag_id);
+
+	return tl_e;
+}
+
+/*******************************************************************************
+ * Retrieve the data pointer of a specified transfer entry.
+ * @tl_e: Pointer to the transfer entry.
+ * Return pointer to the transfer entry data or NULL on error.
+ ******************************************************************************/
+void *transfer_list_entry_data(struct transfer_list_entry *tl_e)
+{
+	if (!tl_e)
+		return NULL;
+
+	return (uint8_t *)tl_e + tl_e->hdr_size;
+}
diff --git a/core/kernel/user_access.c b/core/kernel/user_access.c
index 22b48fbb6b0259baa880139cb4899f45d810ba82..3f229f985713741530a3ac6309f1ca749c9b4bb1 100644
--- a/core/kernel/user_access.c
+++ b/core/kernel/user_access.c
@@ -310,7 +310,7 @@ uint32_t kaddr_to_uref(void *kaddr)
 
 		uref -= VCORE_START_VA;
 		assert(uref < (UINT32_MAX >> MEMTAG_TAG_WIDTH));
-		uref |= memtag_get_tag(kaddr) << uref_tag_shift;
+		uref |= (vaddr_t)memtag_get_tag(kaddr) << uref_tag_shift;
 		return uref;
 	}
 
diff --git a/core/mm/core_mmu.c b/core/mm/core_mmu.c
index 584ff78e0d607aa813d05201d89e914b872e294d..c894e3fc2fa81df0dd6ffde42b26be1f63c8b024 100644
--- a/core/mm/core_mmu.c
+++ b/core/mm/core_mmu.c
@@ -471,6 +471,7 @@ void core_mmu_set_discovered_nsec_ddr(struct core_mmu_phys_mem *start,
 			break;
 		case MEM_AREA_EXT_DT:
 		case MEM_AREA_MANIFEST_DT:
+		case MEM_AREA_RAM_NSEC:
 		case MEM_AREA_RES_VASPACE:
 		case MEM_AREA_SHM_VASPACE:
 		case MEM_AREA_TS_VASPACE:
@@ -596,7 +597,6 @@ static bool pbuf_is_sdp_mem(paddr_t pbuf __unused, size_t len __unused)
 
 /* Check special memories comply with registered memories */
 static void verify_special_mem_areas(struct tee_mmap_region *mem_map,
-				     size_t len,
 				     const struct core_mmu_phys_mem *start,
 				     const struct core_mmu_phys_mem *end,
 				     const char *area_name __maybe_unused)
@@ -604,7 +604,6 @@ static void verify_special_mem_areas(struct tee_mmap_region *mem_map,
 	const struct core_mmu_phys_mem *mem;
 	const struct core_mmu_phys_mem *mem2;
 	struct tee_mmap_region *mmap;
-	size_t n;
 
 	if (start == end) {
 		DMSG("No %s memory area defined", area_name);
@@ -632,7 +631,7 @@ static void verify_special_mem_areas(struct tee_mmap_region *mem_map,
 	 * This is called before reserved VA space is loaded in mem_map.
 	 */
 	for (mem = start; mem < end; mem++) {
-		for (mmap = mem_map, n = 0; n < len; mmap++, n++) {
+		for (mmap = mem_map; mmap->type != MEM_AREA_END; mmap++) {
 			if (core_is_buffer_intersect(mem->addr, mem->size,
 						     mmap->pa, mmap->size)) {
 				MSG_MEM_INSTERSECT(mem->addr, mem->size,
@@ -759,6 +758,8 @@ uint32_t core_mmu_type_to_attr(enum teecore_memtypes t)
 		return attr | TEE_MATTR_PRW | cached;
 	case MEM_AREA_MANIFEST_DT:
 		return attr | TEE_MATTR_SECURE | TEE_MATTR_PR | cached;
+	case MEM_AREA_TRANSFER_LIST:
+		return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | cached;
 	case MEM_AREA_EXT_DT:
 		/*
 		 * If CFG_MAP_EXT_DT_SECURE is enabled map the external device
@@ -778,6 +779,8 @@ uint32_t core_mmu_type_to_attr(enum teecore_memtypes t)
 	case MEM_AREA_RAM_SEC:
 	case MEM_AREA_SEC_RAM_OVERALL:
 		return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | cached;
+	case MEM_AREA_ROM_SEC:
+		return attr | TEE_MATTR_SECURE | TEE_MATTR_PR | cached;
 	case MEM_AREA_RES_VASPACE:
 	case MEM_AREA_SHM_VASPACE:
 		return 0;
@@ -1075,8 +1078,7 @@ static size_t collect_mem_ranges(struct tee_mmap_region *memory_map,
 	}
 
 	if (IS_ENABLED(CFG_SECURE_DATA_PATH))
-		verify_special_mem_areas(memory_map, num_elems,
-					 phys_sdp_mem_begin,
+		verify_special_mem_areas(memory_map, phys_sdp_mem_begin,
 					 phys_sdp_mem_end, "SDP");
 
 	add_va_space(memory_map, num_elems, MEM_AREA_RES_VASPACE,
@@ -1434,6 +1436,7 @@ static void check_mem_map(struct tee_mmap_region *map)
 		case MEM_AREA_IO_NSEC:
 		case MEM_AREA_EXT_DT:
 		case MEM_AREA_MANIFEST_DT:
+		case MEM_AREA_TRANSFER_LIST:
 		case MEM_AREA_RAM_SEC:
 		case MEM_AREA_RAM_NSEC:
 		case MEM_AREA_RES_VASPACE:
diff --git a/core/mm/tee_mm.c b/core/mm/tee_mm.c
index c61306d757f93de9d13a3d3ddaa4fb5b900a6a1d..95084ca1e448756d8f60670a0d4415fb86a6f2e3 100644
--- a/core/mm/tee_mm.c
+++ b/core/mm/tee_mm.c
@@ -8,6 +8,7 @@
 #include <kernel/tee_common.h>
 #include <mm/tee_mm.h>
 #include <mm/tee_pager.h>
+#include <pta_stats.h>
 #include <trace.h>
 #include <util.h>
 
@@ -104,7 +105,7 @@ static size_t tee_mm_stats_allocated(tee_mm_pool_t *pool)
 	return sz << pool->shift;
 }
 
-void tee_mm_get_pool_stats(tee_mm_pool_t *pool, struct malloc_stats *stats,
+void tee_mm_get_pool_stats(tee_mm_pool_t *pool, struct pta_stats_alloc *stats,
 			   bool reset)
 {
 	uint32_t exceptions;
diff --git a/core/pta/attestation.c b/core/pta/attestation.c
index ab5a3bcc14547d9344bae67debc0f33f984e9880..d8a41075875c73e9f111b8183b4d3d4d2dc3a915 100644
--- a/core/pta/attestation.c
+++ b/core/pta/attestation.c
@@ -228,8 +228,8 @@ static TEE_Result sec_storage_obj_read(TEE_UUID *uuid, uint32_t storage_id,
 	if (obj_id_len > TEE_OBJECT_ID_MAX_LEN)
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	res = tee_pobj_get(uuid, (void *)obj_id, obj_id_len, flags, false, fops,
-			   &po);
+	res = tee_pobj_get(uuid, (void *)obj_id, obj_id_len, flags,
+			   TEE_POBJ_USAGE_OPEN, fops, &po);
 	if (res)
 		return res;
 
@@ -272,8 +272,8 @@ static TEE_Result sec_storage_obj_write(TEE_UUID *uuid, uint32_t storage_id,
 	if (obj_id_len > TEE_OBJECT_ID_MAX_LEN)
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	res = tee_pobj_get(uuid, (void *)obj_id, obj_id_len, flags, false,
-			   fops, &po);
+	res = tee_pobj_get(uuid, (void *)obj_id, obj_id_len, flags,
+			   TEE_POBJ_USAGE_OPEN, fops, &po);
 	if (res)
 		return res;
 
diff --git a/core/pta/bcm/gpio.c b/core/pta/bcm/gpio.c
index 43ed935d60d11ab039f27ebac9a2c9282790e11f..f77f9230c8252879dc94dbec22ee8737d9c22550 100644
--- a/core/pta/bcm/gpio.c
+++ b/core/pta/bcm/gpio.c
@@ -181,7 +181,7 @@ static TEE_Result invoke_command(void *session_context __unused,
 		res = pta_gpio_get(param_types, params);
 		break;
 	default:
-		EMSG("cmd: %d Not supported %s\n", cmd_id, GPIO_TA_NAME);
+		EMSG("cmd: %d Not supported %s", cmd_id, GPIO_TA_NAME);
 		res = TEE_ERROR_NOT_SUPPORTED;
 		break;
 	}
diff --git a/core/pta/stats.c b/core/pta/stats.c
index 933d8e104b54197d85376c6979ac82d8e75c11be..966592f008af6fba00c09845a4c97fb41846de30 100644
--- a/core/pta/stats.c
+++ b/core/pta/stats.c
@@ -3,67 +3,33 @@
  * Copyright (c) 2015, Linaro Limited
  */
 #include <compiler.h>
+#include <drivers/clk.h>
+#include <drivers/regulator.h>
 #include <kernel/pseudo_ta.h>
 #include <kernel/tee_time.h>
 #include <malloc.h>
 #include <mm/tee_mm.h>
 #include <mm/tee_pager.h>
+#include <pta_stats.h>
 #include <stdio.h>
 #include <string.h>
 #include <string_ext.h>
+#include <tee_api_types.h>
 #include <trace.h>
 
-#define TA_NAME		"stats.ta"
-
-#define STATS_UUID \
-		{ 0xd96a5b40, 0xe2c7, 0xb1af, \
-			{ 0x87, 0x94, 0x10, 0x02, 0xa5, 0xd5, 0xc6, 0x1b } }
-
-#define STATS_CMD_PAGER_STATS		0
-#define STATS_CMD_ALLOC_STATS		1
-#define STATS_CMD_MEMLEAK_STATS		2
-/*
- * UTEE_ENTRY_FUNC_DUMP_MEMSTATS
- * [out]    memref[0]        Array of context information of loaded TAs
- *
- * Each cell of the TA information array contains:
- * TEE_UUID    TA UUID
- * uint32_t    Non zero if TA panicked, 0 otherwise
- * uint32_t    Number of sessions opened by the TA
- * uint32_t    Byte size currently allocated in TA heap
- * uint32_t    Max bytes allocated since last stats reset
- * uint32_t    TA heap pool byte size
- * uint32_t    Number of failed allocation requests
- * uint32_t    Biggest byte size which allocation failed
- * uint32_t    Biggest byte size which allocation succeeded
- */
-#define STATS_CMD_TA_STATS		3
-
-/*
- * STATS_CMD_GET_TIME - Get both REE time and TEE time
- *
- * [out]    value[0].a        REE time as seen by OP-TEE in seconds
- * [out]    value[0].b        REE time as seen by OP-TEE, milliseconds part
- * [out]    value[1].a        TEE system time in seconds
- * [out]    value[1].b        TEE system time, milliseconds part
- */
-#define STATS_CMD_GET_TIME		4
-
-#define STATS_NB_POOLS			4
-
 static TEE_Result get_alloc_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
 {
-	struct malloc_stats *stats;
-	uint32_t size_to_retrieve;
-	uint32_t pool_id;
-	uint32_t i;
+	struct pta_stats_alloc *stats = NULL;
+	uint32_t size_to_retrieve = 0;
+	uint32_t pool_id = 0;
+	uint32_t i = 0;
 
 	/*
 	 * p[0].value.a = pool id (from 0 to n)
 	 *   - 0 means all the pools to be retrieved
 	 *   - 1..n means pool id
 	 * p[0].value.b = 0 if no reset of the stats
-	 * p[1].memref.buffer = output buffer to struct malloc_stats
+	 * p[1].memref.buffer = output buffer to struct pta_stats_alloc
 	 */
 	if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
 			    TEE_PARAM_TYPE_MEMREF_OUTPUT,
@@ -76,8 +42,8 @@ static TEE_Result get_alloc_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
 	if (pool_id > STATS_NB_POOLS)
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	size_to_retrieve = sizeof(struct malloc_stats);
-	if (!pool_id)
+	size_to_retrieve = sizeof(struct pta_stats_alloc);
+	if (pool_id == ALLOC_ID_ALL)
 		size_to_retrieve *= STATS_NB_POOLS;
 
 	if (p[1].memref.size < size_to_retrieve) {
@@ -87,30 +53,30 @@ static TEE_Result get_alloc_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
 	p[1].memref.size = size_to_retrieve;
 	stats = p[1].memref.buffer;
 
-	for (i = 1; i <= STATS_NB_POOLS; i++) {
-		if ((pool_id) && (i != pool_id))
+	for (i = ALLOC_ID_HEAP; i <= STATS_NB_POOLS; i++) {
+		if (pool_id != ALLOC_ID_ALL && i != pool_id)
 			continue;
 
 		switch (i) {
-		case 1:
+		case ALLOC_ID_HEAP:
 			malloc_get_stats(stats);
 			strlcpy(stats->desc, "Heap", sizeof(stats->desc));
 			if (p[0].value.b)
 				malloc_reset_stats();
 			break;
 
-		case 2:
+		case ALLOC_ID_PUBLIC_DDR:
 			EMSG("public DDR not managed by secure side anymore");
 			break;
 
-		case 3:
+		case ALLOC_ID_TA_RAM:
 			tee_mm_get_pool_stats(&tee_mm_sec_ddr, stats,
 					      !!p[0].value.b);
 			strlcpy(stats->desc, "Secure DDR", sizeof(stats->desc));
 			break;
 
 #ifdef CFG_NS_VIRTUALIZATION
-		case 4:
+		case ALLOC_ID_NEXUS_HEAP:
 			nex_malloc_get_stats(stats);
 			strlcpy(stats->desc, "KHeap", sizeof(stats->desc));
 			if (p[0].value.b)
@@ -130,7 +96,7 @@ static TEE_Result get_alloc_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
 
 static TEE_Result get_pager_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
 {
-	struct tee_pager_stats stats;
+	struct tee_pager_stats stats = { };
 
 	if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
 			    TEE_PARAM_TYPE_VALUE_OUTPUT,
@@ -189,6 +155,7 @@ static TEE_Result get_user_ta_stats(uint32_t type,
 static TEE_Result get_system_time(uint32_t type,
 				  TEE_Param p[TEE_NUM_PARAMS])
 {
+	TEE_Result ret = TEE_ERROR_GENERIC;
 	TEE_Time ree_time = { };
 	TEE_Time tee_time = { };
 
@@ -198,8 +165,13 @@ static TEE_Result get_system_time(uint32_t type,
 			    TEE_PARAM_TYPE_NONE) != type)
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	tee_time_get_sys_time(&tee_time);
-	tee_time_get_ree_time(&ree_time);
+	ret = tee_time_get_sys_time(&tee_time);
+	if (ret)
+		return ret;
+
+	ret = tee_time_get_ree_time(&ree_time);
+	if (ret)
+		return ret;
 
 	p[0].value.a = ree_time.seconds;
 	p[0].value.b = ree_time.millis;
@@ -209,6 +181,28 @@ static TEE_Result get_system_time(uint32_t type,
 	return TEE_SUCCESS;
 }
 
+static TEE_Result print_driver_info(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
+{
+	if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+			    TEE_PARAM_TYPE_NONE,
+			    TEE_PARAM_TYPE_NONE,
+			    TEE_PARAM_TYPE_NONE) != type)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	switch (p[0].value.a) {
+	case STATS_DRIVER_TYPE_CLOCK:
+		clk_print_tree();
+		break;
+	case STATS_DRIVER_TYPE_REGULATOR:
+		regulator_print_tree();
+		break;
+	default:
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	return TEE_SUCCESS;
+}
+
 /*
  * Trusted Application Entry Points
  */
@@ -228,12 +222,14 @@ static TEE_Result invoke_command(void *psess __unused,
 		return get_user_ta_stats(ptypes, params);
 	case STATS_CMD_GET_TIME:
 		return get_system_time(ptypes, params);
+	case STATS_CMD_PRINT_DRIVER_INFO:
+		return print_driver_info(ptypes, params);
 	default:
 		break;
 	}
 	return TEE_ERROR_BAD_PARAMETERS;
 }
 
-pseudo_ta_register(.uuid = STATS_UUID, .name = TA_NAME,
+pseudo_ta_register(.uuid = STATS_UUID, .name = "stats.pta",
 		   .flags = PTA_DEFAULT_FLAGS,
 		   .invoke_command_entry_point = invoke_command);
diff --git a/core/pta/stm32mp/remoteproc_pta.c b/core/pta/stm32mp/remoteproc_pta.c
new file mode 100644
index 0000000000000000000000000000000000000000..b2eed7f257f8dc123f0cefc5b10f17f43f0f5ad3
--- /dev/null
+++ b/core/pta/stm32mp/remoteproc_pta.c
@@ -0,0 +1,356 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2023, STMicroelectronics - All Rights Reserved
+ */
+
+#include <crypto/crypto.h>
+#include <drivers/clk.h>
+#include <drivers/rstctrl.h>
+#include <drivers/stm32_remoteproc.h>
+#include <drivers/stm32mp_dt_bindings.h>
+#include <drivers/stm32mp1_rcc.h>
+#include <initcall.h>
+#include <kernel/pseudo_ta.h>
+#include <kernel/user_ta.h>
+#include <remoteproc_pta.h>
+#include <string.h>
+
+#include "rproc_pub_key.h"
+
+#define PTA_NAME	"remoteproc.pta"
+
+/*
+ * UUID of the remoteproc Trusted application authorized to communicate with
+ * the remoteproc pseudo TA. The UID should match the one defined in the
+ * ta_remoteproc.h header file.
+ */
+#define TA_REMOTEPROC_UUID \
+	{ 0x80a4c275, 0x0a47, 0x4905, \
+		{ 0x82, 0x85, 0x14, 0x86, 0xa9, 0x77, 0x1a, 0x08} }
+
+/*
+ * Firmware states
+ * REMOTEPROC_OFF: firmware is off
+ * REMOTEPROC_ON: firmware is running
+ */
+enum rproc_load_state {
+	REMOTEPROC_OFF = 0,
+	REMOTEPROC_ON,
+};
+
+/* Currently supporting a single remote processor instance */
+static enum rproc_load_state rproc_ta_state = REMOTEPROC_OFF;
+
+static TEE_Result rproc_pta_capabilities(uint32_t pt,
+					 TEE_Param params[TEE_NUM_PARAMS])
+{
+	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+						TEE_PARAM_TYPE_VALUE_OUTPUT,
+						TEE_PARAM_TYPE_VALUE_OUTPUT,
+						TEE_PARAM_TYPE_NONE);
+
+	if (pt != exp_pt)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (!stm32_rproc_get(params[0].value.a))
+		return TEE_ERROR_NOT_SUPPORTED;
+
+	/* Support only ELF format */
+	params[1].value.a = PTA_RPROC_HWCAP_FMT_ELF;
+
+	/*
+	 * Due to stm32mp1 pager, secure memory is too expensive. Support hash
+	 * protected image only, so that firmware image can be loaded from
+	 * non-secure memory.
+	 */
+	params[2].value.a = PTA_RPROC_HWCAP_PROT_HASH_TABLE;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result rproc_pta_load_segment(uint32_t pt,
+					 TEE_Param params[TEE_NUM_PARAMS])
+{
+	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+						TEE_PARAM_TYPE_MEMREF_INPUT,
+						TEE_PARAM_TYPE_VALUE_INPUT,
+						TEE_PARAM_TYPE_MEMREF_INPUT);
+	TEE_Result res = TEE_ERROR_GENERIC;
+	paddr_t pa = 0;
+	void *dst = NULL;
+	uint8_t *src = params[1].memref.buffer;
+	size_t size = params[1].memref.size;
+	uint8_t *hash = params[3].memref.buffer;
+	paddr_t da = (paddr_t)reg_pair_to_64(params[2].value.b,
+					     params[2].value.a);
+
+	if (pt != exp_pt)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (!hash || params[3].memref.size != TEE_SHA256_HASH_SIZE)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (rproc_ta_state != REMOTEPROC_OFF)
+		return TEE_ERROR_BAD_STATE;
+
+	/* Get the physical address in local context mapping */
+	res = stm32_rproc_da_to_pa(params[0].value.a, da, size, &pa);
+	if (res)
+		return res;
+
+	if (stm32_rproc_map(params[0].value.a, pa, size, &dst)) {
+		EMSG("Can't map region %#"PRIxPA" size %zu", pa, size);
+		return TEE_ERROR_GENERIC;
+	}
+
+	/* Copy the segment to the remote processor memory */
+	memcpy(dst, src, size);
+
+	/* Verify that loaded segment is valid */
+	res = hash_sha256_check(hash, dst, size);
+	if (res)
+		memset(dst, 0, size);
+
+	stm32_rproc_unmap(params[0].value.a, dst, size);
+
+	return res;
+}
+
+static TEE_Result rproc_pta_set_memory(uint32_t pt,
+				       TEE_Param params[TEE_NUM_PARAMS])
+{
+	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+						TEE_PARAM_TYPE_VALUE_INPUT,
+						TEE_PARAM_TYPE_VALUE_INPUT,
+						TEE_PARAM_TYPE_VALUE_INPUT);
+	TEE_Result res = TEE_ERROR_GENERIC;
+	paddr_t pa = 0;
+	void *dst = NULL;
+	paddr_t da = params[1].value.a;
+	size_t size = params[2].value.a;
+	uint8_t value = params[3].value.a && 0xFF;
+
+	if (pt != exp_pt)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (rproc_ta_state != REMOTEPROC_OFF)
+		return TEE_ERROR_BAD_STATE;
+
+	/* Get the physical address in CPU mapping */
+	res = stm32_rproc_da_to_pa(params[0].value.a, da, size, &pa);
+	if (res)
+		return res;
+
+	res = stm32_rproc_map(params[0].value.a, pa, size, &dst);
+	if (res) {
+		EMSG("Can't map region %#"PRIxPA" size %zu", pa, size);
+		return TEE_ERROR_GENERIC;
+	}
+
+	memset(dst, value, size);
+
+	return stm32_rproc_unmap(params[0].value.a, dst, size);
+}
+
+static TEE_Result rproc_pta_da_to_pa(uint32_t pt,
+				     TEE_Param params[TEE_NUM_PARAMS])
+{
+	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+						TEE_PARAM_TYPE_VALUE_INPUT,
+						TEE_PARAM_TYPE_VALUE_INPUT,
+						TEE_PARAM_TYPE_VALUE_OUTPUT);
+	TEE_Result res = TEE_ERROR_GENERIC;
+	paddr_t da = params[1].value.a;
+	size_t size = params[2].value.a;
+	paddr_t pa = 0;
+
+	DMSG("Conversion for address %#"PRIxPA" size %zu", da, size);
+
+	if (pt != exp_pt)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	/* Target address is expected 32bit, ensure 32bit MSB are zero */
+	if (params[1].value.b || params[2].value.b)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	res = stm32_rproc_da_to_pa(params[0].value.a, da, size, &pa);
+	if (res)
+		return res;
+
+	reg_pair_from_64((uint64_t)pa, &params[3].value.b, &params[3].value.a);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result rproc_pta_start(uint32_t pt,
+				  TEE_Param params[TEE_NUM_PARAMS])
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+						TEE_PARAM_TYPE_NONE,
+						TEE_PARAM_TYPE_NONE,
+						TEE_PARAM_TYPE_NONE);
+
+	if (pt != exp_pt)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (rproc_ta_state != REMOTEPROC_OFF)
+		return TEE_ERROR_BAD_STATE;
+
+	res = stm32_rproc_start(params[0].value.a);
+	if (res)
+		return res;
+
+	rproc_ta_state = REMOTEPROC_ON;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result rproc_pta_stop(uint32_t pt,
+				 TEE_Param params[TEE_NUM_PARAMS])
+{
+	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+						TEE_PARAM_TYPE_NONE,
+						TEE_PARAM_TYPE_NONE,
+						TEE_PARAM_TYPE_NONE);
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	if (pt != exp_pt)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (rproc_ta_state != REMOTEPROC_ON)
+		return TEE_ERROR_BAD_STATE;
+
+	res = stm32_rproc_stop(params[0].value.a);
+	if (res)
+		return res;
+
+	rproc_ta_state = REMOTEPROC_OFF;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result rproc_pta_verify_rsa_signature(TEE_Param *hash,
+						 TEE_Param *sig, uint32_t algo)
+{
+	struct rsa_public_key key = { };
+	TEE_Result res = TEE_ERROR_GENERIC;
+	uint32_t e = TEE_U32_TO_BIG_ENDIAN(rproc_pub_key_exponent);
+	size_t hash_size = (size_t)hash->memref.size;
+	size_t sig_size = (size_t)sig->memref.size;
+
+	res = crypto_acipher_alloc_rsa_public_key(&key, sig_size);
+	if (res)
+		return res;
+
+	res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key.e);
+	if (res)
+		goto out;
+
+	res = crypto_bignum_bin2bn(rproc_pub_key_modulus,
+				   rproc_pub_key_modulus_size, key.n);
+	if (res)
+		goto out;
+
+	res = crypto_acipher_rsassa_verify(algo, &key, hash_size,
+					   hash->memref.buffer, hash_size,
+					   sig->memref.buffer, sig_size);
+
+out:
+	crypto_acipher_free_rsa_public_key(&key);
+
+	return res;
+}
+
+static TEE_Result rproc_pta_verify_digest(uint32_t pt,
+					  TEE_Param params[TEE_NUM_PARAMS])
+{
+	struct rproc_pta_key_info *keyinfo = NULL;
+	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+						TEE_PARAM_TYPE_MEMREF_INPUT,
+						TEE_PARAM_TYPE_MEMREF_INPUT,
+						TEE_PARAM_TYPE_MEMREF_INPUT);
+
+	if (pt != exp_pt)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (!stm32_rproc_get(params[0].value.a))
+		return TEE_ERROR_NOT_SUPPORTED;
+
+	if (rproc_ta_state != REMOTEPROC_OFF)
+		return TEE_ERROR_BAD_STATE;
+
+	keyinfo = params[1].memref.buffer;
+
+	if (!keyinfo ||
+	    rproc_pta_keyinfo_size(keyinfo) != params[1].memref.size)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (keyinfo->algo != TEE_ALG_RSASSA_PKCS1_V1_5_SHA256)
+		return TEE_ERROR_NOT_SUPPORTED;
+
+	return rproc_pta_verify_rsa_signature(&params[2], &params[3],
+					      keyinfo->algo);
+}
+
+static TEE_Result rproc_pta_invoke_command(void *session __unused,
+					   uint32_t cmd_id,
+					   uint32_t param_types,
+					   TEE_Param params[TEE_NUM_PARAMS])
+{
+	switch (cmd_id) {
+	case PTA_RPROC_HW_CAPABILITIES:
+		return rproc_pta_capabilities(param_types, params);
+	case PTA_RPROC_LOAD_SEGMENT_SHA256:
+		return rproc_pta_load_segment(param_types, params);
+	case PTA_RPROC_SET_MEMORY:
+		return rproc_pta_set_memory(param_types, params);
+	case PTA_RPROC_FIRMWARE_START:
+		return rproc_pta_start(param_types, params);
+	case PTA_RPROC_FIRMWARE_STOP:
+		return rproc_pta_stop(param_types, params);
+	case PTA_RPROC_FIRMWARE_DA_TO_PA:
+		return rproc_pta_da_to_pa(param_types, params);
+	case PTA_RPROC_VERIFY_DIGEST:
+		return rproc_pta_verify_digest(param_types, params);
+	default:
+		return TEE_ERROR_NOT_IMPLEMENTED;
+	}
+}
+
+/*
+ * Pseudo Trusted Application entry points
+ */
+static TEE_Result rproc_pta_open_session(uint32_t pt,
+					 TEE_Param params[TEE_NUM_PARAMS],
+					 void **sess_ctx __unused)
+{
+	struct ts_session *s = ts_get_calling_session();
+	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+						TEE_PARAM_TYPE_NONE,
+						TEE_PARAM_TYPE_NONE,
+						TEE_PARAM_TYPE_NONE);
+	struct ts_ctx *ctx = NULL;
+	TEE_UUID ta_uuid = TA_REMOTEPROC_UUID;
+
+	if (pt != exp_pt)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (!s || !is_user_ta_ctx(s->ctx))
+		return TEE_ERROR_ACCESS_DENIED;
+
+	/* Check that we're called by the remoteproc Trusted application*/
+	ctx = s->ctx;
+	if (memcmp(&ctx->uuid, &ta_uuid, sizeof(TEE_UUID)))
+		return TEE_ERROR_ACCESS_DENIED;
+
+	if (!stm32_rproc_get(params[0].value.a))
+		return TEE_ERROR_NOT_SUPPORTED;
+
+	return TEE_SUCCESS;
+}
+
+pseudo_ta_register(.uuid = PTA_RPROC_UUID, .name = PTA_NAME,
+		   .flags = PTA_DEFAULT_FLAGS,
+		   .invoke_command_entry_point = rproc_pta_invoke_command,
+		   .open_session_entry_point = rproc_pta_open_session);
diff --git a/core/pta/stm32mp/rproc_pub_key.h b/core/pta/stm32mp/rproc_pub_key.h
new file mode 100644
index 0000000000000000000000000000000000000000..b362565237329e902766d7cfaa4704672c2e12ee
--- /dev/null
+++ b/core/pta/stm32mp/rproc_pub_key.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2023, STMicroelectronics - All Rights Reserved
+ */
+
+#ifndef PTA_STM32MP_RPROC_PUB_KEY_H
+#define PTA_STM32MP_RPROC_PUB_KEY_H
+
+#include <types_ext.h>
+
+extern const uint32_t rproc_pub_key_exponent;
+extern const uint8_t rproc_pub_key_modulus[];
+extern const size_t rproc_pub_key_modulus_size;
+
+#endif /* PTA_STM32MP_RPROC_PUB_KEY_H */
+
diff --git a/core/pta/stm32mp/sub.mk b/core/pta/stm32mp/sub.mk
index ed16c5f471c19957bf7aedbad1aa2f809a84f13b..53a738d6ba23000b22e1b64c2be20916c54bf1f6 100644
--- a/core/pta/stm32mp/sub.mk
+++ b/core/pta/stm32mp/sub.mk
@@ -1 +1,2 @@
 srcs-$(CFG_STM32_BSEC_PTA) += bsec_pta.c
+srcs-$(CFG_REMOTEPROC_PTA) += remoteproc_pta.c
diff --git a/core/pta/sub.mk b/core/pta/sub.mk
index 41212d338b111aaa7eb4b0cd256042a2ad2ac5f0..cf8e86298db49b753bbe141f68474ae8279a41ad 100644
--- a/core/pta/sub.mk
+++ b/core/pta/sub.mk
@@ -19,3 +19,12 @@ subdirs-y += bcm
 subdirs-y += stm32mp
 subdirs-y += imx
 subdirs-y += k3
+
+ifeq ($(CFG_REMOTEPROC_PTA),y)
+gensrcs-y += rproc_pub_key
+produce-rproc_pub_key = rproc_pub_key.c
+depends-rproc_pub_key = $(RPROC_SIGN_KEY) scripts/pem_to_pub_c.py
+recipe-rproc_pub_key = $(PYTHON3) scripts/pem_to_pub_c.py \
+	--prefix rproc_pub_key --key $(RPROC_SIGN_KEY)    \
+	--out $(sub-dir-out)/rproc_pub_key.c
+endif
\ No newline at end of file
diff --git a/core/tee/tee_pobj.c b/core/tee/tee_pobj.c
index d8a2d267cd92881263f6c5acbc310e34ef08776b..cabf49df756d7d5d0f812b60d9e96d8bdc4ad18c 100644
--- a/core/tee/tee_pobj.c
+++ b/core/tee/tee_pobj.c
@@ -12,6 +12,26 @@
 static TAILQ_HEAD(tee_pobjs, tee_pobj) tee_pobjs =
 		TAILQ_HEAD_INITIALIZER(tee_pobjs);
 static struct mutex pobjs_mutex = MUTEX_INITIALIZER;
+static struct mutex pobjs_usage_mutex = MUTEX_INITIALIZER;
+
+static bool pobj_need_usage_lock(struct tee_pobj *obj)
+{
+	/* Only lock if we don't have exclusive access to the object */
+	return obj->flags & (TEE_DATA_FLAG_SHARE_WRITE |
+			     TEE_DATA_FLAG_SHARE_READ);
+}
+
+void tee_pobj_lock_usage(struct tee_pobj *obj)
+{
+	if (pobj_need_usage_lock(obj))
+		mutex_lock(&pobjs_usage_mutex);
+}
+
+void tee_pobj_unlock_usage(struct tee_pobj *obj)
+{
+	if (pobj_need_usage_lock(obj))
+		mutex_unlock(&pobjs_usage_mutex);
+}
 
 static TEE_Result tee_pobj_check_access(uint32_t oflags, uint32_t nflags)
 {
diff --git a/core/tee/tee_ree_fs.c b/core/tee/tee_ree_fs.c
index 71d5dcdaa13a08df327fb00a147720d0171fa9bb..2e44ec48da90dc836a9dc0c03fc601920267c0b4 100644
--- a/core/tee/tee_ree_fs.c
+++ b/core/tee/tee_ree_fs.c
@@ -598,7 +598,7 @@ static TEE_Result open_dirh(struct tee_fs_dirfile_dirh **dirh)
 		static bool once;
 
 		if (res != TEE_ERROR_NOT_IMPLEMENTED ||
-		    !IS_ENABLED(CFG_WARN_INSECURE))
+		    !IS_ENABLED(CFG_INSECURE))
 			return res;
 
 		if (!once) {
@@ -633,7 +633,7 @@ static TEE_Result commit_dirh_writes(struct tee_fs_dirfile_dirh *dirh)
 	if (res)
 		return res;
 	res = nv_counter_incr_ree_fs_to(counter);
-	if (res == TEE_ERROR_NOT_IMPLEMENTED && IS_ENABLED(CFG_WARN_INSECURE)) {
+	if (res == TEE_ERROR_NOT_IMPLEMENTED && IS_ENABLED(CFG_INSECURE)) {
 		static bool once;
 
 		if (!once) {
diff --git a/core/tee/tee_rpmb_fs.c b/core/tee/tee_rpmb_fs.c
index 516e3be4f04f0733be319d72d68828b7d509862b..0ed30933b3f301c225e70ef805c4a1f1b8744775 100644
--- a/core/tee/tee_rpmb_fs.c
+++ b/core/tee/tee_rpmb_fs.c
@@ -75,7 +75,7 @@ struct rpmb_fat_entry {
 	uint32_t start_address;
 	uint32_t data_size;
 	uint32_t flags;
-	uint32_t write_counter;
+	uint32_t unused;
 	uint8_t fek[TEE_FS_KM_FEK_SIZE];
 	char filename[TEE_RPMB_FS_FILENAME_LENGTH];
 };
@@ -1518,35 +1518,6 @@ func_exit:
 	return res;
 }
 
-/*
- * Read the RPMB write counter.
- *
- * @dev_id     Device ID of the eMMC device.
- * @counter    Pointer to the counter.
- */
-static TEE_Result tee_rpmb_get_write_counter(uint16_t dev_id,
-					     uint32_t *counter)
-{
-	TEE_Result res = TEE_SUCCESS;
-
-	if (!counter)
-		return TEE_ERROR_BAD_PARAMETERS;
-
-	if (rpmb_dead)
-		return TEE_ERROR_COMMUNICATION;
-
-	if (!rpmb_ctx || !rpmb_ctx->wr_cnt_synced) {
-		res = tee_rpmb_init(dev_id);
-		if (res != TEE_SUCCESS)
-			goto func_exit;
-	}
-
-	*counter = rpmb_ctx->wr_cnt;
-
-func_exit:
-	return res;
-}
-
 /*
  * Read the RPMB max block.
  *
@@ -1986,8 +1957,7 @@ static struct rpmb_file_handle *alloc_file_handle(struct tee_pobj *po,
 /**
  * write_fat_entry: Store info in a fat_entry to RPMB.
  */
-static TEE_Result write_fat_entry(struct rpmb_file_handle *fh,
-				  bool update_write_counter)
+static TEE_Result write_fat_entry(struct rpmb_file_handle *fh)
 {
 	TEE_Result res = TEE_ERROR_GENERIC;
 
@@ -2002,13 +1972,6 @@ static TEE_Result write_fat_entry(struct rpmb_file_handle *fh,
 		goto out;
 	}
 
-	if (update_write_counter) {
-		res = tee_rpmb_get_write_counter(CFG_RPMB_FS_DEV_ID,
-						 &fh->fat_entry.write_counter);
-		if (res)
-			goto out;
-	}
-
 	res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, fh->rpmb_fat_address,
 			     (uint8_t *)&fh->fat_entry,
 			     sizeof(struct rpmb_fat_entry), NULL, NULL);
@@ -2114,15 +2077,10 @@ static TEE_Result rpmb_fs_setup(void)
 	fh->rpmb_fat_address = partition_data->fat_start_address;
 
 	/* Write init FAT entry and partition data to RPMB. */
-	res = write_fat_entry(fh, true);
+	res = write_fat_entry(fh);
 	if (res != TEE_SUCCESS)
 		goto out;
 
-	res =
-	    tee_rpmb_get_write_counter(CFG_RPMB_FS_DEV_ID,
-				       &partition_data->write_counter);
-	if (res != TEE_SUCCESS)
-		goto out;
 	res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, RPMB_STORAGE_START_ADDRESS,
 			     (uint8_t *)partition_data,
 			     sizeof(struct rpmb_fs_partition), NULL, NULL);
@@ -2277,7 +2235,7 @@ static TEE_Result read_fat(struct rpmb_file_handle *fh, tee_mm_pool_t *p)
 			memset(&last_fh, 0, sizeof(last_fh));
 			last_fh.fat_entry.flags = FILE_IS_LAST_ENTRY;
 			last_fh.rpmb_fat_address = fat_address;
-			res = write_fat_entry(&last_fh, true);
+			res = write_fat_entry(&last_fh);
 			if (res != TEE_SUCCESS)
 				goto out;
 		}
@@ -2364,7 +2322,7 @@ static TEE_Result rpmb_fs_open_internal(struct rpmb_file_handle *fh,
 			     (void *)fh->fat_entry.fek);
 			DHEXDUMP(fh->fat_entry.fek, sizeof(fh->fat_entry.fek));
 
-			res = write_fat_entry(fh, true);
+			res = write_fat_entry(fh);
 			if (res != TEE_SUCCESS)
 				goto out;
 		}
@@ -2595,7 +2553,7 @@ static TEE_Result rpmb_fs_write_primitive(struct rpmb_file_handle *fh,
 			fh->fat_entry.data_size = new_size;
 			fh->fat_entry.start_address = new_fat_entry;
 
-			res = write_fat_entry(fh, true);
+			res = write_fat_entry(fh);
 		}
 	}
 
@@ -2649,7 +2607,7 @@ static TEE_Result rpmb_fs_remove_internal(struct rpmb_file_handle *fh)
 
 	/* Clear this file entry. */
 	memset(&fh->fat_entry, 0, sizeof(struct rpmb_fat_entry));
-	return write_fat_entry(fh, false);
+	return write_fat_entry(fh);
 }
 
 static TEE_Result rpmb_fs_remove(struct tee_pobj *po)
@@ -2714,7 +2672,7 @@ static  TEE_Result rpmb_fs_rename_internal(struct tee_pobj *old,
 
 		/* Clear this file entry. */
 		memset(&fh_new->fat_entry, 0, sizeof(struct rpmb_fat_entry));
-		res = write_fat_entry(fh_new, false);
+		res = write_fat_entry(fh_new);
 		if (res != TEE_SUCCESS)
 			goto out;
 	}
@@ -2723,7 +2681,7 @@ static  TEE_Result rpmb_fs_rename_internal(struct tee_pobj *old,
 	memcpy(fh_old->fat_entry.filename, fh_new->filename,
 	       strlen(fh_new->filename));
 
-	res = write_fat_entry(fh_old, false);
+	res = write_fat_entry(fh_old);
 
 out:
 	free(fh_old);
@@ -2815,7 +2773,7 @@ static TEE_Result rpmb_fs_truncate(struct tee_file_handle *tfh, size_t length)
 	/* fh->pos is unchanged */
 	fh->fat_entry.data_size = newsize;
 	fh->fat_entry.start_address = newaddr;
-	res = write_fat_entry(fh, true);
+	res = write_fat_entry(fh);
 
 out:
 	mutex_unlock(&rpmb_mutex);
diff --git a/core/tee/tee_svc.c b/core/tee/tee_svc.c
index f4158dca1517d4afbd05777bbc4b2cfe0d5b802e..237a27de9238ab5940e6c9d43cb6ebcd97cce6e9 100644
--- a/core/tee/tee_svc.c
+++ b/core/tee/tee_svc.c
@@ -700,11 +700,13 @@ static TEE_Result tee_svc_copy_param(struct ts_session *sess,
 		case TEE_PARAM_TYPE_MEMREF_INOUT:
 			va = (void *)param->u[n].mem.offs;
 			s = param->u[n].mem.size;
-			if (!va) {
-				if (s)
-					return TEE_ERROR_BAD_PARAMETERS;
+			if (!s) {
+				param->u[n].mem.mobj = NULL;
 				break;
 			}
+			if (!va)
+				return TEE_ERROR_BAD_PARAMETERS;
+
 			/* uTA cannot expose its private memory */
 			if (vm_buf_is_inside_um_private(&utc->uctx, va, s))
 				return TEE_ERROR_BAD_PARAMETERS;
diff --git a/core/tee/tee_svc_cryp.c b/core/tee/tee_svc_cryp.c
index 72503454bce45a73b10e0200ca2fc2732e5e81e8..5a16ee4d65d4f6dd780e4eced860d6d24385e28b 100644
--- a/core/tee/tee_svc_cryp.c
+++ b/core/tee/tee_svc_cryp.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
  * Copyright (c) 2014, STMicroelectronics International N.V.
- * Copyright (c) 2020, 2022 Linaro Limited
+ * Copyright (c) 2020, 2022-2023 Linaro Limited
  * Copyright (c) 2022, Technology Innovation Institute (TII)
  */
 
@@ -22,7 +22,9 @@
 #include <tee_api_types.h>
 #include <tee/tee_cryp_utl.h>
 #include <tee/tee_obj.h>
+#include <tee/tee_pobj.h>
 #include <tee/tee_svc_cryp.h>
+#include <tee/tee_svc_storage.h>
 #include <tee/tee_svc.h>
 #include <trace.h>
 #include <utee_defines.h>
@@ -1184,7 +1186,13 @@ TEE_Result syscall_cryp_obj_get_info(unsigned long obj,
 	o_info.obj_type = o->info.objectType;
 	o_info.obj_size = o->info.objectSize;
 	o_info.max_obj_size = o->info.maxObjectSize;
-	o_info.obj_usage = o->info.objectUsage;
+	if (o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) {
+		tee_pobj_lock_usage(o->pobj);
+		o_info.obj_usage = o->pobj->obj_info_usage;
+		tee_pobj_unlock_usage(o->pobj);
+	} else {
+		o_info.obj_usage = o->info.objectUsage;
+	}
 	o_info.data_size = o->info.dataSize;
 	o_info.data_pos = o->info.dataPosition;
 	o_info.handle_flags = o->info.handleFlags;
@@ -1202,12 +1210,22 @@ TEE_Result syscall_cryp_obj_restrict_usage(unsigned long obj,
 	struct tee_obj *o = NULL;
 
 	res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o);
-	if (res != TEE_SUCCESS)
-		goto exit;
+	if (res)
+		return res;
 
-	o->info.objectUsage &= usage;
+	if (o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) {
+		uint32_t new_usage = 0;
+
+		tee_pobj_lock_usage(o->pobj);
+		new_usage = o->pobj->obj_info_usage & usage;
+		res = tee_svc_storage_write_usage(o, new_usage);
+		if (!res)
+			o->pobj->obj_info_usage = new_usage;
+		tee_pobj_unlock_usage(o->pobj);
+	} else {
+		o->info.objectUsage &= usage;
+	}
 
-exit:
 	return res;
 }
 
@@ -1271,6 +1289,7 @@ TEE_Result syscall_cryp_obj_get_attr(unsigned long obj, unsigned long attr_id,
 	int idx = 0;
 	const struct attr_ops *ops = NULL;
 	void *attr = NULL;
+	uint32_t obj_usage = 0;
 
 	res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o);
 	if (res != TEE_SUCCESS)
@@ -1281,9 +1300,17 @@ TEE_Result syscall_cryp_obj_get_attr(unsigned long obj, unsigned long attr_id,
 		return TEE_ERROR_BAD_PARAMETERS;
 
 	/* Check that getting the attribute is allowed */
-	if (!(attr_id & TEE_ATTR_FLAG_PUBLIC) &&
-	    !(o->info.objectUsage & TEE_USAGE_EXTRACTABLE))
-		return TEE_ERROR_BAD_PARAMETERS;
+	if (!(attr_id & TEE_ATTR_FLAG_PUBLIC)) {
+		if (o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) {
+			tee_pobj_lock_usage(o->pobj);
+			obj_usage = o->pobj->obj_info_usage;
+			tee_pobj_unlock_usage(o->pobj);
+		} else {
+			obj_usage = o->info.objectUsage;
+		}
+		if (!(obj_usage & TEE_USAGE_EXTRACTABLE))
+			return TEE_ERROR_BAD_PARAMETERS;
+	}
 
 	type_props = tee_svc_find_type_props(o->info.objectType);
 	if (!type_props) {
@@ -1619,7 +1646,10 @@ TEE_Result tee_obj_set_type(struct tee_obj *o, uint32_t obj_type,
 
 	o->info.objectType = obj_type;
 	o->info.maxObjectSize = max_key_size;
-	o->info.objectUsage = TEE_USAGE_DEFAULT;
+	if (o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)
+		o->pobj->obj_info_usage = TEE_USAGE_DEFAULT;
+	else
+		o->info.objectUsage = TEE_USAGE_DEFAULT;
 
 	return TEE_SUCCESS;
 }
@@ -2040,7 +2070,13 @@ TEE_Result syscall_cryp_obj_copy(unsigned long dst, unsigned long src)
 
 	dst_o->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED;
 	dst_o->info.objectSize = src_o->info.objectSize;
-	dst_o->info.objectUsage = src_o->info.objectUsage;
+	if (src_o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) {
+		tee_pobj_lock_usage(src_o->pobj);
+		dst_o->info.objectUsage = src_o->pobj->obj_info_usage;
+		tee_pobj_unlock_usage(src_o->pobj);
+	} else {
+		dst_o->info.objectUsage = src_o->info.objectUsage;
+	}
 	return TEE_SUCCESS;
 }
 
diff --git a/core/tee/tee_svc_storage.c b/core/tee/tee_svc_storage.c
index 3adf62dde7249b3285ca3b1de55f9702f6d7fbeb..5cf39d567dbe5a53e46b320f0fb07c15b6ecaa39 100644
--- a/core/tee/tee_svc_storage.c
+++ b/core/tee/tee_svc_storage.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
  * Copyright (c) 2014, STMicroelectronics International N.V.
- * Copyright (c) 2020, 2022 Linaro Limited
+ * Copyright (c) 2020, 2022-2023 Linaro Limited
  */
 
 #include <config.h>
@@ -150,7 +150,7 @@ static TEE_Result tee_svc_storage_read_head(struct tee_obj *o)
 
 	o->info.dataSize = size - sizeof(head) - head.attr_size;
 	o->info.objectSize = head.objectSize;
-	o->info.objectUsage = head.objectUsage;
+	o->pobj->obj_info_usage = head.objectUsage;
 	o->info.objectType = head.objectType;
 	o->have_attrs = head.have_attrs;
 
@@ -214,7 +214,9 @@ TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id,
 	o->pobj = po;
 	tee_obj_add(utc, o);
 
+	tee_pobj_lock_usage(o->pobj);
 	res = tee_svc_storage_read_head(o);
+	tee_pobj_unlock_usage(o->pobj);
 	if (res != TEE_SUCCESS) {
 		if (res == TEE_ERROR_CORRUPT_OBJECT) {
 			EMSG("Object corrupt");
@@ -263,7 +265,7 @@ static TEE_Result tee_svc_storage_init_file(struct tee_obj *o, bool overwrite,
 			if (res)
 				return res;
 			o->have_attrs = attr_o->have_attrs;
-			o->info.objectUsage = attr_o->info.objectUsage;
+			o->pobj->obj_info_usage = attr_o->info.objectUsage;
 			o->info.objectSize = attr_o->info.objectSize;
 		}
 		res = tee_obj_attr_to_binary(o, NULL, &attr_size);
@@ -289,7 +291,7 @@ static TEE_Result tee_svc_storage_init_file(struct tee_obj *o, bool overwrite,
 	head.attr_size = attr_size;
 	head.objectSize = o->info.objectSize;
 	head.maxObjectSize = o->info.maxObjectSize;
-	head.objectUsage = o->info.objectUsage;
+	head.objectUsage = o->pobj->obj_info_usage;
 	head.objectType = o->info.objectType;
 	head.have_attrs = o->have_attrs;
 
@@ -369,12 +371,16 @@ TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id,
 		/*
 		 * The caller expects the supplied attributes handle to be
 		 * transformed into a persistent object.
+		 *
+		 * Persistent object keeps the objectUsage field in the
+		 * pobj so move the field below.
 		 */
 		uint32_t saved_flags = attr_o->info.handleFlags;
 
 		attr_o->info.handleFlags = TEE_HANDLE_FLAG_PERSISTENT |
 					   TEE_HANDLE_FLAG_INITIALIZED | flags;
 		attr_o->pobj = po;
+		po->obj_info_usage = attr_o->info.objectUsage;
 		res = tee_svc_storage_init_file(attr_o,
 						flags & TEE_DATA_FLAG_OVERWRITE,
 						attr_o, data, len);
@@ -383,6 +389,7 @@ TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id,
 			attr_o->pobj = NULL;
 			goto err;
 		}
+		attr_o->info.objectUsage = 0;
 	} else {
 		o = tee_obj_alloc();
 		if (!o) {
@@ -667,19 +674,21 @@ TEE_Result syscall_storage_next_enum(unsigned long obj_enum,
 	o->info.handleFlags = o->pobj->flags | TEE_HANDLE_FLAG_PERSISTENT |
 			      TEE_HANDLE_FLAG_INITIALIZED;
 
+	tee_pobj_lock_usage(o->pobj);
 	res = tee_svc_storage_read_head(o);
-	if (res != TEE_SUCCESS)
-		goto exit;
-
 	bbuf = (struct utee_object_info){
 		.obj_type = o->info.objectType,
 		.obj_size = o->info.objectSize,
 		.max_obj_size = o->info.maxObjectSize,
-		.obj_usage = o->info.objectUsage,
+		.obj_usage = o->pobj->obj_info_usage,
 		.data_size = o->info.dataSize,
 		.data_pos = o->info.dataPosition,
 		.handle_flags = o->info.handleFlags,
 	};
+	tee_pobj_unlock_usage(o->pobj);
+	if (res != TEE_SUCCESS)
+		goto exit;
+
 	res = copy_to_user(info, &bbuf, sizeof(bbuf));
 	if (res)
 		goto exit;
@@ -809,6 +818,13 @@ exit:
 	return res;
 }
 
+TEE_Result tee_svc_storage_write_usage(struct tee_obj *o, uint32_t usage)
+{
+	const size_t pos = offsetof(struct tee_svc_storage_head, objectUsage);
+
+	return o->pobj->fops->write(o->fh, pos, &usage, NULL, sizeof(usage));
+}
+
 TEE_Result syscall_storage_obj_trunc(unsigned long obj, size_t len)
 {
 	struct ts_session *sess = ts_get_current_session();
diff --git a/ldelf/ta_elf.c b/ldelf/ta_elf.c
index cf802ac8acfe527a30d5104fd734daabd7b818e8..4e11e00ad75eff9cac28fda7becab707ebe00bd3 100644
--- a/ldelf/ta_elf.c
+++ b/ldelf/ta_elf.c
@@ -104,9 +104,9 @@ static TEE_Result e32_parse_ehdr(struct ta_elf *elf, Elf32_Ehdr *ehdr)
 	if (ehdr->e_ident[EI_VERSION] != EV_CURRENT ||
 	    ehdr->e_ident[EI_CLASS] != ELFCLASS32 ||
 	    ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||
-	    ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE ||
+	    (ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE &&
+	     ehdr->e_ident[EI_OSABI] != ELFOSABI_ARM) ||
 	    ehdr->e_type != ET_DYN || ehdr->e_machine != EM_ARM ||
-	    (ehdr->e_flags & EF_ARM_ABIMASK) != EF_ARM_ABI_VERSION ||
 #ifndef CFG_WITH_VFP
 	    (ehdr->e_flags & EF_ARM_ABI_FLOAT_HARD) ||
 #endif
@@ -114,6 +114,14 @@ static TEE_Result e32_parse_ehdr(struct ta_elf *elf, Elf32_Ehdr *ehdr)
 	    ehdr->e_shentsize != sizeof(Elf32_Shdr))
 		return TEE_ERROR_BAD_FORMAT;
 
+	if (ehdr->e_ident[EI_OSABI] == ELFOSABI_NONE &&
+	    (ehdr->e_flags & EF_ARM_ABIMASK) != EF_ARM_ABI_V5)
+		return TEE_ERROR_BAD_FORMAT;
+
+	if (ehdr->e_ident[EI_OSABI] == ELFOSABI_ARM &&
+	    (ehdr->e_flags & EF_ARM_ABIMASK) != EF_ARM_ABI_UNKNOWN)
+		return TEE_ERROR_BAD_FORMAT;
+
 	elf->is_32bit = true;
 	elf->e_entry = ehdr->e_entry;
 	elf->e_phoff = ehdr->e_phoff;
diff --git a/lib/libmbedtls/core/ecc.c b/lib/libmbedtls/core/ecc.c
index 39adf0e3397c016f79dc0d5cb72628433b869365..38585573ef2ca0a8e6b765ff5606293e3ac68213 100644
--- a/lib/libmbedtls/core/ecc.c
+++ b/lib/libmbedtls/core/ecc.c
@@ -228,7 +228,7 @@ static TEE_Result ecc_sign(uint32_t algo, struct ecc_keypair *key,
 					 mbedtls_mpi_size(&s));
 		res = TEE_SUCCESS;
 	} else {
-		FMSG("mbedtls_ecdsa_sign failed, returned 0x%x\n", -lmd_res);
+		FMSG("mbedtls_ecdsa_sign failed, returned 0x%x", -lmd_res);
 		res = TEE_ERROR_GENERIC;
 	}
 out:
diff --git a/lib/libutee/include/elf_common.h b/lib/libutee/include/elf_common.h
index 0ac08fafb8633218bca73f4b3c8f054051f4d471..8fe481cbbe521847f349d5583b659d7670b7069f 100644
--- a/lib/libutee/include/elf_common.h
+++ b/lib/libutee/include/elf_common.h
@@ -260,7 +260,8 @@ typedef struct {
 #define	EM_ALPHA	0x9026	/* Alpha (written in the absence of an ABI) */
 
 /* e_flags for EM_ARM */
-#define EF_ARM_ABI_VERSION	0x05000000	/* ABI version 5 */
+#define EF_ARM_ABI_UNKNOWN	0x00000000
+#define EF_ARM_ABI_V5		0x05000000	/* ABI version 5 */
 #define EF_ARM_ABIMASK		0xFF000000
 #define EF_ARM_BE8		0x00800000
 #define EF_ARM_ABI_FLOAT_HARD	0x00000400	/* ABI version 5 and later */
diff --git a/lib/libutee/include/pta_stats.h b/lib/libutee/include/pta_stats.h
new file mode 100644
index 0000000000000000000000000000000000000000..f95d3acb8c6afee09749f2da92f1e2054755c39b
--- /dev/null
+++ b/lib/libutee/include/pta_stats.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2023, STMicroelectronics
+ * Copyright (C) 2022, Microchip
+ */
+#ifndef __PTA_STATS_H
+#define __PTA_STATS_H
+
+#include <stdint.h>
+#include <tee_api_types.h>
+
+#define STATS_UUID \
+		{ 0xd96a5b40, 0xe2c7, 0xb1af, \
+			{ 0x87, 0x94, 0x10, 0x02, 0xa5, 0xd5, 0xc6, 0x1b } }
+
+/*
+ * STATS_CMD_PAGER_STATS - Get statistics on pager
+ *
+ * [out]    value[0].a        Number of unlocked pages
+ * [out]    value[0].b        Page pool size
+ * [out]    value[1].a        R/O faults since last stats dump
+ * [out]    value[1].b        R/W faults since last stats dump
+ * [out]    value[2].a        Hidden faults since last stats dump
+ * [out]    value[2].b        Zi pages released since last stats dump
+ */
+#define STATS_CMD_PAGER_STATS		0
+
+/*
+ * STATS_CMD_ALLOC_STATS - Get statistics on core heap allocations
+ *
+ * [in]     value[0].a       ID of allocator(s) to get stats from (ALLOC_ID_*)
+ * [out]    memref[0]        Array of struct pta_stats_alloc instances
+ */
+#define STATS_CMD_ALLOC_STATS		1
+
+#define ALLOC_ID_ALL		0	/* All allocators */
+#define ALLOC_ID_HEAP		1	/* Core heap allocator */
+#define ALLOC_ID_PUBLIC_DDR	2	/* Public DDR allocator (deprecated) */
+#define ALLOC_ID_TA_RAM		3	/* TA_RAM allocator */
+#define ALLOC_ID_NEXUS_HEAP	4	/* Nexus heap allocator */
+#define STATS_NB_POOLS		5
+
+#define TEE_ALLOCATOR_DESC_LENGTH 32
+
+struct pta_stats_alloc {
+	char desc[TEE_ALLOCATOR_DESC_LENGTH];
+	uint32_t allocated;               /* Bytes currently allocated */
+	uint32_t max_allocated;           /* Tracks max value of allocated */
+	uint32_t size;                    /* Total size for this allocator */
+	uint32_t num_alloc_fail;          /* Number of failed alloc requests */
+	uint32_t biggest_alloc_fail;      /* Size of biggest failed alloc */
+	uint32_t biggest_alloc_fail_used; /* Alloc bytes when above occurred */
+};
+
+/*
+ * STATS_CMD_MEMLEAK_STATS - Print memory leakage info to console
+ */
+#define STATS_CMD_MEMLEAK_STATS		2
+
+/*
+ * STATS_CMD_TA_STATS - Get information on TA instances
+ *
+ * [out]    memref[0]        Array of struct pta_stats_ta per loaded TA
+ */
+#define STATS_CMD_TA_STATS		3
+
+struct pta_stats_ta {
+	TEE_UUID uuid;
+	uint32_t panicked;	/* True if TA has panicked */
+	uint32_t sess_num;	/* Number of opened session */
+	struct pta_stats_alloc heap;
+};
+
+/*
+ * STATS_CMD_GET_TIME - Get both REE time and TEE time
+ *
+ * [out]    value[0].a        REE time as seen by OP-TEE in seconds
+ * [out]    value[0].b        REE time as seen by OP-TEE, milliseconds part
+ * [out]    value[1].a        TEE system time in seconds
+ * [out]    value[1].b        TEE system time, milliseconds part
+ */
+#define STATS_CMD_GET_TIME		4
+
+/*
+ * STATS_CMD_PRINT_DRIVER_INFO - Print device drivers information to console
+ *
+ * [in]    value[0].a        Target driver, one of STATS_DRIVER_TYPE_*
+ */
+#define STATS_CMD_PRINT_DRIVER_INFO	5
+
+#define STATS_DRIVER_TYPE_CLOCK		0
+#define STATS_DRIVER_TYPE_REGULATOR	1
+
+#endif /*__PTA_STATS_H*/
diff --git a/lib/libutee/include/remoteproc_pta.h b/lib/libutee/include/remoteproc_pta.h
new file mode 100644
index 0000000000000000000000000000000000000000..e4be4becd77004b567e2325af88830b92f9b9bd8
--- /dev/null
+++ b/lib/libutee/include/remoteproc_pta.h
@@ -0,0 +1,150 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2023, STMicroelectronics
+ */
+
+#ifndef __REMOTEPROC_PTA_H
+#define __REMOTEPROC_PTA_H
+
+#include <stdint.h>
+#include <util.h>
+
+/*
+ * Interface to the pseudo TA which provides platform implementation
+ * of the remote processor management
+ */
+
+#define PTA_RPROC_UUID { 0x54af4a68, 0x19be, 0x40d7, \
+		{ 0xbb, 0xe6, 0x89, 0x50, 0x35, 0x0a, 0x87, 0x44 } }
+
+/* Hardware capability: firmware format */
+#define PTA_RPROC_HWCAP_FMT_ELF	BIT32(0)
+
+/* Hardware capability: image protection method */
+/* The platform supports load of segment with hash protection */
+#define PTA_RPROC_HWCAP_PROT_HASH_TABLE	BIT32(0)
+
+/**
+ * struct rproc_pta_key_info - public key information
+ * @algo:	Algorithm, defined by public key algorithms TEE_ALG_*
+ * @info_size:	Byte size of @info
+ * @info:	Append key information data
+ */
+struct rproc_pta_key_info {
+	uint32_t algo;
+	uint32_t info_size;
+	uint8_t info[];
+};
+
+static inline size_t rproc_pta_keyinfo_size(struct rproc_pta_key_info *keyinf)
+{
+	size_t s = 0;
+
+	if (!keyinf || ADD_OVERFLOW(sizeof(*keyinf), keyinf->info_size, &s))
+		return 0;
+
+	return s;
+}
+
+/*
+ * Platform capabilities.
+ *
+ * Get Platform firmware loader service capabilities.
+ *
+ * [in]  params[0].value.a:	Unique 32bit remote processor identifier
+ * [out] params[1].value.a:	Firmware format (PTA_RPROC_HWCAP_FMT_*)
+ * [out] params[2].value.a:	Image protection method (PTA_RPROC_HWCAP_PROT_*)
+ */
+#define PTA_RPROC_HW_CAPABILITIES	1
+
+/*
+ * Firmware loading.
+ *
+ * Optional service to implement only in case of proprietary format.
+ *
+ * [in]  params[0].value.a:	Unique 32bit remote processor identifier
+ * [in]  params[1].memref:	Loadable firmware image
+ */
+#define PTA_RPROC_FIRMWARE_LOAD		2
+
+/*
+ * Load a segment with a SHA256 hash.
+ *
+ * This command is used when the platform secure memory is too constrained to
+ * save the whole firmware image. Upon segment load, a successful completion
+ * ensures the loaded image complies with the provided hash.
+ *
+ * [in]  params[0].value.a:	Unique 32bit remote processor identifier
+ * [in]  params[1].memref:	Section data to load
+ * [in]  params[2].value.a:	32bit LSB load device segment address
+ * [in]  params[2].value.b:	32bit MSB load device segment address
+ * [in]  params[3].memref:	Expected hash (SHA256) of the payload
+ */
+#define PTA_RPROC_LOAD_SEGMENT_SHA256	3
+
+/*
+ * Memory set.
+ *
+ * Fill a remote device memory with requested value. this is used for instance
+ * to clear a memory on the remote firmware load.
+ *
+ * [in]  params[0].value.a:	Unique 32bit remote processor identifier
+ * [in]  params[1].value.a:	32bit LSB device memory address
+ * [in]  params[1].value.b:	32bit MSB device memory address
+ * [in]  params[2].value.a:	32bit LSB device memory size
+ * [in]  params[2].value.b:	32bit MSB device memory size
+ * [in]  params[3].value.a:	Byte value to be set
+ */
+#define PTA_RPROC_SET_MEMORY		4
+
+/*
+ * Firmware start.
+ *
+ * Start up a successfully loaded remote processor firmware.
+ *
+ * [in]  params[0].value.a:	Unique 32bit remote processor identifier
+ */
+#define PTA_RPROC_FIRMWARE_START	5
+
+/*
+ * Firmware stop.
+ *
+ * Stop of the remote processor firmware and release/clean resources.
+ * After the command successful completion, remote processor firmware must be
+ * reloaded prior being started again.
+ *
+ * [in]  params[0].value.a:	Unique 32bit remote processor identifier
+ */
+#define PTA_RPROC_FIRMWARE_STOP		6
+
+/*
+ * Firmware device to physical address conversion.
+ *
+ * Convert the physical address corresponding to an address got from the
+ * firmware address layout.
+ *
+ * [in]  params[0].value.a:	Unique 32bit remote processor identifier
+ * [in]  params[1].value.a:	32bit LSB Device memory address
+ * [in]  params[1].value.b:	32bit MSB Device memory address
+ * [in]  params[2].value.a:	32bit LSB Device memory size
+ * [in]  params[2].value.b:	32bit MSB Device memory size
+ * [out] params[3].value.a:	32bit LSB converted physical address
+ * [out] params[3].value.b:	32bit MSB converted physical address
+ */
+#define PTA_RPROC_FIRMWARE_DA_TO_PA	7
+
+/*
+ * Verify the firmware digest against a signature
+ *
+ * Return TEE_SUCCESS if the signature is verified,
+ *        TEE_ERROR_SIGNATURE_INVALID when signature is not valid,
+ *        another error code for other error cases.
+ *
+ * [in]  params[0].value.a:	Unique 32bit remote processor identifier
+ * [in]  params[1].memref:	Key information (refer to @rproc_pta_key_info)
+ * [in]  params[2].memref:	Digest of the firmware authenticated data
+ * [in]  params[3].memref:	Signature of the firmware authenticated data
+ */
+#define PTA_RPROC_VERIFY_DIGEST		8
+
+#endif /* __REMOTEPROC_PTA_H */
diff --git a/lib/libutee/include/tee_arith_internal.h b/lib/libutee/include/tee_arith_internal.h
index fc5678edc2021287891cecf86843e9b31943f827..cf1d3edd7e1af5e960f16e9d26a790d46e35af50 100644
--- a/lib/libutee/include/tee_arith_internal.h
+++ b/lib/libutee/include/tee_arith_internal.h
@@ -22,12 +22,6 @@
  */
 #define TEE_MATHAPI_EXPORT
 
-/*
- * The modes for String Conversion
- */
-#define TEE_STRING_MODE_HEX_UC MPA_STRING_MODE_HEX_UC
-#define TEE_STRING_MODE_HEX_LC MPA_STRING_MODE_HEX_UC
-
 /*------------------------------------------------------------
  *
  *  Define IN, OUT, INBUF and OUTBUF to keep format from the spec.
diff --git a/lib/libutee/include/utee_defines.h b/lib/libutee/include/utee_defines.h
index 8a3ccf34b73ffa6890dd1383d70d00112a2adb33..6c3248d178d6f6c6c7107eb5ce74b8345e88cf45 100644
--- a/lib/libutee/include/utee_defines.h
+++ b/lib/libutee/include/utee_defines.h
@@ -302,12 +302,18 @@ static inline size_t __tee_alg_get_digest_size(uint32_t algo)
 #endif
 
 /* If we we're on a big endian platform we'll have to update these */
-#define TEE_U64_FROM_BIG_ENDIAN(x)  TEE_U64_BSWAP(x)
-#define TEE_U32_FROM_BIG_ENDIAN(x)  TEE_U32_BSWAP(x)
-#define TEE_U16_FROM_BIG_ENDIAN(x)  TEE_U16_BSWAP(x)
-#define TEE_U64_TO_BIG_ENDIAN(x)    TEE_U64_BSWAP(x)
-#define TEE_U32_TO_BIG_ENDIAN(x)    TEE_U32_BSWAP(x)
-#define TEE_U16_TO_BIG_ENDIAN(x)    TEE_U16_BSWAP(x)
+#define TEE_U64_FROM_LITTLE_ENDIAN(x)  ((uint64_t)(x))
+#define TEE_U32_FROM_LITTLE_ENDIAN(x)  ((uint32_t)(x))
+#define TEE_U16_FROM_LITTLE_ENDIAN(x)  ((uint16_t)(x))
+#define TEE_U64_TO_LITTLE_ENDIAN(x)    ((uint64_t)(x))
+#define TEE_U32_TO_LITTLE_ENDIAN(x)    ((uint32_t)(x))
+#define TEE_U16_TO_LITTLE_ENDIAN(x)    ((uint16_t)(x))
+#define TEE_U64_FROM_BIG_ENDIAN(x)     TEE_U64_BSWAP(x)
+#define TEE_U32_FROM_BIG_ENDIAN(x)     TEE_U32_BSWAP(x)
+#define TEE_U16_FROM_BIG_ENDIAN(x)     TEE_U16_BSWAP(x)
+#define TEE_U64_TO_BIG_ENDIAN(x)       TEE_U64_BSWAP(x)
+#define TEE_U32_TO_BIG_ENDIAN(x)       TEE_U32_BSWAP(x)
+#define TEE_U16_TO_BIG_ENDIAN(x)       TEE_U16_BSWAP(x)
 
 #define TEE_TIME_MILLIS_BASE    1000
 
diff --git a/lib/libutee/tee_api_arith_mpi.c b/lib/libutee/tee_api_arith_mpi.c
index 5842f13a807c05318a87f46d46340a40f40fe555..9ccbd7c68073467fcf453df9b4e33577e45a1dab 100644
--- a/lib/libutee/tee_api_arith_mpi.c
+++ b/lib/libutee/tee_api_arith_mpi.c
@@ -726,10 +726,6 @@ out:
 	return res;
 }
 
-/*
- * Based on libmpa implementation __mpa_egcd(), modified to work with MPI
- * instead.
- */
 static void mpi_egcd(mbedtls_mpi *gcd, mbedtls_mpi *a, mbedtls_mpi *b,
 		     mbedtls_mpi *x_in, mbedtls_mpi *y_in)
 {
diff --git a/lib/libutee/tee_api_operations.c b/lib/libutee/tee_api_operations.c
index f44350da2f794dda1980044bb4361c32cd097d11..752425ae9627a2b3b35373143510c84b3abc40c9 100644
--- a/lib/libutee/tee_api_operations.c
+++ b/lib/libutee/tee_api_operations.c
@@ -132,7 +132,7 @@ TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation,
 		break;
 	}
 
-	/* Check algorithm mode (and maxKeySize for digests) */
+	/* Check algorithm mode */
 	switch (algorithm) {
 	case TEE_ALG_AES_CTS:
 	case TEE_ALG_AES_XTS:
@@ -277,8 +277,6 @@ TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation,
 	case TEE_ALG_SM3:
 		if (mode != TEE_MODE_DIGEST)
 			return TEE_ERROR_NOT_SUPPORTED;
-		if (maxKeySize)
-			return TEE_ERROR_NOT_SUPPORTED;
 		/* v1.1: flags always set for digest operations */
 		handle_state |= TEE_HANDLE_FLAG_KEY_SET;
 		req_key_usage = 0;
diff --git a/lib/libutee/user_ta_entry.c b/lib/libutee/user_ta_entry.c
index 2ac3e25588b830d8e6bfb9e73bb61ad42b73381f..b33953f429e2e79a4deb2e753926b11b9c43ed95 100644
--- a/lib/libutee/user_ta_entry.c
+++ b/lib/libutee/user_ta_entry.c
@@ -392,7 +392,7 @@ static TEE_Result entry_dump_memstats(unsigned long session_id __unused,
 {
 	uint32_t param_types = 0;
 	TEE_Param params[TEE_NUM_PARAMS] = { };
-	struct malloc_stats stats = { };
+	struct pta_stats_alloc stats = { };
 
 	from_utee_params(params, &param_types, up);
 	ta_header_save_params(param_types, params);
diff --git a/lib/libutils/ext/include/trace.h b/lib/libutils/ext/include/trace.h
index 6f28bdb771fa5b465a9e6c45cf60b093b2c6ebeb..6ea6dcc6cd021556e65f983aaff614cfe60194c7 100644
--- a/lib/libutils/ext/include/trace.h
+++ b/lib/libutils/ext/include/trace.h
@@ -26,6 +26,7 @@ extern const char trace_ext_prefix[];
 void trace_ext_puts(const char *str);
 int trace_ext_get_thread_id(void);
 int trace_ext_get_core_id(void);
+int trace_ext_get_guest_id(void);
 void trace_set_level(int level);
 int trace_get_level(void);
 void plat_trace_ext_puts(const char *str);
diff --git a/lib/libutils/ext/mempool.c b/lib/libutils/ext/mempool.c
index 30508aad0389752fc31d6acd6c2df6eabb59f4fe..e12962f0eeede8a87c36fed6763c6dbd8978f4c9 100644
--- a/lib/libutils/ext/mempool.c
+++ b/lib/libutils/ext/mempool.c
@@ -9,6 +9,7 @@
 #include <compiler.h>
 #include <malloc.h>
 #include <mempool.h>
+#include <pta_stats.h>
 #include <string.h>
 #include <util.h>
 
@@ -146,7 +147,7 @@ void *mempool_alloc(struct mempool *pool, size_t size)
 	p = raw_malloc(0, 0, size, pool->mctx);
 	if (p) {
 #ifdef CFG_MEMPOOL_REPORT_LAST_OFFSET
-		struct malloc_stats stats = { };
+		struct pta_stats_alloc stats = { };
 
 		raw_malloc_get_stats(pool->mctx, &stats);
 		if (stats.max_allocated > pool->max_allocated) {
diff --git a/lib/libutils/ext/trace.c b/lib/libutils/ext/trace.c
index 33c099d2c1975d8de2cc025f2f5a4d4e9b815df7..259e4a7af77adacd973d7a29f3e49a81dfb2ece2 100644
--- a/lib/libutils/ext/trace.c
+++ b/lib/libutils/ext/trace.c
@@ -7,12 +7,13 @@
 #include <platform_config.h>
 #endif
 
+#include <config.h>
 #include <printk.h>
 #include <stdarg.h>
 #include <string.h>
 #include <trace.h>
-#include <util.h>
 #include <types_ext.h>
+#include <util.h>
 
 #if (TRACE_LEVEL < TRACE_MIN) || (TRACE_LEVEL > TRACE_MAX)
 #error "Invalid value of TRACE_LEVEL"
@@ -91,11 +92,26 @@ static int print_core_id(char *buf, size_t bs)
 	else
 		return snprintk(buf, bs, "%s ", qm);
 }
+
+static int print_guest_id(char *buf, size_t bs)
+{
+	if (IS_ENABLED(CFG_NS_VIRTUALIZATION))
+		return snprintk(buf, bs, "%d ", trace_ext_get_guest_id());
+	else
+		return 0;
+
+
+}
 #else  /* defined(__KERNEL__) */
 static int print_core_id(char *buf __unused, size_t bs __unused)
 {
 	return 0;
 }
+
+static int print_guest_id(char *buf __unused, size_t bs __unused)
+{
+	return 0;
+}
 #endif
 
 /* Format trace of user ta. Inline with kernel ta */
@@ -133,6 +149,12 @@ void trace_vprintf(const char *function, int line, int level, bool level_ok,
 	boffs += res;
 
 	if (level_ok && (BIT(level) & CFG_MSG_LONG_PREFIX_MASK)) {
+		/* Print the current guest ID or 0 for Nexus */
+		res = print_guest_id(buf + boffs, sizeof(buf) - boffs);
+		if (res < 0)
+			return;
+		boffs += res;
+
 		/* Print the core ID if in atomic context  */
 		res = print_core_id(buf + boffs, sizeof(buf) - boffs);
 		if (res < 0)
diff --git a/lib/libutils/isoc/bget_malloc.c b/lib/libutils/isoc/bget_malloc.c
index 15745bbbc8f4a099c9e7356541f9eceb28b1e4d6..1b26f93c8143bf10741b00e103de23143bf3a90e 100644
--- a/lib/libutils/isoc/bget_malloc.c
+++ b/lib/libutils/isoc/bget_malloc.c
@@ -82,6 +82,7 @@
 #include <config.h>
 #include <malloc.h>
 #include <memtag.h>
+#include <pta_stats.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdlib_ext.h>
@@ -135,7 +136,7 @@ struct malloc_ctx {
 	struct malloc_pool *pool;
 	size_t pool_len;
 #ifdef BufStats
-	struct malloc_stats mstats;
+	struct pta_stats_alloc mstats;
 #endif
 #ifdef __KERNEL__
 	unsigned int spinlock;
@@ -308,7 +309,7 @@ void malloc_reset_stats(void)
 }
 
 static void gen_malloc_get_stats(struct malloc_ctx *ctx,
-				 struct malloc_stats *stats)
+				 struct pta_stats_alloc *stats)
 {
 	uint32_t exceptions = malloc_lock(ctx);
 
@@ -316,7 +317,7 @@ static void gen_malloc_get_stats(struct malloc_ctx *ctx,
 	malloc_unlock(ctx, exceptions);
 }
 
-void malloc_get_stats(struct malloc_stats *stats)
+void malloc_get_stats(struct pta_stats_alloc *stats)
 {
 	gen_malloc_get_stats(&malloc_ctx, stats);
 }
@@ -711,7 +712,7 @@ static void gen_mdbg_check(struct malloc_ctx *ctx, int bufdump)
 			if (!fname)
 				fname = "unknown";
 
-			IMSG("buffer: %d bytes %s:%d\n",
+			IMSG("buffer: %d bytes %s:%d",
 				hdr->pl_size, fname, hdr->line);
 		}
 	}
@@ -996,7 +997,7 @@ bool raw_malloc_buffer_is_within_alloced(struct malloc_ctx *ctx,
 }
 
 #ifdef CFG_WITH_STATS
-void raw_malloc_get_stats(struct malloc_ctx *ctx, struct malloc_stats *stats)
+void raw_malloc_get_stats(struct malloc_ctx *ctx, struct pta_stats_alloc *stats)
 {
 	memcpy_unchecked(stats, &ctx->mstats, sizeof(*stats));
 	stats->allocated = ctx->poolset.totalloc;
@@ -1130,7 +1131,7 @@ void nex_malloc_reset_stats(void)
 	gen_malloc_reset_stats(&nex_malloc_ctx);
 }
 
-void nex_malloc_get_stats(struct malloc_stats *stats)
+void nex_malloc_get_stats(struct pta_stats_alloc *stats)
 {
 	gen_malloc_get_stats(&nex_malloc_ctx, stats);
 }
diff --git a/lib/libutils/isoc/include/malloc.h b/lib/libutils/isoc/include/malloc.h
index d26195585e3169f4143a6ca372a31995d39bdfd4..4e405c03c763044db270363fd8970f4cbe34e696 100644
--- a/lib/libutils/isoc/include/malloc.h
+++ b/lib/libutils/isoc/include/malloc.h
@@ -5,6 +5,7 @@
 #ifndef __MALLOC_H
 #define __MALLOC_H
 
+#include <pta_stats.h>
 #include <stddef.h>
 #include <types_ext.h>
 
@@ -80,22 +81,8 @@ bool malloc_buffer_overlaps_heap(void *buf, size_t len);
 void malloc_add_pool(void *buf, size_t len);
 
 #ifdef CFG_WITH_STATS
-/*
- * Get/reset allocation statistics
- */
-
-#define TEE_ALLOCATOR_DESC_LENGTH 32
-struct malloc_stats {
-	char desc[TEE_ALLOCATOR_DESC_LENGTH];
-	uint32_t allocated;               /* Bytes currently allocated */
-	uint32_t max_allocated;           /* Tracks max value of allocated */
-	uint32_t size;                    /* Total size for this allocator */
-	uint32_t num_alloc_fail;          /* Number of failed alloc requests */
-	uint32_t biggest_alloc_fail;      /* Size of biggest failed alloc */
-	uint32_t biggest_alloc_fail_used; /* Alloc bytes when above occurred */
-};
-
-void malloc_get_stats(struct malloc_stats *stats);
+/* Get/reset allocation statistics */
+void malloc_get_stats(struct pta_stats_alloc *stats);
 void malloc_reset_stats(void);
 #endif /* CFG_WITH_STATS */
 
@@ -142,7 +129,7 @@ void nex_malloc_add_pool(void *buf, size_t len);
  * Get/reset allocation statistics
  */
 
-void nex_malloc_get_stats(struct malloc_stats *stats);
+void nex_malloc_get_stats(struct pta_stats_alloc *stats);
 void nex_malloc_reset_stats(void);
 
 #endif	/* CFG_WITH_STATS */
@@ -174,7 +161,8 @@ bool raw_malloc_buffer_overlaps_heap(struct malloc_ctx *ctx,
 bool raw_malloc_buffer_is_within_alloced(struct malloc_ctx *ctx,
 					 void *buf, size_t len);
 #ifdef CFG_WITH_STATS
-void raw_malloc_get_stats(struct malloc_ctx *ctx, struct malloc_stats *stats);
+void raw_malloc_get_stats(struct malloc_ctx *ctx,
+			  struct pta_stats_alloc *stats);
 #endif
 
 #endif /* __MALLOC_H */
diff --git a/mk/aosp_optee.mk b/mk/aosp_optee.mk
index 07bc67ab4c743f07129ca46b41cf127590665039..65cd4a51aa4cb0c9c606c7b91bb9a30aada84e6a 100644
--- a/mk/aosp_optee.mk
+++ b/mk/aosp_optee.mk
@@ -60,7 +60,8 @@ TA_TARGET := $(local_optee_ta_target)
 else
 TA_TARGET := $(OPTEE_TA_TARGETS)
 endif
-TA_DEV_KIT_DIR := $(ABS_OPTEE_OS_OUT_DIR)/export-$(TA_TARGET)
+TA_DEV_KIT_DIR := $(OPTEE_OS_OUT_DIR)/export-$(TA_TARGET)
+ABS_TA_DEV_KIT_DIR := $(ABS_OPTEE_OS_OUT_DIR)/export-$(TA_TARGET)
 
 CROSS_COMPILE64 ?= $(TOP_ROOT_ABS)/$(TARGET_TOOLS_PREFIX)
 CROSS_COMPILE_LINE := CROSS_COMPILE64="$(CROSS_COMPILE64)"
@@ -73,6 +74,10 @@ OPTEE_BIN := $(OPTEE_OS_OUT_DIR)/core/tee.bin
 
 $(OPTEE_BIN) : $(sort $(shell find -L $(OPTEE_OS_DIR)))
 
+OPTEE_TA_DEV_KIT_MK := $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk
+
+$(OPTEE_TA_DEV_KIT_MK) : $(sort $(shell find -L $(OPTEE_OS_DIR)))
+
 ###########################################################
 ## define making rules for $(OPTEE_BIN) target, and add  ##
 ## condition check to make it only be defined once       ##
@@ -99,6 +104,27 @@ $(OPTEE_BIN):
 
 endif
 
+###########################################################
+## similar to the $(OPTEE_BIN) target above, use condition
+## check to make $(OPTEE_TA_DEV_KIT_MK) for different ta
+## targets only be defined once
+###########################################################
+ifeq ($(filter $(TA_TARGET),$(BUILD_TA_DEV_KIT_DEFINED)),)
+BUILD_TA_DEV_KIT_DEFINED := $(TA_TARGET) $(BUILD_TA_DEV_KIT_DEFINED)
+$(OPTEE_TA_DEV_KIT_MK): PRIVATE_TA_TARGET := $(TA_TARGET)
+$(OPTEE_TA_DEV_KIT_MK):
+	@echo "Start building ta_dev_kit ($(PRIVATE_TA_TARGET))..."
+	+$(HOST_MAKE) -C $(TOP_ROOT_ABS)/$(OPTEE_OS_DIR) \
+		O=$(ABS_OPTEE_OS_OUT_DIR) \
+		CFG_USER_TA_TARGETS=$(PRIVATE_TA_TARGET) \
+		CFG_ARM64_core=$(OPTEE_CFG_ARM64_CORE) \
+		PLATFORM=$(OPTEE_PLATFORM) \
+		PLATFORM_FLAVOR=$(OPTEE_PLATFORM_FLAVOR) \
+		$(CROSS_COMPILE_LINE) \
+		$(OPTEE_EXTRA_FLAGS) ta_dev_kit
+	@echo "Finished building ta_dev_kit ($(PRIVATE_TA_TARGET))..."
+endif
+
 ##########################################################
 ## Lines for building TAs automatically                 ##
 ## will only be included in Android.mk for TAs          ##
@@ -133,8 +159,8 @@ $(TA_TMP_FILE): $(TA_TMP_FILE_DEPS)
 $(TA_TMP_FILE): PRIVATE_TA_SRC_DIR := $(LOCAL_PATH)
 $(TA_TMP_FILE): PRIVATE_TA_TMP_FILE := $(TA_TMP_FILE)
 $(TA_TMP_FILE): PRIVATE_TA_TMP_DIR := $(TA_TMP_DIR)
-$(TA_TMP_FILE): PRIVATE_TA_DEV_KIT_DIR := $(TA_DEV_KIT_DIR)
-$(TA_TMP_FILE): $(OPTEE_BIN)
+$(TA_TMP_FILE): PRIVATE_TA_DEV_KIT_DIR := $(ABS_TA_DEV_KIT_DIR)
+$(TA_TMP_FILE): $(OPTEE_TA_DEV_KIT_MK)
 	@echo "Start building TA for $(PRIVATE_TA_SRC_DIR) $(PRIVATE_TA_TMP_FILE)..."
 	+$(HOST_MAKE) -C $(TOP_ROOT_ABS)/$(PRIVATE_TA_SRC_DIR) O=$(ABS_OPTEE_TA_OUT_DIR)/$(PRIVATE_TA_TMP_DIR) \
 		TA_DEV_KIT_DIR=$(PRIVATE_TA_DEV_KIT_DIR) \
@@ -143,6 +169,27 @@ $(TA_TMP_FILE): $(OPTEE_BIN)
 	@echo "Finished building TA for $(PRIVATE_TA_SRC_DIR) $(PRIVATE_TA_TMP_FILE)..."
 
 include $(BUILD_PREBUILT)
+
+# To get ta elf files for early-ta,
+# copy them to $(PRODUCT_OUT)/unsigned/ on host
+ifeq ($(call ta_class,$(local_module)),EXECUTABLES)
+include $(CLEAR_VARS)
+LOCAL_MODULE := $(local_module).unsigned
+LOCAL_PREBUILT_MODULE_FILE := $(OPTEE_TA_OUT_DIR)/$(LOCAL_MODULE)
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/unsigned
+LOCAL_MODULE_CLASS := $(call ta_class,$(local_module))
+LOCAL_MODULE_TAGS := optional
+
+TA_TMP_STRIPPED_ELF_FILE := $(patsubst %.ta,%.stripped.elf,$(TA_TMP_FILE))
+$(TA_TMP_STRIPPED_ELF_FILE): $(TA_TMP_FILE)
+
+$(LOCAL_PREBUILT_MODULE_FILE): $(TA_TMP_STRIPPED_ELF_FILE)
+	@mkdir -p $(dir $@)
+	cp -vf $< $@
+
+include $(BUILD_PREBUILT)
+endif  # to get ta elf files for early-ta
+
 local_module_deps :=
 local_optee_ta_target :=
 endif
diff --git a/mk/config.mk b/mk/config.mk
index a9a68e3a48db659f71881d6dfe1e7b3937368978..1247ccef935472ef6cb267f884ac464790982040 100644
--- a/mk/config.mk
+++ b/mk/config.mk
@@ -121,7 +121,7 @@ CFG_OS_REV_REPORTS_GIT_SHA1 ?= y
 # with limited depth not including any tag, so there is really no guarantee
 # that TEE_IMPL_VERSION contains the major and minor revision numbers.
 CFG_OPTEE_REVISION_MAJOR ?= 4
-CFG_OPTEE_REVISION_MINOR ?= 0
+CFG_OPTEE_REVISION_MINOR ?= 1
 CFG_OPTEE_REVISION_EXTRA ?=
 
 # Trusted OS implementation version
@@ -359,7 +359,9 @@ $(eval $(call cfg-depends-all,CFG_REE_FS_TA_BUFFERED,CFG_REE_FS_TA))
 # anti-rollback errors. That is, rm /data/tee/dirf.db or rm -rf /data/tee (or
 # whatever path is configured in tee-supplicant as CFG_TEE_FS_PARENT_PATH)
 # can be used to reset the secure storage to a clean, empty state.
-# Typically used for testing only since it weakens storage security.
+# Intended to be used for testing only since it weakens storage security.
+# Warning: If enabled for release build then it will break rollback protection
+# of TAs and the entire REE FS secure storage.
 CFG_REE_FS_ALLOW_RESET ?= n
 
 # Support for loading user TAs from a special section in the TEE binary.
@@ -495,6 +497,19 @@ ifeq ($(CFG_MAP_EXT_DT_SECURE),y)
 $(call force,CFG_DT,y)
 endif
 
+# This option enables OP-TEE to support boot arguments handover via Transfer
+# List defined in Firmware Handoff specification.
+# Note: This is an experimental feature and incompatible ABI changes can be
+# expected. It should be off by default until Firmware Handoff specification
+# has a stable release.
+# This feature requires the support of Device Tree.
+CFG_TRANSFER_LIST ?= n
+ifeq ($(CFG_TRANSFER_LIST),y)
+$(call force,CFG_DT,y)
+$(call force,CFG_EXTERNAL_DT,y)
+$(call force,CFG_MAP_EXT_DT_SECURE,y)
+endif
+
 # Maximum size of the Device Tree Blob, has to be large enough to allow
 # editing of the supplied DTB.
 CFG_DTB_MAX_SIZE ?= 0x10000
@@ -543,6 +558,10 @@ CFG_DRIVERS_CLK_EARLY_PROBE ?= n
 $(call force,CFG_DRIVERS_DT_RECURSIVE_PROBE,n,Mandated by CFG_DT_DRIVER_EMBEDDED_TEST)
 endif
 
+# CFG_WITH_STATS when enabled embeds PTA statistics service to allow non-secure
+# clients to retrieve debug and statistics information on core and loaded TAs.
+CFG_WITH_STATS ?= n
+
 # CFG_DRIVERS_DT_RECURSIVE_PROBE when enabled forces a recursive subnode
 # parsing in the embedded DTB for driver probing. The alternative is
 # an exploration based on compatible drivers found. It is default disabled.
@@ -715,9 +734,20 @@ CFG_CRYPTOLIB_DIR ?= core/lib/libtomcrypt
 # that would set = n.
 $(call force,CFG_CORE_MBEDTLS_MPI,y)
 
-# Enable virtualization support. OP-TEE will not work without compatible
-# hypervisor if this option is enabled.
+# When enabled, CFG_NS_VIRTUALIZATION embeds support for virtualization in
+# the non-secure world. OP-TEE will not work without a compatible hypervisor
+# in the non-secure world if this option is enabled.
+#
+# CFG_VIRTUALIZATION served the same purpose as CFG_NS_VIRTUALIZATION but is
+# deprecated as the configuration switch name was ambiguous regarding which
+# world has virtualization enabled.
+ifneq (undefined,$(flavor CFG_VIRTUALIZATION))
+$(info WARNING: CFG_VIRTUALIZATION is deprecated, use CFG_NS_VIRTUALIZATION instead)
 CFG_NS_VIRTUALIZATION ?= $(CFG_VIRTUALIZATION)
+ifneq ($(CFG_NS_VIRTUALIZATION),$(CFG_VIRTUALIZATION))
+$(error Inconsistent CFG_NS_VIRTUALIZATION=$(CFG_NS_VIRTUALIZATION) and CFG_VIRTUALIZATION=$(CFG_VIRTUALIZATION))
+endif
+endif # CFG_VIRTUALIZATION defined
 CFG_NS_VIRTUALIZATION ?= n
 
 ifeq ($(CFG_NS_VIRTUALIZATION),y)
@@ -859,10 +889,13 @@ CFG_PREALLOC_RPC_CACHE ?= y
 # CFG_DRIVERS_CLK_DT embeds devicetree clock parsing support
 # CFG_DRIVERS_CLK_FIXED add support for "fixed-clock" compatible clocks
 # CFG_DRIVERS_CLK_EARLY_PROBE makes clocks probed at early_init initcall level.
+# CFG_DRIVERS_CLK_PRINT_TREE embeds a helper function to print the clock tree
+# state on OP-TEE core console with the debug trace level.
 CFG_DRIVERS_CLK ?= n
 CFG_DRIVERS_CLK_DT ?= $(call cfg-all-enabled,CFG_DRIVERS_CLK CFG_DT)
 CFG_DRIVERS_CLK_FIXED ?= $(CFG_DRIVERS_CLK_DT)
 CFG_DRIVERS_CLK_EARLY_PROBE ?= $(CFG_DRIVERS_CLK_DT)
+CFG_DRIVERS_CLK_PRINT_TREE ?= n
 
 $(eval $(call cfg-depends-all,CFG_DRIVERS_CLK_DT,CFG_DRIVERS_CLK CFG_DT))
 $(eval $(call cfg-depends-all,CFG_DRIVERS_CLK_FIXED,CFG_DRIVERS_CLK_DT))
@@ -878,6 +911,10 @@ CFG_DRIVERS_GPIO ?= n
 # When enabled, CFG_DRIVERS_I2C provides I2C controller and devices support.
 CFG_DRIVERS_I2C ?= n
 
+# When enabled, CFG_DRIVERS_NVMEM provides a framework to register nvmem
+# providers and allow consumer drivers to get NVMEM cells using the Device Tree.
+CFG_DRIVERS_NVMEM ?= n
+
 # When enabled, CFG_DRIVERS_PINCTRL embeds a pin muxing controller framework in
 # OP-TEE core to provide drivers a way to apply pin muxing configurations based
 # on device-tree.
@@ -889,21 +926,42 @@ CFG_DRIVERS_PINCTRL ?= n
 #
 # When enabled, CFG_REGULATOR_FIXED embeds a voltage regulator driver for
 # DT compatible "regulator-fixed" devices.
+#
+# When enabled, CFG_REGULATOR_GPIO embeds a voltage regulator driver for
+# DT compatible "regulator-gpio" devices.
+#
+# CFG_DRIVERS_REGULATOR_PRINT_TREE embeds a helper function to print the
+# regulator tree state on OP-TEE core console with the info trace level.
 CFG_DRIVERS_REGULATOR ?= n
+CFG_DRIVERS_REGULATOR_PRINT_TREE ?= n
 CFG_REGULATOR_FIXED ?= n
+CFG_REGULATOR_GPIO ?= n
 
 $(eval $(call cfg-enable-all-depends,CFG_REGULATOR_FIXED, \
 	 CFG_DRIVERS_REGULATOR CFG_DT))
+$(eval $(call cfg-enable-all-depends,CFG_REGULATOR_GPIO, \
+	 CFG_DRIVERS_REGULATOR CFG_DT CFG_DRIVERS_GPIO))
 
-# The purpose of this flag is to show a print when booting up the device that
-# indicates whether the board runs a standard developer configuration or not.
-# A developer configuration doesn't necessarily has to be secure. The intention
+# When enabled, CFG_INSECURE permits insecure configuration of OP-TEE core
+# and shows a print (info level) when booting up the device that
+# indicates that the board runs a standard developer configuration.
+#
+# A developer configuration doesn't necessarily have to be secure. The intention
 # is that the one making products based on OP-TEE should override this flag in
 # plat-xxx/conf.mk for the platform they're basing their products on after
 # they've finalized implementing stubbed functionality (see OP-TEE
 # documentation/Porting guidelines) as well as vendor specific security
 # configuration.
-CFG_WARN_INSECURE ?= y
+#
+# CFG_WARN_INSECURE served the same purpose as CFG_INSECURE but is deprecated.
+ifneq (undefined,$(flavor CFG_WARN_INSECURE))
+$(info WARNING: CFG_WARN_INSECURE is deprecated, use CFG_INSECURE instead)
+CFG_INSECURE ?= $(CFG_WARN_INSECURE)
+ifneq ($(CFG_INSECURE),$(CFG_WARN_INSECURE))
+$(error Inconsistent CFG_INSECURE=$(CFG_INSECURE) and CFG_WARN_INSECURE=$(CFG_WARN_INSECURE))
+endif
+endif # CFG_WARN_INSECURE defined
+CFG_INSECURE ?= y
 
 # Enables warnings for declarations mixed with statements
 CFG_WARN_DECL_AFTER_STATEMENT ?= y
@@ -951,11 +1009,19 @@ CFG_PAN ?= n
 
 $(eval $(call cfg-depends-one,CFG_PAN,CFG_ARM64_core CFG_RV64_core CFG_RV32_core))
 
+ifeq ($(filter y, $(CFG_CORE_SEL1_SPMC) $(CFG_CORE_SEL2_SPMC) \
+		  $(CFG_CORE_EL3_SPMC)),y)
+# FF-A case, handled via the FF-A ABI
+CFG_CORE_ASYNC_NOTIF ?= y
+$(call force,_CFG_CORE_ASYNC_NOTIF_DEFAULT_IMPL,n)
+else
 # CFG_CORE_ASYNC_NOTIF is defined by the platform to enable support
-# for sending asynchronous notifications to normal world. Note that an
-# interrupt ID must be configurged by the platform too. Currently is only
+# for sending asynchronous notifications to normal world.
+# Interrupt ID must be configurged by the platform too. Currently is only
 # CFG_CORE_ASYNC_NOTIF_GIC_INTID defined.
 CFG_CORE_ASYNC_NOTIF ?= n
+$(call force,_CFG_CORE_ASYNC_NOTIF_DEFAULT_IMPL,$(CFG_CORE_ASYNC_NOTIF))
+endif
 
 $(eval $(call cfg-enable-all-depends,CFG_MEMPOOL_REPORT_LAST_OFFSET, \
 	 CFG_WITH_STATS))
@@ -1063,3 +1129,23 @@ CFG_HMAC_64_1024_RANGE ?= n
 # By default use standard pbkdf2 implementation
 CFG_CRYPTO_HW_PBKDF2 ?= n
 $(eval $(call cfg-depends-all,CFG_CRYPTO_HW_PBKDF2,CFG_CRYPTO_PBKDF2))
+
+# CFG_HALT_CORES_ON_PANIC, when enabled, makes any call to panic() halt the
+# other cores. The feature currently relies on GIC device to trap the other
+# cores using an SGI interrupt specified by CFG_HALT_CORES_ON_PANIC_SGI.
+CFG_HALT_CORES_ON_PANIC ?= n
+CFG_HALT_CORES_ON_PANIC_SGI ?= 15
+$(eval $(call cfg-depends-all,CFG_HALT_CORES_ON_PANIC,CFG_GIC))
+
+# Enable automatic discovery of maximal PA supported by the hardware and
+# use that. Provides easier configuration of virtual platforms where the
+# maximal PA can vary.
+CFG_AUTO_MAX_PA_BITS ?= n
+
+# CFG_DRIVERS_REMOTEPROC, when enabled, embeds support for remote processor
+# management including generic DT bindings for the configuration.
+CFG_DRIVERS_REMOTEPROC ?= n
+
+# CFG_REMOTEPROC_PTA, when enabled, embeds remote processor management PTA
+# service.
+CFG_REMOTEPROC_PTA ?= n
\ No newline at end of file
diff --git a/scripts/checkpatch_inc.sh b/scripts/checkpatch_inc.sh
index fb77d5ca2f9520e85dfdfeee972e2114aca54d25..166774af53a59d42861e65033424fe77894d5494 100644
--- a/scripts/checkpatch_inc.sh
+++ b/scripts/checkpatch_inc.sh
@@ -23,7 +23,7 @@ function _checkpatch() {
 				typedefs_opt="";
 		# Ignore NOT_UNIFIED_DIFF in case patch has no diff
 		# (e.g., all paths filtered out)
-		$CHECKPATCH $CHECKPATCH_OPT $typedefs_opt -
+		eval "$CHECKPATCH $CHECKPATCH_OPT $typedefs_opt -"
 }
 
 function checkpatch() {
diff --git a/scripts/gen_compile_commands.py b/scripts/gen_compile_commands.py
new file mode 100755
index 0000000000000000000000000000000000000000..1d2b49e91c19d943a29b72e5eb6539dc334a94ba
--- /dev/null
+++ b/scripts/gen_compile_commands.py
@@ -0,0 +1,237 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) Google LLC, 2018
+#
+# Author: Tom Roeder <tmroeder@google.com>
+# Ported and modified for U-Boot by Joao Marcos Costa <jmcosta944@gmail.com>
+# Briefly documented at doc/build/gen_compile_commands.rst
+#
+# Ported and modified for OP-TEE by Joakim Bech <joakim.bech@linaro.org>
+"""A tool for generating compile_commands.json in OP-TEE."""
+
+import argparse
+import json
+import logging
+import os
+import re
+import subprocess
+import sys
+
+_DEFAULT_OUTPUT = 'compile_commands.json'
+_DEFAULT_LOG_LEVEL = 'WARNING'
+
+_FILENAME_PATTERN = r'^\..*\.cmd$'
+_LINE_PATTERN = r'^old-cmd[^ ]* := (?:/usr/bin/ccache )?(.*) -c (\S+)'
+
+_VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
+# The tools/ directory adopts a different build system, and produces .cmd
+# files in a different format. Do not support it.
+_EXCLUDE_DIRS = ['.git', 'Documentation', 'include', 'tools']
+
+
+def parse_arguments():
+    """Sets up and parses command-line arguments.
+
+    Returns:
+        log_level: A logging level to filter log output.
+        directory: The work directory where the objects were built.
+        ar: Command used for parsing .a archives.
+        output: Where to write the compile-commands JSON file.
+        paths: The list of files/directories to handle to find .cmd files.
+    """
+    usage = 'Creates a compile_commands.json database from OP-TEE .cmd files'
+    parser = argparse.ArgumentParser(description=usage)
+
+    directory_help = ('specify the output directory used for the OP-TEE build '
+                      '(defaults to the working directory)')
+    parser.add_argument('-d', '--directory', type=str, default='.',
+                        help=directory_help)
+
+    output_help = ('path to the output command database (defaults to ' +
+                   _DEFAULT_OUTPUT + ')')
+    parser.add_argument('-o', '--output', type=str, default=_DEFAULT_OUTPUT,
+                        help=output_help)
+
+    log_level_help = ('the level of log messages to produce (defaults to ' +
+                      _DEFAULT_LOG_LEVEL + ')')
+    parser.add_argument('--log_level', choices=_VALID_LOG_LEVELS,
+                        default=_DEFAULT_LOG_LEVEL, help=log_level_help)
+
+    ar_help = 'command used for parsing .a archives'
+    parser.add_argument('-a', '--ar', type=str, default='llvm-ar',
+                        help=ar_help)
+
+    paths_help = ('directories to search or files to parse '
+                  '(files should be *.o, *.a, or modules.order). '
+                  'If nothing is specified, the current directory is searched')
+    parser.add_argument('paths', type=str, nargs='*', help=paths_help)
+
+    args = parser.parse_args()
+
+    return (args.log_level,
+            os.path.abspath(args.directory),
+            args.output,
+            args.ar,
+            args.paths if len(args.paths) > 0 else [args.directory])
+
+
+def cmdfiles_in_dir(directory):
+    """Generate the iterator of .cmd files found under the directory.
+
+    Walk under the given directory, and yield every .cmd file found.
+
+    Args:
+        directory: The directory to search for .cmd files.
+
+    Yields:
+        The path to a .cmd file.
+    """
+
+    filename_matcher = re.compile(_FILENAME_PATTERN)
+    exclude_dirs = [os.path.join(directory, d) for d in _EXCLUDE_DIRS]
+
+    for dirpath, dirnames, filenames in os.walk(directory, topdown=True):
+        # Prune unwanted directories.
+        if dirpath in exclude_dirs:
+            dirnames[:] = []
+            continue
+
+        for filename in filenames:
+            if filename_matcher.match(filename):
+                yield os.path.join(dirpath, filename)
+
+
+def to_cmdfile(path):
+    """Return the path of .cmd file used for the given build artifact
+
+    Args:
+        Path: file path
+
+    Returns:
+        The path to .cmd file
+    """
+    dir, base = os.path.split(path)
+    return os.path.join(dir, '.' + base + '.cmd')
+
+
+def cmdfiles_for_a(archive, ar):
+    """Generate the iterator of .cmd files associated with the archive.
+
+    Parse the given archive, and yield every .cmd file used to build it.
+
+    Args:
+        archive: The archive to parse
+
+    Yields:
+        The path to every .cmd file found
+    """
+    for obj in subprocess.check_output([ar, '-t', archive]).decode().split():
+        yield to_cmdfile(obj)
+
+
+def cmdfiles_for_modorder(modorder):
+    """Generate the iterator of .cmd files associated with the modules.order.
+
+    Parse the given modules.order, and yield every .cmd file used to build the
+    contained modules.
+
+    Args:
+        modorder: The modules.order file to parse
+
+    Yields:
+        The path to every .cmd file found
+    """
+    with open(modorder) as f:
+        for line in f:
+            obj = line.rstrip()
+            base, ext = os.path.splitext(obj)
+            if ext != '.o':
+                sys.exit('{}: module path must end with .o'.format(obj))
+            mod = base + '.mod'
+            # Read from *.mod, to get a list of objects that compose the
+            # module.
+            with open(mod) as m:
+                for mod_line in m:
+                    yield to_cmdfile(mod_line.rstrip())
+
+
+def process_line(root_directory, command_prefix, file_path):
+    """Extracts information from a .cmd line and creates an entry from it.
+
+    Args:
+        root_directory: The directory that was searched for .cmd files. Usually
+            used directly in the "directory" entry in compile_commands.json.
+        command_prefix: The extracted command line, up to the last element.
+        file_path: The .c file from the end of the extracted command.
+            Usually relative to root_directory, but sometimes absolute.
+
+    Returns:
+        An entry to append to compile_commands.
+
+    Raises:
+        ValueError: Could not find the extracted file based on file_path and
+            root_directory or file_directory.
+    """
+    # The .cmd files are intended to be included directly by Make, so they
+    # escape the pound sign '#', either as '\#' or '$(pound)' (depending on the
+    # kernel version). The compile_commands.json file is not interpreted
+    # by Make, so this code replaces the escaped version with '#'.
+    prefix = command_prefix.replace('\#', '#').replace('$(pound)', '#')  # noqa: W605
+
+    # Use os.path.abspath() to normalize the path resolving '.' and '..' .
+    abs_path = os.path.abspath(os.path.join(root_directory, file_path))
+    if not os.path.exists(abs_path):
+        raise ValueError('File %s not found' % abs_path)
+    return {
+        'directory': root_directory,
+        'file': abs_path,
+        'command': prefix + file_path,
+    }
+
+
+def main():
+    """Walks through the directory and finds and parses .cmd files."""
+    log_level, directory, output, ar, paths = parse_arguments()
+
+    level = getattr(logging, log_level)
+    logging.basicConfig(format='%(levelname)s: %(message)s', level=level)
+
+    line_matcher = re.compile(_LINE_PATTERN)
+
+    compile_commands = []
+
+    for path in paths:
+        # If 'path' is a directory, handle all .cmd files under it.
+        # Otherwise, handle .cmd files associated with the file.
+        # built-in objects are linked via vmlinux.a
+        # Modules are listed in modules.order.
+        if os.path.isdir(path):
+            cmdfiles = cmdfiles_in_dir(path)
+        elif path.endswith('.a'):
+            cmdfiles = cmdfiles_for_a(path, ar)
+        elif path.endswith('modules.order'):
+            cmdfiles = cmdfiles_for_modorder(path)
+        else:
+            sys.exit('{}: unknown file type'.format(path))
+
+        for cmdfile in cmdfiles:
+            with open(cmdfile, 'rt') as f:
+                try:
+                    result = line_matcher.match(f.readline())
+                    if result:
+                        entry = process_line(directory, result.group(1),
+                                             result.group(2))
+                        compile_commands.append(entry)
+                except ValueError as err:
+                    logging.info('Could not add line from %s: %s',
+                                 cmdfile, err)
+                except AttributeError as err:
+                    continue
+
+    with open(output, 'wt') as f:
+        json.dump(compile_commands, f, indent=2, sort_keys=True)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/scripts/symbolize.py b/scripts/symbolize.py
index 2a7843433d5dc7402f1d3a5ac3b74291b510c8c1..87b2466034fabf7cd01de0e349256fe083f7ddbc 100755
--- a/scripts/symbolize.py
+++ b/scripts/symbolize.py
@@ -19,7 +19,7 @@ TEE_LOAD_ADDR_RE = re.compile(r'TEE load address @ (?P<load_addr>0x[0-9a-f]+)')
 # This gets the address from lines looking like this:
 # E/TC:0  0x001044a8
 STACK_ADDR_RE = re.compile(
-    r'[UEIDFM]/(TC|LD):(\?*|[0-9]*) [0-9]* +(?P<addr>0x[0-9a-f]+)')
+    r'[UEIDFM]/(TC|LD):([0-9]+ )?(\?*|[0-9]*) [0-9]* +(?P<addr>0x[0-9a-f]+)')
 ABORT_ADDR_RE = re.compile(r'-abort at address (?P<addr>0x[0-9a-f]+)')
 TA_PANIC_RE = re.compile(r'TA panicked with code (?P<code>0x[0-9a-f]+)')
 REGION_RE = re.compile(r'region +[0-9]+: va (?P<addr>0x[0-9a-f]+) '
diff --git a/ta/pkcs11/src/object.c b/ta/pkcs11/src/object.c
index 053237bc346a12256f6a0095077cd0e520818263..bbd2b682288f4f3932aab9825bea80b25db169ac 100644
--- a/ta/pkcs11/src/object.c
+++ b/ta/pkcs11/src/object.c
@@ -352,6 +352,11 @@ enum pkcs11_rc entry_create_object(struct pkcs11_client *client,
 	if (rc)
 		goto out;
 
+	/* Set key check value attribute */
+	rc = set_check_value_attr(&head);
+	if (rc)
+		goto out;
+
 	/*
 	 * Check target object attributes match target processing
 	 * Check target object attributes match token state
@@ -983,6 +988,8 @@ enum pkcs11_rc entry_set_attribute_value(struct pkcs11_client *client,
 	size_t template_size = 0;
 	struct pkcs11_object *obj = NULL;
 	struct obj_attrs *head = NULL;
+	struct obj_attrs *head_new = NULL;
+	struct obj_attrs *head_old = NULL;
 	uint32_t object_handle = 0;
 	enum processing_func function = PKCS11_FUNCTION_MODIFY;
 
@@ -1056,25 +1063,50 @@ enum pkcs11_rc entry_set_attribute_value(struct pkcs11_client *client,
 	if (rc)
 		goto out;
 
+	/* Create new object attributes to modify */
+	template_size = sizeof(*obj->attributes) + obj->attributes->attrs_size;
+	head_new = TEE_Malloc(template_size, TEE_MALLOC_FILL_ZERO);
+	if (!head_new) {
+		rc = PKCS11_CKR_DEVICE_MEMORY;
+		goto out;
+	}
+
+	TEE_MemMove(head_new, obj->attributes, template_size);
+
 	/*
 	 * All checks complete. The attributes in @head have been checked and
 	 * can now be used to set/modify the object attributes.
 	 */
-	rc = modify_attributes_list(&obj->attributes, head);
+	rc = modify_attributes_list(&head_new, head);
+	if (rc)
+		goto out;
+
+	/* Set key check value attribute */
+	rc = set_check_value_attr(&head_new);
 	if (rc)
 		goto out;
 
+	/* Update the object */
+	head_old = obj->attributes;
+	obj->attributes = head_new;
+	head_new = NULL;
+
 	if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) {
 		rc = update_persistent_object_attributes(obj);
-		if (rc)
+		if (rc) {
+			obj->attributes = head_old;
 			goto out;
+		}
 	}
 
+	TEE_Free(head_old);
+
 	DMSG("PKCS11 session %"PRIu32": set attributes %#"PRIx32,
 	     session->handle, object_handle);
 
 out:
 	TEE_Free(head);
+	TEE_Free(head_new);
 	TEE_Free(template);
 	return rc;
 }
@@ -1216,6 +1248,11 @@ enum pkcs11_rc entry_copy_object(struct pkcs11_client *client, uint32_t ptypes,
 	if (rc)
 		goto out;
 
+	/* Set key check value attribute */
+	rc = set_check_value_attr(&head_new);
+	if (rc)
+		goto out;
+
 	/*
 	 * At this stage the object is almost created: all its attributes are
 	 * referenced in @head_new, including the key value and are assumed
diff --git a/ta/pkcs11/src/pkcs11_attributes.c b/ta/pkcs11/src/pkcs11_attributes.c
index aef712ee55bc323d94e3640d827ff357a829336c..c0e9d7c51e9f8063dea982f6cff3261a4df4c739 100644
--- a/ta/pkcs11/src/pkcs11_attributes.c
+++ b/ta/pkcs11/src/pkcs11_attributes.c
@@ -4,6 +4,7 @@
  */
 
 #include <assert.h>
+#include <config.h>
 #include <inttypes.h>
 #include <mbedtls/asn1write.h>
 #include <mbedtls/ecp.h>
@@ -355,8 +356,12 @@ static const uint32_t pkcs11_certificate_boolprops[] = {
 };
 
 static const uint32_t pkcs11_certificate_optional[] = {
-	PKCS11_CKA_CERTIFICATE_CATEGORY, PKCS11_CKA_CHECK_VALUE,
-	PKCS11_CKA_START_DATE, PKCS11_CKA_END_DATE, PKCS11_CKA_PUBLIC_KEY_INFO,
+	PKCS11_CKA_CERTIFICATE_CATEGORY, PKCS11_CKA_START_DATE,
+	PKCS11_CKA_END_DATE, PKCS11_CKA_PUBLIC_KEY_INFO,
+#ifdef CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE
+	/* Consider KCV attribute only when supported */
+	PKCS11_CKA_CHECK_VALUE,
+#endif
 };
 
 /*
@@ -404,6 +409,10 @@ static const uint32_t symm_key_opt_or_null[] = {
 
 static const uint32_t symm_key_optional[] = {
 	PKCS11_CKA_VALUE_LEN,
+#ifdef CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE
+	/* Consider KCV attribute only when supported */
+	PKCS11_CKA_CHECK_VALUE,
+#endif
 };
 
 /* PKCS#11 specification for any asymmetric public key (+any_key_xxx) */
@@ -2173,6 +2182,7 @@ static bool attr_is_modifiable_secret_key(struct pkcs11_attribute_head *attr,
 	case PKCS11_CKA_VERIFY:
 	case PKCS11_CKA_WRAP:
 	case PKCS11_CKA_UNWRAP:
+	case PKCS11_CKA_CHECK_VALUE:
 		return true;
 	/* Can't be modified once set to CK_FALSE - 12 in Table 10 */
 	case PKCS11_CKA_EXTRACTABLE:
@@ -2478,7 +2488,11 @@ static enum pkcs11_rc set_secret_key_data(struct obj_attrs **head, void *data,
 	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
 		return PKCS11_CKR_GENERAL_ERROR;
 
-	return add_attribute(head, PKCS11_CKA_VALUE, data, key_length);
+	rc = add_attribute(head, PKCS11_CKA_VALUE, data, key_length);
+	if (rc)
+		return rc;
+
+	return set_check_value_attr(head);
 }
 
 static enum pkcs11_rc set_private_key_data_rsa(struct obj_attrs **head,
@@ -2827,3 +2841,188 @@ enum pkcs11_rc add_missing_attribute_id(struct obj_attrs **pub_head,
 	else
 		return set_attribute(pub_head, PKCS11_CKA_ID, id2, id2_size);
 }
+
+/*
+ * The key check value is derived from the object by taking the first
+ * three bytes of the SHA-1 hash of the object's CKA_VALUE attribute.
+ */
+static enum pkcs11_rc compute_check_value_with_sha1(void *key,
+						    uint32_t key_size,
+						    void *kcv)
+{
+	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	TEE_OperationHandle op = TEE_HANDLE_NULL;
+	size_t buf_size = TEE_MAX_HASH_SIZE;
+	uint8_t *buf = NULL;
+
+	assert(key && kcv);
+
+	res = TEE_AllocateOperation(&op, TEE_ALG_SHA1, TEE_MODE_DIGEST, 0);
+	rc = tee2pkcs_error(res);
+	if (rc != PKCS11_CKR_OK)
+		goto out;
+
+	buf = TEE_Malloc(buf_size, TEE_MALLOC_FILL_ZERO);
+	if (!buf) {
+		rc = PKCS11_CKR_DEVICE_MEMORY;
+		goto out;
+	}
+
+	res = TEE_DigestDoFinal(op, key, key_size, buf, &buf_size);
+	rc = tee2pkcs_error(res);
+	if (rc != PKCS11_CKR_OK)
+		goto out;
+
+	TEE_MemMove(kcv, buf, PKCS11_CKA_CHECK_VALUE_SIZE);
+
+out:
+	TEE_Free(buf);
+	TEE_FreeOperation(op);
+
+	return rc;
+}
+
+/*
+ * The key check value that is calculated as follows:
+ * 1) Take a buffer of the cipher block size of binary zeros (0x00).
+ * 2) Encrypt this block in ECB mode.
+ * 3) Take the first three bytes of cipher text as the check value.
+ */
+static enum pkcs11_rc compute_check_value_with_ecb(void *key, uint32_t key_size,
+						   void *kcv)
+{
+	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	TEE_OperationHandle op = TEE_HANDLE_NULL;
+	TEE_ObjectHandle hkey = TEE_HANDLE_NULL;
+	TEE_Attribute attr = { };
+	uint8_t buf[TEE_AES_BLOCK_SIZE] = { };
+	size_t buf_size = sizeof(buf);
+
+	assert(key && kcv);
+
+	res = TEE_AllocateOperation(&op, TEE_ALG_AES_ECB_NOPAD,
+				    TEE_MODE_ENCRYPT, key_size * 8);
+	rc = tee2pkcs_error(res);
+	if (rc != PKCS11_CKR_OK)
+		goto out;
+
+	res = TEE_AllocateTransientObject(TEE_TYPE_AES, key_size * 8, &hkey);
+	rc = tee2pkcs_error(res);
+	if (rc != PKCS11_CKR_OK)
+		goto out;
+
+	TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, key, key_size);
+
+	res = TEE_PopulateTransientObject(hkey, &attr, 1);
+	rc = tee2pkcs_error(res);
+	if (rc != PKCS11_CKR_OK)
+		goto out;
+
+	res = TEE_SetOperationKey(op, hkey);
+	rc = tee2pkcs_error(res);
+	if (rc != PKCS11_CKR_OK)
+		goto out;
+
+	TEE_CipherInit(op, NULL, 0);
+
+	res = TEE_CipherDoFinal(op, buf, buf_size, buf, &buf_size);
+	rc = tee2pkcs_error(res);
+	if (rc != PKCS11_CKR_OK)
+		goto out;
+
+	TEE_MemMove(kcv, buf, PKCS11_CKA_CHECK_VALUE_SIZE);
+
+out:
+	TEE_FreeTransientObject(hkey);
+	TEE_FreeOperation(op);
+
+	return rc;
+}
+
+enum pkcs11_rc set_check_value_attr(struct obj_attrs **head)
+{
+	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
+	uint32_t val_len = 0;
+	uint32_t kcv2_len = 0;
+	void *val = NULL;
+	uint8_t kcv[PKCS11_CKA_CHECK_VALUE_SIZE] = { };
+	void *kcv2 = NULL;
+
+	assert(head && *head);
+
+	if (!IS_ENABLED(CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE))
+		return PKCS11_CKR_OK;
+
+	switch (get_class(*head)) {
+	case PKCS11_CKO_SECRET_KEY:
+	case PKCS11_CKO_CERTIFICATE:
+		break;
+	default:
+		/* Nothing to do */
+		return PKCS11_CKR_OK;
+	}
+
+	/* Check whether CKA_CHECK_VALUE has been provided in the template */
+	rc = get_attribute_ptr(*head, PKCS11_CKA_CHECK_VALUE, &kcv2, &kcv2_len);
+
+	if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
+		return PKCS11_CKR_GENERAL_ERROR;
+
+	/*
+	 * The generation of the KCV may be prevented by the application
+	 * supplying the attribute in the template as a no-value (0 length)
+	 * entry.
+	 */
+	if (rc == PKCS11_CKR_OK && !kcv2_len)
+		return PKCS11_CKR_OK;
+
+	if (rc == PKCS11_CKR_OK && kcv2_len != PKCS11_CKA_CHECK_VALUE_SIZE)
+		return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
+
+	/* Get key CKA_VALUE */
+	rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE, &val, &val_len);
+	if (rc)
+		return rc;
+
+	if (get_class(*head) == PKCS11_CKO_SECRET_KEY) {
+		switch (get_key_type(*head)) {
+		case PKCS11_CKK_AES:
+			rc = compute_check_value_with_ecb(val, val_len, kcv);
+			break;
+		case PKCS11_CKK_GENERIC_SECRET:
+		case PKCS11_CKK_MD5_HMAC:
+		case PKCS11_CKK_SHA_1_HMAC:
+		case PKCS11_CKK_SHA256_HMAC:
+		case PKCS11_CKK_SHA384_HMAC:
+		case PKCS11_CKK_SHA512_HMAC:
+		case PKCS11_CKK_SHA224_HMAC:
+			rc = compute_check_value_with_sha1(val, val_len, kcv);
+			break;
+		default:
+			rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
+			break;
+		}
+	} else {
+		rc = compute_check_value_with_sha1(val, val_len, kcv);
+	}
+
+	if (rc)
+		return rc;
+
+	/*
+	 * If the computed KCV does not match the provided one
+	 * then return CKR_ATTRIBUTE_VALUE_INVALID
+	 */
+	if (kcv2_len) {
+		/* Provided KCV value shall match the computed one */
+		if (TEE_MemCompare(kcv2, kcv, PKCS11_CKA_CHECK_VALUE_SIZE))
+			rc = PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
+	} else {
+		rc = add_attribute(head, PKCS11_CKA_CHECK_VALUE, kcv,
+				   PKCS11_CKA_CHECK_VALUE_SIZE);
+	}
+
+	return rc;
+}
diff --git a/ta/pkcs11/src/pkcs11_attributes.h b/ta/pkcs11/src/pkcs11_attributes.h
index 1834b430db4ca0dd916f696c4b3dc16865649d74..60cff66e731a056eb3a523f5a66498b93493dc5d 100644
--- a/ta/pkcs11/src/pkcs11_attributes.h
+++ b/ta/pkcs11/src/pkcs11_attributes.h
@@ -11,6 +11,9 @@
 
 #include "serializer.h"
 
+/* The key check value (KCV) attribute for objects is 3 bytes */
+#define PKCS11_CKA_CHECK_VALUE_SIZE	U(3)
+
 struct obj_attrs;
 struct pkcs11_object;
 struct pkcs11_session;
@@ -214,5 +217,11 @@ enum pkcs11_rc alloc_key_data_to_wrap(struct obj_attrs *head, void **data,
  */
 enum pkcs11_rc add_missing_attribute_id(struct obj_attrs **pub_head,
 					struct obj_attrs **priv_head);
+/*
+ * Check an object's check value (Checksum)
+ * @head: Object attribute where to find KCV to be checked
+ * Return a pkcs11_rv compliant value
+ */
+enum pkcs11_rc set_check_value_attr(struct obj_attrs **head);
 
 #endif /*PKCS11_TA_PKCS11_ATTRIBUTES_H*/
diff --git a/ta/pkcs11/src/pkcs11_token.c b/ta/pkcs11/src/pkcs11_token.c
index ab0fc291ef4ba17e4fe23412037755a6f1fdc947..2633b369723b495991193fcd338171b2248ebc6a 100644
--- a/ta/pkcs11/src/pkcs11_token.c
+++ b/ta/pkcs11/src/pkcs11_token.c
@@ -1132,117 +1132,117 @@ static enum pkcs11_rc check_so_pin(struct pkcs11_session *session,
 				   uint8_t *pin, size_t pin_size)
 {
 	struct ck_token *token = session->token;
+	struct token_persistent_main *db = token->db_main;
 	enum pkcs11_rc rc = PKCS11_CKR_OK;
 
-	assert(token->db_main->flags & PKCS11_CKFT_TOKEN_INITIALIZED);
+	assert(db->flags & PKCS11_CKFT_TOKEN_INITIALIZED);
 
 	if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) &&
-	    token->db_main->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH)
+	    db->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH)
 		return verify_identity_auth(token, PKCS11_CKU_SO);
 
-	if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED)
+	if (db->flags & PKCS11_CKFT_SO_PIN_LOCKED)
 		return PKCS11_CKR_PIN_LOCKED;
 
-	rc = verify_pin(PKCS11_CKU_SO, pin, pin_size,
-			token->db_main->so_pin_salt,
-			token->db_main->so_pin_hash);
-	if (rc) {
-		unsigned int pin_count = 0;
-
-		if (rc != PKCS11_CKR_PIN_INCORRECT)
-			return rc;
-
-		token->db_main->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW;
-		token->db_main->so_pin_count++;
+	/*
+	 * Preset the counter and flags conservatively in the database so that
+	 * the tentative is saved whatever happens next.
+	 */
+	db->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW;
+	db->so_pin_count++;
 
-		pin_count = token->db_main->so_pin_count;
-		if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1)
-			token->db_main->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY;
-		if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX)
-			token->db_main->flags |= PKCS11_CKFT_SO_PIN_LOCKED;
+	if (db->so_pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1)
+		db->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY;
+	else if (db->so_pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX)
+		db->flags |= PKCS11_CKFT_SO_PIN_LOCKED;
 
-		update_persistent_db(token);
+	update_persistent_db(token);
 
-		if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED)
+	rc = verify_pin(PKCS11_CKU_SO, pin, pin_size,
+			db->so_pin_salt,
+			db->so_pin_hash);
+	if (rc == PKCS11_CKR_PIN_INCORRECT) {
+		if (db->flags & PKCS11_CKFT_SO_PIN_LOCKED)
 			return PKCS11_CKR_PIN_LOCKED;
 
 		return PKCS11_CKR_PIN_INCORRECT;
 	}
 
-	if (token->db_main->so_pin_count) {
-		token->db_main->so_pin_count = 0;
+	if (rc)
+		db->so_pin_count--;
+	else
+		db->so_pin_count = 0;
 
-		update_persistent_db(token);
+	db->flags &= ~PKCS11_CKFT_SO_PIN_LOCKED;
+	if (db->so_pin_count < PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1) {
+		db->flags &= ~PKCS11_CKFT_SO_PIN_FINAL_TRY;
+		if (!db->so_pin_count)
+			db->flags &= ~PKCS11_CKFT_SO_PIN_COUNT_LOW;
 	}
 
-	if (token->db_main->flags & (PKCS11_CKFT_SO_PIN_COUNT_LOW |
-				     PKCS11_CKFT_SO_PIN_FINAL_TRY)) {
-		token->db_main->flags &= ~(PKCS11_CKFT_SO_PIN_COUNT_LOW |
-					   PKCS11_CKFT_SO_PIN_FINAL_TRY);
-
-		update_persistent_db(token);
-	}
+	update_persistent_db(token);
 
-	return PKCS11_CKR_OK;
+	return rc;
 }
 
 static enum pkcs11_rc check_user_pin(struct pkcs11_session *session,
 				     uint8_t *pin, size_t pin_size)
 {
 	struct ck_token *token = session->token;
+	struct token_persistent_main *db = token->db_main;
 	enum pkcs11_rc rc = PKCS11_CKR_OK;
 
+	if (!(db->flags & PKCS11_CKFT_USER_PIN_INITIALIZED))
+		return PKCS11_CKR_USER_PIN_NOT_INITIALIZED;
+
 	if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) &&
-	    token->db_main->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH)
+	    db->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH)
 		return verify_identity_auth(token, PKCS11_CKU_USER);
 
-	if (!token->db_main->user_pin_salt)
-		return PKCS11_CKR_USER_PIN_NOT_INITIALIZED;
+	assert(db->user_pin_salt);
 
-	if (token->db_main->flags & PKCS11_CKFT_USER_PIN_LOCKED)
+	if (db->flags & PKCS11_CKFT_USER_PIN_LOCKED)
 		return PKCS11_CKR_PIN_LOCKED;
 
-	rc = verify_pin(PKCS11_CKU_USER, pin, pin_size,
-			token->db_main->user_pin_salt,
-			token->db_main->user_pin_hash);
-	if (rc) {
-		unsigned int pin_count = 0;
-
-		if (rc != PKCS11_CKR_PIN_INCORRECT)
-			return rc;
-
-		token->db_main->flags |= PKCS11_CKFT_USER_PIN_COUNT_LOW;
-		token->db_main->user_pin_count++;
+	/*
+	 * Preset the counter and flags conservatively in the database so that
+	 * the tentative is saved whatever happens next.
+	 */
+	db->flags |= PKCS11_CKFT_USER_PIN_COUNT_LOW;
+	db->user_pin_count++;
 
-		pin_count = token->db_main->user_pin_count;
-		if (pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1)
-			token->db_main->flags |= PKCS11_CKFT_USER_PIN_FINAL_TRY;
-		if (pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX)
-			token->db_main->flags |= PKCS11_CKFT_USER_PIN_LOCKED;
+	if (db->user_pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1)
+		db->flags |= PKCS11_CKFT_USER_PIN_FINAL_TRY;
+	else if (db->user_pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX)
+		db->flags |= PKCS11_CKFT_USER_PIN_LOCKED;
 
-		update_persistent_db(token);
+	update_persistent_db(token);
 
-		if (token->db_main->flags & PKCS11_CKFT_USER_PIN_LOCKED)
+	rc = verify_pin(PKCS11_CKU_USER, pin, pin_size,
+			db->user_pin_salt,
+			db->user_pin_hash);
+	if (rc == PKCS11_CKR_PIN_INCORRECT) {
+		if (db->flags & PKCS11_CKFT_USER_PIN_LOCKED)
 			return PKCS11_CKR_PIN_LOCKED;
 
 		return PKCS11_CKR_PIN_INCORRECT;
 	}
 
-	if (token->db_main->user_pin_count) {
-		token->db_main->user_pin_count = 0;
+	if (rc)
+		db->user_pin_count--;
+	else
+		db->user_pin_count = 0;
 
-		update_persistent_db(token);
+	db->flags &= ~PKCS11_CKFT_USER_PIN_LOCKED;
+	if (db->user_pin_count < PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1) {
+		db->flags &= ~PKCS11_CKFT_USER_PIN_FINAL_TRY;
+		if (!db->user_pin_count)
+			db->flags &= ~PKCS11_CKFT_USER_PIN_COUNT_LOW;
 	}
 
-	if (token->db_main->flags & (PKCS11_CKFT_USER_PIN_COUNT_LOW |
-				     PKCS11_CKFT_USER_PIN_FINAL_TRY)) {
-		token->db_main->flags &= ~(PKCS11_CKFT_USER_PIN_COUNT_LOW |
-					   PKCS11_CKFT_USER_PIN_FINAL_TRY);
-
-		update_persistent_db(token);
-	}
+	update_persistent_db(token);
 
-	return PKCS11_CKR_OK;
+	return rc;
 }
 
 enum pkcs11_rc entry_ck_set_pin(struct pkcs11_client *client,
diff --git a/ta/pkcs11/src/processing.c b/ta/pkcs11/src/processing.c
index 6be34829db24d4e0b61c15e00fdcfc15702b0552..0fc26b37597b0c4936cada804b84ee8eb0d8bef2 100644
--- a/ta/pkcs11/src/processing.c
+++ b/ta/pkcs11/src/processing.c
@@ -166,10 +166,10 @@ size_t get_object_key_bit_size(struct pkcs11_object *obj)
 static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head)
 {
 	enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
-	void *data = NULL;
 	uint32_t data_size = 0;
 	uint32_t value_len = 0;
 	void *value = NULL;
+	void *data = NULL;
 
 	if (!*head)
 		return PKCS11_CKR_TEMPLATE_INCONSISTENT;
@@ -196,6 +196,9 @@ static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head)
 
 	rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len);
 
+	if (rc == PKCS11_CKR_OK)
+		rc = set_check_value_attr(head);
+
 	TEE_Free(value);
 
 	return rc;
diff --git a/ta/pkcs11/sub.mk b/ta/pkcs11/sub.mk
index 30dd13cb53395b56d214a93aa2233821f181d79b..aa66ee0ef0429c3f54412fd9b71fb5ee49282d42 100644
--- a/ta/pkcs11/sub.mk
+++ b/ta/pkcs11/sub.mk
@@ -10,6 +10,9 @@ CFG_PKCS11_TA_HEAP_SIZE ?= (32 * 1024)
 # Defines the number of PKCS11 token implemented by the PKCS11 TA
 CFG_PKCS11_TA_TOKEN_COUNT ?= 3
 
+# When enabled, embed support for object checksum value computation
+CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE ?= y
+
 global-incdirs-y += include
 global-incdirs-y += src
 subdirs-y += src
diff --git a/ta/remoteproc/Makefile b/ta/remoteproc/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..0d1a5010ca58cdaff2406360fdc1c8da28ac9fbe
--- /dev/null
+++ b/ta/remoteproc/Makefile
@@ -0,0 +1,18 @@
+# The UUID for the Trusted Application
+BINARY=80a4c275-0a47-4905-8285-1486a9771a08
+
+ifdef TA_CROSS_COMPILE
+CROSS_COMPILE ?= $(TA_CROSS_COMPILE)
+endif
+export CROSS_COMPILE
+
+CFG_TEE_TA_LOG_LEVEL ?= 2
+CPPFLAGS += -DCFG_TEE_TA_LOG_LEVEL=$(CFG_TEE_TA_LOG_LEVEL)
+
+-include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk
+
+ifeq ($(wildcard $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk), )
+clean:
+	@echo 'Note: $$(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk not found, cannot clean TA'
+	@echo 'Note: TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR)'
+endif
diff --git a/ta/remoteproc/include/ta_remoteproc.h b/ta/remoteproc/include/ta_remoteproc.h
new file mode 100644
index 0000000000000000000000000000000000000000..71a15451568eef0f30fa9710700b2fa462393882
--- /dev/null
+++ b/ta/remoteproc/include/ta_remoteproc.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2023, STMicroelectronics
+ */
+
+#ifndef TA_REMOTEPROC_H
+#define TA_REMOTEPROC_H
+
+/*
+ * This UUID is generated with uuidgen
+ * the ITU-T UUID generator at http://www.itu.int/ITU-T/asn1/uuid.html
+ */
+#define TA_REMOTEPROC_UUID { 0x80a4c275, 0x0a47, 0x4905, \
+			     { 0x82, 0x85, 0x14, 0x86, 0xa9, 0x77, 0x1a, 0x08} }
+
+/* The command IDs implemented in this TA */
+
+/*
+ * Authentication of the firmware and load in the remote processor memory.
+ *
+ * [in]  params[0].value.a:	Unique 32bit remote processor identifier
+ * [in]  params[1].memref:	buffer containing the image of the firmware
+ */
+#define TA_RPROC_CMD_LOAD_FW		1
+
+/*
+ * Start the remote processor.
+ *
+ * [in]  params[0].value.a:	Unique 32bit remote processor identifier
+ */
+#define TA_RPROC_CMD_START_FW		2
+
+/*
+ * Stop the remote processor.
+ *
+ * [in]  params[0].value.a:	Unique 32bit remote processor identifier
+ */
+#define TA_RPROC_CMD_STOP_FW		3
+
+/*
+ * Return the physical address of the resource table, or 0 if not found
+ * No check is done to verify that the address returned is accessible by the
+ * non-secure world. If the resource table is loaded in a protected memory,
+ * then accesses from non-secure world will likely fail.
+ *
+ * [in]  params[0].value.a:	Unique 32bit remote processor identifier
+ * [out] params[1].value.a:	32bit LSB resource table memory address
+ * [out] params[1].value.b:	32bit MSB resource table memory address
+ * [out] params[2].value.a:	32bit LSB resource table memory size
+ * [out] params[2].value.b:	32bit MSB resource table memory size
+ */
+#define TA_RPROC_CMD_GET_RSC_TABLE	4
+
+/*
+ * Get remote processor firmware core dump. If found, return either
+ * TEE_SUCCESS on successful completion or TEE_ERROR_SHORT_BUFFER if output
+ * buffer is too short to store the core dump.
+ *
+ * [in]  params[0].value.a:	Unique 32bit remote processor identifier
+ * [out] params[1].memref:	Core dump, if found
+ */
+#define TA_RPROC_CMD_GET_COREDUMP	5
+
+#endif /*TA_REMOTEPROC_H*/
diff --git a/ta/remoteproc/src/elf_parser.c b/ta/remoteproc/src/elf_parser.c
new file mode 100644
index 0000000000000000000000000000000000000000..0cd0bc67d8c187551328d6dffe1fd6c5ba5a1f21
--- /dev/null
+++ b/ta/remoteproc/src/elf_parser.c
@@ -0,0 +1,175 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2023, STMicroelectronics
+ */
+
+#include <assert.h>
+#include <elf_parser.h>
+#include <string.h>
+#include <trace.h>
+#include <types_ext.h>
+#include <util.h>
+
+static bool va_in_fwm_image_range(void *va, uint8_t *fw, size_t fw_size)
+{
+	uint8_t *vaddr = va;
+
+	return vaddr >= fw && vaddr < fw + fw_size;
+}
+
+TEE_Result e32_parse_ehdr(uint8_t *fw, size_t size)
+{
+	Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(void *)fw;
+
+	if (!fw || !IS_ALIGNED_WITH_TYPE(fw, uint32_t)) {
+		EMSG("Invalid firmware address");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	if (size < sizeof(Elf32_Ehdr) ||
+	    size < (ehdr->e_shoff + sizeof(Elf32_Shdr)))
+		return TEE_ERROR_BAD_FORMAT;
+
+	if (!IS_ELF(*ehdr) ||
+	    ehdr->e_ident[EI_VERSION] != EV_CURRENT ||
+	    ehdr->e_ident[EI_CLASS] != ELFCLASS32 ||
+	    ehdr->e_phentsize != sizeof(Elf32_Phdr) ||
+	    ehdr->e_shentsize != sizeof(Elf32_Shdr)) {
+		EMSG("Invalid header");
+		return TEE_ERROR_BAD_FORMAT;
+	}
+
+	if (ehdr->e_phnum == 0) {
+		EMSG("No loadable segment found");
+		return TEE_ERROR_BAD_FORMAT;
+	}
+
+	return TEE_SUCCESS;
+}
+
+TEE_Result e32_parser_load_elf_image(uint8_t *fw, size_t fw_size,
+				     TEE_Result (*load_seg)(uint8_t *src,
+							    uint32_t size,
+							    uint32_t da,
+							    uint32_t mem_size,
+							    void *priv),
+				     void *priv_data)
+{
+	Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(void *)fw;
+	Elf32_Phdr *phdr = (void *)((int8_t *)ehdr + ehdr->e_phoff);
+	TEE_Result res = TEE_SUCCESS;
+	unsigned int i = 0;
+
+	if (!load_seg || fw + fw_size <= fw)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (!IS_ALIGNED_WITH_TYPE(phdr, uint32_t) ||
+	    !va_in_fwm_image_range(phdr, fw, fw_size))
+		return TEE_ERROR_BAD_FORMAT;
+
+	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
+		uint32_t dst = phdr->p_paddr;
+		uint8_t *src = NULL;
+
+		if (phdr->p_type != PT_LOAD)
+			continue;
+
+		if (!va_in_fwm_image_range((void *)((vaddr_t)(phdr + 1) - 1),
+					   fw, fw_size))
+			return TEE_ERROR_BAD_FORMAT;
+
+		src = (uint8_t *)fw + phdr->p_offset;
+
+		if (!va_in_fwm_image_range(src, fw, fw_size) ||
+		    !va_in_fwm_image_range(src + phdr->p_filesz, fw, fw_size))
+			return TEE_ERROR_BAD_FORMAT;
+
+		res = load_seg(src, phdr->p_filesz, dst, phdr->p_memsz,
+			       priv_data);
+		if (res)
+			return res;
+	}
+
+	return TEE_SUCCESS;
+}
+
+TEE_Result e32_parser_find_rsc_table(uint8_t *fw, size_t fw_size,
+				     Elf32_Addr *rsc_addr,
+				     Elf32_Word *rsc_size)
+{
+	Elf32_Shdr *shdr = NULL;
+	unsigned int i = 0;
+	char *name_table = NULL;
+	struct resource_table *table = NULL;
+	Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(void *)fw;
+	uint8_t *elf_data = fw;
+
+	if (fw + fw_size <= fw || fw + ehdr->e_shoff < fw)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	shdr = (void *)(fw + ehdr->e_shoff);
+	if (!IS_ALIGNED_WITH_TYPE(shdr, uint32_t) ||
+	    !va_in_fwm_image_range(shdr, fw, fw_size))
+		return TEE_ERROR_BAD_FORMAT;
+
+	name_table = (char *)elf_data + shdr[ehdr->e_shstrndx].sh_offset;
+	if (!va_in_fwm_image_range(name_table, fw, fw_size))
+		return TEE_ERROR_BAD_FORMAT;
+
+	for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
+		size_t size = shdr->sh_size;
+		size_t offset = shdr->sh_offset;
+		size_t s = 0;
+
+		if (!va_in_fwm_image_range(shdr, fw, fw_size))
+			return TEE_ERROR_BAD_FORMAT;
+
+		if (strcmp(name_table + shdr->sh_name, ".resource_table"))
+			continue;
+
+		if (!shdr->sh_size)
+			return TEE_ERROR_NO_DATA;
+
+		if (offset + size > fw_size || offset + size < size) {
+			EMSG("Resource table truncated");
+			return TEE_ERROR_BAD_FORMAT;
+		}
+
+		if (sizeof(struct resource_table) > size) {
+			EMSG("No header found in resource table");
+			return TEE_ERROR_BAD_FORMAT;
+		}
+
+		table = (struct resource_table *)(void *)(elf_data + offset);
+		if (!IS_ALIGNED_WITH_TYPE(table, uint32_t))
+			return TEE_ERROR_CORRUPT_OBJECT;
+
+		if (table->ver != 1) {
+			EMSG("Unsupported firmware version %"PRId32,
+			     table->ver);
+			return TEE_ERROR_BAD_FORMAT;
+		}
+
+		if (table->reserved[0] || table->reserved[1]) {
+			EMSG("Non zero reserved bytes");
+			return TEE_ERROR_BAD_FORMAT;
+		}
+
+		if (MUL_OVERFLOW(table->num, sizeof(*table->offset), &s) ||
+		    ADD_OVERFLOW(s, sizeof(struct resource_table), &s) ||
+		    s > size) {
+			EMSG("Resource table incomplete");
+			return TEE_ERROR_BAD_FORMAT;
+		}
+
+		DMSG("Resource table address %#"PRIx32", size %"PRIu32,
+		     shdr->sh_addr, shdr->sh_size);
+
+		*rsc_addr = shdr->sh_addr;
+		*rsc_size = shdr->sh_size;
+
+		return TEE_SUCCESS;
+	}
+
+	return TEE_ERROR_NO_DATA;
+}
diff --git a/ta/remoteproc/src/elf_parser.h b/ta/remoteproc/src/elf_parser.h
new file mode 100644
index 0000000000000000000000000000000000000000..1bd658feb29ce516782b4554d4625fbbecd84639
--- /dev/null
+++ b/ta/remoteproc/src/elf_parser.h
@@ -0,0 +1,91 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2023, STMicroelectronics
+ */
+
+#ifndef ELF_PARSER_H
+#define ELF_PARSER_H
+
+#include <elf32.h>
+#include <stdint.h>
+#include <tee_api_types.h>
+
+/**
+ * struct resource_table - firmware resource table header
+ * @ver: version number
+ * @num: number of resource entries
+ * @reserved: reserved (must be zero)
+ * @offset: array of offsets pointing at the various resource entries
+ *
+ * A resource table is essentially a list of system resources required
+ * by the remote processor. It may also include configuration entries.
+ * If needed, the remote processor firmware should contain this table
+ * as a dedicated ".resource_table" ELF section.
+ *
+ * This structure shall be consistent with the Linux kernel structure
+ * definition from include/linux/remoteproc.h.
+ *
+ * The resource_table structure does not need to be packed in OP-TEE. The ELF
+ * parser does not access the system resources structures that follow this
+ * structure in shared memory (no memory alignment constraint on structures).
+ */
+struct resource_table {
+	uint32_t ver;
+	uint32_t num;
+	uint32_t reserved[2];
+	uint32_t offset[];
+};
+
+struct fw_elf32 {
+	uintptr_t e_entry;
+	uintptr_t e_phoff;
+	uintptr_t e_shoff;
+	uint32_t e_phnum;
+	uint32_t e_shnum;
+	uint32_t e_phentsize;
+	uint32_t e_shentsize;
+
+	Elf32_Phdr *phdr;
+	Elf32_Shdr *shdr;
+};
+
+/*
+ * e32_parse_ehdr() - Check and parse the ELF header
+ *
+ * @fw:   Firmware ELF file image
+ * @size: Byte size of firmware ELF file image
+ * Return TEE_SUCCESS or appropriate error.
+ */
+TEE_Result e32_parse_ehdr(uint8_t *fw, size_t size);
+
+/*
+ * e32_parser_load_elf_image() - simple ELF loader
+ * @fw:		Firmware ELF file image
+ * @fw_size:	Firmware ELF file image byte size
+ * @load_seg:	Callback for loading a firmware image segment into device memory
+ * @priv_data:	Private data passed to @load_seg callback.
+ * Return TEE_SUCCESS or appropriate error.
+ */
+TEE_Result e32_parser_load_elf_image(uint8_t *fw, size_t fw_size,
+				     TEE_Result (*load_seg)(uint8_t *src,
+							    uint32_t size,
+							    uint32_t da,
+							    uint32_t mem_size,
+							    void *priv),
+				     void *priv_data);
+
+/*
+ * e32_parser_find_rsc_table() - find resource table in an ELF image
+ * @fw:		Firmware ELF file image
+ * @fw_size:	Firmware ELF file image byte size
+ * @rsc_addr:	Output resource table address from the remote proc perspective
+ * @rsc_size:	Output resource table size
+ * Return TEE_SUCCESS if found,
+ *        TEE_ERROR_NO_DATA if not found,
+ *        or appropriate error.
+ */
+TEE_Result e32_parser_find_rsc_table(uint8_t *fw, size_t fw_size,
+				     Elf32_Addr *rsc_addr,
+				     Elf32_Word *rsc_size);
+
+#endif /*ELF_PARSER_H*/
diff --git a/ta/remoteproc/src/remoteproc_core.c b/ta/remoteproc/src/remoteproc_core.c
new file mode 100644
index 0000000000000000000000000000000000000000..c3b815d9be1d0f6a4b63129069a02a5c3564b08e
--- /dev/null
+++ b/ta/remoteproc/src/remoteproc_core.c
@@ -0,0 +1,1103 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2023, STMicroelectronics
+ */
+
+#include <assert.h>
+#include <elf_parser.h>
+#include <remoteproc_pta.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <ta_remoteproc.h>
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+#include <types_ext.h>
+#include <utee_defines.h>
+
+/*
+ * The remoteproc Trusted Application is in charge of authenticating and loading
+ * images signed by the scripts/sign_rproc_fw.py. The TA is also in charge of
+ * starting and stopping the remote processor.
+ * The structure of the signed image is:
+ *
+ *                   -----+-------------+
+ *                  /     |    Magic    |  32-bit word, magic value equal to
+ *                 /      +-------------+  0x3543A468
+ *                /       +-------------+
+ *               /        |   version   |  32-bit word, version of the format
+ *              /         +-------------+
+ * +-----------+          +-------------+
+ * |   Header  |          |  TLV size   |  32-bit word, size of the TLV
+ * +-----------+          +-------------+  (aligned on 64-bit), in bytes.
+ *              \         +-------------+
+ *               \        |  sign size  |  32-bit word, size of the signature
+ *                \       +-------------+  (aligned on 64-bit), in bytes.
+ *                 \      +-------------+
+ *                  \     | images size |  32-bit word, size of the images to
+ *                   -----+-------------+  load (aligned on 64-bit), in bytes.
+ *
+ *                        +-------------+  Information used to authenticate the
+ *                        |     TLV     |  images and boot the remote processor,
+ *                        |             |  stored in Type-Length-Value format.
+ *                        +-------------+  'Type' and 'Length' are 32-bit words.
+ *
+ *                        +-------------+
+ *                        | Signature   |   Signature of the header and the TLV.
+ *                        +-------------+
+ *
+ *                        +-------------+
+ *                        |   Firmware  |
+ *                        |    image 1  |
+ *                        +-------------+
+ *                               ...
+ *                        +-------------+
+ *                        |   Firmware  |
+ *                        |    image n  |
+ *                        +-------------+
+ */
+
+/* Firmware state */
+enum remoteproc_state {
+	REMOTEPROC_OFF = 0,
+	REMOTEPROC_LOADED,
+	REMOTEPROC_STARTED,
+};
+
+#define RPROC_HDR_MAGIC		0x3543A468
+#define HEADER_VERSION		1
+
+/* Supported signature algorithm */
+enum remoteproc_sign_type {
+	RPROC_RSASSA_PKCS1_v1_5_SHA256 = 1,
+	RPROC_ECDSA_SHA256 = 2,
+};
+
+enum remoteproc_img_type {
+	REMOTEPROC_ELF_TYPE = 1,
+	REMOTEPROC_INVALID_TYPE = 0xFF
+};
+
+/* remoteproc_tlv structure offsets */
+#define RPROC_TLV_LENGTH_OF	U(0x04)
+#define RPROC_TLV_VALUE_OF	U(0x08)
+
+/* TLV types */
+#define RPROC_TLV_SIGNTYPE	U(0x00000001)
+#define RPROC_TLV_HASHTYPE	U(0x00000002)
+#define RPROC_TLV_NUM_IMG	U(0x00000003)
+#define RPROC_TLV_IMGTYPE	U(0x00000004)
+#define RPROC_TLV_IMGSIZE	U(0x00000005)
+#define RPROC_TLV_HASHTABLE	U(0x00000010)
+#define RPROC_TLV_PKEYINFO	U(0x00000011)
+
+#define RPROC_PLAT_TLV_TYPE_MIN	U(0x00010000)
+#define RPROC_PLAT_TLV_TYPE_MAX	U(0x00020000)
+
+#define RPROC_TLV_SIGNTYPE_LGTH U(1)
+
+#define ROUNDUP_64(x) ROUNDUP((x), sizeof(uint64_t))
+
+/*
+ * struct remoteproc_tlv - Type-Length-Value structure
+ * @type: type of data
+ * @length: size of the data.
+ * @value: pointer to the data.
+ */
+struct remoteproc_tlv {
+	uint32_t type;
+	uint32_t length;
+	uint8_t value[];
+};
+
+/*
+ * struct remoteproc_segment - program header with hash structure
+ * @phdr: program header
+ * @hash: hash associated to the program segment.
+ */
+struct remoteproc_segment {
+	Elf32_Phdr phdr;
+	uint8_t hash[TEE_SHA256_HASH_SIZE];
+};
+
+/*
+ * struct remoteproc_fw_hdr - firmware header
+ * @magic:        Magic number, must be equal to RPROC_HDR_MAGIC
+ * @version:      Version of the header (must be 1)
+ * @tlv_len:      Generic meta data chunk (TLV format)
+ * @sign_len:     Signature chunk byte length
+ * @img_len:      Firmware image chunk byte length
+ */
+struct remoteproc_fw_hdr {
+	uint32_t magic;
+	uint32_t version;
+	uint32_t tlv_len;
+	uint32_t sign_len;
+	uint32_t img_len;
+};
+
+#define FW_TLV_PTR(img, hdr)  ((img) + sizeof(*(hdr)))
+#define FW_SIGN_PTR(img, hdr) ({					\
+		struct remoteproc_fw_hdr *__hdr = (hdr);		\
+									\
+		FW_TLV_PTR((img), __hdr) + ROUNDUP_64(__hdr->tlv_len);	\
+	})
+#define FW_IMG_PTR(img, hdr) ({						   \
+		struct remoteproc_fw_hdr *___hdr = (hdr);		   \
+									   \
+		FW_SIGN_PTR((img), ___hdr) + ROUNDUP_64(___hdr->sign_len); \
+	})
+
+/*
+ * struct remoteproc_sig_algo - signature algorithm information
+ * @sign_type: Header signature type
+ * @id:        Signature algorithm identifier TEE_ALG_*
+ * @hash_len:  Signature hash length
+ */
+struct remoteproc_sig_algo {
+	enum remoteproc_sign_type sign_type;
+	uint32_t id;
+	size_t hash_len;
+};
+
+/*
+ * struct remoteproc_context - firmware context
+ * @rproc_id:    Unique Id of the processor
+ * @sec_cpy:     Location of a secure copy of the header, TLVs and signature
+ * @tlvs:        Location of a secure copy of the firmware TLVs
+ * @tlvs_sz:     Byte size of the firmware TLVs blob.
+ * @fw_img:      Firmware image
+ * @fw_img_sz:   Byte size of the firmware image
+ * @hash_table:  Location of a copy of the segment's hash table
+ * @nb_segment:  number of segment to load
+ * @rsc_pa:      Physical address of the firmware resource table
+ * @rsc_size:    Byte size of the firmware resource table
+ * @state:       Remote-processor state
+ * @hw_fmt:      Image format capabilities of the remoteproc PTA
+ * @hw_img_prot: Image protection capabilities of the remoteproc PTA
+ * @link:        Linked list element
+ */
+struct remoteproc_context {
+	uint32_t rproc_id;
+	uint8_t *sec_cpy;
+	uint8_t *tlvs;
+	size_t tlvs_sz;
+	uint8_t *fw_img;
+	size_t fw_img_sz;
+	struct remoteproc_segment *hash_table;
+	uint32_t nb_segment;
+	paddr_t rsc_pa;
+	size_t rsc_size;
+	enum remoteproc_state state;
+	uint32_t hw_fmt;
+	uint32_t hw_img_prot;
+	TAILQ_ENTRY(remoteproc_context) link;
+};
+
+TAILQ_HEAD(remoteproc_firmware_head, remoteproc_context);
+
+static struct remoteproc_firmware_head firmware_head =
+	TAILQ_HEAD_INITIALIZER(firmware_head);
+
+static const struct remoteproc_sig_algo rproc_ta_sign_algo[] = {
+	{
+		.sign_type = RPROC_RSASSA_PKCS1_v1_5_SHA256,
+		.id = TEE_ALG_RSASSA_PKCS1_V1_5_SHA256,
+		.hash_len = TEE_SHA256_HASH_SIZE,
+	},
+	{
+		.sign_type = RPROC_ECDSA_SHA256,
+		.id = TEE_ALG_ECDSA_P256,
+		.hash_len = TEE_SHA256_HASH_SIZE,
+	},
+};
+
+static size_t session_refcount;
+static TEE_TASessionHandle pta_session;
+
+static void remoteproc_header_dump(struct remoteproc_fw_hdr __maybe_unused *hdr)
+{
+	DMSG("magic :\t%#"PRIx32, hdr->magic);
+	DMSG("version :\t%#"PRIx32, hdr->version);
+	DMSG("tlv_len :\t%#"PRIx32, hdr->tlv_len);
+	DMSG("sign_len :\t%#"PRIx32, hdr->sign_len);
+	DMSG("img_len :\t%#"PRIx32, hdr->img_len);
+}
+
+static TEE_Result remoteproc_get_tlv(void *tlv_chunk, size_t tlv_size,
+				     uint16_t type, uint8_t **value,
+				     size_t *length)
+{
+	uint8_t *p_tlv = (uint8_t *)tlv_chunk;
+	uint8_t *p_end_tlv = p_tlv + tlv_size;
+	uint32_t tlv_type = 0;
+	uint32_t tlv_length = 0;
+	uint32_t tlv_v = 0;
+
+	*value = NULL;
+	*length = 0;
+
+	/* Parse the TLV area */
+	while (p_tlv < p_end_tlv) {
+		memcpy(&tlv_v, p_tlv, sizeof(tlv_v));
+		tlv_type = TEE_U32_FROM_LITTLE_ENDIAN(tlv_v);
+		memcpy(&tlv_v, p_tlv + RPROC_TLV_LENGTH_OF, sizeof(tlv_v));
+		tlv_length = TEE_U32_FROM_LITTLE_ENDIAN(tlv_v);
+		if (tlv_type == type) {
+			/* The specified TLV has been found */
+			DMSG("TLV type %#"PRIx32" found, size %#"PRIx32,
+			     type, tlv_length);
+			*value = &p_tlv[RPROC_TLV_VALUE_OF];
+			*length = tlv_length;
+			if (tlv_length)
+				return TEE_SUCCESS;
+			else
+				return TEE_ERROR_NO_DATA;
+		}
+		p_tlv += ROUNDUP_64(sizeof(struct remoteproc_tlv) + tlv_length);
+	}
+
+	return TEE_ERROR_NO_DATA;
+}
+
+static struct remoteproc_context *remoteproc_find_firmware(uint32_t rproc_id)
+{
+	struct remoteproc_context *ctx = NULL;
+
+	TAILQ_FOREACH(ctx, &firmware_head, link)
+		if (ctx->rproc_id == rproc_id)
+			return ctx;
+
+	return NULL;
+}
+
+static struct remoteproc_context *remoteproc_add_firmware(uint32_t rproc_id)
+{
+	struct remoteproc_context *ctx = NULL;
+
+	ctx = TEE_Malloc(sizeof(*ctx), TEE_MALLOC_FILL_ZERO);
+	if (!ctx)
+		return NULL;
+
+	ctx->rproc_id = rproc_id;
+
+	TAILQ_INSERT_TAIL(&firmware_head, ctx, link);
+
+	return ctx;
+}
+
+static const struct remoteproc_sig_algo *remoteproc_get_algo(uint32_t sign_type)
+{
+	unsigned int i = 0;
+
+	for (i = 0; i < ARRAY_SIZE(rproc_ta_sign_algo); i++)
+		if (sign_type == rproc_ta_sign_algo[i].sign_type)
+			return &rproc_ta_sign_algo[i];
+
+	return NULL;
+}
+
+static TEE_Result remoteproc_pta_verify(struct remoteproc_context *ctx,
+					const struct remoteproc_sig_algo *algo,
+					uint8_t *hash, uint32_t hash_len)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct remoteproc_fw_hdr *hdr = (void *)ctx->sec_cpy;
+	struct rproc_pta_key_info *keyinfo = NULL;
+	uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+					       TEE_PARAM_TYPE_MEMREF_INPUT,
+					       TEE_PARAM_TYPE_MEMREF_INPUT,
+					       TEE_PARAM_TYPE_MEMREF_INPUT);
+	TEE_Param params[TEE_NUM_PARAMS] = { };
+	size_t length = 0;
+	uint8_t *tlv_keyinfo = NULL;
+	uint8_t *sign = NULL;
+
+	res = remoteproc_get_tlv(ctx->tlvs, hdr->tlv_len,
+				 RPROC_TLV_PKEYINFO, &tlv_keyinfo,
+				 &length);
+	if (res != TEE_SUCCESS && res != TEE_ERROR_NO_DATA)
+		return res;
+
+	keyinfo = TEE_Malloc(sizeof(*keyinfo) + length, TEE_MALLOC_FILL_ZERO);
+	if (!keyinfo)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	keyinfo->algo = algo->id;
+	keyinfo->info_size = length;
+	memcpy(keyinfo->info, tlv_keyinfo, length);
+
+	sign = FW_SIGN_PTR(ctx->sec_cpy, hdr);
+
+	params[0].value.a = ctx->rproc_id;
+	params[1].memref.buffer = keyinfo;
+	params[1].memref.size = rproc_pta_keyinfo_size(keyinfo);
+	params[2].memref.buffer = hash;
+	params[2].memref.size = hash_len;
+	params[3].memref.buffer = sign;
+	params[3].memref.size = hdr->sign_len;
+
+	res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
+				  PTA_RPROC_VERIFY_DIGEST,
+				  param_types, params, NULL);
+	if (res != TEE_SUCCESS)
+		EMSG("Failed to verify signature, res = %#"PRIx32, res);
+
+	TEE_Free(keyinfo);
+
+	return res;
+}
+
+static TEE_Result
+remoteproc_save_fw_header_and_tlvs(struct remoteproc_context *ctx,
+				   void *fw_orig, uint32_t fw_orig_size)
+{
+	struct remoteproc_fw_hdr *hdr = fw_orig;
+	uint32_t length = 0;
+
+	if (!IS_ALIGNED_WITH_TYPE(fw_orig, struct remoteproc_fw_hdr))
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (ADD_OVERFLOW(sizeof(*hdr), ROUNDUP_64(hdr->tlv_len), &length) ||
+	    ADD_OVERFLOW(length, ROUNDUP_64(hdr->sign_len), &length))
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (fw_orig_size <= length || !hdr->sign_len || !hdr->tlv_len)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	remoteproc_header_dump(hdr);
+
+	/* Copy the header, the TLVs and the signature in secure memory */
+	ctx->sec_cpy = TEE_Malloc(length, TEE_MALLOC_FILL_ZERO);
+	if (!ctx->sec_cpy)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	memcpy(ctx->sec_cpy, fw_orig, length);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result remoteproc_verify_signature(struct remoteproc_context *ctx)
+{
+	TEE_OperationHandle op = TEE_HANDLE_NULL;
+	struct remoteproc_fw_hdr *hdr = (void *)ctx->sec_cpy;
+	const struct remoteproc_sig_algo *algo = NULL;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	uint8_t *tlv_sign_algo = NULL;
+	size_t length = 0;
+	uint8_t *hash = NULL;
+	size_t hash_len = 0;
+
+	/* Get the algo type from TLV data */
+	res = remoteproc_get_tlv(ctx->tlvs, hdr->tlv_len, RPROC_TLV_SIGNTYPE,
+				 &tlv_sign_algo, &length);
+
+	if (res != TEE_SUCCESS || length != RPROC_TLV_SIGNTYPE_LGTH)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	algo = remoteproc_get_algo(*tlv_sign_algo);
+	if (!algo) {
+		EMSG("Unsupported signature type %"PRId8, *tlv_sign_algo);
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+
+	/* Compute the header and TLVs hashes */
+	hash_len = algo->hash_len;
+	hash = TEE_Malloc(hash_len, TEE_MALLOC_FILL_ZERO);
+	if (!hash)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	res = TEE_AllocateOperation(&op, TEE_ALG_SHA256, TEE_MODE_DIGEST, 0);
+	if (res != TEE_SUCCESS)
+		goto free_hash;
+
+	TEE_DigestUpdate(op, hdr, sizeof(*hdr));
+	res = TEE_DigestDoFinal(op, ctx->tlvs, ROUNDUP_64(hdr->tlv_len),
+				hash, &hash_len);
+
+	if (res != TEE_SUCCESS)
+		goto out;
+
+	/*
+	 * This implementation could be enhanced by providing alternative to
+	 * verify the signature in the TA. This could be done for instance by
+	 * getting the key object from secure storage.
+	 */
+
+	/* By default ask the remoteproc PTA to verify the signature. */
+	res = remoteproc_pta_verify(ctx, algo, hash, hash_len);
+
+out:
+	TEE_FreeOperation(op);
+free_hash:
+	TEE_Free(hash);
+
+	return res;
+}
+
+static TEE_Result remoteproc_verify_header(struct remoteproc_context *ctx,
+					   uint32_t fw_orig_size)
+{
+	struct remoteproc_fw_hdr *hdr = (void *)ctx->sec_cpy;
+	uint32_t size = 0;
+
+	if (hdr->magic != RPROC_HDR_MAGIC)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (hdr->version != HEADER_VERSION)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	/*
+	 * The offsets are aligned to 64 bits format. While the length of each
+	 * chunks are the effective length, excluding the alignment padding
+	 * bytes.
+	 */
+	if (ADD_OVERFLOW(sizeof(*hdr), ROUNDUP_64(hdr->sign_len), &size) ||
+	    ADD_OVERFLOW(size, ROUNDUP_64(hdr->img_len), &size) ||
+	    ADD_OVERFLOW(size, ROUNDUP_64(hdr->tlv_len), &size) ||
+	    fw_orig_size != size)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result get_rproc_pta_capabilities(struct remoteproc_context *ctx)
+{
+	uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+					       TEE_PARAM_TYPE_VALUE_OUTPUT,
+					       TEE_PARAM_TYPE_VALUE_OUTPUT,
+					       TEE_PARAM_TYPE_NONE);
+	TEE_Param params[TEE_NUM_PARAMS] = { };
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	params[0].value.a = ctx->rproc_id;
+
+	res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
+				  PTA_RPROC_HW_CAPABILITIES,
+				  param_types, params, NULL);
+	if (res)
+		return res;
+
+	ctx->hw_fmt = params[1].value.a;
+	ctx->hw_img_prot = params[2].value.a;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result remoteproc_verify_firmware(struct remoteproc_context *ctx,
+					     uint8_t *fw_orig,
+					     uint32_t fw_orig_size)
+{
+	struct remoteproc_fw_hdr *hdr = NULL;
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	res = get_rproc_pta_capabilities(ctx);
+	if (res)
+		return res;
+
+	/* Secure the firmware image depending on strategy */
+	if (!(ctx->hw_img_prot & PTA_RPROC_HWCAP_PROT_HASH_TABLE) ||
+	    ctx->hw_fmt != PTA_RPROC_HWCAP_FMT_ELF) {
+		/*
+		 * Only hash table for ELF format support implemented
+		 * in a first step.
+		 */
+		return TEE_ERROR_NOT_IMPLEMENTED;
+	}
+
+	res = remoteproc_save_fw_header_and_tlvs(ctx, fw_orig, fw_orig_size);
+	if (res)
+		return res;
+
+	res = remoteproc_verify_header(ctx, fw_orig_size);
+	if (res)
+		goto free_sec_cpy;
+
+	hdr = (void *)ctx->sec_cpy;
+	ctx->tlvs_sz = hdr->tlv_len;
+	ctx->tlvs = FW_TLV_PTR(ctx->sec_cpy, hdr);
+
+	res = remoteproc_verify_signature(ctx);
+	if (res)
+		goto free_sec_cpy;
+
+	/* Store location of the loadable binary in non-secure memory */
+	ctx->fw_img_sz = hdr->img_len;
+	ctx->fw_img = FW_IMG_PTR(fw_orig, hdr);
+
+	DMSG("Firmware images addr: %p size: %zu", ctx->fw_img,
+	     ctx->fw_img_sz);
+
+	return TEE_SUCCESS;
+
+free_sec_cpy:
+	TEE_Free(ctx->sec_cpy);
+	ctx->sec_cpy = NULL;
+
+	return res;
+}
+
+static paddr_t remoteproc_da_to_pa(uint32_t da, size_t size,
+				   struct remoteproc_context *ctx)
+{
+	uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+					       TEE_PARAM_TYPE_VALUE_INPUT,
+					       TEE_PARAM_TYPE_VALUE_INPUT,
+					       TEE_PARAM_TYPE_VALUE_OUTPUT);
+	TEE_Param params[TEE_NUM_PARAMS] = { };
+	TEE_Result res = TEE_ERROR_GENERIC;
+	paddr_t pa = 0;
+
+	/*
+	 * The ELF file contains remote processor device addresses, that refer
+	 * to the remote processor memory space.
+	 * A translation is needed to get the corresponding physical address.
+	 */
+
+	params[0].value.a = ctx->rproc_id;
+	params[1].value.a = da;
+	params[2].value.a = size;
+
+	res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
+				  PTA_RPROC_FIRMWARE_DA_TO_PA,
+				  param_types, params, NULL);
+	if (res != TEE_SUCCESS) {
+		EMSG("Failed to translate device address %#"PRIx32, da);
+		return 0;
+	}
+
+	pa = (paddr_t)reg_pair_to_64(params[3].value.b, params[3].value.a);
+
+	/* Assert that the pa address is not 0 */
+	assert(pa);
+
+	return pa;
+}
+
+static TEE_Result remoteproc_parse_rsc_table(struct remoteproc_context *ctx,
+					     uint8_t *fw_img, size_t fw_img_sz,
+					     paddr_t *rsc_pa,
+					     size_t *rsc_size)
+{
+	uint32_t da = 0;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	Elf32_Word size = 0;
+
+	res = e32_parser_find_rsc_table(fw_img, fw_img_sz, &da, &size);
+	if (res)
+		return res;
+
+	DMSG("Resource table device address %#"PRIx32" size %#"PRIx32,
+	     da, size);
+
+	*rsc_pa = remoteproc_da_to_pa(da, size, ctx);
+	if (!*rsc_pa)
+		return TEE_ERROR_ACCESS_DENIED;
+
+	*rsc_size = size;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result get_hash_table(struct remoteproc_context *ctx)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	uint8_t *tlv_hash = NULL;
+	struct remoteproc_segment *hash_table = NULL;
+	size_t length = 0;
+
+	/* Get the segment's hash table from TLV data */
+	res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_HASHTABLE,
+				 &tlv_hash, &length);
+	if (res)
+		return res;
+
+	if (length % sizeof(struct remoteproc_segment))
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	/* We can not ensure that tlv_hash is memory aligned so make a copy */
+	hash_table = TEE_Malloc(length, TEE_MALLOC_FILL_ZERO);
+	if (!hash_table)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	memcpy(hash_table, tlv_hash, length);
+
+	ctx->hash_table = hash_table;
+	ctx->nb_segment = length / sizeof(struct remoteproc_segment);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result get_tlv_images_type(struct remoteproc_context *ctx,
+				      uint8_t num_img, uint8_t idx,
+				      uint8_t *img_type)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	uint8_t *tlv_value = NULL;
+	size_t length = 0;
+
+	/* Get the type of the image to load, from TLV data */
+	res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_IMGTYPE,
+				 &tlv_value, &length);
+	if (res)
+		return res;
+
+	if (length != (sizeof(*img_type) * num_img))
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	*img_type = tlv_value[idx];
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result get_tlv_images_size(struct remoteproc_context *ctx,
+				      uint8_t num_img, uint8_t idx,
+				      uint32_t *img_size)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	uint8_t *tlv_value = NULL;
+	uint32_t tlv_v = 0;
+	size_t length = 0;
+
+	/* Get the size of the image to load, from TLV data */
+	res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_IMGSIZE,
+				 &tlv_value, &length);
+	if (res)
+		return res;
+
+	if (length != (sizeof(*img_size) * num_img))
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	memcpy(&tlv_v, &tlv_value[sizeof(*img_size) * idx], sizeof(tlv_v));
+	*img_size = TEE_U32_FROM_LITTLE_ENDIAN(tlv_v);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result get_segment_hash(struct remoteproc_context *ctx, uint8_t *src,
+				   uint32_t size, uint32_t da,
+				   uint32_t mem_size, uint8_t **hash)
+{
+	struct remoteproc_segment *peh = NULL;
+	unsigned int i = 0;
+	unsigned int nb_entry = ctx->nb_segment;
+
+	peh = (void *)(ctx->hash_table);
+
+	for (i = 0; i < nb_entry; peh++, i++) {
+		if (peh->phdr.p_paddr != da)
+			continue;
+
+		/*
+		 * Segment metadata are read from a non-secure memory.
+		 * Validate them using hash table data stored in secure memory.
+		 */
+		if (peh->phdr.p_type != PT_LOAD)
+			return TEE_ERROR_BAD_PARAMETERS;
+
+		if (peh->phdr.p_filesz != size || peh->phdr.p_memsz != mem_size)
+			return TEE_ERROR_BAD_PARAMETERS;
+
+		if (src < ctx->fw_img ||
+		    src >  (ctx->fw_img + ctx->fw_img_sz) ||
+		    (src + peh->phdr.p_filesz) > (ctx->fw_img + ctx->fw_img_sz))
+			return TEE_ERROR_BAD_PARAMETERS;
+
+		*hash = peh->hash;
+
+		return TEE_SUCCESS;
+	}
+
+	return TEE_ERROR_NO_DATA;
+}
+
+static TEE_Result remoteproc_load_segment(uint8_t *src, uint32_t size,
+					  uint32_t da, uint32_t mem_size,
+					  void *priv)
+{
+	struct remoteproc_context *ctx = priv;
+	uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+					       TEE_PARAM_TYPE_MEMREF_INPUT,
+					       TEE_PARAM_TYPE_VALUE_INPUT,
+					       TEE_PARAM_TYPE_MEMREF_INPUT);
+	TEE_Param params[TEE_NUM_PARAMS] = { };
+	TEE_Result res = TEE_ERROR_GENERIC;
+	uint8_t *hash = NULL;
+
+	/*
+	 * Invoke platform remoteproc PTA to load the segment in remote
+	 * processor memory which is not mapped in the TA space.
+	 */
+
+	DMSG("Load segment %#"PRIx32" size %"PRIu32" (%"PRIu32")", da, size,
+	     mem_size);
+
+	res = get_segment_hash(ctx, src, size, da, mem_size, &hash);
+	if (res)
+		return res;
+
+	params[0].value.a = ctx->rproc_id;
+	params[1].memref.buffer = src;
+	params[1].memref.size = size;
+	params[2].value.a = da;
+	params[3].memref.buffer = hash;
+	params[3].memref.size = TEE_SHA256_HASH_SIZE;
+
+	if (size) {
+		res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
+					  PTA_RPROC_LOAD_SEGMENT_SHA256,
+					  param_types, params, NULL);
+		if (res != TEE_SUCCESS) {
+			EMSG("Fails to load segment, res = 0x%#"PRIx32, res);
+			return res;
+		}
+	}
+
+	/* Fill the rest of the memory with 0 */
+	if (size < mem_size) {
+		param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+					      TEE_PARAM_TYPE_VALUE_INPUT,
+					      TEE_PARAM_TYPE_VALUE_INPUT,
+					      TEE_PARAM_TYPE_VALUE_INPUT);
+		params[1].value.a = da + size;
+		params[2].value.a = mem_size - size;
+		params[3].value.a = 0;
+
+		res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
+					  PTA_RPROC_SET_MEMORY,
+					  param_types, params, NULL);
+		if (res != TEE_SUCCESS)
+			EMSG("Fails to clear segment, res = %#"PRIx32, res);
+	}
+
+	return res;
+}
+
+static TEE_Result remoteproc_load_elf(struct remoteproc_context *ctx)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	unsigned int num_img = 0;
+	unsigned int i = 0;
+	uint8_t img_type = REMOTEPROC_INVALID_TYPE;
+	uint32_t img_size = 0;
+	uint8_t *tlv = NULL;
+	int32_t offset = 0;
+	size_t length = 0;
+	paddr_t rsc_pa = 0;
+	size_t rsc_size = 0;
+
+	res = e32_parse_ehdr(ctx->fw_img, ctx->fw_img_sz);
+	if (res) {
+		EMSG("Failed to parse firmware, res = %#"PRIx32, res);
+		return res;
+	}
+
+	res = get_hash_table(ctx);
+	if (res)
+		return res;
+
+	/* Get the number of firmware images to load */
+	res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_NUM_IMG,
+				 &tlv, &length);
+	if (res)
+		goto out;
+	if (length != sizeof(uint8_t)) {
+		res = TEE_ERROR_BAD_FORMAT;
+		goto out;
+	}
+
+	num_img = *tlv;
+	if (!num_img) {
+		res = TEE_ERROR_NO_DATA;
+		goto out;
+	}
+
+	/*
+	 * Initialize resource table with zero. These values will be returned if
+	 * no optional resource table is found in images.
+	 */
+	ctx->rsc_pa = 0;
+	ctx->rsc_size = 0;
+
+	for (i = 0; i < num_img; i++) {
+		res = get_tlv_images_type(ctx, num_img, i, &img_type);
+		if (res)
+			goto out;
+		if (img_type != REMOTEPROC_ELF_TYPE) {
+			res = TEE_ERROR_BAD_FORMAT;
+			goto out;
+		}
+
+		res = get_tlv_images_size(ctx, num_img, i, &img_size);
+		if (res)
+			goto out;
+
+		res = e32_parser_load_elf_image(ctx->fw_img + offset, img_size,
+						remoteproc_load_segment, ctx);
+		if (res)
+			goto out;
+
+		/* Take opportunity to get the resource table address */
+		res = remoteproc_parse_rsc_table(ctx, ctx->fw_img + offset,
+						 img_size, &rsc_pa, &rsc_size);
+		if (res != TEE_SUCCESS && res != TEE_ERROR_NO_DATA)
+			goto out;
+
+		if (res == TEE_SUCCESS) {
+			/*
+			 * Only one resource table is supported, check that no
+			 * other one has been declared in a previously loaded
+			 * firmware.
+			 */
+			if (ctx->rsc_pa || ctx->rsc_size) {
+				EMSG("More than one resource table found");
+				res = TEE_ERROR_BAD_FORMAT;
+				goto out;
+			}
+			ctx->rsc_pa = rsc_pa;
+			ctx->rsc_size = rsc_size;
+		} else {
+			/*
+			 * No resource table found. Force to TEE_SUCCESS as the
+			 * resource table is optional.
+			 */
+			res = TEE_SUCCESS;
+		}
+		offset += img_size;
+	}
+
+out:
+	/* Should we clean-up the memories in case of fail ? */
+	TEE_Free(ctx->hash_table);
+	ctx->hash_table = NULL;
+
+	return res;
+}
+
+static TEE_Result remoteproc_load_fw(uint32_t pt,
+				     TEE_Param params[TEE_NUM_PARAMS])
+{
+	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+						TEE_PARAM_TYPE_MEMREF_INPUT,
+						TEE_PARAM_TYPE_NONE,
+						TEE_PARAM_TYPE_NONE);
+	struct remoteproc_context *ctx = NULL;
+	uint32_t rproc_id = params[0].value.a;
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	if (pt != exp_pt)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	ctx = remoteproc_find_firmware(rproc_id);
+	if (!ctx)
+		ctx = remoteproc_add_firmware(rproc_id);
+	if (!ctx)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	if (ctx->state != REMOTEPROC_OFF)
+		return TEE_ERROR_BAD_STATE;
+
+	if (!params[1].memref.buffer || !params[1].memref.size)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	DMSG("Got base addr: %p size %#zx", params[1].memref.buffer,
+	     params[1].memref.size);
+
+	res = remoteproc_verify_firmware(ctx, params[1].memref.buffer,
+					 params[1].memref.size);
+	if (res) {
+		EMSG("Can't Authenticate the firmware (res = %#"PRIx32")", res);
+		goto out;
+	}
+
+	res = remoteproc_load_elf(ctx);
+	if (res)
+		goto out;
+
+	ctx->state = REMOTEPROC_LOADED;
+
+out:
+	/* Clear reference to firmware image from shared memory */
+	ctx->fw_img = NULL;
+	ctx->fw_img_sz = 0;
+	ctx->nb_segment = 0;
+
+	/* Free allocated memories */
+	TEE_Free(ctx->sec_cpy);
+	ctx->sec_cpy = NULL;
+
+	return res;
+}
+
+static TEE_Result remoteproc_start_fw(uint32_t pt,
+				      TEE_Param params[TEE_NUM_PARAMS])
+{
+	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+						TEE_PARAM_TYPE_NONE,
+						TEE_PARAM_TYPE_NONE,
+						TEE_PARAM_TYPE_NONE);
+	struct remoteproc_context *ctx = NULL;
+	uint32_t rproc_id = params[0].value.a;
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	if (pt != exp_pt)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	ctx = remoteproc_find_firmware(rproc_id);
+	if (!ctx)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	switch (ctx->state) {
+	case REMOTEPROC_OFF:
+		res = TEE_ERROR_BAD_STATE;
+		break;
+	case REMOTEPROC_STARTED:
+		res = TEE_SUCCESS;
+		break;
+	case REMOTEPROC_LOADED:
+		res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
+					  PTA_RPROC_FIRMWARE_START,
+					  pt, params, NULL);
+		if (res == TEE_SUCCESS)
+			ctx->state = REMOTEPROC_STARTED;
+		break;
+	default:
+		res = TEE_ERROR_BAD_STATE;
+	}
+
+	return res;
+}
+
+static TEE_Result remoteproc_stop_fw(uint32_t pt,
+				     TEE_Param params[TEE_NUM_PARAMS])
+{
+	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+						TEE_PARAM_TYPE_NONE,
+						TEE_PARAM_TYPE_NONE,
+						TEE_PARAM_TYPE_NONE);
+	struct remoteproc_context *ctx = NULL;
+	uint32_t rproc_id = params[0].value.a;
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	if (pt != exp_pt)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	ctx = remoteproc_find_firmware(rproc_id);
+	if (!ctx)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	switch (ctx->state) {
+	case REMOTEPROC_LOADED:
+		res = TEE_ERROR_BAD_STATE;
+		break;
+	case REMOTEPROC_OFF:
+		res = TEE_SUCCESS;
+		break;
+	case REMOTEPROC_STARTED:
+		res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
+					  PTA_RPROC_FIRMWARE_STOP,
+					  pt, params, NULL);
+		if (res == TEE_SUCCESS)
+			ctx->state = REMOTEPROC_OFF;
+		break;
+	default:
+		res = TEE_ERROR_BAD_STATE;
+	}
+
+	return res;
+}
+
+static TEE_Result remoteproc_get_rsc_table(uint32_t pt,
+					   TEE_Param params[TEE_NUM_PARAMS])
+{
+	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+						TEE_PARAM_TYPE_VALUE_OUTPUT,
+						TEE_PARAM_TYPE_VALUE_OUTPUT,
+						TEE_PARAM_TYPE_NONE);
+	struct remoteproc_context *ctx = NULL;
+
+	if (pt != exp_pt)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	ctx = remoteproc_find_firmware(params[0].value.a);
+	if (!ctx)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (ctx->state == REMOTEPROC_OFF)
+		return TEE_ERROR_BAD_STATE;
+
+	reg_pair_from_64((uint64_t)ctx->rsc_pa,
+			 &params[1].value.b, &params[1].value.a);
+	reg_pair_from_64((uint64_t)ctx->rsc_size,
+			 &params[2].value.b, &params[2].value.a);
+
+	return TEE_SUCCESS;
+}
+
+TEE_Result TA_CreateEntryPoint(void)
+{
+	return TEE_SUCCESS;
+}
+
+void TA_DestroyEntryPoint(void)
+{
+}
+
+/*
+ * TA_OpenSessionEntryPoint: open a TA session associated to a remote processor
+ * to manage.
+ *
+ * [in] params[0].value.a:	Unique 32bit remote processor identifier
+ */
+TEE_Result TA_OpenSessionEntryPoint(uint32_t pt,
+				    TEE_Param params[TEE_NUM_PARAMS],
+				    void **sess __unused)
+{
+	static const TEE_UUID uuid = PTA_RPROC_UUID;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+						TEE_PARAM_TYPE_NONE,
+						TEE_PARAM_TYPE_NONE,
+						TEE_PARAM_TYPE_NONE);
+
+	if (pt != exp_pt)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (!session_refcount) {
+		res = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, pt, params,
+					&pta_session, NULL);
+		if (res)
+			return res;
+	}
+
+	session_refcount++;
+
+	return TEE_SUCCESS;
+}
+
+void TA_CloseSessionEntryPoint(void *sess __unused)
+{
+	session_refcount--;
+
+	if (!session_refcount)
+		TEE_CloseTASession(pta_session);
+}
+
+TEE_Result TA_InvokeCommandEntryPoint(void *sess __unused, uint32_t cmd_id,
+				      uint32_t pt,
+				      TEE_Param params[TEE_NUM_PARAMS])
+{
+	switch (cmd_id) {
+	case TA_RPROC_CMD_LOAD_FW:
+		return remoteproc_load_fw(pt, params);
+	case TA_RPROC_CMD_START_FW:
+		return remoteproc_start_fw(pt, params);
+	case TA_RPROC_CMD_STOP_FW:
+		return remoteproc_stop_fw(pt, params);
+	case TA_RPROC_CMD_GET_RSC_TABLE:
+		return remoteproc_get_rsc_table(pt, params);
+	case TA_RPROC_CMD_GET_COREDUMP:
+		return TEE_ERROR_NOT_IMPLEMENTED;
+	default:
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+}
diff --git a/ta/remoteproc/src/sub.mk b/ta/remoteproc/src/sub.mk
new file mode 100644
index 0000000000000000000000000000000000000000..81ba566acf9d1ff0e373fada527c37383615d586
--- /dev/null
+++ b/ta/remoteproc/src/sub.mk
@@ -0,0 +1,2 @@
+srcs-y += remoteproc_core.c
+srcs-y += elf_parser.c
diff --git a/ta/remoteproc/src/user_ta_header_defines.h b/ta/remoteproc/src/user_ta_header_defines.h
new file mode 100644
index 0000000000000000000000000000000000000000..d303cb01bc304576b22cb4929b7b034a5ecfbfee
--- /dev/null
+++ b/ta/remoteproc/src/user_ta_header_defines.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2023 STMicroelectronics
+ */
+
+#ifndef USER_TA_HEADER_DEFINES_H
+#define USER_TA_HEADER_DEFINES_H
+
+#include <ta_remoteproc.h>
+
+#define TA_UUID				TA_REMOTEPROC_UUID
+
+#define TA_FLAGS			(TA_FLAG_DEVICE_ENUM | \
+					 TA_FLAG_SINGLE_INSTANCE | \
+					 TA_FLAG_INSTANCE_KEEP_ALIVE)
+
+/* Provisioned stack size */
+#define TA_STACK_SIZE			(4 * 1024)
+
+/* Provisioned heap size for TEE_Malloc() and friends */
+#define TA_DATA_SIZE			CFG_REMOTEPROC_TA_HEAP_SIZE
+
+/* The gpd.ta.version property */
+#define TA_VERSION	"1.0"
+
+/* The gpd.ta.description property */
+#define TA_DESCRIPTION	"remote processor firmware management"
+
+#endif /* USER_TA_HEADER_DEFINES_H */
diff --git a/ta/remoteproc/sub.mk b/ta/remoteproc/sub.mk
new file mode 100644
index 0000000000000000000000000000000000000000..ae78d611bad4dba99cee461154a67025ce15b2a2
--- /dev/null
+++ b/ta/remoteproc/sub.mk
@@ -0,0 +1,3 @@
+global-incdirs-y += include
+global-incdirs-y += src
+subdirs-y += src
diff --git a/ta/remoteproc/user_ta.mk b/ta/remoteproc/user_ta.mk
new file mode 100644
index 0000000000000000000000000000000000000000..84721ff710b5d24868de9828e1506880a0455644
--- /dev/null
+++ b/ta/remoteproc/user_ta.mk
@@ -0,0 +1,4 @@
+user-ta-uuid := 80a4c275-0a47-4905-8285-1486a9771a08
+
+# REMOTEPROC TA heap size can be customized if 4kB is not enough
+CFG_REMOTEPROC_TA_HEAP_SIZE ?= (4 * 1024)
diff --git a/ta/ta.mk b/ta/ta.mk
index 09c20bfa16f5db4ad1562ce7b961f80a775f1f0a..ac46890c5dfc80a549698329f5209c8b3731b57f 100644
--- a/ta/ta.mk
+++ b/ta/ta.mk
@@ -190,7 +190,8 @@ $(foreach f, $(ta-keys), \
 	$(eval $(call copy-file, $(f), $(out-dir)/export-$(sm)/keys)))
 
 # Copy the scripts
-ta-scripts = scripts/sign_encrypt.py scripts/symbolize.py scripts/sign_rproc_fw.py
+ta-scripts = scripts/sign_encrypt.py scripts/symbolize.py \
+       scripts/sign_rproc_fw.py scripts/ftrace_format.py
 $(foreach f, $(ta-scripts), \
 	$(eval $(call copy-file, $(f), $(out-dir)/export-$(sm)/scripts)))