arm: fconf: Fix GICv3 dynamic configuration

At the moment the fconf_populate_gicv3_config() implementation is
somewhat incomplete: First it actually fails to store the retrieved
information (the local addr[] array is going nowhere), but also it makes
quite some assumptions about the device tree passed to it: it needs to
use two address-cells and two size-cells, and also requires all five
register regions to be specified, where actually only the first two
are mandatory according to the binding (and needed by our code).

Fix this by introducing a proper generic function to retrieve "reg"
property information from a DT node:
We retrieve the #address-cells and #size-cells properties from the
parent node, then use those to extract the right values from the "reg"
property. The function takes an index to select one region of a reg
property.

This is loosely based on the STM32 implementation using "reg-names",
which we will subsume in a follow-up patch.

Change-Id: Ia59bfdf80aea4e36876c7b6ed4d153e303f482e8
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
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 44e9d01..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;
-	uint32_t addr[20];
+	uintptr_t addr;
 
 	/* Necessary to work with libfdt APIs */
 	const void *hw_config_dtb = (const void *)config;
@@ -33,19 +33,24 @@
 		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 = fdt_read_uint32_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;
 }
 
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 6469e29..50a5ba4 100644
--- a/plat/arm/board/fvp/jmptbl.i
+++ b/plat/arm/board/fvp/jmptbl.i
@@ -25,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