Merge "fix(sme): add missing ISBs" into integration
diff --git a/Makefile b/Makefile
index 8adc0d0..b42e4ec 100644
--- a/Makefile
+++ b/Makefile
@@ -148,7 +148,10 @@
 CTX_INCLUDE_EL2_REGS := 1
 CTX_INCLUDE_AARCH32_REGS := 0
 ARM_ARCH_MAJOR := 8
-ARM_ARCH_MINOR := 6
+ARM_ARCH_MINOR := 5
+ENABLE_FEAT_ECV = 1
+ENABLE_FEAT_FGT = 1
+
 endif
 
 # USE_SPINLOCK_CAS requires AArch64 build
diff --git a/docs/about/maintainers.rst b/docs/about/maintainers.rst
index 9ce6ff2..a980ed9 100644
--- a/docs/about/maintainers.rst
+++ b/docs/about/maintainers.rst
@@ -162,6 +162,18 @@
 :|F|: include/drivers/ufs.h
 :|F|: include/drivers/synopsys/dw_mmc.h
 
+Arm® Ethos™-N NPU driver
+^^^^^^^^^^^^^^^^^^^^^^^^
+:|M|: Joshua Slater <joshua.slater@arm.com>
+:|G|: `jslater8`_
+:|M|: Mikael Olsson <mikael.olsson@arm.com>
+:|G|: `mikaelolsson-arm`_
+:|F|: drivers/arm/ethosn/
+:|F|: include/drivers/arm/ethosn.h
+:|F|: plat/arm/common/fconf/fconf_ethosn_getter.c
+:|F|: include/plat/arm/common/fconf_ethosn_getter.h
+:|F|: fdts/juno-ethosn.dtsi
+
 JTAG DCC console driver
 ^^^^^^^^^^^^^^^^^^^^^^^
 :M: Michal Simek <michal.simek@amd.com>
@@ -850,6 +862,7 @@
 .. _JackyBai: https://github.com/JackyBai
 .. _jcorbier: https://github.com/jcorbier
 .. _jenswi-linaro: https://github.com/jenswi-linaro
+.. _jslater8: https://github.com/jslater8
 .. _jwerner-chromium: https://github.com/jwerner-chromium
 .. _kostapr: https://github.com/kostapr
 .. _lachitp: https://github.com/lachitp
@@ -857,6 +870,7 @@
 .. _marex: https://github.com/marex
 .. _masahir0y: https://github.com/masahir0y
 .. _michalsimek: https://github.com/michalsimek
+.. _mikaelolsson-arm: https://github.com/mikaelolsson-arm
 .. _mmind: https://github.com/mmind
 .. _MrVan: https://github.com/MrVan
 .. _mtk-rex-bc-chen: https://github.com/mtk-rex-bc-chen
diff --git a/docs/design/cpu-specific-build-macros.rst b/docs/design/cpu-specific-build-macros.rst
index f736e2d..721c399 100644
--- a/docs/design/cpu-specific-build-macros.rst
+++ b/docs/design/cpu-specific-build-macros.rst
@@ -616,6 +616,10 @@
    Cortex-A510 CPU. This needs to applied for revisions r0p0, r0p1, r0p2,
    r0p3, r1p0, r1p1, and is fixed in r1p2.
 
+-  ``ERRATA_A510_2666669``: This applies errata 2666669 workaround to
+   Cortex-A510 CPU. This needs to applied for revisions r0p0, r0p1, r0p2,
+   r0p3, r1p0, r1p1. It is fixed in r1p2.
+
 DSU Errata Workarounds
 ----------------------
 
diff --git a/docs/plat/arm/arm-build-options.rst b/docs/plat/arm/arm-build-options.rst
index afe89b9..407c04b 100644
--- a/docs/plat/arm/arm-build-options.rst
+++ b/docs/plat/arm/arm-build-options.rst
@@ -92,7 +92,7 @@
    SBROM library must be specified via ``CCSBROM_LIB_PATH`` flag.
 
 -  ``ARM_ETHOSN_NPU_DRIVER``: boolean option to enable a SiP service that can
-   configure an Arm Ethos-N NPU. To use this service the target platform's
+   configure an Arm® Ethos™-N NPU. To use this service the target platform's
    ``HW_CONFIG`` must include the device tree nodes for the NPU. Currently, only
    the Arm Juno platform has this included in its ``HW_CONFIG`` and the platform
    only loads the ``HW_CONFIG`` in AArch64 builds. Default is 0.
diff --git a/docs/plat/imx8m.rst b/docs/plat/imx8m.rst
index 101d52b..f8071f7 100644
--- a/docs/plat/imx8m.rst
+++ b/docs/plat/imx8m.rst
@@ -68,3 +68,46 @@
 with a DTB overlay. The overlay will be put at PLAT_IMX8M_DTO_BASE with
 maximum size PLAT_IMX8M_DTO_MAX_SIZE. Then in U-boot we can apply the DTB
 overlay and let U-boot to parse the event log and update the PCRs.
+
+High Assurance Boot (HABv4)
+---------------------------
+
+All actively maintained platforms have a support for High Assurance
+Boot (HABv4), which is implemented via ROM Vector Table (RVT) API to
+extend the Root-of-Trust beyond the SPL. Those calls are done via SMC
+and are executed in EL3, with results returned back to original caller.
+
+Note on DRAM Memory Mapping
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There is a special case of mapping the DRAM: entire DRAM available on the
+platform is mapped into the EL3 with MT_RW attributes.
+
+Mapping the entire DRAM allows the usage of 2MB block mapping in Level-2
+Translation Table entries, which use less Page Table Entries (PTEs). If
+Level-3 PTE mapping is used instead then additional PTEs would be required,
+which leads to the increase of translation table size.
+
+Due to the fact that the size of SRAM is limited on some platforms in the
+family it should rather be avoided creating additional Level-3 mapping and
+introduce more PTEs, hence the implementation uses Level-2 mapping which
+maps entire DRAM space.
+
+The reason for the MT_RW attribute mapping scheme is the fact that the SMC
+API to get the status and events is called from NS world passing destination
+pointers which are located in DRAM. Mapping DRAM without MT_RW permissions
+causes those locations not to be filled, which in turn causing EL1&0 software
+not to receive replies.
+
+Therefore, DRAM mapping is done with MT_RW attributes, as it is required for
+data exchange between EL3 and EL1&0 software.
+
+Reference Documentation
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Details on HABv4 usage and implementation could be found in following documents:
+
+- AN4581: "i.MX Secure Boot on HABv4 Supported Devices",  Rev. 4 - June 2020
+- AN12263: "HABv4 RVT Guidelines and Recommendations", Rev. 1 - 06/2020
+- "HABv4 API Reference Manual". This document in the part of NXP Code Signing Tool (CST) distribution.
+
diff --git a/drivers/arm/ethosn/ethosn_smc.c b/drivers/arm/ethosn/ethosn_smc.c
index 60364cd..915a0d8 100644
--- a/drivers/arm/ethosn/ethosn_smc.c
+++ b/drivers/arm/ethosn/ethosn_smc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,18 +12,17 @@
 #include <drivers/arm/ethosn.h>
 #include <drivers/delay_timer.h>
 #include <lib/mmio.h>
+#include <lib/utils_def.h>
 #include <plat/arm/common/fconf_ethosn_getter.h>
 
 /*
- * Number of Arm Ethos-N NPU (NPU) cores available for a
- * particular parent device
+ * Number of Arm(R) Ethos(TM)-N NPU (NPU) devices available
  */
-#define ETHOSN_NUM_CORES \
-	FCONF_GET_PROPERTY(hw_config, ethosn_config, num_cores)
+#define ETHOSN_NUM_DEVICES \
+	FCONF_GET_PROPERTY(hw_config, ethosn_config, num_devices)
 
-/* Address to an NPU core  */
-#define ETHOSN_CORE_ADDR(core_idx) \
-	FCONF_GET_PROPERTY(hw_config, ethosn_core_addr, core_idx)
+#define ETHOSN_GET_DEVICE(dev_idx) \
+	FCONF_GET_PROPERTY(hw_config, ethosn_device, dev_idx)
 
 /* NPU core sec registry address */
 #define ETHOSN_CORE_SEC_REG(core_addr, reg_offset) \
@@ -40,9 +39,6 @@
 #define SEC_SECCTLR_REG			U(0x0010)
 #define SEC_SECCTLR_VAL			U(0x3)
 
-#define SEC_DEL_MMUSID_REG		U(0x2008)
-#define SEC_DEL_MMUSID_VAL		U(0x3FFFF)
-
 #define SEC_DEL_ADDR_EXT_REG		U(0x201C)
 #define SEC_DEL_ADDR_EXT_VAL		U(0x15)
 
@@ -50,17 +46,63 @@
 #define SEC_SYSCTRL0_SOFT_RESET		U(3U << 29)
 #define SEC_SYSCTRL0_HARD_RESET		U(1U << 31)
 
-static bool ethosn_is_core_addr_valid(uintptr_t core_addr)
+#define SEC_MMUSID_REG_BASE		U(0x3008)
+#define SEC_MMUSID_OFFSET		U(0x1000)
+
+static bool ethosn_get_device_and_core(uintptr_t core_addr,
+				       const struct ethosn_device_t **dev_match,
+				       const struct ethosn_core_t **core_match)
 {
-	for (uint32_t core_idx = 0U; core_idx < ETHOSN_NUM_CORES; core_idx++) {
-		if (ETHOSN_CORE_ADDR(core_idx) == core_addr) {
-			return true;
+	uint32_t dev_idx;
+	uint32_t core_idx;
+
+	for (dev_idx = 0U; dev_idx < ETHOSN_NUM_DEVICES; ++dev_idx) {
+		const struct ethosn_device_t *dev = ETHOSN_GET_DEVICE(dev_idx);
+
+		for (core_idx = 0U; core_idx < dev->num_cores; ++core_idx) {
+			const struct ethosn_core_t *core = &(dev->cores[core_idx]);
+
+			if (core->addr == core_addr) {
+				*dev_match = dev;
+				*core_match = core;
+				return true;
+			}
 		}
 	}
 
+	WARN("ETHOSN: Unknown core address given to SMC call.\n");
 	return false;
 }
 
+static void ethosn_configure_smmu_streams(const struct ethosn_device_t *device,
+					  const struct ethosn_core_t *core,
+					  uint32_t asset_alloc_idx)
+{
+	const struct ethosn_main_allocator_t *main_alloc =
+		&(core->main_allocator);
+	const struct ethosn_asset_allocator_t *asset_alloc =
+		&(device->asset_allocators[asset_alloc_idx]);
+	const uint32_t streams[9] = {
+		main_alloc->firmware.stream_id,
+		main_alloc->working_data.stream_id,
+		asset_alloc->command_stream.stream_id,
+		0U, /* Not used*/
+		main_alloc->firmware.stream_id,
+		asset_alloc->weight_data.stream_id,
+		asset_alloc->buffer_data.stream_id,
+		asset_alloc->intermediate_data.stream_id,
+		asset_alloc->buffer_data.stream_id
+	};
+	size_t i;
+
+	for (i = 0U; i < ARRAY_SIZE(streams); ++i) {
+		const uintptr_t reg_addr = SEC_MMUSID_REG_BASE +
+			(SEC_MMUSID_OFFSET * i);
+		mmio_write_32(ETHOSN_CORE_SEC_REG(core->addr, reg_addr),
+			      streams[i]);
+	}
+}
+
 static void ethosn_delegate_to_ns(uintptr_t core_addr)
 {
 	mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SECCTLR_REG),
@@ -69,9 +111,6 @@
 	mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG),
 			SEC_DEL_VAL);
 
-	mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_MMUSID_REG),
-			SEC_DEL_MMUSID_VAL);
-
 	mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_ADDR_EXT_REG),
 			SEC_DEL_ADDR_EXT_VAL);
 }
@@ -112,7 +151,7 @@
 
 uintptr_t ethosn_smc_handler(uint32_t smc_fid,
 			     u_register_t core_addr,
-			     u_register_t x2,
+			     u_register_t asset_alloc_idx,
 			     u_register_t x3,
 			     u_register_t x4,
 			     void *cookie,
@@ -120,6 +159,8 @@
 			     u_register_t flags)
 {
 	int hard_reset = 0;
+	const struct ethosn_device_t *device = NULL;
+	const struct ethosn_core_t *core = NULL;
 	const uint32_t fid = smc_fid & FUNCID_NUM_MASK;
 
 	/* Only SiP fast calls are expected */
@@ -131,12 +172,14 @@
 	/* Truncate parameters to 32-bits for SMC32 */
 	if (GET_SMC_CC(smc_fid) == SMC_32) {
 		core_addr &= 0xFFFFFFFF;
-		x2 &= 0xFFFFFFFF;
+		asset_alloc_idx &= 0xFFFFFFFF;
 		x3 &= 0xFFFFFFFF;
 		x4 &= 0xFFFFFFFF;
 	}
 
-	if (!is_ethosn_fid(smc_fid)) {
+	if (!is_ethosn_fid(smc_fid) ||
+	    (fid < ETHOSN_FNUM_VERSION || fid > ETHOSN_FNUM_SOFT_RESET)) {
+		WARN("ETHOSN: Unknown SMC call: 0x%x\n", smc_fid);
 		SMC_RET1(handle, SMC_UNK);
 	}
 
@@ -146,25 +189,41 @@
 		SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR);
 	}
 
-	if (!ethosn_is_core_addr_valid(core_addr)) {
-		WARN("ETHOSN: Unknown core address given to SMC call.\n");
+	if (!ethosn_get_device_and_core(core_addr, &device, &core))  {
 		SMC_RET1(handle, ETHOSN_UNKNOWN_CORE_ADDRESS);
 	}
 
-	/* Commands that require a valid addr */
+	/* Commands that require a valid core address */
 	switch (fid) {
 	case ETHOSN_FNUM_IS_SEC:
-		SMC_RET1(handle, ethosn_is_sec(core_addr));
+		SMC_RET1(handle, ethosn_is_sec(core->addr));
+	}
+
+	if (!device->has_reserved_memory &&
+	    asset_alloc_idx >= device->num_allocators) {
+		WARN("ETHOSN: Unknown asset allocator index given to SMC call.\n");
+		SMC_RET1(handle, ETHOSN_UNKNOWN_ALLOCATOR_IDX);
+	}
+
+	/* Commands that require a valid device, core and asset allocator */
+	switch (fid) {
 	case ETHOSN_FNUM_HARD_RESET:
 		hard_reset = 1;
 		/* Fallthrough */
 	case ETHOSN_FNUM_SOFT_RESET:
-		if (!ethosn_reset(core_addr, hard_reset)) {
+		if (!ethosn_reset(core->addr, hard_reset)) {
 			SMC_RET1(handle, ETHOSN_FAILURE);
 		}
+
+		if (!device->has_reserved_memory) {
+			ethosn_configure_smmu_streams(device, core,
+						      asset_alloc_idx);
+		}
-		ethosn_delegate_to_ns(core_addr);
+
+		ethosn_delegate_to_ns(core->addr);
 		SMC_RET1(handle, ETHOSN_SUCCESS);
 	default:
+		WARN("ETHOSN: Unimplemented SMC call: 0x%x\n", fid);
 		SMC_RET1(handle, SMC_UNK);
 	}
 }
diff --git a/drivers/arm/gic/v3/gic600_multichip_private.h b/drivers/arm/gic/v3/gic600_multichip_private.h
index c7b15c1..414bd5b 100644
--- a/drivers/arm/gic/v3/gic600_multichip_private.h
+++ b/drivers/arm/gic/v3/gic600_multichip_private.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, ARM Limited. All rights reserved.
+ * Copyright (c) 2019-2022, ARM Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -74,7 +74,8 @@
  * Multichip data assertion macros
  */
 /* Set bits from 0 to ((spi_id_max + 1) / 32) */
-#define SPI_BLOCKS_TILL_MAX(spi_id_max)	((1 << (((spi_id_max) + 1) >> 5)) - 1)
+#define SPI_BLOCKS_TILL_MAX(spi_id_max) \
+			((1ULL << (((spi_id_max) + 1) >> 5)) - 1)
 /* Set bits from 0 to (spi_id_min / 32) */
 #define SPI_BLOCKS_TILL_MIN(spi_id_min)	((1 << ((spi_id_min) >> 5)) - 1)
 /* Set bits from (spi_id_min / 32) to ((spi_id_max + 1) / 32) */
diff --git a/fdts/juno-ethosn.dtsi b/fdts/juno-ethosn.dtsi
index e2f3355..4609524 100644
--- a/fdts/juno-ethosn.dtsi
+++ b/fdts/juno-ethosn.dtsi
@@ -1,12 +1,13 @@
 /*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 /*
- * For examples of multi-core and multi-device NPU, refer to the examples given in the
- * Arm Ethos-N NPU driver stack.
+ * This device tree is only an example and some properties have been omitted.
+ *
+ * Refer to the Arm(R) Ethos(TM)-N driver stack for complete device tree examples.
  * https://github.com/ARM-software/ethos-n-driver-stack
  */
 
@@ -14,14 +15,62 @@
 	#address-cells = <2>;
 	#size-cells = <2>;
 
-	ethosn0: ethosn@6f300000 {
-		compatible = "ethosn";
-		reg = <0 0x6f300000 0 0x00100000>;
+	smmu_ethosn0: iommu@6f400000 {
+		compatible = "arm,smmu-v3";
+		reg = <0 0x6f400000 0 0x80000>;
 		status = "okay";
-
-		core0 {
-			compatible = "ethosn-core";
-			status = "okay";
-		};
+		/* msi-parent omitted */
+		#iommu-cells = <0x1>;
 	};
+
+	ethosn0: ethosn@6f300000 {
+		 compatible = "ethosn";
+		 reg = <0 0x6f300000 0 0x00100000>;
+		 status = "okay";
+
+		 core0 {
+			 compatible = "ethosn-core";
+			 status = "okay";
+
+			 main_allocator {
+				 compatible = "ethosn-main_allocator";
+				 status = "okay";
+
+				 firmware {
+					 compatible = "ethosn-memory";
+					 iommus = <&smmu_ethosn0 0>;
+				 };
+
+				 working_data {
+					 compatible = "ethosn-memory";
+					 iommus = <&smmu_ethosn0 1>;
+				 };
+			 };
+		 };
+
+		 asset_allocator {
+			 compatible = "ethosn-asset_allocator";
+			 status = "okay";
+
+			 command_stream {
+				 compatible = "ethosn-memory";
+				 iommus = <&smmu_ethosn0 2>;
+			 };
+
+			 weight_data {
+				 compatible = "ethosn-memory";
+				 iommus = <&smmu_ethosn0 3>;
+			 };
+
+			 buffer_data {
+				 compatible = "ethosn-memory";
+				 iommus = <&smmu_ethosn0 4>;
+			 };
+
+			 intermediate_data {
+				 compatible = "ethosn-memory";
+				 iommus = <&smmu_ethosn0 5>;
+			 };
+		 };
+	 };
 };
diff --git a/fdts/stm32mp135f-dk.dts b/fdts/stm32mp135f-dk.dts
index e58be40..aa1dd01 100644
--- a/fdts/stm32mp135f-dk.dts
+++ b/fdts/stm32mp135f-dk.dts
@@ -228,13 +228,13 @@
 			frac = < 0x1400 >;
 		};
 
-		pll3_vco_417_8Mhz: pll2-vco-417_8Mhz {
+		pll3_vco_417_8Mhz: pll3-vco-417_8Mhz {
 			src = < CLK_PLL3_HSE >;
 			divmn = < 1 33 >;
 			frac = < 0x1a04 >;
 		};
 
-		pll4_vco_600Mhz: pll2-vco-600Mhz {
+		pll4_vco_600Mhz: pll4-vco-600Mhz {
 			src = < CLK_PLL4_HSE >;
 			divmn = < 1 49 >;
 		};
diff --git a/include/drivers/arm/ethosn.h b/include/drivers/arm/ethosn.h
index 9310733..dbaf16c 100644
--- a/include/drivers/arm/ethosn.h
+++ b/include/drivers/arm/ethosn.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -38,7 +38,7 @@
 #define is_ethosn_fid(_fid) (((_fid) & ETHOSN_FID_MASK) == ETHOSN_FID_VALUE)
 
 /* Service version  */
-#define ETHOSN_VERSION_MAJOR U(1)
+#define ETHOSN_VERSION_MAJOR U(2)
 #define ETHOSN_VERSION_MINOR U(0)
 
 /* Return codes for function calls */
@@ -48,10 +48,11 @@
 /* -3 Reserved for INVALID_PARAMETER */
 #define ETHOSN_FAILURE			-4
 #define ETHOSN_UNKNOWN_CORE_ADDRESS	-5
+#define ETHOSN_UNKNOWN_ALLOCATOR_IDX	-6
 
 uintptr_t ethosn_smc_handler(uint32_t smc_fid,
 			     u_register_t core_addr,
-			     u_register_t x2,
+			     u_register_t asset_alloc_idx,
 			     u_register_t x3,
 			     u_register_t x4,
 			     void *cookie,
diff --git a/include/lib/cpus/aarch64/cortex_a510.h b/include/lib/cpus/aarch64/cortex_a510.h
index af38734..6af85a8 100644
--- a/include/lib/cpus/aarch64/cortex_a510.h
+++ b/include/lib/cpus/aarch64/cortex_a510.h
@@ -36,5 +36,6 @@
  ******************************************************************************/
 #define CORTEX_A510_CPUACTLR_EL1				S3_0_C15_C1_0
 #define CORTEX_A510_CPUACTLR_EL1_BIT_17				(ULL(1) << 17)
+#define CORTEX_A510_CPUACTLR_EL1_BIT_38				(ULL(1) << 38)
 
 #endif /* CORTEX_A510_H */
\ No newline at end of file
diff --git a/include/plat/arm/common/arm_sip_svc.h b/include/plat/arm/common/arm_sip_svc.h
index 2eeed95..025d10e 100644
--- a/include/plat/arm/common/arm_sip_svc.h
+++ b/include/plat/arm/common/arm_sip_svc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2019,2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2019,2021-2022, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -26,7 +26,7 @@
 /* DEBUGFS_SMC_64			0xC2000030U */
 
 /*
- * Arm Ethos-N NPU SiP SMC function IDs
+ * Arm(R) Ethos(TM)-N NPU SiP SMC function IDs
  * 0xC2000050-0xC200005F
  * 0x82000050-0x8200005F
  */
diff --git a/include/plat/arm/common/fconf_ethosn_getter.h b/include/plat/arm/common/fconf_ethosn_getter.h
index fcdc31f..5b9a7ed 100644
--- a/include/plat/arm/common/fconf_ethosn_getter.h
+++ b/include/plat/arm/common/fconf_ethosn_getter.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -8,27 +8,52 @@
 #define FCONF_ETHOSN_GETTER_H
 
 #include <assert.h>
+#include <stdbool.h>
 
 #include <lib/fconf/fconf.h>
 
 #define hw_config__ethosn_config_getter(prop) ethosn_config.prop
-#define hw_config__ethosn_core_addr_getter(idx) __extension__ ({	\
-	assert(idx < ethosn_config.num_cores);				\
-	ethosn_config.core[idx].addr;					\
+#define hw_config__ethosn_device_getter(dev_idx) __extension__ ({	\
+	assert(dev_idx < ethosn_config.num_devices);			\
+	&ethosn_config.devices[dev_idx];				\
 })
 
-#define ETHOSN_STATUS_DISABLED U(0)
-#define ETHOSN_STATUS_ENABLED  U(1)
+#define ETHOSN_DEV_NUM_MAX U(2)
+#define ETHOSN_DEV_CORE_NUM_MAX U(8)
+#define ETHOSN_DEV_ASSET_ALLOCATOR_NUM_MAX U(16)
 
-#define ETHOSN_CORE_NUM_MAX U(64)
+struct ethosn_allocator_t {
+	uint32_t stream_id;
+};
+
+struct ethosn_main_allocator_t {
+	struct ethosn_allocator_t firmware;
+	struct ethosn_allocator_t working_data;
+};
+
+struct ethosn_asset_allocator_t {
+	struct ethosn_allocator_t command_stream;
+	struct ethosn_allocator_t weight_data;
+	struct ethosn_allocator_t buffer_data;
+	struct ethosn_allocator_t intermediate_data;
+};
 
 struct ethosn_core_t {
 	uint64_t addr;
+	struct ethosn_main_allocator_t main_allocator;
 };
 
-struct ethosn_config_t {
+struct ethosn_device_t {
+	bool has_reserved_memory;
 	uint32_t num_cores;
-	struct ethosn_core_t core[ETHOSN_CORE_NUM_MAX];
+	struct ethosn_core_t cores[ETHOSN_DEV_CORE_NUM_MAX];
+	uint32_t num_allocators;
+	struct ethosn_asset_allocator_t asset_allocators[ETHOSN_DEV_ASSET_ALLOCATOR_NUM_MAX];
+};
+
+struct ethosn_config_t {
+	uint32_t num_devices;
+	struct ethosn_device_t devices[ETHOSN_DEV_NUM_MAX];
 };
 
 int fconf_populate_arm_ethosn(uintptr_t config);
diff --git a/lib/cpus/aarch64/cortex_a510.S b/lib/cpus/aarch64/cortex_a510.S
index 81a4a78..f7f8027 100644
--- a/lib/cpus/aarch64/cortex_a510.S
+++ b/lib/cpus/aarch64/cortex_a510.S
@@ -330,6 +330,37 @@
 	b	cpu_rev_var_ls
 endfunc check_errata_2371937
 
+	/* ------------------------------------------------------
+	 * Errata Workaround for Cortex-A510 Errata #2666669
+	 * This applies to revisions r1p1 and lower, and is fixed
+	 * in r1p2.
+	 * Inputs:
+	 * x0: variant[4:7] and revision[0:3] of current cpu.
+	 * Shall clobber: x0, x1, x17
+	 * ------------------------------------------------------
+	 */
+func errata_cortex_a510_2666669_wa
+	mov	x17, x30
+	bl	check_errata_2666669
+	cbz	x0, 1f
+
+	/*
+	 * Workaround will set IMP_CPUACTLR_EL1[38]
+	 * to 0b1.
+	 */
+	mrs	x1, CORTEX_A510_CPUACTLR_EL1
+	orr	x1, x1, CORTEX_A510_CPUACTLR_EL1_BIT_38
+	msr	CORTEX_A510_CPUACTLR_EL1, x1
+1:
+	ret	x17
+endfunc errata_cortex_a510_2666669_wa
+
+func check_errata_2666669
+	/* Applies to r1p1 and lower */
+	mov	x1, #0x11
+	b	cpu_rev_var_ls
+endfunc check_errata_2666669
+
 	/* ----------------------------------------------------
 	 * HW will do the cache maintenance while powering down
 	 * ----------------------------------------------------
@@ -361,14 +392,15 @@
 	 * checking functions of each errata.
 	 */
 	report_errata ERRATA_A510_1922240, cortex_a510, 1922240
-	report_errata ERRATA_A510_2288014, cortex_a510, 2288014
-	report_errata ERRATA_A510_2042739, cortex_a510, 2042739
 	report_errata ERRATA_A510_2041909, cortex_a510, 2041909
-	report_errata ERRATA_A510_2250311, cortex_a510, 2250311
-	report_errata ERRATA_A510_2218950, cortex_a510, 2218950
+	report_errata ERRATA_A510_2042739, cortex_a510, 2042739
 	report_errata ERRATA_A510_2172148, cortex_a510, 2172148
+	report_errata ERRATA_A510_2218950, cortex_a510, 2218950
+	report_errata ERRATA_A510_2250311, cortex_a510, 2250311
+	report_errata ERRATA_A510_2288014, cortex_a510, 2288014
 	report_errata ERRATA_A510_2347730, cortex_a510, 2347730
 	report_errata ERRATA_A510_2371937, cortex_a510, 2371937
+	report_errata ERRATA_A510_2666669, cortex_a510, 2666669
 	report_errata ERRATA_DSU_2313941, cortex_a510, dsu_2313941
 
 	ldp	x8, x30, [sp], #16
@@ -435,6 +467,11 @@
 	bl	errata_cortex_a510_2347730_wa
 #endif
 
+#if ERRATA_A510_2666669
+	mov	x0, x18
+	bl	errata_cortex_a510_2666669_wa
+#endif
+
 	isb
 	ret	x19
 endfunc cortex_a510_reset_func
diff --git a/lib/cpus/aarch64/neoverse_n2.S b/lib/cpus/aarch64/neoverse_n2.S
index a807b63..72e5ca8 100644
--- a/lib/cpus/aarch64/neoverse_n2.S
+++ b/lib/cpus/aarch64/neoverse_n2.S
@@ -429,6 +429,10 @@
 	orr	x0, x0, #NEOVERSE_N2_CPUACTLR2_EL1_BIT_2
 	msr	NEOVERSE_N2_CPUACTLR2_EL1, x0
 
+	/* Get the CPU revision and stash it in x18. */
+	bl	cpu_get_rev_var
+	mov	x18, x0
+
 #if ERRATA_DSU_2313941
 	bl	errata_dsu_2313941_wa
 #endif
@@ -510,9 +514,6 @@
 	msr	NEOVERSE_N2_CPUECTLR_EL1, x0
 #endif
 
-	bl	cpu_get_rev_var
-	mov	x18, x0
-
 #if ERRATA_N2_2002655
 	mov	x0, x18
 	bl	errata_n2_2002655_wa
diff --git a/lib/cpus/aarch64/neoverse_v1.S b/lib/cpus/aarch64/neoverse_v1.S
index 109b725..3282fbc 100644
--- a/lib/cpus/aarch64/neoverse_v1.S
+++ b/lib/cpus/aarch64/neoverse_v1.S
@@ -508,8 +508,8 @@
 	report_errata ERRATA_V1_1925756, neoverse_v1, 1925756
 	report_errata ERRATA_V1_1940577, neoverse_v1, 1940577
 	report_errata ERRATA_V1_1966096, neoverse_v1, 1966096
-	report_errata ERRATA_V1_2139242, neoverse_v1, 2139242
 	report_errata ERRATA_V1_2108267, neoverse_v1, 2108267
+	report_errata ERRATA_V1_2139242, neoverse_v1, 2139242
 	report_errata ERRATA_V1_2216392, neoverse_v1, 2216392
 	report_errata ERRATA_V1_2294912, neoverse_v1, 2294912
 	report_errata ERRATA_V1_2372203, neoverse_v1, 2372203
@@ -527,6 +527,10 @@
 	msr	SSBS, xzr
 	isb
 
+	/* Get the CPU revision and stash it in x18. */
+	bl	cpu_get_rev_var
+	mov	x18, x0
+
 #if ERRATA_V1_1618635
 	mov x0, x18
 	bl errata_neoverse_v1_1618635_wa
diff --git a/lib/cpus/cpu-ops.mk b/lib/cpus/cpu-ops.mk
index 8b790bc..ec0d95e 100644
--- a/lib/cpus/cpu-ops.mk
+++ b/lib/cpus/cpu-ops.mk
@@ -674,6 +674,10 @@
 # to revisions r0p0, r0p1, r0p2, r0p3, r1p0, and r1p1. It is fixed in r1p2.
 ERRATA_A510_2371937	?=0
 
+# Flag to apply erratum 2666669 workaround during reset. This erratum applies
+# to revisions r0p0, r0p1, r0p2, r0p3, r1p0, and r1p1. It is fixed in r1p2.
+ERRATA_A510_2666669	?=0
+
 # Flag to apply DSU erratum 798953. This erratum applies to DSUs revision r0p0.
 # Applying the workaround results in higher DSU power consumption on idle.
 ERRATA_DSU_798953	?=0
@@ -1272,7 +1276,11 @@
 $(eval $(call assert_boolean,ERRATA_A510_2371937))
 $(eval $(call add_define,ERRATA_A510_2371937))
 
-# Process ERRATA_DSU_798953 flag
+# Process ERRATA_A510_2666669 flag
+$(eval $(call assert_boolean,ERRATA_A510_2666669))
+$(eval $(call add_define,ERRATA_A510_2666669))
+
+#Process ERRATA_DSU_798953 flag
 $(eval $(call assert_boolean,ERRATA_DSU_798953))
 $(eval $(call add_define,ERRATA_DSU_798953))
 
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index ea45b12..51ba035 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -392,6 +392,11 @@
 				plat/arm/board/fvp/fvp_bl2_measured_boot.c	\
 				lib/psa/measured_boot.c
 
+# Note that attestation code does not depend on measured boot interfaces per se,
+# but the two features go together - attestation without boot measurements is
+# pretty much pointless...
+BL31_SOURCES		+=	lib/psa/delegated_attestation.c
+
 PLAT_INCLUDES		+=	-Iinclude/lib/psa
 
 # RSS is not supported on FVP right now. Thus, we use the mocked version
@@ -407,9 +412,12 @@
     include drivers/arm/rss/rss_comms.mk
     BL1_SOURCES		+=	${RSS_COMMS_SOURCES}
     BL2_SOURCES		+=	${RSS_COMMS_SOURCES}
+    BL31_SOURCES	+=	${RSS_COMMS_SOURCES}		\
+				lib/psa/delegated_attestation.c
 
     BL1_CFLAGS		+=	-DPLAT_RSS_COMMS_PAYLOAD_MAX_SIZE=0
     BL2_CFLAGS		+=	-DPLAT_RSS_COMMS_PAYLOAD_MAX_SIZE=0
+    BL31_CFLAGS		+=	-DPLAT_RSS_COMMS_PAYLOAD_MAX_SIZE=0
 endif
 
 endif
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 6f3b889..682a278 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -114,7 +114,7 @@
   endif
 endif
 
-# Arm Ethos-N NPU SiP service
+# Arm(R) Ethos(TM)-N NPU SiP service
 ARM_ETHOSN_NPU_DRIVER			:=	0
 $(eval $(call assert_boolean,ARM_ETHOSN_NPU_DRIVER))
 $(eval $(call add_define,ARM_ETHOSN_NPU_DRIVER))
diff --git a/plat/arm/common/fconf/fconf_ethosn_getter.c b/plat/arm/common/fconf/fconf_ethosn_getter.c
index 0af1a20..0b48a98 100644
--- a/plat/arm/common/fconf/fconf_ethosn_getter.c
+++ b/plat/arm/common/fconf/fconf_ethosn_getter.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -12,107 +12,341 @@
 #include <libfdt.h>
 #include <plat/arm/common/fconf_ethosn_getter.h>
 
-struct ethosn_config_t ethosn_config = {.num_cores = 0};
+struct ethosn_config_t ethosn_config = {0};
 
-static uint8_t fdt_node_get_status(const void *fdt, int node)
+struct ethosn_sub_allocator_t {
+	const char *name;
+	size_t name_len;
+	uint32_t stream_id;
+};
+
+static bool fdt_node_is_enabled(const void *fdt, int node)
 {
 	int len;
-	uint8_t status = ETHOSN_STATUS_DISABLED;
 	const char *node_status;
 
 	node_status = fdt_getprop(fdt, node, "status", &len);
 	if (node_status == NULL ||
 	    (len == 5 && /* Includes null character */
 	     strncmp(node_status, "okay", 4U) == 0)) {
-		status = ETHOSN_STATUS_ENABLED;
+		return true;
 	}
 
+	return false;
+}
+
-	return status;
+static bool fdt_node_has_reserved_memory(const void *fdt, int dev_node)
+{
+	return fdt_get_property(fdt, dev_node, "memory-region", NULL) != NULL;
 }
 
+static int fdt_node_get_iommus_stream_id(const void *fdt, int node, uint32_t *stream_id)
+{
+	int err;
+	uint32_t iommus_array[2] = {0U};
+
+	err = fdt_read_uint32_array(fdt, node, "iommus", 2U, iommus_array);
+	if (err) {
+		return err;
+	}
+
+	*stream_id = iommus_array[1];
+	return 0;
+}
+
+static int fdt_node_populate_sub_allocators(const void *fdt,
+					    int alloc_node,
+					    struct ethosn_sub_allocator_t *sub_allocators,
+					    size_t num_allocs)
+{
+	int sub_node;
+	size_t i;
+	int err = -FDT_ERR_NOTFOUND;
+	uint32_t found_sub_allocators = 0U;
+
+	fdt_for_each_subnode(sub_node, fdt, alloc_node) {
+		const char *node_name;
+
+		if (!fdt_node_is_enabled(fdt, sub_node)) {
+			/* Ignore disabled node */
+			continue;
+		}
+
+		if (fdt_node_check_compatible(fdt, sub_node, "ethosn-memory") != 0) {
+			continue;
+		}
+
+		node_name = fdt_get_name(fdt, sub_node, NULL);
+		for (i = 0U; i < num_allocs; ++i) {
+			if (strncmp(node_name, sub_allocators[i].name,
+				    sub_allocators[i].name_len) != 0) {
+				continue;
+			}
+
+			err = fdt_node_get_iommus_stream_id(fdt, sub_node,
+							    &sub_allocators[i].stream_id);
+			if (err) {
+				ERROR("FCONF: Failed to get stream ID from sub-allocator %s\n",
+				      node_name);
+				return err;
+			}
+
+			++found_sub_allocators;
+			/* Nothing more to do for this node */
+			break;
+		}
+
+		/* Check that at least one of the sub-allocators matched */
+		if (i == num_allocs) {
+			ERROR("FCONF: Unknown sub-allocator %s\n", node_name);
+			return -FDT_ERR_BADSTRUCTURE;
+		}
+	}
+
+	if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) {
+		ERROR("FCONF: Failed to parse sub-allocators\n");
+		return -FDT_ERR_BADSTRUCTURE;
+	}
+
+	if (err == -FDT_ERR_NOTFOUND) {
+		ERROR("FCONF: No matching sub-allocator found\n");
+		return err;
+	}
+
+	if (found_sub_allocators != num_allocs) {
+		ERROR("FCONF: Not all sub-allocators were found\n");
+		return -FDT_ERR_BADSTRUCTURE;
+	}
+
+	return 0;
+}
+
+static int fdt_node_populate_main_allocator(const void *fdt,
+					    int alloc_node,
+					    struct ethosn_main_allocator_t *allocator)
+{
+	int err;
+	struct ethosn_sub_allocator_t sub_allocators[] = {
+		{.name = "firmware", .name_len = 8U},
+		{.name = "working_data", .name_len = 12U}
+	};
+
+	err = fdt_node_populate_sub_allocators(fdt, alloc_node, sub_allocators,
+					       ARRAY_SIZE(sub_allocators));
+	if (err) {
+		return err;
+	}
+
+	allocator->firmware.stream_id = sub_allocators[0].stream_id;
+	allocator->working_data.stream_id = sub_allocators[1].stream_id;
+
+	return 0;
+}
+
+static int fdt_node_populate_asset_allocator(const void *fdt,
+					    int alloc_node,
+					    struct ethosn_asset_allocator_t *allocator)
+{
+	int err;
+	struct ethosn_sub_allocator_t sub_allocators[] = {
+		{.name = "command_stream", .name_len = 14U},
+		{.name = "weight_data", .name_len = 11U},
+		{.name = "buffer_data", .name_len = 11U},
+		{.name = "intermediate_data", .name_len = 17U}
+	};
+
+	err = fdt_node_populate_sub_allocators(fdt, alloc_node, sub_allocators,
+					       ARRAY_SIZE(sub_allocators));
+	if (err) {
+		return err;
+	}
+
+
+	allocator->command_stream.stream_id = sub_allocators[0].stream_id;
+	allocator->weight_data.stream_id = sub_allocators[1].stream_id;
+	allocator->buffer_data.stream_id = sub_allocators[2].stream_id;
+	allocator->intermediate_data.stream_id = sub_allocators[3].stream_id;
+	return 0;
+}
+
+static int fdt_node_populate_core(const void *fdt,
+				  int device_node,
+				  int core_node,
+				  bool has_reserved_memory,
+				  uint32_t core_index,
+				  struct ethosn_core_t *core)
+{
+	int err;
+	int sub_node;
+	uintptr_t core_addr;
+
+	err = fdt_get_reg_props_by_index(fdt, device_node, core_index,
+					 &core_addr, NULL);
+	if (err < 0) {
+		ERROR("FCONF: Failed to read reg property for NPU core %u\n",
+		      core_index);
+		return err;
+	}
+
+	err = -FDT_ERR_NOTFOUND;
+	fdt_for_each_subnode(sub_node, fdt, core_node) {
+
+		if (!fdt_node_is_enabled(fdt, sub_node)) {
+			continue;
+		}
+
+		if (fdt_node_check_compatible(fdt,
+					      sub_node,
+					      "ethosn-main_allocator") != 0) {
+			continue;
+		}
+
+		if (has_reserved_memory) {
+			ERROR("FCONF: Main allocator not supported when using reserved memory\n");
+			return -FDT_ERR_BADSTRUCTURE;
+		}
+
+		if (err != -FDT_ERR_NOTFOUND) {
+			ERROR("FCONF: NPU core 0x%lx has more than one main allocator\n",
+			      core_addr);
+			return -FDT_ERR_BADSTRUCTURE;
+		}
+
+		err = fdt_node_populate_main_allocator(fdt, sub_node, &core->main_allocator);
+		if (err) {
+			ERROR("FCONF: Failed to parse main allocator for NPU core 0x%lx\n",
+			      core_addr);
+			return err;
+		}
+	}
+
+	if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) {
+		ERROR("FCONF: Failed to parse core sub nodes\n");
+		return -FDT_ERR_BADSTRUCTURE;
+	}
+
+	if (!has_reserved_memory && err) {
+		ERROR("FCONF: Main allocator not found for NPU core 0x%lx\n",
+		      core_addr);
+		return err;
+	}
+
+	core->addr = core_addr;
+
+	return 0;
+}
+
 int fconf_populate_ethosn_config(uintptr_t config)
 {
 	int ethosn_node;
+	uint32_t dev_count = 0U;
 	const void *hw_conf_dtb = (const void *)config;
 
-	/* Find offset to node with 'ethosn' compatible property */
-	INFO("Probing Arm Ethos-N NPU\n");
-	uint32_t total_core_count = 0U;
+	INFO("Probing Arm(R) Ethos(TM)-N NPU\n");
 
 	fdt_for_each_compatible_node(hw_conf_dtb, ethosn_node, "ethosn") {
+		struct ethosn_device_t *dev = &ethosn_config.devices[dev_count];
+		uint32_t dev_asset_alloc_count = 0U;
+		uint32_t dev_core_count = 0U;
+		bool has_reserved_memory;
 		int sub_node;
-		uint8_t ethosn_status;
-		uint32_t device_core_count = 0U;
 
-		/* If the Arm Ethos-N NPU is disabled the core check can be skipped */
-		ethosn_status = fdt_node_get_status(hw_conf_dtb, ethosn_node);
-		if (ethosn_status == ETHOSN_STATUS_DISABLED) {
+		if (!fdt_node_is_enabled(hw_conf_dtb, ethosn_node)) {
 			continue;
 		}
 
+		if (dev_count >= ETHOSN_DEV_NUM_MAX) {
+			ERROR("FCONF: Reached max number of NPUs\n");
+			return -FDT_ERR_BADSTRUCTURE;
+		}
+
+		has_reserved_memory = fdt_node_has_reserved_memory(hw_conf_dtb, ethosn_node);
 		fdt_for_each_subnode(sub_node, hw_conf_dtb, ethosn_node) {
 			int err;
-			uintptr_t core_addr;
-			uint8_t core_status;
 
-			if (total_core_count >= ETHOSN_CORE_NUM_MAX) {
-				ERROR("FCONF: Reached max number of Arm Ethos-N NPU cores\n");
-				return -FDT_ERR_BADSTRUCTURE;
+			if (!fdt_node_is_enabled(hw_conf_dtb, sub_node)) {
+				/* Ignore disabled sub node */
+				continue;
 			}
 
-			/* Check that the sub node is "ethosn-core" compatible */
 			if (fdt_node_check_compatible(hw_conf_dtb,
 						      sub_node,
-						      "ethosn-core") != 0) {
-				/* Ignore incompatible sub node */
-				continue;
-			}
+						      "ethosn-core") == 0) {
 
-			core_status = fdt_node_get_status(hw_conf_dtb, sub_node);
-			if (core_status == ETHOSN_STATUS_DISABLED) {
-				continue;
-			}
+				if (dev_core_count >= ETHOSN_DEV_CORE_NUM_MAX) {
+					ERROR("FCONF: Reached max number of NPU cores for NPU %u\n",
+					      dev_count);
+					return -FDT_ERR_BADSTRUCTURE;
+				}
 
-			err = fdt_get_reg_props_by_index(hw_conf_dtb,
-							 ethosn_node,
-							 device_core_count,
-							 &core_addr,
-							 NULL);
-			if (err < 0) {
-				ERROR(
-				"FCONF: Failed to read reg property for Arm Ethos-N NPU core %u\n",
-						device_core_count);
-				return err;
-			}
+				err = fdt_node_populate_core(hw_conf_dtb,
+							     ethosn_node,
+							     sub_node,
+							     has_reserved_memory,
+							     dev_core_count,
+							     &(dev->cores[dev_core_count]));
+				if (err) {
+					return err;
+				}
+				++dev_core_count;
+			} else if (fdt_node_check_compatible(hw_conf_dtb,
+							     sub_node,
+							     "ethosn-asset_allocator") == 0) {
+
+				if (dev_asset_alloc_count >=
+				    ETHOSN_DEV_ASSET_ALLOCATOR_NUM_MAX) {
+					ERROR("FCONF: Reached max number of asset allocators for NPU %u\n",
+					      dev_count);
+					return -FDT_ERR_BADSTRUCTURE;
+				}
+
+				if (has_reserved_memory) {
+					ERROR("FCONF: Asset allocator not supported when using reserved memory\n");
+					return -FDT_ERR_BADSTRUCTURE;
+				}
 
-			INFO("NPU core probed at address 0x%lx\n", core_addr);
-			ethosn_config.core[total_core_count].addr = core_addr;
-			total_core_count++;
-			device_core_count++;
+				err = fdt_node_populate_asset_allocator(hw_conf_dtb,
+									sub_node,
+									&(dev->asset_allocators[dev_asset_alloc_count]));
+				if (err) {
+					ERROR("FCONF: Failed to parse asset allocator for NPU %u\n",
+					      dev_count);
+					return err;
+				}
+				++dev_asset_alloc_count;
+			}
 		}
 
 		if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) {
-			ERROR("FCONF: Failed to parse sub nodes\n");
+			ERROR("FCONF: Failed to parse sub nodes for NPU %u\n",
+			      dev_count);
+			return -FDT_ERR_BADSTRUCTURE;
+		}
+
+		if (dev_core_count == 0U) {
+			ERROR("FCONF: NPU %u must have at least one enabled core\n",
+			      dev_count);
 			return -FDT_ERR_BADSTRUCTURE;
 		}
 
-		if (device_core_count == 0U) {
-			ERROR(
-			"FCONF: Enabled Arm Ethos-N NPU device must have at least one enabled core\n");
+		if (!has_reserved_memory && dev_asset_alloc_count == 0U) {
+			ERROR("FCONF: NPU %u must have at least one asset allocator\n",
+			      dev_count);
 			return -FDT_ERR_BADSTRUCTURE;
 		}
+
+		dev->num_cores = dev_core_count;
+		dev->num_allocators = dev_asset_alloc_count;
+		dev->has_reserved_memory = has_reserved_memory;
+		++dev_count;
 	}
 
-	if (total_core_count == 0U) {
+	if (dev_count == 0U) {
 		ERROR("FCONF: Can't find 'ethosn' compatible node in dtb\n");
 		return -FDT_ERR_BADSTRUCTURE;
 	}
 
-	ethosn_config.num_cores = total_core_count;
-
-	INFO("%d NPU core%s probed\n",
-	     ethosn_config.num_cores,
-	     ethosn_config.num_cores > 1 ? "s" : "");
+	ethosn_config.num_devices = dev_count;
 
 	return 0;
 }
diff --git a/plat/imx/common/imx_sip_svc.c b/plat/imx/common/imx_sip_svc.c
index fae9750..11d02f3 100644
--- a/plat/imx/common/imx_sip_svc.c
+++ b/plat/imx/common/imx_sip_svc.c
@@ -60,6 +60,11 @@
 		SMC_RET1(handle, imx_src_handler(smc_fid, x1, x2, x3, handle));
 		break;
 #endif
+#if defined(PLAT_imx8mm) || defined(PLAT_imx8mn) || defined(PLAT_imx8mp)
+	case IMX_SIP_HAB:
+		SMC_RET1(handle, imx_hab_handler(smc_fid, x1, x2, x3, x4));
+		break;
+#endif
 	case  IMX_SIP_BUILDINFO:
 		SMC_RET1(handle, imx_buildinfo_handler(smc_fid, x1, x2, x3, x4));
 	default:
diff --git a/plat/imx/common/include/imx_sip_svc.h b/plat/imx/common/include/imx_sip_svc.h
index c6e9879..1f45985 100644
--- a/plat/imx/common/include/imx_sip_svc.h
+++ b/plat/imx/common/include/imx_sip_svc.h
@@ -27,6 +27,17 @@
 
 #define IMX_SIP_GET_SOC_INFO		0xC2000006
 
+#define IMX_SIP_HAB			0xC2000007
+#define IMX_SIP_HAB_AUTH_IMG		0x00
+#define IMX_SIP_HAB_ENTRY		0x01
+#define IMX_SIP_HAB_EXIT		0x02
+#define IMX_SIP_HAB_REPORT_EVENT	0x03
+#define IMX_SIP_HAB_REPORT_STATUS	0x04
+#define IMX_SIP_HAB_FAILSAFE		0x05
+#define IMX_SIP_HAB_CHECK_TARGET	0x06
+#define IMX_SIP_HAB_GET_VERSION		0x07
+#define IMX_SIP_HAB_AUTH_IMG_NO_DCD	0x08
+
 #define IMX_SIP_WAKEUP_SRC		0xC2000009
 #define IMX_SIP_WAKEUP_SRC_SCU		0x1
 #define IMX_SIP_WAKEUP_SRC_IRQSTEER	0x2
@@ -58,6 +69,11 @@
 		    u_register_t x2, u_register_t x3, void *handle);
 #endif
 
+#if defined(PLAT_imx8mm) || defined(PLAT_imx8mn) || defined(PLAT_imx8mp)
+int imx_hab_handler(uint32_t smc_fid, u_register_t x1,
+		    u_register_t x2, u_register_t x3, u_register_t x4);
+#endif
+
 #if (defined(PLAT_imx8qm) || defined(PLAT_imx8qx))
 int imx_cpufreq_handler(uint32_t smc_fid, u_register_t x1,
 			u_register_t x2, u_register_t x3);
diff --git a/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
index 1667baf..38fac92 100644
--- a/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
+++ b/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c
@@ -32,12 +32,22 @@
 
 #define TRUSTY_PARAMS_LEN_BYTES      (4096*2)
 
+/*
+ * Note: DRAM region is mapped with entire size available and uses MT_RW
+ * attributes.
+ * See details in docs/plat/imx8m.rst "High Assurance Boot (HABv4)" section
+ * for explanation of this mapping scheme.
+ */
 static const mmap_region_t imx_mmap[] = {
 	MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW),
 	MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW), /* AIPS map */
 	MAP_REGION_FLAT(OCRAM_S_BASE, OCRAM_S_SIZE, MT_DEVICE | MT_RW), /* OCRAM_S */
 	MAP_REGION_FLAT(IMX_DDRPHY_BASE, IMX_DDR_IPS_SIZE, MT_DEVICE | MT_RW), /* DDRMIX */
 	MAP_REGION_FLAT(IMX_VPUMIX_BASE, IMX_VPUMIX_SIZE, MT_DEVICE | MT_RW), /* VPUMIX */
+	MAP_REGION_FLAT(IMX_CAAM_RAM_BASE, IMX_CAAM_RAM_SIZE, MT_MEMORY | MT_RW), /* CAMM RAM */
+	MAP_REGION_FLAT(IMX_NS_OCRAM_BASE, IMX_NS_OCRAM_SIZE, MT_MEMORY | MT_RW), /* NS OCRAM */
+	MAP_REGION_FLAT(IMX_ROM_BASE, IMX_ROM_SIZE, MT_MEMORY | MT_RO), /* ROM code */
+	MAP_REGION_FLAT(IMX_DRAM_BASE, IMX_DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS), /* DRAM */
 	{0},
 };
 
diff --git a/plat/imx/imx8m/imx8mm/include/platform_def.h b/plat/imx/imx8m/imx8mm/include/platform_def.h
index 84d86b9..930372f 100644
--- a/plat/imx/imx8m/imx8mm/include/platform_def.h
+++ b/plat/imx/imx8m/imx8mm/include/platform_def.h
@@ -107,9 +107,16 @@
 #define IMX_DDRPHY_BASE			U(0x3c000000)
 #define IMX_DDR_IPS_BASE		U(0x3d000000)
 #define IMX_DDR_IPS_SIZE		U(0x1800000)
+#define IMX_VPUMIX_BASE			U(0x38330000)
+#define IMX_VPUMIX_SIZE			U(0x100000)
 #define IMX_ROM_BASE			U(0x0)
-#define IMX_VPUMIX_BASE                U(0x38330000)
-#define IMX_VPUMIX_SIZE                U(0x100000)
+#define IMX_ROM_SIZE			U(0x40000)
+#define IMX_NS_OCRAM_BASE		U(0x900000)
+#define IMX_NS_OCRAM_SIZE		U(0x20000)
+#define IMX_CAAM_RAM_BASE		U(0x100000)
+#define IMX_CAAM_RAM_SIZE		U(0x10000)
+#define IMX_DRAM_BASE			U(0x40000000)
+#define IMX_DRAM_SIZE			U(0xc0000000)
 
 #define GPV_BASE			U(0x32000000)
 #define GPV_SIZE			U(0x800000)
diff --git a/plat/imx/imx8m/imx8mm/platform.mk b/plat/imx/imx8m/imx8mm/platform.mk
index e3e5c0c..ebf5c7b 100644
--- a/plat/imx/imx8m/imx8mm/platform.mk
+++ b/plat/imx/imx8m/imx8mm/platform.mk
@@ -32,6 +32,7 @@
 
 BL31_SOURCES		+=	plat/imx/common/imx8_helpers.S			\
 				plat/imx/imx8m/gpc_common.c			\
+				plat/imx/imx8m/imx_hab.c			\
 				plat/imx/imx8m/imx_aipstz.c			\
 				plat/imx/imx8m/imx_rdc.c			\
 				plat/imx/imx8m/imx8m_csu.c			\
diff --git a/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c b/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c
index 464c87d..de30967 100644
--- a/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c
+++ b/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c
@@ -32,7 +32,9 @@
 #define TRUSTY_PARAMS_LEN_BYTES      (4096*2)
 
 static const mmap_region_t imx_mmap[] = {
-	GIC_MAP, AIPS_MAP, OCRAM_S_MAP, DDRC_MAP, {0},
+	GIC_MAP, AIPS_MAP, OCRAM_S_MAP, DDRC_MAP,
+	CAAM_RAM_MAP, NS_OCRAM_MAP, ROM_MAP, DRAM_MAP,
+	{0},
 };
 
 static const struct aipstz_cfg aipstz[] = {
diff --git a/plat/imx/imx8m/imx8mn/include/platform_def.h b/plat/imx/imx8m/imx8mn/include/platform_def.h
index dbb4416..d4b1717 100644
--- a/plat/imx/imx8m/imx8mn/include/platform_def.h
+++ b/plat/imx/imx8m/imx8mn/include/platform_def.h
@@ -94,6 +94,13 @@
 #define IMX_DDR_IPS_BASE		U(0x3d000000)
 #define IMX_DDR_IPS_SIZE		U(0x1800000)
 #define IMX_ROM_BASE			U(0x0)
+#define IMX_ROM_SIZE			U(0x40000)
+#define IMX_NS_OCRAM_BASE		U(0x900000)
+#define IMX_NS_OCRAM_SIZE		U(0x60000)
+#define IMX_CAAM_RAM_BASE		U(0x100000)
+#define IMX_CAAM_RAM_SIZE		U(0x10000)
+#define IMX_DRAM_BASE			U(0x40000000)
+#define IMX_DRAM_SIZE			U(0xc0000000)
 
 #define IMX_GIC_BASE			PLAT_GICD_BASE
 #define IMX_GIC_SIZE			U(0x200000)
@@ -140,5 +147,16 @@
 #define AIPS_MAP	MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW) /* AIPS map */
 #define OCRAM_S_MAP	MAP_REGION_FLAT(OCRAM_S_BASE, OCRAM_S_SIZE, MT_DEVICE | MT_RW) /* OCRAM_S */
 #define DDRC_MAP	MAP_REGION_FLAT(IMX_DDRPHY_BASE, IMX_DDR_IPS_SIZE, MT_DEVICE | MT_RW) /* DDRMIX */
+#define CAAM_RAM_MAP	MAP_REGION_FLAT(IMX_CAAM_RAM_BASE, IMX_CAAM_RAM_SIZE, MT_MEMORY | MT_RW) /* CAMM RAM */
+#define NS_OCRAM_MAP	MAP_REGION_FLAT(IMX_NS_OCRAM_BASE, IMX_NS_OCRAM_SIZE, MT_MEMORY | MT_RW) /* NS OCRAM */
+#define ROM_MAP		MAP_REGION_FLAT(IMX_ROM_BASE, IMX_ROM_SIZE, MT_MEMORY | MT_RO) /* ROM code */
+
+/*
+ * Note: DRAM region is mapped with entire size available and uses MT_RW
+ * attributes.
+ * See details in docs/plat/imx8m.rst "High Assurance Boot (HABv4)" section
+ * for explanation of this mapping scheme.
+ */
+#define DRAM_MAP	MAP_REGION_FLAT(IMX_DRAM_BASE, IMX_DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS) /* DRAM */
 
 #endif /* platform_def.h */
diff --git a/plat/imx/imx8m/imx8mn/platform.mk b/plat/imx/imx8m/imx8mn/platform.mk
index 0f3ad1a..c70f3a1 100644
--- a/plat/imx/imx8m/imx8mn/platform.mk
+++ b/plat/imx/imx8m/imx8mn/platform.mk
@@ -27,6 +27,7 @@
 
 BL31_SOURCES		+=	plat/imx/common/imx8_helpers.S			\
 				plat/imx/imx8m/gpc_common.c			\
+				plat/imx/imx8m/imx_hab.c			\
 				plat/imx/imx8m/imx_aipstz.c			\
 				plat/imx/imx8m/imx_rdc.c			\
 				plat/imx/imx8m/imx8m_caam.c			\
diff --git a/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c b/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c
index 34631b8..70dd8c8 100644
--- a/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c
+++ b/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c
@@ -33,7 +33,9 @@
 
 static const mmap_region_t imx_mmap[] = {
 	GIC_MAP, AIPS_MAP, OCRAM_S_MAP, DDRC_MAP,
-	NOC_MAP, {0},
+	NOC_MAP, CAAM_RAM_MAP, NS_OCRAM_MAP,
+	ROM_MAP, DRAM_MAP,
+	{0},
 };
 
 static const struct aipstz_cfg aipstz[] = {
diff --git a/plat/imx/imx8m/imx8mp/include/platform_def.h b/plat/imx/imx8m/imx8mp/include/platform_def.h
index 8807f5d..1c58f48 100644
--- a/plat/imx/imx8m/imx8mp/include/platform_def.h
+++ b/plat/imx/imx8m/imx8mp/include/platform_def.h
@@ -111,6 +111,13 @@
 #define IMX_DDR_IPS_BASE		U(0x3d000000)
 #define IMX_DDR_IPS_SIZE		U(0x1800000)
 #define IMX_ROM_BASE			U(0x0)
+#define IMX_ROM_SIZE			U(0x40000)
+#define IMX_NS_OCRAM_BASE		U(0x900000)
+#define IMX_NS_OCRAM_SIZE		U(0x60000)
+#define IMX_CAAM_RAM_BASE		U(0x100000)
+#define IMX_CAAM_RAM_SIZE		U(0x10000)
+#define IMX_DRAM_BASE			U(0x40000000)
+#define IMX_DRAM_SIZE			U(0xc0000000)
 
 #define IMX_GIC_BASE			PLAT_GICD_BASE
 #define IMX_GIC_SIZE			U(0x200000)
@@ -178,5 +185,16 @@
 #define OCRAM_S_MAP	MAP_REGION_FLAT(OCRAM_S_BASE, OCRAM_S_SIZE, MT_MEMORY | MT_RW) /* OCRAM_S */
 #define DDRC_MAP	MAP_REGION_FLAT(IMX_DDRPHY_BASE, IMX_DDR_IPS_SIZE, MT_DEVICE | MT_RW) /* DDRMIX */
 #define NOC_MAP		MAP_REGION_FLAT(IMX_NOC_BASE, IMX_NOC_SIZE, MT_DEVICE | MT_RW) /* NOC QoS */
+#define CAAM_RAM_MAP	MAP_REGION_FLAT(IMX_CAAM_RAM_BASE, IMX_CAAM_RAM_SIZE, MT_MEMORY | MT_RW) /* CAMM RAM */
+#define NS_OCRAM_MAP	MAP_REGION_FLAT(IMX_NS_OCRAM_BASE, IMX_NS_OCRAM_SIZE, MT_MEMORY | MT_RW) /* NS OCRAM */
+#define ROM_MAP		MAP_REGION_FLAT(IMX_ROM_BASE, IMX_ROM_SIZE, MT_MEMORY | MT_RO) /* ROM code */
+
+/*
+ * Note: DRAM region is mapped with entire size available and uses MT_RW
+ * attributes.
+ * See details in docs/plat/imx8m.rst "High Assurance Boot (HABv4)" section
+ * for explanation of this mapping scheme.
+ */
+#define DRAM_MAP	MAP_REGION_FLAT(IMX_DRAM_BASE, IMX_DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS) /* DRAM */
 
 #endif /* platform_def.h */
diff --git a/plat/imx/imx8m/imx8mp/platform.mk b/plat/imx/imx8m/imx8mp/platform.mk
index e8669e5..09f9ee9 100644
--- a/plat/imx/imx8m/imx8mp/platform.mk
+++ b/plat/imx/imx8m/imx8mp/platform.mk
@@ -28,6 +28,7 @@
 
 BL31_SOURCES		+=	plat/imx/common/imx8_helpers.S			\
 				plat/imx/imx8m/gpc_common.c			\
+				plat/imx/imx8m/imx_hab.c			\
 				plat/imx/imx8m/imx_aipstz.c			\
 				plat/imx/imx8m/imx_rdc.c			\
 				plat/imx/imx8m/imx8m_caam.c			\
diff --git a/plat/imx/imx8m/imx_hab.c b/plat/imx/imx8m/imx_hab.c
new file mode 100644
index 0000000..222046f
--- /dev/null
+++ b/plat/imx/imx8m/imx_hab.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2017-2020 NXP
+ * Copyright 2022 Leica Geosystems AG
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/runtime_svc.h>
+#include <imx_sip_svc.h>
+
+#define HAB_CID_ATF	U(2)	/* TF-A Caller ID */
+
+/* HAB Status definitions */
+enum hab_status {
+	HAB_STS_ANY = 0x00,	/* Match any status in report_event() */
+	HAB_FAILURE = 0x33,	/* Operation failed */
+	HAB_WARNING = 0x69,	/* Operation completed with warning */
+	HAB_SUCCESS = 0xf0	/* Operation completed successfully */
+};
+
+/* HAB Configuration definitions */
+enum hab_config {
+	HAB_CFG_RETURN = 0x33,	/* Field Return IC */
+	HAB_CFG_OPEN   = 0xf0,	/* Non-secure IC */
+	HAB_CFG_CLOSED = 0xcc	/* Secure IC */
+};
+
+/* HAB State definitions */
+enum hab_state {
+	HAB_STATE_INITIAL   = 0x33,	/* Initializing state (transitory) */
+	HAB_STATE_CHECK     = 0x55,	/* Check state (non-secure) */
+	HAB_STATE_NONSECURE = 0x66,	/* Non-secure state */
+	HAB_STATE_TRUSTED   = 0x99,	/* Trusted state */
+	HAB_STATE_SECURE    = 0xaa,	/* Secure state */
+	HAB_STATE_FAIL_SOFT = 0xcc,	/* Soft fail state */
+	HAB_STATE_FAIL_HARD = 0xff,	/* Hard fail state (terminal) */
+	HAB_STATE_NONE      = 0xf0	/* No security state machine */
+};
+
+/* HAB Verification Target definitions */
+enum hab_target {
+	HAB_TGT_MEMORY     = 0x0f,	/* Check memory allowed list */
+	HAB_TGT_PERIPHERAL = 0xf0,	/* Check peripheral allowed list */
+	HAB_TGT_ANY        = 0x55	/* Check memory & peripheral allowed list */
+};
+
+/* Authenticate Image Loader Callback prototype */
+typedef enum hab_status hab_loader_callback_f_t(void **, size_t *, const void *);
+
+/*
+ * HAB Rom VectorTable (RVT) structure.
+ * This table provides function pointers into the HAB library in ROM for
+ * use by post-ROM boot sequence components.
+ * Functions are ordered in the structure below based on the offsets in ROM
+ * image, and shall not be changed!
+ * Details on API allocation offsets and function description could be
+ * found in following documents from NXP:
+ * - High Assurance Boot Version 4 Application Programming Interface
+ *   Reference Manual (available in CST package)
+ * - HABv4 RVT Guidelines and Recommendations (AN12263)
+ */
+struct hab_rvt_api {
+	uint64_t	hdr;
+	enum hab_status (*entry)(void);
+	enum hab_status (*exit)(void);
+	enum hab_status (*check_target)(enum hab_target type, const void *start, size_t bytes);
+	void* (*authenticate_image)(uint8_t cid, long ivt_offset, void **start,
+		size_t *bytes, hab_loader_callback_f_t loader);
+	enum hab_status (*run_dcd)(const uint8_t *dcd);
+	enum hab_status (*run_csf)(const uint8_t *csf, uint8_t cid, uint32_t srkmask);
+	enum hab_status (*assert)(long type, const void *data, uint32_t count);
+	enum hab_status (*report_event)(enum hab_status status, uint32_t index,
+		uint8_t *event, size_t *bytes);
+	enum hab_status (*report_status)(enum hab_config *config, enum hab_state *state);
+	void (*failsafe)(void);
+	void* (*authenticate_image_no_dcd)(uint8_t cid, long ivt_offset, void **start,
+		size_t *bytes, hab_loader_callback_f_t loader);
+	uint32_t (*get_version)(void);
+	enum hab_status (*authenticate_container)(uint8_t cid, long ivt_offset, void **start,
+		size_t *bytes, hab_loader_callback_f_t loader, uint32_t srkmask, int skip_dcd);
+};
+
+struct hab_rvt_api *g_hab_rvt_api = (struct hab_rvt_api *)HAB_RVT_BASE;
+
+/*******************************************************************************
+ * Handler for servicing HAB SMC calls
+ ******************************************************************************/
+int imx_hab_handler(uint32_t smc_fid,
+			u_register_t x1,
+			u_register_t x2,
+			u_register_t x3,
+			u_register_t x4)
+{
+	switch (x1) {
+	case IMX_SIP_HAB_ENTRY:
+		return g_hab_rvt_api->entry();
+	case IMX_SIP_HAB_EXIT:
+		return g_hab_rvt_api->exit();
+	case IMX_SIP_HAB_CHECK_TARGET:
+		return g_hab_rvt_api->check_target((enum hab_target)x2,
+			(const void *)x3, (size_t)x4);
+	case IMX_SIP_HAB_AUTH_IMG:
+		return (unsigned long)g_hab_rvt_api->authenticate_image(HAB_CID_ATF,
+			x2, (void **)x3, (size_t *)x4, NULL);
+	case IMX_SIP_HAB_REPORT_EVENT:
+		return g_hab_rvt_api->report_event(HAB_FAILURE,
+			(uint32_t)x2, (uint8_t *)x3, (size_t *)x4);
+	case IMX_SIP_HAB_REPORT_STATUS:
+		return g_hab_rvt_api->report_status((enum hab_config *)x2,
+			(enum hab_state *)x3);
+	case IMX_SIP_HAB_FAILSAFE:
+		g_hab_rvt_api->failsafe();
+		break;
+	case IMX_SIP_HAB_AUTH_IMG_NO_DCD:
+		return (unsigned long)g_hab_rvt_api->authenticate_image_no_dcd(
+			HAB_CID_ATF, x2, (void **)x3, (size_t *)x4, NULL);
+	case IMX_SIP_HAB_GET_VERSION:
+		return g_hab_rvt_api->get_version();
+	default:
+		return SMC_UNK;
+	};
+
+	return SMC_OK;
+}
diff --git a/plat/rpi/common/rpi3_pm.c b/plat/rpi/common/rpi3_pm.c
index 86c61f7..2f86279 100644
--- a/plat/rpi/common/rpi3_pm.c
+++ b/plat/rpi/common/rpi3_pm.c
@@ -123,15 +123,6 @@
 #endif
 }
 
-void __dead2 plat_secondary_cold_boot_setup(void);
-
-static void __dead2
-rpi3_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
-{
-	disable_mmu_el3();
-	plat_secondary_cold_boot_setup();
-}
-
 /*******************************************************************************
  * Platform handler called when a power domain is about to be turned on. The
  * mpidr determines the CPU to be turned on.
@@ -262,7 +253,6 @@
 static const plat_psci_ops_t plat_rpi3_psci_pm_ops = {
 	.cpu_standby = rpi3_cpu_standby,
 	.pwr_domain_off = rpi3_pwr_domain_off,
-	.pwr_domain_pwr_down_wfi = rpi3_pwr_domain_pwr_down_wfi,
 	.pwr_domain_on = rpi3_pwr_domain_on,
 	.pwr_domain_on_finish = rpi3_pwr_domain_on_finish,
 	.pwr_domain_pwr_down_wfi = rpi3_pwr_down_wfi,
diff --git a/plat/xilinx/versal/platform.mk b/plat/xilinx/versal/platform.mk
index a8b2c94..8087297 100644
--- a/plat/xilinx/versal/platform.mk
+++ b/plat/xilinx/versal/platform.mk
@@ -11,6 +11,10 @@
 IPI_CRC_CHECK := 0
 HARDEN_SLS_ALL := 0
 
+# A72 Erratum for SoC
+ERRATA_A72_859971 := 1
+ERRATA_A72_1319367 := 1
+
 ifdef VERSAL_ATF_MEM_BASE
     $(eval $(call add_define,VERSAL_ATF_MEM_BASE))
 
diff --git a/plat/xilinx/versal_net/platform.mk b/plat/xilinx/versal_net/platform.mk
index 08e65ac..b3d56bc 100644
--- a/plat/xilinx/versal_net/platform.mk
+++ b/plat/xilinx/versal_net/platform.mk
@@ -6,6 +6,12 @@
 
 PLAT_PATH := plat/xilinx/versal_net
 
+# A78 Erratum for SoC
+ERRATA_A78_AE_1941500 := 1
+ERRATA_A78_AE_1951502 := 1
+ERRATA_A78_AE_2376748 := 1
+ERRATA_A78_AE_2395408 := 1
+
 override PROGRAMMABLE_RESET_ADDRESS := 1
 PSCI_EXTENDED_STATE_ID := 1
 SEPARATE_CODE_AND_RODATA := 1