Maximilian Brune has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/83457?usp=email )
Change subject: commonlib/device_tree.c: Add read reg property helper ......................................................................
commonlib/device_tree.c: Add read reg property helper
Add a helper function to read the reg property.
Signed-off-by: Maximilian Brune maximilian.brune@9elements.com Change-Id: I7846eb8af390d709b0757262025cb819e9988699 --- M src/commonlib/device_tree.c M src/commonlib/include/commonlib/device_tree.h 2 files changed, 56 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/57/83457/1
diff --git a/src/commonlib/device_tree.c b/src/commonlib/device_tree.c index 0ec6ea9..37c0ecc 100644 --- a/src/commonlib/device_tree.c +++ b/src/commonlib/device_tree.c @@ -981,6 +981,60 @@ */
/* + * dt_read_reg_prop reads the reg property inside a node + * + * @params node device tree node to read reg property from + * @params addr_cells number of cells used for one address + * @params size_cells number of cells used for one size + * @params regions all regions that are read inside the reg property are saved inside + * this array + * @params regions_count maximum number of entries that can be saved inside the regions array. + * + * Returns: Either 0 on error or returns the number of regions put into the regions array. + */ +size_t dt_read_reg_prop(struct device_tree_node *node, u32 addr_cells, u32 size_cells, + struct device_tree_region regions[], size_t regions_count) +{ + struct device_tree_property *prop; + bool found = false; + list_for_each(prop, node->properties, list_node) + if (!strcmp("reg", prop->prop.name)) + found = true; + + if (!found) { + printk(BIOS_DEBUG, "no reg property found\n"); + return 0; + } + + // we found the reg property, no need to parse all regions in 'reg' + size_t count = prop->prop.size / (4 * addr_cells + 4 * size_cells); + if (count > regions_count) { + printk(BIOS_ERR, "reg property has more entries (%zd) than regions array can hold (%zd)\n", count, regions_count); + count = regions_count; + } + if (addr_cells > 2 || size_cells > 2) { + printk(BIOS_ERR, "addr_cells (%d) or size_cells (%d) bigger than 2\n", + addr_cells, size_cells); + return 0; + } + uint32_t *ptr = prop->prop.data; + for (int i = 0; i < count; i++) { + if (addr_cells == 1) + regions[i].addr = be32dec(ptr); + else if (addr_cells == 2) + regions[i].addr = be64dec(ptr); + ptr += addr_cells; + if (size_cells == 1) + regions[i].size = be32dec(ptr); + else if (size_cells == 2) + regions[i].size = be64dec(ptr); + ptr += size_cells; + } + + return count; // return the number of regions found in the reg property +} + +/* * Read #address-cells and #size-cells properties from a node. * * @param node The device tree node to read from. diff --git a/src/commonlib/include/commonlib/device_tree.h b/src/commonlib/include/commonlib/device_tree.h index 81377fa..225ef3e 100644 --- a/src/commonlib/include/commonlib/device_tree.h +++ b/src/commonlib/include/commonlib/device_tree.h @@ -147,6 +147,8 @@ /* Flatten a device tree into the buffer pointed to by dest. */ void dt_flatten(const struct device_tree *tree, void *dest); void dt_print_node(const struct device_tree_node *node); +size_t dt_read_reg_prop(struct device_tree_node *node, u32 addr_cells, u32 size_cells, + struct device_tree_region regions[], size_t regions_count); /* Read #address-cells and #size-cells properties from a node. */ void dt_read_cell_props(const struct device_tree_node *node, u32 *addrcp, u32 *sizecp);