bcm53xx: add v5.4 support
[openwrt/staging/dedeckeh.git] / target / linux / bcm53xx / patches-5.4 / 180-usb-xhci-add-support-for-performing-fake-doorbell.patch
1 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
2 Date: Sat, 1 Oct 2016 22:54:48 +0200
3 Subject: [PATCH] usb: xhci: add support for performing fake doorbell
4
5 Broadcom's Northstar XHCI controllers seem to need a special start
6 procedure to work correctly. There isn't any official documentation of
7 this, the problem is that controller doesn't detect any connected
8 devices with default setup. Moreover connecting USB device to controller
9 that doesn't run properly can cause SoC's watchdog issues.
10
11 A workaround that was successfully tested on multiple devices is to
12 perform a fake doorbell. This patch adds code for doing this and enables
13 it on BCM4708 family.
14 ---
15 drivers/usb/host/xhci-plat.c | 6 +++++
16 drivers/usb/host/xhci.c | 63 +++++++++++++++++++++++++++++++++++++++++---
17 drivers/usb/host/xhci.h | 1 +
18 3 files changed, 67 insertions(+), 3 deletions(-)
19
20 Index: linux-5.4.11/drivers/usb/host/xhci-plat.c
21 ===================================================================
22 --- linux-5.4.11.orig/drivers/usb/host/xhci-plat.c
23 +++ linux-5.4.11/drivers/usb/host/xhci-plat.c
24 @@ -67,6 +67,8 @@ static int xhci_priv_resume_quirk(struct
25 static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
26 {
27 struct xhci_plat_priv *priv = xhci_to_priv(xhci);
28 + struct platform_device*pdev = to_platform_device(dev);
29 + struct device_node *node = pdev->dev.of_node;
30
31 /*
32 * As of now platform drivers don't provide MSI support so we ensure
33 @@ -74,6 +76,9 @@ static void xhci_plat_quirks(struct devi
34 * dev struct in order to setup MSI
35 */
36 xhci->quirks |= XHCI_PLAT | priv->quirks;
37 +
38 + if (node && of_machine_is_compatible("brcm,bcm4708"))
39 + xhci->quirks |= XHCI_FAKE_DOORBELL;
40 }
41
42 /* called during probe() after chip reset completes */
43 Index: linux-5.4.11/drivers/usb/host/xhci.c
44 ===================================================================
45 --- linux-5.4.11.orig/drivers/usb/host/xhci.c
46 +++ linux-5.4.11/drivers/usb/host/xhci.c
47 @@ -156,6 +156,49 @@ int xhci_start(struct xhci_hcd *xhci)
48 return ret;
49 }
50
51 +/**
52 + * xhci_fake_doorbell - Perform a fake doorbell on a specified slot
53 + *
54 + * Some controllers require a fake doorbell to start correctly. Without that
55 + * they simply don't detect any devices.
56 + */
57 +static int xhci_fake_doorbell(struct xhci_hcd *xhci, int slot_id)
58 +{
59 + u32 temp;
60 +
61 + /* Alloc a virt device for that slot */
62 + if (!xhci_alloc_virt_device(xhci, slot_id, NULL, GFP_NOIO)) {
63 + xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n");
64 + return -ENOMEM;
65 + }
66 +
67 + /* Ring fake doorbell for slot_id ep 0 */
68 + xhci_ring_ep_doorbell(xhci, slot_id, 0, 0);
69 + usleep_range(1000, 1500);
70 +
71 + /* Read the status to check if HSE is set or not */
72 + temp = readl(&xhci->op_regs->status);
73 +
74 + /* Clear HSE if set */
75 + if (temp & STS_FATAL) {
76 + xhci_dbg(xhci, "HSE problem detected, status: 0x%08x\n", temp);
77 + temp &= ~0x1fff;
78 + temp |= STS_FATAL;
79 + writel(temp, &xhci->op_regs->status);
80 + usleep_range(1000, 1500);
81 + readl(&xhci->op_regs->status);
82 + }
83 +
84 + /* Free virt device */
85 + xhci_free_virt_device(xhci, slot_id);
86 +
87 + /* We're done if controller is already running */
88 + if (readl(&xhci->op_regs->command) & CMD_RUN)
89 + return 0;
90 +
91 + return xhci_start(xhci);
92 +}
93 +
94 /*
95 * Reset a halted HC.
96 *
97 @@ -604,10 +647,20 @@ static int xhci_init(struct usb_hcd *hcd
98
99 static int xhci_run_finished(struct xhci_hcd *xhci)
100 {
101 - if (xhci_start(xhci)) {
102 - xhci_halt(xhci);
103 - return -ENODEV;
104 + int err;
105 +
106 + err = xhci_start(xhci);
107 + if (err) {
108 + err = -ENODEV;
109 + goto err_halt;
110 }
111 +
112 + if (xhci->quirks & XHCI_FAKE_DOORBELL) {
113 + err = xhci_fake_doorbell(xhci, 1);
114 + if (err)
115 + goto err_halt;
116 + }
117 +
118 xhci->shared_hcd->state = HC_STATE_RUNNING;
119 xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
120
121 @@ -617,6 +670,10 @@ static int xhci_run_finished(struct xhci
122 xhci_dbg_trace(xhci, trace_xhci_dbg_init,
123 "Finished xhci_run for USB3 roothub");
124 return 0;
125 +
126 +err_halt:
127 + xhci_halt(xhci);
128 + return err;
129 }
130
131 /*
132 Index: linux-5.4.11/drivers/usb/host/xhci.h
133 ===================================================================
134 --- linux-5.4.11.orig/drivers/usb/host/xhci.h
135 +++ linux-5.4.11/drivers/usb/host/xhci.h
136 @@ -1867,6 +1867,7 @@ struct xhci_hcd {
137 #define XHCI_DEFAULT_PM_RUNTIME_ALLOW BIT_ULL(33)
138 #define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34)
139 #define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35)
140 +#define XHCI_FAKE_DOORBELL BIT_ULL(36)
141
142 unsigned int num_active_eps;
143 unsigned int limit_active_eps;