12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- 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.
- */
- @@ -146,6 +204,10 @@ static int xhci_start(struct xhci_hcd *x
- 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)
- /* clear state flags. Including dying, halted or removing */
- xhci->xhc_state = 0;
|