]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
xhci: Add quirk to workaround the errata seen on Cavium Thunder-X2 Soc
authorCherian, George <George.Cherian@cavium.com>
Fri, 7 Dec 2018 09:21:59 +0000 (17:21 +0800)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Mon, 14 Jan 2019 09:28:55 +0000 (09:28 +0000)
BugLink: http://bugs.launchpad.net/bugs/1806534
Implement workaround for ThunderX2 Errata-129 (documented in
CN99XX Known Issues" available at Cavium support site).
As per ThunderX2errata-129, USB 2 device may come up as USB 1
if a connection to a USB 1 device is followed by another connection to
a USB 2 device, the link will come up as USB 1 for the USB 2 device.

Resolution: Reset the PHY after the USB 1 device is disconnected.
The PHY reset sequence is done using private registers in XHCI register
space. After the PHY is reset we check for the PLL lock status and retry
the operation if it fails. From our tests, retrying 4 times is sufficient.

Add a new quirk flag XHCI_RESET_PLL_ON_DISCONNECT to invoke the workaround
in handle_xhci_port_status().

Cc: stable@vger.kernel.org
Signed-off-by: George Cherian <george.cherian@cavium.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
(backported from commit 11644a7659529730eaf2f166efaabe7c3dc7af8c)
Signed-off-by: Ike Panhc <ike.pan@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
Acked-by: Kleber Souza <kleber.souza@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.h

index c62fa1424601582846b73dca583f9895a8f485de..c25e3e55d8e0d10775108da6af6d24f66abd82ba 100644 (file)
@@ -226,6 +226,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
        if (pdev->vendor == PCI_VENDOR_ID_TI && pdev->device == 0x8241)
                xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_7;
 
+       if ((pdev->vendor == PCI_VENDOR_ID_BROADCOM ||
+            pdev->vendor == PCI_VENDOR_ID_CAVIUM) &&
+            pdev->device == 0x9026)
+               xhci->quirks |= XHCI_RESET_PLL_ON_DISCONNECT;
+
        if (xhci->quirks & XHCI_RESET_ON_RESUME)
                xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
                                "QUIRK: Resetting on resume");
index 773e0bdf42350810e3a1a04800ee87b3f1290ffb..b569626f8e1b4709cb3bfb8fb8524a885eb97f74 100644 (file)
@@ -1554,6 +1554,35 @@ static void handle_device_notification(struct xhci_hcd *xhci,
                usb_wakeup_notification(udev->parent, udev->portnum);
 }
 
+/*
+ * Quirk hanlder for errata seen on Cavium ThunderX2 processor XHCI
+ * Controller.
+ * As per ThunderX2errata-129 USB 2 device may come up as USB 1
+ * If a connection to a USB 1 device is followed by another connection
+ * to a USB 2 device.
+ *
+ * Reset the PHY after the USB device is disconnected if device speed
+ * is less than HCD_USB3.
+ * Retry the reset sequence max of 4 times checking the PLL lock status.
+ *
+ */
+static void xhci_cavium_reset_phy_quirk(struct xhci_hcd *xhci)
+{
+       struct usb_hcd *hcd = xhci_to_hcd(xhci);
+       u32 pll_lock_check;
+       u32 retry_count = 4;
+
+       do {
+               /* Assert PHY reset */
+               writel(0x6F, hcd->regs + 0x1048);
+               udelay(10);
+               /* De-assert the PHY reset */
+               writel(0x7F, hcd->regs + 0x1048);
+               udelay(200);
+               pll_lock_check = readl(hcd->regs + 0x1070);
+       } while (!(pll_lock_check & 0x1) && --retry_count);
+}
+
 static void handle_port_status(struct xhci_hcd *xhci,
                union xhci_trb *event)
 {
@@ -1716,9 +1745,13 @@ static void handle_port_status(struct xhci_hcd *xhci,
                goto cleanup;
        }
 
-       if (hcd->speed < HCD_USB3)
+       if (hcd->speed < HCD_USB3) {
                xhci_test_and_clear_bit(xhci, port_array, faked_port_index,
                                        PORT_PLC);
+               if ((xhci->quirks & XHCI_RESET_PLL_ON_DISCONNECT) &&
+                   (portsc & PORT_CSC) && !(portsc & PORT_CONNECT))
+                       xhci_cavium_reset_phy_quirk(xhci);
+       }
 
 cleanup:
        /* Update event ring dequeue pointer before dropping the lock */
index fbc0de0f04c718161cb8cc903901bb6f45fcaf5d..b2027fad64a6a0a26fe23cc9d003c0964c9cef36 100644 (file)
@@ -1825,6 +1825,7 @@ struct xhci_hcd {
 #define XHCI_ASMEDIA_MODIFY_FLOWCONTROL        BIT_ULL(28)
 #define XHCI_HW_LPM_DISABLE    BIT_ULL(29)
 #define XHCI_SUSPEND_DELAY     BIT_ULL(30)
+#define XHCI_RESET_PLL_ON_DISCONNECT   BIT_ULL(34)
 #define XHCI_SNPS_BROKEN_SUSPEND    BIT_ULL(35)
 
        unsigned int            num_active_eps;