devicetree: Add DT_FOREACH_CHILD_STATUS_OKAY macro
The macro only iterates the enabled child nodes and invokes
provided macro for each node.
Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
diff --git a/doc/guides/dts/macros.bnf b/doc/guides/dts/macros.bnf
index 6211198..838cba0 100644
--- a/doc/guides/dts/macros.bnf
+++ b/doc/guides/dts/macros.bnf
@@ -51,6 +51,9 @@
; These are used internally by DT_FOREACH_CHILD, which iterates over
; each child node.
node-macro =/ %s"DT_N" path-id %s"_FOREACH_CHILD"
+; These are used internally by DT_FOREACH_CHILD_STATUS_OKAY, which iterates
+; over each child node with status "okay".
+node-macro =/ %s"DT_N" path-id %s"_FOREACH_CHILD_STATUS_OKAY"
; The node's status macro; dt-name in this case is something like "okay"
; or "disabled".
node-macro =/ %s"DT_N" path-id %s"_STATUS_" dt-name
diff --git a/include/devicetree.h b/include/devicetree.h
index c65546b..ba94826 100644
--- a/include/devicetree.h
+++ b/include/devicetree.h
@@ -1486,6 +1486,21 @@
DT_CAT(node_id, _FOREACH_CHILD)(fn)
/**
+ * @brief Call "fn" on the child nodes with status "okay"
+ *
+ * The macro "fn" should take one argument, which is the node
+ * identifier for the child node.
+ *
+ * As usual, both a missing status and an "ok" status are
+ * treated as "okay".
+ *
+ * @param node_id node identifier
+ * @param fn macro to invoke
+ */
+#define DT_FOREACH_CHILD_STATUS_OKAY(node_id, fn) \
+ DT_CAT(node_id, _FOREACH_CHILD_STATUS_OKAY)(fn)
+
+/**
* @brief Invokes "fn" for each element in the value of property "prop".
*
* The macro "fn" must take three parameters: fn(node_id, prop, idx).
diff --git a/scripts/dts/gen_defines.py b/scripts/dts/gen_defines.py
index 6ddde90..5ce8417 100755
--- a/scripts/dts/gen_defines.py
+++ b/scripts/dts/gen_defines.py
@@ -119,6 +119,7 @@
f"DT_{node.parent.z_path_id}")
write_child_functions(node)
+ write_child_functions_status_okay(node)
write_dep_info(node)
write_idents_and_existence(node)
write_bus(node)
@@ -479,6 +480,18 @@
node.children.values()))
+def write_child_functions_status_okay(node):
+ # Writes macro that are helpers that will call a macro/function
+ # for each child node with status "okay".
+
+ functions = ''
+ for child in node.children.values():
+ if child.status == "okay":
+ functions = functions + f"fn(DT_{child.z_path_id}) "
+
+ out_dt_define(f"{node.z_path_id}_FOREACH_CHILD_STATUS_OKAY(fn)", functions)
+
+
def write_status(node):
out_dt_define(f"{node.z_path_id}_STATUS_{str2ident(node.status)}", 1)
diff --git a/tests/lib/devicetree/api/app.overlay b/tests/lib/devicetree/api/app.overlay
index f5ad07d..61560df 100644
--- a/tests/lib/devicetree/api/app.overlay
+++ b/tests/lib/devicetree/api/app.overlay
@@ -386,12 +386,15 @@
test_child_a: child-a {
val = <0>;
+ status = "okay";
};
test_child_b: child-b {
val = <1>;
+ status = "okay";
};
test_child_c: child-c {
val = <2>;
+ status = "disabled";
};
};
diff --git a/tests/lib/devicetree/api/src/main.c b/tests/lib/devicetree/api/src/main.c
index 22ed662..db61051 100644
--- a/tests/lib/devicetree/api/src/main.c
+++ b/tests/lib/devicetree/api/src/main.c
@@ -1568,8 +1568,13 @@
DT_INST_FOREACH_CHILD(0, TEST_FUNC)
};
+ struct vnd_child_binding vals_status_okay[] = {
+ DT_FOREACH_CHILD_STATUS_OKAY(TEST_PARENT, TEST_FUNC)
+ };
+
zassert_equal(ARRAY_SIZE(vals), 3, "");
zassert_equal(ARRAY_SIZE(vals_inst), 3, "");
+ zassert_equal(ARRAY_SIZE(vals_status_okay), 2, "");
zassert_false(strlen(STRINGIFY(TEST_PARENT)) == 0, "");
@@ -1579,6 +1584,8 @@
zassert_equal(vals_inst[0].val, 0, "");
zassert_equal(vals_inst[1].val, 1, "");
zassert_equal(vals_inst[2].val, 2, "");
+ zassert_equal(vals_status_okay[0].val, 0, "");
+ zassert_equal(vals_status_okay[1].val, 1, "");
#undef TEST_PARENT
#undef TEST_FUNC