diff --git a/common/fdt_wrappers.c b/common/fdt_wrappers.c index 57e3bcd40..842d71339 100644 --- a/common/fdt_wrappers.c +++ b/common/fdt_wrappers.c @@ -226,3 +226,53 @@ int fdtw_write_inplace_bytes(void *dtb, int node, const char *prop, 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/include/common/fdt_wrappers.h b/include/common/fdt_wrappers.h index 852fe1bf8..7a6b59893 100644 --- a/include/common/fdt_wrappers.h +++ b/include/common/fdt_wrappers.h @@ -28,5 +28,7 @@ int fdtw_read_bytes(const void *dtb, int node, const char *prop, 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/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c index 44e9d0135..f1d9b93f7 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 fconf_populate_gicv3_config(uintptr_t config) { 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 @@ int fconf_populate_gicv3_config(uintptr_t config) 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 - */ - - err = fdt_read_uint32_array(hw_config_dtb, node, "reg", 20, addr); + /* 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 reg property of GIC node\n"); + ERROR("FCONF: Failed to read GICD reg property of GIC node\n"); + return err; } + gicv3_config.gicd_base = addr; + + err = fdt_get_reg_props_by_index(hw_config_dtb, node, 1, &addr, NULL); + if (err < 0) { + 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 cab832f68..a9e569e78 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 6469e2995..50a5ba4d9 100644 --- a/plat/arm/board/fvp/jmptbl.i +++ b/plat/arm/board/fvp/jmptbl.i @@ -25,6 +25,9 @@ fdt fdt_first_subnode 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 66d6e4592..eb4399ec0 100644 --- a/plat/arm/board/juno/jmptbl.i +++ b/plat/arm/board/juno/jmptbl.i @@ -23,6 +23,7 @@ fdt fdt_node_offset_by_compatible 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