Commit 1fcc67e3 authored by Chen-Yu Tsai's avatar Chen-Yu Tsai Committed by Wolfram Sang
Browse files

of: base: Add for_each_child_of_node_with_prefix()



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: default avatarChen-Yu Tsai <wenst@chromium.org>
Reviewed-by: default avatarRob Herring (Arm) <robh@kernel.org>
Reviewed-by: default avatarAngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: default avatarWolfram Sang <wsa+renesas@sang-engineering.com>
parent 81de291d
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -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 *))
+9 −0
Original line number Diff line number Diff line
@@ -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(
@@ -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))