Merge changes from topic "imx8m-hab-support" into integration

* changes:
  docs(imx8m): update for high assurance boot
  feat(imx8m): add support for high assurance boot
  feat(imx8mp): add hab and map required memory blocks
  feat(imx8mn): add hab and map required memory blocks
  feat(imx8mm): add hab and map required memory blocks
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/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/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/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/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;
 }