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/powerpc/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/powerpc/ofw')
-rw-r--r-- | sys/powerpc/ofw/ofw_pci.c | 4 | ||||
-rw-r--r-- | sys/powerpc/ofw/ofw_pcib_pci.c | 6 | ||||
-rw-r--r-- | sys/powerpc/ofw/ofw_pcibus.c | 36 |
3 files changed, 21 insertions, 25 deletions
diff --git a/sys/powerpc/ofw/ofw_pci.c b/sys/powerpc/ofw/ofw_pci.c index 692b1ab..8543035 100644 --- a/sys/powerpc/ofw/ofw_pci.c +++ b/sys/powerpc/ofw/ofw_pci.c @@ -273,9 +273,7 @@ ofw_pci_route_interrupt(device_t bus, device_t dev, int pin) &sc->sc_pci_iinfo, ®, sizeof(reg), &pintr, sizeof(pintr), mintr, sizeof(mintr), &iparent); if (intrcells) { - pintr = ofw_bus_map_intr(dev, iparent, mintr[0]); - if (intrcells == 2) - ofw_bus_config_intr(dev, pintr, mintr[1]); + pintr = ofw_bus_map_intr(dev, iparent, intrcells, mintr); return (pintr); } diff --git a/sys/powerpc/ofw/ofw_pcib_pci.c b/sys/powerpc/ofw/ofw_pcib_pci.c index df274c4..823f7c9 100644 --- a/sys/powerpc/ofw/ofw_pcib_pci.c +++ b/sys/powerpc/ofw/ofw_pcib_pci.c @@ -158,10 +158,8 @@ ofw_pcib_pci_route_interrupt(device_t bridge, device_t dev, int intpin) * it again on higher levels - that causes problems * in some cases, and never seems to be required. */ - mintr[0] = ofw_bus_map_intr(dev, iparent, mintr[0]); - if (intrcells == 2) - ofw_bus_config_intr(dev, mintr[0], mintr[1]); - + mintr[0] = ofw_bus_map_intr(dev, iparent, intrcells, + mintr); return (mintr[0]); } } else if (intpin >= 1 && intpin <= 4) { diff --git a/sys/powerpc/ofw/ofw_pcibus.c b/sys/powerpc/ofw/ofw_pcibus.c index f1063a1..ee14ccf 100644 --- a/sys/powerpc/ofw/ofw_pcibus.c +++ b/sys/powerpc/ofw/ofw_pcibus.c @@ -216,13 +216,9 @@ ofw_pcibus_enum_devtree(device_t dev, u_int domain, u_int busno) "#interrupt-cells", &icells, sizeof(icells)); intr[0] = ofw_bus_map_intr(dev, iparent, - intr[0]); + icells, intr); } - if (iparent != 0 && icells > 1) - ofw_bus_config_intr(dev, intr[0], - intr[1]); - resource_list_add(&dinfo->opd_dinfo.resources, SYS_RES_IRQ, 0, intr[0], intr[0], 1); } @@ -309,18 +305,18 @@ ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child, char *buf, static int ofw_pcibus_assign_interrupt(device_t dev, device_t child) { - ofw_pci_intr_t intr; + ofw_pci_intr_t intr[2]; phandle_t node, iparent; - int isz; + int isz, icells; node = ofw_bus_get_node(child); if (node == -1) { /* Non-firmware enumerated child, use standard routing */ - intr = pci_get_intpin(child); + intr[0] = pci_get_intpin(child); return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, - intr)); + intr[0])); } /* @@ -331,24 +327,28 @@ ofw_pcibus_assign_interrupt(device_t dev, device_t child) iparent = -1; if (OF_getprop(node, "interrupt-parent", &iparent, sizeof(iparent)) < 0) iparent = -1; + icells = 1; + if (iparent != -1) + OF_getprop(OF_xref_phandle(iparent), "#interrupt-cells", + &icells, sizeof(icells)); /* * Any AAPL,interrupts property gets priority and is * fully specified (i.e. does not need routing) */ - isz = OF_getprop(node, "AAPL,interrupts", &intr, sizeof(intr)); - if (isz == sizeof(intr)) - return ((iparent == -1) ? intr : ofw_bus_map_intr(dev, iparent, - intr)); + isz = OF_getprop(node, "AAPL,interrupts", intr, sizeof(intr)); + if (isz == sizeof(intr[0])*icells) + return ((iparent == -1) ? intr[0] : ofw_bus_map_intr(dev, + iparent, icells, intr)); - isz = OF_getprop(node, "interrupts", &intr, sizeof(intr)); - if (isz == sizeof(intr)) { + isz = OF_getprop(node, "interrupts", intr, sizeof(intr)); + if (isz == sizeof(intr[0])*icells) { if (iparent != -1) - intr = ofw_bus_map_intr(dev, iparent, intr); + intr[0] = ofw_bus_map_intr(dev, iparent, icells, intr); } else { /* No property: our best guess is the intpin. */ - intr = pci_get_intpin(child); + intr[0] = pci_get_intpin(child); } /* @@ -361,7 +361,7 @@ ofw_pcibus_assign_interrupt(device_t dev, device_t child) * will always use the route_interrupt method, and treat exceptions * on the level they become apparent. */ - return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr)); + return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr[0])); } static const struct ofw_bus_devinfo * |