Merge changes from topic "fix-imx8m-uart-domain-permission" into integration

* changes:
  fix(imx8m): ensure domain permissions for the console
  refactor(imx8m): replace UART base magic numbers with macros
diff --git a/.editorconfig b/.editorconfig
index 12f786d..1b29c88 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -70,3 +70,6 @@
 # [PEP8] Maximum Line Length
 #	"Limit all lines to a maximum of 79 characters."
 max_line_length = 79
+
+[.git/COMMIT_EDITMSG]
+max_line_length = 72
diff --git a/Makefile b/Makefile
index 179e07a..4f3f261 100644
--- a/Makefile
+++ b/Makefile
@@ -597,19 +597,11 @@
 ################################################################################
 # FEAT_RME
 ifeq (${ENABLE_RME},1)
-	# RME doesn't support BRBE
-	ENABLE_BRBE_FOR_NS := 0
-
 	# RME doesn't support PIE
 	ifneq (${ENABLE_PIE},0)
                 $(error ENABLE_RME does not support PIE)
 	endif
 
-	# RME doesn't support BRBE
-	ifneq (${ENABLE_BRBE_FOR_NS},0)
-                $(error ENABLE_RME does not support BRBE.)
-	endif
-
 	# RME requires AARCH64
 	ifneq (${ARCH},aarch64)
                 $(error ENABLE_RME requires AArch64)
@@ -1177,6 +1169,7 @@
 	HW_ASSISTED_COHERENCY \
 	MEASURED_BOOT \
 	DICE_PROTECTION_ENVIRONMENT \
+	RMMD_ENABLE_EL3_TOKEN_SIGN \
 	DRTM_SUPPORT \
 	NS_TIMER_SWITCH \
 	OVERRIDE_LIBC \
@@ -1263,11 +1256,13 @@
 	ENABLE_FEAT_RNG_TRAP \
 	ENABLE_FEAT_SEL2 \
 	ENABLE_FEAT_TCR2 \
+	ENABLE_FEAT_THE \
 	ENABLE_FEAT_SB \
 	ENABLE_FEAT_S2PIE \
 	ENABLE_FEAT_S1PIE \
 	ENABLE_FEAT_S2POE \
 	ENABLE_FEAT_S1POE \
+	ENABLE_FEAT_SCTLR2 \
 	ENABLE_FEAT_GCS \
 	ENABLE_FEAT_VHE \
 	ENABLE_FEAT_MPAM \
@@ -1331,6 +1326,7 @@
 	ENABLE_PMF \
 	ENABLE_PSCI_STAT \
 	ENABLE_RME \
+	RMMD_ENABLE_EL3_TOKEN_SIGN \
 	ENABLE_RUNTIME_INSTRUMENTATION \
 	ENABLE_SME_FOR_NS \
 	ENABLE_SME2_FOR_NS \
@@ -1419,10 +1415,12 @@
 	ENABLE_FEAT_CSV2_3 \
 	ENABLE_FEAT_PAN \
 	ENABLE_FEAT_TCR2 \
+	ENABLE_FEAT_THE \
 	ENABLE_FEAT_S2PIE \
 	ENABLE_FEAT_S1PIE \
 	ENABLE_FEAT_S2POE \
 	ENABLE_FEAT_S1POE \
+	ENABLE_FEAT_SCTLR2 \
 	ENABLE_FEAT_GCS \
 	ENABLE_FEAT_MTE2 \
 	FEATURE_DETECTION \
diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S
index e47b082..7423805 100644
--- a/bl31/aarch64/runtime_exceptions.S
+++ b/bl31/aarch64/runtime_exceptions.S
@@ -229,7 +229,6 @@
 	save_x30
 	apply_at_speculative_wa
 	sync_and_handle_pending_serror
-	unmask_async_ea
 	handle_sync_exception
 end_vector_entry sync_exception_aarch64
 
@@ -237,7 +236,6 @@
 	save_x30
 	apply_at_speculative_wa
 	sync_and_handle_pending_serror
-	unmask_async_ea
 	b	handle_interrupt_exception
 end_vector_entry irq_aarch64
 
@@ -245,7 +243,6 @@
 	save_x30
 	apply_at_speculative_wa
 	sync_and_handle_pending_serror
-	unmask_async_ea
 	b 	handle_interrupt_exception
 end_vector_entry fiq_aarch64
 
@@ -258,7 +255,6 @@
 	save_x30
 	apply_at_speculative_wa
 	sync_and_handle_pending_serror
-	unmask_async_ea
 	b	handle_lower_el_async_ea
 #else
 	b	report_unhandled_exception
@@ -279,7 +275,6 @@
 	save_x30
 	apply_at_speculative_wa
 	sync_and_handle_pending_serror
-	unmask_async_ea
 	handle_sync_exception
 end_vector_entry sync_exception_aarch32
 
@@ -287,7 +282,6 @@
 	save_x30
 	apply_at_speculative_wa
 	sync_and_handle_pending_serror
-	unmask_async_ea
 	b	handle_interrupt_exception
 end_vector_entry irq_aarch32
 
@@ -295,7 +289,6 @@
 	save_x30
 	apply_at_speculative_wa
 	sync_and_handle_pending_serror
-	unmask_async_ea
 	b	handle_interrupt_exception
 end_vector_entry fiq_aarch32
 
@@ -308,7 +301,6 @@
 	save_x30
 	apply_at_speculative_wa
 	sync_and_handle_pending_serror
-	unmask_async_ea
 	b	handle_lower_el_async_ea
 #else
 	b	report_unhandled_exception
diff --git a/changelog.yaml b/changelog.yaml
index 5224441..3591f02 100644
--- a/changelog.yaml
+++ b/changelog.yaml
@@ -900,6 +900,9 @@
       - title: Console
         scope: console
 
+      - title: Delay Timer
+        scope: delay-timer
+
       - title: Generic Clock
         scope: clk
 
diff --git a/common/feat_detect.c b/common/feat_detect.c
index 9b9f7b4..e63eec4 100644
--- a/common/feat_detect.c
+++ b/common/feat_detect.c
@@ -257,6 +257,18 @@
 
 }
 
+static unsigned int read_feat_the_id_field(void)
+{
+	return ISOLATE_FIELD(read_id_aa64pfr1_el1(), ID_AA64PFR1_EL1_THE_SHIFT,
+			     ID_AA64PFR1_EL1_THE_MASK);
+}
+
+static unsigned int read_feat_sctlr2_id_field(void)
+{
+	return ISOLATE_FIELD(read_id_aa64mmfr3_el1(), ID_AA64MMFR3_EL1_SCTLR2_SHIFT,
+			     ID_AA64MMFR3_EL1_SCTLR2_MASK);
+}
+
 /***********************************************************************************
  * TF-A supports many Arm architectural features starting from arch version
  * (8.0 till 8.7+). These features are mostly enabled through build flags. This
@@ -365,6 +377,10 @@
 		      "CSV2_3", 3, 3);
 	check_feature(ENABLE_FEAT_DEBUGV8P9, read_feat_debugv8p9_id_field(),
 			"DEBUGV8P9", 11, 11);
+	check_feature(ENABLE_FEAT_THE, read_feat_the_id_field(),
+			"THE", 1, 1);
+	check_feature(ENABLE_FEAT_SCTLR2, read_feat_sctlr2_id_field(),
+			"SCTLR2", 1, 1);
 
 	/* v9.0 features */
 	check_feature(ENABLE_BRBE_FOR_NS, read_feat_brbe_id_field(),
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index 4d08a7f..03526a6 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -49,12 +49,14 @@
 :|G|: `laurenw-arm`_
 :|M|: Madhukar Pappireddy <Madhukar.Pappireddy@arm.com>
 :|G|: `madhukar-Arm`_
-:|M|: Raghu Krishnamurthy <raghu.ncstate@icloud.com>
+:|M|: Raghu Krishnamurthy <raghuoss@raghushome.com>
 :|G|: `raghuncstate`_
 :|M|: Manish Badarkhe <manish.badarkhe@arm.com>
 :|G|: `ManishVB-Arm`_
 :|M|: Yann Gautier <yann.gautier@st.com>
 :|G|: `Yann-lms`_
+:|M|: Govindraj Raja <govindraj.raja@arm.com>
+:|G|: `govindraj-arm`_
 
 LTS Maintainers
 ---------------
@@ -1016,7 +1018,7 @@
 :|G|: `sandrine-bailleux-arm`_
 :|M|: Joanna Farley <joanna.farley@arm.com>
 :|G|: `joannafarley-arm`_
-:|M|: Raghu Krishnamurthy <raghu.ncstate@icloud.com>
+:|M|: Raghu Krishnamurthy <raghuoss@raghushome.com>
 :|G|: `raghuncstate`_
 :|M|: Varun Wadekar <vwadekar@nvidia.com>
 :|G|: `vwadekar`_
@@ -1055,6 +1057,7 @@
 .. _divin-raj: https://github.com/divin-raj
 .. _etienne-lms: https://github.com/etienne-lms
 .. _glneo: https://github.com/glneo
+.. _govindraj-arm: https://github.com/govindraj-arm
 .. _gprocopciucnxp: https://github.com/gprocopciucnxp
 .. _grandpaul: https://github.com/grandpaul
 .. _harrisonmutai-arm: https://github.com/harrisonmutai-arm
diff --git a/docs/about/release-information.rst b/docs/about/release-information.rst
index 7fe58f8..9d6bbf6 100644
--- a/docs/about/release-information.rst
+++ b/docs/about/release-information.rst
@@ -72,6 +72,8 @@
 +-----------------+---------------------------+------------------------------+
 | v2.12           | 4th week of Nov '24       | 2nd week of Nov '24          |
 +-----------------+---------------------------+------------------------------+
+| v2.13           | 4th week of May '25       | 2nd week of May '25          |
++-----------------+---------------------------+------------------------------+
 
 Removal of Deprecated Interfaces
 --------------------------------
@@ -111,9 +113,9 @@
 +-----------------------+--------------------------------+
 | Build Option          | Deprecated from TF-A Version   |
 +=======================+================================+
-| CTX_INCLUDE_MTE_REGS  | 2.11                           |
+|                       |                                |
 +-----------------------+--------------------------------+
-| ENABLE_FEAT_MTE       | 2.11                           |
+|                       |                                |
 +-----------------------+--------------------------------+
 
 --------------
diff --git a/docs/components/secure-partition-manager.rst b/docs/components/secure-partition-manager.rst
index 220c3ce..a181204 100644
--- a/docs/components/secure-partition-manager.rst
+++ b/docs/components/secure-partition-manager.rst
@@ -110,7 +110,7 @@
 - Only Arm's FVP platform is supported to use with the TF-A reference software
   stack.
 - When ``SPMD_SPM_AT_SEL2=1``, the reference software stack assumes enablement
-  of FEAT_PAuth, FEAT_BTI and FEAT_MTE architecture extensions.
+  of FEAT_PAuth, FEAT_BTI and FEAT_MTE2 architecture extensions.
 - ``(*) CTX_INCLUDE_EL2_REGS``, this flag is |TF-A| internal and informational
   in this table. When set, it provides the generic support for saving/restoring
   EL2 registers required when S-EL2 firmware is present.
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 203bf0f..7776f5b 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -455,6 +455,22 @@
    the values 0 to 2, to align  with the ``ENABLE_FEAT`` mechanism.
    Default value is ``0``.
 
+-  ``ENABLE_FEAT_THE``: Numeric value to enable support for FEAT_THE
+   (Translation Hardening Extension) at EL2 and below, setting the bit
+   SCR_EL3.RCWMASKEn in EL3 to allow access to RCWMASK_EL1 and RCWSMASK_EL1
+   registers and context switch them.
+   Its an optional architectural feature and is available from v8.8 and upwards.
+   This flag can take the values 0 to 2, to align  with the ``ENABLE_FEAT``
+   mechanism. Default value is ``0``.
+
+-  ``ENABLE_FEAT_SCTLR2``: Numeric value to enable support for FEAT_SCTLR2
+   (Extension to SCTLR_ELx) at EL2 and below, setting the bit
+   SCR_EL3.SCTLR2En in EL3 to allow access to SCTLR2_ELx registers and
+   context switch them. This feature is OPTIONAL from Armv8.0 implementations
+   and mandatory in Armv8.9 implementations.
+   This flag can take the values 0 to 2, to align  with the ``ENABLE_FEAT``
+   mechanism. Default value is ``0``.
+
 -  ``ENABLE_LTO``: Boolean option to enable Link Time Optimization (LTO)
    support in GCC for TF-A. This option is currently only supported for
    AArch64. Default is 0.
diff --git a/docs/plat/index.rst b/docs/plat/index.rst
index 85c97e5..a8e0c8d 100644
--- a/docs/plat/index.rst
+++ b/docs/plat/index.rst
@@ -72,8 +72,8 @@
 +----------------+----------------+--------------------+--------------------+
 |    Platform    |     Vendor     | Deprecated version |  Deleted version   |
 +================+================+====================+====================+
-| None at this   |                |                    |                    |
-| time.          |                |                    |                    |
+|      TC2       |      Arm       |        2.12        |         TBD        |
+|                |                |                    |                    |
 +----------------+----------------+--------------------+--------------------+
 
 --------------
diff --git a/drivers/arm/dcc/dcc_console.c b/drivers/arm/dcc/dcc_console.c
index 19c3450..841c1fd 100644
--- a/drivers/arm/dcc/dcc_console.c
+++ b/drivers/arm/dcc/dcc_console.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2015-2021, Xilinx Inc.
+ * Copyright (c) 2015-2022, Xilinx Inc.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
  * Written by Michal Simek.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -45,7 +46,7 @@
 #define TIMEOUT_COUNT_US	U(0x10624)
 
 struct dcc_console {
-	struct console console;
+	console_t console;
 };
 
 static inline uint32_t __dcc_getstatus(void)
@@ -147,13 +148,14 @@
 	},
 };
 
-int console_dcc_register(void)
+int console_dcc_register(console_t *console)
 {
-	return console_register(&dcc_console.console);
+	memcpy(console, &dcc_console.console, sizeof(console_t));
+	return console_register(console);
 }
 
-void console_dcc_unregister(void)
+void console_dcc_unregister(console_t *console)
 {
-	dcc_console_flush(&dcc_console.console);
-	(void)console_unregister(&dcc_console.console);
+	dcc_console_flush(console);
+	(void)console_unregister(console);
 }
diff --git a/drivers/delay_timer/delay_timer.c b/drivers/delay_timer/delay_timer.c
index a3fd7bf..bdbbbf6 100644
--- a/drivers/delay_timer/delay_timer.c
+++ b/drivers/delay_timer/delay_timer.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -80,3 +80,25 @@
 
 	timer_ops = ops_ptr;
 }
+
+/***********************************************************
+ * Initialize the timer in us
+ ***********************************************************/
+uint64_t timeout_init_us(uint32_t usec)
+{
+	assert(timer_ops != NULL);
+	assert(timer_ops->timeout_init_us != NULL);
+
+	return timer_ops->timeout_init_us(usec);
+}
+
+/***********************************************************
+ * check the given timeout elapsed or not.
+ ***********************************************************/
+bool timeout_elapsed(uint64_t cnt)
+{
+	assert(timer_ops != NULL);
+	assert(timer_ops->timeout_elapsed != NULL);
+
+	return timer_ops->timeout_elapsed(cnt);
+}
diff --git a/drivers/delay_timer/generic_delay_timer.c b/drivers/delay_timer/generic_delay_timer.c
index ca522e0..0407e38 100644
--- a/drivers/delay_timer/generic_delay_timer.c
+++ b/drivers/delay_timer/generic_delay_timer.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -18,7 +18,26 @@
 
 static timer_ops_t ops;
 
-static uint32_t get_timer_value(void)
+static uint64_t timeout_cnt_us2cnt(uint32_t us)
+{
+	return ((uint64_t)us * (uint64_t)read_cntfrq_el0()) / 1000000ULL;
+}
+
+static uint64_t generic_delay_timeout_init_us(uint32_t us)
+{
+	uint64_t cnt = timeout_cnt_us2cnt(us);
+
+	cnt += read_cntpct_el0();
+
+	return cnt;
+}
+
+static bool generic_delay_timeout_elapsed(uint64_t expire_cnt)
+{
+	return read_cntpct_el0() > expire_cnt;
+}
+
+static uint32_t generic_delay_get_timer_value(void)
 {
 	/*
 	 * Generic delay timer implementation expects the timer to be a down
@@ -31,9 +50,11 @@
 
 void generic_delay_timer_init_args(uint32_t mult, uint32_t div)
 {
-	ops.get_timer_value	= get_timer_value;
+	ops.get_timer_value	= generic_delay_get_timer_value;
 	ops.clk_mult		= mult;
 	ops.clk_div		= div;
+	ops.timeout_init_us	= generic_delay_timeout_init_us;
+	ops.timeout_elapsed	= generic_delay_timeout_elapsed;
 
 	timer_init(&ops);
 
@@ -59,4 +80,3 @@
 
 	generic_delay_timer_init_args(mult, div);
 }
-
diff --git a/drivers/st/ddr/phy/phyinit/src/ddrphy_phyinit_c_initphyconfig.c b/drivers/st/ddr/phy/phyinit/src/ddrphy_phyinit_c_initphyconfig.c
index 38b8a07..a0712b5 100644
--- a/drivers/st/ddr/phy/phyinit/src/ddrphy_phyinit_c_initphyconfig.c
+++ b/drivers/st/ddr/phy/phyinit/src/ddrphy_phyinit_c_initphyconfig.c
@@ -71,7 +71,7 @@
 	uint32_t anib;
 	uint32_t atxpren; /* Default to 0xf (max). Optimal setting is technology specific */
 	uint32_t atxprep; /* Default to 0xf (max). Optimal setting is technology specific */
-	uint32_t ck_anib_inst[2];
+	uint32_t ck_anib_inst[2] = {0};
 
 	atxprep = config->uia.txslewriseac;
 	atxpren = config->uia.txslewfallac;
@@ -1012,7 +1012,6 @@
 		} else if (anib == 7U) {
 			aforcetricont = 0xFU;
 		}
-#endif /* STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE */
 
 		/*
 		 * If all the lanes can be disabled, and Anib is not the first or last disable
@@ -1022,6 +1021,8 @@
 		    (anib != (config->uib.numanib - 1U))) {
 			acx4anibdis = acx4anibdis | (0x1U << anib);
 		}
+#endif /* STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE */
+
 		mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TANIB | c_addr |
 								CSR_AFORCETRICONT_ADDR))),
 			      aforcetricont);
diff --git a/fdts/stm32mp25-bl2.dtsi b/fdts/stm32mp25-bl2.dtsi
index e250e3f..e6662d0 100644
--- a/fdts/stm32mp25-bl2.dtsi
+++ b/fdts/stm32mp25-bl2.dtsi
@@ -31,6 +31,7 @@
 			bl32_extra2_uuid = "8ea87bb1-cfa2-3f4d-85fd-e7bba50220d9";
 			bl33_uuid = "d6d0eea7-fcea-d54b-9782-9934f234b6e4";
 			hw_cfg_uuid = "08b8f1d9-c9cf-9349-a962-6fbc6b7265cc";
+			soc_fw_cfg_uuid = "9979814b-0376-fb46-8c8e-8d267f7859e0";
 			tos_fw_cfg_uuid = "26257c1a-dbc6-7f47-8d96-c4c4b0248021";
 			nt_fw_cfg_uuid = "28da9815-93e8-7e44-ac66-1aaf801550f9";
 		};
diff --git a/fdts/stm32mp25-bl31.dtsi b/fdts/stm32mp25-bl31.dtsi
new file mode 100644
index 0000000..fa63f63
--- /dev/null
+++ b/fdts/stm32mp25-bl31.dtsi
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause)
+/*
+ * Copyright (C) 2024, STMicroelectronics - All Rights Reserved
+ */
+
+/ {
+	soc@0 {
+		rifsc@42080000 {
+			/delete-node/ mmc@48220000;
+			/delete-node/ mmc@48230000;
+		};
+	};
+};
diff --git a/fdts/stm32mp25-ddr.dtsi b/fdts/stm32mp25-ddr.dtsi
new file mode 100644
index 0000000..1fcd13d
--- /dev/null
+++ b/fdts/stm32mp25-ddr.dtsi
@@ -0,0 +1,253 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2024, STMicroelectronics - All Rights Reserved
+ */
+
+&ddr{
+	st,mem-name = DDR_MEM_NAME;
+	st,mem-speed = <DDR_MEM_SPEED>;
+	st,mem-size = <(DDR_MEM_SIZE >> 32) (DDR_MEM_SIZE & 0xFFFFFFFF)>;
+
+	st,ctl-reg = <
+		DDR_MSTR
+		DDR_MRCTRL0
+		DDR_MRCTRL1
+		DDR_MRCTRL2
+		DDR_DERATEEN
+		DDR_DERATEINT
+		DDR_DERATECTL
+		DDR_PWRCTL
+		DDR_PWRTMG
+		DDR_HWLPCTL
+		DDR_RFSHCTL0
+		DDR_RFSHCTL1
+		DDR_RFSHCTL3
+		DDR_CRCPARCTL0
+		DDR_CRCPARCTL1
+		DDR_INIT0
+		DDR_INIT1
+		DDR_INIT2
+		DDR_INIT3
+		DDR_INIT4
+		DDR_INIT5
+		DDR_INIT6
+		DDR_INIT7
+		DDR_DIMMCTL
+		DDR_RANKCTL
+		DDR_RANKCTL1
+		DDR_ZQCTL0
+		DDR_ZQCTL1
+		DDR_ZQCTL2
+		DDR_DFITMG0
+		DDR_DFITMG1
+		DDR_DFILPCFG0
+		DDR_DFILPCFG1
+		DDR_DFIUPD0
+		DDR_DFIUPD1
+		DDR_DFIUPD2
+		DDR_DFIMISC
+		DDR_DFITMG2
+		DDR_DFITMG3
+		DDR_DBICTL
+		DDR_DFIPHYMSTR
+		DDR_DBG0
+		DDR_DBG1
+		DDR_DBGCMD
+		DDR_SWCTL
+		DDR_SWCTLSTATIC
+		DDR_POISONCFG
+		DDR_PCCFG
+	>;
+
+	st,ctl-timing = <
+		DDR_RFSHTMG
+		DDR_RFSHTMG1
+		DDR_DRAMTMG0
+		DDR_DRAMTMG1
+		DDR_DRAMTMG2
+		DDR_DRAMTMG3
+		DDR_DRAMTMG4
+		DDR_DRAMTMG5
+		DDR_DRAMTMG6
+		DDR_DRAMTMG7
+		DDR_DRAMTMG8
+		DDR_DRAMTMG9
+		DDR_DRAMTMG10
+		DDR_DRAMTMG11
+		DDR_DRAMTMG12
+		DDR_DRAMTMG13
+		DDR_DRAMTMG14
+		DDR_DRAMTMG15
+		DDR_ODTCFG
+		DDR_ODTMAP
+	>;
+
+	st,ctl-map = <
+		DDR_ADDRMAP0
+		DDR_ADDRMAP1
+		DDR_ADDRMAP2
+		DDR_ADDRMAP3
+		DDR_ADDRMAP4
+		DDR_ADDRMAP5
+		DDR_ADDRMAP6
+		DDR_ADDRMAP7
+		DDR_ADDRMAP8
+		DDR_ADDRMAP9
+		DDR_ADDRMAP10
+		DDR_ADDRMAP11
+	>;
+
+	st,ctl-perf = <
+		DDR_SCHED
+		DDR_SCHED1
+		DDR_PERFHPR1
+		DDR_PERFLPR1
+		DDR_PERFWR1
+		DDR_SCHED3
+		DDR_SCHED4
+		DDR_PCFGR_0
+		DDR_PCFGW_0
+		DDR_PCTRL_0
+		DDR_PCFGQOS0_0
+		DDR_PCFGQOS1_0
+		DDR_PCFGWQOS0_0
+		DDR_PCFGWQOS1_0
+		DDR_PCFGR_1
+		DDR_PCFGW_1
+		DDR_PCTRL_1
+		DDR_PCFGQOS0_1
+		DDR_PCFGQOS1_1
+		DDR_PCFGWQOS0_1
+		DDR_PCFGWQOS1_1
+	>;
+
+	st,phy-basic = <
+		DDR_UIB_DRAMTYPE
+		DDR_UIB_DIMMTYPE
+		DDR_UIB_LP4XMODE
+		DDR_UIB_NUMDBYTE
+		DDR_UIB_NUMACTIVEDBYTEDFI0
+		DDR_UIB_NUMACTIVEDBYTEDFI1
+		DDR_UIB_NUMANIB
+		DDR_UIB_NUMRANK_DFI0
+		DDR_UIB_NUMRANK_DFI1
+		DDR_UIB_DRAMDATAWIDTH
+		DDR_UIB_NUMPSTATES
+		DDR_UIB_FREQUENCY_0
+		DDR_UIB_PLLBYPASS_0
+		DDR_UIB_DFIFREQRATIO_0
+		DDR_UIB_DFI1EXISTS
+		DDR_UIB_TRAIN2D
+		DDR_UIB_HARDMACROVER
+		DDR_UIB_READDBIENABLE_0
+		DDR_UIB_DFIMODE
+	>;
+
+	st,phy-advanced = <
+		DDR_UIA_LP4RXPREAMBLEMODE_0
+		DDR_UIA_LP4POSTAMBLEEXT_0
+		DDR_UIA_D4RXPREAMBLELENGTH_0
+		DDR_UIA_D4TXPREAMBLELENGTH_0
+		DDR_UIA_EXTCALRESVAL
+		DDR_UIA_IS2TTIMING_0
+		DDR_UIA_ODTIMPEDANCE_0
+		DDR_UIA_TXIMPEDANCE_0
+		DDR_UIA_ATXIMPEDANCE
+		DDR_UIA_MEMALERTEN
+		DDR_UIA_MEMALERTPUIMP
+		DDR_UIA_MEMALERTVREFLEVEL
+		DDR_UIA_MEMALERTSYNCBYPASS
+		DDR_UIA_DISDYNADRTRI_0
+		DDR_UIA_PHYMSTRTRAININTERVAL_0
+		DDR_UIA_PHYMSTRMAXREQTOACK_0
+		DDR_UIA_WDQSEXT
+		DDR_UIA_CALINTERVAL
+		DDR_UIA_CALONCE
+		DDR_UIA_LP4RL_0
+		DDR_UIA_LP4WL_0
+		DDR_UIA_LP4WLS_0
+		DDR_UIA_LP4DBIRD_0
+		DDR_UIA_LP4DBIWR_0
+		DDR_UIA_LP4NWR_0
+		DDR_UIA_LP4LOWPOWERDRV
+		DDR_UIA_DRAMBYTESWAP
+		DDR_UIA_RXENBACKOFF
+		DDR_UIA_TRAINSEQUENCECTRL
+		DDR_UIA_SNPSUMCTLOPT
+		DDR_UIA_SNPSUMCTLF0RC5X_0
+		DDR_UIA_TXSLEWRISEDQ_0
+		DDR_UIA_TXSLEWFALLDQ_0
+		DDR_UIA_TXSLEWRISEAC
+		DDR_UIA_TXSLEWFALLAC
+		DDR_UIA_DISABLERETRAINING
+		DDR_UIA_DISABLEPHYUPDATE
+		DDR_UIA_ENABLEHIGHCLKSKEWFIX
+		DDR_UIA_DISABLEUNUSEDADDRLNS
+		DDR_UIA_PHYINITSEQUENCENUM
+		DDR_UIA_ENABLEDFICSPOLARITYFIX
+		DDR_UIA_PHYVREF
+		DDR_UIA_SEQUENCECTRL_0
+	>;
+
+	st,phy-mr = <
+		DDR_UIM_MR0_0
+		DDR_UIM_MR1_0
+		DDR_UIM_MR2_0
+		DDR_UIM_MR3_0
+		DDR_UIM_MR4_0
+		DDR_UIM_MR5_0
+		DDR_UIM_MR6_0
+		DDR_UIM_MR11_0
+		DDR_UIM_MR12_0
+		DDR_UIM_MR13_0
+		DDR_UIM_MR14_0
+		DDR_UIM_MR22_0
+	>;
+
+	st,phy-swizzle = <
+		DDR_UIS_SWIZZLE_0
+		DDR_UIS_SWIZZLE_1
+		DDR_UIS_SWIZZLE_2
+		DDR_UIS_SWIZZLE_3
+		DDR_UIS_SWIZZLE_4
+		DDR_UIS_SWIZZLE_5
+		DDR_UIS_SWIZZLE_6
+		DDR_UIS_SWIZZLE_7
+		DDR_UIS_SWIZZLE_8
+		DDR_UIS_SWIZZLE_9
+		DDR_UIS_SWIZZLE_10
+		DDR_UIS_SWIZZLE_11
+		DDR_UIS_SWIZZLE_12
+		DDR_UIS_SWIZZLE_13
+		DDR_UIS_SWIZZLE_14
+		DDR_UIS_SWIZZLE_15
+		DDR_UIS_SWIZZLE_16
+		DDR_UIS_SWIZZLE_17
+		DDR_UIS_SWIZZLE_18
+		DDR_UIS_SWIZZLE_19
+		DDR_UIS_SWIZZLE_20
+		DDR_UIS_SWIZZLE_21
+		DDR_UIS_SWIZZLE_22
+		DDR_UIS_SWIZZLE_23
+		DDR_UIS_SWIZZLE_24
+		DDR_UIS_SWIZZLE_25
+		DDR_UIS_SWIZZLE_26
+		DDR_UIS_SWIZZLE_27
+		DDR_UIS_SWIZZLE_28
+		DDR_UIS_SWIZZLE_29
+		DDR_UIS_SWIZZLE_30
+		DDR_UIS_SWIZZLE_31
+		DDR_UIS_SWIZZLE_32
+		DDR_UIS_SWIZZLE_33
+		DDR_UIS_SWIZZLE_34
+		DDR_UIS_SWIZZLE_35
+		DDR_UIS_SWIZZLE_36
+		DDR_UIS_SWIZZLE_37
+		DDR_UIS_SWIZZLE_38
+		DDR_UIS_SWIZZLE_39
+		DDR_UIS_SWIZZLE_40
+		DDR_UIS_SWIZZLE_41
+		DDR_UIS_SWIZZLE_42
+		DDR_UIS_SWIZZLE_43
+	>;
+};
diff --git a/fdts/stm32mp25-ddr4-2x16Gbits-2x16bits-1200MHz.dtsi b/fdts/stm32mp25-ddr4-2x16Gbits-2x16bits-1200MHz.dtsi
new file mode 100644
index 0000000..3d69448
--- /dev/null
+++ b/fdts/stm32mp25-ddr4-2x16Gbits-2x16bits-1200MHz.dtsi
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2022-2024, STMicroelectronics - All Rights Reserved
+ */
+
+/*
+ * STM32MP25 DDR4 board configuration
+ * DDR4 2x16Gbits 2x16bits 1200MHz
+ *
+ * version      2
+ * package      1        Package selection (14x14 and 18x18)
+ * memclk       1200MHz  (2x DFI clock) + range check
+ * Speed_Bin    Worse    from JEDEC
+ * device_width 16       x16 by default
+ * width        32       32: full width / 16: half width
+ * density      16Gbits  (per 16bit device)
+ * Addressing   RBC      row/bank interleaving
+ * RDBI         No       Read DBI
+ */
+
+#define DDR_MEM_NAME	"DDR4 2x16Gbits 2x16bits 1200MHz"
+#define DDR_MEM_SPEED	1200000
+#define DDR_MEM_SIZE	0x100000000
+
+#define DDR_MSTR 0x01040010
+#define DDR_MRCTRL0 0x00000030
+#define DDR_MRCTRL1 0x00000000
+#define DDR_MRCTRL2 0x00000000
+#define DDR_DERATEEN 0x00000000
+#define DDR_DERATEINT 0x00000000
+#define DDR_DERATECTL 0x00000000
+#define DDR_PWRCTL 0x00000000
+#define DDR_PWRTMG 0x00130001
+#define DDR_HWLPCTL 0x00000002
+#define DDR_RFSHCTL0 0x00210010
+#define DDR_RFSHCTL1 0x00000000
+#define DDR_RFSHCTL3 0x00000000
+#define DDR_RFSHTMG 0x0092014A
+#define DDR_RFSHTMG1 0x008C0000
+#define DDR_CRCPARCTL0 0x00000000
+#define DDR_CRCPARCTL1 0x00001000
+#define DDR_INIT0 0xC0020002
+#define DDR_INIT1 0x00010002
+#define DDR_INIT2 0x00000D00
+#define DDR_INIT3 0x09400103
+#define DDR_INIT4 0x00180000
+#define DDR_INIT5 0x00100004
+#define DDR_INIT6 0x00080460
+#define DDR_INIT7 0x00000C16
+#define DDR_DIMMCTL 0x00000000
+#define DDR_RANKCTL 0x0000066F
+#define DDR_RANKCTL1 0x0000000D
+#define DDR_DRAMTMG0 0x11152815
+#define DDR_DRAMTMG1 0x0004051E
+#define DDR_DRAMTMG2 0x0609060D
+#define DDR_DRAMTMG3 0x0050400C
+#define DDR_DRAMTMG4 0x0904050A
+#define DDR_DRAMTMG5 0x06060403
+#define DDR_DRAMTMG6 0x02020005
+#define DDR_DRAMTMG7 0x00000202
+#define DDR_DRAMTMG8 0x0606100B
+#define DDR_DRAMTMG9 0x0002040A
+#define DDR_DRAMTMG10 0x001C180A
+#define DDR_DRAMTMG11 0x4408021C
+#define DDR_DRAMTMG12 0x0C020010
+#define DDR_DRAMTMG13 0x1C200004
+#define DDR_DRAMTMG14 0x000000A0
+#define DDR_DRAMTMG15 0x00000000
+#define DDR_ZQCTL0 0x01000040
+#define DDR_ZQCTL1 0x2000493E
+#define DDR_ZQCTL2 0x00000000
+#define DDR_DFITMG0 0x038F8209
+#define DDR_DFITMG1 0x00080303
+#define DDR_DFILPCFG0 0x07004111
+#define DDR_DFILPCFG1 0x00000000
+#define DDR_DFIUPD0 0xC0300018
+#define DDR_DFIUPD1 0x005700B4
+#define DDR_DFIUPD2 0x80000000
+#define DDR_DFIMISC 0x00000041
+#define DDR_DFITMG2 0x00000F09
+#define DDR_DFITMG3 0x00000000
+#define DDR_DBICTL 0x00000001
+#define DDR_DFIPHYMSTR 0x80000000
+#define DDR_ADDRMAP0 0x0000001F
+#define DDR_ADDRMAP1 0x003F0909
+#define DDR_ADDRMAP2 0x00000700
+#define DDR_ADDRMAP3 0x00000000
+#define DDR_ADDRMAP4 0x00001F1F
+#define DDR_ADDRMAP5 0x070F0707
+#define DDR_ADDRMAP6 0x07070707
+#define DDR_ADDRMAP7 0x00000F07
+#define DDR_ADDRMAP8 0x00003F01
+#define DDR_ADDRMAP9 0x07070707
+#define DDR_ADDRMAP10 0x07070707
+#define DDR_ADDRMAP11 0x00000007
+#define DDR_ODTCFG 0x06000618
+#define DDR_ODTMAP 0x00000001
+#define DDR_SCHED 0x80001B00
+#define DDR_SCHED1 0x00000000
+#define DDR_PERFHPR1 0x04000200
+#define DDR_PERFLPR1 0x08000080
+#define DDR_PERFWR1 0x08000400
+#define DDR_SCHED3 0x04040208
+#define DDR_SCHED4 0x08400810
+#define DDR_DBG0 0x00000000
+#define DDR_DBG1 0x00000000
+#define DDR_DBGCMD 0x00000000
+#define DDR_SWCTL 0x00000000
+#define DDR_SWCTLSTATIC 0x00000000
+#define DDR_POISONCFG 0x00000000
+#define DDR_PCCFG 0x00000000
+#define DDR_PCFGR_0 0x00704100
+#define DDR_PCFGW_0 0x00004100
+#define DDR_PCTRL_0 0x00000000
+#define DDR_PCFGQOS0_0 0x0021000C
+#define DDR_PCFGQOS1_0 0x01000080
+#define DDR_PCFGWQOS0_0 0x01100C07
+#define DDR_PCFGWQOS1_0 0x04000200
+#define DDR_PCFGR_1 0x00704100
+#define DDR_PCFGW_1 0x00004100
+#define DDR_PCTRL_1 0x00000000
+#define DDR_PCFGQOS0_1 0x00100007
+#define DDR_PCFGQOS1_1 0x01000080
+#define DDR_PCFGWQOS0_1 0x01100C07
+#define DDR_PCFGWQOS1_1 0x04000200
+
+#define DDR_UIB_DRAMTYPE 0x00000000
+#define DDR_UIB_DIMMTYPE 0x00000004
+#define DDR_UIB_LP4XMODE 0x00000000
+#define DDR_UIB_NUMDBYTE 0x00000004
+#define DDR_UIB_NUMACTIVEDBYTEDFI0 0x00000004
+#define DDR_UIB_NUMACTIVEDBYTEDFI1 0x00000000
+#define DDR_UIB_NUMANIB 0x00000008
+#define DDR_UIB_NUMRANK_DFI0 0x00000001
+#define DDR_UIB_NUMRANK_DFI1 0x00000001
+#define DDR_UIB_DRAMDATAWIDTH 0x00000010
+#define DDR_UIB_NUMPSTATES 0x00000001
+#define DDR_UIB_FREQUENCY_0 0x000004B0
+#define DDR_UIB_PLLBYPASS_0 0x00000000
+#define DDR_UIB_DFIFREQRATIO_0 0x00000001
+#define DDR_UIB_DFI1EXISTS 0x00000001
+#define DDR_UIB_TRAIN2D 0x00000000
+#define DDR_UIB_HARDMACROVER 0x00000003
+#define DDR_UIB_READDBIENABLE_0 0x00000000
+#define DDR_UIB_DFIMODE 0x00000000
+
+#define DDR_UIA_LP4RXPREAMBLEMODE_0 0x00000000
+#define DDR_UIA_LP4POSTAMBLEEXT_0 0x00000000
+#define DDR_UIA_D4RXPREAMBLELENGTH_0 0x00000000
+#define DDR_UIA_D4TXPREAMBLELENGTH_0 0x00000000
+#define DDR_UIA_EXTCALRESVAL 0x00000000
+#define DDR_UIA_IS2TTIMING_0 0x00000000
+#define DDR_UIA_ODTIMPEDANCE_0 0x00000035
+#define DDR_UIA_TXIMPEDANCE_0 0x00000028
+#define DDR_UIA_ATXIMPEDANCE 0x00000028
+#define DDR_UIA_MEMALERTEN 0x00000000
+#define DDR_UIA_MEMALERTPUIMP 0x00000000
+#define DDR_UIA_MEMALERTVREFLEVEL 0x00000000
+#define DDR_UIA_MEMALERTSYNCBYPASS 0x00000000
+#define DDR_UIA_DISDYNADRTRI_0 0x00000001
+#define DDR_UIA_PHYMSTRTRAININTERVAL_0 0x00000000
+#define DDR_UIA_PHYMSTRMAXREQTOACK_0 0x00000000
+#define DDR_UIA_WDQSEXT 0x00000000
+#define DDR_UIA_CALINTERVAL 0x00000009
+#define DDR_UIA_CALONCE 0x00000000
+#define DDR_UIA_LP4RL_0 0x00000000
+#define DDR_UIA_LP4WL_0 0x00000000
+#define DDR_UIA_LP4WLS_0 0x00000000
+#define DDR_UIA_LP4DBIRD_0 0x00000000
+#define DDR_UIA_LP4DBIWR_0 0x00000000
+#define DDR_UIA_LP4NWR_0 0x00000000
+#define DDR_UIA_LP4LOWPOWERDRV 0x00000000
+#define DDR_UIA_DRAMBYTESWAP 0x00000000
+#define DDR_UIA_RXENBACKOFF 0x00000000
+#define DDR_UIA_TRAINSEQUENCECTRL 0x00000000
+#define DDR_UIA_SNPSUMCTLOPT 0x00000000
+#define DDR_UIA_SNPSUMCTLF0RC5X_0 0x00000000
+#define DDR_UIA_TXSLEWRISEDQ_0 0x0000000F
+#define DDR_UIA_TXSLEWFALLDQ_0 0x0000000F
+#define DDR_UIA_TXSLEWRISEAC 0x0000000F
+#define DDR_UIA_TXSLEWFALLAC 0x0000000F
+#define DDR_UIA_DISABLERETRAINING 0x00000001
+#define DDR_UIA_DISABLEPHYUPDATE 0x00000000
+#define DDR_UIA_ENABLEHIGHCLKSKEWFIX 0x00000000
+#define DDR_UIA_DISABLEUNUSEDADDRLNS 0x00000001
+#define DDR_UIA_PHYINITSEQUENCENUM 0x00000000
+#define DDR_UIA_ENABLEDFICSPOLARITYFIX 0x00000000
+#define DDR_UIA_PHYVREF 0x0000005E
+#define DDR_UIA_SEQUENCECTRL_0 0x0000031F
+
+#define DDR_UIM_MR0_0 0x00000940
+#define DDR_UIM_MR1_0 0x00000103
+#define DDR_UIM_MR2_0 0x00000018
+#define DDR_UIM_MR3_0 0x00000000
+#define DDR_UIM_MR4_0 0x00000008
+#define DDR_UIM_MR5_0 0x00000460
+#define DDR_UIM_MR6_0 0x00000C16
+#define DDR_UIM_MR11_0 0x00000000
+#define DDR_UIM_MR12_0 0x00000000
+#define DDR_UIM_MR13_0 0x00000000
+#define DDR_UIM_MR14_0 0x00000000
+#define DDR_UIM_MR22_0 0x00000000
+
+#define DDR_UIS_SWIZZLE_0 0x0000000C
+#define DDR_UIS_SWIZZLE_1 0x00000005
+#define DDR_UIS_SWIZZLE_2 0x00000013
+#define DDR_UIS_SWIZZLE_3 0x0000001A
+#define DDR_UIS_SWIZZLE_4 0x00000009
+#define DDR_UIS_SWIZZLE_5 0x00000003
+#define DDR_UIS_SWIZZLE_6 0x00000001
+#define DDR_UIS_SWIZZLE_7 0x00000019
+#define DDR_UIS_SWIZZLE_8 0x00000007
+#define DDR_UIS_SWIZZLE_9 0x00000004
+#define DDR_UIS_SWIZZLE_10 0x0000000A
+#define DDR_UIS_SWIZZLE_11 0x0000000D
+#define DDR_UIS_SWIZZLE_12 0x00000014
+#define DDR_UIS_SWIZZLE_13 0x00000000
+#define DDR_UIS_SWIZZLE_14 0x00000000
+#define DDR_UIS_SWIZZLE_15 0x00000000
+#define DDR_UIS_SWIZZLE_16 0x00000000
+#define DDR_UIS_SWIZZLE_17 0x00000000
+#define DDR_UIS_SWIZZLE_18 0x00000006
+#define DDR_UIS_SWIZZLE_19 0x0000000B
+#define DDR_UIS_SWIZZLE_20 0x00000000
+#define DDR_UIS_SWIZZLE_21 0x00000000
+#define DDR_UIS_SWIZZLE_22 0x00000000
+#define DDR_UIS_SWIZZLE_23 0x00000008
+#define DDR_UIS_SWIZZLE_24 0x00000002
+#define DDR_UIS_SWIZZLE_25 0x00000018
+#define DDR_UIS_SWIZZLE_26 0x1A13050C
+#define DDR_UIS_SWIZZLE_27 0x19010309
+#define DDR_UIS_SWIZZLE_28 0x0D0A0407
+#define DDR_UIS_SWIZZLE_29 0x00000014
+#define DDR_UIS_SWIZZLE_30 0x000B0600
+#define DDR_UIS_SWIZZLE_31 0x02080000
+#define DDR_UIS_SWIZZLE_32 0x00000018
+#define DDR_UIS_SWIZZLE_33 0x00000000
+#define DDR_UIS_SWIZZLE_34 0x00000000
+#define DDR_UIS_SWIZZLE_35 0x00000000
+#define DDR_UIS_SWIZZLE_36 0x00000000
+#define DDR_UIS_SWIZZLE_37 0x00000000
+#define DDR_UIS_SWIZZLE_38 0x00000000
+#define DDR_UIS_SWIZZLE_39 0x00000000
+#define DDR_UIS_SWIZZLE_40 0x00000000
+#define DDR_UIS_SWIZZLE_41 0x00000000
+#define DDR_UIS_SWIZZLE_42 0x00000000
+#define DDR_UIS_SWIZZLE_43 0x00000000
+
+#include "stm32mp25-ddr.dtsi"
diff --git a/fdts/stm32mp25-ddr4-2x8Gbits-2x16bits-1200MHz.dtsi b/fdts/stm32mp25-ddr4-2x8Gbits-2x16bits-1200MHz.dtsi
new file mode 100644
index 0000000..674cb3d
--- /dev/null
+++ b/fdts/stm32mp25-ddr4-2x8Gbits-2x16bits-1200MHz.dtsi
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2022-2024, STMicroelectronics - All Rights Reserved
+ */
+
+/*
+ * STM32MP25 DDR4 board configuration
+ * DDR4 2x8Gbits 2x16bits 1200MHz
+ *
+ * version     1
+ * package     1        Package selection (14x14 and 18x18)
+ * memclk      1200MHz  (2x DFI clock) + range check
+ * Speed_Bin   Worse    from JEDEC
+ * width       32       32: full width / 16: half width
+ * ranks       1        Single or Dual rank
+ * density     8Gbits   (per 16bit device)
+ * Addressing  RBC      row/bank interleaving
+ * RDBI        No       Read DBI
+ */
+
+#define DDR_MEM_NAME	"DDR4 2x8Gbits 2x16bits 1200MHz"
+#define DDR_MEM_SPEED	1200000
+#define DDR_MEM_SIZE	0x80000000
+
+#define DDR_MSTR 0x01040010
+#define DDR_MRCTRL0 0x00000030
+#define DDR_MRCTRL1 0x00000000
+#define DDR_MRCTRL2 0x00000000
+#define DDR_DERATEEN 0x00000000
+#define DDR_DERATEINT 0x00000000
+#define DDR_DERATECTL 0x00000000
+#define DDR_PWRCTL 0x00000000
+#define DDR_PWRTMG 0x00130001
+#define DDR_HWLPCTL 0x00000002
+#define DDR_RFSHCTL0 0x00210010
+#define DDR_RFSHCTL1 0x00000000
+#define DDR_RFSHCTL3 0x00000000
+#define DDR_RFSHTMG 0x009200D2
+#define DDR_RFSHTMG1 0x008C0000
+#define DDR_CRCPARCTL0 0x00000000
+#define DDR_CRCPARCTL1 0x00001000
+#define DDR_INIT0 0xC0020002
+#define DDR_INIT1 0x00010002
+#define DDR_INIT2 0x00000D00
+#define DDR_INIT3 0x09400103
+#define DDR_INIT4 0x00180000
+#define DDR_INIT5 0x00100004
+#define DDR_INIT6 0x00080460
+#define DDR_INIT7 0x00000C16
+#define DDR_DIMMCTL 0x00000000
+#define DDR_RANKCTL 0x0000066F
+#define DDR_DRAMTMG0 0x11152815
+#define DDR_DRAMTMG1 0x0004051E
+#define DDR_DRAMTMG2 0x0609060D
+#define DDR_DRAMTMG3 0x0050400C
+#define DDR_DRAMTMG4 0x0904050A
+#define DDR_DRAMTMG5 0x06060403
+#define DDR_DRAMTMG6 0x02020005
+#define DDR_DRAMTMG7 0x00000202
+#define DDR_DRAMTMG8 0x04041007
+#define DDR_DRAMTMG9 0x0002040A
+#define DDR_DRAMTMG10 0x001C180A
+#define DDR_DRAMTMG11 0x4408021C
+#define DDR_DRAMTMG12 0x0C020010
+#define DDR_DRAMTMG13 0x1C200004
+#define DDR_DRAMTMG14 0x000000A0
+#define DDR_DRAMTMG15 0x00000000
+#define DDR_ZQCTL0 0x01000040
+#define DDR_ZQCTL1 0x2000493E
+#define DDR_ZQCTL2 0x00000000
+#define DDR_DFITMG0 0x038F8209
+#define DDR_DFITMG1 0x00080303
+#define DDR_DFILPCFG0 0x07004111
+#define DDR_DFILPCFG1 0x00000000
+#define DDR_DFIUPD0 0xC0300018
+#define DDR_DFIUPD1 0x005700B4
+#define DDR_DFIUPD2 0x80000000
+#define DDR_DFIMISC 0x00000041
+#define DDR_DFITMG2 0x00000F09
+#define DDR_DFITMG3 0x00000000
+#define DDR_DBICTL 0x00000001
+#define DDR_DFIPHYMSTR 0x80000000
+#define DDR_ADDRMAP0 0x0000001F
+#define DDR_ADDRMAP1 0x003F0909
+#define DDR_ADDRMAP2 0x00000700
+#define DDR_ADDRMAP3 0x00000000
+#define DDR_ADDRMAP4 0x00001F1F
+#define DDR_ADDRMAP5 0x070F0707
+#define DDR_ADDRMAP6 0x07070707
+#define DDR_ADDRMAP7 0x00000F0F
+#define DDR_ADDRMAP8 0x00003F01
+#define DDR_ADDRMAP9 0x07070707
+#define DDR_ADDRMAP10 0x07070707
+#define DDR_ADDRMAP11 0x00000007
+#define DDR_ODTCFG 0x06000618
+#define DDR_ODTMAP 0x00000001
+#define DDR_SCHED 0x00000F00
+#define DDR_SCHED1 0x00000000
+#define DDR_PERFHPR1 0x0F000001
+#define DDR_PERFLPR1 0x0F000080
+#define DDR_PERFWR1 0x01000200
+#define DDR_DBG0 0x00000000
+#define DDR_DBG1 0x00000000
+#define DDR_DBGCMD 0x00000000
+#define DDR_SWCTL 0x00000000
+#define DDR_POISONCFG 0x00000000
+#define DDR_PCCFG 0x00000000
+#define DDR_PCFGR_0 0x00004100
+#define DDR_PCFGW_0 0x00004100
+#define DDR_PCTRL_0 0x00000000
+#define DDR_PCFGQOS0_0 0x00200007
+#define DDR_PCFGQOS1_0 0x01000100
+#define DDR_PCFGWQOS0_0 0x00000C07
+#define DDR_PCFGWQOS1_0 0x02000200
+#define DDR_PCFGR_1 0x00004100
+#define DDR_PCFGW_1 0x00004100
+#define DDR_PCTRL_1 0x00000000
+#define DDR_PCFGQOS0_1 0x00200007
+#define DDR_PCFGQOS1_1 0x01000180
+#define DDR_PCFGWQOS0_1 0x00000C07
+#define DDR_PCFGWQOS1_1 0x04000400
+
+#define DDR_UIB_DRAMTYPE 0x00000000
+#define DDR_UIB_DIMMTYPE 0x00000004
+#define DDR_UIB_LP4XMODE 0x00000000
+#define DDR_UIB_NUMDBYTE 0x00000004
+#define DDR_UIB_NUMACTIVEDBYTEDFI0 0x00000004
+#define DDR_UIB_NUMACTIVEDBYTEDFI1 0x00000000
+#define DDR_UIB_NUMANIB 0x00000008
+#define DDR_UIB_NUMRANK_DFI0 0x00000001
+#define DDR_UIB_NUMRANK_DFI1 0x00000001
+#define DDR_UIB_DRAMDATAWIDTH 0x00000010
+#define DDR_UIB_NUMPSTATES 0x00000001
+#define DDR_UIB_FREQUENCY_0 0x000004B0
+#define DDR_UIB_PLLBYPASS_0 0x00000000
+#define DDR_UIB_DFIFREQRATIO_0 0x00000001
+#define DDR_UIB_DFI1EXISTS 0x00000001
+#define DDR_UIB_TRAIN2D 0x00000000
+#define DDR_UIB_HARDMACROVER 0x00000003
+#define DDR_UIB_READDBIENABLE_0 0x00000000
+#define DDR_UIB_DFIMODE 0x00000000
+
+#define DDR_UIA_LP4RXPREAMBLEMODE_0 0x00000000
+#define DDR_UIA_LP4POSTAMBLEEXT_0 0x00000000
+#define DDR_UIA_D4RXPREAMBLELENGTH_0 0x00000000
+#define DDR_UIA_D4TXPREAMBLELENGTH_0 0x00000000
+#define DDR_UIA_EXTCALRESVAL 0x00000000
+#define DDR_UIA_IS2TTIMING_0 0x00000000
+#define DDR_UIA_ODTIMPEDANCE_0 0x00000035
+#define DDR_UIA_TXIMPEDANCE_0 0x00000028
+#define DDR_UIA_ATXIMPEDANCE 0x00000028
+#define DDR_UIA_MEMALERTEN 0x00000000
+#define DDR_UIA_MEMALERTPUIMP 0x00000000
+#define DDR_UIA_MEMALERTVREFLEVEL 0x00000000
+#define DDR_UIA_MEMALERTSYNCBYPASS 0x00000000
+#define DDR_UIA_DISDYNADRTRI_0 0x00000001
+#define DDR_UIA_PHYMSTRTRAININTERVAL_0 0x00000000
+#define DDR_UIA_PHYMSTRMAXREQTOACK_0 0x00000000
+#define DDR_UIA_WDQSEXT 0x00000000
+#define DDR_UIA_CALINTERVAL 0x00000009
+#define DDR_UIA_CALONCE 0x00000000
+#define DDR_UIA_LP4RL_0 0x00000000
+#define DDR_UIA_LP4WL_0 0x00000000
+#define DDR_UIA_LP4WLS_0 0x00000000
+#define DDR_UIA_LP4DBIRD_0 0x00000000
+#define DDR_UIA_LP4DBIWR_0 0x00000000
+#define DDR_UIA_LP4NWR_0 0x00000000
+#define DDR_UIA_LP4LOWPOWERDRV 0x00000000
+#define DDR_UIA_DRAMBYTESWAP 0x00000000
+#define DDR_UIA_RXENBACKOFF 0x00000000
+#define DDR_UIA_TRAINSEQUENCECTRL 0x00000000
+#define DDR_UIA_SNPSUMCTLOPT 0x00000000
+#define DDR_UIA_SNPSUMCTLF0RC5X_0 0x00000000
+#define DDR_UIA_TXSLEWRISEDQ_0 0x0000000F
+#define DDR_UIA_TXSLEWFALLDQ_0 0x0000000F
+#define DDR_UIA_TXSLEWRISEAC 0x0000000F
+#define DDR_UIA_TXSLEWFALLAC 0x0000000F
+#define DDR_UIA_DISABLERETRAINING 0x00000001
+#define DDR_UIA_DISABLEPHYUPDATE 0x00000000
+#define DDR_UIA_ENABLEHIGHCLKSKEWFIX 0x00000000
+#define DDR_UIA_DISABLEUNUSEDADDRLNS 0x00000001
+#define DDR_UIA_PHYINITSEQUENCENUM 0x00000000
+#define DDR_UIA_ENABLEDFICSPOLARITYFIX 0x00000000
+#define DDR_UIA_PHYVREF 0x0000005E
+#define DDR_UIA_SEQUENCECTRL_0 0x0000031F
+
+#define DDR_UIM_MR0_0 0x00000940
+#define DDR_UIM_MR1_0 0x00000103
+#define DDR_UIM_MR2_0 0x00000018
+#define DDR_UIM_MR3_0 0x00000000
+#define DDR_UIM_MR4_0 0x00000008
+#define DDR_UIM_MR5_0 0x00000460
+#define DDR_UIM_MR6_0 0x00000C16
+#define DDR_UIM_MR11_0 0x00000000
+#define DDR_UIM_MR12_0 0x00000000
+#define DDR_UIM_MR13_0 0x00000000
+#define DDR_UIM_MR14_0 0x00000000
+#define DDR_UIM_MR22_0 0x00000000
+
+#define DDR_UIS_SWIZZLE_0 0x0000000C
+#define DDR_UIS_SWIZZLE_1 0x00000005
+#define DDR_UIS_SWIZZLE_2 0x00000013
+#define DDR_UIS_SWIZZLE_3 0x0000001A
+#define DDR_UIS_SWIZZLE_4 0x00000009
+#define DDR_UIS_SWIZZLE_5 0x00000003
+#define DDR_UIS_SWIZZLE_6 0x00000001
+#define DDR_UIS_SWIZZLE_7 0x00000019
+#define DDR_UIS_SWIZZLE_8 0x00000007
+#define DDR_UIS_SWIZZLE_9 0x00000004
+#define DDR_UIS_SWIZZLE_10 0x0000000A
+#define DDR_UIS_SWIZZLE_11 0x0000000D
+#define DDR_UIS_SWIZZLE_12 0x00000014
+#define DDR_UIS_SWIZZLE_13 0x00000000
+#define DDR_UIS_SWIZZLE_14 0x00000000
+#define DDR_UIS_SWIZZLE_15 0x00000000
+#define DDR_UIS_SWIZZLE_16 0x00000000
+#define DDR_UIS_SWIZZLE_17 0x00000000
+#define DDR_UIS_SWIZZLE_18 0x00000006
+#define DDR_UIS_SWIZZLE_19 0x0000000B
+#define DDR_UIS_SWIZZLE_20 0x00000000
+#define DDR_UIS_SWIZZLE_21 0x00000000
+#define DDR_UIS_SWIZZLE_22 0x00000000
+#define DDR_UIS_SWIZZLE_23 0x00000008
+#define DDR_UIS_SWIZZLE_24 0x00000002
+#define DDR_UIS_SWIZZLE_25 0x00000018
+#define DDR_UIS_SWIZZLE_26 0x1A13050C
+#define DDR_UIS_SWIZZLE_27 0x19010309
+#define DDR_UIS_SWIZZLE_28 0x0D0A0407
+#define DDR_UIS_SWIZZLE_29 0x00000014
+#define DDR_UIS_SWIZZLE_30 0x000B0600
+#define DDR_UIS_SWIZZLE_31 0x02080000
+#define DDR_UIS_SWIZZLE_32 0x00000018
+#define DDR_UIS_SWIZZLE_33 0x00000000
+#define DDR_UIS_SWIZZLE_34 0x00000000
+#define DDR_UIS_SWIZZLE_35 0x00000000
+#define DDR_UIS_SWIZZLE_36 0x00000000
+#define DDR_UIS_SWIZZLE_37 0x00000000
+#define DDR_UIS_SWIZZLE_38 0x00000000
+#define DDR_UIS_SWIZZLE_39 0x00000000
+#define DDR_UIS_SWIZZLE_40 0x00000000
+#define DDR_UIS_SWIZZLE_41 0x00000000
+#define DDR_UIS_SWIZZLE_42 0x00000000
+#define DDR_UIS_SWIZZLE_43 0x00000000
+
+#include "stm32mp25-ddr.dtsi"
diff --git a/fdts/stm32mp25-fw-config.dtsi b/fdts/stm32mp25-fw-config.dtsi
index 102980d..2f83f24 100644
--- a/fdts/stm32mp25-fw-config.dtsi
+++ b/fdts/stm32mp25-fw-config.dtsi
@@ -31,6 +31,10 @@
 			id = <BL31_IMAGE_ID>;
 		};
 
+		soc_fw-config {
+			id = <SOC_FW_CONFIG_ID>;
+		};
+
 		tos_fw {
 			id = <BL32_IMAGE_ID>;
 		};
diff --git a/fdts/stm32mp251.dtsi b/fdts/stm32mp251.dtsi
index 9e89813..c2c2764 100644
--- a/fdts/stm32mp251.dtsi
+++ b/fdts/stm32mp251.dtsi
@@ -328,6 +328,13 @@
 			reg = <0x44230000 0x10000>;
 		};
 
+		ddr: ddr@48040000 {
+			compatible = "st,stm32mp2-ddr";
+			reg = <0x48040000 0x10000>,
+			      <0x48c00000 0x400000>;
+			status = "okay";
+		};
+
 		pinctrl: pinctrl@44240000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
diff --git a/fdts/stm32mp257f-ev1-ca35tdcid-fw-config.dtsi b/fdts/stm32mp257f-ev1-ca35tdcid-fw-config.dtsi
index e41c6b9..5bfcf8d 100644
--- a/fdts/stm32mp257f-ev1-ca35tdcid-fw-config.dtsi
+++ b/fdts/stm32mp257f-ev1-ca35tdcid-fw-config.dtsi
@@ -11,6 +11,10 @@
 
 / {
 	dtb-registry {
+		soc_fw-config {
+			load-address = <0x0 0x81ff0000>;
+			max-size = <0x10000>;
+		};
 		tos_fw {
 			load-address = <0x0 0x82000000>;
 			max-size = <0x2000000>;
diff --git a/fdts/stm32mp257f-ev1.dts b/fdts/stm32mp257f-ev1.dts
index d2b5e55..5d5e35d 100644
--- a/fdts/stm32mp257f-ev1.dts
+++ b/fdts/stm32mp257f-ev1.dts
@@ -10,6 +10,7 @@
 #include "stm32mp257.dtsi"
 #include "stm32mp25xf.dtsi"
 #include "stm32mp257f-ev1-ca35tdcid-rcc.dtsi"
+#include "stm32mp25-ddr4-2x16Gbits-2x16bits-1200MHz.dtsi"
 #include "stm32mp25-pinctrl.dtsi"
 #include "stm32mp25xxai-pinctrl.dtsi"
 
@@ -37,6 +38,13 @@
 	};
 };
 
+&ddr {
+	vdd-supply = <&vdd_ddr>;
+	vtt-supply = <&vtt_ddr>;
+	vpp-supply = <&vpp_ddr>;
+	vref-supply = <&vref_ddr>;
+};
+
 &i2c7 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&i2c7_pins_a>;
diff --git a/fdts/tc-base.dtsi b/fdts/tc-base.dtsi
index be0a9f6..735d429 100644
--- a/fdts/tc-base.dtsi
+++ b/fdts/tc-base.dtsi
@@ -247,10 +247,6 @@
 			reg = <0x0 TC_NS_OPTEE_BASE 0x0 TC_NS_OPTEE_SIZE>;
 		};
 
-		fwu_mm {
-			reg = <0x0 TC_NS_FWU_BASE 0x0 TC_NS_FWU_SIZE>;
-			no-map;
-		};
 	};
 
 	memory {
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index d8ad881..6a19822 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -406,6 +406,10 @@
 #define ID_AA64MMFR3_EL1_S1PIE_SHIFT		U(8)
 #define ID_AA64MMFR3_EL1_S1PIE_MASK		ULL(0xf)
 
+#define ID_AA64MMFR3_EL1_SCTLR2_SHIFT		U(4)
+#define ID_AA64MMFR3_EL1_SCTLR2_MASK		ULL(0xf)
+#define SCTLR2_IMPLEMENTED			ULL(1)
+
 #define ID_AA64MMFR3_EL1_TCRX_SHIFT		U(0)
 #define ID_AA64MMFR3_EL1_TCRX_MASK		ULL(0xf)
 
@@ -433,6 +437,10 @@
 #define ID_AA64PFR1_EL1_GCS_MASK	ULL(0xf)
 #define GCS_IMPLEMENTED			ULL(1)
 
+#define ID_AA64PFR1_EL1_THE_SHIFT	U(48)
+#define ID_AA64PFR1_EL1_THE_MASK	ULL(0xf)
+#define THE_IMPLEMENTED			ULL(1)
+
 #define RNG_TRAP_IMPLEMENTED		ULL(0x1)
 
 /* ID_AA64PFR2_EL1 definitions */
@@ -589,7 +597,9 @@
 #define SCR_TWEDEL_SHIFT	U(30)
 #define SCR_TWEDEL_MASK		ULL(0xf)
 #define SCR_PIEN_BIT		(UL(1) << 45)
+#define SCR_SCTLR2En_BIT	(UL(1) << 44)
 #define SCR_TCR2EN_BIT		(UL(1) << 43)
+#define SCR_RCWMASKEn_BIT	(UL(1) << 42)
 #define SCR_TRNDR_BIT		(UL(1) << 40)
 #define SCR_GCSEn_BIT		(UL(1) << 39)
 #define SCR_HXEn_BIT		(UL(1) << 38)
@@ -623,6 +633,8 @@
 
 /* MDCR_EL3 definitions */
 #define MDCR_EBWE_BIT		(ULL(1) << 43)
+#define MDCR_E3BREC		(ULL(1) << 38)
+#define MDCR_E3BREW		(ULL(1) << 37)
 #define MDCR_EnPMSN_BIT		(ULL(1) << 36)
 #define MDCR_MPMX_BIT		(ULL(1) << 35)
 #define MDCR_MCCD_BIT		(ULL(1) << 34)
@@ -1473,6 +1485,18 @@
 #define TRFCR_EL1		S3_0_C1_C2_1
 
 /*******************************************************************************
+ * FEAT_THE - Translation Hardening Extension Registers
+ ******************************************************************************/
+#define RCWMASK_EL1		S3_0_C13_C0_6
+#define RCWSMASK_EL1		S3_0_C13_C0_3
+
+/*******************************************************************************
+ * FEAT_SCTLR2 - Extension to SCTLR_ELx Registers
+ ******************************************************************************/
+#define SCTLR2_EL2		S3_4_C1_C0_3
+#define SCTLR2_EL1		S3_0_C1_C0_3
+
+/*******************************************************************************
  * Definitions for DynamicIQ Shared Unit registers
  ******************************************************************************/
 #define CLUSTERPWRDN_EL1	S3_0_c15_c3_6
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index f03c9d5..de21fea 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -134,6 +134,10 @@
  * +----------------------------+
  * |	FEAT_FGT2		|
  * +----------------------------+
+ * |	FEAT_THE		|
+ * +----------------------------+
+ * |	FEAT_SCTLR2		|
+ * +----------------------------+
  */
 
 __attribute__((always_inline))
@@ -262,6 +266,15 @@
 CREATE_FEATURE_FUNCS(feat_s1pie, id_aa64mmfr3_el1, ID_AA64MMFR3_EL1_S1PIE_SHIFT,
 		     ID_AA64MMFR3_EL1_S1PIE_MASK, 1U, ENABLE_FEAT_S1PIE)
 
+/* FEAT_THE: Translation Hardening Extension */
+CREATE_FEATURE_FUNCS(feat_the, id_aa64pfr1_el1, ID_AA64PFR1_EL1_THE_SHIFT,
+		     ID_AA64PFR1_EL1_THE_MASK, THE_IMPLEMENTED, ENABLE_FEAT_THE)
+
+/* FEAT_SCTLR2 */
+CREATE_FEATURE_FUNCS(feat_sctlr2, id_aa64mmfr3_el1, ID_AA64MMFR3_EL1_SCTLR2_SHIFT,
+		     ID_AA64MMFR3_EL1_SCTLR2_MASK, SCTLR2_IMPLEMENTED,
+		     ENABLE_FEAT_SCTLR2)
+
 __attribute__((always_inline))
 static inline bool is_feat_sxpie_supported(void)
 {
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index a892654..acaa1b8 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -670,6 +670,14 @@
 DEFINE_RENAME_SYSREG_RW_FUNCS(gcspr_el1, GCSPR_EL1)
 DEFINE_RENAME_SYSREG_RW_FUNCS(gcspr_el0, GCSPR_EL0)
 
+/* FEAT_THE Registers */
+DEFINE_RENAME_SYSREG_RW_FUNCS(rcwmask_el1, RCWMASK_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(rcwsmask_el1, RCWSMASK_EL1)
+
+/* FEAT_SCTLR2 Registers */
+DEFINE_RENAME_SYSREG_RW_FUNCS(sctlr2_el1, SCTLR2_EL1)
+DEFINE_RENAME_SYSREG_RW_FUNCS(sctlr2_el2, SCTLR2_EL2)
+
 /* DynamIQ Control registers */
 DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpwrdn_el1, CLUSTERPWRDN_EL1)
 DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpmcr_el1, CLUSTERPMCR_EL1)
diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S
index 60c5a0c..1666e3b 100644
--- a/include/arch/aarch64/el3_common_macros.S
+++ b/include/arch/aarch64/el3_common_macros.S
@@ -59,24 +59,18 @@
 	 * zero here but are updated ahead of transitioning to a lower EL in the
 	 * function cm_init_context_common().
 	 *
-	 * SCR_EL3.SIF: Set to one to disable instruction fetches from
-	 *  Non-secure memory.
-	 *
-	 * SCR_EL3.EA: Set to one to route External Aborts and SError Interrupts
-	 *  to EL3 when executing at any EL.
-	 *
 	 * SCR_EL3.EEL2: Set to one if S-EL2 is present and enabled.
 	 *
 	 * NOTE: Modifying EEL2 bit along with EA bit ensures that we mitigate
 	 * against ERRATA_V2_3099206.
 	 * ---------------------------------------------------------------------
 	 */
-	mov_imm	x0, (SCR_RESET_VAL | SCR_EA_BIT | SCR_SIF_BIT)
+	mov_imm	x0, SCR_RESET_VAL
 #if IMAGE_BL31 && defined(SPD_spmd) && SPMD_SPM_AT_SEL2
-	mrs x1, id_aa64pfr0_el1
-	and x1, x1, #(ID_AA64PFR0_SEL2_MASK << ID_AA64PFR0_SEL2_SHIFT)
-	cbz x1, 1f
-	orr x0, x0, #SCR_EEL2_BIT
+	mrs	x1, id_aa64pfr0_el1
+	and	x1, x1, #(ID_AA64PFR0_SEL2_MASK << ID_AA64PFR0_SEL2_SHIFT)
+	cbz	x1, 1f
+	orr	x0, x0, #SCR_EEL2_BIT
 #endif
 1:
 	msr	scr_el3, x0
@@ -84,22 +78,11 @@
 	/* ---------------------------------------------------------------------
 	 * Initialise MDCR_EL3, setting all fields rather than relying on hw.
 	 * Some fields are architecturally UNKNOWN on reset.
-	 *
-	 * MDCR_EL3.SDD: Set to one to disable AArch64 Secure self-hosted debug.
-	 *  Debug exceptions, other than Breakpoint Instruction exceptions, are
-	 *  disabled from all ELs in Secure state.
 	 */
-	mov_imm	x0, (MDCR_EL3_RESET_VAL | MDCR_SDD_BIT)
+	mov_imm	x0, MDCR_EL3_RESET_VAL
 	msr	mdcr_el3, x0
 
 	/* ---------------------------------------------------------------------
-	 * Enable External Aborts and SError Interrupts now that the exception
-	 * vectors have been setup.
-	 * ---------------------------------------------------------------------
-	 */
-	msr	daifclr, #DAIF_ABT_BIT
-
-	/* ---------------------------------------------------------------------
 	 * Initialise CPTR_EL3, setting all fields rather than relying on hw.
 	 * All fields are architecturally UNKNOWN on reset.
 	 * ---------------------------------------------------------------------
@@ -107,28 +90,6 @@
 	mov_imm x0, CPTR_EL3_RESET_VAL
 	msr	cptr_el3, x0
 
-	/*
-	 * If Data Independent Timing (DIT) functionality is implemented,
-	 * always enable DIT in EL3.
-	 * First assert that the FEAT_DIT build flag matches the feature id
-	 * register value for DIT.
-	 */
-#if ENABLE_FEAT_DIT
-#if ENABLE_ASSERTIONS || ENABLE_FEAT_DIT > 1
-	mrs	x0, id_aa64pfr0_el1
-	ubfx	x0, x0, #ID_AA64PFR0_DIT_SHIFT, #ID_AA64PFR0_DIT_LENGTH
-#if ENABLE_FEAT_DIT > 1
-	cbz	x0, 1f
-#else
-	cmp	x0, #DIT_IMPLEMENTED
-	ASM_ASSERT(eq)
-#endif
-
-#endif /* ENABLE_ASSERTIONS */
-	mov	x0, #DIT_BIT
-	msr	DIT, x0
-1:
-#endif
 	.endm
 
 /* -----------------------------------------------------------------------------
@@ -270,6 +231,12 @@
 
 	el3_arch_init_common
 
+	/* ---------------------------------------------------------------------
+	 * Set the el3 execution context(i.e. root_context).
+	 * ---------------------------------------------------------------------
+	 */
+	setup_el3_execution_context
+
 	.if \_secondary_cold_boot
 		/* -------------------------------------------------------------
 		 * Check if this is a primary or secondary CPU cold boot.
@@ -460,4 +427,68 @@
 	end:
 	.endm
 
+/*-----------------------------------------------------------------------------
+ * Helper macro to configure EL3 registers we care about, while executing
+ * at EL3/Root world. Root world has its own execution environment and
+ * needs to have its settings configured to be independent of other worlds.
+ * -----------------------------------------------------------------------------
+ */
+	.macro setup_el3_execution_context
+
+	/* ---------------------------------------------------------------------
+	 * The following registers need to be part of separate root context
+	 * as their values are of importance during EL3 execution.
+	 * Hence these registers are overwritten to their intital values,
+	 * irrespective of whichever world they return from to ensure EL3 has a
+	 * consistent execution context throughout the lifetime of TF-A.
+	 *
+	 * DAIF.A: Enable External Aborts and SError Interrupts at EL3.
+	 *
+	 * MDCR_EL3.SDD: Set to one to disable AArch64 Secure self-hosted debug.
+	 *  Debug exceptions, other than Breakpoint Instruction exceptions, are
+	 *  disabled from all ELs in Secure state.
+	 *
+	 * SCR_EL3.EA: Set to one to enable SError interrupts at EL3.
+	 *
+	 * SCR_EL3.SIF: Set to one to disable instruction fetches from
+	 *  Non-secure memory.
+	 *
+	 * PMCR_EL0.DP: Set to one so that the cycle counter,
+	 *  PMCCNTR_EL0 does not count when event counting is prohibited.
+	 *  Necessary on PMUv3 <= p7 where MDCR_EL3.{SCCD,MCCD} are not
+	 *  available.
+	 *
+	 * PSTATE.DIT: Set to one to enable the Data Independent Timing (DIT)
+	 *  functionality, if implemented in EL3.
+	 * ---------------------------------------------------------------------
+	 */
+		msr	daifclr, #DAIF_ABT_BIT
+
+		mrs 	x15, mdcr_el3
+		orr	x15, x15, #MDCR_SDD_BIT
+		msr	mdcr_el3, x15
+
+		mrs	x15, scr_el3
+		orr	x15, x15, #SCR_EA_BIT
+		orr	x15, x15, #SCR_SIF_BIT
+		msr	scr_el3, x15
+
+		mrs 	x15, pmcr_el0
+		orr	x15, x15, #PMCR_EL0_DP_BIT
+		msr	pmcr_el0, x15
+
+#if ENABLE_FEAT_DIT
+#if ENABLE_FEAT_DIT > 1
+		mrs	x15, id_aa64pfr0_el1
+		ubfx	x15, x15, #ID_AA64PFR0_DIT_SHIFT, #ID_AA64PFR0_DIT_LENGTH
+		cbz	x15, 1f
+#endif
+		mov	x15, #DIT_BIT
+		msr	DIT, x15
+	1:
+#endif
+
+		isb
+	.endm
+
 #endif /* EL3_COMMON_MACROS_S */
diff --git a/include/drivers/arm/dcc.h b/include/drivers/arm/dcc.h
index 072bed5..7f71932 100644
--- a/include/drivers/arm/dcc.h
+++ b/include/drivers/arm/dcc.h
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2021,  Xilinx Inc.
+ * Copyright (c) 2021-2022, Xilinx Inc.
+ * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,7 +15,7 @@
  * Initialize a new dcc console instance and register it with the console
  * framework.
  */
-int console_dcc_register(void);
-void console_dcc_unregister(void);
+int console_dcc_register(console_t *console);
+void console_dcc_unregister(console_t *console);
 
-#endif /* DCC */
+#endif /* DCC_H */
diff --git a/include/drivers/cadence/cdns_sdmmc.h b/include/drivers/cadence/cdns_sdmmc.h
index 8bf3b78..4be7414 100644
--- a/include/drivers/cadence/cdns_sdmmc.h
+++ b/include/drivers/cadence/cdns_sdmmc.h
@@ -281,7 +281,6 @@
 								(SDMMC_CDN_##_reg))
 
 /* MMC Peripheral Definition */
-#define SOCFPGA_MMC_BLOCK_SIZE		U(8192)
 #define SOCFPGA_MMC_BLOCK_MASK		(SOCFPGA_MMC_BLOCK_SIZE - U(1))
 #define SOCFPGA_MMC_BOOT_CLK_RATE	(400 * 1000)
 #define MMC_RESPONSE_NONE			0
diff --git a/include/drivers/delay_timer.h b/include/drivers/delay_timer.h
index 20a5543..e9fdfb7 100644
--- a/include/drivers/delay_timer.h
+++ b/include/drivers/delay_timer.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2019, Linaro Limited
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -25,27 +25,12 @@
 	uint32_t (*get_timer_value)(void);
 	uint32_t clk_mult;
 	uint32_t clk_div;
+	uint64_t (*timeout_init_us)(uint32_t usec);
+	bool (*timeout_elapsed)(uint64_t cnt);
 } timer_ops_t;
 
-static inline uint64_t timeout_cnt_us2cnt(uint32_t us)
-{
-	return ((uint64_t)us * (uint64_t)read_cntfrq_el0()) / 1000000ULL;
-}
-
-static inline uint64_t timeout_init_us(uint32_t us)
-{
-	uint64_t cnt = timeout_cnt_us2cnt(us);
-
-	cnt += read_cntpct_el0();
-
-	return cnt;
-}
-
-static inline bool timeout_elapsed(uint64_t expire_cnt)
-{
-	return read_cntpct_el0() > expire_cnt;
-}
-
+uint64_t timeout_init_us(uint32_t usec);
+bool timeout_elapsed(uint64_t cnt);
 void mdelay(uint32_t msec);
 void udelay(uint32_t usec);
 void timer_init(const timer_ops_t *ops_ptr);
diff --git a/include/lib/cpus/aarch64/cortex_a720_ae.h b/include/lib/cpus/aarch64/cortex_a720_ae.h
new file mode 100644
index 0000000..c88b1f9
--- /dev/null
+++ b/include/lib/cpus/aarch64/cortex_a720_ae.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CORTEX_A720_AE_H
+#define CORTEX_A720_AE_H
+
+#define CORTEX_A720_AE_MIDR				U(0x410FD890)
+
+/*******************************************************************************
+ * CPU Extended Control register specific definitions
+ ******************************************************************************/
+#define CORTEX_A720_AE_CPUECTLR_EL1			S3_0_C15_C1_4
+
+/*******************************************************************************
+ * CPU Power Control register specific definitions
+ ******************************************************************************/
+#define CORTEX_A720_AE_CPUPWRCTLR_EL1			S3_0_C15_C2_7
+#define CORTEX_A720_AE_CPUPWRCTLR_EL1_CORE_PWRDN_BIT	U(1)
+
+#endif /* CORTEX_A720_AE_H */
diff --git a/include/lib/cpus/aarch64/cortex_arcadia.h b/include/lib/cpus/aarch64/cortex_arcadia.h
new file mode 100644
index 0000000..8b74de2
--- /dev/null
+++ b/include/lib/cpus/aarch64/cortex_arcadia.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CORTEX_ARCADIA_H
+#define CORTEX_ARCADIA_H
+
+#define CORTEX_ARCADIA_MIDR					U(0x410FD8F0)
+
+/*******************************************************************************
+ * CPU Extended Control register specific definitions
+ ******************************************************************************/
+#define CORTEX_ARCADIA_CPUECTLR_EL1				S3_0_C15_C1_4
+#define CORTEX_ARCADIA_CPUECTLR_EL1_EXTLLC_BIT			U(0)
+
+/*******************************************************************************
+ * CPU Power Control register specific definitions
+ ******************************************************************************/
+#define CORTEX_ARCADIA_CPUPWRCTLR_EL1				S3_0_C15_C2_7
+#define CORTEX_ARCADIA_CPUPWRCTLR_EL1_CORE_PWRDN_BIT		U(1)
+
+#endif /* CORTEX_ARCADIA_H */
diff --git a/include/lib/cpus/aarch64/cpu_macros.S b/include/lib/cpus/aarch64/cpu_macros.S
index 98294b9..5e92934 100644
--- a/include/lib/cpus/aarch64/cpu_macros.S
+++ b/include/lib/cpus/aarch64/cpu_macros.S
@@ -433,7 +433,7 @@
  *
  * _get_rev:
  *	Optional parameter that determines whether to insert a call to the CPU revision fetching
- *	procedure. Stores the result of this in the temporary register x10.
+ *	procedure. Stores the result of this in the temporary register x10 to allow for chaining
  *
  * clobbers: x0-x10 (PCS compliant)
  */
diff --git a/include/lib/el3_runtime/context_el1.h b/include/lib/el3_runtime/context_el1.h
index 038de25..94af210 100644
--- a/include/lib/el3_runtime/context_el1.h
+++ b/include/lib/el3_runtime/context_el1.h
@@ -107,6 +107,15 @@
 	uint64_t gcspr_el0;
 } el1_gcs_regs_t;
 
+typedef struct el1_the_regs {
+	uint64_t rcwmask_el1;
+	uint64_t rcwsmask_el1;
+} el1_the_regs_t;
+
+typedef struct el1_sctlr2_regs {
+	uint64_t sctlr2_el1;
+} el1_sctlr2_regs_t;
+
 typedef struct el1_sysregs {
 
 	el1_common_regs_t common;
@@ -155,6 +164,14 @@
 	el1_gcs_regs_t gcs;
 #endif
 
+#if ENABLE_FEAT_THE
+	el1_the_regs_t the;
+#endif
+
+#if ENABLE_FEAT_SCTLR2
+	el1_sctlr2_regs_t sctlr2;
+#endif
+
 } el1_sysregs_t;
 
 
@@ -266,6 +283,25 @@
 #define read_el1_ctx_gcs(ctx, reg)		ULL(0)
 #define write_el1_ctx_gcs(ctx, reg, val)
 #endif /* ENABLE_FEAT_GCS */
+
+#if ENABLE_FEAT_THE
+#define read_el1_ctx_the(ctx, reg)		(((ctx)->the).reg)
+#define write_el1_ctx_the(ctx, reg, val)	((((ctx)->the).reg)	\
+							= (uint64_t) (val))
+#else
+#define read_el1_ctx_the(ctx, reg)		ULL(0)
+#define write_el1_ctx_the(ctx, reg, val)
+#endif /* ENABLE_FEAT_THE */
+
+#if ENABLE_FEAT_SCTLR2
+#define read_el1_ctx_sctlr2(ctx, reg)		(((ctx)->sctlr2).reg)
+#define write_el1_ctx_sctlr2(ctx, reg, val)	((((ctx)->sctlr2).reg)	\
+							= (uint64_t) (val))
+#else
+#define read_el1_ctx_sctlr2(ctx, reg)		ULL(0)
+#define write_el1_ctx_sctlr2(ctx, reg, val)
+#endif /* ENABLE_FEAT_SCTLR2 */
+
 /******************************************************************************/
 #endif /* __ASSEMBLER__ */
 
diff --git a/include/lib/el3_runtime/context_el2.h b/include/lib/el3_runtime/context_el2.h
index 14c1fb6..ad0b68f 100644
--- a/include/lib/el3_runtime/context_el2.h
+++ b/include/lib/el3_runtime/context_el2.h
@@ -135,6 +135,10 @@
 	uint64_t mpamvpmv_el2;
 } el2_mpam_regs_t;
 
+typedef struct el2_sctlr2_regs {
+	uint64_t sctlr2_el2;
+} el2_sctlr2_regs_t;
+
 typedef struct el2_sysregs {
 
 	el2_common_regs_t common;
@@ -203,6 +207,10 @@
 	el2_mpam_regs_t mpam;
 #endif
 
+#if ENABLE_FEAT_SCTLR2
+	el2_sctlr2_regs_t sctlr2;
+#endif
+
 } el2_sysregs_t;
 
 /*
@@ -358,6 +366,15 @@
 #define write_el2_ctx_mpam(ctx, reg, val)
 #endif /* CTX_INCLUDE_MPAM_REGS */
 
+#if ENABLE_FEAT_SCTLR2
+#define read_el2_ctx_sctlr2(ctx, reg)		(((ctx)->sctlr2).reg)
+#define write_el2_ctx_sctlr2(ctx, reg, val)	((((ctx)->sctlr2).reg)	\
+							= (uint64_t) (val))
+#else
+#define read_el2_ctx_sctlr2(ctx, reg)		ULL(0)
+#define write_el2_ctx_sctlr2(ctx, reg, val)
+#endif /* ENABLE_FEAT_SCTLR2 */
+
 /******************************************************************************/
 
 #endif /* __ASSEMBLER__ */
diff --git a/include/lib/el3_runtime/cpu_data.h b/include/lib/el3_runtime/cpu_data.h
index 2c7b619..8b54806 100644
--- a/include/lib/el3_runtime/cpu_data.h
+++ b/include/lib/el3_runtime/cpu_data.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -59,8 +59,19 @@
 #define CPU_DATA_CRASH_BUF_END		CPU_DATA_CRASH_BUF_OFFSET
 #endif
 
+/* buffer space for EHF data is sizeof(pe_exc_data_t) */
+#define CPU_DATA_EHF_DATA_SIZE		8
+#define CPU_DATA_EHF_DATA_BUF_OFFSET	CPU_DATA_CRASH_BUF_END
+
+#if defined(IMAGE_BL31) && EL3_EXCEPTION_HANDLING
+#define CPU_DATA_EHF_DATA_BUF_END	(CPU_DATA_EHF_DATA_BUF_OFFSET + \
+						CPU_DATA_EHF_DATA_SIZE)
+#else
+#define CPU_DATA_EHF_DATA_BUF_END	CPU_DATA_EHF_DATA_BUF_OFFSET
+#endif	/* EL3_EXCEPTION_HANDLING */
+
 /* cpu_data size is the data size rounded up to the platform cache line size */
-#define CPU_DATA_SIZE			(((CPU_DATA_CRASH_BUF_END + \
+#define CPU_DATA_SIZE			(((CPU_DATA_EHF_DATA_BUF_END + \
 					CACHE_WRITEBACK_GRANULE - 1) / \
 						CACHE_WRITEBACK_GRANULE) * \
 							CACHE_WRITEBACK_GRANULE)
@@ -68,7 +79,7 @@
 #if ENABLE_RUNTIME_INSTRUMENTATION
 /* Temporary space to store PMF timestamps from assembly code */
 #define CPU_DATA_PMF_TS_COUNT		1
-#define CPU_DATA_PMF_TS0_OFFSET		CPU_DATA_CRASH_BUF_END
+#define CPU_DATA_PMF_TS0_OFFSET		CPU_DATA_EHF_DATA_BUF_END
 #define CPU_DATA_PMF_TS0_IDX		0
 #endif
 
@@ -159,6 +170,12 @@
 	assert_cpu_data_crash_stack_offset_mismatch);
 #endif
 
+#if defined(IMAGE_BL31) && EL3_EXCEPTION_HANDLING
+CASSERT(CPU_DATA_EHF_DATA_BUF_OFFSET == __builtin_offsetof
+	(cpu_data_t, ehf_data),
+	assert_cpu_data_ehf_stack_offset_mismatch);
+#endif
+
 CASSERT(CPU_DATA_SIZE == sizeof(cpu_data_t),
 		assert_cpu_data_size_mismatch);
 
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index ae5aa23..118b537 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -15,6 +15,7 @@
 #endif
 #if ENABLE_RME
 #include <services/rmm_core_manifest.h>
+#include <services/rmm_el3_token_sign.h>
 #endif
 #include <drivers/fwu/fwu_metadata.h>
 #if TRNG_SUPPORT
@@ -376,6 +377,15 @@
 				   uint64_t *remaining_len);
 int plat_rmmd_get_cca_realm_attest_key(uintptr_t buf, size_t *len,
 				       unsigned int type);
+/* The following 3 functions are to be implement if
+ * RMMD_ENABLE_EL3_TOKEN_SIGN=1.
+ * The following three functions are expected to return E_RMM_* error codes.
+ */
+int plat_rmmd_el3_token_sign_get_rak_pub(uintptr_t buf, size_t *len,
+					   unsigned int type);
+int plat_rmmd_el3_token_sign_push_req(
+				const struct el3_token_sign_request *req);
+int plat_rmmd_el3_token_sign_pull_resp(struct el3_token_sign_response *resp);
 size_t plat_rmmd_get_el3_rmm_shared_mem(uintptr_t *shared);
 int plat_rmmd_load_manifest(struct rmm_manifest *manifest);
 #endif
diff --git a/include/services/rmm_el3_token_sign.h b/include/services/rmm_el3_token_sign.h
new file mode 100644
index 0000000..154940c
--- /dev/null
+++ b/include/services/rmm_el3_token_sign.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2024, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RMM_EL3_TOKEN_SIGN_H
+#define RMM_EL3_TOKEN_SIGN_H
+
+#include <stdint.h>
+#include <lib/cassert.h>
+#include <services/rmmd_svc.h>
+
+/*
+ * Defines member of structure and reserves space
+ * for the next member with specified offset.
+ */
+/* cppcheck-suppress [misra-c2012-20.7] */
+#define SET_MEMBER(member, start, end)	\
+	union {				\
+		member;			\
+		unsigned char reserved##end[((end) - (start))];	\
+	}
+
+#define EL3_TOKEN_RESPONSE_MAX_SIG_LEN U(512)
+
+struct el3_token_sign_request {
+	SET_MEMBER(uint32_t sig_alg_id, 0x0, 0x8);
+	SET_MEMBER(uint64_t rec_granule, 0x8, 0x10);
+	SET_MEMBER(uint64_t req_ticket, 0x10, 0x18);
+	SET_MEMBER(uint32_t hash_alg_id, 0x18, 0x20);
+	SET_MEMBER(uint8_t hash_buf[SHA512_DIGEST_SIZE], 0x20, 0x60);
+};
+
+CASSERT(__builtin_offsetof(struct el3_token_sign_request, sig_alg_id) == 0x0U,
+	assert_el3_token_sign_request_sig_alg_mismatch);
+CASSERT(__builtin_offsetof(struct el3_token_sign_request, rec_granule) == 0x8U,
+	assert_el3_token_sign_request_rec_granule_mismatch);
+CASSERT(__builtin_offsetof(struct el3_token_sign_request, req_ticket) == 0x10U,
+	assert_el3_token_sign_request_req_ticket_mismatch);
+CASSERT(__builtin_offsetof(struct el3_token_sign_request, hash_alg_id) == 0x18U,
+	assert_el3_token_sign_request_hash_alg_id_mismatch);
+CASSERT(__builtin_offsetof(struct el3_token_sign_request, hash_buf) == 0x20U,
+	assert_el3_token_sign_request_hash_buf_mismatch);
+
+
+struct el3_token_sign_response {
+	SET_MEMBER(uint64_t rec_granule, 0x0, 0x8);
+	SET_MEMBER(uint64_t req_ticket, 0x8, 0x10);
+	SET_MEMBER(uint16_t sig_len, 0x10, 0x12);
+	SET_MEMBER(uint8_t signature_buf[EL3_TOKEN_RESPONSE_MAX_SIG_LEN], 0x12, 0x212);
+};
+
+CASSERT(__builtin_offsetof(struct el3_token_sign_response, rec_granule) == 0x0U,
+	assert_el3_token_sign_resp_rec_granule_mismatch);
+CASSERT(__builtin_offsetof(struct el3_token_sign_response, req_ticket) == 0x8U,
+	assert_el3_token_sign_resp_req_ticket_mismatch);
+CASSERT(__builtin_offsetof(struct el3_token_sign_response, sig_len) == 0x10U,
+	assert_el3_token_sign_resp_sig_len_mismatch);
+CASSERT(__builtin_offsetof(struct el3_token_sign_response, signature_buf) == 0x12U,
+	assert_el3_token_sign_resp_sig_buf_mismatch);
+
+#endif /* RMM_EL3_TOKEN_SIGN_H */
diff --git a/include/services/rmmd_svc.h b/include/services/rmmd_svc.h
index 635c28e..0cc8628 100644
--- a/include/services/rmmd_svc.h
+++ b/include/services/rmmd_svc.h
@@ -129,8 +129,43 @@
 					/* 0x1B3 */
 #define RMM_ATTEST_GET_PLAT_TOKEN	SMC64_RMMD_EL3_FID(U(3))
 
+/* Starting RMM-EL3 interface version 0.4 */
+#define RMM_EL3_FEATURES				SMC64_RMMD_EL3_FID(U(4))
+#define RMM_EL3_FEAT_REG_0_IDX				U(0)
+/* Bit 0 of FEAT_REG_0 */
+/* 1 - the feature is present in EL3 , 0 - the feature is absent */
+#define RMM_EL3_FEAT_REG_0_EL3_TOKEN_SIGN_MASK		U(0x1)
+
+/*
+ * Function codes to support attestation where EL3 is used to sign
+ * realm attestation tokens. In this model, the private key is not
+ * exposed to the RMM.
+ * The arguments to this SMC are:
+ *     arg0 - Function ID.
+ *     arg1 - Opcode, one of:
+ *               RMM_EL3_TOKEN_SIGN_PUSH_REQ_OP,
+ *               RMM_EL3_TOKEN_SIGN_PULL_RESP_OP,
+ *               RMM_EL3_TOKEN_SIGN_GET_RAK_PUB_OP
+ *     arg2 - Pointer to buffer with request/response structures,
+ *            which is in the RMM<->EL3 shared buffer.
+ *     arg3 - Buffer size of memory pointed by arg2.
+ *     arg4 - ECC Curve, when opcode is RMM_EL3_TOKEN_SIGN_GET_RAK_PUB_OP
+ * The return arguments are:
+ *     ret0 - Status/Error
+ *     ret1 - Size of public key if opcode is RMM_EL3_TOKEN_SIGN_GET_RAK_PUB_OP
+ */
+#define RMM_EL3_TOKEN_SIGN			SMC64_RMMD_EL3_FID(U(5))
+
+/* Opcodes for RMM_EL3_TOKEN_SIGN  */
+#define RMM_EL3_TOKEN_SIGN_PUSH_REQ_OP          U(1)
+#define RMM_EL3_TOKEN_SIGN_PULL_RESP_OP         U(2)
+#define RMM_EL3_TOKEN_SIGN_GET_RAK_PUB_OP       U(3)
+
 /* ECC Curve types for attest key generation */
-#define ATTEST_KEY_CURVE_ECC_SECP384R1		0
+#define ATTEST_KEY_CURVE_ECC_SECP384R1		U(0)
+
+/* Identifier for the hash algorithm used for attestation signing */
+#define EL3_TOKEN_SIGN_HASH_ALG_SHA384		U(1)
 
 /*
  * RMM_BOOT_COMPLETE originates on RMM when the boot finishes (either cold
@@ -153,7 +188,7 @@
  * Increase this when a bug is fixed, or a feature is added without
  * breaking compatibility.
  */
-#define RMM_EL3_IFC_VERSION_MINOR	(U(3))
+#define RMM_EL3_IFC_VERSION_MINOR	(U(4))
 
 #define RMM_EL3_INTERFACE_VERSION				\
 	(((RMM_EL3_IFC_VERSION_MAJOR << 16) & 0x7FFFF) |	\
diff --git a/lib/cpus/aarch64/cortex_a57.S b/lib/cpus/aarch64/cortex_a57.S
index 374cc5d..fecb56f 100644
--- a/lib/cpus/aarch64/cortex_a57.S
+++ b/lib/cpus/aarch64/cortex_a57.S
@@ -57,7 +57,7 @@
 	msr	osdlr_el1, x0
 	isb
 
-	apply_erratum cortex_a57, ERRATUM(817169), ERRATA_A57_817169
+	apply_erratum cortex_a57, ERRATUM(817169), ERRATA_A57_817169, NO_GET_CPU_REV
 
 	dsb	sy
 	ret
diff --git a/lib/cpus/aarch64/cortex_a710.S b/lib/cpus/aarch64/cortex_a710.S
index 4c33dda..b9f6081 100644
--- a/lib/cpus/aarch64/cortex_a710.S
+++ b/lib/cpus/aarch64/cortex_a710.S
@@ -216,7 +216,7 @@
 	 * ----------------------------------------------------
 	 */
 func cortex_a710_core_pwr_dwn
-	apply_erratum cortex_a710, ERRATUM(2008768), ERRATA_A710_2008768
+	apply_erratum cortex_a710, ERRATUM(2008768), ERRATA_A710_2008768, NO_GET_CPU_REV
 	apply_erratum cortex_a710, ERRATUM(2291219), ERRATA_A710_2291219, NO_GET_CPU_REV
 
 	/* ---------------------------------------------------
diff --git a/lib/cpus/aarch64/cortex_a720_ae.S b/lib/cpus/aarch64/cortex_a720_ae.S
new file mode 100644
index 0000000..42d49c3
--- /dev/null
+++ b/lib/cpus/aarch64/cortex_a720_ae.S
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <cortex_a720_ae.h>
+#include <cpu_macros.S>
+#include <plat_macros.S>
+
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "Cortex-A720AE must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
+/* 64-bit only core */
+#if CTX_INCLUDE_AARCH32_REGS == 1
+#error "Cortex-A720AE supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
+#endif
+
+cpu_reset_func_start cortex_a720_ae
+	/* Disable speculative loads */
+	msr	SSBS, xzr
+cpu_reset_func_end cortex_a720_ae
+
+	/* ----------------------------------------------------
+	 * HW will do the cache maintenance while powering down
+	 * ----------------------------------------------------
+	 */
+func cortex_a720_ae_core_pwr_dwn
+	/* ---------------------------------------------------
+	 * Enable CPU power down bit in power control register
+	 * ---------------------------------------------------
+	 */
+	sysreg_bit_set CORTEX_A720_AE_CPUPWRCTLR_EL1, CORTEX_A720_AE_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
+
+	isb
+	ret
+endfunc cortex_a720_ae_core_pwr_dwn
+
+	/* ---------------------------------------------
+	 * This function provides Cortex-A720AE specific
+	 * register information for crash reporting.
+	 * It needs to return with x6 pointing to
+	 * a list of register names in ascii and
+	 * x8 - x15 having values of registers to be
+	 * reported.
+	 * ---------------------------------------------
+	 */
+.section .rodata.cortex_a720_ae_regs, "aS"
+cortex_a720_ae_regs:  /* The ascii list of register names to be reported */
+	.asciz	"cpuectlr_el1", ""
+
+func cortex_a720_ae_cpu_reg_dump
+	adr	x6, cortex_a720_ae_regs
+	mrs	x8, CORTEX_A720_AE_CPUECTLR_EL1
+	ret
+endfunc cortex_a720_ae_cpu_reg_dump
+
+declare_cpu_ops cortex_a720_ae, CORTEX_A720_AE_MIDR, \
+	cortex_a720_ae_reset_func, \
+	cortex_a720_ae_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_a76.S b/lib/cpus/aarch64/cortex_a76.S
index 97e036e..017086a 100644
--- a/lib/cpus/aarch64/cortex_a76.S
+++ b/lib/cpus/aarch64/cortex_a76.S
@@ -505,7 +505,7 @@
 	 */
 	sysreg_bit_set CORTEX_A76_CPUPWRCTLR_EL1, CORTEX_A76_CORE_PWRDN_EN_MASK
 
-	apply_erratum cortex_a76, ERRATUM(2743102), ERRATA_A76_2743102
+	apply_erratum cortex_a76, ERRATUM(2743102), ERRATA_A76_2743102, NO_GET_CPU_REV
 
 	isb
 	ret
diff --git a/lib/cpus/aarch64/cortex_a77.S b/lib/cpus/aarch64/cortex_a77.S
index d1fc41a..f53b646 100644
--- a/lib/cpus/aarch64/cortex_a77.S
+++ b/lib/cpus/aarch64/cortex_a77.S
@@ -161,7 +161,7 @@
 	sysreg_bit_set CORTEX_A77_CPUPWRCTLR_EL1, \
 		CORTEX_A77_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
 
-	apply_erratum cortex_a77, ERRATUM(2743100), ERRATA_A77_2743100
+	apply_erratum cortex_a77, ERRATUM(2743100), ERRATA_A77_2743100, NO_GET_CPU_REV
 
 	isb
 	ret
diff --git a/lib/cpus/aarch64/cortex_a78.S b/lib/cpus/aarch64/cortex_a78.S
index 5a63e78..1de570a 100644
--- a/lib/cpus/aarch64/cortex_a78.S
+++ b/lib/cpus/aarch64/cortex_a78.S
@@ -192,7 +192,7 @@
 func cortex_a78_core_pwr_dwn
 	sysreg_bit_set CORTEX_A78_CPUPWRCTLR_EL1, CORTEX_A78_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT
 
-	apply_erratum cortex_a78, ERRATUM(2772019), ERRATA_A78_2772019
+	apply_erratum cortex_a78, ERRATUM(2772019), ERRATA_A78_2772019, NO_GET_CPU_REV
 
 	isb
 	ret
diff --git a/lib/cpus/aarch64/cortex_a78c.S b/lib/cpus/aarch64/cortex_a78c.S
index 97d5743..260cc73 100644
--- a/lib/cpus/aarch64/cortex_a78c.S
+++ b/lib/cpus/aarch64/cortex_a78c.S
@@ -132,7 +132,7 @@
 	 */
 	sysreg_bit_set CORTEX_A78C_CPUPWRCTLR_EL1, CORTEX_A78C_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT
 
-	apply_erratum cortex_a78c, ERRATUM(2772121), ERRATA_A78C_2772121
+	apply_erratum cortex_a78c, ERRATUM(2772121), ERRATA_A78C_2772121, NO_GET_CPU_REV
 
 	isb
 	ret
diff --git a/lib/cpus/aarch64/cortex_arcadia.S b/lib/cpus/aarch64/cortex_arcadia.S
new file mode 100644
index 0000000..c97d87d
--- /dev/null
+++ b/lib/cpus/aarch64/cortex_arcadia.S
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <cortex_arcadia.h>
+#include <cpu_macros.S>
+#include <plat_macros.S>
+
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "Cortex-ARCADIA must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
+/* 64-bit only core */
+#if CTX_INCLUDE_AARCH32_REGS == 1
+#error "Cortex-ARCADIA supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
+#endif
+
+cpu_reset_func_start cortex_arcadia
+	/* Disable speculative loads */
+	msr	SSBS, xzr
+cpu_reset_func_end cortex_arcadia
+
+	/* ----------------------------------------------------
+	 * HW will do the cache maintenance while powering down
+	 * ----------------------------------------------------
+	 */
+func cortex_arcadia_core_pwr_dwn
+	/* ---------------------------------------------------
+	 * Enable CPU power down bit in power control register
+	 * ---------------------------------------------------
+	 */
+	sysreg_bit_set CORTEX_ARCADIA_CPUPWRCTLR_EL1, CORTEX_ARCADIA_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
+	isb
+	ret
+endfunc cortex_arcadia_core_pwr_dwn
+
+	/* ---------------------------------------------
+	 * This function provides Cortex-Arcadia specific
+	 * register information for crash reporting.
+	 * It needs to return with x6 pointing to
+	 * a list of register names in ascii and
+	 * x8 - x15 having values of registers to be
+	 * reported.
+	 * ---------------------------------------------
+	 */
+.section .rodata.cortex_arcadia_regs, "aS"
+cortex_arcadia_regs:  /* The ascii list of register names to be reported */
+	.asciz	"cpuectlr_el1", ""
+
+func cortex_arcadia_cpu_reg_dump
+	adr	x6, cortex_arcadia_regs
+	mrs	x8, CORTEX_ARCADIA_CPUECTLR_EL1
+	ret
+endfunc cortex_arcadia_cpu_reg_dump
+
+declare_cpu_ops cortex_arcadia, CORTEX_ARCADIA_MIDR, \
+	cortex_arcadia_reset_func, \
+	cortex_arcadia_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_x2.S b/lib/cpus/aarch64/cortex_x2.S
index ab0b19d..ac60903 100644
--- a/lib/cpus/aarch64/cortex_x2.S
+++ b/lib/cpus/aarch64/cortex_x2.S
@@ -126,10 +126,10 @@
 
 check_erratum_ls cortex_x2, ERRATUM(2742423), CPU_REV(2, 1)
 
-workaround_reset_start cortex_x2, ERRATUM(2768515), ERRATA_X2_2768515
+workaround_runtime_start cortex_x2, ERRATUM(2768515), ERRATA_X2_2768515
 	/* dsb before isb of power down sequence */
 	dsb	sy
-workaround_reset_end cortex_x2, ERRATUM(2768515)
+workaround_runtime_end cortex_x2, ERRATUM(2768515)
 
 check_erratum_ls cortex_x2, ERRATUM(2768515), CPU_REV(2, 1)
 
@@ -172,12 +172,7 @@
 	 */
 	sysreg_bit_set CORTEX_X2_CPUPWRCTLR_EL1, CORTEX_X2_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
 
-#if ERRATA_X2_2768515
-	mov	x15, x30
-	bl	cpu_get_rev_var
-	bl	erratum_cortex_x2_2768515_wa
-	mov	x30, x15
-#endif /* ERRATA_X2_2768515 */
+	apply_erratum cortex_x2, ERRATUM(2768515), ERRATA_X2_2768515, NO_GET_CPU_REV
 	isb
 	ret
 endfunc cortex_x2_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_x3.S b/lib/cpus/aarch64/cortex_x3.S
index 248f107..a81c4cf 100644
--- a/lib/cpus/aarch64/cortex_x3.S
+++ b/lib/cpus/aarch64/cortex_x3.S
@@ -114,13 +114,13 @@
 	 * ----------------------------------------------------
 	 */
 func cortex_x3_core_pwr_dwn
-	apply_erratum cortex_x3, ERRATUM(2313909), ERRATA_X3_2313909
+	apply_erratum cortex_x3, ERRATUM(2313909), ERRATA_X3_2313909, NO_GET_CPU_REV
 	/* ---------------------------------------------------
 	 * Enable CPU power down bit in power control register
 	 * ---------------------------------------------------
 	 */
 	sysreg_bit_set CORTEX_X3_CPUPWRCTLR_EL1, CORTEX_X3_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
-	apply_erratum cortex_x3, ERRATUM(2743088), ERRATA_X3_2743088
+	apply_erratum cortex_x3, ERRATUM(2743088), ERRATA_X3_2743088, NO_GET_CPU_REV
 	isb
 	ret
 endfunc cortex_x3_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_x4.S b/lib/cpus/aarch64/cortex_x4.S
index 8820de5..320fd90 100644
--- a/lib/cpus/aarch64/cortex_x4.S
+++ b/lib/cpus/aarch64/cortex_x4.S
@@ -111,7 +111,7 @@
 	 */
 	sysreg_bit_set CORTEX_X4_CPUPWRCTLR_EL1, CORTEX_X4_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
 
-	apply_erratum cortex_x4, ERRATUM(2740089), ERRATA_X4_2740089
+	apply_erratum cortex_x4, ERRATUM(2740089), ERRATA_X4_2740089, NO_GET_CPU_REV
 
 	isb
 	ret
diff --git a/lib/cpus/aarch64/neoverse_n1.S b/lib/cpus/aarch64/neoverse_n1.S
index 50e1ae3..f727226 100644
--- a/lib/cpus/aarch64/neoverse_n1.S
+++ b/lib/cpus/aarch64/neoverse_n1.S
@@ -236,7 +236,7 @@
 	 */
 	sysreg_bit_set NEOVERSE_N1_CPUPWRCTLR_EL1, NEOVERSE_N1_CORE_PWRDN_EN_MASK
 
-	apply_erratum neoverse_n1, ERRATUM(2743102), ERRATA_N1_2743102
+	apply_erratum neoverse_n1, ERRATUM(2743102), ERRATA_N1_2743102, NO_GET_CPU_REV
 
 	isb
 	ret
diff --git a/lib/cpus/aarch64/neoverse_n2.S b/lib/cpus/aarch64/neoverse_n2.S
index 7d7cc44..d2237f1 100644
--- a/lib/cpus/aarch64/neoverse_n2.S
+++ b/lib/cpus/aarch64/neoverse_n2.S
@@ -265,8 +265,7 @@
 cpu_reset_func_end neoverse_n2
 
 func neoverse_n2_core_pwr_dwn
-
-	apply_erratum neoverse_n2, ERRATUM(2009478), ERRATA_N2_2009478
+	apply_erratum neoverse_n2, ERRATUM(2009478), ERRATA_N2_2009478, NO_GET_CPU_REV
 	apply_erratum neoverse_n2, ERRATUM(2326639), ERRATA_N2_2326639, NO_GET_CPU_REV
 
 	/* ---------------------------------------------------
@@ -276,7 +275,7 @@
 	 */
 	sysreg_bit_set NEOVERSE_N2_CPUPWRCTLR_EL1, NEOVERSE_N2_CORE_PWRDN_EN_BIT
 
-	apply_erratum neoverse_n2, ERRATUM(2743089), ERRATA_N2_2743089
+	apply_erratum neoverse_n2, ERRATUM(2743089), ERRATA_N2_2743089, NO_GET_CPU_REV
 
 	isb
 	ret
diff --git a/lib/cpus/aarch64/neoverse_v1.S b/lib/cpus/aarch64/neoverse_v1.S
index 89299b7..1ec3e94 100644
--- a/lib/cpus/aarch64/neoverse_v1.S
+++ b/lib/cpus/aarch64/neoverse_v1.S
@@ -253,7 +253,7 @@
 	 * ---------------------------------------------
 	 */
 	sysreg_bit_set NEOVERSE_V1_CPUPWRCTLR_EL1, NEOVERSE_V1_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
-	apply_erratum neoverse_v1, ERRATUM(2743093), ERRATA_V1_2743093
+	apply_erratum neoverse_v1, ERRATUM(2743093), ERRATA_V1_2743093, NO_GET_CPU_REV
 
 	isb
 	ret
diff --git a/lib/cpus/aarch64/neoverse_v2.S b/lib/cpus/aarch64/neoverse_v2.S
index d8c32a4..ca66f8d 100644
--- a/lib/cpus/aarch64/neoverse_v2.S
+++ b/lib/cpus/aarch64/neoverse_v2.S
@@ -100,7 +100,7 @@
 	 * ---------------------------------------------------
 	 */
 	sysreg_bit_set NEOVERSE_V2_CPUPWRCTLR_EL1, NEOVERSE_V2_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
-	apply_erratum neoverse_v2, ERRATUM(2801372), ERRATA_V2_2801372
+	apply_erratum neoverse_v2, ERRATUM(2801372), ERRATA_V2_2801372, NO_GET_CPU_REV
 
 	isb
 	ret
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index ab9d4b6..a353a87 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -400,9 +400,6 @@
 	/* PMUv3 is presumed to be always present */
 	mrs	x9, pmcr_el0
 	str	x9, [sp, #CTX_EL3STATE_OFFSET + CTX_PMCR_EL0]
-	/* Disable cycle counter when event counting is prohibited */
-	orr	x9, x9, #PMCR_EL0_DP_BIT
-	msr	pmcr_el0, x9
 	isb
 #if CTX_INCLUDE_PAUTH_REGS
 	/* ----------------------------------------------------------
@@ -444,12 +441,7 @@
  */
 func prepare_el3_entry
 	save_gp_pmcr_pauth_regs
-	enable_serror_at_el3
-	/*
-	 * Set the PSTATE bits not described in the Aarch64.TakeException
-	 * pseudocode to their default values.
-	 */
-	set_unset_pstate_bits
+	setup_el3_execution_context
 	ret
 endfunc prepare_el3_entry
 
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 6210356..003cb25 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -260,6 +260,21 @@
 	 */
 	scr_el3 |= get_scr_el3_from_routing_model(NON_SECURE);
 #endif
+
+	if (is_feat_the_supported()) {
+		/* Set the RCWMASKEn bit in SCR_EL3 to enable access to
+		 * RCWMASK_EL1 and RCWSMASK_EL1 registers.
+		 */
+		scr_el3 |= SCR_RCWMASKEn_BIT;
+	}
+
+	if (is_feat_sctlr2_supported()) {
+		/* Set the SCTLR2En bit in SCR_EL3 to enable access to
+		 * SCTLR2_ELx registers.
+		 */
+		scr_el3 |= SCR_SCTLR2En_BIT;
+	}
+
 	write_ctx_reg(state, CTX_SCR_EL3, scr_el3);
 
 	/* Initialize EL2 context registers */
@@ -760,13 +775,6 @@
 		 */
 		trf_enable(ctx);
 	}
-
-	if (is_feat_brbe_supported()) {
-		/*
-		 * Enable FEAT_BRBE for Non-Secure and prohibit for Secure state.
-		 */
-		brbe_enable(ctx);
-	}
 #endif /* IMAGE_BL31 */
 }
 
@@ -792,6 +800,10 @@
 		debugv8p9_extended_bp_wp_enable(ctx);
 	}
 
+	if (is_feat_brbe_supported()) {
+		brbe_enable(ctx);
+	}
+
 	pmuv3_enable(ctx);
 #endif /* IMAGE_BL31 */
 }
@@ -1437,6 +1449,10 @@
 		write_el2_ctx_gcs(el2_sysregs_ctx, gcscr_el2, read_gcscr_el2());
 		write_el2_ctx_gcs(el2_sysregs_ctx, gcspr_el2, read_gcspr_el2());
 	}
+
+	if (is_feat_sctlr2_supported()) {
+		write_el2_ctx_sctlr2(el2_sysregs_ctx, sctlr2_el2, read_sctlr2_el2());
+	}
 }
 
 /*******************************************************************************
@@ -1524,6 +1540,10 @@
 		write_gcscr_el2(read_el2_ctx_gcs(el2_sysregs_ctx, gcscr_el2));
 		write_gcspr_el2(read_el2_ctx_gcs(el2_sysregs_ctx, gcspr_el2));
 	}
+
+	if (is_feat_sctlr2_supported()) {
+		write_sctlr2_el2(read_el2_ctx_sctlr2(el2_sysregs_ctx, sctlr2_el2));
+	}
 }
 #endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
 
@@ -1712,6 +1732,16 @@
 		write_el1_ctx_gcs(ctx, gcspr_el1, read_gcspr_el1());
 		write_el1_ctx_gcs(ctx, gcspr_el0, read_gcspr_el0());
 	}
+
+	if (is_feat_the_supported()) {
+		write_el1_ctx_the(ctx, rcwmask_el1, read_rcwmask_el1());
+		write_el1_ctx_the(ctx, rcwsmask_el1, read_rcwsmask_el1());
+	}
+
+	if (is_feat_sctlr2_supported()) {
+		write_el1_ctx_sctlr2(ctx, sctlr2_el1, read_sctlr2_el1());
+	}
+
 }
 
 static void el1_sysregs_context_restore(el1_sysregs_t *ctx)
@@ -1807,6 +1837,16 @@
 		write_gcspr_el1(read_el1_ctx_gcs(ctx, gcspr_el1));
 		write_gcspr_el0(read_el1_ctx_gcs(ctx, gcspr_el0));
 	}
+
+	if (is_feat_the_supported()) {
+		write_rcwmask_el1(read_el1_ctx_the(ctx, rcwmask_el1));
+		write_rcwsmask_el1(read_el1_ctx_the(ctx, rcwsmask_el1));
+	}
+
+	if (is_feat_sctlr2_supported()) {
+		write_sctlr2_el1(read_el1_ctx_sctlr2(ctx, sctlr2_el1));
+	}
+
 }
 
 /*******************************************************************************
diff --git a/lib/extensions/brbe/brbe.c b/lib/extensions/brbe/brbe.c
index dde0266..fef6647 100644
--- a/lib/extensions/brbe/brbe.c
+++ b/lib/extensions/brbe/brbe.c
@@ -16,11 +16,13 @@
 
 	/*
 	 * MDCR_EL3.SBRBE = 0b01
-	 *
 	 * Allows BRBE usage in non-secure world and prohibited in
 	 * secure world.
+	 *
+	 * MDCR_EL3.{E3BREW, E3BREC} = 0b00
+	 * Branch recording at EL3 is disabled
 	 */
-	mdcr_el3_val &= ~(MDCR_SBRBE_MASK << MDCR_SBRBE_SHIFT);
+	mdcr_el3_val &= ~((MDCR_SBRBE_MASK << MDCR_SBRBE_SHIFT) | MDCR_E3BREW | MDCR_E3BREC);
 	mdcr_el3_val |= (0x1UL << MDCR_SBRBE_SHIFT);
 	write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
 }
diff --git a/lib/psci/aarch64/psci_helpers.S b/lib/psci/aarch64/psci_helpers.S
index 3b77ab2..cca08c1 100644
--- a/lib/psci/aarch64/psci_helpers.S
+++ b/lib/psci/aarch64/psci_helpers.S
@@ -1,11 +1,12 @@
 /*
- * Copyright (c) 2014-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2024, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <asm_macros.S>
 #include <assert_macros.S>
+#include <cpu_macros.S>
 #include <lib/psci/psci.h>
 #include <platform_def.h>
 
@@ -124,9 +125,8 @@
  * -----------------------------------------------------------------------
  */
 func psci_power_down_wfi
-#if ERRATA_A510_2684597
-	bl apply_cpu_pwr_dwn_errata
-#endif
+	apply_erratum cortex_a510, ERRATUM(2684597), ERRATA_A510_2684597
+
 	dsb	sy		// ensure write buffer empty
 1:
 	wfi
diff --git a/lib/psci/aarch64/runtime_errata.S b/lib/psci/aarch64/runtime_errata.S
deleted file mode 100644
index 89e3e12..0000000
--- a/lib/psci/aarch64/runtime_errata.S
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <asm_macros.S>
-#include <cortex_a510.h>
-#include <cpu_macros.S>
-
-/*
- * void apply_cpu_pwr_dwn_errata(void);
- *
- * This function applies various CPU errata during power down.
- */
-	.globl apply_cpu_pwr_dwn_errata
-func apply_cpu_pwr_dwn_errata
-	mov	x19, x30
-	bl      cpu_get_rev_var
-	mov	x18, x0
-
-#if ERRATA_A510_2684597
-	bl erratum_cortex_a510_2684597_wa
-#endif
-
-	ret	x19
-endfunc apply_cpu_pwr_dwn_errata
diff --git a/lib/psci/psci_lib.mk b/lib/psci/psci_lib.mk
index c71580f..527ad3a 100644
--- a/lib/psci/psci_lib.mk
+++ b/lib/psci/psci_lib.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016-2023, Arm Limited and Contributors. All rights reserved.
+# Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -21,8 +21,7 @@
 				lib/psci/${ARCH}/psci_helpers.S
 
 ifeq (${ARCH}, aarch64)
-PSCI_LIB_SOURCES	+=	lib/el3_runtime/aarch64/context.S	\
-				lib/psci/aarch64/runtime_errata.S
+PSCI_LIB_SOURCES	+=	lib/el3_runtime/aarch64/context.S
 endif
 
 ifeq (${USE_COHERENT_MEM}, 1)
diff --git a/make_helpers/arch_features.mk b/make_helpers/arch_features.mk
index 675779f..6c893f4 100644
--- a/make_helpers/arch_features.mk
+++ b/make_helpers/arch_features.mk
@@ -90,7 +90,7 @@
 
 # Enable the features which are mandatory from ARCH version 8.9 and upwards.
 ifeq "8.9" "$(word 1, $(sort 8.9 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))"
-armv8-9-a-feats         := ENABLE_FEAT_TCR2 ENABLE_FEAT_DEBUGV8P9
+armv8-9-a-feats         := ENABLE_FEAT_TCR2 ENABLE_FEAT_DEBUGV8P9 ENABLE_FEAT_SCTLR2
 # 8.8 Compliant
 armv8-9-a-feats         += ${armv8-8-a-feats}
 FEAT_LIST               := ${armv8-9-a-feats}
@@ -219,6 +219,9 @@
 # Flag to enable access to TCR2 (FEAT_TCR2).
 ENABLE_FEAT_TCR2		?=	0
 
+# Flag to enable access to SCTLR2 (FEAT_SCTLR2).
+ENABLE_FEAT_SCTLR2		?=	0
+
 #
 ################################################################################
 # Optional Features defaulted to 0 or 2, if they are not enabled from
@@ -307,13 +310,6 @@
 # registers, by setting SCR_EL3.TRNDR.
 ENABLE_FEAT_RNG_TRAP			?=	0
 
-ifeq ($(CTX_INCLUDE_MTE_REGS),1)
-        $(warning CTX_INCLUDE_MTE_REGS option is deprecated, Check ENABLE_FEAT_MTE2 usage)
-endif
-ifneq ($(ENABLE_FEAT_MTE),)
-        $(warning ENABLE_FEAT_MTE option is deprecated, Check ENABLE_FEAT_MTE2 usage)
-endif
-
 # Enable FEAT_MTE2. This must be set to 1 if the platform wants
 # to use this feature and is enabled at ELX.
 ENABLE_FEAT_MTE2		        ?=	0
@@ -341,6 +337,13 @@
 ENABLE_FEAT_FGT2			?=	0
 
 #----
+# 8.8
+#----
+
+# Flag to enable FEAT_THE (Translation Hardening Extension)
+ENABLE_FEAT_THE				?=	0
+
+#----
 # 8.9
 #----
 
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 8c884b4..584542c 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -409,3 +409,6 @@
 # Allow platforms to save/restore DSU PMU registers over a power cycle.
 # Disabled by default and must be enabled by individual platforms.
 PRESERVE_DSU_PMU_REGS		:= 0
+
+# Enable RMMD to forward attestation requests from RMM to EL3.
+RMMD_ENABLE_EL3_TOKEN_SIGN	:= 0
diff --git a/plat/allwinner/sun50i_a64/platform.mk b/plat/allwinner/sun50i_a64/platform.mk
index e3c7c52..cced7f0 100644
--- a/plat/allwinner/sun50i_a64/platform.mk
+++ b/plat/allwinner/sun50i_a64/platform.mk
@@ -4,6 +4,10 @@
 # SPDX-License-Identifier: BSD-3-Clause
 #
 
+# To report supported idle states
+# this has to be defined before allwinner-common.mk
+SUNXI_AMEND_DTB		:=	1
+
 # The differences between the platform are covered by the include files.
 include plat/allwinner/common/allwinner-common.mk
 
diff --git a/plat/allwinner/sun50i_a64/platform_defaults.mk b/plat/allwinner/sun50i_a64/platform_defaults.mk
new file mode 100644
index 0000000..5b61029
--- /dev/null
+++ b/plat/allwinner/sun50i_a64/platform_defaults.mk
@@ -0,0 +1,9 @@
+#
+# Copyright (c) 2024, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# LTO has to be enabled on this platform due to memory constraints
+ENABLE_LTO			:= 1
+
diff --git a/plat/amd/versal2/aarch64/common.c b/plat/amd/versal2/aarch64/common.c
index 3ab3dca..5fce01e 100644
--- a/plat/amd/versal2/aarch64/common.c
+++ b/plat/amd/versal2/aarch64/common.c
@@ -31,7 +31,7 @@
 	MAP_REGION_FLAT(DEVICE2_BASE, DEVICE2_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(CRF_BASE, CRF_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
 	MAP_REGION_FLAT(IPI_BASE, IPI_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
-#if defined(TRANSFER_LIST)
+#if TRANSFER_LIST
 	MAP_REGION_FLAT(FW_HANDOFF_BASE, FW_HANDOFF_BASE + FW_HANDOFF_SIZE,
 			MT_MEMORY | MT_RW | MT_NS),
 #endif
diff --git a/plat/amd/versal2/bl31_setup.c b/plat/amd/versal2/bl31_setup.c
index 970fca9..64c356a 100644
--- a/plat/amd/versal2/bl31_setup.c
+++ b/plat/amd/versal2/bl31_setup.c
@@ -20,12 +20,14 @@
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #include <plat/common/platform.h>
 #include <plat_arm.h>
+#include <plat_console.h>
 #include <scmi.h>
 
 #include <def.h>
 #include <plat_fdt.h>
 #include <plat_private.h>
 #include <plat_startup.h>
+#include <plat_xfer_list.h>
 #include <pm_api_sys.h>
 #include <pm_client.h>
 
@@ -125,30 +127,7 @@
 
 	uart_clock = get_uart_clk();
 
-	if (CONSOLE_IS(pl011_0) || CONSOLE_IS(pl011_1)) {
-		static console_t _runtime_console;
-
-		/* Initialize the console to provide early debug support */
-		rc = console_pl011_register(UART_BASE, uart_clock,
-					    UART_BAUDRATE,
-					    &_runtime_console);
-		if (rc == 0) {
-			panic();
-		}
-
-		console_set_scope(&_runtime_console, CONSOLE_FLAG_BOOT |
-				  CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
-	} else if (CONSOLE_IS(dcc)) {
-		/* Initialize the dcc console for debug.
-		 * dcc is over jtag and does not configures uart0 or uart1.
-		 */
-		rc = console_dcc_register();
-		if (rc == 0) {
-			panic();
-		}
-	} else {
-		/* Making MISRA C 2012 15.7 compliant */
-	}
+	setup_console();
 
 	NOTICE("TF-A running on %s %d.%d\n", board_name_decode(),
 	       platform_version / 10U, platform_version % 10U);
@@ -168,7 +147,12 @@
 	SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
 	SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
 	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
-	bl31_set_default_config();
+
+	rc = transfer_list_populate_ep_info(&bl32_image_ep_info, &bl33_image_ep_info);
+	if (rc == TL_OPS_NON || rc == TL_OPS_CUS) {
+		NOTICE("BL31: TL not found, using default config\n");
+		bl31_set_default_config();
+	}
 
 	long rev_var = cpu_get_rev_var();
 
@@ -254,6 +238,8 @@
 	if (rc != 0) {
 		panic();
 	}
+
+	console_switch_state(CONSOLE_FLAG_RUNTIME);
 }
 
 /*
@@ -262,10 +248,6 @@
 void bl31_plat_arch_setup(void)
 {
 	const mmap_region_t bl_regions[] = {
-#if (defined(XILINX_OF_BOARD_DTB_ADDR) && !IS_TFA_IN_OCM(BL31_BASE))
-		MAP_REGION_FLAT(XILINX_OF_BOARD_DTB_ADDR, XILINX_OF_BOARD_DTB_MAX_SIZE,
-				MT_MEMORY | MT_RW | MT_NS),
-#endif
 		MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_BASE,
 			MT_MEMORY | MT_RW | MT_SECURE),
 		MAP_REGION_FLAT(BL_CODE_BASE, BL_CODE_END - BL_CODE_BASE,
diff --git a/plat/amd/versal2/include/def.h b/plat/amd/versal2/include/def.h
index 67244a4..f3a7907 100644
--- a/plat/amd/versal2/include/def.h
+++ b/plat/amd/versal2/include/def.h
@@ -15,12 +15,23 @@
 #define MAX_INTR_EL3			2
 
 /* List all consoles */
-#define CONSOLE_ID_pl011	U(1)
-#define CONSOLE_ID_pl011_0	U(1)
-#define CONSOLE_ID_pl011_1	U(2)
-#define CONSOLE_ID_dcc	U(3)
+#define VERSAL2_CONSOLE_ID_none		0
+#define VERSAL2_CONSOLE_ID_pl011	1
+#define VERSAL2_CONSOLE_ID_pl011_0       1
+#define VERSAL2_CONSOLE_ID_pl011_1       2
+#define VERSAL2_CONSOLE_ID_dcc           3
+#define VERSAL2_CONSOLE_ID_dtb           4
 
-#define CONSOLE_IS(con)	(CONSOLE_ID_ ## con == CONSOLE)
+#define CONSOLE_IS(con) (VERSAL2_CONSOLE_ID_ ## con == VERSAL2_CONSOLE)
+
+/* Runtime console */
+#define RT_CONSOLE_ID_pl011   1
+#define RT_CONSOLE_ID_pl011_0   1
+#define RT_CONSOLE_ID_pl011_1   2
+#define RT_CONSOLE_ID_dcc       3
+#define RT_CONSOLE_ID_dtb       4
+
+#define RT_CONSOLE_IS(con)      (RT_CONSOLE_ID_ ## con == CONSOLE_RUNTIME)
 
 /* List all platforms */
 #define SILICON		U(0)
@@ -143,11 +154,35 @@
 
 #define UART_BAUDRATE	115200
 
-#if CONSOLE_IS(pl011_1)
-#define UART_BASE		UART1_BASE
+#if CONSOLE_IS(pl011) || CONSOLE_IS(dtb)
+#define UART_BASE	    UART0_BASE
+# define UART_TYPE	CONSOLE_PL011
+#elif CONSOLE_IS(pl011_1)
+#define UART_BASE           UART1_BASE
+# define UART_TYPE	CONSOLE_PL011
+#elif CONSOLE_IS(dcc)
+# define UART_BASE	0x0
+# define UART_TYPE	CONSOLE_DCC
+#elif CONSOLE_IS(none)
+# define UART_TYPE	CONSOLE_NONE
+#else
+# error "invalid VERSAL2_CONSOLE"
+#endif
+
+/* Runtime console */
+#if defined(CONSOLE_RUNTIME)
+#if RT_CONSOLE_IS(pl011) || RT_CONSOLE_IS(dtb)
+# define RT_UART_BASE UART0_BASE
+# define RT_UART_TYPE	CONSOLE_PL011
+#elif RT_CONSOLE_IS(pl011_1)
+# define RT_UART_BASE UART1_BASE
+# define RT_UART_TYPE	CONSOLE_PL011
+#elif RT_CONSOLE_IS(dcc)
+# define RT_UART_BASE	0x0
+# define RT_UART_TYPE	CONSOLE_DCC
 #else
-/* Default console is UART0 */
-#define UART_BASE            UART0_BASE
+# error "invalid CONSOLE_RUNTIME"
+#endif
 #endif
 
 #endif /* DEF_H */
diff --git a/plat/amd/versal2/include/platform_def.h b/plat/amd/versal2/include/platform_def.h
index 090fe46..42c9b08 100644
--- a/plat/amd/versal2/include/platform_def.h
+++ b/plat/amd/versal2/include/platform_def.h
@@ -91,7 +91,7 @@
 #define PLAT_OCM_BASE			U(0xBBF00000)
 #define PLAT_OCM_LIMIT			U(0xBC000000)
 
-#if defined(TRANSFER_LIST)
+#if TRANSFER_LIST
 /*
  * FIXME: This address should come from firmware before TF-A
  * Having this to make sure the transfer list functionality works
diff --git a/plat/amd/versal2/platform.mk b/plat/amd/versal2/platform.mk
index 3892fcb..3114976 100644
--- a/plat/amd/versal2/platform.mk
+++ b/plat/amd/versal2/platform.mk
@@ -6,6 +6,9 @@
 
 PLAT_PATH := plat/amd/versal2
 
+override NEED_BL1 := no
+override NEED_BL2 := no
+
 # A78 Erratum for SoC
 ERRATA_A78_AE_1941500 := 1
 ERRATA_A78_AE_1951502 := 1
@@ -28,6 +31,10 @@
 
 override CTX_INCLUDE_AARCH32_REGS    := 0
 
+# Platform to support Dynamic XLAT Table by default
+override PLAT_XLAT_TABLES_DYNAMIC := 1
+$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC))
+
 ifdef MEM_BASE
     $(eval $(call add_define,MEM_BASE))
 
@@ -57,13 +64,28 @@
 USE_COHERENT_MEM := 0
 HW_ASSISTED_COHERENCY := 1
 
-CONSOLE	?=	pl011
-ifeq (${CONSOLE}, $(filter ${CONSOLE},pl011 pl011_0 pl011_1 dcc))
+VERSAL2_CONSOLE  ?=      pl011
+ifeq (${VERSAL2_CONSOLE}, $(filter ${VERSAL2_CONSOLE},pl011 pl011_0 pl011_1 dcc dtb none))
+	else
+	  $(error "Please define VERSAL2_CONSOLE")
+  endif
+
+$(eval $(call add_define_val,VERSAL2_CONSOLE,VERSAL2_CONSOLE_ID_${VERSAL2_CONSOLE}))
+
+# Runtime console in default console in DEBUG build
+ifeq ($(DEBUG), 1)
+CONSOLE_RUNTIME ?= pl011
+endif
+
+# Runtime console
+ifdef CONSOLE_RUNTIME
+ifeq 	(${CONSOLE_RUNTIME}, $(filter ${CONSOLE_RUNTIME},pl011 pl011_0 pl011_1 dcc dtb))
+$(eval $(call add_define_val,CONSOLE_RUNTIME,RT_CONSOLE_ID_${CONSOLE_RUNTIME}))
 else
-  $(error Please define CONSOLE)
+	$(error "Please define CONSOLE_RUNTIME")
+endif
 endif
 
-$(eval $(call add_define_val,CONSOLE,CONSOLE_ID_${CONSOLE}))
 
 ifdef XILINX_OF_BOARD_DTB_ADDR
 $(eval $(call add_define,XILINX_OF_BOARD_DTB_ADDR))
@@ -109,6 +131,9 @@
 BL31_SOURCES		+=	${PLAT_PATH}/plat_psci.c
 
 BL31_SOURCES		+=	plat/xilinx/common/plat_fdt.c			\
+				common/fdt_wrappers.c                           \
+				plat/xilinx/common/plat_fdt.c                   \
+				plat/xilinx/common/plat_console.c               \
 				plat/xilinx/common/plat_startup.c		\
 				plat/xilinx/common/ipi.c			\
 				plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c	\
@@ -126,3 +151,9 @@
 CORTEX_A78_AE_H_INC     := 1
 $(eval $(call add_define, CORTEX_A78_AE_H_INC))
 endif
+
+# Enable Handoff protocol using transfer lists
+TRANSFER_LIST                   := 1
+
+include lib/transfer_list/transfer_list.mk
+BL31_SOURCES           +=      plat/xilinx/common/plat_xfer_list.c
diff --git a/plat/amd/versal2/scmi.c b/plat/amd/versal2/scmi.c
index 7f4b6df..59aff08 100644
--- a/plat/amd/versal2/scmi.c
+++ b/plat/amd/versal2/scmi.c
@@ -51,8 +51,8 @@
 	CLOCK_CELL(CLK_SERIAL1_0, CLK_SERIAL1_0, "uart1_uartclk", true, 100000000),
 	CLOCK_CELL(CLK_SERIAL1_1, CLK_SERIAL1_1, "uart1_apb_pclk", true, 100000000),
 	CLOCK_CELL(CLK_UFS0_0, CLK_UFS0_0, "ufs_core_clk", true, 100000000),
-	CLOCK_CELL(CLK_UFS0_1, CLK_UFS0_1, "ufs_phy_clk", true, 100000000),
-	CLOCK_CELL(CLK_UFS0_2, CLK_UFS0_2, "ufs_ref_pclk", true, 100000000),
+	CLOCK_CELL(CLK_UFS0_1, CLK_UFS0_1, "ufs_phy_clk", true, 26000000),
+	CLOCK_CELL(CLK_UFS0_2, CLK_UFS0_2, "ufs_ref_pclk", true, 26000000),
 	CLOCK_CELL(CLK_USB0_0, CLK_USB0_0, "usb0_bus_clk", true, 100000000),
 	CLOCK_CELL(CLK_USB0_1, CLK_USB0_1, "usb0_ref_clk", true, 100000000),
 	CLOCK_CELL(CLK_USB0_2, CLK_USB0_2, "usb0_dwc_clk", true, 100000000),
@@ -649,6 +649,11 @@
 			/* Keep i2c on 100MHz to calculate rates properly */
 			if (i >= CLK_I2C0_0 && i <= CLK_I2C7_0)
 				continue;
+
+			/* Keep UFS clocks to default values to get the expected rates */
+			if (i >= CLK_UFS0_0 && i <= CLK_UFS0_2)
+				continue;
+
 			/*
 			 * SPP supports multiple versions.
 			 * The cpu_clock value is set to corresponding SPP
diff --git a/plat/arm/board/fvp/fvp_el3_token_sign.c b/plat/arm/board/fvp/fvp_el3_token_sign.c
new file mode 100644
index 0000000..282f94a
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_el3_token_sign.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2024, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include <plat/common/platform.h>
+#include <services/rmm_el3_token_sign.h>
+
+static struct el3_token_sign_request el3_req = { 0 };
+static bool el3_req_valid;
+
+/*
+ * According to https://www.secg.org/sec1-v2.pdf 2.3.3
+ * the size of the ECDSA P384 public key is 97 bytes,
+ * with the first byte being 0x04.
+ */
+static uint8_t sample_attest_pub_key[] = {
+	0x04, 0x76, 0xf9, 0x88, 0x09, 0x1b, 0xe5, 0x85, 0xed, 0x41,
+	0x80, 0x1a, 0xec, 0xfa, 0xb8, 0x58, 0x54, 0x8c, 0x63, 0x05,
+	0x7e, 0x16, 0xb0, 0xe6, 0x76, 0x12, 0x0b, 0xbd, 0x0d, 0x2f,
+	0x9c, 0x29, 0xe0, 0x56, 0xc5, 0xd4, 0x1a, 0x01, 0x30, 0xeb,
+	0x9c, 0x21, 0x51, 0x78, 0x99, 0xdc, 0x23, 0x14, 0x6b, 0x28,
+	0xe1, 0xb0, 0x62, 0xbd, 0x3e, 0xa4, 0xb3, 0x15, 0xfd, 0x21,
+	0x9f, 0x1c, 0xbb, 0x52, 0x8c, 0xb6, 0xe7, 0x4c, 0xa4, 0x9b,
+	0xe1, 0x67, 0x73, 0x73, 0x4f, 0x61, 0xa1, 0xca, 0x61, 0x03,
+	0x1b, 0x2b, 0xbf, 0x3d, 0x91, 0x8f, 0x2f, 0x94, 0xff, 0xc4,
+	0x22, 0x8e, 0x50, 0x91, 0x95, 0x44, 0xae
+};
+
+/*
+ * FVP does not support HES, so provide 0's as keys.
+ */
+int plat_rmmd_el3_token_sign_get_rak_pub(uintptr_t buf, size_t *len,
+					 unsigned int type)
+{
+	(void)type;
+	if (*len < sizeof(sample_attest_pub_key)) {
+		return E_RMM_INVAL;
+	}
+
+	if (type != ATTEST_KEY_CURVE_ECC_SECP384R1) {
+		ERROR("Invalid ECC curve specified\n");
+		return E_RMM_INVAL;
+	}
+
+	*len = sizeof(sample_attest_pub_key);
+
+	(void)memcpy((void *)buf, sample_attest_pub_key,
+		     sizeof(sample_attest_pub_key));
+
+	return 0;
+}
+
+int plat_rmmd_el3_token_sign_push_req(const struct el3_token_sign_request *req)
+{
+	/*
+	 * TODO: Today this function is called with a lock held on the
+	 * RMM<->EL3 shared buffer. In the future, we may move to a
+	 * different design that may require handling multi-threaded
+	 * calls to this function, for example, if we have a per CPU
+	 * buffer between RMM and EL3.
+	 */
+	if (el3_req_valid) {
+		return E_RMM_AGAIN;
+	}
+
+	el3_req = *req;
+
+	if ((el3_req.hash_alg_id != EL3_TOKEN_SIGN_HASH_ALG_SHA384) ||
+	    (el3_req.sig_alg_id != ATTEST_KEY_CURVE_ECC_SECP384R1)) {
+		return E_RMM_INVAL;
+	}
+
+	el3_req_valid = true;
+
+	return 0;
+}
+
+int plat_rmmd_el3_token_sign_pull_resp(struct el3_token_sign_response *resp)
+{
+	if (!el3_req_valid) {
+		return E_RMM_AGAIN;
+	}
+
+	resp->rec_granule = el3_req.rec_granule;
+	resp->req_ticket = el3_req.req_ticket;
+	resp->sig_len = (uint16_t)sizeof(resp->signature_buf);
+	/* TODO: Provide real signature */
+	memset(resp->signature_buf, 0, sizeof(resp->signature_buf));
+
+	el3_req_valid = false;
+
+	return 0;
+}
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index feae802..7cb3982 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -71,11 +71,13 @@
 ENABLE_FEAT_ECV			:= 2
 ENABLE_FEAT_FGT			:= 2
 ENABLE_FEAT_FGT2		:= 2
+ENABLE_FEAT_THE			:= 2
 ENABLE_FEAT_TCR2		:= 2
 ENABLE_FEAT_S2PIE		:= 2
 ENABLE_FEAT_S1PIE		:= 2
 ENABLE_FEAT_S2POE		:= 2
 ENABLE_FEAT_S1POE		:= 2
+ENABLE_FEAT_SCTLR2		:= 2
 ENABLE_FEAT_MTE2		:= 2
 
 # The FVP platform depends on this macro to build with correct GIC driver.
@@ -194,6 +196,7 @@
 					lib/cpus/aarch64/cortex_a710.S		\
 					lib/cpus/aarch64/cortex_a715.S		\
 					lib/cpus/aarch64/cortex_a720.S		\
+					lib/cpus/aarch64/cortex_a720_ae.S	\
 					lib/cpus/aarch64/neoverse_n_common.S	\
 					lib/cpus/aarch64/neoverse_n1.S		\
 					lib/cpus/aarch64/neoverse_n2.S		\
@@ -209,10 +212,11 @@
 
 #Build AArch64-only CPUs with no FVP model yet.
 ifeq (${BUILD_CPUS_WITH_NO_FVP_MODEL},1)
-	FVP_CPU_LIBS    +=	lib/cpus/aarch64/neoverse_n3.S	\
+	FVP_CPU_LIBS    +=	lib/cpus/aarch64/neoverse_n3.S		\
 				lib/cpus/aarch64/cortex_gelas.S		\
 				lib/cpus/aarch64/nevis.S		\
-				lib/cpus/aarch64/travis.S
+				lib/cpus/aarch64/travis.S		\
+				lib/cpus/aarch64/cortex_arcadia.S
 endif
 
 else
@@ -264,7 +268,8 @@
 				plat/arm/board/fvp/fvp_cpu_pwr.c
 
 BL31_SOURCES		+=	plat/arm/board/fvp/fvp_plat_attest_token.c	\
-				plat/arm/board/fvp/fvp_realm_attest_key.c
+				plat/arm/board/fvp/fvp_realm_attest_key.c	\
+				plat/arm/board/fvp/fvp_el3_token_sign.c
 endif
 
 ifeq (${ENABLE_FEAT_RNG_TRAP},1)
diff --git a/plat/arm/board/tc/fdts/tc_spmc_manifest.dtsi b/plat/arm/board/tc/fdts/tc_spmc_manifest.dtsi
index a6b63a1..737997d 100644
--- a/plat/arm/board/tc/fdts/tc_spmc_manifest.dtsi
+++ b/plat/arm/board/tc/fdts/tc_spmc_manifest.dtsi
@@ -99,11 +99,7 @@
 
 	memory@1 {
 		device_type = "ns-memory";
-		reg =
-#ifdef TS_SP_FW_CONFIG
-		      <0x0 0x08000000 0x0 0x4000000>,
-#endif /* TS_SP_FW_CONFIG */
-		      <0x0 TC_NS_DRAM1_BASE 0x0 TC_NS_DRAM1_SIZE>,
+		reg = <0x0 TC_NS_DRAM1_BASE 0x0 TC_NS_DRAM1_SIZE>,
 		      <HI(PLAT_ARM_DRAM2_BASE) LO(PLAT_ARM_DRAM2_BASE)
 		       HI(TC_NS_DRAM2_SIZE) LO(TC_NS_DRAM2_SIZE)>;
 	};
@@ -117,4 +113,11 @@
 		device_type = "device-memory";
 		reg = <0x0 PLAT_ARM_BOOT_UART_BASE 0x0 0x01000>;
 	};
+
+#ifdef TS_SP_FW_CONFIG
+	ns_flash {
+		device_type = "ns-device-memory";
+		reg = <0x0 V2M_FLASH0_BASE 0x0 V2M_FLASH0_SIZE>;
+	};
+#endif
 };
diff --git a/plat/arm/board/tc/include/platform_def.h b/plat/arm/board/tc/include/platform_def.h
index 0652148..86fce0e 100644
--- a/plat/arm/board/tc/include/platform_def.h
+++ b/plat/arm/board/tc/include/platform_def.h
@@ -51,9 +51,6 @@
  *               |      (4KB)     |
  *  0x8000_9000  ------------------
  *               |       ...      |
- *  0xf8a0_0000  ------------------   TC_NS_FWU_BASE
- *               |    FWU shmem   |
- *               |      (4MB)     |
  *  0xf8e0_0000  ------------------   TC_NS_OPTEE_BASE
  *               |  OP-TEE shmem  |
  *               |      (2MB)     |
@@ -85,8 +82,6 @@
 
 #define TC_NS_OPTEE_SIZE		(2 * SZ_1M)
 #define TC_NS_OPTEE_BASE		(TC_NS_DRAM1_BASE + TC_NS_DRAM1_SIZE - TC_NS_OPTEE_SIZE)
-#define TC_NS_FWU_SIZE			(4 * SZ_1M)
-#define TC_NS_FWU_BASE			(TC_NS_OPTEE_BASE - TC_NS_FWU_SIZE)
 
 /*
  * Mappings for TC DRAM1 (non-secure) and TC TZC DRAM1 (secure)
@@ -192,7 +187,7 @@
 # if SPM_MM
 #  define PLATFORM_STACK_SIZE		0x500
 # else
-#  define PLATFORM_STACK_SIZE		0xa00
+#  define PLATFORM_STACK_SIZE		0xb00
 # endif
 #elif defined(IMAGE_BL32)
 # define PLATFORM_STACK_SIZE		0x440
@@ -227,8 +222,11 @@
 #define TC_FLASH0_RO	MAP_REGION_FLAT(V2M_FLASH0_BASE,\
 						V2M_FLASH0_SIZE,	\
 						MT_DEVICE | MT_RO | MT_SECURE)
-
-#define PLAT_ARM_NSTIMER_FRAME_ID	0
+#if TARGET_PLATFORM == 2
+#define PLAT_ARM_NSTIMER_FRAME_ID	U(0)
+#else
+#define PLAT_ARM_NSTIMER_FRAME_ID	U(1)
+#endif
 
 #define PLAT_ARM_TRUSTED_ROM_BASE	0x0
 
diff --git a/plat/arm/board/tc/platform_test.mk b/plat/arm/board/tc/platform_test.mk
index 8d39325..2ce6648 100644
--- a/plat/arm/board/tc/platform_test.mk
+++ b/plat/arm/board/tc/platform_test.mk
@@ -33,6 +33,7 @@
     $(eval $(call add_define,PLATFORM_TEST_ROTPK))
 else ifeq (${PLATFORM_TEST},tfm-testsuite)
     include drivers/arm/rse/rse_comms.mk
+    include drivers/measured_boot/rse/qcbor.mk
 
     # The variables need to be set to compile the platform test:
     ifeq (${TF_M_TESTS_PATH},)
@@ -80,7 +81,8 @@
 				$(DELEGATED_ATTEST_TESTS_PATH)/delegated_attest_test.c \
 				drivers/auth/mbedtls/mbedtls_common.c		\
 				lib/psa/measured_boot.c				\
-				lib/psa/delegated_attestation.c
+				lib/psa/delegated_attestation.c			\
+				${QCBOR_SOURCES}
 
     PLAT_INCLUDES	+=	-I$(TF_M_EXTRAS_PATH)/partitions/measured_boot/interface/include \
 				-I$(TF_M_EXTRAS_PATH)/partitions/delegated_attestation/interface/include \
@@ -93,7 +95,8 @@
 				-Iplat/arm/board/tc				\
 				-Iinclude/drivers/auth/mbedtls			\
 				-Iinclude/drivers/arm				\
-				-Iinclude/lib/psa
+				-Iinclude/lib/psa				\
+				-I${QCBOR_INCLUDES}
 
     # Some of the PSA functions are declared in multiple header files, that
     # triggers this warning.
diff --git a/plat/intel/soc/agilex/bl2_plat_setup.c b/plat/intel/soc/agilex/bl2_plat_setup.c
index 36820b2..084539e 100644
--- a/plat/intel/soc/agilex/bl2_plat_setup.c
+++ b/plat/intel/soc/agilex/bl2_plat_setup.c
@@ -129,11 +129,13 @@
 
 	switch (boot_source) {
 	case BOOT_SOURCE_SDMMC:
+		NOTICE("SDMMC boot\n");
 		dw_mmc_init(&params, &mmc_info);
 		socfpga_io_setup(boot_source, PLAT_SDMMC_DATA_BASE);
 		break;
 
 	case BOOT_SOURCE_QSPI:
+		NOTICE("QSPI boot\n");
 		cad_qspi_init(0, QSPI_CONFIG_CPHA, QSPI_CONFIG_CPOL,
 			QSPI_CONFIG_CSDA, QSPI_CONFIG_CSDADS,
 			QSPI_CONFIG_CSEOT, QSPI_CONFIG_CSSOT, 0);
diff --git a/plat/intel/soc/agilex/bl31_plat_setup.c b/plat/intel/soc/agilex/bl31_plat_setup.c
index 6e45158..4c10e7b 100644
--- a/plat/intel/soc/agilex/bl31_plat_setup.c
+++ b/plat/intel/soc/agilex/bl31_plat_setup.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
  * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,12 +14,16 @@
 #include <drivers/ti/uart/uart_16550.h>
 #include <lib/mmio.h>
 #include <lib/xlat_tables/xlat_tables.h>
+#include <plat/common/platform.h>
 
 #include "ccu/ncore_ccu.h"
 #include "socfpga_mailbox.h"
 #include "socfpga_private.h"
 #include "socfpga_sip_svc.h"
 
+/* Get non-secure SPSR for BL33. Zephyr and Linux */
+uint32_t arm_get_spsr_for_bl33_entry(void);
+
 static entry_point_info_t bl32_image_ep_info;
 static entry_point_info_t bl33_image_ep_info;
 
@@ -59,9 +64,7 @@
 				u_register_t arg2, u_register_t arg3)
 {
 	static console_t console;
-
 	mmio_write_64(PLAT_SEC_ENTRY, PLAT_SEC_WARM_ENTRY);
-
 	console_16550_register(PLAT_INTEL_UART_BASE, PLAT_UART_CLOCK,
 		PLAT_BAUDRATE, &console);
 	/*
@@ -69,6 +72,33 @@
 	 */
 	void *from_bl2 = (void *) arg0;
 
+#if RESET_TO_BL31
+	/* There are no parameters from BL2 if BL31 is a reset vector */
+	assert(from_bl2 == NULL);
+	void *plat_params_from_bl2 = (void *) arg3;
+
+	assert(plat_params_from_bl2 == NULL);
+
+	/* Populate entry point information for BL33 */
+	SET_PARAM_HEAD(&bl33_image_ep_info,
+				PARAM_EP,
+				VERSION_1,
+				0);
+
+# if ARM_LINUX_KERNEL_AS_BL33
+	/*
+	 * According to the file ``Documentation/arm64/booting.txt`` of the
+	 * Linux kernel tree, Linux expects the physical address of the device
+	 * tree blob (DTB) in x0, while x1-x3 are reserved for future use and
+	 * must be 0.
+	 */
+	bl33_image_ep_info.args.arg0 = (u_register_t)ARM_PRELOADED_DTB_BASE;
+	bl33_image_ep_info.args.arg1 = 0U;
+	bl33_image_ep_info.args.arg2 = 0U;
+	bl33_image_ep_info.args.arg3 = 0U;
+# endif
+
+#else /* RESET_TO_BL31 */
 	bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2;
 	assert(params_from_bl2 != NULL);
 
@@ -76,28 +106,38 @@
 	 * Copy BL32 (if populated by BL31) and BL33 entry point information.
 	 * They are stored in Secure RAM, in BL31's address space.
 	 */
-
 	if (params_from_bl2->h.type == PARAM_BL_PARAMS &&
 		params_from_bl2->h.version >= VERSION_2) {
-
 		bl_params_node_t *bl_params = params_from_bl2->head;
-
 		while (bl_params) {
 			if (bl_params->image_id == BL33_IMAGE_ID)
 				bl33_image_ep_info = *bl_params->ep_info;
-
 			bl_params = bl_params->next_params_info;
 		}
 	} else {
 		struct socfpga_bl31_params *arg_from_bl2 =
 			(struct socfpga_bl31_params *) from_bl2;
-
 		assert(arg_from_bl2->h.type == PARAM_BL31);
 		assert(arg_from_bl2->h.version >= VERSION_1);
-
 		bl32_image_ep_info = *arg_from_bl2->bl32_ep_info;
 		bl33_image_ep_info = *arg_from_bl2->bl33_ep_info;
 	}
+
+	bl33_image_ep_info.args.arg0 = (u_register_t)ARM_PRELOADED_DTB_BASE;
+	bl33_image_ep_info.args.arg1 = 0U;
+	bl33_image_ep_info.args.arg2 = 0U;
+	bl33_image_ep_info.args.arg3 = 0U;
+#endif
+
+	/*
+	 * Tell BL31 where the non-trusted software image
+	 * is located and the entry state information
+	 */
+# if ARM_LINUX_KERNEL_AS_BL33
+	bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
+	bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry();
+#endif
+
 	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
 }
 
@@ -172,8 +212,34 @@
 #endif
 		{0}
 	};
-
 	setup_page_tables(bl_regions, plat_agilex_mmap);
 	enable_mmu_el3(0);
 }
 
+/* Get non-secure image entrypoint for BL33. Zephyr and Linux */
+uintptr_t plat_get_ns_image_entrypoint(void)
+{
+#ifdef PRELOADED_BL33_BASE
+	return PRELOADED_BL33_BASE;
+#else
+	return PLAT_NS_IMAGE_OFFSET;
+#endif
+}
+
+/* Get non-secure SPSR for BL33. Zephyr and Linux */
+uint32_t arm_get_spsr_for_bl33_entry(void)
+{
+	unsigned int mode;
+	uint32_t spsr;
+
+	/* Figure out what mode we enter the non-secure world in */
+	mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1;
+
+	/*
+	 * TODO: Consider the possibility of specifying the SPSR in
+	 * the FIP ToC and allowing the platform to have a say as
+	 * well.
+	 */
+	spsr = SPSR_64((uint64_t)mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
+	return spsr;
+}
diff --git a/plat/intel/soc/agilex/include/agilex_memory_controller.h b/plat/intel/soc/agilex/include/agilex_memory_controller.h
index 9db4292..f0bbeea 100644
--- a/plat/intel/soc/agilex/include/agilex_memory_controller.h
+++ b/plat/intel/soc/agilex/include/agilex_memory_controller.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -27,7 +28,7 @@
 #define AGX_MPFE_HMC_ADP_ECCCTRL1			0xf8011100
 #define AGX_MPFE_HMC_ADP_ECCCTRL2			0xf8011104
 #define AGX_MPFE_HMC_ADP_RSTHANDSHAKESTAT		0xf8011218
-#define AGX_MPFE_HMC_ADP_RSTHANDSHAKESTAT_SEQ2CORE	0x000000ff
+#define AGX_MPFE_HMC_ADP_RSTHANDSHAKESTAT_SEQ2CORE	0x0000000f
 #define AGX_MPFE_HMC_ADP_RSTHANDSHAKECTRL		0xf8011214
 
 
diff --git a/plat/intel/soc/agilex/include/agilex_system_manager.h b/plat/intel/soc/agilex/include/agilex_system_manager.h
index 20a62be..78aabde 100644
--- a/plat/intel/soc/agilex/include/agilex_system_manager.h
+++ b/plat/intel/soc/agilex/include/agilex_system_manager.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -121,7 +122,7 @@
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_8		0x220
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_9		0x224
 #define SOCFPGA_SYSMGR_MPFE_CONFIG			0x228
-#define SOCFPGA_SYSMGR_MPFE_status			0x22C
+#define SOCFPGA_SYSMGR_MPFE_STATUS			0x22C
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_WARM_0		0x230
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_WARM_1		0x234
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_WARM_2		0x238
diff --git a/plat/intel/soc/agilex/include/socfpga_plat_def.h b/plat/intel/soc/agilex/include/socfpga_plat_def.h
index 9ef7598..94fed3a 100644
--- a/plat/intel/soc/agilex/include/socfpga_plat_def.h
+++ b/plat/intel/soc/agilex/include/socfpga_plat_def.h
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
  * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,9 +16,16 @@
 /* Platform Setting */
 #define PLATFORM_MODEL				PLAT_SOCFPGA_AGILEX
 #define BOOT_SOURCE				BOOT_SOURCE_SDMMC
+/* 1 = Flush cache, 0 = No cache flush.
+ * Default for Agilex is No cache flush.
+ * For Agilex FP8, set to Flush cache.
+ */
+#define CACHE_FLUSH				0
 #define PLAT_PRIMARY_CPU			0
 #define PLAT_CLUSTER_ID_MPIDR_AFF_SHIFT		MPIDR_AFF1_SHIFT
 #define PLAT_CPU_ID_MPIDR_AFF_SHIFT		MPIDR_AFF0_SHIFT
+#define PLAT_HANDOFF_OFFSET			0xFFE3F000
+#define PLAT_TIMER_BASE_ADDR			0xFFD01000
 
 /* FPGA config helpers */
 #define INTEL_SIP_SMC_FPGA_CONFIG_ADDR		0x400000
@@ -27,6 +35,13 @@
 #define CAD_QSPIDATA_OFST			0xff900000
 #define CAD_QSPI_OFFSET				0xff8d2000
 
+/* SDMMC Setting */
+# if ARM_LINUX_KERNEL_AS_BL33
+#define SOCFPGA_MMC_BLOCK_SIZE			U(32768)
+# else
+#define SOCFPGA_MMC_BLOCK_SIZE			U(8192)
+# endif
+
 /* Register Mapping */
 #define SOCFPGA_CCU_NOC_REG_BASE		0xf7000000
 #define SOCFPGA_F2SDRAMMGR_REG_BASE		U(0xf8024000)
diff --git a/plat/intel/soc/agilex5/bl2_plat_setup.c b/plat/intel/soc/agilex5/bl2_plat_setup.c
index 265ee57..78a4889 100644
--- a/plat/intel/soc/agilex5/bl2_plat_setup.c
+++ b/plat/intel/soc/agilex5/bl2_plat_setup.c
@@ -20,9 +20,11 @@
 #include <lib/xlat_tables/xlat_tables_v2.h>
 
 #include "agilex5_clock_manager.h"
+#include "agilex5_ddr.h"
 #include "agilex5_memory_controller.h"
 #include "agilex5_mmc.h"
 #include "agilex5_pinmux.h"
+#include "agilex5_power_manager.h"
 #include "agilex5_system_manager.h"
 #include "ccu/ncore_ccu.h"
 #include "combophy/combophy.h"
@@ -66,33 +68,75 @@
 
 boot_source_type boot_source = BOOT_SOURCE;
 
-void bl2_el3_early_platform_setup(u_register_t x0, u_register_t x1,
-				u_register_t x2, u_register_t x4)
+void bl2_el3_early_platform_setup(u_register_t x0 __unused,
+				  u_register_t x1 __unused,
+				  u_register_t x2 __unused,
+				  u_register_t x3 __unused)
 {
 	static console_t console;
-
-	handoff reverse_handoff_ptr = { 0 };
+	handoff reverse_handoff_ptr;
 
-	generic_delay_timer_init();
-	config_clkmgr_handoff(&reverse_handoff_ptr);
-	mailbox_init();
+	/* Enable nonsecure access for peripherals and other misc components */
 	enable_nonsecure_access();
 
+	/* Bring all the required peripherals out of reset */
 	deassert_peripheral_reset();
-	if (combo_phy_init(&reverse_handoff_ptr) != 0) {
-		ERROR("Combo Phy initialization failed\n");
-	}
 
+	/*
+	 * Initialize the UART console early in BL2 EL3 boot flow to get
+	 * the error/notice messages wherever required.
+	 */
 	console_16550_register(PLAT_INTEL_UART_BASE, PLAT_UART_CLOCK,
-	PLAT_BAUDRATE, &console);
+			       PLAT_BAUDRATE, &console);
+
+	/* Generic delay timer init */
+	generic_delay_timer_init();
+
+	socfpga_delay_timer_init();
+
+	/* Get the handoff data */
+	if ((socfpga_get_handoff(&reverse_handoff_ptr)) != 0) {
+		ERROR("SOCFPGA: Failed to get the correct handoff data\n");
+		panic();
+	}
+
+	/* Configure the pinmux */
+	config_pinmux(&reverse_handoff_ptr);
 
-	/* Store magic number */
-	// TODO: Temp workaround to ungate testing
-	// mmio_write_32(L2_RESET_DONE_REG, PLAT_L2_RESET_REQ);
+	/* Configure the clock manager */
+	if ((config_clkmgr_handoff(&reverse_handoff_ptr)) != 0) {
+		ERROR("SOCFPGA: Failed to initialize the clock manager\n");
+		panic();
+	}
+
+	/* Configure power manager PSS SRAM power gate */
+	config_pwrmgr_handoff(&reverse_handoff_ptr);
+
+	/* Initialize the mailbox to enable communication between HPS and SDM */
+	mailbox_init();
+
+	/* Perform a handshake with certain peripherals before issuing a reset */
+	config_hps_hs_before_warm_reset();
+
+	/* TODO: watchdog init */
+	//watchdog_init(clkmgr_get_rate(CLKMGR_WDT_CLK_ID));
+
+	/* Initialize the CCU module for hardware cache coherency */
+	init_ncore_ccu();
+
+	socfpga_emac_init();
+
+	/* DDR and IOSSM driver init */
+	agilex5_ddr_init(&reverse_handoff_ptr);
+
+	if (combo_phy_init(&reverse_handoff_ptr) != 0) {
+		ERROR("SOCFPGA: Combo Phy initialization failed\n");
+	}
 
+	/* Enable FPGA bridges as required */
 	if (!intel_mailbox_is_fpga_not_ready()) {
 		socfpga_bridges_enable(SOC2FPGA_MASK | LWHPS2FPGA_MASK |
-					FPGA2SOC_MASK | F2SDRAM0_MASK);
+				       FPGA2SOC_MASK | F2SDRAM0_MASK);
 	}
 }
 
@@ -101,7 +145,8 @@
 	handoff reverse_handoff_ptr;
 	unsigned long offset = 0;
 
-	struct cdns_sdmmc_params params = EMMC_INIT_PARAMS((uintptr_t) &cdns_desc, get_mmc_clk());
+	struct cdns_sdmmc_params params = EMMC_INIT_PARAMS((uintptr_t) &cdns_desc,
+							   clkmgr_get_rate(CLKMGR_SDMMC_CLK_ID));
 
 	mmc_info.mmc_dev_type = MMC_DEVICE_TYPE;
 	mmc_info.ocr_voltage = OCR_3_3_3_4 | OCR_3_2_3_3;
diff --git a/plat/intel/soc/agilex5/bl31_plat_setup.c b/plat/intel/soc/agilex5/bl31_plat_setup.c
index 96c4161..c090117 100644
--- a/plat/intel/soc/agilex5/bl31_plat_setup.c
+++ b/plat/intel/soc/agilex5/bl31_plat_setup.c
@@ -58,9 +58,8 @@
 	mmio_write_64(PLAT_SEC_ENTRY, PLAT_SEC_WARM_ENTRY);
 
 	console_16550_register(PLAT_INTEL_UART_BASE, PLAT_UART_CLOCK,
-	PLAT_BAUDRATE, &console);
+			       PLAT_BAUDRATE, &console);
 
-	init_ncore_ccu();
 	setup_smmu_stream_id();
 
 	/*
@@ -191,8 +190,8 @@
 	uint32_t boot_core = 0x00;
 	uint32_t cpuid = 0x00;
 
-	cpuid = read_mpidr();
-	boot_core = (mmio_read_32(AGX5_PWRMGR(MPU_BOOTCONFIG)) & 0xC00);
+	cpuid = MPIDR_AFFLVL1_VAL(read_mpidr());
+	boot_core = ((mmio_read_32(AGX5_PWRMGR(MPU_BOOTCONFIG)) & 0xC00) >> 10);
 	NOTICE("BL31: Boot Core = %x\n", boot_core);
 	NOTICE("BL31: CPU ID = %x\n", cpuid);
 	INFO("BL31: Invalidate Data cache\n");
@@ -235,6 +234,9 @@
 	unsigned int pchctlr_new = 0x00;
 	uint32_t boot_core = 0x00;
 
+	/* Store magic number for SMP secondary cores boot */
+	mmio_write_32(L2_RESET_DONE_REG, SMP_SEC_CORE_BOOT_REQ);
+
 	boot_core = (mmio_read_32(AGX5_PWRMGR(MPU_BOOTCONFIG)) & 0xC00);
 	/* Update the p-channel based on cpu id */
 	pch_cpu = 1 << cpu_id;
diff --git a/plat/intel/soc/agilex5/include/agilex5_cache.h b/plat/intel/soc/agilex5/include/agilex5_cache.h
index 095d99e..f7801b9 100644
--- a/plat/intel/soc/agilex5/include/agilex5_cache.h
+++ b/plat/intel/soc/agilex5/include/agilex5_cache.h
@@ -8,5 +8,6 @@
 #define AGX5_CACHE_H
 
 void invalidate_dcache_all(void);
+void invalidate_cache_low_el(void);
 
 #endif /* AGX5_CACHE_H */
diff --git a/plat/intel/soc/agilex5/include/agilex5_clock_manager.h b/plat/intel/soc/agilex5/include/agilex5_clock_manager.h
index 566a80d..1165c90 100644
--- a/plat/intel/soc/agilex5/include/agilex5_clock_manager.h
+++ b/plat/intel/soc/agilex5/include/agilex5_clock_manager.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,141 +11,304 @@
 #include "socfpga_handoff.h"
 
 /* Clock Manager Registers */
-#define CLKMGR_OFFSET					0x10d10000
+#define CLKMGR_BASE				0x10D10000
+#define CLKMGR_CTRL				0x00
+#define CLKMGR_STAT				0x04
+#define CLKMGR_TESTIOCTROL			0x08
+#define CLKMGR_INTRGEN				0x0C
+#define CLKMGR_INTRMSK				0x10
+#define CLKMGR_INTRCLR				0x14
+#define CLKMGR_INTRSTS				0x18
+#define CLKMGR_INTRSTK				0x1C
+#define CLKMGR_INTRRAW				0x20
 
-#define CLKMGR_CTRL					0x0
-#define CLKMGR_STAT					0x4
-#define CLKMGR_TESTIOCTROL				0x8
-#define CLKMGR_INTRGEN					0xc
-#define CLKMGR_INTRMSK					0x10
-#define CLKMGR_INTRCLR					0x14
-#define CLKMGR_INTRSTS					0x18
-#define CLKMGR_INTRSTK					0x1c
-#define CLKMGR_INTRRAW					0x20
+/* Clock manager control related macros */
+#define CLKMGR(_reg)				(CLKMGR_BASE + (CLKMGR_##_reg))
+#define CLKMGR_STAT_MAINPLLLOCKED		BIT(8)
+#define CLKMGR_STAT_PERPLLLOCKED		BIT(16)
+
+#define CLKMGR_INTRCLR_MAINLOCKLOST		BIT(2)
+#define CLKMGR_INTRCLR_PERLOCKLOST		BIT(3)
+
+#define CLKMGR_STAT_ALLPLLLOCKED		(CLKMGR_STAT_MAINPLLLOCKED | \
+						CLKMGR_STAT_PERPLLLOCKED)
 
 /* Main PLL Group */
-#define CLKMGR_MAINPLL					0x10d10024
-#define CLKMGR_MAINPLL_EN				0x0
-#define CLKMGR_MAINPLL_ENS				0x4
-#define CLKMGR_MAINPLL_BYPASS				0xc
-#define CLKMGR_MAINPLL_BYPASSS				0x10
-#define CLKMGR_MAINPLL_BYPASSR				0x14
-#define CLKMGR_MAINPLL_NOCCLK				0x1c
-#define CLKMGR_MAINPLL_NOCDIV				0x20
-#define CLKMGR_MAINPLL_PLLGLOB				0x24
-#define CLKMGR_MAINPLL_FDBCK				0x28
-#define CLKMGR_MAINPLL_MEM				0x2c
-#define CLKMGR_MAINPLL_MEMSTAT				0x30
-#define CLKMGR_MAINPLL_VCOCALIB				0x34
-#define CLKMGR_MAINPLL_PLLC0				0x38
-#define CLKMGR_MAINPLL_PLLC1				0x3c
-#define CLKMGR_MAINPLL_PLLC2				0x40
-#define CLKMGR_MAINPLL_PLLC3				0x44
-#define CLKMGR_MAINPLL_PLLM				0x48
-#define CLKMGR_MAINPLL_FHOP				0x4c
-#define CLKMGR_MAINPLL_SSC				0x50
-#define CLKMGR_MAINPLL_LOSTLOCK				0x54
+#define CLKMGR_MAINPLL_BASE			0x10D10024
+#define CLKMGR_MAINPLL_EN			0x00
+#define CLKMGR_MAINPLL_ENS			0x04
+#define CLKMGR_MAINPLL_ENR			0x08
+#define CLKMGR_MAINPLL_BYPASS			0x0C
+#define CLKMGR_MAINPLL_BYPASSS			0x10
+#define CLKMGR_MAINPLL_BYPASSR			0x14
+#define CLKMGR_MAINPLL_NOCCLK			0x1C
+#define CLKMGR_MAINPLL_NOCDIV			0x20
+#define CLKMGR_MAINPLL_PLLGLOB			0x24
+#define CLKMGR_MAINPLL_FDBCK			0x28
+#define CLKMGR_MAINPLL_MEM			0x2C
+#define CLKMGR_MAINPLL_MEMSTAT			0x30
+#define CLKMGR_MAINPLL_VCOCALIB			0x34
+#define CLKMGR_MAINPLL_PLLC0			0x38
+#define CLKMGR_MAINPLL_PLLC1			0x3C
+#define CLKMGR_MAINPLL_PLLC2			0x40
+#define CLKMGR_MAINPLL_PLLC3			0x44
+#define CLKMGR_MAINPLL_PLLM			0x48
+#define CLKMGR_MAINPLL_FHOP			0x4C
+#define CLKMGR_MAINPLL_SSC			0x50
+#define CLKMGR_MAINPLL_LOSTLOCK			0x54
+
+#define CLKMGR_MAINPLL(_reg)			(CLKMGR_MAINPLL_BASE + \
+							(CLKMGR_MAINPLL_##_reg))
+
+#define CLKMGR_XPLL_LOSTLOCK_BYPASSCLEAR	BIT(0)
+#define CLKMGR_XPLLGLOB_CLR_LOSTLOCK_BYPASS	BIT(29)
 
 /* Peripheral PLL Group */
-#define CLKMGR_PERPLL					0x10d1007c
-#define CLKMGR_PERPLL_EN				0x0
-#define CLKMGR_PERPLL_ENS				0x4
-#define CLKMGR_PERPLL_BYPASS				0xc
-#define CLKMGR_PERPLL_EMACCTL				0x18
-#define CLKMGR_PERPLL_GPIODIV				0x1c
-#define CLKMGR_PERPLL_PLLGLOB				0x20
-#define CLKMGR_PERPLL_FDBCK				0x24
-#define CLKMGR_PERPLL_MEM				0x28
-#define CLKMGR_PERPLL_MEMSTAT				0x2c
-#define CLKMGR_PERPLL_PLLC0				0x30
-#define CLKMGR_PERPLL_PLLC1				0x34
-#define CLKMGR_PERPLL_VCOCALIB				0x38
-#define CLKMGR_PERPLL_PLLC2				0x3c
-#define CLKMGR_PERPLL_PLLC3				0x40
-#define CLKMGR_PERPLL_PLLM				0x44
-#define CLKMGR_PERPLL_LOSTLOCK				0x50
+#define CLKMGR_PERPLL_BASE			0x10D1007C
+#define CLKMGR_PERPLL_EN			0x00
+#define CLKMGR_PERPLL_ENS			0x04
+#define CLKMGR_PERPLL_ENR			0x08
+#define CLKMGR_PERPLL_BYPASS			0x0C
+#define CLKMGR_PERPLL_BYPASSS			0x10
+#define CLKMGR_PERPLL_BYPASSR			0x14
+#define CLKMGR_PERPLL_EMACCTL			0x18
+#define CLKMGR_PERPLL_GPIODIV			0x1C
+#define CLKMGR_PERPLL_PLLGLOB			0x20
+#define CLKMGR_PERPLL_FDBCK			0x24
+#define CLKMGR_PERPLL_MEM			0x28
+#define CLKMGR_PERPLL_MEMSTAT			0x2C
+#define CLKMGR_PERPLL_VCOCALIB			0x30
+#define CLKMGR_PERPLL_PLLC0			0x34
+#define CLKMGR_PERPLL_PLLC1			0x38
+#define CLKMGR_PERPLL_PLLC2			0x3C
+#define CLKMGR_PERPLL_PLLC3			0x40
+#define CLKMGR_PERPLL_PLLM			0x44
+#define CLKMGR_PERPLL_FHOP			0x48
+#define CLKMGR_PERPLL_SSC			0x4C
+#define CLKMGR_PERPLL_LOSTLOCK			0x50
+
+#define CLKMGR_PERPLL(_reg)			(CLKMGR_PERPLL_BASE + \
+							(CLKMGR_PERPLL_##_reg))
 
 /* Altera Group */
-#define CLKMGR_ALTERA					0x10d100d0
-#define CLKMGR_ALTERA_JTAG				0x0
-#define CLKMGR_ALTERA_EMACACTR				0x4
-#define CLKMGR_ALTERA_EMACBCTR				0x8
-#define CLKMGR_ALTERA_EMACPTPCTR			0xc
-#define CLKMGR_ALTERA_GPIODBCTR				0x10
-#define CLKMGR_ALTERA_S2FUSER0CTR			0x18
-#define CLKMGR_ALTERA_S2FUSER1CTR			0x1c
-#define CLKMGR_ALTERA_PSIREFCTR				0x20
-#define CLKMGR_ALTERA_EXTCNTRST				0x24
-#define CLKMGR_ALTERA_USB31CTR				0x28
-#define CLKMGR_ALTERA_DSUCTR				0x2c
-#define CLKMGR_ALTERA_CORE01CTR				0x30
-#define CLKMGR_ALTERA_CORE23CTR				0x34
-#define CLKMGR_ALTERA_CORE2CTR				0x38
-#define CLKMGR_ALTERA_CORE3CTR				0x3c
+#define CLKMGR_ALTERA_BASE			0x10D100D0
+#define CLKMGR_ALTERA_JTAG			0x00
+#define CLKMGR_ALTERA_EMACACTR			0x04
+#define CLKMGR_ALTERA_EMACBCTR			0x08
+#define CLKMGR_ALTERA_EMACPTPCTR		0x0C
+#define CLKMGR_ALTERA_GPIODBCTR			0x10
+#define CLKMGR_ALTERA_S2FUSER0CTR		0x18
+#define CLKMGR_ALTERA_S2FUSER1CTR		0x1C
+#define CLKMGR_ALTERA_PSIREFCTR			0x20
+#define CLKMGR_ALTERA_EXTCNTRST			0x24
+#define CLKMGR_ALTERA_USB31CTR			0x28
+#define CLKMGR_ALTERA_DSUCTR			0x2C
+#define CLKMGR_ALTERA_CORE01CTR			0x30
+#define CLKMGR_ALTERA_CORE23CTR			0x34
+#define CLKMGR_ALTERA_CORE2CTR			0x38
+#define CLKMGR_ALTERA_CORE3CTR			0x3C
+#define CLKMGR_ALTERA_SERIAL_CON_PLL_CTR	0x40
+
+#define CLKMGR_ALTERA(_reg)			(CLKMGR_ALTERA_BASE + \
+							(CLKMGR_ALTERA_##_reg))
 
-/* Membus */
-#define CLKMGR_MEM_REQ					BIT(24)
-#define CLKMGR_MEM_WR					BIT(25)
-#define CLKMGR_MEM_ERR					BIT(26)
-#define CLKMGR_MEM_WDAT_OFFSET				16
-#define CLKMGR_MEM_ADDR					0x4027
-#define CLKMGR_MEM_WDAT					0x80
+#define CLKMGR_ALTERA_EXTCNTRST_EMACACNTRST	BIT(0)
+#define CLKMGR_ALTERA_EXTCNTRST_EMACBCNTRST	BIT(1)
+#define CLKMGR_ALTERA_EXTCNTRST_EMACPTPCNTRST	BIT(2)
+#define CLKMGR_ALTERA_EXTCNTRST_GPIODBCNTRST	BIT(3)
+#define CLKMGR_ALTERA_EXTCNTRST_S2FUSER0CNTRST	BIT(5)
+#define CLKMGR_ALTERA_EXTCNTRST_S2FUSER1CNTRST	BIT(6)
+#define CLKMGR_ALTERA_EXTCNTRST_PSIREFCNTRST	BIT(7)
+#define CLKMGR_ALTERA_EXTCNTRST_USB31REFCNTRST	BIT(8)
+#define CLKMGR_ALTERA_EXTCNTRST_DSUCNTRST	BIT(10)
+#define CLKMGR_ALTERA_EXTCNTRST_CORE01CNTRST	BIT(11)
+#define CLKMGR_ALTERA_EXTCNTRST_CORE2CNTRST	BIT(12)
+#define CLKMGR_ALTERA_EXTCNTRST_CORE3CNTRST	BIT(13)
+
+#define CLKMGR_ALTERA_EXTCNTRST_ALLCNTRST	\
+						(CLKMGR_ALTERA_EXTCNTRST_EMACACNTRST |	\
+						CLKMGR_ALTERA_EXTCNTRST_EMACBCNTRST |	\
+						CLKMGR_ALTERA_EXTCNTRST_EMACPTPCNTRST |	\
+						CLKMGR_ALTERA_EXTCNTRST_GPIODBCNTRST |	\
+						CLKMGR_ALTERA_EXTCNTRST_S2FUSER0CNTRST |\
+						CLKMGR_ALTERA_EXTCNTRST_S2FUSER1CNTRST |\
+						CLKMGR_ALTERA_EXTCNTRST_PSIREFCNTRST |	\
+						CLKMGR_ALTERA_EXTCNTRST_USB31REFCNTRST |\
+						CLKMGR_ALTERA_EXTCNTRST_DSUCNTRST |	\
+						CLKMGR_ALTERA_EXTCNTRST_CORE01CNTRST |	\
+						CLKMGR_ALTERA_EXTCNTRST_CORE2CNTRST |	\
+						CLKMGR_ALTERA_EXTCNTRST_CORE3CNTRST)
+
+#define CLKMGR_ALTERA_CORE0			0
+#define CLKMGR_ALTERA_CORE1			1
+#define CLKMGR_ALTERA_CORE2			2
+#define CLKMGR_ALTERA_CORE3			3
+
+/* PLL membus configuration macros */
+#define CLKMGR_MEM_REQ				BIT(24)
+#define CLKMGR_MEM_WR				BIT(25)
+#define CLKMGR_MEM_ERR				BIT(26)
+#define CLKMGR_MEM_WDAT_OFFSET			16
+#define CLKMGR_MEM_ADDR_MASK			GENMASK(15, 0)
+#define CLKMGR_MEM_ADDR_START			0x00004000
+#define CLKMGR_PLLCFG_SRC_SYNC_MODE		0x27
+#define CLKMGR_PLLCFG_OVRSHOOT_FREQ_LOCK	0xB3
+#define CLKMGR_PLLCFG_LOCK_SETTLE_TIME		0xE6
+#define CLKMGR_PLLCFG_DUTYCYCLE_CLKSLICE0	0x03
+#define CLKMGR_PLLCFG_DUTYCYCLE_CLKSLICE1	0x07
 
 /* Clock Manager Macros */
-#define CLKMGR_CTRL_BOOTMODE_SET_MSK			0x00000001
-#define CLKMGR_STAT_BUSY_E_BUSY				0x1
-#define CLKMGR_STAT_BUSY(x)				(((x) & 0x00000001) >> 0)
-#define CLKMGR_STAT_MAINPLLLOCKED(x)			(((x) & 0x00000100) >> 8)
-#define CLKMGR_STAT_PERPLLLOCKED(x)			(((x) & 0x00010000) >> 16)
-#define CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK		0x00000004
-#define CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK		0x00000008
-#define CLKMGR_INTOSC_HZ				460000000
+#define CLKMGR_CTRL_BOOTMODE_SET_MSK		0x00000001
+#define CLKMGR_STAT_BUSY_E_BUSY			0x1
+#define CLKMGR_STAT_BUSY(x)			(((x) & 0x00000001) >> 0)
+#define CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK	0x00000004
+#define CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK	0x00000008
+#define CLKMGR_INTOSC_HZ			460000000
+#define CLKMGR_CTRL_BOOTMODE			BIT(0)
+#define CLKMGR_STAT_MAINPLL_LOCKED		BIT(8)
+#define CLKMGR_STAT_MAIN_TRANS			BIT(9)
+#define CLKMGR_STAT_PERPLL_LOCKED		BIT(16)
+#define CLKMGR_STAT_PERF_TRANS			BIT(17)
+#define CLKMGR_STAT_BOOTMODE			BIT(24)
+#define CLKMGR_STAT_BOOTCLKSRC			BIT(25)
 
+#define CLKMGR_STAT_ALLPLL_LOCKED_MASK		(CLKMGR_STAT_MAINPLL_LOCKED | \
+						 CLKMGR_STAT_PERPLL_LOCKED)
 /* Main PLL Macros */
-#define CLKMGR_MAINPLL_EN_RESET				0x0000005e
-#define CLKMGR_MAINPLL_ENS_RESET			0x0000005e
-
-/* Peripheral PLL Macros */
-#define CLKMGR_PERPLL_EN_RESET				0x040007FF
-#define CLKMGR_PERPLL_ENS_RESET			0x040007FF
+#define CLKMGR_MAINPLL_EN_RESET			0x0000005E
+#define CLKMGR_MAINPLL_ENS_RESET		0x0000005E
+#define CLKMGR_MAINPLL_PLLGLOB_PD_N		BIT(0)
+#define CLKMGR_MAINPLL_PLLGLOB_RST_N		BIT(1)
+#define CLKMGR_MAINPLL_PLLCX_EN			BIT(27)
+#define CLKMGR_MAINPLL_PLLCX_MUTE		BIT(28)
 
-#define CLKMGR_PERPLL_EN_SDMMCCLK			BIT(5)
-#define CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET(x)		(((x) << 0) & 0x0000ffff)
+#define CLKMGR_PERPLL_EN_SDMMCCLK		BIT(5)
+#define CLKMGR_PERPLL_GPIODIV_GPIODBCLK_SET(x)	(((x) << 0) & 0x0000FFFF)
+#define CLKMGR_PERPLL_PLLGLOB_PD_N		BIT(0)
+#define CLKMGR_PERPLL_PLLGLOB_RST_N		BIT(1)
+#define CLKMGR_PERPLL_PLLCX_EN			BIT(27)
+#define CLKMGR_PERPLL_PLLCX_MUTE		BIT(28)
 
 /* Altera Macros */
-#define CLKMGR_ALTERA_EXTCNTRST_RESET			0xff
+#define CLKMGR_ALTERA_EXTCNTRST_RESET		0xFF
 
 /* Shared Macros */
-#define CLKMGR_PSRC(x)					(((x) & 0x00030000) >> 16)
-#define CLKMGR_PSRC_MAIN				0
-#define CLKMGR_PSRC_PER					1
+#define CLKMGR_PLLGLOB_PSRC(x)			(((x) & 0x00030000) >> 16)
+#define CLKMGR_PSRC_MAIN			0
+#define CLKMGR_PSRC_PER				1
+
+#define CLKMGR_PLLGLOB_PSRC_EOSC1		0x0
+#define CLKMGR_PLLGLOB_PSRC_INTOSC		0x1
+#define CLKMGR_PLLGLOB_PSRC_F2S			0x2
+
+#define CLKMGR_PLLM_MDIV(x)			((x) & 0x000003FF)
+#define CLKMGR_PLLGLOB_PD_SET_MSK		0x00000001
+#define CLKMGR_PLLGLOB_RST_SET_MSK		0x00000002
+
+#define CLKMGR_PLLGLOB_REFCLKDIV(x)		(((x) & 0x00003F00) >> 8)
+#define CLKMGR_PLLGLOB_AREFCLKDIV(x)		(((x) & 0x00000F00) >> 8)
+#define CLKMGR_PLLGLOB_DREFCLKDIV(x)		(((x) & 0x00003000) >> 12)
 
-#define CLKMGR_PLLGLOB_PSRC_EOSC1			0x0
-#define CLKMGR_PLLGLOB_PSRC_INTOSC			0x1
-#define CLKMGR_PLLGLOB_PSRC_F2S				0x2
+#define CLKMGR_VCOCALIB_HSCNT_SET(x)		(((x) << 0) & 0x000003FF)
+#define CLKMGR_VCOCALIB_MSCNT_SET(x)		(((x) << 16) & 0x00FF0000)
 
-#define CLKMGR_PLLM_MDIV(x)				((x) & 0x000003ff)
-#define CLKMGR_PLLGLOB_PD_SET_MSK			0x00000001
-#define CLKMGR_PLLGLOB_RST_SET_MSK			0x00000002
+#define CLKMGR_CLR_LOSTLOCK_BYPASS		0x20000000
 
-#define CLKMGR_PLLGLOB_REFCLKDIV(x)			(((x) & 0x00003f00) >> 8)
-#define CLKMGR_PLLGLOB_AREFCLKDIV(x)			(((x) & 0x00000f00) >> 8)
-#define CLKMGR_PLLGLOB_DREFCLKDIV(x)			(((x) & 0x00003000) >> 12)
+#define CLKMGR_CLKSRC_MASK			GENMASK(18, 16)
+#define CLKMGR_CLKSRC_OFFSET			16
+#define CLKMGR_CLKSRC_MAIN			0
+#define CLKMGR_CLKSRC_PER			1
+#define CLKMGR_CLKSRC_OSC1			2
+#define CLKMGR_CLKSRC_INTOSC			3
+#define CLKMGR_CLKSRC_FPGA			4
+#define CLKMGR_PLLCX_DIV_MSK			GENMASK(10, 0)
 
-#define CLKMGR_VCOCALIB_HSCNT_SET(x)			(((x) << 0) & 0x000003ff)
-#define CLKMGR_VCOCALIB_MSCNT_SET(x)			(((x) << 16) & 0x00ff0000)
+#define GET_CLKMGR_CLKSRC(x)			(((x) & CLKMGR_CLKSRC_MASK) >> \
+							CLKMGR_CLKSRC_OFFSET)
 
-#define CLKMGR_CLR_LOSTLOCK_BYPASS			0x20000000
+#define CLKMGR_MAINPLL_NOCDIV_L4MP_MASK		GENMASK(5, 4)
+#define CLKMGR_MAINPLL_NOCDIV_L4MP_OFFSET	4
+#define GET_CLKMGR_MAINPLL_NOCDIV_L4MP(x)	(((x) & CLKMGR_MAINPLL_NOCDIV_L4MP_MASK) >> \
+						CLKMGR_MAINPLL_NOCDIV_L4MP_OFFSET)
 
-typedef struct {
-	uint32_t  clk_freq_of_eosc1;
-	uint32_t  clk_freq_of_f2h_free;
-	uint32_t  clk_freq_of_cb_intosc_ls;
-} CLOCK_SOURCE_CONFIG;
+#define CLKMGR_MAINPLL_NOCDIV_L4SP_MASK		GENMASK(7, 6)
+#define CLKMGR_MAINPLL_NOCDIV_L4SP_OFFSET	6
+#define GET_CLKMGR_MAINPLL_NOCDIV_L4SP(x)	(((x) & CLKMGR_MAINPLL_NOCDIV_L4SP_MASK) >> \
+						CLKMGR_MAINPLL_NOCDIV_L4SP_OFFSET)
+
+#define CLKMGR_MAINPLL_NOCDIV_SPHY_MASK		GENMASK(17, 16)
+#define CLKMGR_MAINPLL_NOCDIV_SPHY_OFFSET	16
+#define GET_CLKMGR_MAINPLL_NOCDIV_SPHY(x)	(((x) & CLKMGR_MAINPLL_NOCDIV_SPHY_MASK) >> \
+						CLKMGR_MAINPLL_NOCDIV_SPHY_OFFSET)
+
+
+#define CLKMGR_MAINPLL_NOCDIV_L4SYSFREE_MASK	GENMASK(3, 2)
+#define CLKMGR_MAINPLL_NOCDIV_L4SYSFREE_OFFSET	2
+#define GET_CLKMGR_MAINPLL_NOCDIV_L4SYSFREE(x)	(((x) & CLKMGR_MAINPLL_NOCDIV_L4SYSFREE_MASK) >> \
+						CLKMGR_MAINPLL_NOCDIV_L4SYSFREE_OFFSET)
+
+#define CLKMGR_PERPLL_EMAC0_CLK_SRC_MASK	BIT(26)
+#define CLKMGR_PERPLL_EMAC0_CLK_SRC_OFFSET	26
+#define GET_CLKMGR_PERPLL_EMAC0_CLK_SRC(x)	(((x) & CLKMGR_PERPLL_EMAC0_CLK_SRC_MASK) >> \
+						CLKMGR_PERPLL_EMAC0_CLK_SRC_OFFSET)
+
+#define CLKMGR_ALTERA_EMACACTR_CLK_SRC_MASK	GENMASK(18, 16)
+#define CLKMGR_ALTERA_EMACACTR_CLK_SRC_OFFSET	16
+#define GET_CLKMGR_EMACACTR_CLK_SRC(x)		(((x) & CLKMGR_ALTERA_EMACACTR_CLK_SRC_MASK) >> \
+						CLKMGR_ALTERA_EMACACTR_CLK_SRC_OFFSET)
+
+#define CLKMGR_MPU_CLK_ID			0
+#define CLKMGR_MPU_PERIPH_CLK_ID		1
+#define CLKMGR_L4_MAIN_CLK_ID			2
+#define CLKMGR_L4_MP_CLK_ID			3
+#define CLKMGR_L4_SP_CLK_ID			4
+#define CLKMGR_WDT_CLK_ID			5
+#define CLKMGR_UART_CLK_ID			6
+#define CLKMGR_EMAC0_CLK_ID			7
+#define CLKMGR_EMAC1_CLK_ID			8
+#define CLKMGR_EMAC2_CLK_ID			9
+#define CLKMGR_EMAC_PTP_CLK_ID			10
+#define CLKMGR_SDMMC_CLK_ID			11
+
+#define CLKMGR_MAINPLL_BYPASS_ALL		(0xF6)
+#define CLKMGR_PERPLL_BYPASS_ALL		(0xEF)
+#define CLKMGR_PLLCX_STAT			BIT(29)
+#define GET_PLLCX_STAT(x)			((x) & CLKMGR_PLLCX_STAT)
+
+#define CLKMGR_MAINPLL_TYPE			(0)
+#define CLKMGR_PERPLL_TYPE			(1)
+
+#define CLKMGR_MAX_RETRY_COUNT			1000
+
+#define CLKMGR_PLLM_MDIV_MASK			GENMASK(9, 0)
+#define CLKMGR_PLLGLOB_PD_MASK			BIT(0)
+#define CLKMGR_PLLGLOB_RST_MASK			BIT(1)
+#define CLKMGR_PLLGLOB_AREFCLKDIV_MASK		GENMASK(11, 8)
+#define CLKMGR_PLLGLOB_DREFCLKDIV_MASK		GENMASK(13, 12)
+#define CLKMGR_PLLGLOB_REFCLKDIV_MASK		GENMASK(13, 8)
+#define CLKMGR_PLLGLOB_MODCLKDIV_MASK		GENMASK(24, 27)
+#define CLKMGR_PLLGLOB_AREFCLKDIV_OFFSET	8
+#define CLKMGR_PLLGLOB_DREFCLKDIV_OFFSET	12
+#define CLKMGR_PLLGLOB_REFCLKDIV_OFFSET		8
+#define CLKMGR_PLLGLOB_MODCLKDIV_OFFSET		24
+#define CLKMGR_PLLGLOB_VCO_PSRC_MASK		GENMASK(17, 16)
+#define CLKMGR_PLLGLOB_VCO_PSRC_OFFSET		16
+#define CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK	BIT(29)
+
+#define CLKMGR_VCOCALIB_MSCNT_MASK		GENMASK(23, 16)
+#define CLKMGR_VCOCALIB_MSCNT_OFFSET		16
+#define CLKMGR_VCOCALIB_HSCNT_MASK		GENMASK(9, 0)
+#define CLKMGR_VCOCALIB_MSCNT_CONST		100
+#define CLKMGR_VCOCALIB_HSCNT_CONST		4
+
+int config_clkmgr_handoff(handoff *hoff_ptr);
+uint32_t clkmgr_get_rate(uint32_t clk_id);
 
-void config_clkmgr_handoff(handoff *hoff_ptr);
-uint32_t get_wdt_clk(void);
-uint32_t get_uart_clk(void);
-uint32_t get_mmc_clk(void);
+/* PLL configuration data structure in power-down state */
+typedef struct pll_cfg {
+	uint32_t addr;
+	uint32_t data;
+	uint32_t mask;
+} pll_cfg_t;
 
 #endif
diff --git a/plat/intel/soc/agilex5/include/agilex5_ddr.h b/plat/intel/soc/agilex5/include/agilex5_ddr.h
new file mode 100644
index 0000000..631e006
--- /dev/null
+++ b/plat/intel/soc/agilex5/include/agilex5_ddr.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef AGILEX5_DDR_H
+#define AGILEX5_DDR_H
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <lib/utils_def.h>
+
+#include "socfpga_handoff.h"
+
+#define CONFIG_NR_DRAM_BANKS	1
+
+typedef unsigned long long phys_addr_t;
+typedef unsigned long long phys_size_t;
+typedef phys_addr_t fdt_addr_t;
+
+/* DDR/RAM configuration */
+struct ddr_info {
+	phys_addr_t start;
+	phys_size_t size;
+};
+
+int agilex5_ddr_init(handoff *hoff_ptr);
+
+#endif /* AGILEX5_DDR_H */
diff --git a/plat/intel/soc/agilex5/include/agilex5_iossm_mailbox.h b/plat/intel/soc/agilex5/include/agilex5_iossm_mailbox.h
new file mode 100644
index 0000000..1fd8ef6
--- /dev/null
+++ b/plat/intel/soc/agilex5/include/agilex5_iossm_mailbox.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef AGILEX5_IOSSM_MAILBOX_H
+#define AGILEX5_IOSSM_MAILBOX_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "lib/mmio.h"
+#include "agilex5_ddr.h"
+
+#define TIMEOUT_5000MS					5000
+#define TIMEOUT						TIMEOUT_5000MS
+#define IOSSM_STATUS_CAL_SUCCESS			BIT(0)
+#define IOSSM_STATUS_CAL_FAIL				BIT(1)
+#define IOSSM_STATUS_CAL_BUSY				BIT(2)
+#define IOSSM_STATUS_COMMAND_RESPONSE_READY		1
+#define IOSSM_CMD_RESPONSE_STATUS_OFFSET		0x45C
+#define IOSSM_CMD_RESPONSE_DATA_0_OFFSET		0x458
+#define IOSSM_CMD_RESPONSE_DATA_1_OFFSET		0x454
+#define IOSSM_CMD_RESPONSE_DATA_2_OFFSET		0x450
+#define IOSSM_CMD_REQ_OFFSET				0x43C
+#define IOSSM_CMD_PARAM_0_OFFSET			0x438
+#define IOSSM_CMD_PARAM_1_OFFSET			0x434
+#define IOSSM_CMD_PARAM_2_OFFSET			0x430
+#define IOSSM_CMD_PARAM_3_OFFSET			0x42C
+#define IOSSM_CMD_PARAM_4_OFFSET			0x428
+#define IOSSM_CMD_PARAM_5_OFFSET			0x424
+#define IOSSM_CMD_PARAM_6_OFFSET			0x420
+#define IOSSM_STATUS_OFFSET				0x400
+#define IOSSM_CMD_RESPONSE_DATA_SHORT_MASK		GENMASK(31, 16)
+#define IOSSM_CMD_RESPONSE_DATA_SHORT(data)		(((data) & \
+							IOSSM_CMD_RESPONSE_DATA_SHORT_MASK) >> 16)
+#define MAX_IO96B_SUPPORTED				2
+#define MAX_MEM_INTERFACES_SUPPORTED			2
+
+/* supported mailbox command type */
+enum iossm_mailbox_cmd_type  {
+	CMD_NOP,
+	CMD_GET_SYS_INFO,
+	CMD_GET_MEM_INFO,
+	CMD_GET_MEM_CAL_INFO,
+	CMD_TRIG_CONTROLLER_OP,
+	CMD_TRIG_MEM_CAL_OP
+};
+
+/* supported mailbox command opcode */
+enum iossm_mailbox_cmd_opcode  {
+	GET_MEM_INTF_INFO = 0x0001,
+	GET_MEM_TECHNOLOGY,
+	GET_MEMCLK_FREQ_KHZ,
+	GET_MEM_WIDTH_INFO,
+	ECC_ENABLE_SET = 0x0101,
+	ECC_ENABLE_STATUS,
+	ECC_INTERRUPT_STATUS,
+	ECC_INTERRUPT_ACK,
+	ECC_INTERRUPT_MASK,
+	ECC_WRITEBACK_ENABLE,
+	ECC_SCRUB_IN_PROGRESS_STATUS = 0x0201,
+	ECC_SCRUB_MODE_0_START,
+	ECC_SCRUB_MODE_1_START,
+	BIST_STANDARD_MODE_START = 0x0301,
+	BIST_RESULTS_STATUS,
+	BIST_MEM_INIT_START,
+	BIST_MEM_INIT_STATUS,
+	BIST_SET_DATA_PATTERN_UPPER,
+	BIST_SET_DATA_PATTERN_LOWER,
+	TRIG_MEM_CAL = 0x000a,
+	GET_MEM_CAL_STATUS
+};
+
+/*
+ * IOSSM mailbox required information
+ *
+ * @num_mem_interface:	Number of memory interfaces instantiated
+ * @ip_type:		IP type implemented on the IO96B
+ * @ip_instance_id:	IP identifier for every IP instance implemented on the IO96B
+ */
+struct io96b_mb_ctrl {
+	uint32_t num_mem_interface;
+	uint32_t ip_type[2];
+	uint32_t ip_instance_id[2];
+};
+
+/*
+ * IOSSM mailbox response outputs
+ *
+ * @cmd_resp_status: Command Interface status
+ * @cmd_resp_data_*: More spaces for command response
+ */
+struct io96b_mb_resp {
+	uint32_t cmd_resp_status;
+	uint32_t cmd_resp_data_0;
+	uint32_t cmd_resp_data_1;
+	uint32_t cmd_resp_data_2;
+};
+
+/*
+ * IO96B instance specific information
+ *
+ * @size:		Memory size
+ * @io96b_csr_addr:	IO96B instance CSR address
+ * @cal_status:		IO96B instance calibration status
+ * @mb_ctrl:		IOSSM mailbox required information
+ */
+struct io96b_instance {
+	uint16_t size;
+	phys_addr_t io96b_csr_addr;
+	bool cal_status;
+	struct io96b_mb_ctrl mb_ctrl;
+};
+
+/*
+ * Overall IO96B instance(s) information
+ *
+ * @num_instance:	Number of instance(s) assigned to HPS
+ * @overall_cal_status: Overall calibration status for all IO96B instance(s)
+ * @ddr_type:		DDR memory type
+ * @ecc_status:		ECC enable status (false = disabled, true = enabled)
+ * @overall_size:	Total DDR memory size
+ * @io96b_0:		IO96B 0 instance specific information
+ * @io96b_1:		IO96B 1 instance specific information
+ */
+struct io96b_info {
+	uint8_t num_instance;
+	bool overall_cal_status;
+	const char *ddr_type;
+	bool ecc_status;
+	uint16_t overall_size;
+	struct io96b_instance io96b_0;
+	struct io96b_instance io96b_1;
+};
+
+int io96b_mb_req(phys_addr_t io96b_csr_addr, uint32_t ip_type, uint32_t instance_id,
+		 uint32_t usr_cmd_type, uint32_t usr_cmd_opcode, uint32_t cmd_param_0,
+		 uint32_t cmd_param_1, uint32_t cmd_param_2, uint32_t cmd_param_3,
+		 uint32_t cmd_param_4, uint32_t cmd_param_5, uint32_t cmd_param_6,
+		 uint32_t resp_data_len, struct io96b_mb_resp *resp);
+
+/* Supported IOSSM mailbox function */
+void io96b_mb_init(struct io96b_info *io96b_ctrl);
+int io96b_cal_status(phys_addr_t addr);
+void init_mem_cal(struct io96b_info *io96b_ctrl);
+int trig_mem_cal(struct io96b_info *io96b_ctrl);
+int get_mem_technology(struct io96b_info *io96b_ctrl);
+int get_mem_width_info(struct io96b_info *io96b_ctrl);
+int ecc_enable_status(struct io96b_info *io96b_ctrl);
+int bist_mem_init_start(struct io96b_info *io96b_ctrl);
+
+#endif /* AGILEX5_IOSSM_MAILBOX_H */
diff --git a/plat/intel/soc/agilex5/include/agilex5_pinmux.h b/plat/intel/soc/agilex5/include/agilex5_pinmux.h
index 8a8e8c7..78d19af 100644
--- a/plat/intel/soc/agilex5/include/agilex5_pinmux.h
+++ b/plat/intel/soc/agilex5/include/agilex5_pinmux.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,19 +8,13 @@
 #ifndef AGX5_PINMUX_H
 #define AGX5_PINMUX_H
 
-/* PINMUX REGISTER ADDRESS */
-#define AGX5_PINMUX_PIN0SEL					0x10d13000
-#define AGX5_PINMUX_IO0CTRL					0x10d13130
-#define AGX5_PINMUX_EMAC0_USEFPGA				0x10d13300
-#define AGX5_PINMUX_IO0_DELAY					0x10d13400
-#define AGX5_PERIPHERAL						0x10d14044
-
 #include "socfpga_handoff.h"
 
-/* PINMUX DEFINE */
-#define PINMUX_HANDOFF_ARRAY_SIZE(x)				(sizeof(x) / sizeof((x)[0]))
-#define PINMUX_HANDOFF_CONFIG_ADDR				0xbeec
-#define PINMUX_HANDOFF_CONFIG_VAL				0x7e000
+/* PINMUX REGISTER ADDRESS */
+#define AGX5_PINMUX_PIN0SEL					0x10D13000
+#define AGX5_PINMUX_IO0CTRL					0x10D13130
+#define AGX5_PINMUX_EMAC0_USEFPGA				0x10D13300
+#define AGX5_PINMUX_IO0_DELAY					0x10D13400
 
 /* Macros */
 #define SOCFPGA_PINMUX_SEL_NAND					(0x03)
@@ -142,6 +137,9 @@
 #define SOCFPGA_PINMUX_JTAG_USEFPGA				(0x50)
 #define SOCFPGA_PINMUX_SDMMC_USEFPGA				(0x54)
 
+#define SOCFPGA_PINUMX_USEFPGA(_reg)				(AGX5_PINMUX_EMAC0_USEFPGA \
+								+ SOCFPGA_PINMUX_##_reg)
+
 #define SOCFPGA_PINMUX_IO0DELAY					(0x00)
 #define SOCFPGA_PINMUX_IO1DELAY					(0x04)
 #define SOCFPGA_PINMUX_IO2DELAY					(0x08)
@@ -198,5 +196,4 @@
 								+ (SOCFPGA_PINMUX_##_reg))
 
 void config_pinmux(handoff *handoff);
-void config_peripheral(handoff *handoff);
 #endif
diff --git a/plat/intel/soc/agilex5/include/agilex5_power_manager.h b/plat/intel/soc/agilex5/include/agilex5_power_manager.h
index 1bba74b..178fd5b 100644
--- a/plat/intel/soc/agilex5/include/agilex5_power_manager.h
+++ b/plat/intel/soc/agilex5/include/agilex5_power_manager.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2022-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -77,7 +78,5 @@
 #define AGX5_PWRMGR_PSS_STAT_BUSY_E_BUSY			0x0
 #define AGX5_PWRMGR_PSS_STAT_BUSY(x)				(((x) & 0x000000FF) >> 0)
 
-int pss_sram_power_off(handoff *hoff_ptr);
-int wait_verify_fsm(uint16_t timeout, uint32_t peripheral_handoff);
-
+void config_pwrmgr_handoff(handoff *hoff_ptr);
 #endif
diff --git a/plat/intel/soc/agilex5/include/agilex5_system_manager.h b/plat/intel/soc/agilex5/include/agilex5_system_manager.h
index 53dcd13..f61c479 100644
--- a/plat/intel/soc/agilex5/include/agilex5_system_manager.h
+++ b/plat/intel/soc/agilex5/include/agilex5_system_manager.h
@@ -25,6 +25,7 @@
 #define SOCFPGA_SYSMGR_TSN_0_ACE					0x50
 #define SOCFPGA_SYSMGR_TSN_1_ACE					0x54
 #define SOCFPGA_SYSMGR_TSN_2_ACE					0x58
+#define SOCFPGA_SYSMGR_FPGA_BRIDGE_CTRL				0x5C
 #define SOCFPGA_SYSMGR_FPGAINTF_EN_1					0x68
 #define SOCFPGA_SYSMGR_FPGAINTF_EN_2					0x6C
 #define SOCFPGA_SYSMGR_FPGAINTF_EN_3					0x70
@@ -122,7 +123,7 @@
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_8				0x220
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_9				0x224
 #define SOCFPGA_SYSMGR_MPFE_CONFIG					0x228
-#define SOCFPGA_SYSMGR_MPFE_status					0x22C
+#define SOCFPGA_SYSMGR_MPFE_STATUS					0x22C
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_WARM_0				0x230
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_WARM_1				0x234
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_WARM_2				0x238
@@ -189,6 +190,8 @@
 #define SYSMGR_SDMMC_SMPLSEL(x)						(((x) & 0x7) << 4)
 
 #define SYSMGR_F2S_BRIDGE_CTRL_EN					BIT(0)
+#define SYSMGR_SOC_BRIDGE_CTRL_EN					BIT(0)
+#define SYSMGR_LWSOC_BRIDGE_CTRL_EN					BIT(1)
 #define IDLE_DATA_LWSOC2FPGA						BIT(4)
 #define IDLE_DATA_SOC2FPGA						BIT(0)
 #define IDLE_DATA_MASK							(IDLE_DATA_LWSOC2FPGA \
diff --git a/plat/intel/soc/agilex5/include/socfpga_plat_def.h b/plat/intel/soc/agilex5/include/socfpga_plat_def.h
index 9bfc304..3a0aea1 100644
--- a/plat/intel/soc/agilex5/include/socfpga_plat_def.h
+++ b/plat/intel/soc/agilex5/include/socfpga_plat_def.h
@@ -11,11 +11,16 @@
 
 #include "agilex5_memory_controller.h"
 #include "agilex5_system_manager.h"
+
 #include <platform_def.h>
 
 /* Platform Setting */
 #define PLATFORM_MODEL						PLAT_SOCFPGA_AGILEX5
 #define BOOT_SOURCE						BOOT_SOURCE_SDMMC
+/* 1 = Flush cache, 0 = No cache flush.
+ * Default for Agilex5 is Cache flush.
+ */
+#define CACHE_FLUSH							1
 #define MMC_DEVICE_TYPE						1  /* MMC = 0, SD = 1 */
 #define XLAT_TABLES_V2						U(1)
 #define PLAT_PRIMARY_CPU_A55					0x000
@@ -23,22 +28,31 @@
 #define PLAT_CLUSTER_ID_MPIDR_AFF_SHIFT				MPIDR_AFF2_SHIFT
 #define PLAT_CPU_ID_MPIDR_AFF_SHIFT				MPIDR_AFF1_SHIFT
 #define PLAT_L2_RESET_REQ					0xB007C0DE
+#define PLAT_HANDOFF_OFFSET					0x0007F000
+#define PLAT_TIMER_BASE_ADDR					0x10D01000
 
 /* System Counter */
 /* TODO: Update back to 400MHz.
  * This shall be updated to read from L4 clock instead of hardcoded.
  */
-#define PLAT_SYS_COUNTER_FREQ_IN_TICKS				(400000000)
-#define PLAT_SYS_COUNTER_FREQ_IN_MHZ				(400)
+#define PLAT_SYS_COUNTER_FREQ_IN_TICKS				U(400000000)
+#define PLAT_SYS_COUNTER_FREQ_IN_MHZ				U(400)
 
 /* FPGA config helpers */
 #define INTEL_SIP_SMC_FPGA_CONFIG_ADDR				0x80400000
-#define INTEL_SIP_SMC_FPGA_CONFIG_SIZE				0x2000000
+#define INTEL_SIP_SMC_FPGA_CONFIG_SIZE				0x82000000
 
 /* QSPI Setting */
 #define CAD_QSPIDATA_OFST					0x10900000
 #define CAD_QSPI_OFFSET						0x108d2000
 
+/* SDMMC Setting */
+# if ARM_LINUX_KERNEL_AS_BL33
+#define SOCFPGA_MMC_BLOCK_SIZE					U(32768)
+# else
+#define SOCFPGA_MMC_BLOCK_SIZE					U(8192)
+# endif
+
 /* Register Mapping */
 #define SOCFPGA_CCU_NOC_REG_BASE				0x1c000000
 #define SOCFPGA_F2SDRAMMGR_REG_BASE				0x18001000
@@ -88,11 +102,10 @@
 #define GIC_SIZE						(0x00100000)
 
 #define BL2_BASE						(0x00000000)
-#define BL2_LIMIT						(0x0002b000)
+#define BL2_LIMIT						(0x0007E000)
 
 #define BL31_BASE						(0x80000000)
 #define BL31_LIMIT						(0x82000000)
-
 /*******************************************************************************
  * UART related constants
  ******************************************************************************/
diff --git a/plat/intel/soc/agilex5/platform.mk b/plat/intel/soc/agilex5/platform.mk
index 90678e1..4bb90d5 100644
--- a/plat/intel/soc/agilex5/platform.mk
+++ b/plat/intel/soc/agilex5/platform.mk
@@ -58,14 +58,16 @@
 		lib/cpus/aarch64/cortex_a76.S				\
 		plat/intel/soc/agilex5/soc/agilex5_clock_manager.c	\
 		plat/intel/soc/agilex5/soc/agilex5_memory_controller.c	\
-		plat/intel/soc/agilex5/soc/agilex5_mmc.c			\
+		plat/intel/soc/agilex5/soc/agilex5_mmc.c		\
 		plat/intel/soc/agilex5/soc/agilex5_pinmux.c		\
 		plat/intel/soc/agilex5/soc/agilex5_power_manager.c	\
+		plat/intel/soc/agilex5/soc/agilex5_ddr.c		\
+		plat/intel/soc/agilex5/soc/agilex5_iossm_mailbox.c	\
 		plat/intel/soc/common/bl2_plat_mem_params_desc.c	\
 		plat/intel/soc/common/socfpga_image_load.c		\
 		plat/intel/soc/common/socfpga_ros.c			\
 		plat/intel/soc/common/socfpga_storage.c			\
-		plat/intel/soc/common/socfpga_vab.c				\
+		plat/intel/soc/common/socfpga_vab.c			\
 		plat/intel/soc/common/soc/socfpga_emac.c		\
 		plat/intel/soc/common/soc/socfpga_firewall.c		\
 		plat/intel/soc/common/soc/socfpga_handoff.c		\
diff --git a/plat/intel/soc/agilex5/soc/agilex5_cache.S b/plat/intel/soc/agilex5/soc/agilex5_cache.S
index a174386..52ed5d3 100644
--- a/plat/intel/soc/agilex5/soc/agilex5_cache.S
+++ b/plat/intel/soc/agilex5/soc/agilex5_cache.S
@@ -9,6 +9,21 @@
 #include <plat_macros.S>
 
 	.globl invalidate_dcache_all
+	.globl invalidate_cache_low_el
+	/* --------------------------------------------------------
+	 * Invalidate for NS EL2 and EL1
+	 * --------------------------------------------------------
+	 */
+func invalidate_cache_low_el
+	mrs	x0,SCR_EL3
+	orr	x1,x0,#SCR_NS_BIT
+	msr	SCR_EL3, x1
+	isb
+	tlbi	ALLE2
+	dsb	sy
+	tlbi	ALLE1
+	dsb	sy
+endfunc invalidate_cache_low_el
 
 .pushsection .text.asm_dcache_level, "ax"
 func asm_dcache_level
diff --git a/plat/intel/soc/agilex5/soc/agilex5_clock_manager.c b/plat/intel/soc/agilex5/soc/agilex5_clock_manager.c
index fdf1a82..603aaf8 100644
--- a/plat/intel/soc/agilex5/soc/agilex5_clock_manager.c
+++ b/plat/intel/soc/agilex5/soc/agilex5_clock_manager.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,244 +14,639 @@
 
 #include "agilex5_clock_manager.h"
 #include "agilex5_system_manager.h"
-#include "socfpga_handoff.h"
 #include "socfpga_system_manager.h"
 
-uint32_t wait_pll_lock(void)
+/* Main and Peripheral PLL configurations in Power Down(PD) state. */
+static const pll_cfg_t pll_cfg_set[] = {
+	{
+		/* Enable source synchronous mode */
+		CLKMGR_PLLCFG_SRC_SYNC_MODE,
+		BIT(7),
+		BIT(7)
+	},
+	{
+		/* Limit the PLL overshoot frequency during lock */
+		CLKMGR_PLLCFG_OVRSHOOT_FREQ_LOCK,
+		BIT(0),
+		BIT(0)
+	},
+	{
+		/* To give the PLL more time to settle before lock is asserted */
+		CLKMGR_PLLCFG_LOCK_SETTLE_TIME,
+		BIT(0),
+		BIT(0)
+	},
+	{
+		/* To set the PLL centering duty cycle for clock slice 0 */
+		CLKMGR_PLLCFG_DUTYCYCLE_CLKSLICE0,
+		0x4A,
+		GENMASK(6, 0)
+	},
+	{
+		/* To set the PLL centering duty cycle for clock slice 1 */
+		CLKMGR_PLLCFG_DUTYCYCLE_CLKSLICE1,
+		0x4A,
+		GENMASK(6, 0)
+	},
+};
+
+static int wait_pll_lock(uint32_t mask)
 {
 	uint32_t data;
 	uint32_t count = 0;
+	uint32_t retry = 0U;
 
 	do {
-		data = mmio_read_32(CLKMGR_OFFSET + CLKMGR_STAT);
-		count++;
-		if (count >= 1000)
+		/* return time out */
+		if (count >= CLKMGR_MAX_RETRY_COUNT) {
+			ERROR("CLKMGR: Timed out to satisfy the PLL mask\n");
 			return -ETIMEDOUT;
+		}
+
+		data = mmio_read_32(CLKMGR(STAT)) & mask;
+		/* wait for stable lock, make sure it is stable for these counts */
+		if (data == mask) {
+			retry++;
+		} else {
+			retry = 0U;
+		}
+
+		/* we are good now, break */
+		if (retry >= 5U) {
+			break;
+		}
+
+		count++;
+	} while (1);
 
-	} while ((CLKMGR_STAT_MAINPLLLOCKED(data) == 0) ||
-			(CLKMGR_STAT_PERPLLLOCKED(data) == 0));
 	return 0;
 }
 
-uint32_t wait_fsm(void)
+static int wait_fsm(void)
 {
 	uint32_t data;
 	uint32_t count = 0;
 
 	do {
-		data = mmio_read_32(CLKMGR_OFFSET + CLKMGR_STAT);
+		data = mmio_read_32(CLKMGR(STAT));
 		count++;
-		if (count >= 1000)
+		if (count >= CLKMGR_MAX_RETRY_COUNT) {
+			ERROR("CLKMGR: Timed out on fsm state\n");
 			return -ETIMEDOUT;
-
+		}
 	} while (CLKMGR_STAT_BUSY(data) == CLKMGR_STAT_BUSY_E_BUSY);
 
 	return 0;
 }
 
-uint32_t pll_source_sync_config(uint32_t pll_mem_offset, uint32_t data)
+static uint32_t calc_pll_vcocalibration(uint32_t pllm, uint32_t pllglob)
 {
-	uint32_t val = 0;
-	uint32_t count = 0;
-	uint32_t req_status = 0;
+	uint32_t mdiv, refclkdiv, drefclkdiv, mscnt, hscnt, vcocalib;
 
-	val = (CLKMGR_MEM_WR | CLKMGR_MEM_REQ |
-		(data << CLKMGR_MEM_WDAT_OFFSET) | CLKMGR_MEM_ADDR);
-	mmio_write_32(pll_mem_offset, val);
+	mdiv = pllm & CLKMGR_PLLM_MDIV_MASK;
+	drefclkdiv = ((pllglob & CLKMGR_PLLGLOB_DREFCLKDIV_MASK) >>
+			CLKMGR_PLLGLOB_DREFCLKDIV_OFFSET);
+	refclkdiv = ((pllglob & CLKMGR_PLLGLOB_REFCLKDIV_MASK) >>
+			CLKMGR_PLLGLOB_REFCLKDIV_OFFSET);
+	mscnt = CLKMGR_VCOCALIB_MSCNT_CONST / (mdiv * BIT(drefclkdiv));
+	if (mscnt == 0) {
+		mscnt = 1;
+	}
 
-	do {
-		req_status = mmio_read_32(pll_mem_offset);
+	hscnt = (mdiv * mscnt * BIT(drefclkdiv) / refclkdiv) -
+		CLKMGR_VCOCALIB_HSCNT_CONST;
+
+	vcocalib = (hscnt & CLKMGR_VCOCALIB_HSCNT_MASK) |
+			((mscnt << CLKMGR_VCOCALIB_MSCNT_OFFSET) &
+			CLKMGR_VCOCALIB_MSCNT_MASK);
+
+	return vcocalib;
+}
+
+static int pll_source_sync_wait(uint32_t pll_type, int retry_count)
+{
+	int count = 0;
+	uint32_t req_status;
+
+	if ((pll_type == CLKMGR_MAINPLL_TYPE) != 0) {
+		req_status = mmio_read_32(CLKMGR_MAINPLL(MEM));
+	} else {
+		req_status = mmio_read_32(CLKMGR_PERPLL(MEM));
+	}
+
+	/* Check for error bit set */
+	if ((req_status & CLKMGR_MEM_ERR) != 0) {
+		INFO("CLKMGR: %s: Memory Error Status Signal Assert\n", __func__);
+	}
+
+	while ((count < retry_count) && (req_status & CLKMGR_MEM_REQ)) {
+		if (pll_type == CLKMGR_MAINPLL_TYPE)
+			req_status = mmio_read_32(CLKMGR_MAINPLL(MEM));
+		else
+			req_status = mmio_read_32(CLKMGR_PERPLL(MEM));
 		count++;
-	} while ((req_status & CLKMGR_MEM_REQ) && (count < 10));
+	}
 
-	if (count >= 10)
+	if (count >= retry_count) {
+		ERROR("CLKMGR: %s: timeout with pll_type %d\n", __func__, pll_type);
 		return -ETIMEDOUT;
+	}
 
 	return 0;
 }
 
-uint32_t pll_source_sync_read(uint32_t pll_mem_offset)
+static int pll_source_sync_config(uint32_t pll_type, uint32_t addr_offset,
+				  uint32_t wdat, int retry_count)
 {
-	uint32_t val = 0;
-	uint32_t rdata = 0;
-	uint32_t count = 0;
-	uint32_t req_status = 0;
+	uint32_t addr;
+	uint32_t val;
 
-	val = (CLKMGR_MEM_REQ | CLKMGR_MEM_ADDR);
-	mmio_write_32(pll_mem_offset, val);
+	addr = ((addr_offset | CLKMGR_MEM_ADDR_START) & CLKMGR_MEM_ADDR_MASK);
+	val = (CLKMGR_MEM_REQ | CLKMGR_MEM_WR |
+		(wdat << CLKMGR_MEM_WDAT_OFFSET) | addr);
 
-	do {
-		req_status = mmio_read_32(pll_mem_offset);
-		count++;
-	} while ((req_status & CLKMGR_MEM_REQ) && (count < 10));
+	if ((pll_type == CLKMGR_MAINPLL_TYPE) != 0) {
+		mmio_write_32(CLKMGR_MAINPLL(MEM), val);
+	} else {
+		mmio_write_32(CLKMGR_PERPLL(MEM), val);
+	}
+
+	return pll_source_sync_wait(pll_type, retry_count);
+}
 
-	if (count >= 10)
+static int pll_source_sync_read(uint32_t pll_type, uint32_t addr_offset,
+				uint32_t *rdata, int retry_count)
+{
+	uint32_t addr;
+	uint32_t val;
+
+	addr = ((addr_offset | CLKMGR_MEM_ADDR_START) & CLKMGR_MEM_ADDR_MASK);
+	val = ((CLKMGR_MEM_REQ & ~CLKMGR_MEM_WR) | addr);
+
+	if ((pll_type == CLKMGR_MAINPLL_TYPE) != 0) {
+		mmio_write_32(CLKMGR_MAINPLL(MEM), val);
+	} else {
+		mmio_write_32(CLKMGR_PERPLL(MEM), val);
+	}
+
+	*rdata = 0;
+
+	if ((pll_source_sync_wait(pll_type, retry_count)) != 0) {
 		return -ETIMEDOUT;
+	}
 
-	rdata = mmio_read_32(pll_mem_offset + 0x4);
-	INFO("rdata (%x) = %x\n", pll_mem_offset + 0x4, rdata);
+	if ((pll_type == CLKMGR_MAINPLL_TYPE) != 0) {
+		*rdata = mmio_read_32(CLKMGR_MAINPLL(MEMSTAT));
+	} else {
+		*rdata = mmio_read_32(CLKMGR_PERPLL(MEMSTAT));
+	}
 
-	return rdata;
+	return 0;
 }
 
-void config_clkmgr_handoff(handoff *hoff_ptr)
+static void config_pll_pd_state(uint32_t pll_type)
 {
-	/* Take both PLL out of reset and power up */
+	uint32_t rdata;
 
-	mmio_setbits_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB,
-			CLKMGR_PLLGLOB_PD_SET_MSK |
-			CLKMGR_PLLGLOB_RST_SET_MSK);
-	mmio_setbits_32(CLKMGR_PERPLL + CLKMGR_PERPLL_PLLGLOB,
-			CLKMGR_PLLGLOB_PD_SET_MSK |
-			CLKMGR_PLLGLOB_RST_SET_MSK);
+	for (uint32_t i = 0; i < ARRAY_SIZE(pll_cfg_set); i++) {
+		(void)pll_source_sync_read(pll_type, pll_cfg_set[i].addr, &rdata,
+					   CLKMGR_MAX_RETRY_COUNT);
 
-	/* PLL lock */
-	wait_pll_lock();
+		(void)pll_source_sync_config(pll_type, pll_cfg_set[i].addr,
+				((rdata & ~pll_cfg_set[i].mask) | pll_cfg_set[i].data),
+				CLKMGR_MAX_RETRY_COUNT);
+	}
+}
+
+int config_clkmgr_handoff(handoff *hoff_ptr)
+{
+	int ret = 0;
+	uint32_t mainpll_vcocalib;
+	uint32_t perpll_vcocalib;
+
+	/* Enter boot mode before any configuration */
+	mmio_setbits_32(CLKMGR(CTRL), CLKMGR_CTRL_BOOTMODE);
 
 	/* Bypass all mainpllgrp's clocks to input clock ref */
-	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_BYPASSS, 0xff);
+	mmio_setbits_32(CLKMGR_MAINPLL(BYPASS), CLKMGR_MAINPLL_BYPASS_ALL);
+	ret = wait_fsm();
+	if (ret != 0)
+		return ret;
+
 	/* Bypass all perpllgrp's clocks to input clock ref */
-	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_BYPASS, 0xff);
+	mmio_setbits_32(CLKMGR_PERPLL(BYPASS), CLKMGR_PERPLL_BYPASS_ALL);
+	ret = wait_fsm();
+	if (ret != 0)
+		return ret;
+
+	/* Take both PLL out of reset and power down */
+	mmio_clrbits_32(CLKMGR_MAINPLL(PLLGLOB),
+			CLKMGR_MAINPLL_PLLGLOB_PD_N | CLKMGR_MAINPLL_PLLGLOB_RST_N);
+	mmio_clrbits_32(CLKMGR_PERPLL(PLLGLOB),
+			CLKMGR_PERPLL_PLLGLOB_PD_N | CLKMGR_PERPLL_PLLGLOB_RST_N);
+
+	/* Setup main PLL dividers */
+	mainpll_vcocalib = calc_pll_vcocalibration(hoff_ptr->main_pll_pllm,
+						hoff_ptr->main_pll_pllglob);
+	mmio_write_32(CLKMGR_MAINPLL(PLLGLOB),
+			hoff_ptr->main_pll_pllglob & ~CLKMGR_MAINPLL_PLLGLOB_RST_N);
+	mmio_write_32(CLKMGR_MAINPLL(FDBCK), hoff_ptr->main_pll_fdbck);
+	mmio_write_32(CLKMGR_MAINPLL(VCOCALIB), mainpll_vcocalib);
+	mmio_write_32(CLKMGR_MAINPLL(PLLC0), hoff_ptr->main_pll_pllc0);
+	mmio_write_32(CLKMGR_MAINPLL(PLLC1), hoff_ptr->main_pll_pllc1);
+	mmio_write_32(CLKMGR_MAINPLL(PLLC2), hoff_ptr->main_pll_pllc2);
+	mmio_write_32(CLKMGR_MAINPLL(PLLC3), hoff_ptr->main_pll_pllc3);
+	mmio_write_32(CLKMGR_MAINPLL(PLLM), hoff_ptr->main_pll_pllm);
+	mmio_write_32(CLKMGR_MAINPLL(NOCCLK), hoff_ptr->main_pll_nocclk);
+	mmio_write_32(CLKMGR_MAINPLL(NOCDIV), hoff_ptr->main_pll_nocdiv);
+
+	/* Setup peripheral PLL dividers */
+	perpll_vcocalib = calc_pll_vcocalibration(hoff_ptr->per_pll_pllm,
+						hoff_ptr->per_pll_pllglob);
+	mmio_write_32(CLKMGR_PERPLL(PLLGLOB),
+			hoff_ptr->per_pll_pllglob & ~CLKMGR_PERPLL_PLLGLOB_RST_N);
+	mmio_write_32(CLKMGR_PERPLL(FDBCK), hoff_ptr->per_pll_fdbck);
+	mmio_write_32(CLKMGR_PERPLL(VCOCALIB), perpll_vcocalib);
+	mmio_write_32(CLKMGR_PERPLL(PLLC0), hoff_ptr->per_pll_pllc0);
+	mmio_write_32(CLKMGR_PERPLL(PLLC1), hoff_ptr->per_pll_pllc1);
+	mmio_write_32(CLKMGR_PERPLL(PLLC2), hoff_ptr->per_pll_pllc2);
+	mmio_write_32(CLKMGR_PERPLL(PLLC3), hoff_ptr->per_pll_pllc3);
+	mmio_write_32(CLKMGR_PERPLL(PLLM), hoff_ptr->per_pll_pllm);
+	mmio_write_32(CLKMGR_PERPLL(EMACCTL), hoff_ptr->per_pll_emacctl);
+	mmio_write_32(CLKMGR_PERPLL(GPIODIV), hoff_ptr->per_pll_gpiodiv);
+
+	/* Configure ping pong counters */
+	mmio_write_32(CLKMGR_ALTERA(EMACACTR), hoff_ptr->alt_emacactr);
+	mmio_write_32(CLKMGR_ALTERA(EMACBCTR), hoff_ptr->alt_emacbctr);
+	mmio_write_32(CLKMGR_ALTERA(EMACPTPCTR), hoff_ptr->alt_emacptpctr);
+	mmio_write_32(CLKMGR_ALTERA(GPIODBCTR), hoff_ptr->alt_gpiodbctr);
+	mmio_write_32(CLKMGR_ALTERA(S2FUSER0CTR), hoff_ptr->alt_s2fuser0ctr);
+	mmio_write_32(CLKMGR_ALTERA(S2FUSER1CTR), hoff_ptr->alt_s2fuser1ctr);
+	mmio_write_32(CLKMGR_ALTERA(PSIREFCTR), hoff_ptr->alt_psirefctr);
+	mmio_write_32(CLKMGR_ALTERA(USB31CTR), hoff_ptr->alt_usb31ctr);
+	mmio_write_32(CLKMGR_ALTERA(DSUCTR), hoff_ptr->alt_dsuctr);
+	mmio_write_32(CLKMGR_ALTERA(CORE01CTR), hoff_ptr->alt_core01ctr);
+	mmio_write_32(CLKMGR_ALTERA(CORE23CTR), hoff_ptr->alt_core23ctr);
+	mmio_write_32(CLKMGR_ALTERA(CORE2CTR), hoff_ptr->alt_core2ctr);
+	mmio_write_32(CLKMGR_ALTERA(CORE3CTR), hoff_ptr->alt_core3ctr);
+
+	/* Take both PLL out of reset and power up */
+	mmio_setbits_32(CLKMGR_MAINPLL(PLLGLOB),
+			CLKMGR_MAINPLL_PLLGLOB_PD_N | CLKMGR_MAINPLL_PLLGLOB_RST_N);
+	mmio_setbits_32(CLKMGR_PERPLL(PLLGLOB),
+			CLKMGR_PERPLL_PLLGLOB_PD_N | CLKMGR_PERPLL_PLLGLOB_RST_N);
+
+	/* Main PLL configuration in Powed down state */
+	config_pll_pd_state(CLKMGR_MAINPLL_TYPE);
+
+	/* Peripheral PLL configuration in Powed down state */
+	config_pll_pd_state(CLKMGR_PERPLL_TYPE);
+
+	/* Enable main PLL clkslices */
+	mmio_setbits_32(CLKMGR_MAINPLL(PLLC0), CLKMGR_MAINPLL_PLLCX_EN);
+	mmio_setbits_32(CLKMGR_MAINPLL(PLLC1), CLKMGR_MAINPLL_PLLCX_EN);
+	mmio_setbits_32(CLKMGR_MAINPLL(PLLC2), CLKMGR_MAINPLL_PLLCX_EN);
+	mmio_setbits_32(CLKMGR_MAINPLL(PLLC3), CLKMGR_MAINPLL_PLLCX_EN);
+
+	/* Enable periheral PLL clkslices */
+	mmio_setbits_32(CLKMGR_PERPLL(PLLC0), CLKMGR_PERPLL_PLLCX_EN);
+	mmio_setbits_32(CLKMGR_PERPLL(PLLC1), CLKMGR_PERPLL_PLLCX_EN);
+	mmio_setbits_32(CLKMGR_PERPLL(PLLC2), CLKMGR_PERPLL_PLLCX_EN);
+	mmio_setbits_32(CLKMGR_PERPLL(PLLC3), CLKMGR_PERPLL_PLLCX_EN);
+
+	/* Wait for main and peri PLL lock state */
+	ret = wait_pll_lock(CLKMGR_STAT_ALLPLLLOCKED);
+	if (ret != 0) {
+		return ret;
+	}
+
+	/* Main PLL and per PLL lost lock */
+	mmio_setbits_32(CLKMGR_MAINPLL(LOSTLOCK), CLKMGR_XPLL_LOSTLOCK_BYPASSCLEAR);
+	mmio_setbits_32(CLKMGR_PERPLL(LOSTLOCK), CLKMGR_XPLL_LOSTLOCK_BYPASSCLEAR);
+
+	/* Main PLL and per PLL clear lostlock bypass */
+	mmio_setbits_32(CLKMGR_MAINPLL(PLLGLOB), CLKMGR_XPLLGLOB_CLR_LOSTLOCK_BYPASS);
+	mmio_setbits_32(CLKMGR_PERPLL(PLLGLOB), CLKMGR_XPLLGLOB_CLR_LOSTLOCK_BYPASS);
 
-	/* Pass clock source frequency into scratch register */
-	mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1),
-		hoff_ptr->hps_osc_clk_hz);
-	mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2),
-		hoff_ptr->fpga_clk_hz);
+	/* Pass clock source frequency into boot scratch register */
+	mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1), hoff_ptr->hps_osc_clk_hz);
+	mmio_write_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2), hoff_ptr->fpga_clk_hz);
 
 	/* Take all PLLs out of bypass */
-	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_BYPASS, 0);
-	wait_fsm();
-	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_BYPASS, 0);
-	wait_fsm();
+	mmio_clrbits_32(CLKMGR_MAINPLL(BYPASS), CLKMGR_MAINPLL_BYPASS_ALL);
+	ret = wait_fsm();
+	if (ret != 0) {
+		return ret;
+	}
+
+	mmio_clrbits_32(CLKMGR_PERPLL(BYPASS), CLKMGR_PERPLL_BYPASS_ALL);
+	ret = wait_fsm();
+	if (ret != 0) {
+		return ret;
+	}
+
+	/* Clear the loss of lock bits (write 1 to clear) */
+	mmio_write_32(CLKMGR(INTRCLR),
+			CLKMGR_INTRCLR_MAINLOCKLOST | CLKMGR_INTRCLR_PERLOCKLOST);
+
+	/* Take all ping pong counters out of reset */
+	mmio_clrbits_32(CLKMGR_ALTERA(EXTCNTRST), CLKMGR_ALTERA_EXTCNTRST_ALLCNTRST);
+
+	/* Exit boot mode */
+	mmio_clrbits_32(CLKMGR(CTRL), CLKMGR_CTRL_BOOTMODE);
 
-	/* Enable mainpllgrp's software-managed clock */
-	mmio_write_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_EN,
-			CLKMGR_MAINPLL_EN_RESET);
-	mmio_write_32(CLKMGR_PERPLL + CLKMGR_PERPLL_EN,
-			CLKMGR_PERPLL_EN_RESET);
+	return 0;
 }
 
 /* Extract reference clock from platform clock source */
-uint32_t get_ref_clk(uint32_t pllglob)
+uint32_t get_ref_clk(uint32_t pllglob_reg, uint32_t pllm_reg)
 {
-	uint32_t arefclkdiv, ref_clk;
-	uint32_t scr_reg;
+	uint32_t arefclkdiv, ref_clk, mdiv;
+	uint32_t pllglob_val, pllm_val;
 
-	switch (CLKMGR_PSRC(pllglob)) {
+	/* Read pllglob and pllm registers */
+	pllglob_val = mmio_read_32(pllglob_reg);
+	pllm_val = mmio_read_32(pllm_reg);
+
+	switch (CLKMGR_PLLGLOB_PSRC(pllglob_val)) {
 	case CLKMGR_PLLGLOB_PSRC_EOSC1:
-		scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1);
-		ref_clk = mmio_read_32(scr_reg);
+		ref_clk = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1));
 		break;
+
 	case CLKMGR_PLLGLOB_PSRC_INTOSC:
 		ref_clk = CLKMGR_INTOSC_HZ;
 		break;
+
 	case CLKMGR_PLLGLOB_PSRC_F2S:
-		scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2);
-		ref_clk = mmio_read_32(scr_reg);
+		ref_clk = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2));
 		break;
+
 	default:
 		ref_clk = 0;
 		assert(0);
 		break;
 	}
 
-	arefclkdiv = CLKMGR_PLLGLOB_AREFCLKDIV(pllglob);
+	/* Get reference clock divider */
+	arefclkdiv = CLKMGR_PLLGLOB_AREFCLKDIV(pllglob_val);
 	ref_clk /= arefclkdiv;
 
+	/* Feedback clock divider */
+	mdiv = CLKMGR_PLLM_MDIV(pllm_val);
+	ref_clk *= mdiv;
+
+	VERBOSE("CLKMGR: %s: ref_clk %u\n", __func__, ref_clk);
 	return ref_clk;
 }
 
 /* Calculate clock frequency based on parameter */
-uint32_t get_clk_freq(uint32_t psrc_reg, uint32_t main_pllc, uint32_t per_pllc)
+uint32_t get_clk_freq(uint32_t psrc_reg, uint32_t mainpllc_reg,
+		      uint32_t perpllc_reg)
 {
-	uint32_t ref_clk = 0;
+	uint32_t clock = 0;
+	uint32_t clk_psrc;
 
-	uint32_t clk_psrc, mdiv;
-	uint32_t pllm_reg, pllc_reg, pllc_div, pllglob_reg;
+	/*
+	 * Select source for the active 5:1 clock selection when the PLL
+	 * is not bypassed
+	 */
+	clk_psrc = mmio_read_32(psrc_reg);
+	switch (GET_CLKMGR_CLKSRC(clk_psrc)) {
+	case CLKMGR_CLKSRC_MAIN:
+		clock = get_ref_clk(CLKMGR_MAINPLL(PLLGLOB), CLKMGR_MAINPLL(PLLM));
+		clock /= (mmio_read_32(mainpllc_reg) & CLKMGR_PLLCX_DIV_MSK);
+		break;
 
+	case CLKMGR_CLKSRC_PER:
+		clock = get_ref_clk(CLKMGR_PERPLL(PLLGLOB), CLKMGR_PERPLL(PLLM));
+		clock /= (mmio_read_32(perpllc_reg) & CLKMGR_PLLCX_DIV_MSK);
+		break;
 
-	clk_psrc = mmio_read_32(CLKMGR_MAINPLL + psrc_reg);
-	clk_psrc = 0;
+	case CLKMGR_CLKSRC_OSC1:
+		clock = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1));
+		break;
+
+	case CLKMGR_CLKSRC_INTOSC:
+		clock = CLKMGR_INTOSC_HZ;
+		break;
 
-	switch (clk_psrc) {
-	case 0:
-		pllm_reg = CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLM;
-		pllc_reg = CLKMGR_MAINPLL + main_pllc;
-		pllglob_reg = CLKMGR_MAINPLL + CLKMGR_MAINPLL_PLLGLOB;
+	case CLKMGR_CLKSRC_FPGA:
+		clock = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2));
+		break;
+
+	default:
+		ERROR("CLKMGR: Invalid clock source select\n");
+		assert(0);
 		break;
 	}
 
-	ref_clk = get_ref_clk(mmio_read_32(pllglob_reg));
-	mdiv = CLKMGR_PLLM_MDIV(mmio_read_32(pllm_reg));
-	ref_clk *= mdiv;
+	VERBOSE("CLKMGR: %s: clock type %lu and its value %u\n",
+			__func__, GET_CLKMGR_CLKSRC(clk_psrc), clock);
 
-	pllc_div = mmio_read_32(pllc_reg) & 0x7ff;
-	NOTICE("return = %d Hz\n", (ref_clk / pllc_div));
+	return clock;
+}
 
-	ref_clk = 200000000;
-	return (uint32_t) ref_clk;
+/* Get L3 free clock */
+static uint32_t get_l3_main_free_clk(void)
+{
+	return get_clk_freq(CLKMGR_MAINPLL(NOCCLK),
+			    CLKMGR_MAINPLL(PLLC3),
+			    CLKMGR_PERPLL(PLLC1));
+}
 
+/* Get L4 main clock */
+static uint32_t get_l4_main_clk(void)
+{
+	return get_l3_main_free_clk();
 }
 
-/* Return L3 interconnect clock */
-uint32_t get_l3_clk(void)
+/* Get L4 mp clock */
+static uint32_t get_l4_mp_clk(void)
 {
-	uint32_t l3_clk;
+	uint32_t l3_main_free_clk = get_l3_main_free_clk();
+	uint32_t mainpll_nocdiv_l4mp = BIT(GET_CLKMGR_MAINPLL_NOCDIV_L4MP(
+					mmio_read_32(CLKMGR_MAINPLL(NOCDIV))));
 
-	l3_clk = get_clk_freq(CLKMGR_MAINPLL_NOCCLK, CLKMGR_MAINPLL_PLLC1,
-				CLKMGR_PERPLL_PLLC1);
-	return l3_clk;
+	uint32_t l4_mp_clk = (l3_main_free_clk / mainpll_nocdiv_l4mp);
+
+	return l4_mp_clk;
 }
 
-/* Calculate clock frequency to be used for watchdog timer */
-uint32_t get_wdt_clk(void)
+/* Get L4 sp clock */
+static uint32_t get_l4_sp_clk(void)
 {
-	uint32_t l3_clk, l4_sys_clk;
+	uint32_t l3_main_free_clk = get_l3_main_free_clk();
+	uint32_t mainpll_nocdiv_l4sp = BIT(GET_CLKMGR_MAINPLL_NOCDIV_L4SP(
+					mmio_read_32(CLKMGR_MAINPLL(NOCDIV))));
+
+	uint32_t l4_sp_clk = (l3_main_free_clk / mainpll_nocdiv_l4sp);
+
+	return l4_sp_clk;
+}
 
-	l3_clk = get_l3_clk();
-	l4_sys_clk = l3_clk / 4;
+/* Calculate clock frequency to be used for SDMMC driver */
+uint32_t get_sdmmc_clk(void)
+{
+	uint32_t l4_mp_clk = get_l4_mp_clk();
+	uint32_t mainpll_nocdiv = mmio_read_32(CLKMGR_MAINPLL(NOCDIV));
+	uint32_t sdmmc_clk = l4_mp_clk / BIT(GET_CLKMGR_MAINPLL_NOCDIV_SPHY(mainpll_nocdiv));
 
-	return l4_sys_clk;
+	return sdmmc_clk;
 }
 
-/* Calculate clock frequency to be used for UART driver */
-uint32_t get_uart_clk(void)
+/* Get clock for ethernet mac0 */
+static uint32_t get_emaca_clk(void)
 {
-	uint32_t data32, l3_clk, l4_sp_clk;
+	uint32_t emaca_ctr = mmio_read_32(CLKMGR_ALTERA(EMACACTR));
+	uint32_t perpll_emacctl = mmio_read_32(CLKMGR_PERPLL(EMACCTL));
+	uint32_t perpll_emac_src = GET_CLKMGR_PERPLL_EMAC0_CLK_SRC(perpll_emacctl);
+	uint32_t emac_ctr_reg;
+	uint32_t emac_clock;
 
-	l3_clk = get_l3_clk();
+	if (perpll_emac_src != 0) {
+		emac_ctr_reg = CLKMGR_ALTERA(EMACBCTR);
+	} else {
+		emac_ctr_reg = CLKMGR_ALTERA(EMACACTR);
+	}
 
-	data32 = mmio_read_32(CLKMGR_MAINPLL + CLKMGR_MAINPLL_NOCDIV);
-	data32 = (data32 >> 16) & 0x3;
+	/* Get EMACA clock source */
+	uint32_t emacactr_src = GET_CLKMGR_EMACACTR_CLK_SRC(emaca_ctr);
 
-	l4_sp_clk = l3_clk >> data32;
+	/* Read the desired EMAC register again */
+	emaca_ctr = mmio_read_32(emac_ctr_reg);
 
-	return l4_sp_clk;
+	/* Get the divider now */
+	uint32_t emaca_ctr_div = emaca_ctr & GENMASK(10, 0);
+
+	switch (emacactr_src) {
+	case CLKMGR_CLKSRC_MAIN:
+		emac_clock = get_ref_clk(CLKMGR_MAINPLL(PLLGLOB), CLKMGR_MAINPLL(PLLM));
+		emac_clock /= (mmio_read_32(CLKMGR_MAINPLL(PLLC1)) & GENMASK(10, 0));
+		break;
+
+	case CLKMGR_CLKSRC_PER:
+		emac_clock = get_ref_clk(CLKMGR_PERPLL(PLLGLOB), CLKMGR_PERPLL(PLLM));
+		emac_clock /= (mmio_read_32(CLKMGR_PERPLL(PLLC3)) & GENMASK(10, 0));
+		break;
+
+	default:
+		ERROR("CLKMGR: %s invalid clock source\n", __func__);
+		emac_clock = 0;
+		return emac_clock;
+	}
+
+	emac_clock /= 1 + emaca_ctr_div;
+
+	return emac_clock;
 }
 
-/* Calculate clock frequency to be used for SDMMC driver */
-uint32_t get_mmc_clk(void)
+/* Get MPU clock */
+static uint32_t get_mpu_clk(void)
+{
+	uint32_t cpu_id = MPIDR_AFFLVL1_VAL(read_mpidr());
+	uint32_t ctr_reg = 0U;
+	uint32_t clock;
+
+	if (cpu_id > CLKMGR_ALTERA_CORE1) {
+		clock = get_clk_freq(CLKMGR_ALTERA(CORE23CTR),
+				     CLKMGR_MAINPLL(PLLC0),
+				     CLKMGR_PERPLL(PLLC0));
+	} else {
+		clock = get_clk_freq(CLKMGR_ALTERA(CORE01CTR),
+				     CLKMGR_MAINPLL(PLLC1),
+				     CLKMGR_PERPLL(PLLC0));
+	}
+
+	switch (cpu_id) {
+	case CLKMGR_ALTERA_CORE0:
+	case CLKMGR_ALTERA_CORE1:
+		ctr_reg = CLKMGR_ALTERA(CORE01CTR);
+		break;
+
+	case CLKMGR_ALTERA_CORE2:
+		ctr_reg = CLKMGR_ALTERA(CORE2CTR);
+		break;
+
+	case CLKMGR_ALTERA_CORE3:
+		ctr_reg = CLKMGR_ALTERA(CORE3CTR);
+		break;
+
+	default:
+		break;
+	}
+
+	/* Division setting for ping pong counter in clock slice */
+	clock /= 1 + (mmio_read_32(ctr_reg) & CLKMGR_PLLCX_DIV_MSK);
+
+	return clock;
+}
+
+/* Calculate clock frequency to be used for watchdog timer */
+static uint32_t get_wdt_clk(void)
+{
+	uint32_t l3_main_free_clk = get_l3_main_free_clk();
+	uint32_t mainpll_nocdiv_l4sysfreeclk = BIT(GET_CLKMGR_MAINPLL_NOCDIV_L4SYSFREE(
+						mmio_read_32(CLKMGR_MAINPLL(NOCDIV))));
+	uint32_t l4_sys_free_clk = (l3_main_free_clk / mainpll_nocdiv_l4sysfreeclk);
+
+	return l4_sys_free_clk;
+}
+
+/*
+ * Calculate clock frequency to be used for UART driver.
+ * 'l4_sp_clk' (100MHz) will be used for slow peripherals like UART, I2C
+ * and Timers.
+ */
+static uint32_t get_uart_clk(void)
 {
-	uint32_t mmc_clk;
+	return get_l4_sp_clk();
+}
+
+/* Return the clock value of a given system component */
+uint32_t clkmgr_get_rate(uint32_t clk_id)
+{
+	uint32_t clk_rate;
+
+	switch (clk_id) {
+	case CLKMGR_MPU_CLK_ID:
+		clk_rate = get_mpu_clk();
+		break;
+
+	case CLKMGR_L4_MAIN_CLK_ID:
+		clk_rate = get_l4_main_clk();
+		break;
+
+	case CLKMGR_L4_MP_CLK_ID:
+		clk_rate = get_l4_mp_clk();
+		break;
 
-	//TODO: To update when handoff data is ready
-	//uint32_t data32;
+	case CLKMGR_L4_SP_CLK_ID:
+		clk_rate = get_l4_sp_clk();
+		break;
 
-	//mmc_clk = get_clk_freq(CLKMGR_ALTERA_SDMMCCTR, CLKMGR_MAINPLL_PLLC3, CLKMGR_PERPLL_PLLC3);
+	case CLKMGR_EMAC0_CLK_ID:
+		clk_rate = get_emaca_clk();
+		break;
 
-	//data32 = mmio_read_32(CLKMGR_ALTERA + CLKMGR_ALTERA_SDMMCCTR);
-	//data32 = (data32 & 0x7ff) + 1;
-	//mmc_clk = (mmc_clk / data32) / 4;
+	case CLKMGR_SDMMC_CLK_ID:
+		clk_rate = get_sdmmc_clk();
+		break;
 
+	case CLKMGR_UART_CLK_ID:
+		clk_rate = get_uart_clk();
+		break;
 
-	mmc_clk = get_clk_freq(CLKMGR_MAINPLL_NOCCLK, CLKMGR_MAINPLL_PLLC3,
-				CLKMGR_PERPLL_PLLC3);
+	case CLKMGR_WDT_CLK_ID:
+		clk_rate = get_wdt_clk();
+		break;
 
-	// TODO: To update when handoff data is ready
-	NOTICE("mmc_clk = %d Hz\n", mmc_clk);
+	default:
+		ERROR("CLKMGR: %s: Invalid clock ID\n", __func__);
+		clk_rate = 0;
+		break;
+	}
 
-	return mmc_clk;
+	return clk_rate;
 }
 
 /* Return mpu_periph_clk tick */
diff --git a/plat/intel/soc/agilex5/soc/agilex5_ddr.c b/plat/intel/soc/agilex5/soc/agilex5_ddr.c
new file mode 100644
index 0000000..ef2ae57
--- /dev/null
+++ b/plat/intel/soc/agilex5/soc/agilex5_ddr.c
@@ -0,0 +1,434 @@
+/*
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include "lib/mmio.h"
+
+#include "agilex5_ddr.h"
+#include "agilex5_iossm_mailbox.h"
+
+/*
+ * TODO: We need to leverage the legacy products DDR drivers and consider
+ * the upcoming products like KM and then come up with common source code/driver
+ * architecture to address all the products in one view.
+ */
+
+#define SYSMGR_BS_COLD3_DDR_RESET_TYPE_MASK		GENMASK(31, 29)
+#define SYSMGR_BS_COLD3_DDR_RESET_TYPE_SHIFT		29
+#define SYSMGR_BS_COLD3_DDR_DBE_MASK			(1 << 1)
+#define SYSMGR_BS_COLD3_OCRAM_DBE_MASK			(1)
+#define SYSMGR_BS_POR0_DDR_PROGRESS_MASK		(1)
+
+/* MPFE NOC registers */
+#define F2SDRAM_SIDEBAND_FLAGOUTSET0			0x50
+#define F2SDRAM_SIDEBAND_FLAGOUTCLR0			0x54
+#define F2SDRAM_SIDEBAND_FLAGOUTSTATUS0			0x58
+
+#define SOCFPGA_F2SDRAM_MGR_ADDRESS			0x18001000
+#define SOCFPGA_MPFE_SCR_IO96B0				0x18000D00
+#define SOCFPGA_MPFE_SCR_IO96B1				0x18000D04
+#define SOCFPGA_MPFE_NOC_SCHED_CSR			0x18000D08
+
+#define SIDEBANDMGR_FLAGOUTSET0_REG			(SOCFPGA_F2SDRAM_MGR_ADDRESS \
+							+ F2SDRAM_SIDEBAND_FLAGOUTSET0)
+#define SIDEBANDMGR_FLAGOUTSTATUS0_REG			(SOCFPGA_F2SDRAM_MGR_ADDRESS \
+							+F2SDRAM_SIDEBAND_FLAGOUTSTATUS0)
+#define SIDEBANDMGR_FLAGOUTCLR0_REG			(SOCFPGA_F2SDRAM_MGR_ADDRESS \
+							+ F2SDRAM_SIDEBAND_FLAGOUTCLR0)
+#define SZ_8						0x00000008
+
+
+/* Firewall MPU DDR SCR registers */
+#define FW_MPU_DDR_SCR_EN				0x00
+#define FW_MPU_DDR_SCR_EN_SET				0x04
+#define FW_MPU_DDR_SCR_MPUREGION0ADDR_BASE		0x10
+#define FW_MPU_DDR_SCR_MPUREGION0ADDR_BASEEXT		0x14
+#define FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMIT		0x18
+#define FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMITEXT		0x1c
+
+#define SOCFPGA_FW_DDR_CCU_DMI0_ADDRESS			0x18000800
+#define SOCFPGA_FW_DDR_CCU_DMI1_ADDRESS			0x18000A00
+#define SOCFPGA_FW_TBU2NOC_ADDRESS			0x18000C00
+
+#define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASE		0x90
+#define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASEEXT	0x94
+#define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMIT		0x98
+#define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT	0x9c
+#define FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT_FIELD	0xff
+
+/* Firewall F2SDRAM DDR SCR registers */
+#define FW_F2SDRAM_DDR_SCR_EN				0x00
+#define FW_F2SDRAM_DDR_SCR_EN_SET			0x04
+#define FW_F2SDRAM_DDR_SCR_REGION0ADDR_BASE		0x10
+#define FW_F2SDRAM_DDR_SCR_REGION0ADDR_BASEEXT		0x14
+#define FW_F2SDRAM_DDR_SCR_REGION0ADDR_LIMIT		0x18
+#define FW_F2SDRAM_DDR_SCR_REGION0ADDR_LIMITEXT		0x1c
+
+#define FW_MPU_DDR_SCR_WRITEL(data, reg)					\
+	do {									\
+		mmio_write_32(SOCFPGA_FW_DDR_CCU_DMI0_ADDRESS + (reg), data);	\
+		mmio_write_32(SOCFPGA_FW_DDR_CCU_DMI1_ADDRESS + (reg), data);	\
+	} while (0)
+
+#define FW_F2SDRAM_DDR_SCR_WRITEL(data, reg)				\
+	mmio_write_32(SOCFPGA_FW_TBU2NOC_ADDRESS + (reg), data)
+
+/* DDR banks info set */
+static struct ddr_info ddr_info_set[CONFIG_NR_DRAM_BANKS];
+
+/* Reset type */
+enum reset_type {
+	POR_RESET,
+	WARM_RESET,
+	COLD_RESET,
+	NCONFIG,
+	JTAG_CONFIG,
+	RSU_RECONFIG
+};
+
+/* Get reset type by reading boot scratch register cold3 */
+static inline enum reset_type get_reset_type(uint32_t sys_reg)
+{
+	return ((sys_reg & SYSMGR_BS_COLD3_DDR_RESET_TYPE_MASK) >>
+		 SYSMGR_BS_COLD3_DDR_RESET_TYPE_SHIFT);
+}
+
+/* DDR hang check before the reset */
+static inline bool is_ddr_init_hang(void)
+{
+	uint32_t sys_reg = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_POR_0));
+
+	if ((sys_reg & SYSMGR_BS_POR0_DDR_PROGRESS_MASK) != 0) {
+		INFO("DDR: Hang before this reset\n");
+		return true;
+	}
+
+	return false;
+}
+
+/* Set the DDR init progress bit */
+static inline void ddr_init_inprogress(bool start)
+{
+	if (start) {
+		mmio_setbits_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_POR_0),
+				SYSMGR_BS_POR0_DDR_PROGRESS_MASK);
+	} else {
+		mmio_clrbits_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_POR_0),
+				SYSMGR_BS_POR0_DDR_PROGRESS_MASK);
+	}
+}
+
+/* Configure the IO96B CSRs address based on the handoff data */
+static void config_io96b_csr_addr(bool is_dualemif, struct io96b_info *io96b_ctrl)
+{
+	if (is_dualemif)
+		io96b_ctrl->num_instance = 2;
+	else
+		io96b_ctrl->num_instance = 1;
+
+	/* Assign IO96B CSR base address if it is valid */
+	for (int i = 0; i < io96b_ctrl->num_instance; i++) {
+		switch (i) {
+		case 0:
+			io96b_ctrl->io96b_0.io96b_csr_addr = 0x18400000;
+			INFO("DDR: IO96B0 0x%llx CSR enabled\n",
+			     io96b_ctrl->io96b_0.io96b_csr_addr);
+			break;
+
+		case 1:
+			io96b_ctrl->io96b_1.io96b_csr_addr = 0x18800000;
+			INFO("DDR: IO96B1 0x%llx CSR enabled\n",
+			     io96b_ctrl->io96b_1.io96b_csr_addr);
+			break;
+
+		default:
+			ERROR("%s: Invalid IO96B CSR\n", __func__);
+		} /* switch */
+	} /* for */
+}
+
+static inline bool hps_ocram_dbe_status(void)
+{
+	uint32_t sys_reg = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_3));
+
+	if ((sys_reg & SYSMGR_BS_COLD3_OCRAM_DBE_MASK) != 0)
+		return true;
+
+	return false;
+}
+
+static inline bool ddr_ecc_dbe_status(void)
+{
+	uint32_t sys_reg = mmio_read_32(SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_3));
+
+	if ((sys_reg & SYSMGR_BS_COLD3_DDR_DBE_MASK) != 0)
+		return true;
+
+	return false;
+}
+
+static void sdram_set_firewall_non_f2sdram(void)
+{
+	uint32_t i;
+	phys_size_t value;
+	uint32_t lower, upper;
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+		if (ddr_info_set[i].size == 0) {
+			continue;
+		}
+
+		value = ddr_info_set[i].start;
+
+		/*
+		 * Keep first 1MB of SDRAM memory region as secure region when
+		 * using ATF flow, where the ATF code is located.
+		 */
+		value += SZ_1M;
+
+		/* Setting non-secure MPU region base and base extended */
+		lower = LO(value);
+		upper = HI(value);
+
+		FW_MPU_DDR_SCR_WRITEL(lower,
+				      FW_MPU_DDR_SCR_MPUREGION0ADDR_BASE +
+				      (i * 4 * sizeof(uint32_t)));
+		FW_MPU_DDR_SCR_WRITEL(upper & 0xff,
+				      FW_MPU_DDR_SCR_MPUREGION0ADDR_BASEEXT +
+				      (i * 4 * sizeof(uint32_t)));
+
+		/* Setting non-secure Non-MPU region base and base extended */
+		FW_MPU_DDR_SCR_WRITEL(lower,
+				      FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASE +
+				      (i * 4 * sizeof(uint32_t)));
+		FW_MPU_DDR_SCR_WRITEL(upper & 0xff,
+				      FW_MPU_DDR_SCR_NONMPUREGION0ADDR_BASEEXT +
+				      (i * 4 * sizeof(uint32_t)));
+
+		/* Setting non-secure MPU limit and limit extended */
+		value = ddr_info_set[i].start + ddr_info_set[i].size - 1;
+
+		lower = LO(value);
+		upper = HI(value);
+
+		FW_MPU_DDR_SCR_WRITEL(lower,
+				      FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMIT +
+				      (i * 4 * sizeof(uint32_t)));
+		FW_MPU_DDR_SCR_WRITEL(upper & 0xff,
+				      FW_MPU_DDR_SCR_MPUREGION0ADDR_LIMITEXT +
+				      (i * 4 * sizeof(uint32_t)));
+
+		/* Setting non-secure Non-MPU limit and limit extended */
+		FW_MPU_DDR_SCR_WRITEL(lower,
+				      FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMIT +
+				      (i * 4 * sizeof(uint32_t)));
+		FW_MPU_DDR_SCR_WRITEL(upper & 0xff,
+				      FW_MPU_DDR_SCR_NONMPUREGION0ADDR_LIMITEXT +
+				      (i * 4 * sizeof(uint32_t)));
+
+		FW_MPU_DDR_SCR_WRITEL(BIT(i) | BIT(i + 8),
+				      FW_MPU_DDR_SCR_EN_SET);
+	}
+}
+
+static void sdram_set_firewall_f2sdram(void)
+{
+	uint32_t i;
+	phys_size_t value;
+	uint32_t lower, upper;
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+		if (ddr_info_set[i].size == 0) {
+			continue;
+		}
+
+		value = ddr_info_set[i].start;
+
+		/* Keep first 1MB of SDRAM memory region as secure region when
+		 * using ATF flow, where the ATF code is located.
+		 */
+		value += SZ_1M;
+
+		/* Setting base and base extended */
+		lower = LO(value);
+		upper = HI(value);
+		FW_F2SDRAM_DDR_SCR_WRITEL(lower,
+					  FW_F2SDRAM_DDR_SCR_REGION0ADDR_BASE +
+					  (i * 4 * sizeof(uint32_t)));
+		FW_F2SDRAM_DDR_SCR_WRITEL(upper & 0xff,
+					  FW_F2SDRAM_DDR_SCR_REGION0ADDR_BASEEXT +
+					  (i * 4 * sizeof(uint32_t)));
+
+		/* Setting limit and limit extended */
+		value = ddr_info_set[i].start + ddr_info_set[i].size - 1;
+
+		lower = LO(value);
+		upper = HI(value);
+
+		FW_F2SDRAM_DDR_SCR_WRITEL(lower,
+					  FW_F2SDRAM_DDR_SCR_REGION0ADDR_LIMIT +
+					  (i * 4 * sizeof(uint32_t)));
+		FW_F2SDRAM_DDR_SCR_WRITEL(upper & 0xff,
+					  FW_F2SDRAM_DDR_SCR_REGION0ADDR_LIMITEXT +
+					  (i * 4 * sizeof(uint32_t)));
+
+		FW_F2SDRAM_DDR_SCR_WRITEL(BIT(i), FW_F2SDRAM_DDR_SCR_EN_SET);
+	}
+}
+
+static void sdram_set_firewall(void)
+{
+	sdram_set_firewall_non_f2sdram();
+	sdram_set_firewall_f2sdram();
+}
+
+/*
+ * Agilex5 DDR/IOSSM controller initialization routine
+ */
+int agilex5_ddr_init(handoff *hoff_ptr)
+{
+	int ret;
+	bool full_mem_init = false;
+	phys_size_t hw_ddr_size;
+	phys_size_t config_ddr_size;
+	struct io96b_info io96b_ctrl;
+	enum reset_type reset_t = get_reset_type(mmio_read_32(SOCFPGA_SYSMGR(
+						BOOT_SCRATCH_COLD_3)));
+	bool is_dualport = hoff_ptr->ddr_config & BIT(0);
+	bool is_dualemif = hoff_ptr->ddr_config & BIT(1);
+
+	NOTICE("DDR: Reset type is '%s'\n",
+	       (reset_t == POR_RESET ? "Power-On" : (reset_t == COLD_RESET ? "Cold" : "Warm")));
+
+	/* DDR initialization progress status tracking */
+	bool is_ddr_hang_bfr_rst = is_ddr_init_hang();
+
+	/* Set the DDR initialization progress */
+	ddr_init_inprogress(true);
+
+	/* Configure the IO96B CSR address based on the handoff data */
+	config_io96b_csr_addr(is_dualemif, &io96b_ctrl);
+
+	/* Configuring MPFE sideband manager registers */
+	/* Dual port setting */
+	if (is_dualport)
+		mmio_setbits_32(SIDEBANDMGR_FLAGOUTSET0_REG, BIT(4));
+
+	/* Dual EMIF setting */
+	if (is_dualemif) {
+		/* Set mpfe_lite_active in the system manager */
+		/* TODO: recheck on the bit value?? */
+		mmio_setbits_32(SOCFPGA_SYSMGR(MPFE_CONFIG), BIT(8));
+
+		mmio_setbits_32(SIDEBANDMGR_FLAGOUTSET0_REG, BIT(5));
+	}
+
+	if (is_dualport || is_dualemif)
+		INFO("DDR: SIDEBANDMGR_FLAGOUTSTATUS0: 0x%x\n",
+		     mmio_read_32(SIDEBANDMGR_FLAGOUTSTATUS0_REG));
+
+	/* Ensure calibration status passing */
+	init_mem_cal(&io96b_ctrl);
+
+	/* Initiate IOSSM mailbox */
+	io96b_mb_init(&io96b_ctrl);
+
+	/* Need to trigger re-calibration for DDR DBE */
+	if (ddr_ecc_dbe_status()) {
+		io96b_ctrl.io96b_0.cal_status = false;
+		io96b_ctrl.io96b_1.cal_status = false;
+		io96b_ctrl.overall_cal_status = io96b_ctrl.io96b_0.cal_status ||
+						io96b_ctrl.io96b_1.cal_status;
+	}
+
+	/* Trigger re-calibration if calibration failed */
+	if (!(io96b_ctrl.overall_cal_status)) {
+		NOTICE("DDR: Re-calibration in progress...\n");
+		trig_mem_cal(&io96b_ctrl);
+	}
+	NOTICE("DDR: Calibration success\n");
+
+	/* DDR type, DDR size and ECC status) */
+	ret = get_mem_technology(&io96b_ctrl);
+	if (ret != 0) {
+		ERROR("DDR: Failed to get DDR type\n");
+		return ret;
+	}
+
+	ret = get_mem_width_info(&io96b_ctrl);
+	if (ret != 0) {
+		ERROR("DDR: Failed to get DDR size\n");
+		return ret;
+	}
+
+	/* DDR size queried from the IOSSM controller */
+	hw_ddr_size = (phys_size_t)io96b_ctrl.overall_size * SZ_1G / SZ_8;
+
+	/* TODO: Hard code 1GB as of now, and DDR start and end address */
+	config_ddr_size = 0x40000000;
+	ddr_info_set[0].start = 0x80000000;
+	ddr_info_set[0].size = 0x40000000;
+
+	if (config_ddr_size != hw_ddr_size) {
+		WARN("DDR: DDR size configured is (%lld MiB)\n", config_ddr_size >> 20);
+		WARN("DDR: Mismatch with hardware size (%lld MiB).\n", hw_ddr_size >> 20);
+	}
+
+	if (config_ddr_size > hw_ddr_size) {
+		ERROR("DDR: Confgured DDR size is greater than the hardware size - HANG!!!\n");
+		while (1)
+			;
+	}
+
+	ret = ecc_enable_status(&io96b_ctrl);
+	if (ret != 0) {
+		ERROR("DDR: Failed to get DDR ECC status\n");
+		return ret;
+	}
+
+	/*
+	 * HPS cold or warm reset? If yes, skip full memory initialization if
+	 * ECC is enabled to preserve memory content.
+	 */
+	if (io96b_ctrl.ecc_status != 0) {
+		full_mem_init = hps_ocram_dbe_status() | ddr_ecc_dbe_status() |
+				is_ddr_hang_bfr_rst;
+		if ((full_mem_init == true) || (reset_t == WARM_RESET ||
+			reset_t == COLD_RESET) == 0) {
+			ret = bist_mem_init_start(&io96b_ctrl);
+			if (ret != 0) {
+				ERROR("DDR: Failed to fully initialize DDR memory\n");
+				return ret;
+			}
+		}
+		INFO("DDR: ECC initialized successfully\n");
+	}
+
+	sdram_set_firewall();
+
+	/*
+	 * Firewall setting for MPFE CSRs, allow both secure and non-secure
+	 * transactions.
+	 */
+	/* IO96B0_reg */
+	mmio_setbits_32(SOCFPGA_MPFE_SCR_IO96B0, BIT(0));
+	/* IO96B1_reg */
+	mmio_setbits_32(SOCFPGA_MPFE_SCR_IO96B1, BIT(0));
+	/* noc_scheduler_csr */
+	mmio_setbits_32(SOCFPGA_MPFE_NOC_SCHED_CSR, BIT(0));
+
+	INFO("DDR: firewall init done\n");
+
+	/* Ending DDR driver initialization success tracking */
+	ddr_init_inprogress(false);
+
+	NOTICE("###DDR:init success###\n");
+
+	return 0;
+}
diff --git a/plat/intel/soc/agilex5/soc/agilex5_iossm_mailbox.c b/plat/intel/soc/agilex5/soc/agilex5_iossm_mailbox.c
new file mode 100644
index 0000000..c2ab047
--- /dev/null
+++ b/plat/intel/soc/agilex5/soc/agilex5_iossm_mailbox.c
@@ -0,0 +1,811 @@
+/*
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+
+#include "agilex5_iossm_mailbox.h"
+
+/* supported DDR type list */
+static const char *ddr_type_list[7] = {
+	"DDR4", "DDR5", "DDR5_RDIMM", "LPDDR4", "LPDDR5", "QDRIV", "UNKNOWN"
+};
+
+static inline int wait_for_bit(const void *reg,
+			       const uint32_t mask,
+			       const bool set,
+			       const unsigned int timeout_ms)
+{
+	uint32_t val;
+	uint32_t timeout_sec = (timeout_ms / 1000);
+
+	while (timeout_sec > 0) {
+		val = mmio_read_32((uintptr_t)reg);
+
+		INFO("IOSSM: timeout_sec %d, val %x\n", timeout_sec, val);
+
+		if (!set) {
+			val = ~val;
+		}
+
+		if ((val & mask) == mask) {
+			INFO("IOSSM: %s, success\n", __func__);
+			return 0;
+		}
+
+		/* one second delay */
+		mdelay(1000);
+
+		timeout_sec--;
+	}
+
+	ERROR("IOSSM: %s, failed, time out\n", __func__);
+	return -ETIMEDOUT;
+}
+
+int io96b_mb_req(phys_addr_t io96b_csr_addr, uint32_t ip_type, uint32_t instance_id,
+		 uint32_t usr_cmd_type, uint32_t usr_cmd_opcode, uint32_t cmd_param_0,
+		 uint32_t cmd_param_1, uint32_t cmd_param_2, uint32_t cmd_param_3,
+		 uint32_t cmd_param_4, uint32_t cmd_param_5, uint32_t cmd_param_6,
+		 uint32_t resp_data_len, struct io96b_mb_resp *resp)
+{
+	int i;
+	int ret;
+	uint32_t cmd_req, cmd_resp;
+
+	/* Initialized zeros for responses*/
+	resp->cmd_resp_status = 0;
+	resp->cmd_resp_data_0 = 0;
+	resp->cmd_resp_data_1 = 0;
+	resp->cmd_resp_data_2 = 0;
+
+	/* Ensure CMD_REQ is cleared before write any command request */
+	ret = wait_for_bit((const void *)(io96b_csr_addr + IOSSM_CMD_REQ_OFFSET),
+			   GENMASK(31, 0), 0, 10000);
+
+	if (ret != 0) {
+		ERROR("%s: CMD_REQ not ready\n", __func__);
+		return -1;
+	}
+
+	/* Write CMD_PARAM_* */
+	for (i = 0; i < 6 ; i++) {
+		switch (i) {
+		case 0:
+			if (cmd_param_0 != 0) {
+				mmio_write_32(io96b_csr_addr + IOSSM_CMD_PARAM_0_OFFSET,
+					      cmd_param_0);
+			}
+			break;
+		case 1:
+			if (cmd_param_1 != 0) {
+				mmio_write_32(io96b_csr_addr + IOSSM_CMD_PARAM_1_OFFSET,
+					      cmd_param_1);
+			}
+			break;
+		case 2:
+			if (cmd_param_2 != 0) {
+				mmio_write_32(io96b_csr_addr + IOSSM_CMD_PARAM_2_OFFSET,
+					      cmd_param_2);
+			}
+			break;
+		case 3:
+			if (cmd_param_3 != 0) {
+				mmio_write_32(io96b_csr_addr + IOSSM_CMD_PARAM_3_OFFSET,
+					      cmd_param_3);
+			}
+			break;
+		case 4:
+			if (cmd_param_4 != 0) {
+				mmio_write_32(io96b_csr_addr + IOSSM_CMD_PARAM_4_OFFSET,
+					      cmd_param_4);
+			}
+			break;
+		case 5:
+			if (cmd_param_5 != 0) {
+				mmio_write_32(io96b_csr_addr + IOSSM_CMD_PARAM_5_OFFSET,
+					      cmd_param_5);
+			}
+			break;
+		case 6:
+			if (cmd_param_6 != 0) {
+				mmio_write_32(io96b_csr_addr + IOSSM_CMD_PARAM_6_OFFSET,
+					      cmd_param_6);
+			}
+			break;
+		default:
+			ERROR("IOSSM: %s: Invalid command parameter\n", __func__);
+		}
+	}
+
+	/* Write CMD_REQ (IP_TYPE, IP_INSTANCE_ID, CMD_TYPE and CMD_OPCODE) */
+	cmd_req = (usr_cmd_opcode << 0) | (usr_cmd_type << 16) | (instance_id << 24) |
+		  (ip_type << 29);
+	mmio_write_32(io96b_csr_addr + IOSSM_CMD_REQ_OFFSET, cmd_req);
+	INFO("IOSSM: %s: Write 0x%x to IOSSM_CMD_REQ_OFFSET 0x%llx\n",
+		__func__, cmd_req, io96b_csr_addr + IOSSM_CMD_REQ_OFFSET);
+
+	/* Read CMD_RESPONSE_READY in CMD_RESPONSE_STATUS*/
+	ret = wait_for_bit((const void *)(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET),
+			   IOSSM_STATUS_COMMAND_RESPONSE_READY, 1, 10000);
+
+	if (ret != 0) {
+		ERROR("%s: CMD_RESPONSE ERROR:\n", __func__);
+		cmd_resp = (io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET);
+		ERROR("%s: STATUS_GENERAL_ERROR: 0x%x\n", __func__, (cmd_resp >> 1) & 0xF);
+		ERROR("%s: STATUS_CMD_RESPONSE_ERROR: 0x%x\n", __func__, (cmd_resp >> 5) & 0x7);
+	}
+
+	/* read CMD_RESPONSE_STATUS*/
+	resp->cmd_resp_status = mmio_read_32(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET);
+	INFO("IOSSM: %s: CMD_RESPONSE_STATUS 0x%llx: 0x%x\n",
+		__func__, io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET, resp->cmd_resp_status);
+
+	/* read CMD_RESPONSE_DATA_* */
+	for (i = 0; i < resp_data_len; i++) {
+		switch (i) {
+		case 0:
+			resp->cmd_resp_data_0 =
+				mmio_read_32(io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_0_OFFSET);
+
+			break;
+		case 1:
+			resp->cmd_resp_data_1 =
+				mmio_read_32(io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_1_OFFSET);
+
+			break;
+		case 2:
+			resp->cmd_resp_data_2 =
+				mmio_read_32(io96b_csr_addr + IOSSM_CMD_RESPONSE_DATA_2_OFFSET);
+			break;
+		default:
+			ERROR("%s: Invalid response data\n", __func__);
+		}
+	}
+
+	resp->cmd_resp_status = mmio_read_32(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET);
+	INFO("IOSSM: %s: CMD_RESPONSE_STATUS 0x%llx: 0x%x\n",
+		__func__, io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET, resp->cmd_resp_status);
+
+	/* write CMD_RESPONSE_READY = 0 */
+	mmio_clrbits_32(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET,
+			IOSSM_STATUS_COMMAND_RESPONSE_READY);
+
+	resp->cmd_resp_status = mmio_read_32(io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET);
+	INFO("IOSSM: %s: CMD_RESPONSE_READY 0x%llx: 0x%x\n",
+		__func__, io96b_csr_addr + IOSSM_CMD_RESPONSE_STATUS_OFFSET, resp->cmd_resp_status);
+
+	return 0;
+}
+
+/*
+ * Initial function to be called to set memory interface IP type and instance ID
+ * IP type and instance ID need to be determined before sending mailbox command
+ */
+void io96b_mb_init(struct io96b_info *io96b_ctrl)
+{
+	struct io96b_mb_resp usr_resp;
+	uint8_t ip_type_ret, instance_id_ret;
+	int i, j, k;
+
+	for (i = 0; i < io96b_ctrl->num_instance; i++) {
+		switch (i) {
+		case 0:
+			/* Get memory interface IP type & instance ID (IP identifier) */
+			io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr, 0, 0,
+				     CMD_GET_SYS_INFO, GET_MEM_INTF_INFO, 0, 0,
+				     0, 0, 0, 0, 0, 2, &usr_resp);
+			/* Retrieve number of memory interface(s) */
+			io96b_ctrl->io96b_0.mb_ctrl.num_mem_interface =
+				IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status) & 0x3;
+
+			/* Retrieve memory interface IP type and instance ID (IP identifier) */
+			j = 0;
+			for (k = 0; k < MAX_MEM_INTERFACES_SUPPORTED; k++) {
+				switch (k) {
+				case 0:
+					ip_type_ret = (usr_resp.cmd_resp_data_0 >> 29) & 0x7;
+					instance_id_ret = (usr_resp.cmd_resp_data_0 >> 24) & 0x1F;
+					break;
+				case 1:
+					ip_type_ret = (usr_resp.cmd_resp_data_1 >> 29) & 0x7;
+					instance_id_ret = (usr_resp.cmd_resp_data_1 >> 24) & 0x1F;
+					break;
+				}
+
+				if (ip_type_ret != 0) {
+					io96b_ctrl->io96b_0.mb_ctrl.ip_type[j] = ip_type_ret;
+					io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[j] =
+						instance_id_ret;
+					j++;
+				}
+			}
+			break;
+		case 1:
+			/* Get memory interface IP type and instance ID (IP identifier) */
+			io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr, 0, 0, CMD_GET_SYS_INFO,
+				     GET_MEM_INTF_INFO, 0, 0, 0, 0, 0, 0, 0, 2, &usr_resp);
+
+			/* Retrieve number of memory interface(s) */
+			io96b_ctrl->io96b_1.mb_ctrl.num_mem_interface =
+				IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status) & 0x3;
+
+			/* Retrieve memory interface IP type and instance ID (IP identifier) */
+			j = 0;
+			for (k = 0; k < MAX_MEM_INTERFACES_SUPPORTED; k++) {
+				switch (k) {
+				case 0:
+					ip_type_ret = (usr_resp.cmd_resp_data_0 >> 29) & 0x7;
+					instance_id_ret = (usr_resp.cmd_resp_data_0 >> 24) & 0x1F;
+					break;
+				case 1:
+					ip_type_ret = (usr_resp.cmd_resp_data_1 >> 29) & 0x7;
+					instance_id_ret = (usr_resp.cmd_resp_data_1 >> 24) & 0x1F;
+					break;
+				}
+
+				if (ip_type_ret != 0) {
+					io96b_ctrl->io96b_1.mb_ctrl.ip_type[j] = ip_type_ret;
+					io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[j] =
+						instance_id_ret;
+					j++;
+				}
+			}
+			break;
+		}
+
+	}
+}
+
+static inline void hang(void)
+{
+	ERROR("IOSSM: %s: system is going to die :(\n", __func__);
+	while (1)
+		;
+}
+
+int io96b_cal_status(phys_addr_t addr)
+{
+	int cal_busy_status, cal_success_status;
+	phys_addr_t status_addr = addr + IOSSM_STATUS_OFFSET;
+
+	/* Ensure calibration busy status */
+	cal_busy_status = wait_for_bit((const void *)status_addr, IOSSM_STATUS_CAL_BUSY,
+					false, 15000);
+	if (cal_busy_status != 0) {
+		ERROR("IOSSM: One or more EMIF instances are busy with calibration\n");
+		return -EBUSY;
+	}
+
+	/* Calibration success status check */
+	NOTICE("IOSSM: Calibration success status check...\n");
+	cal_success_status = wait_for_bit((const void *)status_addr, IOSSM_STATUS_CAL_SUCCESS,
+					  true, 15000);
+	if (cal_success_status != 0) {
+		ERROR("IOSSM: One/more EMIF instances either failed to calibrate/not completed\n");
+		return -EBUSY;
+	}
+
+	NOTICE("IOSSM: All EMIF instances within the IO96 have calibrated successfully!\n");
+	return 0;
+}
+
+void init_mem_cal(struct io96b_info *io96b_ctrl)
+{
+	int count, i, ret;
+
+	/* Initialize overall calibration status */
+	io96b_ctrl->overall_cal_status = false;
+
+	/* Check initial calibration status for the assigned IO96B */
+	count = 0;
+	for (i = 0; i < io96b_ctrl->num_instance; i++) {
+		switch (i) {
+		case 0:
+			ret = io96b_cal_status(io96b_ctrl->io96b_0.io96b_csr_addr);
+			if (ret != 0) {
+				io96b_ctrl->io96b_0.cal_status = false;
+				ERROR("%s: Initial DDR calibration IO96B_0 failed %d\n",
+					__func__, ret);
+				break;
+			}
+			io96b_ctrl->io96b_0.cal_status = true;
+			INFO("IOSSM: %s: Initial DDR calibration IO96B_0 succeed\n", __func__);
+			count++;
+			break;
+		case 1:
+			ret = io96b_cal_status(io96b_ctrl->io96b_1.io96b_csr_addr);
+			if (ret != 0) {
+				io96b_ctrl->io96b_1.cal_status = false;
+				ERROR("%s: Initial DDR calibration IO96B_1 failed %d\n",
+					__func__, ret);
+				break;
+			}
+			io96b_ctrl->io96b_1.cal_status = true;
+			INFO("IOSSM: %s: Initial DDR calibration IO96B_1 succeed\n", __func__);
+			count++;
+			break;
+		}
+	}
+
+	if (count == io96b_ctrl->num_instance)
+		io96b_ctrl->overall_cal_status = true;
+}
+
+/*
+ * Trying 3 times re-calibration if initial calibration failed
+ */
+int trig_mem_cal(struct io96b_info *io96b_ctrl)
+{
+	struct io96b_mb_resp usr_resp;
+	bool recal_success;
+	int i;
+	uint8_t cal_stat;
+
+	for (i = 0; i < io96b_ctrl->num_instance; i++) {
+		switch (i) {
+		case 0:
+			if (!(io96b_ctrl->io96b_0.cal_status)) {
+				/* Get the memory calibration status for first memory interface */
+				io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr, 0, 0,
+					     CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS, 0,
+					     0, 0, 0, 0, 0, 0, 2, &usr_resp);
+
+				recal_success = false;
+
+				/* Re-calibration first memory interface with failed calibration */
+				for (i = 0; i < 3; i++) {
+					cal_stat = usr_resp.cmd_resp_data_0 & GENMASK(2, 0);
+					if (cal_stat < 0x2) {
+						recal_success = true;
+						break;
+					}
+					io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr,
+						     io96b_ctrl->io96b_0.mb_ctrl.ip_type[0],
+						     io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[0],
+						     CMD_TRIG_MEM_CAL_OP, TRIG_MEM_CAL, 0, 0, 0, 0,
+						     0, 0, 0, 2, &usr_resp);
+					mdelay(1000);
+					io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr, 0, 0,
+						     CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS,
+						     0, 0, 0, 0, 0, 0, 0, 2, &usr_resp);
+				}
+
+				if (!recal_success) {
+					ERROR("%s: Error as SDRAM calibration failed\n", __func__);
+					hang();
+				}
+
+				/* Get the memory calibration status for second memory interface */
+				io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr, 0, 0,
+					     CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS, 0, 0, 0,
+					     0, 0, 0, 0, 2, &usr_resp);
+
+				recal_success = false;
+
+				/* Re-calibration second memory interface with failed calibration*/
+				for (i = 0; i < 3; i++) {
+					cal_stat = usr_resp.cmd_resp_data_1 & GENMASK(2, 0);
+					if (cal_stat < 0x2) {
+						recal_success = true;
+						break;
+					}
+					io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr,
+						     io96b_ctrl->io96b_0.mb_ctrl.ip_type[1],
+						     io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[1],
+						     CMD_TRIG_MEM_CAL_OP, TRIG_MEM_CAL, 0, 0, 0, 0,
+						     0, 0, 0, 2, &usr_resp);
+					mdelay(1000);
+					io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr, 0, 0,
+						     CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS,
+						     0, 0, 0, 0, 0, 0, 0, 2, &usr_resp);
+				}
+
+				if (!recal_success) {
+					ERROR("IOSSMM: Error as SDRAM calibration failed\n");
+					hang();
+				}
+
+				io96b_ctrl->io96b_0.cal_status = true;
+			}
+			break;
+		case 1:
+			if (!(io96b_ctrl->io96b_1.cal_status)) {
+				/* Get the memory calibration status for first memory interface */
+				io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr, 0, 0,
+					     CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS, 0,
+					     0, 0, 0, 0, 0, 0, 2, &usr_resp);
+
+				recal_success = false;
+
+				/* Re-calibration first memory interface with failed calibration */
+				for (i = 0; i < 3; i++) {
+					cal_stat = usr_resp.cmd_resp_data_0 & GENMASK(2, 0);
+					if (cal_stat < 0x2) {
+						recal_success = true;
+						break;
+					}
+					io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr,
+						     io96b_ctrl->io96b_1.mb_ctrl.ip_type[0],
+						     io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[0],
+						     CMD_TRIG_MEM_CAL_OP, TRIG_MEM_CAL, 0, 0, 0, 0,
+						     0, 0, 0, 2, &usr_resp);
+					mdelay(1000);
+					io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr, 0, 0,
+						     CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS,
+						     0, 0, 0, 0, 0, 0, 0, 2, &usr_resp);
+				}
+
+				if (!recal_success) {
+					ERROR("IOSSM: Error as SDRAM calibration failed\n");
+					hang();
+				}
+
+				/* Get the memory calibration status for second memory interface */
+				io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr, 0, 0,
+					     CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS, 0, 0, 0,
+					     0, 0, 0, 0, 2, &usr_resp);
+
+				recal_success = false;
+
+				/* Re-calibration second memory interface with failed calibration*/
+				for (i = 0; i < 3; i++) {
+					cal_stat = usr_resp.cmd_resp_data_0 & GENMASK(2, 0);
+					if (cal_stat < 0x2) {
+						recal_success = true;
+						break;
+					}
+					io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr,
+						     io96b_ctrl->io96b_1.mb_ctrl.ip_type[1],
+						     io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[1],
+						     CMD_TRIG_MEM_CAL_OP, TRIG_MEM_CAL, 0, 0, 0, 0,
+						     0, 0, 0, 2, &usr_resp);
+					mdelay(1000);
+					io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr, 0, 0,
+						     CMD_TRIG_MEM_CAL_OP, GET_MEM_CAL_STATUS,
+						     0, 0, 0, 0, 0, 0, 0, 2, &usr_resp);
+				}
+
+				if (!recal_success) {
+					ERROR("IOSSM: Error as SDRAM calibration failed\n");
+					hang();
+				}
+
+				io96b_ctrl->io96b_1.cal_status = true;
+			}
+			break;
+		}
+	}
+
+	if (io96b_ctrl->io96b_0.cal_status && io96b_ctrl->io96b_1.cal_status) {
+		INFO("IOSSM: %s: Overall SDRAM calibration success\n", __func__);
+		io96b_ctrl->overall_cal_status = true;
+	}
+
+	return 0;
+}
+
+int get_mem_technology(struct io96b_info *io96b_ctrl)
+{
+	struct io96b_mb_resp usr_resp;
+	int i, j;
+	uint8_t ddr_type_ret;
+
+	/* Initialize ddr type */
+	io96b_ctrl->ddr_type = ddr_type_list[6];
+
+	/* Get and ensure all memory interface(s) same DDR type */
+	for (i = 0; i < io96b_ctrl->num_instance; i++) {
+		switch (i) {
+		case 0:
+			for (j = 0; j < io96b_ctrl->io96b_0.mb_ctrl.num_mem_interface; j++) {
+				io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr,
+					     io96b_ctrl->io96b_0.mb_ctrl.ip_type[j],
+					     io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[j],
+					     CMD_GET_MEM_INFO, GET_MEM_TECHNOLOGY, 0, 0, 0, 0,
+					     0, 0, 0, 0, &usr_resp);
+
+				ddr_type_ret =
+					IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
+					& GENMASK(2, 0);
+
+				if (strcmp(io96b_ctrl->ddr_type, "UNKNOWN") == 0)
+					io96b_ctrl->ddr_type = ddr_type_list[ddr_type_ret];
+
+				if (ddr_type_list[ddr_type_ret] != io96b_ctrl->ddr_type) {
+					ERROR("IOSSM: Mismatch DDR type on IO96B_0\n");
+					return -ENOEXEC;
+				}
+			}
+			break;
+		case 1:
+			for (j = 0; j < io96b_ctrl->io96b_1.mb_ctrl.num_mem_interface; j++) {
+				io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr,
+					     io96b_ctrl->io96b_1.mb_ctrl.ip_type[j],
+					     io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[j],
+					     CMD_GET_MEM_INFO, GET_MEM_TECHNOLOGY, 0, 0, 0,
+					     0, 0, 0, 0, 0, &usr_resp);
+
+				ddr_type_ret =
+					IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
+					& GENMASK(2, 0);
+
+				if (strcmp(io96b_ctrl->ddr_type, "UNKNOWN") == 0)
+					io96b_ctrl->ddr_type = ddr_type_list[ddr_type_ret];
+
+				if (ddr_type_list[ddr_type_ret] != io96b_ctrl->ddr_type) {
+					ERROR("IOSSM: Mismatch DDR type on IO96B_1\n");
+					return -ENOEXEC;
+				}
+			}
+			break;
+		}
+	}
+
+	return 0;
+}
+
+int get_mem_width_info(struct io96b_info *io96b_ctrl)
+{
+	struct io96b_mb_resp usr_resp;
+	int i, j;
+	uint16_t memory_size = 0U;
+	uint16_t total_memory_size = 0U;
+
+	/* Get all memory interface(s) total memory size on all instance(s) */
+	for (i = 0; i < io96b_ctrl->num_instance; i++) {
+		switch (i) {
+		case 0:
+			memory_size = 0;
+			for (j = 0; j < io96b_ctrl->io96b_0.mb_ctrl.num_mem_interface; j++) {
+				io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr,
+					     io96b_ctrl->io96b_0.mb_ctrl.ip_type[j],
+					     io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[j],
+					     CMD_GET_MEM_INFO, GET_MEM_WIDTH_INFO, 0, 0, 0,
+					     0, 0, 0, 0, 2, &usr_resp);
+
+				memory_size = memory_size +
+						(usr_resp.cmd_resp_data_1 & GENMASK(7, 0));
+			}
+
+			if (memory_size == 0U) {
+				ERROR("IOSSM: %s: Failed to get valid memory size\n", __func__);
+				return -ENOEXEC;
+			}
+
+			io96b_ctrl->io96b_0.size = memory_size;
+
+			break;
+		case 1:
+			memory_size = 0;
+			for (j = 0; j < io96b_ctrl->io96b_1.mb_ctrl.num_mem_interface; j++) {
+				io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr,
+					     io96b_ctrl->io96b_1.mb_ctrl.ip_type[j],
+					     io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[j],
+					     CMD_GET_MEM_INFO, GET_MEM_WIDTH_INFO, 0, 0, 0,
+					     0, 0, 0, 0, 2, &usr_resp);
+
+				memory_size = memory_size +
+						(usr_resp.cmd_resp_data_1 & GENMASK(7, 0));
+			}
+
+			if (memory_size == 0U) {
+				ERROR("IOSSM: %s: Failed to get valid memory size\n", __func__);
+				return -ENOEXEC;
+			}
+
+			io96b_ctrl->io96b_1.size = memory_size;
+
+			break;
+		}
+
+		total_memory_size = total_memory_size + memory_size;
+	}
+
+	if (total_memory_size == 0U) {
+		ERROR("IOSSM: %s: Failed to get valid memory size\n", __func__);
+		return -ENOEXEC;
+	}
+
+	io96b_ctrl->overall_size = total_memory_size;
+
+	return 0;
+}
+
+int ecc_enable_status(struct io96b_info *io96b_ctrl)
+{
+	struct io96b_mb_resp usr_resp;
+	int i, j;
+	bool ecc_stat_set = false;
+	bool ecc_stat;
+
+	/* Initialize ECC status */
+	io96b_ctrl->ecc_status = false;
+
+	/* Get and ensure all memory interface(s) same ECC status */
+	for (i = 0; i < io96b_ctrl->num_instance; i++) {
+		switch (i) {
+		case 0:
+			for (j = 0; j < io96b_ctrl->io96b_0.mb_ctrl.num_mem_interface; j++) {
+				io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr,
+					     io96b_ctrl->io96b_0.mb_ctrl.ip_type[j],
+					     io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[j],
+					     CMD_TRIG_CONTROLLER_OP, ECC_ENABLE_STATUS, 0, 0,
+					     0, 0, 0, 0, 0, 0, &usr_resp);
+
+				ecc_stat = ((IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
+						& GENMASK(1, 0)) == 0 ? false : true);
+
+				if (!ecc_stat_set) {
+					io96b_ctrl->ecc_status = ecc_stat;
+					ecc_stat_set = true;
+				}
+
+				if (ecc_stat != io96b_ctrl->ecc_status) {
+					ERROR("IOSSM: %s: Mismatch DDR ECC status on IO96B_0\n",
+						__func__);
+					return -ENOEXEC;
+				}
+			}
+			break;
+		case 1:
+			for (j = 0; j < io96b_ctrl->io96b_1.mb_ctrl.num_mem_interface; j++) {
+				io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr,
+					     io96b_ctrl->io96b_1.mb_ctrl.ip_type[j],
+					     io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[j],
+					     CMD_TRIG_CONTROLLER_OP, ECC_ENABLE_STATUS, 0, 0,
+					     0, 0, 0, 0, 0, 0, &usr_resp);
+
+				ecc_stat = ((IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
+						& GENMASK(1, 0)) == 0 ? false : true);
+
+				if (!ecc_stat_set) {
+					io96b_ctrl->ecc_status = ecc_stat;
+					ecc_stat_set = true;
+				}
+
+				if (ecc_stat != io96b_ctrl->ecc_status) {
+					ERROR("%s: Mismatch DDR ECC status on IO96B_1\n"
+						, __func__);
+					return -ENOEXEC;
+				}
+			}
+			break;
+		}
+	}
+	return 0;
+}
+
+int bist_mem_init_start(struct io96b_info *io96b_ctrl)
+{
+	struct io96b_mb_resp usr_resp;
+	int i, j;
+	bool bist_start, bist_success;
+	uint32_t read_count;
+	uint32_t read_interval_ms;
+
+	/* Full memory initialization BIST performed on all memory interface(s) */
+	for (i = 0; i < io96b_ctrl->num_instance; i++) {
+		switch (i) {
+		case 0:
+			for (j = 0; j < io96b_ctrl->io96b_0.mb_ctrl.num_mem_interface; j++) {
+				bist_start = false;
+				bist_success = false;
+				read_interval_ms = 500U;
+
+				/* Start memory initialization BIST on full memory address */
+				io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr,
+					     io96b_ctrl->io96b_0.mb_ctrl.ip_type[j],
+					     io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[j],
+					     CMD_TRIG_CONTROLLER_OP, BIST_MEM_INIT_START, 0x40,
+					     0, 0, 0, 0, 0, 0, 0, &usr_resp);
+
+				bist_start =
+					(IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
+					& 1);
+
+				if (!bist_start) {
+					ERROR("IOSSM: %s: Failed to initialized memory on IO96B_0\n"
+					, __func__);
+					ERROR("IOSSM: %s: BIST_MEM_INIT_START Error code 0x%x\n",
+					__func__,
+					(IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
+					& GENMASK(2, 1)) > 0x1);
+					return -ENOEXEC;
+				}
+
+				/* Polling for the initiated memory initialization BIST status */
+				read_count = read_interval_ms / TIMEOUT;
+				while (!bist_success) {
+					io96b_mb_req(io96b_ctrl->io96b_0.io96b_csr_addr,
+						     io96b_ctrl->io96b_0.mb_ctrl.ip_type[j],
+						     io96b_ctrl->io96b_0.mb_ctrl.ip_instance_id[j],
+						     CMD_TRIG_CONTROLLER_OP, BIST_MEM_INIT_STATUS,
+						     0, 0, 0, 0, 0, 0, 0, 0, &usr_resp);
+
+					bist_success = (IOSSM_CMD_RESPONSE_DATA_SHORT
+							(usr_resp.cmd_resp_status) & 1);
+
+					if ((!bist_success) && (read_count == 0U)) {
+						ERROR("IOSSM: %s: Timeout init memory on IO96B_0\n"
+							, __func__);
+						ERROR("IOSSM: %s: BIST_MEM_INIT_STATUS Err code%x\n"
+							, __func__, (IOSSM_CMD_RESPONSE_DATA_SHORT
+							(usr_resp.cmd_resp_status)
+							& GENMASK(2, 1)) > 0x1);
+						return -ETIMEDOUT;
+					}
+					read_count--;
+					mdelay(read_interval_ms);
+				}
+			}
+
+			NOTICE("IOSSM: %s: Memory initialized successfully on IO96B_0\n", __func__);
+			break;
+
+		case 1:
+			for (j = 0; j < io96b_ctrl->io96b_1.mb_ctrl.num_mem_interface; j++) {
+				bist_start = false;
+				bist_success = false;
+				read_interval_ms = 500U;
+
+				/* Start memory initialization BIST on full memory address */
+				io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr,
+					     io96b_ctrl->io96b_1.mb_ctrl.ip_type[j],
+					     io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[j],
+					     CMD_TRIG_CONTROLLER_OP, BIST_MEM_INIT_START, 0x40,
+					     0, 0, 0, 0, 0, 0, 0, &usr_resp);
+
+				bist_start =
+					(IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
+					& 1);
+
+				if (!bist_start) {
+					ERROR("IOSSM: %s: Failed to initialized memory on IO96B_1\n"
+						, __func__);
+					ERROR("IOSSM: %s: BIST_MEM_INIT_START Error code 0x%x\n",
+					__func__,
+					(IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status)
+					& GENMASK(2, 1)) > 0x1);
+					return -ENOEXEC;
+				}
+
+				/* Polling for the initiated memory initialization BIST status */
+				read_count = read_interval_ms / TIMEOUT;
+				while (!bist_success) {
+					io96b_mb_req(io96b_ctrl->io96b_1.io96b_csr_addr,
+						     io96b_ctrl->io96b_1.mb_ctrl.ip_type[j],
+						     io96b_ctrl->io96b_1.mb_ctrl.ip_instance_id[j],
+						     CMD_TRIG_CONTROLLER_OP, BIST_MEM_INIT_STATUS,
+						     0, 0, 0, 0, 0, 0, 0, 0, &usr_resp);
+
+					bist_success = (IOSSM_CMD_RESPONSE_DATA_SHORT
+							(usr_resp.cmd_resp_status) & 1);
+
+					if ((!bist_success) && (read_count == 0U)) {
+						ERROR("IOSSM: %s: Timeout init memory on IO96B_1\n"
+							, __func__);
+						ERROR("IOSSM: %s: BIST_MEM_INIT_STATUS ErrCode %x\n"
+							, __func__, (IOSSM_CMD_RESPONSE_DATA_SHORT
+							(usr_resp.cmd_resp_status)
+							& GENMASK(2, 1)) > 0x1);
+						return -ETIMEDOUT;
+					}
+					read_count--;
+					mdelay(read_interval_ms);
+				}
+			}
+
+			NOTICE("IOSSM: %s: Memory initialized successfully on IO96B_1\n", __func__);
+			break;
+		}
+	}
+	return 0;
+}
diff --git a/plat/intel/soc/agilex5/soc/agilex5_pinmux.c b/plat/intel/soc/agilex5/soc/agilex5_pinmux.c
index 50d9e36..317b4d8 100644
--- a/plat/intel/soc/agilex5/soc/agilex5_pinmux.c
+++ b/plat/intel/soc/agilex5/soc/agilex5_pinmux.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -186,40 +187,72 @@
 	0x0000011c, 0x00000000
 };
 
-void config_fpgaintf_mod(void)
+static void config_fpgaintf_mod(void)
 {
-	mmio_write_32(SOCFPGA_SYSMGR(FPGAINTF_EN_2), 1<<8);
+	uint32_t fpgaintf_en_val;
+
+	/*
+	 * System manager FPGA interface enable2 register, disable individual
+	 * interfaces between the FPGA and HPS.
+	 */
+	fpgaintf_en_val = 0U;
+	if ((mmio_read_32(SOCFPGA_PINUMX_USEFPGA(NAND_USEFPGA)) & 0x01) != 0)
+		fpgaintf_en_val |= BIT(4);
+	if ((mmio_read_32(SOCFPGA_PINUMX_USEFPGA(SDMMC_USEFPGA)) & 0x01) != 0)
+		fpgaintf_en_val |= BIT(8);
+	if ((mmio_read_32(SOCFPGA_PINUMX_USEFPGA(SPIM0_USEFPGA)) & 0x01) != 0)
+		fpgaintf_en_val |= BIT(16);
+	if ((mmio_read_32(SOCFPGA_PINUMX_USEFPGA(SPIM1_USEFPGA)) & 0x01) != 0)
+		fpgaintf_en_val |= BIT(24);
+	mmio_write_32(SOCFPGA_SYSMGR(FPGAINTF_EN_2), fpgaintf_en_val);
+
+	/*
+	 * System manager FPGA interface enable3 register, disable individual
+	 * interfaces between the FPGA and HPS.
+	 */
+	fpgaintf_en_val = 0U;
+	if ((mmio_read_32(SOCFPGA_PINUMX_USEFPGA(EMAC0_USEFPGA)) & 0x01) != 0)
+		fpgaintf_en_val |= BIT(0);
+	if ((mmio_read_32(SOCFPGA_PINUMX_USEFPGA(EMAC1_USEFPGA)) & 0x01) != 0)
+		fpgaintf_en_val |= BIT(8);
+	if ((mmio_read_32(SOCFPGA_PINUMX_USEFPGA(EMAC2_USEFPGA)) & 0x01) != 0)
+		fpgaintf_en_val |= BIT(16);
+	mmio_write_32(SOCFPGA_SYSMGR(FPGAINTF_EN_3), fpgaintf_en_val);
 }
 
 void config_pinmux(handoff *hoff_ptr)
 {
-	unsigned int i;
+	uint32_t i;
 
-	mmio_write_32(PINMUX_HANDOFF_CONFIG_ADDR, PINMUX_HANDOFF_CONFIG_VAL);
-	for (i = 0; i < PINMUX_HANDOFF_ARRAY_SIZE(hoff_ptr->pinmux_sel_array); i += 2) {
-		mmio_write_32(AGX5_PINMUX_PIN0SEL +
-			hoff_ptr->pinmux_sel_array[i],
-			hoff_ptr->pinmux_sel_array[i + 1]);
+	/* Configure the pin selection */
+	for (i = 0; i < ARRAY_SIZE(hoff_ptr->pinmux_sel_array); i += 2) {
+		mmio_write_32(AGX5_PINMUX_PIN0SEL + hoff_ptr->pinmux_sel_array[i],
+			      hoff_ptr->pinmux_sel_array[i+1]);
 	}
 
-	config_fpgaintf_mod();
-}
-
-void config_peripheral(handoff *hoff_ptr)
-{
-
-	// TODO: This need to be update due to peripheral_pwr_gate_array handoff change
-	// Pending SDM to pass over handoff data
-	// unsigned int i;
+	/* Configure the pin control */
+	for (i = 0; i < ARRAY_SIZE(hoff_ptr->pinmux_io_array); i += 2) {
+		mmio_write_32(AGX5_PINMUX_IO0CTRL + hoff_ptr->pinmux_io_array[i],
+			      hoff_ptr->pinmux_io_array[i+1]);
+	}
 
-	// for (i = 0; i < 4; i += 2) {
-	//	mmio_write_32(AGX_EDGE_PERIPHERAL +
-	//	hoff_ptr->peripheral_pwr_gate_array[i],
-	//	hoff_ptr->peripheral_pwr_gate_array[i+1]);
-	// }
+	/*
+	 * Configure the FPGA use.
+	 * The actual generic handoff contains extra 4 elements, and these 4 elements
+	 * are not applicable to the Agilex5 platform. Writing these extra 4 elements
+	 * will cause the system to crash, so let's avoid writing them here.
+	 */
+	for (i = 0; i < (ARRAY_SIZE(hoff_ptr->pinmux_fpga_array) - 4); i += 2) {
+		mmio_write_32(AGX5_PINMUX_EMAC0_USEFPGA + hoff_ptr->pinmux_fpga_array[i],
+			      hoff_ptr->pinmux_fpga_array[i+1]);
+	}
 
+	/* Configure the IO delay */
+	for (i = 0; i < ARRAY_SIZE(hoff_ptr->pinmux_iodelay_array); i += 2) {
+		mmio_write_32(AGX5_PINMUX_IO0_DELAY + hoff_ptr->pinmux_iodelay_array[i],
+			      hoff_ptr->pinmux_iodelay_array[i+1]);
+	}
 
-	// TODO: This need to be update due to peripheral_pwr_gate_array handoff change
-	mmio_write_32(AGX5_PERIPHERAL,
-	hoff_ptr->peripheral_pwr_gate_array);
+	/* Enable/Disable individual interfaces between the FPGA and HPS */
+	config_fpgaintf_mod();
 }
diff --git a/plat/intel/soc/agilex5/soc/agilex5_power_manager.c b/plat/intel/soc/agilex5/soc/agilex5_power_manager.c
index 0d81970..ef3acf9 100644
--- a/plat/intel/soc/agilex5/soc/agilex5_power_manager.c
+++ b/plat/intel/soc/agilex5/soc/agilex5_power_manager.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2022-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,7 +14,7 @@
 #include "agilex5_power_manager.h"
 #include "socfpga_reset_manager.h"
 
-int wait_verify_fsm(uint16_t timeout, uint32_t peripheral_handoff)
+static int wait_verify_fsm(uint16_t timeout, uint32_t peripheral_handoff)
 {
 	uint32_t data = 0;
 	uint32_t count = 0;
@@ -38,7 +39,7 @@
 	return 0;
 }
 
-int pss_sram_power_off(handoff *hoff_ptr)
+static int pss_sram_power_off(handoff *hoff_ptr)
 {
 	int ret = 0;
 	uint32_t peripheral_handoff = 0;
@@ -66,7 +67,7 @@
 {
 	int ret = 0;
 
-	switch (hoff_ptr->header_magic) {
+	switch (hoff_ptr->peripheral_pwr_gate_magic) {
 	case HANDOFF_MAGIC_PERIPHERAL:
 		ret = pss_sram_power_off(hoff_ptr);
 		break;
diff --git a/plat/intel/soc/common/aarch64/plat_helpers.S b/plat/intel/soc/common/aarch64/plat_helpers.S
index cbd0121..b3d5665 100644
--- a/plat/intel/soc/common/aarch64/plat_helpers.S
+++ b/plat/intel/soc/common/aarch64/plat_helpers.S
@@ -1,5 +1,7 @@
 /*
  * Copyright (c) 2019-2023, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -96,18 +98,6 @@
 endfunc plat_my_core_pos
 
 func warm_reset_req
-#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
-	bl	plat_is_my_cpu_primary
-	cbnz	x0, warm_reset
-warm_reset:
-	mov_imm x1, PLAT_SEC_ENTRY
-	str	xzr, [x1]
-	mrs	x1, rmr_el3
-	orr	x1, x1, #0x02
-	msr	rmr_el3, x1
-	isb
-	dsb	sy
-#else
 	str	xzr, [x4]
 	bl	plat_is_my_cpu_primary
 	cbz	x0, cpu_in_wfi
@@ -121,22 +111,35 @@
 cpu_in_wfi:
 	wfi
 	b	cpu_in_wfi
-#endif
 endfunc warm_reset_req
 
-/* TODO: Zephyr warm reset test */
 #if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
 func plat_get_my_entrypoint
 	ldr	x4, =L2_RESET_DONE_REG
 	ldr	x5, [x4]
-	ldr	x1, =PLAT_L2_RESET_REQ
+
+	/* Check for warm reset request */
+	ldr	x1, =L2_RESET_DONE_STATUS
 	cmp	x1, x5
-	b.eq	zephyr_reset_req
+	b.eq	warm_reset_req
+
+	/* Check for SMP secondary cores boot request */
+	ldr	x1, =SMP_SEC_CORE_BOOT_REQ
+	cmp	x1, x5
+	b.eq	smp_request
+
+	/* Otherwise it is cold reset */
+	mov	x0, #0
+	ret
+smp_request:
+	/*
+	 * Return the address 'bl31_warm_entrypoint', which is passed to
+	 * 'psci_setup' routine as part of BL31 initialization.
+	 */
 	mov_imm	x1, PLAT_SEC_ENTRY
 	ldr	x0, [x1]
-	ret
-zephyr_reset_req:
-	ldr	x0, =0x00
+	/* Clear the mark up before return */
+	str	xzr, [x4]
 	ret
 endfunc plat_get_my_entrypoint
 #else
diff --git a/plat/intel/soc/common/drivers/ccu/ncore_ccu.c b/plat/intel/soc/common/drivers/ccu/ncore_ccu.c
index ca76b6a..931ffcf 100644
--- a/plat/intel/soc/common/drivers/ccu/ncore_ccu.c
+++ b/plat/intel/soc/common/drivers/ccu/ncore_ccu.c
@@ -1,10 +1,12 @@
 /*
  * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 #include <assert.h>
 #include <common/debug.h>
+#include <drivers/delay_timer.h>
 #include <errno.h>
 #include <lib/mmio.h>
 #include <platform_def.h>
@@ -16,7 +18,24 @@
 
 uint32_t poll_active_bit(uint32_t dir);
 
-#define SMMU_DMI			1
+#define SMMU_DMI					1
+#define CCU_DMI0_DMIUSMCMCR				SOCFPGA_CCU_NOC_REG_BASE + 0x7340
+#define CCU_DMI0_DMIUSMCMAR				SOCFPGA_CCU_NOC_REG_BASE + 0x7344
+#define CCU_DMI0_DMIUSMCMCR_MNTOP			GENMASK(3, 0)
+#define MAX_DISTRIBUTED_MEM_INTERFACE			2
+#define FLUSH_ALL_ENTRIES				0x4
+#define CCU_DMI0_DMIUSMCMCR_ARRAY_ID			GENMASK(21, 16)
+#define ARRAY_ID_TAG					0x0
+#define ARRAY_ID_DATA					0x1
+#define CACHE_OPERATION_DONE				BIT(0)
+#define TIMEOUT_200MS					200
+
+#define __bf_shf(x)					(__builtin_ffsll(x) - 1)
+
+#define FIELD_PREP(_mask, _val)						\
+	({ \
+		((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask);	\
+	})
 
 #if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
 ncore_ccu_reg_t ncore_ccu_modules[] = {
@@ -632,3 +651,61 @@
 	mmio_write_32(SOCFPGA_SYSMGR(TSN_TBU_STREAM_CTRL_REG_3_TSN1), ENABLE_STREAMID);
 	mmio_write_32(SOCFPGA_SYSMGR(TSN_TBU_STREAM_CTRL_REG_3_TSN2), ENABLE_STREAMID);
 }
+
+#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
+/* TODO: Temp added this here*/
+static int poll_idle_status(uint32_t addr, uint32_t mask, uint32_t match, uint32_t delay_ms)
+{
+	int time_out = delay_ms;
+
+	while (time_out-- > 0) {
+
+		if ((mmio_read_32(addr) & mask) == match) {
+			return 0;
+		}
+		udelay(1000);
+	}
+
+	return -ETIMEDOUT;
+}
+
+int flush_l3_dcache(void)
+{
+	int i;
+	int ret = 0;
+
+	/* Flushing all entries in CCU system memory cache */
+	for (i = 0; i < MAX_DISTRIBUTED_MEM_INTERFACE; i++) {
+		mmio_write_32(FIELD_PREP(CCU_DMI0_DMIUSMCMCR_MNTOP, FLUSH_ALL_ENTRIES) |
+			   FIELD_PREP(CCU_DMI0_DMIUSMCMCR_ARRAY_ID, ARRAY_ID_TAG),
+			   (uintptr_t)(CCU_DMI0_DMIUSMCMCR + (i * 0x1000)));
+
+		/* Wait for cache maintenance operation done */
+		ret = poll_idle_status((CCU_DMI0_DMIUSMCMAR +
+				(i * 0x1000)), CACHE_OPERATION_DONE,
+				CACHE_OPERATION_DONE, TIMEOUT_200MS);
+
+		if (ret != 0) {
+			VERBOSE("%s: Timeout while waiting for flushing tag in DMI%d done\n",
+					__func__, i);
+			return ret;
+		}
+
+		mmio_write_32(FIELD_PREP(CCU_DMI0_DMIUSMCMCR_MNTOP, FLUSH_ALL_ENTRIES) |
+			   FIELD_PREP(CCU_DMI0_DMIUSMCMCR_ARRAY_ID, ARRAY_ID_DATA),
+			   (uintptr_t)(CCU_DMI0_DMIUSMCMCR + (i * 0x1000)));
+
+		/* Wait for cache maintenance operation done */
+		ret = poll_idle_status((CCU_DMI0_DMIUSMCMAR +
+				(i * 0x1000)), CACHE_OPERATION_DONE,
+				CACHE_OPERATION_DONE, TIMEOUT_200MS);
+
+		if (ret != 0) {
+			VERBOSE("%s: Timeout while waiting for flushing data in DMI%d done\n",
+					__func__, i);
+		}
+	}
+
+	return ret;
+}
+#endif
diff --git a/plat/intel/soc/common/drivers/ccu/ncore_ccu.h b/plat/intel/soc/common/drivers/ccu/ncore_ccu.h
index e00c4b7..a89c098 100644
--- a/plat/intel/soc/common/drivers/ccu/ncore_ccu.h
+++ b/plat/intel/soc/common/drivers/ccu/ncore_ccu.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -452,5 +453,6 @@
 uint32_t init_ncore_ccu(void);
 void ncore_enable_ocram_firewall(void);
 void setup_smmu_stream_id(void);
+int flush_l3_dcache(void);
 
 #endif
diff --git a/plat/intel/soc/common/include/platform_def.h b/plat/intel/soc/common/include/platform_def.h
index 1946898..08ab5df 100644
--- a/plat/intel/soc/common/include/platform_def.h
+++ b/plat/intel/soc/common/include/platform_def.h
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
  * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -28,26 +29,26 @@
 /* Magic word to indicate L2 reset is completed */
 #define L2_RESET_DONE_STATUS			0x1228E5E7
 
+/* Magic word to differentiate for SMP secondary core boot request */
+#define SMP_SEC_CORE_BOOT_REQ			0x1228E5E8
+
 /* Define next boot image name and offset */
 /* Get non-secure image entrypoint for BL33. Zephyr and Linux */
-#if	PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
-
-#ifndef PRELOADED_BL33_BASE
-#define PLAT_NS_IMAGE_OFFSET			0x80200000
-#else
+#ifdef PRELOADED_BL33_BASE
 #define PLAT_NS_IMAGE_OFFSET			PRELOADED_BL33_BASE
-#endif
-#define PLAT_HANDOFF_OFFSET 0x0003F000
-
+#else
+#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
+#define PLAT_NS_IMAGE_OFFSET			0x80200000
 #else
 #define PLAT_NS_IMAGE_OFFSET			0x10000000
-#define PLAT_HANDOFF_OFFSET			0xFFE3F000
 #endif
+#endif /* #if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5 */
 
 #define PLAT_QSPI_DATA_BASE			(0x3C00000)
 #define PLAT_NAND_DATA_BASE			(0x0200000)
 #define PLAT_SDMMC_DATA_BASE			(0x0)
 
+
 /*******************************************************************************
  * Platform binary types for linking
  ******************************************************************************/
diff --git a/plat/intel/soc/common/include/socfpga_handoff.h b/plat/intel/soc/common/include/socfpga_handoff.h
index b2913c7..7e1d0c0 100644
--- a/plat/intel/soc/common/include/socfpga_handoff.h
+++ b/plat/intel/soc/common/include/socfpga_handoff.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,12 +11,12 @@
 #define HANDOFF_MAGIC_HEADER			0x424f4f54	/* BOOT */
 #define HANDOFF_MAGIC_PINMUX_SEL		0x504d5558	/* PMUX */
 #define HANDOFF_MAGIC_IOCTLR			0x494f4354	/* IOCT */
-#define HANDOFF_MAGIC_FPGA				0x46504741	/* FPGA */
+#define HANDOFF_MAGIC_FPGA			0x46504741	/* FPGA */
 #define HANDOFF_MAGIC_IODELAY			0x444c4159	/* DLAY */
-#define HANDOFF_MAGIC_CLOCK				0x434c4b53	/* CLKS */
-#define HANDOFF_MAGIC_MISC				0x4d495343	/* MISC */
+#define HANDOFF_MAGIC_CLOCK			0x434c4b53	/* CLKS */
+#define HANDOFF_MAGIC_MISC			0x4d495343	/* MISC */
 #define HANDOFF_MAGIC_PERIPHERAL		0x50455249	/* PERIPHERAL */
-#define HANDOFF_MAGIC_DDR				0x5344524d	/* DDR */
+#define HANDOFF_MAGIC_DDR			0x5344524d	/* DDR */
 
 #include <socfpga_plat_def.h>
 
@@ -126,6 +127,8 @@
 	uint32_t	clock_magic;
 	uint32_t	clock_length;
 	uint32_t	_pad_0x588_0x590[2];
+
+	/* main group PLL */
 	uint32_t	main_pll_nocclk;
 	uint32_t	main_pll_nocdiv;
 	uint32_t	main_pll_pllglob;
@@ -135,6 +138,8 @@
 	uint32_t	main_pll_pllc2;
 	uint32_t	main_pll_pllc3;
 	uint32_t	main_pll_pllm;
+
+	/* peripheral group PLL */
 	uint32_t	per_pll_emacctl;
 	uint32_t	per_pll_gpiodiv;
 	uint32_t	per_pll_pllglob;
@@ -144,29 +149,25 @@
 	uint32_t	per_pll_pllc2;
 	uint32_t	per_pll_pllc3;
 	uint32_t	per_pll_pllm;
+
+	/* control group */
 	uint32_t	alt_emacactr;
 	uint32_t	alt_emacbctr;
 	uint32_t	alt_emacptpctr;
 	uint32_t	alt_gpiodbctr;
-	uint32_t	alt_sdmmcctr;
 	uint32_t	alt_s2fuser0ctr;
 	uint32_t	alt_s2fuser1ctr;
 	uint32_t	alt_psirefctr;
-	/* TODO: Temp added for clk manager. */
-	uint32_t	qspi_clk_khz;
+	uint32_t	alt_usb31ctr;
+	uint32_t	alt_dsuctr;
+	uint32_t	alt_core01ctr;
+	uint32_t	alt_core23ctr;
+	uint32_t	alt_core2ctr;
+	uint32_t	alt_core3ctr;
 	uint32_t	hps_osc_clk_hz;
 	uint32_t	fpga_clk_hz;
-	/* TODO: Temp added for clk manager. */
-	uint32_t	ddr_reset_type;
-	/* TODO: Temp added for clk manager. */
-	uint32_t	hps_status_coldreset;
-	/* TODO: Temp remove due to add in extra handoff data */
-	//uint32_t	_pad_0x604_0x610[3];
+	uint32_t	_pad_0x604_0x610[3];
 #endif
-	/* misc configuration */
-	uint32_t	misc_magic;
-	uint32_t	misc_length;
-	uint32_t	_pad_0x618_0x620[2];
 
 #if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
 	/* peripheral configuration - select */
@@ -179,7 +180,7 @@
 	uint32_t	ddr_magic;
 	uint32_t	ddr_length;
 	uint32_t	_pad_0x1C_0x20[2];
-	uint32_t	ddr_array[4];	/* offset, value */
+	uint32_t	ddr_config;	/* BIT[0]-Dual Port. BIT[1]-Dual EMIF */
 #endif
 } handoff;
 
diff --git a/plat/intel/soc/common/include/socfpga_private.h b/plat/intel/soc/common/include/socfpga_private.h
index 041c282..a0d4180 100644
--- a/plat/intel/soc/common/include/socfpga_private.h
+++ b/plat/intel/soc/common/include/socfpga_private.h
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
diff --git a/plat/intel/soc/common/soc/socfpga_mailbox.c b/plat/intel/soc/common/soc/socfpga_mailbox.c
index 74ecc95..5d31e99 100644
--- a/plat/intel/soc/common/soc/socfpga_mailbox.c
+++ b/plat/intel/soc/common/soc/socfpga_mailbox.c
@@ -168,7 +168,7 @@
 		}
 
 		if (MBOX_RESP_ERR(resp_data) > 0U) {
-			INFO("Error in response: %x\n", resp_data);
+			INFO("SDM response: Return Code: 0x%x\n", MBOX_RESP_ERR(resp_data));
 			return -MBOX_RESP_ERR(resp_data);
 		}
 
@@ -337,7 +337,7 @@
 			}
 
 			if (MBOX_RESP_ERR(resp_data) > 0U) {
-				INFO("Error in response: %x\n", resp_data);
+				INFO("SDM response: Return Code: 0x%x\n", MBOX_RESP_ERR(resp_data));
 				return -MBOX_RESP_ERR(resp_data);
 			}
 
@@ -652,7 +652,7 @@
 
 	res = response[RECONFIG_STATUS_SOFTFUNC_STATUS];
 	if ((res & SOFTFUNC_STATUS_SEU_ERROR) != 0U) {
-		ERROR("SoftFunction Status SEU ERROR\n");
+		return MBOX_CFGSTAT_STATE_ERROR_HARDWARE;
 	}
 
 	if ((res & SOFTFUNC_STATUS_CONF_DONE) == 0U) {
diff --git a/plat/intel/soc/common/soc/socfpga_reset_manager.c b/plat/intel/soc/common/soc/socfpga_reset_manager.c
index cb4a210..c7d7076 100644
--- a/plat/intel/soc/common/soc/socfpga_reset_manager.c
+++ b/plat/intel/soc/common/soc/socfpga_reset_manager.c
@@ -76,7 +76,7 @@
 			RSTMGR_FIELD(PER0, DMAIF6) |
 			RSTMGR_FIELD(PER0, DMAIF7));
 
-#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX
+#if (PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX) || (PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5)
 	mmio_clrbits_32(SOCFPGA_RSTMGR(BRGMODRST),
 			RSTMGR_FIELD(BRG, MPFE));
 #endif
@@ -484,6 +484,11 @@
 				(~brg_lst & (RSTMGR_BRGMODRST_SOC2FPGA
 				| RSTMGR_BRGMODRST_LWHPS2FPGA))
 				| RSTMGR_BRGMODRST_SOC2FPGA);
+
+		/* Set System Manager soc bridge control register[soc2fpga_ready_latency_enable] = 1 */
+		VERBOSE("Set SOC soc2fpga_ready_latency_enable ...\n");
+		mmio_setbits_32(SOCFPGA_SYSMGR(FPGA_BRIDGE_CTRL),
+			SYSMGR_SOC_BRIDGE_CTRL_EN);
 	}
 
 /**************** LWSOCFPGA ****************/
@@ -567,6 +572,11 @@
 				((~brg_lst & (RSTMGR_BRGMODRST_SOC2FPGA
 				| RSTMGR_BRGMODRST_LWHPS2FPGA)))
 				| RSTMGR_BRGMODRST_LWHPS2FPGA);
+
+		/* Set System Manager lwsoc bridge control register[lwsoc2fpga_ready_latency_enable] = 1 */
+		VERBOSE("Set LWSOC lwsoc2fpga_ready_latency_enable ...\n");
+		mmio_setbits_32(SOCFPGA_SYSMGR(FPGA_BRIDGE_CTRL),
+			SYSMGR_LWSOC_BRIDGE_CTRL_EN);
 	}
 #else
 	if (brg_mask != 0U) {
@@ -580,9 +590,6 @@
 		/* Wait until idle ack becomes 0 */
 		ret_hps = poll_idle_status(SOCFPGA_SYSMGR(NOC_IDLEACK),
 				       noc_mask, 0, 1000);
-		if (ret_hps < 0) {
-			ERROR("S2F bridge enable: Timeout idle ack\n");
-		}
 	}
 #endif
 
@@ -958,6 +965,11 @@
 		mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST),
 			RSTMGR_BRGMODRST_SOC2FPGA);
 
+		/* Clear System Manager soc bridge control register[soc2fpga_ready_latency_enable] = 1 */
+		VERBOSE("Clear SOC soc2fpga_ready_latency_enable ...\n");
+		mmio_clrbits_32(SOCFPGA_SYSMGR(FPGA_BRIDGE_CTRL),
+			SYSMGR_SOC_BRIDGE_CTRL_EN);
+
 		udelay(1000);
 	}
 
@@ -991,6 +1003,11 @@
 		mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST),
 			RSTMGR_BRGMODRST_LWHPS2FPGA);
 
+		/* Clear System Manager lwsoc bridge control register[lwsoc2fpga_ready_latency_enable] = 1 */
+		VERBOSE("Clear LWSOC lwsoc2fpga_ready_latency_enable ...\n");
+		mmio_clrbits_32(SOCFPGA_SYSMGR(FPGA_BRIDGE_CTRL),
+			SYSMGR_LWSOC_BRIDGE_CTRL_EN);
+
 		udelay(1000);
 	}
 #else
@@ -1266,4 +1283,4 @@
 	} while (timeout-- > 0);
 
 	return RSTMGR_RET_ERROR;
-}
+}
\ No newline at end of file
diff --git a/plat/intel/soc/common/socfpga_delay_timer.c b/plat/intel/soc/common/socfpga_delay_timer.c
index db173a4..3759009 100644
--- a/plat/intel/soc/common/socfpga_delay_timer.c
+++ b/plat/intel/soc/common/socfpga_delay_timer.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,7 +11,6 @@
 #include <lib/mmio.h>
 #include "socfpga_plat_def.h"
 
-
 #if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX
 #include "agilex_clock_manager.h"
 #elif PLATFORM_MODEL == PLAT_SOCFPGA_N5X
@@ -19,7 +19,7 @@
 #include "s10_clock_manager.h"
 #endif
 
-#define SOCFPGA_GLOBAL_TIMER		0xffd01000
+#define SOCFPGA_GLOBAL_TIMER		PLAT_TIMER_BASE_ADDR
 #define SOCFPGA_GLOBAL_TIMER_EN		0x3
 
 static timer_ops_t plat_timer_ops;
@@ -44,7 +44,6 @@
 	plat_timer_ops.clk_div		= PLAT_SYS_COUNTER_FREQ_IN_MHZ;
 
 	timer_init(&plat_timer_ops);
-
 }
 
 void socfpga_delay_timer_init(void)
@@ -54,5 +53,4 @@
 
 	asm volatile("msr cntp_ctl_el0, %0" : : "r" (SOCFPGA_GLOBAL_TIMER_EN));
 	asm volatile("msr cntp_tval_el0, %0" : : "r" (~0));
-
 }
diff --git a/plat/intel/soc/common/socfpga_image_load.c b/plat/intel/soc/common/socfpga_image_load.c
index a5c3279..ee79158 100644
--- a/plat/intel/soc/common/socfpga_image_load.c
+++ b/plat/intel/soc/common/socfpga_image_load.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,7 +13,13 @@
  ******************************************************************************/
 void plat_flush_next_bl_params(void)
 {
+	/*
+	 * We cannot flush these descriptors on the Agilex5 platform,
+	 * since the BL2 runs on the OCRAM and this OCRAM is not cache coherent.
+	 */
+#if PLATFORM_MODEL != PLAT_SOCFPGA_AGILEX5
 	flush_bl_params_desc();
+#endif
 }
 
 /*******************************************************************************
diff --git a/plat/intel/soc/common/socfpga_psci.c b/plat/intel/soc/common/socfpga_psci.c
index 623843e..50d4820 100644
--- a/plat/intel/soc/common/socfpga_psci.c
+++ b/plat/intel/soc/common/socfpga_psci.c
@@ -17,8 +17,13 @@
 #include <lib/mmio.h>
 #include <lib/psci/psci.h>
 #include <plat/common/platform.h>
+#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
+#include "agilex5_cache.h"
+#endif
+#include "ccu/ncore_ccu.h"
 #include "socfpga_mailbox.h"
 #include "socfpga_plat_def.h"
+#include "socfpga_private.h"
 #include "socfpga_reset_manager.h"
 #include "socfpga_sip_svc.h"
 #include "socfpga_system_manager.h"
@@ -190,6 +195,14 @@
 	if (intel_rsu_update_address) {
 		mailbox_rsu_update(addr_buf);
 	} else {
+#if CACHE_FLUSH
+		/* ATF Flush and Invalidate Cache */
+		dcsw_op_all(DCCISW);
+		invalidate_cache_low_el();
+#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
+		flush_l3_dcache();
+#endif
+#endif
 		mailbox_reset_cold();
 	}
 
@@ -200,6 +213,16 @@
 static int socfpga_system_reset2(int is_vendor, int reset_type,
 					u_register_t cookie)
 {
+
+#if CACHE_FLUSH
+	/*
+	 * ATF Flush and Invalidate Cache due to hardware limitation
+	 * of auto Flush and Invalidate Cache.
+	 */
+	dcsw_op_all(DCCISW);
+	invalidate_cache_low_el();
+#endif
+
 #if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5
 	mailbox_reset_warm(reset_type);
 #else
diff --git a/plat/intel/soc/common/socfpga_storage.c b/plat/intel/soc/common/socfpga_storage.c
index d250d9e..7679f59 100644
--- a/plat/intel/soc/common/socfpga_storage.c
+++ b/plat/intel/soc/common/socfpga_storage.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
  * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,16 +22,21 @@
 #include <drivers/partition/partition.h>
 #include <lib/mmio.h>
 #include <tools_share/firmware_image_package.h>
-
 #include "drivers/sdmmc/sdmmc.h"
 #include "socfpga_private.h"
 #include "socfpga_ros.h"
 
 
 #define PLAT_FIP_BASE		(0)
+# if ARM_LINUX_KERNEL_AS_BL33
+#define PLAT_FIP_MAX_SIZE	(0x8000000)
+#define PLAT_MMC_DATA_BASE	(0x10000000)
+#define PLAT_MMC_DATA_SIZE	(0x100000)
+# else
 #define PLAT_FIP_MAX_SIZE	(0x1000000)
 #define PLAT_MMC_DATA_BASE	(0xffe3c000)
 #define PLAT_MMC_DATA_SIZE	(0x2000)
+# endif
 
 static const io_dev_connector_t *fip_dev_con;
 static const io_dev_connector_t *boot_dev_con;
diff --git a/plat/intel/soc/n5x/include/n5x_clock_manager.h b/plat/intel/soc/n5x/include/n5x_clock_manager.h
index 54477da..95a3d5c 100644
--- a/plat/intel/soc/n5x/include/n5x_clock_manager.h
+++ b/plat/intel/soc/n5x/include/n5x_clock_manager.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,7 +10,6 @@
 
 
 /* MACRO DEFINITION */
-#define SOCFPGA_GLOBAL_TIMER				0xffd01000
 #define SOCFPGA_GLOBAL_TIMER_EN				0x3
 
 #define CLKMGR_PLLGLOB_VCO_PSRC_MASK			GENMASK(17, 16)
diff --git a/plat/intel/soc/n5x/include/n5x_system_manager.h b/plat/intel/soc/n5x/include/n5x_system_manager.h
index 3610a6e..fd789a2 100644
--- a/plat/intel/soc/n5x/include/n5x_system_manager.h
+++ b/plat/intel/soc/n5x/include/n5x_system_manager.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -121,7 +122,7 @@
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_8		0x220
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_9		0x224
 #define SOCFPGA_SYSMGR_MPFE_CONFIG			0x228
-#define SOCFPGA_SYSMGR_MPFE_status			0x22C
+#define SOCFPGA_SYSMGR_MPFE_STATUS			0x22C
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_WARM_0		0x230
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_WARM_1		0x234
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_WARM_2		0x238
diff --git a/plat/intel/soc/n5x/include/socfpga_plat_def.h b/plat/intel/soc/n5x/include/socfpga_plat_def.h
index 1eafeef..c477787 100644
--- a/plat/intel/soc/n5x/include/socfpga_plat_def.h
+++ b/plat/intel/soc/n5x/include/socfpga_plat_def.h
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved.
  * Copyright (c) 2020-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -18,6 +19,8 @@
 #define PLAT_PRIMARY_CPU			0
 #define PLAT_CLUSTER_ID_MPIDR_AFF_SHIFT		MPIDR_AFF1_SHIFT
 #define PLAT_CPU_ID_MPIDR_AFF_SHIFT		MPIDR_AFF0_SHIFT
+#define PLAT_HANDOFF_OFFSET			0xFFE3F000
+#define PLAT_TIMER_BASE_ADDR			0xFFD01000
 
 /* FPGA config helpers */
 #define INTEL_SIP_SMC_FPGA_CONFIG_ADDR		0x400000
@@ -27,6 +30,13 @@
 #define CAD_QSPIDATA_OFST			0xff900000
 #define CAD_QSPI_OFFSET				0xff8d2000
 
+/* SDMMC Setting */
+# if ARM_LINUX_KERNEL_AS_BL33
+#define SOCFPGA_MMC_BLOCK_SIZE			U(32768)
+# else
+#define SOCFPGA_MMC_BLOCK_SIZE			U(8192)
+# endif
+
 /* Register Mapping */
 #define SOCFPGA_CCU_NOC_REG_BASE		U(0xf7000000)
 #define SOCFPGA_F2SDRAMMGR_REG_BASE		U(0xf8024000)
diff --git a/plat/intel/soc/stratix10/include/s10_memory_controller.h b/plat/intel/soc/stratix10/include/s10_memory_controller.h
index 155b279..056f6cf 100644
--- a/plat/intel/soc/stratix10/include/s10_memory_controller.h
+++ b/plat/intel/soc/stratix10/include/s10_memory_controller.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -26,7 +27,7 @@
 #define S10_MPFE_HMC_ADP_ECCCTRL1			0xf8011100
 #define S10_MPFE_HMC_ADP_ECCCTRL2			0xf8011104
 #define S10_MPFE_HMC_ADP_RSTHANDSHAKESTAT		0xf8011218
-#define S10_MPFE_HMC_ADP_RSTHANDSHAKESTAT_SEQ2CORE	0x000000ff
+#define S10_MPFE_HMC_ADP_RSTHANDSHAKESTAT_SEQ2CORE	0x0000000f
 #define S10_MPFE_HMC_ADP_RSTHANDSHAKECTRL		0xf8011214
 
 
diff --git a/plat/intel/soc/stratix10/include/s10_system_manager.h b/plat/intel/soc/stratix10/include/s10_system_manager.h
index e7bf730..dcc1517 100644
--- a/plat/intel/soc/stratix10/include/s10_system_manager.h
+++ b/plat/intel/soc/stratix10/include/s10_system_manager.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -120,7 +121,7 @@
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_8		0x220
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_COLD_9		0x224
 #define SOCFPGA_SYSMGR_MPFE_CONFIG			0x228
-#define SOCFPGA_SYSMGR_MPFE_status			0x22C
+#define SOCFPGA_SYSMGR_MPFE_STATUS			0x22C
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_WARM_0		0x230
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_WARM_1		0x234
 #define SOCFPGA_SYSMGR_BOOT_SCRATCH_WARM_2		0x238
diff --git a/plat/intel/soc/stratix10/include/socfpga_plat_def.h b/plat/intel/soc/stratix10/include/socfpga_plat_def.h
index 7f452bd..cd5b076 100644
--- a/plat/intel/soc/stratix10/include/socfpga_plat_def.h
+++ b/plat/intel/soc/stratix10/include/socfpga_plat_def.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2019-2023, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024, Altera Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -17,6 +18,8 @@
 #define PLAT_PRIMARY_CPU			0
 #define PLAT_CLUSTER_ID_MPIDR_AFF_SHIFT		MPIDR_AFF1_SHIFT
 #define PLAT_CPU_ID_MPIDR_AFF_SHIFT		MPIDR_AFF0_SHIFT
+#define PLAT_HANDOFF_OFFSET			0xFFE3F000
+#define PLAT_TIMER_BASE_ADDR			0xFFD01000
 
 /* FPGA config helpers */
 #define INTEL_SIP_SMC_FPGA_CONFIG_ADDR		0x400000
@@ -26,6 +29,13 @@
 #define CAD_QSPIDATA_OFST			0xff900000
 #define CAD_QSPI_OFFSET				0xff8d2000
 
+/* SDMMC Setting */
+# if ARM_LINUX_KERNEL_AS_BL33
+#define SOCFPGA_MMC_BLOCK_SIZE			U(32768)
+# else
+#define SOCFPGA_MMC_BLOCK_SIZE			U(8192)
+# endif
+
 /* Register Mapping */
 #define SOCFPGA_CCU_NOC_REG_BASE		0xf7000000
 #define SOCFPGA_F2SDRAMMGR_REG_BASE		U(0xf8024000)
diff --git a/plat/intel/soc/stratix10/platform.mk b/plat/intel/soc/stratix10/platform.mk
index afcf514..0a33c3d 100644
--- a/plat/intel/soc/stratix10/platform.mk
+++ b/plat/intel/soc/stratix10/platform.mk
@@ -1,6 +1,7 @@
 #
 # Copyright (c) 2019-2023, ARM Limited and Contributors. All rights reserved.
-# Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+# Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
+# Copyright (c) 2024, Altera Corporation. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -26,6 +27,7 @@
 			lib/xlat_tables/xlat_tables_common.c 		\
 			plat/intel/soc/common/aarch64/platform_common.c \
 			plat/intel/soc/common/aarch64/plat_helpers.S	\
+			plat/intel/soc/common/drivers/ccu/ncore_ccu.c	\
 			plat/intel/soc/common/socfpga_delay_timer.c	\
 			plat/intel/soc/common/soc/socfpga_firewall.c
 
diff --git a/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c b/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c
index 26bed29..7b867d8 100644
--- a/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c
+++ b/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c
@@ -97,7 +97,7 @@
 
 	/* PCI-e protect address(64MB) */
 	region_info.start = 0xC0000000ULL;
-	region_info.end = 0xC3FF0000ULL;
+	region_info.end = 0xC3FFFFFFULL;
 	region_info.region = 1;
 	SET_ACCESS_PERMISSION(region_info.apc, 1,
 			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
@@ -108,7 +108,7 @@
 
 	/* SCP protect address */
 	region_info.start = 0x50000000ULL;
-	region_info.end = 0x513F0000ULL;
+	region_info.end = 0x513FFFFFULL;
 	region_info.region = 2;
 	SET_ACCESS_PERMISSION(region_info.apc, 1,
 			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
@@ -117,21 +117,10 @@
 			      NO_PROT, FORBIDDEN, FORBIDDEN, NO_PROT);
 	emi_mpu_set_protection(&region_info);
 
-	/* DSP protect address */
-	region_info.start = 0x40000000ULL;	/* dram base addr */
-	region_info.end = 0x1FFFF0000ULL;
-	region_info.region = 3;
-	SET_ACCESS_PERMISSION(region_info.apc, 1,
-			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
-			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
-			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
-			      FORBIDDEN, FORBIDDEN, FORBIDDEN, NO_PROT);
-	emi_mpu_set_protection(&region_info);
-
 	/* Forbidden All */
 	region_info.start = 0x40000000ULL;	/* dram base addr */
-	region_info.end = 0x1FFFF0000ULL;
-	region_info.region = 4;
+	region_info.end = 0x1FFFFFFFFULL;
+	region_info.region = 3;
 	SET_ACCESS_PERMISSION(region_info.apc, 1,
 			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
 			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
diff --git a/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c b/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c
index b6e5a2d..8e4a675 100644
--- a/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c
+++ b/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c
@@ -118,7 +118,7 @@
 
 	/* SCP DRAM */
 	region_info.start = 0x50000000ULL;
-	region_info.end = 0x51400000ULL;
+	region_info.end = 0x513FFFFFULL;
 	region_info.region = 2;
 	SET_ACCESS_PERMISSION(region_info.apc, 1,
 			      FORBIDDEN, FORBIDDEN, FORBIDDEN, FORBIDDEN,
diff --git a/plat/nxp/s32/s32g274ardb2/include/s32cc-ncore.h b/plat/nxp/s32/s32g274ardb2/include/s32cc-ncore.h
new file mode 100644
index 0000000..0c0870f
--- /dev/null
+++ b/plat/nxp/s32/s32g274ardb2/include/s32cc-ncore.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2019-2021, 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef S32G2_NCORE_H
+#define S32G2_NCORE_H
+
+#include <stdbool.h>
+
+#define NCORE_BASE_ADDR			UL(0x50400000)
+
+#define A53_CLUSTER0_CAIU		U(0)
+#define A53_CLUSTER1_CAIU		U(1)
+
+/**
+ * Directory Unit Registers
+ *
+ * The directory provides a point of serialization for establishing transaction
+ * ordering and sequences coherence operations and memory accesses.
+ */
+#define NCORE_DIRU(N)			(NCORE_BASE_ADDR + UL(0x80000) + ((N) * UL(0x1000)))
+
+/* DIRU Snoop Filtering Enable */
+#define NCORE_DIRUSFE(N)		(NCORE_DIRU(N) + UL(0x10))
+#define NCORE_DIRUSFE_SFEN(SF)		BIT_32(SF)
+
+/* DIRU Caching Agent Snoop Enable */
+#define NCORE_DIRUCASE(N)		(NCORE_DIRU(N) + UL(0x40))
+#define NCORE_DIRUCASE_CASNPEN(CAIU)	BIT_32(CAIU)
+
+/* DIRU Snoop Filter Maintenance Control */
+#define NCORE_DIRUSFMC(N)		(NCORE_DIRU(N) + UL(0x80))
+#define NCORE_DIRUSFMC_SFID(SF)		((SF) << 16U)
+#define NCORE_DIRUSFMC_SFMNTOP_ALL	U(0x0)
+
+/* DIRU Snoop Filter Maintenance Activity */
+#define NCORE_DIRUSFMA(N)		(NCORE_DIRU(N) + UL(0x84))
+#define NCORE_DIRUSFMA_MNTOPACTV	BIT_32(0)
+
+/**
+ * Coherent Agent Interface Unit Registers
+ *
+ * CAI provides a means for a fully-coherent agent to be connected to the Ncore.
+ * The CAI behaves as a fully-coherent slave.
+ */
+#define NCORE_CAIU(N)			(NCORE_BASE_ADDR + ((N) * UL(0x1000)))
+#define NCORE_CAIU0_BASE_ADDR		NCORE_BASE_ADDR
+
+/* CAIU Transaction Control */
+#define NCORE_CAIUTC_OFF		UL(0x0)
+#define NCORE_CAIUTC_ISOLEN_SHIFT	U(1)
+#define NCORE_CAIUTC_ISOLEN_MASK	BIT_32(NCORE_CAIUTC_ISOLEN_SHIFT)
+
+#define NCORE_CAIUTC(N)			(NCORE_CAIU(N) + NCORE_CAIUTC_OFF)
+
+/* CAIU Identification */
+#define NCORE_CAIUID(n)			(NCORE_CAIU(n) + UL(0xFFC))
+#define NCORE_CAIUID_TYPE		GENMASK_32(U(19), U(16))
+#define NCORE_CAIUID_TYPE_ACE_DVM	U(0x0)
+
+/**
+ * Coherent Subsystem Registers
+ */
+#define NCORE_CSR			(NCORE_BASE_ADDR + UL(0xFF000))
+
+/* Coherent Subsystem ACE DVM Snoop Enable */
+#define NCORE_CSADSE			(NCORE_CSR + UL(0x40))
+#define NCORE_CSADSE_DVMSNPEN(CAIU)	BIT_32(CAIU)
+
+/* Coherent Subsystem Identification */
+#define NCORE_CSID			(NCORE_CSR + UL(0xFFC))
+#define NCORE_CSID_NUMSFS_SHIFT		U(18)
+#define NCORE_CSID_NUMSFS_MASK		GENMASK_32(U(22), NCORE_CSID_NUMSFS_SHIFT)
+#define NCORE_CSID_NUMSFS(CSIDR)	(((CSIDR) & NCORE_CSID_NUMSFS_MASK) \
+					  >> NCORE_CSID_NUMSFS_SHIFT)
+
+/* Coherent Subsystem Unit Identification */
+#define NCORE_CSUID			(NCORE_CSR + UL(0xFF8))
+#define NCORE_CSUID_NUMCMIUS_SHIFT	U(24)
+#define NCORE_CSUID_NUMCMIUS_MASK	GENMASK_32(U(29), NCORE_CSUID_NUMCMIUS_SHIFT)
+#define NCORE_CSUID_NUMCMIUS(CSUIDR)	(((CSUIDR) & NCORE_CSUID_NUMCMIUS_MASK) \
+					 >> NCORE_CSUID_NUMCMIUS_SHIFT)
+#define NCORE_CSUID_NUMDIRUS_SHIFT	U(16)
+#define NCORE_CSUID_NUMDIRUS_MASK	GENMASK_32(U(21), NCORE_CSUID_NUMDIRUS_SHIFT)
+#define NCORE_CSUID_NUMDIRUS(CSUIDR)	(((CSUIDR) & NCORE_CSUID_NUMDIRUS_MASK) \
+					 >> NCORE_CSUID_NUMDIRUS_SHIFT)
+#define NCORE_CSUID_NUMNCBUS_SHIFT	U(8)
+#define NCORE_CSUID_NUMNCBUS_MASK	GENMASK_32(U(13), NCORE_CSUID_NUMNCBUS_SHIFT)
+#define NCORE_CSUID_NUMNCBUS(CSUIDR)	(((CSUIDR) & NCORE_CSUID_NUMNCBUS_MASK) \
+					 >> NCORE_CSUID_NUMNCBUS_SHIFT)
+
+#ifndef __ASSEMBLER__
+void ncore_caiu_online(uint32_t caiu);
+void ncore_caiu_offline(uint32_t caiu);
+void ncore_init(void);
+bool ncore_is_caiu_online(uint32_t caiu);
+void ncore_disable_caiu_isolation(uint32_t caiu);
+#endif /* __ASSEMBLER__ */
+
+#endif /* S32G2_NCORE_H */
diff --git a/plat/nxp/s32/s32g274ardb2/plat_bl2_el3_setup.c b/plat/nxp/s32/s32g274ardb2/plat_bl2_el3_setup.c
index 705832c..4645f01 100644
--- a/plat/nxp/s32/s32g274ardb2/plat_bl2_el3_setup.c
+++ b/plat/nxp/s32/s32g274ardb2/plat_bl2_el3_setup.c
@@ -11,6 +11,7 @@
 #include <plat_console.h>
 #include <s32cc-clk-drv.h>
 #include <plat_io_storage.h>
+#include <s32cc-ncore.h>
 
 #define SIUL2_PC09_MSCR		UL(0x4009C2E4)
 #define SIUL2_PC10_MSCR		UL(0x4009C2E8)
@@ -62,6 +63,14 @@
 	linflex_config_pinctrl();
 	console_s32g2_register();
 
+	/* Restore (clear) the CAIUTC[IsolEn] bit for the primary cluster, which
+	 * we have manually set during early BL2 boot.
+	 */
+	ncore_disable_caiu_isolation(A53_CLUSTER0_CAIU);
+
+	ncore_init();
+	ncore_caiu_online(A53_CLUSTER0_CAIU);
+
 	plat_s32g2_io_setup();
 }
 
diff --git a/plat/nxp/s32/s32g274ardb2/plat_helpers.S b/plat/nxp/s32/s32g274ardb2/plat_helpers.S
index 10c0035..7121900 100644
--- a/plat/nxp/s32/s32g274ardb2/plat_helpers.S
+++ b/plat/nxp/s32/s32g274ardb2/plat_helpers.S
@@ -6,10 +6,7 @@
 
 #include <asm_macros.S>
 #include <platform_def.h>
-
-#define S32G_NCORE_CAIU0_BASE_ADDR		UL(0x50400000)
-#define S32G_NCORE_CAIUTC_OFF			U(0x0)
-#define S32G_NCORE_CAIUTC_ISOLEN_SHIFT		U(1)
+#include <s32cc-ncore.h>
 
 .globl	plat_crash_console_flush
 .globl	plat_crash_console_init
@@ -104,12 +101,12 @@
  * Clobber list: x0, x1, x2
  */
 func plat_reset_handler
-	mov	x0, #S32G_NCORE_CAIU0_BASE_ADDR
-	ldr	w1, [x0, #S32G_NCORE_CAIUTC_OFF]
+	mov	x0, #NCORE_CAIU0_BASE_ADDR
+	ldr	w1, [x0, #NCORE_CAIUTC_OFF]
 	movz	w2, #1
-	lsl	w2, w2, #S32G_NCORE_CAIUTC_ISOLEN_SHIFT
+	lsl	w2, w2, #NCORE_CAIUTC_ISOLEN_SHIFT
 	orr	w1, w1, w2
-	str	w1, [x0, #S32G_NCORE_CAIUTC_OFF]
+	str	w1, [x0, #NCORE_CAIUTC_OFF]
 	ret
 endfunc plat_reset_handler
 
diff --git a/plat/nxp/s32/s32g274ardb2/platform.mk b/plat/nxp/s32/s32g274ardb2/platform.mk
index 7dc287d..7d6e960 100644
--- a/plat/nxp/s32/s32g274ardb2/platform.mk
+++ b/plat/nxp/s32/s32g274ardb2/platform.mk
@@ -53,6 +53,7 @@
 	${PLAT_S32G274ARDB2}/plat_bl2_el3_setup.c \
 	${PLAT_S32G274ARDB2}/plat_bl2_image_desc.c \
 	${PLAT_S32G274ARDB2}/plat_io_storage.c \
+	${PLAT_S32G274ARDB2}/s32cc_ncore.c \
 	common/desc_image_load.c \
 	drivers/io/io_fip.c \
 	drivers/io/io_memmap.c \
diff --git a/plat/nxp/s32/s32g274ardb2/s32cc_ncore.c b/plat/nxp/s32/s32g274ardb2/s32cc_ncore.c
new file mode 100644
index 0000000..aa60ac4
--- /dev/null
+++ b/plat/nxp/s32/s32g274ardb2/s32cc_ncore.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2019-2021, 2024 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <lib/mmio.h>
+#include <platform_def.h>
+
+#include <s32cc-ncore.h>
+
+static void ncore_diru_online(uint32_t diru)
+{
+	uint32_t numsfs, sf;
+
+	numsfs = NCORE_CSID_NUMSFS(mmio_read_32(NCORE_CSID)) + 1U;
+
+	/* Initialize all entries maintenance operation for each snoop filter */
+	for (sf = 0U; sf < numsfs; sf++) {
+		mmio_write_32(NCORE_DIRUSFMC(diru), NCORE_DIRUSFMC_SFID(sf) |
+			      NCORE_DIRUSFMC_SFMNTOP_ALL);
+
+		while ((mmio_read_32(NCORE_DIRUSFMA(diru)) & NCORE_DIRUSFMA_MNTOPACTV) != 0U) {
+		}
+
+		mmio_setbits_32(NCORE_DIRUSFE(diru), NCORE_DIRUSFE_SFEN(sf));
+	}
+}
+
+void ncore_disable_caiu_isolation(uint32_t caiu)
+{
+	/* Exit from low-power state */
+	mmio_clrbits_32(NCORE_CAIUTC(caiu), NCORE_CAIUTC_ISOLEN_MASK);
+}
+
+static void set_caiu(uint32_t caiu, bool on)
+{
+	uint32_t dirucase, csadser, caiuidr;
+	uint32_t numdirus, diru;
+
+	/* Enable or disable snoop messages to the CAI for each DIRU */
+	numdirus = NCORE_CSUID_NUMDIRUS(mmio_read_32(NCORE_CSUID));
+	for (diru = 0; diru < numdirus; diru++) {
+		dirucase = mmio_read_32(NCORE_DIRUCASE(diru));
+
+		if (on) {
+			dirucase |= NCORE_DIRUCASE_CASNPEN(caiu);
+		} else {
+			dirucase &= ~NCORE_DIRUCASE_CASNPEN(caiu);
+		}
+
+		mmio_write_32(NCORE_DIRUCASE(diru), dirucase);
+	}
+
+	/* Enable or disable DVM messages to the CAI */
+	caiuidr = mmio_read_32(NCORE_CAIUID(caiu));
+	if ((caiuidr & NCORE_CAIUID_TYPE) == NCORE_CAIUID_TYPE_ACE_DVM) {
+		csadser = mmio_read_32(NCORE_CSADSE);
+
+		if (on) {
+			csadser |= NCORE_CSADSE_DVMSNPEN(caiu);
+		} else {
+			csadser &= ~NCORE_CSADSE_DVMSNPEN(caiu);
+		}
+
+		mmio_write_32(NCORE_CSADSE, csadser);
+	}
+}
+
+void ncore_caiu_online(uint32_t caiu)
+{
+	set_caiu(caiu, true);
+}
+
+void ncore_caiu_offline(uint32_t caiu)
+{
+	set_caiu(caiu, false);
+}
+
+bool ncore_is_caiu_online(uint32_t caiu)
+{
+	uint32_t stat = mmio_read_32(NCORE_CSADSE);
+
+	return ((stat & NCORE_CSADSE_DVMSNPEN(caiu)) != 0U);
+}
+
+void ncore_init(void)
+{
+	uint32_t csuidr = mmio_read_32(NCORE_CSUID);
+	uint32_t numdirus, diru;
+
+	numdirus = NCORE_CSUID_NUMDIRUS(csuidr);
+	for (diru = 0U; diru < numdirus; diru++) {
+		/**
+		 * Transition the directory to an online state by ensuring that
+		 * all DIRUs within the interface are operational.
+		 */
+		ncore_diru_online(diru);
+	}
+}
diff --git a/plat/st/common/stm32mp_fconf_io.c b/plat/st/common/stm32mp_fconf_io.c
index 1aecece..644275e 100644
--- a/plat/st/common/stm32mp_fconf_io.c
+++ b/plat/st/common/stm32mp_fconf_io.c
@@ -77,7 +77,7 @@
 #define DEFAULT_UUID_NUMBER	U(7)
 
 #ifdef __aarch64__
-#define BL31_UUID_NUMBER	U(1)
+#define BL31_UUID_NUMBER	U(2)
 #else
 #define BL31_UUID_NUMBER	U(0)
 #endif
@@ -115,6 +115,7 @@
 	{FW_CONFIG_ID, "fw_cfg_uuid"},
 #ifdef __aarch64__
 	{BL31_IMAGE_ID, "bl31_uuid"},
+	{SOC_FW_CONFIG_ID, "soc_fw_cfg_uuid"},
 #endif
 	{BL32_IMAGE_ID, "bl32_uuid"},
 	{BL32_EXTRA1_IMAGE_ID, "bl32_extra1_uuid"},
diff --git a/plat/st/stm32mp2/bl2_plat_setup.c b/plat/st/stm32mp2/bl2_plat_setup.c
index 20cbc6e..2fabc41 100644
--- a/plat/st/stm32mp2/bl2_plat_setup.c
+++ b/plat/st/stm32mp2/bl2_plat_setup.c
@@ -15,11 +15,13 @@
 #include <drivers/mmc.h>
 #include <drivers/st/regulator_fixed.h>
 #include <drivers/st/stm32mp2_ddr_helpers.h>
+#include <drivers/st/stm32mp2_ram.h>
 #include <drivers/st/stm32mp_pmic2.h>
 #include <drivers/st/stm32mp_risab_regs.h>
 #include <lib/fconf/fconf.h>
 #include <lib/fconf/fconf_dyn_cfg_getter.h>
 #include <lib/mmio.h>
+#include <lib/optee_utils.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #include <plat/common/platform.h>
 
@@ -135,6 +137,21 @@
 
 void bl2_platform_setup(void)
 {
+	int ret;
+
+	ret = stm32mp2_ddr_probe();
+	if (ret != 0) {
+		ERROR("DDR probe: error %d\n", ret);
+		panic();
+	}
+
+	/* Map DDR for binary load, now with cacheable attribute */
+	ret = mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE,
+				      STM32MP_DDR_MAX_SIZE, MT_MEMORY | MT_RW | MT_SECURE);
+	if (ret < 0) {
+		ERROR("DDR mapping: error %d\n", ret);
+		panic();
+	}
 }
 
 static void reset_backup_domain(void)
@@ -258,10 +275,15 @@
 {
 	int err = 0;
 	bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
+	bl_mem_params_node_t *pager_mem_params;
 	const struct dyn_cfg_dtb_info_t *config_info;
 	unsigned int i;
 	const unsigned int image_ids[] = {
 		BL31_IMAGE_ID,
+		SOC_FW_CONFIG_ID,
+		BL32_IMAGE_ID,
+		BL33_IMAGE_ID,
+		HW_CONFIG_ID,
 	};
 
 	assert(bl_mem_params != NULL);
@@ -305,6 +327,28 @@
 			case BL31_IMAGE_ID:
 				bl_mem_params->ep_info.pc = config_info->config_addr;
 				break;
+
+			case BL32_IMAGE_ID:
+				bl_mem_params->ep_info.pc = config_info->config_addr;
+
+				/* In case of OPTEE, initialize address space with tos_fw addr */
+				pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+				if (pager_mem_params != NULL) {
+					pager_mem_params->image_info.image_base =
+						config_info->config_addr;
+					pager_mem_params->image_info.image_max_size =
+						config_info->config_max_size;
+				}
+				break;
+
+			case BL33_IMAGE_ID:
+				bl_mem_params->ep_info.pc = config_info->config_addr;
+				break;
+
+			case HW_CONFIG_ID:
+			case SOC_FW_CONFIG_ID:
+				break;
+
 			default:
 				return -EINVAL;
 			}
@@ -317,6 +361,30 @@
 
 		break;
 
+	case BL32_IMAGE_ID:
+		if ((bl_mem_params->image_info.image_base != 0UL) &&
+		    (optee_header_is_valid(bl_mem_params->image_info.image_base))) {
+			/* BL32 is OP-TEE header */
+			bl_mem_params->ep_info.pc = bl_mem_params->image_info.image_base;
+			pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
+			assert(pager_mem_params != NULL);
+
+			err = parse_optee_header(&bl_mem_params->ep_info,
+						 &pager_mem_params->image_info,
+						 NULL);
+			if (err != 0) {
+				ERROR("OPTEE header parse error.\n");
+				panic();
+			}
+
+			/* Set optee boot info from parsed header data */
+			bl_mem_params->ep_info.args.arg0 = 0U; /* Unused */
+			bl_mem_params->ep_info.args.arg1 = 0U; /* Unused */
+			bl_mem_params->ep_info.args.arg2 = 0U; /* No DT supported */
+		}
+		break;
+
+	case BL33_IMAGE_ID:
 	default:
 		/* Do nothing in default case */
 		break;
diff --git a/plat/st/stm32mp2/bl31_plat_setup.c b/plat/st/stm32mp2/bl31_plat_setup.c
index dbf1371..586bfe8 100644
--- a/plat/st/stm32mp2/bl31_plat_setup.c
+++ b/plat/st/stm32mp2/bl31_plat_setup.c
@@ -8,12 +8,16 @@
 #include <stdint.h>
 
 #include <common/bl_common.h>
+#include <drivers/generic_delay_timer.h>
 #include <drivers/st/stm32_console.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #include <plat/common/platform.h>
 
 #include <platform_def.h>
 
+static entry_point_info_t bl32_image_ep_info;
+static entry_point_info_t bl33_image_ep_info;
+
 void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
 				u_register_t arg2, u_register_t arg3)
 {
@@ -31,6 +35,12 @@
 			BL_CODE_END - BL_CODE_BASE,
 			MT_CODE | MT_SECURE);
 
+	/*
+	 * Map soc_fw_config device tree with secure property, i.e. default region.
+	 * DDR region definitions will be finalized at BL32 level.
+	 */
+	mmap_add_region(arg1, arg1, STM32MP_SOC_FW_CONFIG_MAX_SIZE, MT_RO_DATA | MT_SECURE);
+
 #if USE_COHERENT_MEM
 	/* Map coherent memory */
 	mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
@@ -40,6 +50,20 @@
 
 	configure_mmu();
 
+	ret = dt_open_and_check(arg1);
+	if (ret < 0) {
+		EARLY_ERROR("%s: failed to open DT (%d)\n", __func__, ret);
+		panic();
+	}
+
+	ret = stm32mp2_clk_init();
+	if (ret < 0) {
+		EARLY_ERROR("%s: failed init clocks (%d)\n", __func__, ret);
+		panic();
+	}
+
+	(void)stm32mp_uart_console_setup();
+
 	/*
 	 * Map upper SYSRAM where bl_params_t are stored in BL2
 	 */
@@ -60,6 +84,31 @@
 	bl_params_node_t *bl_params = params_from_bl2->head;
 
 	while (bl_params != NULL) {
+		/*
+		 * Copy BL33 entry point information.
+		 * They are stored in Secure RAM, in BL2's address space.
+		 */
+		if (bl_params->image_id == BL33_IMAGE_ID) {
+			bl33_image_ep_info = *bl_params->ep_info;
+			/*
+			 *  Check if hw_configuration is given to BL32 and
+			 *  share it to BL33
+			 */
+			if (arg2 != 0U) {
+				bl33_image_ep_info.args.arg0 = 0U;
+				bl33_image_ep_info.args.arg1 = 0U;
+				bl33_image_ep_info.args.arg2 = arg2;
+			}
+		}
+
+		if (bl_params->image_id == BL32_IMAGE_ID) {
+			bl32_image_ep_info = *bl_params->ep_info;
+
+			if (arg2 != 0U) {
+				bl32_image_ep_info.args.arg3 = arg2;
+			}
+		}
+
 		bl_params = bl_params->next_params_info;
 	}
 
@@ -73,6 +122,9 @@
 
 void bl31_plat_arch_setup(void)
 {
+	generic_delay_timer_init();
+
+	stm32mp_gic_init();
 }
 
 void bl31_platform_setup(void)
@@ -81,5 +133,27 @@
 
 entry_point_info_t *bl31_plat_get_next_image_ep_info(unsigned int type)
 {
-	return NULL;
+	entry_point_info_t *next_image_info = NULL;
+
+	assert(sec_state_is_valid(type));
+
+	switch (type) {
+	case NON_SECURE:
+		next_image_info = &bl33_image_ep_info;
+		break;
+
+	case SECURE:
+		next_image_info = &bl32_image_ep_info;
+		break;
+
+	default:
+		break;
+	}
+
+	/* None of the next images on ST platforms can have 0x0 as the entrypoint */
+	if ((next_image_info == NULL) || (next_image_info->pc == 0UL)) {
+		return NULL;
+	}
+
+	return next_image_info;
 }
diff --git a/plat/st/stm32mp2/plat_bl2_mem_params_desc.c b/plat/st/stm32mp2/plat_bl2_mem_params_desc.c
index f845560..2513180 100644
--- a/plat/st/stm32mp2/plat_bl2_mem_params_desc.c
+++ b/plat/st/stm32mp2/plat_bl2_mem_params_desc.c
@@ -67,8 +67,85 @@
 				      VERSION_2, image_info_t,
 				      IMAGE_ATTRIB_SKIP_LOADING),
 
+		.next_handoff_image_id = BL32_IMAGE_ID,
+	},
+
+	/* Fill SoC FW config related information */
+	{
+		.image_id = SOC_FW_CONFIG_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | NON_EXECUTABLE),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+
+	/* Fill BL32 related information */
+	{
+		.image_id = BL32_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | EXECUTABLE),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
+
+		.next_handoff_image_id = BL33_IMAGE_ID,
+	},
+
+	/* Fill BL32 external 1 image related information */
+	{
+		.image_id = BL32_EXTRA1_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      SECURE | NON_EXECUTABLE),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
+
 		.next_handoff_image_id = INVALID_IMAGE_ID,
 	},
+
+	/* Fill HW_CONFIG related information if it exists */
+	{
+		.image_id = HW_CONFIG_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY,
+				      VERSION_2, entry_point_info_t,
+				      NON_SECURE | NON_EXECUTABLE),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	},
+
+	/* Fill BL33 related information */
+	{
+		.image_id = BL33_IMAGE_ID,
+
+		SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP,
+				      VERSION_2, entry_point_info_t,
+				      NON_SECURE | EXECUTABLE),
+
+		.ep_info.spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS),
+
+		SET_STATIC_PARAM_HEAD(image_info, PARAM_EP,
+				      VERSION_2, image_info_t,
+				      IMAGE_ATTRIB_SKIP_LOADING),
+
+		.next_handoff_image_id = INVALID_IMAGE_ID,
+	}
 };
 
 REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs)
diff --git a/plat/st/stm32mp2/platform.mk b/plat/st/stm32mp2/platform.mk
index c12e512..df1cacd 100644
--- a/plat/st/stm32mp2/platform.mk
+++ b/plat/st/stm32mp2/platform.mk
@@ -48,6 +48,8 @@
 # Device tree
 BL2_DTSI			:=	stm32mp25-bl2.dtsi
 FDT_SOURCES			:=	$(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME)))
+BL31_DTSI			:=	stm32mp25-bl31.dtsi
+FDT_SOURCES			+=	$(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl31.dts,$(DTB_FILE_NAME)))
 
 # Macros and rules to build TF binary
 STM32_TF_STM32			:=	$(addprefix ${BUILD_PLAT}/tf-a-, $(patsubst %.dtb,%.stm32,$(DTB_FILE_NAME)))
@@ -56,6 +58,7 @@
 
 STM32MP_FW_CONFIG_NAME		:=	$(patsubst %.dtb,%-fw-config.dtb,$(DTB_FILE_NAME))
 STM32MP_FW_CONFIG		:=	${BUILD_PLAT}/fdts/$(STM32MP_FW_CONFIG_NAME)
+STM32MP_SOC_FW_CONFIG		:=	$(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl31.dtb,$(DTB_FILE_NAME)))
 ifeq (${STM32MP_DDR_FIP_IO_STORAGE},1)
 STM32MP_DDR_FW_PATH		?=	drivers/st/ddr/phy/firmware/bin/stm32mp2
 STM32MP_DDR_FW_NAME		:=	${DDR_TYPE}_pmu_train.bin
@@ -64,6 +67,8 @@
 FDT_SOURCES			+=	$(addprefix fdts/, $(patsubst %.dtb,%.dts,$(STM32MP_FW_CONFIG_NAME)))
 # Add the FW_CONFIG to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_PAYLOAD,${STM32MP_FW_CONFIG},--fw-config))
+# Add the SOC_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_IMG,STM32MP_SOC_FW_CONFIG,--soc-fw-config))
 ifeq (${STM32MP_DDR_FIP_IO_STORAGE},1)
 # Add the FW_DDR to FIP and specify the same to certtool
 $(eval $(call TOOL_ADD_IMG,STM32MP_DDR_FW,--ddr-fw))
@@ -198,4 +203,11 @@
 		false; \
 	fi
 
+# Create DTB file for BL31
+${BUILD_PLAT}/fdts/%-bl31.dts: fdts/%.dts fdts/${BL31_DTSI} | $$(@D)/
+	@echo '#include "$(patsubst fdts/%,%,$<)"' > $@
+	@echo '#include "${BL31_DTSI}"' >> $@
+
+${BUILD_PLAT}/fdts/%-bl31.dtb: ${BUILD_PLAT}/fdts/%-bl31.dts
+
 include plat/st/common/common_rules.mk
diff --git a/plat/st/stm32mp2/stm32mp2_def.h b/plat/st/stm32mp2/stm32mp2_def.h
index 73116db..b441502 100644
--- a/plat/st/stm32mp2/stm32mp2_def.h
+++ b/plat/st/stm32mp2/stm32mp2_def.h
@@ -138,7 +138,11 @@
  * MAX_MMAP_REGIONS is usually:
  * BL stm32mp2_mmap size + mmap regions in *_plat_arch_setup
  */
+#if defined(IMAGE_BL31)
+#define MAX_MMAP_REGIONS			7
+#else
 #define MAX_MMAP_REGIONS			6
+#endif
 
 /* DTB initialization value */
 #define STM32MP_BL2_DTB_SIZE			U(0x00006000)	/* 24 KB for DTB */
@@ -166,6 +170,7 @@
 #define STM32MP_HW_CONFIG_BASE			(STM32MP_BL33_BASE + \
 						STM32MP_BL33_MAX_SIZE)
 #define STM32MP_HW_CONFIG_MAX_SIZE		U(0x40000)
+#define STM32MP_SOC_FW_CONFIG_MAX_SIZE		U(0x10000) /* 64kB for BL31 DT */
 
 /*******************************************************************************
  * STM32MP2 device/io map related constants (used for MMU)
diff --git a/plat/st/stm32mp2/stm32mp2_private.c b/plat/st/stm32mp2/stm32mp2_private.c
index 7ad974f..5be4c5a 100644
--- a/plat/st/stm32mp2/stm32mp2_private.c
+++ b/plat/st/stm32mp2/stm32mp2_private.c
@@ -117,6 +117,33 @@
 	return CK_BUS_GPIOA + (bank - GPIO_BANK_A);
 }
 
+#if STM32MP_UART_PROGRAMMER || !defined(IMAGE_BL2)
+/*
+ * UART Management
+ */
+static const uintptr_t stm32mp2_uart_addresses[STM32MP_NB_OF_UART] = {
+	USART1_BASE,
+	USART2_BASE,
+	USART3_BASE,
+	UART4_BASE,
+	UART5_BASE,
+	USART6_BASE,
+	UART7_BASE,
+	UART8_BASE,
+	UART9_BASE,
+};
+
+uintptr_t get_uart_address(uint32_t instance_nb)
+{
+	if ((instance_nb == 0U) ||
+	    (instance_nb > STM32MP_NB_OF_UART)) {
+		return 0U;
+	}
+
+	return stm32mp2_uart_addresses[instance_nb - 1U];
+}
+#endif
+
 uint32_t stm32mp_get_chip_version(void)
 {
 	static uint32_t rev;
diff --git a/plat/xilinx/common/include/plat_console.h b/plat/xilinx/common/include/plat_console.h
index 0f8320e..fa6021d 100644
--- a/plat/xilinx/common/include/plat_console.h
+++ b/plat/xilinx/common/include/plat_console.h
@@ -8,18 +8,30 @@
 #define PLAT_DT_UART_H
 
 #define DT_UART_DCC_COMPAT	"arm,dcc"
+#define DT_UART_CAD_COMPAT	"xlnx,zynqmp-uart"
+#define DT_UART_PL011_COMPAT	"arm,pl011"
 
-#if defined(PLAT_zynqmp)
-#define DT_UART_COMPAT	"xlnx,zynqmp-uart"
-#else
-#define DT_UART_COMPAT	"arm,pl011"
-#endif
+/* Default console type is either CADENCE0 or CADENCE1 or PL011_0 or PL011_1
+ * Debug console type is DCC
+ */
+#define CONSOLE_NONE	0
+#define CONSOLE_CDNS	1
+#define CONSOLE_PL011   2
+#define CONSOLE_DCC	3
+
+typedef struct console_hd {
+	uint32_t clk;
+	uint32_t baud_rate;
+	uintptr_t base;
+	uint32_t console_scope;
+	uint8_t console_type;
+} console_holder;
 
 typedef struct dt_uart_info_s {
 	char compatible[30];
 	uintptr_t base;
 	uint32_t baud_rate;
-	int32_t status;
+	uint8_t console_type;
 } dt_uart_info_t;
 
 void setup_console(void);
diff --git a/plat/xilinx/common/include/plat_xfer_list.h b/plat/xilinx/common/include/plat_xfer_list.h
new file mode 100644
index 0000000..cc79a2c
--- /dev/null
+++ b/plat/xilinx/common/include/plat_xfer_list.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2023-2024, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_XFER_LIST_H
+#define PLAT_XFER_LIST_H
+
+#include <lib/transfer_list.h>
+
+int32_t transfer_list_populate_ep_info(entry_point_info_t *bl32,
+				       entry_point_info_t *bl33);
+
+#endif /* PLAT_XFER_LIST_H */
diff --git a/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c b/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c
index 6265928..0ea51f0 100644
--- a/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c
+++ b/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c
@@ -106,11 +106,11 @@
 		SMC_RET1(handle, 0);
 	case IPI_MAILBOX_STATUS_ENQUIRY:
 	{
-		int32_t disable_irq;
+		int32_t disable_interrupt;
 
-		disable_irq = (x3 & IPI_SMC_ENQUIRY_DIRQ_MASK) ? 1 : 0;
+		disable_interrupt = (x3 & IPI_SMC_ENQUIRY_DIRQ_MASK) ? 1 : 0;
 		ret = ipi_mb_enquire_status(ipi_local_id, ipi_remote_id);
-		if ((ret & IPI_MB_STATUS_RECV_PENDING) && disable_irq)
+		if ((ret & IPI_MB_STATUS_RECV_PENDING) && disable_interrupt)
 			ipi_mb_disable_irq(ipi_local_id, ipi_remote_id);
 		SMC_RET1(handle, ret);
 	}
@@ -124,11 +124,11 @@
 	}
 	case IPI_MAILBOX_ACK:
 	{
-		int32_t enable_irq;
+		int32_t enable_interrupt;
 
-		enable_irq = (x3 & IPI_SMC_ACK_EIRQ_MASK) ? 1 : 0;
+		enable_interrupt = (x3 & IPI_SMC_ACK_EIRQ_MASK) ? 1 : 0;
 		ipi_mb_ack(ipi_local_id, ipi_remote_id);
-		if (enable_irq)
+		if (enable_interrupt)
 			ipi_mb_enable_irq(ipi_local_id, ipi_remote_id);
 		SMC_RET1(handle, 0);
 	}
diff --git a/plat/xilinx/common/plat_console.c b/plat/xilinx/common/plat_console.c
index b84912a..681226f 100644
--- a/plat/xilinx/common/plat_console.c
+++ b/plat/xilinx/common/plat_console.c
@@ -23,9 +23,64 @@
 #include <platform_def.h>
 #include <plat_private.h>
 
-static console_t console;
+#if !(CONSOLE_IS(none))
+static console_t boot_console;
+static console_holder boot_hd_console;
+#if defined(CONSOLE_RUNTIME)
+static console_t runtime_console;
+static console_holder rt_hd_console;
+#endif
+
+#if ((CONSOLE_IS(dtb) || RT_CONSOLE_IS(dtb)) && defined(XILINX_OF_BOARD_DTB_ADDR)) && \
+	(!defined(PLAT_zynqmp) || (defined(PLAT_zynqmp) && \
+				   !IS_TFA_IN_OCM(BL31_BASE)))
+static dt_uart_info_t dt_uart_info;
+#endif
+
+/**
+ * register_console() - Registers the uart with console list.
+ * @consoleh: Console holder structure with UART base address,
+ *  UART clock, UART buad rate, flags & console type
+ * @console: Pointer to the console information structure.
+ */
+static void register_console(const console_holder *consoleh, console_t *console)
+{
+	int32_t rc = 0;
+
+	switch (consoleh->console_type) {
+#if defined(PLAT_zynqmp)
+	case CONSOLE_CDNS:
+		rc = console_cdns_register(consoleh->base,
+				consoleh->clk,
+				consoleh->baud_rate,
+				console);
+		break;
+#else
+	case CONSOLE_PL011:
+		rc = console_pl011_register(consoleh->base,
+				consoleh->clk,
+				consoleh->baud_rate,
+				console);
+		break;
+#endif
+	case CONSOLE_DCC:
+		rc = console_dcc_register(console);
+		break;
+	default:
+		INFO("Invalid console type\n");
+		break;
+	}
 
-#if (defined(XILINX_OF_BOARD_DTB_ADDR) && !IS_TFA_IN_OCM(BL31_BASE))
+	if (rc == 0) {
+		panic();
+	}
+
+	console_set_scope(console, consoleh->console_scope);
+}
+
+#if ((CONSOLE_IS(dtb) || RT_CONSOLE_IS(dtb)) && defined(XILINX_OF_BOARD_DTB_ADDR)) && \
+	(!defined(PLAT_zynqmp) || (defined(PLAT_zynqmp) && \
+				   !IS_TFA_IN_OCM(BL31_BASE)))
 /**
  * get_baudrate() - Get the baudrate form DTB.
  * @dtb: Address of the Device Tree Blob (DTB).
@@ -103,34 +158,56 @@
  * @node: Node address in the device tree.
  * @dtb: Address of the Device Tree Blob(DTB).
  *
- * Return: On success, it returns 1; on failure, it returns an 0.
+ * Return: On success, it returns 0; on failure, it returns -1 or -FDT_ERR_NOTFOUND.
  */
-static uint32_t fdt_add_uart_info(dt_uart_info_t *info, int node, void *dtb)
+static int32_t fdt_add_uart_info(dt_uart_info_t *info, int node, void *dtb)
 {
 	uintptr_t base_addr;
 	const char *com;
 	int32_t ret = 0;
+	uint32_t status;
 
 	com = fdt_getprop(dtb, node, "compatible", NULL);
 	if (com != NULL) {
 		strlcpy(info->compatible, com, sizeof(info->compatible));
 	} else {
 		ERROR("Compatible property not found in DTB node\n");
-		ret  = -FDT_ERR_NOTFOUND;
+		ret = -FDT_ERR_NOTFOUND;
 		goto error;
 	}
 
-	ret = fdt_get_reg_props_by_index(dtb, node, 0, &base_addr, NULL);
-	if (ret >= 0) {
-		info->base = base_addr;
-	} else {
-		ERROR("Failed to retrieve base address. Error code: %d\n", ret);
-		ret  = -FDT_ERR_NOTFOUND;
+	status = get_node_status(dtb, node);
+	if (status == 0) {
+		ERROR("Uart node is disabled in DTB\n");
+		ret = -FDT_ERR_NOTFOUND;
 		goto error;
 	}
 
+	if (strncmp(info->compatible, DT_UART_DCC_COMPAT, strlen(DT_UART_DCC_COMPAT)) != 0) {
+		ret = fdt_get_reg_props_by_index(dtb, node, 0, &base_addr, NULL);
+		if (ret >= 0) {
+			info->base = base_addr;
+		} else {
+			ERROR("Failed to retrieve base address. Error code: %d\n", ret);
+			ret = -FDT_ERR_NOTFOUND;
+			goto error;
+		}
+
-	info->status = get_node_status(dtb, node);
-	info->baud_rate = get_baudrate(dtb);
+		info->baud_rate = get_baudrate(dtb);
+
+		if (strncmp(info->compatible, DT_UART_CAD_COMPAT,
+					strlen(DT_UART_CAD_COMPAT)) == 0) {
+			info->console_type = CONSOLE_CDNS;
+		} else if (strncmp(info->compatible, DT_UART_PL011_COMPAT,
+					strlen(DT_UART_PL011_COMPAT)) == 0) {
+			info->console_type = CONSOLE_PL011;
+		} else {
+			ERROR("Incompatible uart node in DTB\n");
+			ret = -FDT_ERR_NOTFOUND;
+		}
+	} else {
+		info->console_type = CONSOLE_DCC;
+	}
 
 error:
 	return ret;
@@ -150,194 +227,87 @@
 	ret = is_valid_dtb(dtb);
 	if (ret < 0) {
 		ERROR("Invalid Device Tree at %p: error %d\n", dtb, ret);
-		ret  = -FDT_ERR_NOTFOUND;
 		goto error;
 	}
 
 	node = fdt_get_stdout_node_offset(dtb);
 	if (node < 0) {
 		ERROR("DT get stdout node failed : %d\n", node);
-		ret  = -FDT_ERR_NOTFOUND;
 		goto error;
 	}
 
 	ret = fdt_add_uart_info(info, node, dtb);
 	if (ret < 0) {
 		ERROR("Failed to add DT UART info: %d\n", ret);
-		ret  = -FDT_ERR_NOTFOUND;
-		goto error;
-	}
-
-error:
-	return ret;
-}
-
-/**
- * check_fdt_uart_info() - Check early uart info with DTB uart info.
- * @info: Pointer to the UART information structure.
- *
- * Return: On success, it returns 0; on failure, it returns an error+reason.
- */
-static int32_t check_fdt_uart_info(dt_uart_info_t *info)
-{
-	int32_t ret = 0;
-
-	if (info->status == 0) {
-		ret = -ENODEV;
-		goto error;
-	}
-
-	if ((info->base == console.base) &&
-	   (info->baud_rate == UART_BAUDRATE) && !CONSOLE_IS(dcc)) {
-		ret = -ENODEV;
 		goto error;
 	}
 
 error:
 	return ret;
 }
-
-/**
- * console_boot_end() - Unregister the console_t instance form the console list.
- * @boot_console: Pointer to the console information structure.
- */
-static void console_boot_end(console_t *boot_console)
-{
-	if (CONSOLE_IS(dcc)) {
-		console_dcc_unregister();
-	} else {
-		console_flush();
-		(void)console_unregister(boot_console);
-	}
-}
-
-/**
- * setup_runtime_console() - Registers the runtime uart with console list.
- * @clock: UART clock.
- * @info: Pointer to the UART information structure.
- */
-static void setup_runtime_console(uint32_t clock, dt_uart_info_t *info)
-{
-	static console_t bl31_runtime_console;
-	int32_t rc;
-
-#if defined(PLAT_zynqmp)
-	rc = console_cdns_register(info->base,
-				   clock,
-				   info->baud_rate,
-				   &bl31_runtime_console);
-#else
-	rc = console_pl011_register(info->base,
-				    clock,
-				    info->baud_rate,
-				    &bl31_runtime_console);
 #endif
-	if (rc == 0) {
-		panic();
-	}
-
-	console_set_scope(&bl31_runtime_console,
-			  CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME |
-			  CONSOLE_FLAG_CRASH);
-}
 
-
-/**
- * runtime_console_init() - Initializes the run time console information.
- * @uart_info: Pointer to the UART information structure.
- * @bl31_boot_console: Pointer to the console information structure.
- * @clock: UART clock.
- *
- * Return: On success, it returns 0; on failure, it returns an error+reason;
- */
-static int32_t runtime_console_init(dt_uart_info_t *uart_info,
-			  console_t *bl31_boot_console,
-			  uint32_t clock)
+void setup_console(void)
 {
-	int32_t rc = 0;
+	/* This is hardcoded console setup just in case that DTB console fails */
+	boot_hd_console.base = (uintptr_t)UART_BASE;
+	boot_hd_console.baud_rate = (uint32_t)UART_BAUDRATE;
+	boot_hd_console.clk = get_uart_clk();
+	boot_hd_console.console_scope = CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH;
+	boot_hd_console.console_type = UART_TYPE;
 
-	/* Parse UART information from Device Tree Blob (DTB) */
-	rc = fdt_get_uart_info(uart_info);
-	if (rc < 0) {
-		rc = -FDT_ERR_NOTFOUND;
-		goto error;
-	}
+	/* For DT code decoding uncomment console registration below */
+	/* register_console(&boot_hd_console, &boot_console); */
 
-	if (strncmp(uart_info->compatible, DT_UART_COMPAT,
-		   strlen(DT_UART_COMPAT)) == 0) {
-
-		if (check_fdt_uart_info(uart_info) == 0) {
-			setup_runtime_console(clock, uart_info);
-			console_boot_end(bl31_boot_console);
-			INFO("Runtime console setup\n");
-		} else {
-			INFO("Early console and DTB console are same\n");
+#if ((CONSOLE_IS(dtb) || RT_CONSOLE_IS(dtb)) && defined(XILINX_OF_BOARD_DTB_ADDR)) && \
+	(!defined(PLAT_zynqmp) || (defined(PLAT_zynqmp) && \
+				   !IS_TFA_IN_OCM(BL31_BASE)))
+	/* Parse DTB console for UART information  */
+	if (fdt_get_uart_info(&dt_uart_info) == 0) {
+		if (CONSOLE_IS(dtb)) {
+			boot_hd_console.base = dt_uart_info.base;
+			boot_hd_console.baud_rate = dt_uart_info.baud_rate;
+			boot_hd_console.console_type = dt_uart_info.console_type;
 		}
-	} else if (strncmp(uart_info->compatible, DT_UART_DCC_COMPAT,
-			  strlen(DT_UART_DCC_COMPAT)) == 0) {
-		rc = console_dcc_register();
-		if (rc == 0) {
-			panic();
-		}
-		console_boot_end(bl31_boot_console);
 	} else {
-		WARN("BL31: No console device found in DT.\n");
+		ERROR("Failed to initialize DT console or console node is disabled\n");
 	}
-
-error:
-	return rc;
-}
 #endif
 
-void setup_console(void)
-{
-	int32_t rc;
-	uint32_t uart_clk = get_uart_clk();
+	/* Initialize the boot console */
+	register_console(&boot_hd_console, &boot_console);
 
-#if defined(PLAT_zynqmp)
-	if (CONSOLE_IS(cadence) || (CONSOLE_IS(cadence1))) {
-		rc = console_cdns_register(UART_BASE,
-					   uart_clk,
-					   UART_BAUDRATE,
-					   &console);
-		if (rc == 0) {
-			panic();
-		}
+	INFO("BL31: Early console setup\n");
 
-		console_set_scope(&console, CONSOLE_FLAG_BOOT |
-				  CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
-	}
+#ifdef CONSOLE_RUNTIME
+#if (RT_CONSOLE_IS(dtb) && defined(XILINX_OF_BOARD_DTB_ADDR)) && \
+	       (!defined(PLAT_zynqmp) || (defined(PLAT_zynqmp) && \
+					!IS_TFA_IN_OCM(BL31_BASE)))
+	rt_hd_console.base = dt_uart_info.base;
+	rt_hd_console.baud_rate = dt_uart_info.baud_rate;
+	rt_hd_console.console_type = dt_uart_info.console_type;
 #else
-	if (CONSOLE_IS(pl011) || (CONSOLE_IS(pl011_1))) {
-		/* Initialize the console to provide early debug support */
-		rc = console_pl011_register((uint32_t)UART_BASE,
-					   uart_clk,
-					   (uint32_t)UART_BAUDRATE,
-					   &console);
-		if (rc == 0) {
-			panic();
-		}
-
-		console_set_scope(&console, CONSOLE_FLAG_BOOT |
-				  CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH);
-	}
+	rt_hd_console.base = (uintptr_t)RT_UART_BASE;
+	rt_hd_console.baud_rate = (uint32_t)UART_BAUDRATE;
+	rt_hd_console.console_type = RT_UART_TYPE;
 #endif
-	if (CONSOLE_IS(dcc)) {
-		/* Initialize the dcc console for debug */
-		rc = console_dcc_register();
-		if (rc == 0) {
-			panic();
-		}
-	}
-	INFO("BL31: Early console setup\n");
 
-#if (defined(XILINX_OF_BOARD_DTB_ADDR) && !IS_TFA_IN_OCM(BL31_BASE))
-	static dt_uart_info_t uart_info = {0};
+	if ((rt_hd_console.console_type == boot_hd_console.console_type) &&
+			(rt_hd_console.base == boot_hd_console.base)) {
+		console_set_scope(&boot_console,
+				CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH | CONSOLE_FLAG_RUNTIME);
+		INFO("Successfully initialized runtime console\n");
+	} else {
+		rt_hd_console.clk = get_uart_clk();
+		rt_hd_console.console_scope = CONSOLE_FLAG_RUNTIME;
 
-	/* Initialize the runtime console using UART information from the DTB */
-	rc = runtime_console_init(&uart_info, &console, uart_clk);
-	if (rc < 0) {
-		ERROR("Failed to initialize runtime console: %d\n", rc);
+		register_console(&rt_hd_console, &runtime_console);
+		INFO("Successfully initialized new runtime console\n");
 	}
 #endif
 }
+#else
+void setup_console(void)
+{
+}
+#endif
diff --git a/plat/xilinx/common/plat_xfer_list.c b/plat/xilinx/common/plat_xfer_list.c
new file mode 100644
index 0000000..eae7ce4
--- /dev/null
+++ b/plat/xilinx/common/plat_xfer_list.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2023-2024, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <stddef.h>
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <lib/transfer_list.h>
+
+/*
+ * FIXME: This address should come from firmware before TF-A runs
+ * Having this to make sure the transfer list functionality works
+ */
+#define FW_HANDOFF_BASE		U(0x1200000)
+#define FW_HANDOFF_SIZE		U(0x600000)
+
+static struct transfer_list_header *tl_hdr;
+
+int32_t transfer_list_populate_ep_info(entry_point_info_t *bl32,
+				       entry_point_info_t *bl33)
+{
+	struct transfer_list_entry *te = NULL;
+	struct entry_point_info *ep;
+	int32_t ret;
+
+	tl_hdr = (struct transfer_list_header *)FW_HANDOFF_BASE;
+	ret = transfer_list_check_header(tl_hdr);
+	if ((ret == TL_OPS_ALL) || (ret == TL_OPS_RO)) {
+		transfer_list_dump(tl_hdr);
+		while ((te = transfer_list_next(tl_hdr, te)) != NULL) {
+			ep = transfer_list_entry_data(te);
+			if (te->tag_id == TL_TAG_EXEC_EP_INFO64) {
+				switch (GET_SECURITY_STATE(ep->h.attr)) {
+				case NON_SECURE:
+					*bl33 = *ep;
+					continue;
+				case SECURE:
+					*bl32 = *ep;
+					continue;
+				default:
+					ERROR("Unrecognized Image Security State %lu\n",
+					      GET_SECURITY_STATE(ep->h.attr));
+					ret = TL_OPS_NON;
+				}
+			}
+		}
+	}
+	return ret;
+}
diff --git a/plat/xilinx/versal/include/versal_def.h b/plat/xilinx/versal/include/versal_def.h
index c50df7e..3a1c127 100644
--- a/plat/xilinx/versal/include/versal_def.h
+++ b/plat/xilinx/versal/include/versal_def.h
@@ -18,13 +18,24 @@
 /* number of interrupt handlers. increase as required */
 #define MAX_INTR_EL3			2
 /* List all consoles */
+#define VERSAL_CONSOLE_ID_none		0
 #define VERSAL_CONSOLE_ID_pl011	1
 #define VERSAL_CONSOLE_ID_pl011_0	1
 #define VERSAL_CONSOLE_ID_pl011_1	2
 #define VERSAL_CONSOLE_ID_dcc		3
+#define VERSAL_CONSOLE_ID_dtb		4
 
 #define CONSOLE_IS(con)	(VERSAL_CONSOLE_ID_ ## con == VERSAL_CONSOLE)
 
+/* Runtime console */
+#define RT_CONSOLE_ID_pl011	1
+#define RT_CONSOLE_ID_pl011_0	1
+#define RT_CONSOLE_ID_pl011_1	2
+#define RT_CONSOLE_ID_dcc	3
+#define RT_CONSOLE_ID_dtb	4
+
+#define RT_CONSOLE_IS(con)	(RT_CONSOLE_ID_ ## con == CONSOLE_RUNTIME)
+
 /* List of platforms */
 #define VERSAL_SILICON              U(0)
 #define VERSAL_SPP                  U(1)
@@ -63,14 +74,37 @@
 #define VERSAL_UART0_BASE		0xFF000000
 #define VERSAL_UART1_BASE		0xFF010000
 
-#if CONSOLE_IS(pl011) || CONSOLE_IS(dcc)
+#if CONSOLE_IS(pl011) || CONSOLE_IS(dtb)
 # define UART_BASE	VERSAL_UART0_BASE
+# define UART_TYPE	CONSOLE_PL011
 #elif CONSOLE_IS(pl011_1)
 # define UART_BASE	VERSAL_UART1_BASE
+# define UART_TYPE	CONSOLE_PL011
+#elif CONSOLE_IS(dcc)
+# define UART_BASE	0x0
+# define UART_TYPE	CONSOLE_DCC
+#elif CONSOLE_IS(none)
+# define UART_TYPE	CONSOLE_NONE
 #else
 # error "invalid VERSAL_CONSOLE"
 #endif
 
+/* Runtime console */
+#if defined(CONSOLE_RUNTIME)
+#if RT_CONSOLE_IS(pl011) || RT_CONSOLE_IS(dtb)
+# define RT_UART_BASE VERSAL_UART0_BASE
+# define RT_UART_TYPE	CONSOLE_PL011
+#elif RT_CONSOLE_IS(pl011_1)
+# define RT_UART_BASE VERSAL_UART1_BASE
+# define RT_UART_TYPE	CONSOLE_PL011
+#elif RT_CONSOLE_IS(dcc)
+# define RT_UART_BASE	0x0
+# define RT_UART_TYPE	CONSOLE_DCC
+#else
+# error "invalid CONSOLE_RUNTIME"
+#endif
+#endif
+
 /*******************************************************************************
  * Platform related constants
  ******************************************************************************/
diff --git a/plat/xilinx/versal/plat_psci.c b/plat/xilinx/versal/plat_psci.c
index 74c5bf3..a299d14 100644
--- a/plat/xilinx/versal/plat_psci.c
+++ b/plat/xilinx/versal/plat_psci.c
@@ -250,7 +250,7 @@
 
 	uint32_t pstate = psci_get_pstate_type(power_state);
 
-	assert(req_state);
+	assert(req_state != NULL);
 
 	/* Sanity check the requested state */
 	if (pstate == PSTATE_TYPE_STANDBY) {
diff --git a/plat/xilinx/versal/platform.mk b/plat/xilinx/versal/platform.mk
index e65800e..7c15be0 100644
--- a/plat/xilinx/versal/platform.mk
+++ b/plat/xilinx/versal/platform.mk
@@ -85,13 +85,27 @@
 				${XLAT_TABLES_LIB_SRCS}
 
 VERSAL_CONSOLE	?=	pl011
-ifeq (${VERSAL_CONSOLE}, $(filter ${VERSAL_CONSOLE},pl011 pl011_0 pl011_1 dcc))
+ifeq (${VERSAL_CONSOLE}, $(filter ${VERSAL_CONSOLE},pl011 pl011_0 pl011_1 dcc dtb none))
 else
   $(error "Please define VERSAL_CONSOLE")
 endif
 
 $(eval $(call add_define_val,VERSAL_CONSOLE,VERSAL_CONSOLE_ID_${VERSAL_CONSOLE}))
 
+# Runtime console in default console in DEBUG build
+ifeq ($(DEBUG), 1)
+CONSOLE_RUNTIME ?= pl011
+endif
+
+# Runtime console
+ifdef CONSOLE_RUNTIME
+ifeq (${CONSOLE_RUNTIME}, $(filter ${CONSOLE_RUNTIME},pl011 pl011_0 pl011_1 dcc dtb))
+$(eval $(call add_define_val,CONSOLE_RUNTIME,RT_CONSOLE_ID_${CONSOLE_RUNTIME}))
+else
+$(error "Please define CONSOLE_RUNTIME")
+endif
+endif
+
 BL31_SOURCES		+=	drivers/arm/cci/cci.c				\
 				lib/cpus/aarch64/cortex_a72.S			\
 				common/fdt_wrappers.c                           \
diff --git a/plat/xilinx/versal_net/include/versal_net_def.h b/plat/xilinx/versal_net/include/versal_net_def.h
index e7d234b..5caf376 100644
--- a/plat/xilinx/versal_net/include/versal_net_def.h
+++ b/plat/xilinx/versal_net/include/versal_net_def.h
@@ -15,13 +15,24 @@
 #define MAX_INTR_EL3			2
 
 /* List all consoles */
+#define VERSAL_NET_CONSOLE_ID_none	U(0)
 #define VERSAL_NET_CONSOLE_ID_pl011	U(1)
 #define VERSAL_NET_CONSOLE_ID_pl011_0	U(1)
 #define VERSAL_NET_CONSOLE_ID_pl011_1	U(2)
 #define VERSAL_NET_CONSOLE_ID_dcc	U(3)
+#define VERSAL_NET_CONSOLE_ID_dtb	U(4)
 
 #define CONSOLE_IS(con)	(VERSAL_NET_CONSOLE_ID_ ## con == VERSAL_NET_CONSOLE)
 
+/* Runtime console */
+#define RT_CONSOLE_ID_pl011    1
+#define RT_CONSOLE_ID_pl011_0  1
+#define RT_CONSOLE_ID_pl011_1  2
+#define RT_CONSOLE_ID_dcc      3
+#define RT_CONSOLE_ID_dtb      4
+
+#define RT_CONSOLE_IS(con)     (RT_CONSOLE_ID_ ## con == CONSOLE_RUNTIME)
+
 /* List all platforms */
 #define VERSAL_NET_SILICON		U(0)
 #define VERSAL_NET_SPP			U(1)
@@ -138,11 +149,35 @@
 
 #define UART_BAUDRATE	115200
 
-#if CONSOLE_IS(pl011_1)
-#define UART_BASE		VERSAL_NET_UART1_BASE
+#if CONSOLE_IS(pl011) || CONSOLE_IS(dtb)
+#define UART_BASE		VERSAL_NET_UART0_BASE
+# define UART_TYPE	CONSOLE_PL011
+#elif CONSOLE_IS(pl011_1)
+#define UART_BASE            VERSAL_NET_UART1_BASE
+# define UART_TYPE	CONSOLE_PL011
+#elif CONSOLE_IS(dcc)
+# define UART_BASE	0x0
+# define UART_TYPE	CONSOLE_DCC
+#elif CONSOLE_IS(none)
+# define UART_TYPE	CONSOLE_NONE
+#else
+# error "invalid VERSAL_NET_CONSOLE"
+#endif
+
+/* Runtime console */
+#if defined(CONSOLE_RUNTIME)
+#if RT_CONSOLE_IS(pl011) || RT_CONSOLE_IS(dtb)
+# define RT_UART_BASE VERSAL_NET_UART0_BASE
+# define RT_UART_TYPE	CONSOLE_PL011
+#elif RT_CONSOLE_IS(pl011_1)
+# define RT_UART_BASE VERSAL_NET_UART1_BASE
+# define RT_UART_TYPE	CONSOLE_PL011
+#elif RT_CONSOLE_IS(dcc)
+# define RT_UART_BASE	0x0
+# define RT_UART_TYPE	CONSOLE_DCC
 #else
-/* Default console is UART0 */
-#define UART_BASE            VERSAL_NET_UART0_BASE
+# error "invalid CONSOLE_RUNTIME"
+#endif
 #endif
 
 /* Processor core device IDs */
diff --git a/plat/xilinx/versal_net/plat_psci_pm.c b/plat/xilinx/versal_net/plat_psci_pm.c
index fb2005d..7a653d4 100644
--- a/plat/xilinx/versal_net/plat_psci_pm.c
+++ b/plat/xilinx/versal_net/plat_psci_pm.c
@@ -247,7 +247,7 @@
 
 	int32_t pstate = psci_get_pstate_type(power_state);
 
-	assert(req_state);
+	assert(req_state != NULL);
 
 	/* Sanity check the requested state */
 	if (pstate == PSTATE_TYPE_STANDBY) {
diff --git a/plat/xilinx/versal_net/platform.mk b/plat/xilinx/versal_net/platform.mk
index 40e9206..9534118 100644
--- a/plat/xilinx/versal_net/platform.mk
+++ b/plat/xilinx/versal_net/platform.mk
@@ -60,7 +60,7 @@
 HW_ASSISTED_COHERENCY := 1
 
 VERSAL_NET_CONSOLE	?=	pl011
-ifeq (${VERSAL_NET_CONSOLE}, $(filter ${VERSAL_NET_CONSOLE},pl011 pl011_0 pl011_1 dcc))
+ifeq (${VERSAL_NET_CONSOLE}, $(filter ${VERSAL_NET_CONSOLE},pl011 pl011_0 pl011_1 dcc dtb none))
 else
   $(error Please define VERSAL_NET_CONSOLE)
 endif
@@ -71,6 +71,20 @@
 $(eval $(call add_define,XILINX_OF_BOARD_DTB_ADDR))
 endif
 
+# Runtime console in default console in DEBUG build
+ifeq ($(DEBUG), 1)
+CONSOLE_RUNTIME ?= pl011
+endif
+
+# Runtime console
+ifdef CONSOLE_RUNTIME
+ifeq (${CONSOLE_RUNTIME}, $(filter ${CONSOLE_RUNTIME},pl011 pl011_0 pl011_1 dcc dtb))
+$(eval $(call add_define_val,CONSOLE_RUNTIME,RT_CONSOLE_ID_${CONSOLE_RUNTIME}))
+else
+$(error "Please define CONSOLE_RUNTIME")
+endif
+endif
+
 # enable assert() for release/debug builds
 ENABLE_ASSERTIONS := 1
 
diff --git a/plat/xilinx/zynqmp/include/zynqmp_def.h b/plat/xilinx/zynqmp/include/zynqmp_def.h
index d715ce2..68485cf 100644
--- a/plat/xilinx/zynqmp/include/zynqmp_def.h
+++ b/plat/xilinx/zynqmp/include/zynqmp_def.h
@@ -10,13 +10,24 @@
 #include <plat/arm/common/smccc_def.h>
 #include <plat/common/common_def.h>
 
+#define ZYNQMP_CONSOLE_ID_none		0
 #define ZYNQMP_CONSOLE_ID_cadence	1
 #define ZYNQMP_CONSOLE_ID_cadence0	1
 #define ZYNQMP_CONSOLE_ID_cadence1	2
 #define ZYNQMP_CONSOLE_ID_dcc		3
+#define ZYNQMP_CONSOLE_ID_dtb		4
 
 #define CONSOLE_IS(con)	(ZYNQMP_CONSOLE_ID_ ## con == ZYNQMP_CONSOLE)
 
+/* Runtime console */
+#define RT_CONSOLE_ID_cadence	1
+#define RT_CONSOLE_ID_cadence0	1
+#define RT_CONSOLE_ID_cadence1	2
+#define RT_CONSOLE_ID_dcc	3
+#define RT_CONSOLE_ID_dtb	4
+
+#define RT_CONSOLE_IS(con)	(RT_CONSOLE_ID_ ## con == CONSOLE_RUNTIME)
+
 /* Default counter frequency */
 #define ZYNQMP_DEFAULT_COUNTER_FREQ	0U
 
@@ -144,14 +155,38 @@
 #define ZYNQMP_UART0_BASE		U(0xFF000000)
 #define ZYNQMP_UART1_BASE		U(0xFF010000)
 
-#if CONSOLE_IS(cadence) || CONSOLE_IS(dcc)
+/* Boot console */
+#if CONSOLE_IS(cadence) || CONSOLE_IS(dtb)
 # define UART_BASE	ZYNQMP_UART0_BASE
+# define UART_TYPE	CONSOLE_CDNS
 #elif CONSOLE_IS(cadence1)
 # define UART_BASE	ZYNQMP_UART1_BASE
+# define UART_TYPE	CONSOLE_CDNS
+#elif CONSOLE_IS(dcc)
+# define UART_BASE	0x0
+# define UART_TYPE	CONSOLE_DCC
+#elif CONSOLE_IS(none)
+# define UART_TYPE	CONSOLE_NONE
 #else
 # error "invalid ZYNQMP_CONSOLE"
 #endif
 
+/* Runtime console */
+#if defined(CONSOLE_RUNTIME)
+#if RT_CONSOLE_IS(cadence) || RT_CONSOLE_IS(dtb)
+# define RT_UART_BASE	ZYNQMP_UART0_BASE
+# define RT_UART_TYPE	CONSOLE_CDNS
+#elif RT_CONSOLE_IS(cadence1)
+# define RT_UART_BASE	ZYNQMP_UART1_BASE
+# define RT_UART_TYPE	CONSOLE_CDNS
+#elif RT_CONSOLE_IS(dcc)
+# define RT_UART_BASE	0x0
+# define RT_UART_TYPE	CONSOLE_DCC
+#else
+# error "invalid CONSOLE_RUNTIME"
+#endif
+#endif
+
 /* Must be non zero */
 #define UART_BAUDRATE		115200
 
diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk
index 9fdc649..5a86658 100644
--- a/plat/xilinx/zynqmp/platform.mk
+++ b/plat/xilinx/zynqmp/platform.mk
@@ -111,12 +111,26 @@
 				${XLAT_TABLES_LIB_SRCS}
 
 ZYNQMP_CONSOLE	?=	cadence
-ifeq (${ZYNQMP_CONSOLE}, $(filter ${ZYNQMP_CONSOLE},cadence cadence0 cadence1 dcc))
+ifeq (${ZYNQMP_CONSOLE}, $(filter ${ZYNQMP_CONSOLE},cadence cadence0 cadence1 dcc dtb none))
 else
   $(error "Please define ZYNQMP_CONSOLE")
 endif
 $(eval $(call add_define_val,ZYNQMP_CONSOLE,ZYNQMP_CONSOLE_ID_${ZYNQMP_CONSOLE}))
 
+# Runtime console in default console in DEBUG build
+ifeq ($(DEBUG), 1)
+CONSOLE_RUNTIME ?= cadence
+endif
+
+# Runtime console
+ifdef CONSOLE_RUNTIME
+ifeq (${CONSOLE_RUNTIME}, $(filter ${CONSOLE_RUNTIME},cadence cadence0 cadence1 dcc dtb))
+$(eval $(call add_define_val,CONSOLE_RUNTIME,RT_CONSOLE_ID_${CONSOLE_RUNTIME}))
+else
+$(error "Please define CONSOLE_RUNTIME")
+endif
+endif
+
 # Build PM code as a Library
 include plat/xilinx/zynqmp/libpm.mk
 
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
index 9682e59..5a1e218 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
@@ -2791,7 +2791,7 @@
 {
 	struct pm_pll *pll = pm_clock_get_pll(clock_id);
 
-	if (pll) {
+	if (pll != NULL) {
 		*node_id = pll->nid;
 		return PM_RET_SUCCESS;
 	}
@@ -2883,7 +2883,7 @@
 	enum pm_ret_status status;
 	enum pm_pll_mode mode;
 
-	if ((pll == NULL) || !state) {
+	if ((pll == NULL) || (state == NULL)) {
 		return PM_RET_ERROR_ARGS;
 	}
 
@@ -3013,7 +3013,7 @@
 {
 	struct pm_pll *pll = pm_clock_get_pll(clock_id);
 
-	if ((pll == NULL) || !mode) {
+	if ((pll == NULL) || (mode == NULL)) {
 		return PM_RET_ERROR_ARGS;
 	}
 	*mode = pll->mode;
diff --git a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c
index daf3e61..d7c9f24 100644
--- a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c
@@ -1150,7 +1150,7 @@
 
 	/* First try to handle it as a PLL */
 	pll = pm_clock_get_pll(clock_id);
-	if (pll) {
+	if (pll != NULL) {
 		return pm_clock_pll_enable(pll);
 	}
 
@@ -1175,7 +1175,7 @@
 
 	/* First try to handle it as a PLL */
 	pll = pm_clock_get_pll(clock_id);
-	if (pll) {
+	if (pll != NULL) {
 		return pm_clock_pll_disable(pll);
 	}
 
@@ -1203,9 +1203,9 @@
 
 	/* First try to handle it as a PLL */
 	pll = pm_clock_get_pll(clock_id);
-	if (pll)
+	if (pll != NULL) {
 		return pm_clock_pll_get_state(pll, state);
-
+	}
 	/* Check if clock ID is a valid on-chip clock */
 	status = pm_clock_id_is_valid(clock_id);
 	if (status != PM_RET_SUCCESS) {
@@ -1341,7 +1341,7 @@
 
 	/* First try to handle it as a PLL */
 	pll = pm_clock_get_pll_by_related_clk(clock_id);
-	if (pll) {
+	if (pll != NULL) {
 		return pm_clock_pll_set_parent(pll, clock_id, parent_index);
 	}
 
@@ -1376,7 +1376,7 @@
 
 	/* First try to handle it as a PLL */
 	pll = pm_clock_get_pll_by_related_clk(clock_id);
-	if (pll) {
+	if (pll != NULL) {
 		return pm_clock_pll_get_parent(pll, clock_id, parent_index);
 	}
 
diff --git a/services/std_svc/rmmd/rmmd_attest.c b/services/std_svc/rmmd/rmmd_attest.c
index f73236c..7d4ea70 100644
--- a/services/std_svc/rmmd/rmmd_attest.c
+++ b/services/std_svc/rmmd/rmmd_attest.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2024, NVIDIA Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,7 +13,8 @@
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #include <plat/common/platform.h>
 #include "rmmd_private.h"
-#include <services/rmmd_svc.h>
+#include <services/rmm_el3_token_sign.h>
+#include <smccc_helpers.h>
 
 static spinlock_t lock;
 
@@ -156,10 +158,110 @@
 						 (unsigned int)ecc_curve);
 	if (err != 0) {
 		ERROR("Failed to get attestation key: %d.\n", err);
-		err =  E_RMM_UNK;
+		err = E_RMM_UNK;
 	}
 
 	spin_unlock(&lock);
 
 	return err;
 }
+
+static int rmmd_el3_token_sign_push_req(uint64_t buf_pa, uint64_t buf_size)
+{
+	int err;
+
+	err = validate_buffer_params(buf_pa, buf_size);
+	if (err != 0) {
+		return err;
+	}
+
+	if (buf_size < sizeof(struct el3_token_sign_request)) {
+		return E_RMM_INVAL;
+	}
+
+	spin_lock(&lock);
+
+	/* Call platform port to handle attestation toekn signing request. */
+	err = plat_rmmd_el3_token_sign_push_req((struct el3_token_sign_request *)buf_pa);
+
+	spin_unlock(&lock);
+
+	return err;
+}
+
+static int rmmd_el3_token_sign_pull_resp(uint64_t buf_pa, uint64_t buf_size)
+{
+	int err;
+
+	err = validate_buffer_params(buf_pa, buf_size);
+	if (err != 0) {
+		return err;
+	}
+
+
+	if (buf_size < sizeof(struct el3_token_sign_response)) {
+		return E_RMM_INVAL;
+	}
+
+	spin_lock(&lock);
+
+	/* Pull attestation signing response from HES. */
+	err = plat_rmmd_el3_token_sign_pull_resp(
+			(struct el3_token_sign_response *)buf_pa);
+
+	spin_unlock(&lock);
+
+	return err;
+}
+
+static int rmmd_attest_get_attest_pub_key(uint64_t buf_pa, uint64_t *buf_size,
+				   uint64_t ecc_curve)
+{
+	int err;
+
+	err = validate_buffer_params(buf_pa, *buf_size);
+	if (err != 0) {
+		return err;
+	}
+
+	if (ecc_curve != ATTEST_KEY_CURVE_ECC_SECP384R1) {
+		ERROR("Invalid ECC curve specified\n");
+		return E_RMM_INVAL;
+	}
+
+	spin_lock(&lock);
+
+	/* Get the Realm attestation public key from platform port. */
+	err = plat_rmmd_el3_token_sign_get_rak_pub(
+		(uintptr_t)buf_pa, buf_size, (unsigned int)ecc_curve);
+
+	spin_unlock(&lock);
+	if (err != 0) {
+		ERROR("Failed to get attestation public key from HES: %d.\n",
+		      err);
+		err = E_RMM_UNK;
+	}
+
+
+	return err;
+}
+
+uint64_t rmmd_el3_token_sign(void *handle, uint64_t opcode, uint64_t x2,
+				    uint64_t x3, uint64_t x4)
+{
+	int ret;
+
+	switch (opcode) {
+	case RMM_EL3_TOKEN_SIGN_PUSH_REQ_OP:
+		ret = rmmd_el3_token_sign_push_req(x2, x3);
+		SMC_RET1(handle, ret);
+	case RMM_EL3_TOKEN_SIGN_PULL_RESP_OP:
+		ret = rmmd_el3_token_sign_pull_resp(x2, x3);
+		SMC_RET1(handle, ret);
+	case RMM_EL3_TOKEN_SIGN_GET_RAK_PUB_OP:
+		ret = rmmd_attest_get_attest_pub_key(x2, &x3, x4);
+		SMC_RET2(handle, ret, x3);
+	default:
+		SMC_RET1(handle, SMC_UNK);
+	}
+}
diff --git a/services/std_svc/rmmd/rmmd_main.c b/services/std_svc/rmmd/rmmd_main.c
index 153bb01..d063ea3 100644
--- a/services/std_svc/rmmd/rmmd_main.c
+++ b/services/std_svc/rmmd/rmmd_main.c
@@ -441,6 +441,21 @@
 	return ret;
 }
 
+static int rmm_el3_ifc_get_feat_register(uint64_t feat_reg_idx,
+					 uint64_t *feat_reg)
+{
+	if (feat_reg_idx != RMM_EL3_FEAT_REG_0_IDX) {
+		ERROR("RMMD: Failed to get feature register %ld\n", feat_reg_idx);
+		return E_RMM_INVAL;
+	}
+
+	*feat_reg = 0UL;
+#if RMMD_ENABLE_EL3_TOKEN_SIGN
+	*feat_reg |= RMM_EL3_FEAT_REG_0_EL3_TOKEN_SIGN_MASK;
+#endif
+	return E_RMM_OK;
+}
+
 /*******************************************************************************
  * This function handles RMM-EL3 interface SMCs
  ******************************************************************************/
@@ -448,7 +463,7 @@
 				uint64_t x3, uint64_t x4, void *cookie,
 				void *handle, uint64_t flags)
 {
-	uint64_t remaining_len = 0;
+	uint64_t remaining_len = 0UL;
 	uint32_t src_sec_state;
 	int ret;
 
@@ -479,7 +494,13 @@
 	case RMM_ATTEST_GET_REALM_KEY:
 		ret = rmmd_attest_get_signing_key(x1, &x2, x3);
 		SMC_RET2(handle, ret, x2);
-
+	case RMM_EL3_FEATURES:
+		ret = rmm_el3_ifc_get_feat_register(x1, &x2);
+		SMC_RET2(handle, ret, x2);
+#if RMMD_ENABLE_EL3_TOKEN_SIGN
+	case RMM_EL3_TOKEN_SIGN:
+		return rmmd_el3_token_sign(handle, x1, x2, x3, x4);
+#endif
 	case RMM_BOOT_COMPLETE:
 		VERBOSE("RMMD: running rmmd_rmm_sync_exit\n");
 		rmmd_rmm_sync_exit(x1);
diff --git a/services/std_svc/rmmd/rmmd_private.h b/services/std_svc/rmmd/rmmd_private.h
index 6d3b5ec..0ce104d 100644
--- a/services/std_svc/rmmd/rmmd_private.h
+++ b/services/std_svc/rmmd/rmmd_private.h
@@ -51,6 +51,8 @@
 				   uint64_t *remaining_len);
 int rmmd_attest_get_signing_key(uint64_t buf_pa, uint64_t *buf_size,
 				uint64_t ecc_curve);
+uint64_t rmmd_el3_token_sign(void *handle, uint64_t x1, uint64_t x2,
+				    uint64_t x3, uint64_t x4);
 
 /* Assembly helpers */
 uint64_t rmmd_rmm_enter(uint64_t *c_rt_ctx);