diff --git a/src/drivers/usb/xhci.c b/src/drivers/usb/xhci.c index 36dfacc2..5d4cb151 100644 --- a/src/drivers/usb/xhci.c +++ b/src/drivers/usb/xhci.c @@ -3013,6 +3013,41 @@ static struct usb_host_operations xhci_operations = { }, }; +/** + * Fix Intel PCH-specific quirks + * + * @v xhci xHCI device + * @v pci PCI device + */ +static void xhci_pch ( struct xhci_device *xhci, struct pci_device *pci ) { + uint32_t xusb2pr; + uint32_t xusb2prm; + uint32_t usb3pssen; + uint32_t usb3prm; + + /* Enable SuperSpeed capability. Do this before rerouting + * USB2 ports, so that USB3 devices connect at SuperSpeed. + */ + pci_read_config_dword ( pci, XHCI_PCH_USB3PSSEN, &usb3pssen ); + pci_read_config_dword ( pci, XHCI_PCH_USB3PRM, &usb3prm ); + if ( usb3prm & ~usb3pssen ) { + DBGC ( xhci, "XHCI %p enabling SuperSpeed on ports %08x\n", + xhci, ( usb3prm & ~usb3pssen ) ); + } + usb3pssen |= usb3prm; + pci_write_config_dword ( pci, XHCI_PCH_USB3PSSEN, usb3pssen ); + + /* Route USB2 ports from EHCI to xHCI */ + pci_read_config_dword ( pci, XHCI_PCH_XUSB2PR, &xusb2pr ); + pci_read_config_dword ( pci, XHCI_PCH_XUSB2PRM, &xusb2prm ); + if ( xusb2prm & ~xusb2pr ) { + DBGC ( xhci, "XHCI %p routing ports %08x from EHCI to xHCI\n", + xhci, ( xusb2prm & ~xusb2pr ) ); + } + xusb2pr |= xusb2prm; + pci_write_config_dword ( pci, XHCI_PCH_XUSB2PR, xusb2pr ); +} + /** * Probe PCI device * @@ -3054,6 +3089,10 @@ static int xhci_probe ( struct pci_device *pci ) { if ( ( rc = xhci_legacy_claim ( xhci ) ) != 0 ) goto err_legacy_claim; + /* Fix Intel PCH-specific quirks, if applicable */ + if ( pci->id->driver_data & XHCI_PCH ) + xhci_pch ( xhci, pci ); + /* Reset device */ if ( ( rc = xhci_reset ( xhci ) ) != 0 ) goto err_reset; @@ -3115,6 +3154,7 @@ static void xhci_remove ( struct pci_device *pci ) { /** XHCI PCI device IDs */ static struct pci_device_id xhci_ids[] = { + PCI_ROM ( 0x8086, 0xffff, "xhci-pch", "xHCI (Intel PCH)", XHCI_PCH ), PCI_ROM ( 0xffff, 0xffff, "xhci", "xHCI", 0 ), }; diff --git a/src/drivers/usb/xhci.h b/src/drivers/usb/xhci.h index d0effe43..d7bfff16 100644 --- a/src/drivers/usb/xhci.h +++ b/src/drivers/usb/xhci.h @@ -1103,4 +1103,19 @@ struct xhci_endpoint { struct xhci_trb_ring ring; }; +/** Intel PCH quirk */ +#define XHCI_PCH 0x0001 + +/** Intel PCH USB2 port routing register */ +#define XHCI_PCH_XUSB2PR 0xd0 + +/** Intel PCH USB2 port routing mask register */ +#define XHCI_PCH_XUSB2PRM 0xd4 + +/** Intel PCH USB3 port SuperSpeed enable register */ +#define XHCI_PCH_USB3PSSEN 0xd8 + +/** Intel PCH USB3 port routing mask register */ +#define XHCI_PCH_USB3PRM 0xdc + #endif /* _IPXE_XHCI_H */