diff options
author | ian <ian@FreeBSD.org> | 2014-05-15 14:26:11 +0000 |
---|---|---|
committer | ian <ian@FreeBSD.org> | 2014-05-15 14:26:11 +0000 |
commit | 27f0a13f0adbfdb658bb63aac86772e0107c1c20 (patch) | |
tree | 51fd84ee4d563c9fcc06c0dd196587a24ab23dfc /sys/dev/ofw | |
parent | e24fc6cb17a568070581980459e14fc4808f0bb4 (diff) | |
download | FreeBSD-src-27f0a13f0adbfdb658bb63aac86772e0107c1c20.zip FreeBSD-src-27f0a13f0adbfdb658bb63aac86772e0107c1c20.tar.gz |
MFC r261351, r261352, r261355, r261396, r261397, r261398, r261403, r261404,
r261405
Open Firmware interrupt specifiers can consist of arbitrary-length byte
strings and include arbitrary information (IRQ line/domain/sense). When the
ofw_bus_map_intr() API was introduced, it assumed that, as on most systems,
these were either 1 cell, containing an interrupt line, or 2, containing
a line number plus a sense code. It turns out a non-negligible number of
ARM systems use 3 (or even 4!) cells for interrupts, so make this more
general.
Provide a simpler and more standards-compliant simplebus implementation to
get the Routerboard 800 up and running with the vendor device tree. This
does not implement some BERI-specific features (which hopefully won't be
necessary soon), so move the old code to mips/beri, with a higher attach
priority when built, until MIPS interrupt domain support is rearranged.
Allow nesting of simplebuses.
Add a set of helpers (ofw_bus_get_status() and ofw_bus_status_okay()) to
process "status" properties of OF nodes.
Fix one remnant endian flaw in nexus.
Diffstat (limited to 'sys/dev/ofw')
-rw-r--r-- | sys/dev/ofw/ofw_bus.h | 10 | ||||
-rw-r--r-- | sys/dev/ofw/ofw_bus_if.m | 34 | ||||
-rw-r--r-- | sys/dev/ofw/ofw_bus_subr.c | 27 | ||||
-rw-r--r-- | sys/dev/ofw/ofw_bus_subr.h | 4 | ||||
-rw-r--r-- | sys/dev/ofw/ofw_nexus.c | 5 |
5 files changed, 43 insertions, 37 deletions
diff --git a/sys/dev/ofw/ofw_bus.h b/sys/dev/ofw/ofw_bus.h index 1ea4845..f7c7295 100644 --- a/sys/dev/ofw/ofw_bus.h +++ b/sys/dev/ofw/ofw_bus.h @@ -71,15 +71,9 @@ ofw_bus_get_type(device_t dev) } static __inline int -ofw_bus_map_intr(device_t dev, phandle_t iparent, int irq) +ofw_bus_map_intr(device_t dev, phandle_t iparent, int icells, pcell_t *intr) { - return (OFW_BUS_MAP_INTR(dev, dev, iparent, irq)); -} - -static __inline int -ofw_bus_config_intr(device_t dev, int irq, int sense) -{ - return (OFW_BUS_CONFIG_INTR(dev, dev, irq, sense)); + return (OFW_BUS_MAP_INTR(dev, dev, iparent, icells, intr)); } #endif /* !_DEV_OFW_OFW_BUS_H_ */ diff --git a/sys/dev/ofw/ofw_bus_if.m b/sys/dev/ofw/ofw_bus_if.m index 0034a15..6486e96 100644 --- a/sys/dev/ofw/ofw_bus_if.m +++ b/sys/dev/ofw/ofw_bus_if.m @@ -46,6 +46,7 @@ HEADER { char *obd_model; char *obd_name; char *obd_type; + char *obd_status; }; }; @@ -57,7 +58,6 @@ CODE { static ofw_bus_get_node_t ofw_bus_default_get_node; static ofw_bus_get_type_t ofw_bus_default_get_type; static ofw_bus_map_intr_t ofw_bus_default_map_intr; - static ofw_bus_config_intr_t ofw_bus_default_config_intr; static const struct ofw_bus_devinfo * ofw_bus_default_get_devinfo(device_t bus, device_t dev) @@ -103,27 +103,15 @@ CODE { int ofw_bus_default_map_intr(device_t bus, device_t dev, phandle_t iparent, - int irq) + int icells, pcell_t *interrupt) { /* Propagate up the bus hierarchy until someone handles it. */ if (device_get_parent(bus) != NULL) return OFW_BUS_MAP_INTR(device_get_parent(bus), dev, - iparent, irq); + iparent, icells, interrupt); /* If that fails, then assume a one-domain system */ - return (irq); - } - - int - ofw_bus_default_config_intr(device_t bus, device_t dev, int irq, - int sense) - { - /* Propagate up the bus hierarchy until someone handles it. */ - if (device_get_parent(bus) != NULL) - return OFW_BUS_CONFIG_INTR(device_get_parent(bus), dev, - irq, sense); - - return (ENXIO); + return (interrupt[0]); } }; @@ -172,20 +160,14 @@ METHOD const char * get_type { } DEFAULT ofw_bus_default_get_type; # Map an (interrupt parent, IRQ) pair to a unique system-wide interrupt number. +# If the interrupt encoding includes a sense field, the interrupt sense will +# also be configured. METHOD int map_intr { device_t bus; device_t dev; phandle_t iparent; - int irq; + int icells; + pcell_t *interrupt; } DEFAULT ofw_bus_default_map_intr; -# Configure an interrupt using the device-tree encoded sense key (the second -# value in the interrupts property if interrupt-cells is 2). IRQ should be -# encoded as from ofw_bus_map_intr(). -METHOD int config_intr { - device_t bus; - device_t dev; - int irq; - int sense; -} DEFAULT ofw_bus_default_config_intr; diff --git a/sys/dev/ofw/ofw_bus_subr.c b/sys/dev/ofw/ofw_bus_subr.c index bf552a8..64ac11f 100644 --- a/sys/dev/ofw/ofw_bus_subr.c +++ b/sys/dev/ofw/ofw_bus_subr.c @@ -55,6 +55,7 @@ ofw_bus_gen_setup_devinfo(struct ofw_bus_devinfo *obd, phandle_t node) OF_getprop_alloc(node, "compatible", 1, (void **)&obd->obd_compat); OF_getprop_alloc(node, "device_type", 1, (void **)&obd->obd_type); OF_getprop_alloc(node, "model", 1, (void **)&obd->obd_model); + OF_getprop_alloc(node, "status", 1, (void **)&obd->obd_status); obd->obd_node = node; return (0); } @@ -73,6 +74,8 @@ ofw_bus_gen_destroy_devinfo(struct ofw_bus_devinfo *obd) free(obd->obd_name, M_OFWPROP); if (obd->obd_type != NULL) free(obd->obd_type, M_OFWPROP); + if (obd->obd_status != NULL) + free(obd->obd_status, M_OFWPROP); } int @@ -147,6 +150,30 @@ ofw_bus_gen_get_type(device_t bus, device_t dev) return (obd->obd_type); } +const char * +ofw_bus_get_status(device_t dev) +{ + const struct ofw_bus_devinfo *obd; + + obd = OFW_BUS_GET_DEVINFO(device_get_parent(dev), dev); + if (obd == NULL) + return (NULL); + + return (obd->obd_status); +} + +int +ofw_bus_status_okay(device_t dev) +{ + const char *status; + + status = ofw_bus_get_status(dev); + if (status == NULL || strcmp(status, "okay") == 0) + return (1); + + return (0); +} + int ofw_bus_is_compatible(device_t dev, const char *onecompat) { diff --git a/sys/dev/ofw/ofw_bus_subr.h b/sys/dev/ofw/ofw_bus_subr.h index e9ef5e4..a4d8b92 100644 --- a/sys/dev/ofw/ofw_bus_subr.h +++ b/sys/dev/ofw/ofw_bus_subr.h @@ -72,6 +72,10 @@ int ofw_bus_lookup_imap(phandle_t, struct ofw_bus_iinfo *, void *, int, int ofw_bus_search_intrmap(void *, int, void *, int, void *, int, void *, void *, void *, int, phandle_t *); +/* Helper to get device status property */ +const char *ofw_bus_get_status(device_t dev); +int ofw_bus_status_okay(device_t dev); + /* Helper to get node's interrupt parent */ void ofw_bus_find_iparent(phandle_t); diff --git a/sys/dev/ofw/ofw_nexus.c b/sys/dev/ofw/ofw_nexus.c index f602bfe..b3c5e03 100644 --- a/sys/dev/ofw/ofw_nexus.c +++ b/sys/dev/ofw/ofw_nexus.c @@ -467,11 +467,10 @@ nexus_setup_dinfo(device_t dev, phandle_t node) OF_searchencprop(OF_xref_phandle(iparent), "#interrupt-cells", &icells, sizeof(icells)); for (i = 0; i < nintr; i+= icells) { - intr[i] = ofw_bus_map_intr(dev, iparent, intr[i]); + intr[i] = ofw_bus_map_intr(dev, iparent, icells, + &intr[i]); resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, i, intr[i], intr[i], 1); - if (icells > 1) - ofw_bus_config_intr(dev, intr[i], intr[i+1]); } free(intr, M_OFWPROP); } |