summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--payloads/libpayload/drivers/usb/generic_hub.c6
-rw-r--r--payloads/libpayload/drivers/usb/quirks.c24
-rw-r--r--payloads/libpayload/drivers/usb/xhci.c4
-rw-r--r--payloads/libpayload/include/usb/usb.h2
4 files changed, 34 insertions, 2 deletions
diff --git a/payloads/libpayload/drivers/usb/generic_hub.c b/payloads/libpayload/drivers/usb/generic_hub.c
index 9d444ee792..7263400840 100644
--- a/payloads/libpayload/drivers/usb/generic_hub.c
+++ b/payloads/libpayload/drivers/usb/generic_hub.c
@@ -218,9 +218,11 @@ generic_hub_poll(usbdev_t *const dev)
if (!hub)
return;
- if (hub->ops->hub_status_changed &&
- hub->ops->hub_status_changed(dev) != 1)
+ if (!(dev->quirks & USB_QUIRK_HUB_NO_USBSTS_PCD) &&
+ hub->ops->hub_status_changed &&
+ hub->ops->hub_status_changed(dev) != 1) {
return;
+ }
int port;
for (port = 1; port <= hub->num_ports; ++port) {
diff --git a/payloads/libpayload/drivers/usb/quirks.c b/payloads/libpayload/drivers/usb/quirks.c
index 0a3514933c..d5be0e6cda 100644
--- a/payloads/libpayload/drivers/usb/quirks.c
+++ b/payloads/libpayload/drivers/usb/quirks.c
@@ -59,6 +59,30 @@ usb_quirks_t usb_quirks[] = {
*/
};
+#if CONFIG(LP_USB_PCI)
+usb_quirks_t pci_quirks[] = {
+ /* QEMU XHCI root hub does not implement port change detect */
+ { 0x1b36, 0x000d, USB_QUIRK_HUB_NO_USBSTS_PCD, 0 },
+};
+
+u32 pci_quirk_check(pcidev_t controller)
+{
+ int i;
+ u16 vendor = pci_read_config16(controller, REG_VENDOR_ID);
+ u16 device = pci_read_config16(controller, REG_DEVICE_ID);
+
+ for (i = 0; i < ARRAY_SIZE(pci_quirks); i++) {
+ if ((pci_quirks[i].vendor == vendor) &&
+ (pci_quirks[i].device == device)) {
+ printf("PCI quirks enabled: %08x\n", pci_quirks[i].quirks);
+ return pci_quirks[i].quirks;
+ }
+ }
+
+ return USB_QUIRK_NONE;
+}
+#endif
+
u32 usb_quirk_check(u16 vendor, u16 device)
{
int i;
diff --git a/payloads/libpayload/drivers/usb/xhci.c b/payloads/libpayload/drivers/usb/xhci.c
index ef1d73ff68..21af579f4c 100644
--- a/payloads/libpayload/drivers/usb/xhci.c
+++ b/payloads/libpayload/drivers/usb/xhci.c
@@ -314,9 +314,13 @@ xhci_pci_init (pcidev_t addr)
controller = xhci_init((unsigned long)reg_addr);
if (controller) {
+ xhci_t *xhci = controller->instance;
controller->pcidev = addr;
xhci_switch_ppt_ports(addr);
+
+ /* Set up any quirks for controller root hub */
+ xhci->roothub->quirks = pci_quirk_check(addr);
}
return controller;
diff --git a/payloads/libpayload/include/usb/usb.h b/payloads/libpayload/include/usb/usb.h
index 5d27f7cbc6..328e8839fc 100644
--- a/payloads/libpayload/include/usb/usb.h
+++ b/payloads/libpayload/include/usb/usb.h
@@ -318,6 +318,7 @@ void usb_detach_device(hci_t *controller, int devno);
int usb_attach_device(hci_t *controller, int hubaddress, int port,
usb_speed speed);
+u32 pci_quirk_check(pcidev_t controller);
u32 usb_quirk_check(u16 vendor, u16 device);
int usb_interface_check(u16 vendor, u16 device);
@@ -330,6 +331,7 @@ int usb_interface_check(u16 vendor, u16 device);
#define USB_QUIRK_MSC_FORCE_TRANS_CBI_I (1 << 6)
#define USB_QUIRK_MSC_NO_TEST_UNIT_READY (1 << 7)
#define USB_QUIRK_MSC_SHORT_INQUIRY (1 << 8)
+#define USB_QUIRK_HUB_NO_USBSTS_PCD (1 << 9)
#define USB_QUIRK_TEST (1 << 31)
#define USB_QUIRK_NONE 0