Hi,
so that we can easily check if a node is compatible or to find nodes
that are compatible, I would like to add helpers to the fdt routines.
This way the drivers can check if they "match" to a node by simply
calling:
if (fdt_node_compatible(ma->ma_node, "samsung,exynos4210-ehci"))
return (1);
Sometimes it's helpful to find any node that is compatible. It can
be helpful for instance on finding the early uart. Simplified example:
if ((node = fdt_find_compatible("arm,pl011")) != NULL)
pl011cnattach(...);
Thoughts? ok?
Patrick
diff --git sys/dev/ofw/fdt.c sys/dev/ofw/fdt.c
index 4cf7248..3fdbd63 100644
--- sys/dev/ofw/fdt.c
+++ sys/dev/ofw/fdt.c
@@ -34,6 +34,7 @@ void *skip_node(void *);
void *fdt_parent_node_recurse(void *, void *);
int fdt_node_property_int(void *, char *, int *);
int fdt_node_property_ints(void *, char *, int *, int);
+void *fdt_find_compatible_node(void *, char *);
int fdt_translate_memory_address(void *, struct fdt_memory *);
#ifdef DEBUG
void fdt_print_node_recurse(void *, int);
@@ -393,6 +394,62 @@ fdt_parent_node(void *node)
}
/*
+ * Find the first node which is compatible.
+ */
+void *
+fdt_find_compatible_node(void *node, char *compatible)
+{
+ void *child;
+
+ while (node != NULL) {
+ if (fdt_node_compatible(node, compatible))
+ return node;
+
+ child = fdt_child_node(node);
+ if (child != NULL) {
+ child = fdt_find_compatible_node(
+ fdt_child_node(node), compatible);
+ if (child != NULL)
+ return child;
+ }
+
+ node = fdt_next_node(node);
+ }
+
+ return NULL;
+}
+
+void *
+fdt_find_compatible(char *compatible)
+{
+ return fdt_find_compatible_node(fdt_next_node(0), compatible);
+}
+
+/*
+ * Check that node is compatible.
+ */
+int
+fdt_node_compatible(void *node, char *compatible)
+{
+ char *data;
+ int len, clen = strlen(compatible);
+
+ if (node == NULL)
+ return 0;
+
+ len = fdt_node_property(node, "compatible", &data);
+ while (len > 0 && len >= clen + 1) {
+ if (strlen(data) == clen)
+ if (!strncmp(data, compatible, clen))
+ return 1;
+ len -= (strlen(data) + 1);
+ data += (strlen(data) + 1);
+ }
+
+ return 0;
+}
+
+/*
* Translate memory address depending on parent's range.
*
* Ranges are a way of mapping one address to another. This ranges attribute
diff --git sys/dev/ofw/fdt.h sys/dev/ofw/fdt.h
index ff5ef0d..0cdb459 100644
--- sys/dev/ofw/fdt.h
+++ sys/dev/ofw/fdt.h
@@ -60,6 +60,8 @@ char *fdt_node_name(void *);
void *fdt_find_node(char *);
int fdt_node_property(void *, char *, char **);
void *fdt_parent_node(void *);
+void *fdt_find_compatible(char *);
+int fdt_node_compatible(void *, char *);
int fdt_get_memory_address(void *, int, struct fdt_memory *);
#ifdef DEBUG
void *fdt_print_property(void *, int);