diff options
author | ian <ian@FreeBSD.org> | 2014-05-13 16:59:50 +0000 |
---|---|---|
committer | ian <ian@FreeBSD.org> | 2014-05-13 16:59:50 +0000 |
commit | 3d20d204d8598105e6dd4fb0d595e33d2461a02b (patch) | |
tree | a0ed8fb1178d7a67da2987bec28b68a4a0cbc9c2 /sys/powerpc/ofw | |
parent | 788d947f59320093c08b42453a93721d4d0d5a5c (diff) | |
download | FreeBSD-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.c | 27 | ||||
-rw-r--r-- | sys/powerpc/ofw/ofw_pci.h | 2 | ||||
-rw-r--r-- | sys/powerpc/ofw/ofw_pcib_pci.c | 8 | ||||
-rw-r--r-- | sys/powerpc/ofw/ofw_pcibus.c | 11 |
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(®, 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, ®, 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(®, 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, ®, 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 } /* |