This new function returns nodes in address order. There is also a corresponding for_each_child_of_node_by_id() macro. Signed-off-by: Stephen Gordon <gordoste@xxxxxxxxxxxx> --- drivers/of/base.c | 41 ++++++++++++++++++++++++++++++++++++++++- include/linux/of.h | 12 ++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index 7dc394255a0a..0be430b022fb 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -623,7 +623,46 @@ static struct device_node *__of_get_next_child(const struct device_node *node, child = __of_get_next_child(parent, child)) /** - * of_get_next_child - Iterate a node childs + * of_get_next_child_by_id - Iterate a node's children in order of id + * @node: parent node + * @prev: previous child of the parent node, or NULL to get first + * + * Return: A node pointer with refcount incremented, use of_node_put() on + * it when done. Returns NULL when prev is the last child. Decrements the + * refcount of prev. + */ +struct device_node *of_get_next_child_by_id(const struct device_node *node, + struct device_node *prev) +{ + struct device_node *next = NULL; + u32 next_id = U32_MAX; + u32 prev_id, this_id; + unsigned long flags; + + if (!node || !(node->child)) + return NULL; + + if (prev) + of_property_read_u32(prev, "reg", &prev_id); + + for_each_child_of_node_scoped(node, child) { + of_property_read_u32(child, "reg", &this_id); + if ((!prev || (this_id > prev_id)) && this_id < next_id) { + next = child; + next_id = this_id; + } + } + + raw_spin_lock_irqsave(&devtree_lock, flags); + of_node_get(next); + of_node_put(prev); + raw_spin_unlock_irqrestore(&devtree_lock, flags); + return next; +} +EXPORT_SYMBOL(of_get_next_child_by_id); + +/** + * of_get_next_child - Iterate a node's children * @node: parent node * @prev: previous child of the parent node, or NULL to get first * diff --git a/include/linux/of.h b/include/linux/of.h index f921786cb8ac..7eaaade5f749 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -289,6 +289,8 @@ 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_by_id(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); @@ -545,6 +547,12 @@ static inline struct device_node *of_get_next_child( return NULL; } +static inline struct device_node *of_get_next_child_by_id( + const struct device_node *node, struct device_node *prev) +{ + return NULL; +} + static inline struct device_node *of_get_next_available_child( const struct device_node *node, struct device_node *prev) { @@ -1471,6 +1479,10 @@ 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_by_id(parent, child) \ + for (child = of_get_next_child_by_id(parent, NULL); child != NULL; \ + child = of_get_next_child_by_id(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); \ -- 2.39.5