summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorJulius Werner <jwerner@chromium.org>2019-05-03 18:13:53 -0700
committerPatrick Georgi <pgeorgi@google.com>2019-06-04 11:22:57 +0000
commit6702b68a7966d584e310bf7a99f4a1dc57f2f56f (patch)
treeb04b8d7a658d79e4c0c07575eac9c26c36c51962 /src/lib
parent73eaec81689662cf5c1cd6ac5de1152e19b0c14d (diff)
device_tree: Add phandle caching and lookups
This patch caches phandles when unflattening the device tree, so we don't have to look up the phandle property again every time we're trying to find the phandle of a node. This is especially important when supporting phandle lookups, which are also added. In addition we keep track of the highest phandle in the whole tree, which will be important for applying overlays later. With this, dt_get_phandle(node) becomes obsolete because the phandle is already available as a member variable in the node. This patch was adapted from depthcharge's http://crosreview.com/1536385 Change-Id: I9cbd67d1d13e57c25d068b3db18bb75c709d7ebe Signed-off-by: Julius Werner <jwerner@chromium.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/32863 Reviewed-by: Hung-Te Lin <hungte@chromium.org> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/device_tree.c59
1 files changed, 35 insertions, 24 deletions
diff --git a/src/lib/device_tree.c b/src/lib/device_tree.c
index 7a3128efcf..44eca4e2a8 100644
--- a/src/lib/device_tree.c
+++ b/src/lib/device_tree.c
@@ -66,6 +66,12 @@ int fdt_node_name(const void *blob, uint32_t offset, const char **name)
return ALIGN_UP(strlen((char *)ptr) + 1, sizeof(uint32_t)) + 4;
}
+static int dt_prop_is_phandle(struct device_tree_property *prop)
+{
+ return !(strcmp("phandle", prop->prop.name) &&
+ strcmp("linux,phandle", prop->prop.name));
+}
+
/*
@@ -156,6 +162,7 @@ int fdt_skip_node(const void *blob, uint32_t start_offset)
*/
static int fdt_unflatten_node(const void *blob, uint32_t start_offset,
+ struct device_tree *tree,
struct device_tree_node **new_node)
{
struct list_node *last;
@@ -178,6 +185,12 @@ static int fdt_unflatten_node(const void *blob, uint32_t start_offset,
struct device_tree_property *prop = xzalloc(sizeof(*prop));
prop->prop = fprop;
+ if (dt_prop_is_phandle(prop)) {
+ node->phandle = be32dec(prop->prop.data);
+ if (node->phandle > tree->max_phandle)
+ tree->max_phandle = node->phandle;
+ }
+
list_insert_after(&prop->list_node, last);
last = &prop->list_node;
@@ -186,7 +199,7 @@ static int fdt_unflatten_node(const void *blob, uint32_t start_offset,
struct device_tree_node *child;
last = &node->children;
- while ((size = fdt_unflatten_node(blob, offset, &child))) {
+ while ((size = fdt_unflatten_node(blob, offset, tree, &child))) {
list_insert_after(&child->list_node, last);
last = &child->list_node;
@@ -260,7 +273,7 @@ struct device_tree *fdt_unflatten(const void *blob)
offset += size;
}
- fdt_unflatten_node(blob, struct_offset, &tree->root);
+ fdt_unflatten_node(blob, struct_offset, tree, &tree->root);
return tree;
}
@@ -590,6 +603,26 @@ struct device_tree_node *dt_find_node_by_path(struct device_tree_node *parent,
return node;
}
+struct device_tree_node *dt_find_node_by_phandle(struct device_tree_node *root,
+ uint32_t phandle)
+{
+ if (!root)
+ return NULL;
+
+ if (root->phandle == phandle)
+ return root;
+
+ struct device_tree_node *node;
+ struct device_tree_node *result;
+ list_for_each(node, root->children, list_node) {
+ result = dt_find_node_by_phandle(node, phandle);
+ if (result)
+ return result;
+ }
+
+ return NULL;
+}
+
/*
* Check if given node is compatible.
*
@@ -719,28 +752,6 @@ struct device_tree_node *dt_find_prop_value(struct device_tree_node *parent,
return NULL;
}
-/**
- * Find the phandle of a node.
- *
- * @param node Pointer to node containing the phandle
- * @return Zero on error, the phandle on success
- */
-uint32_t dt_get_phandle(const struct device_tree_node *node)
-{
- const uint32_t *phandle;
- size_t len;
-
- dt_find_bin_prop(node, "phandle", (const void **)&phandle, &len);
- if (phandle != NULL && len == sizeof(*phandle))
- return be32_to_cpu(*phandle);
-
- dt_find_bin_prop(node, "linux,phandle", (const void **)&phandle, &len);
- if (phandle != NULL && len == sizeof(*phandle))
- return be32_to_cpu(*phandle);
-
- return 0;
-}
-
/*
* Write an arbitrary sized big-endian integer into a pointer.
*