2015-06-21 10:18:43 +00:00
|
|
|
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(+)
|
|
|
|
|
|
|
|
--- 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.
|
|
|
|
*/
|
2015-06-30 23:26:09 +00:00
|
|
|
@@ -146,6 +204,10 @@ static int xhci_start(struct xhci_hcd *x
|
2015-06-21 10:18:43 +00:00
|
|
|
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;
|