summaryrefslogtreecommitdiffstats
path: root/drivers/of
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2018-01-26 13:44:34 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2018-02-06 09:39:05 +0100
commitbc95e7a96330aa11ff1a094d035a434fd8db6b23 (patch)
tree5b7bef21d92f6c85bf71af44668ee86514e1b02e /drivers/of
parent6c2e0f6c748eeaa231e1f23439c3a68bd401ea37 (diff)
downloadbarebox-bc95e7a96330aa11ff1a094d035a434fd8db6b23.tar.gz
barebox-bc95e7a96330aa11ff1a094d035a434fd8db6b23.tar.xz
of: Add function to find the same node in another tree
For our device tree fixups we have to find a node corresponding to another node in another device tree. We used to use the full name to match the nodes, but this falls apart when nodes get renamed or for example a new bus hierarchy is introduced. To make this more robust we create reproducible names from device nodes which mostly depend on the address in MMIO space, the reg property and as a last resort the name of the device node. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/of')
-rw-r--r--drivers/of/base.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 10b62890b5..23e5e22ffe 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2174,6 +2174,69 @@ int of_device_disable_path(const char *path)
}
/**
+ * of_get_reproducible_name() - get a reproducible name of a node
+ * @node: The node to get a name from
+ *
+ * This function constructs a reproducible name for a node. This name can be
+ * used to find the same node in another device tree. The name is constructed
+ * from different patterns which are appended to each other.
+ * - If a node has no "reg" property, the name of the node is used in angle
+ * brackets, prepended with the result of the parent node
+ * - If the parent node has a "ranges" property then the address in MMIO space
+ * is used in square brackets
+ * - If a node has a "reg" property, but is not translatable in MMIO space then
+ * the start address is used in curly brackets, prepended with the result of
+ * the parent node.
+ *
+ * Returns a dynamically allocated string containing the name
+ */
+char *of_get_reproducible_name(struct device_node *node)
+{
+ const __be32 *reg;
+ u64 addr;
+ u64 offset;
+ int na;
+ char *str, *res;
+
+ if (!node)
+ return 0;
+
+ reg = of_get_property(node, "reg", NULL);
+ if (!reg) {
+ str = of_get_reproducible_name(node->parent);
+ res = basprintf("%s<%s>", str, node->name);
+ free(str);
+ return res;
+ }
+
+ if (node->parent && of_get_property(node->parent, "ranges", NULL)) {
+ addr = of_translate_address(node, reg);
+ return basprintf("[0x%llx]", addr);
+ }
+
+ na = of_n_addr_cells(node);
+
+ offset = of_read_number(reg, na);
+
+ str = of_get_reproducible_name(node->parent);
+ res = basprintf("%s{%llx}", str, offset);
+ free(str);
+
+ return res;
+}
+
+struct device_node *of_find_node_by_reproducible_name(struct device_node *from,
+ const char *name)
+{
+ struct device_node *np;
+
+ of_tree_for_each_node_from(np, from)
+ if (!of_node_cmp(of_get_reproducible_name(np), name))
+ return np;
+ return NULL;
+}
+
+/**
* of_graph_parse_endpoint() - parse common endpoint node properties
* @node: pointer to endpoint device_node
* @endpoint: pointer to the OF endpoint data structure