Przeglądaj źródła

[xhci] Enable USB3 ports on Intel PCH8/PCH9 controllers

Intel PCH controllers default to routing USB2 ports to EHCI rather
than xHCI, and default to disabling SuperSpeed connections.
Manipulate the PCI configuration space registers as necessary to
reroute ports and enable SuperSpeed.

Originally-fixed-by: Dan Ellis <Dan.Ellis@displaylink.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 10 lat temu
rodzic
commit
ff320404d5
2 zmienionych plików z 55 dodań i 0 usunięć
  1. 40
    0
      src/drivers/usb/xhci.c
  2. 15
    0
      src/drivers/usb/xhci.h

+ 40
- 0
src/drivers/usb/xhci.c Wyświetl plik

@@ -3013,6 +3013,41 @@ static struct usb_host_operations xhci_operations = {
3013 3013
 	},
3014 3014
 };
3015 3015
 
3016
+/**
3017
+ * Fix Intel PCH-specific quirks
3018
+ *
3019
+ * @v xhci		xHCI device
3020
+ * @v pci		PCI device
3021
+ */
3022
+static void xhci_pch ( struct xhci_device *xhci, struct pci_device *pci ) {
3023
+	uint32_t xusb2pr;
3024
+	uint32_t xusb2prm;
3025
+	uint32_t usb3pssen;
3026
+	uint32_t usb3prm;
3027
+
3028
+	/* Enable SuperSpeed capability.  Do this before rerouting
3029
+	 * USB2 ports, so that USB3 devices connect at SuperSpeed.
3030
+	 */
3031
+	pci_read_config_dword ( pci, XHCI_PCH_USB3PSSEN, &usb3pssen );
3032
+	pci_read_config_dword ( pci, XHCI_PCH_USB3PRM, &usb3prm );
3033
+	if ( usb3prm & ~usb3pssen ) {
3034
+		DBGC ( xhci, "XHCI %p enabling SuperSpeed on ports %08x\n",
3035
+		       xhci, ( usb3prm & ~usb3pssen ) );
3036
+	}
3037
+	usb3pssen |= usb3prm;
3038
+	pci_write_config_dword ( pci, XHCI_PCH_USB3PSSEN, usb3pssen );
3039
+
3040
+	/* Route USB2 ports from EHCI to xHCI */
3041
+	pci_read_config_dword ( pci, XHCI_PCH_XUSB2PR, &xusb2pr );
3042
+	pci_read_config_dword ( pci, XHCI_PCH_XUSB2PRM, &xusb2prm );
3043
+	if ( xusb2prm & ~xusb2pr ) {
3044
+		DBGC ( xhci, "XHCI %p routing ports %08x from EHCI to xHCI\n",
3045
+		       xhci, ( xusb2prm & ~xusb2pr ) );
3046
+	}
3047
+	xusb2pr |= xusb2prm;
3048
+	pci_write_config_dword ( pci, XHCI_PCH_XUSB2PR, xusb2pr );
3049
+}
3050
+
3016 3051
 /**
3017 3052
  * Probe PCI device
3018 3053
  *
@@ -3054,6 +3089,10 @@ static int xhci_probe ( struct pci_device *pci ) {
3054 3089
 	if ( ( rc = xhci_legacy_claim ( xhci ) ) != 0 )
3055 3090
 		goto err_legacy_claim;
3056 3091
 
3092
+	/* Fix Intel PCH-specific quirks, if applicable */
3093
+	if ( pci->id->driver_data & XHCI_PCH )
3094
+		xhci_pch ( xhci, pci );
3095
+
3057 3096
 	/* Reset device */
3058 3097
 	if ( ( rc = xhci_reset ( xhci ) ) != 0 )
3059 3098
 		goto err_reset;
@@ -3115,6 +3154,7 @@ static void xhci_remove ( struct pci_device *pci ) {
3115 3154
 
3116 3155
 /** XHCI PCI device IDs */
3117 3156
 static struct pci_device_id xhci_ids[] = {
3157
+	PCI_ROM ( 0x8086, 0xffff, "xhci-pch", "xHCI (Intel PCH)", XHCI_PCH ),
3118 3158
 	PCI_ROM ( 0xffff, 0xffff, "xhci", "xHCI", 0 ),
3119 3159
 };
3120 3160
 

+ 15
- 0
src/drivers/usb/xhci.h Wyświetl plik

@@ -1103,4 +1103,19 @@ struct xhci_endpoint {
1103 1103
 	struct xhci_trb_ring ring;
1104 1104
 };
1105 1105
 
1106
+/** Intel PCH quirk */
1107
+#define XHCI_PCH 0x0001
1108
+
1109
+/** Intel PCH USB2 port routing register */
1110
+#define XHCI_PCH_XUSB2PR 0xd0
1111
+
1112
+/** Intel PCH USB2 port routing mask register */
1113
+#define XHCI_PCH_XUSB2PRM 0xd4
1114
+
1115
+/** Intel PCH USB3 port SuperSpeed enable register */
1116
+#define XHCI_PCH_USB3PSSEN 0xd8
1117
+
1118
+/** Intel PCH USB3 port routing mask register */
1119
+#define XHCI_PCH_USB3PRM 0xdc
1120
+
1106 1121
 #endif /* _IPXE_XHCI_H */

Ładowanie…
Anuluj
Zapisz