Merge changes Id942c20c,Idd286bea,I8917a26e,Iec8c3477,If3c25dcd, ... into integration

* changes:
  feat(cpufeat): enable FEAT_PAuth to FEAT_STATE_CHECKED
  perf(cpufeat): centralise PAuth key saving
  refactor(cpufeat): convert FEAT_PAuth setup to C
  refactor(cpufeat): prepare FEAT_PAuth for FEATURE_DETECTION
  chore(cpufeat): remove PAuth presence checks
  feat(cpufeat): enable FEAT_BTI to FEAT_STATE_CHECKED
diff --git a/Makefile b/Makefile
index fd55f03..4f6afaf 100644
--- a/Makefile
+++ b/Makefile
@@ -148,7 +148,7 @@
 		TF_CFLAGS_aarch64	:=	-target aarch64-arm-none-eabi
 	else
 		TF_CFLAGS_aarch32	=	$(target32-directive)
-		TF_CFLAGS_aarch64	:=	-target aarch64-elf
+		TF_CFLAGS_aarch64	:=	-target aarch64-unknown-none-elf
 	endif
 
 else ifeq ($($(ARCH)-cc-id),gnu-gcc)
@@ -1244,6 +1244,7 @@
 	DISCRETE_TPM \
 	DICE_PROTECTION_ENVIRONMENT \
 	RMMD_ENABLE_EL3_TOKEN_SIGN \
+	RMMD_ENABLE_IDE_KEY_PROG \
 	DRTM_SUPPORT \
 	NS_TIMER_SWITCH \
 	OVERRIDE_LIBC \
@@ -1410,6 +1411,7 @@
 	ENABLE_PSCI_STAT \
 	ENABLE_RME \
 	RMMD_ENABLE_EL3_TOKEN_SIGN \
+	RMMD_ENABLE_IDE_KEY_PROG \
 	ENABLE_RUNTIME_INSTRUMENTATION \
 	ENABLE_SME_FOR_NS \
 	ENABLE_SME2_FOR_NS \
diff --git a/bl32/tsp/tsp_common.c b/bl32/tsp/tsp_common.c
index 8a5b059..e69c054 100644
--- a/bl32/tsp/tsp_common.c
+++ b/bl32/tsp/tsp_common.c
@@ -96,7 +96,7 @@
 	tsp_stats[linear_id].eret_count++;
 
 	INFO("TSP: cpu 0x%lx SYSTEM_OFF request\n", read_mpidr());
-	INFO("TSP: cpu 0x%lx: %d smcs, %d erets requests\n", read_mpidr(),
+	INFO("TSP: cpu 0x%lx: %u smcs, %u erets requests\n", read_mpidr(),
 	     tsp_stats[linear_id].smc_count,
 	     tsp_stats[linear_id].eret_count);
 
@@ -124,7 +124,7 @@
 	tsp_stats[linear_id].eret_count++;
 
 	INFO("TSP: cpu 0x%lx SYSTEM_RESET request\n", read_mpidr());
-	INFO("TSP: cpu 0x%lx: %d smcs, %d erets requests\n", read_mpidr(),
+	INFO("TSP: cpu 0x%lx: %u smcs, %u erets requests\n", read_mpidr(),
 	     tsp_stats[linear_id].smc_count,
 	     tsp_stats[linear_id].eret_count);
 
diff --git a/bl32/tsp/tsp_interrupt.c b/bl32/tsp/tsp_interrupt.c
index a847b6c..9d86e3e 100644
--- a/bl32/tsp/tsp_interrupt.c
+++ b/bl32/tsp/tsp_interrupt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -37,8 +37,8 @@
 
 	VERBOSE("TSP: cpu 0x%lx sync s-el1 interrupt request from 0x%" PRIx64 "\n",
 		read_mpidr(), elr_el3);
-	VERBOSE("TSP: cpu 0x%lx: %d sync s-el1 interrupt requests,"
-		" %d sync s-el1 interrupt returns\n",
+	VERBOSE("TSP: cpu 0x%lx: %u sync s-el1 interrupt requests,"
+		" %u sync s-el1 interrupt returns\n",
 		read_mpidr(),
 		tsp_stats[linear_id].sync_sel1_intr_count,
 		tsp_stats[linear_id].sync_sel1_intr_ret_count);
@@ -54,7 +54,7 @@
 	uint32_t linear_id = plat_my_core_pos();
 
 	tsp_stats[linear_id].preempt_intr_count++;
-	VERBOSE("TSP: cpu 0x%lx: %d preempt interrupt requests\n",
+	VERBOSE("TSP: cpu 0x%lx: %u preempt interrupt requests\n",
 		read_mpidr(), tsp_stats[linear_id].preempt_intr_count);
 	return TSP_PREEMPTED;
 }
@@ -107,9 +107,9 @@
 
 	/* Update the statistics and print some messages */
 	tsp_stats[linear_id].sel1_intr_count++;
-	VERBOSE("TSP: cpu 0x%lx handled S-EL1 interrupt %d\n",
+	VERBOSE("TSP: cpu 0x%lx handled S-EL1 interrupt %u\n",
 	       read_mpidr(), id);
-	VERBOSE("TSP: cpu 0x%lx: %d S-EL1 requests\n",
+	VERBOSE("TSP: cpu 0x%lx: %u S-EL1 requests\n",
 	     read_mpidr(), tsp_stats[linear_id].sel1_intr_count);
 	return 0;
 }
diff --git a/bl32/tsp/tsp_main.c b/bl32/tsp/tsp_main.c
index 8c6b2ed..1b7116a 100644
--- a/bl32/tsp/tsp_main.c
+++ b/bl32/tsp/tsp_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -47,7 +47,7 @@
 	tsp_stats[linear_id].eret_count++;
 	tsp_stats[linear_id].cpu_on_count++;
 
-	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n",
+	INFO("TSP: cpu 0x%lx: %u smcs, %u erets %u cpu on requests\n",
 	     read_mpidr(),
 	     tsp_stats[linear_id].smc_count,
 	     tsp_stats[linear_id].eret_count,
@@ -75,7 +75,7 @@
 	tsp_stats[linear_id].cpu_on_count++;
 
 	INFO("TSP: cpu 0x%lx turned on\n", read_mpidr());
-	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n",
+	INFO("TSP: cpu 0x%lx: %u smcs, %u erets %u cpu on requests\n",
 		read_mpidr(),
 		tsp_stats[linear_id].smc_count,
 		tsp_stats[linear_id].eret_count,
@@ -112,7 +112,7 @@
 	tsp_stats[linear_id].cpu_off_count++;
 
 	INFO("TSP: cpu 0x%lx off request\n", read_mpidr());
-	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu off requests\n",
+	INFO("TSP: cpu 0x%lx: %u smcs, %u erets %u cpu off requests\n",
 		read_mpidr(),
 		tsp_stats[linear_id].smc_count,
 		tsp_stats[linear_id].eret_count,
@@ -150,7 +150,7 @@
 	tsp_stats[linear_id].eret_count++;
 	tsp_stats[linear_id].cpu_suspend_count++;
 
-	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n",
+	INFO("TSP: cpu 0x%lx: %u smcs, %u erets %u cpu suspend requests\n",
 		read_mpidr(),
 		tsp_stats[linear_id].smc_count,
 		tsp_stats[linear_id].eret_count,
@@ -184,9 +184,9 @@
 	tsp_stats[linear_id].eret_count++;
 	tsp_stats[linear_id].cpu_resume_count++;
 
-	INFO("TSP: cpu 0x%lx resumed. maximum off power level %" PRId64 "\n",
+	INFO("TSP: cpu 0x%lx resumed. maximum off power level %" PRIu64 "\n",
 	     read_mpidr(), max_off_pwrlvl);
-	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu resume requests\n",
+	INFO("TSP: cpu 0x%lx: %u smcs, %u erets %u cpu resume requests\n",
 		read_mpidr(),
 		tsp_stats[linear_id].smc_count,
 		tsp_stats[linear_id].eret_count,
@@ -224,7 +224,7 @@
 	INFO("TSP: cpu 0x%lx received %s smc 0x%" PRIx64 "\n", read_mpidr(),
 		((func >> 31) & 1) == 1 ? "fast" : "yielding",
 		func);
-	INFO("TSP: cpu 0x%lx: %d smcs, %d erets\n", read_mpidr(),
+	INFO("TSP: cpu 0x%lx: %u smcs, %u erets\n", read_mpidr(),
 		tsp_stats[linear_id].smc_count,
 		tsp_stats[linear_id].eret_count);
 
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index 9e6f613..a011297 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -592,10 +592,10 @@
 
 Arm Total Compute platform port
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:|M|: Vishnu Banavath <vishnu.banavath@arm.com>
-:|G|: `vishnu-banavath`_
-:|M|: Rupinderjit Singh <rupinderjit.singh@arm.com>
-:|G|: `rupsin01`_
+:|M|: Artem Kopotev <artem.kopotev@arm.com>
+:|G|: `artkopotev`_
+:|M|: Oleksandr Tarhunakov <Oleksandr.Tarhunakov@arm.com>
+:|G|: `o-tarhunakov`_
 :|F|: plat/arm/board/tc
 
 Arm Automotive RD platform port
@@ -1113,7 +1113,7 @@
 .. _remi-triplefault: https://github.com/repk
 .. _rockchip-linux: https://github.com/rockchip-linux
 .. _rohit-arm: https://github.com/rohit-arm
-.. _rupsin01: https://github.com/rupsin01
+.. _o-tarhunakov: https://github.com/o-tarhunakov
 .. _rutigl: https://github.com/rutigl
 .. _sandrine-bailleux-arm: https://github.com/sandrine-bailleux-arm
 .. _shawnguo2: https://github.com/shawnguo2
@@ -1128,11 +1128,11 @@
 .. _TravMurav: https://github.com/TravMurav
 .. _uarif1: https://github.com/uarif1
 .. _vijayenthiran-arm: https://github.com/vijayenthiran-arm
-.. _vishnu-banavath: https://github.com/vishnu-banavath
+.. _artkopotev: https://github.com/artkopotev
 .. _vwadekar: https://github.com/vwadekar
 .. _Yann-lms: https://github.com/Yann-lms
 .. _sjaypee208: https://github.com/sjaypee208
 
 --------------
 
-*Copyright (c) 2019-2024, Arm Limited and Contributors. All rights reserved.*
+*Copyright (c) 2019-2025, Arm Limited and Contributors. All rights reserved.*
diff --git a/docs/components/context-management-library.rst b/docs/components/context-management-library.rst
index 8cb1ace..cef6fba 100644
--- a/docs/components/context-management-library.rst
+++ b/docs/components/context-management-library.rst
@@ -106,7 +106,6 @@
 	#define FEAT_STATE_DISABLED     	0
 	#define FEAT_STATE_ENABLED      	1
 	#define FEAT_STATE_CHECK        	2
-	#define FEAT_STATE_CHECK_ASYMMETRIC	3
 
 A pattern is established for feature enablement behavior.
 Each feature must support the 3 possible values with rigid semantics.
@@ -120,15 +119,15 @@
 - **FEAT_STATE_CHECK** - same as ``FEAT_STATE_ALWAYS`` except that the feature's
   existence will be checked at runtime. Default on dynamic platforms (example: FVP).
 
-- **FEAT_STATE_CHECK_ASYMMETRIC** - same as ``FEAT_STATE_CHECK`` except that the feature's
-  existence is asymmetric across cores, which requires the feature existence is checked
-  during warmboot path also. Note that only limited number of features can be asymmetric.
-
  .. note::
-   Only limited number of features can be ``FEAT_STATE_CHECK_ASYMMETRIC`` this is due to
-   the fact that Operating systems are designed for SMP systems.
-   There are no clear guidelines what kind of mismatch is allowed but following pointers
-   can help making a decision
+
+   In general, it is assumed that all cores will support the same set of
+   architectural features (features will be symmetrical). However, there are
+   cases where this is impractical to achieve. Only some features can be
+   mismatched among cores and this is the exception rather than the rule. This
+   is due to the fact that Operating systems are designed for SMP systems. There
+   are no clear guidelines what kind of mismatch is allowed but following
+   pointers can help in making a decision:
 
     - All mandatory features must be symmetric.
     - Any feature that impacts the generation of page tables must be symmetric.
@@ -136,8 +135,9 @@
     - Features related with profiling, debug and trace could be asymmetric
     - Migration of vCPU/tasks between CPUs should not cause an error
 
-    Whenever there is asymmetric feature support is added for a feature TF-A need to add
-    feature specific code in context management code.
+   TF-A caters for mismatched features, however, this is not regularly tested
+   for all features and may not work as expected, even without considering OS
+   support.
 
  .. note::
    ``FEAT_RAS`` is an exception here, as it impacts the execution of EL3 and
@@ -345,9 +345,9 @@
 
 |Context Init WarmBoot|
 
-The primary CPU initializes the Non-Secure context for the secondary CPU while
-restoring re-entry information for the Non-Secure world.
-It initialises via ``cm_init_context_by_index(target_idx, ep )``.
+The primary CPU writes the entrypoint for the secondary CPU. When the secondary
+wakes up it initialises its own context via ``cm_init_my_context( ep )`` using
+the provided entrypoint.
 
 ``psci_warmboot_entrypoint()`` is the warm boot entrypoint procedure.
 During the warm bootup process, secondary CPUs have their secure context
diff --git a/docs/components/rmm-el3-comms-spec.rst b/docs/components/rmm-el3-comms-spec.rst
index 2693e58..1ff2037 100644
--- a/docs/components/rmm-el3-comms-spec.rst
+++ b/docs/components/rmm-el3-comms-spec.rst
@@ -52,7 +52,7 @@
   - ``RES0``: Bit 31 of the version number is reserved 0 as to maintain
     consistency with the versioning schemes used in other parts of RMM.
 
-This document specifies the 0.5 version of Boot Interface ABI and RMM-EL3
+This document specifies the 0.6 version of Boot Interface ABI and RMM-EL3
 services specification and the 0.5 version of the Boot Manifest.
 
 .. _rmm_el3_boot_interface:
@@ -719,6 +719,247 @@
    ``E_RMM_OK``,No errors detected
 
 
+RMM_IDE_KEY_PROG command
+=========================
+
+Set the key/IV info at Root port for an IDE stream as part of Device Assignment flow. This
+command is available from v0.6 of the RMM-EL3 interface.
+
+Please refer to `IDE-KM RFC <https://github.com/TF-RMM/tf-rmm/wiki/RFC:-EL3-RMM-IDE-KM-Interface>`_
+for description of the IDE setup sequence and how this will be invoked by RMM.
+
+The key is 256 bits and IV is 96 bits. The caller needs
+to call this SMC to program this key to the Rx, Tx ports and for each sub-stream
+corresponding to a single keyset.
+
+FID
+---
+
+``0xC40001B7``
+
+Input values
+------------
+
+.. csv-table:: Input values for RMM_IDE_KEY_PROG
+   :header: "Name", "Register", "Field", "Type", "Description"
+   :widths: 1 1 1 1 5
+
+   fid,x0,[63:0],UInt64,Command FID
+   ecam_address,x1,[63:0],UInt64,Used to identify the root complex(RC)
+   rp_id,x2,[63:0],UInt64,Used to identify the root port within the root complex(RC)
+   Keyset[12]:Dir[11]:Substream[10:8]:StreamID[7:0],x3,[63:0],UInt64,IDE selective stream informationKey set: can be 0 or 1unused bits MBZ.
+   KeqQW0,x4,[63:0],UInt64,Quad word of key [63:0]
+   KeqQW1,x5,[63:0],UInt64,Quad word of key [127:64]
+   KeqQW2,x6,[63:0],UInt64,Quad word of key [191:128]
+   KeqQW3,x7,[63:0],UInt64,Quad word of key [255:192]
+   IFVQW0,x8,[63:0],UInt64,Quad word of IV [63:0]
+   IFVQW1,x9,[63:0],UInt64,Quad word of IV [95:64]
+   request_id,x10,[63:0],UInt64,Used only in non-blocking mode. Ignored in blocking mode.
+   cookie,x11,[63:0],UInt64,Used only in non-blocking mode. Ignored in blocking mode.
+
+
+Output values
+-------------
+
+.. csv-table:: Output values for RMM_IDE_KEY_PROG
+   :header: "Name", "Register", "Field", "Type", "Description"
+   :widths: 1 1 1 2 4
+
+   Result,x0,[63:0],Error Code,Command return status
+
+Failure conditions
+------------------
+
+The table below shows all the possible error codes returned in ``Result`` upon
+a failure. The errors are ordered by condition check.
+
+.. csv-table:: Failure conditions for RMM_IDE_KEY_PROG
+   :header: "ID", "Condition"
+   :widths: 1 5
+
+   ``E_RMM_OK``,Key programming is successful.
+   ``E_RMM_FAULT``,Key programming is not successful.
+   ``E_RMM_INVAL``,Key programming arguments are incorrect.
+   ``E_RMM_UNK``,Unknown error or the SMC is not present if the version is < 0.6
+   ``E_RMM_AGAIN``,Returned only for non-blocking mode. IDE-KM interface is busy or request is full. Retry required.
+   ``E_RMM_INPROGRESS``,Returned only for non-blocking mode. The caller must issue RMM_IDE_KM_PULL_RESPONSE SMC to pull the response.
+
+
+RMM_IDE_KEY_SET_GO command
+==========================
+
+Activate the IDE stream at Root Port once the keys have been programmed as part of
+Device Assignment flow. This command is available from v0.6 of the RMM-EL3 interface.
+
+Please refer to `IDE-KM RFC <https://github.com/TF-RMM/tf-rmm/wiki/RFC:-EL3-RMM-IDE-KM-Interface>`_
+for description of the IDE setup sequence and info on how this will be invoked by RMM.
+
+The caller(RMM) needs to ensure the EL3_IDE_KEY_PROG() call had succeeded prior to this call.
+
+FID
+---
+
+``0xC40001B8``
+
+Input values
+------------
+
+.. csv-table:: Input values for RMM_IDE_KEY_SET_GO
+   :header: "Name", "Register", "Field", "Type", "Description"
+   :widths: 1 1 1 1 5
+
+   fid,x0,[63:0],UInt64,Command FID
+   ecam_address,x1,[63:0],UInt64,Used to identify the root complex(RC)
+   rp_id,x2,[63:0],UInt64,Used to identify the root port within the root complex(RC)
+   Keyset[12]:Dir[11]:Substream[10:8]:StreamID[7:0],x3,[63:0],UInt64,IDE selective stream information. Key set can be 0 or 1. Unused bits MBZ.
+   request_id,x4,[63:0],UInt64,Used only in non-blocking mode. Ignored in blocking mode.
+   cookie,x5,[63:0],UInt64,Used only in non-blocking mode. Ignored in blocking mode.
+
+
+Output values
+-------------
+
+.. csv-table:: Output values for RMM_IDE_KEY_SET_GO
+   :header: "Name", "Register", "Field", "Type", "Description"
+   :widths: 1 1 1 2 4
+
+   Result,x0,[63:0],Error Code,Command return status
+
+Failure conditions
+------------------
+
+The table below shows all the possible error codes returned in ``Result`` upon
+a failure. The errors are ordered by condition check.
+
+.. csv-table:: Failure conditions for RMM_IDE_KEY_SET_GO
+   :header: "ID", "Condition"
+   :widths: 1 5
+
+   ``E_RMM_OK``,Key set go is successful.
+   ``E_RMM_FAULT``,Key set go is not successful.
+   ``E_RMM_INVAL``,incorrect arguments.
+   ``E_RMM_UNK``,Unknown error or the SMC is not present if the version is < 0.6.
+   ``E_RMM_AGAIN``,Returned only for non-blocking mode. IDE-KM interface is busy or request is full. Retry required.
+   ``E_RMM_INPROGRESS``,Returned only for non-blocking mode. The caller must issue RMM_IDE_KM_PULL_RESPONSE SMC to pull the response.
+
+
+RMM_IDE_KEY_SET_STOP command
+============================
+
+Deactivate the IDE stream at Root Port as part of Device Assignment flow. This command is
+available from v0.6 of the RMM-EL3 interface.
+
+Please refer to `IDE-KM RFC <https://github.com/TF-RMM/tf-rmm/wiki/RFC:-EL3-RMM-IDE-KM-Interface>`_
+for description of the IDE setup sequence and info on how this will be invoked by RMM.
+
+This SMC is used to tear down an IDE Stream.
+
+FID
+---
+
+``0xC40001B9``
+
+Input values
+------------
+
+.. csv-table:: Input values for RMM_IDE_KEY_SET_STOP
+   :header: "Name", "Register", "Field", "Type", "Description"
+   :widths: 1 1 1 1 5
+
+   fid,x0,[63:0],UInt64,Command FID
+   ecam_address,x1,[63:0],UInt64,Used to identify the root complex(RC)
+   rp_id,x2,[63:0],UInt64,Used to identify the root port within the root complex(RC)
+   Keyset[12]:Dir[11]:Substream[10:8]:StreamID[7:0],x3,[63:0],UInt64,IDE selective stream information. Key set can be 0 or 1. Unused bits MBZ.
+   request_id,x4,[63:0],UInt64,Used only in non-blocking mode. Ignored in blocking mode.
+   cookie,x5,[63:0],UInt64,Used only in non-blocking mode. Ignored in blocking mode.
+
+
+Output values
+-------------
+
+.. csv-table:: Output values for RMM_IDE_KEY_SET_STOP
+   :header: "Name", "Register", "Field", "Type", "Description"
+   :widths: 1 1 1 2 4
+
+   Result,x0,[63:0],Error Code,Command return status
+
+Failure conditions
+------------------
+
+The table below shows all the possible error codes returned in ``Result`` upon
+a failure. The errors are ordered by condition check.
+
+.. csv-table:: Failure conditions for RMM_IDE_KEY_SET_STOP
+   :header: "ID", "Condition"
+   :widths: 1 5
+
+   ``E_RMM_OK``,Key set go is successful.
+   ``E_RMM_FAULT``,Key set go is not successful.
+   ``E_RMM_INVAL``,incorrect arguments.
+   ``E_RMM_UNK``,Unknown error or the SMC is not present if the version is < 0.6.
+   ``E_RMM_AGAIN``,Returned only for non-blocking mode. IDE-KM interface is busy or request is full. Retry required.
+   ``E_RMM_INPROGRESS``,Returned only for non-blocking mode. The caller must issue RMM_IDE_KM_PULL_RESPONSE SMC to pull the response.
+
+
+RMM_IDE_KM_PULL_RESPONSE command
+================================
+
+Retrieve the response from Root Port to a previous non-blocking IDE-KM SMC request as part of
+Device Assignment flow. This command is available from v0.6 of the RMM-EL3 interface.
+
+Please refer to `IDE-KM RFC <https://github.com/TF-RMM/tf-rmm/wiki/RFC:-EL3-RMM-IDE-KM-Interface>`_
+for description of the IDE setup sequence and info on how this will be invoked by RMM.
+
+The response from this call could correspond to any of the last pending requests and the
+RMM needs to identify the request and populate the response. For blocking calls, this SMC
+always returns E_RMM_UNK.
+
+FID
+---
+
+``0xC40001BA``
+
+Input values
+------------
+
+.. csv-table:: Input values for RMM_IDE_KM_PULL_RESPONSE
+   :header: "Name", "Register", "Field", "Type", "Description"
+   :widths: 1 1 1 1 5
+
+   fid,x0,[63:0],UInt64,Command FID
+   ecam_address,x1,[63:0],UInt64,Used to identify the root complex(RC)
+   rp_id,x2,[63:0],UInt64,Used to identify the root port within the root complex(RC)
+
+
+Output values
+-------------
+
+.. csv-table:: Output values for RMM_IDE_KM_PULL_RESPONSE
+   :header: "Name", "Register", "Field", "Type", "Description"
+   :widths: 1 1 1 2 4
+
+   Result,x0,[63:0],Error Code,Command return status
+   Result,x1,[63:0],Error Code,Retrieved response corresponding to previous IDE_KM requests.
+   Result,x2,[63:0],value,passthrough from requested SMC
+   Result,x3,[63:0],value,passthrough from requested SMC
+
+Failure conditions
+------------------
+
+The table below shows all the possible error codes returned in ``Result`` upon
+a failure. The errors are ordered by condition check.
+
+.. csv-table:: Failure conditions for RMM_IDE_KM_PULL_RESPONSE
+   :header: "ID", "Condition"
+   :widths: 1 5
+
+   ``E_RMM_OK``,Key set go is successful.
+   ``E_RMM_FAULT``,Key set go is not successful.
+   ``E_RMM_INVAL``,incorrect arguments.
+   ``E_RMM_UNK``,Unknown error or the SMC is not present if the version is < 0.6.
+   ``E_RMM_AGAIN``,KM request is empty and no response if available.
+
+
 RMM-EL3 world switch register save restore convention
 _____________________________________________________
 
diff --git a/docs/getting_started/prerequisites.rst b/docs/getting_started/prerequisites.rst
index a043991..da7a2c3 100644
--- a/docs/getting_started/prerequisites.rst
+++ b/docs/getting_started/prerequisites.rst
@@ -27,7 +27,7 @@
         Program          Min supported version
 ======================== =====================
 Arm Compiler             6.23
-Arm GNU Compiler         13.3
+Arm GNU Compiler         14.2
 Clang/LLVM               18.1.8
 Device Tree Compiler     1.6.1
 GNU make                 3.81
@@ -51,7 +51,7 @@
 AArch64 builds, the respective targets required are ``arm-none-eabi`` and
 ``aarch64-none-elf``.
 
-Testing has been performed with version 13.3.Rel1 (gcc 13.3) of the Arm
+Testing has been performed with version 14.2.Rel1 (GCC 14.2) of the Arm
 GNU compiler, which can be installed from the `Arm Developer website`_.
 
 In addition, a native compiler is required to build supporting tools.
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index 327c67b..7e40e47 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -2460,6 +2460,163 @@
 The function returns E_RMM_OK on success, RMM_E_INVAL if arguments are invalid and
 E_RMM_UNK if the SMC is not implemented or if interface version is < 0.4.
 
+Function : plat_rmmd_el3_ide_key_program() [mandatory when RMMD_ENABLE_IDE_KEY_PROG == 1]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : uint64_t, uint64_t, uint64_t, struct rp_ide_key_info_t *, uint64_t, uint64_t
+    Return   : int
+
+This function sets the key/IV info for an IDE stream at the Root port. The key is 256 bits
+and IV is 96 bits. The caller calls this SMC to program this key to the Rx and Tx ports
+and for each substream corresponding to a single keyset. The platform should validate
+the arguments `Ecam address` and `Rootport ID` before acting on it. The arguments `request ID`
+and `cookie` are to be ignored for blocking mode and are pass-through to the response for
+non-blocking mode.
+
+The platform needs to ensure proper exclusives are in place when accessed from multiple CPUs.
+Depending on the expected latency for IDE-KM interface, the platform should choose blocking
+or non-blocking semantics. More details about IDE Setup flow can be found
+in this `RFC <https://github.com/TF-RMM/tf-rmm/wiki/RFC:-EL3-RMM-IDE-KM-Interface>`_.
+
+The parameters of the function are:
+
+    arg0 - The ecam address, to access and configure PCI devices in a system.
+
+    arg1 - The rootport ID used to identify the PCIe rootport of a connected device.
+
+    arg2 - The IDE stream info associated with a physical device, this parameter packs the
+    the keyset, direction, substream and stream ID info.
+
+    arg3 - Structure with key and IV info.
+
+    arg4 - The request ID, is used in non-blocking mode only and can be ignored in blocking mode.
+
+    arg5 - The cookie variable, is used in non-blocking mode only and can be ignored in blocking
+    mode.
+
+The function returns E_RMM_OK on success, E_RMM_INVAL if arguments are invalid, E_RMM_FAULT
+if the key programming is unsuccesful, E_RMM_UNK for an unknown error, E_RMM_AGAIN returned
+only for non-blocking mode if the IDE-KM interface is busy or the request queue is full.
+E_RMM_INPROGRESS returned if the request is queued successfully and used only in non-blocking
+mode.
+
+Function : plat_rmmd_el3_ide_key_set_go() [mandatory when RMMD_ENABLE_IDE_KEY_PROG == 1]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : uint64_t, uint64_t, uint64_t, uint64_t, uint64_t
+    Return   : int
+
+This function activates the IDE stream at the Root Port once all the keys have been
+programmed. The platform should validate the arguments `Ecam address` and `Rootport ID`
+before acting on it. The arguments `request ID` and `cookie` are to be ignored for blocking
+mode and are pass-through to the response for non-blocking mode.
+
+The platform needs to ensure proper exclusives are in place when accessed from multiple CPUs.
+Depending on the expected latency for IDE-KM interface, the platform should choose blocking
+or non-blocking semantics. More details about IDE Setup flow can be found
+in this `RFC <https://github.com/TF-RMM/tf-rmm/wiki/RFC:-EL3-RMM-IDE-KM-Interface>`_.
+
+The parameters of the function are:
+
+    arg0 - The ecam address, to access and configure PCI devices in a system.
+
+    arg1 - The rootport ID used to identify the PCIe rootport of a connected device.
+
+    arg2 - The IDE stream info associated with a physical device, this parameter packs the
+    the keyset, direction, substream and stream ID info.
+
+    arg3 - The request ID, is used in non-blocking mode only and can be ignored in blocking mode.
+
+    arg4 - The cookie variable, is used in non-blocking mode only and can be ignored in blocking
+    mode.
+
+The function returns E_RMM_OK on success, E_RMM_INVAL if arguments are invalid, E_RMM_FAULT
+if the key programming is unsuccesful, E_RMM_UNK for an unknown error, E_RMM_AGAIN returned
+only for non-blocking mode if the IDE-KM interface is busy or the request queue is full.
+E_RMM_INPROGRESS returned if the request is queued successfully and used only in non-blocking
+mode.
+
+Function : plat_rmmd_el3_ide_key_set_stop() [mandatory when RMMD_ENABLE_IDE_KEY_PROG == 1]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : uint64_t, uint64_t, uint64_t, uint64_t, uint64_t
+    Return   : int
+
+This function stops the IDE stream and is used to tear down the IDE stream at Root Port.
+The platform should validate the arguments `Ecam address` and `Rootport ID` before acting
+on it. The arguments `request ID` and `cookie` are to be ignored for blocking
+mode and are pass-through to the response for non-blocking mode.
+
+The platform needs to ensure proper exclusives are in place when accessed from multiple CPUs.
+Depending on the expected latency for IDE-KM interface, the platform should choose blocking
+or non-blocking semantics. More details about IDE Setup flow can be found
+in this `RFC <https://github.com/TF-RMM/tf-rmm/wiki/RFC:-EL3-RMM-IDE-KM-Interface>`_.
+
+The parameters of the function are:
+
+    arg0 - The ecam address, to access and configure PCI devices in a system.
+
+    arg1 - The rootport ID used to identify the PCIe rootport of a connected device.
+
+    arg2 - The IDE stream info associated with a physical device, this parameter packs the
+    the keyset, direction, substream and stream ID info.
+
+    arg3 - The request ID, is used in non-blocking mode only and can be ignored in blocking mode.
+
+    arg4 - The cookie variable, is used in non-blocking mode only and can be ignored in blocking
+    mode.
+
+The function returns E_RMM_OK on success, E_RMM_INVAL if arguments are invalid, E_RMM_FAULT
+if the key programming is unsuccesful, E_RMM_UNK for an unknown error, E_RMM_AGAIN returned
+only for non-blocking mode if the IDE-KM interface is busy or the request queue is full.
+E_RMM_INPROGRESS returned if the request is queued successfully and used only in non-blocking
+mode.
+
+Function : plat_rmmd_el3_ide_km_pull_response() [mandatory when RMMD_ENABLE_IDE_KEY_PROG == 1]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : uint64_t, uint64_t, uint64_t *, uint64_t *, uint64_t *
+    Return   : int
+
+This function retrieves a reponse for any of the prior non-blocking IDE-KM requests. The
+caller has to identify the request and populate the accurate response. For blocking calls,
+this function always returns E_RMM_UNK.
+
+The platform needs to ensure proper exclusives are in place when accessed from multiple CPUs.
+Depending on the expected latency for IDE-KM interface, the platform should choose blocking
+or non-blocking semantics. More details about IDE Setup flow can be found
+in this `RFC <https://github.com/TF-RMM/tf-rmm/wiki/RFC:-EL3-RMM-IDE-KM-Interface>`_.
+
+The parameters of the function are:
+
+    arg0 - The ecam address, to access and configure PCI devices in a system.
+
+    arg1 - The rootport ID used to identify the PCIe rootport of a connected device.
+
+    arg2 - Retrieved response corresponding to the previous IDE_KM request.
+
+    arg3 - returns the passthrough request ID of the retrieved response.
+
+    arg4 - returns the passthrough cookie of the retrieved response.
+
+The function returns E_RMM_OK if response is retrieved successfully, E_RMM_INVAL if arguments
+to this function are invalid, E_RMM_UNK if response retrieval failed for an unknown error or
+IDE-KM interface is having blocking semantics, E_RMM_AGAIN if the response queue is empty.
+
+The `arg2` return parameter can return the following values:
+E_RMM_OK - The previous request was successful.
+E_RMM_FAULT - The previous request was not successful.
+E_RMM_INVAL - Arguments to previous request were incorrect.
+E_RMM_UNK - Previous request returned Unknown error.
+
 Function : bl31_plat_enable_mmu [optional]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/drivers/partition/partition.c b/drivers/partition/partition.c
index 387469c..564d29d 100644
--- a/drivers/partition/partition.c
+++ b/drivers/partition/partition.c
@@ -75,11 +75,6 @@
 
 	memcpy(&tmp, mbr_sector + MBR_PRIMARY_ENTRY_OFFSET, sizeof(tmp));
 
-	if (tmp.first_lba != 1) {
-		VERBOSE("MBR header may have an invalid first LBA\n");
-		return -EINVAL;
-	}
-
 	if ((tmp.sector_nums == 0) || (tmp.sector_nums == UINT32_MAX)) {
 		VERBOSE("MBR header entry has an invalid number of sectors\n");
 		return -EINVAL;
@@ -421,6 +416,11 @@
 		goto out;
 	}
 	if (mbr_entry.type == PARTITION_TYPE_GPT) {
+		if (mbr_entry.first_lba != 1U) {
+			VERBOSE("MBR header may have an invalid first LBA\n");
+			return -EINVAL;
+		}
+
 		result = load_primary_gpt(image_handle, mbr_entry.first_lba);
 		if (result != 0) {
 			io_close(image_handle);
diff --git a/fdts/stm32mp151a-prtt1a.dts b/fdts/stm32mp151a-prtt1a.dts
index 9742dcb..d1a8268 100644
--- a/fdts/stm32mp151a-prtt1a.dts
+++ b/fdts/stm32mp151a-prtt1a.dts
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * Copyright (C) 2023, Protonic Holland - All Rights Reserved
- * Copyright (C) 2024, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2024-2025, STMicroelectronics - All Rights Reserved
  * Author: David Jander <david@protonic.nl>
  */
 /dts-v1/;
@@ -71,29 +71,9 @@
 		CLK_MPU_PLL1P
 		CLK_AXI_PLL2P
 		CLK_MCU_PLL3P
-		CLK_PLL12_HSE
-		CLK_PLL3_HSE
-		CLK_PLL4_HSE
 		CLK_RTC_LSI
 		CLK_MCO1_DISABLED
 		CLK_MCO2_DISABLED
-	>;
-
-	st,clkdiv = <
-		1 /*MPU*/
-		0 /*AXI*/
-		0 /*MCU*/
-		1 /*APB1*/
-		1 /*APB2*/
-		1 /*APB3*/
-		1 /*APB4*/
-		2 /*APB5*/
-		23 /*RTC*/
-		0 /*MCO1*/
-		0 /*MCO2*/
-	>;
-
-	st,pkcs = <
 		CLK_CKPER_HSE
 		CLK_FMC_ACLK
 		CLK_QSPI_ACLK
@@ -131,35 +111,76 @@
 		CLK_LPTIM45_LSI
 	>;
 
-	/* VCO = 1300.0 MHz => P = 650 (CPU) */
-	pll1: st,pll@0 {
-		compatible = "st,stm32mp1-pll";
-		reg = <0>;
-		cfg = <2 80 0 0 0 PQR(1,0,0)>;
-		frac = <0x800>;
+	st,clkdiv = <
+		DIV(DIV_MPU, 1)
+		DIV(DIV_AXI, 0)
+		DIV(DIV_MCU, 0)
+		DIV(DIV_APB1, 1)
+		DIV(DIV_APB2, 1)
+		DIV(DIV_APB3, 1)
+		DIV(DIV_APB4, 1)
+		DIV(DIV_APB5, 2)
+		DIV(DIV_RTC, 23)
+		DIV(DIV_MCO1, 0)
+		DIV(DIV_MCO2, 0)
+	>;
+
+	st,pll_vco {
+		pll2_vco_1066Mhz: pll2-vco-1066Mhz {
+			src = <CLK_PLL12_HSE>;
+			divmn = <2 65>;
+			frac = <0x1400>;
+		};
+
+		pll3_vco_417Mhz: pll3-vco-417Mhz {
+			src = <CLK_PLL3_HSE>;
+			divmn = <1 33>;
+			frac = <0x1a04>;
+		};
+
+		pll4_vco_480Mhz: pll4-vco-480Mhz {
+			src = <CLK_PLL4_HSE>;
+			divmn = <1 39>;
+		};
 	};
 
 	/* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */
 	pll2: st,pll@1 {
 		compatible = "st,stm32mp1-pll";
 		reg = <1>;
-		cfg = <2 65 1 0 0 PQR(1,1,1)>;
-		frac = <0x1400>;
+
+		st,pll = <&pll2_cfg1>;
+
+		pll2_cfg1: pll2_cfg1 {
+			st,pll_vco = <&pll2_vco_1066Mhz>;
+			st,pll_div_pqr = <1 0 0>;
+		};
 	};
 
 	/* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */
 	pll3: st,pll@2 {
 		compatible = "st,stm32mp1-pll";
 		reg = <2>;
-		cfg = <1 33 1 16 36 PQR(1,1,1)>;
-		frac = <0x1a04>;
+
+		st,pll = <&pll3_cfg1>;
+
+		pll3_cfg1: pll3_cfg1 {
+			st,pll_vco = <&pll3_vco_417Mhz>;
+			st,pll_div_pqr = <1 16 36>;
+		};
 	};
 
 	/* VCO = 480.0 MHz => P = 120, Q = 40, R = 96 */
 	pll4: st,pll@3 {
 		compatible = "st,stm32mp1-pll";
 		reg = <3>;
-		cfg = <1 39 3 11 4 PQR(1,1,1)>;
+
+		st,pll = <&pll4_cfg1>;
+
+		pll4_cfg1: pll4_cfg1 {
+			st,pll_vco = <&pll4_vco_480Mhz>;
+			st,pll_div_pqr = <3 11 4>;
+		};
 	};
 };
 
diff --git a/fdts/stm32mp153c-lxa-fairytux2-fw-config.dts b/fdts/stm32mp153c-lxa-fairytux2-fw-config.dts
new file mode 100644
index 0000000..9ee09e9
--- /dev/null
+++ b/fdts/stm32mp153c-lxa-fairytux2-fw-config.dts
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
+ */
+
+#define DDR_SIZE	0x20000000 /* 512MB */
+#include "stm32mp15-fw-config.dtsi"
diff --git a/fdts/stm32mp153c-lxa-fairytux2.dts b/fdts/stm32mp153c-lxa-fairytux2.dts
new file mode 100644
index 0000000..0729ae3
--- /dev/null
+++ b/fdts/stm32mp153c-lxa-fairytux2.dts
@@ -0,0 +1,160 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) */
+/*
+ * Copyright (C) 2020 STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2021 Rouven Czerwinski, Pengutronix
+ * Copyright (C) 2024 Leonard Goehrs, Pengutronix
+ */
+
+/dts-v1/;
+
+#include "stm32mp153.dtsi"
+#include "stm32mp15xc.dtsi"
+#include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi"
+#include "stm32mp15xx-osd32.dtsi"
+#include "stm32mp15xxac-pinctrl.dtsi"
+
+/ {
+	model = "Linux Automation GmbH FairyTux 2";
+	compatible = "lxa,stm32mp153c-fairytux-2", "oct,stm32mp15xx-osd32", "st,stm32mp153";
+
+	aliases {
+		mmc1 = &sdmmc2;
+		serial0 = &uart4;
+	};
+
+	chosen {
+		stdout-path = &uart4;
+	};
+
+	led-controller-0 {
+		compatible = "gpio-leds";
+
+		led-0 {
+			label = "fairytux:green:status";
+			gpios = <&gpioa 13 1>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	reg_3v3: regulator_3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		vin-supply = <&v3v3>;
+	};
+};
+
+&pinctrl {
+	fairytux_sdmmc2_d47_pins_b: fairytux-sdmmc2-d47-1 {
+		pins {
+			pinmux = <STM32_PINMUX('A', 8, AF9)>,  /* SDMMC2_D4 */
+				 <STM32_PINMUX('A', 9, AF10)>, /* SDMMC2_D5 */
+				 <STM32_PINMUX('C', 6, AF10)>, /* SDMMC2_D6 */
+				 <STM32_PINMUX('C', 7, AF10)>; /* SDMMC2_D7 */
+			slew-rate = <1>;
+			drive-push-pull;
+			bias-disable;
+		};
+	};
+};
+
+/* VCO = 624 MHz => P = 208, Q = 48, R = 104 */
+&pll3 {
+	st,pll = <&pll3_cfg2>;
+
+	pll3_cfg2: pll3-cfg2 {
+		st,pll_vco = <&pll3_vco_624Mhz>;
+		st,pll_div_pqr = <2 12 5>;
+	};
+};
+
+/* VCO = 750.0 MHz => P = 125, Q = 75, R = 62.5 */
+&pll4 {
+	st,pll = <&pll4_cfg2>;
+
+	pll4_cfg2: pll4-cfg2 {
+		st,pll_vco = <&pll4_vco_750Mhz>;
+		st,pll_div_pqr = <5 9 11>;
+	};
+};
+
+&rcc {
+	/* change parent clocks */
+	st,clksrc = <
+		CLK_MPU_PLL1P
+		CLK_AXI_PLL2P
+		CLK_MCU_PLL3P
+		CLK_RTC_LSE
+		CLK_MCO1_DISABLED
+		CLK_MCO2_DISABLED
+		CLK_CKPER_HSE
+		CLK_FMC_ACLK
+		CLK_QSPI_ACLK
+		CLK_ETH_PLL4P
+		CLK_SDMMC12_PLL3R
+		CLK_DSI_DSIPLL
+		CLK_STGEN_HSE
+		CLK_USBPHY_HSE
+		CLK_SPI2S1_PLL3Q
+		CLK_SPI2S23_PLL3Q
+		CLK_SPI45_HSI
+		CLK_SPI6_HSI
+		CLK_I2C46_HSI
+		CLK_SDMMC3_DISABLED
+		CLK_USBO_USBPHY
+		CLK_ADC_CKPER
+		CLK_CEC_DISABLED
+		CLK_I2C12_HSI
+		CLK_I2C35_HSI
+		CLK_UART1_HSI
+		CLK_UART24_HSI
+		CLK_UART35_HSI
+		CLK_UART6_HSI
+		CLK_UART78_HSI
+		CLK_SPDIF_DISABLED
+		CLK_FDCAN_PLL3Q
+		CLK_SAI1_DISABLED
+		CLK_SAI2_DISABLED
+		CLK_SAI3_DISABLED
+		CLK_SAI4_DISABLED
+		CLK_RNG1_LSI
+		CLK_RNG2_LSI
+		CLK_LPTIM1_PCLK1
+		CLK_LPTIM23_PCLK3
+		CLK_LPTIM45_LSE
+	>;
+
+	st,pll_vco {
+		pll3_vco_624Mhz: pll3-vco-624Mhz {
+			src = <CLK_PLL3_HSE>;
+			divmn = <1 51>;
+		};
+
+		pll4_vco_750Mhz: pll4-vco-750Mhz {
+			src = <CLK_PLL4_HSE>;
+			divmn = <3 124>;
+		};
+	};
+};
+
+&sdmmc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc2_b4_pins_a &fairytux_sdmmc2_d47_pins_b>;
+	bus-width = <8>;
+	mmc-ddr-3_3v;
+	no-1-8-v;
+	no-sd;
+	no-sdio;
+	non-removable;
+	st,neg-edge;
+	vmmc-supply = <&reg_3v3>;
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart4_pins_a>;
+	status = "okay";
+};
diff --git a/include/common/feat_detect.h b/include/common/feat_detect.h
index b85e1ce..18e6c42 100644
--- a/include/common/feat_detect.h
+++ b/include/common/feat_detect.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -14,6 +14,5 @@
 #define FEAT_STATE_DISABLED		0
 #define FEAT_STATE_ALWAYS		1
 #define FEAT_STATE_CHECK		2
-#define FEAT_STATE_CHECK_ASYMMETRIC	3
 
 #endif /* FEAT_DETECT_H */
diff --git a/include/lib/cpus/errata.h b/include/lib/cpus/errata.h
index 8e28d46..1f5f5ea 100644
--- a/include/lib/cpus/errata.h
+++ b/include/lib/cpus/errata.h
@@ -67,7 +67,6 @@
 }
 #endif
 
-
 bool check_if_trbe_disable_affected_core(void);
 int check_wa_cve_2024_7881(void);
 bool errata_ich_vmcr_el2_applies(void);
diff --git a/include/lib/el3_runtime/context_mgmt.h b/include/lib/el3_runtime/context_mgmt.h
index a48ed96..72a8ea2 100644
--- a/include/lib/el3_runtime/context_mgmt.h
+++ b/include/lib/el3_runtime/context_mgmt.h
@@ -34,17 +34,11 @@
 void cm_prepare_el3_exit(uint32_t security_state);
 void cm_prepare_el3_exit_ns(void);
 
-#if !IMAGE_BL1
-void cm_init_context_by_index(unsigned int cpu_idx,
-			      const struct entry_point_info *ep);
-#endif /* !IMAGE_BL1 */
-
 #ifdef __aarch64__
 #if IMAGE_BL31
 void cm_manage_extensions_el3(unsigned int my_idx);
 void manage_extensions_nonsecure_per_world(void);
 void cm_el3_arch_init_per_world(per_world_context_t *per_world_ctx);
-void cm_handle_asymmetric_features(void);
 #endif
 
 #if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
@@ -97,7 +91,6 @@
 void cm_set_next_context(void *context);
 static inline void cm_manage_extensions_el3(unsigned int cpu_idx) {}
 static inline void manage_extensions_nonsecure_per_world(void) {}
-static inline void cm_handle_asymmetric_features(void) {}
 #endif /* __aarch64__ */
 
 #endif /* CONTEXT_MGMT_H */
diff --git a/include/lib/el3_runtime/cpu_data.h b/include/lib/el3_runtime/cpu_data.h
index e417f45..3dc156a 100644
--- a/include/lib/el3_runtime/cpu_data.h
+++ b/include/lib/el3_runtime/cpu_data.h
@@ -23,10 +23,10 @@
 /* Size of cpu_context array */
 #define CPU_DATA_CONTEXT_NUM		3
 /* Offset of cpu_ops_ptr, size 8 bytes */
-#define CPU_DATA_CPU_OPS_PTR		0x18
+#define CPU_DATA_CPU_OPS_PTR		0x20
 #else /* ENABLE_RME */
 #define CPU_DATA_CONTEXT_NUM		2
-#define CPU_DATA_CPU_OPS_PTR		0x10
+#define CPU_DATA_CPU_OPS_PTR		0x18
 #endif /* ENABLE_RME */
 
 #if ENABLE_PAUTH
@@ -47,8 +47,9 @@
 #if CRASH_REPORTING
 #error "Crash reporting is not supported in AArch32"
 #endif
-#define CPU_DATA_CPU_OPS_PTR		0x0
-#define CPU_DATA_CRASH_BUF_OFFSET	(0x4 + PSCI_CPU_DATA_SIZE)
+#define WARMBOOT_EP_INFO		0x0
+#define CPU_DATA_CPU_OPS_PTR		0x4
+#define CPU_DATA_CRASH_BUF_OFFSET	(CPU_DATA_CPU_OPS_PTR + PSCI_CPU_DATA_SIZE)
 
 #endif	/* __aarch64__ */
 
@@ -79,7 +80,12 @@
 #if ENABLE_RUNTIME_INSTRUMENTATION
 /* Temporary space to store PMF timestamps from assembly code */
 #define CPU_DATA_PMF_TS_COUNT		1
+#if __aarch64__
 #define CPU_DATA_PMF_TS0_OFFSET		CPU_DATA_EHF_DATA_BUF_END
+#else
+/* alignment */
+#define CPU_DATA_PMF_TS0_OFFSET		(CPU_DATA_EHF_DATA_BUF_END + 8)
+#endif
 #define CPU_DATA_PMF_TS0_IDX		0
 #endif
 
@@ -131,6 +137,7 @@
 #ifdef __aarch64__
 	void *cpu_context[CPU_DATA_CONTEXT_NUM];
 #endif /* __aarch64__ */
+	entry_point_info_t *warmboot_ep_info;
 	uintptr_t cpu_ops_ptr;
 	struct psci_cpu_data psci_svc_cpu_data;
 #if ENABLE_PAUTH
diff --git a/include/lib/libc/string.h b/include/lib/libc/string.h
index bba9816..098fded 100644
--- a/include/lib/libc/string.h
+++ b/include/lib/libc/string.h
@@ -4,7 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 /*
- * Portions copyright (c) 2018-2020, Arm Limited and Contributors.
+ * Portions copyright (c) 2018-2025, Arm Limited and Contributors.
  * Portions copyright (c) 2023, Intel Corporation. All rights reserved.
  * All rights reserved.
  */
@@ -14,19 +14,26 @@
 
 #include <stddef.h>
 
-void *memcpy(void *dst, const void *src, size_t len);
+/*
+ * When conditions are right, the compiler may have a baked-in call that can be
+ * inlined and that will be much more optimal than our generic implementation.
+ * When it doesn't, it will emit a call to the original function for which we
+ * provide an implementation.
+ */
+#define memcpy  __builtin_memcpy
+#define memset  __builtin_memset
+#define memcmp  __builtin_memcmp
+#define memchr  __builtin_memchr
+#define strcmp  __builtin_strcmp
+#define strncmp __builtin_strncmp
+#define strchr  __builtin_strchr
+#define strlen  __builtin_strlen
+#define strrchr __builtin_strrchr
+
 int memcpy_s(void *dst, size_t dsize, void *src, size_t ssize);
 void *memmove(void *dst, const void *src, size_t len);
-int memcmp(const void *s1, const void *s2, size_t len);
-int strcmp(const char *s1, const char *s2);
-int strncmp(const char *s1, const char *s2, size_t n);
-void *memchr(const void *src, int c, size_t len);
 void *memrchr(const void *src, int c, size_t len);
-char *strchr(const char *s, int c);
-void *memset(void *dst, int val, size_t count);
-size_t strlen(const char *s);
 size_t strnlen(const char *s, size_t maxlen);
-char *strrchr(const char *p, int ch);
 size_t strlcpy(char * dst, const char * src, size_t dsize);
 size_t strlcat(char * dst, const char * src, size_t dsize);
 char *strtok_r(char *s, const char *delim, char **last);
diff --git a/include/lib/libc/string_private.h b/include/lib/libc/string_private.h
new file mode 100644
index 0000000..da85fae
--- /dev/null
+++ b/include/lib/libc/string_private.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef STRING_PRIVATE_H
+#define STRING_PRIVATE_H
+
+/* Do not include outside of the libc. Use string.h instead. */
+
+#include <stddef.h>
+
+int memcmp(const void *s1, const void *s2, size_t len);
+int strcmp(const char *s1, const char *s2);
+int strncmp(const char *s1, const char *s2, size_t n);
+void *memchr(const void *src, int c, size_t len);
+char *strchr(const char *s, int c);
+void *memset(void *dst, int val, size_t count);
+size_t strlen(const char *s);
+char *strrchr(const char *p, int ch);
+
+#endif /* STRING_PRIVATE_H */
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 396bd14..ae2e96f 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -147,6 +147,14 @@
 
 #endif /* defined(IMAGE_BL31) || (!defined(__aarch64__) && defined(IMAGE_BL32)) */
 
+#ifdef __aarch64__
+#define TL_TAG_EXEC_EP_INFO	TL_TAG_EXEC_EP_INFO64
+#define TL_TAG_SRAM_LAYOUT	TL_TAG_SRAM_LAYOUT64
+#else
+#define TL_TAG_EXEC_EP_INFO	TL_TAG_EXEC_EP_INFO32
+#define TL_TAG_SRAM_LAYOUT	TL_TAG_SRAM_LAYOUT32
+#endif
+
 #if ARM_RECOM_STATE_ID_ENC
 /*
  * Macros used to parse state information from State-ID if it is using the
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index e10770c..b9985a3 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -399,6 +399,24 @@
 size_t plat_rmmd_get_el3_rmm_shared_mem(uintptr_t *shared);
 int plat_rmmd_load_manifest(struct rmm_manifest *manifest);
 int plat_rmmd_mecid_key_update(uint16_t mecid);
+
+/* The following 4 functions are to be implemented if
+ * RMMD_ENABLE_IDE_KEY_PROG=1.
+ * The following functions are expected to return E_RMM_* error codes.
+ */
+int plat_rmmd_el3_ide_key_program(uint64_t ecam_address, uint64_t root_port_id,
+				  uint64_t ide_stream_info,
+				  rp_ide_key_info_t *ide_key_info_ptr,
+				  uint64_t request_id, uint64_t cookie);
+int plat_rmmd_el3_ide_key_set_go(uint64_t ecam_address, uint64_t root_port_id,
+				 uint64_t ide_stream_info, uint64_t request_id,
+				 uint64_t cookie);
+int plat_rmmd_el3_ide_key_set_stop(uint64_t ecam_address, uint64_t root_port_id,
+				   uint64_t ide_stream_info, uint64_t request_id,
+				   uint64_t cookie);
+int plat_rmmd_el3_ide_km_pull_response(uint64_t ecam_address, uint64_t root_port_id,
+				   uint64_t *req_resp, uint64_t *request_id,
+				   uint64_t *cookie);
 #endif /* ENABLE_RME */
 
 /*******************************************************************************
diff --git a/include/services/rmmd_svc.h b/include/services/rmmd_svc.h
index 8bf9319..9b99e92 100644
--- a/include/services/rmmd_svc.h
+++ b/include/services/rmmd_svc.h
@@ -92,6 +92,8 @@
 #define E_RMM_NOMEM			-4
 #define E_RMM_INVAL			-5
 #define E_RMM_AGAIN			-6
+#define E_RMM_FAULT			-7
+#define E_RMM_IN_PROGRESS		-8
 
 /* Return error codes from RMI SMCs */
 #define RMI_SUCCESS			0
@@ -179,6 +181,83 @@
 /* Identifier for the hash algorithm used for attestation signing */
 #define EL3_TOKEN_SIGN_HASH_ALG_SHA384		U(1)
 
+/* Starting RMM-EL3 interface version 0.6 */
+/*
+ * Function codes to support RMM IDE Key management Interface.
+ * The arguments to this SMC are:
+ *     arg0 - Function ID.
+ *     arg1 - Enhanced Configuration Access Mechanism address
+ *     arg2 - Root Port ID
+ *     arg3 - IDE selective stream info
+ *     arg4 - Quad word of key[63:0]
+ *     arg5 - Quad word of key[127:64]
+ *     arg6 - Quad word of key[191:128]
+ *     arg7 - Quad word of key[255:192]
+ *     arg8 - Quad word of IV [63:0]
+ *     arg9 - Quad word of IV [95:64]
+ *     arg10 - request_id
+ *     arg11 - cookie
+ * The return arguments are:
+ *     ret0 - Status/Error
+ */
+#define RMM_IDE_KEY_PROG			SMC64_RMMD_EL3_FID(U(7))
+
+/*******************************************************************************
+ * Structure to hold el3_ide_key info
+ ******************************************************************************/
+#ifndef __ASSEMBLER__
+typedef struct rp_ide_key_info {
+	uint64_t keyqw0;
+	uint64_t keyqw1;
+	uint64_t keyqw2;
+	uint64_t keyqw3;
+	uint64_t ifvqw0;
+	uint64_t ifvqw1;
+} rp_ide_key_info_t;
+#endif /* __ASSEMBLER__ */
+
+/*
+ * Function codes to support RMM IDE Key management Interface.
+ * The arguments to this SMC are:
+ *     arg0 - Function ID.
+ *     arg1 - Enhanced Configuration Access Mechanism address
+ *     arg2 - Root Port ID
+ *     arg3 - IDE selective stream info
+ *     arg4 - request_id
+ *     arg5 - cookie
+ * The return arguments are:
+ *     ret0 - Status/Error
+ */
+#define RMM_IDE_KEY_SET_GO			SMC64_RMMD_EL3_FID(U(8))
+
+/*
+ * Function codes to support RMM IDE Key management Interface.
+ * The arguments to this SMC are:
+ *     arg0 - Function ID.
+ *     arg1 - Enhanced Configuration Access Mechanism address
+ *     arg2 - Root Port ID
+ *     arg3 - IDE selective stream info
+ *     arg4 - request_id
+ *     arg5 - cookie
+ * The return arguments are:
+ *     ret0 - Status/Error
+ */
+#define RMM_IDE_KEY_SET_STOP			SMC64_RMMD_EL3_FID(U(9))
+
+/*
+ * Function codes to support RMM IDE Key management Interface.
+ * The arguments to this SMC are:
+ *     arg0 - Function ID.
+ *     arg1 - Enhanced Configuration Access Mechanism address
+ *     arg2 - Root Port ID
+ * The return arguments are:
+ *     ret0 - Status/Error
+ *     ret1 - Retrieved response corresponding to the previous request.
+ *     ret2 - request_id
+ *     ret3 - cookie
+ */
+#define RMM_IDE_KM_PULL_RESPONSE		SMC64_RMMD_EL3_FID(U(10))
+
 /*
  * RMM_BOOT_COMPLETE originates on RMM when the boot finishes (either cold
  * or warm boot). This is handled by the RMM-EL3 interface SMC handler.
@@ -200,7 +279,7 @@
  * Increase this when a bug is fixed, or a feature is added without
  * breaking compatibility.
  */
-#define RMM_EL3_IFC_VERSION_MINOR	(U(5))
+#define RMM_EL3_IFC_VERSION_MINOR	(U(6))
 
 #define RMM_EL3_INTERFACE_VERSION				\
 	(((RMM_EL3_IFC_VERSION_MAJOR << 16) & 0x7FFFF) |	\
diff --git a/include/services/trp/platform_trp.h b/include/services/trp/platform_trp.h
index 756e9db..67dfff1 100644
--- a/include/services/trp/platform_trp.h
+++ b/include/services/trp/platform_trp.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,4 +16,8 @@
  ******************************************************************************/
 void trp_early_platform_setup(struct rmm_manifest *manifest);
 
+#if RMMD_ENABLE_IDE_KEY_PROG
+uint64_t trp_get_test_rootport(uint64_t *ecam, uint64_t *rootport);
+#endif /* RMMD_ENABLE_IDE_KEY_PROG */
+
 #endif /* PLATFORM_TRP_H */
diff --git a/include/services/trp/trp_helpers.h b/include/services/trp/trp_helpers.h
index 83ec740..2f36720 100644
--- a/include/services/trp/trp_helpers.h
+++ b/include/services/trp/trp_helpers.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -17,7 +17,11 @@
 #define TRP_ARG5		0x28
 #define TRP_ARG6		0x30
 #define TRP_ARG7		0x38
-#define TRP_ARGS_END		0x40
+#define TRP_ARG8		0x40
+#define TRP_ARG9		0x48
+#define TRP_ARG10		0x50
+#define TRP_ARG11		0x58
+#define TRP_ARGS_END		0x60
 
 #ifndef __ASSEMBLER__
 
@@ -35,7 +39,11 @@
 			 uint64_t arg4,
 			 uint64_t arg5,
 			 uint64_t arg6,
-			 uint64_t arg7);
+			 uint64_t arg7,
+			 uint64_t arg8,
+			 uint64_t arg9,
+			 uint64_t arg10,
+			 uint64_t arg11);
 
 __dead2 void trp_boot_abort(uint64_t err);
 
diff --git a/lib/el3_runtime/aarch32/context_mgmt.c b/lib/el3_runtime/aarch32/context_mgmt.c
index 132888c..00d9c01 100644
--- a/lib/el3_runtime/aarch32/context_mgmt.c
+++ b/lib/el3_runtime/aarch32/context_mgmt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -155,21 +155,6 @@
 #endif /*  IMAGE_BL32 */
 }
 
-#if !IMAGE_BL1
-/*******************************************************************************
- * The following function initializes the cpu_context for a CPU specified by
- * its `cpu_idx` for first use, and sets the initial entrypoint state as
- * specified by the entry_point_info structure.
- ******************************************************************************/
-void cm_init_context_by_index(unsigned int cpu_idx,
-			      const entry_point_info_t *ep)
-{
-	cpu_context_t *ctx;
-	ctx = cm_get_context_by_index(cpu_idx, GET_SECURITY_STATE(ep->h.attr));
-	cm_setup_context(ctx, ep);
-}
-#endif /* !IMAGE_BL1 */
-
 /*******************************************************************************
  * The following function initializes the cpu_context for the current CPU
  * for first use, and sets the initial entrypoint state as specified by the
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 0cfabb3..d04e02f 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -480,13 +480,6 @@
 	}
 
 	/*
-	 * SCR_EL3.TCR2EN: Enable access to TCR2_ELx for AArch64 if present.
-	 */
-	if (is_feat_tcr2_supported() && (GET_RW(ep->spsr) == MODE_RW_64)) {
-		scr_el3 |= SCR_TCR2EN_BIT;
-	}
-
-	/*
 	 * SCR_EL3.PIEN: Enable permission indirection and overlay
 	 * registers for AArch64 if present.
 	 */
@@ -587,6 +580,10 @@
 		trf_enable(ctx);
 	}
 
+	if (is_feat_tcr2_supported()) {
+		tcr2_enable(ctx);
+	}
+
 	pmuv3_enable(ctx);
 #endif /* IMAGE_BL31 */
 
@@ -835,8 +832,10 @@
 		spe_enable(ctx);
 	}
 
-	if (is_feat_trbe_supported()) {
-		trbe_enable(ctx);
+	if (!check_if_trbe_disable_affected_core()) {
+		if (is_feat_trbe_supported()) {
+			trbe_enable(ctx);
+		}
 	}
 
 	if (is_feat_brbe_supported()) {
@@ -936,21 +935,6 @@
 	}
 #endif /* IMAGE_BL31 */
 }
-
-#if !IMAGE_BL1
-/*******************************************************************************
- * The following function initializes the cpu_context for a CPU specified by
- * its `cpu_idx` for first use, and sets the initial entrypoint state as
- * specified by the entry_point_info structure.
- ******************************************************************************/
-void cm_init_context_by_index(unsigned int cpu_idx,
-			      const entry_point_info_t *ep)
-{
-	cpu_context_t *ctx;
-	ctx = cm_get_context_by_index(cpu_idx, GET_SECURITY_STATE(ep->h.attr));
-	cm_setup_context(ctx, ep);
-}
-#endif /* !IMAGE_BL1 */
 
 /*******************************************************************************
  * The following function initializes the cpu_context for the current CPU
@@ -1629,52 +1613,6 @@
 }
 #endif /* (CTX_INCLUDE_EL2_REGS && IMAGE_BL31) */
 
-#if IMAGE_BL31
-/*********************************************************************************
-* This function allows Architecture features asymmetry among cores.
-* TF-A assumes that all the cores in the platform has architecture feature parity
-* and hence the context is setup on different core (e.g. primary sets up the
-* context for secondary cores).This assumption may not be true for systems where
-* cores are not conforming to same Arch version or there is CPU Erratum which
-* requires certain feature to be be disabled only on a given core.
-*
-* This function is called on secondary cores to override any disparity in context
-* setup by primary, this would be called during warmboot path.
-*********************************************************************************/
-void cm_handle_asymmetric_features(void)
-{
-	cpu_context_t *ctx __maybe_unused = cm_get_context(NON_SECURE);
-
-	assert(ctx != NULL);
-
-#if ENABLE_SPE_FOR_NS == FEAT_STATE_CHECK_ASYMMETRIC
-	if (is_feat_spe_supported()) {
-		spe_enable(ctx);
-	} else {
-		spe_disable(ctx);
-	}
-#endif
-
-	if (check_if_trbe_disable_affected_core()) {
-		if (is_feat_trbe_supported()) {
-			trbe_disable(ctx);
-		}
-	}
-
-#if ENABLE_FEAT_TCR2 == FEAT_STATE_CHECK_ASYMMETRIC
-	el3_state_t *el3_state = get_el3state_ctx(ctx);
-	u_register_t spsr = read_ctx_reg(el3_state, CTX_SPSR_EL3);
-
-	if (is_feat_tcr2_supported() && (GET_RW(spsr) == MODE_RW_64)) {
-		tcr2_enable(ctx);
-	} else {
-		tcr2_disable(ctx);
-	}
-#endif
-
-}
-#endif
-
 /*******************************************************************************
  * This function is used to exit to Non-secure world. If CTX_INCLUDE_EL2_REGS
  * is enabled, it restores EL1 and EL2 sysreg contexts instead of directly
@@ -1683,18 +1621,6 @@
  ******************************************************************************/
 void cm_prepare_el3_exit_ns(void)
 {
-#if IMAGE_BL31
-	/*
-	 * Check and handle Architecture feature asymmetry among cores.
-	 *
-	 * In warmboot path secondary cores context is initialized on core which
-	 * did CPU_ON SMC call, if there is feature asymmetry in these cores handle
-	 * it in this function call.
-	 * For Symmetric cores this is an empty function.
-	 */
-	cm_handle_asymmetric_features();
-#endif
-
 #if (CTX_INCLUDE_EL2_REGS && IMAGE_BL31)
 #if ENABLE_ASSERTIONS
 	cpu_context_t *ctx = cm_get_context(NON_SECURE);
diff --git a/lib/libc/memchr.c b/lib/libc/memchr.c
index 66d7ba1..e009a5f 100644
--- a/lib/libc/memchr.c
+++ b/lib/libc/memchr.c
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <stddef.h>
-#include <string.h>
+#include <string_private.h>
 
 void *memchr(const void *src, int c, size_t len)
 {
diff --git a/lib/libc/memcmp.c b/lib/libc/memcmp.c
index db2701b..1458208 100644
--- a/lib/libc/memcmp.c
+++ b/lib/libc/memcmp.c
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <stddef.h>
-#include <string.h>
+#include <string_private.h>
 
 int memcmp(const void *s1, const void *s2, size_t len)
 {
diff --git a/lib/libc/memcpy.c b/lib/libc/memcpy.c
index af9ed45..ca31de5 100644
--- a/lib/libc/memcpy.c
+++ b/lib/libc/memcpy.c
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <stddef.h>
-#include <string.h>
+#include <string_private.h>
 
 void *memcpy(void *dst, const void *src, size_t len)
 {
diff --git a/lib/libc/memcpy_s.c b/lib/libc/memcpy_s.c
index 26953bf..ee87637 100644
--- a/lib/libc/memcpy_s.c
+++ b/lib/libc/memcpy_s.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2023, Intel Corporation. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
@@ -53,12 +53,7 @@
 		}
 	}
 
-	/*
-	 * Start copy process when there is no error
-	 */
-	while (ssize--) {
-		d[ssize] = s[ssize];
-	}
+	(void)memcpy(dst, src, ssize);
 
 	return 0;
 }
diff --git a/lib/libc/memset.c b/lib/libc/memset.c
index c5bac8d..2513221 100644
--- a/lib/libc/memset.c
+++ b/lib/libc/memset.c
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <stddef.h>
-#include <string.h>
+#include <string_private.h>
 #include <stdint.h>
 
 void *memset(void *dst, int val, size_t count)
diff --git a/lib/libc/strchr.c b/lib/libc/strchr.c
index 1cd03ca..b3bebe4 100644
--- a/lib/libc/strchr.c
+++ b/lib/libc/strchr.c
@@ -30,12 +30,12 @@
  */
 
 /*
- * Portions copyright (c) 2018, Arm Limited and Contributors.
+ * Portions copyright (c) 2018-2025, Arm Limited and Contributors.
  * All rights reserved.
  */
 
 #include <stddef.h>
-#include <string.h>
+#include <string_private.h>
 
 char *
 strchr(const char *p, int ch)
diff --git a/lib/libc/strcmp.c b/lib/libc/strcmp.c
index 290db4c..5afd0e9 100644
--- a/lib/libc/strcmp.c
+++ b/lib/libc/strcmp.c
@@ -33,11 +33,11 @@
  */
 
 /*
- * Portions copyright (c) 2018, Arm Limited and Contributors.
+ * Portions copyright (c) 2018-2025, Arm Limited and Contributors.
  * All rights reserved.
  */
 
-#include <string.h>
+#include <string_private.h>
 
 /*
  * Compare strings.
diff --git a/lib/libc/strlen.c b/lib/libc/strlen.c
index e4b79d9..cc1d1df 100644
--- a/lib/libc/strlen.c
+++ b/lib/libc/strlen.c
@@ -1,10 +1,10 @@
 /*
- * Copyright (c) 2018, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
-#include <string.h>
+#include <string_private.h>
 
 size_t strlen(const char *s)
 {
diff --git a/lib/libc/strncmp.c b/lib/libc/strncmp.c
index f0bbadc..828e0c5 100644
--- a/lib/libc/strncmp.c
+++ b/lib/libc/strncmp.c
@@ -30,11 +30,11 @@
  */
 
 /*
- * Portions copyright (c) 2018, Arm Limited and Contributors.
+ * Portions copyright (c) 2018-2025, Arm Limited and Contributors.
  * All rights reserved.
  */
 
-#include <string.h>
+#include <string_private.h>
 
 int
 strncmp(const char *s1, const char *s2, size_t n)
diff --git a/lib/libc/strrchr.c b/lib/libc/strrchr.c
index cd435ff..98f76c6 100644
--- a/lib/libc/strrchr.c
+++ b/lib/libc/strrchr.c
@@ -30,7 +30,7 @@
  */
 
 #include <stddef.h>
-#include <string.h>
+#include <string_private.h>
 
 char *
 strrchr(const char *p, int ch)
diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c
index 17ecab8..1c634e3 100644
--- a/lib/psci/psci_common.c
+++ b/lib/psci/psci_common.c
@@ -1032,6 +1032,13 @@
 	}
 
 	/*
+	 * Caches and (importantly) coherency are on so we can rely on seeing
+	 * whatever the primary gave us without explicit cache maintenance
+	 */
+	entry_point_info_t *ep = get_cpu_data(warmboot_ep_info);
+	cm_init_my_context(ep);
+
+	/*
 	 * Generic management: Now we just need to retrieve the
 	 * information that we had stashed away during the cpu_on
 	 * call to set this cpu on its way.
diff --git a/lib/psci/psci_main.c b/lib/psci/psci_main.c
index 34668ea..f126f49 100644
--- a/lib/psci/psci_main.c
+++ b/lib/psci/psci_main.c
@@ -28,15 +28,17 @@
 
 {
 	int rc;
-	entry_point_info_t ep;
+	entry_point_info_t *ep;
+	unsigned int target_idx = (unsigned int)plat_core_pos_by_mpidr(target_cpu);
 
 	/* Validate the target CPU */
 	if (!is_valid_mpidr(target_cpu)) {
 		return PSCI_E_INVALID_PARAMS;
 	}
 
-	/* Validate the entry point and get the entry_point_info */
-	rc = psci_validate_entry_point(&ep, entrypoint, context_id);
+	ep = get_cpu_data_by_index(target_idx, warmboot_ep_info);
+	/* Validate the lower EL entry point and put it in the entry_point_info */
+	rc = psci_validate_entry_point(ep, entrypoint, context_id);
 	if (rc != PSCI_E_SUCCESS) {
 		return rc;
 	}
@@ -45,7 +47,7 @@
 	 * To turn this cpu on, specify which power
 	 * levels need to be turned on
 	 */
-	return psci_cpu_on_start(target_cpu, &ep);
+	return psci_cpu_on_start(target_cpu, ep);
 }
 
 unsigned int psci_version(void)
@@ -59,7 +61,6 @@
 {
 	int rc;
 	unsigned int target_pwrlvl, is_power_down_state;
-	entry_point_info_t ep;
 	psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} };
 	plat_local_state_t cpu_pd_state;
 	unsigned int cpu_idx = plat_my_core_pos();
@@ -173,7 +174,9 @@
 	 * point and program entry information.
 	 */
 	if (is_power_down_state != 0U) {
-		rc = psci_validate_entry_point(&ep, entrypoint, context_id);
+		entry_point_info_t *ep = get_cpu_data_by_index(cpu_idx, warmboot_ep_info);
+
+		rc = psci_validate_entry_point(ep, entrypoint, context_id);
 		if (rc != PSCI_E_SUCCESS) {
 			return rc;
 		}
@@ -186,7 +189,6 @@
 	 * arrival of an interrupt
 	 */
 	rc = psci_cpu_suspend_start(cpu_idx,
-				    &ep,
 				    target_pwrlvl,
 				    &state_info,
 				    is_power_down_state);
@@ -199,8 +201,8 @@
 {
 	int rc;
 	psci_power_state_t state_info;
-	entry_point_info_t ep;
 	unsigned int cpu_idx = plat_my_core_pos();
+	entry_point_info_t *ep = get_cpu_data_by_index(cpu_idx, warmboot_ep_info);
 
 	/* Check if the current CPU is the last ON CPU in the system */
 	if (!psci_is_last_on_cpu(cpu_idx)) {
@@ -208,7 +210,7 @@
 	}
 
 	/* Validate the entry point and get the entry_point_info */
-	rc = psci_validate_entry_point(&ep, entrypoint, context_id);
+	rc = psci_validate_entry_point(ep, entrypoint, context_id);
 	if (rc != PSCI_E_SUCCESS) {
 		return rc;
 	}
@@ -235,7 +237,6 @@
 	 * arrival of an interrupt
 	 */
 	rc = psci_cpu_suspend_start(cpu_idx,
-				    &ep,
 				    PLAT_MAX_PWR_LVL,
 				    &state_info,
 				    PSTATE_TYPE_POWERDOWN);
diff --git a/lib/psci/psci_on.c b/lib/psci/psci_on.c
index 3eacb9c..1bbea7a 100644
--- a/lib/psci/psci_on.c
+++ b/lib/psci/psci_on.c
@@ -141,10 +141,7 @@
 	rc = psci_plat_pm_ops->pwr_domain_on(target_cpu);
 	assert((rc == PSCI_E_SUCCESS) || (rc == PSCI_E_INTERN_FAIL));
 
-	if (rc == PSCI_E_SUCCESS) {
-		/* Store the re-entry information for the non-secure world. */
-		cm_init_context_by_index(target_idx, ep);
-	} else {
+	if (rc != PSCI_E_SUCCESS) {
 		/* Restore the state on error. */
 		psci_set_aff_info_state_by_idx(target_idx, AFF_STATE_OFF);
 		flush_cpu_data_by_index(target_idx,
diff --git a/lib/psci/psci_private.h b/lib/psci/psci_private.h
index 49b19c9..f3f5a5c 100644
--- a/lib/psci/psci_private.h
+++ b/lib/psci/psci_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -344,7 +344,6 @@
 
 /* Private exported functions from psci_suspend.c */
 int psci_cpu_suspend_start(unsigned int idx,
-			   const entry_point_info_t *ep,
 			   unsigned int end_pwrlvl,
 			   psci_power_state_t *state_info,
 			   unsigned int is_power_down_state);
diff --git a/lib/psci/psci_setup.c b/lib/psci/psci_setup.c
index 2657b61..0863a82 100644
--- a/lib/psci/psci_setup.c
+++ b/lib/psci/psci_setup.c
@@ -30,6 +30,7 @@
  * of relying on platform defined constants.
  ******************************************************************************/
 static cpu_context_t psci_ns_context[PLATFORM_CORE_COUNT];
+static entry_point_info_t warmboot_ep_info[PLATFORM_CORE_COUNT];
 
 /******************************************************************************
  * Define the psci capability variable.
@@ -114,6 +115,13 @@
 	}
 }
 
+static void __init populate_cpu_data(void)
+{
+	for (unsigned int idx = 0; idx < psci_plat_core_count; idx++) {
+		set_cpu_data_by_index(idx, warmboot_ep_info, &warmboot_ep_info[idx]);
+	}
+}
+
 /*******************************************************************************
  * Core routine to populate the power domain tree. The tree descriptor passed by
  * the platform is populated breadth-first and the first entry in the map
@@ -218,6 +226,9 @@
 	/* Update the CPU limits for each node in psci_non_cpu_pd_nodes */
 	psci_update_pwrlvl_limits();
 
+	/* Initialise the warmboot entrypoints */
+	populate_cpu_data();
+
 	/* Populate the mpidr field of cpu node for this CPU */
 	psci_cpu_pd_nodes[cpu_idx].mpidr =
 		read_mpidr() & MPIDR_AFFINITY_MASK;
diff --git a/lib/psci/psci_suspend.c b/lib/psci/psci_suspend.c
index 1c119d0..a7b53cb 100644
--- a/lib/psci/psci_suspend.c
+++ b/lib/psci/psci_suspend.c
@@ -45,7 +45,6 @@
 static void psci_suspend_to_pwrdown_start(unsigned int idx,
 					  unsigned int end_pwrlvl,
 					  unsigned int max_off_lvl,
-					  const entry_point_info_t *ep,
 					  const psci_power_state_t *state_info)
 {
 	PUBLISH_EVENT_ARG(psci_suspend_pwrdown_start, &idx);
@@ -85,12 +84,6 @@
 	if (psci_plat_pm_ops->pwr_domain_suspend_pwrdown_early != NULL)
 		psci_plat_pm_ops->pwr_domain_suspend_pwrdown_early(state_info);
 #endif
-
-	/*
-	 * Store the re-entry information for the non-secure world.
-	 */
-	cm_init_my_context(ep);
-
 	/*
 	 * Arch. management. Initiate power down sequence.
 	 */
@@ -116,7 +109,6 @@
  * not possible to undo any of the actions taken beyond that point.
  ******************************************************************************/
 int psci_cpu_suspend_start(unsigned int idx,
-			   const entry_point_info_t *ep,
 			   unsigned int end_pwrlvl,
 			   psci_power_state_t *state_info,
 			   unsigned int is_power_down_state)
@@ -124,10 +116,6 @@
 	int rc = PSCI_E_SUCCESS;
 	unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0};
 	unsigned int max_off_lvl = 0;
-#if FEAT_PABANDON
-	cpu_context_t *ctx = cm_get_context(NON_SECURE);
-	cpu_context_t old_ctx;
-#endif
 
 	/*
 	 * This function must only be called on platforms where the
@@ -205,26 +193,9 @@
 #if !CTX_INCLUDE_EL2_REGS
 		cm_el1_sysregs_context_save(NON_SECURE);
 #endif
-		/*
-		 * when the core wakes it expects its context to already be in
-		 * place so we must overwrite it before powerdown. But if
-		 * powerdown never happens we want the old context. Save it in
-		 * case we wake up. EL2/El1 will not be touched by PSCI so don't
-		 * copy */
-		memcpy(&ctx->gpregs_ctx, &old_ctx.gpregs_ctx, sizeof(gp_regs_t));
-		memcpy(&ctx->el3state_ctx, &old_ctx.el3state_ctx, sizeof(el3_state_t));
-#if DYNAMIC_WORKAROUND_CVE_2018_3639
-		memcpy(&ctx->cve_2018_3639_ctx, &old_ctx.cve_2018_3639_ctx, sizeof(cve_2018_3639_t));
-#endif
-#if ERRATA_SPECULATIVE_AT
-		memcpy(&ctx->errata_speculative_at_ctx, &old_ctx.errata_speculative_at_ctx, sizeof(errata_speculative_at_t));
-#endif
-#if CTX_INCLUDE_PAUTH_REGS
-		memcpy(&ctx->pauth_ctx, &old_ctx.pauth_ctx, sizeof(pauth_t));
-#endif
 #endif
 		max_off_lvl = psci_find_max_off_lvl(state_info);
-		psci_suspend_to_pwrdown_start(idx, end_pwrlvl, end_pwrlvl, ep, state_info);
+		psci_suspend_to_pwrdown_start(idx, end_pwrlvl, end_pwrlvl, state_info);
 	}
 
 	/*
@@ -301,18 +272,6 @@
 #if FEAT_PABANDON
 		psci_cpu_suspend_to_powerdown_finish(idx, max_off_lvl, state_info);
 
-		/* we overwrote context ourselves, put it back */
-		memcpy(&ctx->gpregs_ctx, &old_ctx.gpregs_ctx, sizeof(gp_regs_t));
-		memcpy(&ctx->el3state_ctx, &old_ctx.el3state_ctx, sizeof(el3_state_t));
-#if DYNAMIC_WORKAROUND_CVE_2018_3639
-		memcpy(&ctx->cve_2018_3639_ctx, &old_ctx.cve_2018_3639_ctx, sizeof(cve_2018_3639_t));
-#endif
-#if ERRATA_SPECULATIVE_AT
-		memcpy(&ctx->errata_speculative_at_ctx, &old_ctx.errata_speculative_at_ctx, sizeof(errata_speculative_at_t));
-#endif
-#if CTX_INCLUDE_PAUTH_REGS
-		memcpy(&ctx->pauth_ctx, &old_ctx.pauth_ctx, sizeof(pauth_t));
-#endif
 #if !CTX_INCLUDE_EL2_REGS
 		cm_el1_sysregs_context_restore(NON_SECURE);
 #endif
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 906e5d7..965698b 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -432,3 +432,8 @@
 
 # Enable RMMD to forward attestation requests from RMM to EL3.
 RMMD_ENABLE_EL3_TOKEN_SIGN	:= 0
+
+# Enable RMMD to program and manage IDE Keys at the PCIe Root Port(RP).
+# This flag is temporary and it is expected once the interface is
+# finalized, this flag will be removed.
+RMMD_ENABLE_IDE_KEY_PROG	:= 0
diff --git a/plat/amd/versal2/include/plat_ipi.h b/plat/amd/versal2/include/plat_ipi.h
index 503ec1f..c110fb8 100644
--- a/plat/amd/versal2/include/plat_ipi.h
+++ b/plat/amd/versal2/include/plat_ipi.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -11,6 +11,7 @@
 #define PLAT_IPI_H
 
 #include <stdint.h>
+#include <lib/utils_def.h>
 
 #include <ipi.h>
 
@@ -24,7 +25,15 @@
 #define IPI_ID_3	5U
 #define IPI_ID_4	6U
 #define IPI_ID_5	7U
-#define IPI_ID_MAX	8U
+#define IPI_ID_PMC_NOBUF	8U
+#define IPI_ID_6_NOBUF_95	9U
+#define IPI_ID_1_NOBUF	10U
+#define IPI_ID_2_NOBUF	11U
+#define IPI_ID_3_NOBUF	12U
+#define IPI_ID_4_NOBUF	13U
+#define IPI_ID_5_NOBUF	14U
+#define IPI_ID_6_NOBUF_101	15U
+#define IPI_ID_MAX	16U
 
 /*********************************************************************
  * IPI message buffers
@@ -56,17 +65,34 @@
  * IPI registers and bitfields
  ******************************************************************************/
 #define IPI0_REG_BASE		(0xEB330000U)
-#define IPI0_TRIG_BIT		(1 << 2)
-#define PMC_IPI_TRIG_BIT	(1 << 1)
+#define IPI0_TRIG_BIT		BIT_32(2)
+#define PMC_IPI_TRIG_BIT	BIT_32(1)
 #define IPI1_REG_BASE		(0xEB340000U)
-#define IPI1_TRIG_BIT		(1 << 3)
+#define IPI1_TRIG_BIT		BIT_32(3)
 #define IPI2_REG_BASE		(0xEB350000U)
-#define IPI2_TRIG_BIT		(1 << 4)
+#define IPI2_TRIG_BIT		BIT_32(4)
 #define IPI3_REG_BASE		(0xEB360000U)
-#define IPI3_TRIG_BIT		(1 << 5)
+#define IPI3_TRIG_BIT		BIT_32(5)
 #define IPI4_REG_BASE		(0xEB370000U)
-#define IPI4_TRIG_BIT		(1 << 6)
+#define IPI4_TRIG_BIT		BIT_32(6)
 #define IPI5_REG_BASE		(0xEB380000U)
-#define IPI5_TRIG_BIT		(1 << 7)
+#define IPI5_TRIG_BIT		BIT_32(7)
+
+#define PMC_NOBUF_REG_BASE	(0xEB390000U)
+#define PMC_NOBUF_TRIG_BIT	BIT_32(8)
+#define IPI6_NOBUF_95_REG_BASE	(0xEB3A0000U)
+#define IPI6_NOBUF_95_TRIG_BIT	BIT_32(9)
+#define IPI1_NOBUF_REG_BASE	(0xEB3B0000U)
+#define IPI1_NOBUF_TRIG_BIT	BIT_32(10)
+#define IPI2_NOBUF_REG_BASE	(0xEB3B1000U)
+#define IPI2_NOBUF_TRIG_BIT	BIT_32(11)
+#define IPI3_NOBUF_REG_BASE	(0xEB3B2000U)
+#define IPI3_NOBUF_TRIG_BIT	BIT_32(12)
+#define IPI4_NOBUF_REG_BASE	(0xEB3B3000U)
+#define IPI4_NOBUF_TRIG_BIT	BIT_32(13)
+#define IPI5_NOBUF_REG_BASE	(0xEB3B4000U)
+#define IPI5_NOBUF_TRIG_BIT	BIT_32(14)
+#define IPI6_NOBUF_101_REG_BASE	(0xEB3B5000U)
+#define IPI6_NOBUF_101_TRIG_BIT	BIT_32(15)
 
 #endif /* PLAT_IPI_H */
diff --git a/plat/amd/versal2/plat_psci_pm.c b/plat/amd/versal2/plat_psci_pm.c
index 50614d5..3cc6b95 100644
--- a/plat/amd/versal2/plat_psci_pm.c
+++ b/plat/amd/versal2/plat_psci_pm.c
@@ -110,7 +110,7 @@
 	 * Send the system reset request to the firmware if power down request
 	 * is not received from firmware.
 	 */
-	if (pwrdwn_req_received == true) {
+	if (pwrdwn_req_received == false) {
 		/*
 		 * TODO: shutdown scope for this reset needs be revised once
 		 * we have a clearer understanding of the overall reset scoping
diff --git a/plat/amd/versal2/pm_service/pm_svc_main.c b/plat/amd/versal2/pm_service/pm_svc_main.c
index 88848e2..10d2ed2 100644
--- a/plat/amd/versal2/pm_service/pm_svc_main.c
+++ b/plat/amd/versal2/pm_service/pm_svc_main.c
@@ -133,7 +133,7 @@
 
 	/* Check status register for each IPI except PMC */
 	for (i = IPI_ID_APU; i <= IPI_ID_5; i++) {
-		ipi_status = (uint32_t)ipi_mb_enquire_status(IPI_ID_APU, i);
+		ipi_status = ipi_mb_enquire_status(IPI_ID_APU, i);
 
 		/* If any agent other than PMC has generated IPI FIQ then send SGI to mbox driver */
 		if ((ipi_status & (uint32_t)IPI_MB_STATUS_RECV_PENDING) > (uint32_t) 0) {
@@ -143,8 +143,8 @@
 	}
 
 	/* If PMC has not generated interrupt then end ISR */
-	ipi_status = (uint32_t)ipi_mb_enquire_status(IPI_ID_APU, IPI_ID_PMC);
-	if ((ipi_status & (uint32_t) IPI_MB_STATUS_RECV_PENDING) == (uint32_t) 0) {
+	ipi_status = ipi_mb_enquire_status(IPI_ID_APU, IPI_ID_PMC);
+	if ((ipi_status & IPI_MB_STATUS_RECV_PENDING) == (uint32_t)0) {
 		plat_ic_end_of_interrupt(id);
 		goto end;
 	}
diff --git a/plat/amd/versal2/soc_ipi.c b/plat/amd/versal2/soc_ipi.c
index 85d1bcd..24ff969 100644
--- a/plat/amd/versal2/soc_ipi.c
+++ b/plat/amd/versal2/soc_ipi.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,7 +9,6 @@
  * SoC IPI agent registers access management
  */
 
-#include <lib/utils_def.h>
 #include <plat_ipi.h>
 
 /* versal2 ipi configuration table */
@@ -62,6 +61,62 @@
 		.ipi_reg_base = IPI5_REG_BASE,
 		.secure_only = 0,
 	},
+
+	/* PMC_NOBUF IPI */
+	[IPI_ID_PMC_NOBUF] = {
+		.ipi_bit_mask = PMC_NOBUF_TRIG_BIT,
+		.ipi_reg_base = PMC_NOBUF_REG_BASE,
+		.secure_only = IPI_SECURE_MASK,
+	},
+
+	/* IPI6 IPI */
+	[IPI_ID_6_NOBUF_95] = {
+		.ipi_bit_mask = IPI6_NOBUF_95_TRIG_BIT,
+		.ipi_reg_base = IPI6_NOBUF_95_REG_BASE,
+		.secure_only = 0,
+	},
+
+	/* IPI1 NO BUF IPI */
+	[IPI_ID_1_NOBUF] = {
+		.ipi_bit_mask = IPI1_NOBUF_TRIG_BIT,
+		.ipi_reg_base = IPI1_NOBUF_REG_BASE,
+		.secure_only = 0,
+	},
+
+	/* IPI2 NO BUF IPI */
+	[IPI_ID_2_NOBUF] = {
+		.ipi_bit_mask = IPI2_NOBUF_TRIG_BIT,
+		.ipi_reg_base = IPI2_NOBUF_REG_BASE,
+		.secure_only = 0,
+	},
+
+	/* IPI3 NO BUF IPI */
+	[IPI_ID_3_NOBUF] = {
+		.ipi_bit_mask = IPI3_NOBUF_TRIG_BIT,
+		.ipi_reg_base = IPI3_NOBUF_REG_BASE,
+		.secure_only = 0,
+	},
+
+	/* IPI4 NO BUF IPI */
+	[IPI_ID_4_NOBUF] = {
+		.ipi_bit_mask = IPI4_NOBUF_TRIG_BIT,
+		.ipi_reg_base = IPI4_NOBUF_REG_BASE,
+		.secure_only = 0,
+	},
+
+	/* IPI5 NO BUF IPI */
+	[IPI_ID_5_NOBUF] = {
+		.ipi_bit_mask = IPI5_NOBUF_TRIG_BIT,
+		.ipi_reg_base = IPI5_NOBUF_REG_BASE,
+		.secure_only = 0,
+	},
+
+	/* IPI6 NO BUF IPI */
+	[IPI_ID_6_NOBUF_101] = {
+		.ipi_bit_mask = IPI6_NOBUF_101_TRIG_BIT,
+		.ipi_reg_base = IPI6_NOBUF_101_REG_BASE,
+		.secure_only = 0,
+	},
 };
 
 /**
diff --git a/plat/arm/board/automotive_rd/platform/rd1ae/platform.mk b/plat/arm/board/automotive_rd/platform/rd1ae/platform.mk
index 12b1e8c..27a2b72 100644
--- a/plat/arm/board/automotive_rd/platform/rd1ae/platform.mk
+++ b/plat/arm/board/automotive_rd/platform/rd1ae/platform.mk
@@ -28,7 +28,7 @@
 ENABLE_FEAT_ECV				:=	1
 ENABLE_FEAT_FGT				:=	1
 ENABLE_FEAT_MTE2			:=	1
-ENABLE_MPAM_FOR_LOWER_ELS		:=	1
+ENABLE_FEAT_MPAM			:=	1
 GIC_ENABLE_V4_EXTN			:=	1
 GICV3_SUPPORT_GIC600			:=	1
 HW_ASSISTED_COHERENCY			:=	1
diff --git a/plat/arm/board/fvp/fvp_ide_keymgmt.c b/plat/arm/board/fvp/fvp_ide_keymgmt.c
new file mode 100644
index 0000000..ff05351
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_ide_keymgmt.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include <plat/common/platform.h>
+
+int plat_rmmd_el3_ide_key_program(uint64_t ecam_address, uint64_t root_port_id,
+				  uint64_t ide_stream_info,
+				  rp_ide_key_info_t *ide_key_info_ptr, uint64_t request_id,
+				  uint64_t cookie)
+{
+	/* placeholder to add further implementation */
+
+	return 0;
+
+}
+
+int plat_rmmd_el3_ide_key_set_go(uint64_t ecam_address, uint64_t root_port_id,
+				 uint64_t ide_stream_info, uint64_t request_id,
+				 uint64_t cookie)
+{
+	/* placeholder to add further implementation */
+
+	return 0;
+
+}
+
+int plat_rmmd_el3_ide_key_set_stop(uint64_t ecam_address, uint64_t root_port_id,
+				   uint64_t ide_stream_info, uint64_t request_id,
+				   uint64_t cookie)
+{
+	/* placeholder to add further implementation */
+
+	return 0;
+}
+
+int plat_rmmd_el3_ide_km_pull_response(uint64_t ecam_address, uint64_t root_port_id,
+				   uint64_t *req_resp, uint64_t *request,
+				   uint64_t *cookie)
+{
+	/* placeholder to add further implementation */
+	return E_RMM_UNK;
+}
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index f5be8f2..854e48a 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -307,9 +307,15 @@
  * calculated using the current SP_MIN PROGBITS debug size plus the sizes of
  * BL2 and BL1-RW
  */
+#if TRANSFER_LIST
 # define PLAT_ARM_MAX_BL32_SIZE		(PLAT_ARM_TRUSTED_SRAM_SIZE - \
 					 ARM_SHARED_RAM_SIZE - \
+					 PLAT_ARM_FW_HANDOFF_SIZE)
+#else
+# define PLAT_ARM_MAX_BL32_SIZE		(PLAT_ARM_TRUSTED_SRAM_SIZE - \
+					 ARM_SHARED_RAM_SIZE - \
 					 ARM_FW_CONFIGS_SIZE)
+#endif /* TRANSFER_LIST */
 #endif /* RESET_TO_SP_MIN */
 #endif
 
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 8c114e7..280aa39 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -95,6 +95,7 @@
 
 ifeq (${ENABLE_RME},1)
     ENABLE_FEAT_MEC		:= 2
+    RMMD_ENABLE_IDE_KEY_PROG	:= 1
 endif
 
 # The FVP platform depends on this macro to build with correct GIC driver.
@@ -302,7 +303,8 @@
 
 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_el3_token_sign.c
+				plat/arm/board/fvp/fvp_el3_token_sign.c		\
+				plat/arm/board/fvp/fvp_ide_keymgmt.c
 endif
 
 ifeq (${ENABLE_FEAT_RNG_TRAP},1)
diff --git a/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c b/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c
index 76ca5b5..8c193fa 100644
--- a/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c
+++ b/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c
@@ -14,16 +14,34 @@
 
 #include "../fvp_private.h"
 
+static uintptr_t hw_config __unused;
+
 void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1,
 			u_register_t arg2, u_register_t arg3)
 {
 	const struct dyn_cfg_dtb_info_t *tos_fw_config_info __unused;
+	struct transfer_list_header *tl __unused;
 
 	/* Initialize the console to provide early debug support */
 	arm_console_boot_init();
 
-#if !RESET_TO_SP_MIN && !RESET_TO_BL2
+#if TRANSFER_LIST
+	/*
+	 * Register usage at function entry:
+	 *   r0 - Reserved (must be zero)
+	 *   r1 - Register convention and TL signature
+	 *   r2 - Pointer to the FDT located within the TL
+	 *   r3 - Base address of the TL
+	 *
+	 * Initialize TL pointer from r3 and validate that the FDT pointer (arg2)
+	 * lies within the bounds of the Transfer List memory region.
+	 */
+	tl = (struct transfer_list_header *)arg3;
 
+	assert(arg2 > (uintptr_t)tl && arg2 < (uintptr_t)tl + tl->size);
+	hw_config = (uintptr_t)arg2;
+#else
+#if !RESET_TO_SP_MIN && !RESET_TO_BL2
 	INFO("SP_MIN FCONF: FW_CONFIG address = %lx\n", (uintptr_t)arg1);
 	/* Fill the properties struct with the info from the config dtb */
 	fconf_populate("FW_CONFIG", arg1);
@@ -33,6 +51,7 @@
 		arg1 = tos_fw_config_info->config_addr;
 	}
 #endif /* !RESET_TO_SP_MIN && !RESET_TO_BL2 */
+#endif /* TRANSFER_LIST */
 
 	arm_sp_min_early_platform_setup(arg0, arg1, arg2, arg3);
 
@@ -75,7 +94,10 @@
 	 * TODO: remove the ARM_XLAT_TABLES_LIB_V1 check when its support
 	 * gets deprecated.
 	 */
-#if !RESET_TO_SP_MIN && !RESET_TO_BL2 && !ARM_XLAT_TABLES_LIB_V1
+#if TRANSFER_LIST
+	INFO("SP_MIN FCONF: HW_CONFIG address = %p\n", (void *)hw_config);
+	fconf_populate("HW_CONFIG", hw_config);
+#elif !RESET_TO_SP_MIN && !RESET_TO_BL2 && !ARM_XLAT_TABLES_LIB_V1
 	hw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, HW_CONFIG_ID);
 	assert(hw_config_info != NULL);
 	assert(hw_config_info->config_addr != 0UL);
@@ -118,5 +140,6 @@
 		      rc);
 		panic();
 	}
-#endif /*!RESET_TO_SP_MIN && !RESET_TO_BL2 && !ARM_XLAT_TABLES_LIB_V1*/
+
+#endif /* TRANSFER_LIST */
 }
diff --git a/plat/arm/board/fvp/trp/test_ide_km_interface.c b/plat/arm/board/fvp/trp/test_ide_km_interface.c
new file mode 100644
index 0000000..2a1f0e2
--- /dev/null
+++ b/plat/arm/board/fvp/trp/test_ide_km_interface.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <plat/common/platform.h>
+#include <services/trp/platform_trp.h>
+
+#include <platform_def.h>
+
+/*
+ * Helper function for ecam address and root port ID
+ *
+ */
+uint64_t trp_get_test_rootport(uint64_t *ecam_address, uint64_t *rp_id)
+{
+
+	*ecam_address = 0xE001C000;
+	*rp_id = 0x001C0001;
+
+	return 0;
+}
+
diff --git a/plat/arm/board/fvp/trp/trp-fvp.mk b/plat/arm/board/fvp/trp/trp-fvp.mk
index a450541..3c1b96b 100644
--- a/plat/arm/board/fvp/trp/trp-fvp.mk
+++ b/plat/arm/board/fvp/trp/trp-fvp.mk
@@ -6,7 +6,8 @@
 
 # TRP source files specific to FVP platform
 
-RMM_SOURCES		+=	plat/arm/board/fvp/aarch64/fvp_helpers.S
+RMM_SOURCES		+=	plat/arm/board/fvp/aarch64/fvp_helpers.S	\
+				plat/arm/board/fvp/trp/test_ide_km_interface.c
 
 include plat/arm/common/trp/arm_trp.mk
 
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
index a056bc2..cf42243 100644
--- a/plat/arm/board/tc/platform.mk
+++ b/plat/arm/board/tc/platform.mk
@@ -35,8 +35,8 @@
 ENABLE_AMU_AUXILIARY_COUNTERS	:=	1
 ENABLE_MPMM			:=	1
 ENABLE_FEAT_MTE2		:=	2
-ENABLE_SPE_FOR_NS		:=	3
-ENABLE_FEAT_TCR2		:=	3
+ENABLE_SPE_FOR_NS		:=	2
+ENABLE_FEAT_TCR2		:=	2
 
 ifneq ($(filter ${TARGET_PLATFORM}, 3),)
 ENABLE_FEAT_RNG_TRAP		:=	0
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index 75d6a53..06a919c 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -289,18 +289,17 @@
 	return  is_fwu_needed ? NS_BL1U_IMAGE_ID : BL2_IMAGE_ID;
 }
 
-// Use the default implementation of this function when Firmware Handoff is
-// disabled to avoid duplicating its logic.
 #if TRANSFER_LIST
 int bl1_plat_handle_post_image_load(unsigned int image_id)
 {
-	image_desc_t *image_desc __unused;
-
-	assert(image_id == BL2_IMAGE_ID);
 	struct transfer_list_entry *te;
 
+	if (image_id != BL2_IMAGE_ID) {
+		return 0;
+	}
+
 	/* Convey this information to BL2 via its TL. */
-	te = transfer_list_add(secure_tl, TL_TAG_SRAM_LAYOUT64,
+	te = transfer_list_add(secure_tl, TL_TAG_SRAM_LAYOUT,
 			       sizeof(meminfo_t), NULL);
 	assert(te != NULL);
 
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 6418628..bd3946c 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -78,7 +78,7 @@
 #if TRANSFER_LIST
 	secure_tl = (struct transfer_list_header *)arg3;
 
-	te = transfer_list_find(secure_tl, TL_TAG_SRAM_LAYOUT64);
+	te = transfer_list_find(secure_tl, TL_TAG_SRAM_LAYOUT);
 	assert(te != NULL);
 
 	bl2_tzram_layout = *(meminfo_t *)transfer_list_entry_data(te);
diff --git a/plat/arm/common/arm_transfer_list.c b/plat/arm/common/arm_transfer_list.c
index 6847591..5a480b6 100644
--- a/plat/arm/common/arm_transfer_list.c
+++ b/plat/arm/common/arm_transfer_list.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2024-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -71,9 +71,8 @@
 					struct transfer_list_header *tl)
 {
 	uint32_t next_exe_img_id;
-	entry_point_info_t *ep;
+	entry_point_info_t *ep __unused;
 	struct transfer_list_entry *te;
-
 	assert(next_param_node != NULL);
 
 	while ((next_exe_img_id = next_param_node->next_handoff_image_id) !=
@@ -83,14 +82,16 @@
 				next_exe_img_id)];
 		assert(next_param_node != NULL);
 
-		te = transfer_list_add(tl, TL_TAG_EXEC_EP_INFO64,
+		te = transfer_list_add(tl, TL_TAG_EXEC_EP_INFO,
 				       sizeof(entry_point_info_t),
 				       &next_param_node->ep_info);
 		assert(te != NULL);
 
 		ep = transfer_list_entry_data(te);
+		assert(ep != NULL);
 
-		if ((next_exe_img_id == BL32_IMAGE_ID) && SPMC_AT_EL3) {
+#if SPMC_AT_EL3
+		if (next_exe_img_id == BL32_IMAGE_ID) {
 			/*
 			 * Populate the BL32 image base, size and max limit in
 			 * the entry point information, since there is no
@@ -106,6 +107,7 @@
 				next_param_node->image_info.image_base +
 				next_param_node->image_info.image_max_size;
 		}
+#endif /* SPMC_AT_EL3 */
 
 		next_exe_img_id = next_param_node->next_handoff_image_id;
 	}
diff --git a/plat/arm/common/sp_min/arm_sp_min_setup.c b/plat/arm/common/sp_min/arm_sp_min_setup.c
index 78fc88e..cc4ae59 100644
--- a/plat/arm/common/sp_min/arm_sp_min_setup.c
+++ b/plat/arm/common/sp_min/arm_sp_min_setup.c
@@ -16,6 +16,9 @@
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
 
+struct transfer_list_header *secure_tl;
+struct transfer_list_header *ns_tl __unused;
+
 static entry_point_info_t bl33_image_ep_info;
 
 /* Weak definitions may be overridden in specific ARM standard platform */
@@ -28,13 +31,25 @@
 					BL32_END - BL32_BASE,		\
 					MT_MEMORY | MT_RW | MT_SECURE)
 
+#define MAP_EL3_FW_HANDOFF                            \
+	MAP_REGION_FLAT(PLAT_ARM_EL3_FW_HANDOFF_BASE, \
+			PLAT_ARM_FW_HANDOFF_SIZE, MT_MEMORY | MT_RW | EL3_PAS)
+
+#define MAP_FW_NS_HANDOFF                                             \
+	MAP_REGION_FLAT(FW_NS_HANDOFF_BASE, PLAT_ARM_FW_HANDOFF_SIZE, \
+			MT_MEMORY | MT_RW | MT_NS)
+
 /*
  * Check that BL32_BASE is above ARM_FW_CONFIG_LIMIT. The reserved page
  * is required for SOC_FW_CONFIG/TOS_FW_CONFIG passed from BL2.
  */
 #if !RESET_TO_SP_MIN
+#if TRANSFER_LIST
+CASSERT(BL32_BASE >= PLAT_ARM_EL3_FW_HANDOFF_LIMIT, assert_bl32_base_overflows);
+#else
 CASSERT(BL32_BASE >= ARM_FW_CONFIG_LIMIT, assert_bl32_base_overflows);
 #endif
+#endif
 
 /*******************************************************************************
  * Return a pointer to the 'entry_point_info' structure of the next image for the
@@ -64,9 +79,22 @@
 void arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1,
 			u_register_t arg2, u_register_t arg3)
 {
+	struct transfer_list_entry *te __unused;
+
 	/* Initialize the console to provide early debug support */
 	arm_console_boot_init();
 
+#if TRANSFER_LIST
+	secure_tl = (struct transfer_list_header *)arg3;
+
+	te = transfer_list_find(secure_tl, TL_TAG_EXEC_EP_INFO32);
+	assert(te != NULL);
+
+	bl33_image_ep_info =
+		*(struct entry_point_info *)transfer_list_entry_data(te);
+	return;
+#endif /* TRANSFER_LIST */
+
 #if RESET_TO_SP_MIN
 	/* Populate entry point information for BL33 */
 	SET_PARAM_HEAD(&bl33_image_ep_info,
@@ -81,7 +109,7 @@
 	bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry();
 	SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
 
-# if ARM_LINUX_KERNEL_AS_BL33
+#if ARM_LINUX_KERNEL_AS_BL33
 	/*
 	 * According to the file ``Documentation/arm/Booting`` of the Linux
 	 * kernel tree, Linux expects:
@@ -176,10 +204,33 @@
  ******************************************************************************/
 void sp_min_platform_setup(void)
 {
+	struct transfer_list_entry *te __unused;
+
 	/* Initialize the GIC driver, cpu and distributor interfaces */
 	plat_arm_gic_driver_init();
 	plat_arm_gic_init();
 
+#if TRANSFER_LIST
+	ns_tl = transfer_list_ensure((void *)FW_NS_HANDOFF_BASE,
+				       PLAT_ARM_FW_HANDOFF_SIZE);
+	if (ns_tl == NULL) {
+		ERROR("Non-secure transfer list initialisation failed!\n");
+		panic();
+	}
+
+	te = transfer_list_find(secure_tl, TL_TAG_FDT);
+	if (te != NULL) {
+		te = transfer_list_add(ns_tl, TL_TAG_FDT, te->data_size,
+				  (void *)transfer_list_entry_data(te));
+		if (te == NULL) {
+			ERROR("Failed to relocate device tree into non-secure memory.\n");
+			panic();
+		}
+	}
+
+	transfer_list_set_handoff_args(ns_tl, &bl33_image_ep_info);
+#endif
+
 	/*
 	 * Do initial security configuration to allow DRAM/device access
 	 * (if earlier BL has not already done so).
@@ -223,6 +274,10 @@
 #if USE_COHERENT_MEM
 		ARM_MAP_BL_COHERENT_RAM,
 #endif
+#if TRANSFER_LIST
+		MAP_EL3_FW_HANDOFF,
+		MAP_FW_NS_HANDOFF,
+#endif
 		{0}
 	};
 
diff --git a/plat/xilinx/common/include/ipi.h b/plat/xilinx/common/include/ipi.h
index d792710..71c06c3 100644
--- a/plat/xilinx/common/include/ipi.h
+++ b/plat/xilinx/common/include/ipi.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2018, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -60,7 +61,7 @@
 void ipi_mb_release(uint32_t local, uint32_t remote);
 
 /* Enquire IPI mailbox status */
-int ipi_mb_enquire_status(uint32_t local, uint32_t remote);
+uint32_t ipi_mb_enquire_status(uint32_t local, uint32_t remote);
 
 /* Trigger notification on the IPI mailbox */
 void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking);
diff --git a/plat/xilinx/common/include/pm_api_sys.h b/plat/xilinx/common/include/pm_api_sys.h
index 029bb43..2e4b342 100644
--- a/plat/xilinx/common/include/pm_api_sys.h
+++ b/plat/xilinx/common/include/pm_api_sys.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -36,7 +36,7 @@
 				  uint32_t state, uint32_t flag);
 enum pm_ret_status pm_req_wakeup(uint32_t target, uint32_t set_address,
 				 uintptr_t address, uint8_t ack, uint32_t flag);
-enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t device_id,
+enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t wkup_device,
 					uint8_t enable, uint32_t flag);
 enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag,
 			 uint32_t ack);
diff --git a/plat/xilinx/common/ipi.c b/plat/xilinx/common/ipi.c
index cc4b04d..18ae096 100644
--- a/plat/xilinx/common/ipi.c
+++ b/plat/xilinx/common/ipi.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2020-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -20,6 +20,7 @@
 
 #include <ipi.h>
 #include <plat_private.h>
+#include "pm_defs.h"
 
 /*********************************************************************
  * Macros definitions
@@ -139,13 +140,12 @@
  * @local: local IPI ID.
  * @remote: remote IPI ID.
  *
- * Return: 0 idle, positive value for pending sending or receiving,
- *         negative value for errors.
+ * Return: 0 idle and positive value for pending sending or receiving.
  *
  */
-int ipi_mb_enquire_status(uint32_t local, uint32_t remote)
+uint32_t ipi_mb_enquire_status(uint32_t local, uint32_t remote)
 {
-	int ret = 0U;
+	uint32_t ret = (uint32_t)PM_RET_SUCCESS;
 	uint32_t status;
 	uint64_t obr_offset = (uint64_t)(IPI_REG_BASE(local) + IPI_OBR_OFFSET);
 	uint64_t isr_offset = (uint64_t)(IPI_REG_BASE(local) + IPI_ISR_OFFSET);
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 1882669..a2541a3 100644
--- a/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c
+++ b/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -109,7 +109,7 @@
 		bool disable_interrupt;
 
 		disable_interrupt = ((x3 & IPI_SMC_ENQUIRY_DIRQ_MASK) != 0U);
-		ret = ipi_mb_enquire_status(ipi_local_id, ipi_remote_id);
+		ret = (int32_t)ipi_mb_enquire_status(ipi_local_id, ipi_remote_id);
 		if ((((uint32_t)ret & IPI_MB_STATUS_RECV_PENDING) > 0U) && disable_interrupt) {
 			ipi_mb_disable_irq(ipi_local_id, ipi_remote_id);
 		}
diff --git a/plat/xilinx/common/pm_service/pm_ipi.c b/plat/xilinx/common/pm_service/pm_ipi.c
index bf1fd55..610acc7 100644
--- a/plat/xilinx/common/pm_service/pm_ipi.c
+++ b/plat/xilinx/common/pm_service/pm_ipi.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.
  * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -186,7 +186,12 @@
 		value[i] = mmio_read_32(buffer_base + ((i + 1U) * PAYLOAD_ARG_SIZE));
 	}
 
-	ret = mmio_read_32(buffer_base);
+	/*
+	 * Here mmio_read_32() reads return status stored in IPI payload that
+	 * is received from firmware and it's value will be one the values
+	 * listed in enum pm_ret_status.
+	 */
+	ret = (enum pm_ret_status)mmio_read_32(buffer_base);
 #if IPI_CRC_CHECK
 	crc = mmio_read_32(buffer_base + (PAYLOAD_CRC_POS * PAYLOAD_ARG_SIZE));
 	if (crc != calculate_crc((uint32_t *)buffer_base, IPI_W0_TO_W6_SIZE)) {
@@ -273,7 +278,8 @@
 		goto unlock;
 	}
 
-	ret = ERROR_CODE_MASK & (uint32_t)(pm_ipi_buff_read(proc, value, count));
+	ret = (enum pm_ret_status)(ERROR_CODE_MASK &
+				   (uint32_t)(pm_ipi_buff_read(proc, value, count)));
 
 unlock:
 	pm_ipi_lock_release();
@@ -293,15 +299,13 @@
 
 uint32_t pm_ipi_irq_status(const struct pm_proc *proc)
 {
-	int32_t ret;
-	int32_t result = 0;
+	uint32_t ret;
+	uint32_t result = (uint32_t)PM_RET_SUCCESS;
 
 	ret = ipi_mb_enquire_status(proc->ipi->local_ipi_id,
 				    proc->ipi->remote_ipi_id);
-	if (((uint32_t)ret & IPI_MB_STATUS_RECV_PENDING) != 0U) {
-		result = 1;
-	} else {
-		result = 0;
+	if ((ret & IPI_MB_STATUS_RECV_PENDING) != 0U) {
+		result = IPI_MB_STATUS_RECV_PENDING;
 	}
 
 	return result;
diff --git a/plat/xilinx/common/pm_service/pm_svc_main.c b/plat/xilinx/common/pm_service/pm_svc_main.c
index f586ac3..bc8e251 100644
--- a/plat/xilinx/common/pm_service/pm_svc_main.c
+++ b/plat/xilinx/common/pm_service/pm_svc_main.c
@@ -72,7 +72,7 @@
 
 static void notify_os(void)
 {
-	plat_ic_raise_ns_sgi(sgi, read_mpidr_el1());
+	plat_ic_raise_ns_sgi((int)sgi, read_mpidr_el1());
 }
 
 static uint64_t cpu_pwrdwn_req_handler(uint32_t id, uint32_t flags,
@@ -89,7 +89,7 @@
 	/* Deactivate CPU power down SGI */
 	plat_ic_end_of_interrupt(CPU_PWR_DOWN_REQ_INTR);
 
-	return psci_cpu_off();
+	return (uint64_t)psci_cpu_off();
 }
 
 /**
@@ -101,19 +101,19 @@
  */
 static void raise_pwr_down_interrupt(u_register_t mpidr)
 {
-	plat_ic_raise_el3_sgi(CPU_PWR_DOWN_REQ_INTR, mpidr);
+	plat_ic_raise_el3_sgi((int)CPU_PWR_DOWN_REQ_INTR, mpidr);
 }
 
 void request_cpu_pwrdwn(void)
 {
-	enum pm_ret_status ret;
+	int ret;
 
 	VERBOSE("CPU power down request received\n");
 
 	/* Send powerdown request to online secondary core(s) */
 	ret = psci_stop_other_cores(plat_my_core_pos(), PWRDWN_WAIT_TIMEOUT,
 				    raise_pwr_down_interrupt);
-	if (ret != (uint32_t)PSCI_E_SUCCESS) {
+	if (ret != PSCI_E_SUCCESS) {
 		ERROR("Failed to powerdown secondary core(s)\n");
 	}
 
@@ -132,7 +132,7 @@
 	(void)cookie;
 	uint32_t payload[4] = {0};
 	enum pm_ret_status ret;
-	int ipi_status, i;
+	uint32_t ipi_status, i;
 
 	VERBOSE("Received IPI FIQ from firmware\n");
 
@@ -140,19 +140,19 @@
 	(void)plat_ic_acknowledge_interrupt();
 
 	/* Check status register for each IPI except PMC */
-	for (i = (int32_t)IPI_ID_APU; i <= IPI_ID_5; i++) {
+	for (i = IPI_ID_APU; i <= IPI_ID_5; i++) {
 		ipi_status = ipi_mb_enquire_status(IPI_ID_APU, i);
 
 		/* If any agent other than PMC has generated IPI FIQ then send SGI to mbox driver */
-		if ((uint32_t)ipi_status & IPI_MB_STATUS_RECV_PENDING) {
-			plat_ic_raise_ns_sgi(MBOX_SGI_SHARED_IPI, read_mpidr_el1());
+		if ((ipi_status & IPI_MB_STATUS_RECV_PENDING) != 0U) {
+			plat_ic_raise_ns_sgi((int)MBOX_SGI_SHARED_IPI, read_mpidr_el1());
 			break;
 		}
 	}
 
 	/* If PMC has not generated interrupt then end ISR */
 	ipi_status = ipi_mb_enquire_status(IPI_ID_APU, IPI_ID_PMC);
-	if (((uint32_t)ipi_status & IPI_MB_STATUS_RECV_PENDING) == 0U) {
+	if ((ipi_status & IPI_MB_STATUS_RECV_PENDING) == 0U) {
 		plat_ic_end_of_interrupt(id);
 		goto exit_label;
 	}
@@ -187,7 +187,7 @@
 			(void)psci_cpu_off();
 		}
 		break;
-	case PM_RET_ERROR_INVALID_CRC:
+	case (uint32_t)PM_RET_ERROR_INVALID_CRC:
 		pm_ipi_irq_clear(primary_proc);
 		WARN("Invalid CRC in the payload\n");
 		break;
@@ -359,16 +359,16 @@
 		SMC_RET1(handle, (u_register_t)ret);
 
 	case (uint32_t)PM_FORCE_POWERDOWN:
-		ret = pm_force_powerdown(pm_arg[0], pm_arg[1], security_flag);
+		ret = pm_force_powerdown(pm_arg[0], (uint8_t)pm_arg[1], security_flag);
 		SMC_RET1(handle, (u_register_t)ret);
 
 	case (uint32_t)PM_REQ_SUSPEND:
-		ret = pm_req_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
+		ret = pm_req_suspend(pm_arg[0], (uint8_t)pm_arg[1], pm_arg[2],
 				     pm_arg[3], security_flag);
 		SMC_RET1(handle, (u_register_t)ret);
 
 	case (uint32_t)PM_ABORT_SUSPEND:
-		ret = pm_abort_suspend(pm_arg[0], security_flag);
+		ret = pm_abort_suspend((enum pm_abort_reason)pm_arg[0], security_flag);
 		SMC_RET1(handle, (u_register_t)ret);
 
 	case (uint32_t)PM_SYSTEM_SHUTDOWN:
@@ -426,7 +426,7 @@
 		enum pm_ret_status ret;
 
 		ret = pm_get_callbackdata(result, ARRAY_SIZE(result), security_flag, 1U);
-		if (ret != 0) {
+		if (ret != PM_RET_SUCCESS) {
 			result[0] = (uint32_t)ret;
 		}
 
@@ -597,7 +597,8 @@
 		return ret;
 	}
 
-	ret = eemi_psci_debugfs_handler(api_id, pm_arg, handle, flags);
+	ret = eemi_psci_debugfs_handler(api_id, pm_arg, handle,
+					(uint32_t)flags);
 	if (ret !=  (uintptr_t)0) {
 		return ret;
 	}
diff --git a/plat/xilinx/versal/plat_psci.c b/plat/xilinx/versal/plat_psci.c
index 396d7c7..032339f 100644
--- a/plat/xilinx/versal/plat_psci.c
+++ b/plat/xilinx/versal/plat_psci.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
- * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -22,6 +22,9 @@
 #include "pm_ipi.h"
 #include "pm_svc_main.h"
 
+#define SEC_ENTRY_ADDRESS_MASK		0xFFFFFFFFUL
+#define RESUME_ADDR_SET			0x1UL
+
 static uintptr_t versal_sec_entry;
 
 static int32_t versal_pwr_domain_on(u_register_t mpidr)
@@ -42,8 +45,9 @@
 	}
 
 	/* Send request to PMC to wake up selected ACPU core */
-	(void)pm_req_wakeup(proc->node_id, (versal_sec_entry & 0xFFFFFFFFU) | 0x1U,
-			    versal_sec_entry >> 32, 0, SECURE_FLAG);
+	(void)pm_req_wakeup(proc->node_id,
+			    (uint32_t)((versal_sec_entry & SEC_ENTRY_ADDRESS_MASK) |
+			    RESUME_ADDR_SET), versal_sec_entry >> 32, 0, SECURE_FLAG);
 
 	/* Clear power down request */
 	pm_client_wakeup(proc);
@@ -237,7 +241,8 @@
 	 * invoking CPU_on function, during which resume address will
 	 * be set.
 	 */
-	ret = pm_feature_check((uint32_t)PM_SELF_SUSPEND, &version_type[0], SECURE_FLAG);
+	ret = (uint32_t)pm_feature_check((uint32_t)PM_SELF_SUSPEND,
+					 &version_type[0], SECURE_FLAG);
 	if (ret == (uint32_t)PM_RET_SUCCESS) {
 		fw_api_version = version_type[0] & 0xFFFFU;
 		if (fw_api_version >= 3U) {
@@ -311,7 +316,7 @@
 /*******************************************************************************
  * Export the platform specific power ops.
  ******************************************************************************/
-int32_t plat_setup_psci_ops(uintptr_t sec_entrypoint,
+int plat_setup_psci_ops(uintptr_t sec_entrypoint,
 			const struct plat_psci_ops **psci_ops)
 {
 	versal_sec_entry = sec_entrypoint;
diff --git a/plat/xilinx/versal/sip_svc_setup.c b/plat/xilinx/versal/sip_svc_setup.c
index 3027946..bb3f728 100644
--- a/plat/xilinx/versal/sip_svc_setup.c
+++ b/plat/xilinx/versal/sip_svc_setup.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
- * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -116,6 +116,6 @@
 		sip_svc,
 		OEN_SIP_START,
 		OEN_SIP_END,
-		SMC_TYPE_FAST,
+		(uint8_t)SMC_TYPE_FAST,
 		sip_svc_setup,
 		sip_svc_smc_handler);
diff --git a/plat/xilinx/versal/versal_ipi.c b/plat/xilinx/versal/versal_ipi.c
index 74b082d..ac2a3c0 100644
--- a/plat/xilinx/versal/versal_ipi.c
+++ b/plat/xilinx/versal/versal_ipi.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -73,5 +73,6 @@
  */
 void versal_ipi_config_table_init(void)
 {
-	ipi_config_table_init(versal_ipi_table, ARRAY_SIZE(versal_ipi_table));
+	ipi_config_table_init(versal_ipi_table,
+			      (uint32_t)ARRAY_SIZE(versal_ipi_table));
 }
diff --git a/services/spd/tlkd/tlkd.mk b/services/spd/tlkd/tlkd.mk
index fc8840d..6d71632 100644
--- a/services/spd/tlkd/tlkd.mk
+++ b/services/spd/tlkd/tlkd.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2024, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2024-2025, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -8,9 +8,11 @@
 SPD_INCLUDES		:=	-Iinclude/bl32/payloads
 endif
 
-ifeq (${ENABLE_FEAT_D128}, 0)
+ifneq (${ENABLE_FEAT_D128}, 0)
+        $(error spd=tlkd will not work with ENABLE_FEAT_D128 enabled.)
+endif
+
 SPD_SOURCES		:=	services/spd/tlkd/tlkd_common.c		\
 				services/spd/tlkd/tlkd_helpers.S	\
 				services/spd/tlkd/tlkd_main.c		\
 				services/spd/tlkd/tlkd_pm.c
-endif
\ No newline at end of file
diff --git a/services/std_svc/rmmd/rmmd.mk b/services/std_svc/rmmd/rmmd.mk
index eae5031..67955ff 100644
--- a/services/std_svc/rmmd/rmmd.mk
+++ b/services/std_svc/rmmd/rmmd.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2021-2024, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2021-2025, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -16,7 +16,8 @@
 RMMD_SOURCES	+=	$(addprefix services/std_svc/rmmd/,	\
 			${ARCH}/rmmd_helpers.S			\
 			rmmd_main.c				\
-			rmmd_attest.c)
+			rmmd_attest.c				\
+			rmmd_keymgmt.c)
 
 # Let the top-level Makefile know that we intend to include RMM image
 NEED_RMM	:=	yes
diff --git a/services/std_svc/rmmd/rmmd_keymgmt.c b/services/std_svc/rmmd/rmmd_keymgmt.c
new file mode 100644
index 0000000..2414b35
--- /dev/null
+++ b/services/std_svc/rmmd/rmmd_keymgmt.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include "rmmd_private.h"
+#include <common/debug.h>
+#include <lib/spinlock.h>
+#include <plat/common/platform.h>
+#include <services/rmmd_svc.h>
+#include <smccc_helpers.h>
+
+#define DIR_BIT_SHIFT		0xB
+#define KEYSET_BIT_SHIFT	0xC
+#define STREAM_ID_MASK		0xFF
+#define SUBSTREAM_MASK		0x7
+#define SUBSTREAM_SHIFT		0x8
+#define MAX_STREAM_ID		32U
+#define MAX_SUBSTREAM		3U
+
+bool extract_ide_stream_info(uint64_t ide_stream_info)
+{
+	uint8_t keyset, dir;
+	uint8_t stream_id, substream;
+
+	/* Extract keyset, dir, substream and stream ID */
+	keyset = (ide_stream_info >> KEYSET_BIT_SHIFT) & 0x1;
+	dir = (ide_stream_info >> DIR_BIT_SHIFT) & 0x1;
+	stream_id = ide_stream_info & STREAM_ID_MASK;
+	substream = (ide_stream_info >> SUBSTREAM_SHIFT) & SUBSTREAM_MASK;
+
+	if ((stream_id >= MAX_STREAM_ID) || (substream >= MAX_SUBSTREAM)) {
+		ERROR("invalid input: stream_id = %x, substream = %x\n", stream_id, substream);
+		return false;
+	}
+
+	VERBOSE("keyset = %d, dir = %d, stream_id = %d and substream = %d\n", keyset, dir,
+		 stream_id, substream);
+
+	return true;
+}
+
+int rmmd_el3_ide_key_program(uint64_t ecam_address, uint64_t rp_id,
+			     uint64_t ide_stream_info, rp_ide_key_info_t *ide_key_info_ptr,
+			     uint64_t request_id, uint64_t cookie)
+{
+	int err;
+
+	/* TODO: Do validation of params */
+
+	VERBOSE("IDE_KEY_PROG: ecam address = 0x%lx and rp_id = 0x%lx\n", ecam_address, rp_id);
+
+	if (!extract_ide_stream_info(ide_stream_info)) {
+		err = E_RMM_INVAL;
+		goto exit_fn;
+	}
+
+	err = plat_rmmd_el3_ide_key_program(ecam_address, rp_id, ide_stream_info,
+					    ide_key_info_ptr, request_id, cookie);
+
+	assert(err == E_RMM_OK || err == E_RMM_AGAIN || err == E_RMM_INVAL ||
+		err == E_RMM_IN_PROGRESS || err == E_RMM_UNK || err == E_RMM_FAULT);
+
+exit_fn:
+	return err;
+}
+
+int rmmd_el3_ide_key_set_go(uint64_t ecam_address, uint64_t rp_id,
+			    uint64_t ide_stream_info, uint64_t request_id,
+			    uint64_t cookie)
+{
+	int err;
+
+	/* TODO: Do validation of params */
+
+	VERBOSE("IDE_KEY_SET_GO: ecam address = 0x%lx and rp_id = 0x%lx\n", ecam_address, rp_id);
+
+	if (!extract_ide_stream_info(ide_stream_info)) {
+		err = E_RMM_INVAL;
+		goto exit_fn;
+	}
+
+	err = plat_rmmd_el3_ide_key_set_go(ecam_address, rp_id, ide_stream_info,
+					   request_id, cookie);
+
+	assert(err == E_RMM_OK || err == E_RMM_AGAIN || err == E_RMM_INVAL ||
+		err == E_RMM_IN_PROGRESS || err == E_RMM_UNK || err == E_RMM_FAULT);
+
+exit_fn:
+	return err;
+}
+
+int rmmd_el3_ide_key_set_stop(uint64_t ecam_address, uint64_t rp_id,
+			      uint64_t ide_stream_info, uint64_t request_id,
+			      uint64_t cookie)
+{
+	int err;
+
+	/* TODO: Do validation of params */
+
+	VERBOSE("IDE_KEY_SET_STOP: ecam address = 0x%lx and rp_id = 0x%lx\n", ecam_address, rp_id);
+
+	if (!extract_ide_stream_info(ide_stream_info)) {
+		err = E_RMM_INVAL;
+		goto exit_fn;
+	}
+
+	err = plat_rmmd_el3_ide_key_set_stop(ecam_address, rp_id, ide_stream_info,
+					     request_id, cookie);
+
+	assert(err == E_RMM_OK || err == E_RMM_AGAIN || err == E_RMM_INVAL ||
+		err == E_RMM_IN_PROGRESS || err == E_RMM_UNK || err == E_RMM_FAULT);
+
+exit_fn:
+	return err;
+}
+
+int rmmd_el3_ide_km_pull_response(uint64_t ecam_address, uint64_t rp_id,
+				  uint64_t *req_resp, uint64_t *request_id,
+				  uint64_t *cookie)
+{
+	int err;
+
+	/* TODO: Do validation of params */
+
+	VERBOSE("IDE_KM_PULL: ecam address = 0x%lx, rp_id = 0x%lx\n", ecam_address, rp_id);
+
+	err = plat_rmmd_el3_ide_km_pull_response(ecam_address, rp_id, req_resp, request_id, cookie);
+
+	assert(err == E_RMM_OK || err == E_RMM_AGAIN || err == E_RMM_INVAL ||
+		err == E_RMM_IN_PROGRESS || err == E_RMM_UNK || err == E_RMM_FAULT);
+
+	return err;
+}
diff --git a/services/std_svc/rmmd/rmmd_main.c b/services/std_svc/rmmd/rmmd_main.c
index 19c8373..35582dc 100644
--- a/services/std_svc/rmmd/rmmd_main.c
+++ b/services/std_svc/rmmd/rmmd_main.c
@@ -561,6 +561,37 @@
 	case RMM_EL3_TOKEN_SIGN:
 		return rmmd_el3_token_sign(handle, x1, x2, x3, x4);
 #endif
+
+#if RMMD_ENABLE_IDE_KEY_PROG
+	case RMM_IDE_KEY_PROG:
+	{
+		rp_ide_key_info_t ide_key_info;
+
+		ide_key_info.keyqw0 = x4;
+		ide_key_info.keyqw1 = SMC_GET_GP(handle, CTX_GPREG_X5);
+		ide_key_info.keyqw2 = SMC_GET_GP(handle, CTX_GPREG_X6);
+		ide_key_info.keyqw3 = SMC_GET_GP(handle, CTX_GPREG_X7);
+		ide_key_info.ifvqw0 = SMC_GET_GP(handle, CTX_GPREG_X8);
+		ide_key_info.ifvqw1 = SMC_GET_GP(handle, CTX_GPREG_X9);
+		uint64_t x10 = SMC_GET_GP(handle, CTX_GPREG_X10);
+		uint64_t x11 = SMC_GET_GP(handle, CTX_GPREG_X11);
+
+		ret = rmmd_el3_ide_key_program(x1, x2, x3, &ide_key_info, x10, x11);
+		SMC_RET1(handle, ret);
+	}
+	case RMM_IDE_KEY_SET_GO:
+		ret = rmmd_el3_ide_key_set_go(x1, x2, x3, x4, SMC_GET_GP(handle, CTX_GPREG_X5));
+		SMC_RET1(handle, ret);
+	case RMM_IDE_KEY_SET_STOP:
+		ret = rmmd_el3_ide_key_set_stop(x1, x2, x3, x4, SMC_GET_GP(handle, CTX_GPREG_X5));
+		SMC_RET1(handle, ret);
+	case RMM_IDE_KM_PULL_RESPONSE: {
+		uint64_t req_resp = 0, req_id = 0, cookie_var = 0;
+
+		ret = rmmd_el3_ide_km_pull_response(x1, x2, &req_resp, &req_id, &cookie_var);
+		SMC_RET4(handle, ret, req_resp, req_id, cookie_var);
+	}
+#endif /* RMMD_ENABLE_IDE_KEY_PROG */
 	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 0ce104d..1fbcd31 100644
--- a/services/std_svc/rmmd/rmmd_private.h
+++ b/services/std_svc/rmmd/rmmd_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,6 +8,7 @@
 #define RMMD_PRIVATE_H
 
 #include <context.h>
+#include <services/rmmd_svc.h>
 
 /*******************************************************************************
  * Constants that allow assembler code to preserve callee-saved registers of the
@@ -54,6 +55,17 @@
 uint64_t rmmd_el3_token_sign(void *handle, uint64_t x1, uint64_t x2,
 				    uint64_t x3, uint64_t x4);
 
+/* Functions implementing IDE KM programming */
+int rmmd_el3_ide_key_program(uint64_t ecam_address, uint64_t rp_id,
+			     uint64_t ide_stream_info, rp_ide_key_info_t *ide_key_info_ptr,
+			     uint64_t request_id, uint64_t cookie);
+int rmmd_el3_ide_key_set_go(uint64_t ecam_address, uint64_t rp_id, uint64_t ide_stream_info,
+			    uint64_t request_id, uint64_t cookie);
+int rmmd_el3_ide_key_set_stop(uint64_t ecam_address, uint64_t rp_id, uint64_t ide_stream_info,
+			      uint64_t request_id, uint64_t cookie);
+int rmmd_el3_ide_km_pull_response(uint64_t ecam_address, uint64_t rp_id, uint64_t *req_resp,
+				  uint64_t *request_id, uint64_t *cookie_ptr);
+
 /* Assembly helpers */
 uint64_t rmmd_rmm_enter(uint64_t *c_rt_ctx);
 void __dead2 rmmd_rmm_exit(uint64_t c_rt_ctx, uint64_t ret);
diff --git a/services/std_svc/rmmd/trp/trp_entry.S b/services/std_svc/rmmd/trp/trp_entry.S
index 3e1d8c9..a2fd6a0 100644
--- a/services/std_svc/rmmd/trp/trp_entry.S
+++ b/services/std_svc/rmmd/trp/trp_entry.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,6 +21,8 @@
 	 * ---------------------------------------------
 	 */
 	.macro restore_args_call_smc
+	ldp	x10, x11, [x0, #TRP_ARG10]
+	ldp	x8, x9, [x0, #TRP_ARG8]
 	ldp	x6, x7, [x0, #TRP_ARG6]
 	ldp	x4, x5, [x0, #TRP_ARG4]
 	ldp	x2, x3, [x0, #TRP_ARG2]
diff --git a/services/std_svc/rmmd/trp/trp_helpers.c b/services/std_svc/rmmd/trp/trp_helpers.c
index 159f3a5..0607864 100644
--- a/services/std_svc/rmmd/trp/trp_helpers.c
+++ b/services/std_svc/rmmd/trp/trp_helpers.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -25,7 +25,11 @@
 			uint64_t arg4,
 			uint64_t arg5,
 			uint64_t arg6,
-			uint64_t arg7)
+			uint64_t arg7,
+			uint64_t arg8,
+			uint64_t arg9,
+			uint64_t arg10,
+			uint64_t arg11)
 {
 	uint32_t linear_id;
 	trp_args_t *pcpu_smc_args;
@@ -44,6 +48,10 @@
 	write_trp_arg(pcpu_smc_args, TRP_ARG5, arg5);
 	write_trp_arg(pcpu_smc_args, TRP_ARG6, arg6);
 	write_trp_arg(pcpu_smc_args, TRP_ARG7, arg7);
+	write_trp_arg(pcpu_smc_args, TRP_ARG8, arg8);
+	write_trp_arg(pcpu_smc_args, TRP_ARG9, arg9);
+	write_trp_arg(pcpu_smc_args, TRP_ARG10, arg10);
+	write_trp_arg(pcpu_smc_args, TRP_ARG11, arg11);
 
 	return pcpu_smc_args;
 }
@@ -53,6 +61,6 @@
  */
 __dead2 void trp_boot_abort(uint64_t err)
 {
-	(void)trp_smc(set_smc_args(RMM_BOOT_COMPLETE, err, 0, 0, 0, 0, 0, 0));
+	(void)trp_smc(set_smc_args(RMM_BOOT_COMPLETE, err, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
 	panic();
 }
diff --git a/services/std_svc/rmmd/trp/trp_main.c b/services/std_svc/rmmd/trp/trp_main.c
index b75483c..a82966e 100644
--- a/services/std_svc/rmmd/trp/trp_main.c
+++ b/services/std_svc/rmmd/trp/trp_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,6 +15,27 @@
 
 #include <platform_def.h>
 
+#define RMI_ERROR_REALM			2U
+#define RMI_ERROR_NOT_SUPPORTED		6U
+
+#define DIR_BIT_SHIFT			0x8
+#define KEYSET_SHIFT			0xC
+#define	STREAM_ID_MASK			0xFF
+#define STREAM_ID_SHIFT			0x0
+#define SUBSTREAM_MASK			0x7
+#define SUBSTREAM_SHIFT			0x8
+
+#define KEY_SET				0x0
+#define	DIR_VAL				0x0
+#define	SUBSTREAM_VAL			0x1
+#define	STREAM_ID			0x1
+
+#define ENCODE_STREAM_INFO(key, dir, substream, stream_id)			\
+		(((key & 0x1) << KEYSET_SHIFT) |				\
+		((dir & 0x1) << DIR_BIT_SHIFT) |				\
+		((substream && SUBSTREAM_MASK) << SUBSTREAM_SHIFT) |		\
+		((stream_id && STREAM_ID_MASK) << STREAM_ID_SHIFT))
+
 /* Parameters received from the previous image */
 static unsigned int trp_boot_abi_version;
 static uintptr_t trp_shared_region_start;
@@ -129,7 +150,7 @@
 {
 	VERBOSE("Delegating granule 0x%llx\n", x1);
 	smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_DELEGATE, x1,
-						0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
+				0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
 
 	if (smc_ret->x[0] != 0ULL) {
 		ERROR("Granule transition from NON-SECURE type to REALM type "
@@ -145,7 +166,7 @@
 {
 	VERBOSE("Undelegating granule 0x%llx\n", x1);
 	smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_UNDELEGATE, x1,
-						0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
+				0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
 
 	if (smc_ret->x[0] != 0ULL) {
 		ERROR("Granule transition from REALM type to NON-SECURE type "
@@ -154,6 +175,62 @@
 }
 
 /*******************************************************************************
+ * Test the IDE Key management interface
+ ******************************************************************************/
+static void trp_ide_keymgmt_interface_fn(unsigned long long x1, unsigned long long x2,
+					struct trp_smc_result *smc_ret)
+{
+	uint64_t ecam_address = 0U, rp_id = 0U, ide_stream_info;
+	uint64_t keyqw0, keyqw1, keyqw2, keyqw3;
+	uint64_t ifvqw0, ifvqw1;
+	int return_value;
+
+#if RMMD_ENABLE_IDE_KEY_PROG
+	trp_get_test_rootport(&ecam_address, &rp_id);
+#endif /* RMMD_ENABLE_IDE_KEY_PROG */
+	/*
+	 * Dummy values for testing:
+	 * Key set = 0x0
+	 * Dir = 0x0
+	 * Substream = 0x1
+	 * Stream ID = 0x1
+	 */
+	ide_stream_info  = ENCODE_STREAM_INFO(KEY_SET, DIR_VAL, SUBSTREAM_VAL, STREAM_ID);
+
+	/* Dummy key and IV values for testing */
+	keyqw0 = 0xA1B2C3D4E5F60708;
+	keyqw1 = 0x1122334455667788;
+	keyqw2 = 0xDEADBEEFCAFEBABE;
+	keyqw3 = 0x1234567890ABCDEF;
+	ifvqw0 = 0xABCDEF0123456789;
+	ifvqw1 = 0x9876543210FEDCBA;
+
+	return_value = trp_smc(set_smc_args(RMM_IDE_KEY_PROG, ecam_address, rp_id,
+				ide_stream_info, keyqw0, keyqw1, keyqw2, keyqw3, ifvqw0,
+				ifvqw1, 0UL, 0UL));
+
+	INFO("return value from RMM_IDE_KEY_PROG = %d\n", return_value);
+
+	return_value = trp_smc(set_smc_args(RMM_IDE_KEY_SET_GO, ecam_address, rp_id,
+				ide_stream_info, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
+
+	INFO("return value from RMM_IDE_KEY_SET_GO = %d\n", return_value);
+
+	return_value = trp_smc(set_smc_args(RMM_IDE_KEY_SET_STOP, ecam_address, rp_id,
+				ide_stream_info, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
+
+	INFO("return value from RMM_IDE_KEY_SET_STOP = %d\n", return_value);
+
+	return_value = trp_smc(set_smc_args(RMM_IDE_KM_PULL_RESPONSE, ecam_address, rp_id,
+				0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
+
+	INFO("return value from RMM_IDE_KEY_SET_STOP = %d\n", return_value);
+
+	smc_ret->x[0] = RMI_ERROR_NOT_SUPPORTED;
+
+}
+
+/*******************************************************************************
  * Main RMI SMC handler function
  ******************************************************************************/
 void trp_rmi_handler(unsigned long fid,
@@ -179,6 +256,9 @@
 	case RMI_RMM_GRANULE_UNDELEGATE:
 		trp_asc_mark_nonsecure(x1, smc_ret);
 		break;
+	case RMI_RMM_PDEV_CREATE:
+		trp_ide_keymgmt_interface_fn(x1, x2, smc_ret);
+		break;
 	default:
 		ERROR("Invalid SMC code to %s, FID %lx\n", __func__, fid);
 		smc_ret->x[0] = SMC_UNK;
diff --git a/services/std_svc/rmmd/trp/trp_private.h b/services/std_svc/rmmd/trp/trp_private.h
index d8c6960..16edc5e 100644
--- a/services/std_svc/rmmd/trp/trp_private.h
+++ b/services/std_svc/rmmd/trp/trp_private.h
@@ -28,6 +28,7 @@
 #define RMI_RMM_REQ_VERSION		SMC64_RMI_FID(U(0))
 #define RMI_RMM_GRANULE_DELEGATE	SMC64_RMI_FID(U(1))
 #define RMI_RMM_GRANULE_UNDELEGATE	SMC64_RMI_FID(U(2))
+#define RMI_RMM_PDEV_CREATE		SMC64_RMI_FID(U(0x26))
 
 /* Definitions for RMI VERSION */
 #define RMI_ABI_VERSION_MAJOR		U(0x0)
diff --git a/services/std_svc/spm/spm_mm/spm_mm_main.c b/services/std_svc/spm/spm_mm/spm_mm_main.c
index 34e2c00..7fe826d 100644
--- a/services/std_svc/spm/spm_mm/spm_mm_main.c
+++ b/services/std_svc/spm/spm_mm/spm_mm_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -34,53 +34,19 @@
 /*******************************************************************************
  * Set state of a Secure Partition context.
  ******************************************************************************/
-void sp_state_set(sp_context_t *sp_ptr, sp_state_t state)
+static void sp_state_set(sp_context_t *sp_ptr, sp_state_t state)
 {
-	spin_lock(&(sp_ptr->state_lock));
 	sp_ptr->state = state;
 	spin_unlock(&(sp_ptr->state_lock));
 }
 
 /*******************************************************************************
- * Wait until the state of a Secure Partition is the specified one and change it
- * to the desired state.
- ******************************************************************************/
-void sp_state_wait_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to)
-{
-	int success = 0;
-
-	while (success == 0) {
-		spin_lock(&(sp_ptr->state_lock));
-
-		if (sp_ptr->state == from) {
-			sp_ptr->state = to;
-
-			success = 1;
-		}
-
-		spin_unlock(&(sp_ptr->state_lock));
-	}
-}
-
-/*******************************************************************************
- * Check if the state of a Secure Partition is the specified one and, if so,
- * change it to the desired state. Returns 0 on success, -1 on error.
+ * Change the state of a Secure Partition to the one specified.
  ******************************************************************************/
-int sp_state_try_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to)
+static void sp_state_wait_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to)
 {
-	int ret = -1;
-
 	spin_lock(&(sp_ptr->state_lock));
-
-	if (sp_ptr->state == from) {
-		sp_ptr->state = to;
-
-		ret = 0;
-	}
-
-	spin_unlock(&(sp_ptr->state_lock));
-
-	return ret;
+	sp_ptr->state = to;
 }
 
 /*******************************************************************************