|
@@ -1521,6 +1521,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)
|
|
|
{
|
|
@@ -1654,8 +1683,12 @@ 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, 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 */
|