aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm53xx/patches-3.18/820-xhci-add-Broadcom-specific-fake-doorbell.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm53xx/patches-3.18/820-xhci-add-Broadcom-specific-fake-doorbell.patch')
-rw-r--r--target/linux/bcm53xx/patches-3.18/820-xhci-add-Broadcom-specific-fake-doorbell.patch99
1 files changed, 99 insertions, 0 deletions
diff --git a/target/linux/bcm53xx/patches-3.18/820-xhci-add-Broadcom-specific-fake-doorbell.patch b/target/linux/bcm53xx/patches-3.18/820-xhci-add-Broadcom-specific-fake-doorbell.patch
new file mode 100644
index 0000000000..87d23c3a51
--- /dev/null
+++ b/target/linux/bcm53xx/patches-3.18/820-xhci-add-Broadcom-specific-fake-doorbell.patch
@@ -0,0 +1,99 @@
+From 9cc14ca0aae53c16d10ffea49848ac61a5015562 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Sun, 21 Jun 2015 11:10:49 +0200
+Subject: [PATCH] xhci: add Broadcom specific fake doorbell
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This fixes problem with controller seeing devices only in some small
+percentage of cold boots.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+ drivers/usb/host/xhci.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 62 insertions(+)
+
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index 3bceabe..0737ab2 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -122,6 +122,64 @@ int xhci_halt(struct xhci_hcd *xhci)
+ return ret;
+ }
+
++#ifdef CONFIG_ARCH_BCM_5301X
++int xhci_fake_doorbell(struct xhci_hcd *xhci, int slot_id)
++{
++ unsigned int temp1, ret;
++
++ /* alloc a virt device for slot */
++ if (!xhci_alloc_virt_device(xhci, slot_id, 0, GFP_NOIO)) {
++ xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n");
++ return 1;
++ }
++
++ /* ring fake doorbell for slot_id ep 0 */
++ xhci_ring_ep_doorbell(xhci, slot_id, 0, 0);
++ mdelay(1);
++
++ /* read the status register to check if HSE is set or not? */
++ temp1 = readl(&xhci->op_regs->status);
++ xhci_dbg(xhci, "op reg status = %x\n",temp1);
++
++ /* clear HSE if set */
++ if(temp1 & STS_FATAL) {
++ xhci_dbg(xhci, "HSE problem detected\n");
++ temp1 &= ~(0x1fff);
++ temp1 |= STS_FATAL;
++ xhci_dbg(xhci, "temp1=%x\n",temp1);
++ writel(temp1, &xhci->op_regs->status);
++ mdelay(1);
++ temp1 = readl(&xhci->op_regs->status);
++ xhci_dbg(xhci, "After clear op reg status=%x\n", temp1);
++ }
++
++ /* Free virt device */
++ xhci_free_virt_device(xhci, slot_id);
++
++ /* Run the controller if needed */
++ temp1 = readl(&xhci->op_regs->command);
++ if (temp1 & CMD_RUN)
++ return 0;
++ temp1 |= (CMD_RUN);
++
++ writel(temp1, &xhci->op_regs->command);
++ /*
++ * Wait for the HCHalted Status bit to be 0 to indicate the host is running.
++ */
++ ret = xhci_handshake(xhci, &xhci->op_regs->status,
++ STS_HALT, 0, XHCI_MAX_HALT_USEC);
++
++ if (ret == -ETIMEDOUT) {
++ xhci_err(xhci, "Host took too long to start, "
++ "waited %u microseconds.\n",
++ XHCI_MAX_HALT_USEC);
++ return 1;
++ }
++
++ return 0;
++}
++#endif /* CONFIG_ARCH_BCM_5301X */
++
+ /*
+ * Set the run bit and wait for the host to be running.
+ */
+@@ -146,6 +204,10 @@ static int xhci_start(struct xhci_hcd *xhci)
+ xhci_err(xhci, "Host took too long to start, "
+ "waited %u microseconds.\n",
+ XHCI_MAX_HALT_USEC);
++#ifdef CONFIG_ARCH_BCM_5301X
++ xhci_fake_doorbell(xhci, 1);
++#endif /* CONFIG_ARCH_BCM_5301X */
++
+ if (!ret)
+ xhci->xhc_state &= ~XHCI_STATE_HALTED;
+ return ret;
+--
+1.8.4.5
+