Maximilian Brune has uploaded this change for review.

View Change

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);

To view, visit change 83457. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: newchange
Gerrit-Project: coreboot
Gerrit-Branch: main
Gerrit-Change-Id: I7846eb8af390d709b0757262025cb819e9988699
Gerrit-Change-Number: 83457
Gerrit-PatchSet: 1
Gerrit-Owner: Maximilian Brune <maximilian.brune@9elements.com>