summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/mpc85xx
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2010-02-01 17:51:01 +0000
committermarcel <marcel@FreeBSD.org>2010-02-01 17:51:01 +0000
commited3a5157593e6ac00a5e6d1f6841d12fa197035b (patch)
tree66c07a7f06cf0eb8662acdb96a1006aede6276d1 /sys/powerpc/mpc85xx
parent10096f5f2b4a32628e4b3f9a9118e9ee7f314c6e (diff)
downloadFreeBSD-src-ed3a5157593e6ac00a5e6d1f6841d12fa197035b.zip
FreeBSD-src-ed3a5157593e6ac00a5e6d1f6841d12fa197035b.tar.gz
Make PCI Express host controllers functional, by:
1. checking whether there's a link before initializing devices on the bus. When there's no link any access onto the bus will wedge the CPU. 2. synthesizing the class & subclass so that the host controller appears as a standard PCI bridge, rather than a PowerPC CPU.
Diffstat (limited to 'sys/powerpc/mpc85xx')
-rw-r--r--sys/powerpc/mpc85xx/pci_ocp.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/sys/powerpc/mpc85xx/pci_ocp.c b/sys/powerpc/mpc85xx/pci_ocp.c
index 0a1642c..eba3f50 100644
--- a/sys/powerpc/mpc85xx/pci_ocp.c
+++ b/sys/powerpc/mpc85xx/pci_ocp.c
@@ -76,6 +76,9 @@ __FBSDID("$FreeBSD$");
#define REG_PIWBEAR(n) (0x0e0c - 0x20 * (n))
#define REG_PIWAR(n) (0x0e10 - 0x20 * (n))
+#define PCIR_FSL_LTSSM 0x404
+#define FSL_LTSSM_L0 0x16
+
#define DEVFN(b, s, f) ((b << 16) | (s << 8) | f)
struct pci_ocp_softc {
@@ -274,6 +277,18 @@ pci_ocp_read_config(device_t dev, u_int bus, u_int slot, u_int func,
if (bus == sc->sc_busnr && !sc->sc_pcie_cap && slot < 10)
return (~0);
devfn = DEVFN(bus, slot, func);
+ /*
+ * For the host controller itself, pretend to be a standard
+ * PCI bridge, rather than a PowerPC processor. That way the
+ * generic PCI code will enumerate all subordinate busses
+ * and devices as usual.
+ */
+ if (sc->sc_pcie_cap && devfn == 0) {
+ if (reg == PCIR_CLASS && bytes == 1)
+ return (PCIC_BRIDGE);
+ if (reg == PCIR_SUBCLASS && bytes == 1)
+ return (PCIS_BRIDGE_PCI);
+ }
if (devfn == sc->sc_devfn_tundra)
return (~0);
if (devfn == sc->sc_devfn_via_ide && reg == PCIR_INTPIN)
@@ -739,6 +754,17 @@ pci_ocp_attach(device_t dev)
sc->sc_devfn_tundra = -1;
sc->sc_devfn_via_ide = -1;
+ /*
+ * PCI Express host controllers require a link. We don't
+ * fail the attach if there's no link, but we also don't
+ * create a child pci(4) device.
+ */
+ if (sc->sc_pcie_cap) {
+ cfgreg = pci_ocp_cfgread(sc, 0, 0, 0, PCIR_FSL_LTSSM, 4);
+ if (cfgreg < FSL_LTSSM_L0)
+ return (0);
+ }
+
maxslot = (sc->sc_pcie_cap) ? 1 : 31;
pci_ocp_init(sc, sc->sc_busnr, maxslot);
OpenPOWER on IntegriCloud