aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm53xx/patches-5.4/180-usb-xhci-add-support-for-performing-fake-doorbell.patch
diff options
context:
space:
mode:
authorJohn Crispin <john@phrozen.org>2020-02-10 07:46:56 +0100
committerKoen Vandeputte <koen.vandeputte@ncentric.com>2020-02-28 17:50:46 +0100
commit50c6938b95a0c915c5c8ffe1fe67a94b9402e98e (patch)
tree3e2ee026d1a8b32f9fa89e7b96aae9bf03a5bf20 /target/linux/bcm53xx/patches-5.4/180-usb-xhci-add-support-for-performing-fake-doorbell.patch
parent6d5291ff7244a8d5c914542ff2b3809609fdb1c0 (diff)
downloadupstream-50c6938b95a0c915c5c8ffe1fe67a94b9402e98e.tar.gz
upstream-50c6938b95a0c915c5c8ffe1fe67a94b9402e98e.tar.bz2
upstream-50c6938b95a0c915c5c8ffe1fe67a94b9402e98e.zip
bcm53xx: add v5.4 support
Signed-off-by: John Crispin <john@phrozen.org>
Diffstat (limited to 'target/linux/bcm53xx/patches-5.4/180-usb-xhci-add-support-for-performing-fake-doorbell.patch')
-rw-r--r--target/linux/bcm53xx/patches-5.4/180-usb-xhci-add-support-for-performing-fake-doorbell.patch143
1 files changed, 143 insertions, 0 deletions
diff --git a/target/linux/bcm53xx/patches-5.4/180-usb-xhci-add-support-for-performing-fake-doorbell.patch b/target/linux/bcm53xx/patches-5.4/180-usb-xhci-add-support-for-performing-fake-doorbell.patch
new file mode 100644
index 0000000000..be7a52a936
--- /dev/null
+++ b/target/linux/bcm53xx/patches-5.4/180-usb-xhci-add-support-for-performing-fake-doorbell.patch
@@ -0,0 +1,143 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Sat, 1 Oct 2016 22:54:48 +0200
+Subject: [PATCH] usb: xhci: add support for performing fake doorbell
+
+Broadcom's Northstar XHCI controllers seem to need a special start
+procedure to work correctly. There isn't any official documentation of
+this, the problem is that controller doesn't detect any connected
+devices with default setup. Moreover connecting USB device to controller
+that doesn't run properly can cause SoC's watchdog issues.
+
+A workaround that was successfully tested on multiple devices is to
+perform a fake doorbell. This patch adds code for doing this and enables
+it on BCM4708 family.
+---
+ drivers/usb/host/xhci-plat.c | 6 +++++
+ drivers/usb/host/xhci.c | 63 +++++++++++++++++++++++++++++++++++++++++---
+ drivers/usb/host/xhci.h | 1 +
+ 3 files changed, 67 insertions(+), 3 deletions(-)
+
+Index: linux-5.4.11/drivers/usb/host/xhci-plat.c
+===================================================================
+--- linux-5.4.11.orig/drivers/usb/host/xhci-plat.c
++++ linux-5.4.11/drivers/usb/host/xhci-plat.c
+@@ -67,6 +67,8 @@ static int xhci_priv_resume_quirk(struct
+ static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
+ {
+ struct xhci_plat_priv *priv = xhci_to_priv(xhci);
++ struct platform_device*pdev = to_platform_device(dev);
++ struct device_node *node = pdev->dev.of_node;
+
+ /*
+ * As of now platform drivers don't provide MSI support so we ensure
+@@ -74,6 +76,9 @@ static void xhci_plat_quirks(struct devi
+ * dev struct in order to setup MSI
+ */
+ xhci->quirks |= XHCI_PLAT | priv->quirks;
++
++ if (node && of_machine_is_compatible("brcm,bcm4708"))
++ xhci->quirks |= XHCI_FAKE_DOORBELL;
+ }
+
+ /* called during probe() after chip reset completes */
+Index: linux-5.4.11/drivers/usb/host/xhci.c
+===================================================================
+--- linux-5.4.11.orig/drivers/usb/host/xhci.c
++++ linux-5.4.11/drivers/usb/host/xhci.c
+@@ -156,6 +156,49 @@ int xhci_start(struct xhci_hcd *xhci)
+ return ret;
+ }
+
++/**
++ * xhci_fake_doorbell - Perform a fake doorbell on a specified slot
++ *
++ * Some controllers require a fake doorbell to start correctly. Without that
++ * they simply don't detect any devices.
++ */
++static int xhci_fake_doorbell(struct xhci_hcd *xhci, int slot_id)
++{
++ u32 temp;
++
++ /* Alloc a virt device for that slot */
++ if (!xhci_alloc_virt_device(xhci, slot_id, NULL, GFP_NOIO)) {
++ xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n");
++ return -ENOMEM;
++ }
++
++ /* Ring fake doorbell for slot_id ep 0 */
++ xhci_ring_ep_doorbell(xhci, slot_id, 0, 0);
++ usleep_range(1000, 1500);
++
++ /* Read the status to check if HSE is set or not */
++ temp = readl(&xhci->op_regs->status);
++
++ /* Clear HSE if set */
++ if (temp & STS_FATAL) {
++ xhci_dbg(xhci, "HSE problem detected, status: 0x%08x\n", temp);
++ temp &= ~0x1fff;
++ temp |= STS_FATAL;
++ writel(temp, &xhci->op_regs->status);
++ usleep_range(1000, 1500);
++ readl(&xhci->op_regs->status);
++ }
++
++ /* Free virt device */
++ xhci_free_virt_device(xhci, slot_id);
++
++ /* We're done if controller is already running */
++ if (readl(&xhci->op_regs->command) & CMD_RUN)
++ return 0;
++
++ return xhci_start(xhci);
++}
++
+ /*
+ * Reset a halted HC.
+ *
+@@ -604,10 +647,20 @@ static int xhci_init(struct usb_hcd *hcd
+
+ static int xhci_run_finished(struct xhci_hcd *xhci)
+ {
+- if (xhci_start(xhci)) {
+- xhci_halt(xhci);
+- return -ENODEV;
++ int err;
++
++ err = xhci_start(xhci);
++ if (err) {
++ err = -ENODEV;
++ goto err_halt;
+ }
++
++ if (xhci->quirks & XHCI_FAKE_DOORBELL) {
++ err = xhci_fake_doorbell(xhci, 1);
++ if (err)
++ goto err_halt;
++ }
++
+ xhci->shared_hcd->state = HC_STATE_RUNNING;
+ xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
+
+@@ -617,6 +670,10 @@ static int xhci_run_finished(struct xhci
+ xhci_dbg_trace(xhci, trace_xhci_dbg_init,
+ "Finished xhci_run for USB3 roothub");
+ return 0;
++
++err_halt:
++ xhci_halt(xhci);
++ return err;
+ }
+
+ /*
+Index: linux-5.4.11/drivers/usb/host/xhci.h
+===================================================================
+--- linux-5.4.11.orig/drivers/usb/host/xhci.h
++++ linux-5.4.11/drivers/usb/host/xhci.h
+@@ -1867,6 +1867,7 @@ struct xhci_hcd {
+ #define XHCI_DEFAULT_PM_RUNTIME_ALLOW BIT_ULL(33)
+ #define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34)
+ #define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35)
++#define XHCI_FAKE_DOORBELL BIT_ULL(36)
+
+ unsigned int num_active_eps;
+ unsigned int limit_active_eps;