summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/ofw
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2014-05-13 16:59:50 +0000
committerian <ian@FreeBSD.org>2014-05-13 16:59:50 +0000
commit3d20d204d8598105e6dd4fb0d595e33d2461a02b (patch)
treea0ed8fb1178d7a67da2987bec28b68a4a0cbc9c2 /sys/powerpc/ofw
parent788d947f59320093c08b42453a93721d4d0d5a5c (diff)
downloadFreeBSD-src-3d20d204d8598105e6dd4fb0d595e33d2461a02b.zip
FreeBSD-src-3d20d204d8598105e6dd4fb0d595e33d2461a02b.tar.gz
MFC r256814, r256816, r256818, r256846, r256855, r256864 (by nwhitehorn):
- Handle 2GB of ram - Allow the OFW interrupt mapping code to work with PCI devices not enumerated by Open Firmware, as in the case of FDT. - Provide an interface for PCI bus drivers that need some of ofw_pci's metadata during attach. - Use standard ofw_bus helpers instead of reinventing the wheel. - Make hard-wired TLB allocations be at minimum one page.
Diffstat (limited to 'sys/powerpc/ofw')
-rw-r--r--sys/powerpc/ofw/ofw_pci.c27
-rw-r--r--sys/powerpc/ofw/ofw_pci.h2
-rw-r--r--sys/powerpc/ofw/ofw_pcib_pci.c8
-rw-r--r--sys/powerpc/ofw/ofw_pcibus.c11
4 files changed, 35 insertions, 13 deletions
diff --git a/sys/powerpc/ofw/ofw_pci.c b/sys/powerpc/ofw/ofw_pci.c
index 46d483d..f3e9e78 100644
--- a/sys/powerpc/ofw/ofw_pci.c
+++ b/sys/powerpc/ofw/ofw_pci.c
@@ -124,7 +124,7 @@ static device_method_t ofw_pci_methods[] = {
DEFINE_CLASS_0(ofw_pci, ofw_pci_driver, ofw_pci_methods, 0);
int
-ofw_pci_attach(device_t dev)
+ofw_pci_init(device_t dev)
{
struct ofw_pci_softc *sc;
phandle_t node;
@@ -134,6 +134,7 @@ ofw_pci_attach(device_t dev)
node = ofw_bus_get_node(dev);
sc = device_get_softc(dev);
+ sc->sc_initialized = 1;
if (OF_getprop(node, "reg", &sc->sc_pcir, sizeof(sc->sc_pcir)) == -1)
return (ENXIO);
@@ -217,13 +218,28 @@ ofw_pci_attach(device_t dev)
"error = %d\n", rp->pci_hi &
OFW_PCI_PHYS_HI_SPACEMASK, rp->pci,
rp->pci + rp->size - 1, error);
- panic("AHOY");
return (error);
}
}
ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t));
+ return (error);
+}
+
+int
+ofw_pci_attach(device_t dev)
+{
+ struct ofw_pci_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ if (!sc->sc_initialized) {
+ error = ofw_pci_init(dev);
+ if (error)
+ return (error);
+ }
+
device_add_child(dev, "pci", device_get_unit(dev));
return (bus_generic_attach(dev));
}
@@ -246,6 +262,13 @@ ofw_pci_route_interrupt(device_t bus, device_t dev, int pin)
sc = device_get_softc(bus);
pintr = pin;
+
+ /* Fabricate imap information in case this isn't an OFW device */
+ bzero(&reg, sizeof(reg));
+ reg.phys_hi = (pci_get_bus(dev) << OFW_PCI_PHYS_HI_BUSSHIFT) |
+ (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) |
+ (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT);
+
if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, &reg,
sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr),
&iparent, maskbuf))
diff --git a/sys/powerpc/ofw/ofw_pci.h b/sys/powerpc/ofw/ofw_pci.h
index dd277e9..388aa12 100644
--- a/sys/powerpc/ofw/ofw_pci.h
+++ b/sys/powerpc/ofw/ofw_pci.h
@@ -52,6 +52,7 @@ struct ofw_pci_softc {
device_t sc_dev;
phandle_t sc_node;
int sc_bus;
+ int sc_initialized;
int sc_quirks;
@@ -68,6 +69,7 @@ struct ofw_pci_softc {
struct ofw_bus_iinfo sc_pci_iinfo;
};
+int ofw_pci_init(device_t dev);
int ofw_pci_attach(device_t dev);
#endif // POWERPC_OFW_OFW_PCI_H
diff --git a/sys/powerpc/ofw/ofw_pcib_pci.c b/sys/powerpc/ofw/ofw_pcib_pci.c
index d6c4168..fb0a488 100644
--- a/sys/powerpc/ofw/ofw_pcib_pci.c
+++ b/sys/powerpc/ofw/ofw_pcib_pci.c
@@ -29,6 +29,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/systm.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/malloc.h>
@@ -141,6 +142,13 @@ ofw_pcib_pci_route_interrupt(device_t bridge, device_t dev, int intpin)
ii = &sc->ops_iinfo;
if (ii->opi_imapsz > 0) {
pintr = intpin;
+
+ /* Fabricate imap information if this isn't an OFW device */
+ bzero(&reg, sizeof(reg));
+ reg.phys_hi = (pci_get_bus(dev) << OFW_PCI_PHYS_HI_BUSSHIFT) |
+ (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) |
+ (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT);
+
if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), ii, &reg,
sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr),
&iparent, maskbuf)) {
diff --git a/sys/powerpc/ofw/ofw_pcibus.c b/sys/powerpc/ofw/ofw_pcibus.c
index 8005e00..a17e6d7 100644
--- a/sys/powerpc/ofw/ofw_pcibus.c
+++ b/sys/powerpc/ofw/ofw_pcibus.c
@@ -320,20 +320,9 @@ ofw_pcibus_assign_interrupt(device_t dev, device_t child)
if (node == -1) {
/* Non-firmware enumerated child, use standard routing */
- /*
- * XXX: Right now we don't have anything sensible to do here,
- * since the ofw_imap stuff relies on nodes having a reg
- * property. There exist ways around this, so the ePAPR
- * spec will need to be studied.
- */
-
- return (PCI_INVALID_IRQ);
-
-#ifdef NOTYET
intr = pci_get_intpin(child);
return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child,
intr));
-#endif
}
/*
OpenPOWER on IntegriCloud