kernel: bump 6.6 to 6.6.29
[openwrt/staging/pepe2k.git] / target / linux / bcm53xx / patches-6.6 / 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 --- a/drivers/usb/host/xhci-plat.c
21 +++ b/drivers/usb/host/xhci-plat.c
22 @@ -77,8 +77,13 @@ static int xhci_priv_resume_quirk(struct
23 static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci)
24 {
25 struct xhci_plat_priv *priv = xhci_to_priv(xhci);
26 + struct platform_device*pdev = to_platform_device(dev);
27 + struct device_node *node = pdev->dev.of_node;
28
29 xhci->quirks |= priv->quirks;
30 +
31 + if (node && of_machine_is_compatible("brcm,bcm4708"))
32 + xhci->quirks |= XHCI_FAKE_DOORBELL;
33 }
34
35 /* called during probe() after chip reset completes */
36 --- a/drivers/usb/host/xhci.c
37 +++ b/drivers/usb/host/xhci.c
38 @@ -161,6 +161,49 @@ int xhci_start(struct xhci_hcd *xhci)
39 return ret;
40 }
41
42 +/**
43 + * xhci_fake_doorbell - Perform a fake doorbell on a specified slot
44 + *
45 + * Some controllers require a fake doorbell to start correctly. Without that
46 + * they simply don't detect any devices.
47 + */
48 +static int xhci_fake_doorbell(struct xhci_hcd *xhci, int slot_id)
49 +{
50 + u32 temp;
51 +
52 + /* Alloc a virt device for that slot */
53 + if (!xhci_alloc_virt_device(xhci, slot_id, NULL, GFP_NOIO)) {
54 + xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n");
55 + return -ENOMEM;
56 + }
57 +
58 + /* Ring fake doorbell for slot_id ep 0 */
59 + xhci_ring_ep_doorbell(xhci, slot_id, 0, 0);
60 + usleep_range(1000, 1500);
61 +
62 + /* Read the status to check if HSE is set or not */
63 + temp = readl(&xhci->op_regs->status);
64 +
65 + /* Clear HSE if set */
66 + if (temp & STS_FATAL) {
67 + xhci_dbg(xhci, "HSE problem detected, status: 0x%08x\n", temp);
68 + temp &= ~0x1fff;
69 + temp |= STS_FATAL;
70 + writel(temp, &xhci->op_regs->status);
71 + usleep_range(1000, 1500);
72 + readl(&xhci->op_regs->status);
73 + }
74 +
75 + /* Free virt device */
76 + xhci_free_virt_device(xhci, slot_id);
77 +
78 + /* We're done if controller is already running */
79 + if (readl(&xhci->op_regs->command) & CMD_RUN)
80 + return 0;
81 +
82 + return xhci_start(xhci);
83 +}
84 +
85 /*
86 * Reset a halted HC.
87 *
88 @@ -480,6 +523,15 @@ static int xhci_run_finished(struct xhci
89 return -ENODEV;
90 }
91
92 + if (xhci->quirks & XHCI_FAKE_DOORBELL) {
93 + int err = xhci_fake_doorbell(xhci, 1);
94 + if (err) {
95 + xhci_halt(xhci);
96 + spin_unlock_irqrestore(&xhci->lock, flags);
97 + return err;
98 + }
99 + }
100 +
101 xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
102
103 if (xhci->quirks & XHCI_NEC_HOST)
104 --- a/drivers/usb/host/xhci.h
105 +++ b/drivers/usb/host/xhci.h
106 @@ -1912,6 +1912,7 @@ struct xhci_hcd {
107 #define XHCI_RESET_TO_DEFAULT BIT_ULL(44)
108 #define XHCI_ZHAOXIN_TRB_FETCH BIT_ULL(45)
109 #define XHCI_ZHAOXIN_HOST BIT_ULL(46)
110 +#define XHCI_FAKE_DOORBELL BIT_ULL(47)
111
112 unsigned int num_active_eps;
113 unsigned int limit_active_eps;