Merge "build(handoff)!: switch to LibTL submodule" into integration
diff --git a/Makefile b/Makefile
index 2d85b72..88c7b69 100644
--- a/Makefile
+++ b/Makefile
@@ -1114,6 +1114,10 @@
         $(info DICE_PROTECTION_ENVIRONMENT is an experimental feature)
 endif
 
+ifeq (${LFA_SUPPORT},1)
+        $(warning LFA_SUPPORT is an experimental feature)
+endif #(LFA_SUPPORT)
+
 ################################################################################
 # Process platform overrideable behaviour
 ################################################################################
@@ -1315,6 +1319,7 @@
 	EARLY_CONSOLE \
 	PRESERVE_DSU_PMU_REGS \
 	HOB_LIST \
+	LFA_SUPPORT \
 )))
 
 # Numeric_Flags
@@ -1545,6 +1550,7 @@
 	EARLY_CONSOLE \
 	PRESERVE_DSU_PMU_REGS \
 	HOB_LIST \
+	LFA_SUPPORT \
 )))
 
 ifeq (${PLATFORM_REPORT_CTX_MEM_USE}, 1)
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index e390915..d267b11 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -164,6 +164,10 @@
 				${RMMD_SOURCES}
 endif
 
+ifeq (${USE_DSU_DRIVER},1)
+BL31_SOURCES		+=	drivers/arm/dsu/dsu.c
+endif
+
 ifeq ($(FEATURE_DETECTION),1)
 BL31_SOURCES		+=	common/feat_detect.c
 endif
@@ -177,6 +181,11 @@
 				${MBEDTLS_SOURCES}
 endif
 
+ifeq (${LFA_SUPPORT},1)
+include services/std_svc/lfa/lfa.mk
+BL31_SOURCES		+=	${LFA_SOURCES}
+endif
+
 ifeq ($(CROS_WIDEVINE_SMC),1)
 BL31_SOURCES		+=	services/oem/chromeos/widevine_smc_handlers.c
 endif
@@ -200,11 +209,13 @@
 	CRASH_REPORTING \
 	EL3_EXCEPTION_HANDLING \
 	SDEI_SUPPORT \
+	USE_DSU_DRIVER \
 )))
 
 $(eval $(call add_defines,\
     $(sort \
-        CRASH_REPORTING \
-        EL3_EXCEPTION_HANDLING \
-        SDEI_SUPPORT \
+	CRASH_REPORTING \
+	EL3_EXCEPTION_HANDLING \
+	SDEI_SUPPORT \
+	USE_DSU_DRIVER \
 )))
diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c
index a9f89fc..ba26366 100644
--- a/bl31/bl31_main.c
+++ b/bl31/bl31_main.c
@@ -17,6 +17,7 @@
 #include <common/debug.h>
 #include <common/feat_detect.h>
 #include <common/runtime_svc.h>
+#include <drivers/arm/dsu.h>
 #include <drivers/arm/gic.h>
 #include <drivers/console.h>
 #include <lib/bootmarker_capture.h>
@@ -56,7 +57,7 @@
  * Variable to indicate whether next image to execute after BL31 is BL33
  * (non-secure & default) or BL32 (secure).
  ******************************************************************************/
-static uint32_t next_image_type = NON_SECURE;
+static uint32_t next_image_type = (uint32_t)NON_SECURE;
 
 #ifdef SUPPORT_UNKNOWN_MPID
 /*
@@ -146,6 +147,10 @@
 	/* Perform platform setup in BL31 */
 	bl31_platform_setup();
 
+#if USE_DSU_DRIVER
+	dsu_driver_init(&plat_dsu_data);
+#endif
+
 #if USE_GIC_DRIVER
 	/*
 	 * Initialize the GIC driver as well as per-cpu and global interfaces.
diff --git a/changelog.yaml b/changelog.yaml
index 5a8ca1e..e0a4f42 100644
--- a/changelog.yaml
+++ b/changelog.yaml
@@ -775,6 +775,9 @@
       - title: ChromeOS
         scope: cros
 
+      - title: Live Firmware Activation
+        scope: lfa
+
       - title: Secure Payload Dispatcher
         scope: spd
 
diff --git a/common/tf_log.c b/common/tf_log.c
index bef1739..f678975 100644
--- a/common/tf_log.c
+++ b/common/tf_log.c
@@ -12,7 +12,7 @@
 #include <plat/common/platform.h>
 
 /* Set the default maximum log level to the `LOG_LEVEL` build flag */
-static unsigned int max_log_level = LOG_LEVEL;
+static uint32_t max_log_level = LOG_LEVEL;
 
 /*
  * The common log function which is invoked by TF-A code.
@@ -23,12 +23,12 @@
  */
 void tf_log(const char *fmt, ...)
 {
-	unsigned int log_level;
+	uint32_t log_level;
 	va_list args;
 	const char *prefix_str;
 
 	/* We expect the LOG_MARKER_* macro as the first character */
-	log_level = fmt[0];
+	log_level = (uint32_t)fmt[0];
 
 	/* Verify that log_level is one of LOG_MARKER_* macro defined in debug.h */
 	assert((log_level > 0U) && (log_level <= LOG_LEVEL_VERBOSE));
@@ -40,7 +40,7 @@
 	prefix_str = plat_log_get_prefix(log_level);
 
 	while (*prefix_str != '\0') {
-		(void)putchar(*prefix_str);
+		(void)putchar((int)*prefix_str);
 		prefix_str++;
 	}
 
@@ -51,7 +51,7 @@
 
 void tf_log_newline(const char log_fmt[2])
 {
-	unsigned int log_level = log_fmt[0];
+	uint32_t log_level = (uint32_t)log_fmt[0];
 
 	/* Verify that log_level is one of LOG_MARKER_* macro defined in debug.h */
 	assert((log_level > 0U) && (log_level <= LOG_LEVEL_VERBOSE));
@@ -69,12 +69,12 @@
  * maximum log level is determined by `LOG_LEVEL` build flag at compile time
  * and this helper can set a lower (or equal) log level than the one at compile.
  */
-void tf_log_set_max_level(unsigned int log_level)
+void tf_log_set_max_level(uint32_t log_level)
 {
 	assert(log_level <= LOG_LEVEL_VERBOSE);
 	assert((log_level % 10U) == 0U);
 
 	/* Cap log_level to the compile time maximum. */
-	if (log_level <= (unsigned int)LOG_LEVEL)
+	if (log_level <= (uint32_t)LOG_LEVEL)
 		max_log_level = log_level;
 }
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index 10b5c16..569f932 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -507,6 +507,14 @@
 :|F|: include/services/arm_arch_svc.h
 :|F|: include/services/std_svc.h
 
+Live Firmware Activation Service
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:|M|: Manish Badarkhe <manish.badarkhe@arm.com>
+:|G|: `ManishVB-Arm`_
+:|F|: services/std_svc/lfa
+:|F|: include/plat/common/plat_lfa.h
+:|F|: include/services/lfa_svc.h
+
 Platform Ports
 ~~~~~~~~~~~~~~
 
diff --git a/docs/design/firmware-design.rst b/docs/design/firmware-design.rst
index 1306ecb..669bd96 100644
--- a/docs/design/firmware-design.rst
+++ b/docs/design/firmware-design.rst
@@ -1056,6 +1056,18 @@
 integrating PSCI library with AArch32 EL3 Runtime Software can be found
 at :ref:`PSCI Library Integration guide for Armv8-A AArch32 systems`.
 
+DSU driver
+----------
+
+Platforms that include a DSU (DynamIQ Shared Unit) can define
+the ``USE_DSU_DRIVER`` build flag to enable the DSU driver.
+This driver is responsible for configuring DSU-related powerdown
+and power feature settings using ``dsu_driver_init()`` and for
+preserving the context of DSU PMU system registers.
+
+To support the DSU driver, platforms must define the ``plat_dsu_data``
+structure.
+
 .. _firmware_design_sel1_spd:
 
 Secure-EL1 Payloads and Dispatchers
diff --git a/docs/design/interrupt-framework-design.rst b/docs/design/interrupt-framework-design.rst
index dfb2eac..515cf5e 100644
--- a/docs/design/interrupt-framework-design.rst
+++ b/docs/design/interrupt-framework-design.rst
@@ -649,7 +649,7 @@
 
    .. code:: c
 
-       uint32_t plat_ic_get_interrupt_type(void);
+       uint32_t plat_ic_get_pending_interrupt_type(void);
 
    It should return either ``INTR_TYPE_S_EL1`` or ``INTR_TYPE_NS``.
 
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index e80f3d1..f99840b 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -1119,6 +1119,11 @@
    (Coherent memory region is included) or 0 (Coherent memory region is
    excluded). Default is 1.
 
+-  ``USE_DSU_DRIVER``: This flag enables DSU (DynamIQ Shared Unit) driver.
+   The DSU driver allows save/restore of DSU PMU registers through
+   ``PRESERVE_DSU_PMU_REGS`` build option and allows platforms to
+   configure powerdown and power settings of DSU.
+
 -  ``ARM_IO_IN_DTB``: This flag determines whether to use IO based on the
    firmware configuration framework. This will move the io_policies into a
    configuration device tree, instead of static structure in the code base.
@@ -1497,6 +1502,9 @@
    per the `PSA Crypto API specification`_. This feature is only supported if
    using MbedTLS 3.x version. It is disabled (``0``) by default.
 
+-  ``LFA_SUPPORT``: Boolean flag to enable support for Live Firmware
+   activation as per the specification. This option defaults to 0.
+
 -  ``TRANSFER_LIST``: Setting this to ``1`` enables support for Firmware
    Handoff using Transfer List defined in `Firmware Handoff specification`_.
    This defaults to ``0``. Current implementation follows the Firmware Handoff
diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst
index 7e40e47..4157659 100644
--- a/docs/porting-guide.rst
+++ b/docs/porting-guide.rst
@@ -3928,6 +3928,58 @@
 Enabling the MEASURED_BOOT flag adds extra platform requirements. Please refer
 to :ref:`Measured Boot Design` for more details.
 
+Live Firmware Activation Interface
+----------------------------------
+
+Function : plat_lfa_get_components()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : plat_lfa_component_info_t **
+    Return   : int
+
+This platform API provides the list of LFA components available for activation.
+It populates a pointer to an array of ``plat_lfa_component_info_t`` structures,
+which contain information about each component (like UUID, ID, etc.). It returns
+0 on success, or a standard error code on failure.
+
+Function : is_plat_lfa_activation_pending()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : uint32_t
+    Return   : bool
+
+This platform API checks if the specified LFA component, identified
+by its ``lfa_component_id``, is available for activation. It returns
+true if available, otherwise false.
+
+Function : plat_lfa_cancel()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : uint32_t
+    Return   : int
+
+This platform API allows the platform to cancel an ongoing update or activation
+process for the specified ``lfa_component_id``. It returns 0 on success or
+a standard error code on failure.
+
+Function : plat_lfa_load_auth_image()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+    Argument : uint32_t
+    Return   : int
+
+The platform uses this API to load, authenticate and measure the component
+specified by ``lfa_component_id``. It should return 0 on success or appropriate
+error codes for load/authentication failures.
+
 --------------
 
 *Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.*
diff --git a/drivers/arm/css/dsu/dsu.c b/drivers/arm/dsu/dsu.c
similarity index 83%
rename from drivers/arm/css/dsu/dsu.c
rename to drivers/arm/dsu/dsu.c
index f0e8df1..dea89c5 100644
--- a/drivers/arm/css/dsu/dsu.c
+++ b/drivers/arm/dsu/dsu.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024, Arm Limited. All rights reserved.
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -10,7 +10,9 @@
 #include <arch_helpers.h>
 #include <common/bl_common.h>
 #include <common/debug.h>
-#include <drivers/arm/css/dsu.h>
+#include <drivers/arm/dsu.h>
+#include <dsu_def.h>
+#include <lib/utils_def.h>
 
 #include <plat/arm/common/plat_arm.h>
 #include <plat/common/platform.h>
@@ -133,3 +135,30 @@
 	restore_dsu_pmu_state(&cluster_pmu_context[cluster_pos]);
 }
 
+void dsu_driver_init(const dsu_driver_data_t *plat_driver_data)
+{
+	uint64_t actlr_el3 = read_actlr_el3();
+	uint64_t pwrctlr = read_clusterpwrctlr_el1();
+	uint64_t pwrdn = read_clusterpwrdn_el1();
+
+	/* enable access to power control registers. */
+	actlr_el3 |= ACTLR_EL3_PWREN_BIT;
+	write_actlr_el3(actlr_el3);
+
+	UPDATE_REG_FIELD(CLUSTERPWRCTLR_FUNCRET, pwrctlr,
+			plat_driver_data->clusterpwrctlr_funcret);
+
+	UPDATE_REG_FIELD(CLUSTERPWRCTLR_CACHEPWR, pwrctlr,
+			plat_driver_data->clusterpwrctlr_cachepwr);
+
+	write_clusterpwrctlr_el1(pwrctlr);
+
+	UPDATE_REG_FIELD(CLUSTERPWRDN_PWRDN, pwrdn,
+			plat_driver_data->clusterpwrdwn_pwrdn);
+
+	UPDATE_REG_FIELD(CLUSTERPWRDN_MEMRET, pwrdn,
+			plat_driver_data->clusterpwrdwn_memret);
+
+	write_clusterpwrdn_el1(pwrdn);
+}
+
diff --git a/drivers/arm/gic/v2/gicdv2_helpers.c b/drivers/arm/gic/v2/gicdv2_helpers.c
index 2f3f7f8..464bb34 100644
--- a/drivers/arm/gic/v2/gicdv2_helpers.c
+++ b/drivers/arm/gic/v2/gicdv2_helpers.c
@@ -320,7 +320,7 @@
 
 void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
 {
-	uint8_t val = pri & GIC_PRI_MASK;
+	uint8_t val = (uint8_t)(pri & GIC_PRI_MASK);
 
 	mmio_write_8(base + GICD_IPRIORITYR + id, val);
 }
diff --git a/drivers/imx/usdhc/imx_usdhc.c b/drivers/imx/usdhc/imx_usdhc.c
index f6a27dc..30caeba 100644
--- a/drivers/imx/usdhc/imx_usdhc.c
+++ b/drivers/imx/usdhc/imx_usdhc.c
@@ -227,6 +227,8 @@
 		*xfertype |= XFERTYPE_CICEN;
 		*xfertype |= XFERTYPE_CCCEN;
 		break;
+	case MMC_RESPONSE_NONE:
+		break;
 	default:
 		ERROR("Invalid CMD response: %u\n", cmd->resp_type);
 		return -EINVAL;
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index b51e744..93a958c 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -437,7 +437,7 @@
 	int ret;
 
 	/* CMD0: reset to IDLE */
-	ret = mmc_send_cmd(MMC_CMD(0), 0, 0, NULL);
+	ret = mmc_send_cmd(MMC_CMD(0), 0, MMC_RESPONSE_NONE, NULL);
 	if (ret != 0) {
 		return ret;
 	}
diff --git a/drivers/nxp/crypto/caam/src/hw_key_blob.c b/drivers/nxp/crypto/caam/src/hw_key_blob.c
index 6bcb6ba..0ac750d 100644
--- a/drivers/nxp/crypto/caam/src/hw_key_blob.c
+++ b/drivers/nxp/crypto/caam/src/hw_key_blob.c
@@ -43,6 +43,10 @@
 	struct job_descriptor *jobdesc = &desc;
 	uint32_t in_sz = 16U;
 
+	if (size <= 0 ||  size > 16) {
+		ERROR("Error: Requested invalid length of HUK.\n");
+		return -1;
+	}
 	/* Output blob will have 32 bytes key blob in beginning and
 	 * 16 byte HMAC identifier at end of data blob
 	 */
diff --git a/drivers/nxp/crypto/caam/src/rng.c b/drivers/nxp/crypto/caam/src/rng.c
index 58430db..0331040 100644
--- a/drivers/nxp/crypto/caam/src/rng.c
+++ b/drivers/nxp/crypto/caam/src/rng.c
@@ -41,7 +41,7 @@
 	if (rdsta & RNG_STATE0_HANDLE_INSTANTIATED) {
 		*state_handle = 0;
 		ret_code = 1;
-	} else if (rdsta & RNG_STATE0_HANDLE_INSTANTIATED) {
+	} else if (rdsta & RNG_STATE1_HANDLE_INSTANTIATED) {
 		*state_handle = 1;
 		ret_code = 1;
 	}
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index b607945..5506cb1 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -1576,7 +1576,7 @@
 /*******************************************************************************
  * Definitions for DynamicIQ Shared Unit registers
  ******************************************************************************/
-#define CLUSTERPWRDN_EL1	S3_0_c15_c3_6
+#define CLUSTERPWRDN_EL1	S3_0_C15_C3_6
 
 /*******************************************************************************
  * FEAT_FPMR - Floating point Mode Register
diff --git a/include/common/debug.h b/include/common/debug.h
index 0ddb400..6d7f2c6 100644
--- a/include/common/debug.h
+++ b/include/common/debug.h
@@ -32,6 +32,7 @@
 #include <cdefs.h>
 #include <stdarg.h>
 #include <stdbool.h>
+#include <stdint.h>
 #include <stdio.h>
 
 #include <drivers/console.h>
@@ -135,7 +136,7 @@
 
 void tf_log(const char *fmt, ...) __printflike(1, 2);
 void tf_log_newline(const char log_fmt[2]);
-void tf_log_set_max_level(unsigned int log_level);
+void tf_log_set_max_level(uint32_t log_level);
 
 #endif /* __ASSEMBLER__ */
 #endif /* DEBUG_H */
diff --git a/include/drivers/arm/css/dsu.h b/include/drivers/arm/css/dsu.h
deleted file mode 100644
index 4d7822b..0000000
--- a/include/drivers/arm/css/dsu.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef DSU_H
-#define DSU_H
-
-#define PMCR_N_MAX			0x1f
-
-#define save_pmu_reg(state, reg) state->reg = read_##reg()
-
-#define restore_pmu_reg(context, reg) write_##reg(context->reg)
-
-typedef struct cluster_pmu_state{
-	uint64_t clusterpmcr;
-	uint64_t clusterpmcntenset;
-	uint64_t clusterpmccntr;
-	uint64_t clusterpmovsset;
-	uint64_t clusterpmselr;
-	uint64_t clusterpmsevtyper;
-	uint64_t counter_val[PMCR_N_MAX];
-	uint64_t counter_type[PMCR_N_MAX];
-} cluster_pmu_state_t;
-
-static inline unsigned int read_cluster_eventctr_num(void)
-{
-	return ((read_clusterpmcr() >> CLUSTERPMCR_N_SHIFT) &
-			CLUSTERPMCR_N_MASK);
-}
-
-
-void save_dsu_pmu_state(cluster_pmu_state_t *cluster_pmu_context);
-
-void restore_dsu_pmu_state(cluster_pmu_state_t *cluster_pmu_context);
-
-void cluster_on_dsu_pmu_context_restore(void);
-
-void cluster_off_dsu_pmu_context_save(void);
-
-#endif /* DSU_H */
diff --git a/include/drivers/arm/dsu.h b/include/drivers/arm/dsu.h
new file mode 100644
index 0000000..492babd
--- /dev/null
+++ b/include/drivers/arm/dsu.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef DSU_H
+#define DSU_H
+
+#if defined(__aarch64__)
+#include <dsu_def.h>
+
+/*
+ * Power Control Registers enable bit of Auxilary Control register.
+ * ACTLR_EL3_PWREN_BIT definition is same among cores like Cortex-X925,
+ * Cortex-X4, Cortex-A520, Cortex-A725 that are used in a cluster
+ * with DSU.
+ */
+#define ACTLR_EL3_PWREN_BIT		BIT(7)
+
+#define PMCR_N_MAX			0x1f
+
+#define save_pmu_reg(state, reg) state->reg = read_##reg()
+
+#define restore_pmu_reg(context, reg) write_##reg(context->reg)
+
+typedef struct cluster_pmu_state {
+	uint64_t clusterpmcr;
+	uint64_t clusterpmcntenset;
+	uint64_t clusterpmccntr;
+	uint64_t clusterpmovsset;
+	uint64_t clusterpmselr;
+	uint64_t clusterpmsevtyper;
+	uint64_t counter_val[PMCR_N_MAX];
+	uint64_t counter_type[PMCR_N_MAX];
+} cluster_pmu_state_t;
+
+typedef struct dsu_driver_data {
+	uint8_t clusterpwrdwn_pwrdn;
+	uint8_t clusterpwrdwn_memret;
+	uint8_t clusterpwrctlr_cachepwr;
+	uint8_t clusterpwrctlr_funcret;
+} dsu_driver_data_t;
+
+extern const dsu_driver_data_t plat_dsu_data;
+
+static inline unsigned int read_cluster_eventctr_num(void)
+{
+	return ((read_clusterpmcr() >> CLUSTERPMCR_N_SHIFT) &
+			CLUSTERPMCR_N_MASK);
+}
+
+void save_dsu_pmu_state(cluster_pmu_state_t *cluster_pmu_context);
+
+void restore_dsu_pmu_state(cluster_pmu_state_t *cluster_pmu_context);
+
+void cluster_on_dsu_pmu_context_restore(void);
+
+void cluster_off_dsu_pmu_context_save(void);
+
+void dsu_driver_init(const dsu_driver_data_t *data);
+#endif
+#endif /* DSU_H */
diff --git a/include/drivers/cadence/cdns_sdmmc.h b/include/drivers/cadence/cdns_sdmmc.h
index f8d616f..895a705 100644
--- a/include/drivers/cadence/cdns_sdmmc.h
+++ b/include/drivers/cadence/cdns_sdmmc.h
@@ -342,7 +342,6 @@
 /* MMC Peripheral Definition */
 #define SOCFPGA_MMC_BLOCK_MASK			(SOCFPGA_MMC_BLOCK_SIZE - U(1))
 #define SOCFPGA_MMC_BOOT_CLK_RATE		(400 * 1000)
-#define MMC_RESPONSE_NONE			0
 #define SDHC_CDNS_SRS03_VALUE			0x01020013
 
 /* Value randomly chosen for eMMC RCA, it should be > 1 */
diff --git a/include/drivers/mmc.h b/include/drivers/mmc.h
index 454a85a..55ed35c 100644
--- a/include/drivers/mmc.h
+++ b/include/drivers/mmc.h
@@ -52,6 +52,7 @@
 #define MMC_RESPONSE_R5			(MMC_RSP_48 | MMC_RSP_CRC | MMC_RSP_CMD_IDX)
 #define MMC_RESPONSE_R6			(MMC_RSP_48 | MMC_RSP_CRC | MMC_RSP_CMD_IDX)
 #define MMC_RESPONSE_R7			(MMC_RSP_48 | MMC_RSP_CRC | MMC_RSP_CMD_IDX)
+#define MMC_RESPONSE_NONE		0U
 
 /* Value randomly chosen for eMMC RCA, it should be > 1 */
 #define MMC_FIX_RCA			6
diff --git a/include/drivers/nxp/crypto/caam/sec_hw_specific.h b/include/drivers/nxp/crypto/caam/sec_hw_specific.h
index bc11aca..02bd4d0 100644
--- a/include/drivers/nxp/crypto/caam/sec_hw_specific.h
+++ b/include/drivers/nxp/crypto/caam/sec_hw_specific.h
@@ -123,6 +123,7 @@
 
  /* RNG RDSTA bitmask */
 #define RNG_STATE0_HANDLE_INSTANTIATED	0x00000001
+#define RNG_STATE1_HANDLE_INSTANTIATED	0x00000002
 #define RTMCTL_PRGM 0x00010000	/* 1 -> program mode, 0 -> run mode */
  /* use von Neumann data in both entropy shifter and statistical checker */
 #define RTMCTL_SAMP_MODE_VON_NEUMANN_ES_SC	 0
diff --git a/include/lib/cpus/aarch64/dsu_def.h b/include/lib/cpus/aarch64/dsu_def.h
index 3f6dbfe..089ea52 100644
--- a/include/lib/cpus/aarch64/dsu_def.h
+++ b/include/lib/cpus/aarch64/dsu_def.h
@@ -32,13 +32,27 @@
  * DSU Cluster Auxiliary Control registers definitions
  ********************************************************************/
 #define CLUSTERACTLR_EL1	S3_0_C15_C3_3
-#define CLUSTERPWRCTLR_EL1	S3_0_C15_C3_5
+
+/* CLUSTERPWRCTLR_EL1 register definitions */
+#define CLUSTERPWRCTLR_EL1		S3_0_C15_C3_5
+#define CLUSTERPWRCTLR_FUNCRET_WIDTH	U(3)
+#define CLUSTERPWRCTLR_FUNCRET_SHIFT	U(0)
+#define CLUSTERPWRCTLR_FUNCRET_RESET	U(0)
+#define CLUSTERPWRCTLR_CACHEPWR_WIDTH	U(4)
+#define CLUSTERPWRCTLR_CACHEPWR_SHIFT	U(4)
+#define CLUSTERPWRCTLR_CACHEPWR_RESET	U(7)
 
 #define CLUSTERACTLR_EL1_ASSERT_CBUSY			(ULL(1) << 8)
 #define CLUSTERACTLR_EL1_DISABLE_CLOCK_GATING		(ULL(1) << 15)
 #define CLUSTERACTLR_EL1_DISABLE_SCLK_GATING		(ULL(3) << 15)
 #define CLUSTERACTLR_EL1_IGNORE_INTERCONNECT_CBUSY	(ULL(3) << 20)
 
+/* CLUSTERPWRDN_EL1 register definitions */
+#define CLUSTERPWRDN_PWRDN_WIDTH	U(1)
+#define CLUSTERPWRDN_PWRDN_SHIFT	U(0)
+#define CLUSTERPWRDN_MEMRET_WIDTH	U(1)
+#define CLUSTERPWRDN_MEMRET_SHIFT	U(1)
+
 /********************************************************************
  * Masks applied for DSU errata workarounds
  ********************************************************************/
diff --git a/include/lib/libc/stdbool.h b/include/lib/libc/stdbool.h
index c2c9b22..30ced2a 100644
--- a/include/lib/libc/stdbool.h
+++ b/include/lib/libc/stdbool.h
@@ -9,8 +9,8 @@
 
 #define bool	_Bool
 
-#define true	(0 < 1)
-#define false	(0 > 1)
+#define true	(0 == 0)
+#define false	(0 == 1)
 
 #define __bool_true_false_are_defined	1
 
diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h
index 68e464a..7dcc5ce 100644
--- a/include/lib/utils_def.h
+++ b/include/lib/utils_def.h
@@ -86,6 +86,12 @@
 #define EXTRACT(regfield, reg) \
 	(((reg) & MASK(regfield)) >> (regfield##_SHIFT))
 
+#define UPDATE_REG_FIELD(regfield, reg, val) \
+	do { \
+		(reg) &= ~(MASK(regfield)); \
+		(reg) |= ((uint64_t)(val) << (regfield##_SHIFT)); \
+	} while (0)
+
 /*
  * This variant of div_round_up can be used in macro definition but should not
  * be used in C code as the `div` parameter is evaluated twice.
diff --git a/include/plat/common/plat_lfa.h b/include/plat/common/plat_lfa.h
new file mode 100644
index 0000000..fa7c2f9
--- /dev/null
+++ b/include/plat/common/plat_lfa.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLAT_LFA_H
+#define PLAT_LFA_H
+
+#include <services/lfa_component_desc.h>
+#include <tools_share/uuid.h>
+
+typedef struct plat_lfa_component_info {
+	const uint32_t lfa_component_id;
+	const uuid_t uuid;
+	struct lfa_component_ops *activator;
+	bool activation_pending;
+} plat_lfa_component_info_t;
+
+uint32_t plat_lfa_get_components(plat_lfa_component_info_t **components);
+bool is_plat_lfa_activation_pending(uint32_t lfa_component_id);
+int plat_lfa_cancel(uint32_t lfa_component_id);
+int plat_lfa_load_auth_image(uint32_t lfa_component_id);
+
+#endif /* PLAT_LFA_H */
diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h
index b9985a3..8c6ee98 100644
--- a/include/plat/common/platform.h
+++ b/include/plat/common/platform.h
@@ -24,6 +24,9 @@
 #if DRTM_SUPPORT
 #include "plat_drtm.h"
 #endif /* DRTM_SUPPORT */
+#if LFA_SUPPORT
+#include "plat_lfa.h"
+#endif /* LFA_SUPPORT */
 
 /*******************************************************************************
  * Forward declarations
diff --git a/include/services/bl31_lfa.h b/include/services/bl31_lfa.h
new file mode 100644
index 0000000..cfe436c
--- /dev/null
+++ b/include/services/bl31_lfa.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BL31_LFA_H
+#define BL31_LFA_H
+
+#include <services/lfa_component_desc.h>
+
+struct lfa_component_ops *get_bl31_activator(void);
+
+#endif /* BL31_LFA_H */
diff --git a/include/services/lfa_component_desc.h b/include/services/lfa_component_desc.h
new file mode 100644
index 0000000..5f198bd
--- /dev/null
+++ b/include/services/lfa_component_desc.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef LFA_COMPONENT_DESC_H
+#define LFA_COMPONENT_DESC_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+typedef enum {
+	PRIME_NONE = 0,
+	PRIME_STARTED,
+	PRIME_COMPLETE,
+} lfa_prime_status_t;
+
+struct lfa_component_status {
+	uint32_t component_id;
+	lfa_prime_status_t prime_status;
+	bool cpu_rendezvous_required;
+};
+
+typedef int32_t (*component_prime_fn)(struct lfa_component_status *activation);
+typedef int32_t (*component_activate_fn)(struct lfa_component_status *activation,
+					 uint64_t ep_address,
+					 uint64_t context_id);
+
+struct lfa_component_ops {
+	component_prime_fn prime;
+	component_activate_fn activate;
+	bool may_reset_cpu;
+	bool cpu_rendezvous_required;
+};
+
+#endif /* LFA_COMPONENT_DESC_H */
diff --git a/include/services/lfa_holding_pen.h b/include/services/lfa_holding_pen.h
new file mode 100644
index 0000000..9420747
--- /dev/null
+++ b/include/services/lfa_holding_pen.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef LFA_HOLDING_PEN_H
+#define LFA_HOLDING_PEN_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <services/lfa_svc.h>
+
+bool lfa_holding_start(void);
+enum lfa_retc lfa_holding_wait(void);
+void lfa_holding_release(enum lfa_retc status);
+
+#endif
diff --git a/include/services/lfa_svc.h b/include/services/lfa_svc.h
new file mode 100644
index 0000000..69d549c
--- /dev/null
+++ b/include/services/lfa_svc.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef LFA_SVC_H
+#define LFA_SVC_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <lib/smccc.h>
+#include <services/lfa_component_desc.h>
+#include <tools_share/uuid.h>
+
+/*
+ * SMC function IDs for LFA Service
+ * Upper word bits set: Fast call, SMC64, Standard Secure Svc. Call (OEN = 4)
+ */
+#define LFA_FID(func_num)				\
+	((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) |		\
+	(SMC_64 << FUNCID_CC_SHIFT) |			\
+	(OEN_STD_START << FUNCID_OEN_SHIFT) |		\
+	((func_num) << FUNCID_NUM_SHIFT))
+
+#define LFA_VERSION			LFA_FID(0x2E0)
+#define LFA_FEATURES			LFA_FID(0x2E1)
+#define LFA_GET_INFO			LFA_FID(0x2E2)
+#define LFA_GET_INVENTORY		LFA_FID(0x2E3)
+#define LFA_PRIME			LFA_FID(0x2E4)
+#define LFA_ACTIVATE			LFA_FID(0x2E5)
+#define LFA_CANCEL			LFA_FID(0x2E6)
+
+/* Check whether FID is in the range */
+#define is_lfa_fid(_fid)	\
+	((_fid >= LFA_VERSION) && (_fid <= LFA_CANCEL))
+
+/* LFA Service Calls version numbers */
+#define LFA_VERSION_MAJOR		U(1)
+#define LFA_VERSION_MAJOR_SHIFT		16
+#define LFA_VERSION_MAJOR_MASK		U(0x7FFF)
+#define LFA_VERSION_MINOR		U(0)
+#define LFA_VERSION_MINOR_SHIFT		0
+#define LFA_VERSION_MINOR_MASK		U(0xFFFF)
+
+#define LFA_VERSION_VAL						\
+	((((LFA_VERSION_MAJOR) & LFA_VERSION_MAJOR_MASK) <<	\
+	LFA_VERSION_MAJOR_SHIFT)				\
+	| (((LFA_VERSION_MINOR) & LFA_VERSION_MINOR_MASK) <<	\
+	LFA_VERSION_MINOR_SHIFT))
+
+#define LFA_INVALID_COMPONENT		U(0xFFFFFFFF)
+
+#define LFA_ACTIVATION_CAPABLE_SHIFT		0
+#define LFA_ACTIVATION_PENDING_SHIFT		1
+#define LFA_MAY_RESET_CPU_SHIFT			2
+#define LFA_CPU_RENDEZVOUS_OPTIONAL_SHIFT	3
+
+#define LFA_SKIP_CPU_RENDEZVOUS_BIT		BIT(0)
+
+/* List of errors as per the specification */
+enum lfa_retc {
+	LFA_SUCCESS			=  0,
+	LFA_NOT_SUPPORTED		= -1,
+	LFA_BUSY			= -2,
+	LFA_AUTH_ERROR			= -3,
+	LFA_NO_MEMORY			= -4,
+	LFA_CRITICAL_ERROR		= -5,
+	LFA_DEVICE_ERROR		= -6,
+	LFA_WRONG_STATE			= -7,
+	LFA_INVALID_PARAMETERS		= -8,
+	LFA_COMPONENT_WRONG_STATE	= -9,
+	LFA_INVALID_ADDRESS		= -10,
+	LFA_ACTIVATION_FAILED		= -11,
+};
+
+/* Initialization routine for the LFA service */
+int lfa_setup(void);
+
+uint64_t lfa_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2,
+			 u_register_t x3, u_register_t x4, void *cookie,
+			 void *handle, u_register_t flags);
+void lfa_reset_activation(void);
+
+#endif /* LFA_SVC_H */
diff --git a/include/services/rmmd_rmm_lfa.h b/include/services/rmmd_rmm_lfa.h
new file mode 100644
index 0000000..6720cb5
--- /dev/null
+++ b/include/services/rmmd_rmm_lfa.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RMMD_RMM_LFA_H
+#define RMMD_RMM_LFA_H
+
+#include <services/lfa_component_desc.h>
+
+struct lfa_component_ops *get_rmm_activator(void);
+
+#endif /* RMMD_RMM_LFA_H */
diff --git a/lib/psci/psci_main.c b/lib/psci/psci_main.c
index f126f49..dfec9a1 100644
--- a/lib/psci/psci_main.c
+++ b/lib/psci/psci_main.c
@@ -300,7 +300,7 @@
 	flush_cpu_data_by_index(target_idx,
 				psci_svc_cpu_data.aff_info_state);
 
-	return psci_get_aff_info_state_by_idx(target_idx);
+	return (int)psci_get_aff_info_state_by_idx(target_idx);
 }
 
 int psci_migrate(u_register_t target_cpu)
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 4ccca9f..b9df27e 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -435,3 +435,9 @@
 # This flag is temporary and it is expected once the interface is
 # finalized, this flag will be removed.
 RMMD_ENABLE_IDE_KEY_PROG	:= 0
+
+# Live firmware activation support
+LFA_SUPPORT			:= 0
+
+# Enable support for arm DSU driver.
+USE_DSU_DRIVER			:= 0
diff --git a/plat/arm/board/fvp/fvp_lfa.c b/plat/arm/board/fvp/fvp_lfa.c
new file mode 100644
index 0000000..3c5321d
--- /dev/null
+++ b/plat/arm/board/fvp/fvp_lfa.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+#include <plat/common/platform.h>
+#include <services/bl31_lfa.h>
+#include <services/rmmd_rmm_lfa.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <fvp_lfa_components.h>
+
+/* Keep this array consistent with enum fvp_lfa_component_id_t */
+static plat_lfa_component_info_t fvp_lfa_components[LFA_MAX_DEFINED_COMPONENTS] = {
+	[LFA_BL31_COMPONENT] = {LFA_BL31_COMPONENT, UUID_EL3_RUNTIME_FIRMWARE_BL31,
+				NULL, false},
+#if BL32_BASE
+	[LFA_BL32_COMPONENT] = {LFA_BL32_COMPONENT, UUID_SECURE_PAYLOAD_BL32,
+				NULL, false},
+#endif /* BL32_BASE */
+	[LFA_BL33_COMPONENT] = {LFA_BL33_COMPONENT, UUID_NON_TRUSTED_FIRMWARE_BL33,
+				NULL, false},
+#if ENABLE_RME
+	[LFA_RMM_COMPONENT]  = {LFA_RMM_COMPONENT, UUID_REALM_MONITOR_MGMT_FIRMWARE,
+				NULL, false},
+#endif /* ENABLE_RME */
+};
+
+uint32_t plat_lfa_get_components(plat_lfa_component_info_t **components)
+{
+	if (components == NULL) {
+		return -EINVAL;
+	}
+
+	fvp_lfa_components[LFA_BL31_COMPONENT].activator = get_bl31_activator();
+#if ENABLE_RME
+	fvp_lfa_components[LFA_RMM_COMPONENT].activator = get_rmm_activator();
+#endif /* ENABLE_RME */
+
+	*components = fvp_lfa_components;
+	return LFA_MAX_DEFINED_COMPONENTS;
+}
+
+bool is_plat_lfa_activation_pending(uint32_t lfa_component_id)
+{
+#if ENABLE_RME
+	if (lfa_component_id == LFA_RMM_COMPONENT) {
+		return true;
+	}
+#endif /* ENABLE_RME */
+
+	return false;
+}
+
+int plat_lfa_cancel(uint32_t lfa_component_id)
+{
+	/* placeholder function to do cancel LFA of given component */
+	return 0;
+}
+
+int plat_lfa_load_auth_image(uint32_t img_id)
+{
+	/*
+	 * In AEM FVP, we don't want to bloat the code by adding
+	 * loading and authentication mechanism, so here we assumed
+	 * that the components are pre-loaded and authenticated already.
+	 */
+	return 0;
+}
diff --git a/plat/arm/board/fvp/include/fvp_lfa_components.h b/plat/arm/board/fvp/include/fvp_lfa_components.h
new file mode 100644
index 0000000..09dcdfd
--- /dev/null
+++ b/plat/arm/board/fvp/include/fvp_lfa_components.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef FVP_LFA_COMPONENTS_H
+#define FVP_LFA_COMPONENTS_H
+
+/*
+ * Define platform-specific numeric IDs for LFA FVP components.
+ */
+typedef enum {
+	LFA_BL31_COMPONENT = 0,
+#if BL32_BASE
+	LFA_BL32_COMPONENT,
+#endif /* BL32_BASE */
+	LFA_BL33_COMPONENT,
+#if ENABLE_RME
+	LFA_RMM_COMPONENT,
+#endif /* ENABLE_RME */
+	LFA_MAX_DEFINED_COMPONENTS
+} fvp_lfa_component_id_t;
+
+#endif /* FVP_LFA_COMPONENTS_H */
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index ea1b7e7..7f1dfc6 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -591,3 +591,7 @@
 
 # Build macro necessary for running SPM tests on FVP platform
 $(eval $(call add_define,PLAT_TEST_SPM))
+
+ifeq (${LFA_SUPPORT},1)
+BL31_SOURCES            +=      plat/arm/board/fvp/fvp_lfa.c
+endif
diff --git a/plat/arm/board/tc/platform.mk b/plat/arm/board/tc/platform.mk
index b29f0d6..b7edf28 100644
--- a/plat/arm/board/tc/platform.mk
+++ b/plat/arm/board/tc/platform.mk
@@ -16,6 +16,7 @@
 HW_ASSISTED_COHERENCY		:=	1
 USE_COHERENT_MEM		:=	0
 USE_GIC_DRIVER			:=	3
+USE_DSU_DRIVER			:=	1
 GIC_ENABLE_V4_EXTN		:=      1
 GICV3_SUPPORT_GIC600		:=	1
 override NEED_BL2U		:=	no
@@ -162,7 +163,7 @@
 				${TC_BASE}/tc_topology.c	\
 				lib/fconf/fconf.c			\
 				lib/fconf/fconf_dyn_cfg_getter.c	\
-				drivers/arm/css/dsu/dsu.c			\
+				drivers/arm/dsu/dsu.c			\
 				drivers/cfi/v2m/v2m_flash.c		\
 				lib/utils/mem_region.c			\
 				plat/arm/common/arm_nor_psci_mem_protect.c	\
diff --git a/plat/arm/board/tc/tc_bl31_setup.c b/plat/arm/board/tc/tc_bl31_setup.c
index 7f2014b..073e487 100644
--- a/plat/arm/board/tc/tc_bl31_setup.c
+++ b/plat/arm/board/tc/tc_bl31_setup.c
@@ -14,6 +14,7 @@
 #include <common/debug.h>
 #include <drivers/arm/css/css_mhu_doorbell.h>
 #include <drivers/arm/css/scmi.h>
+#include <drivers/arm/dsu.h>
 #include <drivers/arm/sbsa.h>
 #include <lib/fconf/fconf.h>
 #include <lib/fconf/fconf_dyn_cfg_getter.h>
@@ -74,6 +75,13 @@
 #endif
 };
 
+const dsu_driver_data_t plat_dsu_data = {
+	.clusterpwrdwn_pwrdn = false,
+	.clusterpwrdwn_memret = false,
+	.clusterpwrctlr_cachepwr = CLUSTERPWRCTLR_CACHEPWR_RESET,
+	.clusterpwrctlr_funcret = CLUSTERPWRCTLR_FUNCRET_RESET
+};
+
 #if (TARGET_PLATFORM == 3) || (TARGET_PLATFORM == 4)
 static void enable_ns_mcn_pmu(void)
 {
diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c
index 18882d3..80da3d9 100644
--- a/plat/arm/css/common/css_pm.c
+++ b/plat/arm/css/common/css_pm.c
@@ -12,7 +12,7 @@
 #include <bl31/interrupt_mgmt.h>
 #include <common/debug.h>
 #include <drivers/arm/css/css_scp.h>
-#include <drivers/arm/css/dsu.h>
+#include <drivers/arm/dsu.h>
 #include <lib/cassert.h>
 #include <plat/arm/common/plat_arm.h>
 
diff --git a/plat/imx/imx8m/imx8mp/gpc.c b/plat/imx/imx8m/imx8mp/gpc.c
index a95eb36..5e2d9e4 100644
--- a/plat/imx/imx8m/imx8mp/gpc.c
+++ b/plat/imx/imx8m/imx8mp/gpc.c
@@ -268,23 +268,6 @@
 		/* set the PGC bit */
 		mmio_setbits_32(IMX_GPC_BASE + pwr_domain->pgc_offset, 0x1);
 
-		/*
-		 * leave the G1, G2, H1 power domain on until VPUMIX power off,
-		 * otherwise system will hang due to VPUMIX ACK
-		 */
-		if (domain_id == VPU_H1 || domain_id == VPU_G1 || domain_id == VPU_G2) {
-			return;
-		}
-
-		if (domain_id == VPUMIX) {
-			mmio_write_32(IMX_GPC_BASE + PU_PGC_DN_TRG, VPU_G1_PWR_REQ |
-				 VPU_G2_PWR_REQ | VPU_H1_PWR_REQ);
-
-			while (mmio_read_32(IMX_GPC_BASE + PU_PGC_DN_TRG) & (VPU_G1_PWR_REQ |
-					VPU_G2_PWR_REQ | VPU_H1_PWR_REQ))
-				;
-		}
-
 		/* power down the domain */
 		mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, pwr_domain->pwr_req);
 
diff --git a/plat/imx/imx8ulp/imx8ulp_psci.c b/plat/imx/imx8ulp/imx8ulp_psci.c
index 59af8be..e67d0b5 100644
--- a/plat/imx/imx8ulp/imx8ulp_psci.c
+++ b/plat/imx/imx8ulp/imx8ulp_psci.c
@@ -289,7 +289,9 @@
 		/* LDO1 should be power off in PD mode */
 		} else if (mode == PD_PWR_MODE) {
 			/* overwrite the buck3 voltage setting in active mode */
-			upower_pmic_i2c_read(0x22, &volt);
+			if (upower_pmic_i2c_read(0x22, &volt) != 0) {
+				panic();
+			}
 			pd_pmic_reg_cfgs[3].i2c_data = volt;
 			memcpy(&pwr_sys_cfg->ps_apd_pmic_reg_data_cfg, &pd_pmic_reg_cfgs,
 				 sizeof(ps_apd_pmic_reg_data_cfgs_t));
diff --git a/plat/mediatek/drivers/pmic/rules.mk b/plat/mediatek/drivers/pmic/rules.mk
index dc228ee..13ce658 100644
--- a/plat/mediatek/drivers/pmic/rules.mk
+++ b/plat/mediatek/drivers/pmic/rules.mk
@@ -9,8 +9,8 @@
 MODULE := pmic
 
 ifeq (${CONFIG_MTK_PMIC_SHUTDOWN_V2}, y)
-LOCAL_SRCS-y += ${LOCAL_DIR}/pmic_common_swap_api.c
-LOCAL_SRCS-y := ${LOCAL_DIR}/pmic_psc.c
+LOCAL_SRCS-y := ${LOCAL_DIR}/pmic_common_swap_api.c
+LOCAL_SRCS-y += ${LOCAL_DIR}/pmic_psc.c
 LOCAL_SRCS-${CONFIG_MTK_PMIC_LOWPOWER} += ${LOCAL_DIR}/${MTK_SOC}/pmic_lowpower_init.c
 LOCAL_SRCS-${CONFIG_MTK_PMIC_LOWPOWER} += ${LOCAL_DIR}/${MTK_SOC}/pmic_swap_api.c
 LOCAL_SRCS-${CONFIG_MTK_PMIC_SHUTDOWN_CFG} += ${LOCAL_DIR}/${MTK_SOC}/pmic_shutdown_cfg.c
diff --git a/plat/nxp/common/sip_svc/sip_svc.c b/plat/nxp/common/sip_svc/sip_svc.c
index 1c8668e..4eec0ac 100644
--- a/plat/nxp/common/sip_svc/sip_svc.c
+++ b/plat/nxp/common/sip_svc/sip_svc.c
@@ -100,7 +100,7 @@
 		}
 		/* break is not required as SMC_RETx return */
 	case SIP_SVC_HUK:
-		if (is_sec_enabled() == false) {
+		if (ns != 0 || is_sec_enabled() == false) {
 			NOTICE("SEC is disabled.\n");
 			SMC_RET1(handle, SMC_UNK);
 		}
diff --git a/plat/nxp/s32/s32g274ardb2/include/platform_def.h b/plat/nxp/s32/s32g274ardb2/include/platform_def.h
index cb16658..227c8e6 100644
--- a/plat/nxp/s32/s32g274ardb2/include/platform_def.h
+++ b/plat/nxp/s32/s32g274ardb2/include/platform_def.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2024 NXP
+ * Copyright 2024-2025 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -44,24 +44,34 @@
 #define BL33_BASE			UL(0x34500000)
 #define BL33_LIMIT			UL(0x345FF000)
 
+/* IO buffer used to copy images from storage */
+#define IO_BUFFER_BASE			BL33_LIMIT
+#define IO_BUFFER_SIZE			U(0x13000)
+
 #define PLAT_PHY_ADDR_SPACE_SIZE	(ULL(1) << 36)
 /* We'll be doing a 1:1 mapping anyway */
 #define PLAT_VIRT_ADDR_SPACE_SIZE	(ULL(1) << 36)
 
-#define MAX_MMAP_REGIONS		U(18)
-#define MAX_XLAT_TABLES			U(32)
+#define MAX_MMAP_REGIONS		U(21)
+#define MAX_XLAT_TABLES			U(33)
 
 /* Console settings */
 #define UART_BASE			UL(0x401C8000)
 #define UART_BAUDRATE			U(115200)
 #define UART_CLOCK_HZ			U(125000000)
 
+/* uSDHC */
+#define S32G_USDHC_BASE			UL(0x402F0000)
+
 #define S32G_FIP_BASE			UL(0x34100000)
 #define S32G_FIP_SIZE			UL(0x100000)
 
 #define MAX_IO_HANDLES			U(2)
 #define MAX_IO_DEVICES			U(2)
 
+/* uSDHC as block device */
+#define MAX_IO_BLOCK_DEVICES		U(1)
+
 /* GIC settings */
 #define S32G_GIC_BASE			UL(0x50800000)
 #define PLAT_GICD_BASE			S32G_GIC_BASE
diff --git a/plat/nxp/s32/s32g274ardb2/plat_bl2_el3_setup.c b/plat/nxp/s32/s32g274ardb2/plat_bl2_el3_setup.c
index 0929f9d..810b7bb 100644
--- a/plat/nxp/s32/s32g274ardb2/plat_bl2_el3_setup.c
+++ b/plat/nxp/s32/s32g274ardb2/plat_bl2_el3_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2024 NXP
+ * Copyright 2024-2025 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,7 +8,10 @@
 
 #include <common/debug.h>
 #include <common/desc_image_load.h>
+#include <drivers/generic_delay_timer.h>
+#include <imx_usdhc.h>
 #include <lib/mmio.h>
+#include <lib/utils.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
 #include <plat/common/platform.h>
 #include <plat_console.h>
@@ -70,6 +73,29 @@
 	mmio_write_32(SIUL2_PC10_LIN0_IMCR, LIN0_RX_IMCR_CFG);
 }
 
+static void init_s32g_usdhc(void)
+{
+	static struct mmc_device_info sd_device_info = {
+		.mmc_dev_type = MMC_IS_SD_HC,
+		.ocr_voltage = OCR_3_2_3_3 | OCR_3_3_3_4,
+	};
+	imx_usdhc_params_t params;
+
+	zeromem(&params, sizeof(imx_usdhc_params_t));
+
+	params.reg_base = S32G_USDHC_BASE;
+	params.clk_rate = 25000000;
+	params.bus_width = MMC_BUS_WIDTH_4;
+	params.flags = MMC_FLAG_SD_CMD6;
+
+	imx_usdhc_init(&params, &sd_device_info);
+}
+
+static void plat_s32_mmc_setup(void)
+{
+	init_s32g_usdhc();
+}
+
 void bl2_el3_early_platform_setup(u_register_t arg0, u_register_t arg1,
 				  u_register_t arg2, u_register_t arg3)
 {
@@ -103,9 +129,18 @@
 		panic();
 	}
 
+	generic_delay_timer_init();
+
+	/* Configure the generic timer frequency to ensure proper operation
+	 * of the architectural timer in BL2.
+	 */
+	write_cntfrq_el0(plat_get_syscnt_freq2());
+
 	linflex_config_pinctrl();
 	console_s32g2_register();
 
+	plat_s32_mmc_setup();
+
 	plat_s32g2_io_setup();
 }
 
diff --git a/plat/nxp/s32/s32g274ardb2/plat_helpers.S b/plat/nxp/s32/s32g274ardb2/plat_helpers.S
index a7dda0d..924808b 100644
--- a/plat/nxp/s32/s32g274ardb2/plat_helpers.S
+++ b/plat/nxp/s32/s32g274ardb2/plat_helpers.S
@@ -1,5 +1,5 @@
 /*
- * Copyright 2024 NXP
+ * Copyright 2024-2025 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -121,6 +121,9 @@
 	mov_imm	x1, BL33_LIMIT
 	sub	x1, x1, x0
 	bl	zeromem
+	mov_imm	x0, IO_BUFFER_BASE
+	mov_imm	x1, IO_BUFFER_SIZE
+	bl	zeromem
 	mov	x30, x10
 	ret
 endfunc platform_mem_init
diff --git a/plat/nxp/s32/s32g274ardb2/plat_io_storage.c b/plat/nxp/s32/s32g274ardb2/plat_io_storage.c
index db6bcc5..c4efe01 100644
--- a/plat/nxp/s32/s32g274ardb2/plat_io_storage.c
+++ b/plat/nxp/s32/s32g274ardb2/plat_io_storage.c
@@ -1,14 +1,19 @@
 /*
- * Copyright 2024 NXP
+ * Copyright 2024-2025 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include <assert.h>
 
+#include <drivers/io/io_block.h>
 #include <drivers/io/io_driver.h>
 #include <drivers/io/io_fip.h>
 #include <drivers/io/io_memmap.h>
+#include <drivers/mmc.h>
+#include <drivers/partition/partition.h>
+#include <lib/utils.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
 #include <plat/common/platform.h>
 #include <tools_share/firmware_image_package.h>
 
@@ -20,24 +25,23 @@
 	int (*check)(const uintptr_t spec);
 };
 
-static int open_memmap(const uintptr_t spec);
-static int open_fip(const uintptr_t spec);
-
 static uintptr_t fip_dev_handle;
 
-static uintptr_t memmap_dev_handle;
+static io_block_spec_t fip_mmc_spec;
 
-static int open_memmap(const uintptr_t spec)
+static uintptr_t mmc_dev_handle;
+
+static int open_mmc(const uintptr_t spec)
 {
-	uintptr_t temp_handle = 0U;
+	uintptr_t temp_handle;
 	int result;
 
-	result = io_dev_init(memmap_dev_handle, (uintptr_t)0);
+	result = io_dev_init(mmc_dev_handle, (uintptr_t)0U);
 	if (result != 0) {
 		return result;
 	}
 
-	result = io_open(memmap_dev_handle, spec, &temp_handle);
+	result = io_open(mmc_dev_handle, spec, &temp_handle);
 	if (result == 0) {
 		(void)io_close(temp_handle);
 	}
@@ -66,16 +70,43 @@
 
 void plat_s32g2_io_setup(void)
 {
-	static const io_dev_connector_t *memmap_dev_con;
+	static const io_block_dev_spec_t mmc_dev_spec = {
+		/* It's used as temp buffer in block driver. */
+		.buffer		= {
+			.offset = IO_BUFFER_BASE,
+			.length = IO_BUFFER_SIZE,
+		},
+		.ops		= {
+			.read	= mmc_read_blocks,
+			.write	= mmc_write_blocks,
+		},
+		.block_size	= MMC_BLOCK_SIZE,
+	};
 	static const io_dev_connector_t *fip_dev_con;
+	static const io_dev_connector_t *mmc_dev_con;
 
+	partition_entry_t fip_part;
+	uintptr_t io_buf_base;
 	int result __unused;
+	size_t io_buf_size;
+	int ret;
 
-	result = register_io_dev_memmap(&memmap_dev_con);
+	io_buf_base = mmc_dev_spec.buffer.offset;
+	io_buf_size = mmc_dev_spec.buffer.length;
+
+	ret = mmap_add_dynamic_region(io_buf_base, io_buf_base,
+				      io_buf_size,
+				      MT_MEMORY | MT_RW | MT_SECURE);
+	if (ret != 0) {
+		ERROR("Failed to map the IO buffer\n");
+		panic();
+	}
+
+	result = register_io_dev_block(&mmc_dev_con);
 	assert(result == 0);
 
-	result = io_dev_open(memmap_dev_con, (uintptr_t)0,
-			     &memmap_dev_handle);
+	result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_dev_spec,
+			     &mmc_dev_handle);
 	assert(result == 0);
 
 	result = register_io_dev_fip(&fip_dev_con);
@@ -84,14 +115,24 @@
 	result = io_dev_open(fip_dev_con, (uintptr_t)0,
 			     &fip_dev_handle);
 	assert(result == 0);
+
+	ret = gpt_partition_init();
+	if (ret != 0) {
+		ERROR("Could not load MBR partition table\n");
+		panic();
+	}
+
+	fip_part = get_partition_entry_list()->list[FIP_PART];
+	fip_mmc_spec.offset = fip_part.start;
+	fip_mmc_spec.length = fip_part.length;
 }
 
 int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
 			  uintptr_t *image_spec)
 {
-	static const io_block_spec_t fip_block_spec = {
-		.offset = S32G_FIP_BASE,
-		.length = S32G_FIP_SIZE,
+	static const io_block_spec_t mbr_spec = {
+		.offset = 0,
+		.length = PLAT_PARTITION_BLOCK_SIZE,
 	};
 
 	static const io_uuid_spec_t bl31_uuid_spec = {
@@ -102,11 +143,11 @@
 		.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
 	};
 
-	static const struct plat_io_policy policies[BL33_IMAGE_ID + 1] = {
+	static const struct plat_io_policy policies[GPT_IMAGE_ID + 1] = {
 		[FIP_IMAGE_ID] = {
-			.dev_handle = &memmap_dev_handle,
-			.image_spec = (uintptr_t)&fip_block_spec,
-			.check = open_memmap,
+			.dev_handle = &mmc_dev_handle,
+			.image_spec = (uintptr_t)&fip_mmc_spec,
+			.check = open_mmc,
 		},
 		[BL31_IMAGE_ID] = {
 			.dev_handle = &fip_dev_handle,
@@ -118,6 +159,11 @@
 			.image_spec = (uintptr_t)&bl33_uuid_spec,
 			.check = open_fip,
 		},
+		[GPT_IMAGE_ID] = {
+			.dev_handle = &mmc_dev_handle,
+			.image_spec = (uintptr_t)&mbr_spec,
+			.check = open_mmc,
+		},
 	};
 	const struct plat_io_policy *policy;
 	int result;
diff --git a/plat/nxp/s32/s32g274ardb2/platform.mk b/plat/nxp/s32/s32g274ardb2/platform.mk
index 4ec7cd0..25e9ebd 100644
--- a/plat/nxp/s32/s32g274ardb2/platform.mk
+++ b/plat/nxp/s32/s32g274ardb2/platform.mk
@@ -1,5 +1,5 @@
 #
-# Copyright 2024 NXP
+# Copyright 2024-2025 NXP
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -20,7 +20,8 @@
 S32_ERRATA_LIST += ERRATA_S32_051700
 
 PLAT_INCLUDES = \
-	-I${PLAT_S32G274ARDB2}/include
+	-I${PLAT_S32G274ARDB2}/include \
+	-Idrivers/imx/usdhc \
 
 PROGRAMMABLE_RESET_ADDRESS := 1
 
@@ -41,12 +42,19 @@
 PLAT_XLAT_TABLES_DYNAMIC := 1
 $(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC))
 
+NXP_ESDHC_LE := 1
+$(eval $(call add_define,NXP_ESDHC_LE))
+
 # Selecting Drivers for SoC
 $(eval $(call SET_NXP_MAKE_FLAG,CONSOLE_NEEDED,BL_COMM))
 $(eval $(call SET_NXP_MAKE_FLAG,CLK_NEEDED,BL_COMM))
 
 include ${PLAT_DRIVERS_PATH}/drivers.mk
 
+# Selecting the raw partition where the FIP image is stored
+FIP_PART ?= 0
+$(eval $(call add_define,FIP_PART))
+
 BL_COMMON_SOURCES += \
 	${PLAT_S32G274ARDB2}/plat_console.c \
 	${PLAT_S32G274ARDB2}/plat_helpers.S \
@@ -60,11 +68,21 @@
 	${PLAT_S32G274ARDB2}/plat_io_storage.c \
 	${PLAT_S32G274ARDB2}/s32cc_ncore.c \
 	common/desc_image_load.c \
+	common/tf_crc32.c \
+	drivers/delay_timer/delay_timer.c \
+	drivers/delay_timer/generic_delay_timer.c \
+	drivers/imx/usdhc/imx_usdhc.c \
+	drivers/io/io_block.c \
 	drivers/io/io_fip.c \
 	drivers/io/io_memmap.c \
 	drivers/io/io_storage.c \
+	drivers/mmc/mmc.c \
+	drivers/partition/gpt.c \
+	drivers/partition/partition.c \
 	lib/cpus/aarch64/cortex_a53.S \
 
+BL2_CPPFLAGS += -march=armv8-a+crc
+
 BL31_SOURCES += \
 	${GICV3_SOURCES} \
 	${PLAT_S32G274ARDB2}/plat_bl31_setup.c \
diff --git a/plat/nxp/s32/s32g274ardb2/s32cc_bl_common.c b/plat/nxp/s32/s32g274ardb2/s32cc_bl_common.c
index 4664438..eb903c5 100644
--- a/plat/nxp/s32/s32g274ardb2/s32cc_bl_common.c
+++ b/plat/nxp/s32/s32g274ardb2/s32cc_bl_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2024 NXP
+ * Copyright 2024-2025 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -7,6 +7,7 @@
 
 #include <common/bl_common.h>
 #include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat/common/platform.h>
 
 #include <s32cc-bl-common.h>
 
@@ -38,3 +39,8 @@
 
 	return 0;
 }
+
+unsigned int plat_get_syscnt_freq2(void)
+{
+	return COUNTER_FREQUENCY;
+}
diff --git a/plat/nxp/s32/s32g274ardb2/s32g2_soc.c b/plat/nxp/s32/s32g274ardb2/s32g2_soc.c
index 0001352..c005bad 100644
--- a/plat/nxp/s32/s32g274ardb2/s32g2_soc.c
+++ b/plat/nxp/s32/s32g274ardb2/s32g2_soc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2024 NXP
+ * Copyright 2024-2025 NXP
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -45,8 +45,3 @@
 
 	return (int)core_id;
 }
-
-unsigned int plat_get_syscnt_freq2(void)
-{
-	return COUNTER_FREQUENCY;
-}
diff --git a/plat/nxp/soc-lx2160a/lx2160aqds/platform.mk b/plat/nxp/soc-lx2160a/lx2160aqds/platform.mk
index 226b22b..12fbac4 100644
--- a/plat/nxp/soc-lx2160a/lx2160aqds/platform.mk
+++ b/plat/nxp/soc-lx2160a/lx2160aqds/platform.mk
@@ -12,8 +12,8 @@
 NXP_COINED_BB	:=	no
 
  # DDR Compilation Configs
-NUM_OF_DDRC	:=	1
-DDRC_NUM_DIMM	:=	1
+NUM_OF_DDRC	:=	2
+DDRC_NUM_DIMM	:=	2
 DDRC_NUM_CS	:=	2
 DDR_ECC_EN	:=	yes
  #enable address decoding feature
diff --git a/services/arm_arch_svc/arm_arch_svc_setup.c b/services/arm_arch_svc/arm_arch_svc_setup.c
index 6051de8..329f59b 100644
--- a/services/arm_arch_svc/arm_arch_svc_setup.c
+++ b/services/arm_arch_svc/arm_arch_svc_setup.c
@@ -17,7 +17,7 @@
 
 static int32_t smccc_version(void)
 {
-	return MAKE_SMCCC_VERSION(SMCCC_MAJOR_VERSION, SMCCC_MINOR_VERSION);
+	return (int32_t)MAKE_SMCCC_VERSION(SMCCC_MAJOR_VERSION, SMCCC_MINOR_VERSION);
 }
 
 static int32_t smccc_arch_features(u_register_t arg1)
@@ -294,7 +294,7 @@
 		arm_arch_svc,
 		OEN_ARM_START,
 		OEN_ARM_END,
-		SMC_TYPE_FAST,
+		(uint8_t)SMC_TYPE_FAST,
 		NULL,
 		arm_arch_svc_smc_handler
 );
diff --git a/services/std_svc/lfa/bl31_lfa.c b/services/std_svc/lfa/bl31_lfa.c
new file mode 100644
index 0000000..6f66826
--- /dev/null
+++ b/services/std_svc/lfa/bl31_lfa.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <services/bl31_lfa.h>
+#include <services/lfa_svc.h>
+
+static int32_t lfa_bl31_prime(struct lfa_component_status *activation)
+{
+	return LFA_WRONG_STATE;
+}
+
+static int32_t lfa_bl31_activate(struct lfa_component_status *activation,
+		uint64_t ep_address,
+		uint64_t context_id)
+{
+	return LFA_WRONG_STATE;
+}
+
+static struct lfa_component_ops bl31_activator = {
+	.prime = lfa_bl31_prime,
+	.activate = lfa_bl31_activate,
+	.may_reset_cpu = false,
+	.cpu_rendezvous_required = true,
+};
+
+struct lfa_component_ops *get_bl31_activator(void)
+{
+	return &bl31_activator;
+}
diff --git a/services/std_svc/lfa/lfa.mk b/services/std_svc/lfa/lfa.mk
new file mode 100644
index 0000000..056b537
--- /dev/null
+++ b/services/std_svc/lfa/lfa.mk
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2025, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+LFA_SOURCES	+=	$(addprefix services/std_svc/lfa/, \
+			  lfa_main.c \
+			  bl31_lfa.c \
+			  lfa_holding_pen.c)
+
+ifeq (${ENABLE_RME}, 1)
+LFA_SOURCES	+=	services/std_svc/rmmd/rmmd_rmm_lfa.c
+endif
diff --git a/services/std_svc/lfa/lfa_holding_pen.c b/services/std_svc/lfa/lfa_holding_pen.c
new file mode 100644
index 0000000..8ee260c
--- /dev/null
+++ b/services/std_svc/lfa/lfa_holding_pen.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <common/debug.h>
+#include <lib/psci/psci_lib.h>
+#include <lib/spinlock.h>
+#include <lib/utils_def.h>
+#include <plat/common/platform.h>
+#include <services/lfa_holding_pen.h>
+
+#include <platform_def.h>
+
+static spinlock_t holding_lock;
+static spinlock_t activation_lock;
+static uint32_t activation_count;
+static enum lfa_retc activation_status;
+
+/**
+ * lfa_holding_start - Called by each active CPU to coordinate live activation.
+ *
+ * Note that only CPUs that are active at the time of activation will
+ * participate in CPU rendezvous.
+ *
+ * This function is invoked by each CPU participating in the LFA Activate
+ * process. It increments the shared activation count under `activation_lock`
+ * to track how many CPUs have entered the activation phase.
+ *
+ * The first CPU to enter acquires the `holding_lock`, which ensures
+ * serialization during the wait and activation phases. This lock is
+ * released only after the last CPU completes the activation.
+ *
+ * The function returns `true` only for the last CPU to enter, allowing it
+ * to proceed with performing the live firmware activation. All other CPUs
+ * receive `false` and will wait in `lfa_holding_wait()` until activation
+ * is complete.
+ *
+ * @return `true` for the last CPU, `false` for all others.
+ */
+bool lfa_holding_start(void)
+{
+	bool status;
+	unsigned int no_of_cpus;
+
+	spin_lock(&activation_lock);
+
+	if (activation_count == 0U) {
+		/* First CPU locks holding lock */
+		spin_lock(&holding_lock);
+	}
+
+	activation_count += 1U;
+
+	no_of_cpus = psci_num_cpus_running_on_safe(plat_my_core_pos());
+	status = (activation_count == no_of_cpus);
+	if (!status) {
+		VERBOSE("Hold, %d CPU left\n",
+			 PLATFORM_CORE_COUNT - activation_count);
+	}
+
+	spin_unlock(&activation_lock);
+
+	return status;
+}
+
+/**
+ * lfa_holding_wait - CPUs wait until activation is completed by the last CPU.
+ *
+ * All CPUs are serialized using `holding_lock`, which is initially acquired
+ * by the first CPU in `lfa_holding_start()` and only released by the last
+ * CPU through `lfa_holding_release()`. This ensures that no two CPUs enter
+ * the critical section at the same time during the wait phase. Once the
+ * last CPU completes activation, each CPU decrements the activation count
+ * and returns the final activation status,  which was set by the last CPU
+ * to complete the activation process.
+ *
+ * @return Activation status set by the last CPU.
+ */
+enum lfa_retc lfa_holding_wait(void)
+{
+	spin_lock(&holding_lock);
+	activation_count -= 1U;
+	spin_unlock(&holding_lock);
+	return activation_status;
+}
+
+/**
+ * lfa_holding_release - Called by the last CPU to complete activation.
+ *
+ * This function is used by the last participating CPU after it completes
+ * live firmware activation. It updates the shared activation status and
+ * resets the activation count. Finally, it releases the `holding_lock` to
+ * allow other CPUs that were waiting in `lfa_holding_wait()` to proceed.
+ *
+ * @param status Activation status to be shared with other CPUs.
+ */
+void lfa_holding_release(enum lfa_retc status)
+{
+	activation_count = 0U;
+	activation_status = status;
+	spin_unlock(&holding_lock);
+}
diff --git a/services/std_svc/lfa/lfa_main.c b/services/std_svc/lfa/lfa_main.c
new file mode 100644
index 0000000..1cf65ae
--- /dev/null
+++ b/services/std_svc/lfa/lfa_main.c
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <errno.h>
+
+#include <plat/common/platform.h>
+#include <services/bl31_lfa.h>
+#include <services/lfa_svc.h>
+#include <services/rmmd_rmm_lfa.h>
+#include <smccc_helpers.h>
+
+static uint32_t lfa_component_count;
+static plat_lfa_component_info_t *lfa_components;
+static struct lfa_component_status current_activation;
+static bool is_lfa_initialized;
+
+void lfa_reset_activation(void)
+{
+	current_activation.component_id = LFA_INVALID_COMPONENT;
+	current_activation.prime_status = PRIME_NONE;
+	current_activation.cpu_rendezvous_required = false;
+}
+
+static int convert_to_lfa_error(int ret)
+{
+	switch (ret) {
+	case 0:
+		return LFA_SUCCESS;
+	case -EAUTH:
+		return LFA_AUTH_ERROR;
+	case -ENOMEM:
+		return LFA_NO_MEMORY;
+	default:
+		return LFA_DEVICE_ERROR;
+	}
+}
+
+static bool lfa_initialize_components(void)
+{
+	lfa_component_count = plat_lfa_get_components(&lfa_components);
+
+	if (lfa_component_count == 0U || lfa_components == NULL) {
+		/* unlikely to reach here */
+		ERROR("Invalid LFA component setup: count = 0 or components are NULL");
+		return false;
+	}
+
+	return true;
+}
+
+static uint64_t get_fw_activation_flags(uint32_t fw_seq_id)
+{
+	const plat_lfa_component_info_t *comp =
+				&lfa_components[fw_seq_id];
+	uint64_t flags = 0ULL;
+
+	flags |= ((comp->activator == NULL ? 0ULL : 1ULL)
+		 << LFA_ACTIVATION_CAPABLE_SHIFT);
+	flags |= (uint64_t)(comp->activation_pending)
+		 << LFA_ACTIVATION_PENDING_SHIFT;
+
+	if (comp->activator != NULL) {
+		flags |= ((comp->activator->may_reset_cpu ? 1ULL : 0ULL)
+			 << LFA_MAY_RESET_CPU_SHIFT);
+		flags |= ((comp->activator->cpu_rendezvous_required ? 0ULL : 1ULL)
+			 << LFA_CPU_RENDEZVOUS_OPTIONAL_SHIFT);
+	}
+
+	return flags;
+}
+
+static int lfa_cancel(uint32_t component_id)
+{
+	int ret = LFA_SUCCESS;
+
+	if (lfa_component_count == 0U) {
+		return LFA_WRONG_STATE;
+	}
+
+	/* Check if component ID is in range. */
+	if ((component_id >= lfa_component_count) ||
+	    (component_id != current_activation.component_id)) {
+		return LFA_INVALID_PARAMETERS;
+	}
+
+	ret = plat_lfa_cancel(component_id);
+	if (ret != LFA_SUCCESS) {
+		return LFA_BUSY;
+	}
+
+	/* TODO: add proper termination prime and activate phases */
+	lfa_reset_activation();
+
+	return ret;
+}
+
+static int lfa_activate(uint32_t component_id, uint64_t flags,
+			uint64_t ep_address, uint64_t context_id)
+{
+	int ret = LFA_ACTIVATION_FAILED;
+	struct lfa_component_ops *activator;
+
+	if ((lfa_component_count == 0U) ||
+	    (!lfa_components[component_id].activation_pending) ||
+	    (current_activation.prime_status != PRIME_COMPLETE)) {
+		return LFA_COMPONENT_WRONG_STATE;
+	}
+
+	/* Check if fw_seq_id is in range. */
+	if ((component_id >= lfa_component_count) ||
+	    (current_activation.component_id != component_id)) {
+		return LFA_INVALID_PARAMETERS;
+	}
+
+	if (lfa_components[component_id].activator == NULL) {
+		return LFA_NOT_SUPPORTED;
+	}
+
+	activator = lfa_components[component_id].activator;
+	if (activator->activate != NULL) {
+		/*
+		 * Pass skip_cpu_rendezvous (flag[0]) only if flag[0]==1
+		 * & CPU_RENDEZVOUS is not required.
+		 */
+		if (flags & LFA_SKIP_CPU_RENDEZVOUS_BIT) {
+			if (!activator->cpu_rendezvous_required) {
+				INFO("Skipping rendezvous requested by caller.\n");
+				current_activation.cpu_rendezvous_required = false;
+			}
+			/*
+			 * Return error if caller tries to skip rendezvous when
+			 * it is required.
+			 */
+			else {
+				ERROR("CPU Rendezvous is required, can't skip.\n");
+				return LFA_INVALID_PARAMETERS;
+			}
+		}
+
+		ret = activator->activate(&current_activation, ep_address,
+					  context_id);
+	}
+
+	lfa_components[component_id].activation_pending = false;
+
+	return ret;
+}
+
+static int lfa_prime(uint32_t component_id, uint64_t *flags)
+{
+	int ret = LFA_SUCCESS;
+	struct lfa_component_ops *activator;
+
+	if (lfa_component_count == 0U ||
+	    !lfa_components[component_id].activation_pending) {
+		return LFA_WRONG_STATE;
+	}
+
+	/* Check if fw_seq_id is in range. */
+	if (component_id >= lfa_component_count) {
+		return LFA_INVALID_PARAMETERS;
+	}
+
+	if (lfa_components[component_id].activator == NULL) {
+		return LFA_NOT_SUPPORTED;
+	}
+
+	switch (current_activation.prime_status) {
+	case PRIME_NONE:
+		current_activation.component_id = component_id;
+		current_activation.prime_status = PRIME_STARTED;
+		break;
+
+	case PRIME_STARTED:
+		if (current_activation.component_id != component_id) {
+			/* Mismatched component trying to continue PRIME - error */
+			return LFA_WRONG_STATE;
+		}
+		break;
+
+	case PRIME_COMPLETE:
+	default:
+		break;
+	}
+
+	ret = plat_lfa_load_auth_image(component_id);
+	ret = convert_to_lfa_error(ret);
+
+	activator = lfa_components[component_id].activator;
+	if (activator->prime != NULL) {
+		ret = activator->prime(&current_activation);
+		if (ret != LFA_SUCCESS) {
+			/*
+			 * TODO: it should be LFA_PRIME_FAILED but specification
+			 * has not define this error yet
+			 */
+			return ret;
+		}
+	}
+
+	current_activation.prime_status = PRIME_COMPLETE;
+
+	/* TODO: split this into multiple PRIME calls */
+	*flags = 0ULL;
+
+	return ret;
+}
+
+int lfa_setup(void)
+{
+	is_lfa_initialized = lfa_initialize_components();
+	if (!is_lfa_initialized) {
+		return -1;
+	}
+
+	lfa_reset_activation();
+
+	return 0;
+}
+
+uint64_t lfa_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2,
+			 u_register_t x3, u_register_t x4, void *cookie,
+			 void *handle, u_register_t flags)
+{
+	uint64_t retx1, retx2;
+	uint64_t lfa_flags;
+	uint8_t *uuid_p;
+	uint32_t fw_seq_id = (uint32_t)x1;
+	int ret;
+
+	/**
+	 * TODO: Acquire serialization lock.
+	 */
+
+	if (!is_lfa_initialized) {
+		return LFA_NOT_SUPPORTED;
+	}
+
+	switch (smc_fid) {
+	case LFA_VERSION:
+		SMC_RET1(handle, LFA_VERSION_VAL);
+		break;
+
+	case LFA_FEATURES:
+		SMC_RET1(handle, is_lfa_fid(x1) ? LFA_SUCCESS : LFA_NOT_SUPPORTED);
+		break;
+
+	case LFA_GET_INFO:
+		/**
+		 * The current specification limits this input parameter to be zero for
+		 * version 1.0 of LFA
+		 */
+		if (x1 == 0ULL) {
+			SMC_RET3(handle, LFA_SUCCESS, lfa_component_count, 0);
+		} else {
+			SMC_RET1(handle, LFA_INVALID_PARAMETERS);
+		}
+		break;
+
+	case LFA_GET_INVENTORY:
+		if (lfa_component_count == 0U) {
+			SMC_RET1(handle, LFA_WRONG_STATE);
+		}
+
+		/*
+		 * Check if fw_seq_id is in range. LFA_GET_INFO must be called first to scan
+		 * platform firmware and create a valid number of firmware components.
+		 */
+		if (fw_seq_id >= lfa_component_count) {
+			SMC_RET1(handle, LFA_INVALID_PARAMETERS);
+		}
+
+		/*
+		 * grab the UUID of asked fw_seq_id and set the return UUID
+		 * variables
+		 */
+		uuid_p = (uint8_t *)&lfa_components[fw_seq_id].uuid;
+		memcpy(&retx1, uuid_p, sizeof(uint64_t));
+		memcpy(&retx2, uuid_p + sizeof(uint64_t), sizeof(uint64_t));
+
+		/*
+		 * check the given fw_seq_id's update available
+		 * and accordingly set the active_pending flag
+		 */
+		lfa_components[fw_seq_id].activation_pending =
+				is_plat_lfa_activation_pending(fw_seq_id);
+
+		INFO("Component %lu %s live activation:\n", x1,
+		      lfa_components[fw_seq_id].activator ? "supports" :
+		      "does not support");
+
+		if (lfa_components[fw_seq_id].activator != NULL) {
+			INFO("Activation pending: %s\n",
+			      lfa_components[fw_seq_id].activation_pending ? "true" : "false");
+		}
+
+		INFO("x1 = 0x%016lx, x2 = 0x%016lx\n", retx1, retx2);
+
+		SMC_RET4(handle, LFA_SUCCESS, retx1, retx2, get_fw_activation_flags(fw_seq_id));
+
+		break;
+
+	case LFA_PRIME:
+		ret = lfa_prime(x1, &lfa_flags);
+		if (ret != LFA_SUCCESS) {
+			SMC_RET1(handle, ret);
+		} else {
+			SMC_RET2(handle, ret, lfa_flags);
+		}
+		break;
+
+	case LFA_ACTIVATE:
+		ret = lfa_activate(fw_seq_id, x2, x3, x4);
+		/* TODO: implement activate again */
+		SMC_RET2(handle, ret, 0ULL);
+
+		break;
+
+	case LFA_CANCEL:
+		ret = lfa_cancel(x1);
+		SMC_RET1(handle, ret);
+		break;
+
+	default:
+		WARN("Unimplemented LFA Service Call: 0x%x\n", smc_fid);
+		SMC_RET1(handle, SMC_UNK);
+		break; /* unreachable */
+
+	}
+
+	SMC_RET1(handle, SMC_UNK);
+
+	return 0;
+}
diff --git a/services/std_svc/rmmd/rmmd_rmm_lfa.c b/services/std_svc/rmmd/rmmd_rmm_lfa.c
new file mode 100644
index 0000000..966266b
--- /dev/null
+++ b/services/std_svc/rmmd/rmmd_rmm_lfa.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2025, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <services/lfa_svc.h>
+#include <services/rmmd_rmm_lfa.h>
+
+static int32_t lfa_rmm_prime(struct lfa_component_status *activation)
+{
+	return LFA_WRONG_STATE;
+}
+
+static int32_t lfa_rmm_activate(struct lfa_component_status *activation,
+				uint64_t ep_address, uint64_t context_id)
+{
+	return LFA_WRONG_STATE;
+}
+
+static struct lfa_component_ops rmm_activator = {
+	.prime = lfa_rmm_prime,
+	.activate = lfa_rmm_activate,
+	.may_reset_cpu = false,
+	.cpu_rendezvous_required = true,
+};
+
+struct lfa_component_ops *get_rmm_activator(void)
+{
+	return &rmm_activator;
+}
diff --git a/services/std_svc/std_svc_setup.c b/services/std_svc/std_svc_setup.c
index deca1c0..11c6031 100644
--- a/services/std_svc/std_svc_setup.c
+++ b/services/std_svc/std_svc_setup.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -15,6 +15,7 @@
 #include <lib/runtime_instr.h>
 #include <services/drtm_svc.h>
 #include <services/errata_abi_svc.h>
+#include <services/lfa_svc.h>
 #include <services/pci_svc.h>
 #include <services/rmmd_svc.h>
 #include <services/sdei.h>
@@ -86,6 +87,15 @@
 	}
 #endif /* DRTM_SUPPORT */
 
+#if LFA_SUPPORT
+	/*
+	 * Setup/Initialize resources useful during LFA
+	 */
+	if (lfa_setup() != 0) {
+		ret = 1;
+	}
+#endif /* LFA_SUPPORT */
+
 	return ret;
 }
 
@@ -217,6 +227,13 @@
 	}
 #endif /* DRTM_SUPPORT */
 
+#if LFA_SUPPORT
+	if (is_lfa_fid(smc_fid)) {
+		return lfa_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags);
+	}
+#endif /* LFA_SUPPORT */
+
+
 	switch (smc_fid) {
 	case ARM_STD_SVC_CALL_COUNT:
 		/*
diff --git a/tools/sptool/sp_mk_generator.py b/tools/sptool/sp_mk_generator.py
index 9a00c74..3dd1d4e 100644
--- a/tools/sptool/sp_mk_generator.py
+++ b/tools/sptool/sp_mk_generator.py
@@ -1,5 +1,5 @@
 #!/usr/bin/python3
-# Copyright (c) 2020-2024, Arm Limited. All rights reserved.
+# Copyright (c) 2020-2025, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 
@@ -156,7 +156,7 @@
 def get_load_address(sp_layout, sp, args :dict):
     ''' Helper to fetch load-address from pm file listed in sp_layout.json'''
     with open(get_sp_manifest_full_path(sp_layout[sp], args), "r") as pm_f:
-        load_address_lines = [l for l in pm_f if 'load-address' in l]
+        load_address_lines = [l for l in pm_f if re.search(r'load-address[^-]', l)]
 
     if len(load_address_lines) != 1:
         return None