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:
parent
a0962bf8bc
commit
fe11dfea79
@ -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",
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user