diff options
Diffstat (limited to 'target/linux/bcm53xx/patches-4.1/820-xhci-add-Broadcom-specific-fake-doorbell.patch')
-rw-r--r-- | target/linux/bcm53xx/patches-4.1/820-xhci-add-Broadcom-specific-fake-doorbell.patch | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/target/linux/bcm53xx/patches-4.1/820-xhci-add-Broadcom-specific-fake-doorbell.patch b/target/linux/bcm53xx/patches-4.1/820-xhci-add-Broadcom-specific-fake-doorbell.patch new file mode 100644 index 0000000000..9a87a75dd4 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/820-xhci-add-Broadcom-specific-fake-doorbell.patch @@ -0,0 +1,94 @@ +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 +@@ -121,6 +121,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. + */ +@@ -145,6 +203,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) + xhci->xhc_state &= ~XHCI_STATE_HALTED; + return ret; |