libpayload: Handle multifunction bridge devices better.
This change modifies the code in libpayload that scans the PCI hierarchy for USB controllers. Previously, if a devices primary function (function 0) was a bridge, then none of the other functions, if any, would be looked at. If one of the other functions was a bridge, that wouldn't be handled either. The new version looks at each function that's present no matter what, and if it discovers that it's a bridge it scans the other side. Change-Id: I37f269a4fe505fd32d9594e2daf17ddd78609c15 Signed-off-by: Gabe Black <gabeblack@google.com> Reviewed-on: http://review.coreboot.org/2517 Reviewed-by: Marc Jones <marc.jones@se-eng.com> Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
This commit is contained in:
parent
6d0fe9cad0
commit
9e8af58263
|
@ -47,12 +47,12 @@ static int usb_controller_initialize(int bus, int dev, int func)
|
||||||
u32 class;
|
u32 class;
|
||||||
u32 devclass;
|
u32 devclass;
|
||||||
u32 prog_if;
|
u32 prog_if;
|
||||||
pcidev_t addr;
|
pcidev_t pci_device;
|
||||||
u32 pciid;
|
u32 pciid;
|
||||||
|
|
||||||
addr = PCI_DEV (bus, dev, func);
|
pci_device = PCI_DEV (bus, dev, func);
|
||||||
class = pci_read_config32(addr, 8);
|
class = pci_read_config32(pci_device, 8);
|
||||||
pciid = pci_read_config32(addr, 0);
|
pciid = pci_read_config32(pci_device, 0);
|
||||||
|
|
||||||
devclass = class >> 16;
|
devclass = class >> 16;
|
||||||
prog_if = (class >> 8) & 0xff;
|
prog_if = (class >> 8) & 0xff;
|
||||||
|
@ -63,9 +63,9 @@ static int usb_controller_initialize(int bus, int dev, int func)
|
||||||
if (devclass == 0xc03) {
|
if (devclass == 0xc03) {
|
||||||
u32 pci_command;
|
u32 pci_command;
|
||||||
|
|
||||||
pci_command = pci_read_config32(addr, PCI_COMMAND);
|
pci_command = pci_read_config32(pci_device, PCI_COMMAND);
|
||||||
pci_command |= PCI_COMMAND_MASTER;
|
pci_command |= PCI_COMMAND_MASTER;
|
||||||
pci_write_config32(addr, PCI_COMMAND, pci_command);
|
pci_write_config32(pci_device, PCI_COMMAND, pci_command);
|
||||||
|
|
||||||
usb_debug("%02x:%02x.%x %04x:%04x.%d ", bus, dev, func,
|
usb_debug("%02x:%02x.%x %04x:%04x.%d ", bus, dev, func,
|
||||||
pciid >> 16, pciid & 0xFFFF, func);
|
pciid >> 16, pciid & 0xFFFF, func);
|
||||||
|
@ -73,7 +73,7 @@ static int usb_controller_initialize(int bus, int dev, int func)
|
||||||
case 0x00:
|
case 0x00:
|
||||||
#ifdef CONFIG_USB_UHCI
|
#ifdef CONFIG_USB_UHCI
|
||||||
usb_debug("UHCI controller\n");
|
usb_debug("UHCI controller\n");
|
||||||
uhci_init (addr);
|
uhci_init (pci_device);
|
||||||
#else
|
#else
|
||||||
usb_debug("UHCI controller (not supported)\n");
|
usb_debug("UHCI controller (not supported)\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -82,7 +82,7 @@ static int usb_controller_initialize(int bus, int dev, int func)
|
||||||
case 0x10:
|
case 0x10:
|
||||||
#ifdef CONFIG_USB_OHCI
|
#ifdef CONFIG_USB_OHCI
|
||||||
usb_debug("OHCI controller\n");
|
usb_debug("OHCI controller\n");
|
||||||
ohci_init(addr);
|
ohci_init(pci_device);
|
||||||
#else
|
#else
|
||||||
usb_debug("OHCI controller (not supported)\n");
|
usb_debug("OHCI controller (not supported)\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -91,7 +91,7 @@ static int usb_controller_initialize(int bus, int dev, int func)
|
||||||
case 0x20:
|
case 0x20:
|
||||||
#ifdef CONFIG_USB_EHCI
|
#ifdef CONFIG_USB_EHCI
|
||||||
usb_debug("EHCI controller\n");
|
usb_debug("EHCI controller\n");
|
||||||
ehci_init(addr);
|
ehci_init(pci_device);
|
||||||
#else
|
#else
|
||||||
usb_debug("EHCI controller (not supported)\n");
|
usb_debug("EHCI controller (not supported)\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -100,7 +100,7 @@ static int usb_controller_initialize(int bus, int dev, int func)
|
||||||
case 0x30:
|
case 0x30:
|
||||||
#ifdef CONFIG_USB_XHCI
|
#ifdef CONFIG_USB_XHCI
|
||||||
usb_debug("xHCI controller\n");
|
usb_debug("xHCI controller\n");
|
||||||
xhci_init(addr);
|
xhci_init(pci_device);
|
||||||
#else
|
#else
|
||||||
usb_debug("xHCI controller (not supported)\n");
|
usb_debug("xHCI controller (not supported)\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -121,31 +121,37 @@ static void usb_scan_pci_bus(int bus)
|
||||||
int dev, func;
|
int dev, func;
|
||||||
for (dev = 0; dev < 32; dev++) {
|
for (dev = 0; dev < 32; dev++) {
|
||||||
u8 header_type;
|
u8 header_type;
|
||||||
pcidev_t addr = PCI_DEV(bus, dev, 0);
|
pcidev_t pci_device = PCI_DEV(bus, dev, 0);
|
||||||
|
|
||||||
/* Check if there's a device here at all. */
|
/* Check if there's a device here at all. */
|
||||||
if (pci_read_config32(addr, REG_VENDOR_ID) == 0xffffffff)
|
if (pci_read_config32(pci_device, REG_VENDOR_ID) == 0xffffffff)
|
||||||
continue;
|
continue;
|
||||||
header_type = pci_read_config8(addr, REG_HEADER_TYPE);
|
|
||||||
/* If this is a bridge, scan the bus on the other side. */
|
|
||||||
if ((header_type & ~HEADER_TYPE_MULTIFUNCTION) ==
|
|
||||||
HEADER_TYPE_BRIDGE) {
|
|
||||||
int sub_bus =
|
|
||||||
pci_read_config8(addr, REG_SECONDARY_BUS);
|
|
||||||
usb_scan_pci_bus(sub_bus);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* EHCI is defined by standards to be at a higher function
|
* EHCI is defined by standards to be at a higher function
|
||||||
* than the USB1 controllers. We don't want to init USB1 +
|
* than the USB1 controllers. We don't want to init USB1 +
|
||||||
* devices just to "steal" those for USB2, so make sure USB2
|
* devices just to "steal" those for USB2, so make sure USB2
|
||||||
* comes first.
|
* comes first by scanning multifunction devices from 7 to 0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Check for a multifunction device. */
|
/* Check for a multifunction device. */
|
||||||
|
header_type = pci_read_config8(pci_device, REG_HEADER_TYPE);
|
||||||
if (header_type & HEADER_TYPE_MULTIFUNCTION)
|
if (header_type & HEADER_TYPE_MULTIFUNCTION)
|
||||||
for (func = 7; func > 0; func--)
|
func = 7;
|
||||||
|
else
|
||||||
|
func = 0;
|
||||||
|
|
||||||
|
for (; func >= 0; func--) {
|
||||||
|
pci_device = PCI_DEV(bus, dev, func);
|
||||||
|
header_type = pci_read_config8(pci_device, REG_HEADER_TYPE);
|
||||||
|
/* If this is a bridge, scan the other side. */
|
||||||
|
if ((header_type & ~HEADER_TYPE_MULTIFUNCTION) ==
|
||||||
|
HEADER_TYPE_BRIDGE)
|
||||||
|
usb_scan_pci_bus(pci_read_config8(pci_device,
|
||||||
|
REG_SECONDARY_BUS));
|
||||||
|
else
|
||||||
usb_controller_initialize(bus, dev, func);
|
usb_controller_initialize(bus, dev, func);
|
||||||
/* Initialize function 0. */
|
}
|
||||||
usb_controller_initialize(bus, dev, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue