Merge "lib/cpu: Workaround for Cortex A77 erratum 1946167" into integration
diff --git a/drivers/marvell/comphy/phy-comphy-3700.c b/drivers/marvell/comphy/phy-comphy-3700.c
index f6a40a5..02fe97c 100644
--- a/drivers/marvell/comphy/phy-comphy-3700.c
+++ b/drivers/marvell/comphy/phy-comphy-3700.c
@@ -525,7 +525,8 @@
 		data |= TXD_INVERT_BIT;
 	if (invert & COMPHY_POLARITY_RXD_INVERT)
 		data |= RXD_INVERT_BIT;
-	reg_set16(SGMIIPHY_ADDR(COMPHY_SYNC_PATTERN_REG, sd_ip_addr), data, 0);
+	mask = TXD_INVERT_BIT | RXD_INVERT_BIT;
+	reg_set16(SGMIIPHY_ADDR(COMPHY_SYNC_PATTERN_REG, sd_ip_addr), data, mask);
 
 	/*
 	 * 17. Set PHY input ports PIN_PU_PLL, PIN_PU_TX and PIN_PU_RX to 1 to
@@ -563,7 +564,7 @@
 	 * refer to RX initialization part for details.
 	 */
 	reg_set(MVEBU_COMPHY_REG_BASE + COMPHY_PHY_CFG1_OFFSET(comphy_index),
-		PHY_RX_INIT_BIT, 0x0);
+		PHY_RX_INIT_BIT, PHY_RX_INIT_BIT);
 
 	ret = polling_with_timeout(MVEBU_COMPHY_REG_BASE +
 				   COMPHY_PHY_STATUS_OFFSET(comphy_index),
@@ -594,7 +595,7 @@
 	debug_enter();
 
 	data = PIN_RESET_CORE_BIT | PIN_RESET_COMPHY_BIT;
-	mask = 0;
+	mask = data;
 	offset = MVEBU_COMPHY_REG_BASE + COMPHY_PHY_CFG1_OFFSET(comphy_index);
 	reg_set(offset, data, mask);
 
@@ -746,12 +747,15 @@
 	/*
 	 * 13. Check the Polarity invert bit
 	 */
-	if (invert & COMPHY_POLARITY_TXD_INVERT)
-		usb3_reg_set(reg_base, COMPHY_SYNC_PATTERN_REG, TXD_INVERT_BIT,
-			     TXD_INVERT_BIT, mode);
-	if (invert & COMPHY_POLARITY_RXD_INVERT)
-		usb3_reg_set(reg_base, COMPHY_SYNC_PATTERN_REG, RXD_INVERT_BIT,
-			     RXD_INVERT_BIT, mode);
+	data = 0U;
+	if (invert & COMPHY_POLARITY_TXD_INVERT) {
+		data |= TXD_INVERT_BIT;
+	}
+	if (invert & COMPHY_POLARITY_RXD_INVERT) {
+		data |= RXD_INVERT_BIT;
+	}
+	mask = TXD_INVERT_BIT | RXD_INVERT_BIT;
+	usb3_reg_set(reg_base, COMPHY_SYNC_PATTERN_REG, data, mask, mode);
 
 	/*
 	 * 14. Set max speed generation to USB3.0 5Gbps
@@ -802,21 +806,22 @@
 {
 	int ret;
 	uint32_t ref_clk;
+	uint32_t mask, data;
 	int invert = COMPHY_GET_POLARITY_INVERT(comphy_mode);
 
 	debug_enter();
 
 	/* 1. Enable max PLL. */
 	reg_set16(LANE_CFG1_ADDR(PCIE) + COMPHY_SD_ADDR,
-		  USE_MAX_PLL_RATE_EN, 0x0);
+		  USE_MAX_PLL_RATE_EN, USE_MAX_PLL_RATE_EN);
 
 	/* 2. Select 20 bit SERDES interface. */
 	reg_set16(GLOB_CLK_SRC_LO_ADDR(PCIE) + COMPHY_SD_ADDR,
-		  CFG_SEL_20B, 0);
+		  CFG_SEL_20B, CFG_SEL_20B);
 
 	/* 3. Force to use reg setting for PCIe mode */
 	reg_set16(MISC_REG1_ADDR(PCIE) + COMPHY_SD_ADDR,
-		  SEL_BITS_PCIE_FORCE, 0);
+		  SEL_BITS_PCIE_FORCE, SEL_BITS_PCIE_FORCE);
 
 	/* 4. Change RX wait */
 	reg_set16(PWR_MGM_TIM1_ADDR(PCIE) + COMPHY_SD_ADDR,
@@ -830,7 +835,7 @@
 
 	/* 6. Enable the output of 100M/125M/500M clock */
 	reg_set16(MISC_REG0_ADDR(PCIE) + COMPHY_SD_ADDR,
-		  MISC_REG0_DEFAULT_VALUE | CLK500M_EN | CLK100M_125M_EN,
+		  MISC_REG0_DEFAULT_VALUE | CLK500M_EN | TXDCLK_2X_SEL | CLK100M_125M_EN,
 		  REG_16_BIT_MASK);
 
 	/*
@@ -858,13 +863,15 @@
 		  SPEED_PLL_VALUE_16 | USE_MAX_PLL_RATE_BIT, REG_16_BIT_MASK);
 
 	/* 10. Check the Polarity invert bit */
-	if (invert & COMPHY_POLARITY_TXD_INVERT)
-		reg_set16(SYNC_PATTERN_REG_ADDR(PCIE) + COMPHY_SD_ADDR,
-			  TXD_INVERT_BIT, 0x0);
-
-	if (invert & COMPHY_POLARITY_RXD_INVERT)
-		reg_set16(SYNC_PATTERN_REG_ADDR(PCIE) + COMPHY_SD_ADDR,
-			  RXD_INVERT_BIT, 0x0);
+	data = 0U;
+	if (invert & COMPHY_POLARITY_TXD_INVERT) {
+		data |= TXD_INVERT_BIT;
+	}
+	if (invert & COMPHY_POLARITY_RXD_INVERT) {
+		data |= RXD_INVERT_BIT;
+	}
+	mask = TXD_INVERT_BIT | RXD_INVERT_BIT;
+	reg_set16(SYNC_PATTERN_REG_ADDR(PCIE) + COMPHY_SD_ADDR, data, mask);
 
 	/* 11. Release SW reset */
 	reg_set16(GLOB_PHY_CTRL0_ADDR(PCIE) + COMPHY_SD_ADDR,
diff --git a/drivers/marvell/comphy/phy-comphy-3700.h b/drivers/marvell/comphy/phy-comphy-3700.h
index 1628e36..94056f1 100644
--- a/drivers/marvell/comphy/phy-comphy-3700.h
+++ b/drivers/marvell/comphy/phy-comphy-3700.h
@@ -104,6 +104,7 @@
 #define COMPHY_MISC_REG0_ADDR		0x4F
 #define MISC_REG0_ADDR(unit)		(COMPHY_MISC_REG0_ADDR * PHY_SHFT(unit))
 #define CLK100M_125M_EN			BIT(4)
+#define TXDCLK_2X_SEL			BIT(6)
 #define CLK500M_EN			BIT(7)
 #define PHY_REF_CLK_SEL			BIT(10)
 #define MISC_REG0_DEFAULT_VALUE		0xA00D
diff --git a/include/lib/cpus/aarch64/cortex_a78c.h b/include/lib/cpus/aarch64/cortex_a78c.h
new file mode 100644
index 0000000..adb13bc
--- /dev/null
+++ b/include/lib/cpus/aarch64/cortex_a78c.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CORTEX_A78C_H
+#define CORTEX_A78C_H
+
+
+#define CORTEX_A78C_MIDR			        U(0x410FD4B1)
+
+/*******************************************************************************
+ * CPU Extended Control register specific definitions.
+ ******************************************************************************/
+#define CORTEX_A78C_CPUECTLR_EL1		        S3_0_C15_C1_4
+
+/*******************************************************************************
+ * CPU Power Control register specific definitions
+ ******************************************************************************/
+#define CORTEX_A78C_CPUPWRCTLR_EL1			S3_0_C15_C2_7
+#define CORTEX_A78C_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT	U(1)
+
+#endif /* CORTEX_A78C_H */
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index 3135fb4..9d9f9d3 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -160,86 +160,74 @@
 #define CTX_AFSR1_EL2		U(0x10)
 #define CTX_AMAIR_EL2		U(0x18)
 #define CTX_CNTHCTL_EL2		U(0x20)
-#define CTX_CNTHP_CTL_EL2	U(0x28)
-#define CTX_CNTHP_CVAL_EL2	U(0x30)
-#define CTX_CNTHP_TVAL_EL2	U(0x38)
-#define CTX_CNTVOFF_EL2		U(0x40)
-#define CTX_CPTR_EL2		U(0x48)
-#define CTX_DBGVCR32_EL2	U(0x50)
-#define CTX_ELR_EL2		U(0x58)
-#define CTX_ESR_EL2		U(0x60)
-#define CTX_FAR_EL2		U(0x68)
-#define CTX_HACR_EL2		U(0x70)
-#define CTX_HCR_EL2		U(0x78)
-#define CTX_HPFAR_EL2		U(0x80)
-#define CTX_HSTR_EL2		U(0x88)
-#define CTX_ICC_SRE_EL2		U(0x90)
-#define CTX_ICH_HCR_EL2		U(0x98)
-#define CTX_ICH_VMCR_EL2	U(0xa0)
-#define CTX_MAIR_EL2		U(0xa8)
-#define CTX_MDCR_EL2		U(0xb0)
-#define CTX_PMSCR_EL2		U(0xb8)
-#define CTX_SCTLR_EL2		U(0xc0)
-#define CTX_SPSR_EL2		U(0xc8)
-#define CTX_SP_EL2		U(0xd0)
-#define CTX_TCR_EL2		U(0xd8)
-#define CTX_TPIDR_EL2		U(0xe0)
-#define CTX_TTBR0_EL2		U(0xe8)
-#define CTX_VBAR_EL2		U(0xf0)
-#define CTX_VMPIDR_EL2		U(0xf8)
-#define CTX_VPIDR_EL2		U(0x100)
-#define CTX_VTCR_EL2		U(0x108)
-#define CTX_VTTBR_EL2		U(0x110)
+#define CTX_CNTVOFF_EL2		U(0x28)
+#define CTX_CPTR_EL2		U(0x30)
+#define CTX_DBGVCR32_EL2	U(0x38)
+#define CTX_ELR_EL2		U(0x40)
+#define CTX_ESR_EL2		U(0x48)
+#define CTX_FAR_EL2		U(0x50)
+#define CTX_HACR_EL2		U(0x58)
+#define CTX_HCR_EL2		U(0x60)
+#define CTX_HPFAR_EL2		U(0x68)
+#define CTX_HSTR_EL2		U(0x70)
+#define CTX_ICC_SRE_EL2		U(0x78)
+#define CTX_ICH_HCR_EL2		U(0x80)
+#define CTX_ICH_VMCR_EL2	U(0x88)
+#define CTX_MAIR_EL2		U(0x90)
+#define CTX_MDCR_EL2		U(0x98)
+#define CTX_PMSCR_EL2		U(0xa0)
+#define CTX_SCTLR_EL2		U(0xa8)
+#define CTX_SPSR_EL2		U(0xb0)
+#define CTX_SP_EL2		U(0xb8)
+#define CTX_TCR_EL2		U(0xc0)
+#define CTX_TPIDR_EL2		U(0xc8)
+#define CTX_TTBR0_EL2		U(0xd0)
+#define CTX_VBAR_EL2		U(0xd8)
+#define CTX_VMPIDR_EL2		U(0xe0)
+#define CTX_VPIDR_EL2		U(0xe8)
+#define CTX_VTCR_EL2		U(0xf0)
+#define CTX_VTTBR_EL2		U(0xf8)
 
 // Only if MTE registers in use
-#define CTX_TFSR_EL2		U(0x118)
+#define CTX_TFSR_EL2		U(0x100)
 
 // Only if ENABLE_MPAM_FOR_LOWER_ELS==1
-#define CTX_MPAM2_EL2		U(0x120)
-#define CTX_MPAMHCR_EL2		U(0x128)
-#define CTX_MPAMVPM0_EL2	U(0x130)
-#define CTX_MPAMVPM1_EL2	U(0x138)
-#define CTX_MPAMVPM2_EL2	U(0x140)
-#define CTX_MPAMVPM3_EL2	U(0x148)
-#define CTX_MPAMVPM4_EL2	U(0x150)
-#define CTX_MPAMVPM5_EL2	U(0x158)
-#define CTX_MPAMVPM6_EL2	U(0x160)
-#define CTX_MPAMVPM7_EL2	U(0x168)
-#define CTX_MPAMVPMV_EL2	U(0x170)
+#define CTX_MPAM2_EL2		U(0x108)
+#define CTX_MPAMHCR_EL2		U(0x110)
+#define CTX_MPAMVPM0_EL2	U(0x118)
+#define CTX_MPAMVPM1_EL2	U(0x120)
+#define CTX_MPAMVPM2_EL2	U(0x128)
+#define CTX_MPAMVPM3_EL2	U(0x130)
+#define CTX_MPAMVPM4_EL2	U(0x138)
+#define CTX_MPAMVPM5_EL2	U(0x140)
+#define CTX_MPAMVPM6_EL2	U(0x148)
+#define CTX_MPAMVPM7_EL2	U(0x150)
+#define CTX_MPAMVPMV_EL2	U(0x158)
 
 // Starting with Armv8.6
-#define CTX_HAFGRTR_EL2		U(0x178)
-#define CTX_HDFGRTR_EL2		U(0x180)
-#define CTX_HDFGWTR_EL2		U(0x188)
-#define CTX_HFGITR_EL2		U(0x190)
-#define CTX_HFGRTR_EL2		U(0x198)
-#define CTX_HFGWTR_EL2		U(0x1a0)
-#define CTX_CNTPOFF_EL2		U(0x1a8)
+#define CTX_HAFGRTR_EL2		U(0x160)
+#define CTX_HDFGRTR_EL2		U(0x168)
+#define CTX_HDFGWTR_EL2		U(0x170)
+#define CTX_HFGITR_EL2		U(0x178)
+#define CTX_HFGRTR_EL2		U(0x180)
+#define CTX_HFGWTR_EL2		U(0x188)
+#define CTX_CNTPOFF_EL2		U(0x190)
 
 // Starting with Armv8.4
-#define CTX_CNTHPS_CTL_EL2	U(0x1b0)
-#define CTX_CNTHPS_CVAL_EL2	U(0x1b8)
-#define CTX_CNTHPS_TVAL_EL2	U(0x1c0)
-#define CTX_CNTHVS_CTL_EL2	U(0x1c8)
-#define CTX_CNTHVS_CVAL_EL2	U(0x1d0)
-#define CTX_CNTHVS_TVAL_EL2	U(0x1d8)
-#define CTX_CNTHV_CTL_EL2	U(0x1e0)
-#define CTX_CNTHV_CVAL_EL2	U(0x1e8)
-#define CTX_CNTHV_TVAL_EL2	U(0x1f0)
-#define CTX_CONTEXTIDR_EL2	U(0x1f8)
-#define CTX_SDER32_EL2		U(0x200)
-#define CTX_TTBR1_EL2		U(0x208)
-#define CTX_VDISR_EL2		U(0x210)
-#define CTX_VNCR_EL2		U(0x218)
-#define CTX_VSESR_EL2		U(0x220)
-#define CTX_VSTCR_EL2		U(0x228)
-#define CTX_VSTTBR_EL2		U(0x230)
-#define CTX_TRFCR_EL2		U(0x238)
+#define CTX_CONTEXTIDR_EL2	U(0x198)
+#define CTX_SDER32_EL2		U(0x1a0)
+#define CTX_TTBR1_EL2		U(0x1a8)
+#define CTX_VDISR_EL2		U(0x1b0)
+#define CTX_VNCR_EL2		U(0x1b8)
+#define CTX_VSESR_EL2		U(0x1c0)
+#define CTX_VSTCR_EL2		U(0x1c8)
+#define CTX_VSTTBR_EL2		U(0x1d0)
+#define CTX_TRFCR_EL2		U(0x1d8)
 
 // Starting with Armv8.5
-#define CTX_SCXTNUM_EL2		U(0x240)
+#define CTX_SCXTNUM_EL2		U(0x1e0)
 /* Align to the next 16 byte boundary */
-#define CTX_EL2_SYSREGS_END	U(0x250)
+#define CTX_EL2_SYSREGS_END	U(0x1f0)
 
 #endif /* CTX_INCLUDE_EL2_REGS */
 
diff --git a/lib/cpus/aarch64/cortex_a78c.S b/lib/cpus/aarch64/cortex_a78c.S
new file mode 100644
index 0000000..1b170fe
--- /dev/null
+++ b/lib/cpus/aarch64/cortex_a78c.S
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <common/bl_common.h>
+#include <cortex_a78c.h>
+#include <cpu_macros.S>
+#include <plat_macros.S>
+
+/* Hardware handled coherency */
+#if HW_ASSISTED_COHERENCY == 0
+#error "cortex_a78c must be compiled with HW_ASSISTED_COHERENCY enabled"
+#endif
+
+	/* ----------------------------------------------------
+	 * HW will do the cache maintenance while powering down
+	 * ----------------------------------------------------
+	 */
+func cortex_a78c_core_pwr_dwn
+	/* ---------------------------------------------------
+	 * Enable CPU power down bit in power control register
+	 * ---------------------------------------------------
+	 */
+	mrs	x0, CORTEX_A78C_CPUPWRCTLR_EL1
+	orr	x0, x0, #CORTEX_A78C_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT
+	msr	CORTEX_A78C_CPUPWRCTLR_EL1, x0
+	isb
+	ret
+endfunc cortex_a78c_core_pwr_dwn
+
+#if REPORT_ERRATA
+/*
+ * Errata printing function for Cortex A78C. Must follow AAPCS.
+ */
+func cortex_a78c_errata_report
+        ret
+endfunc cortex_a78c_errata_report
+#endif
+
+	/* ---------------------------------------------
+	 * This function provides cortex_a78c specific
+	 * register information for crash reporting.
+	 * It needs to return with x6 pointing to
+	 * a list of register names in ascii and
+	 * x8 - x15 having values of registers to be
+	 * reported.
+	 * ---------------------------------------------
+	 */
+.section .rodata.cortex_a78c_regs, "aS"
+cortex_a78c_regs:  /* The ascii list of register names to be reported */
+	.asciz	"cpuectlr_el1", ""
+
+func cortex_a78c_cpu_reg_dump
+	adr	x6, cortex_a78c_regs
+	mrs	x8, CORTEX_A78C_CPUECTLR_EL1
+	ret
+endfunc cortex_a78c_cpu_reg_dump
+
+declare_cpu_ops cortex_a78c, CORTEX_A78C_MIDR, \
+	CPU_NO_RESET_FUNC, \
+	cortex_a78c_core_pwr_dwn
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index 75e214d..7daf30d 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -30,7 +30,7 @@
 
 /* -----------------------------------------------------
  * The following function strictly follows the AArch64
- * PCS to use x9-x17 (temporary caller-saved registers)
+ * PCS to use x9-x16 (temporary caller-saved registers)
  * to save EL2 system register context. It assumes that
  * 'x0' is pointing to a 'el2_sys_regs' structure where
  * the register context will be saved.
@@ -43,7 +43,6 @@
  * ICH_LR<n>_EL2
  * -----------------------------------------------------
  */
-
 func el2_sysregs_context_save
 	mrs	x9, actlr_el2
 	mrs	x10, afsr0_el2
@@ -54,185 +53,153 @@
 	stp	x11, x12, [x0, #CTX_AFSR1_EL2]
 
 	mrs	x13, cnthctl_el2
-	mrs	x14, cnthp_ctl_el2
+	mrs	x14, cntvoff_el2
 	stp	x13, x14, [x0, #CTX_CNTHCTL_EL2]
 
-	mrs	x15, cnthp_cval_el2
-	mrs	x16, cnthp_tval_el2
-	stp	x15, x16, [x0, #CTX_CNTHP_CVAL_EL2]
-
-	mrs	x17, cntvoff_el2
-	mrs	x9, cptr_el2
-	stp	x17, x9, [x0, #CTX_CNTVOFF_EL2]
+	mrs	x15, cptr_el2
+	str	x15, [x0, #CTX_CPTR_EL2]
 
-	mrs	x11, elr_el2
 #if CTX_INCLUDE_AARCH32_REGS
-	mrs	x10, dbgvcr32_el2
-	stp	x10, x11, [x0, #CTX_DBGVCR32_EL2]
-#else
-	str	x11, [x0, #CTX_ELR_EL2]
+	mrs	x16, dbgvcr32_el2
+	str	x16, [x0, #CTX_DBGVCR32_EL2]
 #endif
 
-	mrs	x14, esr_el2
-	mrs	x15, far_el2
-	stp	x14, x15, [x0, #CTX_ESR_EL2]
+	mrs	x9, elr_el2
+	mrs	x10, esr_el2
+	stp	x9, x10, [x0, #CTX_ELR_EL2]
 
-	mrs	x16, hacr_el2
-	mrs	x17, hcr_el2
-	stp	x16, x17, [x0, #CTX_HACR_EL2]
+	mrs	x11, far_el2
+	mrs	x12, hacr_el2
+	stp	x11, x12, [x0, #CTX_FAR_EL2]
 
-	mrs	x9, hpfar_el2
-	mrs	x10, hstr_el2
-	stp	x9, x10, [x0, #CTX_HPFAR_EL2]
+	mrs	x13, hcr_el2
+	mrs	x14, hpfar_el2
+	stp	x13, x14, [x0, #CTX_HCR_EL2]
 
-	mrs	x11, ICC_SRE_EL2
-	mrs	x12, ICH_HCR_EL2
-	stp	x11, x12, [x0, #CTX_ICC_SRE_EL2]
+	mrs	x15, hstr_el2
+	mrs	x16, ICC_SRE_EL2
+	stp	x15, x16, [x0, #CTX_HSTR_EL2]
 
-	mrs	x13, ICH_VMCR_EL2
-	mrs	x14, mair_el2
-	stp	x13, x14, [x0, #CTX_ICH_VMCR_EL2]
+	mrs	x9, ICH_HCR_EL2
+	mrs	x10, ICH_VMCR_EL2
+	stp	x9, x10, [x0, #CTX_ICH_HCR_EL2]
 
-	mrs	x15, mdcr_el2
+	mrs	x11, mair_el2
+	mrs	x12, mdcr_el2
+	stp	x11, x12, [x0, #CTX_MAIR_EL2]
+
 #if ENABLE_SPE_FOR_LOWER_ELS
-	mrs	x16, PMSCR_EL2
-	stp	x15, x16, [x0, #CTX_MDCR_EL2]
-#else
-	str	x15, [x0, #CTX_MDCR_EL2]
+	mrs	x13, PMSCR_EL2
+	str	x13, [x0, #CTX_PMSCR_EL2]
 #endif
-
-	mrs	x17, sctlr_el2
-	mrs	x9, spsr_el2
-	stp	x17, x9, [x0, #CTX_SCTLR_EL2]
+	mrs	x14, sctlr_el2
+	str	x14, [x0, #CTX_SCTLR_EL2]
 
-	mrs	x10, sp_el2
-	mrs	x11, tcr_el2
-	stp	x10, x11, [x0, #CTX_SP_EL2]
+	mrs	x15, spsr_el2
+	mrs	x16, sp_el2
+	stp	x15, x16, [x0, #CTX_SPSR_EL2]
 
-	mrs	x12, tpidr_el2
-	mrs	x13, ttbr0_el2
-	stp	x12, x13, [x0, #CTX_TPIDR_EL2]
+	mrs	x9, tcr_el2
+	mrs	x10, tpidr_el2
+	stp	x9, x10, [x0, #CTX_TCR_EL2]
 
-	mrs	x14, vbar_el2
-	mrs	x15, vmpidr_el2
-	stp	x14, x15, [x0, #CTX_VBAR_EL2]
+	mrs	x11, ttbr0_el2
+	mrs	x12, vbar_el2
+	stp	x11, x12, [x0, #CTX_TTBR0_EL2]
 
-	mrs	x16, vpidr_el2
-	mrs	x17, vtcr_el2
-	stp	x16, x17, [x0, #CTX_VPIDR_EL2]
+	mrs	x13, vmpidr_el2
+	mrs	x14, vpidr_el2
+	stp	x13, x14, [x0, #CTX_VMPIDR_EL2]
 
-	mrs	x9, vttbr_el2
-	str	x9, [x0, #CTX_VTTBR_EL2]
+	mrs	x15, vtcr_el2
+	mrs	x16, vttbr_el2
+	stp	x15, x16, [x0, #CTX_VTCR_EL2]
 
 #if CTX_INCLUDE_MTE_REGS
-	mrs	x10, TFSR_EL2
-	str	x10, [x0, #CTX_TFSR_EL2]
+	mrs	x9, TFSR_EL2
+	str	x9, [x0, #CTX_TFSR_EL2]
 #endif
 
 #if ENABLE_MPAM_FOR_LOWER_ELS
-	mrs	x9, MPAM2_EL2
-	mrs	x10, MPAMHCR_EL2
-	stp	x9, x10, [x0, #CTX_MPAM2_EL2]
+	mrs	x10, MPAM2_EL2
+	str	x10, [x0, #CTX_MPAM2_EL2]
 
-	mrs	x11, MPAMVPM0_EL2
-	mrs	x12, MPAMVPM1_EL2
-	stp	x11, x12, [x0, #CTX_MPAMVPM0_EL2]
+	mrs	x11, MPAMHCR_EL2
+	mrs	x12, MPAMVPM0_EL2
+	stp	x11, x12, [x0, #CTX_MPAMHCR_EL2]
 
-	mrs	x13, MPAMVPM2_EL2
-	mrs	x14, MPAMVPM3_EL2
-	stp	x13, x14, [x0, #CTX_MPAMVPM2_EL2]
+	mrs	x13, MPAMVPM1_EL2
+	mrs	x14, MPAMVPM2_EL2
+	stp	x13, x14, [x0, #CTX_MPAMVPM1_EL2]
 
-	mrs	x15, MPAMVPM4_EL2
-	mrs	x16, MPAMVPM5_EL2
-	stp	x15, x16, [x0, #CTX_MPAMVPM4_EL2]
+	mrs	x15, MPAMVPM3_EL2
+	mrs	x16, MPAMVPM4_EL2
+	stp	x15, x16, [x0, #CTX_MPAMVPM3_EL2]
 
-	mrs	x17, MPAMVPM6_EL2
-	mrs	x9, MPAMVPM7_EL2
-	stp	x17, x9, [x0, #CTX_MPAMVPM6_EL2]
+	mrs	x9, MPAMVPM5_EL2
+	mrs	x10, MPAMVPM6_EL2
+	stp	x9, x10, [x0, #CTX_MPAMVPM5_EL2]
 
-	mrs	x10, MPAMVPMV_EL2
-	str	x10, [x0, #CTX_MPAMVPMV_EL2]
+	mrs	x11, MPAMVPM7_EL2
+	mrs	x12, MPAMVPMV_EL2
+	stp	x11, x12, [x0, #CTX_MPAMVPM7_EL2]
 #endif
 
-
 #if ARM_ARCH_AT_LEAST(8, 6)
-	mrs	x11, HAFGRTR_EL2
-	mrs	x12, HDFGRTR_EL2
-	stp	x11, x12, [x0, #CTX_HAFGRTR_EL2]
+	mrs	x13, HAFGRTR_EL2
+	mrs	x14, HDFGRTR_EL2
+	stp	x13, x14, [x0, #CTX_HAFGRTR_EL2]
 
-	mrs	x13, HDFGWTR_EL2
-	mrs	x14, HFGITR_EL2
-	stp	x13, x14, [x0, #CTX_HDFGWTR_EL2]
+	mrs	x15, HDFGWTR_EL2
+	mrs	x16, HFGITR_EL2
+	stp	x15, x16, [x0, #CTX_HDFGWTR_EL2]
 
-	mrs	x15, HFGRTR_EL2
-	mrs	x16, HFGWTR_EL2
-	stp	x15, x16, [x0, #CTX_HFGRTR_EL2]
+	mrs	x9, HFGRTR_EL2
+	mrs	x10, HFGWTR_EL2
+	stp	x9, x10, [x0, #CTX_HFGRTR_EL2]
 
-	mrs	x17, CNTPOFF_EL2
-	str	x17, [x0, #CTX_CNTPOFF_EL2]
+	mrs	x11, CNTPOFF_EL2
+	str	x11, [x0, #CTX_CNTPOFF_EL2]
 #endif
 
 #if ARM_ARCH_AT_LEAST(8, 4)
-	mrs	x9, cnthps_ctl_el2
-	mrs	x10, cnthps_cval_el2
-	stp	x9, x10, [x0, #CTX_CNTHPS_CTL_EL2]
-
-	mrs	x11, cnthps_tval_el2
-	mrs	x12, cnthvs_ctl_el2
-	stp	x11, x12, [x0, #CTX_CNTHPS_TVAL_EL2]
-
-	mrs	x13, cnthvs_cval_el2
-	mrs	x14, cnthvs_tval_el2
-	stp	x13, x14, [x0, #CTX_CNTHVS_CVAL_EL2]
-
-	mrs	x15, cnthv_ctl_el2
-	mrs	x16, cnthv_cval_el2
-	stp	x15, x16, [x0, #CTX_CNTHV_CTL_EL2]
-
-	mrs	x17, cnthv_tval_el2
-	mrs	x9, contextidr_el2
-	stp	x17, x9, [x0, #CTX_CNTHV_TVAL_EL2]
+	mrs	x12, contextidr_el2
+	str	x12, [x0, #CTX_CONTEXTIDR_EL2]
 
 #if CTX_INCLUDE_AARCH32_REGS
-	mrs	x10, sder32_el2
-	str	x10, [x0, #CTX_SDER32_EL2]
+	mrs	x13, sder32_el2
+	str	x13, [x0, #CTX_SDER32_EL2]
 #endif
-
-	mrs	x11, ttbr1_el2
-	str	x11, [x0, #CTX_TTBR1_EL2]
-
-	mrs	x12, vdisr_el2
-	str	x12, [x0, #CTX_VDISR_EL2]
+	mrs	x14, ttbr1_el2
+	mrs	x15, vdisr_el2
+	stp	x14, x15, [x0, #CTX_TTBR1_EL2]
 
 #if CTX_INCLUDE_NEVE_REGS
-	mrs	x13, vncr_el2
-	str	x13, [x0, #CTX_VNCR_EL2]
+	mrs	x16, vncr_el2
+	str	x16, [x0, #CTX_VNCR_EL2]
 #endif
 
-	mrs	x14, vsesr_el2
-	str	x14, [x0, #CTX_VSESR_EL2]
-
-	mrs	x15, vstcr_el2
-	str	x15, [x0, #CTX_VSTCR_EL2]
+	mrs	x9, vsesr_el2
+	mrs	x10, vstcr_el2
+	stp	x9, x10, [x0, #CTX_VSESR_EL2]
 
-	mrs	x16, vsttbr_el2
-	str	x16, [x0, #CTX_VSTTBR_EL2]
-
-	mrs	x17, TRFCR_EL2
-	str	x17, [x0, #CTX_TRFCR_EL2]
+	mrs	x11, vsttbr_el2
+	mrs	x12, TRFCR_EL2
+	stp	x11, x12, [x0, #CTX_VSTTBR_EL2]
 #endif
 
 #if ARM_ARCH_AT_LEAST(8, 5)
-	mrs	x9, scxtnum_el2
-	str	x9, [x0, #CTX_SCXTNUM_EL2]
+	mrs	x13, scxtnum_el2
+	str	x13, [x0, #CTX_SCXTNUM_EL2]
 #endif
 
 	ret
 endfunc el2_sysregs_context_save
 
+
 /* -----------------------------------------------------
  * The following function strictly follows the AArch64
- * PCS to use x9-x17 (temporary caller-saved registers)
+ * PCS to use x9-x16 (temporary caller-saved registers)
  * to restore EL2 system register context.  It assumes
  * that 'x0' is pointing to a 'el2_sys_regs' structure
  * from where the register context will be restored
@@ -246,7 +213,6 @@
  * -----------------------------------------------------
  */
 func el2_sysregs_context_restore
-
 	ldp	x9, x10, [x0, #CTX_ACTLR_EL2]
 	msr	actlr_el2, x9
 	msr	afsr0_el2, x10
@@ -257,74 +223,66 @@
 
 	ldp	x13, x14, [x0, #CTX_CNTHCTL_EL2]
 	msr	cnthctl_el2, x13
-	msr	cnthp_ctl_el2, x14
-
-	ldp	x15, x16, [x0, #CTX_CNTHP_CVAL_EL2]
-	msr	cnthp_cval_el2, x15
-	msr	cnthp_tval_el2, x16
+	msr	cntvoff_el2, x14
 
-	ldp	x17, x9, [x0, #CTX_CNTVOFF_EL2]
-	msr	cntvoff_el2, x17
-	msr	cptr_el2, x9
+	ldr	x15, [x0, #CTX_CPTR_EL2]
+	msr	cptr_el2, x15
 
 #if CTX_INCLUDE_AARCH32_REGS
-	ldp	x10, x11, [x0, #CTX_DBGVCR32_EL2]
-	msr	dbgvcr32_el2, x10
-#else
-	ldr	x11, [x0, #CTX_ELR_EL2]
+	ldr	x16, [x0, #CTX_DBGVCR32_EL2]
+	msr	dbgvcr32_el2, x16
 #endif
-	msr	elr_el2, x11
 
-	ldp	x14, x15, [x0, #CTX_ESR_EL2]
-	msr	esr_el2, x14
-	msr	far_el2, x15
+	ldp	x9, x10, [x0, #CTX_ELR_EL2]
+	msr	elr_el2, x9
+	msr	esr_el2, x10
 
-	ldp	x16, x17, [x0, #CTX_HACR_EL2]
-	msr	hacr_el2, x16
-	msr	hcr_el2, x17
+	ldp	x11, x12, [x0, #CTX_FAR_EL2]
+	msr	far_el2, x11
+	msr	hacr_el2, x12
 
-	ldp	x9, x10, [x0, #CTX_HPFAR_EL2]
-	msr	hpfar_el2, x9
-	msr	hstr_el2, x10
+	ldp	x13, x14, [x0, #CTX_HCR_EL2]
+	msr	hcr_el2, x13
+	msr	hpfar_el2, x14
 
-	ldp	x11, x12, [x0, #CTX_ICC_SRE_EL2]
-	msr	ICC_SRE_EL2, x11
-	msr	ICH_HCR_EL2, x12
+	ldp	x15, x16, [x0, #CTX_HSTR_EL2]
+	msr	hstr_el2, x15
+	msr	ICC_SRE_EL2, x16
 
-	ldp	x13, x14, [x0, #CTX_ICH_VMCR_EL2]
-	msr	ICH_VMCR_EL2, x13
-	msr	mair_el2, x14
+	ldp	x9, x10, [x0, #CTX_ICH_HCR_EL2]
+	msr	ICH_HCR_EL2, x9
+	msr	ICH_VMCR_EL2, x10
+
+	ldp	x11, x12, [x0, #CTX_MAIR_EL2]
+	msr	mair_el2, x11
+	msr	mdcr_el2, x12
 
 #if ENABLE_SPE_FOR_LOWER_ELS
-	ldp	x15, x16, [x0, #CTX_MDCR_EL2]
-	msr	PMSCR_EL2, x16
-#else
-	ldr	x15, [x0, #CTX_MDCR_EL2]
+	ldr	x13, [x0, #CTX_PMSCR_EL2]
+	msr	PMSCR_EL2, x13
 #endif
-	msr	mdcr_el2, x15
-
-	ldp	x17, x9, [x0, #CTX_SCTLR_EL2]
-	msr	sctlr_el2, x17
-	msr	spsr_el2, x9
+	ldr	x14, [x0, #CTX_SCTLR_EL2]
+	msr	sctlr_el2, x14
 
-	ldp	x10, x11, [x0, #CTX_SP_EL2]
-	msr	sp_el2, x10
-	msr	tcr_el2, x11
+	ldp	x15, x16, [x0, #CTX_SPSR_EL2]
+	msr	spsr_el2, x15
+	msr	sp_el2, x16
 
-	ldp	x12, x13, [x0, #CTX_TPIDR_EL2]
-	msr	tpidr_el2, x12
-	msr	ttbr0_el2, x13
+	ldp	x9, x10, [x0, #CTX_TCR_EL2]
+	msr	tcr_el2, x9
+	msr	tpidr_el2, x10
 
-	ldp	x13, x14, [x0, #CTX_VBAR_EL2]
-	msr	vbar_el2, x13
-	msr	vmpidr_el2, x14
+	ldp	x11, x12, [x0, #CTX_TTBR0_EL2]
+	msr	ttbr0_el2, x11
+	msr	vbar_el2, x12
 
-	ldp	x15, x16, [x0, #CTX_VPIDR_EL2]
-	msr	vpidr_el2, x15
-	msr	vtcr_el2, x16
+	ldp	x13, x14, [x0, #CTX_VMPIDR_EL2]
+	msr	vmpidr_el2, x13
+	msr	vpidr_el2, x14
 
-	ldr	x17, [x0, #CTX_VTTBR_EL2]
-	msr	vttbr_el2, x17
+	ldp	x15, x16, [x0, #CTX_VTCR_EL2]
+	msr	vtcr_el2, x15
+	msr	vttbr_el2, x16
 
 #if CTX_INCLUDE_MTE_REGS
 	ldr	x9, [x0, #CTX_TFSR_EL2]
@@ -332,100 +290,76 @@
 #endif
 
 #if ENABLE_MPAM_FOR_LOWER_ELS
-	ldp	x10, x11, [x0, #CTX_MPAM2_EL2]
+	ldr	x10, [x0, #CTX_MPAM2_EL2]
 	msr	MPAM2_EL2, x10
-	msr	MPAMHCR_EL2, x11
 
-	ldp	x12, x13, [x0, #CTX_MPAMVPM0_EL2]
+	ldp	x11, x12, [x0, #CTX_MPAMHCR_EL2]
+	msr	MPAMHCR_EL2, x11
 	msr	MPAMVPM0_EL2, x12
-	msr	MPAMVPM1_EL2, x13
 
-	ldp	x14, x15, [x0, #CTX_MPAMVPM2_EL2]
+	ldp	x13, x14, [x0, #CTX_MPAMVPM1_EL2]
+	msr	MPAMVPM1_EL2, x13
 	msr	MPAMVPM2_EL2, x14
-	msr	MPAMVPM3_EL2, x15
 
-	ldp	x16, x17, [x0, #CTX_MPAMVPM4_EL2]
+	ldp	x15, x16, [x0, #CTX_MPAMVPM3_EL2]
+	msr	MPAMVPM3_EL2, x15
 	msr	MPAMVPM4_EL2, x16
-	msr	MPAMVPM5_EL2, x17
 
-	ldp	x9, x10, [x0, #CTX_MPAMVPM6_EL2]
-	msr	MPAMVPM6_EL2, x9
-	msr	MPAMVPM7_EL2, x10
+	ldp	x9, x10, [x0, #CTX_MPAMVPM5_EL2]
+	msr	MPAMVPM5_EL2, x9
+	msr	MPAMVPM6_EL2, x10
 
-	ldr	x11, [x0, #CTX_MPAMVPMV_EL2]
-	msr	MPAMVPMV_EL2, x11
+	ldp	x11, x12, [x0, #CTX_MPAMVPM7_EL2]
+	msr	MPAMVPM7_EL2, x11
+	msr	MPAMVPMV_EL2, x12
 #endif
 
 #if ARM_ARCH_AT_LEAST(8, 6)
-	ldp	x12, x13, [x0, #CTX_HAFGRTR_EL2]
-	msr	HAFGRTR_EL2, x12
-	msr	HDFGRTR_EL2, x13
+	ldp	x13, x14, [x0, #CTX_HAFGRTR_EL2]
+	msr	HAFGRTR_EL2, x13
+	msr	HDFGRTR_EL2, x14
 
-	ldp	x14, x15, [x0, #CTX_HDFGWTR_EL2]
-	msr	HDFGWTR_EL2, x14
-	msr	HFGITR_EL2, x15
+	ldp	x15, x16, [x0, #CTX_HDFGWTR_EL2]
+	msr	HDFGWTR_EL2, x15
+	msr	HFGITR_EL2, x16
 
-	ldp	x16, x17, [x0, #CTX_HFGRTR_EL2]
-	msr	HFGRTR_EL2, x16
-	msr	HFGWTR_EL2, x17
+	ldp	x9, x10, [x0, #CTX_HFGRTR_EL2]
+	msr	HFGRTR_EL2, x9
+	msr	HFGWTR_EL2, x10
 
-	ldr	x9, [x0, #CTX_CNTPOFF_EL2]
-	msr	CNTPOFF_EL2, x9
+	ldr	x11, [x0, #CTX_CNTPOFF_EL2]
+	msr	CNTPOFF_EL2, x11
 #endif
 
 #if ARM_ARCH_AT_LEAST(8, 4)
-	ldp	x10, x11, [x0, #CTX_CNTHPS_CTL_EL2]
-	msr	cnthps_ctl_el2, x10
-	msr	cnthps_cval_el2, x11
-
-	ldp	x12, x13, [x0, #CTX_CNTHPS_TVAL_EL2]
-	msr	cnthps_tval_el2, x12
-	msr	cnthvs_ctl_el2, x13
-
-	ldp	x14, x15, [x0, #CTX_CNTHVS_CVAL_EL2]
-	msr	cnthvs_cval_el2, x14
-	msr	cnthvs_tval_el2, x15
-
-	ldp	x16, x17, [x0, #CTX_CNTHV_CTL_EL2]
-	msr	cnthv_ctl_el2, x16
-	msr	cnthv_cval_el2, x17
-
-	ldp	x9, x10, [x0, #CTX_CNTHV_TVAL_EL2]
-	msr	cnthv_tval_el2, x9
-	msr	contextidr_el2, x10
+	ldr	x12, [x0, #CTX_CONTEXTIDR_EL2]
+	msr	contextidr_el2, x12
 
 #if CTX_INCLUDE_AARCH32_REGS
-	ldr	x11, [x0, #CTX_SDER32_EL2]
-	msr	sder32_el2, x11
+	ldr	x13, [x0, #CTX_SDER32_EL2]
+	msr	sder32_el2, x13
 #endif
-
-	ldr	x12, [x0, #CTX_TTBR1_EL2]
-	msr	ttbr1_el2, x12
-
-	ldr	x13, [x0, #CTX_VDISR_EL2]
-	msr	vdisr_el2, x13
+	ldp	x14, x15, [x0, #CTX_TTBR1_EL2]
+	msr	ttbr1_el2, x14
+	msr	vdisr_el2, x15
 
 #if CTX_INCLUDE_NEVE_REGS
-	ldr	x14, [x0, #CTX_VNCR_EL2]
-	msr	vncr_el2, x14
+	ldr	x16, [x0, #CTX_VNCR_EL2]
+	msr	vncr_el2, x16
 #endif
 
-	ldr	x15, [x0, #CTX_VSESR_EL2]
-	msr	vsesr_el2, x15
+	ldp	x9, x10, [x0, #CTX_VSESR_EL2]
+	msr	vsesr_el2, x9
+	msr	vstcr_el2, x10
 
-	ldr	x16, [x0, #CTX_VSTCR_EL2]
-	msr	vstcr_el2, x16
-
-	ldr	x17, [x0, #CTX_VSTTBR_EL2]
-	msr	vsttbr_el2, x17
-
-	ldr	x9, [x0, #CTX_TRFCR_EL2]
-	msr	TRFCR_EL2, x9
+	ldp	x11, x12, [x0, #CTX_VSTTBR_EL2]
+	msr	vsttbr_el2, x11
+	msr	TRFCR_EL2, x12
 #endif
 
 #if ARM_ARCH_AT_LEAST(8, 5)
-	ldr	x10, [x0, #CTX_SCXTNUM_EL2]
-	msr	scxtnum_el2, x10
+	ldr	x13, [x0, #CTX_SCXTNUM_EL2]
+	msr	scxtnum_el2, x13
 #endif
 
 	ret
diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk
index 3a5f74d..7ce4ba3 100644
--- a/plat/arm/board/arm_fpga/platform.mk
+++ b/plat/arm/board/arm_fpga/platform.mk
@@ -70,7 +70,8 @@
 				lib/cpus/aarch64/cortex_klein.S		\
 				lib/cpus/aarch64/cortex_matterhorn.S	\
 				lib/cpus/aarch64/cortex_makalu.S	\
-				lib/cpus/aarch64/cortex_makalu_elp.S
+				lib/cpus/aarch64/cortex_makalu_elp.S    \
+				lib/cpus/aarch64/cortex_a78c.S
 
 # AArch64/AArch32 cores
 	FPGA_CPU_LIBS	+=	lib/cpus/aarch64/cortex_a55.S	\
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 53145f2..20d80ed 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -136,7 +136,8 @@
 					lib/cpus/aarch64/cortex_makalu.S	\
 					lib/cpus/aarch64/cortex_makalu_elp.S	\
 					lib/cpus/aarch64/cortex_a65.S		\
-					lib/cpus/aarch64/cortex_a65ae.S
+					lib/cpus/aarch64/cortex_a65ae.S		\
+					lib/cpus/aarch64/cortex_a78c.S
 	endif
 	# AArch64/AArch32 cores
 	FVP_CPU_LIBS	+=	lib/cpus/aarch64/cortex_a55.S		\
diff --git a/plat/arm/common/arm_image_load.c b/plat/arm/common/arm_image_load.c
index ed7f1f5..ebf6dff 100644
--- a/plat/arm/common/arm_image_load.c
+++ b/plat/arm/common/arm_image_load.c
@@ -38,38 +38,36 @@
  ******************************************************************************/
 static void plat_add_sp_images_load_info(struct bl_load_info *load_info)
 {
-	bl_load_info_node_t *node_info = load_info->head;
-	unsigned int index = 0;
+	bl_load_info_node_t *curr_node = load_info->head;
+	bl_load_info_node_t *prev_node;
 
-	if (sp_mem_params_descs[index].image_id == 0) {
+	/* Shortcut for empty SP list */
+	if (sp_mem_params_descs[0].image_id == 0) {
 		ERROR("No Secure Partition Image available\n");
 		return;
 	}
 
 	/* Traverse through the bl images list */
 	do {
-		node_info = node_info->next_load_info;
-	} while (node_info->next_load_info != NULL);
+		curr_node = curr_node->next_load_info;
+	} while (curr_node->next_load_info != NULL);
 
-	for (; index < MAX_SP_IDS; index++) {
-		/* Populate the image information */
-		node_info->image_id = sp_mem_params_descs[index].image_id;
-		node_info->image_info = &sp_mem_params_descs[index].image_info;
-
-		if ((index + 1U) == MAX_SP_IDS) {
-			INFO("Reached Max number of SPs\n");
-			return;
-		}
+	prev_node = curr_node;
 
-		if (sp_mem_params_descs[index + 1U].image_id == 0) {
+	for (unsigned int index = 0; index < MAX_SP_IDS; index++) {
+		if (sp_mem_params_descs[index].image_id == 0) {
 			return;
 		}
-
-		node_info->next_load_info =
-			&sp_mem_params_descs[index + 1U].load_node_mem;
-		node_info = node_info->next_load_info;
+		curr_node = &sp_mem_params_descs[index].load_node_mem;
+		/* Populate the image information */
+		curr_node->image_id = sp_mem_params_descs[index].image_id;
+		curr_node->image_info = &sp_mem_params_descs[index].image_info;
 
+		prev_node->next_load_info = curr_node;
+		prev_node = curr_node;
 	}
+
+	INFO("Reached Max number of SPs\n");
 }
 #endif
 
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_image_load.c b/plat/imx/imx8m/imx8mm/imx8mm_image_load.c
new file mode 100644
index 0000000..3a03069
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/imx8mm_image_load.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/bl_common.h>
+#include <common/desc_image_load.h>
+
+#include <platform_def.h>
+#include <plat/common/platform.h>
+
+void plat_flush_next_bl_params(void)
+{
+	flush_bl_params_desc();
+}
+
+bl_load_info_t *plat_get_bl_image_load_info(void)
+{
+	return get_bl_load_info_from_mem_params_desc();
+}
+
+bl_params_t *plat_get_next_bl_params(void)
+{
+	return get_next_bl_params_from_mem_params_desc();
+}
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_io_storage.c b/plat/imx/imx8m/imx8mm/imx8mm_io_storage.c
new file mode 100644
index 0000000..ff6687e
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/imx8mm_io_storage.c
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * 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_driver.h>
+#include <drivers/io/io_memmap.h>
+#include <drivers/mmc.h>
+#include <lib/utils_def.h>
+#include <tbbr_img_def.h>
+#include <tools_share/firmware_image_package.h>
+
+#include <platform_def.h>
+
+static const io_dev_connector_t *fip_dev_con;
+static uintptr_t fip_dev_handle;
+
+#ifndef IMX8MM_FIP_MMAP
+static const io_dev_connector_t *mmc_dev_con;
+static uintptr_t mmc_dev_handle;
+
+static const io_block_spec_t mmc_fip_spec = {
+	.offset = IMX8MM_FIP_MMC_BASE,
+	.length = IMX8MM_FIP_SIZE
+};
+
+static const io_block_dev_spec_t mmc_dev_spec = {
+	/* It's used as temp buffer in block driver. */
+	.buffer		= {
+		.offset	= IMX8MM_FIP_BASE,
+		/* do we need a new value? */
+		.length = IMX8MM_FIP_SIZE
+	},
+	.ops		= {
+		.read	= mmc_read_blocks,
+		.write	= mmc_write_blocks,
+	},
+	.block_size	= MMC_BLOCK_SIZE,
+};
+
+static int open_mmc(const uintptr_t spec);
+
+#else
+static const io_dev_connector_t *memmap_dev_con;
+static uintptr_t memmap_dev_handle;
+
+static const io_block_spec_t fip_block_spec = {
+	.offset = IMX8MM_FIP_BASE,
+	.length = IMX8MM_FIP_SIZE
+};
+static int open_memmap(const uintptr_t spec);
+#endif
+
+static int open_fip(const uintptr_t spec);
+
+static const io_uuid_spec_t bl31_uuid_spec = {
+	.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
+};
+
+static const io_uuid_spec_t bl32_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32,
+};
+
+static const io_uuid_spec_t bl32_extra1_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
+};
+
+static const io_uuid_spec_t bl32_extra2_uuid_spec = {
+	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
+};
+
+static const io_uuid_spec_t bl33_uuid_spec = {
+	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
+};
+
+#if TRUSTED_BOARD_BOOT
+static const io_uuid_spec_t tb_fw_cert_uuid_spec = {
+	.uuid = UUID_TRUSTED_BOOT_FW_CERT,
+};
+
+static const io_uuid_spec_t trusted_key_cert_uuid_spec = {
+	.uuid = UUID_TRUSTED_KEY_CERT,
+};
+
+static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = {
+	.uuid = UUID_SOC_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = {
+	.uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t tos_fw_cert_uuid_spec = {
+	.uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t soc_fw_content_cert_uuid_spec = {
+	.uuid = UUID_SOC_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = {
+	.uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t nt_fw_cert_uuid_spec = {
+	.uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT,
+};
+#endif /* TRUSTED_BOARD_BOOT */
+
+struct plat_io_policy {
+	uintptr_t *dev_handle;
+	uintptr_t image_spec;
+	int (*check)(const uintptr_t spec);
+};
+
+static const struct plat_io_policy policies[] = {
+#ifndef IMX8MM_FIP_MMAP
+	[FIP_IMAGE_ID] = {
+		&mmc_dev_handle,
+		(uintptr_t)&mmc_fip_spec,
+		open_mmc
+	},
+#else
+	[FIP_IMAGE_ID] = {
+		&memmap_dev_handle,
+		(uintptr_t)&fip_block_spec,
+		open_memmap
+	},
+#endif
+	[BL31_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl31_uuid_spec,
+		open_fip
+	},
+	[BL32_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_uuid_spec,
+		open_fip
+	},
+	[BL32_EXTRA1_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_extra1_uuid_spec,
+		open_fip
+	},
+	[BL32_EXTRA2_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl32_extra2_uuid_spec,
+		open_fip
+	},
+	[BL33_IMAGE_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&bl33_uuid_spec,
+		open_fip
+	},
+#if TRUSTED_BOARD_BOOT
+	[TRUSTED_BOOT_FW_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&tb_fw_cert_uuid_spec,
+		open_fip
+	},
+	[SOC_FW_KEY_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&soc_fw_key_cert_uuid_spec,
+		open_fip
+	},
+	[TRUSTED_KEY_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&trusted_key_cert_uuid_spec,
+		open_fip
+	},
+	[TRUSTED_OS_FW_KEY_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&tos_fw_key_cert_uuid_spec,
+		open_fip
+	},
+	[NON_TRUSTED_FW_KEY_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&nt_fw_key_cert_uuid_spec,
+		open_fip
+	},
+	[SOC_FW_CONTENT_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&soc_fw_content_cert_uuid_spec,
+		open_fip
+	},
+	[TRUSTED_OS_FW_CONTENT_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&tos_fw_cert_uuid_spec,
+		open_fip
+	},
+	[NON_TRUSTED_FW_CONTENT_CERT_ID] = {
+		&fip_dev_handle,
+		(uintptr_t)&nt_fw_cert_uuid_spec,
+		open_fip
+	},
+#endif /* TRUSTED_BOARD_BOOT */
+};
+
+static int open_fip(const uintptr_t spec)
+{
+	int result;
+	uintptr_t local_image_handle;
+
+	/* See if a Firmware Image Package is available */
+	result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
+	if (result == 0) {
+		result = io_open(fip_dev_handle, spec, &local_image_handle);
+		if (result == 0) {
+			VERBOSE("Using FIP\n");
+			io_close(local_image_handle);
+		}
+	}
+	return result;
+}
+
+#ifndef IMX8MM_FIP_MMAP
+static int open_mmc(const uintptr_t spec)
+{
+	int result;
+	uintptr_t local_handle;
+
+	result = io_dev_init(mmc_dev_handle, (uintptr_t)NULL);
+	if (result == 0) {
+		result = io_open(mmc_dev_handle, spec, &local_handle);
+		if (result == 0) {
+			io_close(local_handle);
+		}
+	}
+	return result;
+}
+#else
+static int open_memmap(const uintptr_t spec)
+{
+	int result;
+	uintptr_t local_image_handle;
+
+	result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
+	if (result == 0) {
+		result = io_open(memmap_dev_handle, spec, &local_image_handle);
+		if (result == 0) {
+			VERBOSE("Using Memmap\n");
+			io_close(local_image_handle);
+		}
+	}
+	return result;
+}
+#endif
+
+int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+			  uintptr_t *image_spec)
+{
+	int result;
+	const struct plat_io_policy *policy;
+
+	assert(image_id < ARRAY_SIZE(policies));
+
+	policy = &policies[image_id];
+	result = policy->check(policy->image_spec);
+	assert(result == 0);
+
+	*image_spec = policy->image_spec;
+	*dev_handle = *policy->dev_handle;
+
+	return result;
+}
+
+void plat_imx8mm_io_setup(void)
+{
+	int result __unused;
+
+#ifndef IMX8MM_FIP_MMAP
+	result = register_io_dev_block(&mmc_dev_con);
+	assert(result == 0);
+
+	result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_dev_spec,
+			     &mmc_dev_handle);
+	assert(result == 0);
+
+#else
+	result = register_io_dev_memmap(&memmap_dev_con);
+	assert(result == 0);
+
+	result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
+			     &memmap_dev_handle);
+	assert(result == 0);
+#endif
+
+	result = register_io_dev_fip(&fip_dev_con);
+	assert(result == 0);
+
+	result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
+			     &fip_dev_handle);
+	assert(result == 0);
+}
diff --git a/plat/imx/imx8m/imx8mm/include/imx8mm_private.h b/plat/imx/imx8m/imx8mm/include/imx8mm_private.h
new file mode 100644
index 0000000..52d13f0
--- /dev/null
+++ b/plat/imx/imx8m/imx8mm/include/imx8mm_private.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IMX8MM_PRIVATE_H
+#define IMX8MM_PRIVATE_H
+
+/*******************************************************************************
+ * Function and variable prototypes
+ ******************************************************************************/
+void plat_imx8mm_io_setup(void);
+
+#endif /* IMX8MM_PRIVATE_H */
diff --git a/plat/imx/imx8m/imx8mm/include/platform_def.h b/plat/imx/imx8m/imx8mm/include/platform_def.h
index 1041459..ec915ad 100644
--- a/plat/imx/imx8m/imx8mm/include/platform_def.h
+++ b/plat/imx/imx8m/imx8mm/include/platform_def.h
@@ -1,9 +1,11 @@
 /*
- * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include <common/tbbr/tbbr_img_def.h>
+
 #define PLATFORM_LINKER_FORMAT		"elf64-littleaarch64"
 #define PLATFORM_LINKER_ARCH		aarch64
 
@@ -34,11 +36,27 @@
 #define PLAT_SDEI_NORMAL_PRI		0x20
 #define PLAT_SDEI_SGI_PRIVATE		U(9)
 
+#if defined(NEED_BL2)
+#define BL2_BASE			U(0x920000)
+#define BL2_LIMIT			U(0x940000)
+#define BL31_BASE			U(0x900000)
+#define BL31_LIMIT			U(0x920000)
+#define IMX8MM_FIP_BASE			U(0x40310000)
+#define IMX8MM_FIP_SIZE			U(0x000200000)
+#define IMX8MM_FIP_LIMIT		U(FIP_BASE + FIP_SIZE)
+
+/* Define FIP image location on eMMC */
+#define IMX8MM_FIP_MMC_BASE		U(0x100000)
+
+#define PLAT_IMX8MM_BOOT_MMC_BASE	U(0x30B50000) /* SD */
+#else
 #define BL31_BASE			U(0x920000)
 #define BL31_LIMIT			U(0x940000)
+#endif
 
 /* non-secure uboot base */
 #define PLAT_NS_IMAGE_OFFSET		U(0x40200000)
+#define PLAT_NS_IMAGE_SIZE		U(0x00100000)
 
 /* GICv3 base address */
 #define PLAT_GICD_BASE			U(0x38800000)
@@ -127,3 +145,7 @@
 #define COUNTER_FREQUENCY		8000000 /* 8MHz */
 
 #define IMX_WDOG_B_RESET
+
+#define MAX_IO_HANDLES			3U
+#define MAX_IO_DEVICES			2U
+#define MAX_IO_BLOCK_DEVICES		1U