From e905cdcce386f9752ff8a655f9ed0e4961a9a902 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 6 Mar 2015 17:15:29 +0000 Subject: [PATCH] [xhci] Undo PCH-specific quirk fixes when removing device Restore the original values of XUSB2PR and USB3PSSEN, in case we are booting an OS with no support for xHCI. Suggested-by: Dan Ellis Signed-off-by: Michael Brown --- src/drivers/usb/xhci.c | 27 +++++++++++++++++++++++++-- src/drivers/usb/xhci.h | 41 ++++++++++++++++++++++++++--------------- 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/drivers/usb/xhci.c b/src/drivers/usb/xhci.c index 5d4cb151..5d067bd0 100644 --- a/src/drivers/usb/xhci.c +++ b/src/drivers/usb/xhci.c @@ -3019,7 +3019,8 @@ static struct usb_host_operations xhci_operations = { * @v xhci xHCI device * @v pci PCI device */ -static void xhci_pch ( struct xhci_device *xhci, struct pci_device *pci ) { +static void xhci_pch_fix ( struct xhci_device *xhci, struct pci_device *pci ) { + struct xhci_pch *pch = &xhci->pch; uint32_t xusb2pr; uint32_t xusb2prm; uint32_t usb3pssen; @@ -3034,6 +3035,7 @@ static void xhci_pch ( struct xhci_device *xhci, struct pci_device *pci ) { DBGC ( xhci, "XHCI %p enabling SuperSpeed on ports %08x\n", xhci, ( usb3prm & ~usb3pssen ) ); } + pch->usb3pssen = usb3pssen; usb3pssen |= usb3prm; pci_write_config_dword ( pci, XHCI_PCH_USB3PSSEN, usb3pssen ); @@ -3044,10 +3046,27 @@ static void xhci_pch ( struct xhci_device *xhci, struct pci_device *pci ) { DBGC ( xhci, "XHCI %p routing ports %08x from EHCI to xHCI\n", xhci, ( xusb2prm & ~xusb2pr ) ); } + pch->xusb2pr = xusb2pr; xusb2pr |= xusb2prm; pci_write_config_dword ( pci, XHCI_PCH_XUSB2PR, xusb2pr ); } +/** + * Undo Intel PCH-specific quirk fixes + * + * @v xhci xHCI device + * @v pci PCI device + */ +static void xhci_pch_undo ( struct xhci_device *xhci, struct pci_device *pci ) { + struct xhci_pch *pch = &xhci->pch; + + /* Restore USB2 port routing to original state */ + pci_write_config_dword ( pci, XHCI_PCH_XUSB2PR, pch->xusb2pr ); + + /* Restore SuperSpeed capability to original state */ + pci_write_config_dword ( pci, XHCI_PCH_USB3PSSEN, pch->usb3pssen ); +} + /** * Probe PCI device * @@ -3091,7 +3110,7 @@ static int xhci_probe ( struct pci_device *pci ) { /* Fix Intel PCH-specific quirks, if applicable */ if ( pci->id->driver_data & XHCI_PCH ) - xhci_pch ( xhci, pci ); + xhci_pch_fix ( xhci, pci ); /* Reset device */ if ( ( rc = xhci_reset ( xhci ) ) != 0 ) @@ -3126,6 +3145,8 @@ static int xhci_probe ( struct pci_device *pci ) { err_alloc_bus: xhci_reset ( xhci ); err_reset: + if ( pci->id->driver_data & XHCI_PCH ) + xhci_pch_undo ( xhci, pci ); xhci_legacy_release ( xhci ); err_legacy_claim: iounmap ( xhci->regs ); @@ -3147,6 +3168,8 @@ static void xhci_remove ( struct pci_device *pci ) { unregister_usb_bus ( bus ); free_usb_bus ( bus ); xhci_reset ( xhci ); + if ( pci->id->driver_data & XHCI_PCH ) + xhci_pch_undo ( xhci, pci ); xhci_legacy_release ( xhci ); iounmap ( xhci->regs ); free ( xhci ); diff --git a/src/drivers/usb/xhci.h b/src/drivers/usb/xhci.h index d7bfff16..269f50b8 100644 --- a/src/drivers/usb/xhci.h +++ b/src/drivers/usb/xhci.h @@ -1004,6 +1004,29 @@ xhci_ring_consumed ( struct xhci_trb_ring *ring ) { */ #define XHCI_PORT_RESET_MAX_WAIT_MS 500 +/** Intel PCH quirk */ +struct xhci_pch { + /** USB2 port routing register original value */ + uint32_t xusb2pr; + /** USB3 port SuperSpeed enable register original value */ + uint32_t usb3pssen; +}; + +/** Intel PCH quirk flag */ +#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 SuperSpeed enable register */ +#define XHCI_PCH_USB3PSSEN 0xd8 + +/** Intel PCH USB3 port routing mask register */ +#define XHCI_PCH_USB3PRM 0xdc + /** An xHCI device */ struct xhci_device { /** Registers */ @@ -1061,6 +1084,9 @@ struct xhci_device { /** USB bus */ struct usb_bus *bus; + + /** Intel PCH quirk */ + struct xhci_pch pch; }; /** An xHCI device slot */ @@ -1103,19 +1129,4 @@ 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 */