Merge "Fix build type is empty in version string" into integration
diff --git a/bl1/bl1.ld.S b/bl1/bl1.ld.S
index 75355eb..bc23828 100644
--- a/bl1/bl1.ld.S
+++ b/bl1/bl1.ld.S
@@ -4,6 +4,14 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+/*
+ * The .data section gets copied from ROM to RAM at runtime.
+ * Its LMA should be 16-byte aligned to allow efficient copying of 16-bytes
+ * aligned regions in it.
+ * Its VMA must be page-aligned as it marks the first read/write page.
+ */
+#define DATA_ALIGN	16
+
 #include <common/bl_common.ld.h>
 #include <lib/xlat_tables/xlat_tables_defs.h>
 
@@ -87,28 +95,11 @@
     ASSERT(BL1_RW_BASE == ALIGN(PAGE_SIZE),
            "BL1_RW_BASE address is not aligned on a page boundary.")
 
-    /*
-     * The .data section gets copied from ROM to RAM at runtime.
-     * Its LMA should be 16-byte aligned to allow efficient copying of 16-bytes
-     * aligned regions in it.
-     * Its VMA must be page-aligned as it marks the first read/write page.
-     *
-     * It must be placed at a lower address than the stacks if the stack
-     * protector is enabled. Alternatively, the .data.stack_protector_canary
-     * section can be placed independently of the main .data section.
-     */
-    .data . : ALIGN(16) {
-        __DATA_RAM_START__ = .;
-        *(SORT_BY_ALIGNMENT(.data*))
-        __DATA_RAM_END__ = .;
-    } >RAM AT>ROM
-
-    stacks . (NOLOAD) : {
-        __STACKS_START__ = .;
-        *(tzfw_normal_stacks)
-        __STACKS_END__ = .;
-    } >RAM
+    DATA_SECTION >RAM AT>ROM
+    __DATA_RAM_START__ = __DATA_START__;
+    __DATA_RAM_END__ = __DATA_END__;
 
+    STACK_SECTION >RAM
     BSS_SECTION >RAM
     XLAT_TABLE_SECTION >RAM
 
diff --git a/bl2/bl2.ld.S b/bl2/bl2.ld.S
index 15df5dd..37849c3 100644
--- a/bl2/bl2.ld.S
+++ b/bl2/bl2.ld.S
@@ -77,23 +77,8 @@
      */
     __RW_START__ = . ;
 
-    /*
-     * .data must be placed at a lower address than the stacks if the stack
-     * protector is enabled. Alternatively, the .data.stack_protector_canary
-     * section can be placed independently of the main .data section.
-     */
-    .data . : {
-        __DATA_START__ = .;
-        *(SORT_BY_ALIGNMENT(.data*))
-        __DATA_END__ = .;
-    } >RAM
-
-    stacks (NOLOAD) : {
-        __STACKS_START__ = .;
-        *(tzfw_normal_stacks)
-        __STACKS_END__ = .;
-    } >RAM
-
+    DATA_SECTION >RAM
+    STACK_SECTION >RAM
     BSS_SECTION >RAM
     XLAT_TABLE_SECTION >RAM
 
diff --git a/bl2/bl2_el3.ld.S b/bl2/bl2_el3.ld.S
index d04f226..8c45d98 100644
--- a/bl2/bl2_el3.ld.S
+++ b/bl2/bl2_el3.ld.S
@@ -101,16 +101,9 @@
      */
     __RW_START__ = . ;
 
-    /*
-     * .data must be placed at a lower address than the stacks if the stack
-     * protector is enabled. Alternatively, the .data.stack_protector_canary
-     * section can be placed independently of the main .data section.
-     */
-    .data . : {
-        __DATA_RAM_START__ = .;
-        *(SORT_BY_ALIGNMENT(.data*))
-        __DATA_RAM_END__ = .;
-    } >RAM AT>ROM
+    DATA_SECTION >RAM AT>ROM
+    __DATA_RAM_START__ = __DATA_START__;
+    __DATA_RAM_END__ = __DATA_END__;
 
     /*
      * .rela.dyn needs to come after .data for the read-elf utility to parse
@@ -123,12 +116,7 @@
     } >RAM
     __RELA_END__ = .;
 
-    stacks (NOLOAD) : {
-        __STACKS_START__ = .;
-        *(tzfw_normal_stacks)
-        __STACKS_END__ = .;
-    } >RAM
-
+    STACK_SECTION >RAM
     BSS_SECTION >RAM
     XLAT_TABLE_SECTION >RAM
 
diff --git a/bl2u/bl2u.ld.S b/bl2u/bl2u.ld.S
index 8c0bbbd..a7752a4 100644
--- a/bl2u/bl2u.ld.S
+++ b/bl2u/bl2u.ld.S
@@ -79,23 +79,8 @@
      */
     __RW_START__ = . ;
 
-    /*
-     * .data must be placed at a lower address than the stacks if the stack
-     * protector is enabled. Alternatively, the .data.stack_protector_canary
-     * section can be placed independently of the main .data section.
-     */
-    .data . : {
-        __DATA_START__ = .;
-        *(SORT_BY_ALIGNMENT(.data*))
-        __DATA_END__ = .;
-    } >RAM
-
-    stacks (NOLOAD) : {
-        __STACKS_START__ = .;
-        *(tzfw_normal_stacks)
-        __STACKS_END__ = .;
-    } >RAM
-
+    DATA_SECTION >RAM
+    STACK_SECTION >RAM
     BSS_SECTION >RAM
     XLAT_TABLE_SECTION >RAM
 
diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S
index 1cdf7c9..11e86a3 100644
--- a/bl31/bl31.ld.S
+++ b/bl31/bl31.ld.S
@@ -114,16 +114,7 @@
      */
     __RW_START__ = . ;
 
-    /*
-     * .data must be placed at a lower address than the stacks if the stack
-     * protector is enabled. Alternatively, the .data.stack_protector_canary
-     * section can be placed independently of the main .data section.
-     */
-   .data . : {
-        __DATA_START__ = .;
-        *(SORT_BY_ALIGNMENT(.data*))
-        __DATA_END__ = .;
-    } >RAM
+    DATA_SECTION >RAM
 
     /*
      * .rela.dyn needs to come after .data for the read-elf utility to parse
@@ -158,12 +149,7 @@
     __NOBITS_START__ = .;
 #endif
 
-    stacks (NOLOAD) : {
-        __STACKS_START__ = .;
-        *(tzfw_normal_stacks)
-        __STACKS_END__ = .;
-    } >NOBITS
-
+    STACK_SECTION >NOBITS
     BSS_SECTION >NOBITS
     XLAT_TABLE_SECTION >NOBITS
 
diff --git a/bl32/sp_min/sp_min.ld.S b/bl32/sp_min/sp_min.ld.S
index da005db..9e0596f 100644
--- a/bl32/sp_min/sp_min.ld.S
+++ b/bl32/sp_min/sp_min.ld.S
@@ -91,22 +91,13 @@
      */
     __RW_START__ = . ;
 
-    .data . : {
-        __DATA_START__ = .;
-        *(.data*)
-        __DATA_END__ = .;
-    } >RAM
+    DATA_SECTION >RAM
 
 #ifdef BL32_PROGBITS_LIMIT
     ASSERT(. <= BL32_PROGBITS_LIMIT, "BL32 progbits has exceeded its limit.")
 #endif
 
-    stacks (NOLOAD) : {
-        __STACKS_START__ = .;
-        *(tzfw_normal_stacks)
-        __STACKS_END__ = .;
-    } >RAM
-
+    STACK_SECTION >RAM
     BSS_SECTION >RAM
     XLAT_TABLE_SECTION >RAM
 
diff --git a/bl32/tsp/tsp.ld.S b/bl32/tsp/tsp.ld.S
index bf77c92..bdcd2cf 100644
--- a/bl32/tsp/tsp.ld.S
+++ b/bl32/tsp/tsp.ld.S
@@ -70,11 +70,7 @@
      */
     __RW_START__ = . ;
 
-    .data . : {
-        __DATA_START__ = .;
-        *(.data*)
-        __DATA_END__ = .;
-    } >RAM
+    DATA_SECTION >RAM
 
     /*
      * .rela.dyn needs to come after .data for the read-elf utility to parse
@@ -91,12 +87,7 @@
     ASSERT(. <= TSP_PROGBITS_LIMIT, "TSP progbits has exceeded its limit.")
 #endif
 
-    stacks (NOLOAD) : {
-        __STACKS_START__ = .;
-        *(tzfw_normal_stacks)
-        __STACKS_END__ = .;
-    } >RAM
-
+    STACK_SECTION >RAM
     BSS_SECTION >RAM
     XLAT_TABLE_SECTION >RAM
 
diff --git a/common/fdt_wrappers.c b/common/fdt_wrappers.c
index ca5b455..842d713 100644
--- a/common/fdt_wrappers.c
+++ b/common/fdt_wrappers.c
@@ -15,90 +15,72 @@
 #include <common/fdt_wrappers.h>
 
 /*
- * Read cells from a given property of the given node. At most 2 cells of the
- * property are read, and pointer is updated. Returns 0 on success, and -1 upon
- * error
+ * Read cells from a given property of the given node. Any number of 32-bit
+ * cells of the property can be read. Returns 0 on success, or a negative
+ * FDT error value otherwise.
  */
-int fdtw_read_cells(const void *dtb, int node, const char *prop,
-		unsigned int cells, void *value)
+int fdt_read_uint32_array(const void *dtb, int node, const char *prop_name,
+			  unsigned int cells, uint32_t *value)
 {
-	const uint32_t *value_ptr;
-	uint32_t hi = 0, lo;
+	const fdt32_t *prop;
 	int value_len;
 
 	assert(dtb != NULL);
-	assert(prop != NULL);
+	assert(prop_name != NULL);
 	assert(value != NULL);
 	assert(node >= 0);
 
-	/* We expect either 1 or 2 cell property */
-	assert(cells <= 2U);
-
 	/* Access property and obtain its length (in bytes) */
-	value_ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop),
-			&value_len);
-	if (value_ptr == NULL) {
-		WARN("Couldn't find property %s in dtb\n", prop);
-		return -1;
+	prop = fdt_getprop(dtb, node, prop_name, &value_len);
+	if (prop == NULL) {
+		WARN("Couldn't find property %s in dtb\n", prop_name);
+		return -FDT_ERR_NOTFOUND;
 	}
 
-	/* Verify that property length accords with cell length */
-	if (NCELLS((unsigned int)value_len) != cells) {
+	/* Verify that property length can fill the entire array. */
+	if (NCELLS((unsigned int)value_len) < cells) {
 		WARN("Property length mismatch\n");
-		return -1;
+		return -FDT_ERR_BADVALUE;
 	}
 
-	if (cells == 2U) {
-		hi = fdt32_to_cpu(*value_ptr);
-		value_ptr++;
+	for (unsigned int i = 0U; i < cells; i++) {
+		value[i] = fdt32_to_cpu(prop[i]);
 	}
 
-	lo = fdt32_to_cpu(*value_ptr);
-
-	if (cells == 2U)
-		*((uint64_t *) value) = ((uint64_t) hi << 32) | lo;
-	else
-		*((uint32_t *) value) = lo;
-
 	return 0;
 }
 
-/*
- * Read cells from a given property of the given node. Any number of 32-bit
- * cells of the property can be read. The fdt pointer is updated. Returns 0 on
- * success, and -1 on error.
- */
-int fdtw_read_array(const void *dtb, int node, const char *prop,
-		unsigned int cells, void *value)
+int fdt_read_uint32(const void *dtb, int node, const char *prop_name,
+		    uint32_t *value)
 {
-	const uint32_t *value_ptr;
-	int value_len;
+	return fdt_read_uint32_array(dtb, node, prop_name, 1, value);
+}
 
-	assert(dtb != NULL);
-	assert(prop != NULL);
-	assert(value != NULL);
-	assert(node >= 0);
+uint32_t fdt_read_uint32_default(const void *dtb, int node,
+				 const char *prop_name, uint32_t dflt_value)
+{
+	uint32_t ret = dflt_value;
+	int err = fdt_read_uint32(dtb, node, prop_name, &ret);
 
-	/* Access property and obtain its length (in bytes) */
-	value_ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop),
-			&value_len);
-	if (value_ptr == NULL) {
-		WARN("Couldn't find property %s in dtb\n", prop);
-		return -1;
+	if (err < 0) {
+		return dflt_value;
 	}
 
-	/* Verify that property length accords with cell length */
-	if (NCELLS((unsigned int)value_len) != cells) {
-		WARN("Property length mismatch\n");
-		return -1;
-	}
+	return ret;
+}
 
-	uint32_t *dst = value;
+int fdt_read_uint64(const void *dtb, int node, const char *prop_name,
+		    uint64_t *value)
+{
+	uint32_t array[2] = {0, 0};
+	int ret;
 
-	for (unsigned int i = 0U; i < cells; i++) {
-		dst[i] = fdt32_to_cpu(value_ptr[i]);
+	ret = fdt_read_uint32_array(dtb, node, prop_name, 2, array);
+	if (ret < 0) {
+		return ret;
 	}
 
+	*value = ((uint64_t)array[0] << 32) | array[1];
 	return 0;
 }
 
@@ -244,3 +226,53 @@
 
 	return err;
 }
+
+static uint64_t fdt_read_prop_cells(const fdt32_t *prop, int nr_cells)
+{
+	uint64_t reg = fdt32_to_cpu(prop[0]);
+
+	if (nr_cells > 1) {
+		reg = (reg << 32) | fdt32_to_cpu(prop[1]);
+	}
+
+	return reg;
+}
+
+int fdt_get_reg_props_by_index(const void *dtb, int node, int index,
+			       uintptr_t *base, size_t *size)
+{
+	const fdt32_t *prop;
+	int parent, len;
+	int ac, sc;
+	int cell;
+
+	parent = fdt_parent_offset(dtb, node);
+	if (parent < 0) {
+		return -FDT_ERR_BADOFFSET;
+	}
+
+	ac = fdt_address_cells(dtb, parent);
+	sc = fdt_size_cells(dtb, parent);
+
+	cell = index * (ac + sc);
+
+	prop = fdt_getprop(dtb, node, "reg", &len);
+	if (prop == NULL) {
+		WARN("Couldn't find \"reg\" property in dtb\n");
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	if (((cell + ac + sc) * (int)sizeof(uint32_t)) > len) {
+		return -FDT_ERR_BADVALUE;
+	}
+
+	if (base != NULL) {
+		*base = (uintptr_t)fdt_read_prop_cells(&prop[cell], ac);
+	}
+
+	if (size != NULL) {
+		*size = (size_t)fdt_read_prop_cells(&prop[cell + ac], sc);
+	}
+
+	return 0;
+}
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
index 0cc87cc..540c66a 100644
--- a/drivers/st/clk/stm32mp1_clk.c
+++ b/drivers/st/clk/stm32mp1_clk.c
@@ -16,6 +16,7 @@
 #include <arch.h>
 #include <arch_helpers.h>
 #include <common/debug.h>
+#include <common/fdt_wrappers.h>
 #include <drivers/delay_timer.h>
 #include <drivers/generic_delay_timer.h>
 #include <drivers/st/stm32mp_clkfunc.h>
@@ -1239,7 +1240,8 @@
 	uintptr_t clksrc_address = rcc_base + (clksrc >> 4);
 	unsigned long refclk;
 	uint32_t ifrge = 0U;
-	uint32_t src, value, fracv;
+	uint32_t src, value, fracv = 0;
+	void *fdt;
 
 	/* Check PLL output */
 	if (mmio_read_32(pllxcr) != RCC_PLLNCR_PLLON) {
@@ -1278,7 +1280,9 @@
 	}
 
 	/* Fractional configuration */
-	fracv = fdt_read_uint32_default(plloff, "frac", 0);
+	if (fdt_get_address(&fdt) == 1) {
+		fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0);
+	}
 
 	value = fracv << RCC_PLLNFRACR_FRACV_SHIFT;
 	value |= RCC_PLLNFRACR_FRACLE;
@@ -1600,20 +1604,25 @@
 	bool pll4_preserve = false;
 	bool pll4_bootrom = false;
 	const fdt32_t *pkcs_cell;
+	void *fdt;
+
+	if (fdt_get_address(&fdt) == 0) {
+		return false;
+	}
 
 	/* Check status field to disable security */
 	if (!fdt_get_rcc_secure_status()) {
 		mmio_write_32(rcc_base + RCC_TZCR, 0);
 	}
 
-	ret = fdt_rcc_read_uint32_array("st,clksrc", clksrc,
-					(uint32_t)CLKSRC_NB);
+	ret = fdt_rcc_read_uint32_array("st,clksrc", (uint32_t)CLKSRC_NB,
+					clksrc);
 	if (ret < 0) {
 		return -FDT_ERR_NOTFOUND;
 	}
 
-	ret = fdt_rcc_read_uint32_array("st,clkdiv", clkdiv,
-					(uint32_t)CLKDIV_NB);
+	ret = fdt_rcc_read_uint32_array("st,clkdiv", (uint32_t)CLKDIV_NB,
+					clkdiv);
 	if (ret < 0) {
 		return -FDT_ERR_NOTFOUND;
 	}
@@ -1628,8 +1637,8 @@
 			continue;
 		}
 
-		ret = fdt_read_uint32_array(plloff[i], "cfg",
-					    pllcfg[i], (int)PLLCFG_NB);
+		ret = fdt_read_uint32_array(fdt, plloff[i], "cfg",
+					    (int)PLLCFG_NB, pllcfg[i]);
 		if (ret < 0) {
 			return -FDT_ERR_NOTFOUND;
 		}
@@ -1794,14 +1803,14 @@
 			continue;
 		}
 
-		fracv = fdt_read_uint32_default(plloff[i], "frac", 0);
+		fracv = fdt_read_uint32_default(fdt, plloff[i], "frac", 0);
 
 		ret = stm32mp1_pll_config(i, pllcfg[i], fracv);
 		if (ret != 0) {
 			return ret;
 		}
-		ret = fdt_read_uint32_array(plloff[i], "csg", csg,
-					    (uint32_t)PLLCSG_NB);
+		ret = fdt_read_uint32_array(fdt, plloff[i], "csg",
+					    (uint32_t)PLLCSG_NB, csg);
 		if (ret == 0) {
 			stm32mp1_pll_csg(i, csg);
 		} else if (ret != -FDT_ERR_NOTFOUND) {
diff --git a/drivers/st/clk/stm32mp_clkfunc.c b/drivers/st/clk/stm32mp_clkfunc.c
index 87c8e2b..e87ab1b 100644
--- a/drivers/st/clk/stm32mp_clkfunc.c
+++ b/drivers/st/clk/stm32mp_clkfunc.c
@@ -10,6 +10,7 @@
 
 #include <platform_def.h>
 
+#include <common/fdt_wrappers.h>
 #include <drivers/st/stm32_gpio.h>
 #include <drivers/st/stm32mp_clkfunc.h>
 
@@ -150,7 +151,8 @@
 			continue;
 		}
 
-		return fdt_read_uint32_default(subnode, prop_name, dflt_value);
+		return fdt_read_uint32_default(fdt, subnode, prop_name,
+					       dflt_value);
 	}
 
 	return dflt_value;
@@ -200,8 +202,8 @@
  * @param count: number of parameters to be read
  * @return: 0 on succes or a negative value on error
  */
-int fdt_rcc_read_uint32_array(const char *prop_name,
-			      uint32_t *array, uint32_t count)
+int fdt_rcc_read_uint32_array(const char *prop_name, uint32_t count,
+			      uint32_t *array)
 {
 	int node;
 	void *fdt;
@@ -215,7 +217,7 @@
 		return -FDT_ERR_NOTFOUND;
 	}
 
-	return fdt_read_uint32_array(node, prop_name, array, count);
+	return fdt_read_uint32_array(fdt, node, prop_name, count, array);
 }
 
 /*
diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c
index 40cd455..b21c894 100644
--- a/drivers/st/ddr/stm32mp1_ram.c
+++ b/drivers/st/ddr/stm32mp1_ram.c
@@ -12,6 +12,7 @@
 
 #include <arch_helpers.h>
 #include <common/debug.h>
+#include <common/fdt_wrappers.h>
 #include <drivers/st/stm32mp1_ddr.h>
 #include <drivers/st/stm32mp1_ddr_helpers.h>
 #include <drivers/st/stm32mp1_ram.h>
@@ -205,13 +206,13 @@
 		return -EINVAL;
 	}
 
-	config.info.speed = fdt_read_uint32_default(node, "st,mem-speed", 0);
-	if (!config.info.speed) {
+	ret = fdt_read_uint32(fdt, node, "st,mem-speed", &config.info.speed);
+	if (ret < 0) {
 		VERBOSE("%s: no st,mem-speed\n", __func__);
 		return -EINVAL;
 	}
-	config.info.size = fdt_read_uint32_default(node, "st,mem-size", 0);
-	if (!config.info.size) {
+	ret = fdt_read_uint32(fdt, node, "st,mem-size", &config.info.size);
+	if (ret < 0) {
 		VERBOSE("%s: no st,mem-size\n", __func__);
 		return -EINVAL;
 	}
@@ -223,10 +224,10 @@
 	INFO("RAM: %s\n", config.info.name);
 
 	for (idx = 0; idx < ARRAY_SIZE(param); idx++) {
-		ret = fdt_read_uint32_array(node, param[idx].name,
+		ret = fdt_read_uint32_array(fdt, node, param[idx].name,
+					    param[idx].size,
 					    (void *)((uintptr_t)&config +
-						     param[idx].offset),
-					    param[idx].size);
+						     param[idx].offset));
 
 		VERBOSE("%s: %s[0x%x] = %d\n", __func__,
 			param[idx].name, param[idx].size, ret);
diff --git a/include/arch/aarch32/arch.h b/include/arch/aarch32/arch.h
index 8492b3e..a11d55e 100644
--- a/include/arch/aarch32/arch.h
+++ b/include/arch/aarch32/arch.h
@@ -701,4 +701,14 @@
 #define AMEVTYPER1E	p15, 0, c13, c15, 6
 #define AMEVTYPER1F	p15, 0, c13, c15, 7
 
+/*******************************************************************************
+ * Definitions for DynamicIQ Shared Unit registers
+ ******************************************************************************/
+#define CLUSTERPWRDN	p15, 0, c15, c3, 6
+
+/* CLUSTERPWRDN register definitions */
+#define DSU_CLUSTER_PWR_OFF	0
+#define DSU_CLUSTER_PWR_ON	1
+#define DSU_CLUSTER_PWR_MASK	U(1)
+
 #endif /* ARCH_H */
diff --git a/include/arch/aarch32/arch_helpers.h b/include/arch/aarch32/arch_helpers.h
index a90b2a5..eed56e2 100644
--- a/include/arch/aarch32/arch_helpers.h
+++ b/include/arch/aarch32/arch_helpers.h
@@ -336,6 +336,11 @@
 DEFINE_DCOP_PARAM_FUNC(cvac, DCCMVAC)
 #endif
 
+/*
+ * DynamIQ Shared Unit power management
+ */
+DEFINE_COPROCR_RW_FUNCS(clusterpwrdn, CLUSTERPWRDN)
+
 /* Previously defined accessor functions with incomplete register names  */
 #define dsb()			dsbsy()
 #define dmb()			dmbsy()
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 19dd8c5..e45a594 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -947,4 +947,14 @@
 #define RGSR_EL1		S3_0_C1_C0_5
 #define GCR_EL1			S3_0_C1_C0_6
 
+/*******************************************************************************
+ * Definitions for DynamicIQ Shared Unit registers
+ ******************************************************************************/
+#define CLUSTERPWRDN_EL1	S3_0_c15_c3_6
+
+/* CLUSTERPWRDN_EL1 register definitions */
+#define DSU_CLUSTER_PWR_OFF	0
+#define DSU_CLUSTER_PWR_ON	1
+#define DSU_CLUSTER_PWR_MASK	U(1)
+
 #endif /* ARCH_H */
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 669a140..9cd1ae5 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -520,6 +520,9 @@
 DEFINE_RENAME_SYSREG_RW_FUNCS(rgsr_el1, RGSR_EL1)
 DEFINE_RENAME_SYSREG_RW_FUNCS(gcr_el1, GCR_EL1)
 
+/* DynamIQ Shared Unit power management */
+DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpwrdn_el1, CLUSTERPWRDN_EL1)
+
 #define IS_IN_EL(x) \
 	(GET_EL(read_CurrentEl()) == MODE_EL##x)
 
@@ -582,4 +585,7 @@
 #define read_cpacr()		read_cpacr_el1()
 #define write_cpacr(_v)		write_cpacr_el1(_v)
 
+#define read_clusterpwrdn()	read_clusterpwrdn_el1()
+#define write_clusterpwrdn(_v)	write_clusterpwrdn_el1(_v)
+
 #endif /* ARCH_HELPERS_H */
diff --git a/include/common/bl_common.ld.h b/include/common/bl_common.ld.h
index 8ea7d6a..97fed72 100644
--- a/include/common/bl_common.ld.h
+++ b/include/common/bl_common.ld.h
@@ -17,6 +17,10 @@
 #define BSS_ALIGN	8
 #endif
 
+#ifndef DATA_ALIGN
+#define DATA_ALIGN	1
+#endif
+
 #define CPU_OPS						\
 	. = ALIGN(STRUCT_ALIGN);			\
 	__CPU_OPS_START__ = .;				\
@@ -85,6 +89,18 @@
 	GOT						\
 	BASE_XLAT_TABLE_RO
 
+/*
+ * .data must be placed at a lower address than the stacks if the stack
+ * protector is enabled. Alternatively, the .data.stack_protector_canary
+ * section can be placed independently of the main .data section.
+ */
+#define DATA_SECTION					\
+	.data . : ALIGN(DATA_ALIGN) {			\
+		__DATA_START__ = .;			\
+		*(SORT_BY_ALIGNMENT(.data*))		\
+		__DATA_END__ = .;			\
+	}
+
 #define STACK_SECTION					\
 	stacks (NOLOAD) : {				\
 		__STACKS_START__ = .;			\
diff --git a/include/common/fdt_wrappers.h b/include/common/fdt_wrappers.h
index f467958..7a6b598 100644
--- a/include/common/fdt_wrappers.h
+++ b/include/common/fdt_wrappers.h
@@ -12,10 +12,14 @@
 /* Number of cells, given total length in bytes. Each cell is 4 bytes long */
 #define NCELLS(len) ((len) / 4U)
 
-int fdtw_read_cells(const void *dtb, int node, const char *prop,
-		unsigned int cells, void *value);
-int fdtw_read_array(const void *dtb, int node, const char *prop,
-		unsigned int cells, void *value);
+int fdt_read_uint32(const void *dtb, int node, const char *prop_name,
+		    uint32_t *value);
+uint32_t fdt_read_uint32_default(const void *dtb, int node,
+				 const char *prop_name, uint32_t dflt_value);
+int fdt_read_uint64(const void *dtb, int node, const char *prop_name,
+		    uint64_t *value);
+int fdt_read_uint32_array(const void *dtb, int node, const char *prop_name,
+			  unsigned int cells, uint32_t *value);
 int fdtw_read_string(const void *dtb, int node, const char *prop,
 		char *str, size_t size);
 int fdtw_write_inplace_cells(void *dtb, int node, const char *prop,
@@ -24,5 +28,7 @@
 		unsigned int length, void *value);
 int fdtw_write_inplace_bytes(void *dtb, int node, const char *prop,
 		unsigned int length, const void *data);
+int fdt_get_reg_props_by_index(const void *dtb, int node, int index,
+			       uintptr_t *base, size_t *size);
 
 #endif /* FDT_WRAPPERS_H */
diff --git a/include/drivers/st/stm32mp_clkfunc.h b/include/drivers/st/stm32mp_clkfunc.h
index 0769167..0902f44 100644
--- a/include/drivers/st/stm32mp_clkfunc.h
+++ b/include/drivers/st/stm32mp_clkfunc.h
@@ -21,8 +21,8 @@
 
 int fdt_get_rcc_node(void *fdt);
 uint32_t fdt_rcc_read_addr(void);
-int fdt_rcc_read_uint32_array(const char *prop_name,
-			      uint32_t *array, uint32_t count);
+int fdt_rcc_read_uint32_array(const char *prop_name, uint32_t count,
+			      uint32_t *array);
 int fdt_rcc_subnode_offset(const char *name);
 const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp);
 bool fdt_get_rcc_secure_status(void);
diff --git a/lib/fconf/fconf_dyn_cfg_getter.c b/lib/fconf/fconf_dyn_cfg_getter.c
index 317d3e5..03aaf9b 100644
--- a/lib/fconf/fconf_dyn_cfg_getter.c
+++ b/lib/fconf/fconf_dyn_cfg_getter.c
@@ -57,26 +57,32 @@
 	}
 
 	fdt_for_each_subnode(child, dtb, node) {
+		uint32_t val32;
+		uint64_t val64;
+
 		dtb_info = pool_alloc(&dtb_info_pool);
 
 		/* Read configuration dtb information */
-		rc = fdtw_read_cells(dtb, child, "load-address", 2, &dtb_info->config_addr);
+		rc = fdt_read_uint64(dtb, child, "load-address", &val64);
 		if (rc < 0) {
 			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
 			return rc;
 		}
+		dtb_info->config_addr = (uintptr_t)val64;
 
-		rc = fdtw_read_cells(dtb, child, "max-size", 1, &dtb_info->config_max_size);
+		rc = fdt_read_uint32(dtb, child, "max-size", &val32);
 		if (rc < 0) {
 			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
 			return rc;
 		}
+		dtb_info->config_max_size = val32;
 
-		rc = fdtw_read_cells(dtb, child, "id", 1, &dtb_info->config_id);
+		rc = fdt_read_uint32(dtb, child, "id", &val32);
 		if (rc < 0) {
 			ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
 			return rc;
 		}
+		dtb_info->config_id = val32;
 
 		VERBOSE("FCONF: dyn_cfg.dtb_registry cell found with:\n");
 		VERBOSE("\tload-address = %lx\n", dtb_info->config_addr);
diff --git a/lib/fconf/fconf_tbbr_getter.c b/lib/fconf/fconf_tbbr_getter.c
index a4d61d8..2127801 100644
--- a/lib/fconf/fconf_tbbr_getter.c
+++ b/lib/fconf/fconf_tbbr_getter.c
@@ -17,6 +17,8 @@
 {
 	int err;
 	int node;
+	uint64_t val64;
+	uint32_t val32;
 
 	/* As libfdt use void *, we can't avoid this cast */
 	const void *dtb = (void *)config;
@@ -30,7 +32,7 @@
 	}
 
 	/* Locate the disable_auth cell and read the value */
-	err = fdtw_read_cells(dtb, node, "disable_auth", 1, &tbbr_dyn_config.disable_auth);
+	err = fdt_read_uint32(dtb, node, "disable_auth", &tbbr_dyn_config.disable_auth);
 	if (err < 0) {
 		WARN("FCONF: Read cell failed for `disable_auth`\n");
 		return err;
@@ -48,19 +50,19 @@
 #endif
 
 	/* Retrieve the Mbed TLS heap details from the DTB */
-	err = fdtw_read_cells(dtb, node,
-		"mbedtls_heap_addr", 2, &tbbr_dyn_config.mbedtls_heap_addr);
+	err = fdt_read_uint64(dtb, node, "mbedtls_heap_addr", &val64);
 	if (err < 0) {
 		ERROR("FCONF: Read cell failed for mbedtls_heap\n");
 		return err;
 	}
+	tbbr_dyn_config.mbedtls_heap_addr = (void *)(uintptr_t)val64;
 
-	err = fdtw_read_cells(dtb, node,
-		"mbedtls_heap_size", 1, &tbbr_dyn_config.mbedtls_heap_size);
+	err = fdt_read_uint32(dtb, node, "mbedtls_heap_size", &val32);
 	if (err < 0) {
 		ERROR("FCONF: Read cell failed for mbedtls_heap\n");
 		return err;
 	}
+	tbbr_dyn_config.mbedtls_heap_size = val32;
 
 	VERBOSE("FCONF:tbbr.disable_auth cell found with value = %d\n",
 					tbbr_dyn_config.disable_auth);
diff --git a/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
index 2952cde..f1d9b93 100644
--- a/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
+++ b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
@@ -18,7 +18,7 @@
 {
 	int err;
 	int node;
-	int addr[20];
+	uintptr_t addr;
 
 	/* Necessary to work with libfdt APIs */
 	const void *hw_config_dtb = (const void *)config;
@@ -33,26 +33,32 @@
 		WARN("FCONF: Unable to locate node with arm,gic-v3 compatible property\n");
 		return 0;
 	}
-	/* Read the reg cell holding base address of GIC controller modules
-	A sample reg cell array is shown here:
-		reg = <0x0 0x2f000000 0 0x10000>,	// GICD
-		      <0x0 0x2f100000 0 0x200000>,	// GICR
-		      <0x0 0x2c000000 0 0x2000>,	// GICC
-		      <0x0 0x2c010000 0 0x2000>,	// GICH
-		      <0x0 0x2c02f000 0 0x2000>;	// GICV
-	*/
+	/* The GICv3 DT binding holds at least two address/size pairs,
+	 * the first describing the distributor, the second the redistributors.
+	 * See: bindings/interrupt-controller/arm,gic-v3.yaml
+	 */
+	err = fdt_get_reg_props_by_index(hw_config_dtb, node, 0, &addr, NULL);
+	if (err < 0) {
+		ERROR("FCONF: Failed to read GICD reg property of GIC node\n");
+		return err;
+	}
+	gicv3_config.gicd_base = addr;
 
-	err = fdtw_read_array(hw_config_dtb, node, "reg", 20, &addr);
+	err = fdt_get_reg_props_by_index(hw_config_dtb, node, 1, &addr, NULL);
 	if (err < 0) {
-		ERROR("FCONF: Failed to read reg property of GIC node\n");
+		ERROR("FCONF: Failed to read GICR reg property of GIC node\n");
+	} else {
+		gicv3_config.gicr_base = addr;
 	}
+
 	return err;
 }
 
 int fconf_populate_topology(uintptr_t config)
 {
-	int err, node, cluster_node, core_node, thread_node, max_pwr_lvl = 0;
+	int err, node, cluster_node, core_node, thread_node;
 	uint32_t cluster_count = 0, max_cpu_per_cluster = 0, total_cpu_count = 0;
+	uint32_t max_pwr_lvl = 0;
 
 	/* Necessary to work with libfdt APIs */
 	const void *hw_config_dtb = (const void *)config;
@@ -64,7 +70,7 @@
 		return node;
 	}
 
-	err = fdtw_read_cells(hw_config_dtb, node, "max-pwr-lvl", 1, &max_pwr_lvl);
+	err = fdt_read_uint32(hw_config_dtb, node, "max-pwr-lvl", &max_pwr_lvl);
 	if (err < 0) {
 		/*
 		 * Some legacy FVP dts may not have this property. Assign the default
@@ -74,7 +80,7 @@
 		max_pwr_lvl = 2;
 	}
 
-	assert((uint32_t)max_pwr_lvl <= MPIDR_AFFLVL2);
+	assert(max_pwr_lvl <= MPIDR_AFFLVL2);
 
 	/* Find the offset of the "cpus" node */
 	node = fdt_path_offset(hw_config_dtb, "/cpus");
@@ -156,7 +162,7 @@
 		return -1;
 	}
 
-	soc_topology.plat_max_pwr_level = (uint32_t)max_pwr_lvl;
+	soc_topology.plat_max_pwr_level = max_pwr_lvl;
 	soc_topology.plat_cluster_count = cluster_count;
 	soc_topology.cluster_cpu_count = max_cpu_per_cluster;
 	soc_topology.plat_cpu_count = total_cpu_count;
diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c
index c47d837..333d892 100644
--- a/plat/arm/board/fvp/fvp_pm.c
+++ b/plat/arm/board/fvp/fvp_pm.c
@@ -64,6 +64,25 @@
 	/* Disable coherency if this cluster is to be turned off */
 	fvp_interconnect_disable();
 
+#if HW_ASSISTED_COHERENCY
+	uint32_t reg;
+
+	/*
+	 * If we have determined this core to be the last man standing and we
+	 * intend to power down the cluster proactively, we provide a hint to
+	 * the power controller that cluster power is not required when all
+	 * cores are powered down.
+	 * Note that this is only an advisory to power controller and is supported
+	 * by SoCs with DynamIQ Shared Units only.
+	 */
+	reg = read_clusterpwrdn();
+
+	/* Clear and set bit 0 : Cluster power not required */
+	reg &= ~DSU_CLUSTER_PWR_MASK;
+	reg |= DSU_CLUSTER_PWR_OFF;
+	write_clusterpwrdn(reg);
+#endif
+
 	/* Program the power controller to turn the cluster off */
 	fvp_pwrc_write_pcoffr(mpidr);
 }
diff --git a/plat/arm/board/fvp/include/fconf_hw_config_getter.h b/plat/arm/board/fvp/include/fconf_hw_config_getter.h
index cab832f..a9e569e 100644
--- a/plat/arm/board/fvp/include/fconf_hw_config_getter.h
+++ b/plat/arm/board/fvp/include/fconf_hw_config_getter.h
@@ -15,8 +15,8 @@
 #define hw_config__topology_getter(prop) soc_topology.prop
 
 struct gicv3_config_t {
-	void *gicd_base;
-	void *gicr_base;
+	uintptr_t gicd_base;
+	uintptr_t gicr_base;
 };
 
 struct hw_topology_t {
diff --git a/plat/arm/board/fvp/jmptbl.i b/plat/arm/board/fvp/jmptbl.i
index 0c93d0a..50a5ba4 100644
--- a/plat/arm/board/fvp/jmptbl.i
+++ b/plat/arm/board/fvp/jmptbl.i
@@ -15,6 +15,7 @@
 # fdt	fdt_getprop_namelen	patch
 
 rom     rom_lib_init
+fdt     fdt_getprop
 fdt     fdt_getprop_namelen
 fdt     fdt_setprop_inplace
 fdt     fdt_check_header
@@ -24,6 +25,9 @@
 fdt     fdt_next_subnode
 fdt     fdt_path_offset
 fdt     fdt_subnode_offset
+fdt     fdt_address_cells
+fdt     fdt_size_cells
+fdt     fdt_parent_offset
 mbedtls mbedtls_asn1_get_alg
 mbedtls mbedtls_asn1_get_alg_null
 mbedtls mbedtls_asn1_get_bitstring_null
diff --git a/plat/arm/board/juno/jmptbl.i b/plat/arm/board/juno/jmptbl.i
index b1b9ed4..eb4399e 100644
--- a/plat/arm/board/juno/jmptbl.i
+++ b/plat/arm/board/juno/jmptbl.i
@@ -15,6 +15,7 @@
 # fdt	fdt_getprop_namelen	patch
 
 rom     rom_lib_init
+fdt     fdt_getprop
 fdt     fdt_getprop_namelen
 fdt     fdt_setprop_inplace
 fdt     fdt_check_header
@@ -22,6 +23,7 @@
 fdt     fdt_setprop_inplace_namelen_partial
 fdt     fdt_first_subnode
 fdt     fdt_next_subnode
+fdt     fdt_parent_offset
 mbedtls mbedtls_asn1_get_alg
 mbedtls mbedtls_asn1_get_alg_null
 mbedtls mbedtls_asn1_get_bitstring_null
diff --git a/plat/arm/board/rddanielxlr/fdts/rddanielxlr_fw_config.dts b/plat/arm/board/rddanielxlr/fdts/rddanielxlr_fw_config.dts
new file mode 100644
index 0000000..81e4cc1
--- /dev/null
+++ b/plat/arm/board/rddanielxlr/fdts/rddanielxlr_fw_config.dts
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <export/common/tbbr/tbbr_img_def_exp.h>
+
+/dts-v1/;
+
+/ {
+	dtb-registry {
+		compatible = "arm,dyn_cfg-dtb_registry";
+
+		/* tb_fw_config is temporarily contained on this dtb */
+		tb_fw-config {
+			load-address = <0x0 0x4001010>;
+			max-size = <0x200>;
+			id = <TB_FW_CONFIG_ID>;
+		};
+
+		nt_fw-config {
+			load-address = <0x0 0xFEF00000>;
+			max-size = <0x0100000>;
+			id = <NT_FW_CONFIG_ID>;
+		};
+	};
+
+	tb_fw-config {
+		compatible = "arm,tb_fw";
+
+		/* Disable authentication for development */
+		disable_auth = <0x0>;
+
+		/*
+		 * The following two entries are placeholders for Mbed TLS
+		 * heap information. The default values don't matter since
+		 * they will be overwritten by BL1.
+		 * In case of having shared Mbed TLS heap between BL1 and BL2,
+		 * BL1 will populate these two properties with the respective
+		 * info about the shared heap. This info will be available for
+		 * BL2 in order to locate and re-use the heap.
+		 */
+		mbedtls_heap_addr = <0x0 0x0>;
+		mbedtls_heap_size = <0x0>;
+	};
+};
diff --git a/plat/arm/board/rddanielxlr/fdts/rddanielxlr_nt_fw_config.dts b/plat/arm/board/rddanielxlr/fdts/rddanielxlr_nt_fw_config.dts
new file mode 100644
index 0000000..42d07a4
--- /dev/null
+++ b/plat/arm/board/rddanielxlr/fdts/rddanielxlr_nt_fw_config.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/dts-v1/;
+/ {
+	/* compatible string */
+	compatible = "arm,rd-daniel-xlr";
+
+	/*
+	 * Place holder for system-id node with default values. The
+	 * value of platform-id and config-id will be set to the
+	 * correct values during the BL2 stage of boot.
+	 */
+	system-id {
+		platform-id = <0x0>;
+		config-id = <0x0>;
+		multi-chip-mode = <0x0>;
+	};
+};
diff --git a/plat/arm/board/rddanielxlr/include/platform_def.h b/plat/arm/board/rddanielxlr/include/platform_def.h
new file mode 100644
index 0000000..b1376b8
--- /dev/null
+++ b/plat/arm/board/rddanielxlr/include/platform_def.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PLATFORM_DEF_H
+#define PLATFORM_DEF_H
+
+#include <lib/utils_def.h>
+#include <sgi_base_platform_def.h>
+
+#define PLAT_ARM_CLUSTER_COUNT		U(4)
+#define CSS_SGI_MAX_CPUS_PER_CLUSTER	U(1)
+#define CSS_SGI_MAX_PE_PER_CPU		U(1)
+
+#define PLAT_CSS_MHU_BASE		UL(0x45400000)
+#define PLAT_MHUV2_BASE			PLAT_CSS_MHU_BASE
+
+#define CSS_SYSTEM_PWR_DMN_LVL		ARM_PWR_LVL2
+#define PLAT_MAX_PWR_LVL		ARM_PWR_LVL1
+
+/* Virtual address used by dynamic mem_protect for chunk_base */
+#define PLAT_ARM_MEM_PROTEC_VA_FRAME	UL(0xC0000000)
+
+/* Physical and virtual address space limits for MMU in AARCH64 mode */
+#define PLAT_PHY_ADDR_SPACE_SIZE	CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \
+						CSS_SGI_CHIP_COUNT)
+#define PLAT_VIRT_ADDR_SPACE_SIZE	CSS_SGI_REMOTE_CHIP_MEM_OFFSET( \
+						CSS_SGI_CHIP_COUNT)
+
+/* GIC related constants */
+#define PLAT_ARM_GICD_BASE		UL(0x30000000)
+#define PLAT_ARM_GICC_BASE		UL(0x2C000000)
+#define PLAT_ARM_GICR_BASE		UL(0x30140000)
+
+#endif /* PLATFORM_DEF_H */
diff --git a/plat/arm/board/rddanielxlr/platform.mk b/plat/arm/board/rddanielxlr/platform.mk
new file mode 100644
index 0000000..36a0099
--- /dev/null
+++ b/plat/arm/board/rddanielxlr/platform.mk
@@ -0,0 +1,57 @@
+# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Enable GICv4 extension with multichip driver
+GIC_ENABLE_V4_EXTN		:=	1
+GICV3_IMPL_GIC600_MULTICHIP	:=	1
+
+include plat/arm/css/sgi/sgi-common.mk
+
+RDDANIELXLR_BASE	=	plat/arm/board/rddanielxlr
+
+PLAT_INCLUDES		+=	-I${RDDANIELXLR_BASE}/include/
+
+SGI_CPU_SOURCES		:=	lib/cpus/aarch64/neoverse_zeus.S
+
+BL1_SOURCES		+=	${SGI_CPU_SOURCES}			\
+				${RDDANIELXLR_BASE}/rddanielxlr_err.c
+
+BL2_SOURCES		+=	${RDDANIELXLR_BASE}/rddanielxlr_plat.c	\
+				${RDDANIELXLR_BASE}/rddanielxlr_security.c	\
+				${RDDANIELXLR_BASE}/rddanielxlr_err.c	\
+				lib/utils/mem_region.c			\
+				plat/arm/common/arm_nor_psci_mem_protect.c
+
+BL31_SOURCES		+=	${SGI_CPU_SOURCES}			\
+				${RDDANIELXLR_BASE}/rddanielxlr_plat.c	\
+				${RDDANIELXLR_BASE}/rddanielxlr_topology.c	\
+				drivers/cfi/v2m/v2m_flash.c		\
+				drivers/arm/gic/v3/gic600_multichip.c	\
+				lib/utils/mem_region.c			\
+				plat/arm/common/arm_nor_psci_mem_protect.c
+
+# Enable dynamic addition of MMAP regions in BL31
+BL31_CFLAGS		+=	-DPLAT_XLAT_TABLES_DYNAMIC
+
+# Add the FDT_SOURCES and options for Dynamic Config
+FDT_SOURCES		+=	${RDDANIELXLR_BASE}/fdts/${PLAT}_fw_config.dts
+TB_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_fw_config.dtb
+
+# Add the TB_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config))
+
+$(eval $(call CREATE_SEQ,SEQ,4))
+ifneq ($(CSS_SGI_CHIP_COUNT),$(filter $(CSS_SGI_CHIP_COUNT),$(SEQ)))
+ $(error  "Chip count for RD-Daniel Config-XLR should be either $(SEQ) \
+ currently it is set to ${CSS_SGI_CHIP_COUNT}.")
+endif
+
+FDT_SOURCES		+=	${RDDANIELXLR_BASE}/fdts/${PLAT}_nt_fw_config.dts
+NT_FW_CONFIG		:=	${BUILD_PLAT}/fdts/${PLAT}_nt_fw_config.dtb
+
+# Add the NT_FW_CONFIG to FIP and specify the same to certtool
+$(eval $(call TOOL_ADD_PAYLOAD,${NT_FW_CONFIG},--nt-fw-config))
+
+override CTX_INCLUDE_AARCH32_REGS	:= 0
diff --git a/plat/arm/board/rddanielxlr/rddanielxlr_err.c b/plat/arm/board/rddanielxlr/rddanielxlr_err.c
new file mode 100644
index 0000000..bff57cd
--- /dev/null
+++ b/plat/arm/board/rddanielxlr/rddanielxlr_err.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/arm/common/plat_arm.h>
+
+/*
+ * rddanielxlr error handler
+ */
+void __dead2 plat_arm_error_handler(int err)
+{
+	while (true) {
+		wfi();
+	}
+}
diff --git a/plat/arm/board/rddanielxlr/rddanielxlr_plat.c b/plat/arm/board/rddanielxlr/rddanielxlr_plat.c
new file mode 100644
index 0000000..4b5f16a
--- /dev/null
+++ b/plat/arm/board/rddanielxlr/rddanielxlr_plat.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/arm/gic600_multichip.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/common/platform.h>
+#include <sgi_base_platform_def.h>
+#include <sgi_plat.h>
+
+#if defined(IMAGE_BL31)
+static const mmap_region_t rddanielxlr_dynamic_mmap[] = {
+	ARM_MAP_SHARED_RAM_REMOTE_CHIP(1),
+	CSS_SGI_MAP_DEVICE_REMOTE_CHIP(1),
+	SOC_CSS_MAP_DEVICE_REMOTE_CHIP(1),
+#if (CSS_SGI_CHIP_COUNT > 2)
+	ARM_MAP_SHARED_RAM_REMOTE_CHIP(2),
+	CSS_SGI_MAP_DEVICE_REMOTE_CHIP(2),
+	SOC_CSS_MAP_DEVICE_REMOTE_CHIP(2),
+#endif
+#if (CSS_SGI_CHIP_COUNT > 3)
+	ARM_MAP_SHARED_RAM_REMOTE_CHIP(3),
+	CSS_SGI_MAP_DEVICE_REMOTE_CHIP(3),
+	SOC_CSS_MAP_DEVICE_REMOTE_CHIP(3)
+#endif
+};
+
+static struct gic600_multichip_data rddanielxlr_multichip_data __init = {
+	.rt_owner_base = PLAT_ARM_GICD_BASE,
+	.rt_owner = 0,
+	.chip_count = CSS_SGI_CHIP_COUNT,
+	.chip_addrs = {
+		PLAT_ARM_GICD_BASE >> 16,
+		(PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1)) >> 16,
+#if (CSS_SGI_CHIP_COUNT > 2)
+		(PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(2)) >> 16,
+#endif
+#if (CSS_SGI_CHIP_COUNT > 3)
+		(PLAT_ARM_GICD_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(3)) >> 16,
+#endif
+	},
+	.spi_ids = {
+		{32, 255},
+		{0, 0},
+#if (CSS_SGI_CHIP_COUNT > 2)
+		{0, 0},
+#endif
+#if (CSS_SGI_CHIP_COUNT > 3)
+		{0, 0},
+#endif
+	}
+};
+
+static uintptr_t rddanielxlr_multichip_gicr_frames[] = {
+	/* Chip 0's GICR Base */
+	PLAT_ARM_GICR_BASE,
+	/* Chip 1's GICR BASE */
+	PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(1),
+#if (CSS_SGI_CHIP_COUNT > 2)
+	/* Chip 2's GICR BASE */
+	PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(2),
+#endif
+#if (CSS_SGI_CHIP_COUNT > 3)
+	/* Chip 3's GICR BASE */
+	PLAT_ARM_GICR_BASE + CSS_SGI_REMOTE_CHIP_MEM_OFFSET(3),
+#endif
+	UL(0)	/* Zero Termination */
+};
+#endif /* IMAGE_BL31 */
+
+unsigned int plat_arm_sgi_get_platform_id(void)
+{
+	return mmio_read_32(SID_REG_BASE + SID_SYSTEM_ID_OFFSET)
+				& SID_SYSTEM_ID_PART_NUM_MASK;
+}
+
+unsigned int plat_arm_sgi_get_config_id(void)
+{
+	return mmio_read_32(SID_REG_BASE + SID_SYSTEM_CFG_OFFSET);
+}
+
+unsigned int plat_arm_sgi_get_multi_chip_mode(void)
+{
+	return (mmio_read_32(SID_REG_BASE + SID_NODE_ID_OFFSET) &
+			SID_MULTI_CHIP_MODE_MASK) >> SID_MULTI_CHIP_MODE_SHIFT;
+}
+
+/*
+ * bl31_platform_setup_function is guarded by IMAGE_BL31 macro because
+ * PLAT_XLAT_TABLES_DYNAMIC macro is set to build only for BL31 and not
+ * for other stages.
+ */
+#if defined(IMAGE_BL31)
+void bl31_platform_setup(void)
+{
+	int ret;
+	unsigned int i;
+
+	if ((plat_arm_sgi_get_multi_chip_mode() == 0) &&
+			(CSS_SGI_CHIP_COUNT > 1)) {
+		ERROR("Chip Count is set to %u but multi-chip mode is not "
+			"enabled\n", CSS_SGI_CHIP_COUNT);
+		panic();
+	} else if ((plat_arm_sgi_get_multi_chip_mode() == 1) &&
+			(CSS_SGI_CHIP_COUNT > 1)) {
+		INFO("Enabling support for multi-chip in RD-Daniel Cfg-XLR\n");
+
+		for (i = 0; i < ARRAY_SIZE(rddanielxlr_dynamic_mmap); i++) {
+			ret = mmap_add_dynamic_region(
+					rddanielxlr_dynamic_mmap[i].base_pa,
+					rddanielxlr_dynamic_mmap[i].base_va,
+					rddanielxlr_dynamic_mmap[i].size,
+					rddanielxlr_dynamic_mmap[i].attr);
+			if (ret != 0) {
+				ERROR("Failed to add dynamic mmap entry "
+						"(ret=%d)\n", ret);
+				panic();
+			}
+		}
+
+		plat_arm_override_gicr_frames(
+			rddanielxlr_multichip_gicr_frames);
+		gic600_multichip_init(&rddanielxlr_multichip_data);
+	}
+
+	sgi_bl31_common_platform_setup();
+}
+#endif /* IMAGE_BL31 */
diff --git a/plat/arm/board/rddanielxlr/rddanielxlr_security.c b/plat/arm/board/rddanielxlr/rddanielxlr_security.c
new file mode 100644
index 0000000..541f800
--- /dev/null
+++ b/plat/arm/board/rddanielxlr/rddanielxlr_security.c
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Initialize the secure environment */
+void plat_arm_security_setup(void)
+{
+}
diff --git a/plat/arm/board/rddanielxlr/rddanielxlr_topology.c b/plat/arm/board/rddanielxlr/rddanielxlr_topology.c
new file mode 100644
index 0000000..610e667
--- /dev/null
+++ b/plat/arm/board/rddanielxlr/rddanielxlr_topology.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <plat/arm/common/plat_arm.h>
+#include <plat/arm/css/common/css_pm.h>
+#include <sgi_variant.h>
+
+/******************************************************************************
+ * The power domain tree descriptor.
+ ******************************************************************************/
+const unsigned char rd_daniel_xlr_pd_tree_desc_multi_chip[] = {
+	((PLAT_ARM_CLUSTER_COUNT) * (CSS_SGI_CHIP_COUNT)),
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+#if (CSS_SGI_CHIP_COUNT > 1)
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+#endif
+#if (CSS_SGI_CHIP_COUNT > 2)
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+#endif
+#if (CSS_SGI_CHIP_COUNT > 3)
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER,
+	CSS_SGI_MAX_CPUS_PER_CLUSTER
+#endif
+};
+
+/*******************************************************************************
+ * This function returns the topology tree information.
+ ******************************************************************************/
+const unsigned char *plat_get_power_domain_tree_desc(void)
+{
+	if (plat_arm_sgi_get_multi_chip_mode() == 1)
+		return rd_daniel_xlr_pd_tree_desc_multi_chip;
+	panic();
+}
+
+/*******************************************************************************
+ * The array mapping platform core position (implemented by plat_my_core_pos())
+ * to the SCMI power domain ID implemented by SCP.
+ ******************************************************************************/
+const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[] = {
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x0)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x1)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x2)),
+	(SET_SCMI_CHANNEL_ID(0x0) | SET_SCMI_DOMAIN_ID(0x3)),
+#if (CSS_SGI_CHIP_COUNT > 1)
+	(SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x0)),
+	(SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x1)),
+	(SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x2)),
+	(SET_SCMI_CHANNEL_ID(0x1) | SET_SCMI_DOMAIN_ID(0x3)),
+#endif
+#if (CSS_SGI_CHIP_COUNT > 2)
+	(SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x0)),
+	(SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x1)),
+	(SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x2)),
+	(SET_SCMI_CHANNEL_ID(0x2) | SET_SCMI_DOMAIN_ID(0x3)),
+#endif
+#if (CSS_SGI_CHIP_COUNT > 3)
+	(SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x0)),
+	(SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x1)),
+	(SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x2)),
+	(SET_SCMI_CHANNEL_ID(0x3) | SET_SCMI_DOMAIN_ID(0x3))
+#endif
+};
diff --git a/plat/arm/common/fconf/arm_fconf_io.c b/plat/arm/common/fconf/arm_fconf_io.c
index 6ebc467..26e51b2 100644
--- a/plat/arm/common/fconf/arm_fconf_io.c
+++ b/plat/arm/common/fconf/arm_fconf_io.c
@@ -241,7 +241,8 @@
 	/* Locate the uuid cells and read the value for all the load info uuid */
 	for (i = 0; i < FCONF_ARM_IO_UUID_NUMBER; i++) {
 		uuid_ptr = pool_alloc(&fconf_arm_uuids_pool);
-		err = fdtw_read_array(dtb, node, load_info[i].name, 4, &uuid_helper.word);
+		err = fdt_read_uint32_array(dtb, node, load_info[i].name,
+					    4, uuid_helper.word);
 		if (err < 0) {
 			WARN("FCONF: Read cell failed for %s\n", load_info[i].name);
 			return err;
diff --git a/plat/arm/common/fconf/arm_fconf_sp.c b/plat/arm/common/fconf/arm_fconf_sp.c
index 9b6fa9b..1b09bc8 100644
--- a/plat/arm/common/fconf/arm_fconf_sp.c
+++ b/plat/arm/common/fconf/arm_fconf_sp.c
@@ -29,6 +29,7 @@
 	int sp_node, node, err;
 	union uuid_helper_t uuid_helper;
 	unsigned int index = 0;
+	uint32_t val32;
 	const unsigned int sp_start_index = MAX_NUMBER_IDS - MAX_SP_IDS;
 
 	/* As libfdt use void *, we can't avoid this cast */
@@ -44,8 +45,8 @@
 	}
 
 	fdt_for_each_subnode(sp_node, dtb, node) {
-		err = fdtw_read_array(dtb, sp_node, "uuid", 4,
-				      &uuid_helper.word);
+		err = fdt_read_uint32_array(dtb, sp_node, "uuid", 4,
+					    uuid_helper.word);
 		if (err < 0) {
 			ERROR("FCONF: cannot read SP uuid\n");
 			return -1;
@@ -53,12 +54,12 @@
 
 		arm_sp.uuids[index] = uuid_helper;
 
-		err = fdtw_read_cells(dtb, sp_node, "load-address", 1,
-			&arm_sp.load_addr[index]);
+		err = fdt_read_uint32(dtb, sp_node, "load-address", &val32);
 		if (err < 0) {
 			ERROR("FCONF: cannot read SP load address\n");
 			return -1;
 		}
+		arm_sp.load_addr[index] = val32;
 
 		VERBOSE("FCONF: %s UUID %x-%x-%x-%x load_addr=%lx\n",
 			__func__,
diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c
index af69c6f..8e74526 100644
--- a/plat/arm/css/common/css_pm.c
+++ b/plat/arm/css/common/css_pm.c
@@ -124,8 +124,28 @@
 	plat_arm_gic_cpuif_disable();
 
 	/* Cluster is to be turned off, so disable coherency */
-	if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF)
+	if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) {
 		plat_arm_interconnect_exit_coherency();
+
+#if HW_ASSISTED_COHERENCY
+		uint32_t reg;
+
+		/*
+		 * If we have determined this core to be the last man standing and we
+		 * intend to power down the cluster proactively, we provide a hint to
+		 * the power controller that cluster power is not required when all
+		 * cores are powered down.
+		 * Note that this is only an advisory to power controller and is supported
+		 * by SoCs with DynamIQ Shared Units only.
+		 */
+		reg = read_clusterpwrdn();
+
+		/* Clear and set bit 0 : Cluster power not required */
+		reg &= ~DSU_CLUSTER_PWR_MASK;
+		reg |= DSU_CLUSTER_PWR_OFF;
+		write_clusterpwrdn(reg);
+#endif
+	}
 }
 
 /*******************************************************************************
diff --git a/plat/common/plat_spmd_manifest.c b/plat/common/plat_spmd_manifest.c
index f0aa27c..8330356 100644
--- a/plat/common/plat_spmd_manifest.c
+++ b/plat/common/plat_spmd_manifest.c
@@ -21,41 +21,43 @@
 				    const void *fdt,
 				    int node)
 {
+	uint32_t val32;
 	int rc = 0;
 
 	assert(attr && fdt);
 
-	rc = fdtw_read_cells(fdt, node, "maj_ver", 1, &attr->major_version);
+	rc = fdt_read_uint32(fdt, node, "maj_ver", &attr->major_version);
 	if (rc) {
 		ERROR("Missing SPCI major version in SPM core manifest.\n");
 		return -ENOENT;
 	}
 
-	rc = fdtw_read_cells(fdt, node, "min_ver", 1, &attr->minor_version);
+	rc = fdt_read_uint32(fdt, node, "min_ver", &attr->minor_version);
 	if (rc) {
 		ERROR("Missing SPCI minor version in SPM core manifest.\n");
 		return -ENOENT;
 	}
 
-	rc = fdtw_read_cells(fdt, node, "spmc_id", 1, &attr->spmc_id);
+	rc = fdt_read_uint32(fdt, node, "spmc_id", &val32);
 	if (rc) {
 		ERROR("Missing SPMC ID in manifest.\n");
 		return -ENOENT;
 	}
+	attr->spmc_id = val32;
 
-	rc = fdtw_read_cells(fdt, node, "exec_state", 1, &attr->exec_state);
+	rc = fdt_read_uint32(fdt, node, "exec_state", &attr->exec_state);
 	if (rc)
 		NOTICE("Execution state not specified in SPM core manifest.\n");
 
-	rc = fdtw_read_cells(fdt, node, "binary_size", 1, &attr->binary_size);
+	rc = fdt_read_uint32(fdt, node, "binary_size", &attr->binary_size);
 	if (rc)
 		NOTICE("Binary size not specified in SPM core manifest.\n");
 
-	rc = fdtw_read_cells(fdt, node, "load_address", 2, &attr->load_address);
+	rc = fdt_read_uint64(fdt, node, "load_address", &attr->load_address);
 	if (rc)
 		NOTICE("Load address not specified in SPM core manifest.\n");
 
-	rc = fdtw_read_cells(fdt, node, "entrypoint", 2, &attr->entrypoint);
+	rc = fdt_read_uint64(fdt, node, "entrypoint", &attr->entrypoint);
 	if (rc)
 		NOTICE("Entrypoint not specified in SPM core manifest.\n");
 
diff --git a/plat/mediatek/mt6795/bl31.ld.S b/plat/mediatek/mt6795/bl31.ld.S
index b061b91..3d881fc 100644
--- a/plat/mediatek/mt6795/bl31.ld.S
+++ b/plat/mediatek/mt6795/bl31.ld.S
@@ -59,27 +59,13 @@
      */
     __RW_START__ = . ;
 
-    /*
-     * .data must be placed at a lower address than the stacks if the stack
-     * protector is enabled. Alternatively, the .data.stack_protector_canary
-     * section can be placed independently of the main .data section.
-     */
-    .data . : {
-        __DATA_START__ = .;
-        *(.data*)
-        __DATA_END__ = .;
-    } >RAM
+    DATA_SECTION >RAM
 
 #ifdef BL31_PROGBITS_LIMIT
     ASSERT(. <= BL31_PROGBITS_LIMIT, "BL3-1 progbits has exceeded its limit.")
 #endif
 
-    stacks (NOLOAD) : {
-        __STACKS_START__ = .;
-        *(tzfw_normal_stacks)
-        __STACKS_END__ = .;
-    } >RAM
-
+    STACK_SECTION >RAM
     BSS_SECTION >RAM
     __RW_END__ = __BSS_END__;
 
diff --git a/plat/st/common/include/stm32mp_dt.h b/plat/st/common/include/stm32mp_dt.h
index a29d914..91a8d67 100644
--- a/plat/st/common/include/stm32mp_dt.h
+++ b/plat/st/common/include/stm32mp_dt.h
@@ -28,10 +28,6 @@
 int fdt_get_address(void **fdt_addr);
 bool fdt_check_node(int node);
 uint8_t fdt_get_status(int node);
-uint32_t fdt_read_uint32_default(int node, const char *prop_name,
-				 uint32_t dflt_value);
-int fdt_read_uint32_array(int node, const char *prop_name,
-			  uint32_t *array, uint32_t count);
 int fdt_get_reg_props_by_name(int node, const char *name, uintptr_t *base,
 			      size_t *size);
 int dt_set_stdout_pinctrl(void);
diff --git a/plat/st/common/stm32mp_dt.c b/plat/st/common/stm32mp_dt.c
index acb323c..c76b033 100644
--- a/plat/st/common/stm32mp_dt.c
+++ b/plat/st/common/stm32mp_dt.c
@@ -12,6 +12,7 @@
 #include <platform_def.h>
 
 #include <common/debug.h>
+#include <common/fdt_wrappers.h>
 #include <drivers/st/stm32_gpio.h>
 #include <drivers/st/stm32mp1_ddr.h>
 #include <drivers/st/stm32mp1_ram.h>
@@ -135,59 +136,6 @@
 #endif
 
 /*******************************************************************************
- * This function reads a value of a node property (generic use of fdt
- * library).
- * Returns value if success, and a default value if property not found.
- * Default value is passed as parameter.
- ******************************************************************************/
-uint32_t fdt_read_uint32_default(int node, const char *prop_name,
-				 uint32_t dflt_value)
-{
-	const fdt32_t *cuint;
-	int lenp;
-
-	cuint = fdt_getprop(fdt, node, prop_name, &lenp);
-	if (cuint == NULL) {
-		return dflt_value;
-	}
-
-	return fdt32_to_cpu(*cuint);
-}
-
-/*******************************************************************************
- * This function reads a series of parameters in a node property
- * (generic use of fdt library).
- * It reads the values inside the device tree, from property name and node.
- * The number of parameters is also indicated as entry parameter.
- * Returns 0 on success and a negative FDT error code on failure.
- * If success, values are stored at the third parameter address.
- ******************************************************************************/
-int fdt_read_uint32_array(int node, const char *prop_name, uint32_t *array,
-			  uint32_t count)
-{
-	const fdt32_t *cuint;
-	int len;
-	uint32_t i;
-
-	cuint = fdt_getprop(fdt, node, prop_name, &len);
-	if (cuint == NULL) {
-		return -FDT_ERR_NOTFOUND;
-	}
-
-	if ((uint32_t)len != (count * sizeof(uint32_t))) {
-		return -FDT_ERR_BADLAYOUT;
-	}
-
-	for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) {
-		*array = fdt32_to_cpu(*cuint);
-		array++;
-		cuint++;
-	}
-
-	return 0;
-}
-
-/*******************************************************************************
  * This function fills reg node info (base & size) with an index found by
  * checking the reg-names node.
  * Returns 0 on success and a negative FDT error code on failure.
@@ -375,7 +323,7 @@
 		return 0;
 	}
 
-	return fdt_read_uint32_default(node, "st,mem-size", 0);
+	return fdt_read_uint32_default(fdt, node, "st,mem-size", 0);
 }
 
 /*******************************************************************************
@@ -396,7 +344,7 @@
 	assert((fdt_get_node_parent_address_cells(node) == 1) &&
 	       (fdt_get_node_parent_size_cells(node) == 1));
 
-	if (fdt_read_uint32_array(node, "reg", array, 4) < 0) {
+	if (fdt_read_uint32_array(fdt, node, "reg", 4, array) < 0) {
 		return 0;
 	}
 
@@ -421,7 +369,7 @@
 	assert((fdt_get_node_parent_address_cells(node) == 1) &&
 	       (fdt_get_node_parent_size_cells(node) == 1));
 
-	if (fdt_read_uint32_array(node, "reg", array, 4) < 0) {
+	if (fdt_read_uint32_array(fdt, node, "reg", 4, array) < 0) {
 		return 0;
 	}
 
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index 5ce7a9c..b0ba82a 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -62,7 +62,8 @@
 
 include lib/libfdt/libfdt.mk
 
-PLAT_BL_COMMON_SOURCES	:=	plat/st/common/stm32mp_common.c				\
+PLAT_BL_COMMON_SOURCES	:=	common/fdt_wrappers.c					\
+				plat/st/common/stm32mp_common.c				\
 				plat/st/stm32mp1/stm32mp1_private.c
 
 PLAT_BL_COMMON_SOURCES	+=	drivers/st/uart/aarch32/stm32_console.S