The ofnode_find_subnode() function currently processes things two
different ways, so the treatment of unit addresses differs depending on
whether OF_LIVE is enabled or not.

Add a new version which uses the ofnode API and add a test to check that
unit addresses can be matched correctly. Leave the old function in place
for the !OF_LIVE case, to avoid a code-size increase, e.g. on
firefly-rk3288

Signed-off-by: Simon Glass <[email protected]>
---

Changes in v2:
- Split prerequisite patches into their own series

 drivers/core/ofnode.c | 29 ++++++++++++++++++++++-------
 include/dm/ofnode.h   | 12 ++++++++++++
 test/dm/ofnode.c      | 19 +++++++++++++++++++
 3 files changed, 53 insertions(+), 7 deletions(-)

diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index 529bc132f7d..c9b03b0f925 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -599,14 +599,9 @@ ofnode ofnode_find_subnode(ofnode node, const char 
*subnode_name)
        log_debug("%s: %s: ", __func__, subnode_name);
 
        if (ofnode_is_np(node)) {
-               struct device_node *np = ofnode_to_np(node);
-
-               for (np = np->child; np; np = np->sibling) {
-                       if (!strcmp(subnode_name, np->name))
-                               break;
-               }
-               subnode = np_to_ofnode(np);
+               subnode = ofnode_find_subnode_unit(node, subnode_name);
        } else {
+               /* special case to avoid code-size increase */
                int ooffset = fdt_subnode_offset(ofnode_to_fdt(node),
                                ofnode_to_offset(node), subnode_name);
                subnode = noffset_to_ofnode(node, ooffset);
@@ -617,6 +612,26 @@ ofnode ofnode_find_subnode(ofnode node, const char 
*subnode_name)
        return subnode;
 }
 
+ofnode ofnode_find_subnode_unit(ofnode node, const char *subnode_name)
+{
+       ofnode subnode, found = ofnode_null();
+
+       assert(ofnode_valid(node));
+       log_debug("%s: ", subnode_name);
+
+       ofnode_for_each_subnode(subnode, node) {
+               if (ofnode_name_eq_unit(subnode, subnode_name)) {
+                       found = subnode;
+                       break;
+               }
+       }
+
+       log_debug("%s\n", ofnode_valid(found) ?
+                 ofnode_get_name(found) : "<none>");
+
+       return found;
+}
+
 int ofnode_read_u32_array(ofnode node, const char *propname,
                          u32 *out_values, size_t sz)
 {
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 3bb7d3e05e1..74ee6fb4ee2 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -607,6 +607,18 @@ bool ofnode_read_bool(ofnode node, const char *propname);
  */
 ofnode ofnode_find_subnode(ofnode node, const char *subnode_name);
 
+/**
+ * ofnode_find_subnode_unit() - find a named subnode of a parent node
+ *
+ * @node:      valid reference to parent node
+ * @subnode_name: name of subnode to find, including any unit address. If the
+ *     unit address is omitted, any subnode which matches the name (excluding
+ *     any unit address) is returned
+ * Return: reference to subnode (which can be invalid if there is no such
+ * subnode)
+ */
+ofnode ofnode_find_subnode_unit(ofnode node, const char *subnode_name);
+
 #if CONFIG_IS_ENABLED(DM_INLINE_OFNODE)
 #include <asm/global_data.h>
 
diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c
index ce996567c3c..521359c9bd7 100644
--- a/test/dm/ofnode.c
+++ b/test/dm/ofnode.c
@@ -1201,6 +1201,25 @@ static int dm_test_ofnode_find_subnode(struct 
unit_test_state *uts)
 }
 DM_TEST(dm_test_ofnode_find_subnode, UTF_SCAN_FDT);
 
+/* check ofnode_find_subnode() with unit addresses */
+static int dm_test_ofnode_find_subnode_unit(struct unit_test_state *uts)
+{
+       ofnode node, subnode;
+
+       node = ofnode_path("/some-bus");
+       ut_assert(ofnode_valid(node));
+       subnode = ofnode_find_subnode_unit(node, "c-test@5");
+       ut_assert(ofnode_valid(subnode));
+       ut_asserteq_str("c-test@5", ofnode_get_name(subnode));
+
+       subnode = ofnode_find_subnode_unit(node, "c-test");
+       ut_assert(ofnode_valid(subnode));
+       ut_asserteq_str("c-test@5", ofnode_get_name(subnode));
+
+       return 0;
+}
+DM_TEST(dm_test_ofnode_find_subnode_unit, UTF_SCAN_FDT);
+
 /* test ofnode_find_subnode() on the 'other' tree */
 static int dm_test_ofnode_find_subnode_ot(struct unit_test_state *uts)
 {
-- 
2.34.1

Reply via email to