summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhibbits <jhibbits@FreeBSD.org>2016-11-06 15:12:05 +0000
committerjhibbits <jhibbits@FreeBSD.org>2016-11-06 15:12:05 +0000
commitf7aa0ec3729292ce6b4f1786fc183e135543a239 (patch)
tree40c8211dbe9a53492adc3cce8a54891fa38517c3
parent585364f9a2c5d377d01ef3369e465845ef9cf62a (diff)
downloadFreeBSD-src-f7aa0ec3729292ce6b4f1786fc183e135543a239.zip
FreeBSD-src-f7aa0ec3729292ce6b4f1786fc183e135543a239.tar.gz
MFC r304970:
Check all compatible strings on uart devices in powerpc Summary: Some device trees put "fsl,ns16650" first in the compatible list. This causes the probe code to choke, even though the device is compatible with ns16650, and has it listed later in the tree. Reviewed by: nwhitehorn Differential Revision: https://reviews.freebsd.org/D7676
-rw-r--r--sys/dev/ofw/ofw_bus_subr.c28
-rw-r--r--sys/dev/ofw/ofw_bus_subr.h1
-rw-r--r--sys/dev/uart/uart_cpu_powerpc.c8
3 files changed, 30 insertions, 7 deletions
diff --git a/sys/dev/ofw/ofw_bus_subr.c b/sys/dev/ofw/ofw_bus_subr.c
index d6a04d8..1c80106 100644
--- a/sys/dev/ofw/ofw_bus_subr.c
+++ b/sys/dev/ofw/ofw_bus_subr.c
@@ -45,6 +45,8 @@ __FBSDID("$FreeBSD$");
#include "ofw_bus_if.h"
+#define OFW_COMPAT_LEN 255
+
int
ofw_bus_gen_setup_devinfo(struct ofw_bus_devinfo *obd, phandle_t node)
{
@@ -178,7 +180,8 @@ ofw_bus_status_okay(device_t dev)
}
static int
-ofw_bus_node_is_compatible(const char *compat, int len, const char *onecompat)
+ofw_bus_node_is_compatible_int(const char *compat, int len,
+ const char *onecompat)
{
int onelen, l, ret;
@@ -203,6 +206,25 @@ ofw_bus_node_is_compatible(const char *compat, int len, const char *onecompat)
}
int
+ofw_bus_node_is_compatible(phandle_t node, const char *compatstr)
+{
+ char compat[OFW_COMPAT_LEN];
+ int len, rv;
+
+ if ((len = OF_getproplen(node, "compatible")) <= 0)
+ return (0);
+
+ bzero(compat, OFW_COMPAT_LEN);
+
+ if (OF_getprop(node, "compatible", compat, OFW_COMPAT_LEN) < 0)
+ return (0);
+
+ rv = ofw_bus_node_is_compatible_int(compat, len, compatstr);
+
+ return (rv);
+}
+
+int
ofw_bus_is_compatible(device_t dev, const char *onecompat)
{
phandle_t node;
@@ -219,7 +241,7 @@ ofw_bus_is_compatible(device_t dev, const char *onecompat)
if ((len = OF_getproplen(node, "compatible")) <= 0)
return (0);
- return (ofw_bus_node_is_compatible(compat, len, onecompat));
+ return (ofw_bus_node_is_compatible_int(compat, len, onecompat));
}
int
@@ -689,7 +711,7 @@ ofw_bus_find_compatible(phandle_t node, const char *onecompat)
for (child = OF_child(node); child != 0; child = OF_peer(child)) {
len = OF_getprop_alloc(child, "compatible", 1, &compat);
if (len >= 0) {
- ret = ofw_bus_node_is_compatible(compat, len,
+ ret = ofw_bus_node_is_compatible_int(compat, len,
onecompat);
free(compat, M_OFWPROP);
if (ret != 0)
diff --git a/sys/dev/ofw/ofw_bus_subr.h b/sys/dev/ofw/ofw_bus_subr.h
index 146009c..6532a16 100644
--- a/sys/dev/ofw/ofw_bus_subr.h
+++ b/sys/dev/ofw/ofw_bus_subr.h
@@ -107,6 +107,7 @@ phandle_t ofw_bus_find_iparent(phandle_t);
/* Helper routine for checking compat prop */
int ofw_bus_is_compatible(device_t, const char *);
int ofw_bus_is_compatible_strict(device_t, const char *);
+int ofw_bus_node_is_compatible(phandle_t, const char *);
/*
* Helper routine to search a list of compat properties. The table is
diff --git a/sys/dev/uart/uart_cpu_powerpc.c b/sys/dev/uart/uart_cpu_powerpc.c
index 8d98405..d3155b0 100644
--- a/sys/dev/uart/uart_cpu_powerpc.c
+++ b/sys/dev/uart/uart_cpu_powerpc.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/ofw_machdep.h>
+#include <dev/ofw/ofw_bus_subr.h>
#include <dev/ofw/openfirm.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
@@ -163,14 +164,13 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di)
return (ENXIO);
if (strcmp(buf, "serial") != 0)
return (ENXIO);
- if (OF_getprop(input, "compatible", buf, sizeof(buf)) == -1)
- return (ENXIO);
- if (strncmp(buf, "chrp,es", 7) == 0) {
+ if (ofw_bus_node_is_compatible(input, "chrp,es")) {
class = &uart_z8530_class;
di->bas.regshft = 4;
di->bas.chan = 1;
- } else if (strcmp(buf,"ns16550") == 0 || strcmp(buf,"ns8250") == 0) {
+ } else if (ofw_bus_node_is_compatible(input,"ns16550") ||
+ ofw_bus_node_is_compatible(input,"ns8250")) {
class = &uart_ns8250_class;
di->bas.regshft = 0;
di->bas.chan = 0;
OpenPOWER on IntegriCloud