aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.clang-format2
-rw-r--r--src/vppinfra/devicetree.c17
-rw-r--r--src/vppinfra/devicetree.h50
3 files changed, 63 insertions, 6 deletions
diff --git a/.clang-format b/.clang-format
index 798a8c39a35..e4855fce047 100644
--- a/.clang-format
+++ b/.clang-format
@@ -35,6 +35,8 @@ ForEachMacros:
- 'foreach_vnet_dev_port'
- 'foreach_vnet_dev_args'
- 'foreach_vnet_dev_port_args'
+ - 'foreach_clib_dt_tree_node'
+ - 'foreach_clib_dt_child_node'
StatementMacros:
- 'CLIB_MULTIARCH_FN'
diff --git a/src/vppinfra/devicetree.c b/src/vppinfra/devicetree.c
index b725d5a0aed..df5a24f198e 100644
--- a/src/vppinfra/devicetree.c
+++ b/src/vppinfra/devicetree.c
@@ -192,9 +192,16 @@ done:
}
#endif
-clib_dt_node_t *
-clib_dt_get_child_node (clib_dt_node_t *n, char *name)
+__clib_export clib_dt_node_t *
+clib_dt_get_child_node (clib_dt_node_t *n, char *fmt, ...)
{
+ u8 *s;
+ va_list va;
+ va_start (va, fmt);
+ s = va_format (0, fmt, &va);
+ va_end (va);
+ vec_add1 (s, 0);
+
vec_foreach_pointer (cn, n->child_nodes)
{
u8 *p = cn->path + vec_len (cn->path) - 1;
@@ -206,15 +213,17 @@ clib_dt_get_child_node (clib_dt_node_t *n, char *name)
if (p[-1] != '/')
continue;
- while (p[i] == name[i] && name[i] != 0)
+ while (p[i] == s[i] && s[i] != 0)
i++;
- if (name[i] != 0)
+ if (s[i] != 0)
continue;
+ vec_free (s);
return cn;
}
+ vec_free (s);
return 0;
}
diff --git a/src/vppinfra/devicetree.h b/src/vppinfra/devicetree.h
index 21c2e0f7006..db7d8411a11 100644
--- a/src/vppinfra/devicetree.h
+++ b/src/vppinfra/devicetree.h
@@ -42,6 +42,8 @@ typedef struct clib_dt_main
uword *node_by_phandle;
} clib_dt_main_t;
+__clib_export clib_dt_node_t *clib_dt_get_child_node (clib_dt_node_t *n,
+ char *fmt, ...);
clib_dt_node_t *clib_dt_get_node_with_path (clib_dt_main_t *dm, char *fmt,
...);
clib_dt_property_t *clib_dt_get_node_property_by_name (clib_dt_node_t *,
@@ -56,7 +58,7 @@ format_function_t format_clib_dt_desc;
format_function_t format_clib_dt_property_data;
static_always_inline int
-clib_dt_proprerty_is_u32 (clib_dt_property_t *p)
+clib_dt_property_is_u32 (clib_dt_property_t *p)
{
if (p == 0 || p->size != 4)
return 0;
@@ -64,9 +66,53 @@ clib_dt_proprerty_is_u32 (clib_dt_property_t *p)
}
static_always_inline u32
-clib_dt_proprerty_get_u32 (clib_dt_property_t *p)
+clib_dt_property_get_u32 (clib_dt_property_t *p)
{
return clib_net_to_host_u32 (*(u32u *) p->data);
}
+static_always_inline char *
+clib_dt_property_get_string (clib_dt_property_t *p)
+{
+ return (char *) p->data;
+}
+
+static_always_inline clib_dt_node_t *
+clib_dt_get_root_node (clib_dt_node_t *n)
+{
+ return n->dt_main->root;
+}
+
+static_always_inline clib_dt_node_t *
+foreach_clib_dt_tree_node_helper (clib_dt_node_t *first, clib_dt_node_t **prev,
+ clib_dt_node_t *n)
+{
+ clib_dt_node_t *next;
+
+again:
+ if ((!*prev || (*prev)->parent != n) && vec_len (n->child_nodes) > 0)
+ next = n->child_nodes[0];
+ else if (n->next)
+ next = n->next;
+ else
+ {
+ next = n->parent;
+ *prev = n;
+ n = next;
+ if (n == first)
+ return 0;
+ goto again;
+ }
+
+ *prev = n;
+ return next == first ? 0 : next;
+}
+
+#define foreach_clib_dt_child_node(_cn, _n) \
+ vec_foreach_pointer (_cn, (_n)->child_nodes)
+
+#define foreach_clib_dt_tree_node(_n, _first) \
+ for (clib_dt_node_t *__last = 0, *(_n) = _first; _n; \
+ _n = foreach_clib_dt_tree_node_helper (_first, &__last, _n))
+
#endif /* CLIB_DEVICETREE_H_ */