|
@@ -69,6 +69,9 @@
|
|
|
#define NB_PIF0_PWRDOWN_0 0x01100012
|
|
|
#define NB_PIF0_PWRDOWN_1 0x01100013
|
|
|
|
|
|
+#define USB_INTEL_XUSB2PR 0xD0
|
|
|
+#define USB_INTEL_USB3_PSSEN 0xD8
|
|
|
+
|
|
|
static struct amd_chipset_info {
|
|
|
struct pci_dev *nb_dev;
|
|
|
struct pci_dev *smbus_dev;
|
|
@@ -673,6 +676,64 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done,
|
|
|
return -ETIMEDOUT;
|
|
|
}
|
|
|
|
|
|
+bool usb_is_intel_switchable_xhci(struct pci_dev *pdev)
|
|
|
+{
|
|
|
+ return pdev->class == PCI_CLASS_SERIAL_USB_XHCI &&
|
|
|
+ pdev->vendor == PCI_VENDOR_ID_INTEL &&
|
|
|
+ pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(usb_is_intel_switchable_xhci);
|
|
|
+
|
|
|
+/*
|
|
|
+ * Intel's Panther Point chipset has two host controllers (EHCI and xHCI) that
|
|
|
+ * share some number of ports. These ports can be switched between either
|
|
|
+ * controller. Not all of the ports under the EHCI host controller may be
|
|
|
+ * switchable.
|
|
|
+ *
|
|
|
+ * The ports should be switched over to xHCI before PCI probes for any device
|
|
|
+ * start. This avoids active devices under EHCI being disconnected during the
|
|
|
+ * port switchover, which could cause loss of data on USB storage devices, or
|
|
|
+ * failed boot when the root file system is on a USB mass storage device and is
|
|
|
+ * enumerated under EHCI first.
|
|
|
+ *
|
|
|
+ * We write into the xHC's PCI configuration space in some Intel-specific
|
|
|
+ * registers to switch the ports over. The USB 3.0 terminations and the USB
|
|
|
+ * 2.0 data wires are switched separately. We want to enable the SuperSpeed
|
|
|
+ * terminations before switching the USB 2.0 wires over, so that USB 3.0
|
|
|
+ * devices connect at SuperSpeed, rather than at USB 2.0 speeds.
|
|
|
+ */
|
|
|
+void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)
|
|
|
+{
|
|
|
+ u32 ports_available;
|
|
|
+
|
|
|
+ ports_available = 0xffffffff;
|
|
|
+ /* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable
|
|
|
+ * Register, to turn on SuperSpeed terminations for all
|
|
|
+ * available ports.
|
|
|
+ */
|
|
|
+ pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN,
|
|
|
+ cpu_to_le32(ports_available));
|
|
|
+
|
|
|
+ pci_read_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN,
|
|
|
+ &ports_available);
|
|
|
+ dev_dbg(&xhci_pdev->dev, "USB 3.0 ports that are now enabled "
|
|
|
+ "under xHCI: 0x%x\n", ports_available);
|
|
|
+
|
|
|
+ ports_available = 0xffffffff;
|
|
|
+ /* Write XUSB2PR, the xHC USB 2.0 Port Routing Register, to
|
|
|
+ * switch the USB 2.0 power and data lines over to the xHCI
|
|
|
+ * host.
|
|
|
+ */
|
|
|
+ pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,
|
|
|
+ cpu_to_le32(ports_available));
|
|
|
+
|
|
|
+ pci_read_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,
|
|
|
+ &ports_available);
|
|
|
+ dev_dbg(&xhci_pdev->dev, "USB 2.0 ports that are now switched over "
|
|
|
+ "to xHCI: 0x%x\n", ports_available);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(usb_enable_xhci_ports);
|
|
|
+
|
|
|
/**
|
|
|
* PCI Quirks for xHCI.
|
|
|
*
|
|
@@ -732,6 +793,8 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
|
|
|
writel(XHCI_LEGACY_DISABLE_SMI,
|
|
|
base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
|
|
|
|
|
|
+ if (usb_is_intel_switchable_xhci(pdev))
|
|
|
+ usb_enable_xhci_ports(pdev);
|
|
|
hc_init:
|
|
|
op_reg_base = base + XHCI_HC_LENGTH(readl(base));
|
|
|
|