aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAndrew Turner <andrew@FreeBSD.org>2015-05-11 14:10:54 +0000
committerAndrew Turner <andrew@FreeBSD.org>2015-05-11 14:10:54 +0000
commit72a638c7f4a217e4f60da8d64175021ba8bc6eb6 (patch)
tree27c8dacde256d160ced17a3962a7d7ad69b9b769 /sys
parent6bd9126da9b195d9b340d989863565d097f79400 (diff)
downloadsrc-72a638c7f4a217e4f60da8d64175021ba8bc6eb6.tar.gz
src-72a638c7f4a217e4f60da8d64175021ba8bc6eb6.zip
Add ofw_bus_find_compatible to find a compatible ofw node. This will be
used on ARM to help find the correct node to use to start secondary CPUs as this happens before device enumeration.
Notes
Notes: svn path=/head/; revision=282770
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ofw/ofw_bus_subr.c69
1 files changed, 54 insertions, 15 deletions
diff --git a/sys/dev/ofw/ofw_bus_subr.c b/sys/dev/ofw/ofw_bus_subr.c
index 6756398dc317..e69d9c144f7f 100644
--- a/sys/dev/ofw/ofw_bus_subr.c
+++ b/sys/dev/ofw/ofw_bus_subr.c
@@ -176,12 +176,37 @@ ofw_bus_status_okay(device_t dev)
return (0);
}
+static int
+ofw_bus_node_is_compatible(const char *compat, int len, const char *onecompat)
+{
+ int onelen, l, ret;
+
+ onelen = strlen(onecompat);
+
+ ret = 0;
+ while (len > 0) {
+ if (strlen(compat) == onelen &&
+ strncasecmp(compat, onecompat, onelen) == 0) {
+ /* Found it. */
+ ret = 1;
+ break;
+ }
+
+ /* Slide to the next sub-string. */
+ l = strlen(compat) + 1;
+ compat += l;
+ len -= l;
+ }
+
+ return (ret);
+}
+
int
ofw_bus_is_compatible(device_t dev, const char *onecompat)
{
phandle_t node;
const char *compat;
- int len, onelen, l;
+ int len;
if ((compat = ofw_bus_get_compat(dev)) == NULL)
return (0);
@@ -193,20 +218,7 @@ ofw_bus_is_compatible(device_t dev, const char *onecompat)
if ((len = OF_getproplen(node, "compatible")) <= 0)
return (0);
- onelen = strlen(onecompat);
-
- while (len > 0) {
- if (strlen(compat) == onelen &&
- strncasecmp(compat, onecompat, onelen) == 0)
- /* Found it. */
- return (1);
-
- /* Slide to the next sub-string. */
- l = strlen(compat) + 1;
- compat += l;
- len -= l;
- }
- return (0);
+ return (ofw_bus_node_is_compatible(compat, len, onecompat));
}
int
@@ -487,3 +499,30 @@ ofw_bus_intr_to_rl(device_t dev, phandle_t node, struct resource_list *rl)
return (err);
}
+phandle_t
+ofw_bus_find_compatible(phandle_t node, const char *onecompat)
+{
+ phandle_t child, ret;
+ void *compat;
+ int len;
+
+ /*
+ * Traverse all children of 'start' node, and find first with
+ * matching 'compatible' property.
+ */
+ for (child = OF_child(node); child != 0; child = OF_peer(child)) {
+ len = OF_getprop_alloc(node, "compatible", 1, &compat);
+ if (len >= 0) {
+ ret = ofw_bus_node_is_compatible(compat, len,
+ onecompat);
+ free(compat, M_OFWPROP);
+ if (ret != 0)
+ return (child);
+ }
+
+ ret = ofw_bus_find_compatible(child, onecompat);
+ if (ret != 0)
+ return (ret);
+ }
+ return (0);
+}