820-xhci-add-Broadcom-specific-fake-doorbell.patch 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. From 9cc14ca0aae53c16d10ffea49848ac61a5015562 Mon Sep 17 00:00:00 2001
  2. From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
  3. Date: Sun, 21 Jun 2015 11:10:49 +0200
  4. Subject: [PATCH] xhci: add Broadcom specific fake doorbell
  5. MIME-Version: 1.0
  6. Content-Type: text/plain; charset=UTF-8
  7. Content-Transfer-Encoding: 8bit
  8. This fixes problem with controller seeing devices only in some small
  9. percentage of cold boots.
  10. Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
  11. ---
  12. drivers/usb/host/xhci.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++
  13. 1 file changed, 62 insertions(+)
  14. --- a/drivers/usb/host/xhci.c
  15. +++ b/drivers/usb/host/xhci.c
  16. @@ -122,6 +122,64 @@ int xhci_halt(struct xhci_hcd *xhci)
  17. return ret;
  18. }
  19. +#ifdef CONFIG_ARCH_BCM_5301X
  20. +int xhci_fake_doorbell(struct xhci_hcd *xhci, int slot_id)
  21. +{
  22. + unsigned int temp1, ret;
  23. +
  24. + /* alloc a virt device for slot */
  25. + if (!xhci_alloc_virt_device(xhci, slot_id, 0, GFP_NOIO)) {
  26. + xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n");
  27. + return 1;
  28. + }
  29. +
  30. + /* ring fake doorbell for slot_id ep 0 */
  31. + xhci_ring_ep_doorbell(xhci, slot_id, 0, 0);
  32. + mdelay(1);
  33. +
  34. + /* read the status register to check if HSE is set or not? */
  35. + temp1 = readl(&xhci->op_regs->status);
  36. + xhci_dbg(xhci, "op reg status = %x\n",temp1);
  37. +
  38. + /* clear HSE if set */
  39. + if(temp1 & STS_FATAL) {
  40. + xhci_dbg(xhci, "HSE problem detected\n");
  41. + temp1 &= ~(0x1fff);
  42. + temp1 |= STS_FATAL;
  43. + xhci_dbg(xhci, "temp1=%x\n",temp1);
  44. + writel(temp1, &xhci->op_regs->status);
  45. + mdelay(1);
  46. + temp1 = readl(&xhci->op_regs->status);
  47. + xhci_dbg(xhci, "After clear op reg status=%x\n", temp1);
  48. + }
  49. +
  50. + /* Free virt device */
  51. + xhci_free_virt_device(xhci, slot_id);
  52. +
  53. + /* Run the controller if needed */
  54. + temp1 = readl(&xhci->op_regs->command);
  55. + if (temp1 & CMD_RUN)
  56. + return 0;
  57. + temp1 |= (CMD_RUN);
  58. +
  59. + writel(temp1, &xhci->op_regs->command);
  60. + /*
  61. + * Wait for the HCHalted Status bit to be 0 to indicate the host is running.
  62. + */
  63. + ret = xhci_handshake(xhci, &xhci->op_regs->status,
  64. + STS_HALT, 0, XHCI_MAX_HALT_USEC);
  65. +
  66. + if (ret == -ETIMEDOUT) {
  67. + xhci_err(xhci, "Host took too long to start, "
  68. + "waited %u microseconds.\n",
  69. + XHCI_MAX_HALT_USEC);
  70. + return 1;
  71. + }
  72. +
  73. + return 0;
  74. +}
  75. +#endif /* CONFIG_ARCH_BCM_5301X */
  76. +
  77. /*
  78. * Set the run bit and wait for the host to be running.
  79. */
  80. @@ -146,6 +204,10 @@ static int xhci_start(struct xhci_hcd *x
  81. xhci_err(xhci, "Host took too long to start, "
  82. "waited %u microseconds.\n",
  83. XHCI_MAX_HALT_USEC);
  84. +#ifdef CONFIG_ARCH_BCM_5301X
  85. + xhci_fake_doorbell(xhci, 1);
  86. +#endif /* CONFIG_ARCH_BCM_5301X */
  87. +
  88. if (!ret)
  89. /* clear state flags. Including dying, halted or removing */
  90. xhci->xhc_state = 0;