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);