summaryrefslogtreecommitdiff
path: root/src/lib/device_tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/device_tree.c')
-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.
*