Skip to content

Commit

Permalink
of: base: Add for_each_child_of_node_with_prefix()
Browse files Browse the repository at this point in the history
There are cases where drivers would go through child device nodes and
operate on only the ones whose node name starts with a given prefix.

Provide a helper for these users. This will mainly be used in a
subsequent patch that implements a hardware component prober for I2C
busses.

Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
  • Loading branch information
Chen-Yu Tsai authored and Wolfram Sang committed Nov 27, 2024
1 parent 81de291 commit 1fcc67e
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 0 deletions.
35 changes: 35 additions & 0 deletions drivers/of/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,41 @@ struct device_node *of_get_next_child(const struct device_node *node,
}
EXPORT_SYMBOL(of_get_next_child);

/**
* of_get_next_child_with_prefix - Find the next child node with prefix
* @node: parent node
* @prev: previous child of the parent node, or NULL to get first
*
* This function is like of_get_next_child(), except that it automatically
* skips any nodes whose name doesn't have the given prefix.
*
* Return: A node pointer with refcount incremented, use
* of_node_put() on it when done.
*/
struct device_node *of_get_next_child_with_prefix(const struct device_node *node,
struct device_node *prev,
const char *prefix)
{
struct device_node *next;
unsigned long flags;

if (!node)
return NULL;

raw_spin_lock_irqsave(&devtree_lock, flags);
next = prev ? prev->sibling : node->child;
for (; next; next = next->sibling) {
if (!of_node_name_prefix(next, prefix))
continue;
if (of_node_get(next))
break;
}
of_node_put(prev);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return next;
}
EXPORT_SYMBOL(of_get_next_child_with_prefix);

static struct device_node *of_get_next_status_child(const struct device_node *node,
struct device_node *prev,
bool (*checker)(const struct device_node *))
Expand Down
9 changes: 9 additions & 0 deletions include/linux/of.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,9 @@ extern struct device_node *of_get_parent(const struct device_node *node);
extern struct device_node *of_get_next_parent(struct device_node *node);
extern struct device_node *of_get_next_child(const struct device_node *node,
struct device_node *prev);
extern struct device_node *of_get_next_child_with_prefix(const struct device_node *node,
struct device_node *prev,
const char *prefix);
extern struct device_node *of_get_next_available_child(
const struct device_node *node, struct device_node *prev);
extern struct device_node *of_get_next_reserved_child(
Expand Down Expand Up @@ -1468,6 +1471,12 @@ static inline int of_property_read_s32(const struct device_node *np,
child != NULL; \
child = of_get_next_child(parent, child))

#define for_each_child_of_node_with_prefix(parent, child, prefix) \
for (struct device_node *child __free(device_node) = \
of_get_next_child_with_prefix(parent, NULL, prefix); \
child != NULL; \
child = of_get_next_child_with_prefix(parent, child, prefix))

#define for_each_available_child_of_node(parent, child) \
for (child = of_get_next_available_child(parent, NULL); child != NULL; \
child = of_get_next_available_child(parent, child))
Expand Down

0 comments on commit 1fcc67e

Please sign in to comment.