PCI subsystem: Refactor PCI bridge register control

Change-Id: I1766c92abe7a74326c49df74ba38930a502fcb5b
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: http://review.coreboot.org/8536
Tested-by: build bot (Jenkins)
Reviewed-by: Timothy Pearson <tpearson@raptorengineeringinc.com>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
This commit is contained in:
Kyösti Mälkki 2015-02-23 06:58:26 +02:00
parent 6f37017c57
commit 3345240453
2 changed files with 51 additions and 26 deletions

View File

@ -1162,6 +1162,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.
*
@ -1182,8 +1229,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));
@ -1207,27 +1252,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);
@ -1237,9 +1262,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;

View File

@ -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 */