File tree Expand file tree Collapse file tree 5 files changed +101
-0
lines changed
Expand file tree Collapse file tree 5 files changed +101
-0
lines changed Original file line number Diff line number Diff line change @@ -104,6 +104,9 @@ does not apply to macros which take cell names as arguments.
104104For-each macros
105105===============
106106
107+ The :c:macro: `DT_FOREACH_CHILD ` macro allows iterating over the ancestor node
108+ of a devicetree node.
109+
107110There is currently only one "generic" for-each macro,
108111:c:macro: `DT_FOREACH_CHILD `, which allows iterating over the children of a
109112devicetree node.
Original file line number Diff line number Diff line change 29752975 */
29762976#define DT_FOREACH_STATUS_OKAY_NODE_VARGS (fn , ...) DT_FOREACH_OKAY_VARGS_HELPER(fn, __VA_ARGS__)
29772977
2978+ /**
2979+ * @brief Invokes @p fn for each ancestor of @p node_id
2980+ *
2981+ * The macro @p fn must take one parameter, which will be the identifier
2982+ * of a child node of @p node_id to enable traversal of all ancestor nodes.
2983+ *
2984+ * The ancestor will be iterated over in the same order as they
2985+ * appear in the final devicetree.
2986+ *
2987+ * Example devicetree fragment:
2988+ *
2989+ * @code{.dts}
2990+ * n: node1 {
2991+ * foobar = "foo1";
2992+ *
2993+ * n_2: node2 {
2994+ * foobar = "foo2";
2995+ *
2996+ * n_3: node3 {
2997+ * foobar = "foo3";
2998+ * };
2999+ * };
3000+ * };
3001+ * @endcode
3002+ *
3003+ * Example usage:
3004+ *
3005+ * @code{.c}
3006+ * #define GET_PROP(n) DT_PROP(n, foobar),
3007+ *
3008+ * const char *ancestor_names[] = {
3009+ * DT_FOREACH_ANCESTOR(DT_NODELABEL(n_3), GET_PROP)
3010+ * };
3011+ * @endcode
3012+ *
3013+ * This expands to:
3014+ *
3015+ * @code{.c}
3016+ * const char *ancestor_names[] = {
3017+ * "foo2", "foo1",
3018+ * };
3019+ * @endcode
3020+ *
3021+ * @param node_id node identifier
3022+ * @param fn macro to invoke
3023+ */
3024+ #define DT_FOREACH_ANCESTOR (node_id , fn ) \
3025+ DT_CAT(node_id, _FOREACH_ANCESTOR)(fn)
3026+
29783027/**
29793028 * @brief Invokes @p fn for each child of @p node_id
29803029 *
Original file line number Diff line number Diff line change @@ -97,6 +97,7 @@ def main():
9797 out_dt_define (f"{ node .z_path_id } _FOREACH_NODELABEL_VARGS(fn, ...)" ,
9898 " " .join (f"fn({ nodelabel } , __VA_ARGS__)" for nodelabel in node .labels ))
9999
100+ write_parent (node )
100101 write_children (node )
101102 write_dep_info (node )
102103 write_idents_and_existence (node )
@@ -457,6 +458,17 @@ def write_compatibles(node: edtlib.Node) -> None:
457458 out_dt_define (f"{ node .z_path_id } _COMPAT_MODEL_IDX_{ i } " ,
458459 quote_str (node .edt .compat2model [compat ]))
459460
461+ def write_parent (node : edtlib .Node ) -> None :
462+ # Visit all parent nodes.
463+ def _visit_parent_node (node : edtlib .Node ):
464+ while node is not None :
465+ yield node .parent
466+ node = node .parent
467+
468+ # Writes helper macros for dealing with node's parent.
469+ out_dt_define (f"{ node .z_path_id } _FOREACH_ANCESTOR(fn)" ,
470+ " " .join (f"fn(DT_{ parent .z_path_id } )" for parent in
471+ _visit_parent_node (node ) if parent is not None ))
460472
461473def write_children (node : edtlib .Node ) -> None :
462474 # Writes helper macros for dealing with node's children.
Original file line number Diff line number Diff line change 635635 phys = <&test_transceiver1>;
636636 };
637637
638+ test_parent: test-parent {
639+ compatible = "vnd,parent-bindings";
640+
641+ test_parent_a: parent-a {
642+ val = <0>;
643+
644+ test_parent_b: parent-b {
645+ val = <0>;
646+ };
647+ };
648+ };
649+
638650 /* there should only be one of these */
639651 test_children: test-children {
640652 compatible = "vnd,child-bindings";
Original file line number Diff line number Diff line change @@ -2344,6 +2344,31 @@ ZTEST(devicetree_api, test_parent)
23442344 TEST_SPI_BUS_0 ), "" );
23452345}
23462346
2347+ #undef DT_DRV_COMPAT
2348+ #define DT_DRV_COMPAT vnd_parent_bindings
2349+ ZTEST (devicetree_api , test_parent_nodes_list )
2350+ {
2351+ /* When traversing upwards, there are no fixed attributes and labels */
2352+ #define TEST_FUNC (parent ) { /* No operation */ }
2353+ #define TEST_FUNC_AND_COMMA (parent ) TEST_FUNC(parent),
2354+
2355+ struct vnd_parent_binding {
2356+ int val ;
2357+ };
2358+
2359+ struct vnd_parent_binding vals_a [] = {
2360+ DT_FOREACH_ANCESTOR (DT_NODELABEL (test_parent_a ), TEST_FUNC_AND_COMMA )};
2361+
2362+ struct vnd_parent_binding vals_b [] = {
2363+ DT_FOREACH_ANCESTOR (DT_NODELABEL (test_parent_b ), TEST_FUNC_AND_COMMA )};
2364+
2365+ zassert_equal (ARRAY_SIZE (vals_a ), 3 , "" );
2366+ zassert_equal (ARRAY_SIZE (vals_b ), 4 , "" );
2367+
2368+ #undef TEST_FUNC_AND_COMMA
2369+ #undef TEST_FUNC
2370+ }
2371+
23472372#undef DT_DRV_COMPAT
23482373#define DT_DRV_COMPAT vnd_i2c_mux_controller
23492374ZTEST (devicetree_api , test_gparent )
You can’t perform that action at this time.
0 commit comments