Kyösti Mälkki (kyosti.malkki@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/8536
-gerrit
commit 9f30b51ee8c110434d7693a7d6096f1a0a8073ee Author: Kyösti Mälkki kyosti.malkki@gmail.com Date: Mon Feb 23 06:58:26 2015 +0200
PCI subsystem: Refactor PCI bridge register control
Change-Id: I1766c92abe7a74326c49df74ba38930a502fcb5b Signed-off-by: Kyösti Mälkki kyosti.malkki@gmail.com --- src/device/pci_device.c | 76 +++++++++++++++++++++++++++++---------------- src/include/device/device.h | 1 + 2 files changed, 51 insertions(+), 26 deletions(-)
diff --git a/src/device/pci_device.c b/src/device/pci_device.c index 127ee32..d3a7865 100644 --- a/src/device/pci_device.c +++ b/src/device/pci_device.c @@ -1167,6 +1167,53 @@ unsigned int pci_scan_bus(struct bus *bus, unsigned min_devfn, return max; }
+typedef enum { + PCI_ROUTE_CLOSE, + PCI_ROUTE_SCAN, + PCI_ROUTE_FINAL, +} scan_state; + +static void pci_bridge_route(struct bus *link, scan_state state) +{ + struct device *dev = link->dev; + struct bus *parent = dev->bus; + u32 reg, buses = 0; + + if (state == PCI_ROUTE_CLOSE) { + buses |= 0xfeff << 8; + } else if (state == PCI_ROUTE_SCAN) { + buses |= ((u32) link->secondary & 0xff) << 8; + buses |= ((u32) link->subordinate & 0xff) << 16; + } else if (state == PCI_ROUTE_FINAL) { + buses |= parent->secondary & 0xff; + buses |= ((u32) link->secondary & 0xff) << 8; + buses |= ((u32) link->subordinate & 0xff) << 16; + } + + if (state == PCI_ROUTE_SCAN) { + /* Clear all status bits and turn off memory, I/O and master enables. */ + link->bridge_cmd = pci_read_config16(dev, PCI_COMMAND); + pci_write_config16(dev, PCI_COMMAND, 0x0000); + pci_write_config16(dev, PCI_STATUS, 0xffff); + } + + /* + * Configure the bus numbers for this bridge: the configuration + * transactions will not be propagated by the bridge if it is not + * correctly configured. + */ + + reg = pci_read_config32(dev, PCI_PRIMARY_BUS); + reg &= 0xff000000; + reg |= buses; + pci_write_config32(dev, PCI_PRIMARY_BUS, reg); + + if (state == PCI_ROUTE_FINAL) { + pci_write_config16(dev, PCI_COMMAND, link->bridge_cmd); + } +} + + /** * Scan a PCI bridge and the buses behind the bridge. * @@ -1187,8 +1234,6 @@ unsigned int do_pci_scan_bridge(struct device *dev, unsigned int max, unsigned int max)) { struct bus *bus; - u32 buses; - u16 cr;
printk(BIOS_SPEW, "%s for %s\n", __func__, dev_path(dev));
@@ -1212,27 +1257,7 @@ unsigned int do_pci_scan_bridge(struct device *dev, unsigned int max, bus->secondary = ++max; bus->subordinate = 0xff;
- /* Clear all status bits and turn off memory, I/O and master enables. */ - cr = pci_read_config16(dev, PCI_COMMAND); - pci_write_config16(dev, PCI_COMMAND, 0x0000); - pci_write_config16(dev, PCI_STATUS, 0xffff); - - /* - * Read the existing primary/secondary/subordinate bus - * number configuration. - */ - buses = pci_read_config32(dev, PCI_PRIMARY_BUS); - - /* - * Configure the bus numbers for this bridge: the configuration - * transactions will not be propagated by the bridge if it is not - * correctly configured. - */ - buses &= 0xff000000; - buses |= (((unsigned int)(dev->bus->secondary) << 0) | - ((unsigned int)(bus->secondary) << 8) | - ((unsigned int)(bus->subordinate) << 16)); - pci_write_config32(dev, PCI_PRIMARY_BUS, buses); + pci_bridge_route(bus, PCI_ROUTE_SCAN);
/* Now we can scan all subordinate buses (those behind the bridge). */ max = do_scan_bus(bus, 0x00, 0xff, max); @@ -1242,9 +1267,8 @@ unsigned int do_pci_scan_bridge(struct device *dev, unsigned int max, * bus number to its real value. */ bus->subordinate = max; - buses = (buses & 0xff00ffff) | ((unsigned int)(bus->subordinate) << 16); - pci_write_config32(dev, PCI_PRIMARY_BUS, buses); - pci_write_config16(dev, PCI_COMMAND, cr); + + pci_bridge_route(bus, PCI_ROUTE_FINAL);
printk(BIOS_SPEW, "%s returns max %d\n", __func__, max); return max; diff --git a/src/include/device/device.h b/src/include/device/device.h index 559557a..436420f 100644 --- a/src/include/device/device.h +++ b/src/include/device/device.h @@ -81,6 +81,7 @@ struct bus { ROMSTAGE_CONST struct device * children; /* devices behind this bridge */ ROMSTAGE_CONST struct bus *next; /* The next bridge on this device */ unsigned bridge_ctrl; /* Bridge control register */ + uint16_t bridge_cmd; /* Bridge command register */ unsigned char link_num; /* The index of this link */ uint16_t secondary; /* secondary bus number */ uint16_t subordinate; /* max subordinate bus number */