summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/ofw
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2014-05-15 14:26:11 +0000
committerian <ian@FreeBSD.org>2014-05-15 14:26:11 +0000
commit27f0a13f0adbfdb658bb63aac86772e0107c1c20 (patch)
tree51fd84ee4d563c9fcc06c0dd196587a24ab23dfc /sys/powerpc/ofw
parente24fc6cb17a568070581980459e14fc4808f0bb4 (diff)
downloadFreeBSD-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.c4
-rw-r--r--sys/powerpc/ofw/ofw_pcib_pci.c6
-rw-r--r--sys/powerpc/ofw/ofw_pcibus.c36
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, &reg, 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 *
OpenPOWER on IntegriCloud