Modernize mpc85xx PCI hostbridge driver.

Summary:
* Take advantage of NEW_PCIB to remove a lot of setup code.
* Fix some bugs related to multiple PCI bridges.

There's still room for more cleanup, and still some bugs leftover, but this
cleans up a lot.

Test Plan: Tested on P5020 board with IDT PCIe switch.

Differential Revision: https://reviews.freebsd.org/D4127
This commit is contained in:
jhibbits 2015-11-22 01:16:43 +00:00
parent 8f26d7b382
commit 1f1d8cd1f5
2 changed files with 8 additions and 138 deletions

View File

@ -104,9 +104,9 @@ struct fsl_pcib_softc {
device_t sc_dev;
int sc_iomem_target;
bus_addr_t sc_iomem_alloc, sc_iomem_start, sc_iomem_end;
bus_addr_t sc_iomem_start, sc_iomem_end;
int sc_ioport_target;
bus_addr_t sc_ioport_alloc, sc_ioport_start, sc_ioport_end;
bus_addr_t sc_ioport_start, sc_ioport_end;
struct resource *sc_res;
bus_space_handle_t sc_bsh;
@ -266,9 +266,8 @@ fsl_pcib_attach(device_t dev)
/*
* Scan bus using firmware configured, 0 based bus numbering.
*/
sc->sc_busnr = 0;
maxslot = (sc->sc_pcie) ? 0 : PCI_SLOTMAX;
sc->sc_busnr = fsl_pcib_init(sc, sc->sc_busnr, maxslot);
fsl_pcib_init(sc, sc->sc_busnr, maxslot);
if (sc->sc_pcie) {
ltssm = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_LTSSM, 1);
@ -285,6 +284,7 @@ fsl_pcib_attach(device_t dev)
return (ofw_pci_attach(dev));
err:
//panic("Because I said so\n");
return (ENXIO);
}
@ -294,9 +294,6 @@ fsl_pcib_cfgread(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func,
{
uint32_t addr, data;
if (bus == sc->sc_busnr - 1)
bus = 0;
addr = CONFIG_ACCESS_ENABLE;
addr |= (bus & 0xff) << 16;
addr |= (slot & 0x1f) << 11;
@ -335,9 +332,6 @@ fsl_pcib_cfgwrite(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func,
{
uint32_t addr;
if (bus == sc->sc_busnr - 1)
bus = 0;
addr = CONFIG_ACCESS_ENABLE;
addr |= (bus & 0xff) << 16;
addr |= (slot & 0x1f) << 11;
@ -448,65 +442,6 @@ fsl_pcib_init_via(struct fsl_pcib_softc *sc, uint16_t device, int bus,
}
}
static int
fsl_pcib_init_bar(struct fsl_pcib_softc *sc, int bus, int slot, int func,
int barno)
{
bus_addr_t *allocp;
uint32_t addr, mask, size;
int reg, width;
reg = PCIR_BAR(barno);
if (DEVFN(bus, slot, func) == sc->sc_devfn_via_ide) {
switch (barno) {
case 0: addr = 0x1f0; break;
case 1: addr = 0x3f4; break;
case 2: addr = 0x170; break;
case 3: addr = 0x374; break;
case 4: addr = 0xcc0; break;
default: return (1);
}
fsl_pcib_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4);
return (1);
}
fsl_pcib_write_config(sc->sc_dev, bus, slot, func, reg, ~0, 4);
size = fsl_pcib_read_config(sc->sc_dev, bus, slot, func, reg, 4);
if (size == 0)
return (1);
width = ((size & 7) == 4) ? 2 : 1;
if (size & 1) { /* I/O port */
allocp = &sc->sc_ioport_alloc;
size &= ~3;
if ((size & 0xffff0000) == 0)
size |= 0xffff0000;
} else { /* memory */
allocp = &sc->sc_iomem_alloc;
size &= ~15;
}
mask = ~size;
size = mask + 1;
/* Sanity check (must be a power of 2). */
if (size & mask)
return (width);
addr = (*allocp + mask) & ~mask;
*allocp = addr + size;
if (bootverbose)
printf("PCI %u:%u:%u:%u: reg %x: size=%08x: addr=%08x\n",
device_get_unit(sc->sc_dev), bus, slot, func, reg,
size, addr);
fsl_pcib_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4);
if (width == 2)
fsl_pcib_write_config(sc->sc_dev, bus, slot, func, reg + 4,
0, 4);
return (width);
}
static int
fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int maxslot)
{
@ -514,9 +449,8 @@ fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int maxslot)
int old_pribus, old_secbus, old_subbus;
int new_pribus, new_secbus, new_subbus;
int slot, func, maxfunc;
int bar, maxbar;
uint16_t vendor, device;
uint8_t command, hdrtype, class, subclass;
uint8_t command, hdrtype, subclass;
secbus = bus;
for (slot = 0; slot <= maxslot; slot++) {
@ -550,26 +484,9 @@ fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int maxslot)
if (vendor == 0x1106)
fsl_pcib_init_via(sc, device, bus, slot, func);
/* Program the base address registers. */
maxbar = (hdrtype & PCIM_HDRTYPE) ? 1 : 6;
bar = 0;
while (bar < maxbar)
bar += fsl_pcib_init_bar(sc, bus, slot, func,
bar);
/* Put a placeholder interrupt value */
fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
PCIR_INTLINE, PCI_INVALID_IRQ, 1);
command |= PCIM_CMD_MEMEN | PCIM_CMD_PORTEN;
fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
PCIR_COMMAND, command, 1);
/*
* Handle PCI-PCI bridges
*/
class = fsl_pcib_read_config(sc->sc_dev, bus, slot,
func, PCIR_CLASS, 1);
subclass = fsl_pcib_read_config(sc->sc_dev, bus, slot,
func, PCIR_SUBCLASS, 1);
@ -579,32 +496,6 @@ fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int maxslot)
secbus++;
/* Program I/O decoder. */
fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
PCIR_IOBASEL_1, sc->sc_ioport_start >> 8, 1);
fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
PCIR_IOLIMITL_1, sc->sc_ioport_end >> 8, 1);
fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
PCIR_IOBASEH_1, sc->sc_ioport_start >> 16, 2);
fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
PCIR_IOLIMITH_1, sc->sc_ioport_end >> 16, 2);
/* Program (non-prefetchable) memory decoder. */
fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
PCIR_MEMBASE_1, sc->sc_iomem_start >> 16, 2);
fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
PCIR_MEMLIMIT_1, sc->sc_iomem_end >> 16, 2);
/* Program prefetchable memory decoder. */
fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
PCIR_PMBASEL_1, 0x0010, 2);
fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
PCIR_PMLIMITL_1, 0x000f, 2);
fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
PCIR_PMBASEH_1, 0x00000000, 4);
fsl_pcib_write_config(sc->sc_dev, bus, slot, func,
PCIR_PMLIMITH_1, 0x00000000, 4);
/* Read currect bus register configuration */
old_pribus = fsl_pcib_read_config(sc->sc_dev, bus,
slot, func, PCIR_PRIBUS_1, 1);
@ -678,10 +569,10 @@ fsl_pcib_outbound(struct fsl_pcib_softc *sc, int wnd, int res, uint64_t start,
switch (res) {
case SYS_RES_MEMORY:
attr = 0x80044000 | (ffsl(size) - 2);
attr = 0x80044000 | (ffsll(size) - 2);
break;
case SYS_RES_IOPORT:
attr = 0x80088000 | (ffsl(size) - 2);
attr = 0x80088000 | (ffsll(size) - 2);
break;
default:
attr = 0x0004401f;
@ -785,7 +676,6 @@ fsl_pcib_decode_win(phandle_t node, struct fsl_pcib_softc *sc)
sc->sc_ioport_start = sc->pci_sc.sc_range[i].pci;
sc->sc_ioport_end = sc->pci_sc.sc_range[i].pci +
sc->pci_sc.sc_range[i].size - 1;
sc->sc_ioport_alloc = 0x1000 + sc->pci_sc.sc_range[i].pci;
break;
case OFW_PCI_PHYS_HI_SPACE_MEM32:
case OFW_PCI_PHYS_HI_SPACE_MEM64:
@ -797,7 +687,6 @@ fsl_pcib_decode_win(phandle_t node, struct fsl_pcib_softc *sc)
sc->sc_iomem_start = sc->pci_sc.sc_range[i].pci;
sc->sc_iomem_end = sc->pci_sc.sc_range[i].pci +
sc->pci_sc.sc_range[i].size - 1;
sc->sc_iomem_alloc = sc->pci_sc.sc_range[i].pci;
break;
default:
panic("Unknown range type %#x\n",

View File

@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
static int
fsl_pcib_rc_probe(device_t dev)
{
if (pci_get_vendor(dev) != 0x1957)
return (ENXIO);
if (pci_get_progif(dev) != 0)
@ -71,28 +72,8 @@ fsl_pcib_rc_probe(device_t dev)
return (BUS_PROBE_DEFAULT);
}
static int
fsl_pcib_rc_attach(device_t dev)
{
struct pcib_softc *sc;
device_t child;
pcib_bridge_init(dev);
pcib_attach_common(dev);
sc = device_get_softc(dev);
if (sc->bus.sec != 0) {
child = device_add_child(dev, "pci", -1);
if (child != NULL)
return (bus_generic_attach(dev));
}
return (0);
}
static device_method_t fsl_pcib_rc_methods[] = {
DEVMETHOD(device_probe, fsl_pcib_rc_probe),
DEVMETHOD(device_attach, fsl_pcib_rc_attach),
DEVMETHOD_END
};